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.py37
-rw-r--r--django/db/models/sql/datastructures.py8
-rw-r--r--django/db/models/sql/where.py25
3 files changed, 45 insertions, 25 deletions
diff --git a/django/db/models/sql/compiler.py b/django/db/models/sql/compiler.py
index 97c7ba2013..170bde1d42 100644
--- a/django/db/models/sql/compiler.py
+++ b/django/db/models/sql/compiler.py
@@ -4,7 +4,7 @@ import re
from functools import partial
from itertools import chain
-from django.core.exceptions import EmptyResultSet, FieldError
+from django.core.exceptions import EmptyResultSet, FieldError, FullResultSet
from django.db import DatabaseError, NotSupportedError
from django.db.models.constants import LOOKUP_SEP
from django.db.models.expressions import F, OrderBy, RawSQL, Ref, Value
@@ -169,7 +169,7 @@ class SQLCompiler:
expr = Ref(alias, expr)
try:
sql, params = self.compile(expr)
- except EmptyResultSet:
+ except (EmptyResultSet, FullResultSet):
continue
sql, params = expr.select_format(self, sql, params)
params_hash = make_hashable(params)
@@ -287,6 +287,8 @@ class SQLCompiler:
sql, params = "0", ()
else:
sql, params = self.compile(Value(empty_result_set_value))
+ except FullResultSet:
+ sql, params = self.compile(Value(True))
else:
sql, params = col.select_format(self, sql, params)
if alias is None and with_col_aliases:
@@ -721,9 +723,16 @@ class SQLCompiler:
raise
# Use a predicate that's always False.
where, w_params = "0 = 1", []
- having, h_params = (
- self.compile(self.having) if self.having is not None else ("", [])
- )
+ except FullResultSet:
+ where, w_params = "", []
+ try:
+ having, h_params = (
+ self.compile(self.having)
+ if self.having is not None
+ else ("", [])
+ )
+ except FullResultSet:
+ having, h_params = "", []
result = ["SELECT"]
params = []
@@ -1817,11 +1826,12 @@ class SQLDeleteCompiler(SQLCompiler):
)
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)
+ delete = "DELETE FROM %s" % self.quote_name_unless_alias(query.base_table)
+ try:
+ where, params = self.compile(query.where)
+ except FullResultSet:
+ return delete, ()
+ return f"{delete} WHERE {where}", tuple(params)
def as_sql(self):
"""
@@ -1906,8 +1916,11 @@ class SQLUpdateCompiler(SQLCompiler):
"UPDATE %s SET" % qn(table),
", ".join(values),
]
- where, params = self.compile(self.query.where)
- if where:
+ try:
+ where, params = self.compile(self.query.where)
+ except FullResultSet:
+ params = []
+ else:
result.append("WHERE %s" % where)
return " ".join(result), tuple(update_params + params)
diff --git a/django/db/models/sql/datastructures.py b/django/db/models/sql/datastructures.py
index 1edf040e82..069eb1a301 100644
--- a/django/db/models/sql/datastructures.py
+++ b/django/db/models/sql/datastructures.py
@@ -2,6 +2,7 @@
Useful auxiliary data structures for query construction. Not useful outside
the SQL domain.
"""
+from django.core.exceptions import FullResultSet
from django.db.models.sql.constants import INNER, LOUTER
@@ -100,8 +101,11 @@ class Join:
join_conditions.append("(%s)" % extra_sql)
params.extend(extra_params)
if self.filtered_relation:
- extra_sql, extra_params = compiler.compile(self.filtered_relation)
- if extra_sql:
+ try:
+ extra_sql, extra_params = compiler.compile(self.filtered_relation)
+ except FullResultSet:
+ pass
+ else:
join_conditions.append("(%s)" % extra_sql)
params.extend(extra_params)
if not join_conditions:
diff --git a/django/db/models/sql/where.py b/django/db/models/sql/where.py
index 63fdf58d9d..1928ba91b8 100644
--- a/django/db/models/sql/where.py
+++ b/django/db/models/sql/where.py
@@ -4,7 +4,7 @@ Code to manage the creation and SQL rendering of 'where' constraints.
import operator
from functools import reduce
-from django.core.exceptions import EmptyResultSet
+from django.core.exceptions import EmptyResultSet, FullResultSet
from django.db.models.expressions import Case, When
from django.db.models.lookups import Exact
from django.utils import tree
@@ -145,6 +145,8 @@ class WhereNode(tree.Node):
sql, params = compiler.compile(child)
except EmptyResultSet:
empty_needed -= 1
+ except FullResultSet:
+ full_needed -= 1
else:
if sql:
result.append(sql)
@@ -158,24 +160,25 @@ class WhereNode(tree.Node):
# counts.
if empty_needed == 0:
if self.negated:
- return "", []
+ raise FullResultSet
else:
raise EmptyResultSet
if full_needed == 0:
if self.negated:
raise EmptyResultSet
else:
- return "", []
+ raise FullResultSet
conn = " %s " % self.connector
sql_string = conn.join(result)
- if sql_string:
- if self.negated:
- # Some backends (Oracle at least) need parentheses
- # around the inner SQL in the negated case, even if the
- # inner SQL contains just a single expression.
- sql_string = "NOT (%s)" % sql_string
- elif len(result) > 1 or self.resolved:
- sql_string = "(%s)" % sql_string
+ if not sql_string:
+ raise FullResultSet
+ if self.negated:
+ # Some backends (Oracle at least) need parentheses around the inner
+ # SQL in the negated case, even if the inner SQL contains just a
+ # single expression.
+ sql_string = "NOT (%s)" % sql_string
+ elif len(result) > 1 or self.resolved:
+ sql_string = "(%s)" % sql_string
return sql_string, result_params
def get_group_by_cols(self):