From 1b811ab168cf6060985520724915141dbad80b75 Mon Sep 17 00:00:00 2001
From: Ayush Tiwari <ayushtiwari.slg01@gmail.com>
Date: Fri, 15 May 2026 10:51:39 +0000
Subject: [PATCH v2] 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 regression tests using the existing myshop property graph and
customers_us view.  The tests check that DROP LABEL and DROP PROPERTIES
are rejected with the standard dependency error while the view depends
on the referenced label/property.

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 | 15 +++++++++++++++
 src/test/regress/sql/graph_table.sql      | 10 ++++++++++
 3 files changed, 44 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..2b65530bf7f 100644
--- a/src/test/regress/expected/graph_table.out
+++ b/src/test/regress/expected/graph_table.out
@@ -942,6 +942,21 @@ 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.
+ALTER PROPERTY GRAPH myshop ALTER EDGE TABLE order_items DROP LABEL list_items;
+ALTER PROPERTY GRAPH myshop ALTER EDGE TABLE wishlist_items
+    DROP LABEL list_items;  -- error
+ERROR:  cannot drop label list_items of property graph myshop because other objects depend on it
+DETAIL:  view customers_us depends on label list_items of property graph myshop
+HINT:  Use DROP ... CASCADE to drop the dependent objects too.
+ALTER PROPERTY GRAPH myshop ALTER EDGE TABLE order_items
+    ADD LABEL list_items PROPERTIES (order_id AS link_id, product_no);
+ALTER PROPERTY GRAPH myshop ALTER VERTEX TABLE customers
+    ALTER LABEL customers DROP PROPERTIES (address);  -- error
+ERROR:  cannot drop property address of property graph myshop because other objects depend on it
+DETAIL:  view customers_us depends on property address of property graph myshop
+HINT:  Use DROP ... CASCADE to drop the dependent objects too.
 -- 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..1a1a9fc0e14 100644
--- a/src/test/regress/sql/graph_table.sql
+++ b/src/test/regress/sql/graph_table.sql
@@ -536,6 +536,16 @@ 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.
+ALTER PROPERTY GRAPH myshop ALTER EDGE TABLE order_items DROP LABEL list_items;
+ALTER PROPERTY GRAPH myshop ALTER EDGE TABLE wishlist_items
+    DROP LABEL list_items;  -- error
+ALTER PROPERTY GRAPH myshop ALTER EDGE TABLE order_items
+    ADD LABEL list_items PROPERTIES (order_id AS link_id, product_no);
+ALTER PROPERTY GRAPH myshop ALTER VERTEX TABLE customers
+    ALTER LABEL customers DROP PROPERTIES (address);  -- error
+
 -- test view/graph nesting
 
 CREATE VIEW customers_view AS SELECT customer_id, 'redacted' || customer_id AS name_redacted, address FROM customers;
-- 
2.43.0

