]> git.ipfire.org Git - thirdparty/sqlalchemy/sqlalchemy.git/commitdiff
- Fixed bug where query.join() + aliased=True
authorMike Bayer <mike_mp@zzzcomputing.com>
Sat, 30 Jul 2011 16:12:39 +0000 (12:12 -0400)
committerMike Bayer <mike_mp@zzzcomputing.com>
Sat, 30 Jul 2011 16:12:39 +0000 (12:12 -0400)
from a joined-inh structure to itself on
relationship() with join condition on the child
table would convert the lead entity into the
joined one inappropriately.  [ticket:2234]

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

diff --git a/CHANGES b/CHANGES
index 313170a65cd7d1ff971b2951038559add5093713..a7bb9a59fdce129ca474669127c1ab2dac2607e1 100644 (file)
--- a/CHANGES
+++ b/CHANGES
@@ -17,6 +17,12 @@ CHANGES
     if the persistent object primary key 
     is not a single integer.  [ticket:2228]
 
+  - Fixed bug where query.join() + aliased=True
+    from a joined-inh structure to itself on 
+    relationship() with join condition on the child
+    table would convert the lead entity into the 
+    joined one inappropriately.  [ticket:2234]
+
   - Fixed bug whereby if a mapped class
     redefined __hash__() or __eq__() to something
     non-standard, which is a supported use case
index 6a0acaa7c2b651ae66f6e5b9f17bd357b714ee7f..5dc216670a563d98d7bde7d73ccb05345020b976 100644 (file)
@@ -1468,7 +1468,7 @@ class Query(object):
         # which is intended to wrap a the right side in a subquery,
         # ensure that columns retrieved from this target in the result
         # set are also adapted.
-        if aliased_entity:
+        if aliased_entity and not create_aliases:
             self.__mapper_loads_polymorphically_with(
                         right_mapper,
                         ORMAdapter(
index de5cfadd14d8392348370ffdc2425f4425c92369..d5ffedbfcaa47bf0b2d733b1cacedaa2b799e6cb 100644 (file)
@@ -1026,6 +1026,119 @@ class SelfReferentialJ2JTest(_base.MappedTest):
             [m1]
         )
 
+class SelfReferentialJ2JSelfTest(_base.MappedTest):
+    run_setup_mappers = 'once'
+
+    @classmethod
+    def define_tables(cls, metadata):
+        people = Table('people', metadata,
+           Column('person_id', Integer, 
+                        primary_key=True, test_needs_autoincrement=True),
+           Column('name', String(50)),
+           Column('type', String(30)))
+
+        engineers = Table('engineers', metadata,
+           Column('person_id', Integer, 
+                    ForeignKey('people.person_id'), primary_key=True),
+           Column('reports_to_id', Integer, 
+                    ForeignKey('engineers.person_id'))
+          )
+
+
+    @classmethod
+    def setup_mappers(cls):
+        engineers, people = (cls.tables.engineers,
+                                cls.tables.people)
+
+        mapper(Person, people, polymorphic_on=people.c.type, 
+                            polymorphic_identity='person')
+
+        mapper(Engineer, engineers, inherits=Person, 
+          polymorphic_identity='engineer', properties={
+          'reports_to':relationship(Engineer, 
+                            primaryjoin=engineers.c.person_id==engineers.c.reports_to_id, 
+                            backref='engineers',
+                            remote_side=engineers.c.person_id)
+        })
+
+    def _two_obj_fixture(self):
+        e1 = Engineer(name='wally')
+        e2 = Engineer(name='dilbert', 
+                        reports_to=e1)
+        sess = Session()
+        sess.add_all([e1, e2])
+        sess.commit()
+        return sess
+
+    def _five_obj_fixture(self):
+        sess =Session()
+        e1, e2, e3, e4, e5 = [
+            Engineer(name='e%d' % (i + 1)) for i in xrange(5)
+        ]
+        e3.reports_to=e1
+        e4.reports_to=e2
+        sess.add_all([e1, e2, e3, e4, e5])
+        sess.commit()
+        return sess
+
+    def test_has(self):
+        sess = self._two_obj_fixture()
+
+        eq_(
+            sess.query(Engineer).
+                filter(Engineer.reports_to.has(Engineer.name=='wally')).
+                first(), 
+            Engineer(name='dilbert'))
+
+    def test_join_explicit_alias(self):
+        sess = self._five_obj_fixture()
+
+        ea = aliased(Engineer)
+        eq_(
+            sess.query(Engineer).
+                join((ea, Engineer.engineers)).
+                filter(Engineer.name=='e1').all(),
+            [Engineer(name='e1')]
+        )
+
+    def test_join_aliased_flag_one(self):
+        sess = self._two_obj_fixture()
+
+        eq_(
+            sess.query(Engineer).
+                join('reports_to', aliased=True).
+                filter(Engineer.name=='wally').first(), 
+            Engineer(name='dilbert')
+        )
+
+    def test_join_aliased_flag_two(self):
+        sess = self._five_obj_fixture()
+
+        eq_(
+            sess.query(Engineer).
+                join(Engineer.engineers, aliased=True).
+                filter(Engineer.name=='e4').all(),
+            [Engineer(name='e2')]
+        )
+
+
+    def test_relationship_compare(self):
+        sess = self._five_obj_fixture()
+
+        eq_(
+            sess.query(Engineer).
+                join(Engineer.engineers, aliased=True).
+                filter(Engineer.reports_to==None).all(), 
+            []
+        )
+
+        e1 = sess.query(Engineer).filter_by(name='e1').one()
+        eq_(
+            sess.query(Engineer).
+                join(Engineer.engineers, aliased=True).
+                filter(Engineer.reports_to==e1).all(), 
+            [e1]
+        )
 
 
 class M2MFilterTest(_base.MappedTest):