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 policy_id)
 
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 771 of file policy.c.

772 {
773  Relation pg_policy_rel;
774  Oid policy_id;
775  Relation target_table;
776  Oid table_id;
777  Datum *role_oids = NULL;
778  int nitems = 0;
779  ArrayType *role_ids = NULL;
780  List *qual_parse_rtable = NIL;
781  List *with_check_parse_rtable = NIL;
782  Node *qual = NULL;
783  Node *with_check_qual = NULL;
784  ScanKeyData skey[2];
785  SysScanDesc sscan;
786  HeapTuple policy_tuple;
787  HeapTuple new_tuple;
788  Datum values[Natts_pg_policy];
789  bool isnull[Natts_pg_policy];
790  bool replaces[Natts_pg_policy];
791  ObjectAddress target;
792  ObjectAddress myself;
793  Datum polcmd_datum;
794  char polcmd;
795  bool polcmd_isnull;
796  int i;
797 
798  /* Parse role_ids */
799  if (stmt->roles != NULL)
800  {
801  role_oids = policy_role_list_to_array(stmt->roles, &nitems);
802  role_ids = construct_array_builtin(role_oids, nitems, OIDOID);
803  }
804 
805  /* Get id of table. Also handles permissions checks. */
807  0,
809  (void *) stmt);
810 
811  target_table = relation_open(table_id, NoLock);
812 
813  /* Parse the using policy clause */
814  if (stmt->qual)
815  {
816  ParseNamespaceItem *nsitem;
817  ParseState *qual_pstate = make_parsestate(NULL);
818 
819  nsitem = addRangeTableEntryForRelation(qual_pstate, target_table,
821  NULL, false, false);
822 
823  addNSItemToQuery(qual_pstate, nsitem, false, true, true);
824 
825  qual = transformWhereClause(qual_pstate, stmt->qual,
827  "POLICY");
828 
829  /* Fix up collation information */
830  assign_expr_collations(qual_pstate, qual);
831 
832  qual_parse_rtable = qual_pstate->p_rtable;
833  free_parsestate(qual_pstate);
834  }
835 
836  /* Parse the with-check policy clause */
837  if (stmt->with_check)
838  {
839  ParseNamespaceItem *nsitem;
840  ParseState *with_check_pstate = make_parsestate(NULL);
841 
842  nsitem = addRangeTableEntryForRelation(with_check_pstate, target_table,
844  NULL, false, false);
845 
846  addNSItemToQuery(with_check_pstate, nsitem, false, true, true);
847 
848  with_check_qual = transformWhereClause(with_check_pstate,
849  stmt->with_check,
851  "POLICY");
852 
853  /* Fix up collation information */
854  assign_expr_collations(with_check_pstate, with_check_qual);
855 
856  with_check_parse_rtable = with_check_pstate->p_rtable;
857  free_parsestate(with_check_pstate);
858  }
859 
860  /* zero-clear */
861  memset(values, 0, sizeof(values));
862  memset(replaces, 0, sizeof(replaces));
863  memset(isnull, 0, sizeof(isnull));
864 
865  /* Find policy to update. */
866  pg_policy_rel = table_open(PolicyRelationId, RowExclusiveLock);
867 
868  /* Set key - policy's relation id. */
869  ScanKeyInit(&skey[0],
870  Anum_pg_policy_polrelid,
871  BTEqualStrategyNumber, F_OIDEQ,
872  ObjectIdGetDatum(table_id));
873 
874  /* Set key - policy's name. */
875  ScanKeyInit(&skey[1],
876  Anum_pg_policy_polname,
877  BTEqualStrategyNumber, F_NAMEEQ,
878  CStringGetDatum(stmt->policy_name));
879 
880  sscan = systable_beginscan(pg_policy_rel,
881  PolicyPolrelidPolnameIndexId, true, NULL, 2,
882  skey);
883 
884  policy_tuple = systable_getnext(sscan);
885 
886  /* Check that the policy is found, raise an error if not. */
887  if (!HeapTupleIsValid(policy_tuple))
888  ereport(ERROR,
889  (errcode(ERRCODE_UNDEFINED_OBJECT),
890  errmsg("policy \"%s\" for table \"%s\" does not exist",
891  stmt->policy_name,
892  RelationGetRelationName(target_table))));
893 
894  /* Get policy command */
895  polcmd_datum = heap_getattr(policy_tuple, Anum_pg_policy_polcmd,
896  RelationGetDescr(pg_policy_rel),
897  &polcmd_isnull);
898  Assert(!polcmd_isnull);
899  polcmd = DatumGetChar(polcmd_datum);
900 
901  /*
902  * If the command is SELECT or DELETE then WITH CHECK should be NULL.
903  */
904  if ((polcmd == ACL_SELECT_CHR || polcmd == ACL_DELETE_CHR)
905  && stmt->with_check != NULL)
906  ereport(ERROR,
907  (errcode(ERRCODE_SYNTAX_ERROR),
908  errmsg("only USING expression allowed for SELECT, DELETE")));
909 
910  /*
911  * If the command is INSERT then WITH CHECK should be the only expression
912  * provided.
913  */
914  if ((polcmd == ACL_INSERT_CHR)
915  && stmt->qual != NULL)
916  ereport(ERROR,
917  (errcode(ERRCODE_SYNTAX_ERROR),
918  errmsg("only WITH CHECK expression allowed for INSERT")));
919 
920  policy_id = ((Form_pg_policy) GETSTRUCT(policy_tuple))->oid;
921 
922  if (role_ids != NULL)
923  {
924  replaces[Anum_pg_policy_polroles - 1] = true;
925  values[Anum_pg_policy_polroles - 1] = PointerGetDatum(role_ids);
926  }
927  else
928  {
929  Oid *roles;
930  Datum roles_datum;
931  bool attr_isnull;
932  ArrayType *policy_roles;
933 
934  /*
935  * We need to pull the set of roles this policy applies to from what's
936  * in the catalog, so that we can recreate the dependencies correctly
937  * for the policy.
938  */
939 
940  roles_datum = heap_getattr(policy_tuple, Anum_pg_policy_polroles,
941  RelationGetDescr(pg_policy_rel),
942  &attr_isnull);
943  Assert(!attr_isnull);
944 
945  policy_roles = DatumGetArrayTypePCopy(roles_datum);
946 
947  roles = (Oid *) ARR_DATA_PTR(policy_roles);
948 
949  nitems = ARR_DIMS(policy_roles)[0];
950 
951  role_oids = (Datum *) palloc(nitems * sizeof(Datum));
952 
953  for (i = 0; i < nitems; i++)
954  role_oids[i] = ObjectIdGetDatum(roles[i]);
955  }
956 
957  if (qual != NULL)
958  {
959  replaces[Anum_pg_policy_polqual - 1] = true;
960  values[Anum_pg_policy_polqual - 1]
962  }
963  else
964  {
965  Datum value_datum;
966  bool attr_isnull;
967 
968  /*
969  * We need to pull the USING expression and build the range table for
970  * the policy from what's in the catalog, so that we can recreate the
971  * dependencies correctly for the policy.
972  */
973 
974  /* Check if the policy has a USING expr */
975  value_datum = heap_getattr(policy_tuple, Anum_pg_policy_polqual,
976  RelationGetDescr(pg_policy_rel),
977  &attr_isnull);
978  if (!attr_isnull)
979  {
980  char *qual_value;
981  ParseState *qual_pstate;
982 
983  /* parsestate is built just to build the range table */
984  qual_pstate = make_parsestate(NULL);
985 
986  qual_value = TextDatumGetCString(value_datum);
987  qual = stringToNode(qual_value);
988 
989  /* Add this rel to the parsestate's rangetable, for dependencies */
990  (void) addRangeTableEntryForRelation(qual_pstate, target_table,
992  NULL, false, false);
993 
994  qual_parse_rtable = qual_pstate->p_rtable;
995  free_parsestate(qual_pstate);
996  }
997  }
998 
999  if (with_check_qual != NULL)
1000  {
1001  replaces[Anum_pg_policy_polwithcheck - 1] = true;
1002  values[Anum_pg_policy_polwithcheck - 1]
1003  = CStringGetTextDatum(nodeToString(with_check_qual));
1004  }
1005  else
1006  {
1007  Datum value_datum;
1008  bool attr_isnull;
1009 
1010  /*
1011  * We need to pull the WITH CHECK expression and build the range table
1012  * for the policy from what's in the catalog, so that we can recreate
1013  * the dependencies correctly for the policy.
1014  */
1015 
1016  /* Check if the policy has a WITH CHECK expr */
1017  value_datum = heap_getattr(policy_tuple, Anum_pg_policy_polwithcheck,
1018  RelationGetDescr(pg_policy_rel),
1019  &attr_isnull);
1020  if (!attr_isnull)
1021  {
1022  char *with_check_value;
1023  ParseState *with_check_pstate;
1024 
1025  /* parsestate is built just to build the range table */
1026  with_check_pstate = make_parsestate(NULL);
1027 
1028  with_check_value = TextDatumGetCString(value_datum);
1029  with_check_qual = stringToNode(with_check_value);
1030 
1031  /* Add this rel to the parsestate's rangetable, for dependencies */
1032  (void) addRangeTableEntryForRelation(with_check_pstate,
1033  target_table,
1035  NULL, false, false);
1036 
1037  with_check_parse_rtable = with_check_pstate->p_rtable;
1038  free_parsestate(with_check_pstate);
1039  }
1040  }
1041 
1042  new_tuple = heap_modify_tuple(policy_tuple,
1043  RelationGetDescr(pg_policy_rel),
1044  values, isnull, replaces);
1045  CatalogTupleUpdate(pg_policy_rel, &new_tuple->t_self, new_tuple);
1046 
1047  /* Update Dependencies. */
1048  deleteDependencyRecordsFor(PolicyRelationId, policy_id, false);
1049 
1050  /* Record Dependencies */
1051  target.classId = RelationRelationId;
1052  target.objectId = table_id;
1053  target.objectSubId = 0;
1054 
1055  myself.classId = PolicyRelationId;
1056  myself.objectId = policy_id;
1057  myself.objectSubId = 0;
1058 
1059  recordDependencyOn(&myself, &target, DEPENDENCY_AUTO);
1060 
1061  recordDependencyOnExpr(&myself, qual, qual_parse_rtable, DEPENDENCY_NORMAL);
1062 
1063  recordDependencyOnExpr(&myself, with_check_qual, with_check_parse_rtable,
1065 
1066  /* Register role dependencies */
1067  deleteSharedDependencyRecordsFor(PolicyRelationId, policy_id, 0);
1068  target.classId = AuthIdRelationId;
1069  target.objectSubId = 0;
1070  for (i = 0; i < nitems; i++)
1071  {
1072  target.objectId = DatumGetObjectId(role_oids[i]);
1073  /* no dependency if public */
1074  if (target.objectId != ACL_ID_PUBLIC)
1075  recordSharedDependencyOn(&myself, &target,
1077  }
1078 
1079  InvokeObjectPostAlterHook(PolicyRelationId, policy_id, 0);
1080 
1081  heap_freetuple(new_tuple);
1082 
1083  /* Invalidate Relation Cache */
1084  CacheInvalidateRelcache(target_table);
1085 
1086  /* Clean up. */
1087  systable_endscan(sscan);
1088  relation_close(target_table, NoLock);
1089  table_close(pg_policy_rel, RowExclusiveLock);
1090 
1091  return myself;
1092 }
#define ACL_SELECT_CHR
Definition: acl.h:138
#define ACL_DELETE_CHR
Definition: acl.h:140
#define ACL_INSERT_CHR
Definition: acl.h:137
#define ACL_ID_PUBLIC
Definition: acl.h:46
#define DatumGetArrayTypePCopy(X)
Definition: array.h:255
#define ARR_DATA_PTR(a)
Definition: array.h:315
#define ARR_DIMS(a)
Definition: array.h:287
ArrayType * construct_array_builtin(Datum *elems, int nelems, Oid elmtype)
Definition: arrayfuncs.c:3361
static Datum values[MAXATTR]
Definition: bootstrap.c:156
#define CStringGetTextDatum(s)
Definition: builtins.h:94
#define TextDatumGetCString(d)
Definition: builtins.h:95
void recordDependencyOnExpr(const ObjectAddress *depender, Node *expr, List *rtable, DependencyType behavior)
Definition: dependency.c:1602
@ DEPENDENCY_AUTO
Definition: dependency.h:34
@ DEPENDENCY_NORMAL
Definition: dependency.h:33
@ SHARED_DEPENDENCY_POLICY
Definition: dependency.h:76
int errcode(int sqlerrcode)
Definition: elog.c:858
int errmsg(const char *fmt,...)
Definition: elog.c:1069
#define ERROR
Definition: elog.h:39
#define ereport(elevel,...)
Definition: elog.h:149
void systable_endscan(SysScanDesc sysscan)
Definition: genam.c:599
HeapTuple systable_getnext(SysScanDesc sysscan)
Definition: genam.c:506
SysScanDesc systable_beginscan(Relation heapRelation, Oid indexId, bool indexOK, Snapshot snapshot, int nkeys, ScanKey key)
Definition: genam.c:387
HeapTuple heap_modify_tuple(HeapTuple tuple, TupleDesc tupleDesc, Datum *replValues, bool *replIsnull, bool *doReplace)
Definition: heaptuple.c:1113
void heap_freetuple(HeapTuple htup)
Definition: heaptuple.c:1338
#define HeapTupleIsValid(tuple)
Definition: htup.h:78
static Datum heap_getattr(HeapTuple tup, int attnum, TupleDesc tupleDesc, bool *isnull)
Definition: htup_details.h:792
#define GETSTRUCT(TUP)
Definition: htup_details.h:653
#define nitems(x)
Definition: indent.h:31
#define stmt
Definition: indent_codes.h:59
void CatalogTupleUpdate(Relation heapRel, ItemPointer otid, HeapTuple tup)
Definition: indexing.c:313
void CacheInvalidateRelcache(Relation relation)
Definition: inval.c:1363
int i
Definition: isn.c:73
Assert(fmt[strlen(fmt) - 1] !='\n')
#define NoLock
Definition: lockdefs.h:34
#define AccessExclusiveLock
Definition: lockdefs.h:43
#define AccessShareLock
Definition: lockdefs.h:36
#define RowExclusiveLock
Definition: lockdefs.h:38
void * palloc(Size size)
Definition: mcxt.c:1226
Oid RangeVarGetRelidExtended(const RangeVar *relation, LOCKMODE lockmode, uint32 flags, RangeVarGetRelidCallback callback, void *callback_arg)
Definition: namespace.c:239
#define InvokeObjectPostAlterHook(classId, objectId, subId)
Definition: objectaccess.h:197
char * nodeToString(const void *obj)
Definition: outfuncs.c:877
Node * transformWhereClause(ParseState *pstate, Node *clause, ParseExprKind exprKind, const char *constructName)
void assign_expr_collations(ParseState *pstate, Node *expr)
void free_parsestate(ParseState *pstate)
Definition: parse_node.c:77
ParseState * make_parsestate(ParseState *parentParseState)
Definition: parse_node.c:44
@ EXPR_KIND_POLICY
Definition: parse_node.h:77
ParseNamespaceItem * addRangeTableEntryForRelation(ParseState *pstate, Relation rel, int lockmode, Alias *alias, bool inh, bool inFromCl)
void addNSItemToQuery(ParseState *pstate, ParseNamespaceItem *nsitem, bool addToJoinList, bool addToRelNameSpace, bool addToVarNameSpace)
void recordDependencyOn(const ObjectAddress *depender, const ObjectAddress *referenced, DependencyType behavior)
Definition: pg_depend.c:44
long deleteDependencyRecordsFor(Oid classId, Oid objectId, bool skipExtensionDeps)
Definition: pg_depend.c:300
#define NIL
Definition: pg_list.h:68
FormData_pg_policy * Form_pg_policy
Definition: pg_policy.h:51
void deleteSharedDependencyRecordsFor(Oid classId, Oid objectId, int32 objectSubId)
Definition: pg_shdepend.c:1002
void recordSharedDependencyOn(ObjectAddress *depender, ObjectAddress *referenced, SharedDependencyType deptype)
Definition: pg_shdepend.c:122
static void RangeVarCallbackForPolicy(const RangeVar *rv, Oid relid, Oid oldrelid, void *arg)
Definition: policy.c:67
static Datum * policy_role_list_to_array(List *roles, int *num_roles)
Definition: policy.c:140
static Datum PointerGetDatum(const void *X)
Definition: postgres.h:322
uintptr_t Datum
Definition: postgres.h:64
static Oid DatumGetObjectId(Datum X)
Definition: postgres.h:242
static Datum ObjectIdGetDatum(Oid X)
Definition: postgres.h:252
static char DatumGetChar(Datum X)
Definition: postgres.h:112
static Datum CStringGetDatum(const char *X)
Definition: postgres.h:350
unsigned int Oid
Definition: postgres_ext.h:31
void * stringToNode(const char *str)
Definition: read.c:90
#define RelationGetDescr(relation)
Definition: rel.h:530
#define RelationGetRelationName(relation)
Definition: rel.h:538
void ScanKeyInit(ScanKey entry, AttrNumber attributeNumber, StrategyNumber strategy, RegProcedure procedure, Datum argument)
Definition: scankey.c:76
void relation_close(Relation relation, LOCKMODE lockmode)
Definition: relation.c:206
Relation relation_open(Oid relationId, LOCKMODE lockmode)
Definition: relation.c:48
#define BTEqualStrategyNumber
Definition: stratnum.h:31
ItemPointerData t_self
Definition: htup.h:65
Definition: pg_list.h:54
Definition: nodes.h:129
List * p_rtable
Definition: parse_node.h:193
void table_close(Relation relation, LOCKMODE lockmode)
Definition: table.c:126
Relation table_open(Oid relationId, LOCKMODE lockmode)
Definition: table.c:40

References AccessExclusiveLock, AccessShareLock, ACL_DELETE_CHR, ACL_ID_PUBLIC, ACL_INSERT_CHR, ACL_SELECT_CHR, addNSItemToQuery(), addRangeTableEntryForRelation(), ARR_DATA_PTR, ARR_DIMS, Assert(), assign_expr_collations(), BTEqualStrategyNumber, CacheInvalidateRelcache(), CatalogTupleUpdate(), ObjectAddress::classId, construct_array_builtin(), 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, nitems, nodeToString(), NoLock, ObjectAddress::objectId, ObjectIdGetDatum(), ObjectAddress::objectSubId, ParseState::p_rtable, palloc(), PointerGetDatum(), policy_role_list_to_array(), RangeVarCallbackForPolicy(), RangeVarGetRelidExtended(), recordDependencyOn(), recordDependencyOnExpr(), recordSharedDependencyOn(), relation_close(), relation_open(), RelationGetDescr, RelationGetRelationName, RowExclusiveLock, ScanKeyInit(), SHARED_DEPENDENCY_POLICY, stmt, stringToNode(), systable_beginscan(), systable_endscan(), systable_getnext(), HeapTupleData::t_self, table_close(), table_open(), TextDatumGetCString, transformWhereClause(), and values.

Referenced by ProcessUtilitySlow().

◆ CreatePolicy()

ObjectAddress CreatePolicy ( CreatePolicyStmt stmt)

Definition at line 572 of file policy.c.

573 {
574  Relation pg_policy_rel;
575  Oid policy_id;
576  Relation target_table;
577  Oid table_id;
578  char polcmd;
579  Datum *role_oids;
580  int nitems = 0;
581  ArrayType *role_ids;
582  ParseState *qual_pstate;
583  ParseState *with_check_pstate;
584  ParseNamespaceItem *nsitem;
585  Node *qual;
586  Node *with_check_qual;
587  ScanKeyData skey[2];
588  SysScanDesc sscan;
589  HeapTuple policy_tuple;
590  Datum values[Natts_pg_policy];
591  bool isnull[Natts_pg_policy];
592  ObjectAddress target;
593  ObjectAddress myself;
594  int i;
595 
596  /* Parse command */
597  polcmd = parse_policy_command(stmt->cmd_name);
598 
599  /*
600  * If the command is SELECT or DELETE then WITH CHECK should be NULL.
601  */
602  if ((polcmd == ACL_SELECT_CHR || polcmd == ACL_DELETE_CHR)
603  && stmt->with_check != NULL)
604  ereport(ERROR,
605  (errcode(ERRCODE_SYNTAX_ERROR),
606  errmsg("WITH CHECK cannot be applied to SELECT or DELETE")));
607 
608  /*
609  * If the command is INSERT then WITH CHECK should be the only expression
610  * provided.
611  */
612  if (polcmd == ACL_INSERT_CHR && stmt->qual != NULL)
613  ereport(ERROR,
614  (errcode(ERRCODE_SYNTAX_ERROR),
615  errmsg("only WITH CHECK expression allowed for INSERT")));
616 
617  /* Collect role ids */
618  role_oids = policy_role_list_to_array(stmt->roles, &nitems);
619  role_ids = construct_array_builtin(role_oids, nitems, OIDOID);
620 
621  /* Parse the supplied clause */
622  qual_pstate = make_parsestate(NULL);
623  with_check_pstate = make_parsestate(NULL);
624 
625  /* zero-clear */
626  memset(values, 0, sizeof(values));
627  memset(isnull, 0, sizeof(isnull));
628 
629  /* Get id of table. Also handles permissions checks. */
631  0,
633  (void *) stmt);
634 
635  /* Open target_table to build quals. No additional lock is necessary. */
636  target_table = relation_open(table_id, NoLock);
637 
638  /* Add for the regular security quals */
639  nsitem = addRangeTableEntryForRelation(qual_pstate, target_table,
641  NULL, false, false);
642  addNSItemToQuery(qual_pstate, nsitem, false, true, true);
643 
644  /* Add for the with-check quals */
645  nsitem = addRangeTableEntryForRelation(with_check_pstate, target_table,
647  NULL, false, false);
648  addNSItemToQuery(with_check_pstate, nsitem, false, true, true);
649 
650  qual = transformWhereClause(qual_pstate,
651  stmt->qual,
653  "POLICY");
654 
655  with_check_qual = transformWhereClause(with_check_pstate,
656  stmt->with_check,
658  "POLICY");
659 
660  /* Fix up collation information */
661  assign_expr_collations(qual_pstate, qual);
662  assign_expr_collations(with_check_pstate, with_check_qual);
663 
664  /* Open pg_policy catalog */
665  pg_policy_rel = table_open(PolicyRelationId, RowExclusiveLock);
666 
667  /* Set key - policy's relation id. */
668  ScanKeyInit(&skey[0],
669  Anum_pg_policy_polrelid,
670  BTEqualStrategyNumber, F_OIDEQ,
671  ObjectIdGetDatum(table_id));
672 
673  /* Set key - policy's name. */
674  ScanKeyInit(&skey[1],
675  Anum_pg_policy_polname,
676  BTEqualStrategyNumber, F_NAMEEQ,
677  CStringGetDatum(stmt->policy_name));
678 
679  sscan = systable_beginscan(pg_policy_rel,
680  PolicyPolrelidPolnameIndexId, true, NULL, 2,
681  skey);
682 
683  policy_tuple = systable_getnext(sscan);
684 
685  /* Complain if the policy name already exists for the table */
686  if (HeapTupleIsValid(policy_tuple))
687  ereport(ERROR,
689  errmsg("policy \"%s\" for table \"%s\" already exists",
690  stmt->policy_name, RelationGetRelationName(target_table))));
691 
692  policy_id = GetNewOidWithIndex(pg_policy_rel, PolicyOidIndexId,
693  Anum_pg_policy_oid);
694  values[Anum_pg_policy_oid - 1] = ObjectIdGetDatum(policy_id);
695  values[Anum_pg_policy_polrelid - 1] = ObjectIdGetDatum(table_id);
696  values[Anum_pg_policy_polname - 1] = DirectFunctionCall1(namein,
697  CStringGetDatum(stmt->policy_name));
698  values[Anum_pg_policy_polcmd - 1] = CharGetDatum(polcmd);
699  values[Anum_pg_policy_polpermissive - 1] = BoolGetDatum(stmt->permissive);
700  values[Anum_pg_policy_polroles - 1] = PointerGetDatum(role_ids);
701 
702  /* Add qual if present. */
703  if (qual)
704  values[Anum_pg_policy_polqual - 1] = CStringGetTextDatum(nodeToString(qual));
705  else
706  isnull[Anum_pg_policy_polqual - 1] = true;
707 
708  /* Add WITH CHECK qual if present */
709  if (with_check_qual)
710  values[Anum_pg_policy_polwithcheck - 1] = CStringGetTextDatum(nodeToString(with_check_qual));
711  else
712  isnull[Anum_pg_policy_polwithcheck - 1] = true;
713 
714  policy_tuple = heap_form_tuple(RelationGetDescr(pg_policy_rel), values,
715  isnull);
716 
717  CatalogTupleInsert(pg_policy_rel, policy_tuple);
718 
719  /* Record Dependencies */
720  target.classId = RelationRelationId;
721  target.objectId = table_id;
722  target.objectSubId = 0;
723 
724  myself.classId = PolicyRelationId;
725  myself.objectId = policy_id;
726  myself.objectSubId = 0;
727 
728  recordDependencyOn(&myself, &target, DEPENDENCY_AUTO);
729 
730  recordDependencyOnExpr(&myself, qual, qual_pstate->p_rtable,
732 
733  recordDependencyOnExpr(&myself, with_check_qual,
734  with_check_pstate->p_rtable, DEPENDENCY_NORMAL);
735 
736  /* Register role dependencies */
737  target.classId = AuthIdRelationId;
738  target.objectSubId = 0;
739  for (i = 0; i < nitems; i++)
740  {
741  target.objectId = DatumGetObjectId(role_oids[i]);
742  /* no dependency if public */
743  if (target.objectId != ACL_ID_PUBLIC)
744  recordSharedDependencyOn(&myself, &target,
746  }
747 
748  InvokeObjectPostCreateHook(PolicyRelationId, policy_id, 0);
749 
750  /* Invalidate Relation Cache */
751  CacheInvalidateRelcache(target_table);
752 
753  /* Clean up. */
754  heap_freetuple(policy_tuple);
755  free_parsestate(qual_pstate);
756  free_parsestate(with_check_pstate);
757  systable_endscan(sscan);
758  relation_close(target_table, NoLock);
759  table_close(pg_policy_rel, RowExclusiveLock);
760 
761  return myself;
762 }
Oid GetNewOidWithIndex(Relation relation, Oid indexId, AttrNumber oidcolumn)
Definition: catalog.c:393
#define DirectFunctionCall1(func, arg1)
Definition: fmgr.h:642
HeapTuple heap_form_tuple(TupleDesc tupleDescriptor, Datum *values, bool *isnull)
Definition: heaptuple.c:1020
void CatalogTupleInsert(Relation heapRel, HeapTuple tup)
Definition: indexing.c:233
Datum namein(PG_FUNCTION_ARGS)
Definition: name.c:48
#define InvokeObjectPostCreateHook(classId, objectId, subId)
Definition: objectaccess.h:173
static char parse_policy_command(const char *cmd_name)
Definition: policy.c:111
static Datum BoolGetDatum(bool X)
Definition: postgres.h:102
static Datum CharGetDatum(char X)
Definition: postgres.h:122
#define ERRCODE_DUPLICATE_OBJECT
Definition: streamutil.c:32

References AccessExclusiveLock, AccessShareLock, ACL_DELETE_CHR, ACL_ID_PUBLIC, ACL_INSERT_CHR, ACL_SELECT_CHR, addNSItemToQuery(), addRangeTableEntryForRelation(), assign_expr_collations(), BoolGetDatum(), BTEqualStrategyNumber, CacheInvalidateRelcache(), CatalogTupleInsert(), CharGetDatum(), ObjectAddress::classId, construct_array_builtin(), 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(), nitems, nodeToString(), NoLock, ObjectAddress::objectId, ObjectIdGetDatum(), ObjectAddress::objectSubId, ParseState::p_rtable, parse_policy_command(), PointerGetDatum(), policy_role_list_to_array(), RangeVarCallbackForPolicy(), RangeVarGetRelidExtended(), recordDependencyOn(), recordDependencyOnExpr(), recordSharedDependencyOn(), relation_close(), relation_open(), RelationGetDescr, RelationGetRelationName, RowExclusiveLock, ScanKeyInit(), SHARED_DEPENDENCY_POLICY, stmt, systable_beginscan(), systable_endscan(), systable_getnext(), table_close(), table_open(), transformWhereClause(), and values.

Referenced by ProcessUtilitySlow().

◆ get_relation_policy_oid()

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

Definition at line 1207 of file policy.c.

1208 {
1209  Relation pg_policy_rel;
1210  ScanKeyData skey[2];
1211  SysScanDesc sscan;
1212  HeapTuple policy_tuple;
1213  Oid policy_oid;
1214 
1215  pg_policy_rel = table_open(PolicyRelationId, AccessShareLock);
1216 
1217  /* Add key - policy's relation id. */
1218  ScanKeyInit(&skey[0],
1219  Anum_pg_policy_polrelid,
1220  BTEqualStrategyNumber, F_OIDEQ,
1221  ObjectIdGetDatum(relid));
1222 
1223  /* Add key - policy's name. */
1224  ScanKeyInit(&skey[1],
1225  Anum_pg_policy_polname,
1226  BTEqualStrategyNumber, F_NAMEEQ,
1227  CStringGetDatum(policy_name));
1228 
1229  sscan = systable_beginscan(pg_policy_rel,
1230  PolicyPolrelidPolnameIndexId, true, NULL, 2,
1231  skey);
1232 
1233  policy_tuple = systable_getnext(sscan);
1234 
1235  if (!HeapTupleIsValid(policy_tuple))
1236  {
1237  if (!missing_ok)
1238  ereport(ERROR,
1239  (errcode(ERRCODE_UNDEFINED_OBJECT),
1240  errmsg("policy \"%s\" for table \"%s\" does not exist",
1241  policy_name, get_rel_name(relid))));
1242 
1243  policy_oid = InvalidOid;
1244  }
1245  else
1246  policy_oid = ((Form_pg_policy) GETSTRUCT(policy_tuple))->oid;
1247 
1248  /* Clean up. */
1249  systable_endscan(sscan);
1250  table_close(pg_policy_rel, AccessShareLock);
1251 
1252  return policy_oid;
1253 }
char * get_rel_name(Oid relid)
Definition: lsyscache.c:1910
#define InvalidOid
Definition: postgres_ext.h:36

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

Referenced by get_object_address_relobject().

◆ relation_has_policies()

bool relation_has_policies ( Relation  rel)

Definition at line 1259 of file policy.c.

1260 {
1261  Relation catalog;
1262  ScanKeyData skey;
1263  SysScanDesc sscan;
1264  HeapTuple policy_tuple;
1265  bool ret = false;
1266 
1267  catalog = table_open(PolicyRelationId, AccessShareLock);
1268  ScanKeyInit(&skey,
1269  Anum_pg_policy_polrelid,
1270  BTEqualStrategyNumber, F_OIDEQ,
1272  sscan = systable_beginscan(catalog, PolicyPolrelidPolnameIndexId, true,
1273  NULL, 1, &skey);
1274  policy_tuple = systable_getnext(sscan);
1275  if (HeapTupleIsValid(policy_tuple))
1276  ret = true;
1277 
1278  systable_endscan(sscan);
1279  table_close(catalog, AccessShareLock);
1280 
1281  return ret;
1282 }
#define RelationGetRelid(relation)
Definition: rel.h:504

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

◆ RelationBuildRowSecurity()

void RelationBuildRowSecurity ( Relation  relation)

Definition at line 196 of file policy.c.

197 {
198  MemoryContext rscxt;
200  RowSecurityDesc *rsdesc;
201  Relation catalog;
202  ScanKeyData skey;
203  SysScanDesc sscan;
204  HeapTuple tuple;
205 
206  /*
207  * Create a memory context to hold everything associated with this
208  * relation's row security policy. This makes it easy to clean up during
209  * a relcache flush. However, to cover the possibility of an error
210  * partway through, we don't make the context long-lived till we're done.
211  */
213  "row security descriptor",
216  RelationGetRelationName(relation));
217 
218  rsdesc = MemoryContextAllocZero(rscxt, sizeof(RowSecurityDesc));
219  rsdesc->rscxt = rscxt;
220 
221  /*
222  * Now scan pg_policy for RLS policies associated with this relation.
223  * Because we use the index on (polrelid, polname), we should consistently
224  * visit the rel's policies in name order, at least when system indexes
225  * aren't disabled. This simplifies equalRSDesc().
226  */
227  catalog = table_open(PolicyRelationId, AccessShareLock);
228 
229  ScanKeyInit(&skey,
230  Anum_pg_policy_polrelid,
231  BTEqualStrategyNumber, F_OIDEQ,
233 
234  sscan = systable_beginscan(catalog, PolicyPolrelidPolnameIndexId, true,
235  NULL, 1, &skey);
236 
237  while (HeapTupleIsValid(tuple = systable_getnext(sscan)))
238  {
239  Form_pg_policy policy_form = (Form_pg_policy) GETSTRUCT(tuple);
240  RowSecurityPolicy *policy;
241  Datum datum;
242  bool isnull;
243  char *str_value;
244 
245  policy = MemoryContextAllocZero(rscxt, sizeof(RowSecurityPolicy));
246 
247  /*
248  * Note: we must be sure that pass-by-reference data gets copied into
249  * rscxt. We avoid making that context current over wider spans than
250  * we have to, though.
251  */
252 
253  /* Get policy command */
254  policy->polcmd = policy_form->polcmd;
255 
256  /* Get policy, permissive or restrictive */
257  policy->permissive = policy_form->polpermissive;
258 
259  /* Get policy name */
260  policy->policy_name =
261  MemoryContextStrdup(rscxt, NameStr(policy_form->polname));
262 
263  /* Get policy roles */
264  datum = heap_getattr(tuple, Anum_pg_policy_polroles,
265  RelationGetDescr(catalog), &isnull);
266  /* shouldn't be null, but let's check for luck */
267  if (isnull)
268  elog(ERROR, "unexpected null value in pg_policy.polroles");
269  MemoryContextSwitchTo(rscxt);
270  policy->roles = DatumGetArrayTypePCopy(datum);
271  MemoryContextSwitchTo(oldcxt);
272 
273  /* Get policy qual */
274  datum = heap_getattr(tuple, Anum_pg_policy_polqual,
275  RelationGetDescr(catalog), &isnull);
276  if (!isnull)
277  {
278  str_value = TextDatumGetCString(datum);
279  MemoryContextSwitchTo(rscxt);
280  policy->qual = (Expr *) stringToNode(str_value);
281  MemoryContextSwitchTo(oldcxt);
282  pfree(str_value);
283  }
284  else
285  policy->qual = NULL;
286 
287  /* Get WITH CHECK qual */
288  datum = heap_getattr(tuple, Anum_pg_policy_polwithcheck,
289  RelationGetDescr(catalog), &isnull);
290  if (!isnull)
291  {
292  str_value = TextDatumGetCString(datum);
293  MemoryContextSwitchTo(rscxt);
294  policy->with_check_qual = (Expr *) stringToNode(str_value);
295  MemoryContextSwitchTo(oldcxt);
296  pfree(str_value);
297  }
298  else
299  policy->with_check_qual = NULL;
300 
301  /* We want to cache whether there are SubLinks in these expressions */
302  policy->hassublinks = checkExprHasSubLink((Node *) policy->qual) ||
304 
305  /*
306  * Add this object to list. For historical reasons, the list is built
307  * in reverse order.
308  */
309  MemoryContextSwitchTo(rscxt);
310  rsdesc->policies = lcons(policy, rsdesc->policies);
311  MemoryContextSwitchTo(oldcxt);
312  }
313 
314  systable_endscan(sscan);
315  table_close(catalog, AccessShareLock);
316 
317  /*
318  * Success. Reparent the descriptor's memory context under
319  * CacheMemoryContext so that it will live indefinitely, then attach the
320  * policy descriptor to the relcache entry.
321  */
323 
324  relation->rd_rsdesc = rsdesc;
325 }
#define NameStr(name)
Definition: c.h:730
List * lcons(void *datum, List *list)
Definition: list.c:494
void MemoryContextSetParent(MemoryContext context, MemoryContext new_parent)
Definition: mcxt.c:546
void pfree(void *pointer)
Definition: mcxt.c:1456
void * MemoryContextAllocZero(MemoryContext context, Size size)
Definition: mcxt.c:1064
MemoryContext CurrentMemoryContext
Definition: mcxt.c:135
char * MemoryContextStrdup(MemoryContext context, const char *string)
Definition: mcxt.c:1631
MemoryContext CacheMemoryContext
Definition: mcxt.c:144
#define AllocSetContextCreate
Definition: memutils.h:129
#define ALLOCSET_SMALL_SIZES
Definition: memutils.h:163
#define MemoryContextCopyAndSetIdentifier(cxt, id)
Definition: memutils.h:101
static MemoryContext MemoryContextSwitchTo(MemoryContext context)
Definition: palloc.h:138
bool checkExprHasSubLink(Node *node)
Definition: rewriteManip.c:295
struct RowSecurityDesc * rd_rsdesc
Definition: rel.h:119
MemoryContext rscxt
Definition: rowsecurity.h:33
ArrayType * roles
Definition: rowsecurity.h:24
Expr * with_check_qual
Definition: rowsecurity.h:27

References AccessShareLock, ALLOCSET_SMALL_SIZES, AllocSetContextCreate, BTEqualStrategyNumber, CacheMemoryContext, checkExprHasSubLink(), CurrentMemoryContext, DatumGetArrayTypePCopy, elog(), ERROR, GETSTRUCT, RowSecurityPolicy::hassublinks, heap_getattr(), HeapTupleIsValid, lcons(), MemoryContextAllocZero(), MemoryContextCopyAndSetIdentifier, MemoryContextSetParent(), MemoryContextStrdup(), MemoryContextSwitchTo(), NameStr, ObjectIdGetDatum(), RowSecurityPolicy::permissive, pfree(), RowSecurityPolicy::polcmd, RowSecurityDesc::policies, RowSecurityPolicy::policy_name, 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().

◆ RemovePolicyById()

void RemovePolicyById ( Oid  policy_id)

Definition at line 335 of file policy.c.

336 {
337  Relation pg_policy_rel;
338  SysScanDesc sscan;
339  ScanKeyData skey[1];
340  HeapTuple tuple;
341  Oid relid;
342  Relation rel;
343 
344  pg_policy_rel = table_open(PolicyRelationId, RowExclusiveLock);
345 
346  /*
347  * Find the policy to delete.
348  */
349  ScanKeyInit(&skey[0],
350  Anum_pg_policy_oid,
351  BTEqualStrategyNumber, F_OIDEQ,
352  ObjectIdGetDatum(policy_id));
353 
354  sscan = systable_beginscan(pg_policy_rel, PolicyOidIndexId, true,
355  NULL, 1, skey);
356 
357  tuple = systable_getnext(sscan);
358 
359  /* If the policy exists, then remove it, otherwise raise an error. */
360  if (!HeapTupleIsValid(tuple))
361  elog(ERROR, "could not find tuple for policy %u", policy_id);
362 
363  /*
364  * Open and exclusive-lock the relation the policy belongs to. (We need
365  * exclusive lock to lock out queries that might otherwise depend on the
366  * set of policies the rel has; furthermore we've got to hold the lock
367  * till commit.)
368  */
369  relid = ((Form_pg_policy) GETSTRUCT(tuple))->polrelid;
370 
371  rel = table_open(relid, AccessExclusiveLock);
372  if (rel->rd_rel->relkind != RELKIND_RELATION &&
373  rel->rd_rel->relkind != RELKIND_PARTITIONED_TABLE)
374  ereport(ERROR,
375  (errcode(ERRCODE_WRONG_OBJECT_TYPE),
376  errmsg("\"%s\" is not a table",
377  RelationGetRelationName(rel))));
378 
380  ereport(ERROR,
381  (errcode(ERRCODE_INSUFFICIENT_PRIVILEGE),
382  errmsg("permission denied: \"%s\" is a system catalog",
383  RelationGetRelationName(rel))));
384 
385  CatalogTupleDelete(pg_policy_rel, &tuple->t_self);
386 
387  systable_endscan(sscan);
388 
389  /*
390  * Note that, unlike some of the other flags in pg_class, relrowsecurity
391  * is not just an indication of if policies exist. When relrowsecurity is
392  * set by a user, then all access to the relation must be through a
393  * policy. If no policy is defined for the relation then a default-deny
394  * policy is created and all records are filtered (except for queries from
395  * the owner).
396  */
398 
399  table_close(rel, NoLock);
400 
401  /* Clean up */
402  table_close(pg_policy_rel, RowExclusiveLock);
403 }
bool IsSystemRelation(Relation relation)
Definition: catalog.c:75
bool allowSystemTableMods
Definition: globals.c:124
void CatalogTupleDelete(Relation heapRel, ItemPointer tid)
Definition: indexing.c:365
Form_pg_class rd_rel
Definition: rel.h:111

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

Referenced by doDeletion().

◆ RemoveRoleFromObjectPolicy()

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

Definition at line 419 of file policy.c.

420 {
421  Relation pg_policy_rel;
422  SysScanDesc sscan;
423  ScanKeyData skey[1];
424  HeapTuple tuple;
425  Oid relid;
426  ArrayType *policy_roles;
427  Datum roles_datum;
428  Oid *roles;
429  int num_roles;
430  Datum *role_oids;
431  bool attr_isnull;
432  bool keep_policy = true;
433  int i,
434  j;
435 
436  Assert(classid == PolicyRelationId);
437 
438  pg_policy_rel = table_open(PolicyRelationId, RowExclusiveLock);
439 
440  /*
441  * Find the policy to update.
442  */
443  ScanKeyInit(&skey[0],
444  Anum_pg_policy_oid,
445  BTEqualStrategyNumber, F_OIDEQ,
446  ObjectIdGetDatum(policy_id));
447 
448  sscan = systable_beginscan(pg_policy_rel, PolicyOidIndexId, true,
449  NULL, 1, skey);
450 
451  tuple = systable_getnext(sscan);
452 
453  /* Raise an error if we don't find the policy. */
454  if (!HeapTupleIsValid(tuple))
455  elog(ERROR, "could not find tuple for policy %u", policy_id);
456 
457  /* Identify rel the policy belongs to */
458  relid = ((Form_pg_policy) GETSTRUCT(tuple))->polrelid;
459 
460  /* Get the current set of roles */
461  roles_datum = heap_getattr(tuple,
462  Anum_pg_policy_polroles,
463  RelationGetDescr(pg_policy_rel),
464  &attr_isnull);
465 
466  Assert(!attr_isnull);
467 
468  policy_roles = DatumGetArrayTypePCopy(roles_datum);
469  roles = (Oid *) ARR_DATA_PTR(policy_roles);
470  num_roles = ARR_DIMS(policy_roles)[0];
471 
472  /*
473  * Rebuild the polroles array, without any mentions of the target role.
474  * Ordinarily there'd be exactly one, but we must cope with duplicate
475  * mentions, since CREATE/ALTER POLICY historically have allowed that.
476  */
477  role_oids = (Datum *) palloc(num_roles * sizeof(Datum));
478  for (i = 0, j = 0; i < num_roles; i++)
479  {
480  if (roles[i] != roleid)
481  role_oids[j++] = ObjectIdGetDatum(roles[i]);
482  }
483  num_roles = j;
484 
485  /* If any roles remain, update the policy entry. */
486  if (num_roles > 0)
487  {
488  ArrayType *role_ids;
489  Datum values[Natts_pg_policy];
490  bool isnull[Natts_pg_policy];
491  bool replaces[Natts_pg_policy];
492  HeapTuple new_tuple;
493  HeapTuple reltup;
494  ObjectAddress target;
495  ObjectAddress myself;
496 
497  /* zero-clear */
498  memset(values, 0, sizeof(values));
499  memset(replaces, 0, sizeof(replaces));
500  memset(isnull, 0, sizeof(isnull));
501 
502  /* This is the array for the new tuple */
503  role_ids = construct_array_builtin(role_oids, num_roles, OIDOID);
504 
505  replaces[Anum_pg_policy_polroles - 1] = true;
506  values[Anum_pg_policy_polroles - 1] = PointerGetDatum(role_ids);
507 
508  new_tuple = heap_modify_tuple(tuple,
509  RelationGetDescr(pg_policy_rel),
510  values, isnull, replaces);
511  CatalogTupleUpdate(pg_policy_rel, &new_tuple->t_self, new_tuple);
512 
513  /* Remove all the old shared dependencies (roles) */
514  deleteSharedDependencyRecordsFor(PolicyRelationId, policy_id, 0);
515 
516  /* Record the new shared dependencies (roles) */
517  myself.classId = PolicyRelationId;
518  myself.objectId = policy_id;
519  myself.objectSubId = 0;
520 
521  target.classId = AuthIdRelationId;
522  target.objectSubId = 0;
523  for (i = 0; i < num_roles; i++)
524  {
525  target.objectId = DatumGetObjectId(role_oids[i]);
526  /* no need for dependency on the public role */
527  if (target.objectId != ACL_ID_PUBLIC)
528  recordSharedDependencyOn(&myself, &target,
530  }
531 
532  InvokeObjectPostAlterHook(PolicyRelationId, policy_id, 0);
533 
534  heap_freetuple(new_tuple);
535 
536  /* Make updates visible */
538 
539  /*
540  * Invalidate relcache entry for rel the policy belongs to, to force
541  * redoing any dependent plans. In case of a race condition where the
542  * rel was just dropped, we need do nothing.
543  */
544  reltup = SearchSysCache1(RELOID, ObjectIdGetDatum(relid));
545  if (HeapTupleIsValid(reltup))
546  {
548  ReleaseSysCache(reltup);
549  }
550  }
551  else
552  {
553  /* No roles would remain, so drop the policy instead. */
554  keep_policy = false;
555  }
556 
557  /* Clean up. */
558  systable_endscan(sscan);
559 
560  table_close(pg_policy_rel, RowExclusiveLock);
561 
562  return keep_policy;
563 }
void CacheInvalidateRelcacheByTuple(HeapTuple classTuple)
Definition: inval.c:1399
int j
Definition: isn.c:74
void ReleaseSysCache(HeapTuple tuple)
Definition: syscache.c:866
HeapTuple SearchSysCache1(int cacheId, Datum key1)
Definition: syscache.c:818
@ RELOID
Definition: syscache.h:89
void CommandCounterIncrement(void)
Definition: xact.c:1078

References ACL_ID_PUBLIC, ARR_DATA_PTR, ARR_DIMS, Assert(), BTEqualStrategyNumber, CacheInvalidateRelcacheByTuple(), CatalogTupleUpdate(), ObjectAddress::classId, CommandCounterIncrement(), construct_array_builtin(), DatumGetArrayTypePCopy, DatumGetObjectId(), deleteSharedDependencyRecordsFor(), elog(), ERROR, GETSTRUCT, heap_freetuple(), heap_getattr(), heap_modify_tuple(), HeapTupleIsValid, i, InvokeObjectPostAlterHook, j, ObjectAddress::objectId, ObjectIdGetDatum(), ObjectAddress::objectSubId, palloc(), PointerGetDatum(), recordSharedDependencyOn(), RelationGetDescr, ReleaseSysCache(), RELOID, RowExclusiveLock, ScanKeyInit(), SearchSysCache1(), SHARED_DEPENDENCY_POLICY, systable_beginscan(), systable_endscan(), systable_getnext(), HeapTupleData::t_self, table_close(), table_open(), and values.

Referenced by shdepDropOwned().

◆ rename_policy()

ObjectAddress rename_policy ( RenameStmt stmt)

Definition at line 1099 of file policy.c.

1100 {
1101  Relation pg_policy_rel;
1102  Relation target_table;
1103  Oid table_id;
1104  Oid opoloid;
1105  ScanKeyData skey[2];
1106  SysScanDesc sscan;
1107  HeapTuple policy_tuple;
1108  ObjectAddress address;
1109 
1110  /* Get id of table. Also handles permissions checks. */
1111  table_id = RangeVarGetRelidExtended(stmt->relation, AccessExclusiveLock,
1112  0,
1114  (void *) stmt);
1115 
1116  target_table = relation_open(table_id, NoLock);
1117 
1118  pg_policy_rel = table_open(PolicyRelationId, RowExclusiveLock);
1119 
1120  /* First pass -- check for conflict */
1121 
1122  /* Add key - policy's relation id. */
1123  ScanKeyInit(&skey[0],
1124  Anum_pg_policy_polrelid,
1125  BTEqualStrategyNumber, F_OIDEQ,
1126  ObjectIdGetDatum(table_id));
1127 
1128  /* Add key - policy's name. */
1129  ScanKeyInit(&skey[1],
1130  Anum_pg_policy_polname,
1131  BTEqualStrategyNumber, F_NAMEEQ,
1132  CStringGetDatum(stmt->newname));
1133 
1134  sscan = systable_beginscan(pg_policy_rel,
1135  PolicyPolrelidPolnameIndexId, true, NULL, 2,
1136  skey);
1137 
1138  if (HeapTupleIsValid(systable_getnext(sscan)))
1139  ereport(ERROR,
1141  errmsg("policy \"%s\" for table \"%s\" already exists",
1142  stmt->newname, RelationGetRelationName(target_table))));
1143 
1144  systable_endscan(sscan);
1145 
1146  /* Second pass -- find existing policy and update */
1147  /* Add key - policy's relation id. */
1148  ScanKeyInit(&skey[0],
1149  Anum_pg_policy_polrelid,
1150  BTEqualStrategyNumber, F_OIDEQ,
1151  ObjectIdGetDatum(table_id));
1152 
1153  /* Add key - policy's name. */
1154  ScanKeyInit(&skey[1],
1155  Anum_pg_policy_polname,
1156  BTEqualStrategyNumber, F_NAMEEQ,
1157  CStringGetDatum(stmt->subname));
1158 
1159  sscan = systable_beginscan(pg_policy_rel,
1160  PolicyPolrelidPolnameIndexId, true, NULL, 2,
1161  skey);
1162 
1163  policy_tuple = systable_getnext(sscan);
1164 
1165  /* Complain if we did not find the policy */
1166  if (!HeapTupleIsValid(policy_tuple))
1167  ereport(ERROR,
1168  (errcode(ERRCODE_UNDEFINED_OBJECT),
1169  errmsg("policy \"%s\" for table \"%s\" does not exist",
1170  stmt->subname, RelationGetRelationName(target_table))));
1171 
1172  opoloid = ((Form_pg_policy) GETSTRUCT(policy_tuple))->oid;
1173 
1174  policy_tuple = heap_copytuple(policy_tuple);
1175 
1176  namestrcpy(&((Form_pg_policy) GETSTRUCT(policy_tuple))->polname,
1177  stmt->newname);
1178 
1179  CatalogTupleUpdate(pg_policy_rel, &policy_tuple->t_self, policy_tuple);
1180 
1181  InvokeObjectPostAlterHook(PolicyRelationId, opoloid, 0);
1182 
1183  ObjectAddressSet(address, PolicyRelationId, opoloid);
1184 
1185  /*
1186  * Invalidate relation's relcache entry so that other backends (and this
1187  * one too!) are sent SI message to make them rebuild relcache entries.
1188  * (Ideally this should happen automatically...)
1189  */
1190  CacheInvalidateRelcache(target_table);
1191 
1192  /* Clean up. */
1193  systable_endscan(sscan);
1194  table_close(pg_policy_rel, RowExclusiveLock);
1195  relation_close(target_table, NoLock);
1196 
1197  return address;
1198 }
HeapTuple heap_copytuple(HeapTuple tuple)
Definition: heaptuple.c:680
void namestrcpy(Name name, const char *str)
Definition: name.c:233
#define ObjectAddressSet(addr, class_id, object_id)
Definition: objectaddress.h:40

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

Referenced by ExecRenameStmt().