LCOV - code coverage report
Current view: top level - src/odbc/unittests - data.c (source / functions) Hit Total Coverage
Test: FreeTDS coverage Lines: 86 101 85.1 %
Date: 2025-01-18 11:50:39 Functions: 3 4 75.0 %

          Line data    Source code
       1             : /*
       2             :  * Test reading data with SQLBindCol
       3             :  */
       4             : #include "common.h"
       5             : #include <assert.h>
       6             : #include <ctype.h>
       7             : #include "parser.h"
       8             : 
       9             : /*
      10             :  * This test is useful to test odbc_tds2sql function
      11             :  * odbc_tds2sql have some particular cases:
      12             :  * (1) numeric -> binary  numeric is different in ODBC
      13             :  * (2) *       -> binary  dependent from libTDS representation and ODBC one
      14             :  * (3) binary  -> char    TODO
      15             :  * (4) date    -> char    different format
      16             :  * Also we have to check normal char and wide char
      17             :  */
      18             : 
      19             : static int result = 0;
      20             : 
      21             : static int ignore_select_error = 0;
      22             : static int ignore_result = 0;
      23             : 
      24             : static void
      25         560 : Test(const char *type, const char *value_to_convert, SQLSMALLINT out_c_type, const char *expected)
      26             : {
      27             :         char sbuf[1024];
      28             :         unsigned char out_buf[256];
      29         560 :         SQLLEN out_len = 0;
      30             : 
      31         560 :         SQLFreeStmt(odbc_stmt, SQL_UNBIND);
      32         560 :         SQLFreeStmt(odbc_stmt, SQL_RESET_PARAMS);
      33             : 
      34             :         /* execute a select to get data as wire */
      35         560 :         sprintf(sbuf, "SELECT CONVERT(%s, '%s') AS data", type, value_to_convert);
      36         560 :         if (strncmp(value_to_convert, "0x", 2) == 0) {
      37          22 :                 if (odbc_db_is_microsoft())
      38          18 :                         sprintf(sbuf, "SELECT CONVERT(%s, %s) COLLATE Latin1_General_CI_AS AS data", type, value_to_convert);
      39             :                 else
      40           4 :                         sprintf(sbuf, "SELECT CONVERT(%s, %s)", type, value_to_convert);
      41         538 :         } else if (strcmp(type, "SQL_VARIANT") == 0)
      42          64 :                 sprintf(sbuf, "SELECT CONVERT(SQL_VARIANT, %s) AS data", value_to_convert);
      43         474 :         else if (strncmp(value_to_convert, "u&'", 3) == 0)
      44           8 :                 sprintf(sbuf, "SELECT CONVERT(%s, %s) AS data", type, value_to_convert);
      45         560 :         if (ignore_select_error) {
      46         560 :                 if (odbc_command2(sbuf, "SENo") == SQL_ERROR) {
      47          18 :                         odbc_reset_statement();
      48          18 :                         ignore_select_error = 0;
      49          18 :                         ignore_result = 0;
      50          18 :                         return;
      51             :                 }
      52             :         } else {
      53           0 :                 odbc_command(sbuf);
      54             :         }
      55         542 :         SQLBindCol(odbc_stmt, 1, out_c_type, out_buf, sizeof(out_buf), &out_len);
      56         542 :         CHKFetch("S");
      57         542 :         CHKFetch("No");
      58         542 :         CHKMoreResults("No");
      59             : 
      60             :         /* test results */
      61         542 :         odbc_c2string(sbuf, out_c_type, out_buf, out_len);
      62             : 
      63         542 :         if (!ignore_result && strcmp(sbuf, expected) != 0) {
      64           0 :                 fprintf(stderr, "Wrong result\n  Got:      %s\n  Expected: %s\n", sbuf, expected);
      65           0 :                 result = 1;
      66             :         }
      67         542 :         ignore_select_error = 0;
      68         542 :         ignore_result = 0;
      69             : }
      70             : 
      71             : static int
      72           0 : get_int(const char *s, odbc_parser *parser)
      73             : {
      74             :         char *end;
      75             :         long l;
      76             : 
      77           0 :         if (!s)
      78           0 :                 odbc_fatal(parser, ": NULL int\n");
      79           0 :         l = strtol(s, &end, 0);
      80           0 :         if (end[0])
      81           0 :                 odbc_fatal(parser, ": Invalid int\n");
      82           0 :         return (int) l;
      83             : }
      84             : 
      85             : static int
      86        1088 : lookup(const char *name, const struct odbc_lookup_int *table, odbc_parser *parser)
      87             : {
      88             :         int res;
      89             : 
      90        1088 :         if (!table)
      91           0 :                 return get_int(name, parser);
      92             : 
      93        1088 :         res = odbc_lookup(name, table, SQL_UNKNOWN_TYPE);
      94             : 
      95        1088 :         return res == SQL_UNKNOWN_TYPE ? get_int(name, parser) : res;
      96             : }
      97             : 
      98             : int
      99           8 : main(void)
     100             : {
     101           8 :         bool cond = true;
     102             : 
     103             : #define TEST_FILE "data.in"
     104           8 :         const char *in_file = FREETDS_SRCDIR "/" TEST_FILE;
     105             :         FILE *f;
     106             :         odbc_parser *parser;
     107             : 
     108           8 :         odbc_connect();
     109             : 
     110           8 :         f = fopen(in_file, "r");
     111           8 :         if (!f)
     112           0 :                 f = fopen(TEST_FILE, "r");
     113           8 :         if (!f) {
     114           0 :                 fprintf(stderr, "error opening test file\n");
     115           0 :                 exit(1);
     116             :         }
     117             : 
     118             :         /* cache version */
     119           8 :         odbc_tds_version();
     120             : 
     121           8 :         parser = odbc_init_parser(f);
     122        1168 :         for (;;) {
     123             :                 char *p;
     124        1176 :                 const char *cmd = odbc_get_cmd_line(parser, &p, &cond);
     125             : 
     126        1176 :                 if (!cmd)
     127             :                         break;
     128             : 
     129             :                 /* select type */
     130        1168 :                 if (!strcmp(cmd, "select")) {
     131        1056 :                         const char *type = odbc_get_str(parser, &p);
     132        1056 :                         const char *value = odbc_get_str(parser, &p);
     133        1056 :                         int c_type = lookup(odbc_get_tok(&p), odbc_sql_c_types, parser);
     134        1056 :                         const char *expected = odbc_get_str(parser, &p);
     135             : 
     136        2224 :                         if (!cond) continue;
     137             : 
     138         536 :                         ignore_select_error = 1;
     139         536 :                         Test(type, value, c_type, expected);
     140         536 :                         continue;
     141             :                 }
     142             :                 /* select type setting condition */
     143         112 :                 if (!strcmp(cmd, "select_cond")) {
     144          32 :                         const char *bool_name = odbc_get_tok(&p);
     145          32 :                         const char *type = odbc_get_tok(&p);
     146          32 :                         const char *value = odbc_get_str(parser, &p);
     147          32 :                         int c_type = lookup(odbc_get_tok(&p), odbc_sql_c_types, parser);
     148          32 :                         const char *expected = odbc_get_str(parser, &p);
     149          32 :                         int save_result = result;
     150             : 
     151          32 :                         if (!bool_name) odbc_fatal(parser, ": no condition name\n");
     152          32 :                         if (!cond) continue;
     153             : 
     154          24 :                         ignore_select_error = 1;
     155          24 :                         ignore_result = 1;
     156          24 :                         result = 0;
     157          24 :                         Test(type, value, c_type, expected);
     158          24 :                         odbc_set_bool(parser, bool_name, result == 0);
     159          24 :                         result = save_result;
     160          24 :                         continue;
     161             :                 }
     162             :                 /* execute a sql command */
     163          80 :                 if (!strcmp(cmd, "sql")) {
     164          24 :                         const char *sql = odbc_get_str(parser, &p);
     165             : 
     166          24 :                         if (!cond) continue;
     167             : 
     168          12 :                         odbc_command(sql);
     169          12 :                         continue;
     170             :                 }
     171          56 :                 if (!strcmp(cmd, "sql_cond")) {
     172          56 :                         const char *bool_name = odbc_get_tok(&p);
     173          56 :                         const char *sql = odbc_get_str(parser, &p);
     174             : 
     175          56 :                         if (!cond) continue;
     176             : 
     177          42 :                         odbc_set_bool(parser, bool_name, odbc_command2(sql, "SENo") != SQL_ERROR);
     178          42 :                         continue;
     179             :                 }
     180           0 :                 odbc_fatal(parser, ": unknown command\n");
     181             :         }
     182           8 :         odbc_free_parser(parser);
     183           8 :         fclose(f);
     184             : 
     185           8 :         printf("\n");
     186             : 
     187           8 :         odbc_disconnect();
     188             : 
     189           8 :         if (!result)
     190           8 :                 printf("Done successfully!\n");
     191           8 :         return result;
     192             : }

Generated by: LCOV version 1.13