List:Commits« Previous MessageNext Message »
From:jwinstead Date:August 21 2007 8:41pm
Subject:Connector/ODBC 3.51 commit: r673 - in branches/guffert: driver test
View as plain text  
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 testjwinstead21 Aug