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 [email protected]
To unsubscribe from this group, send email to
[email protected]
For more options, visit this group at
http://groups.google.com/group/sqlalchemy?hl=en
-~----------~----~----~----~------~----~------~--~---