From c9485f52e6b25f379d27cc3ec16307ca6d306360 Mon Sep 17 00:00:00 2001 From: Ewan Young Date: Tue, 23 Jun 2026 00:40:22 +0800 Subject: [PATCH v3] Disallow aggregates and window functions in GRAPH_TABLE COLUMNS The COLUMNS list of a GRAPH_TABLE query is parsed as an ordinary select target list, which permits aggregate functions and window functions. GRAPH_TABLE has no machinery to evaluate them, though: the rewriter copies the COLUMNS target list verbatim into a freshly built subquery whose hasAggs/hasWindowFuncs flags are never set, so the planner builds no Agg/WindowAgg node and the Aggref/WindowFunc reaches the executor. This triggers an assertion failure ("ecxt_aggvalues != NULL"), or "Aggref found in non-Agg plan node" on a non-assert build, for otherwise parser-accepted SQL such as SELECT max(c) FROM GRAPH_TABLE (g MATCH (x IS v) COLUMNS (count(*) AS c)); Reject these constructs in transformRangeGraphTable() the same way subqueries are already handled: save and clear pstate->p_hasAggs and p_hasWindowFuncs around the transformation of the COLUMNS list, and raise a "not supported" error if either of them got set. This is deliberately a blanket prohibition for now. Once quantified element patterns such as (a)->{1,5} are supported, aggregates over property references of higher degree (e.g. count(a) or sum(a.val)) can be allowed; at that point the check will need to inspect the aggregate arguments rather than reject all aggregates outright. --- src/backend/parser/parse_clause.c | 22 ++++++++++++++++++++++ src/test/regress/expected/graph_table.out | 5 +++++ src/test/regress/sql/graph_table.sql | 3 +++ 3 files changed, 30 insertions(+) diff --git a/src/backend/parser/parse_clause.c b/src/backend/parser/parse_clause.c index 5fe5257b019..32a180bfc5d 100644 --- a/src/backend/parser/parse_clause.c +++ b/src/backend/parser/parse_clause.c @@ -946,6 +946,8 @@ transformRangeGraphTable(ParseState *pstate, RangeGraphTable *rgt) ListCell *lc; int resno = 0; bool saved_hasSublinks; + bool saved_hasAggs; + bool saved_hasWindowFuncs; rel = parserOpenPropGraph(pstate, rgt->graph_name, AccessShareLock); @@ -967,6 +969,11 @@ transformRangeGraphTable(ParseState *pstate, RangeGraphTable *rgt) saved_hasSublinks = pstate->p_hasSubLinks; pstate->p_hasSubLinks = false; + saved_hasAggs = pstate->p_hasAggs; + pstate->p_hasAggs = false; + saved_hasWindowFuncs = pstate->p_hasWindowFuncs; + pstate->p_hasWindowFuncs = false; + gp = transformGraphPattern(pstate, rgt->graph_pattern); /* @@ -1027,6 +1034,21 @@ transformRangeGraphTable(ParseState *pstate, RangeGraphTable *rgt) errmsg("subqueries within GRAPH_TABLE reference are not supported"))); pstate->p_hasSubLinks = saved_hasSublinks; + /* + * Likewise, GRAPH_TABLE cannot yet evaluate aggregate or window functions + * in its COLUMNS list, so prohibit them for now. + */ + if (pstate->p_hasAggs) + ereport(ERROR, + (errcode(ERRCODE_FEATURE_NOT_SUPPORTED), + errmsg("aggregate functions within GRAPH_TABLE COLUMNS are not supported"))); + if (pstate->p_hasWindowFuncs) + ereport(ERROR, + (errcode(ERRCODE_FEATURE_NOT_SUPPORTED), + errmsg("window functions within GRAPH_TABLE COLUMNS are not supported"))); + pstate->p_hasAggs = saved_hasAggs; + pstate->p_hasWindowFuncs = saved_hasWindowFuncs; + return addRangeTableEntryForGraphTable(pstate, graphid, castNode(GraphPattern, gp), columns, colnames, rgt->alias, false, true); } diff --git a/src/test/regress/expected/graph_table.out b/src/test/regress/expected/graph_table.out index 70d986e8ab0..3622b16d355 100644 --- a/src/test/regress/expected/graph_table.out +++ b/src/test/regress/expected/graph_table.out @@ -455,6 +455,11 @@ SELECT * FROM GRAPH_TABLE (myshop MATCH (c IS customers WHERE c.* IS NOT NULL)-[ ERROR: "*" not allowed here LINE 1: ...M GRAPH_TABLE (myshop MATCH (c IS customers WHERE c.* IS NOT... ^ +-- aggregate and window functions are not supported in COLUMNS +SELECT * FROM GRAPH_TABLE (myshop MATCH (c IS customers) COLUMNS (count(*) AS num)); +ERROR: aggregate functions within GRAPH_TABLE COLUMNS are not supported +SELECT * FROM GRAPH_TABLE (myshop MATCH (c IS customers) COLUMNS (row_number() OVER () AS rn)); +ERROR: window functions within GRAPH_TABLE COLUMNS are not supported -- consecutive element patterns with same kind SELECT * FROM GRAPH_TABLE (g1 MATCH ()() COLUMNS (1 as one)); ERROR: adjacent vertex patterns are not supported diff --git a/src/test/regress/sql/graph_table.sql b/src/test/regress/sql/graph_table.sql index 0b44f70d7e7..0ef1ee7e90f 100644 --- a/src/test/regress/sql/graph_table.sql +++ b/src/test/regress/sql/graph_table.sql @@ -302,6 +302,9 @@ SELECT * FROM GRAPH_TABLE (g1 MATCH (src IS el1 | vl1)-[conn]->(dest) COLUMNS (c SELECT * FROM GRAPH_TABLE (myshop MATCH (c IS customers WHERE c.address = 'US')-[IS customer_orders]->(o IS orders) COLUMNS (c.*)); -- star anywhere else is not allowed as a property reference SELECT * FROM GRAPH_TABLE (myshop MATCH (c IS customers WHERE c.* IS NOT NULL)-[IS customer_orders]->(o IS orders) COLUMNS (c.name)); +-- aggregate and window functions are not supported in COLUMNS +SELECT * FROM GRAPH_TABLE (myshop MATCH (c IS customers) COLUMNS (count(*) AS num)); +SELECT * FROM GRAPH_TABLE (myshop MATCH (c IS customers) COLUMNS (row_number() OVER () AS rn)); -- consecutive element patterns with same kind SELECT * FROM GRAPH_TABLE (g1 MATCH ()() COLUMNS (1 as one)); SELECT * FROM GRAPH_TABLE (g1 MATCH -> COLUMNS (1 AS one)); -- 2.47.3