diff --git a/.github/ISSUE_TEMPLATE/bug_report.md b/.github/ISSUE_TEMPLATE/bug_report.md
index df5bcbc15..9d042118c 100644
--- a/.github/ISSUE_TEMPLATE/bug_report.md
+++ b/.github/ISSUE_TEMPLATE/bug_report.md
@@ -2,7 +2,7 @@
name: SQL Parser Error
about: Create a report to help us improve
title: 'JSQLParser Version : RDBMS : failing feature description'
-labels: ''
+labels: 'Parser Error', 'Feature Request', 'Documentation', 'Java API', 'RDBMS support'
assignees: ''
---
@@ -12,7 +12,7 @@ assignees: ''
- Example: `WITH ROLLUP` can't be parsed
**SQL Example**
-- Simplyfied Query Exmple, focusing on the failing feature
+- Simplified Query Example, focusing on the failing feature
```sql
-- Replace with your ACTUAL example
select 1
@@ -23,6 +23,6 @@ from dual
- JSqlParser version
- Database (e. g. Oracle, MS SQL Server, H2, PostgreSQL, IBM DB2 )
-**Tipps**
-Please write in English and avoid Screenshots (as we can't copy paste content from it).
+**Tips**
+Please write in English and avoid Screenshots (as we can't copy and paste content from it).
[Try your example online with the latest JSQLParser](http://217.160.215.75:8080/jsqlformatter/demo.html) and share the link in the error report.
diff --git a/README.md b/README.md
index ebded4a70..7b5a8488f 100644
--- a/README.md
+++ b/README.md
@@ -50,12 +50,10 @@ To help JSqlParser's development you are encouraged to provide
**Please write in English, since it's the language most of the dev team knows.**
-Also I would like to know about needed examples or documentation stuff.
+Any requests for examples or any particular documentation will be most welcome.
## Extensions in the latest SNAPSHOT version 4.5
-- Add support for `... ALTER COLUMN ... DROP DEFAULT`
-
Additionally, we have fixed many errors and improved the code quality and the test coverage.
## Extensions of JSqlParser releases
@@ -64,6 +62,9 @@ Additionally, we have fixed many errors and improved the code quality and the te
* Modifications before GitHub's release tagging are listed in the [Older Releases](https://github.com/JSQLParser/JSqlParser/wiki/Older-Releases) page.
* UnsupportedStatement support instead of throwing Exceptions
* support for **RETURNING** clause of a **DELETE** statement
+* Add support for `... ALTER COLUMN ... DROP DEFAULT`
+* `INSERT` supports `SetOperations` (e. g. `INSERT INTO ... SELECT ... FROM ... UNION SELECT ... FROM ...`), those `SetOperations` are used both for `SELECT` and `VALUES` clauses (API change) in order to simplify the Grammar
+* `(WITH ... SELECT ...)` statements within brackets are now supported
## Building from the sources
@@ -80,7 +81,7 @@ gradle build
The project requires the following to build:
- Maven (or Gradle)
-- JDK 8 or later. The jar will target JDK 8, but the version of the maven-compiler-plugin that JsqlParser uses requires JDK 8+
+- JDK 8 or later. The JAR will target JDK 8, but the version of the maven-compiler-plugin that JSqlParser uses requires JDK 8+
This will produce the jsqlparser-VERSION.jar file in the `target/` directory (`build/libs/jsqlparser-VERSION.jar` in case of Gradle).
@@ -110,7 +111,7 @@ This is a valid piece of source code:
## Maven Repository
-JSQLParser is deployed at sonatypes open source maven repository.
+JSQLParser is deployed at Sonatype open source maven repository.
Starting from now I will deploy there. The first snapshot version there will be 0.8.5-SNAPSHOT.
To use it this is the repository configuration:
@@ -125,14 +126,14 @@ To use it this is the repository configuration:
```
-This repositories releases will be synched to maven central. Snapshots remain at sonatype.
+These repository releases will be synchronised to Maven Central. Snapshots remain at Sonatype.
And this is the dependency declaration in your pom:
```xml
com.github.jsqlparser
jsqlparser
- 4.2
+ 4.4
```
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 df99ba12a..4e47ec0e1 100644
--- a/src/main/java/net/sf/jsqlparser/statement/insert/Insert.java
+++ b/src/main/java/net/sf/jsqlparser/statement/insert/Insert.java
@@ -15,8 +15,11 @@
import java.util.Iterator;
import java.util.List;
import java.util.Optional;
+
import net.sf.jsqlparser.expression.Expression;
import net.sf.jsqlparser.expression.OracleHint;
+import net.sf.jsqlparser.expression.RowConstructor;
+import net.sf.jsqlparser.expression.operators.relational.ExpressionList;
import net.sf.jsqlparser.expression.operators.relational.ItemsList;
import net.sf.jsqlparser.schema.Column;
import net.sf.jsqlparser.schema.Table;
@@ -25,8 +28,10 @@
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.SelectBody;
+import net.sf.jsqlparser.statement.select.SetOperationList;
import net.sf.jsqlparser.statement.select.WithItem;
+import net.sf.jsqlparser.statement.values.ValuesStatement;
@SuppressWarnings({"PMD.CyclomaticComplexity"})
public class Insert implements Statement {
@@ -34,10 +39,7 @@ public class Insert implements Statement {
private Table table;
private OracleHint oracleHint = null;
private List columns;
- private ItemsList itemsList;
- private boolean useValues = true;
private Select select;
- private boolean useSelectBrackets = true;
private boolean useDuplicate = false;
private List duplicateUpdateColumns;
private List duplicateUpdateExpressionList;
@@ -95,20 +97,41 @@ public void setColumns(List list) {
*
* @return the values of the insert
*/
+ @Deprecated
public ItemsList getItemsList() {
- return itemsList;
+ if (select!=null) {
+ SelectBody selectBody = select.getSelectBody();
+ if (selectBody instanceof SetOperationList) {
+ SetOperationList setOperationList = (SetOperationList) selectBody;
+ List selects = setOperationList.getSelects();
+
+ if (selects.size() == 1) {
+ SelectBody selectBody1 = selects.get(0);
+ if (selectBody1 instanceof ValuesStatement) {
+ ValuesStatement valuesStatement = (ValuesStatement) selectBody1;
+ if (valuesStatement.getExpressions() instanceof ExpressionList) {
+ ExpressionList expressionList = (ExpressionList) valuesStatement.getExpressions();
+
+ if (expressionList.getExpressions().size() == 1 && expressionList.getExpressions().get(0) instanceof RowConstructor) {
+ RowConstructor rowConstructor = (RowConstructor) expressionList.getExpressions().get(0);
+ return rowConstructor.getExprList();
+ } else {
+ return expressionList;
+ }
+ } else {
+ return valuesStatement.getExpressions();
+ }
+ }
+ }
+ }
+ }
+ return null;
}
- public void setItemsList(ItemsList list) {
- itemsList = list;
- }
+ @Deprecated
public boolean isUseValues() {
- return useValues;
- }
-
- public void setUseValues(boolean useValues) {
- this.useValues = useValues;
+ return select!=null && select.getSelectBody() instanceof ValuesStatement;
}
public List getReturningExpressionList() {
@@ -127,12 +150,9 @@ public void setSelect(Select select) {
this.select = select;
}
+ @Deprecated
public boolean isUseSelectBrackets() {
- return useSelectBrackets;
- }
-
- public void setUseSelectBrackets(boolean useSelectBrackets) {
- this.useSelectBrackets = useSelectBrackets;
+ return false;
}
public boolean isUseDuplicate() {
@@ -235,28 +255,10 @@ public String toString() {
sql.append(PlainSelect.getStringList(columns, true, true)).append(" ");
}
- if (outputClause!=null) {
- outputClause.appendTo(sql);
+ if (select != null) {
+ sql.append(select);
}
- if (useValues) {
- sql.append("VALUES ");
- }
-
- if (itemsList != null) {
- sql.append(itemsList);
- } else {
- if (useSelectBrackets) {
- sql.append("(");
- }
- if (select != null) {
- sql.append(select);
- }
- if (useSelectBrackets) {
- sql.append(")");
- }
- }
-
if (useSet) {
sql.append("SET ");
for (int i = 0; i < getSetColumns().size(); i++) {
@@ -291,22 +293,12 @@ public Insert withWithItemsList(List withList) {
this.withItemsList = withList;
return this;
}
-
- public Insert withUseValues(boolean useValues) {
- this.setUseValues(useValues);
- return this;
- }
public Insert withSelect(Select select) {
this.setSelect(select);
return this;
}
- public Insert withUseSelectBrackets(boolean useSelectBrackets) {
- this.setUseSelectBrackets(useSelectBrackets);
- return this;
- }
-
public Insert withUseDuplicate(boolean useDuplicate) {
this.setUseDuplicate(useDuplicate);
return this;
@@ -367,11 +359,6 @@ public Insert withSetColumns(List columns) {
return this;
}
- public Insert withItemsList(ItemsList itemsList) {
- this.setItemsList(itemsList);
- return this;
- }
-
public Insert addColumns(Column... columns) {
List collection = Optional.ofNullable(getColumns()).orElseGet(ArrayList::new);
Collections.addAll(collection, columns);
diff --git a/src/main/java/net/sf/jsqlparser/statement/select/Select.java b/src/main/java/net/sf/jsqlparser/statement/select/Select.java
index 7886f44f7..67a002777 100644
--- a/src/main/java/net/sf/jsqlparser/statement/select/Select.java
+++ b/src/main/java/net/sf/jsqlparser/statement/select/Select.java
@@ -23,6 +23,8 @@ public class Select implements Statement {
private SelectBody selectBody;
private List withItemsList;
+ private boolean useWithBrackets = false;
+
@Override
public void accept(StatementVisitor statementVisitor) {
statementVisitor.visit(this);
@@ -41,11 +43,27 @@ public void setSelectBody(SelectBody body) {
selectBody = body;
}
+ public void setUsingWithBrackets(boolean useWithBrackets) {
+ this.useWithBrackets = useWithBrackets;
+ }
+
+ public Select withUsingWithBrackets(boolean useWithBrackets) {
+ this.useWithBrackets = useWithBrackets;
+ return this;
+ }
+
+ public boolean isUsingWithBrackets() {
+ return this.useWithBrackets;
+ }
+
@Override
@SuppressWarnings({"PMD.CyclomaticComplexity", "PMD.NPathComplexity"})
public String toString() {
StringBuilder retval = new StringBuilder();
if (withItemsList != null && !withItemsList.isEmpty()) {
+ if (useWithBrackets) {
+ retval.append("( ");
+ }
retval.append("WITH ");
for (Iterator iter = withItemsList.iterator(); iter.hasNext();) {
WithItem withItem = iter.next();
@@ -57,6 +75,9 @@ public String toString() {
}
}
retval.append(selectBody);
+ if (withItemsList != null && !withItemsList.isEmpty() && useWithBrackets) {
+ retval.append(" )");
+ }
return retval.toString();
}
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 78ac2c930..f68f059e2 100644
--- a/src/main/java/net/sf/jsqlparser/util/deparser/InsertDeParser.java
+++ b/src/main/java/net/sf/jsqlparser/util/deparser/InsertDeParser.java
@@ -77,17 +77,9 @@ public void deParse(Insert insert) {
buffer.append(")");
}
- if (insert.getOutputClause()!=null) {
- insert.getOutputClause().appendTo(buffer);
- }
-
- if (insert.getItemsList() != null) {
- insert.getItemsList().accept(this);
- }
-
if (insert.getSelect() != null) {
buffer.append(" ");
- if (insert.isUseSelectBrackets()) {
+ if (insert.getSelect().isUsingWithBrackets()) {
buffer.append("(");
}
if (insert.getSelect().getWithItemsList() != null) {
@@ -98,7 +90,7 @@ public void deParse(Insert insert) {
buffer.append(" ");
}
insert.getSelect().getSelectBody().accept(selectVisitor);
- if (insert.isUseSelectBrackets()) {
+ if (insert.getSelect().isUsingWithBrackets()) {
buffer.append(")");
}
}
diff --git a/src/main/java/net/sf/jsqlparser/util/deparser/StatementDeParser.java b/src/main/java/net/sf/jsqlparser/util/deparser/StatementDeParser.java
index 5dc82d3ff..5e904dd0b 100644
--- a/src/main/java/net/sf/jsqlparser/util/deparser/StatementDeParser.java
+++ b/src/main/java/net/sf/jsqlparser/util/deparser/StatementDeParser.java
@@ -143,6 +143,9 @@ public void visit(Select select) {
expressionDeParser.setBuffer(buffer);
selectDeParser.setExpressionVisitor(expressionDeParser);
if (select.getWithItemsList() != null && !select.getWithItemsList().isEmpty()) {
+ if (select.isUsingWithBrackets()) {
+ buffer.append("( ");
+ }
buffer.append("WITH ");
for (Iterator iter = select.getWithItemsList().iterator(); iter.hasNext();) {
WithItem withItem = iter.next();
@@ -154,6 +157,9 @@ public void visit(Select select) {
}
}
select.getSelectBody().accept(selectDeParser);
+ if (select.isUsingWithBrackets()) {
+ buffer.append(" )");
+ }
}
@Override
diff --git a/src/main/java/net/sf/jsqlparser/util/validation/feature/H2Version.java b/src/main/java/net/sf/jsqlparser/util/validation/feature/H2Version.java
index a5ff52606..9cd733acf 100644
--- a/src/main/java/net/sf/jsqlparser/util/validation/feature/H2Version.java
+++ b/src/main/java/net/sf/jsqlparser/util/validation/feature/H2Version.java
@@ -100,6 +100,7 @@ public enum H2Version implements Version {
// http://h2database.com/html/commands.html#insert
Feature.insert,
Feature.insertValues,
+ Feature.values,
Feature.insertFromSelect,
// http://h2database.com/html/commands.html#update
Feature.update,
@@ -136,7 +137,8 @@ public enum H2Version implements Version {
// http://www.h2database.com/html/commands.html#grant_role
Feature.grant,
// http://h2database.com/html/commands.html#commit
- Feature.commit));
+ Feature.commit
+ ));
private Set features;
private String versionString;
diff --git a/src/main/java/net/sf/jsqlparser/util/validation/feature/MariaDbVersion.java b/src/main/java/net/sf/jsqlparser/util/validation/feature/MariaDbVersion.java
index b241ffde5..6a1cba1a4 100644
--- a/src/main/java/net/sf/jsqlparser/util/validation/feature/MariaDbVersion.java
+++ b/src/main/java/net/sf/jsqlparser/util/validation/feature/MariaDbVersion.java
@@ -60,7 +60,7 @@ public enum MariaDbVersion implements Version {
Feature.withItem, Feature.withItemRecursive,
// https://mariadb.com/kb/en/insert/
- Feature.insert, Feature.insertValues,
+ Feature.insert, Feature.insertValues, Feature.values,
Feature.insertFromSelect, Feature.insertModifierPriority, Feature.insertModifierIgnore,
Feature.insertUseSet, Feature.insertUseDuplicateKeyUpdate, Feature.insertReturningExpressionList,
diff --git a/src/main/java/net/sf/jsqlparser/util/validation/feature/MySqlVersion.java b/src/main/java/net/sf/jsqlparser/util/validation/feature/MySqlVersion.java
index cf30655d4..c13abaa3e 100644
--- a/src/main/java/net/sf/jsqlparser/util/validation/feature/MySqlVersion.java
+++ b/src/main/java/net/sf/jsqlparser/util/validation/feature/MySqlVersion.java
@@ -54,6 +54,7 @@ public enum MySqlVersion implements Version {
// https://dev.mysql.com/doc/refman/8.0/en/insert.html
Feature.insert,
Feature.insertValues,
+ Feature.values,
Feature.insertFromSelect, Feature.insertUseSet, Feature.insertModifierPriority,
Feature.insertModifierIgnore, Feature.insertUseDuplicateKeyUpdate,
diff --git a/src/main/java/net/sf/jsqlparser/util/validation/feature/OracleVersion.java b/src/main/java/net/sf/jsqlparser/util/validation/feature/OracleVersion.java
index 62fe19bb6..3c970bf65 100644
--- a/src/main/java/net/sf/jsqlparser/util/validation/feature/OracleVersion.java
+++ b/src/main/java/net/sf/jsqlparser/util/validation/feature/OracleVersion.java
@@ -88,6 +88,7 @@ public enum OracleVersion implements Version {
// https://docs.oracle.com/en/database/oracle/oracle-database/19/sqlrf/INSERT.html
Feature.insert,
Feature.insertValues,
+ Feature.values,
// https://docs.oracle.com/en/database/oracle/oracle-database/19/sqlrf/INSERT.html
// see "single_table_insert"
Feature.insertFromSelect,
diff --git a/src/main/java/net/sf/jsqlparser/util/validation/feature/PostgresqlVersion.java b/src/main/java/net/sf/jsqlparser/util/validation/feature/PostgresqlVersion.java
index 3f439bd41..32e62cca7 100644
--- a/src/main/java/net/sf/jsqlparser/util/validation/feature/PostgresqlVersion.java
+++ b/src/main/java/net/sf/jsqlparser/util/validation/feature/PostgresqlVersion.java
@@ -109,6 +109,7 @@ public enum PostgresqlVersion implements Version {
// https://www.postgresql.org/docs/current/sql-insert.html
Feature.insert,
Feature.insertValues,
+ Feature.values,
Feature.insertFromSelect,
Feature.insertReturningAll, Feature.insertReturningExpressionList,
// https://www.postgresql.org/docs/current/sql-update.html
diff --git a/src/main/java/net/sf/jsqlparser/util/validation/feature/SQLVersion.java b/src/main/java/net/sf/jsqlparser/util/validation/feature/SQLVersion.java
index b6eda6455..3b8266c83 100644
--- a/src/main/java/net/sf/jsqlparser/util/validation/feature/SQLVersion.java
+++ b/src/main/java/net/sf/jsqlparser/util/validation/feature/SQLVersion.java
@@ -29,10 +29,13 @@ public enum SQLVersion implements Version {
Feature.jdbcParameter,
Feature.jdbcNamedParameter,
// common features
+ Feature.setOperation,
Feature.select,
Feature.selectGroupBy, Feature.function,
Feature.insert,
+ Feature.insertFromSelect,
Feature.insertValues,
+ Feature.values,
Feature.update,
Feature.delete,
Feature.truncate,
diff --git a/src/main/jjtree/net/sf/jsqlparser/parser/JSqlParserCC.jjt b/src/main/jjtree/net/sf/jsqlparser/parser/JSqlParserCC.jjt
index 15cc46c09..4f5c2bff0 100644
--- a/src/main/jjtree/net/sf/jsqlparser/parser/JSqlParserCC.jjt
+++ b/src/main/jjtree/net/sf/jsqlparser/parser/JSqlParserCC.jjt
@@ -544,8 +544,29 @@ Statement SingleStatement() :
{
try {
(
+ LOOKAHEAD(2) (
+ "(" with=WithList()
+ (
+ stm = Select( with ) { ( (Select) stm).setUsingWithBrackets(true); }
+
+ /* @todo: unsure, if we need to implement those
+ since DMLs in brackets do not really make any sense
+ |
+ stm = Insert( with ) { ( (Insert) stm).setUsingWithBrackets(true); }
+ |
+ stm = Update( with ) { ( (Update) stm).setUsingWithBrackets(true); }
+ |
+ stm = Delete( with ) { ( (Delete) stm).setUsingWithBrackets(true); }
+ |
+ stm = Merge( with ) { ( (Merge) stm).setUsingWithBrackets(true); }
+
+ */
+ )
+ ")"
+ )
+ |
(
- [ with=WithList() { } ]
+ [ with=WithList() ]
(
stm = Select( with )
|
@@ -558,86 +579,86 @@ Statement SingleStatement() :
stm = Merge( with)
)
)
- |
- stm = Upsert()
- |
- LOOKAHEAD(3)
- stm = Replace()
- |
- LOOKAHEAD(2)
- stm = AlterTable()
- |
- LOOKAHEAD(2)
- stm = AlterSession()
- |
- LOOKAHEAD(CreateFunctionStatement())
- stm = CreateFunctionStatement()
- |
- LOOKAHEAD(CreateIndex())
- stm = CreateIndex()
- |
- LOOKAHEAD(CreateSchema())
- stm = CreateSchema()
- |
- LOOKAHEAD(CreateSequence())
- stm = CreateSequence()
- |
- LOOKAHEAD(CreateSynonym())
- stm = CreateSynonym()
- |
- LOOKAHEAD(CreateTable())
- stm = CreateTable()
- |
- LOOKAHEAD(CreateView())
- stm = CreateView()
- |
- LOOKAHEAD(AlterView())
- stm = AlterView()
- |
- LOOKAHEAD(AlterSequence())
- stm = AlterSequence()
- |
- stm = Drop()
- |
- stm = Truncate()
- |
- stm = Execute()
- |
- stm = Set()
- |
- stm = RenameTableStatement()
- |
- stm = Reset()
- |
- LOOKAHEAD(ShowColumns())
- stm = ShowColumns()
- |
- LOOKAHEAD(ShowTables())
- stm = ShowTables()
- |
- stm = Show()
- |
- stm = Use()
- |
- stm = SavepointStatement()
- |
- stm = RollbackStatement()
- |
- stm = Commit()
- |
- stm = Comment()
- |
- stm = Describe()
- |
- stm = Explain()
- |
- stm = Declare()
- |
- stm = Grant()
- |
- stm = PurgeStatement()
- |
- stm = AlterSystemStatement()
+ |
+ stm = Upsert()
+ |
+ LOOKAHEAD(3)
+ stm = Replace()
+ |
+ LOOKAHEAD(2)
+ stm = AlterTable()
+ |
+ LOOKAHEAD(2)
+ stm = AlterSession()
+ |
+ LOOKAHEAD(CreateFunctionStatement())
+ stm = CreateFunctionStatement()
+ |
+ LOOKAHEAD(CreateIndex())
+ stm = CreateIndex()
+ |
+ LOOKAHEAD(CreateSchema())
+ stm = CreateSchema()
+ |
+ LOOKAHEAD(CreateSequence())
+ stm = CreateSequence()
+ |
+ LOOKAHEAD(CreateSynonym())
+ stm = CreateSynonym()
+ |
+ LOOKAHEAD(CreateTable())
+ stm = CreateTable()
+ |
+ LOOKAHEAD(CreateView())
+ stm = CreateView()
+ |
+ LOOKAHEAD(AlterView())
+ stm = AlterView()
+ |
+ LOOKAHEAD(AlterSequence())
+ stm = AlterSequence()
+ |
+ stm = Drop()
+ |
+ stm = Truncate()
+ |
+ stm = Execute()
+ |
+ stm = Set()
+ |
+ stm = RenameTableStatement()
+ |
+ stm = Reset()
+ |
+ LOOKAHEAD(ShowColumns())
+ stm = ShowColumns()
+ |
+ LOOKAHEAD(ShowTables())
+ stm = ShowTables()
+ |
+ stm = Show()
+ |
+ stm = Use()
+ |
+ stm = SavepointStatement()
+ |
+ stm = RollbackStatement()
+ |
+ stm = Commit()
+ |
+ stm = Comment()
+ |
+ stm = Describe()
+ |
+ stm = Explain()
+ |
+ stm = Declare()
+ |
+ stm = Grant()
+ |
+ stm = PurgeStatement()
+ |
+ stm = AlterSystemStatement()
)
{ return stm; }
} catch (ParseException e) {
@@ -1136,7 +1157,7 @@ ShowStatement Show(): {
ValuesStatement Values(): {
ItemsList itemsList;
} {
-
+ ( | )
itemsList = SimpleExpressionList(false)
@@ -1317,14 +1338,9 @@ Insert Insert( List with ):
Table table = null;
Column tableColumn = null;
List columns = new ArrayList();
- List primaryExpList = new ArrayList();
- ItemsList itemsList = null;
Expression exp = null;
- MultiExpressionList multiExpr = null;
- List returning = null;
+ List returning = null;
Select select = null;
- boolean useValues = true;
- boolean useSelectBrackets = false;
boolean useDuplicate = false;
List duplicateUpdateColumns = null;
List duplicateUpdateExpressionList = null;
@@ -1354,38 +1370,8 @@ Insert Insert( List with ):
[ outputClause = OutputClause() { insert.setOutputClause(outputClause); } ]
(
- LOOKAHEAD(2) [ | ] "(" exp=SimpleExpression() { primaryExpList.add(exp); }
- ("," exp=SimpleExpression() { primaryExpList.add(exp); } )* ")" { itemsList = new ExpressionList(primaryExpList); }
- ("," "(" exp=SimpleExpression() {
- if (multiExpr==null) {
- multiExpr=new MultiExpressionList();
- multiExpr.addExpressionList((ExpressionList)itemsList);
- itemsList = multiExpr;
- }
- primaryExpList = new ArrayList();
- primaryExpList.add(exp); }
- ("," exp=SimpleExpression() { primaryExpList.add(exp); } )* ")" { multiExpr.addExpressionList(primaryExpList); } )*
-
- |
-
(
- LOOKAHEAD(2) "(" { useSelectBrackets = true; }
- { insert.setUseValues(false); }
- select = SelectWithWithItems( )
- ")"
- |
- { insert.setUseValues(false); }
- select = SelectWithWithItems( )
- )
-
- |
-
-
- (
- {
- useSet = true;
- insert.setUseValues(false);
- }
+ { useSet = true; }
tableColumn=Column() "=" exp=SimpleExpression()
{
setColumns = new ArrayList();
@@ -1397,6 +1383,8 @@ Insert Insert( List with ):
{ setColumns.add(tableColumn);
setExpressionList.add(exp); } )*
)
+ |
+ select = SelectWithWithItems( )
)
[
@@ -1420,8 +1408,6 @@ Insert Insert( List with ):
insert.setColumns(columns);
}
return insert.withWithItemsList(with)
- .withItemsList(itemsList)
- .withUseSelectBrackets(useSelectBrackets)
.withSelect(select)
.withTable(table)
.withUseDuplicate(useDuplicate)
@@ -1750,7 +1736,7 @@ String RelObjectName() :
{ Token tk = null; String result = null; }
{
(result = RelObjectNameWithoutValue()
- | tk= | tk= | tk= | tk= | tk= | tk= | tk=
+ | tk= | tk= | tk= | tk= | tk= | tk= | tk=
| tk= | tk= | tk= )
{
@@ -1835,7 +1821,14 @@ Select SelectWithWithItems( ):
List with = null;
}
{
- [ with=WithList() { } ] select = Select( with )
+ LOOKAHEAD(2) (
+ "(" with=WithList() select = Select( with ) ")" { return select.withUsingWithBrackets(true); }
+ )
+ |
+ (
+ [ with=WithList() ] select = Select( with )
+ )
+
{
return select;
}
diff --git a/src/test/java/net/sf/jsqlparser/statement/insert/InsertTest.java b/src/test/java/net/sf/jsqlparser/statement/insert/InsertTest.java
index e131c9995..9315230b8 100644
--- a/src/test/java/net/sf/jsqlparser/statement/insert/InsertTest.java
+++ b/src/test/java/net/sf/jsqlparser/statement/insert/InsertTest.java
@@ -9,8 +9,6 @@
*/
package net.sf.jsqlparser.statement.insert;
-import java.io.StringReader;
-import java.util.Arrays;
import net.sf.jsqlparser.JSQLParserException;
import net.sf.jsqlparser.expression.DoubleValue;
import net.sf.jsqlparser.expression.JdbcParameter;
@@ -24,6 +22,13 @@
import net.sf.jsqlparser.statement.select.AllColumns;
import net.sf.jsqlparser.statement.select.PlainSelect;
import net.sf.jsqlparser.statement.select.Select;
+import net.sf.jsqlparser.statement.values.ValuesStatement;
+import org.junit.jupiter.api.Disabled;
+import org.junit.jupiter.api.Test;
+
+import java.io.StringReader;
+import java.util.Arrays;
+
import static net.sf.jsqlparser.test.TestUtils.assertDeparse;
import static net.sf.jsqlparser.test.TestUtils.assertOracleHintExists;
import static net.sf.jsqlparser.test.TestUtils.assertSqlCanBeParsedAndDeparsed;
@@ -33,8 +38,6 @@
import static org.junit.jupiter.api.Assertions.assertNull;
import static org.junit.jupiter.api.Assertions.assertTrue;
import static org.junit.jupiter.api.Assertions.fail;
-import org.junit.jupiter.api.Disabled;
-import org.junit.jupiter.api.Test;
public class InsertTest {
@@ -56,13 +59,21 @@ public void testRegularInsert() throws JSQLParserException {
getValue());
assertEquals(234, ((LongValue) ((ExpressionList) insert.getItemsList()).getExpressions().
get(2)).getValue());
- assertEquals(statement, "" + insert);
+ assertEquals(statement, insert.toString());
- assertDeparse(new Insert().withTable(new Table("mytable"))
- .addColumns(Arrays.asList(new Column("col1"), new Column("col2"), new Column("col3")))
- .withItemsList(new ExpressionList(new JdbcParameter(), new StringValue("sadfsd"),
- new LongValue().withValue(234))),
- statement);
+ ExpressionList expressionList =new ExpressionList(
+ new JdbcParameter()
+ , new StringValue("sadfsd")
+ , new LongValue().withValue(234)
+ );
+
+ Select select = new Select().withSelectBody(new ValuesStatement().withExpressions(expressionList));
+
+ Insert insert2 = new Insert().withTable(new Table("mytable"))
+ .withColumns(Arrays.asList(new Column("col1"), new Column("col2"), new Column("col3")))
+ .withSelect(select);
+
+ assertDeparse(insert2, statement);
statement = "INSERT INTO myschema.mytable VALUES (?, ?, 2.3)";
insert = (Insert) parserManager.parse(new StringReader(statement));
@@ -82,9 +93,9 @@ public void testInsertWithKeywordValue() throws JSQLParserException {
assertEquals("mytable", insert.getTable().getName());
assertEquals(1, insert.getColumns().size());
assertEquals("col1", insert.getColumns().get(0).getColumnName());
- assertEquals("val1",
- ((StringValue) ((ExpressionList) insert.getItemsList()).getExpressions().get(0)).
- getValue());
+ assertEquals("('val1')",
+ (((ExpressionList) insert.getItemsList()).getExpressions().get(0)).
+ toString());
assertEquals("INSERT INTO mytable (col1) VALUES ('val1')", insert.toString());
}
@@ -103,11 +114,11 @@ public void testInsertFromSelect() throws JSQLParserException {
assertEquals("mytable2",
((Table) ((PlainSelect) insert.getSelect().getSelectBody()).getFromItem()).getName());
- // toString uses brakets
+ // toString uses brackets
String statementToString = "INSERT INTO mytable (col1, col2, col3) SELECT * FROM mytable2";
assertEquals(statementToString, "" + insert);
- assertDeparse(new Insert().withUseValues(false).withUseSelectBrackets(false).withTable(new Table("mytable"))
+ assertDeparse(new Insert().withTable(new Table("mytable"))
.addColumns(new Column("col1"), new Column("col2"), new Column("col3"))
.withSelect(new Select().withSelectBody(
new PlainSelect().addSelectItems(new AllColumns()).withFromItem(new Table("mytable2")))),
@@ -135,7 +146,6 @@ public void testInsertValuesWithDuplicateElimination() throws JSQLParserExceptio
Insert insert = (Insert) parserManager.parse(new StringReader(statement));
assertEquals("TEST", insert.getTable().getName());
assertEquals(2, insert.getColumns().size());
- assertTrue(insert.isUseValues());
assertEquals("ID", insert.getColumns().get(0).getColumnName());
assertEquals("COUNTER", insert.getColumns().get(1).getColumnName());
assertEquals(2, ((ExpressionList) insert.getItemsList()).getExpressions().size());
@@ -175,15 +185,24 @@ public void testInsertFromSetWithDuplicateElimination() throws JSQLParserExcepti
public void testInsertMultiRowValue() throws JSQLParserException {
String statement = "INSERT INTO mytable (col1, col2) VALUES (a, b), (d, e)";
assertSqlCanBeParsedAndDeparsed(statement);
- assertDeparse(new Insert().withTable(new Table("mytable"))
+
+ MultiExpressionList multiExpressionList = new MultiExpressionList()
+ .addExpressionLists( new ExpressionList().addExpressions(new Column("a")).addExpressions(new Column("b")))
+ .addExpressionLists( new ExpressionList().addExpressions(new Column("d")).addExpressions(new Column("e")));
+
+ Select select = new Select().withSelectBody(new ValuesStatement().withExpressions(multiExpressionList));
+
+ Insert insert = new Insert().withTable(new Table("mytable"))
.withColumns(Arrays.asList(new Column("col1"), new Column("col2")))
- .withItemsList(new MultiExpressionList().addExpressionLists(
- new ExpressionList().addExpressions(Arrays.asList(new Column("a"), new Column("b"))),
- new ExpressionList(new Column("d"), new Column("e")))),
- statement);
+ .withSelect(select);
+
+ assertDeparse(insert, statement);
}
@Test
+ @Disabled
+ //@todo: Clarify, if and why this test is supposed to fail and if it is the Parser's job to decide
+ //What if col1 and col2 are Array Columns?
public void testInsertMultiRowValueDifferent() throws JSQLParserException {
try {
assertSqlCanBeParsedAndDeparsed("INSERT INTO mytable (col1, col2) VALUES (a, b), (d, e, c)");
@@ -234,8 +253,8 @@ public void testInsertSelect() throws JSQLParserException {
@Test
public void testInsertWithSelect() throws JSQLParserException {
- assertSqlCanBeParsedAndDeparsed("INSERT INTO mytable (mycolumn) WITH a AS (SELECT mycolumn FROM mytable) SELECT mycolumn FROM a");
- assertSqlCanBeParsedAndDeparsed("INSERT INTO mytable (mycolumn) (WITH a AS (SELECT mycolumn FROM mytable) SELECT mycolumn FROM a)");
+ assertSqlCanBeParsedAndDeparsed("INSERT INTO mytable (mycolumn) WITH a AS (SELECT mycolumn FROM mytable) SELECT mycolumn FROM a", true);
+ assertSqlCanBeParsedAndDeparsed("INSERT INTO mytable (mycolumn) (WITH a AS (SELECT mycolumn FROM mytable) SELECT mycolumn FROM a)", true);
}
@Test
@@ -387,6 +406,46 @@ public void testKeywordDefaultIssue1470() throws JSQLParserException {
assertSqlCanBeParsedAndDeparsed("INSERT INTO mytable (col1, col2, col3) VALUES (?, 'sadfsd', default)");
}
+ @Test
+ public void testInsertUnionSelectIssue1491() throws JSQLParserException {
+ assertSqlCanBeParsedAndDeparsed(
+ "insert into table1 (tf1,tf2,tf2)\n" +
+ "select sf1,sf2,sf3 from s1\n" +
+ "union\n" +
+ "select rf1,rf2,rf2 from r1\n"
+ , true
+ );
+
+ assertSqlCanBeParsedAndDeparsed(
+ "insert into table1 (tf1,tf2,tf2)\n" +
+ "( select sf1,sf2,sf3 from s1\n" +
+ "union\n" +
+ "select rf1,rf2,rf2 from r1\n)"
+ , true
+ );
+
+ assertSqlCanBeParsedAndDeparsed(
+ "insert into table1 (tf1,tf2,tf2)\n" +
+ "(select sf1,sf2,sf3 from s1)" +
+ "union " +
+ "(select rf1,rf2,rf2 from r1)"
+ , true
+ );
+
+ assertSqlCanBeParsedAndDeparsed(
+ "insert into table1 (tf1,tf2,tf2)\n" +
+ "((select sf1,sf2,sf3 from s1)" +
+ "union " +
+ "(select rf1,rf2,rf2 from r1))"
+ , true
+ );
+
+ assertSqlCanBeParsedAndDeparsed(
+ "(with a as (select * from dual) select * from a)"
+ , true
+ );
+ }
+
@Test
public void testInsertOutputClause() throws JSQLParserException {
assertSqlCanBeParsedAndDeparsed(
diff --git a/src/test/java/net/sf/jsqlparser/util/validation/validator/InsertValidatorTest.java b/src/test/java/net/sf/jsqlparser/util/validation/validator/InsertValidatorTest.java
index d9b74658e..f5fe80f79 100644
--- a/src/test/java/net/sf/jsqlparser/util/validation/validator/InsertValidatorTest.java
+++ b/src/test/java/net/sf/jsqlparser/util/validation/validator/InsertValidatorTest.java
@@ -28,8 +28,13 @@ public void testValidationInsert() throws JSQLParserException {
@Test
public void testValidationInsertNotAllowed() throws JSQLParserException {
String sql = "INSERT INTO tab1 (a, b, c) VALUES (5, 'val', ?)";
- validateNotAllowed(sql, 1, 1, FeaturesAllowed.SELECT.copy().add(FeaturesAllowed.JDBC), Feature.insert,
- Feature.insertValues);
+ validateNotAllowed(sql, 1, 1, FeaturesAllowed.SELECT.copy().add(FeaturesAllowed.JDBC)
+ , Feature.insertValues
+ , Feature.setOperation
+ , Feature.insertFromSelect
+ , Feature.values
+ , Feature.insert
+ );
}
@Test