diff --git a/jOOQ/src/main/java/org/jooq/Context.java b/jOOQ/src/main/java/org/jooq/Context.java index aeca6f6191..65f92d31c3 100644 --- a/jOOQ/src/main/java/org/jooq/Context.java +++ b/jOOQ/src/main/java/org/jooq/Context.java @@ -258,6 +258,17 @@ public interface Context> 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. diff --git a/jOOQ/src/main/java/org/jooq/impl/AbstractContext.java b/jOOQ/src/main/java/org/jooq/impl/AbstractContext.java index e7f53cf950..70e2a7705c 100644 --- a/jOOQ/src/main/java/org/jooq/impl/AbstractContext.java +++ b/jOOQ/src/main/java/org/jooq/impl/AbstractContext.java @@ -124,6 +124,7 @@ abstract class AbstractContext> extends AbstractScope imple BitSet subqueryScopedNestedSetOperations; boolean predicandSubquery; boolean derivedTableSubquery; + boolean setOperationSubquery; int stringLiteral; String stringLiteralEscapedApos = "'"; int index; @@ -314,7 +315,7 @@ abstract class AbstractContext> 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> 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++; diff --git a/jOOQ/src/main/java/org/jooq/impl/Alias.java b/jOOQ/src/main/java/org/jooq/impl/Alias.java index de88a46bdb..19ed3baacc 100644 --- a/jOOQ/src/main/java/org/jooq/impl/Alias.java +++ b/jOOQ/src/main/java/org/jooq/impl/Alias.java @@ -214,7 +214,7 @@ final class Alias 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 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); } } } diff --git a/jOOQ/src/main/java/org/jooq/impl/AliasedSelect.java b/jOOQ/src/main/java/org/jooq/impl/AliasedSelect.java index ae1c523fee..9204632d1e 100644 --- a/jOOQ/src/main/java/org/jooq/impl/AliasedSelect.java +++ b/jOOQ/src/main/java/org/jooq/impl/AliasedSelect.java @@ -120,9 +120,9 @@ final class AliasedSelect extends AbstractTable 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 diff --git a/jOOQ/src/main/java/org/jooq/impl/ArrayQuery.java b/jOOQ/src/main/java/org/jooq/impl/ArrayQuery.java index 69a0e5ce62..6faa3e803a 100644 --- a/jOOQ/src/main/java/org/jooq/impl/ArrayQuery.java +++ b/jOOQ/src/main/java/org/jooq/impl/ArrayQuery.java @@ -82,7 +82,7 @@ final class ArrayQuery extends AbstractField implements QOM.ArrayQuery extends AbstractTable } - visitSubquery(ctx, s, true, false); + visitSubquery(ctx, s, true, false, false); diff --git a/jOOQ/src/main/java/org/jooq/impl/DerivedTable.java b/jOOQ/src/main/java/org/jooq/impl/DerivedTable.java index 68d092e8b8..3724321d6d 100644 --- a/jOOQ/src/main/java/org/jooq/impl/DerivedTable.java +++ b/jOOQ/src/main/java/org/jooq/impl/DerivedTable.java @@ -94,7 +94,7 @@ class DerivedTable extends AbstractTable implements QOM.Der - visitSubquery(ctx, query, true, false, false); + visitSubquery(ctx, query, true, false, false, false); } @Override // Avoid AbstractTable implementation diff --git a/jOOQ/src/main/java/org/jooq/impl/Exists.java b/jOOQ/src/main/java/org/jooq/impl/Exists.java index 62b7c6d2d8..30fd7d0f97 100644 --- a/jOOQ/src/main/java/org/jooq/impl/Exists.java +++ b/jOOQ/src/main/java/org/jooq/impl/Exists.java @@ -105,7 +105,7 @@ implements default: ctx.visit(K_EXISTS).sql(' '); - visitSubquery(ctx, query, false, true); + visitSubquery(ctx, query, false, false, true); break; } } diff --git a/jOOQ/src/main/java/org/jooq/impl/GenerateSeries.java b/jOOQ/src/main/java/org/jooq/impl/GenerateSeries.java index de1b227718..87281b38a6 100644 --- a/jOOQ/src/main/java/org/jooq/impl/GenerateSeries.java +++ b/jOOQ/src/main/java/org/jooq/impl/GenerateSeries.java @@ -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 + + diff --git a/jOOQ/src/main/java/org/jooq/impl/JSONTable.java b/jOOQ/src/main/java/org/jooq/impl/JSONTable.java index 4034360285..775c7d00e2 100644 --- a/jOOQ/src/main/java/org/jooq/impl/JSONTable.java +++ b/jOOQ/src/main/java/org/jooq/impl/JSONTable.java @@ -230,6 +230,7 @@ implements path ), true, + false, false ); } diff --git a/jOOQ/src/main/java/org/jooq/impl/Multiset.java b/jOOQ/src/main/java/org/jooq/impl/Multiset.java index 44ffb47d2c..5129853339 100644 --- a/jOOQ/src/main/java/org/jooq/impl/Multiset.java +++ b/jOOQ/src/main/java/org/jooq/impl/Multiset.java @@ -168,6 +168,7 @@ final class Multiset extends AbstractField> implemen + default: { JSONArrayAggOrderByStep order; JSONArrayAggReturningStep returning; @@ -189,7 +190,7 @@ final class Multiset extends AbstractField> 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 extends AbstractField> implemen + default: { JSONArrayAggOrderByStep order; JSONArrayAggReturningStep returning; @@ -242,7 +244,7 @@ final class Multiset extends AbstractField> 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 extends AbstractField> 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 extends AbstractField> implemen } case NATIVE: - visitSubquery(ctx.visit(K_MULTISET), select, false, false); + visitSubquery(ctx.visit(K_MULTISET), select, false, false, false); break; } } diff --git a/jOOQ/src/main/java/org/jooq/impl/QuantifiedSelectImpl.java b/jOOQ/src/main/java/org/jooq/impl/QuantifiedSelectImpl.java index bf9f581da4..85a33e191d 100644 --- a/jOOQ/src/main/java/org/jooq/impl/QuantifiedSelectImpl.java +++ b/jOOQ/src/main/java/org/jooq/impl/QuantifiedSelectImpl.java @@ -111,7 +111,7 @@ final class QuantifiedSelectImpl 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; } diff --git a/jOOQ/src/main/java/org/jooq/impl/RowIsDistinctFrom.java b/jOOQ/src/main/java/org/jooq/impl/RowIsDistinctFrom.java index 7392cffe1e..0ac56ef958 100644 --- a/jOOQ/src/main/java/org/jooq/impl/RowIsDistinctFrom.java +++ b/jOOQ/src/main/java/org/jooq/impl/RowIsDistinctFrom.java @@ -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); } diff --git a/jOOQ/src/main/java/org/jooq/impl/RowSubqueryCondition.java b/jOOQ/src/main/java/org/jooq/impl/RowSubqueryCondition.java index 749b3066b5..f2daaf7c8b 100644 --- a/jOOQ/src/main/java/org/jooq/impl/RowSubqueryCondition.java +++ b/jOOQ/src/main/java/org/jooq/impl/RowSubqueryCondition.java @@ -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 ? "))" : ")"); } diff --git a/jOOQ/src/main/java/org/jooq/impl/ScalarSubquery.java b/jOOQ/src/main/java/org/jooq/impl/ScalarSubquery.java index b354057a7f..69f6da85a1 100644 --- a/jOOQ/src/main/java/org/jooq/impl/ScalarSubquery.java +++ b/jOOQ/src/main/java/org/jooq/impl/ScalarSubquery.java @@ -86,9 +86,9 @@ final class ScalarSubquery extends AbstractField 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); } // ------------------------------------------------------------------------- diff --git a/jOOQ/src/main/java/org/jooq/impl/SelectIsNotNull.java b/jOOQ/src/main/java/org/jooq/impl/SelectIsNotNull.java index 7db83bed38..e1028034b8 100644 --- a/jOOQ/src/main/java/org/jooq/impl/SelectIsNotNull.java +++ b/jOOQ/src/main/java/org/jooq/impl/SelectIsNotNull.java @@ -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()) { diff --git a/jOOQ/src/main/java/org/jooq/impl/SelectIsNull.java b/jOOQ/src/main/java/org/jooq/impl/SelectIsNull.java index 030fbae894..ce12d618df 100644 --- a/jOOQ/src/main/java/org/jooq/impl/SelectIsNull.java +++ b/jOOQ/src/main/java/org/jooq/impl/SelectIsNull.java @@ -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()) { diff --git a/jOOQ/src/main/java/org/jooq/impl/SplitPart.java b/jOOQ/src/main/java/org/jooq/impl/SplitPart.java index 81fc2e36b9..bce53b5835 100644 --- a/jOOQ/src/main/java/org/jooq/impl/SplitPart.java +++ b/jOOQ/src/main/java/org/jooq/impl/SplitPart.java @@ -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; diff --git a/jOOQ/src/main/java/org/jooq/impl/Tools.java b/jOOQ/src/main/java/org/jooq/impl/Tools.java index 99906e7a29..0b4a15fab3 100644 --- a/jOOQ/src/main/java/org/jooq/impl/Tools.java +++ b/jOOQ/src/main/java/org/jooq/impl/Tools.java @@ -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); diff --git a/jOOQ/src/main/java/org/jooq/impl/Unique.java b/jOOQ/src/main/java/org/jooq/impl/Unique.java index c5350ab524..05c6e25e66 100644 --- a/jOOQ/src/main/java/org/jooq/impl/Unique.java +++ b/jOOQ/src/main/java/org/jooq/impl/Unique.java @@ -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: diff --git a/jOOQ/src/main/java/org/jooq/impl/UpdateQueryImpl.java b/jOOQ/src/main/java/org/jooq/impl/UpdateQueryImpl.java index 659caceb92..42ddb91d00 100644 --- a/jOOQ/src/main/java/org/jooq/impl/UpdateQueryImpl.java +++ b/jOOQ/src/main/java/org/jooq/impl/UpdateQueryImpl.java @@ -650,7 +650,7 @@ final class UpdateQueryImpl extends AbstractStoreQuery impl else select = multiSelect; - visitSubquery(ctx, select, false, false); + visitSubquery(ctx, select, false, false, false); } ctx.formatIndentEnd().end(UPDATE_SET_ASSIGNMENT); diff --git a/jOOQ/src/main/java/org/jooq/impl/Values.java b/jOOQ/src/main/java/org/jooq/impl/Values.java index f1da915968..41f889a555 100644 --- a/jOOQ/src/main/java/org/jooq/impl/Values.java +++ b/jOOQ/src/main/java/org/jooq/impl/Values.java @@ -183,7 +183,7 @@ final class Values extends AbstractTable implements QOM.Val selects = selects.unionAll(select); } - visitSubquery(ctx, selects, true, false, false); + visitSubquery(ctx, selects, true, false, false, false); } diff --git a/jOOQ/src/main/java/org/jooq/impl/XMLTable.java b/jOOQ/src/main/java/org/jooq/impl/XMLTable.java index f2a250f837..53f5fe0abf 100644 --- a/jOOQ/src/main/java/org/jooq/impl/XMLTable.java +++ b/jOOQ/src/main/java/org/jooq/impl/XMLTable.java @@ -263,6 +263,7 @@ implements + private final void acceptStandard(Context ctx) {