Skip to content

Commit

Permalink
Fixed #5087 -- Fixed support for TextField filtering with Oracle. Tha…
Browse files Browse the repository at this point in the history
…nks, Ian Kelly.

git-svn-id: http://code.djangoproject.com/svn/django/trunk@5943 bcc190cf-cafb-0310-a4f2-bffc1f526a37
  • Loading branch information
malcolmt committed Aug 19, 2007
1 parent e0c1ca7 commit 7e8efcd
Show file tree
Hide file tree
Showing 3 changed files with 40 additions and 11 deletions.
6 changes: 6 additions & 0 deletions django/db/backends/oracle/base.py
Expand Up @@ -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.
Expand Down
29 changes: 18 additions & 11 deletions django/db/models/query.py
Expand Up @@ -777,44 +777,49 @@ def get_sql(self, opts):
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)
if type(value) == datetime.datetime and backend.get_datetime_cast_sql(): if type(value) == datetime.datetime and backend.get_datetime_cast_sql():
cast_sql = backend.get_datetime_cast_sql() cast_sql = backend.get_datetime_cast_sql()
else: else:
cast_sql = '%s' cast_sql = '%s'
if db_type and hasattr(backend, 'get_field_cast_sql'):
field_cast_sql = backend.get_field_cast_sql(db_type)
else:
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: if lookup_type in ('iexact', 'icontains', 'istartswith', 'iendswith') and backend.needs_upper_for_iops:
format = 'UPPER(%s%s) %s' format = 'UPPER(%s) %s'
else: else:
format = '%s%s %s' 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)
Expand Down Expand Up @@ -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
Expand Down Expand Up @@ -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
Expand Down
16 changes: 16 additions & 0 deletions tests/regressiontests/string_lookup/models.py
Expand Up @@ -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.
Expand Down Expand Up @@ -82,4 +89,13 @@ def __unicode__(self):
# 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>
"""} """}

0 comments on commit 7e8efcd

Please sign in to comment.