diff options
author | Mike Bayer <mike_mp@zzzcomputing.com> | 2007-01-20 12:31:27 +0000 |
---|---|---|
committer | Mike Bayer <mike_mp@zzzcomputing.com> | 2007-01-20 12:31:27 +0000 |
commit | a31979937223c68f395ee0704593c9150f10e86b (patch) | |
tree | 38631a67d1116c1014a894f940db540bbcc9845e /lib | |
parent | 19de5346c2ce305327025d48ae5ed0d9626598ad (diff) | |
download | sqlalchemy-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.py | 4 | ||||
-rw-r--r-- | lib/sqlalchemy/orm/properties.py | 4 | ||||
-rw-r--r-- | lib/sqlalchemy/orm/strategies.py | 2 | ||||
-rw-r--r-- | lib/sqlalchemy/sql.py | 10 |
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] |