]> git.ipfire.org Git - thirdparty/postgresql.git/commitdiff
Record dependencies on graph labels and properties
authorPeter Eisentraut <peter@eisentraut.org>
Tue, 9 Jun 2026 10:55:47 +0000 (12:55 +0200)
committerPeter Eisentraut <peter@eisentraut.org>
Tue, 9 Jun 2026 10:55:47 +0000 (12:55 +0200)
A view definition with GRAPH_TABLE depends upon the property graph it
references as well as the properties and labels referenced in it.  We
recorded the dependency on the property graph, but did not record
dependency on labels and properties.  This allowed properties or
labels referenced by a view to be dropped, resulting in a cache lookup
error when such a view was accessed.  Fix this bug by handling
GraphPropertyRef and GraphLabelRef in find_expr_references_walker().
The dependency on the data type of property does not need to be
recorded separately as it is recorded indirectly via a dependency on
the property graph property itself.

Note that a property or a label associated with individual elements
can still be dropped as long as there are other elements that are
associated with that property or label, since they do not lead to
dropping the property or the label from the property graph altogether.

Reported-by: Man Zeng <zengman@halodbtech.com>
Author: Ayush Tiwari <ayushtiwari.slg01@gmail.com>
Author: Ashutosh Bapat <ashutosh.bapat.oss@gmail.com>
Reviewed-by: Junwang Zhao <zhjwpku@gmail.com>
Discussion: https://www.postgresql.org/message-id/flat/tencent_43D9888041FA4FDE498C7BF1%40qq.com

src/backend/catalog/dependency.c
src/include/catalog/catversion.h
src/test/regress/expected/graph_table.out
src/test/regress/sql/graph_table.sql

