X-Git-Url: http://git.osdn.net/view?a=blobdiff_plain;f=src%2Fbackend%2Fcatalog%2Ftoasting.c;h=a8cf0dbe2f25896ad4f1663ed1bd99997f3de68e;hb=68ef051f5cf16f82a5368067a40ffba3c340b0d3;hp=9e2f20e3bf03233ffae03bad2ffd44ed44f84189;hpb=25d9bf2e3e66ee2e546c5c523d148ecab6ee1dcc;p=pg-rex%2Fsyncrep.git diff --git a/src/backend/catalog/toasting.c b/src/backend/catalog/toasting.c index 9e2f20e3bf..a8cf0dbe2f 100644 --- a/src/backend/catalog/toasting.c +++ b/src/backend/catalog/toasting.c @@ -4,11 +4,11 @@ * This file contains routines to support creation of toast tables * * - * Portions Copyright (c) 1996-2009, PostgreSQL Global Development Group + * Portions Copyright (c) 1996-2011, PostgreSQL Global Development Group * Portions Copyright (c) 1994, Regents of the University of California * * IDENTIFICATION - * $PostgreSQL: pgsql/src/backend/catalog/toasting.c,v 1.18 2009/07/29 20:56:18 tgl Exp $ + * src/backend/catalog/toasting.c * *------------------------------------------------------------------------- */ @@ -31,22 +31,20 @@ #include "utils/builtins.h" #include "utils/syscache.h" +/* Potentially set by contrib/pg_upgrade_support functions */ +extern Oid binary_upgrade_next_toast_pg_class_oid; + +Oid binary_upgrade_next_toast_pg_type_oid = InvalidOid; static bool create_toast_table(Relation rel, Oid toastOid, Oid toastIndexOid, - Datum reloptions, bool force); + Datum reloptions); static bool needs_toast_table(Relation rel); /* * AlterTableCreateToastTable * If the table needs a toast table, and doesn't already have one, - * then create a toast table for it. (With the force option, make - * a toast table even if it appears unnecessary.) - * - * The caller can also specify the OID to be used for the toast table. - * Usually, toastOid should be InvalidOid to allow a free OID to be assigned. - * (This option, as well as the force option, is not used by core Postgres, - * but is provided to support pg_migrator.) + * then create a toast table for it. * * reloptions for the toast table can be passed, too. Pass (Datum) 0 * for default reloptions. @@ -56,20 +54,19 @@ static bool needs_toast_table(Relation rel); * to end with CommandCounterIncrement if it makes any changes. */ void -AlterTableCreateToastTable(Oid relOid, Oid toastOid, - Datum reloptions, bool force) +AlterTableCreateToastTable(Oid relOid, Datum reloptions) { Relation rel; /* - * Grab an exclusive lock on the target table, which we will NOT release - * until end of transaction. (This is probably redundant in all present - * uses...) + * Grab a DDL-exclusive lock on the target table, since we'll update the + * pg_class tuple. This is redundant for all present users. Tuple toasting + * behaves safely in the face of a concurrent TOAST table add. */ - rel = heap_open(relOid, AccessExclusiveLock); + rel = heap_open(relOid, ShareUpdateExclusiveLock); /* create_toast_table does all the work */ - (void) create_toast_table(rel, toastOid, InvalidOid, reloptions, force); + (void) create_toast_table(rel, InvalidOid, InvalidOid, reloptions); heap_close(rel, NoLock); } @@ -95,7 +92,7 @@ BootstrapToastTable(char *relName, Oid toastOid, Oid toastIndexOid) relName))); /* create_toast_table does all the work */ - if (!create_toast_table(rel, toastOid, toastIndexOid, (Datum) 0, false)) + if (!create_toast_table(rel, toastOid, toastIndexOid, (Datum) 0)) elog(ERROR, "\"%s\" does not require a toast table", relName); @@ -106,25 +103,27 @@ BootstrapToastTable(char *relName, Oid toastOid, Oid toastIndexOid) /* * create_toast_table --- internal workhorse * - * rel is already opened and exclusive-locked - * toastOid and toastIndexOid are normally InvalidOid, but - * either or both can be nonzero to specify caller-assigned OIDs + * rel is already opened and locked + * toastOid and toastIndexOid are normally InvalidOid, but during + * bootstrap they can be nonzero to specify hand-assigned OIDs */ static bool -create_toast_table(Relation rel, Oid toastOid, Oid toastIndexOid, - Datum reloptions, bool force) +create_toast_table(Relation rel, Oid toastOid, Oid toastIndexOid, Datum reloptions) { Oid relOid = RelationGetRelid(rel); HeapTuple reltup; TupleDesc tupdesc; bool shared_relation; + bool mapped_relation; + Relation toast_rel; Relation class_rel; Oid toast_relid; - Oid toast_idxid; + Oid toast_typid = InvalidOid; Oid namespaceid; char toast_relname[NAMEDATALEN]; char toast_idxname[NAMEDATALEN]; IndexInfo *indexInfo; + Oid collationObjectId[2]; Oid classObjectId[2]; int16 coloptions[2]; ObjectAddress baseobject, @@ -142,6 +141,9 @@ create_toast_table(Relation rel, Oid toastOid, Oid toastIndexOid, (errcode(ERRCODE_OBJECT_NOT_IN_PREREQUISITE_STATE), errmsg("shared tables cannot be toasted after initdb"))); + /* It's mapped if and only if its parent is, too */ + mapped_relation = RelationIsMapped(rel); + /* * Is it already toasted? */ @@ -151,11 +153,12 @@ create_toast_table(Relation rel, Oid toastOid, Oid toastIndexOid, /* * Check to see whether the table actually needs a TOAST table. * - * Caller can optionally override this check. (Note: at present no - * callers in core Postgres do so, but this option is needed by - * pg_migrator.) + * If an update-in-place toast relfilenode is specified, force toast file + * creation even if it seems not to need one. */ - if (!force && !needs_toast_table(rel)) + if (!needs_toast_table(rel) && + (!IsBinaryUpgrade || + !OidIsValid(binary_upgrade_next_toast_pg_class_oid))) return false; /* @@ -194,29 +197,45 @@ create_toast_table(Relation rel, Oid toastOid, Oid toastIndexOid, * Toast tables for regular relations go in pg_toast; those for temp * relations go into the per-backend temp-toast-table namespace. */ - if (rel->rd_islocaltemp) + if (RelationUsesTempNamespace(rel)) namespaceid = GetTempToastNamespace(); else namespaceid = PG_TOAST_NAMESPACE; + /* Use binary-upgrade override for pg_type.oid, if supplied. */ + if (IsBinaryUpgrade && OidIsValid(binary_upgrade_next_toast_pg_type_oid)) + { + toast_typid = binary_upgrade_next_toast_pg_type_oid; + binary_upgrade_next_toast_pg_type_oid = InvalidOid; + } + toast_relid = heap_create_with_catalog(toast_relname, namespaceid, rel->rd_rel->reltablespace, toastOid, + toast_typid, + InvalidOid, rel->rd_rel->relowner, tupdesc, NIL, RELKIND_TOASTVALUE, + rel->rd_rel->relpersistence, shared_relation, + mapped_relation, true, 0, ONCOMMIT_NOOP, reloptions, + false, true); + Assert(toast_relid != InvalidOid); - /* make the toast relation visible, else index creation will fail */ + /* make the toast relation visible, else heap_open will fail */ CommandCounterIncrement(); + /* ShareLock is not really needed here, but take it anyway */ + toast_rel = heap_open(toast_relid, ShareLock); + /* * Create unique index on chunk_id, chunk_seq. * @@ -237,33 +256,40 @@ create_toast_table(Relation rel, Oid toastOid, Oid toastIndexOid, indexInfo->ii_ExpressionsState = NIL; indexInfo->ii_Predicate = NIL; indexInfo->ii_PredicateState = NIL; + indexInfo->ii_ExclusionOps = NULL; + indexInfo->ii_ExclusionProcs = NULL; + indexInfo->ii_ExclusionStrats = NULL; indexInfo->ii_Unique = true; indexInfo->ii_ReadyForInserts = true; indexInfo->ii_Concurrent = false; indexInfo->ii_BrokenHotChain = false; + collationObjectId[0] = InvalidOid; + collationObjectId[1] = InvalidOid; + classObjectId[0] = OID_BTREE_OPS_OID; classObjectId[1] = INT4_BTREE_OPS_OID; coloptions[0] = 0; coloptions[1] = 0; - toast_idxid = index_create(toast_relid, toast_idxname, toastIndexOid, + index_create(toast_rel, toast_idxname, toastIndexOid, indexInfo, + list_make2("chunk_id", "chunk_seq"), BTREE_AM_OID, rel->rd_rel->reltablespace, - classObjectId, coloptions, (Datum) 0, + collationObjectId, classObjectId, coloptions, (Datum) 0, true, false, false, false, true, false, false); + heap_close(toast_rel, NoLock); + /* * Store the toast table's OID in the parent relation's pg_class row */ class_rel = heap_open(RelationRelationId, RowExclusiveLock); - reltup = SearchSysCacheCopy(RELOID, - ObjectIdGetDatum(relOid), - 0, 0, 0); + reltup = SearchSysCacheCopy1(RELOID, ObjectIdGetDatum(relOid)); if (!HeapTupleIsValid(reltup)) elog(ERROR, "cache lookup failed for relation %u", relOid);