Make attstattarget nullable
authorPeter Eisentraut <[email protected]>
Sat, 13 Jan 2024 17:14:53 +0000 (18:14 +0100)
committerPeter Eisentraut <[email protected]>
Sat, 13 Jan 2024 17:14:53 +0000 (18:14 +0100)
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 <[email protected]>
Discussion: https://www.postgresql.org/message-id/flat/4da8d211-d54d-44b9-9847-f2a9f1184c76@eisentraut.org

16 files changed:
doc/src/sgml/ref/alter_table.sgml
src/backend/access/common/tupdesc.c
src/backend/bootstrap/bootstrap.c
src/backend/catalog/genbki.pl
src/backend/catalog/heap.c
src/backend/catalog/index.c
src/backend/commands/analyze.c
src/backend/commands/tablecmds.c
src/backend/parser/gram.y
src/backend/utils/cache/lsyscache.c
src/bin/pg_dump/pg_dump.c
src/include/catalog/catversion.h
src/include/catalog/pg_attribute.h
src/include/commands/vacuum.h
src/include/utils/lsyscache.h
src/test/regress/expected/create_index.out

index eaada23024888d67b4113e09c3c9d1d824443c45..9670671107e16da0c9aec9b5d2bad8e70d64680d 100644 (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> { 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> 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> RESET ( <replaceable class="parameter">attribute_option</replaceable> [, ... ] )
     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
       sets the per-column statistics-gathering target 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 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"/>.
index 6e7ad79834f3a5e519397e3e10909f874c7ab4da..bc80caee1172978620f803168f7651c5570e0f27 100644 (file)
@@ -453,8 +453,6 @@ equalTupleDescs(TupleDesc tupdesc1, TupleDesc tupdesc2)
            return false;
        if (attr1->atttypid != attr2->atttypid)
            return false;
-       if (attr1->attstattarget != attr2->attstattarget)
-           return false;
        if (attr1->attlen != attr2->attlen)
            return false;
        if (attr1->attndims != attr2->attndims)
@@ -639,7 +637,6 @@ TupleDescInitEntry(TupleDesc desc,
    else if (attributeName != NameStr(att->attname))
        namestrcpy(&(att->attname), attributeName);
 
-   att->attstattarget = -1;
    att->attcacheoff = -1;
    att->atttypmod = typmod;
 
@@ -702,7 +699,6 @@ TupleDescInitBuiltinEntry(TupleDesc desc,
    Assert(attributeName != NULL);
    namestrcpy(&(att->attname), attributeName);
 
-   att->attstattarget = -1;
    att->attcacheoff = -1;
    att->atttypmod = typmod;
 
index 55c53d01f8776b974104e212340aaa3a76dadbe2..141b25ddd7a5c8f18d387b46e56f81f93f65142c 100644 (file)
@@ -552,7 +552,6 @@ DefineAttr(char *name, char *type, int attnum, int nullness)
    if (OidIsValid(attrtypes[attnum]->attcollation))
        attrtypes[attnum]->attcollation = C_COLLATION_OID;
 
-   attrtypes[attnum]->attstattarget = -1;
    attrtypes[attnum]->attcacheoff = -1;
    attrtypes[attnum]->atttypmod = -1;
    attrtypes[attnum]->attislocal = true;
index 531d7cd0d52ce3c2c101f5e1605f6740f7204702..93553e8c3c4c28557f257eb8bd7802f6387ade95 100644 (file)
@@ -840,7 +840,6 @@ sub gen_pg_attribute
                my %row;
                $row{attnum} = $attnum;
                $row{attrelid} = $table->{relation_oid};
-               $row{attstattarget} = '0';
 
                morph_row_for_pgattr(\%row, $schema, $attr, 1);
                print_bki_insert(\%row, $schema);
index e80a90ef4c0d9f83cf9a00f5c9c84a1457627c3f..45a71081d429220f5e8be693c258417eb01cb746 100644 (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_attislocal - 1] = BoolGetDatum(attrs->attislocal);
        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);
        if (attoptions && attoptions[natts] != (Datum) 0)
            slot[slotCount]->tts_values[Anum_pg_attribute_attoptions - 1] = attoptions[natts];
        else
            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_attfdwoptions - 1] = true;
        slot[slotCount]->tts_isnull[Anum_pg_attribute_attmissingval - 1] = true;
@@ -818,9 +820,6 @@ AddNewAttributeTuples(Oid new_rel_oid,
 
    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);
 
    /* 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 */
    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 */
    attStruct->attgenerated = '\0';
 
@@ -1704,9 +1700,11 @@ RemoveAttributeById(Oid relid, AttrNumber attnum)
    replacesAtt[Anum_pg_attribute_attmissingval - 1] = true;
 
    /*
-    * Clear the other variable-length fields.  This saves some space in
-    * pg_attribute and removes no longer useful information.
+    * Clear the other nullable fields.  This saves some space in pg_attribute
+    * 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;
    replacesAtt[Anum_pg_attribute_attacl - 1] = true;
    nullsAtt[Anum_pg_attribute_attoptions - 1] = true;
index 88f7994b5a68ad292d3411b7094870ba10452f1d..fbef3d5382d9e5bbc83b12506b93319a06f099c5 100644 (file)
@@ -325,7 +325,6 @@ ConstructTupleDescriptor(Relation heapRelation,
 
        MemSet(to, 0, ATTRIBUTE_FIXED_PART_SIZE);
        to->attnum = i + 1;
-       to->attstattarget = -1;
        to->attcacheoff = -1;
        to->attislocal = true;
        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))))
        {
            Form_pg_attribute att = (Form_pg_attribute) GETSTRUCT(attrTuple);
+           HeapTuple   tp;
+           Datum       dat;
+           bool        isnull;
            Datum       repl_val[Natts_pg_attribute];
            bool        repl_null[Natts_pg_attribute];
            bool        repl_repl[Natts_pg_attribute];
-           int         attstattarget;
            HeapTuple   newTuple;
 
            /* 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.
             */
-           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;
 
            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));
 
            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,
                                         RelationGetDescr(pg_attribute),
