From: Mike Bayer Date: Tue, 22 Aug 2017 22:35:09 +0000 (-0400) Subject: Handle cache key for option that has no strategy X-Git-Tag: origin~45 X-Git-Url: http://git.ipfire.org/cgi-bin/gitweb.cgi?a=commitdiff_plain;h=3f9df2b86b4a8d7912d1190aead4aa084daf802c;p=thirdparty%2Fsqlalchemy%2Fsqlalchemy.git Handle cache key for option that has no strategy Fixed regression where the use of a :func:`.undefer_group` option in conjunction with a lazy loaded relationship option would cause an attribute error, due to a bug in the SQL cache key generation added in 1.2 as part of :ticket:`3954`. Change-Id: Icd9a34f0b5aa96d6433a2ab9c8d3eaee0006f609 Fixes: #4049 --- diff --git a/doc/build/changelog/unreleased_12/4049.rst b/doc/build/changelog/unreleased_12/4049.rst new file mode 100644 index 0000000000..010d1a2c02 --- /dev/null +++ b/doc/build/changelog/unreleased_12/4049.rst @@ -0,0 +1,8 @@ +.. change:: + :tags: bug, orm + :tickets: 4049 + + Fixed regression where the use of a :func:`.undefer_group` option + in conjunction with a lazy loaded relationship option would cause + an attribute error, due to a bug in the SQL cache key generation + added in 1.2 as part of :ticket:`3954`. \ No newline at end of file diff --git a/lib/sqlalchemy/orm/strategy_options.py b/lib/sqlalchemy/orm/strategy_options.py index c47536a02d..e07a6b3d0e 100644 --- a/lib/sqlalchemy/orm/strategy_options.py +++ b/lib/sqlalchemy/orm/strategy_options.py @@ -110,7 +110,7 @@ class Load(Generative, MapperOption): serialized.append( ( tuple(serialized_path) + - obj.strategy + + (obj.strategy or ()) + (tuple([ (key, obj.local_opts[key]) for key in sorted(obj.local_opts) diff --git a/test/orm/test_deferred.py b/test/orm/test_deferred.py index 9295399bcc..21f40a39af 100644 --- a/test/orm/test_deferred.py +++ b/test/orm/test_deferred.py @@ -387,6 +387,44 @@ class DeferredOptionsTest(AssertsCompiledSQL, _fixtures.FixtureTest): "FROM orders ORDER BY orders.id", {})]) + def test_undefer_group_from_relationship_lazyload(self): + users, Order, User, orders = \ + (self.tables.users, + self.classes.Order, + self.classes.User, + self.tables.orders) + + mapper(User, users, properties=dict( + orders=relationship(Order, order_by=orders.c.id))) + mapper( + Order, orders, properties=util.OrderedDict([ + ('userident', deferred(orders.c.user_id, group='primary')), + ('description', deferred(orders.c.description, + group='primary')), + ('opened', deferred(orders.c.isopen, group='primary')) + ]) + ) + + sess = create_session() + q = sess.query(User).filter(User.id == 7).options( + defaultload(User.orders).undefer_group('primary') + ) + + def go(): + result = q.all() + o2 = result[0].orders[1] + eq_(o2.opened, 1) + eq_(o2.userident, 7) + eq_(o2.description, 'order 3') + self.sql_eq_(go, [ + ("SELECT users.id AS users_id, users.name AS users_name " + "FROM users WHERE users.id = :id_1", {"id_1": 7}), + ("SELECT orders.user_id AS orders_user_id, orders.description " + "AS orders_description, orders.isopen AS orders_isopen, " + "orders.id AS orders_id, orders.address_id AS orders_address_id " + "FROM orders WHERE :param_1 = orders.user_id ORDER BY orders.id", + {'param_1': 7})]) + def test_undefer_star(self): orders, Order = self.tables.orders, self.classes.Order diff --git a/test/orm/test_options.py b/test/orm/test_options.py index 024806d429..44ebe81c37 100644 --- a/test/orm/test_options.py +++ b/test/orm/test_options.py @@ -1393,3 +1393,32 @@ class CacheKeyTest(PathTest, QueryTest): ) ) + def test_unbound_cache_key_undefer_group(self): + User, Address = self.classes('User', 'Address') + + query_path = self._make_path_registry([User, "addresses"]) + + opt = defaultload(User.addresses).undefer_group('xyz') + + eq_( + opt._generate_cache_key(query_path), + + ( + (Address, 'column:*', ("undefer_group_xyz", True)), + ) + ) + + def test_bound_cache_key_undefer_group(self): + User, Address = self.classes('User', 'Address') + + query_path = self._make_path_registry([User, "addresses"]) + + opt = Load(User).defaultload(User.addresses).undefer_group('xyz') + + eq_( + opt._generate_cache_key(query_path), + + ( + (Address, 'column:*', ("undefer_group_xyz", True)), + ) + )