PostgreSQL Source Code  git master
policy.c File Reference
#include "postgres.h"
#include "access/genam.h"
#include "access/htup.h"
#include "access/htup_details.h"
#include "access/relation.h"
#include "access/sysattr.h"
#include "access/table.h"
#include "catalog/catalog.h"
#include "catalog/dependency.h"
#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"
#include "miscadmin.h"
#include "nodes/makefuncs.h"
#include "nodes/pg_list.h"
#include "parser/parse_clause.h"
#include "parser/parse_collate.h"
#include "parser/parse_node.h"
#include "parser/parse_relation.h"
#include "rewrite/rewriteManip.h"
#include "rewrite/rowsecurity.h"
#include "storage/lock.h"
#include "utils/acl.h"
#include "utils/array.h"
#include "utils/builtins.h"
#include "utils/fmgroids.h"
#include "utils/inval.h"
#include "utils/lsyscache.h"
#include "utils/memutils.h"
#include "utils/rel.h"
#include "utils/syscache.h"
Include dependency graph for policy.c:

Go to the source code of this file.

Functions

static void RangeVarCallbackForPolicy (const RangeVar *rv, Oid relid, Oid oldrelid, void *arg)
 
static char parse_policy_command (const char *cmd_name)
 
static Datumpolicy_role_list_to_array (List *roles, int *num_roles)
 
void RelationBuildRowSecurity (Relation relation)
 
void RemovePolicyById (Oid policy_id)
 
bool RemoveRoleFromObjectPolicy (Oid roleid, Oid classid, Oid policy_id)
 
ObjectAddress CreatePolicy (CreatePolicyStmt *stmt)
 
ObjectAddress AlterPolicy (AlterPolicyStmt *stmt)
 
ObjectAddress rename_policy (RenameStmt *stmt)
 
Oid get_relation_policy_oid (Oid relid, const char *policy_name, bool missing_ok)
 
bool relation_has_policies (Relation rel)
 

Function Documentation

◆ AlterPolicy()

ObjectAddress AlterPolicy ( AlterPolicyStmt stmt)

Definition at line 870 of file policy.c.

References AccessExclusiveLock, AccessShareLock, ACL_DELETE_CHR, ACL_ID_PUBLIC, ACL_INSERT_CHR, ACL_SELECT_CHR, addNSItemToQuery(), addRangeTableEntryForRelation(), ARR_DATA_PTR, ARR_DIMS, Assert, assign_expr_collations(), BTEqualStrategyNumber, CacheInvalidateRelcache(), CatalogTupleUpdate(), ObjectAddress::classId, construct_array(), copyObject, CStringGetDatum, CStringGetTextDatum, DatumGetArrayTypePCopy, DatumGetChar, DatumGetObjectId, deleteDependencyRecordsFor(), deleteSharedDependencyRecordsFor(), DEPENDENCY_AUTO, DEPENDENCY_NORMAL, ereport, errcode(), errmsg(), ERROR, EXPR_KIND_POLICY, free_parsestate(), GETSTRUCT, heap_freetuple(), heap_getattr, heap_modify_tuple(), HeapTupleIsValid, i, InvokeObjectPostAlterHook, make_parsestate(), NIL, nodeToString(), NoLock, ObjectAddress::objectId, ObjectIdGetDatum, ObjectAddress::objectSubId, ParseState::p_rtable, palloc(), PointerGetDatum, policy_role_list_to_array(), PolicyPolrelidPolnameIndexId, RangeVarCallbackForPolicy(), RangeVarGetRelidExtended(), recordDependencyOn(), recordDependencyOnExpr(), recordSharedDependencyOn(), relation_close(), relation_open(), RelationGetDescr, RelationGetRelationName, AlterPolicyStmt::roles, RowExclusiveLock, ScanKeyInit(), SHARED_DEPENDENCY_POLICY, stringToNode(), systable_beginscan(), systable_endscan(), systable_getnext(), HeapTupleData::t_self, AlterPolicyStmt::table, table_close(), table_open(), TextDatumGetCString, transformWhereClause(), and values.

Referenced by ProcessUtilitySlow().

