← Back to team overview

maria-developers team mailing list archive

Rev 2818: BUG#31480: Incorrect result for nested subquery when executed via semi join in file:///home/psergey/dev/mysql-next-fix-subq/

 

At file:///home/psergey/dev/mysql-next-fix-subq/

------------------------------------------------------------
revno: 2818
revision-id: psergey@xxxxxxxxxxxx-20090708095341-9i08n2r8igulpxzz
parent: psergey@xxxxxxxxxxxx-20090706143329-72s3e73rov2f5tml
committer: Sergey Petrunya <psergey@xxxxxxxxxxxx>
branch nick: mysql-next-fix-subq
timestamp: Wed 2009-07-08 13:53:41 +0400
message:
  BUG#31480: Incorrect result for nested subquery when executed via semi join
  Make the fix work with prepared statements:
  - collect/save ancestor_used_tables and furthest_correlated_ancestor only at 
    PREPARE phase (at execute() we are unable to tell what table_map the outer
    reference would tell. since it would be the same anyway, we save it at 
    PREPARE phase)
=== modified file 'sql/item_subselect.cc'
--- a/sql/item_subselect.cc	2009-07-06 14:26:03 +0000
+++ b/sql/item_subselect.cc	2009-07-08 09:53:41 +0000
@@ -39,8 +39,8 @@
 Item_subselect::Item_subselect():
   Item_result_field(), value_assigned(0), thd(0), substitution(0),
   engine(0), old_engine(0), used_tables_cache(0), have_to_be_excluded(0),
-  const_item_cache(1), inside_fix_fields(0), engine_changed(0), changed(0),
-  is_correlated(FALSE)
+  const_item_cache(1), inside_first_fix_fields(0), ancestor_used_tables(0), 
+  engine_changed(0), changed(0), is_correlated(FALSE)
 {
   with_subselect= 1;
   reset();
@@ -158,6 +158,7 @@
   DBUG_RETURN(RES_OK);
 }
 
+
 void Item_subselect::set_depth()
 {
   uint n= 0;
@@ -166,6 +167,7 @@
   this->depth= n - 1;
 }
 
+
 bool Item_subselect::fix_fields(THD *thd_param, Item **ref)
 {
   char const *save_where= thd_param->where;
@@ -175,23 +177,25 @@
   DBUG_ASSERT(fixed == 0);
   engine->set_thd((thd= thd_param));
 
-  if (!inside_fix_fields)
+  if (!ancestor_used_tables)
   {
     set_depth();
-    if (!(ancestor_used_tables= (table_map*)thd->calloc((1+depth) * 
-                                                        sizeof(table_map))))
+    if (!(ancestor_used_tables= 
+          (table_map*)alloc_root(thd->stmt_arena->mem_root, 
+                                 (1+depth)*sizeof(table_map))))
       return TRUE;
     furthest_correlated_ancestor= 0;
+    inside_first_fix_fields= TRUE;
   }
 
   if (check_stack_overrun(thd, STACK_MIN_SIZE, (uchar*)&res))
     return TRUE;
 
-  inside_fix_fields++;
   res= engine->prepare();
-
+  
   // all transformation is done (used by prepared statements)
   changed= 1;
+  inside_first_fix_fields= FALSE;
 
   if (!res)
   {
@@ -220,14 +224,12 @@
       if (!(*ref)->fixed)
 	ret= (*ref)->fix_fields(thd, ref);
       thd->where= save_where;
-      inside_fix_fields--;
       return ret;
     }
     // Is it one field subselect?
     if (engine->cols() > max_columns)
     {
       my_error(ER_OPERAND_COLUMNS, MYF(0), 1);
-      inside_fix_fields--;
       return TRUE;
     }
     fix_length_and_dec();
@@ -244,12 +246,23 @@
   fixed= 1;
 
 err:
-  inside_fix_fields--;
   thd->where= save_where;
   return res;
 }
 
 
+void Item_subselect::mark_as_dependent(uint n_levels, table_map dep_map)
+{
+  if (inside_first_fix_fields)
+  {
+    is_correlated= TRUE;
+    furthest_correlated_ancestor= max(furthest_correlated_ancestor, n_levels);
+    if (n_levels > 1)
+      ancestor_used_tables[n_levels - 2]= dep_map;
+  }
+}
+
+
 /*
   Adjust attributes after our parent select has been merged into grandparent
 

=== modified file 'sql/item_subselect.h'
--- a/sql/item_subselect.h	2009-07-06 07:57:39 +0000
+++ b/sql/item_subselect.h	2009-07-08 09:53:41 +0000
@@ -68,7 +68,7 @@
   /* cache of constant state */
 
   bool const_item_cache;
-  int inside_fix_fields;
+  int inside_first_fix_fields;
 public:
   /*
     Depth of the subquery predicate. 
@@ -140,6 +140,7 @@
     return null_value;
   }
   bool fix_fields(THD *thd, Item **ref);
+  void mark_as_dependent(uint n_levels, table_map dep_map);
   void fix_after_pullout(st_select_lex *new_parent, uint parent_tables, 
                          Item **ref);
   virtual bool exec();

=== modified file 'sql/sql_lex.cc'
--- a/sql/sql_lex.cc	2009-07-06 07:57:39 +0000
+++ b/sql/sql_lex.cc	2009-07-08 09:53:41 +0000
@@ -1929,13 +1929,7 @@
     }
     Item_subselect *subquery_predicate= s->master_unit()->item;
     if (subquery_predicate)
-    {
-      subquery_predicate->is_correlated= TRUE;
-      subquery_predicate->furthest_correlated_ancestor= 
-        max(subquery_predicate->furthest_correlated_ancestor, n_levels);
-      if (n_levels > 1)
-        subquery_predicate->ancestor_used_tables[n_levels - 2]= dep_map;
-    }
+      subquery_predicate->mark_as_dependent(n_levels, dep_map);
     n_levels--;
   }
 }