mirror of
https://github.com/django/django.git
synced 2025-12-03 08:32:59 +00:00
Refs #11964 -- Removed SimpleCol in favor of Query(alias_cols).
This prevent having to pass simple_col through multiple function calls by defining whether or not references should be resolved with aliases at the Query level.
This commit is contained in:
parent
f69b32782e
commit
306b687520
6 changed files with 66 additions and 94 deletions
|
|
@ -23,9 +23,7 @@ from django.core.exceptions import (
|
|||
from django.db import DEFAULT_DB_ALIAS, NotSupportedError, connections
|
||||
from django.db.models.aggregates import Count
|
||||
from django.db.models.constants import LOOKUP_SEP
|
||||
from django.db.models.expressions import (
|
||||
BaseExpression, Col, F, OuterRef, Ref, SimpleCol,
|
||||
)
|
||||
from django.db.models.expressions import BaseExpression, Col, F, OuterRef, Ref
|
||||
from django.db.models.fields import Field
|
||||
from django.db.models.fields.related_lookups import MultiColSource
|
||||
from django.db.models.lookups import Lookup
|
||||
|
|
@ -69,12 +67,6 @@ JoinInfo = namedtuple(
|
|||
)
|
||||
|
||||
|
||||
def _get_col(target, field, alias, simple_col):
|
||||
if simple_col:
|
||||
return SimpleCol(target, field)
|
||||
return target.get_col(alias, field)
|
||||
|
||||
|
||||
class RawQuery:
|
||||
"""A single raw SQL query."""
|
||||
|
||||
|
|
@ -151,7 +143,7 @@ class Query(BaseExpression):
|
|||
|
||||
compiler = 'SQLCompiler'
|
||||
|
||||
def __init__(self, model, where=WhereNode):
|
||||
def __init__(self, model, where=WhereNode, alias_cols=True):
|
||||
self.model = model
|
||||
self.alias_refcount = {}
|
||||
# alias_map is the most important data structure regarding joins.
|
||||
|
|
@ -160,6 +152,8 @@ class Query(BaseExpression):
|
|||
# the table name) and the value is a Join-like object (see
|
||||
# sql.datastructures.Join for more information).
|
||||
self.alias_map = {}
|
||||
# Whether to provide alias to columns during reference resolving.
|
||||
self.alias_cols = alias_cols
|
||||
# Sometimes the query contains references to aliases in outer queries (as
|
||||
# a result of split_exclude). Correct alias quoting needs to know these
|
||||
# aliases too.
|
||||
|
|
@ -360,6 +354,11 @@ class Query(BaseExpression):
|
|||
clone.change_aliases(change_map)
|
||||
return clone
|
||||
|
||||
def _get_col(self, target, field, alias):
|
||||
if not self.alias_cols:
|
||||
alias = None
|
||||
return target.get_col(alias, field)
|
||||
|
||||
def rewrite_cols(self, annotation, col_cnt):
|
||||
# We must make sure the inner query has the referred columns in it.
|
||||
# If we are aggregating over an annotation, then Django uses Ref()
|
||||
|
|
@ -1050,17 +1049,16 @@ class Query(BaseExpression):
|
|||
sql = '(%s)' % sql
|
||||
return sql, params
|
||||
|
||||
def resolve_lookup_value(self, value, can_reuse, allow_joins, simple_col):
|
||||
def resolve_lookup_value(self, value, can_reuse, allow_joins):
|
||||
if hasattr(value, 'resolve_expression'):
|
||||
kwargs = {'reuse': can_reuse, 'allow_joins': allow_joins}
|
||||
if isinstance(value, F):
|
||||
kwargs['simple_col'] = simple_col
|
||||
value = value.resolve_expression(self, **kwargs)
|
||||
value = value.resolve_expression(
|
||||
self, reuse=can_reuse, allow_joins=allow_joins,
|
||||
)
|
||||
elif isinstance(value, (list, tuple)):
|
||||
# The items of the iterable may be expressions and therefore need
|
||||
# to be resolved independently.
|
||||
return type(value)(
|
||||
self.resolve_lookup_value(sub_value, can_reuse, allow_joins, simple_col)
|
||||
self.resolve_lookup_value(sub_value, can_reuse, allow_joins)
|
||||
for sub_value in value
|
||||
)
|
||||
return value
|
||||
|
|
@ -1192,7 +1190,7 @@ class Query(BaseExpression):
|
|||
|
||||
def build_filter(self, filter_expr, branch_negated=False, current_negated=False,
|
||||
can_reuse=None, allow_joins=True, split_subq=True,
|
||||
reuse_with_filtered_relation=False, simple_col=False):
|
||||
reuse_with_filtered_relation=False):
|
||||
"""
|
||||
Build a WhereNode for a single filter clause but don't add it
|
||||
to this Query. Query.add_q() will then add this filter to the where
|
||||
|
|
@ -1244,7 +1242,7 @@ class Query(BaseExpression):
|
|||
raise FieldError("Joined field references are not permitted in this query")
|
||||
|
||||
pre_joins = self.alias_refcount.copy()
|
||||
value = self.resolve_lookup_value(value, can_reuse, allow_joins, simple_col)
|
||||
value = self.resolve_lookup_value(value, can_reuse, allow_joins)
|
||||
used_joins = {k for k, v in self.alias_refcount.items() if v > pre_joins.get(k, 0)}
|
||||
|
||||
self.check_filterable(value)
|
||||
|
|
@ -1289,11 +1287,11 @@ class Query(BaseExpression):
|
|||
if num_lookups > 1:
|
||||
raise FieldError('Related Field got invalid lookup: {}'.format(lookups[0]))
|
||||
if len(targets) == 1:
|
||||
col = _get_col(targets[0], join_info.final_field, alias, simple_col)
|
||||
col = self._get_col(targets[0], join_info.final_field, alias)
|
||||
else:
|
||||
col = MultiColSource(alias, targets, join_info.targets, join_info.final_field)
|
||||
else:
|
||||
col = _get_col(targets[0], join_info.final_field, alias, simple_col)
|
||||
col = self._get_col(targets[0], join_info.final_field, alias)
|
||||
|
||||
condition = self.build_lookup(lookups, col, value)
|
||||
lookup_type = condition.lookup_name
|
||||
|
|
@ -1315,7 +1313,7 @@ class Query(BaseExpression):
|
|||
# <=>
|
||||
# NOT (col IS NOT NULL AND col = someval).
|
||||
lookup_class = targets[0].get_lookup('isnull')
|
||||
col = _get_col(targets[0], join_info.targets[0], alias, simple_col)
|
||||
col = self._get_col(targets[0], join_info.targets[0], alias)
|
||||
clause.add(lookup_class(col, False), AND)
|
||||
return clause, used_joins if not require_outer else ()
|
||||
|
||||
|
|
@ -1340,11 +1338,10 @@ class Query(BaseExpression):
|
|||
self.demote_joins(existing_inner)
|
||||
|
||||
def build_where(self, q_object):
|
||||
return self._add_q(q_object, used_aliases=set(), allow_joins=False, simple_col=True)[0]
|
||||
return self._add_q(q_object, used_aliases=set(), allow_joins=False)[0]
|
||||
|
||||
def _add_q(self, q_object, used_aliases, branch_negated=False,
|
||||
current_negated=False, allow_joins=True, split_subq=True,
|
||||
simple_col=False):
|
||||
current_negated=False, allow_joins=True, split_subq=True):
|
||||
"""Add a Q-object to the current filter."""
|
||||
connector = q_object.connector
|
||||
current_negated = current_negated ^ q_object.negated
|
||||
|
|
@ -1356,13 +1353,13 @@ class Query(BaseExpression):
|
|||
if isinstance(child, Node):
|
||||
child_clause, needed_inner = self._add_q(
|
||||
child, used_aliases, branch_negated,
|
||||
current_negated, allow_joins, split_subq, simple_col)
|
||||
current_negated, allow_joins, split_subq)
|
||||
joinpromoter.add_votes(needed_inner)
|
||||
else:
|
||||
child_clause, needed_inner = self.build_filter(
|
||||
child, can_reuse=used_aliases, branch_negated=branch_negated,
|
||||
current_negated=current_negated, allow_joins=allow_joins,
|
||||
split_subq=split_subq, simple_col=simple_col,
|
||||
split_subq=split_subq,
|
||||
)
|
||||
joinpromoter.add_votes(needed_inner)
|
||||
if child_clause:
|
||||
|
|
@ -1639,7 +1636,7 @@ class Query(BaseExpression):
|
|||
else:
|
||||
yield from cls._gen_col_aliases(expr.get_source_expressions())
|
||||
|
||||
def resolve_ref(self, name, allow_joins=True, reuse=None, summarize=False, simple_col=False):
|
||||
def resolve_ref(self, name, allow_joins=True, reuse=None, summarize=False):
|
||||
if not allow_joins and LOOKUP_SEP in name:
|
||||
raise FieldError("Joined field references are not permitted in this query")
|
||||
annotation = self.annotations.get(name)
|
||||
|
|
@ -1673,8 +1670,7 @@ class Query(BaseExpression):
|
|||
join_info.transform_function(targets[0], final_alias)
|
||||
if reuse is not None:
|
||||
reuse.update(join_list)
|
||||
col = _get_col(targets[0], join_info.targets[0], join_list[-1], simple_col)
|
||||
return col
|
||||
return self._get_col(targets[0], join_info.targets[0], join_list[-1])
|
||||
|
||||
def split_exclude(self, filter_expr, can_reuse, names_with_path):
|
||||
"""
|
||||
|
|
|
|||
Loading…
Add table
Add a link
Reference in a new issue