- changed status to resolved
backrefs for polymorphic multi table inheritance doesn't work for relations between children
Issue #259
resolved
Given a hierarchy of: * Parent * Child1 * Child2
Where Child1 has a reference to Child2, creating Child1 with a reference to Child2 doesn't work (Child1 assumes it's primary key is that of Child2). When Child1 is created with NULL reference to Child2, correct primary key is created.
import sqlalchemy as sql
engine = sql.create_engine("sqlite://")
engine.echo=True
meta = sql.BoundMetaData(engine)
devices = sql.Table("devs", meta,
sql.Column("dev_id", sql.types.Integer, primary_key=True),
sql.Column("type", sql.types.String, nullable=False),
sql.Column("name", sql.types.String, nullable=False)
)
r_groups = sql.Table("r_groups", meta,
sql.Column("rg_id", sql.types.Integer, sql.ForeignKey("devs.dev_id"), primary_key=True)
)
routers = sql.Table("routers", meta,
sql.Column("r_id", sql.types.Integer, sql.ForeignKey("devs.dev_id"), primary_key=True),
sql.Column("group_id", sql.types.Integer, sql.ForeignKey("r_groups.rg_id")),
sql.Column("rdata", sql.types.String)
)
class Device(object):
pass
class RouterGroup(Device):
pass
class Router(Device):
pass
dev_join = sql.polymorphic_union(
{
"router": devices.join(routers),
"r_group": devices.join(r_groups),
"device": devices.select(devices.c.type == "device")
}, None, "dev_pjoin"
)
device_mapper = sql.mapper(Device, devices,
select_table=dev_join,
polymorphic_on=dev_join.c.type,
polymorphic_identity="device")
sql.mapper(RouterGroup, r_groups,
inherits=device_mapper,
polymorphic_identity="r_group")
sql.mapper(Router, routers,
inherits=device_mapper,
properties = {
"group": sql.relation(RouterGroup, backref="routers") #doesn't work
# "group": sql.relation(RouterGroup)
},
polymorphic_identity="router")
meta.drop_all()
meta.create_all()
session = sql.create_session(engine)
rg = RouterGroup()
rg.name = "rg1"
session.save(rg)
r1 = Router()
r1.name = "router1"
session.save(r1)
r2 = Router()
r2.name = "router2"
r2.group = rg
session.save(r2)
session.flush()
Comments (1)
-
repo owner - Log in to comment
ive committed a better check for the condition here in changeset:1759, changeset:1760. The error message your program will generate is now:
sqlalchemy.exceptions.ArgumentError: Error determining primary and/or secondary join for relationship 'group' between mappers 'Mapper|Router|routers' and 'Mapper|RouterGroup|r_groups'. You should specify the 'primaryjoin' (and 'secondaryjoin', if there is an association table present) keyword arguments to the relation() function (or for backrefs, by specifying the backref using the backref() function with keyword arguments) to explicitly specify the join conditions. Nested error is "Cant determine join between 'routers' and 'Join object on devs r_groups'; tables have more than one foreign key constraint relationship between them. Please specify the 'onclause' of this join explicitly."
and your fix should now be one of:
or more verbosely: