Ticket #3283: empty_in_clause.patch

File empty_in_clause.patch, 3.2 KB (added by medhat, 8 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'):
Back to Top