[jOOQ/jOOQ#5214] Add support for PostgreSQL's EXCLUDED table

This commit is contained in:
Lukas Eder 2022-05-17 17:45:50 +02:00
parent 38493f7ca1
commit 7cb60cf8ce
5 changed files with 241 additions and 8 deletions

View File

@ -15956,6 +15956,24 @@ public class DSL {
return not(unique(query));
}
// -------------------------------------------------------------------------
// Table functions
// -------------------------------------------------------------------------
/**
* The <code>EXCLUDED</code> function.
* <p>
* Provide "EXCLUDED" qualification for a column for use in ON CONFLICT or ON DUPLICATE
* KEY UPDATE.
*
* @param field The excluded field.
*/
@NotNull
@Support
public static <T> Field<T> excluded(Field<T> field) {
return new Excluded<>(field);
}
// -------------------------------------------------------------------------
// Numeric functions
// -------------------------------------------------------------------------

View File

@ -0,0 +1,179 @@
/*
* 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
*
* http://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: http://www.jooq.org/licenses
*
*
*
*
*
*
*
*
*
*
*
*
*
*
*
*
*/
package org.jooq.impl;
import static org.jooq.impl.DSL.*;
import static org.jooq.impl.Internal.*;
import static org.jooq.impl.Keywords.*;
import static org.jooq.impl.Names.*;
import static org.jooq.impl.SQLDataType.*;
import static org.jooq.impl.Tools.*;
import static org.jooq.impl.Tools.BooleanDataKey.*;
import static org.jooq.impl.Tools.ExtendedDataKey.*;
import static org.jooq.impl.Tools.SimpleDataKey.*;
import static org.jooq.SQLDialect.*;
import org.jooq.*;
import org.jooq.Function1;
import org.jooq.Record;
import org.jooq.conf.*;
import org.jooq.impl.*;
import org.jooq.impl.QOM.*;
import org.jooq.tools.*;
import java.util.*;
import java.util.function.*;
import java.util.stream.*;
/**
* The <code>EXCLUDED</code> statement.
*/
@SuppressWarnings({ "rawtypes", "unchecked", "unused" })
final class Excluded<T>
extends
AbstractField<T>
implements
QOM.Excluded<T>
{
final Field<T> field;
Excluded(
Field<T> field
) {
super(
N_EXCLUDED,
allNotNull((DataType) dataType(field), field)
);
this.field = nullSafeNotNull(field, (DataType) OTHER);
}
// -------------------------------------------------------------------------
// XXX: QueryPart API
// -------------------------------------------------------------------------
@Override
public final void accept(Context<?> ctx) {
switch (ctx.family()) {
case MARIADB:
case MYSQL: {
ctx.visit(K_VALUES).sql('(').qualify(false, c -> c.visit(field)).sql(')');
break;
}
default:
ctx.visit(N_EXCLUDED).sql('.').qualify(false, c -> c.visit(field));
break;
}
}
// -------------------------------------------------------------------------
// XXX: Query Object Model
// -------------------------------------------------------------------------
@Override
public final Field<T> $field() {
return field;
}
@Override
public final QOM.Excluded<T> $field(Field<T> newValue) {
return $constructor().apply(newValue);
}
public final Function1<? super Field<T>, ? extends QOM.Excluded<T>> $constructor() {
return (a1) -> new Excluded<>(a1);
}
// -------------------------------------------------------------------------
// XXX: The Object API
// -------------------------------------------------------------------------
@Override
public boolean equals(Object that) {
if (that instanceof QOM.Excluded) { QOM.Excluded<?> o = (QOM.Excluded<?>) that;
return
StringUtils.equals($field(), o.$field())
;
}
else
return super.equals(that);
}
}

View File

@ -161,18 +161,29 @@ implements
// [#1159] [#1725] Some dialects cannot auto-convert the LHS operand to a
// VARCHAR when applying a LIKE predicate
if ((op == org.jooq.Comparator.LIKE || op == org.jooq.Comparator.NOT_LIKE || op == org.jooq.Comparator.SIMILAR_TO || op == org.jooq.Comparator.NOT_SIMILAR_TO)
&& arg1.getType() != String.class
&& REQUIRES_CAST_ON_LIKE.contains(ctx.dialect())) {
arg1 = castIfNeeded(arg1, String.class);
switch (op) {
case LIKE:
case LIKE_IGNORE_CASE:
case SIMILAR_TO:
case NOT_LIKE:
case NOT_LIKE_IGNORE_CASE:
case NOT_SIMILAR_TO:
if (arg1.getType() != String.class && REQUIRES_CAST_ON_LIKE.contains(ctx.dialect()))
arg1 = castIfNeeded(arg1, String.class);
break;
}
// [#1423] [#9889] PostgreSQL and H2 support ILIKE natively. Other dialects
// need to emulate this as LOWER(lhs) LIKE LOWER(rhs)
else if ((op == org.jooq.Comparator.LIKE_IGNORE_CASE || op == org.jooq.Comparator.NOT_LIKE_IGNORE_CASE) && NO_SUPPORT_ILIKE.contains(ctx.dialect())) {
arg1 = DSL.lower((Field) arg1);
arg2 = DSL.lower((Field) arg2);
op = (op == org.jooq.Comparator.LIKE_IGNORE_CASE ? org.jooq.Comparator.LIKE : org.jooq.Comparator.NOT_LIKE);
switch (op) {
case LIKE_IGNORE_CASE:
case NOT_LIKE_IGNORE_CASE:
if (NO_SUPPORT_ILIKE.contains(ctx.dialect())) {
arg1 = DSL.lower((Field) arg1);
arg2 = DSL.lower((Field) arg2);
op = (op == org.jooq.Comparator.LIKE_IGNORE_CASE ? org.jooq.Comparator.LIKE : org.jooq.Comparator.NOT_LIKE);
}
}
boolean castRhs = castRhs(ctx, arg2);

View File

@ -379,6 +379,7 @@ final class Names {
static final Name N_DELETING = systemName("deleting");
static final Name N_DIGITS = systemName("digits");
static final Name N_E = systemName("e");
static final Name N_EXCLUDED = systemName("excluded");
static final Name N_EXECUTE = systemName("execute");
static final Name N_EXISTS = systemName("exists");
static final Name N_EXP = systemName("exp");

View File

@ -2202,6 +2202,30 @@ public final class QOM {
@NotNull default Field<?> $field() { return $arg1(); }
}
/**
* The <code>EXCLUDED</code> function.
* <p>
* Provide "EXCLUDED" qualification for a column for use in ON CONFLICT or ON DUPLICATE
* KEY UPDATE.
*/
public /*sealed*/ interface Excluded<T>
extends
org.jooq.Field<T>
//permits
// Excluded
{
/**
* The excluded field.
*/
@NotNull Field<T> $field();
/**
* The excluded field.
*/
@NotNull Excluded<T> $field(Field<T> field);
}
/**
* The <code>ROWID</code> operator.
* <p>