Index: ChangeLog =================================================================== --- ChangeLog (revision 416) +++ ChangeLog (working copy) @@ -1,6 +1,8 @@ 3.51.16 Functionality added or changed: + * Calls to SQLSetPos() could cause the driver to incorrectly calculate the + length of some fields. (Bug #16917) Bugs fixed: Index: driver/cursor.c =================================================================== --- driver/cursor.c (revision 416) +++ driver/cursor.c (working copy) @@ -1341,12 +1341,18 @@ sqlRet= SQL_SUCCESS; stmt->cursor_row= (long)(stmt->current_row+irow); mysql_data_seek(stmt->result,(my_ulonglong)stmt->cursor_row); - stmt->current_values= stmt->result->data_cursor->data; + stmt->current_values= mysql_fetch_row(stmt->result); stmt->last_getdata_col= (uint) ~0;; /* reset */ if ( stmt->fix_fields ) stmt->current_values= (*stmt->fix_fields)(stmt,stmt->current_values); else stmt->result_lengths= mysql_fetch_lengths(stmt->result); + /* + Our call to mysql_fetch_row() moved stmt->result's internal + cursor, but we don't want that. So we seek back to this row + so the MYSQL_RES is in the state we expect. + */ + mysql_data_seek(stmt->result,(my_ulonglong)stmt->cursor_row); pthread_mutex_unlock(&stmt->dbc->lock); break; } Index: test/my_types.c =================================================================== --- test/my_types.c (revision 416) +++ test/my_types.c (working copy) @@ -401,12 +401,49 @@ } +DECLARE_TEST(t_bug16917) +{ + SQLCHAR buff[255]; + SQLLEN len; + + ok_sql(hstmt, "DROP TABLE IF EXISTS t_bug16917"); + ok_sql(hstmt, "CREATE TABLE t_bug16917 (a TEXT)"); + ok_sql(hstmt, "INSERT INTO t_bug16917 VALUES ('a\\0b')"); + + ok_stmt(hstmt, SQLFreeStmt(hstmt, SQL_CLOSE)); + + ok_sql(hstmt, "SELECT a FROM t_bug16917"); + + ok_stmt(hstmt, SQLFetch(hstmt)); + + /* This SQLSetPos() causes the field lengths to get lost. */ + ok_stmt(hstmt, SQLSetPos(hstmt, 1, SQL_POSITION, SQL_LOCK_NO_CHANGE)); + + ok_stmt(hstmt, SQLGetData(hstmt, 1, SQL_C_CHAR, buff, 0, &len)); + is_num(len, 3); + + ok_stmt(hstmt, SQLGetData(hstmt, 1, SQL_C_CHAR, buff, sizeof(buff), &len)); + is_num(buff[0], 'a'); + is_num(buff[1], 0); + is_num(buff[2], 'b'); + is_num(len, 3); + + expect_stmt(hstmt, SQLFetch(hstmt), SQL_NO_DATA_FOUND); + + ok_stmt(hstmt, SQLFreeStmt(hstmt, SQL_CLOSE)); + + ok_sql(hstmt, "DROP TABLE IF EXISTS t_bug16917"); + return OK; +} + + BEGIN_TESTS ADD_TEST(t_longlong1) ADD_TEST(t_numeric) ADD_TEST(t_decimal) ADD_TEST(t_bigint) ADD_TEST(t_enumset) + ADD_TEST(t_bug16917) END_TESTS