mirror of
https://github.com/postgres/postgres.git
synced 2025-11-12 05:01:15 +03:00
Add ALTER TABLE ... ALTER COLUMN ... SET STATISTICS DISTINCT
Robert Haas
This commit is contained in:
@@ -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;
|
||||
|
||||
|
||||
@@ -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;
|
||||
|
||||
@@ -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);
|
||||
|
||||
@@ -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;
|
||||
|
||||
@@ -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);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -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
|
||||
@@ -4087,6 +4101,94 @@ ATExecSetStatistics(Relation rel, const char *colName, Node *newValue)
|
||||
heap_close(attrelation, RowExclusiveLock);
|
||||
}
|
||||
|
||||
/*
|
||||
* 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
|
||||
*/
|
||||
|
||||
@@ -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
|
||||
{
|
||||
|
||||
Reference in New Issue
Block a user