[jOOQ/jOOQ#13533] SQL Server MULTISET subquery ORDER BY clause doesn't work with UNION

This commit is contained in:
Lukas Eder 2024-07-09 11:57:18 +02:00
parent 77332e4ddb
commit 109e06203d
3 changed files with 59 additions and 10 deletions

View File

@ -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<R extends Record> extends AbstractField<Result<R>> 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<R extends Record> extends AbstractField<Result<R>> implemen
default: {
if (NO_SUPPORT_CORRELATED_DERIVED_TABLE.contains(ctx.dialect()) && isSimple(select)) {
List<Field<?>> l = map(select.getSelect(), f -> Tools.unalias(f));
@ -283,6 +323,7 @@ final class Multiset<R extends Record> extends AbstractField<Result<R>> implemen
default: {
if (NO_SUPPORT_CORRELATED_DERIVED_TABLE.contains(ctx.dialect()) && isSimple(select)) {

View File

@ -3579,15 +3579,23 @@ final class SelectQueryImpl<R extends Record> extends AbstractResultQuery<R> 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;
}

View File

@ -1789,7 +1789,7 @@ final class Tools {
}
static final <T> Field<T> unqualified(Field<T> field) {
return DSL.field(field.getUnqualifiedName(), field.getDataType());
return field instanceof TableField ? DSL.field(field.getUnqualifiedName(), field.getDataType()) : field;
}
static final <T> SortField<T> unqualified(SortField<T> field) {