Opened 15 months ago
Closed 15 months ago
#34776 closed Cleanup/optimization (invalid)
Issue with maintaining condition order and join promotion in add_q method
Reported by: | Songhee Han | Owned by: | nobody |
---|---|---|---|
Component: | Database layer (models, ORM) | Version: | 4.0 |
Severity: | Normal | Keywords: | |
Cc: | Triage Stage: | Unreviewed | |
Has patch: | no | Needs documentation: | no |
Needs tests: | no | Patch needs improvement: | no |
Easy pickings: | yes | UI/UX: | no |
Description
- related ticket : https://code.djangoproject.com/ticket/29125
- The
__init__
method class Q sorts sorted, while add_q method class Query does
- The issue stemmed from Python 3.5's non-deterministic dictionary ordering, which resulted in the absence of sorted kwargs. Consequently, instances of the Q object having multiple kwargs led to unpredictable outcomes in the deconstruct() method. Recognizing this problem, the incorporated changes were identified to be causing disparate outcomes between class Q and class Query.
django.db.models.query_utils.py
class Q(tree.Node): """ Encapsulate filters as objects that can then be combined logically (using `&` and `|`). """ # Connection types AND = "AND" OR = "OR" XOR = "XOR" default = AND conditional = True def __init__(self, *args, _connector=None, _negated=False, **kwargs): super().__init__( children=[*args, *sorted(kwargs.items())], connector=_connector, negated=_negated, )
django.db.models.sql.query.py
class Query(BaseExpression): ... def add_q(self, q_object): """ A preprocessor for the internal _add_q(). Responsible for doing final join promotion. """ # For join promotion this case is doing an AND for the added q_object # and existing conditions. So, any existing inner join forces the join # type to remain inner. Existing outer joins can however be demoted. # (Consider case where rel_a is LOUTER and rel_a__col=1 is added - if # rel_a doesn't produce any rows, then the whole condition must fail. # So, demotion is OK. existing_inner = { a for a in self.alias_map if self.alias_map[a].join_type == INNER } clause, _ = self._add_q(q_object, self.used_aliases) if clause: self.where.add(clause, AND) self.demote_joins(existing_inner)
Ensuring that conditions are controlled and combined in a consistent order is crucial for maintaining the coherence of join promotion and ensuring the accuracy of the overall query behavior. This is precisely why handling the order of conditions appropriately within the add_q method is pivotal for avoiding unintended changes to join types and guaranteeing accurate query results.
Note:
See TracTickets
for help on using tickets.
Hello Songhee Han,
I'm having a hard time understanding this ticket report. Could you please explain in more detail what's the concrete issue you are experiencing? A django sample project that exercises the problem would be ideal.
Also, please note that there is no version of Django supporting Python 3.5, and that Python 3.5 has reached end-of-life 3 years ago.
I'm closing the ticket due to the lack of details. You could also seek further help in the user support channels from this link.
Regards, Natalia.