From b68c9ac93eea62a1f4ae2c0701e5af7c432e9432 Mon Sep 17 00:00:00 2001 From: Mike Bayer Date: Mon, 13 Jul 2015 15:39:04 -0400 Subject: - Fixed bug in :class:`.AbstractConcreteBase` extension where a column setup on the ABC base which had a different attribute name vs. column name would not be correctly mapped on the final base class. The failure on 0.9 would be silent whereas on 1.0 it raised an ArgumentError, so may not have been noticed prior to 1.0. fixes #3480 --- doc/build/changelog/changelog_10.rst | 11 +++++++++++ lib/sqlalchemy/ext/declarative/api.py | 13 ++++++++++++- lib/sqlalchemy/ext/declarative/base.py | 1 - test/ext/declarative/test_inheritance.py | 30 ++++++++++++++++++++++++++++++ 4 files changed, 53 insertions(+), 2 deletions(-) diff --git a/doc/build/changelog/changelog_10.rst b/doc/build/changelog/changelog_10.rst index 8ac3d5844..b5372be68 100644 --- a/doc/build/changelog/changelog_10.rst +++ b/doc/build/changelog/changelog_10.rst @@ -18,6 +18,17 @@ .. changelog:: :version: 1.0.7 + .. change:: + :tags: bug, orm, declarative + :tickets: 3480 + + Fixed bug in :class:`.AbstractConcreteBase` extension where + a column setup on the ABC base which had a different attribute + name vs. column name would not be correctly mapped on the final + base class. The failure on 0.9 would be silent whereas on + 1.0 it raised an ArgumentError, so may not have been noticed + prior to 1.0. + .. change:: :tags: bug, orm :tickets: 3469 diff --git a/lib/sqlalchemy/ext/declarative/api.py b/lib/sqlalchemy/ext/declarative/api.py index 3d46bd4cb..dfc47ce95 100644 --- a/lib/sqlalchemy/ext/declarative/api.py +++ b/lib/sqlalchemy/ext/declarative/api.py @@ -7,7 +7,7 @@ """Public API functions and helpers for declarative.""" -from ...schema import Table, MetaData +from ...schema import Table, MetaData, Column from ...orm import synonym as _orm_synonym, \ comparable_property,\ interfaces, properties, attributes @@ -525,6 +525,17 @@ class AbstractConcreteBase(ConcreteBase): mappers.append(mn) pjoin = cls._create_polymorphic_union(mappers) + # For columns that were declared on the class, these + # are normally ignored with the "__no_table__" mapping, + # unless they have a different attribute key vs. col name + # and are in the properties argument. + # In that case, ensure we update the properties entry + # to the correct column from the pjoin target table. + declared_cols = set(to_map.declared_columns) + for k, v in list(to_map.properties.items()): + if v in declared_cols: + to_map.properties[k] = pjoin.c[v.key] + to_map.local_table = pjoin m_args = to_map.mapper_args_fn or dict diff --git a/lib/sqlalchemy/ext/declarative/base.py b/lib/sqlalchemy/ext/declarative/base.py index 57eb54f63..57305748c 100644 --- a/lib/sqlalchemy/ext/declarative/base.py +++ b/lib/sqlalchemy/ext/declarative/base.py @@ -463,7 +463,6 @@ class _MapperConfig(object): def _prepare_mapper_arguments(self): properties = self.properties - if self.mapper_args_fn: mapper_args = self.mapper_args_fn() else: diff --git a/test/ext/declarative/test_inheritance.py b/test/ext/declarative/test_inheritance.py index 3e6980190..274a6aa28 100644 --- a/test/ext/declarative/test_inheritance.py +++ b/test/ext/declarative/test_inheritance.py @@ -1453,3 +1453,33 @@ class ConcreteExtensionConfigTest( "FROM actual_documents) AS pjoin" ) + def test_column_attr_names(self): + """test #3480""" + + class Document(Base, AbstractConcreteBase): + documentType = Column('documenttype', String) + + class Offer(Document): + __tablename__ = 'offers' + + id = Column(Integer, primary_key=True) + __mapper_args__ = { + 'polymorphic_identity': 'offer' + } + + configure_mappers() + session = Session() + self.assert_compile( + session.query(Document), + "SELECT pjoin.documenttype AS pjoin_documenttype, " + "pjoin.id AS pjoin_id, pjoin.type AS pjoin_type FROM " + "(SELECT offers.documenttype AS documenttype, offers.id AS id, " + "'offer' AS type FROM offers) AS pjoin" + ) + + self.assert_compile( + session.query(Document.documentType), + "SELECT pjoin.documenttype AS pjoin_documenttype FROM " + "(SELECT offers.documenttype AS documenttype, offers.id AS id, " + "'offer' AS type FROM offers) AS pjoin" + ) -- cgit v1.2.1