From 1b811ab168cf6060985520724915141dbad80b75 Mon Sep 17 00:00:00 2001 From: Ayush Tiwari 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 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