--- /dev/null
+connected
+ orientation=2 delete count=0
+ orientation=4 delete count=30
+ orientation=1 delete count=53
+ orientation=4 delete count=70
+ orientation=1 delete count=83
+ orientation=4 delete count=93
+ orientation=1 delete count=100
+ orientation=4 delete count=105
+ orientation=1 delete count=109
+ orientation=4 delete count=112
+ orientation=1 delete count=114
+ orientation=4 delete count=116
+ orientation=1 delete count=117
+ orientation=4 delete count=118
+ orientation=1 delete count=119
+ orientation=4 delete count=120
+delete all count 120
+ orientation=2 delete count=0
+ orientation=4 delete count=32
+ orientation=1 delete count=56
+ orientation=4 delete count=74
+ orientation=1 delete count=88
+ orientation=4 delete count=98
+ orientation=1 delete count=106
+ orientation=4 delete count=112
+ orientation=1 delete count=116
+ orientation=4 delete count=119
+ orientation=1 delete count=122
+ orientation=4 delete count=124
+ orientation=1 delete count=125
+ orientation=4 delete count=126
+ orientation=1 delete count=127
+ orientation=4 delete count=128
+delete all count 128
+ orientation=2 delete count=0
+ orientation=4 delete count=31
+ orientation=1 delete count=55
+ orientation=4 delete count=73
+ orientation=1 delete count=86
+ orientation=4 delete count=96
+ orientation=1 delete count=103
+ orientation=4 delete count=109
+ orientation=1 delete count=113
+ orientation=4 delete count=116
+ orientation=1 delete count=118
+ orientation=4 delete count=120
+ orientation=1 delete count=121
+ orientation=4 delete count=122
+ orientation=1 delete count=123
+ orientation=4 delete count=124
+delete all count 124
+disconnecting
--- /dev/null
+/*
+ * Test deleting tuples all with scrolling block cursors BOF ->
+ * EOF -> BOF -> ...
+ */
+
+#include <string.h>
+#include <stdio.h>
+#include <stdlib.h>
+
+#include "common.h"
+
+#define TOTAL 120
+#define BLOCK 4
+
+static SQLRETURN delete_loop(HSTMT hstmt)
+{
+ SQLRETURN rc;
+ BOOL use_first_last = 0;
+ int delcnt = 0, delsav;
+ SQLSMALLINT orientation = SQL_FETCH_FIRST;
+
+ do {
+ printf("\torientation=%d delete count=%d\n", orientation, delcnt);
+ delsav = delcnt;
+ if (use_first_last)
+ orientation = (orientation == SQL_FETCH_NEXT ? SQL_FETCH_FIRST : SQL_FETCH_LAST);
+ while (rc = SQLFetchScroll(hstmt, orientation, 0), SQL_SUCCEEDED(rc))
+ {
+ orientation = (orientation == SQL_FETCH_NEXT ? SQL_FETCH_NEXT : (orientation == SQL_FETCH_FIRST ? SQL_FETCH_NEXT : SQL_FETCH_PRIOR));
+ rc = SQLSetPos(hstmt, 1, SQL_DELETE, SQL_LCK_NO_CHANGE);
+ CHECK_STMT_RESULT(rc, "SQLSetPos delete failed", hstmt);
+ delcnt++;
+ }
+ if (SQL_NO_DATA != rc)
+ {
+ CHECK_STMT_RESULT(rc, "SQLFetchScroll failed", hstmt);
+ }
+ orientation = (orientation == SQL_FETCH_NEXT ? SQL_FETCH_PRIOR : SQL_FETCH_NEXT);
+ } while (delcnt != delsav);
+ printf("delete all count %d\n", delcnt);
+
+ return SQL_SUCCESS;
+}
+
+int main(int argc, char **argv)
+{
+ int rc;
+ HSTMT hstmt = SQL_NULL_HSTMT, hstmt2 = SQL_NULL_HSTMT;
+ int i, j, k;
+ int count = TOTAL;
+ char query[100];
+ SQLLEN rowArraySize = BLOCK;
+ SQLULEN rowsFetched;
+ SQLINTEGER id[BLOCK];
+ SQLLEN cbLen[BLOCK];
+
+ /****
+ * Run this test with UseDeclareFetch = 1 and Fetch=37.
+ */
+ 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 = SQLAllocHandle(SQL_HANDLE_STMT, conn, &hstmt2);
+ if (!SQL_SUCCEEDED(rc))
+ {
+ print_diag("failed to allocate stmt handle2", 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_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 = SQLSetStmtAttr(hstmt, SQL_ATTR_ROW_ARRAY_SIZE, (SQLPOINTER) rowArraySize, SQL_IS_UINTEGER);
+ CHECK_STMT_RESULT(rc, "SQLSetStmtAttr ROW_ARRAY_SIZE failed", hstmt);
+ rc = SQLSetStmtAttr(hstmt, SQL_ATTR_CONCURRENCY, (SQLPOINTER) SQL_CONCUR_ROWVER, 0);
+ CHECK_STMT_RESULT(rc, "SQLSetStmtAttr CONCURRENCY failed", hstmt);
+ rc = SQLSetConnectAttr(conn, SQL_AUTOCOMMIT, (SQLPOINTER) SQL_AUTOCOMMIT_OFF, 0);
+
+ rc = SQLSetStmtAttr(hstmt, SQL_ATTR_CURSOR_TYPE, (SQLPOINTER) SQL_CURSOR_STATIC, 0);
+ CHECK_STMT_RESULT(rc, "SQLSetStmtAttr CURSOR_TYPE failed", hstmt);
+ rc = SQLExecDirect(hstmt, (SQLCHAR *) "select * from tmptable", SQL_NTS);
+ CHECK_STMT_RESULT(rc, "select failed", hstmt);
+ rc = SQLExecDirect(hstmt2, (SQLCHAR *) "savepoint yuuki", SQL_NTS);
+ CHECK_STMT_RESULT(rc, "savepoint failed", hstmt2);
+ /*
+ * Scroll next -> EOF -> prior -> BOF -> next -> EOF ->
+ * ......
+ */
+ delete_loop(hstmt); /* the 1st loop */
+
+ rc = SQLExecDirect(hstmt2, (SQLCHAR *) "rollback to yuuki", SQL_NTS);
+ CHECK_STMT_RESULT(rc, "rollback failed", hstmt2);
+ for (i = 0, j = count, i = 0; i < 2; i++)
+ {
+ for (k = 0; k < rowArraySize; k++)
+ {
+ cbLen[k] = 0;
+ id[k] = j++;
+ }
+ /* rc = SQLBulkOperations(hstmt, SQL_ADD);
+ CHECK_STMT_RESULT(rc, "SQLBulkOperations SQL_ADD failed", hstmt); */
+ rc = SQLSetPos(hstmt, 0, SQL_ADD, SQL_LCK_NO_CHANGE);
+ CHECK_STMT_RESULT(rc, "SQLSetPos SQL_ADD failed", hstmt);
+ if (0 == i)
+ {
+ rc = SQLExecDirect(hstmt2, (SQLCHAR *) "savepoint yuuki", SQL_NTS);
+ CHECK_STMT_RESULT(rc, "savpoint failed", hstmt2);
+ }
+ }
+
+ delete_loop(hstmt); /* the 2nd loop */
+
+ rc = SQLExecDirect(hstmt2, (SQLCHAR *) "rollback to yuuki", SQL_NTS);
+ CHECK_STMT_RESULT(rc, "rollback failed", hstmt2);
+
+ delete_loop(hstmt); /* the 3rd loop */
+
+ rc = SQLEndTran(SQL_HANDLE_DBC, conn, SQL_ROLLBACK);
+ CHECK_STMT_RESULT(rc, "SQLEndTran failed", hstmt);
+ rc = SQLFreeStmt(hstmt, SQL_CLOSE);
+ CHECK_STMT_RESULT(rc, "SQLFreeStmt failed", hstmt);
+
+ /* Clean up */
+ test_disconnect();
+
+ return 0;
+}