Skip to content
Projects
Groups
Snippets
Help
Loading...
Help
Support
Keyboard shortcuts
?
Submit feedback
Contribute to GitLab
Sign in / Register
Toggle navigation
M
MariaDB
Project overview
Project overview
Details
Activity
Releases
Repository
Repository
Files
Commits
Branches
Tags
Contributors
Graph
Compare
Issues
0
Issues
0
List
Boards
Labels
Milestones
Merge Requests
0
Merge Requests
0
CI / CD
CI / CD
Pipelines
Jobs
Schedules
Analytics
Analytics
CI / CD
Repository
Value Stream
Wiki
Wiki
Snippets
Snippets
Members
Members
Collapse sidebar
Close sidebar
Activity
Graph
Create a new issue
Jobs
Commits
Issue Boards
Open sidebar
nexedi
MariaDB
Commits
d2ba9edd
Commit
d2ba9edd
authored
6 years ago
by
Alexander Barkov
Browse files
Options
Browse Files
Download
Email Patches
Plain Diff
MDEV-17740 Extend EXTRACT(x AS DAY*) to understand long time intervals
parent
f92d223f
Changes
13
Expand all
Hide whitespace changes
Inline
Side-by-side
Showing
13 changed files
with
1234 additions
and
140 deletions
+1234
-140
include/my_time.h
include/my_time.h
+26
-2
libmysqld/libmysql.c
libmysqld/libmysql.c
+2
-1
mysql-test/main/func_extract.result
mysql-test/main/func_extract.result
+555
-0
mysql-test/main/func_extract.test
mysql-test/main/func_extract.test
+250
-0
mysql-test/main/func_time.result
mysql-test/main/func_time.result
+2
-6
mysql-test/main/str_to_datetime_457.result
mysql-test/main/str_to_datetime_457.result
+1
-4
sql-common/my_time.c
sql-common/my_time.c
+255
-87
sql/item_timefunc.cc
sql/item_timefunc.cc
+7
-5
sql/item_timefunc.h
sql/item_timefunc.h
+2
-2
sql/sql_basic_types.h
sql/sql_basic_types.h
+9
-5
sql/sql_time.cc
sql/sql_time.cc
+14
-12
sql/sql_type.cc
sql/sql_type.cc
+6
-5
sql/sql_type.h
sql/sql_type.h
+105
-11
No files found.
include/my_time.h
View file @
d2ba9edd
...
...
@@ -79,6 +79,16 @@ extern uchar days_in_month[];
/* Useful constants */
#define SECONDS_IN_24H 86400L
/* Limits for the INTERVAL data type */
/* Number of hours between '0001-01-01 00h' and '9999-12-31 23h' */
#define TIME_MAX_INTERVAL_HOUR 87649415
#define TIME_MAX_INTERVAL_HOUR_CHAR_LENGTH 8
/* Number of full days between '0001-01-01' and '9999-12-31'*/
#define TIME_MAX_INTERVAL_DAY 3652058
/*87649415/24*/
#define TIME_MAX_INTERVAL_DAY_CHAR_LENGTH 7
/* Limits for the TIME data type */
#define TIME_MAX_HOUR 838
#define TIME_MAX_MINUTE 59
...
...
@@ -112,7 +122,21 @@ my_bool str_to_DDhhmmssff(const char *str, size_t length, MYSQL_TIME *l_time,
ulong
max_hour
,
MYSQL_TIME_STATUS
*
status
);
my_bool
str_to_datetime_or_date_or_time
(
const
char
*
str
,
size_t
length
,
MYSQL_TIME
*
to
,
ulonglong
flag
,
MYSQL_TIME_STATUS
*
status
);
MYSQL_TIME_STATUS
*
status
,
ulong
time_max_hour
,
ulong
time_err_hour
);
my_bool
str_to_datetime_or_date_or_interval_hhmmssff
(
const
char
*
str
,
size_t
length
,
MYSQL_TIME
*
to
,
ulonglong
flag
,
MYSQL_TIME_STATUS
*
status
,
ulong
time_max_hour
,
ulong
time_err_hour
);
my_bool
str_to_datetime_or_date_or_interval_day
(
const
char
*
str
,
size_t
length
,
MYSQL_TIME
*
to
,
ulonglong
flag
,
MYSQL_TIME_STATUS
*
status
,
ulong
time_max_hour
,
ulong
time_err_hour
);
my_bool
str_to_datetime_or_date
(
const
char
*
str
,
size_t
length
,
MYSQL_TIME
*
to
,
ulonglong
flags
,
MYSQL_TIME_STATUS
*
status
);
...
...
@@ -120,7 +144,7 @@ longlong number_to_datetime_or_date(longlong nr, ulong sec_part,
MYSQL_TIME
*
time_res
,
ulonglong
flags
,
int
*
was_cut
);
int
number_to_time_only
(
my_bool
neg
,
ulonglong
nr
,
ulong
sec_part
,
MYSQL_TIME
*
ltime
,
int
*
was_cut
);
ulong
max_hour
,
MYSQL_TIME
*
to
,
int
*
was_cut
);
ulonglong
TIME_to_ulonglong_datetime
(
const
MYSQL_TIME
*
);
ulonglong
TIME_to_ulonglong_date
(
const
MYSQL_TIME
*
);
...
...
This diff is collapsed.
Click to expand it.
libmysqld/libmysql.c
View file @
d2ba9edd
...
...
@@ -3215,7 +3215,8 @@ static void fetch_string_with_conversion(MYSQL_BIND *param, char *value, size_t
{
MYSQL_TIME
*
tm
=
(
MYSQL_TIME
*
)
buffer
;
MYSQL_TIME_STATUS
status
;
str_to_datetime_or_date_or_time
(
value
,
length
,
tm
,
0
,
&
status
);
str_to_datetime_or_date_or_time
(
value
,
length
,
tm
,
0
,
&
status
,
TIME_MAX_HOUR
,
UINT_MAX32
);
err
=
status
.
warnings
;
*
param
->
error
=
MY_TEST
(
err
);
break
;
...
...
This diff is collapsed.
Click to expand it.
mysql-test/main/func_extract.result
0 → 100644
View file @
d2ba9edd
This diff is collapsed.
Click to expand it.
mysql-test/main/func_extract.test
0 → 100644
View file @
d2ba9edd
--
echo
#
--
echo
# MDEV-17385 MICROSECOND() returns confusing results with an out-of-range TIME-alike argument
--
echo
#
CREATE
TABLE
t1
(
v
VARCHAR
(
64
),
ll
BIGINT
,
t
TIME
,
dt
DATETIME
,
d
DATE
);
CREATE
TABLE
t2
AS
SELECT
EXTRACT
(
DAY
FROM
t
),
EXTRACT
(
DAY_HOUR
FROM
t
),
EXTRACT
(
DAY_MINUTE
FROM
t
),
EXTRACT
(
DAY_SECOND
FROM
t
),
EXTRACT
(
DAY_MICROSECOND
FROM
t
),
EXTRACT
(
DAY
FROM
d
),
EXTRACT
(
DAY_HOUR
FROM
d
),
EXTRACT
(
DAY_MINUTE
FROM
d
),
EXTRACT
(
DAY_SECOND
FROM
d
),
EXTRACT
(
DAY_MICROSECOND
FROM
d
),
EXTRACT
(
DAY
FROM
v
),
EXTRACT
(
DAY_HOUR
FROM
v
),
EXTRACT
(
DAY_MINUTE
FROM
v
),
EXTRACT
(
DAY_SECOND
FROM
v
),
EXTRACT
(
DAY_MICROSECOND
FROM
v
),
EXTRACT
(
DAY
FROM
ll
),
EXTRACT
(
DAY_HOUR
FROM
ll
),
EXTRACT
(
DAY_MINUTE
FROM
ll
),
EXTRACT
(
DAY_SECOND
FROM
ll
),
EXTRACT
(
DAY_MICROSECOND
FROM
ll
)
FROM
t1
;
SHOW
CREATE
TABLE
t2
;
DROP
TABLE
t2
;
DROP
TABLE
t1
;
CREATE
TABLE
t1
(
a
VARCHAR
(
64
),
b
DECIMAL
(
32
,
9
));
INSERT
INTO
t1
VALUES
(
'9999-12-31 23:59:59.123456'
,
99991231235959.123456
),
(
'2001-01-01 10:20:30.123456'
,
20010101102030.123456
),
(
'4294967296:59:59.123456'
,
42949672965959.123456
),
(
'4294967295:59:59.123456'
,
42949672955959.123456
),
(
'87649416:59:59.123456'
,
876494165959.123456
),
(
'87649415:59:59.123456'
,
876494155959.123456
),
(
'87649414:59:59.123456'
,
876494145959.123456
),
(
'9999:59:59.123456'
,
99995959.123456
),
(
'9999:01:01.123456'
,
99990101.123456
),
(
'9999:01:01'
,
99990101
),
(
'0.999999'
,
0.999999
),
(
'0.99999'
,
0.99999
),
(
'0.9999'
,
0.9999
),
(
'0.999'
,
0.999
),
(
'0.99'
,
0.99
),
(
'0.9'
,
0.9
),
(
'000000'
,
0
);
--
echo
# Summary:
--
echo
# Check that FUNC(varchar) and FUNC(decimal) give equal results
--
echo
# Expect empty sets
--
disable_warnings
SELECT
a
,
b
,
EXTRACT
(
DAY_HOUR
FROM
a
),
EXTRACT
(
DAY_HOUR
FROM
b
)
FROM
t1
WHERE
NOT
(
EXTRACT
(
DAY_HOUR
FROM
a
)
<=>
EXTRACT
(
DAY_HOUR
FROM
b
));
SELECT
a
,
b
,
EXTRACT
(
DAY
FROM
a
),
EXTRACT
(
DAY
FROM
b
)
FROM
t1
WHERE
NOT
(
EXTRACT
(
DAY
FROM
a
)
<=>
EXTRACT
(
DAY
FROM
b
));
SELECT
a
,
b
,
EXTRACT
(
HOUR
FROM
a
),
EXTRACT
(
HOUR
FROM
b
)
FROM
t1
WHERE
NOT
(
EXTRACT
(
HOUR
FROM
a
)
<=>
EXTRACT
(
HOUR
FROM
b
));
SELECT
a
,
b
,
EXTRACT
(
MINUTE
FROM
a
),
EXTRACT
(
MINUTE
FROM
b
)
FROM
t1
WHERE
NOT
(
EXTRACT
(
MINUTE
FROM
a
)
<=>
EXTRACT
(
MINUTE
FROM
b
));
SELECT
a
,
b
,
EXTRACT
(
SECOND
FROM
a
),
EXTRACT
(
SECOND
FROM
b
)
FROM
t1
WHERE
NOT
(
EXTRACT
(
SECOND
FROM
a
)
<=>
EXTRACT
(
SECOND
FROM
b
));
SELECT
a
,
b
,
EXTRACT
(
MICROSECOND
FROM
a
),
EXTRACT
(
MICROSECOND
FROM
b
)
FROM
t1
WHERE
NOT
(
EXTRACT
(
MICROSECOND
FROM
a
)
<=>
EXTRACT
(
MICROSECOND
FROM
b
));
--
enable_warnings
--
echo
# Detailed results
SELECT
a
,
EXTRACT
(
DAY
FROM
a
)
*
24
+
EXTRACT
(
HOUR
FROM
a
)
AS
dh
,
EXTRACT
(
DAY_HOUR
FROM
a
),
EXTRACT
(
DAY
FROM
a
),
EXTRACT
(
HOUR
FROM
a
),
EXTRACT
(
MINUTE
FROM
a
),
EXTRACT
(
SECOND
FROM
a
),
EXTRACT
(
MICROSECOND
FROM
a
)
FROM
t1
;
SELECT
b
,
EXTRACT
(
DAY
FROM
b
)
*
24
+
EXTRACT
(
HOUR
FROM
b
)
AS
dh
,
EXTRACT
(
DAY_HOUR
FROM
b
),
EXTRACT
(
DAY
FROM
b
),
EXTRACT
(
HOUR
FROM
b
),
EXTRACT
(
MINUTE
FROM
b
),
EXTRACT
(
SECOND
FROM
b
),
EXTRACT
(
MICROSECOND
FROM
b
)
FROM
t1
;
DROP
TABLE
t1
;
--
echo
# Special case: DAY + TIME
CREATE
TABLE
t1
(
a
VARCHAR
(
64
));
INSERT
INTO
t1
VALUES
(
'9999-01-01'
);
SELECT
a
,
EXTRACT
(
DAY_HOUR
FROM
a
),
EXTRACT
(
DAY_MINUTE
FROM
a
),
EXTRACT
(
DAY_SECOND
FROM
a
),
EXTRACT
(
DAY_MICROSECOND
FROM
a
),
EXTRACT
(
DAY
FROM
a
),
EXTRACT
(
HOUR
FROM
a
),
EXTRACT
(
MINUTE
FROM
a
),
EXTRACT
(
SECOND
FROM
a
),
EXTRACT
(
MICROSECOND
FROM
a
)
FROM
t1
;
DROP
TABLE
t1
;
--
echo
# Bad values
CREATE
TABLE
t1
(
a
VARCHAR
(
64
));
INSERT
INTO
t1
VALUES
(
''
);
SELECT
a
,
EXTRACT
(
DAY_HOUR
FROM
a
),
EXTRACT
(
DAY_MINUTE
FROM
a
),
EXTRACT
(
DAY_SECOND
FROM
a
),
EXTRACT
(
DAY_MICROSECOND
FROM
a
),
EXTRACT
(
DAY
FROM
a
),
EXTRACT
(
HOUR
FROM
a
),
EXTRACT
(
MINUTE
FROM
a
),
EXTRACT
(
SECOND
FROM
a
),
EXTRACT
(
MICROSECOND
FROM
a
)
FROM
t1
;
DROP
TABLE
t1
;
--
echo
# Backward compatibility
--
echo
# This still parses as DATETIME
SELECT
EXTRACT
(
YEAR
FROM
'2001/02/03 10:20:30'
);
SELECT
EXTRACT
(
MONTH
FROM
'2001/02/03 10:20:30'
);
SELECT
EXTRACT
(
DAY
FROM
'2001/02/03 10:20:30'
);
SELECT
EXTRACT
(
YEAR
FROM
'01/02/03 10:20:30'
);
SELECT
EXTRACT
(
MONTH
FROM
'01/02/03 10:20:30'
);
SELECT
EXTRACT
(
DAY
FROM
'01/02/03 10:20:30'
);
SELECT
EXTRACT
(
YEAR
FROM
'01:02:03 10:20:30'
);
SELECT
EXTRACT
(
MONTH
FROM
'01:02:03 10:20:30'
);
SELECT
EXTRACT
(
DAY
FROM
'01:02:03 10:20:30'
);
--
echo
# This still parses as DATETIME and returns NULL
SELECT
EXTRACT
(
YEAR
FROM
"2011-02-32 8:46:06.23434"
);
SELECT
EXTRACT
(
MONTH
FROM
"2011-02-32 8:46:06.23434"
);
SELECT
EXTRACT
(
DAY
FROM
"2011-02-32 8:46:06.23434"
);
SELECT
EXTRACT
(
HOUR
FROM
"2011-02-32 8:46:06.23434"
);
--
echo
# This still parses as DATE
SELECT
EXTRACT
(
YEAR
FROM
'2001/02/03'
);
SELECT
EXTRACT
(
MONTH
FROM
'2001/02/03'
);
SELECT
EXTRACT
(
DAY
FROM
'2001/02/03'
);
SELECT
EXTRACT
(
YEAR
FROM
'01/02/03'
);
SELECT
EXTRACT
(
MONTH
FROM
'01/02/03'
);
SELECT
EXTRACT
(
DAY
FROM
'01/02/03'
);
SELECT
EXTRACT
(
YEAR
FROM
'01-02-03'
);
SELECT
EXTRACT
(
MONTH
FROM
'01-02-03'
);
SELECT
EXTRACT
(
DAY
FROM
'01-02-03'
);
SELECT
EXTRACT
(
YEAR
FROM
'1-2-3'
);
SELECT
EXTRACT
(
MONTH
FROM
'1-2-3'
);
SELECT
EXTRACT
(
DAY
FROM
'1-2-3'
);
SELECT
EXTRACT
(
HOUR
FROM
'1-2-3'
);
SELECT
EXTRACT
(
DAY
FROM
'2024-01-03 garbage /////'
);
SELECT
EXTRACT
(
DAY
FROM
'24-01-03 garbage /////'
);
SELECT
EXTRACT
(
DAY
FROM
'01-02-03'
);
SELECT
EXTRACT
(
DAY
FROM
'24:02:03T'
);
SELECT
EXTRACT
(
DAY
FROM
'24-02-03'
);
SELECT
EXTRACT
(
DAY
FROM
'24/02/03'
);
SELECT
EXTRACT
(
DAY
FROM
'11111'
);
SELECT
TIME
(
'2001-01-01T'
),
TIME
(
'2001-01-01T '
);
SELECT
TIME
(
'2001/01/01T'
),
TIME
(
'2001/01/01T '
);
SELECT
TIME
(
'2001:01:01T'
),
TIME
(
'2001:01:01T '
);
SELECT
EXTRACT
(
DAY
FROM
'2001-01-01T'
),
EXTRACT
(
DAY
FROM
'2001-01-01T '
);
SELECT
EXTRACT
(
DAY
FROM
'2001/01/01T'
),
EXTRACT
(
DAY
FROM
'2001/01/01T '
);
SELECT
EXTRACT
(
DAY
FROM
'2001:01:01T'
),
EXTRACT
(
DAY
FROM
'2001:01:01T '
);
SELECT
TIME
(
'2001:01:01T'
),
TIME
(
'2001:01:01T '
);
SELECT
EXTRACT
(
HOUR
FROM
'2001-01-01T'
),
EXTRACT
(
HOUR
FROM
'2001-01-01T '
);
SELECT
EXTRACT
(
HOUR
FROM
'2001/01/01T'
),
EXTRACT
(
HOUR
FROM
'2001/01/01T '
);
SELECT
EXTRACT
(
HOUR
FROM
'2001:01:01T'
),
EXTRACT
(
HOUR
FROM
'2001:01:01T '
);
--
echo
# This still parses as DATE and returns NULL (without trying TIME)
SELECT
EXTRACT
(
DAY
FROM
'100000:02:03T'
);
SELECT
EXTRACT
(
DAY
FROM
'100000/02/03'
);
SELECT
EXTRACT
(
DAY
FROM
'100000-02-03'
);
SELECT
EXTRACT
(
DAY
FROM
'1111'
);
SELECT
EXTRACT
(
DAY
FROM
'111'
);
SELECT
EXTRACT
(
DAY
FROM
'11'
);
SELECT
EXTRACT
(
DAY
FROM
'1'
);
--
echo
# This still parses as TIME
SELECT
EXTRACT
(
HOUR
FROM
'11111'
);
SELECT
EXTRACT
(
HOUR
FROM
'1111'
);
SELECT
EXTRACT
(
HOUR
FROM
'111'
);
SELECT
EXTRACT
(
HOUR
FROM
'11'
);
SELECT
EXTRACT
(
HOUR
FROM
'1'
);
SELECT
TIME
(
'01:02:03:'
);
SELECT
TIME
(
'01:02:03-'
);
SELECT
TIME
(
'01:02:03;'
);
SELECT
TIME
(
'01:02:03/'
);
SELECT
EXTRACT
(
HOUR
FROM
'01:02:03:'
);
SELECT
EXTRACT
(
HOUR
FROM
'01:02:03-'
);
SELECT
EXTRACT
(
HOUR
FROM
'01:02:03;'
);
SELECT
EXTRACT
(
HOUR
FROM
'01:02:03/'
);
--
echo
# Backward compatibility preserved for YEAR and MONTH only
--
echo
# (behavior has changed for DAY, see below)
SELECT
EXTRACT
(
YEAR
FROM
'01:02:03'
);
SELECT
EXTRACT
(
MONTH
FROM
'01:02:03'
);
SELECT
EXTRACT
(
YEAR
FROM
'24:01:03 garbage /////'
);
SELECT
EXTRACT
(
MONTH
FROM
'24:01:03 garbage /////'
);
--
echo
# This still parses as TIME 00:20:01
SELECT
TIME
(
'2001/01/01'
);
SELECT
TIME
(
'2001-01-01'
);
--
echo
# This still parses as TIME and overflows to '838:59:59'
SELECT
TIME
(
'2001:01:01'
);
--
echo
# This used to parse as DATE, now parses as TIME interval
CREATE
TABLE
t1
(
a
VARCHAR
(
64
));
INSERT
INTO
t1
VALUES
(
'2024:01:03 garbage /////'
),
(
'24:01:03 garbage /////'
),
(
'01:01:03 garbage /////'
),
(
'2024:02:03'
),
(
'100000:02:03'
),
(
'24:02:03'
),
(
'01:02:03'
),
(
'01:02:03:'
),
(
'01:02:03-'
),
(
'01:02:03;'
),
(
'01:02:03/'
),
(
'20 10:20:30'
);
SELECT
EXTRACT
(
DAY
FROM
a
),
EXTRACT
(
DAY_SECOND
FROM
a
),
a
FROM
t1
;
DROP
TABLE
t1
;
This diff is collapsed.
Click to expand it.
mysql-test/main/func_time.result
View file @
d2ba9edd
...
...
@@ -367,9 +367,7 @@ extract(DAY_MINUTE FROM "02 10:11:12")
21011
select extract(DAY_SECOND FROM "225 10:11:12");
extract(DAY_SECOND FROM "225 10:11:12")
34225959
Warnings:
Warning 1292 Truncated incorrect time value: '225 10:11:12'
225101112
select extract(HOUR FROM "1999-01-02 10:11:12");
extract(HOUR FROM "1999-01-02 10:11:12")
10
...
...
@@ -1033,9 +1031,7 @@ Note 1105 Cast to unsigned converted negative integer to it's positive complemen
Warning 1292 Truncated incorrect time value: '18446744073709551615:00:00'
SELECT EXTRACT(HOUR FROM '10000:02:03');
EXTRACT(HOUR FROM '10000:02:03')
22
Warnings:
Warning 1292 Truncated incorrect time value: '10000:02:03'
16
CREATE TABLE t1(f1 TIME);
INSERT IGNORE INTO t1 VALUES('916:00:00 a');
Warnings:
...
...
This diff is collapsed.
Click to expand it.
mysql-test/main/str_to_datetime_457.result
View file @
d2ba9edd
...
...
@@ -17,10 +17,7 @@ Warnings:
Warning 1292 Incorrect datetime value: '0'
select extract(hour from '100000:02:03'), extract(hour from '100000:02:03 ');
extract(hour from '100000:02:03') extract(hour from '100000:02:03 ')
NULL NULL
Warnings:
Warning 1292 Incorrect time value: '100000:02:03'
Warning 1292 Incorrect time value: '100000:02:03 '
16 16
#
# backward compatibility craziness
#
...
...
This diff is collapsed.
Click to expand it.
sql-common/my_time.c
View file @
d2ba9edd
This diff is collapsed.
Click to expand it.
sql/item_timefunc.cc
View file @
d2ba9edd
...
...
@@ -2092,16 +2092,18 @@ void Item_extract::print(String *str, enum_query_type query_type)
bool
Item_extract
::
fix_length_and_dec
()
{
maybe_null
=
1
;
// If wrong date
uint32
daylen
=
args
[
0
]
->
cmp_type
()
==
TIME_RESULT
?
2
:
TIME_MAX_INTERVAL_DAY_CHAR_LENGTH
;
switch
(
int_type
)
{
case
INTERVAL_YEAR
:
set_date_length
(
4
);
break
;
// YYYY
case
INTERVAL_YEAR_MONTH
:
set_date_length
(
6
);
break
;
// YYYYMM
case
INTERVAL_QUARTER
:
set_date_length
(
2
);
break
;
// 1..4
case
INTERVAL_MONTH
:
set_date_length
(
2
);
break
;
// MM
case
INTERVAL_WEEK
:
set_date_length
(
2
);
break
;
// 0..52
case
INTERVAL_DAY
:
set_day_length
(
2
);
break
;
// DD
case
INTERVAL_DAY_HOUR
:
set_
time_length
(
4
);
break
;
// DDhh
case
INTERVAL_DAY_MINUTE
:
set_
time_length
(
6
);
break
;
// DDhhmm
case
INTERVAL_DAY_SECOND
:
set_
time_length
(
8
);
break
;
// DDhhmmss
case
INTERVAL_DAY
:
set_day_length
(
daylen
);
break
;
// DD
case
INTERVAL_DAY_HOUR
:
set_
day_length
(
daylen
+
2
);
break
;
// DDhh
case
INTERVAL_DAY_MINUTE
:
set_
day_length
(
daylen
+
4
);
break
;
// DDhhmm
case
INTERVAL_DAY_SECOND
:
set_
day_length
(
daylen
+
6
);
break
;
// DDhhmmss
case
INTERVAL_HOUR
:
set_time_length
(
2
);
break
;
// hh
case
INTERVAL_HOUR_MINUTE
:
set_time_length
(
4
);
break
;
// hhmm
case
INTERVAL_HOUR_SECOND
:
set_time_length
(
6
);
break
;
// hhmmss
...
...
@@ -2109,7 +2111,7 @@ bool Item_extract::fix_length_and_dec()
case
INTERVAL_MINUTE_SECOND
:
set_time_length
(
4
);
break
;
// mmss
case
INTERVAL_SECOND
:
set_time_length
(
2
);
break
;
// ss
case
INTERVAL_MICROSECOND
:
set_time_length
(
6
);
break
;
// ffffff
case
INTERVAL_DAY_MICROSECOND
:
set_time_length
(
14
);
break
;
// DDhhmmssffffff
case
INTERVAL_DAY_MICROSECOND
:
set_time_length
(
daylen
+
12
);
break
;
// DDhhmmssffffff
case
INTERVAL_HOUR_MICROSECOND
:
set_time_length
(
12
);
break
;
// hhmmssffffff
case
INTERVAL_MINUTE_MICROSECOND
:
set_time_length
(
10
);
break
;
// mmssffffff
case
INTERVAL_SECOND_MICROSECOND
:
set_time_length
(
8
);
break
;
// ssffffff
...
...
This diff is collapsed.
Click to expand it.
sql/item_timefunc.h
View file @
d2ba9edd
...
...
@@ -993,12 +993,12 @@ class Item_extract :public Item_int_func,
EXTRACT(DAY FROM '-24:00:00') -> -1
*/
set_handler
(
handler_by_length
(
max_length
=
length
+
1
/*sign*/
,
11
));
m_date_mode
=
date_mode_t
(
0
)
;
m_date_mode
=
TIME_INTERVAL_DAY
;
}
void
set_time_length
(
uint32
length
)
{
set_handler
(
handler_by_length
(
max_length
=
length
+
1
/*sign*/
,
11
));
m_date_mode
=
TIME_
TIME_ONLY
;
m_date_mode
=
TIME_
INTERVAL_hhmmssff
;
}
public:
const
interval_type
int_type
;
// keep it public
...
...
This diff is collapsed.
Click to expand it.
sql/sql_basic_types.h
View file @
d2ba9edd
...
...
@@ -37,11 +37,13 @@ class date_mode_t
FUZZY_DATES is used for the result will only be used for comparison
purposes. Conversion is as relaxed as possible.
*/
FUZZY_DATES
=
1U
,
TIME_ONLY
=
4U
,
NO_ZERO_IN_DATE
=
(
1UL
<<
23
),
// MODE_NO_ZERO_IN_DATE
NO_ZERO_DATE
=
(
1UL
<<
24
),
// MODE_NO_ZERO_DATE
INVALID_DATES
=
(
1UL
<<
25
)
// MODE_INVALID_DATES
FUZZY_DATES
=
1U
,
TIME_ONLY
=
4U
,
INTERVAL_hhmmssff
=
8U
,
INTERVAL_DAY
=
16U
,
NO_ZERO_IN_DATE
=
(
1UL
<<
23
),
// MODE_NO_ZERO_IN_DATE
NO_ZERO_DATE
=
(
1UL
<<
24
),
// MODE_NO_ZERO_DATE
INVALID_DATES
=
(
1UL
<<
25
)
// MODE_INVALID_DATES
};
private:
...
...
@@ -98,6 +100,8 @@ class date_mode_t
const
date_mode_t
TIME_FUZZY_DATES
(
date_mode_t
::
value_t
::
FUZZY_DATES
),
TIME_TIME_ONLY
(
date_mode_t
::
value_t
::
TIME_ONLY
),
TIME_INTERVAL_hhmmssff
(
date_mode_t
::
value_t
::
INTERVAL_hhmmssff
),
TIME_INTERVAL_DAY
(
date_mode_t
::
value_t
::
INTERVAL_DAY
),
TIME_NO_ZERO_IN_DATE
(
date_mode_t
::
value_t
::
NO_ZERO_IN_DATE
),
TIME_NO_ZERO_DATE
(
date_mode_t
::
value_t
::
NO_ZERO_DATE
),
TIME_INVALID_DATES
(
date_mode_t
::
value_t
::
INVALID_DATES
);
...
...
This diff is collapsed.
Click to expand it.
sql/sql_time.cc
View file @
d2ba9edd
...
...
@@ -371,18 +371,14 @@ class TemporalAsciiBuffer: public LEX_CSTRING
};
/* Character set-aware version of
str
_to_datetime_or_date_or_time() */
bool
Temporal
::
str_to_datetime_or_date_or_time
(
MYSQL_TIME_STATUS
*
st
atus
,
/* Character set-aware version of
ascii
_to_datetime_or_date_or_time() */
bool
Temporal
::
str_to_datetime_or_date_or_time
(
MYSQL_TIME_STATUS
*
st
,
const
char
*
str
,
size_t
length
,
CHARSET_INFO
*
cs
,
date_mode_t
fuzzydate
)
{
TemporalAsciiBuffer
tmp
(
str
,
length
,
cs
);
bool
rc
=
::
str_to_datetime_or_date_or_time
(
tmp
.
str
,
tmp
.
length
,
this
,
ulonglong
(
fuzzydate
&
TIME_MODE_FOR_XXX_TO_DATE
),
status
);
DBUG_ASSERT
(
status
->
warnings
||
!
rc
);
return
rc
;
return
ascii_to_datetime_or_date_or_time
(
st
,
tmp
.
str
,
tmp
.
length
,
fuzzydate
);
}
...
...
@@ -393,11 +389,17 @@ bool Temporal::str_to_datetime_or_date(MYSQL_TIME_STATUS *status,
date_mode_t
flags
)
{
TemporalAsciiBuffer
tmp
(
str
,
length
,
cs
);
bool
rc
=
::
str_to_datetime_or_date
(
tmp
.
str
,
tmp
.
length
,
this
,
ulonglong
(
flags
&
TIME_MODE_FOR_XXX_TO_DATE
),
status
);
DBUG_ASSERT
(
status
->
warnings
||
!
rc
);
return
rc
;
return
ascii_to_datetime_or_date
(
status
,
tmp
.
str
,
tmp
.
length
,
flags
);
}
/* Character set-aware version of ascii_to_temporal() */
bool
Temporal
::
str_to_temporal
(
MYSQL_TIME_STATUS
*
status
,
const
char
*
str
,
size_t
length
,
CHARSET_INFO
*
cs
,
date_mode_t
flags
)
{
TemporalAsciiBuffer
tmp
(
str
,
length
,
cs
);
return
ascii_to_temporal
(
status
,
tmp
.
str
,
tmp
.
length
,
flags
);
}
...
...
This diff is collapsed.
Click to expand it.
sql/sql_type.cc
View file @
d2ba9edd
...
...
@@ -181,9 +181,7 @@ void Temporal::make_from_str(THD *thd, Warn *warn,
push_warning
(
thd
,
Sql_condition
::
WARN_LEVEL_NOTE
,
ER_YES
,
ErrConvString
(
str
,
length
,
cs
).
ptr
()););
if
(
fuzzydate
&
TIME_TIME_ONLY
?
str_to_datetime_or_date_or_time
(
warn
,
str
,
length
,
cs
,
fuzzydate
)
:
str_to_datetime_or_date
(
warn
,
str
,
length
,
cs
,
fuzzydate
))
if
(
str_to_temporal
(
warn
,
str
,
length
,
cs
,
fuzzydate
))
make_fuzzy_date
(
&
warn
->
warnings
,
fuzzydate
);
if
(
warn
->
warnings
)
warn
->
set_str
(
str
,
length
,
&
my_charset_bin
);
...
...
@@ -232,8 +230,11 @@ void Sec6::make_truncated_warning(THD *thd, const char *type_str) const
bool
Sec6
::
convert_to_mysql_time
(
THD
*
thd
,
int
*
warn
,
MYSQL_TIME
*
ltime
,
date_mode_t
fuzzydate
)
const
{
bool
is_time
=
bool
(
fuzzydate
&
TIME_TIME_ONLY
);
bool
rc
=
is_time
?
to_time
(
ltime
,
warn
)
:
to_datetime
(
ltime
,
fuzzydate
,
warn
);
bool
rc
=
fuzzydate
&
(
TIME_INTERVAL_hhmmssff
|
TIME_INTERVAL_DAY
)
?
to_datetime_or_to_interval_hhmmssff
(
ltime
,
warn
)
:
fuzzydate
&
TIME_TIME_ONLY
?
to_datetime_or_time
(
ltime
,
warn
,
fuzzydate
)
:
to_datetime_or_date
(
ltime
,
warn
,
fuzzydate
);
DBUG_ASSERT
(
*
warn
||
!
rc
);
if
(
truncated
())
*
warn
|=
MYSQL_TIME_WARN_TRUNCATED
;
...
...
This diff is collapsed.
Click to expand it.
sql/sql_type.h
View file @
d2ba9edd
...
...
@@ -264,21 +264,59 @@ class Sec6
MYSQL_TIME
*
ltime
,
date_mode_t
fuzzydate
)
const
;
// Convert a number in format hhhmmss.ff to TIME'hhh:mm:ss.ff'
bool
to_time
(
MYSQL_TIME
*
to
,
int
*
warn
)
const
protected:
bool
to_interval_hhmmssff_only
(
MYSQL_TIME
*
to
,
int
*
warn
)
const
{
return
number_to_time_only
(
m_neg
,
m_sec
,
m_usec
,
TIME_MAX_INTERVAL_HOUR
,
to
,
warn
);
}
bool
to_datetime_or_to_interval_hhmmssff
(
MYSQL_TIME
*
to
,
int
*
warn
)
const
{
bool
rc
=
(
m_sec
>
9999999
&&
m_sec
<=
99991231235959ULL
&&
!
neg
())
?
number_to_datetime_or_date
(
m_sec
,
m_usec
,
to
,
C_TIME_INVALID_DATES
,
warn
)
<
0
:
number_to_time_only
(
m_neg
,
m_sec
,
m_usec
,
to
,
warn
);
/*
Convert a number to a time interval.
The following formats are understood:
- 0 <= x <= 999999995959 - parse as hhhhmmss
- 999999995959 < x <= 99991231235959 - parse as YYYYMMDDhhmmss
(YYMMDDhhmmss) (YYYYMMDDhhmmss)
Note, these formats are NOT understood:
- YYMMDD - overlaps with INTERVAL range
- YYYYMMDD - overlaps with INTERVAL range
- YYMMDDhhmmss - overlaps with INTERVAL range, partially
(see TIME_MAX_INTERVAL_HOUR)
If we ever need wider intervals, this code switching between
full datetime and interval-only should be rewised.
*/
DBUG_ASSERT
(
TIME_MAX_INTERVAL_HOUR
<=
999999995959
);
/* (YYMMDDhhmmss) */
if
(
m_sec
>
999999995959ULL
&&
m_sec
<=
99991231235959ULL
&&
m_neg
==
0
)
return
to_datetime_or_date
(
to
,
warn
,
TIME_INVALID_DATES
);
if
(
m_sec
/
10000
>
TIME_MAX_INTERVAL_HOUR
)
{
*
warn
=
MYSQL_TIME_WARN_OUT_OF_RANGE
;
return
true
;
}
return
to_interval_hhmmssff_only
(
to
,
warn
);
}
public:
// [-][DD]hhhmmss.ff, YYMMDDhhmmss.ff, YYYYMMDDhhmmss.ff
bool
to_datetime_or_time
(
MYSQL_TIME
*
to
,
int
*
warn
,
date_mode_t
mode
)
const
{
bool
rc
=
m_sec
>
9999999
&&
m_sec
<=
99991231235959ULL
&&
!
m_neg
?
::
number_to_datetime_or_date
(
m_sec
,
m_usec
,
to
,
ulonglong
(
mode
&
TIME_MODE_FOR_XXX_TO_DATE
),
warn
)
<
0
:
::
number_to_time_only
(
m_neg
,
m_sec
,
m_usec
,
TIME_MAX_HOUR
,
to
,
warn
);
DBUG_ASSERT
(
*
warn
||
!
rc
);
return
rc
;
}
/*
Convert a number in format
YY
YYMMDDhhmmss.ff to
Convert a number in format
s YYYYMMDDhhmmss.ff or
YYMMDDhhmmss.ff to
TIMESTAMP'YYYY-MM-DD hh:mm:ss.ff'
*/
bool
to_datetime
(
MYSQL_TIME
*
to
,
date_mode_t
flags
,
int
*
warn
)
const
bool
to_datetime
_or_date
(
MYSQL_TIME
*
to
,
int
*
warn
,
date_mode_t
flags
)
const
{
if
(
m_neg
)
{
...
...
@@ -458,6 +496,8 @@ class Temporal: protected MYSQL_TIME
timestamp_type
tstype
,
const
char
*
name
)
{
const
char
*
typestr
=
tstype
>=
0
?
type_name_by_timestamp_type
(
tstype
)
:
mode
&
(
TIME_INTERVAL_hhmmssff
|
TIME_INTERVAL_DAY
)
?
"interval"
:
mode
&
TIME_TIME_ONLY
?
"time"
:
"datetime"
;
Temporal
::
push_conversion_warnings
(
thd
,
totally_useless_value
,
warnings
,
typestr
,
name
,
ptr
());
...
...
@@ -579,6 +619,60 @@ class Temporal: protected MYSQL_TIME
if
(
warn
->
warnings
)
warn
->
set_decimal
(
nr
);
}
bool
ascii_to_temporal
(
MYSQL_TIME_STATUS
*
st
,
const
char
*
str
,
size_t
length
,
date_mode_t
mode
)
{
if
(
mode
&
(
TIME_INTERVAL_hhmmssff
|
TIME_INTERVAL_DAY
))
return
ascii_to_datetime_or_date_or_interval_DDhhmmssff
(
st
,
str
,
length
,
mode
);
if
(
mode
&
TIME_TIME_ONLY
)
return
ascii_to_datetime_or_date_or_time
(
st
,
str
,
length
,
mode
);
return
ascii_to_datetime_or_date
(
st
,
str
,
length
,
mode
);
}
bool
ascii_to_datetime_or_date_or_interval_DDhhmmssff
(
MYSQL_TIME_STATUS
*
st
,
const
char
*
str
,
size_t
length
,
date_mode_t
mode
)
{
longlong
cflags
=
ulonglong
(
mode
&
TIME_MODE_FOR_XXX_TO_DATE
);
bool
rc
=
mode
&
TIME_INTERVAL_DAY
?
::
str_to_datetime_or_date_or_interval_day
(
str
,
length
,
this
,
cflags
,
st
,
TIME_MAX_INTERVAL_HOUR
,
TIME_MAX_INTERVAL_HOUR
)
:
::
str_to_datetime_or_date_or_interval_hhmmssff
(
str
,
length
,
this
,
cflags
,
st
,
TIME_MAX_INTERVAL_HOUR
,
TIME_MAX_INTERVAL_HOUR
);
DBUG_ASSERT
(
!
rc
||
st
->
warnings
);
return
rc
;
}
bool
ascii_to_datetime_or_date_or_time
(
MYSQL_TIME_STATUS
*
status
,
const
char
*
str
,
size_t
length
,
date_mode_t
fuzzydate
)
{
ulonglong
cflags
=
ulonglong
(
fuzzydate
&
TIME_MODE_FOR_XXX_TO_DATE
);
bool
rc
=
::
str_to_datetime_or_date_or_time
(
str
,
length
,
this
,
cflags
,
status
,
TIME_MAX_HOUR
,
UINT_MAX32
);
DBUG_ASSERT
(
!
rc
||
status
->
warnings
);
return
rc
;
}
bool
ascii_to_datetime_or_date
(
MYSQL_TIME_STATUS
*
status
,
const
char
*
str
,
size_t
length
,
date_mode_t
fuzzydate
)
{
DBUG_ASSERT
(
bool
(
fuzzydate
&
TIME_TIME_ONLY
)
==
false
);
bool
rc
=
::
str_to_datetime_or_date
(
str
,
length
,
this
,
ulonglong
(
fuzzydate
&
TIME_MODE_FOR_XXX_TO_DATE
),
status
);
DBUG_ASSERT
(
!
rc
||
status
->
warnings
);
return
rc
;
}
// Character set aware versions for string conversion routines
bool
str_to_temporal
(
MYSQL_TIME_STATUS
*
st
,
const
char
*
str
,
size_t
length
,
CHARSET_INFO
*
cs
,
date_mode_t
fuzzydate
);
bool
str_to_datetime_or_date_or_time
(
MYSQL_TIME_STATUS
*
st
,
const
char
*
str
,
size_t
length
,
CHARSET_INFO
*
cs
,
date_mode_t
fuzzydate
);
...
...
@@ -858,7 +952,7 @@ class Interval_DDhhmmssff: public Temporal
*/
static
uint
max_useful_hour
()
{
return
87649415
;
return
TIME_MAX_INTERVAL_HOUR
;
}
public:
Interval_DDhhmmssff
(
THD
*
thd
,
Status
*
st
,
bool
push_warnings
,
...
...
@@ -1120,7 +1214,7 @@ class Time: public Temporal
}
Time
(
THD
*
thd
,
int
*
warn
,
const
Sec6
&
nr
,
const
Options
opt
)
{
if
(
nr
.
to_
time
(
this
,
warn
))
if
(
nr
.
to_
datetime_or_time
(
this
,
warn
,
TIME_INVALID_DATES
))
time_type
=
MYSQL_TIMESTAMP_NONE
;
xxx_to_time_result_to_valid_value
(
thd
,
warn
,
opt
);
}
...
...
@@ -1305,7 +1399,7 @@ class Temporal_with_date: public Temporal
Temporal_with_date
(
int
*
warn
,
const
Sec6
&
nr
,
date_mode_t
flags
)
{
DBUG_ASSERT
(
bool
(
flags
&
TIME_TIME_ONLY
)
==
false
);
if
(
nr
.
to_datetime
(
this
,
flags
,
warn
))
if
(
nr
.
to_datetime
_or_date
(
this
,
warn
,
flags
))
time_type
=
MYSQL_TIMESTAMP_NONE
;
}
Temporal_with_date
(
MYSQL_TIME_STATUS
*
status
,
...
...
This diff is collapsed.
Click to expand it.
Write
Preview
Markdown
is supported
0%
Try again
or
attach a new file
Attach a file
Cancel
You are about to add
0
people
to the discussion. Proceed with caution.
Finish editing this message first!
Cancel
Please
register
or
sign in
to comment