Hello! We noticed some weird behavior where our tests were affecting one
another, and I tracked it down to what I believe is a SQLAlchemy bug. It
appears that performing a particular query with a joinedload can alter
future queries that are run without the same joinedload. This appears to
only happen when using 'polymorphic_load': 'selectin' (and not with
'inline'):
from benchling import db
### Table setup
class Parent(db.Model):
__tablename__ = 'parent'
id = db.Column(db.Integer, primary_key=True)
class Child(db.Model):
__tablename__ = 'child'
id = db.Column(db.Integer, primary_key=True)
parent_id = db.Column(db.Integer, db.ForeignKey('parent.id'))
parent = db.relationship('Parent', backref=db.backref('children'))
type = db.Column(db.String(), nullable=False)
__mapper_args__ = {
'polymorphic_on': type,
}
class ChildSubclass1(Child):
__tablename__ = 'child_subclass1'
id = db.Column(db.Integer, db.ForeignKey('child.id'), primary_key=True)
__mapper_args__ = {'polymorphic_identity': 'subclass1',
'polymorphic_load': 'selectin'}
class Other(db.Model):
id = db.Column(db.Integer, primary_key=True)
child_subclass_id = db.Column(db.Integer,
db.ForeignKey('child_subclass1.id'))
child_subclass = db.relationship('ChildSubclass1',
backref=db.backref('others'))
Parent.__table__.create(bind=db.engine)
Child.__table__.create(bind=db.engine)
ChildSubclass1.__table__.create(bind=db.engine)
Other.__table__.create(bind=db.engine)
def is_other_in_session():
return any(isinstance(model, Other) for model in db.session)
### Bug repro:
parent = Parent()
subclass1 = ChildSubclass1(parent=parent)
other = Other(child_subclass=subclass1)
db.session.add_all([parent, subclass1, other])
db.session.commit()
# Test 1: Loading Parent + Children does not load Other
print '\nTest #1: Loading Parent + Children does not load others'
db.session.expunge_all()
assert not is_other_in_session()
parents =
Parent.query.options(db.joinedload(Parent.children.of_type(ChildSubclass1))).all()
assert not is_other_in_session()
print '\nTest #2: Loading Parent + Children + Others loads others as
expected'
db.session.expunge_all()
assert not is_other_in_session()
parents =
Parent.query.options(db.joinedload(Parent.children.of_type(ChildSubclass1)).joinedload(ChildSubclass1.others)).all()
assert is_other_in_session()
print '\nTest #3: Loading Parent + Children should not load others, but it
does now'
db.session.expunge_all()
assert not is_other_in_session()
parents =
Parent.query.options(db.joinedload(Parent.children.of_type(ChildSubclass1))).all()
assert not is_other_in_session(), 'The above query should not load any
Others!'
Test #1 and Test #3 are identical, but Test #3 fails because it is run
after Test #2 (which does a joinedload on ChildSubclass.others). I thought
this might be related to baked queries, but it still fails
with enable_baked_queries=False . Let me know if there's any other
information I can provide that would be useful, or if there are any
workarounds we can use right now!
--
SQLAlchemy -
The Python SQL Toolkit and Object Relational Mapper
http://www.sqlalchemy.org/
To post example code, please provide an MCVE: Minimal, Complete, and Verifiable
Example. See http://stackoverflow.com/help/mcve for a full description.
---
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 [email protected].
To post to this group, send email to [email protected].
Visit this group at https://groups.google.com/group/sqlalchemy.
For more options, visit https://groups.google.com/d/optout.