PostgreSQL Source Code  git master
policy.c File Reference
#include "postgres.h"
#include "access/genam.h"
#include "access/htup.h"
#include "access/htup_details.h"
#include "access/relation.h"
#include "access/sysattr.h"
#include "access/table.h"
#include "access/xact.h"
#include "catalog/catalog.h"
#include "catalog/dependency.h"
#include "catalog/indexing.h"
#include "catalog/namespace.h"
#include "catalog/objectaccess.h"
#include "catalog/pg_authid.h"
#include "catalog/pg_policy.h"
#include "catalog/pg_type.h"
#include "commands/policy.h"
#include "miscadmin.h"
#include "nodes/makefuncs.h"
#include "nodes/pg_list.h"
#include "parser/parse_clause.h"
#include "parser/parse_collate.h"
#include "parser/parse_node.h"
#include "parser/parse_relation.h"
#include "rewrite/rewriteManip.h"
#include "rewrite/rowsecurity.h"
#include "storage/lock.h"
#include "utils/acl.h"
#include "utils/array.h"
#include "utils/builtins.h"
#include "utils/fmgroids.h"
#include "utils/inval.h"
#include "utils/lsyscache.h"
#include "utils/memutils.h"
#include "utils/rel.h"
#include "utils/syscache.h"
Include dependency graph for policy.c:

Go to the source code of this file.

Functions

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

Function Documentation

◆ AlterPolicy()

ObjectAddress AlterPolicy ( AlterPolicyStmt stmt)

Definition at line 773 of file policy.c.

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

Referenced by ProcessUtilitySlow().

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

◆ CreatePolicy()

ObjectAddress CreatePolicy ( CreatePolicyStmt stmt)

Definition at line 573 of file policy.c.

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

Referenced by ProcessUtilitySlow().

