mirror of
https://github.com/MariaDB/server.git
synced 2025-08-08 11:22:35 +03:00
MDEV-19961 MIN(timestamp_column) returns a wrong result in a GROUP BY query
This commit is contained in:
@@ -588,5 +588,27 @@ ts cts uts ucts
|
|||||||
DROP TABLE t1,t2;
|
DROP TABLE t1,t2;
|
||||||
SET time_zone=DEFAULT;
|
SET time_zone=DEFAULT;
|
||||||
#
|
#
|
||||||
|
# MDEV-19961 MIN(timestamp_column) returns a wrong result in a GROUP BY query
|
||||||
|
#
|
||||||
|
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
|
||||||
|
SELECT i, MIN(d) FROM t1 GROUP BY i;
|
||||||
|
i MIN(d)
|
||||||
|
3 2010-10-31 02:25:26
|
||||||
|
SELECT i, MAX(d) FROM t1 GROUP BY i;
|
||||||
|
i MAX(d)
|
||||||
|
3 2010-10-31 02:25:25
|
||||||
|
DROP TABLE t1;
|
||||||
|
SET timestamp=DEFAULT;
|
||||||
|
SET time_zone=DEFAULT;
|
||||||
|
#
|
||||||
# End of 10.4 tests
|
# End of 10.4 tests
|
||||||
#
|
#
|
||||||
|
@@ -534,6 +534,24 @@ SELECT ts, cts, UNIX_TIMESTAMP(ts) AS uts, UNIX_TIMESTAMP(cts) AS ucts FROM t2;
|
|||||||
DROP TABLE t1,t2;
|
DROP TABLE t1,t2;
|
||||||
SET time_zone=DEFAULT;
|
SET time_zone=DEFAULT;
|
||||||
|
|
||||||
|
--echo #
|
||||||
|
--echo # MDEV-19961 MIN(timestamp_column) returns a wrong result in a GROUP BY query
|
||||||
|
--echo #
|
||||||
|
|
||||||
|
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;
|
||||||
|
SELECT i, MIN(d) FROM t1 GROUP BY i;
|
||||||
|
SELECT i, MAX(d) FROM t1 GROUP BY i;
|
||||||
|
DROP TABLE t1;
|
||||||
|
SET timestamp=DEFAULT;
|
||||||
|
SET time_zone=DEFAULT;
|
||||||
|
|
||||||
|
|
||||||
--echo #
|
--echo #
|
||||||
--echo # End of 10.4 tests
|
--echo # End of 10.4 tests
|
||||||
--echo #
|
--echo #
|
||||||
|
@@ -132,6 +132,9 @@ public:
|
|||||||
int compare_e_json_str();
|
int compare_e_json_str();
|
||||||
int compare_e_str_json();
|
int compare_e_str_json();
|
||||||
|
|
||||||
|
void min_max_update_field_native(THD *thd, Field *field, Item *item,
|
||||||
|
int cmp_sign);
|
||||||
|
|
||||||
Item** cache_converted_constant(THD *thd, Item **value, Item **cache,
|
Item** cache_converted_constant(THD *thd, Item **value, Item **cache,
|
||||||
const Type_handler *type);
|
const Type_handler *type);
|
||||||
inline bool is_owner_equal_func()
|
inline bool is_owner_equal_func()
|
||||||
|
@@ -3086,8 +3086,21 @@ void Item_sum_min_max::update_field()
|
|||||||
tmp_item= args[0];
|
tmp_item= args[0];
|
||||||
args[0]= direct_item;
|
args[0]= direct_item;
|
||||||
}
|
}
|
||||||
switch (result_type()) {
|
if (Item_sum_min_max::type_handler()->is_val_native_ready())
|
||||||
|
{
|
||||||
|
/*
|
||||||
|
TODO-10.5: change Item_sum_min_max to use val_native() for all data types
|
||||||
|
- make all type handlers val_native() ready
|
||||||
|
- use min_max_update_native_field() for all data types
|
||||||
|
- remove Item_sum_min_max::min_max_update_{str|real|int|decimal}_field()
|
||||||
|
*/
|
||||||
|
min_max_update_native_field();
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
switch (Item_sum_min_max::type_handler()->cmp_type()) {
|
||||||
case STRING_RESULT:
|
case STRING_RESULT:
|
||||||
|
case TIME_RESULT:
|
||||||
min_max_update_str_field();
|
min_max_update_str_field();
|
||||||
break;
|
break;
|
||||||
case INT_RESULT:
|
case INT_RESULT:
|
||||||
@@ -3099,6 +3112,7 @@ void Item_sum_min_max::update_field()
|
|||||||
default:
|
default:
|
||||||
min_max_update_real_field();
|
min_max_update_real_field();
|
||||||
}
|
}
|
||||||
|
}
|
||||||
if (unlikely(direct_added))
|
if (unlikely(direct_added))
|
||||||
{
|
{
|
||||||
direct_added= FALSE;
|
direct_added= FALSE;
|
||||||
@@ -3108,6 +3122,40 @@ void Item_sum_min_max::update_field()
|
|||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
void Arg_comparator::min_max_update_field_native(THD *thd,
|
||||||
|
Field *field,
|
||||||
|
Item *item,
|
||||||
|
int cmp_sign)
|
||||||
|
{
|
||||||
|
DBUG_ENTER("Arg_comparator::min_max_update_field_native");
|
||||||
|
if (!item->val_native(current_thd, &m_native2))
|
||||||
|
{
|
||||||
|
if (field->is_null())
|
||||||
|
field->store_native(m_native2); // The first non-null value
|
||||||
|
else
|
||||||
|
{
|
||||||
|
field->val_native(&m_native1);
|
||||||
|
if ((cmp_sign * m_compare_handler->cmp_native(m_native2, m_native1)) < 0)
|
||||||
|
field->store_native(m_native2);
|
||||||
|
}
|
||||||
|
field->set_notnull();
|
||||||
|
}
|
||||||
|
DBUG_VOID_RETURN;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
void
|
||||||
|
Item_sum_min_max::min_max_update_native_field()
|
||||||
|
{
|
||||||
|
DBUG_ENTER("Item_sum_min_max::min_max_update_native_field");
|
||||||
|
DBUG_ASSERT(cmp);
|
||||||
|
DBUG_ASSERT(type_handler_for_comparison() == cmp->compare_type_handler());
|
||||||
|
THD *thd= current_thd;
|
||||||
|
cmp->min_max_update_field_native(thd, result_field, args[0], cmp_sign);
|
||||||
|
DBUG_VOID_RETURN;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
void
|
void
|
||||||
Item_sum_min_max::min_max_update_str_field()
|
Item_sum_min_max::min_max_update_str_field()
|
||||||
{
|
{
|
||||||
|
@@ -1117,6 +1117,7 @@ public:
|
|||||||
void min_max_update_real_field();
|
void min_max_update_real_field();
|
||||||
void min_max_update_int_field();
|
void min_max_update_int_field();
|
||||||
void min_max_update_decimal_field();
|
void min_max_update_decimal_field();
|
||||||
|
void min_max_update_native_field();
|
||||||
void cleanup();
|
void cleanup();
|
||||||
bool any_value() { return was_values; }
|
bool any_value() { return was_values; }
|
||||||
void no_rows_in_result();
|
void no_rows_in_result();
|
||||||
|
@@ -3244,6 +3244,16 @@ public:
|
|||||||
{
|
{
|
||||||
return MYSQL_TIMESTAMP_ERROR;
|
return MYSQL_TIMESTAMP_ERROR;
|
||||||
}
|
}
|
||||||
|
/*
|
||||||
|
Return true if the native format is fully implemented for a data type:
|
||||||
|
- Field_xxx::val_native()
|
||||||
|
- Item_xxx::val_native() for all classes supporting this data type
|
||||||
|
- Type_handler_xxx::cmp_native()
|
||||||
|
*/
|
||||||
|
virtual bool is_val_native_ready() const
|
||||||
|
{
|
||||||
|
return false;
|
||||||
|
}
|
||||||
virtual bool is_timestamp_type() const
|
virtual bool is_timestamp_type() const
|
||||||
{
|
{
|
||||||
return false;
|
return false;
|
||||||
@@ -5582,6 +5592,10 @@ public:
|
|||||||
{
|
{
|
||||||
return MYSQL_TIMESTAMP_DATETIME;
|
return MYSQL_TIMESTAMP_DATETIME;
|
||||||
}
|
}
|
||||||
|
bool is_val_native_ready() const
|
||||||
|
{
|
||||||
|
return true;
|
||||||
|
}
|
||||||
bool is_timestamp_type() const
|
bool is_timestamp_type() const
|
||||||
{
|
{
|
||||||
return true;
|
return true;
|
||||||
|
Reference in New Issue
Block a user