mirror of
https://github.com/MariaDB/server.git
synced 2025-01-17 12:32:27 +01: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:
parent
0ad598a00b
commit
cb11b3fbe9
8 changed files with 105 additions and 16 deletions
|
@ -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 @@ public:
|
|||
|
||||
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 @@ public:
|
|||
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;
|
||||
{
|
||||
#ifndef DBUG_OFF
|
||||
bool res=
|
||||
#endif
|
||||
sl->handle_derived(lex, DT_REINIT);
|
||||
DBUG_ASSERT(res == 0);
|
||||
order->item= &order->item_ptr;
|
||||
}
|
||||
}
|
||||
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();
|
||||
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;
|
||||
|
|
Loading…
Reference in a new issue