From 9c805ab18c88a12b4561aed11bbc23fa2519df05 Mon Sep 17 00:00:00 2001
From: Rahila Syed <rahilasyed.90@gmail.com>
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       | 29 +++++++++++++++++++
 .../injection_points/sql/injection_points.sql |  9 +++++-
 4 files changed, 77 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..39fa33e40cb 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', NULL);
+ 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..ccb1679b666 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, IN private_data BYTEA)
+RETURNS void
+AS 'MODULE_PATHNAME', 'injection_points_attach_func'
+LANGUAGE C 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..257e1af8424 100644
--- a/src/test/modules/injection_points/injection_points.c
+++ b/src/test/modules/injection_points/injection_points.c
@@ -391,6 +391,35 @@ 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));
+	bytea	*private_data = NULL;
+	int	private_data_size = 0;
+
+	if (!PG_ARGISNULL(3))
+	{
+		private_data = PG_GETARG_BYTEA_PP(3);
+		private_data_size = VARSIZE_ANY_EXHDR(private_data);
+	}
+
+	pgstat_report_inj_fixed(1, 0, 0, 0, 0);
+	if (private_data != NULL)
+		InjectionPointAttach(name, lib_name, function, VARDATA_ANY(private_data),
+								private_data_size);
+	else
+		InjectionPointAttach(name, lib_name, function, NULL,
+								0);
+	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..d8652c42a84 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', NULL);
+-- 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

