summaryrefslogtreecommitdiff
path: root/lib/sqlalchemy
diff options
context:
space:
mode:
authorMike Bayer <mike_mp@zzzcomputing.com>2017-01-16 13:34:55 -0500
committerMike Bayer <mike_mp@zzzcomputing.com>2017-03-16 12:34:40 -0400
commit63a7b2d2d9402b06f9bc7745eed2d98ae9f8b11c (patch)
treeddc4a454eb22548a009eb33f90a08331cc0523d3 /lib/sqlalchemy
parent2bfe19152d49b969acdc4607bf7c33727f796f5a (diff)
downloadsqlalchemy-63a7b2d2d9402b06f9bc7745eed2d98ae9f8b11c.tar.gz
Annotate parentmapper in primaryjoin / secondaryjoin
This patch applies the "parentmapper" annotation to the columns in the primaryjoin/secondaryjoin, but more dramatically, also removes all the "deannotate" steps that were historically applied to the relationship primaryjoin/secondaryjoin. These deannotation steps were left over from the initial implementations of annotations where the behaviors were not as reliable. By ensuring these annotations are present, the evaluator no longer needs to do a name-based lookup when it sees a column that has no "parentmapper", because it can be assured this is not a mapped column. This fixes the issue where the expression were based on a relationship primaryjoin but the name of a column in the join condition didn't match the attribute name. Change-Id: I8c1d4594116d4109fef314a87c96a24d2efa0058 Fixes: #3366
Diffstat (limited to 'lib/sqlalchemy')
-rw-r--r--lib/sqlalchemy/orm/evaluator.py4
-rw-r--r--lib/sqlalchemy/orm/relationships.py32
2 files changed, 19 insertions, 17 deletions
diff --git a/lib/sqlalchemy/orm/evaluator.py b/lib/sqlalchemy/orm/evaluator.py
index 95a9e9b91..aff6718d3 100644
--- a/lib/sqlalchemy/orm/evaluator.py
+++ b/lib/sqlalchemy/orm/evaluator.py
@@ -59,7 +59,9 @@ class EvaluatorCompiler(object):
)
key = parentmapper._columntoproperty[clause].key
else:
- key = clause.key
+ raise UnevaluatableError(
+ "Cannot evaluate column: %s" % clause
+ )
get_corresponding_attr = operator.attrgetter(key)
return lambda obj: get_corresponding_attr(obj)
diff --git a/lib/sqlalchemy/orm/relationships.py b/lib/sqlalchemy/orm/relationships.py
index 1298e8880..dacb68b45 100644
--- a/lib/sqlalchemy/orm/relationships.py
+++ b/lib/sqlalchemy/orm/relationships.py
@@ -1727,8 +1727,8 @@ class RelationshipProperty(StrategizedProperty):
support_sync=not self.viewonly,
can_be_synced_fn=self._columns_are_mapped
)
- self.primaryjoin = jc.deannotated_primaryjoin
- self.secondaryjoin = jc.deannotated_secondaryjoin
+ self.primaryjoin = jc.primaryjoin
+ self.secondaryjoin = jc.secondaryjoin
self.direction = jc.direction
self.local_remote_pairs = jc.local_remote_pairs
self.remote_side = jc.remote_columns
@@ -1987,6 +1987,7 @@ class JoinCondition(object):
self._annotate_fks()
self._annotate_remote()
self._annotate_local()
+ self._annotate_parentmapper()
self._setup_pairs()
self._check_foreign_cols(self.primaryjoin, True)
if self.secondaryjoin is not None:
@@ -2450,6 +2451,19 @@ class JoinCondition(object):
self.primaryjoin, {}, locals_
)
+ def _annotate_parentmapper(self):
+ if self.prop is None:
+ return
+
+ def parentmappers_(elem):
+ if "remote" in elem._annotations:
+ return elem._annotate({"parentmapper": self.prop.mapper})
+ elif "local" in elem._annotations:
+ return elem._annotate({"parentmapper": self.prop.parent})
+ self.primaryjoin = visitors.replacement_traverse(
+ self.primaryjoin, {}, parentmappers_
+ )
+
def _check_remote_side(self):
if not self.local_remote_pairs:
raise sa_exc.ArgumentError(
@@ -2707,17 +2721,6 @@ class JoinCondition(object):
def foreign_key_columns(self):
return self._gather_join_annotations("foreign")
- @util.memoized_property
- def deannotated_primaryjoin(self):
- return _deep_deannotate(self.primaryjoin)
-
- @util.memoized_property
- def deannotated_secondaryjoin(self):
- if self.secondaryjoin is not None:
- return _deep_deannotate(self.secondaryjoin)
- else:
- return None
-
def _gather_join_annotations(self, annotation):
s = set(
self._gather_columns_with_annotation(
@@ -2856,9 +2859,6 @@ class JoinCondition(object):
bind_to_col = dict((binds[col].key, col) for col in binds)
- # this is probably not necessary
- lazywhere = _deep_deannotate(lazywhere)
-
return lazywhere, bind_to_col, equated_columns