← Back to team overview

maria-developers team mailing list archive

With_sum_func_cache

 

Hello Sanja,

I recently worked on MDEV-16309 and had hard time to find
which Item classes in the hierarchy:
- have always with_sum_func==true
- have always with_sum_func==false
- have variable with_sum_func

To make it sure, before actually working on MDEV-16309,
I had to create a separate working tree and did with
Item::with_sum_func the same change that we previously
did for Item::with_subselect in:

MDEV-14517 Cleanup for Item::with_subselect and Item::has_subquery()
(which you reviewed)

- I find the code easier to read this way
  (instead of searching for all possible assignments,
   one can search who overrides the method)
- Also, some Item can become smaller in size.

It's pity to throw the patch away. So perhaps we could just apply it.

Can you please have a look?

Thanks.


I the meanwhile I'll create a new MDEV for it
(with a similar description to MDEV-14517)
diff --git a/sql/item.cc b/sql/item.cc
index c19ad32..c0b449d 100644
--- a/sql/item.cc
+++ b/sql/item.cc
@@ -506,7 +506,7 @@ Item::Item(THD *thd):
 {
   DBUG_ASSERT(thd);
   marker= 0;
-  maybe_null=null_value=with_sum_func=with_window_func=with_field=0;
+  maybe_null= null_value= with_window_func= with_field= false;
   in_rollup= 0;
    /* Initially this item is not attached to any JOIN_TAB. */
   join_tab_idx= MAX_TABLES;
@@ -548,7 +548,6 @@ Item::Item(THD *thd, Item *item):
   maybe_null(item->maybe_null),
   in_rollup(item->in_rollup),
   null_value(item->null_value),
-  with_sum_func(item->with_sum_func),
   with_window_func(item->with_window_func),
   with_field(item->with_field),
   fixed(item->fixed),
@@ -2345,7 +2344,7 @@ void Item::split_sum_func2(THD *thd, Ref_ptr_array ref_pointer_array,
   else
   {
     /* Not a SUM() function */
-    if (unlikely((!with_sum_func && !(split_flags & SPLIT_SUM_SELECT))))
+    if (unlikely((!with_sum_func() && !(split_flags & SPLIT_SUM_SELECT))))
     {
       /*
         This is not a SUM function and there are no SUM functions inside.
@@ -2353,7 +2352,7 @@ void Item::split_sum_func2(THD *thd, Ref_ptr_array ref_pointer_array,
       */
       return;
     }
-    if (likely(with_sum_func ||
+    if (likely(with_sum_func() ||
                (type() == FUNC_ITEM &&
                 (((Item_func *) this)->functype() ==
                  Item_func::ISNOTNULLTEST_FUNC ||
@@ -5658,7 +5657,7 @@ resolve_ref_in_select_and_group(THD *thd, Item_ident *ref, SELECT_LEX *select)
     ref->alias_name_used= TRUE;
 
   /* If this is a non-aggregated field inside HAVING, search in GROUP BY. */
-  if (select->having_fix_field && !ref->with_sum_func && group_list)
+  if (select->having_fix_field && !ref->with_sum_func() && group_list)
   {
     group_by_ref= find_field_in_group_list(ref, group_list);
     
@@ -8390,13 +8389,13 @@ bool Item_ref::fix_fields(THD *thd, Item **reference)
   */
   if (!((*ref)->type() == REF_ITEM &&
        ((Item_ref *)(*ref))->ref_type() == OUTER_REF) &&
-      (((*ref)->with_sum_func && name.str &&
+      (((*ref)->with_sum_func() && name.str &&
         !(current_sel->linkage != GLOBAL_OPTIONS_TYPE &&
           current_sel->having_fix_field)) ||
        !(*ref)->fixed))
   {
     my_error(ER_ILLEGAL_REFERENCE, MYF(0),
-             name.str, ((*ref)->with_sum_func?
+             name.str, ((*ref)->with_sum_func() ?
                     "reference to group function":
                     "forward reference in item list"));
     goto error;
@@ -8422,7 +8421,7 @@ void Item_ref::set_properties()
     We have to remember if we refer to a sum function, to ensure that
     split_sum_func() doesn't try to change the reference.
   */
-  with_sum_func= (*ref)->with_sum_func;
+  copy_with_sum_func(*ref);
   with_window_func= (*ref)->with_window_func;
   with_field= (*ref)->with_field;
   fixed= 1;
@@ -8847,7 +8846,7 @@ Item_cache_wrapper::Item_cache_wrapper(THD *thd, Item *item_arg):
   DBUG_ASSERT(orig_item->fixed);
   Type_std_attributes::set(orig_item);
   maybe_null= orig_item->maybe_null;
-  with_sum_func= orig_item->with_sum_func;
+  copy_with_sum_func(orig_item);
   with_field= orig_item->with_field;
   name= item_arg->name;
   m_with_subquery= orig_item->with_subquery();
@@ -9235,7 +9234,7 @@ int Item_cache_wrapper::save_in_field(Field *to, bool no_conversions)
 
 Item* Item_cache_wrapper::get_tmp_table_item(THD *thd)
 {
-  if (!orig_item->with_sum_func && !orig_item->const_item())
+  if (!orig_item->with_sum_func() && !orig_item->const_item())
     return new (thd->mem_root) Item_temptable_field(thd, result_field);
   return copy_or_same(thd);
 }
diff --git a/sql/item.h b/sql/item.h
index d96541a..f210065 100644
--- a/sql/item.h
+++ b/sql/item.h
@@ -109,6 +109,7 @@ struct KEY_FIELD;
 struct SARGABLE_PARAM;
 class RANGE_OPT_PARAM;
 class SEL_TREE;
+class With_sum_func_cache;
 
 enum precedence {
   LOWEST_PRECEDENCE,
@@ -836,7 +837,6 @@ class Item: public Value_source,
   bool in_rollup;                       /* If used in GROUP BY list
                                            of a query with ROLLUP */ 
   bool null_value;			/* if item is null */
-  bool with_sum_func;                   /* True if item contains a sum func */
   bool with_window_func;             /* True if item contains a window func */
   /**
     True if any item except Item_sum contains a field. Set during parsing.
@@ -2072,6 +2072,9 @@ class Item: public Value_source,
   */
   virtual bool with_subquery() const { DBUG_ASSERT(fixed); return false; }
 
+  virtual bool with_sum_func() const { return false; }
+  virtual With_sum_func_cache* get_with_sum_func_cache() { return NULL; }
+
   Item* set_expr_cache(THD *thd);
 
   virtual Item_equal *get_item_equal() { return NULL; }
@@ -2175,6 +2178,48 @@ inline Item* get_item_copy (THD *thd, T* item)
 }	
 
 
+class With_sum_func_cache
+{
+protected:
+  bool m_with_sum_func; // True if the owner item contains a sum func
+public:
+  With_sum_func_cache()
+   :m_with_sum_func(false)
+  { }
+  With_sum_func_cache(const Item *a)
+   :m_with_sum_func(a->with_sum_func())
+  { }
+  With_sum_func_cache(const Item *a, const Item *b)
+   :m_with_sum_func(a->with_sum_func() || b->with_sum_func())
+  { }
+  With_sum_func_cache(const Item *a, const Item *b, const Item *c)
+   :m_with_sum_func(a->with_sum_func() || b->with_sum_func() ||
+                    c->with_sum_func())
+  { }
+  With_sum_func_cache(const Item *a, const Item *b, const Item *c,
+                      const Item *d)
+   :m_with_sum_func(a->with_sum_func() || b->with_sum_func() ||
+                    c->with_sum_func() || d->with_sum_func())
+  { }
+  With_sum_func_cache(const Item *a, const Item *b, const Item *c,
+                      const Item *d, const Item *e)
+   :m_with_sum_func(a->with_sum_func() || b->with_sum_func() ||
+                    c->with_sum_func() || d->with_sum_func() ||
+                    e->with_sum_func())
+  { }
+  void set_with_sum_func() { m_with_sum_func= true; }
+  void reset_with_sum_func() { m_with_sum_func= false; }
+  void copy_with_sum_func(const Item *item)
+  {
+    m_with_sum_func= item->with_sum_func();
+  }
+  void join_with_sum_func(const Item *item)
+  {
+    m_with_sum_func|= item->with_sum_func();
+  }
+};
+
+
 /*
   This class is a replacement for the former member Item::with_subselect.
   Determines if the descendant Item is a subselect or some of
@@ -4878,7 +4923,8 @@ class Item_sp
                          bool *null_value, LEX_CSTRING *name);
 };
 
-class Item_ref :public Item_ident
+class Item_ref :public Item_ident,
+                protected With_sum_func_cache
 {
 protected:
   void set_properties();
@@ -4914,7 +4960,9 @@ class Item_ref :public Item_ident
 
   /* Constructor need to process subselect with temporary tables (see Item) */
   Item_ref(THD *thd, Item_ref *item)
-    :Item_ident(thd, item), set_properties_only(0), ref(item->ref) {}
+    :Item_ident(thd, item),
+     With_sum_func_cache(*item),
+     set_properties_only(0), ref(item->ref) {}
   enum Type type() const		{ return REF_ITEM; }
   enum Type real_type() const           { return ref ? (*ref)->type() :
                                           REF_ITEM; }
@@ -5107,6 +5155,8 @@ class Item_ref :public Item_ident
     DBUG_ASSERT(*ref);
     return (*ref)->vers_trx_id();
   }
+  bool with_sum_func() const { return m_with_sum_func; }
+  With_sum_func_cache* get_with_sum_func_cache() { return this; }
 };
 
 
@@ -5196,7 +5246,8 @@ class Expression_cache_tracker;
 */
 
 class Item_cache_wrapper :public Item_result_field,
-                          public With_subquery_cache
+                          public With_subquery_cache,
+                          protected With_sum_func_cache
 {
 private:
   /* Pointer on the cached expression */
@@ -5224,6 +5275,8 @@ class Item_cache_wrapper :public Item_result_field,
   enum Type type() const { return EXPR_CACHE_ITEM; }
   enum Type real_type() const { return orig_item->type(); }
   bool with_subquery() const { DBUG_ASSERT(fixed); return m_with_subquery; }
+  bool with_sum_func() const { return m_with_sum_func; }
+  With_sum_func_cache* get_with_sum_func_cache() { return this; }
 
   bool set_cache(THD *thd);
   Expression_cache_tracker* init_tracker(MEM_ROOT *mem_root);
diff --git a/sql/item_cmpfunc.cc b/sql/item_cmpfunc.cc
index ba503f1..aa0b65f 100644
--- a/sql/item_cmpfunc.cc
+++ b/sql/item_cmpfunc.cc
@@ -1293,7 +1293,7 @@ bool Item_in_optimizer::fix_left(THD *thd)
     used_tables_cache= args[0]->used_tables();
   }
   eval_not_null_tables(NULL);
-  with_sum_func= args[0]->with_sum_func;
+  copy_with_sum_func(args[0]);
   with_field= args[0]->with_field;
   if ((const_item_cache= args[0]->const_item()))
   {
@@ -1304,7 +1304,7 @@ bool Item_in_optimizer::fix_left(THD *thd)
   {
     /* to avoid overriding is called to update left expression */
     used_tables_and_const_cache_join(args[1]);
-    with_sum_func= with_sum_func || args[1]->with_sum_func;
+    join_with_sum_func(args[1]);
   }
   DBUG_RETURN(0);
 }
@@ -1340,7 +1340,7 @@ bool Item_in_optimizer::fix_fields(THD *thd, Item **ref)
   if (args[1]->maybe_null)
     maybe_null=1;
   m_with_subquery= true;
-  with_sum_func= with_sum_func || args[1]->with_sum_func;
+  join_with_sum_func(args[1]);
   with_field= with_field || args[1]->with_field;
   used_tables_and_const_cache_join(args[1]);
   fixed= 1;
@@ -1890,7 +1890,7 @@ void Item_func_interval::fix_length_and_dec()
   max_length= 2;
   used_tables_and_const_cache_join(row);
   not_null_tables_cache= row->not_null_tables();
-  with_sum_func= with_sum_func || row->with_sum_func;
+  join_with_sum_func(row);
   with_field= with_field || row->with_field;
 }
 
@@ -4620,7 +4620,7 @@ Item_cond::fix_fields(THD *thd, Item **ref)
       const_item_cache= FALSE;
     } 
   
-    with_sum_func|=    item->with_sum_func;
+    join_with_sum_func(item);
     with_field|=       item->with_field;
     m_with_subquery|=  item->with_subquery();
     with_window_func|= item->with_window_func;
@@ -6622,7 +6622,7 @@ bool Item_equal::fix_fields(THD *thd, Item **ref)
     used_tables_cache|= item->used_tables();
     tmp_table_map= item->not_null_tables();
     not_null_tables_cache|= tmp_table_map;
-    DBUG_ASSERT(!item->with_sum_func && !item->with_subquery());
+    DBUG_ASSERT(!item->with_sum_func() && !item->with_subquery());
     if (item->maybe_null)
       maybe_null= 1;
     if (!item->get_item_equal())
diff --git a/sql/item_func.cc b/sql/item_func.cc
index e274027..596c42f 100644
--- a/sql/item_func.cc
+++ b/sql/item_func.cc
@@ -145,7 +145,7 @@ void Item_func::sync_with_sum_func_and_with_field(List<Item> &list)
   Item *item;
   while ((item= li++))
   {
-    with_sum_func|= item->with_sum_func;
+    join_with_sum_func(item);
     with_window_func|= item->with_window_func;
     with_field|= item->with_field;
   }
@@ -366,7 +366,7 @@ Item_func::fix_fields(THD *thd, Item **ref)
       if (item->maybe_null)
 	maybe_null=1;
 
-      with_sum_func= with_sum_func || item->with_sum_func;
+      join_with_sum_func(item);
       with_window_func= with_window_func || item->with_window_func;
       with_field= with_field || item->with_field;
       used_tables_and_const_cache_join(item);
@@ -736,7 +736,7 @@ void Item_func::signal_divide_by_null()
 
 Item *Item_func::get_tmp_table_item(THD *thd)
 {
-  if (!with_sum_func && !const_item())
+  if (!Item_func::with_sum_func() && !const_item())
     return new (thd->mem_root) Item_temptable_field(thd, result_field);
   return copy_or_same(thd);
 }
@@ -3269,6 +3269,7 @@ udf_handler::fix_fields(THD *thd, Item_func_or_sum *func,
     }
     uint i;
     Item **arg,**arg_end;
+    With_sum_func_cache *with_sum_func_cache= func->get_with_sum_func_cache();
     for (i=0, arg=arguments, arg_end=arguments+arg_count;
 	 arg != arg_end ;
 	 arg++,i++)
@@ -3295,7 +3296,8 @@ udf_handler::fix_fields(THD *thd, Item_func_or_sum *func,
 	func->collation.set(&my_charset_bin);
       if (item->maybe_null)
 	func->maybe_null=1;
-      func->with_sum_func= func->with_sum_func || item->with_sum_func;
+      if (with_sum_func_cache)
+        with_sum_func_cache->join_with_sum_func(item);
       func->with_field= func->with_field || item->with_field;
       func->With_subquery_cache::join(item);
       func->used_tables_and_const_cache_join(item);
diff --git a/sql/item_func.h b/sql/item_func.h
index 59fc49e..812fec3 100644
--- a/sql/item_func.h
+++ b/sql/item_func.h
@@ -34,7 +34,8 @@ extern "C"				/* Bug in BSDI include file */
 #include "my_decimal.h" // string2my_decimal
 
 
-class Item_func :public Item_func_or_sum
+class Item_func :public Item_func_or_sum,
+                 protected With_sum_func_cache
 {
   void sync_with_sum_func_and_with_field(List<Item> &list);
 protected:
@@ -80,39 +81,36 @@ class Item_func :public Item_func_or_sum
   virtual enum Functype functype() const   { return UNKNOWN_FUNC; }
   Item_func(THD *thd): Item_func_or_sum(thd)
   {
-    with_sum_func= 0;
     with_field= 0;
   }
-  Item_func(THD *thd, Item *a): Item_func_or_sum(thd, a)
+  Item_func(THD *thd, Item *a): Item_func_or_sum(thd, a),
+    With_sum_func_cache(a)
   {
-    with_sum_func= a->with_sum_func;
     with_field= a->with_field;
   }
   Item_func(THD *thd, Item *a, Item *b):
-    Item_func_or_sum(thd, a, b)
+    Item_func_or_sum(thd, a, b),
+    With_sum_func_cache(a, b)
   {
-    with_sum_func= a->with_sum_func || b->with_sum_func;
     with_field= a->with_field || b->with_field;
   }
   Item_func(THD *thd, Item *a, Item *b, Item *c):
-    Item_func_or_sum(thd, a, b, c)
+    Item_func_or_sum(thd, a, b, c),
+    With_sum_func_cache(a, b, c)
   {
-    with_sum_func= a->with_sum_func || b->with_sum_func || c->with_sum_func;
     with_field= a->with_field || b->with_field || c->with_field;
   }
   Item_func(THD *thd, Item *a, Item *b, Item *c, Item *d):
-    Item_func_or_sum(thd, a, b, c, d)
+    Item_func_or_sum(thd, a, b, c, d),
+    With_sum_func_cache(a, b, c, d)
   {
-    with_sum_func= a->with_sum_func || b->with_sum_func ||
-                   c->with_sum_func || d->with_sum_func;
     with_field= a->with_field || b->with_field ||
                 c->with_field || d->with_field;
   }
   Item_func(THD *thd, Item *a, Item *b, Item *c, Item *d, Item* e):
-    Item_func_or_sum(thd, a, b, c, d, e)
+    Item_func_or_sum(thd, a, b, c, d, e),
+    With_sum_func_cache(a, b, c, d, e)
   {
-    with_sum_func= a->with_sum_func || b->with_sum_func ||
-                   c->with_sum_func || d->with_sum_func || e->with_sum_func;
     with_field= a->with_field || b->with_field ||
                 c->with_field || d->with_field || e->with_field;
   }
@@ -124,6 +122,7 @@ class Item_func :public Item_func_or_sum
   // Constructor used for Item_cond_and/or (see Item comment)
   Item_func(THD *thd, Item_func *item):
     Item_func_or_sum(thd, item),
+    With_sum_func_cache(item),
     not_null_tables_cache(item->not_null_tables_cache)
   {
   }
@@ -373,6 +372,9 @@ class Item_func :public Item_func_or_sum
     - or replaced to an Item_int_with_ref
   */
   bool setup_args_and_comparator(THD *thd, Arg_comparator *cmp);
+
+  bool with_sum_func() const { return m_with_sum_func; }
+  With_sum_func_cache* get_with_sum_func_cache() { return this; }
 };
 
 
diff --git a/sql/item_row.cc b/sql/item_row.cc
index 6479409..a0e99c3 100644
--- a/sql/item_row.cc
+++ b/sql/item_row.cc
@@ -61,7 +61,7 @@ bool Item_row::fix_fields(THD *thd, Item **ref)
       }
     }
     maybe_null|= item->maybe_null;
-    with_sum_func= with_sum_func || item->with_sum_func;
+    join_with_sum_func(item);
     with_window_func = with_window_func || item->with_window_func;
     with_field= with_field || item->with_field;
     m_with_subquery|= item->with_subquery();
diff --git a/sql/item_row.h b/sql/item_row.h
index 73b1986..5e1cf54 100644
--- a/sql/item_row.h
+++ b/sql/item_row.h
@@ -36,7 +36,8 @@
 class Item_row: public Item,
                 private Item_args,
                 private Used_tables_and_const_cache,
-                private With_subquery_cache
+                private With_subquery_cache,
+                private With_sum_func_cache
 {
   table_map not_null_tables_cache;
   /**
@@ -49,7 +50,9 @@ class Item_row: public Item,
   Item(thd), Item_args(thd, list), not_null_tables_cache(0), with_null(0)
   { }
   Item_row(THD *thd, Item_row *row):
-    Item(thd), Item_args(thd, static_cast<Item_args*>(row)), Used_tables_and_const_cache(),
+    Item(thd), Item_args(thd, static_cast<Item_args*>(row)),
+    Used_tables_and_const_cache(),
+    With_sum_func_cache(*row),
     not_null_tables_cache(0), with_null(0)
   { }
 
@@ -97,6 +100,8 @@ class Item_row: public Item,
   void cleanup();
   void split_sum_func(THD *thd, Ref_ptr_array ref_pointer_array,
                       List<Item> &fields, uint flags);
+  bool with_sum_func() const { return m_with_sum_func; }
+  With_sum_func_cache* get_with_sum_func_cache() { return this; }
   table_map used_tables() const { return used_tables_cache; };
   bool const_item() const { return const_item_cache; };
   void update_used_tables()
diff --git a/sql/item_subselect.cc b/sql/item_subselect.cc
index 6378e9b..f6f6d0d 100644
--- a/sql/item_subselect.cc
+++ b/sql/item_subselect.cc
@@ -933,7 +933,7 @@ bool Item_subselect::const_item() const
 
 Item *Item_subselect::get_tmp_table_item(THD *thd_arg)
 {
-  if (!with_sum_func && !const_item())
+  if (!Item_subselect::with_sum_func() && !const_item())
     return new (thd->mem_root) Item_temptable_field(thd_arg, result_field);
   return copy_or_same(thd_arg);
 }
@@ -1136,7 +1136,7 @@ Item_singlerow_subselect::select_transformer(JOIN *join)
   if (!select_lex->master_unit()->is_unit_op() &&
       !select_lex->table_list.elements &&
       select_lex->item_list.elements == 1 &&
-      !select_lex->item_list.head()->with_sum_func &&
+      !select_lex->item_list.head()->with_sum_func() &&
       /*
 	We cant change name of Item_field or Item_ref, because it will
 	prevent it's correct resolving, but we should save name of
diff --git a/sql/item_subselect.h b/sql/item_subselect.h
index fa5cbe8..5b27181 100644
--- a/sql/item_subselect.h
+++ b/sql/item_subselect.h
@@ -47,7 +47,8 @@ class Cached_item;
 /* base class for subselects */
 
 class Item_subselect :public Item_result_field,
-                      protected Used_tables_and_const_cache
+                      protected Used_tables_and_const_cache,
+                      protected With_sum_func_cache
 {
   bool value_assigned;   /* value already assigned to subselect */
   bool own_engine;  /* the engine was not taken from other Item_subselect */
@@ -184,6 +185,8 @@ class Item_subselect :public Item_result_field,
   }
   bool fix_fields(THD *thd, Item **ref);
   bool with_subquery() const { DBUG_ASSERT(fixed); return true; }
+  bool with_sum_func() const { return m_with_sum_func; }
+  With_sum_func_cache* get_with_sum_func_cache() { return this; }
   bool mark_as_dependent(THD *thd, st_select_lex *select, Item *item);
   void fix_after_pullout(st_select_lex *new_parent, Item **ref, bool merge);
   void recalc_used_tables(st_select_lex *new_parent, bool after_pullout);
diff --git a/sql/item_sum.cc b/sql/item_sum.cc
index 4a95189..7d1532c 100644
--- a/sql/item_sum.cc
+++ b/sql/item_sum.cc
@@ -404,7 +404,7 @@ bool Item_sum::register_sum_func(THD *thd, Item **ref)
     for (sl= thd->lex->current_select; 
          sl && sl != aggr_sel && sl->master_unit()->item;
          sl= sl->master_unit()->outer_select() )
-      sl->master_unit()->item->with_sum_func= 1;
+      sl->master_unit()->item->get_with_sum_func_cache()->set_with_sum_func();
   }
   thd->lex->current_select->mark_as_dependent(thd, aggr_sel, NULL);
 
@@ -484,7 +484,6 @@ void Item_sum::mark_as_sum_func()
   cur_select->n_sum_items++;
   cur_select->with_sum_func= 1;
   const_item_cache= false;
-  with_sum_func= 1;
   with_field= 0;
   window_func_sum_expr_flag= false;
 }
diff --git a/sql/item_sum.h b/sql/item_sum.h
index 96f1153..37f3fe0 100644
--- a/sql/item_sum.h
+++ b/sql/item_sum.h
@@ -582,6 +582,8 @@ class Item_sum :public Item_func_or_sum
   void mark_as_window_func_sum_expr() { window_func_sum_expr_flag= true; }
   bool is_window_func_sum_expr() { return window_func_sum_expr_flag; }
   virtual void setup_caches(THD *thd) {};
+
+  bool with_sum_func() const { return true; }
 };
 
 
diff --git a/sql/item_windowfunc.cc b/sql/item_windowfunc.cc
index 85ca8b0..2d85538 100644
--- a/sql/item_windowfunc.cc
+++ b/sql/item_windowfunc.cc
@@ -120,7 +120,6 @@ Item_window_func::fix_fields(THD *thd, Item **ref)
 
   const_item_cache= false;
   with_window_func= true;
-  with_sum_func= false;
 
   fix_length_and_dec();
 
diff --git a/sql/sql_base.cc b/sql/sql_base.cc
index 5ce6a6b..fe69add 100644
--- a/sql/sql_base.cc
+++ b/sql/sql_base.cc
@@ -7328,7 +7328,7 @@ bool setup_fields(THD *thd, Ref_ptr_array ref_pointer_array,
       Item_window_func::split_sum_func.
     */
     if (sum_func_list &&
-         ((item->with_sum_func && item->type() != Item::SUM_FUNC_ITEM) ||
+         ((item->with_sum_func() && item->type() != Item::SUM_FUNC_ITEM) ||
           item->with_window_func))
     {
       item->split_sum_func(thd, ref_pointer_array, *sum_func_list,
diff --git a/sql/sql_select.cc b/sql/sql_select.cc
index d676722..6064a4c 100644
--- a/sql/sql_select.cc
+++ b/sql/sql_select.cc
@@ -1043,7 +1043,7 @@ JOIN::prepare(TABLE_LIST *tables_init,
 
     while ((select_el= select_it++))
     {
-      if (select_el->with_sum_func)
+      if (select_el->with_sum_func())
         found_sum_func_elem= true;
       if (select_el->with_field)
         found_field_elem= true;
@@ -1211,14 +1211,14 @@ JOIN::prepare(TABLE_LIST *tables_init,
             item->max_length)))
         real_order= TRUE;
 
-      if (item->with_sum_func && item->type() != Item::SUM_FUNC_ITEM)
+      if (item->with_sum_func() && item->type() != Item::SUM_FUNC_ITEM)
         item->split_sum_func(thd, ref_ptrs, all_fields, 0);
     }
     if (!real_order)
       order= NULL;
   }
 
-  if (having && having->with_sum_func)
+  if (having && having->with_sum_func())
     having->split_sum_func2(thd, ref_ptrs, all_fields,
                             &having, SPLIT_SUM_SKIP_REGISTERED);
   if (select_lex->inner_sum_func_list)
@@ -2402,7 +2402,7 @@ int JOIN::optimize_stage2()
     elements may be lost during further having
     condition transformation in JOIN::exec.
   */
-  if (having && const_table_map && !having->with_sum_func)
+  if (having && const_table_map && !having->with_sum_func())
   {
     having->update_used_tables();
     having= having->remove_eq_conds(thd, &select_lex->having_value, true);
@@ -12910,7 +12910,7 @@ static void update_depend_map_for_order(JOIN *join, ORDER *order)
     order->used= 0;
     // Not item_sum(), RAND() and no reference to table outside of sub select
     if (!(order->depend_map & (OUTER_REF_TABLE_BIT | RAND_TABLE_BIT))
-        && !order->item[0]->with_sum_func &&
+        && !order->item[0]->with_sum_func() &&
         join->join_tab)
     {
       for (JOIN_TAB **tab=join->map2table;
@@ -13001,7 +13001,7 @@ remove_const(JOIN *join,ORDER *first_order, COND *cond,
   for (order=first_order; order ; order=order->next)
   {
     table_map order_tables=order->item[0]->used_tables();
-    if (order->item[0]->with_sum_func ||
+    if (order->item[0]->with_sum_func() ||
         /*
           If the outer table of an outer join is const (either by itself or
           after applying WHERE condition), grouping on a field from such a
@@ -13177,7 +13177,7 @@ ORDER *simple_remove_const(ORDER *order, COND *where)
   ORDER *first= NULL, *prev= NULL;
   for (; order; order= order->next)
   {
-    DBUG_ASSERT(!order->item[0]->with_sum_func); // should never happen
+    DBUG_ASSERT(!order->item[0]->with_sum_func()); // should never happen
     if (!const_expression_in_where(where, order->item[0]))
     {
       if (!first)
@@ -17108,7 +17108,7 @@ create_tmp_table(THD *thd, TMP_TABLE_PARAM *param, List<Item> &fields,
     }
     if (not_all_columns)
     {
-      if (item->with_sum_func && type != Item::SUM_FUNC_ITEM)
+      if (item->with_sum_func() && type != Item::SUM_FUNC_ITEM)
       {
         if (item->used_tables() & OUTER_REF_TABLE_BIT)
           item->update_used_tables();
@@ -22996,7 +22996,7 @@ setup_group(THD *thd, Ref_ptr_array ref_pointer_array, TABLE_LIST *tables,
                            all_fields, true, true, from_window_spec))
       return 1;
     (*ord->item)->marker= UNDEF_POS;		/* Mark found */
-    if ((*ord->item)->with_sum_func && context_analysis_place == IN_GROUP_BY)
+    if ((*ord->item)->with_sum_func() && context_analysis_place == IN_GROUP_BY)
     {
       my_error(ER_WRONG_GROUP_FIELD, MYF(0), (*ord->item)->full_name());
       return 1;
@@ -23154,7 +23154,7 @@ create_distinct_group(THD *thd, Ref_ptr_array ref_pointer_array,
   li.rewind();
   while ((item=li++))
   {
-    if (!item->const_item() && !item->with_sum_func && !item->marker)
+    if (!item->const_item() && !item->with_sum_func() && !item->marker)
     {
       /* 
         Don't put duplicate columns from the SELECT list into the 
@@ -23251,9 +23251,11 @@ count_field_types(SELECT_LEX *select_lex, TMP_TABLE_PARAM *param,
     }
     else
     {
+      With_sum_func_cache *cache= field->get_with_sum_func_cache();
       param->func_count++;
-      if (reset_with_sum_func)
-	field->with_sum_func=0;
+      // "field" can point to Item_std_field, to "cache" can be NULL here.
+      if (reset_with_sum_func && cache)
+        cache->reset_with_sum_func();
     }
   }
 }
@@ -23653,7 +23655,7 @@ setup_copy_fields(THD *thd, TMP_TABLE_PARAM *param,
 	      real_pos->real_type() == Item::SUBSELECT_ITEM ||
 	      real_pos->type() == Item::CACHE_ITEM ||
 	      real_pos->type() == Item::COND_ITEM) &&
-	     !real_pos->with_sum_func)
+	     !real_pos->with_sum_func())
     {						// Save for send fields
       pos= real_pos;
       /* TODO:
@@ -23860,7 +23862,7 @@ change_to_use_tmp_fields(THD *thd, Ref_ptr_array ref_pointer_array,
   for (uint i= 0; (item= it++); i++)
   {
     Field *field;
-    if (item->with_sum_func && item->type() != Item::SUM_FUNC_ITEM)
+    if (item->with_sum_func() && item->type() != Item::SUM_FUNC_ITEM)
       item_field= item;
     else if (item->type() == Item::FIELD_ITEM)
     {
@@ -24387,7 +24389,7 @@ bool JOIN::rollup_init()
         Marking the expression item as 'with_sum_func' will ensure this.
       */ 
       if (changed)
-        item->with_sum_func= 1;
+        item->get_with_sum_func_cache()->set_with_sum_func();
     }
   }
   return 0;

Follow ups