diff --git a/src/backend/catalog/index.c b/src/backend/catalog/index.c index a78f0fa3db..bedb84e6d2 100644 --- a/src/backend/catalog/index.c +++ b/src/backend/catalog/index.c @@ -8,7 +8,7 @@ * * * IDENTIFICATION - * $Header: /cvsroot/pgsql/src/backend/catalog/index.c,v 1.122 2000/07/04 06:11:23 tgl Exp $ + * $Header: /cvsroot/pgsql/src/backend/catalog/index.c,v 1.123 2000/07/05 16:17:37 wieck Exp $ * * * INTERFACE ROUTINES @@ -1335,7 +1335,8 @@ IndexesAreActive(Oid relid, bool confirmCommitted) if (!LockClassinfoForUpdate(relid, &tuple, &buffer, confirmCommitted)) elog(ERROR, "IndexesAreActive couldn't lock %u", relid); - if (((Form_pg_class) GETSTRUCT(&tuple))->relkind != RELKIND_RELATION) + if (((Form_pg_class) GETSTRUCT(&tuple))->relkind != RELKIND_RELATION && + ((Form_pg_class) GETSTRUCT(&tuple))->relkind != RELKIND_TOASTVALUE) elog(ERROR, "relation %u isn't an relation", relid); isactive = ((Form_pg_class) GETSTRUCT(&tuple))->relhasindex; ReleaseBuffer(buffer); diff --git a/src/backend/commands/command.c b/src/backend/commands/command.c index af5c49af5e..e3847ab5f4 100644 --- a/src/backend/commands/command.c +++ b/src/backend/commands/command.c @@ -8,7 +8,7 @@ * * * IDENTIFICATION - * $Header: /cvsroot/pgsql/src/backend/commands/Attic/command.c,v 1.86 2000/07/05 13:50:59 wieck Exp $ + * $Header: /cvsroot/pgsql/src/backend/commands/Attic/command.c,v 1.87 2000/07/05 16:17:38 wieck Exp $ * * NOTES * The PerformAddAttribute() code, like most of the relation @@ -1319,14 +1319,14 @@ AlterTableCreateToastTable(const char *relationName, bool silent) -1, 0, false); TupleDescInitEntry(tupdesc, (AttrNumber) 3, "chunk_data", - TEXTOID, /* XXX wouldn't BYTEAOID be better? */ + BYTEAOID, -1, 0, false); - /* XXX use RELKIND_TOASTVALUE here? */ /* XXX what if owning relation is temp? need we mark toasttable too? */ - /* !!! No need to worry about temp. It'll go away when it's master */ - /* table is deleted. Jan */ - heap_create_with_catalog(toast_relname, tupdesc, RELKIND_RELATION, + /* XXX How do we know? No naming collisions possible because names */ + /* are OID based. And toast table disappears when master table */ + /* is destroyed. So what is it good for anyway? Jan */ + heap_create_with_catalog(toast_relname, tupdesc, RELKIND_TOASTVALUE, false, true); /* make the toast relation visible, else index creation will fail */ @@ -1368,6 +1368,39 @@ AlterTableCreateToastTable(const char *relationName, bool silent) heap_freetuple(reltup); + /* + * Finally update the toast relations pg_class tuple to say + * it has an index. + */ + reltup = SearchSysCacheTuple(RELNAME, PointerGetDatum(toast_relname), + 0, 0, 0); + if (!HeapTupleIsValid(reltup)) + elog(ERROR, "ALTER TABLE: just created toast relation \"%s\" not found", + toast_relname); + classtuple.t_self = reltup->t_self; + switch (heap_mark4update(class_rel, &classtuple, &buffer)) + { + case HeapTupleSelfUpdated: + case HeapTupleMayBeUpdated: + break; + default: + elog(ERROR, "couldn't lock pg_class tuple"); + } + reltup = heap_copytuple(&classtuple); + ReleaseBuffer(buffer); + + ((Form_pg_class) GETSTRUCT(reltup))->relhasindex = true; + heap_update(class_rel, &reltup->t_self, reltup, NULL); + + CatalogOpenIndices(Num_pg_class_indices, Name_pg_class_indices, ridescs); + CatalogIndexInsert(ridescs, Num_pg_class_indices, class_rel, reltup); + CatalogCloseIndices(Num_pg_class_indices, ridescs); + + heap_freetuple(reltup); + + /* + * Close relatons and make changes visible + */ heap_close(class_rel, NoLock); heap_close(rel, NoLock); diff --git a/src/backend/commands/vacuum.c b/src/backend/commands/vacuum.c index 01ed68b3b7..71682baa8c 100644 --- a/src/backend/commands/vacuum.c +++ b/src/backend/commands/vacuum.c @@ -8,7 +8,7 @@ * * * IDENTIFICATION - * $Header: /cvsroot/pgsql/src/backend/commands/vacuum.c,v 1.161 2000/06/28 03:31:28 tgl Exp $ + * $Header: /cvsroot/pgsql/src/backend/commands/vacuum.c,v 1.162 2000/07/05 16:17:38 wieck Exp $ * *------------------------------------------------------------------------- @@ -58,7 +58,7 @@ static void vacuum_init(void); static void vacuum_shutdown(void); static void vac_vacuum(NameData *VacRelP, bool analyze, List *anal_cols2); static VRelList getrels(NameData *VacRelP); -static void vacuum_rel(Oid relid, bool analyze); +static void vacuum_rel(Oid relid, bool analyze, bool is_toastrel); static void scan_heap(VRelStats *vacrelstats, Relation onerel, VacPageList vacuum_pages, VacPageList fraged_pages); static void repair_frag(VRelStats *vacrelstats, Relation onerel, VacPageList vacuum_pages, VacPageList fraged_pages, int nindices, Relation *Irel); static void vacuum_heap(VRelStats *vacrelstats, Relation onerel, VacPageList vacpagelist); @@ -235,7 +235,7 @@ vac_vacuum(NameData *VacRelP, bool analyze, List *anal_cols2) /* vacuum each heap relation */ for (cur = vrl; cur != (VRelList) NULL; cur = cur->vrl_next) { - vacuum_rel(cur->vrl_relid, analyze); + vacuum_rel(cur->vrl_relid, analyze, false); /* analyze separately so locking is minimized */ if (analyze) analyze_rel(cur->vrl_relid, anal_cols2, MESSAGE_LEVEL); @@ -347,7 +347,7 @@ getrels(NameData *VacRelP) * us to lock the entire database during one pass of the vacuum cleaner. */ static void -vacuum_rel(Oid relid, bool analyze) +vacuum_rel(Oid relid, bool analyze, bool is_toastrel) { HeapTuple tuple; Relation onerel; @@ -361,8 +361,10 @@ vacuum_rel(Oid relid, bool analyze) i; VRelStats *vacrelstats; bool reindex = false; + Oid toast_relid; - StartTransactionCommand(); + if (!is_toastrel) + StartTransactionCommand(); /* * Check for user-requested abort. Note we want this to be inside a @@ -380,7 +382,8 @@ vacuum_rel(Oid relid, bool analyze) 0, 0, 0); if (!HeapTupleIsValid(tuple)) { - CommitTransactionCommand(); + if (!is_toastrel) + CommitTransactionCommand(); return; } @@ -392,6 +395,12 @@ vacuum_rel(Oid relid, bool analyze) */ onerel = heap_open(relid, AccessExclusiveLock); + /* + * Remember the relations TOAST relation for later + * + */ + toast_relid = onerel->rd_rel->reltoastrelid; + #ifndef NO_SECURITY if (!pg_ownercheck(GetPgUserName(), RelationGetRelationName(onerel), RELNAME)) @@ -399,7 +408,8 @@ vacuum_rel(Oid relid, bool analyze) elog(NOTICE, "Skipping \"%s\" --- only table owner can VACUUM it", RelationGetRelationName(onerel)); heap_close(onerel, AccessExclusiveLock); - CommitTransactionCommand(); + if (!is_toastrel) + CommitTransactionCommand(); return; } #endif @@ -488,8 +498,18 @@ vacuum_rel(Oid relid, bool analyze) update_relstats(vacrelstats->relid, vacrelstats->num_pages, vacrelstats->num_tuples, vacrelstats->hasindex, vacrelstats); + /* If the relation has a secondary toast one, vacuum that too + * while we still hold the lock on the master table. We don't + * need to propagate "analyze" to it, because the toaster + * allways uses hardcoded index access and statistics are + * totally unimportant for toast relations + */ + if (toast_relid != InvalidOid) + vacuum_rel(toast_relid, false, true); + /* next command frees attribute stats */ - CommitTransactionCommand(); + if (!is_toastrel) + CommitTransactionCommand(); } /* diff --git a/src/backend/executor/execMain.c b/src/backend/executor/execMain.c index c707315081..6f161d95c0 100644 --- a/src/backend/executor/execMain.c +++ b/src/backend/executor/execMain.c @@ -27,7 +27,7 @@ * * * IDENTIFICATION - * $Header: /cvsroot/pgsql/src/backend/executor/execMain.c,v 1.120 2000/07/05 13:22:25 wieck Exp $ + * $Header: /cvsroot/pgsql/src/backend/executor/execMain.c,v 1.121 2000/07/05 16:17:43 wieck Exp $ * *------------------------------------------------------------------------- */ @@ -720,6 +720,10 @@ InitPlan(CmdType operation, Query *parseTree, Plan *plan, EState *estate) elog(ERROR, "You can't change sequence relation %s", RelationGetRelationName(resultRelationDesc)); + if (resultRelationDesc->rd_rel->relkind == RELKIND_TOASTVALUE) + elog(ERROR, "You can't change toast relation %s", + RelationGetRelationName(resultRelationDesc)); + resultRelationInfo = makeNode(RelationInfo); resultRelationInfo->ri_RangeTableIndex = resultRelationIndex; resultRelationInfo->ri_RelationDesc = resultRelationDesc;