On 01/07/2016 08:04 PM, Christopher Lee wrote: > > I have a simple setup where I create two Nodes connected by an Edge, > where the Edge should be eagerly loaded when the parent is loaded. If I > query the Node with a get(), it issues a select to refresh it, but then > if I access its children, it issues a second get(). This behavior did > not used to occur in 0.8.0. If I expunge the session completely, then a > get() will eagerly load the edges as expected. Is that expected? Did > the mechanism by which get() repopulates the identity map change?
If I run this test in 0.8.0 I get the same behavior as that of master: session.expire_all() node = session.query(Node).get((1,)) # <-- Issues one select against nodes with no outer join print "-------------" edges = node.children # <-- Issues one select against edges with no outer join output at that part: SELECT nodes.node_id AS nodes_node_id FROM nodes WHERE nodes.node_id = ? 2016-01-07 21:57:22,372 INFO sqlalchemy.engine.base.Engine (1,) ------------- 2016-01-07 21:57:22,373 INFO sqlalchemy.engine.base.Engine SELECT edges.parent_id AS edges_parent_id, edges.child_id AS edges_child_id FROM edges WHERE ? = edges.parent_id ORDER BY edges.parent_id 2016-01-07 21:57:22,373 INFO sqlalchemy.engine.base.Engine (1,) The select for edges is after the query, upon access to node.children. I get this with 0.8.7, 0.8.0, latest 0.9, etc. This is expected because the node of identity "1" is still present in the identity map; the get() just emits a refresh of its row, and we don't run eager loaders on "refresh". There's a really ancient issue at https://bitbucket.org/zzzeek/sqlalchemy/issues/1763/run-eager-loaders-on-unexpire that proposes to change this but it's a big deal to mess around with those mechanics. > > > class Node(Base): > __tablename__ = "nodes" > node_id = sa.Column(sa.Integer, primary_key=True) > > > class Edge(Base): > __tablename__ = 'edges' > parent_id = sa.Column(sa.Integer, sa.ForeignKey(Node.node_id), > primary_key=True) > child_id = sa.Column(sa.Integer, sa.ForeignKey(Node.node_id), > primary_key=True) > > > Node.children = sa.orm.relationship( > Edge, > cascade="all, delete-orphan", > lazy=False, > uselist=True, > primaryjoin=Node.node_id==Edge.parent_id, > order_by=Edge.parent_id) > > > engine = sa.create_engine('sqlite:///:memory:', echo=True) > Base.metadata.create_all(engine) > > Session = sa.orm.sessionmaker(bind=engine) > session = Session() > > n1 = Node(node_id=1) > n2 = Node(node_id=2) > > e12 = Edge(parent_id=n1.node_id, child_id=n2.node_id) > > session.add_all([n1, n2, e12,]) > session.commit() > > session.expire_all() > node = session.query(Node).get((1,)) # <-- Issues one select against > nodes with no outer join > edges = node.children # <-- Issues one select against edges with no > outer join > > Whereas if I expunge: > > session.expunge_all() > node = session.query(Node).get((1,)) # <-- Issues an outer join select > against nodes and edges > edges = node.children # <-- No select statement, pulls from identity map > > > -- > 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 https://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 https://groups.google.com/group/sqlalchemy. For more options, visit https://groups.google.com/d/optout.