Custom SQL function (json_agg & json_build_object)
Hello there.
I'm new to Drizzle and I love it 😍.
I have successfully made a
jsonAgg
helper.
Now I have trouble to make a jsonAggBuildObject
😅 that should produce something like this:
I try something but it end with an error error: could not determine data type of parameter $1
Any idea ?14 Replies
It's used like that:
Note: if it doesn't optimize the underlying request (selecting only
themes.id
and themes.label
, forget that, I'm fine with the first helper and some mapping 😄Your function should return an object, not
sql
, because that's what .select()
accepts. So you need to return key-value pairs, where the key is just to map the result object, and the value is what you want to select for that particular key.
No, wait, that's not correct
Could you show how you expect the resulting SQL to look like?the resulting SQL looks like that:
since my message, I read https://github.com/drizzle-team/drizzle-orm/blob/main/docs/joins.md#aggregating-results 😄
using this "manually" in the select works 😉 But I wanted to explore the "helper" way haha.
OK I see. In that case, you need to escape the column names with the
name()
function, which will tell the ORM that it needs to be treated as a column name instead of a parameter.
When you use name()
, you don't need to manually add quotes to the query, it will be done by the ORM.
So something like sql`${name(key)}, ${value}`
Also, you always need to use sql
when you're building the query.
You can compose sql
parts inside other sql
.
You might take a look at how we map the selection objects to the SQL ourselves: https://github.com/drizzle-team/drizzle-orm/blob/main/drizzle-orm/src/pg-core/dialect.ts#L121
But this is an interesting helper! We might explore the possibility to add it to the library.yeah it's more "easy" than to reduce results later :p
btw, I've experimented a bit with this type of query and here's what I got that works (this example uses cities 1:m users):
(just replace the json_build_array with json_build_object)
might help you a bit to build your helper 🙂
the joined count is for an edge case when you're joining nullable columns only and no right rows were joined for a certain left row - the result will have a single right row with all columns as nulls, but the joined count will be zero.
Also, check the
filter
clause in json_agg, it needs to have a check that one of non-nullable columns in the joined table is not null (for automated generation, it can just use a first non-nullable column from the joined table).Thanks for your help!
It takes me 5h but it works 😂
don't tell me there was an easier way, please 🤣
1. You shouldn't use
inlineParams
here, it's only intended for static queries, you're introducing a SQL injection vulnerability. As I wrote earlier, you should use the name()
function.
2. [] as SQL[]
is an incorrect usage, it should be const chunks: SQL[] = []
Other then that, looks goodname()
produces double "
😢But you're escaping a column name, no?
It should be double quotes
json_build_object
is a mapper to make a custom json from a group result.
name()
produces this sql : json_agg(json_build_object("test","themes_2"."id","test2","themes_2"."label"))
should be json_agg(json_build_object('test',"themes_2"."id",'test2',"themes_2"."label"))
(single quotes for key name)
I know that's maybe overthinking 😅ahh I see
then you can use
sql.raw(`'${key}'`)
but you should be careful, since it still has potential for SQL injections, so you shouldn't allow user-specified key namesThank you! I now have everything I need to continue my journey
Very helpful, I divided it in two so I could nest things up a bit!
... so I can do dumb stuff like this: