]> git.ipfire.org Git - thirdparty/postgresql.git/commitdiff
Fix collation of expressions in GRAPH_TABLE COLUMNS clause
authorPeter Eisentraut <peter@eisentraut.org>
Fri, 24 Apr 2026 06:43:26 +0000 (08:43 +0200)
committerPeter Eisentraut <peter@eisentraut.org>
Fri, 24 Apr 2026 06:43:26 +0000 (08:43 +0200)
GRAPH_TABLE clause is converted into a rangetable entry, which is
ignored by assign_query_collations().  Hence we assign collations
while transforming its parts.  But expressions in COLUMNS clause
missed that treatment, so fix that.

While at it, also add comments about collation assignment to the parts
of GRAPH_TABLE clause, and also fix a small grammar issue.

Reported-by: Satyanarayana Narlapuram <satyanarlapuram@gmail.com>
Author: Satyanarayana Narlapuram <satyanarlapuram@gmail.com>
Author: Ashutosh Bapat <ashutosh.bapat.oss@gmail.com>
Discussion: https://www.postgresql.org/message-id/CAHg+QDc4aaiufYSgrwMMPMMRTPtQ66SghcrPFbWJFZMqNaG+BA@mail.gmail.com

src/backend/parser/parse_clause.c
src/backend/parser/parse_graphtable.c
src/test/regress/expected/graph_table.out
src/test/regress/sql/graph_table.sql

index 967eea44f1c7cfb16c68885e794ec03ea5c6f079..4270c2382c47ec07e11ef8122a8c4f8412fd7c37 100644 (file)
@@ -1003,6 +1003,12 @@ transformRangeGraphTable(ParseState *pstate, RangeGraphTable *rgt)
                columns = lappend(columns, te);
        }
 
+       /*
+        * Assign collations to column expressions now since
+        * assign_query_collations() does not process rangetable entries.
+        */
+       assign_list_collations(pstate, columns);
+
        table_close(rel, NoLock);
 
        pstate->p_graph_table_pstate = NULL;
index f889c8df4e314df94a2d114ca47d0a7cf5a57c25..73fbfb541f7ea19bc64783e1803ea7d4a09de911 100644 (file)
@@ -252,6 +252,11 @@ transformGraphElementPattern(ParseState *pstate, GraphElementPattern *gep)
        gep->labelexpr = transformLabelExpr(gpstate, gep->labelexpr);
 
        gep->whereClause = transformExpr(pstate, gep->whereClause, EXPR_KIND_WHERE);
+
+       /*
+        * Assign collations here for the reason mentioned in the prologue of
+        * transformGraphPattern().
+        */
        assign_expr_collations(pstate, gep->whereClause);
 
        gpstate->cur_gep = NULL;
@@ -366,9 +371,14 @@ transformPathPatternList(ParseState *pstate, List *path_pattern)
  * Transform a GraphPattern.
  *
  * A GraphPattern consists of a list of one or more path patterns and an
- * optional where clause. Transform them. We use the previously constructure
+ * optional where clause. Transform them. We use the previously constructed
  * list of variables in the GraphTableParseState to resolve property references
  * in the WHERE clause.
+ *
+ * Since most parts of the GraphPattern do not require collation assignment, we
+ * assign collations to the required expressions as they are transformed.  This
+ * avoids the need to traverse the whole GraphPattern again and avoids exposing
+ * it to assign_expr_collations().
  */
 Node *
 transformGraphPattern(ParseState *pstate, GraphPattern *graph_pattern)
index b579e3df6351398d27b73fc5667ed5988384c324..057f283c43d3c5c698c9f847939fab3d037a12bd 100644 (file)
@@ -652,13 +652,13 @@ SELECT * FROM GRAPH_TABLE (g1 MATCH (a)-(a) COLUMNS (a.vname AS self));
  v33
 (1 row)
 
--- test collation specified in the expression
+-- test explicit and implicit collation assignment
 INSERT INTO e3_3 VALUES (2003, 2003, 'E331', 10011);
-SELECT * FROM GRAPH_TABLE (g1 MATCH (a)-[b]->(a)-[b]->(a) COLUMNS (a.vname AS self, b.ename AS loop_name)) ORDER BY loop_name COLLATE "C" ASC;
+SELECT * FROM GRAPH_TABLE (g1 MATCH (a)-[b]->(a)-[b]->(a) COLUMNS (upper(a.vname) AS self, b.ename AS loop_name)) ORDER BY loop_name COLLATE "C" ASC;
  self | loop_name 
 ------+-----------
v33  | E331
v33  | e331
V33  | E331
V33  | e331
 (2 rows)
 
 SELECT * FROM GRAPH_TABLE (g1 MATCH (a)-[b IS el2 WHERE b.ename > 'E331' COLLATE "C"]->(a)-[b]->(a) COLUMNS (a.vname AS self, b.ename AS loop_name));
index 4ff98817420db9d5adba18e16913df7a7c8bb61c..278064818ffe656b3a98568bcc7767f99aac41ea 100644 (file)
@@ -394,9 +394,9 @@ SELECT * FROM GRAPH_TABLE (g1 MATCH (a)-[b]->(c)-[b]->(d) COLUMNS (a.vname AS an
 SELECT * FROM GRAPH_TABLE (g1 MATCH (a)-[c]-(a) COLUMNS (a.vname AS self, c.ename AS loop_name));
 SELECT * FROM GRAPH_TABLE (g1 MATCH (a)-(a) COLUMNS (a.vname AS self));
 
--- test collation specified in the expression
+-- test explicit and implicit collation assignment
 INSERT INTO e3_3 VALUES (2003, 2003, 'E331', 10011);
-SELECT * FROM GRAPH_TABLE (g1 MATCH (a)-[b]->(a)-[b]->(a) COLUMNS (a.vname AS self, b.ename AS loop_name)) ORDER BY loop_name COLLATE "C" ASC;
+SELECT * FROM GRAPH_TABLE (g1 MATCH (a)-[b]->(a)-[b]->(a) COLUMNS (upper(a.vname) AS self, b.ename AS loop_name)) ORDER BY loop_name COLLATE "C" ASC;
 SELECT * FROM GRAPH_TABLE (g1 MATCH (a)-[b IS el2 WHERE b.ename > 'E331' COLLATE "C"]->(a)-[b]->(a) COLUMNS (a.vname AS self, b.ename AS loop_name));
 SELECT * FROM GRAPH_TABLE (g1 MATCH (a)-[b]->(a)-[b]->(a) WHERE b.ename > 'E331' COLLATE "C" COLUMNS (a.vname AS self, b.ename AS loop_name));
 SELECT * FROM GRAPH_TABLE (g1 MATCH (a)-[b]->(a)-[b]->(a) COLUMNS (a.vname AS self, b.ename AS loop_name)) WHERE loop_name > 'E331' COLLATE "C";