Django

Code

Changeset 6967

Show
Ignore:
Timestamp:
12/22/07 05:16:04 (1 year ago)
Author:
mtredinnick
Message:

queryset-refactor: Work around the fact that "where id is NULL" can return different results in different circumstances in MySQL(!!).

Files:

Legend:

Unmodified
Added
Removed
Modified
Copied
Moved
  • django/branches/queryset-refactor/django/db/models/sql/datastructures.py

    r6959 r6967  
    55 
    66class EmptyResultSet(Exception): 
     7    pass 
     8 
     9class FullResultSet(Exception): 
    710    pass 
    811 
  • django/branches/queryset-refactor/django/db/models/sql/query.py

    r6961 r6967  
    1616from django.dispatch import dispatcher 
    1717from django.db.models import signals 
    18 from django.db.models.sql.where import WhereNode, AND, OR 
     18from django.db.models.sql.where import WhereNode, EverythingNode, AND, OR 
    1919from django.db.models.sql.datastructures import Count, Date 
    2020from django.db.models.fields import FieldDoesNotExist, Field, related 
     
    312312            if not self.where: 
    313313                # Since 'self' matches everything, add an explicit "include 
    314                 # everything" (pk is not NULL) where-constraint so that 
    315                 # connections between the where clauses won't exclude valid 
    316                 # results. 
     314                # everything" where-constraint so that connections between the 
     315                # where clauses won't exclude valid results. 
    317316                alias = self.join((None, self.model._meta.db_table, None, None)) 
    318317                pk = self.model._meta.pk 
    319                 self.where.add([alias, pk.column, pk, 'isnull', False], AND) 
     318                self.where.add(EverythingNode(), AND) 
    320319        elif self.where: 
    321320            # rhs has an empty where clause. Make it match everything (see 
     
    324323            alias = self.join((None, self.model._meta.db_table, None, None)) 
    325324            pk = self.model._meta.pk 
    326             w.add([alias, pk.column, pk, 'isnull', False], AND) 
     325            w.add(EverythingNode(), AND) 
    327326        else: 
    328327            w = WhereNode() 
  • django/branches/queryset-refactor/django/db/models/sql/where.py

    r6961 r6967  
    66from django.utils import tree 
    77from django.db import connection 
    8 from datastructures import EmptyResultSet 
     8from datastructures import EmptyResultSet, FullResultSet 
    99 
    1010# Connection types 
     
    4444        empty = True 
    4545        for child in node.children: 
    46             if hasattr(child, 'as_sql'): 
    47                 sql, params = child.as_sql(qn=qn) 
    48                 format = '(%s)' 
    49             elif isinstance(child, tree.Node): 
    50                 sql, params = self.as_sql(child, qn) 
    51                 if child.negated: 
    52                     format = 'NOT (%s)' 
     46            try: 
     47                if hasattr(child, 'as_sql'): 
     48                    sql, params = child.as_sql(qn=qn) 
     49                    format = '(%s)' 
     50                elif isinstance(child, tree.Node): 
     51                    sql, params = self.as_sql(child, qn) 
     52                    if child.negated: 
     53                        format = 'NOT (%s)' 
     54                    else: 
     55                        format = '(%s)' 
    5356                else: 
    54                     format = '(%s)' 
    55             else: 
    56                 try: 
    5757                    sql, params = self.make_atom(child, qn) 
    5858                    format = '%s' 
    59                 except EmptyResultSet: 
    60                     if self.connector == AND and not node.negated: 
    61                         # We can bail out early in this particular case (only). 
    62                         raise 
    63                     elif node.negated: 
    64                         empty = False 
    65                     continue 
     59            except EmptyResultSet: 
     60                if self.connector == AND and not node.negated: 
     61                    # We can bail out early in this particular case (only). 
     62                    raise 
     63                elif node.negated: 
     64                    empty = False 
     65                continue 
     66            except FullResultSet: 
     67                if self.connector == OR: 
     68                    if node.negated: 
     69                        empty = True 
     70                        break 
     71                    # We match everything. No need for any constraints. 
     72                    return '', [] 
     73                if node.negated: 
     74                    empty = True 
     75                continue 
    6676            empty = False 
    6777            if sql: 
     
    157167                child[0] = change_map.get(val, val) 
    158168 
     169class EverythingNode(object): 
     170    """ 
     171    A node that matches everything. 
     172    """ 
     173    def as_sql(self, qn=None): 
     174        raise FullResultSet 
     175 
     176    def relabel_aliases(self, change_map, node=None): 
     177        return 
  • django/branches/queryset-refactor/tests/regressiontests/null_queries/models.py

    r6760 r6967  
    2727# Exact query with value None returns nothing ("is NULL" in sql, but every 'id' 
    2828# field has a value). 
    29 >>> Choice.objects.filter(id__exact=None) 
     29>>> Choice.objects.filter(choice__exact=None) 
    3030[] 
    3131 
    3232Excluding the previous result returns everything. 
    33 >>> Choice.objects.exclude(id=None).order_by('id') 
     33>>> Choice.objects.exclude(choice=None).order_by('id') 
    3434[<Choice: Choice: Because. in poll Q: Why? >, <Choice: Choice: Why Not? in poll Q: Why? >] 
    3535