mirror of https://github.com/django/django.git
Fixed #20583 -- ORM always uses setup_joins() for join generation
There were a couple of places which used Query.join() directly. By using setup_joins() in these places the code is more DRY, and in addition there is no need to directly call field.get_joining_columns() unless the field is the given join_field from get_path_info(). This makes it easier to make sure a ForeignObject subclass generates joins correctly in all cases.
This commit is contained in:
parent
b3532f7df9
commit
aa22cbd51a
|
@ -631,12 +631,10 @@ class SQLCompiler(object):
|
|||
if not select_related_descend(f, restricted, requested,
|
||||
only_load.get(field_model)):
|
||||
continue
|
||||
table = f.rel.to._meta.db_table
|
||||
promote = nullable or f.null
|
||||
alias = self.query.join_parent_model(opts, model, root_alias, {})
|
||||
join_cols = f.get_joining_columns()
|
||||
alias = self.query.join((alias, table, join_cols),
|
||||
outer_if_first=promote, join_field=f)
|
||||
_, _, _, joins, _ = self.query.setup_joins(
|
||||
[f.name], opts, root_alias, outer_if_first=promote)
|
||||
alias = joins[-1]
|
||||
columns, aliases = self.get_default_columns(start_alias=alias,
|
||||
opts=f.rel.to._meta, as_pairs=True)
|
||||
self.query.related_select_cols.extend(
|
||||
|
@ -660,12 +658,9 @@ class SQLCompiler(object):
|
|||
only_load.get(model), reverse=True):
|
||||
continue
|
||||
|
||||
alias = self.query.join_parent_model(opts, f.rel.to, root_alias, {})
|
||||
table = model._meta.db_table
|
||||
alias = self.query.join(
|
||||
(alias, table, f.get_joining_columns(reverse_join=True)),
|
||||
outer_if_first=True, join_field=f
|
||||
)
|
||||
_, _, _, joins, _ = self.query.setup_joins(
|
||||
[f.related_query_name()], opts, root_alias, outer_if_first=True)
|
||||
alias = joins[-1]
|
||||
from_parent = (opts.model if issubclass(model, opts.model)
|
||||
else None)
|
||||
columns, aliases = self.get_default_columns(start_alias=alias,
|
||||
|
@ -677,7 +672,7 @@ class SQLCompiler(object):
|
|||
# Use True here because we are looking at the _reverse_ side of
|
||||
# the relation, which is always nullable.
|
||||
new_nullable = True
|
||||
|
||||
table = model._meta.db_table
|
||||
self.fill_related_selections(model._meta, table, cur_depth+1,
|
||||
next, restricted, new_nullable)
|
||||
|
||||
|
|
|
@ -926,10 +926,10 @@ class Query(object):
|
|||
"""
|
||||
if model in seen:
|
||||
return seen[model]
|
||||
int_opts = opts
|
||||
chain = opts.get_base_chain(model)
|
||||
if chain is None:
|
||||
return alias
|
||||
curr_opts = opts
|
||||
for int_model in chain:
|
||||
if int_model in seen:
|
||||
return seen[int_model]
|
||||
|
@ -937,14 +937,14 @@ class Query(object):
|
|||
# with no parents, assign the new options
|
||||
# object and skip to the next base in that
|
||||
# case
|
||||
if not int_opts.parents[int_model]:
|
||||
int_opts = int_model._meta
|
||||
if not curr_opts.parents[int_model]:
|
||||
curr_opts = int_model._meta
|
||||
continue
|
||||
link_field = int_opts.get_ancestor_link(int_model)
|
||||
int_opts = int_model._meta
|
||||
connection = (alias, int_opts.db_table, link_field.get_joining_columns())
|
||||
alias = seen[int_model] = self.join(connection, nullable=False,
|
||||
join_field=link_field)
|
||||
link_field = curr_opts.get_ancestor_link(int_model)
|
||||
_, _, _, joins, _ = self.setup_joins(
|
||||
[link_field.name], curr_opts, alias)
|
||||
curr_opts = int_model._meta
|
||||
alias = seen[int_model] = joins[-1]
|
||||
return alias or seen[None]
|
||||
|
||||
def remove_inherited_models(self):
|
||||
|
@ -1321,7 +1321,7 @@ class Query(object):
|
|||
return path, final_field, targets
|
||||
|
||||
def setup_joins(self, names, opts, alias, can_reuse=None, allow_many=True,
|
||||
allow_explicit_fk=False):
|
||||
allow_explicit_fk=False, outer_if_first=False):
|
||||
"""
|
||||
Compute the necessary table joins for the passage through the fields
|
||||
given in 'names'. 'opts' is the Options class for the current model
|
||||
|
@ -1364,8 +1364,9 @@ class Query(object):
|
|||
nullable = True
|
||||
connection = alias, opts.db_table, join.join_field.get_joining_columns()
|
||||
reuse = can_reuse if join.m2m else None
|
||||
alias = self.join(connection, reuse=reuse,
|
||||
nullable=nullable, join_field=join.join_field)
|
||||
alias = self.join(
|
||||
connection, reuse=reuse, nullable=nullable, join_field=join.join_field,
|
||||
outer_if_first=outer_if_first)
|
||||
joins.append(alias)
|
||||
if hasattr(final_field, 'field'):
|
||||
final_field = final_field.field
|
||||
|
|
Loading…
Reference in New Issue