From 4d6b08f5680ecf7f34578f52945d448007bbc0df Mon Sep 17 00:00:00 2001
From: Nazir Bilal Yavuz <byavuz81@gmail.com>
Date: Mon, 24 Mar 2025 13:53:26 +0300
Subject: [PATCH v5 2/3] Return buffer flushed information in
 pg_buffercache_evict function

Prior commit added ability to get buffer flushed information from
EvictUnpinnedBuffer() function. Show this information in
pg_buffercache_evict() function too.

Author: Nazir Bilal Yavuz <byavuz81@gmail.com>
Suggested-by: Joseph Koshakow <koshy44@gmail.com>
Reviewed-by: Aidar Imamov <a.imamov@postgrespro.ru>
Discussion: https://postgr.es/m/CAN55FZ0h_YoSqqutxV6DES1RW8ig6wcA8CR9rJk358YRMxZFmw%40mail.gmail.com
---
 .../pg_buffercache--1.5--1.6.sql              |  8 ++++++++
 contrib/pg_buffercache/pg_buffercache_pages.c | 20 ++++++++++++++++++-
 doc/src/sgml/pgbuffercache.sgml               | 15 ++++++++------
 3 files changed, 36 insertions(+), 7 deletions(-)

diff --git a/contrib/pg_buffercache/pg_buffercache--1.5--1.6.sql b/contrib/pg_buffercache/pg_buffercache--1.5--1.6.sql
index 2e255f3fc10..d54bb1fd6f8 100644
--- a/contrib/pg_buffercache/pg_buffercache--1.5--1.6.sql
+++ b/contrib/pg_buffercache/pg_buffercache--1.5--1.6.sql
@@ -1,5 +1,13 @@
 \echo Use "ALTER EXTENSION pg_buffercache UPDATE TO '1.6'" to load this file. \quit
 
+DROP FUNCTION pg_buffercache_evict(integer);
+CREATE FUNCTION pg_buffercache_evict(
+    IN int,
+    OUT evicted boolean,
+    OUT flushed boolean)
+AS 'MODULE_PATHNAME', 'pg_buffercache_evict'
+LANGUAGE C PARALLEL SAFE VOLATILE STRICT;
+
 CREATE FUNCTION pg_buffercache_evict_relation(
     IN regclass,
     OUT buffers_evicted int4,
diff --git a/contrib/pg_buffercache/pg_buffercache_pages.c b/contrib/pg_buffercache/pg_buffercache_pages.c
index fa8aae43afd..2f275354c56 100644
--- a/contrib/pg_buffercache/pg_buffercache_pages.c
+++ b/contrib/pg_buffercache/pg_buffercache_pages.c
@@ -22,6 +22,7 @@
 #define NUM_BUFFERCACHE_PAGES_ELEM	9
 #define NUM_BUFFERCACHE_SUMMARY_ELEM 5
 #define NUM_BUFFERCACHE_USAGE_COUNTS_ELEM 4
+#define NUM_BUFFERCACHE_EVICT_ELEM 2
 #define NUM_BUFFERCACHE_EVICT_RELATION_ELEM 2
 #define NUM_BUFFERCACHE_EVICT_ALL_ELEM 2
 
@@ -365,7 +366,17 @@ pg_buffercache_usage_counts(PG_FUNCTION_ARGS)
 Datum
 pg_buffercache_evict(PG_FUNCTION_ARGS)
 {
+	Datum		result;
+	TupleDesc	tupledesc;
+	HeapTuple	tuple;
+	Datum		values[NUM_BUFFERCACHE_EVICT_ELEM];
+	bool		nulls[NUM_BUFFERCACHE_EVICT_ELEM] = {0};
+
 	Buffer		buf = PG_GETARG_INT32(0);
+	bool		flushed;
+
+	if (get_call_result_type(fcinfo, NULL, &tupledesc) != TYPEFUNC_COMPOSITE)
+		elog(ERROR, "return type must be a row type");
 
 	if (!superuser())
 		ereport(ERROR,
@@ -375,7 +386,14 @@ pg_buffercache_evict(PG_FUNCTION_ARGS)
 	if (buf < 1 || buf > NBuffers)
 		elog(ERROR, "bad buffer ID: %d", buf);
 
-	PG_RETURN_BOOL(EvictUnpinnedBuffer(buf));
+	values[0] = BoolGetDatum(EvictUnpinnedBuffer(buf, 0, &flushed));
+	values[1] = BoolGetDatum(flushed);
+
+	/* Build and return the tuple. */
+	tuple = heap_form_tuple(tupledesc, values, nulls);
+	result = HeapTupleGetDatum(tuple);
+
+	PG_RETURN_DATUM(result);
 }
 
 /*
diff --git a/doc/src/sgml/pgbuffercache.sgml b/doc/src/sgml/pgbuffercache.sgml
index d99aa979410..681c74251d4 100644
--- a/doc/src/sgml/pgbuffercache.sgml
+++ b/doc/src/sgml/pgbuffercache.sgml
@@ -391,12 +391,15 @@
   <para>
    The <function>pg_buffercache_evict()</function> function takes a buffer
    identifier, as shown in the <structfield>bufferid</structfield> column of
-   the <structname>pg_buffercache</structname> view.  It returns true on success,
-   and false if the buffer wasn't valid, if it couldn't be evicted because it
-   was pinned, or if it became dirty again after an attempt to write it out.
-   The result is immediately out of date upon return, as the buffer might
-   become valid again at any time due to concurrent activity.  The function is
-   intended for developer testing only.
+   the <structname>pg_buffercache</structname> view.  It returns the
+   information about whether the buffer is evicted and flushed.  evicted
+   column is true on success, and false if the buffer wasn't valid, if it
+   couldn't be evicted because it was pinned, or if it became dirty again
+   after an attempt to write it out.  flushed column is true if the buffer is
+   flushed.  This does not necessarily mean that buffer is flushed by us, it
+   might be flushed by someone else.  The result is immediately out of date
+   upon return, as the buffer might become valid again at any time due to
+   concurrent activity. The function is intended for developer testing only.
   </para>
  </sect2>
 
-- 
2.43.0

