diff --git a/jOOQ/src/main/java/org/jooq/UpdateFromStep.java b/jOOQ/src/main/java/org/jooq/UpdateFromStep.java index a6968666d3..34ebcea2dd 100644 --- a/jOOQ/src/main/java/org/jooq/UpdateFromStep.java +++ b/jOOQ/src/main/java/org/jooq/UpdateFromStep.java @@ -41,6 +41,15 @@ package org.jooq; // ... // ... // ... +import static org.jooq.SQLDialect.CUBRID; +// ... +import static org.jooq.SQLDialect.DERBY; +// ... +import static org.jooq.SQLDialect.FIREBIRD; +import static org.jooq.SQLDialect.H2; +// ... +import static org.jooq.SQLDialect.HSQLDB; +// ... // ... // ... import static org.jooq.SQLDialect.POSTGRES; @@ -48,6 +57,8 @@ import static org.jooq.SQLDialect.POSTGRES; import static org.jooq.SQLDialect.SQLITE; // ... // ... +// ... +// ... import java.util.Collection; @@ -94,21 +105,21 @@ public interface UpdateFromStep extends UpdateWhereStep { * Add a FROM clause to the query. */ @NotNull @CheckReturnValue - @Support({ POSTGRES, SQLITE }) + @Support({ CUBRID, DERBY, FIREBIRD, H2, HSQLDB, POSTGRES, SQLITE }) UpdateWhereStep from(TableLike table); /** * Add a FROM clause to the query. */ @NotNull @CheckReturnValue - @Support({ POSTGRES, SQLITE }) + @Support({ CUBRID, DERBY, FIREBIRD, H2, HSQLDB, POSTGRES, SQLITE }) UpdateWhereStep from(TableLike... table); /** * Add a FROM clause to the query. */ @NotNull @CheckReturnValue - @Support({ POSTGRES, SQLITE }) + @Support({ CUBRID, DERBY, FIREBIRD, H2, HSQLDB, POSTGRES, SQLITE }) UpdateWhereStep from(Collection> tables); /** @@ -123,7 +134,7 @@ public interface UpdateFromStep extends UpdateWhereStep { * @see SQL */ @NotNull @CheckReturnValue - @Support({ POSTGRES, SQLITE }) + @Support({ CUBRID, DERBY, FIREBIRD, H2, HSQLDB, POSTGRES, SQLITE }) @PlainSQL UpdateWhereStep from(SQL sql); @@ -139,7 +150,7 @@ public interface UpdateFromStep extends UpdateWhereStep { * @see SQL */ @NotNull @CheckReturnValue - @Support({ POSTGRES, SQLITE }) + @Support({ CUBRID, DERBY, FIREBIRD, H2, HSQLDB, POSTGRES, SQLITE }) @PlainSQL UpdateWhereStep from(String sql); @@ -156,7 +167,7 @@ public interface UpdateFromStep extends UpdateWhereStep { * @see SQL */ @NotNull @CheckReturnValue - @Support({ POSTGRES, SQLITE }) + @Support({ CUBRID, DERBY, FIREBIRD, H2, HSQLDB, POSTGRES, SQLITE }) @PlainSQL UpdateWhereStep from(String sql, Object... bindings); @@ -173,7 +184,7 @@ public interface UpdateFromStep extends UpdateWhereStep { * @see SQL */ @NotNull @CheckReturnValue - @Support({ POSTGRES, SQLITE }) + @Support({ CUBRID, DERBY, FIREBIRD, H2, HSQLDB, POSTGRES, SQLITE }) @PlainSQL UpdateWhereStep from(String sql, QueryPart... parts); @@ -183,6 +194,6 @@ public interface UpdateFromStep extends UpdateWhereStep { * @see DSL#table(Name) */ @NotNull @CheckReturnValue - @Support({ POSTGRES, SQLITE }) + @Support({ CUBRID, DERBY, FIREBIRD, H2, HSQLDB, POSTGRES, SQLITE }) UpdateWhereStep from(Name name); } diff --git a/jOOQ/src/main/java/org/jooq/UpdateQuery.java b/jOOQ/src/main/java/org/jooq/UpdateQuery.java index 284b32b2cc..94fe498403 100644 --- a/jOOQ/src/main/java/org/jooq/UpdateQuery.java +++ b/jOOQ/src/main/java/org/jooq/UpdateQuery.java @@ -42,19 +42,26 @@ package org.jooq; // ... // ... // ... +import static org.jooq.SQLDialect.CUBRID; +// ... +import static org.jooq.SQLDialect.DERBY; // ... import static org.jooq.SQLDialect.FIREBIRD; +// ... import static org.jooq.SQLDialect.H2; // ... import static org.jooq.SQLDialect.HSQLDB; // ... // ... +// ... import static org.jooq.SQLDialect.POSTGRES; // ... // ... import static org.jooq.SQLDialect.SQLITE; // ... // ... +// ... +// ... import static org.jooq.SQLDialect.YUGABYTEDB; import java.util.Collection; @@ -362,7 +369,7 @@ public interface UpdateQuery extends StoreQuery, ConditionP * * @param from The added tables */ - @Support({ POSTGRES, SQLITE, YUGABYTEDB }) + @Support({ CUBRID, DERBY, FIREBIRD, H2, HSQLDB, POSTGRES, SQLITE }) void addFrom(TableLike from); /** @@ -370,7 +377,7 @@ public interface UpdateQuery extends StoreQuery, ConditionP * * @param from The added tables */ - @Support({ POSTGRES, SQLITE, YUGABYTEDB }) + @Support({ CUBRID, DERBY, FIREBIRD, H2, HSQLDB, POSTGRES, SQLITE }) void addFrom(TableLike... from); /** @@ -378,7 +385,7 @@ public interface UpdateQuery extends StoreQuery, ConditionP * * @param from The added tables */ - @Support({ POSTGRES, SQLITE, YUGABYTEDB }) + @Support({ CUBRID, DERBY, FIREBIRD, H2, HSQLDB, POSTGRES, SQLITE }) void addFrom(Collection> from); // ------------------------------------------------------------------------ diff --git a/jOOQ/src/main/java/org/jooq/impl/UpdateQueryImpl.java b/jOOQ/src/main/java/org/jooq/impl/UpdateQueryImpl.java index 07aac0ba05..574f486af0 100644 --- a/jOOQ/src/main/java/org/jooq/impl/UpdateQueryImpl.java +++ b/jOOQ/src/main/java/org/jooq/impl/UpdateQueryImpl.java @@ -52,9 +52,11 @@ import static org.jooq.Clause.UPDATE_WHERE; // ... import static org.jooq.SQLDialect.CUBRID; // ... +// ... import static org.jooq.SQLDialect.DERBY; // ... import static org.jooq.SQLDialect.FIREBIRD; +// ... import static org.jooq.SQLDialect.H2; // ... import static org.jooq.SQLDialect.HSQLDB; @@ -74,6 +76,7 @@ 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.mergeInto; import static org.jooq.impl.DSL.name; import static org.jooq.impl.DSL.row; import static org.jooq.impl.DSL.select; @@ -89,8 +92,10 @@ import static org.jooq.impl.Tools.findAny; import java.util.Arrays; import java.util.Collection; import java.util.Map; +import java.util.Map.Entry; import java.util.Set; import java.util.function.Consumer; +import java.util.function.Function; import org.jooq.Clause; import org.jooq.Condition; @@ -102,6 +107,7 @@ import org.jooq.FieldOrRowOrSelect; import org.jooq.Operator; import org.jooq.OrderField; // ... +import org.jooq.QueryPart; import org.jooq.Record; import org.jooq.Record1; import org.jooq.Record10; @@ -153,6 +159,7 @@ import org.jooq.SQLDialect; import org.jooq.Scope; import org.jooq.Select; import org.jooq.Table; +import org.jooq.TableField; import org.jooq.TableLike; import org.jooq.UpdateQuery; import org.jooq.impl.FieldMapForUpdate.SetClause; @@ -177,6 +184,8 @@ implements + private static final Set EMULATE_FROM_WITH_MERGE = SQLDialect.supportedBy(CUBRID, DERBY, FIREBIRD, H2, HSQLDB); + // LIMIT is not supported at all private static final Set NO_SUPPORT_LIMIT = SQLDialect.supportedUntil(CUBRID, DERBY, FIREBIRD, H2, HSQLDB, POSTGRES, SQLITE, YUGABYTEDB); @@ -530,6 +539,11 @@ implements @Override final void accept0(Context ctx) { + if (!from.isEmpty() && EMULATE_FROM_WITH_MERGE.contains(ctx.dialect())) { + acceptFromAsMerge(ctx); + return; + } + @@ -544,6 +558,45 @@ implements accept1(ctx); } + private final void acceptFromAsMerge(Context ctx) { + // TODO: What about RETURNING? + // TODO: What if there are multiple FROM tables? + // TODO: What if there are SET ROW = ROW assignment(s)? + // TODO: What if there are SET ROW = (SELECT ..) assignment(s)? + + Table s; + boolean patchSource = true; + Condition c = condition; + FieldMapForUpdate um = updateMap; + + if (orderBy.isEmpty() && limit == null) { + if (from.size() == 1 && from.get(0) instanceof TableImpl && !(patchSource = false)) + s = from.get(0); + else + s = select().from(from).asTable("s"); + } + else + s = select().from(from).orderBy(orderBy).limit(limit).asTable("s"); + + if (patchSource && ctx.configuration().requireCommercial(() -> "The UPDATE .. FROM to MERGE transformation requires commercial only logic. Please upgrade to the jOOQ Professional Edition or jOOQ Enterprise Edition")) { + + + + + + + + + + + + + + } + + ctx.visit(mergeInto(table).using(s).on(c).whenMatchedThenUpdate().set(um)); + } + private final UpdateQueryImpl copy(Consumer> consumer) { UpdateQueryImpl u = new UpdateQueryImpl<>(configuration(), with, table);