Starting a new thread from [1] as suggested.

>
> On Fri, Jul 03, 2026 at 04:09:20PM +0530, Ashutosh Bapat wrote:
> > On Wed, Jul 1, 2026 at 9:51 PM Ashutosh Bapat
> > <[email protected]> wrote:
> > >
> > > I wondered whether we are missing special handling for PROPGRAPH at
> > > other places. I looked at other places where we handle OBJECT_SEQUENCE
> > > separately in acl related files. I discovered following missing cases
> > >
> > > 1. ExecGrant_Relation: I think we should clip the extra privileges
> > > with a warning when GRANT ... TABLE syntax is used to grant privileges
> > > on a property graph, just like sequences. To me it looks like we
> > > should prohibit GRANT ... TABLE on property graph altogether. But
> > > haven't done so to keep it in sync with sequences. The backward
> > > compatibility comment,  "For backward compatibility, just ... " should
> > > not be applicable in case of property graph since we can introduce
> > > whatever behaviour we expect from GRANT ... TABLE right from the first
> > > release which introduced property graph. But I am not sure if that's
> > > the only backward compatibility we are talking about here. Those
> > > commits go more than a few decades back and commit message itself
> > > doesn't help me much. Maybe someone with a better historical
> > > perspective may help. I have also added a test scenario for a
> > > non-property graph privilege to be added using GRANT ... TABLE syntax.
> >
> > Since property graphs share the namespace with regular tables, I think
> > GRANT ... TABLE should be supported on property graphs, but restrict
> > it to only the privileges applicable to property graphs.
>
> I don't have a strong opinion on that, but I likely would have chosen to block
> GRANT TABLE on a propgraph.  The backward compatibility argument written for
> SEQUENCE likely means that someone noticed GRANT TABLE worked on sequences and
> decided both that it was a mistake and that reversing the mistake would be a
> cure worse than the disease.  There was a rebuttable presumption that when we
> add a new grantable object with its own GRANT subtype, older GRANT subtypes
> should reject that object.
>
> > > 2. pg_class_aclmask_ext(): this seems to be another omission. Probably
> > > innocuous since we will test only SELECT privileges on a property
> > > graph and ignore other default table privileges.
>
> Makes sense.

Modified the patch to disallow GRANT ... TABLE on property graph.

The patch uses errmsg("\"%s\" is a property graph",
NameStr(pg_class_tuple->relname)) inline with other prohibited cases.
Additionally it gives errhint("Use GRANT ... ON PROPERTY GRAPH
instead.")), which may be obvious from the error message, but I
thought clarity is better than brevity.

There are some cases where we report ""%s" is not a sequence". Inline
with that we could use errmsg("\"%s\" is not a table",
NameStr(pg_class_tuple->relname)) with errhint("Use GRANT ... ON
PROPERTY GRAPH instead.")).

I prefer the first one, but I am ok with the second option as well.

-- 
Best Wishes,
Ashutosh Bapat
From 1739f6fca786a53ed451b35ad7593e4250555b41 Mon Sep 17 00:00:00 2001
From: Ashutosh Bapat <[email protected]>
Date: Wed, 1 Jul 2026 21:34:48 +0530
Subject: [PATCH v20260708 5/5] Prohibit GRANT ... ON TABLE on a property graph

We allowed GRANT ... ON TABLE on sequences for backward compatibility.
We don't need to consider backward compatibility in case of property
graphs since we will be prohibiting its usage on property graph from the
very release which introduced property graphs.

Change regression tests that used GRANT ... ON (TABLE) on property
graphs to use GRANT ... ON PROPERTY GRAPH instead.

While here, add the missing RELKIND_PROPGRAPH cases in
pg_class_aclmask_ext() and in the object-type switch in
ExecGrant_Relation() so that the default ACL and the objtype passed to
restrict_and_check_grant() are correct.

Author: Ashutosh Bapat <[email protected]>
Reviewed by: Noah Misch <[email protected]>
Reviewed by: Tom Lane <[email protected]>
Discussion: https://www.postgresql.org/message-id/[email protected]
---
 src/backend/catalog/aclchk.c                  | 20 ++++++++++++++++++-
 .../expected/create_property_graph.out        |  3 +++
 src/test/regress/expected/graph_table_rls.out |  6 +++---
 src/test/regress/expected/privileges.out      |  4 ++--
 .../regress/sql/create_property_graph.sql     |  1 +
 src/test/regress/sql/graph_table_rls.sql      |  6 +++---
 src/test/regress/sql/privileges.sql           |  4 ++--
 7 files changed, 33 insertions(+), 11 deletions(-)

diff --git a/src/backend/catalog/aclchk.c b/src/backend/catalog/aclchk.c
index 140cd1302f5..c7ab9cc5524 100644
--- a/src/backend/catalog/aclchk.c
+++ b/src/backend/catalog/aclchk.c
@@ -1784,7 +1784,7 @@ ExecGrant_Attribute(InternalGrant *istmt, Oid relOid, const char *relname,
 }
 
 /*
- *	This processes both sequences and non-sequences.
+ * This processes all pg_class entries including sequences and property graphs.
  */
 static void
 ExecGrant_Relation(InternalGrant *istmt)
@@ -1891,6 +1891,18 @@ ExecGrant_Relation(InternalGrant *istmt)
 					this_privileges &= (AclMode) ACL_ALL_RIGHTS_SEQUENCE;
 				}
 			}
