1
0
mirror of https://github.com/postgres/postgres.git synced 2025-04-25 21:42:33 +03:00

Make attstattarget nullable

This changes the pg_attribute field attstattarget into a nullable
field in the variable-length part of the row.  If no value is set by
the user for attstattarget, it is now null instead of previously -1.
This saves space in pg_attribute and tuple descriptors for most
practical scenarios.  (ATTRIBUTE_FIXED_PART_SIZE is reduced from 108
to 104.)  Also, null is the semantically more correct value.

The ANALYZE code internally continues to represent the default
statistics target by -1, so that that code can avoid having to deal
with null values.  But that is now contained to the ANALYZE code.
Only the DDL code deals with attstattarget possibly null.

For system columns, the field is now always null.  The ANALYZE code
skips system columns anyway.

To set a column's statistics target to the default value, the new
command form ALTER TABLE ... SET STATISTICS DEFAULT can be used.  (SET
STATISTICS -1 still works.)

Reviewed-by: Alvaro Herrera <alvherre@alvh.no-ip.org>
Discussion: https://www.postgresql.org/message-id/flat/4da8d211-d54d-44b9-9847-f2a9f1184c76@eisentraut.org
This commit is contained in:
Peter Eisentraut 2024-01-13 18:14:53 +01:00
parent 45da69371e
commit 4f622503d6
16 changed files with 115 additions and 89 deletions

View File

