Fixed #5087 -- Fixed support for TextField filtering with Oracle. Thanks, Ian Kelly.
git-svn-id: http://code.djangoproject.com/svn/django/trunk@5943 bcc190cf-cafb-0310-a4f2-bffc1f526a37
This commit is contained in:
parent
e0c1ca7ef0
commit
7e8efcd4d9
|
@ -181,6 +181,12 @@ def get_date_trunc_sql(lookup_type, field_name):
|
||||||
def get_datetime_cast_sql():
|
def get_datetime_cast_sql():
|
||||||
return "TO_TIMESTAMP(%s, 'YYYY-MM-DD HH24:MI:SS.FF')"
|
return "TO_TIMESTAMP(%s, 'YYYY-MM-DD HH24:MI:SS.FF')"
|
||||||
|
|
||||||
|
def get_field_cast_sql(db_type):
|
||||||
|
if db_type.endswith('LOB'):
|
||||||
|
return "DBMS_LOB.SUBSTR(%s%s)"
|
||||||
|
else:
|
||||||
|
return "%s%s"
|
||||||
|
|
||||||
def get_limit_offset_sql(limit, offset=None):
|
def get_limit_offset_sql(limit, offset=None):
|
||||||
# Limits and offset are too complicated to be handled here.
|
# Limits and offset are too complicated to be handled here.
|
||||||
# Instead, they are handled in django/db/backends/oracle/query.py.
|
# Instead, they are handled in django/db/backends/oracle/query.py.
|
||||||
|
|
|
@ -777,7 +777,7 @@ class QNot(Q):
|
||||||
return SortedDict(), [], []
|
return SortedDict(), [], []
|
||||||
return joins, where2, params
|
return joins, where2, params
|
||||||
|
|
||||||
def get_where_clause(lookup_type, table_prefix, field_name, value):
|
def get_where_clause(lookup_type, table_prefix, field_name, value, db_type):
|
||||||
if table_prefix.endswith('.'):
|
if table_prefix.endswith('.'):
|
||||||
table_prefix = backend.quote_name(table_prefix[:-1])+'.'
|
table_prefix = backend.quote_name(table_prefix[:-1])+'.'
|
||||||
field_name = backend.quote_name(field_name)
|
field_name = backend.quote_name(field_name)
|
||||||
|
@ -785,36 +785,41 @@ def get_where_clause(lookup_type, table_prefix, field_name, value):
|
||||||
cast_sql = backend.get_datetime_cast_sql()
|
cast_sql = backend.get_datetime_cast_sql()
|
||||||
else:
|
else:
|
||||||
cast_sql = '%s'
|
cast_sql = '%s'
|
||||||
if lookup_type in ('iexact', 'icontains', 'istartswith', 'iendswith') and backend.needs_upper_for_iops:
|
if db_type and hasattr(backend, 'get_field_cast_sql'):
|
||||||
format = 'UPPER(%s%s) %s'
|
field_cast_sql = backend.get_field_cast_sql(db_type)
|
||||||
else:
|
else:
|
||||||
format = '%s%s %s'
|
field_cast_sql = '%s%s'
|
||||||
|
field_sql = field_cast_sql % (table_prefix, field_name)
|
||||||
|
if lookup_type in ('iexact', 'icontains', 'istartswith', 'iendswith') and backend.needs_upper_for_iops:
|
||||||
|
format = 'UPPER(%s) %s'
|
||||||
|
else:
|
||||||
|
format = '%s %s'
|
||||||
try:
|
try:
|
||||||
return format % (table_prefix, field_name,
|
return format % (field_sql,
|
||||||
backend.OPERATOR_MAPPING[lookup_type] % cast_sql)
|
backend.OPERATOR_MAPPING[lookup_type] % cast_sql)
|
||||||
except KeyError:
|
except KeyError:
|
||||||
pass
|
pass
|
||||||
if lookup_type == 'in':
|
if lookup_type == 'in':
|
||||||
in_string = ','.join(['%s' for id in value])
|
in_string = ','.join(['%s' for id in value])
|
||||||
if in_string:
|
if in_string:
|
||||||
return '%s%s IN (%s)' % (table_prefix, field_name, in_string)
|
return '%s IN (%s)' % (field_sql, in_string)
|
||||||
else:
|
else:
|
||||||
raise EmptyResultSet
|
raise EmptyResultSet
|
||||||
elif lookup_type in ('range', 'year'):
|
elif lookup_type in ('range', 'year'):
|
||||||
return '%s%s BETWEEN %%s AND %%s' % (table_prefix, field_name)
|
return '%s BETWEEN %%s AND %%s' % field_sql
|
||||||
elif lookup_type in ('month', 'day'):
|
elif lookup_type in ('month', 'day'):
|
||||||
return "%s = %%s" % backend.get_date_extract_sql(lookup_type, table_prefix + field_name)
|
return "%s = %%s" % backend.get_date_extract_sql(lookup_type, field_sql)
|
||||||
elif lookup_type == 'isnull':
|
elif lookup_type == 'isnull':
|
||||||
return "%s%s IS %sNULL" % (table_prefix, field_name, (not value and 'NOT ' or ''))
|
return "%s IS %sNULL" % (field_sql, (not value and 'NOT ' or ''))
|
||||||
elif lookup_type == 'search':
|
elif lookup_type == 'search':
|
||||||
return backend.get_fulltext_search_sql(table_prefix + field_name)
|
return backend.get_fulltext_search_sql(field_sql)
|
||||||
elif lookup_type in ('regex', 'iregex'):
|
elif lookup_type in ('regex', 'iregex'):
|
||||||
if settings.DATABASE_ENGINE == 'oracle':
|
if settings.DATABASE_ENGINE == 'oracle':
|
||||||
if lookup_type == 'regex':
|
if lookup_type == 'regex':
|
||||||
match_option = 'c'
|
match_option = 'c'
|
||||||
else:
|
else:
|
||||||
match_option = 'i'
|
match_option = 'i'
|
||||||
return "REGEXP_LIKE(%s%s, %s, '%s')" % (table_prefix, field_name, cast_sql, match_option)
|
return "REGEXP_LIKE(%s, %s, '%s')" % (field_sql, cast_sql, match_option)
|
||||||
else:
|
else:
|
||||||
raise NotImplementedError
|
raise NotImplementedError
|
||||||
raise TypeError, "Got invalid lookup_type: %s" % repr(lookup_type)
|
raise TypeError, "Got invalid lookup_type: %s" % repr(lookup_type)
|
||||||
|
@ -1071,6 +1076,7 @@ def lookup_inner(path, lookup_type, value, opts, table, column):
|
||||||
else:
|
else:
|
||||||
# No elements left in path. Current element is the element on which
|
# No elements left in path. Current element is the element on which
|
||||||
# the search is being performed.
|
# the search is being performed.
|
||||||
|
db_type = None
|
||||||
|
|
||||||
if join_required:
|
if join_required:
|
||||||
# Last query term is a RelatedObject
|
# Last query term is a RelatedObject
|
||||||
|
@ -1100,8 +1106,9 @@ def lookup_inner(path, lookup_type, value, opts, table, column):
|
||||||
else:
|
else:
|
||||||
# Last query term was a normal field.
|
# Last query term was a normal field.
|
||||||
column = field.column
|
column = field.column
|
||||||
|
db_type = field.db_type()
|
||||||
|
|
||||||
where.append(get_where_clause(lookup_type, current_table + '.', column, value))
|
where.append(get_where_clause(lookup_type, current_table + '.', column, value, db_type))
|
||||||
params.extend(field.get_db_prep_lookup(lookup_type, value))
|
params.extend(field.get_db_prep_lookup(lookup_type, value))
|
||||||
|
|
||||||
return joins, where, params
|
return joins, where, params
|
||||||
|
|
|
@ -36,6 +36,13 @@ class Base(models.Model):
|
||||||
def __unicode__(self):
|
def __unicode__(self):
|
||||||
return "Base %s" % self.name
|
return "Base %s" % self.name
|
||||||
|
|
||||||
|
class Article(models.Model):
|
||||||
|
name = models.CharField(maxlength = 50)
|
||||||
|
text = models.TextField()
|
||||||
|
|
||||||
|
def __str__(self):
|
||||||
|
return "Article %s" % self.name
|
||||||
|
|
||||||
__test__ = {'API_TESTS': ur"""
|
__test__ = {'API_TESTS': ur"""
|
||||||
# Regression test for #1661 and #1662: Check that string form referencing of
|
# Regression test for #1661 and #1662: Check that string form referencing of
|
||||||
# models works, both as pre and post reference, on all RelatedField types.
|
# models works, both as pre and post reference, on all RelatedField types.
|
||||||
|
@ -82,4 +89,13 @@ __test__ = {'API_TESTS': ur"""
|
||||||
# We can also do the above query using UTF-8 strings.
|
# We can also do the above query using UTF-8 strings.
|
||||||
>>> Foo.objects.get(friend__contains='\xc3\xa7')
|
>>> Foo.objects.get(friend__contains='\xc3\xa7')
|
||||||
<Foo: Foo Bjorn>
|
<Foo: Foo Bjorn>
|
||||||
|
|
||||||
|
# Regression tests for #5087: make sure we can perform queries on TextFields.
|
||||||
|
>>> a = Article(name='Test', text='The quick brown fox jumps over the lazy dog.')
|
||||||
|
>>> a.save()
|
||||||
|
>>> Article.objects.get(text__exact='The quick brown fox jumps over the lazy dog.')
|
||||||
|
<Article: Article Test>
|
||||||
|
|
||||||
|
>>> Article.objects.get(text__contains='quick brown fox')
|
||||||
|
<Article: Article Test>
|
||||||
"""}
|
"""}
|
||||||
|
|
Loading…
Reference in New Issue