Make stxstattarget nullable

To match attstattarget change (commit 4f622503d6).  The logic inside
CreateStatistics() is clarified a bit compared to that previous patch,
and so here we also update ATExecSetStatistics() to match.

Reviewed-by: Tomas Vondra <tomas.vondra@enterprisedb.com>
Discussion: https://www.postgresql.org/message-id/flat/4da8d211-d54d-44b9-9847-f2a9f1184c76@eisentraut.org
This commit is contained in:
Peter Eisentraut 2024-03-17 12:22:05 +01:00
parent 33e729c514
commit 012460ee93
11 changed files with 96 additions and 73 deletions

View File

@ -7657,23 +7657,6 @@ SCRAM-SHA-256$<replaceable>&lt;iteration count&gt;</replaceable>:<replaceable>&l
</para></entry>
</row>
<row>
<entry role="catalog_table_entry"><para role="column_definition">
<structfield>stxstattarget</structfield> <type>int2</type>
</para>
<para>
<structfield>stxstattarget</structfield> controls the level of detail
of statistics accumulated for this statistics object by
<link linkend="sql-analyze"><command>ANALYZE</command></link>.
A zero value indicates that no statistics should be collected.
A negative value says to use the maximum of the statistics targets of
the referenced columns, if set, or the system default statistics target.
Positive values of <structfield>stxstattarget</structfield>
determine the target number of <quote>most common values</quote>
to collect.
</para></entry>
</row>
<row>
<entry role="catalog_table_entry"><para role="column_definition">
<structfield>stxkeys</structfield> <type>int2vector</type>
@ -7687,6 +7670,23 @@ SCRAM-SHA-256$<replaceable>&lt;iteration count&gt;</replaceable>:<replaceable>&l
</para></entry>
</row>
<row>
<entry role="catalog_table_entry"><para role="column_definition">
<structfield>stxstattarget</structfield> <type>int2</type>
</para>
<para>
<structfield>stxstattarget</structfield> controls the level of detail
of statistics accumulated for this statistics object by
<link linkend="sql-analyze"><command>ANALYZE</command></link>.
A zero value indicates that no statistics should be collected.
A null value says to use the maximum of the statistics targets of
the referenced columns, if set, or the system default statistics target.
Positive values of <structfield>stxstattarget</structfield>
determine the target number of <quote>most common values</quote>
to collect.
</para></entry>
</row>
<row>
<entry role="catalog_table_entry"><para role="column_definition">
<structfield>stxkind</structfield> <type>char[]</type>

View File

@ -26,7 +26,7 @@ PostgreSQL documentation
ALTER STATISTICS <replaceable class="parameter">name</replaceable> OWNER TO { <replaceable class="parameter">new_owner</replaceable> | CURRENT_ROLE | CURRENT_USER | SESSION_USER }
ALTER STATISTICS <replaceable class="parameter">name</replaceable> RENAME TO <replaceable class="parameter">new_name</replaceable>
ALTER STATISTICS <replaceable class="parameter">name</replaceable> SET SCHEMA <replaceable class="parameter">new_schema</replaceable>
ALTER STATISTICS <replaceable class="parameter">name</replaceable> SET STATISTICS <replaceable class="parameter">new_target</replaceable>
ALTER STATISTICS <replaceable class="parameter">name</replaceable> SET STATISTICS { <replaceable class="parameter">new_target</replaceable> | DEFAULT }
</synopsis>
</refsynopsisdiv>
@ -101,10 +101,11 @@ ALTER STATISTICS <replaceable class="parameter">name</replaceable> SET STATISTIC
<para>
The statistic-gathering target for this statistics object for subsequent
<link linkend="sql-analyze"><command>ANALYZE</command></link> operations.
The target can be set in the range 0 to 10000; alternatively, set it
to -1 to revert to using the maximum of the statistics target of the
referenced columns, if set, or the system default statistics
target (<xref linkend="guc-default-statistics-target"/>).
The target can be set in the range 0 to 10000. Set it to
<literal>DEFAULT</literal> to revert to using the system default
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
<productname>PostgreSQL</productname> query planner, refer to
<xref linkend="planner-stats"/>.

View File

