From 4777370bb3f141a594ba9b6b81ea5554f3b37fbb Mon Sep 17 00:00:00 2001 From: Evgeny Potemkin Date: Mon, 19 Jul 2010 21:11:47 +0400 Subject: Bug#49771: Incorrect MIN/MAX for date/time values. This bug is a design flaw of the fix for the bug#33546. It assumed that an item can be used only in one comparison context, but actually it isn't the case. Item_cache_datetime is used to store result for MIX/MAX aggregate functions. Because Arg_comparator always compares datetime values as INTs when possible the Item_cache_datetime most time caches only INT value. But since all datetime values has STRING result type MIN/MAX functions are asked for a STRING value when the result is being sent to a client. The Item_cache_datetime was designed to avoid conversions and get INT/STRING values from an underlying item, but at the moment the values is asked underlying item doesn't hold it anymore thus wrong result is returned. Beside that MIN/MAX aggregate functions was wrongly initializing cached result and this led to a wrong result. The Item::has_compatible_context helper function is added. It checks whether this and given items has the same comparison context or can be compared as DATETIME values by Arg_comparator. The equality propagation optimization is adjusted to take into account that items which being compared as DATETIME can have different comparison contexts. The Item_cache_datetime now converts cached INT value to a correct STRING DATETIME value by means of number_to_datetime & my_TIME_to_str functions. The Arg_comparator::set_cmp_context_for_datetime helper function is added. It sets comparison context of items being compared as DATETIMEs to INT if items will be compared as longlong. The Item_sum_hybrid::setup function now correctly initializes its result value. In order to avoid unnecessary conversions Item_sum_hybrid now states that it can provide correct longlong value if the item being aggregated can do it too. mysql-test/r/group_by.result: Added a test case for the bug#49771. sql/item.cc: Bug#49771: Incorrect MIN/MAX for date/time values. The equality propagation mechanism is adjusted to take into account that items which being compared as DATETIME can have different comparison contexts. The Item_cache_datetime now converts cached INT value to a correct STRING DATETIME/TIME value. sql/item.h: Bug#49771: Incorrect MIN/MAX for date/time values. The Item::has_compatible_context helper function is added. It checks whether this and given items has the same comparison context or can be compared as DATETIME values by Arg_comparator. Added Item_cache::clear helper function. sql/item_cmpfunc.cc: Bug#49771: Incorrect MIN/MAX for date/time values. The Arg_comparator::set_cmp_func now sets the correct comparison context for items being compared as DATETIME values. sql/item_cmpfunc.h: Bug#49771: Incorrect MIN/MAX for date/time values. The Arg_comparator::set_cmp_context_for_datetime helper function is added. It sets comparison context of items being compared as DATETIMEs to INT if items will be compared as longlong. sql/item_sum.cc: Bug#49771: Incorrect MIN/MAX for date/time values. The Item_sum_hybrid::setup function now correctly initializes its result value. sql/item_sum.h: Bug#49771: Incorrect MIN/MAX for date/time values. In order to avoid unnecessary conversions Item_sum_hybrid now states that it can provide correct longlong value if the item being aggregated can do it too. --- sql/item_sum.cc | 5 ++--- 1 file changed, 2 insertions(+), 3 deletions(-) (limited to 'sql/item_sum.cc') diff --git a/sql/item_sum.cc b/sql/item_sum.cc index 77c45ea85f7..b05d845dead 100644 --- a/sql/item_sum.cc +++ b/sql/item_sum.cc @@ -1214,8 +1214,7 @@ void Item_sum_hybrid::setup_hybrid(Item *item, Item *value_arg) { value= Item_cache::get_cache(item); value->setup(item); - if (value_arg) - value->store(value_arg); + value->store(value_arg); cmp= new Arg_comparator(); cmp->set_cmp_func(this, args, (Item**)&value, FALSE); collation.set(item->collation); @@ -1903,7 +1902,7 @@ void Item_sum_variance::update_field() void Item_sum_hybrid::clear() { - value->null_value= 1; + value->clear(); null_value= 1; } -- cgit v1.2.1