From 3d52f6cc2fd02c37d78b18a9c5a3b6aa505e69ec Mon Sep 17 00:00:00 2001 From: Lukas Eder Date: Sun, 2 Oct 2011 15:39:29 +0000 Subject: [PATCH] [#756] CURSOR: Error when aliasing HSQLDB and Postgres UNNESTed tables --- .../src/org/jooq/test/jOOQAbstractTest.java | 73 ++++++++++--------- .../java/org/jooq/impl/AliasProviderImpl.java | 21 ++++++ .../main/java/org/jooq/impl/ArrayTable.java | 19 ++++- 3 files changed, 75 insertions(+), 38 deletions(-) diff --git a/jOOQ-test/src/org/jooq/test/jOOQAbstractTest.java b/jOOQ-test/src/org/jooq/test/jOOQAbstractTest.java index 6f215986e6..c85dc52125 100644 --- a/jOOQ-test/src/org/jooq/test/jOOQAbstractTest.java +++ b/jOOQ-test/src/org/jooq/test/jOOQAbstractTest.java @@ -6757,8 +6757,8 @@ public abstract class jOOQAbstractTest< assertEquals("1", "" + result.getValue(1, 0)); assertEquals("2", "" + result.getValue(2, 0)); - // Joining an array table - // ---------------------- + // Joining an unnested array table + // ------------------------------- array.set(2, 3); Table table = create().table(array); result = create() @@ -6774,6 +6774,8 @@ public abstract class jOOQAbstractTest< assertEquals("Animal Farm", result.getValue(0, TBook_TITLE())); assertEquals("O Alquimista", result.getValue(1, TBook_TITLE())); + // Joining an aliased unnested array table + // --------------------------------------- result = create() .select(TBook_ID(), TBook_TITLE()) .from(TBook()) @@ -6855,8 +6857,8 @@ public abstract class jOOQAbstractTest< assertEquals(1, result.getValue(1, 0)); assertEquals(2, result.getValue(2, 0)); - // Joining an array table - // ---------------------- + // Joining an unnested array table + // ------------------------------- array = new Integer[] { 2, 3 }; Table table = create().table(array); result = create() @@ -6872,46 +6874,49 @@ public abstract class jOOQAbstractTest< assertEquals("Animal Farm", result.getValue(0, TBook_TITLE())); assertEquals("O Alquimista", result.getValue(1, TBook_TITLE())); - // [#756] TODO : Error when aliasing HSQLDB and Postgres UNNESTed tables + // Joining an aliased unnested array table + // --------------------------------------- + result = create() + .select(TBook_ID(), TBook_TITLE()) + .from(TBook()) + .join(table.as("t")) + .on(table.as("t").getField(0).cast(Integer.class).equal(TBook_ID())) + .fetch(); + + assertEquals(2, result.size()); + assertEquals(Integer.valueOf(2), result.getValue(0, TBook_ID())); + assertEquals(Integer.valueOf(3), result.getValue(1, TBook_ID())); + assertEquals("Animal Farm", result.getValue(0, TBook_TITLE())); + assertEquals("O Alquimista", result.getValue(1, TBook_TITLE())); + + // Cross join the array table with the unnested string array value + // --------------------------------------------------------------- + switch (getDialect()) { - case HSQLDB: case POSTGRES: - log.info("SKIPPING", "Aliasing of ARRAY TABLE tests"); + case H2: + log.info("SKIPPING", "Cross join of table with unnested array is not supported"); break; default: + table = create().table(TArrays_STRING()).as("t"); result = create() - .select(TBook_ID(), TBook_TITLE()) - .from(TBook()) - .join(table.as("t")) - .on(table.as("t").getField(0).cast(Integer.class).equal(TBook_ID())) + .select(TArrays_ID(), table.getField(0)) + .from(TArrays(), table) + .orderBy(TArrays_ID()) .fetch(); - assertEquals(2, result.size()); - assertEquals(Integer.valueOf(2), result.getValue(0, TBook_ID())); - assertEquals(Integer.valueOf(3), result.getValue(1, TBook_ID())); - assertEquals("Animal Farm", result.getValue(0, TBook_TITLE())); - assertEquals("O Alquimista", result.getValue(1, TBook_TITLE())); -// -// -// table = create().table(TArrays_STRING()).as("t"); -// result = create() -// .select(TArrays_ID(), table.getField(0)) -// .from(TArrays(), table) -// .orderBy(TArrays_ID()) -// .fetch(); -// -// assertEquals(3, result.size()); -// assertEquals(Integer.valueOf(3), result.getValue(0, TArrays_ID())); -// assertEquals(Integer.valueOf(4), result.getValue(1, TArrays_ID())); -// assertEquals(Integer.valueOf(4), result.getValue(2, TArrays_ID())); -// -// assertEquals("a", result.getValue(0, 1)); -// assertEquals("a", result.getValue(1, 1)); -// assertEquals("b", result.getValue(2, 1)); - break; + assertEquals(3, result.size()); + assertEquals(Integer.valueOf(3), result.getValue(0, TArrays_ID())); + assertEquals(Integer.valueOf(4), result.getValue(1, TArrays_ID())); + assertEquals(Integer.valueOf(4), result.getValue(2, TArrays_ID())); + + assertEquals("a", result.getValue(0, 1)); + assertEquals("a", result.getValue(1, 1)); + assertEquals("b", result.getValue(2, 1)); } + // Functions returning arrays // -------------------------- result = create().select().from(create().table(FArrays1Field(null))).fetch(); diff --git a/jOOQ/src/main/java/org/jooq/impl/AliasProviderImpl.java b/jOOQ/src/main/java/org/jooq/impl/AliasProviderImpl.java index adef50e832..8640bef4e0 100644 --- a/jOOQ/src/main/java/org/jooq/impl/AliasProviderImpl.java +++ b/jOOQ/src/main/java/org/jooq/impl/AliasProviderImpl.java @@ -101,6 +101,27 @@ class AliasProviderImpl> extends AbstractNamedQueryPa context.sql(" "); context.literal(alias); + + // [#756] If the aliased object is an anonymous table (usually an + // unnested array), then field names must be part of the alias + // declaration. For example: + // + // SELECT t.column_value FROM UNNEST(ARRAY[1, 2]) AS t(column_value) + + switch (context.getDialect()) { + case HSQLDB: + case POSTGRES: { + if (context.declareTables() && aliasProvider instanceof ArrayTable) { + ArrayTable table = (ArrayTable) aliasProvider; + + context.sql("("); + table.getFields().toSQLNames(context); + context.sql(")"); + } + + break; + } + } } else { context.literal(alias); diff --git a/jOOQ/src/main/java/org/jooq/impl/ArrayTable.java b/jOOQ/src/main/java/org/jooq/impl/ArrayTable.java index f55ad9a79d..7c32374314 100644 --- a/jOOQ/src/main/java/org/jooq/impl/ArrayTable.java +++ b/jOOQ/src/main/java/org/jooq/impl/ArrayTable.java @@ -60,8 +60,13 @@ class ArrayTable extends AbstractTable { private final Field array; private final FieldList field; + private final String alias; ArrayTable(Field array) { + this(array, "array_table(COLUMN_VALUE)"); + } + + ArrayTable(Field array, String alias) { super("array_table"); Class arrayType; @@ -74,6 +79,7 @@ class ArrayTable extends AbstractTable { } this.array = array; + this.alias = alias; this.field = new FieldList(); this.field.add(create().field("COLUMN_VALUE", arrayType)); } @@ -85,8 +91,8 @@ class ArrayTable extends AbstractTable { } @Override - public final Table as(String alias) { - return new TableAlias(this, alias); + public final Table as(String as) { + return new TableAlias(new ArrayTable(array, ""), as); } @Override @@ -113,11 +119,16 @@ class ArrayTable extends AbstractTable { break; } + // [#756] These dialects need special care when aliasing unnested + // arrays case HSQLDB: case POSTGRES: { + context.sql("unnest(").sql(array).sql(")"); + + if (!StringUtils.isBlank(alias)) { + context.sql(" as ").sql(alias); + } - // [#756] TODO: Handle aliasing correctly - context.sql("unnest(").sql(array).sql(") array_table(COLUMN_VALUE)"); break; }