Hello,

It took me a couple of days to narrow this down. It appears that when
object inherits from another object via joined table inheritance (I
haven't tested the other two inheritance modes), mapped attributes
defined as SQL expressions don't load correctly.

In the example below I have a Party object, which can be a Person or a
Company. The Person object has a mapped attribute "full_name", which
is simply first and last name concatenated with the space (similar to
the example in SQLALchemy documentation). Querying on Party and then
accessing this property returns None. Strangely, if we queried on
Person during the same session, subsequent query on Party would work.

I've attached a fully self-contained test case below; just replace
DB_URI with the correct value for you and the bug can be reproduced by
executing the code.

My setup:
Python 2.5 (r25:51908, Sep 19 2006, 09:52:17) [MSC v.1310 32 bit
(Intel)] on win32
SQLAlchemy 0.5.5

<code>

from sqlalchemy import create_engine, Table, Column, Integer, String,
MetaData, ForeignKey
from sqlalchemy.orm import mapper, relation, backref, column_property,
sessionmaker
from sqlalchemy.sql import select, func

DB_URI='postgres://postg...@localhost/postgres' #Replace this
accordingly
db_engine=create_engine(DB_URI, echo=True)
metadata = MetaData()

parties=Table('parties', metadata,
              Column('id', Integer, primary_key=True),
              Column('type', String(1), nullable=False) #This field
needed for joined table inheritance
              )

class Party(object):
    pass

persons=Table('persons', metadata,
              Column('id', Integer, ForeignKey('parties.id'),
primary_key=True), #Foreign key needed for joined table inheritance
              Column('first_name', String(50)),
              Column('last_name', String(50))
              )

class Person(Party):
    def __init__(self, first_name, last_name):
        self.first_name=first_name
        self.last_name=last_name

companies=Table('companies', metadata,
                Column('id', Integer, ForeignKey('parties.id'),
primary_key=True),
                Column('name', String(50)),
                Column('tax_id', String(10))
                )

class Company(Party):
    def __init__(self, name, tax_id):
        self.name=name
        self.tax_id=tax_id

mapper(Party, parties, polymorphic_on=parties.c.type,
polymorphic_identity='T')
mapper(Person, persons, inherits=Party, polymorphic_identity='P',
properties={
    'full_name': column_property((persons.c.first_name + ' ' +
persons.c.last_name).label('full_name'))
})
mapper(Company, companies, inherits=Party, polymorphic_identity='C')

if __name__ == '__main__':
    metadata.create_all(db_engine)
    s=sessionmaker(bind=db_engine)()
    s.add_all([Person('John', 'Smith'), Company('ACME Inc.', '1234')])
    s.commit()
    try:
        #Weird - if the following two lines were run before the
subsequent query, final assert wouldn't fail!!
        #all_persons=s.query(Person).all()
        #assert all_persons[0].full_name=='John Smith'

        all_parties=s.query(Party).all()
        #Altough we queried on Party, SQLAlchemy correctly recognizes
that second object is a copmany, as per specification
        assert all_parties[1].tax_id=='1234'
        #However, for SQL expression mapped atributes it returns None
instead of the stored value.
        #SQLAlchemy documentation clearly states that this should work
- see section "Controlling Which Tables are Queried".
        #BTW, this failure doesn't happen for objects that are not
part of inheritance hierarchy.
        assert all_parties[0].full_name=='John Smith'
    finally:
        s.close()
        metadata.drop_all(db_engine)

</code>

--~--~---------~--~----~------------~-------~--~----~
You received this message because you are subscribed to the Google Groups 
"sqlalchemy" group.
To post to this group, send email to sqlalchemy@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