]> git.ipfire.org Git - thirdparty/sqlalchemy/sqlalchemy.git/commitdiff
- Improved the behavior of query.join()
authorMike Bayer <mike_mp@zzzcomputing.com>
Tue, 12 Aug 2008 15:19:09 +0000 (15:19 +0000)
committerMike Bayer <mike_mp@zzzcomputing.com>
Tue, 12 Aug 2008 15:19:09 +0000 (15:19 +0000)
when joining to joined-table inheritance
subclasses, using explicit join criteria
(i.e. not on a relation).

CHANGES
lib/sqlalchemy/orm/query.py
test/orm/inheritance/query.py

diff --git a/CHANGES b/CHANGES
index 503a9c16eecff386b148dd760e80f8524168be55..9c88030c632d42fd91958cb8404b0a1fc2a0b223 100644 (file)
--- a/CHANGES
+++ b/CHANGES
@@ -22,6 +22,11 @@ CHANGES
       should not "leak" their inner FROM objects out
       into the enclosing query.
     
+    - Improved the behavior of query.join()
+      when joining to joined-table inheritance
+      subclasses, using explicit join criteria
+      (i.e. not on a relation).
+      
     - Fixed @on_reconsitute hook for subclasses 
       which inherit from a base class.
       [ticket:1129]
index b9801370b4e0502a85836fd1a71689766ebd71bc..ed3c2f7c38dc09d8b0db6df77b941e92c0dc3a06 100644 (file)
@@ -829,7 +829,10 @@ class Query(object):
             if not clause:
                 raise sa_exc.InvalidRequestError("Could not find a FROM clause to join from")
 
-            bogus, right_selectable, is_aliased_class = _entity_info(right_entity)
+            mp, right_selectable, is_aliased_class = _entity_info(right_entity)
+            
+            if not right_mapper and mp:
+                right_mapper = mp
 
             if right_mapper and not is_aliased_class:
                 if right_entity is right_selectable:
@@ -851,7 +854,7 @@ class Query(object):
                     right_entity = aliased(right_mapper)
                     alias_criterion = True
                     aliased_entity = True
-                    
+                        
                 elif prop:
                     if prop.table in self.__currenttables:
                         if prop.secondary is not None and prop.secondary not in self.__currenttables:
@@ -867,13 +870,19 @@ class Query(object):
 
                     right_entity = prop.mapper
 
+            if alias_criterion:
+                right_adapter = ORMAdapter(right_entity, 
+                    equivalents=right_mapper._equivalent_columns, chain_to=self._filter_aliases)
+                    
+                if isinstance(onclause, sql.ClauseElement):
+                    onclause = right_adapter.traverse(onclause)
+
             if prop:
                 onclause = prop
             
             clause = orm_join(clause, right_entity, onclause, isouter=outerjoin)
             if alias_criterion: 
-                self._filter_aliases = ORMAdapter(right_entity, 
-                        equivalents=right_mapper._equivalent_columns, chain_to=self._filter_aliases)
+                self._filter_aliases = right_adapter
                 
                 if aliased_entity:
                     self.__mapper_loads_polymorphically_with(right_mapper, ORMAdapter(right_entity, equivalents=right_mapper._equivalent_columns))
index 28659ba38a3e4c71c8fc4ae459e653a38424f2f3..eb40f01e56c8552dee303d5845dfcf65af5f23bf 100644 (file)
@@ -455,6 +455,25 @@ def make_test(select_type):
                         join('paperwork', from_joinpoint=True, aliased=aliased).filter(Paperwork.description.like('%#%')).all(),
                     [c1, c2]
                 )
+        def test_explicit_polymorphic_join(self):
+            sess = create_session()
+
+            # join from Company to Engineer; join condition formulated by
+            # ORMJoin using regular table foreign key connections.  Engineer
+            # is expressed as "(select * people join engineers) as anon_1"
+            # so the join is contained.
+            self.assertEquals(
+                sess.query(Company).join(Engineer).filter(Engineer.engineer_name=='vlad').one(),
+                c2
+            )
+
+            # same, using explicit join condition.  Query.join() must adapt the on clause
+            # here to match the subquery wrapped around "people join engineers".
+            self.assertEquals(
+                sess.query(Company).join((Engineer, Company.company_id==Engineer.company_id)).filter(Engineer.engineer_name=='vlad').one(),
+                c2
+            )
+                
         
         def test_filter_on_baseclass(self):
             sess = create_session()