[jOOQ/jOOQ#7291] Add support for multiple MERGE .. WHEN [ NOT ] MATCHED AND { condition }
This commit is contained in:
parent
e62581488c
commit
7b443dc2f1
@ -81,7 +81,7 @@ import org.jooq.impl.DSL;
|
||||
*
|
||||
* @author Lukas Eder
|
||||
*/
|
||||
public interface MergeMatchedDeleteStep<R extends Record> extends MergeNotMatchedStep<R> {
|
||||
public interface MergeMatchedDeleteStep<R extends Record> extends MergeMatchedStep<R> {
|
||||
|
||||
/**
|
||||
* Add an additional <code>DELETE WHERE</code> clause to the preceding
|
||||
|
||||
@ -49,6 +49,8 @@ import static org.jooq.SQLDialect.HSQLDB;
|
||||
// ...
|
||||
// ...
|
||||
|
||||
import org.jooq.impl.DSL;
|
||||
|
||||
/**
|
||||
* This type is used for the {@link Merge}'s DSL API.
|
||||
* <p>
|
||||
@ -90,8 +92,89 @@ public interface MergeMatchedStep<R extends Record> extends MergeNotMatchedStep<
|
||||
|
||||
/**
|
||||
* Add the <code>WHEN MATCHED THEN UPDATE</code> clause to the
|
||||
* <code>MERGE</code> statement
|
||||
* <code>MERGE</code> statement.
|
||||
*/
|
||||
@Support({ CUBRID, DERBY, FIREBIRD, H2, HSQLDB })
|
||||
MergeMatchedSetStep<R> whenMatchedThenUpdate();
|
||||
|
||||
/**
|
||||
* Add the <code>WHEN MATCHED AND .. THEN UPDATE</code> clause to the
|
||||
* <code>MERGE</code> statement.
|
||||
*/
|
||||
@Support({ DERBY, H2, HSQLDB })
|
||||
MergeMatchedThenStep<R> whenMatchedAnd(Condition condition);
|
||||
|
||||
/**
|
||||
* Add the <code>WHEN MATCHED AND .. THEN UPDATE</code> clause to the
|
||||
* <code>MERGE</code> statement.
|
||||
*/
|
||||
@Support({ DERBY, H2, HSQLDB })
|
||||
MergeMatchedThenStep<R> whenMatchedAnd(Field<Boolean> condition);
|
||||
|
||||
/**
|
||||
* Add the <code>WHEN MATCHED AND .. THEN UPDATE</code> clause to the
|
||||
* <code>MERGE</code> statement.
|
||||
* <p>
|
||||
* <b>NOTE</b>: When inserting plain SQL into jOOQ objects, you must
|
||||
* guarantee syntax integrity. You may also create the possibility of
|
||||
* malicious SQL injection. Be sure to properly use bind variables and/or
|
||||
* escape literals when concatenated into SQL clauses!
|
||||
*
|
||||
* @see DSL#condition(SQL)
|
||||
* @see SQL
|
||||
*/
|
||||
@PlainSQL
|
||||
@Support({ DERBY, H2, HSQLDB })
|
||||
MergeMatchedThenStep<R> whenMatchedAnd(SQL sql);
|
||||
|
||||
/**
|
||||
* Add the <code>WHEN MATCHED AND .. THEN UPDATE</code> clause to the
|
||||
* <code>MERGE</code> statement.
|
||||
* <p>
|
||||
* <b>NOTE</b>: When inserting plain SQL into jOOQ objects, you must
|
||||
* guarantee syntax integrity. You may also create the possibility of
|
||||
* malicious SQL injection. Be sure to properly use bind variables and/or
|
||||
* escape literals when concatenated into SQL clauses!
|
||||
*
|
||||
* @see DSL#condition(String)
|
||||
* @see SQL
|
||||
*/
|
||||
@PlainSQL
|
||||
@Support({ DERBY, H2, HSQLDB })
|
||||
MergeMatchedThenStep<R> whenMatchedAnd(String sql);
|
||||
|
||||
/**
|
||||
* Add the <code>WHEN MATCHED AND .. THEN UPDATE</code> clause to the
|
||||
* <code>MERGE</code> statement.
|
||||
* <p>
|
||||
* <b>NOTE</b>: When inserting plain SQL into jOOQ objects, you must
|
||||
* guarantee syntax integrity. You may also create the possibility of
|
||||
* malicious SQL injection. Be sure to properly use bind variables and/or
|
||||
* escape literals when concatenated into SQL clauses!
|
||||
*
|
||||
* @see DSL#condition(String, Object...)
|
||||
* @see DSL#sql(String, Object...)
|
||||
* @see SQL
|
||||
*/
|
||||
@PlainSQL
|
||||
@Support({ DERBY, H2, HSQLDB })
|
||||
MergeMatchedThenStep<R> whenMatchedAnd(String sql, Object... bindings);
|
||||
|
||||
/**
|
||||
* Add the <code>WHEN MATCHED AND .. THEN UPDATE</code> clause to the
|
||||
* <code>MERGE</code> statement.
|
||||
* <p>
|
||||
* <b>NOTE</b>: When inserting plain SQL into jOOQ objects, you must
|
||||
* guarantee syntax integrity. You may also create the possibility of
|
||||
* malicious SQL injection. Be sure to properly use bind variables and/or
|
||||
* escape literals when concatenated into SQL clauses!
|
||||
*
|
||||
* @see DSL#condition(String, QueryPart...)
|
||||
* @see DSL#sql(String, QueryPart...)
|
||||
* @see SQL
|
||||
*/
|
||||
@PlainSQL
|
||||
@Support({ DERBY, H2, HSQLDB })
|
||||
MergeMatchedThenStep<R> whenMatchedAnd(String sql, QueryPart... parts);
|
||||
|
||||
}
|
||||
|
||||
@ -119,6 +119,7 @@ import org.jooq.MergeKeyStep8;
|
||||
import org.jooq.MergeKeyStep9;
|
||||
import org.jooq.MergeMatchedDeleteStep;
|
||||
import org.jooq.MergeMatchedSetMoreStep;
|
||||
import org.jooq.MergeMatchedThenStep;
|
||||
import org.jooq.MergeNotMatchedSetMoreStep;
|
||||
import org.jooq.MergeNotMatchedValuesStep1;
|
||||
import org.jooq.MergeNotMatchedValuesStep10;
|
||||
@ -203,6 +204,7 @@ implements
|
||||
MergeOnStep<R>,
|
||||
MergeOnConditionStep<R>,
|
||||
MergeMatchedSetMoreStep<R>,
|
||||
MergeMatchedThenStep<R>,
|
||||
MergeNotMatchedSetMoreStep<R>,
|
||||
|
||||
|
||||
@ -254,7 +256,8 @@ implements
|
||||
|
||||
// Flags to keep track of DSL object creation state
|
||||
private boolean matchedClause;
|
||||
private FieldMapForUpdate matchedUpdate;
|
||||
private List<FieldMapForUpdate> matchedUpdate;
|
||||
private List<Condition> matchedUpdateAnd;
|
||||
private boolean notMatchedClause;
|
||||
private FieldMapsForInsert notMatchedInsert;
|
||||
|
||||
@ -275,6 +278,8 @@ implements
|
||||
this.with = with;
|
||||
this.table = table;
|
||||
this.on = new ConditionProviderImpl();
|
||||
this.matchedUpdate = new ArrayList<>();
|
||||
this.matchedUpdateAnd = new ArrayList<>();
|
||||
|
||||
if (fields != null)
|
||||
columns(fields);
|
||||
@ -305,6 +310,10 @@ implements
|
||||
return upsertValues;
|
||||
}
|
||||
|
||||
FieldMapForUpdate getLastMatchedUpdate() {
|
||||
return matchedUpdate.get(matchedUpdate.size() - 1);
|
||||
}
|
||||
|
||||
@Override
|
||||
public final MergeImpl columns(Field<?>... fields) {
|
||||
return columns(Arrays.asList(fields));
|
||||
@ -917,12 +926,50 @@ implements
|
||||
@Override
|
||||
public final MergeImpl whenMatchedThenUpdate() {
|
||||
matchedClause = true;
|
||||
matchedUpdate = new FieldMapForUpdate(table, MERGE_SET_ASSIGNMENT);
|
||||
matchedUpdate.add(new FieldMapForUpdate(table, MERGE_SET_ASSIGNMENT));
|
||||
matchedUpdateAnd.add(null);
|
||||
|
||||
notMatchedClause = false;
|
||||
return this;
|
||||
}
|
||||
|
||||
@Override
|
||||
public final MergeImpl whenMatchedAnd(Condition condition) {
|
||||
whenMatchedThenUpdate();
|
||||
matchedUpdateAnd.set(matchedUpdateAnd.size() - 1, condition);
|
||||
return this;
|
||||
}
|
||||
|
||||
@Override
|
||||
public final MergeImpl whenMatchedAnd(Field<Boolean> condition) {
|
||||
return whenMatchedAnd(condition(condition));
|
||||
}
|
||||
|
||||
@Override
|
||||
public final MergeImpl whenMatchedAnd(SQL sql) {
|
||||
return whenMatchedAnd(condition(sql));
|
||||
}
|
||||
|
||||
@Override
|
||||
public final MergeImpl whenMatchedAnd(String sql) {
|
||||
return whenMatchedAnd(condition(sql));
|
||||
}
|
||||
|
||||
@Override
|
||||
public final MergeImpl whenMatchedAnd(String sql, Object... bindings) {
|
||||
return whenMatchedAnd(condition(sql, bindings));
|
||||
}
|
||||
|
||||
@Override
|
||||
public final MergeImpl whenMatchedAnd(String sql, QueryPart... parts) {
|
||||
return whenMatchedAnd(condition(sql, parts));
|
||||
}
|
||||
|
||||
@Override
|
||||
public final MergeImpl thenUpdate() {
|
||||
return this;
|
||||
}
|
||||
|
||||
@Override
|
||||
public final <T> MergeImpl set(Field<T> field, T value) {
|
||||
return set(field, Tools.field(value, field));
|
||||
@ -931,7 +978,7 @@ implements
|
||||
@Override
|
||||
public final <T> MergeImpl set(Field<T> field, Field<T> value) {
|
||||
if (matchedClause)
|
||||
matchedUpdate.put(field, nullSafe(value));
|
||||
getLastMatchedUpdate().put(field, nullSafe(value));
|
||||
else if (notMatchedClause)
|
||||
notMatchedInsert.set(field, nullSafe(value));
|
||||
else
|
||||
@ -956,7 +1003,7 @@ implements
|
||||
@Override
|
||||
public final MergeImpl set(Map<?, ?> map) {
|
||||
if (matchedClause)
|
||||
matchedUpdate.set(map);
|
||||
getLastMatchedUpdate().set(map);
|
||||
else if (notMatchedClause)
|
||||
notMatchedInsert.set(map);
|
||||
else
|
||||
@ -1525,18 +1572,25 @@ implements
|
||||
.start(MERGE_SET);
|
||||
|
||||
// [#999] WHEN MATCHED clause is optional
|
||||
if (matchedUpdate != null) {
|
||||
for (int i = 0; i < matchedUpdate.size(); i++) {
|
||||
FieldMapForUpdate map = matchedUpdate.get(i);
|
||||
Condition condition = matchedUpdateAnd.get(i);
|
||||
|
||||
ctx.formatSeparator()
|
||||
.visit(K_WHEN).sql(' ').visit(K_MATCHED);
|
||||
|
||||
// [#5110] Standard SQL "WHERE" clause in updates
|
||||
if (matchedWhere != null && NO_SUPPORT_WHERE.contains(ctx.family()))
|
||||
// [#7291] Standard SQL AND clause in updates
|
||||
if (condition != null)
|
||||
ctx.sql(' ').visit(K_AND).sql(' ').visit(condition);
|
||||
|
||||
// [#5110] Oracle style "WHERE" clause in updates
|
||||
else if (matchedWhere != null && NO_SUPPORT_WHERE.contains(ctx.family()))
|
||||
ctx.sql(' ').visit(K_AND).sql(' ').visit(matchedWhere);
|
||||
|
||||
ctx.sql(' ').visit(K_THEN).sql(' ').visit(K_UPDATE).sql(' ').visit(K_SET)
|
||||
.formatIndentStart()
|
||||
.formatSeparator()
|
||||
.visit(matchedUpdate)
|
||||
.visit(map)
|
||||
.formatIndentEnd();
|
||||
}
|
||||
|
||||
|
||||
Loading…
Reference in New Issue
Block a user