From 94f05982ffb1abf9dd1f4864dce04e28b61290f2 Mon Sep 17 00:00:00 2001
From: "okbob@github.com" <okbob@github.com>
Date: Fri, 19 Jan 2024 20:01:56 +0100
Subject: [PATCH 12/15] function pg_get_session_variables_memory for cleaning
 tests

This is a function designed for testing and debugging.  It returns the
content of sessionvars as-is, and can therefore display entries about
session variables that were dropped but for which this backend didn't
process the shared invalidations yet.
---
 src/backend/commands/session_variable.c | 100 ++++++++++++++++++++++++
 src/include/catalog/pg_proc.dat         |   8 ++
 2 files changed, 108 insertions(+)

diff --git a/src/backend/commands/session_variable.c b/src/backend/commands/session_variable.c
index 768163e2009..73ebf0340e3 100644
--- a/src/backend/commands/session_variable.c
+++ b/src/backend/commands/session_variable.c
@@ -22,6 +22,7 @@
 #include "executor/execdesc.h"
 #include "executor/executor.h"
 #include "executor/svariableReceiver.h"
+#include "funcapi.h"
 #include "miscadmin.h"
 #include "nodes/plannodes.h"
 #include "parser/parse_type.h"
@@ -600,3 +601,102 @@ ExecuteLetStmt(ParseState *pstate,
 
 	PopActiveSnapshot();
 }
+
+/*
+ * pg_get_session_variables_memory - designed for testing
+ *
+ * This is a function designed for testing and debugging.  It returns the
+ * content of session variables as-is, and can therefore display data about
+ * session variables that were dropped, but for which this backend didn't
+ * process the shared invalidations yet.
+ */
+Datum
+pg_get_session_variables_memory(PG_FUNCTION_ARGS)
+{
+#define NUM_PG_GET_SESSION_VARIABLES_MEMORY_ATTS 8
+
+	/*
+	 * Make sure syscache entries are flushed for recent catalog changes. For
+	 * stable behavior we need to reliably detect which variables were
+	 * dropped.
+	 */
+	AcceptInvalidationMessages();
+
+	InitMaterializedSRF(fcinfo, 0);
+
+	if (sessionvars)
+	{
+		ReturnSetInfo *rsinfo = (ReturnSetInfo *) fcinfo->resultinfo;
+		HASH_SEQ_STATUS status;
+		SVariable	svar;
+
+		hash_seq_init(&status, sessionvars);
+
+		while ((svar = (SVariable) hash_seq_search(&status)) != NULL)
+		{
+			Datum		values[NUM_PG_GET_SESSION_VARIABLES_MEMORY_ATTS];
+			bool		nulls[NUM_PG_GET_SESSION_VARIABLES_MEMORY_ATTS];
+			HeapTuple	tp;
+			bool		var_is_valid = false;
+
+			memset(values, 0, sizeof(values));
+			memset(nulls, 0, sizeof(nulls));
+
+			values[0] = ObjectIdGetDatum(svar->varid);
+			values[3] = ObjectIdGetDatum(svar->typid);
+
+			/*
+			 * It is possible that the variable has been dropped from the
+			 * catalog, but not yet purged from the hash table.
+			 */
+			tp = SearchSysCache1(VARIABLEOID, ObjectIdGetDatum(svar->varid));
+
+			if (HeapTupleIsValid(tp))
+			{
+				Form_pg_variable varform = (Form_pg_variable) GETSTRUCT(tp);
+
+				/*
+				 * It is also possible that a variable has been dropped and
+				 * someone created a new variable with the same object ID.
+				 * Use the catalog information only if that is not the case.
+				 */
+				if (svar->create_lsn == varform->varcreate_lsn)
+				{
+					values[1] = CStringGetTextDatum(
+													get_namespace_name(varform->varnamespace));
+
+					values[2] = CStringGetTextDatum(NameStr(varform->varname));
+					values[4] = CStringGetTextDatum(format_type_be(svar->typid));
+					values[5] = BoolGetDatum(false);
+
+					values[6] = BoolGetDatum(
+											 object_aclcheck(VariableRelationId, svar->varid,
+															 GetUserId(), ACL_SELECT) == ACLCHECK_OK);
+
+					values[7] = BoolGetDatum(
+											 object_aclcheck(VariableRelationId, svar->varid,
+															 GetUserId(), ACL_UPDATE) == ACLCHECK_OK);
+
+					var_is_valid = true;
+				}
+
+				ReleaseSysCache(tp);
+			}
+
+			/* if there is no matching catalog entry, return null values */
+			if (!var_is_valid)
+			{
+				nulls[1] = true;
+				nulls[2] = true;
+				nulls[4] = true;
+				values[5] = BoolGetDatum(true);
+				nulls[6] = true;
+				nulls[7] = true;
+			}
+
+			tuplestore_putvalues(rsinfo->setResult, rsinfo->setDesc, values, nulls);
+		}
+	}
+
+	return (Datum) 0;
+}
diff --git a/src/include/catalog/pg_proc.dat b/src/include/catalog/pg_proc.dat
index 593bd95eb23..cc086f3faf0 100644
--- a/src/include/catalog/pg_proc.dat
+++ b/src/include/catalog/pg_proc.dat
@@ -12611,4 +12611,12 @@
   proargnames => '{pid,io_id,io_generation,state,operation,off,length,target,handle_data_len,raw_result,result,target_desc,f_sync,f_localmem,f_buffered}',
   prosrc => 'pg_get_aios' },
 
+# Session variables support
+{ oid => '8488', descr => 'internal view of memory entries used by session variables (for debugging)',
+  proname => 'pg_get_session_variables_memory', prorows => '1000', proretset => 't',
+  provolatile => 's', proparallel => 'r', prorettype => 'record',
+  proargtypes => '', proallargtypes => '{oid,text,text,oid,text,bool,bool,bool}',
+  proargmodes => '{o,o,o,o,o,o,o,o}',
+  proargnames => '{varid,schema,name,typid,typname,dropped,can_select,can_update}',
+  prosrc => 'pg_get_session_variables_memory' },
 ]
-- 
2.51.0

