]> git.ipfire.org Git - thirdparty/postgresql.git/commitdiff
Add attstattarget to FormExtraData_pg_attribute
authorPeter Eisentraut <peter@eisentraut.org>
Sun, 17 Mar 2024 11:38:27 +0000 (12:38 +0100)
committerPeter Eisentraut <peter@eisentraut.org>
Sun, 17 Mar 2024 11:38:27 +0000 (12:38 +0100)
This allows setting attstattarget when a relation is created.

We make use of this by having index_concurrently_create_copy() copy
over the attstattarget values when the new index is created, instead
of having index_concurrently_swap() fix it up later.

Reviewed-by: Tomas Vondra <tomas.vondra@enterprisedb.com>
Discussion: https://www.postgresql.org/message-id/flat/4da8d211-d54d-44b9-9847-f2a9f1184c76@eisentraut.org

src/backend/catalog/heap.c
src/backend/catalog/index.c
src/backend/catalog/toasting.c
src/backend/commands/indexcmds.c
src/include/catalog/index.h
src/include/catalog/pg_attribute.h

index de982c2c529e59852c82162688589819d90a206b..cc31909012d513dbc129b4d630970e2e26acc0ed 100644 (file)
@@ -758,18 +758,21 @@ InsertPgAttributeTuples(Relation pg_attribute_rel,
                slot[slotCount]->tts_values[Anum_pg_attribute_attcollation - 1] = ObjectIdGetDatum(attrs->attcollation);
                if (attrs_extra)
                {
+                       slot[slotCount]->tts_values[Anum_pg_attribute_attstattarget - 1] = attrs_extra->attstattarget.value;
+                       slot[slotCount]->tts_isnull[Anum_pg_attribute_attstattarget - 1] = attrs_extra->attstattarget.isnull;
+
                        slot[slotCount]->tts_values[Anum_pg_attribute_attoptions - 1] = attrs_extra->attoptions.value;
                        slot[slotCount]->tts_isnull[Anum_pg_attribute_attoptions - 1] = attrs_extra->attoptions.isnull;
                }
                else
                {
+                       slot[slotCount]->tts_isnull[Anum_pg_attribute_attstattarget - 1] = true;
                        slot[slotCount]->tts_isnull[Anum_pg_attribute_attoptions - 1] = true;
                }
 
                /*
                 * 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;
index 7e428f3eb79dc8800df13ea6213168dbd6530906..b6a7c60e230fc9afe18aa669a1e1351b4a1e0449 100644 (file)
@@ -107,7 +107,7 @@ static TupleDesc ConstructTupleDescriptor(Relation heapRelation,
                                                                                  const Oid *opclassIds);
 static void InitializeAttributeOids(Relation indexRelation,
                                                                        int numatts, Oid indexoid);
-static void AppendAttributeTuples(Relation indexRelation, const Datum *attopts);
+static void AppendAttributeTuples(Relation indexRelation, const Datum *attopts, const NullableDatum *stattargets);
 static void UpdateIndexRelation(Oid indexoid, Oid heapoid,
                                                                Oid parentIndexId,
                                                                const IndexInfo *indexInfo,
@@ -507,7 +507,7 @@ InitializeAttributeOids(Relation indexRelation,
  * ----------------------------------------------------------------
  */
 static void
-AppendAttributeTuples(Relation indexRelation, const Datum *attopts)
+AppendAttributeTuples(Relation indexRelation, const Datum *attopts, const NullableDatum *stattargets)
 {
        Relation        pg_attribute;
        CatalogIndexState indstate;
@@ -524,6 +524,11 @@ AppendAttributeTuples(Relation indexRelation, const Datum *attopts)
                                attrs_extra[i].attoptions.value = attopts[i];
                        else
                                attrs_extra[i].attoptions.isnull = true;
+
+                       if (stattargets)
+                               attrs_extra[i].attstattarget = stattargets[i];
+                       else
+                               attrs_extra[i].attstattarget.isnull = true;
                }
        }
 