@ -495,9 +495,9 @@ CreateStatistics(CreateStatsStmt *stmt)
values[Anum_pg_statistic_ext_stxrelid - 1] = ObjectIdGetDatum(relid);
values[Anum_pg_statistic_ext_stxname - 1] = NameGetDatum(&stxname);
values[Anum_pg_statistic_ext_stxnamespace - 1] = ObjectIdGetDatum(namespaceId);
values[Anum_pg_statistic_ext_stxstattarget - 1] = Int16GetDatum(-1);
values[Anum_pg_statistic_ext_stxowner - 1] = ObjectIdGetDatum(stxowner);
values[Anum_pg_statistic_ext_stxkeys - 1] = PointerGetDatum(stxkeys);
nulls[Anum_pg_statistic_ext_stxstattarget - 1] = true;
values[Anum_pg_statistic_ext_stxkind - 1] = PointerGetDatum(stxkind);
values[Anum_pg_statistic_ext_stxexprs - 1] = exprsDatum;
@ -606,23 +606,36 @@ AlterStatistics(AlterStatsStmt *stmt)
bool repl_null[Natts_pg_statistic_ext];
bool repl_repl[Natts_pg_statistic_ext];
ObjectAddress address;
int newtarget = stmt->stxstattarget;
int newtarget;
bool newtarget_default;
/* Limit statistics target to a sane range */
if (newtarget < -1)
/* -1 was used in previous versions for the default setting */
if (stmt->stxstattarget && intVal(stmt->stxstattarget) != -1)
{
ereport(ERROR,
(errcode(ERRCODE_INVALID_PARAMETER_VALUE),
errmsg("statistics target %d is too low",
newtarget)));
newtarget = intVal(stmt->stxstattarget);
newtarget_default = false;
}
else if (newtarget > MAX_STATISTICS_TARGET)
else
newtarget_default = true;
if (!newtarget_default)
{
newtarget = MAX_STATISTICS_TARGET;
ereport(WARNING,
(errcode(ERRCODE_INVALID_PARAMETER_VALUE),
errmsg("lowering statistics target to %d",
newtarget)));
/* Limit statistics target to a sane range */
if (newtarget < 0)
{
ereport(ERROR,
(errcode(ERRCODE_INVALID_PARAMETER_VALUE),
errmsg("statistics target %d is too low",
newtarget)));
}
else if (newtarget > MAX_STATISTICS_TARGET)
{
newtarget = MAX_STATISTICS_TARGET;
ereport(WARNING,
(errcode(ERRCODE_INVALID_PARAMETER_VALUE),
errmsg("lowering statistics target to %d",
newtarget)));
}
}
/* lookup OID of the statistics object */
@ -673,7 +686,10 @@ AlterStatistics(AlterStatsStmt *stmt)
/* replace the stxstattarget column */
repl_repl[Anum_pg_statistic_ext_stxstattarget - 1] = true;
repl_val[Anum_pg_statistic_ext_stxstattarget - 1] = Int16GetDatum(newtarget);
if (!newtarget_default)
repl_val[Anum_pg_statistic_ext_stxstattarget - 1] = Int16GetDatum(newtarget);
else
repl_null[Anum_pg_statistic_ext_stxstattarget - 1] = true;
newtup = heap_modify_tuple(oldtup, RelationGetDescr(rel),
repl_val, repl_null, repl_repl);

View File

