I'm currently using SQLKorma for a project, and I'm running into a bit of a snag with it.
I have constructed a query with two left-joins; one of them contains an array with entries that I wish to use in my WHERE
clause.
This is trivial to express in SQL. Note that this is a primarily redacted query.
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
The portion in regards to ILIKE ANY
is what I'd like to be able to translate to Korma.
I understand from the docs that the ANY
clause isn't supported from the WHERE
clause, and I should look into using raw
or exec-raw
instead.
With that, I want to pass in a parameterized raw
string into the WHERE
clause to accomplish what I'm trying to go for.
This I've attempted, but it does fails with a syntax error in 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])))
Specifically:
PSQLException:
Message: ERROR: syntax error at or near "["
Position: 1006
SQLState: 42601
Error Code: 0
How would I go about this using Korma? Do I have to resort to a full-blown exec-raw
query?
Korma has a very helpful function korma.core/sql-only
which will render the SQL string that would be executed.
(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\"]"
or the more readable:
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"]
as you can see, the ILIKE is surrounded by []
. Korma's raw
just takes a raw string and doesn't support parameterisation like exec-raw
does. The vector around the ILIKE string was just turned into a string with its contents. This is why you got a Postgres error about [
.
You need to remove the []
from around the ILIKE string if you want to continue using raw
, or see if exec-raw
is going to fit your needs better. There is the very present danger of SQL injection if you are using 'raw' though which you will need to address.
;; 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)"])))