Hi,
a month ago I've asked for help with my heterogenous mapping. You've
fixed the provided example and it now it commits. Today I've tried it
and found that SA can't fetch the committed data from the db.

Ideas?

from sqlalchemy import *


global_connect('sqlite://')


element_table = Table('elements',
    Column('element_id', Integer, primary_key=True),
    Column('name', String(128))).create()

detail_table = Table('details',
    Column('element_id', Integer, ForeignKey('elements.element_id'),
        primary_key=True),
    Column('material', String(128), default=''),
    Column('weight', Float, default=0)).create()

assembly_table = Table('assemblies',
    Column('element_id', Integer, ForeignKey('elements.element_id'),
        primary_key=True)).create()

specification_table = Table('specification',
    Column('spec_line_id', Integer, primary_key=True),
    Column('master_id', Integer, ForeignKey("elements.element_id"),
        nullable=False),
    Column('slave_id', Integer, ForeignKey("elements.element_id"),
        nullable=True),
    Column('quantity', Float, default=1)).create()

class Element(object):
    def __repr__(self):
        return '<%s %s>' % (self.__class__.__name__, self.name)

class Detail(Element): pass

class Assembly(Element): pass

class SpecLine(object):
    def __repr__(self):
        return '<%s %.01f %s>' % (self.__class__.__name__,
            self.quantity, getattr(self.slave, 'name', None))

assign_mapper(Element, element_table,
    properties=dict(name=element_table.c.name))


assign_mapper(SpecLine, specification_table, properties=dict(
        _master = relation(Element.mapper, backref="specification"),
        quantity=specification_table.c.quantity
        )
        )

assign_mapper(Assembly, assembly_table, inherits=Element.mapper)

assign_mapper(Detail, detail_table, inherits=Element.mapper)


detail_join = select([element_table,
    detail_table.c.material,
    detail_table.c.weight,
    column("'detail'").label('type')],
    element_table.c.element_id==detail_table.c.element_id)

assembly_join = select([element_table,
    null().label('material'),
    null().label('weight'),
    column("'assembly'").label('type')],
    element_table.c.element_id==assembly_table.c.element_id)

element_type_join = detail_join.union_all(assembly_join).alias('pjoin')


class Extension(MapperExtension):
    def create_instance(ext, mapper, row, imap, class_):
        if row['pjoin_type'] == 'detail':
            return Detail()
        elif row['pjoin_type'] == 'assembly':
            return Assembly()
        else:
            return Element()

element_type_mapper = mapper(Element, element_type_join, extension=Extension())


SpecLine.mapper.add_property('master', relation(element_type_mapper,
            primaryjoin=specification_table.c.master_id==element_type_mapper.c.element_id,
            foreignkey=specification_table.c.master_id,
            lazy=True, uselist=False,
            )
            )
        
SpecLine.mapper.add_property('slave', relation(element_type_mapper,
            primaryjoin=specification_table.c.slave_id==element_type_mapper.c.element_id,
            foreignkey=specification_table.c.slave_id,
            lazy=False, uselist=False),
        )

a1 = Assembly(name='a1')
a1.specification.append(SpecLine())
objectstore.commit()
print a1.specification

a1 = element_type_mapper.selectone_by(name='a1')
print a1.specification

Reply via email to