LCOV - code coverage report
Current view: top level - src/odbc/unittests - cursor1.c (source / functions) Hit Total Coverage
Test: FreeTDS coverage Lines: 78 80 97.5 %
Date: 2024-03-23 08:24:27 Functions: 3 3 100.0 %

          Line data    Source code
       1             : #include "common.h"
       2             : 
       3             : /* Test cursors */
       4             : 
       5             : #define SWAP_STMT(b) do { SQLHSTMT xyz = odbc_stmt; odbc_stmt = b; b = xyz; } while(0)
       6             : 
       7             : static int mssql2005 = 0;
       8             : 
       9             : static void
      10          60 : Test0(int use_sql, const char *create_sql, const char *insert_sql, const char *select_sql)
      11             : {
      12             : #define ROWS 4
      13             : #define C_LEN 10
      14             : 
      15             :         SQLUINTEGER n[ROWS];
      16             :         char c[ROWS][C_LEN];
      17             :         SQLLEN c_len[ROWS], n_len[ROWS];
      18             : 
      19             :         SQLUSMALLINT statuses[ROWS];
      20             :         SQLUSMALLINT i;
      21             :         SQLULEN num_row;
      22             :         SQLHSTMT stmt2;
      23             : 
      24             :         /* create test table */
      25          60 :         odbc_command("IF OBJECT_ID('tempdb..#test') IS NOT NULL DROP TABLE #test");
      26          60 :         odbc_command(create_sql);
      27         420 :         for (i = 1; i <= 6; ++i) {
      28             :                 char sql_buf[80], data[10];
      29         360 :                 memset(data, 'a' + (i - 1), sizeof(data));
      30         360 :                 data[i] = 0;
      31         360 :                 sprintf(sql_buf, insert_sql, data, i);
      32         360 :                 odbc_command(sql_buf);
      33             :         }
      34             : 
      35             :         /* set cursor options */
      36          60 :         odbc_reset_statement();
      37          60 :         CHKSetStmtAttr(SQL_ATTR_CONCURRENCY, (SQLPOINTER) SQL_CONCUR_ROWVER, 0, "S");
      38          60 :         CHKSetStmtAttr(SQL_ATTR_CURSOR_TYPE, (SQLPOINTER) SQL_CURSOR_DYNAMIC, 0, "S");
      39          60 :         CHKSetStmtAttr(SQL_ATTR_ROW_ARRAY_SIZE, (SQLPOINTER) ROWS, 0, "S");
      40          60 :         CHKSetStmtAttr(SQL_ATTR_ROW_STATUS_PTR, (SQLPOINTER) statuses, 0, "S");
      41          60 :         CHKSetStmtAttr(SQL_ATTR_ROWS_FETCHED_PTR, &num_row, 0, "S");
      42          60 :         CHKSetCursorName(T("C1"), SQL_NTS, "S");
      43             : 
      44             :         /* */
      45          60 :         CHKExecDirect(T(select_sql), SQL_NTS, "S");
      46             : 
      47             :         /* bind some rows at a time */
      48          60 :         CHKBindCol(1, SQL_C_ULONG, n, 0, n_len, "S");
      49          60 :         CHKBindCol(2, SQL_C_CHAR, c, C_LEN, c_len, "S");
      50             : 
      51             :         /* allocate an additional statement */
      52          60 :         CHKAllocStmt(&stmt2, "S");
      53             : 
      54         240 :         while (CHKFetchScroll(SQL_FETCH_NEXT, 0, "SNo") == SQL_SUCCESS) {
      55             :                 /* print, just for debug */
      56         360 :                 for (i = 0; i < num_row; ++i)
      57         360 :                         printf("row %d i %d c %s\n", (int) (i + 1), (int) n[i], c[i]);
      58         120 :                 printf("---\n");
      59             : 
      60             :                 /* delete a row */
      61         120 :                 i = 1;
      62         120 :                 if (i > 0 && i <= num_row) {
      63         120 :                         CHKSetPos(i, use_sql ? SQL_POSITION : SQL_DELETE, SQL_LOCK_NO_CHANGE, mssql2005 ? "SI": "S");
      64         120 :                         if (use_sql) {
      65          60 :                                 SWAP_STMT(stmt2);
      66          60 :                                 CHKPrepare(T("DELETE FROM #test WHERE CURRENT OF C1"), SQL_NTS, "S");
      67          60 :                                 CHKExecute("S");
      68          60 :                                 SWAP_STMT(stmt2);
      69             :                         }
      70             :                 }
      71             : 
      72             :                 /* update another row */
      73         120 :                 i = 2;
      74         120 :                 if (i > 0 && i <= num_row) {
      75         120 :                         strcpy(c[i - 1], "foo");
      76         120 :                         c_len[i - 1] = 3;
      77         120 :                         if (strstr(select_sql, "#a") == NULL || use_sql) {
      78         108 :                                 CHKSetPos(i, use_sql ? SQL_POSITION : SQL_UPDATE, SQL_LOCK_NO_CHANGE, "S");
      79             :                         } else {
      80             :                                 SQLTCHAR sqlstate[6];
      81             :                                 SQLTCHAR msg[256];
      82             : 
      83          12 :                                 n[i - 1] = 321;
      84          12 :                                 CHKSetPos(i, use_sql ? SQL_POSITION : SQL_UPDATE, SQL_LOCK_NO_CHANGE, "E");
      85             : 
      86          12 :                                 CHKGetDiagRec(SQL_HANDLE_STMT, odbc_stmt, 1, sqlstate, NULL, msg, TDS_VECTOR_SIZE(msg), NULL, "S");
      87          12 :                                 if (strstr(C(msg), "Invalid column name 'c'") == NULL) {
      88           0 :                                         fprintf(stderr, "Expected message not found at line %d\n", __LINE__);
      89           0 :                                         exit(1);
      90             :                                 }
      91             :                         }
      92         120 :                         if (use_sql) {
      93          60 :                                 SWAP_STMT(stmt2);
      94          60 :                                 CHKPrepare(T("UPDATE #test SET c=? WHERE CURRENT OF C1"), SQL_NTS, "S");
      95          60 :                                 CHKBindParameter(1, SQL_PARAM_INPUT, SQL_C_CHAR, SQL_CHAR, C_LEN, 0, c[i - 1], 0, NULL, "S");
      96          60 :                                 CHKExecute("S");
      97             :                                 /* FIXME this is not necessary for mssql driver */
      98          60 :                                 SQLMoreResults(odbc_stmt);
      99          60 :                                 SWAP_STMT(stmt2);
     100             :                         }
     101             :                 }
     102             :         }
     103             : 
     104          60 :         SWAP_STMT(stmt2);
     105          60 :         CHKFreeStmt(SQL_DROP, "S");
     106          60 :         SWAP_STMT(stmt2);
     107             : 
     108          60 :         odbc_reset_statement();
     109             : 
     110             :         /* test values */
     111          60 :         odbc_check_no_row("IF (SELECT COUNT(*) FROM #test) <> 4 SELECT 1");
     112          60 :         odbc_check_no_row("IF NOT EXISTS(SELECT * FROM #test WHERE i = 3 AND c = 'ccc') SELECT 1");
     113          60 :         odbc_check_no_row("IF NOT EXISTS(SELECT * FROM #test WHERE i = 4 AND c = 'dddd') SELECT 1");
     114          60 :         if (strstr(select_sql, "#a") == NULL || use_sql) {
     115          54 :                 odbc_check_no_row("IF NOT EXISTS(SELECT * FROM #test WHERE i = 2 AND c = 'foo') SELECT 1");
     116          54 :                 odbc_check_no_row("IF NOT EXISTS(SELECT * FROM #test WHERE i = 6 AND c = 'foo') SELECT 1");
     117             :         }
     118          60 : }
     119             : 
     120             : static void
     121          12 : Test(int use_sql)
     122             : {
     123          12 :         odbc_command_with_result(odbc_stmt, "DROP TABLE #a");
     124          12 :         odbc_command("CREATE TABLE #a(x int)");
     125          12 :         odbc_command("INSERT INTO #a VALUES(123)");
     126          12 :         Test0(use_sql, "CREATE TABLE #test(i int, c varchar(6))", "INSERT INTO #test(c, i) VALUES('%s', %d)", "SELECT x AS i, c FROM #test, #a");
     127             : 
     128          12 :         Test0(use_sql, "CREATE TABLE #test(i int, c varchar(6))", "INSERT INTO #test(c, i) VALUES('%s', %d)", "SELECT i, c FROM #test");
     129          12 :         if (odbc_db_is_microsoft()) {
     130          12 :                 Test0(use_sql, "CREATE TABLE #test(i int identity(1,1), c varchar(6))", "INSERT INTO #test(c) VALUES('%s')", "SELECT i, c FROM #test");
     131          12 :                 Test0(use_sql, "CREATE TABLE #test(i int primary key, c varchar(6))", "INSERT INTO #test(c, i) VALUES('%s', %d)", "SELECT i, c FROM #test");
     132             :         }
     133          12 :         Test0(use_sql, "CREATE TABLE #test(i int, c varchar(6))", "INSERT INTO #test(c, i) VALUES('%s', %d)", "SELECT i, c, c + 'xxx' FROM #test");
     134          12 : }
     135             : 
     136             : int
     137           8 : main(void)
     138             : {
     139           8 :         odbc_connect();
     140           8 :         odbc_check_cursor();
     141             : 
     142           6 :         if (odbc_db_is_microsoft() && odbc_db_version_int() >= 0x09000000u)
     143           4 :                 mssql2005 = 1;
     144             : 
     145           6 :         Test(1);
     146             : 
     147           6 :         Test(0);
     148             : 
     149           6 :         odbc_disconnect();
     150             :         return 0;
     151             : }

Generated by: LCOV version 1.13