On second thoughts, treat a bookmark as a 32-bit integer, not SQLULEN.
authorHeikki Linnakangas <heikki.linnakangas@iki.fi>
Fri, 5 Dec 2014 22:52:37 +0000 (00:52 +0200)
committerHeikki Linnakangas <heikki.linnakangas@iki.fi>
Fri, 5 Dec 2014 22:52:37 +0000 (00:52 +0200)
This seems more reliable.

Add a test case for SQLBulkOperations(SQL_FETCH_BY_BOOKMARK), although it's
disabled because it doesn't seem to work correctly (fetches wrong rows).
I don't have the energy to actually fix that now.

options.c
pgapi30.c
results.c
test/expected/bulkoperations.out
test/src/bulkoperations-test.c

index 20897dff8de6682a7dd1106b428cc04ad4528138..594c2e1d8249610eea7a395ff772c5555aa4a3f1 100644 (file)
--- a/options.c
+++ b/options.c
@@ -674,6 +674,7 @@ PGAPI_GetStmtOption(HSTMT hstmt,
    QResultClass *res;
    SQLLEN      ridx;
    SQLINTEGER  len = sizeof(SQLINTEGER);
+   UInt4       bookmark;
 
    mylog("%s: entering...\n", func);
 
@@ -726,7 +727,8 @@ PGAPI_GetStmtOption(HSTMT hstmt,
                return SQL_ERROR;
            }
 
-           *((SQLULEN *) pvParam) = SC_get_bookmark(stmt);
+           bookmark = SC_get_bookmark(stmt);
+           memcpy(pvParam, &bookmark, sizeof(UInt4));
 
            break;
 
index 518853a7c93e5d95c7e52f5555f827d07b6fe926..8c5155dc4c3716ed56fa314ec02d388859862f6a 100644 (file)
--- a/pgapi30.c
+++ b/pgapi30.c
@@ -1933,7 +1933,7 @@ inolog("set ard=%p\n", stmt->ard);
 
 #define    CALC_BOOKMARK_ADDR(book, offset, bind_size, index) \
    (book->buffer + offset + \
-   (bind_size > 0 ? bind_size : (SQL_C_VARBOOKMARK == book->returntype ? book->buflen : sizeof(BOOKMARK))) * index)
+   (bind_size > 0 ? bind_size : (SQL_C_VARBOOKMARK == book->returntype ? book->buflen : sizeof(UInt4))) * index)
 
 /* SQL_NEED_DATA callback for PGAPI_BulkOperations */
 typedef struct
@@ -1976,8 +1976,8 @@ RETCODE   bulk_ope_callback(RETCODE retcode, void *para)
    {
        if (SQL_ADD != s->operation)
        {
-           BOOKMARK tmp;
-           memcpy(&tmp, CALC_BOOKMARK_ADDR(bookmark, offset, bind_size, s->idx), sizeof(BOOKMARK));
+           UInt4 tmp;
+           memcpy(&tmp, CALC_BOOKMARK_ADDR(bookmark, offset, bind_size, s->idx), sizeof(UInt4));
            global_idx = SC_resolve_bookmark(tmp);
        }
        /* Note opts->row_operation_ptr is ignored */
index 8080d195420833a0276e646d62539d55fdabf2db..164938d8ac34bbd92ea7a747057ca2af56e610d9 100644 (file)
--- a/results.c
+++ b/results.c
@@ -1012,15 +1012,15 @@ inolog("currT=%d base=%d rowset=%d\n", stmt->currTuple, QR_get_rowstart_in_cache
 
        if (rgbValue)
        {
-           if (SQL_C_BOOKMARK == target_type || sizeof(BOOKMARK) <= cbValueMax)
+           if (SQL_C_BOOKMARK == target_type || sizeof(UInt4) <= cbValueMax)
            {
-               SQLULEN tmp = SC_get_bookmark(stmt);
-               memcpy(rgbValue, &tmp, sizeof(BOOKMARK));
+               UInt4 bookmark = SC_get_bookmark(stmt);
                contents_get = TRUE;
+               memcpy(rgbValue, &bookmark, sizeof(UInt4));
            }
        }
        if (pcbValue)
-           *pcbValue = sizeof(BOOKMARK);
+           *pcbValue = sizeof(UInt4);
 
        if (contents_get)
            result = SQL_SUCCESS;
index 3115d2043e83b090bb1ccfb7b9123c576438a5d0..eea9bb850b779215bc7e77240c5baed270b3cd58 100644 (file)
@@ -10,6 +10,7 @@ Opening a cursor for update, and fetching 10 rows
 
 Updating result set
 105    5
+Testing bulk fetch of original, updated, and inserted rows
 
 Querying the table again
 Result set:
index 6e62115af798198b0176740a5356f5902e885a09..7c78c52ba59e963a7136828694a0e4ed694afd2f 100644 (file)
@@ -40,9 +40,19 @@ int main(int argc, char **argv)
    SQLINTEGER  colvalue2;
    SQLLEN      indColvalue1;
    SQLLEN      indColvalue2;
-   char        bookmark[100];
+   char        bookmark[10];
    SQLLEN      bookmark_ind;
 
+   char        saved_bookmarks[3][10];
+   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);
@@ -88,7 +98,7 @@ int main(int argc, char **argv)
    rc = SQLExecDirect(hstmt, (SQLCHAR *) "SELECT * FROM bulkoperations_test ORDER BY orig", SQL_NTS);
    CHECK_STMT_RESULT(rc, "SQLExecDirect failed", hstmt);
 
-   for (i = 0; i < 5; i++)
+   for (i = 1; i <= 5; i++)
    {
        rc = SQLFetch(hstmt);
        if (rc == SQL_NO_DATA)
@@ -100,6 +110,13 @@ int main(int argc, char **argv)
            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 */
@@ -123,15 +140,51 @@ int main(int argc, char **argv)
    /* 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);