From 42c8bc879e11ef816e50751e149f116112dc9905 Mon Sep 17 00:00:00 2001
From: Justin Pryzby <pryzbyj@telsasoft.com>
Date: Sun, 23 Oct 2022 12:29:33 -0500
Subject: [PATCH 2/4] f!Allow index AMs to build and use custom statistics

XXX: should enable GUC for CI during development

ci-os-only: windows-cross, windows-run-cross, windows-msvc
---
 src/backend/access/brin/brin_minmax.c         | 10 ++--
 src/backend/statistics/extended_stats.c       |  2 +
 src/backend/utils/adt/selfuncs.c              |  6 +--
 src/backend/utils/misc/postgresql.conf.sample |  1 +
 src/include/access/brin_internal.h            |  2 +-
 src/include/catalog/pg_amproc.dat             | 52 +++++++++----------
 src/test/regress/expected/sysviews.out        |  3 +-
 7 files changed, 41 insertions(+), 35 deletions(-)

diff --git a/src/backend/access/brin/brin_minmax.c b/src/backend/access/brin/brin_minmax.c
index e4c9e56c623..be1d9b47d5b 100644
--- a/src/backend/access/brin/brin_minmax.c
+++ b/src/backend/access/brin/brin_minmax.c
@@ -842,9 +842,11 @@ brin_minmax_count_overlaps_bruteforce(BrinRanges *ranges, TypeCacheEntry *typcac
 			if (range_values_cmp(&rb->max_value, &ra->min_value, typcache) < 0)
 				continue;
 
+#if 0
 			elog(DEBUG1, "[%ld,%ld] overlaps [%ld,%ld]",
 				 ra->min_value, ra->max_value,
 				 rb->min_value, rb->max_value);
+#endif
 
 			noverlaps++;
 		}
@@ -1173,11 +1175,11 @@ brin_minmax_value_stats(BrinRange **minranges, BrinRange **maxranges,
 
 #ifdef STATS_DEBUG
 	elog(WARNING, "----- brin_minmax_value_stats -----");
-	elog(WARNING, "minval ndistinct %ld correlation %f",
-		 *minval_ndistinct, *minval_correlation);
+	elog(WARNING, "minval ndistinct %lld correlation %f",
+		 (long long)*minval_ndistinct, *minval_correlation);
 
-	elog(WARNING, "maxval ndistinct %ld correlation %f",
-		 *maxval_ndistinct, *maxval_correlation);
+	elog(WARNING, "maxval ndistinct %lld correlation %f",
+		 (long long)*maxval_ndistinct, *maxval_correlation);
 #endif
 }
 
diff --git a/src/backend/statistics/extended_stats.c b/src/backend/statistics/extended_stats.c
index ab97e71dd79..d91b4fd93eb 100644
--- a/src/backend/statistics/extended_stats.c
+++ b/src/backend/statistics/extended_stats.c
@@ -2370,6 +2370,8 @@ serialize_expr_stats(AnlExprData *exprdata, int nexprs)
 		values[Anum_pg_statistic_stanullfrac - 1] = Float4GetDatum(stats->stanullfrac);
 		values[Anum_pg_statistic_stawidth - 1] = Int32GetDatum(stats->stawidth);
 		values[Anum_pg_statistic_stadistinct - 1] = Float4GetDatum(stats->stadistinct);
