summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorAnssi Kääriäinen <akaariai@gmail.com>2013-03-24 22:59:44 +0200
committerAnssi Kääriäinen <akaariai@gmail.com>2013-03-26 15:05:37 +0200
commit207117ae731096d8148c17c6ca16f06ebf18537c (patch)
tree4ba8c6e3f60f7824185a90e7d76ad9bb869289d6
parent5e2bb1223c4e622113cef0edb6d7df53fab0367c (diff)
[1.5.x] Fixed #20091 -- Oracle null promotion for empty strings
Backpatch of e17fa9e877e84e93b699c2bd13ea48dbbb86e451
-rw-r--r--django/db/models/sql/query.py9
-rw-r--r--tests/regressiontests/queries/tests.py9
2 files changed, 16 insertions, 2 deletions
diff --git a/django/db/models/sql/query.py b/django/db/models/sql/query.py
index e7c8d6caaf..7368fed24c 100644
--- a/django/db/models/sql/query.py
+++ b/django/db/models/sql/query.py
@@ -1106,7 +1106,14 @@ class Query(object):
# If value is a query expression, evaluate it
value = SQLEvaluator(value, self, reuse=can_reuse)
having_clause = value.contains_aggregate
-
+ # For Oracle '' is equivalent to null. The check needs to be done
+ # at this stage because join promotion can't be done at compiler
+ # stage. Using DEFAULT_DB_ALIAS isn't nice, but it is the best we
+ # can do here. Similar thing is done in is_nullable(), too.
+ if (connections[DEFAULT_DB_ALIAS].features.interprets_empty_strings_as_nulls and
+ lookup_type == 'exact' and value == ''):
+ value = True
+ lookup_type = 'isnull'
for alias, aggregate in self.aggregates.items():
if alias in (parts[0], LOOKUP_SEP.join(parts)):
entry = self.where_class()
diff --git a/tests/regressiontests/queries/tests.py b/tests/regressiontests/queries/tests.py
index a2f91e9964..33e5337f58 100644
--- a/tests/regressiontests/queries/tests.py
+++ b/tests/regressiontests/queries/tests.py
@@ -1533,7 +1533,6 @@ class Queries6Tests(TestCase):
# Nested queries are possible (although should be used with care, since
# they have performance problems on backends like MySQL.
-
self.assertQuerysetEqual(
Annotation.objects.filter(notes__in=Note.objects.filter(note="n1")),
['<Annotation: a1>']
@@ -2142,3 +2141,11 @@ class NullJoinPromotionOrTest(TestCase):
# so we can use INNER JOIN for it. However, we can NOT use INNER JOIN
# for the b->c join, as a->b is nullable.
self.assertEqual(str(qset.query).count('INNER JOIN'), 1)
+
+class EmptyStringPromotionTests(TestCase):
+ def test_empty_string_promotion(self):
+ qs = RelatedObject.objects.filter(single__name='')
+ if connection.features.interprets_empty_strings_as_nulls:
+ self.assertIn('LEFT OUTER JOIN', str(qs.query))
+ else:
+ self.assertNotIn('LEFT OUTER JOIN', str(qs.query))