From c15f7cfea5c2974d4d66ebb8c63594283eca6c30 Mon Sep 17 00:00:00 2001 From: Hiroshi Inoue Date: Sat, 26 Mar 2016 22:20:38 +0900 Subject: [PATCH] Add test declare-block-test. It contains 3 cases which correspond to bugs introduced in 9.05.0100. They are all in declare/fetch mode. 1. Using block cursors. 2. Scroll BOF -> EOF -> BOF ... 3. When fetching a row "behind" the rowset by "fetch absolute", how many rows can be fetched? --- test/expected/declare-fetch-block.out | 10 +++ test/src/declare-fetch-block-test.c | 125 ++++++++++++++++++++++++++++++++++ 2 files changed, 135 insertions(+) create mode 100644 test/expected/declare-fetch-block.out create mode 100644 test/src/declare-fetch-block-test.c diff --git a/test/expected/declare-fetch-block.out b/test/expected/declare-fetch-block.out new file mode 100644 index 0000000..2368b59 --- /dev/null +++ b/test/expected/declare-fetch-block.out @@ -0,0 +1,10 @@ +connected +fetchIdx=1, fetched rows=84, total rows=84 +fetchIdx=2, fetched rows=36, total rows=120 +next total rows=120 +prior total rows=120 +next total rows=120 +prior total rows=120 +FetchScroll beyond the end failed 100 +encountered EOF at 120 +disconnecting diff --git a/test/src/declare-fetch-block-test.c b/test/src/declare-fetch-block-test.c new file mode 100644 index 0000000..2ecd0c2 --- /dev/null +++ b/test/src/declare-fetch-block-test.c @@ -0,0 +1,125 @@ +/* + * Test what happens when using block cursors, scrolling next and prior, or + * fetching a row "behind" the rowset by "fetch absolute". + */ + +#include +#include +#include + +#include "common.h" + +#define TOTAL 120 +#define BLOCK 84 +int main(int argc, char **argv) +{ + int rc; + HSTMT hstmt = SQL_NULL_HSTMT; + int i; + int count = TOTAL; + char query[100]; + int totalRows = 0; + int fetchIdx = 0; + SQLLEN rowArraySize = BLOCK; + SQLULEN rowsFetched; + SQLINTEGER id[BLOCK]; + SQLLEN cbLen[BLOCK]; + + /**** + * Run this test with UseDeclareFetch = 1 and Fetch=100(default). + */ + test_connect_ext("UseDeclareFetch=1"); + + rc = SQLAllocHandle(SQL_HANDLE_STMT, conn, &hstmt); + if (!SQL_SUCCEEDED(rc)) + { + print_diag("failed to allocate stmt handle", SQL_HANDLE_DBC, conn); + exit(1); + } + + rc = SQLExecDirect(hstmt, (SQLCHAR *) "create temporary table tmptable(id int4 primary key)", SQL_NTS); + CHECK_STMT_RESULT(rc, "SQLExecDirect create table failed", hstmt); + + /* insert into a table */ + for (i = 0; i < count; i++) + { + snprintf(query, sizeof(query), "insert into tmptable values (%d)", i); + rc = SQLExecDirect(hstmt, (SQLCHAR *) query, SQL_NTS); + CHECK_STMT_RESULT(rc, "insert into table failed", hstmt); + } + rc = SQLFreeStmt(hstmt, SQL_CLOSE); + CHECK_STMT_RESULT(rc, "SQLFreeStmt failed", hstmt); + + /* + * Block cursor + */ + rc = SQLSetStmtAttr(hstmt, SQL_ATTR_ROW_ARRAY_SIZE, (SQLPOINTER) rowArraySize, 0); + CHECK_STMT_RESULT(rc, "SQLSetStmtAttr ROW_ARRAY_SIZE failed", hstmt); + rc = SQLSetStmtAttr(hstmt, SQL_ATTR_ROWS_FETCHED_PTR, (SQLPOINTER) &rowsFetched, 0); + CHECK_STMT_RESULT(rc, "SQLSetStmtAttr ROWS_FETCHED_PTR failed", hstmt); + rc = SQLBindCol(hstmt, 1, SQL_C_SLONG, &id, 0, cbLen); + CHECK_STMT_RESULT(rc, "SQLBindCol failed", hstmt); + rc = SQLExecDirect(hstmt, (SQLCHAR *) "select * from tmptable", SQL_NTS); + CHECK_STMT_RESULT(rc, "select failed", hstmt); + while (rc = SQLFetch(hstmt), SQL_SUCCEEDED(rc)) + { + fetchIdx++; + totalRows += (int) rowsFetched; + printf("fetchIdx=%d, fetched rows=%d, total rows=%d\n", fetchIdx, (int) rowsFetched, totalRows); + } + rc = SQLFreeStmt(hstmt, SQL_CLOSE); + CHECK_STMT_RESULT(rc, "SQLFreeStmt failed", hstmt); + /* + * Scroll next -> EOF -> prior -> BOF -> next -> EOF -> prior -> BOF + */ + rc = SQLSetStmtAttr(hstmt, SQL_ATTR_ROW_ARRAY_SIZE, (SQLPOINTER) 1, SQL_IS_UINTEGER); + CHECK_STMT_RESULT(rc, "SQLSetStmtAttr ROW_ARRAY_SIZE failed", hstmt); + rc = SQLSetStmtAttr(hstmt, SQL_ATTR_CURSOR_TYPE, (SQLPOINTER) SQL_CURSOR_STATIC, 0); + CHECK_STMT_RESULT(rc, "SQLSetStmtAttr CURSOR_TYPE failed", hstmt); + rc = SQLSetStmtAttr(hstmt, SQL_ATTR_CONCURRENCY, (SQLPOINTER) SQL_CONCUR_ROWVER, 0); + CHECK_STMT_RESULT(rc, "SQLSetStmtAttr CONCURRENCY failed", hstmt); + rc = SQLExecDirect(hstmt, (SQLCHAR *) "select * from tmptable", SQL_NTS); + CHECK_STMT_RESULT(rc, "select failed", hstmt); + for (i = 0; i < 2; i++) + { + totalRows = 0; + while (rc = SQLFetchScroll(hstmt, SQL_FETCH_NEXT, 0), SQL_SUCCEEDED(rc)) + totalRows += (int) rowsFetched; + if (SQL_NO_DATA != rc) + CHECK_STMT_RESULT(rc, "fetch failed", hstmt); + printf("next total rows=%d\n", totalRows); + totalRows = 0; + while (rc = SQLFetchScroll(hstmt, SQL_FETCH_PRIOR, 0), SQL_SUCCEEDED(rc)) + totalRows += (int) rowsFetched; + if (SQL_NO_DATA != rc) + CHECK_STMT_RESULT(rc, "fetch failed", hstmt); + printf("prior total rows=%d\n", totalRows); + } + rc = SQLFreeStmt(hstmt, SQL_CLOSE); + CHECK_STMT_RESULT(rc, "SQLFreeStmt failed", hstmt); + /* + * When fetching a row "behind" the rowset by "fetch absolute" only the first ones of the result set can be fetched? + */ + rc = SQLExecDirect(hstmt, (SQLCHAR *) "select * from tmptable", SQL_NTS); + CHECK_STMT_RESULT(rc, "select failed", hstmt); + if (rc = SQLFetchScroll(hstmt, SQL_FETCH_ABSOLUTE, count + 1), !SQL_SUCCEEDED(rc)) + { + printf("FetchScroll beyond the end failed %d\n", rc); + } + rc = SQLFetchScroll(hstmt, SQL_FETCH_ABSOLUTE, 1); + CHECK_STMT_RESULT(rc, "FetchScroll the 1st row failed", hstmt); + for (i = 1; i < count; i++) + { + if (!SQL_SUCCEEDED(rc = SQLFetchScroll(hstmt, SQL_FETCH_NEXT, 0))) + break; + } + printf("encountered EOF at %d\n", i); + + rc = SQLFreeStmt(hstmt, SQL_CLOSE); + CHECK_STMT_RESULT(rc, "SQLFreeStmt failed", hstmt); + + /* Clean up */ + test_disconnect(); + + return 0; +} -- 2.5.5