871 {
872  Relation pg_policy_rel;
873  Oid policy_id;
874  Relation target_table;
875  Oid table_id;
876  Datum *role_oids = NULL;
877  int nitems = 0;
878  ArrayType *role_ids = NULL;
879  List *qual_parse_rtable = NIL;
880  List *with_check_parse_rtable = NIL;
881  Node *qual = NULL;
882  Node *with_check_qual = NULL;
883  ScanKeyData skey[2];
884  SysScanDesc sscan;
885  HeapTuple policy_tuple;
886  HeapTuple new_tuple;
887  Datum values[Natts_pg_policy];
888  bool isnull[Natts_pg_policy];
889  bool replaces[Natts_pg_policy];
890  ObjectAddress target;
891  ObjectAddress myself;
892  Datum polcmd_datum;
893  char polcmd;
894  bool polcmd_isnull;
895  int i;
896 
897  /* Parse role_ids */
898  if (stmt->roles != NULL)
899  {
900  role_oids = policy_role_list_to_array(stmt->roles, &nitems);
901  role_ids = construct_array(role_oids, nitems, OIDOID,
902  sizeof(Oid), true, TYPALIGN_INT);
903  }
904 
905  /* Get id of table. Also handles permissions checks. */
907  0,
909  (void *) stmt);
910 
911  target_table = relation_open(table_id, NoLock);
912 
913  /* Parse the using policy clause */
914  if (stmt->qual)
915  {
916  ParseNamespaceItem *nsitem;
917  ParseState *qual_pstate = make_parsestate(NULL);
918 
919  nsitem = addRangeTableEntryForRelation(qual_pstate, target_table,
921  NULL, false, false);
922 
923  addNSItemToQuery(qual_pstate, nsitem, false, true, true);
924 
925  qual = transformWhereClause(qual_pstate, copyObject(stmt->qual),
927  "POLICY");
928 
929  /* Fix up collation information */
930  assign_expr_collations(qual_pstate, qual);
931 
932  qual_parse_rtable = qual_pstate->p_rtable;
933  free_parsestate(qual_pstate);
934  }
935 
936  /* Parse the with-check policy clause */
937  if (stmt->with_check)
938  {
939  ParseNamespaceItem *nsitem;
940  ParseState *with_check_pstate = make_parsestate(NULL);
941 
942  nsitem = addRangeTableEntryForRelation(with_check_pstate, target_table,
944  NULL, false, false);
945 
946  addNSItemToQuery(with_check_pstate, nsitem, false, true, true);
947 
948  with_check_qual = transformWhereClause(with_check_pstate,
949  copyObject(stmt->with_check),
951  "POLICY");
952 
953  /* Fix up collation information */
954  assign_expr_collations(with_check_pstate, with_check_qual);
955 
956  with_check_parse_rtable = with_check_pstate->p_rtable;
957  free_parsestate(with_check_pstate);
958  }
959 
960  /* zero-clear */
961  memset(values, 0, sizeof(values));
962  memset(replaces, 0, sizeof(replaces));
963  memset(isnull, 0, sizeof(isnull));
964 
965  /* Find policy to update. */
966  pg_policy_rel = table_open(PolicyRelationId, RowExclusiveLock);
967 
968  /* Set key - policy's relation id. */
969  ScanKeyInit(&skey[0],
970  Anum_pg_policy_polrelid,
971  BTEqualStrategyNumber, F_OIDEQ,
972  ObjectIdGetDatum(table_id));
973 
974  /* Set key - policy's name. */
975  ScanKeyInit(&skey[1],
976  Anum_pg_policy_polname,
977  BTEqualStrategyNumber, F_NAMEEQ,
979 
980  sscan = systable_beginscan(pg_policy_rel,
981  PolicyPolrelidPolnameIndexId, true, NULL, 2,
982  skey);
983 
984  policy_tuple = systable_getnext(sscan);
985 
986  /* Check that the policy is found, raise an error if not. */
987  if (!HeapTupleIsValid(policy_tuple))
988  ereport(ERROR,
989  (errcode(ERRCODE_UNDEFINED_OBJECT),
990  errmsg("policy \"%s\" for table \"%s\" does not exist",
991  stmt->policy_name,
992  RelationGetRelationName(target_table))));
993 
994  /* Get policy command */
995  polcmd_datum = heap_getattr(policy_tuple, Anum_pg_policy_polcmd,
996  RelationGetDescr(pg_policy_rel),
997  &polcmd_isnull);
998  Assert(!polcmd_isnull);
999  polcmd = DatumGetChar(polcmd_datum);
1000 
1001  /*
1002  * If the command is SELECT or DELETE then WITH CHECK should be NULL.
1003  */
1004  if ((polcmd == ACL_SELECT_CHR || polcmd == ACL_DELETE_CHR)
1005  && stmt->with_check != NULL)
1006  ereport(ERROR,
1007  (errcode(ERRCODE_SYNTAX_ERROR),
1008  errmsg("only USING expression allowed for SELECT, DELETE")));
1009 
1010  /*
1011  * If the command is INSERT then WITH CHECK should be the only expression
1012  * provided.
1013  */
1014  if ((polcmd == ACL_INSERT_CHR)
1015  && stmt->qual != NULL)
1016  ereport(ERROR,
1017  (errcode(ERRCODE_SYNTAX_ERROR),
1018  errmsg("only WITH CHECK expression allowed for INSERT")));
1019 
1020  policy_id = ((Form_pg_policy) GETSTRUCT(policy_tuple))->oid;
1021 
1022  if (role_ids != NULL)
1023  {
1024  replaces[Anum_pg_policy_polroles - 1] = true;
1025  values[Anum_pg_policy_polroles - 1] = PointerGetDatum(role_ids);
1026  }
1027  else
1028  {
1029  Oid *roles;
1030  Datum roles_datum;
1031  bool attr_isnull;
1032  ArrayType *policy_roles;
1033 
1034  /*
1035  * We need to pull the set of roles this policy applies to from what's
1036  * in the catalog, so that we can recreate the dependencies correctly
1037  * for the policy.
1038  */
1039 
1040  roles_datum = heap_getattr(policy_tuple, Anum_pg_policy_polroles,
1041  RelationGetDescr(pg_policy_rel),
1042  &attr_isnull);
1043  Assert(!attr_isnull);
1044 
1045  policy_roles = DatumGetArrayTypePCopy(roles_datum);
1046 
1047  roles = (Oid *) ARR_DATA_PTR(policy_roles);
1048 
1049  nitems = ARR_DIMS(policy_roles)[0];
1050 
1051  role_oids = (Datum *) palloc(nitems * sizeof(Datum));
1052 
1053  for (i = 0; i < nitems; i++)
1054  role_oids[i] = ObjectIdGetDatum(roles[i]);
1055  }
1056 
1057  if (qual != NULL)
1058  {
1059  replaces[Anum_pg_policy_polqual - 1] = true;
1060  values[Anum_pg_policy_polqual - 1]
1062  }
1063  else
1064  {
1065  Datum value_datum;
1066  bool attr_isnull;
1067 
1068  /*
1069  * We need to pull the USING expression and build the range table for
1070  * the policy from what's in the catalog, so that we can recreate the
1071  * dependencies correctly for the policy.
1072  */
1073 
1074  /* Check if the policy has a USING expr */
1075  value_datum = heap_getattr(policy_tuple, Anum_pg_policy_polqual,
1076  RelationGetDescr(pg_policy_rel),
1077  &attr_isnull);
1078  if (!attr_isnull)
1079  {
1080  char *qual_value;
1081  ParseState *qual_pstate;
1082 
1083  /* parsestate is built just to build the range table */
1084  qual_pstate = make_parsestate(NULL);
1085 
1086  qual_value = TextDatumGetCString(value_datum);
1087  qual = stringToNode(qual_value);
1088 
1089  /* Add this rel to the parsestate's rangetable, for dependencies */
1090  (void) addRangeTableEntryForRelation(qual_pstate, target_table,
1092  NULL, false, false);
1093 
1094  qual_parse_rtable = qual_pstate->p_rtable;
1095  free_parsestate(qual_pstate);
1096  }
1097  }
1098 
1099  if (with_check_qual != NULL)
1100  {
1101  replaces[Anum_pg_policy_polwithcheck - 1] = true;
1102  values[Anum_pg_policy_polwithcheck - 1]
1103  = CStringGetTextDatum(nodeToString(with_check_qual));
1104  }
1105  else
1106  {
1107  Datum value_datum;
1108  bool attr_isnull;
1109 
1110  /*
1111  * We need to pull the WITH CHECK expression and build the range table
1112  * for the policy from what's in the catalog, so that we can recreate
1113  * the dependencies correctly for the policy.
1114  */
1115 
1116  /* Check if the policy has a WITH CHECK expr */
1117  value_datum = heap_getattr(policy_tuple, Anum_pg_policy_polwithcheck,
1118  RelationGetDescr(pg_policy_rel),
1119  &attr_isnull);
1120  if (!attr_isnull)
1121  {
1122  char *with_check_value;
1123  ParseState *with_check_pstate;
1124 
1125  /* parsestate is built just to build the range table */
1126  with_check_pstate = make_parsestate(NULL);
1127 
1128  with_check_value = TextDatumGetCString(value_datum);
1129  with_check_qual = stringToNode(with_check_value);
1130 
1131  /* Add this rel to the parsestate's rangetable, for dependencies */
1132  (void) addRangeTableEntryForRelation(with_check_pstate,
1133  target_table,
1135  NULL, false, false);
1136 
1137  with_check_parse_rtable = with_check_pstate->p_rtable;
1138  free_parsestate(with_check_pstate);
1139  }
1140  }
1141 
1142  new_tuple = heap_modify_tuple(policy_tuple,
1143  RelationGetDescr(pg_policy_rel),
1144  values, isnull, replaces);
1145  CatalogTupleUpdate(pg_policy_rel, &new_tuple->t_self, new_tuple);
1146 
1147  /* Update Dependencies. */
1148  deleteDependencyRecordsFor(PolicyRelationId, policy_id, false);
1149 
1150  /* Record Dependencies */
1151  target.classId = RelationRelationId;
1152  target.objectId = table_id;
1153  target.objectSubId = 0;
1154 
1155  myself.classId = PolicyRelationId;
1156  myself.objectId = policy_id;
1157  myself.objectSubId = 0;
1158 
1159  recordDependencyOn(&myself, &target, DEPENDENCY_AUTO);
1160 
1161  recordDependencyOnExpr(&myself, qual, qual_parse_rtable, DEPENDENCY_NORMAL);
1162 
1163  recordDependencyOnExpr(&myself, with_check_qual, with_check_parse_rtable,
1165 
1166  /* Register role dependencies */
1167  deleteSharedDependencyRecordsFor(PolicyRelationId, policy_id, 0);
1168  target.classId = AuthIdRelationId;
1169  target.objectSubId = 0;
1170  for (i = 0; i < nitems; i++)
1171  {
1172  target.objectId = DatumGetObjectId(role_oids[i]);
1173  /* no dependency if public */
1174  if (target.objectId != ACL_ID_PUBLIC)
1175  recordSharedDependencyOn(&myself, &target,
1177  }
1178 
1179  InvokeObjectPostAlterHook(PolicyRelationId, policy_id, 0);
1180 
1181  heap_freetuple(new_tuple);
1182 
1183  /* Invalidate Relation Cache */
1184  CacheInvalidateRelcache(target_table);
1185 
1186  /* Clean up. */
1187  systable_endscan(sscan);
1188  relation_close(target_table, NoLock);
1189  table_close(pg_policy_rel, RowExclusiveLock);
1190 
1191  return myself;
1192 }
#define NIL
Definition: pg_list.h:65
#define ACL_INSERT_CHR
Definition: acl.h:137
void recordSharedDependencyOn(ObjectAddress *depender, ObjectAddress *referenced, SharedDependencyType deptype)
Definition: pg_shdepend.c:120
void table_close(Relation relation, LOCKMODE lockmode)
Definition: table.c:167
void systable_endscan(SysScanDesc sysscan)
Definition: genam.c:569
#define GETSTRUCT(TUP)
Definition: htup_details.h:655
#define RelationGetDescr(relation)
Definition: rel.h:483
#define PointerGetDatum(X)
Definition: postgres.h:556
#define DatumGetObjectId(X)
Definition: postgres.h:500
long deleteDependencyRecordsFor(Oid classId, Oid objectId, bool skipExtensionDeps)
Definition: pg_depend.c:272
#define ACL_DELETE_CHR
Definition: acl.h:140
ArrayType * construct_array(Datum *elems, int nelems, Oid elmtype, int elmlen, bool elmbyval, char elmalign)
Definition: arrayfuncs.c:3313
#define AccessShareLock
Definition: lockdefs.h:36
void addNSItemToQuery(ParseState *pstate, ParseNamespaceItem *nsitem, bool addToJoinList, bool addToRelNameSpace, bool addToVarNameSpace)
Definition: nodes.h:527
int errcode(int sqlerrcode)
Definition: elog.c:691
void * stringToNode(const char *str)
Definition: read.c:89
void recordDependencyOn(const ObjectAddress *depender, const ObjectAddress *referenced, DependencyType behavior)
Definition: pg_depend.c:46
void heap_freetuple(HeapTuple htup)
Definition: heaptuple.c:1338
unsigned int Oid
Definition: postgres_ext.h:31
SysScanDesc systable_beginscan(Relation heapRelation, Oid indexId, bool indexOK, Snapshot snapshot, int nkeys, ScanKey key)
Definition: genam.c:357
RangeVar * table
Definition: parsenodes.h:2403
ParseNamespaceItem * addRangeTableEntryForRelation(ParseState *pstate, Relation rel, int lockmode, Alias *alias, bool inh, bool inFromCl)
ParseState * make_parsestate(ParseState *parentParseState)
Definition: parse_node.c:43
void assign_expr_collations(ParseState *pstate, Node *expr)
HeapTuple systable_getnext(SysScanDesc sysscan)
Definition: genam.c:476
char * policy_name
Definition: parsenodes.h:2402
#define ObjectIdGetDatum(X)
Definition: postgres.h:507
#define ERROR
Definition: elog.h:43
Relation relation_open(Oid relationId, LOCKMODE lockmode)
Definition: relation.c:48
#define ARR_DIMS(a)
Definition: array.h:282
ItemPointerData t_self
Definition: htup.h:65
#define ARR_DATA_PTR(a)
Definition: array.h:310
#define NoLock
Definition: lockdefs.h:34
#define RowExclusiveLock
Definition: lockdefs.h:38
#define CStringGetDatum(X)
Definition: postgres.h:578
void recordDependencyOnExpr(const ObjectAddress *depender, Node *expr, List *rtable, DependencyType behavior)
Definition: dependency.c:1689
#define RelationGetRelationName(relation)
Definition: rel.h:491
Oid RangeVarGetRelidExtended(const RangeVar *relation, LOCKMODE lockmode, uint32 flags, RangeVarGetRelidCallback callback, void *callback_arg)
Definition: namespace.c:236
#define InvokeObjectPostAlterHook(classId, objectId, subId)
Definition: objectaccess.h:175
void deleteSharedDependencyRecordsFor(Oid classId, Oid objectId, int32 objectSubId)
Definition: pg_shdepend.c:945
#define heap_getattr(tup, attnum, tupleDesc, isnull)
Definition: htup_details.h:762
#define ACL_SELECT_CHR
Definition: acl.h:138
#define TextDatumGetCString(d)
Definition: builtins.h:87
uintptr_t Datum
Definition: postgres.h:367
#define DatumGetChar(X)
Definition: postgres.h:409
#define DatumGetArrayTypePCopy(X)
Definition: array.h:250
FormData_pg_policy * Form_pg_policy
Definition: pg_policy.h:50
#define ereport(elevel,...)
Definition: elog.h:155
#define HeapTupleIsValid(tuple)
Definition: htup.h:78
void relation_close(Relation relation, LOCKMODE lockmode)
Definition: relation.c:206
#define Assert(condition)
Definition: c.h:800
#define PolicyPolrelidPolnameIndexId
Definition: pg_policy.h:57
Node * transformWhereClause(ParseState *pstate, Node *clause, ParseExprKind exprKind, const char *constructName)
static Datum * policy_role_list_to_array(List *roles, int *num_roles)
Definition: policy.c:139
void CatalogTupleUpdate(Relation heapRel, ItemPointer otid, HeapTuple tup)
Definition: indexing.c:301
void CacheInvalidateRelcache(Relation relation)
Definition: inval.c:1278
static Datum values[MAXATTR]
Definition: bootstrap.c:165
#define AccessExclusiveLock
Definition: lockdefs.h:45
void * palloc(Size size)
Definition: mcxt.c:950
int errmsg(const char *fmt,...)
Definition: elog.c:902
static void RangeVarCallbackForPolicy(const RangeVar *rv, Oid relid, Oid oldrelid, void *arg)
Definition: policy.c:66
int i
void ScanKeyInit(ScanKey entry, AttrNumber attributeNumber, StrategyNumber strategy, RegProcedure procedure, Datum argument)
Definition: scankey.c:76
#define CStringGetTextDatum(s)
Definition: builtins.h:86
char * nodeToString(const void *obj)
Definition: outfuncs.c:4377
#define ACL_ID_PUBLIC
Definition: acl.h:46
#define copyObject(obj)
Definition: nodes.h:643
void free_parsestate(ParseState *pstate)
Definition: parse_node.c:76
Relation table_open(Oid relationId, LOCKMODE lockmode)
Definition: table.c:39
HeapTuple heap_modify_tuple(HeapTuple tuple, TupleDesc tupleDesc, Datum *replValues, bool *replIsnull, bool *doReplace)
Definition: heaptuple.c:1113
Definition: pg_list.h:50
#define BTEqualStrategyNumber
Definition: stratnum.h:31
List * p_rtable
Definition: parse_node.h:180

◆ CreatePolicy()

ObjectAddress CreatePolicy ( CreatePolicyStmt stmt)

Definition at line 670 of file policy.c.

References AccessExclusiveLock, AccessShareLock, ACL_DELETE_CHR, ACL_ID_PUBLIC, ACL_INSERT_CHR, ACL_SELECT_CHR, addNSItemToQuery(), addRangeTableEntryForRelation(), assign_expr_collations(), BoolGetDatum, BTEqualStrategyNumber, CacheInvalidateRelcache(), CatalogTupleInsert(), CharGetDatum, ObjectAddress::classId, CreatePolicyStmt::cmd_name, construct_array(), copyObject, CStringGetDatum, CStringGetTextDatum, DatumGetObjectId, DEPENDENCY_AUTO, DEPENDENCY_NORMAL, DirectFunctionCall1, ereport, errcode(), ERRCODE_DUPLICATE_OBJECT, errmsg(), ERROR, EXPR_KIND_POLICY, free_parsestate(), GetNewOidWithIndex(), heap_form_tuple(), heap_freetuple(), HeapTupleIsValid, i, InvokeObjectPostCreateHook, make_parsestate(), namein(), nodeToString(), NoLock, ObjectAddress::objectId, ObjectIdGetDatum, ObjectAddress::objectSubId, ParseState::p_rtable, parse_policy_command(), PointerGetDatum, policy_role_list_to_array(), PolicyOidIndexId, PolicyPolrelidPolnameIndexId, CreatePolicyStmt::qual, RangeVarCallbackForPolicy(), RangeVarGetRelidExtended(), recordDependencyOn(), recordDependencyOnExpr(), recordSharedDependencyOn(), relation_close(), relation_open(), RelationGetDescr, RelationGetRelationName, CreatePolicyStmt::roles, RowExclusiveLock, ScanKeyInit(), SHARED_DEPENDENCY_POLICY, systable_beginscan(), systable_endscan(), systable_getnext(), CreatePolicyStmt::table, table_close(), table_open(), transformWhereClause(), values, and CreatePolicyStmt::with_check.

Referenced by ProcessUtilitySlow().

671 {
672  Relation pg_policy_rel;
673  Oid policy_id;
674  Relation target_table;
675  Oid table_id;
676  char polcmd;
677  Datum *role_oids;
678  int nitems = 0;
679  ArrayType *role_ids;
680  ParseState *qual_pstate;
681  ParseState *with_check_pstate;
682  ParseNamespaceItem *nsitem;
683  Node *qual;
684  Node *with_check_qual;
685  ScanKeyData skey[2];
686  SysScanDesc sscan;
687  HeapTuple policy_tuple;
688  Datum values[Natts_pg_policy];
689  bool isnull[Natts_pg_policy];
690  ObjectAddress target;
691  ObjectAddress myself;
692  int i;
693 
694  /* Parse command */
695  polcmd = parse_policy_command(stmt->cmd_name);
696 
697  /*
698  * If the command is SELECT or DELETE then WITH CHECK should be NULL.
699  */
700  if ((polcmd == ACL_SELECT_CHR || polcmd == ACL_DELETE_CHR)
701  && stmt->with_check != NULL)
702  ereport(ERROR,
703  (errcode(ERRCODE_SYNTAX_ERROR),
704  errmsg("WITH CHECK cannot be applied to SELECT or DELETE")));
705 
706  /*
707  * If the command is INSERT then WITH CHECK should be the only expression
708  * provided.
709  */
710  if (polcmd == ACL_INSERT_CHR && stmt->qual != NULL)
711  ereport(ERROR,
712  (errcode(ERRCODE_SYNTAX_ERROR),
713  errmsg("only WITH CHECK expression allowed for INSERT")));
714 
715  /* Collect role ids */
716  role_oids = policy_role_list_to_array(stmt->roles, &nitems);
717  role_ids = construct_array(role_oids, nitems, OIDOID,
718  sizeof(Oid), true, TYPALIGN_INT);
719 
720  /* Parse the supplied clause */
721  qual_pstate = make_parsestate(NULL);
722  with_check_pstate = make_parsestate(NULL);
723 
724  /* zero-clear */
725  memset(values, 0, sizeof(values));
726  memset(isnull, 0, sizeof(isnull));
727 
728  /* Get id of table. Also handles permissions checks. */
730  0,
732  (void *) stmt);
733 
734  /* Open target_table to build quals. No additional lock is necessary. */
735  target_table = relation_open(table_id, NoLock);
736 
737  /* Add for the regular security quals */
738  nsitem = addRangeTableEntryForRelation(qual_pstate, target_table,
740  NULL, false, false);
741  addNSItemToQuery(qual_pstate, nsitem, false, true, true);
742 
743  /* Add for the with-check quals */
744  nsitem = addRangeTableEntryForRelation(with_check_pstate, target_table,
746  NULL, false, false);
747  addNSItemToQuery(with_check_pstate, nsitem, false, true, true);
748 
749  qual = transformWhereClause(qual_pstate,
750  copyObject(stmt->qual),
752  "POLICY");
753 
754  with_check_qual = transformWhereClause(with_check_pstate,
755  copyObject(stmt->with_check),
757  "POLICY");
758 
759  /* Fix up collation information */
760  assign_expr_collations(qual_pstate, qual);
761  assign_expr_collations(with_check_pstate, with_check_qual);
762 
763  /* Open pg_policy catalog */
764  pg_policy_rel = table_open(PolicyRelationId, RowExclusiveLock);
765 
766  /* Set key - policy's relation id. */
767  ScanKeyInit(&skey[0],
768  Anum_pg_policy_polrelid,
769  BTEqualStrategyNumber, F_OIDEQ,
770  ObjectIdGetDatum(table_id));
771 
772  /* Set key - policy's name. */
773  ScanKeyInit(&skey[1],
774  Anum_pg_policy_polname,
775  BTEqualStrategyNumber, F_NAMEEQ,
777 
778  sscan = systable_beginscan(pg_policy_rel,
779  PolicyPolrelidPolnameIndexId, true, NULL, 2,
780  skey);
781 
782  policy_tuple = systable_getnext(sscan);
783 
784  /* Complain if the policy name already exists for the table */
785  if (HeapTupleIsValid(policy_tuple))
786  ereport(ERROR,
788  errmsg("policy \"%s\" for table \"%s\" already exists",
789  stmt->policy_name, RelationGetRelationName(target_table))));
790 
791  policy_id = GetNewOidWithIndex(pg_policy_rel, PolicyOidIndexId,
792  Anum_pg_policy_oid);
793  values[Anum_pg_policy_oid - 1] = ObjectIdGetDatum(policy_id);
794  values[Anum_pg_policy_polrelid - 1] = ObjectIdGetDatum(table_id);
795  values[Anum_pg_policy_polname - 1] = DirectFunctionCall1(namein,
797  values[Anum_pg_policy_polcmd - 1] = CharGetDatum(polcmd);
798  values[Anum_pg_policy_polpermissive - 1] = BoolGetDatum(stmt->permissive);
799  values[Anum_pg_policy_polroles - 1] = PointerGetDatum(role_ids);
800 
801  /* Add qual if present. */
802  if (qual)
803  values[Anum_pg_policy_polqual - 1] = CStringGetTextDatum(nodeToString(qual));
804  else
805  isnull[Anum_pg_policy_polqual - 1] = true;
806 
807  /* Add WITH CHECK qual if present */
808  if (with_check_qual)
809  values[Anum_pg_policy_polwithcheck - 1] = CStringGetTextDatum(nodeToString(with_check_qual));
810  else
811  isnull[Anum_pg_policy_polwithcheck - 1] = true;
812 
813  policy_tuple = heap_form_tuple(RelationGetDescr(pg_policy_rel), values,
814  isnull);
815 
816  CatalogTupleInsert(pg_policy_rel, policy_tuple);
817 
818  /* Record Dependencies */
819  target.classId = RelationRelationId;
820  target.objectId = table_id;
821  target.objectSubId = 0;
822 
823  myself.classId = PolicyRelationId;
824  myself.objectId = policy_id;
825  myself.objectSubId = 0;
826 
827  recordDependencyOn(&myself, &target, DEPENDENCY_AUTO);
828 
829  recordDependencyOnExpr(&myself, qual, qual_pstate->p_rtable,
831 
832  recordDependencyOnExpr(&myself, with_check_qual,
833  with_check_pstate->p_rtable, DEPENDENCY_NORMAL);
834 
835  /* Register role dependencies */
836  target.classId = AuthIdRelationId;
837  target.objectSubId = 0;
838  for (i = 0; i < nitems; i++)
839  {
840  target.objectId = DatumGetObjectId(role_oids[i]);
841  /* no dependency if public */
842  if (target.objectId != ACL_ID_PUBLIC)
843  recordSharedDependencyOn(&myself, &target,
845  }
846 
847  InvokeObjectPostCreateHook(PolicyRelationId, policy_id, 0);
848 
849  /* Invalidate Relation Cache */
850  CacheInvalidateRelcache(target_table);
851 
852  /* Clean up. */
853  heap_freetuple(policy_tuple);
854  free_parsestate(qual_pstate);
855  free_parsestate(with_check_pstate);
856  systable_endscan(sscan);
857  relation_close(target_table, NoLock);
858  table_close(pg_policy_rel, RowExclusiveLock);
859 
860  return myself;
861 }
Oid GetNewOidWithIndex(Relation relation, Oid indexId, AttrNumber oidcolumn)
Definition: catalog.c:315
#define ACL_INSERT_CHR
Definition: acl.h:137
void recordSharedDependencyOn(ObjectAddress *depender, ObjectAddress *referenced, SharedDependencyType deptype)
Definition: pg_shdepend.c:120
Datum namein(PG_FUNCTION_ARGS)
Definition: name.c:48
void table_close(Relation relation, LOCKMODE lockmode)
Definition: table.c:167
void systable_endscan(SysScanDesc sysscan)
Definition: genam.c:569
#define PolicyOidIndexId
Definition: pg_policy.h:55
#define InvokeObjectPostCreateHook(classId, objectId, subId)
Definition: objectaccess.h:151
#define RelationGetDescr(relation)
Definition: rel.h:483
#define PointerGetDatum(X)
Definition: postgres.h:556
#define DatumGetObjectId(X)
Definition: postgres.h:500
#define ACL_DELETE_CHR
Definition: acl.h:140
ArrayType * construct_array(Datum *elems, int nelems, Oid elmtype, int elmlen, bool elmbyval, char elmalign)
Definition: arrayfuncs.c:3313
#define AccessShareLock
Definition: lockdefs.h:36
void addNSItemToQuery(ParseState *pstate, ParseNamespaceItem *nsitem, bool addToJoinList, bool addToRelNameSpace, bool addToVarNameSpace)
Definition: nodes.h:527
int errcode(int sqlerrcode)
Definition: elog.c:691
static char parse_policy_command(const char *cmd_name)
Definition: policy.c:110
void recordDependencyOn(const ObjectAddress *depender, const ObjectAddress *referenced, DependencyType behavior)
Definition: pg_depend.c:46
HeapTuple heap_form_tuple(TupleDesc tupleDescriptor, Datum *values, bool *isnull)
Definition: heaptuple.c:1020
#define DirectFunctionCall1(func, arg1)
Definition: fmgr.h:626
void heap_freetuple(HeapTuple htup)
Definition: heaptuple.c:1338
unsigned int Oid
Definition: postgres_ext.h:31
SysScanDesc systable_beginscan(Relation heapRelation, Oid indexId, bool indexOK, Snapshot snapshot, int nkeys, ScanKey key)
Definition: genam.c:357
ParseNamespaceItem * addRangeTableEntryForRelation(ParseState *pstate, Relation rel, int lockmode, Alias *alias, bool inh, bool inFromCl)
ParseState * make_parsestate(ParseState *parentParseState)
Definition: parse_node.c:43
void assign_expr_collations(ParseState *pstate, Node *expr)
HeapTuple systable_getnext(SysScanDesc sysscan)
Definition: genam.c:476
#define ObjectIdGetDatum(X)
Definition: postgres.h:507
#define ERROR
Definition: elog.h:43
Relation relation_open(Oid relationId, LOCKMODE lockmode)
Definition: relation.c:48
#define NoLock
Definition: lockdefs.h:34
#define RowExclusiveLock
Definition: lockdefs.h:38
#define CStringGetDatum(X)
Definition: postgres.h:578
void recordDependencyOnExpr(const ObjectAddress *depender, Node *expr, List *rtable, DependencyType behavior)
Definition: dependency.c:1689
#define RelationGetRelationName(relation)
Definition: rel.h:491
Oid RangeVarGetRelidExtended(const RangeVar *relation, LOCKMODE lockmode, uint32 flags, RangeVarGetRelidCallback callback, void *callback_arg)
Definition: namespace.c:236
#define ACL_SELECT_CHR
Definition: acl.h:138
uintptr_t Datum
Definition: postgres.h:367
#define BoolGetDatum(X)
Definition: postgres.h:402
#define ereport(elevel,...)
Definition: elog.h:155
#define HeapTupleIsValid(tuple)
Definition: htup.h:78
void relation_close(Relation relation, LOCKMODE lockmode)
Definition: relation.c:206
#define PolicyPolrelidPolnameIndexId
Definition: pg_policy.h:57
Node * transformWhereClause(ParseState *pstate, Node *clause, ParseExprKind exprKind, const char *constructName)
static Datum * policy_role_list_to_array(List *roles, int *num_roles)
Definition: policy.c:139
#define CharGetDatum(X)
Definition: postgres.h:416
RangeVar * table
Definition: parsenodes.h:2387
void CacheInvalidateRelcache(Relation relation)
Definition: inval.c:1278
static Datum values[MAXATTR]
Definition: bootstrap.c:165
#define AccessExclusiveLock
Definition: lockdefs.h:45
int errmsg(const char *fmt,...)
Definition: elog.c:902
static void RangeVarCallbackForPolicy(const RangeVar *rv, Oid relid, Oid oldrelid, void *arg)
Definition: policy.c:66
int i
void ScanKeyInit(ScanKey entry, AttrNumber attributeNumber, StrategyNumber strategy, RegProcedure procedure, Datum argument)
Definition: scankey.c:76
#define CStringGetTextDatum(s)
Definition: builtins.h:86
char * nodeToString(const void *obj)
Definition: outfuncs.c:4377
#define ACL_ID_PUBLIC
Definition: acl.h:46
#define copyObject(obj)
Definition: nodes.h:643
void free_parsestate(ParseState *pstate)
Definition: parse_node.c:76
Relation table_open(Oid relationId, LOCKMODE lockmode)
Definition: table.c:39
#define ERRCODE_DUPLICATE_OBJECT
Definition: streamutil.c:32
void CatalogTupleInsert(Relation heapRel, HeapTuple tup)
Definition: indexing.c:221
#define BTEqualStrategyNumber
Definition: stratnum.h:31
List * p_rtable
Definition: parse_node.h:180

◆ get_relation_policy_oid()

Oid get_relation_policy_oid ( Oid  relid,
const char *  policy_name,
bool  missing_ok 
)

Definition at line 1307 of file policy.c.

References AccessShareLock, BTEqualStrategyNumber, CStringGetDatum, ereport, errcode(), errmsg(), ERROR, get_rel_name(), GETSTRUCT, HeapTupleIsValid, InvalidOid, ObjectIdGetDatum, PolicyPolrelidPolnameIndexId, ScanKeyInit(), systable_beginscan(), systable_endscan(), systable_getnext(), table_close(), and table_open().

Referenced by get_object_address_relobject().

1308 {
1309  Relation pg_policy_rel;
1310  ScanKeyData skey[2];
1311  SysScanDesc sscan;
1312  HeapTuple policy_tuple;
1313  Oid policy_oid;
1314 
1315  pg_policy_rel = table_open(PolicyRelationId, AccessShareLock);
1316 
1317  /* Add key - policy's relation id. */
1318  ScanKeyInit(&skey[0],
1319  Anum_pg_policy_polrelid,
1320  BTEqualStrategyNumber, F_OIDEQ,
1321  ObjectIdGetDatum(relid));
1322 
1323  /* Add key - policy's name. */
1324  ScanKeyInit(&skey[1],
1325  Anum_pg_policy_polname,
1326  BTEqualStrategyNumber, F_NAMEEQ,
1327  CStringGetDatum(policy_name));
1328 
1329  sscan = systable_beginscan(pg_policy_rel,
1330  PolicyPolrelidPolnameIndexId, true, NULL, 2,
1331  skey);
1332 
1333  policy_tuple = systable_getnext(sscan);
1334 
1335  if (!HeapTupleIsValid(policy_tuple))
1336  {
1337  if (!missing_ok)
1338  ereport(ERROR,
1339  (errcode(ERRCODE_UNDEFINED_OBJECT),
1340  errmsg("policy \"%s\" for table \"%s\" does not exist",
1341  policy_name, get_rel_name(relid))));
1342 
1343  policy_oid = InvalidOid;
1344  }
1345  else
1346  policy_oid = ((Form_pg_policy) GETSTRUCT(policy_tuple))->oid;
1347 
1348  /* Clean up. */
1349  systable_endscan(sscan);
1350  table_close(pg_policy_rel, AccessShareLock);
1351 
1352  return policy_oid;
1353 }
void table_close(Relation relation, LOCKMODE lockmode)
Definition: table.c:167
void systable_endscan(SysScanDesc sysscan)
Definition: genam.c:569
#define GETSTRUCT(TUP)
Definition: htup_details.h:655
#define AccessShareLock
Definition: lockdefs.h:36
int errcode(int sqlerrcode)
Definition: elog.c:691
unsigned int Oid
Definition: postgres_ext.h:31
SysScanDesc systable_beginscan(Relation heapRelation, Oid indexId, bool indexOK, Snapshot snapshot, int nkeys, ScanKey key)
Definition: genam.c:357
HeapTuple systable_getnext(SysScanDesc sysscan)
Definition: genam.c:476
#define ObjectIdGetDatum(X)
Definition: postgres.h:507
#define ERROR
Definition: elog.h:43
#define CStringGetDatum(X)
Definition: postgres.h:578
#define InvalidOid
Definition: postgres_ext.h:36
FormData_pg_policy * Form_pg_policy
Definition: pg_policy.h:50
#define ereport(elevel,...)
Definition: elog.h:155
#define HeapTupleIsValid(tuple)
Definition: htup.h:78
#define PolicyPolrelidPolnameIndexId
Definition: pg_policy.h:57
int errmsg(const char *fmt,...)
Definition: elog.c:902
void ScanKeyInit(ScanKey entry, AttrNumber attributeNumber, StrategyNumber strategy, RegProcedure procedure, Datum argument)
Definition: scankey.c:76
Relation table_open(Oid relationId, LOCKMODE lockmode)
Definition: table.c:39
char * get_rel_name(Oid relid)
Definition: lsyscache.c:1845
#define BTEqualStrategyNumber
Definition: stratnum.h:31

◆ parse_policy_command()

static char parse_policy_command ( const char *  cmd_name)
static

Definition at line 110 of file policy.c.

References ACL_DELETE_CHR, ACL_INSERT_CHR, ACL_SELECT_CHR, ACL_UPDATE_CHR, elog, and ERROR.

Referenced by CreatePolicy().

111 {
112  char polcmd;
113 
114  if (!cmd_name)
115  elog(ERROR, "unrecognized policy command");
116 
117  if (strcmp(cmd_name, "all") == 0)
118  polcmd = '*';
119  else if (strcmp(cmd_name, "select") == 0)
120  polcmd = ACL_SELECT_CHR;
121  else if (strcmp(cmd_name, "insert") == 0)
122  polcmd = ACL_INSERT_CHR;
123  else if (strcmp(cmd_name, "update") == 0)
124  polcmd = ACL_UPDATE_CHR;
125  else if (strcmp(cmd_name, "delete") == 0)
126  polcmd = ACL_DELETE_CHR;
127  else
128  elog(ERROR, "unrecognized policy command");
129 
130  return polcmd;
131 }
#define ACL_INSERT_CHR
Definition: acl.h:137
#define ACL_DELETE_CHR
Definition: acl.h:140
#define ERROR
Definition: elog.h:43
#define ACL_SELECT_CHR
Definition: acl.h:138
#define ACL_UPDATE_CHR
Definition: acl.h:139
#define elog(elevel,...)
Definition: elog.h:228

◆ policy_role_list_to_array()

static Datum * policy_role_list_to_array ( List roles,
int *  num_roles 
)
static

Definition at line 139 of file policy.c.

References ACL_ID_PUBLIC, ereport, errcode(), errhint(), errmsg(), get_rolespec_oid(), i, lfirst, list_length(), NIL, ObjectIdGetDatum, palloc(), ROLESPEC_PUBLIC, RoleSpec::roletype, and WARNING.

Referenced by AlterPolicy(), and CreatePolicy().

140 {
141  Datum *role_oids;
142  ListCell *cell;
143  int i = 0;
144 
145  /* Handle no roles being passed in as being for public */
146  if (roles == NIL)
147  {
148  *num_roles = 1;
149  role_oids = (Datum *) palloc(*num_roles * sizeof(Datum));
150  role_oids[0] = ObjectIdGetDatum(ACL_ID_PUBLIC);
151 
152  return role_oids;
153  }
154 
155  *num_roles = list_length(roles);
156  role_oids = (Datum *) palloc(*num_roles * sizeof(Datum));
157 
158  foreach(cell, roles)
159  {
160  RoleSpec *spec = lfirst(cell);
161 
162  /*
163  * PUBLIC covers all roles, so it only makes sense alone.
164  */
165  if (spec->roletype == ROLESPEC_PUBLIC)
166  {
167  if (*num_roles != 1)
168  {
170  (errcode(ERRCODE_INVALID_PARAMETER_VALUE),
171  errmsg("ignoring specified roles other than PUBLIC"),
172  errhint("All roles are members of the PUBLIC role.")));
173  *num_roles = 1;
174  }
175  role_oids[0] = ObjectIdGetDatum(ACL_ID_PUBLIC);
176 
177  return role_oids;
178  }
179  else
180  role_oids[i++] =
181  ObjectIdGetDatum(get_rolespec_oid(spec, false));
182  }
183 
184  return role_oids;
185 }
#define NIL
Definition: pg_list.h:65
int errhint(const char *fmt,...)
Definition: elog.c:1149
int errcode(int sqlerrcode)
Definition: elog.c:691
#define ObjectIdGetDatum(X)
Definition: postgres.h:507
#define WARNING
Definition: elog.h:40
uintptr_t Datum
Definition: postgres.h:367
RoleSpecType roletype
Definition: parsenodes.h:329
Oid get_rolespec_oid(const RoleSpec *role, bool missing_ok)
Definition: acl.c:5209
#define ereport(elevel,...)
Definition: elog.h:155
#define lfirst(lc)
Definition: pg_list.h:169
static int list_length(const List *l)
Definition: pg_list.h:149
void * palloc(Size size)
Definition: mcxt.c:950
int errmsg(const char *fmt,...)
Definition: elog.c:902
int i
#define ACL_ID_PUBLIC
Definition: acl.h:46

◆ RangeVarCallbackForPolicy()

static void RangeVarCallbackForPolicy ( const RangeVar rv,
Oid  relid,
Oid  oldrelid,
void *  arg 
)
static

Definition at line 66 of file policy.c.

References aclcheck_error(), ACLCHECK_NOT_OWNER, allowSystemTableMods, ereport, errcode(), errmsg(), ERROR, get_rel_relkind(), get_relkind_objtype(), GETSTRUCT, GetUserId(), HeapTupleIsValid, IsSystemClass(), ObjectIdGetDatum, pg_class_ownercheck(), ReleaseSysCache(), RangeVar::relname, RELOID, and SearchSysCache1().

Referenced by AlterPolicy(), CreatePolicy(), and rename_policy().

68 {
69  HeapTuple tuple;
70  Form_pg_class classform;
71  char relkind;
72 
73  tuple = SearchSysCache1(RELOID, ObjectIdGetDatum(relid));
74  if (!HeapTupleIsValid(tuple))
75  return;
76 
77  classform = (Form_pg_class) GETSTRUCT(tuple);
78  relkind = classform->relkind;
79 
80  /* Must own relation. */
81  if (!pg_class_ownercheck(relid, GetUserId()))
83 
84  /* No system table modifications unless explicitly allowed. */
85  if (!allowSystemTableMods && IsSystemClass(relid, classform))
86  ereport(ERROR,
87  (errcode(ERRCODE_INSUFFICIENT_PRIVILEGE),
88  errmsg("permission denied: \"%s\" is a system catalog",
89  rv->relname)));
90 
91  /* Relation type MUST be a table. */
92  if (relkind != RELKIND_RELATION && relkind != RELKIND_PARTITIONED_TABLE)
93  ereport(ERROR,
94  (errcode(ERRCODE_WRONG_OBJECT_TYPE),
95  errmsg("\"%s\" is not a table", rv->relname)));
96 
97  ReleaseSysCache(tuple);
98 }
#define GETSTRUCT(TUP)
Definition: htup_details.h:655
Oid GetUserId(void)
Definition: miscinit.c:476
char get_rel_relkind(Oid relid)
Definition: lsyscache.c:1920
int errcode(int sqlerrcode)
Definition: elog.c:691
bool IsSystemClass(Oid relid, Form_pg_class reltuple)
Definition: catalog.c:78
char * relname
Definition: primnodes.h:68
void aclcheck_error(AclResult aclerr, ObjectType objtype, const char *objectname)
Definition: aclchk.c:3294
#define ObjectIdGetDatum(X)
Definition: postgres.h:507
#define ERROR
Definition: elog.h:43
HeapTuple SearchSysCache1(int cacheId, Datum key1)
Definition: syscache.c:1115
void ReleaseSysCache(HeapTuple tuple)
Definition: syscache.c:1163
bool allowSystemTableMods
Definition: globals.c:120
#define ereport(elevel,...)
Definition: elog.h:155
#define HeapTupleIsValid(tuple)
Definition: htup.h:78
bool pg_class_ownercheck(Oid class_oid, Oid roleid)
Definition: aclchk.c:4687
FormData_pg_class * Form_pg_class
Definition: pg_class.h:153
int errmsg(const char *fmt,...)
Definition: elog.c:902
ObjectType get_relkind_objtype(char relkind)

◆ relation_has_policies()

bool relation_has_policies ( Relation  rel)

Definition at line 1359 of file policy.c.

References AccessShareLock, BTEqualStrategyNumber, HeapTupleIsValid, ObjectIdGetDatum, PolicyPolrelidPolnameIndexId, RelationGetRelid, ScanKeyInit(), systable_beginscan(), systable_endscan(), systable_getnext(), table_close(), and table_open().

Referenced by DefineQueryRewrite().

1360 {
1361  Relation catalog;
1362  ScanKeyData skey;
1363  SysScanDesc sscan;
1364  HeapTuple policy_tuple;
1365  bool ret = false;
1366 
1367  catalog = table_open(PolicyRelationId, AccessShareLock);
1368  ScanKeyInit(&skey,
1369  Anum_pg_policy_polrelid,
1370  BTEqualStrategyNumber, F_OIDEQ,
1372  sscan = systable_beginscan(catalog, PolicyPolrelidPolnameIndexId, true,
1373  NULL, 1, &skey);
1374  policy_tuple = systable_getnext(sscan);
1375  if (HeapTupleIsValid(policy_tuple))
1376  ret = true;
1377 
1378  systable_endscan(sscan);
1379  table_close(catalog, AccessShareLock);
1380 
1381  return ret;
1382 }
void table_close(Relation relation, LOCKMODE lockmode)
Definition: table.c:167
void systable_endscan(SysScanDesc sysscan)
Definition: genam.c:569
#define AccessShareLock
Definition: lockdefs.h:36
SysScanDesc systable_beginscan(Relation heapRelation, Oid indexId, bool indexOK, Snapshot snapshot, int nkeys, ScanKey key)
Definition: genam.c:357
HeapTuple systable_getnext(SysScanDesc sysscan)
Definition: genam.c:476
#define ObjectIdGetDatum(X)
Definition: postgres.h:507
#define HeapTupleIsValid(tuple)
Definition: htup.h:78
#define PolicyPolrelidPolnameIndexId
Definition: pg_policy.h:57
void ScanKeyInit(ScanKey entry, AttrNumber attributeNumber, StrategyNumber strategy, RegProcedure procedure, Datum argument)
Definition: scankey.c:76
Relation table_open(Oid relationId, LOCKMODE lockmode)
Definition: table.c:39
#define RelationGetRelid(relation)
Definition: rel.h:457
#define BTEqualStrategyNumber
Definition: stratnum.h:31

◆ RelationBuildRowSecurity()

void RelationBuildRowSecurity ( Relation  relation)

Definition at line 195 of file policy.c.

References AccessShareLock, ALLOCSET_SMALL_SIZES, AllocSetContextCreate, BTEqualStrategyNumber, CacheMemoryContext, checkExprHasSubLink(), CurrentMemoryContext, DatumGetArrayTypePCopy, elog, ERROR, GETSTRUCT, RowSecurityPolicy::hassublinks, heap_getattr, HeapTupleIsValid, lcons(), MemoryContextAllocZero(), MemoryContextCopyAndSetIdentifier, MemoryContextSetParent(), MemoryContextStrdup(), MemoryContextSwitchTo(), NameStr, ObjectIdGetDatum, RowSecurityPolicy::permissive, pfree(), RowSecurityPolicy::polcmd, RowSecurityDesc::policies, RowSecurityPolicy::policy_name, PolicyPolrelidPolnameIndexId, RowSecurityPolicy::qual, RelationData::rd_rsdesc, RelationGetDescr, RelationGetRelationName, RelationGetRelid, RowSecurityPolicy::roles, RowSecurityDesc::rscxt, ScanKeyInit(), stringToNode(), systable_beginscan(), systable_endscan(), systable_getnext(), table_close(), table_open(), TextDatumGetCString, and RowSecurityPolicy::with_check_qual.

Referenced by RelationBuildDesc(), and RelationCacheInitializePhase3().

196 {
197  MemoryContext rscxt;
199  RowSecurityDesc *rsdesc;
200  Relation catalog;
201  ScanKeyData skey;
202  SysScanDesc sscan;
203  HeapTuple tuple;
204 
205  /*
206  * Create a memory context to hold everything associated with this
207  * relation's row security policy. This makes it easy to clean up during
208  * a relcache flush. However, to cover the possibility of an error
209  * partway through, we don't make the context long-lived till we're done.
210  */
212  "row security descriptor",
215  RelationGetRelationName(relation));
216 
217  rsdesc = MemoryContextAllocZero(rscxt, sizeof(RowSecurityDesc));
218  rsdesc->rscxt = rscxt;
219 
220  /*
221  * Now scan pg_policy for RLS policies associated with this relation.
222  * Because we use the index on (polrelid, polname), we should consistently
223  * visit the rel's policies in name order, at least when system indexes
224  * aren't disabled. This simplifies equalRSDesc().
225  */
226  catalog = table_open(PolicyRelationId, AccessShareLock);
227 
228  ScanKeyInit(&skey,
229  Anum_pg_policy_polrelid,
230  BTEqualStrategyNumber, F_OIDEQ,
232 
233  sscan = systable_beginscan(catalog, PolicyPolrelidPolnameIndexId, true,
234  NULL, 1, &skey);
235 
236  while (HeapTupleIsValid(tuple = systable_getnext(sscan)))
237  {
238  Form_pg_policy policy_form = (Form_pg_policy) GETSTRUCT(tuple);
239  RowSecurityPolicy *policy;
240  Datum datum;
241  bool isnull;
242  char *str_value;
243 
244  policy = MemoryContextAllocZero(rscxt, sizeof(RowSecurityPolicy));
245 
246  /*
247  * Note: we must be sure that pass-by-reference data gets copied into
248  * rscxt. We avoid making that context current over wider spans than
249  * we have to, though.
250  */
251 
252  /* Get policy command */
253  policy->polcmd = policy_form->polcmd;
254 
255  /* Get policy, permissive or restrictive */
256  policy->permissive = policy_form->polpermissive;
257 
258  /* Get policy name */
259  policy->policy_name =
260  MemoryContextStrdup(rscxt, NameStr(policy_form->polname));
261 
262  /* Get policy roles */
263  datum = heap_getattr(tuple, Anum_pg_policy_polroles,
264  RelationGetDescr(catalog), &isnull);
265  /* shouldn't be null, but let's check for luck */
266  if (isnull)
267  elog(ERROR, "unexpected null value in pg_policy.polroles");
268  MemoryContextSwitchTo(rscxt);
269  policy->roles = DatumGetArrayTypePCopy(datum);
270  MemoryContextSwitchTo(oldcxt);
271 
272  /* Get policy qual */
273  datum = heap_getattr(tuple, Anum_pg_policy_polqual,
274  RelationGetDescr(catalog), &isnull);
275  if (!isnull)
276  {
277  str_value = TextDatumGetCString(datum);
278  MemoryContextSwitchTo(rscxt);
279  policy->qual = (Expr *) stringToNode(str_value);
280  MemoryContextSwitchTo(oldcxt);
281  pfree(str_value);
282  }
283  else
284  policy->qual = NULL;
285 
286  /* Get WITH CHECK qual */
287  datum = heap_getattr(tuple, Anum_pg_policy_polwithcheck,
288  RelationGetDescr(catalog), &isnull);
289  if (!isnull)
290  {
291  str_value = TextDatumGetCString(datum);
292  MemoryContextSwitchTo(rscxt);
293  policy->with_check_qual = (Expr *) stringToNode(str_value);
294  MemoryContextSwitchTo(oldcxt);
295  pfree(str_value);
296  }
297  else
298  policy->with_check_qual = NULL;
299 
300  /* We want to cache whether there are SubLinks in these expressions */
301  policy->hassublinks = checkExprHasSubLink((Node *) policy->qual) ||
303 
304  /*
305  * Add this object to list. For historical reasons, the list is built
306  * in reverse order.
307  */
308  MemoryContextSwitchTo(rscxt);
309  rsdesc->policies = lcons(policy, rsdesc->policies);
310  MemoryContextSwitchTo(oldcxt);
311  }
312 
313  systable_endscan(sscan);
314  table_close(catalog, AccessShareLock);
315 
316  /*
317  * Success. Reparent the descriptor's memory context under
318  * CacheMemoryContext so that it will live indefinitely, then attach the
319  * policy descriptor to the relcache entry.
320  */
322 
323  relation->rd_rsdesc = rsdesc;
324 }
#define AllocSetContextCreate
Definition: memutils.h:170
void table_close(Relation relation, LOCKMODE lockmode)
Definition: table.c:167
void systable_endscan(SysScanDesc sysscan)
Definition: genam.c:569
#define GETSTRUCT(TUP)
Definition: htup_details.h:655
bool checkExprHasSubLink(Node *node)
Definition: rewriteManip.c:277
#define RelationGetDescr(relation)
Definition: rel.h:483
void MemoryContextSetParent(MemoryContext context, MemoryContext new_parent)
Definition: mcxt.c:355
#define ALLOCSET_SMALL_SIZES
Definition: memutils.h:202
static MemoryContext MemoryContextSwitchTo(MemoryContext context)
Definition: palloc.h:109
#define AccessShareLock
Definition: lockdefs.h:36
Definition: nodes.h:527
void * stringToNode(const char *str)
Definition: read.c:89
SysScanDesc systable_beginscan(Relation heapRelation, Oid indexId, bool indexOK, Snapshot snapshot, int nkeys, ScanKey key)
Definition: genam.c:357
HeapTuple systable_getnext(SysScanDesc sysscan)
Definition: genam.c:476
void pfree(void *pointer)
Definition: mcxt.c:1057
#define ObjectIdGetDatum(X)
Definition: postgres.h:507
#define ERROR
Definition: elog.h:43
#define MemoryContextCopyAndSetIdentifier(cxt, id)
Definition: memutils.h:97
Expr * with_check_qual
Definition: rowsecurity.h:27
#define RelationGetRelationName(relation)
Definition: rel.h:491
ArrayType * roles
Definition: rowsecurity.h:24
MemoryContext CurrentMemoryContext
Definition: mcxt.c:38
struct RowSecurityDesc * rd_rsdesc
Definition: rel.h:118
MemoryContext rscxt
Definition: rowsecurity.h:33
#define heap_getattr(tup, attnum, tupleDesc, isnull)
Definition: htup_details.h:762
#define TextDatumGetCString(d)
Definition: builtins.h:87
uintptr_t Datum
Definition: postgres.h:367
#define DatumGetArrayTypePCopy(X)
Definition: array.h:250
void * MemoryContextAllocZero(MemoryContext context, Size size)
Definition: mcxt.c:840
FormData_pg_policy * Form_pg_policy
Definition: pg_policy.h:50
List * lcons(void *datum, List *list)
Definition: list.c:453
#define HeapTupleIsValid(tuple)
Definition: htup.h:78
#define PolicyPolrelidPolnameIndexId
Definition: pg_policy.h:57
char * MemoryContextStrdup(MemoryContext context, const char *string)
Definition: mcxt.c:1174
#define elog(elevel,...)
Definition: elog.h:228
#define NameStr(name)
Definition: c.h:677
void ScanKeyInit(ScanKey entry, AttrNumber attributeNumber, StrategyNumber strategy, RegProcedure procedure, Datum argument)
Definition: scankey.c:76
Relation table_open(Oid relationId, LOCKMODE lockmode)
Definition: table.c:39
#define RelationGetRelid(relation)
Definition: rel.h:457
#define BTEqualStrategyNumber
Definition: stratnum.h:31
MemoryContext CacheMemoryContext
Definition: mcxt.c:47

◆ RemovePolicyById()

void RemovePolicyById ( Oid  policy_id)

Definition at line 334 of file policy.c.

References AccessExclusiveLock, allowSystemTableMods, BTEqualStrategyNumber, CacheInvalidateRelcache(), CatalogTupleDelete(), elog, ereport, errcode(), errmsg(), ERROR, GETSTRUCT, HeapTupleIsValid, IsSystemRelation(), NoLock, ObjectIdGetDatum, PolicyOidIndexId, RelationData::rd_rel, RelationGetRelationName, RowExclusiveLock, ScanKeyInit(), systable_beginscan(), systable_endscan(), systable_getnext(), HeapTupleData::t_self, table_close(), and table_open().

Referenced by doDeletion().

335 {
336  Relation pg_policy_rel;
337  SysScanDesc sscan;
338  ScanKeyData skey[1];
339  HeapTuple tuple;
340  Oid relid;
341  Relation rel;
342 
343  pg_policy_rel = table_open(PolicyRelationId, RowExclusiveLock);
344 
345  /*
346  * Find the policy to delete.
347  */
348  ScanKeyInit(&skey[0],
349  Anum_pg_policy_oid,
350  BTEqualStrategyNumber, F_OIDEQ,
351  ObjectIdGetDatum(policy_id));
352 
353  sscan = systable_beginscan(pg_policy_rel, PolicyOidIndexId, true,
354  NULL, 1, skey);
355 
356  tuple = systable_getnext(sscan);
357 
358  /* If the policy exists, then remove it, otherwise raise an error. */
359  if (!HeapTupleIsValid(tuple))
360  elog(ERROR, "could not find tuple for policy %u", policy_id);
361 
362  /*
363  * Open and exclusive-lock the relation the policy belongs to. (We need
364  * exclusive lock to lock out queries that might otherwise depend on the
365  * set of policies the rel has; furthermore we've got to hold the lock
366  * till commit.)
367  */
368  relid = ((Form_pg_policy) GETSTRUCT(tuple))->polrelid;
369 
370  rel = table_open(relid, AccessExclusiveLock);
371  if (rel->rd_rel->relkind != RELKIND_RELATION &&
372  rel->rd_rel->relkind != RELKIND_PARTITIONED_TABLE)
373  ereport(ERROR,
374  (errcode(ERRCODE_WRONG_OBJECT_TYPE),
375  errmsg("\"%s\" is not a table",
376  RelationGetRelationName(rel))));
377 
379  ereport(ERROR,
380  (errcode(ERRCODE_INSUFFICIENT_PRIVILEGE),
381  errmsg("permission denied: \"%s\" is a system catalog",
382  RelationGetRelationName(rel))));
383 
384  CatalogTupleDelete(pg_policy_rel, &tuple->t_self);
385 
386  systable_endscan(sscan);
387 
388  /*
389  * Note that, unlike some of the other flags in pg_class, relrowsecurity
390  * is not just an indication of if policies exist. When relrowsecurity is
391  * set by a user, then all access to the relation must be through a
392  * policy. If no policy is defined for the relation then a default-deny
393  * policy is created and all records are filtered (except for queries from
394  * the owner).
395  */
397 
398  table_close(rel, NoLock);
399 
400  /* Clean up */
401  table_close(pg_policy_rel, RowExclusiveLock);
402 }
void table_close(Relation relation, LOCKMODE lockmode)
Definition: table.c:167
void systable_endscan(SysScanDesc sysscan)
Definition: genam.c:569
#define GETSTRUCT(TUP)
Definition: htup_details.h:655
#define PolicyOidIndexId
Definition: pg_policy.h:55
bool IsSystemRelation(Relation relation)
Definition: catalog.c:66
int errcode(int sqlerrcode)
Definition: elog.c:691
void CatalogTupleDelete(Relation heapRel, ItemPointer tid)
Definition: indexing.c:350
Form_pg_class rd_rel
Definition: rel.h:110
unsigned int Oid
Definition: postgres_ext.h:31
SysScanDesc systable_beginscan(Relation heapRelation, Oid indexId, bool indexOK, Snapshot snapshot, int nkeys, ScanKey key)
Definition: genam.c:357
HeapTuple systable_getnext(SysScanDesc sysscan)
Definition: genam.c:476
#define ObjectIdGetDatum(X)
Definition: postgres.h:507
#define ERROR
Definition: elog.h:43
ItemPointerData t_self
Definition: htup.h:65
#define NoLock
Definition: lockdefs.h:34
#define RowExclusiveLock
Definition: lockdefs.h:38
#define RelationGetRelationName(relation)
Definition: rel.h:491
bool allowSystemTableMods
Definition: globals.c:120
FormData_pg_policy * Form_pg_policy
Definition: pg_policy.h:50
#define ereport(elevel,...)
Definition: elog.h:155
#define HeapTupleIsValid(tuple)
Definition: htup.h:78
void CacheInvalidateRelcache(Relation relation)
Definition: inval.c:1278
#define AccessExclusiveLock
Definition: lockdefs.h:45
int errmsg(const char *fmt,...)
Definition: elog.c:902
#define elog(elevel,...)
Definition: elog.h:228
void ScanKeyInit(ScanKey entry, AttrNumber attributeNumber, StrategyNumber strategy, RegProcedure procedure, Datum argument)
Definition: scankey.c:76
Relation table_open(Oid relationId, LOCKMODE lockmode)
Definition: table.c:39
#define BTEqualStrategyNumber
Definition: stratnum.h:31

◆ RemoveRoleFromObjectPolicy()

bool RemoveRoleFromObjectPolicy ( Oid  roleid,
Oid  classid,
Oid  policy_id 
)

Definition at line 419 of file policy.c.

References AccessExclusiveLock, AccessShareLock, ACL_ID_PUBLIC, addRangeTableEntryForRelation(), allowSystemTableMods, ARR_DATA_PTR, ARR_DIMS, Assert, BTEqualStrategyNumber, CacheInvalidateRelcache(), CatalogTupleUpdate(), ObjectAddress::classId, construct_array(), DatumGetArrayTypePCopy, DatumGetObjectId, deleteDependencyRecordsFor(), deleteSharedDependencyRecordsFor(), DEPENDENCY_AUTO, DEPENDENCY_NORMAL, elog, ereport, errcode(), errmsg(), ERROR, free_parsestate(), GETSTRUCT, GetUserId(), GetUserNameFromId(), heap_freetuple(), heap_getattr, heap_modify_tuple(), HeapTupleIsValid, i, InvokeObjectPostAlterHook, IsSystemRelation(), make_parsestate(), NameStr, NIL, NoLock, ObjectAddress::objectId, ObjectIdGetDatum, ObjectAddress::objectSubId, ParseState::p_rtable, palloc(), pg_class_ownercheck(), PointerGetDatum, PolicyOidIndexId, RelationData::rd_rel, recordDependencyOn(), recordDependencyOnExpr(), recordSharedDependencyOn(), relation_close(), relation_open(), RelationGetDescr, RelationGetRelationName, RowExclusiveLock, ScanKeyInit(), SHARED_DEPENDENCY_POLICY, stringToNode(), systable_beginscan(), systable_endscan(), systable_getnext(), HeapTupleData::t_self, table_close(), table_open(), TextDatumGetCString, values, and WARNING.

Referenced by shdepDropOwned().

420 {
421  Relation pg_policy_rel;
422  SysScanDesc sscan;
423  ScanKeyData skey[1];
424  HeapTuple tuple;
425  Oid relid;
426  Relation rel;
427  ArrayType *policy_roles;
428  int num_roles;
429  Datum roles_datum;
430  bool attr_isnull;
431  bool noperm = true;
432 
433  Assert(classid == PolicyRelationId);
434 
435  pg_policy_rel = table_open(PolicyRelationId, RowExclusiveLock);
436 
437  /*
438  * Find the policy to update.
439  */
440  ScanKeyInit(&skey[0],
441  Anum_pg_policy_oid,
442  BTEqualStrategyNumber, F_OIDEQ,
443  ObjectIdGetDatum(policy_id));
444 
445  sscan = systable_beginscan(pg_policy_rel, PolicyOidIndexId, true,
446  NULL, 1, skey);
447 
448  tuple = systable_getnext(sscan);
449 
450  /* Raise an error if we don't find the policy. */
451  if (!HeapTupleIsValid(tuple))
452  elog(ERROR, "could not find tuple for policy %u", policy_id);
453 
454  /*
455  * Open and exclusive-lock the relation the policy belongs to.
456  */
457  relid = ((Form_pg_policy) GETSTRUCT(tuple))->polrelid;
458 
459  rel = relation_open(relid, AccessExclusiveLock);
460 
461  if (rel->rd_rel->relkind != RELKIND_RELATION &&
462  rel->rd_rel->relkind != RELKIND_PARTITIONED_TABLE)
463  ereport(ERROR,
464  (errcode(ERRCODE_WRONG_OBJECT_TYPE),
465  errmsg("\"%s\" is not a table",
466  RelationGetRelationName(rel))));
467 
469  ereport(ERROR,
470  (errcode(ERRCODE_INSUFFICIENT_PRIVILEGE),
471  errmsg("permission denied: \"%s\" is a system catalog",
472  RelationGetRelationName(rel))));
473 
474  /* Get the current set of roles */
475  roles_datum = heap_getattr(tuple,
476  Anum_pg_policy_polroles,
477  RelationGetDescr(pg_policy_rel),
478  &attr_isnull);
479 
480  Assert(!attr_isnull);
481 
482  policy_roles = DatumGetArrayTypePCopy(roles_datum);
483 
484  /* We should be removing exactly one entry from the roles array */
485  num_roles = ARR_DIMS(policy_roles)[0] - 1;
486 
487  Assert(num_roles >= 0);
488 
489  /* Must own relation. */
490  if (pg_class_ownercheck(relid, GetUserId()))
491  noperm = false; /* user is allowed to modify this policy */
492  else
494  (errcode(ERRCODE_WARNING_PRIVILEGE_NOT_REVOKED),
495  errmsg("role \"%s\" could not be removed from policy \"%s\" on \"%s\"",
496  GetUserNameFromId(roleid, false),
497  NameStr(((Form_pg_policy) GETSTRUCT(tuple))->polname),
498  RelationGetRelationName(rel))));
499 
500  /*
501  * If multiple roles exist on this policy, then remove the one we were
502  * asked to and leave the rest.
503  */
504  if (!noperm && num_roles > 0)
505  {
506  int i,
507  j;
508  Oid *roles = (Oid *) ARR_DATA_PTR(policy_roles);
509  Datum *role_oids;
510  char *qual_value;
511  Node *qual_expr;
512  List *qual_parse_rtable = NIL;
513  char *with_check_value;
514  Node *with_check_qual;
515  List *with_check_parse_rtable = NIL;
516  Datum values[Natts_pg_policy];
517  bool isnull[Natts_pg_policy];
518  bool replaces[Natts_pg_policy];
519  Datum value_datum;
520  ArrayType *role_ids;
521  HeapTuple new_tuple;
522  ObjectAddress target;
523  ObjectAddress myself;
524 
525  /* zero-clear */
526  memset(values, 0, sizeof(values));
527  memset(replaces, 0, sizeof(replaces));
528  memset(isnull, 0, sizeof(isnull));
529 
530  /*
531  * All of the dependencies will be removed from the policy and then
532  * re-added. In order to get them correct, we need to extract out the
533  * expressions in the policy and construct a parsestate just enough to
534  * build the range table(s) to then pass to recordDependencyOnExpr().
535  */
536 
537  /* Get policy qual, to update dependencies */
538  value_datum = heap_getattr(tuple, Anum_pg_policy_polqual,
539  RelationGetDescr(pg_policy_rel), &attr_isnull);
540  if (!attr_isnull)
541  {
542  ParseState *qual_pstate;
543 
544  /* parsestate is built just to build the range table */
545  qual_pstate = make_parsestate(NULL);
546 
547  qual_value = TextDatumGetCString(value_datum);
548  qual_expr = stringToNode(qual_value);
549 
550  /* Add this rel to the parsestate's rangetable, for dependencies */
551  (void) addRangeTableEntryForRelation(qual_pstate, rel,
553  NULL, false, false);
554 
555  qual_parse_rtable = qual_pstate->p_rtable;
556  free_parsestate(qual_pstate);
557  }
558  else
559  qual_expr = NULL;
560 
561  /* Get WITH CHECK qual, to update dependencies */
562  value_datum = heap_getattr(tuple, Anum_pg_policy_polwithcheck,
563  RelationGetDescr(pg_policy_rel), &attr_isnull);
564  if (!attr_isnull)
565  {
566  ParseState *with_check_pstate;
567 
568  /* parsestate is built just to build the range table */
569  with_check_pstate = make_parsestate(NULL);
570 
571  with_check_value = TextDatumGetCString(value_datum);
572  with_check_qual = stringToNode(with_check_value);
573 
574  /* Add this rel to the parsestate's rangetable, for dependencies */
575  (void) addRangeTableEntryForRelation(with_check_pstate, rel,
577  NULL, false, false);
578 
579  with_check_parse_rtable = with_check_pstate->p_rtable;
580  free_parsestate(with_check_pstate);
581  }
582  else
583  with_check_qual = NULL;
584 
585  /* Rebuild the roles array to then update the pg_policy tuple with */
586  role_oids = (Datum *) palloc(num_roles * sizeof(Datum));
587  for (i = 0, j = 0; i < ARR_DIMS(policy_roles)[0]; i++)
588  /* Copy over all of the roles which are not the one being removed */
589  if (roles[i] != roleid)
590  role_oids[j++] = ObjectIdGetDatum(roles[i]);
591 
592  /* We should have only removed the one role */
593  Assert(j == num_roles);
594 
595  /* This is the array for the new tuple */
596  role_ids = construct_array(role_oids, num_roles, OIDOID,
597  sizeof(Oid), true, TYPALIGN_INT);
598 
599  replaces[Anum_pg_policy_polroles - 1] = true;
600  values[Anum_pg_policy_polroles - 1] = PointerGetDatum(role_ids);
601 
602  new_tuple = heap_modify_tuple(tuple,
603  RelationGetDescr(pg_policy_rel),
604  values, isnull, replaces);
605  CatalogTupleUpdate(pg_policy_rel, &new_tuple->t_self, new_tuple);
606 
607  /* Remove all old dependencies. */
608  deleteDependencyRecordsFor(PolicyRelationId, policy_id, false);
609 
610  /* Record the new set of dependencies */
611  target.classId = RelationRelationId;
612  target.objectId = relid;
613  target.objectSubId = 0;
614 
615  myself.classId = PolicyRelationId;
616  myself.objectId = policy_id;
617  myself.objectSubId = 0;
618 
619  recordDependencyOn(&myself, &target, DEPENDENCY_AUTO);
620 
621  if (qual_expr)
622  recordDependencyOnExpr(&myself, qual_expr, qual_parse_rtable,
624 
625  if (with_check_qual)
626  recordDependencyOnExpr(&myself, with_check_qual,
627  with_check_parse_rtable,
629 
630  /* Remove all the old shared dependencies (roles) */
631  deleteSharedDependencyRecordsFor(PolicyRelationId, policy_id, 0);
632 
633  /* Record the new shared dependencies (roles) */
634  target.classId = AuthIdRelationId;
635  target.objectSubId = 0;
636  for (i = 0; i < num_roles; i++)
637  {
638  target.objectId = DatumGetObjectId(role_oids[i]);
639  /* no need for dependency on the public role */
640  if (target.objectId != ACL_ID_PUBLIC)
641  recordSharedDependencyOn(&myself, &target,
643  }
644 
645  InvokeObjectPostAlterHook(PolicyRelationId, policy_id, 0);
646 
647  heap_freetuple(new_tuple);
648 
649  /* Invalidate Relation Cache */
651  }
652 
653  /* Clean up. */
654  systable_endscan(sscan);
655 
656  relation_close(rel, NoLock);
657 
658  table_close(pg_policy_rel, RowExclusiveLock);
659 
660  return (noperm || num_roles > 0);
661 }
#define NIL
Definition: pg_list.h:65
void recordSharedDependencyOn(ObjectAddress *depender, ObjectAddress *referenced, SharedDependencyType deptype)
Definition: pg_shdepend.c:120
void table_close(Relation relation, LOCKMODE lockmode)
Definition: table.c:167
void systable_endscan(SysScanDesc sysscan)
Definition: genam.c:569
#define GETSTRUCT(TUP)
Definition: htup_details.h:655
#define PolicyOidIndexId
Definition: pg_policy.h:55
bool IsSystemRelation(Relation relation)
Definition: catalog.c:66
#define RelationGetDescr(relation)
Definition: rel.h:483
Oid GetUserId(void)
Definition: miscinit.c:476
#define PointerGetDatum(X)
Definition: postgres.h:556
#define DatumGetObjectId(X)
Definition: postgres.h:500
long deleteDependencyRecordsFor(Oid classId, Oid objectId, bool skipExtensionDeps)
Definition: pg_depend.c:272
ArrayType * construct_array(Datum *elems, int nelems, Oid elmtype, int elmlen, bool elmbyval, char elmalign)
Definition: arrayfuncs.c:3313
#define AccessShareLock
Definition: lockdefs.h:36
Definition: nodes.h:527
int errcode(int sqlerrcode)
Definition: elog.c:691
void * stringToNode(const char *str)
Definition: read.c:89
void recordDependencyOn(const ObjectAddress *depender, const ObjectAddress *referenced, DependencyType behavior)
Definition: pg_depend.c:46
Form_pg_class rd_rel
Definition: rel.h:110
void heap_freetuple(HeapTuple htup)
Definition: heaptuple.c:1338
unsigned int Oid
Definition: postgres_ext.h:31
SysScanDesc systable_beginscan(Relation heapRelation, Oid indexId, bool indexOK, Snapshot snapshot, int nkeys, ScanKey key)
Definition: genam.c:357
ParseNamespaceItem * addRangeTableEntryForRelation(ParseState *pstate, Relation rel, int lockmode, Alias *alias, bool inh, bool inFromCl)
ParseState * make_parsestate(ParseState *parentParseState)
Definition: parse_node.c:43
HeapTuple systable_getnext(SysScanDesc sysscan)
Definition: genam.c:476
#define ObjectIdGetDatum(X)
Definition: postgres.h:507
#define ERROR
Definition: elog.h:43
Relation relation_open(Oid relationId, LOCKMODE lockmode)
Definition: relation.c:48
#define ARR_DIMS(a)
Definition: array.h:282
ItemPointerData t_self
Definition: htup.h:65
#define ARR_DATA_PTR(a)
Definition: array.h:310
#define NoLock
Definition: lockdefs.h:34
#define RowExclusiveLock
Definition: lockdefs.h:38
void recordDependencyOnExpr(const ObjectAddress *depender, Node *expr, List *rtable, DependencyType behavior)
Definition: dependency.c:1689
#define RelationGetRelationName(relation)
Definition: rel.h:491
#define InvokeObjectPostAlterHook(classId, objectId, subId)
Definition: objectaccess.h:175
void deleteSharedDependencyRecordsFor(Oid classId, Oid objectId, int32 objectSubId)
Definition: pg_shdepend.c:945
#define WARNING
Definition: elog.h:40
#define heap_getattr(tup, attnum, tupleDesc, isnull)
Definition: htup_details.h:762
#define TextDatumGetCString(d)
Definition: builtins.h:87
uintptr_t Datum
Definition: postgres.h:367
#define DatumGetArrayTypePCopy(X)
Definition: array.h:250
bool allowSystemTableMods
Definition: globals.c:120
FormData_pg_policy * Form_pg_policy
Definition: pg_policy.h:50
#define ereport(elevel,...)
Definition: elog.h:155
#define HeapTupleIsValid(tuple)
Definition: htup.h:78
void relation_close(Relation relation, LOCKMODE lockmode)
Definition: relation.c:206
char * GetUserNameFromId(Oid roleid, bool noerr)
Definition: miscinit.c:891
#define Assert(condition)
Definition: c.h:800
bool pg_class_ownercheck(Oid class_oid, Oid roleid)
Definition: aclchk.c:4687
void CatalogTupleUpdate(Relation heapRel, ItemPointer otid, HeapTuple tup)
Definition: indexing.c:301
void CacheInvalidateRelcache(Relation relation)
Definition: inval.c:1278
static Datum values[MAXATTR]
Definition: bootstrap.c:165
#define AccessExclusiveLock
Definition: lockdefs.h:45
void * palloc(Size size)
Definition: mcxt.c:950
int errmsg(const char *fmt,...)
Definition: elog.c:902
#define elog(elevel,...)
Definition: elog.h:228
int i
#define NameStr(name)
Definition: c.h:677
void ScanKeyInit(ScanKey entry, AttrNumber attributeNumber, StrategyNumber strategy, RegProcedure procedure, Datum argument)
Definition: scankey.c:76
#define ACL_ID_PUBLIC
Definition: acl.h:46
void free_parsestate(ParseState *pstate)
Definition: parse_node.c:76
Relation table_open(Oid relationId, LOCKMODE lockmode)
Definition: table.c:39
HeapTuple heap_modify_tuple(HeapTuple tuple, TupleDesc tupleDesc, Datum *replValues, bool *replIsnull, bool *doReplace)
Definition: heaptuple.c:1113
Definition: pg_list.h:50
#define BTEqualStrategyNumber
Definition: stratnum.h:31
List * p_rtable
Definition: parse_node.h:180

◆ rename_policy()

ObjectAddress rename_policy ( RenameStmt stmt)

Definition at line 1199 of file policy.c.

References AccessExclusiveLock, BTEqualStrategyNumber, CacheInvalidateRelcache(), CatalogTupleUpdate(), CStringGetDatum, ereport, errcode(), ERRCODE_DUPLICATE_OBJECT, errmsg(), ERROR, GETSTRUCT, heap_copytuple(), HeapTupleIsValid, InvokeObjectPostAlterHook, namestrcpy(), NoLock, ObjectAddressSet, ObjectIdGetDatum, PolicyPolrelidPolnameIndexId, RangeVarCallbackForPolicy(), RangeVarGetRelidExtended(), RenameStmt::relation, relation_close(), relation_open(), RelationGetRelationName, RowExclusiveLock, ScanKeyInit(), systable_beginscan(), systable_endscan(), systable_getnext(), HeapTupleData::t_self, table_close(), and table_open().

Referenced by ExecRenameStmt().

1200 {
1201  Relation pg_policy_rel;
1202  Relation target_table;
1203  Oid table_id;
1204  Oid opoloid;
1205  ScanKeyData skey[2];
1206  SysScanDesc sscan;
1207  HeapTuple policy_tuple;
1208  ObjectAddress address;
1209 
1210  /* Get id of table. Also handles permissions checks. */
1212  0,
1214  (void *) stmt);
1215 
1216  target_table = relation_open(table_id, NoLock);
1217 
1218  pg_policy_rel = table_open(PolicyRelationId, RowExclusiveLock);
1219 
1220  /* First pass -- check for conflict */
1221 
1222  /* Add key - policy's relation id. */
1223  ScanKeyInit(&skey[0],
1224  Anum_pg_policy_polrelid,
1225  BTEqualStrategyNumber, F_OIDEQ,
1226  ObjectIdGetDatum(table_id));
1227 
1228  /* Add key - policy's name. */
1229  ScanKeyInit(&skey[1],
1230  Anum_pg_policy_polname,
1231  BTEqualStrategyNumber, F_NAMEEQ,
1232  CStringGetDatum(stmt->newname));
1233 
1234  sscan = systable_beginscan(pg_policy_rel,
1235  PolicyPolrelidPolnameIndexId, true, NULL, 2,
1236  skey);
1237 
1238  if (HeapTupleIsValid(systable_getnext(sscan)))
1239  ereport(ERROR,
1241  errmsg("policy \"%s\" for table \"%s\" already exists",
1242  stmt->newname, RelationGetRelationName(target_table))));
1243 
1244  systable_endscan(sscan);
1245 
1246  /* Second pass -- find existing policy and update */
1247  /* Add key - policy's relation id. */
1248  ScanKeyInit(&skey[0],
1249  Anum_pg_policy_polrelid,
1250  BTEqualStrategyNumber, F_OIDEQ,
1251  ObjectIdGetDatum(table_id));
1252 
1253  /* Add key - policy's name. */
1254  ScanKeyInit(&skey[1],
1255  Anum_pg_policy_polname,
1256  BTEqualStrategyNumber, F_NAMEEQ,
1257  CStringGetDatum(stmt->subname));
1258 
1259  sscan = systable_beginscan(pg_policy_rel,
1260  PolicyPolrelidPolnameIndexId, true, NULL, 2,
1261  skey);
1262 
1263  policy_tuple = systable_getnext(sscan);
1264 
1265  /* Complain if we did not find the policy */
1266  if (!HeapTupleIsValid(policy_tuple))
1267  ereport(ERROR,
1268  (errcode(ERRCODE_UNDEFINED_OBJECT),
1269  errmsg("policy \"%s\" for table \"%s\" does not exist",
1270  stmt->subname, RelationGetRelationName(target_table))));
1271 
1272  opoloid = ((Form_pg_policy) GETSTRUCT(policy_tuple))->oid;
1273 
1274  policy_tuple = heap_copytuple(policy_tuple);
1275 
1276  namestrcpy(&((Form_pg_policy) GETSTRUCT(policy_tuple))->polname,
1277  stmt->newname);
1278 
1279  CatalogTupleUpdate(pg_policy_rel, &policy_tuple->t_self, policy_tuple);
1280 
1281  InvokeObjectPostAlterHook(PolicyRelationId, opoloid, 0);
1282 
1283  ObjectAddressSet(address, PolicyRelationId, opoloid);
1284 
1285  /*
1286  * Invalidate relation's relcache entry so that other backends (and this
1287  * one too!) are sent SI message to make them rebuild relcache entries.
1288  * (Ideally this should happen automatically...)
1289  */
1290  CacheInvalidateRelcache(target_table);
1291 
1292  /* Clean up. */
1293  systable_endscan(sscan);
1294  table_close(pg_policy_rel, RowExclusiveLock);
1295  relation_close(target_table, NoLock);
1296 
1297  return address;
1298 }
HeapTuple heap_copytuple(HeapTuple tuple)
Definition: heaptuple.c:680
void table_close(Relation relation, LOCKMODE lockmode)
Definition: table.c:167
void systable_endscan(SysScanDesc sysscan)
Definition: genam.c:569
#define GETSTRUCT(TUP)
Definition: htup_details.h:655
char * subname
Definition: parsenodes.h:2920
void namestrcpy(Name name, const char *str)
Definition: name.c:233
int errcode(int sqlerrcode)
Definition: elog.c:691
char * newname
Definition: parsenodes.h:2922
unsigned int Oid
Definition: postgres_ext.h:31
SysScanDesc systable_beginscan(Relation heapRelation, Oid indexId, bool indexOK, Snapshot snapshot, int nkeys, ScanKey key)
Definition: genam.c:357
HeapTuple systable_getnext(SysScanDesc sysscan)
Definition: genam.c:476
#define ObjectIdGetDatum(X)
Definition: postgres.h:507
#define ERROR
Definition: elog.h:43
Relation relation_open(Oid relationId, LOCKMODE lockmode)
Definition: relation.c:48
ItemPointerData t_self
Definition: htup.h:65
#define NoLock
Definition: lockdefs.h:34
#define RowExclusiveLock
Definition: lockdefs.h:38
#define CStringGetDatum(X)
Definition: postgres.h:578
#define RelationGetRelationName(relation)
Definition: rel.h:491
Oid RangeVarGetRelidExtended(const RangeVar *relation, LOCKMODE lockmode, uint32 flags, RangeVarGetRelidCallback callback, void *callback_arg)
Definition: namespace.c:236
#define InvokeObjectPostAlterHook(classId, objectId, subId)
Definition: objectaccess.h:175
RangeVar * relation
Definition: parsenodes.h:2918
FormData_pg_policy * Form_pg_policy
Definition: pg_policy.h:50
#define ereport(elevel,...)
Definition: elog.h:155
#define HeapTupleIsValid(tuple)
Definition: htup.h:78
void relation_close(Relation relation, LOCKMODE lockmode)
Definition: relation.c:206
#define PolicyPolrelidPolnameIndexId
Definition: pg_policy.h:57
void CatalogTupleUpdate(Relation heapRel, ItemPointer otid, HeapTuple tup)
Definition: indexing.c:301
#define ObjectAddressSet(addr, class_id, object_id)
Definition: objectaddress.h:40
void CacheInvalidateRelcache(Relation relation)
Definition: inval.c:1278
#define AccessExclusiveLock
Definition: lockdefs.h:45
int errmsg(const char *fmt,...)
Definition: elog.c:902
static void RangeVarCallbackForPolicy(const RangeVar *rv, Oid relid, Oid oldrelid, void *arg)
Definition: policy.c:66
void ScanKeyInit(ScanKey entry, AttrNumber attributeNumber, StrategyNumber strategy, RegProcedure procedure, Datum argument)
Definition: scankey.c:76
Relation table_open(Oid relationId, LOCKMODE lockmode)
Definition: table.c:39
#define ERRCODE_DUPLICATE_OBJECT
Definition: streamutil.c:32
#define BTEqualStrategyNumber
Definition: stratnum.h:31