aboutsummaryrefslogtreecommitdiff
path: root/src/backend
diff options
context:
space:
mode:
Diffstat (limited to 'src/backend')
-rw-r--r--src/backend/catalog/index.c56
-rw-r--r--src/backend/utils/cache/lsyscache.c27
2 files changed, 83 insertions, 0 deletions
diff --git a/src/backend/catalog/index.c b/src/backend/catalog/index.c
index 1cb9172a5f3..15149377486 100644
--- a/src/backend/catalog/index.c
+++ b/src/backend/catalog/index.c
@@ -1884,6 +1884,62 @@ 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);
+ 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 */
+ if (att->attisdropped)
+ continue;
+
+ /*
+ * Get attstattarget from the old index and refresh the new value.
+ */
+ attstattarget = get_attstattarget(oldIndexId, att->attnum);
+
+ /* no need for a refresh if both match */
+ if (attstattarget == att->attstattarget)
+ 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] = Int32GetDatum(attstattarget);
+
+ 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/utils/cache/lsyscache.c b/src/backend/utils/cache/lsyscache.c
index 85c458bc46e..6bba5f8ec4e 100644
--- a/src/backend/utils/cache/lsyscache.c
+++ b/src/backend/utils/cache/lsyscache.c
@@ -872,6 +872,33 @@ get_attnum(Oid relid, const char *attname)
}
/*
+ * 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
*
* Given the relation id and the attribute number,