diff --git a/src/main/java/net/sf/jsqlparser/expression/RangeExpression.java b/src/main/java/net/sf/jsqlparser/expression/RangeExpression.java index 19d0fa628..69cba377d 100644 --- a/src/main/java/net/sf/jsqlparser/expression/RangeExpression.java +++ b/src/main/java/net/sf/jsqlparser/expression/RangeExpression.java @@ -1,3 +1,12 @@ +/*- + * #%L + * JSQLParser library + * %% + * Copyright (C) 2004 - 2023 JSQLParser + * %% + * Dual licensed under GNU LGPL 2.1 or Apache License 2.0 + * #L% + */ package net.sf.jsqlparser.expression; import net.sf.jsqlparser.parser.ASTNodeAccessImpl; diff --git a/src/main/java/net/sf/jsqlparser/expression/operators/relational/ExpressionList.java b/src/main/java/net/sf/jsqlparser/expression/operators/relational/ExpressionList.java index f1c03bd59..9f08215b8 100644 --- a/src/main/java/net/sf/jsqlparser/expression/operators/relational/ExpressionList.java +++ b/src/main/java/net/sf/jsqlparser/expression/operators/relational/ExpressionList.java @@ -11,7 +11,6 @@ import net.sf.jsqlparser.expression.Expression; import net.sf.jsqlparser.expression.ExpressionVisitor; -import net.sf.jsqlparser.statement.select.PlainSelect; import net.sf.jsqlparser.parser.SimpleNode; import java.io.Serializable; @@ -65,7 +64,7 @@ public ExpressionList addExpressions(T... expressions) { return this; } - public ExpressionList addExpressions(Collection expressions) { + public ExpressionList addExpressions(Collection expressions) { addAll(expressions); return this; } @@ -80,9 +79,19 @@ public ExpressionList withExpressions(Collection expressions) { return addExpressions(expressions); } + public StringBuilder appendTo(StringBuilder builder) { + for (int i = 0; i < size(); i++) { + if (i > 0) { + builder.append(", "); + } + builder.append(get(i)); + } + return builder; + } + @Override public String toString() { - return PlainSelect.getStringList(this, true, false); + return appendTo(new StringBuilder()).toString(); } @Override diff --git a/src/main/java/net/sf/jsqlparser/expression/operators/relational/MemberOfExpression.java b/src/main/java/net/sf/jsqlparser/expression/operators/relational/MemberOfExpression.java index b8279840d..590606629 100644 --- a/src/main/java/net/sf/jsqlparser/expression/operators/relational/MemberOfExpression.java +++ b/src/main/java/net/sf/jsqlparser/expression/operators/relational/MemberOfExpression.java @@ -1,3 +1,12 @@ +/*- + * #%L + * JSQLParser library + * %% + * Copyright (C) 2004 - 2023 JSQLParser + * %% + * Dual licensed under GNU LGPL 2.1 or Apache License 2.0 + * #L% + */ package net.sf.jsqlparser.expression.operators.relational; import net.sf.jsqlparser.expression.Expression; diff --git a/src/main/java/net/sf/jsqlparser/statement/ReturningClause.java b/src/main/java/net/sf/jsqlparser/statement/ReturningClause.java new file mode 100644 index 000000000..6d42ffdfc --- /dev/null +++ b/src/main/java/net/sf/jsqlparser/statement/ReturningClause.java @@ -0,0 +1,97 @@ +/*- + * #%L + * JSQLParser library + * %% + * Copyright (C) 2004 - 2023 JSQLParser + * %% + * Dual licensed under GNU LGPL 2.1 or Apache License 2.0 + * #L% + */ +package net.sf.jsqlparser.statement; + +import net.sf.jsqlparser.statement.select.SelectItem; + +import java.util.ArrayList; +import java.util.List; + +/** + * RETURNING clause according to + * {@see https://docs.oracle.com/en/database/oracle/oracle-database/19/sqlrf/DELETE.html#GUID-156845A5-B626-412B-9F95-8869B988ABD7 + * } Part of UPDATE, INSERT, DELETE statements + */ + +public class ReturningClause extends ArrayList> { + enum Keyword { + RETURN, RETURNING; + + public static Keyword from(String keyword) { + return Enum.valueOf(Keyword.class, keyword.toUpperCase()); + } + } + + private Keyword keyword; + + /** + * List of output targets like Table or UserVariable + */ + private final List dataItems; + + public ReturningClause(Keyword keyword, List> selectItems, + List dataItems) { + this.keyword = keyword; + this.addAll(selectItems); + this.dataItems = dataItems; + } + + public ReturningClause(String keyword, List> selectItems, + List dataItems) { + this(Keyword.from(keyword), selectItems, dataItems); + } + + public ReturningClause(Keyword keyword, List> selectItems) { + this(keyword, selectItems, null); + } + + public ReturningClause(String keyword, List> selectItems) { + this(Keyword.valueOf(keyword), selectItems, null); + } + + public Keyword getKeyword() { + return keyword; + } + + public ReturningClause setKeyword(Keyword keyword) { + this.keyword = keyword; + return this; + } + + public List getDataItems() { + return dataItems; + } + + public StringBuilder appendTo(StringBuilder builder) { + builder.append(" ").append(keyword).append(" "); + for (int i = 0; i < size(); i++) { + if (i > 0) { + builder.append(", "); + } + builder.append(get(i)); + } + + if (dataItems != null && dataItems.size() > 0) { + builder.append(" INTO "); + for (int i = 0; i < dataItems.size(); i++) { + if (i > 0) { + builder.append(" ,"); + } + builder.append(dataItems.get(i)); + } + } + return builder; + } + + @Override + public String toString() { + return appendTo(new StringBuilder()).toString(); + } +} 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 b5deac617..c28a4a0d8 100644 --- a/src/main/java/net/sf/jsqlparser/statement/delete/Delete.java +++ b/src/main/java/net/sf/jsqlparser/statement/delete/Delete.java @@ -13,13 +13,13 @@ import net.sf.jsqlparser.expression.OracleHint; import net.sf.jsqlparser.schema.Table; import net.sf.jsqlparser.statement.OutputClause; +import net.sf.jsqlparser.statement.ReturningClause; import net.sf.jsqlparser.statement.Statement; import net.sf.jsqlparser.statement.StatementVisitor; import net.sf.jsqlparser.statement.select.Join; import net.sf.jsqlparser.statement.select.Limit; import net.sf.jsqlparser.statement.select.OrderByElement; import net.sf.jsqlparser.statement.select.PlainSelect; -import net.sf.jsqlparser.statement.select.SelectItem; import net.sf.jsqlparser.statement.select.WithItem; import java.util.ArrayList; @@ -46,7 +46,8 @@ public class Delete implements Statement { private DeleteModifierPriority modifierPriority; private boolean modifierIgnore; private boolean modifierQuick; - private List> returningExpressionList = null; + + private ReturningClause returningClause; private OutputClause outputClause; public OutputClause getOutputClause() { @@ -57,16 +58,12 @@ public void setOutputClause(OutputClause outputClause) { this.outputClause = outputClause; } - public List> getReturningExpressionList() { - return returningExpressionList; - } - - public void setReturningExpressionList(List> returningExpressionList) { - this.returningExpressionList = returningExpressionList; + public ReturningClause getReturningClause() { + return returningClause; } - public Delete withReturningExpressionList(List> returningExpressionList) { - this.returningExpressionList = returningExpressionList; + public Delete setReturningClause(ReturningClause returningClause) { + this.returningClause = returningClause; return this; } @@ -248,9 +245,8 @@ public String toString() { b.append(limit); } - if (getReturningExpressionList() != null) { - b.append(" RETURNING ") - .append(PlainSelect.getStringList(getReturningExpressionList(), true, false)); + if (returningClause != null) { + returningClause.appendTo(b); } return b.toString(); diff --git a/src/main/java/net/sf/jsqlparser/statement/insert/Insert.java b/src/main/java/net/sf/jsqlparser/statement/insert/Insert.java index 6c87b45fe..398c7c138 100644 --- a/src/main/java/net/sf/jsqlparser/statement/insert/Insert.java +++ b/src/main/java/net/sf/jsqlparser/statement/insert/Insert.java @@ -14,17 +14,16 @@ import net.sf.jsqlparser.schema.Column; import net.sf.jsqlparser.schema.Table; import net.sf.jsqlparser.statement.OutputClause; +import net.sf.jsqlparser.statement.ReturningClause; import net.sf.jsqlparser.statement.Statement; import net.sf.jsqlparser.statement.StatementVisitor; import net.sf.jsqlparser.statement.select.PlainSelect; import net.sf.jsqlparser.statement.select.Select; -import net.sf.jsqlparser.statement.select.SelectItem; import net.sf.jsqlparser.statement.select.SetOperationList; import net.sf.jsqlparser.statement.select.Values; import net.sf.jsqlparser.statement.select.WithItem; import net.sf.jsqlparser.statement.update.UpdateSet; -import java.util.ArrayList; import java.util.Arrays; import java.util.Collection; import java.util.Iterator; @@ -41,7 +40,7 @@ public class Insert implements Statement { private List duplicateUpdateSets = null; private InsertModifierPriority modifierPriority = null; private boolean modifierIgnore = false; - private List> returningExpressionList = null; + private ReturningClause returningClause; private List setUpdateSets = null; private List withItemsList; private OutputClause outputClause; @@ -108,12 +107,13 @@ public boolean isUseValues() { return select != null && select instanceof Values; } - public List> getReturningExpressionList() { - return returningExpressionList; + public ReturningClause getReturningClause() { + return returningClause; } - public void setReturningExpressionList(List> returningExpressionList) { - this.returningExpressionList = returningExpressionList; + public Insert setReturningClause(ReturningClause returningClause) { + this.returningClause = returningClause; + return this; } public Select getSelect() { @@ -257,9 +257,8 @@ public String toString() { conflictAction.appendTo(sql); } - if (getReturningExpressionList() != null) { - sql.append(" RETURNING ") - .append(PlainSelect.getStringList(getReturningExpressionList(), true, false)); + if (returningClause != null) { + returningClause.appendTo(sql); } return sql.toString(); @@ -285,11 +284,6 @@ public Insert withModifierIgnore(boolean modifierIgnore) { return this; } - public Insert withReturningExpressionList(List> returningExpressionList) { - this.setReturningExpressionList(returningExpressionList); - return this; - } - public Insert withTable(Table table) { this.setTable(table); return this; @@ -310,16 +304,4 @@ public Insert addColumns(Collection columns) { collection.addAll(columns); return this.withColumns(collection); } - - public Insert addReturningExpressionList(SelectItem... returningExpressions) { - return this.addReturningExpressionList(Arrays.asList(returningExpressions)); - } - - public Insert addReturningExpressionList( - Collection> returningExpressions) { - List> collection = - Optional.ofNullable(getReturningExpressionList()).orElseGet(ArrayList::new); - collection.addAll(returningExpressions); - return this.withReturningExpressionList(collection); - } } diff --git a/src/main/java/net/sf/jsqlparser/statement/update/Update.java b/src/main/java/net/sf/jsqlparser/statement/update/Update.java index 6cbae76e7..0ba506ea6 100644 --- a/src/main/java/net/sf/jsqlparser/statement/update/Update.java +++ b/src/main/java/net/sf/jsqlparser/statement/update/Update.java @@ -14,6 +14,7 @@ import net.sf.jsqlparser.schema.Column; import net.sf.jsqlparser.schema.Table; import net.sf.jsqlparser.statement.OutputClause; +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; @@ -22,7 +23,6 @@ import net.sf.jsqlparser.statement.select.OrderByElement; import net.sf.jsqlparser.statement.select.PlainSelect; import net.sf.jsqlparser.statement.select.Select; -import net.sf.jsqlparser.statement.select.SelectItem; import net.sf.jsqlparser.statement.select.WithItem; import java.util.ArrayList; @@ -46,7 +46,7 @@ public class Update implements Statement { private OracleHint oracleHint = null; private List orderByElements; private Limit limit; - private List> returningExpressionList = null; + private ReturningClause returningClause; private UpdateModifierPriority modifierPriority; private boolean modifierIgnore; @@ -245,12 +245,13 @@ public Limit getLimit() { return limit; } - public List> getReturningExpressionList() { - return returningExpressionList; + public ReturningClause getReturningClause() { + return returningClause; } - public void setReturningExpressionList(List> returningExpressionList) { - this.returningExpressionList = returningExpressionList; + public Update setReturningClause(ReturningClause returningClause) { + this.returningClause = returningClause; + return this; } public UpdateModifierPriority getModifierPriority() { @@ -335,9 +336,8 @@ public String toString() { b.append(limit); } - if (getReturningExpressionList() != null) { - b.append(" RETURNING ") - .append(PlainSelect.getStringList(getReturningExpressionList(), true, false)); + if (returningClause != null) { + returningClause.appendTo(b); } return b.toString(); @@ -388,11 +388,6 @@ public Update withLimit(Limit limit) { return this; } - public Update withReturningExpressionList(List> returningExpressionList) { - this.setReturningExpressionList(returningExpressionList); - return this; - } - public Update withWhere(Expression where) { this.setWhere(where); return this; @@ -478,21 +473,6 @@ public Update addOrderByElements(Collection orderByEle return this.withOrderByElements(collection); } - public Update addReturningExpressionList(SelectItem... returningExpressionList) { - List> collection = - Optional.ofNullable(getReturningExpressionList()).orElseGet(ArrayList::new); - Collections.addAll(collection, returningExpressionList); - return this.withReturningExpressionList(collection); - } - - public Update addReturningExpressionList( - Collection> returningExpressionList) { - List> collection = - Optional.ofNullable(getReturningExpressionList()).orElseGet(ArrayList::new); - collection.addAll(returningExpressionList); - return this.withReturningExpressionList(collection); - } - public E getWhere(Class type) { return type.cast(getWhere()); } diff --git a/src/main/java/net/sf/jsqlparser/statement/upsert/Upsert.java b/src/main/java/net/sf/jsqlparser/statement/upsert/Upsert.java index 6b6660703..4e63782d2 100644 --- a/src/main/java/net/sf/jsqlparser/statement/upsert/Upsert.java +++ b/src/main/java/net/sf/jsqlparser/statement/upsert/Upsert.java @@ -9,7 +9,6 @@ */ package net.sf.jsqlparser.statement.upsert; -import net.sf.jsqlparser.expression.Expression; import net.sf.jsqlparser.expression.operators.relational.ExpressionList; import net.sf.jsqlparser.schema.Column; import net.sf.jsqlparser.schema.Table; @@ -30,7 +29,7 @@ public class Upsert implements Statement { private Table table; private ExpressionList columns; - private ExpressionList expressions; + private ExpressionList expressions; private Select select; private List updateSets; private List duplicateUpdateSets; @@ -111,7 +110,7 @@ public void setExpressions(ExpressionList list) { } @Deprecated - public ExpressionList getSetExpressions() { + public ExpressionList getSetExpressions() { return expressions; } 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 3b5b34803..b97794af4 100644 --- a/src/main/java/net/sf/jsqlparser/util/deparser/DeleteDeParser.java +++ b/src/main/java/net/sf/jsqlparser/util/deparser/DeleteDeParser.java @@ -14,7 +14,6 @@ import net.sf.jsqlparser.schema.Table; import net.sf.jsqlparser.statement.delete.Delete; import net.sf.jsqlparser.statement.select.Join; -import net.sf.jsqlparser.statement.select.PlainSelect; import net.sf.jsqlparser.statement.select.WithItem; import java.util.Iterator; @@ -100,9 +99,8 @@ public void deParse(Delete delete) { new LimitDeparser(expressionVisitor, buffer).deParse(delete.getLimit()); } - if (delete.getReturningExpressionList() != null) { - buffer.append(" RETURNING ").append( - PlainSelect.getStringList(delete.getReturningExpressionList(), true, false)); + if (delete.getReturningClause() != null) { + delete.getReturningClause().appendTo(buffer); } } diff --git a/src/main/java/net/sf/jsqlparser/util/deparser/InsertDeParser.java b/src/main/java/net/sf/jsqlparser/util/deparser/InsertDeParser.java index 5a10fd4a4..a0614540e 100644 --- a/src/main/java/net/sf/jsqlparser/util/deparser/InsertDeParser.java +++ b/src/main/java/net/sf/jsqlparser/util/deparser/InsertDeParser.java @@ -12,7 +12,6 @@ import net.sf.jsqlparser.expression.ExpressionVisitor; import net.sf.jsqlparser.schema.Column; import net.sf.jsqlparser.statement.insert.Insert; -import net.sf.jsqlparser.statement.select.PlainSelect; import net.sf.jsqlparser.statement.select.Select; import net.sf.jsqlparser.statement.select.SelectVisitor; import net.sf.jsqlparser.statement.select.WithItem; @@ -104,9 +103,8 @@ public void deParse(Insert insert) { insert.getConflictAction().appendTo(buffer); } - if (insert.getReturningExpressionList() != null) { - buffer.append(" RETURNING ").append( - PlainSelect.getStringList(insert.getReturningExpressionList(), true, false)); + if (insert.getReturningClause() != null) { + insert.getReturningClause().appendTo(buffer); } } diff --git a/src/main/java/net/sf/jsqlparser/util/deparser/UpdateDeParser.java b/src/main/java/net/sf/jsqlparser/util/deparser/UpdateDeParser.java index e147d5e6b..4f8affbeb 100644 --- a/src/main/java/net/sf/jsqlparser/util/deparser/UpdateDeParser.java +++ b/src/main/java/net/sf/jsqlparser/util/deparser/UpdateDeParser.java @@ -14,7 +14,6 @@ import net.sf.jsqlparser.statement.select.Join; import net.sf.jsqlparser.statement.select.OrderByElement; import net.sf.jsqlparser.statement.select.OrderByVisitor; -import net.sf.jsqlparser.statement.select.PlainSelect; import net.sf.jsqlparser.statement.select.WithItem; import net.sf.jsqlparser.statement.update.Update; @@ -97,9 +96,8 @@ public void deParse(Update update) { new LimitDeparser(expressionVisitor, buffer).deParse(update.getLimit()); } - if (update.getReturningExpressionList() != null) { - buffer.append(" RETURNING ").append( - PlainSelect.getStringList(update.getReturningExpressionList(), true, false)); + if (update.getReturningClause() != null) { + update.getReturningClause().appendTo(buffer); } } diff --git a/src/main/java/net/sf/jsqlparser/util/validation/validator/DeleteValidator.java b/src/main/java/net/sf/jsqlparser/util/validation/validator/DeleteValidator.java index 564278dfe..3de5343c4 100644 --- a/src/main/java/net/sf/jsqlparser/util/validation/validator/DeleteValidator.java +++ b/src/main/java/net/sf/jsqlparser/util/validation/validator/DeleteValidator.java @@ -28,7 +28,8 @@ public void validate(Delete delete) { validateOptionalFeature(c, delete.getJoins(), Feature.deleteJoin); validateOptionalFeature(c, delete.getLimit(), Feature.deleteLimit); validateOptionalFeature(c, delete.getOrderByElements(), Feature.deleteOrderBy); - validateOptionalFeature(c, delete.getReturningExpressionList(), Feature.deleteReturningExpressionList); + validateOptionalFeature(c, delete.getReturningClause(), + Feature.deleteReturningExpressionList); } SelectValidator v = getValidator(SelectValidator.class); @@ -47,8 +48,8 @@ public void validate(Delete delete) { getValidator(LimitValidator.class).validate(delete.getLimit()); } - if (isNotEmpty(delete.getReturningExpressionList())) { - delete.getReturningExpressionList().forEach(c -> c .accept(v)); + if (delete.getReturningClause() != null) { + delete.getReturningClause().forEach(c -> c.accept(v)); } } diff --git a/src/main/java/net/sf/jsqlparser/util/validation/validator/InsertValidator.java b/src/main/java/net/sf/jsqlparser/util/validation/validator/InsertValidator.java index 187e717ab..be09f314c 100644 --- a/src/main/java/net/sf/jsqlparser/util/validation/validator/InsertValidator.java +++ b/src/main/java/net/sf/jsqlparser/util/validation/validator/InsertValidator.java @@ -37,7 +37,7 @@ public void validate(Insert insert) { validateOptionalFeature(c, insert.getSelect(), Feature.insertFromSelect); validateFeature(c, insert.isUseSet(), Feature.insertUseSet); validateFeature(c, insert.isUseDuplicate(), Feature.insertUseDuplicateKeyUpdate); - validateOptionalFeature(c, insert.getReturningExpressionList(), + validateOptionalFeature(c, insert.getReturningClause(), Feature.insertReturningExpressionList); } @@ -71,9 +71,9 @@ public void validate(Insert insert) { } } - if (isNotEmpty(insert.getReturningExpressionList())) { + if (insert.getReturningClause() != null) { SelectValidator v = getValidator(SelectValidator.class); - insert.getReturningExpressionList().forEach(c -> c.accept(v)); + insert.getReturningClause().forEach(c -> c.accept(v)); } } diff --git a/src/main/java/net/sf/jsqlparser/util/validation/validator/UpdateValidator.java b/src/main/java/net/sf/jsqlparser/util/validation/validator/UpdateValidator.java index 052dfd6d1..735725126 100644 --- a/src/main/java/net/sf/jsqlparser/util/validation/validator/UpdateValidator.java +++ b/src/main/java/net/sf/jsqlparser/util/validation/validator/UpdateValidator.java @@ -28,7 +28,7 @@ public void validate(Update update) { validateFeature(c, update.isUseSelect(), Feature.updateUseSelect); validateOptionalFeature(c, update.getOrderByElements(), Feature.updateOrderBy); validateOptionalFeature(c, update.getLimit(), Feature.updateLimit); - validateOptionalFeature(c, update.getReturningExpressionList(), + validateOptionalFeature(c, update.getReturningClause(), Feature.updateReturning); } @@ -59,9 +59,9 @@ public void validate(Update update) { getValidator(LimitValidator.class).validate(update.getLimit()); } - if (isNotEmpty(update.getReturningExpressionList())) { + if (update.getReturningClause() != null) { SelectValidator v = getValidator(SelectValidator.class); - update.getReturningExpressionList().forEach(c -> c.accept(v)); + update.getReturningClause().forEach(c -> c.accept(v)); } } diff --git a/src/main/jjtree/net/sf/jsqlparser/parser/JSqlParserCC.jjt b/src/main/jjtree/net/sf/jsqlparser/parser/JSqlParserCC.jjt index 33d04c871..1d5fd3091 100644 --- a/src/main/jjtree/net/sf/jsqlparser/parser/JSqlParserCC.jjt +++ b/src/main/jjtree/net/sf/jsqlparser/parser/JSqlParserCC.jjt @@ -1179,7 +1179,7 @@ Statement Show(): captureRest = captureRest() { if (captureRest.size()==1) { - statement = new ShowStatement(captureRest.get(1)); + statement = new ShowStatement(captureRest.get(0)); } else { statement = new UnsupportedStatement("SHOW", captureRest); } @@ -1253,6 +1253,33 @@ Values Values(): { } } +ReturningClause ReturningClause(): +{ + Token keyword; + List> selectItems; + Object dataItem; + List dataItems = null; +} +{ + ( keyword= | keyword="RETURN" ) + selectItems = SelectItemsList() + + [ + + ( dataItem = Table() | dataItem = UserVariable() ) + { dataItems = new ArrayList(); dataItems.add(dataItem); } + + ( + "," + ( dataItem = Table() | dataItem = UserVariable() ) { dataItems.add(dataItem); } + )* + ] + + { + return new ReturningClause(keyword.image, selectItems, dataItems); + } +} + Update Update( List with ): { Update update = new Update(); @@ -1266,7 +1293,7 @@ Update Update( List with ): Limit limit = null; List orderByElements; boolean useColumnsBrackets = false; - List> returning = null; + ReturningClause returningClause; Token tk = null; UpdateModifierPriority modifierPriority = null; boolean modifierIgnore = false; @@ -1290,7 +1317,7 @@ Update Update( List with ): [ orderByElements = OrderByElements() { update.setOrderByElements(orderByElements); } ] [ limit = PlainLimit() { update.setLimit(limit); } ] - [ returning=SelectItemsList() ] + [ returningClause = ReturningClause() { update.setReturningClause(returningClause); } ] { return update.withWithItemsList(with) @@ -1299,8 +1326,7 @@ Update Update( List with ): .withFromItem(fromItem) .withJoins(joins) .withModifierPriority(modifierPriority) - .withModifierIgnore(modifierIgnore) - .withReturningExpressionList(returning); + .withModifierIgnore(modifierIgnore); } } @@ -1364,7 +1390,7 @@ Insert Insert( List with ): Column tableColumn = null; ExpressionList columns = new ExpressionList(); Expression exp = null; - List> returning = null; + ReturningClause returningClause; Select select = null; boolean useDuplicate = false; Token tk = null; @@ -1418,7 +1444,7 @@ Insert Insert( List with ): conflictAction = InsertConflictAction() { insert.withConflictTarget(conflictTarget).setConflictAction(conflictAction); } ] - [ returning=SelectItemsList() ] + [ returningClause = ReturningClause() { insert.setReturningClause(returningClause); } ] { if (!columns.isEmpty()) { @@ -1427,7 +1453,6 @@ Insert Insert( List with ): return insert.withWithItemsList(with) .withSelect(select) .withTable(table) - .withReturningExpressionList(returning) .withModifierPriority(modifierPriority) .withModifierIgnore(modifierIgnore); } @@ -1520,7 +1545,6 @@ Upsert Upsert(): ExpressionList columns; List updateSets; - List> returning = null; Select select = null; List duplicateUpdateSets; Token tk = null; @@ -1578,8 +1602,8 @@ Delete Delete( List with ): boolean modifierIgnore = false; boolean modifierQuick = false; - List> returning = null; - OutputClause outputClause = null; + ReturningClause returningClause; + OutputClause outputClause; } { { delete.setOracleHint(getOracleHint()); } @@ -1598,7 +1622,7 @@ Delete Delete( List with ): [orderByElements = OrderByElements() { delete.setOrderByElements(orderByElements); } ] [limit=PlainLimit() {delete.setLimit(limit); } ] - [ returning=SelectItemsList() ] + [ returningClause = ReturningClause() { delete.setReturningClause(returningClause); } ] { if (joins != null && joins.size() > 0) { delete.setJoins(joins); @@ -1610,8 +1634,7 @@ Delete Delete( List with ): .withUsingList(usingList) .withModifierPriority(modifierPriority) .withModifierIgnore(modifierIgnore) - .withModifierQuick(modifierQuick) - .withReturningExpressionList(returning); + .withModifierQuick(modifierQuick); } } diff --git a/src/test/java/net/sf/jsqlparser/expression/JdbcNamedParameterTest.java b/src/test/java/net/sf/jsqlparser/expression/JdbcNamedParameterTest.java index 685a807e9..f2a4bfe70 100644 --- a/src/test/java/net/sf/jsqlparser/expression/JdbcNamedParameterTest.java +++ b/src/test/java/net/sf/jsqlparser/expression/JdbcNamedParameterTest.java @@ -1,3 +1,12 @@ +/*- + * #%L + * JSQLParser library + * %% + * Copyright (C) 2004 - 2023 JSQLParser + * %% + * Dual licensed under GNU LGPL 2.1 or Apache License 2.0 + * #L% + */ package net.sf.jsqlparser.expression; import net.sf.jsqlparser.JSQLParserException; diff --git a/src/test/java/net/sf/jsqlparser/expression/operators/relational/MemberOfExpressionTest.java b/src/test/java/net/sf/jsqlparser/expression/operators/relational/MemberOfExpressionTest.java index b0ff896a0..07da800e1 100644 --- a/src/test/java/net/sf/jsqlparser/expression/operators/relational/MemberOfExpressionTest.java +++ b/src/test/java/net/sf/jsqlparser/expression/operators/relational/MemberOfExpressionTest.java @@ -1,11 +1,18 @@ +/*- + * #%L + * JSQLParser library + * %% + * Copyright (C) 2004 - 2023 JSQLParser + * %% + * Dual licensed under GNU LGPL 2.1 or Apache License 2.0 + * #L% + */ package net.sf.jsqlparser.expression.operators.relational; import net.sf.jsqlparser.JSQLParserException; import net.sf.jsqlparser.test.TestUtils; import org.junit.jupiter.api.Test; -import static org.junit.jupiter.api.Assertions.*; - class MemberOfExpressionTest { @Test void testMemberOf() throws JSQLParserException { diff --git a/src/test/java/net/sf/jsqlparser/statement/ReturningClause.java b/src/test/java/net/sf/jsqlparser/statement/ReturningClause.java deleted file mode 100644 index eef449245..000000000 --- a/src/test/java/net/sf/jsqlparser/statement/ReturningClause.java +++ /dev/null @@ -1,12 +0,0 @@ -package net.sf.jsqlparser.statement; - -import net.sf.jsqlparser.expression.operators.relational.ExpressionList; -import net.sf.jsqlparser.schema.Column; - -/** - * @see https://docs.oracle.com/en/database/oracle/oracle-database/21/lnpls/RETURNING-INTO-clause.html#GUID-38F735B9-1100-45AF-AE71-18FB74A899BE - */ -public class ReturningClause { - private String returnKeyword = "RETURNING"; - ExpressionList columns; -} diff --git a/src/test/java/net/sf/jsqlparser/statement/ReturningClauseTest.java b/src/test/java/net/sf/jsqlparser/statement/ReturningClauseTest.java new file mode 100644 index 000000000..331f7263b --- /dev/null +++ b/src/test/java/net/sf/jsqlparser/statement/ReturningClauseTest.java @@ -0,0 +1,28 @@ +/*- + * #%L + * JSQLParser library + * %% + * Copyright (C) 2004 - 2023 JSQLParser + * %% + * Dual licensed under GNU LGPL 2.1 or Apache License 2.0 + * #L% + */ +package net.sf.jsqlparser.statement; + +import net.sf.jsqlparser.JSQLParserException; +import net.sf.jsqlparser.test.TestUtils; +import org.junit.jupiter.api.Test; + +class ReturningClauseTest { + @Test + void returnIntoTest() throws JSQLParserException { + String sqlStr = " insert into emp\n" + + " (empno, ename)\n" + + " values\n" + + " (seq_emp.nextval, 'morgan')\n" + + " returning empno\n" + + " into x"; + TestUtils.assertSqlCanBeParsedAndDeparsed(sqlStr, true); + } + +} diff --git a/src/test/java/net/sf/jsqlparser/statement/select/SpecialOracleTest.java b/src/test/java/net/sf/jsqlparser/statement/select/SpecialOracleTest.java index 862d4a0a7..6d2b4a1a8 100644 --- a/src/test/java/net/sf/jsqlparser/statement/select/SpecialOracleTest.java +++ b/src/test/java/net/sf/jsqlparser/statement/select/SpecialOracleTest.java @@ -89,7 +89,8 @@ public class SpecialOracleTest { "groupby08.sql", "groupby09.sql", "groupby10.sql", "groupby11.sql", "groupby12.sql", "groupby13.sql", "groupby14.sql", "groupby15.sql", "groupby16.sql", "groupby17.sql", "groupby19.sql", "groupby20.sql", "groupby21.sql", "groupby22.sql", "groupby23.sql", - "insert02.sql", "interval02.sql", "interval04.sql", "interval05.sql", "join01.sql", + "insert02.sql", "insert11.sql", "insert12.sql", "interval02.sql", "interval04.sql", + "interval05.sql", "join01.sql", "join02.sql", "join03.sql", "join04.sql", "join06.sql", "join07.sql", "join08.sql", "join09.sql", "join10.sql", "join11.sql", "join12.sql", "join13.sql", "join14.sql", "join15.sql", "join16.sql", "join17.sql", "join18.sql", "join19.sql", "join20.sql", diff --git a/src/test/java/net/sf/jsqlparser/util/APISanitationTest.java b/src/test/java/net/sf/jsqlparser/util/APISanitationTest.java index 2fa898d64..89efa2651 100644 --- a/src/test/java/net/sf/jsqlparser/util/APISanitationTest.java +++ b/src/test/java/net/sf/jsqlparser/util/APISanitationTest.java @@ -1,3 +1,12 @@ +/*- + * #%L + * JSQLParser library + * %% + * Copyright (C) 2004 - 2023 JSQLParser + * %% + * Dual licensed under GNU LGPL 2.1 or Apache License 2.0 + * #L% + */ package net.sf.jsqlparser.util; import net.sf.jsqlparser.expression.Expression; @@ -272,11 +281,13 @@ boolean testGenericType(Field field, Class boundClass) { ParameterizedType parameterizedType = (ParameterizedType) superclassType; if (parameterizedType != null) { for (final Type actualTypeArgument : parameterizedType.getActualTypeArguments()) { - final TypeVariable typeVariable = - (TypeVariable) actualTypeArgument; - for (Type type : typeVariable.getBounds()) { - if (type.getTypeName().equals(boundClass.getTypeName())) { - return true; + if (actualTypeArgument instanceof TypeVariable) { + final TypeVariable typeVariable = + (TypeVariable) actualTypeArgument; + for (Type type : typeVariable.getBounds()) { + if (type.getTypeName().equals(boundClass.getTypeName())) { + return true; + } } } } diff --git a/src/test/resources/net/sf/jsqlparser/statement/select/oracle-tests/insert11.sql b/src/test/resources/net/sf/jsqlparser/statement/select/oracle-tests/insert11.sql index 34b8d4df2..4bc74d6fb 100644 --- a/src/test/resources/net/sf/jsqlparser/statement/select/oracle-tests/insert11.sql +++ b/src/test/resources/net/sf/jsqlparser/statement/select/oracle-tests/insert11.sql @@ -15,4 +15,5 @@ into x --@FAILURE: Encountered unexpected token: "into" "INTO" recorded first on Aug 3, 2021, 7:20:08 AM ---@FAILURE: Encountered unexpected token: "x" recorded first on 24 Oct 2021, 16:56:39 \ No newline at end of file +--@FAILURE: Encountered unexpected token: "x" recorded first on 24 Oct 2021, 16:56:39 +--@SUCCESSFULLY_PARSED_AND_DEPARSED first on 16 May 2023, 20:12:52 \ No newline at end of file diff --git a/src/test/resources/net/sf/jsqlparser/statement/select/oracle-tests/insert12.sql b/src/test/resources/net/sf/jsqlparser/statement/select/oracle-tests/insert12.sql index 8c5c511c3..ebb68fdfd 100644 --- a/src/test/resources/net/sf/jsqlparser/statement/select/oracle-tests/insert12.sql +++ b/src/test/resources/net/sf/jsqlparser/statement/select/oracle-tests/insert12.sql @@ -15,4 +15,5 @@ into r --@FAILURE: Encountered unexpected token: "into" "INTO" recorded first on Aug 3, 2021, 7:20:08 AM ---@FAILURE: Encountered unexpected token: "r" recorded first on 24 Oct 2021, 16:56:39 \ No newline at end of file +--@FAILURE: Encountered unexpected token: "r" recorded first on 24 Oct 2021, 16:56:39 +--@SUCCESSFULLY_PARSED_AND_DEPARSED first on 16 May 2023, 20:12:52 \ No newline at end of file