]> git.ipfire.org Git - thirdparty/sqlalchemy/sqlalchemy.git/commitdiff
Add _WILDCARD_TOKEN special case in _chop_path 9931/head
authorMatthew Martin <phy1729@gmail.com>
Wed, 31 May 2023 17:18:47 +0000 (12:18 -0500)
committerMatthew Martin <phy1729@gmail.com>
Sun, 11 Jun 2023 13:29:40 +0000 (08:29 -0500)
Fixes #9870.

doc/build/changelog/unreleased_20/9870.rst [new file with mode: 0644]
lib/sqlalchemy/orm/strategy_options.py
test/orm/test_deferred.py

diff --git a/doc/build/changelog/unreleased_20/9870.rst b/doc/build/changelog/unreleased_20/9870.rst
new file mode 100644 (file)
index 0000000..3c3a5dd
--- /dev/null
@@ -0,0 +1,8 @@
+.. change::
+    :tags: bug, orm, regression
+    :tickets: 9870
+
+    Fixed regression in the 2.0 series where a query that used
+    :func:`.undefer_group` with :func:`_orm.selectinload` or
+    :func:`_orm.subqueryload` would raise an ``AttributeError``. Pull request
+    courtesy of Matthew Martin.
index 90b8dda8b096cbabab77370d5c04a2390403459d..d93ec0a273151c98d921a9f42146f2a6adf43ce0 100644 (file)
@@ -931,7 +931,10 @@ class _AbstractLoad(traversals.GenerativeOnTraversal, LoaderOption):
             zip(to_chop, path.natural_path)
         ):
             if isinstance(c_token, str):
-                if i == 0 and c_token.endswith(f":{_DEFAULT_TOKEN}"):
+                if i == 0 and (
+                    c_token.endswith(f":{_DEFAULT_TOKEN}")
+                    or c_token.endswith(f":{_WILDCARD_TOKEN}")
+                ):
                     return to_chop
                 elif (
                     c_token != f"{_RELATIONSHIP_TOKEN}:{_WILDCARD_TOKEN}"
index 74352992406ae1d8a2a5463e888d3151696d5a41..c93ac6d60ac0a1b457adab04e9370aa772f01b9a 100644 (file)
@@ -692,6 +692,75 @@ class DeferredOptionsTest(AssertsCompiledSQL, _fixtures.FixtureTest):
             ],
         )
 
+    def test_undefer_group_with_load(self):
+        users, Order, User, orders = (
+            self.tables.users,
+            self.classes.Order,
+            self.classes.User,
+            self.tables.orders,
+        )
+
+        self.mapper_registry.map_imperatively(
+            User,
+            users,
+        )
+        self.mapper_registry.map_imperatively(
+            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")),
+                    ("user", relationship(User)),
+                ]
+            ),
+        )
+
+        sess = fixture_session()
+        q = (
+            sess.query(Order)
+            .filter(Order.id == 3)
+            .options(
+                selectinload(Order.user),
+                undefer_group("primary"),
+            )
+        )
+
+        def go():
+            result = q.all()
+            print(result)
+            o = result[0]
+            eq_(o.opened, 1)
+            eq_(o.userident, 7)
+            eq_(o.description, "order 3")
+            u = o.user
+            eq_(u.id, 7)
+
+        self.sql_eq_(
+            go,
+            [
+                (
+                    "SELECT orders.id AS orders_id, "
+                    "orders.user_id AS orders_user_id, "
+                    "orders.address_id AS orders_address_id, "
+                    "orders.description AS orders_description, "
+                    "orders.isopen AS orders_isopen "
+                    "FROM orders WHERE orders.id = :id_1",
+                    {"id_1": 3},
+                ),
+                (
+                    "SELECT users.id AS users_id, users.name AS users_name "
+                    "FROM users WHERE users.id IN "
+                    "(__[POSTCOMPILE_primary_keys])",
+                    [{"primary_keys": [7]}],
+                ),
+            ],
+        )
+
     def test_undefer_group_from_relationship_lazyload(self):
         users, Order, User, orders = (
             self.tables.users,