summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorOleksandr Byelkin <sanja@mariadb.com>2018-01-15 14:50:35 +0100
committerOleksandr Byelkin <sanja@mariadb.com>2018-01-22 09:22:19 +0100
commit4fb5d64666325b33605c2ad2cfc36c724e5ce343 (patch)
tree3a23181b4ca7c9de851a879c8169c383afceaeeb
parentc0e964dcf1787a101f6e9c115751c0d02b0fac1b (diff)
downloadmariadb-git-bb-5.5-MDEV-14786.tar.gz
MDEV-14786: Server crashes in Item_cond::transform on 2nd execution of SP querying from a viewbb-5.5-MDEV-14786
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.result16
-rw-r--r--mysql-test/t/derived.test15
-rw-r--r--sql/item.cc2
-rw-r--r--sql/item.h7
-rw-r--r--sql/item_cmpfunc.cc27
-rw-r--r--sql/item_cmpfunc.h2
-rw-r--r--sql/sql_derived.cc20
-rw-r--r--sql/sql_select.cc3
8 files changed, 91 insertions, 1 deletions
diff --git a/mysql-test/r/derived.result b/mysql-test/r/derived.result
index 33af7c61613..fb834a179b8 100644
--- a/mysql-test/r/derived.result
+++ b/mysql-test/r/derived.result
@@ -1011,4 +1011,20 @@ id id data
2 2 yes
1 NULL NULL
drop table t1;
+#
+# 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 f8ba87ac1f5..be238c0547e 100644
--- a/mysql-test/t/derived.test
+++ b/mysql-test/t/derived.test
@@ -864,5 +864,20 @@ select distinct t1.id, tt.id, tt.data
drop table t1;
+--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;
+#set debug_dbug='d,where';
+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 332e027adf1..562c0bec78d 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.ptr() == buf)
return buf;
else
return "Couldn't fit into buffer";
diff --git a/sql/item.h b/sql/item.h
index 4d0860af547..add408602fc 100644
--- a/sql/item.h
+++ b/sql/item.h
@@ -4478,4 +4478,11 @@ public:
void close() {}
};
+#ifdef DBUG_OFF
+static inline const char *dbug_print_item(Item *item) { return NULL; }
+#else
+extern const char *dbug_print_item(Item *item);
+#endif
+
+
#endif /* SQL_ITEM_INCLUDED */
diff --git a/sql/item_cmpfunc.cc b/sql/item_cmpfunc.cc
index 62e76922c0e..a40340baae9 100644
--- a/sql/item_cmpfunc.cc
+++ b/sql/item_cmpfunc.cc
@@ -1443,6 +1443,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");
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 5a7fa4d2c6f..240ce5e9305 100644
--- a/sql/sql_select.cc
+++ b/sql/sql_select.cc
@@ -634,6 +634,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);