mirror of
https://github.com/postgres/postgres.git
synced 2025-07-14 08:21:07 +03:00
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:
@ -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,
|
|||||||
* 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)
|
|||||||
/*
|
/*
|
||||||
* 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)
|
|||||||
}
|
}
|
||||||
|
|
||||||
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
|
* XXX is the following check sufficient? At least it would
|
||||||
*/
|
* allow to create TOAST tables for views. But why not - someone
|
||||||
reltup = SearchSysCacheTuple(RELNAME,
|
* can insert into a view, so it shouldn't be impossible to hide
|
||||||
PointerGetDatum(relationName),
|
* huge data there :-)
|
||||||
0, 0, 0);
|
|
||||||
|
|
||||||
if (!HeapTupleIsValid(reltup))
|
|
||||||
elog(ERROR, "ALTER TABLE: relation \"%s\" not found",
|
|
||||||
relationName);
|
|
||||||
|
|
||||||
/*
|
|
||||||
* XXX is the following check sufficient?
|
|
||||||
*/
|
*/
|
||||||
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)
|
|||||||
|
|
||||||
/* 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)
|
|||||||
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)
|
|||||||
((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 @@
|
|||||||
*
|
*
|
||||||
*
|
*
|
||||||
* 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,
|
|||||||
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,
|
|||||||
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 @@
|
|||||||
* 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,
|
|||||||
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
|
||||||
|
Reference in New Issue
Block a user