]> git.ipfire.org Git - thirdparty/sqlalchemy/sqlalchemy.git/commitdiff
- Fixed regression since 0.9 where the 0.9 style loader options
authorMike Bayer <mike_mp@zzzcomputing.com>
Sat, 9 Jan 2016 15:10:20 +0000 (10:10 -0500)
committerMike Bayer <mike_mp@zzzcomputing.com>
Sat, 9 Jan 2016 15:10:20 +0000 (10:10 -0500)
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

doc/build/changelog/changelog_10.rst
lib/sqlalchemy/orm/strategies.py
lib/sqlalchemy/orm/strategy_options.py
test/orm/test_deferred.py

index debcf1eadd76cfb1ac4b1fa53122fc07cd92d2d6..4d017cfb15fb338cadf7ee92f08b9d10500675bb 100644 (file)
     :version: 1.0.12
     :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
index b60e47bb39380628fc4f58a2e7674a4cd2c904bd..0252a65f98225d0d4b5fb930f4ea6cd004950c84 100644 (file)
@@ -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
             (
index 3467328e3a1405058fdc847c08db67de7a7cabe1..f08367941667739bab487ea3561a3dae5916fa55 100644 (file)
@@ -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}
     )
 
 
index 29087fdb868fe3c07a619970b2a723985e3c7ba1..7f449c40ac6f36aaa4d91bcf63a0a65c4674dc9a 100644 (file)
@@ -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