mirror of
https://github.com/MariaDB/server.git
synced 2025-07-21 21:22:27 +03:00
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
This commit is contained in:
@ -8072,4 +8072,37 @@ CALL sp;
|
|||||||
c a b a b
|
c a b a b
|
||||||
DROP PROCEDURE sp;
|
DROP PROCEDURE sp;
|
||||||
DROP TABLE t1;
|
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
|
# End of 5.5 test
|
||||||
|
@ -9373,5 +9373,46 @@ CALL sp;
|
|||||||
DROP PROCEDURE sp;
|
DROP PROCEDURE sp;
|
||||||
DROP TABLE t1;
|
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
|
--echo # End of 5.5 test
|
||||||
|
@ -90,6 +90,7 @@ mysql_handle_derived(LEX *lex, uint phases)
|
|||||||
sl= sl->next_select_in_list())
|
sl= sl->next_select_in_list())
|
||||||
{
|
{
|
||||||
TABLE_LIST *cursor= sl->get_table_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
|
DT_MERGE_FOR_INSERT is not needed for views/derived tables inside
|
||||||
subqueries. Views and derived tables of subqueries should be
|
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()));
|
derived->get_unit()));
|
||||||
st_select_lex_unit *unit= 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->unclean();
|
||||||
unit->types.empty();
|
unit->types.empty();
|
||||||
/* for derived tables & PS (which can't be reset by Item_subquery) */
|
/* 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);
|
DBUG_RETURN(TRUE);
|
||||||
}
|
}
|
||||||
select_lex->fix_prepare_information(thd, &fake_conds, &fake_conds);
|
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
|
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;
|
n_child_sum_items= 0;
|
||||||
subquery_in_having= explicit_limit= 0;
|
subquery_in_having= explicit_limit= 0;
|
||||||
is_item_list_lookup= 0;
|
is_item_list_lookup= 0;
|
||||||
first_execution= 1;
|
changed_elements= 0;
|
||||||
first_natural_join_processing= 1;
|
first_natural_join_processing= 1;
|
||||||
first_cond_optimization= 1;
|
first_cond_optimization= 1;
|
||||||
parsing_place= NO_MATTER;
|
parsing_place= NO_MATTER;
|
||||||
@ -3367,9 +3367,10 @@ void st_select_lex::fix_prepare_information(THD *thd, Item **conds,
|
|||||||
Item **having_conds)
|
Item **having_conds)
|
||||||
{
|
{
|
||||||
DBUG_ENTER("st_select_lex::fix_prepare_information");
|
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.first)
|
||||||
{
|
{
|
||||||
if (!group_list_ptrs)
|
if (!group_list_ptrs)
|
||||||
|
@ -729,6 +729,10 @@ public:
|
|||||||
|
|
||||||
typedef class st_select_lex_unit SELECT_LEX_UNIT;
|
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
|
SELECT_LEX - store information of parsed SELECT statment
|
||||||
*/
|
*/
|
||||||
@ -876,7 +880,8 @@ public:
|
|||||||
subquery. Prepared statements work OK in that regard, as in
|
subquery. Prepared statements work OK in that regard, as in
|
||||||
case of an error during prepare the PS is not created.
|
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_natural_join_processing;
|
||||||
bool first_cond_optimization;
|
bool first_cond_optimization;
|
||||||
/* do not wrap view fields with Item_ref */
|
/* 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())
|
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() */
|
/* remove option which was put by mysql_explain_union() */
|
||||||
sl->options&= ~SELECT_DESCRIBE;
|
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);
|
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)
|
for (order= sl->group_list.first; order; order= order->next)
|
||||||
|
{
|
||||||
order->item= &order->item_ptr;
|
order->item= &order->item_ptr;
|
||||||
|
}
|
||||||
/* Fix ORDER list */
|
/* Fix ORDER list */
|
||||||
for (order= sl->order_list.first; order; order= order->next)
|
for (order= sl->order_list.first; order; order= order->next)
|
||||||
order->item= &order->item_ptr;
|
|
||||||
{
|
{
|
||||||
#ifndef DBUG_OFF
|
order->item= &order->item_ptr;
|
||||||
bool res=
|
|
||||||
#endif
|
|
||||||
sl->handle_derived(lex, DT_REINIT);
|
|
||||||
DBUG_ASSERT(res == 0);
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
if (sl->changed_elements & TOUCHED_SEL_DERIVED)
|
||||||
|
{
|
||||||
|
#ifndef DBUG_OFF
|
||||||
|
bool res=
|
||||||
|
#endif
|
||||||
|
sl->handle_derived(lex, DT_REINIT);
|
||||||
|
DBUG_ASSERT(res == 0);
|
||||||
|
}
|
||||||
|
|
||||||
{
|
{
|
||||||
SELECT_LEX_UNIT *unit= sl->master_unit();
|
SELECT_LEX_UNIT *unit= sl->master_unit();
|
||||||
unit->unclean();
|
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
|
called at the first execution of the statement, while first_execution
|
||||||
shows whether this is called at the first execution of the union that
|
shows whether this is called at the first execution of the union that
|
||||||
may form just a subselect.
|
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;
|
for (ORDER *order= global_parameters->order_list.first;
|
||||||
order;
|
order;
|
||||||
|
Reference in New Issue
Block a user