Opened 3 years ago

Closed 3 years ago

#18854 closed Cleanup/optimization (fixed)

Fix join promotion in disjunction cases

Reported by: akaariai Owned by: nobody
Component: Database layer (models, ORM) Version: master
Severity: Normal Keywords:
Cc: Triage Stage: Accepted
Has patch: yes Needs documentation: no
Needs tests: no Patch needs improvement: no
Easy pickings: no UI/UX: no


The current join promotion logic in disjuction cases is confusing, and it produces often too many LEFT joins.

I'd like to clean it up with something like this. There are two commits, one doing the cleanup in sql/, the other adds tests. 4/6 of the added tests fail on master.

Change History (3)

comment:1 Changed 3 years ago by akaariai

I have done some more work on the patch. I think this is nearing commit quality.

All Django's current tests pass and there are even more (hopefully correct) test cases to verify the taken approach.

In short, the taken approach is this: When doing an ORed filter, if some join is referenced in all of the childs of the filter (the OR branches) it is kept as inner join. If there is an existing join to some alias generated by earlier .filter() calls or another branch of the current Q-object, then the existing join type is kept. Otherwise joins generated by the ORed filters are promoted to left outer joins.

comment:2 Changed 3 years ago by akaariai

  • Triage Stage changed from Unreviewed to Accepted

I still do think there is room for improvement here. Marking as accepted.

comment:3 Changed 3 years ago by Anssi Kääriäinen <akaariai@…>

  • Resolution set to fixed
  • Status changed from new to closed

In d407164c0499c234ec043f5720b3209311b2f4e9:

Fixed #18854 -- Join promotion in disjunction cases

The added promotion logic is based on promoting any joins used in only
some of the childs of an OR clause unless the join existed before the
OR clause addition.

Note: See TracTickets for help on using tickets.
Back to Top