Hi,

I'm struggling trying to merge two patterns which separately are no-
brainers in sqa: joined tabled inheritance and (an arbitrary number
of) graph relationships, here represented as connections and
dependencies. I've run into quite a few different errors from the
following code using version 0.5.3:

(most recently)

sqlalchemy.orm.exc.UnmappedColumnError: Can't execute sync rule for
source column 'dep_dependency.parent_id'; mapper 'Mapper|Component|
dep_group_components' does not map this column.  Try using an explicit
`foreign_keys` collection which does not include destination column
'dep_group_components.group_id' (or use a viewonly=True relation).

(and when the foreign_keys is blank)

sqlalchemy.exc.ArgumentError: Could not determine relation direction
for secondaryjoin condition 'dep_groups INNER JOIN
dep_group_components ON dep_groups.group_id =
dep_group_components.group_id INNER JOIN dep_dependency ON
dep_group_components.group_id = dep_dependency.child_id', on relation
Component.dependents. Specify the foreign_keys argument to indicate
which columns on the relation are foreign.

Any thoughts on what to do here? I'm fully stumped at this point. I
should note that I've tried using a polymorphic_union (for locating
the value of the polymorphic_on and for primary and secondaryjoin in
relations). That only yields sql code with multiple definitions of
'type'.

Many thanks,
-thomas

---

from sqlalchemy import create_engine
from sqlalchemy.ext.declarative import declarative_base,
DeclarativeMeta
from sqlalchemy.orm import sessionmaker, scoped_session,
create_session
from sqlalchemy import  Table, Column, Integer, String, Date,
DateTime, Time, \
                        MetaData, ForeignKey, Boolean,
ForeignKeyConstraint
from sqlalchemy.schema import UniqueConstraint, CheckConstraint
from sqlalchemy.orm import backref, mapper, relation, reconstructor,
polymorphic_union
from sqlalchemy import and_, or_

ENGINE_URL = 'mysql://'

TYPE_GROUP = 'group'
TYPE_COMPONENT = 'comp'

Base = declarative_base()
metadata = MetaData()
Base.metadata = metadata

engine = create_engine( ENGINE_URL, echo=False)

class Group(object):
    def __repr__(self):
        return "<Group( %s )>" % self.name

    def __init__(self, name=None, expired=False):
        """
        Note that self.type is automatically populated when
polymorphic_on is
        configued in Group's mapper.
        """
        self.name = name
        self.expired = expired

class DependencyHolderGroup(Group):
    def __init__(self, name=None, version=None, expired=False):
        self.name = name
        self.version = version
        self.expired = expired

class Component(DependencyHolderGroup):
    pass

dep_groups = Table('dep_groups', metadata,

    Column('group_id', Integer, primary_key=True),
    Column('type', String(8)),
    Column('name', String(100), unique=True),
    Column('expired', Boolean),

    UniqueConstraint('name', 'type', name='name_type_x'),

    mysql_engine = 'InnoDb'
)

connections_table = Table('dep_connections', metadata,
    Column('parent_id', Integer, ForeignKey('dep_groups.group_id')),
    Column('child_id', Integer, ForeignKey('dep_groups.group_id')),

    mysql_engine='InnoDb'
)

dependencies_table = Table('dep_dependency', metadata,
    Column('parent_id', Integer, ForeignKey('dep_groups.group_id')),
    Column('child_id', Integer, ForeignKey('dep_groups.group_id')),

    mysql_engine='InnoDb'
)

dep_group_components = Table('dep_group_components', metadata,

    Column('group_id', Integer, ForeignKey('dep_groups.group_id'),
primary_key=True),
    Column('group_name', String(100)),
    Column('version', String(50)),

    # ForeignKeyConstraint(['group_name'], ['dep_groups.name']),
    # UniqueConstraint('group_name', 'version',
name='name_version_x'),
    # CheckConstraint('type == %s' % TYPE_COMPONENT,
name='type_comp_x'),
    CheckConstraint('dependents.type != "set"',
name='no_set_child_x'),

    mysql_engine = 'InnoDb'
)

groups_mapper = mapper(Group,

    dep_groups,
    order_by=['name'],
    polymorphic_on=dep_groups.c.type,
    polymorphic_identity=TYPE_GROUP,
    properties={

    'children':relation(Group, lazy=False,
    primaryjoin=dep_groups.c.group_id==connections_table.c.parent_id,
    secondaryjoin=dep_groups.c.group_id==connections_table.c.child_id,
    secondary=connections_table, backref='parents', cascade='all'),
})

primary = dep_groups.join(dep_group_components,
 
dep_groups.c.group_id==dep_group_components.c.group_id).join
(dependencies_table,
 
dep_group_components.c.group_id==dependencies_table.c.parent_id)
secondary = dep_groups.join(dep_group_components,
 
dep_groups.c.group_id==dep_group_components.c.group_id).join
(dependencies_table,
 
dep_group_components.c.group_id==dependencies_table.c.child_id)

components_mapper = mapper(Component,

        dep_group_components,
        inherits=Group,
        order_by=['name','version'],
        polymorphic_identity=TYPE_COMPONENT,
        properties={

        'dependents': relation(Group,
        foreign_keys=[  dep_group_components.c.group_id,
                        dependencies_table.c.parent_id,
                        dependencies_table.c.child_id  ],
        primaryjoin=primary.onclause,
secondaryjoin=secondary.onclause,
        secondary=dependencies_table) # backref='dep_parents',
cascade='all'),
})

if __name__ == '__main__':

    metadata.bind = engine
    metadata.create_all()
    s = scoped_session(sessionmaker(bind=engine, autoflush=True))()
    #s = create_session(bind=engine, autoflush=True, autocommit=True)
# for sqlite
    g1 = Group(name='g1')
    g2 = Group(name='g2')
    g1.children.append(g2)
    s.add(g1)
    s.add(g2)
    c = Component(name='c1', version='1')
    c.dependents.append(g1)
    s.add(c)
    s.commit()

--~--~---------~--~----~------------~-------~--~----~
You received this message because you are subscribed to the Google Groups 
"sqlalchemy" group.
To post to this group, send email to sqlalchemy@googlegroups.com
To unsubscribe from this group, send email to 
sqlalchemy+unsubscr...@googlegroups.com
For more options, visit this group at 
http://groups.google.com/group/sqlalchemy?hl=en
-~----------~----~----~----~------~----~------~--~---

Reply via email to