PostgreSQL Source Code  git master
pg_shdepend.c File Reference
#include "postgres.h"
#include "access/genam.h"
#include "access/htup_details.h"
#include "access/table.h"
#include "access/xact.h"
#include "catalog/catalog.h"
#include "catalog/dependency.h"
#include "catalog/indexing.h"
#include "catalog/pg_authid.h"
#include "catalog/pg_collation.h"
#include "catalog/pg_conversion.h"
#include "catalog/pg_database.h"
#include "catalog/pg_default_acl.h"
#include "catalog/pg_event_trigger.h"
#include "catalog/pg_extension.h"
#include "catalog/pg_foreign_data_wrapper.h"
#include "catalog/pg_foreign_server.h"
#include "catalog/pg_language.h"
#include "catalog/pg_largeobject.h"
#include "catalog/pg_largeobject_metadata.h"
#include "catalog/pg_namespace.h"
#include "catalog/pg_opclass.h"
#include "catalog/pg_operator.h"
#include "catalog/pg_opfamily.h"
#include "catalog/pg_proc.h"
#include "catalog/pg_shdepend.h"
#include "catalog/pg_statistic_ext.h"
#include "catalog/pg_subscription.h"
#include "catalog/pg_tablespace.h"
#include "catalog/pg_ts_config.h"
#include "catalog/pg_ts_dict.h"
#include "catalog/pg_type.h"
#include "catalog/pg_user_mapping.h"
#include "commands/alter.h"
#include "commands/collationcmds.h"
#include "commands/conversioncmds.h"
#include "commands/dbcommands.h"
#include "commands/defrem.h"
#include "commands/event_trigger.h"
#include "commands/extension.h"
#include "commands/policy.h"
#include "commands/proclang.h"
#include "commands/publicationcmds.h"
#include "commands/schemacmds.h"
#include "commands/subscriptioncmds.h"
#include "commands/tablecmds.h"
#include "commands/typecmds.h"
#include "miscadmin.h"
#include "storage/lmgr.h"
#include "utils/acl.h"
#include "utils/fmgroids.h"
#include "utils/syscache.h"
Include dependency graph for pg_shdepend.c:

Go to the source code of this file.

Data Structures

struct  ShDependObjectInfo
 
struct  remoteDep
 

Macros

#define MAX_REPORTED_DEPS   100
 

Enumerations

enum  SharedDependencyObjectType { LOCAL_OBJECT, SHARED_OBJECT, REMOTE_OBJECT }
 

Functions

static void getOidListDiff (Oid *list1, int *nlist1, Oid *list2, int *nlist2)
 
static Oid classIdGetDbId (Oid classId)
 
static void shdepChangeDep (Relation sdepRel, Oid classid, Oid objid, int32 objsubid, Oid refclassid, Oid refobjid, SharedDependencyType deptype)
 
static void shdepAddDependency (Relation sdepRel, Oid classId, Oid objectId, int32 objsubId, Oid refclassId, Oid refobjId, SharedDependencyType deptype)
 
static void shdepDropDependency (Relation sdepRel, Oid classId, Oid objectId, int32 objsubId, bool drop_subobjects, Oid refclassId, Oid refobjId, SharedDependencyType deptype)
 
static void storeObjectDescription (StringInfo descs, SharedDependencyObjectType type, ObjectAddress *object, SharedDependencyType deptype, int count)
 
static bool isSharedObjectPinned (Oid classId, Oid objectId, Relation sdepRel)
 
void recordSharedDependencyOn (ObjectAddress *depender, ObjectAddress *referenced, SharedDependencyType deptype)
 
void recordDependencyOnOwner (Oid classId, Oid objectId, Oid owner)
 
void changeDependencyOnOwner (Oid classId, Oid objectId, Oid newOwnerId)
 
void updateAclDependencies (Oid classId, Oid objectId, int32 objsubId, Oid ownerId, int noldmembers, Oid *oldmembers, int nnewmembers, Oid *newmembers)
 
static int shared_dependency_comparator (const void *a, const void *b)
 
bool checkSharedDependencies (Oid classId, Oid objectId, char **detail_msg, char **detail_log_msg)
 
void copyTemplateDependencies (Oid templateDbId, Oid newDbId)
 
void dropDatabaseDependencies (Oid databaseId)
 
void deleteSharedDependencyRecordsFor (Oid classId, Oid objectId, int32 objectSubId)
 
void shdepLockAndCheckObject (Oid classId, Oid objectId)
 
void shdepDropOwned (List *roleids, DropBehavior behavior)
 
void shdepReassignOwned (List *roleids, Oid newrole)
 

Macro Definition Documentation

◆ MAX_REPORTED_DEPS

#define MAX_REPORTED_DEPS   100

Referenced by checkSharedDependencies().

Enumeration Type Documentation

◆ SharedDependencyObjectType

Enumerator
LOCAL_OBJECT 
SHARED_OBJECT 
REMOTE_OBJECT 

Definition at line 69 of file pg_shdepend.c.

Function Documentation

◆ changeDependencyOnOwner()

void changeDependencyOnOwner ( Oid  classId,
Oid  objectId,
Oid  newOwnerId 
)

Definition at line 309 of file pg_shdepend.c.

References RowExclusiveLock, SHARED_DEPENDENCY_ACL, SHARED_DEPENDENCY_OWNER, shdepChangeDep(), shdepDropDependency(), table_close(), and table_open().

Referenced by AlterDatabaseOwner(), AlterEventTriggerOwner_internal(), AlterForeignDataWrapperOwner_internal(), AlterForeignServerOwner_internal(), AlterObjectOwner_internal(), AlterPublicationOwner_internal(), AlterSchemaOwner_internal(), AlterSubscriptionOwner_internal(), AlterTypeOwner_oid(), and ATExecChangeOwner().

