Skip to content

Commit 107c08d

Browse files
committed
feat: add support for Oracle INSERT ALL/FIRST with WHEN branches
1 parent ecaa26d commit 107c08d

File tree

8 files changed

+427
-52
lines changed

8 files changed

+427
-52
lines changed

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

Lines changed: 77 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -55,6 +55,9 @@ public class Insert implements Statement {
5555
private InsertConflictAction conflictAction;
5656
private InsertDuplicateAction duplicateAction;
5757
private Alias rowAlias;
58+
private boolean oracleMultiInsert = false;
59+
private boolean oracleMultiInsertFirst = false;
60+
private List<OracleMultiInsertBranch> oracleMultiInsertBranches;
5861

5962
public List<UpdateSet> getDuplicateUpdateSets() {
6063
if (duplicateAction != null) {
@@ -97,6 +100,11 @@ public <T, S> T accept(StatementVisitor<T> statementVisitor, S context) {
97100
}
98101

99102
public Table getTable() {
103+
if (table == null && oracleMultiInsertBranches != null && !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,6 +278,30 @@ 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(List<OracleMultiInsertBranch> oracleMultiInsertBranches) {
302+
this.oracleMultiInsertBranches = oracleMultiInsertBranches;
303+
}
304+
273305
@Override
274306
@SuppressWarnings({"PMD.CyclomaticComplexity", "PMD.NPathComplexity"})
275307
public String toString() {
@@ -295,6 +327,18 @@ public String toString() {
295327
if (modifierIgnore) {
296328
sql.append("IGNORE ");
297329
}
330+
if (oracleMultiInsert) {
331+
sql.append(oracleMultiInsertFirst ? "FIRST" : "ALL");
332+
if (oracleMultiInsertBranches != null && !oracleMultiInsertBranches.isEmpty()) {
333+
for (OracleMultiInsertBranch branch : oracleMultiInsertBranches) {
334+
appendOracleMultiInsertBranch(sql, branch);
335+
}
336+
}
337+
if (select != null) {
338+
sql.append(" ").append(select);
339+
}
340+
return sql.toString();
341+
}
298342
if (overwrite) {
299343
sql.append("OVERWRITE ");
300344
} else {
@@ -424,4 +468,37 @@ public Alias getRowAlias() {
424468
public void setRowAlias(Alias rowAlias) {
425469
this.rowAlias = rowAlias;
426470
}
471+
472+
public Insert withOracleMultiInsert(boolean oracleMultiInsert) {
473+
this.setOracleMultiInsert(oracleMultiInsert);
474+
return this;
475+
}
476+
477+
public Insert withOracleMultiInsertFirst(boolean oracleMultiInsertFirst) {
478+
this.setOracleMultiInsertFirst(oracleMultiInsertFirst);
479+
return this;
480+
}
481+
482+
public Insert withOracleMultiInsertBranches(
483+
List<OracleMultiInsertBranch> oracleMultiInsertBranches) {
484+
this.setOracleMultiInsertBranches(oracleMultiInsertBranches);
485+
return this;
486+
}
487+
488+
private void appendOracleMultiInsertBranch(StringBuilder sql,
489+
OracleMultiInsertBranch branch) {
490+
if (branch == null || branch.getClauses() == null || branch.getClauses().isEmpty()) {
491+
return;
492+
}
493+
494+
if (branch.getWhenExpression() != null) {
495+
sql.append(" WHEN ").append(branch.getWhenExpression()).append(" THEN");
496+
} else if (branch.isElseClause()) {
497+
sql.append(" ELSE");
498+
}
499+
500+
for (OracleMultiInsertClause clause : branch.getClauses()) {
501+
sql.append(" ").append(clause);
502+
}
503+
}
427504
}

src/main/java/net/sf/jsqlparser/util/TablesNamesFinder.java

Lines changed: 20 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -105,6 +105,8 @@
105105
import net.sf.jsqlparser.statement.grant.Grant;
106106
import net.sf.jsqlparser.statement.imprt.Import;
107107
import net.sf.jsqlparser.statement.insert.Insert;
108+
import net.sf.jsqlparser.statement.insert.OracleMultiInsertBranch;
109+
import net.sf.jsqlparser.statement.insert.OracleMultiInsertClause;
108110
import net.sf.jsqlparser.statement.insert.ParenthesedInsert;
109111
import net.sf.jsqlparser.statement.lock.LockStatement;
110112
import net.sf.jsqlparser.statement.merge.Merge;
@@ -1051,7 +1053,24 @@ public void visit(Update update) {
10511053

10521054
@Override
10531055
public <S> Void visit(Insert insert, S context) {
1054-
visit(insert.getTable(), context);
1056+
if (insert.isOracleMultiInsert() && insert.getOracleMultiInsertBranches() != null) {
1057+
for (OracleMultiInsertBranch branch : insert.getOracleMultiInsertBranches()) {
1058+
if (branch.getWhenExpression() != null) {
1059+
branch.getWhenExpression().accept(this, context);
1060+
}
1061+
if (branch.getClauses() == null) {
1062+
continue;
1063+
}
1064+
for (OracleMultiInsertClause clause : branch.getClauses()) {
1065+
visit(clause.getTable(), context);
1066+
if (clause.getSelect() != null) {
1067+
visit(clause.getSelect(), context);
1068+
}
1069+
}
1070+
}
1071+
} else if (insert.getTable() != null) {
1072+
visit(insert.getTable(), context);
1073+
}
10551074
if (insert.getWithItemsList() != null) {
10561075
for (WithItem<?> withItem : insert.getWithItemsList()) {
10571076
withItem.accept((SelectVisitor<?>) this, context);

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

Lines changed: 57 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -14,6 +14,8 @@
1414
import net.sf.jsqlparser.schema.Partition;
1515
import net.sf.jsqlparser.statement.insert.ConflictActionType;
1616
import net.sf.jsqlparser.statement.insert.Insert;
17+
import net.sf.jsqlparser.statement.insert.OracleMultiInsertBranch;
18+
import net.sf.jsqlparser.statement.insert.OracleMultiInsertClause;
1719
import net.sf.jsqlparser.statement.select.Select;
1820
import net.sf.jsqlparser.statement.select.SelectVisitor;
1921
import net.sf.jsqlparser.statement.select.WithItem;
@@ -63,6 +65,19 @@ public void deParse(Insert insert) {
6365
if (insert.isModifierIgnore()) {
6466
builder.append("IGNORE ");
6567
}
68+
if (insert.isOracleMultiInsert()) {
69+
builder.append(insert.isOracleMultiInsertFirst() ? "FIRST" : "ALL");
70+
if (insert.getOracleMultiInsertBranches() != null) {
71+
for (OracleMultiInsertBranch branch : insert.getOracleMultiInsertBranches()) {
72+
appendOracleMultiInsertBranch(branch);
73+
}
74+
}
75+
if (insert.getSelect() != null) {
76+
builder.append(" ");
77+
insert.getSelect().accept(selectVisitor, null);
78+
}
79+
return;
80+
}
6681
if (insert.isOverwrite()) {
6782
builder.append("OVERWRITE ");
6883
} else {
@@ -158,4 +173,46 @@ public SelectVisitor<StringBuilder> getSelectVisitor() {
158173
public void setSelectVisitor(SelectVisitor<StringBuilder> visitor) {
159174
selectVisitor = visitor;
160175
}
176+
177+
private void appendOracleIntoClause(OracleMultiInsertClause clause) {
178+
builder.append("INTO ").append(clause.getTable().toString());
179+
if (clause.getColumns() != null && !clause.getColumns().isEmpty()) {
180+
builder.append(" (");
181+
for (Iterator<Column> iter = clause.getColumns().iterator(); iter.hasNext();) {
182+
Column column = iter.next();
183+
builder.append(column.getColumnName());
184+
if (iter.hasNext()) {
185+
builder.append(", ");
186+
}
187+
}
188+
builder.append(")");
189+
}
190+
if (clause.getSelect() != null) {
191+
builder.append(" ");
192+
clause.getSelect().accept(selectVisitor, null);
193+
}
194+
}
195+
196+
private void appendOracleMultiInsertBranch(OracleMultiInsertBranch branch) {
197+
if (branch == null || branch.getClauses() == null || branch.getClauses().isEmpty()) {
198+
return;
199+
}
200+
201+
if (branch.getWhenExpression() != null) {
202+
builder.append(" WHEN ");
203+
if (expressionVisitor != null) {
204+
branch.getWhenExpression().accept(expressionVisitor, null);
205+
} else {
206+
builder.append(branch.getWhenExpression().toString());
207+
}
208+
builder.append(" THEN");
209+
} else if (branch.isElseClause()) {
210+
builder.append(" ELSE");
211+
}
212+
213+
for (OracleMultiInsertClause clause : branch.getClauses()) {
214+
builder.append(" ");
215+
appendOracleIntoClause(clause);
216+
}
217+
}
161218
}

src/main/java/net/sf/jsqlparser/util/validation/validator/InsertValidator.java

Lines changed: 24 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -11,6 +11,8 @@
1111

1212
import net.sf.jsqlparser.parser.feature.Feature;
1313
import net.sf.jsqlparser.statement.insert.Insert;
14+
import net.sf.jsqlparser.statement.insert.OracleMultiInsertBranch;
15+
import net.sf.jsqlparser.statement.insert.OracleMultiInsertClause;
1416
import net.sf.jsqlparser.statement.select.Values;
1517
import net.sf.jsqlparser.statement.update.UpdateSet;
1618
import net.sf.jsqlparser.util.validation.ValidationCapability;
@@ -41,8 +43,28 @@ public void validate(Insert insert) {
4143
Feature.insertReturningExpressionList);
4244
}
4345

44-
validateOptionalFromItem(insert.getTable());
45-
validateOptionalExpressions(insert.getColumns());
46+
if (insert.isOracleMultiInsert() && insert.getOracleMultiInsertBranches() != null) {
47+
ExpressionValidator v = getValidator(ExpressionValidator.class);
48+
for (OracleMultiInsertBranch branch : insert.getOracleMultiInsertBranches()) {
49+
if (branch.getWhenExpression() != null) {
50+
branch.getWhenExpression().accept(v, null);
51+
}
52+
if (branch.getClauses() == null) {
53+
continue;
54+
}
55+
for (OracleMultiInsertClause clause : branch.getClauses()) {
56+
validateOptionalFromItem(clause.getTable());
57+
validateOptionalExpressions(clause.getColumns());
58+
if (clause.getSelect() instanceof Values) {
59+
clause.getSelect().accept(getValidator(StatementValidator.class), null);
60+
validateOptionalExpressions(clause.getSelect().as(Values.class).getExpressions());
61+
}
62+
}
63+
}
64+
} else {
65+
validateOptionalFromItem(insert.getTable());
66+
validateOptionalExpressions(insert.getColumns());
67+
}
4668

4769
if (insert.getSelect() instanceof Values) {
4870
insert.getSelect().accept(getValidator(StatementValidator.class), null);

0 commit comments

Comments
 (0)