diff --git a/src/main/java/net/sf/jsqlparser/statement/delete/Delete.java b/src/main/java/net/sf/jsqlparser/statement/delete/Delete.java
index 3072d9872..4e0f45ffe 100644
--- a/src/main/java/net/sf/jsqlparser/statement/delete/Delete.java
+++ b/src/main/java/net/sf/jsqlparser/statement/delete/Delete.java
@@ -17,6 +17,7 @@
import net.sf.jsqlparser.statement.ReturningClause;
import net.sf.jsqlparser.statement.Statement;
import net.sf.jsqlparser.statement.StatementVisitor;
+import net.sf.jsqlparser.statement.select.FromItem;
import net.sf.jsqlparser.statement.select.Join;
import net.sf.jsqlparser.statement.select.Limit;
import net.sf.jsqlparser.statement.select.OrderByElement;
@@ -29,6 +30,7 @@
import java.util.Iterator;
import java.util.List;
import java.util.Optional;
+import java.util.stream.Collectors;
import static java.util.stream.Collectors.joining;
@@ -38,7 +40,7 @@ public class Delete implements Statement {
private Table table;
private OracleHint oracleHint = null;
private List
tables;
- private List usingList;
+ private List usingFromItemList;
private List joins;
private Expression where;
private PreferringClause preferringClause;
@@ -157,12 +159,29 @@ public void setTables(List tables) {
this.tables = tables;
}
+ /**
+ * This is compatible with the old logic. When calling this method, you need to ensure that the
+ * specific table is used after using.
+ *
+ * @return Table collection used in using.
+ */
+ @Deprecated
public List getUsingList() {
- return usingList;
+ if (usingFromItemList == null || usingFromItemList.isEmpty()) {
+ return new ArrayList<>();
+ }
+ return usingFromItemList.stream().map(ele -> (Table) ele).collect(Collectors.toList());
}
+ /**
+ * This is compatible with the old logic. When calling this method, you need to ensure that the
+ * specific table is used after using.
+ *
+ * @param usingList Table collection used in using.
+ */
+ @Deprecated
public void setUsingList(List usingList) {
- this.usingList = usingList;
+ this.usingFromItemList = new ArrayList<>(usingList);
}
public List getJoins() {
@@ -228,10 +247,10 @@ public String toString() {
}
b.append(" ").append(table);
- if (usingList != null && usingList.size() > 0) {
+ if (usingFromItemList != null && !usingFromItemList.isEmpty()) {
b.append(" USING ");
- b.append(usingList.stream()
- .map(Table::toString)
+ b.append(usingFromItemList.stream()
+ .map(Object::toString)
.collect(joining(", ")));
}
@@ -273,11 +292,30 @@ public Delete withTables(List tables) {
return this;
}
+ /**
+ * The old method has been replaced by withUsingFromItemList.
+ *
+ * @param usingList
+ * @return
+ * @see Delete#withUsingFromItemList
+ */
+ @Deprecated
public Delete withUsingList(List usingList) {
this.setUsingList(usingList);
return this;
}
+ /**
+ * New using syntax method.Supports the complete using syntax of pg, such as subqueries, etc.
+ *
+ * @param usingFromItemList
+ * @return
+ */
+ public Delete withUsingFromItemList(List usingFromItemList) {
+ this.setUsingFromItemList(usingFromItemList);
+ return this;
+ }
+
public Delete withJoins(List joins) {
this.setJoins(joins);
return this;
@@ -364,18 +402,60 @@ public Delete addTables(Collection extends Table> tables) {
return this.withTables(collection);
}
+ /**
+ * The old method has been replaced by addUsingFromItemList.
+ *
+ * @param usingList
+ * @return
+ * @see Delete#addUsingFromItemList
+ */
+ @Deprecated
public Delete addUsingList(Table... usingList) {
List collection = Optional.ofNullable(getUsingList()).orElseGet(ArrayList::new);
Collections.addAll(collection, usingList);
return this.withUsingList(collection);
}
+ /**
+ * New using syntax method.Supports the complete using syntax of pg, such as subqueries, etc.
+ *
+ * @param usingFromItemList
+ * @return
+ */
+ public Delete addUsingFromItemList(FromItem... usingFromItemList) {
+ List collection =
+ Optional.ofNullable(getUsingFromItemList()).orElseGet(ArrayList::new);
+ Collections.addAll(collection, usingFromItemList);
+ return this.withUsingFromItemList(collection);
+ }
+
+ /**
+ * The old method has been replaced by addUsingFromItemList.
+ *
+ * @param usingList
+ * @return
+ * @see Delete#addUsingFromItemList
+ */
+ @Deprecated
public Delete addUsingList(Collection extends Table> usingList) {
List collection = Optional.ofNullable(getUsingList()).orElseGet(ArrayList::new);
collection.addAll(usingList);
return this.withUsingList(collection);
}
+ /**
+ * New using syntax method. Supports the complete using syntax of pg, such as subqueries, etc.
+ *
+ * @param usingFromItemList
+ * @return
+ */
+ public Delete addUsingFromItemList(Collection extends Table> usingFromItemList) {
+ List collection =
+ Optional.ofNullable(getUsingFromItemList()).orElseGet(ArrayList::new);
+ collection.addAll(usingFromItemList);
+ return this.withUsingFromItemList(collection);
+ }
+
public Delete addJoins(Join... joins) {
List collection = Optional.ofNullable(getJoins()).orElseGet(ArrayList::new);
Collections.addAll(collection, joins);
@@ -405,4 +485,23 @@ public Delete addOrderByElements(Collection extends OrderByElement> orderByEle
public E getWhere(Class type) {
return type.cast(getWhere());
}
+
+ /**
+ * Return the content after using. Supports the complete using syntax of pg, such as subqueries,
+ * etc.
+ *
+ * @return
+ */
+ public List getUsingFromItemList() {
+ return usingFromItemList;
+ }
+
+ /**
+ * Supports the complete using syntax of pg, such as subqueries, etc.
+ *
+ * @param usingFromItemList The content after using.
+ */
+ public void setUsingFromItemList(List usingFromItemList) {
+ this.usingFromItemList = usingFromItemList;
+ }
}
diff --git a/src/main/java/net/sf/jsqlparser/util/TablesNamesFinder.java b/src/main/java/net/sf/jsqlparser/util/TablesNamesFinder.java
index bbb1b40f5..26568d644 100644
--- a/src/main/java/net/sf/jsqlparser/util/TablesNamesFinder.java
+++ b/src/main/java/net/sf/jsqlparser/util/TablesNamesFinder.java
@@ -167,6 +167,7 @@
import net.sf.jsqlparser.statement.refresh.RefreshMaterializedViewStatement;
import net.sf.jsqlparser.statement.select.AllColumns;
import net.sf.jsqlparser.statement.select.AllTableColumns;
+import net.sf.jsqlparser.statement.select.FromItem;
import net.sf.jsqlparser.statement.select.FromItemVisitor;
import net.sf.jsqlparser.statement.select.FunctionAllColumns;
import net.sf.jsqlparser.statement.select.Join;
@@ -1014,9 +1015,9 @@ public Void visit(MySQLGroupConcat groupConcat, S context) {
public Void visit(Delete delete, S context) {
visit(delete.getTable(), context);
- if (delete.getUsingList() != null) {
- for (Table using : delete.getUsingList()) {
- visit(using, context);
+ if (delete.getUsingFromItemList() != null) {
+ for (FromItem usingFromItem : delete.getUsingFromItemList()) {
+ usingFromItem.accept(this, context);
}
}
diff --git a/src/main/java/net/sf/jsqlparser/util/deparser/DeleteDeParser.java b/src/main/java/net/sf/jsqlparser/util/deparser/DeleteDeParser.java
index 23b5eb32b..2ab59ea14 100644
--- a/src/main/java/net/sf/jsqlparser/util/deparser/DeleteDeParser.java
+++ b/src/main/java/net/sf/jsqlparser/util/deparser/DeleteDeParser.java
@@ -78,9 +78,9 @@ public void deParse(Delete delete) {
}
builder.append(" ").append(delete.getTable().toString());
- if (delete.getUsingList() != null && !delete.getUsingList().isEmpty()) {
+ if (delete.getUsingFromItemList() != null && !delete.getUsingFromItemList().isEmpty()) {
builder.append(" USING").append(
- delete.getUsingList().stream().map(Table::toString)
+ delete.getUsingFromItemList().stream().map(Object::toString)
.collect(joining(", ", " ", "")));
}
if (delete.getJoins() != null) {
diff --git a/src/main/jjtree/net/sf/jsqlparser/parser/JSqlParserCC.jjt b/src/main/jjtree/net/sf/jsqlparser/parser/JSqlParserCC.jjt
index f44a57dda..9998043a7 100644
--- a/src/main/jjtree/net/sf/jsqlparser/parser/JSqlParserCC.jjt
+++ b/src/main/jjtree/net/sf/jsqlparser/parser/JSqlParserCC.jjt
@@ -3012,8 +3012,8 @@ Delete Delete():
Table table = null;
List tables = new ArrayList();
List> with = null;
- Table usingTable = null;
- List usingList = new ArrayList();
+ FromItem usingFromItem = null;
+ List usingFromItemList = new ArrayList();
List joins = null;
Expression where = null;
PreferringClause preferringClause = null;
@@ -3039,8 +3039,8 @@ Delete Delete():
| ) { hasFrom = true; }]
[ LOOKAHEAD(3) table=TableWithAlias() [ LOOKAHEAD(2) joins=JoinsList() ] ]
- [ usingTable=TableWithAlias() { usingList.add(usingTable); }
- ("," usingTable=TableWithAlias() { usingList.add(usingTable); } )*]
+ [ usingFromItem=FromItem() { usingFromItemList.add(usingFromItem); }
+ ("," usingFromItem=FromItem() { usingFromItemList.add(usingFromItem); } )*]
[where=WhereClause() { delete.setWhere(where); } ]
[preferringClause=PreferringClause() { delete.setPreferringClause(preferringClause);} ]
[orderByElements = OrderByElements() { delete.setOrderByElements(orderByElements); } ]
@@ -3055,7 +3055,7 @@ Delete Delete():
.withTables(tables)
.withTable(table)
.withHasFrom(hasFrom)
- .withUsingList(usingList)
+ .withUsingFromItemList(usingFromItemList)
.withModifierPriority(modifierPriority)
.withModifierIgnore(modifierIgnore)
.withModifierQuick(modifierQuick);
diff --git a/src/test/java/net/sf/jsqlparser/statement/delete/DeleteTest.java b/src/test/java/net/sf/jsqlparser/statement/delete/DeleteTest.java
index 7981cc819..2b7bab5e9 100644
--- a/src/test/java/net/sf/jsqlparser/statement/delete/DeleteTest.java
+++ b/src/test/java/net/sf/jsqlparser/statement/delete/DeleteTest.java
@@ -25,7 +25,9 @@
import static org.junit.jupiter.api.Assertions.assertThrows;
import static org.junit.jupiter.api.Assertions.assertTrue;
+import net.sf.jsqlparser.schema.Table;
import net.sf.jsqlparser.statement.insert.Insert;
+import net.sf.jsqlparser.statement.select.ParenthesedSelect;
import net.sf.jsqlparser.statement.select.PlainSelect;
import net.sf.jsqlparser.statement.select.SelectItem;
import net.sf.jsqlparser.statement.select.WithItem;
@@ -397,4 +399,19 @@ public void testDeleteWithSkylineKeywords() throws JSQLParserException {
delete.getWhere().toString());
}
+ @Test
+ public void testDeleteUsingFromItem() throws JSQLParserException {
+ String statement =
+ "DELETE A USING B.C D,(SELECT id FROM producers WHERE active = false) p WHERE D.Z = 1 and p.id = D.id";
+ Delete delete = (Delete) assertSqlCanBeParsedAndDeparsed(statement);
+ assertEquals("B.C",
+ ((Table) delete.getUsingFromItemList().get(0)).getFullyQualifiedName());
+ assertEquals("D",
+ ((Table) delete.getUsingFromItemList().get(0)).getAlias().getName());
+ assertEquals("producers",
+ ((Table) ((ParenthesedSelect) delete.getUsingFromItemList().get(1)).getPlainSelect()
+ .getFromItem()).getFullyQualifiedName());
+ assertEquals("p",
+ delete.getUsingFromItemList().get(1).getAlias().getName());
+ }
}