From 7acc26838a7a0ba4b7ffce17c1602ae6256e041e Mon Sep 17 00:00:00 2001 From: Lukas Eder Date: Fri, 6 Apr 2012 20:40:46 +0000 Subject: [PATCH] [#1273] Simulate GROUP_CONCAT() aggregate function using Oracle's LISTAGG() function, where available --- .../AggregateWindowFunctionTests.java | 2 +- .../java/org/jooq/GroupConcatOrderByStep.java | 7 ++++--- .../org/jooq/GroupConcatSeparatorStep.java | 3 ++- jOOQ/src/main/java/org/jooq/impl/Factory.java | 8 +++---- .../src/main/java/org/jooq/impl/Function.java | 21 ++++++++++++++----- jOOQ/src/main/java/org/jooq/impl/Term.java | 3 +++ 6 files changed, 30 insertions(+), 14 deletions(-) diff --git a/jOOQ-test/src/org/jooq/test/_/testcases/AggregateWindowFunctionTests.java b/jOOQ-test/src/org/jooq/test/_/testcases/AggregateWindowFunctionTests.java index d2d5f1face..4808b5ceaa 100644 --- a/jOOQ-test/src/org/jooq/test/_/testcases/AggregateWindowFunctionTests.java +++ b/jOOQ-test/src/org/jooq/test/_/testcases/AggregateWindowFunctionTests.java @@ -736,7 +736,6 @@ extends BaseTestORDER BY clause to the query */ - @Support({ CUBRID, DB2, H2, HSQLDB, MYSQL, ORACLE, SYBASE }) + @Support({ CUBRID, DB2, H2, HSQLDB, MYSQL, ORACLE, POSTGRES, SYBASE }) GroupConcatSeparatorStep orderBy(Field... fields); /** * Add an ORDER BY clause to the query */ - @Support({ CUBRID, DB2, H2, HSQLDB, MYSQL, ORACLE, SYBASE }) + @Support({ CUBRID, DB2, H2, HSQLDB, MYSQL, ORACLE, POSTGRES, SYBASE }) GroupConcatSeparatorStep orderBy(SortField... fields); /** * Add an ORDER BY clause to the query */ - @Support({ CUBRID, DB2, H2, HSQLDB, MYSQL, ORACLE, SYBASE }) + @Support({ CUBRID, DB2, H2, HSQLDB, MYSQL, ORACLE, POSTGRES, SYBASE }) GroupConcatSeparatorStep orderBy(Collection> fields); } diff --git a/jOOQ/src/main/java/org/jooq/GroupConcatSeparatorStep.java b/jOOQ/src/main/java/org/jooq/GroupConcatSeparatorStep.java index 619f1ab777..68de4f5059 100644 --- a/jOOQ/src/main/java/org/jooq/GroupConcatSeparatorStep.java +++ b/jOOQ/src/main/java/org/jooq/GroupConcatSeparatorStep.java @@ -41,6 +41,7 @@ import static org.jooq.SQLDialect.H2; 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.SYBASE; import org.jooq.impl.Factory; @@ -56,6 +57,6 @@ public interface GroupConcatSeparatorStep extends AggregateFunction { /** * Specify the separator on the GROUP_CONCAT function */ - @Support({ CUBRID, DB2, H2, HSQLDB, MYSQL, ORACLE, SYBASE }) + @Support({ CUBRID, DB2, H2, HSQLDB, MYSQL, ORACLE, POSTGRES, SYBASE }) AggregateFunction separator(String separator); } diff --git a/jOOQ/src/main/java/org/jooq/impl/Factory.java b/jOOQ/src/main/java/org/jooq/impl/Factory.java index f71fa49f01..f631b3e769 100644 --- a/jOOQ/src/main/java/org/jooq/impl/Factory.java +++ b/jOOQ/src/main/java/org/jooq/impl/Factory.java @@ -4263,7 +4263,7 @@ public class Factory implements FactoryOperations { * * @see #groupConcat(Field) */ - @Support({ CUBRID, DB2, H2, HSQLDB, MYSQL, ORACLE, SYBASE }) + @Support({ CUBRID, DB2, H2, HSQLDB, MYSQL, ORACLE, POSTGRES, SYBASE }) public static OrderedAggregateFunction listAgg(Field field) { return new Function(Term.LIST_AGG, SQLDataType.VARCHAR, nullSafe(field)); } @@ -4284,7 +4284,7 @@ public class Factory implements FactoryOperations { * * @see #groupConcat(Field, String) */ - @Support({ CUBRID, DB2, H2, HSQLDB, MYSQL, ORACLE, SYBASE }) + @Support({ CUBRID, DB2, H2, HSQLDB, MYSQL, ORACLE, POSTGRES, SYBASE }) public static OrderedAggregateFunction listAgg(Field field, String separator) { Field literal = literal("'" + separator.replace("'", "''") + "'"); return new Function(Term.LIST_AGG, SQLDataType.VARCHAR, nullSafe(field), literal); @@ -4310,7 +4310,7 @@ public class Factory implements FactoryOperations { * * @see #listAgg(Field) */ - @Support({ CUBRID, DB2, H2, HSQLDB, MYSQL, ORACLE, SYBASE }) + @Support({ CUBRID, DB2, H2, HSQLDB, MYSQL, ORACLE, POSTGRES, SYBASE }) public static GroupConcatOrderByStep groupConcat(Field field) { return new GroupConcat(nullSafe(field)); } @@ -4333,7 +4333,7 @@ public class Factory implements FactoryOperations { * * @see #listAgg(Field) */ - @Support({ CUBRID, H2, HSQLDB, MYSQL, SYBASE }) + @Support({ CUBRID, H2, HSQLDB, MYSQL, POSTGRES, SYBASE }) public static GroupConcatOrderByStep groupConcatDistinct(Field field) { return new GroupConcat(nullSafe(field), true); } diff --git a/jOOQ/src/main/java/org/jooq/impl/Function.java b/jOOQ/src/main/java/org/jooq/impl/Function.java index 781d81f926..ae880598ee 100644 --- a/jOOQ/src/main/java/org/jooq/impl/Function.java +++ b/jOOQ/src/main/java/org/jooq/impl/Function.java @@ -42,6 +42,7 @@ import static org.jooq.SQLDialect.DB2; import static org.jooq.SQLDialect.H2; import static org.jooq.SQLDialect.HSQLDB; import static org.jooq.SQLDialect.MYSQL; +import static org.jooq.SQLDialect.POSTGRES; import static org.jooq.SQLDialect.SYBASE; import static org.jooq.impl.Factory.one; import static org.jooq.impl.Term.LIST_AGG; @@ -172,8 +173,8 @@ class Function extends AbstractField implements if (term == LIST_AGG && asList(CUBRID, H2, HSQLDB, MYSQL).contains(context.getDialect())) { toSQLGroupConcat(context); } - else if (term == LIST_AGG && asList(SYBASE).contains(context.getDialect())) { - toSQLList(context); + else if (term == LIST_AGG && asList(POSTGRES, SYBASE).contains(context.getDialect())) { + toSQLStringAgg(context); } else if (term == LIST_AGG && asList(DB2).contains(context.getDialect())) { toSQLXMLAGG(context); @@ -233,9 +234,9 @@ class Function extends AbstractField implements } /** - * [#1275] LIST_AGG simulation for CUBRID, HSQLDB, MySQL + * [#1275] LIST_AGG simulation for Postgres, Sybase */ - private void toSQLList(RenderContext context) { + private void toSQLStringAgg(RenderContext context) { context.sql(getFNName(context.getDialect())); context.sql("("); @@ -243,7 +244,16 @@ class Function extends AbstractField implements context.keyword("distinct "); } - context.sql(arguments); + // The explicit cast is needed in Postgres + context.sql(((Field) arguments.get(0)).cast(String.class)); + + if (arguments.size() > 1) { + context.sql(", "); + context.sql(arguments.get(1)); + } + else { + context.sql(", ''"); + } if (!withinGroupOrderBy.isEmpty()) { context.keyword(" order by ") @@ -251,6 +261,7 @@ class Function extends AbstractField implements } context.sql(")"); + toSQLOverClause(context); } /** diff --git a/jOOQ/src/main/java/org/jooq/impl/Term.java b/jOOQ/src/main/java/org/jooq/impl/Term.java index 0ebc617f35..556c0933e6 100644 --- a/jOOQ/src/main/java/org/jooq/impl/Term.java +++ b/jOOQ/src/main/java/org/jooq/impl/Term.java @@ -118,6 +118,9 @@ enum Term { case ORACLE: return "listagg"; + case POSTGRES: + return "string_agg"; + case SYBASE: return "list"; }