+		nulls[Anum_pg_statistic_staindexam - 1] = true;
+
 		i = Anum_pg_statistic_stakind1 - 1;
 		for (k = 0; k < STATISTIC_NUM_SLOTS; k++)
 		{
diff --git a/src/backend/utils/adt/selfuncs.c b/src/backend/utils/adt/selfuncs.c
index 9f640adb13c..14e0885f19f 100644
--- a/src/backend/utils/adt/selfuncs.c
+++ b/src/backend/utils/adt/selfuncs.c
@@ -7789,9 +7789,9 @@ brincostestimate(PlannerInfo *root, IndexPath *path, double loop_count,
 
 				if (amstats)
 				{
-					elog(DEBUG1, "found AM stats: attnum %d n_ranges %ld n_summarized %ld n_all_nulls %ld n_has_nulls %ld avg_overlaps %f",
-						 attnum, amstats->n_ranges, amstats->n_summarized,
-						 amstats->n_all_nulls, amstats->n_has_nulls,
+					elog(DEBUG1, "found AM stats: attnum %d n_ranges %lld n_summarized %lld n_all_nulls %lld n_has_nulls %lld avg_overlaps %f",
+						 attnum, (long long)amstats->n_ranges, (long long)amstats->n_summarized,
+						 (long long)amstats->n_all_nulls, (long long)amstats->n_has_nulls,
 						 amstats->avg_overlaps);
 
 					/*
diff --git a/src/backend/utils/misc/postgresql.conf.sample b/src/backend/utils/misc/postgresql.conf.sample
index 868d21c351e..8c5d442ff45 100644
--- a/src/backend/utils/misc/postgresql.conf.sample
+++ b/src/backend/utils/misc/postgresql.conf.sample
@@ -374,6 +374,7 @@
 #enable_hashagg = on
 #enable_hashjoin = on
 #enable_incremental_sort = on
+#enable_indexam_stats = off
 #enable_indexscan = on
 #enable_indexonlyscan = on
 #enable_material = on
diff --git a/src/include/access/brin_internal.h b/src/include/access/brin_internal.h
index ee6c6f9b709..f4be357c176 100644
--- a/src/include/access/brin_internal.h
+++ b/src/include/access/brin_internal.h
@@ -73,9 +73,9 @@ typedef struct BrinDesc
 #define BRIN_PROCNUM_UNION			4
 #define BRIN_MANDATORY_NPROCS		4
 #define BRIN_PROCNUM_OPTIONS 		5	/* optional */
-#define BRIN_PROCNUM_STATISTICS		6	/* optional */
 /* procedure numbers up to 10 are reserved for BRIN future expansion */
 #define BRIN_FIRST_OPTIONAL_PROCNUM 11
+#define BRIN_PROCNUM_STATISTICS		11	/* optional */
 #define BRIN_LAST_OPTIONAL_PROCNUM	15
 
 #undef BRIN_DEBUG
diff --git a/src/include/catalog/pg_amproc.dat b/src/include/catalog/pg_amproc.dat
index ea3de9bcba1..558df53206d 100644
--- a/src/include/catalog/pg_amproc.dat
+++ b/src/include/catalog/pg_amproc.dat
@@ -805,7 +805,7 @@
 { amprocfamily => 'brin/bytea_minmax_ops', amproclefttype => 'bytea',
   amprocrighttype => 'bytea', amprocnum => '4', amproc => 'brin_minmax_union' },
 { amprocfamily => 'brin/bytea_minmax_ops', amproclefttype => 'bytea',
-  amprocrighttype => 'bytea', amprocnum => '6', amproc => 'brin_minmax_stats' },
+  amprocrighttype => 'bytea', amprocnum => '11', amproc => 'brin_minmax_stats' },
 
 # bloom bytea
 { amprocfamily => 'brin/bytea_bloom_ops', amproclefttype => 'bytea',
@@ -838,7 +838,7 @@
 { amprocfamily => 'brin/char_minmax_ops', amproclefttype => 'char',
   amprocrighttype => 'char', amprocnum => '4', amproc => 'brin_minmax_union' },
 { amprocfamily => 'brin/char_minmax_ops', amproclefttype => 'char',
-  amprocrighttype => 'char', amprocnum => '6', amproc => 'brin_minmax_stats' },
+  amprocrighttype => 'char', amprocnum => '11', amproc => 'brin_minmax_stats' },
 
 # bloom "char"
 { amprocfamily => 'brin/char_bloom_ops', amproclefttype => 'char',
@@ -869,7 +869,7 @@
 { amprocfamily => 'brin/name_minmax_ops', amproclefttype => 'name',
   amprocrighttype => 'name', amprocnum => '4', amproc => 'brin_minmax_union' },
 { amprocfamily => 'brin/name_minmax_ops', amproclefttype => 'name',
-  amprocrighttype => 'name', amprocnum => '6', amproc => 'brin_minmax_stats' },
+  amprocrighttype => 'name', amprocnum => '11', amproc => 'brin_minmax_stats' },
 
 # bloom name
 { amprocfamily => 'brin/name_bloom_ops', amproclefttype => 'name',
@@ -900,7 +900,7 @@
 { amprocfamily => 'brin/integer_minmax_ops', amproclefttype => 'int8',
   amprocrighttype => 'int8', amprocnum => '4', amproc => 'brin_minmax_union' },
 { amprocfamily => 'brin/integer_minmax_ops', amproclefttype => 'int8',
-  amprocrighttype => 'int8', amprocnum => '6', amproc => 'brin_minmax_stats' },
+  amprocrighttype => 'int8', amprocnum => '11', amproc => 'brin_minmax_stats' },
 
 { amprocfamily => 'brin/integer_minmax_ops', amproclefttype => 'int2',
   amprocrighttype => 'int2', amprocnum => '1',
@@ -914,7 +914,7 @@
 { amprocfamily => 'brin/integer_minmax_ops', amproclefttype => 'int2',
   amprocrighttype => 'int2', amprocnum => '4', amproc => 'brin_minmax_union' },
 { amprocfamily => 'brin/integer_minmax_ops', amproclefttype => 'int2',
-  amprocrighttype => 'int2', amprocnum => '6', amproc => 'brin_minmax_stats' },
+  amprocrighttype => 'int2', amprocnum => '11', amproc => 'brin_minmax_stats' },
 
 { amprocfamily => 'brin/integer_minmax_ops', amproclefttype => 'int4',
   amprocrighttype => 'int4', amprocnum => '1',
@@ -928,7 +928,7 @@
 { amprocfamily => 'brin/integer_minmax_ops', amproclefttype => 'int4',
   amprocrighttype => 'int4', amprocnum => '4', amproc => 'brin_minmax_union' },
 { amprocfamily => 'brin/integer_minmax_ops', amproclefttype => 'int4',
-  amprocrighttype => 'int4', amprocnum => '6', amproc => 'brin_minmax_stats' },
+  amprocrighttype => 'int4', amprocnum => '11', amproc => 'brin_minmax_stats' },
 
 # minmax multi integer: int2, int4, int8
 { amprocfamily => 'brin/integer_minmax_multi_ops', amproclefttype => 'int2',
@@ -1047,7 +1047,7 @@
 { amprocfamily => 'brin/text_minmax_ops', amproclefttype => 'text',
   amprocrighttype => 'text', amprocnum => '4', amproc => 'brin_minmax_union' },
 { amprocfamily => 'brin/text_minmax_ops', amproclefttype => 'text',
-  amprocrighttype => 'text', amprocnum => '6', amproc => 'brin_minmax_stats' },
+  amprocrighttype => 'text', amprocnum => '11', amproc => 'brin_minmax_stats' },
 
 # bloom text
 { amprocfamily => 'brin/text_bloom_ops', amproclefttype => 'text',
@@ -1077,7 +1077,7 @@
 { amprocfamily => 'brin/oid_minmax_ops', amproclefttype => 'oid',
   amprocrighttype => 'oid', amprocnum => '4', amproc => 'brin_minmax_union' },
 { amprocfamily => 'brin/oid_minmax_ops', amproclefttype => 'oid',
-  amprocrighttype => 'oid', amprocnum => '6', amproc => 'brin_minmax_stats' },
+  amprocrighttype => 'oid', amprocnum => '11', amproc => 'brin_minmax_stats' },
 
 # minmax multi oid
 { amprocfamily => 'brin/oid_minmax_multi_ops', amproclefttype => 'oid',
@@ -1127,7 +1127,7 @@
 { amprocfamily => 'brin/tid_minmax_ops', amproclefttype => 'tid',
   amprocrighttype => 'tid', amprocnum => '4', amproc => 'brin_minmax_union' },
 { amprocfamily => 'brin/tid_minmax_ops', amproclefttype => 'tid',
-  amprocrighttype => 'tid', amprocnum => '6', amproc => 'brin_minmax_stats' },
+  amprocrighttype => 'tid', amprocnum => '11', amproc => 'brin_minmax_stats' },
 
 # bloom tid
 { amprocfamily => 'brin/tid_bloom_ops', amproclefttype => 'tid',
@@ -1179,7 +1179,7 @@
   amprocrighttype => 'float4', amprocnum => '4',
   amproc => 'brin_minmax_union' },
 { amprocfamily => 'brin/float_minmax_ops', amproclefttype => 'float4',
-  amprocrighttype => 'float4', amprocnum => '6',
+  amprocrighttype => 'float4', amprocnum => '11',
   amproc => 'brin_minmax_stats' },
 
 { amprocfamily => 'brin/float_minmax_ops', amproclefttype => 'float8',
@@ -1195,7 +1195,7 @@
   amprocrighttype => 'float8', amprocnum => '4',
   amproc => 'brin_minmax_union' },
 { amprocfamily => 'brin/float_minmax_ops', amproclefttype => 'float8',
-  amprocrighttype => 'float8', amprocnum => '6',
+  amprocrighttype => 'float8', amprocnum => '11',
   amproc => 'brin_minmax_stats' },
 
 # minmax multi float
@@ -1286,7 +1286,7 @@
   amprocrighttype => 'macaddr', amprocnum => '4',
   amproc => 'brin_minmax_union' },
 { amprocfamily => 'brin/macaddr_minmax_ops', amproclefttype => 'macaddr',
-  amprocrighttype => 'macaddr', amprocnum => '6',
+  amprocrighttype => 'macaddr', amprocnum => '11',
   amproc => 'brin_minmax_stats' },
 
 # minmax multi macaddr
@@ -1342,7 +1342,7 @@
   amprocrighttype => 'macaddr8', amprocnum => '4',
   amproc => 'brin_minmax_union' },
 { amprocfamily => 'brin/macaddr8_minmax_ops', amproclefttype => 'macaddr8',
-  amprocrighttype => 'macaddr8', amprocnum => '6',
+  amprocrighttype => 'macaddr8', amprocnum => '11',
   amproc => 'brin_minmax_stats' },
 
 # minmax multi macaddr8
@@ -1397,7 +1397,7 @@
 { amprocfamily => 'brin/network_minmax_ops', amproclefttype => 'inet',
   amprocrighttype => 'inet', amprocnum => '4', amproc => 'brin_minmax_union' },
 { amprocfamily => 'brin/network_minmax_ops', amproclefttype => 'inet',
-  amprocrighttype => 'inet', amprocnum => '6', amproc => 'brin_minmax_stats' },
+  amprocrighttype => 'inet', amprocnum => '11', amproc => 'brin_minmax_stats' },
 
 # minmax multi inet
 { amprocfamily => 'brin/network_minmax_multi_ops', amproclefttype => 'inet',
@@ -1469,7 +1469,7 @@
   amprocrighttype => 'bpchar', amprocnum => '4',
   amproc => 'brin_minmax_union' },
 { amprocfamily => 'brin/bpchar_minmax_ops', amproclefttype => 'bpchar',
-  amprocrighttype => 'bpchar', amprocnum => '6',
+  amprocrighttype => 'bpchar', amprocnum => '11',
   amproc => 'brin_minmax_stats' },
 
 # bloom character
