[jOOQ/jOOQ#15732] Fix MULTISET equality semantics
This commit is contained in:
parent
6bd3d9e110
commit
3b6045ff43
@ -178,6 +178,7 @@ final class ArrayDataType<T> extends DefaultDataType<T[]> {
|
||||
switch (configuration.family()) {
|
||||
|
||||
|
||||
case DUCKDB:
|
||||
case POSTGRES:
|
||||
case YUGABYTEDB:
|
||||
return dataType + "[]";
|
||||
|
||||
@ -296,6 +296,7 @@ import org.jooq.tools.jdbc.JDBCUtils;
|
||||
import org.jooq.tools.jdbc.MockArray;
|
||||
import org.jooq.tools.jdbc.MockResultSet;
|
||||
import org.jooq.tools.json.JSONArray;
|
||||
import org.jooq.tools.json.JSONValue;
|
||||
import org.jooq.types.DayToSecond;
|
||||
import org.jooq.types.UByte;
|
||||
import org.jooq.types.UInteger;
|
||||
@ -1420,7 +1421,7 @@ public class DefaultBinding<T, U> implements Binding<T, U> {
|
||||
|
||||
// [#15732] Use JSON as a workaround to bind array types for now.
|
||||
case DUCKDB: {
|
||||
ctx.statement().setString(ctx.index(), new JSONArray(asList(value)).toString());
|
||||
ctx.statement().setString(ctx.index(), JSONValue.toJSONString(value));
|
||||
break;
|
||||
}
|
||||
|
||||
|
||||
@ -45,6 +45,7 @@ import static org.jooq.SQLDialect.MYSQL;
|
||||
import static org.jooq.SQLDialect.*;
|
||||
import static org.jooq.SQLDialect.POSTGRES;
|
||||
import static org.jooq.SQLDialect.YUGABYTEDB;
|
||||
import static org.jooq.impl.DSL.arrayAgg;
|
||||
import static org.jooq.impl.DSL.field;
|
||||
import static org.jooq.impl.DSL.function;
|
||||
import static org.jooq.impl.DSL.inline;
|
||||
@ -97,6 +98,7 @@ import java.util.Set;
|
||||
import java.util.function.Function;
|
||||
|
||||
import org.jooq.AggregateFilterStep;
|
||||
import org.jooq.ArrayAggOrderByStep;
|
||||
import org.jooq.Context;
|
||||
import org.jooq.DataType;
|
||||
import org.jooq.Field;
|
||||
@ -119,6 +121,8 @@ import org.jooq.Result;
|
||||
import org.jooq.SQLDialect;
|
||||
import org.jooq.Scope;
|
||||
import org.jooq.Select;
|
||||
import org.jooq.SelectJoinStep;
|
||||
import org.jooq.SelectOrderByStep;
|
||||
import org.jooq.Spatial;
|
||||
import org.jooq.Table;
|
||||
import org.jooq.TableLike;
|
||||
@ -126,6 +130,8 @@ import org.jooq.TableLike;
|
||||
import org.jooq.XML;
|
||||
import org.jooq.XMLAggOrderByStep;
|
||||
|
||||
import org.jetbrains.annotations.NotNull;
|
||||
|
||||
/**
|
||||
* @author Lukas Eder
|
||||
*/
|
||||
@ -394,9 +400,14 @@ final class Multiset<R extends Record> extends AbstractField<Result<R>> implemen
|
||||
|
||||
case NATIVE:
|
||||
switch (ctx.family()) {
|
||||
case DUCKDB:
|
||||
visitSubquery(ctx.visit(K_ARRAY), select(DSL.field(N_T)).from(select.asTable(N_T)));
|
||||
case DUCKDB: {
|
||||
SelectOrderByStep<?> s = select(DSL.field(N_T)).from(select.asTable(N_T));
|
||||
visitSubquery(ctx.visit(K_ARRAY), multisetCondition
|
||||
? s.orderBy(DSL.field(N_T))
|
||||
: s
|
||||
);
|
||||
break;
|
||||
}
|
||||
|
||||
default:
|
||||
visitSubquery(ctx.visit(K_MULTISET), select);
|
||||
@ -603,6 +614,14 @@ final class Multiset<R extends Record> extends AbstractField<Result<R>> implemen
|
||||
);
|
||||
}
|
||||
|
||||
static final ArrayAggOrderByStep<?> arrayAggEmulation(Fields fields, boolean agg) {
|
||||
return arrayAgg(
|
||||
new RowAsField<>(row(
|
||||
map(fields.fields(), (f, i) -> agg ? f : DSL.field(fieldName(i), f.getDataType()))
|
||||
))
|
||||
);
|
||||
}
|
||||
|
||||
// -------------------------------------------------------------------------
|
||||
// XXX: Query Object Model
|
||||
// -------------------------------------------------------------------------
|
||||
|
||||
@ -39,31 +39,26 @@ package org.jooq.impl;
|
||||
|
||||
import static java.lang.Boolean.TRUE;
|
||||
// ...
|
||||
import static org.jooq.impl.DSL.row;
|
||||
import static org.jooq.impl.DSL.xmlelement;
|
||||
import static org.jooq.impl.DSL.xmlserializeContent;
|
||||
import static org.jooq.impl.Multiset.NO_SUPPORT_JSONB_COMPARE;
|
||||
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.arrayAggEmulation;
|
||||
import static org.jooq.impl.Multiset.jsonArrayaggEmulation;
|
||||
import static org.jooq.impl.Multiset.jsonbArrayaggEmulation;
|
||||
import static org.jooq.impl.Multiset.nResult;
|
||||
import static org.jooq.impl.Multiset.returningClob;
|
||||
import static org.jooq.impl.Multiset.xmlaggEmulation;
|
||||
import static org.jooq.impl.Names.N_ARRAY_AGG;
|
||||
import static org.jooq.impl.Names.N_MULTISET_AGG;
|
||||
import static org.jooq.impl.Names.N_RESULT;
|
||||
import static org.jooq.impl.SQLDataType.VARCHAR;
|
||||
import static org.jooq.impl.Tools.emulateMultiset;
|
||||
import static org.jooq.impl.Tools.BooleanDataKey.DATA_MULTISET_CONDITION;
|
||||
import static org.jooq.impl.Tools.BooleanDataKey.DATA_MULTISET_CONTENT;
|
||||
|
||||
import java.util.function.BiFunction;
|
||||
import java.util.function.Predicate;
|
||||
|
||||
import org.jooq.ArrayAggOrderByStep;
|
||||
import org.jooq.Context;
|
||||
import org.jooq.Field;
|
||||
import org.jooq.Function1;
|
||||
import org.jooq.JSON;
|
||||
import org.jooq.JSONArrayAggOrderByStep;
|
||||
import org.jooq.JSONB;
|
||||
@ -164,23 +159,16 @@ final class MultisetAgg<R extends Record> extends AbstractAggregateFunction<Resu
|
||||
break;
|
||||
}
|
||||
|
||||
case NATIVE:
|
||||
switch (ctx.family()) {
|
||||
case DUCKDB:
|
||||
ctx.visit(N_ARRAY_AGG);
|
||||
break;
|
||||
default:
|
||||
ctx.visit(N_MULTISET_AGG);
|
||||
break;
|
||||
}
|
||||
case NATIVE: {
|
||||
ArrayAggOrderByStep<?> order = arrayAggEmulation(row, true);
|
||||
|
||||
ctx.visit(multisetCondition
|
||||
? fo(order.orderBy(row.fields()))
|
||||
: ofo((AbstractAggregateFunction<?>) order)
|
||||
);
|
||||
|
||||
ctx.sql('(');
|
||||
acceptArguments1(ctx, new QueryPartListView<>(new RowAsField<>(DSL.row(arguments))));
|
||||
acceptOrderBy(ctx);
|
||||
ctx.sql(')');
|
||||
acceptFilterClause(ctx);
|
||||
acceptOverClause(ctx);
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@ -22,7 +22,9 @@ package org.jooq.tools.json;
|
||||
|
||||
import java.io.IOException;
|
||||
import java.io.Reader;
|
||||
import java.io.StringWriter;
|
||||
import java.io.Writer;
|
||||
import java.util.Arrays;
|
||||
import java.util.List;
|
||||
import java.util.Map;
|
||||
|
||||
@ -43,26 +45,28 @@ public class JSONValue {
|
||||
return;
|
||||
}
|
||||
|
||||
if (value instanceof String) {
|
||||
if (value instanceof String s) {
|
||||
out.write('\"');
|
||||
out.write(escape((String) value));
|
||||
out.write(escape(s));
|
||||
out.write('\"');
|
||||
return;
|
||||
}
|
||||
|
||||
if (value instanceof Double) {
|
||||
if (((Double) value).isInfinite() || ((Double) value).isNaN())
|
||||
if (value instanceof Double d) {
|
||||
if (d.isInfinite() || d.isNaN())
|
||||
out.write("null");
|
||||
else
|
||||
out.write(value.toString());
|
||||
|
||||
return;
|
||||
}
|
||||
|
||||
if (value instanceof Float) {
|
||||
if (((Float) value).isInfinite() || ((Float) value).isNaN())
|
||||
if (value instanceof Float f) {
|
||||
if (f.isInfinite() || f.isNaN())
|
||||
out.write("null");
|
||||
else
|
||||
out.write(value.toString());
|
||||
|
||||
return;
|
||||
}
|
||||
|
||||
@ -76,13 +80,18 @@ public class JSONValue {
|
||||
return;
|
||||
}
|
||||
|
||||
if (value instanceof Map) {
|
||||
JSONObject.writeJSONString((Map<?, ?>) value, out);
|
||||
if (value instanceof Map<?, ?> m) {
|
||||
JSONObject.writeJSONString(m, out);
|
||||
return;
|
||||
}
|
||||
|
||||
if (value instanceof List) {
|
||||
JSONArray.writeJSONString((List<?>) value, out);
|
||||
if (value instanceof List<?> l) {
|
||||
JSONArray.writeJSONString(l, out);
|
||||
return;
|
||||
}
|
||||
|
||||
if (value instanceof Object[] a) {
|
||||
JSONArray.writeJSONString(Arrays.asList(a), out);
|
||||
return;
|
||||
}
|
||||
|
||||
@ -102,41 +111,14 @@ public class JSONValue {
|
||||
* number.
|
||||
*/
|
||||
public static String toJSONString(Object value) {
|
||||
if (value == null)
|
||||
return "null";
|
||||
Writer w = new StringWriter();
|
||||
|
||||
if (value instanceof String)
|
||||
return "\"" + escape((String) value) + "\"";
|
||||
|
||||
if (value instanceof Double) {
|
||||
if (((Double) value).isInfinite() || ((Double) value).isNaN())
|
||||
return "null";
|
||||
else
|
||||
return value.toString();
|
||||
try {
|
||||
writeJSONString(value, w);
|
||||
}
|
||||
catch (IOException ignore) {}
|
||||
|
||||
if (value instanceof Float) {
|
||||
if (((Float) value).isInfinite() || ((Float) value).isNaN())
|
||||
return "null";
|
||||
else
|
||||
return value.toString();
|
||||
}
|
||||
|
||||
if (value instanceof Number)
|
||||
return value.toString();
|
||||
|
||||
if (value instanceof Boolean)
|
||||
return value.toString();
|
||||
|
||||
if (value instanceof Map)
|
||||
return JSONObject.toJSONString((Map<?, ?>) value);
|
||||
|
||||
if (value instanceof List)
|
||||
return JSONArray.toJSONString((List<?>) value);
|
||||
|
||||
// Patched original according to issue 27 of JSON-simple
|
||||
// http://code.google.com/p/json-simple/issues/detail?id=27
|
||||
return "\"" + escape(value.toString()) + "\"";
|
||||
return w.toString();
|
||||
}
|
||||
|
||||
/**
|
||||
|
||||
Loading…
Reference in New Issue
Block a user