index deef865ce6deddf57054364623902aab9c88e821..a03495d6c95ee11e0b4a6c4b47f106e08afb1919 100644 (file)
@@ -1004,6 +1004,10 @@ static VacAttrStats *
 examine_attribute(Relation onerel, int attnum, Node *index_expr)
 {
    Form_pg_attribute attr = TupleDescAttr(onerel->rd_att, attnum - 1);
+   int         attstattarget;
+   HeapTuple   atttuple;
+   Datum       dat;
+   bool        isnull;
    HeapTuple   typtuple;
    VacAttrStats *stats;
    int         i;
@@ -1013,15 +1017,28 @@ examine_attribute(Relation onerel, int attnum, Node *index_expr)
    if (attr->attisdropped)
        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 */
-   if (attr->attstattarget == 0)
+   if (attstattarget == 0)
        return NULL;
 
    /*
     * Create the VacAttrStats struct.
     */
    stats = (VacAttrStats *) palloc0(sizeof(VacAttrStats));
-   stats->attstattarget = attr->attstattarget;
+   stats->attstattarget = attstattarget;
 
    /*
     * When analyzing an expression index, believe the expression tree's type
index 5e558fabf65a6f4c5e1ed956f7e994ea0dfaab57..5496f1268261ad1d2883ad9e458d4414571bfd6e 100644 (file)
@@ -8543,10 +8543,14 @@ ATExecSetStatistics(Relation rel, const char *colName, int16 colNum, Node *newVa
 {
    int         newtarget;
    Relation    attrelation;
-   HeapTuple   tuple;
+   HeapTuple   tuple,
+               newtuple;
    Form_pg_attribute attrtuple;
    AttrNumber  attnum;
    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
@@ -8559,8 +8563,18 @@ ATExecSetStatistics(Relation rel, const char *colName, int16 colNum, Node *newVa
                (errcode(ERRCODE_FEATURE_NOT_SUPPORTED),
                 errmsg("cannot refer to non-index column by number")));
 
-   Assert(IsA(newValue, Integer));
-   newtarget = intVal(newValue);
+   if (newValue)
+   {
+       Assert(IsA(newValue, Integer));
+       newtarget = intVal(newValue);
+   }
+   else
+   {
+       /*
+        * -1 was used in previous versions to represent the default setting
+        */
+       newtarget = -1;
+   }
 
    /*
     * Limit target to a sane range
@@ -8585,7 +8599,7 @@ ATExecSetStatistics(Relation rel, const char *colName, int16 colNum, Node *newVa
 
    if (colName)
    {
-       tuple = SearchSysCacheCopyAttName(RelationGetRelid(rel), colName);
+       tuple = SearchSysCacheAttName(RelationGetRelid(rel), colName);
 
        if (!HeapTupleIsValid(tuple))
            ereport(ERROR,
@@ -8595,7 +8609,7 @@ ATExecSetStatistics(Relation rel, const char *colName, int16 colNum, Node *newVa
    }
    else
    {
-       tuple = SearchSysCacheCopyAttNum(RelationGetRelid(rel), colNum);
+       tuple = SearchSysCacheAttNum(RelationGetRelid(rel), colNum);
 
        if (!HeapTupleIsValid(tuple))
            ereport(ERROR,
@@ -8629,16 +8643,27 @@ ATExecSetStatistics(Relation rel, const char *colName, int16 colNum, Node *newVa
                     errhint("Alter statistics on table column instead.")));
    }
 
-   attrtuple->attstattarget = newtarget;
-
-   CatalogTupleUpdate(attrelation, &tuple->t_self, tuple);
+   /* Build new tuple. */
+   memset(repl_null, false, sizeof(repl_null));
+   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,
                              RelationGetRelid(rel),
                              attrtuple->attnum);
    ObjectAddressSubSet(address, RelationRelationId,
                        RelationGetRelid(rel), attnum);