+			else if (pg_class_tuple->relkind == RELKIND_PROPGRAPH)
+			{
+				/*
+				 * Do not allow GRANT ... TABLE on property graph. We allowed
+				 * it on sequences for backward compatibility but there is no
+				 * reason to continue that further.
+				 */
+				ereport(ERROR,
+						errcode(ERRCODE_WRONG_OBJECT_TYPE),
+						errmsg("\"%s\" is a property graph", NameStr(pg_class_tuple->relname)),
+						errhint("Use GRANT ... ON PROPERTY GRAPH instead."));
+			}
 			else
 			{
 				if (this_privileges & ~((AclMode) ACL_ALL_RIGHTS_RELATION))
@@ -1996,6 +2008,9 @@ ExecGrant_Relation(InternalGrant *istmt)
 				case RELKIND_SEQUENCE:
 					objtype = OBJECT_SEQUENCE;
 					break;
+				case RELKIND_PROPGRAPH:
+					objtype = OBJECT_PROPGRAPH;
+					break;
 				default:
 					objtype = OBJECT_TABLE;
 					break;
@@ -3389,6 +3404,9 @@ pg_class_aclmask_ext(Oid table_oid, Oid roleid, AclMode mask,
 			case RELKIND_SEQUENCE:
 				acl = acldefault(OBJECT_SEQUENCE, ownerId);
 				break;
+			case RELKIND_PROPGRAPH:
+				acl = acldefault(OBJECT_PROPGRAPH, ownerId);
+				break;
 			default:
 				acl = acldefault(OBJECT_TABLE, ownerId);
 				break;
diff --git a/src/test/regress/expected/create_property_graph.out b/src/test/regress/expected/create_property_graph.out
index 3efcce046cf..da148db0653 100644
--- a/src/test/regress/expected/create_property_graph.out
+++ b/src/test/regress/expected/create_property_graph.out
@@ -250,6 +250,9 @@ SET ROLE regress_graph_user1;
 GRANT SELECT ON PROPERTY GRAPH g1 TO regress_graph_user2;
 GRANT UPDATE ON PROPERTY GRAPH g1 TO regress_graph_user2;  -- fail
 ERROR:  invalid privilege type UPDATE for property graph
+GRANT UPDATE ON TABLE g1 TO regress_graph_user2;  -- warning
+ERROR:  "g1" is a property graph
+HINT:  Use GRANT ... ON PROPERTY GRAPH instead.
 RESET ROLE;
 -- collation
 CREATE TABLE tc1 (a int, b text);
diff --git a/src/test/regress/expected/graph_table_rls.out b/src/test/regress/expected/graph_table_rls.out
index 0e719c7ebd7..230ae4cdb01 100644
--- a/src/test/regress/expected/graph_table_rls.out
+++ b/src/test/regress/expected/graph_table_rls.out
@@ -74,7 +74,7 @@ CREATE PROPERTY GRAPH cabinet
     EDGE TABLES (accessed KEY (aid)
                  SOURCE KEY (uid) REFERENCES users (uid)
                  DESTINATION KEY (did) REFERENCES document (did));
-GRANT SELECT ON cabinet TO public;
+GRANT SELECT ON PROPERTY GRAPH cabinet TO public;
 --
 -- Basic RLS tests
 --
@@ -261,7 +261,7 @@ CREATE PROPERTY GRAPH cabinet
     EDGE TABLES (accessed KEY (aid)
                  SOURCE KEY (uid) REFERENCES users (uid)
                  DESTINATION KEY (did) REFERENCES document (did));
-GRANT SELECT ON cabinet TO public;
+GRANT SELECT ON PROPERTY GRAPH cabinet TO public;
 SET row_security TO ON;
 -- viewpoint from regress_graph_rls_bob
 SET SESSION AUTHORIZATION regress_graph_rls_bob;
@@ -456,7 +456,7 @@ CREATE PROPERTY GRAPH cabinet
     EDGE TABLES (accessed KEY (aid)
                  SOURCE KEY (uid) REFERENCES users (uid)
                  DESTINATION KEY (did) REFERENCES document (did));
-GRANT SELECT ON cabinet TO public;
+GRANT SELECT ON PROPERTY GRAPH cabinet TO public;
 SET row_security TO ON;
 -- viewpoint from regress_graph_rls_bob
 SET SESSION AUTHORIZATION regress_graph_rls_bob;
diff --git a/src/test/regress/expected/privileges.out b/src/test/regress/expected/privileges.out
index f6cc1a1029c..fd18549e84e 100644
--- a/src/test/regress/expected/privileges.out
+++ b/src/test/regress/expected/privileges.out
@@ -3206,7 +3206,7 @@ select * from graph_table (ptg1 match (is atest5) COLUMNS (1 as value)) limit 0;
 -------
 (0 rows)
 
-grant select on ptg1 to regress_priv_user2;
+grant select on property graph ptg1 to regress_priv_user2;
 set session role regress_priv_user2;
 select * from graph_table (ptg1 match (is atest1) COLUMNS (1 as value)) limit 0; -- ok
  value 
@@ -3232,7 +3232,7 @@ select * from graph_table (ptg1 match (v is lttc) COLUMNS (v.lttck)) limit 0; --
 -------
 (0 rows)
 
-grant select on ptg1 to regress_priv_user4;
+grant select on property graph ptg1 to regress_priv_user4;
 set session role regress_priv_user4;
 select * from graph_table (ptg1 match (a is atest5) COLUMNS (a.four)) limit 0; -- ok
  four 
diff --git a/src/test/regress/sql/create_property_graph.sql b/src/test/regress/sql/create_property_graph.sql
index f98a9187451..d05062678a2 100644
--- a/src/test/regress/sql/create_property_graph.sql
+++ b/src/test/regress/sql/create_property_graph.sql
@@ -196,6 +196,7 @@ ALTER PROPERTY GRAPH g1 OWNER TO regress_graph_user1;
 SET ROLE regress_graph_user1;
 GRANT SELECT ON PROPERTY GRAPH g1 TO regress_graph_user2;
 GRANT UPDATE ON PROPERTY GRAPH g1 TO regress_graph_user2;  -- fail
+GRANT UPDATE ON TABLE g1 TO regress_graph_user2;  -- warning
 RESET ROLE;
 
 -- collation
diff --git a/src/test/regress/sql/graph_table_rls.sql b/src/test/regress/sql/graph_table_rls.sql
index 5837eac402e..5c79ade68d4 100644
--- a/src/test/regress/sql/graph_table_rls.sql
+++ b/src/test/regress/sql/graph_table_rls.sql
@@ -87,7 +87,7 @@ CREATE PROPERTY GRAPH cabinet
     EDGE TABLES (accessed KEY (aid)
                  SOURCE KEY (uid) REFERENCES users (uid)
                  DESTINATION KEY (did) REFERENCES document (did));
-GRANT SELECT ON cabinet TO public;
+GRANT SELECT ON PROPERTY GRAPH cabinet TO public;
 
 --
 -- Basic RLS tests
@@ -198,7 +198,7 @@ CREATE PROPERTY GRAPH cabinet
     EDGE TABLES (accessed KEY (aid)
                  SOURCE KEY (uid) REFERENCES users (uid)
                  DESTINATION KEY (did) REFERENCES document (did));
-GRANT SELECT ON cabinet TO public;
+GRANT SELECT ON PROPERTY GRAPH cabinet TO public;
 
 SET row_security TO ON;
 
@@ -267,7 +267,7 @@ CREATE PROPERTY GRAPH cabinet
     EDGE TABLES (accessed KEY (aid)
                  SOURCE KEY (uid) REFERENCES users (uid)
                  DESTINATION KEY (did) REFERENCES document (did));
-GRANT SELECT ON cabinet TO public;
+GRANT SELECT ON PROPERTY GRAPH cabinet TO public;
 SET row_security TO ON;
 
 -- viewpoint from regress_graph_rls_bob
diff --git a/src/test/regress/sql/privileges.sql b/src/test/regress/sql/privileges.sql
index 6cd9bb840ff..6e0686da131 100644
--- a/src/test/regress/sql/privileges.sql
+++ b/src/test/regress/sql/privileges.sql
@@ -1890,7 +1890,7 @@ create property graph ptg1
 			label ltv properties (col1 as ltvk));
 -- select privileges on property graph as well as table
 select * from graph_table (ptg1 match (is atest5) COLUMNS (1 as value)) limit 0; -- ok
-grant select on ptg1 to regress_priv_user2;
+grant select on property graph ptg1 to regress_priv_user2;
 set session role regress_priv_user2;
 select * from graph_table (ptg1 match (is atest1) COLUMNS (1 as value)) limit 0; -- ok
 -- select privileges on property graph but not table
@@ -1904,7 +1904,7 @@ select * from graph_table (ptg1 match (is atest5) COLUMNS (1 as value)) limit 0;
 -- column privileges
 set session role regress_priv_user1;
 select * from graph_table (ptg1 match (v is lttc) COLUMNS (v.lttck)) limit 0; -- ok
-grant select on ptg1 to regress_priv_user4;
+grant select on property graph ptg1 to regress_priv_user4;
 set session role regress_priv_user4;
 select * from graph_table (ptg1 match (a is atest5) COLUMNS (a.four)) limit 0; -- ok
 select * from graph_table (ptg1 match (v is lttc) COLUMNS (v.lttck)) limit 0; -- fail
-- 
2.34.1

Reply via email to