diff options
author | Mike Bayer <mike_mp@zzzcomputing.com> | 2016-01-09 10:10:20 -0500 |
---|---|---|
committer | Mike Bayer <mike_mp@zzzcomputing.com> | 2016-01-09 10:10:20 -0500 |
commit | c7ae0daf0ed24e2697d6f948db2d9fdc5953c795 (patch) | |
tree | 424c000be8adb806ebf3198bf32837dbeeb8699c | |
parent | 89facbed8855d1443dbe37919ff0645aea640ed0 (diff) | |
download | sqlalchemy-c7ae0daf0ed24e2697d6f948db2d9fdc5953c795.tar.gz |
- Fixed regression since 0.9 where the 0.9 style loader options
system failed to accommodate for multiple :func:`.undefer_group`
loader options in a single query. Multiple :func:`.undefer_group`
options will now be taken into account even against the same
entity. fixes #3623
-rw-r--r-- | doc/build/changelog/changelog_10.rst | 10 | ||||
-rw-r--r-- | lib/sqlalchemy/orm/strategies.py | 2 | ||||
-rw-r--r-- | lib/sqlalchemy/orm/strategy_options.py | 25 | ||||
-rw-r--r-- | test/orm/test_deferred.py | 58 |
4 files changed, 91 insertions, 4 deletions
diff --git a/doc/build/changelog/changelog_10.rst b/doc/build/changelog/changelog_10.rst index debcf1ead..4d017cfb1 100644 --- a/doc/build/changelog/changelog_10.rst +++ b/doc/build/changelog/changelog_10.rst @@ -20,6 +20,16 @@ :released: .. change:: + :tags: bug, orm + :tickets: 3623 + + Fixed regression since 0.9 where the 0.9 style loader options + system failed to accommodate for multiple :func:`.undefer_group` + loader options in a single query. Multiple :func:`.undefer_group` + options will now be taken into account even against the same + entity. + + .. change:: :tags: bug, mssql, firebird :tickets: 3622 diff --git a/lib/sqlalchemy/orm/strategies.py b/lib/sqlalchemy/orm/strategies.py index b60e47bb3..0252a65f9 100644 --- a/lib/sqlalchemy/orm/strategies.py +++ b/lib/sqlalchemy/orm/strategies.py @@ -238,7 +238,7 @@ class DeferredColumnLoader(LoaderStrategy): ( loadopt and self.group and - loadopt.local_opts.get('undefer_group', False) == self.group + loadopt.local_opts.get('undefer_group_%s' % self.group, False) ) or ( diff --git a/lib/sqlalchemy/orm/strategy_options.py b/lib/sqlalchemy/orm/strategy_options.py index 3467328e3..f08367941 100644 --- a/lib/sqlalchemy/orm/strategy_options.py +++ b/lib/sqlalchemy/orm/strategy_options.py @@ -88,6 +88,7 @@ class Load(Generative, MapperOption): cloned.local_opts = {} return cloned + _merge_into_path = False strategy = None propagate_to_loaders = False @@ -214,7 +215,15 @@ class Load(Generative, MapperOption): cloned._set_path_strategy() def _set_path_strategy(self): - if self.path.has_entity: + if self._merge_into_path: + # special helper for undefer_group + existing = self.path.get(self.context, "loader") + if existing: + existing.local_opts.update(self.local_opts) + else: + self.path.set(self.context, "loader", self) + + elif self.path.has_entity: self.path.parent.set(self.context, "loader", self) else: self.path.set(self.context, "loader", self) @@ -411,11 +420,20 @@ class _UnboundLoad(Load): if effective_path.is_token: for path in effective_path.generate_for_superclasses(): - if self._is_chain_link: + if self._merge_into_path: + # special helper for undefer_group + existing = path.get(context, "loader") + if existing: + existing.local_opts.update(self.local_opts) + else: + path.set(context, "loader", loader) + elif self._is_chain_link: path.setdefault(context, "loader", loader) else: path.set(context, "loader", loader) else: + # only supported for the undefer_group() wildcard opt + assert not self._merge_into_path if self._is_chain_link: effective_path.setdefault(context, "loader", loader) else: @@ -1025,10 +1043,11 @@ def undefer_group(loadopt, name): :func:`.orm.undefer` """ + loadopt._merge_into_path = True return loadopt.set_column_strategy( "*", None, - {"undefer_group": name} + {"undefer_group_%s" % name: True} ) diff --git a/test/orm/test_deferred.py b/test/orm/test_deferred.py index 29087fdb8..7f449c40a 100644 --- a/test/orm/test_deferred.py +++ b/test/orm/test_deferred.py @@ -320,6 +320,64 @@ class DeferredOptionsTest(AssertsCompiledSQL, _fixtures.FixtureTest): "FROM orders ORDER BY orders.id", {})]) + def test_undefer_group_multi(self): + orders, Order = self.tables.orders, self.classes.Order + + 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='secondary')) + ] + )) + + sess = create_session() + q = sess.query(Order).order_by(Order.id) + def go(): + l = q.options( + undefer_group('primary'), undefer_group('secondary')).all() + o2 = l[2] + eq_(o2.opened, 1) + eq_(o2.userident, 7) + eq_(o2.description, 'order 3') + + self.sql_eq_(go, [ + ("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 ORDER BY orders.id", + {})]) + + def test_undefer_group_multi_pathed(self): + orders, Order = self.tables.orders, self.classes.Order + + 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='secondary')) + ] + )) + + sess = create_session() + q = sess.query(Order).order_by(Order.id) + def go(): + l = q.options( + Load(Order).undefer_group('primary').undefer_group('secondary')).all() + o2 = l[2] + eq_(o2.opened, 1) + eq_(o2.userident, 7) + eq_(o2.description, 'order 3') + + self.sql_eq_(go, [ + ("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 ORDER BY orders.id", + {})]) + def test_undefer_star(self): orders, Order = self.tables.orders, self.classes.Order |