From: Mike Bayer Date: Sun, 22 Jun 2008 19:02:19 +0000 (+0000) Subject: - Fixed explicit, self-referential joins between two X-Git-Tag: rel_0_5beta2~46 X-Git-Url: http://git.ipfire.org/cgi-bin/gitweb.cgi?a=commitdiff_plain;h=3e8b0951780d96bdf59dd7aceddf028be62eaa0b;p=thirdparty%2Fsqlalchemy%2Fsqlalchemy.git - Fixed explicit, self-referential joins between two joined-table inheritance mappers when using query.join(cls, aliased=True). [ticket:1082] --- diff --git a/CHANGES b/CHANGES index d34bf8b810..fc32ab2d0e 100644 --- a/CHANGES +++ b/CHANGES @@ -20,6 +20,10 @@ CHANGES locally modified, so that they are refreshed with the most recent data upon access. [ticket:887] + - Fixed explicit, self-referential joins between two + joined-table inheritance mappers when using + query.join(cls, aliased=True). [ticket:1082] + 0.5beta1 ======== - An ongoing document describing the changes from 0.4 to 0.5 diff --git a/lib/sqlalchemy/orm/query.py b/lib/sqlalchemy/orm/query.py index 51c57ca302..37463ef10d 100644 --- a/lib/sqlalchemy/orm/query.py +++ b/lib/sqlalchemy/orm/query.py @@ -842,14 +842,14 @@ class Query(object): right_entity = aliased(right_mapper, right_selectable) alias_criterion = True - elif right_mapper.with_polymorphic or isinstance(right_mapper.mapped_table, expression.Join): - aliased_entity = True + elif create_aliases: right_entity = aliased(right_mapper) alias_criterion = True - - elif create_aliases: + + elif right_mapper.with_polymorphic or isinstance(right_mapper.mapped_table, expression.Join): right_entity = aliased(right_mapper) alias_criterion = True + aliased_entity = True elif prop: if prop.table in self.__currenttables: @@ -873,7 +873,7 @@ class Query(object): if alias_criterion: self._filter_aliases = ORMAdapter(right_entity, equivalents=right_mapper._equivalent_columns, chain_to=self._filter_aliases) - + if aliased_entity: self.__mapper_loads_polymorphically_with(right_mapper, ORMAdapter(right_entity, equivalents=right_mapper._equivalent_columns)) @@ -1567,7 +1567,7 @@ class _MapperEntity(_QueryEntity): def setup_context(self, query, context): adapter = self._get_entity_clauses(query, context) - + context.froms.append(self.selectable) if context.order_by is False and self.mapper.order_by: diff --git a/test/orm/inheritance/query.py b/test/orm/inheritance/query.py index c706acf6e1..678513dbc2 100644 --- a/test/orm/inheritance/query.py +++ b/test/orm/inheritance/query.py @@ -653,7 +653,7 @@ for select_type in ('', 'Polymorphic', 'Unions', 'AliasedJoins', 'Joins'): del testclass -class SelfReferentialTest(ORMTest): +class SelfReferentialTestJoinedToBase(ORMTest): keep_mappers = True def define_tables(self, metadata): @@ -706,7 +706,62 @@ class SelfReferentialTest(ORMTest): sess.flush() sess.clear() - self.assertEquals(sess.query(Engineer).join('reports_to', aliased=True).filter(Person.name=='dogbert').first(), Engineer(name='dilbert')) + self.assertEquals( + sess.query(Engineer).join('reports_to', aliased=True).filter(Person.name=='dogbert').first(), + Engineer(name='dilbert')) + +class SelfReferentialTestJoinedToJoined(ORMTest): + keep_mappers = True + + def define_tables(self, metadata): + global people, engineers + people = Table('people', metadata, + Column('person_id', Integer, Sequence('person_id_seq', optional=True), primary_key=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('primary_language', String(50)), + Column('reports_to_id', Integer, ForeignKey('managers.person_id')) + ) + + managers = Table('managers', metadata, + Column('person_id', Integer, ForeignKey('people.person_id'), primary_key=True), + ) + + mapper(Person, people, polymorphic_on=people.c.type, polymorphic_identity='person') + mapper(Manager, managers, inherits=Person, polymorphic_identity='manager') + + mapper(Engineer, engineers, inherits=Person, + polymorphic_identity='engineer', properties={ + 'reports_to':relation(Manager, primaryjoin=managers.c.person_id==engineers.c.reports_to_id) + }) + + def test_has(self): + + m1 = Manager(name='dogbert') + e1 = Engineer(name='dilbert', primary_language='java', reports_to=m1) + sess = create_session() + sess.save(m1) + sess.save(e1) + sess.flush() + sess.clear() + + self.assertEquals(sess.query(Engineer).filter(Engineer.reports_to.has(Manager.name=='dogbert')).first(), Engineer(name='dilbert')) + + def test_join(self): + m1 = Manager(name='dogbert') + e1 = Engineer(name='dilbert', primary_language='java', reports_to=m1) + sess = create_session() + sess.save(m1) + sess.save(e1) + sess.flush() + sess.clear() + + self.assertEquals( + sess.query(Engineer).join('reports_to', aliased=True).filter(Manager.name=='dogbert').first(), + Engineer(name='dilbert')) class M2MFilterTest(ORMTest):