From 8713ea7568af8871bf1306f14cc928058df0d4c7 Mon Sep 17 00:00:00 2001 From: Josh Smeaton Date: Wed, 7 Jan 2015 21:30:25 +1100 Subject: [PATCH] Fixed null handling in Value expression --- django/db/models/expressions.py | 5 +++++ tests/annotations/tests.py | 7 +++++++ tests/expressions/tests.py | 15 ++++++++++++++- 3 files changed, 26 insertions(+), 1 deletion(-) diff --git a/django/db/models/expressions.py b/django/db/models/expressions.py index ac69307edc..9fe3a35fee 100644 --- a/django/db/models/expressions.py +++ b/django/db/models/expressions.py @@ -483,6 +483,11 @@ class Value(ExpressionNode): self.value = value def as_sql(self, compiler, connection): + if self.value is None: + # cx_Oracle does not always convert None to the appropriate + # NULL type (like in case expressions using numbers), so we + # use a literal SQL NULL + return 'NULL', [] return '%s', [self.value] diff --git a/tests/annotations/tests.py b/tests/annotations/tests.py index 570ef4d52c..90a9c13048 100644 --- a/tests/annotations/tests.py +++ b/tests/annotations/tests.py @@ -190,6 +190,13 @@ class NonAggregateAnnotationTestCase(TestCase): lambda d: (d.other_name, d.other_chain, d.is_open, d.book_isbn) ) + def test_null_annotation(self): + """ + Test that annotating None onto a model round-trips + """ + book = Book.objects.annotate(no_value=Value(None, output_field=IntegerField())).first() + self.assertIsNone(book.no_value) + def test_column_field_ordering(self): """ Test that columns are aligned in the correct order for diff --git a/tests/expressions/tests.py b/tests/expressions/tests.py index 0e9bd57e91..8165a496dc 100644 --- a/tests/expressions/tests.py +++ b/tests/expressions/tests.py @@ -5,7 +5,7 @@ import datetime from django.core.exceptions import FieldError from django.db import connection, transaction, DatabaseError -from django.db.models import F +from django.db.models import F, Value from django.test import TestCase, skipIfDBFeature, skipUnlessDBFeature from django.test.utils import Approximate from django.utils import six @@ -174,6 +174,19 @@ class BasicExpressionsTests(TestCase): ordered=False ) + def test_update_with_none(self): + Number.objects.create(integer=1, float=1.0) + Number.objects.create(integer=2) + Number.objects.filter(float__isnull=False).update(float=Value(None)) + self.assertQuerysetEqual( + Number.objects.all(), [ + None, + None, + ], + lambda n: n.float, + ordered=False + ) + def test_filter_with_join(self): # F Expressions can also span joins Company.objects.update(point_of_contact=F('ceo'))