From 173311a0a6ba59955bc0a24cff6970b3c0007959 Mon Sep 17 00:00:00 2001
From: Adrian Grucza <adrian.grucza@iress.com>
Date: Wed, 12 May 2021 23:16:35 +1000
Subject: [PATCH 2/3] Remove REFCUR_SUPPORT, add FetchRefcursors setting

---
 dlg_specific.c | 18 ++++++++++++++++++
 dlg_specific.h |  4 ++++
 dlg_wingui.c   |  2 ++
 psqlodbc.h     |  1 +
 psqlodbc.rc    |  4 ++++
 resource.h     |  3 ++-
 statement.c    | 27 ++++++++++++---------------
 7 files changed, 43 insertions(+), 16 deletions(-)

diff --git a/dlg_specific.c b/dlg_specific.c
index 3f2192c..45662a6 100644
--- a/dlg_specific.c
+++ b/dlg_specific.c
@@ -369,6 +369,7 @@ MYLOG(DETAIL_LOG_LEVEL, "hlen=" FORMAT_SSIZE_T "\n", hlen);
 			"%s"		/* INIKEEPALIVE TIME/INTERVAL */
 			ABBR_NUMERIC_AS "=%d;"
 			INI_OPTIONAL_ERRORS "=%d;"
+			INI_FETCHREFCURSORS "=%d;"
 #ifdef	_HANDLE_ENLIST_IN_DTC_
 			INI_XAOPT "=%d"	/* XAOPT */
 #endif /* _HANDLE_ENLIST_IN_DTC_ */
@@ -403,6 +404,7 @@ MYLOG(DETAIL_LOG_LEVEL, "hlen=" FORMAT_SSIZE_T "\n", hlen);
 			,makeKeepaliveConnectString(keepaliveStr, sizeof(keepaliveStr), ci, FALSE)
 			,ci->numeric_as
 			,ci->optional_errors
+			,ci->fetch_refcursors
 #ifdef	_HANDLE_ENLIST_IN_DTC_
 			,ci->xa_opt
 #endif /* _HANDLE_ENLIST_IN_DTC_ */
@@ -461,6 +463,8 @@ MYLOG(DETAIL_LOG_LEVEL, "hlen=" FORMAT_SSIZE_T "\n", hlen);
 			flag |= BIT_LOWERCASEIDENTIFIER;
 		if (ci->optional_errors)
 			flag |= BIT_OPTIONALERRORS;
+		if (ci->fetch_refcursors)
+			flag |= BIT_FETCHREFCURSORS;
 
 		if (ci->sslmode[0])
 		{
@@ -583,6 +587,7 @@ unfoldCXAttribute(ConnInfo *ci, const char *value)
 	ci->use_server_side_prepare = (char)((flag & BIT_USESERVERSIDEPREPARE) != 0);
 	ci->lower_case_identifier = (char)((flag & BIT_LOWERCASEIDENTIFIER) != 0);
 	ci->optional_errors = (char)((flag & BIT_OPTIONALERRORS) != 0);
+	ci->fetch_refcursors = (char)((flag & BIT_FETCHREFCURSORS) != 0);
 }
 
 BOOL
@@ -793,6 +798,8 @@ copyConnAttributes(ConnInfo *ci, const char *attribute, const char *value)
 		ci->drivers.bools_as_char = atoi(value);
 	else if (stricmp(attribute, INI_EXTRASYSTABLEPREFIXES) == 0 || stricmp(attribute, ABBR_EXTRASYSTABLEPREFIXES) == 0)
 		STRCPY_FIXED(ci->drivers.extra_systable_prefixes, value);
+	else if (stricmp(attribute, INI_FETCHREFCURSORS) == 0 || stricmp(attribute, ABBR_FETCHREFCURSORS) == 0)
+		ci->fetch_refcursors = atoi(value);
 	else
 		found = FALSE;
 
@@ -842,6 +849,7 @@ getCiDefaults(ConnInfo *ci)
 				ci->wcs_debug = 1;
 	}
 	ci->disable_convert_func = 0;
