Commits

Mike Bayer committed 5892f58

- Fixed bug where determination of "self referential"
relationship would fail with no workaround
for joined-inh subclass related to itself,
or joined-inh subclass related to a subclass
of that with no cols in the sub-sub class
in the join condition. [ticket:2149]
Also in 0.6.8.

Comments (0)

Files changed (3)

     elements are otherwise not easily accessible.
     [ticket:2155]
 
+  - Fixed bug where determination of "self referential"
+    relationship would fail with no workaround
+    for joined-inh subclass related to itself,
+    or joined-inh subclass related to a subclass
+    of that with no cols in the sub-sub class 
+    in the join condition.  [ticket:2149]
+    Also in 0.6.8.
+
   - It is an error to call query.get() when the
     given entity is not a single, full class 
     entity or mapper (i.e. a column).  This is

lib/sqlalchemy/orm/properties.py

         return strategy.use_get
 
     def _refers_to_parent_table(self):
+        pt = self.parent.mapped_table
+        mt = self.mapper.mapped_table
         for c, f in self.synchronize_pairs:
-            if c.table is f.table:
+            if (
+                pt.is_derived_from(c.table) and \
+                pt.is_derived_from(f.table) and \
+                mt.is_derived_from(c.table) and \
+                mt.is_derived_from(f.table)
+            ):
                 return True
         else:
             return False

test/orm/inheritance/test_polymorph2.py

             ]
         )
 
+class JoinedInhAdjacencyTest(fixtures.MappedTest):
+    @classmethod
+    def define_tables(cls, metadata):
+        Table('people', metadata,
+                 Column('id', Integer, primary_key=True, 
+                                test_needs_autoincrement=True),
+                 Column('type', String(30)),
+                 )
+        Table('users', metadata,
+              Column('id', Integer, ForeignKey('people.id'), 
+                                primary_key=True),
+              Column('supervisor_id', Integer, ForeignKey('people.id')),
+        )
+        Table('dudes', metadata,
+              Column('id', Integer, ForeignKey('users.id'), 
+                                primary_key=True),
+        )
+
+    @classmethod
+    def setup_classes(cls):
+        class Person(cls.Comparable):
+            pass
+
+        class User(Person):
+            pass
+
+        class Dude(User):
+            pass
+
+    def _roundtrip(self):
+        Person, User = self.classes.Person, self.classes.User
+        sess = Session()
+        u1 = User()
+        u2 = User()
+        u2.supervisor = u1
+        sess.add_all([u1, u2])
+        sess.commit()
+
+        assert u2.supervisor is u1
+
+    def _dude_roundtrip(self):
+        Dude, User = self.classes.Dude, self.classes.User
+        sess = Session()
+        u1 = User()
+        d1 = Dude()
+        d1.supervisor = u1
+        sess.add_all([u1, d1])
+        sess.commit()
+
+        assert d1.supervisor is u1
+
+    def test_joined_to_base(self):
+        people, users = self.tables.people, self.tables.users
+        Person, User = self.classes.Person, self.classes.User
+
+        mapper(Person, people,
+            polymorphic_on=people.c.type,
+            polymorphic_identity='person',
+        )
+        mapper(User, users, inherits=Person,
+            polymorphic_identity='user',
+            inherit_condition=(users.c.id == people.c.id),
+            properties = {
+                'supervisor': relationship(Person,
+                                primaryjoin=users.c.supervisor_id==people.c.id,
+                               ),
+               }
+        )
+
+        assert User.supervisor.property.direction is MANYTOONE
+        self._roundtrip()
+
+    def test_joined_to_same_subclass(self):
+        people, users = self.tables.people, self.tables.users
+        Person, User = self.classes.Person, self.classes.User
+
+        mapper(Person, people,
+            polymorphic_on=people.c.type,
+            polymorphic_identity='person',
+        )
+        mapper(User, users, inherits=Person,
+            polymorphic_identity='user',
+            inherit_condition=(users.c.id == people.c.id),
+            properties = {
+                'supervisor': relationship(User,
+                                   primaryjoin=users.c.supervisor_id==people.c.id,
+                                   remote_side=people.c.id,
+                                   foreign_keys=[users.c.supervisor_id]
+                               ),
+               }
+        )
+        assert User.supervisor.property.direction is MANYTOONE
+        self._roundtrip()
+
+    def test_joined_subclass_to_superclass(self):
+        people, users, dudes = self.tables.people, self.tables.users, self.tables.dudes
+        Person, User, Dude = self.classes.Person, self.classes.User, self.classes.Dude
+
+        mapper(Person, people,
+            polymorphic_on=people.c.type,
+            polymorphic_identity='person',
+        )
+        mapper(User, users, inherits=Person,
+            polymorphic_identity='user',
+            inherit_condition=(users.c.id == people.c.id),
+        )
+        mapper(Dude, dudes, inherits=User,
+            polymorphic_identity='dude',
+            inherit_condition=(dudes.c.id==users.c.id),
+            properties={
+                'supervisor': relationship(User,
+                                   primaryjoin=users.c.supervisor_id==people.c.id,
+                                   remote_side=people.c.id,
+                                   foreign_keys=[users.c.supervisor_id]
+                               ),
+            }
+        )
+        assert Dude.supervisor.property.direction is MANYTOONE
+        self._dude_roundtrip()