LCOV - code coverage report
Current view: top level - src/odbc/unittests - array_out.c (source / functions) Hit Total Coverage
Test: FreeTDS coverage Lines: 75 88 85.2 %
Date: 2025-01-18 11:50:39 Functions: 2 2 100.0 %

          Line data    Source code
       1             : #include "common.h"
       2             : #include <assert.h>
       3             : 
       4             : /* Test using array binding */
       5             : 
       6             : static const char *test_query = NULL;
       7             : static int trunc = 0;
       8             : static int record_bind = 0;
       9             : 
      10             : typedef struct
      11             : {
      12             :         SQLUINTEGER id;
      13             :         SQLLEN id_len;
      14             :         SQLLEN desc_len;
      15             : } Record;
      16             : 
      17             : static void
      18          32 : query_test(const char* expected, const char *expected_status)
      19             : {
      20             : #define ARRAY_SIZE 10
      21             : 
      22          32 :         ODBC_BUF *odbc_buf = NULL;
      23             :         SQLUINTEGER *ids;
      24             :         SQLCHAR *descs;
      25             :         SQLLEN *id_lens, *desc_lens;
      26             :         SQLULEN processed;
      27             :         SQLUSMALLINT i, statuses[ARRAY_SIZE];
      28          32 :         int desc_len = trunc ? 4 : 51;
      29          32 :         int rec_size = 0;
      30          32 :         Record *rec = NULL;
      31             :         char status[20];
      32             : 
      33          32 :         assert(odbc_stmt != SQL_NULL_HSTMT);
      34          32 :         odbc_reset_statement();
      35             : 
      36          32 :         SQLSetStmtAttr(odbc_stmt, SQL_ATTR_ROW_STATUS_PTR, statuses, 0);
      37          32 :         SQLSetStmtAttr(odbc_stmt, SQL_ATTR_ROW_ARRAY_SIZE, (void *) ARRAY_SIZE, 0);
      38          32 :         SQLSetStmtAttr(odbc_stmt, SQL_ATTR_ROWS_FETCHED_PTR, &processed, 0);
      39          32 :         SQLSetStmtAttr(odbc_stmt, SQL_ATTR_ROW_BIND_TYPE, SQL_BIND_BY_COLUMN, 0);
      40             : 
      41          32 :         if (!record_bind) {
      42          16 :                 ids = (SQLUINTEGER *) ODBC_GET(sizeof(SQLUINTEGER) * ARRAY_SIZE);
      43          16 :                 descs = (SQLCHAR *) ODBC_GET(sizeof(SQLCHAR) * ARRAY_SIZE * desc_len);
      44          16 :                 desc_lens = (SQLLEN *) ODBC_GET(sizeof(SQLLEN) * ARRAY_SIZE);
      45          16 :                 id_lens = (SQLLEN *) ODBC_GET(sizeof(SQLLEN) * ARRAY_SIZE);
      46          16 :                 assert(descs && ids && desc_lens && id_lens);
      47             :         } else {
      48          16 :                 rec_size = (sizeof(Record) + (sizeof(SQLCHAR) * desc_len + sizeof(SQLLEN) - 1)) & ~(sizeof(SQLLEN) - 1);
      49          16 :                 SQLSetStmtAttr(odbc_stmt, SQL_ATTR_ROW_BIND_TYPE, TDS_INT2PTR(rec_size), 0);
      50          16 :                 rec = (Record *) ODBC_GET(rec_size * ARRAY_SIZE);
      51          16 :                 ids = &rec->id;
      52          16 :                 id_lens = &rec->id_len;
      53          16 :                 desc_lens = &rec->desc_len;
      54          16 :                 descs = (SQLCHAR *) (((char *) rec) + sizeof(Record));
      55             :         }
      56             : #define REC(f,n) (((char*)f)+rec_size*(n))
      57             : #define DESCS(n) (rec ? (SQLCHAR*)REC(descs,n): (descs+(n)*desc_len))
      58             : #define IDS(n) *(rec ? (SQLUINTEGER*)REC(ids,n) : &ids[n])
      59             : #define ID_LENS(n) *(rec ? (SQLLEN*)REC(id_lens,n) : &id_lens[n])
      60             : #define DESC_LENS(n) *(rec ? (SQLLEN*)REC(desc_lens,n) : &desc_lens[n])
      61             : 
      62          32 :         processed = ARRAY_SIZE + 1;
      63         352 :         for (i = 0; i < ARRAY_SIZE; i++) {
      64         320 :                 statuses[i] = SQL_ROW_UPDATED;
      65         320 :                 IDS(i) = i * 132;
      66         320 :                 sprintf((char *) DESCS(i), "aaa");
      67         320 :                 ID_LENS(i) = 0;
      68         320 :                 DESC_LENS(i) = -i;
      69             :         }
      70             : 
      71          32 :         SQLBindCol(odbc_stmt, 1, SQL_C_ULONG, &IDS(0), 0, &ID_LENS(0));
      72          32 :         SQLBindCol(odbc_stmt, 2, SQL_C_CHAR, DESCS(0), desc_len, &DESC_LENS(0));
      73             : 
      74          32 :         CHKExecDirect(T(test_query), SQL_NTS, "S");
      75             : 
      76          32 :         CHKFetch(expected);
      77             : 
      78          32 :         assert(processed <= ARRAY_SIZE);
      79             : 
      80         288 :         for (i = 0; i < processed; ++i) {
      81             :                 char buf[128];
      82             : 
      83         288 :                 sprintf(buf, "%crow number %d", 'a' + i, i * 13);
      84         288 :                 if (trunc)
      85          80 :                         buf[3] = 0;
      86         288 :                 if (IDS(i) != i + 1 || strcmp((char *) DESCS(i), buf) != 0) {
      87           0 :                         fprintf(stderr, "Invalid result\n\tgot '%d|%s'\n\texpected '%d|%s'\n", (int) IDS(i), DESCS(i), i + 1, buf);
      88           0 :                         exit(1);
      89             :                 }
      90             : 
      91         288 :                 switch (statuses[i]) {
      92         208 :                 case SQL_ROW_SUCCESS:
      93         208 :                         status[i] = 'V';
      94         208 :                         break;
      95             : 
      96           0 :                 case SQL_ROW_SUCCESS_WITH_INFO:
      97           0 :                         status[i] = 'v';
      98           0 :                         break;
      99             : 
     100          80 :                 case SQL_ROW_ERROR:
     101          80 :                         status[i] = '!';
     102          80 :                         break;
     103             : 
     104           0 :                 case SQL_ROW_NOROW:
     105           0 :                         status[i] = ' ';
     106           0 :                         break;
     107             : 
     108           0 :                 default:
     109           0 :                         fprintf(stderr, "Invalid status returned\n");
     110           0 :                         exit(1);
     111             :                 }
     112             :         }
     113          32 :         status[i] = 0;
     114             : 
     115          32 :         if (expected_status && strcmp(expected_status, status) != 0) {
     116           0 :                 fprintf(stderr, "Invalid status\n\tgot '%s'\n\texpected '%s'\n", status, expected_status);
     117           0 :                 exit(1);
     118             :         }
     119             : 
     120          32 :         ODBC_FREE();
     121          32 : }
     122             : 
     123             : int
     124           8 : main(void)
     125             : {
     126             :         int i;
     127             : 
     128           8 :         odbc_use_version3 = 1;
     129           8 :         odbc_connect();
     130             : 
     131           8 :         odbc_command("CREATE TABLE #odbc_test(i INT, t TEXT)");
     132          88 :         for (i = 0; i < 10; ++i) {
     133             :                 char buf[128];
     134             : 
     135          80 :                 sprintf(buf, "INSERT INTO #odbc_test(i, t) VALUES(%d, '%crow number %d')", i + 1, 'a' + i, i * 13);
     136          80 :                 odbc_command(buf);
     137             :         }
     138             : 
     139           8 :         odbc_reset_statement();
     140             : 
     141           8 :         test_query = "SELECT * FROM #odbc_test ORDER BY i";
     142           8 :         printf("test line %d\n", __LINE__);
     143           8 :         query_test("S", "VVVVVVVVVV");
     144             : 
     145           8 :         test_query = "SELECT * FROM #odbc_test WHERE i < 7 ORDER BY i";
     146           8 :         printf("test line %d\n", __LINE__);
     147           8 :         query_test("S", "VVVVVV");
     148             : 
     149             :         /* binding row */
     150           8 :         test_query = "SELECT * FROM #odbc_test ORDER BY i";
     151           8 :         record_bind = 1;
     152           8 :         printf("test line %d\n", __LINE__);
     153           8 :         query_test("S", "VVVVVVVVVV");
     154             : 
     155             :         /* row and truncation */
     156           8 :         trunc = 1;
     157           8 :         printf("test line %d\n", __LINE__);
     158           8 :         query_test("I", "!!!!!!!!!!");
     159             : 
     160             :         /* TODO bind offset, SQLGetData, no bind, error */
     161             : 
     162           8 :         odbc_disconnect();
     163             : 
     164           8 :         printf("Success!.\n");
     165             :         return 0;
     166             : }

Generated by: LCOV version 1.13