-   heap_freetuple(tuple);
+
+   heap_freetuple(newtuple);
+
+   ReleaseSysCache(tuple);
 
    table_close(attrelation, RowExclusiveLock);
 
index 6b88096e8e1c09baf3f654540f3554f67b471cf2..3460fea56bacf8ef6b26d786b9c3965cc2a5aa6c 100644 (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_identity_column_option_list
 %type <defelt>  alter_identity_column_option
+%type <node>   set_statistics_value
 
 %type <list>   createdb_opt_list createdb_opt_items copy_opt_list
                transaction_mode_list
@@ -2446,18 +2447,18 @@ alter_table_cmd:
                    n->missing_ok = true;
                    $$ = (Node *) n;
                }
-           /* ALTER TABLE <name> ALTER [COLUMN] <colname> SET STATISTICS <SignedIconst> */
-           | ALTER opt_column ColId SET STATISTICS SignedIconst
+           /* ALTER TABLE <name> ALTER [COLUMN] <colname> SET STATISTICS */
+           | ALTER opt_column ColId SET STATISTICS set_statistics_value
                {
                    AlterTableCmd *n = makeNode(AlterTableCmd);
 
                    n->subtype = AT_SetStatistics;
                    n->name = $3;
-                   n->def = (Node *) makeInteger($6);
+                   n->def = $6;
                    $$ = (Node *) n;
                }
-           /* ALTER TABLE <name> ALTER [COLUMN] <colnum> SET STATISTICS <SignedIconst> */
-           | ALTER opt_column Iconst SET STATISTICS SignedIconst
+           /* ALTER TABLE <name> ALTER [COLUMN] <colnum> SET STATISTICS */
+           | ALTER opt_column Iconst SET STATISTICS set_statistics_value
                {
                    AlterTableCmd *n = makeNode(AlterTableCmd);
 
@@ -2469,7 +2470,7 @@ alter_table_cmd:
 
                    n->subtype = AT_SetStatistics;
                    n->num = (int16) $3;
-                   n->def = (Node *) makeInteger($6);
+                   n->def = $6;
                    $$ = (Node *) n;
                }
            /* 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:
            /* a HASH partition */
            FOR VALUES WITH '(' hash_partbound ')'
index 8ec83561bfa1d7fcb99b129228646c095488aab0..f730aa26c47f56aef4b1ca3757f49e378f7afc29 100644 (file)
@@ -872,33 +872,6 @@ get_attnum(Oid relid, const char *attname)
        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
  *
index 22d1e6cf92261d654731e3044f1dc495ae0c5435..d4a888f5f137c08e8a5dc0a6b904d87a0d693ea9 100644 (file)
@@ -8925,7 +8925,10 @@ getTableAttrs(Archive *fout, TableInfo *tblinfo, int numTables)
                         tbinfo->dobj.name);
            tbinfo->attnames[j] = pg_strdup(PQgetvalue(res, r, i_attname));
            tbinfo->atttypnames[j] = pg_strdup(PQgetvalue(res, r, i_atttypname));
