-<!-- $PostgreSQL: pgsql/doc/src/sgml/catalogs.sgml,v 2.218 2010/01/17 22:56:21 tgl Exp $ -->
+<!-- $PostgreSQL: pgsql/doc/src/sgml/catalogs.sgml,v 2.219 2010/01/22 16:40:18 rhaas Exp $ -->
<!--
Documentation of the system catalogs, directed toward PostgreSQL developers
-->
</entry>
</row>
- <row>
- <entry><structfield>attdistinct</structfield></entry>
- <entry><type>float4</type></entry>
- <entry></entry>
- <entry>
- <structfield>attdistinct</structfield>, if nonzero, is a user-specified
- number-of-distinct-values figure to be used instead of estimating the
- number of distinct values during <command>ANALYZE</>. Nonzero values
- have the same meanings as for
- <link linkend="catalog-pg-statistic"><structname>pg_statistic</></link>.<structfield>stadistinct</>
- </entry>
- </row>
-
<row>
<entry><structfield>attlen</structfield></entry>
<entry><type>int2</type></entry>
</entry>
</row>
+ <row>
+ <entry><structfield>attoptions</structfield></entry>
+ <entry><type>text[]</type></entry>
+ <entry></entry>
+ <entry>
+ Attribute-level options, as <quote>keyword=value</> strings
+ </entry>
+ </row>
+
</tbody>
</tgroup>
</table>
<!--
-$PostgreSQL: pgsql/doc/src/sgml/ref/alter_table.sgml,v 1.109 2009/09/18 05:00:41 petere Exp $
+$PostgreSQL: pgsql/doc/src/sgml/ref/alter_table.sgml,v 1.110 2010/01/22 16:40:18 rhaas Exp $
PostgreSQL documentation
-->
ALTER [ COLUMN ] <replaceable class="PARAMETER">column</replaceable> DROP DEFAULT
ALTER [ COLUMN ] <replaceable class="PARAMETER">column</replaceable> { SET | DROP } NOT NULL
ALTER [ COLUMN ] <replaceable class="PARAMETER">column</replaceable> SET STATISTICS <replaceable class="PARAMETER">integer</replaceable>
- ALTER [ COLUMN ] <replaceable class="PARAMETER">column</replaceable> SET STATISTICS DISTINCT <replaceable class="PARAMETER">number</replaceable>
+ ALTER [ COLUMN ] <replaceable class="PARAMETER">column</replaceable> SET ( <replaceable class="PARAMETER">attribute_option</replaceable> = <replaceable class="PARAMETER">value</replaceable> [, ... ] )
+ ALTER [ COLUMN ] <replaceable class="PARAMETER">column</replaceable> RESET ( <replaceable class="PARAMETER">attribute_option</replaceable> [, ... ] )
ALTER [ COLUMN ] <replaceable class="PARAMETER">column</replaceable> SET STORAGE { PLAIN | EXTERNAL | EXTENDED | MAIN }
ADD <replaceable class="PARAMETER">table_constraint</replaceable>
DROP CONSTRAINT [ IF EXISTS ] <replaceable class="PARAMETER">constraint_name</replaceable> [ RESTRICT | CASCADE ]
</varlistentry>
<varlistentry>
- <term><literal>SET STATISTICS DISTINCT</literal></term>
+ <term><literal>SET ( <replaceable class="PARAMETER">attribute_option</replaceable> = <replaceable class="PARAMETER">value</replaceable> [, ... ] )</term></literal>
+ <term><literal>RESET ( <replaceable class="PARAMETER">attribute_option</replaceable> [, ... ] )</literal>
<listitem>
<para>
- This form overrides the number-of-distinct-values estimate made by
- subsequent <xref linkend="sql-analyze" endterm="sql-analyze-title">
- operations. When set to a positive value, <command>ANALYZE</> will
- assume that the column contains exactly the specified number of distinct
- nonnull values. When set to a negative value, which must be greater
+ This form sets or resets attribute-level options. Currently, the only
+ define attribute-level options are <literal>n_distinct</> and
+ <literal>n_distinct_inherited</>, which override the
+ number-of-distinct-values estimate made by subsequent
+ <xref linkend="sql-analyze" endterm="sql-analyze-title">
+ operations. <literal>n_distinct</> affects the statistics for the table
+ itself, while <literal>n_distinct_inherited</> affects the statistics
+ gathered for the table and its inheritance children. When set to a
+ positive value, <command>ANALYZE</> will assume that the column contains
+ exactly the specified number of distinct nonnull values. When set to a
+ negative value, which must be greater
than or equal to -1, <command>ANALYZE</> will assume that the number of
distinct nonnull values in the column is linear in the size of the
table; the exact count is to be computed by multiplying the estimated
<!--
-$PostgreSQL: pgsql/doc/src/sgml/ref/analyze.sgml,v 1.27 2009/08/04 22:04:37 petere Exp $
+$PostgreSQL: pgsql/doc/src/sgml/ref/analyze.sgml,v 1.28 2010/01/22 16:40:18 rhaas Exp $
PostgreSQL documentation
-->
with the largest possible statistics target. If this inaccuracy leads to
bad query plans, a more accurate value can be determined manually and then
installed with
- <command>ALTER TABLE ... ALTER COLUMN ... SET STATISTICS DISTINCT</>
+ <command>ALTER TABLE ... ALTER COLUMN ... SET (n_distinct = ...)</>
(see <xref linkend="sql-altertable" endterm="sql-altertable-title">).
</para>
</refsect1>
*
*
* IDENTIFICATION
- * $PostgreSQL: pgsql/src/backend/access/common/reloptions.c,v 1.31 2010/01/05 21:53:58 rhaas Exp $
+ * $PostgreSQL: pgsql/src/backend/access/common/reloptions.c,v 1.32 2010/01/22 16:40:18 rhaas Exp $
*
*-------------------------------------------------------------------------
*/
#include "commands/tablespace.h"
#include "nodes/makefuncs.h"
#include "utils/array.h"
+#include "utils/attoptcache.h"
#include "utils/builtins.h"
#include "utils/guc.h"
#include "utils/memutils.h"
},
-1, 0.0, DBL_MAX
},
+ {
+ {
+ "n_distinct",
+ "Sets the planner's estimate of the number of distinct values appearing in a column (excluding child relations).",
+ RELOPT_KIND_ATTRIBUTE
+ },
+ 0, -1.0, DBL_MAX
+ },
+ {
+ {
+ "n_distinct_inherited",
+ "Sets the planner's estimate of the number of distinct values appearing in a column (including child relations).",
+ RELOPT_KIND_ATTRIBUTE
+ },
+ 0, -1.0, DBL_MAX
+ },
/* list terminator */
{{NULL}}
};
return DatumGetByteaP(result);
}
+/*
+ * Option parser for attribute reloptions
+ */
+bytea *
+attribute_reloptions(Datum reloptions, bool validate)
+{
+ relopt_value *options;
+ AttributeOpts *aopts;
+ int numoptions;
+ static const relopt_parse_elt tab[] = {
+ {"n_distinct", RELOPT_TYPE_REAL, offsetof(AttributeOpts, n_distinct)},
+ {"n_distinct_inherited", RELOPT_TYPE_REAL, offsetof(AttributeOpts, n_distinct_inherited)}
+ };
+
+ options = parseRelOptions(reloptions, validate, RELOPT_KIND_ATTRIBUTE,
+ &numoptions);
+
+ /* if none set, we're done */
+ if (numoptions == 0)
+ return NULL;
+
+ aopts = allocateReloptStruct(sizeof(AttributeOpts), options, numoptions);
+
+ fillRelOptions((void *) aopts, sizeof(AttributeOpts), options, numoptions,
+ validate, tab, lengthof(tab));
+
+ pfree(options);
+
+ return (bytea *) aopts;
+}
+
/*
* Option parser for tablespace reloptions
*/
*
*
* IDENTIFICATION
- * $PostgreSQL: pgsql/src/backend/access/common/tupdesc.c,v 1.131 2010/01/02 16:57:33 momjian Exp $
+ * $PostgreSQL: pgsql/src/backend/access/common/tupdesc.c,v 1.132 2010/01/22 16:40:18 rhaas Exp $
*
* NOTES
* some of the executor utility code such as "ExecTypeFromTL" should be
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)
return false;
if (attr1->attinhcount != attr2->attinhcount)
return false;
- /* attacl is ignored, since it's not even present... */
+ /* attacl and attoptions are not even present... */
}
if (tupdesc1->constr != NULL)
MemSet(NameStr(att->attname), 0, NAMEDATALEN);
att->attstattarget = -1;
- att->attdistinct = 0;
att->attcacheoff = -1;
att->atttypmod = typmod;
att->attisdropped = false;
att->attislocal = true;
att->attinhcount = 0;
- /* attacl is not set because it's not present in tupledescs */
+ /* attacl and attoptions are not present in tupledescs */
tuple = SearchSysCache(TYPEOID,
ObjectIdGetDatum(oidtypeid),
* Portions Copyright (c) 1994, Regents of the University of California
*
* IDENTIFICATION
- * $PostgreSQL: pgsql/src/backend/bootstrap/bootstrap.c,v 1.257 2010/01/20 09:16:23 heikki Exp $
+ * $PostgreSQL: pgsql/src/backend/bootstrap/bootstrap.c,v 1.258 2010/01/22 16:40:18 rhaas Exp $
*
*-------------------------------------------------------------------------
*/
}
attrtypes[attnum]->attstattarget = -1;
- attrtypes[attnum]->attdistinct = 0;
attrtypes[attnum]->attcacheoff = -1;
attrtypes[attnum]->atttypmod = -1;
attrtypes[attnum]->attislocal = true;
# Portions Copyright (c) 1996-2010, PostgreSQL Global Development Group
# Portions Copyright (c) 1994, Regents of the University of California
#
-# $PostgreSQL: pgsql/src/backend/catalog/genbki.pl,v 1.6 2010/01/06 22:02:45 tgl Exp $
+# $PostgreSQL: pgsql/src/backend/catalog/genbki.pl,v 1.7 2010/01/22 16:40:18 rhaas Exp $
#
#----------------------------------------------------------------------
# Store schemapg entries for later.
$row = emit_schemapg_row($row, grep { $bki_attr{$_} eq 'bool' } @attnames);
push @{ $schemapg_entries{$table_name} },
- '{ ' . join(', ', map $row->{$_}, @attnames) . ' }';
+ '{ ' . join(', ', grep { defined $_ }
+ map $row->{$_}, @attnames) . ' }';
}
# Generate entries for system attributes.
# Add in default values for pg_attribute
my %PGATTR_DEFAULTS = (
- attdistinct => '0',
attcacheoff => '-1',
atttypmod => '-1',
atthasdef => 'f',
attisdropped => 'f',
attislocal => 't',
attinhcount => '0',
- attacl => '_null_'
+ attacl => '_null_',
+ attoptions => '_null_'
);
return {%PGATTR_DEFAULTS, %row};
}
$row->{attname} = q|{"| . $row->{attname} . q|"}|;
$row->{attstorage} = q|'| . $row->{attstorage} . q|'|;
$row->{attalign} = q|'| . $row->{attalign} . q|'|;
- $row->{attacl} = q|{ 0 }|;
+
+ # We don't emit initializers for the variable length fields at all.
+ # Only the fixed-size portions of the descriptors are ever used.
+ delete $row->{attacl};
+ delete $row->{attoptions};
# Expand booleans from 'f'/'t' to 'false'/'true'.
# Some values might be other macros (eg FLOAT4PASSBYVAL), don't change.
*
*
* IDENTIFICATION
- * $PostgreSQL: pgsql/src/backend/catalog/heap.c,v 1.366 2010/01/06 05:18:18 momjian Exp $
+ * $PostgreSQL: pgsql/src/backend/catalog/heap.c,v 1.367 2010/01/22 16:40:18 rhaas Exp $
*
*
* INTERFACE ROUTINES
* Disadvantage: special cases will be all over the place.
*/
+/*
+ * The initializers below do not include the attoptions or attacl fields,
+ * but that's OK - we're never going to reference anything beyond the
+ * fixed-size portion of the structure anyway.
+ */
+
static FormData_pg_attribute a1 = {
- 0, {"ctid"}, TIDOID, 0, 0, sizeof(ItemPointerData),
+ 0, {"ctid"}, TIDOID, 0, sizeof(ItemPointerData),
SelfItemPointerAttributeNumber, 0, -1, -1,
- false, 'p', 's', true, false, false, true, 0, {0}
+ false, 'p', 's', true, false, false, true, 0
};
static FormData_pg_attribute a2 = {
- 0, {"oid"}, OIDOID, 0, 0, sizeof(Oid),
+ 0, {"oid"}, OIDOID, 0, sizeof(Oid),
ObjectIdAttributeNumber, 0, -1, -1,
- true, 'p', 'i', true, false, false, true, 0, {0}
+ true, 'p', 'i', true, false, false, true, 0
};
static FormData_pg_attribute a3 = {
- 0, {"xmin"}, XIDOID, 0, 0, sizeof(TransactionId),
+ 0, {"xmin"}, XIDOID, 0, sizeof(TransactionId),
MinTransactionIdAttributeNumber, 0, -1, -1,
- true, 'p', 'i', true, false, false, true, 0, {0}
+ true, 'p', 'i', true, false, false, true, 0
};
static FormData_pg_attribute a4 = {
- 0, {"cmin"}, CIDOID, 0, 0, sizeof(CommandId),
+ 0, {"cmin"}, CIDOID, 0, sizeof(CommandId),
MinCommandIdAttributeNumber, 0, -1, -1,
- true, 'p', 'i', true, false, false, true, 0, {0}
+ true, 'p', 'i', true, false, false, true, 0
};
static FormData_pg_attribute a5 = {
- 0, {"xmax"}, XIDOID, 0, 0, sizeof(TransactionId),
+ 0, {"xmax"}, XIDOID, 0, sizeof(TransactionId),
MaxTransactionIdAttributeNumber, 0, -1, -1,
- true, 'p', 'i', true, false, false, true, 0, {0}
+ true, 'p', 'i', true, false, false, true, 0
};
static FormData_pg_attribute a6 = {
- 0, {"cmax"}, CIDOID, 0, 0, sizeof(CommandId),
+ 0, {"cmax"}, CIDOID, 0, sizeof(CommandId),
MaxCommandIdAttributeNumber, 0, -1, -1,
- true, 'p', 'i', true, false, false, true, 0, {0}
+ true, 'p', 'i', true, false, false, true, 0
};
/*
* used in SQL.
*/
static FormData_pg_attribute a7 = {
- 0, {"tableoid"}, OIDOID, 0, 0, sizeof(Oid),
+ 0, {"tableoid"}, OIDOID, 0, sizeof(Oid),
TableOidAttributeNumber, 0, -1, -1,
- true, 'p', 'i', true, false, false, true, 0, {0}
+ true, 'p', 'i', true, false, false, true, 0
};
static const Form_pg_attribute SysAtt[] = {&a1, &a2, &a3, &a4, &a5, &a6, &a7};
* Construct and insert a new tuple in pg_attribute.
*
* Caller has already opened and locked pg_attribute. new_attribute is the
- * attribute to insert (but we ignore its attacl, if indeed it has one).
+ * attribute to insert (but we ignore attacl and attoptions, which are always
+ * initialized to NULL).
*
* indstate is the index state for CatalogIndexInsert. It can be passed as
* NULL, in which case we'll fetch the necessary info. (Don't do this when
* inserting multiple attributes, because it's a tad more expensive.)
- *
- * We always initialize attacl to NULL (i.e., default permissions).
*/
void
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);
values[Anum_pg_attribute_attislocal - 1] = BoolGetDatum(new_attribute->attislocal);
values[Anum_pg_attribute_attinhcount - 1] = Int32GetDatum(new_attribute->attinhcount);
- /* start out with empty permissions */
+ /* start out with empty permissions and empty options */
nulls[Anum_pg_attribute_attacl - 1] = true;
+ nulls[Anum_pg_attribute_attoptions - 1] = true;
tup = heap_form_tuple(RelationGetDescr(pg_attribute_rel), values, nulls);
attr->attrelid = new_rel_oid;
/* Make sure these are OK, too */
attr->attstattarget = -1;
- attr->attdistinct = 0;
attr->attcacheoff = -1;
InsertPgAttributeTuple(rel, attr, indstate);
*
*
* IDENTIFICATION
- * $PostgreSQL: pgsql/src/backend/catalog/index.c,v 1.330 2010/01/17 22:56:21 tgl Exp $
+ * $PostgreSQL: pgsql/src/backend/catalog/index.c,v 1.331 2010/01/22 16:40:18 rhaas Exp $
*
*
* INTERFACE ROUTINES
to->attnum = i + 1;
to->attstattarget = -1;
- to->attdistinct = 0;
to->attcacheoff = -1;
to->attnotnull = false;
to->atthasdef = false;
*
*
* IDENTIFICATION
- * $PostgreSQL: pgsql/src/backend/commands/analyze.c,v 1.147 2010/01/02 16:57:36 momjian Exp $
+ * $PostgreSQL: pgsql/src/backend/commands/analyze.c,v 1.148 2010/01/22 16:40:18 rhaas Exp $
*
*-------------------------------------------------------------------------
*/
#include "storage/proc.h"
#include "storage/procarray.h"
#include "utils/acl.h"
+#include "utils/attoptcache.h"
#include "utils/datum.h"
#include "utils/guc.h"
#include "utils/lsyscache.h"
for (i = 0; i < attr_cnt; i++)
{
VacAttrStats *stats = vacattrstats[i];
+ AttributeOpts *aopt =
+ get_attribute_options(onerel->rd_id, stats->attr->attnum);
stats->rows = rows;
stats->tupDesc = onerel->rd_att;
numrows,
totalrows);
- /* If attdistinct is set, override with that value */
- if (stats->attr->attdistinct != 0)
- stats->stadistinct = stats->attr->attdistinct;
+ /*
+ * If the appropriate flavor of the n_distinct option is
+ * specified, override with the corresponding value.
+ */
+ if (aopt != NULL)
+ {
+ float8 n_distinct =
+ inh ? aopt->n_distinct_inherited : aopt->n_distinct;
+ if (n_distinct != 0.0)
+ stats->stadistinct = n_distinct;
+ }
MemoryContextResetAndDeleteChildren(col_context);
}
for (i = 0; i < attr_cnt; i++)
{
VacAttrStats *stats = thisdata->vacattrstats[i];
+ AttributeOpts *aopt =
+ get_attribute_options(stats->attr->attrelid,
+ stats->attr->attnum);
stats->exprvals = exprvals + i;
stats->exprnulls = exprnulls + i;
ind_fetch_func,
numindexrows,
totalindexrows);
- /* If attdistinct is set, override with that value */
- if (stats->attr->attdistinct != 0)
- stats->stadistinct = stats->attr->attdistinct;
+
+ /*
+ * If the n_distinct option is specified, it overrides the
+ * above computation. For indices, we always use just
+ * n_distinct, not n_distinct_inherited.
+ */
+ if (aopt != NULL && aopt->n_distinct != 0.0)
+ stats->stadistinct = aopt->n_distinct;
+
MemoryContextResetAndDeleteChildren(col_context);
}
}
*
*
* IDENTIFICATION
- * $PostgreSQL: pgsql/src/backend/commands/tablecmds.c,v 1.317 2010/01/20 19:43:40 heikki Exp $
+ * $PostgreSQL: pgsql/src/backend/commands/tablecmds.c,v 1.318 2010/01/22 16:40:18 rhaas Exp $
*
*-------------------------------------------------------------------------
*/
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 ATExecSetOptions(Relation rel, const char *colName,
+ Node *options, bool isReset);
static void ATExecSetStorage(Relation rel, const char *colName,
Node *newValue);
static void ATExecDropColumn(List **wqueue, Relation rel, const char *colName,
ATPrepSetStatistics(rel, cmd->name, cmd->def);
pass = AT_PASS_COL_ATTRS;
break;
- case AT_SetDistinct: /* ALTER COLUMN SET STATISTICS DISTINCT */
- ATSimpleRecursion(wqueue, rel, cmd, recurse);
- /* Performs own permission checks */
- ATPrepSetDistinct(rel, cmd->name, cmd->def);
+ case AT_SetOptions: /* ALTER COLUMN SET ( options ) */
+ case AT_ResetOptions: /* ALTER COLUMN RESET ( options ) */
+ ATSimplePermissionsRelationOrIndex(rel);
+ /* This command never recurses */
pass = AT_PASS_COL_ATTRS;
break;
case AT_SetStorage: /* ALTER COLUMN SET STORAGE */
case AT_SetStatistics: /* ALTER COLUMN SET STATISTICS */
ATExecSetStatistics(rel, cmd->name, cmd->def);
break;
- case AT_SetDistinct: /* ALTER COLUMN SET STATISTICS DISTINCT */
- ATExecSetDistinct(rel, cmd->name, cmd->def);
+ case AT_SetOptions: /* ALTER COLUMN SET ( options ) */
+ ATExecSetOptions(rel, cmd->name, cmd->def, false);
+ break;
+ case AT_ResetOptions: /* ALTER COLUMN RESET ( options ) */
+ ATExecSetOptions(rel, cmd->name, cmd->def, true);
break;
case AT_SetStorage: /* ALTER COLUMN SET STORAGE */
ATExecSetStorage(rel, cmd->name, cmd->def);
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;
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)
+ATExecSetOptions(Relation rel, const char *colName, Node *options,
+ bool isReset)
{
- float4 newdistinct;
Relation attrelation;
- HeapTuple tuple;
+ HeapTuple tuple,
+ newtuple;
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)));
- }
+ Datum datum,
+ newOptions;
+ bool isnull;
+ Datum repl_val[Natts_pg_attribute];
+ bool repl_null[Natts_pg_attribute];
+ bool repl_repl[Natts_pg_attribute];
attrelation = heap_open(AttributeRelationId, RowExclusiveLock);
- tuple = SearchSysCacheCopyAttName(RelationGetRelid(rel), colName);
+ tuple = SearchSysCacheAttName(RelationGetRelid(rel), colName);
if (!HeapTupleIsValid(tuple))
ereport(ERROR,
errmsg("cannot alter system column \"%s\"",
colName)));
- attrtuple->attdistinct = newdistinct;
-
- simple_heap_update(attrelation, &tuple->t_self, tuple);
+ /* Generate new proposed attoptions (text array) */
+ Assert(IsA(options, List));
+ datum = SysCacheGetAttr(ATTNAME, tuple, Anum_pg_attribute_attoptions,
+ &isnull);
+ newOptions = transformRelOptions(isnull ? (Datum) 0 : datum,
+ (List *) options, NULL, NULL, false,
+ isReset);
+ /* Validate new options */
+ (void) attribute_reloptions(newOptions, true);
- /* keep system catalog indexes current */
- CatalogUpdateIndexes(attrelation, tuple);
+ /* Build new tuple. */
+ memset(repl_null, false, sizeof(repl_null));
+ memset(repl_repl, false, sizeof(repl_repl));
+ if (newOptions != (Datum) 0)
+ repl_val[Anum_pg_attribute_attoptions - 1] = newOptions;
+ else
+ repl_null[Anum_pg_attribute_attoptions - 1] = true;
+ repl_repl[Anum_pg_attribute_attoptions - 1] = true;
+ newtuple = heap_modify_tuple(tuple, RelationGetDescr(attrelation),
+ repl_val, repl_null, repl_repl);
+ ReleaseSysCache(tuple);
- heap_freetuple(tuple);
+ /* Update system catalog. */
+ simple_heap_update(attrelation, &newtuple->t_self, newtuple);
+ CatalogUpdateIndexes(attrelation, newtuple);
+ heap_freetuple(newtuple);
heap_close(attrelation, RowExclusiveLock);
}
*
*
* IDENTIFICATION
- * $PostgreSQL: pgsql/src/backend/parser/gram.y,v 2.703 2010/01/06 05:31:13 itagaki Exp $
+ * $PostgreSQL: pgsql/src/backend/parser/gram.y,v 2.704 2010/01/22 16:40:18 rhaas Exp $
*
* HISTORY
* AUTHOR DATE MAJOR EVENT
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
+ /* ALTER TABLE <name> ALTER [COLUMN] <colname> SET ( column_parameter = value [, ... ] ) */
+ | ALTER opt_column ColId SET reloptions
{
AlterTableCmd *n = makeNode(AlterTableCmd);
- n->subtype = AT_SetDistinct;
+ n->subtype = AT_SetOptions;
n->name = $3;
- n->def = (Node *) $7;
+ n->def = (Node *) $5;
+ $$ = (Node *)n;
+ }
+ /* ALTER TABLE <name> ALTER [COLUMN] <colname> SET ( column_parameter = value [, ... ] ) */
+ | ALTER opt_column ColId RESET reloptions
+ {
+ AlterTableCmd *n = makeNode(AlterTableCmd);
+ n->subtype = AT_ResetOptions;
+ n->name = $3;
+ n->def = (Node *) $5;
$$ = (Node *)n;
}
/* ALTER TABLE <name> ALTER [COLUMN] <colname> SET STORAGE <storagemode> */
# Makefile for utils/cache
#
# IDENTIFICATION
-# $PostgreSQL: pgsql/src/backend/utils/cache/Makefile,v 1.24 2010/01/05 21:53:59 rhaas Exp $
+# $PostgreSQL: pgsql/src/backend/utils/cache/Makefile,v 1.25 2010/01/22 16:40:19 rhaas Exp $
#
#-------------------------------------------------------------------------
top_builddir = ../../../..
include $(top_builddir)/src/Makefile.global
-OBJS = catcache.o inval.o plancache.o relcache.o \
+OBJS = attoptcache.o catcache.o inval.o plancache.o relcache.o \
spccache.o syscache.o lsyscache.o typcache.o ts_cache.o
include $(top_srcdir)/src/backend/common.mk
* by PostgreSQL
*
* IDENTIFICATION
- * $PostgreSQL: pgsql/src/bin/pg_dump/pg_dump.c,v 1.567 2010/01/17 22:56:22 tgl Exp $
+ * $PostgreSQL: pgsql/src/bin/pg_dump/pg_dump.c,v 1.568 2010/01/22 16:40:19 rhaas Exp $
*
*-------------------------------------------------------------------------
*/
int i_atttypname;
int i_atttypmod;
int i_attstattarget;
- int i_attdistinct;
int i_attstorage;
int i_typstorage;
int i_attnotnull;
int i_attlen;
int i_attalign;
int i_attislocal;
+ int i_attoptions;
PGresult *res;
int ntups;
bool hasdefaults;
if (g_fout->remoteVersion >= 80500)
{
- /* attdistinct is new in 8.5 */
+ /* attoptions is new in 8.5 */
appendPQExpBuffer(q, "SELECT a.attnum, a.attname, a.atttypmod, "
- "a.attstattarget, a.attdistinct, "
- "a.attstorage, t.typstorage, "
+ "a.attstattarget, a.attstorage, t.typstorage, "
"a.attnotnull, a.atthasdef, a.attisdropped, "
"a.attlen, a.attalign, a.attislocal, "
- "pg_catalog.format_type(t.oid,a.atttypmod) AS atttypname "
+ "pg_catalog.format_type(t.oid,a.atttypmod) AS atttypname, "
+ "array_to_string(attoptions, ', ') AS attoptions "
"FROM pg_catalog.pg_attribute a LEFT JOIN pg_catalog.pg_type t "
"ON a.atttypid = t.oid "
"WHERE a.attrelid = '%u'::pg_catalog.oid "
{
/* need left join here to not fail on dropped columns ... */
appendPQExpBuffer(q, "SELECT a.attnum, a.attname, a.atttypmod, "
- "a.attstattarget, 0 AS attdistinct, "
- "a.attstorage, t.typstorage, "
+ "a.attstattarget, a.attstorage, t.typstorage, "
"a.attnotnull, a.atthasdef, a.attisdropped, "
"a.attlen, a.attalign, a.attislocal, "
- "pg_catalog.format_type(t.oid,a.atttypmod) AS atttypname "
+ "pg_catalog.format_type(t.oid,a.atttypmod) AS atttypname, "
+ "'' AS attoptions "
"FROM pg_catalog.pg_attribute a LEFT JOIN pg_catalog.pg_type t "
"ON a.atttypid = t.oid "
"WHERE a.attrelid = '%u'::pg_catalog.oid "
* explicitly set or was just a default.
*/
appendPQExpBuffer(q, "SELECT a.attnum, a.attname, a.atttypmod, "
- "-1 AS attstattarget, 0 AS attdistinct, "
- "a.attstorage, "
+ "-1 AS attstattarget, a.attstorage, "
"t.typstorage, a.attnotnull, a.atthasdef, "
"false AS attisdropped, a.attlen, "
"a.attalign, false AS attislocal, "
- "format_type(t.oid,a.atttypmod) AS atttypname "
+ "format_type(t.oid,a.atttypmod) AS atttypname, "
+ "'' AS attoptions "
"FROM pg_attribute a LEFT JOIN pg_type t "
"ON a.atttypid = t.oid "
"WHERE a.attrelid = '%u'::oid "
{
/* format_type not available before 7.1 */
appendPQExpBuffer(q, "SELECT attnum, attname, atttypmod, "
- "-1 AS attstattarget, 0 AS attdistinct, "
+ "-1 AS attstattarget, "
"attstorage, attstorage AS typstorage, "
"attnotnull, atthasdef, false AS attisdropped, "
"attlen, attalign, "
"false AS attislocal, "
- "(SELECT typname FROM pg_type WHERE oid = atttypid) AS atttypname "
+ "(SELECT typname FROM pg_type WHERE oid = atttypid) AS atttypname, "
+ "'' AS attoptions "
"FROM pg_attribute a "
"WHERE attrelid = '%u'::oid "
"AND attnum > 0::int2 "
i_atttypname = PQfnumber(res, "atttypname");
i_atttypmod = PQfnumber(res, "atttypmod");
i_attstattarget = PQfnumber(res, "attstattarget");
- i_attdistinct = PQfnumber(res, "attdistinct");
i_attstorage = PQfnumber(res, "attstorage");
i_typstorage = PQfnumber(res, "typstorage");
i_attnotnull = PQfnumber(res, "attnotnull");
i_attlen = PQfnumber(res, "attlen");
i_attalign = PQfnumber(res, "attalign");
i_attislocal = PQfnumber(res, "attislocal");
+ i_attoptions = PQfnumber(res, "attoptions");
tbinfo->numatts = ntups;
tbinfo->attnames = (char **) malloc(ntups * sizeof(char *));
tbinfo->atttypnames = (char **) malloc(ntups * sizeof(char *));
tbinfo->atttypmod = (int *) malloc(ntups * sizeof(int));
tbinfo->attstattarget = (int *) malloc(ntups * sizeof(int));
- tbinfo->attdistinct = (float4 *) malloc(ntups * sizeof(float4));
tbinfo->attstorage = (char *) malloc(ntups * sizeof(char));
tbinfo->typstorage = (char *) malloc(ntups * sizeof(char));
tbinfo->attisdropped = (bool *) malloc(ntups * sizeof(bool));
tbinfo->attislocal = (bool *) malloc(ntups * sizeof(bool));
tbinfo->notnull = (bool *) malloc(ntups * sizeof(bool));
tbinfo->attrdefs = (AttrDefInfo **) malloc(ntups * sizeof(AttrDefInfo *));
+ tbinfo->attoptions = (char **) malloc(ntups * sizeof(char *));
tbinfo->inhAttrs = (bool *) malloc(ntups * sizeof(bool));
tbinfo->inhAttrDef = (bool *) malloc(ntups * sizeof(bool));
tbinfo->inhNotNull = (bool *) malloc(ntups * sizeof(bool));
tbinfo->atttypnames[j] = strdup(PQgetvalue(res, j, i_atttypname));
tbinfo->atttypmod[j] = atoi(PQgetvalue(res, j, i_atttypmod));
tbinfo->attstattarget[j] = atoi(PQgetvalue(res, j, i_attstattarget));
- tbinfo->attdistinct[j] = strtod(PQgetvalue(res, j, i_attdistinct),
- (char **) NULL);
tbinfo->attstorage[j] = *(PQgetvalue(res, j, i_attstorage));
tbinfo->typstorage[j] = *(PQgetvalue(res, j, i_typstorage));
tbinfo->attisdropped[j] = (PQgetvalue(res, j, i_attisdropped)[0] == 't');
tbinfo->attalign[j] = *(PQgetvalue(res, j, i_attalign));
tbinfo->attislocal[j] = (PQgetvalue(res, j, i_attislocal)[0] == 't');
tbinfo->notnull[j] = (PQgetvalue(res, j, i_attnotnull)[0] == 't');
+ tbinfo->attoptions[j] = strdup(PQgetvalue(res, j, i_attoptions));
tbinfo->attrdefs[j] = NULL; /* fix below */
if (PQgetvalue(res, j, i_atthasdef)[0] == 't')
hasdefaults = true;
tbinfo->attstattarget[j]);
}
- /*
- * Dump per-column ndistinct information. We only issue an ALTER
- * TABLE statement if the attdistinct entry for this column is
- * non-zero (i.e. it's not the default value)
- */
- if (tbinfo->attdistinct[j] != 0 &&
- !tbinfo->attisdropped[j])
- {
- appendPQExpBuffer(q, "ALTER TABLE ONLY %s ",
- fmtId(tbinfo->dobj.name));
- appendPQExpBuffer(q, "ALTER COLUMN %s ",
- fmtId(tbinfo->attnames[j]));
- appendPQExpBuffer(q, "SET STATISTICS DISTINCT %g;\n",
- tbinfo->attdistinct[j]);
- }
-
/*
* Dump per-column storage information. The statement is only
* dumped if the storage has been changed from the type's default.
storage);
}
}
+
+ /*
+ * Dump per-column attributes.
+ */
+ if (tbinfo->attoptions[j] && tbinfo->attoptions[j][0] != '\0')
+ {
+ appendPQExpBuffer(q, "ALTER TABLE ONLY %s ",
+ fmtId(tbinfo->dobj.name));
+ appendPQExpBuffer(q, "ALTER COLUMN %s ",
+ fmtId(tbinfo->attnames[j]));
+ appendPQExpBuffer(q, "SET (%s);\n",
+ tbinfo->attoptions[j]);
+ }
}
}
* Portions Copyright (c) 1996-2010, PostgreSQL Global Development Group
* Portions Copyright (c) 1994, Regents of the University of California
*
- * $PostgreSQL: pgsql/src/bin/pg_dump/pg_dump.h,v 1.160 2010/01/02 16:57:59 momjian Exp $
+ * $PostgreSQL: pgsql/src/bin/pg_dump/pg_dump.h,v 1.161 2010/01/22 16:40:19 rhaas Exp $
*
*-------------------------------------------------------------------------
*/
char **atttypnames; /* attribute type names */
int *atttypmod; /* type-specific type modifiers */
int *attstattarget; /* attribute statistics targets */
- float4 *attdistinct; /* override ndistinct calculation */
char *attstorage; /* attribute storage scheme */
char *typstorage; /* type storage scheme */
bool *attisdropped; /* true if attr is dropped; don't dump it */
int *attlen; /* attribute length, used by binary_upgrade */
char *attalign; /* attribute align, used by binary_upgrade */
bool *attislocal; /* true if attr has local definition */
+ char **attoptions; /* per-attribute options */
/*
* Note: we need to store per-attribute notnull, default, and constraint
*
* Copyright (c) 2000-2010, PostgreSQL Global Development Group
*
- * $PostgreSQL: pgsql/src/bin/psql/tab-complete.c,v 1.190 2010/01/02 21:28:46 tgl Exp $
+ * $PostgreSQL: pgsql/src/bin/psql/tab-complete.c,v 1.191 2010/01/22 16:40:19 rhaas Exp $
*/
/*----------------------------------------------------------------------
COMPLETE_WITH_LIST(list_COLUMNSET);
}
- else if (((pg_strcasecmp(prev5_wd, "ALTER") == 0 &&
- pg_strcasecmp(prev4_wd, "COLUMN") == 0) ||
- pg_strcasecmp(prev4_wd, "ALTER") == 0) &&
- pg_strcasecmp(prev2_wd, "SET") == 0 &&
- pg_strcasecmp(prev_wd, "STATISTICS") == 0)
- {
- static const char *const list_COLUMNSETSTATS[] =
- {"DISTINCT", NULL};
-
- COMPLETE_WITH_LIST(list_COLUMNSETSTATS);
- }
else if (((pg_strcasecmp(prev4_wd, "ALTER") == 0 &&
pg_strcasecmp(prev3_wd, "COLUMN") == 0) ||
(pg_strcasecmp(prev5_wd, "TABLE") == 0 &&
* Portions Copyright (c) 1996-2010, PostgreSQL Global Development Group
* Portions Copyright (c) 1994, Regents of the University of California
*
- * $PostgreSQL: pgsql/src/include/access/reloptions.h,v 1.18 2010/01/05 21:53:59 rhaas Exp $
+ * $PostgreSQL: pgsql/src/include/access/reloptions.h,v 1.19 2010/01/22 16:40:19 rhaas Exp $
*
*-------------------------------------------------------------------------
*/
RELOPT_KIND_HASH = (1 << 3),
RELOPT_KIND_GIN = (1 << 4),
RELOPT_KIND_GIST = (1 << 5),
- RELOPT_KIND_TABLESPACE = (1 << 6),
+ RELOPT_KIND_ATTRIBUTE = (1 << 6),
+ RELOPT_KIND_TABLESPACE = (1 << 7),
/* if you add a new kind, make sure you update "last_default" too */
RELOPT_KIND_LAST_DEFAULT = RELOPT_KIND_TABLESPACE,
/* some compilers treat enums as signed ints, so we can't use 1 << 31 */
extern bytea *heap_reloptions(char relkind, Datum reloptions, bool validate);
extern bytea *index_reloptions(RegProcedure amoptions, Datum reloptions,
bool validate);
+extern bytea *attribute_reloptions(Datum reloptions, bool validate);
extern bytea *tablespace_reloptions(Datum reloptions, bool validate);
#endif /* RELOPTIONS_H */
* Portions Copyright (c) 1996-2010, PostgreSQL Global Development Group
* Portions Copyright (c) 1994, Regents of the University of California
*
- * $PostgreSQL: pgsql/src/include/catalog/pg_attribute.h,v 1.157 2010/01/05 01:06:56 tgl Exp $
+ * $PostgreSQL: pgsql/src/include/catalog/pg_attribute.h,v 1.158 2010/01/22 16:40:19 rhaas Exp $
*
* NOTES
* the genbki.pl script reads this file and generates .bki
*/
int4 attstattarget;
- /*
- * attdistinct, if nonzero, is a user-specified ndistinct value to be used
- * instead of estimating the number of distinct values during ANALYZE.
- * Nonzero values have the same meanings as for pg_statistic.stadistinct.
- */
- float4 attdistinct;
-
/*
* attlen is a copy of the typlen field from pg_type for this attribute.
* See atttypid comments above.
/* Column-level access permissions */
aclitem attacl[1];
+
+ /* Column-level options */
+ text attoptions[1];
} FormData_pg_attribute;
/*
#define Anum_pg_attribute_attname 2
#define Anum_pg_attribute_atttypid 3
#define Anum_pg_attribute_attstattarget 4
-#define Anum_pg_attribute_attdistinct 5
-#define Anum_pg_attribute_attlen 6
-#define Anum_pg_attribute_attnum 7
-#define Anum_pg_attribute_attndims 8
-#define Anum_pg_attribute_attcacheoff 9
-#define Anum_pg_attribute_atttypmod 10
-#define Anum_pg_attribute_attbyval 11
-#define Anum_pg_attribute_attstorage 12
-#define Anum_pg_attribute_attalign 13
-#define Anum_pg_attribute_attnotnull 14
-#define Anum_pg_attribute_atthasdef 15
-#define Anum_pg_attribute_attisdropped 16
-#define Anum_pg_attribute_attislocal 17
-#define Anum_pg_attribute_attinhcount 18
-#define Anum_pg_attribute_attacl 19
+#define Anum_pg_attribute_attlen 5
+#define Anum_pg_attribute_attnum 6
+#define Anum_pg_attribute_attndims 7
+#define Anum_pg_attribute_attcacheoff 8
+#define Anum_pg_attribute_atttypmod 9
+#define Anum_pg_attribute_attbyval 10
+#define Anum_pg_attribute_attstorage 11
+#define Anum_pg_attribute_attalign 12
+#define Anum_pg_attribute_attnotnull 13
+#define Anum_pg_attribute_atthasdef 14
+#define Anum_pg_attribute_attisdropped 15
+#define Anum_pg_attribute_attislocal 16
+#define Anum_pg_attribute_attinhcount 17
+#define Anum_pg_attribute_attacl 18
+#define Anum_pg_attribute_attoptions 19
/* ----------------
* Portions Copyright (c) 1996-2010, PostgreSQL Global Development Group
* Portions Copyright (c) 1994, Regents of the University of California
*
- * $PostgreSQL: pgsql/src/include/nodes/parsenodes.h,v 1.425 2010/01/17 22:56:23 tgl Exp $
+ * $PostgreSQL: pgsql/src/include/nodes/parsenodes.h,v 1.426 2010/01/22 16:40:19 rhaas Exp $
*
*-------------------------------------------------------------------------
*/
AT_DropNotNull, /* alter column drop not null */
AT_SetNotNull, /* alter column set not null */
AT_SetStatistics, /* alter column set statistics */
- AT_SetDistinct, /* alter column set statistics distinct */
+ AT_SetOptions, /* alter column set ( options ) */
+ AT_ResetOptions, /* alter column reset ( options ) */
AT_SetStorage, /* alter column set storage */
AT_DropColumn, /* drop column */
AT_DropColumnRecurse, /* internal to commands/tablecmds.c */