diff options
author | Oleksandr Byelkin <sanja@mariadb.com> | 2018-01-15 14:50:35 +0100 |
---|---|---|
committer | Oleksandr Byelkin <sanja@mariadb.com> | 2018-01-23 13:42:41 +0100 |
commit | ba8d0fa700a73893979793785ed53f7bbd950df8 (patch) | |
tree | fcd00cf7e93d7b3449025a89d9687180961f66c5 | |
parent | 11408a69adc6749c855a9867fc4db3e3d45236c3 (diff) | |
download | mariadb-git-ba8d0fa700a73893979793785ed53f7bbd950df8.tar.gz |
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()
-rw-r--r-- | mysql-test/r/derived.result | 16 | ||||
-rw-r--r-- | mysql-test/t/derived.test | 15 | ||||
-rw-r--r-- | sql/item.cc | 2 | ||||
-rw-r--r-- | sql/item.h | 6 | ||||
-rw-r--r-- | sql/item_cmpfunc.cc | 34 | ||||
-rw-r--r-- | sql/item_cmpfunc.h | 2 | ||||
-rw-r--r-- | sql/sql_derived.cc | 20 | ||||
-rw-r--r-- | sql/sql_select.cc | 3 |
8 files changed, 97 insertions, 1 deletions
diff --git a/mysql-test/r/derived.result b/mysql-test/r/derived.result index 763dbe264fb..54c78dc9f6f 100644 --- a/mysql-test/r/derived.result +++ b/mysql-test/r/derived.result @@ -1036,4 +1036,20 @@ SELECT * FROM v1, t2, v3 WHERE a = c AND b = d; a b c d DROP VIEW v1, v3; 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 diff --git a/mysql-test/t/derived.test b/mysql-test/t/derived.test index eb6e502b029..c5b792c8d4d 100644 --- a/mysql-test/t/derived.test +++ b/mysql-test/t/derived.test @@ -888,4 +888,19 @@ SELECT * FROM v1, t2, v3 WHERE a = c AND b = d; DROP VIEW v1, v3; 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 diff --git a/sql/item.cc b/sql/item.cc index 576dce78299..08a00615c0c 100644 --- a/sql/item.cc +++ b/sql/item.cc @@ -10010,7 +10010,7 @@ const char *dbug_print_item(Item *item) if (!item) return "(Item*)NULL"; item->print(&str ,QT_ORDINARY); - if (str.c_ptr() == buf) + if (str.c_ptr_safe() == buf) return buf; else return "Couldn't fit into buffer"; diff --git a/sql/item.h b/sql/item.h index 4daca60f68e..830f8bf14a4 100644 --- a/sql/item.h +++ b/sql/item.h @@ -50,6 +50,12 @@ bool trace_unsupported_by_check_vcol_func_processor(const char *where) 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; struct TABLE_LIST; void item_init(void); /* Init item functions */ diff --git a/sql/item_cmpfunc.cc b/sql/item_cmpfunc.cc index 62e76922c0e..a77443f40ef 100644 --- a/sql/item_cmpfunc.cc +++ b/sql/item_cmpfunc.cc @@ -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) { + DBUG_ASSERT(fixed); /* This will re-calculate attributes of our Item_in_subselect: */ 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) { 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; DBUG_ENTER("Item_in_optimizer::expr_cache_insert_transformer"); + DBUG_ASSERT(fixed); + if (args[1]->type() != Item::SUBSELECT_ITEM) 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) { + DBUG_ASSERT(fixed); /* Add left expression to the list of the parameters of the subquery */ if (args[0]->cols() == 1) parameters.add_unique(args[0], &cmp_items); @@ -1842,6 +1873,7 @@ Item *Item_in_optimizer::transform(Item_transformer transformer, uchar *argument { Item *new_item; + DBUG_ASSERT(fixed); DBUG_ASSERT(!current_thd->stmt_arena->is_stmt_prepare()); 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) { + DBUG_ASSERT(fixed); return args[0]->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() { + DBUG_ASSERT(fixed); return args[0]->is_expensive() || args[1]->is_expensive(); } diff --git a/sql/item_cmpfunc.h b/sql/item_cmpfunc.h index 7b7ca9223fd..c0e97be20c4 100644 --- a/sql/item_cmpfunc.h +++ b/sql/item_cmpfunc.h @@ -268,6 +268,8 @@ public: bool is_top_level_item(); bool eval_not_null_tables(uchar *opt_arg); 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 diff --git a/sql/sql_derived.cc b/sql/sql_derived.cc index 2a6d82c161a..2e947ecba16 100644 --- a/sql/sql_derived.cc +++ b/sql/sql_derived.cc @@ -366,7 +366,11 @@ bool mysql_derived_merge(THD *thd, LEX *lex, TABLE_LIST *derived) derived->get_unit())); if (derived->merged) + { + + DBUG_PRINT("info", ("Irreversibly merged: exit")); DBUG_RETURN(FALSE); + } if (dt_select->uncacheable & UNCACHEABLE_RAND) { @@ -667,6 +671,17 @@ bool mysql_derived_prepare(THD *thd, LEX *lex, TABLE_LIST *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; 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", (derived->alias ? derived->alias : "<NULL>"), derived->get_unit())); + if (derived->merged) + { + DBUG_PRINT("info", ("Irreversibly merged: exit")); + DBUG_RETURN(FALSE); + } if (unit->optimized) DBUG_RETURN(FALSE); diff --git a/sql/sql_select.cc b/sql/sql_select.cc index 5db503cd266..90bb536c0e2 100644 --- a/sql/sql_select.cc +++ b/sql/sql_select.cc @@ -638,6 +638,9 @@ JOIN::prepare(Item ***rref_pointer_array, join_list= &select_lex->top_join_list; 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)) DBUG_RETURN(1); |