you have inter-row dependencies (where a "row" here represents a  
joined row from base table to child table), which SQLAlchemy only  
detects at the mapped object level, not the interdependent column  
level (SQLA doesn't have any intelligence attached to the setting of  
foreign key attributes).  So you have to set the relationships between  
A and B objects using the relation()s:

b1 = ChildB(key = "b1", data_b = "azerty", link_a=a1)
b2 = ChildB(key = "b2", data_b = "ytreza", link_a=a2)

from that, the unit of work detects that b1 and b2 are both dependent  
on an A object, which then gets INSERTed first.

ironically, its the presence of the "link_a" relation that sets off  
the "inter-row" dependency logic in the first place.  If this relation  
is set to viewonly=True, the UOW doesn't drop into inter-row  
dependencies, and the order of INSERT among a particular set of  
objects with a common base class is determined by the order in which  
the objects where added to the session, so it works again.


On Mar 7, 2009, at 1:46 PM, Matthieu wrote:

> # -*- coding: utf-8 -*-
>
> # imports from sqlalchemy
> import sqlalchemy
> from sqlalchemy import create_engine, Table, Column, Text, MetaData,
> ForeignKey
> from sqlalchemy.sql import text
> from sqlalchemy.orm import mapper, relation, sessionmaker
>
> class BaseClass(object):
>
>    def __init__(self,
>                 key = None,
>                 data = None,
>                 class_type = "BaseClass"):
>        self.key = key
>        self.data = data
>        self.class_type = class_type
>
> class ChildA(BaseClass):
>
>    def __init__(self,
>                 key = None,
>                 data_a = None,
>                 **kwargs):
>        super(ChildA, self).__init__(key = key, class_type = "ChildA",
> **kwargs)
>        self.data_a = data_a
>
> class ChildB(BaseClass):
>
>    def __init__(self,
>                 key = None,
>                 data_b = None,
>                 key_child_a = None,
>                 **kwargs):
>        super(ChildB, self).__init__(key = key, class_type = "ChildB",
> **kwargs)
>        self.data_b = data_b
>        self.key_child_a = key_child_a
>
> sqla_engine = create_engine("postgres:///sqla-test", echo = True)
> sqla_connexion = sqla_engine.connect()
> sqla_metadata = MetaData()
> sqla_metadata.bind = sqla_engine
> sqla_session_maker = sessionmaker(bind = sqla_engine, autoflush =
> True, autocommit = False)
> sqla_session = sqla_session_maker()
>
> base_class_table = Table(
>    'base_class',
>    sqla_metadata,
>    Column('key', Text, primary_key = True),
>    Column('class_type', Text, nullable = False),
>    Column('data', Text))
>
> child_a_table = Table(
>    'child_a',
>    sqla_metadata,
>    Column('key', Text, ForeignKey('base_class.key'), primary_key =
> True),
>    Column('data_a', Text))
>
> child_b_table = Table(
>    'child_b',
>    sqla_metadata,
>    Column('key', Text, ForeignKey('base_class.key'), primary_key =
> True),
>    Column('data_b', Text),
>    Column('key_child_a', Text, ForeignKey(base_class_table.c.key)))
>
>
> drop_statment = text("""DROP TABLE "child_b"; DROP TABLE "child_a";
> DROP TABLE "base_class" """)
> sqla_connexion.execute(drop_statment)
> sqla_metadata.create_all()
>
>
> mapper(BaseClass,
>       base_class_table,
>       polymorphic_on = base_class_table.c.class_type,
>       polymorphic_identity = "BaseClass")
>
> mapper(ChildA,
>       child_a_table,
>       inherits = BaseClass,
>       polymorphic_identity = "ChildA")
>
> mapper(ChildB,
>       child_b_table,
>       inherits = BaseClass,
>       inherit_condition = child_b_table.c.key ==
> base_class_table.c.key,
>       polymorphic_identity = "ChildB",
>       properties = {
>        'link_a':
>            relation(ChildA,
>                     backref = 'links_b',
>                     primaryjoin = child_b_table.c.key_child_a ==
> base_class_table.c.key)})
>
> a1 = ChildA(key = "a1", data_a = "foo")
> sqla_session.add(a1)
> #sqla_session.flush()
> a2 = ChildA(key = "a2", data_a = "bar")
> sqla_session.add(a2)
> #sqla_session.flush()
> b1 = ChildB(key = "b1", data_b = "azerty", key_child_a = "a1")
> sqla_session.add(b1)
> #sqla_session.flush()
> b2 = ChildB(key = "b2", data_b = "ytreza", key_child_a = "a2")
> sqla_session.add(b2)
> sqla_session.flush()


--~--~---------~--~----~------------~-------~--~----~
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
-~----------~----~----~----~------~----~------~--~---

Reply via email to