On Oct 18, 2010, at 2:46 PM, Jasper K wrote: > Hi Group, > > I am using SqlAlchemy 0.5.8 > > I get an "(OperationalError) no such column: child.child_id" error > when trying to eagerload a viewonly many-to-many relationship that > uses the Association Object pattern with a custom secondaryjoin > condition (http://www.sqlalchemy.org/docs/05/mappers.html#association- > object). > > The following example demonstrates the issue. It consists of three > tables: Parent, Child, Association. The goal is to have a mapped > property on the Parent table that filters out certain associations > based on properties stored in the Child table (the Parent is trying to > eagerload all it's "nice children"). It seems the SQL that gets > generated during the eagerload fails to include the Child table. > However when used without the eagerload everything works as expected. > I have not tried this with the newer SqlAlchemy but I would like to > get it working on 0.5.8 if possible.
So "secondary" and "secondaryjoin" only apply to this exact pattern: Parent -> association table -> Child your example is doing this: Parent -> association table -> Association Object The correct mapping, using "secondary", would be: mapper(Parent, parent_table, properties={ 'nice_children': relation(Child, lazy=True, secondary=association_table, primaryjoin=parent_table.c.parent_id==association_table.c.parent_id, secondaryjoin=and_(association_table.c.child_id==child_table.c.child_id, child_table.c.status==NICE), viewonly=True) }) If you'd like to maintain that "nice_children" returns "Association" objects, you'd have to get the link to "child" to be referenced inside the primaryjoin, as the endpoint of the JOIN must be the target of the relation(): mapper(Parent, parent_table, properties={ 'nice_children': relation(Association, lazy=True, primaryjoin=and_( parent_table.c.parent_id==association_table.c.parent_id, association_table.c.child_id.in_(select([child_table.c.child_id]).where(child_table.c.status==NICE)) ), viewonly=True) }) > > Any help is much appreciated, > > Thanks > > > from sqlalchemy import Table, Column, String, Integer, MetaData, > ForeignKey, create_engine, and_ > from sqlalchemy.orm import mapper, relation, sessionmaker, eagerload > > engine = create_engine('sqlite:///:memory:', echo=True) > metadata = MetaData() > Session = sessionmaker(bind=engine) > session = Session() > > NICE = 'NICE' > NAUGHTY = 'NAUGHTY' > > parent_table = Table('parent', metadata, > Column('parent_id', Integer, primary_key=True), > Column('name', String(32))) > > child_table = Table('child', metadata, > Column('child_id', Integer, primary_key=True), > Column('name', String(32)), > Column('status', String(32))) > > association_table = Table('association', metadata, > Column('id', Integer, primary_key=True), > Column('parent_id', ForeignKey('parent.parent_id')), > Column('child_id', ForeignKey('child.child_id'))) > > class Parent(object): > def __init__(self, name): > self.name = name > > class Child(object): > def __init__(self, name, status): > self.name = name > self.status = status > > class Association(object): > def __init__(self, parent, child): > self.parent = parent > self.child = child > > mapper(Parent, parent_table, properties={ > 'nice_children': relation(Association, lazy=True, > secondary=association_table, > > primaryjoin=parent_table.c.parent_id==association_table.c.parent_id, > > secondaryjoin=and_(association_table.c.child_id==child_table.c.child_id, > child_table.c.status==NICE), > viewonly=True) > }) > > mapper(Association, association_table, properties={ > 'child': relation(Child), > 'parent': relation(Parent) > }) > > mapper(Child, child_table) > > metadata.create_all(engine) > > > # CREATE ALL THE OBJECTS > > jack = Parent('Jack') > kid1 = Child('Kid1', NICE) > kid2 = Child('Kid2', NAUGHTY) > > session.add_all([jack, kid1, kid2]) > session.flush() > > assoc1 = Association(jack, kid1) > assoc2 = Association(jack, kid2) > > session.add_all([assoc1, assoc2]) > session.flush() > > assert jack.nice_children > > session.expunge_all() > > # TEST THE EAGERLOADING > > parents = session.query(Parent).all() > assert parents > assert parents[0].nice_children[0].child.name == 'Kid1' > > # fails > parents = > session.query(Parent).options(eagerload('nice_children')).all() > assert parents > assert parents[0].nice_children[0].child.name == 'Kid1' > > > > > > -- > You received this message because you are subscribed to the Google Groups > "sqlalchemy" group. > To post to this group, send email to sqlalch...@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. > -- You received this message because you are subscribed to the Google Groups "sqlalchemy" group. To post to this group, send email to sqlalch...@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.