]> git.ipfire.org Git - thirdparty/sqlalchemy/sqlalchemy.git/commitdiff
- setting the relation()-level order by to a column in the
authorMike Bayer <mike_mp@zzzcomputing.com>
Fri, 29 Feb 2008 21:54:40 +0000 (21:54 +0000)
committerMike Bayer <mike_mp@zzzcomputing.com>
Fri, 29 Feb 2008 21:54:40 +0000 (21:54 +0000)
many-to-many "secondary" table will now work with eager
loading, previously the "order by" wasn't aliased against
the secondary table's alias.

CHANGES
lib/sqlalchemy/orm/util.py
test/orm/eager_relations.py

diff --git a/CHANGES b/CHANGES
index c2bd34e8aa06f3c2489f62eed83a86e7c9e2a7b8..501db5d286f1b8a2894b210d29afb21743c9959a 100644 (file)
--- a/CHANGES
+++ b/CHANGES
@@ -59,6 +59,11 @@ CHANGES
       populating the PK value of <somechild> in the case that
       <somechild> was pending.
 
+    - setting the relation()-level order by to a column in the
+      many-to-many "secondary" table will now work with eager 
+      loading, previously the "order by" wasn't aliased against
+      the secondary table's alias.
+      
 - dialects
     - Invalid SQLite connection URLs now raise an error.
 
index 9ddfcd278ffc12d6470b58220f5138395105753b..8a3583c36fcf56477a8c988a12f585ebd3faee23 100644 (file)
@@ -214,17 +214,23 @@ class PropertyAliasedClauses(AliasedClauses):
             self.primaryjoin = primary_aliasizer.traverse(primaryjoin, clone=True)
         else:
             if parentclauses is not None: 
-                aliasizer = sql_util.ClauseAdapter(self.alias, exclude=prop.local_side)
-                aliasizer.chain(sql_util.ClauseAdapter(parentclauses.alias, exclude=prop.remote_side))
+                primary_aliasizer = sql_util.ClauseAdapter(self.alias, exclude=prop.local_side)
+                primary_aliasizer.chain(sql_util.ClauseAdapter(parentclauses.alias, exclude=prop.remote_side))
             else:
-                aliasizer = sql_util.ClauseAdapter(self.alias, exclude=prop.local_side)
+                primary_aliasizer = sql_util.ClauseAdapter(self.alias, exclude=prop.local_side)
 
-            self.primaryjoin = aliasizer.traverse(primaryjoin, clone=True)
+            self.primaryjoin = primary_aliasizer.traverse(primaryjoin, clone=True)
             self.secondary = None
             self.secondaryjoin = None
         
         if prop.order_by:
-            self.order_by = sql_util.ClauseAdapter(self.alias).copy_and_process(util.to_list(prop.order_by))
+            if prop.secondary:
+                # usually this is not used but occasionally someone has a sort key in their secondary
+                # table, even tho SA does not support writing this column directly
+                self.order_by = secondary_aliasizer.copy_and_process(util.to_list(prop.order_by))
+            else:
+                self.order_by = primary_aliasizer.copy_and_process(util.to_list(prop.order_by))
+                
         else:
             self.order_by = None
     
index f35fbcbfc28e5481431a0bf4e0f9f573ee59f6e2..5553b9c79718c11e5f6da2b8d8198970b6d745b5 100644 (file)
@@ -74,7 +74,7 @@ class EagerTest(FixtureTest):
             User(id=10, addresses=[])
         ] == q.all()
 
-    def test_orderby_secondary(self):
+    def test_orderby_related(self):
         """tests that a regular mapper select on a single table can order by a relation to a second table"""
 
         mapper(Address, addresses)
@@ -649,6 +649,59 @@ class AddEntityTest(FixtureTest):
             self.assertEquals(ret, self._assert_result())
         self.assert_sql_count(testing.db, go, 1)
 
+class OrderBySecondaryTest(ORMTest):
+    def define_tables(self, metadata):
+        global a, b, m2m
+        m2m = Table('mtom', metadata, 
+            Column('id', Integer, primary_key=True),
+            Column('aid', Integer, ForeignKey('a.id')),
+            Column('bid', Integer, ForeignKey('b.id')),
+            )
+            
+        a = Table('a', metadata,
+            Column('id', Integer, primary_key=True),
+            Column('data', String(50)),
+            )
+        b = Table('b', metadata,
+            Column('id', Integer, primary_key=True),
+            Column('data', String(50)),
+            )
+
+    def insert_data(self):
+        a.insert().execute([
+            {'id':1, 'data':'a1'},
+            {'id':2, 'data':'a2'}
+        ])
+        
+        b.insert().execute([
+            {'id':1, 'data':'b1'},
+            {'id':2, 'data':'b2'},
+            {'id':3, 'data':'b3'},
+            {'id':4, 'data':'b4'},
+        ])
+        
+        m2m.insert().execute([
+            {'id':2, 'aid':1, 'bid':1},
+            {'id':4, 'aid':2, 'bid':4},
+            {'id':1, 'aid':1, 'bid':3},
+            {'id':6, 'aid':2, 'bid':2},
+            {'id':3, 'aid':1, 'bid':2},
+            {'id':5, 'aid':2, 'bid':3},
+        ])
+    
+    def test_ordering(self):
+        class A(Base):pass
+        class B(Base):pass
+        
+        mapper(A, a, properties={
+            'bs':relation(B, secondary=m2m, lazy=False, order_by=m2m.c.id)
+        })
+        mapper(B, b)
+        
+        sess = create_session()
+        self.assertEquals(sess.query(A).all(), [A(data='a1', bs=[B(data='b3'), B(data='b1'), B(data='b2')]), A(bs=[B(data='b4'), B(data='b3'), B(data='b2')])])
+        
+        
 class SelfReferentialEagerTest(ORMTest):
     def define_tables(self, metadata):
         global nodes