Re: Status of UTF-8 support in 0.83 dev

Sebastien FLAESCH <[email protected]>
Newsgroups gmane.comp.db.tds.freetds
Organization Four J's Development Tools
Message-ID <[email protected]>
Sorry I mean SQL_WVARCHAR, not SQL_NVARCHAR...

I made a little UTF-8 test (see attachment *warning*: UTF-8 file!).

Simple SQL statements without SQL parameters seem to work... (CREATE TABLE, INSERT).
But some characters are not converted properly (iconv issue?):
The 'abcéáô' and 'abcéîô' strings become 'abceao' and 'abceio' in the database...

Further, I can't execute an INSERT with SQLBindParameter():

When using SQL_WVARCHAR, I get an error but diagnostic info shows unreadable strings:

Error -1 at: SQLExecute StmtH
Diagnostic info:
   SQL State: \uffff\uffffu
   SQL code : 0
   Message  :

With SQL_VARCHAR, I get this:

Error -1 at: SQLExecute StmtH
Diagnostic info:
   SQL State: 42000
   SQL code : 4002
   Message  : [FreeTDS][SQL Server]The incoming tabular data stream (TDS) protocol stream is incorrect. The stream ended unexpectedly.


Seb

Sebastien FLAESCH wrote:
> Hi all,
> 
> I would like to start some tests using ODBC in a UTF-8 environment.
> 
> What is the current status of this project?
> 
> I found this in the TODO file:
> 
> . conversion from ucs2 to utf8, provide for 2+ bytes/character
> 
> I have set ClientCharset = UTF8 in the odbc.ini file...
> 
> What SQL_* types should I use to bind buffers with SQLBindParameter
> or SQLBindCol, when using UTF8 charset?
> 
> For example, would this be ok?
> 
>      char v_char[41];   /* Can hold up to 10 UTF-8 characters */
> 
>      SQLBindParameter(m_hstmt1, 2, SQL_PARAM_INPUT,
>                       SQL_C_CHAR,
>                       SQL_NVARCHAR, 10, 0, v_char, 0,
>                       &v_ind_char);
> 
> Assuming that I use a NVARCHAR(10) in the db?
> 
> Thanks!
> Seb
> _______________________________________________
> FreeTDS mailing list
> [email protected]
> http://lists.ibiblio.org/mailman/listinfo/freetds
>

_______________________________________________
FreeTDS mailing list
[email protected]
http://lists.ibiblio.org/mailman/listinfo/freetds
odbctest11.c (text/plain, 5.8 KB)
/* Test UTF-8 character set
 * Author: Sebastien FLAESCH
 *
 * The ODBC config parameter ClientCharset must be set:
 *   ClientCharset = UTF8
 */

static const char * g_dbname = "freetds_msvtest2_cobra";
static const char * g_usernm = "msvuser";
static const char * g_passwd = "fourjs";

#ifdef _WIN32
#include <WINDOWS.H>
#endif
#include <stdio.h>
#include <sql.h>
#include <sqlext.h>

#define CHECK_RCODE(t,h,m) \
   if ( rcode != SQL_NO_DATA \
     && rcode != SQL_SUCCESS \
     && rcode != SQL_SUCCESS_WITH_INFO  \
     && rcode != SQL_NEED_DATA ) { \
      fprintf(stderr,"Error %d at: %s\n",rcode,m); \
      getErrorInfo(t,h); \
      exit(1); \
   }

static int v_key;
static SQLINTEGER v_ind_key;

static char v_char[41];           /* Can hold 10 UTF-8 chars */
static SQLINTEGER v_ind_char;

static char v_varchar[41];        /* Can hold 10 UTF-8 chars */
static SQLINTEGER v_ind_varchar;

static void getErrorInfo(SQLSMALLINT sqlhdltype, SQLHANDLE sqlhandle)
{
    SQLRETURN rcode = 0;
    SQLCHAR sqlstate[SQL_SQLSTATE_SIZE + 1];
    SQLINTEGER naterror = 0;
    SQLCHAR msgtext[SQL_MAX_MESSAGE_LENGTH + 1];
    SQLSMALLINT msgtextl = 0;
    int ifxerror = 0;
    rcode = SQLGetDiagRec((SQLSMALLINT) sqlhdltype,
                          (SQLHANDLE) sqlhandle,
                          (SQLSMALLINT) 1,
                          (SQLCHAR *) sqlstate,
                          (SQLINTEGER *) & naterror,
                          (SQLCHAR *) msgtext,
                          (SQLSMALLINT) sizeof(msgtext),
                          (SQLSMALLINT *) & msgtextl);
    fprintf(stderr, "Diagnostic info:\n");
    fprintf(stderr, "  SQL State: %s\n", (char *) sqlstate);
    fprintf(stderr, "  SQL code : %d\n", (int) naterror);
    fprintf(stderr, "  Message  : %s\n", (char *) msgtext);
}