+	ci->fetch_refcursors = DEFAULT_FETCHREFCURSORS;
 #ifdef	_HANDLE_ENLIST_IN_DTC_
 	ci->xa_opt = DEFAULT_XAOPT;
 #endif /* _HANDLE_ENLIST_IN_DTC_ */
@@ -1082,6 +1090,9 @@ MYLOG(0, "drivername=%s\n", drivername);
 	if (SQLGetPrivateProfileString(DSN, INI_SSLMODE, NULL_STRING, temp, sizeof(temp), ODBC_INI) > 0)
 		STRCPY_FIXED(ci->sslmode, temp);
 
+	if (SQLGetPrivateProfileString(DSN, INI_FETCHREFCURSORS, NULL_STRING, temp, sizeof(temp), ODBC_INI) > 0)
+		ci->fetch_refcursors = atoi(temp);
+
 #ifdef	_HANDLE_ENLIST_IN_DTC_
 	if (SQLGetPrivateProfileString(DSN, INI_XAOPT, NULL_STRING, temp, sizeof(temp), ODBC_INI) > 0)
 		ci->xa_opt = atoi(temp);
@@ -1374,6 +1385,11 @@ writeDSNinfo(const ConnInfo *ci)
 								 INI_IGNORETIMEOUT,
 								 temp,
 								 ODBC_INI);
+	ITOA_FIXED(temp, ci->fetch_refcursors);
+	SQLWritePrivateProfileString(DSN,
+								 INI_FETCHREFCURSORS,
+								 temp,
+								 ODBC_INI);
 #ifdef	_HANDLE_ENLIST_IN_DTC_
 	ITOA_FIXED(temp, ci->xa_opt);
 	SQLWritePrivateProfileString(DSN, INI_XAOPT, temp, ODBC_INI);
@@ -1789,6 +1805,7 @@ CC_conninfo_init(ConnInfo *conninfo, UInt4 option)
 	conninfo->batch_size = DEFAULT_BATCH_SIZE;
 	conninfo->ignore_timeout = DEFAULT_IGNORETIMEOUT;
 	conninfo->wcs_debug = -1;
+	conninfo->fetch_refcursors = -1;
 #ifdef	_HANDLE_ENLIST_IN_DTC_
 	conninfo->xa_opt = -1;
 #endif /* _HANDLE_ENLIST_IN_DTC_ */
@@ -1890,6 +1907,7 @@ CC_copy_conninfo(ConnInfo *ci, const ConnInfo *sci)
 	CORR_VALCPY(keepalive_interval);
 	CORR_VALCPY(batch_size);
 	CORR_VALCPY(ignore_timeout);
+	CORR_VALCPY(fetch_refcursors);
 #ifdef	_HANDLE_ENLIST_IN_DTC_
 	CORR_VALCPY(xa_opt);
 #endif
