From 69f62e6b6971baa56e70961ce8bf0c844ffb289b Mon Sep 17 00:00:00 2001 From: Lukas Eder Date: Mon, 29 Aug 2022 16:32:35 +0200 Subject: [PATCH] [jOOQ/jOOQ#13928] Emulate UPDATE .. RETURNING in MariaDB 10.5+ using INSERT .. SELECT .. ON DUPLICATE KEY UPDATE .. RETURNING --- .../java/org/jooq/UpdateReturningStep.java | 55 ++++++++++--------- .../java/org/jooq/impl/AbstractDMLQuery.java | 2 +- .../java/org/jooq/impl/UpdateQueryImpl.java | 35 ++++++++++-- 3 files changed, 59 insertions(+), 33 deletions(-) diff --git a/jOOQ/src/main/java/org/jooq/UpdateReturningStep.java b/jOOQ/src/main/java/org/jooq/UpdateReturningStep.java index a215009787..eac9b517d1 100644 --- a/jOOQ/src/main/java/org/jooq/UpdateReturningStep.java +++ b/jOOQ/src/main/java/org/jooq/UpdateReturningStep.java @@ -45,6 +45,7 @@ import org.jetbrains.annotations.*; // ... import static org.jooq.SQLDialect.FIREBIRD; import static org.jooq.SQLDialect.H2; +import static org.jooq.SQLDialect.MARIADB; // ... import static org.jooq.SQLDialect.POSTGRES; // ... @@ -106,7 +107,7 @@ public interface UpdateReturningStep extends UpdateFinalStep returning(); /** @@ -126,7 +127,7 @@ public interface UpdateReturningStep extends UpdateFinalStep returning(SelectFieldOrAsterisk... fields); /** @@ -146,7 +147,7 @@ public interface UpdateReturningStep extends UpdateFinalStep returning(Collection fields); /** @@ -160,7 +161,7 @@ public interface UpdateReturningStep extends UpdateFinalStep returningResult(SelectFieldOrAsterisk... fields); /** @@ -174,7 +175,7 @@ public interface UpdateReturningStep extends UpdateFinalStep returningResult(Collection fields); @@ -189,7 +190,7 @@ public interface UpdateReturningStep extends UpdateFinalStep UpdateResultStep> returningResult(SelectField field1); /** @@ -202,7 +203,7 @@ public interface UpdateReturningStep extends UpdateFinalStep UpdateResultStep> returningResult(SelectField field1, SelectField field2); /** @@ -215,7 +216,7 @@ public interface UpdateReturningStep extends UpdateFinalStep UpdateResultStep> returningResult(SelectField field1, SelectField field2, SelectField field3); /** @@ -228,7 +229,7 @@ public interface UpdateReturningStep extends UpdateFinalStep UpdateResultStep> returningResult(SelectField field1, SelectField field2, SelectField field3, SelectField field4); /** @@ -241,7 +242,7 @@ public interface UpdateReturningStep extends UpdateFinalStep UpdateResultStep> returningResult(SelectField field1, SelectField field2, SelectField field3, SelectField field4, SelectField field5); /** @@ -254,7 +255,7 @@ public interface UpdateReturningStep extends UpdateFinalStep UpdateResultStep> returningResult(SelectField field1, SelectField field2, SelectField field3, SelectField field4, SelectField field5, SelectField field6); /** @@ -267,7 +268,7 @@ public interface UpdateReturningStep extends UpdateFinalStep UpdateResultStep> returningResult(SelectField field1, SelectField field2, SelectField field3, SelectField field4, SelectField field5, SelectField field6, SelectField field7); /** @@ -280,7 +281,7 @@ public interface UpdateReturningStep extends UpdateFinalStep UpdateResultStep> returningResult(SelectField field1, SelectField field2, SelectField field3, SelectField field4, SelectField field5, SelectField field6, SelectField field7, SelectField field8); /** @@ -293,7 +294,7 @@ public interface UpdateReturningStep extends UpdateFinalStep UpdateResultStep> returningResult(SelectField field1, SelectField field2, SelectField field3, SelectField field4, SelectField field5, SelectField field6, SelectField field7, SelectField field8, SelectField field9); /** @@ -306,7 +307,7 @@ public interface UpdateReturningStep extends UpdateFinalStep UpdateResultStep> returningResult(SelectField field1, SelectField field2, SelectField field3, SelectField field4, SelectField field5, SelectField field6, SelectField field7, SelectField field8, SelectField field9, SelectField field10); /** @@ -319,7 +320,7 @@ public interface UpdateReturningStep extends UpdateFinalStep UpdateResultStep> returningResult(SelectField field1, SelectField field2, SelectField field3, SelectField field4, SelectField field5, SelectField field6, SelectField field7, SelectField field8, SelectField field9, SelectField field10, SelectField field11); /** @@ -332,7 +333,7 @@ public interface UpdateReturningStep extends UpdateFinalStep UpdateResultStep> returningResult(SelectField field1, SelectField field2, SelectField field3, SelectField field4, SelectField field5, SelectField field6, SelectField field7, SelectField field8, SelectField field9, SelectField field10, SelectField field11, SelectField field12); /** @@ -345,7 +346,7 @@ public interface UpdateReturningStep extends UpdateFinalStep UpdateResultStep> returningResult(SelectField field1, SelectField field2, SelectField field3, SelectField field4, SelectField field5, SelectField field6, SelectField field7, SelectField field8, SelectField field9, SelectField field10, SelectField field11, SelectField field12, SelectField field13); /** @@ -358,7 +359,7 @@ public interface UpdateReturningStep extends UpdateFinalStep UpdateResultStep> returningResult(SelectField field1, SelectField field2, SelectField field3, SelectField field4, SelectField field5, SelectField field6, SelectField field7, SelectField field8, SelectField field9, SelectField field10, SelectField field11, SelectField field12, SelectField field13, SelectField field14); /** @@ -371,7 +372,7 @@ public interface UpdateReturningStep extends UpdateFinalStep UpdateResultStep> returningResult(SelectField field1, SelectField field2, SelectField field3, SelectField field4, SelectField field5, SelectField field6, SelectField field7, SelectField field8, SelectField field9, SelectField field10, SelectField field11, SelectField field12, SelectField field13, SelectField field14, SelectField field15); /** @@ -384,7 +385,7 @@ public interface UpdateReturningStep extends UpdateFinalStep UpdateResultStep> returningResult(SelectField field1, SelectField field2, SelectField field3, SelectField field4, SelectField field5, SelectField field6, SelectField field7, SelectField field8, SelectField field9, SelectField field10, SelectField field11, SelectField field12, SelectField field13, SelectField field14, SelectField field15, SelectField field16); /** @@ -397,7 +398,7 @@ public interface UpdateReturningStep extends UpdateFinalStep UpdateResultStep> returningResult(SelectField field1, SelectField field2, SelectField field3, SelectField field4, SelectField field5, SelectField field6, SelectField field7, SelectField field8, SelectField field9, SelectField field10, SelectField field11, SelectField field12, SelectField field13, SelectField field14, SelectField field15, SelectField field16, SelectField field17); /** @@ -410,7 +411,7 @@ public interface UpdateReturningStep extends UpdateFinalStep UpdateResultStep> returningResult(SelectField field1, SelectField field2, SelectField field3, SelectField field4, SelectField field5, SelectField field6, SelectField field7, SelectField field8, SelectField field9, SelectField field10, SelectField field11, SelectField field12, SelectField field13, SelectField field14, SelectField field15, SelectField field16, SelectField field17, SelectField field18); /** @@ -423,7 +424,7 @@ public interface UpdateReturningStep extends UpdateFinalStep UpdateResultStep> returningResult(SelectField field1, SelectField field2, SelectField field3, SelectField field4, SelectField field5, SelectField field6, SelectField field7, SelectField field8, SelectField field9, SelectField field10, SelectField field11, SelectField field12, SelectField field13, SelectField field14, SelectField field15, SelectField field16, SelectField field17, SelectField field18, SelectField field19); /** @@ -436,7 +437,7 @@ public interface UpdateReturningStep extends UpdateFinalStep UpdateResultStep> returningResult(SelectField field1, SelectField field2, SelectField field3, SelectField field4, SelectField field5, SelectField field6, SelectField field7, SelectField field8, SelectField field9, SelectField field10, SelectField field11, SelectField field12, SelectField field13, SelectField field14, SelectField field15, SelectField field16, SelectField field17, SelectField field18, SelectField field19, SelectField field20); /** @@ -449,7 +450,7 @@ public interface UpdateReturningStep extends UpdateFinalStep UpdateResultStep> returningResult(SelectField field1, SelectField field2, SelectField field3, SelectField field4, SelectField field5, SelectField field6, SelectField field7, SelectField field8, SelectField field9, SelectField field10, SelectField field11, SelectField field12, SelectField field13, SelectField field14, SelectField field15, SelectField field16, SelectField field17, SelectField field18, SelectField field19, SelectField field20, SelectField field21); /** @@ -462,7 +463,7 @@ public interface UpdateReturningStep extends UpdateFinalStep UpdateResultStep> returningResult(SelectField field1, SelectField field2, SelectField field3, SelectField field4, SelectField field5, SelectField field6, SelectField field7, SelectField field8, SelectField field9, SelectField field10, SelectField field11, SelectField field12, SelectField field13, SelectField field14, SelectField field15, SelectField field16, SelectField field17, SelectField field18, SelectField field19, SelectField field20, SelectField field21, SelectField field22); diff --git a/jOOQ/src/main/java/org/jooq/impl/AbstractDMLQuery.java b/jOOQ/src/main/java/org/jooq/impl/AbstractDMLQuery.java index a900e1b3e9..fb6681f238 100644 --- a/jOOQ/src/main/java/org/jooq/impl/AbstractDMLQuery.java +++ b/jOOQ/src/main/java/org/jooq/impl/AbstractDMLQuery.java @@ -179,7 +179,7 @@ abstract class AbstractDMLQuery extends AbstractRowCountQuery private static final Set NO_SUPPORT_INSERT_ALIASED_TABLE = SQLDialect.supportedBy(DERBY, FIREBIRD, H2, MARIADB, MYSQL); private static final Set NATIVE_SUPPORT_INSERT_RETURNING = SQLDialect.supportedBy(FIREBIRD, MARIADB, POSTGRES, YUGABYTEDB); - private static final Set NATIVE_SUPPORT_UPDATE_RETURNING = SQLDialect.supportedBy(FIREBIRD, POSTGRES, YUGABYTEDB); + private static final Set NATIVE_SUPPORT_UPDATE_RETURNING = SQLDialect.supportedBy(FIREBIRD, MARIADB, POSTGRES, YUGABYTEDB); private static final Set NATIVE_SUPPORT_DELETE_RETURNING = SQLDialect.supportedBy(FIREBIRD, MARIADB, POSTGRES, YUGABYTEDB); private static final Set NATIVE_SUPPORT_DATA_CHANGE_DELTA_TABLE = SQLDialect.supportedBy(H2); private static final Set NO_SUPPORT_FETCHING_KEYS = SQLDialect.supportedBy(IGNITE); diff --git a/jOOQ/src/main/java/org/jooq/impl/UpdateQueryImpl.java b/jOOQ/src/main/java/org/jooq/impl/UpdateQueryImpl.java index fe616e8b15..476d3a2806 100644 --- a/jOOQ/src/main/java/org/jooq/impl/UpdateQueryImpl.java +++ b/jOOQ/src/main/java/org/jooq/impl/UpdateQueryImpl.java @@ -63,6 +63,7 @@ import static org.jooq.SQLDialect.HSQLDB; import static org.jooq.SQLDialect.IGNITE; // ... // ... +import static org.jooq.SQLDialect.MARIADB; // ... // ... import static org.jooq.SQLDialect.POSTGRES; @@ -76,10 +77,14 @@ import static org.jooq.SQLDialect.SQLITE; // ... import static org.jooq.SQLDialect.YUGABYTEDB; import static org.jooq.conf.SettingsTools.getExecuteUpdateWithoutWhere; +import static org.jooq.impl.DSL.insertInto; import static org.jooq.impl.DSL.mergeInto; import static org.jooq.impl.DSL.name; +import static org.jooq.impl.DSL.noCondition; +import static org.jooq.impl.DSL.noField; import static org.jooq.impl.DSL.row; import static org.jooq.impl.DSL.select; +import static org.jooq.impl.DSL.selectFrom; import static org.jooq.impl.DSL.trueCondition; import static org.jooq.impl.Keywords.K_FROM; import static org.jooq.impl.Keywords.K_LIMIT; @@ -87,6 +92,7 @@ import static org.jooq.impl.Keywords.K_ORDER_BY; import static org.jooq.impl.Keywords.K_SET; import static org.jooq.impl.Keywords.K_UPDATE; import static org.jooq.impl.Keywords.K_WHERE; +import static org.jooq.impl.SQLDataType.INTEGER; import static org.jooq.impl.Tools.findAny; import java.util.Arrays; @@ -176,7 +182,7 @@ implements UNotYetImplemented { - private static final Clause[] CLAUSES = { UPDATE }; + private static final Clause[] CLAUSES = { UPDATE }; @@ -184,14 +190,15 @@ implements - private static final Set EMULATE_FROM_WITH_MERGE = SQLDialect.supportedBy(CUBRID, DERBY, FIREBIRD, H2, HSQLDB); + private static final Set EMULATE_FROM_WITH_MERGE = SQLDialect.supportedBy(CUBRID, DERBY, FIREBIRD, H2, HSQLDB); + private static final Set EMULATE_RETURNING_WITH_UPSERT = SQLDialect.supportedBy(MARIADB); // LIMIT is not supported at all - private static final Set NO_SUPPORT_LIMIT = SQLDialect.supportedUntil(CUBRID, DERBY, FIREBIRD, H2, HSQLDB, POSTGRES, SQLITE, YUGABYTEDB); + private static final Set NO_SUPPORT_LIMIT = SQLDialect.supportedUntil(CUBRID, DERBY, FIREBIRD, H2, HSQLDB, POSTGRES, SQLITE, YUGABYTEDB); // LIMIT is supported but not ORDER BY - private static final Set NO_SUPPORT_ORDER_BY_LIMIT = SQLDialect.supportedBy(IGNITE); - static final Set NO_SUPPORT_UPDATE_JOIN = SQLDialect.supportedBy(CUBRID, DERBY, FIREBIRD, H2, HSQLDB, IGNITE, POSTGRES, SQLITE, YUGABYTEDB); + private static final Set NO_SUPPORT_ORDER_BY_LIMIT = SQLDialect.supportedBy(IGNITE); + static final Set NO_SUPPORT_UPDATE_JOIN = SQLDialect.supportedBy(CUBRID, DERBY, FIREBIRD, H2, HSQLDB, IGNITE, POSTGRES, SQLITE, YUGABYTEDB); private final FieldMapForUpdate updateMap; private final TableList from; @@ -547,6 +554,10 @@ implements acceptFromAsMerge(ctx); return; } + else if (!returning.isEmpty() && EMULATE_RETURNING_WITH_UPSERT.contains(ctx.dialect())) { + acceptReturningAsUpsert(ctx); + return; + } @@ -562,6 +573,20 @@ implements accept1(ctx); } + private final void acceptReturningAsUpsert(Context ctx) { + ctx.visit( + insertInto(table) + .select( + selectFrom(table) + .where(hasWhere() ? getWhere() : noCondition()) + .orderBy(orderBy) + .limit(limit != null ? limit : noField(INTEGER))) + .onDuplicateKeyUpdate() + .set(updateMap) + .returning(returning) + ); + } + private final void acceptFromAsMerge(Context ctx) { // TODO: What about RETURNING? // TODO: What if there are multiple FROM tables?