From f104b9475195bd073c598af009b0458f6126a9eb Mon Sep 17 00:00:00 2001 From: Rahila Syed Date: Wed, 29 Oct 2025 16:38:38 +0530 Subject: [PATCH] Overload the injection_points_attach sql function Add a new sql function to assign C functions to injection points. This function has same name but different arguments as injection_points_attach. It takes as input module name and function name in addition to injection point name. --- .../expected/injection_points.out | 29 +++++++++++++++ .../injection_points--1.0.sql | 11 ++++++ .../injection_points/injection_points.c | 37 +++++++++++++++++++ .../injection_points/sql/injection_points.sql | 9 ++++- 4 files changed, 85 insertions(+), 1 deletion(-) diff --git a/src/test/modules/injection_points/expected/injection_points.out b/src/test/modules/injection_points/expected/injection_points.out index 382f3b0bf88..97365284366 100644 --- a/src/test/modules/injection_points/expected/injection_points.out +++ b/src/test/modules/injection_points/expected/injection_points.out @@ -307,6 +307,35 @@ SELECT injection_points_detach('TestConditionLocal1'); (1 row) +-- +-- Test the custom function variant of injection_points_attach +SELECT injection_points_attach('TestInjectionNoticeFunc', 'injection_points', 'injection_notice'); + injection_points_attach +------------------------- + +(1 row) + +-- The injection point should be present +SELECT point_name, library, function FROM injection_points_list() + ORDER BY point_name COLLATE "C"; + point_name | library | function +-------------------------+------------------+------------------ + TestInjectionNoticeFunc | injection_points | injection_notice +(1 row) + +SELECT injection_points_run('TestInjectionNoticeFunc', NULL); -- notice function +NOTICE: notice triggered for injection point TestInjectionNoticeFunc + injection_points_run +---------------------- + +(1 row) + +SELECT injection_points_detach('TestInjectionNoticeFunc'); + injection_points_detach +------------------------- + +(1 row) + -- No points should be left around. SELECT point_name, library, function FROM injection_points_list() ORDER BY point_name COLLATE "C"; 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 a7b61fbdfe6..5bff4ca6539 100644 --- a/src/test/modules/injection_points/injection_points--1.0.sql +++ b/src/test/modules/injection_points/injection_points--1.0.sql @@ -14,6 +14,17 @@ RETURNS void AS 'MODULE_PATHNAME', 'injection_points_attach' LANGUAGE C STRICT PARALLEL UNSAFE; +-- +-- injection_points_attach() +-- +-- Attaches a function to the given injection point. +-- +CREATE FUNCTION injection_points_attach(IN point_name TEXT, + IN library_name TEXT, IN function_name TEXT) +RETURNS void +AS 'MODULE_PATHNAME', 'injection_points_attach_func' +LANGUAGE C STRICT PARALLEL UNSAFE; + -- -- injection_points_load() -- diff --git a/src/test/modules/injection_points/injection_points.c b/src/test/modules/injection_points/injection_points.c index 31138301117..ebc0d8835f2 100644 --- a/src/test/modules/injection_points/injection_points.c +++ b/src/test/modules/injection_points/injection_points.c @@ -391,6 +391,43 @@ injection_points_attach(PG_FUNCTION_ARGS) PG_RETURN_VOID(); } +/* + * SQL function for creating an injection point. + */ +PG_FUNCTION_INFO_V1(injection_points_attach_func); +Datum +injection_points_attach_func(PG_FUNCTION_ARGS) +{ + char *name = text_to_cstring(PG_GETARG_TEXT_PP(0)); + char *lib_name = text_to_cstring(PG_GETARG_TEXT_PP(1)); + char *function = text_to_cstring(PG_GETARG_TEXT_PP(2)); + InjectionPointCondition condition = {0}; + + if (injection_point_local) + { + condition.type = INJ_CONDITION_PID; + condition.pid = MyProcPid; + } + + pgstat_report_inj_fixed(1, 0, 0, 0, 0); + InjectionPointAttach(name, lib_name, function, &condition, + sizeof(InjectionPointCondition)); + if (injection_point_local) + { + MemoryContext oldctx; + + /* Local injection point, so track it for automated cleanup */ + oldctx = MemoryContextSwitchTo(TopMemoryContext); + inj_list_local = lappend(inj_list_local, makeString(pstrdup(name))); + MemoryContextSwitchTo(oldctx); + } + + /* Add entry for stats */ + pgstat_create_inj(name); + + PG_RETURN_VOID(); + +} /* * SQL function for loading an injection point. */ diff --git a/src/test/modules/injection_points/sql/injection_points.sql b/src/test/modules/injection_points/sql/injection_points.sql index 874421e9c11..6d49400e180 100644 --- a/src/test/modules/injection_points/sql/injection_points.sql +++ b/src/test/modules/injection_points/sql/injection_points.sql @@ -87,7 +87,14 @@ SELECT injection_points_detach('TestConditionError'); -- previously should work. SELECT injection_points_attach('TestConditionLocal1', 'error'); SELECT injection_points_detach('TestConditionLocal1'); - +-- +-- Test the custom function variant of injection_points_attach +SELECT injection_points_attach('TestInjectionNoticeFunc', 'injection_points', 'injection_notice'); +-- The injection point should be present +SELECT point_name, library, function FROM injection_points_list() + ORDER BY point_name COLLATE "C"; +SELECT injection_points_run('TestInjectionNoticeFunc', NULL); -- notice function +SELECT injection_points_detach('TestInjectionNoticeFunc'); -- No points should be left around. SELECT point_name, library, function FROM injection_points_list() ORDER BY point_name COLLATE "C"; -- 2.34.1