From: Mike Bayer Date: Sat, 30 Jul 2011 16:12:39 +0000 (-0400) Subject: - Fixed bug where query.join() + aliased=True X-Git-Tag: rel_0_6_9~35 X-Git-Url: http://git.ipfire.org/cgi-bin/gitweb.cgi?a=commitdiff_plain;h=e57cf91357dfdfd4b15d27bae42fc980392be5e0;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] --- diff --git a/CHANGES b/CHANGES index 313170a65c..a7bb9a59fd 100644 --- 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 diff --git a/lib/sqlalchemy/orm/query.py b/lib/sqlalchemy/orm/query.py index 6a0acaa7c2..5dc216670a 100644 --- a/lib/sqlalchemy/orm/query.py +++ b/lib/sqlalchemy/orm/query.py @@ -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( diff --git a/test/orm/inheritance/test_query.py b/test/orm/inheritance/test_query.py index de5cfadd14..d5ffedbfca 100644 --- a/test/orm/inheritance/test_query.py +++ b/test/orm/inheritance/test_query.py @@ -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):