diff --git a/dlg_specific.h b/dlg_specific.h
index c585750..87d32c7 100644
--- a/dlg_specific.h
+++ b/dlg_specific.h
@@ -173,6 +173,8 @@ extern "C" {
 #define INI_IGNORETIMEOUT		"IgnoreTimeout"
 #define ABBR_IGNORETIMEOUT		"D9"
 #define INI_DTCLOG			"Dtclog"
+#define INI_FETCHREFCURSORS		"FetchRefcursors"
+#define ABBR_FETCHREFCURSORS		"DA"
 /* "PreferLibpq", abbreviated "D4", used to mean whether to prefer libpq.
  * libpq is now required
 #define INI_PREFERLIBPQ			"PreferLibpq"
@@ -220,6 +222,7 @@ extern "C" {
 #define BIT_USESERVERSIDEPREPARE		(1L<<25)
 #define BIT_LOWERCASEIDENTIFIER			(1L<<26)
 #define BIT_OPTIONALERRORS			(1L<<27)
+#define BIT_FETCHREFCURSORS			(1L<<28)
 
 #define EFFECTIVE_BIT_COUNT			28
 
@@ -274,6 +277,7 @@ extern "C" {
 #define DEFAULT_OPTIONAL_ERRORS		0
 #define DEFAULT_BATCH_SIZE		100
 #define DEFAULT_IGNORETIMEOUT		0
+#define DEFAULT_FETCHREFCURSORS		0
 
 #ifdef	_HANDLE_ENLIST_IN_DTC_
 #define DEFAULT_XAOPT			1
diff --git a/dlg_wingui.c b/dlg_wingui.c
index 276d8f1..c348ccc 100644
--- a/dlg_wingui.c
+++ b/dlg_wingui.c
@@ -571,6 +571,7 @@ ds_options_update(HWND hdlg, ConnInfo *ci)
 	ci->allow_keyset = IsDlgButtonChecked(hdlg, DS_UPDATABLECURSORS);
 	ci->use_server_side_prepare = IsDlgButtonChecked(hdlg, DS_SERVERSIDEPREPARE);
 	ci->bytea_as_longvarbinary = IsDlgButtonChecked(hdlg, DS_BYTEAASLONGVARBINARY);
+	ci->fetch_refcursors = IsDlgButtonChecked(hdlg, DS_FETCH_REFCURSORS);
 	/*ci->lower_case_identifier = IsDlgButtonChecked(hdlg, DS_LOWERCASEIDENTIFIER);*/
 
 	/* OID Options */
@@ -721,6 +722,7 @@ ds_options2Proc(HWND hdlg,
 			CheckDlgButton(hdlg, DS_UPDATABLECURSORS, ci->allow_keyset);
 			CheckDlgButton(hdlg, DS_SERVERSIDEPREPARE, ci->use_server_side_prepare);
 			CheckDlgButton(hdlg, DS_BYTEAASLONGVARBINARY, ci->bytea_as_longvarbinary);
+			CheckDlgButton(hdlg, DS_FETCH_REFCURSORS, ci->fetch_refcursors);
 			/*CheckDlgButton(hdlg, DS_LOWERCASEIDENTIFIER, ci->lower_case_identifier);*/
 
 			EnableWindow(GetDlgItem(hdlg, DS_FAKEOIDINDEX), atoi(ci->show_oid_column));
diff --git a/psqlodbc.h b/psqlodbc.h
index f41ff9b..ca8bab5 100644
--- a/psqlodbc.h
+++ b/psqlodbc.h
@@ -645,6 +645,7 @@ typedef struct
 	signed char	numeric_as;
 	signed char	optional_errors;
 	signed char	ignore_timeout;
+	signed char	fetch_refcursors;
 	UInt4		extra_opts;
 	Int4		keepalive_idle;
 	Int4		keepalive_interval;
diff --git a/psqlodbc.rc b/psqlodbc.rc
index 2c76ed6..75269c9 100644
--- a/psqlodbc.rc
+++ b/psqlodbc.rc
@@ -221,6 +221,8 @@ BEGIN
     PUSHBUTTON      "“K—p",IDAPPLY,128,ENDLINE_Y,50,14
     CONTROL         "bytea‚ðLO‚Æ‚µ‚Äˆµ‚¤",DS_BYTEAASLONGVARBINARY,"Button",
                     BS_AUTOCHECKBOX | WS_TABSTOP,15,85,87,10
+    CONTROL         "Šerefcursor‚©‚çŒ‹‰Ê‚ðŽæ“¾‚µ‚Ü‚·",DS_FETCH_REFCURSORS,
+                    "Button",BS_AUTOCHECKBOX | WS_TABSTOP,139,85,140,10
 END
 
 #define	DTC_GRP_X	10
@@ -638,6 +640,8 @@ BEGIN
     GROUPBOX        "Int8 As",IDC_STATIC,5,97,256,25
     CONTROL         "default",DS_INT8_AS_DEFAULT,"Button",BS_AUTORADIOBUTTON | 
                     WS_GROUP,12,107,40,10
+    CONTROL         "Fetch result from each refcursor",DS_FETCH_REFCURSORS,
+                    "Button",BS_AUTOCHECKBOX | WS_TABSTOP,163,84,122,10
     CONTROL         "bigint",DS_INT8_AS_BIGINT,"Button",BS_AUTORADIOBUTTON | 
                     WS_TABSTOP,55,107,35,10
     CONTROL         "numeric",DS_INT8_AS_NUMERIC,"Button",BS_AUTORADIOBUTTON | 
diff --git a/resource.h b/resource.h
index fac1fbb..483e623 100644
--- a/resource.h
+++ b/resource.h
@@ -119,6 +119,7 @@
 #define DS_NUMERIC_AS_LONGVARCHAR	1111
 #define DS_BATCH_SIZE			1112
 #define DS_IGNORETIMEOUT		1113
+#define DS_FETCH_REFCURSORS		1114
 
 // Next default values for new objects
 //
@@ -126,7 +127,7 @@
 #ifndef APSTUDIO_READONLY_SYMBOLS
 #define _APS_NEXT_RESOURCE_VALUE        106
 #define _APS_NEXT_COMMAND_VALUE         40001
-#define _APS_NEXT_CONTROL_VALUE         1114
+#define _APS_NEXT_CONTROL_VALUE         1115
 #define _APS_NEXT_SYMED_VALUE           101
 #endif
 #endif
diff --git a/statement.c b/statement.c
index 972aa50..9f47b40 100644
--- a/statement.c
+++ b/statement.c
@@ -2243,33 +2243,30 @@ MYLOG(DETAIL_LOG_LEVEL, "!!%p->miscinfo=%x res=%p\n", self, self->miscinfo, firs
 	{
 		Int2	io, out;
 		has_out_para = (CountParameters(self, NULL, &io, &out) > 0);
-/*
- *	I'm not sure if the following REFCUR_SUPPORT stuff is valuable
- *	or not.
- */
-#ifdef	REFCUR_SUPPORT
+if (ci->fetch_refcursors)
+{
 
-MYLOG(DETAIL_LOG_LEVEL, "!!! numfield=%d field_type=%u\n", QR_NumResultCols(res), QR_get_field_type(res, 0));
+MYLOG(DETAIL_LOG_LEVEL, "!!! numfield=%d field_type=%u\n", QR_NumResultCols(rhold.first), QR_get_field_type(rhold.first, 0));
 		if (!has_out_para &&
-		    0 < QR_NumResultCols(res) &&
-		    PG_TYPE_REFCURSOR == QR_get_field_type(res, 0))
+		    0 < QR_NumResultCols(rhold.first) &&
+		    PG_TYPE_REFCURSOR == QR_get_field_type(rhold.first, 0))
 		{
 			char	fetch[128];
 			int	stmt_type = self->statement_type;
 
-			STR_TO_NAME(self->cursor_name, QR_get_value_backend_text(res, 0, 0));
-			QR_Destructor(res);
+			STR_TO_NAME(self->cursor_name, QR_get_value_backend_text(rhold.first, 0, 0));
+			QR_Destructor(rhold.first);
 			SC_init_Result(self);
 			SC_set_fetchcursor(self);
 			qi.result_in = NULL;
 			qi.cursor = SC_cursor_name(self);
-			qi.cache_size = qi.row_size = ci->drivers.fetch_max;
+			qi.fetch_size = qi.row_size = ci->drivers.fetch_max;
 			SPRINTF_FIXED(fetch, "fetch " FORMAT_LEN " in \"%s\"", qi.fetch_size, SC_cursor_name(self));
-			res = CC_send_query(conn, fetch, &qi, qflag | READ_ONLY_QUERY, SC_get_ancestor(self));
-			if (NULL != res)
-				SC_set_Result(self, res);
+			rhold.first = CC_send_query(conn, fetch, &qi, qflag | READ_ONLY_QUERY, SC_get_ancestor(self));
+			if (NULL != rhold.first)
+				SC_set_Result(self, rhold.first);
 		}
-#endif	/* REFCUR_SUPPORT */
+}
 	}
 	if (has_out_para)
 	{	/* get the return value of the procedure call */
-- 
2.31.1.windows.1