@@ -1503,7 +1503,7 @@
 { amprocfamily => 'brin/time_minmax_ops', amproclefttype => 'time',
   amprocrighttype => 'time', amprocnum => '4', amproc => 'brin_minmax_union' },
 { amprocfamily => 'brin/time_minmax_ops', amproclefttype => 'time',
-  amprocrighttype => 'time', amprocnum => '6', amproc => 'brin_minmax_stats' },
+  amprocrighttype => 'time', amprocnum => '11', amproc => 'brin_minmax_stats' },
 
 # minmax multi time without time zone
 { amprocfamily => 'brin/time_minmax_multi_ops', amproclefttype => 'time',
@@ -1555,7 +1555,7 @@
   amprocrighttype => 'timestamp', amprocnum => '4',
   amproc => 'brin_minmax_union' },
 { amprocfamily => 'brin/datetime_minmax_ops', amproclefttype => 'timestamp',
-  amprocrighttype => 'timestamp', amprocnum => '6',
+  amprocrighttype => 'timestamp', amprocnum => '11',
   amproc => 'brin_minmax_stats' },
 
 { amprocfamily => 'brin/datetime_minmax_ops', amproclefttype => 'timestamptz',
@@ -1571,7 +1571,7 @@
   amprocrighttype => 'timestamptz', amprocnum => '4',
   amproc => 'brin_minmax_union' },
 { amprocfamily => 'brin/datetime_minmax_ops', amproclefttype => 'timestamptz',
-  amprocrighttype => 'timestamptz', amprocnum => '6',
+  amprocrighttype => 'timestamptz', amprocnum => '11',
   amproc => 'brin_minmax_stats' },
 
 { amprocfamily => 'brin/datetime_minmax_ops', amproclefttype => 'date',
@@ -1586,7 +1586,7 @@
 { amprocfamily => 'brin/datetime_minmax_ops', amproclefttype => 'date',
   amprocrighttype => 'date', amprocnum => '4', amproc => 'brin_minmax_union' },
 { amprocfamily => 'brin/datetime_minmax_ops', amproclefttype => 'date',
-  amprocrighttype => 'date', amprocnum => '6', amproc => 'brin_minmax_stats' },
+  amprocrighttype => 'date', amprocnum => '11', amproc => 'brin_minmax_stats' },
 
 # minmax multi datetime (date, timestamp, timestamptz)
 { amprocfamily => 'brin/datetime_minmax_multi_ops',
@@ -1714,7 +1714,7 @@
   amprocrighttype => 'interval', amprocnum => '4',
   amproc => 'brin_minmax_union' },
 { amprocfamily => 'brin/interval_minmax_ops', amproclefttype => 'interval',
-  amprocrighttype => 'interval', amprocnum => '6',
+  amprocrighttype => 'interval', amprocnum => '11',
   amproc => 'brin_minmax_stats' },
 
 # minmax multi interval
