fix: analyze a copy of the view body in CREATE VIEW hook - #231
Merged
Conversation
The pg_ducklake utility hook parse-analyzes every CREATE VIEW body to detect duckdb_row target columns (RewriteDuckdbRowViewStmt). It fed the ViewStmt's raw query directly to parse_analyze, but parse analysis rewrites the raw tree in place: transformFromClauseItem replaces a JoinExpr's larg/rarg with RangeTblRef nodes, and transformSubLink replaces SubLink->subselect (a raw SelectStmt) with an analyzed Query. For any view we do not end up rewriting (the common case), the hook returned without using the analyzed result, leaving stmt->query corrupted. DefineView then re-ran parse analysis on the mutated tree and failed: - #229: explicit JOIN/LEFT JOIN -> "unrecognized node type: 63" (transformFromClauseItem sees a RangeTblRef where a raw FROM item is expected). - #230: EXISTS / IN (SELECT) / correlated subquery -> "unexpected non-SELECT command in SubLink" (transformSubLink sees subselect already a Query). CTE views could crash the backend outright. Both issues share this single root cause. Fix: parse-analyze a copyObject of stmt->query so the original raw tree stays pristine for DefineView. Plain SELECT and comma-join views worked before only because those shapes are not mutated in place. Adds create_view_shapes regression test: JOIN, LEFT JOIN, EXISTS, correlated scalar subquery, IN (SELECT), CTE, UNION, and LATERAL views over heap tables, plus JOIN and EXISTS over ducklake tables, each verifying SELECT returns correct rows. Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Add this suggestion to a batch that can be applied as a single commit.This suggestion is invalid because no changes were made to the code.Suggestions cannot be applied while the pull request is closed.Suggestions cannot be applied while viewing a subset of changes.Only one suggestion per line can be applied in a batch.Add this suggestion to a batch that can be applied as a single commit.Applying suggestions on deleted lines is not supported.You must change the existing code in this line in order to create a valid suggestion.Outdated suggestions cannot be applied.This suggestion has been applied or marked resolved.Suggestions cannot be applied from pending reviews.Suggestions cannot be applied on multi-line comments.Suggestions cannot be applied while the pull request is queued to merge.Suggestion cannot be applied right now. Please check back later.
With pg_ducklake installed, CREATE VIEW fails for any view body containing an explicit JOIN (ERROR: unrecognized node type: 63) or a subquery -- EXISTS, IN (SELECT ...), or a correlated subquery in the SELECT list (ERROR: unexpected non-SELECT command in SubLink). This hits pure heap tables too, no ducklake table involved, and views with CTEs crashed the backend outright.
The CREATE VIEW utility hook parse-analyzes the view body to detect duckdb_row target columns, but it fed the ViewStmt's raw query tree directly to parse_analyze. PostgreSQL's parse analysis mutates the raw tree in place (JoinExpr larg/rarg become RangeTblRef nodes, SubLink->subselect becomes an analyzed Query), so for the common case where the hook does not rewrite the view, DefineView then re-analyzed a corrupted tree and failed.
The fix is one line: analyze a copyObject of the query so the original raw tree stays pristine for DefineView.
Adds a create_view_shapes regression test covering eight view shapes over heap tables (JOIN, LEFT JOIN, EXISTS, correlated scalar subquery, IN (SELECT), CTE, UNION, LATERAL) plus JOIN and EXISTS views over ducklake tables; all of them fail or crash on unfixed code. Full regression suite passes (52/52).
Fixes #229
Fixes #230
Forward-port to main is needed.
🤖 Generated with Claude Code