Received: from malur.postgresql.org ([217.196.149.56]) by arkaria.postgresql.org with esmtps (TLS1.3) tls TLS_ECDHE_RSA_WITH_AES_256_GCM_SHA384 (Exim 4.96) (envelope-from ) id 1wFaIX-005KRy-1F for pgsql-hackers@arkaria.postgresql.org; Wed, 22 Apr 2026 16:19:33 +0000 Received: from localhost ([127.0.0.1] helo=malur.postgresql.org) by malur.postgresql.org with esmtp (Exim 4.96) (envelope-from ) id 1wFaIW-00ENaS-1I for pgsql-hackers@arkaria.postgresql.org; Wed, 22 Apr 2026 16:19:32 +0000 Received: from makus.postgresql.org ([2001:4800:3e1:1::229]) by malur.postgresql.org with esmtps (TLS1.3) tls TLS_ECDHE_RSA_WITH_AES_256_GCM_SHA384 (Exim 4.96) (envelope-from ) id 1wFaIV-00ENaC-39 for pgsql-hackers@lists.postgresql.org; Wed, 22 Apr 2026 16:19:32 +0000 Received: from mail-wm1-x32f.google.com ([2a00:1450:4864:20::32f]) by makus.postgresql.org with esmtps (TLS1.3) tls TLS_ECDHE_RSA_WITH_AES_128_GCM_SHA256 (Exim 4.98.2) (envelope-from ) id 1wFaIT-00000002HEs-2I6b for pgsql-hackers@lists.postgresql.org; Wed, 22 Apr 2026 16:19:31 +0000 Received: by mail-wm1-x32f.google.com with SMTP id 5b1f17b1804b1-4891f625344so40545665e9.0 for ; Wed, 22 Apr 2026 09:19:29 -0700 (PDT) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=gmail.com; s=20251104; t=1776874768; x=1777479568; darn=lists.postgresql.org; h=content-disposition:mime-version:message-id:subject:cc:to:from:date :from:to:cc:subject:date:message-id:reply-to; bh=o3oE4QKcEu9oJ6P5q4gRWDuFrHXlyoQUpEKpi+O8QiY=; b=FyV9d2aE13Y4gWufrOkgEWZEbttxuov1d+TGWMCOp5YHW6SeQvZ+JmFhfRQIFlIaSy QhTeJiLjDiZHxi3b0EP9XNgZRYryIRww7sHKPGs6SokyKaDhcAZtFAe0wrX56CXc+ka/ fRRa92KykZOM2MMCm89AtbAe5Nuzy2Eu+l7zLnYt4dPptS8I1yERDaCP+tXo4Dse+/7d swHb9xU6AvkXUHdG2Js8s9Vciz7plC3amfN2pnUPr0xbVNMyB/iSeThylh/FgTPQb2PG 7zQCxpO1lluAbNiFMWhjwPiVE5QERbYvm1ZhrN8W4od10bhUOALnVxQNCiIdRAhfyhUf W0Fw== X-Google-DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=1e100.net; s=20251104; t=1776874768; x=1777479568; h=content-disposition:mime-version:message-id:subject:cc:to:from:date :x-gm-gg:x-gm-message-state:from:to:cc:subject:date:message-id :reply-to; bh=o3oE4QKcEu9oJ6P5q4gRWDuFrHXlyoQUpEKpi+O8QiY=; b=nbFqoD7Ks6SDQ6D/9+udO8J78LW30LIPqR7lr9/f7ilmpmUxxed7veL1phlkWTsTO+ r4Pfu73L6lldh9VzAW/Vq73QFq1ursArlntOmY29xBF3AqurnYPbuWsVnoQhqEhkoFcv Ja7yuO9OXnIb0kjKP+agOv30L8AOYyILtQ7rPtIXi1ePoI1VBHP5eeUJB9XcehVNWden D/qI24q6EzeIun9zPd8XCGzlRE9T5+oSsJ4gbHRtfJjlXSfETA6JM/ucxgouyNUF+EF/ zWTpJEQriizpH4hfW9mySJz7rBT0XyeYKIejbXkRQhUzLh3NGBZ1vTdTcwwVbiRt5o9A XDOQ== X-Gm-Message-State: AOJu0YytkwCk28gp3TAdFqTlQl434wpxCA2Bb9uY/vH5fjKOYFlF9JGL mF2x0kbz8CiTQNVW+nwIJjKNHC+uQeOdFpvsOcieDHeTAK6aQVT4SZ8oKjm0EQ== X-Gm-Gg: AeBDietBIVof5k6ZOGq9CTgquK1tHZUnGO7OIXzC/tSEyILZwpQqAGuPp9o7wfxjBnd CUNOjv7yn5dEDRzVlC6XEVdNX6XSKM+ZB3eqP/Zvps0WqzjzdaOltZQjYP1r8GyBB8Gggt3ud0S uYSxXeUXUvnXGgvtG40QFvt6703whcNRMzkWv5Mz1uhB9SU7DFMerIwSF/s6rYv/3RugivPN9YJ F0auUaKhhanY0BJBmNDIvY6fdnqdqeh+RtgmG4w7BcSygQIHq37yc+vQaon0ihSDFwbdV+xu5K4 62H5OilfnLvKLN6Gx5HXzARU2ppc/zQwtRIO3XMnG8B1WuOntZUUvPOgbDvLaZWb1NehwQvI1W5 mjhqZkdr+qTnx7aPw0wzgbBFvHtOOB2stC3DXllV8pmbtyjZQ88i5KN82PDEr2NZwdXPzsVHOki Jppo0nuC7nLvQZORlWV914KIwmcu/pPbttMeVrW9n9XVr3U8ixJk1/CKferOqMKq3/fJrJY+wvz DgTAmkVAqw1541tJKP64g== X-Received: by 2002:a05:600c:3055:b0:489:32b:ac0b with SMTP id 5b1f17b1804b1-489032bae49mr154648105e9.6.1776874768255; Wed, 22 Apr 2026 09:19:28 -0700 (PDT) Received: from bdtpg (ec2-15-237-197-144.eu-west-3.compute.amazonaws.com. [15.237.197.144]) by smtp.gmail.com with ESMTPSA id 5b1f17b1804b1-48a5a579bd3sm75014605e9.6.2026.04.22.09.19.27 (version=TLS1_3 cipher=TLS_AES_256_GCM_SHA384 bits=256/256); Wed, 22 Apr 2026 09:19:27 -0700 (PDT) Date: Wed, 22 Apr 2026 16:19:26 +0000 From: Bertrand Drouvot To: pgsql-hackers@lists.postgresql.org Cc: Peter Eisentraut , Ashutosh Bapat Subject: Fix DROP PROPERTY GRAPH "unsupported object class" error Message-ID: MIME-Version: 1.0 Content-Type: multipart/mixed; boundary="s/7v445LwpBnK/Gl" Content-Disposition: inline List-Id: List-Help: List-Subscribe: List-Post: List-Owner: List-Archive: Archived-At: Precedence: bulk --s/7v445LwpBnK/Gl Content-Type: text/plain; charset=us-ascii Content-Disposition: inline Hi hackers, While testing the Property Graphs, I observed that DROP PROPERTY GRAPH could generate the "unsupported object class" error. Indeed, getObjectTypeDescription() and getObjectIdentityParts() are missing switch cases for PropgraphElementLabelRelationId and PropgraphLabelPropertyRelationId, causing DROP PROPERTY GRAPH to hit the default case and error out with "unsupported object class". The bug only manifests when an event trigger is active, because that is what calls these functions. The attached adds the missing cases so that DROP PROPERTY GRAPH, DROP PROPERTY GRAPH IF EXISTS, and DROP SCHEMA CASCADE on schemas containing property graphs all work correctly when event triggers are present. It also adds test cases that create an event trigger and then exercise DROP PROPERTY GRAPH and DROP SCHEMA CASCADE with property graphs. I think that's worth an open item and I'll add one for this issue. Regards, -- Bertrand Drouvot PostgreSQL Contributors Team RDS Open Source Databases Amazon Web Services: https://aws.amazon.com --s/7v445LwpBnK/Gl Content-Type: text/x-diff; charset=us-ascii Content-Disposition: attachment; filename="v1-0001-Fix-DROP-PROPERTY-GRAPH-unsupported-object-class-.patch" From bc81c1002bad4b556644152754c03d31a2c89ee7 Mon Sep 17 00:00:00 2001 From: Bertrand Drouvot Date: Wed, 22 Apr 2026 15:01:12 +0000 Subject: [PATCH v1] Fix DROP PROPERTY GRAPH "unsupported object class" error getObjectTypeDescription() and getObjectIdentityParts() are missing switch cases for PropgraphElementLabelRelationId and PropgraphLabelPropertyRelationId, causing DROP PROPERTY GRAPH to hit the default case and error out with "unsupported object class". The bug only manifests when an event trigger is active, because that is what calls these functions. This commit adds the missing cases so that DROP PROPERTY GRAPH, DROP PROPERTY GRAPH IF EXISTS, and DROP SCHEMA CASCADE on schemas containing property graphs all work correctly when event triggers are present. It also adds test cases that create an event trigger and then exercise DROP PROPERTY GRAPH and DROP SCHEMA CASCADE with property graphs. Author: Bertrand Drouvot --- src/backend/catalog/objectaddress.c | 93 +++++++++++++++++++ .../expected/create_property_graph.out | 36 +++++++ .../regress/sql/create_property_graph.sql | 36 +++++++ 3 files changed, 165 insertions(+) 54.5% src/backend/catalog/ 24.2% src/test/regress/expected/ 21.1% src/test/regress/sql/ diff --git a/src/backend/catalog/objectaddress.c b/src/backend/catalog/objectaddress.c index c1862809577..e2d6d8f71f6 100644 --- a/src/backend/catalog/objectaddress.c +++ b/src/backend/catalog/objectaddress.c @@ -4901,10 +4901,18 @@ getObjectTypeDescription(const ObjectAddress *object, bool missing_ok) appendStringInfoString(&buffer, "policy"); break; + case PropgraphElementLabelRelationId: + appendStringInfoString(&buffer, "property graph element label"); + break; + case PropgraphElementRelationId: appendStringInfoString(&buffer, "property graph element"); break; + case PropgraphLabelPropertyRelationId: + appendStringInfoString(&buffer, "property graph label property"); + break; + case PropgraphLabelRelationId: appendStringInfoString(&buffer, "property graph label"); break; @@ -6161,6 +6169,49 @@ getObjectIdentityParts(const ObjectAddress *object, break; } + case PropgraphElementLabelRelationId: + { + Relation ellabelDesc; + ScanKeyData skey[1]; + SysScanDesc ellabelscan; + HeapTuple tup; + Form_pg_propgraph_element_label pgelform; + ObjectAddress oa; + + ellabelDesc = table_open(PropgraphElementLabelRelationId, AccessShareLock); + ScanKeyInit(&skey[0], + Anum_pg_propgraph_element_label_oid, + BTEqualStrategyNumber, F_OIDEQ, + ObjectIdGetDatum(object->objectId)); + + ellabelscan = systable_beginscan(ellabelDesc, + PropgraphElementLabelObjectIndexId, + true, NULL, 1, skey); + + tup = systable_getnext(ellabelscan); + if (!HeapTupleIsValid(tup)) + { + if (!missing_ok) + elog(ERROR, "could not find tuple for element label %u", + object->objectId); + + systable_endscan(ellabelscan); + table_close(ellabelDesc, AccessShareLock); + break; + } + + pgelform = (Form_pg_propgraph_element_label) GETSTRUCT(tup); + + ObjectAddressSet(oa, PropgraphElementRelationId, pgelform->pgelelid); + + appendStringInfoString(&buffer, getObjectIdentityParts(&oa, objname, + objargs, false)); + + systable_endscan(ellabelscan); + table_close(ellabelDesc, AccessShareLock); + break; + } + case PropgraphElementRelationId: { HeapTuple tup; @@ -6184,6 +6235,48 @@ getObjectIdentityParts(const ObjectAddress *object, break; } + case PropgraphLabelPropertyRelationId: + { + Relation lblpropDesc; + ScanKeyData skey[1]; + SysScanDesc lblpropscan; + HeapTuple tup; + Form_pg_propgraph_label_property plpform; + ObjectAddress oa; + + lblpropDesc = table_open(PropgraphLabelPropertyRelationId, + AccessShareLock); + ScanKeyInit(&skey[0], + Anum_pg_propgraph_label_property_oid, + BTEqualStrategyNumber, F_OIDEQ, + ObjectIdGetDatum(object->objectId)); + + lblpropscan = systable_beginscan(lblpropDesc, PropgraphLabelPropertyObjectIndexId, + true, NULL, 1, skey); + + tup = systable_getnext(lblpropscan); + if (!HeapTupleIsValid(tup)) + { + if (!missing_ok) + elog(ERROR, "could not find tuple for label property %u", + object->objectId); + + systable_endscan(lblpropscan); + table_close(lblpropDesc, AccessShareLock); + break; + } + + plpform = (Form_pg_propgraph_label_property) GETSTRUCT(tup); + + ObjectAddressSet(oa, PropgraphElementLabelRelationId, plpform->plpellabelid); + appendStringInfoString(&buffer, getObjectIdentityParts(&oa, objname, + objargs, false)); + + systable_endscan(lblpropscan); + table_close(lblpropDesc, AccessShareLock); + break; + } + case PropgraphLabelRelationId: { HeapTuple tup; diff --git a/src/test/regress/expected/create_property_graph.out b/src/test/regress/expected/create_property_graph.out index bc9a596ec89..942a1294b15 100644 --- a/src/test/regress/expected/create_property_graph.out +++ b/src/test/regress/expected/create_property_graph.out @@ -922,5 +922,41 @@ ALTER PROPERTY GRAPH IF EXISTS g1 SET SCHEMA create_property_graph_tests_2; NOTICE: relation "g1" does not exist, skipping DROP PROPERTY GRAPH IF EXISTS g1; NOTICE: property graph "g1" does not exist, skipping +-- Test DROP PROPERTY GRAPH with dependency resolution +RESET search_path; +CREATE FUNCTION dpg_evt_func() RETURNS event_trigger +LANGUAGE plpgsql AS $$ +BEGIN END; +$$; +CREATE EVENT TRIGGER dpg_evt ON ddl_command_end EXECUTE FUNCTION dpg_evt_func(); +CREATE TABLE dpg_t1 (id int PRIMARY KEY, val text); +CREATE TABLE dpg_t2 (id int PRIMARY KEY, src int, dst int); +CREATE PROPERTY GRAPH dpg_test + VERTEX TABLES (dpg_t1 KEY (id) LABEL person PROPERTIES (val AS name)) + EDGE TABLES (dpg_t2 KEY (id) + SOURCE KEY (src) REFERENCES dpg_t1 (id) + DESTINATION KEY (dst) REFERENCES dpg_t1 (id) + LABEL knows); +DROP PROPERTY GRAPH dpg_test; +-- table survives graph drop +SELECT COUNT(*) FROM dpg_t1; + count +------- + 0 +(1 row) + +DROP TABLE dpg_t1, dpg_t2; +-- Test DROP SCHEMA CASCADE with property graphs inside +CREATE SCHEMA dpg_schema; +SET search_path = dpg_schema; +CREATE TABLE t (id int PRIMARY KEY); +CREATE PROPERTY GRAPH g VERTEX TABLES (t KEY (id)); +RESET search_path; +DROP SCHEMA dpg_schema CASCADE; +NOTICE: drop cascades to 2 other objects +DETAIL: drop cascades to table dpg_schema.t +drop cascades to property graph dpg_schema.g +DROP EVENT TRIGGER dpg_evt; +DROP FUNCTION dpg_evt_func; DROP ROLE regress_graph_user1, regress_graph_user2; -- leave remaining objects behind for pg_upgrade/pg_dump tests diff --git a/src/test/regress/sql/create_property_graph.sql b/src/test/regress/sql/create_property_graph.sql index 241f93df302..857098dadc8 100644 --- a/src/test/regress/sql/create_property_graph.sql +++ b/src/test/regress/sql/create_property_graph.sql @@ -360,6 +360,42 @@ ALTER PROPERTY GRAPH g1 ADD VERTEX TABLES (t1 KEY (a)); -- error ALTER PROPERTY GRAPH IF EXISTS g1 SET SCHEMA create_property_graph_tests_2; DROP PROPERTY GRAPH IF EXISTS g1; + +-- Test DROP PROPERTY GRAPH with dependency resolution + +RESET search_path; +CREATE FUNCTION dpg_evt_func() RETURNS event_trigger +LANGUAGE plpgsql AS $$ +BEGIN END; +$$; + +CREATE EVENT TRIGGER dpg_evt ON ddl_command_end EXECUTE FUNCTION dpg_evt_func(); + +CREATE TABLE dpg_t1 (id int PRIMARY KEY, val text); +CREATE TABLE dpg_t2 (id int PRIMARY KEY, src int, dst int); +CREATE PROPERTY GRAPH dpg_test + VERTEX TABLES (dpg_t1 KEY (id) LABEL person PROPERTIES (val AS name)) + EDGE TABLES (dpg_t2 KEY (id) + SOURCE KEY (src) REFERENCES dpg_t1 (id) + DESTINATION KEY (dst) REFERENCES dpg_t1 (id) + LABEL knows); +DROP PROPERTY GRAPH dpg_test; + +-- table survives graph drop +SELECT COUNT(*) FROM dpg_t1; +DROP TABLE dpg_t1, dpg_t2; + +-- Test DROP SCHEMA CASCADE with property graphs inside +CREATE SCHEMA dpg_schema; +SET search_path = dpg_schema; +CREATE TABLE t (id int PRIMARY KEY); +CREATE PROPERTY GRAPH g VERTEX TABLES (t KEY (id)); +RESET search_path; +DROP SCHEMA dpg_schema CASCADE; + +DROP EVENT TRIGGER dpg_evt; +DROP FUNCTION dpg_evt_func; + DROP ROLE regress_graph_user1, regress_graph_user2; -- leave remaining objects behind for pg_upgrade/pg_dump tests -- 2.34.1 --s/7v445LwpBnK/Gl--