Skip to content

Generic: Parse IN lists that start with a parenthesized subquery - #2586

Merged
LucaCappelletti94 merged 4 commits into
mainfrom
upstream/in-list-leading-subquery
Oct 2, 2026
Merged

LucaCappelletti94 merged 4 commits into
mainfrom
upstream/in-list-leading-subquery

Conversation

@LucaCappelletti94

Copy link
Copy Markdown
Contributor

Since #1793, x IN ((SELECT a FROM u), 1) fails with Expected: ), found: ,.

parse_in takes any query it can read after IN ( as the whole subquery, so a list whose first item is a parenthesized scalar subquery never reaches the list branch, but they are valid Postgres and SQLite syntax.

The speculative subquery now only counts when ) follows it, and otherwise the parser rewinds and reads a list, so IN ((SELECT a FROM u)) and the UNION case from #1793 still produce InSubquery.

Since this type of recursions sometimes scale horribly, I double checked to verify the scalability and seems rather clean, expecially when compared to the current main.

Case accepted by current main

depth SQL length (chars) main rewind branch
4 108 0.10 ms 0.13 ms 0.08 ms
8 208 1.8 ms 1.6 ms 0.20 ms
12 308 24 ms 23 ms 0.52 ms
16 408 368 ms 373 ms 0.77 ms
20 508 6 114 ms 5 930 ms 1.0 ms
24 608 > 60 s, killed > 60 s, killed 1.5 ms
32 808 not run not run 2.8 ms
64 1 608 not run not run 9.1 ms
128 3 208 not run not run 32.6 ms

Case rejected by current main

depth SQL length (chars) main rewind branch
4 84 0.02 ms, rejected 0.08 ms 0.06 ms
8 160 0.07 ms, rejected 1.3 ms 0.14 ms
12 236 0.13 ms, rejected 20 ms 0.31 ms
16 312 0.19 ms, rejected 298 ms 0.53 ms
20 388 0.32 ms, rejected 4 925 ms 0.79 ms
24 464 0.41 ms, rejected > 60 s, killed 1.1 ms
32 616 0.70 ms, rejected not run 2.4 ms
64 1 224 2.6 ms, rejected not run 6.4 ms
128 2 440 10.3 ms, rejected not run 23.8 ms

@LucaCappelletti94 LucaCappelletti94 added the bug Something isn't working label Sep 26, 2026
@codecov-commenter

codecov-commenter commented Sep 26, 2026 •

Copy link
Copy Markdown

Codecov Report

❌ Patch coverage is 97.05882% with 1 line in your changes missing coverage. Please review.
✅ Project coverage is 81.13%. Comparing base (bfc7d38) to head (bc0802a).
⚠️ Report is 4 commits behind head on main.

Files with missing lines Patch % Lines
src/parser/mod.rs 97.05% 1 Missing ⚠️
Additional details and impacted files
@@            Coverage Diff             @@
##             main    #2586      +/-   ##
==========================================
+ Coverage   81.09%   81.13%   +0.03%     
==========================================
  Files          42       42              
  Lines       33682    33729      +47     
  Branches    33682    33729      +47     
==========================================
+ Hits        27316    27367      +51     
- Misses       2796     2797       +1     
+ Partials     3570     3565       -5     

☔ View full report in Codecov by Harness.
📢 Have feedback on the report? Share it here.

🚀 New features to boost your workflow:
  • ❄️ Test Analytics: Detect flaky tests, report on failures, and find test suite problems.

@LucaCappelletti94
LucaCappelletti94 marked this pull request as ready for review September 26, 2026 10:06

@EthanVieira EthanVieira left a comment

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

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

Overall lgtm but made a note about improving diagnostics.

Comment thread src/parser/mod.rs Outdated
if !self.failed_in_subquery_positions.contains(&start) {
if let Some(subquery) = self.maybe_parse(|p| {
let subquery = p.parse_query()?;
p.expect_token(&Token::RParen)?;

@EthanVieira EthanVieira Sep 30, 2026 •

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

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

It looks like we will discard the error for an incorrect subquery and always report it as a failed list. I think the diagnostics could be improved here in certain scenarios.

For example:
SELECT * FROM t WHERE x IN (SELECT y FROM u would report a missing ) at y when it should report a missing ) at the end of the line.

We could store a missing ) error for the subquery and then if the list interpretation also fails, report the clearer error.
Maybe a heuristic like:

  1. If parsing the SELECT query itself fails, there’s no saved closing-parenthesis error. The list parser’s error is reported.
  2. If the query parses but its required ) is missing, the parser saves that error.
  3. If the list interpretation succeeds, the saved error is ignored.
  4. If the list also fails, the parser reports the saved ) error. One exception would be that a recursion-limit error takes priority.

@alamb

alamb commented Oct 1, 2026

Copy link
Copy Markdown
Contributor

Thank you @LucaCappelletti94 and @EthanVieira for the review

@LucaCappelletti94
LucaCappelletti94 added this pull request to the merge queue Oct 2, 2026
Merged via the queue into main with commit 1ba145b Oct 2, 2026
13 checks passed
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

bug Something isn't working PostgreSQL SQLite

Projects

None yet

Development

Successfully merging this pull request may close these issues.

4 participants