574 {
575  Relation pg_policy_rel;
576  Oid policy_id;
577  Relation target_table;
578  Oid table_id;
579  char polcmd;
580  Datum *role_oids;
581  int nitems = 0;
582  ArrayType *role_ids;
583  ParseState *qual_pstate;
584  ParseState *with_check_pstate;
585  ParseNamespaceItem *nsitem;
586  Node *qual;
587  Node *with_check_qual;
588  ScanKeyData skey[2];
589  SysScanDesc sscan;
590  HeapTuple policy_tuple;
591  Datum values[Natts_pg_policy];
592  bool isnull[Natts_pg_policy];
593  ObjectAddress target;
594  ObjectAddress myself;
595  int i;
596 
597  /* Parse command */
598  polcmd = parse_policy_command(stmt->cmd_name);
599 
600  /*
601  * If the command is SELECT or DELETE then WITH CHECK should be NULL.
602  */
603  if ((polcmd == ACL_SELECT_CHR || polcmd == ACL_DELETE_CHR)
604  && stmt->with_check != NULL)
605  ereport(ERROR,
606  (errcode(ERRCODE_SYNTAX_ERROR),
607  errmsg("WITH CHECK cannot be applied to SELECT or DELETE")));
608 
609  /*
610  * If the command is INSERT then WITH CHECK should be the only expression
611  * provided.
612  */
613  if (polcmd == ACL_INSERT_CHR && stmt->qual != NULL)
614  ereport(ERROR,
615  (errcode(ERRCODE_SYNTAX_ERROR),
616  errmsg("only WITH CHECK expression allowed for INSERT")));
617 
618  /* Collect role ids */
619  role_oids = policy_role_list_to_array(stmt->roles, &nitems);
620  role_ids = construct_array(role_oids, nitems, OIDOID,
621  sizeof(Oid), true, TYPALIGN_INT);
622 
623  /* Parse the supplied clause */
624  qual_pstate = make_parsestate(NULL);
625  with_check_pstate = make_parsestate(NULL);
626 
627  /* zero-clear */
628  memset(values, 0, sizeof(values));
629  memset(isnull, 0, sizeof(isnull));
630 
631  /* Get id of table. Also handles permissions checks. */
633  0,
635  (void *) stmt);
636 
637  /* Open target_table to build quals. No additional lock is necessary. */
638  target_table = relation_open(table_id, NoLock);
639 
640  /* Add for the regular security quals */
641  nsitem = addRangeTableEntryForRelation(qual_pstate, target_table,
643  NULL, false, false);
644  addNSItemToQuery(qual_pstate, nsitem, false, true, true);
645 
646  /* Add for the with-check quals */
647  nsitem = addRangeTableEntryForRelation(with_check_pstate, target_table,
649  NULL, false, false);
650  addNSItemToQuery(with_check_pstate, nsitem, false, true, true);
651 
652  qual = transformWhereClause(qual_pstate,
653  stmt->qual,
655  "POLICY");
656 
657  with_check_qual = transformWhereClause(with_check_pstate,
658  stmt->with_check,
660  "POLICY");
661 
662  /* Fix up collation information */
663  assign_expr_collations(qual_pstate, qual);
664  assign_expr_collations(with_check_pstate, with_check_qual);
665 
666  /* Open pg_policy catalog */
667  pg_policy_rel = table_open(PolicyRelationId, RowExclusiveLock);
668 
669  /* Set key - policy's relation id. */
670  ScanKeyInit(&skey[0],
671  Anum_pg_policy_polrelid,
672  BTEqualStrategyNumber, F_OIDEQ,
673  ObjectIdGetDatum(table_id));
674 
675  /* Set key - policy's name. */
676  ScanKeyInit(&skey[1],
677  Anum_pg_policy_polname,
678  BTEqualStrategyNumber, F_NAMEEQ,
680 
681  sscan = systable_beginscan(pg_policy_rel,
682  PolicyPolrelidPolnameIndexId, true, NULL, 2,
683  skey);
684 
685  policy_tuple = systable_getnext(sscan);
686 
687  /* Complain if the policy name already exists for the table */
688  if (HeapTupleIsValid(policy_tuple))
689  ereport(ERROR,
691  errmsg("policy \"%s\" for table \"%s\" already exists",
692  stmt->policy_name, RelationGetRelationName(target_table))));
693 
694  policy_id = GetNewOidWithIndex(pg_policy_rel, PolicyOidIndexId,
695  Anum_pg_policy_oid);
696  values[Anum_pg_policy_oid - 1] = ObjectIdGetDatum(policy_id);
697  values[Anum_pg_policy_polrelid - 1] = ObjectIdGetDatum(table_id);
698  values[Anum_pg_policy_polname - 1] = DirectFunctionCall1(namein,
700  values[Anum_pg_policy_polcmd - 1] = CharGetDatum(polcmd);
701  values[Anum_pg_policy_polpermissive - 1] = BoolGetDatum(stmt->permissive);
702  values[Anum_pg_policy_polroles - 1] = PointerGetDatum(role_ids);
703 
704  /* Add qual if present. */
705  if (qual)
706  values[Anum_pg_policy_polqual - 1] = CStringGetTextDatum(nodeToString(qual));
707  else
708  isnull[Anum_pg_policy_polqual - 1] = true;
709 
710  /* Add WITH CHECK qual if present */
711  if (with_check_qual)
712  values[Anum_pg_policy_polwithcheck - 1] = CStringGetTextDatum(nodeToString(with_check_qual));
713  else
714  isnull[Anum_pg_policy_polwithcheck - 1] = true;
715 
716  policy_tuple = heap_form_tuple(RelationGetDescr(pg_policy_rel), values,
717  isnull);
718 
719  CatalogTupleInsert(pg_policy_rel, policy_tuple);
720 
721  /* Record Dependencies */
722  target.classId = RelationRelationId;
723  target.objectId = table_id;
724  target.objectSubId = 0;
725 
726  myself.classId = PolicyRelationId;
727  myself.objectId = policy_id;
728  myself.objectSubId = 0;
729 
730  recordDependencyOn(&myself, &target, DEPENDENCY_AUTO);
731 
732  recordDependencyOnExpr(&myself, qual, qual_pstate->p_rtable,
734 
735  recordDependencyOnExpr(&myself, with_check_qual,
736  with_check_pstate->p_rtable, DEPENDENCY_NORMAL);
737 
738  /* Register role dependencies */
739  target.classId = AuthIdRelationId;
740  target.objectSubId = 0;
741  for (i = 0; i < nitems; i++)
742  {
743  target.objectId = DatumGetObjectId(role_oids[i]);
744  /* no dependency if public */
745  if (target.objectId != ACL_ID_PUBLIC)
746  recordSharedDependencyOn(&myself, &target,
748  }
749 
750  InvokeObjectPostCreateHook(PolicyRelationId, policy_id, 0);
751 
752  /* Invalidate Relation Cache */
753  CacheInvalidateRelcache(target_table);
754 
755  /* Clean up. */
756  heap_freetuple(policy_tuple);
757  free_parsestate(qual_pstate);
758  free_parsestate(with_check_pstate);
759  systable_endscan(sscan);
760  relation_close(target_table, NoLock);
761  table_close(pg_policy_rel, RowExclusiveLock);
762 
763  return myself;
764 }
Oid GetNewOidWithIndex(Relation relation, Oid indexId, AttrNumber oidcolumn)
Definition: catalog.c:381
#define ACL_INSERT_CHR
Definition: acl.h:137
void recordSharedDependencyOn(ObjectAddress *depender, ObjectAddress *referenced, SharedDependencyType deptype)
Definition: pg_shdepend.c:120
Datum namein(PG_FUNCTION_ARGS)
Definition: name.c:48
void table_close(Relation relation, LOCKMODE lockmode)
Definition: table.c:167
void systable_endscan(SysScanDesc sysscan)
Definition: genam.c:595
#define InvokeObjectPostCreateHook(classId, objectId, subId)
Definition: objectaccess.h:151
#define RelationGetDescr(relation)
Definition: rel.h:503
#define PointerGetDatum(X)
Definition: postgres.h:600
#define DatumGetObjectId(X)
Definition: postgres.h:544
#define ACL_DELETE_CHR
Definition: acl.h:140
ArrayType * construct_array(Datum *elems, int nelems, Oid elmtype, int elmlen, bool elmbyval, char elmalign)
Definition: arrayfuncs.c:3319
#define AccessShareLock
Definition: lockdefs.h:36
void addNSItemToQuery(ParseState *pstate, ParseNamespaceItem *nsitem, bool addToJoinList, bool addToRelNameSpace, bool addToVarNameSpace)
Definition: nodes.h:537
int errcode(int sqlerrcode)
Definition: elog.c:698
static char parse_policy_command(const char *cmd_name)
Definition: policy.c:111
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:1020
#define DirectFunctionCall1(func, arg1)
Definition: fmgr.h:626
void heap_freetuple(HeapTuple htup)
Definition: heaptuple.c:1338
unsigned int Oid
Definition: postgres_ext.h:31
SysScanDesc systable_beginscan(Relation heapRelation, Oid indexId, bool indexOK, Snapshot snapshot, int nkeys, ScanKey key)
Definition: genam.c:383
ParseNamespaceItem * addRangeTableEntryForRelation(ParseState *pstate, Relation rel, int lockmode, Alias *alias, bool inh, bool inFromCl)
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:502
#define ObjectIdGetDatum(X)
Definition: postgres.h:551
#define ERROR
Definition: elog.h:46
Relation relation_open(Oid relationId, LOCKMODE lockmode)
Definition: relation.c:48
#define NoLock
Definition: lockdefs.h:34
#define RowExclusiveLock
Definition: lockdefs.h:38
#define CStringGetDatum(X)
Definition: postgres.h:622
void recordDependencyOnExpr(const ObjectAddress *depender, Node *expr, List *rtable, DependencyType behavior)
Definition: dependency.c:1571
#define RelationGetRelationName(relation)
Definition: rel.h:511
Oid RangeVarGetRelidExtended(const RangeVar *relation, LOCKMODE lockmode, uint32 flags, RangeVarGetRelidCallback callback, void *callback_arg)
Definition: namespace.c:237
#define ACL_SELECT_CHR
Definition: acl.h:138
uintptr_t Datum
Definition: postgres.h:411
#define BoolGetDatum(X)
Definition: postgres.h:446
#define ereport(elevel,...)
Definition: elog.h:157
#define HeapTupleIsValid(tuple)
Definition: htup.h:78
void relation_close(Relation relation, LOCKMODE lockmode)
Definition: relation.c:206
Node * transformWhereClause(ParseState *pstate, Node *clause, ParseExprKind exprKind, const char *constructName)
static Datum * policy_role_list_to_array(List *roles, int *num_roles)
Definition: policy.c:140
#define CharGetDatum(X)
Definition: postgres.h:460
RangeVar * table
Definition: parsenodes.h:2500
void CacheInvalidateRelcache(Relation relation)
Definition: inval.c:1362
static Datum values[MAXATTR]
Definition: bootstrap.c:156
#define AccessExclusiveLock
Definition: lockdefs.h:45
int errmsg(const char *fmt,...)
Definition: elog.c:909
static void RangeVarCallbackForPolicy(const RangeVar *rv, Oid relid, Oid oldrelid, void *arg)
Definition: policy.c:67
int i
void ScanKeyInit(ScanKey entry, AttrNumber attributeNumber, StrategyNumber strategy, RegProcedure procedure, Datum argument)
Definition: scankey.c:76
#define CStringGetTextDatum(s)
Definition: builtins.h:86
char * nodeToString(const void *obj)
Definition: outfuncs.c:4544
#define ACL_ID_PUBLIC
Definition: acl.h:46
void free_parsestate(ParseState *pstate)
Definition: parse_node.c:77
Relation table_open(Oid relationId, LOCKMODE lockmode)
Definition: table.c:39
#define ERRCODE_DUPLICATE_OBJECT
Definition: streamutil.c:32
void CatalogTupleInsert(Relation heapRel, HeapTuple tup)
Definition: indexing.c:221
#define BTEqualStrategyNumber
Definition: stratnum.h:31
List * p_rtable
Definition: parse_node.h:182

◆ get_relation_policy_oid()

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

Definition at line 1210 of file policy.c.

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().

1211 {
1212  Relation pg_policy_rel;
1213  ScanKeyData skey[2];
1214  SysScanDesc sscan;
1215  HeapTuple policy_tuple;
1216  Oid policy_oid;
1217 
1218  pg_policy_rel = table_open(PolicyRelationId, AccessShareLock);
1219 
1220  /* Add key - policy's relation id. */
1221  ScanKeyInit(&skey[0],
1222  Anum_pg_policy_polrelid,
1223  BTEqualStrategyNumber, F_OIDEQ,
1224  ObjectIdGetDatum(relid));
1225 
1226  /* Add key - policy's name. */
1227  ScanKeyInit(&skey[1],
1228  Anum_pg_policy_polname,
1229  BTEqualStrategyNumber, F_NAMEEQ,
1230  CStringGetDatum(policy_name));
1231 
1232  sscan = systable_beginscan(pg_policy_rel,
1233  PolicyPolrelidPolnameIndexId, true, NULL, 2,
1234  skey);
1235 
1236  policy_tuple = systable_getnext(sscan);
1237 
1238  if (!HeapTupleIsValid(policy_tuple))
1239  {
1240  if (!missing_ok)
1241  ereport(ERROR,
1242  (errcode(ERRCODE_UNDEFINED_OBJECT),
1243  errmsg("policy \"%s\" for table \"%s\" does not exist",
1244  policy_name, get_rel_name(relid))));
1245 
1246  policy_oid = InvalidOid;
1247  }
1248  else
1249  policy_oid = ((Form_pg_policy) GETSTRUCT(policy_tuple))->oid;
1250 
1251  /* Clean up. */
1252  systable_endscan(sscan);
1253  table_close(pg_policy_rel, AccessShareLock);
1254 
1255  return policy_oid;
1256 }
void table_close(Relation relation, LOCKMODE lockmode)
Definition: table.c:167
void systable_endscan(SysScanDesc sysscan)
Definition: genam.c:595
#define GETSTRUCT(TUP)
Definition: htup_details.h:654
#define AccessShareLock
Definition: lockdefs.h:36
int errcode(int sqlerrcode)
Definition: elog.c:698
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:383
HeapTuple systable_getnext(SysScanDesc sysscan)
Definition: genam.c:502
#define ObjectIdGetDatum(X)
Definition: postgres.h:551
#define ERROR
Definition: elog.h:46
#define CStringGetDatum(X)
Definition: postgres.h:622
#define InvalidOid
Definition: postgres_ext.h:36
FormData_pg_policy * Form_pg_policy
Definition: pg_policy.h:51
#define ereport(elevel,...)
Definition: elog.h:157
#define HeapTupleIsValid(tuple)
Definition: htup.h:78
int errmsg(const char *fmt,...)
Definition: elog.c:909
void ScanKeyInit(ScanKey entry, AttrNumber attributeNumber, StrategyNumber strategy, RegProcedure procedure, Datum argument)
Definition: scankey.c:76
Relation table_open(Oid relationId, LOCKMODE lockmode)
Definition: table.c:39
char * get_rel_name(Oid relid)
Definition: lsyscache.c:1899
#define BTEqualStrategyNumber
Definition: stratnum.h:31

◆ parse_policy_command()

static char parse_policy_command ( const char *  cmd_name)
static

Definition at line 111 of file policy.c.

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

Referenced by CreatePolicy().

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

◆ policy_role_list_to_array()

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

Definition at line 140 of file policy.c.

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

Referenced by AlterPolicy(), and CreatePolicy().

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

◆ RangeVarCallbackForPolicy()

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

Definition at line 67 of file policy.c.

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

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

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

◆ relation_has_policies()

bool relation_has_policies ( Relation  rel)

Definition at line 1262 of file policy.c.

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

Referenced by DefineQueryRewrite().

1263 {
1264  Relation catalog;
1265  ScanKeyData skey;
1266  SysScanDesc sscan;
1267  HeapTuple policy_tuple;
1268  bool ret = false;
1269 
1270  catalog = table_open(PolicyRelationId, AccessShareLock);
1271  ScanKeyInit(&skey,
1272  Anum_pg_policy_polrelid,
1273  BTEqualStrategyNumber, F_OIDEQ,
1275  sscan = systable_beginscan(catalog, PolicyPolrelidPolnameIndexId, true,
1276  NULL, 1, &skey);
1277  policy_tuple = systable_getnext(sscan);
1278  if (HeapTupleIsValid(policy_tuple))
1279  ret = true;
1280 
1281  systable_endscan(sscan);
1282  table_close(catalog, AccessShareLock);
1283 
1284  return ret;
1285 }
void table_close(Relation relation, LOCKMODE lockmode)
Definition: table.c:167
void systable_endscan(SysScanDesc sysscan)
Definition: genam.c:595
#define AccessShareLock
Definition: lockdefs.h:36
SysScanDesc systable_beginscan(Relation heapRelation, Oid indexId, bool indexOK, Snapshot snapshot, int nkeys, ScanKey key)
Definition: genam.c:383
HeapTuple systable_getnext(SysScanDesc sysscan)
Definition: genam.c:502
#define ObjectIdGetDatum(X)
Definition: postgres.h:551
#define HeapTupleIsValid(tuple)
Definition: htup.h:78
void ScanKeyInit(ScanKey entry, AttrNumber attributeNumber, StrategyNumber strategy, RegProcedure procedure, Datum argument)
Definition: scankey.c:76
Relation table_open(Oid relationId, LOCKMODE lockmode)
Definition: table.c:39
#define RelationGetRelid(relation)
Definition: rel.h:477
#define BTEqualStrategyNumber
Definition: stratnum.h:31

◆ RelationBuildRowSecurity()

void RelationBuildRowSecurity ( Relation  relation)

Definition at line 196 of file policy.c.

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

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 AllocSetContextCreate
Definition: memutils.h:173
void table_close(Relation relation, LOCKMODE lockmode)
Definition: table.c:167
void systable_endscan(SysScanDesc sysscan)
Definition: genam.c:595
#define GETSTRUCT(TUP)
Definition: htup_details.h:654
bool checkExprHasSubLink(Node *node)
Definition: rewriteManip.c:277
#define RelationGetDescr(relation)
Definition: rel.h:503
void MemoryContextSetParent(MemoryContext context, MemoryContext new_parent)
Definition: mcxt.c:361
#define ALLOCSET_SMALL_SIZES
Definition: memutils.h:205
static MemoryContext MemoryContextSwitchTo(MemoryContext context)
Definition: palloc.h:109
#define AccessShareLock
Definition: lockdefs.h:36
Definition: nodes.h:537
void * stringToNode(const char *str)
Definition: read.c:89
SysScanDesc systable_beginscan(Relation heapRelation, Oid indexId, bool indexOK, Snapshot snapshot, int nkeys, ScanKey key)
Definition: genam.c:383
HeapTuple systable_getnext(SysScanDesc sysscan)
Definition: genam.c:502
void pfree(void *pointer)
Definition: mcxt.c:1169
#define ObjectIdGetDatum(X)
Definition: postgres.h:551
#define ERROR
Definition: elog.h:46
#define MemoryContextCopyAndSetIdentifier(cxt, id)
Definition: memutils.h:98
Expr * with_check_qual
Definition: rowsecurity.h:27
#define RelationGetRelationName(relation)
Definition: rel.h:511
ArrayType * roles
Definition: rowsecurity.h:24
MemoryContext CurrentMemoryContext
Definition: mcxt.c:42
struct RowSecurityDesc * rd_rsdesc
Definition: rel.h:117
MemoryContext rscxt
Definition: rowsecurity.h:33
#define heap_getattr(tup, attnum, tupleDesc, isnull)
Definition: htup_details.h:761
#define TextDatumGetCString(d)
Definition: builtins.h:87
uintptr_t Datum
Definition: postgres.h:411
#define DatumGetArrayTypePCopy(X)
Definition: array.h:255
void * MemoryContextAllocZero(MemoryContext context, Size size)
Definition: mcxt.c:906
FormData_pg_policy * Form_pg_policy
Definition: pg_policy.h:51
List * lcons(void *datum, List *list)
Definition: list.c:468
#define HeapTupleIsValid(tuple)
Definition: htup.h:78
char * MemoryContextStrdup(MemoryContext context, const char *string)
Definition: mcxt.c:1286
#define elog(elevel,...)
Definition: elog.h:232
#define NameStr(name)
Definition: c.h:681
void ScanKeyInit(ScanKey entry, AttrNumber attributeNumber, StrategyNumber strategy, RegProcedure procedure, Datum argument)
Definition: scankey.c:76
Relation table_open(Oid relationId, LOCKMODE lockmode)
Definition: table.c:39
#define RelationGetRelid(relation)
Definition: rel.h:477
#define BTEqualStrategyNumber
Definition: stratnum.h:31
MemoryContext CacheMemoryContext
Definition: mcxt.c:51

◆ RemovePolicyById()

void RemovePolicyById ( Oid  policy_id)

Definition at line 335 of file policy.c.

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().

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 }
void table_close(Relation relation, LOCKMODE lockmode)
Definition: table.c:167
void systable_endscan(SysScanDesc sysscan)
Definition: genam.c:595
#define GETSTRUCT(TUP)
Definition: htup_details.h:654
bool IsSystemRelation(Relation relation)
Definition: catalog.c:74
int errcode(int sqlerrcode)
Definition: elog.c:698
void CatalogTupleDelete(Relation heapRel, ItemPointer tid)
Definition: indexing.c:350
Form_pg_class rd_rel
Definition: rel.h:109
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:383
HeapTuple systable_getnext(SysScanDesc sysscan)
Definition: genam.c:502
#define ObjectIdGetDatum(X)
Definition: postgres.h:551
#define ERROR
Definition: elog.h:46
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:511
bool allowSystemTableMods
Definition: globals.c:123
FormData_pg_policy * Form_pg_policy
Definition: pg_policy.h:51
#define ereport(elevel,...)
Definition: elog.h:157
#define HeapTupleIsValid(tuple)
Definition: htup.h:78
void CacheInvalidateRelcache(Relation relation)
Definition: inval.c:1362
#define AccessExclusiveLock
Definition: lockdefs.h:45
int errmsg(const char *fmt,...)
Definition: elog.c:909
#define elog(elevel,...)
Definition: elog.h:232
void ScanKeyInit(ScanKey entry, AttrNumber attributeNumber, StrategyNumber strategy, RegProcedure procedure, Datum argument)
Definition: scankey.c:76
Relation table_open(Oid relationId, LOCKMODE lockmode)
Definition: table.c:39
#define BTEqualStrategyNumber
Definition: stratnum.h:31

◆ RemoveRoleFromObjectPolicy()

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

Definition at line 419 of file policy.c.

References ACL_ID_PUBLIC, ARR_DATA_PTR, ARR_DIMS, Assert, BTEqualStrategyNumber, CacheInvalidateRelcacheByTuple(), CatalogTupleUpdate(), ObjectAddress::classId, CommandCounterIncrement(), construct_array(), DatumGetArrayTypePCopy, DatumGetObjectId, deleteSharedDependencyRecordsFor(), elog, ERROR, GETSTRUCT, heap_freetuple(), heap_getattr, heap_modify_tuple(), HeapTupleIsValid, i, InvokeObjectPostAlterHook, 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().

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(role_oids, num_roles, OIDOID,
504  sizeof(Oid), true, TYPALIGN_INT);
505 
506  replaces[Anum_pg_policy_polroles - 1] = true;
507  values[Anum_pg_policy_polroles - 1] = PointerGetDatum(role_ids);
508 
509  new_tuple = heap_modify_tuple(tuple,
510  RelationGetDescr(pg_policy_rel),
511  values, isnull, replaces);
512  CatalogTupleUpdate(pg_policy_rel, &new_tuple->t_self, new_tuple);
513 
514  /* Remove all the old shared dependencies (roles) */
515  deleteSharedDependencyRecordsFor(PolicyRelationId, policy_id, 0);
516 
517  /* Record the new shared dependencies (roles) */
518  myself.classId = PolicyRelationId;
519  myself.objectId = policy_id;
520  myself.objectSubId = 0;
521 
522  target.classId = AuthIdRelationId;
523  target.objectSubId = 0;
524  for (i = 0; i < num_roles; i++)
525  {
526  target.objectId = DatumGetObjectId(role_oids[i]);
527  /* no need for dependency on the public role */
528  if (target.objectId != ACL_ID_PUBLIC)
529  recordSharedDependencyOn(&myself, &target,
531  }
532 
533  InvokeObjectPostAlterHook(PolicyRelationId, policy_id, 0);
534 
535  heap_freetuple(new_tuple);
536 
537  /* Make updates visible */
539 
540  /*
541  * Invalidate relcache entry for rel the policy belongs to, to force
542  * redoing any dependent plans. In case of a race condition where the
543  * rel was just dropped, we need do nothing.
544  */
545  reltup = SearchSysCache1(RELOID, ObjectIdGetDatum(relid));
546  if (HeapTupleIsValid(reltup))
547  {
549  ReleaseSysCache(reltup);
550  }
551  }
552  else
553  {
554  /* No roles would remain, so drop the policy instead. */
555  keep_policy = false;
556  }
557 
558  /* Clean up. */
559  systable_endscan(sscan);
560 
561  table_close(pg_policy_rel, RowExclusiveLock);
562 
563  return keep_policy;
564 }
void recordSharedDependencyOn(ObjectAddress *depender, ObjectAddress *referenced, SharedDependencyType deptype)
Definition: pg_shdepend.c:120
void table_close(Relation relation, LOCKMODE lockmode)
Definition: table.c:167
void systable_endscan(SysScanDesc sysscan)
Definition: genam.c:595
#define GETSTRUCT(TUP)
Definition: htup_details.h:654
#define RelationGetDescr(relation)
Definition: rel.h:503
#define PointerGetDatum(X)
Definition: postgres.h:600
#define DatumGetObjectId(X)
Definition: postgres.h:544
ArrayType * construct_array(Datum *elems, int nelems, Oid elmtype, int elmlen, bool elmbyval, char elmalign)
Definition: arrayfuncs.c:3319
void heap_freetuple(HeapTuple htup)
Definition: heaptuple.c:1338
unsigned int Oid
Definition: postgres_ext.h:31
SysScanDesc systable_beginscan(Relation heapRelation, Oid indexId, bool indexOK, Snapshot snapshot, int nkeys, ScanKey key)
Definition: genam.c:383
HeapTuple systable_getnext(SysScanDesc sysscan)
Definition: genam.c:502
#define ObjectIdGetDatum(X)
Definition: postgres.h:551
#define ERROR
Definition: elog.h:46
#define ARR_DIMS(a)
Definition: array.h:287
ItemPointerData t_self
Definition: htup.h:65
#define ARR_DATA_PTR(a)
Definition: array.h:315
#define RowExclusiveLock
Definition: lockdefs.h:38
#define InvokeObjectPostAlterHook(classId, objectId, subId)
Definition: objectaccess.h:175
void deleteSharedDependencyRecordsFor(Oid classId, Oid objectId, int32 objectSubId)
Definition: pg_shdepend.c:997
#define heap_getattr(tup, attnum, tupleDesc, isnull)
Definition: htup_details.h:761
HeapTuple SearchSysCache1(int cacheId, Datum key1)
Definition: syscache.c:1127
uintptr_t Datum
Definition: postgres.h:411
void CommandCounterIncrement(void)
Definition: xact.c:1022
void ReleaseSysCache(HeapTuple tuple)
Definition: syscache.c:1175
#define DatumGetArrayTypePCopy(X)
Definition: array.h:255
FormData_pg_policy * Form_pg_policy
Definition: pg_policy.h:51
#define HeapTupleIsValid(tuple)
Definition: htup.h:78
#define Assert(condition)
Definition: c.h:804
void CatalogTupleUpdate(Relation heapRel, ItemPointer otid, HeapTuple tup)
Definition: indexing.c:301
static Datum values[MAXATTR]
Definition: bootstrap.c:156
void * palloc(Size size)
Definition: mcxt.c:1062
#define elog(elevel,...)
Definition: elog.h:232
int i
void ScanKeyInit(ScanKey entry, AttrNumber attributeNumber, StrategyNumber strategy, RegProcedure procedure, Datum argument)
Definition: scankey.c:76
#define ACL_ID_PUBLIC
Definition: acl.h:46
void CacheInvalidateRelcacheByTuple(HeapTuple classTuple)
Definition: inval.c:1398
Relation table_open(Oid relationId, LOCKMODE lockmode)
Definition: table.c:39
HeapTuple heap_modify_tuple(HeapTuple tuple, TupleDesc tupleDesc, Datum *replValues, bool *replIsnull, bool *doReplace)
Definition: heaptuple.c:1113
#define BTEqualStrategyNumber
Definition: stratnum.h:31

◆ rename_policy()

ObjectAddress rename_policy ( RenameStmt stmt)

Definition at line 1102 of file policy.c.

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

Referenced by ExecRenameStmt().

1103 {
1104  Relation pg_policy_rel;
1105  Relation target_table;
1106  Oid table_id;
1107  Oid opoloid;
1108  ScanKeyData skey[2];
1109  SysScanDesc sscan;
1110  HeapTuple policy_tuple;
1111  ObjectAddress address;
1112 
1113  /* Get id of table. Also handles permissions checks. */
1115  0,
1117  (void *) stmt);
1118 
1119  target_table = relation_open(table_id, NoLock);
1120 
1121  pg_policy_rel = table_open(PolicyRelationId, RowExclusiveLock);
1122 
1123  /* First pass -- check for conflict */
1124 
1125  /* Add key - policy's relation id. */
1126  ScanKeyInit(&skey[0],
1127  Anum_pg_policy_polrelid,
1128  BTEqualStrategyNumber, F_OIDEQ,
1129  ObjectIdGetDatum(table_id));
1130 
1131  /* Add key - policy's name. */
1132  ScanKeyInit(&skey[1],
1133  Anum_pg_policy_polname,
1134  BTEqualStrategyNumber, F_NAMEEQ,
1135  CStringGetDatum(stmt->newname));
1136 
1137  sscan = systable_beginscan(pg_policy_rel,
1138  PolicyPolrelidPolnameIndexId, true, NULL, 2,
1139  skey);
1140 
1141  if (HeapTupleIsValid(systable_getnext(sscan)))
1142  ereport(ERROR,
1144  errmsg("policy \"%s\" for table \"%s\" already exists",
1145  stmt->newname, RelationGetRelationName(target_table))));
1146 
1147  systable_endscan(sscan);
1148 
1149  /* Second pass -- find existing policy and update */
1150  /* Add key - policy's relation id. */
1151  ScanKeyInit(&skey[0],
1152  Anum_pg_policy_polrelid,
1153  BTEqualStrategyNumber, F_OIDEQ,
1154  ObjectIdGetDatum(table_id));
1155 
1156  /* Add key - policy's name. */
1157  ScanKeyInit(&skey[1],
1158  Anum_pg_policy_polname,
1159  BTEqualStrategyNumber, F_NAMEEQ,
1160  CStringGetDatum(stmt->subname));
1161 
1162  sscan = systable_beginscan(pg_policy_rel,
1163  PolicyPolrelidPolnameIndexId, true, NULL, 2,
1164  skey);
1165 
1166  policy_tuple = systable_getnext(sscan);
1167 
1168  /* Complain if we did not find the policy */
1169  if (!HeapTupleIsValid(policy_tuple))
1170  ereport(ERROR,
1171  (errcode(ERRCODE_UNDEFINED_OBJECT),
1172  errmsg("policy \"%s\" for table \"%s\" does not exist",
1173  stmt->subname, RelationGetRelationName(target_table))));
1174 
1175  opoloid = ((Form_pg_policy) GETSTRUCT(policy_tuple))->oid;
1176 
1177  policy_tuple = heap_copytuple(policy_tuple);
1178 
1179  namestrcpy(&((Form_pg_policy) GETSTRUCT(policy_tuple))->polname,
1180  stmt->newname);
1181 
1182  CatalogTupleUpdate(pg_policy_rel, &policy_tuple->t_self, policy_tuple);
1183 
1184  InvokeObjectPostAlterHook(PolicyRelationId, opoloid, 0);
1185 
1186  ObjectAddressSet(address, PolicyRelationId, opoloid);
1187 
1188  /*
1189  * Invalidate relation's relcache entry so that other backends (and this
1190  * one too!) are sent SI message to make them rebuild relcache entries.
1191  * (Ideally this should happen automatically...)
1192  */
1193  CacheInvalidateRelcache(target_table);
1194 
1195  /* Clean up. */
1196  systable_endscan(sscan);
1197  table_close(pg_policy_rel, RowExclusiveLock);
1198  relation_close(target_table, NoLock);
1199 
1200  return address;
1201 }
HeapTuple heap_copytuple(HeapTuple tuple)
Definition: heaptuple.c:680
void table_close(Relation relation, LOCKMODE lockmode)
Definition: table.c:167
void systable_endscan(SysScanDesc sysscan)
Definition: genam.c:595
#define GETSTRUCT(TUP)
Definition: htup_details.h:654
char * subname
Definition: parsenodes.h:3059
void namestrcpy(Name name, const char *str)
Definition: name.c:233
int errcode(int sqlerrcode)
Definition: elog.c:698
char * newname
Definition: parsenodes.h:3061
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:383
HeapTuple systable_getnext(SysScanDesc sysscan)
Definition: genam.c:502
#define ObjectIdGetDatum(X)
Definition: postgres.h:551
#define ERROR
Definition: elog.h:46
Relation relation_open(Oid relationId, LOCKMODE lockmode)
Definition: relation.c:48
ItemPointerData t_self
Definition: htup.h:65
#define NoLock
Definition: lockdefs.h:34
#define RowExclusiveLock
Definition: lockdefs.h:38
#define CStringGetDatum(X)
Definition: postgres.h:622
#define RelationGetRelationName(relation)
Definition: rel.h:511
Oid RangeVarGetRelidExtended(const RangeVar *relation, LOCKMODE lockmode, uint32 flags, RangeVarGetRelidCallback callback, void *callback_arg)
Definition: namespace.c:237
#define InvokeObjectPostAlterHook(classId, objectId, subId)
Definition: objectaccess.h:175
RangeVar * relation
Definition: parsenodes.h:3057
FormData_pg_policy * Form_pg_policy
Definition: pg_policy.h:51
#define ereport(elevel,...)
Definition: elog.h:157
#define HeapTupleIsValid(tuple)
Definition: htup.h:78
void relation_close(Relation relation, LOCKMODE lockmode)
Definition: relation.c:206
void CatalogTupleUpdate(Relation heapRel, ItemPointer otid, HeapTuple tup)
Definition: indexing.c:301
#define ObjectAddressSet(addr, class_id, object_id)
Definition: objectaddress.h:40
void CacheInvalidateRelcache(Relation relation)
Definition: inval.c:1362
#define AccessExclusiveLock
Definition: lockdefs.h:45
int errmsg(const char *fmt,...)
Definition: elog.c:909
static void RangeVarCallbackForPolicy(const RangeVar *rv, Oid relid, Oid oldrelid, void *arg)
Definition: policy.c:67
void ScanKeyInit(ScanKey entry, AttrNumber attributeNumber, StrategyNumber strategy, RegProcedure procedure, Datum argument)
Definition: scankey.c:76
Relation table_open(Oid relationId, LOCKMODE lockmode)
Definition: table.c:39
#define ERRCODE_DUPLICATE_OBJECT
Definition: streamutil.c:32
#define BTEqualStrategyNumber
Definition: stratnum.h:31