[Commits] Rev 3488: MDEV-3903 fix. in file:///home/bell/maria/bzr/work-maria-10.0-base-exists2in/

sanja at askmonty.org sanja at askmonty.org
Thu Feb 7 14:52:14 EET 2013


At file:///home/bell/maria/bzr/work-maria-10.0-base-exists2in/

------------------------------------------------------------
revno: 3488
revision-id: sanja at askmonty.org-20130207125211-tdiknbz6344njon4
parent: sanja at askmonty.org-20130206084755-7bsuj86imqx6dfcp
committer: sanja at askmonty.org
branch nick: work-maria-10.0-base-exists2in
timestamp: Thu 2013-02-07 14:52:11 +0200
message:
  MDEV-3903 fix.
  
  The problem was that when we create IN subquery 
  unit->item is already assigned and the subquery
  writes itself there as temporary changing
  (in Item_subselect::init).
-------------- next part --------------
=== modified file 'mysql-test/r/subselect_exists2in.result'
--- a/mysql-test/r/subselect_exists2in.result	2013-02-06 08:47:55 +0000
+++ b/mysql-test/r/subselect_exists2in.result	2013-02-07 12:52:11 +0000
@@ -801,8 +801,6 @@ EXECUTE stmt;
 a
 EXECUTE stmt;
 a
-1
-7
 drop table t1;
 #
 # MDEV-3904: Assertion `in_subs->has_strategy()' failed in
@@ -825,4 +823,24 @@ drop view v;
 drop table t1,t2;
 set optimizer_switch=default;
 set optimizer_switch='exists_to_in=on';
+#
+# MDEV-3903: Server crashes in Item_cond::fix_fields on 2nd execution
+# of a prepared stmt with exists_to_in+materialization+semijoin,
+# EXISTS subquery, STRAIGHT_JOIN
+#
+SET optimizer_switch='materialization=on,semijoin=on,exists_to_in=on';
+CREATE TABLE t1 (a INT) ENGINE=MyISAM;
+INSERT INTO t1 VALUES (1),(2);
+CREATE TABLE t2 (b INT) ENGINE=MyISAM;
+INSERT INTO t2 VALUES (3),(4);
+PREPARE stmt FROM
+'SELECT STRAIGHT_JOIN * FROM t1
+WHERE EXISTS ( SELECT * FROM t2 WHERE b = a )';
+EXECUTE stmt;
+a
+EXECUTE stmt;
+a
+drop table t1,t2;
+set optimizer_switch=default;
+set optimizer_switch='exists_to_in=on';
 set optimizer_switch=default;

=== modified file 'mysql-test/t/subselect_exists2in.test'
--- a/mysql-test/t/subselect_exists2in.test	2013-02-06 08:47:55 +0000
+++ b/mysql-test/t/subselect_exists2in.test	2013-02-07 12:52:11 +0000
@@ -688,6 +688,31 @@ drop table t1,t2;
 set optimizer_switch=default;
 set optimizer_switch='exists_to_in=on';
 
+--echo #
+--echo # MDEV-3903: Server crashes in Item_cond::fix_fields on 2nd execution
+--echo # of a prepared stmt with exists_to_in+materialization+semijoin,
+--echo # EXISTS subquery, STRAIGHT_JOIN
+--echo #
+
+SET optimizer_switch='materialization=on,semijoin=on,exists_to_in=on';
+
+CREATE TABLE t1 (a INT) ENGINE=MyISAM;
+INSERT INTO t1 VALUES (1),(2);
+
+CREATE TABLE t2 (b INT) ENGINE=MyISAM;
+INSERT INTO t2 VALUES (3),(4);
+
+PREPARE stmt FROM
+'SELECT STRAIGHT_JOIN * FROM t1
+WHERE EXISTS ( SELECT * FROM t2 WHERE b = a )';
+
+EXECUTE stmt;
+EXECUTE stmt;
+
+drop table t1,t2;
+set optimizer_switch=default;
+set optimizer_switch='exists_to_in=on';
+
 
 #restore defaults
 set optimizer_switch=default;

