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/tablespace.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 recordDependencyOnTablespace (Oid classId, Oid objectId, Oid tablespace)
 
void changeDependencyOnTablespace (Oid classId, Oid objectId, Oid newTablespaceId)
 
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 70 of file pg_shdepend.c.

Function Documentation

◆ changeDependencyOnOwner()

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

Definition at line 313 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().

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

◆ changeDependencyOnTablespace()

void changeDependencyOnTablespace ( Oid  classId,
Oid  objectId,
Oid  newTablespaceId 
)

Definition at line 382 of file pg_shdepend.c.

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

Referenced by SetRelationTableSpace().

383 {
384  Relation sdepRel;
385 
386  sdepRel = table_open(SharedDependRelationId, RowExclusiveLock);
387 
388  if (newTablespaceId != DEFAULTTABLESPACE_OID &&
389  newTablespaceId != InvalidOid)
390  shdepChangeDep(sdepRel,
391  classId, objectId, 0,
392  TableSpaceRelationId, newTablespaceId,
394  else
395  shdepDropDependency(sdepRel,
396  classId, objectId, 0, true,
399 
400  table_close(sdepRel, RowExclusiveLock);
401 }
void table_close(Relation relation, LOCKMODE lockmode)
Definition: table.c:167
static void shdepChangeDep(Relation sdepRel, Oid classid, Oid objid, int32 objsubid, Oid refclassid, Oid refobjid, SharedDependencyType deptype)
Definition: pg_shdepend.c:203
#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:1078
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 633 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(), and DropTableSpace().

635 {
636  Relation sdepRel;
637  ScanKeyData key[2];
638  SysScanDesc scan;
639  HeapTuple tup;
640  int numReportedDeps = 0;
641  int numNotReportedDeps = 0;
642  int numNotReportedDbs = 0;
643  List *remDeps = NIL;
644  ListCell *cell;
645  ObjectAddress object;
646  ShDependObjectInfo *objects;
647  int numobjects;
648  int allocedobjects;
649  StringInfoData descs;
650  StringInfoData alldescs;
651 
652  /*
653  * We limit the number of dependencies reported to the client to
654  * MAX_REPORTED_DEPS, since client software may not deal well with
655  * enormous error strings. The server log always gets a full report.
656  *
657  * For stability of regression test results, we sort local and shared
658  * objects by OID before reporting them. We don't worry about the order
659  * in which other databases are reported, though.
660  */
661 #define MAX_REPORTED_DEPS 100
662 
663  allocedobjects = 128; /* arbitrary initial array size */
664  objects = (ShDependObjectInfo *)
665  palloc(allocedobjects * sizeof(ShDependObjectInfo));
666  numobjects = 0;
667  initStringInfo(&descs);
668  initStringInfo(&alldescs);
669 
670  sdepRel = table_open(SharedDependRelationId, AccessShareLock);
671 
672  ScanKeyInit(&key[0],
673  Anum_pg_shdepend_refclassid,
674  BTEqualStrategyNumber, F_OIDEQ,
675  ObjectIdGetDatum(classId));
676  ScanKeyInit(&key[1],
677  Anum_pg_shdepend_refobjid,
678  BTEqualStrategyNumber, F_OIDEQ,
679  ObjectIdGetDatum(objectId));
680 
681  scan = systable_beginscan(sdepRel, SharedDependReferenceIndexId, true,
682  NULL, 2, key);
683 
684  while (HeapTupleIsValid(tup = systable_getnext(scan)))
685  {
686  Form_pg_shdepend sdepForm = (Form_pg_shdepend) GETSTRUCT(tup);
687 
688  /* This case can be dispatched quickly */
689  if (sdepForm->deptype == SHARED_DEPENDENCY_PIN)
690  {
691  object.classId = classId;
692  object.objectId = objectId;
693  object.objectSubId = 0;
694  ereport(ERROR,
695  (errcode(ERRCODE_DEPENDENT_OBJECTS_STILL_EXIST),
696  errmsg("cannot drop %s because it is required by the database system",
697  getObjectDescription(&object, false))));
698  }
699 
700  object.classId = sdepForm->classid;
701  object.objectId = sdepForm->objid;
702  object.objectSubId = sdepForm->objsubid;
703 
704  /*
705  * If it's a dependency local to this database or it's a shared
706  * object, add it to the objects array.
707  *
708  * If it's a remote dependency, keep track of it so we can report the
709  * number of them later.
710  */
711  if (sdepForm->dbid == MyDatabaseId ||
712  sdepForm->dbid == InvalidOid)
713  {
714  if (numobjects >= allocedobjects)
715  {
716  allocedobjects *= 2;
717  objects = (ShDependObjectInfo *)
718  repalloc(objects,
719  allocedobjects * sizeof(ShDependObjectInfo));
720  }
721  objects[numobjects].object = object;
722  objects[numobjects].deptype = sdepForm->deptype;
723  objects[numobjects].objtype = (sdepForm->dbid == MyDatabaseId) ?
725  numobjects++;
726  }
727  else
728  {
729  /* It's not local nor shared, so it must be remote. */
730  remoteDep *dep;
731  bool stored = false;
732 
733  /*
734  * XXX this info is kept on a simple List. Maybe it's not good
735  * for performance, but using a hash table seems needlessly
736  * complex. The expected number of databases is not high anyway,
737  * I suppose.
738  */
739  foreach(cell, remDeps)
740  {
741  dep = lfirst(cell);
742  if (dep->dbOid == sdepForm->dbid)
743  {
744  dep->count++;
745  stored = true;
746  break;
747  }
748  }
749  if (!stored)
750  {
751  dep = (remoteDep *) palloc(sizeof(remoteDep));
752  dep->dbOid = sdepForm->dbid;
753  dep->count = 1;
754  remDeps = lappend(remDeps, dep);
755  }
756  }
757  }
758 
759  systable_endscan(scan);
760 
761  table_close(sdepRel, AccessShareLock);
762 
763  /*
764  * Sort and report local and shared objects.
765  */
766  if (numobjects > 1)
767  qsort((void *) objects, numobjects,
769 
770  for (int i = 0; i < numobjects; i++)
771  {
772  if (numReportedDeps < MAX_REPORTED_DEPS)
773  {
774  numReportedDeps++;
775  storeObjectDescription(&descs,
776  objects[i].objtype,
777  &objects[i].object,
778  objects[i].deptype,
779  0);
780  }
781  else
782  numNotReportedDeps++;
783  storeObjectDescription(&alldescs,
784  objects[i].objtype,
785  &objects[i].object,
786  objects[i].deptype,
787  0);
788  }
789 
790  /*
791  * Summarize dependencies in remote databases.
792  */
793  foreach(cell, remDeps)
794  {
795  remoteDep *dep = lfirst(cell);
796 
797  object.classId = DatabaseRelationId;
798  object.objectId = dep->dbOid;
799  object.objectSubId = 0;
800 
801  if (numReportedDeps < MAX_REPORTED_DEPS)
802  {
803  numReportedDeps++;
804  storeObjectDescription(&descs, REMOTE_OBJECT, &object,
806  }
807  else
808  numNotReportedDbs++;
809  storeObjectDescription(&alldescs, REMOTE_OBJECT, &object,
811  }
812 
813  pfree(objects);
814  list_free_deep(remDeps);
815 
816  if (descs.len == 0)
817  {
818  pfree(descs.data);
819  pfree(alldescs.data);
820  *detail_msg = *detail_log_msg = NULL;
821  return false;
822  }
823 
824  if (numNotReportedDeps > 0)
825  appendStringInfo(&descs, ngettext("\nand %d other object "
826  "(see server log for list)",
827  "\nand %d other objects "
828  "(see server log for list)",
829  numNotReportedDeps),
830  numNotReportedDeps);
831  if (numNotReportedDbs > 0)
832  appendStringInfo(&descs, ngettext("\nand objects in %d other database "
833  "(see server log for list)",
834  "\nand objects in %d other databases "
835  "(see server log for list)",
836  numNotReportedDbs),
837  numNotReportedDbs);
838 
839  *detail_msg = descs.data;
840  *detail_log_msg = alldescs.data;
841  return true;
842 }
#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:167
static int shared_dependency_comparator(const void *a, const void *b)
Definition: pg_shdepend.c:565
void systable_endscan(SysScanDesc sysscan)
Definition: genam.c:595
#define GETSTRUCT(TUP)
Definition: htup_details.h:654
FormData_pg_shdepend * Form_pg_shdepend
Definition: pg_shdepend.h:73
#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:1230
int errcode(int sqlerrcode)
Definition: elog.c:698
void list_free_deep(List *list)
Definition: list.c:1405
SysScanDesc systable_beginscan(Relation heapRelation, Oid indexId, bool indexOK, Snapshot snapshot, int nkeys, ScanKey key)
Definition: genam.c:383
SharedDependencyObjectType objtype
Definition: pg_shdepend.c:81
HeapTuple systable_getnext(SysScanDesc sysscan)
Definition: genam.c:502
void pfree(void *pointer)
Definition: mcxt.c:1169
void appendStringInfo(StringInfo str, const char *fmt,...)
Definition: stringinfo.c:91
#define ObjectIdGetDatum(X)
Definition: postgres.h:551
#define ERROR
Definition: elog.h:46
#define SharedDependReferenceIndexId
Definition: pg_shdepend.h:78
List * lappend(List *list, void *datum)
Definition: list.c:336
void initStringInfo(StringInfo str)
Definition: stringinfo.c:59
#define ngettext(s, p, n)
Definition: c.h:1182
Oid MyDatabaseId
Definition: globals.c:88
#define InvalidOid
Definition: postgres_ext.h:36
#define ereport(elevel,...)
Definition: elog.h:157
#define HeapTupleIsValid(tuple)
Definition: htup.h:78
#define lfirst(lc)
Definition: pg_list.h:169
void * repalloc(void *pointer, Size size)
Definition: mcxt.c:1182
void * palloc(Size size)
Definition: mcxt.c:1062
int errmsg(const char *fmt,...)
Definition: elog.c:909
int i
void ScanKeyInit(ScanKey entry, AttrNumber attributeNumber, StrategyNumber strategy, RegProcedure procedure, Datum argument)
Definition: scankey.c:76
#define qsort(a, b, c, d)
Definition: port.h:504
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:79

◆ classIdGetDbId()

static Oid classIdGetDbId ( Oid  classId)
static

Definition at line 1144 of file pg_shdepend.c.

References InvalidOid, IsSharedRelation(), and MyDatabaseId.

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

1145 {
1146  Oid dbId;
1147 
1148  if (IsSharedRelation(classId))
1149  dbId = InvalidOid;
1150  else
1151  dbId = MyDatabaseId;
1152 
1153  return dbId;
1154 }
unsigned int Oid
Definition: postgres_ext.h:31
Oid MyDatabaseId
Definition: globals.c:88
bool IsSharedRelation(Oid relationId)
Definition: catalog.c:243
#define InvalidOid
Definition: postgres_ext.h:36

◆ copyTemplateDependencies()

void copyTemplateDependencies ( Oid  templateDbId,
Oid  newDbId 
)

Definition at line 852 of file pg_shdepend.c.

References BTEqualStrategyNumber, CatalogCloseIndexes(), CatalogOpenIndexes(), CatalogTuplesMultiInsertWithInfo(), ExecClearTuple(), ExecDropSingleTupleTableSlot(), ExecStoreVirtualTuple(), FormData_pg_shdepend, GETSTRUCT, HeapTupleIsValid, i, sort-test::key, MakeSingleTupleTableSlot(), MAX_CATALOG_MULTI_INSERT_BYTES, ObjectIdGetDatum, palloc(), pfree(), RelationGetDescr, RowExclusiveLock, ScanKeyInit(), SharedDependDependerIndexId, systable_beginscan(), systable_endscan(), systable_getnext(), table_close(), table_open(), TupleTableSlot::tts_values, and TTSOpsHeapTuple.

Referenced by createdb().

853 {
854  Relation sdepRel;
855  TupleDesc sdepDesc;
856  ScanKeyData key[1];
857  SysScanDesc scan;
858  HeapTuple tup;
859  CatalogIndexState indstate;
860  TupleTableSlot **slot;
861  int max_slots,
862  slot_init_count,
863  slot_stored_count;
864 
865  sdepRel = table_open(SharedDependRelationId, RowExclusiveLock);
866  sdepDesc = RelationGetDescr(sdepRel);
867 
868  /*
869  * Allocate the slots to use, but delay costly initialization until we
870  * know that they will be used.
871  */
873  slot = palloc(sizeof(TupleTableSlot *) * max_slots);
874 
875  indstate = CatalogOpenIndexes(sdepRel);
876 
877  /* Scan all entries with dbid = templateDbId */
878  ScanKeyInit(&key[0],
879  Anum_pg_shdepend_dbid,
880  BTEqualStrategyNumber, F_OIDEQ,
881  ObjectIdGetDatum(templateDbId));
882 
883  scan = systable_beginscan(sdepRel, SharedDependDependerIndexId, true,
884  NULL, 1, key);
885 
886  /* number of slots currently storing tuples */
887  slot_stored_count = 0;
888  /* number of slots currently initialized */
889  slot_init_count = 0;
890 
891  /*
892  * Copy the entries of the original database, changing the database Id to
893  * that of the new database. Note that because we are not copying rows
894  * with dbId == 0 (ie, rows describing dependent shared objects) we won't
895  * copy the ownership dependency of the template database itself; this is
896  * what we want.
897  */
898  while (HeapTupleIsValid(tup = systable_getnext(scan)))
899  {
900  Form_pg_shdepend shdep;
901 
902  if (slot_init_count < max_slots)
903  {
904  slot[slot_stored_count] = MakeSingleTupleTableSlot(sdepDesc, &TTSOpsHeapTuple);
905  slot_init_count++;
906  }
907 
908  ExecClearTuple(slot[slot_stored_count]);
909 
910  shdep = (Form_pg_shdepend) GETSTRUCT(tup);
911 
912  slot[slot_stored_count]->tts_values[Anum_pg_shdepend_dbid] = ObjectIdGetDatum(newDbId);
913  slot[slot_stored_count]->tts_values[Anum_pg_shdepend_classid] = shdep->classid;
914  slot[slot_stored_count]->tts_values[Anum_pg_shdepend_objid] = shdep->objid;
915  slot[slot_stored_count]->tts_values[Anum_pg_shdepend_objsubid] = shdep->objsubid;
916  slot[slot_stored_count]->tts_values[Anum_pg_shdepend_refclassid] = shdep->refclassid;
917  slot[slot_stored_count]->tts_values[Anum_pg_shdepend_refobjid] = shdep->refobjid;
918  slot[slot_stored_count]->tts_values[Anum_pg_shdepend_deptype] = shdep->deptype;
919 
920  ExecStoreVirtualTuple(slot[slot_stored_count]);
921  slot_stored_count++;
922 
923  /* If slots are full, insert a batch of tuples */
924  if (slot_stored_count == max_slots)
925  {
926  CatalogTuplesMultiInsertWithInfo(sdepRel, slot, slot_stored_count, indstate);
927  slot_stored_count = 0;
928  }
929  }
930 
931  /* Insert any tuples left in the buffer */
932  if (slot_stored_count > 0)
933  CatalogTuplesMultiInsertWithInfo(sdepRel, slot, slot_stored_count, indstate);
934 
935  systable_endscan(scan);
936 
937  CatalogCloseIndexes(indstate);
938  table_close(sdepRel, RowExclusiveLock);
939 
940  /* Drop only the number of slots used */
941  for (int i = 0; i < slot_init_count; i++)
943  pfree(slot);
944 }
void table_close(Relation relation, LOCKMODE lockmode)
Definition: table.c:167
void systable_endscan(SysScanDesc sysscan)
Definition: genam.c:595
#define GETSTRUCT(TUP)
Definition: htup_details.h:654
static TupleTableSlot * ExecClearTuple(TupleTableSlot *slot)
Definition: tuptable.h:425
#define RelationGetDescr(relation)
Definition: rel.h:483
TupleTableSlot * MakeSingleTupleTableSlot(TupleDesc tupdesc, const TupleTableSlotOps *tts_ops)
Definition: execTuples.c:1238
#define MAX_CATALOG_MULTI_INSERT_BYTES
Definition: indexing.h:33
FormData_pg_shdepend * Form_pg_shdepend
Definition: pg_shdepend.h:73
Datum * tts_values
Definition: tuptable.h:126
SysScanDesc systable_beginscan(Relation heapRelation, Oid indexId, bool indexOK, Snapshot snapshot, int nkeys, ScanKey key)
Definition: genam.c:383
HeapTuple systable_getnext(SysScanDesc sysscan)
Definition: genam.c:502
void pfree(void *pointer)
Definition: mcxt.c:1169
#define ObjectIdGetDatum(X)
Definition: postgres.h:551
void CatalogTuplesMultiInsertWithInfo(Relation heapRel, TupleTableSlot **slot, int ntuples, CatalogIndexState indstate)
Definition: indexing.c:261
void ExecDropSingleTupleTableSlot(TupleTableSlot *slot)
Definition: execTuples.c:1254
#define RowExclusiveLock
Definition: lockdefs.h:38
#define HeapTupleIsValid(tuple)
Definition: htup.h:78
FormData_pg_shdepend
Definition: pg_shdepend.h:66
CatalogIndexState CatalogOpenIndexes(Relation heapRel)
Definition: indexing.c:43
void * palloc(Size size)
Definition: mcxt.c:1062
int i
const TupleTableSlotOps TTSOpsHeapTuple
Definition: execTuples.c:84
void ScanKeyInit(ScanKey entry, AttrNumber attributeNumber, StrategyNumber strategy, RegProcedure procedure, Datum argument)
Definition: scankey.c:76
void CatalogCloseIndexes(CatalogIndexState indstate)
Definition: indexing.c:61
Relation table_open(Oid relationId, LOCKMODE lockmode)
Definition: table.c:39
#define SharedDependDependerIndexId
Definition: pg_shdepend.h:76
#define BTEqualStrategyNumber
Definition: stratnum.h:31
TupleTableSlot * ExecStoreVirtualTuple(TupleTableSlot *slot)
Definition: execTuples.c:1552

◆ deleteSharedDependencyRecordsFor()

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

Definition at line 1001 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().

1002 {
1003  Relation sdepRel;
1004 
1005  sdepRel = table_open(SharedDependRelationId, RowExclusiveLock);
1006 
1007  shdepDropDependency(sdepRel, classId, objectId, objectSubId,
1008  (objectSubId == 0),
1011 
1012  table_close(sdepRel, RowExclusiveLock);
1013 }
void table_close(Relation relation, LOCKMODE lockmode)
Definition: table.c:167
#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:1078
Relation table_open(Oid relationId, LOCKMODE lockmode)
Definition: table.c:39

◆ dropDatabaseDependencies()

void dropDatabaseDependencies ( Oid  databaseId)

Definition at line 953 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().

954 {
955  Relation sdepRel;
956  ScanKeyData key[1];
957  SysScanDesc scan;
958  HeapTuple tup;
959 
960  sdepRel = table_open(SharedDependRelationId, RowExclusiveLock);
961 
962  /*
963  * First, delete all the entries that have the database Oid in the dbid
964  * field.
965  */
966  ScanKeyInit(&key[0],
967  Anum_pg_shdepend_dbid,
968  BTEqualStrategyNumber, F_OIDEQ,
969  ObjectIdGetDatum(databaseId));
970  /* We leave the other index fields unspecified */
971 
972  scan = systable_beginscan(sdepRel, SharedDependDependerIndexId, true,
973  NULL, 1, key);
974 
975  while (HeapTupleIsValid(tup = systable_getnext(scan)))
976  {
977  CatalogTupleDelete(sdepRel, &tup->t_self);
978  }
979 
980  systable_endscan(scan);
981 
982  /* Now delete all entries corresponding to the database itself */
983  shdepDropDependency(sdepRel, DatabaseRelationId, databaseId, 0, true,
986 
987  table_close(sdepRel, RowExclusiveLock);
988 }
void table_close(Relation relation, LOCKMODE lockmode)
Definition: table.c:167
void systable_endscan(SysScanDesc sysscan)
Definition: genam.c:595
void CatalogTupleDelete(Relation heapRel, ItemPointer tid)
Definition: indexing.c:350
SysScanDesc systable_beginscan(Relation heapRelation, Oid indexId, bool indexOK, Snapshot snapshot, int nkeys, ScanKey key)
Definition: genam.c:383
HeapTuple systable_getnext(SysScanDesc sysscan)
Definition: genam.c:502
#define ObjectIdGetDatum(X)
Definition: postgres.h:551
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:1078
#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 SharedDependDependerIndexId
Definition: pg_shdepend.h:76
#define BTEqualStrategyNumber
Definition: stratnum.h:31

◆ getOidListDiff()

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

Definition at line 412 of file pg_shdepend.c.

Referenced by updateAclDependencies().

413 {
414  int in1,
415  in2,
416  out1,
417  out2;
418 
419  in1 = in2 = out1 = out2 = 0;
420  while (in1 < *nlist1 && in2 < *nlist2)
421  {
422  if (list1[in1] == list2[in2])
423  {
424  /* skip over duplicates */
425  in1++;
426  in2++;
427  }
428  else if (list1[in1] < list2[in2])
429  {
430  /* list1[in1] is not in list2 */
431  list1[out1++] = list1[in1++];
432  }
433  else
434  {
435  /* list2[in2] is not in list1 */
436  list2[out2++] = list2[in2++];
437  }
438  }
439 
440  /* any remaining list1 entries are not in list2 */
441  while (in1 < *nlist1)
442  {
443  list1[out1++] = list1[in1++];
444  }
445 
446  /* any remaining list2 entries are not in list1 */
447  while (in2 < *nlist2)
448  {
449  list2[out2++] = list2[in2++];
450  }
451 
452  *nlist1 = out1;
453  *nlist2 = out2;
454 }

◆ isSharedObjectPinned()

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

Definition at line 1283 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().

1284 {
1285  bool result = false;
1286  ScanKeyData key[2];
1287  SysScanDesc scan;
1288  HeapTuple tup;
1289 
1290  ScanKeyInit(&key[0],
1291  Anum_pg_shdepend_refclassid,
1292  BTEqualStrategyNumber, F_OIDEQ,
1293  ObjectIdGetDatum(classId));
1294  ScanKeyInit(&key[1],
1295  Anum_pg_shdepend_refobjid,
1296  BTEqualStrategyNumber, F_OIDEQ,
1297  ObjectIdGetDatum(objectId));
1298 
1299  scan = systable_beginscan(sdepRel, SharedDependReferenceIndexId, true,
1300  NULL, 2, key);
1301 
1302  /*
1303  * Since we won't generate additional pg_shdepend entries for pinned
1304  * objects, there can be at most one entry referencing a pinned object.
1305  * Hence, it's sufficient to look at the first returned tuple; we don't
1306  * need to loop.
1307  */
1308  tup = systable_getnext(scan);
1309  if (HeapTupleIsValid(tup))
1310  {
1311  Form_pg_shdepend shdepForm = (Form_pg_shdepend) GETSTRUCT(tup);
1312 
1313  if (shdepForm->deptype == SHARED_DEPENDENCY_PIN)
1314  result = true;
1315  }
1316 
1317  systable_endscan(scan);
1318 
1319  return result;
1320 }
void systable_endscan(SysScanDesc sysscan)
Definition: genam.c:595
#define GETSTRUCT(TUP)
Definition: htup_details.h:654
FormData_pg_shdepend * Form_pg_shdepend
Definition: pg_shdepend.h:73
SysScanDesc systable_beginscan(Relation heapRelation, Oid indexId, bool indexOK, Snapshot snapshot, int nkeys, ScanKey key)
Definition: genam.c:383
HeapTuple systable_getnext(SysScanDesc sysscan)
Definition: genam.c:502
#define ObjectIdGetDatum(X)
Definition: postgres.h:551
#define SharedDependReferenceIndexId
Definition: pg_shdepend.h:78
#define HeapTupleIsValid(tuple)
Definition: htup.h:78
void ScanKeyInit(ScanKey entry, AttrNumber attributeNumber, StrategyNumber strategy, RegProcedure procedure, Datum argument)
Definition: scankey.c:76
#define BTEqualStrategyNumber
Definition: stratnum.h:31

◆ recordDependencyOnOwner()

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

Definition at line 165 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().

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

◆ recordDependencyOnTablespace()

void recordDependencyOnTablespace ( Oid  classId,
Oid  objectId,
Oid  tablespace 
)

Definition at line 361 of file pg_shdepend.c.

References ObjectAddressSet, recordSharedDependencyOn(), and SHARED_DEPENDENCY_TABLESPACE.

Referenced by heap_create().

362 {
363  ObjectAddress myself,
364  referenced;
365 
366  ObjectAddressSet(myself, classId, objectId);
367  ObjectAddressSet(referenced, TableSpaceRelationId, tablespace);
368 
369  recordSharedDependencyOn(&myself, &referenced,
371 }
void recordSharedDependencyOn(ObjectAddress *depender, ObjectAddress *referenced, SharedDependencyType deptype)
Definition: pg_shdepend.c:121
char * tablespace
Definition: pgbench.c:224
#define ObjectAddressSet(addr, class_id, object_id)
Definition: objectaddress.h:40

◆ recordSharedDependencyOn()

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

Definition at line 121 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(), recordDependencyOnTablespace(), and RemoveRoleFromObjectPolicy().

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

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

Referenced by checkSharedDependencies().

566 {
567  const ShDependObjectInfo *obja = (const ShDependObjectInfo *) a;
568  const ShDependObjectInfo *objb = (const ShDependObjectInfo *) b;
569 
570  /*
571  * Primary sort key is OID ascending.
572  */
573  if (obja->object.objectId < objb->object.objectId)
574  return -1;
575  if (obja->object.objectId > objb->object.objectId)
576  return 1;
577 
578  /*
579  * Next sort on catalog ID, in case identical OIDs appear in different
580  * catalogs. Sort direction is pretty arbitrary here.
581  */
582  if (obja->object.classId < objb->object.classId)
583  return -1;
584  if (obja->object.classId > objb->object.classId)
585  return 1;
586 
587  /*
588  * Sort on object subId.
589  *
590  * We sort the subId as an unsigned int so that 0 (the whole object) will
591  * come first.
592  */
593  if ((unsigned int) obja->object.objectSubId < (unsigned int) objb->object.objectSubId)
594  return -1;
595  if ((unsigned int) obja->object.objectSubId > (unsigned int) objb->object.objectSubId)
596  return 1;
597 
598  /*
599  * Last, sort on deptype, in case the same object has multiple dependency
600  * types. (Note that there's no need to consider objtype, as that's
601  * determined by the catalog OID.)
602  */
603  if (obja->deptype < objb->deptype)
604  return -1;
605  if (obja->deptype > objb->deptype)
606  return 1;
607 
608  return 0;
609 }
ObjectAddress object
Definition: pg_shdepend.c:79

◆ shdepAddDependency()

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

Definition at line 1023 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().

1027 {
1028  HeapTuple tup;
1029  Datum values[Natts_pg_shdepend];
1030  bool nulls[Natts_pg_shdepend];
1031 
1032  /*
1033  * Make sure the object doesn't go away while we record the dependency on
1034  * it. DROP routines should lock the object exclusively before they check
1035  * shared dependencies.
1036  */
1037  shdepLockAndCheckObject(refclassId, refobjId);
1038 
1039  memset(nulls, false, sizeof(nulls));
1040 
1041  /*
1042  * Form the new tuple and record the dependency.
1043  */
1044  values[Anum_pg_shdepend_dbid - 1] = ObjectIdGetDatum(classIdGetDbId(classId));
1045  values[Anum_pg_shdepend_classid - 1] = ObjectIdGetDatum(classId);
1046  values[Anum_pg_shdepend_objid - 1] = ObjectIdGetDatum(objectId);
1047  values[Anum_pg_shdepend_objsubid - 1] = Int32GetDatum(objsubId);
1048 
1049  values[Anum_pg_shdepend_refclassid - 1] = ObjectIdGetDatum(refclassId);
1050  values[Anum_pg_shdepend_refobjid - 1] = ObjectIdGetDatum(refobjId);
1051  values[Anum_pg_shdepend_deptype - 1] = CharGetDatum(deptype);
1052 
1053  tup = heap_form_tuple(sdepRel->rd_att, values, nulls);
1054 
1055  CatalogTupleInsert(sdepRel, tup);
1056 
1057  /* clean up */
1058  heap_freetuple(tup);
1059 }
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:551
void shdepLockAndCheckObject(Oid classId, Oid objectId)
Definition: pg_shdepend.c:1165
uintptr_t Datum
Definition: postgres.h:411
TupleDesc rd_att
Definition: rel.h:111
static Oid classIdGetDbId(Oid classId)
Definition: pg_shdepend.c:1144
#define CharGetDatum(X)
Definition: postgres.h:460
static Datum values[MAXATTR]
Definition: bootstrap.c:166
#define Int32GetDatum(X)
Definition: postgres.h:523
void CatalogTupleInsert(Relation heapRel, HeapTuple tup)
Definition: indexing.c:221

◆ shdepChangeDep()

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

Definition at line 203 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(), and changeDependencyOnTablespace().

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

1083 {
1084  ScanKeyData key[4];
1085  int nkeys;
1086  SysScanDesc scan;
1087  HeapTuple tup;
1088 
1089  /* Scan for entries matching the dependent object */
1090  ScanKeyInit(&key[0],
1091  Anum_pg_shdepend_dbid,
1092  BTEqualStrategyNumber, F_OIDEQ,
1093  ObjectIdGetDatum(classIdGetDbId(classId)));
1094  ScanKeyInit(&key[1],
1095  Anum_pg_shdepend_classid,
1096  BTEqualStrategyNumber, F_OIDEQ,
1097  ObjectIdGetDatum(classId));
1098  ScanKeyInit(&key[2],
1099  Anum_pg_shdepend_objid,
1100  BTEqualStrategyNumber, F_OIDEQ,
1101  ObjectIdGetDatum(objectId));
1102  if (drop_subobjects)
1103  nkeys = 3;
1104  else
1105  {
1106  ScanKeyInit(&key[3],
1107  Anum_pg_shdepend_objsubid,
1108  BTEqualStrategyNumber, F_INT4EQ,
1109  Int32GetDatum(objsubId));
1110  nkeys = 4;
1111  }
1112 
1113  scan = systable_beginscan(sdepRel, SharedDependDependerIndexId, true,
1114  NULL, nkeys, key);
1115 
1116  while (HeapTupleIsValid(tup = systable_getnext(scan)))
1117  {
1118  Form_pg_shdepend shdepForm = (Form_pg_shdepend) GETSTRUCT(tup);
1119 
1120  /* Filter entries according to additional parameters */
1121  if (OidIsValid(refclassId) && shdepForm->refclassid != refclassId)
1122  continue;
1123  if (OidIsValid(refobjId) && shdepForm->refobjid != refobjId)
1124  continue;
1125  if (deptype != SHARED_DEPENDENCY_INVALID &&
1126  shdepForm->deptype != deptype)
1127  continue;
1128 
1129  /* OK, delete it */
1130  CatalogTupleDelete(sdepRel, &tup->t_self);
1131  }
1132 
1133  systable_endscan(scan);
1134 }
void systable_endscan(SysScanDesc sysscan)
Definition: genam.c:595
#define GETSTRUCT(TUP)
Definition: htup_details.h:654
FormData_pg_shdepend * Form_pg_shdepend
Definition: pg_shdepend.h:73
void CatalogTupleDelete(Relation heapRel, ItemPointer tid)
Definition: indexing.c:350
#define OidIsValid(objectId)
Definition: c.h:710
SysScanDesc systable_beginscan(Relation heapRelation, Oid indexId, bool indexOK, Snapshot snapshot, int nkeys, ScanKey key)
Definition: genam.c:383
HeapTuple systable_getnext(SysScanDesc sysscan)
Definition: genam.c:502
#define ObjectIdGetDatum(X)
Definition: postgres.h:551
ItemPointerData t_self
Definition: htup.h:65
#define HeapTupleIsValid(tuple)
Definition: htup.h:78
static Oid classIdGetDbId(Oid classId)
Definition: pg_shdepend.c:1144
#define Int32GetDatum(X)
Definition: postgres.h:523
void ScanKeyInit(ScanKey entry, AttrNumber attributeNumber, StrategyNumber strategy, RegProcedure procedure, Datum argument)
Definition: scankey.c:76
#define SharedDependDependerIndexId
Definition: pg_shdepend.h:76
#define BTEqualStrategyNumber
Definition: stratnum.h:31

◆ shdepDropOwned()

void shdepDropOwned ( List roleids,
DropBehavior  behavior 
)

Definition at line 1335 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().

1336 {
1337  Relation sdepRel;
1338  ListCell *cell;
1339  ObjectAddresses *deleteobjs;
1340 
1341  deleteobjs = new_object_addresses();
1342 
1343  /*
1344  * We don't need this strong a lock here, but we'll call routines that
1345  * acquire RowExclusiveLock. Better get that right now to avoid potential
1346  * deadlock failures.
1347  */
1348  sdepRel = table_open(SharedDependRelationId, RowExclusiveLock);
1349 
1350  /*
1351  * For each role, find the dependent objects and drop them using the
1352  * regular (non-shared) dependency management.
1353  */
1354  foreach(cell, roleids)
1355  {
1356  Oid roleid = lfirst_oid(cell);
1357  ScanKeyData key[2];
1358  SysScanDesc scan;
1359  HeapTuple tuple;
1360 
1361  /* Doesn't work for pinned objects */
1362  if (isSharedObjectPinned(AuthIdRelationId, roleid, sdepRel))
1363  {
1364  ObjectAddress obj;
1365 
1366  obj.classId = AuthIdRelationId;
1367  obj.objectId = roleid;
1368  obj.objectSubId = 0;
1369 
1370  ereport(ERROR,
1371  (errcode(ERRCODE_DEPENDENT_OBJECTS_STILL_EXIST),
1372  errmsg("cannot drop objects owned by %s because they are "
1373  "required by the database system",
1374  getObjectDescription(&obj, false))));
1375  }
1376 
1377  ScanKeyInit(&key[0],
1378  Anum_pg_shdepend_refclassid,
1379  BTEqualStrategyNumber, F_OIDEQ,
1380  ObjectIdGetDatum(AuthIdRelationId));
1381  ScanKeyInit(&key[1],
1382  Anum_pg_shdepend_refobjid,
1383  BTEqualStrategyNumber, F_OIDEQ,
1384  ObjectIdGetDatum(roleid));
1385 
1386  scan = systable_beginscan(sdepRel, SharedDependReferenceIndexId, true,
1387  NULL, 2, key);
1388 
1389  while ((tuple = systable_getnext(scan)) != NULL)
1390  {
1391  Form_pg_shdepend sdepForm = (Form_pg_shdepend) GETSTRUCT(tuple);
1392  ObjectAddress obj;
1393 
1394  /*
1395  * We only operate on shared objects and objects in the current
1396  * database
1397  */
1398  if (sdepForm->dbid != MyDatabaseId &&
1399  sdepForm->dbid != InvalidOid)
1400  continue;
1401 
1402  switch (sdepForm->deptype)
1403  {
1404  /* Shouldn't happen */
1405  case SHARED_DEPENDENCY_PIN:
1407  elog(ERROR, "unexpected dependency type");
1408  break;
1409  case SHARED_DEPENDENCY_ACL:
1410  RemoveRoleFromObjectACL(roleid,
1411  sdepForm->classid,
1412  sdepForm->objid);
1413  break;
1415 
1416  /*
1417  * Try to remove role from policy; if unable to, remove
1418  * policy.
1419  */
1420  if (!RemoveRoleFromObjectPolicy(roleid,
1421  sdepForm->classid,
1422  sdepForm->objid))
1423  {
1424  obj.classId = sdepForm->classid;
1425  obj.objectId = sdepForm->objid;
1426  obj.objectSubId = sdepForm->objsubid;
1427 
1428  /*
1429  * Acquire lock on object, then verify this dependency
1430  * is still relevant. If not, the object might have
1431  * been dropped or the policy modified. Ignore the
1432  * object in that case.
1433  */
1434  AcquireDeletionLock(&obj, 0);
1435  if (!systable_recheck_tuple(scan, tuple))
1436  {
1437  ReleaseDeletionLock(&obj);
1438  break;
1439  }
1440  add_exact_object_address(&obj, deleteobjs);
1441  }
1442  break;
1444  /* If a local object, save it for deletion below */
1445  if (sdepForm->dbid == MyDatabaseId)
1446  {
1447  obj.classId = sdepForm->classid;
1448  obj.objectId = sdepForm->objid;
1449  obj.objectSubId = sdepForm->objsubid;
1450  /* as above */
1451  AcquireDeletionLock(&obj, 0);
1452  if (!systable_recheck_tuple(scan, tuple))
1453  {
1454  ReleaseDeletionLock(&obj);
1455  break;
1456  }
1457  add_exact_object_address(&obj, deleteobjs);
1458  }
1459  break;
1460  }
1461  }
1462 
1463  systable_endscan(scan);
1464  }
1465 
1466  /*
1467  * For stability of deletion-report ordering, sort the objects into
1468  * approximate reverse creation order before deletion. (This might also
1469  * make the deletion go a bit faster, since there's less chance of having
1470  * to rearrange the objects due to dependencies.)
1471  */
1472  sort_object_addresses(deleteobjs);
1473 
1474  /* the dependency mechanism does the actual work */
1475  performMultipleDeletions(deleteobjs, behavior, 0);
1476 
1477  table_close(sdepRel, RowExclusiveLock);
1478 
1479  free_object_addresses(deleteobjs);
1480 }
char * getObjectDescription(const ObjectAddress *object, bool missing_ok)
void table_close(Relation relation, LOCKMODE lockmode)
Definition: table.c:167
void systable_endscan(SysScanDesc sysscan)
Definition: genam.c:595
#define GETSTRUCT(TUP)
Definition: htup_details.h:654
static bool isSharedObjectPinned(Oid classId, Oid objectId, Relation sdepRel)
Definition: pg_shdepend.c:1283
void sort_object_addresses(ObjectAddresses *addrs)
Definition: dependency.c:2850
FormData_pg_shdepend * Form_pg_shdepend
Definition: pg_shdepend.h:73
void ReleaseDeletionLock(const ObjectAddress *object)
Definition: dependency.c:1632
int errcode(int sqlerrcode)
Definition: elog.c:698
void add_exact_object_address(const ObjectAddress *object, ObjectAddresses *addrs)
Definition: dependency.c:2621
void RemoveRoleFromObjectACL(Oid roleid, Oid classid, Oid objid)
Definition: aclchk.c:1396
ObjectAddresses * new_object_addresses(void)
Definition: dependency.c:2566
void free_object_addresses(ObjectAddresses *addrs)
Definition: dependency.c:2862
unsigned int Oid
Definition: postgres_ext.h:31
SysScanDesc systable_beginscan(Relation heapRelation, Oid indexId, bool indexOK, Snapshot snapshot, int nkeys, ScanKey key)
Definition: genam.c:383
bool systable_recheck_tuple(SysScanDesc sysscan, HeapTuple tup)
Definition: genam.c:561
bool RemoveRoleFromObjectPolicy(Oid roleid, Oid classid, Oid policy_id)
Definition: policy.c:419
HeapTuple systable_getnext(SysScanDesc sysscan)
Definition: genam.c:502
#define ObjectIdGetDatum(X)
Definition: postgres.h:551
#define ERROR
Definition: elog.h:46
#define SharedDependReferenceIndexId
Definition: pg_shdepend.h:78
#define RowExclusiveLock
Definition: lockdefs.h:38
void AcquireDeletionLock(const ObjectAddress *object, int flags)
Definition: dependency.c:1603
Oid MyDatabaseId
Definition: globals.c:88
#define InvalidOid
Definition: postgres_ext.h:36
#define ereport(elevel,...)
Definition: elog.h:157
int errmsg(const char *fmt,...)
Definition: elog.c:909
#define elog(elevel,...)
Definition: elog.h:232
void ScanKeyInit(ScanKey entry, AttrNumber attributeNumber, StrategyNumber strategy, RegProcedure procedure, Datum argument)
Definition: scankey.c:76
void performMultipleDeletions(const ObjectAddresses *objects, DropBehavior behavior, int flags)
Definition: dependency.c:372
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:171

◆ shdepLockAndCheckObject()

void shdepLockAndCheckObject ( Oid  classId,
Oid  objectId 
)

Definition at line 1165 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().

1166 {
1167  /* AccessShareLock should be OK, since we are not modifying the object */
1168  LockSharedObject(classId, objectId, 0, AccessShareLock);
1169 
1170  switch (classId)
1171  {
1172  case AuthIdRelationId:
1174  ereport(ERROR,
1175  (errcode(ERRCODE_UNDEFINED_OBJECT),
1176  errmsg("role %u was concurrently dropped",
1177  objectId)));
1178  break;
1179 
1180  case TableSpaceRelationId:
1181  {
1182  /* For lack of a syscache on pg_tablespace, do this: */
1183  char *tablespace = get_tablespace_name(objectId);
1184 
1185  if (tablespace == NULL)
1186  ereport(ERROR,
1187  (errcode(ERRCODE_UNDEFINED_OBJECT),
1188  errmsg("tablespace %u was concurrently dropped",
1189  objectId)));
1190  pfree(tablespace);
1191  break;
1192  }
1193 
1194  case DatabaseRelationId:
1195  {
1196  /* For lack of a syscache on pg_database, do this: */
1197  char *database = get_database_name(objectId);
1198 
1199  if (database == NULL)
1200  ereport(ERROR,
1201  (errcode(ERRCODE_UNDEFINED_OBJECT),
1202  errmsg("database %u was concurrently dropped",
1203  objectId)));
1204  pfree(database);
1205  break;
1206  }
1207 
1208 
1209  default:
1210  elog(ERROR, "unrecognized shared classId: %u", classId);
1211  }
1212 }
#define AccessShareLock
Definition: lockdefs.h:36
int errcode(int sqlerrcode)
Definition: elog.c:698
#define SearchSysCacheExists1(cacheId, key1)
Definition: syscache.h:184
void pfree(void *pointer)
Definition: mcxt.c:1169
#define ObjectIdGetDatum(X)
Definition: postgres.h:551
#define ERROR
Definition: elog.h:46
char * get_database_name(Oid dbid)
Definition: dbcommands.c:2155
char * tablespace
Definition: pgbench.c:224
void LockSharedObject(Oid classid, Oid objid, uint16 objsubid, LOCKMODE lockmode)
Definition: lmgr.c:1017
#define ereport(elevel,...)
Definition: elog.h:157
int errmsg(const char *fmt,...)
Definition: elog.c:909
char * get_tablespace_name(Oid spc_oid)
Definition: tablespace.c:1479
#define elog(elevel,...)
Definition: elog.h:232

◆ shdepReassignOwned()

void shdepReassignOwned ( List roleids,
Oid  newrole 
)

Definition at line 1489 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().

1490 {
1491  Relation sdepRel;
1492  ListCell *cell;
1493 
1494  /*
1495  * We don't need this strong a lock here, but we'll call routines that
1496  * acquire RowExclusiveLock. Better get that right now to avoid potential
1497  * deadlock problems.
1498  */
1499  sdepRel = table_open(SharedDependRelationId, RowExclusiveLock);
1500 
1501  foreach(cell, roleids)
1502  {
1503  SysScanDesc scan;
1504  ScanKeyData key[2];
1505  HeapTuple tuple;
1506  Oid roleid = lfirst_oid(cell);
1507 
1508  /* Refuse to work on pinned roles */
1509  if (isSharedObjectPinned(AuthIdRelationId, roleid, sdepRel))
1510  {
1511  ObjectAddress obj;
1512 
1513  obj.classId = AuthIdRelationId;
1514  obj.objectId = roleid;
1515  obj.objectSubId = 0;
1516 
1517  ereport(ERROR,
1518  (errcode(ERRCODE_DEPENDENT_OBJECTS_STILL_EXIST),
1519  errmsg("cannot reassign ownership of objects owned by %s because they are required by the database system",
1520  getObjectDescription(&obj, false))));
1521 
1522  /*
1523  * There's no need to tell the whole truth, which is that we
1524  * didn't track these dependencies at all ...
1525  */
1526  }
1527 
1528  ScanKeyInit(&key[0],
1529  Anum_pg_shdepend_refclassid,
1530  BTEqualStrategyNumber, F_OIDEQ,
1531  ObjectIdGetDatum(AuthIdRelationId));
1532  ScanKeyInit(&key[1],
1533  Anum_pg_shdepend_refobjid,
1534  BTEqualStrategyNumber, F_OIDEQ,
1535  ObjectIdGetDatum(roleid));
1536 
1537  scan = systable_beginscan(sdepRel, SharedDependReferenceIndexId, true,
1538  NULL, 2, key);
1539 
1540  while ((tuple = systable_getnext(scan)) != NULL)
1541  {
1542  Form_pg_shdepend sdepForm = (Form_pg_shdepend) GETSTRUCT(tuple);
1543 
1544  /*
1545  * We only operate on shared objects and objects in the current
1546  * database
1547  */
1548  if (sdepForm->dbid != MyDatabaseId &&
1549  sdepForm->dbid != InvalidOid)
1550  continue;
1551 
1552  /* Unexpected because we checked for pins above */
1553  if (sdepForm->deptype == SHARED_DEPENDENCY_PIN)
1554  elog(ERROR, "unexpected shared pin");
1555 
1556  /* We leave non-owner dependencies alone */
1557  if (sdepForm->deptype != SHARED_DEPENDENCY_OWNER)
1558  continue;
1559 
1560  /* Issue the appropriate ALTER OWNER call */
1561  switch (sdepForm->classid)
1562  {
1563  case TypeRelationId:
1564  AlterTypeOwner_oid(sdepForm->objid, newrole, true);
1565  break;
1566 
1567  case NamespaceRelationId:
1568  AlterSchemaOwner_oid(sdepForm->objid, newrole);
1569  break;
1570 
1571  case RelationRelationId:
1572 
1573  /*
1574  * Pass recursing = true so that we don't fail on indexes,
1575  * owned sequences, etc when we happen to visit them
1576  * before their parent table.
1577  */
1578  ATExecChangeOwner(sdepForm->objid, newrole, true, AccessExclusiveLock);
1579  break;
1580 
1581  case DefaultAclRelationId:
1582 
1583  /*
1584  * Ignore default ACLs; they should be handled by DROP
1585  * OWNED, not REASSIGN OWNED.
1586  */
1587  break;
1588 
1589  case UserMappingRelationId:
1590  /* ditto */
1591  break;
1592 
1593  case ForeignServerRelationId:
1594  AlterForeignServerOwner_oid(sdepForm->objid, newrole);
1595  break;
1596 
1597  case ForeignDataWrapperRelationId:
1598  AlterForeignDataWrapperOwner_oid(sdepForm->objid, newrole);
1599  break;
1600 
1601  case EventTriggerRelationId:
1602  AlterEventTriggerOwner_oid(sdepForm->objid, newrole);
1603  break;
1604 
1605  case PublicationRelationId:
1606  AlterPublicationOwner_oid(sdepForm->objid, newrole);
1607  break;
1608 
1609  case SubscriptionRelationId:
1610  AlterSubscriptionOwner_oid(sdepForm->objid, newrole);
1611  break;
1612 
1613  /* Generic alter owner cases */
1614  case CollationRelationId:
1615  case ConversionRelationId:
1616  case OperatorRelationId:
1617  case ProcedureRelationId:
1618  case LanguageRelationId:
1619  case LargeObjectRelationId:
1620  case OperatorFamilyRelationId:
1621  case OperatorClassRelationId:
1622  case ExtensionRelationId:
1623  case StatisticExtRelationId:
1624  case TableSpaceRelationId:
1625  case DatabaseRelationId:
1626  case TSConfigRelationId:
1627  case TSDictionaryRelationId:
1628  {
1629  Oid classId = sdepForm->classid;
1630  Relation catalog;
1631 
1632  if (classId == LargeObjectRelationId)
1633  classId = LargeObjectMetadataRelationId;
1634 
1635  catalog = table_open(classId, RowExclusiveLock);
1636 
1637  AlterObjectOwner_internal(catalog, sdepForm->objid,
1638  newrole);
1639 
1640  table_close(catalog, NoLock);
1641  }
1642  break;
1643 
1644  default:
1645  elog(ERROR, "unexpected classid %u", sdepForm->classid);
1646  break;
1647  }
1648  /* Make sure the next iteration will see my changes */
1650  }
1651 
1652  systable_endscan(scan);
1653  }
1654 
1655  table_close(sdepRel, RowExclusiveLock);
1656 }
char * getObjectDescription(const ObjectAddress *object, bool missing_ok)
void table_close(Relation relation, LOCKMODE lockmode)
Definition: table.c:167
void systable_endscan(SysScanDesc sysscan)
Definition: genam.c:595
#define GETSTRUCT(TUP)
Definition: htup_details.h:654
void AlterForeignDataWrapperOwner_oid(Oid fwdId, Oid newOwnerId)
Definition: foreigncmds.c:313
static bool isSharedObjectPinned(Oid classId, Oid objectId, Relation sdepRel)
Definition: pg_shdepend.c:1283
void AlterSchemaOwner_oid(Oid oid, Oid newOwnerId)
Definition: schemacmds.c:276
FormData_pg_shdepend * Form_pg_shdepend
Definition: pg_shdepend.h:73
void AlterForeignServerOwner_oid(Oid srvId, Oid newOwnerId)
Definition: foreigncmds.c:450
int errcode(int sqlerrcode)
Definition: elog.c:698
unsigned int Oid
Definition: postgres_ext.h:31
SysScanDesc systable_beginscan(Relation heapRelation, Oid indexId, bool indexOK, Snapshot snapshot, int nkeys, ScanKey key)
Definition: genam.c:383
HeapTuple systable_getnext(SysScanDesc sysscan)
Definition: genam.c:502
#define ObjectIdGetDatum(X)
Definition: postgres.h:551
#define ERROR
Definition: elog.h:46
#define SharedDependReferenceIndexId
Definition: pg_shdepend.h:78
void AlterTypeOwner_oid(Oid typeOid, Oid newOwnerId, bool hasDependEntry)
Definition: typecmds.c:3800
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:13056
void CommandCounterIncrement(void)
Definition: xact.c:1021
Oid MyDatabaseId
Definition: globals.c:88
#define InvalidOid
Definition: postgres_ext.h:36
void AlterEventTriggerOwner_oid(Oid trigOid, Oid newOwnerId)
#define ereport(elevel,...)
Definition: elog.h:157
#define AccessExclusiveLock
Definition: lockdefs.h:45
int errmsg(const char *fmt,...)
Definition: elog.c:909
#define elog(elevel,...)
Definition: elog.h:232
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)
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:171

◆ storeObjectDescription()

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

Definition at line 1230 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, SHARED_DEPENDENCY_TABLESPACE, and SHARED_OBJECT.

Referenced by checkSharedDependencies().

1235 {
1236  char *objdesc = getObjectDescription(object, false);
1237 
1238  /* separate entries with a newline */
1239  if (descs->len != 0)
1240  appendStringInfoChar(descs, '\n');
1241 
1242  switch (type)
1243  {
1244  case LOCAL_OBJECT:
1245  case SHARED_OBJECT:
1246  if (deptype == SHARED_DEPENDENCY_OWNER)
1247  appendStringInfo(descs, _("owner of %s"), objdesc);
1248  else if (deptype == SHARED_DEPENDENCY_ACL)
1249  appendStringInfo(descs, _("privileges for %s"), objdesc);
1250  else if (deptype == SHARED_DEPENDENCY_POLICY)
1251  appendStringInfo(descs, _("target of %s"), objdesc);
1252  else if (deptype == SHARED_DEPENDENCY_TABLESPACE)
1253  appendStringInfo(descs, _("tablespace for %s"), objdesc);
1254  else
1255  elog(ERROR, "unrecognized dependency type: %d",
1256  (int) deptype);
1257  break;
1258 
1259  case REMOTE_OBJECT:
1260  /* translator: %s will always be "database %s" */
1261  appendStringInfo(descs, ngettext("%d object in %s",
1262  "%d objects in %s",
1263  count),
1264  count, objdesc);
1265  break;
1266 
1267  default:
1268  elog(ERROR, "unrecognized object type: %d", type);
1269  }
1270 
1271  pfree(objdesc);
1272 }
char * getObjectDescription(const ObjectAddress *object, bool missing_ok)
void pfree(void *pointer)
Definition: mcxt.c:1169
void appendStringInfo(StringInfo str, const char *fmt,...)
Definition: stringinfo.c:91
#define ERROR
Definition: elog.h:46
void appendStringInfoChar(StringInfo str, char ch)
Definition: stringinfo.c:188
#define ngettext(s, p, n)
Definition: c.h:1182
#define elog(elevel,...)
Definition: elog.h:232
#define _(x)
Definition: elog.c:89

◆ updateAclDependencies()

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

Definition at line 482 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().

486 {
487  Relation sdepRel;
488  int i;
489 
490  /*
491  * Remove entries that are common to both lists; those represent existing
492  * dependencies we don't need to change.
493  *
494  * OK to overwrite the inputs since we'll pfree them anyway.
495  */
496  getOidListDiff(oldmembers, &noldmembers, newmembers, &nnewmembers);
497 
498  if (noldmembers > 0 || nnewmembers > 0)
499  {
500  sdepRel = table_open(SharedDependRelationId, RowExclusiveLock);
501 
502  /* Add new dependencies that weren't already present */
503  for (i = 0; i < nnewmembers; i++)
504  {
505  Oid roleid = newmembers[i];
506 
507  /*
508  * Skip the owner: he has an OWNER shdep entry instead. (This is
509  * not just a space optimization; it makes ALTER OWNER easier. See
510  * notes in changeDependencyOnOwner.)
511  */
512  if (roleid == ownerId)
513  continue;
514 
515  /* Skip pinned roles; they don't need dependency entries */
516  if (isSharedObjectPinned(AuthIdRelationId, roleid, sdepRel))
517  continue;
518 
519  shdepAddDependency(sdepRel, classId, objectId, objsubId,
520  AuthIdRelationId, roleid,
522  }
523 
524  /* Drop no-longer-used old dependencies */
525  for (i = 0; i < noldmembers; i++)
526  {
527  Oid roleid = oldmembers[i];
528 
529  /* Skip the owner, same as above */
530  if (roleid == ownerId)
531  continue;
532 
533  /* Skip pinned roles */
534  if (isSharedObjectPinned(AuthIdRelationId, roleid, sdepRel))
535  continue;
536 
537  shdepDropDependency(sdepRel, classId, objectId, objsubId,
538  false, /* exact match on objsubId */
539  AuthIdRelationId, roleid,
541  }
542 
543  table_close(sdepRel, RowExclusiveLock);
544  }
545 
546  if (oldmembers)
547  pfree(oldmembers);
548  if (newmembers)
549  pfree(newmembers);
550 }
void table_close(Relation relation, LOCKMODE lockmode)
Definition: table.c:167
static bool isSharedObjectPinned(Oid classId, Oid objectId, Relation sdepRel)
Definition: pg_shdepend.c:1283
static void getOidListDiff(Oid *list1, int *nlist1, Oid *list2, int *nlist2)
Definition: pg_shdepend.c:412
static void shdepAddDependency(Relation sdepRel, Oid classId, Oid objectId, int32 objsubId, Oid refclassId, Oid refobjId, SharedDependencyType deptype)
Definition: pg_shdepend.c:1023
unsigned int Oid
Definition: postgres_ext.h:31
void pfree(void *pointer)
Definition: mcxt.c:1169
#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:1078
int i
Relation table_open(Oid relationId, LOCKMODE lockmode)
Definition: table.c:39