summaryrefslogtreecommitdiff
path: root/lib/sqlalchemy
diff options
context:
space:
mode:
authorMike Bayer <mike_mp@zzzcomputing.com>2009-01-29 06:40:29 +0000
committerMike Bayer <mike_mp@zzzcomputing.com>2009-01-29 06:40:29 +0000
commit966119f4d31ec511930024ad4b12d5e53cc8a6ec (patch)
tree010f1cda2d05da08096cd40126656716f5157edc /lib/sqlalchemy
parentb2ee806b6f4188db42b01fce6e538928d37f507d (diff)
downloadsqlalchemy-966119f4d31ec511930024ad4b12d5e53cc8a6ec.tar.gz
- improvements to the "determine direction" logic of
relation() such that the direction of tricky situations like mapper(A.join(B)) -> relation-> mapper(B) can be determined.
Diffstat (limited to 'lib/sqlalchemy')
-rw-r--r--lib/sqlalchemy/orm/properties.py52
1 files changed, 34 insertions, 18 deletions
diff --git a/lib/sqlalchemy/orm/properties.py b/lib/sqlalchemy/orm/properties.py
index f05613f5c..73e794370 100644
--- a/lib/sqlalchemy/orm/properties.py
+++ b/lib/sqlalchemy/orm/properties.py
@@ -889,29 +889,45 @@ class RelationProperty(StrategizedProperty):
self.direction = MANYTOONE
else:
- for mappedtable, parenttable in [(self.mapper.mapped_table, self.parent.mapped_table), (self.mapper.local_table, self.parent.local_table)]:
- onetomany = [c for c in self._foreign_keys if mappedtable.c.contains_column(c)]
- manytoone = [c for c in self._foreign_keys if parenttable.c.contains_column(c)]
-
- if not onetomany and not manytoone:
- raise sa_exc.ArgumentError(
- "Can't determine relation direction for relationship '%s' "
- "- foreign key columns are present in neither the "
- "parent nor the child's mapped tables" %(str(self)))
- elif onetomany and manytoone:
- continue
- elif onetomany:
+ foreign_keys = [f for c, f in self.synchronize_pairs]
+
+ parentcols = util.column_set(self.parent.mapped_table.c)
+ targetcols = util.column_set(self.mapper.mapped_table.c)
+
+ # fk collection which suggests ONETOMANY.
+ onetomany_fk = targetcols.intersection(foreign_keys)
+
+ # fk collection which suggests MANYTOONE.
+ manytoone_fk = parentcols.intersection(foreign_keys)
+
+ if not onetomany_fk and not manytoone_fk:
+ raise sa_exc.ArgumentError(
+ "Can't determine relation direction for relationship '%s' "
+ "- foreign key columns are present in neither the "
+ "parent nor the child's mapped tables" % self )
+
+ elif onetomany_fk and manytoone_fk:
+ # fks on both sides. do the same
+ # test only based on the local side.
+ referents = [c for c, f in self.synchronize_pairs]
+ onetomany_local = parentcols.intersection(referents)
+ manytoone_local = targetcols.intersection(referents)
+
+ if onetomany_local and not manytoone_local:
self.direction = ONETOMANY
- break
- elif manytoone:
+ elif manytoone_local and not onetomany_local:
self.direction = MANYTOONE
- break
- else:
+ elif onetomany_fk:
+ self.direction = ONETOMANY
+ elif manytoone_fk:
+ self.direction = MANYTOONE
+
+ if not self.direction:
raise sa_exc.ArgumentError(
"Can't determine relation direction for relationship '%s' "
"- foreign key columns are present in both the parent and "
"the child's mapped tables. Specify 'foreign_keys' "
- "argument." % (str(self)))
+ "argument." % self)
if self.cascade.delete_orphan and not self.single_parent and \
(self.direction is MANYTOMANY or self.direction is MANYTOONE):
@@ -1001,7 +1017,7 @@ class RelationProperty(StrategizedProperty):
def _refers_to_parent_table(self):
- return self.parent.mapped_table is self.target or self.parent.mapped_table is self.target
+ return self.parent.mapped_table is self.target
def _is_self_referential(self):
return self.mapper.common_parent(self.parent)