diff options
Diffstat (limited to 'sql/item_sum.cc')
-rw-r--r-- | sql/item_sum.cc | 163 |
1 files changed, 92 insertions, 71 deletions
diff --git a/sql/item_sum.cc b/sql/item_sum.cc index 92b6b57af08..df69263c705 100644 --- a/sql/item_sum.cc +++ b/sql/item_sum.cc @@ -402,14 +402,15 @@ Item *Item_sum::get_tmp_table_item(THD *thd) } -bool Item_sum::walk (Item_processor processor, byte *argument) +bool Item_sum::walk (Item_processor processor, bool walk_subquery, + uchar *argument) { if (arg_count) { Item **arg,**arg_end; for (arg= args, arg_end= args+arg_count; arg != arg_end; arg++) { - if ((*arg)->walk(processor, argument)) + if ((*arg)->walk(processor, walk_subquery, argument)) return 1; } } @@ -420,32 +421,35 @@ bool Item_sum::walk (Item_processor processor, byte *argument) Field *Item_sum::create_tmp_field(bool group, TABLE *table, uint convert_blob_length) { + Field *field; switch (result_type()) { case REAL_RESULT: - return new Field_double(max_length, maybe_null, name, table, decimals, - TRUE); + field= new Field_double(max_length, maybe_null, name, decimals, TRUE); + break; case INT_RESULT: - return new Field_longlong(max_length,maybe_null,name,table,unsigned_flag); + field= new Field_longlong(max_length, maybe_null, name, unsigned_flag); + break; case STRING_RESULT: - /* - Make sure that the blob fits into a Field_varstring which has - 2-byte lenght. - */ - if (max_length/collation.collation->mbmaxlen > 255 && - convert_blob_length <= Field_varstring::MAX_SIZE && convert_blob_length) - return new Field_varstring(convert_blob_length, maybe_null, - name, table, - collation.collation); - return make_string_field(table); -case DECIMAL_RESULT: - return new Field_new_decimal(max_length, maybe_null, name, table, + if (max_length/collation.collation->mbmaxlen <= 255 || + convert_blob_length > Field_varstring::MAX_SIZE || + !convert_blob_length) + return make_string_field(table); + field= new Field_varstring(convert_blob_length, maybe_null, + name, table->s, collation.collation); + break; + case DECIMAL_RESULT: + field= new Field_new_decimal(max_length, maybe_null, name, decimals, unsigned_flag); + break; case ROW_RESULT: default: // This case should never be choosen DBUG_ASSERT(0); return 0; } + if (field) + field->init(table); + return field; } @@ -612,9 +616,10 @@ Item_sum_hybrid::fix_fields(THD *thd, Item **ref) Field *Item_sum_hybrid::create_tmp_field(bool group, TABLE *table, uint convert_blob_length) { + Field *field; if (args[0]->type() == Item::FIELD_ITEM) { - Field *field= ((Item_field*) args[0])->field; + field= ((Item_field*) args[0])->field; if ((field= create_tmp_field_from_field(current_thd, field, name, table, NULL, convert_blob_length))) @@ -628,16 +633,21 @@ Field *Item_sum_hybrid::create_tmp_field(bool group, TABLE *table, */ switch (args[0]->field_type()) { case MYSQL_TYPE_DATE: - return new Field_date(maybe_null, name, table, collation.collation); + field= new Field_date(maybe_null, name, collation.collation); + break; case MYSQL_TYPE_TIME: - return new Field_time(maybe_null, name, table, collation.collation); + field= new Field_time(maybe_null, name, collation.collation); + break; case MYSQL_TYPE_TIMESTAMP: case MYSQL_TYPE_DATETIME: - return new Field_datetime(maybe_null, name, table, collation.collation); - default: + field= new Field_datetime(maybe_null, name, collation.collation); break; + default: + return Item_sum::create_tmp_field(group, table, convert_blob_length); } - return Item_sum::create_tmp_field(group, table, convert_blob_length); + if (field) + field->init(table); + return field; } @@ -795,7 +805,7 @@ static int simple_raw_key_cmp(void* arg, const void* key1, const void* key2) static int item_sum_distinct_walk(void *element, element_count num_of_dups, void *item) { - return ((Item_sum_distinct*) (item))->unique_walk_function(element); + return ((Item_sum_distinct*) (item))->unique_walk_function(element); } C_MODE_END @@ -902,8 +912,8 @@ void Item_sum_distinct::fix_length_and_dec() bool Item_sum_distinct::setup(THD *thd) { - List<create_field> field_list; - create_field field_def; /* field definition */ + List<Create_field> field_list; + Create_field field_def; /* field definition */ DBUG_ENTER("Item_sum_distinct::setup"); /* It's legal to call setup() more than once when in a subquery */ if (tree) @@ -1149,6 +1159,7 @@ Item *Item_sum_avg::copy_or_same(THD* thd) Field *Item_sum_avg::create_tmp_field(bool group, TABLE *table, uint convert_blob_len) { + Field *field; if (group) { /* @@ -1156,14 +1167,18 @@ Field *Item_sum_avg::create_tmp_field(bool group, TABLE *table, The easiest way is to do this is to store both value in a string and unpack on access. */ - return new Field_string(((hybrid_type == DECIMAL_RESULT) ? + field= new Field_string(((hybrid_type == DECIMAL_RESULT) ? dec_bin_size : sizeof(double)) + sizeof(longlong), - 0, name, table, &my_charset_bin); + 0, name, &my_charset_bin); } - if (hybrid_type == DECIMAL_RESULT) - return new Field_new_decimal(max_length, maybe_null, name, table, + else if (hybrid_type == DECIMAL_RESULT) + field= new Field_new_decimal(max_length, maybe_null, name, decimals, unsigned_flag); - return new Field_double(max_length, maybe_null, name, table, decimals, TRUE); + else + field= new Field_double(max_length, maybe_null, name, decimals, TRUE); + if (field) + field->init(table); + return field; } @@ -1348,6 +1363,7 @@ Item *Item_sum_variance::copy_or_same(THD* thd) Field *Item_sum_variance::create_tmp_field(bool group, TABLE *table, uint convert_blob_len) { + Field *field; if (group) { /* @@ -1355,9 +1371,15 @@ Field *Item_sum_variance::create_tmp_field(bool group, TABLE *table, The easiest way is to do this is to store both value in a string and unpack on access. */ - return new Field_string(sizeof(double)*2 + sizeof(longlong), 0, name, table, &my_charset_bin); + field= new Field_string(sizeof(double)*2 + sizeof(longlong), 0, name, &my_charset_bin); } - return new Field_double(max_length, maybe_null, name, table, decimals, TRUE); + else + field= new Field_double(max_length, maybe_null, name, decimals, TRUE); + + if (field != NULL) + field->init(table); + + return field; } @@ -1414,7 +1436,7 @@ my_decimal *Item_sum_variance::val_decimal(my_decimal *dec_buf) void Item_sum_variance::reset_field() { double nr; - char *res= result_field->ptr; + uchar *res= result_field->ptr; nr= args[0]->val_real(); /* sets null_value as side-effect */ @@ -1437,7 +1459,7 @@ void Item_sum_variance::reset_field() void Item_sum_variance::update_field() { ulonglong field_count; - char *res=result_field->ptr; + uchar *res=result_field->ptr; double nr= args[0]->val_real(); /* sets null_value as side-effect */ @@ -1568,16 +1590,13 @@ Item_sum_hybrid::val_str(String *str) case STRING_RESULT: return &value; case REAL_RESULT: - str->set(sum,decimals, &my_charset_bin); + str->set_real(sum,decimals, &my_charset_bin); break; case DECIMAL_RESULT: my_decimal2string(E_DEC_FATAL_ERROR, &sum_dec, 0, 0, 0, str); return str; case INT_RESULT: - if (unsigned_flag) - str->set((ulonglong) sum_int, &my_charset_bin); - else - str->set((longlong) sum_int, &my_charset_bin); + str->set_int(sum_int, unsigned_flag, &my_charset_bin); break; case ROW_RESULT: default: @@ -1804,7 +1823,7 @@ bool Item_sum_and::add() void Item_sum_num::reset_field() { double nr= args[0]->val_real(); - char *res=result_field->ptr; + uchar *res=result_field->ptr; if (maybe_null) { @@ -1926,7 +1945,7 @@ void Item_sum_sum::reset_field() void Item_sum_count::reset_field() { - char *res=result_field->ptr; + uchar *res=result_field->ptr; longlong nr=0; if (!args[0]->maybe_null || !args[0]->is_null()) @@ -1937,7 +1956,7 @@ void Item_sum_count::reset_field() void Item_sum_avg::reset_field() { - char *res=result_field->ptr; + uchar *res=result_field->ptr; if (hybrid_type == DECIMAL_RESULT) { longlong tmp; @@ -1978,7 +1997,7 @@ void Item_sum_bit::reset_field() void Item_sum_bit::update_field() { - char *res=result_field->ptr; + uchar *res=result_field->ptr; bits= uint8korr(res); add(); int8store(res, bits); @@ -2013,7 +2032,7 @@ void Item_sum_sum::update_field() else { double old_nr,nr; - char *res=result_field->ptr; + uchar *res=result_field->ptr; float8get(old_nr,res); nr= args[0]->val_real(); @@ -2030,7 +2049,7 @@ void Item_sum_sum::update_field() void Item_sum_count::update_field() { longlong nr; - char *res=result_field->ptr; + uchar *res=result_field->ptr; nr=sint8korr(res); if (!args[0]->maybe_null || !args[0]->is_null()) @@ -2042,7 +2061,7 @@ void Item_sum_count::update_field() void Item_sum_avg::update_field() { longlong field_count; - char *res=result_field->ptr; + uchar *res=result_field->ptr; if (hybrid_type == DECIMAL_RESULT) { my_decimal value, *arg_val= args[0]->val_decimal(&value); @@ -2211,7 +2230,7 @@ double Item_avg_field::val_real() // fix_fields() never calls for this Item double nr; longlong count; - char *res; + uchar *res; if (hybrid_type == DECIMAL_RESULT) return val_real_from_decimal(); @@ -2344,10 +2363,10 @@ double Item_variance_field::val_real() ** COUNT(DISTINCT ...) ****************************************************************************/ -int simple_str_key_cmp(void* arg, byte* key1, byte* key2) +int simple_str_key_cmp(void* arg, uchar* key1, uchar* key2) { Field *f= (Field*) arg; - return f->cmp((const char*)key1, (const char*)key2); + return f->cmp(key1, key2); } /* @@ -2357,7 +2376,7 @@ int simple_str_key_cmp(void* arg, byte* key1, byte* key2) static */ -int composite_key_cmp(void* arg, byte* key1, byte* key2) +int composite_key_cmp(void* arg, uchar* key1, uchar* key2) { Item_sum_count_distinct* item = (Item_sum_count_distinct*)arg; Field **field = item->table->field; @@ -2367,7 +2386,7 @@ int composite_key_cmp(void* arg, byte* key1, byte* key2) { Field* f = *field; int len = *lengths++; - int res = f->cmp((char *) key1, (char *) key2); + int res = f->cmp(key1, key2); if (res) return res; key1 += len; @@ -2492,7 +2511,7 @@ bool Item_sum_count_distinct::setup(THD *thd) table->file->extra(HA_EXTRA_NO_ROWS); // Don't update rows table->no_rows=1; - if (table->s->db_type == DB_TYPE_HEAP) + if (table->s->db_type() == heap_hton) { /* No blobs, otherwise it would have been MyISAM: set up a compare @@ -2612,9 +2631,8 @@ bool Item_sum_count_distinct::add() */ return tree->unique_add(table->record[0] + table->s->null_bytes); } - if ((error= table->file->write_row(table->record[0])) && - error != HA_ERR_FOUND_DUPP_KEY && - error != HA_ERR_FOUND_DUPP_UNIQUE) + if ((error= table->file->ha_write_row(table->record[0])) && + table->file->is_fatal_error(error, HA_CHECK_DUP)) return TRUE; return FALSE; } @@ -2646,7 +2664,7 @@ longlong Item_sum_count_distinct::val_int() table->file->print_error(error, MYF(0)); } - return table->file->records; + return table->file->stats.records; } @@ -2841,8 +2859,8 @@ String *Item_sum_udf_str::val_str(String *str) GROUP_CONCAT(DISTINCT expr,...) */ -int group_concat_key_cmp_with_distinct(void* arg, byte* key1, - byte* key2) +int group_concat_key_cmp_with_distinct(void* arg, uchar* key1, + uchar* key2) { Item_func_group_concat* grp_item= (Item_func_group_concat*)arg; TABLE *table= grp_item->table; @@ -2859,14 +2877,15 @@ int group_concat_key_cmp_with_distinct(void* arg, byte* key1, */ Field *field= (*field_item)->get_tmp_table_field(); /* - If field_item is a const item then either get_tp_table_field returns 0 + If field_item is a const item then either get_tmp_table_field returns 0 or it is an item over a const table. */ if (field && !(*field_item)->const_item()) { int res; - uint offset= field->offset() - table->s->null_bytes; - if ((res= field->cmp((char *) key1 + offset, (char *) key2 + offset))) + uint offset= (field->offset(field->table->record[0]) - + table->s->null_bytes); + if ((res= field->cmp(key1 + offset, key2 + offset))) return res; } } @@ -2879,7 +2898,7 @@ int group_concat_key_cmp_with_distinct(void* arg, byte* key1, GROUP_CONCAT(expr,... ORDER BY col,... ) */ -int group_concat_key_cmp_with_order(void* arg, byte* key1, byte* key2) +int group_concat_key_cmp_with_order(void* arg, uchar* key1, uchar* key2) { Item_func_group_concat* grp_item= (Item_func_group_concat*) arg; ORDER **order_item, **end; @@ -2903,8 +2922,9 @@ int group_concat_key_cmp_with_order(void* arg, byte* key1, byte* key2) if (field && !item->const_item()) { int res; - uint offset= field->offset() - table->s->null_bytes; - if ((res= field->cmp((char *) key1 + offset, (char *) key2 + offset))) + uint offset= (field->offset(field->table->record[0]) - + table->s->null_bytes); + if ((res= field->cmp(key1 + offset, key2 + offset))) return (*order_item)->asc ? res : -res; } } @@ -2927,8 +2947,8 @@ int group_concat_key_cmp_with_order(void* arg, byte* key1, byte* key2) the duplicated values when inserting things sorted by ORDER BY */ -int group_concat_key_cmp_with_distinct_and_order(void* arg,byte* key1, - byte* key2) +int group_concat_key_cmp_with_distinct_and_order(void* arg,uchar* key1, + uchar* key2) { if (!group_concat_key_cmp_with_distinct(arg,key1,key2)) return 0; @@ -2940,7 +2960,7 @@ int group_concat_key_cmp_with_distinct_and_order(void* arg,byte* key1, Append data from current leaf to item->result */ -int dump_leaf_key(byte* key, element_count count __attribute__((unused)), +int dump_leaf_key(uchar* key, element_count count __attribute__((unused)), Item_func_group_concat *item) { TABLE *table= item->table; @@ -2971,9 +2991,10 @@ int dump_leaf_key(byte* key, element_count count __attribute__((unused)), because it contains both order and arg list fields. */ Field *field= (*arg)->get_tmp_table_field(); - uint offset= field->offset() - table->s->null_bytes; + uint offset= (field->offset(field->table->record[0]) - + table->s->null_bytes); DBUG_ASSERT(offset < table->s->reclength); - res= field->val_str(&tmp, (char *) key + offset); + res= field->val_str(&tmp, key + offset); } else res= (*arg)->val_str(&tmp); @@ -3239,7 +3260,7 @@ Item_func_group_concat::fix_fields(THD *thd, Item **ref) char *buf; String *new_separator; - if (!(buf= thd->stmt_arena->alloc(buflen)) || + if (!(buf= (char*) thd->stmt_arena->alloc(buflen)) || !(new_separator= new(thd->stmt_arena->mem_root) String(buf, buflen, collation.collation))) return TRUE; |