staticvoid RangeVarCallbackForPolicy(const RangeVar *rv,
Oid relid, Oid oldrelid, void *arg); staticchar parse_policy_command(constchar *cmd_name); static Datum *policy_role_list_to_array(List *roles, int *num_roles);
/* Must own relation. */ if (!object_ownercheck(RelationRelationId, relid, GetUserId()))
aclcheck_error(ACLCHECK_NOT_OWNER, get_relkind_objtype(get_rel_relkind(relid)), rv->relname);
/* No system table modifications unless explicitly allowed. */ if (!allowSystemTableMods && IsSystemClass(relid, classform))
ereport(ERROR,
(errcode(ERRCODE_INSUFFICIENT_PRIVILEGE),
errmsg("permission denied: \"%s\" is a system catalog",
rv->relname)));
/* Relation type MUST be a table. */ if (relkind != RELKIND_RELATION && relkind != RELKIND_PARTITIONED_TABLE)
ereport(ERROR,
(errcode(ERRCODE_WRONG_OBJECT_TYPE),
errmsg("\"%s\" is not a table", rv->relname)));
/* *policy_role_list_to_array *helperfunctiontoconvertalistofRoleSpecstoanarrayof *roleidDatums.
*/ static Datum *
policy_role_list_to_array(List *roles, int *num_roles)
{
Datum *role_oids;
ListCell *cell; int i = 0;
/* Handle no roles being passed in as being for public */ if (roles == NIL)
{
*num_roles = 1;
role_oids = (Datum *) palloc(*num_roles * sizeof(Datum));
role_oids[0] = ObjectIdGetDatum(ACL_ID_PUBLIC);
/* *PUBLICcoversallroles,soitonlymakessensealone.
*/ if (spec->roletype == ROLESPEC_PUBLIC)
{ if (*num_roles != 1)
{
ereport(WARNING,
(errcode(ERRCODE_INVALID_PARAMETER_VALUE),
errmsg("ignoring specified roles other than PUBLIC"),
errhint("All roles are members of the PUBLIC role.")));
*num_roles = 1;
}
role_oids[0] = ObjectIdGetDatum(ACL_ID_PUBLIC);
/* Get policy command */
policy->polcmd = policy_form->polcmd;
/* Get policy, permissive or restrictive */
policy->permissive = policy_form->polpermissive;
/* Get policy name */
policy->policy_name =
MemoryContextStrdup(rscxt, NameStr(policy_form->polname));
/* Get policy roles */
datum = heap_getattr(tuple, Anum_pg_policy_polroles,
RelationGetDescr(catalog), &isnull); /* shouldn't be null, but let's check for luck */ if (isnull)
elog(ERROR, "unexpected null value in pg_policy.polroles");
MemoryContextSwitchTo(rscxt);
policy->roles = DatumGetArrayTypePCopy(datum);
MemoryContextSwitchTo(oldcxt);
/* Get policy qual */
datum = heap_getattr(tuple, Anum_pg_policy_polqual,
RelationGetDescr(catalog), &isnull); if (!isnull)
{
str_value = TextDatumGetCString(datum);
MemoryContextSwitchTo(rscxt);
policy->qual = (Expr *) stringToNode(str_value);
MemoryContextSwitchTo(oldcxt);
pfree(str_value);
} else
policy->qual = NULL;
/* Get WITH CHECK qual */
datum = heap_getattr(tuple, Anum_pg_policy_polwithcheck,
RelationGetDescr(catalog), &isnull); if (!isnull)
{
str_value = TextDatumGetCString(datum);
MemoryContextSwitchTo(rscxt);
policy->with_check_qual = (Expr *) stringToNode(str_value);
MemoryContextSwitchTo(oldcxt);
pfree(str_value);
} else
policy->with_check_qual = NULL;
/* We want to cache whether there are SubLinks in these expressions */
policy->hassublinks = checkExprHasSubLink((Node *) policy->qual) ||
checkExprHasSubLink((Node *) policy->with_check_qual);
/* If the policy exists, then remove it, otherwise raise an error. */ if (!HeapTupleIsValid(tuple))
elog(ERROR, "could not find tuple for policy %u", policy_id);
rel = table_open(relid, AccessExclusiveLock); if (rel->rd_rel->relkind != RELKIND_RELATION &&
rel->rd_rel->relkind != RELKIND_PARTITIONED_TABLE)
ereport(ERROR,
(errcode(ERRCODE_WRONG_OBJECT_TYPE),
errmsg("\"%s\" is not a table",
RelationGetRelationName(rel))));
if (!allowSystemTableMods && IsSystemRelation(rel))
ereport(ERROR,
(errcode(ERRCODE_INSUFFICIENT_PRIVILEGE),
errmsg("permission denied: \"%s\" is a system catalog",
RelationGetRelationName(rel))));
/* Remove all the old shared dependencies (roles) */
deleteSharedDependencyRecordsFor(PolicyRelationId, policy_id, 0);
/* Record the new shared dependencies (roles) */
myself.classId = PolicyRelationId;
myself.objectId = policy_id;
myself.objectSubId = 0;
target.classId = AuthIdRelationId;
target.objectSubId = 0; for (i = 0; i < num_roles; i++)
{
target.objectId = DatumGetObjectId(role_oids[i]); /* no need for dependency on the public role */ if (target.objectId != ACL_ID_PUBLIC)
recordSharedDependencyOn(&myself, &target,
SHARED_DEPENDENCY_POLICY);
}
/* Get id of table. Also handles permissions checks. */
table_id = RangeVarGetRelidExtended(stmt->table, AccessExclusiveLock, 0,
RangeVarCallbackForPolicy,
stmt);
/* Open target_table to build quals. No additional lock is necessary. */
target_table = relation_open(table_id, NoLock);
/* Add for the regular security quals */
nsitem = addRangeTableEntryForRelation(qual_pstate, target_table,
AccessShareLock,
NULL, false, false);
addNSItemToQuery(qual_pstate, nsitem, false, true, true);
/* Add for the with-check quals */
nsitem = addRangeTableEntryForRelation(with_check_pstate, target_table,
AccessShareLock,
NULL, false, false);
addNSItemToQuery(with_check_pstate, nsitem, false, true, true);
qual = transformWhereClause(qual_pstate,
stmt->qual,
EXPR_KIND_POLICY, "POLICY");
/* Complain if the policy name already exists for the table */ if (HeapTupleIsValid(policy_tuple))
ereport(ERROR,
(errcode(ERRCODE_DUPLICATE_OBJECT),
errmsg("policy \"%s\" for table \"%s\" already exists",
stmt->policy_name, RelationGetRelationName(target_table))));
/* 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);
}
/* Get id of table. Also handles permissions checks. */
table_id = RangeVarGetRelidExtended(stmt->table, AccessExclusiveLock, 0,
RangeVarCallbackForPolicy,
stmt);
target_table = relation_open(table_id, NoLock);
/* Parse the using policy clause */ if (stmt->qual)
{
ParseNamespaceItem *nsitem;
ParseState *qual_pstate = make_parsestate(NULL);
/* Check that the policy is found, raise an error if not. */ if (!HeapTupleIsValid(policy_tuple))
ereport(ERROR,
(errcode(ERRCODE_UNDEFINED_OBJECT),
errmsg("policy \"%s\" for table \"%s\" does not exist",
stmt->policy_name,
RelationGetRelationName(target_table))));
/* Check if the policy has a USING expr */
value_datum = heap_getattr(policy_tuple, Anum_pg_policy_polqual,
RelationGetDescr(pg_policy_rel),
&attr_isnull); if (!attr_isnull)
{ char *qual_value;
ParseState *qual_pstate;
/* parsestate is built just to build the range table */
qual_pstate = make_parsestate(NULL);
qual_value = TextDatumGetCString(value_datum);
qual = stringToNode(qual_value);
/* Add this rel to the parsestate's rangetable, for dependencies */
(void) addRangeTableEntryForRelation(qual_pstate, target_table,
AccessShareLock,
NULL, false, false);
/* Check if the policy has a WITH CHECK expr */
value_datum = heap_getattr(policy_tuple, Anum_pg_policy_polwithcheck,
RelationGetDescr(pg_policy_rel),
&attr_isnull); if (!attr_isnull)
{ char *with_check_value;
ParseState *with_check_pstate;
/* parsestate is built just to build the range table */
with_check_pstate = make_parsestate(NULL);
/* Add this rel to the parsestate's rangetable, for dependencies */
(void) addRangeTableEntryForRelation(with_check_pstate,
target_table,
AccessShareLock,
NULL, false, false);
/* 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);
}
/* Get id of table. Also handles permissions checks. */
table_id = RangeVarGetRelidExtended(stmt->relation, AccessExclusiveLock, 0,
RangeVarCallbackForPolicy,
stmt);
/* Complain if we did not find the policy */ if (!HeapTupleIsValid(policy_tuple))
ereport(ERROR,
(errcode(ERRCODE_UNDEFINED_OBJECT),
errmsg("policy \"%s\" for table \"%s\" does not exist",
stmt->subname, RelationGetRelationName(target_table))));
if (!HeapTupleIsValid(policy_tuple))
{ if (!missing_ok)
ereport(ERROR,
(errcode(ERRCODE_UNDEFINED_OBJECT),
errmsg("policy \"%s\" for table \"%s\" does not exist",
policy_name, get_rel_name(relid))));
Die Informationen auf dieser Webseite wurden
nach bestem Wissen sorgfältig zusammengestellt. Es wird jedoch weder Vollständigkeit, noch Richtigkeit,
noch Qualität der bereit gestellten Informationen zugesichert.
Bemerkung:
Die farbliche Syntaxdarstellung und die Messung sind noch experimentell.