From fab7113f8398ba41d5e54e32dc0b3259a6297dfc Mon Sep 17 00:00:00 2001 From: unknown Date: Thu, 12 Feb 2004 18:50:00 +0200 Subject: [PATCH] PS fixed to be compatible with derived tables (BUG#2641) sql/mysql_priv.h: description moved to be accessable from sql_class.h sql/sql_base.cc: put all derived table preparation in temporary memory pull sql/sql_class.h: close tables to close derived tables before freeing memory pool where they are placed sql/sql_prepare.cc: now temporary memory pool for prrepared statements registration is oppened in open_and_lock_tables thd->current_statement set only for tables preparation, because we do not need memory pool tricks for PS executing tests/client_test.c: derived table added to test expression with aggregate functions added to test --- sql/mysql_priv.h | 3 +- sql/sql_base.cc | 8 ++++++ sql/sql_class.h | 1 + sql/sql_prepare.cc | 68 +++++++++++++++++++++++++++++++-------------- tests/client_test.c | 17 ++++++------ 5 files changed, 67 insertions(+), 30 deletions(-) diff --git a/sql/mysql_priv.h b/sql/mysql_priv.h index 3e76a32577c..73cc8b9ce03 100644 --- a/sql/mysql_priv.h +++ b/sql/mysql_priv.h @@ -350,6 +350,8 @@ typedef Comp_creator* (*chooser_compare_func_creator)(bool invert); /* sql_parse.cc */ void free_items(Item *item); void cleanup_items(Item *item); +class THD; +void close_thread_tables(THD *thd, bool locked=0, bool skip_derived=0); #include "sql_class.h" #include "opt_range.h" @@ -687,7 +689,6 @@ bool rm_temporary_table(enum db_type base, char *path); void free_io_cache(TABLE *entry); void intern_close_table(TABLE *entry); bool close_thread_table(THD *thd, TABLE **table_ptr); -void close_thread_tables(THD *thd, bool locked=0, bool skip_derived=0); void close_temporary_tables(THD *thd); TABLE_LIST * find_table_in_list(TABLE_LIST *table, const char *db_name, const char *table_name); diff --git a/sql/sql_base.cc b/sql/sql_base.cc index 4c6ca0fde76..3a09a8fbc8e 100644 --- a/sql/sql_base.cc +++ b/sql/sql_base.cc @@ -1590,6 +1590,14 @@ int open_and_lock_tables(THD *thd, TABLE_LIST *tables) if (open_tables(thd, tables, &counter) || lock_tables(thd, tables, counter)) DBUG_RETURN(-1); /* purecov: inspected */ fix_tables_pointers(thd->lex->all_selects_list); + + /* + open temporary memory pool, which will be closed in + mysql_test_select_fields, mysql_test_upd_fields or + mysql_test_insert_fields + */ + if (thd->current_statement) + thd->ps_setup_prepare_memory(); DBUG_RETURN(mysql_handle_derived(thd->lex)); } diff --git a/sql/sql_class.h b/sql/sql_class.h index 0d75575f6b7..93703acc97b 100644 --- a/sql/sql_class.h +++ b/sql/sql_class.h @@ -934,6 +934,7 @@ public: DBUG_ASSERT(current_statement!=0); cleanup_items(current_statement->free_list); free_items(free_list); + close_thread_tables(this); // to close derived tables free_root(&mem_root, MYF(0)); set_item_arena(current_statement); } diff --git a/sql/sql_prepare.cc b/sql/sql_prepare.cc index 34ccb67cda9..9be11b6154c 100644 --- a/sql/sql_prepare.cc +++ b/sql/sql_prepare.cc @@ -622,7 +622,12 @@ static bool mysql_test_insert_fields(Prepared_statement *stmt, DBUG_RETURN(1); #endif if (open_and_lock_tables(thd, table_list)) - DBUG_RETURN(1); + { + // this memory pool was opened in open_and_lock_tables + thd->ps_setup_free_memory(); + DBUG_RETURN(1); + } + table= table_list->table; if ((values= its++)) @@ -630,12 +635,12 @@ static bool mysql_test_insert_fields(Prepared_statement *stmt, uint value_count; ulong counter= 0; - thd->ps_setup_prepare_memory(); if (check_insert_fields(thd,table,fields,*values,1)) { thd->ps_setup_free_memory(); DBUG_RETURN(1); } + // this memory pool was opened in open_and_lock_tables thd->ps_setup_free_memory(); value_count= values->elements; @@ -653,6 +658,11 @@ static bool mysql_test_insert_fields(Prepared_statement *stmt, } } } + else + { + // this memory pool was opened in open_and_lock_tables + thd->ps_setup_free_memory(); + } if (send_prep_stmt(stmt, 0)) DBUG_RETURN(1); DBUG_RETURN(0); @@ -683,16 +693,21 @@ static bool mysql_test_upd_fields(Prepared_statement *stmt, DBUG_RETURN(1); #endif if (open_and_lock_tables(thd, table_list)) + { + // this memory pool was opened in open_and_lock_tables + thd->ps_setup_free_memory(); DBUG_RETURN(1); + } - thd->ps_setup_prepare_memory(); if (setup_tables(table_list, 0) || setup_fields(thd, 0, table_list, fields, 1, 0, 0) || setup_conds(thd, table_list, &conds) || thd->net.report_error) { + // this memory pool was opened in open_and_lock_tables thd->ps_setup_free_memory(); DBUG_RETURN(1); } + // this memory pool was opened in open_and_lock_tables thd->ps_setup_free_memory(); /* @@ -748,44 +763,50 @@ static bool mysql_test_select_fields(Prepared_statement *stmt, DBUG_RETURN(1); if (open_and_lock_tables(thd, tables)) + { + // this memory pool was opened in open_and_lock_tables + thd->ps_setup_free_memory(); DBUG_RETURN(1); + } if (lex->describe) { if (send_prep_stmt(stmt, 0)) - DBUG_RETURN(1); + goto err; } else { if (!result && !(result= new select_send())) { send_error(thd, ER_OUT_OF_RESOURCES); - DBUG_RETURN(1); + goto err; } thd->used_tables= 0; // Updated by setup_fields - thd->ps_setup_prepare_memory(); if (unit->prepare(thd, result, 0)) - { - unit->cleanup(); - thd->ps_setup_free_memory(); - DBUG_RETURN(1); - } - + goto err_prep; + if (send_prep_stmt(stmt, fields.elements) || thd->protocol_simple.send_fields(&fields, 0) #ifndef EMBEDDED_LIBRARY || net_flush(&thd->net) #endif ) - { - DBUG_RETURN(1); - } + goto err_prep; + unit->cleanup(); - thd->ps_setup_free_memory(); } - DBUG_RETURN(0); + // this memory pool was opened in open_and_lock_tables + thd->ps_setup_free_memory(); + DBUG_RETURN(0); + +err_prep: + unit->cleanup(); +err: + // this memory pool was opened in open_and_lock_tables + thd->ps_setup_free_memory(); + DBUG_RETURN(1); } @@ -1006,7 +1027,6 @@ void mysql_stmt_execute(THD *thd, char *packet) stmt->query_id= thd->query_id; thd->stmt_backup.set_statement(thd); thd->set_statement(stmt); - thd->current_statement= stmt; thd->free_list= 0; /* @@ -1051,8 +1071,14 @@ void mysql_stmt_execute(THD *thd, char *packet) tables->table= 0; // safety - nasty init tables->table_list= 0; } - - sl->master_unit()->unclean(); + + { + SELECT_LEX_UNIT *unit= sl->master_unit(); + unit->unclean(); + unit->types.empty(); + // for derived tables & PS (which can't be reset bu Item_subquery) + unit->reinit_exec_mechanism(); + } } @@ -1082,10 +1108,10 @@ void mysql_stmt_execute(THD *thd, char *packet) free_items(thd->free_list); cleanup_items(stmt->free_list); + close_thread_tables(thd); // to close derived tables free_root(&thd->mem_root, MYF(0)); thd->set_statement(&thd->stmt_backup); end: - thd->current_statement= 0; DBUG_VOID_RETURN; } diff --git a/tests/client_test.c b/tests/client_test.c index 1e34b5a6f30..0f3698b8a29 100644 --- a/tests/client_test.c +++ b/tests/client_test.c @@ -8117,7 +8117,7 @@ static void test_subqueries() { MYSQL_STMT *stmt; int rc, i; - const char *query= "SELECT (SELECT SUM(a+b) FROM t2 where t1.b=t2.b GROUP BY t1.a LIMIT 1) as scalar_s, exists (select 1 from t2 where t2.a/2=t1.a) as exists_s, a in (select a+3 from t2) as in_s, (a-1,b-1) in (select a,b from t2) as in_row_s FROM t1"; + const char *query= "SELECT (SELECT SUM(a+b) FROM t2 where t1.b=t2.b GROUP BY t1.a LIMIT 1) as scalar_s, exists (select 1 from t2 where t2.a/2=t1.a) as exists_s, a in (select a+3 from t2) as in_s, (a-1,b-1) in (select a,b from t2) as in_row_s FROM t1, (select a x, b y from t2) tt WHERE x=a"; myheader("test_subquery"); @@ -8165,7 +8165,8 @@ static void test_distinct() { MYSQL_STMT *stmt; int rc, i; - const char *query= "SELECT count(distinct b), group_concat(a) FROM t1"; + const char *query= + "SELECT 2+count(distinct b), group_concat(a) FROM t1 group by a"; myheader("test_subquery"); @@ -8176,7 +8177,8 @@ static void test_distinct() myquery(rc); rc= mysql_query(mysql, - "insert into t1 values (1,1), (2, 2), (3,3), (4,4), (5,5);"); + "insert into t1 values (1,1), (2, 2), (3,3), (4,4), (5,5),\ +(1,10), (2, 20), (3,30), (4,40), (5,50)\;"); myquery(rc); for (i= 0; i < 3; i++) @@ -8185,7 +8187,7 @@ static void test_distinct() mystmt_init(stmt); rc= mysql_execute(stmt); mystmt(stmt, rc); - assert(1 == my_process_stmt_result(stmt)); + assert(5 == my_process_stmt_result(stmt)); mysql_stmt_close(stmt); } @@ -8194,9 +8196,6 @@ static void test_distinct() } -/* - Test for bug#2248 "mysql_fetch without prior mysql_execute hangs" -*/ static void test_bug2248() { @@ -8391,6 +8390,8 @@ int main(int argc, char **argv) start_time= time((time_t *)0); + test_subqueries(); + client_query(); /* simple client query test */ #if NOT_YET_WORKING /* Used for internal new development debugging */ @@ -8457,7 +8458,7 @@ int main(int argc, char **argv) test_stmt_close(); /* mysql_stmt_close() test -- hangs */ test_prepare_field_result(); /* prepare meta info */ test_multi_stmt(); /* multi stmt test */ - test_multi_statements(); /* test multi statement execution */ +/* test_multi_statements(); *//* test multi statement execution */ test_store_result(); /* test the store_result */ test_store_result1(); /* test store result without buffers */ test_store_result2(); /* test store result for misc case */