1 /*-------------------------------------------------------------------------
4 * routines to support manipulation of the pg_depend relation
6 * Portions Copyright (c) 1996-2004, PostgreSQL Global Development Group
7 * Portions Copyright (c) 1994, Regents of the University of California
11 * $PostgreSQL: pgsql/src/backend/catalog/pg_depend.c,v 1.11 2004/08/29 04:12:28 momjian Exp $
13 *-------------------------------------------------------------------------
17 #include "access/genam.h"
18 #include "access/heapam.h"
19 #include "catalog/catname.h"
20 #include "catalog/indexing.h"
21 #include "catalog/dependency.h"
22 #include "catalog/pg_depend.h"
23 #include "miscadmin.h"
24 #include "utils/fmgroids.h"
27 static bool isObjectPinned(const ObjectAddress *object, Relation rel);
31 * Record a dependency between 2 objects via their respective objectAddress.
32 * The first argument is the dependent object, the second the one it
35 * This simply creates an entry in pg_depend, without any other processing.
38 recordDependencyOn(const ObjectAddress *depender,
39 const ObjectAddress *referenced,
40 DependencyType behavior)
42 recordMultipleDependencies(depender, referenced, 1, behavior);
46 * Record multiple dependencies (of the same kind) for a single dependent
47 * object. This has a little less overhead than recording each separately.
50 recordMultipleDependencies(const ObjectAddress *depender,
51 const ObjectAddress *referenced,
53 DependencyType behavior)
56 CatalogIndexState indstate;
59 char nulls[Natts_pg_depend];
60 Datum values[Natts_pg_depend];
63 return; /* nothing to do */
66 * During bootstrap, do nothing since pg_depend may not exist yet.
67 * initdb will fill in appropriate pg_depend entries after bootstrap.
69 if (IsBootstrapProcessingMode())
72 dependDesc = heap_openr(DependRelationName, RowExclusiveLock);
74 /* Don't open indexes unless we need to make an update */
77 memset(nulls, ' ', sizeof(nulls));
79 for (i = 0; i < nreferenced; i++, referenced++)
82 * If the referenced object is pinned by the system, there's no
83 * real need to record dependencies on it. This saves lots of
84 * space in pg_depend, so it's worth the time taken to check.
86 if (!isObjectPinned(referenced, dependDesc))
89 * Record the Dependency. Note we don't bother to check for
90 * duplicate dependencies; there's no harm in them.
92 values[Anum_pg_depend_classid - 1] = ObjectIdGetDatum(depender->classId);
93 values[Anum_pg_depend_objid - 1] = ObjectIdGetDatum(depender->objectId);
94 values[Anum_pg_depend_objsubid - 1] = Int32GetDatum(depender->objectSubId);
96 values[Anum_pg_depend_refclassid - 1] = ObjectIdGetDatum(referenced->classId);
97 values[Anum_pg_depend_refobjid - 1] = ObjectIdGetDatum(referenced->objectId);
98 values[Anum_pg_depend_refobjsubid - 1] = Int32GetDatum(referenced->objectSubId);
100 values[Anum_pg_depend_deptype - 1] = CharGetDatum((char) behavior);
102 tup = heap_formtuple(dependDesc->rd_att, values, nulls);
104 simple_heap_insert(dependDesc, tup);
106 /* keep indexes current */
107 if (indstate == NULL)
108 indstate = CatalogOpenIndexes(dependDesc);
110 CatalogIndexInsert(indstate, tup);
116 if (indstate != NULL)
117 CatalogCloseIndexes(indstate);
119 heap_close(dependDesc, RowExclusiveLock);
123 * deleteDependencyRecordsFor -- delete all records with given depender
124 * classId/objectId. Returns the number of records deleted.
126 * This is used when redefining an existing object. Links leading to the
127 * object do not change, and links leading from it will be recreated
128 * (possibly with some differences from before).
131 deleteDependencyRecordsFor(Oid classId, Oid objectId)
139 depRel = heap_openr(DependRelationName, RowExclusiveLock);
142 Anum_pg_depend_classid,
143 BTEqualStrategyNumber, F_OIDEQ,
144 ObjectIdGetDatum(classId));
146 Anum_pg_depend_objid,
147 BTEqualStrategyNumber, F_OIDEQ,
148 ObjectIdGetDatum(objectId));
150 scan = systable_beginscan(depRel, DependDependerIndex, true,
151 SnapshotNow, 2, key);
153 while (HeapTupleIsValid(tup = systable_getnext(scan)))
155 simple_heap_delete(depRel, &tup->t_self);
159 systable_endscan(scan);
161 heap_close(depRel, RowExclusiveLock);
169 * Test if an object is required for basic database functionality.
170 * Caller must already have opened pg_depend.
172 * The passed subId, if any, is ignored; we assume that only whole objects
173 * are pinned (and that this implies pinning their components).
176 isObjectPinned(const ObjectAddress *object, Relation rel)
184 Anum_pg_depend_refclassid,
185 BTEqualStrategyNumber, F_OIDEQ,
186 ObjectIdGetDatum(object->classId));
189 Anum_pg_depend_refobjid,
190 BTEqualStrategyNumber, F_OIDEQ,
191 ObjectIdGetDatum(object->objectId));
193 scan = systable_beginscan(rel, DependReferenceIndex, true,
194 SnapshotNow, 2, key);
197 * Since we won't generate additional pg_depend entries for pinned
198 * objects, there can be at most one entry referencing a pinned
199 * object. Hence, it's sufficient to look at the first returned
200 * tuple; we don't need to loop.
202 tup = systable_getnext(scan);
203 if (HeapTupleIsValid(tup))
205 Form_pg_depend foundDep = (Form_pg_depend) GETSTRUCT(tup);
207 if (foundDep->deptype == DEPENDENCY_PIN)
211 systable_endscan(scan);