-           tbinfo->attstattarget[j] = atoi(PQgetvalue(res, r, i_attstattarget));
+           if (PQgetisnull(res, r, i_attstattarget))
+               tbinfo->attstattarget[j] = -1;
+           else
+               tbinfo->attstattarget[j] = atoi(PQgetvalue(res, r, i_attstattarget));
            tbinfo->attstorage[j] = *(PQgetvalue(res, r, i_attstorage));
            tbinfo->typstorage[j] = *(PQgetvalue(res, r, i_typstorage));
            tbinfo->attidentity[j] = *(PQgetvalue(res, r, i_attidentity));
@@ -16507,7 +16510,7 @@ dumpTableSchema(Archive *fout, const TableInfo *tbinfo)
            /*
             * Dump per-column statistics information. We only issue an ALTER
             * 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)
                appendPQExpBuffer(q, "ALTER %sTABLE ONLY %s ALTER COLUMN %s SET STATISTICS %d;\n",
index a94dcdc271300d38862760ac862245bd928edad8..460d80ac97e8b737b1d612aa7403b2aaf7cb2114 100644 (file)
@@ -57,6 +57,6 @@
  */
 
 /*                         yyyymmddN */
-#define CATALOG_VERSION_NO 202401111
+#define CATALOG_VERSION_NO 202401131
 
 #endif
index 7f4d308e8ddfdd11dc957503a27f5ac8a2ae441c..e2aadb941413d6a797ead54c2dfcb380324de5ee 100644 (file)
@@ -158,22 +158,22 @@ CATALOG(pg_attribute,1249,AttributeRelationId) BKI_BOOTSTRAP BKI_ROWTYPE_OID(75,
    /* Number of times inherited from direct parent relation(s) */
    int16       attinhcount BKI_DEFAULT(0);
 
+   /* attribute's collation, if any */
+   Oid         attcollation BKI_LOOKUP_OPT(pg_collation);
+
+#ifdef CATALOG_VARLEN          /* variable-length/nullable fields start here */
+   /* 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 "-1" here indicates
-    * that no value has been explicitly set for this column, so ANALYZE
-    * should use the default setting.
+    * 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(-1);
-
-   /* attribute's collation, if any */
-   Oid         attcollation BKI_LOOKUP_OPT(pg_collation);
-
-#ifdef CATALOG_VARLEN          /* variable-length fields start here */
-   /* NOTE: The following fields are not present in tuple descriptors. */
+   int16       attstattarget BKI_DEFAULT(_null_) BKI_FORCE_NULL;
 
    /* Column-level access permissions */
    aclitem     attacl[1] BKI_DEFAULT(_null_);
index 5cacefc7670ebe91cd86effe012ef10bf6b858c6..7f623b37fdc9b968b6cda144c29916c2214ce9e9 100644 (file)
@@ -121,7 +121,7 @@ typedef struct VacAttrStats
     * than the underlying column/expression.  Therefore, use these fields for
     * 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 */
    int32       attrtypmod;     /* typmod of data being analyzed */
    Form_pg_type attrtype;      /* copy of pg_type row for attrtypid */
index be9ed70e8413297f9e6744ac64ad8872db9cd81a..e4a200b00ec9c15030cdadee53c25a74dacb79bf 100644 (file)
@@ -90,7 +90,6 @@ extern Oid    get_opfamily_proc(Oid opfamily, Oid lefttype, Oid righttype,
                              int16 procnum);
 extern char *get_attname(Oid relid, AttrNumber attnum, bool missing_ok);
 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 Oid get_atttype(Oid relid, AttrNumber attnum);
 extern void get_atttypetypmodcoll(Oid relid, AttrNumber attnum,
index 446cfa678b7c1a5c2c4eee773be5cb0061506303..79fa117cb54d3674aeda6749d8820d4dc66bb2ed 100644 (file)
@@ -2707,8 +2707,8 @@ SELECT attrelid::regclass, attnum, attstattarget
          attrelid          | attnum | attstattarget 
 ---------------------------+--------+---------------
  concur_exprs_index_expr   |      1 |           100
- concur_exprs_index_pred   |      1 |            -1
- concur_exprs_index_pred_2 |      1 |            -1
+ concur_exprs_index_pred   |      1 |              
+ concur_exprs_index_pred_2 |      1 |              
 (3 rows)
 
 DROP TABLE concur_exprs_tab;