Ticket #5763: #ne_notin.diff

File #ne_notin.diff, 10.7 KB (added by German M. Bravo, 12 years ago)

This adds ne and notin filters

  • db/backends/mysql/base.py

    diff -ruN django.orig/db/backends/mysql/base.py django/db/backends/mysql/base.py
    old new  
    258258class DatabaseWrapper(BaseDatabaseWrapper):
    259259    vendor = 'mysql'
    260260    operators = {
     261        'ne': '<> %s',
    261262        'exact': '= %s',
    262263        'iexact': 'LIKE %s',
    263264        'contains': 'LIKE BINARY %s',
  • db/backends/oracle/base.py

    diff -ruN django.orig/db/backends/oracle/base.py django/db/backends/oracle/base.py
    old new  
    384384    operators = _UninitializedOperatorsDescriptor()
    385385
    386386    _standard_operators = {
     387        'ne': '<> %s',
    387388        'exact': '= %s',
    388389        'iexact': '= UPPER(%s)',
    389390        'contains': "LIKE TRANSLATE(%s USING NCHAR_CS) ESCAPE TRANSLATE('\\' USING NCHAR_CS)",
  • db/backends/postgresql/base.py

    diff -ruN django.orig/db/backends/postgresql/base.py django/db/backends/postgresql/base.py
    old new  
    8787class DatabaseWrapper(BaseDatabaseWrapper):
    8888    vendor = 'postgresql'
    8989    operators = {
     90        'ne': '<> %s',
    9091        'exact': '= %s',
    9192        'iexact': '= UPPER(%s)',
    9293        'contains': 'LIKE %s',
  • db/backends/postgresql_psycopg2/base.py

    diff -ruN django.orig/db/backends/postgresql_psycopg2/base.py django/db/backends/postgresql_psycopg2/base.py
    old new  
    8484class DatabaseWrapper(BaseDatabaseWrapper):
    8585    vendor = 'postgresql'
    8686    operators = {
     87        'ne': '<> %s',
    8788        'exact': '= %s',
    8889        'iexact': '= UPPER(%s)',
    8990        'contains': 'LIKE %s',
  • db/backends/sqlite3/base.py

    diff -ruN django.orig/db/backends/sqlite3/base.py django/db/backends/sqlite3/base.py
    old new  
    167167    # being escaped has a percent or underscore in it.
    168168    # See http://www.sqlite.org/lang_expr.html for an explanation.
    169169    operators = {
     170        'ne': '<> %s',
    170171        'exact': '= %s',
    171172        'iexact': "LIKE %s ESCAPE '\\'",
    172173        'contains': "LIKE %s ESCAPE '\\'",
  • db/models/fields/__init__.py

    diff -ruN django.orig/db/models/fields/__init__.py django/db/models/fields/__init__.py
    old new  
    288288                'endswith', 'iendswith', 'isnull'
    289289            ):
    290290            return value
    291         elif lookup_type in ('exact', 'gt', 'gte', 'lt', 'lte'):
     291        elif lookup_type in ('ne', 'exact', 'gt', 'gte', 'lt', 'lte'):
    292292            return self.get_prep_value(value)
    293         elif lookup_type in ('range', 'in'):
     293        elif lookup_type in ('range', 'in', 'notin'):
    294294            return [self.get_prep_value(v) for v in value]
    295295        elif lookup_type == 'year':
    296296            try:
     
    319319
    320320        if lookup_type in ('regex', 'iregex', 'month', 'day', 'week_day', 'search'):
    321321            return [value]
    322         elif lookup_type in ('exact', 'gt', 'gte', 'lt', 'lte'):
     322        elif lookup_type in ('ne', 'exact', 'gt', 'gte', 'lt', 'lte'):
    323323            return [self.get_db_prep_value(value, connection=connection, prepared=prepared)]
    324         elif lookup_type in ('range', 'in'):
     324        elif lookup_type in ('range', 'in', 'notin'):
    325325            return [self.get_db_prep_value(v, connection=connection, prepared=prepared) for v in value]
    326326        elif lookup_type in ('contains', 'icontains'):
    327327            return ["%%%s%%" % connection.ops.prep_for_like_query(value)]
  • db/models/fields/related.py

    diff -ruN django.orig/db/models/fields/related.py django/db/models/fields/related.py
    old new  
    132132        # get_(next/prev)_by_date work; other lookups are not allowed since that
    133133        # gets messy pretty quick. This is a good candidate for some refactoring
    134134        # in the future.
    135         if lookup_type in ['exact', 'gt', 'lt', 'gte', 'lte']:
     135        if lookup_type in ['ne', 'exact', 'gt', 'lt', 'gte', 'lte']:
    136136            return self._pk_trace(value, 'get_prep_lookup', lookup_type)
    137         if lookup_type in ('range', 'in'):
     137        if lookup_type in ('range', 'in', 'notin'):
    138138            return [self._pk_trace(v, 'get_prep_lookup', lookup_type) for v in value]
    139139        elif lookup_type == 'isnull':
    140140            return []
     
    160160        # get_(next/prev)_by_date work; other lookups are not allowed since that
    161161        # gets messy pretty quick. This is a good candidate for some refactoring
    162162        # in the future.
    163         if lookup_type in ['exact', 'gt', 'lt', 'gte', 'lte']:
     163        if lookup_type in ['ne', 'exact', 'gt', 'lt', 'gte', 'lte']:
    164164            return [self._pk_trace(value, 'get_db_prep_lookup', lookup_type,
    165165                            connection=connection, prepared=prepared)]
    166         if lookup_type in ('range', 'in'):
     166        if lookup_type in ('range', 'in', 'notin'):
    167167            return [self._pk_trace(v, 'get_db_prep_lookup', lookup_type,
    168168                            connection=connection, prepared=prepared)
    169169                    for v in value]
     
    204204            else:
    205205                field = field.rel.to._meta.pk
    206206
    207         if lookup_type in ('range', 'in'):
     207        if lookup_type in ('range', 'in', 'notin'):
    208208            v = [v]
    209209        v = getattr(field, prep_func)(lookup_type, v, **kwargs)
    210210        if isinstance(v, list):
  • db/models/sql/constants.py

    diff -ruN django.orig/db/models/sql/constants.py django/db/models/sql/constants.py
    old new  
    22
    33# Valid query types (a dictionary is used for speedy lookups).
    44QUERY_TERMS = dict([(x, None) for x in (
    5     'exact', 'iexact', 'contains', 'icontains', 'gt', 'gte', 'lt', 'lte', 'in',
    6     'startswith', 'istartswith', 'endswith', 'iendswith', 'range', 'year',
     5    'ne', 'exact', 'iexact', 'contains', 'icontains', 'gt', 'gte', 'lt', 'lte', 'in',
     6    'notin', 'startswith', 'istartswith', 'endswith', 'iendswith', 'range', 'year',
    77    'month', 'day', 'week_day', 'isnull', 'search', 'regex', 'iregex',
    88    )])
    99
  • db/models/sql/query.py

    diff -ruN django.orig/db/models/sql/query.py django/db/models/sql/query.py
    old new  
    10391039        # Interpret '__exact=None' as the sql 'is NULL'; otherwise, reject all
    10401040        # uses of None as a query value.
    10411041        if value is None:
    1042             if lookup_type != 'exact':
     1042            if lookup_type not in ('exact', 'ne'):
    10431043                raise ValueError("Cannot use None as a query value")
     1044            value = lookup_type == 'exact'
    10441045            lookup_type = 'isnull'
    1045             value = True
    10461046        elif callable(value):
    10471047            value = value()
    10481048        elif hasattr(value, 'evaluate'):
     
    11431143                            entry.negate()
    11441144                            self.where.add(entry, AND)
    11451145                            break
    1146                 if not (lookup_type == 'in'
     1146                if not (lookup_type in ('in', 'notin')
    11471147                            and not hasattr(value, 'as_sql')
    11481148                            and not hasattr(value, '_as_sql')
    11491149                            and not value) and field.null:
     
    11511151                    # exclude the "foo__in=[]" case from this handling, because
    11521152                    # it's short-circuited in the Where class.
    11531153                    # We also need to handle the case where a subquery is provided
    1154                     self.where.add((Constraint(alias, col, None), 'isnull', False), AND)
     1154                    self.where.add((Constraint(alias, col, None), 'isnull', lookup_type == 'notin'), AND)
    11551155
    11561156        if can_reuse is not None:
    11571157            can_reuse.update(join_list)
  • db/models/sql/where.py

    diff -ruN django.orig/db/models/sql/where.py django/db/models/sql/where.py
    old new  
    163163        else:
    164164            extra = ''
    165165
    166         if (len(params) == 1 and params[0] == '' and lookup_type == 'exact'
     166        if (len(params) == 1 and params[0] == '' and lookup_type in ('exact', 'ne')
    167167            and connection.features.interprets_empty_strings_as_nulls):
     168            value_annot = lookup_type == 'exact'
    168169            lookup_type = 'isnull'
    169             value_annot = True
    170170
    171171        if lookup_type in connection.operators:
    172172            format = "%s %%s %%s" % (connection.ops.lookup_cast(lookup_type),)
     
    174174                              connection.operators[lookup_type] % cast_sql,
    175175                              extra), params)
    176176
    177         if lookup_type == 'in':
     177        if lookup_type in ('in', 'notin'):
    178178            if not value_annot:
    179179                raise EmptyResultSet
     180            if lookup_type == 'in':
     181                op = 'IN'
     182            else:
     183                op = 'NOT IN'
    180184            if extra:
    181                 return ('%s IN %s' % (field_sql, extra), params)
     185                return ('%s %s %s' % (field_sql, op, extra), params)
    182186            max_in_list_size = connection.ops.max_in_list_size()
    183187            if max_in_list_size and len(params) > max_in_list_size:
    184188                # Break up the params list into an OR of manageable chunks.
     
    186190                for offset in xrange(0, len(params), max_in_list_size):
    187191                    if offset > 0:
    188192                        in_clause_elements.append(' OR ')
    189                     in_clause_elements.append('%s IN (' % field_sql)
     193                    in_clause_elements.append('%s %s (' % (field_sql, op))
    190194                    group_size = min(len(params) - offset, max_in_list_size)
    191195                    param_group = ', '.join(repeat('%s', group_size))
    192196                    in_clause_elements.append(param_group)
     
    194198                in_clause_elements.append(')')
    195199                return ''.join(in_clause_elements), params
    196200            else:
    197                 return ('%s IN (%s)' % (field_sql,
     201                return ('%s %s (%s)' % (field_sql, op,
    198202                                        ', '.join(repeat('%s', len(params)))),
    199203                        params)
    200204        elif lookup_type in ('range', 'year'):
Back to Top