diff options
Diffstat (limited to 'src/backend/commands/policy.c')
-rw-r--r-- | src/backend/commands/policy.c | 87 |
1 files changed, 61 insertions, 26 deletions
diff --git a/src/backend/commands/policy.c b/src/backend/commands/policy.c index 17b48d49596..9544f75032b 100644 --- a/src/backend/commands/policy.c +++ b/src/backend/commands/policy.c @@ -22,6 +22,7 @@ #include "catalog/indexing.h" #include "catalog/namespace.h" #include "catalog/objectaccess.h" +#include "catalog/pg_authid.h" #include "catalog/pg_policy.h" #include "catalog/pg_type.h" #include "commands/policy.h" @@ -48,7 +49,7 @@ static void RangeVarCallbackForPolicy(const RangeVar *rv, Oid relid, Oid oldrelid, void *arg); static char parse_policy_command(const char *cmd_name); -static ArrayType *policy_role_list_to_array(List *roles); +static Datum *policy_role_list_to_array(List *roles, int *num_roles); /* * Callback to RangeVarGetRelidExtended(). @@ -130,30 +131,28 @@ parse_policy_command(const char *cmd_name) /* * policy_role_list_to_array - * helper function to convert a list of RoleSpecs to an array of role ids. + * helper function to convert a list of RoleSpecs to an array of + * role id Datums. */ -static ArrayType * -policy_role_list_to_array(List *roles) +static Datum * +policy_role_list_to_array(List *roles, int *num_roles) { - ArrayType *role_ids; - Datum *temp_array; + Datum *role_oids; ListCell *cell; - int num_roles; int i = 0; /* Handle no roles being passed in as being for public */ if (roles == NIL) { - temp_array = (Datum *) palloc(sizeof(Datum)); - temp_array[0] = ObjectIdGetDatum(ACL_ID_PUBLIC); + *num_roles = 1; + role_oids = (Datum *) palloc(*num_roles * sizeof(Datum)); + role_oids[0] = ObjectIdGetDatum(ACL_ID_PUBLIC); - role_ids = construct_array(temp_array, 1, OIDOID, sizeof(Oid), true, - 'i'); - return role_ids; + return role_oids; } - num_roles = list_length(roles); - temp_array = (Datum *) palloc(num_roles * sizeof(Datum)); + *num_roles = list_length(roles); + role_oids = (Datum *) palloc(*num_roles * sizeof(Datum)); foreach(cell, roles) { @@ -164,24 +163,24 @@ policy_role_list_to_array(List *roles) */ if (spec->roletype == ROLESPEC_PUBLIC) { - if (num_roles != 1) + if (*num_roles != 1) + { ereport(WARNING, (errcode(ERRCODE_INVALID_PARAMETER_VALUE), errmsg("ignoring roles specified other than public"), errhint("All roles are members of the public role."))); - temp_array[0] = ObjectIdGetDatum(ACL_ID_PUBLIC); - num_roles = 1; - break; + *num_roles = 1; + } + role_oids[0] = ObjectIdGetDatum(ACL_ID_PUBLIC); + + return role_oids; } else - temp_array[i++] = + role_oids[i++] = ObjectIdGetDatum(get_rolespec_oid((Node *) spec, false)); } - role_ids = construct_array(temp_array, num_roles, OIDOID, sizeof(Oid), true, - 'i'); - - return role_ids; + return role_oids; } /* @@ -463,6 +462,8 @@ CreatePolicy(CreatePolicyStmt *stmt) Relation target_table; Oid table_id; char polcmd; + Datum *role_oids; + int nitems = 0; ArrayType *role_ids; ParseState *qual_pstate; ParseState *with_check_pstate; @@ -476,6 +477,7 @@ CreatePolicy(CreatePolicyStmt *stmt) bool isnull[Natts_pg_policy]; ObjectAddress target; ObjectAddress myself; + int i; /* Parse command */ polcmd = parse_policy_command(stmt->cmd); @@ -498,9 +500,10 @@ CreatePolicy(CreatePolicyStmt *stmt) (errcode(ERRCODE_SYNTAX_ERROR), errmsg("only WITH CHECK expression allowed for INSERT"))); - /* Collect role ids */ - role_ids = policy_role_list_to_array(stmt->roles); + role_oids = policy_role_list_to_array(stmt->roles, &nitems); + role_ids = construct_array(role_oids, nitems, OIDOID, + sizeof(Oid), true, 'i'); /* Parse the supplied clause */ qual_pstate = make_parsestate(NULL); @@ -614,6 +617,18 @@ CreatePolicy(CreatePolicyStmt *stmt) recordDependencyOnExpr(&myself, with_check_qual, with_check_pstate->p_rtable, DEPENDENCY_NORMAL); + /* Register role dependencies */ + target.classId = AuthIdRelationId; + target.objectSubId = 0; + for (i = 0; i < nitems; i++) + { + target.objectId = DatumGetObjectId(role_oids[i]); + /* no dependency if public */ + if (target.objectId != ACL_ID_PUBLIC) + recordSharedDependencyOn(&myself, &target, + SHARED_DEPENDENCY_POLICY); + } + /* Invalidate Relation Cache */ CacheInvalidateRelcache(target_table); @@ -641,6 +656,8 @@ AlterPolicy(AlterPolicyStmt *stmt) Oid policy_id; Relation target_table; Oid table_id; + Datum *role_oids; + int nitems = 0; ArrayType *role_ids = NULL; List *qual_parse_rtable = NIL; List *with_check_parse_rtable = NIL; @@ -658,10 +675,15 @@ AlterPolicy(AlterPolicyStmt *stmt) Datum cmd_datum; char polcmd; bool polcmd_isnull; + int i; /* Parse role_ids */ if (stmt->roles != NULL) - role_ids = policy_role_list_to_array(stmt->roles); + { + role_oids = policy_role_list_to_array(stmt->roles, &nitems); + role_ids = construct_array(role_oids, nitems, OIDOID, + sizeof(Oid), true, 'i'); + } /* Get id of table. Also handles permissions checks. */ table_id = RangeVarGetRelidExtended(stmt->table, AccessExclusiveLock, @@ -825,6 +847,19 @@ AlterPolicy(AlterPolicyStmt *stmt) recordDependencyOnExpr(&myself, with_check_qual, with_check_parse_rtable, DEPENDENCY_NORMAL); + /* Register role dependencies */ + deleteSharedDependencyRecordsFor(PolicyRelationId, policy_id, 0); + target.classId = AuthIdRelationId; + target.objectSubId = 0; + for (i = 0; i < nitems; i++) + { + target.objectId = DatumGetObjectId(role_oids[i]); + /* no dependency if public */ + if (target.objectId != ACL_ID_PUBLIC) + recordSharedDependencyOn(&myself, &target, + SHARED_DEPENDENCY_POLICY); + } + heap_freetuple(new_tuple); /* Invalidate Relation Cache */ |