diff options
-rw-r--r-- | sql/sql_lex.cc | 1 | ||||
-rw-r--r-- | sql/sql_union.cc | 33 | ||||
-rw-r--r-- | tests/client_test.c | 60 |
3 files changed, 81 insertions, 13 deletions
diff --git a/sql/sql_lex.cc b/sql/sql_lex.cc index 757eb4fdc7d..5d4fcaa4c57 100644 --- a/sql/sql_lex.cc +++ b/sql/sql_lex.cc @@ -1004,6 +1004,7 @@ void st_select_lex_unit::init_query() table= 0; fake_select_lex= 0; cleaned= 0; + item_list.empty(); } void st_select_lex::init_query() diff --git a/sql/sql_union.cc b/sql/sql_union.cc index 87f70bcbd3a..1ad783649f3 100644 --- a/sql/sql_union.cc +++ b/sql/sql_union.cc @@ -226,13 +226,23 @@ int st_select_lex_unit::prepare(THD *thd_arg, select_result *sel_result, thd_arg->lex->current_select= lex_select_save; { + Statement *stmt= thd->current_statement; + Statement backup; + if (stmt) + thd->set_n_backup_item_arena(stmt, &backup); Field **field; for (field= table->field; *field; field++) { Item_field *item= new Item_field(*field); if (!item || item_list.push_back(item)) + { + if (stmt) + thd->restore_backup_item_arena(stmt, &backup); DBUG_RETURN(-1); + } } + if (stmt) + thd->restore_backup_item_arena(stmt, &backup); } } else @@ -427,7 +437,7 @@ int st_select_lex_unit::cleanup() { DBUG_RETURN(0); } - cleaned= 0; + cleaned= 1; if (union_result) { @@ -461,16 +471,19 @@ void st_select_lex_unit::reinit_exec_mechanism() { prepared= optimized= executed= 0; #ifndef DBUG_OFF - List_iterator_fast<Item> it(item_list); - Item_field *field; - while ((field= (Item_field *)it++)) + if (first_select()->next_select()) { - /* - we can't cleanup here, because it broke link to temporary table field, - but have to drop fixed flag to allow next fix_field of this field - during re-executing - */ - field->fixed= 0; + List_iterator_fast<Item> it(item_list); + Item *field; + while ((field= it++)) + { + /* + we can't cleanup here, because it broke link to temporary table field, + but have to drop fixed flag to allow next fix_field of this field + during re-executing + */ + field->fixed= 0; + } } #endif } diff --git a/tests/client_test.c b/tests/client_test.c index 31a53f6d81e..5aa48255a64 100644 --- a/tests/client_test.c +++ b/tests/client_test.c @@ -160,7 +160,10 @@ static void print_st_error(MYSQL_STMT *stmt, const char *msg) MYSQL_STMT *STDCALL mysql_simple_prepare(MYSQL *mysql, const char *query) { - return mysql_prepare(mysql, query, strlen(query)); + MYSQL_STMT *stmt= mysql_stmt_init(mysql); + if (mysql_stmt_prepare(stmt, query, strlen(query))) + return 0; + return stmt; } @@ -8377,6 +8380,58 @@ static void test_subqueries_ref() myquery(rc); } + +static void test_union() +{ + MYSQL_STMT *stmt; + int rc; + + myheader("test_union"); + + rc= mysql_query(mysql, "DROP TABLE IF EXISTS t1, t2"); + myquery(rc); + + rc= mysql_query(mysql, + "CREATE TABLE t1 " + "(id INTEGER NOT NULL PRIMARY KEY, " + " name VARCHAR(20) NOT NULL)"); + myquery(rc); + rc= mysql_query(mysql, + "INSERT INTO t1 (id, name) VALUES " + "(2, 'Ja'), (3, 'Ede'), " + "(4, 'Haag'), (5, 'Kabul'), " + "(6, 'Almere'), (7, 'Utrecht'), " + "(8, 'Qandahar'), (9, 'Amsterdam'), " + "(10, 'Amersfoort'), (11, 'Constantine')"); + myquery(rc); + rc= mysql_query(mysql, + "CREATE TABLE t2 " + "(id INTEGER NOT NULL PRIMARY KEY, " + " name VARCHAR(20) NOT NULL)"); + myquery(rc); + rc= mysql_query(mysql, + "INSERT INTO t2 (id, name) VALUES " + "(4, 'Guam'), (5, 'Aruba'), " + "(6, 'Angola'), (7, 'Albania'), " + "(8, 'Anguilla'), (9, 'Argentina'), " + "(10, 'Azerbaijan'), (11, 'Afghanistan'), " + "(12, 'Burkina Faso'), (13, 'Faroe Islands')"); + myquery(rc); + + stmt= mysql_simple_prepare(mysql, + "SELECT t1.name FROM t1 UNION " + "SELECT t2.name FROM t2"); + mystmt_init(stmt); + + rc= mysql_stmt_execute(stmt); + mystmt(stmt,rc); + assert(20 == my_process_stmt_result(stmt)); + mysql_stmt_close(stmt); + + rc= mysql_query(mysql, "DROP TABLE t1, t2"); + myquery(rc); +} + /* Read and parse arguments and MySQL options from my.cnf */ @@ -8634,8 +8689,7 @@ int main(int argc, char **argv) test_distinct(); /* distinct aggregate functions */ test_subqueries_ref(); /* outer reference in subqueries converted Item_field -> Item_ref */ - - + test_union(); /* test union with prepared statements */ end_time= time((time_t *)0); total_time+= difftime(end_time, start_time); |