summaryrefslogtreecommitdiff
path: root/django/db/models/sql
diff options
context:
space:
mode:
Diffstat (limited to 'django/db/models/sql')
-rw-r--r--django/db/models/sql/compiler.py44
-rw-r--r--django/db/models/sql/constants.py4
-rw-r--r--django/db/models/sql/subqueries.py12
3 files changed, 34 insertions, 26 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):
"""
diff --git a/django/db/models/sql/constants.py b/django/db/models/sql/constants.py
index fdfb2ea891..709405b0df 100644
--- a/django/db/models/sql/constants.py
+++ b/django/db/models/sql/constants.py
@@ -11,8 +11,10 @@ GET_ITERATOR_CHUNK_SIZE = 100
# How many results to expect from a cursor.execute call
MULTI = "multi"
SINGLE = "single"
-CURSOR = "cursor"
NO_RESULTS = "no results"
+# Rather than returning results, returns:
+CURSOR = "cursor"
+ROW_COUNT = "row count"
ORDER_DIR = {
"ASC": ("ASC", "DESC"),
diff --git a/django/db/models/sql/subqueries.py b/django/db/models/sql/subqueries.py
index f639eb8b82..b2810c8413 100644
--- a/django/db/models/sql/subqueries.py
+++ b/django/db/models/sql/subqueries.py
@@ -3,7 +3,11 @@ Query subclasses which provide extra functionality beyond simple data retrieval.
"""
from django.core.exceptions import FieldError
-from django.db.models.sql.constants import CURSOR, GET_ITERATOR_CHUNK_SIZE, NO_RESULTS
+from django.db.models.sql.constants import (
+ GET_ITERATOR_CHUNK_SIZE,
+ NO_RESULTS,
+ ROW_COUNT,
+)
from django.db.models.sql.query import Query
__all__ = ["DeleteQuery", "UpdateQuery", "InsertQuery", "AggregateQuery"]
@@ -17,11 +21,7 @@ class DeleteQuery(Query):
def do_query(self, table, where, using):
self.alias_map = {table: self.alias_map[table]}
self.where = where
- cursor = self.get_compiler(using).execute_sql(CURSOR)
- if cursor:
- with cursor:
- return cursor.rowcount
- return 0
+ return self.get_compiler(using).execute_sql(ROW_COUNT)
def delete_batch(self, pk_list, using):
"""