Hello,
I just found a bug in a larger query of mine, which boils down to this simplified example:
(For the sake of the example, assume a Post can have only one, optional, Comment)
Post
|> join(:left, [p], c in assoc(p, :comment)
|> join(:inner, [p, c], u in assoc(c, :user))
The correct version uses left
in both join statements.
I believe this query is wrong, because the inner join was written with the idea that a Comment will always have a User, so a join between Comment and User will always produce the same rows, whether an :inner
or a :left
join. However, at the SQL level it’s a huge difference whether we join
Post <<-> (Comment <-> User)
# or
(Post <<-> Comment) <-> User
# where <<-> shall denote a left join and <-> an inner join
in other words, joins of different types are not associative.
Apparently, in my case, the join pipeline boiled down to first joining Post-Comment, then User, which lead to missing result rows.
The question then is:
At the Ecto level, is this undefined behaviour, or is it just undocumented? (Or, is it documented but I could not find it?)