Here's a patchset consolidating all the fixes discussed till now. The test fix for buildfarm issue is already committed.
0001: Fixes the segmentation fault reported in [1]. There is some difference of opinion about supporting non-local variable references [2]. Given that it's a segmentation fault, we need to fix this sooner. 0002: Cleanup patch proposed by Man Zeng [3]. I think we can wait to collect more such cleanups before committing this. [1] https://www.postgresql.org/message-id/[email protected] [2] https://www.postgresql.org/message-id/CAAAe_zCA_9=JWBf4S5o_C2=EO=6dBZ6-=t0tuh+z5cvjkrt...@mail.gmail.com [3] https://www.postgresql.org/message-id/[email protected] -- Best Wishes, Ashutosh Bapat
From 3425fb0945f06593d792004a9ea80dc171cb8e8a Mon Sep 17 00:00:00 2001 From: Ashutosh Bapat <[email protected]> Date: Wed, 18 Mar 2026 19:27:38 +0530 Subject: [PATCH v20260320 1/2] Cross variable references in graph pattern causes segfault When converting the WHERE clause in an element pattern, generate_query_for_graph_path() calls replace_property_refs() to replace the property references in it. Only the current graph element pattern is passed as the context for replacement. If there are references to variables from other element patterns, it causes a segmentation fault (an assertion failure in an Assert enabled build) since it does not find path_element object corresponding to those variables. Fix the issue by passing all the path elements in the graph pattern as context for replacement. Author: Ashutosh Bapat <[email protected]> Reported by: Man Zeng <[email protected]> Investigated by: Henson Choi <[email protected]> Reviewed by: Junwang Zhao <[email protected]> --- src/backend/rewrite/rewriteGraphTable.c | 2 +- src/test/regress/expected/graph_table.out | 14 ++++++++++++++ src/test/regress/sql/graph_table.sql | 4 ++++ 3 files changed, 19 insertions(+), 1 deletion(-) diff --git a/src/backend/rewrite/rewriteGraphTable.c b/src/backend/rewrite/rewriteGraphTable.c index 06f2f3442d8..d3f382573fd 100644 --- a/src/backend/rewrite/rewriteGraphTable.c +++ b/src/backend/rewrite/rewriteGraphTable.c @@ -519,7 +519,7 @@ generate_query_for_graph_path(RangeTblEntry *rte, List *graph_path) { Node *tr; - tr = replace_property_refs(rte->relid, pf->whereClause, list_make1(pe)); + tr = replace_property_refs(rte->relid, pf->whereClause, graph_path); qual_exprs = lappend(qual_exprs, tr); } diff --git a/src/test/regress/expected/graph_table.out b/src/test/regress/expected/graph_table.out index 27c81ec6e42..eeaf1b85121 100644 --- a/src/test/regress/expected/graph_table.out +++ b/src/test/regress/expected/graph_table.out @@ -395,6 +395,20 @@ SELECT * FROM GRAPH_TABLE (g1 MATCH (v1 IS vl2)-(v2) COLUMNS (v1.vname AS v1name v22 | v32 (3 rows) +-- cross variable references +SELECT * FROM GRAPH_TABLE (g1 MATCH (a)-[b WHERE a.vprop1 = 10]->(c) COLUMNS (a.vname AS aname, a.vprop1 AS ap1, b.ename AS bname, b.eprop1 AS bp1, c.vname AS cname, c.vprop1 AS cp1)) ORDER BY aname, bname, cname; + aname | ap1 | bname | bp1 | cname | cp1 +-------+-----+-------+-------+-------+------ + v11 | 10 | e121 | 10001 | v22 | 1020 + v11 | 10 | e131 | 10003 | v33 | 2030 + v11 | 10 | e132 | 10004 | v31 | 2010 +(3 rows) + +-- forward variable reference, not supported +SELECT * FROM GRAPH_TABLE (g1 MATCH (a WHERE b.eprop1 = 10001)-[b]->(c) COLUMNS (a.vname AS aname, a.vprop1 AS ap1, b.ename AS bname, b.eprop1 AS bp1, c.vname AS cname, c.vprop1 AS cp1)) ORDER BY aname, bname, cname; +ERROR: missing FROM-clause entry for table "b" +LINE 1: SELECT * FROM GRAPH_TABLE (g1 MATCH (a WHERE b.eprop1 = 1000... + ^ -- Errors -- vl1 is not associated with property vprop2 SELECT src, src_vprop2, conn, dest FROM GRAPH_TABLE (g1 MATCH (a IS vl1)-[b IS el1]->(c IS vl2 | vl3) COLUMNS (a.vname AS src, a.vprop2 AS src_vprop2, b.ename AS conn, c.vname AS dest)); diff --git a/src/test/regress/sql/graph_table.sql b/src/test/regress/sql/graph_table.sql index 6d2b08b997b..c3a35b69e92 100644 --- a/src/test/regress/sql/graph_table.sql +++ b/src/test/regress/sql/graph_table.sql @@ -274,6 +274,10 @@ SELECT src, conn, dest, lprop1, vprop2, vprop1 FROM GRAPH_TABLE (g1 MATCH (a IS -- edges directed in both ways - to and from v2 SELECT * FROM GRAPH_TABLE (g1 MATCH (v1 IS vl2)-[conn]-(v2) COLUMNS (v1.vname AS v1name, conn.ename AS cname, v2.vname AS v2name)); SELECT * FROM GRAPH_TABLE (g1 MATCH (v1 IS vl2)-(v2) COLUMNS (v1.vname AS v1name, v2.vname AS v2name)); +-- cross variable references +SELECT * FROM GRAPH_TABLE (g1 MATCH (a)-[b WHERE a.vprop1 = 10]->(c) COLUMNS (a.vname AS aname, a.vprop1 AS ap1, b.ename AS bname, b.eprop1 AS bp1, c.vname AS cname, c.vprop1 AS cp1)) ORDER BY aname, bname, cname; +-- forward variable reference, not supported +SELECT * FROM GRAPH_TABLE (g1 MATCH (a WHERE b.eprop1 = 10001)-[b]->(c) COLUMNS (a.vname AS aname, a.vprop1 AS ap1, b.ename AS bname, b.eprop1 AS bp1, c.vname AS cname, c.vprop1 AS cp1)) ORDER BY aname, bname, cname; -- Errors -- vl1 is not associated with property vprop2 base-commit: e7975f1c06b585dcda645c6047e6f37cdfacce84 -- 2.34.1
From 1468d55b022cd1b0d19352a90bf32eefc3c39dbc Mon Sep 17 00:00:00 2001 From: Ashutosh Bapat <[email protected]> Date: Tue, 17 Mar 2026 14:30:16 +0530 Subject: [PATCH v20260320 2/2] rewriteGraphTable.c cleanup --- src/backend/rewrite/rewriteGraphTable.c | 32 ++++++++++++------------- 1 file changed, 15 insertions(+), 17 deletions(-) diff --git a/src/backend/rewrite/rewriteGraphTable.c b/src/backend/rewrite/rewriteGraphTable.c index d3f382573fd..007f58d6d88 100644 --- a/src/backend/rewrite/rewriteGraphTable.c +++ b/src/backend/rewrite/rewriteGraphTable.c @@ -33,7 +33,6 @@ #include "parser/parse_oper.h" #include "parser/parse_relation.h" #include "parser/parsetree.h" -#include "parser/parse_relation.h" #include "parser/parse_graphtable.h" #include "rewrite/rewriteGraphTable.h" #include "rewrite/rewriteHandler.h" @@ -247,16 +246,14 @@ generate_queries_for_path_pattern(RangeTblEntry *rte, List *path_pattern) if (!pf) { - { - pf = palloc0_object(struct path_factor); - pf->factorpos = factorpos++; - pf->kind = gep->kind; - pf->labelexpr = gep->labelexpr; - pf->variable = gep->variable; - pf->whereClause = gep->whereClause; - - path_factors = lappend(path_factors, pf); - } + pf = palloc0_object(struct path_factor); + pf->factorpos = factorpos++; + pf->kind = gep->kind; + pf->labelexpr = gep->labelexpr; + pf->variable = gep->variable; + pf->whereClause = gep->whereClause; + + path_factors = lappend(path_factors, pf); } /* @@ -280,7 +277,7 @@ generate_queries_for_path_pattern(RangeTblEntry *rte, List *path_pattern) * be merged even though they have different variables. Such element * patterns form a walk of graph where vertex and edges are repeated. * For example, in (a)-[b]->(c)<-[b]-(d), (a) and (d) represent the - * same vertex element. This is slighly harder to implement and + * same vertex element. This is slightly harder to implement and * probably less useful. Hence not supported for now. */ if (prev_pf) @@ -423,7 +420,7 @@ generate_query_for_graph_path(RangeTblEntry *rte, List *graph_path) Assert(pf->kind == VERTEX_PATTERN || IS_EDGE_PATTERN(pf->kind)); - /* Add conditions representing edge connnections. */ + /* Add conditions representing edge connections. */ if (IS_EDGE_PATTERN(pf->kind)) { struct path_element *src_pe; @@ -736,7 +733,7 @@ generate_setop_from_pathqueries(List *pathqueries, List **rtable, List **targetl /* * Construct a path_element object for the graph element given by `elemoid` - * statisfied by the path factor `pf`. + * satisfied by the path factor `pf`. * * If the type of graph element does not fit the element pattern kind, the * function returns NULL. @@ -936,7 +933,7 @@ get_path_elements_for_path_factor(Oid propgraphid, struct path_factor *pf) } /* - * Rememeber qualified and unqualified elements processed so + * Remember qualified and unqualified elements processed so * far to avoid processing already processed elements again. */ elem_oids_seen = lappend_oid(elem_oids_seen, label_elem->pgelelid); @@ -1105,8 +1102,9 @@ replace_property_refs_mutator(Node *node, struct replace_property_refs_context * * The property is associated with at least one of the labels * that satisfy given element pattern. If it's associated with * the given element (through some other label), use - * correspondig value expression. Otherwise NULL. Ref. SQL/PGQ - * standard section 6.5 Property Reference, General Rule 2.b. + * corresponding value expression. Otherwise NULL. Ref. + * SQL/PGQ standard section 6.5 Property Reference, General + * Rule 2.b. */ n = get_element_property_expr(found_mapping->elemoid, gpr->propid, mapping_factor->factorpos + 1); -- 2.34.1
