public inbox for [email protected]  
help / color / mirror / Atom feed
From: SATYANARAYANA NARLAPURAM <[email protected]>
To: PostgreSQL Hackers <[email protected]>
To: Ashutosh Bapat <[email protected]>
Subject: [Bug][patch]: After dropping the last label from a property graph element, invoking pg_get_propgraphdef() triggers an assertion failure
Date: Mon, 20 Apr 2026 11:12:44 -0700
Message-ID: <CAHg+QDeP=mTHTV48R23zKMy1SBmCKZ_L7-z5zKnYyw+K0x-gCg@mail.gmail.com> (raw)

Hi hackers,

ALTER PROPERTY GRAPH ... ALTER ... DROP LABEL currently allows removing
the last label from an element, leaving it with zero labels.

On assert-enabled builds, pg_get_propgraphdef() hits
TRAP: failed Assert("count > 0"), File: "ruleutils.c", Line: 1837, PID:
1821840

Repro:

CREATE TABLE t (x int PRIMARY KEY, y int, z int);
CREATE PROPERTY GRAPH g VERTEX TABLES (t KEY (x) LABEL l1 LABEL l2);
ALTER PROPERTY GRAPH g ALTER VERTEX TABLE t DROP LABEL l2;
ALTER PROPERTY GRAPH g ALTER VERTEX TABLE t DROP LABEL l1;
SELECT pg_get_propgraphdef('g'::regclass);

We can fix it two ways, (1) Prevent dropping the last label; (2) handle
zero labels.
I feel it is easier to prevent dropping the last label than handling zero
labels. Thoughts?

The attached patch adds a check in AlterPropGraph() before
performDeletion(). It scans pg_propgraph_element_label to count labels
for the element, and raises an error if only one remains. A regression test
is included
that drops labels down to the last one, verifies the error, then re-adds
them back.

Thanks,
Satya


Attachments:

  [application/octet-stream] 0001-Prevent-dropping-the-last-label-from-a-property-grap.patch (4.3K, 3-0001-Prevent-dropping-the-last-label-from-a-property-grap.patch)
  download | inline diff:
From 8e3373ec7682b881c5b12c0ebf6f68ba860ebb45 Mon Sep 17 00:00:00 2001
From: satyanarayana narlapuram <[email protected]>
Date: Mon, 20 Apr 2026 18:07:40 +0000
Subject: [PATCH] Prevent dropping the last label from a property graph element

ALTER PROPERTY GRAPH ... DROP LABEL allowed removing the last label
from an element, leaving it with zero labels. This causes 
pg_get_propgraphdef() to crash.

Add a check in AlterPropGraph() that counts the element's labels
before deletion and errors out if only one remains.

Reported-by: Satyanarayana Narlapuram <[email protected]>
---
 src/backend/commands/propgraphcmds.c          | 30 +++++++++++++++++++
 .../expected/create_property_graph.out        |  6 ++++
 .../regress/sql/create_property_graph.sql     |  4 +++
 3 files changed, 40 insertions(+)

diff --git a/src/backend/commands/propgraphcmds.c b/src/backend/commands/propgraphcmds.c
index 45d2ff1b..16ef611b 100644
--- a/src/backend/commands/propgraphcmds.c
+++ b/src/backend/commands/propgraphcmds.c
@@ -1522,6 +1522,36 @@ 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.
+		 */
+		{
+			Relation	elrel;
+			SysScanDesc elscan;
+			ScanKeyData elkey[1];
+			int			nlabels = 0;
+
+			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++;
+			systable_endscan(elscan);
+			table_close(elrel, AccessShareLock);
+
+			if (nlabels <= 1)
+				ereport(ERROR,
+						(errcode(ERRCODE_INVALID_OBJECT_DEFINITION),
+						 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 bc9a596e..740f886c 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 241f93df..4cf77159 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.43.0



view thread (13+ messages)  latest in thread

reply

Reply instructions:

You may reply publicly to this message via plain-text email
using any one of the following methods:

* Reply to all the recipients using the --to and --cc options:
  reply via email

  To: [email protected]
  Cc: [email protected], [email protected], [email protected]
  Subject: Re: [Bug][patch]: After dropping the last label from a property graph element, invoking pg_get_propgraphdef() triggers an assertion failure
  In-Reply-To: <CAHg+QDeP=mTHTV48R23zKMy1SBmCKZ_L7-z5zKnYyw+K0x-gCg@mail.gmail.com>

* Save the following mbox file, import it into your mail client,
  and reply-to-all from there: mbox

This inbox is served by agora; see mirroring instructions
for how to clone and mirror all data and code used for this inbox