在 SQLKorma 中表达(参数化)对 Postgres 的任何(数组)查询
Expressing (parameterized) ANY(array) query for Postgres in SQLKorma
我目前正在为一个项目使用 SQLKorma,但我 运行 遇到了一些问题。
我构建了一个包含两个左连接的查询;其中之一包含一个数组,其中包含我希望在 WHERE
子句中使用的条目。
这在SQL中表达起来很简单。请注意,这是一个主要经过编辑的查询。
SELECT
cu.name,
c.description,
c.created_at AT TIME ZONE 'utc'
FROM calendar_users cu LEFT JOIN calendars c ON cu.id = c.user_id
LEFT JOIN meetings m ON c.id = m.id
WHERE 'status_report' ILIKE ANY (m.meeting_metadata)
GROUP BY m.meeting_metadata, c.created_at, cu.name, cu.description
ORDER BY c.created_at DESC
关于 ILIKE ANY
的部分是我希望能够翻译成 Korma 的内容。
I understand from the docs WHERE
子句不支持 ANY
子句,我应该考虑改用 raw
或 exec-raw
。
因此,我想将参数化的 raw
字符串传递到 WHERE
子句中以完成我想要实现的目标。
我已经尝试过了,但在 Postgres 中由于语法错误而失败了:
(select calendars
(fields calendar-user-cols)
(join :calendar_users (= :calendars.user_id :calendar_users.id))
(join :meetings (= :calendars.id :meetings.id))
(where (raw ["? ILIKE ANY(meetings.meeting_metadata)" metadata])))
具体来说:
PSQLException:
Message: ERROR: syntax error at or near "["
Position: 1006
SQLState: 42601
Error Code: 0
我将如何使用 Korma 来解决这个问题?我是否必须求助于成熟的 exec-raw
查询?
Korma 有一个非常有用的函数 korma.core/sql-only
,它将呈现将要执行的 SQL 字符串。
(defentity calendars)
=> #'korma-test.core/calendars
(sql-only
(select calendars
(fields :x :y)
(join :calendar_users (= :calendars.user_id :calendar_users.id))
(join :meetings (= :calendars.id :meetings.id))
(where (raw ["? ILIKE ANY(meetings.meeting_metadata)" "status_report"]))))
=> "SELECT \"calendars\".\"x\", \"calendars\".\"y\" FROM (\"calendars\" LEFT JOIN \"calendar_users\" ON \"calendars\".\"user_id\" = \"calendar_users\".\"id\") LEFT JOIN \"meetings\" ON \"calendars\".\"id\" = \"meetings\".\"id\" WHERE [\"? ILIKE ANY(meetings.meeting_metadata)\" \"status_report\"]"
或更具可读性:
SELECT "calendars"."x",
"calendars"."y"
FROM ("calendars"
LEFT JOIN "calendar_users" ON "calendars"."user_id" = "calendar_users"."id")
LEFT JOIN "meetings" ON "calendars"."id" = "meetings"."id"
WHERE ["? ILIKE ANY(meetings.meeting_metadata)" "status_report"]
如您所见,ILIKE 被 []
包围。 Korma 的 raw
只接受原始字符串,不像 exec-raw
那样支持参数化。 ILIKE 字符串周围的向量刚刚变成一个包含其内容的字符串。这就是为什么您收到有关 [
.
的 Postgres 错误的原因
如果您想继续使用 raw
,您需要从 ILIKE 字符串周围删除 []
,或者查看 exec-raw
是否会更好地满足您的需求。如果您使用 'raw',则存在 SQL 注入的危险,您需要解决这个问题。
;; require clojure.string :as str in your ns
;; change your clause from
(where (raw ["? ILIKE ANY(meetings.meeting_metadata)" "status_report"])))
;; to this
(where (raw (str/join " " ["'status_report'" "ILIKE ANY(meetings.meeting_metadata)"])))
我目前正在为一个项目使用 SQLKorma,但我 运行 遇到了一些问题。
我构建了一个包含两个左连接的查询;其中之一包含一个数组,其中包含我希望在 WHERE
子句中使用的条目。
这在SQL中表达起来很简单。请注意,这是一个主要经过编辑的查询。
SELECT
cu.name,
c.description,
c.created_at AT TIME ZONE 'utc'
FROM calendar_users cu LEFT JOIN calendars c ON cu.id = c.user_id
LEFT JOIN meetings m ON c.id = m.id
WHERE 'status_report' ILIKE ANY (m.meeting_metadata)
GROUP BY m.meeting_metadata, c.created_at, cu.name, cu.description
ORDER BY c.created_at DESC
关于 ILIKE ANY
的部分是我希望能够翻译成 Korma 的内容。
I understand from the docs WHERE
子句不支持 ANY
子句,我应该考虑改用 raw
或 exec-raw
。
因此,我想将参数化的 raw
字符串传递到 WHERE
子句中以完成我想要实现的目标。
我已经尝试过了,但在 Postgres 中由于语法错误而失败了:
(select calendars
(fields calendar-user-cols)
(join :calendar_users (= :calendars.user_id :calendar_users.id))
(join :meetings (= :calendars.id :meetings.id))
(where (raw ["? ILIKE ANY(meetings.meeting_metadata)" metadata])))
具体来说:
PSQLException:
Message: ERROR: syntax error at or near "["
Position: 1006
SQLState: 42601
Error Code: 0
我将如何使用 Korma 来解决这个问题?我是否必须求助于成熟的 exec-raw
查询?
Korma 有一个非常有用的函数 korma.core/sql-only
,它将呈现将要执行的 SQL 字符串。
(defentity calendars)
=> #'korma-test.core/calendars
(sql-only
(select calendars
(fields :x :y)
(join :calendar_users (= :calendars.user_id :calendar_users.id))
(join :meetings (= :calendars.id :meetings.id))
(where (raw ["? ILIKE ANY(meetings.meeting_metadata)" "status_report"]))))
=> "SELECT \"calendars\".\"x\", \"calendars\".\"y\" FROM (\"calendars\" LEFT JOIN \"calendar_users\" ON \"calendars\".\"user_id\" = \"calendar_users\".\"id\") LEFT JOIN \"meetings\" ON \"calendars\".\"id\" = \"meetings\".\"id\" WHERE [\"? ILIKE ANY(meetings.meeting_metadata)\" \"status_report\"]"
或更具可读性:
SELECT "calendars"."x",
"calendars"."y"
FROM ("calendars"
LEFT JOIN "calendar_users" ON "calendars"."user_id" = "calendar_users"."id")
LEFT JOIN "meetings" ON "calendars"."id" = "meetings"."id"
WHERE ["? ILIKE ANY(meetings.meeting_metadata)" "status_report"]
如您所见,ILIKE 被 []
包围。 Korma 的 raw
只接受原始字符串,不像 exec-raw
那样支持参数化。 ILIKE 字符串周围的向量刚刚变成一个包含其内容的字符串。这就是为什么您收到有关 [
.
如果您想继续使用 raw
,您需要从 ILIKE 字符串周围删除 []
,或者查看 exec-raw
是否会更好地满足您的需求。如果您使用 'raw',则存在 SQL 注入的危险,您需要解决这个问题。
;; require clojure.string :as str in your ns
;; change your clause from
(where (raw ["? ILIKE ANY(meetings.meeting_metadata)" "status_report"])))
;; to this
(where (raw (str/join " " ["'status_report'" "ILIKE ANY(meetings.meeting_metadata)"])))