[jOOQ/jOOQ#3497] Add Context::setOperationSubquery

This commit is contained in:
Lukas Eder 2022-02-23 12:29:27 +01:00
parent 3c2fb3721e
commit 3560816a62
23 changed files with 63 additions and 25 deletions

View File

@ -258,6 +258,17 @@ public interface Context<C extends Context<C>> extends Scope {
@NotNull
C derivedTableSubquery(boolean derivedTableSubquery);
/**
* Whether the current context is rendering a set operation subquery.
*/
boolean setOperationSubquery();
/**
* Set the new context value for {@link #setOperationSubquery()}.
*/
@NotNull
C setOperationSubquery(boolean setOperationSubquery);
/**
* Whether the current context is rendering a predicand subquery, i.e. a
* subquery that is an operand of a predicate.

View File

@ -124,6 +124,7 @@ abstract class AbstractContext<C extends Context<C>> extends AbstractScope imple
BitSet subqueryScopedNestedSetOperations;
boolean predicandSubquery;
boolean derivedTableSubquery;
boolean setOperationSubquery;
int stringLiteral;
String stringLiteralEscapedApos = "'";
int index;
@ -314,7 +315,7 @@ abstract class AbstractContext<C extends Context<C>> extends AbstractScope imple
@Override
public final C visitSubquery(QueryPart part) {
Tools.visitSubquery(this, part, false, false);
Tools.visitSubquery(this, part, false, false, false);
return (C) this;
}
@ -670,12 +671,25 @@ abstract class AbstractContext<C extends Context<C>> extends AbstractScope imple
return (C) this;
}
@Override
public final boolean setOperationSubquery() {
return setOperationSubquery;
}
@Override
public final C setOperationSubquery(boolean s) {
setOperationSubquery = s;
return (C) this;
}
@Override
public final boolean subquery() {
return subquery > 0;
}
final C subquery0(boolean s, boolean setOperation) {
setOperationSubquery(setOperation);
if (s) {
subquery++;

View File

@ -214,7 +214,7 @@ final class Alias<Q extends QueryPart> extends AbstractQueryPart implements UEmp
&& (SUPPORT_DERIVED_COLUMN_NAMES_SPECIAL1.contains(dialect))
&& (wrapped instanceof TableImpl || wrapped instanceof CommonTableExpressionImpl)) {
visitSubquery(context, select(asterisk()).from(((Table<?>) wrapped).as(alias)), true, false);
visitSubquery(context, select(asterisk()).from(((Table<?>) wrapped).as(alias)), true, false, false);
}
// [#1801] Some databases do not support "derived column names".
@ -287,7 +287,7 @@ final class Alias<Q extends QueryPart> extends AbstractQueryPart implements UEmp
}
}
visitSubquery(context, select(fields).where(falseCondition()).unionAll(wrappedAsSelect), true, false);
visitSubquery(context, select(fields).where(falseCondition()).unionAll(wrappedAsSelect), true, false, false);
}
}
}

View File

@ -120,9 +120,9 @@ final class AliasedSelect<R extends Record> extends AbstractTable<R> implements
// they cannot be referenced. In that case, revert to
// actual derived table usage.
if (ctx.family() == DERBY && q != null && q.hasUnions())
visitSubquery(ctx, selectFrom(query.asTable(DSL.name("t"), aliases)), true, false, false);
visitSubquery(ctx, selectFrom(query.asTable(DSL.name("t"), aliases)), true, false, false, false);
else
ctx.data(DATA_SELECT_ALIASES, aliases, subquery ? c -> visitSubquery(c, query, true, false, false) : c -> c.visit(query));
ctx.data(DATA_SELECT_ALIASES, aliases, subquery ? c -> visitSubquery(c, query, true, false, false, false) : c -> c.visit(query));
}
@Override // Avoid AbstractTable implementation

View File

@ -82,7 +82,7 @@ final class ArrayQuery<T> extends AbstractField<T[]> implements QOM.ArrayQuery<T
// [#11053] TODO: Move ORDER BY clause from subquery to ARRAY_AGG
// See https://github.com/jOOQ/jOOQ/issues/11053#issuecomment-735773248
visitSubquery(ctx, DSL.select(arrayAgg(c)).from(t), false, false);
visitSubquery(ctx, DSL.select(arrayAgg(c)).from(t), false, false, false);
break;
}

View File

@ -138,7 +138,7 @@ final class CommonTableExpressionImpl<R extends Record> extends AbstractTable<R>
}
visitSubquery(ctx, s, true, false);
visitSubquery(ctx, s, true, false, false);

View File

@ -94,7 +94,7 @@ class DerivedTable<R extends Record> extends AbstractTable<R> implements QOM.Der
visitSubquery(ctx, query, true, false, false);
visitSubquery(ctx, query, true, false, false, false);
}
@Override // Avoid AbstractTable implementation

View File

@ -105,7 +105,7 @@ implements
default:
ctx.visit(K_EXISTS).sql(' ');
visitSubquery(ctx, query, false, true);
visitSubquery(ctx, query, false, false, true);
break;
}
}

View File

@ -158,6 +158,7 @@ implements
.as(select(from).unionAll(select(iadd(f, step == null ? inline(1) : step)).from(name).where(f.lt(to))))
.select(f).from(name),
true,
false,
false
);
}
@ -211,6 +212,8 @@ implements

View File

@ -230,6 +230,7 @@ implements
path
),
true,
false,
false
);
}

View File

@ -168,6 +168,7 @@ final class Multiset<R extends Record> extends AbstractField<Result<R>> implemen
default: {
JSONArrayAggOrderByStep<JSON> order;
JSONArrayAggReturningStep<JSON> returning;
@ -189,7 +190,7 @@ final class Multiset<R extends Record> extends AbstractField<Result<R>> implemen
if (multisetCondition && NO_SUPPORT_JSON_COMPARE.contains(ctx.dialect()))
ctx.visit(DSL.field(s).cast(VARCHAR));
else
visitSubquery(ctx, s, false, false);
visitSubquery(ctx, s, false, false, false);
break;
}
@ -221,6 +222,7 @@ final class Multiset<R extends Record> extends AbstractField<Result<R>> implemen
default: {
JSONArrayAggOrderByStep<JSONB> order;
JSONArrayAggReturningStep<JSONB> returning;
@ -242,7 +244,7 @@ final class Multiset<R extends Record> extends AbstractField<Result<R>> implemen
if (multisetCondition && NO_SUPPORT_JSONB_COMPARE.contains(ctx.dialect()))
ctx.visit(DSL.field(s).cast(VARCHAR));
else
visitSubquery(ctx, s, false, false);
visitSubquery(ctx, s, false, false, false);
break;
}
@ -289,7 +291,7 @@ final class Multiset<R extends Record> extends AbstractField<Result<R>> implemen
if (multisetCondition && NO_SUPPORT_XML_COMPARE.contains(ctx.dialect()))
ctx.visit(xmlserializeContent(DSL.field(s), VARCHAR));
else
visitSubquery(ctx, s, false, false);
visitSubquery(ctx, s, false, false, false);
break;
}
@ -299,7 +301,7 @@ final class Multiset<R extends Record> extends AbstractField<Result<R>> implemen
}
case NATIVE:
visitSubquery(ctx.visit(K_MULTISET), select, false, false);
visitSubquery(ctx.visit(K_MULTISET), select, false, false, false);
break;
}
}

View File

@ -111,7 +111,7 @@ final class QuantifiedSelectImpl<R extends Record> extends AbstractQueryPart imp
default:
ctx.visit(quantifier.toKeyword());
ctx.sql(extraParentheses ? " ((" : " (");
visitSubquery(ctx, delegate(ctx.configuration()), false, true, false);
visitSubquery(ctx, delegate(ctx.configuration()), false, false, true, false);
ctx.sql(extraParentheses ? "))" : ")");
break;
}

View File

@ -138,7 +138,7 @@ final class RowIsDistinctFrom extends AbstractCondition implements UNotYetImplem
if (rhsRow != null)
ctx.visit(rhsRow);
else
visitSubquery(ctx, rhsSelect, false, true);
visitSubquery(ctx, rhsSelect, false, false, true);
if (!not)
ctx.sql(')');
@ -154,7 +154,7 @@ final class RowIsDistinctFrom extends AbstractCondition implements UNotYetImplem
if (rhsRow != null)
ctx.visit(rhsRow);
else
visitSubquery(ctx, rhsSelect, false, true);
visitSubquery(ctx, rhsSelect, false, false, true);
}

View File

@ -251,7 +251,7 @@ final class RowSubqueryCondition extends AbstractCondition implements UNotYetImp
boolean extraParentheses = false ;
ctx.sql(extraParentheses ? "((" : "(")
.data(BooleanDataKey.DATA_ROW_VALUE_EXPRESSION_PREDICATE_SUBQUERY, true, c -> visitSubquery(c, right, false, true, false))
.data(BooleanDataKey.DATA_ROW_VALUE_EXPRESSION_PREDICATE_SUBQUERY, true, c -> visitSubquery(c, right, false, false, true, false))
.sql(extraParentheses ? "))" : ")");
}

View File

@ -86,9 +86,9 @@ final class ScalarSubquery<T> extends AbstractField<T> implements QOM.ScalarSubq
// HSQLDB allows for using WITH inside of IN, see: https://sourceforge.net/p/hsqldb/bugs/1617/
// We'll still emulate CTE in scalar subqueries with a derived tables in all cases.
if (q != null && q.with != null && NO_SUPPORT_WITH_IN_SCALAR_SUBQUERY.contains(ctx.dialect()))
visitSubquery(ctx, select(asterisk()).from(query.asTable("t")), false, predicandSubquery);
visitSubquery(ctx, select(asterisk()).from(query.asTable("t")), false, false, predicandSubquery);
else
visitSubquery(ctx, query, false, predicandSubquery);
visitSubquery(ctx, query, false, false, predicandSubquery);
}
// -------------------------------------------------------------------------

View File

@ -90,7 +90,7 @@ final class SelectIsNotNull extends AbstractCondition implements QOM.SelectIsNot
}
private final void acceptStandard(Context<?> ctx) {
visitSubquery(ctx, select, false, true);
visitSubquery(ctx, select, false, false, true);
switch (ctx.family()) {

View File

@ -124,7 +124,7 @@ final class SelectIsNull extends AbstractCondition implements QOM.SelectIsNull {
}
private final void acceptStandard(Context<?> ctx) {
visitSubquery(ctx, select, false, true);
visitSubquery(ctx, select, false, false, true);
switch (ctx.family()) {

View File

@ -177,6 +177,7 @@ implements
ctx,
withRecursive(s1, s2).select(DSL.coalesce(DSL.max(DSL.field(name("x"))), inline(""))).from(s2).where(s2.field("n").eq((Field) n)),
true,
false,
false
);
break;

View File

@ -2502,15 +2502,17 @@ final class Tools {
Context<?> ctx,
QueryPart query,
boolean derivedTableSubquery,
boolean setOperationSubquery,
boolean predicandSubquery
) {
visitSubquery(ctx, query, derivedTableSubquery, predicandSubquery, true);
visitSubquery(ctx, query, derivedTableSubquery, setOperationSubquery, predicandSubquery, true);
}
static final void visitSubquery(
Context<?> ctx,
QueryPart query,
boolean derivedTableSubquery,
boolean setOperationSubquery,
boolean predicandSubquery,
boolean parentheses
) {
@ -2524,15 +2526,18 @@ final class Tools {
boolean previousPredicandSubquery = ctx.predicandSubquery();
boolean previousDerivedTableSubquery = ctx.derivedTableSubquery();
boolean previousSetOperationSubquery = ctx.setOperationSubquery();
ctx.subquery(true)
.predicandSubquery(predicandSubquery)
.derivedTableSubquery(derivedTableSubquery)
.setOperationSubquery(setOperationSubquery)
.formatIndentStart()
.formatNewLine()
.visit(query)
.formatIndentEnd()
.formatNewLine()
.setOperationSubquery(previousSetOperationSubquery)
.derivedTableSubquery(previousDerivedTableSubquery)
.predicandSubquery(previousPredicandSubquery)
.subquery(false);

View File

@ -103,7 +103,7 @@ implements
case H2:
ctx.visit(K_UNIQUE).sql(' ');
visitSubquery(ctx, query, false, true);
visitSubquery(ctx, query, false, false, true);
break;
default:

View File

@ -650,7 +650,7 @@ final class UpdateQueryImpl<R extends Record> extends AbstractStoreQuery<R> impl
else
select = multiSelect;
visitSubquery(ctx, select, false, false);
visitSubquery(ctx, select, false, false, false);
}
ctx.formatIndentEnd().end(UPDATE_SET_ASSIGNMENT);

View File

@ -183,7 +183,7 @@ final class Values<R extends Record> extends AbstractTable<R> implements QOM.Val
selects = selects.unionAll(select);
}
visitSubquery(ctx, selects, true, false, false);
visitSubquery(ctx, selects, true, false, false, false);
}

View File

@ -263,6 +263,7 @@ implements
private final void acceptStandard(Context<?> ctx) {