From 74e7051be35011361d830ee2bc72b7438e84f31c Mon Sep 17 00:00:00 2001 From: Lukas Eder Date: Thu, 3 Jan 2013 21:13:53 +0100 Subject: [PATCH] [#1801] Add Table.as(String, String...) to allow for creating a table aliases (correlation names) with derived column lists - Simulate derived column lists for Oracle using CTE's --- jOOQ/src/main/java/org/jooq/Table.java | 13 +++++ jOOQ/src/main/java/org/jooq/impl/Alias.java | 59 ++++++++++++++------- 2 files changed, 53 insertions(+), 19 deletions(-) diff --git a/jOOQ/src/main/java/org/jooq/Table.java b/jOOQ/src/main/java/org/jooq/Table.java index b5031ac6b1..c9f6e418c8 100644 --- a/jOOQ/src/main/java/org/jooq/Table.java +++ b/jOOQ/src/main/java/org/jooq/Table.java @@ -103,6 +103,19 @@ public interface Table extends FieldProvider, TableLike { * aliases. On the other hand, some databases do support derived column * lists, but only for derived tables. jOOQ will try to turn table * references into derived tables to make this syntax work. + *

+ * Other databases may not support derived column lists at all, but they do + * support common table expressions. The following two statements are + * equivalent:

+     * -- Using derived column lists to rename columns (e.g. Postgres)
+     * select * from (select 1) as u(b)
+     *
+     * -- Using common table expressions to rename columns (e.g. Oracle)
+     * select * from (
+     *   with u(b) as (select 1 from dual)
+     *   select * from u
+     * ) u
+     * 
* * @param alias The alias name * @param fieldAliases The field aliases. Excess aliases are ignored, diff --git a/jOOQ/src/main/java/org/jooq/impl/Alias.java b/jOOQ/src/main/java/org/jooq/impl/Alias.java index f42a02cead..4a299f9aab 100644 --- a/jOOQ/src/main/java/org/jooq/impl/Alias.java +++ b/jOOQ/src/main/java/org/jooq/impl/Alias.java @@ -42,6 +42,7 @@ import static org.jooq.SQLDialect.DERBY; import static org.jooq.SQLDialect.FIREBIRD; import static org.jooq.SQLDialect.HSQLDB; import static org.jooq.SQLDialect.MYSQL; +import static org.jooq.SQLDialect.ORACLE; import static org.jooq.SQLDialect.POSTGRES; import static org.jooq.SQLDialect.SQLSERVER; import static org.jooq.SQLDialect.SYBASE; @@ -49,6 +50,7 @@ import static org.jooq.SQLDialect.SYBASE; import org.jooq.BindContext; import org.jooq.QueryPart; import org.jooq.RenderContext; +import org.jooq.SQLDialect; /** * @author Lukas Eder @@ -87,14 +89,30 @@ class Alias extends AbstractQueryPart { @Override public final void toSQL(RenderContext context) { if (context.declareFields() || context.declareTables()) { + SQLDialect dialect = context.getDialect(); + boolean simulateDerivedColumnList = asList(ORACLE).contains(dialect); - // [#1801] Some databases don't allow "derived column names" in "simple - // class specifications". Hence, wrap the table reference in a subselect + // [#1801] Some databases don't support "derived column names" at + // all. They can be simulated using common table expressions + if (fieldAliases != null && simulateDerivedColumnList) { + context.keyword("(with") + .sql(" v"); + toSQLDerivedColumnList(context); + context.keyword(" as (select * from ") + .sql(wrapped) + .sql(") ") + .keyword("select * from") + .sql(" v)"); + } + + // [#1801] Some databases don't allow "derived column names" in + // "simple class specifications". Hence, wrap the table reference in + // a subselect // Feature requests placed here: // http://jira.cubrid.org/browse/ENGINE-96 // http://tracker.firebirdsql.org/browse/CORE-4025 - if (asList(CUBRID, FIREBIRD, SQLSERVER, SYBASE).contains(context.getDialect()) && fieldAliases != null && wrapped instanceof TableImpl) { + else if (fieldAliases != null && asList(CUBRID, FIREBIRD, SQLSERVER, SYBASE).contains(dialect) && wrapped instanceof TableImpl) { context.keyword("(select * from ") .sql(wrapped) .sql(")"); @@ -114,7 +132,7 @@ class Alias extends AbstractQueryPart { } // [#291] some aliases cause trouble, if they are not explicitly marked using "as" - if (asList(DERBY, HSQLDB, MYSQL, POSTGRES).contains(context.getDialect())) { + if (asList(DERBY, HSQLDB, MYSQL, POSTGRES).contains(dialect)) { context.keyword(" as"); } @@ -122,19 +140,8 @@ class Alias extends AbstractQueryPart { context.literal(alias); // [#1801] Add field aliases to the table alias, if applicable - if (fieldAliases != null) { - String separator = ""; - - context.sql("("); - - for (int i = 0; i < fieldAliases.length; i++) { - context.sql(separator); - context.literal(fieldAliases[i]); - - separator = ", "; - } - - context.sql(")"); + if (fieldAliases != null && !simulateDerivedColumnList) { + toSQLDerivedColumnList(context); } else { @@ -145,8 +152,7 @@ class Alias extends AbstractQueryPart { // SELECT t.column_value FROM UNNEST(ARRAY[1, 2]) AS t(column_value) // TODO: Is this still needed? - - switch (context.getDialect()) { + switch (dialect) { case HSQLDB: case POSTGRES: { // The javac compiler doesn't like casting of generics @@ -170,6 +176,21 @@ class Alias extends AbstractQueryPart { } } + private void toSQLDerivedColumnList(RenderContext context) { + String separator = ""; + + context.sql("("); + + for (int i = 0; i < fieldAliases.length; i++) { + context.sql(separator); + context.literal(fieldAliases[i]); + + separator = ", "; + } + + context.sql(")"); + } + @Override public final void bind(BindContext context) { if (context.declareFields() || context.declareTables()) {