Skip to content

fix(postgrest): prevent filter query builder state leakage#1385

Open
Dodothereal wants to merge 1 commit intosupabase:mainfrom
Dodothereal:codex/fix-issue-1208-query-builder-immutability
Open

fix(postgrest): prevent filter query builder state leakage#1385
Dodothereal wants to merge 1 commit intosupabase:mainfrom
Dodothereal:codex/fix-issue-1208-query-builder-immutability

Conversation

@Dodothereal
Copy link

@Dodothereal Dodothereal commented Feb 8, 2026

Summary

  • make filter builder operations copy-on-write instead of mutating shared query builder state
  • update not_, filter, and or_ to return new builder instances with independent request state
  • fix match() chaining to work with immutable builder semantics
  • add sync/async tests reproducing the issue scenario where reusing a base query previously accumulated old filters

Why

Issue #1208 reports that reusing a query builder leaks previous filters into later queries. This change preserves the base builder and prevents cross-call filter accumulation.

Testing

  • uv run --package postgrest pytest tests/_sync/test_filter_request_builder.py tests/_async/test_filter_request_builder.py tests/_sync/test_request_builder.py tests/_async/test_request_builder.py (run in src/postgrest)
  • uv run --package postgrest pytest tests/_sync/test_client.py tests/_async/test_client.py (run in src/postgrest)
  • make postgrest.mypy
  • uv run ruff check src/postgrest/src/postgrest/base_request_builder.py src/postgrest/tests/_sync/test_filter_request_builder.py src/postgrest/tests/_async/test_filter_request_builder.py

Closes #1208

Summary by CodeRabbit

  • Bug Fixes

    • Fixed filter builder operations to maintain immutability—chaining operations no longer mutate the original builder, ensuring independent query modifications don't affect each other.
  • Tests

    • Added tests to verify filter builder immutability across sync and async implementations.

@Dodothereal
Copy link
Author

@olirice @silentworks could you please review this bugfix for #1208 when you have time? Thanks.

@coderabbitai
Copy link

coderabbitai bot commented Feb 8, 2026

📝 Walkthrough

Walkthrough

The pull request implements immutability for query builder objects by introducing a _clone() method that creates shallow copies of builder state. Methods like not_(), filter(), or_(), and match() now operate on clones and return the modified copy instead of mutating the original builder instance.

Changes

Cohort / File(s) Summary
Builder Immutability Implementation
src/postgrest/src/postgrest/base_request_builder.py
Added _clone() method to create copies of builder state including RequestConfig (session, path, http_method, headers, params, auth, json) and negate_next flag. Modified not_(), filter(), or_(), and match() methods to return cloned builders instead of mutating self.
Immutability Tests
src/postgrest/tests/_async/test_filter_request_builder.py, src/postgrest/tests/_sync/test_filter_request_builder.py
Added test_filter_builders_are_immutable() test to verify that filter builder chaining operations preserve the original builder's state while allowing independent modifications on derived queries.

Estimated code review effort

🎯 2 (Simple) | ⏱️ ~12 minutes

🚥 Pre-merge checks | ✅ 5
✅ Passed checks (5 passed)
Check name Status Explanation
Description Check ✅ Passed Check skipped - CodeRabbit’s high-level summary is enabled.
Title check ✅ Passed The title accurately describes the main change: preventing filter query builder state leakage through immutability implementation.
Linked Issues check ✅ Passed The PR fully addresses issue #1208 by implementing copy-on-write semantics for filter builder operations, making them immutable and preventing state leakage across chained calls.
Out of Scope Changes check ✅ Passed All changes in the PR are directly scoped to resolving issue #1208: the clone method implementation and updates to not, filter, and or_ methods for immutability, plus relevant test additions.
Docstring Coverage ✅ Passed No functions found in the changed files to evaluate docstring coverage. Skipping docstring coverage check.

✏️ Tip: You can configure your own custom pre-merge checks in the settings.

✨ Finishing touches
  • 📝 Generate docstrings
🧪 Generate unit tests (beta)
  • Create PR with unit tests
  • Post copyable unit tests in a comment

No actionable comments were generated in the recent review. 🎉

🧹 Recent nitpick comments
src/postgrest/src/postgrest/base_request_builder.py (1)

277-291: Consider deep copying mutable request JSON for safer immutability guarantees.

_clone copies headers/params but passes request.json by reference. While the current codebase doesn't mutate json, deep copying (e.g., copy.deepcopy(self.request.json)) would provide stronger isolation and prevent accidental state leakage if json is modified externally.


Comment @coderabbitai help to get the list of available commands and usage tips.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

Query builder queries are not immutable

1 participant