]> granicus.if.org Git - postgresql/blob - src/backend/catalog/catalog.c
Fix recently-understood problems with handling of XID freezing, particularly
[postgresql] / src / backend / catalog / catalog.c
1 /*-------------------------------------------------------------------------
2  *
3  * catalog.c
4  *              routines concerned with catalog naming conventions and other
5  *              bits of hard-wired knowledge
6  *
7  *
8  * Portions Copyright (c) 1996-2006, PostgreSQL Global Development Group
9  * Portions Copyright (c) 1994, Regents of the University of California
10  *
11  *
12  * IDENTIFICATION
13  *        $PostgreSQL: pgsql/src/backend/catalog/catalog.c,v 1.68 2006/10/04 00:29:50 momjian Exp $
14  *
15  *-------------------------------------------------------------------------
16  */
17
18 #include "postgres.h"
19
20 #include <fcntl.h>
21 #include <unistd.h>
22
23 #include "access/genam.h"
24 #include "access/transam.h"
25 #include "catalog/catalog.h"
26 #include "catalog/indexing.h"
27 #include "catalog/pg_auth_members.h"
28 #include "catalog/pg_authid.h"
29 #include "catalog/pg_database.h"
30 #include "catalog/pg_namespace.h"
31 #include "catalog/pg_pltemplate.h"
32 #include "catalog/pg_shdepend.h"
33 #include "catalog/pg_shdescription.h"
34 #include "catalog/pg_tablespace.h"
35 #include "catalog/toasting.h"
36 #include "miscadmin.h"
37 #include "storage/fd.h"
38 #include "utils/fmgroids.h"
39 #include "utils/relcache.h"
40
41
42 #define OIDCHARS        10                      /* max chars printed by %u */
43
44
45 /*
46  * relpath                      - construct path to a relation's file
47  *
48  * Result is a palloc'd string.
49  */
50 char *
51 relpath(RelFileNode rnode)
52 {
53         int                     pathlen;
54         char       *path;
55
56         if (rnode.spcNode == GLOBALTABLESPACE_OID)
57         {
58                 /* Shared system relations live in {datadir}/global */
59                 Assert(rnode.dbNode == 0);
60                 pathlen = 7 + OIDCHARS + 1;
61                 path = (char *) palloc(pathlen);
62                 snprintf(path, pathlen, "global/%u",
63                                  rnode.relNode);
64         }
65         else if (rnode.spcNode == DEFAULTTABLESPACE_OID)
66         {
67                 /* The default tablespace is {datadir}/base */
68                 pathlen = 5 + OIDCHARS + 1 + OIDCHARS + 1;
69                 path = (char *) palloc(pathlen);
70                 snprintf(path, pathlen, "base/%u/%u",
71                                  rnode.dbNode, rnode.relNode);
72         }
73         else
74         {
75                 /* All other tablespaces are accessed via symlinks */
76                 pathlen = 10 + OIDCHARS + 1 + OIDCHARS + 1 + OIDCHARS + 1;
77                 path = (char *) palloc(pathlen);
78                 snprintf(path, pathlen, "pg_tblspc/%u/%u/%u",
79                                  rnode.spcNode, rnode.dbNode, rnode.relNode);
80         }
81         return path;
82 }
83
84 /*
85  * GetDatabasePath                      - construct path to a database dir
86  *
87  * Result is a palloc'd string.
88  *
89  * XXX this must agree with relpath()!
90  */
91 char *
92 GetDatabasePath(Oid dbNode, Oid spcNode)
93 {
94         int                     pathlen;
95         char       *path;
96
97         if (spcNode == GLOBALTABLESPACE_OID)
98         {
99                 /* Shared system relations live in {datadir}/global */
100                 Assert(dbNode == 0);
101                 pathlen = 6 + 1;
102                 path = (char *) palloc(pathlen);
103                 snprintf(path, pathlen, "global");
104         }
105         else if (spcNode == DEFAULTTABLESPACE_OID)
106         {
107                 /* The default tablespace is {datadir}/base */
108                 pathlen = 5 + OIDCHARS + 1;
109                 path = (char *) palloc(pathlen);
110                 snprintf(path, pathlen, "base/%u",
111                                  dbNode);
112         }
113         else
114         {
115                 /* All other tablespaces are accessed via symlinks */
116                 pathlen = 10 + OIDCHARS + 1 + OIDCHARS + 1;
117                 path = (char *) palloc(pathlen);
118                 snprintf(path, pathlen, "pg_tblspc/%u/%u",
119                                  spcNode, dbNode);
120         }
121         return path;
122 }
123
124
125 /*
126  * IsSystemRelation
127  *              True iff the relation is a system catalog relation.
128  *
129  *              NB: TOAST relations are considered system relations by this test
130  *              for compatibility with the old IsSystemRelationName function.
131  *              This is appropriate in many places but not all.  Where it's not,
132  *              also check IsToastRelation.
133  *
134  *              We now just test if the relation is in the system catalog namespace;
135  *              so it's no longer necessary to forbid user relations from having
136  *              names starting with pg_.
137  */
138 bool
139 IsSystemRelation(Relation relation)
140 {
141         return IsSystemNamespace(RelationGetNamespace(relation)) ||
142                 IsToastNamespace(RelationGetNamespace(relation));
143 }
144
145 /*
146  * IsSystemClass
147  *              Like the above, but takes a Form_pg_class as argument.
148  *              Used when we do not want to open the relation and have to
149  *              search pg_class directly.
150  */
151 bool
152 IsSystemClass(Form_pg_class reltuple)
153 {
154         Oid                     relnamespace = reltuple->relnamespace;
155
156         return IsSystemNamespace(relnamespace) ||
157                 IsToastNamespace(relnamespace);
158 }
159
160 /*
161  * IsToastRelation
162  *              True iff relation is a TOAST support relation (or index).
163  */
164 bool
165 IsToastRelation(Relation relation)
166 {
167         return IsToastNamespace(RelationGetNamespace(relation));
168 }
169
170 /*
171  * IsToastClass
172  *              Like the above, but takes a Form_pg_class as argument.
173  *              Used when we do not want to open the relation and have to
174  *              search pg_class directly.
175  */
176 bool
177 IsToastClass(Form_pg_class reltuple)
178 {
179         Oid                     relnamespace = reltuple->relnamespace;
180
181         return IsToastNamespace(relnamespace);
182 }
183
184 /*
185  * IsSystemNamespace
186  *              True iff namespace is pg_catalog.
187  *
188  * NOTE: the reason this isn't a macro is to avoid having to include
189  * catalog/pg_namespace.h in a lot of places.
190  */
191 bool
192 IsSystemNamespace(Oid namespaceId)
193 {
194         return namespaceId == PG_CATALOG_NAMESPACE;
195 }
196
197 /*
198  * IsToastNamespace
199  *              True iff namespace is pg_toast.
200  *
201  * NOTE: the reason this isn't a macro is to avoid having to include
202  * catalog/pg_namespace.h in a lot of places.
203  */
204 bool
205 IsToastNamespace(Oid namespaceId)
206 {
207         return namespaceId == PG_TOAST_NAMESPACE;
208 }
209
210
211 /*
212  * IsReservedName
213  *              True iff name starts with the pg_ prefix.
214  *
215  *              For some classes of objects, the prefix pg_ is reserved for
216  *              system objects only.  As of 8.0, this is only true for
217  *              schema and tablespace names.
218  */
219 bool
220 IsReservedName(const char *name)
221 {
222         /* ugly coding for speed */
223         return (name[0] == 'p' &&
224                         name[1] == 'g' &&
225                         name[2] == '_');
226 }
227
228
229 /*
230  * IsSharedRelation
231  *              Given the OID of a relation, determine whether it's supposed to be
232  *              shared across an entire database cluster.
233  *
234  * Hard-wiring this list is pretty grotty, but we really need it so that
235  * we can compute the locktag for a relation (and then lock it) without
236  * having already read its pg_class entry.      If we try to retrieve relisshared
237  * from pg_class with no pre-existing lock, there is a race condition against
238  * anyone who is concurrently committing a change to the pg_class entry:
239  * since we read system catalog entries under SnapshotNow, it's possible
240  * that both the old and new versions of the row are invalid at the instants
241  * we scan them.  We fix this by insisting that updaters of a pg_class
242  * row must hold exclusive lock on the corresponding rel, and that users
243  * of a relation must hold at least AccessShareLock on the rel *before*
244  * trying to open its relcache entry.  But to lock a rel, you have to
245  * know if it's shared.  Fortunately, the set of shared relations is
246  * fairly static, so a hand-maintained list of their OIDs isn't completely
247  * impractical.
248  */
249 bool
250 IsSharedRelation(Oid relationId)
251 {
252         /* These are the shared catalogs (look for BKI_SHARED_RELATION) */
253         if (relationId == AuthIdRelationId ||
254                 relationId == AuthMemRelationId ||
255                 relationId == DatabaseRelationId ||
256                 relationId == PLTemplateRelationId ||
257                 relationId == SharedDescriptionRelationId ||
258                 relationId == SharedDependRelationId ||
259                 relationId == TableSpaceRelationId)
260                 return true;
261         /* These are their indexes (see indexing.h) */
262         if (relationId == AuthIdRolnameIndexId ||
263                 relationId == AuthIdOidIndexId ||
264                 relationId == AuthMemRoleMemIndexId ||
265                 relationId == AuthMemMemRoleIndexId ||
266                 relationId == DatabaseNameIndexId ||
267                 relationId == DatabaseOidIndexId ||
268                 relationId == PLTemplateNameIndexId ||
269                 relationId == SharedDescriptionObjIndexId ||
270                 relationId == SharedDependDependerIndexId ||
271                 relationId == SharedDependReferenceIndexId ||
272                 relationId == TablespaceOidIndexId ||
273                 relationId == TablespaceNameIndexId)
274                 return true;
275         /* These are their toast tables and toast indexes (see toasting.h) */
276         if (relationId == PgAuthidToastTable ||
277                 relationId == PgAuthidToastIndex ||
278                 relationId == PgDatabaseToastTable ||
279                 relationId == PgDatabaseToastIndex ||
280                 relationId == PgShdescriptionToastTable ||
281                 relationId == PgShdescriptionToastIndex)
282                 return true;
283         return false;
284 }
285
286
287 /*
288  * GetNewOid
289  *              Generate a new OID that is unique within the given relation.
290  *
291  * Caller must have a suitable lock on the relation.
292  *
293  * Uniqueness is promised only if the relation has a unique index on OID.
294  * This is true for all system catalogs that have OIDs, but might not be
295  * true for user tables.  Note that we are effectively assuming that the
296  * table has a relatively small number of entries (much less than 2^32)
297  * and there aren't very long runs of consecutive existing OIDs.  Again,
298  * this is reasonable for system catalogs but less so for user tables.
299  *
300  * Since the OID is not immediately inserted into the table, there is a
301  * race condition here; but a problem could occur only if someone else
302  * managed to cycle through 2^32 OIDs and generate the same OID before we
303  * finish inserting our row.  This seems unlikely to be a problem.      Note
304  * that if we had to *commit* the row to end the race condition, the risk
305  * would be rather higher; therefore we use SnapshotDirty in the test,
306  * so that we will see uncommitted rows.
307  */
308 Oid
309 GetNewOid(Relation relation)
310 {
311         Oid                     newOid;
312         Oid                     oidIndex;
313         Relation        indexrel;
314
315         /* If relation doesn't have OIDs at all, caller is confused */
316         Assert(relation->rd_rel->relhasoids);
317
318         /* In bootstrap mode, we don't have any indexes to use */
319         if (IsBootstrapProcessingMode())
320                 return GetNewObjectId();
321
322         /* The relcache will cache the identity of the OID index for us */
323         oidIndex = RelationGetOidIndex(relation);
324
325         /* If no OID index, just hand back the next OID counter value */
326         if (!OidIsValid(oidIndex))
327         {
328                 /*
329                  * System catalogs that have OIDs should *always* have a unique OID
330                  * index; we should only take this path for user tables. Give a
331                  * warning if it looks like somebody forgot an index.
332                  */
333                 if (IsSystemRelation(relation))
334                         elog(WARNING, "generating possibly-non-unique OID for \"%s\"",
335                                  RelationGetRelationName(relation));
336
337                 return GetNewObjectId();
338         }
339
340         /* Otherwise, use the index to find a nonconflicting OID */
341         indexrel = index_open(oidIndex, AccessShareLock);
342         newOid = GetNewOidWithIndex(relation, indexrel);
343         index_close(indexrel, AccessShareLock);
344
345         return newOid;
346 }
347
348 /*
349  * GetNewOidWithIndex
350  *              Guts of GetNewOid: use the supplied index
351  *
352  * This is exported separately because there are cases where we want to use
353  * an index that will not be recognized by RelationGetOidIndex: TOAST tables
354  * and pg_largeobject have indexes that are usable, but have multiple columns
355  * and are on ordinary columns rather than a true OID column.  This code
356  * will work anyway, so long as the OID is the index's first column.
357  *
358  * Caller must have a suitable lock on the relation.
359  */
360 Oid
361 GetNewOidWithIndex(Relation relation, Relation indexrel)
362 {
363         Oid                     newOid;
364         IndexScanDesc scan;
365         ScanKeyData key;
366         bool            collides;
367
368         /* Generate new OIDs until we find one not in the table */
369         do
370         {
371                 newOid = GetNewObjectId();
372
373                 ScanKeyInit(&key,
374                                         (AttrNumber) 1,
375                                         BTEqualStrategyNumber, F_OIDEQ,
376                                         ObjectIdGetDatum(newOid));
377
378                 /* see notes above about using SnapshotDirty */
379                 scan = index_beginscan(relation, indexrel,
380                                                            SnapshotDirty, 1, &key);
381
382                 collides = HeapTupleIsValid(index_getnext(scan, ForwardScanDirection));
383
384                 index_endscan(scan);
385         } while (collides);
386
387         return newOid;
388 }
389
390 /*
391  * GetNewRelFileNode
392  *              Generate a new relfilenode number that is unique within the given
393  *              tablespace.
394  *
395  * If the relfilenode will also be used as the relation's OID, pass the
396  * opened pg_class catalog, and this routine will guarantee that the result
397  * is also an unused OID within pg_class.  If the result is to be used only
398  * as a relfilenode for an existing relation, pass NULL for pg_class.
399  *
400  * As with GetNewOid, there is some theoretical risk of a race condition,
401  * but it doesn't seem worth worrying about.
402  *
403  * Note: we don't support using this in bootstrap mode.  All relations
404  * created by bootstrap have preassigned OIDs, so there's no need.
405  */
406 Oid
407 GetNewRelFileNode(Oid reltablespace, bool relisshared, Relation pg_class)
408 {
409         RelFileNode rnode;
410         char       *rpath;
411         int                     fd;
412         bool            collides;
413
414         /* This should match RelationInitPhysicalAddr */
415         rnode.spcNode = reltablespace ? reltablespace : MyDatabaseTableSpace;
416         rnode.dbNode = relisshared ? InvalidOid : MyDatabaseId;
417
418         do
419         {
420                 /* Generate the OID */
421                 if (pg_class)
422                         rnode.relNode = GetNewOid(pg_class);
423                 else
424                         rnode.relNode = GetNewObjectId();
425
426                 /* Check for existing file of same name */
427                 rpath = relpath(rnode);
428                 fd = BasicOpenFile(rpath, O_RDONLY | PG_BINARY, 0);
429
430                 if (fd >= 0)
431                 {
432                         /* definite collision */
433                         close(fd);
434                         collides = true;
435                 }
436                 else
437                 {
438                         /*
439                          * Here we have a little bit of a dilemma: if errno is something
440                          * other than ENOENT, should we declare a collision and loop? In
441                          * particular one might think this advisable for, say, EPERM.
442                          * However there really shouldn't be any unreadable files in a
443                          * tablespace directory, and if the EPERM is actually complaining
444                          * that we can't read the directory itself, we'd be in an infinite
445                          * loop.  In practice it seems best to go ahead regardless of the
446                          * errno.  If there is a colliding file we will get an smgr
447                          * failure when we attempt to create the new relation file.
448                          */
449                         collides = false;
450                 }
451
452                 pfree(rpath);
453         } while (collides);
454
455         return rnode.relNode;
456 }