diff options
author | Alexander Barkov <bar@mariadb.org> | 2018-02-14 22:58:34 +0400 |
---|---|---|
committer | Alexander Barkov <bar@mariadb.org> | 2018-02-14 22:58:34 +0400 |
commit | c17a06abf8f7418091b87abd5e1fa7c6522c7591 (patch) | |
tree | 9f8aa80599830631f6210d3a961f113e544e45c1 /sql-common | |
parent | 1fe9092d0684bd8fb2985093f341c54204d280b1 (diff) | |
download | mariadb-git-c17a06abf8f7418091b87abd5e1fa7c6522c7591.tar.gz |
MDEV-15310 Range optimizer does not work well for "WHERE temporal_column NOT IN (const_list)"
There were two problems related to the bug report:
1. Item_datetime::get_date() was not implemented.
So execution went through val_int() followed
by int-to-datetime or int-to-time conversion.
This was the reason why the optimizer did not
work well on data with fractional seconds.
2. Item_datetime::set() did not have a TIME specific code
to mix months and days to hours after unpack_time().
This is why the optimizer did not work well with negative
TIME values, as well as huge time values.
Changes:
1. Overriding Item_datetime::get_date(), to return ltime.
This fixes the problem N1.
2. Cleanup: Moving pack_time() and unpack_time() from
sql-common/my_time.c and include/my_time.h to
sql/sql_time.cc and sql/sql_time.h, as they are not needed
on the client side.
3. Adding a new "enum_mysql_timestamp_type ts_type" parameter
to unpack_time() and moving the TIME specific code to mix
months and days with hours inside unpack_time().
Adding a new "ts_type" parameter to Item_datetime::set(),
to pass it from the caller down to unpack_time().
So now the TIME specific code is automatically called
from Item_datetime::set(). This fixes the problem N2.
This change also helped to get rid of duplicate TIME specific code
from other three places, where mixing month/days to hours
was done immediately after unpack_time().
Moving the DATE specific code to zero hhmmssff
from Item_func_min_max::get_date_native to inside unpack_time(),
for symmetry.
4. Removing the virtual method in_vector::result_type(),
adding in_vector::type_handler() instead.
This helps to get result_type(), field_type(),
mysql_timestamp_type() of an in_vector easier.
Passing type_handler()->mysql_timestamp_type() as
a new parameter to Item_datetime::set() inside
in_temporal::value_to_item().
5. Cleaup: Removing separate implementations of in_datetime::get_value()
and in_time::get_value(). Adding a single implementation
in_temporal::get_value() instead.
Passing type_handler()->field_type() to get_value_internal().
Diffstat (limited to 'sql-common')
-rw-r--r-- | sql-common/my_time.c | 28 |
1 files changed, 0 insertions, 28 deletions
diff --git a/sql-common/my_time.c b/sql-common/my_time.c index d7953fe36bf..0fa5e5ff1bb 100644 --- a/sql-common/my_time.c +++ b/sql-common/my_time.c @@ -1425,31 +1425,3 @@ double TIME_to_double(const MYSQL_TIME *my_time) d+= my_time->second_part/(double)TIME_SECOND_PART_FACTOR; return my_time->neg ? -d : d; } - -longlong pack_time(const MYSQL_TIME *my_time) -{ - return ((((((my_time->year * 13ULL + - my_time->month) * 32ULL + - my_time->day) * 24ULL + - my_time->hour) * 60ULL + - my_time->minute) * 60ULL + - my_time->second) * 1000000ULL + - my_time->second_part) * (my_time->neg ? -1 : 1); -} - -#define get_one(WHERE, FACTOR) WHERE= (ulong)(packed % FACTOR); packed/= FACTOR - -MYSQL_TIME *unpack_time(longlong packed, MYSQL_TIME *my_time) -{ - if ((my_time->neg= packed < 0)) - packed= -packed; - get_one(my_time->second_part, 1000000ULL); - get_one(my_time->second, 60U); - get_one(my_time->minute, 60U); - get_one(my_time->hour, 24U); - get_one(my_time->day, 32U); - get_one(my_time->month, 13U); - my_time->year= (uint)packed; - my_time->time_type= MYSQL_TIMESTAMP_DATETIME; - return my_time; -} |