PostgreSQL Source Code  git master
policy.h File Reference
Include dependency graph for policy.h:
This graph shows which files directly or indirectly include this file:

Go to the source code of this file.

Functions

void RelationBuildRowSecurity (Relation relation)
 
void RemovePolicyById (Oid policy_id)
 
bool RemoveRoleFromObjectPolicy (Oid roleid, Oid classid, Oid objid)
 
ObjectAddress CreatePolicy (CreatePolicyStmt *stmt)
 
ObjectAddress AlterPolicy (AlterPolicyStmt *stmt)
 
Oid get_relation_policy_oid (Oid relid, const char *policy_name, bool missing_ok)
 
ObjectAddress rename_policy (RenameStmt *stmt)
 
bool relation_has_policies (Relation rel)
 

Function Documentation

◆ AlterPolicy()

ObjectAddress AlterPolicy ( AlterPolicyStmt stmt)

Definition at line 881 of file policy.c.

References AccessExclusiveLock, 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(), heap_close, heap_freetuple(), heap_getattr, heap_modify_tuple(), heap_open(), HeapTupleGetOid, 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, TextDatumGetCString, transformWhereClause(), and values.

Referenced by ProcessUtilitySlow().

882 {
883  Relation pg_policy_rel;
884  Oid policy_id;
885  Relation target_table;
886  Oid table_id;
887  Datum *role_oids = NULL;
888  int nitems = 0;
889  ArrayType *role_ids = NULL;
890  List *qual_parse_rtable = NIL;
891  List *with_check_parse_rtable = NIL;
892  Node *qual = NULL;
893  Node *with_check_qual = NULL;
894  ScanKeyData skey[2];
895  SysScanDesc sscan;
896  HeapTuple policy_tuple;
897  HeapTuple new_tuple;
898  Datum values[Natts_pg_policy];
899  bool isnull[Natts_pg_policy];
900  bool replaces[Natts_pg_policy];
901  ObjectAddress target;
902  ObjectAddress myself;
903  Datum polcmd_datum;
904  char polcmd;
905  bool polcmd_isnull;
906  int i;
907 
908  /* Parse role_ids */
909  if (stmt->roles != NULL)
910  {
911  role_oids = policy_role_list_to_array(stmt->roles, &nitems);
912  role_ids = construct_array(role_oids, nitems, OIDOID,
913  sizeof(Oid), true, 'i');
914  }
915 
916  /* Get id of table. Also handles permissions checks. */
918  0,
920  (void *) stmt);
921 
922  target_table = relation_open(table_id, NoLock);
923 
924  /* Parse the using policy clause */
925  if (stmt->qual)
926  {
927  RangeTblEntry *rte;
928  ParseState *qual_pstate = make_parsestate(NULL);
929 
930  rte = addRangeTableEntryForRelation(qual_pstate, target_table,
931  NULL, false, false);
932 
933  addRTEtoQuery(qual_pstate, rte, false, true, true);
934 
935  qual = transformWhereClause(qual_pstate, copyObject(stmt->qual),
937  "POLICY");
938 
939  /* Fix up collation information */
940  assign_expr_collations(qual_pstate, qual);
941 
942  qual_parse_rtable = qual_pstate->p_rtable;
943  free_parsestate(qual_pstate);
944  }
945 
946  /* Parse the with-check policy clause */
947  if (stmt->with_check)
948  {
949  RangeTblEntry *rte;
950  ParseState *with_check_pstate = make_parsestate(NULL);
951 
952  rte = addRangeTableEntryForRelation(with_check_pstate, target_table,
953  NULL, false, false);
954 
955  addRTEtoQuery(with_check_pstate, rte, false, true, true);
956 
957  with_check_qual = transformWhereClause(with_check_pstate,
958  copyObject(stmt->with_check),
960  "POLICY");
961 
962  /* Fix up collation information */
963  assign_expr_collations(with_check_pstate, with_check_qual);
964 
965  with_check_parse_rtable = with_check_pstate->p_rtable;
966  free_parsestate(with_check_pstate);
967  }
968 
969  /* zero-clear */
970  memset(values, 0, sizeof(values));
971  memset(replaces, 0, sizeof(replaces));
972  memset(isnull, 0, sizeof(isnull));
973 
974  /* Find policy to update. */
975  pg_policy_rel = heap_open(PolicyRelationId, RowExclusiveLock);
976 
977  /* Set key - policy's relation id. */
978  ScanKeyInit(&skey[0],
979  Anum_pg_policy_polrelid,
980  BTEqualStrategyNumber, F_OIDEQ,
981  ObjectIdGetDatum(table_id));
982 
983  /* Set key - policy's name. */
984  ScanKeyInit(&skey[1],
985  Anum_pg_policy_polname,
986  BTEqualStrategyNumber, F_NAMEEQ,
988 
989  sscan = systable_beginscan(pg_policy_rel,
990  PolicyPolrelidPolnameIndexId, true, NULL, 2,
991  skey);
992 
993  policy_tuple = systable_getnext(sscan);
994 
995  /* Check that the policy is found, raise an error if not. */
996  if (!HeapTupleIsValid(policy_tuple))
997  ereport(ERROR,
998  (errcode(ERRCODE_UNDEFINED_OBJECT),
999  errmsg("policy \"%s\" for table \"%s\" does not exist",
1000  stmt->policy_name,
1001  RelationGetRelationName(target_table))));
1002 
1003  /* Get policy command */
1004  polcmd_datum = heap_getattr(policy_tuple, Anum_pg_policy_polcmd,
1005  RelationGetDescr(pg_policy_rel),
1006  &polcmd_isnull);
1007  Assert(!polcmd_isnull);
1008  polcmd = DatumGetChar(polcmd_datum);
1009 
1010  /*
1011  * If the command is SELECT or DELETE then WITH CHECK should be NULL.
1012  */
1013  if ((polcmd == ACL_SELECT_CHR || polcmd == ACL_DELETE_CHR)
1014  && stmt->with_check != NULL)
1015  ereport(ERROR,
1016  (errcode(ERRCODE_SYNTAX_ERROR),
1017  errmsg("only USING expression allowed for SELECT, DELETE")));
1018 
1019  /*
1020  * If the command is INSERT then WITH CHECK should be the only expression
1021  * provided.
1022  */
1023  if ((polcmd == ACL_INSERT_CHR)
1024  && stmt->qual != NULL)
1025  ereport(ERROR,
1026  (errcode(ERRCODE_SYNTAX_ERROR),
1027  errmsg("only WITH CHECK expression allowed for INSERT")));
1028 
1029  policy_id = HeapTupleGetOid(policy_tuple);
1030 
1031  if (role_ids != NULL)
1032  {
1033  replaces[Anum_pg_policy_polroles - 1] = true;
1034  values[Anum_pg_policy_polroles - 1] = PointerGetDatum(role_ids);
1035  }
1036  else
1037  {
1038  Oid *roles;
1039  Datum roles_datum;
1040  bool attr_isnull;
1041  ArrayType *policy_roles;
1042 
1043  /*
1044  * We need to pull the set of roles this policy applies to from what's
1045  * in the catalog, so that we can recreate the dependencies correctly
1046  * for the policy.
1047  */
1048 
1049  roles_datum = heap_getattr(policy_tuple, Anum_pg_policy_polroles,
1050  RelationGetDescr(pg_policy_rel),
1051  &attr_isnull);
1052  Assert(!attr_isnull);
1053 
1054  policy_roles = DatumGetArrayTypePCopy(roles_datum);
1055 
1056  roles = (Oid *) ARR_DATA_PTR(policy_roles);
1057 
1058  nitems = ARR_DIMS(policy_roles)[0];
1059 
1060  role_oids = (Datum *) palloc(nitems * sizeof(Datum));
1061 
1062  for (i = 0; i < nitems; i++)
1063  role_oids[i] = ObjectIdGetDatum(roles[i]);
1064  }
1065 
1066  if (qual != NULL)
1067  {
1068  replaces[Anum_pg_policy_polqual - 1] = true;
1069  values[Anum_pg_policy_polqual - 1]
1071  }
1072  else
1073  {
1074  Datum value_datum;
1075  bool attr_isnull;
1076 
1077  /*
1078  * We need to pull the USING expression and build the range table for
1079  * the policy from what's in the catalog, so that we can recreate the
1080  * dependencies correctly for the policy.
1081  */
1082 
1083  /* Check if the policy has a USING expr */
1084  value_datum = heap_getattr(policy_tuple, Anum_pg_policy_polqual,
1085  RelationGetDescr(pg_policy_rel),
1086  &attr_isnull);
1087  if (!attr_isnull)
1088  {
1089  char *qual_value;
1090  ParseState *qual_pstate;
1091 
1092  /* parsestate is built just to build the range table */
1093  qual_pstate = make_parsestate(NULL);
1094 
1095  qual_value = TextDatumGetCString(value_datum);
1096  qual = stringToNode(qual_value);
1097 
1098  /* Add this rel to the parsestate's rangetable, for dependencies */
1099  addRangeTableEntryForRelation(qual_pstate, target_table, NULL,
1100  false, false);
1101 
1102  qual_parse_rtable = qual_pstate->p_rtable;
1103  free_parsestate(qual_pstate);
1104  }
1105  }
1106 
1107  if (with_check_qual != NULL)
1108  {
1109  replaces[Anum_pg_policy_polwithcheck - 1] = true;
1110  values[Anum_pg_policy_polwithcheck - 1]
1111  = CStringGetTextDatum(nodeToString(with_check_qual));
1112  }
1113  else
1114  {
1115  Datum value_datum;
1116  bool attr_isnull;
1117 
1118  /*
1119  * We need to pull the WITH CHECK expression and build the range table
1120  * for the policy from what's in the catalog, so that we can recreate
1121  * the dependencies correctly for the policy.
1122  */
1123 
1124  /* Check if the policy has a WITH CHECK expr */
1125  value_datum = heap_getattr(policy_tuple, Anum_pg_policy_polwithcheck,
1126  RelationGetDescr(pg_policy_rel),
1127  &attr_isnull);
1128  if (!attr_isnull)
1129  {
1130  char *with_check_value;
1131  ParseState *with_check_pstate;
1132 
1133  /* parsestate is built just to build the range table */
1134  with_check_pstate = make_parsestate(NULL);
1135 
1136  with_check_value = TextDatumGetCString(value_datum);
1137  with_check_qual = stringToNode(with_check_value);
1138 
1139  /* Add this rel to the parsestate's rangetable, for dependencies */
1140  addRangeTableEntryForRelation(with_check_pstate, target_table, NULL,
1141  false, false);
1142 
1143  with_check_parse_rtable = with_check_pstate->p_rtable;
1144  free_parsestate(with_check_pstate);
1145  }
1146  }
1147 
1148  new_tuple = heap_modify_tuple(policy_tuple,
1149  RelationGetDescr(pg_policy_rel),
1150  values, isnull, replaces);
1151  CatalogTupleUpdate(pg_policy_rel, &new_tuple->t_self, new_tuple);
1152 
1153  /* Update Dependencies. */
1154  deleteDependencyRecordsFor(PolicyRelationId, policy_id, false);
1155 
1156  /* Record Dependencies */
1157  target.classId = RelationRelationId;
1158  target.objectId = table_id;
1159  target.objectSubId = 0;
1160 
1161  myself.classId = PolicyRelationId;
1162  myself.objectId = policy_id;
1163  myself.objectSubId = 0;
1164 
1165  recordDependencyOn(&myself, &target, DEPENDENCY_AUTO);
1166 
1167  recordDependencyOnExpr(&myself, qual, qual_parse_rtable, DEPENDENCY_NORMAL);
1168 
1169  recordDependencyOnExpr(&myself, with_check_qual, with_check_parse_rtable,
1171 
1172  /* Register role dependencies */
1173  deleteSharedDependencyRecordsFor(PolicyRelationId, policy_id, 0);
1174  target.classId = AuthIdRelationId;
1175  target.objectSubId = 0;
1176  for (i = 0; i < nitems; i++)
1177  {
1178  target.objectId = DatumGetObjectId(role_oids[i]);
1179  /* no dependency if public */
1180  if (target.objectId != ACL_ID_PUBLIC)
1181  recordSharedDependencyOn(&myself, &target,
1183  }
1184 
1185  InvokeObjectPostAlterHook(PolicyRelationId, policy_id, 0);
1186 
1187  heap_freetuple(new_tuple);
1188 
1189  /* Invalidate Relation Cache */
1190  CacheInvalidateRelcache(target_table);
1191 
1192  /* Clean up. */
1193  systable_endscan(sscan);
1194  relation_close(target_table, NoLock);
1195  heap_close(pg_policy_rel, RowExclusiveLock);
1196 
1197  return myself;
1198 }
#define NIL
Definition: pg_list.h:69
#define ACL_INSERT_CHR
Definition: acl.h:138
void * stringToNode(char *str)
Definition: read.c:39
void recordSharedDependencyOn(ObjectAddress *depender, ObjectAddress *referenced, SharedDependencyType deptype)
Definition: pg_shdepend.c:115
void systable_endscan(SysScanDesc sysscan)
Definition: genam.c:502
#define RelationGetDescr(relation)
Definition: rel.h:433
#define PointerGetDatum(X)
Definition: postgres.h:539
#define DatumGetObjectId(X)
Definition: postgres.h:483
long deleteDependencyRecordsFor(Oid classId, Oid objectId, bool skipExtensionDeps)
Definition: pg_depend.c:191
#define ACL_DELETE_CHR
Definition: acl.h:141
ArrayType * construct_array(Datum *elems, int nelems, Oid elmtype, int elmlen, bool elmbyval, char elmalign)
Definition: arrayfuncs.c:3279
Definition: nodes.h:517
int errcode(int sqlerrcode)
Definition: elog.c:575
void relation_close(Relation relation, LOCKMODE lockmode)
Definition: heapam.c:1270
void recordDependencyOn(const ObjectAddress *depender, const ObjectAddress *referenced, DependencyType behavior)
Definition: pg_depend.c:44
#define heap_close(r, l)
Definition: heapam.h:97
void heap_freetuple(HeapTuple htup)
Definition: heaptuple.c:1773
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:331
RangeVar * table
Definition: parsenodes.h:2343
ParseState * make_parsestate(ParseState *parentParseState)
Definition: parse_node.c:44
void assign_expr_collations(ParseState *pstate, Node *expr)
HeapTuple systable_getnext(SysScanDesc sysscan)
Definition: genam.c:419
char * policy_name
Definition: parsenodes.h:2342
#define ObjectIdGetDatum(X)
Definition: postgres.h:490
#define ERROR
Definition: elog.h:43
#define ARR_DIMS(a)
Definition: array.h:279
ItemPointerData t_self
Definition: htup.h:65
#define ARR_DATA_PTR(a)
Definition: array.h:307
#define NoLock
Definition: lockdefs.h:34
#define RowExclusiveLock
Definition: lockdefs.h:38
#define CStringGetDatum(X)
Definition: postgres.h:561
void recordDependencyOnExpr(const ObjectAddress *depender, Node *expr, List *rtable, DependencyType behavior)
Definition: dependency.c:1360
#define RelationGetRelationName(relation)
Definition: rel.h:441
Oid RangeVarGetRelidExtended(const RangeVar *relation, LOCKMODE lockmode, uint32 flags, RangeVarGetRelidCallback callback, void *callback_arg)
Definition: namespace.c:227
#define PolicyPolrelidPolnameIndexId
Definition: indexing.h:332
#define ereport(elevel, rest)
Definition: elog.h:122
#define InvokeObjectPostAlterHook(classId, objectId, subId)
Definition: objectaccess.h:163
void addRTEtoQuery(ParseState *pstate, RangeTblEntry *rte, bool addToJoinList, bool addToRelNameSpace, bool addToVarNameSpace)
void deleteSharedDependencyRecordsFor(Oid classId, Oid objectId, int32 objectSubId)
Definition: pg_shdepend.c:823
#define heap_getattr(tup, attnum, tupleDesc, isnull)
Definition: htup_details.h:786
#define ACL_SELECT_CHR
Definition: acl.h:139
#define TextDatumGetCString(d)
Definition: builtins.h:96
uintptr_t Datum
Definition: postgres.h:365
#define DatumGetChar(X)
Definition: postgres.h:392
#define DatumGetArrayTypePCopy(X)
Definition: array.h:247
Relation heap_open(Oid relationId, LOCKMODE lockmode)
Definition: heapam.c:1294
#define HeapTupleIsValid(tuple)
Definition: htup.h:78
#define Assert(condition)
Definition: c.h:699
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:138
void CatalogTupleUpdate(Relation heapRel, ItemPointer otid, HeapTuple tup)
Definition: indexing.c:211
RangeTblEntry * addRangeTableEntryForRelation(ParseState *pstate, Relation rel, Alias *alias, bool inh, bool inFromCl)
void CacheInvalidateRelcache(Relation relation)
Definition: inval.c:1233
static Datum values[MAXATTR]
Definition: bootstrap.c:164
#define AccessExclusiveLock
Definition: lockdefs.h:45
void * palloc(Size size)
Definition: mcxt.c:924
int errmsg(const char *fmt,...)
Definition: elog.c:797
static void RangeVarCallbackForPolicy(const RangeVar *rv, Oid relid, Oid oldrelid, void *arg)
Definition: policy.c:65
int i
void ScanKeyInit(ScanKey entry, AttrNumber attributeNumber, StrategyNumber strategy, RegProcedure procedure, Datum argument)
Definition: scankey.c:76
#define CStringGetTextDatum(s)
Definition: builtins.h:95
char * nodeToString(const void *obj)
Definition: outfuncs.c:4331
#define ACL_ID_PUBLIC
Definition: acl.h:47
Relation relation_open(Oid relationId, LOCKMODE lockmode)
Definition: heapam.c:1124
#define HeapTupleGetOid(tuple)
Definition: htup_details.h:712
#define copyObject(obj)
Definition: nodes.h:630
void free_parsestate(ParseState *pstate)
Definition: parse_node.c:77
HeapTuple heap_modify_tuple(HeapTuple tuple, TupleDesc tupleDesc, Datum *replValues, bool *replIsnull, bool *doReplace)
Definition: heaptuple.c:1173
Definition: pg_list.h:45
#define BTEqualStrategyNumber
Definition: stratnum.h:31
List * p_rtable
Definition: parse_node.h:174

◆ CreatePolicy()

ObjectAddress CreatePolicy ( CreatePolicyStmt stmt)

Definition at line 686 of file policy.c.

References AccessExclusiveLock, 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(), heap_close, heap_form_tuple(), heap_freetuple(), heap_open(), 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(), 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, transformWhereClause(), values, and CreatePolicyStmt::with_check.

Referenced by ProcessUtilitySlow().

687 {
688  Relation pg_policy_rel;
689  Oid policy_id;
690  Relation target_table;
691  Oid table_id;
692  char polcmd;
693  Datum *role_oids;
694  int nitems = 0;
695  ArrayType *role_ids;
696  ParseState *qual_pstate;
697  ParseState *with_check_pstate;
698  RangeTblEntry *rte;
699  Node *qual;
700  Node *with_check_qual;
701  ScanKeyData skey[2];
702  SysScanDesc sscan;
703  HeapTuple policy_tuple;
704  Datum values[Natts_pg_policy];
705  bool isnull[Natts_pg_policy];
706  ObjectAddress target;
707  ObjectAddress myself;
708  int i;
709 
710  /* Parse command */
711  polcmd = parse_policy_command(stmt->cmd_name);
712 
713  /*
714  * If the command is SELECT or DELETE then WITH CHECK should be NULL.
715  */
716  if ((polcmd == ACL_SELECT_CHR || polcmd == ACL_DELETE_CHR)
717  && stmt->with_check != NULL)
718  ereport(ERROR,
719  (errcode(ERRCODE_SYNTAX_ERROR),
720  errmsg("WITH CHECK cannot be applied to SELECT or DELETE")));
721 
722  /*
723  * If the command is INSERT then WITH CHECK should be the only expression
724  * provided.
725  */
726  if (polcmd == ACL_INSERT_CHR && stmt->qual != NULL)
727  ereport(ERROR,
728  (errcode(ERRCODE_SYNTAX_ERROR),
729  errmsg("only WITH CHECK expression allowed for INSERT")));
730 
731  /* Collect role ids */
732  role_oids = policy_role_list_to_array(stmt->roles, &nitems);
733  role_ids = construct_array(role_oids, nitems, OIDOID,
734  sizeof(Oid), true, 'i');
735 
736  /* Parse the supplied clause */
737  qual_pstate = make_parsestate(NULL);
738  with_check_pstate = make_parsestate(NULL);
739 
740  /* zero-clear */
741  memset(values, 0, sizeof(values));
742  memset(isnull, 0, sizeof(isnull));
743 
744  /* Get id of table. Also handles permissions checks. */
746  0,
748  (void *) stmt);
749 
750  /* Open target_table to build quals. No additional lock is necessary. */
751  target_table = relation_open(table_id, NoLock);
752 
753  /* Add for the regular security quals */
754  rte = addRangeTableEntryForRelation(qual_pstate, target_table,
755  NULL, false, false);
756  addRTEtoQuery(qual_pstate, rte, false, true, true);
757 
758  /* Add for the with-check quals */
759  rte = addRangeTableEntryForRelation(with_check_pstate, target_table,
760  NULL, false, false);
761  addRTEtoQuery(with_check_pstate, rte, false, true, true);
762 
763  qual = transformWhereClause(qual_pstate,
764  copyObject(stmt->qual),
766  "POLICY");
767 
768  with_check_qual = transformWhereClause(with_check_pstate,
769  copyObject(stmt->with_check),
771  "POLICY");
772 
773  /* Fix up collation information */
774  assign_expr_collations(qual_pstate, qual);
775  assign_expr_collations(with_check_pstate, with_check_qual);
776 
777  /* Open pg_policy catalog */
778  pg_policy_rel = heap_open(PolicyRelationId, RowExclusiveLock);
779 
780  /* Set key - policy's relation id. */
781  ScanKeyInit(&skey[0],
782  Anum_pg_policy_polrelid,
783  BTEqualStrategyNumber, F_OIDEQ,
784  ObjectIdGetDatum(table_id));
785 
786  /* Set key - policy's name. */
787  ScanKeyInit(&skey[1],
788  Anum_pg_policy_polname,
789  BTEqualStrategyNumber, F_NAMEEQ,
791 
792  sscan = systable_beginscan(pg_policy_rel,
793  PolicyPolrelidPolnameIndexId, true, NULL, 2,
794  skey);
795 
796  policy_tuple = systable_getnext(sscan);
797 
798  /* Complain if the policy name already exists for the table */
799  if (HeapTupleIsValid(policy_tuple))
800  ereport(ERROR,
802  errmsg("policy \"%s\" for table \"%s\" already exists",
803  stmt->policy_name, RelationGetRelationName(target_table))));
804 
805  values[Anum_pg_policy_polrelid - 1] = ObjectIdGetDatum(table_id);
806  values[Anum_pg_policy_polname - 1] = DirectFunctionCall1(namein,
808  values[Anum_pg_policy_polcmd - 1] = CharGetDatum(polcmd);
809  values[Anum_pg_policy_polpermissive - 1] = BoolGetDatum(stmt->permissive);
810  values[Anum_pg_policy_polroles - 1] = PointerGetDatum(role_ids);
811 
812  /* Add qual if present. */
813  if (qual)
814  values[Anum_pg_policy_polqual - 1] = CStringGetTextDatum(nodeToString(qual));
815  else
816  isnull[Anum_pg_policy_polqual - 1] = true;
817 
818  /* Add WITH CHECK qual if present */
819  if (with_check_qual)
820  values[Anum_pg_policy_polwithcheck - 1] = CStringGetTextDatum(nodeToString(with_check_qual));
821  else
822  isnull[Anum_pg_policy_polwithcheck - 1] = true;
823 
824  policy_tuple = heap_form_tuple(RelationGetDescr(pg_policy_rel), values,
825  isnull);
826 
827  policy_id = CatalogTupleInsert(pg_policy_rel, policy_tuple);
828 
829  /* Record Dependencies */
830  target.classId = RelationRelationId;
831  target.objectId = table_id;
832  target.objectSubId = 0;
833 
834  myself.classId = PolicyRelationId;
835  myself.objectId = policy_id;
836  myself.objectSubId = 0;
837 
838  recordDependencyOn(&myself, &target, DEPENDENCY_AUTO);
839 
840  recordDependencyOnExpr(&myself, qual, qual_pstate->p_rtable,
842 
843  recordDependencyOnExpr(&myself, with_check_qual,
844  with_check_pstate->p_rtable, DEPENDENCY_NORMAL);
845 
846  /* Register role dependencies */
847  target.classId = AuthIdRelationId;
848  target.objectSubId = 0;
849  for (i = 0; i < nitems; i++)
850  {
851  target.objectId = DatumGetObjectId(role_oids[i]);
852  /* no dependency if public */
853  if (target.objectId != ACL_ID_PUBLIC)
854  recordSharedDependencyOn(&myself, &target,
856  }
857 
858  InvokeObjectPostCreateHook(PolicyRelationId, policy_id, 0);
859 
860  /* Invalidate Relation Cache */
861  CacheInvalidateRelcache(target_table);
862 
863  /* Clean up. */
864  heap_freetuple(policy_tuple);
865  free_parsestate(qual_pstate);
866  free_parsestate(with_check_pstate);
867  systable_endscan(sscan);
868  relation_close(target_table, NoLock);
869  heap_close(pg_policy_rel, RowExclusiveLock);
870 
871  return myself;
872 }
#define ACL_INSERT_CHR
Definition: acl.h:138
void recordSharedDependencyOn(ObjectAddress *depender, ObjectAddress *referenced, SharedDependencyType deptype)
Definition: pg_shdepend.c:115
Datum namein(PG_FUNCTION_ARGS)
Definition: name.c:46
void systable_endscan(SysScanDesc sysscan)
Definition: genam.c:502
#define InvokeObjectPostCreateHook(classId, objectId, subId)
Definition: objectaccess.h:145
#define RelationGetDescr(relation)
Definition: rel.h:433
#define PointerGetDatum(X)
Definition: postgres.h:539
#define DatumGetObjectId(X)
Definition: postgres.h:483
#define ACL_DELETE_CHR
Definition: acl.h:141
ArrayType * construct_array(Datum *elems, int nelems, Oid elmtype, int elmlen, bool elmbyval, char elmalign)
Definition: arrayfuncs.c:3279
Definition: nodes.h:517
int errcode(int sqlerrcode)
Definition: elog.c:575
void relation_close(Relation relation, LOCKMODE lockmode)
Definition: heapam.c:1270
static char parse_policy_command(const char *cmd_name)
Definition: policy.c:109
void recordDependencyOn(const ObjectAddress *depender, const ObjectAddress *referenced, DependencyType behavior)
Definition: pg_depend.c:44
HeapTuple heap_form_tuple(TupleDesc tupleDescriptor, Datum *values, bool *isnull)
Definition: heaptuple.c:1074
#define heap_close(r, l)
Definition: heapam.h:97
#define DirectFunctionCall1(func, arg1)
Definition: fmgr.h:590
void heap_freetuple(HeapTuple htup)
Definition: heaptuple.c:1773
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:331
ParseState * make_parsestate(ParseState *parentParseState)
Definition: parse_node.c:44
void assign_expr_collations(ParseState *pstate, Node *expr)
HeapTuple systable_getnext(SysScanDesc sysscan)
Definition: genam.c:419
#define ObjectIdGetDatum(X)
Definition: postgres.h:490
#define ERROR
Definition: elog.h:43
Oid CatalogTupleInsert(Relation heapRel, HeapTuple tup)
Definition: indexing.c:163
#define NoLock
Definition: lockdefs.h:34
#define RowExclusiveLock
Definition: lockdefs.h:38
#define CStringGetDatum(X)
Definition: postgres.h:561
void recordDependencyOnExpr(const ObjectAddress *depender, Node *expr, List *rtable, DependencyType behavior)
Definition: dependency.c:1360
#define RelationGetRelationName(relation)
Definition: rel.h:441
Oid RangeVarGetRelidExtended(const RangeVar *relation, LOCKMODE lockmode, uint32 flags, RangeVarGetRelidCallback callback, void *callback_arg)
Definition: namespace.c:227
#define PolicyPolrelidPolnameIndexId
Definition: indexing.h:332
#define ereport(elevel, rest)
Definition: elog.h:122
void addRTEtoQuery(ParseState *pstate, RangeTblEntry *rte, bool addToJoinList, bool addToRelNameSpace, bool addToVarNameSpace)
#define ACL_SELECT_CHR
Definition: acl.h:139
uintptr_t Datum
Definition: postgres.h:365
Relation heap_open(Oid relationId, LOCKMODE lockmode)
Definition: heapam.c:1294
#define BoolGetDatum(X)
Definition: postgres.h:385
#define HeapTupleIsValid(tuple)
Definition: htup.h:78
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:138
RangeTblEntry * addRangeTableEntryForRelation(ParseState *pstate, Relation rel, Alias *alias, bool inh, bool inFromCl)
#define CharGetDatum(X)
Definition: postgres.h:399
RangeVar * table
Definition: parsenodes.h:2327
void CacheInvalidateRelcache(Relation relation)
Definition: inval.c:1233
static Datum values[MAXATTR]
Definition: bootstrap.c:164
#define AccessExclusiveLock
Definition: lockdefs.h:45
int errmsg(const char *fmt,...)
Definition: elog.c:797
static void RangeVarCallbackForPolicy(const RangeVar *rv, Oid relid, Oid oldrelid, void *arg)
Definition: policy.c:65
int i
void ScanKeyInit(ScanKey entry, AttrNumber attributeNumber, StrategyNumber strategy, RegProcedure procedure, Datum argument)
Definition: scankey.c:76
#define CStringGetTextDatum(s)
Definition: builtins.h:95
char * nodeToString(const void *obj)
Definition: outfuncs.c:4331
#define ACL_ID_PUBLIC
Definition: acl.h:47
Relation relation_open(Oid relationId, LOCKMODE lockmode)
Definition: heapam.c:1124
#define copyObject(obj)
Definition: nodes.h:630
void free_parsestate(ParseState *pstate)
Definition: parse_node.c:77
#define ERRCODE_DUPLICATE_OBJECT
Definition: streamutil.c:32
#define BTEqualStrategyNumber
Definition: stratnum.h:31
List * p_rtable
Definition: parse_node.h:174

◆ get_relation_policy_oid()

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

Definition at line 1314 of file policy.c.

References AccessShareLock, BTEqualStrategyNumber, CStringGetDatum, ereport, errcode(), errmsg(), ERROR, get_rel_name(), heap_close, heap_open(), HeapTupleGetOid, HeapTupleIsValid, InvalidOid, ObjectIdGetDatum, PolicyPolrelidPolnameIndexId, ScanKeyInit(), systable_beginscan(), systable_endscan(), and systable_getnext().

Referenced by get_object_address_relobject().

1315 {
1316  Relation pg_policy_rel;
1317  ScanKeyData skey[2];
1318  SysScanDesc sscan;
1319  HeapTuple policy_tuple;
1320  Oid policy_oid;
1321 
1322  pg_policy_rel = heap_open(PolicyRelationId, AccessShareLock);
1323 
1324  /* Add key - policy's relation id. */
1325  ScanKeyInit(&skey[0],
1326  Anum_pg_policy_polrelid,
1327  BTEqualStrategyNumber, F_OIDEQ,
1328  ObjectIdGetDatum(relid));
1329 
1330  /* Add key - policy's name. */
1331  ScanKeyInit(&skey[1],
1332  Anum_pg_policy_polname,
1333  BTEqualStrategyNumber, F_NAMEEQ,
1334  CStringGetDatum(policy_name));
1335 
1336  sscan = systable_beginscan(pg_policy_rel,
1337  PolicyPolrelidPolnameIndexId, true, NULL, 2,
1338  skey);
1339 
1340  policy_tuple = systable_getnext(sscan);
1341 
1342  if (!HeapTupleIsValid(policy_tuple))
1343  {
1344  if (!missing_ok)
1345  ereport(ERROR,
1346  (errcode(ERRCODE_UNDEFINED_OBJECT),
1347  errmsg("policy \"%s\" for table \"%s\" does not exist",
1348  policy_name, get_rel_name(relid))));
1349 
1350  policy_oid = InvalidOid;
1351  }
1352  else
1353  policy_oid = HeapTupleGetOid(policy_tuple);
1354 
1355  /* Clean up. */
1356  systable_endscan(sscan);
1357  heap_close(pg_policy_rel, AccessShareLock);
1358 
1359  return policy_oid;
1360 }
void systable_endscan(SysScanDesc sysscan)
Definition: genam.c:502
#define AccessShareLock
Definition: lockdefs.h:36
int errcode(int sqlerrcode)
Definition: elog.c:575
#define heap_close(r, l)
Definition: heapam.h:97
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:331
HeapTuple systable_getnext(SysScanDesc sysscan)
Definition: genam.c:419
#define ObjectIdGetDatum(X)
Definition: postgres.h:490
#define ERROR
Definition: elog.h:43
#define CStringGetDatum(X)
Definition: postgres.h:561
#define PolicyPolrelidPolnameIndexId
Definition: indexing.h:332
#define ereport(elevel, rest)
Definition: elog.h:122
Relation heap_open(Oid relationId, LOCKMODE lockmode)
Definition: heapam.c:1294
#define InvalidOid
Definition: postgres_ext.h:36
#define HeapTupleIsValid(tuple)
Definition: htup.h:78
int errmsg(const char *fmt,...)
Definition: elog.c:797
void ScanKeyInit(ScanKey entry, AttrNumber attributeNumber, StrategyNumber strategy, RegProcedure procedure, Datum argument)
Definition: scankey.c:76
#define HeapTupleGetOid(tuple)
Definition: htup_details.h:712
char * get_rel_name(Oid relid)
Definition: lsyscache.c:1730
#define BTEqualStrategyNumber
Definition: stratnum.h:31

◆ relation_has_policies()

bool relation_has_policies ( Relation  rel)

Definition at line 1366 of file policy.c.

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

Referenced by DefineQueryRewrite().

1367 {
1368  Relation catalog;
1369  ScanKeyData skey;
1370  SysScanDesc sscan;
1371  HeapTuple policy_tuple;
1372  bool ret = false;
1373 
1374  catalog = heap_open(PolicyRelationId, AccessShareLock);
1375  ScanKeyInit(&skey,
1376  Anum_pg_policy_polrelid,
1377  BTEqualStrategyNumber, F_OIDEQ,
1379  sscan = systable_beginscan(catalog, PolicyPolrelidPolnameIndexId, true,
1380  NULL, 1, &skey);
1381  policy_tuple = systable_getnext(sscan);
1382  if (HeapTupleIsValid(policy_tuple))
1383  ret = true;
1384 
1385  systable_endscan(sscan);
1386  heap_close(catalog, AccessShareLock);
1387 
1388  return ret;
1389 }
void systable_endscan(SysScanDesc sysscan)
Definition: genam.c:502
#define AccessShareLock
Definition: lockdefs.h:36
#define heap_close(r, l)
Definition: heapam.h:97
SysScanDesc systable_beginscan(Relation heapRelation, Oid indexId, bool indexOK, Snapshot snapshot, int nkeys, ScanKey key)
Definition: genam.c:331
HeapTuple systable_getnext(SysScanDesc sysscan)
Definition: genam.c:419
#define ObjectIdGetDatum(X)
Definition: postgres.h:490
#define PolicyPolrelidPolnameIndexId
Definition: indexing.h:332
Relation heap_open(Oid relationId, LOCKMODE lockmode)
Definition: heapam.c:1294
#define HeapTupleIsValid(tuple)
Definition: htup.h:78
void ScanKeyInit(ScanKey entry, AttrNumber attributeNumber, StrategyNumber strategy, RegProcedure procedure, Datum argument)
Definition: scankey.c:76
#define RelationGetRelid(relation)
Definition: rel.h:407
#define BTEqualStrategyNumber
Definition: stratnum.h:31

◆ RelationBuildRowSecurity()

void RelationBuildRowSecurity ( Relation  relation)

Definition at line 191 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_close, heap_getattr, heap_open(), 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(), TextDatumGetCString, and RowSecurityPolicy::with_check_qual.

Referenced by RelationBuildDesc(), and RelationCacheInitializePhase3().

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

◆ RemovePolicyById()

void RemovePolicyById ( Oid  policy_id)

Definition at line 353 of file policy.c.

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

Referenced by doDeletion().

354 {
355  Relation pg_policy_rel;
356  SysScanDesc sscan;
357  ScanKeyData skey[1];
358  HeapTuple tuple;
359  Oid relid;
360  Relation rel;
361 
362  pg_policy_rel = heap_open(PolicyRelationId, RowExclusiveLock);
363 
364  /*
365  * Find the policy to delete.
366  */
367  ScanKeyInit(&skey[0],
369  BTEqualStrategyNumber, F_OIDEQ,
370  ObjectIdGetDatum(policy_id));
371 
372  sscan = systable_beginscan(pg_policy_rel, PolicyOidIndexId, true,
373  NULL, 1, skey);
374 
375  tuple = systable_getnext(sscan);
376 
377  /* If the policy exists, then remove it, otherwise raise an error. */
378  if (!HeapTupleIsValid(tuple))
379  elog(ERROR, "could not find tuple for policy %u", policy_id);
380 
381  /*
382  * Open and exclusive-lock the relation the policy belongs to. (We need
383  * exclusive lock to lock out queries that might otherwise depend on the
384  * set of policies the rel has; furthermore we've got to hold the lock
385  * till commit.)
386  */
387  relid = ((Form_pg_policy) GETSTRUCT(tuple))->polrelid;
388 
389  rel = heap_open(relid, AccessExclusiveLock);
390  if (rel->rd_rel->relkind != RELKIND_RELATION &&
391  rel->rd_rel->relkind != RELKIND_PARTITIONED_TABLE)
392  ereport(ERROR,
393  (errcode(ERRCODE_WRONG_OBJECT_TYPE),
394  errmsg("\"%s\" is not a table",
395  RelationGetRelationName(rel))));
396 
398  ereport(ERROR,
399  (errcode(ERRCODE_INSUFFICIENT_PRIVILEGE),
400  errmsg("permission denied: \"%s\" is a system catalog",
401  RelationGetRelationName(rel))));
402 
403  CatalogTupleDelete(pg_policy_rel, &tuple->t_self);
404 
405  systable_endscan(sscan);
406 
407  /*
408  * Note that, unlike some of the other flags in pg_class, relrowsecurity
409  * is not just an indication of if policies exist. When relrowsecurity is
410  * set by a user, then all access to the relation must be through a
411  * policy. If no policy is defined for the relation then a default-deny
412  * policy is created and all records are filtered (except for queries from
413  * the owner).
414  */
416 
417  heap_close(rel, NoLock);
418 
419  /* Clean up */
420  heap_close(pg_policy_rel, RowExclusiveLock);
421 }
void systable_endscan(SysScanDesc sysscan)
Definition: genam.c:502
#define GETSTRUCT(TUP)
Definition: htup_details.h:673
bool IsSystemRelation(Relation relation)
Definition: catalog.c:63
#define ObjectIdAttributeNumber
Definition: sysattr.h:22
#define PolicyOidIndexId
Definition: indexing.h:329
int errcode(int sqlerrcode)
Definition: elog.c:575
void CatalogTupleDelete(Relation heapRel, ItemPointer tid)
Definition: indexing.c:256
#define heap_close(r, l)
Definition: heapam.h:97
Form_pg_class rd_rel
Definition: rel.h:84
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:331
HeapTuple systable_getnext(SysScanDesc sysscan)
Definition: genam.c:419
#define ObjectIdGetDatum(X)
Definition: postgres.h:490
#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:441
#define ereport(elevel, rest)
Definition: elog.h:122
Relation heap_open(Oid relationId, LOCKMODE lockmode)
Definition: heapam.c:1294
bool allowSystemTableMods
Definition: globals.c:121
FormData_pg_policy * Form_pg_policy
Definition: pg_policy.h:48
#define HeapTupleIsValid(tuple)
Definition: htup.h:78
void CacheInvalidateRelcache(Relation relation)
Definition: inval.c:1233
#define AccessExclusiveLock
Definition: lockdefs.h:45
int errmsg(const char *fmt,...)
Definition: elog.c:797
void ScanKeyInit(ScanKey entry, AttrNumber attributeNumber, StrategyNumber strategy, RegProcedure procedure, Datum argument)
Definition: scankey.c:76
#define elog
Definition: elog.h:219
#define BTEqualStrategyNumber
Definition: stratnum.h:31

◆ RemoveRoleFromObjectPolicy()

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

Definition at line 438 of file policy.c.

References AccessExclusiveLock, 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_close, heap_freetuple(), heap_getattr, heap_modify_tuple(), heap_open(), HeapTupleIsValid, i, InvokeObjectPostAlterHook, IsSystemRelation(), make_parsestate(), NameStr, NIL, NoLock, ObjectAddress::objectId, ObjectIdAttributeNumber, 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, TextDatumGetCString, values, and WARNING.

Referenced by shdepDropOwned().

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

◆ rename_policy()

ObjectAddress rename_policy ( RenameStmt stmt)

Definition at line 1205 of file policy.c.

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

Referenced by ExecRenameStmt().

1206 {
1207  Relation pg_policy_rel;
1208  Relation target_table;
1209  Oid table_id;
1210  Oid opoloid;
1211  ScanKeyData skey[2];
1212  SysScanDesc sscan;
1213  HeapTuple policy_tuple;
1214  ObjectAddress address;
1215 
1216  /* Get id of table. Also handles permissions checks. */
1218  0,
1220  (void *) stmt);
1221 
1222  target_table = relation_open(table_id, NoLock);
1223 
1224  pg_policy_rel = heap_open(PolicyRelationId, RowExclusiveLock);
1225 
1226  /* First pass -- check for conflict */
1227 
1228  /* Add key - policy's relation id. */
1229  ScanKeyInit(&skey[0],
1230  Anum_pg_policy_polrelid,
1231  BTEqualStrategyNumber, F_OIDEQ,
1232  ObjectIdGetDatum(table_id));
1233 
1234  /* Add key - policy's name. */
1235  ScanKeyInit(&skey[1],
1236  Anum_pg_policy_polname,
1237  BTEqualStrategyNumber, F_NAMEEQ,
1238  CStringGetDatum(stmt->newname));
1239 
1240  sscan = systable_beginscan(pg_policy_rel,
1241  PolicyPolrelidPolnameIndexId, true, NULL, 2,
1242  skey);
1243 
1244  if (HeapTupleIsValid(systable_getnext(sscan)))
1245  ereport(ERROR,
1247  errmsg("policy \"%s\" for table \"%s\" already exists",
1248  stmt->newname, RelationGetRelationName(target_table))));
1249 
1250  systable_endscan(sscan);
1251 
1252  /* Second pass -- find existing policy and update */
1253  /* Add key - policy's relation id. */
1254  ScanKeyInit(&skey[0],
1255  Anum_pg_policy_polrelid,
1256  BTEqualStrategyNumber, F_OIDEQ,
1257  ObjectIdGetDatum(table_id));
1258 
1259  /* Add key - policy's name. */
1260  ScanKeyInit(&skey[1],
1261  Anum_pg_policy_polname,
1262  BTEqualStrategyNumber, F_NAMEEQ,
1263  CStringGetDatum(stmt->subname));
1264 
1265  sscan = systable_beginscan(pg_policy_rel,
1266  PolicyPolrelidPolnameIndexId, true, NULL, 2,
1267  skey);
1268 
1269  policy_tuple = systable_getnext(sscan);
1270 
1271  /* Complain if we did not find the policy */
1272  if (!HeapTupleIsValid(policy_tuple))
1273  ereport(ERROR,
1274  (errcode(ERRCODE_UNDEFINED_OBJECT),
1275  errmsg("policy \"%s\" for table \"%s\" does not exist",
1276  stmt->subname, RelationGetRelationName(target_table))));
1277 
1278  opoloid = HeapTupleGetOid(policy_tuple);
1279 
1280  policy_tuple = heap_copytuple(policy_tuple);
1281 
1282  namestrcpy(&((Form_pg_policy) GETSTRUCT(policy_tuple))->polname,
1283  stmt->newname);
1284 
1285  CatalogTupleUpdate(pg_policy_rel, &policy_tuple->t_self, policy_tuple);
1286 
1287  InvokeObjectPostAlterHook(PolicyRelationId,
1288  HeapTupleGetOid(policy_tuple), 0);
1289 
1290  ObjectAddressSet(address, PolicyRelationId, opoloid);
1291 
1292  /*
1293  * Invalidate relation's relcache entry so that other backends (and this
1294  * one too!) are sent SI message to make them rebuild relcache entries.
1295  * (Ideally this should happen automatically...)
1296  */
1297  CacheInvalidateRelcache(target_table);
1298 
1299  /* Clean up. */
1300  systable_endscan(sscan);
1301  heap_close(pg_policy_rel, RowExclusiveLock);
1302  relation_close(target_table, NoLock);
1303 
1304  return address;
1305 }
HeapTuple heap_copytuple(HeapTuple tuple)
Definition: heaptuple.c:722
void systable_endscan(SysScanDesc sysscan)
Definition: genam.c:502
#define GETSTRUCT(TUP)
Definition: htup_details.h:673
char * subname
Definition: parsenodes.h:2847
int errcode(int sqlerrcode)
Definition: elog.c:575
void relation_close(Relation relation, LOCKMODE lockmode)
Definition: heapam.c:1270
#define heap_close(r, l)
Definition: heapam.h:97
char * newname
Definition: parsenodes.h:2849
unsigned int Oid
Definition: postgres_ext.h:31
int namestrcpy(Name name, const char *str)
Definition: name.c:216
SysScanDesc systable_beginscan(Relation heapRelation, Oid indexId, bool indexOK, Snapshot snapshot, int nkeys, ScanKey key)
Definition: genam.c:331
HeapTuple systable_getnext(SysScanDesc sysscan)
Definition: genam.c:419
#define ObjectIdGetDatum(X)
Definition: postgres.h:490
#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 CStringGetDatum(X)
Definition: postgres.h:561
#define RelationGetRelationName(relation)
Definition: rel.h:441
Oid RangeVarGetRelidExtended(const RangeVar *relation, LOCKMODE lockmode, uint32 flags, RangeVarGetRelidCallback callback, void *callback_arg)
Definition: namespace.c:227
#define PolicyPolrelidPolnameIndexId
Definition: indexing.h:332
#define ereport(elevel, rest)
Definition: elog.h:122
#define InvokeObjectPostAlterHook(classId, objectId, subId)
Definition: objectaccess.h:163
Relation heap_open(Oid relationId, LOCKMODE lockmode)
Definition: heapam.c:1294
RangeVar * relation
Definition: parsenodes.h:2845
FormData_pg_policy * Form_pg_policy
Definition: pg_policy.h:48
#define HeapTupleIsValid(tuple)
Definition: htup.h:78
void CatalogTupleUpdate(Relation heapRel, ItemPointer otid, HeapTuple tup)
Definition: indexing.c:211
#define ObjectAddressSet(addr, class_id, object_id)
Definition: objectaddress.h:40
void CacheInvalidateRelcache(Relation relation)
Definition: inval.c:1233
#define AccessExclusiveLock
Definition: lockdefs.h:45
int errmsg(const char *fmt,...)
Definition: elog.c:797
static void RangeVarCallbackForPolicy(const RangeVar *rv, Oid relid, Oid oldrelid, void *arg)
Definition: policy.c:65
void ScanKeyInit(ScanKey entry, AttrNumber attributeNumber, StrategyNumber strategy, RegProcedure procedure, Datum argument)
Definition: scankey.c:76
Relation relation_open(Oid relationId, LOCKMODE lockmode)
Definition: heapam.c:1124
#define HeapTupleGetOid(tuple)
Definition: htup_details.h:712
#define ERRCODE_DUPLICATE_OBJECT
Definition: streamutil.c:32
#define BTEqualStrategyNumber
Definition: stratnum.h:31