LCOV - code coverage report
Current view: top level - src/odbc/unittests - utf8.c (source / functions) Hit Total Coverage
Test: FreeTDS coverage Lines: 47 50 94.0 %
Date: 2026-03-24 22:22:09 Functions: 2 2 100.0 %

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

Generated by: LCOV version 1.13