SELECT 来自更新的结果 ... 在 jOOQ 中返回
SELECT from result of UPDATE ... RETURNING in jOOQ
我正在将一些旧的 PostgreSQL 代码转换为 jOOQ,我目前正在努力处理具有多个 WITH
子句的 SQL,其中每个子句都依赖于前一个。最好保持 SQL 逻辑的编写方式而不是更改它(例如,对 DB 的多个查询)。
看起来,SELECT 无法对正在更新...返回的内容进行操作,例如
dsl.select(DSL.asterisk())
.from(dsl.update(...)
.returning(DSL.asterisk())
)
我创建了一些测试 tables,试图创建某种 MVCE:
create table dashboard.test (id int primary key not null, data text); --test table
with updated_test AS (
UPDATE dashboard.test SET data = 'new data'
WHERE id = 1
returning data
),
test_user AS (
select du.* from dashboard.dashboard_user du, updated_test -- from previous WITH
where du.is_active AND du.data = updated_test.data
)
SELECT jsonb_build_object('test_user', to_jsonb(tu.*), 'updated_test', to_jsonb(ut.*))
FROM test_user tu, updated_test ut; -- from both WITH clauses
到目前为止,这是我的 jOOQ 代码(用 Kotlin 编写):
dsl.with("updated_test").`as`(
dsl.update(Tables.TEST)
.set(Tables.TEST.DATA, DSL.value("new data"))
.returning(Tables.TEST.DATA) //ERROR is here: Required Select<*>, found UpdateResultStep<TestRecord>
).with("test_user").`as`(
dsl
.select(DSL.asterisk())
.from(
Tables.DASHBOARD_USER,
DSL.table(DSL.name("updated_test")) //or what to use here?
)
.where(Tables.DASHBOARD_USER.IS_ACTIVE.isTrue
.and(Tables.DASHBOARD_USER.DATA.eq(DSL.field(DSL.name("updated_test.data"), String::class.java)))
)
)
.select() //here goes my own logic for jsonBBuildObject (which is tested and works for other queries)
.from(
DSL.table(DSL.name("updated_test")), //what to use here
DSL.table(DSL.name("test_user")) //or here
)
是否有任何解决方法?如果可能,我想避免更改 SQL。
此外,在这个项目中,这个技巧经常用于从 UPDATE 子句中获取 JSON(B)(table 也有 JSON(B) 列):
with _updated AS (update dashboard.test SET data = 'something' WHERE id = 1 returning *)
select to_jsonb(_updated.*) from _updated;
如果没有解决方法,这对我们来说将是真正的倒退。
我正在使用 JOOQ 版本 3.13.3
和 Postgres 12.0.
jOOQ 目前不支持此功能,请参阅:
解决方法一如既往,当某些特定于供应商的语法不受支持时,求助于plain SQL templating
例如
// If you don't need to map data types
dsl.fetch("with t as ({0}) {1}", update, select);
// If you need to map data types
dsl.resultQuery("with t as ({0}) {1}", update, select).coerce(select.getSelect()).fetch();
我正在将一些旧的 PostgreSQL 代码转换为 jOOQ,我目前正在努力处理具有多个 WITH
子句的 SQL,其中每个子句都依赖于前一个。最好保持 SQL 逻辑的编写方式而不是更改它(例如,对 DB 的多个查询)。
看起来,SELECT 无法对正在更新...返回的内容进行操作,例如
dsl.select(DSL.asterisk())
.from(dsl.update(...)
.returning(DSL.asterisk())
)
我创建了一些测试 tables,试图创建某种 MVCE:
create table dashboard.test (id int primary key not null, data text); --test table
with updated_test AS (
UPDATE dashboard.test SET data = 'new data'
WHERE id = 1
returning data
),
test_user AS (
select du.* from dashboard.dashboard_user du, updated_test -- from previous WITH
where du.is_active AND du.data = updated_test.data
)
SELECT jsonb_build_object('test_user', to_jsonb(tu.*), 'updated_test', to_jsonb(ut.*))
FROM test_user tu, updated_test ut; -- from both WITH clauses
到目前为止,这是我的 jOOQ 代码(用 Kotlin 编写):
dsl.with("updated_test").`as`(
dsl.update(Tables.TEST)
.set(Tables.TEST.DATA, DSL.value("new data"))
.returning(Tables.TEST.DATA) //ERROR is here: Required Select<*>, found UpdateResultStep<TestRecord>
).with("test_user").`as`(
dsl
.select(DSL.asterisk())
.from(
Tables.DASHBOARD_USER,
DSL.table(DSL.name("updated_test")) //or what to use here?
)
.where(Tables.DASHBOARD_USER.IS_ACTIVE.isTrue
.and(Tables.DASHBOARD_USER.DATA.eq(DSL.field(DSL.name("updated_test.data"), String::class.java)))
)
)
.select() //here goes my own logic for jsonBBuildObject (which is tested and works for other queries)
.from(
DSL.table(DSL.name("updated_test")), //what to use here
DSL.table(DSL.name("test_user")) //or here
)
是否有任何解决方法?如果可能,我想避免更改 SQL。 此外,在这个项目中,这个技巧经常用于从 UPDATE 子句中获取 JSON(B)(table 也有 JSON(B) 列):
with _updated AS (update dashboard.test SET data = 'something' WHERE id = 1 returning *)
select to_jsonb(_updated.*) from _updated;
如果没有解决方法,这对我们来说将是真正的倒退。
我正在使用 JOOQ 版本 3.13.3
和 Postgres 12.0.
jOOQ 目前不支持此功能,请参阅:
解决方法一如既往,当某些特定于供应商的语法不受支持时,求助于plain SQL templating
例如
// If you don't need to map data types
dsl.fetch("with t as ({0}) {1}", update, select);
// If you need to map data types
dsl.resultQuery("with t as ({0}) {1}", update, select).coerce(select.getSelect()).fetch();