Skip to content

SQL summary: isolate select state, fix bugs#16017

Merged
trask merged 3 commits intoopen-telemetry:mainfrom
trask:isolate-select-state
Jan 30, 2026
Merged

SQL summary: isolate select state, fix bugs#16017
trask merged 3 commits intoopen-telemetry:mainfrom
trask:isolate-select-state

Conversation

@trask
Copy link
Copy Markdown
Member

@trask trask commented Jan 27, 2026

Follow-up to @laurit's #15986 (comment)

Problem

Subqueries were sharing state with their outer queries, causing several bugs:

  1. Tables after subqueries not captured: SELECT * FROM a, (SELECT * FROM b), c would miss "c" because the subquery's completion interfered with the outer FROM clause state
  2. UNION inside subquery corrupted outer state: The UNION/INTERSECT/EXCEPT handling was setting operation = none, which broke the outer query's operation tracking
  3. VALUES in subquery polluted summary: INSERT INTO t SELECT * FROM (VALUES (1)) would incorrectly append "VALUES" to the summary

Solution

Introduced an operation stack to properly isolate subquery state:

  • operationStack (ArrayDeque): Pushes current operation when entering a subquery, pops when exiting
  • subqueryStartLevels (ArrayDeque): Tracks paren levels where subqueries begin

When a subquery completes, the outer query's state is restored and updated to account for the subquery as one "table reference" in the FROM clause.

Additional cleanup

Simplified the Select class state from 12 fields to 6:

Removed Reason
mainTableSetAlready Redundant with identifierCount > 0
inImplicitJoin Unused
identifiersAfterComma Merged into single identifierCount
expectingSubqueryOrTable Redundant with captureTableList || captureSingleTable
inColumnAliasList Redundant with columnAliasListParenLevel >= 0
identifiersAfterJoin Merged into single identifierCount

Renamed fields for clarity:

  • expectingTableNamecaptureTableList (FROM clause mode)
  • expectingJoinTableNamecaptureSingleTable (JOIN clause mode)

Testing

Added test cases for subquery state isolation:

  • SELECT * FROM a, (SELECT * FROM b), c"SELECT a b c"
  • SELECT * FROM (SELECT * FROM inner1), (SELECT * FROM inner2), outer_table → captures all tables

Comment on lines +742 to +747
Arguments.of(
"SELECT * FROM a, (SELECT * FROM b), c",
expect("SELECT", null, "SELECT a SELECT b c")),
Arguments.of(
"SELECT * FROM (SELECT * FROM inner1), (SELECT * FROM inner2), outer_table",
expect("SELECT", null, "SELECT SELECT inner1 SELECT inner2 outer_table")));
Copy link
Copy Markdown
Member Author

Choose a reason for hiding this comment

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

these didn't work previously

@trask trask force-pushed the isolate-select-state branch from 24a8e75 to 3cda0ec Compare January 27, 2026 23:25
@trask trask marked this pull request as ready for review January 28, 2026 03:00
@trask trask requested a review from a team as a code owner January 28, 2026 03:00
private void pushOperation() {
operationStack.push(operation);
subqueryStartLevels.push(parenLevel);
operation = none;
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.

what if you have SELECT * FROM (TABLE)

Copy link
Copy Markdown
Member Author

Choose a reason for hiding this comment

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

I don't think this is valid SQL?

Copy link
Copy Markdown
Contributor

@laurit laurit Jan 29, 2026

Choose a reason for hiding this comment

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

you can try it our in https://www.db-fiddle.com/ it works on mysql but doesn't on postgres

Copy link
Copy Markdown
Member Author

@trask trask Jan 29, 2026

Choose a reason for hiding this comment

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

handled now in 0eba6fd

@trask trask force-pushed the isolate-select-state branch from e08b74b to 0eba6fd Compare January 29, 2026 18:58

/** Called when an identifier is seen - cancels pending subquery (it's a parenthesized table name). */
private void cancelPendingSubqueryIfNeeded() {
pendingSubqueryPush = false;
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.

commenting this line out doesn't seem to make any tests fail

Copy link
Copy Markdown
Member Author

Choose a reason for hiding this comment

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

now it does! 214d013

@trask trask enabled auto-merge (squash) January 30, 2026 16:09
@trask trask merged commit 9268602 into open-telemetry:main Jan 30, 2026
85 checks passed
@trask trask deleted the isolate-select-state branch January 30, 2026 16:49
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