PostgreSQL Source Code git master
All Data Structures Namespaces Files Functions Variables Typedefs Enumerations Enumerator Macros Pages
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 768 of file policy.c.

769{
770 Relation pg_policy_rel;
771 Oid policy_id;
772 Relation target_table;
773 Oid table_id;
774 Datum *role_oids = NULL;
775 int nitems = 0;
776 ArrayType *role_ids = NULL;
777 List *qual_parse_rtable = NIL;
778 List *with_check_parse_rtable = NIL;
779 Node *qual = NULL;
780 Node *with_check_qual = NULL;
781 ScanKeyData skey[2];
782 SysScanDesc sscan;
783 HeapTuple policy_tuple;
784 HeapTuple new_tuple;
785 Datum values[Natts_pg_policy];
786 bool isnull[Natts_pg_policy];
787 bool replaces[Natts_pg_policy];
788 ObjectAddress target;
789 ObjectAddress myself;
790 Datum polcmd_datum;
791 char polcmd;
792 bool polcmd_isnull;
793 int i;
794
795 /* Parse role_ids */
796 if (stmt->roles != NULL)
797 {
798 role_oids = policy_role_list_to_array(stmt->roles, &nitems);
799 role_ids = construct_array_builtin(role_oids, nitems, OIDOID);
800 }
801
802 /* Get id of table. Also handles permissions checks. */
804 0,
806 stmt);
807
808 target_table = relation_open(table_id, NoLock);
809
810 /* Parse the using policy clause */
811 if (stmt->qual)
812 {
813 ParseNamespaceItem *nsitem;
814 ParseState *qual_pstate = make_parsestate(NULL);
815
816 nsitem = addRangeTableEntryForRelation(qual_pstate, target_table,
818 NULL, false, false);
819
820 addNSItemToQuery(qual_pstate, nsitem, false, true, true);
821
822 qual = transformWhereClause(qual_pstate, stmt->qual,
824 "POLICY");
825
826 /* Fix up collation information */
827 assign_expr_collations(qual_pstate, qual);
828
829 qual_parse_rtable = qual_pstate->p_rtable;
830 free_parsestate(qual_pstate);
831 }
832
833 /* Parse the with-check policy clause */
834 if (stmt->with_check)
835 {
836 ParseNamespaceItem *nsitem;
837 ParseState *with_check_pstate = make_parsestate(NULL);
838
839 nsitem = addRangeTableEntryForRelation(with_check_pstate, target_table,
841 NULL, false, false);
842
843 addNSItemToQuery(with_check_pstate, nsitem, false, true, true);
844
845 with_check_qual = transformWhereClause(with_check_pstate,
846 stmt->with_check,
848 "POLICY");
849
850 /* Fix up collation information */
851 assign_expr_collations(with_check_pstate, with_check_qual);
852
853 with_check_parse_rtable = with_check_pstate->p_rtable;
854 free_parsestate(with_check_pstate);
855 }
856
857 /* zero-clear */
858 memset(values, 0, sizeof(values));
859 memset(replaces, 0, sizeof(replaces));
860 memset(isnull, 0, sizeof(isnull));
861
862 /* Find policy to update. */
863 pg_policy_rel = table_open(PolicyRelationId, RowExclusiveLock);
864
865 /* Set key - policy's relation id. */
866 ScanKeyInit(&skey[0],
867 Anum_pg_policy_polrelid,
868 BTEqualStrategyNumber, F_OIDEQ,
869 ObjectIdGetDatum(table_id));
870
871 /* Set key - policy's name. */
872 ScanKeyInit(&skey[1],
873 Anum_pg_policy_polname,
874 BTEqualStrategyNumber, F_NAMEEQ,
875 CStringGetDatum(stmt->policy_name));
876
877 sscan = systable_beginscan(pg_policy_rel,
878 PolicyPolrelidPolnameIndexId, true, NULL, 2,
879 skey);
880
881 policy_tuple = systable_getnext(sscan);
882
883 /* Check that the policy is found, raise an error if not. */
884 if (!HeapTupleIsValid(policy_tuple))
886 (errcode(ERRCODE_UNDEFINED_OBJECT),
887 errmsg("policy \"%s\" for table \"%s\" does not exist",
888 stmt->policy_name,
889 RelationGetRelationName(target_table))));
890
891 /* Get policy command */
892 polcmd_datum = heap_getattr(policy_tuple, Anum_pg_policy_polcmd,
893 RelationGetDescr(pg_policy_rel),
894 &polcmd_isnull);
895 Assert(!polcmd_isnull);
896 polcmd = DatumGetChar(polcmd_datum);
897
898 /*
899 * If the command is SELECT or DELETE then WITH CHECK should be NULL.
900 */
901 if ((polcmd == ACL_SELECT_CHR || polcmd == ACL_DELETE_CHR)
902 && stmt->with_check != NULL)
904 (errcode(ERRCODE_SYNTAX_ERROR),
905 errmsg("only USING expression allowed for SELECT, DELETE")));
906
907 /*
908 * If the command is INSERT then WITH CHECK should be the only expression
909 * provided.
910 */
911 if ((polcmd == ACL_INSERT_CHR)
912 && stmt->qual != NULL)
914 (errcode(ERRCODE_SYNTAX_ERROR),
915 errmsg("only WITH CHECK expression allowed for INSERT")));
916
917 policy_id = ((Form_pg_policy) GETSTRUCT(policy_tuple))->oid;
918
919 if (role_ids != NULL)
920 {
921 replaces[Anum_pg_policy_polroles - 1] = true;
922 values[Anum_pg_policy_polroles - 1] = PointerGetDatum(role_ids);
923 }
924 else
925 {
926 Oid *roles;
927 Datum roles_datum;
928 bool attr_isnull;
929 ArrayType *policy_roles;
930
931 /*
932 * We need to pull the set of roles this policy applies to from what's
933 * in the catalog, so that we can recreate the dependencies correctly
934 * for the policy.
935 */
936
937 roles_datum = heap_getattr(policy_tuple, Anum_pg_policy_polroles,
938 RelationGetDescr(pg_policy_rel),
939 &attr_isnull);
940 Assert(!attr_isnull);
941
942 policy_roles = DatumGetArrayTypePCopy(roles_datum);
943
944 roles = (Oid *) ARR_DATA_PTR(policy_roles);
945
946 nitems = ARR_DIMS(policy_roles)[0];
947
948 role_oids = (Datum *) palloc(nitems * sizeof(Datum));
949
950 for (i = 0; i < nitems; i++)
951 role_oids[i] = ObjectIdGetDatum(roles[i]);
952 }
953
954 if (qual != NULL)
955 {
956 replaces[Anum_pg_policy_polqual - 1] = true;
957 values[Anum_pg_policy_polqual - 1]
959 }
960 else
961 {
962 Datum value_datum;
963 bool attr_isnull;
964
965 /*
966 * We need to pull the USING expression and build the range table for
967 * the policy from what's in the catalog, so that we can recreate the
968 * dependencies correctly for the policy.
969 */
970
971 /* Check if the policy has a USING expr */
972 value_datum = heap_getattr(policy_tuple, Anum_pg_policy_polqual,
973 RelationGetDescr(pg_policy_rel),
974 &attr_isnull);
975 if (!attr_isnull)
976 {
977 char *qual_value;
978 ParseState *qual_pstate;
979
980 /* parsestate is built just to build the range table */
981 qual_pstate = make_parsestate(NULL);
982
983 qual_value = TextDatumGetCString(value_datum);
984 qual = stringToNode(qual_value);
985
986 /* Add this rel to the parsestate's rangetable, for dependencies */
987 (void) addRangeTableEntryForRelation(qual_pstate, target_table,
989 NULL, false, false);
990
991 qual_parse_rtable = qual_pstate->p_rtable;
992 free_parsestate(qual_pstate);
993 }
994 }
995
996 if (with_check_qual != NULL)
997 {
998 replaces[Anum_pg_policy_polwithcheck - 1] = true;
999 values[Anum_pg_policy_polwithcheck - 1]
1000 = CStringGetTextDatum(nodeToString(with_check_qual));
1001 }
1002 else
1003 {
1004 Datum value_datum;
1005 bool attr_isnull;
1006
1007 /*
1008 * We need to pull the WITH CHECK expression and build the range table
1009 * for the policy from what's in the catalog, so that we can recreate
1010 * the dependencies correctly for the policy.
1011 */
1012
1013 /* Check if the policy has a WITH CHECK expr */
1014 value_datum = heap_getattr(policy_tuple, Anum_pg_policy_polwithcheck,
1015 RelationGetDescr(pg_policy_rel),
1016 &attr_isnull);
1017 if (!attr_isnull)
1018 {
1019 char *with_check_value;
1020 ParseState *with_check_pstate;
1021
1022 /* parsestate is built just to build the range table */
1023 with_check_pstate = make_parsestate(NULL);
1024
1025 with_check_value = TextDatumGetCString(value_datum);
1026 with_check_qual = stringToNode(with_check_value);
1027
1028 /* Add this rel to the parsestate's rangetable, for dependencies */
1029 (void) addRangeTableEntryForRelation(with_check_pstate,
1030 target_table,
1032 NULL, false, false);
1033
1034 with_check_parse_rtable = with_check_pstate->p_rtable;
1035 free_parsestate(with_check_pstate);
1036 }
1037 }
1038
1039 new_tuple = heap_modify_tuple(policy_tuple,
1040 RelationGetDescr(pg_policy_rel),
1041 values, isnull, replaces);
1042 CatalogTupleUpdate(pg_policy_rel, &new_tuple->t_self, new_tuple);
1043
1044 /* Update Dependencies. */
1045 deleteDependencyRecordsFor(PolicyRelationId, policy_id, false);
1046
1047 /* Record Dependencies */
1048 target.classId = RelationRelationId;
1049 target.objectId = table_id;
1050 target.objectSubId = 0;
1051
1052 myself.classId = PolicyRelationId;
1053 myself.objectId = policy_id;
1054 myself.objectSubId = 0;
1055
1056 recordDependencyOn(&myself, &target, DEPENDENCY_AUTO);
1057
1058 recordDependencyOnExpr(&myself, qual, qual_parse_rtable, DEPENDENCY_NORMAL);
1059
1060 recordDependencyOnExpr(&myself, with_check_qual, with_check_parse_rtable,
1062
1063 /* Register role dependencies */
1064 deleteSharedDependencyRecordsFor(PolicyRelationId, policy_id, 0);
1065 target.classId = AuthIdRelationId;
1066 target.objectSubId = 0;
1067 for (i = 0; i < nitems; i++)
1068 {
1069 target.objectId = DatumGetObjectId(role_oids[i]);
1070 /* no dependency if public */
1071 if (target.objectId != ACL_ID_PUBLIC)
1072 recordSharedDependencyOn(&myself, &target,
1074 }
1075
1076 InvokeObjectPostAlterHook(PolicyRelationId, policy_id, 0);
1077
1078 heap_freetuple(new_tuple);
1079
1080 /* Invalidate Relation Cache */
1081 CacheInvalidateRelcache(target_table);
1082
1083 /* Clean up. */
1084 systable_endscan(sscan);
1085 relation_close(target_table, NoLock);
1086 table_close(pg_policy_rel, RowExclusiveLock);
1087
1088 return myself;
1089}
#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:262
#define ARR_DATA_PTR(a)
Definition: array.h:322
#define ARR_DIMS(a)
Definition: array.h:294
ArrayType * construct_array_builtin(Datum *elems, int nelems, Oid elmtype)
Definition: arrayfuncs.c:3381
static Datum values[MAXATTR]
Definition: bootstrap.c:151
#define CStringGetTextDatum(s)
Definition: builtins.h:97
#define TextDatumGetCString(d)
Definition: builtins.h:98
#define Assert(condition)
Definition: c.h:812
void recordDependencyOnExpr(const ObjectAddress *depender, Node *expr, List *rtable, DependencyType behavior)
Definition: dependency.c:1553
@ DEPENDENCY_AUTO
Definition: dependency.h:34
@ DEPENDENCY_NORMAL
Definition: dependency.h:33
@ SHARED_DEPENDENCY_POLICY
Definition: dependency.h:83
int errcode(int sqlerrcode)
Definition: elog.c:853
int errmsg(const char *fmt,...)
Definition: elog.c:1070
#define ERROR
Definition: elog.h:39
#define ereport(elevel,...)
Definition: elog.h:149
void systable_endscan(SysScanDesc sysscan)
Definition: genam.c:606
HeapTuple systable_getnext(SysScanDesc sysscan)
Definition: genam.c:513
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, const Datum *replValues, const bool *replIsnull, const bool *doReplace)
Definition: heaptuple.c:1210
void heap_freetuple(HeapTuple htup)
Definition: heaptuple.c:1435
#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:1553
int i
Definition: isn.c:72
#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:1317
Oid RangeVarGetRelidExtended(const RangeVar *relation, LOCKMODE lockmode, uint32 flags, RangeVarGetRelidCallback callback, void *callback_arg)
Definition: namespace.c:441
#define InvokeObjectPostAlterHook(classId, objectId, subId)
Definition: objectaccess.h:197
char * nodeToString(const void *obj)
Definition: outfuncs.c:794
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:72
ParseState * make_parsestate(ParseState *parentParseState)
Definition: parse_node.c:39
@ EXPR_KIND_POLICY
Definition: parse_node.h:78
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:45
long deleteDependencyRecordsFor(Oid classId, Oid objectId, bool skipExtensionDeps)
Definition: pg_depend.c:301
#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:1047
void recordSharedDependencyOn(ObjectAddress *depender, ObjectAddress *referenced, SharedDependencyType deptype)
Definition: pg_shdepend.c:125
static void RangeVarCallbackForPolicy(const RangeVar *rv, Oid relid, Oid oldrelid, void *arg)
Definition: policy.c:64
static Datum * policy_role_list_to_array(List *roles, int *num_roles)
Definition: policy.c:137
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:531
#define RelationGetRelationName(relation)
Definition: rel.h:539
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:205
Relation relation_open(Oid relationId, LOCKMODE lockmode)
Definition: relation.c:47
#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:212
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 569 of file policy.c.

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

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

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

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

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

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

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

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

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(), 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 1096 of file policy.c.

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