static int odbc_dispatch20(void) { unsigned long retval; PWord rval; int rtype; PWord arg1; int type1; PWord arg2; int type2; PWord arg3; int type3; PWord arg4; int type4; PI_getan(&arg1,&type1,1); if (type1 != PI_INT) if (!CI_get_integer((unsigned long *)&arg1,type1)) PI_FAIL; PI_getan(&arg2,&type2,2); if (type2 != PI_INT) if (!CI_get_integer((unsigned long *)&arg2,type2)) PI_FAIL; PI_getan(&arg3,&type3,3); if (type3 != PI_INT) if (!CI_get_integer((unsigned long *)&arg3,type3)) PI_FAIL; PI_getan(&arg4,&type4,4); switch(arg1) { case 0: retval = (unsigned long) SQLNumParams(((SQLHSTMT ) arg2),((SQLSMALLINT * ) arg3)); break; case 1: retval = (unsigned long) SQLBulkOperations(((SQLHSTMT ) arg2),((SQLSMALLINT ) arg3)); break; case 2: retval = (unsigned long) SQLRowCount(((SQLHSTMT ) arg2),((SQLINTEGER * ) arg3)); break; case 3: retval = (unsigned long) SQLParamData(((SQLHSTMT ) arg2),((SQLPOINTER * ) arg3)); break; case 4: retval = (unsigned long) SQLNumResultCols(((SQLHSTMT ) arg2),((SQLSMALLINT * ) arg3)); break; case 5: retval = (unsigned long) SQLGetTypeInfo(((SQLHSTMT ) arg2),((SQLSMALLINT ) arg3)); break; case 6: retval = (unsigned long) SQLFreeStmt(((SQLHSTMT ) arg2),((SQLUSMALLINT ) arg3)); break; case 7: retval = (unsigned long) SQLFreeHandle(((SQLSMALLINT ) arg2),((SQLHANDLE ) arg3)); break; case 8: retval = (unsigned long) SQLCopyDesc(((SQLHDESC ) arg2),((SQLHDESC ) arg3)); break; case 9: retval = (unsigned long) SQLAllocStmt(((SQLHDBC ) arg2),((SQLHSTMT * ) arg3)); break; case 10: retval = (unsigned long) SQLAllocConnect(((SQLHENV ) arg2),((SQLHDBC * ) arg3)); break; default: PI_FAIL; } PI_makedouble(&rval,&rtype,(double) retval); if (PI_unify(arg4,type4,rval,rtype)) PI_SUCCEED; PI_FAIL; }
int main(int argc, char **argv) { int rc; HSTMT hstmt = SQL_NULL_HSTMT; int i; SQLINTEGER colvalue1; SQLINTEGER colvalue2; SQLLEN indColvalue1; SQLLEN indColvalue2; char bookmark[8]; SQLLEN bookmark_ind; char saved_bookmarks[3][8]; SQLLEN saved_bookmark_inds[3]; SQLINTEGER colvalues1[3]; SQLINTEGER colvalues2[3]; SQLLEN indColvalues1[3]; SQLLEN indColvalues2[3]; memset(bookmark, 0x7F, sizeof(bookmark)); memset(saved_bookmarks, 0xF7, sizeof(saved_bookmarks)); test_connect_ext("UpdatableCursors=1;UseDeclareFetch=0"); rc = SQLAllocHandle(SQL_HANDLE_STMT, conn, &hstmt); if (!SQL_SUCCEEDED(rc)) { print_diag("failed to allocate stmt handle", SQL_HANDLE_DBC, conn); exit(1); } /* * Initialize a table with some test data. */ printf("Creating test table bulkoperations_test\n"); rc = SQLExecDirect(hstmt, (SQLCHAR *) "CREATE TEMPORARY TABLE bulkoperations_test(i int4, orig int4)", SQL_NTS); CHECK_STMT_RESULT(rc, "SQLExecDirect failed", hstmt); rc = SQLExecDirect(hstmt, (SQLCHAR *) "INSERT INTO bulkoperations_test SELECT g, g FROM generate_series(1, 10) g", SQL_NTS); CHECK_STMT_RESULT(rc, "SQLExecDirect failed", hstmt); rc = SQLFreeStmt(hstmt, SQL_CLOSE); CHECK_STMT_RESULT(rc, "SQLFreeStmt failed", hstmt); printf("Opening a cursor for update, and fetching 10 rows\n"); rc = SQLSetStmtAttr(hstmt, SQL_ATTR_CONCURRENCY, (SQLPOINTER) SQL_CONCUR_ROWVER, 0); CHECK_STMT_RESULT(rc, "SQLSetStmtAttr failed", hstmt); rc = SQLSetStmtAttr(hstmt, SQL_ATTR_CURSOR_TYPE, (SQLPOINTER) SQL_CURSOR_KEYSET_DRIVEN, 0); CHECK_STMT_RESULT(rc, "SQLSetStmtAttr failed", hstmt); /* Enable bookmarks */ rc = SQLSetStmtAttr(hstmt, SQL_ATTR_USE_BOOKMARKS, (SQLPOINTER) SQL_UB_VARIABLE, SQL_IS_UINTEGER); CHECK_STMT_RESULT(rc, "SQLSetStmtAttr failed", hstmt); rc = SQLBindCol(hstmt, 0, SQL_C_VARBOOKMARK, &bookmark, sizeof(bookmark), &bookmark_ind); CHECK_STMT_RESULT(rc, "SQLBindCol failed", hstmt); rc = SQLBindCol(hstmt, 1, SQL_C_LONG, &colvalue1, 0, &indColvalue1); CHECK_STMT_RESULT(rc, "SQLBindCol failed", hstmt); rc = SQLBindCol(hstmt, 2, SQL_C_LONG, &colvalue2, 0, &indColvalue2); CHECK_STMT_RESULT(rc, "SQLBindCol failed", hstmt); rc = SQLExecDirect(hstmt, (SQLCHAR *) "SELECT * FROM bulkoperations_test ORDER BY orig", SQL_NTS); CHECK_STMT_RESULT(rc, "SQLExecDirect failed", hstmt); for (i = 1; i <= 5; i++) { rc = SQLFetch(hstmt); if (rc == SQL_NO_DATA) break; if (rc == SQL_SUCCESS) printCurrentRow(hstmt); else { print_diag("SQLFetch failed", SQL_HANDLE_STMT, hstmt); exit(1); } /* Save row # 2's bookmark for fetch test */ if (i == 2) { memcpy(saved_bookmarks[0], bookmark, bookmark_ind); saved_bookmark_inds[0] = bookmark_ind; } } /* Do a positioned update and delete */ printf("\nUpdating result set\n"); colvalue1 += 100; rc = SQLBulkOperations(hstmt, SQL_UPDATE_BY_BOOKMARK); CHECK_STMT_RESULT(rc, "SQLBulkOperations failed", hstmt); /* Have to use an absolute position after SQLBulkOperations. */ rc = SQLFetchScroll(hstmt, SQL_FETCH_ABSOLUTE, 8); CHECK_STMT_RESULT(rc, "SQLFetchScroll failed", hstmt); rc = SQLBulkOperations(hstmt, SQL_DELETE_BY_BOOKMARK); CHECK_STMT_RESULT(rc, "SQLBulkOperations failed", hstmt); /* Have to use an absolute position after SQLBulkOperations. */ rc = SQLFetchScroll(hstmt, SQL_FETCH_ABSOLUTE, 5); CHECK_STMT_RESULT(rc, "SQLFetchScroll failed", hstmt); /* Print the updated row */ printCurrentRow(hstmt); /* remember its bookmark for later fetch */ memcpy(saved_bookmarks[1], bookmark, bookmark_ind); saved_bookmark_inds[1] = bookmark_ind; /* Perform an insertion */ colvalue1 = 1234; colvalue2 = 5678; rc = SQLBulkOperations(hstmt, SQL_ADD); CHECK_STMT_RESULT(rc, "SQLBulkOperations failed", hstmt); /* Remember the bookmark of the inserted row */ memcpy(saved_bookmarks[2], bookmark, bookmark_ind); saved_bookmark_inds[2] = bookmark_ind; /**** Test bulk fetch *****/ printf("Testing bulk fetch of original, updated, and inserted rows\n"); rc = SQLBindCol(hstmt, 0, SQL_C_VARBOOKMARK, saved_bookmarks, sizeof(bookmark), saved_bookmark_inds); CHECK_STMT_RESULT(rc, "SQLBindCol failed", hstmt); rc = SQLBindCol(hstmt, 1, SQL_C_LONG, colvalues1, 0, indColvalues1); CHECK_STMT_RESULT(rc, "SQLBindCol failed", hstmt); rc = SQLBindCol(hstmt, 2, SQL_C_LONG, colvalues2, 0, indColvalues2); CHECK_STMT_RESULT(rc, "SQLBindCol failed", hstmt); rc = SQLSetStmtAttr(hstmt, SQL_ATTR_ROW_ARRAY_SIZE, (SQLPOINTER) 3, 0); CHECK_STMT_RESULT(rc, "SQLSetStmtAttr failed", hstmt); /* * FIXME: Disabled, because this doesn't currently seem to produce the * right results. */ #ifdef BROKEN rc = SQLBulkOperations(hstmt, SQL_FETCH_BY_BOOKMARK); CHECK_STMT_RESULT(rc, "SQLBulkOperations failed", hstmt); printf ("row no #2: %d - %d\n", colvalues1[0], colvalues2[0]); printf ("updated row: %d - %d\n", colvalues1[1], colvalues2[1]); printf ("inserted row: %d - %d\n", colvalues1[2], colvalues2[2]); #endif rc = SQLFreeStmt(hstmt, SQL_CLOSE); CHECK_STMT_RESULT(rc, "SQLFreeStmt failed", hstmt); rc = SQLSetStmtAttr(hstmt, SQL_ATTR_ROW_ARRAY_SIZE, (SQLPOINTER) 1, 0); CHECK_STMT_RESULT(rc, "SQLSetStmtAttr failed", hstmt); /**** See if the updates really took effect ****/ printf("\nQuerying the table again\n"); rc = SQLExecDirect(hstmt, (SQLCHAR *) "SELECT * FROM bulkoperations_test ORDER BY orig", SQL_NTS); CHECK_STMT_RESULT(rc, "SQLExecDirect failed", hstmt); print_result(hstmt); /* Clean up */ test_disconnect(); return 0; }