From 20d35849e84233c28858271655b91e09edd66863 Mon Sep 17 00:00:00 2001
From: shruthi gowda <shruthi.kc@enterprisedb.com>
Date: Thu, 9 Apr 2026 08:37:36 +0000
Subject: [PATCH v1_test] Tests for NULL connection validation

---
 src/interfaces/ecpg/test/connect/Makefile     |   3 +-
 src/interfaces/ecpg/test/connect/meson.build  |   1 +
 .../ecpg/test/connect/test_null_connection.c  | 150 ++++++++++++++++++
 .../test/connect/test_null_connection.pgc     |  69 ++++++++
 src/interfaces/ecpg/test/ecpg_schedule        |   1 +
 .../connect-test_null_connection.stderr       |  50 ++++++
 .../connect-test_null_connection.stdout       |   8 +
 7 files changed, 281 insertions(+), 1 deletion(-)
 create mode 100644 src/interfaces/ecpg/test/connect/test_null_connection.c
 create mode 100644 src/interfaces/ecpg/test/connect/test_null_connection.pgc
 create mode 100644 src/interfaces/ecpg/test/expected/connect-test_null_connection.stderr
 create mode 100644 src/interfaces/ecpg/test/expected/connect-test_null_connection.stdout

diff --git a/src/interfaces/ecpg/test/connect/Makefile b/src/interfaces/ecpg/test/connect/Makefile
index 2602d5d286f..02151733c4c 100644
--- a/src/interfaces/ecpg/test/connect/Makefile
+++ b/src/interfaces/ecpg/test/connect/Makefile
@@ -7,6 +7,7 @@ TESTS = test1 test1.c \
         test2 test2.c \
         test3 test3.c \
         test4 test4.c \
-        test5 test5.c
+        test5 test5.c \
+        test_null_connection test_null_connection.c
 
 all: $(TESTS)
diff --git a/src/interfaces/ecpg/test/connect/meson.build b/src/interfaces/ecpg/test/connect/meson.build
index 591e04bc422..1147b4e8f51 100644
--- a/src/interfaces/ecpg/test/connect/meson.build
+++ b/src/interfaces/ecpg/test/connect/meson.build
@@ -6,6 +6,7 @@ pgc_files = [
   'test3',
   'test4',
   'test5',
+  'test_null_connection',
 ]
 
 foreach pgc_file : pgc_files
