Skip to content
Permalink
Browse files
Merge remote-tracking branch 'origin/10.4' into 10.5
  • Loading branch information
abarkov committed Aug 22, 2020
2 parents ee61c8c + ae33ebe commit 6708e67
Show file tree
Hide file tree
Showing 10 changed files with 367 additions and 4 deletions.
@@ -2286,5 +2286,127 @@ SELECT '1972-11-06 16:58:58' < TIME'20:31:05';
'1972-11-06 16:58:58' < TIME'20:31:05'
1
#
# MDEV-23525 Wrong result of MIN(time_expr) and MAX(time_expr) with GROUP BY
#
SET timestamp=UNIX_TIMESTAMP('2020-08-21 18:19:20');
CREATE PROCEDURE p1()
BEGIN
SELECT MIN(t), MAX(t) FROM t1;
SELECT i, MIN(t), MAX(t) FROM t1 GROUP BY i;
SELECT i, MIN(COALESCE(t)), MAX(COALESCE(t)) FROM t1 GROUP BY i;
SELECT i, MIN(t+INTERVAL 1 SECOND), MAX(t+INTERVAL 1 SECOND) FROM t1 GROUP BY i;
SELECT i, MIN(TIME'10:20:30'+INTERVAL 1 SECOND) FROM t1 GROUP BY i;
SELECT i, MIN(CURRENT_TIME), MAX(CURRENT_TIME) FROM t1 GROUP BY i;
SELECT
i,
MIN((SELECT MAX(CURRENT_TIME) FROM t1)),
MAX((SELECT MAX(CURRENT_TIME) FROM t1))
FROM t1 GROUP BY i;
SELECT
i,
MIN(NAME_CONST('name',TIME'10:20:30')),
MAX(NAME_CONST('name',TIME'10:20:30'))
FROM t1 GROUP BY i;
EXECUTE IMMEDIATE "SELECT i, MIN(?),MAX(?) FROM t1 GROUP BY i"
USING TIME'10:20:30', TIME'10:20:30';
END;
$$
CREATE TABLE t1 (i INT, t TIME);
INSERT INTO t1 VALUES (1,'10:20:30');
INSERT INTO t1 VALUES (1,'100:20:20');
CALL p1;
MIN(t) MAX(t)
10:20:30 100:20:20
i MIN(t) MAX(t)
1 10:20:30 100:20:20
i MIN(COALESCE(t)) MAX(COALESCE(t))
1 10:20:30 100:20:20
i MIN(t+INTERVAL 1 SECOND) MAX(t+INTERVAL 1 SECOND)
1 10:20:31 100:20:21
i MIN(TIME'10:20:30'+INTERVAL 1 SECOND)
1 10:20:31
i MIN(CURRENT_TIME) MAX(CURRENT_TIME)
1 18:19:20 18:19:20
i MIN((SELECT MAX(CURRENT_TIME) FROM t1)) MAX((SELECT MAX(CURRENT_TIME) FROM t1))
1 18:19:20 18:19:20
i MIN(NAME_CONST('name',TIME'10:20:30')) MAX(NAME_CONST('name',TIME'10:20:30'))
1 10:20:30 10:20:30
i MIN(?) MAX(?)
1 10:20:30 10:20:30
DROP TABLE t1;
CREATE TABLE t1 (i INT, t TIME(3));
INSERT INTO t1 VALUES (1,'10:20:30.123');
INSERT INTO t1 VALUES (1,'100:20:20.123');
CALL p1;
MIN(t) MAX(t)
10:20:30.123 100:20:20.123
i MIN(t) MAX(t)
1 10:20:30.123 100:20:20.123
i MIN(COALESCE(t)) MAX(COALESCE(t))
1 10:20:30.123 100:20:20.123
i MIN(t+INTERVAL 1 SECOND) MAX(t+INTERVAL 1 SECOND)
1 10:20:31.123 100:20:21.123
i MIN(TIME'10:20:30'+INTERVAL 1 SECOND)
1 10:20:31
i MIN(CURRENT_TIME) MAX(CURRENT_TIME)
1 18:19:20 18:19:20
i MIN((SELECT MAX(CURRENT_TIME) FROM t1)) MAX((SELECT MAX(CURRENT_TIME) FROM t1))
1 18:19:20 18:19:20
i MIN(NAME_CONST('name',TIME'10:20:30')) MAX(NAME_CONST('name',TIME'10:20:30'))
1 10:20:30 10:20:30
i MIN(?) MAX(?)
1 10:20:30 10:20:30
DROP TABLE t1;
CREATE TABLE t1 (i INT, t TIME(6));
INSERT INTO t1 VALUES (1,'10:20:30.123456');
INSERT INTO t1 VALUES (1,'100:20:20.123456');
CALL p1;
MIN(t) MAX(t)
10:20:30.123456 100:20:20.123456
i MIN(t) MAX(t)
1 10:20:30.123456 100:20:20.123456
i MIN(COALESCE(t)) MAX(COALESCE(t))
1 10:20:30.123456 100:20:20.123456
i MIN(t+INTERVAL 1 SECOND) MAX(t+INTERVAL 1 SECOND)
1 10:20:31.123456 100:20:21.123456
i MIN(TIME'10:20:30'+INTERVAL 1 SECOND)
1 10:20:31
i MIN(CURRENT_TIME) MAX(CURRENT_TIME)
1 18:19:20 18:19:20
i MIN((SELECT MAX(CURRENT_TIME) FROM t1)) MAX((SELECT MAX(CURRENT_TIME) FROM t1))
1 18:19:20 18:19:20
i MIN(NAME_CONST('name',TIME'10:20:30')) MAX(NAME_CONST('name',TIME'10:20:30'))
1 10:20:30 10:20:30
i MIN(?) MAX(?)
1 10:20:30 10:20:30
DROP TABLE t1;
SET @@global.mysql56_temporal_format=false;
CREATE TABLE t1 (i INT, t TIME(6));
INSERT INTO t1 VALUES (1,'10:20:30.123456');
INSERT INTO t1 VALUES (1,'100:20:20.123456');
CALL p1;
MIN(t) MAX(t)
10:20:30.123456 100:20:20.123456
i MIN(t) MAX(t)
1 10:20:30.123456 100:20:20.123456
i MIN(COALESCE(t)) MAX(COALESCE(t))
1 10:20:30.123456 100:20:20.123456
i MIN(t+INTERVAL 1 SECOND) MAX(t+INTERVAL 1 SECOND)
1 10:20:31.123456 100:20:21.123456
i MIN(TIME'10:20:30'+INTERVAL 1 SECOND)
1 10:20:31
i MIN(CURRENT_TIME) MAX(CURRENT_TIME)
1 18:19:20 18:19:20
i MIN((SELECT MAX(CURRENT_TIME) FROM t1)) MAX((SELECT MAX(CURRENT_TIME) FROM t1))
1 18:19:20 18:19:20
i MIN(NAME_CONST('name',TIME'10:20:30')) MAX(NAME_CONST('name',TIME'10:20:30'))
1 10:20:30 10:20:30
i MIN(?) MAX(?)
1 10:20:30 10:20:30
DROP TABLE t1;
SET @@global.mysql56_temporal_format=default;
DROP PROCEDURE p1;
SET timestamp=DEFAULT;
#
# End of 10.4 tests
#
@@ -1490,6 +1490,66 @@ DROP TABLE t1;

