withinGroupOrderBy(SortField>... fields);
/**
diff --git a/jOOQ/src/main/java/org/jooq/impl/Factory.java b/jOOQ/src/main/java/org/jooq/impl/Factory.java
index 53bd5d404c..bec9a52018 100644
--- a/jOOQ/src/main/java/org/jooq/impl/Factory.java
+++ b/jOOQ/src/main/java/org/jooq/impl/Factory.java
@@ -4248,18 +4248,35 @@ public class Factory implements FactoryOperations {
/**
* Get the aggregated concatenation for a field.
+ *
+ * This is natively supported by {@link SQLDialect#ORACLE}. It is simulated
+ * by the following dialects:
+ *
+ * - {@link SQLDialect#CUBRID}: Using
GROUP_CONCAT()
+ * - {@link SQLDialect#MYSQL}: Using
GROUP_CONCAT()
+ * - {@link SQLDialect#SYBASE}: Using
LIST()
+ *
*/
- @Support(ORACLE)
+ @Support({ CUBRID, MYSQL, ORACLE, SYBASE })
public static OrderedAggregateFunction listAgg(Field> field) {
return new Function(Term.LIST_AGG, SQLDataType.VARCHAR, nullSafe(field));
}
/**
* Get the aggregated concatenation for a field.
+ *
+ * This is natively supported by {@link SQLDialect#ORACLE}. It is simulated
+ * by the following dialects:
+ *
+ * - {@link SQLDialect#CUBRID}: Using
GROUP_CONCAT
+ * - {@link SQLDialect#MYSQL}: Using
GROUP_CONCAT
+ * - {@link SQLDialect#SYBASE}: Using
LIST()
+ *
*/
- @Support(ORACLE)
+ @Support({ CUBRID, MYSQL, ORACLE, SYBASE })
public static OrderedAggregateFunction listAgg(Field> field, String delimiter) {
- return new Function(Term.LIST_AGG, SQLDataType.VARCHAR, nullSafe(field), literal("'" + delimiter.replace("'", "''") + "'"));
+ Field literal = literal("'" + delimiter.replace("'", "''") + "'");
+ return new Function(Term.LIST_AGG, SQLDataType.VARCHAR, nullSafe(field), literal);
}
// -------------------------------------------------------------------------
diff --git a/jOOQ/src/main/java/org/jooq/impl/Function.java b/jOOQ/src/main/java/org/jooq/impl/Function.java
index a0234043a0..839228173b 100644
--- a/jOOQ/src/main/java/org/jooq/impl/Function.java
+++ b/jOOQ/src/main/java/org/jooq/impl/Function.java
@@ -36,7 +36,12 @@
package org.jooq.impl;
+import static java.util.Arrays.asList;
+import static org.jooq.SQLDialect.CUBRID;
+import static org.jooq.SQLDialect.MYSQL;
+import static org.jooq.SQLDialect.SYBASE;
import static org.jooq.impl.Factory.one;
+import static org.jooq.impl.Term.LIST_AGG;
import java.util.Arrays;
import java.util.Collection;
@@ -138,14 +143,87 @@ class Function extends AbstractField implements
}
@Override
- public final void toSQL(RenderContext context) {
- context.sql(getFNName(context.getDialect()));
- toSQLArguments(context);
- toSQLWithinGroupClause(context);
- toSQLOverClause(context);
+ public final void bind(BindContext context) {
+
+ if (term == LIST_AGG && asList(MYSQL, CUBRID).contains(context.getDialect())) {
+ context.bind(arguments.get(0));
+ context.bind((QueryPart) withinGroupOrderBy);
+
+ if (arguments.size() > 1) {
+ context.bind(arguments.get(1));
+ }
+ }
+ else {
+ context.bind((QueryPart) arguments)
+ .bind((QueryPart) withinGroupOrderBy)
+ .bind((QueryPart) partitionBy)
+ .bind((QueryPart) orderBy);
+ }
}
- private void toSQLOverClause(RenderContext context) {
+ @Override
+ public final void toSQL(RenderContext context) {
+ context.sql(getFNName(context.getDialect()));
+
+ if (term == LIST_AGG && asList(MYSQL, CUBRID).contains(context.getDialect())) {
+ toSQLGroupConcat(context);
+ }
+ if (term == LIST_AGG && asList(SYBASE).contains(context.getDialect())) {
+ toSQLList(context);
+ }
+ else {
+ toSQLArguments(context);
+ toSQLWithinGroupClause(context);
+ toSQLOverClause(context);
+ }
+ }
+
+ /**
+ * [#1275] LIST_AGG simulation for MySQL and CUBRID
+ */
+ private void toSQLList(RenderContext context) {
+ context.sql("(");
+
+ if (distinct) {
+ context.keyword("distinct ");
+ }
+
+ context.sql(arguments);
+
+ if (!withinGroupOrderBy.isEmpty()) {
+ context.keyword(" order by ")
+ .sql(withinGroupOrderBy);
+ }
+
+ context.sql(")");
+ }
+
+ /**
+ * [#1273] LIST_AGG simulation for MySQL and CUBRID
+ */
+ private final void toSQLGroupConcat(RenderContext context) {
+ context.sql("(");
+
+ if (distinct) {
+ context.keyword("distinct ");
+ }
+
+ context.sql(arguments.get(0));
+
+ if (!withinGroupOrderBy.isEmpty()) {
+ context.keyword(" order by ")
+ .sql(withinGroupOrderBy);
+ }
+
+ if (arguments.size() > 1) {
+ context.keyword(" separator ")
+ .sql(arguments.get(1));
+ }
+
+ context.sql(")");
+ }
+
+ private final void toSQLOverClause(RenderContext context) {
if (!over) return;
String glue = "";
@@ -214,7 +292,7 @@ class Function extends AbstractField implements
/**
* Render WITHIN GROUP (ORDER BY ..) clause
*/
- private void toSQLWithinGroupClause(RenderContext context) {
+ private final void toSQLWithinGroupClause(RenderContext context) {
if (!withinGroupOrderBy.isEmpty()) {
context.keyword(" within group (order by ")
.sql(withinGroupOrderBy)
@@ -225,7 +303,7 @@ class Function extends AbstractField implements
/**
* Render function arguments and argument modifiers
*/
- private void toSQLArguments(RenderContext context) {
+ private final void toSQLArguments(RenderContext context) {
context.sql("(");
if (distinct) {
@@ -285,14 +363,6 @@ class Function extends AbstractField implements
}
}
- @Override
- public final void bind(BindContext context) {
- context.bind((QueryPart) arguments)
- .bind((QueryPart) withinGroupOrderBy)
- .bind((QueryPart) partitionBy)
- .bind((QueryPart) orderBy);
- }
-
@Override
public final boolean isNullLiteral() {
return false;
diff --git a/jOOQ/src/main/java/org/jooq/impl/Term.java b/jOOQ/src/main/java/org/jooq/impl/Term.java
index 62cb0eb0b9..1cc70c9322 100644
--- a/jOOQ/src/main/java/org/jooq/impl/Term.java
+++ b/jOOQ/src/main/java/org/jooq/impl/Term.java
@@ -103,6 +103,18 @@ enum Term {
LIST_AGG {
@Override
public String translate(SQLDialect dialect) {
+ switch (dialect) {
+ case CUBRID:
+ case MYSQL:
+ return "group_concat";
+
+ case ORACLE:
+ return "listagg";
+
+ case SYBASE:
+ return "list";
+ }
+
return "listagg";
}
},