-
Notifications
You must be signed in to change notification settings - Fork 1.5k
ensure select statements in joined queries have access to parent bindings #4653
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
ensure select statements in joined queries have access to parent bindings #4653
Conversation
Thanks for the PR! I would like to hear @greg-rychlewski's opinion but my gut feeling is that the test should not pass indeed. In this case:
The parent query of Forget subqueries for a second. Imagine you have
In this case, Therefore, when you do this:
Once again, |
Let me give another example:
which one is now the actual parent? The query above doesn't work, because we only allow a subset of queries in joins, but we could allow the construct above in the future (it is not a technical limitation, it just wasn't implemented yet), and now there would be ambiguity, because you want the |
I could be wrong here, but don't i.e given your example: query =
from thing in Post,
as: :outer,
inner_lateral_join: sub in ^from(row in subquery(child), join: "outers", as: :outer),
on: true
|
The walking upwards does not matter, because, as per my first comment, there is no parent/child relationship between the You have three queries:
QUERY 1 and 2 is regular query composition. There is no parent/child relationship in there. The same way |
In summary, you only have child/parent relationships if there is an explicit subquery call. That's exactly so people don't have to guess what is composition and what is parent/child. That's why I said it could only work if you did double nesting:
(which in this case is obviously unnecessary) |
Yeah after looking at this I have the same opinion as @josevalim. I think the crux is these two things are not the same
The subquery in the latter example doesn't know anything outside of I can understand the confusion though because if I was just writing the SQL by hand and joining on a query I would be forced to wrap the whole thing in a subquery or it would be invalid SQL. But with Ecto you have to think in terms of composition. |
Roger. It makes sense, but I think is a bit of a footgun. In a case like that when you're slotting an Ecto query into a place that can only ever be a subquery (lateral joins require a subquery) it feels like it should just treat the containing query as a "parent" for the purposes of Probably as simple as me not doing that or unwrapping it when I do the inner lateral join 🤷 |
I think the issue is that in raw SQL the joined query must be in a subquery whether it is lateral or not. Lateral just changes how the join is done and allows access to the outside. So when Ecto is allowing a join on a query under any circumstance, it is performing composition rather than an implicit subquery. Which, for the record, I agree is confusing at first. The first time I saw it I had to take a look at the actual query that was being generated to fully understand what was going on. But it is providing useful functionality to users. |
Ultimately, I don't fully understand how parent binding sources are managed well enough to really say if this is the most correct fix. Since
parent_as
works in other, non-select contexts using this formulation, it feels like there may be a more targeted/specific fix available?Regardless, the newly added test will fail without the fix, and the fix does not cause any additional test failures. Open to adjusting it if as needed.