Skip to content

Commit 5c59b7b

Browse files
authored
Model MySQL DROP object lists (#2545)
* feat(parser): model MySQL DROP object lists * test: keep DROP assertions Java 11 compatible
1 parent 897fbd4 commit 5c59b7b

7 files changed

Lines changed: 116 additions & 9 deletions

File tree

‎src/main/java/net/sf/jsqlparser/statement/StatementVisitorAdapter.java‎

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -239,7 +239,7 @@ public <S> T visit(ParenthesedInsert insert, S context) {
239239
@Override
240240
public <S> T visit(Drop drop, S context) {
241241
if (drop.getType().equalsIgnoreCase("table")) {
242-
fromItemVisitor.visitFromItem(drop.getName(), context);
242+
drop.getNames().forEach(name -> fromItemVisitor.visitFromItem(name, context));
243243
}
244244
// @todo: handle schemas
245245

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

Lines changed: 58 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -14,8 +14,10 @@
1414
import java.util.Collections;
1515
import java.util.HashMap;
1616
import java.util.List;
17+
import java.util.Locale;
1718
import java.util.Map;
1819
import java.util.Optional;
20+
import java.util.stream.Collectors;
1921

2022
import net.sf.jsqlparser.schema.Table;
2123
import net.sf.jsqlparser.statement.Statement;
@@ -24,8 +26,13 @@
2426

2527
public class Drop implements Statement {
2628

29+
public enum ObjectType {
30+
DATABASE, EVENT, FUNCTION, INDEX, PROCEDURE, SCHEMA, SEQUENCE, SERVER, TABLE, TABLESPACE, TRIGGER, VIEW, OTHER
31+
}
32+
2733
private String type;
28-
private Table name;
34+
private ObjectType objectType = ObjectType.OTHER;
35+
private final List<Table> names = new ArrayList<>();
2936
private List<String> parameters;
3037
private Map<String, List<String>> typeToParameters = new HashMap<>();
3138
private boolean ifExists = false;
@@ -46,11 +53,25 @@ public <T, S> T accept(StatementVisitor<T> statementVisitor, S context) {
4653
}
4754

4855
public Table getName() {
49-
return name;
56+
return names.isEmpty() ? null : names.get(0);
57+
}
58+
59+
public void setName(Table name) {
60+
names.clear();
61+
if (name != null) {
62+
names.add(name);
63+
}
64+
}
65+
66+
public List<Table> getNames() {
67+
return Collections.unmodifiableList(names);
5068
}
5169

52-
public void setName(Table string) {
53-
name = string;
70+
public void setNames(Collection<? extends Table> names) {
71+
this.names.clear();
72+
if (names != null) {
73+
this.names.addAll(names);
74+
}
5475
}
5576

5677
public List<String> getParameters() {
@@ -67,6 +88,22 @@ public String getType() {
6788

6889
public void setType(String string) {
6990
type = string;
91+
try {
92+
objectType = ObjectType.valueOf(string.toUpperCase(Locale.ROOT));
93+
} catch (IllegalArgumentException | NullPointerException ignored) {
94+
objectType = ObjectType.OTHER;
95+
}
96+
}
97+
98+
public ObjectType getObjectType() {
99+
return objectType;
100+
}
101+
102+
public void setObjectType(ObjectType objectType) {
103+
this.objectType = objectType == null ? ObjectType.OTHER : objectType;
104+
if (this.objectType != ObjectType.OTHER) {
105+
this.type = this.objectType.name();
106+
}
70107
}
71108

72109
public boolean isIfExists() {
@@ -112,7 +149,8 @@ public String toString() {
112149
+ (isUsingTemporary ? "TEMPORARY " : "")
113150
+ (materialized ? "MATERIALIZED " : "")
114151
+ type + " "
115-
+ (ifExists ? "IF EXISTS " : "") + name.toString();
152+
+ (ifExists ? "IF EXISTS " : "") + names.stream().map(Table::toString)
153+
.collect(Collectors.joining(", "));
116154

117155
if (type.equals("FUNCTION")) {
118156
sql += formatFuncParams(getParamsByType("FUNCTION"));
@@ -149,6 +187,21 @@ public Drop withName(Table name) {
149187
return this;
150188
}
151189

190+
public Drop withNames(Collection<? extends Table> names) {
191+
setNames(names);
192+
return this;
193+
}
194+
195+
public Drop addNames(Table... names) {
196+
Collections.addAll(this.names, names);
197+
return this;
198+
}
199+
200+
public Drop withObjectType(ObjectType objectType) {
201+
setObjectType(objectType);
202+
return this;
203+
}
204+
152205
public Drop withParameters(List<String> parameters) {
153206
this.setParameters(parameters);
154207
return this;

‎src/main/java/net/sf/jsqlparser/util/TablesNamesFinder.java‎

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1502,7 +1502,7 @@ public void visit(Analyze analyze) {
15021502

15031503
@Override
15041504
public <S> Void visit(Drop drop, S context) {
1505-
visit(drop.getName(), context);
1505+
drop.getNames().forEach(name -> visit(name, context));
15061506
return null;
15071507
}
15081508

‎src/main/java/net/sf/jsqlparser/util/deparser/DropDeParser.java‎

Lines changed: 3 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -9,6 +9,7 @@
99
*/
1010
package net.sf.jsqlparser.util.deparser;
1111

12+
import java.util.stream.Collectors;
1213
import net.sf.jsqlparser.statement.drop.Drop;
1314
import net.sf.jsqlparser.statement.select.PlainSelect;
1415

@@ -32,7 +33,8 @@ public void deParse(Drop drop) {
3233
builder.append(" IF EXISTS");
3334
}
3435

35-
builder.append(" ").append(drop.getName());
36+
builder.append(" ").append(drop.getNames().stream().map(Object::toString)
37+
.collect(Collectors.joining(", ")));
3638

3739
if (drop.getType().equals("FUNCTION")) {
3840
builder.append(Drop.formatFuncParams(drop.getParamsByType("FUNCTION")));

‎src/main/java/net/sf/jsqlparser/util/validation/validator/DropValidator.java‎

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -47,7 +47,7 @@ public void validate(Drop drop) {
4747

4848
NamedObject named = NamedObject.forName(type);
4949
if (Arrays.asList(NamedObject.table, NamedObject.view).contains(named)) {
50-
validateName(named, drop.getName().getFullyQualifiedName());
50+
drop.getNames().forEach(name -> validateName(named, name.getFullyQualifiedName()));
5151
}
5252
}
5353

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

Lines changed: 7 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -12762,17 +12762,24 @@ Drop Drop():
1276212762
|
1276312763
tk=<K_VIEW>
1276412764
|
12765+
tk=<K_DATABASE>
12766+
|
12767+
tk=<K_PROCEDURE>
12768+
|
1276512769
tk=<K_SCHEMA>
1276612770
|
1276712771
tk=<K_SEQUENCE>
1276812772
|
12773+
tk=<K_TRIGGER>
12774+
|
1276912775
tk=<K_FUNCTION>
1277012776
)
1277112777
{ drop.setType(tk.image); }
1277212778

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

1277512781
name = Table() { drop.setName(name); }
12782+
( "," name = Table() { drop.addNames(name); } )*
1277612783
[ LOOKAHEAD(2) funcArgs = FuncArgsList() ]
1277712784
(
1277812785
(

‎src/test/java/net/sf/jsqlparser/statement/drop/DropTest.java‎

Lines changed: 45 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -10,6 +10,8 @@
1010
package net.sf.jsqlparser.statement.drop;
1111

1212
import java.io.StringReader;
13+
import java.util.List;
14+
import java.util.stream.Collectors;
1315
import net.sf.jsqlparser.JSQLParserException;
1416
import net.sf.jsqlparser.parser.CCJSqlParserManager;
1517
import net.sf.jsqlparser.parser.CCJSqlParserUtil;
@@ -169,4 +171,47 @@ public void testDropTableFollowedByLockTableIssue2490() throws JSQLParserExcepti
169171
"DROP TABLE t1; LOCK TABLE t2 IN SHARE MODE;");
170172
assertEquals(2, statements.size());
171173
}
174+
175+
@Test
176+
public void testMySqlDropObjectTypes() throws JSQLParserException {
177+
Drop database = (Drop) assertSqlCanBeParsedAndDeparsed(
178+
"DROP DATABASE IF EXISTS database_1");
179+
assertEquals(Drop.ObjectType.DATABASE, database.getObjectType());
180+
181+
Drop procedure = (Drop) assertSqlCanBeParsedAndDeparsed(
182+
"DROP PROCEDURE IF EXISTS procedure_1");
183+
assertEquals(Drop.ObjectType.PROCEDURE, procedure.getObjectType());
184+
185+
Drop trigger = (Drop) assertSqlCanBeParsedAndDeparsed(
186+
"DROP TRIGGER IF EXISTS schema_1.trigger_1");
187+
assertEquals(Drop.ObjectType.TRIGGER, trigger.getObjectType());
188+
assertEquals("schema_1.trigger_1", trigger.getName().getFullyQualifiedName());
189+
}
190+
191+
@Test
192+
public void testMySqlDropMultipleTables() throws JSQLParserException {
193+
String sql = "DROP TABLE IF EXISTS table_1, table_2, table_3 RESTRICT";
194+
Drop drop = (Drop) assertSqlCanBeParsedAndDeparsed(sql);
195+
196+
assertEquals(List.of("table_1", "table_2", "table_3"), drop.getNames().stream()
197+
.map(Table::getFullyQualifiedName).collect(Collectors.toList()));
198+
assertEquals("table_1", drop.getName().getFullyQualifiedName());
199+
assertEquals(List.of("RESTRICT"), drop.getParameters());
200+
201+
assertDeparse(new Drop().withObjectType(Drop.ObjectType.TABLE).withIfExists(true)
202+
.withNames(List.of(new Table("table_1"), new Table("table_2"),
203+
new Table("table_3")))
204+
.addParameters("RESTRICT"), sql);
205+
}
206+
207+
@Test
208+
public void testMySqlDropMultipleViews() throws JSQLParserException {
209+
Drop drop = (Drop) assertSqlCanBeParsedAndDeparsed(
210+
"DROP VIEW IF EXISTS view_1, view_2 CASCADE");
211+
212+
assertEquals(Drop.ObjectType.VIEW, drop.getObjectType());
213+
assertEquals(List.of("view_1", "view_2"), drop.getNames().stream()
214+
.map(Table::getFullyQualifiedName).collect(Collectors.toList()));
215+
assertEquals(List.of("CASCADE"), drop.getParameters());
216+
}
172217
}

0 commit comments

Comments
 (0)