310 {
311  Relation sdepRel;
312 
313  sdepRel = table_open(SharedDependRelationId, RowExclusiveLock);
314 
315  /* Adjust the SHARED_DEPENDENCY_OWNER entry */
316  shdepChangeDep(sdepRel,
317  classId, objectId, 0,
318  AuthIdRelationId, newOwnerId,
320 
321  /*----------
322  * There should never be a SHARED_DEPENDENCY_ACL entry for the owner,
323  * so get rid of it if there is one. This can happen if the new owner
324  * was previously granted some rights to the object.
325  *
326  * This step is analogous to aclnewowner's removal of duplicate entries
327  * in the ACL. We have to do it to handle this scenario:
328  * A grants some rights on an object to B
329  * ALTER OWNER changes the object's owner to B
330  * ALTER OWNER changes the object's owner to C
331  * The third step would remove all mention of B from the object's ACL,
332  * but we'd still have a SHARED_DEPENDENCY_ACL for B if we did not do
333  * things this way.
334  *
335  * The rule against having a SHARED_DEPENDENCY_ACL entry for the owner
336  * allows us to fix things up in just this one place, without having
337  * to make the various ALTER OWNER routines each know about it.
338  *----------
339  */
340  shdepDropDependency(sdepRel, classId, objectId, 0, true,
341  AuthIdRelationId, newOwnerId,
343 
344  table_close(sdepRel, RowExclusiveLock);
345 }
void table_close(Relation relation, LOCKMODE lockmode)
Definition: table.c:133
static void shdepChangeDep(Relation sdepRel, Oid classid, Oid objid, int32 objsubid, Oid refclassid, Oid refobjid, SharedDependencyType deptype)
Definition: pg_shdepend.c:199
#define RowExclusiveLock
Definition: lockdefs.h:38
static void shdepDropDependency(Relation sdepRel, Oid classId, Oid objectId, int32 objsubId, bool drop_subobjects, Oid refclassId, Oid refobjId, SharedDependencyType deptype)
Definition: pg_shdepend.c:984
Relation table_open(Oid relationId, LOCKMODE lockmode)
Definition: table.c:39

◆ checkSharedDependencies()

bool checkSharedDependencies ( Oid  classId,
Oid  objectId,
char **  detail_msg,
char **  detail_log_msg 
)

Definition at line 577 of file pg_shdepend.c.

References AccessShareLock, appendStringInfo(), BTEqualStrategyNumber, remoteDep::count, StringInfoData::data, remoteDep::dbOid, ShDependObjectInfo::deptype, ereport, errcode(), errmsg(), ERROR, getObjectDescription(), GETSTRUCT, HeapTupleIsValid, i, initStringInfo(), InvalidOid, sort-test::key, lappend(), StringInfoData::len, lfirst, list_free_deep(), LOCAL_OBJECT, MAX_REPORTED_DEPS, MyDatabaseId, ngettext, NIL, ShDependObjectInfo::object, ObjectIdGetDatum, ShDependObjectInfo::objtype, palloc(), pfree(), qsort, REMOTE_OBJECT, repalloc(), ScanKeyInit(), shared_dependency_comparator(), SHARED_DEPENDENCY_INVALID, SHARED_DEPENDENCY_PIN, SHARED_OBJECT, SharedDependReferenceIndexId, storeObjectDescription(), systable_beginscan(), systable_endscan(), systable_getnext(), table_close(), and table_open().

Referenced by DropRole().

579 {
580  Relation sdepRel;
581  ScanKeyData key[2];
582  SysScanDesc scan;
583  HeapTuple tup;
584  int numReportedDeps = 0;
585  int numNotReportedDeps = 0;
586  int numNotReportedDbs = 0;
587  List *remDeps = NIL;
588  ListCell *cell;
589  ObjectAddress object;
590  ShDependObjectInfo *objects;
591  int numobjects;
592  int allocedobjects;
593  StringInfoData descs;
594  StringInfoData alldescs;
595 
596  /*
597  * We limit the number of dependencies reported to the client to
598  * MAX_REPORTED_DEPS, since client software may not deal well with
599  * enormous error strings. The server log always gets a full report.
600  *
601  * For stability of regression test results, we sort local and shared
602  * objects by OID before reporting them. We don't worry about the order
603  * in which other databases are reported, though.
604  */
605 #define MAX_REPORTED_DEPS 100
606 
607  allocedobjects = 128; /* arbitrary initial array size */
608  objects = (ShDependObjectInfo *)
609  palloc(allocedobjects * sizeof(ShDependObjectInfo));
610  numobjects = 0;
611  initStringInfo(&descs);
612  initStringInfo(&alldescs);
613 
614  sdepRel = table_open(SharedDependRelationId, AccessShareLock);
615 
616  ScanKeyInit(&key[0],
617  Anum_pg_shdepend_refclassid,
618  BTEqualStrategyNumber, F_OIDEQ,
619  ObjectIdGetDatum(classId));
620  ScanKeyInit(&key[1],
621  Anum_pg_shdepend_refobjid,
622  BTEqualStrategyNumber, F_OIDEQ,
623  ObjectIdGetDatum(objectId));
624 
625  scan = systable_beginscan(sdepRel, SharedDependReferenceIndexId, true,
626  NULL, 2, key);
627 
628  while (HeapTupleIsValid(tup = systable_getnext(scan)))
629  {
630  Form_pg_shdepend sdepForm = (Form_pg_shdepend) GETSTRUCT(tup);
631 
632  /* This case can be dispatched quickly */
633  if (sdepForm->deptype == SHARED_DEPENDENCY_PIN)
634  {
635  object.classId = classId;
636  object.objectId = objectId;
637  object.objectSubId = 0;
638  ereport(ERROR,
639  (errcode(ERRCODE_DEPENDENT_OBJECTS_STILL_EXIST),
640  errmsg("cannot drop %s because it is required by the database system",
641  getObjectDescription(&object, false))));
642  }
643 
644  object.classId = sdepForm->classid;
645  object.objectId = sdepForm->objid;
646  object.objectSubId = sdepForm->objsubid;
647 
648  /*
649  * If it's a dependency local to this database or it's a shared
650  * object, add it to the objects array.
651  *
652  * If it's a remote dependency, keep track of it so we can report the
653  * number of them later.
654  */
655  if (sdepForm->dbid == MyDatabaseId ||
656  sdepForm->dbid == InvalidOid)
657  {
658  if (numobjects >= allocedobjects)
659  {
660  allocedobjects *= 2;
661  objects = (ShDependObjectInfo *)
662  repalloc(objects,
663  allocedobjects * sizeof(ShDependObjectInfo));
664  }
665  objects[numobjects].object = object;
666  objects[numobjects].deptype = sdepForm->deptype;
667  objects[numobjects].objtype = (sdepForm->dbid == MyDatabaseId) ?
669  numobjects++;
670  }
671  else
672  {
673  /* It's not local nor shared, so it must be remote. */
674  remoteDep *dep;
675  bool stored = false;
676 
677  /*
678  * XXX this info is kept on a simple List. Maybe it's not good
679  * for performance, but using a hash table seems needlessly
680  * complex. The expected number of databases is not high anyway,
681  * I suppose.
682  */
683  foreach(cell, remDeps)
684  {
685  dep = lfirst(cell);
686  if (dep->dbOid == sdepForm->dbid)
687  {
688  dep->count++;
689  stored = true;
690  break;
691  }
692  }
693  if (!stored)
694  {
695  dep = (remoteDep *) palloc(sizeof(remoteDep));
696  dep->dbOid = sdepForm->dbid;
697  dep->count = 1;
698  remDeps = lappend(remDeps, dep);
699  }
700  }
701  }
702 
703  systable_endscan(scan);
704 
705  table_close(sdepRel, AccessShareLock);
706 
707  /*
708  * Sort and report local and shared objects.
709  */
710  if (numobjects > 1)
711  qsort((void *) objects, numobjects,
713 
714  for (int i = 0; i < numobjects; i++)
715  {
716  if (numReportedDeps < MAX_REPORTED_DEPS)
717  {
718  numReportedDeps++;
719  storeObjectDescription(&descs,
720  objects[i].objtype,
721  &objects[i].object,
722  objects[i].deptype,
723  0);
724  }
725  else
726  numNotReportedDeps++;
727  storeObjectDescription(&alldescs,
728  objects[i].objtype,
729  &objects[i].object,
730  objects[i].deptype,
731  0);
732  }
733 
734  /*
735  * Summarize dependencies in remote databases.
736  */
737  foreach(cell, remDeps)
738  {
739  remoteDep *dep = lfirst(cell);
740 
741  object.classId = DatabaseRelationId;
742  object.objectId = dep->dbOid;
743  object.objectSubId = 0;
744 
745  if (numReportedDeps < MAX_REPORTED_DEPS)
746  {
747  numReportedDeps++;
748  storeObjectDescription(&descs, REMOTE_OBJECT, &object,
750  }
751  else
752  numNotReportedDbs++;
753  storeObjectDescription(&alldescs, REMOTE_OBJECT, &object,
755  }
756 
757  pfree(objects);
758  list_free_deep(remDeps);
759 
760  if (descs.len == 0)
761  {
762  pfree(descs.data);
763  pfree(alldescs.data);
764  *detail_msg = *detail_log_msg = NULL;
765  return false;
766  }
767 
768  if (numNotReportedDeps > 0)
769  appendStringInfo(&descs, ngettext("\nand %d other object "
770  "(see server log for list)",
771  "\nand %d other objects "
772  "(see server log for list)",
773  numNotReportedDeps),
774  numNotReportedDeps);
775  if (numNotReportedDbs > 0)
776  appendStringInfo(&descs, ngettext("\nand objects in %d other database "
777  "(see server log for list)",
778  "\nand objects in %d other databases "
779  "(see server log for list)",
780  numNotReportedDbs),
781  numNotReportedDbs);
782 
783  *detail_msg = descs.data;
784  *detail_log_msg = alldescs.data;
785  return true;
786 }
#define NIL
Definition: pg_list.h:65
char * getObjectDescription(const ObjectAddress *object, bool missing_ok)
void table_close(Relation relation, LOCKMODE lockmode)
Definition: table.c:133
static int shared_dependency_comparator(const void *a, const void *b)
Definition: pg_shdepend.c:509
void systable_endscan(SysScanDesc sysscan)
Definition: genam.c:529
#define GETSTRUCT(TUP)
Definition: htup_details.h:655
FormData_pg_shdepend * Form_pg_shdepend
Definition: pg_shdepend.h:70
#define AccessShareLock
Definition: lockdefs.h:36
#define MAX_REPORTED_DEPS
static void storeObjectDescription(StringInfo descs, SharedDependencyObjectType type, ObjectAddress *object, SharedDependencyType deptype, int count)
Definition: pg_shdepend.c:1144
int errcode(int sqlerrcode)
Definition: elog.c:610
void list_free_deep(List *list)
Definition: list.c:1390
SysScanDesc systable_beginscan(Relation heapRelation, Oid indexId, bool indexOK, Snapshot snapshot, int nkeys, ScanKey key)
Definition: genam.c:356
SharedDependencyObjectType objtype
Definition: pg_shdepend.c:80
HeapTuple systable_getnext(SysScanDesc sysscan)
Definition: genam.c:448
void pfree(void *pointer)
Definition: mcxt.c:1056
void appendStringInfo(StringInfo str, const char *fmt,...)
Definition: stringinfo.c:91
#define ObjectIdGetDatum(X)
Definition: postgres.h:507
#define ERROR
Definition: elog.h:43
List * lappend(List *list, void *datum)
Definition: list.c:321
void initStringInfo(StringInfo str)
Definition: stringinfo.c:59
#define ngettext(s, p, n)
Definition: c.h:1152
Oid MyDatabaseId
Definition: globals.c:85
#define InvalidOid
Definition: postgres_ext.h:36
#define ereport(elevel,...)
Definition: elog.h:144
#define HeapTupleIsValid(tuple)
Definition: htup.h:78
#define lfirst(lc)
Definition: pg_list.h:190
void * repalloc(void *pointer, Size size)
Definition: mcxt.c:1069
void * palloc(Size size)
Definition: mcxt.c:949
int errmsg(const char *fmt,...)
Definition: elog.c:824
int i
void ScanKeyInit(ScanKey entry, AttrNumber attributeNumber, StrategyNumber strategy, RegProcedure procedure, Datum argument)
Definition: scankey.c:76
#define SharedDependReferenceIndexId
Definition: indexing.h:225
#define qsort(a, b, c, d)
Definition: port.h:479
Relation table_open(Oid relationId, LOCKMODE lockmode)
Definition: table.c:39
Definition: pg_list.h:50
#define BTEqualStrategyNumber
Definition: stratnum.h:31
ObjectAddress object
Definition: pg_shdepend.c:78

◆ classIdGetDbId()

static Oid classIdGetDbId ( Oid  classId)
static

Definition at line 1050 of file pg_shdepend.c.

References InvalidOid, IsSharedRelation(), and MyDatabaseId.

Referenced by shdepAddDependency(), shdepChangeDep(), and shdepDropDependency().

1051 {
1052  Oid dbId;
1053 
1054  if (IsSharedRelation(classId))
1055  dbId = InvalidOid;
1056  else
1057  dbId = MyDatabaseId;
1058 
1059  return dbId;
1060 }
unsigned int Oid
Definition: postgres_ext.h:31
Oid MyDatabaseId
Definition: globals.c:85
bool IsSharedRelation(Oid relationId)
Definition: catalog.c:238
#define InvalidOid
Definition: postgres_ext.h:36

◆ copyTemplateDependencies()

void copyTemplateDependencies ( Oid  templateDbId,
Oid  newDbId 
)

Definition at line 795 of file pg_shdepend.c.

References BTEqualStrategyNumber, CatalogCloseIndexes(), CatalogOpenIndexes(), CatalogTupleInsertWithInfo(), heap_freetuple(), heap_modify_tuple(), HeapTupleIsValid, sort-test::key, ObjectIdGetDatum, RelationGetDescr, RowExclusiveLock, ScanKeyInit(), SharedDependDependerIndexId, systable_beginscan(), systable_endscan(), systable_getnext(), table_close(), table_open(), and values.

Referenced by createdb().

796 {
797  Relation sdepRel;
798  TupleDesc sdepDesc;
799  ScanKeyData key[1];
800  SysScanDesc scan;
801  HeapTuple tup;
802  CatalogIndexState indstate;
803  Datum values[Natts_pg_shdepend];
804  bool nulls[Natts_pg_shdepend];
805  bool replace[Natts_pg_shdepend];
806 
807  sdepRel = table_open(SharedDependRelationId, RowExclusiveLock);
808  sdepDesc = RelationGetDescr(sdepRel);
809 
810  indstate = CatalogOpenIndexes(sdepRel);
811 
812  /* Scan all entries with dbid = templateDbId */
813  ScanKeyInit(&key[0],
814  Anum_pg_shdepend_dbid,
815  BTEqualStrategyNumber, F_OIDEQ,
816  ObjectIdGetDatum(templateDbId));
817 
818  scan = systable_beginscan(sdepRel, SharedDependDependerIndexId, true,
819  NULL, 1, key);
820 
821  /* Set up to copy the tuples except for inserting newDbId */
822  memset(values, 0, sizeof(values));
823  memset(nulls, false, sizeof(nulls));
824  memset(replace, false, sizeof(replace));
825 
826  replace[Anum_pg_shdepend_dbid - 1] = true;
827  values[Anum_pg_shdepend_dbid - 1] = ObjectIdGetDatum(newDbId);
828 
829  /*
830  * Copy the entries of the original database, changing the database Id to
831  * that of the new database. Note that because we are not copying rows
832  * with dbId == 0 (ie, rows describing dependent shared objects) we won't
833  * copy the ownership dependency of the template database itself; this is
834  * what we want.
835  */
836  while (HeapTupleIsValid(tup = systable_getnext(scan)))
837  {
838  HeapTuple newtup;
839 
840  newtup = heap_modify_tuple(tup, sdepDesc, values, nulls, replace);
841  CatalogTupleInsertWithInfo(sdepRel, newtup, indstate);
842 
843  heap_freetuple(newtup);
844  }
845 
846  systable_endscan(scan);
847 
848  CatalogCloseIndexes(indstate);
849  table_close(sdepRel, RowExclusiveLock);
850 }
void table_close(Relation relation, LOCKMODE lockmode)
Definition: table.c:133
void systable_endscan(SysScanDesc sysscan)
Definition: genam.c:529
#define SharedDependDependerIndexId
Definition: indexing.h:223
#define RelationGetDescr(relation)
Definition: rel.h:482
void heap_freetuple(HeapTuple htup)
Definition: heaptuple.c:1338
SysScanDesc systable_beginscan(Relation heapRelation, Oid indexId, bool indexOK, Snapshot snapshot, int nkeys, ScanKey key)
Definition: genam.c:356
HeapTuple systable_getnext(SysScanDesc sysscan)
Definition: genam.c:448
#define ObjectIdGetDatum(X)
Definition: postgres.h:507
#define RowExclusiveLock
Definition: lockdefs.h:38
uintptr_t Datum
Definition: postgres.h:367
void CatalogTupleInsertWithInfo(Relation heapRel, HeapTuple tup, CatalogIndexState indstate)
Definition: indexing.c:204
#define HeapTupleIsValid(tuple)
Definition: htup.h:78
CatalogIndexState CatalogOpenIndexes(Relation heapRel)
Definition: indexing.c:42
static Datum values[MAXATTR]
Definition: bootstrap.c:167
void ScanKeyInit(ScanKey entry, AttrNumber attributeNumber, StrategyNumber strategy, RegProcedure procedure, Datum argument)
Definition: scankey.c:76
void CatalogCloseIndexes(CatalogIndexState indstate)
Definition: indexing.c:60
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

◆ deleteSharedDependencyRecordsFor()

void deleteSharedDependencyRecordsFor ( Oid  classId,
Oid  objectId,
int32  objectSubId 
)

Definition at line 907 of file pg_shdepend.c.

References InvalidOid, RowExclusiveLock, SHARED_DEPENDENCY_INVALID, shdepDropDependency(), table_close(), and table_open().

Referenced by AlterPolicy(), deleteOneObject(), DropSubscription(), DropTableSpace(), GenerateTypeDependencies(), makeConfigurationDependencies(), makeOperatorDependencies(), and RemoveRoleFromObjectPolicy().

908 {
909  Relation sdepRel;
910 
911  sdepRel = table_open(SharedDependRelationId, RowExclusiveLock);
912 
913  shdepDropDependency(sdepRel, classId, objectId, objectSubId,
914  (objectSubId == 0),
917 
918  table_close(sdepRel, RowExclusiveLock);
919 }
void table_close(Relation relation, LOCKMODE lockmode)
Definition: table.c:133
#define RowExclusiveLock
Definition: lockdefs.h:38
#define InvalidOid
Definition: postgres_ext.h:36
static void shdepDropDependency(Relation sdepRel, Oid classId, Oid objectId, int32 objsubId, bool drop_subobjects, Oid refclassId, Oid refobjId, SharedDependencyType deptype)
Definition: pg_shdepend.c:984
Relation table_open(Oid relationId, LOCKMODE lockmode)
Definition: table.c:39

◆ dropDatabaseDependencies()

void dropDatabaseDependencies ( Oid  databaseId)

Definition at line 859 of file pg_shdepend.c.

References BTEqualStrategyNumber, CatalogTupleDelete(), HeapTupleIsValid, InvalidOid, sort-test::key, ObjectIdGetDatum, RowExclusiveLock, ScanKeyInit(), SHARED_DEPENDENCY_INVALID, SharedDependDependerIndexId, shdepDropDependency(), systable_beginscan(), systable_endscan(), systable_getnext(), HeapTupleData::t_self, table_close(), and table_open().

Referenced by dropdb().

860 {
861  Relation sdepRel;
862  ScanKeyData key[1];
863  SysScanDesc scan;
864  HeapTuple tup;
865 
866  sdepRel = table_open(SharedDependRelationId, RowExclusiveLock);
867 
868  /*
869  * First, delete all the entries that have the database Oid in the dbid
870  * field.
871  */
872  ScanKeyInit(&key[0],
873  Anum_pg_shdepend_dbid,
874  BTEqualStrategyNumber, F_OIDEQ,
875  ObjectIdGetDatum(databaseId));
876  /* We leave the other index fields unspecified */
877 
878  scan = systable_beginscan(sdepRel, SharedDependDependerIndexId, true,
879  NULL, 1, key);
880 
881  while (HeapTupleIsValid(tup = systable_getnext(scan)))
882  {
883  CatalogTupleDelete(sdepRel, &tup->t_self);
884  }
885 
886  systable_endscan(scan);
887 
888  /* Now delete all entries corresponding to the database itself */
889  shdepDropDependency(sdepRel, DatabaseRelationId, databaseId, 0, true,
892 
893  table_close(sdepRel, RowExclusiveLock);
894 }
void table_close(Relation relation, LOCKMODE lockmode)
Definition: table.c:133
void systable_endscan(SysScanDesc sysscan)
Definition: genam.c:529
#define SharedDependDependerIndexId
Definition: indexing.h:223
void CatalogTupleDelete(Relation heapRel, ItemPointer tid)
Definition: indexing.c:269
SysScanDesc systable_beginscan(Relation heapRelation, Oid indexId, bool indexOK, Snapshot snapshot, int nkeys, ScanKey key)
Definition: genam.c:356
HeapTuple systable_getnext(SysScanDesc sysscan)
Definition: genam.c:448
#define ObjectIdGetDatum(X)
Definition: postgres.h:507
ItemPointerData t_self
Definition: htup.h:65
#define RowExclusiveLock
Definition: lockdefs.h:38
#define InvalidOid
Definition: postgres_ext.h:36
static void shdepDropDependency(Relation sdepRel, Oid classId, Oid objectId, int32 objsubId, bool drop_subobjects, Oid refclassId, Oid refobjId, SharedDependencyType deptype)
Definition: pg_shdepend.c:984
#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 BTEqualStrategyNumber
Definition: stratnum.h:31

◆ getOidListDiff()

static void getOidListDiff ( Oid list1,
int *  nlist1,
Oid list2,
int *  nlist2 
)
static

Definition at line 356 of file pg_shdepend.c.

Referenced by updateAclDependencies().

357 {
358  int in1,
359  in2,
360  out1,
361  out2;
362 
363  in1 = in2 = out1 = out2 = 0;
364  while (in1 < *nlist1 && in2 < *nlist2)
365  {
366  if (list1[in1] == list2[in2])
367  {
368  /* skip over duplicates */
369  in1++;
370  in2++;
371  }
372  else if (list1[in1] < list2[in2])
373  {
374  /* list1[in1] is not in list2 */
375  list1[out1++] = list1[in1++];
376  }
377  else
378  {
379  /* list2[in2] is not in list1 */
380  list2[out2++] = list2[in2++];
381  }
382  }
383 
384  /* any remaining list1 entries are not in list2 */
385  while (in1 < *nlist1)
386  {
387  list1[out1++] = list1[in1++];
388  }
389 
390  /* any remaining list2 entries are not in list1 */
391  while (in2 < *nlist2)
392  {
393  list2[out2++] = list2[in2++];
394  }
395 
396  *nlist1 = out1;
397  *nlist2 = out2;
398 }

◆ isSharedObjectPinned()

static bool isSharedObjectPinned ( Oid  classId,
Oid  objectId,
Relation  sdepRel 
)
static

Definition at line 1195 of file pg_shdepend.c.

References BTEqualStrategyNumber, GETSTRUCT, HeapTupleIsValid, sort-test::key, ObjectIdGetDatum, ScanKeyInit(), SHARED_DEPENDENCY_PIN, SharedDependReferenceIndexId, systable_beginscan(), systable_endscan(), and systable_getnext().

Referenced by recordSharedDependencyOn(), shdepChangeDep(), shdepDropOwned(), shdepReassignOwned(), and updateAclDependencies().

1196 {
1197  bool result = false;
1198  ScanKeyData key[2];
1199  SysScanDesc scan;
1200  HeapTuple tup;
1201 
1202  ScanKeyInit(&key[0],
1203  Anum_pg_shdepend_refclassid,
1204  BTEqualStrategyNumber, F_OIDEQ,
1205  ObjectIdGetDatum(classId));
1206  ScanKeyInit(&key[1],
1207  Anum_pg_shdepend_refobjid,
1208  BTEqualStrategyNumber, F_OIDEQ,
1209  ObjectIdGetDatum(objectId));
1210 
1211  scan = systable_beginscan(sdepRel, SharedDependReferenceIndexId, true,
1212  NULL, 2, key);
1213 
1214  /*
1215  * Since we won't generate additional pg_shdepend entries for pinned
1216  * objects, there can be at most one entry referencing a pinned object.
1217  * Hence, it's sufficient to look at the first returned tuple; we don't
1218  * need to loop.
1219  */
1220  tup = systable_getnext(scan);
1221  if (HeapTupleIsValid(tup))
1222  {
1223  Form_pg_shdepend shdepForm = (Form_pg_shdepend) GETSTRUCT(tup);
1224 
1225  if (shdepForm->deptype == SHARED_DEPENDENCY_PIN)
1226  result = true;
1227  }
1228 
1229  systable_endscan(scan);
1230 
1231  return result;
1232 }
void systable_endscan(SysScanDesc sysscan)
Definition: genam.c:529
#define GETSTRUCT(TUP)
Definition: htup_details.h:655
FormData_pg_shdepend * Form_pg_shdepend
Definition: pg_shdepend.h:70
SysScanDesc systable_beginscan(Relation heapRelation, Oid indexId, bool indexOK, Snapshot snapshot, int nkeys, ScanKey key)
Definition: genam.c:356
HeapTuple systable_getnext(SysScanDesc sysscan)
Definition: genam.c:448
#define ObjectIdGetDatum(X)
Definition: postgres.h:507
#define HeapTupleIsValid(tuple)
Definition: htup.h:78
void ScanKeyInit(ScanKey entry, AttrNumber attributeNumber, StrategyNumber strategy, RegProcedure procedure, Datum argument)
Definition: scankey.c:76
#define SharedDependReferenceIndexId
Definition: indexing.h:225
#define BTEqualStrategyNumber
Definition: stratnum.h:31

◆ recordDependencyOnOwner()

void recordDependencyOnOwner ( Oid  classId,
Oid  objectId,
Oid  owner 
)

Definition at line 164 of file pg_shdepend.c.

References ObjectAddress::classId, ObjectAddress::objectId, ObjectAddress::objectSubId, recordSharedDependencyOn(), and SHARED_DEPENDENCY_OWNER.

Referenced by CollationCreate(), ConversionCreate(), createdb(), CreateForeignDataWrapper(), CreateForeignServer(), CreateOpFamily(), CreateProceduralLanguage(), CreatePublication(), CreateStatistics(), CreateSubscription(), CreateTableSpace(), CreateUserMapping(), DefineOpClass(), GenerateTypeDependencies(), heap_create_with_catalog(), insert_event_trigger_tuple(), InsertExtensionTuple(), inv_create(), makeConfigurationDependencies(), makeDictionaryDependencies(), makeOperatorDependencies(), NamespaceCreate(), ProcedureCreate(), and SetDefaultACL().

165 {
166  ObjectAddress myself,
167  referenced;
168 
169  myself.classId = classId;
170  myself.objectId = objectId;
171  myself.objectSubId = 0;
172 
173  referenced.classId = AuthIdRelationId;
174  referenced.objectId = owner;
175  referenced.objectSubId = 0;
176 
177  recordSharedDependencyOn(&myself, &referenced, SHARED_DEPENDENCY_OWNER);
178 }
void recordSharedDependencyOn(ObjectAddress *depender, ObjectAddress *referenced, SharedDependencyType deptype)
Definition: pg_shdepend.c:120

◆ recordSharedDependencyOn()

void recordSharedDependencyOn ( ObjectAddress depender,
ObjectAddress referenced,
SharedDependencyType  deptype 
)

Definition at line 120 of file pg_shdepend.c.

References Assert, ObjectAddress::classId, IsBootstrapProcessingMode, isSharedObjectPinned(), ObjectAddress::objectId, ObjectAddress::objectSubId, RowExclusiveLock, shdepAddDependency(), table_close(), and table_open().

Referenced by AlterPolicy(), CreatePolicy(), recordDependencyOnOwner(), and RemoveRoleFromObjectPolicy().

123 {
124  Relation sdepRel;
125 
126  /*
127  * Objects in pg_shdepend can't have SubIds.
128  */
129  Assert(depender->objectSubId == 0);
130  Assert(referenced->objectSubId == 0);
131 
132  /*
133  * During bootstrap, do nothing since pg_shdepend may not exist yet.
134  * initdb will fill in appropriate pg_shdepend entries after bootstrap.
135  */
137  return;
138 
139  sdepRel = table_open(SharedDependRelationId, RowExclusiveLock);
140 
141  /* If the referenced object is pinned, do nothing. */
142  if (!isSharedObjectPinned(referenced->classId, referenced->objectId,
143  sdepRel))
144  {
145  shdepAddDependency(sdepRel, depender->classId, depender->objectId,
146  depender->objectSubId,
147  referenced->classId, referenced->objectId,
148  deptype);
149  }
150 
151  table_close(sdepRel, RowExclusiveLock);
152 }
void table_close(Relation relation, LOCKMODE lockmode)
Definition: table.c:133
static bool isSharedObjectPinned(Oid classId, Oid objectId, Relation sdepRel)
Definition: pg_shdepend.c:1195
static void shdepAddDependency(Relation sdepRel, Oid classId, Oid objectId, int32 objsubId, Oid refclassId, Oid refobjId, SharedDependencyType deptype)
Definition: pg_shdepend.c:929
#define RowExclusiveLock
Definition: lockdefs.h:38
#define Assert(condition)
Definition: c.h:745
#define IsBootstrapProcessingMode()
Definition: miscadmin.h:392
Relation table_open(Oid relationId, LOCKMODE lockmode)
Definition: table.c:39

◆ shared_dependency_comparator()

static int shared_dependency_comparator ( const void *  a,
const void *  b 
)
static

Definition at line 509 of file pg_shdepend.c.

References ObjectAddress::classId, ShDependObjectInfo::deptype, ShDependObjectInfo::object, ObjectAddress::objectId, and ObjectAddress::objectSubId.

Referenced by checkSharedDependencies().

510 {
511  const ShDependObjectInfo *obja = (const ShDependObjectInfo *) a;
512  const ShDependObjectInfo *objb = (const ShDependObjectInfo *) b;
513 
514  /*
515  * Primary sort key is OID ascending.
516  */
517  if (obja->object.objectId < objb->object.objectId)
518  return -1;
519  if (obja->object.objectId > objb->object.objectId)
520  return 1;
521 
522  /*
523  * Next sort on catalog ID, in case identical OIDs appear in different
524  * catalogs. Sort direction is pretty arbitrary here.
525  */
526  if (obja->object.classId < objb->object.classId)
527  return -1;
528  if (obja->object.classId > objb->object.classId)
529  return 1;
530 
531  /*
532  * Sort on object subId.
533  *
534  * We sort the subId as an unsigned int so that 0 (the whole object) will
535  * come first.
536  */
537  if ((unsigned int) obja->object.objectSubId < (unsigned int) objb->object.objectSubId)
538  return -1;
539  if ((unsigned int) obja->object.objectSubId > (unsigned int) objb->object.objectSubId)
540  return 1;
541 
542  /*
543  * Last, sort on deptype, in case the same object has multiple dependency
544  * types. (Note that there's no need to consider objtype, as that's
545  * determined by the catalog OID.)
546  */
547  if (obja->deptype < objb->deptype)
548  return -1;
549  if (obja->deptype > objb->deptype)
550  return 1;
551 
552  return 0;
553 }
ObjectAddress object
Definition: pg_shdepend.c:78

◆ shdepAddDependency()

static void shdepAddDependency ( Relation  sdepRel,
Oid  classId,
Oid  objectId,
int32  objsubId,
Oid  refclassId,
Oid  refobjId,
SharedDependencyType  deptype 
)
static

Definition at line 929 of file pg_shdepend.c.

References CatalogTupleInsert(), CharGetDatum, classIdGetDbId(), heap_form_tuple(), heap_freetuple(), Int32GetDatum, ObjectIdGetDatum, RelationData::rd_att, shdepLockAndCheckObject(), and values.

Referenced by recordSharedDependencyOn(), and updateAclDependencies().

933 {
934  HeapTuple tup;
935  Datum values[Natts_pg_shdepend];
936  bool nulls[Natts_pg_shdepend];
937 
938  /*
939  * Make sure the object doesn't go away while we record the dependency on
940  * it. DROP routines should lock the object exclusively before they check
941  * shared dependencies.
942  */
943  shdepLockAndCheckObject(refclassId, refobjId);
944 
945  memset(nulls, false, sizeof(nulls));
946 
947  /*
948  * Form the new tuple and record the dependency.
949  */
950  values[Anum_pg_shdepend_dbid - 1] = ObjectIdGetDatum(classIdGetDbId(classId));
951  values[Anum_pg_shdepend_classid - 1] = ObjectIdGetDatum(classId);
952  values[Anum_pg_shdepend_objid - 1] = ObjectIdGetDatum(objectId);
953  values[Anum_pg_shdepend_objsubid - 1] = Int32GetDatum(objsubId);
954 
955  values[Anum_pg_shdepend_refclassid - 1] = ObjectIdGetDatum(refclassId);
956  values[Anum_pg_shdepend_refobjid - 1] = ObjectIdGetDatum(refobjId);
957  values[Anum_pg_shdepend_deptype - 1] = CharGetDatum(deptype);
958 
959  tup = heap_form_tuple(sdepRel->rd_att, values, nulls);
960 
961  CatalogTupleInsert(sdepRel, tup);
962 
963  /* clean up */
964  heap_freetuple(tup);
965 }
HeapTuple heap_form_tuple(TupleDesc tupleDescriptor, Datum *values, bool *isnull)
Definition: heaptuple.c:1020
void heap_freetuple(HeapTuple htup)
Definition: heaptuple.c:1338
#define ObjectIdGetDatum(X)
Definition: postgres.h:507
void shdepLockAndCheckObject(Oid classId, Oid objectId)
Definition: pg_shdepend.c:1071
uintptr_t Datum
Definition: postgres.h:367
TupleDesc rd_att
Definition: rel.h:110
static Oid classIdGetDbId(Oid classId)
Definition: pg_shdepend.c:1050
#define CharGetDatum(X)
Definition: postgres.h:416
static Datum values[MAXATTR]
Definition: bootstrap.c:167
#define Int32GetDatum(X)
Definition: postgres.h:479
void CatalogTupleInsert(Relation heapRel, HeapTuple tup)
Definition: indexing.c:183

◆ shdepChangeDep()

static void shdepChangeDep ( Relation  sdepRel,
Oid  classid,
Oid  objid,
int32  objsubid,
Oid  refclassid,
Oid  refobjid,
SharedDependencyType  deptype 
)
static

Definition at line 199 of file pg_shdepend.c.

References BTEqualStrategyNumber, CatalogTupleDelete(), CatalogTupleInsert(), CatalogTupleUpdate(), CharGetDatum, classIdGetDbId(), elog, ERROR, GETSTRUCT, heap_copytuple(), heap_form_tuple(), heap_freetuple(), Int32GetDatum, isSharedObjectPinned(), sort-test::key, ObjectIdGetDatum, RelationGetDescr, ScanKeyInit(), SharedDependDependerIndexId, shdepLockAndCheckObject(), systable_beginscan(), systable_endscan(), systable_getnext(), HeapTupleData::t_self, and values.

Referenced by changeDependencyOnOwner().

203 {
204  Oid dbid = classIdGetDbId(classid);
205  HeapTuple oldtup = NULL;
206  HeapTuple scantup;
207  ScanKeyData key[4];
208  SysScanDesc scan;
209 
210  /*
211  * Make sure the new referenced object doesn't go away while we record the
212  * dependency.
213  */
214  shdepLockAndCheckObject(refclassid, refobjid);
215 
216  /*
217  * Look for a previous entry
218  */
219  ScanKeyInit(&key[0],
220  Anum_pg_shdepend_dbid,
221  BTEqualStrategyNumber, F_OIDEQ,
222  ObjectIdGetDatum(dbid));
223  ScanKeyInit(&key[1],
224  Anum_pg_shdepend_classid,
225  BTEqualStrategyNumber, F_OIDEQ,
226  ObjectIdGetDatum(classid));
227  ScanKeyInit(&key[2],
228  Anum_pg_shdepend_objid,
229  BTEqualStrategyNumber, F_OIDEQ,
230  ObjectIdGetDatum(objid));
231  ScanKeyInit(&key[3],
232  Anum_pg_shdepend_objsubid,
233  BTEqualStrategyNumber, F_INT4EQ,
234  Int32GetDatum(objsubid));
235 
236  scan = systable_beginscan(sdepRel, SharedDependDependerIndexId, true,
237  NULL, 4, key);
238 
239  while ((scantup = systable_getnext(scan)) != NULL)
240  {
241  /* Ignore if not of the target dependency type */
242  if (((Form_pg_shdepend) GETSTRUCT(scantup))->deptype != deptype)
243  continue;
244  /* Caller screwed up if multiple matches */
245  if (oldtup)
246  elog(ERROR,
247  "multiple pg_shdepend entries for object %u/%u/%d deptype %c",
248  classid, objid, objsubid, deptype);
249  oldtup = heap_copytuple(scantup);
250  }
251 
252  systable_endscan(scan);
253 
254  if (isSharedObjectPinned(refclassid, refobjid, sdepRel))
255  {
256  /* No new entry needed, so just delete existing entry if any */
257  if (oldtup)
258  CatalogTupleDelete(sdepRel, &oldtup->t_self);
259  }
260  else if (oldtup)
261  {
262  /* Need to update existing entry */
263  Form_pg_shdepend shForm = (Form_pg_shdepend) GETSTRUCT(oldtup);
264 
265  /* Since oldtup is a copy, we can just modify it in-memory */
266  shForm->refclassid = refclassid;
267  shForm->refobjid = refobjid;
268 
269  CatalogTupleUpdate(sdepRel, &oldtup->t_self, oldtup);
270  }
271  else
272  {
273  /* Need to insert new entry */
274  Datum values[Natts_pg_shdepend];
275  bool nulls[Natts_pg_shdepend];
276 
277  memset(nulls, false, sizeof(nulls));
278 
279  values[Anum_pg_shdepend_dbid - 1] = ObjectIdGetDatum(dbid);
280  values[Anum_pg_shdepend_classid - 1] = ObjectIdGetDatum(classid);
281  values[Anum_pg_shdepend_objid - 1] = ObjectIdGetDatum(objid);
282  values[Anum_pg_shdepend_objsubid - 1] = Int32GetDatum(objsubid);
283 
284  values[Anum_pg_shdepend_refclassid - 1] = ObjectIdGetDatum(refclassid);
285  values[Anum_pg_shdepend_refobjid - 1] = ObjectIdGetDatum(refobjid);
286  values[Anum_pg_shdepend_deptype - 1] = CharGetDatum(deptype);
287 
288  /*
289  * we are reusing oldtup just to avoid declaring a new variable, but
290  * it's certainly a new tuple
291  */
292  oldtup = heap_form_tuple(RelationGetDescr(sdepRel), values, nulls);
293  CatalogTupleInsert(sdepRel, oldtup);
294  }
295 
296  if (oldtup)
297  heap_freetuple(oldtup);
298 }
HeapTuple heap_copytuple(HeapTuple tuple)
Definition: heaptuple.c:680
void systable_endscan(SysScanDesc sysscan)
Definition: genam.c:529
#define GETSTRUCT(TUP)
Definition: htup_details.h:655
#define SharedDependDependerIndexId
Definition: indexing.h:223
static bool isSharedObjectPinned(Oid classId, Oid objectId, Relation sdepRel)
Definition: pg_shdepend.c:1195
#define RelationGetDescr(relation)
Definition: rel.h:482
FormData_pg_shdepend * Form_pg_shdepend
Definition: pg_shdepend.h:70
void CatalogTupleDelete(Relation heapRel, ItemPointer tid)
Definition: indexing.c:269
HeapTuple heap_form_tuple(TupleDesc tupleDescriptor, Datum *values, bool *isnull)
Definition: heaptuple.c:1020
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:356
HeapTuple systable_getnext(SysScanDesc sysscan)
Definition: genam.c:448
#define ObjectIdGetDatum(X)
Definition: postgres.h:507
#define ERROR
Definition: elog.h:43
void shdepLockAndCheckObject(Oid classId, Oid objectId)
Definition: pg_shdepend.c:1071
ItemPointerData t_self
Definition: htup.h:65
uintptr_t Datum
Definition: postgres.h:367
static Oid classIdGetDbId(Oid classId)
Definition: pg_shdepend.c:1050
void CatalogTupleUpdate(Relation heapRel, ItemPointer otid, HeapTuple tup)
Definition: indexing.c:224
#define CharGetDatum(X)
Definition: postgres.h:416
static Datum values[MAXATTR]
Definition: bootstrap.c:167
#define Int32GetDatum(X)
Definition: postgres.h:479
#define elog(elevel,...)
Definition: elog.h:214
void ScanKeyInit(ScanKey entry, AttrNumber attributeNumber, StrategyNumber strategy, RegProcedure procedure, Datum argument)
Definition: scankey.c:76
void CatalogTupleInsert(Relation heapRel, HeapTuple tup)
Definition: indexing.c:183
#define BTEqualStrategyNumber
Definition: stratnum.h:31

◆ shdepDropDependency()

static void shdepDropDependency ( Relation  sdepRel,
Oid  classId,
Oid  objectId,
int32  objsubId,
bool  drop_subobjects,
Oid  refclassId,
Oid  refobjId,
SharedDependencyType  deptype 
)
static

Definition at line 984 of file pg_shdepend.c.

References BTEqualStrategyNumber, CatalogTupleDelete(), classIdGetDbId(), GETSTRUCT, HeapTupleIsValid, Int32GetDatum, sort-test::key, ObjectIdGetDatum, OidIsValid, ScanKeyInit(), SHARED_DEPENDENCY_INVALID, SharedDependDependerIndexId, systable_beginscan(), systable_endscan(), systable_getnext(), and HeapTupleData::t_self.

Referenced by changeDependencyOnOwner(), deleteSharedDependencyRecordsFor(), dropDatabaseDependencies(), and updateAclDependencies().

989 {
990  ScanKeyData key[4];
991  int nkeys;
992  SysScanDesc scan;
993  HeapTuple tup;
994 
995  /* Scan for entries matching the dependent object */
996  ScanKeyInit(&key[0],
997  Anum_pg_shdepend_dbid,
998  BTEqualStrategyNumber, F_OIDEQ,
999  ObjectIdGetDatum(classIdGetDbId(classId)));
1000  ScanKeyInit(&key[1],
1001  Anum_pg_shdepend_classid,
1002  BTEqualStrategyNumber, F_OIDEQ,
1003  ObjectIdGetDatum(classId));
1004  ScanKeyInit(&key[2],
1005  Anum_pg_shdepend_objid,
1006  BTEqualStrategyNumber, F_OIDEQ,
1007  ObjectIdGetDatum(objectId));
1008  if (drop_subobjects)
1009  nkeys = 3;
1010  else
1011  {
1012  ScanKeyInit(&key[3],
1013  Anum_pg_shdepend_objsubid,
1014  BTEqualStrategyNumber, F_INT4EQ,
1015  Int32GetDatum(objsubId));
1016  nkeys = 4;
1017  }
1018 
1019  scan = systable_beginscan(sdepRel, SharedDependDependerIndexId, true,
1020  NULL, nkeys, key);
1021 
1022  while (HeapTupleIsValid(tup = systable_getnext(scan)))
1023  {
1024  Form_pg_shdepend shdepForm = (Form_pg_shdepend) GETSTRUCT(tup);
1025 
1026  /* Filter entries according to additional parameters */
1027  if (OidIsValid(refclassId) && shdepForm->refclassid != refclassId)
1028  continue;
1029  if (OidIsValid(refobjId) && shdepForm->refobjid != refobjId)
1030  continue;
1031  if (deptype != SHARED_DEPENDENCY_INVALID &&
1032  shdepForm->deptype != deptype)
1033  continue;
1034 
1035  /* OK, delete it */
1036  CatalogTupleDelete(sdepRel, &tup->t_self);
1037  }
1038 
1039  systable_endscan(scan);
1040 }
void systable_endscan(SysScanDesc sysscan)
Definition: genam.c:529
#define GETSTRUCT(TUP)
Definition: htup_details.h:655
#define SharedDependDependerIndexId
Definition: indexing.h:223
FormData_pg_shdepend * Form_pg_shdepend
Definition: pg_shdepend.h:70
void CatalogTupleDelete(Relation heapRel, ItemPointer tid)
Definition: indexing.c:269
#define OidIsValid(objectId)
Definition: c.h:651
SysScanDesc systable_beginscan(Relation heapRelation, Oid indexId, bool indexOK, Snapshot snapshot, int nkeys, ScanKey key)
Definition: genam.c:356
HeapTuple systable_getnext(SysScanDesc sysscan)
Definition: genam.c:448
#define ObjectIdGetDatum(X)
Definition: postgres.h:507
ItemPointerData t_self
Definition: htup.h:65
#define HeapTupleIsValid(tuple)
Definition: htup.h:78
static Oid classIdGetDbId(Oid classId)
Definition: pg_shdepend.c:1050
#define Int32GetDatum(X)
Definition: postgres.h:479
void ScanKeyInit(ScanKey entry, AttrNumber attributeNumber, StrategyNumber strategy, RegProcedure procedure, Datum argument)
Definition: scankey.c:76
#define BTEqualStrategyNumber
Definition: stratnum.h:31

◆ shdepDropOwned()

void shdepDropOwned ( List roleids,
DropBehavior  behavior 
)

Definition at line 1247 of file pg_shdepend.c.

References AcquireDeletionLock(), add_exact_object_address(), BTEqualStrategyNumber, ObjectAddress::classId, elog, ereport, errcode(), errmsg(), ERROR, free_object_addresses(), getObjectDescription(), GETSTRUCT, InvalidOid, isSharedObjectPinned(), sort-test::key, lfirst_oid, MyDatabaseId, new_object_addresses(), ObjectAddress::objectId, ObjectIdGetDatum, ObjectAddress::objectSubId, performMultipleDeletions(), ReleaseDeletionLock(), RemoveRoleFromObjectACL(), RemoveRoleFromObjectPolicy(), RowExclusiveLock, ScanKeyInit(), SHARED_DEPENDENCY_ACL, SHARED_DEPENDENCY_INVALID, SHARED_DEPENDENCY_OWNER, SHARED_DEPENDENCY_PIN, SHARED_DEPENDENCY_POLICY, SharedDependReferenceIndexId, sort_object_addresses(), systable_beginscan(), systable_endscan(), systable_getnext(), systable_recheck_tuple(), table_close(), and table_open().

Referenced by DropOwnedObjects().

1248 {
1249  Relation sdepRel;
1250  ListCell *cell;
1251  ObjectAddresses *deleteobjs;
1252 
1253  deleteobjs = new_object_addresses();
1254 
1255  /*
1256  * We don't need this strong a lock here, but we'll call routines that
1257  * acquire RowExclusiveLock. Better get that right now to avoid potential
1258  * deadlock failures.
1259  */
1260  sdepRel = table_open(SharedDependRelationId, RowExclusiveLock);
1261 
1262  /*
1263  * For each role, find the dependent objects and drop them using the
1264  * regular (non-shared) dependency management.
1265  */
1266  foreach(cell, roleids)
1267  {
1268  Oid roleid = lfirst_oid(cell);
1269  ScanKeyData key[2];
1270  SysScanDesc scan;
1271  HeapTuple tuple;
1272 
1273  /* Doesn't work for pinned objects */
1274  if (isSharedObjectPinned(AuthIdRelationId, roleid, sdepRel))
1275  {
1276  ObjectAddress obj;
1277 
1278  obj.classId = AuthIdRelationId;
1279  obj.objectId = roleid;
1280  obj.objectSubId = 0;
1281 
1282  ereport(ERROR,
1283  (errcode(ERRCODE_DEPENDENT_OBJECTS_STILL_EXIST),
1284  errmsg("cannot drop objects owned by %s because they are "
1285  "required by the database system",
1286  getObjectDescription(&obj, false))));
1287  }
1288 
1289  ScanKeyInit(&key[0],
1290  Anum_pg_shdepend_refclassid,
1291  BTEqualStrategyNumber, F_OIDEQ,
1292  ObjectIdGetDatum(AuthIdRelationId));
1293  ScanKeyInit(&key[1],
1294  Anum_pg_shdepend_refobjid,
1295  BTEqualStrategyNumber, F_OIDEQ,
1296  ObjectIdGetDatum(roleid));
1297 
1298  scan = systable_beginscan(sdepRel, SharedDependReferenceIndexId, true,
1299  NULL, 2, key);
1300 
1301  while ((tuple = systable_getnext(scan)) != NULL)
1302  {
1303  Form_pg_shdepend sdepForm = (Form_pg_shdepend) GETSTRUCT(tuple);
1304  ObjectAddress obj;
1305 
1306  /*
1307  * We only operate on shared objects and objects in the current
1308  * database
1309  */
1310  if (sdepForm->dbid != MyDatabaseId &&
1311  sdepForm->dbid != InvalidOid)
1312  continue;
1313 
1314  switch (sdepForm->deptype)
1315  {
1316  /* Shouldn't happen */
1317  case SHARED_DEPENDENCY_PIN:
1319  elog(ERROR, "unexpected dependency type");
1320  break;
1321  case SHARED_DEPENDENCY_ACL:
1322  RemoveRoleFromObjectACL(roleid,
1323  sdepForm->classid,
1324  sdepForm->objid);
1325  break;
1327 
1328  /*
1329  * Try to remove role from policy; if unable to, remove
1330  * policy.
1331  */
1332  if (!RemoveRoleFromObjectPolicy(roleid,
1333  sdepForm->classid,
1334  sdepForm->objid))
1335  {
1336  obj.classId = sdepForm->classid;
1337  obj.objectId = sdepForm->objid;
1338  obj.objectSubId = sdepForm->objsubid;
1339 
1340  /*
1341  * Acquire lock on object, then verify this dependency
1342  * is still relevant. If not, the object might have
1343  * been dropped or the policy modified. Ignore the
1344  * object in that case.
1345  */
1346  AcquireDeletionLock(&obj, 0);
1347  if (!systable_recheck_tuple(scan, tuple))
1348  {
1349  ReleaseDeletionLock(&obj);
1350  break;
1351  }
1352  add_exact_object_address(&obj, deleteobjs);
1353  }
1354  break;
1356  /* If a local object, save it for deletion below */
1357  if (sdepForm->dbid == MyDatabaseId)
1358  {
1359  obj.classId = sdepForm->classid;
1360  obj.objectId = sdepForm->objid;
1361  obj.objectSubId = sdepForm->objsubid;
1362  /* as above */
1363  AcquireDeletionLock(&obj, 0);
1364  if (!systable_recheck_tuple(scan, tuple))
1365  {
1366  ReleaseDeletionLock(&obj);
1367  break;
1368  }
1369  add_exact_object_address(&obj, deleteobjs);
1370  }
1371  break;
1372  }
1373  }
1374 
1375  systable_endscan(scan);
1376  }
1377 
1378  /*
1379  * For stability of deletion-report ordering, sort the objects into
1380  * approximate reverse creation order before deletion. (This might also
1381  * make the deletion go a bit faster, since there's less chance of having
1382  * to rearrange the objects due to dependencies.)
1383  */
1384  sort_object_addresses(deleteobjs);
1385 
1386  /* the dependency mechanism does the actual work */
1387  performMultipleDeletions(deleteobjs, behavior, 0);
1388 
1389  table_close(sdepRel, RowExclusiveLock);
1390 
1391  free_object_addresses(deleteobjs);
1392 }
char * getObjectDescription(const ObjectAddress *object, bool missing_ok)
void table_close(Relation relation, LOCKMODE lockmode)
Definition: table.c:133
void systable_endscan(SysScanDesc sysscan)
Definition: genam.c:529
#define GETSTRUCT(TUP)
Definition: htup_details.h:655
static bool isSharedObjectPinned(Oid classId, Oid objectId, Relation sdepRel)
Definition: pg_shdepend.c:1195
void sort_object_addresses(ObjectAddresses *addrs)
Definition: dependency.c:2695
FormData_pg_shdepend * Form_pg_shdepend
Definition: pg_shdepend.h:70
void ReleaseDeletionLock(const ObjectAddress *object)
Definition: dependency.c:1559
int errcode(int sqlerrcode)
Definition: elog.c:610
void add_exact_object_address(const ObjectAddress *object, ObjectAddresses *addrs)
Definition: dependency.c:2467
void RemoveRoleFromObjectACL(Oid roleid, Oid classid, Oid objid)
Definition: aclchk.c:1377
ObjectAddresses * new_object_addresses(void)
Definition: dependency.c:2412
void free_object_addresses(ObjectAddresses *addrs)
Definition: dependency.c:2707
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:356
bool systable_recheck_tuple(SysScanDesc sysscan, HeapTuple tup)
Definition: genam.c:501
bool RemoveRoleFromObjectPolicy(Oid roleid, Oid classid, Oid policy_id)
Definition: policy.c:439
HeapTuple systable_getnext(SysScanDesc sysscan)
Definition: genam.c:448
#define ObjectIdGetDatum(X)
Definition: postgres.h:507
#define ERROR
Definition: elog.h:43
#define RowExclusiveLock
Definition: lockdefs.h:38
void AcquireDeletionLock(const ObjectAddress *object, int flags)
Definition: dependency.c:1530
Oid MyDatabaseId
Definition: globals.c:85
#define InvalidOid
Definition: postgres_ext.h:36
#define ereport(elevel,...)
Definition: elog.h:144
int errmsg(const char *fmt,...)
Definition: elog.c:824
#define elog(elevel,...)
Definition: elog.h:214
void ScanKeyInit(ScanKey entry, AttrNumber attributeNumber, StrategyNumber strategy, RegProcedure procedure, Datum argument)
Definition: scankey.c:76
void performMultipleDeletions(const ObjectAddresses *objects, DropBehavior behavior, int flags)
Definition: dependency.c:371
#define SharedDependReferenceIndexId
Definition: indexing.h:225
Relation table_open(Oid relationId, LOCKMODE lockmode)
Definition: table.c:39
#define BTEqualStrategyNumber
Definition: stratnum.h:31
#define lfirst_oid(lc)
Definition: pg_list.h:192

◆ shdepLockAndCheckObject()

void shdepLockAndCheckObject ( Oid  classId,
Oid  objectId 
)

Definition at line 1071 of file pg_shdepend.c.

References AccessShareLock, AUTHOID, elog, ereport, errcode(), errmsg(), ERROR, get_database_name(), get_tablespace_name(), LockSharedObject(), ObjectIdGetDatum, pfree(), SearchSysCacheExists1, and tablespace.

Referenced by AlterDatabaseSet(), AlterRoleSet(), shdepAddDependency(), and shdepChangeDep().

1072 {
1073  /* AccessShareLock should be OK, since we are not modifying the object */
1074  LockSharedObject(classId, objectId, 0, AccessShareLock);
1075 
1076  switch (classId)
1077  {
1078  case AuthIdRelationId:
1080  ereport(ERROR,
1081  (errcode(ERRCODE_UNDEFINED_OBJECT),
1082  errmsg("role %u was concurrently dropped",
1083  objectId)));
1084  break;
1085 
1086  /*
1087  * Currently, this routine need not support any other shared
1088  * object types besides roles. If we wanted to record explicit
1089  * dependencies on databases or tablespaces, we'd need code along
1090  * these lines:
1091  */
1092 #ifdef NOT_USED
1093  case TableSpaceRelationId:
1094  {
1095  /* For lack of a syscache on pg_tablespace, do this: */
1096  char *tablespace = get_tablespace_name(objectId);
1097 
1098  if (tablespace == NULL)
1099  ereport(ERROR,
1100  (errcode(ERRCODE_UNDEFINED_OBJECT),
1101  errmsg("tablespace %u was concurrently dropped",
1102  objectId)));
1103  pfree(tablespace);
1104  break;
1105  }
1106 #endif
1107 
1108  case DatabaseRelationId:
1109  {
1110  /* For lack of a syscache on pg_database, do this: */
1111  char *database = get_database_name(objectId);
1112 
1113  if (database == NULL)
1114  ereport(ERROR,
1115  (errcode(ERRCODE_UNDEFINED_OBJECT),
1116  errmsg("database %u was concurrently dropped",
1117  objectId)));
1118  pfree(database);
1119  break;
1120  }
1121 
1122 
1123  default:
1124  elog(ERROR, "unrecognized shared classId: %u", classId);
1125  }
1126 }
#define AccessShareLock
Definition: lockdefs.h:36
int errcode(int sqlerrcode)
Definition: elog.c:610
#define SearchSysCacheExists1(cacheId, key1)
Definition: syscache.h:183
void pfree(void *pointer)
Definition: mcxt.c:1056
#define ObjectIdGetDatum(X)
Definition: postgres.h:507
#define ERROR
Definition: elog.h:43
char * get_database_name(Oid dbid)
Definition: dbcommands.c:2155
char * tablespace
Definition: pgbench.c:188
void LockSharedObject(Oid classid, Oid objid, uint16 objsubid, LOCKMODE lockmode)
Definition: lmgr.c:1002
#define ereport(elevel,...)
Definition: elog.h:144
int errmsg(const char *fmt,...)
Definition: elog.c:824
char * get_tablespace_name(Oid spc_oid)
Definition: tablespace.c:1467
#define elog(elevel,...)
Definition: elog.h:214

◆ shdepReassignOwned()

void shdepReassignOwned ( List roleids,
Oid  newrole 
)

Definition at line 1401 of file pg_shdepend.c.

References AccessExclusiveLock, AlterEventTriggerOwner_oid(), AlterForeignDataWrapperOwner_oid(), AlterForeignServerOwner_oid(), AlterObjectOwner_internal(), AlterPublicationOwner_oid(), AlterSchemaOwner_oid(), AlterSubscriptionOwner_oid(), AlterTypeOwner_oid(), ATExecChangeOwner(), BTEqualStrategyNumber, ObjectAddress::classId, CommandCounterIncrement(), elog, ereport, errcode(), errmsg(), ERROR, getObjectDescription(), GETSTRUCT, InvalidOid, isSharedObjectPinned(), sort-test::key, lfirst_oid, MyDatabaseId, NoLock, ObjectAddress::objectId, ObjectIdGetDatum, ObjectAddress::objectSubId, RowExclusiveLock, ScanKeyInit(), SHARED_DEPENDENCY_OWNER, SHARED_DEPENDENCY_PIN, SharedDependReferenceIndexId, systable_beginscan(), systable_endscan(), systable_getnext(), table_close(), and table_open().

Referenced by ReassignOwnedObjects().

1402 {
1403  Relation sdepRel;
1404  ListCell *cell;
1405 
1406  /*
1407  * We don't need this strong a lock here, but we'll call routines that
1408  * acquire RowExclusiveLock. Better get that right now to avoid potential
1409  * deadlock problems.
1410  */
1411  sdepRel = table_open(SharedDependRelationId, RowExclusiveLock);
1412 
1413  foreach(cell, roleids)
1414  {
1415  SysScanDesc scan;
1416  ScanKeyData key[2];
1417  HeapTuple tuple;
1418  Oid roleid = lfirst_oid(cell);
1419 
1420  /* Refuse to work on pinned roles */
1421  if (isSharedObjectPinned(AuthIdRelationId, roleid, sdepRel))
1422  {
1423  ObjectAddress obj;
1424 
1425  obj.classId = AuthIdRelationId;
1426  obj.objectId = roleid;
1427  obj.objectSubId = 0;
1428 
1429  ereport(ERROR,
1430  (errcode(ERRCODE_DEPENDENT_OBJECTS_STILL_EXIST),
1431  errmsg("cannot reassign ownership of objects owned by %s because they are required by the database system",
1432  getObjectDescription(&obj, false))));
1433 
1434  /*
1435  * There's no need to tell the whole truth, which is that we
1436  * didn't track these dependencies at all ...
1437  */
1438  }
1439 
1440  ScanKeyInit(&key[0],
1441  Anum_pg_shdepend_refclassid,
1442  BTEqualStrategyNumber, F_OIDEQ,
1443  ObjectIdGetDatum(AuthIdRelationId));
1444  ScanKeyInit(&key[1],
1445  Anum_pg_shdepend_refobjid,
1446  BTEqualStrategyNumber, F_OIDEQ,
1447  ObjectIdGetDatum(roleid));
1448 
1449  scan = systable_beginscan(sdepRel, SharedDependReferenceIndexId, true,
1450  NULL, 2, key);
1451 
1452  while ((tuple = systable_getnext(scan)) != NULL)
1453  {
1454  Form_pg_shdepend sdepForm = (Form_pg_shdepend) GETSTRUCT(tuple);
1455 
1456  /*
1457  * We only operate on shared objects and objects in the current
1458  * database
1459  */
1460  if (sdepForm->dbid != MyDatabaseId &&
1461  sdepForm->dbid != InvalidOid)
1462  continue;
1463 
1464  /* Unexpected because we checked for pins above */
1465  if (sdepForm->deptype == SHARED_DEPENDENCY_PIN)
1466  elog(ERROR, "unexpected shared pin");
1467 
1468  /* We leave non-owner dependencies alone */
1469  if (sdepForm->deptype != SHARED_DEPENDENCY_OWNER)
1470  continue;
1471 
1472  /* Issue the appropriate ALTER OWNER call */
1473  switch (sdepForm->classid)
1474  {
1475  case TypeRelationId:
1476  AlterTypeOwner_oid(sdepForm->objid, newrole, true);
1477  break;
1478 
1479  case NamespaceRelationId:
1480  AlterSchemaOwner_oid(sdepForm->objid, newrole);
1481  break;
1482 
1483  case RelationRelationId:
1484 
1485  /*
1486  * Pass recursing = true so that we don't fail on indexes,
1487  * owned sequences, etc when we happen to visit them
1488  * before their parent table.
1489  */
1490  ATExecChangeOwner(sdepForm->objid, newrole, true, AccessExclusiveLock);
1491  break;
1492 
1493  case DefaultAclRelationId:
1494 
1495  /*
1496  * Ignore default ACLs; they should be handled by DROP
1497  * OWNED, not REASSIGN OWNED.
1498  */
1499  break;
1500 
1501  case UserMappingRelationId:
1502  /* ditto */
1503  break;
1504 
1505  case ForeignServerRelationId:
1506  AlterForeignServerOwner_oid(sdepForm->objid, newrole);
1507  break;
1508 
1509  case ForeignDataWrapperRelationId:
1510  AlterForeignDataWrapperOwner_oid(sdepForm->objid, newrole);
1511  break;
1512 
1513  case EventTriggerRelationId:
1514  AlterEventTriggerOwner_oid(sdepForm->objid, newrole);
1515  break;
1516 
1517  case PublicationRelationId:
1518  AlterPublicationOwner_oid(sdepForm->objid, newrole);
1519  break;
1520 
1521  case SubscriptionRelationId:
1522  AlterSubscriptionOwner_oid(sdepForm->objid, newrole);
1523  break;
1524 
1525  /* Generic alter owner cases */
1526  case CollationRelationId:
1527  case ConversionRelationId:
1528  case OperatorRelationId:
1529  case ProcedureRelationId:
1530  case LanguageRelationId:
1531  case LargeObjectRelationId:
1532  case OperatorFamilyRelationId:
1533  case OperatorClassRelationId:
1534  case ExtensionRelationId:
1535  case StatisticExtRelationId:
1536  case TableSpaceRelationId:
1537  case DatabaseRelationId:
1538  case TSConfigRelationId:
1539  case TSDictionaryRelationId:
1540  {
1541  Oid classId = sdepForm->classid;
1542  Relation catalog;
1543 
1544  if (classId == LargeObjectRelationId)
1545  classId = LargeObjectMetadataRelationId;
1546 
1547  catalog = table_open(classId, RowExclusiveLock);
1548 
1549  AlterObjectOwner_internal(catalog, sdepForm->objid,
1550  newrole);
1551 
1552  table_close(catalog, NoLock);
1553  }
1554  break;
1555 
1556  default:
1557  elog(ERROR, "unexpected classid %u", sdepForm->classid);
1558  break;
1559  }
1560  /* Make sure the next iteration will see my changes */
1562  }
1563 
1564  systable_endscan(scan);
1565  }
1566 
1567  table_close(sdepRel, RowExclusiveLock);
1568 }
char * getObjectDescription(const ObjectAddress *object, bool missing_ok)
void table_close(Relation relation, LOCKMODE lockmode)
Definition: table.c:133
void systable_endscan(SysScanDesc sysscan)
Definition: genam.c:529
#define GETSTRUCT(TUP)
Definition: htup_details.h:655
void AlterForeignDataWrapperOwner_oid(Oid fwdId, Oid newOwnerId)
Definition: foreigncmds.c:313
static bool isSharedObjectPinned(Oid classId, Oid objectId, Relation sdepRel)
Definition: pg_shdepend.c:1195
void AlterSchemaOwner_oid(Oid oid, Oid newOwnerId)
Definition: schemacmds.c:276
FormData_pg_shdepend * Form_pg_shdepend
Definition: pg_shdepend.h:70
void AlterForeignServerOwner_oid(Oid srvId, Oid newOwnerId)
Definition: foreigncmds.c:450
int errcode(int sqlerrcode)
Definition: elog.c:610
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:356
HeapTuple systable_getnext(SysScanDesc sysscan)
Definition: genam.c:448
#define ObjectIdGetDatum(X)
Definition: postgres.h:507
#define ERROR
Definition: elog.h:43
void AlterTypeOwner_oid(Oid typeOid, Oid newOwnerId, bool hasDependEntry)
Definition: typecmds.c:3340
void AlterObjectOwner_internal(Relation rel, Oid objectId, Oid new_ownerId)
Definition: alter.c:934
#define NoLock
Definition: lockdefs.h:34
#define RowExclusiveLock
Definition: lockdefs.h:38
void ATExecChangeOwner(Oid relationOid, Oid newOwnerId, bool recursing, LOCKMODE lockmode)
Definition: tablecmds.c:12323
void CommandCounterIncrement(void)
Definition: xact.c:1006
Oid MyDatabaseId
Definition: globals.c:85
#define InvalidOid
Definition: postgres_ext.h:36
void AlterEventTriggerOwner_oid(Oid trigOid, Oid newOwnerId)
#define ereport(elevel,...)
Definition: elog.h:144
#define AccessExclusiveLock
Definition: lockdefs.h:45
int errmsg(const char *fmt,...)
Definition: elog.c:824
#define elog(elevel,...)
Definition: elog.h:214
void AlterSubscriptionOwner_oid(Oid subid, Oid newOwnerId)
void ScanKeyInit(ScanKey entry, AttrNumber attributeNumber, StrategyNumber strategy, RegProcedure procedure, Datum argument)
Definition: scankey.c:76
void AlterPublicationOwner_oid(Oid subid, Oid newOwnerId)
#define SharedDependReferenceIndexId
Definition: indexing.h:225
Relation table_open(Oid relationId, LOCKMODE lockmode)
Definition: table.c:39
#define BTEqualStrategyNumber
Definition: stratnum.h:31
#define lfirst_oid(lc)
Definition: pg_list.h:192

◆ storeObjectDescription()

static void storeObjectDescription ( StringInfo  descs,
SharedDependencyObjectType  type,
ObjectAddress object,
SharedDependencyType  deptype,
int  count 
)
static

Definition at line 1144 of file pg_shdepend.c.

References _, appendStringInfo(), appendStringInfoChar(), elog, ERROR, getObjectDescription(), StringInfoData::len, LOCAL_OBJECT, ngettext, pfree(), REMOTE_OBJECT, SHARED_DEPENDENCY_ACL, SHARED_DEPENDENCY_OWNER, SHARED_DEPENDENCY_POLICY, and SHARED_OBJECT.

Referenced by checkSharedDependencies().

1149 {
1150  char *objdesc = getObjectDescription(object, false);
1151 
1152  /* separate entries with a newline */
1153  if (descs->len != 0)
1154  appendStringInfoChar(descs, '\n');
1155 
1156  switch (type)
1157  {
1158  case LOCAL_OBJECT:
1159  case SHARED_OBJECT:
1160  if (deptype == SHARED_DEPENDENCY_OWNER)
1161  appendStringInfo(descs, _("owner of %s"), objdesc);
1162  else if (deptype == SHARED_DEPENDENCY_ACL)
1163  appendStringInfo(descs, _("privileges for %s"), objdesc);
1164  else if (deptype == SHARED_DEPENDENCY_POLICY)
1165  appendStringInfo(descs, _("target of %s"), objdesc);
1166  else
1167  elog(ERROR, "unrecognized dependency type: %d",
1168  (int) deptype);
1169  break;
1170 
1171  case REMOTE_OBJECT:
1172  /* translator: %s will always be "database %s" */
1173  appendStringInfo(descs, ngettext("%d object in %s",
1174  "%d objects in %s",
1175  count),
1176  count, objdesc);
1177  break;
1178 
1179  default:
1180  elog(ERROR, "unrecognized object type: %d", type);
1181  }
1182 
1183  pfree(objdesc);
1184 }
char * getObjectDescription(const ObjectAddress *object, bool missing_ok)
void pfree(void *pointer)
Definition: mcxt.c:1056
void appendStringInfo(StringInfo str, const char *fmt,...)
Definition: stringinfo.c:91
#define ERROR
Definition: elog.h:43
void appendStringInfoChar(StringInfo str, char ch)
Definition: stringinfo.c:188
#define ngettext(s, p, n)
Definition: c.h:1152
#define elog(elevel,...)
Definition: elog.h:214
#define _(x)
Definition: elog.c:88

◆ updateAclDependencies()

void updateAclDependencies ( Oid  classId,
Oid  objectId,
int32  objsubId,
Oid  ownerId,
int  noldmembers,
Oid oldmembers,
int  nnewmembers,
Oid newmembers 
)

Definition at line 426 of file pg_shdepend.c.

References getOidListDiff(), i, isSharedObjectPinned(), pfree(), RowExclusiveLock, SHARED_DEPENDENCY_ACL, shdepAddDependency(), shdepDropDependency(), table_close(), and table_open().

Referenced by ExecGrant_Attribute(), ExecGrant_Database(), ExecGrant_Fdw(), ExecGrant_ForeignServer(), ExecGrant_Function(), ExecGrant_Language(), ExecGrant_Largeobject(), ExecGrant_Namespace(), ExecGrant_Relation(), ExecGrant_Tablespace(), ExecGrant_Type(), recordDependencyOnNewAcl(), and SetDefaultACL().

430 {
431  Relation sdepRel;
432  int i;
433 
434  /*
435  * Remove entries that are common to both lists; those represent existing
436  * dependencies we don't need to change.
437  *
438  * OK to overwrite the inputs since we'll pfree them anyway.
439  */
440  getOidListDiff(oldmembers, &noldmembers, newmembers, &nnewmembers);
441 
442  if (noldmembers > 0 || nnewmembers > 0)
443  {
444  sdepRel = table_open(SharedDependRelationId, RowExclusiveLock);
445 
446  /* Add new dependencies that weren't already present */
447  for (i = 0; i < nnewmembers; i++)
448  {
449  Oid roleid = newmembers[i];
450 
451  /*
452  * Skip the owner: he has an OWNER shdep entry instead. (This is
453  * not just a space optimization; it makes ALTER OWNER easier. See
454  * notes in changeDependencyOnOwner.)
455  */
456  if (roleid == ownerId)
457  continue;
458 
459  /* Skip pinned roles; they don't need dependency entries */
460  if (isSharedObjectPinned(AuthIdRelationId, roleid, sdepRel))
461  continue;
462 
463  shdepAddDependency(sdepRel, classId, objectId, objsubId,
464  AuthIdRelationId, roleid,
466  }
467 
468  /* Drop no-longer-used old dependencies */
469  for (i = 0; i < noldmembers; i++)
470  {
471  Oid roleid = oldmembers[i];
472 
473  /* Skip the owner, same as above */
474  if (roleid == ownerId)
475  continue;
476 
477  /* Skip pinned roles */
478  if (isSharedObjectPinned(AuthIdRelationId, roleid, sdepRel))
479  continue;
480 
481  shdepDropDependency(sdepRel, classId, objectId, objsubId,
482  false, /* exact match on objsubId */
483  AuthIdRelationId, roleid,
485  }
486 
487  table_close(sdepRel, RowExclusiveLock);
488  }
489 
490  if (oldmembers)
491  pfree(oldmembers);
492  if (newmembers)
493  pfree(newmembers);
494 }
void table_close(Relation relation, LOCKMODE lockmode)
Definition: table.c:133
static bool isSharedObjectPinned(Oid classId, Oid objectId, Relation sdepRel)
Definition: pg_shdepend.c:1195
static void getOidListDiff(Oid *list1, int *nlist1, Oid *list2, int *nlist2)
Definition: pg_shdepend.c:356
static void shdepAddDependency(Relation sdepRel, Oid classId, Oid objectId, int32 objsubId, Oid refclassId, Oid refobjId, SharedDependencyType deptype)
Definition: pg_shdepend.c:929
unsigned int Oid
Definition: postgres_ext.h:31
void pfree(void *pointer)
Definition: mcxt.c:1056
#define RowExclusiveLock
Definition: lockdefs.h:38
static void shdepDropDependency(Relation sdepRel, Oid classId, Oid objectId, int32 objsubId, bool drop_subobjects, Oid refclassId, Oid refobjId, SharedDependencyType deptype)
Definition: pg_shdepend.c:984
int i
Relation table_open(Oid relationId, LOCKMODE lockmode)
Definition: table.c:39