Ticket #5763: django_5763_plus_contains.diff

File django_5763_plus_contains.diff, 10.4 KB (added by PhiR_42, 10 years ago)

patch updated for 1.5, plus handles negative contains and icontains

  • django/db/backends/mysql/base.py

    diff -ur ../orig/Django-1.5.5/django/db/backends/mysql/base.py django/db/backends/mysql/base.py
    old new  
    339339class DatabaseWrapper(BaseDatabaseWrapper):
    340340    vendor = 'mysql'
    341341    operators = {
     342        'ne': '<> %s',
    342343        'exact': '= %s',
    343344        'iexact': 'LIKE %s',
    344345        'contains': 'LIKE BINARY %s',
    345346        'icontains': 'LIKE %s',
     347        'ncontains': 'NOT LIKE BINARY %s',
     348        'nicontains': 'NOT LIKE %s',
    346349        'regex': 'REGEXP BINARY %s',
    347350        'iregex': 'REGEXP %s',
    348351        'gt': '> %s',
  • django/db/backends/oracle/base.py

    diff -ur ../orig/Django-1.5.5/django/db/backends/oracle/base.py django/db/backends/oracle/base.py
    old new  
    431431    operators = _UninitializedOperatorsDescriptor()
    432432
    433433    _standard_operators = {
     434        'ne': '<> %s',
    434435        'exact': '= %s',
    435436        'iexact': '= UPPER(%s)',
    436437        'contains': "LIKE TRANSLATE(%s USING NCHAR_CS) ESCAPE TRANSLATE('\\' USING NCHAR_CS)",
  • django/db/backends/postgresql_psycopg2/base.py

    diff -ur ../orig/Django-1.5.5/django/db/backends/postgresql_psycopg2/base.py django/db/backends/postgresql_psycopg2/base.py
    old new  
    9090class DatabaseWrapper(BaseDatabaseWrapper):
    9191    vendor = 'postgresql'
    9292    operators = {
     93        'ne': '<> %s',
    9394        'exact': '= %s',
    9495        'iexact': '= UPPER(%s)',
    9596        'contains': 'LIKE %s',
  • django/db/backends/sqlite3/base.py

    diff -ur ../orig/Django-1.5.5/django/db/backends/sqlite3/base.py django/db/backends/sqlite3/base.py
    old new  
    240240    # being escaped has a percent or underscore in it.
    241241    # See http://www.sqlite.org/lang_expr.html for an explanation.
    242242    operators = {
     243        'ne': '<> %s',
    243244        'exact': '= %s',
    244245        'iexact': "LIKE %s ESCAPE '\\'",
    245246        'contains': "LIKE %s ESCAPE '\\'",
    246247        'icontains': "LIKE %s ESCAPE '\\'",
     248        'ncontains': "NOT LIKE %s ESCAPE '\\'",
     249        'nicontains': "NOT LIKE %s ESCAPE '\\'",
    247250        'regex': 'REGEXP %s',
    248251        'iregex': "REGEXP '(?i)' || %s",
    249252        'gt': '> %s',
  • django/db/models/fields/__init__.py

    diff -ur ../orig/Django-1.5.5/django/db/models/fields/__init__.py django/db/models/fields/__init__.py
    old new  
    315315        if lookup_type in (
    316316                'regex', 'iregex', 'month', 'day', 'week_day', 'search',
    317317                'contains', 'icontains', 'iexact', 'startswith', 'istartswith',
    318                 'endswith', 'iendswith', 'isnull'
     318                'endswith', 'iendswith', 'isnull',
     319                'ncontains', 'nicontains'
    319320            ):
    320321            return value
    321         elif lookup_type in ('exact', 'gt', 'gte', 'lt', 'lte'):
     322        elif lookup_type in ('exact', 'ne', 'gt', 'gte', 'lt', 'lte'):
    322323            return self.get_prep_value(value)
    323         elif lookup_type in ('range', 'in'):
     324        elif lookup_type in ('range', 'in', 'notin'):
    324325            return [self.get_prep_value(v) for v in value]
    325326        elif lookup_type == 'year':
    326327            try:
     
    354355        if lookup_type in ('regex', 'iregex', 'month', 'day', 'week_day',
    355356                           'search'):
    356357            return [value]
    357         elif lookup_type in ('exact', 'gt', 'gte', 'lt', 'lte'):
     358        elif lookup_type in ('exact', 'ne', 'gt', 'gte', 'lt', 'lte'):
    358359            return [self.get_db_prep_value(value, connection=connection,
    359360                                           prepared=prepared)]
    360         elif lookup_type in ('range', 'in'):
     361        elif lookup_type in ('range', 'in', 'notin'):
    361362            return [self.get_db_prep_value(v, connection=connection,
    362363                                           prepared=prepared) for v in value]
    363         elif lookup_type in ('contains', 'icontains'):
     364        elif lookup_type in ('contains', 'icontains', 'ncontains', 'nicontains'):
    364365            return ["%%%s%%" % connection.ops.prep_for_like_query(value)]
    365366        elif lookup_type == 'iexact':
    366367            return [connection.ops.prep_for_iexact_query(value)]
  • django/db/models/fields/related.py

    diff -ur ../orig/Django-1.5.5/django/db/models/fields/related.py django/db/models/fields/related.py
    old new  
    139139        # get_(next/prev)_by_date work; other lookups are not allowed since that
    140140        # gets messy pretty quick. This is a good candidate for some refactoring
    141141        # in the future.
    142         if lookup_type in ['exact', 'gt', 'lt', 'gte', 'lte']:
     142        if lookup_type in ['exact', 'ne', 'gt', 'lt', 'gte', 'lte']:
    143143            return self._pk_trace(value, 'get_prep_lookup', lookup_type)
    144         if lookup_type in ('range', 'in'):
     144        if lookup_type in ('range', 'in', 'notin'):
    145145            return [self._pk_trace(v, 'get_prep_lookup', lookup_type) for v in value]
    146146        elif lookup_type == 'isnull':
    147147            return []
     
    167167        # get_(next/prev)_by_date work; other lookups are not allowed since that
    168168        # gets messy pretty quick. This is a good candidate for some refactoring
    169169        # in the future.
    170         if lookup_type in ['exact', 'gt', 'lt', 'gte', 'lte']:
     170        if lookup_type in ['exact', 'ne', 'gt', 'lt', 'gte', 'lte']:
    171171            return [self._pk_trace(value, 'get_db_prep_lookup', lookup_type,
    172172                            connection=connection, prepared=prepared)]
    173         if lookup_type in ('range', 'in'):
     173        if lookup_type in ('range', 'in', 'notin'):
    174174            return [self._pk_trace(v, 'get_db_prep_lookup', lookup_type,
    175175                            connection=connection, prepared=prepared)
    176176                    for v in value]
     
    211211            else:
    212212                field = field.rel.to._meta.pk
    213213
    214         if lookup_type in ('range', 'in'):
     214        if lookup_type in ('range', 'in', 'notin'):
    215215            v = [v]
    216216        v = getattr(field, prep_func)(lookup_type, v, **kwargs)
    217217        if isinstance(v, list):
  • django/db/models/sql/constants.py

    diff -ur ../orig/Django-1.5.5/django/db/models/sql/constants.py django/db/models/sql/constants.py
    old new  
    1212    'exact', 'iexact', 'contains', 'icontains', 'gt', 'gte', 'lt', 'lte', 'in',
    1313    'startswith', 'istartswith', 'endswith', 'iendswith', 'range', 'year',
    1414    'month', 'day', 'week_day', 'isnull', 'search', 'regex', 'iregex',
     15    'ne', 'notin', 'ncontains', 'nicontains',
    1516])
    1617
    1718# Size of each "chunk" for get_iterator calls.
  • django/db/models/sql/query.py

    diff -ur ../orig/Django-1.5.5/django/db/models/sql/query.py django/db/models/sql/query.py
    old new  
    11011101        # Interpret '__exact=None' as the sql 'is NULL'; otherwise, reject all
    11021102        # uses of None as a query value.
    11031103        if value is None:
    1104             if lookup_type != 'exact':
     1104            if lookup_type not in ('exact', 'ne'):
    11051105                raise ValueError("Cannot use None as a query value")
     1106            value = lookup_type == 'exact'
    11061107            lookup_type = 'isnull'
    1107             value = True
    11081108        elif callable(value):
    11091109            value = value()
    11101110        elif isinstance(value, ExpressionNode):
  • django/db/models/sql/where.py

    diff -ur ../orig/Django-1.5.5/django/db/models/sql/where.py django/db/models/sql/where.py
    old new  
    185185        else:
    186186            extra = ''
    187187
    188         if (len(params) == 1 and params[0] == '' and lookup_type == 'exact'
     188        if (len(params) == 1 and params[0] == '' and lookup_type in ('exact', 'ne')
    189189            and connection.features.interprets_empty_strings_as_nulls):
     190            value_annotation = lookup_type == 'exact'
    190191            lookup_type = 'isnull'
    191             value_annotation = True
    192192
    193193        if lookup_type in connection.operators:
    194194            format = "%s %%s %%s" % (connection.ops.lookup_cast(lookup_type),)
     
    196196                              connection.operators[lookup_type] % cast_sql,
    197197                              extra), params)
    198198
    199         if lookup_type == 'in':
     199        if lookup_type in ('in', 'notin'):
    200200            if not value_annotation:
    201201                raise EmptyResultSet
     202            if lookup_type == 'in':
     203                op = 'IN'
     204            else:
     205                op = 'NOT IN'
    202206            if extra:
    203                 return ('%s IN %s' % (field_sql, extra), params)
     207                return ('%s %s %s' % (field_sql, op, extra), params)
    204208            max_in_list_size = connection.ops.max_in_list_size()
    205209            if max_in_list_size and len(params) > max_in_list_size:
    206210                # Break up the params list into an OR of manageable chunks.
     
    208212                for offset in xrange(0, len(params), max_in_list_size):
    209213                    if offset > 0:
    210214                        in_clause_elements.append(' OR ')
    211                     in_clause_elements.append('%s IN (' % field_sql)
     215                    in_clause_elements.append('%s %s (' % (field_sql, op))
    212216                    group_size = min(len(params) - offset, max_in_list_size)
    213217                    param_group = ', '.join(repeat('%s', group_size))
    214218                    in_clause_elements.append(param_group)
     
    216220                in_clause_elements.append(')')
    217221                return ''.join(in_clause_elements), params
    218222            else:
    219                 return ('%s IN (%s)' % (field_sql,
     223                return ('%s %s (%s)' % (field_sql, op,
    220224                                        ', '.join(repeat('%s', len(params)))),
    221225                        params)
    222226        elif lookup_type in ('range', 'year'):
Back to Top