summaryrefslogtreecommitdiff
path: root/sql/item_sum.cc
diff options
context:
space:
mode:
Diffstat (limited to 'sql/item_sum.cc')
-rw-r--r--sql/item_sum.cc223
1 files changed, 168 insertions, 55 deletions
diff --git a/sql/item_sum.cc b/sql/item_sum.cc
index c43a7d87f8f..d0bf98e7adb 100644
--- a/sql/item_sum.cc
+++ b/sql/item_sum.cc
@@ -138,11 +138,12 @@ bool Item_sum::walk (Item_processor processor, byte *argument)
return (this->*processor)(argument);
}
+
String *
Item_sum_num::val_str(String *str)
{
DBUG_ASSERT(fixed == 1);
- double nr=val();
+ double nr= val_real();
if (null_value)
return 0;
str->set(nr,decimals, &my_charset_bin);
@@ -172,8 +173,9 @@ Item_sum_num::fix_fields(THD *thd, TABLE_LIST *tables, Item **ref)
if (!thd->allow_sum_func)
{
- my_error(ER_INVALID_GROUP_FUNC_USE,MYF(0));
- return 1;
+ my_message(ER_INVALID_GROUP_FUNC_USE, ER(ER_INVALID_GROUP_FUNC_USE),
+ MYF(0));
+ return TRUE;
}
thd->allow_sum_func=0; // No included group funcs
decimals=0;
@@ -181,7 +183,7 @@ Item_sum_num::fix_fields(THD *thd, TABLE_LIST *tables, Item **ref)
for (uint i=0 ; i < arg_count ; i++)
{
if (args[i]->fix_fields(thd, tables, args + i) || args[i]->check_cols(1))
- return 1;
+ return TRUE;
if (decimals < args[i]->decimals)
decimals=args[i]->decimals;
maybe_null |= args[i]->maybe_null;
@@ -192,7 +194,7 @@ Item_sum_num::fix_fields(THD *thd, TABLE_LIST *tables, Item **ref)
fix_length_and_dec();
thd->allow_sum_func=1; // Allow group functions
fixed= 1;
- return 0;
+ return FALSE;
}
@@ -204,8 +206,9 @@ Item_sum_hybrid::fix_fields(THD *thd, TABLE_LIST *tables, Item **ref)
Item *item= args[0];
if (!thd->allow_sum_func)
{
- my_error(ER_INVALID_GROUP_FUNC_USE,MYF(0));
- return 1;
+ my_message(ER_INVALID_GROUP_FUNC_USE, ER(ER_INVALID_GROUP_FUNC_USE),
+ MYF(0));
+ return TRUE;
}
thd->allow_sum_func=0; // No included group funcs
@@ -213,7 +216,7 @@ Item_sum_hybrid::fix_fields(THD *thd, TABLE_LIST *tables, Item **ref)
if (!item->fixed &&
item->fix_fields(thd, tables, args) ||
(item= args[0])->check_cols(1))
- return 1;
+ return TRUE;
hybrid_type= item->result_type();
if (hybrid_type == INT_RESULT)
@@ -241,7 +244,7 @@ Item_sum_hybrid::fix_fields(THD *thd, TABLE_LIST *tables, Item **ref)
else
hybrid_field_type= Item::field_type();
fixed= 1;
- return 0;
+ return FALSE;
}
@@ -263,20 +266,136 @@ void Item_sum_sum::clear()
bool Item_sum_sum::add()
{
- sum+=args[0]->val();
+ sum+= args[0]->val_real();
if (!args[0]->null_value)
null_value= 0;
return 0;
}
-double Item_sum_sum::val()
+double Item_sum_sum::val_real()
{
DBUG_ASSERT(fixed == 1);
return sum;
}
+/* Item_sum_sum_distinct */
+
+Item_sum_sum_distinct::Item_sum_sum_distinct(Item *item)
+ :Item_sum_num(item), sum(0.0), tree(0)
+{
+ /*
+ quick_group is an optimizer hint, which means that GROUP BY can be
+ handled with help of index on grouped columns.
+ By setting quick_group to zero we force creation of temporary table
+ to perform GROUP BY.
+ */
+ quick_group= 0;
+}
+
+
+Item_sum_sum_distinct::Item_sum_sum_distinct(THD *thd,
+ Item_sum_sum_distinct *original)
+ :Item_sum_num(thd, original), sum(0.0), tree(0)
+{
+ quick_group= 0;
+}
+
+
+Item_sum_sum_distinct::~Item_sum_sum_distinct()
+{
+ delete tree;
+}
+
+
+Item *
+Item_sum_sum_distinct::copy_or_same(THD *thd)
+{
+ return new (thd->mem_root) Item_sum_sum_distinct(thd, this);
+}
+
+C_MODE_START
+
+static int simple_raw_key_cmp(void* arg, const void* key1, const void* key2)
+{
+ return memcmp(key1, key2, *(uint *) arg);
+}
+
+C_MODE_END
+
+bool Item_sum_sum_distinct::setup(THD *thd)
+{
+ SELECT_LEX *select_lex= thd->lex->current_select;
+ /* what does it mean??? */
+ if (select_lex->linkage == GLOBAL_OPTIONS_TYPE)
+ return 1;
+
+ DBUG_ASSERT(tree == 0); /* setup can not be called twice */
+
+ /*
+ Uniques handles all unique elements in a tree until they can't fit in.
+ Then thee tree is dumped to the temporary file.
+ See class Unique for details.
+ */
+ null_value= maybe_null= 1;
+ /*
+ TODO: if underlying item result fits in 4 bytes we can take advantage
+ of it and have tree of long/ulong. It gives 10% performance boost
+ */
+ static uint key_length= sizeof(double);
+ tree= new Unique(simple_raw_key_cmp, &key_length, key_length,
+ thd->variables.max_heap_table_size);
+ return tree == 0;
+}
+
+void Item_sum_sum_distinct::clear()
+{
+ DBUG_ASSERT(tree); /* we always have a tree */
+ null_value= 1;
+ tree->reset();
+}
+
+bool Item_sum_sum_distinct::add()
+{
+ /* args[0]->val_real() may reset args[0]->null_value */
+ double val= args[0]->val_real();
+ if (!args[0]->null_value)
+ {
+ DBUG_ASSERT(tree);
+ null_value= 0;
+ if (val)
+ return tree->unique_add(&val);
+ }
+ return 0;
+}
+
+C_MODE_START
+
+static int sum_sum_distinct(void *element, element_count num_of_dups,
+ void *item_sum_sum_distinct)
+{
+ ((Item_sum_sum_distinct *)
+ (item_sum_sum_distinct))->add(* (double *) element);
+ return 0;
+}
+
+C_MODE_END
+
+double Item_sum_sum_distinct::val_real()
+{
+ /*
+ We don't have a tree only if 'setup()' hasn't been called;
+ this is the case of sql_select.cc:return_zero_rows.
+ */
+ sum= 0.0;
+ if (tree)
+ tree->walk(sum_sum_distinct, (void *) this);
+ return sum;
+}
+
+/* end of Item_sum_sum_distinct */
+
Item *Item_sum_count::copy_or_same(THD* thd)
{
return new (thd->mem_root) Item_sum_count(thd, this);
@@ -336,7 +455,7 @@ void Item_sum_avg::clear()
bool Item_sum_avg::add()
{
- double nr=args[0]->val();
+ double nr= args[0]->val_real();
if (!args[0]->null_value)
{
sum+=nr;
@@ -345,7 +464,7 @@ bool Item_sum_avg::add()
return 0;
}
-double Item_sum_avg::val()
+double Item_sum_avg::val_real()
{
DBUG_ASSERT(fixed == 1);
if (!count)
@@ -362,10 +481,10 @@ double Item_sum_avg::val()
Standard deviation
*/
-double Item_sum_std::val()
+double Item_sum_std::val_real()
{
DBUG_ASSERT(fixed == 1);
- double tmp= Item_sum_variance::val();
+ double tmp= Item_sum_variance::val_real();
return tmp <= 0.0 ? 0.0 : sqrt(tmp);
}
@@ -393,7 +512,7 @@ void Item_sum_variance::clear()
bool Item_sum_variance::add()
{
- double nr=args[0]->val();
+ double nr= args[0]->val_real();
if (!args[0]->null_value)
{
sum+=nr;
@@ -403,7 +522,7 @@ bool Item_sum_variance::add()
return 0;
}
-double Item_sum_variance::val()
+double Item_sum_variance::val_real()
{
DBUG_ASSERT(fixed == 1);
if (!count)
@@ -420,7 +539,7 @@ double Item_sum_variance::val()
void Item_sum_variance::reset_field()
{
- double nr=args[0]->val();
+ double nr= args[0]->val_real();
char *res=result_field->ptr;
if (args[0]->null_value)
@@ -445,7 +564,7 @@ void Item_sum_variance::update_field()
float8get(old_sqr, res+sizeof(double));
field_count=sint8korr(res+sizeof(double)*2);
- nr=args[0]->val();
+ nr= args[0]->val_real();
if (!args[0]->null_value)
{
old_nr+=nr;
@@ -467,7 +586,7 @@ void Item_sum_hybrid::clear()
null_value= 1;
}
-double Item_sum_hybrid::val()
+double Item_sum_hybrid::val_real()
{
DBUG_ASSERT(fixed == 1);
int err;
@@ -500,7 +619,7 @@ longlong Item_sum_hybrid::val_int()
return 0;
if (hybrid_type == INT_RESULT)
return sum_int;
- return (longlong) Item_sum_hybrid::val();
+ return (longlong) Item_sum_hybrid::val_real();
}
@@ -576,7 +695,7 @@ bool Item_sum_min::add()
break;
case REAL_RESULT:
{
- double nr=args[0]->val();
+ double nr= args[0]->val_real();
if (!args[0]->null_value && (null_value || nr < sum))
{
sum=nr;
@@ -629,7 +748,7 @@ bool Item_sum_max::add()
break;
case REAL_RESULT:
{
- double nr=args[0]->val();
+ double nr= args[0]->val_real();
if (!args[0]->null_value && (null_value || nr > sum))
{
sum=nr;
@@ -709,7 +828,7 @@ bool Item_sum_and::add()
void Item_sum_num::reset_field()
{
- double nr=args[0]->val();
+ double nr= args[0]->val_real();
char *res=result_field->ptr;
if (maybe_null)
@@ -763,7 +882,7 @@ void Item_sum_hybrid::reset_field()
}
else // REAL_RESULT
{
- double nr=args[0]->val();
+ double nr= args[0]->val_real();
if (maybe_null)
{
@@ -782,7 +901,7 @@ void Item_sum_hybrid::reset_field()
void Item_sum_sum::reset_field()
{
- double nr=args[0]->val(); // Nulls also return 0
+ double nr= args[0]->val_real(); // Nulls also return 0
float8store(result_field->ptr,nr);
if (args[0]->null_value)
result_field->set_null();
@@ -810,7 +929,7 @@ void Item_sum_count::reset_field()
void Item_sum_avg::reset_field()
{
- double nr=args[0]->val();
+ double nr= args[0]->val_real();
char *res=result_field->ptr;
if (args[0]->null_value)
@@ -848,7 +967,7 @@ void Item_sum_sum::update_field()
char *res=result_field->ptr;
float8get(old_nr,res);
- nr=args[0]->val();
+ nr= args[0]->val_real();
if (!args[0]->null_value)
{
old_nr+=nr;
@@ -885,7 +1004,7 @@ void Item_sum_avg::update_field()
float8get(old_nr,res);
field_count=sint8korr(res+sizeof(double));
- nr=args[0]->val();
+ nr= args[0]->val_real();
if (!args[0]->null_value)
{
old_nr+=nr;
@@ -931,7 +1050,7 @@ Item_sum_hybrid::min_max_update_real_field()
double nr,old_nr;
old_nr=result_field->val_real();
- nr=args[0]->val();
+ nr= args[0]->val_real();
if (!args[0]->null_value)
{
if (result_field->is_null(0) ||
@@ -983,7 +1102,7 @@ Item_avg_field::Item_avg_field(Item_sum_avg *item)
}
-double Item_avg_field::val()
+double Item_avg_field::val_real()
{
// fix_fields() never calls for this Item
double nr;
@@ -1004,7 +1123,7 @@ double Item_avg_field::val()
String *Item_avg_field::val_str(String *str)
{
// fix_fields() never calls for this Item
- double nr=Item_avg_field::val();
+ double nr= Item_avg_field::val_real();
if (null_value)
return 0;
str->set(nr,decimals, &my_charset_bin);
@@ -1016,10 +1135,10 @@ Item_std_field::Item_std_field(Item_sum_std *item)
{
}
-double Item_std_field::val()
+double Item_std_field::val_real()
{
// fix_fields() never calls for this Item
- double tmp= Item_variance_field::val();
+ double tmp= Item_variance_field::val_real();
return tmp <= 0.0 ? 0.0 : sqrt(tmp);
}
@@ -1032,7 +1151,7 @@ Item_variance_field::Item_variance_field(Item_sum_variance *item)
maybe_null=1;
}
-double Item_variance_field::val()
+double Item_variance_field::val_real()
{
// fix_fields() never calls for this Item
double sum,sum_sqr;
@@ -1055,7 +1174,7 @@ double Item_variance_field::val()
String *Item_variance_field::val_str(String *str)
{
// fix_fields() never calls for this Item
- double nr=val();
+ double nr= val_real();
if (null_value)
return 0;
str->set(nr,decimals, &my_charset_bin);
@@ -1068,11 +1187,6 @@ String *Item_variance_field::val_str(String *str)
#include "sql_select.h"
-int simple_raw_key_cmp(void* arg, byte* key1, byte* key2)
-{
- return memcmp(key1, key2, *(uint*) arg);
-}
-
int simple_str_key_cmp(void* arg, byte* key1, byte* key2)
{
Item_sum_count_distinct* item = (Item_sum_count_distinct*)arg;
@@ -1438,7 +1552,7 @@ Item *Item_sum_udf_float::copy_or_same(THD* thd)
return new (thd->mem_root) Item_sum_udf_float(thd, this);
}
-double Item_sum_udf_float::val()
+double Item_sum_udf_float::val_real()
{
DBUG_ASSERT(fixed == 1);
DBUG_ENTER("Item_sum_udf_float::val");
@@ -1450,7 +1564,7 @@ double Item_sum_udf_float::val()
String *Item_sum_udf_float::val_str(String *str)
{
DBUG_ASSERT(fixed == 1);
- double nr=val();
+ double nr= val_real();
if (null_value)
return 0; /* purecov: inspected */
str->set(nr,decimals, &my_charset_bin);
@@ -1889,8 +2003,9 @@ Item_func_group_concat::fix_fields(THD *thd, TABLE_LIST *tables, Item **ref)
if (!thd->allow_sum_func)
{
- my_error(ER_INVALID_GROUP_FUNC_USE,MYF(0));
- return 1;
+ my_message(ER_INVALID_GROUP_FUNC_USE, ER(ER_INVALID_GROUP_FUNC_USE),
+ MYF(0));
+ return TRUE;
}
thd->allow_sum_func= 0;
@@ -1904,7 +2019,7 @@ Item_func_group_concat::fix_fields(THD *thd, TABLE_LIST *tables, Item **ref)
for (i=0 ; i < arg_count ; i++)
{
if (args[i]->fix_fields(thd, tables, args + i) || args[i]->check_cols(1))
- return 1;
+ return TRUE;
if (i < arg_count_field)
maybe_null|= args[i]->maybe_null;
}
@@ -1912,14 +2027,14 @@ Item_func_group_concat::fix_fields(THD *thd, TABLE_LIST *tables, Item **ref)
result_field= 0;
null_value= 1;
max_length= group_concat_max_len;
- thd->allow_sum_func= 1;
+ thd->allow_sum_func= 1;
if (!(tmp_table_param= new TMP_TABLE_PARAM))
- return 1;
+ return TRUE;
/* We'll convert all blobs to varchar fields in the temporary table */
tmp_table_param->convert_blob_length= group_concat_max_len;
tables_list= tables;
fixed= 1;
- return 0;
+ return FALSE;
}
@@ -1928,7 +2043,6 @@ bool Item_func_group_concat::setup(THD *thd)
List<Item> list;
SELECT_LEX *select_lex= thd->lex->current_select;
uint const_fields;
- byte *record;
qsort_cmp2 compare_key;
DBUG_ENTER("Item_func_group_concat::setup");
@@ -1937,7 +2051,7 @@ bool Item_func_group_concat::setup(THD *thd)
/*
push all not constant fields to list and create temp table
- */
+ */
const_fields= 0;
always_null= 0;
for (uint i= 0; i < arg_count_field; i++)
@@ -1955,15 +2069,15 @@ bool Item_func_group_concat::setup(THD *thd)
}
if (always_null)
DBUG_RETURN(0);
-
+
List<Item> all_fields(list);
- if (arg_count_order)
+ if (arg_count_order)
{
bool hidden_group_fields;
setup_group(thd, args, tables_list, list, all_fields, *order,
&hidden_group_fields);
}
-
+
count_field_types(tmp_table_param,all_fields,0);
if (table)
{
@@ -1993,7 +2107,6 @@ bool Item_func_group_concat::setup(THD *thd)
table->no_rows= 1;
key_length= table->reclength;
- record= table->record[0];
/* Offset to first result field in table */
field_list_offset= table->fields - (list.elements - const_fields);