使用unfst作为字段而不是jOOQ中的表

时间:2016-04-12 11:46:44

标签: postgresql jooq

这是我试图在PostgreSQL中运行的查询:

SELECT * FROM message WHERE id IN (
    SELECT unnest(message_ids) "mid"
        FROM session_messages WHERE session_id = '?' ORDER BY "mid" ASC
);

但是,我无法做某事:

create.selectFrom(Tables.MESSAGE).where(Tables.MESSAGE.ID.in(
    create.select(DSL.unnest(..))

因为DSL.unnestTable<?>,因为它试图采用类似List的对象(主要是文字对象)并将其转换为表格而有意义。

我有一种感觉,我需要找到一种方法来围绕我的字段名称包装函数,但我不知道如何继续。

请注意。字段message_ids的类型为bigint[]

修改

所以,这就是我现在正在做的事情,它完全符合预期,但我不确定这是否是最好的方法:

Field<Long> unnestMessageIdField = DSL.field(
                "unnest(" +  SESSION_MESSAGES.MESSAGE_IDS.getName() + ")",
                Long.class)
        .as("mid");

Field<Long> messageIdField = DSL.field("mid", Long.class);

MESSAGE.ID.in(
        ctx.select(messageIdField).from(
            ctx.select(unnestMessageIdField)
               .from(Tables.CHAT_SESSION_MESSAGES)
                    .where(Tables.CHAT_SESSION_MESSAGES.SESSION_ID.eq(sessionId))
            )
            .where(condition)
)

EDIT2

在查看https://github.com/jOOQ/jOOQ/blob/master/jOOQ/src/main/java/org/jooq/impl/DSL.java上的代码后,我想正确的方法是:

DSL.function("unnest", SQLDataTypes.BIGINT.getArrayType(), SESSION_MESSAGES.MESSAGE_IDS)

EDIT3

因为总是lukas在这里为我的jOOQ困境,我将利用这个:)

尝试在排序

的签名中概括此函数
public <T> Field<T> unnest(Field<T[]> arrayField) {
    return DSL.function("unnest", <??>, arrayField);
}

我不知道如何获取数据类型。似乎有办法使用DataType<T[]>DataType<T>获取DataType::getArrayDataType(),但反过来是不可能的。我找到了ArrayDataType这个类,但它似乎是包私有的,所以我不能使用它(即使我可以,它也不会暴露字段elementType)。

1 个答案:

答案 0 :(得分:2)

旧的PostgreSQL版本有这个时髦的想法,可以从SELECT子句中生成一个表,并将其扩展到“外部”表中,就好像它是在FROM中声明的那样条款。这是一个非常模糊的PostgreSQL遗产,这个例子很好地摆脱它,并使用LATERAL代替。您的查询与此相同:

SELECT * 
FROM message 
WHERE id IN (
    SELECT "mid"
    FROM session_messages 
    CROSS JOIN LATERAL unnest(message_ids) AS t("mid")
    WHERE session_id = '?' 
);

这可以更容易地翻译成jOOQ:

DSL.using(configuration)
   .select()
   .from(MESSAGE)
   .where(MESSAGE.ID).in(
        select(field(name("mid"), MESSAGE.ID.getDataType()))
       .from(SESSION_MESSAGES)
       .crossJoin(lateral(unnest(SESSION_MESSAGES.MESSAGE_IDS)).as("t", "mid"))
       .where(SESSION_MESSAGES.SESSION_ID.eq("'?'"))
   )