Index: driver/utility.c =================================================================== --- driver/utility.c (revision 161) +++ driver/utility.c (working copy) @@ -757,7 +757,7 @@ case SQL_C_LONG: case SQL_C_SLONG: case SQL_C_ULONG: - return sizeof(long); + return sizeof(SQLINTEGER); case SQL_C_FLOAT: return sizeof(float); case SQL_C_DOUBLE: Index: driver/cursor.c =================================================================== --- driver/cursor.c (revision 161) +++ driver/cursor.c (working copy) @@ -615,83 +615,108 @@ /* @type : myodbc3 internal - @purpose : copies all resultset column data to where clause + @purpose : generate a WHERE clause based on the fields in the result set */ -static SQLRETURN insert_fields( STMT FAR * stmt, - DYNAMIC_STRING *dynQuery ) +static SQLRETURN append_all_fields(STMT FAR *stmt, + DYNAMIC_STRING *dynQuery) { - MYSQL_RES * result = stmt->result; - MYSQL_FIELD * field; - SQLUSMALLINT ncol; - MYSQL_RES * presultAllColumns; - char select[NAME_LEN+15]; + MYSQL_RES *result= stmt->result; + MYSQL_RES *presultAllColumns; + char select[NAME_LEN+30]; + int i, j; - /* get base table name - fails if we have more than one */ - if ( !( find_used_table( stmt ) ) ) - return ( SQL_ERROR ); + MYODBCDbgEnter; - /* get a list of all table cols using "SELECT & LIMIT 0" method */ - strxmov( select, "SELECT * FROM `", stmt->table_name, "` LIMIT 0", NullS ); - MYLOG_QUERY( stmt, select ); - pthread_mutex_lock( &stmt->dbc->lock ); - if ( ( mysql_query( &stmt->dbc->mysql, select ) || !( presultAllColumns = mysql_store_result( &stmt->dbc->mysql ) ) ) ) - { - set_error( stmt, MYERR_S1000, mysql_error( &stmt->dbc->mysql ), mysql_errno( &stmt->dbc->mysql ) ); - pthread_mutex_unlock( &stmt->dbc->lock ); - return ( SQL_ERROR ); - } - pthread_mutex_unlock( &stmt->dbc->lock ); + /* + Get the base table name. If there was more than one table underlying + the result set, this will fail, and we couldn't build a suitable + list of fields. + */ + if (!(find_used_table(stmt))) + MYODBCDbgReturn(SQL_ERROR); + /* + Get the list of all of the columns of the underlying table by using + SELECT * FROM LIMIT 0. + */ + strxmov(select, "SELECT * FROM `", stmt->table_name, "` LIMIT 0", NullS); + MYLOG_QUERY(stmt, select); + pthread_mutex_lock(&stmt->dbc->lock); + if (mysql_query(&stmt->dbc->mysql, select) || + !(presultAllColumns= mysql_store_result(&stmt->dbc->mysql))) + { + set_error(stmt, MYERR_S1000, mysql_error(&stmt->dbc->mysql), + mysql_errno(&stmt->dbc->mysql)); + pthread_mutex_unlock(&stmt->dbc->lock); + MYODBCDbgReturn(SQL_ERROR); + } + pthread_mutex_unlock(&stmt->dbc->lock); + + /* + If the number of fields in the underlying table is not the same as + our result set, we bail out -- we need them all! + */ + if (presultAllColumns->field_count != result->field_count) + { + mysql_free_result(presultAllColumns); + MYODBCDbgReturn(SQL_ERROR); + } + + /* + Now we walk through the list of columns in the underlying table, + appending them to the query along with the value from the row at the + current cursor position. + */ + for (i= 0; i < presultAllColumns->field_count; i++) + { + MYSQL_FIELD *table_field= presultAllColumns->fields + i; + /* - If current result set field count is not the total - count from the actual table, then use the temp result - to have a search condition from all table fields .. - - This can be buggy, if multiple times the same - column is used in the select ..rare case .. + We also can't handle floating-point fields because their comparison + is inexact. */ -/* printf( "\n[PAH][%s][%d]\n", __FILE__, __LINE__ ); */ - if ( presultAllColumns->row_count != result->row_count && !if_dynamic_cursor(stmt) ) + if (if_float_field(stmt, table_field)) { -/* printf( "\n[PAH][%s][%d]\n", __FILE__, __LINE__ ); */ - mysql_free_result(presultAllColumns); - presultAllColumns= 0; + MYODBCDbgInfo("field '%s' is a floating-point field", + table_field->name); + mysql_free_result(presultAllColumns); + MYODBCDbgReturn(SQL_ERROR); } - else if ( presultAllColumns->field_count != result->field_count || - !result->data_cursor || - (if_dynamic_cursor(stmt) && - presultAllColumns->row_count != result->row_count) ) + + for (j= 0; j < result->field_count; j++) { - for ( ncol= 0; ncol < (SQLUSMALLINT)stmt->current_row; ncol++ ) + MYSQL_FIELD *cursor_field= result->fields + j; + if (cursor_field->org_name && + !strcmp(cursor_field->org_name, table_field->name)) + { + dynstr_append_quoted_name(dynQuery, table_field->name); + dynstr_append_mem(dynQuery, "=", 1); + if (insert_field(stmt, result, dynQuery, j)) { -/* printf( "\n[PAH][%s][%d] Column %d of %d\n", __FILE__, __LINE__, ncol, stmt->current_row ); */ - presultAllColumns->data_cursor = presultAllColumns->data_cursor->next; + MYODBCDbgInfo("failed to append value for '%s'", table_field->name); + mysql_free_result(presultAllColumns); + MYODBCDbgReturn(SQL_ERROR); } - result = presultAllColumns; + j= -1; + break; + } } -/* printf( "\n[PAH][%s][%d]\n", __FILE__, __LINE__ ); */ - pthread_mutex_lock( &stmt->dbc->lock ); - /* Copy all row buffers to query search clause */ - for ( ncol = 0; ncol < result->field_count; ncol++ ) + /* + If we didn't find the field, we have failed. + */ + if (j > 0) { - field = result->fields + ncol; - dynstr_append_quoted_name( dynQuery, field->name ); - dynstr_append_mem( dynQuery, "=", 1 ); - - if ( if_float_field( stmt, field ) || insert_field( stmt, result, dynQuery, ncol ) ) - { - mysql_free_result( presultAllColumns ); - pthread_mutex_unlock( &stmt->dbc->lock ); - return ( SQL_ERROR ); - } + MYODBCDbgInfo("could not find field '%s' in result set", + table_field->name); + mysql_free_result(presultAllColumns); + MYODBCDbgReturn(SQL_ERROR); } + } - mysql_free_result( presultAllColumns ); - pthread_mutex_unlock( &stmt->dbc->lock ); - - return( SQL_SUCCESS ); + mysql_free_result(presultAllColumns); + MYODBCDbgReturn(SQL_SUCCESS); } /* @@ -717,9 +742,10 @@ } else { - if ( insert_fields( pStmt, dynQuery ) != SQL_SUCCESS ) + if ( append_all_fields( pStmt, dynQuery ) != SQL_SUCCESS ) return set_stmt_error( pStmt, "HY000", "Build WHERE -> insert_fields() failed.", 0 ); } + /* Remove the trailing ' AND ' */ dynQuery->length -= 5; /* IF irow = 0 THEN delete all rows in the rowset ELSE specific (as in one) row */ @@ -971,9 +997,7 @@ dynQuery->length= query_length; /* append our WHERE clause to our DELETE statement */ -/* printf( "\n[PAH][%s][%d] %d\n", __FILE__, __LINE__, rowset_pos ); */ nReturn = build_where_clause( stmt, dynQuery, (SQLUSMALLINT)rowset_pos ); -/* printf( "\n[PAH][%s][%d] (%s)\n", __FILE__, __LINE__, dynQuery ); */ if ( !SQL_SUCCEEDED( nReturn ) ) return nReturn; Index: test/dyn_cursor/my_dyn_cursor.c =================================================================== --- test/dyn_cursor/my_dyn_cursor.c (revision 164) +++ test/dyn_cursor/my_dyn_cursor.c (working copy) @@ -18,12 +18,11 @@ SQLCHAR *mysock= NULL; -/******************************************************** -* perform positioned update and delete * +/******************************************************** perform positioned + * update and delete * *********************************************************/ void my_dynamic_pos_cursor(SQLHDBC hdbc, SQLHSTMT hstmt) { -#if BUG_22796_FIXED SQLRETURN rc; SQLLEN nRowCount; SQLHSTMT hstmt_pos; @@ -149,7 +148,6 @@ SQLFreeStmt(hstmt, SQL_RESET_PARAMS); SQLFreeStmt(hstmt, SQL_UNBIND); SQLFreeStmt(hstmt, SQL_CLOSE); -#endif } @@ -310,7 +308,10 @@ */ void my_setpos_delete_ignore(SQLHDBC hdbc, SQLHSTMT hstmt) { -#if BUG_22796_FIXED +#if ALLOW_CRAZY_TESTS + /* + This test does not actually test what it claims to test. + */ SQLRETURN rc; SQLLEN nlen; char szData[255]={0}; @@ -355,11 +356,9 @@ mystmt(hstmt,rc); strcpy(szData,"mysql2"); -printf( "\n[PAH][%s][%d]\n", __FILE__, __LINE__ ); /* SQL_DELETE all rows by passing row=0 */ rc = SQLSetPos( hstmt, 0, SQL_DELETE, SQL_LOCK_NO_CHANGE ); mystmt( hstmt, rc ); -printf( "\n[PAH][%s][%d]\n", __FILE__, __LINE__ ); rc = SQLRowCount(hstmt,&nlen); mystmt(hstmt,rc); @@ -387,7 +386,10 @@ */ void my_setpos_update_ignore(SQLHDBC hdbc, SQLHSTMT hstmt) { -#if BUG_22796_FIXED +#if ALLOW_CRAZY_TESTS + /* + This test does not actually test what it claims to test. + */ SQLRETURN rc; SQLLEN nlen; char szData[255]={0}; @@ -460,7 +462,10 @@ */ void my_setpos_update_ignore1(SQLHDBC hdbc, SQLHSTMT hstmt) { -#if BUG_22796_FIXED +#if ALLOW_CRAZY_TESTS + /* + This test does not actually test what it claims to test. + */ SQLRETURN rc; SQLLEN nlen; char szData[255]={0}; @@ -533,7 +538,6 @@ */ void my_position(SQLHDBC hdbc, SQLHSTMT hstmt) { -#if BUG_22796_FIXED SQLRETURN rc; SQLLEN nlen; char szData[255]={0}; @@ -632,7 +636,6 @@ rc = SQLFreeStmt(hstmt,SQL_CLOSE); mystmt(hstmt,rc); -#endif } /* @@ -640,11 +643,10 @@ */ void my_position1(SQLHDBC hdbc, SQLHSTMT hstmt) { -#if BUG_22796_FIXED SQLRETURN rc; - SQLLEN nlen[15]; + SQLINTEGER nData[15]; + SQLLEN nlen[15]= {0}, nrow[15]= {0}; char szData[15][15]={0}; - long nData[15], nrow[15]; SQLExecDirect(hstmt,"drop table my_position",SQL_NTS); rc = SQLExecDirect(hstmt,"create table my_position(col1 int, col2 varchar(30))",SQL_NTS); @@ -693,18 +695,18 @@ rc = SQLExecDirect(hstmt,"select * from my_position",SQL_NTS); mystmt(hstmt,rc); - rc = SQLBindCol(hstmt,1,SQL_C_LONG,&nData,0,(long *)&nrow); + rc = SQLBindCol(hstmt,1,SQL_C_LONG,&nData,0,nrow); mystmt(hstmt,rc); - rc = SQLBindCol(hstmt,2,SQL_C_CHAR,szData,sizeof(szData[0]),(long *)&nlen); + rc = SQLBindCol(hstmt,2,SQL_C_CHAR,szData,sizeof(szData[0]),nlen); mystmt(hstmt,rc); rc = SQLFetchScroll(hstmt,SQL_FETCH_ABSOLUTE,4); mystmt(hstmt,rc); - nData[0] = 888; + nData[0] = 888; nData[1] = 999; nrow[1] = SQL_COLUMN_IGNORE; - nData[2] = 1000; + nData[2] = 1000; strcpy(szData[0],"updatex"); nlen[0] = 15; strcpy(szData[1],"updatey"); nlen[1] = 15; @@ -717,17 +719,17 @@ mystmt(hstmt,rc); rc = SQLFreeStmt(hstmt,SQL_CLOSE); - mystmt(hstmt,rc); + mystmt(hstmt,rc); rc = SQLExecDirect(hstmt,"select * from my_position",SQL_NTS); - mystmt(hstmt,rc); + mystmt(hstmt,rc); rc = SQLFetchScroll(hstmt,SQL_FETCH_ABSOLUTE,4); mystmt(hstmt,rc); - printMessage("\n updated data1:%d,%s",nData[0],szData[0]); - printMessage("\n updated data2:%d,%s",nData[1],szData[1]); - printMessage("\n updated data3:%d,%s",nData[2],szData[2]); + printMessage("updated data1:%d,%s\n",nData[0],szData[0]); + printMessage("updated data2:%d,%s\n",nData[1],szData[1]); + printMessage("updated data3:%d,%s\n",nData[2],szData[2]); myassert(nData[0] == 4);myassert(strcmp(szData[0],"MySQL4")== 0); myassert(nData[1] == 5);myassert(strcmp(szData[1],"updatey")== 0); myassert(nData[2] == 1000);myassert(strcmp(szData[2],"updatez")== 0); @@ -740,7 +742,6 @@ rc = SQLSetStmtAttr(hstmt, SQL_ATTR_ROW_ARRAY_SIZE ,(SQLPOINTER)1 , 0); mystmt(hstmt, rc); -#endif } /* @@ -748,11 +749,10 @@ */ void my_zero_irow_update(SQLHDBC hdbc, SQLHSTMT hstmt) { -#if BUG_22796_FIXED SQLRETURN rc; - SQLLEN nlen[15]; + SQLLEN nlen[15]= {0}, nrow[15]= {0}; char szData[15][15]={0}; - long nData[15], nrow[15]; + SQLINTEGER nData[15]; SQLExecDirect(hstmt,"drop table my_zero_irow",SQL_NTS); rc = SQLExecDirect(hstmt,"create table my_zero_irow(col1 int, col2 varchar(30))",SQL_NTS); @@ -789,10 +789,10 @@ rc = SQLExecDirect(hstmt,"select * from my_zero_irow",SQL_NTS); mystmt(hstmt,rc); - rc = SQLBindCol(hstmt,1,SQL_C_LONG,&nData,0,(long *)&nrow); + rc = SQLBindCol(hstmt,1,SQL_C_LONG,&nData,0,nrow); mystmt(hstmt,rc); - rc = SQLBindCol(hstmt,2,SQL_C_CHAR,szData,sizeof(szData[0]),(long *)&nlen); + rc = SQLBindCol(hstmt,2,SQL_C_CHAR,szData,sizeof(szData[0]),nlen); mystmt(hstmt,rc); rc = SQLFetchScroll(hstmt,SQL_FETCH_ABSOLUTE,2); @@ -833,18 +833,16 @@ rc = SQLSetStmtAttr(hstmt, SQL_ATTR_ROW_ARRAY_SIZE ,(SQLPOINTER)1 , 0); mystmt(hstmt, rc); -#endif } /* IROW VALUE - 0 - DELETE */ void my_zero_irow_delete(SQLHDBC hdbc, SQLHSTMT hstmt) { -#if BUG_22796_FIXED SQLRETURN rc; - SQLLEN nlen[15]; + SQLLEN nlen[15]= {0}, nrow[15]= {0}; char szData[15][15]={0}; - long nData[15], nrow[15]; + SQLINTEGER nData[15]; SQLExecDirect(hstmt,"drop table my_zero_irow",SQL_NTS); rc = SQLExecDirect(hstmt,"create table my_zero_irow(col1 int, col2 varchar(30))",SQL_NTS); @@ -881,10 +879,10 @@ rc = SQLExecDirect(hstmt,"select * from my_zero_irow",SQL_NTS); mystmt(hstmt,rc); - rc = SQLBindCol(hstmt,1,SQL_C_LONG,&nData,0,&nrow); + rc = SQLBindCol(hstmt,1,SQL_C_LONG,&nData,0,nrow); mystmt(hstmt,rc); - rc = SQLBindCol(hstmt,2,SQL_C_CHAR,szData,sizeof(szData[0]),(long *)&nlen); + rc = SQLBindCol(hstmt,2,SQL_C_CHAR,szData,sizeof(szData[0]),nlen); mystmt(hstmt,rc); rc = SQLFetchScroll(hstmt,SQL_FETCH_ABSOLUTE,2); @@ -920,7 +918,6 @@ rc = SQLSetStmtAttr(hstmt, SQL_ATTR_ROW_ARRAY_SIZE ,(SQLPOINTER)1 , 0); mystmt(hstmt, rc); -#endif } /** Index: test/keys/my_keys.c =================================================================== --- test/keys/my_keys.c (revision 164) +++ test/keys/my_keys.c (working copy) @@ -532,6 +532,13 @@ */ void my_no_keys_all_dups(SQLHDBC hdbc, SQLHSTMT hstmt) { +#if ALLOW_CRAZY_TESTS + + /* + This test does not make any sense. You can't update a table based + on a cursor against one non-primary-key column. + */ + SQLRETURN rc; SQLLEN rowcount; long nData; @@ -624,6 +631,7 @@ SQLFreeStmt(hstmt,SQL_UNBIND); SQLFreeStmt(hstmt,SQL_CLOSE); +#endif } /* Initialize the foreignkey tables (MySQL specific)