=== modified file 'sql/item_subselect.cc'
--- a/sql/item_subselect.cc	2013-02-06 08:47:55 +0000
+++ b/sql/item_subselect.cc	2013-02-07 12:52:11 +0000
@@ -86,15 +86,24 @@ void Item_subselect::init(st_select_lex
 
   if (unit->item)
   {
-    /*
-      Item can be changed in JOIN::prepare while engine in JOIN::optimize
-      => we do not copy old_engine here
-    */
     engine= unit->item->engine;
-    own_engine= FALSE;
     parsing_place= unit->item->parsing_place;
-    thd->change_item_tree((Item**)&unit->item, this);
-    engine->change_result(this, result, TRUE);
+    if (unit->item->substype() == EXISTS_SUBS &&
+        ((Item_exists_subselect *)unit->item)->exists_transformed)
+    {
+      /* it is permanent transformation of EXISTS to IN */
+      unit->item= this;
+      engine->change_result(this, result, FALSE);
+    }
+    else
+    {
+      /*
+        Item can be changed in JOIN::prepare while engine in JOIN::optimize
+        => we do not copy old_engine here
+      */
+      thd->change_item_tree((Item**)&unit->item, this);
+      engine->change_result(this, result, TRUE);
+    }
   }
   else
   {
@@ -1309,7 +1318,7 @@ bool Item_singlerow_subselect::get_date(
 
 Item_exists_subselect::Item_exists_subselect(st_select_lex *select_lex):
   Item_subselect(), upper_not(NULL), abort_on_null(0),
-  emb_on_expr_nest(NULL), optimizer(0)
+  emb_on_expr_nest(NULL), optimizer(0), exists_transformed(0)
 {
   DBUG_ENTER("Item_exists_subselect::Item_exists_subselect");
   bool val_bool();
@@ -1348,7 +1357,7 @@ bool Item_in_subselect::test_limit(st_se
 Item_in_subselect::Item_in_subselect(Item * left_exp,
 				     st_select_lex *select_lex):
   Item_exists_subselect(), left_expr_cache(0), first_execution(TRUE),
-  exists_transformed(0), in_strategy(SUBS_NOT_TRANSFORMED),
+  in_strategy(SUBS_NOT_TRANSFORMED),
   pushed_cond_guards(NULL), is_jtbm_merged(FALSE), is_jtbm_const_tab(FALSE),
   is_flattenable_semijoin(FALSE), is_registered_semijoin(FALSE),
   upper_item(0)
@@ -2794,6 +2803,10 @@ bool Item_exists_subselect::exists2in_pr
       goto out;
     }
   }
+
+  /* make EXISTS->IN permanet (see Item_subselect::init()) */
+  set_exists_transformed();
+
   first_select->select_limit= NULL;
   if (!(in_subs= new Item_in_subselect(left_exp, first_select)))
   {
@@ -3044,14 +3057,23 @@ void Item_in_subselect::print(String *st
   Item_subselect::print(str, query_type);
 }
 
+bool Item_exists_subselect::fix_fields(THD *thd_arg, Item **ref)
+{
+  DBUG_ENTER("Item_exists_subselect::fix_fields");
+  if (exists_transformed)
+    DBUG_RETURN( !( (*ref)= new Item_int(1)));
+  DBUG_RETURN(Item_subselect::fix_fields(thd_arg, ref));
+}
+
 
 bool Item_in_subselect::fix_fields(THD *thd_arg, Item **ref)
 {
   uint outer_cols_num;
   List<Item> *inner_cols;
+  DBUG_ENTER("Item_in_subselect::fix_fields");
 
   if (test_strategy(SUBS_SEMI_JOIN))
-    return !( (*ref)= new Item_int(1));
+    DBUG_RETURN( !( (*ref)= new Item_int(1)) );
 
   /*
     Check if the outer and inner IN operands match in those cases when we
@@ -3083,7 +3105,7 @@ bool Item_in_subselect::fix_fields(THD *
     if (outer_cols_num != inner_cols->elements)
     {
       my_error(ER_OPERAND_COLUMNS, MYF(0), outer_cols_num);
-      return TRUE;
+      DBUG_RETURN(TRUE);
     }
     if (outer_cols_num > 1)
     {
@@ -3093,7 +3115,7 @@ bool Item_in_subselect::fix_fields(THD *
       {
         inner_col= inner_col_it++;
         if (inner_col->check_cols(left_expr->element_index(i)->cols()))
-          return TRUE;
+          DBUG_RETURN(TRUE);
       }
     }
   }
@@ -3101,12 +3123,12 @@ bool Item_in_subselect::fix_fields(THD *
   if (thd_arg->lex->is_view_context_analysis() &&
       left_expr && !left_expr->fixed &&
       left_expr->fix_fields(thd_arg, &left_expr))
-    return TRUE;
+    DBUG_RETURN(TRUE);
   else
   if (Item_subselect::fix_fields(thd_arg, ref))
-    return TRUE;
+    DBUG_RETURN(TRUE);
   fixed= TRUE;
-  return FALSE;
+  DBUG_RETURN(FALSE);
 }
 
 

=== modified file 'sql/item_subselect.h'
--- a/sql/item_subselect.h	2013-02-06 08:47:55 +0000
+++ b/sql/item_subselect.h	2013-02-07 12:52:11 +0000
@@ -360,11 +360,13 @@ public:
     Reference on the Item_in_optimizer wrapper of this subquery
   */
   Item_in_optimizer *optimizer;
+  /* true if we got this from EXISTS or to IN */
+  bool exists_transformed;
 
   Item_exists_subselect(st_select_lex *select_lex);
   Item_exists_subselect()
     :Item_subselect(), upper_not(NULL),abort_on_null(0),
-    emb_on_expr_nest(NULL), optimizer(0)
+    emb_on_expr_nest(NULL), optimizer(0), exists_transformed(0)
   {}
 
   subs_type substype() { return EXISTS_SUBS; }
@@ -381,6 +383,7 @@ public:
   String *val_str(String*);
   my_decimal *val_decimal(my_decimal *);
   bool val_bool();
+  bool fix_fields(THD *thd, Item **ref);
   void fix_length_and_dec();
   virtual void print(String *str, enum_query_type query_type);
   bool select_transformer(JOIN *join);
@@ -396,6 +399,7 @@ public:
   }
   virtual void under_not(Item_func_not *upper) { upper_not= upper; };
 
+  void set_exists_transformed() { exists_transformed= TRUE; }
 
   friend class select_exists_subselect;
   friend class subselect_uniquesubquery_engine;
@@ -449,8 +453,6 @@ protected:
   */
   List<Cached_item> *left_expr_cache;
   bool first_execution;
-  /* true if we got this IN from EXISTS */
-  bool exists_transformed;
 
   /*
     expr & optimizer used in subselect rewriting to store Item for
@@ -570,7 +572,7 @@ public:
   Item_in_subselect(Item * left_expr, st_select_lex *select_lex);
   Item_in_subselect()
     :Item_exists_subselect(), left_expr_cache(0), first_execution(TRUE),
-    exists_transformed(0), in_strategy(SUBS_NOT_TRANSFORMED),
+    in_strategy(SUBS_NOT_TRANSFORMED),
     pushed_cond_guards(NULL), func(NULL), is_jtbm_merged(FALSE),
     is_jtbm_const_tab(FALSE), upper_item(0)
     {
@@ -615,8 +617,6 @@ public:
   bool expr_cache_is_needed(THD *thd);
   inline bool left_expr_has_null();
 
-  void set_exists_transformed() { exists_transformed= TRUE; }
-
   int optimize(double *out_rows, double *cost);
   /*
     Return the identifier that we could use to identify the subquery for the

=== modified file 'sql/sql_select.cc'
--- a/sql/sql_select.cc	2013-02-06 08:47:55 +0000
+++ b/sql/sql_select.cc	2013-02-07 12:52:11 +0000
@@ -1057,7 +1057,8 @@ JOIN::optimize_inner()
     before 'optimize' from upper query 'optimize' to allow semijoin
     conversion happened (which done in the same way.
   */
-  if(conds && conds->walk(&Item::exists2in_processor, 0, (uchar *)thd))
+  if(select_lex->first_cond_optimization &&
+     conds && conds->walk(&Item::exists2in_processor, 0, (uchar *)thd))
     DBUG_RETURN(1);
   /*
 TODO: make view to decide if it is possible to write to WHERE directly or make Semi-Joins able to process ON condition if it is possible



More information about the commits mailing list