abstractconcretebase doesn't correctly handle setting up "mixin" columns via name vs. attribute name

Issue #3480 resolved
Mike Bayer repo owner created an issue

without the "key" workarounds uncommented, this fails:

from sqlalchemy.ext.declarative import declarative_base, AbstractConcreteBase
from sqlalchemy.ext.declarative.api import declared_attr
from sqlalchemy.orm.mapper import configure_mappers
from sqlalchemy.orm.session import Session
from sqlalchemy.sql.schema import Column, ForeignKey
from sqlalchemy.sql.sqltypes import Date, String, Integer

Base = declarative_base()


class Company(Base):
    __tablename__ = 'companies'
    id = Column(Integer, primary_key=True)


class Document(object):
    date = Column(Date)
    documentType = Column('documenttype', String) #, key="documentType")


class ContactDocument(AbstractConcreteBase, Base, Document):
    contactPersonName = Column('contactpersonname', String) #, key="contactPersonName")
    salesPersonName = Column(String)
    sendMethod = Column('sendmethod', String) #, key="sendMethod")

    @declared_attr
    def company_id(self):
        return Column(ForeignKey('companies.id'))


class Offer(ContactDocument):
    __tablename__ = 'offers'

    id = Column(Integer, primary_key=True)


class SalesOrder(ContactDocument):
    __tablename__ = 'orders'

    id = Column(Integer, primary_key=True)


configure_mappers()
session = Session()
query = session.query(ContactDocument)
print(query)
#!


  File "/Users/classic/dev/sqlalchemy/lib/sqlalchemy/orm/mapper.py", line 627, in __init__
    self._configure_properties()
  File "/Users/classic/dev/sqlalchemy/lib/sqlalchemy/orm/mapper.py", line 1284, in _configure_properties
    self._configure_property(key, prop, False)
  File "/Users/classic/dev/sqlalchemy/lib/sqlalchemy/orm/mapper.py", line 1525, in _configure_property
    prop = self._property_from_column(key, prop)
  File "/Users/classic/dev/sqlalchemy/lib/sqlalchemy/orm/mapper.py", line 1679, in _property_from_column
    "attribute." % (key, self, c))
sqlalchemy.exc.ArgumentError: When configuring property 'documentType' on Mapper|ContactDocument|pjoin, column 'documenttype' is not represented in the mapper's table. Use the `column_property()` function to force this column to be mapped as a read-only attribute.

Comments (6)

  1. Mike Bayer reporter

    not strictly a regression. 0.9 is broken as well, the column is still mapped incorrectly:

    from sqlalchemy import Column
    from sqlalchemy.ext.declarative import declarative_base, AbstractConcreteBase
    from sqlalchemy.orm.mapper import configure_mappers
    from sqlalchemy.orm.session import Session
    from sqlalchemy.sql.sqltypes import Date, String, Integer
    
    Base = declarative_base()
    
    
    class Document(AbstractConcreteBase, Base):
        date = Column(Date)
        documentType = Column('documenttype', String)
    
    
    class Offer(Document):
        __tablename__ = 'offers'
    
        id = Column(Integer, primary_key=True)
    
    configure_mappers()
    session = Session()
    print session.query(Document.documentType)
    

    output:

    SELECT documenttype AS documenttype
    

    whereas with key:

    documentType = Column('documenttype', String, key="documentType")
    

    we get the expected:

    #!
    
    
    SELECT pjoin.documenttype AS pjoin_documenttype 
    FROM (SELECT offers.date AS date, offers.documenttype AS documenttype, offers.id AS id, None AS type 
    FROM offers) AS pjoin
    

    the bug is in all versions and is based on the fact that the base ABC is mapped to "pjoin", but no step is performed to go through the "properties" of what is to be mapped on the base and refer them from pjoin.

  2. Mike Bayer reporter
    • 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

    → <<cset b68c9ac93eea>>

  3. Mike Bayer reporter

    well it wasn't :) ive refactored declarative a lot for 1.0 to make this kind of thing more flexible.

  4. Log in to comment