diff options
| author | Mike Bayer <mike_mp@zzzcomputing.com> | 2007-02-01 03:18:08 +0000 |
|---|---|---|
| committer | Mike Bayer <mike_mp@zzzcomputing.com> | 2007-02-01 03:18:08 +0000 |
| commit | 154a831822c21ade7ff445381b1cacceb717e1e8 (patch) | |
| tree | 3bc40484ca45356317522fa1a7360e2911066131 /lib | |
| parent | 72f479b324c0b62a19e58c7b173a62b55c34a928 (diff) | |
| download | sqlalchemy-154a831822c21ade7ff445381b1cacceb717e1e8.tar.gz | |
- the "polymorphic_primaryjoin" again goes against the parent's non-polymorphic local table.
lazy load clause evaluation is plenty solid enough to handle it this time.
- the join_to() method on PropertyLoader takes the parent mapper as an argument and alisiazes
the primaryjoin against that mapper's selectable, so that the same primary join can be used against
the base mapper, any inheriting mapper, etc., whether or not it uses a polymorphic union (although
needs to be tested against alternate polymorphic unions added on subclasses). fixes [ticket:448]
Diffstat (limited to 'lib')
| -rw-r--r-- | lib/sqlalchemy/ext/selectresults.py | 4 | ||||
| -rw-r--r-- | lib/sqlalchemy/orm/properties.py | 40 | ||||
| -rw-r--r-- | lib/sqlalchemy/orm/query.py | 4 | ||||
| -rw-r--r-- | lib/sqlalchemy/orm/strategies.py | 2 |
4 files changed, 30 insertions, 20 deletions
diff --git a/lib/sqlalchemy/ext/selectresults.py b/lib/sqlalchemy/ext/selectresults.py index 23fd98893..3e7fa93c8 100644 --- a/lib/sqlalchemy/ext/selectresults.py +++ b/lib/sqlalchemy/ext/selectresults.py @@ -134,9 +134,9 @@ class SelectResults(object): for key in keys: prop = mapper.props[key] if outerjoin: - clause = clause.outerjoin(prop.select_table, prop.get_join()) + clause = clause.outerjoin(prop.select_table, prop.get_join(mapper)) else: - clause = clause.join(prop.select_table, prop.get_join()) + clause = clause.join(prop.select_table, prop.get_join(mapper)) mapper = prop.mapper return (clause, mapper) diff --git a/lib/sqlalchemy/orm/properties.py b/lib/sqlalchemy/orm/properties.py index 09c90c6ac..5e8fab807 100644 --- a/lib/sqlalchemy/orm/properties.py +++ b/lib/sqlalchemy/orm/properties.py @@ -87,6 +87,7 @@ class PropertyLoader(StrategizedProperty): self.collection_class = collection_class self.passive_deletes = passive_deletes self.remote_side = util.to_set(remote_side) + self._parent_join_cache = {} if cascade is not None: self.cascade = mapperutil.CascadeOptions(cascade) @@ -260,7 +261,6 @@ class PropertyLoader(StrategizedProperty): # as we will be using the polymorphic selectables (i.e. select_table argument to Mapper) to figure this out, # first create maps of all the "equivalent" columns, since polymorphic selectables will often munge # several "equivalent" columns (such as parent/child fk cols) into just one column. - parent_equivalents = self.parent._get_inherited_column_equivalents() target_equivalents = self.mapper._get_inherited_column_equivalents() # if the target mapper loads polymorphically, adapt the clauses to the target's selectable @@ -281,15 +281,7 @@ class PropertyLoader(StrategizedProperty): self.polymorphic_primaryjoin = self.primaryjoin.copy_container() self.polymorphic_secondaryjoin = self.secondaryjoin and self.secondaryjoin.copy_container() or None - # if the parent mapper loads polymorphically, adapt the clauses to the parent's selectable - if self.parent.select_table is not self.parent.mapped_table: - if self.direction is sync.ONETOMANY: - self.polymorphic_primaryjoin.accept_visitor(sql_util.ClauseAdapter(self.parent.select_table, exclude=self.foreignkey, equivalents=parent_equivalents)) - elif self.direction is sync.MANYTOONE: - self.polymorphic_primaryjoin.accept_visitor(sql_util.ClauseAdapter(self.parent.select_table, include=self.foreignkey, equivalents=parent_equivalents)) - elif self.secondaryjoin: - self.polymorphic_primaryjoin.accept_visitor(sql_util.ClauseAdapter(self.parent.select_table, exclude=self.foreignkey, equivalents=parent_equivalents)) - + #print "KEY", self.key, "PARENT", str(self.parent) #print "KEY", self.key, "REG PRIMARY JOIN", str(self.primaryjoin) #print "KEY", self.key, "POLY PRIMARY JOIN", str(self.polymorphic_primaryjoin) @@ -372,12 +364,30 @@ class PropertyLoader(StrategizedProperty): raise exceptions.ArgumentError("Cant determine relation direction for '%s' on mapper '%s' with primary join '%s' - no foreign key relationship is expressed within the join condition. Specify 'foreignkey' argument." %(self.key, str(self.parent), str(self.primaryjoin))) self.foreignkey = foreignkeys - def get_join(self): - if self.polymorphic_secondaryjoin is not None: - return self.polymorphic_primaryjoin & self.polymorphic_secondaryjoin - else: - return self.polymorphic_primaryjoin + def get_join(self, parent): + try: + return self._parent_join_cache[parent] + except KeyError: + parent_equivalents = parent._get_inherited_column_equivalents() + primaryjoin = self.polymorphic_primaryjoin.copy_container() + if self.secondaryjoin is not None: + secondaryjoin = self.polymorphic_secondaryjoin.copy_container() + else: + secondaryjoin = None + if self.direction is sync.ONETOMANY: + primaryjoin.accept_visitor(sql_util.ClauseAdapter(parent.select_table, exclude=self.foreignkey, equivalents=parent_equivalents)) + elif self.direction is sync.MANYTOONE: + primaryjoin.accept_visitor(sql_util.ClauseAdapter(parent.select_table, include=self.foreignkey, equivalents=parent_equivalents)) + elif self.secondaryjoin: + primaryjoin.accept_visitor(sql_util.ClauseAdapter(parent.select_table, exclude=self.foreignkey, equivalents=parent_equivalents)) + if secondaryjoin is not None: + j = primaryjoin & secondaryjoin + else: + j = primaryjoin + self._parent_join_cache[parent] = j + return j + def register_dependencies(self, uowcommit): if not self.viewonly: self._dependency_processor.register_dependencies(uowcommit) diff --git a/lib/sqlalchemy/orm/query.py b/lib/sqlalchemy/orm/query.py index adec69116..09863dbab 100644 --- a/lib/sqlalchemy/orm/query.py +++ b/lib/sqlalchemy/orm/query.py @@ -186,9 +186,9 @@ class Query(object): for key in keys: prop = mapper.props[key] if clause is None: - clause = prop.get_join() + clause = prop.get_join(mapper) else: - clause &= prop.get_join() + clause &= prop.get_join(mapper) mapper = prop.mapper return clause diff --git a/lib/sqlalchemy/orm/strategies.py b/lib/sqlalchemy/orm/strategies.py index 29b60a8f6..1cdf0b177 100644 --- a/lib/sqlalchemy/orm/strategies.py +++ b/lib/sqlalchemy/orm/strategies.py @@ -156,7 +156,7 @@ class LazyLoader(AbstractRelationLoader): def init(self): super(LazyLoader, self).init() (self.lazywhere, self.lazybinds, self.lazyreverse) = self._create_lazy_clause( - self.parent.select_table, + self.parent.local_table, self.mapper.select_table, self.polymorphic_primaryjoin, self.polymorphic_secondaryjoin, |
