Fixed #34547 -- Deprecated DatabaseOperations.field_cast_sql().

This commit is contained in:
David Smith 2023-08-18 14:16:57 +01:00 committed by Mariusz Felisiak
parent 500e01073a
commit 27b399d235
5 changed files with 59 additions and 2 deletions

View File

@ -1,6 +1,7 @@
import datetime import datetime
import decimal import decimal
import json import json
import warnings
from importlib import import_module from importlib import import_module
import sqlparse import sqlparse
@ -10,6 +11,7 @@ from django.db import NotSupportedError, transaction
from django.db.backends import utils from django.db.backends import utils
from django.db.models.expressions import Col from django.db.models.expressions import Col
from django.utils import timezone from django.utils import timezone
from django.utils.deprecation import RemovedInDjango60Warning
from django.utils.encoding import force_str from django.utils.encoding import force_str
@ -220,6 +222,13 @@ class BaseDatabaseOperations:
it in a WHERE statement. The resulting string should contain a '%s' it in a WHERE statement. The resulting string should contain a '%s'
placeholder for the column being searched against. placeholder for the column being searched against.
""" """
warnings.warn(
(
"DatabaseOperations.field_cast_sql() is deprecated use "
"DatabaseOperations.lookup_cast() instead."
),
RemovedInDjango60Warning,
)
return "%s" return "%s"
def force_no_ordering(self): def force_no_ordering(self):

View File

@ -1,7 +1,9 @@
import itertools import itertools
import math import math
import warnings
from django.core.exceptions import EmptyResultSet, FullResultSet from django.core.exceptions import EmptyResultSet, FullResultSet
from django.db.backends.base.operations import BaseDatabaseOperations
from django.db.models.expressions import Case, Expression, Func, Value, When from django.db.models.expressions import Case, Expression, Func, Value, When
from django.db.models.fields import ( from django.db.models.fields import (
BooleanField, BooleanField,
@ -13,6 +15,7 @@ from django.db.models.fields import (
) )
from django.db.models.query_utils import RegisterLookupMixin from django.db.models.query_utils import RegisterLookupMixin
from django.utils.datastructures import OrderedSet from django.utils.datastructures import OrderedSet
from django.utils.deprecation import RemovedInDjango60Warning
from django.utils.functional import cached_property from django.utils.functional import cached_property
from django.utils.hashable import make_hashable from django.utils.hashable import make_hashable
@ -217,8 +220,22 @@ class BuiltinLookup(Lookup):
def process_lhs(self, compiler, connection, lhs=None): def process_lhs(self, compiler, connection, lhs=None):
lhs_sql, params = super().process_lhs(compiler, connection, lhs) lhs_sql, params = super().process_lhs(compiler, connection, lhs)
field_internal_type = self.lhs.output_field.get_internal_type() field_internal_type = self.lhs.output_field.get_internal_type()
db_type = self.lhs.output_field.db_type(connection=connection) if (
lhs_sql = connection.ops.field_cast_sql(db_type, field_internal_type) % lhs_sql hasattr(connection.ops.__class__, "field_cast_sql")
and connection.ops.__class__.field_cast_sql
is not BaseDatabaseOperations.field_cast_sql
):
warnings.warn(
(
"The usage of DatabaseOperations.field_cast_sql() is deprecated. "
"Implement DatabaseOperations.lookup_cast() instead."
),
RemovedInDjango60Warning,
)
db_type = self.lhs.output_field.db_type(connection=connection)
lhs_sql = (
connection.ops.field_cast_sql(db_type, field_internal_type) % lhs_sql
)
lhs_sql = ( lhs_sql = (
connection.ops.lookup_cast(self.lookup_name, field_internal_type) % lhs_sql connection.ops.lookup_cast(self.lookup_name, field_internal_type) % lhs_sql
) )

View File

@ -40,6 +40,8 @@ details on these changes.
* Support for ``cx_Oracle`` will be removed. * Support for ``cx_Oracle`` will be removed.
* ``BaseDatabaseOperations.field_cast_sql()`` will be removed.
.. _deprecation-removed-in-5.1: .. _deprecation-removed-in-5.1:
5.1 5.1

View File

@ -663,6 +663,11 @@ Miscellaneous
* Support for ``cx_Oracle`` is deprecated in favor of `oracledb`_ 1.3.2+ Python * Support for ``cx_Oracle`` is deprecated in favor of `oracledb`_ 1.3.2+ Python
driver. driver.
* ``DatabaseOperations.field_cast_sql()`` is deprecated in favor of
``DatabaseOperations.lookup_cast()``. Starting with Django 6.0,
``BuiltinLookup.process_lhs()`` will no longer call ``field_cast_sql()``.
Third-party database backends should implement ``lookup_cast()`` instead.
.. _`oracledb`: https://oracle.github.io/python-oracledb/ .. _`oracledb`: https://oracle.github.io/python-oracledb/
Features removed in 5.0 Features removed in 5.0

View File

@ -1,10 +1,12 @@
import decimal import decimal
from unittest import mock
from django.core.management.color import no_style from django.core.management.color import no_style
from django.db import NotSupportedError, connection, transaction from django.db import NotSupportedError, connection, transaction
from django.db.backends.base.operations import BaseDatabaseOperations from django.db.backends.base.operations import BaseDatabaseOperations
from django.db.models import DurationField, Value from django.db.models import DurationField, Value
from django.db.models.expressions import Col from django.db.models.expressions import Col
from django.db.models.lookups import Exact
from django.test import ( from django.test import (
SimpleTestCase, SimpleTestCase,
TestCase, TestCase,
@ -13,6 +15,7 @@ from django.test import (
skipIfDBFeature, skipIfDBFeature,
) )
from django.utils import timezone from django.utils import timezone
from django.utils.deprecation import RemovedInDjango60Warning
from ..models import Author, Book from ..models import Author, Book
@ -235,3 +238,24 @@ class SqlFlushTests(TransactionTestCase):
self.assertEqual(author.pk, 1) self.assertEqual(author.pk, 1)
book = Book.objects.create(author=author) book = Book.objects.create(author=author)
self.assertEqual(book.pk, 1) self.assertEqual(book.pk, 1)
class DeprecationTests(TestCase):
def test_field_cast_sql_warning(self):
base_ops = BaseDatabaseOperations(connection=connection)
msg = (
"DatabaseOperations.field_cast_sql() is deprecated use "
"DatabaseOperations.lookup_cast() instead."
)
with self.assertRaisesMessage(RemovedInDjango60Warning, msg):
base_ops.field_cast_sql("integer", "IntegerField")
def test_field_cast_sql_usage_warning(self):
compiler = Author.objects.all().query.get_compiler(connection.alias)
msg = (
"The usage of DatabaseOperations.field_cast_sql() is deprecated. Implement "
"DatabaseOperations.lookup_cast() instead."
)
with mock.patch.object(connection.ops.__class__, "field_cast_sql"):
with self.assertRaisesMessage(RemovedInDjango60Warning, msg):
Exact("name", "book__author__name").as_sql(compiler, connection)