summaryrefslogtreecommitdiff
path: root/lib
diff options
context:
space:
mode:
authorMike Bayer <mike_mp@zzzcomputing.com>2007-02-01 03:18:08 +0000
committerMike Bayer <mike_mp@zzzcomputing.com>2007-02-01 03:18:08 +0000
commit154a831822c21ade7ff445381b1cacceb717e1e8 (patch)
tree3bc40484ca45356317522fa1a7360e2911066131 /lib
parent72f479b324c0b62a19e58c7b173a62b55c34a928 (diff)
downloadsqlalchemy-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.py4
-rw-r--r--lib/sqlalchemy/orm/properties.py40
-rw-r--r--lib/sqlalchemy/orm/query.py4
-rw-r--r--lib/sqlalchemy/orm/strategies.py2
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,