diff --git a/jOOQ/src/main/java/org/jooq/Asterisk.java b/jOOQ/src/main/java/org/jooq/Asterisk.java index b0b9432194..6e6d594429 100644 --- a/jOOQ/src/main/java/org/jooq/Asterisk.java +++ b/jOOQ/src/main/java/org/jooq/Asterisk.java @@ -37,8 +37,6 @@ */ package org.jooq; -import static org.jooq.SQLDialect.H2; - import org.jooq.impl.DSL; /** @@ -77,7 +75,7 @@ public interface Asterisk extends SelectFieldOrAsterisk { * dialects (e.g. {@link SQLDialect#H2}) implement this feature natively. In * other dialects, jOOQ expands the asterisk if possible. */ - @Support({ H2 }) + @Support Asterisk except(String... fieldNames); /** @@ -87,7 +85,7 @@ public interface Asterisk extends SelectFieldOrAsterisk { * dialects (e.g. {@link SQLDialect#H2}) implement this feature natively. In * other dialects, jOOQ expands the asterisk if possible. */ - @Support({ H2 }) + @Support Asterisk except(Name... fieldNames); /** @@ -97,6 +95,6 @@ public interface Asterisk extends SelectFieldOrAsterisk { * dialects (e.g. {@link SQLDialect#H2}) implement this feature natively. In * other dialects, jOOQ expands the asterisk if possible. */ - @Support({ H2 }) + @Support Asterisk except(Field... fields); } diff --git a/jOOQ/src/main/java/org/jooq/QualifiedAsterisk.java b/jOOQ/src/main/java/org/jooq/QualifiedAsterisk.java index d042541e36..22520234a1 100644 --- a/jOOQ/src/main/java/org/jooq/QualifiedAsterisk.java +++ b/jOOQ/src/main/java/org/jooq/QualifiedAsterisk.java @@ -37,8 +37,6 @@ */ package org.jooq; -import static org.jooq.SQLDialect.H2; - /** * A qualified asterisk. *

@@ -79,7 +77,7 @@ public interface QualifiedAsterisk extends SelectFieldOrAsterisk { * dialects (e.g. {@link SQLDialect#H2}) implement this feature natively. In * other dialects, jOOQ expands the asterisk if possible. */ - @Support({ H2 }) + @Support QualifiedAsterisk except(String... fieldNames); /** @@ -90,7 +88,7 @@ public interface QualifiedAsterisk extends SelectFieldOrAsterisk { * dialects (e.g. {@link SQLDialect#H2}) implement this feature natively. In * other dialects, jOOQ expands the asterisk if possible. */ - @Support({ H2 }) + @Support QualifiedAsterisk except(Name... fieldNames); /** @@ -101,7 +99,7 @@ public interface QualifiedAsterisk extends SelectFieldOrAsterisk { * dialects (e.g. {@link SQLDialect#H2}) implement this feature natively. In * other dialects, jOOQ expands the asterisk if possible. */ - @Support({ H2 }) + @Support QualifiedAsterisk except(Field... fields); } diff --git a/jOOQ/src/main/java/org/jooq/impl/AsteriskImpl.java b/jOOQ/src/main/java/org/jooq/impl/AsteriskImpl.java index 2b531d0359..c6704e798c 100644 --- a/jOOQ/src/main/java/org/jooq/impl/AsteriskImpl.java +++ b/jOOQ/src/main/java/org/jooq/impl/AsteriskImpl.java @@ -66,16 +66,10 @@ final class AsteriskImpl extends AbstractQueryPart implements Asterisk { public final void accept(Context ctx) { ctx.sql('*'); - if (!fields.isEmpty()) { - switch (ctx.family()) { - - // [#7921] H2 has native support for EXCEPT - case H2: - default: - ctx.sql(' ').visit(K_EXCEPT).sql(" (").visit(fields).sql(')'); - break; - } - } + // [#7921] H2 has native support for EXCEPT. Emulations are implemented + // in SelectQueryImpl + if (!fields.isEmpty()) + ctx.sql(' ').visit(K_EXCEPT).sql(" (").visit(fields).sql(')'); } @Override diff --git a/jOOQ/src/main/java/org/jooq/impl/QualifiedAsteriskImpl.java b/jOOQ/src/main/java/org/jooq/impl/QualifiedAsteriskImpl.java index 8eff117f8c..b96a52766b 100644 --- a/jOOQ/src/main/java/org/jooq/impl/QualifiedAsteriskImpl.java +++ b/jOOQ/src/main/java/org/jooq/impl/QualifiedAsteriskImpl.java @@ -69,16 +69,10 @@ final class QualifiedAsteriskImpl extends AbstractQueryPart implements Qualified public final void accept(Context ctx) { ctx.visit(table).sql('.').visit(AsteriskImpl.INSTANCE); - if (!fields.isEmpty()) { - switch (ctx.family()) { - - // [#7921] H2 has native support for EXCEPT - case H2: - default: - ctx.sql(' ').visit(K_EXCEPT).sql(" (").visit(fields).sql(')'); - break; - } - } + // [#7921] H2 has native support for EXCEPT. Emulations are implemented + // in SelectQueryImpl + if (!fields.isEmpty()) + ctx.sql(' ').visit(K_EXCEPT).sql(" (").visit(fields).sql(')'); } @Override diff --git a/jOOQ/src/main/java/org/jooq/impl/SelectQueryImpl.java b/jOOQ/src/main/java/org/jooq/impl/SelectQueryImpl.java index 2657391bb1..8676bb3b3b 100644 --- a/jOOQ/src/main/java/org/jooq/impl/SelectQueryImpl.java +++ b/jOOQ/src/main/java/org/jooq/impl/SelectQueryImpl.java @@ -1265,7 +1265,7 @@ final class SelectQueryImpl extends AbstractResultQuery imp // The default behaviour else { - context.visit(getSelect1()); + context.visit(getSelectResolveUnsupportedAsterisks(family)); } @@ -1833,7 +1833,7 @@ final class SelectQueryImpl extends AbstractResultQuery imp @Override public final void addSelect(Collection fields) { - getSelect0().addAll(fields); + getSelectAsSpecified().addAll(fields); } @Override @@ -2028,26 +2028,7 @@ final class SelectQueryImpl extends AbstractResultQuery imp @Override public final List> getSelect() { - List> result = new ArrayList>(); - - // [#7921] TODO Find a better, more efficient way to resolve asterisks - for (SelectFieldOrAsterisk f : getSelect1()) - if (f instanceof Field) - result.add((Field) f); - else if (f instanceof QualifiedAsterisk) - if (((QualifiedAsteriskImpl) f).fields.isEmpty()) - result.addAll(Arrays.asList(((QualifiedAsterisk) f).qualifier().fields())); - else - result.addAll(subtract(Arrays.asList(((QualifiedAsterisk) f).qualifier().fields()), (((QualifiedAsteriskImpl) f).fields))); - else if (f instanceof Asterisk) - if (((AsteriskImpl) f).fields.isEmpty()) - result.addAll(resolveAsterisk(new QueryPartList>())); - else - result.addAll(resolveAsterisk(new QueryPartList>(), ((AsteriskImpl) f).fields)); - else - throw new AssertionError("Type not supported: " + f); - - return result; + return getSelectResolveAllAsterisks(configuration().family()); } private final Collection> subtract(List> left, List> right) { @@ -2063,15 +2044,74 @@ final class SelectQueryImpl extends AbstractResultQuery imp return result; } - final SelectFieldList getSelect0() { + /** + * The select list as specified by the API user. + */ + final SelectFieldList getSelectAsSpecified() { return select; } - final SelectFieldList getSelect1() { - if (getSelect0().isEmpty()) + /** + * The select list with resolved implicit asterisks. + */ + final SelectFieldList getSelectResolveImplicitAsterisks() { + if (getSelectAsSpecified().isEmpty()) return resolveAsterisk(new SelectFieldList()); - return getSelect0(); + return getSelectAsSpecified(); + } + + /** + * The select list with resolved explicit asterisks (if they contain the + * except clause and that is not supported). + */ + final SelectFieldList getSelectResolveUnsupportedAsterisks(SQLDialect family) { + return getSelectResolveSomeAsterisks0(family, false); + } + + /** + * The select list with resolved explicit asterisks (if they contain the + * except clause and that is not supported). + */ + @SuppressWarnings({ "rawtypes", "unchecked" }) + final SelectFieldList> getSelectResolveAllAsterisks(SQLDialect family) { + return (SelectFieldList) getSelectResolveSomeAsterisks0(family, true); + } + + private final SelectFieldList getSelectResolveSomeAsterisks0(SQLDialect family, boolean resolveSupported) { + SelectFieldList result = new SelectFieldList(); + + // [#7921] Only H2 supports the * EXCEPT (..) syntax + boolean resolveExcept = resolveSupported || family != H2; + + // [#7921] TODO Find a better, more efficient way to resolve asterisks + for (SelectFieldOrAsterisk f : getSelectResolveImplicitAsterisks()) + if (f instanceof Field) + result.add(f); + else if (f instanceof QualifiedAsterisk) + if (((QualifiedAsteriskImpl) f).fields.isEmpty()) + if (resolveSupported) + result.addAll(Arrays.asList(((QualifiedAsterisk) f).qualifier().fields())); + else + result.add(f); + else if (resolveExcept) + result.addAll(subtract(Arrays.asList(((QualifiedAsterisk) f).qualifier().fields()), (((QualifiedAsteriskImpl) f).fields))); + else + result.add(f); + else if (f instanceof Asterisk) + if (((AsteriskImpl) f).fields.isEmpty()) + if (resolveSupported) + result.addAll(resolveAsterisk(new QueryPartList>())); + else + result.add(f); + else if (resolveExcept) + result.addAll(resolveAsterisk(new QueryPartList>(), ((AsteriskImpl) f).fields)); + else + result.add(f); + else + throw new AssertionError("Type not supported: " + f); + + return result; } private final >> Q resolveAsterisk(Q result) { @@ -2147,12 +2187,10 @@ final class SelectQueryImpl extends AbstractResultQuery imp // - on a single table // - a select * - if (getFrom().size() == 1 && getSelect0().isEmpty()) { + if (getFrom().size() == 1 && getSelectAsSpecified().isEmpty()) return (Class) getFrom().get(0).asTable().getRecordType(); - } - else { + else return (Class) RecordImpl.class; - } } final TableList getFrom() {