Ticket #3592: fixed_Q_joins.patch

File fixed_Q_joins.patch, 2.9 KB (added by anonymous, 17 years ago)
  • db/models/query.py

     
    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):
Back to Top