diff options
Diffstat (limited to 'src/backend')
-rw-r--r-- | src/backend/access/common/tupdesc.c | 5 | ||||
-rw-r--r-- | src/backend/bootstrap/bootstrap.c | 3 | ||||
-rw-r--r-- | src/backend/catalog/heap.c | 18 | ||||
-rw-r--r-- | src/backend/catalog/index.c | 3 | ||||
-rw-r--r-- | src/backend/commands/analyze.c | 10 | ||||
-rw-r--r-- | src/backend/commands/tablecmds.c | 116 | ||||
-rw-r--r-- | src/backend/parser/gram.y | 11 |
7 files changed, 146 insertions, 20 deletions
diff --git a/src/backend/access/common/tupdesc.c b/src/backend/access/common/tupdesc.c index 0bd50318f6c..9c561beed19 100644 --- a/src/backend/access/common/tupdesc.c +++ b/src/backend/access/common/tupdesc.c @@ -8,7 +8,7 @@ * * * IDENTIFICATION - * $PostgreSQL: pgsql/src/backend/access/common/tupdesc.c,v 1.127 2009/07/16 06:33:42 petere Exp $ + * $PostgreSQL: pgsql/src/backend/access/common/tupdesc.c,v 1.128 2009/08/02 22:14:51 tgl Exp $ * * NOTES * some of the executor utility code such as "ExecTypeFromTL" should be @@ -338,6 +338,8 @@ equalTupleDescs(TupleDesc tupdesc1, TupleDesc tupdesc2) return false; if (attr1->attstattarget != attr2->attstattarget) return false; + if (attr1->attdistinct != attr2->attdistinct) + return false; if (attr1->attlen != attr2->attlen) return false; if (attr1->attndims != attr2->attndims) @@ -465,6 +467,7 @@ TupleDescInitEntry(TupleDesc desc, MemSet(NameStr(att->attname), 0, NAMEDATALEN); att->attstattarget = -1; + att->attdistinct = 0; att->attcacheoff = -1; att->atttypmod = typmod; diff --git a/src/backend/bootstrap/bootstrap.c b/src/backend/bootstrap/bootstrap.c index ff31e5f040e..ac560ee298d 100644 --- a/src/backend/bootstrap/bootstrap.c +++ b/src/backend/bootstrap/bootstrap.c @@ -8,7 +8,7 @@ * Portions Copyright (c) 1994, Regents of the University of California * * IDENTIFICATION - * $PostgreSQL: pgsql/src/backend/bootstrap/bootstrap.c,v 1.251 2009/07/31 20:26:22 tgl Exp $ + * $PostgreSQL: pgsql/src/backend/bootstrap/bootstrap.c,v 1.252 2009/08/02 22:14:51 tgl Exp $ * *------------------------------------------------------------------------- */ @@ -757,6 +757,7 @@ DefineAttr(char *name, char *type, int attnum) } attrtypes[attnum]->attstattarget = -1; + attrtypes[attnum]->attdistinct = 0; attrtypes[attnum]->attcacheoff = -1; attrtypes[attnum]->atttypmod = -1; attrtypes[attnum]->attislocal = true; diff --git a/src/backend/catalog/heap.c b/src/backend/catalog/heap.c index 478583a742f..01084553682 100644 --- a/src/backend/catalog/heap.c +++ b/src/backend/catalog/heap.c @@ -8,7 +8,7 @@ * * * IDENTIFICATION - * $PostgreSQL: pgsql/src/backend/catalog/heap.c,v 1.356 2009/07/30 02:45:36 tgl Exp $ + * $PostgreSQL: pgsql/src/backend/catalog/heap.c,v 1.357 2009/08/02 22:14:52 tgl Exp $ * * * INTERFACE ROUTINES @@ -111,37 +111,37 @@ static List *insert_ordered_unique_oid(List *list, Oid datum); */ static FormData_pg_attribute a1 = { - 0, {"ctid"}, TIDOID, 0, sizeof(ItemPointerData), + 0, {"ctid"}, TIDOID, 0, 0, sizeof(ItemPointerData), SelfItemPointerAttributeNumber, 0, -1, -1, false, 'p', 's', true, false, false, true, 0, {0} }; static FormData_pg_attribute a2 = { - 0, {"oid"}, OIDOID, 0, sizeof(Oid), + 0, {"oid"}, OIDOID, 0, 0, sizeof(Oid), ObjectIdAttributeNumber, 0, -1, -1, true, 'p', 'i', true, false, false, true, 0, {0} }; static FormData_pg_attribute a3 = { - 0, {"xmin"}, XIDOID, 0, sizeof(TransactionId), + 0, {"xmin"}, XIDOID, 0, 0, sizeof(TransactionId), MinTransactionIdAttributeNumber, 0, -1, -1, true, 'p', 'i', true, false, false, true, 0, {0} }; static FormData_pg_attribute a4 = { - 0, {"cmin"}, CIDOID, 0, sizeof(CommandId), + 0, {"cmin"}, CIDOID, 0, 0, sizeof(CommandId), MinCommandIdAttributeNumber, 0, -1, -1, true, 'p', 'i', true, false, false, true, 0, {0} }; static FormData_pg_attribute a5 = { - 0, {"xmax"}, XIDOID, 0, sizeof(TransactionId), + 0, {"xmax"}, XIDOID, 0, 0, sizeof(TransactionId), MaxTransactionIdAttributeNumber, 0, -1, -1, true, 'p', 'i', true, false, false, true, 0, {0} }; static FormData_pg_attribute a6 = { - 0, {"cmax"}, CIDOID, 0, sizeof(CommandId), + 0, {"cmax"}, CIDOID, 0, 0, sizeof(CommandId), MaxCommandIdAttributeNumber, 0, -1, -1, true, 'p', 'i', true, false, false, true, 0, {0} }; @@ -153,7 +153,7 @@ static FormData_pg_attribute a6 = { * used in SQL. */ static FormData_pg_attribute a7 = { - 0, {"tableoid"}, OIDOID, 0, sizeof(Oid), + 0, {"tableoid"}, OIDOID, 0, 0, sizeof(Oid), TableOidAttributeNumber, 0, -1, -1, true, 'p', 'i', true, false, false, true, 0, {0} }; @@ -501,6 +501,7 @@ InsertPgAttributeTuple(Relation pg_attribute_rel, values[Anum_pg_attribute_attname - 1] = NameGetDatum(&new_attribute->attname); values[Anum_pg_attribute_atttypid - 1] = ObjectIdGetDatum(new_attribute->atttypid); values[Anum_pg_attribute_attstattarget - 1] = Int32GetDatum(new_attribute->attstattarget); + values[Anum_pg_attribute_attdistinct - 1] = Float4GetDatum(new_attribute->attdistinct); values[Anum_pg_attribute_attlen - 1] = Int16GetDatum(new_attribute->attlen); values[Anum_pg_attribute_attnum - 1] = Int16GetDatum(new_attribute->attnum); values[Anum_pg_attribute_attndims - 1] = Int32GetDatum(new_attribute->attndims); @@ -571,6 +572,7 @@ AddNewAttributeTuples(Oid new_rel_oid, attr->attrelid = new_rel_oid; /* Make sure these are OK, too */ attr->attstattarget = -1; + attr->attdistinct = 0; attr->attcacheoff = -1; InsertPgAttributeTuple(rel, attr, indstate); diff --git a/src/backend/catalog/index.c b/src/backend/catalog/index.c index 73472d1568e..759950b2265 100644 --- a/src/backend/catalog/index.c +++ b/src/backend/catalog/index.c @@ -8,7 +8,7 @@ * * * IDENTIFICATION - * $PostgreSQL: pgsql/src/backend/catalog/index.c,v 1.320 2009/07/29 20:56:18 tgl Exp $ + * $PostgreSQL: pgsql/src/backend/catalog/index.c,v 1.321 2009/08/02 22:14:52 tgl Exp $ * * * INTERFACE ROUTINES @@ -192,6 +192,7 @@ ConstructTupleDescriptor(Relation heapRelation, to->attnum = i + 1; to->attstattarget = -1; + to->attdistinct = 0; to->attcacheoff = -1; to->attnotnull = false; to->atthasdef = false; diff --git a/src/backend/commands/analyze.c b/src/backend/commands/analyze.c index f5e76e2aedd..2a90eeaad93 100644 --- a/src/backend/commands/analyze.c +++ b/src/backend/commands/analyze.c @@ -8,7 +8,7 @@ * * * IDENTIFICATION - * $PostgreSQL: pgsql/src/backend/commands/analyze.c,v 1.139 2009/06/11 14:48:55 momjian Exp $ + * $PostgreSQL: pgsql/src/backend/commands/analyze.c,v 1.140 2009/08/02 22:14:52 tgl Exp $ * *------------------------------------------------------------------------- */ @@ -425,6 +425,11 @@ analyze_rel(Oid relid, VacuumStmt *vacstmt, std_fetch_func, numrows, totalrows); + + /* If attdistinct is set, override with that value */ + if (stats->attr->attdistinct != 0) + stats->stadistinct = stats->attr->attdistinct; + MemoryContextResetAndDeleteChildren(col_context); } @@ -679,6 +684,9 @@ compute_index_stats(Relation onerel, double totalrows, ind_fetch_func, numindexrows, totalindexrows); + /* If attdistinct is set, override with that value */ + if (stats->attr->attdistinct != 0) + stats->stadistinct = stats->attr->attdistinct; MemoryContextResetAndDeleteChildren(col_context); } } 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 diff --git a/src/backend/parser/gram.y b/src/backend/parser/gram.y index 543aea99283..6e52d3bcbd3 100644 --- a/src/backend/parser/gram.y +++ b/src/backend/parser/gram.y @@ -11,7 +11,7 @@ * * * IDENTIFICATION - * $PostgreSQL: pgsql/src/backend/parser/gram.y,v 2.675 2009/07/30 02:45:37 tgl Exp $ + * $PostgreSQL: pgsql/src/backend/parser/gram.y,v 2.676 2009/08/02 22:14:52 tgl Exp $ * * HISTORY * AUTHOR DATE MAJOR EVENT @@ -1605,6 +1605,15 @@ alter_table_cmd: n->def = (Node *) makeInteger($6); $$ = (Node *)n; } + /* ALTER TABLE <name> ALTER [COLUMN] <colname> SET STATISTICS DISTINCT <NumericOnly> */ + | ALTER opt_column ColId SET STATISTICS DISTINCT NumericOnly + { + AlterTableCmd *n = makeNode(AlterTableCmd); + n->subtype = AT_SetDistinct; + n->name = $3; + n->def = (Node *) $7; + $$ = (Node *)n; + } /* ALTER TABLE <name> ALTER [COLUMN] <colname> SET STORAGE <storagemode> */ | ALTER opt_column ColId SET STORAGE ColId { |