[MDEV-9541] Selecting a time using a datetime fails Created: 2016-02-09 Updated: 2020-12-01 |
|
| Status: | Open |
| Project: | MariaDB Server |
| Component/s: | Data types, Temporal Types |
| Affects Version/s: | 5.5.47, 10.0.23, 10.1.9, 5.3.13 |
| Fix Version/s: | 10.2 |
| Type: | Bug | Priority: | Major |
| Reporter: | Scott Bronson | Assignee: | Alexander Barkov |
| Resolution: | Unresolved | Votes: | 0 |
| Labels: | datatype | ||
| Environment: |
Ver 15.1 Distrib 10.1.9-MariaDB, for osx10.11 |
||
| Epic Link: | Data type cleanups |
| Description |
|
MariaDB seems to behave differently from other databases when selecting a time with a datetime. Maria requires truncating the date first, otherwise it returns the empty set. MySQL, Postgres, Sqlite, and SQL Server ignore the date and return rows matching the time portion. Here are the examples: https://gist.github.com/bronson/0a49e7d3fe7242cb5cd3 (thanks to litheum for this table) Monty says: what looks wrong at my end is that we are converting the string to this time: "838:49:59.99999" and then trying to compare that. This is stored in a Item_time_literal. |
| Comments |
| Comment by Sergei Golubchik [ 2016-02-09 ] | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
|
Saving the data from the paste:
| ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| Comment by Michael Widenius [ 2016-02-10 ] | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
|
The issue is caused by the code in item.cc::Item::get_time_with_conversion()
If OLD_MODE_ZERO_DATE_TIME_CAST is set, then the above returns null, which will cause the comparison to fail in equal field propagations. This will delay the comparison to Arg_comparator::compare_temporal() which will compare a time to a datetime which will of course fail. This is not how MySQL did it so the option doesn't deliver on it's promises. If OLD_MODE_ZERO_DATE_TIME_CAST is not set datetime_to_time_with_warn() is called, which will convert the datetime to a time value relative to the current time, which doesn't make any sense to me (No other database seems to do it this way and it doesn't match how insert is working). This function also tests the above flag, which is pointless in this context as it was already tested in the calling function. We only come here if the flag is set and all date parts are zero, which doesn't help this particular problem. How things should work:
Suggestion:
Open questions:
| ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| Comment by Alexander Barkov [ 2016-02-10 ] | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
|
Some background: The SQL standard does not allow direct copying or comparison between TIME and DATETIME/TIMESTAMP. The CAST from TIME to DATETIME/TIMESTAMP works as follows:
Note, the SQL standard also supports only time in the range 00:00:00..23:59:59. So
was intended to work as:
If in some cases does not work that way, it should be fixed. | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| Comment by Alexander Barkov [ 2016-02-10 ] | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
|
Also, I think we should add a note whenever automatic conversion between TIME and TIMESTAMP/DATETIME happens (both directions), | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| Comment by Alexander Barkov [ 2016-02-10 ] | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
|
The SQL standard suggests to through away the DATE part when casting from TIMESTAMP to TIME:
We do the same on INSERT:
The question is what should happen in these cases:
Should we cast both sides to TIME or to TIMESTAMP/DATETIME? The SQL standard says: | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| Comment by Sergei Golubchik [ 2016-02-10 ] | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
|
How other data types behave:
In all these cases the conversion is done in a direction to avoid data loss. | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| Comment by Alexander Barkov [ 2016-02-10 ] | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
|
PostgreSQL follows the standard (almost):
Notice, comparison of different types is generally not allowed, like the standard suggests. Comparing a TIME field to a TIMESTAMP-alike typeless string constant is possible though (but not the other way around!). It would be good to find an explanation in the PostgreSQL documentation about this. | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| Comment by Alexander Barkov [ 2016-02-10 ] | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
|
MySQL-5.7:
returns
Conversion from TIME to DATETIME happens. | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| Comment by Alexander Barkov [ 2016-02-11 ] | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
|
SQL Server 2012 works as follows:
Summary:
| ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| Comment by Alexander Barkov [ 2016-02-11 ] | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
|
Oracle 11.2 works as follows:
I.e. TIMESTAMP always wins VARCHAR. |