[jOOQ/jOOQ#11238] Fixed MariaDB and MySQL emulations

This commit is contained in:
Lukas Eder 2021-02-19 16:45:38 +01:00
parent 89d7c45e1d
commit df90a78f71
3 changed files with 43 additions and 35 deletions

View File

@ -84,21 +84,21 @@ implements
/**
* Generated UID
*/
private static final long serialVersionUID = -8613744948308064895L;
private static final Set<SQLDialect> SUPPORT_FILTER = SQLDialect.supportedBy(H2, HSQLDB, POSTGRES, SQLITE);
private static final Set<SQLDialect> SUPPORT_DISTINCT_RVE = SQLDialect.supportedBy(H2, POSTGRES);
private static final long serialVersionUID = -8613744948308064895L;
static final Set<SQLDialect> SUPPORT_FILTER = SQLDialect.supportedBy(H2, HSQLDB, POSTGRES, SQLITE);
static final Set<SQLDialect> SUPPORT_DISTINCT_RVE = SQLDialect.supportedBy(H2, POSTGRES);
static final Field<Integer> ASTERISK = DSL.field("*", Integer.class);
static final Field<Integer> ASTERISK = DSL.field("*", Integer.class);
// Other attributes
final QueryPartList<Field<?>> arguments;
final boolean distinct;
Condition filter;
final QueryPartList<Field<?>> arguments;
final boolean distinct;
Condition filter;
// Other attributes
SortFieldList withinGroupOrderBy;
SortFieldList keepDenseRankOrderBy;
boolean first;
SortFieldList withinGroupOrderBy;
SortFieldList keepDenseRankOrderBy;
boolean first;
AbstractAggregateFunction(boolean distinct, Name name, DataType<T> type, Field<?>... arguments) {
super(name, type);
@ -124,25 +124,21 @@ implements
ctx.sql('(');
}
if (!args.isEmpty()) {
if (filter == null || SUPPORT_FILTER.contains(ctx.dialect())) {
ctx.visit(args);
}
else {
QueryPartList<Field<?>> expressions = new QueryPartList<>();
for (Field<?> argument : args)
expressions.add(DSL.when(filter, argument == ASTERISK ? one() : argument));
ctx.visit(expressions);
}
}
if (!args.isEmpty())
acceptArguments2(ctx, args);
if (distinct)
if (args.size() > 1 && SUPPORT_DISTINCT_RVE.contains(ctx.dialect()))
ctx.sql(')');
}
final void acceptArguments2(Context<?> ctx, QueryPartCollectionView<Field<?>> args) {
if (filter == null || SUPPORT_FILTER.contains(ctx.dialect()))
ctx.visit(args);
else
ctx.visit(args.map(arg -> DSL.when(filter, arg == ASTERISK ? one() : arg)));
}
final void acceptFilterClause(Context<?> ctx) {
acceptFilterClause(ctx, filter);
}

View File

@ -47,6 +47,7 @@ import static org.jooq.impl.DSL.noCondition;
import static org.jooq.impl.JSONEntryImpl.jsonCast;
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;
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;
@ -156,10 +157,14 @@ implements JSONArrayAggOrderByStep<J> {
Field<?> arg2 = arg1;
return DSL.concat(
inline('['),
DSL.field("{0}", VARCHAR, CustomQueryPart.of(c -> {
c.visit(groupConcatEmulationWithoutArrayWrappers(arg2, withinGroupOrderBy));
acceptOverClause(c);
})),
CustomField.of(N_GROUP_CONCAT, VARCHAR, c1 -> {
c1.visit(groupConcatEmulationWithoutArrayWrappers(
CustomField.of(Names.N_FIELD, VARCHAR, c2 -> acceptArguments2(c2, QueryPartListView.wrap(arg2))),
withinGroupOrderBy
));
acceptFilterClause(ctx);
acceptOverClause(c1);
}),
inline(']')
);
}

View File

@ -46,6 +46,7 @@ import static org.jooq.impl.DSL.noCondition;
import static org.jooq.impl.DSL.when;
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_FIELD;
import static org.jooq.impl.Names.N_JSONB_OBJECT_AGG;
import static org.jooq.impl.Names.N_JSON_OBJECTAGG;
import static org.jooq.impl.Names.N_JSON_OBJECT_AGG;
@ -106,7 +107,9 @@ implements JSONObjectAggNullStep<J> {
// [#10089] These dialects support non-standard JSON_OBJECTAGG without ABSENT ON NULL support
case MARIADB:
case MYSQL:
if (onNull == ABSENT_ON_NULL)
// [#11238] FILTER cannot be emulated with the standard syntax
if (onNull == ABSENT_ON_NULL || filter != null)
acceptGroupConcat(ctx);
@ -137,17 +140,21 @@ implements JSONObjectAggNullStep<J> {
}
private final void acceptGroupConcat(Context<?> ctx) {
final Field<String> listagg = DSL.field("{0}", String.class, CustomQueryPart.of(c -> {
Field<JSON> o = jsonObject(entry.key(), entry.value());
final Field<String> listagg = CustomField.of(Names.N_GROUP_CONCAT, VARCHAR, c1 -> {
Field<JSON> o1 = jsonObject(entry.key(), entry.value());
if (onNull == ABSENT_ON_NULL)
o = when(entry.value().isNull(), inline((JSON) null)).else_(o);
o1 = when(entry.value().isNull(), inline((JSON) null)).else_(o1);
c.visit(groupConcat(DSL.concat(
DSL.regexpReplaceAll(o.cast(VARCHAR), inline("^\\{(.*)\\}$"), inline(RegexpReplace.replacement(ctx, 1)))
Field<JSON> o2 = o1;
c1.visit(groupConcat(DSL.concat(
CustomField.of(N_FIELD, VARCHAR, c2 -> acceptArguments2(c2, QueryPartListView.wrap(
DSL.regexpReplaceAll(o2.cast(VARCHAR), inline("^\\{(.*)\\}$"), inline(RegexpReplace.replacement(ctx, 1)))
)))
)));
acceptOverClause(c);
}));
acceptOverClause(c1);
});
ctx.sql('(').visit(DSL.concat(inline('{'), listagg, inline('}'))).sql(')');
}