I have this statement:
myuser.orders.exists?(['(orderstatus = ?) ', statusid])
It returns true since there is an orderstatus that matches the statusid.
Next I have:
myuser.orders.where('id not in (?)', nil).exists?(['(orderstatus = ?) ', statusid])
This returns false where I thought it might return true since there are no ids that are nil.
Then I have:
myuser.orders.where(nil).exists?(['(orderstatus = ?) ', statusid])
This returns true.
My question is why does the middle statement return false? It doesn’t complain or throw any errors. I guess I’m using nil wrong, but can someone explain?
You’re having trouble with SQL’s NULL. The
wherein the middle one:becomes this SQL:
and that’s equivalent to this:
But the result of
id != nullis neither true nor false, the result is NULL and NULL in a boolean context is false; in fact,x = nullandx != nullresult in NULL for allx(even whenxitself is NULL); for example, in PostgreSQL:MySQL and every other reasonably compliant database will do the same thing (with possibly different casting requirements to make the NULL obvious).
The result is that
where(id not in (?)', nil)always yields an empty set and your existence check will always fail on an empty set.If you want to say “all the rows where
idis not NULL” then you want to say:If your
idis a primary key (as it almost certainly is), thenidwill never be NULL and you can leave thatwhereout completely.When you hand
wherejust anil:where‘s argument parsing logic will ignore thenilcompletely andwhere(nil)will be the same aswhere()andwhere()does nothing at all to the query. The result is that the first and third queries are identical as far as the database is concerned.