summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorhayashi <sshayashi0208@gmail.com>2018-01-16 03:11:20 +0900
committerTim Graham <timograham@gmail.com>2018-01-17 09:28:03 -0500
commit27557a7a99ab1ad032c699dc01e114a5e6504b0a (patch)
treea897c2f3a6913c493850b0fa6ac13e1a936fa4fd
parentb902878fd61feb83159a4770ccf327d532963b67 (diff)
Fixed #28857 -- Fixed invalid SQL when using Cast with complex expressions on PostgreSQL.
-rw-r--r--django/db/models/functions/comparison.py4
-rw-r--r--tests/db_functions/test_cast.py18
2 files changed, 19 insertions, 3 deletions
diff --git a/django/db/models/functions/comparison.py b/django/db/models/functions/comparison.py
index 8bf4fdc8d7..69e9d09abb 100644
--- a/django/db/models/functions/comparison.py
+++ b/django/db/models/functions/comparison.py
@@ -21,7 +21,9 @@ class Cast(Func):
def as_postgresql(self, compiler, connection):
# CAST would be valid too, but the :: shortcut syntax is more readable.
- return self.as_sql(compiler, connection, template='%(expressions)s::%(db_type)s')
+ # 'expressions' is wrapped in parentheses in case it's a complex
+ # expression.
+ return self.as_sql(compiler, connection, template='(%(expressions)s)::%(db_type)s')
class Coalesce(Func):
diff --git a/tests/db_functions/test_cast.py b/tests/db_functions/test_cast.py
index 36220cf640..12932d95be 100644
--- a/tests/db_functions/test_cast.py
+++ b/tests/db_functions/test_cast.py
@@ -1,10 +1,14 @@
import datetime
import decimal
+import unittest
-from django.db import models
+from django.db import connection, models
+from django.db.models import Avg
from django.db.models.expressions import Value
from django.db.models.functions import Cast
-from django.test import TestCase, ignore_warnings, skipUnlessDBFeature
+from django.test import (
+ TestCase, ignore_warnings, override_settings, skipUnlessDBFeature,
+)
from .models import Author
@@ -60,3 +64,13 @@ class CastTests(TestCase):
cast_float = numbers.get().cast_float
self.assertIsInstance(cast_float, float)
self.assertEqual(cast_float, 0.125)
+
+ @unittest.skipUnless(connection.vendor == 'postgresql', 'PostgreSQL test')
+ @override_settings(DEBUG=True)
+ def test_expression_wrapped_with_parentheses_on_postgresql(self):
+ """
+ The SQL for the Cast expression is wrapped with parentheses in case
+ it's a complex expression.
+ """
+ list(Author.objects.annotate(cast_float=Cast(Avg('age'), models.FloatField())))
+ self.assertIn('(AVG("db_functions_author"."age"))::double precision', connection.queries[-1]['sql'])