@ -8712,6 +8712,7 @@ static ObjectAddress
ATExecSetStatistics(Relation rel, const char *colName, int16 colNum, Node *newValue, LOCKMODE lockmode)
{
int newtarget;
bool newtarget_default;
Relation attrelation;
HeapTuple tuple,
newtuple;
@ -8733,35 +8734,35 @@ ATExecSetStatistics(Relation rel, const char *colName, int16 colNum, Node *newVa
(errcode(ERRCODE_FEATURE_NOT_SUPPORTED),
errmsg("cannot refer to non-index column by number")));
if (newValue)
/* -1 was used in previous versions for the default setting */
if (newValue && intVal(newValue) != -1)
{
newtarget = intVal(newValue);
newtarget_default = false;
}
else
newtarget_default = true;
if (!newtarget_default)
{
/*
* -1 was used in previous versions to represent the default setting
* Limit target to a sane range
*/
newtarget = -1;
}
/*
* Limit target to a sane range
*/
if (newtarget < -1)
{
ereport(ERROR,
(errcode(ERRCODE_INVALID_PARAMETER_VALUE),
errmsg("statistics target %d is too low",
newtarget)));
}
else if (newtarget > MAX_STATISTICS_TARGET)
{
newtarget = MAX_STATISTICS_TARGET;
ereport(WARNING,
(errcode(ERRCODE_INVALID_PARAMETER_VALUE),
errmsg("lowering statistics target to %d",
newtarget)));
if (newtarget < 0)
{
ereport(ERROR,
(errcode(ERRCODE_INVALID_PARAMETER_VALUE),
errmsg("statistics target %d is too low",
newtarget)));
}
else if (newtarget > MAX_STATISTICS_TARGET)
{
newtarget = MAX_STATISTICS_TARGET;
ereport(WARNING,
(errcode(ERRCODE_INVALID_PARAMETER_VALUE),
errmsg("lowering statistics target to %d",
newtarget)));
}
}
attrelation = table_open(AttributeRelationId, RowExclusiveLock);
@ -8815,7 +8816,7 @@ ATExecSetStatistics(Relation rel, const char *colName, int16 colNum, Node *newVa
/* Build new tuple. */
memset(repl_null, false, sizeof(repl_null));
memset(repl_repl, false, sizeof(repl_repl));
if (newtarget != -1)
if (!newtarget_default)
repl_val[Anum_pg_attribute_attstattarget - 1] = newtarget;
else
repl_null[Anum_pg_attribute_attstattarget - 1] = true;

View File

@ -4610,7 +4610,7 @@ stats_param: ColId
*****************************************************************************/
AlterStatsStmt:
ALTER STATISTICS any_name SET STATISTICS SignedIconst
ALTER STATISTICS any_name SET STATISTICS set_statistics_value
{
AlterStatsStmt *n = makeNode(AlterStatsStmt);
@ -4619,7 +4619,7 @@ AlterStatsStmt:
n->stxstattarget = $6;
$$ = (Node *) n;
}
| ALTER STATISTICS IF_P EXISTS any_name SET STATISTICS SignedIconst
| ALTER STATISTICS IF_P EXISTS any_name SET STATISTICS set_statistics_value
{
AlterStatsStmt *n = makeNode(AlterStatsStmt);

View File

@ -454,13 +454,15 @@ fetch_statentries_for_relation(Relation pg_statext, Oid relid)
entry->statOid = staForm->oid;
entry->schema = get_namespace_name(staForm->stxnamespace);
entry->name = pstrdup(NameStr(staForm->stxname));
entry->stattarget = staForm->stxstattarget;
for (i = 0; i < staForm->stxkeys.dim1; i++)
{
entry->columns = bms_add_member(entry->columns,
staForm->stxkeys.values[i]);
}
datum = SysCacheGetAttr(STATEXTOID, htup, Anum_pg_statistic_ext_stxstattarget, &isnull);
entry->stattarget = isnull ? -1 : DatumGetInt16(datum);
/* decode the stxkind char array into a list of chars */
datum = SysCacheGetAttrNotNull(STATEXTOID, htup,
Anum_pg_statistic_ext_stxkind);

View File

@ -7580,7 +7580,7 @@ getExtendedStatistics(Archive *fout)
if (fout->remoteVersion < 130000)
appendPQExpBufferStr(query, "SELECT tableoid, oid, stxname, "
"stxnamespace, stxowner, stxrelid, (-1) AS stxstattarget "
"stxnamespace, stxowner, stxrelid, NULL AS stxstattarget "
"FROM pg_catalog.pg_statistic_ext");
else
appendPQExpBufferStr(query, "SELECT tableoid, oid, stxname, "
@ -7613,7 +7613,10 @@ getExtendedStatistics(Archive *fout)
statsextinfo[i].rolname = getRoleName(PQgetvalue(res, i, i_stxowner));
statsextinfo[i].stattable =
findTableByOid(atooid(PQgetvalue(res, i, i_stxrelid)));
statsextinfo[i].stattarget = atoi(PQgetvalue(res, i, i_stattarget));
if (PQgetisnull(res, i, i_stattarget))
statsextinfo[i].stattarget = -1;
else
statsextinfo[i].stattarget = atoi(PQgetvalue(res, i, i_stattarget));
/* Decide whether we want to dump it */
selectDumpableStatisticsObject(&(statsextinfo[i]), fout);
@ -17062,8 +17065,7 @@ dumpStatisticsExt(Archive *fout, const StatsExtInfo *statsextinfo)
/*
* We only issue an ALTER STATISTICS statement if the stxstattarget entry
* for this statistics object is non-negative (i.e. it's not the default
* value).
* for this statistics object is not the default value.
*/
if (statsextinfo->stattarget >= 0)
{

View File

@ -2804,7 +2804,8 @@ describeOneTableDetails(const char *schemaname,
PQgetvalue(result, i, 1));
/* Show the stats target if it's not default */
if (strcmp(PQgetvalue(result, i, 8), "-1") != 0)
if (!PQgetisnull(result, i, 8) &&
strcmp(PQgetvalue(result, i, 8), "-1") != 0)
appendPQExpBuffer(&buf, "; STATISTICS %s",
PQgetvalue(result, i, 8));

View File

@ -57,6 +57,6 @@
*/
/* yyyymmddN */
#define CATALOG_VERSION_NO 202403141
#define CATALOG_VERSION_NO 202403171
#endif

View File

@ -43,15 +43,15 @@ CATALOG(pg_statistic_ext,3381,StatisticExtRelationId)
* object's namespace */
Oid stxowner BKI_LOOKUP(pg_authid); /* statistics object's owner */
int16 stxstattarget BKI_DEFAULT(-1); /* statistics target */
/*
* variable-length fields start here, but we allow direct access to
* stxkeys
* variable-length/nullable fields start here, but we allow direct access
* to stxkeys
*/
int2vector stxkeys BKI_FORCE_NOT_NULL; /* array of column keys */
#ifdef CATALOG_VARLEN
int16 stxstattarget BKI_DEFAULT(_null_) BKI_FORCE_NULL; /* statistics target */
char stxkind[1] BKI_FORCE_NOT_NULL; /* statistics kinds requested
* to build */
pg_node_tree stxexprs; /* A list of expression trees for stats

View File

@ -3269,7 +3269,7 @@ typedef struct AlterStatsStmt
{
NodeTag type;
List *defnames; /* qualified name (list of String) */
int stxstattarget; /* statistics target */
Node *stxstattarget; /* statistics target */
bool missing_ok; /* skip error if statistics object is missing */
} AlterStatsStmt;