[Commits] Rev 2881: Fix of problem with WHERE/HAVING consist of alone outer reference field by wrapping it. in file:///home/bell/maria/bzr/work-maria-5.3-mwl89-valgrind/

sanja at askmonty.org sanja at askmonty.org
Mon Jan 24 13:31:18 EET 2011


At file:///home/bell/maria/bzr/work-maria-5.3-mwl89-valgrind/

------------------------------------------------------------
revno: 2881
revision-id: sanja at askmonty.org-20110124113117-v3otndf9uu20p5n6
parent: timour at askmonty.org-20110118171555-xglvrq7nnwp71ua3
committer: sanja at askmonty.org
branch nick: work-maria-5.3-mwl89-valgrind
timestamp: Mon 2011-01-24 13:31:17 +0200
message:
  Fix of problem with WHERE/HAVING consist of alone outer reference field by wrapping it.
-------------- next part --------------
=== modified file 'sql/item.cc'
--- a/sql/item.cc	2011-01-11 12:04:08 +0000
+++ b/sql/item.cc	2011-01-24 11:31:17 +0000
@@ -6619,6 +6619,40 @@ bool Item_direct_ref::get_date(MYSQL_TIM
 }
 
 
+Item* Item_direct_ref_to_ident::transform(Item_transformer transformer,
+                                          uchar *argument)
+{
+  DBUG_ASSERT(!current_thd->is_stmt_prepare());
+
+  Item *new_item= ident->transform(transformer, argument);
+  if (!new_item)
+    return 0;
+  DBUG_ASSERT(new_item->type() == FIELD_ITEM || new_item->type() == REF_ITEM);
+
+  if (ident != new_item)
+    current_thd->change_item_tree((Item**)&ident, new_item);
+  return (this->*transformer)(argument);
+}
+
+
+Item* Item_direct_ref_to_ident::compile(Item_analyzer analyzer, uchar **arg_p,
+                                        Item_transformer transformer,
+                                        uchar *arg_t)
+{
+  if (!(this->*analyzer)(arg_p))
+    return 0;
+
+  uchar *arg_v= *arg_p;
+  Item *new_item= ident->compile(analyzer, &arg_v, transformer, arg_t);
+  if (new_item && ident != new_item)
+  {
+    DBUG_ASSERT(new_item->type() == FIELD_ITEM || new_item->type() == REF_ITEM);
+    current_thd->change_item_tree((Item**)&ident, new_item);
+  }
+  return (this->*transformer)(arg_t);
+}
+
+
 Item_cache_wrapper::~Item_cache_wrapper()
 {
   delete expr_cache;

=== modified file 'sql/item.h'
--- a/sql/item.h	2011-01-11 12:04:08 +0000
+++ b/sql/item.h	2011-01-24 11:31:17 +0000
@@ -518,7 +518,7 @@ public:
              SUBSELECT_ITEM, ROW_ITEM, CACHE_ITEM, TYPE_HOLDER,
              PARAM_ITEM, TRIGGER_FIELD_ITEM, DECIMAL_ITEM,
              XPATH_NODESET, XPATH_NODESET_CMP,
-             VIEW_FIXER_ITEM, EXPR_CACHE_ITEM};
+             VIEW_FIXER_ITEM, EXPR_CACHE_ITEM, UNKNOWN_ITEM};
 
   enum cond_result { COND_UNDEF,COND_OK,COND_TRUE,COND_FALSE };
 
@@ -612,7 +612,7 @@ public:
   virtual Item_result cast_to_int_type() const { return result_type(); }
   virtual enum_field_types string_field_type() const;
   virtual enum_field_types field_type() const;
