On Tue, Apr 15, 2025 at 08:00:50AM +0900, Michael Paquier wrote:
> On Mon, Apr 14, 2025 at 04:29:37PM +0300, Aleksander Alekseev wrote:
>> If I didn't miss anything, all SQL functions dealing with injection
>> points are gathered in injection_points extension so IMO
>> pg_get_injection_points() belongs there. It would be awkward to have
>> it in the core considering the fact that injection points presumably
>> should be disabled in release builds.
> 
> There are two more in test_aio, and by design out-of-core extensions
> can define their own.
> 
>> Users will see a function in \df that does nothing.
> 
> Yeah, this one's true if --enable-injection-points is not used.

The first patch of this thread introducing InjectionPointList() has
been applied as 7b2eb72b1b8c.

Now for the second part with the SRF making the injection point
information available at SQL level.  The point about adding the new
function in the core engine has been sticky, and I'm coming down to
the conclusion that I'd still want to make this stuff backpatchable if
need be in the future.  So let's just add a new function in the test
module injection_points and call it a day.

This results in the second patch attached.  Comments are welcome.
--
Michael
From a114f24e3226956ad57dc8f98668239e4461ed4c Mon Sep 17 00:00:00 2001
From: Michael Paquier <mich...@paquier.xyz>
Date: Thu, 3 Jul 2025 08:31:50 +0900
Subject: [PATCH v6] injection_points: Add injection_points_list()

This function can be used to retrieve the information about all the
injection points attached to a cluster.
---
 .../expected/injection_points.out             | 16 ++++++++
 .../injection_points--1.0.sql                 | 12 ++++++
 .../injection_points/injection_points.c       | 40 +++++++++++++++++++
 .../injection_points/sql/injection_points.sql |  7 ++++
 4 files changed, 75 insertions(+)

diff --git a/src/test/modules/injection_points/expected/injection_points.out b/src/test/modules/injection_points/expected/injection_points.out
index 43bcdd01582f..e59065029b41 100644
--- a/src/test/modules/injection_points/expected/injection_points.out
+++ b/src/test/modules/injection_points/expected/injection_points.out
@@ -39,6 +39,15 @@ SELECT injection_points_attach('TestInjectionLog2', 'notice');
  
 (1 row)
 
+SELECT name, library, function FROM pg_get_injection_points()
+  ORDER BY name COLLATE "C";
+        name        |     library      |     function     
+--------------------+------------------+------------------
+ TestInjectionError | injection_points | injection_error
+ TestInjectionLog   | injection_points | injection_notice
+ TestInjectionLog2  | injection_points | injection_notice
+(3 rows)
+
 SELECT injection_points_run('TestInjectionBooh'); -- nothing
  injection_points_run 
 ----------------------
@@ -298,5 +307,12 @@ SELECT injection_points_detach('TestConditionLocal1');
  
 (1 row)
 
+-- No points should be left around.
+SELECT name, library, function FROM pg_get_injection_points()
+  ORDER BY name COLLATE "C";
+ name | library | function 
+------+---------+----------
+(0 rows)
+
 DROP EXTENSION injection_points;
 DROP FUNCTION wait_pid;
diff --git a/src/test/modules/injection_points/injection_points--1.0.sql b/src/test/modules/injection_points/injection_points--1.0.sql
index cc76b1bf99ae..5f5657b2043c 100644
--- a/src/test/modules/injection_points/injection_points--1.0.sql
+++ b/src/test/modules/injection_points/injection_points--1.0.sql
@@ -77,6 +77,18 @@ RETURNS void
 AS 'MODULE_PATHNAME', 'injection_points_detach'
 LANGUAGE C STRICT PARALLEL UNSAFE;
 
+--
+-- injection_points_list()
+--
+-- List of all the injection points currently attached.
+--
+CREATE FUNCTION injection_points_list(OUT point_name text,
+   OUT library text,
+   OUT function text)
+RETURNS SETOF record
+AS 'MODULE_PATHNAME', 'injection_points_list'
+LANGUAGE C STRICT VOLATILE PARALLEL RESTRICTED;
+
 --
 -- injection_points_stats_numcalls()
 --
