1
0
mirror of https://github.com/postgres/postgres.git synced 2025-06-05 23:56:58 +03:00

Make stxstattarget nullable

To match attstattarget change (commit 4f622503d6d).  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> </para></entry>
</row> </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> <row>
<entry role="catalog_table_entry"><para role="column_definition"> <entry role="catalog_table_entry"><para role="column_definition">
<structfield>stxkeys</structfield> <type>int2vector</type> <structfield>stxkeys</structfield> <type>int2vector</type>
@ -7687,6 +7670,23 @@ SCRAM-SHA-256$<replaceable>&lt;iteration count&gt;</replaceable>:<replaceable>&l
</para></entry> </para></entry>
</row> </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> <row>
<entry role="catalog_table_entry"><para role="column_definition"> <entry role="catalog_table_entry"><para role="column_definition">
<structfield>stxkind</structfield> <type>char[]</type> <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> 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> 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 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> </synopsis>
</refsynopsisdiv> </refsynopsisdiv>
@ -101,10 +101,11 @@ ALTER STATISTICS <replaceable class="parameter">name</replaceable> SET STATISTIC
<para> <para>
The statistic-gathering target for this statistics object for subsequent The statistic-gathering target for this statistics object 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
to -1 to revert to using the maximum of the statistics target of the <literal>DEFAULT</literal> to revert to using the system default
referenced columns, if set, or the system default statistics statistics target (<xref linkend="guc-default-statistics-target"/>).
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

