.. changelog::
:version: 1.0.10
+ .. change::
+ :tags: bug, ext
+ :versions: 1.1.0b1
+ :tickets: 3597
+
+ Fixed an issue in baked queries where the .get() method, used either
+ directly or within lazy loads, didn't consider the mapper's "get clause"
+ as part of the cache key, causing bound parameter mismatches if the
+ clause got re-generated. This clause is cached by mappers
+ on the fly but in highly concurrent scenarios may be generated more
+ than once when first accessed.
+
.. change::
:tags: feature, sql
:versions: 1.1.0b1
# (remember, we can map to an OUTER JOIN)
bq = self.bq
+ # add the clause we got from mapper._get_clause to the cache
+ # key so that if a race causes multiple calls to _get_clause,
+ # we've cached on ours
+ bq = bq._clone()
+ bq._cache_key += (_get_clause, )
+
bq = bq.with_criteria(setup, tuple(elem is None for elem in ident))
params = dict([
eq_(u2.name, 'chuck')
self.assert_sql_count(testing.db, go, 0)
+ def test_get_includes_getclause(self):
+ # test issue #3597
+ User = self.classes.User
+
+ bq = self.bakery(lambda s: s.query(User))
+
+ for i in range(5):
+ sess = Session()
+ u1 = bq(sess).get(7)
+ eq_(u1.name, 'jack')
+
+ eq_(len(bq._bakery), 2)
+
+ # simulate race where mapper._get_clause
+ # may be generated more than once
+ from sqlalchemy import inspect
+ del inspect(User).__dict__['_get_clause']
+
+ for i in range(5):
+ sess = Session()
+ u1 = bq(sess).get(7)
+ eq_(u1.name, 'jack')
+ eq_(len(bq._bakery), 4)
+
class ResultTest(BakedTest):
__backend__ = True