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:
parent
f2dfd5616c
commit
030962da26
@ -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);
|
||||
}
|
||||
|
||||
|
@ -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");
|
||||
|
@ -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
|
||||
|
Loading…
x
Reference in New Issue
Block a user