]> git.ipfire.org Git - thirdparty/sqlalchemy/sqlalchemy.git/commitdiff
- backported 0.5's contains_eager() behavior such that rendering of eager clauses...
authorMike Bayer <mike_mp@zzzcomputing.com>
Thu, 8 May 2008 00:19:06 +0000 (00:19 +0000)
committerMike Bayer <mike_mp@zzzcomputing.com>
Thu, 8 May 2008 00:19:06 +0000 (00:19 +0000)
CHANGES
lib/sqlalchemy/orm/strategies.py
test/orm/query.py

diff --git a/CHANGES b/CHANGES
index 8ec857dadde7e63c3ba647606f6a9d1f6f8fedf1..35d53ab61815ae534f581315052f51dfcf63c0a1 100644 (file)
--- a/CHANGES
+++ b/CHANGES
@@ -13,6 +13,11 @@ CHANGES
     - Also re-established viewonly relation() configurations
       that join across multiple tables.
 
+    - contains_eager(), the hot function of the week, suppresses
+      the eager loader's own generation of the LEFT OUTER JOIN,
+      so that it is reasonable to use any Query, not just those
+      which use from_statement().  
+      
     - Added an experimental relation() flag to help with
       primaryjoins across functions, etc.,
       _local_remote_pairs=[tuples].  This complements a complex
index e758ac08b102d57c0283bdc6fe357bdc62ab63f9..65a8b019b865a3579061d6fa7b811cfdae73762d 100644 (file)
@@ -502,6 +502,28 @@ class EagerLoader(AbstractRelationLoader):
                 if self.mapper.base_mapper in path:
                     return
 
+        if ("eager_row_processor", path) in context.attributes:
+            # if user defined eager_row_processor, that's contains_eager().
+            # don't render LEFT OUTER JOIN, generate an AliasedClauses from 
+            # the decorator (this is a hack here, cleaned up in 0.5)
+            cl = context.attributes[("eager_row_processor", path)]
+            if cl:
+                row = cl(None)
+                class ActsLikeAliasedClauses(object):
+                    def aliased_column(self, col):
+                        return row.map[col]
+                clauses = ActsLikeAliasedClauses()
+            else:
+                clauses = None
+        else:
+            clauses = self.__create_eager_join(context, path, parentclauses, parentmapper, **kwargs)
+            if not clauses:
+                return
+
+        for value in self.mapper._iterate_polymorphic_properties():
+            context.exec_with_path(self.mapper, value.key, value.setup, context, parentclauses=clauses, parentmapper=self.mapper)
+
+    def __create_eager_join(self, context, path, parentclauses, parentmapper, **kwargs):
         if parentmapper is None:
             localparent = context.mapper
         else:
@@ -546,8 +568,7 @@ class EagerLoader(AbstractRelationLoader):
         if clauses.order_by:
             context.eager_order_by += util.to_list(clauses.order_by)
         
-        for value in self.mapper._iterate_polymorphic_properties():
-            context.exec_with_path(self.mapper, value.key, value.setup, context, parentclauses=clauses, parentmapper=self.mapper)
+        return clauses
         
     def _create_row_decorator(self, selectcontext, row, path):
         """Create a *row decorating* function that will apply eager
index cdd50cb70701e7b9efc56d4f632b9c6603fc0ae8..f1afdb90b40b140660e68b27e8edf700bc3e73dc 100644 (file)
@@ -906,7 +906,7 @@ class SynonymTest(QueryTest):
             o = sess.query(Order).with_parent(u1, property=orderprop).all()
             assert [Order(description="order 1"), Order(description="order 3"), Order(description="order 5")] == o
 
-class InstancesTest(QueryTest):
+class InstancesTest(QueryTest, AssertsCompiledSQL):
 
     def test_from_alias(self):
 
@@ -927,9 +927,26 @@ class InstancesTest(QueryTest):
         self.assert_sql_count(testing.db, go, 1)
 
     def test_contains_eager(self):
+        sess = create_session()
 
+        q = sess.query(User).outerjoin(User.addresses).options(contains_eager(User.addresses))
+        self.assert_compile(q.statement, "SELECT addresses.id AS addresses_id, addresses.user_id AS addresses_user_id, "
+        "addresses.email_address AS addresses_email_address, users.id AS users_id, users.name AS users_name "\
+        "FROM users LEFT OUTER JOIN addresses ON users.id = addresses.user_id ORDER BY users.id", dialect=default.DefaultDialect())
+        
+        def go():
+            assert fixtures.user_address_result == q.all()
+        self.assert_sql_count(testing.db, go, 1)
+        sess.clear()
+        
+        adalias = addresses.alias()
+        q = sess.query(User).select_from(users.outerjoin(adalias)).options(contains_eager(User.addresses, alias=adalias))
+        def go():
+            assert fixtures.user_address_result == q.all()
+        self.assert_sql_count(testing.db, go, 1)
+        sess.clear()
+        
         selectquery = users.outerjoin(addresses).select(users.c.id<10, use_labels=True, order_by=[users.c.id, addresses.c.id])
-        sess = create_session()
         q = sess.query(User)
 
         def go():