Skip to content

Commit 4f982e7

Browse files
authored
feat: add support for Oracle INSERT ALL/FIRST with WHEN branches (#2394)
* feat: add support for Oracle INSERT ALL/FIRST with WHEN branches * feat: add support for Oracle INSERT ALL/FIRST with WHEN branches * fix * polish
1 parent 64542c8 commit 4f982e7

File tree

10 files changed

+645
-80
lines changed

10 files changed

+645
-80
lines changed

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

Lines changed: 109 additions & 9 deletions
Original file line numberDiff line numberDiff line change
@@ -9,6 +9,11 @@
99
*/
1010
package net.sf.jsqlparser.statement.insert;
1111

12+
import java.util.Arrays;
13+
import java.util.Collection;
14+
import java.util.Iterator;
15+
import java.util.List;
16+
import java.util.Optional;
1217
import net.sf.jsqlparser.expression.Alias;
1318
import net.sf.jsqlparser.expression.OracleHint;
1419
import net.sf.jsqlparser.expression.operators.relational.ExpressionList;
@@ -26,12 +31,6 @@
2631
import net.sf.jsqlparser.statement.select.WithItem;
2732
import net.sf.jsqlparser.statement.update.UpdateSet;
2833

29-
import java.util.Arrays;
30-
import java.util.Collection;
31-
import java.util.Iterator;
32-
import java.util.List;
33-
import java.util.Optional;
34-
3534
@SuppressWarnings({"PMD.CyclomaticComplexity"})
3635
public class Insert implements Statement {
3736

@@ -55,6 +54,9 @@ public class Insert implements Statement {
5554
private InsertConflictAction conflictAction;
5655
private InsertDuplicateAction duplicateAction;
5756
private Alias rowAlias;
57+
private boolean oracleMultiInsert = false;
58+
private boolean oracleMultiInsertFirst = false;
59+
private List<OracleMultiInsertBranch> oracleMultiInsertBranches;
5860

5961
public List<UpdateSet> getDuplicateUpdateSets() {
6062
if (duplicateAction != null) {
@@ -97,6 +99,12 @@ public <T, S> T accept(StatementVisitor<T> statementVisitor, S context) {
9799
}
98100

99101
public Table getTable() {
102+
if (table == null && oracleMultiInsertBranches != null
103+
&& !oracleMultiInsertBranches.isEmpty()
104+
&& oracleMultiInsertBranches.get(0).getClauses() != null
105+
&& !oracleMultiInsertBranches.get(0).getClauses().isEmpty()) {
106+
return oracleMultiInsertBranches.get(0).getClauses().get(0).getTable();
107+
}
100108
return table;
101109
}
102110

@@ -270,10 +278,46 @@ public Insert withConflictAction(InsertConflictAction conflictAction) {
270278
return this;
271279
}
272280

281+
public boolean isOracleMultiInsert() {
282+
return oracleMultiInsert;
283+
}
284+
285+
public void setOracleMultiInsert(boolean oracleMultiInsert) {
286+
this.oracleMultiInsert = oracleMultiInsert;
287+
}
288+
289+
public boolean isOracleMultiInsertFirst() {
290+
return oracleMultiInsertFirst;
291+
}
292+
293+
public void setOracleMultiInsertFirst(boolean oracleMultiInsertFirst) {
294+
this.oracleMultiInsertFirst = oracleMultiInsertFirst;
295+
}
296+
297+
public List<OracleMultiInsertBranch> getOracleMultiInsertBranches() {
298+
return oracleMultiInsertBranches;
299+
}
300+
301+
public void setOracleMultiInsertBranches(
302+
List<OracleMultiInsertBranch> oracleMultiInsertBranches) {
303+
this.oracleMultiInsertBranches = oracleMultiInsertBranches;
304+
}
305+
273306
@Override
274307
@SuppressWarnings({"PMD.CyclomaticComplexity", "PMD.NPathComplexity"})
275308
public String toString() {
276309
StringBuilder sql = new StringBuilder();
310+
appendWithItems(sql);
311+
appendInsertPrefix(sql);
312+
if (appendOracleMultiInsert(sql)) {
313+
return sql.toString();
314+
}
315+
appendInsertTargetAndValues(sql);
316+
appendInsertActions(sql);
317+
return sql.toString();
318+
}
319+
320+
private void appendWithItems(StringBuilder sql) {
277321
if (withItemsList != null && !withItemsList.isEmpty()) {
278322
sql.append("WITH ");
279323
for (Iterator<WithItem<?>> iter = withItemsList.iterator(); iter.hasNext();) {
@@ -285,6 +329,9 @@ public String toString() {
285329
sql.append(" ");
286330
}
287331
}
332+
}
333+
334+
private void appendInsertPrefix(StringBuilder sql) {
288335
sql.append("INSERT ");
289336
if (oracleHint != null) {
290337
sql.append(oracleHint).append(" ");
@@ -295,6 +342,26 @@ public String toString() {
295342
if (modifierIgnore) {
296343
sql.append("IGNORE ");
297344
}
345+
}
346+
347+
private boolean appendOracleMultiInsert(StringBuilder sql) {
348+
if (!oracleMultiInsert) {
349+
return false;
350+
}
351+
352+
sql.append(oracleMultiInsertFirst ? "FIRST" : "ALL");
353+
if (oracleMultiInsertBranches != null && !oracleMultiInsertBranches.isEmpty()) {
354+
for (OracleMultiInsertBranch branch : oracleMultiInsertBranches) {
355+
appendOracleMultiInsertBranch(sql, branch);
356+
}
357+
}
358+
if (select != null) {
359+
sql.append(" ").append(select);
360+
}
361+
return true;
362+
}
363+
364+
private void appendInsertTargetAndValues(StringBuilder sql) {
298365
if (overwrite) {
299366
sql.append("OVERWRITE ");
300367
} else {
@@ -338,10 +405,12 @@ public String toString() {
338405
if (select != null) {
339406
sql.append(select);
340407
}
408+
}
341409

410+
private void appendInsertActions(StringBuilder sql) {
342411
if (setUpdateSets != null && !setUpdateSets.isEmpty()) {
343412
sql.append("SET ");
344-
sql = UpdateSet.appendUpdateSetsTo(sql, setUpdateSets);
413+
UpdateSet.appendUpdateSetsTo(sql, setUpdateSets);
345414
if (rowAlias != null) {
346415
sql.append(" ").append(rowAlias);
347416
}
@@ -364,8 +433,6 @@ public String toString() {
364433
if (returningClause != null) {
365434
returningClause.appendTo(sql);
366435
}
367-
368-
return sql.toString();
369436
}
370437

371438
public Insert withWithItemsList(List<WithItem<?>> withList) {
@@ -424,4 +491,37 @@ public Alias getRowAlias() {
424491
public void setRowAlias(Alias rowAlias) {
425492
this.rowAlias = rowAlias;
426493
}
494+
495+
public Insert withOracleMultiInsert(boolean oracleMultiInsert) {
496+
this.setOracleMultiInsert(oracleMultiInsert);
497+
return this;
498+
}
499+
500+
public Insert withOracleMultiInsertFirst(boolean oracleMultiInsertFirst) {
501+
this.setOracleMultiInsertFirst(oracleMultiInsertFirst);
502+
return this;
503+
}
504+
505+
public Insert withOracleMultiInsertBranches(
506+
List<OracleMultiInsertBranch> oracleMultiInsertBranches) {
507+
this.setOracleMultiInsertBranches(oracleMultiInsertBranches);
508+
return this;
509+
}
510+
511+
private void appendOracleMultiInsertBranch(StringBuilder sql,
512+
OracleMultiInsertBranch branch) {
513+
if (branch == null || branch.getClauses() == null || branch.getClauses().isEmpty()) {
514+
return;
515+
}
516+
517+
if (branch.getWhenExpression() != null) {
518+
sql.append(" WHEN ").append(branch.getWhenExpression()).append(" THEN");
519+
} else if (branch.isElseClause()) {
520+
sql.append(" ELSE");
521+
}
522+
523+
for (OracleMultiInsertClause clause : branch.getClauses()) {
524+
sql.append(" ").append(clause);
525+
}
526+
}
427527
}
Lines changed: 74 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,74 @@
1+
/*-
2+
* #%L
3+
* JSQLParser library
4+
* %%
5+
* Copyright (C) 2004 - 2019 JSQLParser
6+
* %%
7+
* Dual licensed under GNU LGPL 2.1 or Apache License 2.0
8+
* #L%
9+
*/
10+
package net.sf.jsqlparser.statement.insert;
11+
12+
import java.io.Serializable;
13+
import java.util.ArrayList;
14+
import java.util.List;
15+
import net.sf.jsqlparser.expression.Expression;
16+
17+
public class OracleMultiInsertBranch implements Serializable {
18+
19+
private Expression whenExpression;
20+
private boolean elseClause;
21+
private List<OracleMultiInsertClause> clauses = new ArrayList<>();
22+
23+
public Expression getWhenExpression() {
24+
return whenExpression;
25+
}
26+
27+
public void setWhenExpression(Expression whenExpression) {
28+
this.whenExpression = whenExpression;
29+
if (whenExpression != null) {
30+
this.elseClause = false;
31+
}
32+
}
33+
34+
public boolean isElseClause() {
35+
return elseClause;
36+
}
37+
38+
public void setElseClause(boolean elseClause) {
39+
this.elseClause = elseClause;
40+
if (elseClause) {
41+
this.whenExpression = null;
42+
}
43+
}
44+
45+
public List<OracleMultiInsertClause> getClauses() {
46+
return clauses;
47+
}
48+
49+
public void setClauses(List<OracleMultiInsertClause> clauses) {
50+
this.clauses = clauses == null ? new ArrayList<>() : clauses;
51+
}
52+
53+
public void addClause(OracleMultiInsertClause clause) {
54+
if (clause == null) {
55+
return;
56+
}
57+
clauses.add(clause);
58+
}
59+
60+
public OracleMultiInsertBranch withWhenExpression(Expression whenExpression) {
61+
this.setWhenExpression(whenExpression);
62+
return this;
63+
}
64+
65+
public OracleMultiInsertBranch withElseClause(boolean elseClause) {
66+
this.setElseClause(elseClause);
67+
return this;
68+
}
69+
70+
public OracleMultiInsertBranch withClauses(List<OracleMultiInsertClause> clauses) {
71+
this.setClauses(clauses);
72+
return this;
73+
}
74+
}
Lines changed: 87 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,87 @@
1+
/*-
2+
* #%L
3+
* JSQLParser library
4+
* %%
5+
* Copyright (C) 2004 - 2019 JSQLParser
6+
* %%
7+
* Dual licensed under GNU LGPL 2.1 or Apache License 2.0
8+
* #L%
9+
*/
10+
package net.sf.jsqlparser.statement.insert;
11+
12+
import java.io.Serializable;
13+
import java.util.Iterator;
14+
import net.sf.jsqlparser.expression.operators.relational.ExpressionList;
15+
import net.sf.jsqlparser.schema.Column;
16+
import net.sf.jsqlparser.schema.Table;
17+
import net.sf.jsqlparser.statement.select.Select;
18+
19+
public class OracleMultiInsertClause implements Serializable {
20+
21+
private Table table;
22+
private ExpressionList<Column> columns;
23+
private Select select;
24+
25+
public Table getTable() {
26+
return table;
27+
}
28+
29+
public void setTable(Table table) {
30+
this.table = table;
31+
}
32+
33+
public ExpressionList<Column> getColumns() {
34+
return columns;
35+
}
36+
37+
public void setColumns(ExpressionList<Column> columns) {
38+
this.columns = columns;
39+
}
40+
41+
public Select getSelect() {
42+
return select;
43+
}
44+
45+
public void setSelect(Select select) {
46+
this.select = select;
47+
}
48+
49+
@Override
50+
public String toString() {
51+
StringBuilder sql = new StringBuilder("INTO ");
52+
sql.append(table);
53+
54+
if (columns != null && !columns.isEmpty()) {
55+
sql.append(" (");
56+
for (Iterator<Column> iter = columns.iterator(); iter.hasNext();) {
57+
Column column = iter.next();
58+
sql.append(column.getColumnName());
59+
if (iter.hasNext()) {
60+
sql.append(", ");
61+
}
62+
}
63+
sql.append(")");
64+
}
65+
66+
if (select != null) {
67+
sql.append(" ").append(select);
68+
}
69+
70+
return sql.toString();
71+
}
72+
73+
public OracleMultiInsertClause withTable(Table table) {
74+
this.setTable(table);
75+
return this;
76+
}
77+
78+
public OracleMultiInsertClause withColumns(ExpressionList<Column> columns) {
79+
this.setColumns(columns);
80+
return this;
81+
}
82+
83+
public OracleMultiInsertClause withSelect(Select select) {
84+
this.setSelect(select);
85+
return this;
86+
}
87+
}

0 commit comments

Comments
 (0)