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.cc163
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;