|
@@ -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):
|