@@ -1770,7 +1770,7 @@
   amprocrighttype => 'timetz', amprocnum => '4',
   amproc => 'brin_minmax_union' },
 { amprocfamily => 'brin/timetz_minmax_ops', amproclefttype => 'timetz',
-  amprocrighttype => 'timetz', amprocnum => '6',
+  amprocrighttype => 'timetz', amprocnum => '11',
   amproc => 'brin_minmax_stats' },
 
 # minmax multi time with time zone
@@ -1823,7 +1823,7 @@
 { amprocfamily => 'brin/bit_minmax_ops', amproclefttype => 'bit',
   amprocrighttype => 'bit', amprocnum => '4', amproc => 'brin_minmax_union' },
 { amprocfamily => 'brin/bit_minmax_ops', amproclefttype => 'bit',
-  amprocrighttype => 'bit', amprocnum => '6', amproc => 'brin_minmax_stats' },
+  amprocrighttype => 'bit', amprocnum => '11', amproc => 'brin_minmax_stats' },
 
 # minmax bit varying
 { amprocfamily => 'brin/varbit_minmax_ops', amproclefttype => 'varbit',
@@ -1839,7 +1839,7 @@
   amprocrighttype => 'varbit', amprocnum => '4',
   amproc => 'brin_minmax_union' },
 { amprocfamily => 'brin/varbit_minmax_ops', amproclefttype => 'varbit',
-  amprocrighttype => 'varbit', amprocnum => '6',
+  amprocrighttype => 'varbit', amprocnum => '11',
   amproc => 'brin_minmax_stats' },
 
 # minmax numeric