@@ -730,6 +735,7 @@ index_create(Relation heapRelation,
                         const Oid *opclassIds,
                         const Datum *opclassOptions,
                         const int16 *coloptions,
+                        const NullableDatum *stattargets,
                         Datum reloptions,
                         bits16 flags,
                         bits16 constr_flags,
@@ -1024,7 +1030,7 @@ index_create(Relation heapRelation,
        /*
         * append ATTRIBUTE tuples for the index
         */
-       AppendAttributeTuples(indexRelation, opclassOptions);
+       AppendAttributeTuples(indexRelation, opclassOptions, stattargets);
 
        /* ----------------
         *        update pg_index
@@ -1303,6 +1309,7 @@ index_concurrently_create_copy(Relation heapRelation, Oid oldIndexId,
        Datum      *opclassOptions;
        oidvector  *indclass;
        int2vector *indcoloptions;
+       NullableDatum *stattargets;
        bool            isnull;
        List       *indexColNames = NIL;
        List       *indexExprs = NIL;
@@ -1407,6 +1414,23 @@ index_concurrently_create_copy(Relation heapRelation, Oid oldIndexId,
        for (int i = 0; i < newInfo->ii_NumIndexAttrs; i++)
                opclassOptions[i] = get_attoptions(oldIndexId, i + 1);
 
+       /* Extract statistic targets for each attribute */
+       stattargets = palloc0_array(NullableDatum, newInfo->ii_NumIndexAttrs);
+       for (int i = 0; i < newInfo->ii_NumIndexAttrs; i++)
+       {
+               HeapTuple       tp;
+               Datum           dat;
+
+               tp = SearchSysCache2(ATTNUM, ObjectIdGetDatum(oldIndexId), Int16GetDatum(i + 1));
+               if (!HeapTupleIsValid(tp))
+                       elog(ERROR, "cache lookup failed for attribute %d of relation %u",
+                                i + 1, oldIndexId);
+               dat = SysCacheGetAttr(ATTNUM, tp, Anum_pg_attribute_attstattarget, &isnull);
+               ReleaseSysCache(tp);
+               stattargets[i].value = dat;
+               stattargets[i].isnull = isnull;
+       }
+
        /*
         * Now create the new index.
         *
@@ -1428,6 +1452,7 @@ index_concurrently_create_copy(Relation heapRelation, Oid oldIndexId,
                                                          indclass->values,
                                                          opclassOptions,
                                                          indcoloptions->values,
+                                                         stattargets,
                                                          reloptionsDatum,
                                                          INDEX_CREATE_SKIP_BUILD | INDEX_CREATE_CONCURRENT,
                                                          0,
@@ -1771,72 +1796,6 @@ index_concurrently_swap(Oid newIndexId, Oid oldIndexId, const char *oldName)
        /* Copy data of pg_statistic from the old index to the new one */
        CopyStatistics(oldIndexId, newIndexId);
 
-       /* Copy pg_attribute.attstattarget for each index attribute */
-       {
-               HeapTuple       attrTuple;
-               Relation        pg_attribute;
-               SysScanDesc scan;
-               ScanKeyData key[1];
-
-               pg_attribute = table_open(AttributeRelationId, RowExclusiveLock);
-               ScanKeyInit(&key[0],
-                                       Anum_pg_attribute_attrelid,
-                                       BTEqualStrategyNumber, F_OIDEQ,
-                                       ObjectIdGetDatum(newIndexId));
-               scan = systable_beginscan(pg_attribute, AttributeRelidNumIndexId,
-                                                                 true, NULL, 1, key);
-
-               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];
-                       HeapTuple       newTuple;
-
-                       /* Ignore dropped columns */
-                       if (att->attisdropped)
-                               continue;
-
-                       /*
-                        * Get attstattarget from the old index and refresh the new value.
-                        */
-                       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 old index value is null.  (All new
-                        * index values are null at this point.)
-                        */
-                       if (isnull)
-                               continue;
-
-                       memset(repl_val, 0, sizeof(repl_val));
-                       memset(repl_null, false, sizeof(repl_null));
-                       memset(repl_repl, false, sizeof(repl_repl));
-
-                       repl_repl[Anum_pg_attribute_attstattarget - 1] = true;
-                       repl_val[Anum_pg_attribute_attstattarget - 1] = dat;
-
-                       newTuple = heap_modify_tuple(attrTuple,
-                                                                                RelationGetDescr(pg_attribute),
-                                                                                repl_val, repl_null, repl_repl);
-                       CatalogTupleUpdate(pg_attribute, &newTuple->t_self, newTuple);
-
-                       heap_freetuple(newTuple);
-               }
-
-               systable_endscan(scan);
-               table_close(pg_attribute, RowExclusiveLock);
-       }
-
        /* Close relations */
        table_close(pg_class, RowExclusiveLock);
        table_close(pg_index, RowExclusiveLock);
index 21be81c1fb37ea3196b1eb22d2a337614a604de5..738bc46ae8293cf45d8ffdbda90b1dd41d1213ea 100644 (file)
@@ -323,7 +323,7 @@ create_toast_table(Relation rel, Oid toastOid, Oid toastIndexOid,
                                 list_make2("chunk_id", "chunk_seq"),
                                 BTREE_AM_OID,
                                 rel->rd_rel->reltablespace,
-                                collationIds, opclassIds, NULL, coloptions, (Datum) 0,
+                                collationIds, opclassIds, NULL, coloptions, NULL, (Datum) 0,
                                 INDEX_CREATE_IS_PRIMARY, 0, true, true, NULL);
 
        table_close(toast_rel, NoLock);
index de89be8d759721aee500b3f076ea60ac2e4f9ca6..7b20d103c867165bcf1c53abb2f541b100d9d235 100644 (file)
@@ -1210,7 +1210,7 @@ DefineIndex(Oid tableId,
                                         stmt->oldNumber, indexInfo, indexColNames,
                                         accessMethodId, tablespaceId,
                                         collationIds, opclassIds, opclassOptions,
-                                        coloptions, reloptions,
+                                        coloptions, NULL, reloptions,
                                         flags, constr_flags,
                                         allowSystemTableMods, !check_rights,
                                         &createdConstraintId);
index 2ef8512dbffe8fc28e04995f7b5af5750d85718f..2dea96f47c396648bfa992b07414b5a0ac1c5b31 100644 (file)
@@ -80,6 +80,7 @@ extern Oid    index_create(Relation heapRelation,
                                                 const Oid *opclassIds,
                                                 const Datum *opclassOptions,
                                                 const int16 *coloptions,
+                                                const NullableDatum *stattargets,
                                                 Datum reloptions,
                                                 bits16 flags,
                                                 bits16 constr_flags,
index 1cc7a848f03df6f344e94bc87a84c5f2e66cdb71..1c62b8bfcb58e244e45d45bd57f923e6a0d23bba 100644 (file)
@@ -218,6 +218,7 @@ typedef FormData_pg_attribute *Form_pg_attribute;
  */
 typedef struct FormExtraData_pg_attribute
 {
+       NullableDatum attstattarget;
        NullableDatum attoptions;
 } FormExtraData_pg_attribute;