[jOOQ/jOOQ#11969] Let Condition extend Field<Boolean>
This commit is contained in:
parent
5b5a57eab8
commit
088571bbcc
@ -372,7 +372,7 @@ public class DerbyDatabase extends AbstractDatabase implements ResultQueryDataba
|
||||
.when(inline("INTEGER"), inline((long) Integer.MAX_VALUE))
|
||||
.when(inline("BIGINT"), inline(Long.MAX_VALUE))
|
||||
).coerce(NUMERIC).as(SYSSEQUENCES.MAXIMUMVALUE),
|
||||
field(SYSSEQUENCES.CYCLEOPTION.eq(inline("Y"))).as(SYSSEQUENCES.CYCLEOPTION),
|
||||
SYSSEQUENCES.CYCLEOPTION.eq(inline("Y")).as(SYSSEQUENCES.CYCLEOPTION),
|
||||
inline(null, BIGINT).cast(BIGINT).as("cache")
|
||||
)
|
||||
.from(SYSSEQUENCES)
|
||||
|
||||
@ -46,6 +46,7 @@ import static org.jooq.impl.DSL.arrayAgg;
|
||||
import static org.jooq.impl.DSL.coalesce;
|
||||
import static org.jooq.impl.DSL.concat;
|
||||
import static org.jooq.impl.DSL.condition;
|
||||
import static org.jooq.impl.DSL.exists;
|
||||
import static org.jooq.impl.DSL.falseCondition;
|
||||
import static org.jooq.impl.DSL.field;
|
||||
import static org.jooq.impl.DSL.inline;
|
||||
@ -241,7 +242,7 @@ public class H2Database extends AbstractDatabase implements ResultQueryDatabase
|
||||
INDEXES.TABLE_SCHEMA,
|
||||
INDEXES.TABLE_NAME,
|
||||
INDEXES.INDEX_NAME,
|
||||
field(field(INDEXES.getQualifiedName().append("INDEX_TYPE_NAME")).ne(inline("UNIQUE INDEX"))).as(INDEXES.NON_UNIQUE),
|
||||
field(INDEXES.getQualifiedName().append("INDEX_TYPE_NAME")).ne(inline("UNIQUE INDEX")).as(INDEXES.NON_UNIQUE),
|
||||
field("i.column_name", INDEXES.COLUMN_NAME).as(INDEXES.COLUMN_NAME),
|
||||
field("i.ordinal_position", INDEXES.ORDINAL_POSITION).as(INDEXES.ORDINAL_POSITION),
|
||||
field("i.ordering_specification", INDEXES.ASC_OR_DESC).as(INDEXES.ASC_OR_DESC))
|
||||
@ -599,7 +600,7 @@ public class H2Database extends AbstractDatabase implements ResultQueryDatabase
|
||||
: SEQUENCES.MAX_VALUE;
|
||||
|
||||
Field<Boolean> isCycle = is2_0_202()
|
||||
? field(field(SEQUENCES.getQualifiedName().append("CYCLE_OPTION")).eq(inline("YES")))
|
||||
? field(SEQUENCES.getQualifiedName().append("CYCLE_OPTION")).eq(inline("YES"))
|
||||
: SEQUENCES.IS_CYCLE;
|
||||
|
||||
return create()
|
||||
@ -748,13 +749,13 @@ public class H2Database extends AbstractDatabase implements ResultQueryDatabase
|
||||
private List<RoutineDefinition> getRoutines1_4() {
|
||||
List<RoutineDefinition> result = new ArrayList<>();
|
||||
|
||||
Field<Boolean> overloaded = field(select(field(DSL.exists(
|
||||
Field<Boolean> overloaded = field(select(DSL.exists(
|
||||
select(one())
|
||||
.from(FUNCTION_ALIASES.as("a"))
|
||||
.where(field(name("a", FUNCTION_ALIASES.ALIAS_SCHEMA.getName())).eq(FUNCTION_ALIASES.ALIAS_SCHEMA))
|
||||
.and(field(name("a", FUNCTION_ALIASES.ALIAS_NAME.getName())).eq(FUNCTION_ALIASES.ALIAS_NAME))
|
||||
.and(field(name("a", FUNCTION_ALIASES.COLUMN_COUNT.getName())).ne(FUNCTION_ALIASES.COLUMN_COUNT))
|
||||
)))).as("overloaded");
|
||||
))).as("overloaded");
|
||||
|
||||
for (Record record : create()
|
||||
.select(
|
||||
|
||||
@ -124,11 +124,11 @@ public class H2TableDefinition extends AbstractTableDefinition {
|
||||
COLUMNS.NUMERIC_PRECISION).as(COLUMNS.NUMERIC_PRECISION),
|
||||
nvl(ELEMENT_TYPES.NUMERIC_SCALE, COLUMNS.NUMERIC_SCALE).as(COLUMNS.NUMERIC_SCALE),
|
||||
COLUMNS.IS_NULLABLE,
|
||||
field(Tables.COLUMNS.IS_GENERATED.eq(inline("ALWAYS"))).as(COLUMNS.IS_COMPUTED),
|
||||
Tables.COLUMNS.IS_GENERATED.eq(inline("ALWAYS")).as(COLUMNS.IS_COMPUTED),
|
||||
Tables.COLUMNS.GENERATION_EXPRESSION,
|
||||
COLUMNS.COLUMN_DEFAULT,
|
||||
COLUMNS.REMARKS,
|
||||
field(Tables.COLUMNS.IS_IDENTITY.eq(inline("YES"))).as(Tables.COLUMNS.IS_IDENTITY),
|
||||
Tables.COLUMNS.IS_IDENTITY.eq(inline("YES")).as(Tables.COLUMNS.IS_IDENTITY),
|
||||
COLUMNS.DOMAIN_SCHEMA,
|
||||
COLUMNS.DOMAIN_NAME
|
||||
)
|
||||
@ -220,7 +220,7 @@ public class H2TableDefinition extends AbstractTableDefinition {
|
||||
COLUMNS.COLUMN_DEFAULT.as("GENERATION_EXPRESSION"),
|
||||
COLUMNS.COLUMN_DEFAULT,
|
||||
COLUMNS.REMARKS,
|
||||
field(COLUMNS.SEQUENCE_NAME.isNotNull()).as("IS_IDENTITY"),
|
||||
COLUMNS.SEQUENCE_NAME.isNotNull().as("IS_IDENTITY"),
|
||||
db.is1_4_198() ? COLUMNS.DOMAIN_SCHEMA : inline("").as(COLUMNS.DOMAIN_SCHEMA),
|
||||
db.is1_4_198() ? COLUMNS.DOMAIN_NAME : inline("").as(COLUMNS.DOMAIN_NAME)
|
||||
)
|
||||
|
||||
@ -566,7 +566,7 @@ public class HSQLDBDatabase extends AbstractDatabase implements ResultQueryDatab
|
||||
nvl(ELEMENT_TYPES.COLLECTION_TYPE_IDENTIFIER, ROUTINES.DATA_TYPE).as("datatype"),
|
||||
ROUTINES.NUMERIC_PRECISION,
|
||||
ROUTINES.NUMERIC_SCALE,
|
||||
field(ROUTINES.ROUTINE_DEFINITION.likeRegex(".*(?i:(\\w+\\s+)+aggregate\\s+function).*")).as("aggregate"))
|
||||
ROUTINES.ROUTINE_DEFINITION.likeRegex(".*(?i:(\\w+\\s+)+aggregate\\s+function).*").as("aggregate"))
|
||||
.from(ROUTINES)
|
||||
.leftOuterJoin(ELEMENT_TYPES)
|
||||
.on(ROUTINES.ROUTINE_SCHEMA.equal(ELEMENT_TYPES.OBJECT_SCHEMA))
|
||||
|
||||
@ -935,7 +935,7 @@ public class PostgresDatabase extends AbstractDatabase implements ResultQueryDat
|
||||
|
||||
// [#7785] The pg_proc.proisagg column has been replaced incompatibly in PostgreSQL 11
|
||||
Field<Boolean> isAgg = (is11()
|
||||
? field(PG_PROC.PROKIND.eq(inline("a")))
|
||||
? PG_PROC.PROKIND.eq(inline("a"))
|
||||
: field("{0}.proisagg", SQLDataType.BOOLEAN, PG_PROC)
|
||||
).as("is_agg");
|
||||
|
||||
|
||||
@ -81,7 +81,7 @@ import org.jetbrains.annotations.NotNull;
|
||||
*
|
||||
* @author Lukas Eder
|
||||
*/
|
||||
public interface Condition extends QueryPart {
|
||||
public interface Condition extends Field<Boolean> {
|
||||
|
||||
/**
|
||||
* Combine this condition with another one using the {@link Operator#AND}
|
||||
|
||||
@ -90,6 +90,30 @@ public interface Context<C extends Context<C>> extends Scope {
|
||||
@NotNull
|
||||
C visit(QueryPart part) throws DataAccessException;
|
||||
|
||||
/**
|
||||
* Visit a {@link Condition} as an ordinary {@link QueryPart}.
|
||||
*/
|
||||
@NotNull
|
||||
C visit(Condition part) throws DataAccessException;
|
||||
|
||||
/**
|
||||
* Visit a {@link Field} as a {@link DSL#field(Condition)}, if it is a
|
||||
* {@link Condition}, or as an ordinery {@link QueryPart}, otherwise.
|
||||
* <p>
|
||||
* [#11969] Not all RDBMS support {@link Condition} in the form of
|
||||
* {@link Field} of type {@link Boolean}, natively. As such, we must wrap
|
||||
* any such {@link Condition} using {@link DSL#field(Condition)} to make
|
||||
* sure the appropriate emulations are implemented. This applies to
|
||||
* conditions that are declared as {@link Field}, e.g. the arguments of a
|
||||
* function like {@link DSL#nvl(Field, Field)}.
|
||||
* <p>
|
||||
* If a {@link Condition} is declared as a condition, then this doesn't
|
||||
* apply and {@link #visit(Condition)} is invoked, instead, e.g. the
|
||||
* arguments of {@link AggregateFunction#filterWhere(Condition)}.
|
||||
*/
|
||||
@NotNull
|
||||
C visit(Field<?> part) throws DataAccessException;
|
||||
|
||||
/**
|
||||
* Visit a <code>QueryPart</code> as a subquery in the current
|
||||
* <code>Context</code>.
|
||||
|
||||
@ -57,11 +57,13 @@ import org.jooq.Select;
|
||||
/**
|
||||
* @author Lukas Eder
|
||||
*/
|
||||
abstract class AbstractCondition extends AbstractQueryPart implements Condition {
|
||||
abstract class AbstractCondition extends AbstractField<Boolean> implements Condition {
|
||||
|
||||
private static final Clause[] CLAUSES = { CONDITION };
|
||||
|
||||
AbstractCondition() {}
|
||||
AbstractCondition() {
|
||||
super(DSL.name("condition"), SQLDataType.BOOLEAN);
|
||||
}
|
||||
|
||||
/**
|
||||
* [#10179] Subclasses may override this method to indicate that the
|
||||
|
||||
@ -75,9 +75,11 @@ import java.util.function.Supplier;
|
||||
|
||||
import org.jooq.BindContext;
|
||||
import org.jooq.Clause;
|
||||
import org.jooq.Condition;
|
||||
import org.jooq.Configuration;
|
||||
import org.jooq.Context;
|
||||
import org.jooq.DSLContext;
|
||||
import org.jooq.Field;
|
||||
import org.jooq.ForeignKey;
|
||||
import org.jooq.JoinType;
|
||||
import org.jooq.LanguageContext;
|
||||
@ -97,13 +99,10 @@ import org.jooq.conf.RenderImplicitJoinType;
|
||||
import org.jooq.conf.Settings;
|
||||
import org.jooq.conf.SettingsTools;
|
||||
import org.jooq.conf.StatementType;
|
||||
import org.jooq.impl.AbstractContext.ScopeStackElement;
|
||||
import org.jooq.impl.Tools.DataKey;
|
||||
import org.jooq.impl.Tools.DataKeyScopeStackPart;
|
||||
import org.jooq.tools.StringUtils;
|
||||
|
||||
import org.jetbrains.annotations.NotNull;
|
||||
|
||||
|
||||
/**
|
||||
* @author Lukas Eder
|
||||
@ -230,6 +229,16 @@ abstract class AbstractContext<C extends Context<C>> extends AbstractScope imple
|
||||
// VisitListener API
|
||||
// ------------------------------------------------------------------------
|
||||
|
||||
@Override
|
||||
public final C visit(Condition part) {
|
||||
return visit((QueryPart) part);
|
||||
}
|
||||
|
||||
@Override
|
||||
public final C visit(Field<?> part) {
|
||||
return part instanceof Condition ? visit((QueryPart) DSL.field((Condition) part)) : visit((QueryPart) part);
|
||||
}
|
||||
|
||||
@Override
|
||||
public final C visit(QueryPart part) {
|
||||
if (part != null) {
|
||||
|
||||
@ -265,11 +265,11 @@ abstract class AbstractInList<T> extends AbstractCondition {
|
||||
private final int padSize;
|
||||
|
||||
PaddedList(List<T> delegate, int maxPadding, int padBase) {
|
||||
int b = max(2, padBase);
|
||||
int b = Math.max(2, padBase);
|
||||
|
||||
this.delegate = delegate;
|
||||
this.realSize = delegate.size();
|
||||
this.padSize = min(maxPadding, (int) round(pow(b, ceil(log(realSize) / log(b)))));
|
||||
this.padSize = Math.min(maxPadding, (int) Math.round(Math.pow(b, Math.ceil(Math.log(realSize) / Math.log(b)))));
|
||||
}
|
||||
|
||||
@Override
|
||||
|
||||
@ -61,12 +61,17 @@ import org.jetbrains.annotations.Nullable;
|
||||
/**
|
||||
* @author Lukas Eder
|
||||
*/
|
||||
final class ConditionProviderImpl extends AbstractQueryPart implements ConditionProvider, Condition, UProxy<Condition> {
|
||||
final class ConditionProviderImpl extends AbstractField<Boolean> implements ConditionProvider, Condition, UProxy<Condition> {
|
||||
|
||||
private Condition condition;
|
||||
|
||||
ConditionProviderImpl() {}
|
||||
ConditionProviderImpl() {
|
||||
this(null);
|
||||
}
|
||||
|
||||
ConditionProviderImpl(Condition condition) {
|
||||
super(DSL.name("condition"), SQLDataType.BOOLEAN);
|
||||
|
||||
this.condition = condition;
|
||||
}
|
||||
|
||||
|
||||
@ -20232,7 +20232,7 @@ public class DSL {
|
||||
@NotNull
|
||||
@Support
|
||||
public static Condition condition(Field<Boolean> field) {
|
||||
return field instanceof NoField ? noCondition() : field instanceof ConditionAsField ? ((ConditionAsField) field).condition : new FieldCondition(field);
|
||||
return field instanceof Condition ? (Condition) field : field instanceof NoField ? noCondition() : field instanceof ConditionAsField ? ((ConditionAsField) field).condition : new FieldCondition(field);
|
||||
}
|
||||
|
||||
// -------------------------------------------------------------------------
|
||||
|
||||
@ -4744,7 +4744,7 @@ public class DefaultDSLContext extends AbstractScope implements DSLContext, Seri
|
||||
|
||||
@Override
|
||||
public boolean fetchExists(Select<?> query) {
|
||||
return fetchValue(field(exists(query)));
|
||||
return fetchValue(exists(query));
|
||||
}
|
||||
|
||||
@Override
|
||||
|
||||
@ -64,6 +64,7 @@ import static org.jooq.impl.DSL.emptyGroupingSet;
|
||||
|
||||
import java.util.Set;
|
||||
|
||||
import org.jooq.Condition;
|
||||
import org.jooq.Context;
|
||||
import org.jooq.Field;
|
||||
import org.jooq.GroupField;
|
||||
|
||||
@ -7524,8 +7524,6 @@ final class DefaultParseContext extends AbstractScope implements ParseContext {
|
||||
return null;
|
||||
else if (part instanceof Field)
|
||||
return (Field<?>) part;
|
||||
else if (part instanceof Condition)
|
||||
return field((Condition) part);
|
||||
else if (part instanceof Row)
|
||||
return (Row) part;
|
||||
else
|
||||
@ -7537,8 +7535,6 @@ final class DefaultParseContext extends AbstractScope implements ParseContext {
|
||||
return null;
|
||||
else if (part instanceof Field)
|
||||
return (Field<?>) part;
|
||||
else if (part instanceof Condition)
|
||||
return field((Condition) part);
|
||||
else
|
||||
throw expected("Field");
|
||||
}
|
||||
@ -8317,7 +8313,7 @@ final class DefaultParseContext extends AbstractScope implements ParseContext {
|
||||
else if (parseFunctionNameIf("IFNULL"))
|
||||
return parseFunctionArgs2((f1, f2) -> ifnull((Field<?>) f1, (Field<?>) f2));
|
||||
else if (parseFunctionNameIf("ISNULL"))
|
||||
return parseFunctionArgs2(f -> field(f.isNull()), (f1, f2) -> isnull((Field<?>) f1, (Field<?>) f2));
|
||||
return parseFunctionArgs2(f -> f.isNull(), (f1, f2) -> isnull((Field<?>) f1, (Field<?>) f2));
|
||||
else if ((field = parseFieldIfIf()) != null)
|
||||
return field;
|
||||
else
|
||||
|
||||
@ -193,19 +193,19 @@ final class QuantifiedComparisonCondition extends AbstractCondition implements L
|
||||
}
|
||||
else if ((query.array != null || query.query != null) && emulateOperator) {
|
||||
Field<String> pattern = DSL.field(name("pattern"), VARCHAR);
|
||||
Condition cond;
|
||||
Condition condition;
|
||||
Field<Boolean> lhs;
|
||||
switch (comparator) {
|
||||
case NOT_LIKE:
|
||||
case NOT_SIMILAR_TO:
|
||||
case NOT_LIKE_IGNORE_CASE:
|
||||
cond = comparisonCondition(inverse(comparator), pattern);
|
||||
condition = comparisonCondition(inverse(comparator), pattern);
|
||||
lhs = inline(false);
|
||||
break;
|
||||
case LIKE:
|
||||
case SIMILAR_TO:
|
||||
case LIKE_IGNORE_CASE:
|
||||
cond = comparisonCondition(comparator, pattern);
|
||||
condition = comparisonCondition(comparator, pattern);
|
||||
lhs = inline(true);
|
||||
break;
|
||||
default:
|
||||
@ -215,7 +215,7 @@ final class QuantifiedComparisonCondition extends AbstractCondition implements L
|
||||
Table<?> t = query.array != null
|
||||
? new ArrayTable(query.array).asTable("t", "pattern")
|
||||
: new AliasedSelect<>(query.query, true, true, false, name("pattern")).as("t");
|
||||
Select<Record1<Boolean>> select = select(DSL.field(cond)).from(t);
|
||||
Select<Record1<Boolean>> select = select(condition).from(t);
|
||||
ctx.visit(lhs.eq(query.quantifier.apply(select)));
|
||||
}
|
||||
else {
|
||||
@ -296,22 +296,22 @@ final class QuantifiedComparisonCondition extends AbstractCondition implements L
|
||||
private Condition comparisonCondition(Comparator operator, Object value) {
|
||||
switch (operator) {
|
||||
case LIKE:
|
||||
return escape != null ? field.like(convert(value, String.class), escape) : field.like(convert(value, String.class));
|
||||
return escape != null ? field.like(Convert.convert(value, String.class), escape) : field.like(Convert.convert(value, String.class));
|
||||
|
||||
case NOT_LIKE:
|
||||
return escape != null ? field.notLike(convert(value, String.class), escape) : field.notLike(convert(value, String.class));
|
||||
return escape != null ? field.notLike(Convert.convert(value, String.class), escape) : field.notLike(Convert.convert(value, String.class));
|
||||
|
||||
case SIMILAR_TO:
|
||||
return escape != null ? field.similarTo(convert(value, String.class), escape) : field.similarTo(convert(value, String.class));
|
||||
return escape != null ? field.similarTo(Convert.convert(value, String.class), escape) : field.similarTo(Convert.convert(value, String.class));
|
||||
|
||||
case NOT_SIMILAR_TO:
|
||||
return escape != null ? field.notSimilarTo(convert(value, String.class), escape) : field.notSimilarTo(convert(value, String.class));
|
||||
return escape != null ? field.notSimilarTo(Convert.convert(value, String.class), escape) : field.notSimilarTo(Convert.convert(value, String.class));
|
||||
|
||||
case LIKE_IGNORE_CASE:
|
||||
return escape != null ? field.likeIgnoreCase(convert(value, String.class), escape) : field.likeIgnoreCase(convert(value, String.class));
|
||||
return escape != null ? field.likeIgnoreCase(Convert.convert(value, String.class), escape) : field.likeIgnoreCase(Convert.convert(value, String.class));
|
||||
|
||||
case NOT_LIKE_IGNORE_CASE:
|
||||
return escape != null ? field.notLikeIgnoreCase(convert(value, String.class), escape) : field.notLikeIgnoreCase(convert(value, String.class));
|
||||
return escape != null ? field.notLikeIgnoreCase(Convert.convert(value, String.class), escape) : field.notLikeIgnoreCase(Convert.convert(value, String.class));
|
||||
|
||||
default:
|
||||
return ((Field) field).compare(operator, value);
|
||||
|
||||
@ -56,6 +56,7 @@ import java.util.Set;
|
||||
import java.util.function.Function;
|
||||
import java.util.function.Predicate;
|
||||
|
||||
import org.jooq.Condition;
|
||||
import org.jooq.Context;
|
||||
import org.jooq.Function1;
|
||||
import org.jooq.QueryPart;
|
||||
@ -240,7 +241,15 @@ implements
|
||||
* Subclasses may override this method
|
||||
*/
|
||||
protected void acceptElement(Context<?> ctx, T part) {
|
||||
ctx.visit(part);
|
||||
// [#11969] As of jOOQ 3.17, *all* QueryPartCollectionView<Field<?>> are
|
||||
// declared as such, there are no QueryPartCollectionView<Condition>
|
||||
// declarations. Hence, it is currently safe to assume that
|
||||
// if (part instanceof Condition), then it must have been passed
|
||||
// as a subtype of Field<?> and must be wrapped
|
||||
if (part instanceof Condition)
|
||||
ctx.visit((QueryPart) DSL.field((Condition) part));
|
||||
else
|
||||
ctx.visit(part);
|
||||
}
|
||||
|
||||
/**
|
||||
|
||||
@ -38,6 +38,7 @@
|
||||
|
||||
package org.jooq.impl;
|
||||
|
||||
import org.jooq.Condition;
|
||||
import org.jooq.Context;
|
||||
import org.jooq.SelectFieldOrAsterisk;
|
||||
|
||||
|
||||
@ -38,7 +38,6 @@
|
||||
|
||||
package org.jooq.impl;
|
||||
|
||||
import static java.util.Collections.emptyList;
|
||||
import static org.jooq.SortOrder.DESC;
|
||||
import static org.jooq.impl.Tools.anyMatch;
|
||||
|
||||
|
||||
@ -6751,6 +6751,8 @@ final class Tools {
|
||||
static final <T> Field<T> nullSafe(Field<T> field, DataType<?> type) {
|
||||
return field == null
|
||||
? (Field<T>) DSL.val((T) null, type)
|
||||
: field instanceof Condition
|
||||
? (Field<T>) DSL.field((Condition) field)
|
||||
: convertVal(field, type);
|
||||
}
|
||||
|
||||
|
||||
@ -113,7 +113,7 @@ implements
|
||||
.from(queryTable)
|
||||
.where(row(queryFields).isNotNull())
|
||||
.groupBy(queryFields)
|
||||
.having(count().gt(one()));
|
||||
.having(DSL.count().gt(one()));
|
||||
|
||||
// TODO: [#7362] [#10304] Find a better way to prevent double negation and unnecessary parentheses
|
||||
ctx.visit(notExists(subquery));
|
||||
|
||||
Loading…
Reference in New Issue
Block a user