diff --git a/src/test/modules/injection_points/injection_points.c b/src/test/modules/injection_points/injection_points.c
index 3da0cbc10e08..6888ac01e29c 100644
--- a/src/test/modules/injection_points/injection_points.c
+++ b/src/test/modules/injection_points/injection_points.c
@@ -18,8 +18,10 @@
 #include "postgres.h"
 
 #include "fmgr.h"
+#include "funcapi.h"
 #include "injection_stats.h"
 #include "miscadmin.h"
+#include "nodes/execnodes.h"
 #include "nodes/pg_list.h"
 #include "nodes/value.h"
 #include "storage/condition_variable.h"
@@ -545,6 +547,44 @@ injection_points_detach(PG_FUNCTION_ARGS)
 	PG_RETURN_VOID();
 }
 
+/*
+ * SQL function for listing all the injection points attached.
+ */
+PG_FUNCTION_INFO_V1(injection_points_list);
+Datum
+injection_points_list(PG_FUNCTION_ARGS)
+{
+#define NUM_INJECTION_POINTS_LIST 3
+	ReturnSetInfo *rsinfo = (ReturnSetInfo *) fcinfo->resultinfo;
+	List	   *inj_points;
+	ListCell   *lc;
+
+	/* Build a tuplestore to return our results in */
+	InitMaterializedSRF(fcinfo, 0);
+
+	inj_points = InjectionPointList();
+
+	foreach(lc, inj_points)
+	{
+		Datum		values[NUM_INJECTION_POINTS_LIST];
+		bool		nulls[NUM_INJECTION_POINTS_LIST];
+		InjectionPointData *inj_point = lfirst(lc);
+
+		memset(values, 0, sizeof(values));
+		memset(nulls, 0, sizeof(nulls));
+
+		values[0] = PointerGetDatum(cstring_to_text(inj_point->name));
+		values[1] = PointerGetDatum(cstring_to_text(inj_point->library));
+		values[2] = PointerGetDatum(cstring_to_text(inj_point->function));
+
+		/* shove row into tuplestore */
+		tuplestore_putvalues(rsinfo->setResult, rsinfo->setDesc, values, nulls);
+	}
+
+	return (Datum) 0;
+#undef NUM_INJECTION_POINTS_LIST
+}
+
 
 void
 _PG_init(void)
diff --git a/src/test/modules/injection_points/sql/injection_points.sql b/src/test/modules/injection_points/sql/injection_points.sql
index d9748331c771..874421e9c118 100644
--- a/src/test/modules/injection_points/sql/injection_points.sql
+++ b/src/test/modules/injection_points/sql/injection_points.sql
@@ -18,6 +18,9 @@ SELECT injection_points_attach('TestInjectionError', 'error');
 SELECT injection_points_attach('TestInjectionLog', 'notice');
 SELECT injection_points_attach('TestInjectionLog2', 'notice');
 
+SELECT point_name, library, function FROM injection_points_list()
+  ORDER BY point_name COLLATE "C";
+
 SELECT injection_points_run('TestInjectionBooh'); -- nothing
 SELECT injection_points_run('TestInjectionLog2'); -- notice
 SELECT injection_points_run('TestInjectionLog2', NULL); -- notice
@@ -85,5 +88,9 @@ SELECT injection_points_detach('TestConditionError');
 SELECT injection_points_attach('TestConditionLocal1', 'error');
 SELECT injection_points_detach('TestConditionLocal1');
 
+-- No points should be left around.
+SELECT point_name, library, function FROM injection_points_list()
+  ORDER BY point_name COLLATE "C";
+
 DROP EXTENSION injection_points;
 DROP FUNCTION wait_pid;
-- 
2.50.0

Attachment: signature.asc
Description: PGP signature

Reply via email to