Skip to content

fix: parenthesize IN-list quals when deparsing - #654

Closed
breken-ai wants to merge 1 commit into
supabase:mainfrom
breken-ai:fix/in-list-qual-parentheses
Closed

breken-ai wants to merge 1 commit into
supabase:mainfrom
breken-ai:fix/in-list-qual-parentheses

Conversation

@breken-ai

Copy link
Copy Markdown

What kind of change does this PR introduce?

Bug fix (qual deparse, supabase-wrappers/src/interface.rs and mysql_fdw).

What is the current behavior?

Qual::deparse_with_fmt renders an IN list (use_or = true) as a bare OR chain, id = 1 or id = 2 or id = 3. The FDWs join quals with " and ", so:

SELECT count(*) FROM mysql_agg.orders WHERE id IN (1, 2, 3) AND status = 'inactive';

reaches the remote as

... where `id` = 1 or `id` = 2 or `id` = 3 and `status` = 'inactive'

AND binds tighter than OR, so ids 1 and 2 match whatever their status is.

  • With aggregate pushdown (MySQL, ClickHouse, BigQuery), that wrong count or sum is returned directly: the query above returns 3 instead of 1.
  • Plain scans are rechecked locally, so they only over-fetch.
  • A plain scan still returns too few rows when a LIMIT is also pushed down.

The same pattern is in Qual::deparse (used by BigQuery, DuckDB, ClickHouse, MSSQL, and Wasm FDWs through the host's deparse) and in the copy in mysql_fdw::deparse_qual.

What is the new behavior?

An OR list with more than one element is wrapped in parentheses: (id = 1 or id = 2 or id = 3). Single-element and empty lists are rendered exactly as before.

Additional context

  • New tests:
    • Unit tests in interface.rs: test_qual_deparse_or_list_is_parenthesized and test_qual_deparse_single_element_or_list.
    • A mysql_fdw case: COUNT(*) ... WHERE id IN (1, 2, 3) AND status = 'inactive' returns 1 and is still pushed down.
  • Red/green:
    • On main, the unit test fails (left: "id = 1 or id = 2 or id = 3") and the mysql case fails with expected 1, got 3, run with cargo pgrx test pg17 mysql --features mysql_fdw against mysql:8.4.
    • With this change, cargo test -p supabase-wrappers --lib passes 38/38 and all 3 mysql pgrx tests pass.
  • Checks: cargo fmt --check passes, and cargo clippy --tests -D warnings (pg17, mysql_fdw) is clean.

This PR was prepared with AI assistance (Claude). I reproduced the failure and ran the tests locally as described above.

🤖 Generated with Claude Code

An IN list is deparsed as a chain of ORs (id = 1 or id = 2). FDWs join
quals with "and", so WHERE id IN (1, 2) AND status = 'x' reached the
remote as id = 1 or id = 2 and status = 'x', which matches id 1 regardless
of status. Aggregate pushdown returns that wrong result directly.

Wrap multi-element OR lists in parentheses in Qual::deparse_with_fmt and
in mysql_fdw's own deparse_qual.

Co-Authored-By: Claude Opus 5.5 (1M context) <noreply@anthropic.com>
@imor

imor commented Sep 27, 2026

Copy link
Copy Markdown
Contributor

Closing as this is 100% AI generated.

@imor imor closed this Sep 27, 2026
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.

2 participants