Skip to content

fix: analyze a copy of the view body in CREATE VIEW hook - #231

Merged
qsliu2017 merged 1 commit into
v1.0from
fix/229-230-view-query-walker
Jul 17, 2026
Merged

fix: analyze a copy of the view body in CREATE VIEW hook#231
qsliu2017 merged 1 commit into
v1.0from
fix/229-230-view-query-walker

Conversation

@qsliu2017

Copy link
Copy Markdown
Collaborator

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

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>
@qsliu2017
qsliu2017 merged commit a867311 into v1.0 Jul 17, 2026
8 checks passed
@qsliu2017
qsliu2017 deleted the fix/229-230-view-query-walker branch July 17, 2026 03:37
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.

1 participant