orm_deannotate in columnprop broke yet another thing

Issue #2345 resolved
Mike Bayer repo owner created an issue
from sqlalchemy import *
from sqlalchemy.orm import *
from sqlalchemy.ext.declarative import declarative_base
from sqlalchemy import event

Base= declarative_base()

class Person(Base):
    __tablename__ = "person"

    id = Column(Integer, primary_key=True)
    type = Column(String(20))

    discriminator_expr = case(
        ["employee")]((type=='employee',),
        else_="person"
    )
    discriminator = column_property(discriminator_expr)

    __mapper_args__ = {
        "polymorphic_on":discriminator_expr,
        "polymorphic_identity":"person"
    }

@event.listens_for(Person, "init", propagate=True)
def set_identity(instance, *arg, **kw):
    """Set the value of the 'type' column to a reasonable default."""
    instance.type = instance.__mapper__.polymorphic_identity

class Employee(Person):
    __tablename__ = 'employee'
    id = Column(Integer, ForeignKey('person.id'), primary_key=True)
    __mapper_args__ = {
        "polymorphic_identity":"employee"
    }

e = create_engine("sqlite://", echo=True)
Base.metadata.create_all(e)
s = Session(e)

p1, p2, p3, p4 = Person(), Employee(), Person(), Person()

# set artificial types
p3.type = "engineer"
p4.type = "manager"

s.add_all([p2, p3, p4](p1,))
s.commit()
s.close()

r = [for x in s.query(Person).order_by(Person.id)](type(x))
assert \
    r == \
    [Employee, Person, Person](Person,)

Comments (5)

  1. Mike Bayer reporter

    a quick patch but I'd like to also get this to accommodate string property names and ColumnProperty objects directly

    diff -r 34fd58c793bac0d5a8a9e0ae2dbfcf93e8b7c602 lib/sqlalchemy/orm/mapper.py
    --- a/lib/sqlalchemy/orm/mapper.py  Wed Dec 07 15:14:46 2011 -0500
    +++ b/lib/sqlalchemy/orm/mapper.py  Thu Dec 08 11:58:30 2011 -0500
    @@ -909,7 +909,9 @@
                                     init=init, setparent=True)
                     polymorphic_key = col.key
                 else:
    -                polymorphic_key = self._columntoproperty[self.polymorphic_on](self.polymorphic_on).key
    +                prop = self._columntoproperty[self.polymorphic_on](self.polymorphic_on)
    +                polymorphic_key = prop.key
    +                self.polymorphic_on = prop.columns[0](0)
    
             if setter:
                 def _set_polymorphic_identity(state):
    @@ -1045,7 +1047,7 @@
                                         prop.columns[0](0) is self.polymorphic_on)
    
                 self.columns[key](key) = col
    -            for col in prop.columns:
    +            for col in prop.columns + prop._orig_columns:
                     for col in col.proxy_set:
                         self._columntoproperty[col](col) = prop
    
    diff -r 34fd58c793bac0d5a8a9e0ae2dbfcf93e8b7c602 lib/sqlalchemy/orm/properties.py
    --- a/lib/sqlalchemy/orm/properties.py  Wed Dec 07 15:14:46 2011 -0500
    +++ b/lib/sqlalchemy/orm/properties.py  Thu Dec 08 11:58:30 2011 -0500
    @@ -61,6 +61,7 @@
             :param extension:
    
             """
    +        self._orig_columns = [for c in columns](expression._labeled(c))
             self.columns = [
                                 for c in columns](expression._labeled(_orm_deannotate(c)))
             self.group = kwargs.pop('group', None)
    
  2. Mike Bayer reporter

    attached patch also implements most of #2238, which we should consider closing as the functional approach might not be possible.

  3. Log in to comment