main(int argc,char **argv)
{
    SQLRETURN rcode;
    SQLHENV m_henv;
    SQLHDBC m_hdbc;
    SQLHSTMT m_hstmt1;
    int i,j;
    const char * dbname;
    const char * usernm;
    const char * passwd;

    if (argc == 4) {
       dbname = argv[1];
       usernm = argv[2];
       passwd = argv[3];
    } else {
       dbname = g_dbname;
       usernm = g_usernm;
       passwd = g_passwd;
    }

    m_henv = NULL;
    rcode = SQLAllocHandle(SQL_HANDLE_ENV, SQL_NULL_HANDLE, &m_henv);
    CHECK_RCODE(SQL_HANDLE_ENV,NULL,"SQLAllocHandle EnvH");

    rcode = SQLSetEnvAttr(m_henv, SQL_ATTR_ODBC_VERSION, (SQLPOINTER) SQL_OV_ODBC3, SQL_IS_UINTEGER);
    CHECK_RCODE(SQL_HANDLE_ENV,m_henv,"ODBC V3");

    m_hdbc = NULL;
    rcode = SQLAllocHandle(SQL_HANDLE_DBC, (SQLHANDLE) m_henv, (SQLHANDLE *) &m_hdbc);
    CHECK_RCODE(SQL_HANDLE_ENV,m_henv,"SQLAllocHandle DbcH");

    rcode = SQLConnect((SQLHANDLE) m_hdbc,
                       (SQLCHAR *) dbname,
                       (SQLINTEGER) SQL_NTS,
                       (SQLCHAR *) usernm,
                       (SQLINTEGER) SQL_NTS,
                       (SQLCHAR *) passwd,
                       (SQLINTEGER) SQL_NTS);
    CHECK_RCODE(SQL_HANDLE_DBC,m_hdbc,"SQLConnect");

    rcode = SQLSetConnectAttr(m_hdbc,
               SQL_ATTR_AUTOCOMMIT, (SQLPOINTER) SQL_AUTOCOMMIT_ON, SQL_IS_UINTEGER);
    CHECK_RCODE(SQL_HANDLE_ENV,m_henv,"SQLSetConnectAttr(autocommit)");

    m_hstmt1 = NULL;
    rcode = SQLAllocHandle(SQL_HANDLE_STMT, m_hdbc, &m_hstmt1);
    CHECK_RCODE(SQL_HANDLE_DBC,m_hdbc,"SQLAllocHandle StmtH 1");

    rcode = SQLExecDirect(m_hstmt1, (SQLCHAR *) "drop table mytab王鴻", SQL_NTS);
    rcode = SQLExecDirect(m_hstmt1, (SQLCHAR *) "create table mytab王鴻 (k int, c nchar(10), vc nvarchar(10))", SQL_NTS);
    CHECK_RCODE(SQL_HANDLE_STMT,m_hstmt1,"SQLExecDirect 1.1");

    rcode = SQLExecDirect(m_hstmt1, (SQLCHAR *) "insert into mytab王鴻 values (1,'aaa','aaa')", SQL_NTS);
    CHECK_RCODE(SQL_HANDLE_STMT,m_hstmt1,"SQLExecDirect 1.2");
    rcode = SQLExecDirect(m_hstmt1, (SQLCHAR *) "insert into mytab王鴻 values (2,'abcéáô','abcéîô')", SQL_NTS);
    CHECK_RCODE(SQL_HANDLE_STMT,m_hstmt1,"SQLExecDirect 1.3");
    rcode = SQLExecDirect(m_hstmt1, (SQLCHAR *) "insert into mytab王鴻 values (3,'abc王鴻','abc王鴻傑王鴻傑')", SQL_NTS);
    CHECK_RCODE(SQL_HANDLE_STMT,m_hstmt1,"SQLExecDirect 1.4");

    /* Now with SQL parameters */
    rcode = SQLPrepare(m_hstmt1, (SQLCHAR *) "insert into mytab王鴻 values (?,?,?)", SQL_NTS);
    CHECK_RCODE(SQL_HANDLE_STMT,m_hstmt1,"SQLPrepare 1");

    SQLBindParameter(m_hstmt1, 1, SQL_PARAM_INPUT,
                     SQL_C_LONG,
                     SQL_INTEGER, 0, 0, &v_key, 0,
                     &v_ind_key);
    CHECK_RCODE(SQL_HANDLE_STMT,m_hstmt1,"SQLBindParameter 1");

    SQLBindParameter(m_hstmt1, 2, SQL_PARAM_INPUT,
                     SQL_C_CHAR,
                     SQL_WCHAR, 10, 0, v_char, 0,
                     &v_ind_char);
    CHECK_RCODE(SQL_HANDLE_STMT,m_hstmt1,"SQLBindParameter 2");

    SQLBindParameter(m_hstmt1, 3, SQL_PARAM_INPUT,
                     SQL_C_CHAR,
                     SQL_WVARCHAR, 10, 0, v_varchar, 0,
                     &v_ind_varchar);
    CHECK_RCODE(SQL_HANDLE_STMT,m_hstmt1,"SQLBindParameter 3");

    /* Assign UTF-8 values using SBCS functions, sorry */
    strcpy(v_char, "abc王鴻" );
    v_ind_char = strlen(v_char);
    strcpy(v_varchar, "abc王鴻傑王鴻傑" ); 
    v_ind_varchar = strlen(v_varchar);

    rcode = SQLExecute(m_hstmt1);
    CHECK_RCODE(SQL_HANDLE_STMT,m_hstmt1,"SQLExecute StmtH");

    rcode = SQLFreeHandle(SQL_HANDLE_STMT, (SQLHANDLE) m_hstmt1);
    CHECK_RCODE(SQL_HANDLE_STMT,m_hstmt1,"SQLFreeHandle StmtH 1");

    rcode = SQLDisconnect(m_hdbc);
    CHECK_RCODE(SQL_HANDLE_DBC,m_hdbc,"SQLDisconnect");

    rcode = SQLFreeHandle(SQL_HANDLE_DBC, (SQLHANDLE) m_hdbc);
    CHECK_RCODE(SQL_HANDLE_DBC,m_hdbc,"SQLFreeHandle DbcH");

    rcode = SQLFreeHandle(SQL_HANDLE_ENV, (SQLHANDLE) m_henv);
    CHECK_RCODE(SQL_HANDLE_ENV,m_henv,"SQLFreeHandle EnvH");

}
lmpx.com only provides a reader for public news (NNTP) servers. It is not affiliated with the servers or forums shown here and is not responsible for the content of articles, which is written by their respective authors.