Commits

Mike Bayer committed 27e029c

- [bug] Fixed bug in declarative
whereby the precedence of columns
in a joined-table, composite
column (typically for id) would fail to
be correct if the columns contained
names distinct from their attribute
names. This would cause things like
primaryjoin conditions made against the
entity attributes to be incorrect. Related
to [ticket:1892] as this was supposed
to be part of that, this is [ticket:2491].

Comments (0)

Files changed (3)

     distinct class encountered in the polymorphic
     result.  [ticket:2480]
 
+  - [bug] Fixed bug in declarative 
+    whereby the precedence of columns 
+    in a joined-table, composite
+    column (typically for id) would fail to
+    be correct if the columns contained
+    names distinct from their attribute 
+    names.  This would cause things like
+    primaryjoin conditions made against the
+    entity attributes to be incorrect.  Related
+    to [ticket:1892] as this was supposed
+    to be part of that, this is [ticket:2491].
+
 - oracle
   - [bug] Added ROWID to oracle.*, [ticket:2483]
 

lib/sqlalchemy/ext/declarative.py

             if k in inherited_mapper._props:
                 p = inherited_mapper._props[k]
                 if isinstance(p, ColumnProperty):
-                    # note here we place the superclass column
-                    # first.  this corresponds to the 
-                    # append() in mapper._configure_property().
-                    # change this ordering when we do [ticket:1892]
-                    our_stuff[k] = p.columns + [col]
+                    # note here we place the subclass column
+                    # first.  See [ticket:1892] for background.
+                    our_stuff[k] = [col] + p.columns
 
 
     cls.__mapper__ = mapper_cls(cls, 

test/ext/test_declarative.py

 
         assert A.__mapper__.inherits is a_1.__mapper__
 
+class OverlapColPrecedenceTest(DeclarativeTestBase):
+    """test #1892 cases when declarative does column precedence."""
+
+    def _run_test(self, Engineer, e_id, p_id):
+        p_table = Base.metadata.tables['person']
+        e_table = Base.metadata.tables['engineer']
+        assert Engineer.id.property.columns[0] is e_table.c[e_id]
+        assert Engineer.id.property.columns[1] is p_table.c[p_id]
+
+    def test_basic(self):
+        class Person(Base):
+            __tablename__ = 'person'
+            id = Column(Integer, primary_key=True)
+
+        class Engineer(Person):
+            __tablename__ = 'engineer'
+            id = Column(Integer, ForeignKey('person.id'), primary_key=True)
+
+        self._run_test(Engineer, "id", "id")
+
+    def test_alt_name_base(self):
+        class Person(Base):
+            __tablename__ = 'person'
+            id = Column("pid", Integer, primary_key=True)
+
+        class Engineer(Person):
+            __tablename__ = 'engineer'
+            id = Column(Integer, ForeignKey('person.pid'), primary_key=True)
+
+        self._run_test(Engineer, "id", "pid")
+
+    def test_alt_name_sub(self):
+        class Person(Base):
+            __tablename__ = 'person'
+            id = Column(Integer, primary_key=True)
+
+        class Engineer(Person):
+            __tablename__ = 'engineer'
+            id = Column("eid", Integer, ForeignKey('person.id'), primary_key=True)
+
+        self._run_test(Engineer, "eid", "id")
+
+    def test_alt_name_both(self):
+        class Person(Base):
+            __tablename__ = 'person'
+            id = Column("pid", Integer, primary_key=True)
+
+        class Engineer(Person):
+            __tablename__ = 'engineer'
+            id = Column("eid", Integer, ForeignKey('person.pid'), primary_key=True)
+
+        self._run_test(Engineer, "eid", "pid")
+
+
+
 from test.orm.test_events import _RemoveListeners
 class ConcreteInhTest(_RemoveListeners, DeclarativeTestBase):
     def _roundtrip(self, Employee, Manager, Engineer, Boss, polymorphic=True):
         assert len(General.bar.prop.columns) == 1
         assert Specific.bar.prop is not General.bar.prop
         assert len(Specific.bar.prop.columns) == 2
-        assert Specific.bar.prop.columns[0] is General.__table__.c.bar_newname
-        assert Specific.bar.prop.columns[1] is Specific.__table__.c.bar_newname
+        assert Specific.bar.prop.columns[0] is Specific.__table__.c.bar_newname
+        assert Specific.bar.prop.columns[1] is General.__table__.c.bar_newname
 
     def test_column_join_checks_superclass_type(self):
         """Test that the logic which joins subclass props to those