|
I run this script using two timestamp values near DST change:
SET time_zone='Europe/Moscow';
|
CREATE OR REPLACE TABLE t1 (i INT, d TIMESTAMP);
|
SET timestamp=1288477526 /* this is summer time */ ;
|
INSERT INTO t1 VALUES (3,NULL);
|
SET timestamp=1288477526+3599 /* this is winter time*/ ;
|
INSERT INTO t1 VALUES (3,NULL);
|
SELECT i, d, UNIX_TIMESTAMP(d) FROM t1 ORDER BY d;
|
+------+---------------------+-------------------+
|
| i | d | UNIX_TIMESTAMP(d) |
|
+------+---------------------+-------------------+
|
| 3 | 2010-10-31 02:25:26 | 1288477526 |
|
| 3 | 2010-10-31 02:25:25 | 1288481125 |
|
+------+---------------------+-------------------+
|
The record with Unix timestamp value of 1288477526 returned first, because it is smaller.
Now I run a GROUP BY query with MIN:
SELECT i, MIN(d) FROM t1 GROUP BY i;
|
+------+---------------------+
|
| i | MIN(d) |
|
+------+---------------------+
|
| 3 | 2010-10-31 02:25:25 |
|
+------+---------------------+
|
It erroneously chose a wrong record.
This happens because TIMESTAMP in this piece of code is handled in striing format (which uses DATETIME rather than TIMESTAMP representation):
void Item_sum_hybrid::update_field()
|
{
|
DBUG_ENTER("Item_sum_hybrid::update_field");
|
Item *UNINIT_VAR(tmp_item);
|
if (unlikely(direct_added))
|
{
|
tmp_item= args[0];
|
args[0]= direct_item;
|
}
|
switch (result_type()) {
|
case STRING_RESULT:
|
min_max_update_str_field();
|
break;
|
case INT_RESULT:
|
min_max_update_int_field();
|
break;
|
case DECIMAL_RESULT:
|
min_max_update_decimal_field();
|
break;
|
default:
|
min_max_update_real_field();
|
}
|
if (unlikely(direct_added))
|
{
|
direct_added= FALSE;
|
args[0]= tmp_item;
|
}
|
DBUG_VOID_RETURN;
|
}
|
|