v1-0001-SQL-PGQ-Record-dependencies-on-graph-labels-and-p.patch

application/octet-stream

Filename: v1-0001-SQL-PGQ-Record-dependencies-on-graph-labels-and-p.patch
Type: application/octet-stream
Part: 0
Message: Re: (SQL/PGQ) cache lookup failed for label
From b3388d6aaa75c6a8e516af8a120f3479f18a4724 Mon Sep 17 00:00:00 2001
From: Ayush Tiwari <ayushtiwari.slg01@gmail.com>
Date: Fri, 15 May 2026 09:55:59 +0000
Subject: [PATCH v1] SQL/PGQ: Record dependencies on graph labels and
 properties

When a view or rule references a property graph via a GRAPH_TABLE
clause, the parsetree stored in pg_rewrite contains GraphLabelRef and
GraphPropertyRef nodes that point at pg_propgraph_label and
pg_propgraph_property entries.  find_expr_references_walker() did not
have cases for these nodes, so only the property graph relation itself
acquired a pg_depend entry.  Labels and properties used by the stored
query could then be dropped via ALTER PROPERTY GRAPH ... DROP LABEL /
DROP PROPERTIES, leaving the view to fail later at execution with
"cache lookup failed for label NNN".

Add cases for the two graph-table node types so that each referenced
label and property gets a normal dependency on the view.  No new
traversal is needed: query_tree_walker() already descends into
rte->graph_pattern and rte->graph_table_columns, and through them into
GraphElementPattern->labelexpr and the GraphPropertyRef expressions in
the COLUMNS list.

Add a regression test in graph_table that creates a view referencing a
multi-label vertex and then exercises DROP LABEL and DROP PROPERTIES.
Both commands are now rejected with the standard dependency error, and
succeed once the view is dropped.

Reported-by: Man Zeng <zengman@halodbtech.com>
Discussion: https://postgr.es/m/tencent_43D9888041FA4FDE498C7BF1@qq.com
---
 src/backend/catalog/dependency.c          | 19 +++++++++++++++
 src/test/regress/expected/graph_table.out | 29 +++++++++++++++++++++++
 src/test/regress/sql/graph_table.sql      | 24 +++++++++++++++++++
 3 files changed, 72 insertions(+)

diff --git a/src/backend/catalog/dependency.c b/src/backend/catalog/dependency.c
index fdb8e67e1f5..dc570e907f6 100644
--- a/src/backend/catalog/dependency.c
+++ b/src/backend/catalog/dependency.c
@@ -2165,6 +2165,25 @@ find_expr_references_walker(Node *node,
 		add_object_address(TypeRelationId, rowexpr->row_typeid, 0,
 						   context->addrs);
 	}
