#$Id$
# -*- coding: cp1251 -*-
from sqlalchemy import *
db = create_engine( 'sqlite:///:memory:')
meta = BoundMetaData( db)
meta.engine.echo = True
import logging
logging.getLogger('sqlalchemy.orm').setLevel( logging.DEBUG)

class Base( object):
    _dataname = 'name'
    def __str__( obj):
        idname = 'db_id'
        r = obj.__class__.__name__ +'/id'+ str( getattr( obj, idname)) +'('
        for k in obj.props:
            v = getattr( obj, k, '<notset>')
            if isinstance( v, Base):
                vv = '>' + v.__class__.__name__ +'/id'+ str( getattr( v, idname))
                try: vv += '/'+ str( v._namer)
                except AttributeError: pass
                v = vv
            r+= ' '+k+'='+str(v)
        return r+' )'

#====generated SA set-up

table_Entity = Table( 'Entity', meta,
    Column( 'disabled',   type= Boolean, ),
#    Column( 'obj_id', Integer, Sequence('bozibo',start=None,increment=None,optional=False), ),
    Column( 'db_id',   primary_key= True,   type= Integer, ),
    Column( 'atype',   type= String, ),
)
table_Name = Table( 'Name', meta,
    Column( 'ime',   type= String, ),
    Column( 'db_id',   primary_key= True,   type= Integer, ),
)
table_Person = Table( 'Person', meta,
    Column( 'ime_id', Integer, ForeignKey( 'Name.db_id', ), ),
    Column( 'address_id', Integer, ForeignKey( 'Address.db_id', ), ),
    Column( 'passport_id', Integer, ForeignKey( 'Passport.db_id', ), ),
    Column( 'db_id', Integer, ForeignKey( 'Entity.db_id', ),   primary_key= True, ),
)
table_Passport = Table( 'Passport', meta,
    Column( 'number',   type= String, ),
    Column( 'db_id',   primary_key= True,   type= Integer, ),
)
table_Address = Table( 'Address', meta,
    Column( 'details',   type= String, ),
    Column( 'darzhava_id', Integer, ForeignKey( 'Darzhava.db_id', ), ),
    Column( 'db_id',   primary_key= True,   type= Integer, ),
)
table_Nomenclature = Table( 'Nomenclature', meta,
    Column( 'code',   type= String, ),
    Column( 'ime_id', Integer, ForeignKey( 'Name.db_id', ), ),
    Column( 'db_id', Integer, ForeignKey( 'Entity.db_id', ),   primary_key= True, ),
)
table_Darzhava = Table( 'Darzhava', meta,
    Column( 'db_id', Integer, ForeignKey( 'Nomenclature.db_id', ),   primary_key= True, ),
)

meta.create_all()
Element = Base
class Entity( Element):
    props = ['db_id', 'disabled', ]
class Name( Element):
    props = ['db_id', 'ime']
class Person( Entity):
    props = ['db_id', 'ime', 'address', 'disabled', 'passport', ]
class Nomenclature( Entity):
    props = ['db_id', 'code', 'ime', 'disabled', ]
class Darzhava( Nomenclature):
    props = ['db_id', 'code', 'ime', 'disabled', ]
class Address( Element):
    props = ['db_id', 'details', 'darzhava']
class Passport( Element):
    props = ['db_id', 'number', ]


pu_entity = polymorphic_union( {
                'Person': join( table_Entity, table_Person, table_Person.c.db_id == table_Entity.c.db_id, ),
                'Darzhava': join( join( table_Entity, table_Nomenclature, table_Nomenclature.c.db_id == table_Entity.c.db_id, ), table_Darzhava, table_Darzhava.c.db_id == table_Nomenclature.c.db_id, ),
                }, None, 'pu_entity', ) #tableinh
mapper_Entity = mapper( Entity, table_Entity,
            polymorphic_identity= 'Entity',
            polymorphic_on= pu_entity.c.atype,
            select_table= pu_entity,
            )
mapper_Address = mapper( Address, table_Address,
            polymorphic_identity= 'Address',
            )

mapper_Address.add_property( 'darzhava', relation( Darzhava,
            foreign_keys= table_Address.c.darzhava_id,
            lazy= True,
            primaryjoin= table_Address.c.darzhava_id == table_Darzhava.c.db_id,
            remote_side= table_Darzhava.c.db_id,
            uselist= False,
            ) )

pu_nomenclature = polymorphic_union( {
                'Darzhava': join( join( table_Entity, table_Nomenclature, table_Nomenclature.c.db_id == table_Entity.c.db_id, ), table_Darzhava, table_Darzhava.c.db_id == table_Nomenclature.c.db_id, ),
                }, None, 'pu_nomenclature', ) #tableinh
mapper_Nomenclature = mapper( Nomenclature, table_Nomenclature,
            inherit_condition= table_Nomenclature.c.db_id == table_Entity.c.db_id,
            inherits= mapper_Entity,
            polymorphic_identity= 'Nomenclature',
            polymorphic_on= pu_nomenclature.c.atype,
            select_table= pu_nomenclature,
            )
mapper_Nomenclature.add_property( 'ime', relation( Name,
            foreign_keys= table_Nomenclature.c.ime_id,
            lazy= False,
            primaryjoin= table_Nomenclature.c.ime_id == table_Name.c.db_id,
            remote_side= table_Name.c.db_id,
            uselist= False,
            ) )

mapper_Darzhava = mapper( Darzhava, table_Darzhava,
            inherit_condition= table_Darzhava.c.db_id == table_Nomenclature.c.db_id,
            inherits= mapper_Nomenclature,
            polymorphic_identity= 'Darzhava',
            )


mapper_Name = mapper( Name, table_Name,
            polymorphic_identity= 'Name',
            )

mapper_Passport = mapper( Passport, table_Passport,
            polymorphic_identity= 'Passport',
            )

mapper_Person = mapper( Person, table_Person,
            inherit_condition= table_Person.c.db_id == table_Entity.c.db_id,
            inherits= mapper_Entity,
            polymorphic_identity= 'Person',
            )
mapper_Person.add_property( 'ime', relation( Name,
            foreign_keys= table_Person.c.ime_id,
            lazy= False,
            primaryjoin= table_Person.c.ime_id == table_Name.c.db_id,
            remote_side= table_Name.c.db_id,
            uselist= False,
            ) )

mapper_Person.add_property( 'passport', relation( Passport,
            foreign_keys= table_Person.c.passport_id,
            lazy= False,
            primaryjoin= table_Person.c.passport_id == table_Passport.c.db_id,
            remote_side= table_Passport.c.db_id,
            uselist= False,
            ) )
mapper_Person.add_property( 'address', relation( Address,
            foreign_keys= table_Person.c.address_id,
            lazy= False,
            primaryjoin= table_Person.c.address_id == table_Address.c.db_id,
            remote_side= table_Address.c.db_id,
            uselist= False,
            ) )

#========= eo generated SA set-up

session = create_session()
p = Person()
p.ime = Name()
p.ime.ime = 'john'
p.address = a = Address()
p.passport = u = Passport()

session.save( p)
session.flush()

session.clear()
q = session.query(Person)
for a in q: print a

