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]>
With this other example (using SQL_CHAR / SQL_VARCHAR), I get this error:

Error -1 at: SQLExecute 1.1 StmtH
Diagnostic info:
   SQL State: 42000
   SQL code : 8005
   Message  : [FreeTDS][SQL Server]The incoming tabular data stream (TDS) remote procedure call (RPC) protocol stream is incorrect. Parameter 4: The 
parameter name is invalid.


I think in a UTF-8 context it makes sense to bind with SQL_CHAR/SQL_VARCHAR
for the ParameterType argument (#5) of SQLBindParameter, and passing a number
of bytes in the ColumnSize (#6) and StrLen_or_IndPtr (#10) arguments...

?

Seb

_______________________________________________
FreeTDS mailing list
[email protected]
http://lists.ibiblio.org/mailman/listinfo/freetds
odbctest11.c (text/plain, 6 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_CHAR, 40, 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_VARCHAR, 40, 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 1.1 StmtH");

    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 1.2 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.