From b61edc12210eb71c8a7a987171e8bbf39299989c Mon Sep 17 00:00:00 2001
From: Tatsuo Ishii <ishii@postgresql.org>
Date: Wed, 10 Jul 2024 16:22:41 +0900
Subject: [PATCH v2 5/5] Add memory/disk usage for Window Aggregate nodes in
 EXPLAIN

---
 src/backend/commands/explain.c       | 12 ++++++++++++
 src/backend/executor/nodeWindowAgg.c | 19 +++++++++++++++++++
 src/include/nodes/execnodes.h        |  2 ++
 3 files changed, 33 insertions(+)

diff --git a/src/backend/commands/explain.c b/src/backend/commands/explain.c
index 054d909093..5f32c967e1 100644
--- a/src/backend/commands/explain.c
+++ b/src/backend/commands/explain.c
@@ -131,6 +131,7 @@ static void show_material_info(MaterialState *mstate, ExplainState *es);
 static void show_ctescan_info(CteScanState *ctescanstate, ExplainState *es);
 static void show_table_func_can_info(TableFuncScanState *tscanstate, ExplainState *es);
 static void show_recursive_union_info(RecursiveUnionState *rstate, ExplainState *es);
+static void show_windowagg_info(WindowAggState *winstate, ExplainState *es);
 static void show_memoize_info(MemoizeState *mstate, List *ancestors,
 							  ExplainState *es);
 static void show_hashagg_info(AggState *aggstate, ExplainState *es);
@@ -2222,6 +2223,7 @@ ExplainNode(PlanState *planstate, List *ancestors,
 										   planstate, es);
 			show_upper_qual(((WindowAgg *) plan)->runConditionOrig,
 							"Run Condition", planstate, ancestors, es);
+			show_windowagg_info(castNode(WindowAggState, planstate), es);
 			break;
 		case T_Group:
 			show_group_keys(castNode(GroupState, planstate), ancestors, es);
@@ -3426,6 +3428,16 @@ show_recursive_union_info(RecursiveUnionState *rstate, ExplainState *es)
 	show_storage_info(NULL, rstate->storageSize, rstate->storageType, es);
 }
 
+/*
+ * Show information on WindowAgg node, storage method and maximum memory/disk
+ * space used.
+ */
+static void
+show_windowagg_info(WindowAggState *winstate, ExplainState *es)
+{
+	show_storage_info(NULL, winstate->storageSize, winstate->storageType, es);
+}
+
 /*
  * Show information on memoize hits/misses/evictions and memory usage.
  */
diff --git a/src/backend/executor/nodeWindowAgg.c b/src/backend/executor/nodeWindowAgg.c
index 3221fa1522..bcfe144511 100644
--- a/src/backend/executor/nodeWindowAgg.c
+++ b/src/backend/executor/nodeWindowAgg.c
@@ -1360,7 +1360,23 @@ release_partition(WindowAggState *winstate)
 	}
 
 	if (winstate->buffer)
+	{
+		int64	spaceUsed = tuplestore_space_used(winstate->buffer);
+
+		/*
+		 * We want to track the max mem/disk usage so that we can use the info
+		 * in EXPLAIN (ANALYZE).
+		 */
+		if (spaceUsed > winstate->storageSize)
+		{
+			if (winstate->storageType != NULL)
+				pfree(winstate->storageType);
+			winstate->storageType =
+				pstrdup(tuplestore_storage_type_name(winstate->buffer));
+			winstate->storageSize = spaceUsed;
+		}
 		tuplestore_end(winstate->buffer);
+	}
 	winstate->buffer = NULL;
 	winstate->partition_spooled = false;
 }
@@ -2671,6 +2687,9 @@ ExecInitWindowAgg(WindowAgg *node, EState *estate, int eflags)
 	winstate->partition_spooled = false;
 	winstate->more_partitions = false;
 
+	winstate->storageType = NULL;
+	winstate->storageSize = 0;
+
 	return winstate;
 }
 
diff --git a/src/include/nodes/execnodes.h b/src/include/nodes/execnodes.h
index bc2c0baed6..82a597aae9 100644
--- a/src/include/nodes/execnodes.h
+++ b/src/include/nodes/execnodes.h
@@ -2596,6 +2596,8 @@ typedef struct WindowAggState
 	ExprState  *partEqfunction; /* equality funcs for partition columns */
 	ExprState  *ordEqfunction;	/* equality funcs for ordering columns */
 	Tuplestorestate *buffer;	/* stores rows of current partition */
+	int64		storageSize;	/* max storage size in buffer */
+	char		*storageType;	/* the storage type above */
 	int			current_ptr;	/* read pointer # for current row */
 	int			framehead_ptr;	/* read pointer # for frame head, if used */
 	int			frametail_ptr;	/* read pointer # for frame tail, if used */
-- 
2.25.1

