Skip to content

Fix SnowflakeConnection.query() cache key to include params#13652

Merged
sfc-gh-kmcgrady merged 2 commits intodevelopfrom
kmcgrady/snowflake-params-cache-fix
Jan 21, 2026
Merged

Fix SnowflakeConnection.query() cache key to include params#13652
sfc-gh-kmcgrady merged 2 commits intodevelopfrom
kmcgrady/snowflake-params-cache-fix

Conversation

@sfc-gh-kmcgrady
Copy link
Copy Markdown
Contributor

@sfc-gh-kmcgrady sfc-gh-kmcgrady commented Jan 20, 2026

Describe your changes

Fixed a bug in SnowflakeConnection.query() where the params argument was captured as a closure variable instead of being passed as an explicit parameter to the cached _query function. This caused different parameter values to incorrectly share the same cache entry, returning stale results when queries were executed with different parameters.

The fix makes params an explicit parameter of the _query function, ensuring st.cache_data includes it in the cache key, consistent with how SQLConnection.query() handles this pattern.

Closes: #13644

Testing Plan

Added a new test test_query_caches_separately_for_different_params that verifies different parameter values create separate cache entries while identical parameters correctly hit the cache.


Contribution License Agreement

By submitting this pull request you agree that all contributions to this project are made under the Apache 2.0 license.

The params argument was captured as a closure variable instead of being passed
as an explicit parameter to the cached _query function. This caused different
parameter values to incorrectly share the same cache entry. Now params is an
explicit parameter so st.cache_data includes it in the cache key.

Fixes #13644

Co-Authored-By: Claude <[email protected]>
Copilot AI review requested due to automatic review settings January 20, 2026 20:47
@snyk-io
Copy link
Copy Markdown
Contributor

snyk-io bot commented Jan 20, 2026

Snyk checks have passed. No issues have been found so far.

Status Scanner Critical High Medium Low Total (0)
Open Source Security 0 0 0 0 0 issues
Licenses 0 0 0 0 0 issues

💻 Catch issues earlier using the plugins for VS Code, JetBrains IDEs, Visual Studio, and Eclipse.

@github-actions
Copy link
Copy Markdown
Contributor

github-actions bot commented Jan 20, 2026

✅ PR preview is ready!

Name Link
📦 Wheel file https://core-previews.s3-us-west-2.amazonaws.com/pr-13652/streamlit-1.53.0-py3-none-any.whl
📦 @streamlit/component-v2-lib Download from artifacts
🕹️ Preview app pr-13652.streamlit.app (☁️ Deploy here if not accessible)

@sfc-gh-kmcgrady sfc-gh-kmcgrady added security-assessment-completed change:bugfix PR contains bug fix implementation impact:users PR changes affect end users ai-review If applied to PR or issue will run AI review workflow labels Jan 20, 2026
Copy link
Copy Markdown
Contributor

Copilot AI left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Pull request overview

This PR fixes a critical caching bug in SnowflakeConnection.query() where the params argument was captured as a closure variable instead of being an explicit parameter to the cached _query function. This caused queries with different parameter values to incorrectly share cache entries, returning stale results.

Changes:

  • Modified _query function signature to include params as an explicit parameter, ensuring it's included in the cache key
  • Updated the _query call to pass params explicitly
  • Added test coverage to verify different parameter values create separate cache entries

Reviewed changes

Copilot reviewed 2 out of 2 changed files in this pull request and generated 1 comment.

File Description
lib/streamlit/connections/snowflake_connection.py Fixed the _query function to accept params as an explicit parameter and pass it through correctly, aligning with the SQLConnection pattern
lib/tests/streamlit/connections/snowflake_connection_test.py Added test to verify cache behavior with different params values, ensuring separate cache entries are created

Comment on lines +122 to +124
# Should have been called twice (once for each unique params value)
assert conn._instance.cursor.call_count == 2
assert mock_cursor.execute.call_count == 2
Copy link

Copilot AI Jan 20, 2026

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

The test validates cache behavior (call counts) but doesn't verify that the execute method was called with the correct params values. Consider adding assertions to verify the actual parameters passed, such as checking that execute was called with params=["active"] and params=["inactive"]. This would strengthen the test by ensuring not just that caching works, but that the correct data flows through to the underlying Snowflake connector.

