From a843f826deb71a75f6d465570c811f79879b20a5 Mon Sep 17 00:00:00 2001 From: Adrian Grucza Date: Fri, 23 Jun 2023 09:15:24 +0900 Subject: [PATCH] Prevent cursors being closed prematurely --- qresult.c | 22 ++++++++++++++++------ test/expected/fetch-refcursors.out | 12 ++++++------ test/src/fetch-refcursors-test.c | 13 +++++++------ 3 files changed, 29 insertions(+), 18 deletions(-) diff --git a/qresult.c b/qresult.c index 40ad3b7..f4e5fd4 100644 --- a/qresult.c +++ b/qresult.c @@ -99,14 +99,24 @@ QR_set_cursor(QResultClass *self, const char *name) } else { - QResultClass *res; - self->cursor_name = NULL; - for (res = QR_nextr(self); NULL != res; res = QR_nextr(res)) + + /* + * The isSqlServr() check below was added because the code was freeing + * cursors prematurely when other results with open cursors exist. The + * code was originally added for a scenario using SQL Server linked + * servers in commit c07342d22d82ea6293d27057840babfc2ff6d750. + */ + if (isSqlServr()) { - if (NULL != res->cursor_name) - free(res->cursor_name); - res->cursor_name = NULL; + QResultClass *res; + + for (res = QR_nextr(self); NULL != res; res = QR_nextr(res)) + { + if (NULL != res->cursor_name) + free(res->cursor_name); + res->cursor_name = NULL; + } } } } diff --git a/test/expected/fetch-refcursors.out b/test/expected/fetch-refcursors.out index bfe6f85..a594d4d 100644 --- a/test/expected/fetch-refcursors.out +++ b/test/expected/fetch-refcursors.out @@ -2,25 +2,25 @@ Creating procedure 'refproc' connected disconnecting --- TEST using FetchRefcursors=0, autocommit=1, numresults=2 +-- TEST using Fetch=1;FetchRefcursors=0, autocommit=1, numresults=2 connected Output param num_cursor is 2 --1 Result set: 2 disconnecting --- TEST using FetchRefcursors=1, autocommit=1, numresults=2 +-- TEST using Fetch=1;FetchRefcursors=1, autocommit=1, numresults=2 connected SQLExecute failed HY000=Query must be executed in a transaction when FetchRefcursors setting is enabled. --- TEST using FetchRefcursors=1, autocommit=0, numresults=0 +-- TEST using Fetch=1;FetchRefcursors=1, autocommit=0, numresults=0 connected Output param num_cursor is 0 --1 Result set: disconnecting --- TEST using FetchRefcursors=1, autocommit=0, numresults=1 +-- TEST using Fetch=1;FetchRefcursors=1, autocommit=0, numresults=1 connected Output param num_cursor is 1 --1 Result set: @@ -29,7 +29,7 @@ Output param num_cursor is 1 3 foobar disconnecting --- TEST using FetchRefcursors=1, autocommit=0, numresults=2 +-- TEST using Fetch=1;FetchRefcursors=1, autocommit=0, numresults=2 connected Output param num_cursor is 2 --1 Result set: @@ -42,7 +42,7 @@ bar 2 foo 1 disconnecting --- TEST using FetchRefcursors=1, autocommit=0, numresults=3 +-- TEST using Fetch=1;FetchRefcursors=1, autocommit=0, numresults=3 connected Output param num_cursor is 2 --1 Result set: diff --git a/test/src/fetch-refcursors-test.c b/test/src/fetch-refcursors-test.c index 01e58e4..9453949 100644 --- a/test/src/fetch-refcursors-test.c +++ b/test/src/fetch-refcursors-test.c @@ -108,12 +108,13 @@ int main(int argc, char **argv) { setup_procedure(); - refcursor_test("FetchRefcursors=0", SQL_AUTOCOMMIT_ON, 2); - refcursor_test("FetchRefcursors=1", SQL_AUTOCOMMIT_ON, 2); - refcursor_test("FetchRefcursors=1", SQL_AUTOCOMMIT_OFF, 0); - refcursor_test("FetchRefcursors=1", SQL_AUTOCOMMIT_OFF, 1); - refcursor_test("FetchRefcursors=1", SQL_AUTOCOMMIT_OFF, 2); - refcursor_test("FetchRefcursors=1", SQL_AUTOCOMMIT_OFF, 3); + /* Using a fetch cache size of 1 to test multiple fetches per cursor */ + refcursor_test("Fetch=1;FetchRefcursors=0", SQL_AUTOCOMMIT_ON, 2); + refcursor_test("Fetch=1;FetchRefcursors=1", SQL_AUTOCOMMIT_ON, 2); + refcursor_test("Fetch=1;FetchRefcursors=1", SQL_AUTOCOMMIT_OFF, 0); + refcursor_test("Fetch=1;FetchRefcursors=1", SQL_AUTOCOMMIT_OFF, 1); + refcursor_test("Fetch=1;FetchRefcursors=1", SQL_AUTOCOMMIT_OFF, 2); + refcursor_test("Fetch=1;FetchRefcursors=1", SQL_AUTOCOMMIT_OFF, 3); return 0; } -- 2.39.5