mirror of https://github.com/django/django.git
Fixed #35856 -- Added QuerySet.explain() support for MEMORY/SERIALIZE option on PostgreSQL 17+.
This commit is contained in:
parent
97a6a678c4
commit
3a8f52fbc6
|
@ -160,6 +160,10 @@ class DatabaseFeatures(BaseDatabaseFeatures):
|
||||||
def is_postgresql_16(self):
|
def is_postgresql_16(self):
|
||||||
return self.connection.pg_version >= 160000
|
return self.connection.pg_version >= 160000
|
||||||
|
|
||||||
|
@cached_property
|
||||||
|
def is_postgresql_17(self):
|
||||||
|
return self.connection.pg_version >= 170000
|
||||||
|
|
||||||
supports_unlimited_charfield = True
|
supports_unlimited_charfield = True
|
||||||
supports_nulls_distinct_unique_constraints = property(
|
supports_nulls_distinct_unique_constraints = property(
|
||||||
operator.attrgetter("is_postgresql_15")
|
operator.attrgetter("is_postgresql_15")
|
||||||
|
|
|
@ -32,7 +32,9 @@ class DatabaseOperations(BaseDatabaseOperations):
|
||||||
"BUFFERS",
|
"BUFFERS",
|
||||||
"COSTS",
|
"COSTS",
|
||||||
"GENERIC_PLAN",
|
"GENERIC_PLAN",
|
||||||
|
"MEMORY",
|
||||||
"SETTINGS",
|
"SETTINGS",
|
||||||
|
"SERIALIZE",
|
||||||
"SUMMARY",
|
"SUMMARY",
|
||||||
"TIMING",
|
"TIMING",
|
||||||
"VERBOSE",
|
"VERBOSE",
|
||||||
|
@ -365,6 +367,9 @@ class DatabaseOperations(BaseDatabaseOperations):
|
||||||
|
|
||||||
def explain_query_prefix(self, format=None, **options):
|
def explain_query_prefix(self, format=None, **options):
|
||||||
extra = {}
|
extra = {}
|
||||||
|
if serialize := options.pop("serialize", None):
|
||||||
|
if serialize.upper() in {"TEXT", "BINARY"}:
|
||||||
|
extra["SERIALIZE"] = serialize.upper()
|
||||||
# Normalize options.
|
# Normalize options.
|
||||||
if options:
|
if options:
|
||||||
options = {
|
options = {
|
||||||
|
|
|
@ -3110,6 +3110,11 @@ there are triggers or if a function is called, even for a ``SELECT`` query.
|
||||||
|
|
||||||
Support for the ``generic_plan`` option on PostgreSQL 16+ was added.
|
Support for the ``generic_plan`` option on PostgreSQL 16+ was added.
|
||||||
|
|
||||||
|
.. versionchanged:: 5.2
|
||||||
|
|
||||||
|
Support for the ``memory`` and ``serialize`` options on PostgreSQL 17+ was
|
||||||
|
added.
|
||||||
|
|
||||||
.. _field-lookups:
|
.. _field-lookups:
|
||||||
|
|
||||||
``Field`` lookups
|
``Field`` lookups
|
||||||
|
|
|
@ -277,6 +277,9 @@ Models
|
||||||
longer required to be set on SQLite, which supports unlimited ``VARCHAR``
|
longer required to be set on SQLite, which supports unlimited ``VARCHAR``
|
||||||
columns.
|
columns.
|
||||||
|
|
||||||
|
* :meth:`.QuerySet.explain` now supports the ``memory`` and ``serialize``
|
||||||
|
options on PostgreSQL 17+.
|
||||||
|
|
||||||
Requests and Responses
|
Requests and Responses
|
||||||
~~~~~~~~~~~~~~~~~~~~~~
|
~~~~~~~~~~~~~~~~~~~~~~
|
||||||
|
|
||||||
|
|
|
@ -90,13 +90,24 @@ class ExplainTests(TestCase):
|
||||||
]
|
]
|
||||||
if connection.features.is_postgresql_16:
|
if connection.features.is_postgresql_16:
|
||||||
test_options.append({"generic_plan": True})
|
test_options.append({"generic_plan": True})
|
||||||
|
if connection.features.is_postgresql_17:
|
||||||
|
test_options.append({"memory": True})
|
||||||
|
test_options.append({"serialize": "TEXT", "analyze": True})
|
||||||
|
test_options.append({"serialize": "text", "analyze": True})
|
||||||
|
test_options.append({"serialize": "BINARY", "analyze": True})
|
||||||
|
test_options.append({"serialize": "binary", "analyze": True})
|
||||||
for options in test_options:
|
for options in test_options:
|
||||||
with self.subTest(**options), transaction.atomic():
|
with self.subTest(**options), transaction.atomic():
|
||||||
with CaptureQueriesContext(connection) as captured_queries:
|
with CaptureQueriesContext(connection) as captured_queries:
|
||||||
qs.explain(format="text", **options)
|
qs.explain(format="text", **options)
|
||||||
self.assertEqual(len(captured_queries), 1)
|
self.assertEqual(len(captured_queries), 1)
|
||||||
for name, value in options.items():
|
for name, value in options.items():
|
||||||
option = "{} {}".format(name.upper(), "true" if value else "false")
|
if isinstance(value, str):
|
||||||
|
option = "{} {}".format(name.upper(), value.upper())
|
||||||
|
else:
|
||||||
|
option = "{} {}".format(
|
||||||
|
name.upper(), "true" if value else "false"
|
||||||
|
)
|
||||||
self.assertIn(option, captured_queries[0]["sql"])
|
self.assertIn(option, captured_queries[0]["sql"])
|
||||||
|
|
||||||
@skipUnlessDBFeature("supports_select_union")
|
@skipUnlessDBFeature("supports_select_union")
|
||||||
|
|
Loading…
Reference in New Issue