From 1fdb63b6fd899aaa8578fe7718da1a18f95cee46 Mon Sep 17 00:00:00 2001 From: Lukas Eder Date: Fri, 22 Dec 2023 13:57:36 +0100 Subject: [PATCH] [jOOQ/jOOQ#15980] Regression in PostgreSQL query using 'x' = ANY (ARRAY [(SELECT ARRAY ['x'])]) style quantified comparison predicate on multi dimensional arrays This includes: - [jOOQ/jOOQ#15982] Comparison predicates and quantified comparison predicates should hint array type to org.jooq.impl.Array for empty expression array casts --- jOOQ/src/main/java/org/jooq/impl/Array.java | 10 +++++++++- jOOQ/src/main/java/org/jooq/impl/Eq.java | 4 ++++ jOOQ/src/main/java/org/jooq/impl/EqQuantified.java | 7 +++++-- jOOQ/src/main/java/org/jooq/impl/Tools.java | 5 +++++ 4 files changed, 23 insertions(+), 3 deletions(-) diff --git a/jOOQ/src/main/java/org/jooq/impl/Array.java b/jOOQ/src/main/java/org/jooq/impl/Array.java index 5d9120768d..78f4951144 100644 --- a/jOOQ/src/main/java/org/jooq/impl/Array.java +++ b/jOOQ/src/main/java/org/jooq/impl/Array.java @@ -46,6 +46,7 @@ import static org.jooq.impl.Cast.renderCastIf; import static org.jooq.impl.Keywords.K_ARRAY; import static org.jooq.impl.Keywords.K_INT; import static org.jooq.impl.Names.N_ARRAY; +import static org.jooq.impl.Tools.ExtendedDataKey.DATA_EMPTY_ARRAY_BASE_TYPE; import java.util.Collection; import java.util.Set; @@ -107,7 +108,14 @@ final class Array extends AbstractField implements QOM.Array { break; } }, - c -> c.visit(K_INT).sql("[]"), + c -> { + DataType type = (DataType) c.data(DATA_EMPTY_ARRAY_BASE_TYPE); + + if (type != null && !type.isOther()) + c.sql(type.getCastTypeName(ctx.configuration())).sql("[]"); + else + c.visit(K_INT).sql("[]"); + }, () -> fields.fields.length == 0 && REQUIRES_CAST.contains(ctx.dialect()) ); diff --git a/jOOQ/src/main/java/org/jooq/impl/Eq.java b/jOOQ/src/main/java/org/jooq/impl/Eq.java index abc775b6e6..ea52fecb69 100644 --- a/jOOQ/src/main/java/org/jooq/impl/Eq.java +++ b/jOOQ/src/main/java/org/jooq/impl/Eq.java @@ -151,6 +151,10 @@ implements + else if (arg1 instanceof Array && ((Array) arg1).fields.fields.length == 0) + ctx.data(ExtendedDataKey.DATA_EMPTY_ARRAY_BASE_TYPE, arg2.getDataType().getArrayComponentDataType(), c -> acceptDefault.apply(c, arg1, arg2)); + else if (arg2 instanceof Array && ((Array) arg2).fields.fields.length == 0) + ctx.data(ExtendedDataKey.DATA_EMPTY_ARRAY_BASE_TYPE, arg1.getDataType().getArrayComponentDataType(), c -> acceptDefault.apply(c, arg1, arg2)); else acceptDefault.apply(ctx, arg1, arg2); } diff --git a/jOOQ/src/main/java/org/jooq/impl/EqQuantified.java b/jOOQ/src/main/java/org/jooq/impl/EqQuantified.java index f216ff8a53..d724d29281 100644 --- a/jOOQ/src/main/java/org/jooq/impl/EqQuantified.java +++ b/jOOQ/src/main/java/org/jooq/impl/EqQuantified.java @@ -179,8 +179,11 @@ implements // [#9224] Special case when a SQL dialect actually supports quantified // arrays, such as x = any(?::int[]) in PostgreSQL - if (quantifiedArrayParam && SUPPORTS_QUANTIFIED_ARRAYS.contains(ctx.dialect()) && !emulateOperator) { - accept1(ctx, arg1, op, arg2); + if ((quantifiedArrayParam || quantifiedArray) && SUPPORTS_QUANTIFIED_ARRAYS.contains(ctx.dialect()) && !emulateOperator) { + if (quantifiedArray && ((Array) ((QOM.QuantifiedArray) arg2).$arg2()).fields.fields.length == 0) + ctx.data(DATA_EMPTY_ARRAY_BASE_TYPE, arg1.getDataType(), c -> accept1(c, arg1, op, arg2)); + else + accept1(ctx, arg1, op, arg2); } else if (quantifiedArrayParam || quantifiedArray) { QOM.QuantifiedArray a = (org.jooq.impl.QOM.QuantifiedArray) arg2; diff --git a/jOOQ/src/main/java/org/jooq/impl/Tools.java b/jOOQ/src/main/java/org/jooq/impl/Tools.java index 68cba7d804..85b5ba1096 100644 --- a/jOOQ/src/main/java/org/jooq/impl/Tools.java +++ b/jOOQ/src/main/java/org/jooq/impl/Tools.java @@ -966,6 +966,11 @@ final class Tools { */ DATA_RENDER_TABLE(true, null, 0), + /** + * [#15982] The base type of an empty array in the current scope. + */ + DATA_EMPTY_ARRAY_BASE_TYPE + ; private final boolean resetInSubqueryScope;