diff --git a/src/interfaces/ecpg/test/connect/test_null_connection.c b/src/interfaces/ecpg/test/connect/test_null_connection.c
new file mode 100644
index 00000000000..ef0af1fe157
--- /dev/null
+++ b/src/interfaces/ecpg/test/connect/test_null_connection.c
@@ -0,0 +1,150 @@
+/* Processed by ecpg (regression mode) */
+/* These include files are added by the preprocessor */
+#include <ecpglib.h>
+#include <ecpgerrno.h>
+#include <sqlca.h>
+/* End of automatic include section */
+#define ECPGdebug(X,Y) ECPGdebug((X)+100,(Y))
+
+#line 1 "test_null_connection.pgc"
+/*
+ * This test verifies that ecpg functions properly handle NULL connections
+ * (i.e., when a connection name doesn't exist or has been disconnected).
+ * Before the fix, these operations would cause a segmentation fault.
+ */
+
+#include <stdlib.h>
+#include <string.h>
+#include <stdio.h>
+
+
+#line 1 "./../regression.h"
+
+
+
+
+
+
+#line 11 "test_null_connection.pgc"
+
+
+int
+main(void)
+{
+/* exec sql begin declare section */
+
+
+
+
+
+
+#line 17 "test_null_connection.pgc"
+ char * query = "SELECT 1" ;
+
+#line 18 "test_null_connection.pgc"
+ int val1output = 2 ;
+
+#line 19 "test_null_connection.pgc"
+ int val1 = 1 ;
+
+#line 20 "test_null_connection.pgc"
+ char val2 [ 5 ] = "data1" ;
+
+#line 21 "test_null_connection.pgc"
+ char * stmt1 = "SELECT * from test1 where a = $1 and b = $2" ;
+/* exec sql end declare section */
+#line 22 "test_null_connection.pgc"
+
+
+	ECPGdebug(1, stderr);
+
+	/* Connect to the database */
+	{ ECPGconnect(__LINE__, 0, "ecpg1_regression" , NULL, NULL , "myconn", 0); }
+#line 27 "test_null_connection.pgc"
+
+
+	/* Test 1: Try to get descriptor on a disconnected connection */
+	printf("Test 1: Try to get descriptor on a disconnected connection \n");
+	{ ECPGdo(__LINE__, 0, 1, NULL, 0, ECPGst_normal, "create table test1 ( a int , b text )", ECPGt_EOIT, ECPGt_EORT);}
+#line 31 "test_null_connection.pgc"
+
+	{ ECPGdo(__LINE__, 0, 1, NULL, 0, ECPGst_normal, "insert into test1 ( a , b ) values ( 1 , 'data1' )", ECPGt_EOIT, ECPGt_EORT);}
+#line 32 "test_null_connection.pgc"
+
+
+	ECPGallocate_desc(__LINE__, "indesc");
+#line 34 "test_null_connection.pgc"
+
+	ECPGallocate_desc(__LINE__, "outdesc");
+#line 35 "test_null_connection.pgc"
+
+
+	{ ECPGprepare(__LINE__, NULL, 0, "foo2", stmt1);}
+#line 37 "test_null_connection.pgc"
+
+
+	{ ECPGset_desc(__LINE__, "indesc", 1,ECPGd_data,
+	ECPGt_int,&(val1),(long)1,(long)1,sizeof(int), ECPGd_EODT);
+}
+#line 39 "test_null_connection.pgc"
+
+	{ ECPGset_desc(__LINE__, "indesc", 2,ECPGd_data,
+	ECPGt_char,(val2),(long)5,(long)1,(5)*sizeof(char), ECPGd_EODT);
+}
+#line 40 "test_null_connection.pgc"
+
+
+	{ ECPGdo(__LINE__, 0, 1, NULL, 0, ECPGst_execute, "foo2",
+	ECPGt_descriptor, "indesc", 1L, 1L, 1L, 
+	ECPGt_NO_INDICATOR, NULL , 0L, 0L, 0L, ECPGt_EOIT, 
+	ECPGt_descriptor, "outdesc", 1L, 1L, 1L, 
+	ECPGt_NO_INDICATOR, NULL , 0L, 0L, 0L, ECPGt_EORT);}
+#line 42 "test_null_connection.pgc"
+
+
+	{ ECPGdisconnect(__LINE__, "CURRENT");}
+#line 44 "test_null_connection.pgc"
+
+	{ ECPGget_desc(__LINE__, "outdesc", 1,ECPGd_data,
+	ECPGt_int,&(val1output),(long)1,(long)1,sizeof(int), ECPGd_EODT);
+}
+#line 45 "test_null_connection.pgc"
+
+	printf("sqlca.sqlcode = %ld\n", sqlca.sqlcode);
+
+	/* Test 2: Try to deallocate all on a non-existent connection */
+	printf("Test 2: deallocate all with non-existent connection\n");
+	{ ECPGdeallocate_all(__LINE__, 0, "nonexistent");}
+#line 50 "test_null_connection.pgc"
+
+	printf("sqlca.sqlcode = %ld\n", sqlca.sqlcode);
+
+	/* Test 3: deallocate on disconnected connection */
+	printf("Test 3: deallocate all on disconnected connection\n");
+	{ ECPGdeallocate_all(__LINE__, 0, NULL);}
+#line 55 "test_null_connection.pgc"
+
+	printf("sqlca.sqlcode = %ld\n", sqlca.sqlcode);
+
+	/* Test 4: Use prepared statement from non-existent connection */
+	printf("Test 4: Use prepared statement from non-existent connection\n");
+  	{ ECPGprepare(__LINE__, "nonexistent", 0, "stmt1", "SELECT 1");}
+#line 60 "test_null_connection.pgc"
+
+  	/* declare cur1 cursor for $1 */
+#line 61 "test_null_connection.pgc"
+
+ 	{ ECPGdo(__LINE__, 0, 1, "nonexistent", 0, ECPGst_normal, "declare cur1 cursor for $1", 
+	ECPGt_char_variable,(ECPGprepared_statement("nonexistent", "stmt1", __LINE__)),(long)1,(long)1,(1)*sizeof(char), 
+	ECPGt_NO_INDICATOR, NULL , 0L, 0L, 0L, ECPGt_EOIT, ECPGt_EORT);}
+#line 62 "test_null_connection.pgc"
+
+
+	printf("All tests completed !\n");
+
+	{ ECPGdisconnect(__LINE__, "CURRENT");}
+#line 66 "test_null_connection.pgc"
+
+
+	return 0;
+}
diff --git a/src/interfaces/ecpg/test/connect/test_null_connection.pgc b/src/interfaces/ecpg/test/connect/test_null_connection.pgc
new file mode 100644
index 00000000000..886e4eab218
--- /dev/null
+++ b/src/interfaces/ecpg/test/connect/test_null_connection.pgc
@@ -0,0 +1,69 @@
+/*
+ * This test verifies that ecpg functions properly handle NULL connections
+ * (i.e., when a connection name doesn't exist or has been disconnected).
+ * Before the fix, these operations would cause a segmentation fault.
+ */
+
+#include <stdlib.h>
+#include <string.h>
+#include <stdio.h>
+
+exec sql include ../regression;
+
+int
+main(void)
+{
+exec sql begin declare section;
+	char *query = "SELECT 1";
+	int val1output = 2;
+	int val1 = 1;
+	char val2[5] = "data1";
+	char *stmt1 = "SELECT * from test1 where a = $1 and b = $2";
+exec sql end declare section;
+
+	ECPGdebug(1, stderr);
+
+	/* Connect to the database */
+	exec sql connect to REGRESSDB1 as myconn;
+
+	/* Test 1: Try to get descriptor on a disconnected connection */
+	printf("Test 1: Try to get descriptor on a disconnected connection \n");
+	exec sql create table test1 (a int, b text);
+	exec sql insert into test1 (a,b) values (1, 'data1');
+
+	exec sql allocate descriptor indesc;
+	exec sql allocate descriptor outdesc;
+
+	exec sql prepare foo2 from :stmt1;
+
+	exec sql set descriptor indesc value 1 DATA = :val1;
+	exec sql set descriptor indesc value 2 DATA = :val2;
+
+	exec sql execute foo2 using sql descriptor indesc into sql descriptor outdesc;
+
+	exec sql disconnect;
+	exec sql get descriptor outdesc value 1 :val1output = DATA;
+	printf("sqlca.sqlcode = %ld\n", sqlca.sqlcode);
+
+	/* Test 2: Try to deallocate all on a non-existent connection */
+	printf("Test 2: deallocate all with non-existent connection\n");
+	exec sql at nonexistent deallocate all;
+	printf("sqlca.sqlcode = %ld\n", sqlca.sqlcode);
+
+	/* Test 3: deallocate on disconnected connection */
+	printf("Test 3: deallocate all on disconnected connection\n");
+	exec sql deallocate all;
+	printf("sqlca.sqlcode = %ld\n", sqlca.sqlcode);
+
+	/* Test 4: Use prepared statement from non-existent connection */
+	printf("Test 4: Use prepared statement from non-existent connection\n");
+  	exec sql at nonexistent prepare stmt1 FROM "SELECT 1";
+  	exec sql at nonexistent declare cur1 cursor for stmt1;
+ 	exec sql at nonexistent open cur1;
+
+	printf("All tests completed !\n");
+
+	exec sql disconnect;
+
+	return 0;
+}
diff --git a/src/interfaces/ecpg/test/ecpg_schedule b/src/interfaces/ecpg/test/ecpg_schedule
index b75e16fde1e..a798f2497ab 100644
--- a/src/interfaces/ecpg/test/ecpg_schedule
+++ b/src/interfaces/ecpg/test/ecpg_schedule
@@ -13,6 +13,7 @@ test: connect/test2
 test: connect/test3
 test: connect/test4
 test: connect/test5