SELECT '1972-11-06 16:58:58' < TIME'20:31:05';

--echo #
--echo # MDEV-23525 Wrong result of MIN(time_expr) and MAX(time_expr) with GROUP BY
--echo #

SET timestamp=UNIX_TIMESTAMP('2020-08-21 18:19:20');

DELIMITER $$;
CREATE PROCEDURE p1()
BEGIN
SELECT MIN(t), MAX(t) FROM t1;
SELECT i, MIN(t), MAX(t) FROM t1 GROUP BY i;
SELECT i, MIN(COALESCE(t)), MAX(COALESCE(t)) FROM t1 GROUP BY i;
SELECT i, MIN(t+INTERVAL 1 SECOND), MAX(t+INTERVAL 1 SECOND) FROM t1 GROUP BY i;
SELECT i, MIN(TIME'10:20:30'+INTERVAL 1 SECOND) FROM t1 GROUP BY i;
SELECT i, MIN(CURRENT_TIME), MAX(CURRENT_TIME) FROM t1 GROUP BY i;
SELECT
i,
MIN((SELECT MAX(CURRENT_TIME) FROM t1)),
MAX((SELECT MAX(CURRENT_TIME) FROM t1))
FROM t1 GROUP BY i;
SELECT
i,
MIN(NAME_CONST('name',TIME'10:20:30')),
MAX(NAME_CONST('name',TIME'10:20:30'))
FROM t1 GROUP BY i;
EXECUTE IMMEDIATE "SELECT i, MIN(?),MAX(?) FROM t1 GROUP BY i"
USING TIME'10:20:30', TIME'10:20:30';
END;
$$
DELIMITER ;$$

