Make stxstattarget nullable
authorPeter Eisentraut
Sun, 17 Mar 2024 11:22:05 +0000 (12:22 +0100)
committerPeter Eisentraut
Sun, 17 Mar 2024 11:26:26 +0000 (12:26 +0100)
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
Discussion: https://www.postgresql.org/message-id/flat/4da8d211-d54d-44b9-9847-f2a9f1184c76@eisentraut.org

doc/src/sgml/catalogs.sgml
doc/src/sgml/ref/alter_statistics.sgml
src/backend/commands/statscmds.c
src/backend/commands/tablecmds.c
src/backend/parser/gram.y
src/backend/statistics/extended_stats.c
src/bin/pg_dump/pg_dump.c
src/bin/psql/describe.c
src/include/catalog/catversion.h
src/include/catalog/pg_statistic_ext.h
src/include/nodes/parsenodes.h

index 387a14b18691bf3f3096be590b529fd873fceb38..2f091ad09d1d5af918cca53b121e20e0c2ad5c1d 100644 (file)
@@ -7657,6 +7657,19 @@ SCRAM-SHA-256$<iteration count>:&l
       
      
 
+     
+      
+       stxkeys int2vector
+       (references pg_attribute.attnum)
+      
+      
+       An array of attribute numbers, indicating which table columns are
+       covered by this statistics object;
+       for example a value of 1 3 would
+       mean that the first and the third table columns are covered
+      
+     
+
      
       
        stxstattarget int2
@@ -7666,7 +7679,7 @@ SCRAM-SHA-256$<iteration count>:&l
        of statistics accumulated for this statistics object by
        ANALYZE.
        A zero value indicates that no statistics should be collected.
-       A negative value says to use the maximum of the statistics targets of
+       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 stxstattarget
        determine the target number of most common values
@@ -7674,19 +7687,6 @@ SCRAM-SHA-256$<iteration count>:&l
       
      
 
-     
-      
-       stxkeys int2vector
-       (references pg_attribute.attnum)
-      
-      
-       An array of attribute numbers, indicating which table columns are
-       covered by this statistics object;
-       for example a value of 1 3 would
-       mean that the first and the third table columns are covered
-      
-     
-
      
       
        stxkind char[]
index 73cc9e830de5bd2f806df8234f4acf3b3deefa94..c82a728a910ee7d1580fafd442ad6d538037cdfb 100644 (file)
@@ -26,7 +26,7 @@ PostgreSQL documentation
 ALTER STATISTICS name OWNER TO { new_owner | CURRENT_ROLE | CURRENT_USER | SESSION_USER }
 ALTER STATISTICS name RENAME TO new_name
 ALTER STATISTICS name SET SCHEMA new_schema
-ALTER STATISTICS name SET STATISTICS new_target
+ALTER STATISTICS name SET STATISTICS new_target | DEFAULT }
 
  
 
@@ -101,10 +101,11 @@ ALTER STATISTICS name SET STATISTIC
        
         The statistic-gathering target for this statistics object for subsequent
         ANALYZE 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 ().
+        The target can be set in the range 0 to 10000.  Set it to
+        DEFAULT to revert to using the system 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
         PostgreSQL query planner, refer to
         .
index a855f750c751fe90140795883a5a23c118c1d24d..5f49479832d9192a7d28a704c2d465aa8d20f214 100644 (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);
index 2470265561a8d820ddad21980c3d95719f6cb7f5..ae6719329e7df36e3f82fabff88321ce7438f502 100644 (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;
index c6e2f679fd5930072b1de5c1cdb974649c17229d..3ad99fffe1d561b90a381f7fcc496e64928af3e0 100644 (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);
 
index f21bdc2ab9a05a61ec1531c764697d2dddc56030..99fdf208dba1c4e4711755fd0a2925e27537e707 100644 (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);
index 171e591696596a3e263f1238729146a2c0394537..a5149ca823c9b1c4dddea2a92358d23320d3899d 100644 (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)
    {
index 1ab80eb7cacc8dd60c77c8352ace2ec6cb29a925..6433497bcd20893baad82f3a0c55c3fb8570f5a7 100644 (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));
 
index 9cf6dae3d90c94b793c349185f1482555be01b52..aec49079c123f06e3b544023b4e39aaa77484d67 100644 (file)
@@ -57,6 +57,6 @@
  */
 
 /*                         yyyymmddN */
-#define CATALOG_VERSION_NO 202403141
+#define CATALOG_VERSION_NO 202403171
 
 #endif
index 85064086ec5519f2fa7aa5381fe4c888c2b056b0..50a5c021edf53a54033aa8f5386e5dd4e7982806 100644 (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
index aadaf67f57439d426c011cc8bfbf0a2c5760e95b..70a21df0fee7f5606c006708b3e0f87608b85c12 100644 (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;