mirror of
https://github.com/MariaDB/server.git
synced 2025-07-30 16:24:05 +03:00
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
This commit is contained in:
@ -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);
|
|||||||
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)
|
|||||||
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 @@ public:
|
|||||||
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,
|
|||||||
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,
|
|||||||
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,
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
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,
|
|||||||
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,
|
|||||||
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)
|
|||||||
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)
|
|||||||
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)
|
|||||||
|
|
||||||
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()
|
|||||||
{
|
{
|
||||||
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()
|
|||||||
{
|
{
|
||||||
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()
|
|||||||
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()
|
|||||||
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()
|
|||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
/*
|
|
||||||
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)
|
|||||||
|
|
||||||
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)
|
|||||||
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 */
|
||||||
|
Reference in New Issue
Block a user