From: Mike Bayer Date: Wed, 11 Apr 2007 19:37:56 +0000 (+0000) Subject: - fix to many-to-many relationships targeting polymorphic mappers X-Git-Tag: rel_0_3_7~77 X-Git-Url: http://git.ipfire.org/cgi-bin/gitweb.cgi?a=commitdiff_plain;h=95520005d5469f311f53ea9c51bbaef61be89178;p=thirdparty%2Fsqlalchemy%2Fsqlalchemy.git - fix to many-to-many relationships targeting polymorphic mappers [ticket:533] --- diff --git a/CHANGES b/CHANGES index 458763a13d..ba99f5e330 100644 --- a/CHANGES +++ b/CHANGES @@ -48,6 +48,8 @@ - improved/fixed custom collection classes when giving it "set"/ "sets.Set" classes or subclasses (was still looking for append() methods on them during lazy loads) + - fix to many-to-many relationships targeting polymorphic mappers + [ticket:533] - sqlite: - removed silly behavior where sqlite would reflect UNIQUE indexes as part of the primary key (?!) diff --git a/lib/sqlalchemy/orm/properties.py b/lib/sqlalchemy/orm/properties.py index e3bd98e3e1..1b6203e063 100644 --- a/lib/sqlalchemy/orm/properties.py +++ b/lib/sqlalchemy/orm/properties.py @@ -384,6 +384,8 @@ class PropertyLoader(StrategizedProperty): # load "polymorphic" versions of the columns present in "remote_side" - this is # important for lazy-clause generation which goes off the polymorphic target selectable for c in list(self.remote_side): + if self.secondary and c in self.secondary.columns: + continue for equiv in [c] + (c in target_equivalents and target_equivalents[c] or []): corr = self.mapper.select_table.corresponding_column(equiv, raiseerr=False) if corr: diff --git a/test/orm/inheritance5.py b/test/orm/inheritance5.py index bdc9e02e12..6575304056 100644 --- a/test/orm/inheritance5.py +++ b/test/orm/inheritance5.py @@ -777,6 +777,56 @@ class MultiLevelTest(testbase.ORMTest): assert set(session.query(Employee).select()) == set([a,b,c]) assert set(session.query( Engineer).select()) == set([b,c]) assert session.query( Manager).select() == [c] + +class ManyToManyPolyTest(testbase.ORMTest): + def define_tables(self, metadata): + global base_item_table, item_table, base_item_collection_table, collection_table + base_item_table = Table( + 'base_item', metadata, + Column('id', Integer, primary_key=True), + Column('child_name', String(255), default=None)) + + item_table = Table( + 'item', metadata, + Column('id', Integer, ForeignKey('base_item.id'), primary_key=True), + Column('dummy', Integer, default=0)) # Dummy column to avoid weird insert problems + + base_item_collection_table = Table( + 'base_item_collection', metadata, + Column('item_id', Integer, ForeignKey('base_item.id')), + Column('collection_id', Integer, ForeignKey('collection.id'))) + + collection_table = Table( + 'collection', metadata, + Column('id', Integer, primary_key=True), + Column('name', Unicode(255))) + + def test_pjoin_compile(self): + """test that remote_side columns in the secondary join table arent attempted to be + matched to the target polymorphic selectable""" + class BaseItem(object): pass + class Item(BaseItem): pass + class Collection(object): pass + item_join = polymorphic_union( { + 'BaseItem':base_item_table.select(base_item_table.c.child_name=='BaseItem'), + 'Item':base_item_table.join(item_table), + }, None, 'item_join') + + mapper( + BaseItem, base_item_table, + select_table=item_join, + polymorphic_on=base_item_table.c.child_name, + polymorphic_identity='BaseItem', + properties=dict(collections=relation(Collection, secondary=base_item_collection_table, backref="items"))) + + mapper( + Item, item_table, + inherits=BaseItem, + polymorphic_identity='Item') + + mapper(Collection, collection_table) + + class_mapper(BaseItem) if __name__ == "__main__": testbase.main()