亚洲在线久爱草,狠狠天天香蕉网,天天搞日日干久草,伊人亚洲日本欧美

為了賬號安全,請及時綁定郵箱和手機立即綁定
已解決430363個問題,去搜搜看,總會有你想問的

使用 jOOQ 創建自定義聚合函數

使用 jOOQ 創建自定義聚合函數

慕婉清6462132 2021-12-01 14:35:43
語境我正在針對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#ArrayAggOrderBySteppublic 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   vpublic 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(并不是我不喜歡它——這只是我們的管道太糟糕了)
查看完整描述

1 回答

?
FFIVE

TA貢獻1797條經驗 獲得超6個贊

從 jOOQ 3.14.0 開始

JSON_OBJECTAGG聚合函數是在本機現在jOOQ支持:

DSL.jsonObjectAgg(TABLE.NAME, TABLE.VALUE).filterWhere(TABLE.NAME.isNotNull());

FILTER在 jOOQ 3.14.8 中添加了對子句的支持。

從 jOOQ 3.14.8 和 3.15.0 開始

如果 jOOQ 沒有實現特定的聚合函數,您現在可以指定DSL.aggregate()使用自定義聚合函數。

DSL.aggregate("json_object_agg", SQLDataType.JSON, TABLE.NAME, TABLE.VALUE)
   .filterWhere(TABLE.NAME.isNotNull());

這是通過https://github.com/jOOQ/jOOQ/issues/1729實現的

對于 jOOQ 3.14.0

jOOQ DSLAPI 中缺少一個功能,即創建純 SQL 聚合函數。這還不可用的原因(從 jOOQ 3.11 開始)是因為有很多微妙的內部結構來指定支持所有供應商特定選項的供應商不可知聚合函數,包括:

  • FILTER (WHERE ...) 條款(如您在問題中提到的),必須使用 CASE

  • OVER (...) 子句將聚合函數轉換為窗口函數

  • WITHIN GROUP (ORDER BY ...) 支持有序集合聚合函數的子句

  • DISTINCT 條款,如果支持

  • 其他特定于供應商的聚合函數擴展

在您的特定情況下,簡單的解決方法是一直使用純 SQL 模板,正如您在問題中提到的:

DSL.field("COALESCE(jsonb_object_agg({0}, ({1})) FILTER (WHERE {0} IS NOT NULL), '{}')::jsonb", JSON_TYPE, key, select)

或者你做你之前提到的事情。關于這種擔憂:

...但我隨后遇到了我的 T 類型為 JsonNode 的問題,其中 DSL#coalesce 似乎將我的 coalesceTo 轉換為 varchar。

那可能是因為您使用了agg.getType()which returnsClass<?>而不是agg.getDataType()which returns DataType<?>。

但這將是最后的手段:感覺就像我離讓用戶將他們想要的任何 SQL 注入我的數據庫僅一步之遙

我不確定為什么這是一個問題。您仍然可以自己控制普通 SQL API 的使用,用戶將無法注入任意內容key,select因為您也控制這些元素。


查看完整回答
反對 回復 2021-12-01
  • 1 回答
  • 0 關注
  • 328 瀏覽
慕課專欄
更多

添加回答

舉報

0/150
提交
取消
微信客服

購課補貼
聯系客服咨詢優惠詳情

幫助反饋 APP下載

慕課網APP
您的移動學習伙伴

公眾號

掃描二維碼
關注慕課網微信公眾號