From 00340faa3be64541f6fac2bca55880f621f940d0 Mon Sep 17 00:00:00 2001 From: satyanarayana narlapuram Date: Tue, 21 Apr 2026 14:33:33 +0000 Subject: [PATCH] Add Graph* node support to expression_tree_mutator expression_tree_mutator_impl() was missing case handlers for T_GraphPattern, T_GraphElementPattern, and T_GraphPropertyRef. The corresponding expression_tree_walker_impl() already handled all three node types, but the mutator did not, causing an "unrecognized node type: 106" error whenever a GRAPH_TABLE subquery appeared in a HAVING clause. The fix adds three case handlers mirroring the walker: - T_GraphPropertyRef: leaf node, FLATCOPY only - T_GraphElementPattern: FLATCOPY + MUTATE subexpr, whereClause - T_GraphPattern: FLATCOPY + MUTATE path_pattern_list, whereClause --- src/backend/nodes/nodeFuncs.c | 31 +++++++++++++++++++++++ src/test/regress/expected/graph_table.out | 15 +++++++++++ src/test/regress/sql/graph_table.sql | 9 +++++++ 3 files changed, 55 insertions(+) diff --git a/src/backend/nodes/nodeFuncs.c b/src/backend/nodes/nodeFuncs.c index c0b880ec..c18f2b0e 100644 --- a/src/backend/nodes/nodeFuncs.c +++ b/src/backend/nodes/nodeFuncs.c @@ -3810,6 +3810,37 @@ expression_tree_mutator_impl(Node *node, return (Node *) newnode; } break; + case T_GraphPropertyRef: + { + GraphPropertyRef *newnode; + + FLATCOPY(newnode, node, GraphPropertyRef); + /* leaf node, no expression subnodes */ + return (Node *) newnode; + } + break; + case T_GraphElementPattern: + { + GraphElementPattern *gep = (GraphElementPattern *) node; + GraphElementPattern *newnode; + + FLATCOPY(newnode, gep, GraphElementPattern); + MUTATE(newnode->subexpr, gep->subexpr, List *); + MUTATE(newnode->whereClause, gep->whereClause, Node *); + return (Node *) newnode; + } + break; + case T_GraphPattern: + { + GraphPattern *gp = (GraphPattern *) node; + GraphPattern *newnode; + + FLATCOPY(newnode, gp, GraphPattern); + MUTATE(newnode->path_pattern_list, gp->path_pattern_list, List *); + MUTATE(newnode->whereClause, gp->whereClause, Node *); + return (Node *) newnode; + } + break; default: elog(ERROR, "unrecognized node type: %d", (int) nodeTag(node)); diff --git a/src/test/regress/expected/graph_table.out b/src/test/regress/expected/graph_table.out index b579e3df..5e57d248 100644 --- a/src/test/regress/expected/graph_table.out +++ b/src/test/regress/expected/graph_table.out @@ -1022,4 +1022,19 @@ SELECT sname, dname FROM GRAPH_TABLE (g1 MATCH (src)->(dest) WHERE src.vprop1 > ERROR: subqueries within GRAPH_TABLE reference are not supported SELECT sname, dname FROM GRAPH_TABLE (g1 MATCH (src)->(dest) WHERE out_degree(src.vname) > (SELECT max(out_degree(nname)) FROM GRAPH_TABLE (g1 MATCH (node) COLUMNS (node.vname AS nname))) COLUMNS(src.vname AS sname, dest.vname AS dname)); ERROR: subqueries within GRAPH_TABLE reference are not supported +-- GRAPH_TABLE subquery in HAVING clause +SELECT src.vname, count(*) + FROM v1 AS src + GROUP BY src.vname + HAVING count(*) >= (SELECT count(*) + FROM GRAPH_TABLE (g1 MATCH (a IS vl1) + COLUMNS (a.vname AS n)) + WHERE n = src.vname); + vname | count +-------+------- + v13 | 1 + v12 | 1 + v11 | 1 +(3 rows) + -- leave the objects behind for pg_upgrade/pg_dump tests diff --git a/src/test/regress/sql/graph_table.sql b/src/test/regress/sql/graph_table.sql index 4ff98817..3d5224d3 100644 --- a/src/test/regress/sql/graph_table.sql +++ b/src/test/regress/sql/graph_table.sql @@ -582,4 +582,13 @@ SELECT * FROM customers co WHERE co.customer_id = (SELECT customer_id FROM GRAPH SELECT sname, dname FROM GRAPH_TABLE (g1 MATCH (src)->(dest) WHERE src.vprop1 > (SELECT max(v1.vprop1) FROM v1) COLUMNS(src.vname AS sname, dest.vname AS dname)); SELECT sname, dname FROM GRAPH_TABLE (g1 MATCH (src)->(dest) WHERE out_degree(src.vname) > (SELECT max(out_degree(nname)) FROM GRAPH_TABLE (g1 MATCH (node) COLUMNS (node.vname AS nname))) COLUMNS(src.vname AS sname, dest.vname AS dname)); +-- GRAPH_TABLE subquery in HAVING clause +SELECT src.vname, count(*) + FROM v1 AS src + GROUP BY src.vname + HAVING count(*) >= (SELECT count(*) + FROM GRAPH_TABLE (g1 MATCH (a IS vl1) + COLUMNS (a.vname AS n)) + WHERE n = src.vname); + -- leave the objects behind for pg_upgrade/pg_dump tests -- 2.43.0