From 6cf495cefaeaaee2c939eab2a37009b004efacd5 Mon Sep 17 00:00:00 2001 From: Lukas Eder Date: Thu, 1 Jul 2021 12:56:31 +0200 Subject: [PATCH] [jOOQ/jOOQ#3884] MULTISET via SQL/JSON emulation must use RETURNING CLOB --- .../src/main/java/org/jooq/impl/Multiset.java | 79 ++++++++++++++++--- .../main/java/org/jooq/impl/MultisetAgg.java | 14 ++-- 2 files changed, 74 insertions(+), 19 deletions(-) diff --git a/jOOQ/src/main/java/org/jooq/impl/Multiset.java b/jOOQ/src/main/java/org/jooq/impl/Multiset.java index 02f8275418..ee4aa44fa6 100644 --- a/jOOQ/src/main/java/org/jooq/impl/Multiset.java +++ b/jOOQ/src/main/java/org/jooq/impl/Multiset.java @@ -59,6 +59,7 @@ import static org.jooq.impl.Keywords.K_MULTISET; import static org.jooq.impl.Names.N_MULTISET; import static org.jooq.impl.Names.N_RECORD; import static org.jooq.impl.Names.N_RESULT; +import static org.jooq.impl.SQLDataType.CLOB; import static org.jooq.impl.SQLDataType.VARCHAR; import static org.jooq.impl.Tools.emulateMultiset; import static org.jooq.impl.Tools.fieldName; @@ -74,11 +75,15 @@ import org.jooq.Field; import org.jooq.Fields; import org.jooq.JSON; import org.jooq.JSONArrayAggOrderByStep; +import org.jooq.JSONArrayAggReturningStep; +import org.jooq.JSONArrayReturningStep; import org.jooq.JSONB; +import org.jooq.JSONObjectReturningStep; import org.jooq.Record; import org.jooq.Record1; import org.jooq.Result; import org.jooq.SQLDialect; +import org.jooq.Scope; import org.jooq.Select; import org.jooq.Table; import org.jooq.XML; @@ -140,17 +145,20 @@ final class Multiset extends AbstractField> { default: { JSONArrayAggOrderByStep order; - AggregateFilterStep filter; + JSONArrayAggReturningStep returning; - filter = order = jsonArrayaggEmulation(t, multisetCondition); + returning = order = jsonArrayaggEmulation(ctx, t, multisetCondition); // TODO: Re-apply derived table's ORDER BY clause as aggregate ORDER BY if (multisetCondition) - filter = order.orderBy(t.fields()); + returning = order.orderBy(t.fields()); Select> s = patchOracleArrayAggBug( ctx.configuration(), - select(DSL.coalesce(filter, jsonArray())).from(t) + select(DSL.coalesce( + returningClob(ctx, returning), + returningClob(ctx, jsonArray()) + )).from(t) ); if (multisetCondition && NO_SUPPORT_JSON_COMPARE.contains(ctx.dialect())) @@ -180,17 +188,20 @@ final class Multiset extends AbstractField> { default: { JSONArrayAggOrderByStep order; - AggregateFilterStep filter; + JSONArrayAggReturningStep returning; - filter = order = jsonbArrayaggEmulation(t, multisetCondition); + returning = order = jsonbArrayaggEmulation(ctx, t, multisetCondition); // TODO: Re-apply derived table's ORDER BY clause as aggregate ORDER BY if (multisetCondition) - filter = order.orderBy(t.fields()); + returning = order.orderBy(t.fields()); Select> s = patchOracleArrayAggBug( ctx.configuration(), - select(DSL.coalesce(filter, jsonbArray())).from(t) + select(DSL.coalesce( + returningClob(ctx, returning), + returningClob(ctx, jsonbArray()) + )).from(t) ); visitSubquery(ctx, s, true); @@ -249,12 +260,56 @@ final class Multiset extends AbstractField> { } } - static final JSONArrayAggOrderByStep jsonArrayaggEmulation(Fields fields, boolean multisetCondition) { - return jsonArrayAgg(jsonObject(map(fields.fields(), (f, i) -> jsonEntry(multisetCondition ? Tools.fieldNameString(i) : f.getName(), f)))); + static final Field returningClob(Scope ctx, JSONObjectReturningStep jsonObject) { + switch (ctx.family()) { + + + + + + default: + return jsonObject; + } } - static final JSONArrayAggOrderByStep jsonbArrayaggEmulation(Fields fields, boolean multisetCondition) { - return jsonbArrayAgg(jsonbObject(map(fields.fields(), (f, i) -> jsonEntry(multisetCondition ? Tools.fieldNameString(i) : f.getName(), f)))); + static final Field returningClob(Scope ctx, JSONArrayReturningStep jsonArray) { + switch (ctx.family()) { + + + + + + default: + return jsonArray; + } + } + + static final Field returningClob(Scope ctx, JSONArrayAggReturningStep jsonArrayagg) { + switch (ctx.family()) { + + + + + + default: + return jsonArrayagg; + } + } + + static final JSONArrayAggOrderByStep jsonArrayaggEmulation(Scope ctx, Fields fields, boolean multisetCondition) { + return jsonArrayAgg( + returningClob(ctx, jsonObject( + map(fields.fields(), (f, i) -> jsonEntry(multisetCondition ? Tools.fieldNameString(i) : f.getName(), f)) + )) + ); + } + + static final JSONArrayAggOrderByStep jsonbArrayaggEmulation(Scope ctx, Fields fields, boolean multisetCondition) { + return jsonbArrayAgg( + returningClob(ctx, jsonbObject( + map(fields.fields(), (f, i) -> jsonEntry(multisetCondition ? Tools.fieldNameString(i) : f.getName(), f)) + )) + ); } static final XMLAggOrderByStep xmlaggEmulation(Fields fields, boolean multisetCondition) { diff --git a/jOOQ/src/main/java/org/jooq/impl/MultisetAgg.java b/jOOQ/src/main/java/org/jooq/impl/MultisetAgg.java index be549cf5ca..3c068c141b 100644 --- a/jOOQ/src/main/java/org/jooq/impl/MultisetAgg.java +++ b/jOOQ/src/main/java/org/jooq/impl/MultisetAgg.java @@ -49,6 +49,7 @@ import static org.jooq.impl.Multiset.NO_SUPPORT_JSON_COMPARE; import static org.jooq.impl.Multiset.NO_SUPPORT_XML_COMPARE; import static org.jooq.impl.Multiset.jsonArrayaggEmulation; import static org.jooq.impl.Multiset.jsonbArrayaggEmulation; +import static org.jooq.impl.Multiset.returningClob; import static org.jooq.impl.Multiset.xmlaggEmulation; import static org.jooq.impl.Names.N_MULTISET_AGG; import static org.jooq.impl.Names.N_RECORD; @@ -112,12 +113,11 @@ final class MultisetAgg extends DefaultAggregateFunction ctx, boolean multisetCondition) { switch (emulateMultiset(ctx.configuration())) { case JSON: { - JSONArrayAggOrderByStep order = jsonArrayaggEmulation(row, multisetCondition); + JSONArrayAggOrderByStep order = jsonArrayaggEmulation(ctx, row, multisetCondition); Field f = multisetCondition - ? fo((AbstractAggregateFunction) order.orderBy(row.fields())) - : ofo((AbstractAggregateFunction) order); - + ? fo((AbstractAggregateFunction) returningClob(ctx, order.orderBy(row.fields()))) + : ofo((AbstractAggregateFunction) returningClob(ctx, order)); if (multisetCondition && NO_SUPPORT_JSON_COMPARE.contains(ctx.dialect())) ctx.visit(f.cast(VARCHAR)); @@ -128,11 +128,11 @@ final class MultisetAgg extends DefaultAggregateFunction order = jsonbArrayaggEmulation(row, multisetCondition); + JSONArrayAggOrderByStep order = jsonbArrayaggEmulation(ctx, row, multisetCondition); Field f = multisetCondition - ? fo((AbstractAggregateFunction) order.orderBy(row.fields())) - : ofo((AbstractAggregateFunction) order); + ? fo((AbstractAggregateFunction) returningClob(ctx, order.orderBy(row.fields()))) + : ofo((AbstractAggregateFunction) returningClob(ctx, order)); ctx.visit(f); break;