@@ -1856,7 +1856,7 @@
   amprocrighttype => 'numeric', amprocnum => '4',
   amproc => 'brin_minmax_union' },
 { amprocfamily => 'brin/numeric_minmax_ops', amproclefttype => 'numeric',
-  amprocrighttype => 'numeric', amprocnum => '6',
+  amprocrighttype => 'numeric', amprocnum => '11',
   amproc => 'brin_minmax_stats' },
 
 # minmax multi numeric
@@ -1911,7 +1911,7 @@
 { amprocfamily => 'brin/uuid_minmax_ops', amproclefttype => 'uuid',
   amprocrighttype => 'uuid', amprocnum => '4', amproc => 'brin_minmax_union' },
 { amprocfamily => 'brin/uuid_minmax_ops', amproclefttype => 'uuid',
-  amprocrighttype => 'uuid', amprocnum => '6', amproc => 'brin_minmax_stats' },
+  amprocrighttype => 'uuid', amprocnum => '11', amproc => 'brin_minmax_stats' },
 
 # minmax multi uuid
 { amprocfamily => 'brin/uuid_minmax_multi_ops', amproclefttype => 'uuid',
@@ -1986,7 +1986,7 @@
   amprocrighttype => 'pg_lsn', amprocnum => '4',
   amproc => 'brin_minmax_union' },
 { amprocfamily => 'brin/pg_lsn_minmax_ops', amproclefttype => 'pg_lsn',
-  amprocrighttype => 'pg_lsn', amprocnum => '6',
+  amprocrighttype => 'pg_lsn', amprocnum => '11',
   amproc => 'brin_minmax_stats' },
 
 # minmax multi pg_lsn
diff --git a/src/test/regress/expected/sysviews.out b/src/test/regress/expected/sysviews.out
index 579b861d84f..b19dae255e9 100644
--- a/src/test/regress/expected/sysviews.out
+++ b/src/test/regress/expected/sysviews.out
@@ -117,6 +117,7 @@ select name, setting from pg_settings where name like 'enable%';
  enable_hashagg                 | on
  enable_hashjoin                | on
  enable_incremental_sort        | on
+ enable_indexam_stats           | off
  enable_indexonlyscan           | on
  enable_indexscan               | on
  enable_material                | on
@@ -131,7 +132,7 @@ select name, setting from pg_settings where name like 'enable%';
  enable_seqscan                 | on
  enable_sort                    | on
  enable_tidscan                 | on
-(20 rows)
+(21 rows)
 
 -- Test that the pg_timezone_names and pg_timezone_abbrevs views are
 -- more-or-less working.  We can't test their contents in any great detail
-- 
2.25.1

