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

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

◆ changeDependencyOnTablespace()

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

Definition at line 380 of file pg_shdepend.c.

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

Referenced by SetRelationTableSpace().

381 {
382  Relation sdepRel;
383 
384  sdepRel = table_open(SharedDependRelationId, RowExclusiveLock);
385 
386  if (newTablespaceId != DEFAULTTABLESPACE_OID &&
387  newTablespaceId != InvalidOid)
388  shdepChangeDep(sdepRel,
389  classId, objectId, 0,
390  TableSpaceRelationId, newTablespaceId,
392  else
393  shdepDropDependency(sdepRel,
394  classId, objectId, 0, true,
397 
398  table_close(sdepRel, RowExclusiveLock);
399 }
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:201
#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:1074
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 629 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, IsPinnedObject(), 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_OBJECT, storeObjectDescription(), systable_beginscan(), systable_endscan(), systable_getnext(), table_close(), and table_open().

Referenced by DropRole(), and DropTableSpace().

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

References InvalidOid, IsSharedRelation(), and MyDatabaseId.

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

1141 {
1142  Oid dbId;
1143 
1144  if (IsSharedRelation(classId))
1145  dbId = InvalidOid;
1146  else
1147  dbId = MyDatabaseId;
1148 
1149  return dbId;
1150 }
unsigned int Oid
Definition: postgres_ext.h:31
Oid MyDatabaseId
Definition: globals.c:88
bool IsSharedRelation(Oid relationId)
Definition: catalog.c:244
#define InvalidOid
Definition: postgres_ext.h:36

◆ copyTemplateDependencies()

void copyTemplateDependencies ( Oid  templateDbId,
Oid  newDbId 
)

Definition at line 848 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(), systable_beginscan(), systable_endscan(), systable_getnext(), table_close(), table_open(), TupleTableSlot::tts_values, and TTSOpsHeapTuple.

Referenced by createdb().

849 {
850  Relation sdepRel;
851  TupleDesc sdepDesc;
852  ScanKeyData key[1];
853  SysScanDesc scan;
854  HeapTuple tup;
855  CatalogIndexState indstate;
856  TupleTableSlot **slot;
857  int max_slots,
858  slot_init_count,
859  slot_stored_count;
860 
861  sdepRel = table_open(SharedDependRelationId, RowExclusiveLock);
862  sdepDesc = RelationGetDescr(sdepRel);
863 
864  /*
865  * Allocate the slots to use, but delay costly initialization until we
866  * know that they will be used.
867  */
869  slot = palloc(sizeof(TupleTableSlot *) * max_slots);
870 
871  indstate = CatalogOpenIndexes(sdepRel);
872 
873  /* Scan all entries with dbid = templateDbId */
874  ScanKeyInit(&key[0],
875  Anum_pg_shdepend_dbid,
876  BTEqualStrategyNumber, F_OIDEQ,
877  ObjectIdGetDatum(templateDbId));
878 
879  scan = systable_beginscan(sdepRel, SharedDependDependerIndexId, true,
880  NULL, 1, key);
881 
882  /* number of slots currently storing tuples */
883  slot_stored_count = 0;
884  /* number of slots currently initialized */
885  slot_init_count = 0;
886 
887  /*
888  * Copy the entries of the original database, changing the database Id to
889  * that of the new database. Note that because we are not copying rows
890  * with dbId == 0 (ie, rows describing dependent shared objects) we won't
891  * copy the ownership dependency of the template database itself; this is
892  * what we want.
893  */
894  while (HeapTupleIsValid(tup = systable_getnext(scan)))
895  {
896  Form_pg_shdepend shdep;
897 
898  if (slot_init_count < max_slots)
899  {
900  slot[slot_stored_count] = MakeSingleTupleTableSlot(sdepDesc, &TTSOpsHeapTuple);
901  slot_init_count++;
902  }
903 
904  ExecClearTuple(slot[slot_stored_count]);
905 
906  shdep = (Form_pg_shdepend) GETSTRUCT(tup);
907 
908  slot[slot_stored_count]->tts_values[Anum_pg_shdepend_dbid] = ObjectIdGetDatum(newDbId);
909  slot[slot_stored_count]->tts_values[Anum_pg_shdepend_classid] = shdep->classid;
910  slot[slot_stored_count]->tts_values[Anum_pg_shdepend_objid] = shdep->objid;
911  slot[slot_stored_count]->tts_values[Anum_pg_shdepend_objsubid] = shdep->objsubid;
912  slot[slot_stored_count]->tts_values[Anum_pg_shdepend_refclassid] = shdep->refclassid;
913  slot[slot_stored_count]->tts_values[Anum_pg_shdepend_refobjid] = shdep->refobjid;
914  slot[slot_stored_count]->tts_values[Anum_pg_shdepend_deptype] = shdep->deptype;
915 
916  ExecStoreVirtualTuple(slot[slot_stored_count]);
917  slot_stored_count++;
918 
919  /* If slots are full, insert a batch of tuples */
920  if (slot_stored_count == max_slots)
921  {
922  CatalogTuplesMultiInsertWithInfo(sdepRel, slot, slot_stored_count, indstate);
923  slot_stored_count = 0;
924  }
925  }
926 
927  /* Insert any tuples left in the buffer */
928  if (slot_stored_count > 0)
929  CatalogTuplesMultiInsertWithInfo(sdepRel, slot, slot_stored_count, indstate);
930 
931  systable_endscan(scan);
932 
933  CatalogCloseIndexes(indstate);
934  table_close(sdepRel, RowExclusiveLock);
935 
936  /* Drop only the number of slots used */
937  for (int i = 0; i < slot_init_count; i++)
939  pfree(slot);
940 }
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:503
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 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 997 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().

998 {
999  Relation sdepRel;
1000 
1001  sdepRel = table_open(SharedDependRelationId, RowExclusiveLock);
1002 
1003  shdepDropDependency(sdepRel, classId, objectId, objectSubId,
1004  (objectSubId == 0),
1007 
1008  table_close(sdepRel, RowExclusiveLock);
1009 }
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:1074
Relation table_open(Oid relationId, LOCKMODE lockmode)
Definition: table.c:39

◆ dropDatabaseDependencies()

void dropDatabaseDependencies ( Oid  databaseId)

Definition at line 949 of file pg_shdepend.c.

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

Referenced by dropdb().

950 {
951  Relation sdepRel;
952  ScanKeyData key[1];
953  SysScanDesc scan;
954  HeapTuple tup;
955 
956  sdepRel = table_open(SharedDependRelationId, RowExclusiveLock);
957 
958  /*
959  * First, delete all the entries that have the database Oid in the dbid
960  * field.
961  */
962  ScanKeyInit(&key[0],
963  Anum_pg_shdepend_dbid,
964  BTEqualStrategyNumber, F_OIDEQ,
965  ObjectIdGetDatum(databaseId));
966  /* We leave the other index fields unspecified */
967 
968  scan = systable_beginscan(sdepRel, SharedDependDependerIndexId, true,
969  NULL, 1, key);
970 
971  while (HeapTupleIsValid(tup = systable_getnext(scan)))
972  {
973  CatalogTupleDelete(sdepRel, &tup->t_self);
974  }
975 
976  systable_endscan(scan);
977 
978  /* Now delete all entries corresponding to the database itself */
979  shdepDropDependency(sdepRel, DatabaseRelationId, databaseId, 0, true,
982 
983  table_close(sdepRel, RowExclusiveLock);
984 }
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:1074
#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 410 of file pg_shdepend.c.

Referenced by updateAclDependencies().

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

◆ recordDependencyOnOwner()

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

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

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

◆ recordDependencyOnTablespace()

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

Definition at line 359 of file pg_shdepend.c.

References ObjectAddressSet, recordSharedDependencyOn(), and SHARED_DEPENDENCY_TABLESPACE.

Referenced by heap_create().

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

◆ recordSharedDependencyOn()

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

Definition at line 120 of file pg_shdepend.c.

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

Referenced by AlterPolicy(), CreatePolicy(), recordDependencyOnOwner(), recordDependencyOnTablespace(), 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 (!IsPinnedObject(referenced->classId, referenced->objectId))
143  {
144  shdepAddDependency(sdepRel, depender->classId, depender->objectId,
145  depender->objectSubId,
146  referenced->classId, referenced->objectId,
147  deptype);
148  }
149 
150  table_close(sdepRel, RowExclusiveLock);
151 }
void table_close(Relation relation, LOCKMODE lockmode)
Definition: table.c:167
static void shdepAddDependency(Relation sdepRel, Oid classId, Oid objectId, int32 objsubId, Oid refclassId, Oid refobjId, SharedDependencyType deptype)
Definition: pg_shdepend.c:1019
bool IsPinnedObject(Oid classId, Oid objectId)
Definition: catalog.c:307
#define RowExclusiveLock
Definition: lockdefs.h:38
#define Assert(condition)
Definition: c.h:804
#define IsBootstrapProcessingMode()
Definition: miscadmin.h:406
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 563 of file pg_shdepend.c.

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

Referenced by checkSharedDependencies().

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

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

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

Referenced by changeDependencyOnOwner(), and changeDependencyOnTablespace().

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

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

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

1079 {
1080  ScanKeyData key[4];
1081  int nkeys;
1082  SysScanDesc scan;
1083  HeapTuple tup;
1084 
1085  /* Scan for entries matching the dependent object */
1086  ScanKeyInit(&key[0],
1087  Anum_pg_shdepend_dbid,
1088  BTEqualStrategyNumber, F_OIDEQ,
1089  ObjectIdGetDatum(classIdGetDbId(classId)));
1090  ScanKeyInit(&key[1],
1091  Anum_pg_shdepend_classid,
1092  BTEqualStrategyNumber, F_OIDEQ,
1093  ObjectIdGetDatum(classId));
1094  ScanKeyInit(&key[2],
1095  Anum_pg_shdepend_objid,
1096  BTEqualStrategyNumber, F_OIDEQ,
1097  ObjectIdGetDatum(objectId));
1098  if (drop_subobjects)
1099  nkeys = 3;
1100  else
1101  {
1102  ScanKeyInit(&key[3],
1103  Anum_pg_shdepend_objsubid,
1104  BTEqualStrategyNumber, F_INT4EQ,
1105  Int32GetDatum(objsubId));
1106  nkeys = 4;
1107  }
1108 
1109  scan = systable_beginscan(sdepRel, SharedDependDependerIndexId, true,
1110  NULL, nkeys, key);
1111 
1112  while (HeapTupleIsValid(tup = systable_getnext(scan)))
1113  {
1114  Form_pg_shdepend shdepForm = (Form_pg_shdepend) GETSTRUCT(tup);
1115 
1116  /* Filter entries according to additional parameters */
1117  if (OidIsValid(refclassId) && shdepForm->refclassid != refclassId)
1118  continue;
1119  if (OidIsValid(refobjId) && shdepForm->refobjid != refobjId)
1120  continue;
1121  if (deptype != SHARED_DEPENDENCY_INVALID &&
1122  shdepForm->deptype != deptype)
1123  continue;
1124 
1125  /* OK, delete it */
1126  CatalogTupleDelete(sdepRel, &tup->t_self);
1127  }
1128 
1129  systable_endscan(scan);
1130 }
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:1140
#define Int32GetDatum(X)
Definition: postgres.h:523
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 1284 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, IsPinnedObject(), 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_POLICY, sort_object_addresses(), systable_beginscan(), systable_endscan(), systable_getnext(), systable_recheck_tuple(), table_close(), and table_open().

Referenced by DropOwnedObjects().

1285 {
1286  Relation sdepRel;
1287  ListCell *cell;
1288  ObjectAddresses *deleteobjs;
1289 
1290  deleteobjs = new_object_addresses();
1291 
1292  /*
1293  * We don't need this strong a lock here, but we'll call routines that
1294  * acquire RowExclusiveLock. Better get that right now to avoid potential
1295  * deadlock failures.
1296  */
1297  sdepRel = table_open(SharedDependRelationId, RowExclusiveLock);
1298 
1299  /*
1300  * For each role, find the dependent objects and drop them using the
1301  * regular (non-shared) dependency management.
1302  */
1303  foreach(cell, roleids)
1304  {
1305  Oid roleid = lfirst_oid(cell);
1306  ScanKeyData key[2];
1307  SysScanDesc scan;
1308  HeapTuple tuple;
1309 
1310  /* Doesn't work for pinned objects */
1311  if (IsPinnedObject(AuthIdRelationId, roleid))
1312  {
1313  ObjectAddress obj;
1314 
1315  obj.classId = AuthIdRelationId;
1316  obj.objectId = roleid;
1317  obj.objectSubId = 0;
1318 
1319  ereport(ERROR,
1320  (errcode(ERRCODE_DEPENDENT_OBJECTS_STILL_EXIST),
1321  errmsg("cannot drop objects owned by %s because they are "
1322  "required by the database system",
1323  getObjectDescription(&obj, false))));
1324  }
1325 
1326  ScanKeyInit(&key[0],
1327  Anum_pg_shdepend_refclassid,
1328  BTEqualStrategyNumber, F_OIDEQ,
1329  ObjectIdGetDatum(AuthIdRelationId));
1330  ScanKeyInit(&key[1],
1331  Anum_pg_shdepend_refobjid,
1332  BTEqualStrategyNumber, F_OIDEQ,
1333  ObjectIdGetDatum(roleid));
1334 
1335  scan = systable_beginscan(sdepRel, SharedDependReferenceIndexId, true,
1336  NULL, 2, key);
1337 
1338  while ((tuple = systable_getnext(scan)) != NULL)
1339  {
1340  Form_pg_shdepend sdepForm = (Form_pg_shdepend) GETSTRUCT(tuple);
1341  ObjectAddress obj;
1342 
1343  /*
1344  * We only operate on shared objects and objects in the current
1345  * database
1346  */
1347  if (sdepForm->dbid != MyDatabaseId &&
1348  sdepForm->dbid != InvalidOid)
1349  continue;
1350 
1351  switch (sdepForm->deptype)
1352  {
1353  /* Shouldn't happen */
1355  elog(ERROR, "unexpected dependency type");
1356  break;
1357  case SHARED_DEPENDENCY_ACL:
1358  RemoveRoleFromObjectACL(roleid,
1359  sdepForm->classid,
1360  sdepForm->objid);
1361  break;
1363 
1364  /*
1365  * Try to remove role from policy; if unable to, remove
1366  * policy.
1367  */
1368  if (!RemoveRoleFromObjectPolicy(roleid,
1369  sdepForm->classid,
1370  sdepForm->objid))
1371  {
1372  obj.classId = sdepForm->classid;
1373  obj.objectId = sdepForm->objid;
1374  obj.objectSubId = sdepForm->objsubid;
1375 
1376  /*
1377  * Acquire lock on object, then verify this dependency
1378  * is still relevant. If not, the object might have
1379  * been dropped or the policy modified. Ignore the
1380  * object in that case.
1381  */
1382  AcquireDeletionLock(&obj, 0);
1383  if (!systable_recheck_tuple(scan, tuple))
1384  {
1385  ReleaseDeletionLock(&obj);
1386  break;
1387  }
1388  add_exact_object_address(&obj, deleteobjs);
1389  }
1390  break;
1392  /* If a local object, save it for deletion below */
1393  if (sdepForm->dbid == MyDatabaseId)
1394  {
1395  obj.classId = sdepForm->classid;
1396  obj.objectId = sdepForm->objid;
1397  obj.objectSubId = sdepForm->objsubid;
1398  /* as above */
1399  AcquireDeletionLock(&obj, 0);
1400  if (!systable_recheck_tuple(scan, tuple))
1401  {
1402  ReleaseDeletionLock(&obj);
1403  break;
1404  }
1405  add_exact_object_address(&obj, deleteobjs);
1406  }
1407  break;
1408  }
1409  }
1410 
1411  systable_endscan(scan);
1412  }
1413 
1414  /*
1415  * For stability of deletion-report ordering, sort the objects into
1416  * approximate reverse creation order before deletion. (This might also
1417  * make the deletion go a bit faster, since there's less chance of having
1418  * to rearrange the objects due to dependencies.)
1419  */
1420  sort_object_addresses(deleteobjs);
1421 
1422  /* the dependency mechanism does the actual work */
1423  performMultipleDeletions(deleteobjs, behavior, 0);
1424 
1425  table_close(sdepRel, RowExclusiveLock);
1426 
1427  free_object_addresses(deleteobjs);
1428 }
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 sort_object_addresses(ObjectAddresses *addrs)
Definition: dependency.c:2710
FormData_pg_shdepend * Form_pg_shdepend
Definition: pg_shdepend.h:73
void ReleaseDeletionLock(const ObjectAddress *object)
Definition: dependency.c:1543
int errcode(int sqlerrcode)
Definition: elog.c:698
void add_exact_object_address(const ObjectAddress *object, ObjectAddresses *addrs)
Definition: dependency.c:2482
void RemoveRoleFromObjectACL(Oid roleid, Oid classid, Oid objid)
Definition: aclchk.c:1391
ObjectAddresses * new_object_addresses(void)
Definition: dependency.c:2427
void free_object_addresses(ObjectAddresses *addrs)
Definition: dependency.c:2722
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
bool IsPinnedObject(Oid classId, Oid objectId)
Definition: catalog.c:307
#define ObjectIdGetDatum(X)
Definition: postgres.h:551
#define ERROR
Definition: elog.h:46
#define RowExclusiveLock
Definition: lockdefs.h:38
void AcquireDeletionLock(const ObjectAddress *object, int flags)
Definition: dependency.c:1514
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 1161 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().

1162 {
1163  /* AccessShareLock should be OK, since we are not modifying the object */
1164  LockSharedObject(classId, objectId, 0, AccessShareLock);
1165 
1166  switch (classId)
1167  {
1168  case AuthIdRelationId:
1170  ereport(ERROR,
1171  (errcode(ERRCODE_UNDEFINED_OBJECT),
1172  errmsg("role %u was concurrently dropped",
1173  objectId)));
1174  break;
1175 
1176  case TableSpaceRelationId:
1177  {
1178  /* For lack of a syscache on pg_tablespace, do this: */
1179  char *tablespace = get_tablespace_name(objectId);
1180 
1181  if (tablespace == NULL)
1182  ereport(ERROR,
1183  (errcode(ERRCODE_UNDEFINED_OBJECT),
1184  errmsg("tablespace %u was concurrently dropped",
1185  objectId)));
1186  pfree(tablespace);
1187  break;
1188  }
1189 
1190  case DatabaseRelationId:
1191  {
1192  /* For lack of a syscache on pg_database, do this: */
1193  char *database = get_database_name(objectId);
1194 
1195  if (database == NULL)
1196  ereport(ERROR,
1197  (errcode(ERRCODE_UNDEFINED_OBJECT),
1198  errmsg("database %u was concurrently dropped",
1199  objectId)));
1200  pfree(database);
1201  break;
1202  }
1203 
1204 
1205  default:
1206  elog(ERROR, "unrecognized shared classId: %u", classId);
1207  }
1208 }
#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:2113
char * tablespace
Definition: pgbench.c:226
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:1477
#define elog(elevel,...)
Definition: elog.h:232

◆ shdepReassignOwned()

void shdepReassignOwned ( List roleids,
Oid  newrole 
)

Definition at line 1437 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, IsPinnedObject(), sort-test::key, lfirst_oid, MyDatabaseId, NoLock, ObjectAddress::objectId, ObjectIdGetDatum, ObjectAddress::objectSubId, RowExclusiveLock, ScanKeyInit(), SHARED_DEPENDENCY_OWNER, systable_beginscan(), systable_endscan(), systable_getnext(), table_close(), and table_open().

Referenced by ReassignOwnedObjects().

1438 {
1439  Relation sdepRel;
1440  ListCell *cell;
1441 
1442  /*
1443  * We don't need this strong a lock here, but we'll call routines that
1444  * acquire RowExclusiveLock. Better get that right now to avoid potential
1445  * deadlock problems.
1446  */
1447  sdepRel = table_open(SharedDependRelationId, RowExclusiveLock);
1448 
1449  foreach(cell, roleids)
1450  {
1451  SysScanDesc scan;
1452  ScanKeyData key[2];
1453  HeapTuple tuple;
1454  Oid roleid = lfirst_oid(cell);
1455 
1456  /* Refuse to work on pinned roles */
1457  if (IsPinnedObject(AuthIdRelationId, roleid))
1458  {
1459  ObjectAddress obj;
1460 
1461  obj.classId = AuthIdRelationId;
1462  obj.objectId = roleid;
1463  obj.objectSubId = 0;
1464 
1465  ereport(ERROR,
1466  (errcode(ERRCODE_DEPENDENT_OBJECTS_STILL_EXIST),
1467  errmsg("cannot reassign ownership of objects owned by %s because they are required by the database system",
1468  getObjectDescription(&obj, false))));
1469 
1470  /*
1471  * There's no need to tell the whole truth, which is that we
1472  * didn't track these dependencies at all ...
1473  */
1474  }
1475 
1476  ScanKeyInit(&key[0],
1477  Anum_pg_shdepend_refclassid,
1478  BTEqualStrategyNumber, F_OIDEQ,
1479  ObjectIdGetDatum(AuthIdRelationId));
1480  ScanKeyInit(&key[1],
1481  Anum_pg_shdepend_refobjid,
1482  BTEqualStrategyNumber, F_OIDEQ,
1483  ObjectIdGetDatum(roleid));
1484 
1485  scan = systable_beginscan(sdepRel, SharedDependReferenceIndexId, true,
1486  NULL, 2, key);
1487 
1488  while ((tuple = systable_getnext(scan)) != NULL)
1489  {
1490  Form_pg_shdepend sdepForm = (Form_pg_shdepend) GETSTRUCT(tuple);
1491 
1492  /*
1493  * We only operate on shared objects and objects in the current
1494  * database
1495  */
1496  if (sdepForm->dbid != MyDatabaseId &&
1497  sdepForm->dbid != InvalidOid)
1498  continue;
1499 
1500  /* We leave non-owner dependencies alone */
1501  if (sdepForm->deptype != SHARED_DEPENDENCY_OWNER)
1502  continue;
1503 
1504  /* Issue the appropriate ALTER OWNER call */
1505  switch (sdepForm->classid)
1506  {
1507  case TypeRelationId:
1508  AlterTypeOwner_oid(sdepForm->objid, newrole, true);
1509  break;
1510 
1511  case NamespaceRelationId:
1512  AlterSchemaOwner_oid(sdepForm->objid, newrole);
1513  break;
1514 
1515  case RelationRelationId:
1516 
1517  /*
1518  * Pass recursing = true so that we don't fail on indexes,
1519  * owned sequences, etc when we happen to visit them
1520  * before their parent table.
1521  */
1522  ATExecChangeOwner(sdepForm->objid, newrole, true, AccessExclusiveLock);
1523  break;
1524 
1525  case DefaultAclRelationId:
1526 
1527  /*
1528  * Ignore default ACLs; they should be handled by DROP
1529  * OWNED, not REASSIGN OWNED.
1530  */
1531  break;
1532 
1533  case UserMappingRelationId:
1534  /* ditto */
1535  break;
1536 
1537  case ForeignServerRelationId:
1538  AlterForeignServerOwner_oid(sdepForm->objid, newrole);
1539  break;
1540 
1541  case ForeignDataWrapperRelationId:
1542  AlterForeignDataWrapperOwner_oid(sdepForm->objid, newrole);
1543  break;
1544 
1545  case EventTriggerRelationId:
1546  AlterEventTriggerOwner_oid(sdepForm->objid, newrole);
1547  break;
1548 
1549  case PublicationRelationId:
1550  AlterPublicationOwner_oid(sdepForm->objid, newrole);
1551  break;
1552 
1553  case SubscriptionRelationId:
1554  AlterSubscriptionOwner_oid(sdepForm->objid, newrole);
1555  break;
1556 
1557  /* Generic alter owner cases */
1558  case CollationRelationId:
1559  case ConversionRelationId:
1560  case OperatorRelationId:
1561  case ProcedureRelationId:
1562  case LanguageRelationId:
1563  case LargeObjectRelationId:
1564  case OperatorFamilyRelationId:
1565  case OperatorClassRelationId:
1566  case ExtensionRelationId:
1567  case StatisticExtRelationId:
1568  case TableSpaceRelationId:
1569  case DatabaseRelationId:
1570  case TSConfigRelationId:
1571  case TSDictionaryRelationId:
1572  {
1573  Oid classId = sdepForm->classid;
1574  Relation catalog;
1575 
1576  if (classId == LargeObjectRelationId)
1577  classId = LargeObjectMetadataRelationId;
1578 
1579  catalog = table_open(classId, RowExclusiveLock);
1580 
1581  AlterObjectOwner_internal(catalog, sdepForm->objid,
1582  newrole);
1583 
1584  table_close(catalog, NoLock);
1585  }
1586  break;
1587 
1588  default:
1589  elog(ERROR, "unexpected classid %u", sdepForm->classid);
1590  break;
1591  }
1592  /* Make sure the next iteration will see my changes */
1594  }
1595 
1596  systable_endscan(scan);
1597  }
1598 
1599  table_close(sdepRel, RowExclusiveLock);
1600 }
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
void AlterSchemaOwner_oid(Oid oid, Oid newOwnerId)
Definition: schemacmds.c:277
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
bool IsPinnedObject(Oid classId, Oid objectId)
Definition: catalog.c:307
#define ObjectIdGetDatum(X)
Definition: postgres.h:551
#define ERROR
Definition: elog.h:46
void AlterTypeOwner_oid(Oid typeOid, Oid newOwnerId, bool hasDependEntry)
Definition: typecmds.c:3785
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:13240
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 1226 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().

1231 {
1232  char *objdesc = getObjectDescription(object, false);
1233 
1234  /* separate entries with a newline */
1235  if (descs->len != 0)
1236  appendStringInfoChar(descs, '\n');
1237 
1238  switch (type)
1239  {
1240  case LOCAL_OBJECT:
1241  case SHARED_OBJECT:
1242  if (deptype == SHARED_DEPENDENCY_OWNER)
1243  appendStringInfo(descs, _("owner of %s"), objdesc);
1244  else if (deptype == SHARED_DEPENDENCY_ACL)
1245  appendStringInfo(descs, _("privileges for %s"), objdesc);
1246  else if (deptype == SHARED_DEPENDENCY_POLICY)
1247  appendStringInfo(descs, _("target of %s"), objdesc);
1248  else if (deptype == SHARED_DEPENDENCY_TABLESPACE)
1249  appendStringInfo(descs, _("tablespace for %s"), objdesc);
1250  else
1251  elog(ERROR, "unrecognized dependency type: %d",
1252  (int) deptype);
1253  break;
1254 
1255  case REMOTE_OBJECT:
1256  /* translator: %s will always be "database %s" */
1257  appendStringInfo(descs, ngettext("%d object in %s",
1258  "%d objects in %s",
1259  count),
1260  count, objdesc);
1261  break;
1262 
1263  default:
1264  elog(ERROR, "unrecognized object type: %d", type);
1265  }
1266 
1267  pfree(objdesc);
1268 }
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 480 of file pg_shdepend.c.

References getOidListDiff(), i, IsPinnedObject(), 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().

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