Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Differences between IN queries between v1 and v2 #418

Closed
austb opened this issue Jul 29, 2022 · 2 comments
Closed

Differences between IN queries between v1 and v2 #418

austb opened this issue Jul 29, 2022 · 2 comments
Assignees
Labels
documentation I need to write something up!

Comments

@austb
Copy link

austb commented Jul 29, 2022

Hi, I'm in the process of upgrading from honeysql v1 to v2. We make use of a lot of queries with IN expressions, and I'm curious if this change is intentional between the two versions of honeysql, and if so, if I have the proper workaround.

=> (require '[honeysql.core :as hsqlv1])
=> (require '[honey.sql :as hsqlv2])

=> (def in-query {:select [:foo] :from [:bar] :where [:in [:bar :baz] {:select [:bar :baz] :from [:oof]}]})

=> (hsqlv1/format in-query)
["SELECT foo FROM bar WHERE ((bar, baz) in (SELECT bar, baz FROM oof))"]

In v1 it works in the way that we intended, creating an IN statement using two columns. However in hsql v2 it turns the columns into a function call. Based on some of the docs, I thought that function calls required to be doubly nest, like [[:d :e]] from the migration doc?

=> (hsqlv2/format in-query)
["SELECT foo FROM bar WHERE BAR(baz) IN (SELECT bar, baz FROM oof)"]

I have found a workaround, by adding :inline wrappers to the columns, I can get the query that I want. Is this the proper way to construct this type of query?

=> (def inlined-query {:select [:foo] :from [:bar] :where [:in [[:inline :bar] [:inline :baz]] {:select [:bar :baz] :from [:oof]}]})
=> (hsqlv2/format inlined-query)
["SELECT foo FROM bar WHERE (bar, baz) IN (SELECT bar, baz FROM oof)"]

It also affects single column queries

=> (def single-column-query {:select [:foo] :from [:bar] :where [:in [:bar] {:select [:bar] :from [:oof]}]})
=> (hsqlv2/format single-column-query)
["SELECT foo FROM bar WHERE BAR() IN (SELECT bar FROM oof)"]

but those have a simpler workaround of just omitting the square brackets all together

=> (def single-column-query {:select [:foo] :from [:bar] :where [:in :bar {:select [:bar] :from [:oof]}]})
=> (hsqlv2/format single-column-query)
["SELECT foo FROM bar WHERE bar IN (SELECT bar FROM oof)"]
@seancorfield
Copy link
Owner

Interesting. I had no idea that multi-column IN expressions were legal SQL nor that HoneySQL (v1) used to produce them correctly.

The "doubly nest" for function calls is only in SELECT (and similar contexts that support aliasing) -- purely to distinguish between [:a :b] meaning a AS b and [[:a b]] meaning A(b) -- the full form is [[:a :b] :c] meaning A(b) AS c but the alias can be omitted.

The v2 way to get a tuple of columns is using :composite:

dev=> (sql/format {:select [:foo] :from [:bar] :where [:in [:composite :bar :baz] {:select [:bar :baz] :from [:oof]}]})
["SELECT foo FROM bar WHERE (bar, baz) IN (SELECT bar, baz FROM oof)"]
dev=>

I'll update the :in documentation to warn about this difference and how to produce the multi-column version.

@seancorfield seancorfield self-assigned this Jul 29, 2022
@seancorfield seancorfield added the documentation I need to write something up! label Jul 29, 2022
@austb
Copy link
Author

austb commented Jul 29, 2022

Thanks! That makes sense.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
documentation I need to write something up!
Projects
None yet
Development

No branches or pull requests

2 participants