From 109e06203d73edc0ba0ccfcbb277a24d9eab0bb7 Mon Sep 17 00:00:00 2001 From: Lukas Eder Date: Tue, 9 Jul 2024 11:57:18 +0200 Subject: [PATCH] [jOOQ/jOOQ#13533] SQL Server MULTISET subquery ORDER BY clause doesn't work with UNION --- .../src/main/java/org/jooq/impl/Multiset.java | 53 ++++++++++++++++--- .../java/org/jooq/impl/SelectQueryImpl.java | 14 +++-- jOOQ/src/main/java/org/jooq/impl/Tools.java | 2 +- 3 files changed, 59 insertions(+), 10 deletions(-) diff --git a/jOOQ/src/main/java/org/jooq/impl/Multiset.java b/jOOQ/src/main/java/org/jooq/impl/Multiset.java index ee6859c0e3..cd3aab9912 100644 --- a/jOOQ/src/main/java/org/jooq/impl/Multiset.java +++ b/jOOQ/src/main/java/org/jooq/impl/Multiset.java @@ -41,23 +41,26 @@ import static java.lang.Boolean.TRUE; import static java.util.Arrays.asList; // ... // ... +// ... +import static org.jooq.SQLDialect.MARIADB; import static org.jooq.SQLDialect.MYSQL; -import static org.jooq.SQLDialect.*; +// ... import static org.jooq.SQLDialect.POSTGRES; +// ... +import static org.jooq.SQLDialect.TRINO; import static org.jooq.SQLDialect.YUGABYTEDB; import static org.jooq.impl.DSL.arrayAgg; -import static org.jooq.impl.DSL.field; import static org.jooq.impl.DSL.function; import static org.jooq.impl.DSL.inline; import static org.jooq.impl.DSL.jsonArray; import static org.jooq.impl.DSL.jsonEntry; import static org.jooq.impl.DSL.jsonbArray; +import static org.jooq.impl.DSL.noField; import static org.jooq.impl.DSL.row; import static org.jooq.impl.DSL.select; import static org.jooq.impl.DSL.selectFrom; // ... // ... -import static org.jooq.impl.DSL.toHex; import static org.jooq.impl.DSL.when; import static org.jooq.impl.DSL.xmlagg; import static org.jooq.impl.DSL.xmlattributes; @@ -76,6 +79,7 @@ import static org.jooq.impl.Names.N_RESULT; import static org.jooq.impl.Names.N_T; import static org.jooq.impl.SQLDataType.BLOB; import static org.jooq.impl.SQLDataType.CLOB; +import static org.jooq.impl.SQLDataType.INTEGER; import static org.jooq.impl.SQLDataType.JSON; import static org.jooq.impl.SQLDataType.JSONB; import static org.jooq.impl.SQLDataType.VARCHAR; @@ -87,10 +91,12 @@ import static org.jooq.impl.Tools.filter; import static org.jooq.impl.Tools.map; import static org.jooq.impl.Tools.selectQueryImpl; import static org.jooq.impl.Tools.sortable; +import static org.jooq.impl.Tools.unqualified; import static org.jooq.impl.Tools.visitSubquery; import static org.jooq.impl.Tools.BooleanDataKey.DATA_MULTISET_CONDITION; import static org.jooq.impl.Tools.BooleanDataKey.DATA_MULTISET_CONTENT; +import java.util.ArrayList; import java.util.Arrays; import java.util.Collection; import java.util.List; @@ -113,6 +119,7 @@ import org.jooq.JSONEntry; import org.jooq.JSONObjectNullStep; import org.jooq.JSONObjectReturningStep; import org.jooq.Name; +// ... import org.jooq.QueryPart; import org.jooq.Record; import org.jooq.Record1; @@ -121,8 +128,8 @@ import org.jooq.Result; import org.jooq.SQLDialect; import org.jooq.Scope; import org.jooq.Select; -import org.jooq.SelectJoinStep; import org.jooq.SelectOrderByStep; +import org.jooq.SortField; import org.jooq.Spatial; import org.jooq.Table; import org.jooq.TableLike; @@ -130,8 +137,6 @@ import org.jooq.TableLike; import org.jooq.XML; import org.jooq.XMLAggOrderByStep; -import org.jetbrains.annotations.NotNull; - /** * @author Lukas Eder */ @@ -180,6 +185,40 @@ final class Multiset extends AbstractField> implemen ctx.data(DATA_MULTISET_CONTENT, true, c -> accept0(c, false)); } + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + @SuppressWarnings("unchecked") private final void accept0(Context ctx, boolean multisetCondition) { switch (emulateMultiset(ctx.configuration())) { @@ -207,6 +246,7 @@ final class Multiset extends AbstractField> implemen + default: { if (NO_SUPPORT_CORRELATED_DERIVED_TABLE.contains(ctx.dialect()) && isSimple(select)) { List> l = map(select.getSelect(), f -> Tools.unalias(f)); @@ -283,6 +323,7 @@ final class Multiset extends AbstractField> implemen + default: { if (NO_SUPPORT_CORRELATED_DERIVED_TABLE.contains(ctx.dialect()) && isSimple(select)) { diff --git a/jOOQ/src/main/java/org/jooq/impl/SelectQueryImpl.java b/jOOQ/src/main/java/org/jooq/impl/SelectQueryImpl.java index 682dec3e10..0e6c3d5af7 100644 --- a/jOOQ/src/main/java/org/jooq/impl/SelectQueryImpl.java +++ b/jOOQ/src/main/java/org/jooq/impl/SelectQueryImpl.java @@ -3579,15 +3579,23 @@ final class SelectQueryImpl extends AbstractResultQuery imp } // [#13509] Force a LIMIT clause to prevent optimisation of "unnecessary" ORDER BY - else if (!actualOrderBy.isEmpty() && TRUE.equals(ctx.data(DATA_FORCE_LIMIT_WITH_ORDER_BY))) { + // [#13533] A variant of this are dialects where ORDER BY in subqueries is only syntactically valid with LIMIT + else if (!actualOrderBy.isEmpty() + && ( + TRUE.equals(ctx.data(DATA_FORCE_LIMIT_WITH_ORDER_BY)) + + + + ) + ) { Limit l = new Limit(); switch (ctx.family()) { case TRINO: - l.setLimit(Integer.MAX_VALUE); + l.setLimit(inline(Integer.MAX_VALUE)); break; default: - l.setLimit(Long.MAX_VALUE); + l.setLimit(inline(Long.MAX_VALUE)); break; } diff --git a/jOOQ/src/main/java/org/jooq/impl/Tools.java b/jOOQ/src/main/java/org/jooq/impl/Tools.java index affbc4d5c8..ab0c4ecec6 100644 --- a/jOOQ/src/main/java/org/jooq/impl/Tools.java +++ b/jOOQ/src/main/java/org/jooq/impl/Tools.java @@ -1789,7 +1789,7 @@ final class Tools { } static final Field unqualified(Field field) { - return DSL.field(field.getUnqualifiedName(), field.getDataType()); + return field instanceof TableField ? DSL.field(field.getUnqualifiedName(), field.getDataType()) : field; } static final SortField unqualified(SortField field) {