Hi,

I have a situation where the dependency solver of the session fails to
correctly choose the order of the sql commands. The effect of that is
that some inserts in tables fail due to foreign key constraint
violations. For example an object in table A has a foreign key
referencing an object in table B, so the dependency solver should
choose the following order: insert object of B, then insert object of
A.

This happens with a joined table inheritance database model.

As a workaround, it is possible to manually do the operation in the
right order and call session.flush after each operation, but i would
prefer to either understand what i am doing wrong or have the bug
fixed in sqlalchemy.

i have a simple test case for reproducing the bug (tested with 0.4.8
and 0.5.2):

# -*- 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