summaryrefslogtreecommitdiff
path: root/django/db/models/sql/compiler.py
diff options
context:
space:
mode:
authorRaphael Gaschignard <raphael@rtpg.co>2024-11-19 14:50:24 +1000
committerSarah Boyce <42296566+sarahboyce@users.noreply.github.com>2025-01-03 15:07:02 +0100
commitddefc3fed1cf1f0d3fab455babbbc009b76e4196 (patch)
tree0e6084422b038e819a825370334fc6da2a55bb7c /django/db/models/sql/compiler.py
parentd97cacc2aedf948f7c557d0231e3b410905678b2 (diff)
Fixed #35918 -- Added support for execute_sql to directly return row counts.
Diffstat (limited to 'django/db/models/sql/compiler.py')
-rw-r--r--django/db/models/sql/compiler.py44
1 files changed, 25 insertions, 19 deletions
diff --git a/django/db/models/sql/compiler.py b/django/db/models/sql/compiler.py
index 49c5d301cc..5bb491d823 100644
--- a/django/db/models/sql/compiler.py
+++ b/django/db/models/sql/compiler.py
@@ -19,6 +19,7 @@ from django.db.models.sql.constants import (
MULTI,
NO_RESULTS,
ORDER_DIR,
+ ROW_COUNT,
SINGLE,
)
from django.db.models.sql.query import Query, get_order_dir
@@ -1596,15 +1597,15 @@ class SQLCompiler:
):
"""
Run the query against the database and return the result(s). The
- return value is a single data item if result_type is SINGLE, or an
- iterator over the results if the result_type is MULTI.
+ return value depends on the value of result_type.
- result_type is either MULTI (use fetchmany() to retrieve all rows),
- SINGLE (only retrieve a single row), or None. In this last case, the
- cursor is returned if any query is executed, since it's used by
- subclasses such as InsertQuery). It's possible, however, that no query
- is needed, as the filters describe an empty set. In that case, None is
- returned, to avoid any unnecessary database interaction.
+ When result_type is:
+ - MULTI: Retrieves all rows using fetchmany(). Wraps in an iterator for
+ chunked reads when supported.
+ - SINGLE: Retrieves a single row using fetchone().
+ - ROW_COUNT: Retrieves the number of rows in the result.
+ - CURSOR: Runs the query, and returns the cursor object. It is the
+ caller's responsibility to close the cursor.
"""
result_type = result_type or NO_RESULTS
try:
@@ -1627,6 +1628,11 @@ class SQLCompiler:
cursor.close()
raise
+ if result_type == ROW_COUNT:
+ try:
+ return cursor.rowcount
+ finally:
+ cursor.close()
if result_type == CURSOR:
# Give the caller the cursor to process and close.
return cursor
@@ -2069,19 +2075,19 @@ class SQLUpdateCompiler(SQLCompiler):
non-empty query that is executed. Row counts for any subsequent,
related queries are not available.
"""
- cursor = super().execute_sql(result_type)
- try:
- rows = cursor.rowcount if cursor else 0
- is_empty = cursor is None
- finally:
- if cursor:
- cursor.close()
+ row_count = super().execute_sql(result_type)
+ is_empty = row_count is None
+ row_count = row_count or 0
+
for query in self.query.get_related_updates():
- aux_rows = query.get_compiler(self.using).execute_sql(result_type)
- if is_empty and aux_rows:
- rows = aux_rows
+ # If the result_type is NO_RESULTS then the aux_row_count is None.
+ aux_row_count = query.get_compiler(self.using).execute_sql(result_type)
+ if is_empty and aux_row_count:
+ # Returns the row count for any related updates as the number of
+ # rows updated.
+ row_count = aux_row_count
is_empty = False
- return rows
+ return row_count
def pre_sql_setup(self):
"""