The test passes for me in 0.8.0.  (Yes, we have 0.8.0 running in
production, and are finally getting around to upgrading... sigh...)


On Tue, Nov 24, 2015 at 4:09 PM, Christopher Lee <c...@sirdodger.net> wrote:

> I'll see if I can nail down the repro; I had to abstract some production
> code that I am migrating between versions, and I may have lost some
> important detail.
>
> Looking at the SQL it generates before and after moving the "links"
> relationship, it appears that it is outer joining against the wrong target,
> which explains why the identity map is getting confused.  (e.g., it is
> joining against the innermost anon_1 subquery in the bad case, and against
> the todo_elements_1 reference in the good case, which is why the good case
> is forming a nice tree.)
>
> On Tue, Nov 24, 2015 at 3:49 PM, Mike Bayer <mike...@zzzcomputing.com>
> wrote:
>
>>
>>
>> On 11/24/2015 06:14 PM, Christopher Lee wrote:
>> >
>> > I am having a problem with SQLAlchemy 1.0.9 that cropped up when I
>> > upgraded from 0.8.
>>
>> this is a nicely written test but I get the same recursion overflow
>> error when I run it in 0.8, 0.9, and 1.0, even back in 0.8.3.  Can you
>> provide a script that illustrates success in 0.8 and not in 1.0 ?  thanks.
>>
>>
>>
>>
>>
>>
>> >
>> > I have the following polymorphic relationship defined.  For some reason,
>> > when I build a tree, and I try to access the children of the middle node
>> > of the tree, it is picking up the wrong edge object and going into a
>> > recursive loop.  (Querying for the children of n2 is picking up the edge
>> > e12, instead of the edges e23, e24 and e25.)
>> >
>> > Looking at the identity map, it looks like the query isn't populating
>> > the correct objects.
>> >
>> > If I move the "links" relationship from the NodesWithEdges class to the
>> > base Node class, the query works fine.  Also, if I drop join_depth or
>> > remove with with_polymorphic mapper arg, it forces multiple queries, and
>> > the problem doesn't occur.  Is this a bug with the new release, or am I
>> > doing something bad?
>> >
>> >
>> > from __future__ import print_function, unicode_literals
>> >
>> > import sqlalchemy as sa
>> > import sqlalchemy.orm
>> > import sqlalchemy.ext.associationproxy
>> > import sqlalchemy.ext.declarative
>> > import sqlalchemy.ext.orderinglist
>> >
>> > Base = sqlalchemy.ext.declarative.declarative_base()
>> >
>> >
>> > class Node(Base):
>> > __tablename__ = 'todo_elements'
>> >
>> > element_id = sa.Column(sa.Integer, nullable=False, primary_key=True)
>> >     element_type = sa.Column(sa.String(20), nullable=False)
>> >
>> >     __mapper_args__ = {
>> >         'polymorphic_on': element_type,
>> > 'with_polymorphic': ('*', None),
>> > }
>> >
>> >
>> > class NodeWithEdges(Node):
>> > __mapper_args__ = {'polymorphic_identity': 'todo.list'}
>> >
>> >
>> > class LeafNode(Node):
>> > __mapper_args__ = {'polymorphic_identity': 'todo.item'}
>> >
>> >     my_flag = sa.Column(sa.Boolean, default=False)
>> >
>> >
>> > class Edge(Base):
>> > __tablename__ = 'todo_links'
>> > __table_args__ = (
>> >         sa.PrimaryKeyConstraint('parent_id', 'child_id'),
>> > sa.ForeignKeyConstraint(['parent_id'], [Node.element_id]),
>> > sa.ForeignKeyConstraint(['child_id'], [Node.element_id]),
>> > )
>> >
>> >     parent_id = sa.Column(sa.Integer, nullable=False)
>> >     child_id = sa.Column(sa.Integer, nullable=False)
>> >
>> >
>> > Edge.child = sa.orm.relationship(
>> >     Node,
>> > uselist=False,
>> > primaryjoin=Edge.child_id == Node.element_id,
>> > lazy=False,
>> > cascade='all',
>> > passive_updates=False,
>> > join_depth=8,
>> > )
>> >
>> >
>> > NodeWithEdges.links = sa.orm.relationship(
>> >     Edge,
>> > primaryjoin=NodeWithEdges.element_id == Edge.parent_id,
>> > lazy=False,
>> > cascade='all, delete-orphan',
>> > single_parent=True,
>> > passive_updates=False,
>> > join_depth=8,
>> > )
>> >
>> > NodeWithEdges.children = sa.ext.associationproxy.association_proxy(
>> >     'links', 'child',
>> > creator=lambda child: Edge(child_id=child.element_id))
>> >
>> >
>> >
>> > engine = sa.create_engine('sqlite:///:memory:', echo=True)
>> > Base.metadata.create_all(engine)
>> >
>> > Session = sa.orm.sessionmaker(bind=engine)
>> > session = Session()
>> >
>> >
>> > #
>> > # 1 --> 2 --> 3
>> > # --> 4
>> > # --> 5
>> > #
>> >
>> > n1 = NodeWithEdges(element_id=1)
>> > n2 = NodeWithEdges(element_id=2)
>> > n3 = LeafNode(element_id=3)
>> > n4 = LeafNode(element_id=4, my_flag=True)
>> > n5 = LeafNode(element_id=5)
>> >
>> > e12 = Edge(parent_id=n1.element_id, child_id=n2.element_id)
>> > e23 = Edge(parent_id=n2.element_id, child_id=n3.element_id)
>> > e24 = Edge(parent_id=n2.element_id, child_id=n4.element_id)
>> > e25 = Edge(parent_id=n2.element_id, child_id=n5.element_id)
>> >
>> > session.add_all([n1, n2, n3, n4, n5, e12, e23, e24, e25])
>> > session.commit()
>> > session.expunge_all()
>> >
>> > new_n1 =
>> session.query(NodeWithEdges).filter(NodeWithEdges.element_id==1).first()
>> > print(session.identity_map.keys())
>> >
>> >
>> > def traverse(node, f, depth=0):
>> > f(node, depth)
>> >     if hasattr(node, 'children'):
>> > for c in node.children:
>> > traverse(c, f, depth + 1)
>> >
>> > def indent_print(node, depth):
>> > print(' ' * depth + str(node.element_id))
>> >     if hasattr(node, 'my_flag'):
>> > print(node.my_flag)
>> >
>> > traverse(new_n1, indent_print)
>> >
>> > --
>> > You received this message because you are subscribed to the Google
>> > Groups "sqlalchemy" group.
>> > To unsubscribe from this group and stop receiving emails from it, send
>> > an email to sqlalchemy+unsubscr...@googlegroups.com
>> > <mailto:sqlalchemy+unsubscr...@googlegroups.com>.
>> > To post to this group, send email to sqlalchemy@googlegroups.com
>> > <mailto:sqlalchemy@googlegroups.com>.
>> > Visit this group at http://groups.google.com/group/sqlalchemy.
>> > For more options, visit https://groups.google.com/d/optout.
>>
>> --
>> You received this message because you are subscribed to the Google Groups
>> "sqlalchemy" group.
>> To unsubscribe from this group and stop receiving emails from it, send an
>> email to sqlalchemy+unsubscr...@googlegroups.com.
>> To post to this group, send email to sqlalchemy@googlegroups.com.
>> Visit this group at http://groups.google.com/group/sqlalchemy.
>> For more options, visit https://groups.google.com/d/optout.
>>
>
>

-- 
You received this message because you are subscribed to the Google Groups 
"sqlalchemy" group.
To unsubscribe from this group and stop receiving emails from it, send an email 
to sqlalchemy+unsubscr...@googlegroups.com.
To post to this group, send email to sqlalchemy@googlegroups.com.
Visit this group at http://groups.google.com/group/sqlalchemy.
For more options, visit https://groups.google.com/d/optout.

Reply via email to