diff options
author | Tom Lane <tgl@sss.pgh.pa.us> | 2009-08-02 22:14:53 +0000 |
---|---|---|
committer | Tom Lane <tgl@sss.pgh.pa.us> | 2009-08-02 22:14:53 +0000 |
commit | 90725929465474648de133d216b873bdb69fe357 (patch) | |
tree | 7285d55b3b98e6050d7bd035aacf25a20191d888 /src/backend/commands/tablecmds.c | |
parent | 527f0ae3fa48c3c3a8ba1bde19039545e88a52b6 (diff) | |
download | postgresql-90725929465474648de133d216b873bdb69fe357.tar.gz postgresql-90725929465474648de133d216b873bdb69fe357.zip |
Add ALTER TABLE ... ALTER COLUMN ... SET STATISTICS DISTINCT
Robert Haas
Diffstat (limited to 'src/backend/commands/tablecmds.c')
-rw-r--r-- | src/backend/commands/tablecmds.c | 116 |
1 files changed, 109 insertions, 7 deletions
diff --git a/src/backend/commands/tablecmds.c b/src/backend/commands/tablecmds.c index 53abfec6976..1f2d67bcb12 100644 --- a/src/backend/commands/tablecmds.c +++ b/src/backend/commands/tablecmds.c @@ -8,7 +8,7 @@ * * * IDENTIFICATION - * $PostgreSQL: pgsql/src/backend/commands/tablecmds.c,v 1.294 2009/07/30 02:45:36 tgl Exp $ + * $PostgreSQL: pgsql/src/backend/commands/tablecmds.c,v 1.295 2009/08/02 22:14:52 tgl Exp $ * *------------------------------------------------------------------------- */ @@ -280,9 +280,13 @@ static void ATExecSetNotNull(AlteredTableInfo *tab, Relation rel, static void ATExecColumnDefault(Relation rel, const char *colName, Node *newDefault); static void ATPrepSetStatistics(Relation rel, const char *colName, - Node *flagValue); + Node *newValue); static void ATExecSetStatistics(Relation rel, const char *colName, Node *newValue); +static void ATPrepSetDistinct(Relation rel, const char *colName, + Node *newValue); +static void ATExecSetDistinct(Relation rel, const char *colName, + Node *newValue); static void ATExecSetStorage(Relation rel, const char *colName, Node *newValue); static void ATExecDropColumn(List **wqueue, Relation rel, const char *colName, @@ -2399,13 +2403,19 @@ ATPrepCmd(List **wqueue, Relation rel, AlterTableCmd *cmd, /* No command-specific prep needed */ pass = AT_PASS_ADD_CONSTR; break; - case AT_SetStatistics: /* ALTER COLUMN STATISTICS */ + case AT_SetStatistics: /* ALTER COLUMN SET STATISTICS */ ATSimpleRecursion(wqueue, rel, cmd, recurse); /* Performs own permission checks */ ATPrepSetStatistics(rel, cmd->name, cmd->def); pass = AT_PASS_COL_ATTRS; break; - case AT_SetStorage: /* ALTER COLUMN STORAGE */ + case AT_SetDistinct: /* ALTER COLUMN SET STATISTICS DISTINCT */ + ATSimpleRecursion(wqueue, rel, cmd, recurse); + /* Performs own permission checks */ + ATPrepSetDistinct(rel, cmd->name, cmd->def); + pass = AT_PASS_COL_ATTRS; + break; + case AT_SetStorage: /* ALTER COLUMN SET STORAGE */ ATSimplePermissions(rel, false); ATSimpleRecursion(wqueue, rel, cmd, recurse); /* No command-specific prep needed */ @@ -2616,10 +2626,13 @@ ATExecCmd(List **wqueue, AlteredTableInfo *tab, Relation rel, case AT_SetNotNull: /* ALTER COLUMN SET NOT NULL */ ATExecSetNotNull(tab, rel, cmd->name); break; - case AT_SetStatistics: /* ALTER COLUMN STATISTICS */ + case AT_SetStatistics: /* ALTER COLUMN SET STATISTICS */ ATExecSetStatistics(rel, cmd->name, cmd->def); break; - case AT_SetStorage: /* ALTER COLUMN STORAGE */ + case AT_SetDistinct: /* ALTER COLUMN SET STATISTICS DISTINCT */ + ATExecSetDistinct(rel, cmd->name, cmd->def); + break; + case AT_SetStorage: /* ALTER COLUMN SET STORAGE */ ATExecSetStorage(rel, cmd->name, cmd->def); break; case AT_DropColumn: /* DROP COLUMN */ @@ -3620,6 +3633,7 @@ ATExecAddColumn(AlteredTableInfo *tab, Relation rel, namestrcpy(&(attribute.attname), colDef->colname); attribute.atttypid = typeOid; attribute.attstattarget = (newattnum > 0) ? -1 : 0; + attribute.attdistinct = 0; attribute.attlen = tform->typlen; attribute.attcacheoff = -1; attribute.atttypmod = typmod; @@ -4007,7 +4021,7 @@ ATExecColumnDefault(Relation rel, const char *colName, * ALTER TABLE ALTER COLUMN SET STATISTICS */ static void -ATPrepSetStatistics(Relation rel, const char *colName, Node *flagValue) +ATPrepSetStatistics(Relation rel, const char *colName, Node *newValue) { /* * We do our own permission checking because (a) we want to allow SET @@ -4088,6 +4102,94 @@ ATExecSetStatistics(Relation rel, const char *colName, Node *newValue) } /* + * ALTER TABLE ALTER COLUMN SET STATISTICS DISTINCT + */ +static void +ATPrepSetDistinct(Relation rel, const char *colName, Node *newValue) +{ + /* + * We do our own permission checking because (a) we want to allow SET + * DISTINCT on indexes (for expressional index columns), and (b) we want + * to allow SET DISTINCT on system catalogs without requiring + * allowSystemTableMods to be turned on. + */ + if (rel->rd_rel->relkind != RELKIND_RELATION && + rel->rd_rel->relkind != RELKIND_INDEX) + ereport(ERROR, + (errcode(ERRCODE_WRONG_OBJECT_TYPE), + errmsg("\"%s\" is not a table or index", + RelationGetRelationName(rel)))); + + /* Permissions checks */ + if (!pg_class_ownercheck(RelationGetRelid(rel), GetUserId())) + aclcheck_error(ACLCHECK_NOT_OWNER, ACL_KIND_CLASS, + RelationGetRelationName(rel)); +} + +static void +ATExecSetDistinct(Relation rel, const char *colName, Node *newValue) +{ + float4 newdistinct; + Relation attrelation; + HeapTuple tuple; + Form_pg_attribute attrtuple; + + switch (nodeTag(newValue)) + { + case T_Integer: + newdistinct = intVal(newValue); + break; + case T_Float: + newdistinct = floatVal(newValue); + break; + default: + elog(ERROR, "unrecognized node type: %d", + (int) nodeTag(newValue)); + newdistinct = 0; /* keep compiler quiet */ + break; + } + + /* + * Limit ndistinct to sane values + */ + if (newdistinct < -1.0) + { + ereport(ERROR, + (errcode(ERRCODE_INVALID_PARAMETER_VALUE), + errmsg("number of distinct values %g is too low", + newdistinct))); + } + + attrelation = heap_open(AttributeRelationId, RowExclusiveLock); + + tuple = SearchSysCacheCopyAttName(RelationGetRelid(rel), colName); + + if (!HeapTupleIsValid(tuple)) + ereport(ERROR, + (errcode(ERRCODE_UNDEFINED_COLUMN), + errmsg("column \"%s\" of relation \"%s\" does not exist", + colName, RelationGetRelationName(rel)))); + attrtuple = (Form_pg_attribute) GETSTRUCT(tuple); + + if (attrtuple->attnum <= 0) + ereport(ERROR, + (errcode(ERRCODE_FEATURE_NOT_SUPPORTED), + errmsg("cannot alter system column \"%s\"", + colName))); + + attrtuple->attdistinct = newdistinct; + + simple_heap_update(attrelation, &tuple->t_self, tuple); + + /* keep system catalog indexes current */ + CatalogUpdateIndexes(attrelation, tuple); + + heap_freetuple(tuple); + + heap_close(attrelation, RowExclusiveLock); +} + +/* * ALTER TABLE ALTER COLUMN SET STORAGE */ static void |