from sqlalchemy import *
db = create_engine( 'sqlite:///:memory:')
meta = BoundMetaData( db)
import sys
meta.engine.echo= 'echo' in sys.argv

table_human = Table( 'human', meta,
    Column( 'age',   type= Integer, ),
    Column( 'name',   type= String, ),
    Column( 'friend_id', Integer, ForeignKey( 'human.db_id',     name= 'friend_id_fk',     use_alter= True, ), ),
    Column( 'db_id',   primary_key= True,   type= Integer, ),
    Column( 'atype',   type= String, ),
)
table_person = Table( 'person', meta,
    Column( 'alias',   type= String, ),
    Column( 'db_id', Integer, ForeignKey( 'human.db_id', ),   primary_key= True, ),
)

meta.create_all()

class Human( object):pass
class VIPerson( Human):pass

pu_human = polymorphic_union( {
                'VIPerson': join( table_human, table_person, table_person.c.db_id == table_human.c.db_id, ),
                'Human': table_human.select( table_human.c.atype == 'Human', ).alias( 'bz4human' ),
                }, None, 'pu_human', ) #tableinh
mapper_Human = mapper( Human, table_human,
            polymorphic_identity= 'Human',
            polymorphic_on= pu_human.c.atype,
            select_table= pu_human,
            )
mapper_Human.add_property( 'friend', relation( Human,
            foreign_keys= table_human.c.friend_id,
            lazy= True,
            post_update= True,
            primaryjoin= table_human.c.friend_id == table_human.c.db_id,
            remote_side= table_human.c.db_id,
            uselist= False,
            ) )

mapper_Person = mapper( VIPerson, table_person,
            inherit_condition= table_person.c.db_id == table_human.c.db_id,
            inherits= mapper_Human,
            polymorphic_identity= 'VIPerson',
            )

session = create_session()
a = VIPerson()
a.name = 'aa'
a.age = '22'
b = VIPerson()
b.name='bb'
b.age='33'
b.friend = a
a.friend = b
session.save(a)
session.save(b)
session.flush()
session.clear()

if 1: # ok
    t1 = table_human.alias()
    q = session.query( VIPerson).select( (table_human.c.friend_id==t1.c.db_id) & (t1.c.age > 25) )
    print [s.name for s in q ]

if 2: # not ok - this is what is needed
    s0 = mapper_Human.select_table
    s1 = s0.alias()
    q = session.query( Human).select( (s0.c.friend_id == s1.c.db_id) & (s1.c.age > 25) )
    print [s.name for s in q ]

if 3: # not ok either
    t1 = table_human.alias()
    q = session.query( Human).select( (mapper_Human.select_table.c.friend_id == t1.c.db_id) & (t1.c.age > 25) )
    print [s.name for s in q ]

