Bugfix in ALTER TABLE CREATE TOAST TABLE

Automatically create toast table at CREATE TABLE if new table
has toastable attributes.

Jan
This commit is contained in:
Jan Wieck 2000-07-05 12:45:31 +00:00
parent f2dfd5616c
commit 030962da26
3 changed files with 63 additions and 40 deletions

View File

@ -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);
}

View File

@ -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");

View File

@ -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