OSDN Git Service

Update copyright to 2004.
[pg-rex/syncrep.git] / src / backend / catalog / pg_depend.c
1 /*-------------------------------------------------------------------------
2  *
3  * pg_depend.c
4  *        routines to support manipulation of the pg_depend relation
5  *
6  * Portions Copyright (c) 1996-2004, PostgreSQL Global Development Group
7  * Portions Copyright (c) 1994, Regents of the University of California
8  *
9  *
10  * IDENTIFICATION
11  *        $PostgreSQL: pgsql/src/backend/catalog/pg_depend.c,v 1.11 2004/08/29 04:12:28 momjian Exp $
12  *
13  *-------------------------------------------------------------------------
14  */
15 #include "postgres.h"
16
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"
25
26
27 static bool isObjectPinned(const ObjectAddress *object, Relation rel);
28
29
30 /*
31  * Record a dependency between 2 objects via their respective objectAddress.
32  * The first argument is the dependent object, the second the one it
33  * references.
34  *
35  * This simply creates an entry in pg_depend, without any other processing.
36  */
37 void
38 recordDependencyOn(const ObjectAddress *depender,
39                                    const ObjectAddress *referenced,
40                                    DependencyType behavior)
41 {
42         recordMultipleDependencies(depender, referenced, 1, behavior);
43 }
44
45 /*
46  * Record multiple dependencies (of the same kind) for a single dependent
47  * object.      This has a little less overhead than recording each separately.
48  */
49 void
50 recordMultipleDependencies(const ObjectAddress *depender,
51                                                    const ObjectAddress *referenced,
52                                                    int nreferenced,
53                                                    DependencyType behavior)
54 {
55         Relation        dependDesc;
56         CatalogIndexState indstate;
57         HeapTuple       tup;
58         int                     i;
59         char            nulls[Natts_pg_depend];
60         Datum           values[Natts_pg_depend];
61
62         if (nreferenced <= 0)
63                 return;                                 /* nothing to do */
64
65         /*
66          * During bootstrap, do nothing since pg_depend may not exist yet.
67          * initdb will fill in appropriate pg_depend entries after bootstrap.
68          */
69         if (IsBootstrapProcessingMode())
70                 return;
71
72         dependDesc = heap_openr(DependRelationName, RowExclusiveLock);
73
74         /* Don't open indexes unless we need to make an update */
75         indstate = NULL;
76
77         memset(nulls, ' ', sizeof(nulls));
78
79         for (i = 0; i < nreferenced; i++, referenced++)
80         {
81                 /*
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.
85                  */
86                 if (!isObjectPinned(referenced, dependDesc))
87                 {
88                         /*
89                          * Record the Dependency.  Note we don't bother to check for
90                          * duplicate dependencies; there's no harm in them.
91                          */
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);
95
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);
99
100                         values[Anum_pg_depend_deptype - 1] = CharGetDatum((char) behavior);
101
102                         tup = heap_formtuple(dependDesc->rd_att, values, nulls);
103
104                         simple_heap_insert(dependDesc, tup);
105
106                         /* keep indexes current */
107                         if (indstate == NULL)
108                                 indstate = CatalogOpenIndexes(dependDesc);
109
110                         CatalogIndexInsert(indstate, tup);
111
112                         heap_freetuple(tup);
113                 }
114         }
115
116         if (indstate != NULL)
117                 CatalogCloseIndexes(indstate);
118
119         heap_close(dependDesc, RowExclusiveLock);
120 }
121
122 /*
123  * deleteDependencyRecordsFor -- delete all records with given depender
124  * classId/objectId.  Returns the number of records deleted.
125  *
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).
129  */
130 long
131 deleteDependencyRecordsFor(Oid classId, Oid objectId)
132 {
133         long            count = 0;
134         Relation        depRel;
135         ScanKeyData key[2];
136         SysScanDesc scan;
137         HeapTuple       tup;
138
139         depRel = heap_openr(DependRelationName, RowExclusiveLock);
140
141         ScanKeyInit(&key[0],
142                                 Anum_pg_depend_classid,
143                                 BTEqualStrategyNumber, F_OIDEQ,
144                                 ObjectIdGetDatum(classId));
145         ScanKeyInit(&key[1],
146                                 Anum_pg_depend_objid,
147                                 BTEqualStrategyNumber, F_OIDEQ,
148                                 ObjectIdGetDatum(objectId));
149
150         scan = systable_beginscan(depRel, DependDependerIndex, true,
151                                                           SnapshotNow, 2, key);
152
153         while (HeapTupleIsValid(tup = systable_getnext(scan)))
154         {
155                 simple_heap_delete(depRel, &tup->t_self);
156                 count++;
157         }
158
159         systable_endscan(scan);
160
161         heap_close(depRel, RowExclusiveLock);
162
163         return count;
164 }
165
166 /*
167  * isObjectPinned()
168  *
169  * Test if an object is required for basic database functionality.
170  * Caller must already have opened pg_depend.
171  *
172  * The passed subId, if any, is ignored; we assume that only whole objects
173  * are pinned (and that this implies pinning their components).
174  */
175 static bool
176 isObjectPinned(const ObjectAddress *object, Relation rel)
177 {
178         bool            ret = false;
179         SysScanDesc scan;
180         HeapTuple       tup;
181         ScanKeyData key[2];
182
183         ScanKeyInit(&key[0],
184                                 Anum_pg_depend_refclassid,
185                                 BTEqualStrategyNumber, F_OIDEQ,
186                                 ObjectIdGetDatum(object->classId));
187
188         ScanKeyInit(&key[1],
189                                 Anum_pg_depend_refobjid,
190                                 BTEqualStrategyNumber, F_OIDEQ,
191                                 ObjectIdGetDatum(object->objectId));
192
193         scan = systable_beginscan(rel, DependReferenceIndex, true,
194                                                           SnapshotNow, 2, key);
195
196         /*
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.
201          */
202         tup = systable_getnext(scan);
203         if (HeapTupleIsValid(tup))
204         {
205                 Form_pg_depend foundDep = (Form_pg_depend) GETSTRUCT(tup);
206
207                 if (foundDep->deptype == DEPENDENCY_PIN)
208                         ret = true;
209         }
210
211         systable_endscan(scan);
212
213         return ret;
214 }