Skip to content

Commit 49115da

Browse files
committed
fix: readd standard fields and add compatibility logic
1 parent 6570d44 commit 49115da

File tree

2 files changed

+138
-29
lines changed

2 files changed

+138
-29
lines changed

src/main/java/net/sf/jsqlparser/statement/merge/Merge.java

Lines changed: 71 additions & 26 deletions
Original file line numberDiff line numberDiff line change
@@ -26,6 +26,7 @@
2626
import java.util.Iterator;
2727
import java.util.List;
2828
import java.util.Optional;
29+
import java.util.stream.Collectors;
2930

3031
public class Merge implements Statement {
3132

@@ -34,10 +35,46 @@ public class Merge implements Statement {
3435
private OracleHint oracleHint = null;
3536
private FromItem fromItem;
3637
private Expression onCondition;
38+
private MergeInsert mergeInsert;
39+
private MergeUpdate mergeUpdate;
40+
private boolean insertFirst = false;
3741
private List<MergeOperation> operations;
3842

3943
private OutputClause outputClause;
4044

45+
private void deriveOperationsFromStandardClauses() {
46+
List<MergeOperation> operations = new ArrayList<>();
47+
if (insertFirst) {
48+
Optional.ofNullable(mergeInsert).ifPresent(operations::add);
49+
Optional.ofNullable(mergeUpdate).ifPresent(operations::add);
50+
} else {
51+
Optional.ofNullable(mergeUpdate).ifPresent(operations::add);
52+
Optional.ofNullable(mergeInsert).ifPresent(operations::add);
53+
}
54+
this.operations = operations;
55+
}
56+
57+
private void deriveStandardClausesFromOperations() {
58+
List<MergeOperation> applicableOperations =
59+
Optional.ofNullable(operations).orElse(Collections.emptyList()).stream()
60+
.filter(o -> o instanceof MergeUpdate || o instanceof MergeInsert)
61+
.collect(Collectors.toList());
62+
mergeUpdate = applicableOperations.stream()
63+
.filter(o -> o instanceof MergeUpdate)
64+
.map(MergeUpdate.class::cast)
65+
.findFirst()
66+
.orElse(null);
67+
mergeInsert = applicableOperations.stream()
68+
.filter(o -> o instanceof MergeInsert)
69+
.map(MergeInsert.class::cast)
70+
.findFirst()
71+
.orElse(null);
72+
insertFirst = applicableOperations.stream()
73+
.findFirst()
74+
.map(o -> o instanceof MergeInsert)
75+
.orElse(false);
76+
}
77+
4178
public List<WithItem> getWithItemsList() {
4279
return withItemsList;
4380
}
@@ -133,46 +170,39 @@ public List<MergeOperation> getOperations() {
133170

134171
public void setOperations(List<MergeOperation> operations) {
135172
this.operations = operations;
173+
deriveStandardClausesFromOperations();
136174
}
137175

138-
/**
139-
* @deprecated use {@link #getOperations()} or consider a {@link MergeOperationVisitor} instead
140-
*/
141-
@Deprecated
142176
public MergeInsert getMergeInsert() {
143-
return operations.stream()
144-
.filter(MergeInsert.class::isInstance)
145-
.findFirst()
146-
.map(MergeInsert.class::cast)
147-
.orElse(null);
177+
return mergeInsert;
178+
}
179+
180+
public void setMergeInsert(MergeInsert mergeInsert) {
181+
this.mergeInsert = mergeInsert;
182+
deriveOperationsFromStandardClauses();
148183
}
149184

150-
/**
151-
* @deprecated use {@link #getOperations()} or consider a {@link MergeOperationVisitor} instead
152-
*/
153-
@Deprecated
154185
public MergeUpdate getMergeUpdate() {
155-
return operations.stream()
156-
.filter(MergeUpdate.class::isInstance)
157-
.findFirst()
158-
.map(MergeUpdate.class::cast)
159-
.orElse(null);
186+
return mergeUpdate;
187+
}
188+
189+
public void setMergeUpdate(MergeUpdate mergeUpdate) {
190+
this.mergeUpdate = mergeUpdate;
191+
deriveOperationsFromStandardClauses();
160192
}
161193

162194
@Override
163195
public void accept(StatementVisitor statementVisitor) {
164196
statementVisitor.visit(this);
165197
}
166198

167-
/**
168-
* @deprecated use {@link #getOperations()} or consider a {@link MergeOperationVisitor} instead
169-
*/
170-
@Deprecated
171199
public boolean isInsertFirst() {
172-
if (operations == null || operations.isEmpty()) {
173-
return false;
174-
}
175-
return operations.get(0) instanceof MergeInsert;
200+
return insertFirst;
201+
}
202+
203+
public void setInsertFirst(boolean insertFirst) {
204+
this.insertFirst = insertFirst;
205+
deriveOperationsFromStandardClauses();
176206
}
177207

178208
public OutputClause getOutputClause() {
@@ -244,11 +274,26 @@ public Merge withOnCondition(Expression onCondition) {
244274
return this;
245275
}
246276

277+
public Merge withMergeUpdate(MergeUpdate mergeUpdate) {
278+
this.setMergeUpdate(mergeUpdate);
279+
return this;
280+
}
281+
282+
public Merge withInsertFirst(boolean insertFirst) {
283+
this.setInsertFirst(insertFirst);
284+
return this;
285+
}
286+
247287
public Merge withTable(Table table) {
248288
this.setTable(table);
249289
return this;
250290
}
251291

292+
public Merge withMergeInsert(MergeInsert mergeInsert) {
293+
this.setMergeInsert(mergeInsert);
294+
return this;
295+
}
296+
252297
public <E extends Expression> E getOnCondition(Class<E> type) {
253298
return type.cast(getOnCondition());
254299
}

src/test/java/net/sf/jsqlparser/statement/merge/MergeTest.java

Lines changed: 67 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -12,11 +12,20 @@
1212
import net.sf.jsqlparser.JSQLParserException;
1313
import net.sf.jsqlparser.parser.CCJSqlParserUtil;
1414
import net.sf.jsqlparser.statement.Statement;
15-
import org.assertj.core.api.Assertions;
1615
import org.junit.jupiter.api.Test;
16+
import org.junit.jupiter.params.ParameterizedTest;
17+
import org.junit.jupiter.params.provider.Arguments;
18+
import org.junit.jupiter.params.provider.MethodSource;
19+
20+
import java.util.Arrays;
21+
import java.util.Collections;
22+
import java.util.List;
23+
import java.util.stream.Stream;
1724

1825
import static net.sf.jsqlparser.test.TestUtils.assertOracleHintExists;
1926
import static net.sf.jsqlparser.test.TestUtils.assertSqlCanBeParsedAndDeparsed;
27+
import static org.assertj.core.api.Assertions.assertThat;
28+
import static org.mockito.Mockito.mock;
2029

2130
/**
2231
*
@@ -153,10 +162,10 @@ public void testInsertMergeWhere() throws JSQLParserException {
153162

154163
Merge merge = (Merge) statement;
155164
MergeInsert mergeInsert = merge.getMergeInsert();
156-
Assertions.assertThat(mergeInsert.getWhereCondition());
165+
assertThat(mergeInsert.getWhereCondition());
157166

158167
MergeUpdate mergeUpdate = merge.getMergeUpdate();
159-
Assertions.assertThat(mergeUpdate.getWhereCondition());
168+
assertThat(mergeUpdate.getWhereCondition());
160169
}
161170

162171
@Test
@@ -266,4 +275,59 @@ void testSnowflakeMergeStatementWithManyWhensAndDelete() throws JSQLParserExcept
266275

267276
assertSqlCanBeParsedAndDeparsed(sql, true);
268277
}
278+
279+
@ParameterizedTest
280+
@MethodSource("deriveOperationsFromStandardClausesCases")
281+
void testDeriveOperationsFromStandardClauses(List<MergeOperation> expectedOperations,
282+
MergeUpdate update, MergeInsert insert, boolean insertFirst) {
283+
Merge merge = new Merge();
284+
merge.setMergeUpdate(update);
285+
merge.setMergeInsert(insert);
286+
merge.setInsertFirst(insertFirst);
287+
288+
assertThat(merge.getOperations()).isEqualTo(expectedOperations);
289+
}
290+
291+
private static Stream<Arguments> deriveOperationsFromStandardClausesCases() {
292+
MergeUpdate update = mock(MergeUpdate.class);
293+
MergeInsert insert = mock(MergeInsert.class);
294+
295+
return Stream.of(
296+
Arguments.of(Arrays.asList(update, insert), update, insert, false),
297+
Arguments.of(Arrays.asList(insert, update), update, insert, true));
298+
}
299+
300+
@ParameterizedTest
301+
@MethodSource("deriveStandardClausesFromOperationsCases")
302+
void testDeriveStandardClausesFromOperations(List<MergeOperation> operations,
303+
MergeUpdate expectedUpdate, MergeInsert expectedInsert, boolean expectedInsertFirst) {
304+
Merge merge = new Merge();
305+
merge.setOperations(operations);
306+
307+
assertThat(merge.getMergeUpdate()).isEqualTo(expectedUpdate);
308+
assertThat(merge.getMergeInsert()).isEqualTo(expectedInsert);
309+
assertThat(merge.isInsertFirst()).isEqualTo(expectedInsertFirst);
310+
}
311+
312+
private static Stream<Arguments> deriveStandardClausesFromOperationsCases() {
313+
MergeDelete delete1 = mock(MergeDelete.class);
314+
MergeUpdate update1 = mock(MergeUpdate.class);
315+
MergeUpdate update2 = mock(MergeUpdate.class);
316+
MergeInsert insert1 = mock(MergeInsert.class);
317+
MergeInsert insert2 = mock(MergeInsert.class);
318+
319+
return Stream.of(
320+
// just the two standard clauses present
321+
Arguments.of(Arrays.asList(update1, insert1), update1, insert1, false),
322+
Arguments.of(Arrays.asList(insert1, update1), update1, insert1, true),
323+
// some clause(s) missing
324+
Arguments.of(Collections.singletonList(update1), update1, null, false),
325+
Arguments.of(Collections.singletonList(insert1), null, insert1, true),
326+
Arguments.of(Collections.emptyList(), null, null, false),
327+
// many clauses (non-standard)
328+
Arguments.of(Arrays.asList(update1, update2, delete1, insert1, insert2), update1,
329+
insert1, false),
330+
Arguments.of(Arrays.asList(insert1, insert2, update1, update2, delete1), update1,
331+
insert1, true));
332+
}
269333
}

0 commit comments

Comments
 (0)