@ -495,9 +495,9 @@ CreateStatistics(CreateStatsStmt *stmt)
values[Anum_pg_statistic_ext_stxrelid - 1] = ObjectIdGetDatum(relid); values[Anum_pg_statistic_ext_stxrelid - 1] = ObjectIdGetDatum(relid);
values[Anum_pg_statistic_ext_stxname - 1] = NameGetDatum(&stxname); values[Anum_pg_statistic_ext_stxname - 1] = NameGetDatum(&stxname);
values[Anum_pg_statistic_ext_stxnamespace - 1] = ObjectIdGetDatum(namespaceId); 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_stxowner - 1] = ObjectIdGetDatum(stxowner);
values[Anum_pg_statistic_ext_stxkeys - 1] = PointerGetDatum(stxkeys); 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_stxkind - 1] = PointerGetDatum(stxkind);
values[Anum_pg_statistic_ext_stxexprs - 1] = exprsDatum; values[Anum_pg_statistic_ext_stxexprs - 1] = exprsDatum;
@ -606,23 +606,36 @@ AlterStatistics(AlterStatsStmt *stmt)
bool repl_null[Natts_pg_statistic_ext]; bool repl_null[Natts_pg_statistic_ext];
bool repl_repl[Natts_pg_statistic_ext]; bool repl_repl[Natts_pg_statistic_ext];
ObjectAddress address; ObjectAddress address;
int newtarget = stmt->stxstattarget; int newtarget;
bool newtarget_default;
/* Limit statistics target to a sane range */ /* -1 was used in previous versions for the default setting */
if (newtarget < -1) if (stmt->stxstattarget && intVal(stmt->stxstattarget) != -1)
{ {
ereport(ERROR, newtarget = intVal(stmt->stxstattarget);
(errcode(ERRCODE_INVALID_PARAMETER_VALUE), newtarget_default = false;
errmsg("statistics target %d is too low",
newtarget)));
} }
else if (newtarget > MAX_STATISTICS_TARGET) else
newtarget_default = true;
if (!newtarget_default)
{ {
newtarget = MAX_STATISTICS_TARGET; /* Limit statistics target to a sane range */
ereport(WARNING, if (newtarget < 0)
(errcode(ERRCODE_INVALID_PARAMETER_VALUE), {
errmsg("lowering statistics target to %d", ereport(ERROR,
newtarget))); (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 */ /* lookup OID of the statistics object */
@ -673,7 +686,10 @@ AlterStatistics(AlterStatsStmt *stmt)
/* replace the stxstattarget column */ /* replace the stxstattarget column */
repl_repl[Anum_pg_statistic_ext_stxstattarget - 1] = true; 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), newtup = heap_modify_tuple(oldtup, RelationGetDescr(rel),
repl_val, repl_null, repl_repl); 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) ATExecSetStatistics(Relation rel, const char *colName, int16 colNum, Node *newValue, LOCKMODE lockmode)
{ {
int newtarget; int newtarget;
bool newtarget_default;
Relation attrelation; Relation attrelation;
HeapTuple tuple, HeapTuple tuple,
newtuple; newtuple;
@ -8733,35 +8734,35 @@ 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) /* -1 was used in previous versions for the default setting */
if (newValue && intVal(newValue) != -1)
{ {
newtarget = intVal(newValue); newtarget = intVal(newValue);
newtarget_default = false;
} }
else 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; if (newtarget < 0)
} {
ereport(ERROR,
/* (errcode(ERRCODE_INVALID_PARAMETER_VALUE),
* Limit target to a sane range errmsg("statistics target %d is too low",
*/ newtarget)));
if (newtarget < -1) }
{ else if (newtarget > MAX_STATISTICS_TARGET)
ereport(ERROR, {
(errcode(ERRCODE_INVALID_PARAMETER_VALUE), newtarget = MAX_STATISTICS_TARGET;
errmsg("statistics target %d is too low", ereport(WARNING,
newtarget))); (errcode(ERRCODE_INVALID_PARAMETER_VALUE),
} errmsg("lowering statistics target to %d",
else if (newtarget > MAX_STATISTICS_TARGET) newtarget)));
{ }
newtarget = MAX_STATISTICS_TARGET;
ereport(WARNING,
(errcode(ERRCODE_INVALID_PARAMETER_VALUE),
errmsg("lowering statistics target to %d",
newtarget)));
} }
attrelation = table_open(AttributeRelationId, RowExclusiveLock); attrelation = table_open(AttributeRelationId, RowExclusiveLock);
@ -8815,7 +8816,7 @@ ATExecSetStatistics(Relation rel, const char *colName, int16 colNum, Node *newVa
/* Build new tuple. */ /* Build new tuple. */
memset(repl_null, false, sizeof(repl_null)); memset(repl_null, false, sizeof(repl_null));
memset(repl_repl, false, sizeof(repl_repl)); memset(repl_repl, false, sizeof(repl_repl));
if (newtarget != -1) if (!newtarget_default)
repl_val[Anum_pg_attribute_attstattarget - 1] = newtarget; repl_val[Anum_pg_attribute_attstattarget - 1] = newtarget;
else else
repl_null[Anum_pg_attribute_attstattarget - 1] = true; repl_null[Anum_pg_attribute_attstattarget - 1] = true;

View File

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

View File

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

View File

@ -7580,7 +7580,7 @@ getExtendedStatistics(Archive *fout)
if (fout->remoteVersion < 130000) if (fout->remoteVersion < 130000)
appendPQExpBufferStr(query, "SELECT tableoid, oid, stxname, " appendPQExpBufferStr(query, "SELECT tableoid, oid, stxname, "
"stxnamespace, stxowner, stxrelid, (-1) AS stxstattarget " "stxnamespace, stxowner, stxrelid, NULL AS stxstattarget "
"FROM pg_catalog.pg_statistic_ext"); "FROM pg_catalog.pg_statistic_ext");
else else
appendPQExpBufferStr(query, "SELECT tableoid, oid, stxname, " appendPQExpBufferStr(query, "SELECT tableoid, oid, stxname, "
@ -7613,7 +7613,10 @@ getExtendedStatistics(Archive *fout)
statsextinfo[i].rolname = getRoleName(PQgetvalue(res, i, i_stxowner)); statsextinfo[i].rolname = getRoleName(PQgetvalue(res, i, i_stxowner));
statsextinfo[i].stattable = statsextinfo[i].stattable =
findTableByOid(atooid(PQgetvalue(res, i, i_stxrelid))); 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 */ /* Decide whether we want to dump it */
selectDumpableStatisticsObject(&(statsextinfo[i]), fout); 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 * 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 * for this statistics object is not the default value.
* value).
*/ */
if (statsextinfo->stattarget >= 0) if (statsextinfo->stattarget >= 0)
{ {

View File

@ -2804,7 +2804,8 @@ describeOneTableDetails(const char *schemaname,
PQgetvalue(result, i, 1)); PQgetvalue(result, i, 1));
/* Show the stats target if it's not default */ /* 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", appendPQExpBuffer(&buf, "; STATISTICS %s",
PQgetvalue(result, i, 8)); PQgetvalue(result, i, 8));

View File

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

View File

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

View File

@ -3269,7 +3269,7 @@ typedef struct AlterStatsStmt
{ {
NodeTag type; NodeTag type;
List *defnames; /* qualified name (list of String) */ 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 */ bool missing_ok; /* skip error if statistics object is missing */
} AlterStatsStmt; } AlterStatsStmt;