v20260421-0001-Prevent-dropping-the-last-label-from-a-pro.patch
text/x-patch
Filename: v20260421-0001-Prevent-dropping-the-last-label-from-a-pro.patch
Type: text/x-patch
Part: 0
Patch
Same data as JSON:
GET /api/v1/attachments/:id/patch
the parsed metadata as JSON — format, series position, per-file stats; never the diff bytes.
API reference →
Format: format-patch
Series: patch v20260421-0001
Subject: Prevent dropping the last label from a property graph element
| File | + | − |
|---|---|---|
| doc/src/sgml/ref/alter_property_graph.sgml | 3 | 1 |
| src/backend/commands/propgraphcmds.c | 32 | 0 |
| src/test/regress/expected/create_property_graph.out | 6 | 0 |
| src/test/regress/sql/create_property_graph.sql | 4 | 0 |
From 973b724463c0e0755fd59260bd8b5f0f928f524e Mon Sep 17 00:00:00 2001
From: satyanarayana narlapuram <satyanarlapuram@gmail.com>
Date: Tue, 21 Apr 2026 07:52:56 +0000
Subject: [PATCH v20260421 5/5] Prevent dropping the last label from a property
graph element
Per SQL/PGQ standard, every graph element must have at least one label. When
dropping a label from a graph element, ensure that there exists at least one
other label on the element. If the label being dropped is the only label on the
element, raise an error.
Reported By: Satyanarayana Narlapuram <satyanarlapuram@gmail.com>
Author: Satyanarayana Narlapuram <satyanarlapuram@gmail.com>
Reviewed By: Ashutosh Bapat <ashutosh.bapat.oss@gmail.com>
---
doc/src/sgml/ref/alter_property_graph.sgml | 4 ++-
src/backend/commands/propgraphcmds.c | 32 +++++++++++++++++++
.../expected/create_property_graph.out | 6 ++++
.../regress/sql/create_property_graph.sql | 4 +++
4 files changed, 45 insertions(+), 1 deletion(-)
diff --git a/doc/src/sgml/ref/alter_property_graph.sgml b/doc/src/sgml/ref/alter_property_graph.sgml
index f517f2b2d7a..2fd0c138e12 100644
--- a/doc/src/sgml/ref/alter_property_graph.sgml
+++ b/doc/src/sgml/ref/alter_property_graph.sgml
@@ -99,7 +99,9 @@ ALTER PROPERTY GRAPH [ IF EXISTS ] <replaceable class="parameter">name</replacea
<term><literal>ALTER {VERTEX|NODE|EDGE|RELATIONSHIP} TABLE ... DROP LABEL</literal></term>
<listitem>
<para>
- This form removes a label from an existing vertex or edge table.
+ This form removes a label from an existing vertex or edge table. The
+ last label on an element table cannot be dropped; every vertex or edge
+ table must have at least one label.
</para>
</listitem>
</varlistentry>
diff --git a/src/backend/commands/propgraphcmds.c b/src/backend/commands/propgraphcmds.c
index 3842f4a711b..583bd43cd7b 100644
--- a/src/backend/commands/propgraphcmds.c
+++ b/src/backend/commands/propgraphcmds.c
@@ -1493,6 +1493,11 @@ AlterPropGraph(ParseState *pstate, const AlterPropGraphStmt *stmt)
Oid labeloid;
Oid ellabeloid;
ObjectAddress obj;
+ Relation elrel;
+ SysScanDesc elscan;
+ ScanKeyData elkey[1];
+ int nlabels = 0;
+
if (stmt->element_kind == PROPGRAPH_ELEMENT_KIND_VERTEX)
peoid = get_vertex_oid(pstate, pgrelid, stmt->element_alias, -1);
@@ -1522,6 +1527,33 @@ AlterPropGraph(ParseState *pstate, const AlterPropGraphStmt *stmt)
get_rel_name(pgrelid), stmt->element_alias, stmt->drop_label),
parser_errposition(pstate, -1));
+ /*
+ * Prevent dropping the last label from an element. Every element must
+ * have at least one label.
+ */
+ elrel = table_open(PropgraphElementLabelRelationId, AccessShareLock);
+ ScanKeyInit(&elkey[0],
+ Anum_pg_propgraph_element_label_pgelelid,
+ BTEqualStrategyNumber, F_OIDEQ,
+ ObjectIdGetDatum(peoid));
+ elscan = systable_beginscan(elrel, PropgraphElementLabelElementLabelIndexId,
+ true, NULL, 1, elkey);
+ while (HeapTupleIsValid(systable_getnext(elscan)))
+ {
+ nlabels++;
+ if (nlabels > 1)
+ break;
+ }
+ systable_endscan(elscan);
+ table_close(elrel, AccessShareLock);
+
+ if (nlabels <= 1)
+ ereport(ERROR,
+ (errcode(ERRCODE_OBJECT_NOT_IN_PREREQUISITE_STATE),
+ errmsg("cannot drop the last label from element \"%s\"",
+ stmt->element_alias),
+ errhint("Every element must have at least one label.")));
+
ObjectAddressSet(obj, PropgraphElementLabelRelationId, ellabeloid);
performDeletion(&obj, stmt->drop_behavior, 0);
diff --git a/src/test/regress/expected/create_property_graph.out b/src/test/regress/expected/create_property_graph.out
index bc9a596ec89..740f886cd83 100644
--- a/src/test/regress/expected/create_property_graph.out
+++ b/src/test/regress/expected/create_property_graph.out
@@ -57,6 +57,12 @@ ALTER PROPERTY GRAPH g3
ALTER PROPERTY GRAPH g3 ALTER VERTEX TABLE t3 DROP LABEL t3l3x; -- error
ERROR: property graph "g3" element "t3" has no label "t3l3x"
ALTER PROPERTY GRAPH g3 ALTER VERTEX TABLE t3 DROP LABEL t3l3;
+-- Test that the last label on an element cannot be dropped
+ALTER PROPERTY GRAPH g3 ALTER VERTEX TABLE t3 DROP LABEL t3l2;
+ALTER PROPERTY GRAPH g3 ALTER VERTEX TABLE t3 DROP LABEL t3l1; -- error: last label
+ERROR: cannot drop the last label from element "t3"
+HINT: Every element must have at least one label.
+ALTER PROPERTY GRAPH g3 ALTER VERTEX TABLE t3 ADD LABEL t3l2 PROPERTIES ALL COLUMNS;
ALTER PROPERTY GRAPH g3 DROP VERTEX TABLES (t2); -- fail
ERROR: cannot drop vertex t2 of property graph g3 because other objects depend on it
DETAIL: edge e1 of property graph g3 depends on vertex t2 of property graph g3
diff --git a/src/test/regress/sql/create_property_graph.sql b/src/test/regress/sql/create_property_graph.sql
index 241f93df302..4cf771596a8 100644
--- a/src/test/regress/sql/create_property_graph.sql
+++ b/src/test/regress/sql/create_property_graph.sql
@@ -52,6 +52,10 @@ ALTER PROPERTY GRAPH g3
ADD LABEL t3l3 PROPERTIES ALL COLUMNS;
ALTER PROPERTY GRAPH g3 ALTER VERTEX TABLE t3 DROP LABEL t3l3x; -- error
ALTER PROPERTY GRAPH g3 ALTER VERTEX TABLE t3 DROP LABEL t3l3;
+-- Test that the last label on an element cannot be dropped
+ALTER PROPERTY GRAPH g3 ALTER VERTEX TABLE t3 DROP LABEL t3l2;
+ALTER PROPERTY GRAPH g3 ALTER VERTEX TABLE t3 DROP LABEL t3l1; -- error: last label
+ALTER PROPERTY GRAPH g3 ALTER VERTEX TABLE t3 ADD LABEL t3l2 PROPERTIES ALL COLUMNS;
ALTER PROPERTY GRAPH g3 DROP VERTEX TABLES (t2); -- fail
ALTER PROPERTY GRAPH g3 DROP VERTEX TABLES (t2) CASCADE;
ALTER PROPERTY GRAPH g3 DROP EDGE TABLES (e2);
--
2.34.1