From: Mike Bayer Date: Sun, 29 Apr 2007 23:07:18 +0000 (+0000) Subject: - adapted gaetan's eager load adaption code for non-mapped column properties X-Git-Tag: rel_0_3_7~1 X-Git-Url: http://git.ipfire.org/cgi-bin/gitweb.cgi?a=commitdiff_plain;h=d266ca023b023e72b490fb1e793ef0ec9114c6b9;p=thirdparty%2Fsqlalchemy%2Fsqlalchemy.git - adapted gaetan's eager load adaption code for non-mapped column properties --- diff --git a/lib/sqlalchemy/orm/strategies.py b/lib/sqlalchemy/orm/strategies.py index 1d7eee56d8..4e5cf522d4 100644 --- a/lib/sqlalchemy/orm/strategies.py +++ b/lib/sqlalchemy/orm/strategies.py @@ -20,17 +20,13 @@ class ColumnLoader(LoaderStrategy): self.columns = self.parent_property.columns self._should_log_debug = logging.is_debug_enabled(self.logger) - def setup_query(self, context, eagertable=None, **kwargs): + def setup_query(self, context, eagertable=None, parentclauses=None, **kwargs): for c in self.columns: - if eagertable is not None: - conv = eagertable.corresponding_column(c, raiseerr=False) - if conv: - context.statement.append_column(conv) - else: - context.statement.append_column(c) + if parentclauses is not None: + context.statement.append_column(parentclauses.aliased_column(c)) else: context.statement.append_column(c) - + def init_class_attribute(self): self.logger.info("register managed attribute %s on class %s" % (self.key, self.parent.class_.__name__)) coltype = self.columns[0].type @@ -366,6 +362,7 @@ class EagerLoader(AbstractRelationLoader): self.parent = eagerloader self.target = eagerloader.select_table self.eagertarget = eagerloader.select_table.alias(self._aliashash("/target")) + self.extra_cols = {} if eagerloader.secondary: self.eagersecondary = eagerloader.secondary.alias(self._aliashash("/secondary")) @@ -392,6 +389,25 @@ class EagerLoader(AbstractRelationLoader): self._row_decorator = self._create_decorator_row() + def aliased_column(self, column): + """return the aliased version of the given column, creating a new label for it if not already + present in this AliasedClauses eagertable.""" + + conv = self.eagertarget.corresponding_column(column, raiseerr=False) + if conv: + return conv + + if column in self.extra_cols: + return self.extra_cols[column] + + aliased_column = column.copy_container() + sql_util.ClauseAdapter(self.eagertarget).traverse(aliased_column) + alias = self._aliashash(column.name) + aliased_column = aliased_column.label(alias) + self._row_decorator.map[column] = alias + self.extra_cols[column] = aliased_column + return aliased_column + def _aliashash(self, extra): """return a deterministic 4 digit hash value for this AliasedClause's id + extra.""" # use the first 4 digits of an MD5 hash @@ -423,6 +439,7 @@ class EagerLoader(AbstractRelationLoader): map[parent] = c map[parent._label] = c map[parent.name] = c + EagerRowAdapter.map = map return EagerRowAdapter def _decorate_row(self, row): diff --git a/test/orm/mapper.py b/test/orm/mapper.py index 99712b082f..a9cc401029 100644 --- a/test/orm/mapper.py +++ b/test/orm/mapper.py @@ -455,10 +455,6 @@ class MapperTest(MapperSuperTest): assert str(e) == "Column '%s' is not represented in mapper's table. Use the `column_property()` function to force this column to be mapped as a read-only attribute." % str(f) clear_mappers() - mapper(Address, addresses, properties={ - 'user':relation(User, lazy=False) - }) - mapper(User, users, properties={ 'concat': column_property(f), 'count': column_property(select([func.count(addresses.c.address_id)], users.c.user_id==addresses.c.user_id, scalar=True).label('count')) @@ -473,12 +469,22 @@ class MapperTest(MapperSuperTest): ### eager loads, not really working across all DBs, no column aliasing in place so # results still wont be good for larger situations - #l = sess.query(Address).select() - l = sess.query(Address).options(lazyload('user')).select() - for a in l: - print "User", a.user.user_id, a.user.user_name, a.user.concat, a.user.count - assert l[0].user.concat == l[0].user.user_id * 2 == 14 - assert l[1].user.concat == l[1].user.user_id * 2 == 16 + clear_mappers() + mapper(Address, addresses, properties={ + 'user':relation(User, lazy=False) + }) + + mapper(User, users, properties={ + 'concat': column_property(f), + }) + + for x in range(0, 2): + sess.clear() + l = sess.query(Address).select() + for a in l: + print "User", a.user.user_id, a.user.user_name, a.user.concat + assert l[0].user.concat == l[0].user.user_id * 2 == 14 + assert l[1].user.concat == l[1].user.user_id * 2 == 16 @testbase.unsupported('firebird')