]> git.ipfire.org Git - thirdparty/sqlalchemy/sqlalchemy.git/commitdiff
accommodate for untracked boundparam lambda in offline_string
authorMike Bayer <mike_mp@zzzcomputing.com>
Thu, 5 Aug 2021 23:17:07 +0000 (19:17 -0400)
committerMike Bayer <mike_mp@zzzcomputing.com>
Thu, 5 Aug 2021 23:19:02 +0000 (19:19 -0400)
Fixed an issue in the ``CacheKey.to_offline_string()`` method used by the
dogpile.caching example where attempting to create a proper cache key from
the special "lambda" query generated by the lazy loader would fail to
include the parameter values, leading to an incorrect cache key.

Fixes: #6858
Change-Id: Ice27087583c6f3ff79cf7d5b879e5dd0a4e58158

doc/build/changelog/unreleased_14/6858.rst [new file with mode: 0644]
examples/dogpile_caching/caching_query.py
lib/sqlalchemy/sql/traversals.py
test/sql/test_lambdas.py

diff --git a/doc/build/changelog/unreleased_14/6858.rst b/doc/build/changelog/unreleased_14/6858.rst
new file mode 100644 (file)
index 0000000..0aa9d75
--- /dev/null
@@ -0,0 +1,9 @@
+.. change::
+    :tags: bug, sql
+    :tickets: 6858
+
+    Fixed an issue in the ``CacheKey.to_offline_string()`` method used by the
+    dogpile.caching example where attempting to create a proper cache key from
+    the special "lambda" query generated by the lazy loader would fail to
+    include the parameter values, leading to an incorrect cache key.
+
index d1199090c89b0411f4a98cb899efab343d0e737f..68f72e5f06e92733f1b757d6de95bff4ee064807 100644 (file)
@@ -139,7 +139,6 @@ class FromCache(UserDefinedOption):
         key = statement_cache_key.to_offline_string(
             orm_cache._statement_cache, statement, parameters
         ) + repr(self.cache_key)
-
         # print("here's our key...%s" % key)
         return key
 
index a86d16ef4c06a8345df183ee0c18d725e0e58e2a..3d377271f99b8418b215751461714b5d92c19d5f 100644 (file)
@@ -299,15 +299,15 @@ class CacheKey(namedtuple("CacheKey", ["key", "bindparams"])):
         else:
             sql_str = statement_cache[self.key]
 
-        return repr(
-            (
-                sql_str,
-                tuple(
-                    parameters.get(bindparam.key, bindparam.value)
-                    for bindparam in self.bindparams
-                ),
+        if not self.bindparams:
+            param_tuple = tuple(parameters[key] for key in sorted(parameters))
+        else:
+            param_tuple = tuple(
+                parameters.get(bindparam.key, bindparam.value)
+                for bindparam in self.bindparams
             )
-        )
+
+        return repr((sql_str, param_tuple))
 
     def __eq__(self, other):
         return self.key == other.key
index ea31c9aeca8c7dc0de519e56e8bd40b8d27fc1e1..51530b0791ccd12f41ad8380d4187ebf9b384a0d 100644 (file)
@@ -897,6 +897,42 @@ class LambdaElementTest(
             checkparams={"q_1": 1},
         )
 
+    def test_offline_cache_key_no_paramtrack(self):
+        def go():
+            stmt = lambdas.lambda_stmt(
+                lambda: select(column("x")).where(
+                    column("y") == bindparam("q")
+                ),
+                global_track_bound_values=False,
+            )
+
+            return stmt
+
+        s1 = go()
+
+        eq_(
+            s1._generate_cache_key().to_offline_string({}, s1, {"q": 5}),
+            "('SELECT x \\nWHERE y = :q', (5,))",
+        )
+
+    def test_offline_cache_key_paramtrack(self):
+        def go(param):
+            stmt = lambdas.lambda_stmt(
+                lambda: select(column("x")).where(column("y") == param),
+            )
+
+            return stmt
+
+        s1 = go(5)
+
+        param_key = s1._resolved._where_criteria[0].right.key
+        eq_(
+            s1._generate_cache_key().to_offline_string(
+                {}, s1, {param_key: 10}
+            ),
+            "('SELECT x \\nWHERE y = :param_1', (10,))",
+        )
+
     def test_stmt_lambda_w_list_of_opts(self):
         def go(opts):
             stmt = lambdas.lambda_stmt(lambda: select(column("x")))