honeysql

igrishaev 2024-06-18T19:41:37.659509Z

Is there a way to generate an expression like

select data['attrs']['users'][0]['email']
having a vector
[:attrs :users 0 :email]
? Of course, I can do that with the #> operator and array:
[:#>> :data [:array ...]]
but I'm still interested in the first option.

p-himik 2024-06-18T19:49:48.753059Z

The only relevant way to get [...] in the HoneySQL code is via :inline. However, it doesn't work by itself because [...] passed to :inline gets treated as wrapping in (...). But using [:inline [:lift [...]]] works.

(sql/format {:select [[[:inline :data
                        [:lift ["attrs"]]
                        [:lift ["users"]]
                        [:lift [0]]
                        [:lift ["email"]]]]]})
=> ["SELECT data ['attrs'] ['users'] [0] ['email']"]
I would definitely create my own clause for this. :)

igrishaev 2024-06-18T19:57:00.658319Z

Interesting... thanks!

seancorfield 2024-06-18T20:03:39.807429Z

I'd be willing to add support for this if you can think of a reasonable (special) syntax that won't conflict with anything else...

seancorfield 2024-06-18T20:04:40.627619Z

Also, does it specifically need to be inlined or can those indices be expressions/external values (i.e., data[?][?][?][?] and params for the constants)?

igrishaev 2024-06-19T06:03:56.009579Z

I've checked if indices can be parameters, and yes they can:

prepare test as select ('{"foo": {"bar": 42}}'::jsonb) [$1];
PREPARE

test=# execute test('foo');
    jsonb
-------------
 {"bar": 42}
(1 row)
so it could be something like that
["select data[?][?][?]" "foo" "bar" "baz"]

👍🏻 1