=== modified file 'driver/execute.c' --- driver/execute.c 2010-09-13 16:37:56 +0000 +++ driver/execute.c 2010-09-17 17:46:52 +0000 @@ -727,7 +727,7 @@ SQLRETURN my_SQLExecute( STMT FAR *pStmt ) { char *query, *cursor_pos; - int dae_rec, is_select_stmt; + int dae_rec, is_select_stmt, one_of_params_not_succeded= 0; STMT FAR * pStmtCursor = pStmt; SQLRETURN rc; SQLULEN row, length= 0; @@ -836,11 +836,14 @@ if (is_select_stmt) pthread_mutex_unlock(&pStmt->dbc->lock); + one_of_params_not_succeded= 1; + /* For other errors we continue processing of paramsets So this creates some inconsistency. But I guess that's better that user see diagnostics for this type of error */ break; } + pStmt->current_param= dae_rec; pStmt->dae_type= DAE_NORMAL; return SQL_NEED_DATA; @@ -857,6 +860,11 @@ if (map_error_to_param_status( param_status_ptr, rc)) lastError= param_status_ptr; + if (rc != SQL_SUCCESS) + { + one_of_params_not_succeded= 1; + } + if (!SQL_SUCCEEDED(rc)) { if (pStmt->apd->array_size > 1 && is_select_stmt @@ -889,7 +897,16 @@ { rc= do_query(pStmt, query, length); if (map_error_to_param_status(param_status_ptr, rc)) + { lastError= param_status_ptr; + } + + /* if we have anything but not SQL_SUCCESS for any paramset, we return SQL_SUCCESS_WITH_INFO + as the whole operation result */ + if (rc != SQL_SUCCESS) + { + one_of_params_not_succeded= 1; + } length= 0; } } @@ -917,6 +934,12 @@ if (pStmt->dummy_state == ST_DUMMY_PREPARED) pStmt->dummy_state= ST_DUMMY_EXECUTED; + + if (pStmt->apd->array_size > 1 && one_of_params_not_succeded != 0) + { + return SQL_SUCCESS_WITH_INFO; + } + return rc; } === modified file 'test/my_param.c' --- test/my_param.c 2010-08-19 15:37:55 +0000 +++ test/my_param.c 2010-09-19 18:50:31 +0000 @@ -429,8 +429,9 @@ dataBinding[i].indStr= SQL_NTS; } - ok_stmt(hstmt, SQLExecDirect(hstmt, "INSERT INTO t_bug48310 (bData, intField, strField) " \ - "VALUES (?,?,?)", SQL_NTS)); + /* We don't expect errors in paramsets processing, thus we should get SQL_SUCCESS only*/ + expect_stmt(hstmt, SQLExecDirect(hstmt, "INSERT INTO t_bug48310 (bData, intField, strField) " \ + "VALUES (?,?,?)", SQL_NTS), SQL_SUCCESS); is_num(paramsProcessed, ROWS_TO_INSERT); @@ -526,8 +527,9 @@ ok_stmt(hstmt, SQLBindParameter(hstmt, 3, SQL_PARAM_INPUT, SQL_C_CHAR, SQL_CHAR, 0, 0, (SQLPOINTER)strField, 5, strInd )); - ok_stmt(hstmt, SQLExecDirect(hstmt, "INSERT INTO t_bug48310 (bData, intField, strField) " \ - "VALUES (?,?,?)", SQL_NTS)); + /* We don't expect errors in paramsets processing, thus we should get SQL_SUCCESS only*/ + expect_stmt(hstmt, SQLExecDirect(hstmt, "INSERT INTO t_bug48310 (bData, intField, strField) " \ + "VALUES (?,?,?)", SQL_NTS), SQL_SUCCESS); is_num(paramsProcessed, ROWS_TO_INSERT); @@ -615,8 +617,9 @@ ok_stmt(hstmt, SQLBindParameter(hstmt, 3, SQL_PARAM_INPUT, SQL_C_CHAR, SQL_CHAR, 0, 0, (SQLPOINTER)strField, 5, strInd )); - ok_stmt(hstmt, SQLExecDirect(hstmt, "INSERT INTO t_bug48310 (bData, intField, strField) " \ - "VALUES (?,?,?)", SQL_NTS)); + /* We don't expect errors in paramsets processing, thus we should get SQL_SUCCESS only*/ + expect_stmt(hstmt, SQLExecDirect(hstmt, "INSERT INTO t_bug48310 (bData, intField, strField) " \ + "VALUES (?,?,?)", SQL_NTS), SQL_SUCCESS); is_num(paramsProcessed, ROWS_TO_INSERT); @@ -709,8 +712,8 @@ ok_stmt(hstmt, SQLBindParameter(hstmt, 1, SQL_PARAM_INPUT, SQL_C_LONG, SQL_INTEGER, 0, 0, intField, 0, intInd)); - ok_stmt(hstmt, SQLExecDirect(hstmt, "SELect ?,'So what'", SQL_NTS)); - + /* We don't expect errors in paramsets processing, thus we should get SQL_SUCCESS only*/ + expect_stmt(hstmt, SQLExecDirect(hstmt, "SELect ?,'So what'", SQL_NTS), SQL_SUCCESS); is_num(paramsProcessed, STMTS_TO_EXEC); for (i= 0; i < paramsProcessed; ++i) @@ -762,6 +765,93 @@ } +/* + Bug #56804 - Server with sql mode NO_BACKSLASHES_ESCAPE obviously + can work incorrectly (at least) with binary parameters +*/ +DECLARE_TEST(t_bug56804) +{ +#define PARAMSET_SIZE 10 + + SQLINTEGER len = 1; + int i; + + SQLINTEGER c1[PARAMSET_SIZE]= {0, 1, 2, 3, 4, 5, 1, 7, 8, 9}; + SQLINTEGER c2[PARAMSET_SIZE]= {9, 8, 7, 6, 5, 4, 3, 2, 1, 0}; + SQLLEN d1[PARAMSET_SIZE]= {4, 4, 4, 4, 4, 4, 4, 4, 4, 4}; + SQLLEN d2[PARAMSET_SIZE]= {4, 4, 4, 4, 4, 4, 4, 4, 4, 4}; + SQLUSMALLINT status[PARAMSET_SIZE]= {0, 0, 0, 0, 0, 0, 0, 0, 0, 0}; + + SQLSMALLINT paramset_size = PARAMSET_SIZE; + + ok_sql(hstmt, "DROP TABLE IF EXISTS bug56804"); + ok_sql(hstmt, "create table bug56804 (c1 int primary key not null, c2 int)"); + ok_sql(hstmt, "insert into bug56804 values( 1, 1 ), (9, 9009)"); + + ok_stmt(hstmt, SQLFreeStmt(hstmt, SQL_CLOSE)); + ok_stmt(hstmt, SQLPrepare(hstmt, (SQLCHAR *)"insert into bug56804 values( ?,? )", SQL_NTS)); + + ok_stmt(hstmt, SQLSetStmtAttr( hstmt, SQL_ATTR_PARAMSET_SIZE, + (SQLPOINTER)paramset_size, SQL_IS_UINTEGER )); + + ok_stmt(hstmt, SQLSetStmtAttr( hstmt, SQL_ATTR_PARAM_STATUS_PTR, + status, SQL_IS_POINTER )); + + ok_stmt(hstmt, SQLBindParameter( hstmt, 1, SQL_PARAM_INPUT, SQL_C_SLONG, + SQL_DECIMAL, 4, 0, c1, 4, d1)); + + ok_stmt(hstmt, SQLBindParameter( hstmt, 2, SQL_PARAM_INPUT, SQL_C_SLONG, + SQL_DECIMAL, 4, 0, c2, 4, d2)); + + expect_stmt(hstmt, SQLExecute(hstmt), SQL_SUCCESS_WITH_INFO); + + /* Following tests are here to ensure that driver works how it is currently + expected to work an they need to be changed if driver changes smth in the + way how it reports errors in paramsets and diagnostics */ + for(i = 0; i < PARAMSET_SIZE; ++i ) + { + switch (i) + { + case 1: + case 6: + /* all errors but last have SQL_PARAM_DIAG_UNAVAILABLE */ + is_num(status[i], SQL_PARAM_DIAG_UNAVAILABLE); + break; + case 9: + /* Last error - we are supposed to get SQL_PARAM_ERROR for it */ + is_num(status[i], SQL_PARAM_ERROR); + break; + default: + is_num(status[i], SQL_PARAM_SUCCESS); + } + } + + { + SQLCHAR sqlstate[6]= {0}; + SQLCHAR message[255]= {0}; + SQLINTEGER native_err= 0; + SQLSMALLINT msglen= 0; + + i= 0; + while(SQL_SUCCEEDED(SQLGetDiagRec(SQL_HANDLE_STMT, hstmt, ++i, sqlstate, + &native_err, message, sizeof(message), &msglen))) + { + printMessage("%d) [%s] %s %d", i, sqlstate, message, native_err); + } + + /* just to make sure we got 1 diagnostics record ... */ + is_num(i, 2); + /* ... and what the record is for the last error */ + is(strstr(message, "Duplicate entry '9'")); + } + + ok_stmt(hstmt, SQLFreeStmt(hstmt, SQL_CLOSE)); + ok_sql(hstmt, "DROP TABLE IF EXISTS bug56804"); + + return OK; +#undef PARAMSET_SIZE +} + BEGIN_TESTS ADD_TEST(my_init_table) ADD_TEST(my_param_insert) @@ -774,6 +864,7 @@ ADD_TEST(paramarray_ignore_paramset) ADD_TEST(paramarray_select) ADD_TEST(t_bug49029) + ADD_TEST(t_bug56804) END_TESTS