语境
我正在针对PostgreSQL数据库使用jOOQ。 我想在 a 的结果集上使用。
jsonb_object_agg(name, value)LEFT OUTER JOIN
问题
连接是OUTER一个,有时name聚合函数的组件很简单null:那行不通。然后我会去:
COALESCE(
json_object_agg(table.name, table.value) FILTER (WHERE table.name IS NOT NULL),
'{}'
)::json
到目前为止,我用来调用的代码jsonb_object_agg(不完全是,但归结为)如下:
public static Field<?> jsonbObjectAgg(final Field<?> key, final Select<?> select) {
return DSL.field("jsonb_object_agg({0}, ({1}))::jsonb", JSON_TYPE, key, select);
}
...在哪里JSON_TYPE:
private static final DataType<JsonNode> JSON_TYPE = SQLDataType.VARCHAR.asConvertedDataType(/* a custom Converter */);
不完整的解决方案
我很想利用jOOQ的AggregateFilterStep界面,特别是能够使用它的AggregateFilterStep#filterWhere(Condition... conditions).
但是,(间接通过和)的org.jooq.impl.Function类对其 的可见性受到限制,因此我不能盲目地回收 的实现:implements AggregateFilterStepAgregateFunctionArrayAggOrderBySteppackageDSL#ArrayAggOrderByStep
public static <T> ArrayAggOrderByStep<T[]> arrayAgg(Field<T> field) {
return new org.jooq.impl.Function<T[]>(Term.ARRAY_AGG, field.getDataType().getArrayDataType(), nullSafe(field));
}
尝试
我最接近合理的东西是......构建我自己的coalesceAggregation函数,专门合并聚合字段:
// Can't quite use AggregateFunction there
// v v
public static <T> Field<T> coalesceAggregation(final Field<T> agg, final Condition coalesceWhen, @NonNull final T coalesceTo) {
return DSL.coalesce(DSL.field("{0} FILTER (WHERE {1})", agg.getType(), agg, coalesceWhen), coalesceTo);
}
public static <T> Field<T> coalesceAggregation(final Field<T> agg, @NonNull final T coalesceTo) {
return coalesceAggregation(agg, agg.isNotNull(), coalesceTo);
}
......但是我再跑进我的问题T类型是JsonNode,其中DSL#coalesce好像CAST我coalesceTo来varchar。
或者,你知道:
DSL.field("COALESCE(jsonb_object_agg({0}, ({1})) FILTER (WHERE {0} IS NOT NULL), '{}')::jsonb", JSON_TYPE, key, select)
但这将是最后的手段:感觉就像我离让用户将他们想要的任何 SQL 注入我的数据库只差一步了🙄
简而言之
jOOQ 中是否有一种方法可以“正确”实现自己的聚合函数,作为实际的org.jooq.AgregateFunction?
我想尽可能避免生成它jooq-codegen(并不是我不喜欢它——这只是我们的管道太糟糕了)
FFIVE
相关分类