Loading sql/sql_cursor.cc +18 −8 Original line number Diff line number Diff line Loading @@ -558,6 +558,24 @@ int Materialized_cursor::open(JOIN *join __attribute__((unused))) result->prepare(item_list, &fake_unit) || table->file->ha_rnd_init(TRUE)); thd->restore_active_arena(this, &backup_arena); if (rc == 0) { /* Now send the result set metadata to the client. We need to do it here, as in Select_materialize::send_fields the exact column types are not yet known. The new types may differ from the original ones sent at prepare if some of them were altered by MySQL HEAP tables mechanism -- used when create_tmp_field_from_item may alter the original column type. We can't simply supply SEND_EOF flag to send_fields, because send_fields doesn't flush the network buffer. */ rc= result->send_fields(item_list, Protocol::SEND_NUM_ROWS); thd->server_status|= SERVER_STATUS_CURSOR_EXISTS; result->send_eof(); thd->server_status&= ~SERVER_STATUS_CURSOR_EXISTS; } return rc; } Loading Loading @@ -647,14 +665,6 @@ bool Select_materialize::send_fields(List<Item> &list, uint flags) if (create_result_table(unit->thd, unit->get_unit_column_types(), FALSE, thd->options | TMP_TABLE_ALL_COLUMNS, "")) return TRUE; /* We can't simply supply SEND_EOF flag to send_fields, because send_fields doesn't flush the network buffer. */ rc= result->send_fields(list, Protocol::SEND_NUM_ROWS); thd->server_status|= SERVER_STATUS_CURSOR_EXISTS; result->send_eof(); thd->server_status&= ~SERVER_STATUS_CURSOR_EXISTS; return rc; } tests/mysql_client_test.c +69 −0 Original line number Diff line number Diff line Loading @@ -14419,6 +14419,74 @@ static void test_bug14210() myquery(rc); } /* Bug#13488 */ static void test_bug13488() { MYSQL_BIND bind[3]; MYSQL_STMT *stmt1; int rc, f1, f2, f3, i; const ulong type= CURSOR_TYPE_READ_ONLY; const char *query= "select * from t1 left join t2 on f1=f2 where f1=1"; myheader("test_bug13488"); rc= mysql_query(mysql, "drop table if exists t1, t2"); myquery(rc); rc= mysql_query(mysql, "create table t1 (f1 int not null primary key)"); myquery(rc); rc= mysql_query(mysql, "create table t2 (f2 int not null primary key, " "f3 int not null)"); myquery(rc); rc= mysql_query(mysql, "insert into t1 values (1), (2)"); myquery(rc); rc= mysql_query(mysql, "insert into t2 values (1,2), (2,4)"); myquery(rc); memset(bind, 0, sizeof(bind)); for (i= 0; i < 3; i++) { bind[i].buffer_type= MYSQL_TYPE_LONG; bind[i].buffer_length= 4; bind[i].length= 0; } bind[0].buffer=&f1; bind[1].buffer=&f2; bind[2].buffer=&f3; stmt1= mysql_stmt_init(mysql); rc= mysql_stmt_attr_set(stmt1,STMT_ATTR_CURSOR_TYPE, (const void *)&type); check_execute(stmt1, rc); rc= mysql_stmt_prepare(stmt1, query, strlen(query)); check_execute(stmt1, rc); rc= mysql_stmt_execute(stmt1); check_execute(stmt1, rc); rc= mysql_stmt_bind_result(stmt1, bind); check_execute(stmt1, rc); rc= mysql_stmt_fetch(stmt1); check_execute(stmt1, rc); rc= mysql_stmt_free_result(stmt1); check_execute(stmt1, rc); rc= mysql_stmt_reset(stmt1); check_execute(stmt1, rc); rc= mysql_stmt_close(stmt1); check_execute(stmt1, rc); if (!opt_silent) printf("data is: %s", (f1 == 1 && f2 == 1 && f3 == 2)?"OK": "wrong"); DIE_UNLESS(f1 == 1 && f2 == 1 && f3 == 2); rc= mysql_query(mysql, "drop table t1, t2"); myquery(rc); } /* Read and parse arguments and MySQL options from my.cnf */ Loading Loading @@ -14675,6 +14743,7 @@ static struct my_tests_st my_tests[]= { { "test_bug11904", test_bug11904 }, { "test_bug12243", test_bug12243 }, { "test_bug14210", test_bug14210 }, { "test_bug13488", test_bug13488 }, { 0, 0 } }; Loading Loading
sql/sql_cursor.cc +18 −8 Original line number Diff line number Diff line Loading @@ -558,6 +558,24 @@ int Materialized_cursor::open(JOIN *join __attribute__((unused))) result->prepare(item_list, &fake_unit) || table->file->ha_rnd_init(TRUE)); thd->restore_active_arena(this, &backup_arena); if (rc == 0) { /* Now send the result set metadata to the client. We need to do it here, as in Select_materialize::send_fields the exact column types are not yet known. The new types may differ from the original ones sent at prepare if some of them were altered by MySQL HEAP tables mechanism -- used when create_tmp_field_from_item may alter the original column type. We can't simply supply SEND_EOF flag to send_fields, because send_fields doesn't flush the network buffer. */ rc= result->send_fields(item_list, Protocol::SEND_NUM_ROWS); thd->server_status|= SERVER_STATUS_CURSOR_EXISTS; result->send_eof(); thd->server_status&= ~SERVER_STATUS_CURSOR_EXISTS; } return rc; } Loading Loading @@ -647,14 +665,6 @@ bool Select_materialize::send_fields(List<Item> &list, uint flags) if (create_result_table(unit->thd, unit->get_unit_column_types(), FALSE, thd->options | TMP_TABLE_ALL_COLUMNS, "")) return TRUE; /* We can't simply supply SEND_EOF flag to send_fields, because send_fields doesn't flush the network buffer. */ rc= result->send_fields(list, Protocol::SEND_NUM_ROWS); thd->server_status|= SERVER_STATUS_CURSOR_EXISTS; result->send_eof(); thd->server_status&= ~SERVER_STATUS_CURSOR_EXISTS; return rc; }
tests/mysql_client_test.c +69 −0 Original line number Diff line number Diff line Loading @@ -14419,6 +14419,74 @@ static void test_bug14210() myquery(rc); } /* Bug#13488 */ static void test_bug13488() { MYSQL_BIND bind[3]; MYSQL_STMT *stmt1; int rc, f1, f2, f3, i; const ulong type= CURSOR_TYPE_READ_ONLY; const char *query= "select * from t1 left join t2 on f1=f2 where f1=1"; myheader("test_bug13488"); rc= mysql_query(mysql, "drop table if exists t1, t2"); myquery(rc); rc= mysql_query(mysql, "create table t1 (f1 int not null primary key)"); myquery(rc); rc= mysql_query(mysql, "create table t2 (f2 int not null primary key, " "f3 int not null)"); myquery(rc); rc= mysql_query(mysql, "insert into t1 values (1), (2)"); myquery(rc); rc= mysql_query(mysql, "insert into t2 values (1,2), (2,4)"); myquery(rc); memset(bind, 0, sizeof(bind)); for (i= 0; i < 3; i++) { bind[i].buffer_type= MYSQL_TYPE_LONG; bind[i].buffer_length= 4; bind[i].length= 0; } bind[0].buffer=&f1; bind[1].buffer=&f2; bind[2].buffer=&f3; stmt1= mysql_stmt_init(mysql); rc= mysql_stmt_attr_set(stmt1,STMT_ATTR_CURSOR_TYPE, (const void *)&type); check_execute(stmt1, rc); rc= mysql_stmt_prepare(stmt1, query, strlen(query)); check_execute(stmt1, rc); rc= mysql_stmt_execute(stmt1); check_execute(stmt1, rc); rc= mysql_stmt_bind_result(stmt1, bind); check_execute(stmt1, rc); rc= mysql_stmt_fetch(stmt1); check_execute(stmt1, rc); rc= mysql_stmt_free_result(stmt1); check_execute(stmt1, rc); rc= mysql_stmt_reset(stmt1); check_execute(stmt1, rc); rc= mysql_stmt_close(stmt1); check_execute(stmt1, rc); if (!opt_silent) printf("data is: %s", (f1 == 1 && f2 == 1 && f3 == 2)?"OK": "wrong"); DIE_UNLESS(f1 == 1 && f2 == 1 && f3 == 2); rc= mysql_query(mysql, "drop table t1, t2"); myquery(rc); } /* Read and parse arguments and MySQL options from my.cnf */ Loading Loading @@ -14675,6 +14743,7 @@ static struct my_tests_st my_tests[]= { { "test_bug11904", test_bug11904 }, { "test_bug12243", test_bug12243 }, { "test_bug14210", test_bug14210 }, { "test_bug13488", test_bug13488 }, { 0, 0 } }; Loading