LCOV - code coverage report
Current view: top level - src/odbc/unittests - getdata.c (source / functions) Hit Total Coverage
Test: FreeTDS coverage Lines: 162 195 83.1 %
Date: 2025-07-02 09:40:27 Functions: 4 4 100.0 %

          Line data    Source code
       1             : /*
       2             :  * Test reading data with SQLGetData
       3             :  */
       4             : #include "common.h"
       5             : #include <assert.h>
       6             : 
       7             : static void
       8          50 : test_err(const char *data, int c_type, const char *state)
       9             : {
      10             :         char sql[128];
      11             :         SQLLEN ind;
      12          50 :         const unsigned int buf_size = 128;
      13          50 :         char *buf = (char *) malloc(buf_size);
      14             : 
      15          50 :         sprintf(sql, "SELECT '%s'", data);
      16          50 :         odbc_command(sql);
      17          50 :         SQLFetch(odbc_stmt);
      18          50 :         CHKGetData(1, c_type, buf, buf_size, &ind, "E");
      19          50 :         free(buf);
      20          50 :         odbc_read_error();
      21          50 :         if (strcmp(odbc_sqlstate, state) != 0) {
      22           0 :                 fprintf(stderr, "Unexpected sql state returned\n");
      23           0 :                 odbc_disconnect();
      24           0 :                 exit(1);
      25             :         }
      26          50 :         odbc_reset_statement();
      27          50 : }
      28             : 
      29             : static int lc;
      30             : static int type;
      31             : 
      32             : static int
      33         144 : mycmp(const char *s1, const char *s2)
      34             : {
      35             :         SQLWCHAR buf[128], *wp;
      36             :         size_t l;
      37             : 
      38         144 :         if (type == SQL_C_CHAR)
      39          72 :                 return strcmp(s1, s2);
      40             : 
      41          72 :         l = strlen(s2);
      42          72 :         assert(l < TDS_VECTOR_SIZE(buf));
      43             :         wp = buf;
      44             :         do {
      45         558 :                 *wp++ = *s2;
      46         558 :         } while (*s2++);
      47             : 
      48          72 :         return memcmp(s1, buf, l * lc + lc);
      49             : }
      50             : 
      51             : static void
      52          36 : test_split(const char *n_flag)
      53             : {
      54             : #define CheckLen(x) do { \
      55             :         if (len != (x)) { \
      56             :                 fprintf(stderr, "Wrong len %ld at line %d expected %d\n", (long int) len, __LINE__, (x)); \
      57             :                 exit(1); \
      58             :         } \
      59             :         } while(0)
      60             : 
      61             :         char *sql;
      62          36 :         char *buf = NULL;
      63          36 :         const char *collate = "";
      64             :         SQLLEN len;
      65             : 
      66             :         /* TODO test with VARCHAR too */
      67          36 :         if (odbc_db_is_microsoft())
      68          32 :                 collate = " COLLATE Latin1_General_CI_AS";
      69          36 :         sql = odbc_buf_asprintf(&odbc_buf, "SELECT CONVERT(%sTEXT,'Prova'%s + REPLICATE('x',500))%s", n_flag, collate, collate);
      70          36 :         odbc_command(sql);
      71             : 
      72          36 :         CHKFetch("S");
      73             : 
      74             :         /* these 2 tests test an old severe BUG in FreeTDS */
      75          36 :         buf = (char *) ODBC_GET(1);
      76          36 :         CHKGetData(1, type, buf, 0, &len, "I");
      77          36 :         if (len != SQL_NO_TOTAL)
      78          18 :                 CheckLen(505*lc);
      79          36 :         CHKGetData(1, type, buf, 0, &len, "I");
      80          36 :         if (len != SQL_NO_TOTAL)
      81          18 :                 CheckLen(505*lc);
      82          36 :         buf = (char *) ODBC_GET(3*lc);
      83          36 :         CHKGetData(1, type, buf, 3 * lc, &len, "I");
      84          36 :         if (len != SQL_NO_TOTAL)
      85          18 :                 CheckLen(505*lc);
      86          36 :         if (mycmp(buf, "Pr") != 0) {
      87           0 :                 printf("Wrong data result 1\n");
      88           0 :                 exit(1);
      89             :         }
      90             : 
      91          36 :         buf = (char *) ODBC_GET(16*lc);
      92          36 :         CHKGetData(1, type, buf, 16 * lc, &len, "I");
      93          36 :         if (len != SQL_NO_TOTAL)
      94          18 :                 CheckLen(503*lc);
      95          36 :         if (mycmp(buf, "ovaxxxxxxxxxxxx") != 0) {
      96           0 :                 printf("Wrong data result 2 res = '%s'\n", buf);
      97           0 :                 exit(1);
      98             :         }
      99             : 
     100          36 :         buf = (char *) ODBC_GET(256*lc);
     101          36 :         CHKGetData(1, type, buf, 256 * lc, &len, "I");
     102          36 :         if (len != SQL_NO_TOTAL)
     103          18 :                 CheckLen(488*lc);
     104          36 :         CHKGetData(1, type, buf, 256 * lc, &len, "S");
     105          36 :         CheckLen(233*lc);
     106          36 :         CHKGetData(1, type, buf, 256 * lc, &len, "No");
     107             : 
     108          36 :         odbc_reset_statement();
     109             : 
     110             :         /* test with varchar, not blob but variable */
     111          36 :         sql = odbc_buf_asprintf(&odbc_buf, "SELECT CONVERT(%sVARCHAR(100), 'Other test')", n_flag);
     112          36 :         odbc_command(sql);
     113             : 
     114          36 :         CHKFetch("S");
     115             : 
     116          36 :         buf = (char *) ODBC_GET(7*lc);
     117          36 :         CHKGetData(1, type, buf, 7 * lc, NULL, "I");
     118          36 :         if (mycmp(buf, "Other ") != 0) {
     119           0 :                 printf("Wrong data result 1\n");
     120           0 :                 exit(1);
     121             :         }
     122             : 
     123          36 :         buf = (char *) ODBC_GET(5*lc);
     124          36 :         CHKGetData(1, type, buf, 20, NULL, "S");
     125          36 :         if (mycmp(buf, "test") != 0) {
     126           0 :                 printf("Wrong data result 2 res = '%s'\n", buf);
     127           0 :                 exit(1);
     128             :         }
     129          36 :         ODBC_FREE();
     130             : 
     131          36 :         odbc_reset_statement();
     132          36 : }
     133             : 
     134          10 : TEST_MAIN()
     135             : {
     136             :         char buf[32];
     137             :         SQLINTEGER int_buf;
     138             :         SQLLEN len;
     139             :         SQLRETURN rc;
     140             :         TIMESTAMP_STRUCT tss;
     141             : 
     142          10 :         odbc_connect();
     143             : 
     144          10 :         lc = 1;
     145          10 :         type = SQL_C_CHAR;
     146          10 :         test_split("");
     147             : 
     148          10 :         lc = sizeof(SQLWCHAR);
     149          10 :         type = SQL_C_WCHAR;
     150          10 :         test_split("");
     151             : 
     152          10 :         if (odbc_db_is_microsoft() && odbc_db_version_int() >= 0x07000000u) {
     153           8 :                 lc = 1;
     154           8 :                 type = SQL_C_CHAR;
     155           8 :                 test_split("N");
     156             : 
     157           8 :                 lc = sizeof(SQLWCHAR);
     158           8 :                 type = SQL_C_WCHAR;
     159           8 :                 test_split("N");
     160             :         }
     161             : 
     162             :         /* test with fixed length */
     163          10 :         odbc_command("SELECT CONVERT(INT, 12345)");
     164             : 
     165          10 :         CHKFetch("S");
     166             : 
     167          10 :         int_buf = 0xdeadbeef;
     168          10 :         CHKGetData(1, SQL_C_SLONG, &int_buf, 0, NULL, "S");
     169          10 :         if (int_buf != 12345) {
     170           0 :                 printf("Wrong data result\n");
     171           0 :                 exit(1);
     172             :         }
     173             : 
     174          10 :         CHKGetData(1, SQL_C_SLONG, &int_buf, 0, NULL, "No");
     175          10 :         if (int_buf != 12345) {
     176           0 :                 printf("Wrong data result 2 res = %d\n", (int) int_buf);
     177           0 :                 exit(1);
     178             :         }
     179             : 
     180          10 :         odbc_reset_statement();
     181             : 
     182             :         /* test with numeric */
     183          10 :         odbc_command("SELECT CONVERT(NUMERIC(18,5), 1850000000000)");
     184             : 
     185          10 :         CHKFetch("S");
     186             : 
     187          10 :         memset(buf, 'x', sizeof(buf));
     188          10 :         CHKGetData(1, SQL_C_CHAR, buf, 14, NULL, "S");
     189          10 :         buf[sizeof(buf)-1] = 0;
     190          10 :         if (strcmp(buf, "1850000000000") != 0) {
     191           0 :                 printf("Wrong data result: %s\n", buf);
     192           0 :                 exit(1);
     193             :         }
     194             : 
     195             :         /* should give NO DATA */
     196          10 :         CHKGetData(1, SQL_C_CHAR, buf, 14, NULL, "No");
     197          10 :         buf[sizeof(buf)-1] = 0;
     198          10 :         if (strcmp(buf, "1850000000000") != 0) {
     199           0 :                 printf("Wrong data result 3 res = %s\n", buf);
     200           0 :                 exit(1);
     201             :         }
     202             : 
     203          10 :         odbc_reset_statement();
     204             : 
     205             : 
     206             :         /* test int to truncated string */
     207          10 :         odbc_command("SELECT CONVERT(INTEGER, 12345)");
     208          10 :         CHKFetch("S");
     209             : 
     210             :         /* error 22003 */
     211          10 :         memset(buf, 'x', sizeof(buf));
     212          10 :         CHKGetData(1, SQL_C_CHAR, buf, 4, NULL, "E");
     213             : #ifdef ENABLE_DEVELOPING
     214             :         buf[4] = 0;
     215             :         if (strcmp(buf, "xxxx") != 0) {
     216             :                 fprintf(stderr, "Wrong buffer result buf = %s\n", buf);
     217             :                 exit(1);
     218             :         }
     219             : #endif
     220          10 :         odbc_read_error();
     221          10 :         if (strcmp(odbc_sqlstate, "22003") != 0) {
     222           0 :                 fprintf(stderr, "Unexpected sql state %s returned\n", odbc_sqlstate);
     223           0 :                 odbc_disconnect();
     224           0 :                 exit(1);
     225             :         }
     226          10 :         CHKGetData(1, SQL_C_CHAR, buf, 2, NULL, "No");
     227          10 :         odbc_reset_statement();
     228             : 
     229             :         /* test unique identifier to truncated string */
     230          10 :         rc = odbc_command2("SELECT CONVERT(UNIQUEIDENTIFIER, 'AA7DF450-F119-11CD-8465-00AA00425D90')", "SENo");
     231          10 :         if (rc != SQL_ERROR) {
     232           8 :                 CHKFetch("S");
     233             : 
     234             :                 /* error 22003 */
     235           8 :                 CHKGetData(1, SQL_C_CHAR, buf, 17, NULL, "E");
     236           8 :                 odbc_read_error();
     237           8 :                 if (strcmp(odbc_sqlstate, "22003") != 0) {
     238           0 :                         fprintf(stderr, "Unexpected sql state %s returned\n", odbc_sqlstate);
     239           0 :                         odbc_disconnect();
     240           0 :                         exit(1);
     241             :                 }
     242           8 :                 CHKGetData(1, SQL_C_CHAR, buf, 2, NULL, "No");
     243             :         }
     244          10 :         odbc_reset_statement();
     245             : 
     246             : 
     247          10 :         odbc_disconnect();
     248             : 
     249          10 :         odbc_use_version3 = 1;
     250          10 :         odbc_connect();
     251             : 
     252             :         /* test error from SQLGetData */
     253             :         /* wrong constant, SQL_VARCHAR is invalid as C type */
     254          10 :         test_err("prova 123",           SQL_VARCHAR,     "HY003");
     255             :         /* use ARD but no ARD data column */
     256          10 :         test_err("prova 123",           SQL_ARD_TYPE,    "07009");
     257             :         /* wrong conversion, int */
     258          10 :         test_err("prova 123",           SQL_C_LONG,      "22018");
     259             :         /* wrong conversion, date */
     260          10 :         test_err("prova 123",           SQL_C_TIMESTAMP, "22018");
     261             :         /* overflow */
     262          10 :         test_err("1234567890123456789", SQL_C_LONG,      "22003");
     263             : 
     264             :         /* test datetime precision */
     265          10 :         odbc_command("SELECT CONVERT(DATETIME, '2018-08-15 12:34:56.007')");
     266             : 
     267          10 :         CHKFetch("S");
     268             : 
     269          10 :         memset(&tss, 'x', sizeof(tss));
     270          10 :         CHKGetData(1, SQL_C_TYPE_TIMESTAMP, &tss, sizeof(tss), NULL, "S");
     271          10 :         if (tss.fraction != 7000000) {
     272           0 :                 printf("Wrong data result: %lu\n", (unsigned long) tss.fraction);
     273           0 :                 exit(1);
     274             :         }
     275             : 
     276          10 :         odbc_reset_statement();
     277             : 
     278             :         /* test for empty string from mssql */
     279          10 :         if (odbc_db_is_microsoft()) {
     280           8 :                 lc = 1;
     281           8 :                 type = SQL_C_CHAR;
     282             : 
     283           8 :                 for (;;) {
     284          16 :                         void *buf = ODBC_GET(lc);
     285             : 
     286          16 :                         odbc_command("SELECT CONVERT(TEXT,'' COLLATE Latin1_General_CI_AS)");
     287             : 
     288          16 :                         CHKFetch("S");
     289             : 
     290          16 :                         len = 1234;
     291          16 :                         CHKGetData(1, type, buf, lc, &len, "S");
     292             : 
     293          16 :                         if (len != 0) {
     294           0 :                                 fprintf(stderr, "Wrong len returned, returned %ld\n", (long) len);
     295           0 :                                 return 1;
     296             :                         }
     297             : 
     298          16 :                         CHKGetData(1, type, buf, lc, NULL, "No");
     299          16 :                         odbc_reset_statement();
     300          16 :                         ODBC_FREE();
     301             : 
     302          16 :                         buf = ODBC_GET(4096*lc);
     303             : 
     304          16 :                         odbc_command("SELECT CONVERT(TEXT,'' COLLATE Latin1_General_CI_AS)");
     305             : 
     306          16 :                         CHKFetch("S");
     307             : 
     308          16 :                         len = 1234;
     309          16 :                         CHKGetData(1, type, buf, lc*4096, &len, "S");
     310             : 
     311          16 :                         if (len != 0) {
     312           0 :                                 fprintf(stderr, "Wrong len returned, returned %ld\n", (long) len);
     313           0 :                                 return 1;
     314             :                         }
     315             : 
     316          16 :                         CHKGetData(1, type, buf, lc*4096, NULL, "No");
     317          16 :                         odbc_reset_statement();
     318          16 :                         ODBC_FREE();
     319             : 
     320          16 :                         if (type != SQL_C_CHAR)
     321             :                                 break;
     322           8 :                         lc = sizeof(SQLWCHAR);
     323           8 :                         type = SQL_C_WCHAR;
     324             :                 }       
     325             : 
     326           8 :                 odbc_command("SELECT CONVERT(TEXT,'' COLLATE Latin1_General_CI_AS)");
     327             : 
     328           8 :                 CHKFetch("S");
     329             : 
     330           8 :                 len = 1234;
     331           8 :                 CHKGetData(1, SQL_C_BINARY, buf, 1, &len, "S");
     332             : 
     333           8 :                 if (len != 0) {
     334           0 :                         fprintf(stderr, "Wrong len returned, returned %ld\n", (long) len);
     335           0 :                         return 1;
     336             :                 }
     337             : 
     338           8 :                 CHKGetData(1, SQL_C_BINARY, buf, 1, NULL, "No");
     339             :         }
     340             : 
     341          10 :         odbc_disconnect();
     342             : 
     343          10 :         printf("Done.\n");
     344          10 :         return 0;
     345             : }

Generated by: LCOV version 1.13