31
31
#include "catalog/pg_authid.h"
32
32
#include "catalog/pg_database.h"
33
33
#include "catalog/pg_db_role_setting.h"
34
+ #include "catalog/pg_largeobject.h"
34
35
#include "catalog/pg_namespace.h"
35
36
#include "catalog/pg_replication_origin.h"
36
37
#include "catalog/pg_shdepend.h"
120
121
IsCatalogRelationOid (Oid relid )
121
122
{
122
123
/*
123
- * We consider a relation to be a system catalog if it has an OID that was
124
- * manually assigned or assigned by genbki.pl. This includes all the
125
- * defined catalogs, their indexes, and their TOAST tables and indexes.
124
+ * We consider a relation to be a system catalog if it has a pinned OID.
125
+ * This includes all the defined catalogs, their indexes, and their TOAST
126
+ * tables and indexes.
126
127
*
127
128
* This rule excludes the relations in information_schema, which are not
128
129
* integral to the system and can be treated the same as user relations.
@@ -132,7 +133,7 @@ IsCatalogRelationOid(Oid relid)
132
133
* This test is reliable since an OID wraparound will skip this range of
133
134
* OIDs; see GetNewObjectId().
134
135
*/
135
- return (relid < (Oid ) FirstBootstrapObjectId );
136
+ return (relid < (Oid ) FirstUnpinnedObjectId );
136
137
}
137
138
138
139
/*
@@ -294,6 +295,64 @@ IsSharedRelation(Oid relationId)
294
295
return false;
295
296
}
296
297
298
+ /*
299
+ * IsPinnedObject
300
+ * Given the class + OID identity of a database object, report whether
301
+ * it is "pinned", that is not droppable because the system requires it.
302
+ *
303
+ * We used to represent this explicitly in pg_depend, but that proved to be
304
+ * an undesirable amount of overhead, so now we rely on an OID range test.
305
+ */
306
+ bool
307
+ IsPinnedObject (Oid classId , Oid objectId )
308
+ {
309
+ /*
310
+ * Objects with OIDs above FirstUnpinnedObjectId are never pinned. Since
311
+ * the OID generator skips this range when wrapping around, this check
312
+ * guarantees that user-defined objects are never considered pinned.
313
+ */
314
+ if (objectId >= FirstUnpinnedObjectId )
315
+ return false;
316
+
317
+ /*
318
+ * Large objects are never pinned. We need this special case because
319
+ * their OIDs can be user-assigned.
320
+ */
321
+ if (classId == LargeObjectRelationId )
322
+ return false;
323
+
324
+ /*
325
+ * There are a few objects defined in the catalog .dat files that, as a
326
+ * matter of policy, we prefer not to treat as pinned. We used to handle
327
+ * that by excluding them from pg_depend, but it's just as easy to
328
+ * hard-wire their OIDs here. (If the user does indeed drop and recreate
329
+ * them, they'll have new but certainly-unpinned OIDs, so no problem.)
330
+ *
331
+ * Checking both classId and objectId is overkill, since OIDs below
332
+ * FirstGenbkiObjectId should be globally unique, but do it anyway for
333
+ * robustness.
334
+ */
335
+
336
+ /* template1 is not pinned */
337
+ if (classId == DatabaseRelationId &&
338
+ objectId == TemplateDbOid )
339
+ return false;
340
+
341
+ /* the public namespace is not pinned */
342
+ if (classId == NamespaceRelationId &&
343
+ objectId == PG_PUBLIC_NAMESPACE )
344
+ return false;
345
+
346
+ /*
347
+ * All other initdb-created objects are pinned. This is overkill (the
348
+ * system doesn't really depend on having every last weird datatype, for
349
+ * instance) but generating only the minimum required set of dependencies
350
+ * seems hard, and enforcing an accurate list would be much more expensive
351
+ * than the simple range test used here.
352
+ */
353
+ return true;
354
+ }
355
+
297
356
298
357
/*
299
358
* GetNewOidWithIndex
@@ -533,7 +592,8 @@ pg_nextoid(PG_FUNCTION_ARGS)
533
592
if (!superuser ())
534
593
ereport (ERROR ,
535
594
(errcode (ERRCODE_INSUFFICIENT_PRIVILEGE ),
536
- errmsg ("must be superuser to call pg_nextoid()" )));
595
+ errmsg ("must be superuser to call %s()" ,
596
+ "pg_nextoid" )));
537
597
538
598
rel = table_open (reloid , RowExclusiveLock );
539
599
idx = index_open (idxoid , RowExclusiveLock );
@@ -580,5 +640,29 @@ pg_nextoid(PG_FUNCTION_ARGS)
580
640
table_close (rel , RowExclusiveLock );
581
641
index_close (idx , RowExclusiveLock );
582
642
583
- return newoid ;
643
+ PG_RETURN_OID (newoid );
644
+ }
645
+
646
+ /*
647
+ * SQL callable interface for StopGeneratingPinnedObjectIds().
648
+ *
649
+ * This is only to be used by initdb, so it's intentionally not documented in
650
+ * the user facing docs.
651
+ */
652
+ Datum
653
+ pg_stop_making_pinned_objects (PG_FUNCTION_ARGS )
654
+ {
655
+ /*
656
+ * Belt-and-suspenders check, since StopGeneratingPinnedObjectIds will
657
+ * fail anyway in non-single-user mode.
658
+ */
659
+ if (!superuser ())
660
+ ereport (ERROR ,
661
+ (errcode (ERRCODE_INSUFFICIENT_PRIVILEGE ),
662
+ errmsg ("must be superuser to call %s()" ,
663
+ "pg_stop_making_pinned_objects" )));
664
+
665
+ StopGeneratingPinnedObjectIds ();
666
+
667
+ PG_RETURN_VOID ();
584
668
}
0 commit comments