Commit cb11b3fb authored by Oleksandr Byelkin's avatar Oleksandr Byelkin

MDEV-17055: Server crashes in find_order_in_list upon 2nd (3rd) execution of SP with UPDATE

1. Always drop merged_for_insert flag on cleanup (there could be errors which prevent TABLE to be assigned)
2. Make more precise cleanup of select parts which was touched
parent 0ad598a0
......@@ -8072,4 +8072,37 @@ CALL sp;
c a b a b
DROP PROCEDURE sp;
DROP TABLE t1;
#
# MDEV-17055: Server crashes in find_order_in_list upon
# 2nd (3rd) execution of SP with UPDATE
#
CREATE TABLE t1 (a INT);
CREATE VIEW v1 AS SELECT * FROM t1;
CREATE TABLE t2 (c INT);
CREATE PROCEDURE sp() UPDATE v1 SET a = 1 ORDER BY a, b LIMIT 1;
LOCK TABLE t2 READ;
CALL sp;
ERROR HY000: Table 'v1' was not locked with LOCK TABLES
UNLOCK TABLES;
CALL sp;
ERROR 42S22: Unknown column 'b' in 'order clause'
CALL sp;
ERROR 42S22: Unknown column 'b' in 'order clause'
CALL sp;
ERROR 42S22: Unknown column 'b' in 'order clause'
DROP PROCEDURE sp;
CREATE PROCEDURE sp() UPDATE v1 SET a = 1 WHERE a=1 and b=2;
LOCK TABLE t2 READ;
CALL sp;
ERROR HY000: Table 'v1' was not locked with LOCK TABLES
UNLOCK TABLES;
CALL sp;
ERROR 42S22: Unknown column 'b' in 'where clause'
CALL sp;
ERROR 42S22: Unknown column 'b' in 'where clause'
CALL sp;
ERROR 42S22: Unknown column 'b' in 'where clause'
DROP PROCEDURE sp;
DROP VIEW v1;
DROP TABLE t1, t2;
# End of 5.5 test
......@@ -9373,5 +9373,46 @@ CALL sp;
DROP PROCEDURE sp;
DROP TABLE t1;
--echo #
--echo # MDEV-17055: Server crashes in find_order_in_list upon
--echo # 2nd (3rd) execution of SP with UPDATE
--echo #
CREATE TABLE t1 (a INT);
CREATE VIEW v1 AS SELECT * FROM t1;
CREATE TABLE t2 (c INT);
CREATE PROCEDURE sp() UPDATE v1 SET a = 1 ORDER BY a, b LIMIT 1;
LOCK TABLE t2 READ;
--error ER_TABLE_NOT_LOCKED
CALL sp;
UNLOCK TABLES;
--error ER_BAD_FIELD_ERROR
CALL sp;
--error ER_BAD_FIELD_ERROR
CALL sp;
--error ER_BAD_FIELD_ERROR
CALL sp;
# Cleanup
DROP PROCEDURE sp;
CREATE PROCEDURE sp() UPDATE v1 SET a = 1 WHERE a=1 and b=2;
LOCK TABLE t2 READ;
--error ER_TABLE_NOT_LOCKED
CALL sp;
UNLOCK TABLES;
--error ER_BAD_FIELD_ERROR
CALL sp;
--error ER_BAD_FIELD_ERROR
CALL sp;
--error ER_BAD_FIELD_ERROR
CALL sp;
# Cleanup
DROP PROCEDURE sp;
DROP VIEW v1;
DROP TABLE t1, t2;
--echo # End of 5.5 test
......@@ -90,6 +90,7 @@ mysql_handle_derived(LEX *lex, uint phases)
sl= sl->next_select_in_list())
{
TABLE_LIST *cursor= sl->get_table_list();
sl->changed_elements|= TOUCHED_SEL_DERIVED;
/*
DT_MERGE_FOR_INSERT is not needed for views/derived tables inside
subqueries. Views and derived tables of subqueries should be
......@@ -1002,8 +1003,7 @@ bool mysql_derived_reinit(THD *thd, LEX *lex, TABLE_LIST *derived)
derived->get_unit()));
st_select_lex_unit *unit= derived->get_unit();
if (derived->table)
derived->merged_for_insert= FALSE;
derived->merged_for_insert= FALSE;
unit->unclean();
unit->types.empty();
/* for derived tables & PS (which can't be reset by Item_subquery) */
......
......@@ -1510,7 +1510,6 @@ bool mysql_prepare_insert(THD *thd, TABLE_LIST *table_list,
DBUG_RETURN(TRUE);
}
select_lex->fix_prepare_information(thd, &fake_conds, &fake_conds);
select_lex->first_execution= 0;
}
/*
Only call prepare_for_posistion() if we are not performing a DELAYED
......
......@@ -1904,7 +1904,7 @@ void st_select_lex::init_query()
n_child_sum_items= 0;
subquery_in_having= explicit_limit= 0;
is_item_list_lookup= 0;
first_execution= 1;
changed_elements= 0;
first_natural_join_processing= 1;
first_cond_optimization= 1;
parsing_place= NO_MATTER;
......@@ -3367,9 +3367,10 @@ void st_select_lex::fix_prepare_information(THD *thd, Item **conds,
Item **having_conds)
{
DBUG_ENTER("st_select_lex::fix_prepare_information");
if (!thd->stmt_arena->is_conventional() && first_execution)
if (!thd->stmt_arena->is_conventional() &&
!(changed_elements & TOUCHED_SEL_COND))
{
first_execution= 0;
changed_elements|= TOUCHED_SEL_COND;
if (group_list.first)
{
if (!group_list_ptrs)
......
......@@ -729,6 +729,10 @@ class st_select_lex_unit: public st_select_lex_node {
typedef class st_select_lex_unit SELECT_LEX_UNIT;
#define TOUCHED_SEL_COND 1/* WHERE/HAVING/ON should be reinited before use */
#define TOUCHED_SEL_DERIVED (1<<1)/* derived should be reinited before use */
/*
SELECT_LEX - store information of parsed SELECT statment
*/
......@@ -876,7 +880,8 @@ class st_select_lex: public st_select_lex_node
subquery. Prepared statements work OK in that regard, as in
case of an error during prepare the PS is not created.
*/
bool first_execution;
uint8 changed_elements; // see TOUCHED_SEL_*
/* TODO: add foloowing first_* to bitmap above */
bool first_natural_join_processing;
bool first_cond_optimization;
/* do not wrap view fields with Item_ref */
......
......@@ -2496,7 +2496,7 @@ void reinit_stmt_before_use(THD *thd, LEX *lex)
}
for (; sl; sl= sl->next_select_in_list())
{
if (!sl->first_execution)
if (sl->changed_elements & TOUCHED_SEL_COND)
{
/* remove option which was put by mysql_explain_union() */
sl->options&= ~SELECT_DESCRIBE;
......@@ -2543,19 +2543,28 @@ void reinit_stmt_before_use(THD *thd, LEX *lex)
order->next= sl->group_list_ptrs->at(ix+1);
}
}
}
{ // no harm to do it (item_ptr set on parsing)
ORDER *order;
for (order= sl->group_list.first; order; order= order->next)
{
order->item= &order->item_ptr;
}
/* Fix ORDER list */
for (order= sl->order_list.first; order; order= order->next)
order->item= &order->item_ptr;
{
order->item= &order->item_ptr;
}
}
if (sl->changed_elements & TOUCHED_SEL_DERIVED)
{
#ifndef DBUG_OFF
bool res=
bool res=
#endif
sl->handle_derived(lex, DT_REINIT);
DBUG_ASSERT(res == 0);
}
sl->handle_derived(lex, DT_REINIT);
DBUG_ASSERT(res == 0);
}
{
SELECT_LEX_UNIT *unit= sl->master_unit();
unit->unclean();
......
......@@ -215,8 +215,9 @@ st_select_lex_unit::init_prepare_fake_select_lex(THD *thd_arg,
called at the first execution of the statement, while first_execution
shows whether this is called at the first execution of the union that
may form just a subselect.
*/
if (!fake_select_lex->first_execution && first_execution)
*/
if ((fake_select_lex->changed_elements & TOUCHED_SEL_COND) &&
first_execution)
{
for (ORDER *order= global_parameters->order_list.first;
order;
......
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