On Aug 17, 2010, at 6:23 AM, jean-philippe serafin wrote:

> ok, everything is working as expected....
> 
> thanks, SQLAlchemy just rocks!

I've added a patch in ticket 1895:

http://www.sqlalchemy.org/trac/ticket/1895

The patch passes all tests, and will most likely be applied for SQLAlchemy 0.7 
and simplifies how the "polymorphic identity" is set on an instance.   With it, 
your original test passes, as the "class_name" attribute is assigned at object 
construction time which affects the column on both mapped tables.  It also 
takes a little bit of overhead out of the flush so its my favorite kind of 
patch.


> 
> 2010/8/17 jean-philippe serafin <serafi...@gmail.com>
> ok, thanks for your aswers, I'll try it tonight.
> 
> 2010/8/17 Michael Bayer <mike...@zzzcomputing.com>
> 
> 
> On Aug 16, 2010, at 4:20 AM, jean-philippe serafin wrote:
> 
>> AbstractA is AbstractB "base" class.........
>> AbstractB is ClassA "base" class............
>> 
>> Everything work fine in this case.
>> 
>> I just want to set 'polymorphic_identity' on each inheritance level 
>> if I set by hand : update abstract_a set class_name = 'class_a' :
>> AbstractA.query.first() give me back a ClassA object
> 
> 
> The reason you can't easily set "class_name" on the base is that you've named 
> the attribute the same thing on both AbstractA and AbstractB.  So 
> AbstractB.class_name will never affect the basemost attribute on AbstractA.   
> If you name them differently, your constructor can ensure they are set:
> 
>    def __init__(self, label):
>        self.label = label
>        self.class_name_a = self.class_name_b = self.__tablename__
> 
> But what works better, merge them on AbstractB (still remove the unnecessary 
> polymorphic_on from B, however), the value gets propagated to that of 
> AbstractB:
> 
> class AbstractA(Base):
> 
>    __tablename__ = "abstract_a"
> 
>    id = Column(Integer, primary_key=True)
>    class_name = Column('class_name', String(50))
> 
>    __mapper_args__ = {
>        'polymorphic_on': class_name,
>    }
> 
> class AbstractB(AbstractA):
> 
>    __tablename__ = "abstract_b"
> 
>    id = Column(Integer, ForeignKey('abstract_a.id'),primary_key=True)
>    class_name = column_property(Column('class_name', String(50)), 
> AbstractA.__table__.c.class_name)
> 
>    __mapper_args__ = {
>        'polymorphic_identity': __tablename__,
>    }
> 
> 
> Note however, it is not possible to load a ClassA object without querying at 
> the very least "abstract_a".   So the "class_name" column of "abstract_a" is 
> always available with regular polymorphic querying.  Its redundant and less 
> normalized to have "class_name" on both tables with the same value  
> (technically its not normalized in the first place to have a discriminator 
> column at all, though it has a dramatically positive effect on our ability to 
> locate subtypes without many outer joins).   So there's no reason I can think 
> of why you'd want class_name on B.   But even if you did, there's still no 
> reason to ever put polymorphic_on on a non-base table with the current 
> implementation, and that should still be changed to emit a warning (#1880)- 
> even here it would have alerted you to the issue.
> 
> 
> 
>> 
>> 
>> 2010/8/15 Michael Bayer <mike...@zzzcomputing.com>
>> 
>> On Aug 15, 2010, at 6:52 AM, jean-philippe serafin wrote:
>> 
>> > Hi,
>> >
>> > I've got a class mapping with two polymorphic inheritance :
>> >
>> > class AbstractA(Base):
>> >
>> >    __tablename__ = "abstract_a"
>> >
>> >    id = Column(Integer, primary_key=True)
>> >    class_name = Column('class_name', String(50))
>> >
>> >    __mapper_args__ = {
>> >        'polymorphic_on': class_name,
>> >    }
>> >    #some stuff here
>> >
>> > class AbstractB(AbstractA):
>> >
>> >    __tablename__ = "abstract_b"
>> >
>> >    id = Column(Integer, ForeignKey('abstract_a.id'),
>> > primary_key=True)
>> >    class_name = Column('class_name', String(50))
>> >
>> >    __mapper_args__ = {
>> >        'polymorphic_on': class_name,
>> >        'polymorphic_identity': __tablename__,
>> >    }
>> >    #some stuff here
>> >
>> > class ClassA(AbstractB):
>> >
>> >    __tablename__ = "table_a"
>> >    __mapper_args__ = {
>> >        'polymorphic_identity': __tablename__,
>> >    }
>> >
>> >    id = Column(Integer, ForeignKey('abstract_b.id'),
>> > primary_key=True)
>> >    label = Column('label', String(50))
>> >
>> >    def __init__(self, label):
>> >        self.label = label
>> >
>> > I persist a ClassA object :
>> >
>> > object = ClassA('toto')
>> > db_session.add(object)
>> > db_session.commit()
>> >
>> > When I try to reload the object like this :
>> >
>> > reloaded_object = AbstractB.query.first()
>> >
>> > I get back a ClassA object (just fine)
>> >
>> > but when I try to reload like this :
>> >
>> > reloaded_object = AbstractA.query.first()
>> >
>> > I get back a AbstractA object because abstract_a.class_name has not
>> > been set to polymorphic_identity.
>> >
>> > Is this an issue or expected work?
>> 
>> polymorphic_on only goes on the base class.    SQLA should be changed to 
>> raise an error on the setup you have above.
>> 
>> 
>> >
>> > --
>> > You received this message because you are subscribed to the Google Groups 
>> > "sqlalchemy" group.
>> > To post to this group, send email to sqlalch...@googlegroups.com.
>> > To unsubscribe from this group, send email to 
>> > sqlalchemy+unsubscr...@googlegroups.com.
>> > For more options, visit this group at 
>> > http://groups.google.com/group/sqlalchemy?hl=en.
>> >
>> 
>> --
>> You received this message because you are subscribed to the Google Groups 
>> "sqlalchemy" group.
>> To post to this group, send email to sqlalch...@googlegroups.com.
>> To unsubscribe from this group, send email to 
>> sqlalchemy+unsubscr...@googlegroups.com.
>> For more options, visit this group at 
>> http://groups.google.com/group/sqlalchemy?hl=en.
>> 
>> 
>> 
>> -- 
>> You received this message because you are subscribed to the Google Groups 
>> "sqlalchemy" group.
>> To post to this group, send email to sqlalch...@googlegroups.com.
>> To unsubscribe from this group, send email to 
>> sqlalchemy+unsubscr...@googlegroups.com.
>> For more options, visit this group at 
>> http://groups.google.com/group/sqlalchemy?hl=en.
> 
> 
> -- 
> You received this message because you are subscribed to the Google Groups 
> "sqlalchemy" group.
> To post to this group, send email to sqlalch...@googlegroups.com.
> To unsubscribe from this group, send email to 
> sqlalchemy+unsubscr...@googlegroups.com.
> For more options, visit this group at 
> http://groups.google.com/group/sqlalchemy?hl=en.
> 
> 
> 
> -- 
> You received this message because you are subscribed to the Google Groups 
> "sqlalchemy" group.
> To post to this group, send email to sqlalch...@googlegroups.com.
> To unsubscribe from this group, send email to 
> sqlalchemy+unsubscr...@googlegroups.com.
> For more options, visit this group at 
> http://groups.google.com/group/sqlalchemy?hl=en.

-- 
You received this message because you are subscribed to the Google Groups 
"sqlalchemy" group.
To post to this group, send email to sqlalch...@googlegroups.com.
To unsubscribe from this group, send email to 
sqlalchemy+unsubscr...@googlegroups.com.
For more options, visit this group at 
http://groups.google.com/group/sqlalchemy?hl=en.

Reply via email to