injection_points: Add injection_points_list()
authorMichael Paquier <michael@paquier.xyz>
Thu, 10 Jul 2025 01:01:10 +0000 (10:01 +0900)
committerMichael Paquier <michael@paquier.xyz>
Thu, 10 Jul 2025 01:01:20 +0000 (10:01 +0900)
This function can be used to retrieve the information about all the
injection points attached to a cluster, providing coverage for
InjectionPointList() introduced in 7b2eb72b1b8c.

The original proposal turned around a system function, but that would
not be backpatchable to stable branches.  It was also a bit weird to
have a system function that fails depending on if the build allows
injection points or not.

Reviewed-by: Aleksander Alekseev <aleksander@timescale.com>
Reviewed-by: Rahila Syed <rahilasyed90@gmail.com>
Discussion: https://postgr.es/m/Z_xYkA21KyLEHvWR@paquier.xyz

src/test/modules/injection_points/expected/injection_points.out
src/test/modules/injection_points/injection_points--1.0.sql
src/test/modules/injection_points/injection_points.c
src/test/modules/injection_points/sql/injection_points.sql

index 43bcdd01582f711cc71aa7d799aa96b348ca497e..382f3b0bf8848f0a3a744ec6a9d265402f8ecf76 100644 (file)
@@ -39,6 +39,15 @@ SELECT injection_points_attach('TestInjectionLog2', 'notice');
  
 (1 row)
 
+SELECT point_name, library, function FROM injection_points_list()
+  ORDER BY point_name COLLATE "C";
+     point_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 point_name, library, function FROM injection_points_list()
+  ORDER BY point_name COLLATE "C";
+ point_name | library | function 
+------------+---------+----------
+(0 rows)
+
 DROP EXTENSION injection_points;
 DROP FUNCTION wait_pid;
index cc76b1bf99ae6f2ec496a518528c635ce8ad5b4d..5f5657b2043caebfd949547bd981921ae1bd9327 100644 (file)
@@ -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()
 --
index 3da0cbc10e08fafae1f284085122f55e510007ae..31138301117002f97e3c684064113493cc5fdfb7 100644 (file)
@@ -18,6 +18,7 @@
 #include "postgres.h"
 
 #include "fmgr.h"
+#include "funcapi.h"
 #include "injection_stats.h"
 #include "miscadmin.h"
 #include "nodes/pg_list.h"
@@ -545,6 +546,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)
index d9748331c77155c3be03d03295907b888216a468..874421e9c11877c7bda4450fda26849e76d1ec27 100644 (file)
@@ -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;