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