summaryrefslogtreecommitdiff
path: root/lib
diff options
context:
space:
mode:
authorMike Bayer <mike_mp@zzzcomputing.com>2007-01-20 12:31:27 +0000
committerMike Bayer <mike_mp@zzzcomputing.com>2007-01-20 12:31:27 +0000
commita31979937223c68f395ee0704593c9150f10e86b (patch)
tree38631a67d1116c1014a894f940db540bbcc9845e /lib
parent19de5346c2ce305327025d48ae5ed0d9626598ad (diff)
downloadsqlalchemy-a31979937223c68f395ee0704593c9150f10e86b.tar.gz
- tightened down conditions used to locate "relation direction", associating
the "foreignkey" of the relationship with the "primaryjoin". the column match now must be exact, not just "corresponding". this enables self-referential relationships on a polymorphic mapper. - a little bit of improvement to the concept of a "concrete" inheritance mapping, though that concept is not well fleshed out yet (added test case to support concrete mappers on top of a polymorphic base).
Diffstat (limited to 'lib')
-rw-r--r--lib/sqlalchemy/orm/mapper.py4
-rw-r--r--lib/sqlalchemy/orm/properties.py4
-rw-r--r--lib/sqlalchemy/orm/strategies.py2
-rw-r--r--lib/sqlalchemy/sql.py10
4 files changed, 15 insertions, 5 deletions
diff --git a/lib/sqlalchemy/orm/mapper.py b/lib/sqlalchemy/orm/mapper.py
index 872f3d121..8efd70967 100644
--- a/lib/sqlalchemy/orm/mapper.py
+++ b/lib/sqlalchemy/orm/mapper.py
@@ -462,7 +462,7 @@ class Mapper(object):
if self.inherits is not None:
for key, prop in self.inherits.__props.iteritems():
- if not self.__props.has_key(key):
+ if not self.__props.has_key(key) and (not self.concrete or not isinstance(prop, ColumnProperty)):
prop.adapt_to_inherited(key, self)
# load properties from the main table object,
@@ -516,6 +516,8 @@ class Mapper(object):
the columns of select_table should encompass all the columns of the mapped_table either directly
or through proxying relationships."""
if self.select_table is not self.mapped_table:
+ if self.polymorphic_identity is None:
+ raise exceptions.ArgumentError("Could not locate a polymorphic_identity field for mapper '%s'. This field is required for polymorphic mappers" % str(self))
props = {}
if self.properties is not None:
for key, prop in self.properties.iteritems():
diff --git a/lib/sqlalchemy/orm/properties.py b/lib/sqlalchemy/orm/properties.py
index 452af04cc..db43a8e27 100644
--- a/lib/sqlalchemy/orm/properties.py
+++ b/lib/sqlalchemy/orm/properties.py
@@ -274,8 +274,8 @@ class PropertyLoader(StrategizedProperty):
else:
return sync.MANYTOONE
else:
- onetomany = len([c for c in self.foreignkey if self.mapper.unjoined_table.corresponding_column(c, False) is not None])
- manytoone = len([c for c in self.foreignkey if self.parent.unjoined_table.corresponding_column(c, False) is not None])
+ onetomany = len([c for c in self.foreignkey if self.mapper.unjoined_table.corresponding_column(c, False, require_exact=True) is not None])
+ manytoone = len([c for c in self.foreignkey if self.parent.unjoined_table.corresponding_column(c, False, require_exact=True) is not None])
if not onetomany and not manytoone:
raise exceptions.ArgumentError("Cant determine relation direction for '%s' on mapper '%s' with primary join '%s' - foreign key columns are not present in neither the parent nor the child's mapped tables" %(self.key, str(self.parent), str(self.primaryjoin)))
elif onetomany and manytoone:
diff --git a/lib/sqlalchemy/orm/strategies.py b/lib/sqlalchemy/orm/strategies.py
index 54590f4ad..88a22bbcd 100644
--- a/lib/sqlalchemy/orm/strategies.py
+++ b/lib/sqlalchemy/orm/strategies.py
@@ -248,7 +248,7 @@ class LazyLoader(AbstractRelationLoader):
binds = {}
reverse = {}
def column_in_table(table, column):
- return table.corresponding_column(column, raiseerr=False, keys_ok=False) is not None
+ return table.corresponding_column(column, raiseerr=False, keys_ok=False, require_exact=True) is not None
if remote_side is None or len(remote_side) == 0:
remote_side = foreignkey
diff --git a/lib/sqlalchemy/sql.py b/lib/sqlalchemy/sql.py
index f944b468d..5b960546e 100644
--- a/lib/sqlalchemy/sql.py
+++ b/lib/sqlalchemy/sql.py
@@ -728,9 +728,17 @@ class FromClause(Selectable):
if not hasattr(self, '_oid_column'):
self._oid_column = self._locate_oid_column()
return self._oid_column
- def corresponding_column(self, column, raiseerr=True, keys_ok=False):
+ def corresponding_column(self, column, raiseerr=True, keys_ok=False, require_exact=False):
"""given a ColumnElement, return the ColumnElement object from this
Selectable which corresponds to that original Column via a proxy relationship."""
+ if require_exact:
+ if self.columns.get(column.key) is column:
+ return column
+ else:
+ if not raiseerr:
+ return None
+ else:
+ raise exceptions.InvalidRequestError("Column instance '%s' is not directly present in table '%s'" % (str(column), str(column.table)))
for c in column.orig_set:
try:
return self.original_columns[c]