Modified:
branches/guffert/driver/ansi.c
branches/guffert/driver/cursor.c
branches/guffert/driver/driver.def
branches/guffert/driver/driver.h
branches/guffert/driver/options.c
branches/guffert/driver/unicode.c
branches/guffert/test/my_unicode.c
Log:
Implement SQLSetStmtAttrW() and SQLSetCursorNameW()
Modified: branches/guffert/driver/ansi.c
===================================================================
--- branches/guffert/driver/ansi.c 2007-08-21 18:14:46 UTC (rev 672)
+++ branches/guffert/driver/ansi.c 2007-08-21 18:41:44 UTC (rev 673)
@@ -91,6 +91,40 @@
SQLRETURN SQL_API
+SQLSetCursorName(SQLHSTMT hstmt, SQLCHAR *name, SQLSMALLINT name_len)
+{
+ STMT *stmt= (STMT *)hstmt;
+ SQLINTEGER len= name_len;
+ uint errors= 0;
+
+ if (stmt->dbc->ansi_charset_info->number ==
+ stmt->dbc->cxn_charset_info->number)
+ return MySQLSetCursorName(hstmt, name, name_len);
+
+ name= sqlchar_as_sqlchar(stmt->dbc->ansi_charset_info,
+ stmt->dbc->cxn_charset_info,
+ name, &len, &errors);
+
+ if (!name && len == -1)
+ {
+ set_mem_error(&stmt->dbc->mysql);
+ return handle_connection_error(stmt);
+ }
+
+ /* Character conversion problems are not tolerated. */
+ if (errors)
+ {
+ x_free(name);
+ return set_stmt_error(stmt, "HY000",
+ "Cursor name included characters that could not "
+ "be converted to connection character set", 0);
+ }
+
+ return MySQLSetCursorName(hstmt, name, (SQLSMALLINT)len);
+}
+
+
+SQLRETURN SQL_API
SQLDriverConnect(SQLHDBC hdbc, SQLHWND hwnd, SQLCHAR *in, SQLSMALLINT in_len,
SQLCHAR *out, SQLSMALLINT out_max, SQLSMALLINT *out_len,
SQLUSMALLINT completion)
@@ -226,7 +260,7 @@
rc= MySQLSetConnectAttr(hdbc, attribute, value, value_len);
if (free_value)
- x_free(value_len);
+ x_free(value);
return rc;
}
@@ -247,6 +281,15 @@
}
+SQLRETURN SQL_API
+SQLSetStmtAttr(SQLHSTMT hstmt, SQLINTEGER attribute,
+ SQLPOINTER value, SQLINTEGER value_len)
+{
+ /* Nothing special to do, since we don't have any string stmt attribs */
+ return MySQLSetStmtAttr(hstmt, attribute, value, value_len);
+}
+
+
#ifdef NOT_IMPLEMENTED_YET
SQLRETURN SQL_API
SQLBrowseConnect(SQLHDBC hdbc, SQLCHAR *in, SQLSMALLINT in_len,
@@ -429,13 +472,6 @@
SQLRETURN SQL_API
-SQLSetCursorName(SQLHSTMT hstmt, SQLCHAR *name, SQLSMALLINT name_len)
-{
- NOT_IMPLEMENTED;
-}
-
-
-SQLRETURN SQL_API
SQLSetDescField(SQLHDESC hdesc, SQLSMALLINT record, SQLSMALLINT field,
SQLPOINTER value, SQLINTEGER value_len)
{
@@ -444,14 +480,6 @@
SQLRETURN SQL_API
-SQLSetStmtAttr(SQLHSTMT hstmt, SQLINTEGER attribute,
- SQLPOINTER value, SQLINTEGER value_len)
-{
- NOT_IMPLEMENTED;
-}
-
-
-SQLRETURN SQL_API
SQLSpecialColumns(SQLHSTMT hstmt, SQLUSMALLINT type,
SQLCHAR *catalog, SQLSMALLINT catalog_len,
SQLCHAR *schema, SQLSMALLINT schema_len,
Modified: branches/guffert/driver/cursor.c
===================================================================
--- branches/guffert/driver/cursor.c 2007-08-21 18:14:46 UTC (rev 672)
+++ branches/guffert/driver/cursor.c 2007-08-21 18:41:44 UTC (rev 673)
@@ -1412,38 +1412,33 @@
}
-/*
- @type : ODBC 1.0 API
- @purpose : associates a cursor name with an active statement.
- If an application does not call SQLSetCursorName, the driver
- generates cursor names as needed for SQL statement processing
-*/
-
-SQLRETURN SQL_API SQLSetCursorName(SQLHSTMT hstmt, SQLCHAR *szCursor,
- SQLSMALLINT cbCursor)
+SQLRETURN SQL_API
+MySQLSetCursorName(SQLHSTMT hstmt, SQLCHAR *name, SQLSMALLINT len)
{
- STMT FAR *stmt= (STMT FAR*) hstmt;
+ STMT *stmt= (STMT *) hstmt;
- CLEAR_STMT_ERROR(stmt);
+ CLEAR_STMT_ERROR(stmt);
- if ( !szCursor )
- return set_error(stmt,MYERR_S1009,NULL,0);
+ if (!name)
+ return set_error(stmt, MYERR_S1009, NULL, 0);
- if ( cbCursor == SQL_NTS )
- cbCursor= (SQLSMALLINT) strlen((char*) szCursor);
+ if (len == SQL_NTS)
+ len= strlen((char *)name);
- if ( cbCursor < 0 )
- return set_error(stmt,MYERR_S1090,NULL,0);
+ if (len < 0)
+ return set_error(stmt, MYERR_S1009, NULL, 0);
- if ( (cbCursor == 0) ||
- (cbCursor > MYSQL_MAX_CURSOR_LEN) ||
- (myodbc_casecmp((char*) szCursor, "SQLCUR", 6) == 0) ||
- (myodbc_casecmp((char*) szCursor, "SQL_CUR", 7) == 0) )
- return set_error(stmt,MYERR_34000,NULL,0);
+ /** @todo use charset-aware casecmp */
+ if (len == 0 ||
+ len > MYSQL_MAX_CURSOR_LEN ||
+ myodbc_casecmp((char *)name, "SQLCUR", 6) == 0 ||
+ myodbc_casecmp((char *)name, "SQL_CUR", 7) == 0)
+ return set_error(stmt, MYERR_34000, NULL, 0);
- x_free((gptr) stmt->cursor.name);
- stmt->cursor.name= dupp_str((char*) szCursor,cbCursor);
- return SQL_SUCCESS;
+ x_free(stmt->cursor.name);
+ stmt->cursor.name= dupp_str((char*)name, len);
+
+ return SQL_SUCCESS;
}
Modified: branches/guffert/driver/driver.def
===================================================================
--- branches/guffert/driver/driver.def 2007-08-21 18:14:46 UTC (rev 672)
+++ branches/guffert/driver/driver.def 2007-08-21 18:41:44 UTC (rev 673)
@@ -110,7 +110,14 @@
SQLConnectW
SQLDriverConnectW
SQLExecDirectW
+SQLGetStmtAttrW
+SQLNativeSqlW
SQLPrepareW
+SQLSetConnectAttrW
+SQLSetConnectOptionW
+SQLSetCursorNameW
+SQLSetStmtAttrW
+
;
DllMain
LoadByOrdinal
Modified: branches/guffert/driver/driver.h
===================================================================
--- branches/guffert/driver/driver.h 2007-08-21 18:14:46 UTC (rev 672)
+++ branches/guffert/driver/driver.h 2007-08-21 18:41:44 UTC (rev 673)
@@ -420,5 +420,9 @@
SQLRETURN SQL_API MySQLSetConnectAttr(SQLHDBC hdbc, SQLINTEGER Attribute,
SQLPOINTER ValuePtr,
SQLINTEGER StringLengthPtr);
+SQLRETURN SQL_API MySQLSetCursorName(SQLHSTMT hstmt, SQLCHAR *name,
+ SQLSMALLINT len);
+SQLRETURN SQL_API MySQLSetStmtAttr(SQLHSTMT hstmt, SQLINTEGER attribute,
+ SQLPOINTER value, SQLINTEGER len);
#endif /* __MYODBC3_H__ */
Modified: branches/guffert/driver/options.c
===================================================================
--- branches/guffert/driver/options.c 2007-08-21 18:14:46 UTC (rev 672)
+++ branches/guffert/driver/options.c 2007-08-21 18:41:44 UTC (rev 673)
@@ -575,11 +575,9 @@
@purpose : sets the statement attributes
*/
-static SQLRETURN
-set_stmt_attr(SQLHSTMT hstmt,
- SQLINTEGER Attribute,
- SQLPOINTER ValuePtr,
- SQLINTEGER StringLengthPtr __attribute__((unused)))
+SQLRETURN SQL_API
+MySQLSetStmtAttr(SQLHSTMT hstmt, SQLINTEGER Attribute, SQLPOINTER ValuePtr,
+ SQLINTEGER StringLengthPtr __attribute__((unused)))
{
STMT FAR *stmt= (STMT FAR*) hstmt;
SQLRETURN result= SQL_SUCCESS;
@@ -782,19 +780,6 @@
/*
- @type : ODBC 1.0 API
- @purpose : sets the statement options
-*/
-
-SQLRETURN SQL_API SQLSetStmtOption( SQLHSTMT hstmt,
- SQLUSMALLINT fOption,
- SQLULEN vParam )
-{
- return set_stmt_attr(hstmt,fOption,(SQLPOINTER)vParam,SQL_NTS);
-}
-
-
-/*
@type : ODBC 3.0 API
@purpose : sets the environment attributes
*/
@@ -873,29 +858,16 @@
return get_con_attr(hdbc, Attribute, ValuePtr, BufferLength, StringLengthPtr);
}
-/*
- @type : ODBC 3.0 API
- @purpose : sets the statement attributes
-*/
-SQLRETURN SQL_API SQLSetStmtAttr(SQLHSTMT hstmt,
- SQLINTEGER Attribute,
- SQLPOINTER ValuePtr,
- SQLINTEGER StringLength)
+SQLRETURN SQL_API
+SQLGetStmtOption(SQLHSTMT hstmt,SQLUSMALLINT option, SQLPOINTER param)
{
- return set_stmt_attr(hstmt, Attribute, ValuePtr, StringLength );
+ return MySQLGetStmtAttr(hstmt, option, param, SQL_NTS, (SQLINTEGER *)NULL);
}
-/*
- @type : ODBC 1.0 API
- @purpose : returns the statement options
-*/
-
-SQLRETURN SQL_API SQLGetStmtOption(SQLHSTMT hstmt,SQLUSMALLINT fOption,
- SQLPOINTER vParam)
+SQLRETURN SQL_API
+SQLSetStmtOption(SQLHSTMT hstmt, SQLUSMALLINT option, SQLULEN param)
{
- return MySQLGetStmtAttr(hstmt, fOption, vParam, SQL_NTS, (SQLINTEGER *)NULL);
+ return MySQLSetStmtAttr(hstmt, option, (SQLPOINTER)param, SQL_NTS);
}
-
-
Modified: branches/guffert/driver/unicode.c
===================================================================
--- branches/guffert/driver/unicode.c 2007-08-21 18:14:46 UTC (rev 672)
+++ branches/guffert/driver/unicode.c 2007-08-21 18:41:44 UTC (rev 673)
@@ -369,6 +369,32 @@
SQLRETURN SQL_API
+SQLSetCursorNameW(SQLHSTMT hstmt, SQLWCHAR *name, SQLSMALLINT name_len)
+{
+ SQLRETURN rc;
+ DBC *dbc= ((STMT *)hstmt)->dbc;
+ SQLINTEGER len= name_len;
+ uint errors= 0;
+ SQLCHAR *name_char= sqlwchar_as_sqlchar(dbc->cxn_charset_info,
+ name, &len, &errors);
+
+ rc= MySQLSetCursorName(hstmt, name_char, len);
+
+ x_free(name_char);
+
+ /* Character conversion problems are not tolerated. */
+ if (errors)
+ {
+ return set_stmt_error((STMT *)hstmt, "HY000",
+ "Cursor name included characters that could not "
+ "be converted to connection character set", 0);
+ }
+
+ return rc;
+}
+
+
+SQLRETURN SQL_API
SQLSetConnectOptionW(SQLHDBC hdbc, SQLUSMALLINT option, SQLULEN param)
{
SQLINTEGER value_len= 0;
@@ -383,6 +409,15 @@
}
+SQLRETURN SQL_API
+SQLSetStmtAttrW(SQLHSTMT hstmt, SQLINTEGER attribute,
+ SQLPOINTER value, SQLINTEGER value_len)
+{
+ /* Nothing special to do, since we don't have any string stmt attribs */
+ return MySQLSetStmtAttr(hstmt, attribute, value, value_len);
+}
+
+
#ifdef NOT_IMPLEMENTED_YET
SQLRETURN SQL_API
SQLBrowseConnectW(SQLHDBC hdbc, SQLWCHAR *in, SQLSMALLINT in_len,
@@ -580,13 +615,6 @@
SQLRETURN SQL_API
-SQLSetCursorNameW(SQLHSTMT hstmt, SQLWCHAR *name, SQLSMALLINT name_len)
-{
- NOT_IMPLEMENTED;
-}
-
-
-SQLRETURN SQL_API
SQLSetDescFieldW(SQLHDESC hdesc, SQLSMALLINT record, SQLSMALLINT field,
SQLPOINTER value, SQLINTEGER value_len)
{
@@ -595,14 +623,6 @@
SQLRETURN SQL_API
-SQLSetStmtAttrW(SQLHSTMT hstmt, SQLINTEGER attribute,
- SQLPOINTER value, SQLINTEGER value_len)
-{
- NOT_IMPLEMENTED;
-}
-
-
-SQLRETURN SQL_API
SQLSpecialColumnsW(SQLHSTMT hstmt, SQLUSMALLINT type,
SQLWCHAR *catalog, SQLSMALLINT catalog_len,
SQLWCHAR *schema, SQLSMALLINT schema_len,
Modified: branches/guffert/test/my_unicode.c
===================================================================
--- branches/guffert/test/my_unicode.c 2007-08-21 18:14:46 UTC (rev 672)
+++ branches/guffert/test/my_unicode.c 2007-08-21 18:41:44 UTC (rev 673)
@@ -269,6 +269,107 @@
}
+DECLARE_TEST(sqlsetcursorname)
+{
+ HDBC hdbc1;
+ HSTMT hstmt1, hstmt_pos;
+ 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'),"
+ "(2,'MySQL2'),(3,'MySQL3'),(4,'MySQL4')");
+
+ ok_stmt(hstmt, SQLFreeStmt(hstmt, SQL_CLOSE));
+
+ ok_stmt(hstmt1, SQLSetStmtAttr(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' */
+ ok_sql(hstmt1, "SELECT * FROM my_demo_cursor");
+
+ /* goto the last row */
+ ok_stmt(hstmt1, SQLFetchScroll(hstmt1, SQL_FETCH_LAST, 1L));
+
+ /* create new statement handle */
+ ok_con(hdbc1, SQLAllocHandle(SQL_HANDLE_STMT, hdbc1, &hstmt_pos));
+
+ /* now update the name field to 'updated' using positioned cursor */
+ ok_stmt(hstmt_pos,
+ SQLExecDirectW(hstmt_pos,
+ W(L"UPDATE my_demo_cursor SET name='updated' "
+ L"WHERE CURRENT OF a\u00e3b"), SQL_NTS));
+
+ ok_stmt(hstmt_pos, SQLRowCount(hstmt_pos, &nRowCount));
+ is_num(nRowCount, 1);
+
+ ok_stmt(hstmt_pos, SQLFreeStmt(hstmt_pos, SQL_CLOSE));
+ ok_stmt(hstmt1, SQLFreeStmt(hstmt1, SQL_CLOSE));
+
+ /* Now delete 2nd row */
+ ok_sql(hstmt1, "SELECT * FROM my_demo_cursor");
+
+ /* goto the second row */
+ ok_stmt(hstmt1, SQLFetchScroll(hstmt1, SQL_FETCH_ABSOLUTE, 2L));
+
+ /* now delete the current row */
+ ok_stmt(hstmt_pos,
+ SQLExecDirectW(hstmt_pos,
+ W(L"DELETE FROM my_demo_cursor "
+ L"WHERE CURRENT OF a\u00e3b"), SQL_NTS));
+
+ ok_stmt(hstmt_pos, SQLRowCount(hstmt_pos, &nRowCount));
+ is_num(nRowCount, 1);
+
+ /* free the statement cursor */
+ ok_stmt(hstmt1, SQLFreeStmt(hstmt1, SQL_CLOSE));
+
+ /* Free the statement 'hstmt_pos' */
+ ok_stmt(hstmt_pos, SQLFreeHandle(SQL_HANDLE_STMT, hstmt_pos));
+
+ /* Now fetch and verify the data */
+ ok_sql(hstmt1, "SELECT * FROM my_demo_cursor");
+
+ ok_stmt(hstmt1, SQLFetch(hstmt1));
+ is_num(my_fetch_int(hstmt1, 1), 0);
+ is_str(my_fetch_str(hstmt1, data, 2), "MySQL0", 6);
+
+ ok_stmt(hstmt1, SQLFetch(hstmt1));
+ is_num(my_fetch_int(hstmt1, 1), 2);
+ is_str(my_fetch_str(hstmt1, data, 2), "MySQL2", 6);
+
+ ok_stmt(hstmt1, SQLFetch(hstmt1));
+ is_num(my_fetch_int(hstmt1, 1), 3);
+ is_str(my_fetch_str(hstmt1, data, 2), "MySQL3", 6);
+
+ ok_stmt(hstmt1, SQLFetch(hstmt1));
+ is_num(my_fetch_int(hstmt1, 1), 4);
+ is_str(my_fetch_str(hstmt1, data, 2), "updated", 7);
+
+ expect_stmt(hstmt1, SQLFetch(hstmt1), SQL_NO_DATA_FOUND);
+
+ ok_stmt(hstmt1, SQLFreeStmt(hstmt1, SQL_CLOSE));
+
+ ok_sql(hstmt, "DROP TABLE IF EXISTS my_demo_cursor");
+
+ 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)
@@ -276,6 +377,7 @@
ADD_TEST(sqlchar)
ADD_TEST(sqldriverconnect)
ADD_TEST(sqlnativesql)
+ ADD_TEST(sqlsetcursorname)
END_TESTS
| Thread |
|---|
| • Connector/ODBC 3.51 commit: r673 - in branches/guffert: driver test | jwinstead | 21 Aug |