[jOOQ/jOOQ#15632] Support INSERT .. ON DUPLICATE KEY UPDATE
This commit is contained in:
parent
6e26879228
commit
2923e4aa77
@ -254,7 +254,6 @@ implements
|
||||
ctx.scopeStart(this);
|
||||
|
||||
// [#2682] [#15632] Apply inline derived tables to the target table
|
||||
// [#15632] TODO: Check if this behaves correctly with aliases
|
||||
// [#15632] TODO: Refactor this logic with UpdateQueryImpl
|
||||
Table<?> t = table(ctx);
|
||||
Table<?> i = InlineDerivedTable.inlineDerivedTable(ctx, t);
|
||||
|
||||
@ -43,14 +43,25 @@ import static org.jooq.impl.DSL.table;
|
||||
import static org.jooq.impl.Tools.anyMatch;
|
||||
import static org.jooq.tools.StringUtils.defaultIfNull;
|
||||
|
||||
import java.util.List;
|
||||
|
||||
import org.jooq.Check;
|
||||
import org.jooq.Condition;
|
||||
import org.jooq.Context;
|
||||
import org.jooq.ForeignKey;
|
||||
import org.jooq.Identity;
|
||||
import org.jooq.Index;
|
||||
import org.jooq.QueryPart;
|
||||
import org.jooq.Record;
|
||||
// ...
|
||||
import org.jooq.Select;
|
||||
import org.jooq.Table;
|
||||
import org.jooq.TableField;
|
||||
// ...
|
||||
import org.jooq.UniqueKey;
|
||||
|
||||
import org.jetbrains.annotations.NotNull;
|
||||
import org.jetbrains.annotations.Nullable;
|
||||
|
||||
/**
|
||||
* @author Lukas Eder
|
||||
@ -62,7 +73,7 @@ final class InlineDerivedTable<R extends Record> extends DerivedTable<R> {
|
||||
final boolean policyGenerated;
|
||||
|
||||
InlineDerivedTable(TableImpl<R> t) {
|
||||
this(removeWhere(t), t.where, false);
|
||||
this(t.where((Condition) null), t.where, false);
|
||||
}
|
||||
|
||||
InlineDerivedTable(Table<R> table, Condition condition, boolean policyGenerated) {
|
||||
@ -241,25 +252,6 @@ final class InlineDerivedTable<R extends Record> extends DerivedTable<R> {
|
||||
return null;
|
||||
}
|
||||
|
||||
private static final <R extends Record> Table<R> removeWhere(Table<R> t) {
|
||||
if (t instanceof TableImpl<R> i) {
|
||||
return new TableImpl<>(
|
||||
i.getQualifiedName(),
|
||||
i.getSchema(),
|
||||
i.path,
|
||||
i.childPath,
|
||||
i.parentPath,
|
||||
i.alias != null ? removeWhere(i.alias.wrapped) : null,
|
||||
i.parameters,
|
||||
i.getCommentPart(),
|
||||
i.getOptions(),
|
||||
null
|
||||
);
|
||||
}
|
||||
else
|
||||
return t;
|
||||
}
|
||||
|
||||
@Override
|
||||
final FieldsImpl<R> fields0() {
|
||||
|
||||
|
||||
@ -66,7 +66,6 @@ import static org.jooq.SQLDialect.MYSQL;
|
||||
import static org.jooq.SQLDialect.POSTGRES;
|
||||
// ...
|
||||
// ...
|
||||
// ...
|
||||
import static org.jooq.SQLDialect.SQLITE;
|
||||
// ...
|
||||
// ...
|
||||
@ -83,7 +82,6 @@ import static org.jooq.impl.DSL.select;
|
||||
import static org.jooq.impl.DSL.selectFrom;
|
||||
import static org.jooq.impl.DSL.selectOne;
|
||||
import static org.jooq.impl.FieldMapsForInsert.toSQLInsertSelect;
|
||||
import static org.jooq.impl.InlineDerivedTable.inlineDerivedTable;
|
||||
import static org.jooq.impl.Keywords.K_AS;
|
||||
import static org.jooq.impl.Keywords.K_DEFAULT;
|
||||
import static org.jooq.impl.Keywords.K_DEFAULT_VALUES;
|
||||
@ -99,7 +97,6 @@ import static org.jooq.impl.Keywords.K_SET;
|
||||
import static org.jooq.impl.Keywords.K_VALUES;
|
||||
import static org.jooq.impl.Keywords.K_WHERE;
|
||||
import static org.jooq.impl.QueryPartListView.wrap;
|
||||
import static org.jooq.impl.Tools.aliased;
|
||||
import static org.jooq.impl.Tools.aliasedFields;
|
||||
import static org.jooq.impl.Tools.anyMatch;
|
||||
import static org.jooq.impl.Tools.collect;
|
||||
@ -108,6 +105,7 @@ import static org.jooq.impl.Tools.flattenCollection;
|
||||
import static org.jooq.impl.Tools.map;
|
||||
import static org.jooq.impl.Tools.orElse;
|
||||
import static org.jooq.impl.Tools.qualify;
|
||||
import static org.jooq.impl.Tools.unalias;
|
||||
import static org.jooq.impl.Tools.unqualified;
|
||||
import static org.jooq.impl.Tools.BooleanDataKey.DATA_CONSTRAINT_REFERENCE;
|
||||
import static org.jooq.impl.Tools.BooleanDataKey.DATA_INSERT_SELECT;
|
||||
@ -119,18 +117,15 @@ import static org.jooq.tools.StringUtils.defaultIfNull;
|
||||
import java.util.ArrayList;
|
||||
import java.util.Arrays;
|
||||
import java.util.Collection;
|
||||
import java.util.Collections;
|
||||
import java.util.HashMap;
|
||||
import java.util.Iterator;
|
||||
import java.util.LinkedHashMap;
|
||||
import java.util.List;
|
||||
import java.util.Map;
|
||||
import java.util.Map.Entry;
|
||||
import java.util.Objects;
|
||||
import java.util.function.Consumer;
|
||||
import java.util.Set;
|
||||
import java.util.function.Consumer;
|
||||
|
||||
import org.jooq.CheckReturnValue;
|
||||
import org.jooq.Clause;
|
||||
import org.jooq.Condition;
|
||||
import org.jooq.Configuration;
|
||||
@ -150,7 +145,6 @@ import org.jooq.Operator;
|
||||
import org.jooq.QueryPart;
|
||||
import org.jooq.Record;
|
||||
// ...
|
||||
// ...
|
||||
import org.jooq.Row;
|
||||
import org.jooq.SQLDialect;
|
||||
import org.jooq.Scope;
|
||||
@ -158,22 +152,17 @@ import org.jooq.Select;
|
||||
import org.jooq.Table;
|
||||
import org.jooq.TableField;
|
||||
// ...
|
||||
// ...
|
||||
import org.jooq.UniqueKey;
|
||||
import org.jooq.conf.ParamType;
|
||||
import org.jooq.conf.WriteIfReadonly;
|
||||
import org.jooq.impl.FieldMapForUpdate.SetClause;
|
||||
import org.jooq.impl.QOM.Insert;
|
||||
import org.jooq.impl.QOM.UNotYetImplemented;
|
||||
import org.jooq.impl.QOM.UnmodifiableList;
|
||||
import org.jooq.impl.QOM.UnmodifiableMap;
|
||||
import org.jooq.impl.QOM.With;
|
||||
import org.jooq.impl.Tools.BooleanDataKey;
|
||||
import org.jooq.impl.Tools.ExtendedDataKey;
|
||||
import org.jooq.tools.StringUtils;
|
||||
|
||||
import org.jetbrains.annotations.NotNull;
|
||||
import org.jetbrains.annotations.Nullable;
|
||||
|
||||
/**
|
||||
* @author Lukas Eder
|
||||
*/
|
||||
@ -385,12 +374,12 @@ implements
|
||||
insertMaps.set(map);
|
||||
}
|
||||
|
||||
@SuppressWarnings({ "rawtypes", "unchecked" })
|
||||
@Override
|
||||
public final void accept(Context<?> ctx) {
|
||||
ctx.scopeStart(this);
|
||||
|
||||
// [#2682] [#15632] Apply inline derived tables to the target table (TODO: Apply also to FROM, etc.)
|
||||
// [#15632] TODO: Check if this behaves correctly with aliases
|
||||
// [#2682] [#15632] Apply inline derived tables to the target table
|
||||
Table<?> t = InlineDerivedTable.inlineDerivedTable(ctx, table(ctx));
|
||||
if (t instanceof InlineDerivedTable<?> i) {
|
||||
copy(
|
||||
@ -399,7 +388,36 @@ implements
|
||||
|
||||
// [#15632] SchemaMapping could produce a different table than the one contained
|
||||
// in the inline derived table specification, and the alias must reflect that
|
||||
Table<?> m = DSL.table(defaultIfNull(ctx.dsl().map(i.table), i.table).getUnqualifiedName());
|
||||
Table<?> m = DSL.table(name("t"));
|
||||
|
||||
if ((onDuplicateKeyIgnore || onDuplicateKeyUpdate) && ctx.configuration().requireCommercial(() -> "InlineDerivedTable emulation for INSERT .. ON DUPLICATE KEY clauses is available in the commercial jOOQ editions only")) {
|
||||
|
||||
// [pro] */
|
||||
// [#15632] The i.condition may reference columns that aren't part of d.insertMaps, so
|
||||
// we have to synthetically add explicit defaults for any known fields.
|
||||
List<Field<?>> fields = (List) i.condition.$traverse(Traversers.findingAll(p -> p instanceof TableField<?, ?> tf
|
||||
? tf.getTable() == null || unalias(i.table).equals(unalias(tf.getTable()))
|
||||
: false
|
||||
));
|
||||
for (Field<?> f : fields) {
|
||||
if (!d.insertMaps.values.containsKey(f))
|
||||
d.addValue(f, (Field) f.getDataType().default_());
|
||||
}
|
||||
|
||||
// [#15632] Don't allow for values to be created that don't match the InlineDerivedTable or policy
|
||||
Condition c, c2;
|
||||
c = c2 = i.condition;
|
||||
for (Entry<?, ?> e : d.updateMap.entrySet()) {
|
||||
c2 = (Condition) c2.$replace(q -> e.getKey().equals(q)
|
||||
? (QueryPart) e.getValue()
|
||||
: q
|
||||
);
|
||||
}
|
||||
|
||||
if (c2 != c)
|
||||
d.addConditions(c2);
|
||||
/* [/pro] */
|
||||
}
|
||||
|
||||
d.select =
|
||||
selectFrom(
|
||||
@ -409,7 +427,9 @@ implements
|
||||
|
||||
// [#15632] Map the original table reference to the derived table alias
|
||||
// to prevent schema mapping in the condition.
|
||||
.scopeRegister(i.table, false, m).visit(i.condition)
|
||||
.scopeRegister(i.table, false, m)
|
||||
.visit(i.condition)
|
||||
.scopeRegister(i.table, false, null)
|
||||
));
|
||||
}
|
||||
},
|
||||
|
||||
@ -156,7 +156,6 @@ import static org.jooq.impl.DSL.regexpReplaceAll;
|
||||
import static org.jooq.impl.DSL.row;
|
||||
import static org.jooq.impl.DSL.rowNumber;
|
||||
// ...
|
||||
import static org.jooq.impl.DSL.selectFrom;
|
||||
import static org.jooq.impl.DSL.table;
|
||||
import static org.jooq.impl.DSL.trueCondition;
|
||||
import static org.jooq.impl.DSL.unquotedName;
|
||||
@ -218,7 +217,6 @@ import static org.jooq.impl.Tools.selectQueryImpl;
|
||||
import static org.jooq.impl.Tools.traverseJoins;
|
||||
import static org.jooq.impl.Tools.unalias;
|
||||
import static org.jooq.impl.Tools.unqualified;
|
||||
import static org.jooq.impl.Tools.unwrap;
|
||||
import static org.jooq.impl.Tools.BooleanDataKey.DATA_COLLECT_SEMI_ANTI_JOIN;
|
||||
import static org.jooq.impl.Tools.BooleanDataKey.DATA_FORCE_LIMIT_WITH_ORDER_BY;
|
||||
import static org.jooq.impl.Tools.BooleanDataKey.DATA_INSERT_SELECT;
|
||||
@ -287,12 +285,10 @@ import org.jooq.Operator;
|
||||
import org.jooq.OrderField;
|
||||
import org.jooq.Param;
|
||||
// ...
|
||||
// ...
|
||||
import org.jooq.QualifiedAsterisk;
|
||||
import org.jooq.QueryPart;
|
||||
import org.jooq.Record;
|
||||
// ...
|
||||
// ...
|
||||
import org.jooq.Result;
|
||||
import org.jooq.Row;
|
||||
import org.jooq.SQLDialect;
|
||||
|
||||
@ -91,9 +91,7 @@ import static org.jooq.impl.DSL.selectFrom;
|
||||
import static org.jooq.impl.DSL.trueCondition;
|
||||
import static org.jooq.impl.InlineDerivedTable.transformInlineDerivedTables;
|
||||
import static org.jooq.impl.Keywords.K_FROM;
|
||||
import static org.jooq.impl.Keywords.K_LIMIT;
|
||||
import static org.jooq.impl.Keywords.K_ORDER_BY;
|
||||
import static org.jooq.impl.Keywords.K_ROWS;
|
||||
import static org.jooq.impl.Keywords.K_SET;
|
||||
import static org.jooq.impl.Keywords.K_UPDATE;
|
||||
import static org.jooq.impl.Keywords.K_WHERE;
|
||||
@ -566,7 +564,6 @@ implements
|
||||
ctx.scopeStart(this);
|
||||
|
||||
// [#2682] [#15632] Apply inline derived tables to the target table
|
||||
// [#15632] TODO: Check if this behaves correctly with aliases
|
||||
// [#15632] TODO: Refactor this logic with DeleteQueryImpl
|
||||
Table<?> t = table(ctx);
|
||||
Table<?> i = InlineDerivedTable.inlineDerivedTable(ctx, t);
|
||||
|
||||
Loading…
Reference in New Issue
Block a user