]> git.ipfire.org Git - thirdparty/sqlalchemy/sqlalchemy.git/commitdiff
- adapted gaetan's eager load adaption code for non-mapped column properties
authorMike Bayer <mike_mp@zzzcomputing.com>
Sun, 29 Apr 2007 23:07:18 +0000 (23:07 +0000)
committerMike Bayer <mike_mp@zzzcomputing.com>
Sun, 29 Apr 2007 23:07:18 +0000 (23:07 +0000)
lib/sqlalchemy/orm/strategies.py
test/orm/mapper.py

index 1d7eee56d84f74b095eca3bb6c51f3e7d9280ac4..4e5cf522d4943a7454f73536282fcec0e1262736 100644 (file)
@@ -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):
index 99712b082fbc94a9ce01e865e521ea362940ce25..a9cc40102918e487f9b84220a36a2400cf25ff04 100644 (file)
@@ -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')