[jOOQ/jOOQ#13640] Add DML statement QOM API

This includes:
- Delete
- DeleteReturning
- Insert
- InsertReturning
- Update
- UpdateReturning
This commit is contained in:
Lukas Eder 2022-10-28 18:07:37 +02:00
parent cfc7a4b7e7
commit 3daf6a1d6f
21 changed files with 1635 additions and 137 deletions

View File

@ -77,22 +77,18 @@ import org.jetbrains.annotations.NotNull;
*
* @author Lukas Eder
*/
final class DMLQueryAsResultQuery<R extends Record, Q extends AbstractDMLQuery<R>>
abstract class AbstractDMLQueryAsResultQuery<R extends Record, Q extends AbstractDMLQuery<R>>
extends
AbstractQueryPart
implements
ResultQueryTrait<R>,
DeleteResultStep<R>,
UpdateResultStep<R>,
InsertResultStep<R>,
UNotYetImplemented
ResultQueryTrait<R>
{
private final Q delegate;
private final boolean returningResult;
private Table<?> coerceTable;
private Collection<? extends Field<?>> coerceFields;
final Q delegate;
final boolean returningResult;
Table<?> coerceTable;
Collection<? extends Field<?>> coerceFields;
DMLQueryAsResultQuery(Q delegate, boolean returningResult) {
AbstractDMLQueryAsResultQuery(Q delegate, boolean returningResult) {
this.delegate = delegate;
this.returningResult = returningResult;
}

View File

@ -37,28 +37,44 @@
*/
package org.jooq.impl;
import static org.jooq.impl.QOM.tuple;
import static org.jooq.impl.QOM.unmodifiable;
import static org.jooq.impl.Tools.map;
import java.util.Collection;
import java.util.LinkedHashMap;
import java.util.Map;
import java.util.Set;
import java.util.function.Function;
import org.jooq.Context;
import org.jooq.QueryPart;
// ...
// ...
import org.jooq.impl.QOM.Tuple2;
import org.jooq.impl.QOM.UnmodifiableList;
/**
* @author Lukas Eder
*/
abstract class AbstractQueryPartMap<K extends QueryPart, V extends QueryPart>
abstract sealed class AbstractQueryPartMap<K extends QueryPart, V extends QueryPart>
extends
AbstractQueryPart
implements
Map<K, V>
QOM.UnmodifiableMap<K, V>
permits
FieldMapForUpdate,
QueryPartMapView
{
private final Map<K, V> map;
AbstractQueryPartMap() {
map = new LinkedHashMap<>();
this(new LinkedHashMap<>());
}
AbstractQueryPartMap(Map<K, V> map) {
this.map = map;
}
// -------------------------------------------------------------------------
@ -131,4 +147,42 @@ implements
public final Set<Entry<K, V>> entrySet() {
return map.entrySet();
}
// -------------------------------------------------------------------------
// XXX: Query Object Model
// -------------------------------------------------------------------------
@Override
public final UnmodifiableList<Tuple2<K, V>> $tuples() {
return unmodifiable(map(entrySet(), e -> tuple(e.getKey(), e.getValue())));
}
abstract Function<? super Map<K, V>, ? extends AbstractQueryPartMap<K, V>> $construct();
}

View File

@ -65,7 +65,7 @@ import org.jooq.Record1;
// ...
import org.jooq.Select;
import org.jooq.impl.QOM.CaseSearched;
import org.jooq.impl.QOM.UTuple2;
import org.jooq.impl.QOM.Tuple2;
import org.jooq.impl.QOM.UnmodifiableList;
/**
@ -79,7 +79,7 @@ implements
QOM.CaseSearched<T>
{
private final List<UTuple2<Condition, Field<T>>> when;
private final List<Tuple2<Condition, Field<T>>> when;
private Field<T> else_;
CaseConditionStepImpl(DataType<T> type) {
@ -223,7 +223,7 @@ implements
ctx.visit(K_CASE)
.formatIndentStart();
for (UTuple2<Condition, Field<T>> e : when) {
for (Tuple2<Condition, Field<T>> e : when) {
Condition c = e.$1();
@ -263,7 +263,7 @@ implements
// -------------------------------------------------------------------------
@Override
public final Function2<? super UnmodifiableList<? extends UTuple2<Condition, Field<T>>>, ? super Field<T>, ? extends CaseSearched<T>> $constructor() {
public final Function2<? super UnmodifiableList<? extends Tuple2<Condition, Field<T>>>, ? super Field<T>, ? extends CaseSearched<T>> $constructor() {
return (w, e) -> {
CaseConditionStepImpl<T> r = new CaseConditionStepImpl<>(getDataType());
w.forEach(t -> r.when(t.$1(), t.$2()));
@ -273,12 +273,12 @@ implements
}
@Override
public final UnmodifiableList<? extends UTuple2<Condition, Field<T>>> $arg1() {
public final UnmodifiableList<? extends Tuple2<Condition, Field<T>>> $arg1() {
return QOM.unmodifiable(when);
}
@Override
public final CaseSearched<T> $arg1(UnmodifiableList<? extends UTuple2<Condition, Field<T>>> w) {
public final CaseSearched<T> $arg1(UnmodifiableList<? extends Tuple2<Condition, Field<T>>> w) {
return $constructor().apply(w, $else());
}

View File

@ -61,7 +61,7 @@ import org.jooq.Field;
import org.jooq.Function3;
// ...
import org.jooq.impl.QOM.CaseSimple;
import org.jooq.impl.QOM.UTuple2;
import org.jooq.impl.QOM.Tuple2;
import org.jooq.impl.QOM.UnmodifiableList;
/**
@ -76,7 +76,7 @@ implements
{
private final Field<V> value;
private final List<UTuple2<Field<V>, Field<T>>> when;
private final List<Tuple2<Field<V>, Field<T>>> when;
private Field<T> else_;
CaseWhenStepImpl(Field<V> value, Field<V> compareValue, Field<T> result) {
@ -237,7 +237,7 @@ implements
private final void acceptSearched(Context<?> ctx) {
CaseConditionStep<T> w = null;
for (UTuple2<Field<V>, Field<T>> e : when)
for (Tuple2<Field<V>, Field<T>> e : when)
if (w == null)
w = DSL.when(value.eq(e.$1()), e.$2());
else
@ -257,7 +257,7 @@ implements
.visit(value)
.formatIndentStart();
for (UTuple2<Field<V>, Field<T>> e : when)
for (Tuple2<Field<V>, Field<T>> e : when)
ctx.formatSeparator()
.visit(K_WHEN).sql(' ')
.visit(e.$1()).sql(' ')
@ -282,7 +282,7 @@ implements
// -------------------------------------------------------------------------
@Override
public final Function3<? super Field<V>, ? super UnmodifiableList<? extends UTuple2<Field<V>, Field<T>>>, ? super Field<T>, ? extends CaseSimple<V, T>> $constructor() {
public final Function3<? super Field<V>, ? super UnmodifiableList<? extends Tuple2<Field<V>, Field<T>>>, ? super Field<T>, ? extends CaseSimple<V, T>> $constructor() {
return (v, w, e) -> {
CaseWhenStepImpl<V, T> r = new CaseWhenStepImpl<>(v, getDataType());
w.forEach(t -> r.when(t.$1(), t.$2()));
@ -302,12 +302,12 @@ implements
}
@Override
public final UnmodifiableList<? extends UTuple2<Field<V>, Field<T>>> $arg2() {
public final UnmodifiableList<? extends Tuple2<Field<V>, Field<T>>> $arg2() {
return QOM.unmodifiable(when);
}
@Override
public final CaseSimple<V, T> $arg2(UnmodifiableList<? extends UTuple2<Field<V>, Field<T>>> w) {
public final CaseSimple<V, T> $arg2(UnmodifiableList<? extends Tuple2<Field<V>, Field<T>>> w) {
return $constructor().apply($value(), w, $else());
}

View File

@ -73,6 +73,15 @@ final class ConditionProviderImpl extends AbstractField<Boolean> implements Cond
this.condition = condition;
}
static final Condition extractCondition(Condition c) {
// join(..).on(..).and(..) uses some identity tricks to keep the right
// reference to the mutable ConditionProviderImpl instance, which we
// must take into account here.
return c instanceof ConditionProviderImpl cp ? cp.getWhere() : c;
}
@Nullable
final Condition getWhereOrNull() {
return hasWhere() ? condition : null;

View File

@ -0,0 +1,116 @@
/*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* https://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*
* Other licenses:
* -----------------------------------------------------------------------------
* Commercial licenses for this work are available. These replace the above
* ASL 2.0 and offer limited warranties, support, maintenance, and commercial
* database integrations.
*
* For more information, please visit: https://www.jooq.org/legal/licensing
*
*
*
*
*
*
*
*
*
*
*
*
*
*
*
*
*/
package org.jooq.impl;
import java.util.Collection;
import org.jooq.DeleteResultStep;
import org.jooq.QueryPart;
import org.jooq.Record;
// ...
import org.jooq.ResultQuery;
import org.jooq.SelectFieldOrAsterisk;
// ...
import org.jooq.impl.QOM.Delete;
import org.jooq.impl.QOM.DeleteReturning;
import org.jooq.impl.QOM.UnmodifiableList;
/**
* A wrapped {@link Delete} that works like a {@link ResultQuery}.
*
* @author Lukas Eder
*/
final class DeleteAsResultQuery<R extends Record>
extends
AbstractDMLQueryAsResultQuery<R, DeleteQueryImpl<R>>
implements
DeleteResultStep<R>,
QOM.DeleteReturning<R>
{
DeleteAsResultQuery(DeleteQueryImpl<R> delegate, boolean returningResult) {
super(delegate, returningResult);
}
@Override
public final Delete<?> $delete() {
return getDelegate();
}
@SuppressWarnings({ "rawtypes", "unchecked" })
@Override
public final DeleteReturning<R> $delete(Delete<?> newDelete) {
return new DeleteAsResultQuery(Tools.deleteQueryImpl(newDelete).copy(d -> d.setReturning($returning())), returningResult);
}
@Override
public final UnmodifiableList<? extends SelectFieldOrAsterisk> $returning() {
return QOM.unmodifiable(getDelegate().returning);
}
@Override
public final DeleteReturning<?> $returning(Collection<? extends SelectFieldOrAsterisk> returning) {
return new DeleteAsResultQuery<>(getDelegate().copy(d -> d.setReturning(returning)), returningResult);
}
}

View File

@ -54,7 +54,6 @@ import org.jooq.Field;
import org.jooq.Name;
import org.jooq.Operator;
import org.jooq.OrderField;
import org.jooq.Param;
import org.jooq.QueryPart;
import org.jooq.Record;
import org.jooq.Record1;
@ -79,24 +78,33 @@ import org.jooq.Record6;
import org.jooq.Record7;
import org.jooq.Record8;
import org.jooq.Record9;
// ...
import org.jooq.SQL;
import org.jooq.Select;
import org.jooq.SelectField;
import org.jooq.SelectFieldOrAsterisk;
import org.jooq.SortField;
import org.jooq.Table;
import org.jooq.TableLike;
// ...
import org.jooq.impl.QOM.Delete;
import org.jooq.impl.QOM.UnmodifiableList;
import org.jooq.impl.QOM.With;
/**
* @author Lukas Eder
*/
@SuppressWarnings({ "rawtypes", "unchecked" })
final class DeleteImpl<R extends Record>
extends AbstractDelegatingDMLQuery<R, DeleteQueryImpl<R>>
implements
extends
AbstractDelegatingDMLQuery<R, DeleteQueryImpl<R>>
implements
// Cascading interface implementations for Delete behaviour
DeleteUsingStep<R>,
DeleteConditionStep<R> {
DeleteConditionStep<R>,
QOM.Delete<R>
{
private boolean returningResult;
DeleteImpl(Configuration configuration, WithImpl with, Table<R> table) {
@ -333,33 +341,33 @@ final class DeleteImpl<R extends Record>
@Override
public final DeleteResultStep<R> returning() {
getDelegate().setReturning();
return new DMLQueryAsResultQuery<>(getDelegate(), returningResult);
return new DeleteAsResultQuery<>(getDelegate(), returningResult);
}
@Override
public final DeleteResultStep<R> returning(SelectFieldOrAsterisk... f) {
getDelegate().setReturning(f);
return new DMLQueryAsResultQuery<>(getDelegate(), returningResult);
return new DeleteAsResultQuery<>(getDelegate(), returningResult);
}
@Override
public final DeleteResultStep<R> returning(Collection<? extends SelectFieldOrAsterisk> f) {
getDelegate().setReturning(f);
return new DMLQueryAsResultQuery<>(getDelegate(), returningResult);
return new DeleteAsResultQuery<>(getDelegate(), returningResult);
}
@Override
public final DeleteResultStep<Record> returningResult(SelectFieldOrAsterisk... f) {
returningResult = true;
getDelegate().setReturning(f);
return new DMLQueryAsResultQuery(getDelegate(), returningResult);
return new DeleteAsResultQuery(getDelegate(), returningResult);
}
@Override
public final DeleteResultStep<Record> returningResult(Collection<? extends SelectFieldOrAsterisk> f) {
returningResult = true;
getDelegate().setReturning(f);
return new DMLQueryAsResultQuery(getDelegate(), returningResult);
return new DeleteAsResultQuery(getDelegate(), returningResult);
}
@ -475,4 +483,77 @@ final class DeleteImpl<R extends Record>
}
// -------------------------------------------------------------------------
// XXX: Query Object Model
// -------------------------------------------------------------------------
@Override
public final With $with() {
return getDelegate().$with();
}
@Override
public final Table<R> $from() {
return getDelegate().$from();
}
@Override
public final Delete<?> $from(Table<?> from) {
return getDelegate().$from(from);
}
@Override
public final UnmodifiableList<? extends Table<?>> $using() {
return getDelegate().$using();
}
@Override
public final Delete<R> $using(Collection<? extends Table<?>> using) {
return getDelegate().$using(using);
}
@Override
public final Condition $where() {
return getDelegate().$where();
}
@Override
public final Delete<R> $where(Condition condition) {
return getDelegate().$where(condition);
}
@Override
public final UnmodifiableList<? extends SortField<?>> $orderBy() {
return getDelegate().$orderBy();
}
@Override
public final Delete<R> $orderBy(Collection<? extends SortField<?>> orderBy) {
return getDelegate().$orderBy(orderBy);
}
@Override
public final Field<? extends Number> $limit() {
return getDelegate().$limit();
}
@Override
public final Delete<R> $limit(Field<? extends Number> limit) {
return getDelegate().$limit(limit);
}
}

View File

@ -50,7 +50,6 @@ import static org.jooq.Clause.DELETE_WHERE;
// ...
import static org.jooq.SQLDialect.CUBRID;
// ...
// ...
import static org.jooq.SQLDialect.DERBY;
// ...
import static org.jooq.SQLDialect.FIREBIRD;
@ -75,6 +74,7 @@ import static org.jooq.SQLDialect.SQLITE;
// ...
import static org.jooq.SQLDialect.YUGABYTEDB;
import static org.jooq.conf.SettingsTools.getExecuteDeleteWithoutWhere;
import static org.jooq.impl.ConditionProviderImpl.extractCondition;
import static org.jooq.impl.DSL.row;
import static org.jooq.impl.DSL.select;
import static org.jooq.impl.DSL.trueCondition;
@ -90,6 +90,7 @@ import static org.jooq.impl.Tools.traverseJoins;
import java.util.Arrays;
import java.util.Collection;
import java.util.Set;
import java.util.function.Consumer;
import org.jooq.Clause;
import org.jooq.Condition;
@ -99,20 +100,31 @@ import org.jooq.DeleteQuery;
import org.jooq.Field;
import org.jooq.Operator;
import org.jooq.OrderField;
import org.jooq.Param;
// ...
import org.jooq.QueryPart;
import org.jooq.Record;
// ...
import org.jooq.SQLDialect;
import org.jooq.Scope;
import org.jooq.SelectFieldOrAsterisk;
import org.jooq.SortField;
import org.jooq.Table;
import org.jooq.TableLike;
// ...
import org.jooq.conf.ParamType;
import org.jooq.impl.QOM.UNotYetImplemented;
import org.jooq.impl.QOM.Delete;
import org.jooq.impl.QOM.UnmodifiableList;
/**
* @author Lukas Eder
*/
final class DeleteQueryImpl<R extends Record> extends AbstractDMLQuery<R> implements DeleteQuery<R>, UNotYetImplemented {
final class DeleteQueryImpl<R extends Record>
extends
AbstractDMLQuery<R>
implements
DeleteQuery<R>,
QOM.Delete<R>
{
private static final Clause[] CLAUSES = { DELETE };
private static final Set<SQLDialect> SPECIAL_DELETE_AS_SYNTAX = SQLDialect.supportedBy(MARIADB, MYSQL);
@ -355,6 +367,136 @@ final class DeleteQueryImpl<R extends Record> extends AbstractDMLQuery<R> implem
return super.isExecutable();
}
// -------------------------------------------------------------------------
// XXX: Query Object Model
// -------------------------------------------------------------------------
final DeleteQueryImpl<R> copy(Consumer<? super DeleteQueryImpl<R>> finisher) {
return copy(finisher, table);
}
final <O extends Record> DeleteQueryImpl<O> copy(Consumer<? super DeleteQueryImpl<O>> finisher, Table<O> t) {
DeleteQueryImpl<O> r = new DeleteQueryImpl<>(configuration(), with, t);
r.using.addAll(using);
r.condition.addConditions(extractCondition(condition));
r.orderBy.addAll(orderBy);
r.limit = limit;
r.setReturning(returning);
finisher.accept(r);
return r;
}
@Override
public final WithImpl $with() {
return with;
}
@Override
public final Table<R> $from() {
return table;
}
@Override
public final Delete<?> $from(Table<?> newFrom) {
if ($from() == newFrom)
return this;
else
return copy(d -> {}, newFrom);
}
@Override
public final UnmodifiableList<? extends Table<?>> $using() {
return QOM.unmodifiable(using);
}
@Override
public final Delete<R> $using(Collection<? extends Table<?>> using) {
return copy(d -> {
d.using.clear();
d.using.addAll(using);
});
}
@Override
public final Condition $where() {
return condition.getWhereOrNull();
}
@Override
public final Delete<R> $where(Condition newWhere) {
if ($where() == newWhere)
return this;
else
return copy(d -> d.condition.setWhere(newWhere));
}
@Override
public final UnmodifiableList<? extends SortField<?>> $orderBy() {
return QOM.unmodifiable(orderBy);
}
@Override
public final Delete<R> $orderBy(Collection<? extends SortField<?>> newOrderBy) {
return copy(d -> {
d.orderBy.clear();
d.orderBy.addAll(newOrderBy);
});
}
@Override
public final Field<? extends Number> $limit() {
return limit;
}
@Override
public final Delete<R> $limit(Field<? extends Number> newLimit) {
if ($limit() == newLimit)
return this;
else
return copy(d -> d.limit = newLimit);
}

View File

@ -94,6 +94,7 @@ import java.util.LinkedHashSet;
import java.util.List;
import java.util.Map;
import java.util.Set;
import java.util.function.Function;
import org.jooq.Clause;
import org.jooq.Condition;
@ -115,7 +116,10 @@ import org.jooq.impl.QOM.UNotYetImplemented;
/**
* @author Lukas Eder
*/
final class FieldMapForUpdate extends AbstractQueryPartMap<FieldOrRow, FieldOrRowOrSelect> implements UNotYetImplemented {
final class FieldMapForUpdate
extends
AbstractQueryPartMap<FieldOrRow, FieldOrRowOrSelect>
{
static final Set<SQLDialect> CASTS_NEEDED = SQLDialect.supportedBy(POSTGRES, YUGABYTEDB);
static final Set<SQLDialect> NO_SUPPORT_QUALIFY = SQLDialect.supportedBy(POSTGRES, SQLITE, YUGABYTEDB);
@ -510,4 +514,17 @@ final class FieldMapForUpdate extends AbstractQueryPartMap<FieldOrRow, FieldOrRo
INSERT,
MERGE
}
// -------------------------------------------------------------------------
// XXX: Query Object Model
// -------------------------------------------------------------------------
@Override
final Function<? super Map<FieldOrRow, FieldOrRowOrSelect>, ? extends AbstractQueryPartMap<FieldOrRow, FieldOrRowOrSelect>> $construct() {
return m -> {
FieldMapForUpdate r = new FieldMapForUpdate(table, setClause, assignmentClause);
r.putAll(m);
return r;
};
}
}

View File

@ -117,6 +117,13 @@ final class FieldMapsForInsert extends AbstractQueryPart implements UNotYetImple
this.empty = new LinkedHashMap<>();
}
void clear() {
empty.clear();
values.clear();
rows = 0;
nextRow = -1;
}
// -------------------------------------------------------------------------
// The QueryPart API
// -------------------------------------------------------------------------

View File

@ -0,0 +1,119 @@
/*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* https://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*
* Other licenses:
* -----------------------------------------------------------------------------
* Commercial licenses for this work are available. These replace the above
* ASL 2.0 and offer limited warranties, support, maintenance, and commercial
* database integrations.
*
* For more information, please visit: https://www.jooq.org/legal/licensing
*
*
*
*
*
*
*
*
*
*
*
*
*
*
*
*
*/
package org.jooq.impl;
import java.util.Collection;
import org.jooq.DeleteResultStep;
import org.jooq.InsertResultStep;
import org.jooq.QueryPart;
import org.jooq.Record;
// ...
import org.jooq.ResultQuery;
import org.jooq.SelectFieldOrAsterisk;
// ...
import org.jooq.Update;
import org.jooq.impl.QOM.Insert;
import org.jooq.impl.QOM.InsertReturning;
import org.jooq.impl.QOM.UnmodifiableList;
/**
* A wrapped DML query ({@link Insert}, {@link Update}, {@link Delete}) that
* works like a {@link ResultQuery}.
*
* @author Lukas Eder
*/
final class InsertAsResultQuery<R extends Record>
extends
AbstractDMLQueryAsResultQuery<R, InsertQueryImpl<R>>
implements
InsertResultStep<R>,
QOM.InsertReturning<R>
{
InsertAsResultQuery(InsertQueryImpl<R> delegate, boolean returningResult) {
super(delegate, returningResult);
}
@Override
public final Insert<?> $insert() {
return getDelegate();
}
@SuppressWarnings({ "rawtypes", "unchecked" })
@Override
public final InsertReturning<R> $insert(Insert<?> newInsert) {
return new InsertAsResultQuery(Tools.insertQueryImpl(newInsert).copy(i -> i.setReturning($returning())), returningResult);
}
@Override
public final UnmodifiableList<? extends SelectFieldOrAsterisk> $returning() {
return QOM.unmodifiable(getDelegate().returning);
}
@Override
public final InsertReturning<?> $returning(Collection<? extends SelectFieldOrAsterisk> returning) {
return new InsertAsResultQuery<>(getDelegate().copy(i -> i.setReturning(returning)), returningResult);
}
}

View File

@ -54,22 +54,15 @@ import org.jooq.Configuration;
import org.jooq.Constraint;
import org.jooq.Field;
import org.jooq.FieldLike;
import org.jooq.FieldOrRow;
import org.jooq.FieldOrRowOrSelect;
import org.jooq.InsertOnConflictConditionStep;
import org.jooq.InsertOnConflictWhereIndexPredicateStep;
import org.jooq.InsertOnDuplicateSetMoreStep;
import org.jooq.InsertResultStep;
import org.jooq.InsertSetMoreStep;
import org.jooq.InsertSetStep;
import org.jooq.InsertValuesStepN;
import org.jooq.InsertValuesStep1;
import org.jooq.InsertValuesStep2;
import org.jooq.InsertValuesStep3;
import org.jooq.InsertValuesStep4;
import org.jooq.InsertValuesStep5;
import org.jooq.InsertValuesStep6;
import org.jooq.InsertValuesStep7;
import org.jooq.InsertValuesStep8;
import org.jooq.InsertValuesStep9;
import org.jooq.InsertValuesStep10;
import org.jooq.InsertValuesStep11;
import org.jooq.InsertValuesStep12;
@ -80,22 +73,23 @@ import org.jooq.InsertValuesStep16;
import org.jooq.InsertValuesStep17;
import org.jooq.InsertValuesStep18;
import org.jooq.InsertValuesStep19;
import org.jooq.InsertValuesStep2;
import org.jooq.InsertValuesStep20;
import org.jooq.InsertValuesStep21;
import org.jooq.InsertValuesStep22;
import org.jooq.InsertValuesStep3;
import org.jooq.InsertValuesStep4;
import org.jooq.InsertValuesStep5;
import org.jooq.InsertValuesStep6;
import org.jooq.InsertValuesStep7;
import org.jooq.InsertValuesStep8;
import org.jooq.InsertValuesStep9;
import org.jooq.InsertValuesStepN;
import org.jooq.Name;
import org.jooq.Operator;
import org.jooq.QueryPart;
import org.jooq.Record;
import org.jooq.Record1;
import org.jooq.Record2;
import org.jooq.Record3;
import org.jooq.Record4;
import org.jooq.Record5;
import org.jooq.Record6;
import org.jooq.Record7;
import org.jooq.Record8;
import org.jooq.Record9;
import org.jooq.Record10;
import org.jooq.Record11;
import org.jooq.Record12;
@ -106,20 +100,20 @@ import org.jooq.Record16;
import org.jooq.Record17;
import org.jooq.Record18;
import org.jooq.Record19;
import org.jooq.Record2;
import org.jooq.Record20;
import org.jooq.Record21;
import org.jooq.Record22;
import org.jooq.Record3;
import org.jooq.Record4;
import org.jooq.Record5;
import org.jooq.Record6;
import org.jooq.Record7;
import org.jooq.Record8;
import org.jooq.Record9;
// ...
import org.jooq.Row;
import org.jooq.RowN;
import org.jooq.Row1;
import org.jooq.Row2;
import org.jooq.Row3;
import org.jooq.Row4;
import org.jooq.Row5;
import org.jooq.Row6;
import org.jooq.Row7;
import org.jooq.Row8;
import org.jooq.Row9;
import org.jooq.Row10;
import org.jooq.Row11;
import org.jooq.Row12;
@ -130,15 +124,28 @@ import org.jooq.Row16;
import org.jooq.Row17;
import org.jooq.Row18;
import org.jooq.Row19;
import org.jooq.Row2;
import org.jooq.Row20;
import org.jooq.Row21;
import org.jooq.Row22;
import org.jooq.Row3;
import org.jooq.Row4;
import org.jooq.Row5;
import org.jooq.Row6;
import org.jooq.Row7;
import org.jooq.Row8;
import org.jooq.Row9;
import org.jooq.RowN;
import org.jooq.SQL;
import org.jooq.Select;
import org.jooq.SelectField;
import org.jooq.SelectFieldOrAsterisk;
import org.jooq.Table;
// ...
import org.jooq.UniqueKey;
import org.jooq.impl.QOM.Insert;
import org.jooq.impl.QOM.UnmodifiableList;
import org.jooq.impl.QOM.UnmodifiableMap;
/**
* @author Lukas Eder
@ -176,7 +183,9 @@ final class InsertImpl<R extends Record, T1, T2, T3, T4, T5, T6, T7, T8, T9, T10
InsertSetMoreStep<R>,
InsertOnDuplicateSetMoreStep<R>,
InsertOnConflictWhereIndexPredicateStep<R>,
InsertOnConflictConditionStep<R> {
InsertOnConflictConditionStep<R>,
QOM.Insert<R>
{
private final Table<R> into;
private Field<?>[] fields;
@ -1417,33 +1426,33 @@ final class InsertImpl<R extends Record, T1, T2, T3, T4, T5, T6, T7, T8, T9, T10
@Override
public final InsertResultStep<R> returning() {
getDelegate().setReturning();
return new DMLQueryAsResultQuery<>(getDelegate(), returningResult);
return new InsertAsResultQuery<>(getDelegate(), returningResult);
}
@Override
public final InsertResultStep<R> returning(SelectFieldOrAsterisk... f) {
getDelegate().setReturning(f);
return new DMLQueryAsResultQuery<>(getDelegate(), returningResult);
return new InsertAsResultQuery<>(getDelegate(), returningResult);
}
@Override
public final InsertResultStep<R> returning(Collection<? extends SelectFieldOrAsterisk> f) {
getDelegate().setReturning(f);
return new DMLQueryAsResultQuery<>(getDelegate(), returningResult);
return new InsertAsResultQuery<>(getDelegate(), returningResult);
}
@Override
public final InsertResultStep<Record> returningResult(SelectFieldOrAsterisk... f) {
returningResult = true;
getDelegate().setReturning(f);
return new DMLQueryAsResultQuery(getDelegate(), returningResult);
return new InsertAsResultQuery(getDelegate(), returningResult);
}
@Override
public final InsertResultStep<Record> returningResult(Collection<? extends SelectFieldOrAsterisk> f) {
returningResult = true;
getDelegate().setReturning(f);
return new DMLQueryAsResultQuery(getDelegate(), returningResult);
return new InsertAsResultQuery(getDelegate(), returningResult);
}
@Override
@ -1577,4 +1586,138 @@ final class InsertImpl<R extends Record, T1, T2, T3, T4, T5, T6, T7, T8, T9, T10
public final <T1, T2, T3, T4, T5, T6, T7, T8, T9, T10, T11, T12, T13, T14, T15, T16, T17, T18, T19, T20, T21, T22> InsertResultStep<Record22<T1, T2, T3, T4, T5, T6, T7, T8, T9, T10, T11, T12, T13, T14, T15, T16, T17, T18, T19, T20, T21, T22>> returningResult(SelectField<T1> field1, SelectField<T2> field2, SelectField<T3> field3, SelectField<T4> field4, SelectField<T5> field5, SelectField<T6> field6, SelectField<T7> field7, SelectField<T8> field8, SelectField<T9> field9, SelectField<T10> field10, SelectField<T11> field11, SelectField<T12> field12, SelectField<T13> field13, SelectField<T14> field14, SelectField<T15> field15, SelectField<T16> field16, SelectField<T17> field17, SelectField<T18> field18, SelectField<T19> field19, SelectField<T20> field20, SelectField<T21> field21, SelectField<T22> field22) {
return (InsertResultStep) returningResult(new SelectField[] { field1, field2, field3, field4, field5, field6, field7, field8, field9, field10, field11, field12, field13, field14, field15, field16, field17, field18, field19, field20, field21, field22 });
}
// -------------------------------------------------------------------------
// XXX: Query Object Model
// -------------------------------------------------------------------------
@Override
public final WithImpl $with() {
return getDelegate().$with();
}
@Override
public final Table<R> $into() {
return getDelegate().$into();
}
@Override
public final Insert<?> $into(Table<?> newInto) {
return getDelegate().$into(newInto);
}
@Override
public final UnmodifiableList<? extends Field<?>> $columns() {
return getDelegate().$columns();
}
@Override
public final Insert<?> $columns(Collection<? extends Field<?>> columns) {
return getDelegate().$columns(columns);
}
@Override
public final Select<?> $select() {
return getDelegate().$select();
}
@Override
public final Insert<?> $select(Select<?> select) {
return getDelegate().$select(select);
}
@Override
public final boolean $defaultValues() {
return getDelegate().$defaultValues();
}
@Override
public final Insert<?> $defaultValues(boolean defaultValues) {
return getDelegate().$defaultValues(defaultValues);
}
@Override
public final UnmodifiableList<? extends Row> $values() {
return getDelegate().$values();
}
@Override
public final Insert<?> $values(Collection<? extends Row> values) {
return getDelegate().$values(values);
}
@Override
public final boolean $onDuplicateKeyIgnore() {
return getDelegate().$onDuplicateKeyIgnore();
}
@Override
public final Insert<?> $onDuplicateKeyIgnore(boolean onDuplicateKeyIgnore) {
return getDelegate().$onDuplicateKeyIgnore(onDuplicateKeyIgnore);
}
@Override
public boolean $onDuplicateKeyUpdate() {
return getDelegate().$onDuplicateKeyUpdate();
}
@Override
public final Insert<?> $onDuplicateKeyUpdate(boolean onDuplicateKeyUpdate) {
return getDelegate().$onDuplicateKeyUpdate(onDuplicateKeyUpdate);
}
@Override
public final UnmodifiableList<? extends Field<?>> $onConflict() {
return getDelegate().$onConflict();
}
@Override
public final Insert<?> $onConflict(Collection<? extends Field<?>> onConflictFields) {
return getDelegate().$onConflict(onConflictFields);
}
@Override
public final Condition $onConflictWhere() {
return getDelegate().$onConflictWhere();
}
@Override
public final Insert<?> $onConflictWhere(Condition where) {
return getDelegate().$onConflictWhere(where);
}
@Override
public final UnmodifiableMap<? extends FieldOrRow, ? extends FieldOrRowOrSelect> $updateSet() {
return getDelegate().$updateSet();
}
@Override
public final Insert<?> $updateSet(Map<? extends FieldOrRow, ? extends FieldOrRowOrSelect> updateSet) {
return getDelegate().$updateSet(updateSet);
}
@Override
public final Condition $updateWhere() {
return getDelegate().$updateWhere();
}
@Override
public final Insert<?> $updateWhere(Condition where) {
return getDelegate().$updateWhere(where);
}
}

View File

@ -62,6 +62,7 @@ import static org.jooq.SQLDialect.SQLITE;
// ...
// ...
import static org.jooq.conf.ParamType.INLINED;
import static org.jooq.impl.ConditionProviderImpl.extractCondition;
import static org.jooq.impl.DSL.constraint;
import static org.jooq.impl.DSL.falseCondition;
import static org.jooq.impl.DSL.name;
@ -108,6 +109,7 @@ import java.util.HashMap;
import java.util.List;
import java.util.Map;
import java.util.Map.Entry;
import java.util.function.Consumer;
import java.util.Set;
import org.jooq.Clause;
@ -116,6 +118,8 @@ import org.jooq.Configuration;
import org.jooq.Constraint;
import org.jooq.Context;
import org.jooq.Field;
import org.jooq.FieldOrRow;
import org.jooq.FieldOrRowOrSelect;
import org.jooq.GeneratorStatementType;
import org.jooq.Identity;
import org.jooq.InsertQuery;
@ -126,20 +130,30 @@ import org.jooq.Operator;
// ...
import org.jooq.QueryPart;
import org.jooq.Record;
// ...
import org.jooq.Row;
import org.jooq.SQLDialect;
import org.jooq.Scope;
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
*/
@ -148,7 +162,7 @@ extends
AbstractStoreQuery<R, Field<?>, Field<?>>
implements
InsertQuery<R>,
UNotYetImplemented
QOM.Insert<R>
{
static final Clause[] CLAUSES = { INSERT };
@ -158,7 +172,6 @@ implements
static final Set<SQLDialect> NO_SUPPORT_SUBQUERY_IN_MERGE_USING = SQLDialect.supportedBy(DERBY);
static final Set<SQLDialect> REQUIRE_NEW_MYSQL_EXCLUDED_EMULATION = SQLDialect.supportedBy(MYSQL);
final FieldMapForUpdate updateMap;
final FieldMapsForInsert insertMaps;
Select<?> select;
boolean defaultValues;
@ -168,15 +181,16 @@ implements
UniqueKey<R> onConstraintUniqueKey;
QueryPartList<Field<?>> onConflict;
final ConditionProviderImpl onConflictWhere;
final ConditionProviderImpl condition;
final FieldMapForUpdate updateMap;
final ConditionProviderImpl updateWhere;
InsertQueryImpl(Configuration configuration, WithImpl with, Table<R> into) {
super(configuration, with, into);
this.updateMap = new FieldMapForUpdate(into, SetClause.INSERT, INSERT_ON_DUPLICATE_KEY_UPDATE_ASSIGNMENT);
this.insertMaps = new FieldMapsForInsert(into);
this.onConflictWhere = new ConditionProviderImpl();
this.condition = new ConditionProviderImpl();
this.updateMap = new FieldMapForUpdate(into, SetClause.INSERT, INSERT_ON_DUPLICATE_KEY_UPDATE_ASSIGNMENT);
this.updateWhere = new ConditionProviderImpl();
}
@Override
@ -246,14 +260,31 @@ implements
@Override
public final void onDuplicateKeyUpdate(boolean flag) {
this.onDuplicateKeyIgnore = false;
this.onDuplicateKeyUpdate = flag;
onDuplicateKeyUpdate = flag;
if (flag) {
onDuplicateKeyIgnore = false;
clearOnConflict();
}
}
@Override
public final void onDuplicateKeyIgnore(boolean flag) {
this.onDuplicateKeyUpdate = false;
this.onDuplicateKeyIgnore = flag;
onDuplicateKeyIgnore = flag;
if (flag) {
onDuplicateKeyUpdate = false;
updateMap.clear();
updateWhere.setWhere(null);
clearOnConflict();
}
}
private final void clearOnConflict() {
onConflict = null;
onConflictWhere.setWhere(null);
onConstraint = null;
onConstraintUniqueKey = null;
}
@Override
@ -273,37 +304,38 @@ implements
@Override
public final void addConditions(Condition conditions) {
condition.addConditions(conditions);
updateWhere.addConditions(conditions);
}
@Override
public final void addConditions(Condition... conditions) {
condition.addConditions(conditions);
updateWhere.addConditions(conditions);
}
@Override
public final void addConditions(Collection<? extends Condition> conditions) {
condition.addConditions(conditions);
updateWhere.addConditions(conditions);
}
@Override
public final void addConditions(Operator operator, Condition conditions) {
condition.addConditions(operator, conditions);
updateWhere.addConditions(operator, conditions);
}
@Override
public final void addConditions(Operator operator, Condition... conditions) {
condition.addConditions(operator, conditions);
updateWhere.addConditions(operator, conditions);
}
@Override
public final void addConditions(Operator operator, Collection<? extends Condition> conditions) {
condition.addConditions(operator, conditions);
updateWhere.addConditions(operator, conditions);
}
@Override
public final void setDefaultValues() {
defaultValues = true;
select = null;
}
private final boolean defaultValues(Configuration c) {
@ -322,6 +354,8 @@ implements
@Override
public final void setSelect(Collection<? extends Field<?>> f, Select<?> s) {
defaultValues = false;
insertMaps.clear();
insertMaps.addFields(f);
select = s;
}
@ -412,11 +446,11 @@ implements
.visit(updateMapComputedOnClientStored(ctx))
.formatIndentEnd();
if (condition.hasWhere())
if (updateWhere.hasWhere())
ctx.formatSeparator()
.visit(K_WHERE)
.sql(' ')
.visit(condition);
.visit(updateWhere);
ctx.end(INSERT_ON_DUPLICATE_KEY_UPDATE);
}
@ -469,8 +503,8 @@ implements
.qualify(newQualify);
// [#8479] Emulate WHERE clause using CASE
if (condition.hasWhere())
ctx.data(DATA_ON_DUPLICATE_KEY_WHERE, condition.getWhere());
if (updateWhere.hasWhere())
ctx.data(DATA_ON_DUPLICATE_KEY_WHERE, updateWhere.getWhere());
if (requireNewMySQLExcludedEmulation) {
um.replaceAll((k, v) -> {
@ -484,7 +518,7 @@ implements
ctx.visit(um);
if (condition.hasWhere())
if (updateWhere.hasWhere())
ctx.data().remove(DATA_ON_DUPLICATE_KEY_WHERE);
ctx.qualify(oldQualify)
@ -945,8 +979,8 @@ implements
// computed column emulation
um = updateMapComputedOnClientStored(ctx, um);
notMatched = condition.hasWhere()
? on.whenMatchedAnd(condition.getWhere()).thenUpdate().set(um)
notMatched = updateWhere.hasWhere()
? on.whenMatchedAnd(updateWhere.getWhere()).thenUpdate().set(um)
: on.whenMatchedThenUpdate().set(um);
}
@ -1070,6 +1104,222 @@ implements
// -------------------------------------------------------------------------
// XXX: Query Object Model
// -------------------------------------------------------------------------
final InsertQueryImpl<R> copy(Consumer<? super InsertQueryImpl<R>> finisher) {
return copy(finisher, table);
}
final <O extends Record> InsertQueryImpl<O> copy(Consumer<? super InsertQueryImpl<O>> finisher, Table<O> t) {
InsertQueryImpl<O> i = new InsertQueryImpl<>(configuration(), with, t);
if (!returning.isEmpty())
i.setReturning(returning);
i.insertMaps.empty.putAll(insertMaps.empty);
i.insertMaps.values.putAll(insertMaps.values);
i.insertMaps.rows = insertMaps.rows;
i.insertMaps.nextRow = insertMaps.nextRow;
i.defaultValues = defaultValues;
i.select = select;
if (onConflict != null)
i.onConflict(onConflict);
if (onConflictWhere.hasWhere())
i.onConflictWhere.setWhere(extractCondition(onConflictWhere));
i.onConstraint = onConstraint;
i.onConstraintUniqueKey = (UniqueKey) onConstraintUniqueKey;
i.onDuplicateKeyIgnore = onDuplicateKeyIgnore;
i.onDuplicateKeyUpdate = onDuplicateKeyUpdate;
i.updateWhere.setWhere(updateWhere.getWhere());
i.updateMap.putAll(updateMap);
finisher.accept(i);
return i;
}
@Override
public final WithImpl $with() {
return with;
}
@Override
public final Table<R> $into() {
return table;
}
@Override
public final Insert<?> $into(Table<?> newInto) {
if ($into() == newInto)
return this;
else
return copy(i -> {}, newInto);
}
@Override
public final UnmodifiableList<? extends Field<?>> $columns() {
return QOM.unmodifiable(new ArrayList<>(insertMaps.values.keySet()));
}
@Override
public final Insert<?> $columns(Collection<? extends Field<?>> columns) {
throw new QOM.NotYetImplementedException();
}
@Override
public final Select<?> $select() {
return select;
}
@Override
public final Insert<?> $select(Select<?> newSelect) {
if ($select() == newSelect)
return this;
else
return copy(i -> {
i.setSelect($columns(), newSelect);
});
}
@Override
public final boolean $defaultValues() {
return defaultValues;
}
@Override
public final Insert<?> $defaultValues(boolean newDefaultValues) {
if ($defaultValues() == newDefaultValues)
return this;
else
return copy(i -> {
if (newDefaultValues)
i.setDefaultValues();
else
i.defaultValues = false;
});
}
@Override
public final UnmodifiableList<? extends Row> $values() {
return QOM.unmodifiable(new ArrayList<>());
}
@Override
public final Insert<?> $values(Collection<? extends Row> values) {
throw new QOM.NotYetImplementedException();
}
@Override
public final boolean $onDuplicateKeyIgnore() {
return onDuplicateKeyIgnore;
}
@Override
public final Insert<?> $onDuplicateKeyIgnore(boolean newOnDuplicateKeyIgnore) {
if ($onDuplicateKeyIgnore() == newOnDuplicateKeyIgnore)
return this;
else
return copy(i -> i.onDuplicateKeyIgnore(newOnDuplicateKeyIgnore));
}
@Override
public final boolean $onDuplicateKeyUpdate() {
return onDuplicateKeyUpdate;
}
@Override
public final Insert<?> $onDuplicateKeyUpdate(boolean newOnDuplicateKeyUpdate) {
if ($onDuplicateKeyUpdate() == newOnDuplicateKeyUpdate)
return this;
else
return copy(i -> i.onDuplicateKeyUpdate(newOnDuplicateKeyUpdate));
}
@Override
public final UnmodifiableList<? extends Field<?>> $onConflict() {
return QOM.unmodifiable(onConflict == null ? new ArrayList<>() : onConflict);
}
@Override
public final Insert<?> $onConflict(Collection<? extends Field<?>> newOnConflict) {
if ($onConflict() == newOnConflict)
return this;
else
return copy(i -> i.onConflict(newOnConflict));
}
@Override
public final Condition $onConflictWhere() {
return onConflictWhere.getWhereOrNull();
}
@Override
public final Insert<?> $onConflictWhere(Condition newWhere) {
if ($onConflictWhere() == newWhere)
return this;
else
return copy(i -> i.onConflictWhere.setWhere(newWhere));
}
@Override
public final UnmodifiableMap<? extends FieldOrRow, ? extends FieldOrRowOrSelect> $updateSet() {
return QOM.unmodifiable(updateMap);
}
@Override
public final Insert<?> $updateSet(Map<? extends FieldOrRow, ? extends FieldOrRowOrSelect> newUpdateSet) {
if ($updateSet() == newUpdateSet)
return this;
else
return copy(i -> i.addValuesForUpdate(newUpdateSet));
}
@Override
public final Condition $updateWhere() {
return updateWhere.getWhereOrNull();
}
@Override
public final Insert<?> $updateWhere(Condition newWhere) {
if ($updateWhere() == newWhere)
return this;
else
return copy(i -> i.updateWhere.setWhere(newWhere));
}

View File

@ -39,6 +39,7 @@ package org.jooq.impl;
import static java.util.Collections.unmodifiableCollection;
import static java.util.Collections.unmodifiableList;
import static java.util.Collections.unmodifiableMap;
import static org.jooq.impl.DSL.keyword;
import java.math.BigDecimal;
@ -46,7 +47,9 @@ import java.sql.Date;
import java.sql.Timestamp;
import java.util.ArrayList;
import java.util.Collection;
import java.util.Collections;
import java.util.List;
import java.util.Map;
import java.util.UUID;
import java.util.function.Predicate;
@ -64,6 +67,7 @@ import org.jooq.DatePart;
import org.jooq.Domain;
import org.jooq.Field;
import org.jooq.FieldOrRow;
import org.jooq.FieldOrRowOrSelect;
import org.jooq.Function1;
import org.jooq.Function10;
import org.jooq.Function11;
@ -115,13 +119,16 @@ import org.jooq.SQL;
import org.jooq.SQLDialect;
import org.jooq.Schema;
import org.jooq.Select;
import org.jooq.SelectFieldOrAsterisk;
import org.jooq.Sequence;
import org.jooq.SortField;
import org.jooq.Spatial;
import org.jooq.Statement;
import org.jooq.Table;
import org.jooq.TableElement;
import org.jooq.TableLike;
// ...
import org.jooq.UniqueKey;
// ...
import org.jooq.WindowDefinition;
import org.jooq.WindowSpecification;
@ -221,16 +228,29 @@ public final class QOM {
/**
* A generic tuple of degree 2 for use in {@link QOM} types.
*/
public sealed interface UTuple2<Q1 extends org.jooq.QueryPart, Q2 extends org.jooq.QueryPart>
public sealed interface Tuple2<Q1 extends org.jooq.QueryPart, Q2 extends org.jooq.QueryPart>
extends
org.jooq.QueryPart
permits
UTupleImpl2
TupleImpl2
{
@NotNull Q1 $1();
@NotNull UTuple2<Q1, Q2> $1(Q1 newPart1);
@NotNull Tuple2<Q1, Q2> $1(Q1 newPart1);
@NotNull Q2 $2();
@NotNull UTuple2<Q1, Q2> $2(Q2 newPart2);
@NotNull Tuple2<Q1, Q2> $2(Q2 newPart2);
}
/**
* An unmodifiable {@link Map} of {@link QueryPart} keys and values.
*/
public sealed interface UnmodifiableMap<K extends org.jooq.QueryPart, V extends org.jooq.QueryPart>
extends
org.jooq.QueryPart,
java.util.Map<K, V>
permits
AbstractQueryPartMap
{
@NotNull UnmodifiableList<Tuple2<K, V>> $tuples();
}
/**
@ -335,6 +355,117 @@ public final class QOM {
// XXX: Queries
// -------------------------------------------------------------------------
public sealed interface Insert<R extends Record>
extends
DMLQuery<R>
permits
InsertImpl,
InsertQueryImpl
{
@Nullable With $with();
@NotNull Table<R> $into();
@NotNull Insert<?> $into(Table<?> into);
@NotNull UnmodifiableList<? extends Field<?>> $columns();
@NotNull Insert<?> $columns(Collection<? extends Field<?>> columns);
@Nullable Select<?> $select();
@NotNull Insert<?> $select(Select<?> select);
boolean $defaultValues();
@NotNull Insert<?> $defaultValues(boolean defaultValues);
@NotNull UnmodifiableList<? extends Row> $values();
@NotNull Insert<?> $values(Collection<? extends Row> values);
boolean $onDuplicateKeyIgnore();
@NotNull Insert<?> $onDuplicateKeyIgnore(boolean onDuplicateKeyIgnore);
boolean $onDuplicateKeyUpdate();
@NotNull Insert<?> $onDuplicateKeyUpdate(boolean onDuplicateKeyUpdate);
@NotNull UnmodifiableList<? extends Field<?>> $onConflict();
@NotNull Insert<?> $onConflict(Collection<? extends Field<?>> onConflictFields);
// [#13640] TODO: What to do about the CONSTRAINT? Re-design this model?
@Nullable Condition $onConflictWhere();
@NotNull Insert<?> $onConflictWhere(Condition where);
@NotNull UnmodifiableMap<? extends FieldOrRow, ? extends FieldOrRowOrSelect> $updateSet();
@NotNull Insert<?> $updateSet(Map<? extends FieldOrRow, ? extends FieldOrRowOrSelect> updateSet);
@Nullable Condition $updateWhere();
@NotNull Insert<?> $updateWhere(Condition where);
}
public sealed interface InsertReturning<R extends Record>
extends
ResultQuery<R>
permits
InsertAsResultQuery
{
@NotNull Insert<?> $insert();
@NotNull InsertReturning<R> $insert(Insert<?> insert);
@NotNull UnmodifiableList<? extends SelectFieldOrAsterisk> $returning();
@NotNull InsertReturning<?> $returning(Collection<? extends SelectFieldOrAsterisk> returning);
}
public sealed interface Update<R extends Record>
extends
DMLQuery<R>
permits
UpdateImpl,
UpdateQueryImpl
{
@Nullable With $with();
@NotNull Table<R> $table();
@NotNull Update<?> $table(Table<?> table);
@NotNull UnmodifiableList<? extends Table<?>> $from();
@NotNull Update<R> $from(Collection<? extends Table<?>> from);
@NotNull UnmodifiableMap<? extends FieldOrRow, ? extends FieldOrRowOrSelect> $set();
@NotNull Update<R> $set(Map<? extends FieldOrRow, ? extends FieldOrRowOrSelect> set);
@Nullable Condition $where();
@NotNull Update<R> $where(Condition condition);
@NotNull UnmodifiableList<? extends SortField<?>> $orderBy();
@NotNull Update<R> $orderBy(Collection<? extends SortField<?>> orderBy);
@Nullable Field<? extends Number> $limit();
@NotNull Update<R> $limit(Field<? extends Number> limit);
}
public sealed interface UpdateReturning<R extends Record>
extends
ResultQuery<R>
permits
UpdateAsResultQuery
{
@NotNull Update<?> $update();
@NotNull UpdateReturning<R> $update(Update<?> update);
@NotNull UnmodifiableList<? extends SelectFieldOrAsterisk> $returning();
@NotNull UpdateReturning<?> $returning(Collection<? extends SelectFieldOrAsterisk> returning);
}
public sealed interface Delete<R extends Record>
extends
DMLQuery<R>
permits
DeleteImpl,
DeleteQueryImpl
{
@Nullable With $with();
@NotNull Table<R> $from();
@NotNull Delete<?> $from(Table<?> table);
@NotNull UnmodifiableList<? extends Table<?>> $using();
@NotNull Delete<R> $using(Collection<? extends Table<?>> using);
@Nullable Condition $where();
@NotNull Delete<R> $where(Condition condition);
@NotNull UnmodifiableList<? extends SortField<?>> $orderBy();
@NotNull Delete<R> $orderBy(Collection<? extends SortField<?>> orderBy);
@Nullable Field<? extends Number> $limit();
@NotNull Delete<R> $limit(Field<? extends Number> limit);
}
public sealed interface DeleteReturning<R extends Record>
extends
ResultQuery<R>
permits
DeleteAsResultQuery
{
@NotNull Delete<?> $delete();
@NotNull DeleteReturning<R> $delete(Delete<?> delete);
@NotNull UnmodifiableList<? extends SelectFieldOrAsterisk> $returning();
@NotNull DeleteReturning<?> $returning(Collection<? extends SelectFieldOrAsterisk> returning);
}
public /*sealed*/ interface CreateType
extends
DDLQuery
@ -1040,12 +1171,12 @@ public final class QOM {
public /*sealed*/ interface CaseSimple<V, T>
extends
Field<T>,
UOperator3<Field<V>, UnmodifiableList<? extends UTuple2<Field<V>, Field<T>>>, Field<T>, CaseSimple<V, T>>
UOperator3<Field<V>, UnmodifiableList<? extends Tuple2<Field<V>, Field<T>>>, Field<T>, CaseSimple<V, T>>
{
@NotNull default Field<V> $value() { return $arg1(); }
@NotNull default CaseSimple<V, T> $value(Field<V> value) { return $arg1(value); }
@NotNull default UnmodifiableList<? extends UTuple2<Field<V>, Field<T>>> $when() { return $arg2(); }
@NotNull default CaseSimple<V, T> $when(UnmodifiableList<? extends UTuple2<Field<V>, Field<T>>> when) { return $arg2(when); }
@NotNull default UnmodifiableList<? extends Tuple2<Field<V>, Field<T>>> $when() { return $arg2(); }
@NotNull default CaseSimple<V, T> $when(UnmodifiableList<? extends Tuple2<Field<V>, Field<T>>> when) { return $arg2(when); }
@Nullable default Field<T> $else() { return $arg3(); }
@NotNull default CaseSimple<V, T> $else(Field<T> else_) { return $arg3(else_); }
}
@ -1053,10 +1184,10 @@ public final class QOM {
public /*sealed*/ interface CaseSearched<T>
extends
Field<T>,
UOperator2<UnmodifiableList<? extends UTuple2<Condition, Field<T>>>, Field<T>, CaseSearched<T>>
UOperator2<UnmodifiableList<? extends Tuple2<Condition, Field<T>>>, Field<T>, CaseSearched<T>>
{
@NotNull default UnmodifiableList<? extends UTuple2<Condition, Field<T>>> $when() { return $arg1(); }
@NotNull default CaseSearched<T> $when(UnmodifiableList<? extends UTuple2<Condition, Field<T>>> when) { return $arg1(when); }
@NotNull default UnmodifiableList<? extends Tuple2<Condition, Field<T>>> $when() { return $arg1(); }
@NotNull default CaseSearched<T> $when(UnmodifiableList<? extends Tuple2<Condition, Field<T>>> when) { return $arg1(when); }
@Nullable default Field<T> $else() { return $arg2(); }
@NotNull default CaseSearched<T> $else(Field<T> else_) { return $arg2(else_); }
}
@ -7824,8 +7955,16 @@ public final class QOM {
return new QueryPartList<>(unmodifiableCollection(collection));
}
/**
* Turn a {@link Map} into an unmodifiable {@link UnmodifiableMap}.
*/
@Internal
public static final <Q1 extends QueryPart, Q2 extends QueryPart> UTuple2<Q1, Q2> tuple(Q1 q1, Q2 q2) {
return new UTupleImpl2<>(q1, q2);
public static final <K extends QueryPart, V extends QueryPart> UnmodifiableMap<K, V> unmodifiable(Map<K, V> map) {
return new QueryPartMapView<>(unmodifiableMap(map));
}
@Internal
public static final <Q1 extends QueryPart, Q2 extends QueryPart> Tuple2<Q1, Q2> tuple(Q1 q1, Q2 q2) {
return new TupleImpl2<>(q1, q2);
}
}

View File

@ -0,0 +1,79 @@
/*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* https://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*
* Other licenses:
* -----------------------------------------------------------------------------
* Commercial licenses for this work are available. These replace the above
* ASL 2.0 and offer limited warranties, support, maintenance, and commercial
* database integrations.
*
* For more information, please visit: https://www.jooq.org/legal/licensing
*
*
*
*
*
*
*
*
*
*
*
*
*
*
*
*
*/
package org.jooq.impl;
import static org.jooq.impl.QueryPartCollectionView.wrap;
import java.util.Map;
import java.util.function.Function;
import org.jooq.Context;
import org.jooq.QueryPart;
/**
* @author Lukas Eder
*/
final class QueryPartMapView<K extends QueryPart, V extends QueryPart>
extends
AbstractQueryPartMap<K, V>
{
QueryPartMapView(Map<K, V> map) {
super(map);
}
// -------------------------------------------------------------------------
// The QueryPart API
// -------------------------------------------------------------------------
@Override
public final void accept(Context<?> ctx) {
// This is a placeholder implementation without any real SQL usage
ctx.visit(wrap($tuples()));
}
// -------------------------------------------------------------------------
// XXX: Query Object Model
// -------------------------------------------------------------------------
@Override
final Function<? super Map<K, V>, ? extends AbstractQueryPartMap<K, V>> $construct() {
return QueryPartMapView::new;
}
}

View File

@ -124,6 +124,7 @@ import static org.jooq.impl.CombineOperator.INTERSECT_ALL;
import static org.jooq.impl.CombineOperator.UNION;
import static org.jooq.impl.CombineOperator.UNION_ALL;
import static org.jooq.impl.CommonTableExpressionList.markTopLevelCteAndAccept;
import static org.jooq.impl.ConditionProviderImpl.extractCondition;
import static org.jooq.impl.DSL.asterisk;
import static org.jooq.impl.DSL.createTable;
import static org.jooq.impl.DSL.emptyGroupingSet;
@ -4617,7 +4618,7 @@ final class SelectQueryImpl<R extends Record> extends AbstractResultQuery<R> imp
@Override
public final UnmodifiableList<GroupField> $groupBy() {
return QOM.unmodifiable(groupBy == null ? new GroupFieldList() : groupBy);
return QOM.unmodifiable(groupBy);
}
@Override
@ -4846,15 +4847,6 @@ final class SelectQueryImpl<R extends Record> extends AbstractResultQuery<R> imp

View File

@ -3873,7 +3873,7 @@ final class Tools {
return q;
else if (query instanceof AbstractDelegatingDMLQuery<?, ?> q)
return abstractDMLQuery(q.getDelegate());
else if (query instanceof DMLQueryAsResultQuery<?, ?> q)
else if (query instanceof AbstractDMLQueryAsResultQuery<?, ?> q)
return q.getDelegate();
else
return null;

View File

@ -43,7 +43,7 @@ import org.jooq.Context;
import org.jooq.QueryPart;
// ...
// ...
import org.jooq.impl.QOM.UTuple2;
import org.jooq.impl.QOM.Tuple2;
/**
* A generic tuple of degree 2, which acts as a {@link QueryPart} for traversal,
@ -51,17 +51,17 @@ import org.jooq.impl.QOM.UTuple2;
*
* @author Lukas Eder
*/
final class UTupleImpl2<Q1 extends QueryPart, Q2 extends QueryPart>
final class TupleImpl2<Q1 extends QueryPart, Q2 extends QueryPart>
extends
AbstractQueryPart
implements
UTuple2<Q1, Q2>
Tuple2<Q1, Q2>
{
private final Q1 part1;
private final Q2 part2;
UTupleImpl2(Q1 part1, Q2 part2) {
TupleImpl2(Q1 part1, Q2 part2) {
this.part1 = part1;
this.part2 = part2;
}
@ -92,12 +92,12 @@ implements
}
@Override
public final UTuple2<Q1, Q2> $1(Q1 newPart1) {
public final Tuple2<Q1, Q2> $1(Q1 newPart1) {
return tuple(newPart1, part2);
}
@Override
public final UTuple2<Q1, Q2> $2(Q2 newPart2) {
public final Tuple2<Q1, Q2> $2(Q2 newPart2) {
return tuple(part1, newPart2);
}

View File

@ -0,0 +1,116 @@
/*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* https://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*
* Other licenses:
* -----------------------------------------------------------------------------
* Commercial licenses for this work are available. These replace the above
* ASL 2.0 and offer limited warranties, support, maintenance, and commercial
* database integrations.
*
* For more information, please visit: https://www.jooq.org/legal/licensing
*
*
*
*
*
*
*
*
*
*
*
*
*
*
*
*
*/
package org.jooq.impl;
import java.util.Collection;
import org.jooq.QueryPart;
import org.jooq.Record;
// ...
import org.jooq.ResultQuery;
import org.jooq.SelectFieldOrAsterisk;
// ...
import org.jooq.UpdateResultStep;
import org.jooq.impl.QOM.UnmodifiableList;
import org.jooq.impl.QOM.Update;
import org.jooq.impl.QOM.UpdateReturning;
/**
* A wrapped {@link Update} that works like a {@link ResultQuery}.
*
* @author Lukas Eder
*/
final class UpdateAsResultQuery<R extends Record>
extends
AbstractDMLQueryAsResultQuery<R, UpdateQueryImpl<R>>
implements
UpdateResultStep<R>,
QOM.UpdateReturning<R>
{
UpdateAsResultQuery(UpdateQueryImpl<R> delegate, boolean returningResult) {
super(delegate, returningResult);
}
@Override
public final Update<?> $update() {
return getDelegate();
}
@SuppressWarnings({ "rawtypes", "unchecked" })
@Override
public final UpdateReturning<R> $update(Update<?> newUpdate) {
return new UpdateAsResultQuery(Tools.updateQueryImpl(newUpdate).copy(d -> d.setReturning($returning())), returningResult);
}
@Override
public final UnmodifiableList<? extends SelectFieldOrAsterisk> $returning() {
return QOM.unmodifiable(getDelegate().returning);
}
@Override
public final UpdateReturning<?> $returning(Collection<? extends SelectFieldOrAsterisk> returning) {
return new UpdateAsResultQuery<>(getDelegate().copy(d -> d.setReturning(returning)), returningResult);
}
}

View File

@ -49,6 +49,8 @@ import java.util.Map;
import org.jooq.Condition;
import org.jooq.Configuration;
import org.jooq.Field;
import org.jooq.FieldOrRow;
import org.jooq.FieldOrRowOrSelect;
import org.jooq.Name;
import org.jooq.Operator;
import org.jooq.OrderField;
@ -76,6 +78,7 @@ import org.jooq.Record6;
import org.jooq.Record7;
import org.jooq.Record8;
import org.jooq.Record9;
// ...
import org.jooq.Row1;
import org.jooq.Row10;
import org.jooq.Row11;
@ -103,8 +106,10 @@ import org.jooq.SQL;
import org.jooq.Select;
import org.jooq.SelectField;
import org.jooq.SelectFieldOrAsterisk;
import org.jooq.SortField;
import org.jooq.Table;
import org.jooq.TableLike;
// ...
import org.jooq.UpdateConditionStep;
import org.jooq.UpdateFromStep;
import org.jooq.UpdateQuery;
@ -112,6 +117,10 @@ import org.jooq.UpdateResultStep;
import org.jooq.UpdateSetFirstStep;
import org.jooq.UpdateSetMoreStep;
import org.jooq.UpdateWhereStep;
import org.jooq.impl.QOM.UnmodifiableList;
import org.jooq.impl.QOM.UnmodifiableMap;
import org.jooq.impl.QOM.Update;
import org.jooq.impl.QOM.With;
/**
* A wrapper for an {@link UpdateQuery}
@ -120,13 +129,16 @@ import org.jooq.UpdateWhereStep;
*/
@SuppressWarnings({ "rawtypes", "unchecked" })
final class UpdateImpl<R extends Record>
extends AbstractDelegatingDMLQuery<R, UpdateQueryImpl<R>>
implements
extends
AbstractDelegatingDMLQuery<R, UpdateQueryImpl<R>>
implements
// Cascading interface implementations for Update behaviour
UpdateSetFirstStep<R>,
UpdateSetMoreStep<R>,
UpdateConditionStep<R> {
UpdateConditionStep<R>,
QOM.Update<R>
{
private boolean returningResult;
UpdateImpl(Configuration configuration, WithImpl with, Table<R> table) {
@ -679,33 +691,33 @@ final class UpdateImpl<R extends Record>
@Override
public final UpdateResultStep<R> returning() {
getDelegate().setReturning();
return new DMLQueryAsResultQuery<>(getDelegate(), returningResult);
return new UpdateAsResultQuery<>(getDelegate(), returningResult);
}
@Override
public final UpdateResultStep<R> returning(SelectFieldOrAsterisk... f) {
getDelegate().setReturning(f);
return new DMLQueryAsResultQuery<>(getDelegate(), returningResult);
return new UpdateAsResultQuery<>(getDelegate(), returningResult);
}
@Override
public final UpdateResultStep<R> returning(Collection<? extends SelectFieldOrAsterisk> f) {
getDelegate().setReturning(f);
return new DMLQueryAsResultQuery<>(getDelegate(), returningResult);
return new UpdateAsResultQuery<>(getDelegate(), returningResult);
}
@Override
public final UpdateResultStep<Record> returningResult(SelectFieldOrAsterisk... f) {
returningResult = true;
getDelegate().setReturning(f);
return new DMLQueryAsResultQuery(getDelegate(), returningResult);
return new UpdateAsResultQuery(getDelegate(), returningResult);
}
@Override
public final UpdateResultStep<Record> returningResult(Collection<? extends SelectFieldOrAsterisk> f) {
returningResult = true;
getDelegate().setReturning(f);
return new DMLQueryAsResultQuery(getDelegate(), returningResult);
return new UpdateAsResultQuery(getDelegate(), returningResult);
}
@ -821,4 +833,88 @@ final class UpdateImpl<R extends Record>
}
// -------------------------------------------------------------------------
// XXX: Query Object Model
// -------------------------------------------------------------------------
@Override
public final With $with() {
return getDelegate().$with();
}
@Override
public final Table<R> $table() {
return getDelegate().$table();
}
@Override
public final Update<?> $table(Table<?> table) {
return getDelegate().$table(table);
}
@Override
public final UnmodifiableList<? extends Table<?>> $from() {
return getDelegate().$from();
}
@Override
public final Update<R> $from(Collection<? extends Table<?>> using) {
return getDelegate().$from(using);
}
@Override
public final UnmodifiableMap<? extends FieldOrRow, ? extends FieldOrRowOrSelect> $set() {
return getDelegate().$set();
}
@Override
public final Update<R> $set(Map<? extends FieldOrRow, ? extends FieldOrRowOrSelect> set) {
return getDelegate().$set(set);
}
@Override
public final Condition $where() {
return getDelegate().$where();
}
@Override
public final Update<R> $where(Condition condition) {
return getDelegate().$where(condition);
}
@Override
public final UnmodifiableList<? extends SortField<?>> $orderBy() {
return getDelegate().$orderBy();
}
@Override
public final Update<R> $orderBy(Collection<? extends SortField<?>> orderBy) {
return getDelegate().$orderBy(orderBy);
}
@Override
public final Field<? extends Number> $limit() {
return getDelegate().$limit();
}
@Override
public final Update<R> $limit(Field<? extends Number> limit) {
return getDelegate().$limit(limit);
}
}

View File

@ -77,6 +77,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.ConditionProviderImpl.extractCondition;
import static org.jooq.impl.DSL.insertInto;
import static org.jooq.impl.DSL.mergeInto;
import static org.jooq.impl.DSL.name;
@ -137,6 +138,7 @@ import org.jooq.Record6;
import org.jooq.Record7;
import org.jooq.Record8;
import org.jooq.Record9;
// ...
import org.jooq.Row;
import org.jooq.Row1;
import org.jooq.Row10;
@ -164,12 +166,16 @@ import org.jooq.RowN;
import org.jooq.SQLDialect;
import org.jooq.Scope;
import org.jooq.Select;
import org.jooq.SortField;
import org.jooq.Table;
import org.jooq.TableField;
import org.jooq.TableLike;
// ...
import org.jooq.UpdateQuery;
import org.jooq.impl.FieldMapForUpdate.SetClause;
import org.jooq.impl.QOM.UNotYetImplemented;
import org.jooq.impl.QOM.UnmodifiableList;
import org.jooq.impl.QOM.UnmodifiableMap;
import org.jooq.impl.QOM.Update;
/**
* @author Lukas Eder
@ -179,7 +185,7 @@ extends
AbstractStoreQuery<R, FieldOrRow, FieldOrRowOrSelect>
implements
UpdateQuery<R>,
UNotYetImplemented
QOM.Update<R>
{
private static final Clause[] CLAUSES = { UPDATE };
@ -636,8 +642,12 @@ implements
ctx.visit(mergeInto(table).using(s).on(c).whenMatchedThenUpdate().set(um));
}
private final UpdateQueryImpl<R> copy(Consumer<? super UpdateQueryImpl<R>> consumer) {
UpdateQueryImpl<R> u = new UpdateQueryImpl<>(configuration(), with, table);
final UpdateQueryImpl<R> copy(Consumer<? super UpdateQueryImpl<R>> finisher) {
return copy(finisher, table);
}
final <O extends Record> UpdateQueryImpl<O> copy(Consumer<? super UpdateQueryImpl<O>> finisher, Table<O> t) {
UpdateQueryImpl<O> u = new UpdateQueryImpl<>(configuration(), with, t);
if (!returning.isEmpty())
u.setReturning(returning);
@ -647,7 +657,7 @@ implements
u.condition.setWhere(condition.getWhere());
u.orderBy.addAll(orderBy);
u.limit = limit;
consumer.accept(u);
finisher.accept(u);
return u;
}
@ -784,6 +794,138 @@ implements
return updateMap.size() > 0;
}
// -------------------------------------------------------------------------
// XXX: Query Object Model
// -------------------------------------------------------------------------
@Override
public final WithImpl $with() {
return with;
}
@Override
public final Table<R> $table() {
return table;
}
@Override
public final Update<?> $table(Table<?> newTable) {
if ($from() == newTable)
return this;
else
return copy(d -> {}, newTable);
}
@Override
public final UnmodifiableList<? extends Table<?>> $from() {
return QOM.unmodifiable(from);
}
@Override
public final Update<R> $from(Collection<? extends Table<?>> newFrom) {
return copy(d -> {
d.from.clear();
d.from.addAll(newFrom);
});
}
@Override
public final UnmodifiableMap<? extends FieldOrRow, ? extends FieldOrRowOrSelect> $set() {
return QOM.unmodifiable(updateMap);
}
@Override
public final Update<R> $set(Map<? extends FieldOrRow, ? extends FieldOrRowOrSelect> newSet) {
return copy(u -> {
u.updateMap.clear();
u.updateMap.putAll(newSet);
});
}
@Override
public final Condition $where() {
return condition.getWhereOrNull();
}
@Override
public final Update<R> $where(Condition newWhere) {
if ($where() == newWhere)
return this;
else
return copy(u -> u.condition.setWhere(newWhere));
}
@Override
public final UnmodifiableList<? extends SortField<?>> $orderBy() {
return QOM.unmodifiable(orderBy);
}
@Override
public final Update<R> $orderBy(Collection<? extends SortField<?>> newOrderBy) {
return copy(u -> {
u.orderBy.clear();
u.orderBy.addAll(newOrderBy);
});
}
@Override
public final Field<? extends Number> $limit() {
return limit;
}
@Override
public final Update<R> $limit(Field<? extends Number> newLimit) {
if ($limit() == newLimit)
return this;
else
return copy(s -> s.limit = newLimit);
}