diff -ur ../orig/Django-1.5.5/django/db/backends/mysql/base.py django/db/backends/mysql/base.py
old
|
new
|
|
339 | 339 | class DatabaseWrapper(BaseDatabaseWrapper): |
340 | 340 | vendor = 'mysql' |
341 | 341 | operators = { |
| 342 | 'ne': '<> %s', |
342 | 343 | 'exact': '= %s', |
343 | 344 | 'iexact': 'LIKE %s', |
344 | 345 | 'contains': 'LIKE BINARY %s', |
345 | 346 | 'icontains': 'LIKE %s', |
| 347 | 'ncontains': 'NOT LIKE BINARY %s', |
| 348 | 'nicontains': 'NOT LIKE %s', |
346 | 349 | 'regex': 'REGEXP BINARY %s', |
347 | 350 | 'iregex': 'REGEXP %s', |
348 | 351 | 'gt': '> %s', |
diff -ur ../orig/Django-1.5.5/django/db/backends/oracle/base.py django/db/backends/oracle/base.py
old
|
new
|
|
431 | 431 | operators = _UninitializedOperatorsDescriptor() |
432 | 432 | |
433 | 433 | _standard_operators = { |
| 434 | 'ne': '<> %s', |
434 | 435 | 'exact': '= %s', |
435 | 436 | 'iexact': '= UPPER(%s)', |
436 | 437 | 'contains': "LIKE TRANSLATE(%s USING NCHAR_CS) ESCAPE TRANSLATE('\\' USING NCHAR_CS)", |
diff -ur ../orig/Django-1.5.5/django/db/backends/postgresql_psycopg2/base.py django/db/backends/postgresql_psycopg2/base.py
old
|
new
|
|
90 | 90 | class DatabaseWrapper(BaseDatabaseWrapper): |
91 | 91 | vendor = 'postgresql' |
92 | 92 | operators = { |
| 93 | 'ne': '<> %s', |
93 | 94 | 'exact': '= %s', |
94 | 95 | 'iexact': '= UPPER(%s)', |
95 | 96 | 'contains': 'LIKE %s', |
diff -ur ../orig/Django-1.5.5/django/db/backends/sqlite3/base.py django/db/backends/sqlite3/base.py
old
|
new
|
|
240 | 240 | # being escaped has a percent or underscore in it. |
241 | 241 | # See http://www.sqlite.org/lang_expr.html for an explanation. |
242 | 242 | operators = { |
| 243 | 'ne': '<> %s', |
243 | 244 | 'exact': '= %s', |
244 | 245 | 'iexact': "LIKE %s ESCAPE '\\'", |
245 | 246 | 'contains': "LIKE %s ESCAPE '\\'", |
246 | 247 | 'icontains': "LIKE %s ESCAPE '\\'", |
| 248 | 'ncontains': "NOT LIKE %s ESCAPE '\\'", |
| 249 | 'nicontains': "NOT LIKE %s ESCAPE '\\'", |
247 | 250 | 'regex': 'REGEXP %s', |
248 | 251 | 'iregex': "REGEXP '(?i)' || %s", |
249 | 252 | 'gt': '> %s', |
diff -ur ../orig/Django-1.5.5/django/db/models/fields/__init__.py django/db/models/fields/__init__.py
old
|
new
|
|
315 | 315 | if lookup_type in ( |
316 | 316 | 'regex', 'iregex', 'month', 'day', 'week_day', 'search', |
317 | 317 | 'contains', 'icontains', 'iexact', 'startswith', 'istartswith', |
318 | | 'endswith', 'iendswith', 'isnull' |
| 318 | 'endswith', 'iendswith', 'isnull', |
| 319 | 'ncontains', 'nicontains' |
319 | 320 | ): |
320 | 321 | return value |
321 | | elif lookup_type in ('exact', 'gt', 'gte', 'lt', 'lte'): |
| 322 | elif lookup_type in ('exact', 'ne', 'gt', 'gte', 'lt', 'lte'): |
322 | 323 | return self.get_prep_value(value) |
323 | | elif lookup_type in ('range', 'in'): |
| 324 | elif lookup_type in ('range', 'in', 'notin'): |
324 | 325 | return [self.get_prep_value(v) for v in value] |
325 | 326 | elif lookup_type == 'year': |
326 | 327 | try: |
… |
… |
|
354 | 355 | if lookup_type in ('regex', 'iregex', 'month', 'day', 'week_day', |
355 | 356 | 'search'): |
356 | 357 | return [value] |
357 | | elif lookup_type in ('exact', 'gt', 'gte', 'lt', 'lte'): |
| 358 | elif lookup_type in ('exact', 'ne', 'gt', 'gte', 'lt', 'lte'): |
358 | 359 | return [self.get_db_prep_value(value, connection=connection, |
359 | 360 | prepared=prepared)] |
360 | | elif lookup_type in ('range', 'in'): |
| 361 | elif lookup_type in ('range', 'in', 'notin'): |
361 | 362 | return [self.get_db_prep_value(v, connection=connection, |
362 | 363 | prepared=prepared) for v in value] |
363 | | elif lookup_type in ('contains', 'icontains'): |
| 364 | elif lookup_type in ('contains', 'icontains', 'ncontains', 'nicontains'): |
364 | 365 | return ["%%%s%%" % connection.ops.prep_for_like_query(value)] |
365 | 366 | elif lookup_type == 'iexact': |
366 | 367 | return [connection.ops.prep_for_iexact_query(value)] |
diff -ur ../orig/Django-1.5.5/django/db/models/fields/related.py django/db/models/fields/related.py
old
|
new
|
|
139 | 139 | # get_(next/prev)_by_date work; other lookups are not allowed since that |
140 | 140 | # gets messy pretty quick. This is a good candidate for some refactoring |
141 | 141 | # in the future. |
142 | | if lookup_type in ['exact', 'gt', 'lt', 'gte', 'lte']: |
| 142 | if lookup_type in ['exact', 'ne', 'gt', 'lt', 'gte', 'lte']: |
143 | 143 | 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'): |
145 | 145 | return [self._pk_trace(v, 'get_prep_lookup', lookup_type) for v in value] |
146 | 146 | elif lookup_type == 'isnull': |
147 | 147 | return [] |
… |
… |
|
167 | 167 | # get_(next/prev)_by_date work; other lookups are not allowed since that |
168 | 168 | # gets messy pretty quick. This is a good candidate for some refactoring |
169 | 169 | # in the future. |
170 | | if lookup_type in ['exact', 'gt', 'lt', 'gte', 'lte']: |
| 170 | if lookup_type in ['exact', 'ne', 'gt', 'lt', 'gte', 'lte']: |
171 | 171 | return [self._pk_trace(value, 'get_db_prep_lookup', lookup_type, |
172 | 172 | connection=connection, prepared=prepared)] |
173 | | if lookup_type in ('range', 'in'): |
| 173 | if lookup_type in ('range', 'in', 'notin'): |
174 | 174 | return [self._pk_trace(v, 'get_db_prep_lookup', lookup_type, |
175 | 175 | connection=connection, prepared=prepared) |
176 | 176 | for v in value] |
… |
… |
|
211 | 211 | else: |
212 | 212 | field = field.rel.to._meta.pk |
213 | 213 | |
214 | | if lookup_type in ('range', 'in'): |
| 214 | if lookup_type in ('range', 'in', 'notin'): |
215 | 215 | v = [v] |
216 | 216 | v = getattr(field, prep_func)(lookup_type, v, **kwargs) |
217 | 217 | if isinstance(v, list): |
diff -ur ../orig/Django-1.5.5/django/db/models/sql/constants.py django/db/models/sql/constants.py
old
|
new
|
|
12 | 12 | 'exact', 'iexact', 'contains', 'icontains', 'gt', 'gte', 'lt', 'lte', 'in', |
13 | 13 | 'startswith', 'istartswith', 'endswith', 'iendswith', 'range', 'year', |
14 | 14 | 'month', 'day', 'week_day', 'isnull', 'search', 'regex', 'iregex', |
| 15 | 'ne', 'notin', 'ncontains', 'nicontains', |
15 | 16 | ]) |
16 | 17 | |
17 | 18 | # Size of each "chunk" for get_iterator calls. |
diff -ur ../orig/Django-1.5.5/django/db/models/sql/query.py django/db/models/sql/query.py
old
|
new
|
|
1101 | 1101 | # Interpret '__exact=None' as the sql 'is NULL'; otherwise, reject all |
1102 | 1102 | # uses of None as a query value. |
1103 | 1103 | if value is None: |
1104 | | if lookup_type != 'exact': |
| 1104 | if lookup_type not in ('exact', 'ne'): |
1105 | 1105 | raise ValueError("Cannot use None as a query value") |
| 1106 | value = lookup_type == 'exact' |
1106 | 1107 | lookup_type = 'isnull' |
1107 | | value = True |
1108 | 1108 | elif callable(value): |
1109 | 1109 | value = value() |
1110 | 1110 | elif isinstance(value, ExpressionNode): |
diff -ur ../orig/Django-1.5.5/django/db/models/sql/where.py django/db/models/sql/where.py
old
|
new
|
|
185 | 185 | else: |
186 | 186 | extra = '' |
187 | 187 | |
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') |
189 | 189 | and connection.features.interprets_empty_strings_as_nulls): |
| 190 | value_annotation = lookup_type == 'exact' |
190 | 191 | lookup_type = 'isnull' |
191 | | value_annotation = True |
192 | 192 | |
193 | 193 | if lookup_type in connection.operators: |
194 | 194 | format = "%s %%s %%s" % (connection.ops.lookup_cast(lookup_type),) |
… |
… |
|
196 | 196 | connection.operators[lookup_type] % cast_sql, |
197 | 197 | extra), params) |
198 | 198 | |
199 | | if lookup_type == 'in': |
| 199 | if lookup_type in ('in', 'notin'): |
200 | 200 | if not value_annotation: |
201 | 201 | raise EmptyResultSet |
| 202 | if lookup_type == 'in': |
| 203 | op = 'IN' |
| 204 | else: |
| 205 | op = 'NOT IN' |
202 | 206 | if extra: |
203 | | return ('%s IN %s' % (field_sql, extra), params) |
| 207 | return ('%s %s %s' % (field_sql, op, extra), params) |
204 | 208 | max_in_list_size = connection.ops.max_in_list_size() |
205 | 209 | if max_in_list_size and len(params) > max_in_list_size: |
206 | 210 | # Break up the params list into an OR of manageable chunks. |
… |
… |
|
208 | 212 | for offset in xrange(0, len(params), max_in_list_size): |
209 | 213 | if offset > 0: |
210 | 214 | in_clause_elements.append(' OR ') |
211 | | in_clause_elements.append('%s IN (' % field_sql) |
| 215 | in_clause_elements.append('%s %s (' % (field_sql, op)) |
212 | 216 | group_size = min(len(params) - offset, max_in_list_size) |
213 | 217 | param_group = ', '.join(repeat('%s', group_size)) |
214 | 218 | in_clause_elements.append(param_group) |
… |
… |
|
216 | 220 | in_clause_elements.append(')') |
217 | 221 | return ''.join(in_clause_elements), params |
218 | 222 | else: |
219 | | return ('%s IN (%s)' % (field_sql, |
| 223 | return ('%s %s (%s)' % (field_sql, op, |
220 | 224 | ', '.join(repeat('%s', len(params)))), |
221 | 225 | params) |
222 | 226 | elif lookup_type in ('range', 'year'): |