CREATE TABLE t1 (i INT, t TIME);
INSERT INTO t1 VALUES (1,'10:20:30');
INSERT INTO t1 VALUES (1,'100:20:20');
CALL p1;
DROP TABLE t1;

CREATE TABLE t1 (i INT, t TIME(3));
INSERT INTO t1 VALUES (1,'10:20:30.123');
INSERT INTO t1 VALUES (1,'100:20:20.123');
CALL p1;
DROP TABLE t1;

CREATE TABLE t1 (i INT, t TIME(6));
INSERT INTO t1 VALUES (1,'10:20:30.123456');
INSERT INTO t1 VALUES (1,'100:20:20.123456');
CALL p1;
DROP TABLE t1;

SET @@global.mysql56_temporal_format=false;
CREATE TABLE t1 (i INT, t TIME(6));
INSERT INTO t1 VALUES (1,'10:20:30.123456');
INSERT INTO t1 VALUES (1,'100:20:20.123456');
CALL p1;
DROP TABLE t1;
SET @@global.mysql56_temporal_format=default;

DROP PROCEDURE p1;
SET timestamp=DEFAULT;

--echo #
--echo # End of 10.4 tests
--echo #
@@ -6085,6 +6085,24 @@ bool Field_time0::get_date(MYSQL_TIME *ltime, date_mode_t fuzzydate)
}


int Field_time::store_native(const Native &value)
{
Time t(value);
DBUG_ASSERT(t.is_valid_time());
store_TIME(t);
return 0;
}


bool Field_time::val_native(Native *to)
{
MYSQL_TIME ltime;
get_date(&ltime, date_mode_t(0));
int warn;
return Time(&warn, &ltime, 0).to_native(to, decimals());
}


bool Field_time::send(Protocol *protocol)
{
MYSQL_TIME ltime;
@@ -6321,6 +6339,22 @@ Binlog_type_info Field_timef::binlog_type_info() const
return Binlog_type_info(Field_timef::binlog_type(), decimals(), 1);
}

int Field_timef::store_native(const Native &value)
{
DBUG_ASSERT(value.length() == my_time_binary_length(dec));
DBUG_ASSERT(Time(value).is_valid_time());
memcpy(ptr, value.ptr(), value.length());
return 0;
}


bool Field_timef::val_native(Native *to)
{
uint32 binlen= my_time_binary_length(dec);
return to->copy((const char*) ptr, binlen);
}


