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/include | jwinstead | 22 Aug |