This is an automated email from the ASF dual-hosted git repository.
MuhammadTahaNaveed pushed a commit to branch master
in repository https://gitbox.apache.org/repos/asf/age.git
The following commit(s) were added to refs/heads/master by this push:
new 2e2120b5 Fix create_graph failing when ag_catalog is not in
search_path (#2505)
2e2120b5 is described below
commit 2e2120b5c116a1dd391d9c7331a2865a0b68255f
Author: Himmel <[email protected]>
AuthorDate: Tue Sep 15 04:02:16 2026 +0800
Fix create_graph failing when ag_catalog is not in search_path (#2505)
create_index_on_column() passed "graphid_ops" as an unqualified operator
class name, so it was resolved against the caller's search_path. Whenever
ag_catalog was not on the search_path, creating a label failed with
ERROR: operator class "graphid_ops" does not exist for access method
"btree"
even for a fully qualified call such as
SELECT ag_catalog.create_graph('g');
The error is misleading: the operator class does exist, it is simply not
visible. This affected create_graph(), create_vlabel(), create_elabel(),
the CSV loader, and label creation from a CREATE or MERGE clause at query
time, since all of them reach create_label().
The unqualified name arrived with the id column indexes in #2117, so this
is a regression. Before that commit create_label() built no index and
resolved no name through the search_path. Every other object referenced by
the DDL that create_label() generates is already reached either by OID or
by an ag_catalog qualified name, so qualifying this one restores the
previous behaviour.
---
regress/expected/catalog.out | 52 +++++++++++++++++++++++++++++++++++
regress/sql/catalog.sql | 18 ++++++++++++
src/backend/commands/label_commands.c | 3 +-
3 files changed, 72 insertions(+), 1 deletion(-)
diff --git a/regress/expected/catalog.out b/regress/expected/catalog.out
index a15fa469..7cf67cda 100644
--- a/regress/expected/catalog.out
+++ b/regress/expected/catalog.out
@@ -607,3 +607,55 @@ NOTICE: graph "graph" has been dropped
(1 row)
+--
+-- create_label() must not resolve graphid_ops through the search_path
+--
+-- Every AGE object is referenced with an ag_catalog qualified name here, so
+-- these statements have to work with ag_catalog off the search_path.
+--
+SET search_path TO public;
+SELECT ag_catalog.create_graph('graphid_ops_search_path');
+NOTICE: graph "graphid_ops_search_path" has been created
+ create_graph
+--------------
+
+(1 row)
+
+-- vertex labels index id, edge labels index start_id and end_id
+SELECT ag_catalog.create_vlabel('graphid_ops_search_path', 'v');
+NOTICE: VLabel "v" has been created
+ create_vlabel
+---------------
+
+(1 row)
+
+SELECT ag_catalog.create_elabel('graphid_ops_search_path', 'e');
+NOTICE: ELabel "e" has been created
+ create_elabel
+---------------
+
+(1 row)
+
+-- label creation at query time goes through the same path
+SELECT * FROM ag_catalog.cypher('graphid_ops_search_path',
+ $$CREATE (:query_time_v)-[:query_time_e]->(:query_time_v)$$)
+ AS (result ag_catalog.agtype);
+ result
+--------
+(0 rows)
+
+SELECT ag_catalog.drop_graph('graphid_ops_search_path', true);
+NOTICE: drop cascades to 6 other objects
+DETAIL: drop cascades to table graphid_ops_search_path._ag_label_vertex
+drop cascades to table graphid_ops_search_path._ag_label_edge
+drop cascades to table graphid_ops_search_path.v
+drop cascades to table graphid_ops_search_path.e
+drop cascades to table graphid_ops_search_path.query_time_v
+drop cascades to table graphid_ops_search_path.query_time_e
+NOTICE: graph "graphid_ops_search_path" has been dropped
+ drop_graph
+------------
+
+(1 row)
+
+SET search_path TO ag_catalog;
diff --git a/regress/sql/catalog.sql b/regress/sql/catalog.sql
index bb72c349..87a8bf76 100644
--- a/regress/sql/catalog.sql
+++ b/regress/sql/catalog.sql
@@ -235,3 +235,21 @@ SELECT count(*) FROM ag_label;
-- dropping the graphs
SELECT drop_graph('issue_2245', true);
SELECT drop_graph('graph', true);
+
+--
+-- create_label() must not resolve graphid_ops through the search_path
+--
+-- Every AGE object is referenced with an ag_catalog qualified name here, so
+-- these statements have to work with ag_catalog off the search_path.
+--
+SET search_path TO public;
+SELECT ag_catalog.create_graph('graphid_ops_search_path');
+-- vertex labels index id, edge labels index start_id and end_id
+SELECT ag_catalog.create_vlabel('graphid_ops_search_path', 'v');
+SELECT ag_catalog.create_elabel('graphid_ops_search_path', 'e');
+-- label creation at query time goes through the same path
+SELECT * FROM ag_catalog.cypher('graphid_ops_search_path',
+ $$CREATE (:query_time_v)-[:query_time_e]->(:query_time_v)$$)
+ AS (result ag_catalog.agtype);
+SELECT ag_catalog.drop_graph('graphid_ops_search_path', true);
+SET search_path TO ag_catalog;
diff --git a/src/backend/commands/label_commands.c
b/src/backend/commands/label_commands.c
index bc8d63da..1560ae10 100644
--- a/src/backend/commands/label_commands.c
+++ b/src/backend/commands/label_commands.c
@@ -509,7 +509,8 @@ static void create_index_on_column(char *schema_name,
index_col->expr = NULL;
index_col->indexcolname = NULL;
index_col->collation = NIL;
- index_col->opclass = list_make1(makeString("graphid_ops"));
+ index_col->opclass = list_make2(makeString("ag_catalog"),
+ makeString("graphid_ops"));
index_col->opclassopts = NIL;
index_col->ordering = SORTBY_DEFAULT;
index_col->nulls_ordering = SORTBY_NULLS_DEFAULT;