/****************************************************************************
** year type
** Save in a byte the year 0, 1901->2155
@@ -3560,6 +3560,8 @@ class Field_time :public Field_temporal {
decimals() == from->decimals();
}
sql_mode_t conversion_depends_on_sql_mode(THD *, Item *) const override;
int store_native(const Native &value) override;
bool val_native(Native *to) override;
int store_time_dec(const MYSQL_TIME *ltime, uint dec) override;
int store(const char *to,size_t length,CHARSET_INFO *charset) override;
int store(double nr) override;
@@ -3711,6 +3713,8 @@ class Field_timef final :public Field_time_with_dec {
}
int reset() override;
bool get_date(MYSQL_TIME *ltime, date_mode_t fuzzydate) override;
int store_native(const Native &value) override;
bool val_native(Native *to) override;
uint size_of() const override { return sizeof *this; }
Binlog_type_info binlog_type_info() const override;
};
@@ -2064,6 +2064,11 @@ bool Item_name_const::get_date(THD *thd, MYSQL_TIME *ltime, date_mode_t fuzzydat
return rc;
}

bool Item_name_const::val_native(THD *thd, Native *to)
{
return val_native_from_item(thd, value_item, to);
}

bool Item_name_const::is_null()
{
return value_item->is_null();
@@ -1333,16 +1333,13 @@ class Item: public Value_source,
{
/*
The default implementation for the Items that do not need native format:
- Item_basic_value
- Item_basic_value (default implementation)
- Item_copy
- Item_exists_subselect
- Item_sum_field
- Item_sum_or_func (default implementation)
- Item_proc
- Item_type_holder (as val_xxx() are never called for it);
- TODO: Item_name_const will need val_native() in the future,
when we add this syntax:
TIMESTAMP WITH LOCAL TIMEZONE'2001-01-01 00:00:00'

These hybrid Item types override val_native():
- Item_field
@@ -1353,6 +1350,8 @@ class Item: public Value_source,
- Item_direct_ref
- Item_direct_view_ref
- Item_ref_null_helper
- Item_name_const
- Item_time_literal
- Item_sum_or_func
Note, these hybrid type Item_sum_or_func descendants
override the default implementation:
@@ -3173,6 +3172,7 @@ class Item_name_const : public Item_fixed_hybrid
String *val_str(String *sp);
my_decimal *val_decimal(my_decimal *);
bool get_date(THD *thd, MYSQL_TIME *ltime, date_mode_t fuzzydate);
bool val_native(THD *thd, Native *to);
bool is_null();
virtual void print(String *str, enum_query_type query_type);

@@ -4897,6 +4897,10 @@ class Item_time_literal: public Item_temporal_literal
String *val_str(String *to) { return Time(this).to_string(to, decimals); }
my_decimal *val_decimal(my_decimal *to) { return Time(this).to_decimal(to); }
bool get_date(THD *thd, MYSQL_TIME *res, date_mode_t fuzzydate);
bool val_native(THD *thd, Native *to)
{
return Time(thd, this).to_native(to, decimals);
}
Item *get_copy(THD *thd)
{ return get_item_copy<Item_time_literal>(thd, this); }
};
@@ -6874,6 +6878,10 @@ class Item_cache_time: public Item_cache_temporal
{
return has_value() ? Time(this).to_decimal(to) : NULL;
}
bool val_native(THD *thd, Native *to)
{
return has_value() ? Time(thd, this).to_native(to, decimals) : true;
}
};


@@ -485,6 +485,12 @@ class Item_handled_func: public Item_func
virtual longlong val_int(Item_handled_func *) const= 0;
virtual my_decimal *val_decimal(Item_handled_func *, my_decimal *) const= 0;
virtual bool get_date(THD *thd, Item_handled_func *, MYSQL_TIME *, date_mode_t fuzzydate) const= 0;
virtual bool val_native(THD *thd, Item_handled_func *, Native *to) const
{
DBUG_ASSERT(0);
to->length(0);
return true;
}
virtual const Type_handler *
return_type_handler(const Item_handled_func *item) const= 0;
virtual const Type_handler *
@@ -631,6 +637,10 @@ class Item_handled_func: public Item_func
{
return Time(item).to_string(to, item->decimals);
}
bool val_native(THD *thd, Item_handled_func *item, Native *to) const
{
return Time(thd, item).to_native(to, item->decimals);
}
};


@@ -788,6 +798,10 @@ class Item_handled_func: public Item_func
{
return m_func_handler->get_date(thd, this, to, fuzzydate);
}
bool val_native(THD *thd, Native *to)
{
return m_func_handler->val_native(thd, this, to);
}
};


@@ -598,6 +598,10 @@ class Item_timefunc :public Item_func
double val_real() { return Time(this).to_double(); }
String *val_str(String *to) { return Time(this).to_string(to, decimals); }
my_decimal *val_decimal(my_decimal *to) { return Time(this).to_decimal(to); }
bool val_native(THD *thd, Native *to)
{
return Time(thd, this).to_native(to, decimals);
}
};


0 comments on commit 6708e67

Please sign in to comment.