From 036919ec3116404f14def7ca43c086cef584872d Mon Sep 17 00:00:00 2001 From: Lukas Eder Date: Wed, 18 Sep 2019 11:36:08 +0200 Subject: [PATCH] [jOOQ/jOOQ#9224] Regression for "= ANY(?::int[])" DSL.any(T...) no longer produces array bind variable in PostgreSQL, when used with natively supported quantified comparison operators like =, !=, etc. This commit fixes the issue and refactors some of the internals to prevent some casting --- .../impl/QuantifiedComparisonCondition.java | 51 ++++++++++++------- 1 file changed, 32 insertions(+), 19 deletions(-) diff --git a/jOOQ/src/main/java/org/jooq/impl/QuantifiedComparisonCondition.java b/jOOQ/src/main/java/org/jooq/impl/QuantifiedComparisonCondition.java index 0395470e2b..44846d6bf0 100644 --- a/jOOQ/src/main/java/org/jooq/impl/QuantifiedComparisonCondition.java +++ b/jOOQ/src/main/java/org/jooq/impl/QuantifiedComparisonCondition.java @@ -41,6 +41,14 @@ package org.jooq.impl; import static org.jooq.Clause.CONDITION; import static org.jooq.Clause.CONDITION_BETWEEN; +import static org.jooq.Comparator.LIKE; +import static org.jooq.Comparator.LIKE_IGNORE_CASE; +import static org.jooq.Comparator.NOT_LIKE; +import static org.jooq.Comparator.NOT_LIKE_IGNORE_CASE; +import static org.jooq.Comparator.NOT_SIMILAR_TO; +import static org.jooq.Comparator.SIMILAR_TO; +// ... +import static org.jooq.SQLDialect.POSTGRES; import static org.jooq.impl.DSL.inline; import static org.jooq.impl.DSL.name; import static org.jooq.impl.DSL.row; @@ -64,6 +72,7 @@ import org.jooq.Operator; import org.jooq.Param; import org.jooq.QuantifiedSelect; import org.jooq.Record1; +import org.jooq.SQLDialect; import org.jooq.Select; import org.jooq.Table; @@ -72,17 +81,18 @@ import org.jooq.Table; */ final class QuantifiedComparisonCondition extends AbstractCondition implements LikeEscapeStep { - private static final long serialVersionUID = -402776705884329740L; - private static final Clause[] CLAUSES = { CONDITION, CONDITION_BETWEEN }; - private static final EnumSet SYNTHETIC_OPERATORS = EnumSet.of(Comparator.LIKE, Comparator.NOT_LIKE, Comparator.LIKE_IGNORE_CASE, Comparator.NOT_LIKE_IGNORE_CASE, Comparator.SIMILAR_TO, Comparator.NOT_SIMILAR_TO); + private static final long serialVersionUID = -402776705884329740L; + private static final Clause[] CLAUSES = { CONDITION, CONDITION_BETWEEN }; + private static final EnumSet SYNTHETIC_OPERATORS = EnumSet.of(LIKE, NOT_LIKE, LIKE_IGNORE_CASE, NOT_LIKE_IGNORE_CASE, SIMILAR_TO, NOT_SIMILAR_TO); + private static final EnumSet SUPPORTS_QUANTIFIED_ARRAYS = EnumSet.of(POSTGRES); - private final QuantifiedSelect query; + private final QuantifiedSelectImpl query; private final Field field; private final Comparator comparator; private Character escape; QuantifiedComparisonCondition(QuantifiedSelect query, Field field, Comparator comparator) { - this.query = query; + this.query = (QuantifiedSelectImpl) query; this.field = field; this.comparator = comparator; } @@ -101,26 +111,29 @@ final class QuantifiedComparisonCondition extends AbstractCondition implements L accept0(ctx); } - @SuppressWarnings({ "unchecked", "null" }) + @SuppressWarnings({ "unchecked" }) private final void accept0(Context ctx) { - Field array = ((QuantifiedSelectImpl) query).array; - Field[] values = (Field[]) ((QuantifiedSelectImpl) query).values; - Quantifier quantifier = ((QuantifiedSelectImpl) query).quantifier; - Select subquery = ((QuantifiedSelectImpl) query).query; + boolean syntheticOperator = SYNTHETIC_OPERATORS.contains(comparator); + boolean quantifiedArray = query.array instanceof Param; - if (values != null || array instanceof Param) { + // [#9224] Special case when a SQL dialect actually supports quantified + // arrays, such as x = any(?::int[]) in PostgreSQL + if (quantifiedArray && SUPPORTS_QUANTIFIED_ARRAYS.contains(ctx.family()) && !syntheticOperator) { + accept1(ctx); + } + else if (query.values != null || quantifiedArray) { List conditions = new ArrayList<>(); - if (values != null) - for (Field value : values) + + if (query.values != null) + for (Field value : query.values) conditions.add(comparisonCondition(comparator, value)); else - for (Object value : ((Param) array).getValue()) + for (Object value : ((Param) query.array).getValue()) conditions.add(value instanceof Field ? comparisonCondition(comparator, (Field) value) : comparisonCondition(comparator, value)); - Condition combinedCondition = CombinedCondition.of(quantifier == Quantifier.ALL ? Operator.AND : Operator.OR, conditions); - ctx.visit(combinedCondition); + ctx.visit(CombinedCondition.of(query.quantifier == Quantifier.ALL ? Operator.AND : Operator.OR, conditions)); } - else if ((array != null || subquery != null) && SYNTHETIC_OPERATORS.contains(comparator)) { + else if ((query.array != null || query.query != null) && syntheticOperator) { Field pattern = DSL.field(name("pattern"), VARCHAR); Condition cond; Field lhs; @@ -141,9 +154,9 @@ final class QuantifiedComparisonCondition extends AbstractCondition implements L throw new IllegalStateException(); } - Table t = (array != null ? new ArrayTable(array) : subquery).asTable("t", "pattern"); + Table t = (query.array != null ? new ArrayTable(query.array) : query.query).asTable("t", "pattern"); Select> select = select(DSL.field(cond)).from(t); - ctx.visit(lhs.eq(quantifier.apply(select))); + ctx.visit(lhs.eq(query.quantifier.apply(select))); } else { accept1(ctx);