Is there any way to automatically turn a %Ecto.Query{}
struct into a string that contains a SQL query that I can just copy-paste into psql
without changing anything?
Let’s say I have this Ecto query:
recipient_id = "a6c0b3c0-27f0-4fea-8182-acd24b86c02e"
ecto_query = from(m in Message, where: is_nil(m.read_at) and m.recipient_id == ^recipient_id)
# => #Ecto.Query<from m0 in Message,
# where: is_nil(m0.read_at) and m0.recipient_id == ^"a6c0b3c0-27f0-4fea-8182-acd24b86c02e">
I would execute the query like this:
Repo.aggregate(ecto_query, :count, :id)
# => [debug] QUERY OK source="messages" db=11.3ms queue=0.5ms idle=1723.2ms
# SELECT count(m0."id") FROM "messages" AS m0 WHERE ((m0."read_at" IS NULL) AND (m0."recipient_id" = $1)) [<<166, 192, 179, 192, 39, 240, 79, 234, 129, 130, 172, 210, 75, 134, 192, 46>>]
And the hypothetical function I am asking about would work something like this:
sql_query = some_magical_function({Repo, :aggregate, [ecto_query, :count, :id]})
IO.puts(sql_query)
# => SELECT count(m0."id") FROM "messages" AS m0 WHERE ((m0."read_at" IS NULL) AND (m0."recipient_id" = 'a6c0b3c0-27f0-4fea-8182-acd24b86c02e'));
I tried reading the sources of Ecto, ecto_sql
, and postgrex
but couldn’t figure out anything on my own.
Currently, whenever I need this, I do this slow manual process:
Step 0: I run my Ecto query and copy the SQL query from Ecto’s debug log and paste it somewhere.
SELECT count(m0."id") FROM "messages" AS m0 WHERE ((m0."read_at" IS NULL) AND (m0."recipient_id" = $1)) [<<166, 192, 179, 192, 39, 240, 79, 234, 129, 130, 172, 210, 75, 134, 192, 46>>]
Step 1: I read the query, find all the UUID binaries and turn them into strings. To do that, I fire up iex
and I run Ecto.UUID.cast
.
SELECT count(m0."id") FROM "messages" AS m0 WHERE ((m0."read_at" IS NULL) AND (m0."recipient_id" = $1)) ['a6c0b3c0-27f0-4fea-8182-acd24b86c02e']
Step 2: I substitute all the $ parameters with their values, remove the [...]
, and add ;
at the end. The bigger the query, the more annoying it gets.
SELECT count(m0."id") FROM "messages" AS m0 WHERE ((m0."read_at" IS NULL) AND (m0."recipient_id" = 'a6c0b3c0-27f0-4fea-8182-acd24b86c02e'));