LCOV - code coverage report
Current view: top level - src/odbc/unittests - utf8.c (source / functions) Hit Total Coverage
Test: FreeTDS coverage Lines: 48 53 90.6 %
Date: 2024-03-23 08:24:27 Functions: 2 2 100.0 %

          Line data    Source code
       1             : #include "common.h"
       2             : 
       3             : /* test binding with UTF-8 encoding */
       4             : 
       5             : #ifndef _WIN32
       6             : /* test table name, it contains two japanese characters */
       7             : static const char table_name[] = "mytab\xe7\x8e\x8b\xe9\xb4\xbb";
       8             : 
       9             : static const char * const strings[] = {
      10             :         /* ascii */
      11             :         "aaa", "aaa",
      12             :         /* latin 1*/
      13             :         "abc\xc3\xa9\xc3\xa1\xc3\xb4", "abc\xc3\xa9\xc3\xae\xc3\xb4",
      14             :         /* Japanese... */
      15             :         "abc\xe7\x8e\x8b\xe9\xb4\xbb", "abc\xe7\x8e\x8b\xe9\xb4\xbb\xe5\x82\x91\xe7\x8e\x8b\xe9\xb4\xbb\xe5\x82\x91",
      16             :         NULL, NULL
      17             : };
      18             : 
      19             : /* same strings in hex */
      20             : static const char * const strings_hex[] = {
      21             :         /* ascii */
      22             :         "0x610061006100", "0x610061006100",
      23             :         /* latin 1*/
      24             :         "0x610062006300e900e100f400", "0x610062006300e900ee00f400",
      25             :         /* Japanese... */
      26             :         "0x6100620063008b733b9d", "0x6100620063008b733b9d91508b733b9d9150",
      27             :         NULL, NULL
      28             : };
      29             : 
      30             : static char tmp[1024*3];
      31             : 
      32             : static void
      33          12 : TestBinding(int minimun)
      34             : {
      35             :         const char * const*p;
      36             :         SQLINTEGER n;
      37             :         SQLLEN n_len;
      38             : 
      39          12 :         sprintf(tmp, "DELETE FROM %s", table_name);
      40          12 :         odbc_command(tmp);
      41             : 
      42             :         /* insert with SQLPrepare/SQLBindParameter/SQLExecute */
      43          12 :         sprintf(tmp, "INSERT INTO %s VALUES(?,?,?)", table_name);
      44          12 :         CHKPrepare(T(tmp), SQL_NTS, "S");
      45          12 :         CHKBindParameter(1, SQL_PARAM_INPUT, SQL_C_LONG,
      46             :                 SQL_INTEGER, 0, 0, &n, 0, &n_len, "S");
      47          12 :         n_len = sizeof(n);
      48             :         
      49          48 :         for (n = 1, p = strings; p[0] && p[1]; p += 2, ++n) {
      50             :                 SQLLEN s1_len, s2_len;
      51             :                 unsigned int len;
      52             : 
      53          36 :                 len = minimun ? (strlen(strings_hex[p-strings]) - 2) /4 : 40;
      54          36 :                 CHKBindParameter(2, SQL_PARAM_INPUT, SQL_C_CHAR,
      55             :                         SQL_WCHAR, len, 0, (void *) p[0], 0, &s1_len, "S");
      56          36 :                 len = minimun ? (strlen(strings_hex[p+1-strings]) - 2) /4 : 40;
      57             :                 /* FIXME this with SQL_VARCHAR produce wrong protocol data */
      58          36 :                 CHKBindParameter(3, SQL_PARAM_INPUT, SQL_C_CHAR,
      59             :                         SQL_WVARCHAR, len, 0, (void *) p[1], 0, &s2_len, "S");
      60          36 :                 s1_len = strlen(p[0]);
      61          36 :                 s2_len = strlen(p[1]);
      62          36 :                 printf("insert #%d\n", (int) n);
      63          36 :                 CHKExecute("S");
      64             :         }
      65             : 
      66             :         /* check rows */
      67          48 :         for (n = 1, p = strings_hex; p[0] && p[1]; p += 2, ++n) {
      68          36 :                 sprintf(tmp, "IF NOT EXISTS(SELECT * FROM %s WHERE k = %d AND c = %s AND vc = %s) SELECT 1", table_name, (int) n, p[0], p[1]);
      69          36 :                 odbc_check_no_row(tmp);
      70             :         }
      71             : 
      72          12 :         odbc_reset_statement();
      73          12 : }
      74             : 
      75             : int
      76           8 : main(void)
      77             : {
      78             :         const char * const*p;
      79             :         SQLINTEGER n;
      80             : 
      81           8 :         odbc_use_version3 = 1;
      82           8 :         odbc_conn_additional_params = "ClientCharset=UTF-8;";
      83             : 
      84           8 :         odbc_connect();
      85           8 :         if (!odbc_driver_is_freetds()) {
      86           0 :                 odbc_disconnect();
      87           0 :                 printf("Driver is not FreeTDS, exiting\n");
      88           0 :                 odbc_test_skipped();
      89           0 :                 return 0;
      90             :         }
      91             : 
      92           8 :         if (!odbc_db_is_microsoft() || odbc_db_version_int() < 0x08000000u) {
      93           2 :                 odbc_disconnect();
      94           2 :                 printf("Test for MSSQL only\n");
      95           2 :                 odbc_test_skipped();
      96           0 :                 return 0;
      97             :         }
      98             : 
      99           6 :         CHKAllocStmt(&odbc_stmt, "S");
     100             : 
     101             :         /* create test table */
     102           6 :         sprintf(tmp, "IF OBJECT_ID(N'%s') IS NOT NULL DROP TABLE %s", table_name, table_name);
     103           6 :         odbc_command(tmp);
     104           6 :         sprintf(tmp, "CREATE TABLE %s (k int, c NCHAR(10), vc NVARCHAR(10))", table_name);
     105           6 :         odbc_command(tmp);
     106             : 
     107             :         /* insert with INSERT statements */
     108          24 :         for (n = 1, p = strings; p[0] && p[1]; p += 2, ++n) {
     109          18 :                 sprintf(tmp, "INSERT INTO %s VALUES (%d,N'%s',N'%s')", table_name, (int) n, p[0], p[1]);
     110          18 :                 odbc_command(tmp);
     111             :         }
     112             : 
     113             :         /* check rows */
     114          18 :         for (n = 1, p = strings_hex; p[0] && p[1]; p += 2, ++n) {
     115          18 :                 sprintf(tmp, "IF NOT EXISTS(SELECT * FROM %s WHERE k = %d AND c = %s AND vc = %s) SELECT 1", table_name, (int) n, p[0], p[1]);
     116          18 :                 odbc_check_no_row(tmp);
     117             :         }
     118             : 
     119           6 :         TestBinding(0);
     120             : 
     121           6 :         TestBinding(1);
     122             : 
     123             :         /* cleanup */
     124           6 :         sprintf(tmp, "IF OBJECT_ID(N'%s') IS NOT NULL DROP TABLE %s", table_name, table_name);
     125           6 :         odbc_command(tmp);
     126             : 
     127           6 :         odbc_disconnect();
     128           6 :         printf("Done.\n");
     129           6 :         return 0;
     130             : }
     131             : 
     132             : #else
     133             : 
     134             : int
     135             : main(void)
     136             : {
     137             :         /* on Windows SQLExecDirect is always converted to SQLExecDirectW by the DM */
     138             :         printf("Not possible for this platform.\n");
     139             :         odbc_test_skipped();
     140             :         return 0;
     141             : }
     142             : #endif

Generated by: LCOV version 1.13