summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorDavid Smith <smithdc@gmail.com>2023-08-18 14:16:57 +0100
committerMariusz Felisiak <felisiak.mariusz@gmail.com>2023-08-31 06:18:07 +0200
commit27b399d23531541d091886f683991e321c8fa314 (patch)
tree468439e4efdd26e6d78609b61ed872ceabfb1380
parent500e01073adda32d5149624ee9a5cb7aa3d3583f (diff)
Fixed #34547 -- Deprecated DatabaseOperations.field_cast_sql().
-rw-r--r--django/db/backends/base/operations.py9
-rw-r--r--django/db/models/lookups.py21
-rw-r--r--docs/internals/deprecation.txt2
-rw-r--r--docs/releases/5.0.txt5
-rw-r--r--tests/backends/base/test_operations.py24
5 files changed, 59 insertions, 2 deletions
diff --git a/django/db/backends/base/operations.py b/django/db/backends/base/operations.py
index 6f10e31cd5..0ee2ffc5c4 100644
--- a/django/db/backends/base/operations.py
+++ b/django/db/backends/base/operations.py
@@ -1,6 +1,7 @@
import datetime
import decimal
import json
+import warnings
from importlib import import_module
import sqlparse
@@ -10,6 +11,7 @@ from django.db import NotSupportedError, transaction
from django.db.backends import utils
from django.db.models.expressions import Col
from django.utils import timezone
+from django.utils.deprecation import RemovedInDjango60Warning
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'
placeholder for the column being searched against.
"""
+ warnings.warn(
+ (
+ "DatabaseOperations.field_cast_sql() is deprecated use "
+ "DatabaseOperations.lookup_cast() instead."
+ ),
+ RemovedInDjango60Warning,
+ )
return "%s"
def force_no_ordering(self):
diff --git a/django/db/models/lookups.py b/django/db/models/lookups.py
index 8528fcda5c..896d3eee44 100644
--- a/django/db/models/lookups.py
+++ b/django/db/models/lookups.py
@@ -1,7 +1,9 @@
import itertools
import math
+import warnings
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.fields import (
BooleanField,
@@ -13,6 +15,7 @@ from django.db.models.fields import (
)
from django.db.models.query_utils import RegisterLookupMixin
from django.utils.datastructures import OrderedSet
+from django.utils.deprecation import RemovedInDjango60Warning
from django.utils.functional import cached_property
from django.utils.hashable import make_hashable
@@ -217,8 +220,22 @@ class BuiltinLookup(Lookup):
def process_lhs(self, compiler, connection, lhs=None):
lhs_sql, params = super().process_lhs(compiler, connection, lhs)
field_internal_type = self.lhs.output_field.get_internal_type()
- db_type = self.lhs.output_field.db_type(connection=connection)
- lhs_sql = connection.ops.field_cast_sql(db_type, field_internal_type) % lhs_sql
+ if (
+ 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 = (
connection.ops.lookup_cast(self.lookup_name, field_internal_type) % lhs_sql
)
diff --git a/docs/internals/deprecation.txt b/docs/internals/deprecation.txt
index c9a8b05637..98b027cd1a 100644
--- a/docs/internals/deprecation.txt
+++ b/docs/internals/deprecation.txt
@@ -40,6 +40,8 @@ details on these changes.
* Support for ``cx_Oracle`` will be removed.
+* ``BaseDatabaseOperations.field_cast_sql()`` will be removed.
+
.. _deprecation-removed-in-5.1:
5.1
diff --git a/docs/releases/5.0.txt b/docs/releases/5.0.txt
index cae3668bfc..28814f141f 100644
--- a/docs/releases/5.0.txt
+++ b/docs/releases/5.0.txt
@@ -663,6 +663,11 @@ Miscellaneous
* Support for ``cx_Oracle`` is deprecated in favor of `oracledb`_ 1.3.2+ Python
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/
Features removed in 5.0
diff --git a/tests/backends/base/test_operations.py b/tests/backends/base/test_operations.py
index 9d2828c8ce..d2a3fb6765 100644
--- a/tests/backends/base/test_operations.py
+++ b/tests/backends/base/test_operations.py
@@ -1,10 +1,12 @@
import decimal
+from unittest import mock
from django.core.management.color import no_style
from django.db import NotSupportedError, connection, transaction
from django.db.backends.base.operations import BaseDatabaseOperations
from django.db.models import DurationField, Value
from django.db.models.expressions import Col
+from django.db.models.lookups import Exact
from django.test import (
SimpleTestCase,
TestCase,
@@ -13,6 +15,7 @@ from django.test import (
skipIfDBFeature,
)
from django.utils import timezone
+from django.utils.deprecation import RemovedInDjango60Warning
from ..models import Author, Book
@@ -235,3 +238,24 @@ class SqlFlushTests(TransactionTestCase):
self.assertEqual(author.pk, 1)
book = Book.objects.create(author=author)
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)