luckyframework / luckyframework/avram

Unable to query a model where 2 associations use the same model

Open
#1,011 3 comments 0 reactions 0 assignees View on GitHub

Nobody has claimed this yet.

bug
Dominant language
Crystal
Stars
183
Forks
67
PR merge metrics
No merged PRs in 30d

Description

Related: #1007

Say you have a model where it has 2 `belongs_to` and both of those associations are the same model (e.g. User), any query you do that requires both will only use 1 join and override any where clauses set.

```crystal
class Interview < BaseModel
table do
belongs_to interviewer : User
belongs_to interviewee : User
end
end

# I want to query for all interviews where the Interviewer isn't available for hire, but the Interviewee is
InterviewQuery.new
.where_interviewer(UserQuery.new.available_for_hire(false))
.where_interviewee(UserQuery.new.available_for_hire(true))
```

In this case, we end up getting this SQL which is not what I want

```sql
SELECT interviews.*
FROM interviews
INNER JOIN users ON interviews.interviewer_id = users.id
WHERE users.available_for_hire = 'false'
AND users.available_for_hire = 'true'
```

My initial thought is if we just always alias the joins to your association method name, then maybe it'll fix this. However, I think that may also be a breaking change for anyone using `where(raw_query : String)`.

So `where_interviewer` would go from

```
INNER JOIN users ON interviews.interviewer_id = users.id
```

to

```
INNER JOIN users AS interviewers ON interviews.interviewer_id = interviewers.id
```

But then anyone that was doing `where("users.something @> ?", ...)` would now get runtime errors since they would need to change it to `where("interviewers.something @> ?", ...)`.

Maybe we can use some annotation to turn on this change at compile time and give people time to swap over? I'm not sure how that would work. :thinking:

Contributor guide

Open the contributing guide

First steps

  1. Read the whole issue, then the project's contributing guide.
  2. Comment on the issue to say you are picking it up — it saves two people doing the same work.
  3. Fork the repository and make your change on a branch.
  4. Open a pull request that references the issue number.

Research direction

Start with the where_interviewer and where_interviewee query methods and reproduce the SQL shown in the issue using two belongs_to associations targeting User. Investigate how joins and raw where clauses are named; done means both associations can be queried independently without conflicting conditions while the compatibility impact of existing users[something] clauses is addressed.

Written by the indexing model from the issue text.

Assessment

Tech stack
crystal, sql
Domain
backend, databases
Issue type
Bug
Difficulty
4/5
Estimated time
3-5 days
Activity status
Stale
Clarity
Mostly clear
Newbie friendliness
35/100

Get new issues in your inbox

A short digest of beginner-friendly GitHub issues.