Skip to content

Commit b5672c5

Browse files
INSERT with SetOperations (#1531)
* INSERT with SetOperations Simplify the INSERT production Use SetOperations for Select and Values Better Bracket handling for WITH ... SELECT ... Fixes #1491 * INSERT with SetOperations Appease Codazy/PMD * INSERT with SetOperations Appease Codazy/PMD * Update Readme List the changes Minor rephrases Correct the Maven Artifact Example * Fix the two test cases (missing white space) * Remove unused import
1 parent e8f0750 commit b5672c5

File tree

15 files changed

+296
-224
lines changed

15 files changed

+296
-224
lines changed

.github/ISSUE_TEMPLATE/bug_report.md

Lines changed: 4 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -2,7 +2,7 @@
22
name: SQL Parser Error
33
about: Create a report to help us improve
44
title: 'JSQLParser Version : RDBMS : failing feature description'
5-
labels: ''
5+
labels: 'Parser Error', 'Feature Request', 'Documentation', 'Java API', 'RDBMS support'
66
assignees: ''
77

88
---
@@ -12,7 +12,7 @@ assignees: ''
1212
- Example: `WITH ROLLUP` can't be parsed
1313

1414
**SQL Example**
15-
- Simplyfied Query Exmple, focusing on the failing feature
15+
- Simplified Query Example, focusing on the failing feature
1616
```sql
1717
-- Replace with your ACTUAL example
1818
select 1
@@ -23,6 +23,6 @@ from dual
2323
- JSqlParser version
2424
- Database (e. g. Oracle, MS SQL Server, H2, PostgreSQL, IBM DB2 )
2525

26-
**Tipps**
27-
Please write in English and avoid Screenshots (as we can't copy paste content from it).
26+
**Tips**
27+
Please write in English and avoid Screenshots (as we can't copy and paste content from it).
2828
[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.

README.md

Lines changed: 8 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -50,12 +50,10 @@ To help JSqlParser's development you are encouraged to provide
5050

5151
**Please write in English, since it's the language most of the dev team knows.**
5252

53-
Also I would like to know about needed examples or documentation stuff.
53+
Any requests for examples or any particular documentation will be most welcome.
5454

5555
## Extensions in the latest SNAPSHOT version 4.5
5656

57-
- Add support for `... ALTER COLUMN ... DROP DEFAULT`
58-
5957
Additionally, we have fixed many errors and improved the code quality and the test coverage.
6058

6159
## Extensions of JSqlParser releases
@@ -64,6 +62,9 @@ Additionally, we have fixed many errors and improved the code quality and the te
6462
* Modifications before GitHub's release tagging are listed in the [Older Releases](https://github.com/JSQLParser/JSqlParser/wiki/Older-Releases) page.
6563
* UnsupportedStatement support instead of throwing Exceptions
6664
* support for **RETURNING** clause of a **DELETE** statement
65+
* Add support for `... ALTER COLUMN ... DROP DEFAULT`
66+
* `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
67+
* `(WITH ... SELECT ...)` statements within brackets are now supported
6768

6869

6970
## Building from the sources
@@ -80,7 +81,7 @@ gradle build
8081

8182
The project requires the following to build:
8283
- Maven (or Gradle)
83-
- JDK 8 or later. The jar will target JDK 8, but the version of the maven-compiler-plugin that JsqlParser uses requires JDK 8+
84+
- JDK 8 or later. The JAR will target JDK 8, but the version of the maven-compiler-plugin that JSqlParser uses requires JDK 8+
8485

8586
This will produce the jsqlparser-VERSION.jar file in the `target/` directory (`build/libs/jsqlparser-VERSION.jar` in case of Gradle).
8687

@@ -110,7 +111,7 @@ This is a valid piece of source code:
110111

111112
## Maven Repository
112113

113-
JSQLParser is deployed at sonatypes open source maven repository.
114+
JSQLParser is deployed at Sonatype open source maven repository.
114115
Starting from now I will deploy there. The first snapshot version there will be 0.8.5-SNAPSHOT.
115116
To use it this is the repository configuration:
116117

@@ -125,14 +126,14 @@ To use it this is the repository configuration:
125126
</repository>
126127
</repositories>
127128
```
128-
This repositories releases will be synched to maven central. Snapshots remain at sonatype.
129+
These repository releases will be synchronised to Maven Central. Snapshots remain at Sonatype.
129130

130131
And this is the dependency declaration in your pom:
131132
```xml
132133
<dependency>
133134
<groupId>com.github.jsqlparser</groupId>
134135
<artifactId>jsqlparser</artifactId>
135-
<version>4.2</version>
136+
<version>4.4</version>
136137
</dependency>
137138
```
138139

src/main/java/net/sf/jsqlparser/statement/insert/Insert.java

Lines changed: 40 additions & 53 deletions
Original file line numberDiff line numberDiff line change
@@ -15,8 +15,11 @@
1515
import java.util.Iterator;
1616
import java.util.List;
1717
import java.util.Optional;
18+
1819
import net.sf.jsqlparser.expression.Expression;
1920
import net.sf.jsqlparser.expression.OracleHint;
21+
import net.sf.jsqlparser.expression.RowConstructor;
22+
import net.sf.jsqlparser.expression.operators.relational.ExpressionList;
2023
import net.sf.jsqlparser.expression.operators.relational.ItemsList;
2124
import net.sf.jsqlparser.schema.Column;
2225
import net.sf.jsqlparser.schema.Table;
@@ -25,19 +28,18 @@
2528
import net.sf.jsqlparser.statement.StatementVisitor;
2629
import net.sf.jsqlparser.statement.select.PlainSelect;
2730
import net.sf.jsqlparser.statement.select.Select;
28-
import net.sf.jsqlparser.statement.select.SelectItem;
31+
import net.sf.jsqlparser.statement.select.SelectBody;
32+
import net.sf.jsqlparser.statement.select.SetOperationList;
2933
import net.sf.jsqlparser.statement.select.WithItem;
34+
import net.sf.jsqlparser.statement.values.ValuesStatement;
3035

3136
@SuppressWarnings({"PMD.CyclomaticComplexity"})
3237
public class Insert implements Statement {
3338

3439
private Table table;
3540
private OracleHint oracleHint = null;
3641
private List<Column> columns;
37-
private ItemsList itemsList;
38-
private boolean useValues = true;
3942
private Select select;
40-
private boolean useSelectBrackets = true;
4143
private boolean useDuplicate = false;
4244
private List<Column> duplicateUpdateColumns;
4345
private List<Expression> duplicateUpdateExpressionList;
@@ -95,20 +97,41 @@ public void setColumns(List<Column> list) {
9597
*
9698
* @return the values of the insert
9799
*/
100+
@Deprecated
98101
public ItemsList getItemsList() {
99-
return itemsList;
102+
if (select!=null) {
103+
SelectBody selectBody = select.getSelectBody();
104+
if (selectBody instanceof SetOperationList) {
105+
SetOperationList setOperationList = (SetOperationList) selectBody;
106+
List<SelectBody> selects = setOperationList.getSelects();
107+
108+
if (selects.size() == 1) {
109+
SelectBody selectBody1 = selects.get(0);
110+
if (selectBody1 instanceof ValuesStatement) {
111+
ValuesStatement valuesStatement = (ValuesStatement) selectBody1;
112+
if (valuesStatement.getExpressions() instanceof ExpressionList) {
113+
ExpressionList expressionList = (ExpressionList) valuesStatement.getExpressions();
114+
115+
if (expressionList.getExpressions().size() == 1 && expressionList.getExpressions().get(0) instanceof RowConstructor) {
116+
RowConstructor rowConstructor = (RowConstructor) expressionList.getExpressions().get(0);
117+
return rowConstructor.getExprList();
118+
} else {
119+
return expressionList;
120+
}
121+
} else {
122+
return valuesStatement.getExpressions();
123+
}
124+
}
125+
}
126+
}
127+
}
128+
return null;
100129
}
101130

102-
public void setItemsList(ItemsList list) {
103-
itemsList = list;
104-
}
105131

132+
@Deprecated
106133
public boolean isUseValues() {
107-
return useValues;
108-
}
109-
110-
public void setUseValues(boolean useValues) {
111-
this.useValues = useValues;
134+
return select!=null && select.getSelectBody() instanceof ValuesStatement;
112135
}
113136

114137
public List<SelectItem> getReturningExpressionList() {
@@ -127,12 +150,9 @@ public void setSelect(Select select) {
127150
this.select = select;
128151
}
129152

153+
@Deprecated
130154
public boolean isUseSelectBrackets() {
131-
return useSelectBrackets;
132-
}
133-
134-
public void setUseSelectBrackets(boolean useSelectBrackets) {
135-
this.useSelectBrackets = useSelectBrackets;
155+
return false;
136156
}
137157

138158
public boolean isUseDuplicate() {
@@ -235,28 +255,10 @@ public String toString() {
235255
sql.append(PlainSelect.getStringList(columns, true, true)).append(" ");
236256
}
237257

238-
if (outputClause!=null) {
239-
outputClause.appendTo(sql);
258+
if (select != null) {
259+
sql.append(select);
240260
}
241261

242-
if (useValues) {
243-
sql.append("VALUES ");
244-
}
245-
246-
if (itemsList != null) {
247-
sql.append(itemsList);
248-
} else {
249-
if (useSelectBrackets) {
250-
sql.append("(");
251-
}
252-
if (select != null) {
253-
sql.append(select);
254-
}
255-
if (useSelectBrackets) {
256-
sql.append(")");
257-
}
258-
}
259-
260262
if (useSet) {
261263
sql.append("SET ");
262264
for (int i = 0; i < getSetColumns().size(); i++) {
@@ -291,22 +293,12 @@ public Insert withWithItemsList(List<WithItem> withList) {
291293
this.withItemsList = withList;
292294
return this;
293295
}
294-
295-
public Insert withUseValues(boolean useValues) {
296-
this.setUseValues(useValues);
297-
return this;
298-
}
299296

300297
public Insert withSelect(Select select) {
301298
this.setSelect(select);
302299
return this;
303300
}
304301

305-
public Insert withUseSelectBrackets(boolean useSelectBrackets) {
306-
this.setUseSelectBrackets(useSelectBrackets);
307-
return this;
308-
}
309-
310302
public Insert withUseDuplicate(boolean useDuplicate) {
311303
this.setUseDuplicate(useDuplicate);
312304
return this;
@@ -367,11 +359,6 @@ public Insert withSetColumns(List<Column> columns) {
367359
return this;
368360
}
369361

370-
public Insert withItemsList(ItemsList itemsList) {
371-
this.setItemsList(itemsList);
372-
return this;
373-
}
374-
375362
public Insert addColumns(Column... columns) {
376363
List<Column> collection = Optional.ofNullable(getColumns()).orElseGet(ArrayList::new);
377364
Collections.addAll(collection, columns);

src/main/java/net/sf/jsqlparser/statement/select/Select.java

Lines changed: 21 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -23,6 +23,8 @@ public class Select implements Statement {
2323
private SelectBody selectBody;
2424
private List<WithItem> withItemsList;
2525

26+
private boolean useWithBrackets = false;
27+
2628
@Override
2729
public void accept(StatementVisitor statementVisitor) {
2830
statementVisitor.visit(this);
@@ -41,11 +43,27 @@ public void setSelectBody(SelectBody body) {
4143
selectBody = body;
4244
}
4345

46+
public void setUsingWithBrackets(boolean useWithBrackets) {
47+
this.useWithBrackets = useWithBrackets;
48+
}
49+
50+
public Select withUsingWithBrackets(boolean useWithBrackets) {
51+
this.useWithBrackets = useWithBrackets;
52+
return this;
53+
}
54+
55+
public boolean isUsingWithBrackets() {
56+
return this.useWithBrackets;
57+
}
58+
4459
@Override
4560
@SuppressWarnings({"PMD.CyclomaticComplexity", "PMD.NPathComplexity"})
4661
public String toString() {
4762
StringBuilder retval = new StringBuilder();
4863
if (withItemsList != null && !withItemsList.isEmpty()) {
64+
if (useWithBrackets) {
65+
retval.append("( ");
66+
}
4967
retval.append("WITH ");
5068
for (Iterator<WithItem> iter = withItemsList.iterator(); iter.hasNext();) {
5169
WithItem withItem = iter.next();
@@ -57,6 +75,9 @@ public String toString() {
5775
}
5876
}
5977
retval.append(selectBody);
78+
if (withItemsList != null && !withItemsList.isEmpty() && useWithBrackets) {
79+
retval.append(" )");
80+
}
6081
return retval.toString();
6182
}
6283

src/main/java/net/sf/jsqlparser/util/deparser/InsertDeParser.java

Lines changed: 2 additions & 10 deletions
Original file line numberDiff line numberDiff line change
@@ -77,17 +77,9 @@ public void deParse(Insert insert) {
7777
buffer.append(")");
7878
}
7979

80-
if (insert.getOutputClause()!=null) {
81-
insert.getOutputClause().appendTo(buffer);
82-
}
83-
84-
if (insert.getItemsList() != null) {
85-
insert.getItemsList().accept(this);
86-
}
87-
8880
if (insert.getSelect() != null) {
8981
buffer.append(" ");
90-
if (insert.isUseSelectBrackets()) {
82+
if (insert.getSelect().isUsingWithBrackets()) {
9183
buffer.append("(");
9284
}
9385
if (insert.getSelect().getWithItemsList() != null) {
@@ -98,7 +90,7 @@ public void deParse(Insert insert) {
9890
buffer.append(" ");
9991
}
10092
insert.getSelect().getSelectBody().accept(selectVisitor);
101-
if (insert.isUseSelectBrackets()) {
93+
if (insert.getSelect().isUsingWithBrackets()) {
10294
buffer.append(")");
10395
}
10496
}

src/main/java/net/sf/jsqlparser/util/deparser/StatementDeParser.java

Lines changed: 6 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -143,6 +143,9 @@ public void visit(Select select) {
143143
expressionDeParser.setBuffer(buffer);
144144
selectDeParser.setExpressionVisitor(expressionDeParser);
145145
if (select.getWithItemsList() != null && !select.getWithItemsList().isEmpty()) {
146+
if (select.isUsingWithBrackets()) {
147+
buffer.append("( ");
148+
}
146149
buffer.append("WITH ");
147150
for (Iterator<WithItem> iter = select.getWithItemsList().iterator(); iter.hasNext();) {
148151
WithItem withItem = iter.next();
@@ -154,6 +157,9 @@ public void visit(Select select) {
154157
}
155158
}
156159
select.getSelectBody().accept(selectDeParser);
160+
if (select.isUsingWithBrackets()) {
161+
buffer.append(" )");
162+
}
157163
}
158164

159165
@Override

src/main/java/net/sf/jsqlparser/util/validation/feature/H2Version.java

Lines changed: 3 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -100,6 +100,7 @@ public enum H2Version implements Version {
100100
// http://h2database.com/html/commands.html#insert
101101
Feature.insert,
102102
Feature.insertValues,
103+
Feature.values,
103104
Feature.insertFromSelect,
104105
// http://h2database.com/html/commands.html#update
105106
Feature.update,
@@ -136,7 +137,8 @@ public enum H2Version implements Version {
136137
// http://www.h2database.com/html/commands.html#grant_role
137138
Feature.grant,
138139
// http://h2database.com/html/commands.html#commit
139-
Feature.commit));
140+
Feature.commit
141+
));
140142

141143
private Set<Feature> features;
142144
private String versionString;

src/main/java/net/sf/jsqlparser/util/validation/feature/MariaDbVersion.java

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -60,7 +60,7 @@ public enum MariaDbVersion implements Version {
6060
Feature.withItem, Feature.withItemRecursive,
6161

6262
// https://mariadb.com/kb/en/insert/
63-
Feature.insert, Feature.insertValues,
63+
Feature.insert, Feature.insertValues, Feature.values,
6464
Feature.insertFromSelect, Feature.insertModifierPriority, Feature.insertModifierIgnore,
6565
Feature.insertUseSet, Feature.insertUseDuplicateKeyUpdate, Feature.insertReturningExpressionList,
6666

src/main/java/net/sf/jsqlparser/util/validation/feature/MySqlVersion.java

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -54,6 +54,7 @@ public enum MySqlVersion implements Version {
5454
// https://dev.mysql.com/doc/refman/8.0/en/insert.html
5555
Feature.insert,
5656
Feature.insertValues,
57+
Feature.values,
5758
Feature.insertFromSelect, Feature.insertUseSet, Feature.insertModifierPriority,
5859
Feature.insertModifierIgnore, Feature.insertUseDuplicateKeyUpdate,
5960

src/main/java/net/sf/jsqlparser/util/validation/feature/OracleVersion.java

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -88,6 +88,7 @@ public enum OracleVersion implements Version {
8888
// https://docs.oracle.com/en/database/oracle/oracle-database/19/sqlrf/INSERT.html
8989
Feature.insert,
9090
Feature.insertValues,
91+
Feature.values,
9192
// https://docs.oracle.com/en/database/oracle/oracle-database/19/sqlrf/INSERT.html
9293
// see "single_table_insert"
9394
Feature.insertFromSelect,

src/main/java/net/sf/jsqlparser/util/validation/feature/PostgresqlVersion.java

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -109,6 +109,7 @@ public enum PostgresqlVersion implements Version {
109109
// https://www.postgresql.org/docs/current/sql-insert.html
110110
Feature.insert,
111111
Feature.insertValues,
112+
Feature.values,
112113
Feature.insertFromSelect,
113114
Feature.insertReturningAll, Feature.insertReturningExpressionList,
114115
// https://www.postgresql.org/docs/current/sql-update.html

0 commit comments

Comments
 (0)