+test: connect/test_null_connection
 test: pgtypeslib/dt_test
 test: pgtypeslib/dt_test2
 test: pgtypeslib/num_test
diff --git a/src/interfaces/ecpg/test/expected/connect-test_null_connection.stderr b/src/interfaces/ecpg/test/expected/connect-test_null_connection.stderr
new file mode 100644
index 00000000000..f4bc2a07924
--- /dev/null
+++ b/src/interfaces/ecpg/test/expected/connect-test_null_connection.stderr
@@ -0,0 +1,50 @@
+[NO_PID]: ECPGdebug: set to 1
+[NO_PID]: sqlca: code: 0, state: 00000
+[NO_PID]: ECPGconnect: opening database ecpg1_regression on <DEFAULT> port <DEFAULT>  
+[NO_PID]: sqlca: code: 0, state: 00000
+[NO_PID]: ecpg_execute on line 31: query: create table test1 ( a int , b text ); with 0 parameter(s) on connection myconn
+[NO_PID]: sqlca: code: 0, state: 00000
+[NO_PID]: ecpg_execute on line 31: using PQexec
+[NO_PID]: sqlca: code: 0, state: 00000
+[NO_PID]: ecpg_process_output on line 31: OK: CREATE TABLE
+[NO_PID]: sqlca: code: 0, state: 00000
+[NO_PID]: ecpg_execute on line 32: query: insert into test1 ( a , b ) values ( 1 , 'data1' ); with 0 parameter(s) on connection myconn
+[NO_PID]: sqlca: code: 0, state: 00000
+[NO_PID]: ecpg_execute on line 32: using PQexec
+[NO_PID]: sqlca: code: 0, state: 00000
+[NO_PID]: ecpg_process_output on line 32: OK: INSERT 0 1
+[NO_PID]: sqlca: code: 0, state: 00000
+[NO_PID]: prepare_common on line 37: name foo2; query: "SELECT * from test1 where a = $1 and b = $2"
+[NO_PID]: sqlca: code: 0, state: 00000
+[NO_PID]: ecpg_execute on line 42: query: SELECT * from test1 where a = $1 and b = $2; with 2 parameter(s) on connection myconn
+[NO_PID]: sqlca: code: 0, state: 00000
+[NO_PID]: ecpg_execute on line 42: using PQexecPrepared for "SELECT * from test1 where a = $1 and b = $2"
+[NO_PID]: sqlca: code: 0, state: 00000
+[NO_PID]: ecpg_free_params on line 42: parameter 1 = 1
+[NO_PID]: sqlca: code: 0, state: 00000
+[NO_PID]: ecpg_free_params on line 42: parameter 2 = data1
+[NO_PID]: sqlca: code: 0, state: 00000
+[NO_PID]: ecpg_process_output on line 42: correctly got 1 tuples with 2 fields
+[NO_PID]: sqlca: code: 0, state: 00000
+[NO_PID]: ecpg_process_output on line 42: putting result (1 tuples) into descriptor outdesc
+[NO_PID]: sqlca: code: 0, state: 00000
+[NO_PID]: deallocate_one on line 0: name foo2
+[NO_PID]: sqlca: code: 0, state: 00000
+[NO_PID]: ecpg_finish: connection myconn closed
+[NO_PID]: sqlca: code: 0, state: 00000
+[NO_PID]: ECPGget_desc: reading items for tuple 1
+[NO_PID]: sqlca: code: 0, state: 00000
+[NO_PID]: raising sqlcode -220 on line 45: connection "NULL" does not exist on line 45
+[NO_PID]: sqlca: code: -220, state: 08003
+[NO_PID]: raising sqlcode -220 on line 50: connection "nonexistent" does not exist on line 50
+[NO_PID]: sqlca: code: -220, state: 08003
+[NO_PID]: raising sqlcode -220 on line 55: connection "NULL" does not exist on line 55
+[NO_PID]: sqlca: code: -220, state: 08003
+[NO_PID]: raising sqlcode -220 on line 60: connection "nonexistent" does not exist on line 60
+[NO_PID]: sqlca: code: -220, state: 08003
+[NO_PID]: raising sqlcode -220 on line 63: connection "nonexistent" does not exist on line 63
+[NO_PID]: sqlca: code: -220, state: 08003
+[NO_PID]: raising sqlcode -220 on line 62: connection "nonexistent" does not exist on line 62
+[NO_PID]: sqlca: code: -220, state: 08003
+[NO_PID]: raising sqlcode -220 on line 66: connection "CURRENT" does not exist on line 66
+[NO_PID]: sqlca: code: -220, state: 08003
diff --git a/src/interfaces/ecpg/test/expected/connect-test_null_connection.stdout b/src/interfaces/ecpg/test/expected/connect-test_null_connection.stdout
new file mode 100644
index 00000000000..a845c736a0a
--- /dev/null
+++ b/src/interfaces/ecpg/test/expected/connect-test_null_connection.stdout
@@ -0,0 +1,8 @@
+Test 1: Try to get descriptor on a disconnected connection 
+sqlca.sqlcode = -220
+Test 2: deallocate all with non-existent connection
+sqlca.sqlcode = -220
+Test 3: deallocate all on disconnected connection
+sqlca.sqlcode = -220
+Test 4: Use prepared statement from non-existent connection
+All tests completed !
-- 
2.43.0

