[jOOQ/jOOQ#13509] MySQL may ignore MULTISET subquery ORDER BY clause
This commit is contained in:
parent
86373d9897
commit
4f5ad3ce74
@ -299,7 +299,7 @@ final class Alias<Q extends QueryPart> extends AbstractQueryPart implements UEmp
|
||||
// by pushing down projection aliases into the
|
||||
// derived table
|
||||
else
|
||||
context.sql('(').visit(new AliasedSelect<>(wrappedAsSelect, true, false, fieldAliases)).sql(')');
|
||||
context.sql('(').visit(new AliasedSelect<>(wrappedAsSelect, true, false, false, fieldAliases)).sql(')');
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@ -42,6 +42,7 @@ import static org.jooq.impl.DSL.selectFrom;
|
||||
import static org.jooq.impl.Names.NQ_SELECT;
|
||||
import static org.jooq.impl.Tools.selectQueryImpl;
|
||||
import static org.jooq.impl.Tools.visitSubquery;
|
||||
import static org.jooq.impl.Tools.BooleanDataKey.DATA_FORCE_LIMIT_WITH_ORDER_BY;
|
||||
import static org.jooq.impl.Tools.SimpleDataKey.DATA_SELECT_ALIASES;
|
||||
|
||||
import org.jooq.Clause;
|
||||
@ -65,18 +66,20 @@ final class AliasedSelect<R extends Record> extends AbstractTable<R> implements
|
||||
private final Select<R> query;
|
||||
private final boolean subquery;
|
||||
private final boolean ignoreOrderBy;
|
||||
private final boolean forceLimit;
|
||||
private final Name[] aliases;
|
||||
|
||||
AliasedSelect(Select<R> query, boolean subquery, boolean ignoreOrderBy) {
|
||||
this(query, subquery, ignoreOrderBy, Tools.fieldNames(Tools.degree(query)));
|
||||
AliasedSelect(Select<R> query, boolean subquery, boolean ignoreOrderBy, boolean forceLimit) {
|
||||
this(query, subquery, ignoreOrderBy, forceLimit, Tools.fieldNames(Tools.degree(query)));
|
||||
}
|
||||
|
||||
AliasedSelect(Select<R> query, boolean subquery, boolean ignoreOrderBy, Name... aliases) {
|
||||
AliasedSelect(Select<R> query, boolean subquery, boolean ignoreOrderBy, boolean forceLimit, Name... aliases) {
|
||||
super(TableOptions.expression(), NQ_SELECT);
|
||||
|
||||
this.query = query;
|
||||
this.subquery = subquery;
|
||||
this.ignoreOrderBy = ignoreOrderBy;
|
||||
this.forceLimit = forceLimit;
|
||||
this.aliases = aliases;
|
||||
}
|
||||
|
||||
@ -114,6 +117,13 @@ final class AliasedSelect<R extends Record> extends AbstractTable<R> implements
|
||||
|
||||
@Override
|
||||
public final void accept(Context<?> ctx) {
|
||||
if (forceLimit)
|
||||
ctx.data(DATA_FORCE_LIMIT_WITH_ORDER_BY, true, c -> accept0(c));
|
||||
else
|
||||
accept0(ctx);
|
||||
}
|
||||
|
||||
private final void accept0(Context<?> ctx) {
|
||||
SelectQueryImpl<R> q = selectQueryImpl(query);
|
||||
|
||||
// [#3679] [#10540] Without standardised UNION subquery column names,
|
||||
|
||||
@ -65,7 +65,7 @@ final class FetchCount extends AbstractResultQuery<Record1<Integer>> implements
|
||||
|
||||
@Override
|
||||
public final void accept(Context<?> ctx) {
|
||||
ctx.visit(select(count).from(new AliasedSelect<>(query, true, true).as("t")));
|
||||
ctx.visit(select(count).from(new AliasedSelect<>(query, true, true, false).as("t")));
|
||||
}
|
||||
|
||||
@SuppressWarnings({ "unchecked", "rawtypes" })
|
||||
|
||||
@ -853,7 +853,7 @@ implements
|
||||
|
||||
// [#6375] INSERT .. VALUES and INSERT .. SELECT distinction also in MERGE
|
||||
if (NO_SUPPORT_DERIVED_COLUMN_LIST_IN_MERGE_USING.contains(ctx.dialect()))
|
||||
t = new AliasedSelect<Record>((Select<Record>) s, true, true, map(f, Field::getUnqualifiedName, Name[]::new)).as("t");
|
||||
t = new AliasedSelect<Record>((Select<Record>) s, true, true, false, map(f, Field::getUnqualifiedName, Name[]::new)).as("t");
|
||||
else
|
||||
t = s.asTable("t", map(f, Field::getName, String[]::new));
|
||||
}
|
||||
|
||||
@ -40,16 +40,15 @@ package org.jooq.impl;
|
||||
import static java.lang.Boolean.TRUE;
|
||||
// ...
|
||||
// ...
|
||||
import static org.jooq.SQLDialect.MYSQL;
|
||||
// ...
|
||||
import static org.jooq.SQLDialect.POSTGRES;
|
||||
// ...
|
||||
import static org.jooq.SQLDialect.YUGABYTEDB;
|
||||
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.quotedName;
|
||||
import static org.jooq.impl.DSL.select;
|
||||
import static org.jooq.impl.DSL.selectFrom;
|
||||
import static org.jooq.impl.DSL.when;
|
||||
@ -154,7 +153,7 @@ final class Multiset<R extends Record> extends AbstractField<Result<R>> implemen
|
||||
private final void accept0(Context<?> ctx, boolean multisetCondition) {
|
||||
switch (emulateMultiset(ctx.configuration())) {
|
||||
case JSON: {
|
||||
Table<?> t = new AliasedSelect<>(select, true, false, fieldNames(select.getSelect().size())).as(DSL.name("t"), (Name[]) null);
|
||||
Table<?> t = new AliasedSelect<>(select, true, false, ctx.family() == MYSQL, fieldNames(select.getSelect().size())).as(DSL.name("t"), (Name[]) null);
|
||||
|
||||
switch (ctx.family()) {
|
||||
|
||||
@ -207,7 +206,7 @@ final class Multiset<R extends Record> extends AbstractField<Result<R>> implemen
|
||||
}
|
||||
|
||||
case JSONB: {
|
||||
Table<?> t = new AliasedSelect<>(select, true, false, fieldNames(select.getSelect().size())).as(DSL.name("t"), (Name[]) null);
|
||||
Table<?> t = new AliasedSelect<>(select, true, false, ctx.family() == MYSQL, fieldNames(select.getSelect().size())).as(DSL.name("t"), (Name[]) null);
|
||||
|
||||
switch (ctx.family()) {
|
||||
|
||||
@ -262,7 +261,7 @@ final class Multiset<R extends Record> extends AbstractField<Result<R>> implemen
|
||||
|
||||
case XML: {
|
||||
List<Field<?>> fields = select.getSelect();
|
||||
Table<?> t = new AliasedSelect<>(select, true, false, fieldNames(fields.size())).as(DSL.name("t"), (Name[]) null);
|
||||
Table<?> t = new AliasedSelect<>(select, true, false, ctx.family() == MYSQL, fieldNames(fields.size())).as(DSL.name("t"), (Name[]) null);
|
||||
|
||||
switch (ctx.family()) {
|
||||
|
||||
|
||||
@ -214,7 +214,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, name("pattern")).as("t");
|
||||
: new AliasedSelect<>(query.query, true, true, false, name("pattern")).as("t");
|
||||
Select<Record1<Boolean>> select = select(DSL.field(cond)).from(t);
|
||||
ctx.visit(lhs.eq(query.quantifier.apply(select)));
|
||||
}
|
||||
|
||||
@ -190,7 +190,7 @@ final class RowSubqueryCondition extends AbstractCondition implements UNotYetImp
|
||||
Name[] names = fieldNames(l.size());
|
||||
|
||||
return select()
|
||||
.from(new AliasedSelect<>(s, true, true, names).as(table))
|
||||
.from(new AliasedSelect<>(s, true, true, false, names).as(table))
|
||||
.where(c == null
|
||||
? noCondition()
|
||||
: new RowCondition(l, row(fieldsByName(table, names)), c));
|
||||
|
||||
@ -81,7 +81,7 @@ final class SelectIsNotNull extends AbstractCondition implements QOM.SelectIsNot
|
||||
acceptStandard(ctx);
|
||||
}
|
||||
else {
|
||||
Table<?> t = new AliasedSelect<>(select, true, true).as("t");
|
||||
Table<?> t = new AliasedSelect<>(select, true, true, false).as("t");
|
||||
ctx.visit(inline(1).eq(selectCount().from(t).where(allNotNull(t.fields()))));
|
||||
}
|
||||
}
|
||||
|
||||
@ -115,7 +115,7 @@ final class SelectIsNull extends AbstractCondition implements QOM.SelectIsNull {
|
||||
acceptStandard(ctx);
|
||||
}
|
||||
else {
|
||||
Table<?> t = new AliasedSelect<>(select, true, true).as("t");
|
||||
Table<?> t = new AliasedSelect<>(select, true, true, false).as("t");
|
||||
ctx.visit(inline(1).eq(selectCount().from(t).where(allNull(t.fields()))));
|
||||
}
|
||||
}
|
||||
|
||||
@ -207,6 +207,7 @@ import static org.jooq.impl.Tools.traverseJoins;
|
||||
import static org.jooq.impl.Tools.unalias;
|
||||
import static org.jooq.impl.Tools.unqualified;
|
||||
import static org.jooq.impl.Tools.BooleanDataKey.DATA_COLLECT_SEMI_ANTI_JOIN;
|
||||
import static org.jooq.impl.Tools.BooleanDataKey.DATA_FORCE_LIMIT_WITH_ORDER_BY;
|
||||
import static org.jooq.impl.Tools.BooleanDataKey.DATA_INSERT_SELECT;
|
||||
import static org.jooq.impl.Tools.BooleanDataKey.DATA_INSERT_SELECT_WITHOUT_INSERT_COLUMN_LIST;
|
||||
import static org.jooq.impl.Tools.BooleanDataKey.DATA_NESTED_SET_OPERATIONS;
|
||||
@ -3039,8 +3040,16 @@ final class SelectQueryImpl<R extends Record> extends AbstractResultQuery<R> imp
|
||||
.formatNewLine()
|
||||
.sql(") x");
|
||||
|
||||
if (TRUE.equals(ctx.data().get(DATA_RENDER_TRAILING_LIMIT_IF_APPLICABLE)) && actualLimit.isApplicable())
|
||||
ctx.visit(actualLimit);
|
||||
if (TRUE.equals(ctx.data(DATA_RENDER_TRAILING_LIMIT_IF_APPLICABLE))) {
|
||||
if (actualLimit.isApplicable()) {
|
||||
ctx.visit(actualLimit);
|
||||
}
|
||||
else if (!actualOrderBy.isEmpty() && TRUE.equals(ctx.data(DATA_FORCE_LIMIT_WITH_ORDER_BY))) {
|
||||
Limit l = new Limit();
|
||||
l.setLimit(Integer.MAX_VALUE);
|
||||
ctx.visit(l);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
private final boolean applySeekOnDerivedTable() {
|
||||
|
||||
@ -557,6 +557,14 @@ final class Tools {
|
||||
*/
|
||||
DATA_RENDER_TRAILING_LIMIT_IF_APPLICABLE,
|
||||
|
||||
/**
|
||||
* [#13509] In some cases, it may be desirable to enforce appending a
|
||||
* <code>LIMIT</code> clause, when there's an <code>ORDER BY</code>
|
||||
* clause, e.g. to prevent the optimiser from removing the seemingly
|
||||
* unnecessary sort.
|
||||
*/
|
||||
DATA_FORCE_LIMIT_WITH_ORDER_BY,
|
||||
|
||||
/**
|
||||
* [#3886] Whether a list has already been indented.
|
||||
*/
|
||||
@ -6146,7 +6154,7 @@ final class Tools {
|
||||
List<Field<?>> result = collect(flattenCollection(select));
|
||||
Name tableName = name("t");
|
||||
Name[] fieldNames = fieldNames(result.size());
|
||||
Table<?> t = new AliasedSelect<>(field.query, true, true, fieldNames).as("t");
|
||||
Table<?> t = new AliasedSelect<>(field.query, true, true, false, fieldNames).as("t");
|
||||
for (int i = 0; i < result.size(); i++)
|
||||
result.set(i, DSL.field(DSL.select(DSL.field(tableName.append(fieldNames[i]), result.get(i).getDataType())).from(t)));
|
||||
|
||||
|
||||
Loading…
Reference in New Issue
Block a user