From: Mike Bayer Date: Sat, 30 Jul 2011 16:12:32 +0000 (-0400) Subject: - Fixed bug where query.join() + aliased=True X-Git-Tag: rel_0_7_2~5 X-Git-Url: http://git.ipfire.org/gitweb.cgi?a=commitdiff_plain;h=de0e2724c5a85586e98f524bba85b69e3ae6a21e;p=thirdparty%2Fsqlalchemy%2Fsqlalchemy.git - 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] Also in 0.6.9. --- diff --git a/CHANGES b/CHANGES index 9a39c613e0..59139fd992 100644 --- a/CHANGES +++ b/CHANGES @@ -38,6 +38,13 @@ CHANGES a fix for multiply-nested any()/has() constructs against a joined table structure. [ticket:2195] + - 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] + Also in 0.6.9. + - Fixed regression from 0.6 where Session.add() against an object which contained None in a collection would raise an internal exception. diff --git a/lib/sqlalchemy/orm/query.py b/lib/sqlalchemy/orm/query.py index a3b13abb27..d9c67d56cd 100644 --- a/lib/sqlalchemy/orm/query.py +++ b/lib/sqlalchemy/orm/query.py @@ -1535,7 +1535,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( diff --git a/test/orm/inheritance/test_query.py b/test/orm/inheritance/test_query.py index 23052f9977..2560d22843 100644 --- a/test/orm/inheritance/test_query.py +++ b/test/orm/inheritance/test_query.py @@ -1083,7 +1083,119 @@ class SelfReferentialJ2JTest(fixtures.MappedTest): [m1] ) +class SelfReferentialJ2JSelfTest(fixtures.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(fixtures.MappedTest): run_setup_mappers = 'once'