Opened 4 years ago

Closed 4 years ago

#21956 closed Bug (wontfix)

Inconsistent behaviour of Q objects

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


Suppose we have a contact model with following definition:

class Contact(models.Model):
    name = models.CharField()
    company_uid = models.IntegerField(null=True, blank=True)

Consider following two queries:

Contact.objects.filter(~(Q(name='ABC') | Q(company_uid=5)))
Contact.objects.filter(~Q(name='ABC') & ~Q(company_uid=5))

These queries are exactly the same, right? Just used DeMorgan's law i.e "not (A or B)" is the same as "(not A) and (not B)". But the generated SQL of these queries says something else:

SELECT "profiles_contact"."id", "profiles_contact"."name", "profiles_contact"."company_uid" FROM "profiles_contact" WHERE NOT (("profiles_contact"."name" = ABC OR "profiles_contact"."company_uid" = 5 ))

SELECT "profiles_contact"."id", "profiles_contact"."name", "profiles_contact"."company_uid" FROM "profiles_contact" WHERE (NOT ("profiles_contact"."name" = ABC ) AND NOT (("profiles_contact"."company_uid" = 5 AND "profiles_contact"."company_uid" IS NOT NULL)))

(The desired query is the one with IS NOT NULL condition)

This issue only exists till version 1.5, it has been fixed in Django-1.6. There is already a closed bug ( which was similar to this one. The bug was closed stating that the issue has been fixed in Django-1.6 and changes required to back-patch the fixes to 1.5 are just too big. But I believe this issue is more severe than the issue stated the that bug, as it is a more general case and should be back-patched to 1.5 and older version too.

Change History (1)

comment:1 Changed 4 years ago by Shai Berger

Resolution: wontfix
Status: newclosed

Per the documented release process:

Committers may choose to backport bugfixes at their own discretion, provided they do not introduce backwards incompatibilities.

This is a bugfix, not a security fix; a committer has considered backporting it, and decided against. The route to getting it backported nonetheless can go through two directions:

  • Go to the developers list and argue your case there, and/or
  • Provide a patch against 1.5 yourself -- but be warned, without agreement on the list, there's a high chance of it getting rejected.
Note: See TracTickets for help on using tickets.
Back to Top