diff options
| author | Simon Charette <charette.s@gmail.com> | 2022-11-06 11:19:33 -0500 |
|---|---|---|
| committer | Mariusz Felisiak <felisiak.mariusz@gmail.com> | 2022-11-07 20:23:53 +0100 |
| commit | 76e37513e22f4d9a01c7f15eee36fe44388e6670 (patch) | |
| tree | 575decec7547c3c128857b0444f342452865a0f9 /django/db/models/sql | |
| parent | 4b702c832cd550fe682ef37a69e93866815b9123 (diff) | |
Refs #33374 -- Adjusted full match condition handling.
Adjusting WhereNode.as_sql() to raise an exception when encoutering a
full match just like with empty matches ensures that all case are
explicitly handled.
Diffstat (limited to 'django/db/models/sql')
| -rw-r--r-- | django/db/models/sql/compiler.py | 37 | ||||
| -rw-r--r-- | django/db/models/sql/datastructures.py | 8 | ||||
| -rw-r--r-- | django/db/models/sql/where.py | 25 |
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): |
