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 890 of file policy.c.

References AccessExclusiveLock, AccessShareLock, ACL_DELETE_CHR, ACL_ID_PUBLIC, ACL_INSERT_CHR, ACL_SELECT_CHR, addRangeTableEntryForRelation(), addRTEtoQuery(), 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().

891 {
892  Relation pg_policy_rel;
893  Oid policy_id;
894  Relation target_table;
895  Oid table_id;
896  Datum *role_oids = NULL;
897  int nitems = 0;
898  ArrayType *role_ids = NULL;
899  List *qual_parse_rtable = NIL;
900  List *with_check_parse_rtable = NIL;
901  Node *qual = NULL;
902  Node *with_check_qual = NULL;
903  ScanKeyData skey[2];
904  SysScanDesc sscan;
905  HeapTuple policy_tuple;
906  HeapTuple new_tuple;
907  Datum values[Natts_pg_policy];
908  bool isnull[Natts_pg_policy];
909  bool replaces[Natts_pg_policy];
910  ObjectAddress target;
911  ObjectAddress myself;
912  Datum polcmd_datum;
913  char polcmd;
914  bool polcmd_isnull;
915  int i;
916 
917  /* Parse role_ids */
918  if (stmt->roles != NULL)
919  {
920  role_oids = policy_role_list_to_array(stmt->roles, &nitems);
921  role_ids = construct_array(role_oids, nitems, OIDOID,
922  sizeof(Oid), true, 'i');
923  }
924 
925  /* Get id of table. Also handles permissions checks. */
927  0,
929  (void *) stmt);
930 
931  target_table = relation_open(table_id, NoLock);
932 
933  /* Parse the using policy clause */
934  if (stmt->qual)
935  {
936  RangeTblEntry *rte;
937  ParseState *qual_pstate = make_parsestate(NULL);
938 
939  rte = addRangeTableEntryForRelation(qual_pstate, target_table,
941  NULL, false, false);
942 
943  addRTEtoQuery(qual_pstate, rte, false, true, true);
944 
945  qual = transformWhereClause(qual_pstate, copyObject(stmt->qual),
947  "POLICY");
948 
949  /* Fix up collation information */
950  assign_expr_collations(qual_pstate, qual);
951 
952  qual_parse_rtable = qual_pstate->p_rtable;
953  free_parsestate(qual_pstate);
954  }
955 
956  /* Parse the with-check policy clause */
957  if (stmt->with_check)
958  {
959  RangeTblEntry *rte;
960  ParseState *with_check_pstate = make_parsestate(NULL);
961 
962  rte = addRangeTableEntryForRelation(with_check_pstate, target_table,
964  NULL, false, false);
965 
966  addRTEtoQuery(with_check_pstate, rte, false, true, true);
967 
968  with_check_qual = transformWhereClause(with_check_pstate,
969  copyObject(stmt->with_check),
971  "POLICY");
972 
973  /* Fix up collation information */
974  assign_expr_collations(with_check_pstate, with_check_qual);
975 
976  with_check_parse_rtable = with_check_pstate->p_rtable;
977  free_parsestate(with_check_pstate);
978  }
979 
980  /* zero-clear */
981  memset(values, 0, sizeof(values));
982  memset(replaces, 0, sizeof(replaces));
983  memset(isnull, 0, sizeof(isnull));
984 
985  /* Find policy to update. */
986  pg_policy_rel = table_open(PolicyRelationId, RowExclusiveLock);
987 
988  /* Set key - policy's relation id. */
989  ScanKeyInit(&skey[0],
990  Anum_pg_policy_polrelid,
991  BTEqualStrategyNumber, F_OIDEQ,
992  ObjectIdGetDatum(table_id));
993 
994  /* Set key - policy's name. */
995  ScanKeyInit(&skey[1],
996  Anum_pg_policy_polname,
997  BTEqualStrategyNumber, F_NAMEEQ,
999 
1000  sscan = systable_beginscan(pg_policy_rel,
1001  PolicyPolrelidPolnameIndexId, true, NULL, 2,
1002  skey);
1003 
1004  policy_tuple = systable_getnext(sscan);
1005 
1006  /* Check that the policy is found, raise an error if not. */
1007  if (!HeapTupleIsValid(policy_tuple))
1008  ereport(ERROR,
1009  (errcode(ERRCODE_UNDEFINED_OBJECT),
1010  errmsg("policy \"%s\" for table \"%s\" does not exist",
1011  stmt->policy_name,
1012  RelationGetRelationName(target_table))));
1013 
1014  /* Get policy command */
1015  polcmd_datum = heap_getattr(policy_tuple, Anum_pg_policy_polcmd,
1016  RelationGetDescr(pg_policy_rel),
1017  &polcmd_isnull);
1018  Assert(!polcmd_isnull);
1019  polcmd = DatumGetChar(polcmd_datum);
1020 
1021  /*
1022  * If the command is SELECT or DELETE then WITH CHECK should be NULL.
1023  */
1024  if ((polcmd == ACL_SELECT_CHR || polcmd == ACL_DELETE_CHR)
1025  && stmt->with_check != NULL)
1026  ereport(ERROR,
1027  (errcode(ERRCODE_SYNTAX_ERROR),
1028  errmsg("only USING expression allowed for SELECT, DELETE")));
1029 
1030  /*
1031  * If the command is INSERT then WITH CHECK should be the only expression
1032  * provided.
1033  */
1034  if ((polcmd == ACL_INSERT_CHR)
1035  && stmt->qual != NULL)
1036  ereport(ERROR,
1037  (errcode(ERRCODE_SYNTAX_ERROR),
1038  errmsg("only WITH CHECK expression allowed for INSERT")));
1039 
1040  policy_id = ((Form_pg_policy) GETSTRUCT(policy_tuple))->oid;
1041 
1042  if (role_ids != NULL)
1043  {
1044  replaces[Anum_pg_policy_polroles - 1] = true;
1045  values[Anum_pg_policy_polroles - 1] = PointerGetDatum(role_ids);
1046  }
1047  else
1048  {
1049  Oid *roles;
1050  Datum roles_datum;
1051  bool attr_isnull;
1052  ArrayType *policy_roles;
1053 
1054  /*
1055  * We need to pull the set of roles this policy applies to from what's
1056  * in the catalog, so that we can recreate the dependencies correctly
1057  * for the policy.
1058  */
1059 
1060  roles_datum = heap_getattr(policy_tuple, Anum_pg_policy_polroles,
1061  RelationGetDescr(pg_policy_rel),
1062  &attr_isnull);
1063  Assert(!attr_isnull);
1064 
1065  policy_roles = DatumGetArrayTypePCopy(roles_datum);
1066 
1067  roles = (Oid *) ARR_DATA_PTR(policy_roles);
1068 
1069  nitems = ARR_DIMS(policy_roles)[0];
1070 
1071  role_oids = (Datum *) palloc(nitems * sizeof(Datum));
1072 
1073  for (i = 0; i < nitems; i++)
1074  role_oids[i] = ObjectIdGetDatum(roles[i]);
1075  }
1076 
1077  if (qual != NULL)
1078  {
1079  replaces[Anum_pg_policy_polqual - 1] = true;
1080  values[Anum_pg_policy_polqual - 1]
1082  }
1083  else
1084  {
1085  Datum value_datum;
1086  bool attr_isnull;
1087 
1088  /*
1089  * We need to pull the USING expression and build the range table for
1090  * the policy from what's in the catalog, so that we can recreate the
1091  * dependencies correctly for the policy.
1092  */
1093 
1094  /* Check if the policy has a USING expr */
1095  value_datum = heap_getattr(policy_tuple, Anum_pg_policy_polqual,
1096  RelationGetDescr(pg_policy_rel),
1097  &attr_isnull);
1098  if (!attr_isnull)
1099  {
1100  char *qual_value;
1101  ParseState *qual_pstate;
1102 
1103  /* parsestate is built just to build the range table */
1104  qual_pstate = make_parsestate(NULL);
1105 
1106  qual_value = TextDatumGetCString(value_datum);
1107  qual = stringToNode(qual_value);
1108 
1109  /* Add this rel to the parsestate's rangetable, for dependencies */
1110  addRangeTableEntryForRelation(qual_pstate, target_table,
1112  NULL, false, false);
1113 
1114  qual_parse_rtable = qual_pstate->p_rtable;
1115  free_parsestate(qual_pstate);
1116  }
1117  }
1118 
1119  if (with_check_qual != NULL)
1120  {
1121  replaces[Anum_pg_policy_polwithcheck - 1] = true;
1122  values[Anum_pg_policy_polwithcheck - 1]
1123  = CStringGetTextDatum(nodeToString(with_check_qual));
1124  }
1125  else
1126  {
1127  Datum value_datum;
1128  bool attr_isnull;
1129 
1130  /*
1131  * We need to pull the WITH CHECK expression and build the range table
1132  * for the policy from what's in the catalog, so that we can recreate
1133  * the dependencies correctly for the policy.
1134  */
1135 
1136  /* Check if the policy has a WITH CHECK expr */
1137  value_datum = heap_getattr(policy_tuple, Anum_pg_policy_polwithcheck,
1138  RelationGetDescr(pg_policy_rel),
1139  &attr_isnull);
1140  if (!attr_isnull)
1141  {
1142  char *with_check_value;
1143  ParseState *with_check_pstate;
1144 
1145  /* parsestate is built just to build the range table */
1146  with_check_pstate = make_parsestate(NULL);
1147 
1148  with_check_value = TextDatumGetCString(value_datum);
1149  with_check_qual = stringToNode(with_check_value);
1150 
1151  /* Add this rel to the parsestate's rangetable, for dependencies */
1152  addRangeTableEntryForRelation(with_check_pstate, target_table,
1154  NULL, false, false);
1155 
1156  with_check_parse_rtable = with_check_pstate->p_rtable;
1157  free_parsestate(with_check_pstate);
1158  }
1159  }
1160 
1161  new_tuple = heap_modify_tuple(policy_tuple,
1162  RelationGetDescr(pg_policy_rel),
1163  values, isnull, replaces);
1164  CatalogTupleUpdate(pg_policy_rel, &new_tuple->t_self, new_tuple);
1165 
1166  /* Update Dependencies. */
1167  deleteDependencyRecordsFor(PolicyRelationId, policy_id, false);
1168 
1169  /* Record Dependencies */
1170  target.classId = RelationRelationId;
1171  target.objectId = table_id;
1172  target.objectSubId = 0;
1173 
1174  myself.classId = PolicyRelationId;
1175  myself.objectId = policy_id;
1176  myself.objectSubId = 0;
1177 
1178  recordDependencyOn(&myself, &target, DEPENDENCY_AUTO);
1179 
1180  recordDependencyOnExpr(&myself, qual, qual_parse_rtable, DEPENDENCY_NORMAL);
1181 
1182  recordDependencyOnExpr(&myself, with_check_qual, with_check_parse_rtable,
1184 
1185  /* Register role dependencies */
1186  deleteSharedDependencyRecordsFor(PolicyRelationId, policy_id, 0);
1187  target.classId = AuthIdRelationId;
1188  target.objectSubId = 0;
1189  for (i = 0; i < nitems; i++)
1190  {
1191  target.objectId = DatumGetObjectId(role_oids[i]);
1192  /* no dependency if public */
1193  if (target.objectId != ACL_ID_PUBLIC)
1194  recordSharedDependencyOn(&myself, &target,
1196  }
1197 
1198  InvokeObjectPostAlterHook(PolicyRelationId, policy_id, 0);
1199 
1200  heap_freetuple(new_tuple);
1201 
1202  /* Invalidate Relation Cache */
1203  CacheInvalidateRelcache(target_table);
1204 
1205  /* Clean up. */
1206  systable_endscan(sscan);
1207  relation_close(target_table, NoLock);
1208  table_close(pg_policy_rel, RowExclusiveLock);
1209 
1210  return myself;
1211 }
#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:133
void systable_endscan(SysScanDesc sysscan)
Definition: genam.c:525
#define GETSTRUCT(TUP)
Definition: htup_details.h:655
#define RelationGetDescr(relation)
Definition: rel.h:448
#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:190
#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:3291
#define AccessShareLock
Definition: lockdefs.h:36
Definition: nodes.h:525
int errcode(int sqlerrcode)
Definition: elog.c:608
void * stringToNode(const char *str)
Definition: read.c:89
void recordDependencyOn(const ObjectAddress *depender, const ObjectAddress *referenced, DependencyType behavior)
Definition: pg_depend.c:43
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:352
RangeVar * table
Definition: parsenodes.h:2382
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:444
char * policy_name
Definition: parsenodes.h:2381
#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
RangeTblEntry * addRangeTableEntryForRelation(ParseState *pstate, Relation rel, int lockmode, Alias *alias, bool inh, bool inFromCl)
#define CStringGetDatum(X)
Definition: postgres.h:578
void recordDependencyOnExpr(const ObjectAddress *depender, Node *expr, List *rtable, DependencyType behavior)
Definition: dependency.c:1586
#define RelationGetRelationName(relation)
Definition: rel.h:456
Oid RangeVarGetRelidExtended(const RangeVar *relation, LOCKMODE lockmode, uint32 flags, RangeVarGetRelidCallback callback, void *callback_arg)
Definition: namespace.c:228
#define PolicyPolrelidPolnameIndexId
Definition: indexing.h:337
#define ereport(elevel, rest)
Definition: elog.h:141
#define InvokeObjectPostAlterHook(classId, objectId, subId)
Definition: objectaccess.h:175
void addRTEtoQuery(ParseState *pstate, RangeTblEntry *rte, bool addToJoinList, bool addToRelNameSpace, bool addToVarNameSpace)
void deleteSharedDependencyRecordsFor(Oid classId, Oid objectId, int32 objectSubId)
Definition: pg_shdepend.c:907
#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:84
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 HeapTupleIsValid(tuple)
Definition: htup.h:78
void relation_close(Relation relation, LOCKMODE lockmode)
Definition: relation.c:206
#define Assert(condition)
Definition: c.h:739
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:224
void CacheInvalidateRelcache(Relation relation)
Definition: inval.c:1270
static Datum values[MAXATTR]
Definition: bootstrap.c:167
#define AccessExclusiveLock
Definition: lockdefs.h:45
void * palloc(Size size)
Definition: mcxt.c:949
int errmsg(const char *fmt,...)
Definition: elog.c:822
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:83
char * nodeToString(const void *obj)
Definition: outfuncs.c:4322
#define ACL_ID_PUBLIC
Definition: acl.h:46
#define copyObject(obj)
Definition: nodes.h:641
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:177

◆ CreatePolicy()

ObjectAddress CreatePolicy ( CreatePolicyStmt stmt)

Definition at line 690 of file policy.c.

References AccessExclusiveLock, AccessShareLock, ACL_DELETE_CHR, ACL_ID_PUBLIC, ACL_INSERT_CHR, ACL_SELECT_CHR, addRangeTableEntryForRelation(), addRTEtoQuery(), 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().

691 {
692  Relation pg_policy_rel;
693  Oid policy_id;
694  Relation target_table;
695  Oid table_id;
696  char polcmd;
697  Datum *role_oids;
698  int nitems = 0;
699  ArrayType *role_ids;
700  ParseState *qual_pstate;
701  ParseState *with_check_pstate;
702  RangeTblEntry *rte;
703  Node *qual;
704  Node *with_check_qual;
705  ScanKeyData skey[2];
706  SysScanDesc sscan;
707  HeapTuple policy_tuple;
708  Datum values[Natts_pg_policy];
709  bool isnull[Natts_pg_policy];
710  ObjectAddress target;
711  ObjectAddress myself;
712  int i;
713 
714  /* Parse command */
715  polcmd = parse_policy_command(stmt->cmd_name);
716 
717  /*
718  * If the command is SELECT or DELETE then WITH CHECK should be NULL.
719  */
720  if ((polcmd == ACL_SELECT_CHR || polcmd == ACL_DELETE_CHR)
721  && stmt->with_check != NULL)
722  ereport(ERROR,
723  (errcode(ERRCODE_SYNTAX_ERROR),
724  errmsg("WITH CHECK cannot be applied to SELECT or DELETE")));
725 
726  /*
727  * If the command is INSERT then WITH CHECK should be the only expression
728  * provided.
729  */
730  if (polcmd == ACL_INSERT_CHR && stmt->qual != NULL)
731  ereport(ERROR,
732  (errcode(ERRCODE_SYNTAX_ERROR),
733  errmsg("only WITH CHECK expression allowed for INSERT")));
734 
735  /* Collect role ids */
736  role_oids = policy_role_list_to_array(stmt->roles, &nitems);
737  role_ids = construct_array(role_oids, nitems, OIDOID,
738  sizeof(Oid), true, 'i');
739 
740  /* Parse the supplied clause */
741  qual_pstate = make_parsestate(NULL);
742  with_check_pstate = make_parsestate(NULL);
743 
744  /* zero-clear */
745  memset(values, 0, sizeof(values));
746  memset(isnull, 0, sizeof(isnull));
747 
748  /* Get id of table. Also handles permissions checks. */
750  0,
752  (void *) stmt);
753 
754  /* Open target_table to build quals. No additional lock is necessary. */
755  target_table = relation_open(table_id, NoLock);
756 
757  /* Add for the regular security quals */
758  rte = addRangeTableEntryForRelation(qual_pstate, target_table,
760  NULL, false, false);
761  addRTEtoQuery(qual_pstate, rte, false, true, true);
762 
763  /* Add for the with-check quals */
764  rte = addRangeTableEntryForRelation(with_check_pstate, target_table,
766  NULL, false, false);
767  addRTEtoQuery(with_check_pstate, rte, false, true, true);
768 
769  qual = transformWhereClause(qual_pstate,
770  copyObject(stmt->qual),
772  "POLICY");
773 
774  with_check_qual = transformWhereClause(with_check_pstate,
775  copyObject(stmt->with_check),
777  "POLICY");
778 
779  /* Fix up collation information */
780  assign_expr_collations(qual_pstate, qual);
781  assign_expr_collations(with_check_pstate, with_check_qual);
782 
783  /* Open pg_policy catalog */
784  pg_policy_rel = table_open(PolicyRelationId, RowExclusiveLock);
785 
786  /* Set key - policy's relation id. */
787  ScanKeyInit(&skey[0],
788  Anum_pg_policy_polrelid,
789  BTEqualStrategyNumber, F_OIDEQ,
790  ObjectIdGetDatum(table_id));
791 
792  /* Set key - policy's name. */
793  ScanKeyInit(&skey[1],
794  Anum_pg_policy_polname,
795  BTEqualStrategyNumber, F_NAMEEQ,
797 
798  sscan = systable_beginscan(pg_policy_rel,
799  PolicyPolrelidPolnameIndexId, true, NULL, 2,
800  skey);
801 
802  policy_tuple = systable_getnext(sscan);
803 
804  /* Complain if the policy name already exists for the table */
805  if (HeapTupleIsValid(policy_tuple))
806  ereport(ERROR,
808  errmsg("policy \"%s\" for table \"%s\" already exists",
809  stmt->policy_name, RelationGetRelationName(target_table))));
810 
811  policy_id = GetNewOidWithIndex(pg_policy_rel, PolicyOidIndexId,
812  Anum_pg_policy_oid);
813  values[Anum_pg_policy_oid - 1] = ObjectIdGetDatum(policy_id);
814  values[Anum_pg_policy_polrelid - 1] = ObjectIdGetDatum(table_id);
815  values[Anum_pg_policy_polname - 1] = DirectFunctionCall1(namein,
817  values[Anum_pg_policy_polcmd - 1] = CharGetDatum(polcmd);
818  values[Anum_pg_policy_polpermissive - 1] = BoolGetDatum(stmt->permissive);
819  values[Anum_pg_policy_polroles - 1] = PointerGetDatum(role_ids);
820 
821  /* Add qual if present. */
822  if (qual)
823  values[Anum_pg_policy_polqual - 1] = CStringGetTextDatum(nodeToString(qual));
824  else
825  isnull[Anum_pg_policy_polqual - 1] = true;
826 
827  /* Add WITH CHECK qual if present */
828  if (with_check_qual)
829  values[Anum_pg_policy_polwithcheck - 1] = CStringGetTextDatum(nodeToString(with_check_qual));
830  else
831  isnull[Anum_pg_policy_polwithcheck - 1] = true;
832 
833  policy_tuple = heap_form_tuple(RelationGetDescr(pg_policy_rel), values,
834  isnull);
835 
836  CatalogTupleInsert(pg_policy_rel, policy_tuple);
837 
838  /* Record Dependencies */
839  target.classId = RelationRelationId;
840  target.objectId = table_id;
841  target.objectSubId = 0;
842 
843  myself.classId = PolicyRelationId;
844  myself.objectId = policy_id;
845  myself.objectSubId = 0;
846 
847  recordDependencyOn(&myself, &target, DEPENDENCY_AUTO);
848 
849  recordDependencyOnExpr(&myself, qual, qual_pstate->p_rtable,
851 
852  recordDependencyOnExpr(&myself, with_check_qual,
853  with_check_pstate->p_rtable, DEPENDENCY_NORMAL);
854 
855  /* Register role dependencies */
856  target.classId = AuthIdRelationId;
857  target.objectSubId = 0;
858  for (i = 0; i < nitems; i++)
859  {
860  target.objectId = DatumGetObjectId(role_oids[i]);
861  /* no dependency if public */
862  if (target.objectId != ACL_ID_PUBLIC)
863  recordSharedDependencyOn(&myself, &target,
865  }
866 
867  InvokeObjectPostCreateHook(PolicyRelationId, policy_id, 0);
868 
869  /* Invalidate Relation Cache */
870  CacheInvalidateRelcache(target_table);
871 
872  /* Clean up. */
873  heap_freetuple(policy_tuple);
874  free_parsestate(qual_pstate);
875  free_parsestate(with_check_pstate);
876  systable_endscan(sscan);
877  relation_close(target_table, NoLock);
878  table_close(pg_policy_rel, RowExclusiveLock);
879 
880  return myself;
881 }
Oid GetNewOidWithIndex(Relation relation, Oid indexId, AttrNumber oidcolumn)
Definition: catalog.c:322
#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:133
void systable_endscan(SysScanDesc sysscan)
Definition: genam.c:525
#define InvokeObjectPostCreateHook(classId, objectId, subId)
Definition: objectaccess.h:151
#define RelationGetDescr(relation)
Definition: rel.h:448
#define PolicyOidIndexId
Definition: indexing.h:334
#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:3291
#define AccessShareLock
Definition: lockdefs.h:36
Definition: nodes.h:525
int errcode(int sqlerrcode)
Definition: elog.c:608
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:43
HeapTuple heap_form_tuple(TupleDesc tupleDescriptor, Datum *values, bool *isnull)
Definition: heaptuple.c:1020
#define DirectFunctionCall1(func, arg1)
Definition: fmgr.h:615
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:352
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:444
#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
RangeTblEntry * addRangeTableEntryForRelation(ParseState *pstate, Relation rel, int lockmode, Alias *alias, bool inh, bool inFromCl)
#define CStringGetDatum(X)
Definition: postgres.h:578
void recordDependencyOnExpr(const ObjectAddress *depender, Node *expr, List *rtable, DependencyType behavior)
Definition: dependency.c:1586
#define RelationGetRelationName(relation)
Definition: rel.h:456
Oid RangeVarGetRelidExtended(const RangeVar *relation, LOCKMODE lockmode, uint32 flags, RangeVarGetRelidCallback callback, void *callback_arg)
Definition: namespace.c:228
#define PolicyPolrelidPolnameIndexId
Definition: indexing.h:337
#define ereport(elevel, rest)
Definition: elog.h:141
void addRTEtoQuery(ParseState *pstate, RangeTblEntry *rte, bool addToJoinList, bool addToRelNameSpace, bool addToVarNameSpace)
#define ACL_SELECT_CHR
Definition: acl.h:138
uintptr_t Datum
Definition: postgres.h:367
#define BoolGetDatum(X)
Definition: postgres.h:402
#define HeapTupleIsValid(tuple)
Definition: htup.h:78
void relation_close(Relation relation, LOCKMODE lockmode)
Definition: relation.c:206
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:2366
void CacheInvalidateRelcache(Relation relation)
Definition: inval.c:1270
static Datum values[MAXATTR]
Definition: bootstrap.c:167
#define AccessExclusiveLock
Definition: lockdefs.h:45
int errmsg(const char *fmt,...)
Definition: elog.c:822
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:83
char * nodeToString(const void *obj)
Definition: outfuncs.c:4322
#define ACL_ID_PUBLIC
Definition: acl.h:46
#define copyObject(obj)
Definition: nodes.h:641
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:31
void CatalogTupleInsert(Relation heapRel, HeapTuple tup)
Definition: indexing.c:183
#define BTEqualStrategyNumber
Definition: stratnum.h:31
List * p_rtable
Definition: parse_node.h:177

◆ get_relation_policy_oid()

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

Definition at line 1326 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().

1327 {
1328  Relation pg_policy_rel;
1329  ScanKeyData skey[2];
1330  SysScanDesc sscan;
1331  HeapTuple policy_tuple;
1332  Oid policy_oid;
1333 
1334  pg_policy_rel = table_open(PolicyRelationId, AccessShareLock);
1335 
1336  /* Add key - policy's relation id. */
1337  ScanKeyInit(&skey[0],
1338  Anum_pg_policy_polrelid,
1339  BTEqualStrategyNumber, F_OIDEQ,
1340  ObjectIdGetDatum(relid));
1341 
1342  /* Add key - policy's name. */
1343  ScanKeyInit(&skey[1],
1344  Anum_pg_policy_polname,
1345  BTEqualStrategyNumber, F_NAMEEQ,
1346  CStringGetDatum(policy_name));
1347 
1348  sscan = systable_beginscan(pg_policy_rel,
1349  PolicyPolrelidPolnameIndexId, true, NULL, 2,
1350  skey);
1351 
1352  policy_tuple = systable_getnext(sscan);
1353 
1354  if (!HeapTupleIsValid(policy_tuple))
1355  {
1356  if (!missing_ok)
1357  ereport(ERROR,
1358  (errcode(ERRCODE_UNDEFINED_OBJECT),
1359  errmsg("policy \"%s\" for table \"%s\" does not exist",
1360  policy_name, get_rel_name(relid))));
1361 
1362  policy_oid = InvalidOid;
1363  }
1364  else
1365  policy_oid = ((Form_pg_policy) GETSTRUCT(policy_tuple))->oid;
1366 
1367  /* Clean up. */
1368  systable_endscan(sscan);
1369  table_close(pg_policy_rel, AccessShareLock);
1370 
1371  return policy_oid;
1372 }
void table_close(Relation relation, LOCKMODE lockmode)
Definition: table.c:133
void systable_endscan(SysScanDesc sysscan)
Definition: genam.c:525
#define GETSTRUCT(TUP)
Definition: htup_details.h:655
#define AccessShareLock
Definition: lockdefs.h:36
int errcode(int sqlerrcode)
Definition: elog.c:608
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:352
HeapTuple systable_getnext(SysScanDesc sysscan)
Definition: genam.c:444
#define ObjectIdGetDatum(X)
Definition: postgres.h:507
#define ERROR
Definition: elog.h:43
#define CStringGetDatum(X)
Definition: postgres.h:578
#define PolicyPolrelidPolnameIndexId
Definition: indexing.h:337
#define ereport(elevel, rest)
Definition: elog.h:141
#define InvalidOid
Definition: postgres_ext.h:36
FormData_pg_policy * Form_pg_policy
Definition: pg_policy.h:50
#define HeapTupleIsValid(tuple)
Definition: htup.h:78
int errmsg(const char *fmt,...)
Definition: elog.c:822
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:1730
#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:1069
int errcode(int sqlerrcode)
Definition: elog.c:608
#define ObjectIdGetDatum(X)
Definition: postgres.h:507
#define ereport(elevel, rest)
Definition: elog.h:141
#define WARNING
Definition: elog.h:40
uintptr_t Datum
Definition: postgres.h:367
RoleSpecType roletype
Definition: parsenodes.h:328
Oid get_rolespec_oid(const RoleSpec *role, bool missing_ok)
Definition: acl.c:5217
#define lfirst(lc)
Definition: pg_list.h:190
static int list_length(const List *l)
Definition: pg_list.h:169
void * palloc(Size size)
Definition: mcxt.c:949
int errmsg(const char *fmt,...)
Definition: elog.c:822
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(), relkind, 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:380
char get_rel_relkind(Oid relid)
Definition: lsyscache.c:1805
int errcode(int sqlerrcode)
Definition: elog.c:608
char relkind
Definition: pg_class.h:81
bool IsSystemClass(Oid relid, Form_pg_class reltuple)
Definition: catalog.c:81
char * relname
Definition: primnodes.h:68
void aclcheck_error(AclResult aclerr, ObjectType objtype, const char *objectname)
Definition: aclchk.c:3352
#define ObjectIdGetDatum(X)
Definition: postgres.h:507
#define ERROR
Definition: elog.h:43
#define ereport(elevel, rest)
Definition: elog.h:141
HeapTuple SearchSysCache1(int cacheId, Datum key1)
Definition: syscache.c:1116
void ReleaseSysCache(HeapTuple tuple)
Definition: syscache.c:1164
bool allowSystemTableMods
Definition: globals.c:120
#define HeapTupleIsValid(tuple)
Definition: htup.h:78
bool pg_class_ownercheck(Oid class_oid, Oid roleid)
Definition: aclchk.c:4753
FormData_pg_class * Form_pg_class
Definition: pg_class.h:150
int errmsg(const char *fmt,...)
Definition: elog.c:822
ObjectType get_relkind_objtype(char relkind)

◆ relation_has_policies()

bool relation_has_policies ( Relation  rel)

Definition at line 1378 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().

1379 {
1380  Relation catalog;
1381  ScanKeyData skey;
1382  SysScanDesc sscan;
1383  HeapTuple policy_tuple;
1384  bool ret = false;
1385 
1386  catalog = table_open(PolicyRelationId, AccessShareLock);
1387  ScanKeyInit(&skey,
1388  Anum_pg_policy_polrelid,
1389  BTEqualStrategyNumber, F_OIDEQ,
1391  sscan = systable_beginscan(catalog, PolicyPolrelidPolnameIndexId, true,
1392  NULL, 1, &skey);
1393  policy_tuple = systable_getnext(sscan);
1394  if (HeapTupleIsValid(policy_tuple))
1395  ret = true;
1396 
1397  systable_endscan(sscan);
1398  table_close(catalog, AccessShareLock);
1399 
1400  return ret;
1401 }
void table_close(Relation relation, LOCKMODE lockmode)
Definition: table.c:133
void systable_endscan(SysScanDesc sysscan)
Definition: genam.c:525
#define AccessShareLock
Definition: lockdefs.h:36
SysScanDesc systable_beginscan(Relation heapRelation, Oid indexId, bool indexOK, Snapshot snapshot, int nkeys, ScanKey key)
Definition: genam.c:352
HeapTuple systable_getnext(SysScanDesc sysscan)
Definition: genam.c:444
#define ObjectIdGetDatum(X)
Definition: postgres.h:507
#define PolicyPolrelidPolnameIndexId
Definition: indexing.h:337
#define HeapTupleIsValid(tuple)
Definition: htup.h:78
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:422
#define BTEqualStrategyNumber
Definition: stratnum.h:31

◆ RelationBuildRowSecurity()

void RelationBuildRowSecurity ( Relation  relation)

Definition at line 192 of file policy.c.

References AccessShareLock, ALLOCSET_SMALL_SIZES, AllocSetContextCreate, Assert, BTEqualStrategyNumber, CacheMemoryContext, checkExprHasSubLink(), copyObject, CurrentMemoryContext, DatumGetArrayTypePCopy, DatumGetBool, DatumGetChar, DatumGetName, elog, ERROR, RowSecurityPolicy::hassublinks, heap_getattr, HeapTupleIsValid, lcons(), MemoryContextAllocZero(), MemoryContextCopyAndSetIdentifier, MemoryContextDelete(), MemoryContextSwitchTo(), NameStr, ObjectIdGetDatum, palloc0(), RowSecurityPolicy::permissive, pfree(), PG_CATCH, PG_END_TRY, PG_RE_THROW, PG_TRY, RowSecurityPolicy::polcmd, RowSecurityDesc::policies, RowSecurityPolicy::policy_name, PolicyPolrelidPolnameIndexId, pstrdup(), 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().

193 {
194  MemoryContext rscxt;
196  RowSecurityDesc *volatile rsdesc = NULL;
197 
198  /*
199  * Create a memory context to hold everything associated with this
200  * relation's row security policy. This makes it easy to clean up during
201  * a relcache flush.
202  */
204  "row security descriptor",
206 
207  /*
208  * Since rscxt lives under CacheMemoryContext, it is long-lived. Use a
209  * PG_TRY block to ensure it'll get freed if we fail partway through.
210  */
211  PG_TRY();
212  {
213  Relation catalog;
214  ScanKeyData skey;
215  SysScanDesc sscan;
216  HeapTuple tuple;
217 
219  RelationGetRelationName(relation));
220 
221  rsdesc = MemoryContextAllocZero(rscxt, sizeof(RowSecurityDesc));
222  rsdesc->rscxt = rscxt;
223 
224  catalog = table_open(PolicyRelationId, AccessShareLock);
225 
226  ScanKeyInit(&skey,
227  Anum_pg_policy_polrelid,
228  BTEqualStrategyNumber, F_OIDEQ,
230 
231  sscan = systable_beginscan(catalog, PolicyPolrelidPolnameIndexId, true,
232  NULL, 1, &skey);
233 
234  /*
235  * Loop through the row level security policies for this relation, if
236  * any.
237  */
238  while (HeapTupleIsValid(tuple = systable_getnext(sscan)))
239  {
240  Datum value_datum;
241  char cmd_value;
242  bool permissive_value;
243  Datum roles_datum;
244  char *qual_value;
245  Expr *qual_expr;
246  char *with_check_value;
247  Expr *with_check_qual;
248  char *policy_name_value;
249  bool isnull;
250  RowSecurityPolicy *policy;
251 
252  /*
253  * Note: all the pass-by-reference data we collect here is either
254  * still stored in the tuple, or constructed in the caller's
255  * short-lived memory context. We must copy it into rscxt
256  * explicitly below.
257  */
258 
259  /* Get policy command */
260  value_datum = heap_getattr(tuple, Anum_pg_policy_polcmd,
261  RelationGetDescr(catalog), &isnull);
262  Assert(!isnull);
263  cmd_value = DatumGetChar(value_datum);
264 
265  /* Get policy permissive or restrictive */
266  value_datum = heap_getattr(tuple, Anum_pg_policy_polpermissive,
267  RelationGetDescr(catalog), &isnull);
268  Assert(!isnull);
269  permissive_value = DatumGetBool(value_datum);
270 
271  /* Get policy name */
272  value_datum = heap_getattr(tuple, Anum_pg_policy_polname,
273  RelationGetDescr(catalog), &isnull);
274  Assert(!isnull);
275  policy_name_value = NameStr(*(DatumGetName(value_datum)));
276 
277  /* Get policy roles */
278  roles_datum = heap_getattr(tuple, Anum_pg_policy_polroles,
279  RelationGetDescr(catalog), &isnull);
280  /* shouldn't be null, but initdb doesn't mark it so, so check */
281  if (isnull)
282  elog(ERROR, "unexpected null value in pg_policy.polroles");
283 
284  /* Get policy qual */
285  value_datum = heap_getattr(tuple, Anum_pg_policy_polqual,
286  RelationGetDescr(catalog), &isnull);
287  if (!isnull)
288  {
289  qual_value = TextDatumGetCString(value_datum);
290  qual_expr = (Expr *) stringToNode(qual_value);
291  }
292  else
293  qual_expr = NULL;
294 
295  /* Get WITH CHECK qual */
296  value_datum = heap_getattr(tuple, Anum_pg_policy_polwithcheck,
297  RelationGetDescr(catalog), &isnull);
298  if (!isnull)
299  {
300  with_check_value = TextDatumGetCString(value_datum);
301  with_check_qual = (Expr *) stringToNode(with_check_value);
302  }
303  else
304  with_check_qual = NULL;
305 
306  /* Now copy everything into the cache context */
307  MemoryContextSwitchTo(rscxt);
308 
309  policy = palloc0(sizeof(RowSecurityPolicy));
310  policy->policy_name = pstrdup(policy_name_value);
311  policy->polcmd = cmd_value;
312  policy->permissive = permissive_value;
313  policy->roles = DatumGetArrayTypePCopy(roles_datum);
314  policy->qual = copyObject(qual_expr);
315  policy->with_check_qual = copyObject(with_check_qual);
316  policy->hassublinks = checkExprHasSubLink((Node *) qual_expr) ||
317  checkExprHasSubLink((Node *) with_check_qual);
318 
319  rsdesc->policies = lcons(policy, rsdesc->policies);
320 
321  MemoryContextSwitchTo(oldcxt);
322 
323  /* clean up some (not all) of the junk ... */
324  if (qual_expr != NULL)
325  pfree(qual_expr);
326  if (with_check_qual != NULL)
327  pfree(with_check_qual);
328  }
329 
330  systable_endscan(sscan);
331  table_close(catalog, AccessShareLock);
332  }
333  PG_CATCH();
334  {
335  /* Delete rscxt, first making sure it isn't active */
336  MemoryContextSwitchTo(oldcxt);
337  MemoryContextDelete(rscxt);
338  PG_RE_THROW();
339  }
340  PG_END_TRY();
341 
342  /* Success --- attach the policy descriptor to the relcache entry */
343  relation->rd_rsdesc = rsdesc;
344 }
void MemoryContextDelete(MemoryContext context)
Definition: mcxt.c:211
#define AllocSetContextCreate
Definition: memutils.h:170
void table_close(Relation relation, LOCKMODE lockmode)
Definition: table.c:133
void systable_endscan(SysScanDesc sysscan)
Definition: genam.c:525
bool checkExprHasSubLink(Node *node)
Definition: rewriteManip.c:277
#define RelationGetDescr(relation)
Definition: rel.h:448
char * pstrdup(const char *in)
Definition: mcxt.c:1186
#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:525
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:352
#define DatumGetName(X)
Definition: postgres.h:585
HeapTuple systable_getnext(SysScanDesc sysscan)
Definition: genam.c:444
void pfree(void *pointer)
Definition: mcxt.c:1056
#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 DatumGetBool(X)
Definition: postgres.h:393
#define RelationGetRelationName(relation)
Definition: rel.h:456
ArrayType * roles
Definition: rowsecurity.h:24
MemoryContext CurrentMemoryContext
Definition: mcxt.c:38
#define PolicyPolrelidPolnameIndexId
Definition: indexing.h:337
struct RowSecurityDesc * rd_rsdesc
Definition: rel.h:91
MemoryContext rscxt
Definition: rowsecurity.h:33
#define heap_getattr(tup, attnum, tupleDesc, isnull)
Definition: htup_details.h:762
#define TextDatumGetCString(d)
Definition: builtins.h:84
void * palloc0(Size size)
Definition: mcxt.c:980
uintptr_t Datum
Definition: postgres.h:367
#define DatumGetChar(X)
Definition: postgres.h:409
#define DatumGetArrayTypePCopy(X)
Definition: array.h:250
void * MemoryContextAllocZero(MemoryContext context, Size size)
Definition: mcxt.c:839
List * lcons(void *datum, List *list)
Definition: list.c:454
#define PG_CATCH()
Definition: elog.h:332
#define HeapTupleIsValid(tuple)
Definition: htup.h:78
#define Assert(condition)
Definition: c.h:739
#define PG_RE_THROW()
Definition: elog.h:363
#define elog(elevel,...)
Definition: elog.h:228
#define NameStr(name)
Definition: c.h:616
void ScanKeyInit(ScanKey entry, AttrNumber attributeNumber, StrategyNumber strategy, RegProcedure procedure, Datum argument)
Definition: scankey.c:76
#define copyObject(obj)
Definition: nodes.h:641
#define PG_TRY()
Definition: elog.h:322
Relation table_open(Oid relationId, LOCKMODE lockmode)
Definition: table.c:39
#define RelationGetRelid(relation)
Definition: rel.h:422
#define PG_END_TRY()
Definition: elog.h:347
#define BTEqualStrategyNumber
Definition: stratnum.h:31
MemoryContext CacheMemoryContext
Definition: mcxt.c:47

◆ RemovePolicyById()

void RemovePolicyById ( Oid  policy_id)

Definition at line 354 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().

355 {
356  Relation pg_policy_rel;
357  SysScanDesc sscan;
358  ScanKeyData skey[1];
359  HeapTuple tuple;
360  Oid relid;
361  Relation rel;
362 
363  pg_policy_rel = table_open(PolicyRelationId, RowExclusiveLock);
364 
365  /*
366  * Find the policy to delete.
367  */
368  ScanKeyInit(&skey[0],
369  Anum_pg_policy_oid,
370  BTEqualStrategyNumber, F_OIDEQ,
371  ObjectIdGetDatum(policy_id));
372 
373  sscan = systable_beginscan(pg_policy_rel, PolicyOidIndexId, true,
374  NULL, 1, skey);
375 
376  tuple = systable_getnext(sscan);
377 
378  /* If the policy exists, then remove it, otherwise raise an error. */
379  if (!HeapTupleIsValid(tuple))
380  elog(ERROR, "could not find tuple for policy %u", policy_id);
381 
382  /*
383  * Open and exclusive-lock the relation the policy belongs to. (We need
384  * exclusive lock to lock out queries that might otherwise depend on the
385  * set of policies the rel has; furthermore we've got to hold the lock
386  * till commit.)
387  */
388  relid = ((Form_pg_policy) GETSTRUCT(tuple))->polrelid;
389 
390  rel = table_open(relid, AccessExclusiveLock);
391  if (rel->rd_rel->relkind != RELKIND_RELATION &&
392  rel->rd_rel->relkind != RELKIND_PARTITIONED_TABLE)
393  ereport(ERROR,
394  (errcode(ERRCODE_WRONG_OBJECT_TYPE),
395  errmsg("\"%s\" is not a table",
396  RelationGetRelationName(rel))));
397 
399  ereport(ERROR,
400  (errcode(ERRCODE_INSUFFICIENT_PRIVILEGE),
401  errmsg("permission denied: \"%s\" is a system catalog",
402  RelationGetRelationName(rel))));
403 
404  CatalogTupleDelete(pg_policy_rel, &tuple->t_self);
405 
406  systable_endscan(sscan);
407 
408  /*
409  * Note that, unlike some of the other flags in pg_class, relrowsecurity
410  * is not just an indication of if policies exist. When relrowsecurity is
411  * set by a user, then all access to the relation must be through a
412  * policy. If no policy is defined for the relation then a default-deny
413  * policy is created and all records are filtered (except for queries from
414  * the owner).
415  */
417 
418  table_close(rel, NoLock);
419 
420  /* Clean up */
421  table_close(pg_policy_rel, RowExclusiveLock);
422 }
void table_close(Relation relation, LOCKMODE lockmode)
Definition: table.c:133
void systable_endscan(SysScanDesc sysscan)
Definition: genam.c:525
#define GETSTRUCT(TUP)
Definition: htup_details.h:655
bool IsSystemRelation(Relation relation)
Definition: catalog.c:69
#define PolicyOidIndexId
Definition: indexing.h:334
int errcode(int sqlerrcode)
Definition: elog.c:608
void CatalogTupleDelete(Relation heapRel, ItemPointer tid)
Definition: indexing.c:269
Form_pg_class rd_rel
Definition: rel.h:83
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:352
HeapTuple systable_getnext(SysScanDesc sysscan)
Definition: genam.c:444
#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:456
#define ereport(elevel, rest)
Definition: elog.h:141
bool allowSystemTableMods
Definition: globals.c:120
FormData_pg_policy * Form_pg_policy
Definition: pg_policy.h:50
#define HeapTupleIsValid(tuple)
Definition: htup.h:78
void CacheInvalidateRelcache(Relation relation)
Definition: inval.c:1270
#define AccessExclusiveLock
Definition: lockdefs.h:45
int errmsg(const char *fmt,...)
Definition: elog.c:822
#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 439 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().

440 {
441  Relation pg_policy_rel;
442  SysScanDesc sscan;
443  ScanKeyData skey[1];
444  HeapTuple tuple;
445  Oid relid;
446  Relation rel;
447  ArrayType *policy_roles;
448  int num_roles;
449  Datum roles_datum;
450  bool attr_isnull;
451  bool noperm = true;
452 
453  Assert(classid == PolicyRelationId);
454 
455  pg_policy_rel = table_open(PolicyRelationId, RowExclusiveLock);
456 
457  /*
458  * Find the policy to update.
459  */
460  ScanKeyInit(&skey[0],
461  Anum_pg_policy_oid,
462  BTEqualStrategyNumber, F_OIDEQ,
463  ObjectIdGetDatum(policy_id));
464 
465  sscan = systable_beginscan(pg_policy_rel, PolicyOidIndexId, true,
466  NULL, 1, skey);
467 
468  tuple = systable_getnext(sscan);
469 
470  /* Raise an error if we don't find the policy. */
471  if (!HeapTupleIsValid(tuple))
472  elog(ERROR, "could not find tuple for policy %u", policy_id);
473 
474  /*
475  * Open and exclusive-lock the relation the policy belongs to.
476  */
477  relid = ((Form_pg_policy) GETSTRUCT(tuple))->polrelid;
478 
479  rel = relation_open(relid, AccessExclusiveLock);
480 
481  if (rel->rd_rel->relkind != RELKIND_RELATION &&
482  rel->rd_rel->relkind != RELKIND_PARTITIONED_TABLE)
483  ereport(ERROR,
484  (errcode(ERRCODE_WRONG_OBJECT_TYPE),
485  errmsg("\"%s\" is not a table",
486  RelationGetRelationName(rel))));
487 
489  ereport(ERROR,
490  (errcode(ERRCODE_INSUFFICIENT_PRIVILEGE),
491  errmsg("permission denied: \"%s\" is a system catalog",
492  RelationGetRelationName(rel))));
493 
494  /* Get the current set of roles */
495  roles_datum = heap_getattr(tuple,
496  Anum_pg_policy_polroles,
497  RelationGetDescr(pg_policy_rel),
498  &attr_isnull);
499 
500  Assert(!attr_isnull);
501 
502  policy_roles = DatumGetArrayTypePCopy(roles_datum);
503 
504  /* We should be removing exactly one entry from the roles array */
505  num_roles = ARR_DIMS(policy_roles)[0] - 1;
506 
507  Assert(num_roles >= 0);
508 
509  /* Must own relation. */
510  if (pg_class_ownercheck(relid, GetUserId()))
511  noperm = false; /* user is allowed to modify this policy */
512  else
514  (errcode(ERRCODE_WARNING_PRIVILEGE_NOT_REVOKED),
515  errmsg("role \"%s\" could not be removed from policy \"%s\" on \"%s\"",
516  GetUserNameFromId(roleid, false),
517  NameStr(((Form_pg_policy) GETSTRUCT(tuple))->polname),
518  RelationGetRelationName(rel))));
519 
520  /*
521  * If multiple roles exist on this policy, then remove the one we were
522  * asked to and leave the rest.
523  */
524  if (!noperm && num_roles > 0)
525  {
526  int i,
527  j;
528  Oid *roles = (Oid *) ARR_DATA_PTR(policy_roles);
529  Datum *role_oids;
530  char *qual_value;
531  Node *qual_expr;
532  List *qual_parse_rtable = NIL;
533  char *with_check_value;
534  Node *with_check_qual;
535  List *with_check_parse_rtable = NIL;
536  Datum values[Natts_pg_policy];
537  bool isnull[Natts_pg_policy];
538  bool replaces[Natts_pg_policy];
539  Datum value_datum;
540  ArrayType *role_ids;
541  HeapTuple new_tuple;
542  ObjectAddress target;
543  ObjectAddress myself;
544 
545  /* zero-clear */
546  memset(values, 0, sizeof(values));
547  memset(replaces, 0, sizeof(replaces));
548  memset(isnull, 0, sizeof(isnull));
549 
550  /*
551  * All of the dependencies will be removed from the policy and then
552  * re-added. In order to get them correct, we need to extract out the
553  * expressions in the policy and construct a parsestate just enough to
554  * build the range table(s) to then pass to recordDependencyOnExpr().
555  */
556 
557  /* Get policy qual, to update dependencies */
558  value_datum = heap_getattr(tuple, Anum_pg_policy_polqual,
559  RelationGetDescr(pg_policy_rel), &attr_isnull);
560  if (!attr_isnull)
561  {
562  ParseState *qual_pstate;
563 
564  /* parsestate is built just to build the range table */
565  qual_pstate = make_parsestate(NULL);
566 
567  qual_value = TextDatumGetCString(value_datum);
568  qual_expr = stringToNode(qual_value);
569 
570  /* Add this rel to the parsestate's rangetable, for dependencies */
571  addRangeTableEntryForRelation(qual_pstate, rel,
573  NULL, false, false);
574 
575  qual_parse_rtable = qual_pstate->p_rtable;
576  free_parsestate(qual_pstate);
577  }
578  else
579  qual_expr = NULL;
580 
581  /* Get WITH CHECK qual, to update dependencies */
582  value_datum = heap_getattr(tuple, Anum_pg_policy_polwithcheck,
583  RelationGetDescr(pg_policy_rel), &attr_isnull);
584  if (!attr_isnull)
585  {
586  ParseState *with_check_pstate;
587 
588  /* parsestate is built just to build the range table */
589  with_check_pstate = make_parsestate(NULL);
590 
591  with_check_value = TextDatumGetCString(value_datum);
592  with_check_qual = stringToNode(with_check_value);
593 
594  /* Add this rel to the parsestate's rangetable, for dependencies */
595  addRangeTableEntryForRelation(with_check_pstate, rel,
597  NULL, false, false);
598 
599  with_check_parse_rtable = with_check_pstate->p_rtable;
600  free_parsestate(with_check_pstate);
601  }
602  else
603  with_check_qual = NULL;
604 
605  /* Rebuild the roles array to then update the pg_policy tuple with */
606  role_oids = (Datum *) palloc(num_roles * sizeof(Datum));
607  for (i = 0, j = 0; i < ARR_DIMS(policy_roles)[0]; i++)
608  /* Copy over all of the roles which are not the one being removed */
609  if (roles[i] != roleid)
610  role_oids[j++] = ObjectIdGetDatum(roles[i]);
611 
612  /* We should have only removed the one role */
613  Assert(j == num_roles);
614 
615  /* This is the array for the new tuple */
616  role_ids = construct_array(role_oids, num_roles, OIDOID,
617  sizeof(Oid), true, 'i');
618 
619  replaces[Anum_pg_policy_polroles - 1] = true;
620  values[Anum_pg_policy_polroles - 1] = PointerGetDatum(role_ids);
621 
622  new_tuple = heap_modify_tuple(tuple,
623  RelationGetDescr(pg_policy_rel),
624  values, isnull, replaces);
625  CatalogTupleUpdate(pg_policy_rel, &new_tuple->t_self, new_tuple);
626 
627  /* Remove all old dependencies. */
628  deleteDependencyRecordsFor(PolicyRelationId, policy_id, false);
629 
630  /* Record the new set of dependencies */
631  target.classId = RelationRelationId;
632  target.objectId = relid;
633  target.objectSubId = 0;
634 
635  myself.classId = PolicyRelationId;
636  myself.objectId = policy_id;
637  myself.objectSubId = 0;
638 
639  recordDependencyOn(&myself, &target, DEPENDENCY_AUTO);
640 
641  if (qual_expr)
642  recordDependencyOnExpr(&myself, qual_expr, qual_parse_rtable,
644 
645  if (with_check_qual)
646  recordDependencyOnExpr(&myself, with_check_qual,
647  with_check_parse_rtable,
649 
650  /* Remove all the old shared dependencies (roles) */
651  deleteSharedDependencyRecordsFor(PolicyRelationId, policy_id, 0);
652 
653  /* Record the new shared dependencies (roles) */
654  target.classId = AuthIdRelationId;
655  target.objectSubId = 0;
656  for (i = 0; i < num_roles; i++)
657  {
658  target.objectId = DatumGetObjectId(role_oids[i]);
659  /* no need for dependency on the public role */
660  if (target.objectId != ACL_ID_PUBLIC)
661  recordSharedDependencyOn(&myself, &target,
663  }
664 
665  InvokeObjectPostAlterHook(PolicyRelationId, policy_id, 0);
666 
667  heap_freetuple(new_tuple);
668 
669  /* Invalidate Relation Cache */
671  }
672 
673  /* Clean up. */
674  systable_endscan(sscan);
675 
676  relation_close(rel, NoLock);
677 
678  table_close(pg_policy_rel, RowExclusiveLock);
679 
680  return (noperm || num_roles > 0);
681 }
#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:133
void systable_endscan(SysScanDesc sysscan)
Definition: genam.c:525
#define GETSTRUCT(TUP)
Definition: htup_details.h:655
bool IsSystemRelation(Relation relation)
Definition: catalog.c:69
#define RelationGetDescr(relation)
Definition: rel.h:448
Oid GetUserId(void)
Definition: miscinit.c:380
#define PolicyOidIndexId
Definition: indexing.h:334
#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:190
ArrayType * construct_array(Datum *elems, int nelems, Oid elmtype, int elmlen, bool elmbyval, char elmalign)
Definition: arrayfuncs.c:3291
#define AccessShareLock
Definition: lockdefs.h:36
Definition: nodes.h:525
int errcode(int sqlerrcode)
Definition: elog.c:608
void * stringToNode(const char *str)
Definition: read.c:89
void recordDependencyOn(const ObjectAddress *depender, const ObjectAddress *referenced, DependencyType behavior)
Definition: pg_depend.c:43
Form_pg_class rd_rel
Definition: rel.h:83
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:352
ParseState * make_parsestate(ParseState *parentParseState)
Definition: parse_node.c:43
HeapTuple systable_getnext(SysScanDesc sysscan)
Definition: genam.c:444
#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
RangeTblEntry * addRangeTableEntryForRelation(ParseState *pstate, Relation rel, int lockmode, Alias *alias, bool inh, bool inFromCl)
void recordDependencyOnExpr(const ObjectAddress *depender, Node *expr, List *rtable, DependencyType behavior)
Definition: dependency.c:1586
#define RelationGetRelationName(relation)
Definition: rel.h:456
#define ereport(elevel, rest)
Definition: elog.h:141
#define InvokeObjectPostAlterHook(classId, objectId, subId)
Definition: objectaccess.h:175
void deleteSharedDependencyRecordsFor(Oid classId, Oid objectId, int32 objectSubId)
Definition: pg_shdepend.c:907
#define WARNING
Definition: elog.h:40
#define heap_getattr(tup, attnum, tupleDesc, isnull)
Definition: htup_details.h:762
#define TextDatumGetCString(d)
Definition: builtins.h:84
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 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:795
#define Assert(condition)
Definition: c.h:739
bool pg_class_ownercheck(Oid class_oid, Oid roleid)
Definition: aclchk.c:4753
void CatalogTupleUpdate(Relation heapRel, ItemPointer otid, HeapTuple tup)
Definition: indexing.c:224
void CacheInvalidateRelcache(Relation relation)
Definition: inval.c:1270
static Datum values[MAXATTR]
Definition: bootstrap.c:167
#define AccessExclusiveLock
Definition: lockdefs.h:45
void * palloc(Size size)
Definition: mcxt.c:949
int errmsg(const char *fmt,...)
Definition: elog.c:822
#define elog(elevel,...)
Definition: elog.h:228
int i
#define NameStr(name)
Definition: c.h:616
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:177

◆ rename_policy()

ObjectAddress rename_policy ( RenameStmt stmt)

Definition at line 1218 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().

1219 {
1220  Relation pg_policy_rel;
1221  Relation target_table;
1222  Oid table_id;
1223  Oid opoloid;
1224  ScanKeyData skey[2];
1225  SysScanDesc sscan;
1226  HeapTuple policy_tuple;
1227  ObjectAddress address;
1228 
1229  /* Get id of table. Also handles permissions checks. */
1231  0,
1233  (void *) stmt);
1234 
1235  target_table = relation_open(table_id, NoLock);
1236 
1237  pg_policy_rel = table_open(PolicyRelationId, RowExclusiveLock);
1238 
1239  /* First pass -- check for conflict */
1240 
1241  /* Add key - policy's relation id. */
1242  ScanKeyInit(&skey[0],
1243  Anum_pg_policy_polrelid,
1244  BTEqualStrategyNumber, F_OIDEQ,
1245  ObjectIdGetDatum(table_id));
1246 
1247  /* Add key - policy's name. */
1248  ScanKeyInit(&skey[1],
1249  Anum_pg_policy_polname,
1250  BTEqualStrategyNumber, F_NAMEEQ,
1251  CStringGetDatum(stmt->newname));
1252 
1253  sscan = systable_beginscan(pg_policy_rel,
1254  PolicyPolrelidPolnameIndexId, true, NULL, 2,
1255  skey);
1256 
1257  if (HeapTupleIsValid(systable_getnext(sscan)))
1258  ereport(ERROR,
1260  errmsg("policy \"%s\" for table \"%s\" already exists",
1261  stmt->newname, RelationGetRelationName(target_table))));
1262 
1263  systable_endscan(sscan);
1264 
1265  /* Second pass -- find existing policy and update */
1266  /* Add key - policy's relation id. */
1267  ScanKeyInit(&skey[0],
1268  Anum_pg_policy_polrelid,
1269  BTEqualStrategyNumber, F_OIDEQ,
1270  ObjectIdGetDatum(table_id));
1271 
1272  /* Add key - policy's name. */
1273  ScanKeyInit(&skey[1],
1274  Anum_pg_policy_polname,
1275  BTEqualStrategyNumber, F_NAMEEQ,
1276  CStringGetDatum(stmt->subname));
1277 
1278  sscan = systable_beginscan(pg_policy_rel,
1279  PolicyPolrelidPolnameIndexId, true, NULL, 2,
1280  skey);
1281 
1282  policy_tuple = systable_getnext(sscan);
1283 
1284  /* Complain if we did not find the policy */
1285  if (!HeapTupleIsValid(policy_tuple))
1286  ereport(ERROR,
1287  (errcode(ERRCODE_UNDEFINED_OBJECT),
1288  errmsg("policy \"%s\" for table \"%s\" does not exist",
1289  stmt->subname, RelationGetRelationName(target_table))));
1290 
1291  opoloid = ((Form_pg_policy) GETSTRUCT(policy_tuple))->oid;
1292 
1293  policy_tuple = heap_copytuple(policy_tuple);
1294 
1295  namestrcpy(&((Form_pg_policy) GETSTRUCT(policy_tuple))->polname,
1296  stmt->newname);
1297 
1298  CatalogTupleUpdate(pg_policy_rel, &policy_tuple->t_self, policy_tuple);
1299 
1300  InvokeObjectPostAlterHook(PolicyRelationId, opoloid, 0);
1301 
1302  ObjectAddressSet(address, PolicyRelationId, opoloid);
1303 
1304  /*
1305  * Invalidate relation's relcache entry so that other backends (and this
1306  * one too!) are sent SI message to make them rebuild relcache entries.
1307  * (Ideally this should happen automatically...)
1308  */
1309  CacheInvalidateRelcache(target_table);
1310 
1311  /* Clean up. */
1312  systable_endscan(sscan);
1313  table_close(pg_policy_rel, RowExclusiveLock);
1314  relation_close(target_table, NoLock);
1315 
1316  return address;
1317 }
HeapTuple heap_copytuple(HeapTuple tuple)
Definition: heaptuple.c:680
void table_close(Relation relation, LOCKMODE lockmode)
Definition: table.c:133
void systable_endscan(SysScanDesc sysscan)
Definition: genam.c:525
#define GETSTRUCT(TUP)
Definition: htup_details.h:655
char * subname
Definition: parsenodes.h:2895
int errcode(int sqlerrcode)
Definition: elog.c:608
char * newname
Definition: parsenodes.h:2897
unsigned int Oid
Definition: postgres_ext.h:31
int namestrcpy(Name name, const char *str)
Definition: name.c:250
SysScanDesc systable_beginscan(Relation heapRelation, Oid indexId, bool indexOK, Snapshot snapshot, int nkeys, ScanKey key)
Definition: genam.c:352
HeapTuple systable_getnext(SysScanDesc sysscan)
Definition: genam.c:444
#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:456
Oid RangeVarGetRelidExtended(const RangeVar *relation, LOCKMODE lockmode, uint32 flags, RangeVarGetRelidCallback callback, void *callback_arg)
Definition: namespace.c:228
#define PolicyPolrelidPolnameIndexId
Definition: indexing.h:337
#define ereport(elevel, rest)
Definition: elog.h:141
#define InvokeObjectPostAlterHook(classId, objectId, subId)
Definition: objectaccess.h:175
RangeVar * relation
Definition: parsenodes.h:2893
FormData_pg_policy * Form_pg_policy
Definition: pg_policy.h:50
#define HeapTupleIsValid(tuple)
Definition: htup.h:78
void relation_close(Relation relation, LOCKMODE lockmode)
Definition: relation.c:206
void CatalogTupleUpdate(Relation heapRel, ItemPointer otid, HeapTuple tup)
Definition: indexing.c:224
#define ObjectAddressSet(addr, class_id, object_id)
Definition: objectaddress.h:40
void CacheInvalidateRelcache(Relation relation)
Definition: inval.c:1270
#define AccessExclusiveLock
Definition: lockdefs.h:45
int errmsg(const char *fmt,...)
Definition: elog.c:822
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:31
#define BTEqualStrategyNumber
Definition: stratnum.h:31