From 6ca757544b78095e88c0ba765dfb66d100a1eb71 Mon Sep 17 00:00:00 2001 From: unknown Date: Tue, 4 May 2004 19:08:19 +0400 Subject: Fix for remaining issues described in Bug #1664 "mysql_send_long_data() API call is completely broken". Now we are resetting some members (long_data_supplied/null_value...) of Item_param to its initial state after each execution of prepared statement. We also manipulating Item_param::maybe_null/null_value only via Item_param::set_* setters which makes code a bit more robust. sql/item.cc: Now we are assuming that Item_param may be NULL until we know this fact exactly. Added non-empty implementation of Item_param::reset() method which should be used for restoring Item_param state after each statment execution. (We need to clear long_data_supplied flag, we also clear some other Item_param members here since it makes code simpler.) sql/item.h: Now Item_param::reset() method really does something. sql/sql_prepare.cc: Now we are calling Item_param::reset() for each parameter after execution for resetting Item_param to initial state. So we no longer don't need Prepared_statement::long_data_flag. We also set Item_param::null_value/maybe_null value in Item_param::set_* and reset() methods instead of doing it explicitly in insert_params_* functions (this by the way lowers probability that we will forget to update one of such functions). tests/client_test.c: Added test for Bug#1664 "mysql_send_long_data() API call is broken". --- tests/client_test.c | 147 ++++++++++++++++++++++++++++++++++++++++++++++++++++ 1 file changed, 147 insertions(+) (limited to 'tests') diff --git a/tests/client_test.c b/tests/client_test.c index 7d7b21bd4bf..475e3dc8cce 100644 --- a/tests/client_test.c +++ b/tests/client_test.c @@ -9101,6 +9101,152 @@ static void test_xjoin() } +/* + This tests for various mysql_send_long_data bugs described in #1664 +*/ + +static void test_bug1664() +{ + MYSQL_STMT *stmt; + int rc, int_data; + const char *data; + const char *str_data= "Simple string"; + MYSQL_BIND bind[2]; + const char *query= "INSERT INTO test_long_data(col2, col1) VALUES(?,?)"; + + myheader("test_bug1664"); + + rc= mysql_query(mysql,"DROP TABLE IF EXISTS test_long_data"); + myquery(rc); + + rc= mysql_query(mysql,"CREATE TABLE test_long_data(col1 int, col2 long varchar)"); + myquery(rc); + + stmt= mysql_stmt_init(mysql); + mystmt_init(stmt); + rc= mysql_stmt_prepare(stmt, query, strlen(query)); + mystmt(stmt, rc); + + verify_param_count(stmt, 2); + + bzero(&bind, sizeof(bind)); + + bind[0].buffer_type= FIELD_TYPE_STRING; + bind[0].buffer= (char *)str_data; + bind[0].buffer_length= strlen(str_data); + + bind[1].buffer= (char *)&int_data; + bind[1].buffer_type= FIELD_TYPE_LONG; + + rc= mysql_stmt_bind_param(stmt,bind); + mystmt(stmt, rc); + + int_data= 1; + + /* + Let us supply empty long_data. This should work and should + not break following execution. + */ + data= ""; + rc= mysql_stmt_send_long_data(stmt,0,data,strlen(data)); + mystmt(stmt,rc); + + rc= mysql_stmt_execute(stmt); + fprintf(stdout," mysql_execute() returned %d\n",rc); + mystmt(stmt,rc); + + verify_col_data("test_long_data","col1","1"); + verify_col_data("test_long_data","col2",""); + + rc= mysql_query(mysql,"DELETE FROM test_long_data"); + myquery(rc); + + /* This should pass OK */ + data= (char *)"Data"; + rc= mysql_stmt_send_long_data(stmt, 0, data, strlen(data)); + mystmt(stmt, rc); + + rc= mysql_stmt_execute(stmt); + fprintf(stdout," mysql_execute() returned %d\n",rc); + mystmt(stmt, rc); + + verify_col_data("test_long_data", "col1", "1"); + verify_col_data("test_long_data", "col2", "Data"); + + /* clean up */ + rc= mysql_query(mysql, "DELETE FROM test_long_data"); + myquery(rc); + + /* + Now we are changing int parameter and don't do anything + with first parameter. Second mysql_execute() should run + OK treating this first parameter as string parameter. + */ + + int_data= 2; + /* execute */ + rc = mysql_stmt_execute(stmt); + fprintf(stdout, " mysql_execute() returned %d\n", rc); + mystmt(stmt, rc); + + verify_col_data("test_long_data", "col1", "2"); + verify_col_data("test_long_data", "col2", str_data); + + /* clean up */ + rc= mysql_query(mysql, "DELETE FROM test_long_data"); + myquery(rc); + + /* + Now we are sending other long data. It should not be + concatened to previous. + */ + + data= (char *)"SomeOtherData"; + rc= mysql_stmt_send_long_data(stmt, 0, data, strlen(data)); + mystmt(stmt, rc); + + rc= mysql_stmt_execute(stmt); + fprintf(stdout, " mysql_execute() returned %d\n", rc); + mystmt(stmt, rc); + + verify_col_data("test_long_data", "col1", "2"); + verify_col_data("test_long_data", "col2", "SomeOtherData"); + + mysql_stmt_close(stmt); + + /* clean up */ + rc= mysql_query(mysql, "DELETE FROM test_long_data"); + myquery(rc); + + /* Now let us test how mysql_stmt_reset works. */ + stmt= mysql_stmt_init(mysql); + mystmt_init(stmt); + rc= mysql_stmt_prepare(stmt, query, strlen(query)); + mystmt(stmt, rc); + rc= mysql_bind_param(stmt, bind); + mystmt(stmt, rc); + + data= (char *)"SomeData"; + rc= mysql_stmt_send_long_data(stmt, 0, data, strlen(data)); + mystmt(stmt, rc); + + rc= mysql_stmt_reset(stmt); + mystmt(stmt, rc); + + rc= mysql_stmt_execute(stmt); + fprintf(stdout," mysql_execute() returned %d\n",rc); + mystmt(stmt, rc); + + verify_col_data("test_long_data", "col1", "2"); + verify_col_data("test_long_data", "col2", str_data); + + mysql_stmt_close(stmt); + + /* Final clean up */ + rc= mysql_query(mysql, "DROP TABLE test_long_data"); + myquery(rc); +} + /* Read and parse arguments and MySQL options from my.cnf */ @@ -9373,6 +9519,7 @@ int main(int argc, char **argv) test_bind_nagative(); /* bind negative to unsigned BUG#3223 */ test_derived(); /* derived table with parameter BUG#3020 */ test_xjoin(); /* complex join test */ + test_bug1664(); end_time= time((time_t *)0); total_time+= difftime(end_time, start_time); -- cgit v1.2.1