Skip to content
Open
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
41 changes: 38 additions & 3 deletions tortoise/queryset.py
Original file line number Diff line number Diff line change
Expand Up @@ -1428,15 +1428,50 @@ def __init__(

def _make_query(self) -> None:
self.query = copy(self.model._meta.basequery)
if self.capabilities.support_update_limit_order_by and self._limit:
self.query._limit = self.query._wrapper_cls(self._limit)
self.resolve_filters()

# If joins are detected, rewrite into an IN subquery to avoid JOINs in DELETE
if self._joined_tables:
pk_column = self.model._meta.db_pk_column

# Create a pristine, completely separate SELECT query builder
subquery = self._db.query_class.from_(self.model._meta.basetable).select(
self.model._meta.basetable[pk_column]
)

# Transfer the resolved wheres and havings criteria from our filter resolution
subquery._wheres = self.query._wheres
subquery._havings = self.query._havings

# Apply joins directly to the subquery builder
subquery._joins = self.query._joins

# Re-apply limits and sorting to the subquery if needed
if self._limit:
subquery._limit = subquery._wrapper_cls(self._limit)

self.resolve_ordering(
model=self.model,
table=self.model._meta.basetable,
orderings=self._orderings,
annotations=self._annotations,
)
self.resolve_filters()
subquery._orderbys = self.query._orderbys

# Reconstruct clean pristine delete statement pointing to our subquery
self.query = copy(self.model._meta.basequery)
self.query = self.query.where(self.model._meta.basetable[pk_column].isin(subquery))
else:
# Traditional optimization path if no backward relations/joins exist
if self.capabilities.support_update_limit_order_by and self._limit:
self.query._limit = self.query._wrapper_cls(self._limit)
self.resolve_ordering(
model=self.model,
table=self.model._meta.basetable,
orderings=self._orderings,
annotations=self._annotations,
)

self.query._delete_from = True
return

Expand Down