# Bazaar merge directive format 2 (Bazaar 0.90)
# revision_id: adamsch1@yahoo.com-20090708234218-4fw8ouhyy7vg81e0
# target_branch: bzr+ssh://bazaar.launchpad.net/%7Emysql/mysql-\
#   server/mysql-5.1/
# testament_sha1: 58dc898b61aa531cd35e4c2f51b2164d12098f0f
# timestamp: 2009-07-08 23:45:12 +0000
# base_revision_id: joro@sun.com-20090708131116-kyz8iotbum8w9yic
# 
# Begin patch
=== modified file 'sql/item_create.cc'
--- sql/item_create.cc	2009-03-24 18:27:33 +0000
+++ sql/item_create.cc	2009-07-08 23:42:18 +0000
@@ -1079,6 +1079,18 @@
   virtual ~Create_func_greatest() {}
 };
 
+class Create_func_grouping : public Create_func_arg1
+{
+public:
+  virtual Item *create(THD *thd, Item *arg1);
+
+  static Create_func_grouping s_singleton;
+
+protected:
+  Create_func_grouping() {}
+  virtual ~Create_func_grouping() {}
+};
+
 
 class Create_func_hex : public Create_func_arg1
 {
@@ -3561,6 +3573,15 @@
 }
 
 
+Create_func_grouping Create_func_grouping::s_singleton;
+
+Item*
+Create_func_grouping::create(THD *thd, Item *arg1 )
+{
+  return new (thd->mem_root) Item_func_grouping(arg1);
+}
+
+
 Create_func_hex Create_func_hex::s_singleton;
 
 Item*
@@ -4810,6 +4831,7 @@
   { { C_STRING_WITH_LEN("GET_LOCK") }, BUILDER(Create_func_get_lock)},
   { { C_STRING_WITH_LEN("GLENGTH") }, GEOM_BUILDER(Create_func_glength)},
   { { C_STRING_WITH_LEN("GREATEST") }, BUILDER(Create_func_greatest)},
+  { { C_STRING_WITH_LEN("GROUPING") }, BUILDER(Create_func_grouping)},
   { { C_STRING_WITH_LEN("HEX") }, BUILDER(Create_func_hex)},
   { { C_STRING_WITH_LEN("IFNULL") }, BUILDER(Create_func_ifnull)},
   { { C_STRING_WITH_LEN("INET_ATON") }, BUILDER(Create_func_inet_aton)},

=== modified file 'sql/item_func.h'
--- sql/item_func.h	2009-07-03 10:36:04 +0000
+++ sql/item_func.h	2009-07-08 23:42:18 +0000
@@ -55,7 +55,7 @@
                   NOW_FUNC, TRIG_COND_FUNC,
                   SUSERVAR_FUNC, GUSERVAR_FUNC, COLLATE_FUNC,
                   EXTRACT_FUNC, CHAR_TYPECAST_FUNC, FUNC_SP, UDF_FUNC,
-                  NEG_FUNC, GSYSVAR_FUNC };
+                  NEG_FUNC, GSYSVAR_FUNC, GROUPING_FUNC };
   enum optimize_type { OPTIMIZE_NONE,OPTIMIZE_KEY,OPTIMIZE_OP, OPTIMIZE_NULL,
                        OPTIMIZE_EQUAL };
   enum Type type() const { return FUNC_ITEM; }
@@ -776,6 +776,21 @@
   const char *func_name() const { return "greatest"; }
 };
 
+/*
+  Objects of this class are used as markers in ROLLUP queries
+  they get replaced by a literal int of 1 or 0 depending on 
+  if the row is a subtotal 
+*/
+class Item_func_grouping :public Item_int_func
+{
+  int level;
+public:
+  Item_func_grouping(Item *a) :Item_int_func(a), level(0) {}
+  Item *column() { return args[0]; }
+  const char *func_name() const { return "grouping"; }
+  enum Functype functype() const   { return GROUPING_FUNC; }
+  longlong val_int() { return level; }
+};
 
 /* 
   Objects of this class are used for ROLLUP queries to wrap up 

=== modified file 'sql/sql_select.cc'
--- sql/sql_select.cc	2009-07-03 10:43:54 +0000
+++ sql/sql_select.cc	2009-07-08 23:42:18 +0000
@@ -15766,6 +15766,36 @@
               return 1;
 	    item->maybe_null= 1;		// Value will be null sometimes
             null_item->result_field= item->get_tmp_table_field();
+
+            /*
+              Look for grouping(col) entries that match the current elemnt
+              that will be set to null.  Replace it with the current level
+              we simply substitute grouping(col) entries for subtotal rows
+            */
+            {
+              List_iterator<Item> group_it(rollup.fields[pos]);
+              Item *group_item;
+              while ((group_item= group_it++))
+              {
+                if (group_item->type() == Item::FUNC_ITEM &&
+                     ((Item_func*)group_item)->functype() ==
+                        Item_func::GROUPING_FUNC )  {
+                  Item_func_grouping *gitem = (Item_func_grouping*)group_item;
+                  Field *b = item->get_tmp_table_field();
+                  Field *a = gitem->column() ?
+                    gitem->column()->get_tmp_table_field() : 0 ;
+                  if( a && b && a->eq(b) )
+                  {
+                    /* Found one - this col is a subtotal */
+                    Item_int *inty = new (thd->mem_root)Item_int((int32)1,
+                      MY_INT32_NUM_DECIMAL_DIGITS);
+                    group_it.replace(inty);
+                    break;
+                  }
+                }
+              }
+            }
+
             item= null_item;
 	    break;
 	  }

# Begin bundle
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