index fdb8e67e1f5e650b8687b166f030e93064c90875..c54774b327590e2b3b05aa32c7b88a3439ade216 100644 (file)
@@ -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 depends on the property graph label */
+               add_object_address(PropgraphLabelRelationId, glr->labelid, 0,
+                                                  context->addrs);
+       }
+       else if (IsA(node, GraphPropertyRef))
+       {
+               GraphPropertyRef *gpr = (GraphPropertyRef *) node;
+
+               /*
+                * GRAPH_TABLE property reference depends on the property graph
+                * property
+                */
+               add_object_address(PropgraphPropertyRelationId, gpr->propid, 0,
+                                                  context->addrs);
+       }
        else if (IsA(node, RowCompareExpr))
        {
                RowCompareExpr *rcexpr = (RowCompareExpr *) node;
index 87007e725c16107bb3146eedf7a09d83dff913b1..c4e94a3a09e14d837d78c8428d25cefa64d465fb 100644 (file)
@@ -57,6 +57,6 @@
  */
 
 /*                                                     yyyymmddN */
-#define CATALOG_VERSION_NO     202606051
+#define CATALOG_VERSION_NO     202606091
 
 #endif
index 27b721d4480cbe060e1ab151cf8a1f6596fa0ea4..70d986e8ab0d59c250fffbc8649eb898fa4fe93f 100644 (file)
@@ -934,7 +934,7 @@ SELECT * FROM GRAPH_TABLE (g4 MATCH (s WHERE s.id = 3)-[e]-(d) COLUMNS (s.val, e
   30 | 300 |  10
 (2 rows)
 
--- ruleutils reverse parsing
+-- GRAPH_TABLE in views
 -- The query in the view definition is intentionally complex to test one view with many
 -- features like label disjunction, lateral references, WHERE clauses in graph
 -- patterns.
@@ -943,16 +943,35 @@ SELECT g.* FROM x1,
                 GRAPH_TABLE (myshop MATCH (c IS customers WHERE c.address = 'US' AND c.customer_id = x1.a)
                                           -[IS customer_orders | customer_wishlists ]->
                                           (l IS orders | wishlists)-[ IS list_items]->(p IS products)
-                                    COLUMNS (c.name AS customer_name, p.name AS product_name, x1.a AS a)) g
+                                    COLUMNS (c.name AS customer_name, p.name AS product_name, p.price, x1.a AS a)) g
            ORDER BY customer_name, product_name;
+-- Dropping properties or labels used by a view is not allowed
+-- If these DDLs succeed, the pg_get_viewdef call below will throw cache lookup
+-- error.
+ALTER PROPERTY GRAPH myshop ALTER VERTEX TABLE orders DROP LABEL orders; -- error
+ERROR:  cannot drop label orders of property graph myshop because other objects depend on it
+DETAIL:  view customers_us depends on label orders of property graph myshop
+HINT:  Use DROP ... CASCADE to drop the dependent objects too.
+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.
+ALTER PROPERTY GRAPH myshop ALTER VERTEX TABLE products
+    ALTER LABEL products DROP PROPERTIES (price);  -- error
+ERROR:  cannot drop property price of property graph myshop because other objects depend on it
+DETAIL:  view customers_us depends on property price of property graph myshop
+HINT:  Use DROP ... CASCADE to drop the dependent objects too.
+-- ruleutils reverse parsing
 SELECT pg_get_viewdef('customers_us'::regclass);
-                                                                                                                                        pg_get_viewdef                                                                                                                                        
-----------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------
-  SELECT g.customer_name,                                                                                                                                                                                                                                                                    +
-     g.product_name,                                                                                                                                                                                                                                                                         +
-     g.a                                                                                                                                                                                                                                                                                     +
-    FROM x1,                                                                                                                                                                                                                                                                                 +
-     GRAPH_TABLE (myshop MATCH (c IS customers WHERE (((c.address)::text = 'US'::text) AND (c.customer_id = x1.a)))-[IS customer_orders|customer_wishlists]->(l IS orders|wishlists)-[IS list_items]->(p IS products) COLUMNS (c.name AS customer_name, p.name AS product_name, x1.a AS a)) g+
+                                                                                                                                                 pg_get_viewdef                                                                                                                                                 
+----------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------
+  SELECT g.customer_name,                                                                                                                                                                                                                                                                                      +
+     g.product_name,                                                                                                                                                                                                                                                                                           +
+     g.price,                                                                                                                                                                                                                                                                                                  +
+     g.a                                                                                                                                                                                                                                                                                                       +
+    FROM x1,                                                                                                                                                                                                                                                                                                   +
+     GRAPH_TABLE (myshop MATCH (c IS customers WHERE (((c.address)::text = 'US'::text) AND (c.customer_id = x1.a)))-[IS customer_orders|customer_wishlists]->(l IS orders|wishlists)-[IS list_items]->(p IS products) COLUMNS (c.name AS customer_name, p.name AS product_name, p.price AS price, x1.a AS a)) g+
    ORDER BY g.customer_name, g.product_name;
 (1 row)
 
index d7608100c95fb08219f5e62a1cd47dfa3fe68916..0b44f70d7e7af8ba81b96bc9c1d2b60fc6e63ecc 100644 (file)
@@ -529,7 +529,8 @@ SELECT * FROM GRAPH_TABLE (g4 MATCH (s IS ptnv)-[e IS ptne]->(d IS ptnv) COLUMNS
 SELECT * FROM GRAPH_TABLE (g4 MATCH (s)-[e]-(d) WHERE s.id = 3 COLUMNS (s.val, e.val, d.val)) ORDER BY 1, 2, 3;
 SELECT * FROM GRAPH_TABLE (g4 MATCH (s WHERE s.id = 3)-[e]-(d) COLUMNS (s.val, e.val, d.val)) ORDER BY 1, 2, 3;
 
--- ruleutils reverse parsing
+-- GRAPH_TABLE in views
+
 -- The query in the view definition is intentionally complex to test one view with many
 -- features like label disjunction, lateral references, WHERE clauses in graph
 -- patterns.
@@ -538,8 +539,17 @@ SELECT g.* FROM x1,
                 GRAPH_TABLE (myshop MATCH (c IS customers WHERE c.address = 'US' AND c.customer_id = x1.a)
                                           -[IS customer_orders | customer_wishlists ]->
                                           (l IS orders | wishlists)-[ IS list_items]->(p IS products)
-                                    COLUMNS (c.name AS customer_name, p.name AS product_name, x1.a AS a)) g
+                                    COLUMNS (c.name AS customer_name, p.name AS product_name, p.price, x1.a AS a)) g
            ORDER BY customer_name, product_name;
+-- Dropping properties or labels used by a view is not allowed
+-- If these DDLs succeed, the pg_get_viewdef call below will throw cache lookup
+-- error.
+ALTER PROPERTY GRAPH myshop ALTER VERTEX TABLE orders DROP LABEL orders; -- error
+ALTER PROPERTY GRAPH myshop ALTER VERTEX TABLE customers
+    ALTER LABEL customers DROP PROPERTIES (address);  -- error
+ALTER PROPERTY GRAPH myshop ALTER VERTEX TABLE products
+    ALTER LABEL products DROP PROPERTIES (price);  -- error
+-- ruleutils reverse parsing
 SELECT pg_get_viewdef('customers_us'::regclass);
 
 -- test view/graph nesting