+	else if (IsA(node, GraphLabelRef))
+	{
+		GraphLabelRef *glr = (GraphLabelRef *) node;
+
+		/*
+		 * GRAPH_TABLE label reference: depend on the label catalog entry.
+		 * No expression substructure to recurse into.
+		 */
+		add_object_address(PropgraphLabelRelationId, glr->labelid, 0,
+						   context->addrs);
+	}
+	else if (IsA(node, GraphPropertyRef))
+	{
+		GraphPropertyRef *gpr = (GraphPropertyRef *) node;
+
+		/* GRAPH_TABLE property reference: depend on the property entry. */
+		add_object_address(PropgraphPropertyRelationId, gpr->propid, 0,
+						   context->addrs);
+	}
 	else if (IsA(node, RowCompareExpr))
 	{
 		RowCompareExpr *rcexpr = (RowCompareExpr *) node;
diff --git a/src/test/regress/expected/graph_table.out b/src/test/regress/expected/graph_table.out
index cc6d80afd82..3346fd6e0e9 100644
--- a/src/test/regress/expected/graph_table.out
+++ b/src/test/regress/expected/graph_table.out
@@ -942,6 +942,35 @@ SELECT pg_get_viewdef('customers_us'::regclass);
    ORDER BY g.customer_name, g.product_name;
 (1 row)
 
+-- A view defined over GRAPH_TABLE should record dependencies on the labels
+-- and properties it references, so they cannot be dropped from under it.
+CREATE TABLE depv (id int PRIMARY KEY, name text, addr text);
+CREATE TABLE depe (id int PRIMARY KEY,
+                   src int REFERENCES depv(id),
+                   dst int REFERENCES depv(id));
+CREATE PROPERTY GRAPH depg
+    VERTEX TABLES (depv LABEL l1 PROPERTIES (name)
+                        LABEL l2 PROPERTIES (name, addr))
+    EDGE TABLES (depe
+                     SOURCE KEY (src) REFERENCES depv (id)
+                     DESTINATION KEY (dst) REFERENCES depv (id));
+CREATE VIEW depv_view AS
+    SELECT * FROM GRAPH_TABLE (depg MATCH (a IS l2)-[e IS depe]->(b IS l2)
+                                    COLUMNS (a.name, a.addr, b.name AS bname));
+ALTER PROPERTY GRAPH depg ALTER VERTEX TABLE depv DROP LABEL l2;  -- error
+ERROR:  cannot drop label l2 of property graph depg because other objects depend on it
+DETAIL:  view depv_view depends on label l2 of property graph depg
+HINT:  Use DROP ... CASCADE to drop the dependent objects too.
+ALTER PROPERTY GRAPH depg
+    ALTER VERTEX TABLE depv ALTER LABEL l2
+    DROP PROPERTIES (addr);  -- error
+ERROR:  cannot drop property addr of property graph depg because other objects depend on it
+DETAIL:  view depv_view depends on property addr of property graph depg
+HINT:  Use DROP ... CASCADE to drop the dependent objects too.
+DROP VIEW depv_view;
+ALTER PROPERTY GRAPH depg ALTER VERTEX TABLE depv DROP LABEL l2;
+DROP PROPERTY GRAPH depg;
+DROP TABLE depe, depv;
 -- test view/graph nesting
 CREATE VIEW customers_view AS SELECT customer_id, 'redacted' || customer_id AS name_redacted, address FROM customers;
 SELECT * FROM customers;
diff --git a/src/test/regress/sql/graph_table.sql b/src/test/regress/sql/graph_table.sql
index 0e381ec72bc..61ee148a879 100644
--- a/src/test/regress/sql/graph_table.sql
+++ b/src/test/regress/sql/graph_table.sql
@@ -536,6 +536,30 @@ SELECT g.* FROM x1,
            ORDER BY customer_name, product_name;
 SELECT pg_get_viewdef('customers_us'::regclass);
 
+-- A view defined over GRAPH_TABLE should record dependencies on the labels
+-- and properties it references, so they cannot be dropped from under it.
+CREATE TABLE depv (id int PRIMARY KEY, name text, addr text);
+CREATE TABLE depe (id int PRIMARY KEY,
+                   src int REFERENCES depv(id),
+                   dst int REFERENCES depv(id));
+CREATE PROPERTY GRAPH depg
+    VERTEX TABLES (depv LABEL l1 PROPERTIES (name)
+                        LABEL l2 PROPERTIES (name, addr))
+    EDGE TABLES (depe
+                     SOURCE KEY (src) REFERENCES depv (id)
+                     DESTINATION KEY (dst) REFERENCES depv (id));
+CREATE VIEW depv_view AS
+    SELECT * FROM GRAPH_TABLE (depg MATCH (a IS l2)-[e IS depe]->(b IS l2)
+                                    COLUMNS (a.name, a.addr, b.name AS bname));
+ALTER PROPERTY GRAPH depg ALTER VERTEX TABLE depv DROP LABEL l2;  -- error
+ALTER PROPERTY GRAPH depg
+    ALTER VERTEX TABLE depv ALTER LABEL l2
+    DROP PROPERTIES (addr);  -- error
+DROP VIEW depv_view;
+ALTER PROPERTY GRAPH depg ALTER VERTEX TABLE depv DROP LABEL l2;
+DROP PROPERTY GRAPH depg;
+DROP TABLE depe, depv;
+
 -- test view/graph nesting
 
 CREATE VIEW customers_view AS SELECT customer_id, 'redacted' || customer_id AS name_redacted, address FROM customers;
-- 
2.43.0