From 0e0fb1cfbc2ab863f5e3ff38acd6a29ba1656161 Mon Sep 17 00:00:00 2001 From: Michael Paquier Date: Tue, 15 Apr 2025 14:40:55 +0900 Subject: [PATCH v3 2/2] Add pg_get_injection_points() This is a system function that displays the information about the injection points currently attached to the system, feeding from the states of things in shared memory. --- src/include/catalog/pg_proc.dat | 8 +++ src/backend/utils/misc/Makefile | 1 + .../utils/misc/injection_point_funcs.c | 59 +++++++++++++++++++ src/backend/utils/misc/meson.build | 1 + .../expected/injection_points.out | 16 +++++ .../injection_points/sql/injection_points.sql | 7 +++ src/test/regress/expected/misc_functions.out | 7 +++ src/test/regress/sql/misc_functions.sql | 3 + doc/src/sgml/func.sgml | 46 +++++++++++++++ 9 files changed, 148 insertions(+) create mode 100644 src/backend/utils/misc/injection_point_funcs.c diff --git a/src/include/catalog/pg_proc.dat b/src/include/catalog/pg_proc.dat index 62beb71da288..d087d9fda1e8 100644 --- a/src/include/catalog/pg_proc.dat +++ b/src/include/catalog/pg_proc.dat @@ -12566,4 +12566,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' }, +# Injection point functions +{ oid => '8490', descr => 'information about injection points attached', + proname => 'pg_get_injection_points', prorows => '3', proretset => 't', + provolatile => 'v', proparallel => 'r', prorettype => 'record', + proargtypes => '', proallargtypes => '{text,text,text}', + proargmodes => '{o,o,o}', proargnames => '{name,library,function}', + prosrc => 'pg_get_injection_points' }, + ] diff --git a/src/backend/utils/misc/Makefile b/src/backend/utils/misc/Makefile index b362ae437710..93703633f69a 100644 --- a/src/backend/utils/misc/Makefile +++ b/src/backend/utils/misc/Makefile @@ -22,6 +22,7 @@ OBJS = \ guc_tables.o \ help_config.o \ injection_point.o \ + injection_point_funcs.o \ pg_config.o \ pg_controldata.o \ pg_rusage.o \ diff --git a/src/backend/utils/misc/injection_point_funcs.c b/src/backend/utils/misc/injection_point_funcs.c new file mode 100644 index 000000000000..750ac4abf67d --- /dev/null +++ b/src/backend/utils/misc/injection_point_funcs.c @@ -0,0 +1,59 @@ +/*------------------------------------------------------------------------- + * + * injection_point_funcs.c + * + * SQL commands and SQL-accessible functions related to injection points. + * + * Portions Copyright (c) 1996-2025, PostgreSQL Global Development Group + * Portions Copyright (c) 1994, Regents of the University of California + * + * + * IDENTIFICATION + * src/backend/utils/misc/injection_point_funcs.c + * + *------------------------------------------------------------------------- + */ +#include "postgres.h" + +#include "funcapi.h" +#include "utils/builtins.h" +#include "utils/injection_point.h" + +/* + * pg_get_injection_points + * + * Return a table of all the injection points currently attached to the + * system. + */ +Datum +pg_get_injection_points(PG_FUNCTION_ARGS) +{ +#define NUM_PG_GET_INJECTION_POINTS 3 + ReturnSetInfo *rsinfo = (ReturnSetInfo *) fcinfo->resultinfo; + uint32 num_points = 0; + InjectionPointData *injps = NULL; + + /* Build a tuplestore to return our results in */ + InitMaterializedSRF(fcinfo, 0); + + injps = InjectionPointList(&num_points); + + for (uint32 idx = 0; idx < num_points; idx++) + { + Datum values[NUM_PG_GET_INJECTION_POINTS]; + bool nulls[NUM_PG_GET_INJECTION_POINTS]; + + memset(values, 0, sizeof(values)); + memset(nulls, 0, sizeof(nulls)); + + values[0] = PointerGetDatum(cstring_to_text(injps[idx].name)); + values[1] = PointerGetDatum(cstring_to_text(injps[idx].library)); + values[2] = PointerGetDatum(cstring_to_text(injps[idx].function)); + + /* shove row into tuplestore */ + tuplestore_putvalues(rsinfo->setResult, rsinfo->setDesc, values, nulls); + } + + return (Datum) 0; +#undef NUM_PG_GET_INJECTION_POINTS +} diff --git a/src/backend/utils/misc/meson.build b/src/backend/utils/misc/meson.build index 9e389a00d057..4a89f1e016ea 100644 --- a/src/backend/utils/misc/meson.build +++ b/src/backend/utils/misc/meson.build @@ -7,6 +7,7 @@ backend_sources += files( 'guc_tables.c', 'help_config.c', 'injection_point.c', + 'injection_point_funcs.c', 'pg_config.c', 'pg_controldata.c', 'pg_rusage.c', diff --git a/src/test/modules/injection_points/expected/injection_points.out b/src/test/modules/injection_points/expected/injection_points.out index f25bbe4966ee..4b1436a3ef69 100644 --- a/src/test/modules/injection_points/expected/injection_points.out +++ b/src/test/modules/injection_points/expected/injection_points.out @@ -26,6 +26,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 ---------------------- @@ -253,5 +262,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/sql/injection_points.sql b/src/test/modules/injection_points/sql/injection_points.sql index e3a481d60449..b12c40551954 100644 --- a/src/test/modules/injection_points/sql/injection_points.sql +++ b/src/test/modules/injection_points/sql/injection_points.sql @@ -14,6 +14,9 @@ SELECT injection_points_attach('TestInjectionError', 'error'); SELECT injection_points_attach('TestInjectionLog', 'notice'); SELECT injection_points_attach('TestInjectionLog2', 'notice'); +SELECT name, library, function FROM pg_get_injection_points() + ORDER BY name COLLATE "C"; + SELECT injection_points_run('TestInjectionBooh'); -- nothing SELECT injection_points_run('TestInjectionLog2'); -- notice SELECT injection_points_run('TestInjectionLog'); -- notice @@ -75,5 +78,9 @@ SELECT injection_points_detach('TestConditionError'); SELECT injection_points_attach('TestConditionLocal1', 'error'); SELECT injection_points_detach('TestConditionLocal1'); +-- No points should be left around. +SELECT name, library, function FROM pg_get_injection_points() + ORDER BY name COLLATE "C"; + DROP EXTENSION injection_points; DROP FUNCTION wait_pid; diff --git a/src/test/regress/expected/misc_functions.out b/src/test/regress/expected/misc_functions.out index d3f5d16a6725..c09bff495045 100644 --- a/src/test/regress/expected/misc_functions.out +++ b/src/test/regress/expected/misc_functions.out @@ -802,6 +802,13 @@ SELECT count(*) > 0 AS ok FROM pg_control_system(); t (1 row) +-- Test function for injection point +SELECT count(*) >= 0 AS ok FROM pg_get_injection_points(); + ok +---- + t +(1 row) + -- pg_split_walfile_name, pg_walfile_name & pg_walfile_name_offset SELECT * FROM pg_split_walfile_name(NULL); segment_number | timeline_id diff --git a/src/test/regress/sql/misc_functions.sql b/src/test/regress/sql/misc_functions.sql index aaebb298330b..e351a19a8744 100644 --- a/src/test/regress/sql/misc_functions.sql +++ b/src/test/regress/sql/misc_functions.sql @@ -355,6 +355,9 @@ SELECT count(*) > 0 AS ok FROM pg_control_init(); SELECT count(*) > 0 AS ok FROM pg_control_recovery(); SELECT count(*) > 0 AS ok FROM pg_control_system(); +-- Test function for injection point +SELECT count(*) >= 0 AS ok FROM pg_get_injection_points(); + -- pg_split_walfile_name, pg_walfile_name & pg_walfile_name_offset SELECT * FROM pg_split_walfile_name(NULL); SELECT * FROM pg_split_walfile_name('invalid'); diff --git a/doc/src/sgml/func.sgml b/doc/src/sgml/func.sgml index 1c5cfee25d12..6c0e0b45fa83 100644 --- a/doc/src/sgml/func.sgml +++ b/doc/src/sgml/func.sgml @@ -28496,6 +28496,52 @@ acl | {postgres=arwdDxtm/postgres,foo=r/postgres} + + Injection Points Information Functions + + + The functions shown in + print information about the injection points. + See . + + + + WAL Summarization Information Functions + + + + + Function + + + Description + + + + + + + + + pg_get_injection_points + + pg_get_injection_points () + setof record + ( name text, + library text, + function text ) + + + Returns information about the injection points currently attached + to the cluster. + + + + + +
+
+ -- 2.49.0