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.cc66
1 files changed, 49 insertions, 17 deletions
diff --git a/sql/item_sum.cc b/sql/item_sum.cc
index c3835c7536c..d60eb1415b9 100644
--- a/sql/item_sum.cc
+++ b/sql/item_sum.cc
@@ -1,4 +1,4 @@
-/* Copyright (c) 2000, 2010, Oracle and/or its affiliates. All rights reserved.
+/* Copyright (c) 2000, 2010, Oracle and/or its affiliates.
This program is free software; you can redistribute it and/or modify
it under the terms of the GNU General Public License as published by
@@ -331,7 +331,6 @@ bool Item_sum::register_sum_func(THD *thd, Item **ref)
if (aggr_level >= 0)
{
ref_by= ref;
- thd->lex->current_select->register_dependency_item(aggr_sel, ref);
/* Add the object to the list of registered objects assigned to aggr_sel */
if (!aggr_sel->inner_sum_func_list)
next= this;
@@ -368,6 +367,16 @@ bool Item_sum::register_sum_func(THD *thd, Item **ref)
}
+bool Item_sum::collect_outer_ref_processor(uchar *param)
+{
+ Collect_deps_prm *prm= (Collect_deps_prm *)param;
+ SELECT_LEX *ds;
+ if ((ds= depended_from()) && ds->nest_level < prm->nest_level)
+ prm->parameters->add_unique(this, &cmp_items);
+ return FALSE;
+}
+
+
Item_sum::Item_sum(List<Item> &list) :arg_count(list.elements),
forced_const(FALSE)
{
@@ -432,6 +441,7 @@ void Item_sum::mark_as_sum_func()
cur_select->n_sum_items++;
cur_select->with_sum_func= 1;
with_sum_func= 1;
+ with_field= 0;
}
@@ -498,7 +508,7 @@ bool Item_sum::walk (Item_processor processor, bool walk_subquery,
Field *Item_sum::create_tmp_field(bool group, TABLE *table,
uint convert_blob_length)
{
- Field *field;
+ Field *UNINIT_VAR(field);
switch (result_type()) {
case REAL_RESULT:
field= new Field_double(max_length, maybe_null, name, decimals, TRUE);
@@ -518,7 +528,8 @@ Field *Item_sum::create_tmp_field(bool group, TABLE *table,
field= Field_new_decimal::create_from_item(this);
break;
case ROW_RESULT:
- default:
+ case TIME_RESULT:
+ case IMPOSSIBLE_RESULT:
// This case should never be choosen
DBUG_ASSERT(0);
return 0;
@@ -543,7 +554,7 @@ void Item_sum::update_used_tables ()
used_tables_cache&= PSEUDO_TABLE_BITS;
/* the aggregate function is aggregated into its local context */
- used_tables_cache |= (1 << aggr_sel->join->tables) - 1;
+ used_tables_cache |= (1 << aggr_sel->join->table_count) - 1;
}
}
@@ -985,7 +996,7 @@ bool Aggregator_distinct::add()
*/
return tree->unique_add(table->record[0] + table->s->null_bytes);
}
- if ((error= table->file->ha_write_row(table->record[0])) &&
+ if ((error= table->file->ha_write_tmp_row(table->record[0])) &&
table->file->is_fatal_error(error, HA_CHECK_DUP))
return TRUE;
return FALSE;
@@ -1154,7 +1165,8 @@ Item_sum_hybrid::fix_fields(THD *thd, Item **ref)
max_length= float_length(decimals);
break;
case ROW_RESULT:
- default:
+ case TIME_RESULT:
+ case IMPOSSIBLE_RESULT:
DBUG_ASSERT(0);
};
setup_hybrid(args[0], NULL);
@@ -1189,17 +1201,31 @@ Item_sum_hybrid::fix_fields(THD *thd, Item **ref)
Setup cache/comparator of MIN/MAX functions. When called by the
copy_or_same function value_arg parameter contains calculated value
of the original MIN/MAX object and it is saved in this object's cache.
+
+ We mark the value and arg_cache with 'RAND_TABLE_BIT' to ensure
+ that Arg_comparator::compare_datetime() doesn't allocate new
+ item inside of Arg_comparator. This would cause compare_datetime()
+ and Item_sum_min::add() to use different values!
*/
void Item_sum_hybrid::setup_hybrid(Item *item, Item *value_arg)
{
- value= Item_cache::get_cache(item);
+ if (!(value= Item_cache::get_cache(item)))
+ return;
value->setup(item);
value->store(value_arg);
- arg_cache= Item_cache::get_cache(item);
+ /* Don't cache value, as it will change */
+ if (!item->const_item())
+ value->set_used_tables(RAND_TABLE_BIT);
+ if (!(arg_cache= Item_cache::get_cache(item, item->cmp_type())))
+ return;
arg_cache->setup(item);
+ /* Don't cache value, as it will change */
+ if (!item->const_item())
+ arg_cache->set_used_tables(RAND_TABLE_BIT);
cmp= new Arg_comparator();
- cmp->set_cmp_func(this, (Item**)&arg_cache, (Item**)&value, FALSE);
+ if (cmp)
+ cmp->set_cmp_func(this, (Item**)&arg_cache, (Item**)&value, FALSE);
collation.set(item->collation);
}
@@ -1224,14 +1250,17 @@ Field *Item_sum_hybrid::create_tmp_field(bool group, TABLE *table,
*/
switch (args[0]->field_type()) {
case MYSQL_TYPE_DATE:
- field= new Field_newdate(maybe_null, name, collation.collation);
+ field= new Field_newdate(0, maybe_null ? (uchar*)"" : 0, 0, Field::NONE,
+ name, collation.collation);
break;
case MYSQL_TYPE_TIME:
- field= new Field_time(maybe_null, name, collation.collation);
+ field= new_Field_time(0, maybe_null ? (uchar*)"" : 0, 0, Field::NONE,
+ name, decimals, collation.collation);
break;
case MYSQL_TYPE_TIMESTAMP:
case MYSQL_TYPE_DATETIME:
- field= new Field_datetime(maybe_null, name, collation.collation);
+ field= new_Field_datetime(0, maybe_null ? (uchar*)"" : 0, 0, Field::NONE,
+ name, decimals, collation.collation);
break;
default:
return Item_sum::create_tmp_field(group, table, convert_blob_length);
@@ -1290,13 +1319,14 @@ void Item_sum_sum::fix_length_and_dec()
DBUG_ENTER("Item_sum_sum::fix_length_and_dec");
maybe_null=null_value=1;
decimals= args[0]->decimals;
- switch (args[0]->result_type()) {
+ switch (args[0]->cast_to_int_type()) {
case REAL_RESULT:
case STRING_RESULT:
hybrid_type= REAL_RESULT;
sum= 0.0;
break;
case INT_RESULT:
+ case TIME_RESULT:
case DECIMAL_RESULT:
{
/* SUM result can't be longer than length(arg) + length(MAX_ROWS) */
@@ -1310,7 +1340,7 @@ void Item_sum_sum::fix_length_and_dec()
break;
}
case ROW_RESULT:
- default:
+ case IMPOSSIBLE_RESULT:
DBUG_ASSERT(0);
}
DBUG_PRINT("info", ("Type: %s (%d, %d)",
@@ -1747,7 +1777,8 @@ void Item_sum_variance::fix_length_and_dec()
break;
}
case ROW_RESULT:
- default:
+ case TIME_RESULT:
+ case IMPOSSIBLE_RESULT:
DBUG_ASSERT(0);
}
DBUG_PRINT("info", ("Type: REAL_RESULT (%d, %d)", max_length, (int)decimals));
@@ -2184,7 +2215,8 @@ void Item_sum_hybrid::reset_field()
break;
}
case ROW_RESULT:
- default:
+ case TIME_RESULT:
+ case IMPOSSIBLE_RESULT:
DBUG_ASSERT(0);
}
}