Mike Bayer avatar Mike Bayer committed e2213e9

- adapted gaetan's eager load adaption code for non-mapped column properties

Comments (0)

Files changed (2)

lib/sqlalchemy/orm/strategies.py

         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
             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"))
 
             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
                 map[parent] = c
                 map[parent._label] = c
                 map[parent.name] = c
+            EagerRowAdapter.map = map
             return EagerRowAdapter
 
         def _decorate_row(self, row):

test/orm/mapper.py

             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'))
         
         ### 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') 
Tip: Filter by directory path e.g. /media app.js to search for public/media/app.js.
Tip: Use camelCasing e.g. ProjME to search for ProjectModifiedEvent.java.
Tip: Filter by extension type e.g. /repo .js to search for all .js files in the /repo directory.
Tip: Separate your search with spaces e.g. /ssh pom.xml to search for src/ssh/pom.xml.
Tip: Use ↑ and ↓ arrow keys to navigate and return to view the file.
Tip: You can also navigate files with Ctrl+j (next) and Ctrl+k (previous) and view the file with Ctrl+o.
Tip: You can also navigate files with Alt+j (next) and Alt+k (previous) and view the file with Alt+o.