Commit 030962da authored by Jan Wieck's avatar Jan Wieck

Bugfix in ALTER TABLE CREATE TOAST TABLE

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

Jan
parent f2dfd561
...@@ -8,7 +8,7 @@ ...@@ -8,7 +8,7 @@
* *
* *
* IDENTIFICATION * 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 * NOTES
* The PerformAddAttribute() code, like most of the relation * The PerformAddAttribute() code, like most of the relation
...@@ -1177,21 +1177,23 @@ AlterTableDropConstraint(const char *relationName, ...@@ -1177,21 +1177,23 @@ AlterTableDropConstraint(const char *relationName,
* ALTER TABLE CREATE TOAST TABLE * ALTER TABLE CREATE TOAST TABLE
*/ */
void void
AlterTableCreateToastTable(const char *relationName) AlterTableCreateToastTable(const char *relationName, bool silent)
{ {
Relation rel; Relation rel;
Oid myrelid; Oid myrelid;
HeapTuple reltup; HeapTuple reltup;
HeapTupleData classtuple;
TupleDesc tupdesc; TupleDesc tupdesc;
Form_pg_attribute *att; Form_pg_attribute *att;
Relation class_rel; Relation class_rel;
Buffer buffer;
Relation ridescs[Num_pg_class_indices]; Relation ridescs[Num_pg_class_indices];
Oid toast_relid; Oid toast_relid;
Oid toast_idxid; Oid toast_idxid;
bool has_toastable_attrs = false; bool has_toastable_attrs = false;
int i; int i;
char toast_relname[NAMEDATALEN]; char toast_relname[NAMEDATALEN + 1];
char toast_idxname[NAMEDATALEN]; char toast_idxname[NAMEDATALEN + 1];
Relation toast_rel; Relation toast_rel;
AttrNumber attNums[1]; AttrNumber attNums[1];
Oid classObjectId[1]; Oid classObjectId[1];
...@@ -1199,16 +1201,33 @@ AlterTableCreateToastTable(const char *relationName) ...@@ -1199,16 +1201,33 @@ AlterTableCreateToastTable(const char *relationName)
/* /*
* permissions checking. XXX exactly what is appropriate here? * 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 #ifndef NO_SECURITY
if (!pg_ownercheck(UserName, relationName, RELNAME)) if (!pg_ownercheck(UserName, relationName, RELNAME))
elog(ERROR, "ALTER TABLE: permission denied"); elog(ERROR, "ALTER TABLE: permission denied");
#endif #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 * Grab an exclusive lock on the target table, which we will NOT
* release until end of transaction. * release until end of transaction.
...@@ -1231,22 +1250,24 @@ AlterTableCreateToastTable(const char *relationName) ...@@ -1231,22 +1250,24 @@ AlterTableCreateToastTable(const char *relationName)
} }
if (!has_toastable_attrs) 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", elog(ERROR, "ALTER TABLE: relation \"%s\" has no toastable attributes",
relationName); 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) if (((Form_pg_class) GETSTRUCT(reltup))->relkind != RELKIND_RELATION)
{ {
...@@ -1281,6 +1302,8 @@ AlterTableCreateToastTable(const char *relationName) ...@@ -1281,6 +1302,8 @@ AlterTableCreateToastTable(const char *relationName)
/* XXX use RELKIND_TOASTVALUE here? */ /* XXX use RELKIND_TOASTVALUE here? */
/* XXX what if owning relation is temp? need we mark toasttable too? */ /* 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, heap_create_with_catalog(toast_relname, tupdesc, RELKIND_RELATION,
false, true); false, true);
...@@ -1307,18 +1330,6 @@ AlterTableCreateToastTable(const char *relationName) ...@@ -1307,18 +1330,6 @@ AlterTableCreateToastTable(const char *relationName)
toast_idxid = RelationGetRelid(toast_rel); toast_idxid = RelationGetRelid(toast_rel);
index_close(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 * Store the toast table- and index-Oid's in the relation tuple
*/ */
...@@ -1326,14 +1337,16 @@ AlterTableCreateToastTable(const char *relationName) ...@@ -1326,14 +1337,16 @@ AlterTableCreateToastTable(const char *relationName)
((Form_pg_class) GETSTRUCT(reltup))->reltoastidxid = toast_idxid; ((Form_pg_class) GETSTRUCT(reltup))->reltoastidxid = toast_idxid;
heap_update(class_rel, &reltup->t_self, reltup, NULL); 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); 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); CatalogCloseIndices(Num_pg_class_indices, ridescs);
heap_freetuple(reltup); heap_freetuple(reltup);
heap_close(class_rel, RowExclusiveLock); heap_close(class_rel, NoLock);
heap_close(rel, NoLock); heap_close(rel, NoLock);
} }
......
...@@ -10,7 +10,7 @@ ...@@ -10,7 +10,7 @@
* *
* *
* IDENTIFICATION * 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, ...@@ -159,6 +159,15 @@ ProcessUtility(Node *parsetree,
CHECK_IF_ABORTED(); CHECK_IF_ABORTED();
DefineRelation((CreateStmt *) parsetree, RELKIND_RELATION); DefineRelation((CreateStmt *) parsetree, RELKIND_RELATION);
/*
* Let AlterTableCreateToastTable decide if this
* one needs a secondary relation too.
*
*/
CommandCounterIncrement();
AlterTableCreateToastTable(((CreateStmt *)parsetree)->relname,
true);
break; break;
case T_DropStmt: case T_DropStmt:
...@@ -361,7 +370,7 @@ ProcessUtility(Node *parsetree, ...@@ -361,7 +370,7 @@ ProcessUtility(Node *parsetree,
AlterTableDropConstraint(stmt->relname, stmt->inh, stmt->name, stmt->behavior); AlterTableDropConstraint(stmt->relname, stmt->inh, stmt->name, stmt->behavior);
break; break;
case 'E': /* CREATE TOAST TABLE */ case 'E': /* CREATE TOAST TABLE */
AlterTableCreateToastTable(stmt->relname); AlterTableCreateToastTable(stmt->relname, false);
break; break;
default: /* oops */ default: /* oops */
elog(ERROR, "T_AlterTableStmt: unknown subtype"); elog(ERROR, "T_AlterTableStmt: unknown subtype");
......
...@@ -7,7 +7,7 @@ ...@@ -7,7 +7,7 @@
* Portions Copyright (c) 1996-2000, PostgreSQL, Inc * Portions Copyright (c) 1996-2000, PostgreSQL, Inc
* Portions Copyright (c) 1994, Regents of the University of California * 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, ...@@ -58,7 +58,8 @@ extern void AlterTableDropConstraint(const char *relationName,
bool inh, const char *constrName, bool inh, const char *constrName,
int behavior); int behavior);
extern void AlterTableCreateToastTable(const char *relationName); extern void AlterTableCreateToastTable(const char *relationName,
bool silent);
/* /*
* LOCK * LOCK
......
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment