diff --git a/sql/sql_prepare.cc b/sql/sql_prepare.cc index 18707cc6c87..0861bd1b0b2 100644 --- a/sql/sql_prepare.cc +++ b/sql/sql_prepare.cc @@ -88,6 +88,7 @@ class Prepared_statement: public Statement { public: THD *thd; + Protocol *protocol; Item_param **param_array; uint param_count; uint last_errno; @@ -2021,6 +2022,7 @@ void mysql_stmt_execute(THD *thd, char *packet, uint packet_length) DBUG_VOID_RETURN; /* If lex->result is set, mysql_execute_command will use it */ stmt->lex->result= &cursor->result; + stmt->protocol= &cursor->protocol; thd->lock_id= &cursor->lock_id; } } @@ -2055,7 +2057,7 @@ void mysql_stmt_execute(THD *thd, char *packet, uint packet_length) } mysql_log.write(thd, thd->command, "[%lu] %s", stmt->id, thd->query); - thd->protocol= &thd->protocol_prep; // Switch to binary protocol + thd->protocol= stmt->protocol; // Switch to binary protocol if (!(specialflag & SPECIAL_NO_PRIOR)) my_pthread_setprio(pthread_self(),QUERY_PRIOR); mysql_execute_command(thd); @@ -2247,7 +2249,7 @@ void mysql_stmt_fetch(THD *thd, char *packet, uint packet_length) if (!(specialflag & SPECIAL_NO_PRIOR)) my_pthread_setprio(pthread_self(), QUERY_PRIOR); - thd->protocol= &thd->protocol_prep; // Switch to binary protocol + thd->protocol= stmt->protocol; // Switch to binary protocol cursor->fetch(num_rows); thd->protocol= &thd->protocol_simple; // Use normal protocol @@ -2419,6 +2421,7 @@ Prepared_statement::Prepared_statement(THD *thd_arg) thd_arg->variables.query_alloc_block_size, thd_arg->variables.query_prealloc_size), thd(thd_arg), + protocol(&thd_arg->protocol_prep), param_array(0), param_count(0), last_errno(0) diff --git a/sql/sql_select.cc b/sql/sql_select.cc index 1f89f04a19a..137e422a7d3 100644 --- a/sql/sql_select.cc +++ b/sql/sql_select.cc @@ -1715,6 +1715,7 @@ JOIN::destroy() Cursor::Cursor(THD *thd) :Query_arena(&main_mem_root, INITIALIZED), join(0), unit(0), + protocol(thd), close_at_commit(FALSE) { /* We will overwrite it at open anyway. */ diff --git a/sql/sql_select.h b/sql/sql_select.h index 1fa246370c6..c950444e1c6 100644 --- a/sql/sql_select.h +++ b/sql/sql_select.h @@ -396,6 +396,7 @@ class Cursor: public Sql_alloc, public Query_arena }; Engine_info ht_info[MAX_HA]; public: + Protocol_prep protocol; Item_change_list change_list; select_send result; THR_LOCK_OWNER lock_id; diff --git a/tests/mysql_client_test.c b/tests/mysql_client_test.c index 53708a7a741..5e6de152f40 100644 --- a/tests/mysql_client_test.c +++ b/tests/mysql_client_test.c @@ -13932,6 +13932,125 @@ static void test_bug12001() DIE_UNLESS(res==1); } + +/* Bug#11909: wrong metadata if fetching from two cursors */ + +static void test_bug11909() +{ + MYSQL_STMT *stmt1, *stmt2; + MYSQL_BIND bind[7]; + int rc; + char firstname[20], midinit[20], lastname[20], workdept[20]; + ulong firstname_len, midinit_len, lastname_len, workdept_len; + uint32 empno; + double salary; + float bonus; + const char *stmt_text; + + myheader("test_bug11909"); + + stmt_text= "drop table if exists t1"; + rc= mysql_real_query(mysql, stmt_text, strlen(stmt_text)); + myquery(rc); + + stmt_text= "create table t1 (" + " empno int(11) not null, firstname varchar(20) not null," + " midinit varchar(20) not null, lastname varchar(20) not null," + " workdept varchar(6) not null, salary double not null," + " bonus float not null, primary key (empno)" + ") default charset=latin1 collate=latin1_bin"; + rc= mysql_real_query(mysql, stmt_text, strlen(stmt_text)); + myquery(rc); + + stmt_text= "insert into t1 values " + "(10, 'CHRISTINE', 'I', 'HAAS', 'A00', 52750, 1000), " + "(20, 'MICHAEL', 'L', 'THOMPSON', 'B01', 41250, 800)," + "(30, 'SALLY', 'A', 'KWAN', 'C01', 38250, 800)," + "(50, 'JOHN', 'B', 'GEYER', 'E01', 40175, 800), " + "(60, 'IRVING', 'F', 'STERN', 'D11', 32250, 500)"; + rc= mysql_real_query(mysql, stmt_text, strlen(stmt_text)); + myquery(rc); + + /* ****** Begin of trace ****** */ + + stmt1= open_cursor("SELECT empno, firstname, midinit, lastname," + "workdept, salary, bonus FROM t1"); + + bzero(bind, sizeof(bind)); + bind[0].buffer_type= MYSQL_TYPE_LONG; + bind[0].buffer= (void*) &empno; + + bind[1].buffer_type= MYSQL_TYPE_VAR_STRING; + bind[1].buffer= (void*) firstname; + bind[1].buffer_length= sizeof(firstname); + bind[1].length= &firstname_len; + + bind[2].buffer_type= MYSQL_TYPE_VAR_STRING; + bind[2].buffer= (void*) midinit; + bind[2].buffer_length= sizeof(midinit); + bind[2].length= &midinit_len; + + bind[3].buffer_type= MYSQL_TYPE_VAR_STRING; + bind[3].buffer= (void*) lastname; + bind[3].buffer_length= sizeof(lastname); + bind[3].length= &lastname_len; + + bind[4].buffer_type= MYSQL_TYPE_VAR_STRING; + bind[4].buffer= (void*) workdept; + bind[4].buffer_length= sizeof(workdept); + bind[4].length= &workdept_len; + + bind[5].buffer_type= MYSQL_TYPE_DOUBLE; + bind[5].buffer= (void*) &salary; + + bind[6].buffer_type= MYSQL_TYPE_FLOAT; + bind[6].buffer= (void*) &bonus; + rc= mysql_stmt_bind_result(stmt1, bind); + check_execute(stmt1, rc); + + rc= mysql_stmt_execute(stmt1); + check_execute(stmt1, rc); + + rc= mysql_stmt_fetch(stmt1); + DIE_UNLESS(rc == 0); + DIE_UNLESS(empno == 10); + DIE_UNLESS(strcmp(firstname, "CHRISTINE") == 0); + DIE_UNLESS(strcmp(midinit, "I") == 0); + DIE_UNLESS(strcmp(lastname, "HAAS") == 0); + DIE_UNLESS(strcmp(workdept, "A00") == 0); + DIE_UNLESS(salary == (double) 52750.0); + DIE_UNLESS(bonus == (float) 1000.0); + + stmt2= open_cursor("SELECT empno, firstname FROM t1"); + rc= mysql_stmt_bind_result(stmt2, bind); + check_execute(stmt2, rc); + + rc= mysql_stmt_execute(stmt2); + check_execute(stmt2, rc); + + rc= mysql_stmt_fetch(stmt2); + DIE_UNLESS(rc == 0); + + DIE_UNLESS(empno == 10); + DIE_UNLESS(strcmp(firstname, "CHRISTINE") == 0); + + rc= mysql_stmt_reset(stmt2); + check_execute(stmt2, rc); + + /* ERROR: next statement should return 0 */ + + rc= mysql_stmt_fetch(stmt1); + DIE_UNLESS(rc == 0); + + mysql_stmt_close(stmt1); + mysql_stmt_close(stmt2); + rc= mysql_rollback(mysql); + myquery(rc); + + rc= mysql_query(mysql, "drop table t1"); + myquery(rc); +} + /* Read and parse arguments and MySQL options from my.cnf */ @@ -14178,6 +14297,7 @@ static struct my_tests_st my_tests[]= { { "test_bug11037", test_bug11037 }, { "test_bug10760", test_bug10760 }, { "test_bug12001", test_bug12001 }, + { "test_bug11909", test_bug11909 }, { 0, 0 } };