From 4cd6a54ef711cccd1f7d7bfb6e32d3ae1aa85411 Mon Sep 17 00:00:00 2001
From: Ewan Young <kdbase.hack@gmail.com>
Date: Mon, 31 Aug 2026 22:53:03 +0800
Subject: [PATCH] Coerce GRAPH_TABLE pattern WHERE clauses to boolean

transformGraphElementPattern() and transformGraphPattern() ran their
WHERE clauses through transformExpr() without ever applying
coerce_to_boolean(), so a WHERE clause of any type was accepted and its
bare datum was used as the qual.  For example,
MATCH (c IS customers WHERE c.name) is accepted and EXPLAIN shows
"Filter: name"; the never-null text pointer is always taken as true,
so the condition silently degenerates to roughly "name IS NOT NULL"
instead of raising the usual "argument of WHERE must be type boolean"
error.  Wrong results, no diagnostic.

Route both sites through transformWhereClause(), like every other WHERE
clause, and add regression tests for the element-level and
pattern-level cases.
---
 src/backend/parser/parse_graphtable.c     | 7 +++++--
 src/test/regress/expected/graph_table.out | 4 ++++
 src/test/regress/sql/graph_table.sql      | 2 ++
 3 files changed, 11 insertions(+), 2 deletions(-)

diff --git a/src/backend/parser/parse_graphtable.c b/src/backend/parser/parse_graphtable.c
index 73fbfb541f7..b44f7ccd0a7 100644
--- a/src/backend/parser/parse_graphtable.c
+++ b/src/backend/parser/parse_graphtable.c
@@ -22,6 +22,7 @@
 #include "catalog/pg_propgraph_property.h"
 #include "miscadmin.h"
 #include "nodes/makefuncs.h"
+#include "parser/parse_clause.h"
 #include "parser/parse_collate.h"
 #include "parser/parse_expr.h"
 #include "parser/parse_graphtable.h"
@@ -251,7 +252,8 @@ transformGraphElementPattern(ParseState *pstate, GraphElementPattern *gep)
 
 	gep->labelexpr = transformLabelExpr(gpstate, gep->labelexpr);
 
-	gep->whereClause = transformExpr(pstate, gep->whereClause, EXPR_KIND_WHERE);
+	gep->whereClause = transformWhereClause(pstate, gep->whereClause,
+											EXPR_KIND_WHERE, "WHERE");
 
 	/*
 	 * Assign collations here for the reason mentioned in the prologue of
@@ -387,7 +389,8 @@ transformGraphPattern(ParseState *pstate, GraphPattern *graph_pattern)
 											 transformPathPatternList(pstate, graph_pattern->path_pattern_list));
 
 	graph_pattern->path_pattern_list = path_pattern_list;
-	graph_pattern->whereClause = transformExpr(pstate, graph_pattern->whereClause, EXPR_KIND_WHERE);
+	graph_pattern->whereClause = transformWhereClause(pstate, graph_pattern->whereClause,
+													  EXPR_KIND_WHERE, "WHERE");
 	assign_expr_collations(pstate, graph_pattern->whereClause);
 
 	return (Node *) graph_pattern;
diff --git a/src/test/regress/expected/graph_table.out b/src/test/regress/expected/graph_table.out
index 2e862a82ba0..dd051aa4d1c 100644
--- a/src/test/regress/expected/graph_table.out
+++ b/src/test/regress/expected/graph_table.out
@@ -101,6 +101,10 @@ LINE 1: SELECT * FROM GRAPH_TABLE (myshop MATCH COLUMNS (1 AS col));
                                                 ^
 SELECT customer_name FROM GRAPH_TABLE (myshop MATCH (c IS customers)->{1,2}(o IS orders) COLUMNS (c.name AS customer_name));  -- error
 ERROR:  element pattern quantifier is not supported
+SELECT customer_name FROM GRAPH_TABLE (myshop MATCH (c IS customers WHERE c.name) COLUMNS (c.name AS customer_name));  -- error, WHERE must yield boolean
+ERROR:  argument of WHERE must be type boolean, not type character varying
+SELECT customer_name FROM GRAPH_TABLE (myshop MATCH (c IS customers) WHERE c.customer_id COLUMNS (c.name AS customer_name));  -- error, WHERE must yield boolean
+ERROR:  argument of WHERE must be type boolean, not type integer
 SELECT * FROM GRAPH_TABLE (myshop MATCH ((c IS customers)->(o IS orders)) COLUMNS (c.name));
 ERROR:  unsupported element pattern kind: "nested path pattern"
 LINE 1: SELECT * FROM GRAPH_TABLE (myshop MATCH ((c IS customers)->(...
diff --git a/src/test/regress/sql/graph_table.sql b/src/test/regress/sql/graph_table.sql
index 21e70015f6e..67ea6d2f0d2 100644
--- a/src/test/regress/sql/graph_table.sql
+++ b/src/test/regress/sql/graph_table.sql
@@ -92,6 +92,8 @@ SELECT customer_name FROM GRAPH_TABLE (myshop MATCH (c IS customers WHERE c.addr
 SELECT * FROM GRAPH_TABLE (myshop MATCH (c IS customers), (o IS orders) COLUMNS (c.name AS customer_name));  -- error
 SELECT * FROM GRAPH_TABLE (myshop MATCH COLUMNS (1 AS col));  -- error, empty match clause
 SELECT customer_name FROM GRAPH_TABLE (myshop MATCH (c IS customers)->{1,2}(o IS orders) COLUMNS (c.name AS customer_name));  -- error
+SELECT customer_name FROM GRAPH_TABLE (myshop MATCH (c IS customers WHERE c.name) COLUMNS (c.name AS customer_name));  -- error, WHERE must yield boolean
+SELECT customer_name FROM GRAPH_TABLE (myshop MATCH (c IS customers) WHERE c.customer_id COLUMNS (c.name AS customer_name));  -- error, WHERE must yield boolean
 SELECT * FROM GRAPH_TABLE (myshop MATCH ((c IS customers)->(o IS orders)) COLUMNS (c.name));
 
 -- a property graph can be referenced only from within GRAPH_TABLE clause.
-- 
2.47.3

