From c2036e9ca0936a31623e8dbe05892d3af3ea5010 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 03/22] function pg_session_variables 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 | 92 +++++++++++++++++++++++++
 src/include/catalog/pg_proc.dat         |  8 +++
 2 files changed, 100 insertions(+)

diff --git a/src/backend/commands/session_variable.c b/src/backend/commands/session_variable.c
index 548d9835c0d..13ab9575fa9 100644
--- a/src/backend/commands/session_variable.c
+++ b/src/backend/commands/session_variable.c
@@ -569,3 +569,95 @@ ExecuteLetStmt(ParseState *pstate,
 
 	PopActiveSnapshot();
 }
+
+/*
+ * pg_session_variables - 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_session_variables(PG_FUNCTION_ARGS)
+{
+#define NUM_PG_SESSION_VARIABLES_ATTS 8
+
+	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_SESSION_VARIABLES_ATTS];
+			bool		nulls[NUM_PG_SESSION_VARIABLES_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 41f1121d19f..e943a74846f 100644
--- a/src/include/catalog/pg_proc.dat
+++ b/src/include/catalog/pg_proc.dat
@@ -12405,4 +12405,12 @@
   proargtypes => 'int2',
   prosrc => 'gist_stratnum_identity' },
 
+# Session variables support
+{ oid => '8488', descr => 'list of used session variables',
+  proname => 'pg_session_variables', 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,removed,can_select,can_update}',
+  prosrc => 'pg_session_variables' },
 ]
-- 
2.47.0

