This is an automated email from the ASF dual-hosted git repository. ztao1987 pushed a commit to branch master in repository https://gitbox.apache.org/repos/asf/hawq.git
The following commit(s) were added to refs/heads/master by this push: new 30270d692 HAWQ-1854. Support GRANT/REVOKE ON ALL TABLES/SEQUENCES/FUNCTIONS IN SCHEMA 30270d692 is described below commit 30270d69274611fd2a7c3c0367acb5cc8cc6c461 Author: ztao1987 <zhenglin.ta...@gmail.com> AuthorDate: Sun Jan 22 21:32:29 2023 +0800 HAWQ-1854. Support GRANT/REVOKE ON ALL TABLES/SEQUENCES/FUNCTIONS IN SCHEMA --- doc/src/sgml/ref/revoke.sgml | 9 ++- src/backend/catalog/aclchk.c | 124 ++++++++++++++++++++++++++++++++++++++++- src/backend/nodes/copyfuncs.c | 1 + src/backend/nodes/equalfuncs.c | 1 + src/backend/parser/gram.y | 48 ++++++++++++++-- src/include/nodes/parsenodes.h | 9 +++ src/include/parser/kwlist.h | 3 + 7 files changed, 187 insertions(+), 8 deletions(-) diff --git a/doc/src/sgml/ref/revoke.sgml b/doc/src/sgml/ref/revoke.sgml index e5fe81142..cb7d79697 100755 --- a/doc/src/sgml/ref/revoke.sgml +++ b/doc/src/sgml/ref/revoke.sgml @@ -23,14 +23,16 @@ PostgreSQL documentation REVOKE [ GRANT OPTION FOR ] { { SELECT | INSERT | UPDATE | DELETE | REFERENCES | TRUNCATE } [,...] | ALL [ PRIVILEGES ] } - ON [ TABLE ] <replaceable class="PARAMETER">tablename</replaceable> [, ...] + ON { [ TABLE ] <replaceable class="PARAMETER">table_name</replaceable> [, ...] + | ALL TABLES IN SCHEMA <replaceable>schema_name</replaceable> [, ...] } FROM { <replaceable class="PARAMETER">rolename</replaceable> | PUBLIC } [, ...] [ CASCADE | RESTRICT ] REVOKE [ GRANT OPTION FOR ] { { USAGE | SELECT | UPDATE } [,...] | ALL [ PRIVILEGES ] } - ON SEQUENCE <replaceable class="PARAMETER">sequencename</replaceable> [, ...] + ON { SEQUENCE <replaceable class="PARAMETER">sequence_name</replaceable> [, ...] + | ALL SEQUENCES IN SCHEMA <replaceable>schema_name</replaceable> [, ...] } FROM { <replaceable class="PARAMETER">rolename</replaceable> | PUBLIC } [, ...] [ CASCADE | RESTRICT ] @@ -42,7 +44,8 @@ REVOKE [ GRANT OPTION FOR ] REVOKE [ GRANT OPTION FOR ] { EXECUTE | ALL [ PRIVILEGES ] } - ON FUNCTION <replaceable>funcname</replaceable> ( [ [ <replaceable class="parameter">argmode</replaceable> ] [ <replaceable class="parameter">argname</replaceable> ] <replaceable class="parameter">argtype</replaceable> [, ...] ] ) [, ...] + ON { FUNCTION <replaceable>function_name</replaceable> ( [ [ <replaceable class="parameter">argmode</replaceable> ] [ <replaceable class="parameter">arg_name</replaceable> ] <replaceable class="parameter">arg_type</replaceable> [, ...] ] ) [, ...] + | ALL FUNCTIONS IN SCHEMA <replaceable>schema_name</replaceable> [, ...] } FROM { <replaceable class="PARAMETER">rolename</replaceable> | PUBLIC } [, ...] [ CASCADE | RESTRICT ] diff --git a/src/backend/catalog/aclchk.c b/src/backend/catalog/aclchk.c index 062b624c2..4401ef22d 100644 --- a/src/backend/catalog/aclchk.c +++ b/src/backend/catalog/aclchk.c @@ -75,6 +75,8 @@ static void ExecGrant_Tablespace(InternalGrant *grantStmt); static void ExecGrant_ExtProtocol(InternalGrant *grantstmt); static List *objectNamesToOids(GrantObjectType objtype, List *objnames); +static List *objectsInSchemaToOids(GrantObjectType objtype, List *nspnames); +static List *getRelationsInNamespace(Oid namespaceId, char relkind); static AclMode string_to_privilege(const char *privname); static const char *privilege_to_string(AclMode privilege); static AclMode restrict_and_check_grant(bool is_grant, AclMode avail_goptions, @@ -335,7 +337,21 @@ ExecuteGrantStmt(GrantStmt *stmt) */ istmt.is_grant = stmt->is_grant; istmt.objtype = stmt->objtype; - istmt.objects = objectNamesToOids(stmt->objtype, stmt->objects); + + /* Collect the OIDs of the target objects */ + switch (stmt->targtype) + { + case ACL_TARGET_OBJECT: + istmt.objects = objectNamesToOids(stmt->objtype, stmt->objects); + break; + case ACL_TARGET_ALL_IN_SCHEMA: + istmt.objects = objectsInSchemaToOids(stmt->objtype, stmt->objects); + break; + /* ACL_TARGET_DEFAULTS should not be seen here */ + default: + elog(ERROR, "unrecognized GrantStmt.targtype: %d", + (int) stmt->targtype); + } /* * Don't allow GRANT/REVOKE for objects managed by Ranger @@ -838,6 +854,112 @@ objectNamesToOids(GrantObjectType objtype, List *objnames) return objects; } +/* + * objectsInSchemaToOids + * + * Find all objects of a given type in specified schemas, and make a list + * of their Oids. We check USAGE privilege on the schemas, but there is + * no privilege checking on the individual objects here. + */ +static List * +objectsInSchemaToOids(GrantObjectType objtype, List *nspnames) +{ + List *objects = NIL; + ListCell *cell; + + foreach(cell, nspnames) + { + char *nspname = strVal(lfirst(cell)); + Oid namespaceId; + List *objs; + + namespaceId = LookupExplicitNamespace(nspname, NSPDBOID_CURRENT); + + switch (objtype) + { + case ACL_OBJECT_RELATION: + /* Process both regular tables and views */ + objs = getRelationsInNamespace(namespaceId, RELKIND_RELATION); + objects = list_concat(objects, objs); + objs = getRelationsInNamespace(namespaceId, RELKIND_VIEW); + objects = list_concat(objects, objs); + break; + case ACL_OBJECT_SEQUENCE: + objs = getRelationsInNamespace(namespaceId, RELKIND_SEQUENCE); + objects = list_concat(objects, objs); + break; + case ACL_OBJECT_FUNCTION: + { + ScanKeyData key[1]; + Relation rel; + HeapScanDesc scan; + HeapTuple tuple; + + ScanKeyInit(&key[0], + Anum_pg_proc_pronamespace, + BTEqualStrategyNumber, F_OIDEQ, + ObjectIdGetDatum(namespaceId)); + + rel = heap_open(ProcedureRelationId, AccessShareLock); + scan = heap_beginscan(rel, SnapshotNow, 1, key); + + while ((tuple = heap_getnext(scan, ForwardScanDirection)) != NULL) + { + objects = lappend_oid(objects, HeapTupleGetOid(tuple)); + } + + heap_endscan(scan); + heap_close(rel, AccessShareLock); + } + break; + default: + /* should not happen */ + elog(ERROR, "unrecognized GrantStmt.objtype: %d", + (int) objtype); + } + } + + return objects; +} + +/* + * getRelationsInNamespace + * + * Return Oid list of relations in given namespace filtered by relation kind + */ +static List * +getRelationsInNamespace(Oid namespaceId, char relkind) +{ + List *relations = NIL; + ScanKeyData key[2]; + Relation rel; + HeapScanDesc scan; + HeapTuple tuple; + + ScanKeyInit(&key[0], + Anum_pg_class_relnamespace, + BTEqualStrategyNumber, F_OIDEQ, + ObjectIdGetDatum(namespaceId)); + ScanKeyInit(&key[1], + Anum_pg_class_relkind, + BTEqualStrategyNumber, F_CHAREQ, + CharGetDatum(relkind)); + + rel = heap_open(RelationRelationId, AccessShareLock); + scan = heap_beginscan(rel, SnapshotNow, 2, key); + + while ((tuple = heap_getnext(scan, ForwardScanDirection)) != NULL) + { + relations = lappend_oid(relations, HeapTupleGetOid(tuple)); + } + + heap_endscan(scan); + heap_close(rel, AccessShareLock); + + return relations; +} + + /* * This processes both sequences and non-sequences. */ diff --git a/src/backend/nodes/copyfuncs.c b/src/backend/nodes/copyfuncs.c index a83966fbc..a466507bb 100644 --- a/src/backend/nodes/copyfuncs.c +++ b/src/backend/nodes/copyfuncs.c @@ -2912,6 +2912,7 @@ _copyGrantStmt(GrantStmt *from) GrantStmt *newnode = makeNode(GrantStmt); COPY_SCALAR_FIELD(is_grant); + COPY_SCALAR_FIELD(targtype); COPY_SCALAR_FIELD(objtype); COPY_NODE_FIELD(objects); COPY_NODE_FIELD(privileges); diff --git a/src/backend/nodes/equalfuncs.c b/src/backend/nodes/equalfuncs.c index 55470c925..de3524edb 100644 --- a/src/backend/nodes/equalfuncs.c +++ b/src/backend/nodes/equalfuncs.c @@ -973,6 +973,7 @@ static bool _equalGrantStmt(GrantStmt *a, GrantStmt *b) { COMPARE_SCALAR_FIELD(is_grant); + COMPARE_SCALAR_FIELD(targtype); COMPARE_SCALAR_FIELD(objtype); COMPARE_NODE_FIELD(objects); COMPARE_NODE_FIELD(privileges); diff --git a/src/backend/parser/gram.y b/src/backend/parser/gram.y index 10cf3196f..2c24a5d31 100755 --- a/src/backend/parser/gram.y +++ b/src/backend/parser/gram.y @@ -523,7 +523,7 @@ static Node *makeIsNotDistinctFromNode(Node *expr, int position); EXCHANGE EXCLUDE EXCLUDING EXCLUSIVE EXECUTE EXISTS EXPLAIN EXTERNAL EXTRACT EDGE FALSE_P FETCH FIELDS FILESPACE FILESYSTEM FILL FILTER FIRST_P FLOAT_P FOLLOWING FOR - FORCE FOREIGN FORMAT FORMATTER FORWARD FREEZE FROM FULL FUNCTION + FORCE FOREIGN FORMAT FORMATTER FORWARD FREEZE FROM FULL FUNCTION FUNCTIONS GB GLOBAL GRANT GRANTED GREATEST GROUP_P GROUP_ID GROUPING GRAPH @@ -567,7 +567,7 @@ static Node *makeIsNotDistinctFromNode(Node *expr, int position); ROLE ROLLBACK ROLLUP ROOTPARTITION ROW ROWS RULE SAVEPOINT SCATTER SCHEMA SCROLL SEARCH SECOND_P - SECURITY SEGMENT SELECT SEQUENCE + SECURITY SEGMENT SELECT SEQUENCE SEQUENCES SERIALIZABLE SERVER SESSION SESSION_USER SET SETOF SETS SHARE SHOW SIMILAR SIMPLE SMALLINT SOME SPLIT SQL STABLE START STATEMENT STATISTICS STDIN STDOUT STORAGE STRICT_P @@ -575,7 +575,7 @@ static Node *makeIsNotDistinctFromNode(Node *expr, int position); SUBSTRING SUPERUSER_P SYMMETRIC SYSID SYSTEM_P - TABLE TABLESPACE TB TEMP TEMPLATE TEMPORARY THEN THRESHOLD TIES TIME TIMESTAMP + TABLE TABLES TABLESPACE TB TEMP TEMPLATE TEMPORARY THEN THRESHOLD TIES TIME TIMESTAMP TO TRAILING TRANSACTION TREAT TRIGGER TRIM TRUE_P TRUNCATE TRUSTED TYPE_P @@ -6839,6 +6839,7 @@ GrantStmt: GRANT privileges ON privilege_target TO grantee_list GrantStmt *n = makeNode(GrantStmt); n->is_grant = true; n->privileges = $2; + n->targtype = ($4)->targtype; n->objtype = ($4)->objtype; n->objects = ($4)->objs; n->grantees = $6; @@ -6855,6 +6856,7 @@ RevokeStmt: n->is_grant = false; n->grant_option = false; n->privileges = $2; + n->targtype = ($4)->targtype; n->objtype = ($4)->objtype; n->objects = ($4)->objs; n->grantees = $6; @@ -6868,6 +6870,7 @@ RevokeStmt: n->is_grant = false; n->grant_option = true; n->privileges = $5; + n->targtype = ($7)->targtype; n->objtype = ($7)->objtype; n->objects = ($7)->objs; n->grantees = $9; @@ -6915,6 +6918,7 @@ privilege_target: qualified_name_list { PrivTarget *n = makeNode(PrivTarget); + n->targtype = ACL_TARGET_OBJECT; n->objtype = ACL_OBJECT_RELATION; n->objs = $1; $$ = n; @@ -6922,6 +6926,7 @@ privilege_target: | TABLE qualified_name_list { PrivTarget *n = makeNode(PrivTarget); + n->targtype = ACL_TARGET_OBJECT; n->objtype = ACL_OBJECT_RELATION; n->objs = $2; $$ = n; @@ -6929,6 +6934,7 @@ privilege_target: | SEQUENCE qualified_name_list { PrivTarget *n = makeNode(PrivTarget); + n->targtype = ACL_TARGET_OBJECT; n->objtype = ACL_OBJECT_SEQUENCE; n->objs = $2; $$ = n; @@ -6936,6 +6942,7 @@ privilege_target: | FOREIGN DATA_P WRAPPER name_list { PrivTarget *n = makeNode(PrivTarget); + n->targtype = ACL_TARGET_OBJECT; n->objtype = ACL_OBJECT_FDW; n->objs = $4; $$ = n; @@ -6943,6 +6950,7 @@ privilege_target: | FOREIGN SERVER name_list { PrivTarget *n = makeNode(PrivTarget); + n->targtype = ACL_TARGET_OBJECT; n->objtype = ACL_OBJECT_FOREIGN_SERVER; n->objs = $3; $$ = n; @@ -6950,6 +6958,7 @@ privilege_target: | FUNCTION function_with_argtypes_list { PrivTarget *n = makeNode(PrivTarget); + n->targtype = ACL_TARGET_OBJECT; n->objtype = ACL_OBJECT_FUNCTION; n->objs = $2; $$ = n; @@ -6957,6 +6966,7 @@ privilege_target: | DATABASE name_list { PrivTarget *n = makeNode(PrivTarget); + n->targtype = ACL_TARGET_OBJECT; n->objtype = ACL_OBJECT_DATABASE; n->objs = $2; $$ = n; @@ -6964,6 +6974,7 @@ privilege_target: | LANGUAGE name_list { PrivTarget *n = makeNode(PrivTarget); + n->targtype = ACL_TARGET_OBJECT; n->objtype = ACL_OBJECT_LANGUAGE; n->objs = $2; $$ = n; @@ -6971,6 +6982,7 @@ privilege_target: | SCHEMA name_list { PrivTarget *n = makeNode(PrivTarget); + n->targtype = ACL_TARGET_OBJECT; n->objtype = ACL_OBJECT_NAMESPACE; n->objs = $2; $$ = n; @@ -6978,6 +6990,7 @@ privilege_target: | TABLESPACE name_list { PrivTarget *n = makeNode(PrivTarget); + n->targtype = ACL_TARGET_OBJECT; n->objtype = ACL_OBJECT_TABLESPACE; n->objs = $2; $$ = n; @@ -6988,7 +7001,31 @@ privilege_target: n->objtype = ACL_OBJECT_EXTPROTOCOL; n->objs = $2; $$ = n; - } + } + | ALL TABLES IN_P SCHEMA name_list + { + PrivTarget *n = (PrivTarget *) palloc(sizeof(PrivTarget)); + n->targtype = ACL_TARGET_ALL_IN_SCHEMA; + n->objtype = ACL_OBJECT_RELATION; + n->objs = $5; + $$ = n; + } + | ALL SEQUENCES IN_P SCHEMA name_list + { + PrivTarget *n = (PrivTarget *) palloc(sizeof(PrivTarget)); + n->targtype = ACL_TARGET_ALL_IN_SCHEMA; + n->objtype = ACL_OBJECT_SEQUENCE; + n->objs = $5; + $$ = n; + } + | ALL FUNCTIONS IN_P SCHEMA name_list + { + PrivTarget *n = (PrivTarget *) palloc(sizeof(PrivTarget)); + n->targtype = ACL_TARGET_ALL_IN_SCHEMA; + n->objtype = ACL_OBJECT_FUNCTION; + n->objs = $5; + $$ = n; + } ; @@ -13030,6 +13067,7 @@ unreserved_keyword: | FORMATTER | FORWARD | FUNCTION + | FUNCTIONS | GB | GLOBAL | GRANTED @@ -13166,6 +13204,7 @@ unreserved_keyword: | SECURITY | SEGMENT | SEQUENCE + | SEQUENCES | SERIALIZABLE | SESSION | SET @@ -13187,6 +13226,7 @@ unreserved_keyword: | SUPERUSER_P | SYSID | SYSTEM_P + | TABLES | TABLESPACE | TB | TEMP diff --git a/src/include/nodes/parsenodes.h b/src/include/nodes/parsenodes.h index 897472fed..164eafeb1 100644 --- a/src/include/nodes/parsenodes.h +++ b/src/include/nodes/parsenodes.h @@ -1254,6 +1254,13 @@ typedef struct AlterDomainStmt { * Grant|Revoke Statement * ---------------------- */ +typedef enum GrantTargetType +{ + ACL_TARGET_OBJECT, /* grant on specific named object(s) */ + ACL_TARGET_ALL_IN_SCHEMA, /* grant on all objects in given schema(s) */ + ACL_TARGET_DEFAULTS /* ALTER DEFAULT PRIVILEGES */ +} GrantTargetType; + typedef enum GrantObjectType { ACL_OBJECT_RELATION, /* table, view */ ACL_OBJECT_SEQUENCE, /* sequence */ @@ -1271,6 +1278,7 @@ typedef enum GrantObjectType { typedef struct GrantStmt { NodeTag type; bool is_grant; /* true = GRANT, false = REVOKE */ + GrantTargetType targtype; /* type of the grant target */ GrantObjectType objtype; /* kind of object being operated on */ List *objects; /* list of RangeVar nodes, FuncWithArgs nodes, * or plain names (as Value strings) */ @@ -1301,6 +1309,7 @@ typedef struct FuncWithArgs { /* This is only used internally in gram.y. */ typedef struct PrivTarget { NodeTag type; + GrantTargetType targtype; GrantObjectType objtype; List *objs; } PrivTarget; diff --git a/src/include/parser/kwlist.h b/src/include/parser/kwlist.h index 8f0798469..d8f8f2452 100644 --- a/src/include/parser/kwlist.h +++ b/src/include/parser/kwlist.h @@ -185,6 +185,7 @@ PG_KEYWORD("freeze", FREEZE, TYPE_FUNC_NAME_KEYWORD) PG_KEYWORD("from", FROM, RESERVED_KEYWORD) PG_KEYWORD("full", FULL, TYPE_FUNC_NAME_KEYWORD) PG_KEYWORD("function", FUNCTION, UNRESERVED_KEYWORD) +PG_KEYWORD("functions", FUNCTIONS, UNRESERVED_KEYWORD) PG_KEYWORD("gb", GB, UNRESERVED_KEYWORD) PG_KEYWORD("global", GLOBAL, UNRESERVED_KEYWORD) PG_KEYWORD("grant", GRANT, RESERVED_KEYWORD) @@ -394,6 +395,7 @@ PG_KEYWORD("security", SECURITY, UNRESERVED_KEYWORD) PG_KEYWORD("segment", SEGMENT, UNRESERVED_KEYWORD) PG_KEYWORD("select", SELECT, RESERVED_KEYWORD) PG_KEYWORD("sequence", SEQUENCE, UNRESERVED_KEYWORD) +PG_KEYWORD("sequences", SEQUENCES, UNRESERVED_KEYWORD) PG_KEYWORD("serializable", SERIALIZABLE, UNRESERVED_KEYWORD) PG_KEYWORD("server", SERVER, UNRESERVED_KEYWORD) PG_KEYWORD("session", SESSION, UNRESERVED_KEYWORD) @@ -427,6 +429,7 @@ PG_KEYWORD("symmetric", SYMMETRIC, RESERVED_KEYWORD) PG_KEYWORD("sysid", SYSID, UNRESERVED_KEYWORD) PG_KEYWORD("system", SYSTEM_P, UNRESERVED_KEYWORD) PG_KEYWORD("table", TABLE, RESERVED_KEYWORD) +PG_KEYWORD("tables", TABLES, UNRESERVED_KEYWORD) PG_KEYWORD("tablespace", TABLESPACE, UNRESERVED_KEYWORD) PG_KEYWORD("tb", TB, UNRESERVED_KEYWORD) PG_KEYWORD("temp", TEMP, UNRESERVED_KEYWORD)