Opened 21 months ago

Last modified 7 months ago

#29865 new New feature

Add XOR for use in Q Queries

Reported by: Griffith Rees Owned by: nobody
Component: Database layer (models, ORM) Version: 2.1
Severity: Normal Keywords: xor
Cc: felixxm Triage Stage: Someday/Maybe
Has patch: no Needs documentation: no
Needs tests: no Patch needs improvement: no
Easy pickings: no UI/UX: no

Description

XOR seems to be available in Postgresql, MySQL, SequelServer and Oracle but NOT sqlite. Two stackoverflow questions cover this sort of thing: https://stackoverflow.com/questions/50408142/django-models-xor-at-the-model-level and https://stackoverflow.com/questions/14711203/perform-a-logical-exclusive-or-on-a-django-q-object.

I propose adding XOR to work with Q queries like the answer to the second question above. This will be my first time making a major contribution so we'll see how this goes (apologies in advance if this is annoying!).

Change History (6)

comment:1 Changed 21 months ago by Tim Graham

Triage Stage: UnreviewedSomeday/Maybe

It's probably best to write to the DevelopersMailingList to see if there's consensus about this (although having a working patch may help evaluate the idea). I wonder if it's possible to emulate XOR on SQLite similar to what we do for some other database functions.

comment:2 Changed 21 months ago by felixxm

XOR is not officially supported on Oracle (see doc) you pointed to the old MySQL documentation.

comment:3 Changed 21 months ago by felixxm

Cc: felixxm added

comment:4 Changed 21 months ago by Marten Kenbeek

To be clear, you're talking about logical XOR, and not bitwise XOR?

You linked to PostgreSQL's bitwise XOR operator, #. At the moment it does not have a logical XOR operator. The only logical operators it supports are AND, OR and NOT.

comment:5 in reply to:  4 Changed 12 months ago by Nick Pope

Replying to Marten Kenbeek:

To be clear, you're talking about logical XOR, and not bitwise XOR?

As you've highlighted, this should be for logical XOR and not bitwise XOR. So this is only supported for MariaDB and MySQL which have XOR.

This could be implemented by defining Q.XOR and Q.__xor__() and then propagating that around the place.
It could be possible to support this for other backends by specifying connection.features.supports_logical_xor = False and then writing out the query differently.

For Q(a=1) ^ Q(b=2), the supporting backends would output (a = 1 XOR a = 2), while the others could output ((a = 1 OR b = 2) AND NOT (a = 1 AND b = 2)).

comment:6 Changed 7 months ago by jishansingh

XOR can be implemented by

def __xor__(self,other):
        return self.__or__(other).__and__(self.__invert__().__or__(other.__invert__()))

it works for sqlite (possibly for others)
wouldn't it solves the problem

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