@ -51,7 +51,7 @@ ALTER TABLE [ IF EXISTS ] <replaceable class="parameter">name</replaceable>
ALTER [ COLUMN ] <replaceable class="parameter">column_name</replaceable> ADD GENERATED { ALWAYS | BY DEFAULT } AS IDENTITY [ ( <replaceable>sequence_options</replaceable> ) ] ALTER [ COLUMN ] <replaceable class="parameter">column_name</replaceable> ADD GENERATED { ALWAYS | BY DEFAULT } AS IDENTITY [ ( <replaceable>sequence_options</replaceable> ) ]
ALTER [ COLUMN ] <replaceable class="parameter">column_name</replaceable> { SET GENERATED { ALWAYS | BY DEFAULT } | SET <replaceable>sequence_option</replaceable> | RESTART [ [ WITH ] <replaceable class="parameter">restart</replaceable> ] } [...] ALTER [ COLUMN ] <replaceable class="parameter">column_name</replaceable> { SET GENERATED { ALWAYS | BY DEFAULT } | SET <replaceable>sequence_option</replaceable> | RESTART [ [ WITH ] <replaceable class="parameter">restart</replaceable> ] } [...]
ALTER [ COLUMN ] <replaceable class="parameter">column_name</replaceable> DROP IDENTITY [ IF EXISTS ] ALTER [ COLUMN ] <replaceable class="parameter">column_name</replaceable> DROP IDENTITY [ IF EXISTS ]
ALTER [ COLUMN ] <replaceable class="parameter">column_name</replaceable> SET STATISTICS <replaceable class="parameter">integer</replaceable> ALTER [ COLUMN ] <replaceable class="parameter">column_name</replaceable> SET STATISTICS { <replaceable class="parameter">integer</replaceable> | DEFAULT }
ALTER [ COLUMN ] <replaceable class="parameter">column_name</replaceable> SET ( <replaceable class="parameter">attribute_option</replaceable> = <replaceable class="parameter">value</replaceable> [, ... ] ) ALTER [ COLUMN ] <replaceable class="parameter">column_name</replaceable> SET ( <replaceable class="parameter">attribute_option</replaceable> = <replaceable class="parameter">value</replaceable> [, ... ] )
ALTER [ COLUMN ] <replaceable class="parameter">column_name</replaceable> RESET ( <replaceable class="parameter">attribute_option</replaceable> [, ... ] ) ALTER [ COLUMN ] <replaceable class="parameter">column_name</replaceable> RESET ( <replaceable class="parameter">attribute_option</replaceable> [, ... ] )
ALTER [ COLUMN ] <replaceable class="parameter">column_name</replaceable> SET STORAGE { PLAIN | EXTERNAL | EXTENDED | MAIN | DEFAULT } ALTER [ COLUMN ] <replaceable class="parameter">column_name</replaceable> SET STORAGE { PLAIN | EXTERNAL | EXTENDED | MAIN | DEFAULT }
@ -328,9 +328,11 @@ WITH ( MODULUS <replaceable class="parameter">numeric_literal</replaceable>, REM
This form This form
sets the per-column statistics-gathering target for subsequent sets the per-column statistics-gathering target for subsequent
<link linkend="sql-analyze"><command>ANALYZE</command></link> operations. <link linkend="sql-analyze"><command>ANALYZE</command></link> operations.
The target can be set in the range 0 to 10000; alternatively, set it The target can be set in the range 0 to 10000. Set it
to -1 to revert to using the system default statistics to <literal>DEFAULT</literal> to revert to using the system default
target (<xref linkend="guc-default-statistics-target"/>). statistics target (<xref linkend="guc-default-statistics-target"/>).
(Setting to a value of -1 is an obsolete way spelling to get the same
outcome.)
For more information on the use of statistics by the For more information on the use of statistics by the
<productname>PostgreSQL</productname> query planner, refer to <productname>PostgreSQL</productname> query planner, refer to
<xref linkend="planner-stats"/>. <xref linkend="planner-stats"/>.

View File

@ -453,8 +453,6 @@ equalTupleDescs(TupleDesc tupdesc1, TupleDesc tupdesc2)
return false; return false;
if (attr1->atttypid != attr2->atttypid) if (attr1->atttypid != attr2->atttypid)
return false; return false;
if (attr1->attstattarget != attr2->attstattarget)
return false;
if (attr1->attlen != attr2->attlen) if (attr1->attlen != attr2->attlen)
return false; return false;
if (attr1->attndims != attr2->attndims) if (attr1->attndims != attr2->attndims)
@ -639,7 +637,6 @@ TupleDescInitEntry(TupleDesc desc,
else if (attributeName != NameStr(att->attname)) else if (attributeName != NameStr(att->attname))
namestrcpy(&(att->attname), attributeName); namestrcpy(&(att->attname), attributeName);
att->attstattarget = -1;
att->attcacheoff = -1; att->attcacheoff = -1;
att->atttypmod = typmod; att->atttypmod = typmod;
@ -702,7 +699,6 @@ TupleDescInitBuiltinEntry(TupleDesc desc,
Assert(attributeName != NULL); Assert(attributeName != NULL);
namestrcpy(&(att->attname), attributeName); namestrcpy(&(att->attname), attributeName);
att->attstattarget = -1;
att->attcacheoff = -1; att->attcacheoff = -1;
att->atttypmod = typmod; att->atttypmod = typmod;

View File

@ -552,7 +552,6 @@ DefineAttr(char *name, char *type, int attnum, int nullness)
if (OidIsValid(attrtypes[attnum]->attcollation)) if (OidIsValid(attrtypes[attnum]->attcollation))
attrtypes[attnum]->attcollation = C_COLLATION_OID; attrtypes[attnum]->attcollation = C_COLLATION_OID;
attrtypes[attnum]->attstattarget = -1;
attrtypes[attnum]->attcacheoff = -1; attrtypes[attnum]->attcacheoff = -1;
attrtypes[attnum]->atttypmod = -1; attrtypes[attnum]->atttypmod = -1;
attrtypes[attnum]->attislocal = true; attrtypes[attnum]->attislocal = true;

View File

@ -840,7 +840,6 @@ sub gen_pg_attribute
my %row; my %row;
$row{attnum} = $attnum; $row{attnum} = $attnum;
$row{attrelid} = $table->{relation_oid}; $row{attrelid} = $table->{relation_oid};
$row{attstattarget} = '0';
morph_row_for_pgattr(\%row, $schema, $attr, 1); morph_row_for_pgattr(\%row, $schema, $attr, 1);
print_bki_insert(\%row, $schema); print_bki_insert(\%row, $schema);

View File

@ -749,14 +749,16 @@ InsertPgAttributeTuples(Relation pg_attribute_rel,
slot[slotCount]->tts_values[Anum_pg_attribute_attisdropped - 1] = BoolGetDatum(attrs->attisdropped); slot[slotCount]->tts_values[Anum_pg_attribute_attisdropped - 1] = BoolGetDatum(attrs->attisdropped);
slot[slotCount]->tts_values[Anum_pg_attribute_attislocal - 1] = BoolGetDatum(attrs->attislocal); slot[slotCount]->tts_values[Anum_pg_attribute_attislocal - 1] = BoolGetDatum(attrs->attislocal);
slot[slotCount]->tts_values[Anum_pg_attribute_attinhcount - 1] = Int16GetDatum(attrs->attinhcount); slot[slotCount]->tts_values[Anum_pg_attribute_attinhcount - 1] = Int16GetDatum(attrs->attinhcount);
slot[slotCount]->tts_values[Anum_pg_attribute_attstattarget - 1] = Int16GetDatum(attrs->attstattarget);
slot[slotCount]->tts_values[Anum_pg_attribute_attcollation - 1] = ObjectIdGetDatum(attrs->attcollation); slot[slotCount]->tts_values[Anum_pg_attribute_attcollation - 1] = ObjectIdGetDatum(attrs->attcollation);
if (attoptions && attoptions[natts] != (Datum) 0) if (attoptions && attoptions[natts] != (Datum) 0)
slot[slotCount]->tts_values[Anum_pg_attribute_attoptions - 1] = attoptions[natts]; slot[slotCount]->tts_values[Anum_pg_attribute_attoptions - 1] = attoptions[natts];
else else
slot[slotCount]->tts_isnull[Anum_pg_attribute_attoptions - 1] = true; slot[slotCount]->tts_isnull[Anum_pg_attribute_attoptions - 1] = true;
/* start out with empty permissions and empty options */ /*
* The remaining fields are not set for new columns.
*/
slot[slotCount]->tts_isnull[Anum_pg_attribute_attstattarget - 1] = true;
slot[slotCount]->tts_isnull[Anum_pg_attribute_attacl - 1] = true; slot[slotCount]->tts_isnull[Anum_pg_attribute_attacl - 1] = true;
slot[slotCount]->tts_isnull[Anum_pg_attribute_attfdwoptions - 1] = true; slot[slotCount]->tts_isnull[Anum_pg_attribute_attfdwoptions - 1] = true;
slot[slotCount]->tts_isnull[Anum_pg_attribute_attmissingval - 1] = true; slot[slotCount]->tts_isnull[Anum_pg_attribute_attmissingval - 1] = true;
@ -818,9 +820,6 @@ AddNewAttributeTuples(Oid new_rel_oid,
indstate = CatalogOpenIndexes(rel); indstate = CatalogOpenIndexes(rel);
/* set stats detail level to a sane default */
for (int i = 0; i < natts; i++)
tupdesc->attrs[i].attstattarget = -1;
InsertPgAttributeTuples(rel, tupdesc, new_rel_oid, NULL, indstate); InsertPgAttributeTuples(rel, tupdesc, new_rel_oid, NULL, indstate);
/* add dependencies on their datatypes and collations */ /* add dependencies on their datatypes and collations */
@ -1685,9 +1684,6 @@ RemoveAttributeById(Oid relid, AttrNumber attnum)
/* Remove any not-null constraint the column may have */ /* Remove any not-null constraint the column may have */
attStruct->attnotnull = false; attStruct->attnotnull = false;
/* We don't want to keep stats for it anymore */
attStruct->attstattarget = 0;
/* Unset this so no one tries to look up the generation expression */ /* Unset this so no one tries to look up the generation expression */
attStruct->attgenerated = '\0'; attStruct->attgenerated = '\0';
@ -1704,9 +1700,11 @@ RemoveAttributeById(Oid relid, AttrNumber attnum)
replacesAtt[Anum_pg_attribute_attmissingval - 1] = true; replacesAtt[Anum_pg_attribute_attmissingval - 1] = true;
/* /*
* Clear the other variable-length fields. This saves some space in * Clear the other nullable fields. This saves some space in pg_attribute
* pg_attribute and removes no longer useful information. * and removes no longer useful information.
*/ */
nullsAtt[Anum_pg_attribute_attstattarget - 1] = true;
replacesAtt[Anum_pg_attribute_attstattarget - 1] = true;
nullsAtt[Anum_pg_attribute_attacl - 1] = true; nullsAtt[Anum_pg_attribute_attacl - 1] = true;
replacesAtt[Anum_pg_attribute_attacl - 1] = true; replacesAtt[Anum_pg_attribute_attacl - 1] = true;
nullsAtt[Anum_pg_attribute_attoptions - 1] = true; nullsAtt[Anum_pg_attribute_attoptions - 1] = true;

View File

@ -325,7 +325,6 @@ ConstructTupleDescriptor(Relation heapRelation,
MemSet(to, 0, ATTRIBUTE_FIXED_PART_SIZE); MemSet(to, 0, ATTRIBUTE_FIXED_PART_SIZE);
to->attnum = i + 1; to->attnum = i + 1;
to->attstattarget = -1;
to->attcacheoff = -1; to->attcacheoff = -1;
to->attislocal = true; to->attislocal = true;
to->attcollation = (i < numkeyatts) ? collationIds[i] : InvalidOid; to->attcollation = (i < numkeyatts) ? collationIds[i] : InvalidOid;
@ -1780,10 +1779,12 @@ index_concurrently_swap(Oid newIndexId, Oid oldIndexId, const char *oldName)
while (HeapTupleIsValid((attrTuple = systable_getnext(scan)))) while (HeapTupleIsValid((attrTuple = systable_getnext(scan))))
{ {
Form_pg_attribute att = (Form_pg_attribute) GETSTRUCT(attrTuple); Form_pg_attribute att = (Form_pg_attribute) GETSTRUCT(attrTuple);
HeapTuple tp;
Datum dat;
bool isnull;
Datum repl_val[Natts_pg_attribute]; Datum repl_val[Natts_pg_attribute];
bool repl_null[Natts_pg_attribute]; bool repl_null[Natts_pg_attribute];
bool repl_repl[Natts_pg_attribute]; bool repl_repl[Natts_pg_attribute];
int attstattarget;
HeapTuple newTuple; HeapTuple newTuple;
/* Ignore dropped columns */ /* Ignore dropped columns */
@ -1793,10 +1794,18 @@ index_concurrently_swap(Oid newIndexId, Oid oldIndexId, const char *oldName)
/* /*
* Get attstattarget from the old index and refresh the new value. * Get attstattarget from the old index and refresh the new value.
*/ */
attstattarget = get_attstattarget(oldIndexId, att->attnum); tp = SearchSysCache2(ATTNUM, ObjectIdGetDatum(oldIndexId), Int16GetDatum(att->attnum));
if (!HeapTupleIsValid(tp))
elog(ERROR, "cache lookup failed for attribute %d of relation %u",
att->attnum, oldIndexId);
dat = SysCacheGetAttr(ATTNUM, tp, Anum_pg_attribute_attstattarget, &isnull);
ReleaseSysCache(tp);
/* no need for a refresh if both match */ /*
if (attstattarget == att->attstattarget) * No need for a refresh if old index value is null. (All new
* index values are null at this point.)
*/
if (isnull)
continue; continue;
memset(repl_val, 0, sizeof(repl_val)); memset(repl_val, 0, sizeof(repl_val));
@ -1804,7 +1813,7 @@ index_concurrently_swap(Oid newIndexId, Oid oldIndexId, const char *oldName)
memset(repl_repl, false, sizeof(repl_repl)); memset(repl_repl, false, sizeof(repl_repl));
repl_repl[Anum_pg_attribute_attstattarget - 1] = true; repl_repl[Anum_pg_attribute_attstattarget - 1] = true;
repl_val[Anum_pg_attribute_attstattarget - 1] = Int16GetDatum(attstattarget); repl_val[Anum_pg_attribute_attstattarget - 1] = dat;
newTuple = heap_modify_tuple(attrTuple, newTuple = heap_modify_tuple(attrTuple,
RelationGetDescr(pg_attribute), RelationGetDescr(pg_attribute),

View File

@ -1004,6 +1004,10 @@ static VacAttrStats *
examine_attribute(Relation onerel, int attnum, Node *index_expr) examine_attribute(Relation onerel, int attnum, Node *index_expr)
{ {
Form_pg_attribute attr = TupleDescAttr(onerel->rd_att, attnum - 1); Form_pg_attribute attr = TupleDescAttr(onerel->rd_att, attnum - 1);
int attstattarget;
HeapTuple atttuple;
Datum dat;
bool isnull;
HeapTuple typtuple; HeapTuple typtuple;
VacAttrStats *stats; VacAttrStats *stats;
int i; int i;
@ -1013,15 +1017,28 @@ examine_attribute(Relation onerel, int attnum, Node *index_expr)
if (attr->attisdropped) if (attr->attisdropped)
return NULL; return NULL;
/*
* Get attstattarget value. Set to -1 if null. (Analyze functions expect
* -1 to mean use default_statistics_target; see for example
* std_typanalyze.)
*/
atttuple = SearchSysCache2(ATTNUM, ObjectIdGetDatum(RelationGetRelid(onerel)), Int16GetDatum(attnum));
if (!HeapTupleIsValid(atttuple))
elog(ERROR, "cache lookup failed for attribute %d of relation %u",
attnum, RelationGetRelid(onerel));
dat = SysCacheGetAttr(ATTNUM, atttuple, Anum_pg_attribute_attstattarget, &isnull);
attstattarget = isnull ? -1 : DatumGetInt16(dat);
ReleaseSysCache(atttuple);
/* Don't analyze column if user has specified not to */ /* Don't analyze column if user has specified not to */
if (attr->attstattarget == 0) if (attstattarget == 0)
return NULL; return NULL;
/* /*
* Create the VacAttrStats struct. * Create the VacAttrStats struct.
*/ */
stats = (VacAttrStats *) palloc0(sizeof(VacAttrStats)); stats = (VacAttrStats *) palloc0(sizeof(VacAttrStats));
stats->attstattarget = attr->attstattarget; stats->attstattarget = attstattarget;
/* /*
* When analyzing an expression index, believe the expression tree's type * When analyzing an expression index, believe the expression tree's type

View File

@ -8543,10 +8543,14 @@ ATExecSetStatistics(Relation rel, const char *colName, int16 colNum, Node *newVa
{ {
int newtarget; int newtarget;
Relation attrelation; Relation attrelation;
HeapTuple tuple; HeapTuple tuple,
newtuple;
Form_pg_attribute attrtuple; Form_pg_attribute attrtuple;
AttrNumber attnum; AttrNumber attnum;
ObjectAddress address; ObjectAddress address;
Datum repl_val[Natts_pg_attribute];
bool repl_null[Natts_pg_attribute];
bool repl_repl[Natts_pg_attribute];
/* /*
* We allow referencing columns by numbers only for indexes, since table * We allow referencing columns by numbers only for indexes, since table
@ -8559,8 +8563,18 @@ ATExecSetStatistics(Relation rel, const char *colName, int16 colNum, Node *newVa
(errcode(ERRCODE_FEATURE_NOT_SUPPORTED), (errcode(ERRCODE_FEATURE_NOT_SUPPORTED),
errmsg("cannot refer to non-index column by number"))); errmsg("cannot refer to non-index column by number")));
if (newValue)
{
Assert(IsA(newValue, Integer)); Assert(IsA(newValue, Integer));
newtarget = intVal(newValue); newtarget = intVal(newValue);
}
else
{
/*
* -1 was used in previous versions to represent the default setting
*/
newtarget = -1;
}
/* /*
* Limit target to a sane range * Limit target to a sane range
@ -8585,7 +8599,7 @@ ATExecSetStatistics(Relation rel, const char *colName, int16 colNum, Node *newVa
if (colName) if (colName)
{ {
tuple = SearchSysCacheCopyAttName(RelationGetRelid(rel), colName); tuple = SearchSysCacheAttName(RelationGetRelid(rel), colName);
if (!HeapTupleIsValid(tuple)) if (!HeapTupleIsValid(tuple))
ereport(ERROR, ereport(ERROR,
@ -8595,7 +8609,7 @@ ATExecSetStatistics(Relation rel, const char *colName, int16 colNum, Node *newVa
} }
else else
{ {
tuple = SearchSysCacheCopyAttNum(RelationGetRelid(rel), colNum); tuple = SearchSysCacheAttNum(RelationGetRelid(rel), colNum);
if (!HeapTupleIsValid(tuple)) if (!HeapTupleIsValid(tuple))
ereport(ERROR, ereport(ERROR,
@ -8629,16 +8643,27 @@ ATExecSetStatistics(Relation rel, const char *colName, int16 colNum, Node *newVa
errhint("Alter statistics on table column instead."))); errhint("Alter statistics on table column instead.")));
} }
attrtuple->attstattarget = newtarget; /* Build new tuple. */
memset(repl_null, false, sizeof(repl_null));
CatalogTupleUpdate(attrelation, &tuple->t_self, tuple); memset(repl_repl, false, sizeof(repl_repl));
if (newtarget != -1)
repl_val[Anum_pg_attribute_attstattarget - 1] = newtarget;
else
repl_null[Anum_pg_attribute_attstattarget - 1] = true;
repl_repl[Anum_pg_attribute_attstattarget - 1] = true;
newtuple = heap_modify_tuple(tuple, RelationGetDescr(attrelation),
repl_val, repl_null, repl_repl);
CatalogTupleUpdate(attrelation, &tuple->t_self, newtuple);
InvokeObjectPostAlterHook(RelationRelationId, InvokeObjectPostAlterHook(RelationRelationId,
RelationGetRelid(rel), RelationGetRelid(rel),
attrtuple->attnum); attrtuple->attnum);
ObjectAddressSubSet(address, RelationRelationId, ObjectAddressSubSet(address, RelationRelationId,
RelationGetRelid(rel), attnum); RelationGetRelid(rel), attnum);
heap_freetuple(tuple);
heap_freetuple(newtuple);
ReleaseSysCache(tuple);
table_close(attrelation, RowExclusiveLock); table_close(attrelation, RowExclusiveLock);

View File

@ -337,6 +337,7 @@ static Node *makeRecursiveViewSelect(char *relname, List *aliases, Node *query);
%type <list> alter_table_cmds alter_type_cmds %type <list> alter_table_cmds alter_type_cmds
%type <list> alter_identity_column_option_list %type <list> alter_identity_column_option_list
%type <defelt> alter_identity_column_option %type <defelt> alter_identity_column_option
%type <node> set_statistics_value
%type <list> createdb_opt_list createdb_opt_items copy_opt_list %type <list> createdb_opt_list createdb_opt_items copy_opt_list
transaction_mode_list transaction_mode_list
@ -2446,18 +2447,18 @@ alter_table_cmd:
n->missing_ok = true; n->missing_ok = true;
$$ = (Node *) n; $$ = (Node *) n;
} }
/* ALTER TABLE <name> ALTER [COLUMN] <colname> SET STATISTICS <SignedIconst> */ /* ALTER TABLE <name> ALTER [COLUMN] <colname> SET STATISTICS */
| ALTER opt_column ColId SET STATISTICS SignedIconst | ALTER opt_column ColId SET STATISTICS set_statistics_value
{ {
AlterTableCmd *n = makeNode(AlterTableCmd); AlterTableCmd *n = makeNode(AlterTableCmd);
n->subtype = AT_SetStatistics; n->subtype = AT_SetStatistics;
n->name = $3; n->name = $3;
n->def = (Node *) makeInteger($6); n->def = $6;
$$ = (Node *) n; $$ = (Node *) n;
} }
/* ALTER TABLE <name> ALTER [COLUMN] <colnum> SET STATISTICS <SignedIconst> */ /* ALTER TABLE <name> ALTER [COLUMN] <colnum> SET STATISTICS */
| ALTER opt_column Iconst SET STATISTICS SignedIconst | ALTER opt_column Iconst SET STATISTICS set_statistics_value
{ {
AlterTableCmd *n = makeNode(AlterTableCmd); AlterTableCmd *n = makeNode(AlterTableCmd);
@ -2469,7 +2470,7 @@ alter_table_cmd:
n->subtype = AT_SetStatistics; n->subtype = AT_SetStatistics;
n->num = (int16) $3; n->num = (int16) $3;
n->def = (Node *) makeInteger($6); n->def = $6;
$$ = (Node *) n; $$ = (Node *) n;
} }
/* ALTER TABLE <name> ALTER [COLUMN] <colname> SET ( column_parameter = value [, ... ] ) */ /* ALTER TABLE <name> ALTER [COLUMN] <colname> SET ( column_parameter = value [, ... ] ) */
@ -3070,6 +3071,11 @@ alter_identity_column_option:
} }
; ;
set_statistics_value:
SignedIconst { $$ = (Node *) makeInteger($1); }
| DEFAULT { $$ = NULL; }
;
PartitionBoundSpec: PartitionBoundSpec:
/* a HASH partition */ /* a HASH partition */
FOR VALUES WITH '(' hash_partbound ')' FOR VALUES WITH '(' hash_partbound ')'

View File

@ -872,33 +872,6 @@ get_attnum(Oid relid, const char *attname)
return InvalidAttrNumber; return InvalidAttrNumber;
} }
/*
* get_attstattarget
*
* Given the relation id and the attribute number,
* return the "attstattarget" field from the attribute relation.
*
* Errors if not found.
*/
int
get_attstattarget(Oid relid, AttrNumber attnum)
{
HeapTuple tp;
Form_pg_attribute att_tup;
int result;
tp = SearchSysCache2(ATTNUM,
ObjectIdGetDatum(relid),
Int16GetDatum(attnum));
if (!HeapTupleIsValid(tp))
elog(ERROR, "cache lookup failed for attribute %d of relation %u",
attnum, relid);
att_tup = (Form_pg_attribute) GETSTRUCT(tp);
result = att_tup->attstattarget;
ReleaseSysCache(tp);
return result;
}
/* /*
* get_attgenerated * get_attgenerated
* *

View File

@ -8925,6 +8925,9 @@ getTableAttrs(Archive *fout, TableInfo *tblinfo, int numTables)
tbinfo->dobj.name); tbinfo->dobj.name);
tbinfo->attnames[j] = pg_strdup(PQgetvalue(res, r, i_attname)); tbinfo->attnames[j] = pg_strdup(PQgetvalue(res, r, i_attname));
tbinfo->atttypnames[j] = pg_strdup(PQgetvalue(res, r, i_atttypname)); tbinfo->atttypnames[j] = pg_strdup(PQgetvalue(res, r, i_atttypname));
if (PQgetisnull(res, r, i_attstattarget))
tbinfo->attstattarget[j] = -1;
else
tbinfo->attstattarget[j] = atoi(PQgetvalue(res, r, i_attstattarget)); tbinfo->attstattarget[j] = atoi(PQgetvalue(res, r, i_attstattarget));
tbinfo->attstorage[j] = *(PQgetvalue(res, r, i_attstorage)); tbinfo->attstorage[j] = *(PQgetvalue(res, r, i_attstorage));
tbinfo->typstorage[j] = *(PQgetvalue(res, r, i_typstorage)); tbinfo->typstorage[j] = *(PQgetvalue(res, r, i_typstorage));
@ -16507,7 +16510,7 @@ dumpTableSchema(Archive *fout, const TableInfo *tbinfo)
/* /*
* Dump per-column statistics information. We only issue an ALTER * Dump per-column statistics information. We only issue an ALTER
* TABLE statement if the attstattarget entry for this column is * TABLE statement if the attstattarget entry for this column is
* non-negative (i.e. it's not the default value) * not the default value.
*/ */
if (tbinfo->attstattarget[j] >= 0) if (tbinfo->attstattarget[j] >= 0)
appendPQExpBuffer(q, "ALTER %sTABLE ONLY %s ALTER COLUMN %s SET STATISTICS %d;\n", appendPQExpBuffer(q, "ALTER %sTABLE ONLY %s ALTER COLUMN %s SET STATISTICS %d;\n",

View File

@ -57,6 +57,6 @@
*/ */
/* yyyymmddN */ /* yyyymmddN */
#define CATALOG_VERSION_NO 202401111 #define CATALOG_VERSION_NO 202401131
#endif #endif

View File

@ -158,23 +158,23 @@ CATALOG(pg_attribute,1249,AttributeRelationId) BKI_BOOTSTRAP BKI_ROWTYPE_OID(75,
/* Number of times inherited from direct parent relation(s) */ /* Number of times inherited from direct parent relation(s) */
int16 attinhcount BKI_DEFAULT(0); int16 attinhcount BKI_DEFAULT(0);
/*
* attstattarget is the target number of statistics datapoints to collect
* during VACUUM ANALYZE of this column. A zero here indicates that we do
* not wish to collect any stats about this column. A "-1" here indicates
* that no value has been explicitly set for this column, so ANALYZE
* should use the default setting.
*
* int16 is sufficient for the current max value (MAX_STATISTICS_TARGET).
*/
int16 attstattarget BKI_DEFAULT(-1);
/* attribute's collation, if any */ /* attribute's collation, if any */
Oid attcollation BKI_LOOKUP_OPT(pg_collation); Oid attcollation BKI_LOOKUP_OPT(pg_collation);
#ifdef CATALOG_VARLEN /* variable-length fields start here */ #ifdef CATALOG_VARLEN /* variable-length/nullable fields start here */
/* NOTE: The following fields are not present in tuple descriptors. */ /* NOTE: The following fields are not present in tuple descriptors. */
/*
* attstattarget is the target number of statistics datapoints to collect
* during VACUUM ANALYZE of this column. A zero here indicates that we do
* not wish to collect any stats about this column. A null value here
* indicates that no value has been explicitly set for this column, so
* ANALYZE should use the default setting.
*
* int16 is sufficient for the current max value (MAX_STATISTICS_TARGET).
*/
int16 attstattarget BKI_DEFAULT(_null_) BKI_FORCE_NULL;
/* Column-level access permissions */ /* Column-level access permissions */
aclitem attacl[1] BKI_DEFAULT(_null_); aclitem attacl[1] BKI_DEFAULT(_null_);

View File

@ -121,7 +121,7 @@ typedef struct VacAttrStats
* than the underlying column/expression. Therefore, use these fields for * than the underlying column/expression. Therefore, use these fields for
* information about the datatype being fed to the typanalyze function. * information about the datatype being fed to the typanalyze function.
*/ */
int attstattarget; int attstattarget; /* -1 to use default */
Oid attrtypid; /* type of data being analyzed */ Oid attrtypid; /* type of data being analyzed */
int32 attrtypmod; /* typmod of data being analyzed */ int32 attrtypmod; /* typmod of data being analyzed */
Form_pg_type attrtype; /* copy of pg_type row for attrtypid */ Form_pg_type attrtype; /* copy of pg_type row for attrtypid */

View File

@ -90,7 +90,6 @@ extern Oid get_opfamily_proc(Oid opfamily, Oid lefttype, Oid righttype,
int16 procnum); int16 procnum);
extern char *get_attname(Oid relid, AttrNumber attnum, bool missing_ok); extern char *get_attname(Oid relid, AttrNumber attnum, bool missing_ok);
extern AttrNumber get_attnum(Oid relid, const char *attname); extern AttrNumber get_attnum(Oid relid, const char *attname);
extern int get_attstattarget(Oid relid, AttrNumber attnum);
extern char get_attgenerated(Oid relid, AttrNumber attnum); extern char get_attgenerated(Oid relid, AttrNumber attnum);
extern Oid get_atttype(Oid relid, AttrNumber attnum); extern Oid get_atttype(Oid relid, AttrNumber attnum);
extern void get_atttypetypmodcoll(Oid relid, AttrNumber attnum, extern void get_atttypetypmodcoll(Oid relid, AttrNumber attnum,

View File

@ -2707,8 +2707,8 @@ SELECT attrelid::regclass, attnum, attstattarget
attrelid | attnum | attstattarget attrelid | attnum | attstattarget
---------------------------+--------+--------------- ---------------------------+--------+---------------
concur_exprs_index_expr | 1 | 100 concur_exprs_index_expr | 1 | 100
concur_exprs_index_pred | 1 | -1 concur_exprs_index_pred | 1 |
concur_exprs_index_pred_2 | 1 | -1 concur_exprs_index_pred_2 | 1 |
(3 rows) (3 rows)
DROP TABLE concur_exprs_tab; DROP TABLE concur_exprs_tab;