Copilot generated this review using guidance from repository custom instructions.
@github-actions github-actions bot removed the ai-review If applied to PR or issue will run AI review workflow label Jan 20, 2026
@github-actions
Copy link
Copy Markdown
Contributor

Summary

This PR fixes a caching bug in SnowflakeConnection.query() where the params argument was captured as a closure variable instead of being passed as an explicit parameter to the inner _query function. This caused different parameter values to incorrectly share the same cache entry, returning stale results when queries were executed with different parameters.

The fix makes params an explicit parameter of the _query function, ensuring st.cache_data includes it in the cache key. This is consistent with how SQLConnection.query() handles the same pattern.

Code Quality

The code change is minimal, focused, and correct:

Changes in lib/streamlit/connections/snowflake_connection.py:

  1. Line 138: The _query inner function signature changed from:

    def _query(sql: str) -> DataFrame:

    to:

    def _query(sql: str, params: Any = None) -> DataFrame:
  2. Line 156: The function call changed from:

    return _query(sql)

    to:

    return _query(sql, params)

This pattern is now consistent with SQLConnection.query() (see lines 313-319 and 348-354 in sql_connection.py), where params is explicitly passed to the inner _query function to ensure proper cache key calculation.

The fix correctly addresses the closure variable capture issue - previously, params was accessed from the outer scope inside _query, meaning @st.cache_data would not include it in the cache key calculation.

Test Coverage

The new test test_query_caches_separately_for_different_params adequately covers the fix:

Strengths:

  • Tests that different params values create separate cache entries
  • Tests that identical params values correctly hit the cache
  • Uses a unique connection name (my_snowflake_connection_params) to avoid cache interference with other tests
  • Includes a docstring explaining the test purpose
  • Follows the existing test patterns in the file

The test logic:

  1. Calls query() with params=["active"] - cache miss, executes query
  2. Calls query() with params=["inactive"] - cache miss, executes query
  3. Calls query() with params=["active"] again - cache hit
  4. Calls query() with params=["inactive"] again - cache hit
  5. Asserts cursor.call_count == 2 and execute.call_count == 2

This implicitly includes a negative assertion: the test verifies that same params DO hit the cache (2 calls, not 4).

Backwards Compatibility

This change is fully backwards compatible:

  • The params parameter in _query has a default value of None, matching the original behavior when params is not specified
  • The external API of SnowflakeConnection.query() remains unchanged
  • Existing code that doesn't use params will continue to work identically
  • The only behavioral change is that queries with different params values will now be cached separately (which is the correct/expected behavior)

Security & Risk

No security concerns identified.

Low regression risk:

  • The change is minimal and targeted
  • The fix aligns the implementation with the existing SQLConnection.query() pattern
  • The test provides good coverage of the fix
  • No changes to public API signatures

Recommendations

No blocking issues. The PR is well-implemented with appropriate test coverage.

Minor suggestions (non-blocking):

  1. Consider adding a brief inline comment explaining why params must be an explicit parameter (to include it in the cache key), similar to the existing comment about __qualname__ manipulation. However, this is optional as the code is self-documenting given the context.

  2. The test could optionally verify that the execute calls received the correct params values using mock_cursor.execute.assert_any_call(), but the current assertion is sufficient to verify the caching behavior.

Verdict

APPROVED: This is a correct and well-tested bug fix that addresses a real caching issue where different query parameters incorrectly shared cache entries. The implementation is consistent with existing patterns in SQLConnection.query() and poses no backwards compatibility or security risks.


This is an automated AI review using opus-4.5-thinking. Please verify the feedback and use your judgment.

Add inline comment clarifying why params must be an explicit parameter
(to include it in the cache key). Also add assertions to verify execute
was called with the correct params values.

Co-Authored-By: Claude <[email protected]>
Copy link
Copy Markdown
Collaborator

@lukasmasuch lukasmasuch left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

LGTM 👍

@sfc-gh-kmcgrady sfc-gh-kmcgrady merged commit 7a984a4 into develop Jan 21, 2026
43 checks passed
@sfc-gh-kmcgrady sfc-gh-kmcgrady deleted the kmcgrady/snowflake-params-cache-fix branch January 21, 2026 22:19
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

change:bugfix PR contains bug fix implementation impact:users PR changes affect end users

Projects

None yet

Development

Successfully merging this pull request may close these issues.

SnowflakeConnection.query() cache key ignores params argument

4 participants