diff --git a/jOOQ/src/main/java/org/jooq/Context.java b/jOOQ/src/main/java/org/jooq/Context.java index 2938bc130d..aeca6f6191 100644 --- a/jOOQ/src/main/java/org/jooq/Context.java +++ b/jOOQ/src/main/java/org/jooq/Context.java @@ -247,6 +247,17 @@ public interface Context> extends Scope { @NotNull C subquery(boolean subquery); + /** + * Whether the current context is rendering a derived table subquery. + */ + boolean derivedTableSubquery(); + + /** + * Set the new context value for {@link #derivedTableSubquery()}. + */ + @NotNull + C derivedTableSubquery(boolean derivedTableSubquery); + /** * 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 0b0bb29217..e7f53cf950 100644 --- a/jOOQ/src/main/java/org/jooq/impl/AbstractContext.java +++ b/jOOQ/src/main/java/org/jooq/impl/AbstractContext.java @@ -123,6 +123,7 @@ abstract class AbstractContext> extends AbstractScope imple int subquery; BitSet subqueryScopedNestedSetOperations; boolean predicandSubquery; + boolean derivedTableSubquery; int stringLiteral; String stringLiteralEscapedApos = "'"; int index; @@ -313,7 +314,7 @@ abstract class AbstractContext> extends AbstractScope imple @Override public final C visitSubquery(QueryPart part) { - Tools.visitSubquery(this, part, false); + Tools.visitSubquery(this, part, false, false); return (C) this; } @@ -658,6 +659,17 @@ abstract class AbstractContext> extends AbstractScope imple return (C) this; } + @Override + public final boolean derivedTableSubquery() { + return derivedTableSubquery; + } + + @Override + public final C derivedTableSubquery(boolean s) { + derivedTableSubquery = s; + return (C) this; + } + @Override public final boolean subquery() { return subquery > 0; diff --git a/jOOQ/src/main/java/org/jooq/impl/Alias.java b/jOOQ/src/main/java/org/jooq/impl/Alias.java index 1f004db3c1..de88a46bdb 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)), false); + visitSubquery(context, select(asterisk()).from(((Table) wrapped).as(alias)), true, false); } // [#1801] Some databases do not support "derived column names". @@ -287,15 +287,14 @@ final class Alias extends AbstractQueryPart implements UEmp } } - visitSubquery(context, select(fields).where(falseCondition()).unionAll(wrappedAsSelect), false); + visitSubquery(context, select(fields).where(falseCondition()).unionAll(wrappedAsSelect), true, false); } } } // The default behaviour - else { + else toSQLWrapped(context); - } // [#291] some aliases cause trouble, if they are not explicitly marked using "as" toSQLAs(context); diff --git a/jOOQ/src/main/java/org/jooq/impl/AliasedSelect.java b/jOOQ/src/main/java/org/jooq/impl/AliasedSelect.java index 2b52a61c1b..ae1c523fee 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)), false, false); + visitSubquery(ctx, selectFrom(query.asTable(DSL.name("t"), aliases)), true, false, false); else - ctx.data(DATA_SELECT_ALIASES, aliases, subquery ? c -> visitSubquery(c, query, false, false) : c -> c.visit(query)); + ctx.data(DATA_SELECT_ALIASES, aliases, subquery ? c -> visitSubquery(c, query, true, 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 c04c2377ff..69a0e5ce62 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, false); + visitSubquery(ctx, s, true, false); diff --git a/jOOQ/src/main/java/org/jooq/impl/DerivedTable.java b/jOOQ/src/main/java/org/jooq/impl/DerivedTable.java index caa11fdbaf..68d092e8b8 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, false, false); + visitSubquery(ctx, query, true, 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 997e970c34..62b7c6d2d8 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, true); + visitSubquery(ctx, query, 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 40b6cf88e5..de1b227718 100644 --- a/jOOQ/src/main/java/org/jooq/impl/GenerateSeries.java +++ b/jOOQ/src/main/java/org/jooq/impl/GenerateSeries.java @@ -157,6 +157,7 @@ implements withRecursive(name, name) .as(select(from).unionAll(select(iadd(f, step == null ? inline(1) : step)).from(name).where(f.lt(to)))) .select(f).from(name), + true, false ); } @@ -208,6 +209,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 8151d119dd..4034360285 100644 --- a/jOOQ/src/main/java/org/jooq/impl/JSONTable.java +++ b/jOOQ/src/main/java/org/jooq/impl/JSONTable.java @@ -229,6 +229,7 @@ implements json.getType() == JSONB.class ? json : json.cast(JSONB), path ), + true, false ); } diff --git a/jOOQ/src/main/java/org/jooq/impl/Multiset.java b/jOOQ/src/main/java/org/jooq/impl/Multiset.java index e3e3f619c8..44ffb47d2c 100644 --- a/jOOQ/src/main/java/org/jooq/impl/Multiset.java +++ b/jOOQ/src/main/java/org/jooq/impl/Multiset.java @@ -167,6 +167,7 @@ final class Multiset extends AbstractField> implemen + default: { JSONArrayAggOrderByStep order; JSONArrayAggReturningStep returning; @@ -188,7 +189,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); + visitSubquery(ctx, s, false, false); break; } @@ -219,6 +220,7 @@ final class Multiset extends AbstractField> implemen + default: { JSONArrayAggOrderByStep order; JSONArrayAggReturningStep returning; @@ -240,7 +242,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); + visitSubquery(ctx, s, false, false); break; } @@ -287,7 +289,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); + visitSubquery(ctx, s, false, false); break; } @@ -297,7 +299,7 @@ final class Multiset extends AbstractField> implemen } case NATIVE: - visitSubquery(ctx.visit(K_MULTISET), select, false); + visitSubquery(ctx.visit(K_MULTISET), select, 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 a41219b18c..bf9f581da4 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()), true, false); + visitSubquery(ctx, delegate(ctx.configuration()), 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 4d5bdbf5c6..7392cffe1e 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, true); + visitSubquery(ctx, rhsSelect, 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, true); + visitSubquery(ctx, rhsSelect, 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 bc6067cf97..749b3066b5 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, true, false)) + .data(BooleanDataKey.DATA_ROW_VALUE_EXPRESSION_PREDICATE_SUBQUERY, true, c -> visitSubquery(c, right, 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 4c57ce5e04..b354057a7f 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")), predicandSubquery); + visitSubquery(ctx, select(asterisk()).from(query.asTable("t")), false, predicandSubquery); else - visitSubquery(ctx, query, predicandSubquery); + visitSubquery(ctx, query, 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 03378fd065..7db83bed38 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, true); + visitSubquery(ctx, select, 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 dbc1cf3843..030fbae894 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, true); + visitSubquery(ctx, select, 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 fa9dbf6638..81fc2e36b9 100644 --- a/jOOQ/src/main/java/org/jooq/impl/SplitPart.java +++ b/jOOQ/src/main/java/org/jooq/impl/SplitPart.java @@ -176,6 +176,7 @@ implements visitSubquery( 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 ); break; diff --git a/jOOQ/src/main/java/org/jooq/impl/Tools.java b/jOOQ/src/main/java/org/jooq/impl/Tools.java index 5d9581606e..99906e7a29 100644 --- a/jOOQ/src/main/java/org/jooq/impl/Tools.java +++ b/jOOQ/src/main/java/org/jooq/impl/Tools.java @@ -2498,11 +2498,22 @@ final class Tools { return e; } - static final void visitSubquery(Context ctx, QueryPart query, boolean predicandSubquery) { - visitSubquery(ctx, query, predicandSubquery, true); + static final void visitSubquery( + Context ctx, + QueryPart query, + boolean derivedTableSubquery, + boolean predicandSubquery + ) { + visitSubquery(ctx, query, derivedTableSubquery, predicandSubquery, true); } - static final void visitSubquery(Context ctx, QueryPart query, boolean predicandSubquery, boolean parentheses) { + static final void visitSubquery( + Context ctx, + QueryPart query, + boolean derivedTableSubquery, + boolean predicandSubquery, + boolean parentheses + ) { @@ -2512,14 +2523,17 @@ final class Tools { ctx.sql('('); boolean previousPredicandSubquery = ctx.predicandSubquery(); + boolean previousDerivedTableSubquery = ctx.derivedTableSubquery(); ctx.subquery(true) .predicandSubquery(predicandSubquery) + .derivedTableSubquery(derivedTableSubquery) .formatIndentStart() .formatNewLine() .visit(query) .formatIndentEnd() .formatNewLine() + .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 1d9b442155..c5350ab524 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, true); + visitSubquery(ctx, query, 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 27b9bf00b0..659caceb92 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); + visitSubquery(ctx, select, 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 d7b9d0a80d..f1da915968 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, false, false); + visitSubquery(ctx, selects, true, 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 f06a0d35a0..f2a250f837 100644 --- a/jOOQ/src/main/java/org/jooq/impl/XMLTable.java +++ b/jOOQ/src/main/java/org/jooq/impl/XMLTable.java @@ -262,6 +262,7 @@ implements + private final void acceptStandard(Context ctx) {