diff options
Diffstat (limited to 'django/db/models/sql/compiler.py')
| -rw-r--r-- | django/db/models/sql/compiler.py | 39 |
1 files changed, 30 insertions, 9 deletions
diff --git a/django/db/models/sql/compiler.py b/django/db/models/sql/compiler.py index 9493d0dc3c..638813333d 100644 --- a/django/db/models/sql/compiler.py +++ b/django/db/models/sql/compiler.py @@ -7,13 +7,16 @@ from django.core.exceptions import EmptyResultSet, FieldError from django.db.models.constants import LOOKUP_SEP from django.db.models.expressions import OrderBy, Random, RawSQL, Ref, Value from django.db.models.functions import Cast -from django.db.models.query_utils import QueryWrapper, select_related_descend +from django.db.models.query_utils import ( + Q, QueryWrapper, select_related_descend, +) from django.db.models.sql.constants import ( CURSOR, GET_ITERATOR_CHUNK_SIZE, MULTI, NO_RESULTS, ORDER_DIR, SINGLE, ) from django.db.models.sql.query import Query, get_order_dir from django.db.transaction import TransactionManagementError from django.db.utils import DatabaseError, NotSupportedError +from django.utils.functional import cached_property from django.utils.hashable import make_hashable @@ -1344,19 +1347,37 @@ class SQLInsertCompiler(SQLCompiler): class SQLDeleteCompiler(SQLCompiler): + @cached_property + def single_alias(self): + return sum(self.query.alias_refcount[t] > 0 for t in self.query.alias_map) == 1 + + def _as_sql(self, query): + result = [ + 'DELETE FROM %s' % self.quote_name_unless_alias(query.base_table) + ] + where, params = self.compile(query.where) + if where: + result.append('WHERE %s' % where) + return ' '.join(result), tuple(params) + def as_sql(self): """ Create the SQL for this query. Return the SQL string and list of parameters. """ - assert len([t for t in self.query.alias_map if self.query.alias_refcount[t] > 0]) == 1, \ - "Can only delete from one table at a time." - qn = self.quote_name_unless_alias - result = ['DELETE FROM %s' % qn(self.query.base_table)] - where, params = self.compile(self.query.where) - if where: - result.append('WHERE %s' % where) - return ' '.join(result), tuple(params) + if self.single_alias: + return self._as_sql(self.query) + innerq = self.query.clone() + innerq.__class__ = Query + innerq.clear_select_clause() + pk = self.query.model._meta.pk + innerq.select = [ + pk.get_col(self.query.get_initial_alias()) + ] + outerq = Query(self.query.model) + outerq.where = self.query.where_class() + outerq.add_q(Q(pk__in=innerq)) + return self._as_sql(outerq) class SQLUpdateCompiler(SQLCompiler): |
