diff options
Diffstat (limited to 'src/backend/commands/command.c')
-rw-r--r-- | src/backend/commands/command.c | 128 |
1 files changed, 111 insertions, 17 deletions
diff --git a/src/backend/commands/command.c b/src/backend/commands/command.c index 96d493688e3..13a78f11773 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.125 2001/03/23 04:49:52 momjian Exp $ + * $Header: /cvsroot/pgsql/src/backend/commands/Attic/command.c,v 1.126 2001/05/07 00:43:17 tgl Exp $ * * NOTES * The PerformAddAttribute() code, like most of the relation @@ -56,6 +56,7 @@ #include "access/genam.h" +static void drop_default(Oid relid, int16 attnum); static bool needs_toast_table(Relation rel); static bool is_relation(char *name); @@ -408,7 +409,7 @@ AlterTableAddColumn(const char *relationName, HeapTuple typeTuple; Form_pg_type tform; char *typename; - int attnelems; + int attndims; if (SearchSysCacheExists(ATTNAME, ObjectIdGetDatum(reltup->t_data->t_oid), @@ -425,11 +426,11 @@ AlterTableAddColumn(const char *relationName, if (colDef->typename->arrayBounds) { - attnelems = length(colDef->typename->arrayBounds); + attndims = length(colDef->typename->arrayBounds); typename = makeArrayTypeName(colDef->typename->name); } else - attnelems = 0; + attndims = 0; typeTuple = SearchSysCache(TYPENAME, PointerGetDatum(typename), @@ -441,12 +442,12 @@ AlterTableAddColumn(const char *relationName, namestrcpy(&(attribute->attname), colDef->colname); attribute->atttypid = typeTuple->t_data->t_oid; attribute->attlen = tform->typlen; - attribute->attdispersion = 0; + attribute->attstattarget = DEFAULT_ATTSTATTARGET; attribute->attcacheoff = -1; attribute->atttypmod = colDef->typename->typmod; attribute->attnum = i; attribute->attbyval = tform->typbyval; - attribute->attnelems = attnelems; + attribute->attndims = attndims; attribute->attisset = (bool) (tform->typtype == 'c'); attribute->attstorage = tform->typstorage; attribute->attalign = tform->typalign; @@ -496,17 +497,13 @@ AlterTableAddColumn(const char *relationName, } - -static void drop_default(Oid relid, int16 attnum); - - /* * ALTER TABLE ALTER COLUMN SET/DROP DEFAULT */ void -AlterTableAlterColumn(const char *relationName, - bool inh, const char *colName, - Node *newDefault) +AlterTableAlterColumnDefault(const char *relationName, + bool inh, const char *colName, + Node *newDefault) { Relation rel; HeapTuple tuple; @@ -551,8 +548,8 @@ AlterTableAlterColumn(const char *relationName, if (childrelid == myrelid) continue; rel = heap_open(childrelid, AccessExclusiveLock); - AlterTableAlterColumn(RelationGetRelationName(rel), - false, colName, newDefault); + AlterTableAlterColumnDefault(RelationGetRelationName(rel), + false, colName, newDefault); heap_close(rel, AccessExclusiveLock); } } @@ -560,7 +557,7 @@ AlterTableAlterColumn(const char *relationName, /* -= now do the thing on this relation =- */ /* reopen the business */ - rel = heap_openr((char *) relationName, AccessExclusiveLock); + rel = heap_openr(relationName, AccessExclusiveLock); /* * get the number of the attribute @@ -647,7 +644,6 @@ AlterTableAlterColumn(const char *relationName, } - static void drop_default(Oid relid, int16 attnum) { @@ -675,6 +671,104 @@ drop_default(Oid relid, int16 attnum) } +/* + * ALTER TABLE ALTER COLUMN SET STATISTICS + */ +void +AlterTableAlterColumnStatistics(const char *relationName, + bool inh, const char *colName, + Node *statsTarget) +{ + Relation rel; + Oid myrelid; + int newtarget; + Relation attrelation; + HeapTuple tuple; + +#ifndef NO_SECURITY + if (!pg_ownercheck(GetUserId(), relationName, RELNAME)) + elog(ERROR, "ALTER TABLE: permission denied"); +#endif + + rel = heap_openr(relationName, AccessExclusiveLock); + if (rel->rd_rel->relkind != RELKIND_RELATION) + elog(ERROR, "ALTER TABLE: relation \"%s\" is not a table", + relationName); + myrelid = RelationGetRelid(rel); + heap_close(rel, NoLock); /* close rel, but keep lock! */ + + /* + * Propagate to children if desired + */ + if (inh) + { + List *child, + *children; + + /* this routine is actually in the planner */ + children = find_all_inheritors(myrelid); + + /* + * find_all_inheritors does the recursive search of the + * inheritance hierarchy, so all we have to do is process all of + * the relids in the list that it returns. + */ + foreach(child, children) + { + Oid childrelid = lfirsti(child); + + if (childrelid == myrelid) + continue; + rel = heap_open(childrelid, AccessExclusiveLock); + AlterTableAlterColumnStatistics(RelationGetRelationName(rel), + false, colName, statsTarget); + heap_close(rel, AccessExclusiveLock); + } + } + + /* -= now do the thing on this relation =- */ + + Assert(IsA(statsTarget, Integer)); + newtarget = intVal(statsTarget); + + /* Limit target to sane range (should we raise an error instead?) */ + if (newtarget < 0) + newtarget = 0; + else if (newtarget > 1000) + newtarget = 1000; + + attrelation = heap_openr(AttributeRelationName, RowExclusiveLock); + + tuple = SearchSysCacheCopy(ATTNAME, + ObjectIdGetDatum(myrelid), + PointerGetDatum(colName), + 0, 0); + if (!HeapTupleIsValid(tuple)) + elog(ERROR, "ALTER TABLE: relation \"%s\" has no column \"%s\"", + relationName, colName); + + if (((Form_pg_attribute) GETSTRUCT(tuple))->attnum < 0) + elog(ERROR, "ALTER TABLE: cannot change system attribute \"%s\"", + colName); + + ((Form_pg_attribute) GETSTRUCT(tuple))->attstattarget = newtarget; + + simple_heap_update(attrelation, &tuple->t_self, tuple); + + /* keep system catalog indices current */ + { + Relation irelations[Num_pg_attr_indices]; + + CatalogOpenIndices(Num_pg_attr_indices, Name_pg_attr_indices, irelations); + CatalogIndexInsert(irelations, Num_pg_attr_indices, attrelation, tuple); + CatalogCloseIndices(Num_pg_attr_indices, irelations); + } + + heap_freetuple(tuple); + heap_close(attrelation, RowExclusiveLock); +} + + #ifdef _DROP_COLUMN_HACK__ /* * ALTER TABLE DROP COLUMN trial implementation |