aboutsummaryrefslogtreecommitdiff
path: root/src/backend
diff options
context:
space:
mode:
Diffstat (limited to 'src/backend')
-rw-r--r--src/backend/access/common/tupdesc.c5
-rw-r--r--src/backend/bootstrap/bootstrap.c3
-rw-r--r--src/backend/catalog/heap.c18
-rw-r--r--src/backend/catalog/index.c3
-rw-r--r--src/backend/commands/analyze.c10
-rw-r--r--src/backend/commands/tablecmds.c116
-rw-r--r--src/backend/parser/gram.y11
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
{