diff options
author | Jan Wieck <JanWieck@Yahoo.com> | 2000-07-03 23:10:14 +0000 |
---|---|---|
committer | Jan Wieck <JanWieck@Yahoo.com> | 2000-07-03 23:10:14 +0000 |
commit | 57d8080a40f51e1ff9eedea602e96e2612161d77 (patch) | |
tree | 6dbed1f7333436cb08af6e7c0d9c55ac5e064750 /src/backend/commands/command.c | |
parent | ef5bea51e17d36ab06e7e67847a8b1e489d6d189 (diff) | |
download | postgresql-57d8080a40f51e1ff9eedea602e96e2612161d77.tar.gz postgresql-57d8080a40f51e1ff9eedea602e96e2612161d77.zip |
TOAST
WARNING: This is actually broken - we have self-deadlocks
due to concurrent changes in buffer management.
Vadim and me are working on it.
Jan
Diffstat (limited to 'src/backend/commands/command.c')
-rw-r--r-- | src/backend/commands/command.c | 158 |
1 files changed, 156 insertions, 2 deletions
diff --git a/src/backend/commands/command.c b/src/backend/commands/command.c index d0bd89fdfd2..595c09dc4ec 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.81 2000/06/28 03:31:28 tgl Exp $ + * $Header: /cvsroot/pgsql/src/backend/commands/Attic/command.c,v 1.82 2000/07/03 23:09:33 wieck Exp $ * * NOTES * The PerformAddAttribute() code, like most of the relation @@ -35,6 +35,7 @@ #include "catalog/pg_index.h" #include "parser/parse.h" #endif /* _DROP_COLUMN_HACK__ */ +#include "access/genam.h" /* -------------------------------- @@ -438,7 +439,7 @@ AlterTableAddColumn(const char *relationName, attribute->attbyval = tform->typbyval; attribute->attnelems = attnelems; attribute->attisset = (bool) (tform->typtype == 'c'); - attribute->attstorage = 'p'; + attribute->attstorage = tform->typstorage; attribute->attalign = tform->typalign; attribute->attnotnull = false; attribute->atthasdef = (colDef->raw_default != NULL || @@ -1171,6 +1172,159 @@ AlterTableDropConstraint(const char *relationName, /* + * ALTER TABLE CREATE TOAST TABLE + */ +void +AlterTableCreateToastTable(const char *relationName) +{ + Relation rel; + Oid myrelid; + HeapTuple reltup; + TupleDesc tupdesc; + Form_pg_attribute *att; + Relation class_rel; + Relation ridescs[Num_pg_class_indices]; + Oid toast_relid = 2; + Oid toast_idxid = 2; + bool has_toastable_attrs = false; + bool old_allow; + int i; + + char toast_relname[NAMEDATALEN]; + char toast_idxname[NAMEDATALEN]; + char tmp_query[1024]; + Relation toast_rel; + + /* + * permissions checking. this would normally be done in utility.c, + * but this particular routine is recursive. + * + * normally, only the owner of a class can change its schema. + */ +/* + 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 + + /* + * Grab an exclusive lock on the target table, which we will NOT + * release until end of transaction. + */ + rel = heap_openr(relationName, RowExclusiveLock); + myrelid = RelationGetRelid(rel); + + /* + * Check if there are any toastable attributes on the table + */ + tupdesc = rel->rd_att; + att = tupdesc->attrs; + for (i = 0; i < tupdesc->natts; i++) + { + if (att[i]->attstorage != 'p') + { + has_toastable_attrs = true; + break; + } + } + + if (!has_toastable_attrs) + 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? + */ + if (((Form_pg_class) GETSTRUCT(reltup))->relkind != RELKIND_RELATION) + { + elog(ERROR, "ALTER TABLE: relation \"%s\" is not a table", + relationName); + } + + if (((Form_pg_class) GETSTRUCT(reltup))->reltoastrelid != InvalidOid) + elog(ERROR, "ALTER TABLE: relation \"%s\" already has a toast table", + relationName); + + /* + * Create the toast table and it's index + * This is bad and ugly, because we need to override + * allowSystemTableMods in order to keep the toast + * table- and index-name out of the users namespace. + */ + sprintf(toast_relname, "pg_toast_%d", myrelid); + sprintf(toast_idxname, "pg_toast_%d_idx", myrelid); + + old_allow = allowSystemTableMods; + allowSystemTableMods = true; + + sprintf(tmp_query, "create table \"%s\" (chunk_id oid, chunk_seq int4, chunk_data text)", + toast_relname); + pg_exec_query_dest(tmp_query, None, CurrentMemoryContext); + + sprintf(tmp_query, "create index \"%s\" on \"%s\" (chunk_id)", + toast_idxname, toast_relname); + pg_exec_query_dest(tmp_query, None, CurrentMemoryContext); + + allowSystemTableMods = old_allow; + + /* + * Get the OIDs of the newly created objects + */ + toast_rel = heap_openr(toast_relname, NoLock); + toast_relid = RelationGetRelid(toast_rel); + heap_close(toast_rel, NoLock); + toast_rel = index_openr(toast_idxname); + 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 + */ + ((Form_pg_class) GETSTRUCT(reltup))->reltoastrelid = toast_relid; + ((Form_pg_class) GETSTRUCT(reltup))->reltoastidxid = toast_idxid; + heap_update(class_rel, &reltup->t_self, reltup, NULL); + + /* keep catalog indices current */ + CatalogOpenIndices(Num_pg_class_indices, Name_pg_class_indices, ridescs); + CatalogIndexInsert(ridescs, Num_pg_class_indices, rel, reltup); + CatalogCloseIndices(Num_pg_class_indices, ridescs); + + heap_freetuple(reltup); + + heap_close(rel, NoLock); + heap_close(class_rel, NoLock); +} + + + +/* * * LOCK TABLE * |