List:Commits« Previous MessageNext Message »
From:jwinstead Date:August 21 2007 11:46pm
Subject:Connector/ODBC 3.51 commit: r674 - in branches/guffert: driver test test/include
View as plain text  
Modified:
   branches/guffert/driver/ansi.c
   branches/guffert/driver/cursor.c
   branches/guffert/driver/driver.h
   branches/guffert/driver/unicode.c
   branches/guffert/test/include/mytest3.h
   branches/guffert/test/my_cursor.c
   branches/guffert/test/my_unicode.c
Log:
Implement SQLGetCursorNameW()


Modified: branches/guffert/driver/ansi.c
===================================================================
--- branches/guffert/driver/ansi.c	2007-08-21 18:41:44 UTC (rev 673)
+++ branches/guffert/driver/ansi.c	2007-08-21 23:46:30 UTC (rev 674)
@@ -148,6 +148,54 @@
 
 
 SQLRETURN SQL_API
+SQLGetCursorName(SQLHSTMT hstmt, SQLCHAR *cursor, SQLSMALLINT cursor_max,
+                 SQLSMALLINT *cursor_len)
+{
+  STMT *stmt= (STMT *)hstmt;
+  SQLCHAR *name;
+  my_bool free_name= FALSE;
+  SQLINTEGER len;
+  uint errors;
+
+  CLEAR_STMT_ERROR(stmt);
+
+  if (cursor_max < 0)
+    return set_error(stmt, MYERR_S1090, NULL, 0);
+
+  if (stmt->dbc->ansi_charset_info->number ==
+      stmt->dbc->cxn_charset_info->number)
+  {
+    name= MySQLGetCursorName(hstmt);
+    len= strlen((char *)name);
+  }
+  else
+  {
+    name= sqlchar_as_sqlchar(stmt->dbc->cxn_charset_info,
+                             stmt->dbc->ansi_charset_info,
+                             MySQLGetCursorName(hstmt),
+                             &len, &errors);
+    free_name= TRUE;
+  }
+
+  if (cursor && cursor_max > 1)
+    strmake((char *)cursor, (char *)name, cursor_max - 1);
+  cursor[cursor_max]= '\0';
+
+  if (cursor_len)
+    *cursor_len= len;
+
+  if (free_name)
+    x_free(name);
+
+  /* Warn if name truncated */
+  if (len > cursor_max - 1)
+    return set_error(stmt, MYERR_01004, NULL, 0);
+
+  return SQL_SUCCESS;
+}
+
+
+SQLRETURN SQL_API
 SQLGetStmtAttr(SQLHSTMT hstmt, SQLINTEGER attribute, SQLPOINTER value,
                 SQLINTEGER value_max, SQLINTEGER *value_len)
 {
@@ -236,7 +284,8 @@
   DBC *dbc= (DBC *)hdbc;
   my_bool free_value= FALSE;
 
-  if (dbc->ansi_charset_info->number != dbc->cxn_charset_info->number)
+  if (dbc->ansi_charset_info &&
+      dbc->ansi_charset_info->number != dbc->cxn_charset_info->number)
   {
     switch (attribute) {
     case SQL_ATTR_CURRENT_CATALOG:
@@ -387,14 +436,6 @@
 
 
 SQLRETURN SQL_API
-SQLGetCursorName(SQLHSTMT hstmt, SQLCHAR *cursor, SQLSMALLINT cursor_max,
-                 SQLSMALLINT *cursor_len)
-{
-  NOT_IMPLEMENTED;
-}
-
-
-SQLRETURN SQL_API
 SQLGetDescField(SQLHDESC hdesc, SQLSMALLINT record, SQLSMALLINT field,
                 SQLPOINTER value, SQLINTEGER value_max, SQLINTEGER *value_len)
 {

Modified: branches/guffert/driver/cursor.c
===================================================================
--- branches/guffert/driver/cursor.c	2007-08-21 18:41:44 UTC (rev 673)
+++ branches/guffert/driver/cursor.c	2007-08-21 23:46:30 UTC (rev 674)
@@ -1442,43 +1442,21 @@
 }
 
 
-/*
-  @type    : ODBC 1.0 API
-  @purpose : returns the cursor name associated with a specified statement
-*/
+/**
+  Get the current cursor name, generating one if necessary.
 
-SQLRETURN SQL_API SQLGetCursorName(SQLHSTMT hstmt, SQLCHAR FAR *szCursor,
-                                   SQLSMALLINT cbCursorMax,
-                                   SQLSMALLINT FAR *pcbCursor)
+  @param[in]   hstmt  Statement handle
+
+  @return  Pointer to cursor name (terminated with '\0')
+*/
+SQLCHAR *MySQLGetCursorName(HSTMT hstmt)
 {
-    STMT FAR    *stmt= (STMT FAR*) hstmt;
-    SQLINTEGER  nLength;
-    SQLSMALLINT nDummyLength;
+  STMT *stmt= (STMT *)hstmt;
 
-    CLEAR_STMT_ERROR(stmt);
+  if (!stmt->cursor.name)
+    set_dynamic_cursor_name(stmt);
 
-    if ( cbCursorMax < 0 )
-        return set_error(stmt,MYERR_S1090,NULL,0);
-
-    if ( !pcbCursor )
-        pcbCursor= &nDummyLength;
-
-    if ( cbCursorMax )
-        cbCursorMax-= sizeof(char);
-
-    if ( !stmt->cursor.name )
-        set_dynamic_cursor_name(stmt);
-
-    *pcbCursor= strlen(stmt->cursor.name);
-    if ( szCursor && cbCursorMax > 0 )
-        strmake((char*) szCursor, stmt->cursor.name, cbCursorMax);
-
-    nLength= min(*pcbCursor , cbCursorMax);
-
-    if ( nLength != *pcbCursor )
-        return set_error(stmt,MYERR_01004,NULL,0);
-
-    return SQL_SUCCESS;
+  return stmt->cursor.name;
 }
 
 

Modified: branches/guffert/driver/driver.h
===================================================================
--- branches/guffert/driver/driver.h	2007-08-21 18:41:44 UTC (rev 673)
+++ branches/guffert/driver/driver.h	2007-08-21 23:46:30 UTC (rev 674)
@@ -410,6 +410,7 @@
                                      SQLCHAR *out, SQLSMALLINT out_max,
                                      SQLSMALLINT *out_len,
                                      SQLUSMALLINT completion);
+SQLCHAR *MySQLGetCursorName(HSTMT hstmt);
 SQLRETURN SQL_API MySQLGetStmtAttr(SQLHSTMT hstmt, SQLINTEGER Attribute,
                                    SQLPOINTER ValuePtr,
                                    SQLINTEGER BufferLength

Modified: branches/guffert/driver/unicode.c
===================================================================
--- branches/guffert/driver/unicode.c	2007-08-21 18:41:44 UTC (rev 673)
+++ branches/guffert/driver/unicode.c	2007-08-21 23:46:30 UTC (rev 674)
@@ -48,6 +48,89 @@
 
 
 /**
+  Duplicate a SQLCHAR in the specified character set as a SQLWCHAR.
+
+  @param[in]      charset_info  Character set to convert into
+  @param[in]      str           String to convert
+  @param[in,out]  len           Pointer to length of source (in chars) or
+                                destination string (in bytes)
+  @param[out]     errors        Pointer to count of errors in conversion
+
+  @return  Pointer to a newly allocated SQLWCHAR, or @c NULL
+*/
+SQLWCHAR *sqlchar_as_sqlwchar(CHARSET_INFO *charset_info, SQLCHAR *str,
+                              SQLINTEGER *len, uint *errors)
+{
+  SQLCHAR *str_end;
+  SQLWCHAR *out;
+  SQLINTEGER i, out_bytes;
+  my_bool free_str= FALSE;
+
+  if (*len == SQL_NTS)
+    *len= strlen((char *)str);
+
+  if (!str || *len == 0)
+  {
+    *len= 0;
+    return NULL;
+  }
+
+  if (charset_info->number != 33) /* not utf-8 */
+  {
+    uint32 used_bytes, used_chars;
+    size_t u8_max= (*len / charset_info->mbminlen *
+                    utf8_charset_info->mbmaxlen + 1);
+    SQLCHAR *u8= (SQLCHAR *)my_malloc(u8_max, MYF(0));
+
+    if (!u8)
+    {
+      *len= -1;
+      return NULL;
+    }
+
+    *len= copy_and_convert((char *)u8, u8_max, utf8_charset_info,
+                           (char *)str, *len, charset_info,
+                           &used_bytes, &used_chars, errors);
+    str= u8;
+    free_str= TRUE;
+  }
+
+  str_end= str + *len;
+
+  out_bytes= (*len + 1) * sizeof(SQLWCHAR);
+
+  out= (SQLWCHAR *)my_malloc(out_bytes, MYF(0));
+  if (!out)
+  {
+    *len= -1;
+    return NULL;
+  }
+
+  for (i= 0; *str && str < str_end; )
+  {
+    if (sizeof(SQLWCHAR) == 4)
+    {
+      str+= utf8toutf32(str, (UTF32 *)(out + i++));
+    }
+    else
+    {
+      UTF32 u32;
+      str+= utf8toutf32(str, &u32);
+      i+= utf32toutf16(u32, (UTF16 *)(out + i));
+    }
+  }
+
+  *len= i;
+  out[i]= 0;
+
+  if (free_str)
+    x_free(str);
+
+  return out;
+}
+
+
+/**
   Duplicate a SQLWCHAR as a SQLCHAR in the specified character set.
 
   @param[in]      charset_info  Character set to convert into
@@ -275,6 +358,44 @@
 
 
 SQLRETURN SQL_API
+SQLGetCursorNameW(SQLHSTMT hstmt, SQLWCHAR *cursor, SQLSMALLINT cursor_max,
+                  SQLSMALLINT *cursor_len)
+{
+  SQLRETURN rc= SQL_SUCCESS;
+  STMT *stmt= (STMT *)hstmt;
+  SQLWCHAR *name;
+  SQLINTEGER len= SQL_NTS;
+  uint errors;
+
+  CLEAR_STMT_ERROR(stmt);
+
+  if (cursor_max < 0)
+    return set_error(stmt, MYERR_S1090, NULL, 0);
+
+  name= sqlchar_as_sqlwchar(stmt->dbc->cxn_charset_info,
+                            MySQLGetCursorName(hstmt), &len, &errors);
+
+  if (cursor_len)
+    *cursor_len= len;
+
+  /* Warn if name truncated */
+  if (len > cursor_max - 1)
+    rc= set_error(stmt, MYERR_01004, NULL, 0);
+
+  if (cursor_max > 0)
+  {
+    len= min(len, cursor_max - 1);
+    (void)memcpy((char *)cursor, (const char *)name, len * sizeof(SQLWCHAR));
+    cursor[len]= 0;
+  }
+
+  x_free(name);
+
+  return rc;
+}
+
+
+SQLRETURN SQL_API
 SQLGetStmtAttrW(SQLHSTMT hstmt, SQLINTEGER attribute, SQLPOINTER value,
                 SQLINTEGER value_max, SQLINTEGER *value_len)
 {
@@ -287,8 +408,9 @@
               SQLWCHAR *out, SQLINTEGER out_max, SQLINTEGER *out_len)
 {
   SQLRETURN rc= SQL_SUCCESS;
+
   if (in_len == SQL_NTS)
-    in_len= sqlwchar_strlen((char *)in);
+    in_len= sqlwchar_strlen(in);
 
   if (out)
     *out_len= in_len;
@@ -296,11 +418,14 @@
   if (in_len > out_max)
     rc= set_conn_error((DBC *)hdbc, MYERR_01004, NULL, 0);
 
-  if (in_len > out_max - 1)
-    in_len= out_max - 1;
+  if (out_max > 0)
+  {
+    if (in_len > out_max - 1)
+      in_len= out_max - 1;
 
-  (void)memcpy((char *)out, (const char *)in, in_len * sizeof(SQLWCHAR));
-  out[in_len]= 0;
+    (void)memcpy((char *)out, (const char *)in, in_len * sizeof(SQLWCHAR));
+    out[in_len]= 0;
+  }
 
   return SQL_SUCCESS;
 }
@@ -522,14 +647,6 @@
 
 
 SQLRETURN SQL_API
-SQLGetCursorNameW(SQLHSTMT hstmt, SQLWCHAR *cursor, SQLSMALLINT cursor_max,
-                  SQLSMALLINT *cursor_len)
-{
-  NOT_IMPLEMENTED;
-}
-
-
-SQLRETURN SQL_API
 SQLGetDescFieldW(SQLHDESC hdesc, SQLSMALLINT record, SQLSMALLINT field,
                  SQLPOINTER value, SQLINTEGER value_max, SQLINTEGER *value_len)
 {

Modified: branches/guffert/test/include/mytest3.h
===================================================================
--- branches/guffert/test/include/mytest3.h	2007-08-21 18:41:44 UTC (rev 673)
+++ branches/guffert/test/include/mytest3.h	2007-08-21 23:46:30 UTC (rev 674)
@@ -504,26 +504,37 @@
 
 
 /**
+  Convert a SQLWCHAR to wchar_t
+*/
+wchar_t *sqlwchar_to_wchar_t(SQLWCHAR *in)
+{
+  static wchar_t buff[2048];
+  wchar_t *to= buff;
+
+  if (sizeof(wchar_t) == sizeof(SQLWCHAR))
+    return (wchar_t *)in;
+
+  for ( ; *in && to < buff + sizeof(buff) - 2; in++)
+    to+= utf16toutf32((UTF16 *)in, (UTF32 *)to);
+
+  *to= L'\0';
+
+  return buff;
+}
+
+/**
   return wide string data, by fetching it and possibly converting it to wchar_t
 */
 wchar_t *my_fetch_wstr(SQLHSTMT hstmt, SQLWCHAR *buffer, SQLUSMALLINT irow)
 {
   SQLRETURN rc;
   SQLLEN nLen;
-  static wchar_t buff[2048];
-  wchar_t *to= buff;
 
   rc= SQLGetData(hstmt, irow, SQL_WCHAR, buffer, MAX_ROW_DATA_LEN + 1, &nLen);
   if (!SQL_SUCCEEDED(rc))
     return L"";
 
-  if (sizeof(wchar_t) == sizeof(SQLWCHAR))
-    return (wchar_t *)buffer;
-
-  for ( ; *buffer && to < buff + sizeof(buff) - 2; buffer++)
-    to+= utf16toutf32((UTF16 *)buffer, (UTF32 *)to);
-
-  return buff;
+  return sqlwchar_to_wchar_t(buffer);
 }
 
 

Modified: branches/guffert/test/my_cursor.c
===================================================================
--- branches/guffert/test/my_cursor.c	2007-08-21 18:41:44 UTC (rev 673)
+++ branches/guffert/test/my_cursor.c	2007-08-21 23:46:30 UTC (rev 674)
@@ -785,22 +785,21 @@
       rc = SQLGetCursorName(hstmt1,curname,4,&nlen);
       mystmt_err(hstmt1,rc == SQL_SUCCESS_WITH_INFO, rc);
       fprintf(stdout,"truncated cursor name: %s(%d)\n",curname,nlen);
-      myassert(nlen == 8);
-      myassert(!strcmp(curname,"SQL"));
+      is_num(nlen, 8);
+      is_str(curname, "SQL", 4);
 
       rc = SQLGetCursorName(hstmt1,curname,0,&nlen);
       mystmt_err(hstmt1,rc == SQL_SUCCESS_WITH_INFO, rc);
       fprintf(stdout,"untouched cursor name: %s(%d)\n",curname,nlen);
       myassert(nlen == 8);
 
-      rc = SQLGetCursorName(hstmt1,curname,8,&nlen);
-      mystmt_err(hstmt1,rc == SQL_SUCCESS_WITH_INFO, rc);
+      expect_stmt(hstmt1, SQLGetCursorName(hstmt1, curname, 8, &nlen),
+                  SQL_SUCCESS_WITH_INFO);
       fprintf(stdout,"truncated cursor name: %s(%d)\n",curname,nlen);
       myassert(nlen == 8);
       myassert(!strcmp(curname,"SQL_CUR"));
 
       rc = SQLGetCursorName(hstmt1,curname,9,&nlen);
-      mystmt(hstmt1,rc);
       fprintf(stdout,"full cursor name     : %s(%d)\n",curname,nlen);
       myassert(nlen == 8);
       myassert(!strcmp(curname,"SQL_CUR0"));

Modified: branches/guffert/test/my_unicode.c
===================================================================
--- branches/guffert/test/my_unicode.c	2007-08-21 18:41:44 UTC (rev 673)
+++ branches/guffert/test/my_unicode.c	2007-08-21 23:46:30 UTC (rev 674)
@@ -22,6 +22,7 @@
 
 #include "odbctap.h"
 #include <sqlucode.h>
+#include <wchar.h>
 
 
 DECLARE_TEST(sqlconnect)
@@ -252,19 +253,29 @@
 
 DECLARE_TEST(sqlnativesql)
 {
+  HDBC hdbc1;
   SQLWCHAR    out[128];
   wchar_t in[]= L"SELECT * FROM venu";
   SQLINTEGER len;
 
-  ok_con(hdbc, SQLNativeSqlW(hdbc, W(in), SQL_NTS, out, sizeof(out), &len));
+  ok_env(henv, SQLAllocConnect(henv, &hdbc1));
+  ok_con(hdbc1, SQLConnectW(hdbc1,
+                            W(L"myodbc3"), SQL_NTS,
+                            W(L"root"), SQL_NTS,
+                            W(L""), SQL_NTS));
+
+  ok_con(hdbc1, SQLNativeSqlW(hdbc1, W(in), SQL_NTS, out, sizeof(out), &len));
   is_num(len, sizeof(in) / sizeof(wchar_t) - 1);
-  is_wstr(out, W(in), sizeof(in) / sizeof(wchar_t) - 1);
+  is_wstr(sqlwchar_to_wchar_t(out), in, sizeof(in) / sizeof(wchar_t) - 1);
 
-  ok_con(hdbc, SQLNativeSqlW(hdbc, W(in), SQL_NTS, out, 8, &len));
+  ok_con(hdbc1, SQLNativeSqlW(hdbc1, W(in), SQL_NTS, out, 8, &len));
   is_num(len, sizeof(in) / sizeof(wchar_t) - 1);
-  is_wstr(out, W(in), 7);
+  is_wstr(sqlwchar_to_wchar_t(out), in, 7);
   is(out[7] == 0);
 
+  ok_con(hdbc1, SQLDisconnect(hdbc1));
+  ok_con(hdbc1, SQLFreeConnect(hdbc1));
+
   return OK;
 }
 
@@ -276,12 +287,6 @@
   SQLLEN  nRowCount;
   SQLCHAR data[10];
 
-  ok_env(henv, SQLAllocConnect(henv, &hdbc1));
-  ok_con(hdbc1, SQLConnectW(hdbc1, W(L"myodbc3"), SQL_NTS, W(L"root"), SQL_NTS,
-                            W(L""), SQL_NTS));
-
-  ok_con(hdbc, SQLAllocStmt(hdbc1, &hstmt1));
-
   ok_sql(hstmt, "DROP TABLE IF EXISTS my_demo_cursor");
   ok_sql(hstmt, "CREATE TABLE my_demo_cursor (id INT, name VARCHAR(20))");
   ok_sql(hstmt, "INSERT INTO my_demo_cursor VALUES (0,'MySQL0'),(1,'MySQL1'),"
@@ -289,9 +294,15 @@
 
   ok_stmt(hstmt, SQLFreeStmt(hstmt, SQL_CLOSE));
 
-  ok_stmt(hstmt1, SQLSetStmtAttr(hstmt1, SQL_ATTR_CURSOR_TYPE,
-                                 (SQLPOINTER)SQL_CURSOR_DYNAMIC, 0));
+  ok_env(henv, SQLAllocConnect(henv, &hdbc1));
+  ok_con(hdbc1, SQLConnectW(hdbc1, W(L"myodbc3"), SQL_NTS, W(L"root"), SQL_NTS,
+                            W(L""), SQL_NTS));
 
+  ok_con(hdbc1, SQLAllocStmt(hdbc1, &hstmt1));
+
+  ok_stmt(hstmt1, SQLSetStmtAttrW(hstmt1, SQL_ATTR_CURSOR_TYPE,
+                                  (SQLPOINTER)SQL_CURSOR_DYNAMIC, 0));
+
   ok_stmt(hstmt1, SQLSetCursorNameW(hstmt1, W(L"a\u00e3b"), SQL_NTS));
 
   /* Open the resultset of table 'my_demo_cursor' */
@@ -370,6 +381,69 @@
 }
 
 
+DECLARE_TEST(sqlgetcursorname)
+{
+  SQLRETURN rc;
+  HDBC hdbc1;
+  SQLHSTMT hstmt1,hstmt2,hstmt3;
+  SQLWCHAR curname[50];
+  SQLSMALLINT nlen;
+
+
+  ok_env(henv, SQLAllocConnect(henv, &hdbc1));
+  ok_con(hdbc1, SQLConnectW(hdbc1, W(L"myodbc3"), SQL_NTS, W(L"root"), SQL_NTS,
+                            W(L""), SQL_NTS));
+
+  ok_con(hdbc1, SQLAllocStmt(hdbc1, &hstmt1));
+  ok_con(hdbc1, SQLAllocStmt(hdbc1, &hstmt2));
+  ok_con(hdbc1, SQLAllocStmt(hdbc1, &hstmt3));
+
+  rc= SQLGetCursorNameW(hstmt1, curname, 50, &nlen);
+  if (SQL_SUCCEEDED(rc))
+  {
+    is_num(nlen, 8);
+    is_wstr(sqlwchar_to_wchar_t(curname), L"SQL_CUR0", 8);
+
+    ok_stmt(hstmt3,  SQLGetCursorNameW(hstmt3, curname, 50, &nlen));
+
+    expect_stmt(hstmt3,  SQLGetCursorNameW(hstmt1, curname, 4, &nlen),
+                SQL_SUCCESS_WITH_INFO);
+    is_num(nlen, 8);
+    is_wstr(sqlwchar_to_wchar_t(curname), L"SQL", 4);
+
+    expect_stmt(hstmt3,  SQLGetCursorNameW(hstmt1, curname, 0, &nlen),
+                SQL_SUCCESS_WITH_INFO);
+    rc = SQLGetCursorNameW(hstmt1, curname, 0, &nlen);
+    mystmt_err(hstmt1,rc == SQL_SUCCESS_WITH_INFO, rc);
+    is_num(nlen, 8);
+
+    expect_stmt(hstmt1, SQLGetCursorNameW(hstmt1, curname, 8, &nlen),
+                SQL_SUCCESS_WITH_INFO);
+    is_num(nlen, 8);
+    is_wstr(sqlwchar_to_wchar_t(curname), L"SQL_CUR", 8);
+
+    ok_stmt(hstmt1, SQLGetCursorNameW(hstmt1, curname, 9, &nlen));
+    is_num(nlen, 8);
+    is_wstr(sqlwchar_to_wchar_t(curname), L"SQL_CUR0", 8);
+  }
+
+  ok_stmt(hstmt1,  SQLSetCursorNameW(hstmt1, W(L"venucur123"), 7));
+
+  ok_stmt(hstmt1,  SQLGetCursorNameW(hstmt1, curname, 8, &nlen));
+  is_num(nlen, 7);
+  is_wstr(sqlwchar_to_wchar_t(curname), L"venucur", 8);
+
+  ok_stmt(hstmt3, SQLFreeStmt(hstmt3, SQL_DROP));
+  ok_stmt(hstmt2, SQLFreeStmt(hstmt2, SQL_DROP));
+  ok_stmt(hstmt1, SQLFreeStmt(hstmt1, SQL_DROP));
+
+  ok_con(hdbc1, SQLDisconnect(hdbc1));
+  ok_con(hdbc1, SQLFreeConnect(hdbc1));
+
+  return OK;
+}
+
+
 BEGIN_TESTS
   ADD_TEST(sqlconnect)
   ADD_TEST(sqlprepare)
@@ -378,6 +452,7 @@
   ADD_TEST(sqldriverconnect)
   ADD_TEST(sqlnativesql)
   ADD_TEST(sqlsetcursorname)
+  ADD_TEST(sqlgetcursorname)
 END_TESTS
 
 

Thread
Connector/ODBC 3.51 commit: r674 - in branches/guffert: driver test test/includejwinstead22 Aug