diff options
| author | Mike Bayer <mike_mp@zzzcomputing.com> | 2009-08-28 20:29:08 +0000 |
|---|---|---|
| committer | Mike Bayer <mike_mp@zzzcomputing.com> | 2009-08-28 20:29:08 +0000 |
| commit | 72b9be719fae32dc19793989d505d9c92f40b739 (patch) | |
| tree | e6a70b2cb20622d77b723b62a2a22382aadf27c9 /lib | |
| parent | f892d1a3fe8e349d1008bee51be5633dbfbf1189 (diff) | |
| download | sqlalchemy-72b9be719fae32dc19793989d505d9c92f40b739.tar.gz | |
- Fixed an obscure issue whereby a joined-table subclass
with a self-referential eager load on the base class
would populate the related object's "subclass" table with
data from the "subclass" table of the parent.
[ticket:1485]
Diffstat (limited to 'lib')
| -rw-r--r-- | lib/sqlalchemy/orm/strategies.py | 4 | ||||
| -rw-r--r-- | lib/sqlalchemy/orm/util.py | 4 | ||||
| -rw-r--r-- | lib/sqlalchemy/sql/util.py | 13 |
3 files changed, 16 insertions, 5 deletions
diff --git a/lib/sqlalchemy/orm/strategies.py b/lib/sqlalchemy/orm/strategies.py index a76eae0e0..b3290a2d6 100644 --- a/lib/sqlalchemy/orm/strategies.py +++ b/lib/sqlalchemy/orm/strategies.py @@ -116,7 +116,7 @@ class ColumnLoader(LoaderStrategy): key, col = self.key, self.columns[0] if adapter: col = adapter.columns[col] - if col in row: + if col is not None and col in row: def new_execute(state, dict_, row, **flags): dict_[key] = row[col] @@ -700,7 +700,7 @@ class EagerLoader(AbstractRelationLoader): # create AliasedClauses object to build up the eager query. clauses = mapperutil.ORMAdapter(mapperutil.AliasedClass(self.mapper), - equivalents=self.mapper._equivalent_columns) + equivalents=self.mapper._equivalent_columns, adapt_required=True) join_to_left = False if adapter: diff --git a/lib/sqlalchemy/orm/util.py b/lib/sqlalchemy/orm/util.py index c858ca102..bc23d8c6d 100644 --- a/lib/sqlalchemy/orm/util.py +++ b/lib/sqlalchemy/orm/util.py @@ -257,13 +257,13 @@ class ORMAdapter(sql_util.ColumnAdapter): and the AliasedClass if any is referenced. """ - def __init__(self, entity, equivalents=None, chain_to=None): + def __init__(self, entity, equivalents=None, chain_to=None, adapt_required=False): self.mapper, selectable, is_aliased_class = _entity_info(entity) if is_aliased_class: self.aliased_class = entity else: self.aliased_class = None - sql_util.ColumnAdapter.__init__(self, selectable, equivalents, chain_to) + sql_util.ColumnAdapter.__init__(self, selectable, equivalents, chain_to, adapt_required=adapt_required) def replace(self, elem): entity = elem._annotations.get('parentmapper', None) diff --git a/lib/sqlalchemy/sql/util.py b/lib/sqlalchemy/sql/util.py index 27ae3e624..9be405e21 100644 --- a/lib/sqlalchemy/sql/util.py +++ b/lib/sqlalchemy/sql/util.py @@ -498,11 +498,12 @@ class ColumnAdapter(ClauseAdapter): adapted_row() factory. """ - def __init__(self, selectable, equivalents=None, chain_to=None, include=None, exclude=None): + def __init__(self, selectable, equivalents=None, chain_to=None, include=None, exclude=None, adapt_required=False): ClauseAdapter.__init__(self, selectable, equivalents, include, exclude) if chain_to: self.chain(chain_to) self.columns = util.populate_column_dict(self._locate_col) + self.adapt_required = adapt_required def wrap(self, adapter): ac = self.__class__.__new__(self.__class__) @@ -530,6 +531,16 @@ class ColumnAdapter(ClauseAdapter): # anonymize labels in case they have a hardcoded name if isinstance(c, expression._Label): c = c.label(None) + + # adapt_required indicates that if we got the same column + # back which we put in (i.e. it passed through), + # it's not correct. this is used by eagerloading which + # knows that all columns and expressions need to be adapted + # to a result row, and a "passthrough" is definitely targeting + # the wrong column. + if self.adapt_required and c is col: + return None + return c def adapted_row(self, row): |
