{
char fetch[128];
QResultClass *last = NULL, *res;
+ BOOL refcursor_found = FALSE;
/* Iterate the columns in the result to look for refcursors */
numcols = QR_NumResultCols(rhold.first);
break;
}
+ refcursor_found = TRUE;
STR_TO_NAME(self->cursor_name, QR_get_value_backend_text(rhold.first, 0, i));
+ /* Skip NULL refcursors (allows procedure to return a variable number of results) */
+ if (!SC_cursor_is_valid(self))
+ continue;
+
SC_set_fetchcursor(self);
qi.result_in = NULL;
qi.cursor = SC_cursor_name(self);
QR_concat(last, res);
self->multi_statement = TRUE;
}
+ last = res;
if (!QR_command_maybe_successful(res))
{
SC_set_errorinfo(self, res, 0);
- QR_Destructor(rhold.first);
break;
}
-
- last = res;
}
}
}
- if (last)
- QR_Destructor(rhold.first);
+ if (refcursor_found)
+ {
+ /* Discard original result */
+ if (NULL == last)
+ SC_set_Result(self, QR_Constructor()); /* return empty result */
+ else
+ QR_Destructor(rhold.first);
+ }
}
}
cleanup:
connected
disconnecting
--- TEST using FetchRefcursors=0 and SQL_ATTR_AUTOCOMMIT=1
+-- TEST using FetchRefcursors=0, autocommit=1, numresults=2
connected
Output param num_cursor is 2
--1 Result set:
-2 ref1 ref2
+2 <unnamed portal 1> <unnamed portal 2>
disconnecting
--- TEST using FetchRefcursors=1 and SQL_ATTR_AUTOCOMMIT=1
+-- TEST using 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 and SQL_ATTR_AUTOCOMMIT=0
+-- TEST using 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
+connected
+Output param num_cursor is 1
+--1 Result set:
+1 foo
+2 bar
+3 foobar
+disconnecting
+
+-- TEST using FetchRefcursors=1, autocommit=0, numresults=2
+connected
+Output param num_cursor is 2
+--1 Result set:
+1 foo
+2 bar
+3 foobar
+--2 Result set:
+foobar 3
+bar 2
+foo 1
+disconnecting
+
+-- TEST using FetchRefcursors=1, autocommit=0, numresults=3
connected
Output param num_cursor is 2
--1 Result set:
CHECK_CONN_RESULT(rc, "failed to allocate stmt handle", conn);
rc = SQLExecDirect(hstmt, "create or replace procedure refproc"
- "(inout num_cursor integer, inout ref1 refcursor default 'ref1', inout ref2 refcursor default 'ref2') as "
+ "(inout num_cursor integer, inout ref1 refcursor default null, inout ref2 refcursor default null) as "
"$procedure$ \n"
"DECLARE \n"
"BEGIN \n"
- "num_cursor := 2; \n"
- "OPEN ref1 FOR SELECT id, t FROM testtab1 ORDER BY id ASC; \n"
- "OPEN ref2 FOR SELECT t, id FROM testtab1 ORDER BY id DESC; \n"
+ "IF num_cursor > 0 THEN \n"
+ " OPEN ref1 FOR SELECT id, t FROM testtab1 ORDER BY id ASC; \n"
+ "END IF; \n"
+ "IF num_cursor > 1 THEN \n"
+ " OPEN ref2 FOR SELECT t, id FROM testtab1 ORDER BY id DESC; \n"
+ "END IF; \n"
+ "IF num_cursor > 2 THEN \n"
+ " num_cursor := 2; \n"
+ "END IF; \n"
"END; \n"
"$procedure$ \n"
"LANGUAGE plpgsql\n"
test_disconnect();
}
-static void refcursor_test(char* connectparams, SQLUINTEGER autocommit)
+static void refcursor_test(char* connectparams, SQLUINTEGER autocommit, int numresults)
{
SQLRETURN rc;
HSTMT hstmt = SQL_NULL_HSTMT;
- int num_cursor = 0;
+ int num_cursor = numresults;
- printf("\n-- TEST using %s and SQL_ATTR_AUTOCOMMIT=%u\n", connectparams, autocommit);
+ printf("\n-- TEST using %s, autocommit=%u, numresults=%d\n", connectparams, autocommit, numresults);
test_connect_ext(connectparams);
{
setup_procedure();
- refcursor_test("FetchRefcursors=0", SQL_AUTOCOMMIT_ON);
- refcursor_test("FetchRefcursors=1", SQL_AUTOCOMMIT_ON);
- refcursor_test("FetchRefcursors=1", SQL_AUTOCOMMIT_OFF);
+ 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);
return 0;
}