Skip to content

Commit 1f0b9dd

Browse files
committed
fix: model PostgreSQL DROP INDEX concurrency separately from its name
Signed-off-by: minleejae <mmj9808@gmail.com>
1 parent dac8159 commit 1f0b9dd

3 files changed

Lines changed: 80 additions & 1 deletion

File tree

‎src/main/java/net/sf/jsqlparser/statement/drop/Drop.java‎

Lines changed: 21 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -38,6 +38,22 @@ public enum ObjectType {
3838
private Map<String, List<String>> typeToParameters = new HashMap<>();
3939
private boolean ifExists = false;
4040
private boolean materialized = false;
41+
private boolean concurrently;
42+
43+
/** PostgreSQL DROP INDEX CONCURRENTLY, preceding IF EXISTS and the index name. */
44+
public boolean isConcurrently() {
45+
return concurrently;
46+
}
47+
48+
public void setConcurrently(boolean concurrently) {
49+
this.concurrently = concurrently;
50+
}
51+
52+
public Drop withConcurrently(boolean concurrently) {
53+
setConcurrently(concurrently);
54+
return this;
55+
}
56+
4157

4258
private boolean isUsingTemporary;
4359

@@ -201,7 +217,11 @@ public StringBuilder appendTo(StringBuilder builder, Consumer<Table> tablePrinte
201217
if (materialized) {
202218
builder.append("MATERIALIZED ");
203219
}
204-
builder.append(type).append(ifExists ? " IF EXISTS " : " ");
220+
builder.append(type);
221+
if (concurrently) {
222+
builder.append(" CONCURRENTLY");
223+
}
224+
builder.append(ifExists ? " IF EXISTS " : " ");
205225
appendNames(builder, tablePrinter);
206226
if ("FUNCTION".equals(type)) {
207227
builder.append(formatFuncParams(getParamsByType("FUNCTION")));

‎src/main/jjtree/net/sf/jsqlparser/parser/JSqlParserCC.jjt‎

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -16334,6 +16334,9 @@ Drop Drop():
1633416334
tk=<K_FUNCTION>
1633516335
)
1633616336
{ drop.setType(tk.image); }
16337+
[ LOOKAHEAD({ drop.getObjectType() == Drop.ObjectType.INDEX
16338+
&& getToken(1).kind == K_CONCURRENTLY })
16339+
<K_CONCURRENTLY> { drop.setConcurrently(true); } ]
1633716340

1633816341
[ LOOKAHEAD(2) <K_IF> <K_EXISTS> {drop.setIfExists(true);} ]
1633916342

Lines changed: 56 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,56 @@
1+
/*-
2+
* #%L
3+
* JSQLParser library
4+
* %%
5+
* Copyright (C) 2004 - 2026 JSQLParser
6+
* %%
7+
* Dual licensed under GNU LGPL 2.1 or Apache License 2.0
8+
* #L%
9+
*/
10+
package net.sf.jsqlparser.statement.drop;
11+
12+
import static org.junit.jupiter.api.Assertions.*;
13+
import net.sf.jsqlparser.JSQLParserException;
14+
import net.sf.jsqlparser.parser.AbstractJSqlParser.Dialect;
15+
import net.sf.jsqlparser.parser.CCJSqlParserUtil;
16+
import net.sf.jsqlparser.schema.Table;
17+
import net.sf.jsqlparser.util.deparser.StatementDeParser;
18+
import org.junit.jupiter.api.Test;
19+
import org.junit.jupiter.params.ParameterizedTest;
20+
import org.junit.jupiter.params.provider.ValueSource;
21+
22+
class PostgreSqlDropIndexTest {
23+
@ParameterizedTest
24+
@ValueSource(strings = {"DROP INDEX CONCURRENTLY ix",
25+
"DROP INDEX CONCURRENTLY IF EXISTS ix",
26+
"DROP INDEX CONCURRENTLY IF EXISTS public.ix RESTRICT"})
27+
void concurrencyIsIndependentOfTarget(String sql) throws JSQLParserException {
28+
Drop drop = (Drop) CCJSqlParserUtil.parse(sql, p -> p.withDialect(Dialect.POSTGRESQL));
29+
assertTrue(drop.isConcurrently());
30+
assertEquals(sql.contains("IF EXISTS"), drop.isIfExists());
31+
assertEquals("ix", drop.getName().getName());
32+
assertEquals(sql, drop.toString());
33+
drop.setName(new Table("new_ix"));
34+
String expected = sql.replace("public.ix", "ix").replace("ix", "new_ix");
35+
assertEquals(expected, drop.toString());
36+
StringBuilder buffer = new StringBuilder();
37+
drop.accept(new StatementDeParser(buffer), null);
38+
assertEquals(expected, buffer.toString());
39+
Drop reparsed = (Drop) CCJSqlParserUtil.parse(expected);
40+
assertEquals("new_ix", reparsed.getName().getName());
41+
assertTrue(reparsed.isConcurrently());
42+
assertEquals(2, CCJSqlParserUtil.parseStatements(expected + "; SELECT 1").size());
43+
drop.setConcurrently(false);
44+
assertEquals(expected.replace("CONCURRENTLY ", ""), drop.toString());
45+
}
46+
47+
@Test
48+
void ordinaryAndQuotedConcurrentNamesArePreserved() throws JSQLParserException {
49+
for (String sql : new String[] {"DROP TABLE concurrently", "DROP INDEX \"concurrently\"",
50+
"DROP INDEX ix1, ix2 CASCADE", "DROP INDEX ix ON t ALGORITHM = INPLACE"}) {
51+
Drop drop = (Drop) CCJSqlParserUtil.parse(sql);
52+
assertFalse(drop.isConcurrently());
53+
assertEquals(sql, drop.toString());
54+
}
55+
}
56+
}

0 commit comments

Comments
 (0)