v2-0003-WIP-Add-attstattarget-to-Form_pg_attribute_extra.patch

text/plain

Filename: v2-0003-WIP-Add-attstattarget-to-Form_pg_attribute_extra.patch
Type: text/plain
Part: 2
Message: Re: Make attstattarget nullable

Patch

Format: format-patch
Series: patch v2-0003
Subject: WIP: Add attstattarget to Form_pg_attribute_extra
File+
src/backend/catalog/heap.c 4 1
src/backend/catalog/index.c 28 69
src/backend/catalog/toasting.c 1 1
src/backend/commands/indexcmds.c 1 1
src/include/catalog/index.h 1 0
src/include/catalog/pg_attribute.h 1 0
From eb616c2156163a3ca1d74f122377987b6c358764 Mon Sep 17 00:00:00 2001
From: Peter Eisentraut <peter@eisentraut.org>
Date: Sat, 23 Dec 2023 12:14:42 +0100
Subject: [PATCH v2 3/3] WIP: Add attstattarget to Form_pg_attribute_extra

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.
---
 src/backend/catalog/heap.c         |  5 +-
 src/backend/catalog/index.c        | 97 +++++++++---------------------
 src/backend/catalog/toasting.c     |  2 +-
 src/backend/commands/indexcmds.c   |  2 +-
 src/include/catalog/index.h        |  1 +
 src/include/catalog/pg_attribute.h |  1 +
 6 files changed, 36 insertions(+), 72 deletions(-)

diff --git a/src/backend/catalog/heap.c b/src/backend/catalog/heap.c
index 40b23fbead..f61c510b8d 100644
--- a/src/backend/catalog/heap.c
+++ b/src/backend/catalog/heap.c
@@ -753,18 +753,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;
diff --git a/src/backend/catalog/index.c b/src/backend/catalog/index.c
index eaeae568a3..e2ee775df1 100644
--- a/src/backend/catalog/index.c
+++ b/src/backend/catalog/index.c
@@ -112,7 +112,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,
@@ -512,7 +512,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;
@@ -529,6 +529,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;
 		}
 	}
 
@@ -735,6 +740,7 @@ index_create(Relation heapRelation,
 			 const Oid *opclassIds,
 			 const Datum *opclassOptions,
 			 const int16 *coloptions,
+			 const NullableDatum *stattargets,
 			 Datum reloptions,
 			 bits16 flags,
 			 bits16 constr_flags,
@@ -1029,7 +1035,7 @@ index_create(Relation heapRelation,
 	/*
 	 * append ATTRIBUTE tuples for the index
 	 */
-	AppendAttributeTuples(indexRelation, opclassOptions);
+	AppendAttributeTuples(indexRelation, opclassOptions, stattargets);
 
 	/* ----------------
 	 *	  update pg_index
@@ -1308,6 +1314,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;
@@ -1412,6 +1419,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);
 
+	/* Extra 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.
 	 *
@@ -1433,6 +1457,7 @@ index_concurrently_create_copy(Relation heapRelation, Oid oldIndexId,
 							  indclass->values,
 							  opclassOptions,
 							  indcoloptions->values,
+							  stattargets,
 							  reloptionsDatum,
 							  INDEX_CREATE_SKIP_BUILD | INDEX_CREATE_CONCURRENT,
 							  0,
@@ -1775,72 +1800,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);
diff --git a/src/backend/catalog/toasting.c b/src/backend/catalog/toasting.c
index 989f820791..35a0dbeeb0 100644
--- a/src/backend/catalog/toasting.c
+++ b/src/backend/catalog/toasting.c
@@ -326,7 +326,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);
diff --git a/src/backend/commands/indexcmds.c b/src/backend/commands/indexcmds.c
index e56205abd8..dbd363589f 100644
--- a/src/backend/commands/indexcmds.c
+++ b/src/backend/commands/indexcmds.c
@@ -1193,7 +1193,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);
diff --git a/src/include/catalog/index.h b/src/include/catalog/index.h
index 41a0b9aee1..cb9d380616 100644
--- a/src/include/catalog/index.h
+++ b/src/include/catalog/index.h
@@ -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,
diff --git a/src/include/catalog/pg_attribute.h b/src/include/catalog/pg_attribute.h
index 7336d7f2fd..98ab4ae538 100644
--- a/src/include/catalog/pg_attribute.h
+++ b/src/include/catalog/pg_attribute.h
@@ -210,6 +210,7 @@ typedef FormData_pg_attribute *Form_pg_attribute;
 
 typedef struct FormData_pg_attribute_extra
 {
+	NullableDatum attstattarget;
 	NullableDatum attoptions;
 } FormData_pg_attribute_extra;
 
-- 
2.43.0