diff options
Diffstat (limited to 'sql/item_sum.cc')
-rw-r--r-- | sql/item_sum.cc | 223 |
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); |