From f9ad96e50abb17115a6c3292ec0cfb750db33af3 Mon Sep 17 00:00:00 2001
From: Vladlen Popolitov <v.popolitov@postgrespro.ru>
Date: Thu, 19 Sep 2024 14:17:58 +0300
Subject: [PATCH v1] maintenance_work_mem limit increased in 64-bit Windows

---
 src/backend/access/hash/hash.c        |  2 +-
 src/backend/access/heap/vacuumlazy.c  |  2 +-
 src/backend/commands/vacuumparallel.c |  2 +-
 src/backend/optimizer/path/costsize.c |  2 +-
 src/backend/utils/adt/ri_triggers.c   | 23 +++++++++++++++++++----
 src/backend/utils/misc/guc_tables.c   | 10 +++++++++-
 6 files changed, 32 insertions(+), 9 deletions(-)

diff --git a/src/backend/access/hash/hash.c b/src/backend/access/hash/hash.c
index 5ce3609394..0063902021 100644
--- a/src/backend/access/hash/hash.c
+++ b/src/backend/access/hash/hash.c
@@ -120,7 +120,7 @@ hashbuild(Relation heap, Relation index, IndexInfo *indexInfo)
 	double		reltuples;
 	double		allvisfrac;
 	uint32		num_buckets;
-	long		sort_threshold;
+	uint64		sort_threshold;
 	HashBuildState buildstate;
 
 	/*
diff --git a/src/backend/access/heap/vacuumlazy.c b/src/backend/access/heap/vacuumlazy.c
index d82aa3d489..eb658f66f1 100644
--- a/src/backend/access/heap/vacuumlazy.c
+++ b/src/backend/access/heap/vacuumlazy.c
@@ -2883,7 +2883,7 @@ dead_items_alloc(LVRelState *vacrel, int nworkers)
 	 */
 
 	dead_items_info = (VacDeadItemsInfo *) palloc(sizeof(VacDeadItemsInfo));
-	dead_items_info->max_bytes = vac_work_mem * 1024L;
+	dead_items_info->max_bytes = vac_work_mem * (size_t)1024;
 	dead_items_info->num_items = 0;
 	vacrel->dead_items_info = dead_items_info;
 
diff --git a/src/backend/commands/vacuumparallel.c b/src/backend/commands/vacuumparallel.c
index 22c057fe61..208c99c48c 100644
--- a/src/backend/commands/vacuumparallel.c
+++ b/src/backend/commands/vacuumparallel.c
@@ -373,7 +373,7 @@ parallel_vacuum_init(Relation rel, Relation *indrels, int nindexes,
 		(nindexes_mwm > 0) ?
 		maintenance_work_mem / Min(parallel_workers, nindexes_mwm) :
 		maintenance_work_mem;
-	shared->dead_items_info.max_bytes = vac_work_mem * 1024L;
+	shared->dead_items_info.max_bytes = vac_work_mem * (size_t)1024;
 
 	/* Prepare DSA space for dead items */
 	dead_items = TidStoreCreateShared(shared->dead_items_info.max_bytes,
diff --git a/src/backend/optimizer/path/costsize.c b/src/backend/optimizer/path/costsize.c
index e1523d15df..795a26e42a 100644
--- a/src/backend/optimizer/path/costsize.c
+++ b/src/backend/optimizer/path/costsize.c
@@ -1903,7 +1903,7 @@ cost_tuplesort(Cost *startup_cost, Cost *run_cost,
 	double		input_bytes = relation_byte_size(tuples, width);
 	double		output_bytes;
 	double		output_tuples;
-	long		sort_mem_bytes = sort_mem * 1024L;
+	int64		sort_mem_bytes = sort_mem * INT64CONST(1024);
 
 	/*
 	 * We want to be sure the cost of a sort is never estimated as zero, even
diff --git a/src/backend/utils/adt/ri_triggers.c b/src/backend/utils/adt/ri_triggers.c
index 6896e1ae63..eb3423f5ca 100644
--- a/src/backend/utils/adt/ri_triggers.c
+++ b/src/backend/utils/adt/ri_triggers.c
@@ -1617,11 +1617,26 @@ RI_Initial_Check(Trigger *trigger, Relation fk_rel, Relation pk_rel)
 	 * care of undoing the setting on error.
 	 */
 	save_nestlevel = NewGUCNestLevel();
+	{
+		int work_mem_new_value;
+#if SIZEOF_SIZE_T > 4 && SIZEOF_LONG > 4
+		work_mem_new_value = maintenance_work_mem;
+#else
+		if (maintenance_work_mem >= (INT_MAX / 1024))
+		{
+			work_mem_new_value = (INT_MAX / 1024);
+		}
+		else
+		{
+			work_mem_new_value = maintenance_work_mem;
+		}
+#endif
 
-	snprintf(workmembuf, sizeof(workmembuf), "%d", maintenance_work_mem);
-	(void) set_config_option("work_mem", workmembuf,
-							 PGC_USERSET, PGC_S_SESSION,
-							 GUC_ACTION_SAVE, true, 0, false);
+		snprintf(workmembuf, sizeof(workmembuf), "%d", work_mem_new_value);
+		(void) set_config_option("work_mem", workmembuf,
+								PGC_USERSET, PGC_S_SESSION,
+								GUC_ACTION_SAVE, true, 0, false);
+	}
 	(void) set_config_option("hash_mem_multiplier", "1",
 							 PGC_USERSET, PGC_S_SESSION,
 							 GUC_ACTION_SAVE, true, 0, false);
diff --git a/src/backend/utils/misc/guc_tables.c b/src/backend/utils/misc/guc_tables.c
index 686309db58..8cbadaa02a 100644
--- a/src/backend/utils/misc/guc_tables.c
+++ b/src/backend/utils/misc/guc_tables.c
@@ -722,6 +722,14 @@ const char *const config_group_names[] =
 StaticAssertDecl(lengthof(config_group_names) == (DEVELOPER_OPTIONS + 1),
 				 "array length mismatch");
 
+/* upper limit for GUC variables measured in kilobytes of memory */
+/* only for GUC variables that are not affected by a "long" variable */
+#if SIZEOF_SIZE_T > 4
+#define MAX_SIZE_T_KILOBYTES	INT_MAX
+#else
+#define MAX_SIZE_T_KILOBYTES	(INT_MAX / 1024)
+#endif
+
 /*
  * Displayable names for GUC variable types (enum config_type)
  *
@@ -2520,7 +2528,7 @@ struct config_int ConfigureNamesInt[] =
 			GUC_UNIT_KB
 		},
 		&maintenance_work_mem,
-		65536, 64, MAX_KILOBYTES,
+		65536, 64, MAX_SIZE_T_KILOBYTES,
 		NULL, NULL, NULL
 	},
 
-- 
2.42.0.windows.2

