Code

Ticket #3283: empty_in_clause.patch

File empty_in_clause.patch, 3.2 KB (added by medhat, 7 years ago)

another solution for the empty in-clause using empty querysets

  • query.py

     
    2525# Larger values are slightly faster at the expense of more storage space. 
    2626GET_ITERATOR_CHUNK_SIZE = 100 
    2727 
     28class EmptyInClause(Exception): 
     29    pass 
     30 
    2831#################### 
    2932# HELPER FUNCTIONS # 
    3033#################### 
     
    168171        extra_select = self._select.items() 
    169172 
    170173        cursor = connection.cursor() 
    171         select, sql, params = self._get_sql_clause() 
     174 
     175        try: 
     176            select, sql, params = self._get_sql_clause() 
     177        except EmptyInClause: 
     178            raise StopIteration 
     179 
    172180        cursor.execute("SELECT " + (self._distinct and "DISTINCT " or "") + ",".join(select) + sql, params) 
    173181        fill_cache = self._select_related 
    174182        index_end = len(self.model._meta.fields) 
     
    192200        counter._offset = None 
    193201        counter._limit = None 
    194202        counter._select_related = False 
    195         select, sql, params = counter._get_sql_clause() 
     203 
     204        try: 
     205            select, sql, params = counter._get_sql_clause() 
     206        except EmptyInClause: 
     207            return 0 
     208 
    196209        cursor = connection.cursor() 
    197210        if self._distinct: 
    198211            id_col = "%s.%s" % (backend.quote_name(self.model._meta.db_table), 
     
    523536            field_names = [f.attname for f in self.model._meta.fields] 
    524537 
    525538        cursor = connection.cursor() 
    526         select, sql, params = self._get_sql_clause() 
     539 
     540        try: 
     541            select, sql, params = self._get_sql_clause() 
     542        except EmptyInClause: 
     543            raise StopIteration 
     544 
    527545        select = ['%s.%s' % (backend.quote_name(self.model._meta.db_table), backend.quote_name(c)) for c in columns] 
    528546        cursor.execute("SELECT " + (self._distinct and "DISTINCT " or "") + ",".join(select) + sql, params) 
    529547        while 1: 
     
    545563        if self._field.null: 
    546564            self._where.append('%s.%s IS NOT NULL' % \ 
    547565                (backend.quote_name(self.model._meta.db_table), backend.quote_name(self._field.column))) 
    548         select, sql, params = self._get_sql_clause() 
     566 
     567        try: 
     568            select, sql, params = self._get_sql_clause() 
     569        except EmptyInClause: 
     570            raise StopIteration 
     571 
    549572        sql = 'SELECT %s %s GROUP BY 1 ORDER BY 1 %s' % \ 
    550573            (backend.get_date_trunc_sql(self._kind, '%s.%s' % (backend.quote_name(self.model._meta.db_table), 
    551574            backend.quote_name(self._field.column))), sql, self._order) 
     
    645687        if in_string: 
    646688            return '%s%s IN (%s)' % (table_prefix, field_name, in_string) 
    647689        else: 
    648             # Most backends do not accept an empty string inside the IN 
    649             # expression, i.e. cannot do "WHERE ... IN ()".  Since there are 
    650             # also some backends that do not accept "WHERE false", we instead 
    651             # use an expression that always evaluates to False. 
    652             return '0=1' 
     690            raise EmptyInClause 
    653691    elif lookup_type == 'range': 
    654692        return '%s%s BETWEEN %%s AND %%s' % (table_prefix, field_name) 
    655693    elif lookup_type in ('year', 'month', 'day'):