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

Generated by: LCOV version 1.13