Django

Code

Ticket #3592: fixed_Q_joins.patch

File fixed_Q_joins.patch, 2.9 kB (added by anonymous, 1 year ago)
  • db/models/query.py

    old new  
    630630 
    631631class QOperator(object): 
    632632    "Base class for QAnd and QOr" 
     633    underneath_an_or = False # used to track ORs 
     634    checked_or       = False 
     635     
     636    def search_for_or(self): 
     637        " Returns true if an or exists beneath this Q operator. " 
     638        if type(self) == QOr: 
     639            return True 
     640 
     641        for val in self.args: 
     642            if val.search_for_or(): 
     643                return True 
     644 
     645        return False # there was no OR below this. 
     646 
     647    def set_or_found(self, or_value): 
     648        if self.checked_or: 
     649            return 
     650 
     651        self.underneath_an_or = or_value 
     652        self.checked_or       = True 
     653 
     654        for val in self.args: 
     655            val.set_or_found(or_value) # set for all the children 
     656         
    633657    def __init__(self, *args): 
    634658        self.args = args 
    635659 
    636660    def get_sql(self, opts): 
     661 
     662        if not self.checked_or: 
     663            found_an_or = self.underneath_an_or() 
     664            self.set_or_found(found_an_or) 
     665 
     666        # now that we've finished building the query 
     667        self.checked_or = False 
     668 
    637669        joins, where, params = SortedDict(), [], [] 
    638670        for val in self.args: 
    639671            try: 
     
    678710 
    679711class Q(object): 
    680712    "Encapsulates queries as objects that can be combined logically." 
     713    underneath_an_or = False 
     714    checked_or       = False 
     715    outer_join       = 'LEFT OUTER JOIN' 
     716    inner_join       = 'INNER JOIN' 
     717     
    681718    def __init__(self, **kwargs): 
    682719        self.kwargs = kwargs 
    683720 
     
    687724    def __or__(self, other): 
    688725        return QOr(self, other) 
    689726 
     727    def search_for_or(self): 
     728        ' Returns false, since there are no OR Qs below. ' 
     729        return False 
     730 
     731    def set_or_found(self, or_found): 
     732        """ Set whether or not we have an OR above us. """ 
     733        if not self.checked_or: 
     734            self.underneath_an_or = or_found 
     735            self.checked_or       = True  # we checked for an OR 
     736 
    690737    def get_sql(self, opts): 
    691         return parse_lookup(self.kwargs.items(), opts) 
     738        # we will check to see if it's an OR, and change the join 
     739        # based upon that 
    692740 
     741        if self.underneath_an_or: 
     742            join_text = self.outer_join 
     743        else: 
     744            join_text = self.inner_join 
     745 
     746        joins, where, params = parse_lookup(self.kwargs.items(), opts) 
     747 
     748        joins2 = {} 
     749        for item, key in joins.items(): 
     750            # now we will fix the joins dictionary with 
     751            # the new type of join 
     752            joins2[item] = (key[0], join_text, key[2]) 
     753 
     754        # now that we've done creating the query, 
     755        # it's best that we let ourselves search again 
     756        self.checked_or = False 
     757 
     758        return joins2, where, params 
     759 
    693760class QNot(Q): 
    694761    "Encapsulates NOT (...) queries as objects" 
    695762    def __init__(self, q):