Summary
When pg_ducklake is loaded, any CREATE VIEW statement whose query body
contains an explicit JOIN, LEFT JOIN, RIGHT JOIN, or LATERAL clause
crashes with:
ERROR: unrecognized node type: 63
The view is not created. The same query works fine as a plain SELECT.
Reproduction
-- Setup
CREATE TABLE t1 (id int PRIMARY KEY);
CREATE TABLE t2 (id int PRIMARY KEY, label text);
-- ✅ WORKS — plain SELECT with explicit JOIN is fine
SELECT t1.id, t2.label
FROM t1
LEFT JOIN t2 ON t2.id = t1.id;
-- ✅ WORKS — CREATE VIEW with implicit comma join
CREATE VIEW test_implicit_join AS
SELECT t1.id, t2.label
FROM t1, t2
WHERE t2.id = t1.id;
-- ❌ FAILS — CREATE VIEW with explicit LEFT JOIN
-- ERROR: unrecognized node type: 63
CREATE VIEW test_left_join AS
SELECT t1.id, t2.label
FROM t1
LEFT JOIN t2 ON t2.id = t1.id;
Root cause (hypothesis)
PostgreSQL represents every explicit JOIN / LEFT JOIN / LATERAL in the
query parse tree as a JoinExpr node (T_JoinExpr = 63).
pg_ducklake installs a DDL hook that walks the query tree of CREATE VIEW
statements to discover DuckLake table references. That walker's node-dispatch
switch appears to have no case for JoinExpr, so it falls through to the
default branch and calls ereport(ERROR, ...) with the raw node tag integer,
producing the "unrecognized node type: 63" message.
The implicit comma-join (FROM t1, t2 WHERE ...) avoids the problem because
it produces a FromExpr whose fromlist holds plain RangeTblRef entries —
no JoinExpr node is generated at all.
Suggested fix
Add a JoinExpr case to the walker that recurses into:
joinexpr->larg (left relation)
joinexpr->rarg (right relation)
joinexpr->quals (the ON expression, if any)
This is the standard pattern used by PostgreSQL's own tree-walkers (see
pg_walker.c / expression_tree_walker).
Workaround
Until fixed, rewrite explicit JOINs as implicit comma joins:
-- Instead of: FROM t1 LEFT JOIN t2 ON t2.id = t1.id
-- Write: FROM t1, t2 WHERE t2.id = t1.id
Note that this only works for inner-join semantics. There is no comma-join
equivalent for LEFT JOIN (rows with no match on the right are silently
dropped), so views that require outer joins cannot be created while
pg_ducklake is loaded.
Version: pg_ducklake 1.0.0, PostgreSQL 18.4
Summary
When
pg_ducklakeis loaded, anyCREATE VIEWstatement whose query bodycontains an explicit
JOIN,LEFT JOIN,RIGHT JOIN, orLATERALclausecrashes with:
The view is not created. The same query works fine as a plain
SELECT.Reproduction
Root cause (hypothesis)
PostgreSQL represents every explicit
JOIN/LEFT JOIN/LATERALin thequery parse tree as a
JoinExprnode (T_JoinExpr = 63).pg_ducklake installs a DDL hook that walks the query tree of
CREATE VIEWstatements to discover DuckLake table references. That walker's node-dispatch
switch appears to have no case for
JoinExpr, so it falls through to thedefault branch and calls
ereport(ERROR, ...)with the raw node tag integer,producing the "unrecognized node type: 63" message.
The implicit comma-join (
FROM t1, t2 WHERE ...) avoids the problem becauseit produces a
FromExprwhosefromlistholds plainRangeTblRefentries —no
JoinExprnode is generated at all.Suggested fix
Add a
JoinExprcase to the walker that recurses into:joinexpr->larg(left relation)joinexpr->rarg(right relation)joinexpr->quals(the ON expression, if any)This is the standard pattern used by PostgreSQL's own tree-walkers (see
pg_walker.c/expression_tree_walker).Workaround
Until fixed, rewrite explicit JOINs as implicit comma joins:
Note that this only works for inner-join semantics. There is no comma-join
equivalent for
LEFT JOIN(rows with no match on the right are silentlydropped), so views that require outer joins cannot be created while
pg_ducklake is loaded.
Version: pg_ducklake 1.0.0, PostgreSQL 18.4