Fix for sp.test failure in --ps-protocol mode (2nd attempt).

Now we should call open_and_lock_tables() even if table list is empty -
to cache stored routines used by query and open and lock tables required
for their execution.
parent ca336ad1
...@@ -217,9 +217,11 @@ bool mysql_insert(THD *thd,TABLE_LIST *table_list, ...@@ -217,9 +217,11 @@ bool mysql_insert(THD *thd,TABLE_LIST *table_list,
} }
if ((table= delayed_get_table(thd,table_list)) && !thd->is_fatal_error) if ((table= delayed_get_table(thd,table_list)) && !thd->is_fatal_error)
{ {
res= 0; /*
if (table_list->next_global) /* if sub select */ Open tables used for sub-selects or in stored functions, will also
res= open_and_lock_tables(thd, table_list->next_global); cache these functions.
*/
res= open_and_lock_tables(thd, table_list->next_global);
/* /*
First is not processed by open_and_lock_tables() => we need set First is not processed by open_and_lock_tables() => we need set
updateability flags "by hands". updateability flags "by hands".
......
...@@ -1230,7 +1230,7 @@ static bool mysql_test_do_fields(Prepared_statement *stmt, ...@@ -1230,7 +1230,7 @@ static bool mysql_test_do_fields(Prepared_statement *stmt,
if (tables && check_table_access(thd, SELECT_ACL, tables, 0)) if (tables && check_table_access(thd, SELECT_ACL, tables, 0))
DBUG_RETURN(TRUE); DBUG_RETURN(TRUE);
if (tables && open_and_lock_tables(thd, tables)) if (open_and_lock_tables(thd, tables))
{ {
DBUG_RETURN(TRUE); DBUG_RETURN(TRUE);
} }
...@@ -1261,12 +1261,12 @@ static bool mysql_test_set_fields(Prepared_statement *stmt, ...@@ -1261,12 +1261,12 @@ static bool mysql_test_set_fields(Prepared_statement *stmt,
List_iterator_fast<set_var_base> it(*var_list); List_iterator_fast<set_var_base> it(*var_list);
THD *thd= stmt->thd; THD *thd= stmt->thd;
set_var_base *var; set_var_base *var;
bool res= 0; bool res;
if (tables && check_table_access(thd, SELECT_ACL, tables, 0)) if (tables && check_table_access(thd, SELECT_ACL, tables, 0))
DBUG_RETURN(TRUE); DBUG_RETURN(TRUE);
if (tables && (res= open_and_lock_tables(thd, tables))) if ((res= open_and_lock_tables(thd, tables)))
goto error; goto error;
while ((var= it++)) while ((var= it++))
{ {
...@@ -1287,30 +1287,30 @@ error: ...@@ -1287,30 +1287,30 @@ error:
Check internal SELECT of the prepared command Check internal SELECT of the prepared command
SYNOPSIS SYNOPSIS
select_like_statement_test() select_like_stmt_test()
stmt - prepared table handler stmt - prepared statement handler
tables - global list of tables specific_prepare - function of command specific prepare
specific_prepare - function of command specific prepare setup_tables_done_option - options to be passed to LEX::unit.prepare()
NOTE
This function won't directly open tables used in select. They should
be opened either by calling function (and in this case you probably
should use select_like_stmt_test_with_open_n_lock()) or by
"specific_prepare" call (like this happens in case of multi-update).
RETURN VALUE RETURN VALUE
FALSE success FALSE success
TRUE error TRUE error
*/ */
static bool select_like_statement_test(Prepared_statement *stmt,
TABLE_LIST *tables, static bool select_like_stmt_test(Prepared_statement *stmt,
bool (*specific_prepare)(THD *thd), bool (*specific_prepare)(THD *thd),
ulong setup_tables_done_option) ulong setup_tables_done_option)
{ {
DBUG_ENTER("select_like_statement_test"); DBUG_ENTER("select_like_stmt_test");
THD *thd= stmt->thd; THD *thd= stmt->thd;
LEX *lex= stmt->lex; LEX *lex= stmt->lex;
bool res= 0; bool res= FALSE;
/* check that tables was not opened during conversion from usual update */
if (tables &&
(!tables->table && !tables->view) &&
(res= open_and_lock_tables(thd, tables)))
goto end;
if (specific_prepare && (res= (*specific_prepare)(thd))) if (specific_prepare && (res= (*specific_prepare)(thd)))
goto end; goto end;
...@@ -1328,6 +1328,44 @@ end: ...@@ -1328,6 +1328,44 @@ end:
} }
/*
Check internal SELECT of the prepared command (with opening and
locking tables used).
SYNOPSIS
select_like_stmt_test_with_open_n_lock()
stmt - prepared statement handler
tables - list of tables to be opened and locked
before calling specific_prepare function
specific_prepare - function of command specific prepare
setup_tables_done_option - options to be passed to LEX::unit.prepare()
RETURN VALUE
FALSE success
TRUE error
*/
static bool
select_like_stmt_test_with_open_n_lock(Prepared_statement *stmt,
TABLE_LIST *tables,
bool (*specific_prepare)(THD *thd),
ulong setup_tables_done_option)
{
DBUG_ENTER("select_like_stmt_test_with_open_n_lock");
/*
We should not call LEX::unit.cleanup() after this open_and_lock_tables()
call because we don't allow prepared EXPLAIN yet so derived tables will
clean up after themself.
*/
if (open_and_lock_tables(stmt->thd, tables))
DBUG_RETURN(TRUE);
DBUG_RETURN(select_like_stmt_test(stmt, specific_prepare,
setup_tables_done_option));
}
/* /*
Validate and prepare for execution CREATE TABLE statement Validate and prepare for execution CREATE TABLE statement
...@@ -1358,7 +1396,7 @@ static int mysql_test_create_table(Prepared_statement *stmt) ...@@ -1358,7 +1396,7 @@ static int mysql_test_create_table(Prepared_statement *stmt)
select_lex->item_list.elements) select_lex->item_list.elements)
{ {
select_lex->resolve_mode= SELECT_LEX::SELECT_MODE; select_lex->resolve_mode= SELECT_LEX::SELECT_MODE;
res= select_like_statement_test(stmt, tables, 0, 0); res= select_like_stmt_test_with_open_n_lock(stmt, tables, 0, 0);
select_lex->resolve_mode= SELECT_LEX::NOMATTER_MODE; select_lex->resolve_mode= SELECT_LEX::NOMATTER_MODE;
} }
...@@ -1389,12 +1427,9 @@ static bool mysql_test_multiupdate(Prepared_statement *stmt, ...@@ -1389,12 +1427,9 @@ static bool mysql_test_multiupdate(Prepared_statement *stmt,
/* if we switched from normal update, rights are checked */ /* if we switched from normal update, rights are checked */
if (!converted && multi_update_precheck(stmt->thd, tables)) if (!converted && multi_update_precheck(stmt->thd, tables))
return TRUE; return TRUE;
/*
here we do not pass tables for opening, tables will be opened and locked return select_like_stmt_test(stmt, &mysql_multi_update_prepare,
by mysql_multi_update_prepare OPTION_SETUP_TABLES_DONE);
*/
return select_like_statement_test(stmt, 0, &mysql_multi_update_prepare,
OPTION_SETUP_TABLES_DONE);
} }
...@@ -1422,9 +1457,9 @@ static int mysql_test_multidelete(Prepared_statement *stmt, ...@@ -1422,9 +1457,9 @@ static int mysql_test_multidelete(Prepared_statement *stmt,
uint fake_counter; uint fake_counter;
if ((res= multi_delete_precheck(stmt->thd, tables, &fake_counter))) if ((res= multi_delete_precheck(stmt->thd, tables, &fake_counter)))
return res; return res;
if ((res= select_like_statement_test(stmt, tables, if ((res= select_like_stmt_test_with_open_n_lock(stmt, tables,
&mysql_multi_delete_prepare, &mysql_multi_delete_prepare,
OPTION_SETUP_TABLES_DONE))) OPTION_SETUP_TABLES_DONE)))
return res; return res;
if (!tables->table) if (!tables->table)
{ {
...@@ -1500,9 +1535,9 @@ static int mysql_test_insert_select(Prepared_statement *stmt, ...@@ -1500,9 +1535,9 @@ static int mysql_test_insert_select(Prepared_statement *stmt,
first_local_table= (TABLE_LIST *)lex->select_lex.table_list.first; first_local_table= (TABLE_LIST *)lex->select_lex.table_list.first;
DBUG_ASSERT(first_local_table != 0); DBUG_ASSERT(first_local_table != 0);
res= select_like_statement_test(stmt, tables, res= select_like_stmt_test_with_open_n_lock(stmt, tables,
&mysql_insert_select_prepare_tester, &mysql_insert_select_prepare_tester,
OPTION_SETUP_TABLES_DONE); OPTION_SETUP_TABLES_DONE);
/* revert changes made by mysql_insert_select_prepare_tester */ /* revert changes made by mysql_insert_select_prepare_tester */
lex->select_lex.table_list.first= (byte*) first_local_table; lex->select_lex.table_list.first= (byte*) first_local_table;
lex->select_lex.resolve_mode= SELECT_LEX::INSERT_MODE; lex->select_lex.resolve_mode= SELECT_LEX::INSERT_MODE;
......
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