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: 2025-01-18 11:50:39 Functions: 3 3 100.0 %

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

Generated by: LCOV version 1.13