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