diff --git a/jOOQ/src/main/java/org/jooq/impl/InsertQueryImpl.java b/jOOQ/src/main/java/org/jooq/impl/InsertQueryImpl.java index c180debcd2..504a3f367f 100644 --- a/jOOQ/src/main/java/org/jooq/impl/InsertQueryImpl.java +++ b/jOOQ/src/main/java/org/jooq/impl/InsertQueryImpl.java @@ -45,6 +45,7 @@ import static org.jooq.Clause.INSERT_SELECT; import static org.jooq.SQLDialect.MARIADB; import static org.jooq.SQLDialect.MYSQL; // ... +import static org.jooq.impl.DSL.dual; import static org.jooq.impl.DSL.select; import static org.jooq.impl.DSL.selectFrom; import static org.jooq.impl.DSL.selectOne; @@ -64,6 +65,7 @@ import static org.jooq.impl.Keywords.K_VALUES; import static org.jooq.impl.Keywords.K_WHERE; import static org.jooq.impl.Tools.EMPTY_FIELD; import static org.jooq.impl.Tools.aliasedFields; +import static org.jooq.impl.Tools.fieldNameStrings; import static org.jooq.impl.Tools.fieldNames; import static org.jooq.impl.Tools.DataKey.DATA_INSERT_SELECT_WITHOUT_INSERT_COLUMN_LIST; @@ -556,21 +558,32 @@ final class InsertQueryImpl extends AbstractStoreQuery impl private final Merge toMerge(Configuration configuration) { if (table.getPrimaryKey() != null) { - MergeOnConditionStep on = - create(configuration).mergeInto(table) - .usingDual() - .on(matchByPrimaryKey(insertMaps.lastMap())); + + // [#6375] INSERT .. VALUES and INSERT .. SELECT distinction also in MERGE + Table t = select == null + ? dual() + : table(select).as("t", fieldNameStrings(insertMaps.fields().toArray(EMPTY_FIELD))); + + MergeOnConditionStep on = select == null + ? create(configuration).mergeInto(table) + .usingDual() + .on(matchByPrimaryKey(insertMaps.lastMap())) + : create(configuration).mergeInto(table) + .using(t) + .on(matchByPrimaryKey(t)); // [#1295] Use UPDATE clause only when with ON DUPLICATE KEY UPDATE, - // not with ON DUPLICATE KEY IGNORE + // not with ON DUPLICATE KEY IGNORE MergeNotMatchedStep notMatched = on; - if (onDuplicateKeyUpdate) { + if (onDuplicateKeyUpdate) notMatched = on.whenMatchedThenUpdate() .set(updateMap); - } - return notMatched.whenNotMatchedThenInsert(insertMaps.fields()) - .values(insertMaps.lastMap().values()); + return select == null + ? notMatched.whenNotMatchedThenInsert(insertMaps.fields()) + .values(insertMaps.lastMap().values()) + : notMatched.whenNotMatchedThenInsert(insertMaps.fields()) + .values(t.fields()); } else { throw new IllegalStateException("The ON DUPLICATE KEY IGNORE/UPDATE clause cannot be emulated when inserting into non-updatable tables : " + table); @@ -589,7 +602,26 @@ final class InsertQueryImpl extends AbstractStoreQuery impl Field field = (Field) f; Field value = (Field) map.get(field); - Condition other = field.equal(value); + Condition other = field.eq(value); + result = (result == null) ? other : result.and(other); + } + + return result; + } + + /** + * Produce a {@link Condition} that matches existing rows by the inserted or + * updated primary key values. + */ + @SuppressWarnings("unchecked") + private final Condition matchByPrimaryKey(Table s) { + Condition result = null; + + for (Field f : table.getPrimaryKey().getFields()) { + Field field = (Field) f; + Field value = s.field(field); + + Condition other = field.eq(value); result = (result == null) ? other : result.and(other); } diff --git a/jOOQ/src/main/java/org/jooq/impl/Tools.java b/jOOQ/src/main/java/org/jooq/impl/Tools.java index 2e837db863..b9009f2113 100644 --- a/jOOQ/src/main/java/org/jooq/impl/Tools.java +++ b/jOOQ/src/main/java/org/jooq/impl/Tools.java @@ -906,6 +906,18 @@ final class Tools { return result; } + static final String[] fieldNameStrings(Field[] fields) { + if (fields == null) + return null; + + String[] result = new String[fields.length]; + + for (int i = 0; i < fields.length; i++) + result[i] = fields[i].getName(); + + return result; + } + static final Field[] fields(int length) { Field[] result = new Field[length]; Name[] names = fieldNames(length);