diff --git a/doc/src/sgml/ddl.sgml b/doc/src/sgml/ddl.sgml index 3c53973b762..abe3b582016 100644 --- a/doc/src/sgml/ddl.sgml +++ b/doc/src/sgml/ddl.sgml @@ -1,4 +1,4 @@ - + Data Definition @@ -871,7 +871,7 @@ CREATE TABLE order_items ( The object identifier (object ID) of a row. This column is only present if the table was created using WITH OIDS, or if the - configuration variable was enabled. This column is of type + configuration variable was set. This column is of type oid (same name as the column); see for more information about the type. @@ -992,7 +992,13 @@ CREATE TABLE order_items ( A unique constraint should be created on the OID column of each - table for which the OID will be used to identify rows. + table for which the OID will be used to identify rows. When such + a unique constraint (or unique index) exists, the system takes + care not to generate an OID matching an already-existing row. + (Of course, this is only possible if the table contains fewer + than 232 (4 billion) rows, and in practice the + table size had better be much less than that, or performance + may suffer.) @@ -1005,9 +1011,8 @@ CREATE TABLE order_items ( The tables in question should be created using WITH - OIDS to ensure forward compatibility with future - releases of PostgreSQL. It is - planned that WITHOUT OIDS will become the default. + OIDS. As of PostgreSQL 8.1, + WITHOUT OIDS is the default. diff --git a/src/backend/access/heap/heapam.c b/src/backend/access/heap/heapam.c index c5851765f25..6e70ab25c10 100644 --- a/src/backend/access/heap/heapam.c +++ b/src/backend/access/heap/heapam.c @@ -8,7 +8,7 @@ * * * IDENTIFICATION - * $PostgreSQL: pgsql/src/backend/access/heap/heapam.c,v 1.196 2005/08/01 20:31:05 tgl Exp $ + * $PostgreSQL: pgsql/src/backend/access/heap/heapam.c,v 1.197 2005/08/12 01:35:54 tgl Exp $ * * * INTERFACE ROUTINES @@ -1069,9 +1069,7 @@ heap_insert(Relation relation, HeapTuple tup, CommandId cid, * pointers to one another). */ if (!OidIsValid(HeapTupleGetOid(tup))) - HeapTupleSetOid(tup, newoid()); - else - CheckMaxObjectId(HeapTupleGetOid(tup)); + HeapTupleSetOid(tup, GetNewOid(relation)); } else { diff --git a/src/backend/access/heap/tuptoaster.c b/src/backend/access/heap/tuptoaster.c index 5359f24fce2..02da8446cd0 100644 --- a/src/backend/access/heap/tuptoaster.c +++ b/src/backend/access/heap/tuptoaster.c @@ -8,7 +8,7 @@ * * * IDENTIFICATION - * $PostgreSQL: pgsql/src/backend/access/heap/tuptoaster.c,v 1.51 2005/08/02 16:11:57 tgl Exp $ + * $PostgreSQL: pgsql/src/backend/access/heap/tuptoaster.c,v 1.52 2005/08/12 01:35:54 tgl Exp $ * * * INTERFACE ROUTINES @@ -1006,6 +1006,15 @@ toast_save_datum(Relation rel, Datum value) char *data_p; int32 data_todo; + /* + * Open the toast relation and its index. We can use the index to + * check uniqueness of the OID we assign to the toasted item, even + * though it has additional columns besides OID. + */ + toastrel = heap_open(rel->rd_rel->reltoastrelid, RowExclusiveLock); + toasttupDesc = toastrel->rd_att; + toastidx = index_open(toastrel->rd_rel->reltoastidxid); + /* * Create the varattrib reference */ @@ -1023,7 +1032,8 @@ toast_save_datum(Relation rel, Datum value) result->va_content.va_external.va_extsize = VARATT_SIZE(value) - VARHDRSZ; - result->va_content.va_external.va_valueid = newoid(); + result->va_content.va_external.va_valueid = + GetNewOidWithIndex(toastrel, toastidx); result->va_content.va_external.va_toastrelid = rel->rd_rel->reltoastrelid; @@ -1043,12 +1053,9 @@ toast_save_datum(Relation rel, Datum value) data_todo = VARATT_SIZE(value) - VARHDRSZ; /* - * Open the toast relation. We must explicitly lock the toast index - * because we aren't using an index scan here. + * We must explicitly lock the toast index because we aren't using an + * index scan here. */ - toastrel = heap_open(rel->rd_rel->reltoastrelid, RowExclusiveLock); - toasttupDesc = toastrel->rd_att; - toastidx = index_open(toastrel->rd_rel->reltoastidxid); LockRelation(toastidx, RowExclusiveLock); /* diff --git a/src/backend/access/transam/varsup.c b/src/backend/access/transam/varsup.c index 5c51e69253e..9edb028a1cc 100644 --- a/src/backend/access/transam/varsup.c +++ b/src/backend/access/transam/varsup.c @@ -6,7 +6,7 @@ * Copyright (c) 2000-2005, PostgreSQL Global Development Group * * IDENTIFICATION - * $PostgreSQL: pgsql/src/backend/access/transam/varsup.c,v 1.64 2005/05/19 21:35:45 tgl Exp $ + * $PostgreSQL: pgsql/src/backend/access/transam/varsup.c,v 1.65 2005/08/12 01:35:55 tgl Exp $ * *------------------------------------------------------------------------- */ @@ -247,13 +247,16 @@ SetTransactionIdLimit(TransactionId oldest_datfrozenxid, } -/* ---------------------------------------------------------------- - * object id generation support - * ---------------------------------------------------------------- +/* + * GetNewObjectId -- allocate a new OID + * + * OIDs are generated by a cluster-wide counter. Since they are only 32 bits + * wide, counter wraparound will occur eventually, and therefore it is unwise + * to assume they are unique unless precautions are taken to make them so. + * Hence, this routine should generally not be used directly. The only + * direct callers should be GetNewOid() and GetNewRelFileNode() in + * catalog/catalog.c. */ - -static Oid lastSeenOid = InvalidOid; - Oid GetNewObjectId(void) { @@ -265,8 +268,9 @@ GetNewObjectId(void) * Check for wraparound of the OID counter. We *must* not return 0 * (InvalidOid); and as long as we have to check that, it seems a good * idea to skip over everything below FirstNormalObjectId too. (This - * basically just reduces the odds of OID collision right after a wrap - * occurs.) Note we are relying on unsigned comparison here. + * basically just avoids lots of collisions with bootstrap-assigned OIDs + * right after a wrap occurs, so as to avoid a possibly large number of + * iterations in GetNewOid.) Note we are relying on unsigned comparison. * * During initdb, we start the OID generator at FirstBootstrapObjectId, * so we only enforce wrapping to that point when in bootstrap or @@ -310,46 +314,5 @@ GetNewObjectId(void) LWLockRelease(OidGenLock); - lastSeenOid = result; - return result; } - -void -CheckMaxObjectId(Oid assigned_oid) -{ - if (lastSeenOid != InvalidOid && assigned_oid < lastSeenOid) - return; - - LWLockAcquire(OidGenLock, LW_EXCLUSIVE); - - if (assigned_oid < ShmemVariableCache->nextOid) - { - lastSeenOid = ShmemVariableCache->nextOid - 1; - LWLockRelease(OidGenLock); - return; - } - - /* If we are in the logged oid range, just bump nextOid up */ - if (assigned_oid <= ShmemVariableCache->nextOid + - ShmemVariableCache->oidCount - 1) - { - ShmemVariableCache->oidCount -= - assigned_oid - ShmemVariableCache->nextOid + 1; - ShmemVariableCache->nextOid = assigned_oid + 1; - LWLockRelease(OidGenLock); - return; - } - - /* - * We have exceeded the logged oid range. We should lock the database - * and kill all other backends but we are loading oid's that we can - * not guarantee are unique anyway, so we must rely on the user. - */ - - XLogPutNextOid(assigned_oid + VAR_OID_PREFETCH); - ShmemVariableCache->nextOid = assigned_oid + 1; - ShmemVariableCache->oidCount = VAR_OID_PREFETCH - 1; - - LWLockRelease(OidGenLock); -} diff --git a/src/backend/catalog/catalog.c b/src/backend/catalog/catalog.c index 480fbc05628..0648b578e9f 100644 --- a/src/backend/catalog/catalog.c +++ b/src/backend/catalog/catalog.c @@ -9,18 +9,25 @@ * * * IDENTIFICATION - * $PostgreSQL: pgsql/src/backend/catalog/catalog.c,v 1.62 2005/07/04 04:51:45 tgl Exp $ + * $PostgreSQL: pgsql/src/backend/catalog/catalog.c,v 1.63 2005/08/12 01:35:56 tgl Exp $ * *------------------------------------------------------------------------- */ #include "postgres.h" +#include +#include + +#include "access/genam.h" #include "access/transam.h" #include "catalog/catalog.h" #include "catalog/pg_namespace.h" #include "catalog/pg_tablespace.h" #include "miscadmin.h" +#include "storage/fd.h" +#include "utils/fmgroids.h" +#include "utils/relcache.h" #define OIDCHARS 10 /* max chars printed by %u */ @@ -211,16 +218,171 @@ IsReservedName(const char *name) /* - * newoid - returns a unique identifier across all catalogs. + * GetNewOid + * Generate a new OID that is unique within the given relation. * - * Object Id allocation is now done by GetNewObjectID in - * access/transam/varsup. + * Caller must have a suitable lock on the relation. * - * This code probably needs to change to generate OIDs separately - * for each table. + * Uniqueness is promised only if the relation has a unique index on OID. + * This is true for all system catalogs that have OIDs, but might not be + * true for user tables. Note that we are effectively assuming that the + * table has a relatively small number of entries (much less than 2^32) + * and there aren't very long runs of consecutive existing OIDs. Again, + * this is reasonable for system catalogs but less so for user tables. + * + * Since the OID is not immediately inserted into the table, there is a + * race condition here; but a problem could occur only if someone else + * managed to cycle through 2^32 OIDs and generate the same OID before we + * finish inserting our row. This seems unlikely to be a problem. Note + * that if we had to *commit* the row to end the race condition, the risk + * would be rather higher; therefore we use SnapshotDirty in the test, + * so that we will see uncommitted rows. */ Oid -newoid(void) +GetNewOid(Relation relation) { - return GetNewObjectId(); + Oid newOid; + Oid oidIndex; + Relation indexrel; + + /* If relation doesn't have OIDs at all, caller is confused */ + Assert(relation->rd_rel->relhasoids); + + /* In bootstrap mode, we don't have any indexes to use */ + if (IsBootstrapProcessingMode()) + return GetNewObjectId(); + + /* The relcache will cache the identity of the OID index for us */ + oidIndex = RelationGetOidIndex(relation); + + /* If no OID index, just hand back the next OID counter value */ + if (!OidIsValid(oidIndex)) + { + /* + * System catalogs that have OIDs should *always* have a unique + * OID index; we should only take this path for user tables. + * Give a warning if it looks like somebody forgot an index. + */ + if (IsSystemRelation(relation)) + elog(WARNING, "generating possibly-non-unique OID for \"%s\"", + RelationGetRelationName(relation)); + + return GetNewObjectId(); + } + + /* Otherwise, use the index to find a nonconflicting OID */ + indexrel = index_open(oidIndex); + newOid = GetNewOidWithIndex(relation, indexrel); + index_close(indexrel); + + return newOid; +} + +/* + * GetNewOidWithIndex + * Guts of GetNewOid: use the supplied index + * + * This is exported separately because there are cases where we want to use + * an index that will not be recognized by RelationGetOidIndex: TOAST tables + * and pg_largeobject have indexes that are usable, but have multiple columns + * and are on ordinary columns rather than a true OID column. This code + * will work anyway, so long as the OID is the index's first column. + * + * Caller must have a suitable lock on the relation. + */ +Oid +GetNewOidWithIndex(Relation relation, Relation indexrel) +{ + Oid newOid; + IndexScanDesc scan; + ScanKeyData key; + bool collides; + + /* Generate new OIDs until we find one not in the table */ + do + { + newOid = GetNewObjectId(); + + ScanKeyInit(&key, + (AttrNumber) 1, + BTEqualStrategyNumber, F_OIDEQ, + ObjectIdGetDatum(newOid)); + + /* see notes above about using SnapshotDirty */ + scan = index_beginscan(relation, indexrel, SnapshotDirty, 1, &key); + + collides = HeapTupleIsValid(index_getnext(scan, ForwardScanDirection)); + + index_endscan(scan); + } while (collides); + + return newOid; +} + +/* + * GetNewRelFileNode + * Generate a new relfilenode number that is unique within the given + * tablespace. + * + * If the relfilenode will also be used as the relation's OID, pass the + * opened pg_class catalog, and this routine will guarantee that the result + * is also an unused OID within pg_class. If the result is to be used only + * as a relfilenode for an existing relation, pass NULL for pg_class. + * + * As with GetNewOid, there is some theoretical risk of a race condition, + * but it doesn't seem worth worrying about. + * + * Note: we don't support using this in bootstrap mode. All relations + * created by bootstrap have preassigned OIDs, so there's no need. + */ +Oid +GetNewRelFileNode(Oid reltablespace, bool relisshared, Relation pg_class) +{ + RelFileNode rnode; + char *rpath; + int fd; + bool collides; + + /* This should match RelationInitPhysicalAddr */ + rnode.spcNode = reltablespace ? reltablespace : MyDatabaseTableSpace; + rnode.dbNode = relisshared ? InvalidOid : MyDatabaseId; + + do + { + /* Generate the OID */ + if (pg_class) + rnode.relNode = GetNewOid(pg_class); + else + rnode.relNode = GetNewObjectId(); + + /* Check for existing file of same name */ + rpath = relpath(rnode); + fd = BasicOpenFile(rpath, O_RDONLY | PG_BINARY, 0); + + if (fd >= 0) + { + /* definite collision */ + close(fd); + collides = true; + } + else + { + /* + * Here we have a little bit of a dilemma: if errno is something + * other than ENOENT, should we declare a collision and loop? + * In particular one might think this advisable for, say, EPERM. + * However there really shouldn't be any unreadable files in a + * tablespace directory, and if the EPERM is actually complaining + * that we can't read the directory itself, we'd be in an infinite + * loop. In practice it seems best to go ahead regardless of the + * errno. If there is a colliding file we will get an smgr failure + * when we attempt to create the new relation file. + */ + collides = false; + } + + pfree(rpath); + } while (collides); + + return rnode.relNode; } diff --git a/src/backend/catalog/heap.c b/src/backend/catalog/heap.c index 324e20026e3..5027fd1f92f 100644 --- a/src/backend/catalog/heap.c +++ b/src/backend/catalog/heap.c @@ -8,7 +8,7 @@ * * * IDENTIFICATION - * $PostgreSQL: pgsql/src/backend/catalog/heap.c,v 1.288 2005/07/28 07:38:33 neilc Exp $ + * $PostgreSQL: pgsql/src/backend/catalog/heap.c,v 1.289 2005/08/12 01:35:56 tgl Exp $ * * * INTERFACE ROUTINES @@ -66,11 +66,10 @@ static void AddNewRelationTuple(Relation pg_class_desc, Relation new_rel_desc, Oid new_rel_oid, Oid new_type_oid, char relkind); -static void AddNewRelationType(const char *typeName, +static Oid AddNewRelationType(const char *typeName, Oid typeNamespace, Oid new_rel_oid, - char new_rel_kind, - Oid new_type_oid); + char new_rel_kind); static void RelationRemoveInheritance(Oid relid); static void StoreRelCheck(Relation rel, char *ccname, char *ccbin); static void StoreConstraints(Relation rel, TupleDesc tupdesc); @@ -190,9 +189,8 @@ SystemAttributeByName(const char *attname, bool relhasoids) /* ---------------------------------------------------------------- * heap_create - Create an uncataloged heap relation * - * relid is normally InvalidOid to specify that this routine should - * generate an OID for the relation. During bootstrap, it can be - * nonzero to specify a preselected OID. + * Note API change: the caller must now always provide the OID + * to use for the relation. * * rel->rd_rel is initialized by RelationBuildLocalRelation, * and is mostly zeroes at return. @@ -211,6 +209,9 @@ heap_create(const char *relname, bool create_storage; Relation rel; + /* The caller must have provided an OID for the relation. */ + Assert(OidIsValid(relid)); + /* * sanity checks */ @@ -223,12 +224,6 @@ heap_create(const char *relname, get_namespace_name(relnamespace), relname), errdetail("System catalog modifications are currently disallowed."))); - /* - * Allocate an OID for the relation, unless we were told what to use. - */ - if (!OidIsValid(relid)) - relid = newoid(); - /* * Decide if we need storage or not, and handle a couple other * special cases for particular relkinds. @@ -307,12 +302,12 @@ heap_create(const char *relname, * * 3) heap_create() is called to create the new relation on disk. * - * 4) AddNewRelationTuple() is called to register the - * relation in pg_class. - * - * 5) TypeCreate() is called to define a new type corresponding + * 4) TypeCreate() is called to define a new type corresponding * to the new relation. * + * 5) AddNewRelationTuple() is called to register the + * relation in pg_class. + * * 6) AddNewAttributeTuples() is called to register the * new relation's schema in pg_attribute. * @@ -628,36 +623,35 @@ AddNewRelationTuple(Relation pg_class_desc, * define a composite type corresponding to the new relation * -------------------------------- */ -static void +static Oid AddNewRelationType(const char *typeName, Oid typeNamespace, Oid new_rel_oid, - char new_rel_kind, - Oid new_type_oid) + char new_rel_kind) { - TypeCreate(typeName, /* type name */ - typeNamespace, /* type namespace */ - new_type_oid, /* preassigned oid for type */ - new_rel_oid, /* relation oid */ - new_rel_kind, /* relation kind */ - -1, /* internal size (varlena) */ - 'c', /* type-type (complex) */ - ',', /* default array delimiter */ - F_RECORD_IN, /* input procedure */ - F_RECORD_OUT, /* output procedure */ - F_RECORD_RECV, /* receive procedure */ - F_RECORD_SEND, /* send procedure */ - InvalidOid, /* analyze procedure - default */ - InvalidOid, /* array element type - irrelevant */ - InvalidOid, /* domain base type - irrelevant */ - NULL, /* default type value - none */ - NULL, /* default type binary representation */ - false, /* passed by reference */ - 'd', /* alignment - must be the largest! */ - 'x', /* fully TOASTable */ - -1, /* typmod */ - 0, /* array dimensions for typBaseType */ - false); /* Type NOT NULL */ + return + TypeCreate(typeName, /* type name */ + typeNamespace, /* type namespace */ + new_rel_oid, /* relation oid */ + new_rel_kind, /* relation kind */ + -1, /* internal size (varlena) */ + 'c', /* type-type (complex) */ + ',', /* default array delimiter */ + F_RECORD_IN, /* input procedure */ + F_RECORD_OUT, /* output procedure */ + F_RECORD_RECV, /* receive procedure */ + F_RECORD_SEND, /* send procedure */ + InvalidOid, /* analyze procedure - default */ + InvalidOid, /* array element type - irrelevant */ + InvalidOid, /* domain base type - irrelevant */ + NULL, /* default value - none */ + NULL, /* default binary representation */ + false, /* passed by reference */ + 'd', /* alignment - must be the largest! */ + 'x', /* fully TOASTable */ + -1, /* typmod */ + 0, /* array dimensions for typBaseType */ + false); /* Type NOT NULL */ } /* -------------------------------- @@ -681,9 +675,10 @@ heap_create_with_catalog(const char *relname, { Relation pg_class_desc; Relation new_rel_desc; - Oid new_rel_oid; Oid new_type_oid; + pg_class_desc = heap_open(RelationRelationId, RowExclusiveLock); + /* * sanity checks */ @@ -696,6 +691,16 @@ heap_create_with_catalog(const char *relname, (errcode(ERRCODE_DUPLICATE_TABLE), errmsg("relation \"%s\" already exists", relname))); + /* + * Allocate an OID for the relation, unless we were told what to use. + * + * The OID will be the relfilenode as well, so make sure it doesn't + * collide with either pg_class OIDs or existing physical files. + */ + if (!OidIsValid(relid)) + relid = GetNewRelFileNode(reltablespace, shared_relation, + pg_class_desc); + /* * Create the relcache entry (mostly dummy at this point) and the * physical disk file. (If we fail further down, it's the smgr's @@ -710,26 +715,7 @@ heap_create_with_catalog(const char *relname, shared_relation, allow_system_table_mods); - /* Fetch the relation OID assigned by heap_create */ - new_rel_oid = RelationGetRelid(new_rel_desc); - - /* Assign an OID for the relation's tuple type */ - new_type_oid = newoid(); - - /* - * now create an entry in pg_class for the relation. - * - * NOTE: we could get a unique-index failure here, in case someone else - * is creating the same relation name in parallel but hadn't committed - * yet when we checked for a duplicate name above. - */ - pg_class_desc = heap_open(RelationRelationId, RowExclusiveLock); - - AddNewRelationTuple(pg_class_desc, - new_rel_desc, - new_rel_oid, - new_type_oid, - relkind); + Assert(relid == RelationGetRelid(new_rel_desc)); /* * since defining a relation also defines a complex type, we add a new @@ -738,17 +724,29 @@ heap_create_with_catalog(const char *relname, * NOTE: we could get a unique-index failure here, in case the same name * has already been used for a type. */ - AddNewRelationType(relname, - relnamespace, - new_rel_oid, - relkind, - new_type_oid); + new_type_oid = AddNewRelationType(relname, + relnamespace, + relid, + relkind); + + /* + * now create an entry in pg_class for the relation. + * + * NOTE: we could get a unique-index failure here, in case someone else + * is creating the same relation name in parallel but hadn't committed + * yet when we checked for a duplicate name above. + */ + AddNewRelationTuple(pg_class_desc, + new_rel_desc, + relid, + new_type_oid, + relkind); /* * now add tuples to pg_attribute for the attributes in our new * relation. */ - AddNewAttributeTuples(new_rel_oid, new_rel_desc->rd_att, relkind, + AddNewAttributeTuples(relid, new_rel_desc->rd_att, relkind, oidislocal, oidinhcount); /* @@ -764,14 +762,14 @@ heap_create_with_catalog(const char *relname, referenced; myself.classId = RelationRelationId; - myself.objectId = new_rel_oid; + myself.objectId = relid; myself.objectSubId = 0; referenced.classId = NamespaceRelationId; referenced.objectId = relnamespace; referenced.objectSubId = 0; recordDependencyOn(&myself, &referenced, DEPENDENCY_NORMAL); - recordDependencyOnOwner(RelationRelationId, new_rel_oid, GetUserId()); + recordDependencyOnOwner(RelationRelationId, relid, GetUserId()); } /* @@ -788,16 +786,16 @@ heap_create_with_catalog(const char *relname, * If there's a special on-commit action, remember it */ if (oncommit != ONCOMMIT_NOOP) - register_on_commit_action(new_rel_oid, oncommit); + register_on_commit_action(relid, oncommit); /* * ok, the relation has been cataloged, so close our relations and - * return the oid of the newly created relation. + * return the OID of the newly created relation. */ heap_close(new_rel_desc, NoLock); /* do not unlock till end of xact */ heap_close(pg_class_desc, RowExclusiveLock); - return new_rel_oid; + return relid; } diff --git a/src/backend/catalog/index.c b/src/backend/catalog/index.c index 89ba99c4484..b06079820ef 100644 --- a/src/backend/catalog/index.c +++ b/src/backend/catalog/index.c @@ -8,7 +8,7 @@ * * * IDENTIFICATION - * $PostgreSQL: pgsql/src/backend/catalog/index.c,v 1.258 2005/06/25 16:53:49 tgl Exp $ + * $PostgreSQL: pgsql/src/backend/catalog/index.c,v 1.259 2005/08/12 01:35:56 tgl Exp $ * * * INTERFACE ROUTINES @@ -53,7 +53,7 @@ static TupleDesc ConstructTupleDescriptor(Relation heapRelation, IndexInfo *indexInfo, Oid *classObjectId); -static void UpdateRelationRelation(Relation indexRelation); +static void UpdateRelationRelation(Relation pg_class, Relation indexRelation); static void InitializeAttributeOids(Relation indexRelation, int numatts, Oid indexoid); static void AppendAttributeTuples(Relation indexRelation, int numatts); @@ -241,13 +241,10 @@ ConstructTupleDescriptor(Relation heapRelation, * ---------------------------------------------------------------- */ static void -UpdateRelationRelation(Relation indexRelation) +UpdateRelationRelation(Relation pg_class, Relation indexRelation) { - Relation pg_class; HeapTuple tuple; - pg_class = heap_open(RelationRelationId, RowExclusiveLock); - /* XXX Natts_pg_class_fixed is a hack - see pg_class.h */ tuple = heap_addheader(Natts_pg_class_fixed, true, @@ -259,13 +256,13 @@ UpdateRelationRelation(Relation indexRelation) * would be embarrassing to do this sort of thing in polite company. */ HeapTupleSetOid(tuple, RelationGetRelid(indexRelation)); + simple_heap_insert(pg_class, tuple); /* update the system catalog indexes */ CatalogUpdateIndexes(pg_class, tuple); heap_freetuple(tuple); - heap_close(pg_class, RowExclusiveLock); } /* ---------------------------------------------------------------- @@ -464,14 +461,16 @@ index_create(Oid heapRelationId, bool allow_system_table_mods, bool skip_build) { + Relation pg_class; Relation heapRelation; Relation indexRelation; TupleDesc indexTupDesc; bool shared_relation; Oid namespaceId; - Oid indexoid; int i; + pg_class = heap_open(RelationRelationId, RowExclusiveLock); + /* * Only SELECT ... FOR UPDATE/SHARE are allowed while doing this */ @@ -524,6 +523,16 @@ index_create(Oid heapRelationId, indexInfo, classObjectId); + /* + * Allocate an OID for the index, unless we were told what to use. + * + * The OID will be the relfilenode as well, so make sure it doesn't + * collide with either pg_class OIDs or existing physical files. + */ + if (!OidIsValid(indexRelationId)) + indexRelationId = GetNewRelFileNode(tableSpaceId, shared_relation, + pg_class); + /* * create the index relation's relcache entry and physical disk file. * (If we fail further down, it's the smgr's responsibility to remove @@ -538,8 +547,7 @@ index_create(Oid heapRelationId, shared_relation, allow_system_table_mods); - /* Fetch the relation OID assigned by heap_create */ - indexoid = RelationGetRelid(indexRelation); + Assert(indexRelationId == RelationGetRelid(indexRelation)); /* * Obtain exclusive lock on it. Although no other backends can see it @@ -562,7 +570,10 @@ index_create(Oid heapRelationId, /* * store index's pg_class entry */ - UpdateRelationRelation(indexRelation); + UpdateRelationRelation(pg_class, indexRelation); + + /* done with pg_class */ + heap_close(pg_class, RowExclusiveLock); /* * now update the object id's of all the attribute tuple forms in the @@ -570,7 +581,7 @@ index_create(Oid heapRelationId, */ InitializeAttributeOids(indexRelation, indexInfo->ii_NumIndexAttrs, - indexoid); + indexRelationId); /* * append ATTRIBUTE tuples for the index @@ -585,7 +596,7 @@ index_create(Oid heapRelationId, * (Or, could define a rule to maintain the predicate) --Nels, Feb '92 * ---------------- */ - UpdateIndexRelation(indexoid, heapRelationId, indexInfo, + UpdateIndexRelation(indexRelationId, heapRelationId, indexInfo, classObjectId, primary); /* @@ -608,7 +619,7 @@ index_create(Oid heapRelationId, referenced; myself.classId = RelationRelationId; - myself.objectId = indexoid; + myself.objectId = indexRelationId; myself.objectSubId = 0; if (isconstraint) @@ -735,7 +746,7 @@ index_create(Oid heapRelationId, */ if (IsBootstrapProcessingMode()) { - index_register(heapRelationId, indexoid, indexInfo); + index_register(heapRelationId, indexRelationId, indexInfo); /* XXX shouldn't we close the heap and index rels here? */ } else if (skip_build) @@ -750,7 +761,7 @@ index_create(Oid heapRelationId, /* index_build closes the passed rels */ } - return indexoid; + return indexRelationId; } /* @@ -1113,7 +1124,9 @@ setNewRelfilenode(Relation relation) Assert(!relation->rd_rel->relisshared); /* Allocate a new relfilenode */ - newrelfilenode = newoid(); + newrelfilenode = GetNewRelFileNode(relation->rd_rel->reltablespace, + relation->rd_rel->relisshared, + NULL); /* * Find the pg_class tuple for the given relation. This is not used @@ -1738,6 +1751,11 @@ reindex_relation(Oid relid, bool toast_too) * whether they have index entries. Also, a new pg_class index will * be created with an entry for its own pg_class row because we do * setNewRelfilenode() before we do index_build(). + * + * Note that we also clear pg_class's rd_oidindex until the loop is done, + * so that that index can't be accessed either. This means we cannot + * safely generate new relation OIDs while in the loop; shouldn't be a + * problem. */ is_pg_class = (RelationGetRelid(rel) == RelationRelationId); doneIndexes = NIL; @@ -1748,7 +1766,7 @@ reindex_relation(Oid relid, bool toast_too) Oid indexOid = lfirst_oid(indexId); if (is_pg_class) - RelationSetIndexList(rel, doneIndexes); + RelationSetIndexList(rel, doneIndexes, InvalidOid); reindex_index(indexOid); @@ -1759,7 +1777,7 @@ reindex_relation(Oid relid, bool toast_too) } if (is_pg_class) - RelationSetIndexList(rel, indexIds); + RelationSetIndexList(rel, indexIds, ClassOidIndexId); /* * Close rel, but continue to hold the lock. diff --git a/src/backend/catalog/pg_type.c b/src/backend/catalog/pg_type.c index 0144e10fdbb..d84bc2c1ac8 100644 --- a/src/backend/catalog/pg_type.c +++ b/src/backend/catalog/pg_type.c @@ -8,7 +8,7 @@ * * * IDENTIFICATION - * $PostgreSQL: pgsql/src/backend/catalog/pg_type.c,v 1.102 2005/07/07 20:39:57 tgl Exp $ + * $PostgreSQL: pgsql/src/backend/catalog/pg_type.c,v 1.103 2005/08/12 01:35:57 tgl Exp $ * *------------------------------------------------------------------------- */ @@ -142,16 +142,12 @@ TypeShellMake(const char *typeName, Oid typeNamespace) * * This does all the necessary work needed to define a new type. * - * NOTE: if assignedTypeOid is not InvalidOid, then that OID is assigned to - * the new type (which, therefore, cannot already exist as a shell type). - * This hack is only intended for use in creating a relation's associated - * type, where we need to have created the relation tuple already. + * Returns the OID assigned to the new type. * ---------------------------------------------------------------- */ Oid TypeCreate(const char *typeName, Oid typeNamespace, - Oid assignedTypeOid, Oid relationOid, /* only for 'c'atalog types */ char relationKind, /* ditto */ int16 internalSize, @@ -285,10 +281,9 @@ TypeCreate(const char *typeName, { /* * check that the type is not already defined. It may exist as a - * shell type, however (but only if assignedTypeOid is not given). + * shell type, however. */ - if (((Form_pg_type) GETSTRUCT(tup))->typisdefined || - assignedTypeOid != InvalidOid) + if (((Form_pg_type) GETSTRUCT(tup))->typisdefined) ereport(ERROR, (errcode(ERRCODE_DUPLICATE_OBJECT), errmsg("type \"%s\" already exists", typeName))); @@ -314,9 +309,6 @@ TypeCreate(const char *typeName, values, nulls); - /* preassign tuple Oid, if one was given */ - HeapTupleSetOid(tup, assignedTypeOid); - typeObjectId = simple_heap_insert(pg_type_desc, tup); } diff --git a/src/backend/commands/dbcommands.c b/src/backend/commands/dbcommands.c index 01b53e06933..40e28a0821c 100644 --- a/src/backend/commands/dbcommands.c +++ b/src/backend/commands/dbcommands.c @@ -15,7 +15,7 @@ * * * IDENTIFICATION - * $PostgreSQL: pgsql/src/backend/commands/dbcommands.c,v 1.169 2005/08/02 19:02:31 tgl Exp $ + * $PostgreSQL: pgsql/src/backend/commands/dbcommands.c,v 1.170 2005/08/12 01:35:57 tgl Exp $ * *------------------------------------------------------------------------- */ @@ -80,7 +80,7 @@ createdb(const CreatedbStmt *stmt) TransactionId src_frozenxid; Oid src_deftablespace; volatile Oid dst_deftablespace; - volatile Relation pg_database_rel = NULL; + volatile Relation pg_database_rel; HeapTuple tuple; TupleDesc pg_database_dsc; Datum new_record[Natts_pg_database]; @@ -347,9 +347,13 @@ createdb(const CreatedbStmt *stmt) /* * Preassign OID for pg_database tuple, so that we can compute db - * path. + * path. We have to open pg_database to do this, but we don't want + * to take ExclusiveLock yet, so just do it and close again. */ - dboid = newoid(); + pg_database_rel = heap_open(DatabaseRelationId, AccessShareLock); + dboid = GetNewOid(pg_database_rel); + heap_close(pg_database_rel, AccessShareLock); + pg_database_rel = NULL; /* * Force dirty buffers out to disk, to ensure source database is diff --git a/src/backend/commands/trigger.c b/src/backend/commands/trigger.c index 9df00d8cbea..4ea973ae7fa 100644 --- a/src/backend/commands/trigger.c +++ b/src/backend/commands/trigger.c @@ -7,7 +7,7 @@ * Portions Copyright (c) 1994, Regents of the University of California * * IDENTIFICATION - * $PostgreSQL: pgsql/src/backend/commands/trigger.c,v 1.190 2005/08/01 20:31:07 tgl Exp $ + * $PostgreSQL: pgsql/src/backend/commands/trigger.c,v 1.191 2005/08/12 01:35:57 tgl Exp $ * *------------------------------------------------------------------------- */ @@ -184,7 +184,9 @@ CreateTrigger(CreateTrigStmt *stmt, bool forConstraint) * Generate the trigger's OID now, so that we can use it in the name * if needed. */ - trigoid = newoid(); + tgrel = heap_open(TriggerRelationId, RowExclusiveLock); + + trigoid = GetNewOid(tgrel); /* * If trigger is an RI constraint, use specified trigger name as @@ -252,7 +254,6 @@ CreateTrigger(CreateTrigStmt *stmt, bool forConstraint) * NOTE that this is cool only because we have AccessExclusiveLock on the * relation, so the trigger set won't be changing underneath us. */ - tgrel = heap_open(TriggerRelationId, RowExclusiveLock); ScanKeyInit(&key, Anum_pg_trigger_tgrelid, BTEqualStrategyNumber, F_OIDEQ, diff --git a/src/backend/commands/typecmds.c b/src/backend/commands/typecmds.c index 31e43cd4281..e0c3a311eac 100644 --- a/src/backend/commands/typecmds.c +++ b/src/backend/commands/typecmds.c @@ -8,7 +8,7 @@ * * * IDENTIFICATION - * $PostgreSQL: pgsql/src/backend/commands/typecmds.c,v 1.78 2005/08/04 01:09:28 tgl Exp $ + * $PostgreSQL: pgsql/src/backend/commands/typecmds.c,v 1.79 2005/08/12 01:35:58 tgl Exp $ * * DESCRIPTION * The "DefineFoo" routines take the parse tree and pick out the @@ -339,7 +339,6 @@ DefineType(List *names, List *parameters) typoid = TypeCreate(typeName, /* type name */ typeNamespace, /* namespace */ - InvalidOid, /* preassigned type oid (not done here) */ InvalidOid, /* relation oid (n/a here) */ 0, /* relation kind (ditto) */ internalLength, /* internal size */ @@ -372,7 +371,6 @@ DefineType(List *names, List *parameters) TypeCreate(shadow_type, /* type name */ typeNamespace, /* namespace */ - InvalidOid, /* preassigned type oid (not done here) */ InvalidOid, /* relation oid (n/a here) */ 0, /* relation kind (ditto) */ -1, /* internal size */ @@ -724,7 +722,6 @@ DefineDomain(CreateDomainStmt *stmt) domainoid = TypeCreate(domainName, /* type name */ domainNamespace, /* namespace */ - InvalidOid, /* preassigned type oid (none here) */ InvalidOid, /* relation oid (n/a here) */ 0, /* relation kind (ditto) */ internalLength, /* internal size */ diff --git a/src/backend/storage/large_object/inv_api.c b/src/backend/storage/large_object/inv_api.c index 38734a5f9c3..9762c769163 100644 --- a/src/backend/storage/large_object/inv_api.c +++ b/src/backend/storage/large_object/inv_api.c @@ -9,7 +9,7 @@ * * * IDENTIFICATION - * $PostgreSQL: pgsql/src/backend/storage/large_object/inv_api.c,v 1.111 2005/06/13 02:26:49 tgl Exp $ + * $PostgreSQL: pgsql/src/backend/storage/large_object/inv_api.c,v 1.112 2005/08/12 01:35:58 tgl Exp $ * *------------------------------------------------------------------------- */ @@ -177,14 +177,14 @@ inv_create(Oid lobjId) { /* * Allocate an OID to be the LO's identifier, unless we were told - * what to use. In event of collision with an existing ID, loop - * to find a free one. + * what to use. We can use the index on pg_largeobject for checking + * OID uniqueness, even though it has additional columns besides OID. */ if (!OidIsValid(lobjId)) { - do { - lobjId = newoid(); - } while (LargeObjectExists(lobjId)); + open_lo_relation(); + + lobjId = GetNewOidWithIndex(lo_heap_r, lo_index_r); } /* diff --git a/src/backend/utils/cache/relcache.c b/src/backend/utils/cache/relcache.c index 09f54f7bc91..f7c8d46a23c 100644 --- a/src/backend/utils/cache/relcache.c +++ b/src/backend/utils/cache/relcache.c @@ -8,7 +8,7 @@ * * * IDENTIFICATION - * $PostgreSQL: pgsql/src/backend/utils/cache/relcache.c,v 1.226 2005/08/08 19:17:22 tgl Exp $ + * $PostgreSQL: pgsql/src/backend/utils/cache/relcache.c,v 1.227 2005/08/12 01:35:59 tgl Exp $ * *------------------------------------------------------------------------- */ @@ -1899,6 +1899,7 @@ AtEOXact_RelationCache(bool isCommit) { list_free(relation->rd_indexlist); relation->rd_indexlist = NIL; + relation->rd_oidindex = InvalidOid; relation->rd_indexvalid = 0; } } @@ -1959,6 +1960,7 @@ AtEOSubXact_RelationCache(bool isCommit, SubTransactionId mySubid, { list_free(relation->rd_indexlist); relation->rd_indexlist = NIL; + relation->rd_oidindex = InvalidOid; relation->rd_indexvalid = 0; } } @@ -2512,6 +2514,11 @@ CheckConstraintFetch(Relation relation) * may freeList() the returned list after scanning it. This is necessary * since the caller will typically be doing syscache lookups on the relevant * indexes, and syscache lookup could cause SI messages to be processed! + * + * We also update rd_oidindex, which this module treats as effectively part + * of the index list. rd_oidindex is valid when rd_indexvalid isn't zero; + * it is the pg_class OID of a unique index on OID when the relation has one, + * and InvalidOid if there is no such index. */ List * RelationGetIndexList(Relation relation) @@ -2521,6 +2528,7 @@ RelationGetIndexList(Relation relation) ScanKeyData skey; HeapTuple htup; List *result; + Oid oidIndex; MemoryContext oldcxt; /* Quick exit if we already computed the list. */ @@ -2534,6 +2542,7 @@ RelationGetIndexList(Relation relation) * memory leakage if we get some sort of error partway through. */ result = NIL; + oidIndex = InvalidOid; /* Prepare to scan pg_index for entries having indrelid = this rel. */ ScanKeyInit(&skey, @@ -2549,7 +2558,16 @@ RelationGetIndexList(Relation relation) { Form_pg_index index = (Form_pg_index) GETSTRUCT(htup); + /* Add index's OID to result list in the proper order */ result = insert_ordered_oid(result, index->indexrelid); + + /* Check to see if it is a unique, non-partial btree index on OID */ + if (index->indnatts == 1 && + index->indisunique && + index->indkey.values[0] == ObjectIdAttributeNumber && + index->indclass.values[0] == OID_BTREE_OPS_OID && + heap_attisnull(htup, Anum_pg_index_indpred)) + oidIndex = index->indexrelid; } systable_endscan(indscan); @@ -2558,6 +2576,7 @@ RelationGetIndexList(Relation relation) /* Now save a copy of the completed list in the relcache entry. */ oldcxt = MemoryContextSwitchTo(CacheMemoryContext); relation->rd_indexlist = list_copy(result); + relation->rd_oidindex = oidIndex; relation->rd_indexvalid = 1; MemoryContextSwitchTo(oldcxt); @@ -2601,8 +2620,8 @@ insert_ordered_oid(List *list, Oid datum) * RelationSetIndexList -- externally force the index list contents * * This is used to temporarily override what we think the set of valid - * indexes is. The forcing will be valid only until transaction commit - * or abort. + * indexes is (including the presence or absence of an OID index). + * The forcing will be valid only until transaction commit or abort. * * This should only be applied to nailed relations, because in a non-nailed * relation the hacked index list could be lost at any time due to SI @@ -2611,7 +2630,7 @@ insert_ordered_oid(List *list, Oid datum) * It is up to the caller to make sure the given list is correctly ordered. */ void -RelationSetIndexList(Relation relation, List *indexIds) +RelationSetIndexList(Relation relation, List *indexIds, Oid oidIndex) { MemoryContext oldcxt; @@ -2623,11 +2642,40 @@ RelationSetIndexList(Relation relation, List *indexIds) /* Okay to replace old list */ list_free(relation->rd_indexlist); relation->rd_indexlist = indexIds; + relation->rd_oidindex = oidIndex; relation->rd_indexvalid = 2; /* mark list as forced */ /* must flag that we have a forced index list */ need_eoxact_work = true; } +/* + * RelationGetOidIndex -- get the pg_class OID of the relation's OID index + * + * Returns InvalidOid if there is no such index. + */ +Oid +RelationGetOidIndex(Relation relation) +{ + List *ilist; + + /* + * If relation doesn't have OIDs at all, caller is probably confused. + * (We could just silently return InvalidOid, but it seems better to + * throw an assertion.) + */ + Assert(relation->rd_rel->relhasoids); + + if (relation->rd_indexvalid == 0) + { + /* RelationGetIndexList does the heavy lifting. */ + ilist = RelationGetIndexList(relation); + list_free(ilist); + Assert(relation->rd_indexvalid != 0); + } + + return relation->rd_oidindex; +} + /* * RelationGetIndexExpressions -- get the index expressions for an index * @@ -3057,6 +3105,7 @@ load_relcache_init_file(void) rel->rd_refcnt = 0; rel->rd_indexvalid = 0; rel->rd_indexlist = NIL; + rel->rd_oidindex = InvalidOid; rel->rd_createSubid = InvalidSubTransactionId; MemSet(&rel->pgstat_info, 0, sizeof(rel->pgstat_info)); diff --git a/src/bin/pg_dump/pg_backup_archiver.c b/src/bin/pg_dump/pg_backup_archiver.c index 224dbcec6fb..9bfed97424f 100644 --- a/src/bin/pg_dump/pg_backup_archiver.c +++ b/src/bin/pg_dump/pg_backup_archiver.c @@ -15,7 +15,7 @@ * * * IDENTIFICATION - * $PostgreSQL: pgsql/src/bin/pg_dump/pg_backup_archiver.c,v 1.111 2005/06/21 20:45:44 tgl Exp $ + * $PostgreSQL: pgsql/src/bin/pg_dump/pg_backup_archiver.c,v 1.112 2005/08/12 01:35:59 tgl Exp $ * *------------------------------------------------------------------------- */ @@ -1962,11 +1962,11 @@ _tocEntryRequired(TocEntry *te, RestoreOptions *ropt, bool include_acls) } /* - * Special case: type with tag; this is part of a - * DATA restore even though it has SQL. + * Special case: type with tag; this is obsolete + * and we always ignore it. */ if ((strcmp(te->desc, "") == 0) && (strcmp(te->tag, "Max OID") == 0)) - res = REQ_DATA; + return 0; /* Mask it if we only want schema */ if (ropt->schemaOnly) diff --git a/src/bin/pg_dump/pg_dump.c b/src/bin/pg_dump/pg_dump.c index 54ca6252a45..70255a91d6d 100644 --- a/src/bin/pg_dump/pg_dump.c +++ b/src/bin/pg_dump/pg_dump.c @@ -12,7 +12,7 @@ * by PostgreSQL * * IDENTIFICATION - * $PostgreSQL: pgsql/src/bin/pg_dump/pg_dump.c,v 1.415 2005/07/10 15:08:52 momjian Exp $ + * $PostgreSQL: pgsql/src/bin/pg_dump/pg_dump.c,v 1.416 2005/08/12 01:36:00 tgl Exp $ * *------------------------------------------------------------------------- */ @@ -158,7 +158,6 @@ static const char *convertRegProcReference(const char *proc); static const char *convertOperatorReference(const char *opr); static Oid findLastBuiltinOid_V71(const char *); static Oid findLastBuiltinOid_V70(void); -static void setMaxOid(Archive *fout); static void selectSourceSchema(const char *schemaName); static char *getFormattedTypeName(Oid oid, OidOptions opts); static char *myFormatType(const char *typname, int32 typmod); @@ -611,10 +610,6 @@ main(int argc, char **argv) if (!dataOnly) dumpDatabase(g_fout); - /* Max OID is next. */ - if (oids == true) - setMaxOid(g_fout); - /* Now the rearrangeable objects. */ for (i = 0; i < numObjs; i++) dumpDumpableObject(g_fout, dobjs[i]); @@ -7408,51 +7403,6 @@ dumpTableConstraintComment(Archive *fout, ConstraintInfo *coninfo) destroyPQExpBuffer(q); } -/* - * setMaxOid - - * find the maximum oid and generate a COPY statement to set it - */ -static void -setMaxOid(Archive *fout) -{ - PGresult *res; - Oid max_oid; - char sql[1024]; - - if (fout->remoteVersion >= 70200) - do_sql_command(g_conn, - "CREATE TEMPORARY TABLE pgdump_oid (dummy integer) WITH OIDS"); - else - do_sql_command(g_conn, - "CREATE TEMPORARY TABLE pgdump_oid (dummy integer)"); - res = PQexec(g_conn, "INSERT INTO pgdump_oid VALUES (0)"); - check_sql_result(res, g_conn, "INSERT INTO pgdump_oid VALUES (0)", - PGRES_COMMAND_OK); - max_oid = PQoidValue(res); - if (max_oid == 0) - { - write_msg(NULL, "inserted invalid OID\n"); - exit_nicely(); - } - PQclear(res); - do_sql_command(g_conn, "DROP TABLE pgdump_oid;"); - if (g_verbose) - write_msg(NULL, "maximum system OID is %u\n", max_oid); - snprintf(sql, sizeof(sql), - "CREATE TEMPORARY TABLE pgdump_oid (dummy integer) WITH OIDS;\n" - "COPY pgdump_oid WITH OIDS FROM stdin;\n" - "%u\t0\n" - "\\.\n" - "DROP TABLE pgdump_oid;\n", - max_oid); - - ArchiveEntry(fout, nilCatalogId, createDumpId(), - "Max OID", NULL, NULL, "", - false, "", sql, "", NULL, - NULL, 0, - NULL, NULL); -} - /* * findLastBuiltInOid - * find the last built in oid diff --git a/src/include/access/transam.h b/src/include/access/transam.h index 20518fa3835..51e54a9e053 100644 --- a/src/include/access/transam.h +++ b/src/include/access/transam.h @@ -7,7 +7,7 @@ * Portions Copyright (c) 1996-2005, PostgreSQL Global Development Group * Portions Copyright (c) 1994, Regents of the University of California * - * $PostgreSQL: pgsql/src/include/access/transam.h,v 1.54 2005/04/13 18:54:57 tgl Exp $ + * $PostgreSQL: pgsql/src/include/access/transam.h,v 1.55 2005/08/12 01:36:03 tgl Exp $ * *------------------------------------------------------------------------- */ @@ -126,6 +126,5 @@ extern TransactionId ReadNewTransactionId(void); extern void SetTransactionIdLimit(TransactionId oldest_datfrozenxid, Name oldest_datname); extern Oid GetNewObjectId(void); -extern void CheckMaxObjectId(Oid assigned_oid); #endif /* TRAMSAM_H */ diff --git a/src/include/catalog/catalog.h b/src/include/catalog/catalog.h index c9da1b35abe..d30bc763591 100644 --- a/src/include/catalog/catalog.h +++ b/src/include/catalog/catalog.h @@ -7,7 +7,7 @@ * Portions Copyright (c) 1996-2005, PostgreSQL Global Development Group * Portions Copyright (c) 1994, Regents of the University of California * - * $PostgreSQL: pgsql/src/include/catalog/catalog.h,v 1.32 2005/05/10 22:27:30 momjian Exp $ + * $PostgreSQL: pgsql/src/include/catalog/catalog.h,v 1.33 2005/08/12 01:36:04 tgl Exp $ * *------------------------------------------------------------------------- */ @@ -31,6 +31,9 @@ extern bool IsToastNamespace(Oid namespaceId); extern bool IsReservedName(const char *name); -extern Oid newoid(void); +extern Oid GetNewOid(Relation relation); +extern Oid GetNewOidWithIndex(Relation relation, Relation indexrel); +extern Oid GetNewRelFileNode(Oid reltablespace, bool relisshared, + Relation pg_class); #endif /* CATALOG_H */ diff --git a/src/include/catalog/pg_type.h b/src/include/catalog/pg_type.h index 5712e0d692f..6e4092fd390 100644 --- a/src/include/catalog/pg_type.h +++ b/src/include/catalog/pg_type.h @@ -8,7 +8,7 @@ * Portions Copyright (c) 1996-2005, PostgreSQL Global Development Group * Portions Copyright (c) 1994, Regents of the University of California * - * $PostgreSQL: pgsql/src/include/catalog/pg_type.h,v 1.164 2005/07/20 16:42:32 momjian Exp $ + * $PostgreSQL: pgsql/src/include/catalog/pg_type.h,v 1.165 2005/08/12 01:36:04 tgl Exp $ * * NOTES * the genbki.sh script reads this file and generates .bki @@ -556,7 +556,6 @@ extern Oid TypeShellMake(const char *typeName, Oid typeNamespace); extern Oid TypeCreate(const char *typeName, Oid typeNamespace, - Oid assignedTypeOid, Oid relationOid, char relationKind, int16 internalSize, diff --git a/src/include/utils/rel.h b/src/include/utils/rel.h index e3f636b83d8..172810ab1fa 100644 --- a/src/include/utils/rel.h +++ b/src/include/utils/rel.h @@ -7,7 +7,7 @@ * Portions Copyright (c) 1996-2005, PostgreSQL Global Development Group * Portions Copyright (c) 1994, Regents of the University of California * - * $PostgreSQL: pgsql/src/include/utils/rel.h,v 1.84 2005/05/27 23:31:21 tgl Exp $ + * $PostgreSQL: pgsql/src/include/utils/rel.h,v 1.85 2005/08/12 01:36:05 tgl Exp $ * *------------------------------------------------------------------------- */ @@ -136,8 +136,8 @@ typedef struct RelationData bool rd_istemp; /* rel uses the local buffer mgr */ bool rd_isnailed; /* rel is nailed in cache */ bool rd_isvalid; /* relcache entry is valid */ - char rd_indexvalid; /* state of rd_indexlist: 0 = not valid, 1 - * = valid, 2 = temporarily forced */ + char rd_indexvalid; /* state of rd_indexlist: 0 = not valid, + * 1 = valid, 2 = temporarily forced */ SubTransactionId rd_createSubid; /* rel was created in current xact */ /* @@ -151,6 +151,7 @@ typedef struct RelationData TupleDesc rd_att; /* tuple descriptor */ Oid rd_id; /* relation's object id */ List *rd_indexlist; /* list of OIDs of indexes on relation */ + Oid rd_oidindex; /* OID of unique index on OID, if any */ LockInfoData rd_lockInfo; /* lock mgr's info for locking relation */ RuleLock *rd_rules; /* rewrite rules */ MemoryContext rd_rulescxt; /* private memory cxt for rd_rules, if any */ diff --git a/src/include/utils/relcache.h b/src/include/utils/relcache.h index 0f58921ea1a..aadf14c4792 100644 --- a/src/include/utils/relcache.h +++ b/src/include/utils/relcache.h @@ -7,7 +7,7 @@ * Portions Copyright (c) 1996-2005, PostgreSQL Global Development Group * Portions Copyright (c) 1994, Regents of the University of California * - * $PostgreSQL: pgsql/src/include/utils/relcache.h,v 1.50 2005/04/14 20:03:27 tgl Exp $ + * $PostgreSQL: pgsql/src/include/utils/relcache.h,v 1.51 2005/08/12 01:36:05 tgl Exp $ * *------------------------------------------------------------------------- */ @@ -30,10 +30,12 @@ extern void RelationClose(Relation relation); * Routines to compute/retrieve additional cached information */ extern List *RelationGetIndexList(Relation relation); +extern Oid RelationGetOidIndex(Relation relation); extern List *RelationGetIndexExpressions(Relation relation); extern List *RelationGetIndexPredicate(Relation relation); -extern void RelationSetIndexList(Relation relation, List *indexIds); +extern void RelationSetIndexList(Relation relation, + List *indexIds, Oid oidIndex); extern void RelationInitIndexAccessInfo(Relation relation);