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.cc96
1 files changed, 58 insertions, 38 deletions
diff --git a/sql/item_sum.cc b/sql/item_sum.cc
index 4d70debb966..51c8ba6e5da 100644
--- a/sql/item_sum.cc
+++ b/sql/item_sum.cc
@@ -353,14 +353,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,
+ byte *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;
}
}
@@ -371,26 +372,33 @@ 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);
+ field= new Field_double(max_length, maybe_null, name, decimals);
+ 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:
- if (max_length/collation.collation->mbmaxlen > 255 && 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)
+ 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;
}
@@ -538,9 +546,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)))
@@ -554,16 +563,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;
}
@@ -721,7 +735,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
@@ -1065,6 +1079,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)
{
/*
@@ -1072,14 +1087,18 @@ Field *Item_sum_avg::create_tmp_field(bool group, TABLE *table,
The easyest 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);
+ else
+ field= new Field_double(max_length, maybe_null, name, decimals);
+ if (field)
+ field->init(table);
+ return field;
}
@@ -1244,6 +1263,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)
{
/*
@@ -1251,15 +1271,19 @@ Field *Item_sum_variance::create_tmp_field(bool group, TABLE *table,
The easyest 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_size0 + dec_bin_size1 :
sizeof(double)*2) + 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);
+ else
+ field= new Field_double(max_length, maybe_null, name, decimals);
+ if (field)
+ field->init(table);
+ return field;
}
@@ -1554,16 +1578,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:
@@ -2525,7 +2546,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
@@ -2640,9 +2661,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;
}
@@ -2664,7 +2684,7 @@ longlong Item_sum_count_distinct::val_int()
return (longlong) count;
}
table->file->info(HA_STATUS_VARIABLE | HA_STATUS_NO_LOCK);
- return table->file->records;
+ return table->file->stats.records;
}