Commit f20b775c authored by bell@sanja.is.com.ua's avatar bell@sanja.is.com.ua

PS fixed to be compatible with derived tables (BUG#2641)

parent 6777120d
...@@ -350,6 +350,8 @@ typedef Comp_creator* (*chooser_compare_func_creator)(bool invert); ...@@ -350,6 +350,8 @@ typedef Comp_creator* (*chooser_compare_func_creator)(bool invert);
/* sql_parse.cc */ /* sql_parse.cc */
void free_items(Item *item); void free_items(Item *item);
void cleanup_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 "sql_class.h"
#include "opt_range.h" #include "opt_range.h"
...@@ -687,7 +689,6 @@ bool rm_temporary_table(enum db_type base, char *path); ...@@ -687,7 +689,6 @@ bool rm_temporary_table(enum db_type base, char *path);
void free_io_cache(TABLE *entry); void free_io_cache(TABLE *entry);
void intern_close_table(TABLE *entry); void intern_close_table(TABLE *entry);
bool close_thread_table(THD *thd, TABLE **table_ptr); 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); void close_temporary_tables(THD *thd);
TABLE_LIST * find_table_in_list(TABLE_LIST *table, TABLE_LIST * find_table_in_list(TABLE_LIST *table,
const char *db_name, const char *table_name); const char *db_name, const char *table_name);
......
...@@ -1590,6 +1590,14 @@ int open_and_lock_tables(THD *thd, TABLE_LIST *tables) ...@@ -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)) if (open_tables(thd, tables, &counter) || lock_tables(thd, tables, counter))
DBUG_RETURN(-1); /* purecov: inspected */ DBUG_RETURN(-1); /* purecov: inspected */
fix_tables_pointers(thd->lex->all_selects_list); 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)); DBUG_RETURN(mysql_handle_derived(thd->lex));
} }
......
...@@ -934,6 +934,7 @@ class THD :public ilink, ...@@ -934,6 +934,7 @@ class THD :public ilink,
DBUG_ASSERT(current_statement!=0); DBUG_ASSERT(current_statement!=0);
cleanup_items(current_statement->free_list); cleanup_items(current_statement->free_list);
free_items(free_list); free_items(free_list);
close_thread_tables(this); // to close derived tables
free_root(&mem_root, MYF(0)); free_root(&mem_root, MYF(0));
set_item_arena(current_statement); set_item_arena(current_statement);
} }
......
...@@ -622,7 +622,12 @@ static bool mysql_test_insert_fields(Prepared_statement *stmt, ...@@ -622,7 +622,12 @@ static bool mysql_test_insert_fields(Prepared_statement *stmt,
DBUG_RETURN(1); DBUG_RETURN(1);
#endif #endif
if (open_and_lock_tables(thd, table_list)) 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; table= table_list->table;
if ((values= its++)) if ((values= its++))
...@@ -630,12 +635,12 @@ static bool mysql_test_insert_fields(Prepared_statement *stmt, ...@@ -630,12 +635,12 @@ static bool mysql_test_insert_fields(Prepared_statement *stmt,
uint value_count; uint value_count;
ulong counter= 0; ulong counter= 0;
thd->ps_setup_prepare_memory();
if (check_insert_fields(thd,table,fields,*values,1)) if (check_insert_fields(thd,table,fields,*values,1))
{ {
thd->ps_setup_free_memory(); thd->ps_setup_free_memory();
DBUG_RETURN(1); DBUG_RETURN(1);
} }
// this memory pool was opened in open_and_lock_tables
thd->ps_setup_free_memory(); thd->ps_setup_free_memory();
value_count= values->elements; value_count= values->elements;
...@@ -653,6 +658,11 @@ static bool mysql_test_insert_fields(Prepared_statement *stmt, ...@@ -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)) if (send_prep_stmt(stmt, 0))
DBUG_RETURN(1); DBUG_RETURN(1);
DBUG_RETURN(0); DBUG_RETURN(0);
...@@ -683,16 +693,21 @@ static bool mysql_test_upd_fields(Prepared_statement *stmt, ...@@ -683,16 +693,21 @@ static bool mysql_test_upd_fields(Prepared_statement *stmt,
DBUG_RETURN(1); DBUG_RETURN(1);
#endif #endif
if (open_and_lock_tables(thd, table_list)) 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); DBUG_RETURN(1);
}
thd->ps_setup_prepare_memory();
if (setup_tables(table_list, 0) || if (setup_tables(table_list, 0) ||
setup_fields(thd, 0, table_list, fields, 1, 0, 0) || setup_fields(thd, 0, table_list, fields, 1, 0, 0) ||
setup_conds(thd, table_list, &conds) || thd->net.report_error) 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(); thd->ps_setup_free_memory();
DBUG_RETURN(1); DBUG_RETURN(1);
} }
// this memory pool was opened in open_and_lock_tables
thd->ps_setup_free_memory(); thd->ps_setup_free_memory();
/* /*
...@@ -748,44 +763,50 @@ static bool mysql_test_select_fields(Prepared_statement *stmt, ...@@ -748,44 +763,50 @@ static bool mysql_test_select_fields(Prepared_statement *stmt,
DBUG_RETURN(1); DBUG_RETURN(1);
if (open_and_lock_tables(thd, tables)) 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); DBUG_RETURN(1);
}
if (lex->describe) if (lex->describe)
{ {
if (send_prep_stmt(stmt, 0)) if (send_prep_stmt(stmt, 0))
DBUG_RETURN(1); goto err;
} }
else else
{ {
if (!result && !(result= new select_send())) if (!result && !(result= new select_send()))
{ {
send_error(thd, ER_OUT_OF_RESOURCES); send_error(thd, ER_OUT_OF_RESOURCES);
DBUG_RETURN(1); goto err;
} }
thd->used_tables= 0; // Updated by setup_fields thd->used_tables= 0; // Updated by setup_fields
thd->ps_setup_prepare_memory();
if (unit->prepare(thd, result, 0)) if (unit->prepare(thd, result, 0))
{ goto err_prep;
unit->cleanup();
thd->ps_setup_free_memory();
DBUG_RETURN(1);
}
if (send_prep_stmt(stmt, fields.elements) || if (send_prep_stmt(stmt, fields.elements) ||
thd->protocol_simple.send_fields(&fields, 0) thd->protocol_simple.send_fields(&fields, 0)
#ifndef EMBEDDED_LIBRARY #ifndef EMBEDDED_LIBRARY
|| net_flush(&thd->net) || net_flush(&thd->net)
#endif #endif
) )
{ goto err_prep;
DBUG_RETURN(1);
}
unit->cleanup(); 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) ...@@ -1006,7 +1027,6 @@ void mysql_stmt_execute(THD *thd, char *packet)
stmt->query_id= thd->query_id; stmt->query_id= thd->query_id;
thd->stmt_backup.set_statement(thd); thd->stmt_backup.set_statement(thd);
thd->set_statement(stmt); thd->set_statement(stmt);
thd->current_statement= stmt;
thd->free_list= 0; thd->free_list= 0;
/* /*
...@@ -1051,8 +1071,14 @@ void mysql_stmt_execute(THD *thd, char *packet) ...@@ -1051,8 +1071,14 @@ void mysql_stmt_execute(THD *thd, char *packet)
tables->table= 0; // safety - nasty init tables->table= 0; // safety - nasty init
tables->table_list= 0; 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) ...@@ -1082,10 +1108,10 @@ void mysql_stmt_execute(THD *thd, char *packet)
free_items(thd->free_list); free_items(thd->free_list);
cleanup_items(stmt->free_list); cleanup_items(stmt->free_list);
close_thread_tables(thd); // to close derived tables
free_root(&thd->mem_root, MYF(0)); free_root(&thd->mem_root, MYF(0));
thd->set_statement(&thd->stmt_backup); thd->set_statement(&thd->stmt_backup);
end: end:
thd->current_statement= 0;
DBUG_VOID_RETURN; DBUG_VOID_RETURN;
} }
......
...@@ -8117,7 +8117,7 @@ static void test_subqueries() ...@@ -8117,7 +8117,7 @@ static void test_subqueries()
{ {
MYSQL_STMT *stmt; MYSQL_STMT *stmt;
int rc, i; 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"); myheader("test_subquery");
...@@ -8165,7 +8165,8 @@ static void test_distinct() ...@@ -8165,7 +8165,8 @@ static void test_distinct()
{ {
MYSQL_STMT *stmt; MYSQL_STMT *stmt;
int rc, i; 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"); myheader("test_subquery");
...@@ -8176,7 +8177,8 @@ static void test_distinct() ...@@ -8176,7 +8177,8 @@ static void test_distinct()
myquery(rc); myquery(rc);
rc= mysql_query(mysql, 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); myquery(rc);
for (i= 0; i < 3; i++) for (i= 0; i < 3; i++)
...@@ -8185,7 +8187,7 @@ static void test_distinct() ...@@ -8185,7 +8187,7 @@ static void test_distinct()
mystmt_init(stmt); mystmt_init(stmt);
rc= mysql_execute(stmt); rc= mysql_execute(stmt);
mystmt(stmt, rc); mystmt(stmt, rc);
assert(1 == my_process_stmt_result(stmt)); assert(5 == my_process_stmt_result(stmt));
mysql_stmt_close(stmt); mysql_stmt_close(stmt);
} }
...@@ -8194,9 +8196,6 @@ static void test_distinct() ...@@ -8194,9 +8196,6 @@ static void test_distinct()
} }
/*
Test for bug#2248 "mysql_fetch without prior mysql_execute hangs"
*/
static void test_bug2248() static void test_bug2248()
{ {
...@@ -8391,6 +8390,8 @@ int main(int argc, char **argv) ...@@ -8391,6 +8390,8 @@ int main(int argc, char **argv)
start_time= time((time_t *)0); start_time= time((time_t *)0);
test_subqueries();
client_query(); /* simple client query test */ client_query(); /* simple client query test */
#if NOT_YET_WORKING #if NOT_YET_WORKING
/* Used for internal new development debugging */ /* Used for internal new development debugging */
...@@ -8457,7 +8458,7 @@ int main(int argc, char **argv) ...@@ -8457,7 +8458,7 @@ int main(int argc, char **argv)
test_stmt_close(); /* mysql_stmt_close() test -- hangs */ test_stmt_close(); /* mysql_stmt_close() test -- hangs */
test_prepare_field_result(); /* prepare meta info */ test_prepare_field_result(); /* prepare meta info */
test_multi_stmt(); /* multi stmt test */ 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_result(); /* test the store_result */
test_store_result1(); /* test store result without buffers */ test_store_result1(); /* test store result without buffers */
test_store_result2(); /* test store result for misc case */ test_store_result2(); /* test store result for misc case */
......
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment