MDEV-14786: Server crashes in Item_cond::transform on 2nd execution of SP querying from a view
MDEV-14957: JOIN::prepare gets unusable "conds" as argument Do not touch merged derived (it is irreversible) Fix first argument of in_optimizer for calls possible before fix_fields()
This commit is contained in:
parent
11408a69ad
commit
ba8d0fa700
@ -1036,4 +1036,20 @@ SELECT * FROM v1, t2, v3 WHERE a = c AND b = d;
|
|||||||
a b c d
|
a b c d
|
||||||
DROP VIEW v1, v3;
|
DROP VIEW v1, v3;
|
||||||
DROP TABLE t1, t2, t3;
|
DROP TABLE t1, t2, t3;
|
||||||
|
#
|
||||||
|
# MDEV-14786: Server crashes in Item_cond::transform on 2nd
|
||||||
|
# execution of SP querying from a view
|
||||||
|
#
|
||||||
|
create table t1 (i int, row_start timestamp(6) not null default now(),
|
||||||
|
row_end timestamp(6) not null default '2030-01-01 0:0:0');
|
||||||
|
create view v1 as select i from t1 where i < 5 and (row_end =
|
||||||
|
TIMESTAMP'2030-01-01 0:0:0' or row_end is null);
|
||||||
|
create procedure pr(x int) select i from v1;
|
||||||
|
call pr(1);
|
||||||
|
i
|
||||||
|
call pr(2);
|
||||||
|
i
|
||||||
|
drop procedure pr;
|
||||||
|
drop view v1;
|
||||||
|
drop table t1;
|
||||||
# end of 5.5
|
# end of 5.5
|
||||||
|
@ -888,4 +888,19 @@ SELECT * FROM v1, t2, v3 WHERE a = c AND b = d;
|
|||||||
DROP VIEW v1, v3;
|
DROP VIEW v1, v3;
|
||||||
DROP TABLE t1, t2, t3;
|
DROP TABLE t1, t2, t3;
|
||||||
|
|
||||||
|
--echo #
|
||||||
|
--echo # MDEV-14786: Server crashes in Item_cond::transform on 2nd
|
||||||
|
--echo # execution of SP querying from a view
|
||||||
|
--echo #
|
||||||
|
create table t1 (i int, row_start timestamp(6) not null default now(),
|
||||||
|
row_end timestamp(6) not null default '2030-01-01 0:0:0');
|
||||||
|
create view v1 as select i from t1 where i < 5 and (row_end =
|
||||||
|
TIMESTAMP'2030-01-01 0:0:0' or row_end is null);
|
||||||
|
create procedure pr(x int) select i from v1;
|
||||||
|
call pr(1);
|
||||||
|
call pr(2);
|
||||||
|
drop procedure pr;
|
||||||
|
drop view v1;
|
||||||
|
drop table t1;
|
||||||
|
|
||||||
--echo # end of 5.5
|
--echo # end of 5.5
|
||||||
|
@ -10010,7 +10010,7 @@ const char *dbug_print_item(Item *item)
|
|||||||
if (!item)
|
if (!item)
|
||||||
return "(Item*)NULL";
|
return "(Item*)NULL";
|
||||||
item->print(&str ,QT_ORDINARY);
|
item->print(&str ,QT_ORDINARY);
|
||||||
if (str.c_ptr() == buf)
|
if (str.c_ptr_safe() == buf)
|
||||||
return buf;
|
return buf;
|
||||||
else
|
else
|
||||||
return "Couldn't fit into buffer";
|
return "Couldn't fit into buffer";
|
||||||
|
@ -50,6 +50,12 @@ bool trace_unsupported_by_check_vcol_func_processor(const char *where)
|
|||||||
return trace_unsupported_func(where, "check_vcol_func_processor");
|
return trace_unsupported_func(where, "check_vcol_func_processor");
|
||||||
}
|
}
|
||||||
|
|
||||||
|
#ifdef DBUG_OFF
|
||||||
|
static inline const char *dbug_print_item(Item *item) { return NULL; }
|
||||||
|
#else
|
||||||
|
extern const char *dbug_print_item(Item *item);
|
||||||
|
#endif
|
||||||
|
|
||||||
class Protocol;
|
class Protocol;
|
||||||
struct TABLE_LIST;
|
struct TABLE_LIST;
|
||||||
void item_init(void); /* Init item functions */
|
void item_init(void); /* Init item functions */
|
||||||
|
@ -1420,6 +1420,7 @@ bool Item_in_optimizer::is_top_level_item()
|
|||||||
|
|
||||||
void Item_in_optimizer::fix_after_pullout(st_select_lex *new_parent, Item **ref)
|
void Item_in_optimizer::fix_after_pullout(st_select_lex *new_parent, Item **ref)
|
||||||
{
|
{
|
||||||
|
DBUG_ASSERT(fixed);
|
||||||
/* This will re-calculate attributes of our Item_in_subselect: */
|
/* This will re-calculate attributes of our Item_in_subselect: */
|
||||||
Item_bool_func::fix_after_pullout(new_parent, ref);
|
Item_bool_func::fix_after_pullout(new_parent, ref);
|
||||||
|
|
||||||
@ -1443,6 +1444,33 @@ bool Item_in_optimizer::eval_not_null_tables(uchar *opt_arg)
|
|||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
void Item_in_optimizer::print(String *str, enum_query_type query_type)
|
||||||
|
{
|
||||||
|
restore_first_argumet();
|
||||||
|
Item_func::print(str, query_type);
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
/**
|
||||||
|
"Restore" first argument before fix_fields() call (after it is harmless).
|
||||||
|
|
||||||
|
@Note: Main pointer to left part of IN/ALL/ANY subselect is subselect's
|
||||||
|
lest_expr (see Item_in_optimizer::fix_left) so changes made during
|
||||||
|
fix_fields will be rolled back there which can make
|
||||||
|
Item_in_optimizer::args[0] unusable on second execution before fix_left()
|
||||||
|
call. This call fix the pointer.
|
||||||
|
*/
|
||||||
|
|
||||||
|
void Item_in_optimizer::restore_first_argumet()
|
||||||
|
{
|
||||||
|
if (args[1]->type() == Item::SUBSELECT_ITEM &&
|
||||||
|
((Item_subselect *)args[1])->is_in_predicate())
|
||||||
|
{
|
||||||
|
args[0]= ((Item_in_subselect *)args[1])->left_expr;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
bool Item_in_optimizer::fix_left(THD *thd, Item **ref)
|
bool Item_in_optimizer::fix_left(THD *thd, Item **ref)
|
||||||
{
|
{
|
||||||
DBUG_ENTER("Item_in_optimizer::fix_left");
|
DBUG_ENTER("Item_in_optimizer::fix_left");
|
||||||
@ -1588,6 +1616,8 @@ Item *Item_in_optimizer::expr_cache_insert_transformer(uchar *thd_arg)
|
|||||||
{
|
{
|
||||||
THD *thd= (THD*) thd_arg;
|
THD *thd= (THD*) thd_arg;
|
||||||
DBUG_ENTER("Item_in_optimizer::expr_cache_insert_transformer");
|
DBUG_ENTER("Item_in_optimizer::expr_cache_insert_transformer");
|
||||||
|
DBUG_ASSERT(fixed);
|
||||||
|
|
||||||
if (args[1]->type() != Item::SUBSELECT_ITEM)
|
if (args[1]->type() != Item::SUBSELECT_ITEM)
|
||||||
DBUG_RETURN(this); // MAX/MIN transformed => do nothing
|
DBUG_RETURN(this); // MAX/MIN transformed => do nothing
|
||||||
|
|
||||||
@ -1611,6 +1641,7 @@ Item *Item_in_optimizer::expr_cache_insert_transformer(uchar *thd_arg)
|
|||||||
|
|
||||||
void Item_in_optimizer::get_cache_parameters(List<Item> ¶meters)
|
void Item_in_optimizer::get_cache_parameters(List<Item> ¶meters)
|
||||||
{
|
{
|
||||||
|
DBUG_ASSERT(fixed);
|
||||||
/* Add left expression to the list of the parameters of the subquery */
|
/* Add left expression to the list of the parameters of the subquery */
|
||||||
if (args[0]->cols() == 1)
|
if (args[0]->cols() == 1)
|
||||||
parameters.add_unique(args[0], &cmp_items);
|
parameters.add_unique(args[0], &cmp_items);
|
||||||
@ -1842,6 +1873,7 @@ Item *Item_in_optimizer::transform(Item_transformer transformer, uchar *argument
|
|||||||
{
|
{
|
||||||
Item *new_item;
|
Item *new_item;
|
||||||
|
|
||||||
|
DBUG_ASSERT(fixed);
|
||||||
DBUG_ASSERT(!current_thd->stmt_arena->is_stmt_prepare());
|
DBUG_ASSERT(!current_thd->stmt_arena->is_stmt_prepare());
|
||||||
DBUG_ASSERT(arg_count == 2);
|
DBUG_ASSERT(arg_count == 2);
|
||||||
|
|
||||||
@ -1893,6 +1925,7 @@ Item *Item_in_optimizer::transform(Item_transformer transformer, uchar *argument
|
|||||||
|
|
||||||
bool Item_in_optimizer::is_expensive_processor(uchar *arg)
|
bool Item_in_optimizer::is_expensive_processor(uchar *arg)
|
||||||
{
|
{
|
||||||
|
DBUG_ASSERT(fixed);
|
||||||
return args[0]->is_expensive_processor(arg) ||
|
return args[0]->is_expensive_processor(arg) ||
|
||||||
args[1]->is_expensive_processor(arg);
|
args[1]->is_expensive_processor(arg);
|
||||||
}
|
}
|
||||||
@ -1900,6 +1933,7 @@ bool Item_in_optimizer::is_expensive_processor(uchar *arg)
|
|||||||
|
|
||||||
bool Item_in_optimizer::is_expensive()
|
bool Item_in_optimizer::is_expensive()
|
||||||
{
|
{
|
||||||
|
DBUG_ASSERT(fixed);
|
||||||
return args[0]->is_expensive() || args[1]->is_expensive();
|
return args[0]->is_expensive() || args[1]->is_expensive();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -268,6 +268,8 @@ public:
|
|||||||
bool is_top_level_item();
|
bool is_top_level_item();
|
||||||
bool eval_not_null_tables(uchar *opt_arg);
|
bool eval_not_null_tables(uchar *opt_arg);
|
||||||
void fix_after_pullout(st_select_lex *new_parent, Item **ref);
|
void fix_after_pullout(st_select_lex *new_parent, Item **ref);
|
||||||
|
virtual void print(String *str, enum_query_type query_type);
|
||||||
|
void restore_first_argumet();
|
||||||
};
|
};
|
||||||
|
|
||||||
class Comp_creator
|
class Comp_creator
|
||||||
|
@ -366,7 +366,11 @@ bool mysql_derived_merge(THD *thd, LEX *lex, TABLE_LIST *derived)
|
|||||||
derived->get_unit()));
|
derived->get_unit()));
|
||||||
|
|
||||||
if (derived->merged)
|
if (derived->merged)
|
||||||
|
{
|
||||||
|
|
||||||
|
DBUG_PRINT("info", ("Irreversibly merged: exit"));
|
||||||
DBUG_RETURN(FALSE);
|
DBUG_RETURN(FALSE);
|
||||||
|
}
|
||||||
|
|
||||||
if (dt_select->uncacheable & UNCACHEABLE_RAND)
|
if (dt_select->uncacheable & UNCACHEABLE_RAND)
|
||||||
{
|
{
|
||||||
@ -667,6 +671,17 @@ bool mysql_derived_prepare(THD *thd, LEX *lex, TABLE_LIST *derived)
|
|||||||
|
|
||||||
unit->derived= derived;
|
unit->derived= derived;
|
||||||
|
|
||||||
|
/*
|
||||||
|
Above cascade call of prepare is important for PS protocol, but after it
|
||||||
|
is called we can check if we really need prepare for this derived
|
||||||
|
*/
|
||||||
|
if (derived->merged)
|
||||||
|
{
|
||||||
|
DBUG_PRINT("info", ("Irreversibly merged: exit"));
|
||||||
|
DBUG_RETURN(FALSE);
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
derived->fill_me= FALSE;
|
derived->fill_me= FALSE;
|
||||||
|
|
||||||
if (!(derived->derived_result= new select_union))
|
if (!(derived->derived_result= new select_union))
|
||||||
@ -795,6 +810,11 @@ bool mysql_derived_optimize(THD *thd, LEX *lex, TABLE_LIST *derived)
|
|||||||
DBUG_PRINT("enter", ("Alias: '%s' Unit: %p",
|
DBUG_PRINT("enter", ("Alias: '%s' Unit: %p",
|
||||||
(derived->alias ? derived->alias : "<NULL>"),
|
(derived->alias ? derived->alias : "<NULL>"),
|
||||||
derived->get_unit()));
|
derived->get_unit()));
|
||||||
|
if (derived->merged)
|
||||||
|
{
|
||||||
|
DBUG_PRINT("info", ("Irreversibly merged: exit"));
|
||||||
|
DBUG_RETURN(FALSE);
|
||||||
|
}
|
||||||
|
|
||||||
if (unit->optimized)
|
if (unit->optimized)
|
||||||
DBUG_RETURN(FALSE);
|
DBUG_RETURN(FALSE);
|
||||||
|
@ -638,6 +638,9 @@ JOIN::prepare(Item ***rref_pointer_array,
|
|||||||
join_list= &select_lex->top_join_list;
|
join_list= &select_lex->top_join_list;
|
||||||
union_part= unit_arg->is_union();
|
union_part= unit_arg->is_union();
|
||||||
|
|
||||||
|
// simple check that we got usable conds
|
||||||
|
dbug_print_item(conds);
|
||||||
|
|
||||||
if (select_lex->handle_derived(thd->lex, DT_PREPARE))
|
if (select_lex->handle_derived(thd->lex, DT_PREPARE))
|
||||||
DBUG_RETURN(1);
|
DBUG_RETURN(1);
|
||||||
|
|
||||||
|
Loading…
x
Reference in New Issue
Block a user