-  virtual enum Type type() const =0;
+  virtual enum Type type() const { return UNKNOWN_ITEM; };
   
   /*
     Return information about function monotonicity. See comment for
@@ -2609,6 +2609,43 @@ public:
   virtual Ref_Type ref_type() { return DIRECT_REF; }
 };
 
+
+/**
+  This class is the same as Item_direct_ref but created to wrap Item_ident
+  before fix_fields() call
+*/
+
+class Item_direct_ref_to_ident :public Item_direct_ref
+{
+  Item_ident *ident;
+public:
+  Item_direct_ref_to_ident(Item_ident *item)
+    :Item_direct_ref(item->context, (Item**)&item, item->table_name, item->field_name,
+                     FALSE)
+  {
+    ident= item;
+    ref= (Item**)&ident;
+  }
+
+  bool fix_fields(THD *thd, Item **it)
+  {
+    DBUG_ASSERT(ident->type() == FIELD_ITEM || ident->type() == REF_ITEM);
+    if ((!ident->fixed && ident->fix_fields(thd, ref)) ||
+        ident->check_cols(1))
+      return TRUE;
+    set_properties();
+    return FALSE;
+  }
+
+  virtual void print(String *str, enum_query_type query_type)
+  { ident->print(str, query_type); }
+
+  virtual Item* transform(Item_transformer transformer, uchar *arg);
+  virtual Item* compile(Item_analyzer analyzer, uchar **arg_p,
+                        Item_transformer transformer, uchar *arg_t);
+};
+
+
 class Expression_cache;
 class Item_cache;
 

=== modified file 'sql/mysql_priv.h'
--- a/sql/mysql_priv.h	2011-01-11 12:04:08 +0000
+++ b/sql/mysql_priv.h	2011-01-24 11:31:17 +0000
@@ -1612,6 +1612,7 @@ inline bool setup_fields_with_no_wrap(TH
 }
 int setup_conds(THD *thd, TABLE_LIST *tables, TABLE_LIST *leaves,
 		COND **conds);
+void wrap_ident(THD *thd, Item **conds);
 int setup_ftfuncs(SELECT_LEX* select);
 int init_ftfuncs(THD *thd, SELECT_LEX* select, bool no_order);
 void wait_for_condition(THD *thd, pthread_mutex_t *mutex,

=== modified file 'sql/sql_base.cc'
--- a/sql/sql_base.cc	2010-12-06 08:25:44 +0000
+++ b/sql/sql_base.cc	2011-01-24 11:31:17 +0000
@@ -8120,6 +8120,29 @@ insert_fields(THD *thd, Name_resolution_
 }
 
 
+/**
+  Wrap Item_ident
+
+  @param thd             thread handle
+  @param conds           pointer to the condition which should be wrapped
+*/
+
+void wrap_ident(THD *thd, Item **conds)
+{
+  Item_direct_ref_to_ident *wrapper;
+  DBUG_ASSERT((*conds)->type() == Item::FIELD_ITEM || (*conds)->type() == Item::REF_ITEM);
+  Query_arena *arena= thd->stmt_arena, backup;
+  if (arena->is_conventional())
+    arena= 0;
+  else
+    thd->set_n_backup_active_arena(arena, &backup);
+  if ((wrapper= new Item_direct_ref_to_ident((Item_ident *)(*conds))))
+    (*conds)= (Item*) wrapper;
+  if (arena)
+    thd->restore_active_arena(arena, &backup);
+}
+
+
 /*
   Fix all conditions and outer join expressions.
 
@@ -8183,6 +8206,12 @@ int setup_conds(THD *thd, TABLE_LIST *ta
                  print_where(*conds,
                              "WHERE in setup_conds",
                              QT_ORDINARY););
+    /*
+      Wrap alone field in WHERE clause in case it will be outer field of subquery
+      which need persistent pointer on it, but conds could be changed by optimizer
+    */
+    if ((*conds)->type() == Item::FIELD_ITEM)
+      wrap_ident(thd, conds);
     if ((!(*conds)->fixed && (*conds)->fix_fields(thd, conds)) ||
 	(*conds)->check_cols(1))
       goto err_no_arena;

=== modified file 'sql/sql_select.cc'
--- a/sql/sql_select.cc	2011-01-17 11:48:14 +0000
+++ b/sql/sql_select.cc	2011-01-24 11:31:17 +0000
@@ -543,6 +543,13 @@ JOIN::prepare(Item ***rref_pointer_array
     thd->where="having clause";
     thd->lex->allow_sum_func|= 1 << select_lex_arg->nest_level;
     select_lex->having_fix_field= 1;
+    /*
+      Wrap alone field in HAVING clause in case it will be outer field of subquery
+      which need persistent pointer on it, but having could be changed by optimizer
+    */
+    if (having->type() == Item::REF_ITEM &&
+        ((Item_ref *)having)->ref_type() == Item_ref::REF)
+      wrap_ident(thd, &having);
     bool having_fix_rc= (!having->fixed &&
 			 (having->fix_fields(thd, &having) ||
 			  having->check_cols(1)));



More information about the commits mailing list