diff --git a/jOOQ/src/main/java/org/jooq/impl/DSL.java b/jOOQ/src/main/java/org/jooq/impl/DSL.java
index fd1668c581..b0af91d641 100644
--- a/jOOQ/src/main/java/org/jooq/impl/DSL.java
+++ b/jOOQ/src/main/java/org/jooq/impl/DSL.java
@@ -23843,7 +23843,7 @@ public class DSL {
* {@link SelectForStep#forXML()}. jOOQ produces an XML encoding that is
* compatible with {@link DSLContext#fetchFromXML(String)}. Future jOOQ
* versions will make this format configurable according to
- * {@link XMLFormat.RecordFormat}.
+ * {@link XMLFormat.RecordFormau}.
*
{@link NestedCollectionEmulation#NATIVE}: A few dialects have native
* support for MULTISET.
* {@link NestedCollectionEmulation#DEFAULT}: By default, jOOQ chooses
diff --git a/jOOQ/src/main/java/org/jooq/impl/JSONArrayAgg.java b/jOOQ/src/main/java/org/jooq/impl/JSONArrayAgg.java
index e189afce18..20446e8608 100644
--- a/jOOQ/src/main/java/org/jooq/impl/JSONArrayAgg.java
+++ b/jOOQ/src/main/java/org/jooq/impl/JSONArrayAgg.java
@@ -39,15 +39,14 @@ package org.jooq.impl;
// ...
import static org.jooq.SQLDialect.MARIADB;
-// ...
import static org.jooq.SQLDialect.MYSQL;
// ...
-// ...
import static org.jooq.impl.DSL.function;
import static org.jooq.impl.DSL.groupConcat;
import static org.jooq.impl.DSL.inline;
import static org.jooq.impl.DSL.noCondition;
import static org.jooq.impl.JSONEntryImpl.jsonCastMapper;
+import static org.jooq.impl.JSONEntryImpl.jsonMerge;
import static org.jooq.impl.JSONOnNull.ABSENT_ON_NULL;
import static org.jooq.impl.JSONOnNull.NULL_ON_NULL;
import static org.jooq.impl.Names.N_GROUP_CONCAT;
@@ -55,8 +54,6 @@ import static org.jooq.impl.Names.N_JSONB_AGG;
import static org.jooq.impl.Names.N_JSON_AGG;
import static org.jooq.impl.Names.N_JSON_ARRAYAGG;
import static org.jooq.impl.Names.N_JSON_GROUP_ARRAY;
-import static org.jooq.impl.Names.N_JSON_MERGE;
-import static org.jooq.impl.Names.N_JSON_MERGE_PRESERVE;
import static org.jooq.impl.Names.N_JSON_QUOTE;
import static org.jooq.impl.SQLDataType.JSON;
import static org.jooq.impl.SQLDataType.VARCHAR;
@@ -88,7 +85,6 @@ extends AbstractAggregateFunction
implements JSONArrayAggOrderByStep {
static final Set EMULATE_WITH_GROUP_CONCAT = SQLDialect.supportedBy(MARIADB, MYSQL);
- static final Set SUPPORT_JSON_MERGE_PRESERVE = SQLDialect.supportedBy(MARIADB, MYSQL);
@@ -102,13 +98,13 @@ implements JSONArrayAggOrderByStep {
}
@Override
- public void accept(Context> ctx) {
+ public final void accept(Context> ctx) {
switch (ctx.family()) {
case MARIADB:
case MYSQL: {
// Workaround for https://jira.mariadb.org/browse/MDEV-21912,
// https://jira.mariadb.org/browse/MDEV-21914, and other issues
- ctx.visit(SUPPORT_JSON_MERGE_PRESERVE.contains(ctx.dialect()) ? N_JSON_MERGE_PRESERVE : N_JSON_MERGE).sql('(').visit(inline("[]")).sql(", ").visit(groupConcatEmulation(ctx)).sql(')');
+ ctx.visit(jsonMerge(ctx, "[]", groupConcatEmulation(ctx)));
break;
}
diff --git a/jOOQ/src/main/java/org/jooq/impl/JSONEntryImpl.java b/jOOQ/src/main/java/org/jooq/impl/JSONEntryImpl.java
index 9882e3fbc5..7c4ccbd83a 100644
--- a/jOOQ/src/main/java/org/jooq/impl/JSONEntryImpl.java
+++ b/jOOQ/src/main/java/org/jooq/impl/JSONEntryImpl.java
@@ -39,6 +39,10 @@ package org.jooq.impl;
import static java.lang.Boolean.TRUE;
// ...
+import static org.jooq.SQLDialect.MARIADB;
+// ...
+import static org.jooq.SQLDialect.MYSQL;
+// ...
import static org.jooq.impl.DSL.NULL;
import static org.jooq.impl.DSL.coalesce;
import static org.jooq.impl.DSL.condition;
@@ -53,11 +57,15 @@ import static org.jooq.impl.Keywords.K_JSON;
import static org.jooq.impl.Keywords.K_KEY;
import static org.jooq.impl.Keywords.K_VALUE;
import static org.jooq.impl.Names.N_JSON;
+import static org.jooq.impl.Names.N_JSON_MERGE;
+import static org.jooq.impl.Names.N_JSON_MERGE_PRESERVE;
import static org.jooq.impl.Names.N_JSON_QUERY;
import static org.jooq.impl.SQLDataType.VARCHAR;
+import static org.jooq.impl.Tools.combine;
import static org.jooq.impl.Tools.emulateMultiset;
import static org.jooq.impl.Tools.BooleanDataKey.DATA_MULTISET_CONTENT;
+import java.util.Set;
import java.util.UUID;
import java.util.function.Function;
@@ -69,6 +77,7 @@ import org.jooq.JSONEntryValueStep;
import org.jooq.Param;
// ...
import org.jooq.Record1;
+import org.jooq.SQLDialect;
import org.jooq.Scope;
import org.jooq.Select;
import org.jooq.conf.NestedCollectionEmulation;
@@ -80,8 +89,12 @@ import org.jooq.conf.NestedCollectionEmulation;
* @author Lukas Eder
*/
final class JSONEntryImpl extends AbstractQueryPart implements JSONEntry, JSONEntryValueStep {
- private final Field key;
- private final Field value;
+
+ static final Set REQUIRE_JSON_MERGE = SQLDialect.supportedBy(MARIADB, MYSQL);
+ static final Set SUPPORT_JSON_MERGE_PRESERVE = SQLDialect.supportedBy(MARIADB, MYSQL);
+
+ private final Field key;
+ private final Field value;
JSONEntryImpl(Field key) {
this(key, null);
@@ -248,4 +261,12 @@ final class JSONEntryImpl extends AbstractQueryPart implements JSONEntry,
+
+ static final Field> jsonMerge(Scope scope, String empty, Field>... fields) {
+ return function(
+ SUPPORT_JSON_MERGE_PRESERVE.contains(scope.dialect()) ? N_JSON_MERGE_PRESERVE : N_JSON_MERGE,
+ fields[0].getDataType(),
+ combine(inline(empty), fields)
+ );
+ }
}
diff --git a/jOOQ/src/main/java/org/jooq/impl/JSONObject.java b/jOOQ/src/main/java/org/jooq/impl/JSONObject.java
index 079f971141..de69e61ab1 100644
--- a/jOOQ/src/main/java/org/jooq/impl/JSONObject.java
+++ b/jOOQ/src/main/java/org/jooq/impl/JSONObject.java
@@ -182,23 +182,14 @@ implements
case MARIADB: {
JSONEntry> first;
- Name name = JSONArrayAgg.SUPPORT_JSON_MERGE_PRESERVE.contains(ctx.dialect()) ? N_JSON_MERGE_PRESERVE : N_JSON_MERGE;
// Workaround for https://jira.mariadb.org/browse/MDEV-13701
if (entries.size() > 1) {
- ctx.visit(name).sql('(').visit(inline("{}"))
- .formatIndentStart();
-
- for (JSONEntry> entry : entries)
- ctx.sql(',').formatSeparator().visit(jsonObject(entry));
-
- ctx.formatIndentEnd()
- .formatNewLine()
- .sql(')');
+ ctx.visit(jsonMerge(ctx, "{}", Tools.map(entries, e -> jsonObject(e), Field[]::new)));
}
else if (!entries.isEmpty() && isJSONArray((first = entries.iterator().next()).value())) {
ctx.visit(jsonObject(
- key(first.key()).value(DSL.field("{0}({1}, {2})", getDataType(), name, inline("[]"), first.value()))
+ key(first.key()).value(jsonMerge(ctx, "[]", first.value()))
));
}
else
diff --git a/jOOQ/src/main/java/org/jooq/impl/JSONObjectAgg.java b/jOOQ/src/main/java/org/jooq/impl/JSONObjectAgg.java
index 9616dd75f8..3f2824fc6e 100644
--- a/jOOQ/src/main/java/org/jooq/impl/JSONObjectAgg.java
+++ b/jOOQ/src/main/java/org/jooq/impl/JSONObjectAgg.java
@@ -41,7 +41,6 @@ import static org.jooq.SQLDialect.MARIADB;
import static org.jooq.impl.DSL.groupConcat;
import static org.jooq.impl.DSL.inline;
import static org.jooq.impl.DSL.jsonObject;
-import static org.jooq.impl.DSL.jsonValue;
import static org.jooq.impl.DSL.noCondition;
import static org.jooq.impl.DSL.when;
import static org.jooq.impl.JSONOnNull.ABSENT_ON_NULL;
@@ -60,11 +59,8 @@ import org.jooq.Field;
import org.jooq.JSON;
import org.jooq.JSONEntry;
import org.jooq.JSONObjectAggNullStep;
-import org.jooq.JSONObjectNullStep;
// ...
-import org.jetbrains.annotations.NotNull;
-
/**
* The JSON object constructor.
diff --git a/jOOQ/src/main/java/org/jooq/impl/Multiset.java b/jOOQ/src/main/java/org/jooq/impl/Multiset.java
index 9bb5ad691f..955412dbaf 100644
--- a/jOOQ/src/main/java/org/jooq/impl/Multiset.java
+++ b/jOOQ/src/main/java/org/jooq/impl/Multiset.java
@@ -42,6 +42,8 @@ import static java.lang.Boolean.TRUE;
// ...
// ...
import static org.jooq.SQLDialect.POSTGRES;
+import static org.jooq.impl.DSL.function;
+import static org.jooq.impl.DSL.inline;
import static org.jooq.impl.DSL.jsonArray;
import static org.jooq.impl.DSL.jsonArrayAgg;
import static org.jooq.impl.DSL.jsonEntry;
@@ -55,7 +57,13 @@ import static org.jooq.impl.DSL.xmlagg;
import static org.jooq.impl.DSL.xmlelement;
import static org.jooq.impl.DSL.xmlserializeContent;
import static org.jooq.impl.JSONArrayAgg.patchOracleArrayAggBug;
+import static org.jooq.impl.JSONEntryImpl.REQUIRE_JSON_MERGE;
+import static org.jooq.impl.JSONEntryImpl.SUPPORT_JSON_MERGE_PRESERVE;
+import static org.jooq.impl.JSONEntryImpl.isJSON;
+import static org.jooq.impl.JSONEntryImpl.jsonMerge;
import static org.jooq.impl.Keywords.K_MULTISET;
+import static org.jooq.impl.Names.N_JSON_MERGE;
+import static org.jooq.impl.Names.N_JSON_MERGE_PRESERVE;
import static org.jooq.impl.Names.N_MULTISET;
import static org.jooq.impl.Names.N_RECORD;
import static org.jooq.impl.Names.N_RESULT;
@@ -335,7 +343,7 @@ final class Multiset extends AbstractField> {
default:
return jsonArrayAgg(
returningClob(ctx, jsonArray(
- map(fields.fields(), (f, i) -> agg ? f : DSL.field(fieldName(i), f.getDataType()))
+ map(fields.fields(), (f, i) -> jsonMerge(ctx, "[]", agg ? f : DSL.field(fieldName(i), f.getDataType())))
).nullOnNull())
);
}
@@ -359,12 +367,24 @@ final class Multiset extends AbstractField> {
default:
return jsonbArrayAgg(
returningClob(ctx, jsonbArray(
- map(fields.fields(), (f, i) -> agg ? f : DSL.field(fieldName(i), f.getDataType()))
+ map(fields.fields(), (f, i) -> jsonMerge(ctx, "[]", agg ? f : DSL.field(fieldName(i), f.getDataType())))
).nullOnNull())
);
}
}
+ private static final Field> jsonMerge(Scope scope, String empty, Field> field) {
+
+ // [#12168] Yet another MariaDB JSON un-escaping workaround https://jira.mariadb.org/browse/MDEV-26134
+ return REQUIRE_JSON_MERGE.contains(scope.dialect()) && isJSON(scope, field.getDataType())
+ ? function(
+ SUPPORT_JSON_MERGE_PRESERVE.contains(scope.dialect()) ? N_JSON_MERGE_PRESERVE : N_JSON_MERGE,
+ field.getDataType(),
+ inline(empty),
+ field
+ )
+ : field;
+ }
static final XMLAggOrderByStep xmlaggEmulation(Fields fields, boolean multisetCondition, boolean agg) {
return xmlagg(
xmlelement(N_RECORD,