Refs #32858, Refs #32392 -- Restored using :: shortcut syntax in Cast() on PostgreSQL.

This partly reverts commit fdfbc66331
unnecessary since b69b0c3fe8.
This commit is contained in:
Mariusz Felisiak 2021-06-22 06:10:54 +02:00
parent b69b0c3fe8
commit e07609a0d1
3 changed files with 24 additions and 1 deletions

View File

@ -42,6 +42,12 @@ class Cast(Func):
template = "JSON_EXTRACT(%(expressions)s, '$')" template = "JSON_EXTRACT(%(expressions)s, '$')"
return self.as_sql(compiler, connection, template=template, **extra_context) return self.as_sql(compiler, connection, template=template, **extra_context)
def as_postgresql(self, compiler, connection, **extra_context):
# CAST would be valid too, but the :: shortcut syntax is more readable.
# 'expressions' is wrapped in parentheses in case it's a complex
# expression.
return self.as_sql(compiler, connection, template='(%(expressions)s)::%(db_type)s', **extra_context)
def as_oracle(self, compiler, connection, **extra_context): def as_oracle(self, compiler, connection, **extra_context):
if self.output_field.get_internal_type() == 'JSONField': if self.output_field.get_internal_type() == 'JSONField':
# Oracle doesn't support explicit cast to JSON. # Oracle doesn't support explicit cast to JSON.

View File

@ -1,9 +1,11 @@
import datetime import datetime
import decimal import decimal
import unittest
from django.db import connection, models from django.db import connection, models
from django.db.models.functions import Cast from django.db.models.functions import Cast
from django.test import TestCase, ignore_warnings, skipUnlessDBFeature from django.test import TestCase, ignore_warnings, skipUnlessDBFeature
from django.test.utils import CaptureQueriesContext
from ..models import Author, DTModel, Fan, FloatModel from ..models import Author, DTModel, Fan, FloatModel
@ -125,5 +127,20 @@ class CastTests(TestCase):
self.assertIsInstance(cast_float, float) self.assertIsInstance(cast_float, float)
self.assertEqual(cast_float, 0.125) self.assertEqual(cast_float, 0.125)
@unittest.skipUnless(connection.vendor == 'postgresql', 'PostgreSQL test')
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.
"""
with CaptureQueriesContext(connection) as captured_queries:
list(Author.objects.annotate(
cast_float=Cast(models.Avg('age'), models.FloatField()),
))
self.assertIn(
'(AVG("db_functions_author"."age"))::double precision',
captured_queries[0]['sql'],
)
def test_cast_to_text_field(self): def test_cast_to_text_field(self):
self.assertEqual(Author.objects.values_list(Cast('age', models.TextField()), flat=True).get(), '1') self.assertEqual(Author.objects.values_list(Cast('age', models.TextField()), flat=True).get(), '1')

View File

@ -305,7 +305,7 @@ class SchemaTests(PostgreSQLTestCase):
self.assertIn(index_name, constraints) self.assertIn(index_name, constraints)
self.assertIn(constraints[index_name]['type'], GinIndex.suffix) self.assertIn(constraints[index_name]['type'], GinIndex.suffix)
self.assertIs(sql.references_column(table, 'field'), True) self.assertIs(sql.references_column(table, 'field'), True)
self.assertIn(' AS tsvector', str(sql)) self.assertIn('::tsvector', str(sql))
with connection.schema_editor() as editor: with connection.schema_editor() as editor:
editor.remove_index(TextFieldModel, index) editor.remove_index(TextFieldModel, index)
self.assertNotIn(index_name, self.get_constraints(table)) self.assertNotIn(index_name, self.get_constraints(table))