diff --git a/src/backend/commands/command.c b/src/backend/commands/command.c index 19c8710429..bb77fdf11f 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.83 2000/07/04 06:11:27 tgl Exp $ + * $Header: /cvsroot/pgsql/src/backend/commands/Attic/command.c,v 1.84 2000/07/05 12:45:25 wieck Exp $ * * NOTES * The PerformAddAttribute() code, like most of the relation @@ -1177,21 +1177,23 @@ AlterTableDropConstraint(const char *relationName, * ALTER TABLE CREATE TOAST TABLE */ void -AlterTableCreateToastTable(const char *relationName) +AlterTableCreateToastTable(const char *relationName, bool silent) { Relation rel; Oid myrelid; HeapTuple reltup; + HeapTupleData classtuple; TupleDesc tupdesc; Form_pg_attribute *att; Relation class_rel; + Buffer buffer; Relation ridescs[Num_pg_class_indices]; Oid toast_relid; Oid toast_idxid; bool has_toastable_attrs = false; int i; - char toast_relname[NAMEDATALEN]; - char toast_idxname[NAMEDATALEN]; + char toast_relname[NAMEDATALEN + 1]; + char toast_idxname[NAMEDATALEN + 1]; Relation toast_rel; AttrNumber attNums[1]; Oid classObjectId[1]; @@ -1199,16 +1201,33 @@ AlterTableCreateToastTable(const char *relationName) /* * permissions checking. XXX exactly what is appropriate here? */ -/* - if (!allowSystemTableMods && IsSystemRelationName(relationName)) - elog(ERROR, "ALTER TABLE: relation \"%s\" is a system catalog", - relationName); -*/ #ifndef NO_SECURITY if (!pg_ownercheck(UserName, relationName, RELNAME)) elog(ERROR, "ALTER TABLE: permission denied"); #endif + /* + * lock the pg_class tuple for update + */ + reltup = SearchSysCacheTuple(RELNAME, PointerGetDatum(relationName), + 0, 0, 0); + + if (!HeapTupleIsValid(reltup)) + elog(ERROR, "ALTER TABLE: relation \"%s\" not found", + relationName); + class_rel = heap_openr(RelationRelationName, RowExclusiveLock); + 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); + /* * Grab an exclusive lock on the target table, which we will NOT * release until end of transaction. @@ -1231,22 +1250,24 @@ AlterTableCreateToastTable(const char *relationName) } if (!has_toastable_attrs) + { + if (silent) + { + heap_close(rel, NoLock); + heap_close(class_rel, NoLock); + return; + } + elog(ERROR, "ALTER TABLE: relation \"%s\" has no toastable attributes", relationName); + } + /* - * Get the pg_class tuple for the relation - */ - reltup = SearchSysCacheTuple(RELNAME, - PointerGetDatum(relationName), - 0, 0, 0); - - if (!HeapTupleIsValid(reltup)) - elog(ERROR, "ALTER TABLE: relation \"%s\" not found", - relationName); - - /* - * XXX is the following check sufficient? + * XXX is the following check sufficient? At least it would + * allow to create TOAST tables for views. But why not - someone + * can insert into a view, so it shouldn't be impossible to hide + * huge data there :-) */ if (((Form_pg_class) GETSTRUCT(reltup))->relkind != RELKIND_RELATION) { @@ -1281,6 +1302,8 @@ AlterTableCreateToastTable(const char *relationName) /* 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, false, true); @@ -1307,18 +1330,6 @@ AlterTableCreateToastTable(const char *relationName) toast_idxid = RelationGetRelid(toast_rel); index_close(toast_rel); - /* - * Get the pg_class tuple for the relation - */ - class_rel = heap_openr(RelationRelationName, RowExclusiveLock); - - reltup = SearchSysCacheTupleCopy(RELNAME, - PointerGetDatum(relationName), - 0, 0, 0); - if (!HeapTupleIsValid(reltup)) - elog(ERROR, "ALTER TABLE: relation \"%s\" not found", - relationName); - /* * Store the toast table- and index-Oid's in the relation tuple */ @@ -1326,14 +1337,16 @@ AlterTableCreateToastTable(const char *relationName) ((Form_pg_class) GETSTRUCT(reltup))->reltoastidxid = toast_idxid; heap_update(class_rel, &reltup->t_self, reltup, NULL); - /* keep catalog indices current */ + /* + * Keep catalog indices current + */ CatalogOpenIndices(Num_pg_class_indices, Name_pg_class_indices, ridescs); - CatalogIndexInsert(ridescs, Num_pg_class_indices, rel, reltup); + CatalogIndexInsert(ridescs, Num_pg_class_indices, class_rel, reltup); CatalogCloseIndices(Num_pg_class_indices, ridescs); heap_freetuple(reltup); - heap_close(class_rel, RowExclusiveLock); + heap_close(class_rel, NoLock); heap_close(rel, NoLock); } diff --git a/src/backend/tcop/utility.c b/src/backend/tcop/utility.c index 17c77da850..409aca70ad 100644 --- a/src/backend/tcop/utility.c +++ b/src/backend/tcop/utility.c @@ -10,7 +10,7 @@ * * * IDENTIFICATION - * $Header: /cvsroot/pgsql/src/backend/tcop/utility.c,v 1.90 2000/07/03 23:09:46 wieck Exp $ + * $Header: /cvsroot/pgsql/src/backend/tcop/utility.c,v 1.91 2000/07/05 12:45:26 wieck Exp $ * *------------------------------------------------------------------------- */ @@ -159,6 +159,15 @@ ProcessUtility(Node *parsetree, CHECK_IF_ABORTED(); DefineRelation((CreateStmt *) parsetree, RELKIND_RELATION); + + /* + * Let AlterTableCreateToastTable decide if this + * one needs a secondary relation too. + * + */ + CommandCounterIncrement(); + AlterTableCreateToastTable(((CreateStmt *)parsetree)->relname, + true); break; case T_DropStmt: @@ -361,7 +370,7 @@ ProcessUtility(Node *parsetree, AlterTableDropConstraint(stmt->relname, stmt->inh, stmt->name, stmt->behavior); break; case 'E': /* CREATE TOAST TABLE */ - AlterTableCreateToastTable(stmt->relname); + AlterTableCreateToastTable(stmt->relname, false); break; default: /* oops */ elog(ERROR, "T_AlterTableStmt: unknown subtype"); diff --git a/src/include/commands/command.h b/src/include/commands/command.h index e870126355..b2b3d6383f 100644 --- a/src/include/commands/command.h +++ b/src/include/commands/command.h @@ -7,7 +7,7 @@ * Portions Copyright (c) 1996-2000, PostgreSQL, Inc * Portions Copyright (c) 1994, Regents of the University of California * - * $Id: command.h,v 1.20 2000/07/03 23:10:10 wieck Exp $ + * $Id: command.h,v 1.21 2000/07/05 12:45:31 wieck Exp $ * *------------------------------------------------------------------------- */ @@ -58,7 +58,8 @@ extern void AlterTableDropConstraint(const char *relationName, bool inh, const char *constrName, int behavior); -extern void AlterTableCreateToastTable(const char *relationName); +extern void AlterTableCreateToastTable(const char *relationName, + bool silent); /* * LOCK