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
b6156392
Commit
b6156392
authored
Oct 20, 2003
by
unknown
Browse files
Options
Browse Files
Download
Email Patches
Plain Diff
Scrum task 835 - text-to-datetime conversion function
parent
99450993
Changes
21
Show whitespace changes
Inline
Side-by-side
Showing
21 changed files
with
1650 additions
and
495 deletions
+1650
-495
mysql-test/r/date_formats.result
mysql-test/r/date_formats.result
+157
-0
mysql-test/t/date_formats-master.opt
mysql-test/t/date_formats-master.opt
+1
-0
mysql-test/t/date_formats.test
mysql-test/t/date_formats.test
+82
-0
sql/field.cc
sql/field.cc
+44
-29
sql/item.cc
sql/item.cc
+17
-17
sql/item.h
sql/item.h
+9
-1
sql/item_create.cc
sql/item_create.cc
+5
-0
sql/item_create.h
sql/item_create.h
+1
-0
sql/item_timefunc.cc
sql/item_timefunc.cc
+752
-371
sql/item_timefunc.h
sql/item_timefunc.h
+43
-0
sql/lex.h
sql/lex.h
+2
-0
sql/mysql_priv.h
sql/mysql_priv.h
+22
-5
sql/mysqld.cc
sql/mysqld.cc
+67
-1
sql/protocol.cc
sql/protocol.cc
+19
-26
sql/set_var.cc
sql/set_var.cc
+72
-0
sql/set_var.h
sql/set_var.h
+50
-0
sql/sql_class.cc
sql/sql_class.cc
+3
-0
sql/sql_class.h
sql/sql_class.h
+1
-0
sql/sql_yacc.yy
sql/sql_yacc.yy
+11
-0
sql/structs.h
sql/structs.h
+7
-2
sql/time.cc
sql/time.cc
+285
-43
No files found.
mysql-test/r/date_formats.result
0 → 100644
View file @
b6156392
SHOW GLOBAL VARIABLES LIKE "%_format%";
Variable_name Value
date_format %d.%m.%Y
datetime_format %Y/%d/%m-%H:%i:%s
default_week_format 0
time_format %H.%i.%s
SHOW SESSION VARIABLES LIKE "%_format%";
Variable_name Value
date_format %d.%m.%Y
datetime_format %Y/%d/%m-%H:%i:%s
default_week_format 0
time_format %H.%i.%s
SET date_format="%d.%m.%Y";
select CAST("01.01.2001" as DATE) as a;
a
01.01.2001
SET datetime_format="%d.%m.%Y %H.%i.%s";
select CAST("01.01.2001 05.12.06" as DATETIME) as a;
a
01.01.2001 05.12.06
SET time_format="%H.%i.%s";
select CAST("05.12.06" as TIME) as a;
a
05.12.06
SET datetime_format="%d.%m.%Y %h:%i:%s %p";
select CAST("01.01.2001 05:12:06AM" as DATETIME) as a;
a
01.01.2001 05:12:06 AM
select CAST("01.01.2001 05:12:06 PM" as DATETIME) as a;
a
01.01.2001 05:12:06 PM
SET time_format="%h:%i:%s %p";
select CAST("05:12:06 AM" as TIME) as a;
a
05:12:06 AM
select CAST("05:12:06.1234PM" as TIME) as a;
a
05:12:06.001234 PM
SET time_format="%h.%i.%s %p";
SET date_format='%d.%m.%y';
SET datetime_format="%d.%m.%y %h.%i.%s %p";
select CAST("12-12-06" as DATE) as a;
a
12.12.06
select adddate("01.01.97 11.59.59.000001 PM", 10);
adddate("01.01.97 11.59.59.000001 PM", 10)
11.01.97 11.59.59.000001 PM
select datediff("31.12.97 11.59:59.000001 PM","01.01.98");
datediff("31.12.97 11.59:59.000001 PM","01.01.98")
-1
select weekofyear("31.11.97 11:59:59.000001 PM");
weekofyear("31.11.97 11:59:59.000001 PM")
49
select makedate(1997,1);
makedate(1997,1)
01.01.97
select addtime("31.12.97 11.59.59.999999 PM", "1 1.1.1.000002");
addtime("31.12.97 11.59.59.999999 PM", "1 1.1.1.000002")
02.01.98 01.01.01.000001 AM
select maketime(23,11,12);
maketime(23,11,12)
11.11.12 PM
select timediff("01.01.97 11:59:59.000001 PM","31.12.95 11:59:59.000002 PM");
timediff("01.01.97 11:59:59.000001 PM","31.12.95 11:59:59.000002 PM")
8795.59.59.999999 PM
SET time_format="%H%i%s";
SET time_format="%h%i%s";
ERROR HY000: Unknown error
SET date_format='%d.%m.%d';
ERROR HY000: Unknown error
SET datetime_format="%d.%m.%y %h.%i.%s";
ERROR HY000: Unknown error
SET GLOBAL date_format=default;
SHOW GLOBAL VARIABLES LIKE "date_format%";
Variable_name Value
date_format %d.%m.%Y
SET GLOBAL time_format=default;
SHOW GLOBAL VARIABLES LIKE "time_format%";
Variable_name Value
time_format %H.%i.%s
SET GLOBAL datetime_format=default;
SHOW GLOBAL VARIABLES LIKE "datetime_format%";
Variable_name Value
datetime_format %Y/%d/%m-%H:%i:%s
SET date_format=default;
SHOW SESSION VARIABLES LIKE "date_format%";
Variable_name Value
date_format %d.%m.%Y
SET time_format=default;
SHOW SESSION VARIABLES LIKE "time_format%";
Variable_name Value
time_format %H.%i.%s
SET datetime_format=default;
SHOW SESSION VARIABLES LIKE "datetime_format%";
Variable_name Value
datetime_format %Y/%d/%m-%H:%i:%s
SET time_format='%i:%s:%H';
select cast(str_to_date("15-01-2001 12:59:59", "%d-%m-%Y %H:%i:%S") as TIME);
cast(str_to_date("15-01-2001 12:59:59", "%d-%m-%Y %H:%i:%S") as TIME)
59:59:12
SET GLOBAL date_format='%Y-%m-%d';
SET GLOBAL time_format='%H:%i:%s';
SET GLOBAL datetime_format='%Y-%m-%d %H:%i:%s';
SET date_format='%Y-%m-%d';
SET time_format='%H:%i:%s';
SET datetime_format='%Y-%m-%d %H:%i:%s';
select str_to_date("15-01-2001 12:59:59", "%d-%m-%Y %H:%i:%S");
str_to_date("15-01-2001 12:59:59", "%d-%m-%Y %H:%i:%S")
2001-01-15 12:59:59
select str_to_date("15 September 2001", "%d %M %Y");
str_to_date("15 September 2001", "%d %M %Y")
2001-09-15 00:00:00
select str_to_date("15 Septembeb 2001", "%d %M %Y");
str_to_date("15 Septembeb 2001", "%d %M %Y")
NULL
select str_to_date("15 MAY 2001", "%d %b %Y");
str_to_date("15 MAY 2001", "%d %b %Y")
2001-05-15 00:00:00
select str_to_date("Sunday 15 MAY 2001", "%W %d %b %Y");
str_to_date("Sunday 15 MAY 2001", "%W %d %b %Y")
2001-05-15 00:00:00
select str_to_date("Sundai 15 MAY 2001", "%W %d %b %Y");
str_to_date("Sundai 15 MAY 2001", "%W %d %b %Y")
NULL
select str_to_date("Sundai 15 MA", "%W %d %b %Y");
str_to_date("Sundai 15 MA", "%W %d %b %Y")
NULL
select str_to_date("Tuesday 52 2001", "%W %V %X");
str_to_date("Tuesday 52 2001", "%W %V %X")
NULL
select str_to_date("Sunday 01 2001", "%W %V %X");
str_to_date("Sunday 01 2001", "%W %V %X")
NULL
select str_to_date("Tuesday 00 2002", "%W %U %Y");
str_to_date("Tuesday 00 2002", "%W %U %Y")
2002-01-01 00:00:00
select str_to_date("Thursday 53 1998", "%W %u %Y");
str_to_date("Thursday 53 1998", "%W %u %Y")
1998-12-31 00:00:00
select str_to_date("15-01-2001", "%d-%m-%Y %H:%i:%S");
str_to_date("15-01-2001", "%d-%m-%Y %H:%i:%S")
2001-01-15 00:00:00
select str_to_date("15-01-20", "%d-%m-%Y");
str_to_date("15-01-20", "%d-%m-%Y")
NULL
select str_to_date("15-2001-1", "%d-%Y-%c");
str_to_date("15-2001-1", "%d-%Y-%c")
2001-01-15 00:00:00
select get_format(DATE, 'USA') as a;
a
%m.%d.%Y
select get_format(TIME, 'internal') as a;
a
%H%i%s
select get_format(DATETIME, 'eur') as a;
a
%Y-%m-%d-%H.%i.%s
mysql-test/t/date_formats-master.opt
0 → 100644
View file @
b6156392
--date_format=%d.%m.%Y --time_format=%H.%i.%s --datetime_format=%Y/%d/%m-%H:%i:%s
mysql-test/t/date_formats.test
0 → 100644
View file @
b6156392
SHOW
GLOBAL
VARIABLES
LIKE
"%_format%"
;
SHOW
SESSION
VARIABLES
LIKE
"%_format%"
;
SET
date_format
=
"%d.%m.%Y"
;
select
CAST
(
"01.01.2001"
as
DATE
)
as
a
;
SET
datetime_format
=
"%d.%m.%Y %H.%i.%s"
;
select
CAST
(
"01.01.2001 05.12.06"
as
DATETIME
)
as
a
;
SET
time_format
=
"%H.%i.%s"
;
select
CAST
(
"05.12.06"
as
TIME
)
as
a
;
SET
datetime_format
=
"%d.%m.%Y %h:%i:%s %p"
;
select
CAST
(
"01.01.2001 05:12:06AM"
as
DATETIME
)
as
a
;
select
CAST
(
"01.01.2001 05:12:06 PM"
as
DATETIME
)
as
a
;
SET
time_format
=
"%h:%i:%s %p"
;
select
CAST
(
"05:12:06 AM"
as
TIME
)
as
a
;
select
CAST
(
"05:12:06.1234PM"
as
TIME
)
as
a
;
SET
time_format
=
"%h.%i.%s %p"
;
SET
date_format
=
'%d.%m.%y'
;
SET
datetime_format
=
"%d.%m.%y %h.%i.%s %p"
;
select
CAST
(
"12-12-06"
as
DATE
)
as
a
;
select
adddate
(
"01.01.97 11.59.59.000001 PM"
,
10
);
select
datediff
(
"31.12.97 11.59:59.000001 PM"
,
"01.01.98"
);
select
weekofyear
(
"31.11.97 11:59:59.000001 PM"
);
select
makedate
(
1997
,
1
);
select
addtime
(
"31.12.97 11.59.59.999999 PM"
,
"1 1.1.1.000002"
);
select
maketime
(
23
,
11
,
12
);
select
timediff
(
"01.01.97 11:59:59.000001 PM"
,
"31.12.95 11:59:59.000002 PM"
);
SET
time_format
=
"%H%i%s"
;
--
error
1105
SET
time_format
=
"%h%i%s"
;
--
error
1105
SET
date_format
=
'%d.%m.%d'
;
--
error
1105
SET
datetime_format
=
"%d.%m.%y %h.%i.%s"
;
SET
GLOBAL
date_format
=
default
;
SHOW
GLOBAL
VARIABLES
LIKE
"date_format%"
;
SET
GLOBAL
time_format
=
default
;
SHOW
GLOBAL
VARIABLES
LIKE
"time_format%"
;
SET
GLOBAL
datetime_format
=
default
;
SHOW
GLOBAL
VARIABLES
LIKE
"datetime_format%"
;
SET
date_format
=
default
;
SHOW
SESSION
VARIABLES
LIKE
"date_format%"
;
SET
time_format
=
default
;
SHOW
SESSION
VARIABLES
LIKE
"time_format%"
;
SET
datetime_format
=
default
;
SHOW
SESSION
VARIABLES
LIKE
"datetime_format%"
;
SET
time_format
=
'%i:%s:%H'
;
select
cast
(
str_to_date
(
"15-01-2001 12:59:59"
,
"%d-%m-%Y %H:%i:%S"
)
as
TIME
);
SET
GLOBAL
date_format
=
'%Y-%m-%d'
;
SET
GLOBAL
time_format
=
'%H:%i:%s'
;
SET
GLOBAL
datetime_format
=
'%Y-%m-%d %H:%i:%s'
;
SET
date_format
=
'%Y-%m-%d'
;
SET
time_format
=
'%H:%i:%s'
;
SET
datetime_format
=
'%Y-%m-%d %H:%i:%s'
;
select
str_to_date
(
"15-01-2001 12:59:59"
,
"%d-%m-%Y %H:%i:%S"
);
select
str_to_date
(
"15 September 2001"
,
"%d %M %Y"
);
select
str_to_date
(
"15 Septembeb 2001"
,
"%d %M %Y"
);
select
str_to_date
(
"15 MAY 2001"
,
"%d %b %Y"
);
select
str_to_date
(
"Sunday 15 MAY 2001"
,
"%W %d %b %Y"
);
select
str_to_date
(
"Sundai 15 MAY 2001"
,
"%W %d %b %Y"
);
select
str_to_date
(
"Sundai 15 MA"
,
"%W %d %b %Y"
);
select
str_to_date
(
"Tuesday 52 2001"
,
"%W %V %X"
);
select
str_to_date
(
"Sunday 01 2001"
,
"%W %V %X"
);
select
str_to_date
(
"Tuesday 00 2002"
,
"%W %U %Y"
);
select
str_to_date
(
"Thursday 53 1998"
,
"%W %u %Y"
);
select
str_to_date
(
"15-01-2001"
,
"%d-%m-%Y %H:%i:%S"
);
select
str_to_date
(
"15-01-20"
,
"%d-%m-%Y"
);
select
str_to_date
(
"15-2001-1"
,
"%d-%Y-%c"
);
select
get_format
(
DATE
,
'USA'
)
as
a
;
select
get_format
(
TIME
,
'internal'
)
as
a
;
select
get_format
(
DATETIME
,
'eur'
)
as
a
;
sql/field.cc
View file @
b6156392
...
...
@@ -279,7 +279,8 @@ bool Field::get_date(TIME *ltime,bool fuzzydate)
char
buff
[
40
];
String
tmp
(
buff
,
sizeof
(
buff
),
&
my_charset_bin
),
tmp2
,
*
res
;
if
(
!
(
res
=
val_str
(
&
tmp
,
&
tmp2
))
||
str_to_TIME
(
res
->
ptr
(),
res
->
length
(),
ltime
,
fuzzydate
)
==
TIMESTAMP_NONE
)
str_to_TIME
(
res
->
ptr
(),
res
->
length
(),
ltime
,
fuzzydate
,
current_thd
)
<=
WRONG_TIMESTAMP_FULL
)
return
1
;
return
0
;
}
...
...
@@ -289,7 +290,7 @@ bool Field::get_time(TIME *ltime)
char
buff
[
40
];
String
tmp
(
buff
,
sizeof
(
buff
),
&
my_charset_bin
),
tmp2
,
*
res
;
if
(
!
(
res
=
val_str
(
&
tmp
,
&
tmp2
))
||
str_to_time
(
res
->
ptr
(),
res
->
length
(),
ltime
))
str_to_time
(
res
->
ptr
(),
res
->
length
(),
ltime
,
current_thd
))
return
1
;
return
0
;
}
...
...
@@ -299,28 +300,29 @@ bool Field::get_time(TIME *ltime)
void
Field
::
store_time
(
TIME
*
ltime
,
timestamp_type
type
)
{
char
buff
[
25
];
String
tmp
((
char
*
)
buff
,
sizeof
(
buff
),
&
my_charset_bin
);
DATETIME_FORMAT
*
tmp_format
=
0
;
bool
is_time_only
=
0
;
switch
(
type
)
{
case
TIMESTAMP_NONE
:
case
WRONG_TIMESTAMP_FULL
:
store
(
""
,
0
,
&
my_charset_bin
);
// Probably an error
break
;
return
;
case
TIMESTAMP_DATE
:
sprintf
(
buff
,
"%04d-%02d-%02d"
,
ltime
->
year
,
ltime
->
month
,
ltime
->
day
);
store
(
buff
,
10
,
&
my_charset_bin
);
tmp_format
=
&
t_datetime_frm
(
current_thd
,
DATE_FORMAT_TYPE
).
datetime_format
;
break
;
case
TIMESTAMP_FULL
:
sprintf
(
buff
,
"%04d-%02d-%02d %02d:%02d:%02d"
,
ltime
->
year
,
ltime
->
month
,
ltime
->
day
,
ltime
->
hour
,
ltime
->
minute
,
ltime
->
second
);
store
(
buff
,
19
,
&
my_charset_bin
);
tmp_format
=&
t_datetime_frm
(
current_thd
,
DATETIME_FORMAT_TYPE
).
datetime_format
;
break
;
case
TIMESTAMP_TIME
:
{
ulong
length
=
my_sprintf
(
buff
,
(
buff
,
"%02d:%02d:%02d"
,
ltime
->
hour
,
ltime
->
minute
,
ltime
->
second
));
store
(
buff
,(
uint
)
length
,
&
my_charset_bin
);
tmp_format
=
&
t_datetime_frm
(
current_thd
,
TIME_FORMAT_TYPE
).
datetime_format
;
is_time_only
=
1
;
break
;
}
}
make_datetime
(
&
tmp
,
ltime
,
is_time_only
,
0
,
tmp_format
->
format
,
tmp_format
->
format_length
,
1
);
store
(
tmp
.
ptr
(),
tmp
.
length
(),
&
my_charset_bin
);
}
...
...
@@ -2684,7 +2686,7 @@ Field_timestamp::Field_timestamp(char *ptr_arg, uint32 len_arg,
int
Field_timestamp
::
store
(
const
char
*
from
,
uint
len
,
CHARSET_INFO
*
cs
)
{
long
tmp
=
(
long
)
str_to_timestamp
(
from
,
len
);
long
tmp
=
(
long
)
str_to_timestamp
(
from
,
len
,
current_thd
);
#ifdef WORDS_BIGENDIAN
if
(
table
->
db_low_byte_first
)
{
...
...
@@ -3018,7 +3020,7 @@ int Field_time::store(const char *from,uint len,CHARSET_INFO *cs)
TIME
ltime
;
long
tmp
;
int
error
=
0
;
if
(
str_to_time
(
from
,
len
,
&
ltime
))
if
(
str_to_time
(
from
,
len
,
&
ltime
,
current_thd
))
{
tmp
=
0L
;
error
=
1
;
...
...
@@ -3127,19 +3129,25 @@ longlong Field_time::val_int(void)
String
*
Field_time
::
val_str
(
String
*
val_buffer
,
String
*
val_ptr
__attribute__
((
unused
)))
{
TIME
ltime
;
val_buffer
->
alloc
(
16
);
long
tmp
=
(
long
)
sint3korr
(
ptr
);
const
char
*
sign
=
""
;
ltime
.
neg
=
0
;
if
(
tmp
<
0
)
{
tmp
=
-
tmp
;
sign
=
"-"
;
}
long
length
=
my_sprintf
((
char
*
)
val_buffer
->
ptr
(),
((
char
*
)
val_buffer
->
ptr
(),
"%s%02d:%02d:%02d"
,
sign
,(
int
)
(
tmp
/
10000
),
(
int
)
(
tmp
/
100
%
100
),
(
int
)
(
tmp
%
100
)));
val_buffer
->
length
(
length
);
ltime
.
neg
=
1
;
}
DATETIME_FORMAT
*
tmp_format
=
(
&
t_datetime_frm
(
current_thd
,
TIME_FORMAT_TYPE
).
datetime_format
);
ltime
.
day
=
(
uint
)
0
;
ltime
.
hour
=
(
uint
)
(
tmp
/
10000
);
ltime
.
minute
=
(
uint
)
(
tmp
/
100
%
100
);
ltime
.
second
=
(
uint
)
(
tmp
%
100
);
make_datetime
(
val_buffer
,
&
ltime
,
0
,
0
,
tmp_format
->
format
,
tmp_format
->
format_length
,
1
);
return
val_buffer
;
}
...
...
@@ -3305,7 +3313,7 @@ int Field_date::store(const char *from, uint len,CHARSET_INFO *cs)
TIME
l_time
;
uint32
tmp
;
int
error
=
0
;
if
(
str_to_TIME
(
from
,
len
,
&
l_time
,
1
)
==
TIMESTAMP_NONE
)
if
(
str_to_TIME
(
from
,
len
,
&
l_time
,
1
,
current_thd
)
<=
WRONG_TIMESTAMP_FULL
)
{
tmp
=
0
;
error
=
1
;
...
...
@@ -3415,6 +3423,7 @@ longlong Field_date::val_int(void)
String
*
Field_date
::
val_str
(
String
*
val_buffer
,
String
*
val_ptr
__attribute__
((
unused
)))
{
TIME
ltime
;
val_buffer
->
alloc
(
field_length
);
val_buffer
->
length
(
field_length
);
int32
tmp
;
...
...
@@ -3424,9 +3433,15 @@ String *Field_date::val_str(String *val_buffer,
else
#endif
longget
(
tmp
,
ptr
);
sprintf
((
char
*
)
val_buffer
->
ptr
(),
"%04d-%02d-%02d"
,
(
int
)
((
uint32
)
tmp
/
10000L
%
10000
),
(
int
)
((
uint32
)
tmp
/
100
%
100
),
(
int
)
((
uint32
)
tmp
%
100
));
DATETIME_FORMAT
*
tmp_format
=
(
&
t_datetime_frm
(
current_thd
,
DATE_FORMAT_TYPE
).
datetime_format
);
ltime
.
neg
=
0
;
ltime
.
year
=
(
int
)
((
uint32
)
tmp
/
10000L
%
10000
);
ltime
.
month
=
(
int
)
((
uint32
)
tmp
/
100
%
100
);
ltime
.
day
=
(
int
)
((
uint32
)
tmp
%
100
);
make_datetime
(
val_buffer
,
&
ltime
,
0
,
0
,
tmp_format
->
format
,
tmp_format
->
format_length
,
1
);
return
val_buffer
;
}
...
...
@@ -3485,7 +3500,7 @@ int Field_newdate::store(const char *from,uint len,CHARSET_INFO *cs)
TIME
l_time
;
long
tmp
;
int
error
=
0
;
if
(
str_to_TIME
(
from
,
len
,
&
l_time
,
1
)
==
TIMESTAMP_NONE
)
if
(
str_to_TIME
(
from
,
len
,
&
l_time
,
1
,
current_thd
)
<=
WRONG_TIMESTAMP_FULL
)
{
tmp
=
0L
;
error
=
1
;
...
...
@@ -3654,7 +3669,7 @@ void Field_newdate::sql_type(String &res) const
int
Field_datetime
::
store
(
const
char
*
from
,
uint
len
,
CHARSET_INFO
*
cs
)
{
longlong
tmp
=
str_to_datetime
(
from
,
len
,
1
);
longlong
tmp
=
str_to_datetime
(
from
,
len
,
1
,
current_thd
);
#ifdef WORDS_BIGENDIAN
if
(
table
->
db_low_byte_first
)
{
...
...
sql/item.cc
View file @
b6156392
...
...
@@ -46,7 +46,7 @@ Item::Item():
collation
.
set
(
default_charset
(),
DERIVATION_COERCIBLE
);
name
=
0
;
decimals
=
0
;
max_length
=
0
;
THD
*
thd
=
current_thd
;
thd
=
current_thd
;
next
=
thd
->
free_list
;
// Put in free list
thd
->
free_list
=
this
;
/*
...
...
@@ -69,7 +69,7 @@ Item::Item():
Used for duplicating lists in processing queries with temporary
tables
*/
Item
::
Item
(
THD
*
thd
,
Item
&
item
)
:
Item
::
Item
(
THD
*
c_
thd
,
Item
&
item
)
:
str_value
(
item
.
str_value
),
name
(
item
.
name
),
max_length
(
item
.
max_length
),
...
...
@@ -82,7 +82,8 @@ Item::Item(THD *thd, Item &item):
fixed
(
item
.
fixed
),
collation
(
item
.
collation
)
{
next
=
thd
->
free_list
;
// Put in free list
next
=
c_thd
->
free_list
;
// Put in free list
thd
=
c_thd
;
thd
->
free_list
=
this
;
}
...
...
@@ -174,7 +175,8 @@ bool Item::get_date(TIME *ltime,bool fuzzydate)
char
buff
[
40
];
String
tmp
(
buff
,
sizeof
(
buff
),
&
my_charset_bin
),
*
res
;
if
(
!
(
res
=
val_str
(
&
tmp
))
||
str_to_TIME
(
res
->
ptr
(),
res
->
length
(),
ltime
,
fuzzydate
)
==
TIMESTAMP_NONE
)
str_to_TIME
(
res
->
ptr
(),
res
->
length
(),
ltime
,
fuzzydate
,
thd
)
<=
WRONG_TIMESTAMP_FULL
)
{
bzero
((
char
*
)
ltime
,
sizeof
(
*
ltime
));
return
1
;
...
...
@@ -192,7 +194,7 @@ bool Item::get_time(TIME *ltime)
char
buff
[
40
];
String
tmp
(
buff
,
sizeof
(
buff
),
&
my_charset_bin
),
*
res
;
if
(
!
(
res
=
val_str
(
&
tmp
))
||
str_to_time
(
res
->
ptr
(),
res
->
length
(),
ltime
))
str_to_time
(
res
->
ptr
(),
res
->
length
(),
ltime
,
thd
))
{
bzero
((
char
*
)
ltime
,
sizeof
(
*
ltime
));
return
1
;
...
...
@@ -673,30 +675,28 @@ String *Item_param::query_val_str(String* str)
}
else
{
char
buff
[
25
];
DATETIME_FORMAT
*
tmp_format
=
0
;
bool
is_time_only
=
0
;
switch
(
ltime
.
time_type
)
{
case
TIMESTAMP_NONE
:
case
WRONG_TIMESTAMP_FULL
:
break
;
case
TIMESTAMP_DATE
:
sprintf
(
buff
,
"%04d-%02d-%02d"
,
ltime
.
year
,
ltime
.
month
,
ltime
.
day
);
str
->
append
(
buff
,
10
);
tmp_format
=
&
t_datetime_frm
(
thd
,
DATE_FORMAT_TYPE
).
datetime_format
;
break
;
case
TIMESTAMP_FULL
:
sprintf
(
buff
,
"%04d-%02d-%02d %02d:%02d:%02d"
,
ltime
.
year
,
ltime
.
month
,
ltime
.
day
,
ltime
.
hour
,
ltime
.
minute
,
ltime
.
second
);
str
->
append
(
buff
,
19
);
tmp_format
=
&
t_datetime_frm
(
thd
,
DATETIME_FORMAT_TYPE
).
datetime_format
;
break
;
case
TIMESTAMP_TIME
:
{
sprintf
(
buff
,
"%02d:%02d:%02d"
,
ltime
.
hour
,
ltime
.
minute
,
ltime
.
second
);
str
->
append
(
buff
,
8
);
tmp_format
=
&
t_datetime_frm
(
thd
,
TIME_FORMAT_TYPE
).
datetime_format
;
is_time_only
=
1
;
break
;
}
}
make_datetime
(
str
,
&
ltime
,
is_time_only
,
0
,
tmp_format
->
format
,
tmp_format
->
format_length
,
0
);
}
str
->
append
(
"'"
);
}
...
...
sql/item.h
View file @
b6156392
...
...
@@ -114,6 +114,14 @@ class Item {
my_bool
fixed
;
/* If item fixed with fix_fields */
DTCollation
collation
;
/*
thd is current_thd value. Like some other Item's fields it
will be a problem for using one Item in different threads
(as stored procedures may want to do in the future)
*/
THD
*
thd
;
// alloc & destruct is done as start of select using sql_alloc
Item
();
/*
...
...
@@ -124,7 +132,7 @@ class Item {
top AND/OR ctructure of WHERE clause to protect it of
optimisation changes in prepared statements
*/
Item
(
THD
*
thd
,
Item
&
item
);
Item
(
THD
*
c_
thd
,
Item
&
item
);
virtual
~
Item
()
{
name
=
0
;
}
/*lint -e1509 */
void
set_name
(
const
char
*
str
,
uint
length
,
CHARSET_INFO
*
cs
);
void
init_make_field
(
Send_field
*
tmp_field
,
enum
enum_field_types
type
);
...
...
sql/item_create.cc
View file @
b6156392
...
...
@@ -701,3 +701,8 @@ Item *create_func_maketime(Item* a,Item* b,Item* c)
{
return
new
Item_func_maketime
(
a
,
b
,
c
);
}
Item
*
create_func_str_to_date
(
Item
*
a
,
Item
*
b
)
{
return
new
Item_func_str_to_date
(
a
,
b
);
}
sql/item_create.h
View file @
b6156392
...
...
@@ -149,3 +149,4 @@ Item *create_func_addtime(Item* a,Item* b);
Item
*
create_func_subtime
(
Item
*
a
,
Item
*
b
);
Item
*
create_func_timediff
(
Item
*
a
,
Item
*
b
);
Item
*
create_func_maketime
(
Item
*
a
,
Item
*
b
,
Item
*
c
);
Item
*
create_func_str_to_date
(
Item
*
a
,
Item
*
b
);
sql/item_timefunc.cc
View file @
b6156392
...
...
@@ -57,82 +57,544 @@ static String day_names[] =
String
(
"Sunday"
,
&
my_charset_latin1
)
};
enum
date_time_format_types
uint
check_names
(
String
*
arr
,
int
item_count
,
const
char
*
val_ptr
,
const
char
*
val_end
,
uint
*
val
,
bool
check_part
)
{
TIME_ONLY
=
0
,
TIME_MICROSECOND
,
DATE_ONLY
,
DATE_TIME
,
DATE_TIME_MICROSECOND
};
for
(
int
i
=
0
;
i
<
item_count
;
i
++
)
{
String
*
tmp
=&
arr
[
i
];
if
(
!
my_strnncoll
(
&
my_charset_latin1
,
(
const
uchar
*
)
val_ptr
,
3
,
(
const
uchar
*
)
tmp
->
ptr
(),
3
))
{
if
(
check_part
)
{
*
val
=
i
+
1
;
return
3
;
}
typedef
struct
date_time_format
{
const
char
*
format_str
;
uint
length
;
};
int
part_len
=
tmp
->
length
()
-
3
;
int
val_len
=
val_end
-
val_ptr
-
3
;
if
(
val_len
<
part_len
)
return
0
;
val_ptr
+=
3
;
if
(
!
my_strnncoll
(
&
my_charset_latin1
,
(
const
uchar
*
)
val_ptr
,
part_len
,
(
const
uchar
*
)
tmp
->
ptr
()
+
3
,
part_len
))
{
*
val
=
i
+
1
;
return
tmp
->
length
();
}
return
0
;
}
}
return
0
;
}
static
struct
date_time_format
date_time_formats
[]
=
uint
check_val_is_digit
(
const
char
*
ptr
,
uint
val_len
,
uint
digit_count
)
{
{
"%s%02d:%02d:%02d"
,
10
},
{
"%s%02d:%02d:%02d.%06d"
,
17
},
{
"%04d-%02d-%02d"
,
10
},
{
"%04d-%02d-%02d %02d:%02d:%02d"
,
19
},
{
"%04d-%02d-%02d %02d:%02d:%02d.%06d"
,
26
}
};
uint
i
;
uint
verify_count
=
(
val_len
<
digit_count
?
val_len
:
digit_count
);
uint
digit_found
=
0
;
for
(
i
=
0
;
i
<
verify_count
;
i
++
)
{
if
(
!
my_isdigit
(
&
my_charset_latin1
,
*
(
ptr
+
i
)))
break
;
digit_found
++
;
}
return
digit_found
;
}
/*
OPTIMIZATION TODO:
- Replace the switch with a function that should be called for each
date type.
- Remove sprintf and opencode the conversion, like we do in
Field_datetime.
Extract datetime value to TIME struct from string value
according to format string.
*/
String
*
make_datetime
(
String
*
str
,
TIME
*
ltime
,
enum
date_time_format_types
format
)
bool
extract_datetime
(
const
char
*
str_val
,
uint
str_val_len
,
const
char
*
str_format
,
uint
str_format_len
,
TIME
*
l_time
)
{
char
*
buff
;
char
intbuff
[
15
];
int
weekday
=
0
,
yearday
=
0
,
daypart
=
0
,
len
;
int
val_len
=
0
;
int
week_number
=
-
1
;
ulong
length
;
CHARSET_INFO
*
cs
=
&
my_charset_bin
;
uint
length
=
date_time_formats
[
format
].
length
+
32
;
const
char
*
format_str
=
date_time_formats
[
format
].
format_str
;
int
err
=
0
;
bool
usa_time
=
0
;
bool
sunday_first
=
0
;
const
char
*
rT_format
=
"%H:%i:%s"
;
uint
part_len
=
0
;
const
char
*
val_ptr
=
str_val
;
const
char
*
val_end
=
str_val
+
str_val_len
;
const
char
*
ptr
=
str_format
;
const
char
*
end
=
ptr
+
str_format_len
;
DBUG_ENTER
(
"extract_datetime"
);
for
(;
ptr
!=
end
&&
val_ptr
!=
val_end
;
ptr
++
)
{
if
(
*
ptr
==
'%'
&&
ptr
+
1
!=
end
)
{
val_len
=
val_end
-
val_ptr
;
char
*
val_end1
=
(
char
*
)
val_end
;
switch
(
*++
ptr
)
{
case
'h'
:
case
'I'
:
case
'H'
:
l_time
->
hour
=
my_strntoll
(
cs
,
val_ptr
,
2
,
10
,
&
val_end1
,
&
err
);
if
(
err
||
(
val_end1
-
val_ptr
!=
2
))
return
1
;
usa_time
=
(
*
ptr
==
'I'
||
*
ptr
==
'h'
);
val_ptr
+=
2
;
break
;
case
'k'
:
case
'l'
:
l_time
->
hour
=
my_strntoll
(
cs
,
val_ptr
,
2
,
10
,
&
val_end1
,
&
err
);
if
(
err
)
return
1
;
usa_time
=
(
*
ptr
==
'l'
);
val_ptr
=
val_end1
;
break
;
case
'e'
:
l_time
->
day
=
my_strntoll
(
cs
,
val_ptr
,
2
,
10
,
&
val_end1
,
&
err
);
if
(
err
)
return
1
;
val_ptr
=
val_end1
;
break
;
case
'c'
:
l_time
->
month
=
my_strntoll
(
cs
,
val_ptr
,
2
,
10
,
&
val_end1
,
&
err
);
if
(
err
)
return
1
;
val_ptr
=
val_end1
;
break
;
case
'Y'
:
l_time
->
year
=
my_strntoll
(
cs
,
val_ptr
,
4
,
10
,
&
val_end1
,
&
err
);
if
(
err
||
(
val_end1
-
val_ptr
!=
4
))
return
1
;
val_ptr
+=
4
;
break
;
case
'y'
:
l_time
->
year
=
my_strntoll
(
cs
,
val_ptr
,
2
,
10
,
&
val_end1
,
&
err
);
if
(
err
||
(
val_end1
-
val_ptr
!=
2
))
return
1
;
l_time
->
year
+=
(
l_time
->
year
<
YY_PART_YEAR
?
2000
:
1900
);
val_ptr
+=
2
;
break
;
case
'm'
:
l_time
->
month
=
my_strntoll
(
cs
,
val_ptr
,
2
,
10
,
&
val_end1
,
&
err
);
if
(
err
||
(
val_end1
-
val_ptr
!=
2
))
return
1
;
val_ptr
+=
2
;
break
;
case
'd'
:
l_time
->
day
=
my_strntoll
(
cs
,
val_ptr
,
2
,
10
,
&
val_end1
,
&
err
);
if
(
err
||
(
val_end1
-
val_ptr
!=
2
))
return
1
;
val_ptr
+=
2
;
break
;
case
'D'
:
l_time
->
day
=
my_strntoll
(
cs
,
val_ptr
,
2
,
10
,
&
val_end1
,
&
err
);
if
(
err
||
(
val_len
<
val_end1
-
val_ptr
+
2
))
return
1
;
val_ptr
=
val_end1
+
2
;
break
;
case
'i'
:
l_time
->
minute
=
my_strntoll
(
cs
,
val_ptr
,
2
,
10
,
&
val_end1
,
&
err
);
if
(
err
||
(
val_end1
-
val_ptr
!=
2
))
return
1
;
val_ptr
+=
2
;
break
;
case
's'
:
case
'S'
:
l_time
->
second
=
my_strntoll
(
cs
,
val_ptr
,
2
,
10
,
&
val_end1
,
&
err
);
if
(
err
||
(
val_end1
-
val_ptr
!=
2
))
return
1
;
val_ptr
+=
2
;
break
;
case
'M'
:
if
(
val_len
<
3
||
!
(
part_len
=
check_names
(
month_names
,
12
,
val_ptr
,
val_end
,
&
l_time
->
month
,
0
)))
return
1
;
val_ptr
+=
part_len
;
break
;
case
'b'
:
if
(
val_len
<
3
||
!
(
part_len
=
check_names
(
month_names
,
12
,
val_ptr
,
val_end
,(
uint
*
)
&
l_time
->
month
,
1
)))
return
1
;
val_ptr
+=
part_len
;
break
;
case
'W'
:
if
(
val_len
<
3
||
!
(
part_len
=
check_names
(
day_names
,
7
,
val_ptr
,
val_end
,(
uint
*
)
&
weekday
,
0
)))
return
1
;
val_ptr
+=
part_len
;
break
;
case
'a'
:
if
(
val_len
<
3
||
!
(
part_len
=
check_names
(
day_names
,
7
,
val_ptr
,
val_end
,(
uint
*
)
&
weekday
,
1
)))
return
1
;
val_ptr
+=
part_len
;
break
;
case
'w'
:
weekday
=
my_strntoll
(
cs
,
val_ptr
,
1
,
10
,
&
val_end1
,
&
err
);
if
(
err
)
return
1
;
val_ptr
++
;
break
;
case
'j'
:
yearday
=
my_strntoll
(
cs
,
val_ptr
,
3
,
10
,
&
val_end1
,
&
err
);
if
(
err
||
(
val_end1
-
val_ptr
!=
3
))
return
1
;
val_ptr
+=
3
;
break
;
case
'f'
:
l_time
->
second_part
=
my_strntoll
(
cs
,
val_ptr
,
3
,
10
,
&
val_end1
,
&
err
);
if
(
err
)
return
1
;
val_ptr
=
val_end1
;
break
;
case
'p'
:
if
(
val_len
<
2
)
return
1
;
if
(
!
my_strnncoll
(
&
my_charset_latin1
,
(
const
uchar
*
)
val_ptr
,
2
,
(
const
uchar
*
)
"PM"
,
2
))
{
daypart
=
12
;
val_ptr
+=
2
;
}
break
;
case
'U'
:
week_number
=
my_strntoll
(
cs
,
val_ptr
,
2
,
10
,
&
val_end1
,
&
err
);
if
(
err
||
(
val_end1
-
val_ptr
!=
2
))
return
1
;
sunday_first
=
1
;
val_ptr
+=
2
;
break
;
case
'u'
:
week_number
=
my_strntoll
(
cs
,
val_ptr
,
2
,
10
,
&
val_end1
,
&
err
);
if
(
err
||
(
val_end1
-
val_ptr
!=
2
))
return
1
;
sunday_first
=
0
;
val_ptr
+=
2
;
break
;
case
'r'
:
case
'T'
:
usa_time
=
(
*
ptr
==
'r'
);
if
(
extract_datetime
(
val_ptr
,
val_end
-
val_ptr
,
rT_format
,
strlen
(
rT_format
),
l_time
))
return
1
;
val_ptr
+=
8
;
break
;
default:
if
(
*
val_ptr
!=
*
ptr
)
return
1
;
val_ptr
++
;
}
}
else
{
if
(
*
val_ptr
!=
*
ptr
)
return
1
;
val_ptr
++
;
}
}
if
(
usa_time
)
{
if
(
l_time
->
hour
>
12
||
l_time
->
hour
<
1
)
return
1
;
l_time
->
hour
=
l_time
->
hour
%
12
+
daypart
;
}
if
(
str
->
alloc
(
length
))
return
0
;
if
(
yearday
>
0
)
{
uint
days
=
calc_daynr
(
l_time
->
year
,
1
,
1
)
+
yearday
-
1
;
if
(
days
>
0
||
days
<
MAX_DAY_NUMBER
)
{
get_date_from_daynr
(
days
,
&
l_time
->
year
,
&
l_time
->
month
,
&
l_time
->
day
);
}
}
if
(
week_number
>=
0
&&
weekday
)
{
int
days
=
calc_daynr
(
l_time
->
year
,
1
,
1
);
uint
weekday_b
;
if
(
weekday
>
7
||
weekday
<
0
)
return
1
;
if
(
sunday_first
)
weekday
=
weekday
%
7
;
if
(
week_number
==
53
)
{
days
+=
(
week_number
-
1
)
*
7
;
weekday_b
=
calc_weekday
(
days
,
sunday_first
);
weekday
=
weekday
-
weekday_b
-
!
sunday_first
;
days
+=
weekday
;
}
else
if
(
week_number
==
0
)
{
weekday_b
=
calc_weekday
(
days
,
sunday_first
);
weekday
=
weekday
-
weekday_b
-
!
sunday_first
;
days
+=
weekday
;
}
else
{
days
+=
(
week_number
-
!
sunday_first
)
*
7
;
weekday_b
=
calc_weekday
(
days
,
sunday_first
);
weekday
=
weekday
-
weekday_b
-
!
sunday_first
;
days
+=
weekday
;
}
if
(
days
>
0
||
days
<
MAX_DAY_NUMBER
)
{
get_date_from_daynr
(
days
,
&
l_time
->
year
,
&
l_time
->
month
,
&
l_time
->
day
);
}
}
if
(
l_time
->
month
>
12
||
l_time
->
day
>
31
||
l_time
->
hour
>
23
||
l_time
->
minute
>
59
||
l_time
->
second
>
59
)
return
1
;
buff
=
(
char
*
)
str
->
ptr
();
switch
(
format
)
{
case
TIME_ONLY
:
length
=
cs
->
cset
->
snprintf
(
cs
,
buff
,
length
,
format_str
,
ltime
->
neg
?
"-"
:
""
,
ltime
->
hour
,
ltime
->
minute
,
ltime
->
second
);
DBUG_RETURN
(
0
);
}
/*
Print datetime string from TIME struct
according to format string.
*/
String
*
make_datetime
(
String
*
str
,
TIME
*
l_time
,
const
bool
is_time_only
,
const
bool
add_second_frac
,
const
char
*
ptr
,
uint
format_length
,
bool
set_len_to_zero
)
{
char
intbuff
[
15
];
uint
days_i
;
uint
hours_i
;
uint
weekday
;
ulong
length
;
if
(
set_len_to_zero
)
str
->
length
(
0
);
if
(
l_time
->
neg
)
str
->
append
(
"-"
,
1
);
const
char
*
end
=
ptr
+
format_length
;
for
(;
ptr
!=
end
;
ptr
++
)
{
if
(
*
ptr
!=
'%'
||
ptr
+
1
==
end
)
str
->
append
(
*
ptr
);
else
{
switch
(
*++
ptr
)
{
case
'M'
:
if
(
!
l_time
->
month
)
return
0
;
str
->
append
(
month_names
[
l_time
->
month
-
1
]);
break
;
case
'b'
:
if
(
!
l_time
->
month
)
return
0
;
str
->
append
(
month_names
[
l_time
->
month
-
1
].
ptr
(),
3
);
break
;
case
TIME_MICROSECOND
:
length
=
cs
->
cset
->
snprintf
(
cs
,
buff
,
length
,
format_str
,
ltime
->
neg
?
"-"
:
""
,
ltime
->
hour
,
ltime
->
minute
,
ltime
->
second
,
ltime
->
second_part
);
case
'W'
:
if
(
is_time_only
)
return
0
;
weekday
=
calc_weekday
(
calc_daynr
(
l_time
->
year
,
l_time
->
month
,
l_time
->
day
),
0
);
str
->
append
(
day_names
[
weekday
]);
break
;
case
DATE_ONLY
:
length
=
cs
->
cset
->
snprintf
(
cs
,
buff
,
length
,
format_str
,
ltime
->
year
,
ltime
->
month
,
ltime
->
day
);
case
'a'
:
if
(
is_time_only
)
return
0
;
weekday
=
calc_weekday
(
calc_daynr
(
l_time
->
year
,
l_time
->
month
,
l_time
->
day
),
0
);
str
->
append
(
day_names
[
weekday
].
ptr
(),
3
);
break
;
case
'D'
:
if
(
is_time_only
)
return
0
;
length
=
int10_to_str
(
l_time
->
day
,
intbuff
,
10
)
-
intbuff
;
str
->
append_with_prefill
(
intbuff
,
length
,
1
,
'0'
);
if
(
l_time
->
day
>=
10
&&
l_time
->
day
<=
19
)
str
->
append
(
"th"
);
else
{
switch
(
l_time
->
day
%
10
)
{
case
1
:
str
->
append
(
"st"
,
2
);
break
;
case
DATE_TIME
:
length
=
cs
->
cset
->
snprintf
(
cs
,
buff
,
length
,
format_str
,
ltime
->
year
,
ltime
->
month
,
ltime
->
day
,
ltime
->
hour
,
ltime
->
minute
,
ltime
->
second
);
case
2
:
str
->
append
(
"nd"
,
2
);
break
;
case
DATE_TIME_MICROSECOND
:
length
=
cs
->
cset
->
snprintf
(
cs
,
buff
,
length
,
format_str
,
ltime
->
year
,
ltime
->
month
,
ltime
->
day
,
ltime
->
hour
,
ltime
->
minute
,
ltime
->
second
,
ltime
->
second_part
);
case
3
:
str
->
append
(
"rd"
,
2
);
break
;
default:
str
->
append
(
"th"
,
2
);
break
;
}
}
break
;
case
'Y'
:
length
=
int10_to_str
(
l_time
->
year
,
intbuff
,
10
)
-
intbuff
;
str
->
append_with_prefill
(
intbuff
,
length
,
4
,
'0'
);
break
;
case
'y'
:
length
=
int10_to_str
(
l_time
->
year
%
100
,
intbuff
,
10
)
-
intbuff
;
str
->
append_with_prefill
(
intbuff
,
length
,
2
,
'0'
);
break
;
case
'm'
:
length
=
int10_to_str
(
l_time
->
month
,
intbuff
,
10
)
-
intbuff
;
str
->
append_with_prefill
(
intbuff
,
length
,
2
,
'0'
);
break
;
case
'c'
:
length
=
int10_to_str
(
l_time
->
month
,
intbuff
,
10
)
-
intbuff
;
str
->
append_with_prefill
(
intbuff
,
length
,
1
,
'0'
);
break
;
case
'd'
:
length
=
int10_to_str
(
l_time
->
day
,
intbuff
,
10
)
-
intbuff
;
str
->
append_with_prefill
(
intbuff
,
length
,
2
,
'0'
);
break
;
case
'e'
:
length
=
int10_to_str
(
l_time
->
day
,
intbuff
,
10
)
-
intbuff
;
str
->
append_with_prefill
(
intbuff
,
length
,
1
,
'0'
);
break
;
case
'f'
:
length
=
int10_to_str
(
l_time
->
second_part
,
intbuff
,
10
)
-
intbuff
;
str
->
append_with_prefill
(
intbuff
,
length
,
6
,
'0'
);
break
;
case
'H'
:
length
=
int10_to_str
(
l_time
->
hour
,
intbuff
,
10
)
-
intbuff
;
str
->
append_with_prefill
(
intbuff
,
length
,
2
,
'0'
);
break
;
case
'h'
:
case
'I'
:
days_i
=
l_time
->
hour
/
24
;
hours_i
=
(
l_time
->
hour
%
24
+
11
)
%
12
+
1
+
24
*
days_i
;
length
=
int10_to_str
(
hours_i
,
intbuff
,
10
)
-
intbuff
;
str
->
append_with_prefill
(
intbuff
,
length
,
2
,
'0'
);
break
;
case
'i'
:
/* minutes */
length
=
int10_to_str
(
l_time
->
minute
,
intbuff
,
10
)
-
intbuff
;
str
->
append_with_prefill
(
intbuff
,
length
,
2
,
'0'
);
break
;
case
'j'
:
if
(
is_time_only
)
return
0
;
length
=
int10_to_str
(
calc_daynr
(
l_time
->
year
,
l_time
->
month
,
l_time
->
day
)
-
calc_daynr
(
l_time
->
year
,
1
,
1
)
+
1
,
intbuff
,
10
)
-
intbuff
;
str
->
append_with_prefill
(
intbuff
,
length
,
3
,
'0'
);
break
;
case
'k'
:
length
=
int10_to_str
(
l_time
->
hour
,
intbuff
,
10
)
-
intbuff
;
str
->
append_with_prefill
(
intbuff
,
length
,
1
,
'0'
);
break
;
case
'l'
:
days_i
=
l_time
->
hour
/
24
;
hours_i
=
(
l_time
->
hour
%
24
+
11
)
%
12
+
1
+
24
*
days_i
;
length
=
int10_to_str
(
hours_i
,
intbuff
,
10
)
-
intbuff
;
str
->
append_with_prefill
(
intbuff
,
length
,
1
,
'0'
);
break
;
case
'p'
:
hours_i
=
l_time
->
hour
%
24
;
str
->
append
(
hours_i
<
12
?
"AM"
:
"PM"
,
2
);
break
;
case
'r'
:
length
=
my_sprintf
(
intbuff
,
(
intbuff
,
(
l_time
->
hour
<
12
)
?
"%02d:%02d:%02d AM"
:
"%02d:%02d:%02d PM"
,
(
l_time
->
hour
+
11
)
%
12
+
1
,
l_time
->
minute
,
l_time
->
second
));
str
->
append
(
intbuff
,
length
);
break
;
case
'S'
:
case
's'
:
length
=
int10_to_str
(
l_time
->
second
,
intbuff
,
10
)
-
intbuff
;
str
->
append_with_prefill
(
intbuff
,
length
,
2
,
'0'
);
if
(
add_second_frac
)
{
str
->
append
(
"."
,
1
);
length
=
int10_to_str
(
l_time
->
second_part
,
intbuff
,
10
)
-
intbuff
;
str
->
append_with_prefill
(
intbuff
,
length
,
6
,
'0'
);
}
break
;
case
'T'
:
length
=
my_sprintf
(
intbuff
,
(
intbuff
,
"%02d:%02d:%02d"
,
l_time
->
hour
,
l_time
->
minute
,
l_time
->
second
));
str
->
append
(
intbuff
,
length
);
break
;
case
'U'
:
case
'u'
:
{
uint
year
;
if
(
is_time_only
)
return
0
;
length
=
int10_to_str
(
calc_week
(
l_time
,
0
,
(
*
ptr
)
==
'U'
,
&
year
),
intbuff
,
10
)
-
intbuff
;
str
->
append_with_prefill
(
intbuff
,
length
,
2
,
'0'
);
}
break
;
case
'v'
:
case
'V'
:
{
uint
year
;
if
(
is_time_only
)
return
0
;
length
=
int10_to_str
(
calc_week
(
l_time
,
1
,
(
*
ptr
)
==
'V'
,
&
year
),
intbuff
,
10
)
-
intbuff
;
str
->
append_with_prefill
(
intbuff
,
length
,
2
,
'0'
);
}
break
;
case
'x'
:
case
'X'
:
{
uint
year
;
if
(
is_time_only
)
return
0
;
(
void
)
calc_week
(
l_time
,
1
,
(
*
ptr
)
==
'X'
,
&
year
);
length
=
int10_to_str
(
year
,
intbuff
,
10
)
-
intbuff
;
str
->
append_with_prefill
(
intbuff
,
length
,
4
,
'0'
);
}
break
;
case
'w'
:
if
(
is_time_only
)
return
0
;
weekday
=
calc_weekday
(
calc_daynr
(
l_time
->
year
,
l_time
->
month
,
l_time
->
day
),
1
);
length
=
int10_to_str
(
weekday
,
intbuff
,
10
)
-
intbuff
;
str
->
append_with_prefill
(
intbuff
,
length
,
1
,
'0'
);
break
;
default:
str
->
append
(
*
ptr
);
break
;
}
}
}
str
->
length
(
length
);
str
->
set_charset
(
cs
);
return
str
;
}
/*
** Get a array of positive numbers from a string object.
** Each number is separated by 1 non digit character
...
...
@@ -346,7 +808,7 @@ longlong Item_func_year::val_int()
longlong
Item_func_unix_timestamp
::
val_int
()
{
if
(
arg_count
==
0
)
return
(
longlong
)
current_
thd
->
query_start
();
return
(
longlong
)
thd
->
query_start
();
if
(
args
[
0
]
->
type
()
==
FIELD_ITEM
)
{
// Optimize timestamp field
Field
*
field
=
((
Item_field
*
)
args
[
0
])
->
field
;
...
...
@@ -358,7 +820,7 @@ longlong Item_func_unix_timestamp::val_int()
{
return
0
;
/* purecov: inspected */
}
return
(
longlong
)
str_to_timestamp
(
str
->
ptr
(),
str
->
length
());
return
(
longlong
)
str_to_timestamp
(
str
->
ptr
(),
str
->
length
()
,
thd
);
}
...
...
@@ -522,22 +984,26 @@ static bool get_interval_value(Item *args,interval_type int_type,
String
*
Item_date
::
val_str
(
String
*
str
)
{
DATETIME_FORMAT
*
tmp_format
;
TIME
ltime
;
ulong
value
=
(
ulong
)
val_int
();
if
(
null_value
)
return
(
String
*
)
0
;
if
(
!
value
)
// zero daynr
{
str
->
copy
(
"0000-00-00"
,
10
,
&
my_charset_latin1
,
default_charset
());
return
str
;
}
goto
null_date
;
ltime
.
year
=
(
value
/
10000L
)
%
10000
;
ltime
.
month
=
(
value
/
100
)
%
100
;
ltime
.
day
=
(
value
%
100
);
ltime
.
neg
=
0
;
ltime
.
time_type
=
TIMESTAMP_DATE
;
char
tmpbuff
[
11
];
sprintf
(
tmpbuff
,
"%04d-%02d-%02d"
,
(
int
)
(
value
/
10000L
)
%
10000
,
(
int
)
(
value
/
100
)
%
100
,
(
int
)
(
value
%
100
));
str
->
copy
(
tmpbuff
,
10
,
&
my_charset_latin1
,
default_charset
());
tmp_format
=
&
t_datetime_frm
(
thd
,
DATE_FORMAT_TYPE
).
datetime_format
;
if
(
make_datetime
(
str
,
&
ltime
,
0
,
0
,
tmp_format
->
format
,
tmp_format
->
format_length
,
1
))
return
str
;
null_value
=
1
;
null_date:
return
0
;
}
...
...
@@ -577,7 +1043,7 @@ void Item_func_curdate::fix_length_and_dec()
decimals
=
0
;
max_length
=
10
*
default_charset
()
->
mbmaxlen
;
store_now_in_tm
(
current_
thd
->
query_start
(),
&
start
);
store_now_in_tm
(
thd
->
query_start
(),
&
start
);
value
=
(
longlong
)
((
ulong
)
((
uint
)
start
.
tm_year
+
1900
)
*
10000L
+
((
uint
)
start
.
tm_mon
+
1
)
*
100
+
...
...
@@ -632,22 +1098,27 @@ String *Item_func_curtime::val_str(String *str)
void
Item_func_curtime
::
fix_length_and_dec
()
{
struct
tm
start
;
CHARSET_INFO
*
cs
=
default_charset
();
DATETIME_FORMAT
*
tmp_format
;
String
tmp
((
char
*
)
buff
,
sizeof
(
buff
),
default_charset
());
TIME
ltime
;
decimals
=
0
;
max_length
=
8
*
cs
->
mbmaxlen
;
collation
.
set
(
cs
);
store_now_in_tm
(
current_thd
->
query_start
(),
&
start
);
store_now_in_tm
(
thd
->
query_start
(),
&
start
);
value
=
(
longlong
)
((
ulong
)
((
uint
)
start
.
tm_hour
)
*
10000L
+
(
ulong
)
(((
uint
)
start
.
tm_min
)
*
100L
+
(
uint
)
start
.
tm_sec
));
buff_length
=
cs
->
cset
->
snprintf
(
cs
,
buff
,
sizeof
(
buff
),
"%02d:%02d:%02d"
,
(
int
)
start
.
tm_hour
,
(
int
)
start
.
tm_min
,
(
int
)
start
.
tm_sec
);
ltime
.
day
=
0
;
ltime
.
hour
=
start
.
tm_hour
;
ltime
.
minute
=
start
.
tm_min
;
ltime
.
second
=
start
.
tm_sec
;
ltime
.
second_part
=
0
;
ltime
.
neg
=
0
;
ltime
.
time_type
=
TIMESTAMP_TIME
;
tmp_format
=
&
t_datetime_frm
(
thd
,
TIME_FORMAT_TYPE
).
datetime_format
;
make_datetime
(
&
tmp
,
&
ltime
,
0
,
0
,
tmp_format
->
format
,
tmp_format
->
format_length
,
1
);
buff_length
=
tmp
.
length
();
max_length
=
buff_length
;
}
...
...
@@ -681,14 +1152,11 @@ String *Item_func_now::val_str(String *str)
void
Item_func_now
::
fix_length_and_dec
()
{
struct
tm
start
;
CHARSET_INFO
*
cs
=
&
my_charset_bin
;
DATETIME_FORMAT
*
tmp_format
;
String
tmp
((
char
*
)
buff
,
sizeof
(
buff
),
&
my_charset_bin
);
decimals
=
0
;
max_length
=
19
*
cs
->
mbmaxlen
;
collation
.
set
(
cs
);
store_now_in_tm
(
current_thd
->
query_start
(),
&
start
);
store_now_in_tm
(
thd
->
query_start
(),
&
start
);
value
=
((
longlong
)
((
ulong
)
((
uint
)
start
.
tm_year
+
1900
)
*
10000L
+
(((
uint
)
start
.
tm_mon
+
1
)
*
100
+
(
uint
)
start
.
tm_mday
))
*
(
longlong
)
1000000L
+
...
...
@@ -696,14 +1164,6 @@ void Item_func_now::fix_length_and_dec()
(
ulong
)
(((
uint
)
start
.
tm_min
)
*
100L
+
(
uint
)
start
.
tm_sec
)));
buff_length
=
(
uint
)
cs
->
cset
->
snprintf
(
cs
,
buff
,
sizeof
(
buff
),
"%04d-%02d-%02d %02d:%02d:%02d"
,
((
int
)
(
start
.
tm_year
+
1900
))
%
10000
,
(
int
)
start
.
tm_mon
+
1
,
(
int
)
start
.
tm_mday
,
(
int
)
start
.
tm_hour
,
(
int
)
start
.
tm_min
,
(
int
)
start
.
tm_sec
);
/* For getdate */
ltime
.
year
=
start
.
tm_year
+
1900
;
ltime
.
month
=
start
.
tm_mon
+
1
;
...
...
@@ -711,9 +1171,15 @@ void Item_func_now::fix_length_and_dec()
ltime
.
hour
=
start
.
tm_hour
;
ltime
.
minute
=
start
.
tm_min
;
ltime
.
second
=
start
.
tm_sec
;
ltime
.
second_part
=
0
;
ltime
.
neg
=
0
;
ltime
.
time_type
=
TIMESTAMP_FULL
;
ltime
.
second_part
=
0
;
ltime
.
neg
=
0
;
ltime
.
time_type
=
TIMESTAMP_FULL
;
tmp_format
=
&
t_datetime_frm
(
thd
,
DATETIME_FORMAT_TYPE
).
datetime_format
;
make_datetime
(
&
tmp
,
&
ltime
,
0
,
0
,
tmp_format
->
format
,
tmp_format
->
format_length
,
1
);
buff_length
=
tmp
.
length
();
max_length
=
buff_length
;
}
bool
Item_func_now
::
get_date
(
TIME
*
res
,
...
...
@@ -754,22 +1220,36 @@ void Item_func_now_utc::store_now_in_tm(time_t now, struct tm *now_tm)
String
*
Item_func_sec_to_time
::
val_str
(
String
*
str
)
{
char
buff
[
23
*
2
];
const
char
*
sign
=
""
;
longlong
seconds
=
(
longlong
)
args
[
0
]
->
val_int
();
ulong
length
;
uint
sec
;
DATETIME_FORMAT
*
tmp_format
;
TIME
ltime
;
if
((
null_value
=
args
[
0
]
->
null_value
))
return
(
String
*
)
0
;
goto
null_date
;
ltime
.
neg
=
0
;
if
(
seconds
<
0
)
{
seconds
=
-
seconds
;
sign
=
"-"
;
ltime
.
neg
=
1
;
}
uint
sec
=
(
uint
)
((
ulonglong
)
seconds
%
3600
);
length
=
my_sprintf
(
buff
,(
buff
,
"%s%02lu:%02u:%02u"
,
sign
,(
long
)
(
seconds
/
3600
),
sec
/
60
,
sec
%
60
));
str
->
copy
(
buff
,
length
,
&
my_charset_latin1
,
default_charset
());
sec
=
(
uint
)
((
ulonglong
)
seconds
%
3600
);
ltime
.
day
=
0
;
ltime
.
hour
=
seconds
/
3600
;
ltime
.
minute
=
sec
/
60
;
ltime
.
second
=
sec
%
60
;
tmp_format
=
&
t_datetime_frm
(
thd
,
TIME_FORMAT_TYPE
).
datetime_format
;
if
(
make_datetime
(
str
,
&
ltime
,
0
,
0
,
tmp_format
->
format
,
tmp_format
->
format_length
,
1
))
return
str
;
null_value
=
1
;
null_date:
return
(
String
*
)
0
;
}
...
...
@@ -879,9 +1359,7 @@ String *Item_func_date_format::val_str(String *str)
{
String
*
format
;
TIME
l_time
;
char
intbuff
[
15
];
uint
size
,
weekday
;
ulong
length
;
if
(
!
date_or_time
)
{
...
...
@@ -892,24 +1370,17 @@ String *Item_func_date_format::val_str(String *str)
{
String
*
res
;
if
(
!
(
res
=
args
[
0
]
->
val_str
(
str
)))
{
null_value
=
1
;
return
0
;
}
if
(
str_to_time
(
res
->
ptr
(),
res
->
length
(),
&
l_time
))
{
null_value
=
1
;
return
0
;
}
goto
null_date
;
if
(
str_to_time
(
res
->
ptr
(),
res
->
length
(),
&
l_time
,
thd
))
goto
null_date
;
l_time
.
year
=
l_time
.
month
=
l_time
.
day
=
0
;
null_value
=
0
;
}
if
(
!
(
format
=
args
[
1
]
->
val_str
(
str
))
||
!
format
->
length
())
{
null_value
=
1
;
return
0
;
}
goto
null_date
;
if
(
fixed_length
)
size
=
max_length
;
...
...
@@ -918,237 +1389,53 @@ String *Item_func_date_format::val_str(String *str)
if
(
format
==
str
)
str
=
&
value
;
// Save result here
if
(
str
->
alloc
(
size
))
{
null_value
=
1
;
return
0
;
}
str
->
length
(
0
);
goto
null_date
;
/* Create the result string */
const
char
*
ptr
=
format
->
ptr
();
const
char
*
end
=
ptr
+
format
->
length
();
for
(;
ptr
!=
end
;
ptr
++
)
{
if
(
*
ptr
!=
'%'
||
ptr
+
1
==
end
)
str
->
append
(
*
ptr
);
else
{
switch
(
*++
ptr
)
{
case
'M'
:
if
(
!
l_time
.
month
)
{
null_value
=
1
;
return
0
;
}
str
->
append
(
month_names
[
l_time
.
month
-
1
]);
break
;
case
'b'
:
if
(
!
l_time
.
month
)
{
null_value
=
1
;
return
0
;
}
str
->
append
(
month_names
[
l_time
.
month
-
1
].
ptr
(),
3
);
break
;
case
'W'
:
if
(
date_or_time
)
{
null_value
=
1
;
return
0
;
}
weekday
=
calc_weekday
(
calc_daynr
(
l_time
.
year
,
l_time
.
month
,
l_time
.
day
),
0
);
str
->
append
(
day_names
[
weekday
]);
break
;
case
'a'
:
if
(
date_or_time
)
{
null_value
=
1
;
return
0
;
}
weekday
=
calc_weekday
(
calc_daynr
(
l_time
.
year
,
l_time
.
month
,
l_time
.
day
),
0
);
str
->
append
(
day_names
[
weekday
].
ptr
(),
3
);
break
;
case
'D'
:
if
(
date_or_time
)
{
null_value
=
1
;
return
0
;
}
length
=
int10_to_str
(
l_time
.
day
,
intbuff
,
10
)
-
intbuff
;
str
->
append_with_prefill
(
intbuff
,
length
,
1
,
'0'
);
if
(
l_time
.
day
>=
10
&&
l_time
.
day
<=
19
)
str
->
append
(
"th"
);
else
{
switch
(
l_time
.
day
%
10
)
{
case
1
:
str
->
append
(
"st"
,
2
);
break
;
case
2
:
str
->
append
(
"nd"
,
2
);
break
;
case
3
:
str
->
append
(
"rd"
,
2
);
break
;
default:
str
->
append
(
"th"
,
2
);
break
;
}
}
break
;
case
'Y'
:
length
=
int10_to_str
(
l_time
.
year
,
intbuff
,
10
)
-
intbuff
;
str
->
append_with_prefill
(
intbuff
,
length
,
4
,
'0'
);
break
;
case
'y'
:
length
=
int10_to_str
(
l_time
.
year
%
100
,
intbuff
,
10
)
-
intbuff
;
str
->
append_with_prefill
(
intbuff
,
length
,
2
,
'0'
);
break
;
case
'm'
:
length
=
int10_to_str
(
l_time
.
month
,
intbuff
,
10
)
-
intbuff
;
str
->
append_with_prefill
(
intbuff
,
length
,
2
,
'0'
);
break
;
case
'c'
:
length
=
int10_to_str
(
l_time
.
month
,
intbuff
,
10
)
-
intbuff
;
str
->
append_with_prefill
(
intbuff
,
length
,
1
,
'0'
);
break
;
case
'd'
:
length
=
int10_to_str
(
l_time
.
day
,
intbuff
,
10
)
-
intbuff
;
str
->
append_with_prefill
(
intbuff
,
length
,
2
,
'0'
);
break
;
case
'e'
:
length
=
int10_to_str
(
l_time
.
day
,
intbuff
,
10
)
-
intbuff
;
str
->
append_with_prefill
(
intbuff
,
length
,
1
,
'0'
);
break
;
case
'f'
:
length
=
int10_to_str
(
l_time
.
second_part
,
intbuff
,
10
)
-
intbuff
;
str
->
append_with_prefill
(
intbuff
,
length
,
6
,
'0'
);
break
;
case
'H'
:
length
=
int10_to_str
(
l_time
.
hour
,
intbuff
,
10
)
-
intbuff
;
str
->
append_with_prefill
(
intbuff
,
length
,
2
,
'0'
);
break
;
case
'h'
:
case
'I'
:
length
=
int10_to_str
((
l_time
.
hour
+
11
)
%
12
+
1
,
intbuff
,
10
)
-
intbuff
;
str
->
append_with_prefill
(
intbuff
,
length
,
2
,
'0'
);
break
;
case
'i'
:
/* minutes */
length
=
int10_to_str
(
l_time
.
minute
,
intbuff
,
10
)
-
intbuff
;
str
->
append_with_prefill
(
intbuff
,
length
,
2
,
'0'
);
break
;
case
'j'
:
if
(
date_or_time
)
{
if
(
make_datetime
(
str
,
&
l_time
,
0
,
0
,
format
->
ptr
(),
format
->
length
(),
1
))
return
str
;
null_date:
null_value
=
1
;
return
0
;
}
length
=
int10_to_str
(
calc_daynr
(
l_time
.
year
,
l_time
.
month
,
l_time
.
day
)
-
calc_daynr
(
l_time
.
year
,
1
,
1
)
+
1
,
intbuff
,
10
)
-
intbuff
;
str
->
append_with_prefill
(
intbuff
,
length
,
3
,
'0'
);
break
;
case
'k'
:
length
=
int10_to_str
(
l_time
.
hour
,
intbuff
,
10
)
-
intbuff
;
str
->
append_with_prefill
(
intbuff
,
length
,
1
,
'0'
);
break
;
case
'l'
:
length
=
int10_to_str
((
l_time
.
hour
+
11
)
%
12
+
1
,
intbuff
,
10
)
-
intbuff
;
str
->
append_with_prefill
(
intbuff
,
length
,
1
,
'0'
);
break
;
case
'p'
:
str
->
append
(
l_time
.
hour
<
12
?
"AM"
:
"PM"
,
2
);
break
;
case
'r'
:
length
=
my_sprintf
(
intbuff
,
(
intbuff
,
(
l_time
.
hour
<
12
)
?
"%02d:%02d:%02d AM"
:
"%02d:%02d:%02d PM"
,
(
l_time
.
hour
+
11
)
%
12
+
1
,
l_time
.
minute
,
l_time
.
second
));
str
->
append
(
intbuff
,
length
);
break
;
case
'S'
:
case
's'
:
length
=
int10_to_str
(
l_time
.
second
,
intbuff
,
10
)
-
intbuff
;
str
->
append_with_prefill
(
intbuff
,
length
,
2
,
'0'
);
break
;
case
'T'
:
length
=
my_sprintf
(
intbuff
,
(
intbuff
,
"%02d:%02d:%02d"
,
l_time
.
hour
,
l_time
.
minute
,
l_time
.
second
));
str
->
append
(
intbuff
,
length
);
break
;
case
'U'
:
case
'u'
:
{
uint
year
;
length
=
int10_to_str
(
calc_week
(
&
l_time
,
0
,
(
*
ptr
)
==
'U'
,
&
year
),
intbuff
,
10
)
-
intbuff
;
str
->
append_with_prefill
(
intbuff
,
length
,
2
,
'0'
);
}
break
;
case
'v'
:
case
'V'
:
{
uint
year
;
length
=
int10_to_str
(
calc_week
(
&
l_time
,
1
,
(
*
ptr
)
==
'V'
,
&
year
),
intbuff
,
10
)
-
intbuff
;
str
->
append_with_prefill
(
intbuff
,
length
,
2
,
'0'
);
}
break
;
case
'x'
:
case
'X'
:
{
uint
year
;
(
void
)
calc_week
(
&
l_time
,
1
,
(
*
ptr
)
==
'X'
,
&
year
);
length
=
int10_to_str
(
year
,
intbuff
,
10
)
-
intbuff
;
str
->
append_with_prefill
(
intbuff
,
length
,
4
,
'0'
);
}
break
;
case
'w'
:
weekday
=
calc_weekday
(
calc_daynr
(
l_time
.
year
,
l_time
.
month
,
l_time
.
day
),
1
);
length
=
int10_to_str
(
weekday
,
intbuff
,
10
)
-
intbuff
;
str
->
append_with_prefill
(
intbuff
,
length
,
1
,
'0'
);
break
;
default:
str
->
append
(
*
ptr
);
break
;
}
}
}
return
str
;
}
String
*
Item_func_from_unixtime
::
val_str
(
String
*
str
)
{
struct
tm
tm_tmp
,
*
start
;
DATETIME_FORMAT
*
tmp_format
;
time_t
tmp
=
(
time_t
)
args
[
0
]
->
val_int
();
uint32
l
;
CHARSET_INFO
*
cs
=
default_charset
();
TIME
ltime
;
if
((
null_value
=
args
[
0
]
->
null_value
))
return
0
;
goto
null_date
;
localtime_r
(
&
tmp
,
&
tm_tmp
);
start
=&
tm_tmp
;
ltime
.
year
=
start
->
tm_year
+
1900
;
ltime
.
month
=
start
->
tm_mon
+
1
;
ltime
.
day
=
start
->
tm_mday
;
ltime
.
hour
=
start
->
tm_hour
;
ltime
.
minute
=
start
->
tm_min
;
ltime
.
second
=
start
->
tm_sec
;
ltime
.
second_part
=
0
;
ltime
.
neg
=
0
;
l
=
20
*
cs
->
mbmaxlen
+
32
;
if
(
str
->
alloc
(
l
))
return
str
;
/* purecov: inspected */
l
=
cs
->
cset
->
snprintf
(
cs
,(
char
*
)
str
->
ptr
(),
l
,
"%04d-%02d-%02d %02d:%02d:%02d"
,
(
int
)
start
->
tm_year
+
1900
,
(
int
)
start
->
tm_mon
+
1
,
(
int
)
start
->
tm_mday
,
(
int
)
start
->
tm_hour
,
(
int
)
start
->
tm_min
,
(
int
)
start
->
tm_sec
);
str
->
length
(
l
);
str
->
set_charset
(
cs
);
tmp_format
=
&
t_datetime_frm
(
thd
,
DATETIME_FORMAT_TYPE
).
datetime_format
;
if
(
str
->
alloc
(
l
)
&&
make_datetime
(
str
,
&
ltime
,
1
,
0
,
tmp_format
->
format
,
tmp_format
->
format_length
,
1
))
return
str
;
null_value
=
1
;
null_date:
return
0
;
}
...
...
@@ -1229,7 +1516,7 @@ bool Item_date_add_interval::get_date(TIME *ltime, bool fuzzy_date)
{
long
period
,
sign
;
INTERVAL
interval
;
ltime
->
neg
=
0
;
if
(
args
[
0
]
->
get_date
(
ltime
,
0
)
||
get_interval_value
(
args
[
1
],
int_type
,
&
value
,
&
interval
))
goto
null_date
;
...
...
@@ -1329,19 +1616,17 @@ bool Item_date_add_interval::get_date(TIME *ltime, bool fuzzy_date)
String
*
Item_date_add_interval
::
val_str
(
String
*
str
)
{
TIME
ltime
;
enum
date_time_format_types
format
;
DATETIME_FORMAT
*
tmp_
format
;
if
(
Item_date_add_interval
::
get_date
(
&
ltime
,
0
))
return
0
;
if
(
ltime
.
time_type
==
TIMESTAMP_DATE
)
format
=
DATE_ONLY
;
else
if
(
ltime
.
second_part
)
format
=
DATE_TIME_MICROSECOND
;
tmp_format
=
&
t_datetime_frm
(
thd
,
DATE_FORMAT_TYPE
).
datetime_format
;
else
format
=
DATE_TIME
;
if
(
make_datetime
(
str
,
&
ltime
,
format
))
tmp_format
=
&
t_datetime_frm
(
thd
,
DATETIME_FORMAT_TYPE
).
datetime_format
;
if
(
make_datetime
(
str
,
&
ltime
,
1
,
ltime
.
second_part
,
tmp_format
->
format
,
tmp_format
->
format_length
,
1
))
return
str
;
null_value
=
1
;
...
...
@@ -1400,7 +1685,7 @@ longlong Item_extract::val_int()
else
{
String
*
res
=
args
[
0
]
->
val_str
(
&
value
);
if
(
!
res
||
str_to_time
(
res
->
ptr
(),
res
->
length
(),
&
ltime
))
if
(
!
res
||
str_to_time
(
res
->
ptr
(),
res
->
length
(),
&
ltime
,
thd
))
{
null_value
=
1
;
return
0
;
...
...
@@ -1408,7 +1693,6 @@ longlong Item_extract::val_int()
neg
=
ltime
.
neg
?
-
1
:
1
;
null_value
=
0
;
}
switch
(
int_type
)
{
case
INTERVAL_YEAR
:
return
ltime
.
year
;
case
INTERVAL_YEAR_MONTH
:
return
ltime
.
year
*
100L
+
ltime
.
month
;
...
...
@@ -1530,10 +1814,12 @@ void Item_char_typecast::fix_length_and_dec()
String
*
Item_datetime_typecast
::
val_str
(
String
*
str
)
{
TIME
ltime
;
DATETIME_FORMAT
*
tmp_format
=
(
&
t_datetime_frm
(
thd
,
DATETIME_FORMAT_TYPE
).
datetime_format
);
if
(
!
get_arg0_date
(
&
ltime
,
1
)
&&
make_datetime
(
str
,
&
ltime
,
ltime
.
second_part
?
DATE_TIME_MICROSECOND
:
DATE_TIME
))
make_datetime
(
str
,
&
ltime
,
1
,
ltime
.
second_part
,
tmp_format
->
format
,
tmp_format
->
format_length
,
1
))
return
str
;
null_date:
...
...
@@ -1553,9 +1839,12 @@ bool Item_time_typecast::get_time(TIME *ltime)
String
*
Item_time_typecast
::
val_str
(
String
*
str
)
{
TIME
ltime
;
DATETIME_FORMAT
*
tmp_format
=
(
&
t_datetime_frm
(
thd
,
TIME_FORMAT_TYPE
).
datetime_format
);
if
(
!
get_arg0_time
(
&
ltime
)
&&
make_datetime
(
str
,
&
ltime
,
ltime
.
second_part
?
TIME_MICROSECOND
:
TIME_ONLY
))
make_datetime
(
str
,
&
ltime
,
0
,
ltime
.
second_part
,
tmp_format
->
format
,
tmp_format
->
format_length
,
1
))
return
str
;
null_value
=
1
;
...
...
@@ -1574,9 +1863,12 @@ bool Item_date_typecast::get_date(TIME *ltime, bool fuzzy_date)
String
*
Item_date_typecast
::
val_str
(
String
*
str
)
{
TIME
ltime
;
DATETIME_FORMAT
*
tmp_format
=
(
&
t_datetime_frm
(
thd
,
DATE_FORMAT_TYPE
).
datetime_format
);
if
(
!
get_arg0_date
(
&
ltime
,
1
)
&&
make_datetime
(
str
,
&
ltime
,
DATE_ONLY
))
make_datetime
(
str
,
&
ltime
,
1
,
0
,
tmp_format
->
format
,
tmp_format
->
format_length
,
1
))
return
str
;
null_date:
...
...
@@ -1605,7 +1897,11 @@ String *Item_func_makedate::val_str(String *str)
{
null_value
=
0
;
get_date_from_daynr
(
days
,
&
l_time
.
year
,
&
l_time
.
month
,
&
l_time
.
day
);
if
(
make_datetime
(
str
,
&
l_time
,
DATE_ONLY
))
DATETIME_FORMAT
*
tmp_format
=
(
&
t_datetime_frm
(
thd
,
DATE_FORMAT_TYPE
).
datetime_format
);
if
(
make_datetime
(
str
,
&
l_time
,
1
,
0
,
tmp_format
->
format
,
tmp_format
->
format_length
,
1
))
return
str
;
}
...
...
@@ -1656,6 +1952,7 @@ String *Item_func_add_time::val_str(String *str)
bool
is_time
=
0
;
long
microseconds
,
seconds
,
days
=
0
;
int
l_sign
=
sign
;
DATETIME_FORMAT
*
tmp_format
;
null_value
=
0
;
l_time3
.
neg
=
0
;
...
...
@@ -1720,19 +2017,21 @@ String *Item_func_add_time::val_str(String *str)
calc_time_from_sec
(
&
l_time3
,
seconds
,
microseconds
);
if
(
!
is_time
)
{
tmp_format
=
&
t_datetime_frm
(
thd
,
DATETIME_FORMAT_TYPE
).
datetime_format
;
get_date_from_daynr
(
days
,
&
l_time3
.
year
,
&
l_time3
.
month
,
&
l_time3
.
day
);
if
(
l_time3
.
day
&&
make_datetime
(
str
,
&
l_time3
,
l_time1
.
second_part
||
l_time2
.
second_part
?
DATE_TIME_MICROSECOND
:
DATE_TIME
))
make_datetime
(
str
,
&
l_time3
,
1
,
l_time1
.
second_part
||
l_time2
.
second_part
,
tmp_format
->
format
,
tmp_format
->
format_length
,
1
))
return
str
;
goto
null_date
;
}
tmp_format
=
&
t_datetime_frm
(
thd
,
TIME_FORMAT_TYPE
).
datetime_format
;
l_time3
.
hour
+=
days
*
24
;
if
(
make_datetime
(
str
,
&
l_time3
,
l_time1
.
second_part
||
l_time2
.
second_part
?
TIME_MICROSECOND
:
TIME_ONLY
))
if
(
make_datetime
(
str
,
&
l_time3
,
0
,
l_time1
.
second_part
||
l_time2
.
second_part
,
tmp_format
->
format
,
tmp_format
->
format_length
,
1
))
return
str
;
null_date:
...
...
@@ -1755,6 +2054,7 @@ String *Item_func_timediff::val_str(String *str)
long
days
;
int
l_sign
=
1
;
TIME
l_time1
,
l_time2
,
l_time3
;
DATETIME_FORMAT
*
tmp_format
;
null_value
=
0
;
if
(
args
[
0
]
->
get_time
(
&
l_time1
)
||
...
...
@@ -1800,9 +2100,11 @@ String *Item_func_timediff::val_str(String *str)
l_time3
.
neg
=
l_time3
.
neg
?
0
:
1
;
calc_time_from_sec
(
&
l_time3
,
seconds
,
microseconds
);
if
(
make_datetime
(
str
,
&
l_time3
,
l_time1
.
second_part
||
l_time2
.
second_part
?
TIME_MICROSECOND
:
TIME_ONLY
))
tmp_format
=
&
t_datetime_frm
(
thd
,
TIME_FORMAT_TYPE
).
datetime_format
;
if
(
make_datetime
(
str
,
&
l_time3
,
0
,
l_time1
.
second_part
||
l_time2
.
second_part
,
tmp_format
->
format
,
tmp_format
->
format_length
,
1
))
return
str
;
null_date:
...
...
@@ -1819,6 +2121,7 @@ String *Item_func_timediff::val_str(String *str)
String
*
Item_func_maketime
::
val_str
(
String
*
str
)
{
TIME
ltime
;
DATETIME_FORMAT
*
tmp_format
;
long
hour
=
args
[
0
]
->
val_int
();
long
minute
=
args
[
1
]
->
val_int
();
...
...
@@ -1840,7 +2143,9 @@ String *Item_func_maketime::val_str(String *str)
ltime
.
hour
=
(
ulong
)
hour
;
ltime
.
minute
=
(
ulong
)
minute
;
ltime
.
second
=
(
ulong
)
second
;
if
(
make_datetime
(
str
,
&
ltime
,
TIME_ONLY
))
tmp_format
=
&
t_datetime_frm
(
thd
,
TIME_FORMAT_TYPE
).
datetime_format
;
if
(
make_datetime
(
str
,
&
ltime
,
0
,
0
,
tmp_format
->
format
,
tmp_format
->
format_length
,
1
))
return
str
;
null_date:
...
...
@@ -1860,3 +2165,79 @@ longlong Item_func_microsecond::val_int()
return
ltime
.
second_part
;
return
0
;
}
/*
Array of MySQL date/time/datetime formats
Firts element is date format
Second element is time format
Third element is datetime format
Fourth is format name.
*/
const
char
*
datetime_formats
[
4
][
5
]
=
{
{
"%m.%d.%Y"
,
"%Y-%m-%d"
,
"%Y-%m-%d"
,
"%d.%m.%Y"
,
"%Y%m%d"
},
{
"%h:%i:%s %p"
,
"%H:%i:%s"
,
"%H:%i:%s"
,
"%H.%i.%S"
,
"%H%i%s"
},
{
"%Y-%m-%d-%H.%i.%s"
,
"%Y-%m-%d %H:%i:%s"
,
"%Y-%m-%d %H:%i:%s"
,
"%Y-%m-%d-%H.%i.%s"
,
"%Y%m%d%H%i%s"
},
{
"USA"
,
"JIS"
,
"ISO"
,
"EUR"
,
"INTERNAL"
}
};
/*
Return format string according format name.
If name is unknown, result is ISO format string
*/
String
*
Item_func_get_format
::
val_str
(
String
*
str
)
{
String
*
val
=
args
[
0
]
->
val_str
(
str
);
const
char
*
format_str
=
datetime_formats
[
tm_format
][
ISO_FORMAT
];
if
(
!
args
[
0
]
->
null_value
)
{
const
char
*
val_ptr
=
val
->
ptr
();
uint
val_len
=
val
->
length
();
for
(
int
i
=
0
;
i
<
5
;
i
++
)
{
const
char
*
name_format_str
=
datetime_formats
[
3
][
i
];
uint
format_str_len
=
strlen
(
name_format_str
);
if
(
val_len
==
format_str_len
&&
!
my_strnncoll
(
&
my_charset_latin1
,
(
const
uchar
*
)
val_ptr
,
val_len
,
(
const
uchar
*
)
name_format_str
,
format_str_len
))
{
format_str
=
datetime_formats
[
tm_format
][
i
];
break
;
}
}
}
null_value
=
0
;
str
->
length
(
0
);
str
->
append
(
format_str
);
return
str
;
}
String
*
Item_func_str_to_date
::
val_str
(
String
*
str
)
{
TIME
ltime
;
bzero
((
char
*
)
&
ltime
,
sizeof
(
ltime
));
DATETIME_FORMAT
*
tmp_format
;
String
*
val
=
args
[
0
]
->
val_str
(
str
);
String
*
format
=
args
[
1
]
->
val_str
(
str
);
if
(
args
[
0
]
->
null_value
||
args
[
1
]
->
null_value
||
extract_datetime
(
val
->
ptr
(),
val
->
length
(),
format
->
ptr
(),
val
->
length
(),
&
ltime
))
goto
null_date
;
tmp_format
=
&
t_datetime_frm
(
thd
,
DATETIME_FORMAT_TYPE
).
datetime_format
;
if
(
make_datetime
(
str
,
&
ltime
,
0
,
0
,
tmp_format
->
format
,
tmp_format
->
format_length
,
1
))
return
str
;
null_date:
null_value
=
1
;
return
0
;
}
sql/item_timefunc.h
View file @
b6156392
...
...
@@ -763,3 +763,46 @@ class Item_func_microsecond :public Item_int_func
maybe_null
=
1
;
}
};
enum
datetime_format
{
USA_FORMAT
,
JIS_FORMAT
,
ISO_FORMAT
,
EUR_FORMAT
,
INTERNAL_FORMAT
};
enum
datetime_format_types
{
DATE_FORMAT_TYPE
=
0
,
TIME_FORMAT_TYPE
,
DATETIME_FORMAT_TYPE
};
class
Item_func_get_format
:
public
Item_str_func
{
const
datetime_format_types
tm_format
;
public:
Item_func_get_format
(
datetime_format_types
type_arg1
,
Item
*
a
)
:
Item_str_func
(
a
),
tm_format
(
type_arg1
)
{}
String
*
val_str
(
String
*
str
);
const
char
*
func_name
()
const
{
return
"get_format"
;
}
void
fix_length_and_dec
()
{
decimals
=
0
;
max_length
=
17
*
MY_CHARSET_BIN_MB_MAXLEN
;
}
};
class
Item_func_str_to_date
:
public
Item_str_func
{
public:
Item_func_str_to_date
(
Item
*
a
,
Item
*
b
)
:
Item_str_func
(
a
,
b
)
{}
String
*
val_str
(
String
*
str
);
const
char
*
func_name
()
const
{
return
"str_to_date"
;
}
void
fix_length_and_dec
()
{
decimals
=
0
;
max_length
=
29
*
MY_CHARSET_BIN_MB_MAXLEN
;
}
};
sql/lex.h
View file @
b6156392
...
...
@@ -176,6 +176,7 @@ static SYMBOL symbols[] = {
{
"FUNCTION"
,
SYM
(
UDF_SYM
),
0
,
0
},
{
"GEOMETRY"
,
SYM
(
GEOMETRY_SYM
),
0
,
0
},
{
"GEOMETRYCOLLECTION"
,
SYM
(
GEOMETRYCOLLECTION
),
0
,
0
},
{
"GET_FORMAT"
,
SYM
(
GET_FORMAT
),
0
,
0
},
{
"GLOBAL"
,
SYM
(
GLOBAL_SYM
),
0
,
0
},
{
"GRANT"
,
SYM
(
GRANT
),
0
,
0
},
{
"GRANTS"
,
SYM
(
GRANTS
),
0
,
0
},
...
...
@@ -634,6 +635,7 @@ static SYMBOL sql_functions[] = {
{
"STARTPOINT"
,
SYM
(
FUNC_ARG1
),
0
,
CREATE_FUNC
(
create_func_startpoint
)},
{
"STD"
,
SYM
(
STD_SYM
),
0
,
0
},
{
"STDDEV"
,
SYM
(
STD_SYM
),
0
,
0
},
{
"STR_TO_DATE"
,
SYM
(
FUNC_ARG2
),
0
,
CREATE_FUNC
(
create_func_str_to_date
)},
{
"STRCMP"
,
SYM
(
FUNC_ARG2
),
0
,
CREATE_FUNC
(
create_func_strcmp
)},
{
"SUBSTR"
,
SYM
(
SUBSTRING
),
0
,
0
},
{
"SUBSTRING"
,
SYM
(
SUBSTRING
),
0
,
0
},
...
...
sql/mysql_priv.h
View file @
b6156392
...
...
@@ -800,6 +800,13 @@ extern struct system_variables global_system_variables;
extern
struct
system_variables
max_system_variables
;
extern
struct
rand_struct
sql_rand
;
#define g_datetime_frm(a) (global_system_variables.datetime_formats[(a)])
#define t_datetime_frm(a, b) ((a)->variables.datetime_formats[(b)])
extern
const
char
*
datetime_formats
[
4
][
5
];
extern
const
char
*
opt_datetime_format_names
[
3
];
extern
const
char
*
opt_datetime_formats
[
3
];
/* optional things, have_* variables */
extern
SHOW_COMP_OPTION
have_isam
,
have_innodb
,
have_berkeley_db
;
...
...
@@ -863,14 +870,24 @@ void get_date_from_daynr(long daynr,uint *year, uint *month,
uint
*
day
);
void
init_time
(
void
);
long
my_gmt_sec
(
TIME
*
,
long
*
current_timezone
);
time_t
str_to_timestamp
(
const
char
*
str
,
uint
length
);
bool
str_to_time
(
const
char
*
str
,
uint
length
,
TIME
*
l_time
);
longlong
str_to_datetime
(
const
char
*
str
,
uint
length
,
bool
fuzzy_date
);
time_t
str_to_timestamp
(
const
char
*
str
,
uint
length
,
THD
*
thd
);
bool
str_to_time
(
const
char
*
str
,
uint
length
,
TIME
*
l_time
,
THD
*
thd
);
longlong
str_to_datetime
(
const
char
*
str
,
uint
length
,
bool
fuzzy_date
,
THD
*
thd
);
timestamp_type
str_to_TIME
(
const
char
*
str
,
uint
length
,
TIME
*
l_time
,
bool
fuzzy_date
);
bool
fuzzy_date
,
THD
*
thd
);
void
localtime_to_TIME
(
TIME
*
to
,
struct
tm
*
from
);
void
calc_time_from_sec
(
TIME
*
to
,
long
seconds
,
long
microseconds
);
extern
DATETIME_FORMAT
*
make_format
(
DATETIME_FORMAT
*
datetime_format
,
datetime_format_types
format_type
,
const
char
*
format_str
,
uint
format_length
,
bool
is_alloc
);
extern
String
*
make_datetime
(
String
*
str
,
TIME
*
l_time
,
const
bool
is_time_only
,
const
bool
add_second_frac
,
const
char
*
ptr
,
uint
format_length
,
bool
set_len_to_zero
);
int
test_if_number
(
char
*
str
,
int
*
res
,
bool
allow_wildcards
);
void
change_byte
(
byte
*
,
uint
,
char
,
char
);
extern
"C"
void
unireg_abort
(
int
exit_code
);
...
...
sql/mysqld.cc
View file @
b6156392
...
...
@@ -310,6 +310,12 @@ char* log_error_file_ptr= log_error_file;
char
mysql_real_data_home
[
FN_REFLEN
],
language
[
LIBLEN
],
reg_ext
[
FN_EXTLEN
],
mysql_charsets_dir
[
FN_REFLEN
],
max_sort_char
,
*
mysqld_user
,
*
mysqld_chroot
,
*
opt_init_file
;
const
char
*
opt_datetime_formats
[
3
];
const
char
*
opt_datetime_format_names
[
3
]
=
{
"date_format"
,
"time_format"
,
"datetime_format"
};
char
*
language_ptr
,
*
default_collation_name
,
*
default_character_set_name
;
char
mysql_data_home_buff
[
2
],
*
mysql_data_home
=
mysql_real_data_home
;
char
server_version
[
SERVER_VERSION_LENGTH
]
=
MYSQL_SERVER_VERSION
;
...
...
@@ -893,6 +899,9 @@ void clean_up(bool print_message)
#ifdef USE_RAID
end_raid
();
#endif
g_datetime_frm
(
DATE_FORMAT_TYPE
).
clean
();
g_datetime_frm
(
TIME_FORMAT_TYPE
).
clean
();
g_datetime_frm
(
DATETIME_FORMAT_TYPE
).
clean
();
if
(
defaults_argv
)
free_defaults
(
defaults_argv
);
free_tmpdir
(
&
mysql_tmpdir_list
);
...
...
@@ -1976,6 +1985,36 @@ bool open_log(MYSQL_LOG *log, const char *hostname,
}
int
init_global_datetime_format
(
datetime_format_types
format_type
,
bool
is_alloc
)
{
const
char
*
format_str
=
opt_datetime_formats
[
format_type
];
uint
format_length
=
0
;
DATETIME_FORMAT
*
tmp_format
=
&
g_datetime_frm
(
format_type
).
datetime_format
;
if
(
format_str
)
{
format_str
=
opt_datetime_formats
[
format_type
];
format_length
=
strlen
(
format_str
);
}
else
{
format_str
=
datetime_formats
[
format_type
][
ISO_FORMAT
];
format_length
=
strlen
(
datetime_formats
[
format_type
][
ISO_FORMAT
]);
opt_datetime_formats
[
format_type
]
=
format_str
;
}
if
(
make_format
(
tmp_format
,
format_type
,
format_str
,
format_length
,
is_alloc
))
{
g_datetime_frm
(
format_type
).
name
=
opt_datetime_format_names
[
format_type
];
g_datetime_frm
(
format_type
).
name_length
=
strlen
(
opt_datetime_format_names
[
format_type
]);
g_datetime_frm
(
format_type
).
format_type
=
format_type
;
return
0
;
}
return
1
;
}
static
int
init_common_variables
(
const
char
*
conf_file_name
,
int
argc
,
char
**
argv
,
const
char
**
groups
)
{
...
...
@@ -2089,6 +2128,11 @@ static int init_common_variables(const char *conf_file_name, int argc,
global_system_variables
.
character_set_client
=
default_charset_info
;
global_system_variables
.
collation_connection
=
default_charset_info
;
if
(
init_global_datetime_format
(
DATE_FORMAT_TYPE
,
1
)
||
init_global_datetime_format
(
TIME_FORMAT_TYPE
,
1
)
||
init_global_datetime_format
(
DATETIME_FORMAT_TYPE
,
1
))
return
1
;
if
(
use_temp_pool
&&
bitmap_init
(
&
temp_pool
,
1024
,
1
))
return
1
;
return
0
;
...
...
@@ -3533,7 +3577,10 @@ enum options
OPT_DEFAULT_WEEK_FORMAT
,
OPT_GROUP_CONCAT_MAX_LEN
,
OPT_DEFAULT_COLLATION
,
OPT_SECURE_AUTH
OPT_SECURE_AUTH
,
OPT_DATE_FORMAT
,
OPT_TIME_FORMAT
,
OPT_DATETIME_FORMAT
};
...
...
@@ -4444,6 +4491,21 @@ The minimum value for this variable is 4096.",
(
gptr
*
)
&
global_system_variables
.
default_week_format
,
(
gptr
*
)
&
max_system_variables
.
default_week_format
,
0
,
GET_ULONG
,
REQUIRED_ARG
,
0
,
0
,
3L
,
0
,
1
,
0
},
{
"date-format"
,
OPT_DATE_FORMAT
,
"The DATE format."
,
(
gptr
*
)
&
opt_datetime_formats
[
DATE_FORMAT_TYPE
],
(
gptr
*
)
&
opt_datetime_formats
[
DATE_FORMAT_TYPE
],
0
,
GET_STR
,
REQUIRED_ARG
,
0
,
0
,
0
,
0
,
0
,
0
},
{
"datetime-format"
,
OPT_DATETIME_FORMAT
,
"The DATETIME/TIMESTAMP format."
,
(
gptr
*
)
&
opt_datetime_formats
[
DATETIME_FORMAT_TYPE
],
(
gptr
*
)
&
opt_datetime_formats
[
DATETIME_FORMAT_TYPE
],
0
,
GET_STR
,
REQUIRED_ARG
,
0
,
0
,
0
,
0
,
0
,
0
},
{
"time-format"
,
OPT_TIME_FORMAT
,
"The TIME format."
,
(
gptr
*
)
&
opt_datetime_formats
[
TIME_FORMAT_TYPE
],
(
gptr
*
)
&
opt_datetime_formats
[
TIME_FORMAT_TYPE
],
0
,
GET_STR
,
REQUIRED_ARG
,
0
,
0
,
0
,
0
,
0
,
0
},
{
0
,
0
,
0
,
0
,
0
,
0
,
GET_NO_ARG
,
NO_ARG
,
0
,
0
,
0
,
0
,
0
,
0
}
};
...
...
@@ -4821,6 +4883,10 @@ static void mysql_init_variables(void)
max_system_variables
.
max_join_size
=
(
ulonglong
)
HA_POS_ERROR
;
global_system_variables
.
old_passwords
=
0
;
init_global_datetime_format
(
DATE_FORMAT_TYPE
,
0
);
init_global_datetime_format
(
TIME_FORMAT_TYPE
,
0
);
init_global_datetime_format
(
DATETIME_FORMAT_TYPE
,
0
);
/* Variables that depends on compile options */
#ifndef DBUG_OFF
default_dbug_option
=
IF_WIN
(
"d:t:i:O,
\\
mysqld.trace"
,
...
...
sql/protocol.cc
View file @
b6156392
...
...
@@ -831,17 +831,12 @@ bool Protocol_simple::store(TIME *tm)
field_pos
++
;
#endif
char
buff
[
40
];
uint
length
;
length
=
my_sprintf
(
buff
,(
buff
,
"%04d-%02d-%02d %02d:%02d:%02d"
,
(
int
)
tm
->
year
,
(
int
)
tm
->
month
,
(
int
)
tm
->
day
,
(
int
)
tm
->
hour
,
(
int
)
tm
->
minute
,
(
int
)
tm
->
second
));
if
(
tm
->
second_part
)
length
+=
my_sprintf
(
buff
+
length
,(
buff
+
length
,
".%06d"
,
(
int
)
tm
->
second_part
));
return
net_store_data
((
char
*
)
buff
,
length
);
String
tmp
((
char
*
)
buff
,
sizeof
(
buff
),
&
my_charset_bin
);
DATETIME_FORMAT
*
tmp_format
=
(
&
t_datetime_frm
(
current_thd
,
DATETIME_FORMAT_TYPE
).
datetime_format
);
make_datetime
(
&
tmp
,
tm
,
1
,
tm
->
second_part
,
tmp_format
->
format
,
tmp_format
->
format_length
,
1
);
return
net_store_data
((
char
*
)
tmp
.
ptr
(),
tmp
.
length
());
}
...
...
@@ -853,12 +848,12 @@ bool Protocol_simple::store_date(TIME *tm)
field_pos
++
;
#endif
char
buff
[
40
];
uint
length
;
length
=
my_sprintf
(
buff
,(
buff
,
"%04d-%02d-%02d"
,
(
int
)
tm
->
year
,
(
int
)
tm
->
month
,
(
int
)
tm
->
day
)
);
return
net_store_data
((
char
*
)
buff
,
length
);
String
tmp
((
char
*
)
buff
,
sizeof
(
buff
),
&
my_charset_bin
)
;
DATETIME_FORMAT
*
tmp_format
=
(
&
t_datetime_frm
(
current_thd
,
DATE_FORMAT_TYPE
).
datetime_format
);
make_datetime
(
&
tmp
,
tm
,
1
,
0
,
tmp_format
->
format
,
tmp_format
->
format_length
,
1
);
return
net_store_data
((
char
*
)
tmp
.
ptr
(),
tmp
.
length
()
);
}
...
...
@@ -876,16 +871,14 @@ bool Protocol_simple::store_time(TIME *tm)
field_pos
++
;
#endif
char
buff
[
40
];
uint
length
;
String
tmp
((
char
*
)
buff
,
sizeof
(
buff
),
&
my_charset_bin
);
DATETIME_FORMAT
*
tmp_format
=
(
&
t_datetime_frm
(
current_thd
,
TIME_FORMAT_TYPE
).
datetime_format
);
uint
day
=
(
tm
->
year
||
tm
->
month
)
?
0
:
tm
->
day
;
length
=
my_sprintf
(
buff
,(
buff
,
"%s%02ld:%02d:%02d"
,
tm
->
neg
?
"-"
:
""
,
(
long
)
day
*
24L
+
(
long
)
tm
->
hour
,
(
int
)
tm
->
minute
,
(
int
)
tm
->
second
));
if
(
tm
->
second_part
)
length
+=
my_sprintf
(
buff
+
length
,(
buff
+
length
,
".%06d"
,
(
int
)
tm
->
second_part
));
return
net_store_data
((
char
*
)
buff
,
length
);
tm
->
hour
=
(
long
)
day
*
24L
+
(
long
)
tm
->
hour
;
make_datetime
(
&
tmp
,
tm
,
0
,
tm
->
second_part
,
tmp_format
->
format
,
tmp_format
->
format_length
,
1
);
return
net_store_data
((
char
*
)
tmp
.
ptr
(),
tmp
.
length
());
}
...
...
sql/set_var.cc
View file @
b6156392
...
...
@@ -383,6 +383,9 @@ sys_var *sys_variables[]=
&
sys_collation_connection
,
&
sys_concurrent_insert
,
&
sys_connect_timeout
,
&
g_datetime_frm
(
DATE_FORMAT_TYPE
),
&
g_datetime_frm
(
DATETIME_FORMAT_TYPE
),
&
g_datetime_frm
(
TIME_FORMAT_TYPE
),
&
sys_default_week_format
,
&
sys_delay_key_write
,
&
sys_delayed_insert_limit
,
...
...
@@ -512,6 +515,8 @@ struct show_var_st init_vars[]= {
{
sys_concurrent_insert
.
name
,(
char
*
)
&
sys_concurrent_insert
,
SHOW_SYS
},
{
sys_connect_timeout
.
name
,
(
char
*
)
&
sys_connect_timeout
,
SHOW_SYS
},
{
"datadir"
,
mysql_real_data_home
,
SHOW_CHAR
},
{
"date_format"
,
(
char
*
)
&
g_datetime_frm
(
DATE_FORMAT_TYPE
),
SHOW_SYS
},
{
"datetime_format"
,
(
char
*
)
&
g_datetime_frm
(
DATETIME_FORMAT_TYPE
),
SHOW_SYS
},
{
"default_week_format"
,
(
char
*
)
&
sys_default_week_format
,
SHOW_SYS
},
{
sys_delay_key_write
.
name
,
(
char
*
)
&
sys_delay_key_write
,
SHOW_SYS
},
{
sys_delayed_insert_limit
.
name
,
(
char
*
)
&
sys_delayed_insert_limit
,
SHOW_SYS
},
...
...
@@ -661,6 +666,7 @@ struct show_var_st init_vars[]= {
#endif
{
"thread_stack"
,
(
char
*
)
&
thread_stack
,
SHOW_LONG
},
{
sys_tx_isolation
.
name
,
(
char
*
)
&
sys_tx_isolation
,
SHOW_SYS
},
{
"time_format"
,
(
char
*
)
&
g_datetime_frm
(
TIME_FORMAT_TYPE
),
SHOW_SYS
},
#ifdef HAVE_TZNAME
{
"timezone"
,
time_zone
,
SHOW_CHAR
},
#endif
...
...
@@ -671,9 +677,75 @@ struct show_var_st init_vars[]= {
{
NullS
,
NullS
,
SHOW_LONG
}
};
/*
Functions to check and update variables
*/
char
*
update_datetime_format
(
THD
*
thd
,
enum
enum_var_type
type
,
enum
datetime_format_types
format_type
,
DATETIME_FORMAT
*
tmp_format
)
{
char
*
old_value
;
if
(
type
==
OPT_GLOBAL
)
{
pthread_mutex_lock
(
&
LOCK_global_system_variables
);
old_value
=
g_datetime_frm
(
format_type
).
datetime_format
.
format
;
g_datetime_frm
(
format_type
).
datetime_format
=
*
tmp_format
;
pthread_mutex_unlock
(
&
LOCK_global_system_variables
);
}
else
{
old_value
=
t_datetime_frm
(
thd
,
format_type
).
datetime_format
.
format
;
t_datetime_frm
(
thd
,
format_type
).
datetime_format
=
*
tmp_format
;
}
return
old_value
;
}
bool
sys_var_datetime_format
::
update
(
THD
*
thd
,
set_var
*
var
)
{
DATETIME_FORMAT
tmp_format
;
char
*
old_value
;
uint
new_length
;
if
((
new_length
=
var
->
value
->
str_value
.
length
()))
{
if
(
!
make_format
(
&
tmp_format
,
format_type
,
var
->
value
->
str_value
.
ptr
(),
new_length
,
1
))
return
1
;
}
old_value
=
update_datetime_format
(
thd
,
var
->
type
,
format_type
,
&
tmp_format
);
my_free
(
old_value
,
MYF
(
MY_ALLOW_ZERO_PTR
));
return
0
;
}
byte
*
sys_var_datetime_format
::
value_ptr
(
THD
*
thd
,
enum_var_type
type
,
LEX_STRING
*
base
)
{
if
(
type
==
OPT_GLOBAL
)
return
(
byte
*
)
g_datetime_frm
(
format_type
).
datetime_format
.
format
;
return
(
byte
*
)
t_datetime_frm
(
thd
,
format_type
).
datetime_format
.
format
;
}
void
sys_var_datetime_format
::
set_default
(
THD
*
thd
,
enum_var_type
type
)
{
DATETIME_FORMAT
tmp_format
;
char
*
old_value
;
uint
new_length
;
if
((
new_length
=
strlen
(
opt_datetime_formats
[
format_type
])))
{
if
(
!
make_format
(
&
tmp_format
,
format_type
,
opt_datetime_formats
[
format_type
],
new_length
,
1
))
return
;
}
old_value
=
update_datetime_format
(
thd
,
type
,
format_type
,
&
tmp_format
);
my_free
(
old_value
,
MYF
(
MY_ALLOW_ZERO_PTR
));
}
/*
The following 3 functions need to be changed in 4.1 when we allow
...
...
sql/set_var.h
View file @
b6156392
...
...
@@ -49,6 +49,8 @@ class sys_var
const
char
*
name
;
sys_after_update_func
after_update
;
sys_var
()
{}
sys_var
(
const
char
*
name_arg
)
:
name
(
name_arg
),
after_update
(
0
)
{}
sys_var
(
const
char
*
name_arg
,
sys_after_update_func
func
)
...
...
@@ -188,6 +190,9 @@ class sys_var_enum :public sys_var
class
sys_var_thd
:
public
sys_var
{
public:
sys_var_thd
()
:
sys_var
()
{}
sys_var_thd
(
const
char
*
name_arg
)
:
sys_var
(
name_arg
)
{}
...
...
@@ -538,6 +543,51 @@ class sys_var_key_buffer_size :public sys_var
};
class
sys_var_datetime_format
:
public
sys_var_thd
{
public:
enum
datetime_format_types
format_type
;
DATETIME_FORMAT
datetime_format
;
sys_var_datetime_format
()
:
sys_var_thd
()
{}
void
clean
()
{
my_free
(
datetime_format
.
format
,
MYF
(
MY_ALLOW_ZERO_PTR
));
datetime_format
.
format
=
0
;
}
/*
It's for copying of global_system_variables structure
in THD constructor.
*/
inline
sys_var_datetime_format
&
operator
=
(
sys_var_datetime_format
&
s
)
{
if
(
&
s
!=
this
)
{
name
=
s
.
name
;
name_length
=
s
.
name_length
;
datetime_format
=
s
.
datetime_format
;
datetime_format
.
format
=
(
my_strdup_with_length
(
s
.
datetime_format
.
format
,
s
.
datetime_format
.
format_length
,
MYF
(
0
)));
format_type
=
s
.
format_type
;
}
return
*
this
;
}
SHOW_TYPE
type
()
{
return
SHOW_CHAR
;
}
bool
check_update_type
(
Item_result
type
)
{
return
type
!=
STRING_RESULT
;
/* Only accept strings */
}
bool
check_default
(
enum_var_type
type
)
{
return
0
;
}
bool
update
(
THD
*
thd
,
set_var
*
var
);
byte
*
value_ptr
(
THD
*
thd
,
enum_var_type
type
,
LEX_STRING
*
base
);
void
set_default
(
THD
*
thd
,
enum_var_type
type
);
};
/* Variable that you can only read from */
class
sys_var_readonly
:
public
sys_var
...
...
sql/sql_class.cc
View file @
b6156392
...
...
@@ -274,6 +274,9 @@ void THD::cleanup(void)
close_thread_tables
(
this
);
}
close_temporary_tables
(
this
);
variables
.
datetime_formats
[
DATE_FORMAT_TYPE
].
clean
();
variables
.
datetime_formats
[
TIME_FORMAT_TYPE
].
clean
();
variables
.
datetime_formats
[
DATETIME_FORMAT_TYPE
].
clean
();
delete_dynamic
(
&
user_var_events
);
hash_free
(
&
user_vars
);
if
(
global_read_lock
)
...
...
sql/sql_class.h
View file @
b6156392
...
...
@@ -406,6 +406,7 @@ struct system_variables
CHARSET_INFO
*
character_set_client
;
CHARSET_INFO
*
character_set_results
;
CHARSET_INFO
*
collation_connection
;
sys_var_datetime_format
datetime_formats
[
3
];
};
void
free_tmp_table
(
THD
*
thd
,
TABLE
*
entry
);
...
...
sql/sql_yacc.yy
View file @
b6156392
...
...
@@ -79,6 +79,7 @@ inline Item *or_or_concat(THD *thd, Item* A, Item* B)
CHARSET_INFO *charset;
thr_lock_type lock_type;
interval_type interval;
datetime_format_types datetime_format_type;
st_select_lex *select_lex;
chooser_compare_func_creator boolfunc2creator;
}
...
...
@@ -477,6 +478,7 @@ bool my_yyoverflow(short **a, YYSTYPE **b,int *yystacksize);
%token GEOMETRYCOLLECTION
%token GROUP_CONCAT_SYM
%token GROUP_UNIQUE_USERS
%token GET_FORMAT
%token HOUR_MICROSECOND_SYM
%token HOUR_MINUTE_SYM
%token HOUR_SECOND_SYM
...
...
@@ -639,6 +641,7 @@ bool my_yyoverflow(short **a, YYSTYPE **b,int *yystacksize);
UDF_CHAR_FUNC UDF_FLOAT_FUNC UDF_INT_FUNC
UDA_CHAR_SUM UDA_FLOAT_SUM UDA_INT_SUM
%type <datetime_format_type> datetime_format_type;
%type <interval> interval
%type <db_type> table_types
...
...
@@ -2529,6 +2532,8 @@ simple_expr:
{ $$= new Item_func_spatial_collection(* $3,
Geometry::wkbGeometryCollection,
Geometry::wkbPoint); }
| GET_FORMAT '(' datetime_format_type ',' expr ')'
{ $$= new Item_func_get_format($3, $5); }
| HOUR_SYM '(' expr ')'
{ $$= new Item_func_hour($3); }
| IF '(' expr ',' expr ',' expr ')'
...
...
@@ -3133,6 +3138,11 @@ interval:
| YEAR_MONTH_SYM { $$=INTERVAL_YEAR_MONTH; }
| YEAR_SYM { $$=INTERVAL_YEAR; };
datetime_format_type:
DATE_SYM {$$=DATE_FORMAT_TYPE;}
| TIME_SYM {$$=TIME_FORMAT_TYPE;}
| DATETIME {$$=DATETIME_FORMAT_TYPE;};
table_alias:
/* empty */
| AS
...
...
@@ -4479,6 +4489,7 @@ keyword:
| FLUSH_SYM {}
| GEOMETRY_SYM {}
| GEOMETRYCOLLECTION {}
| GET_FORMAT {}
| GRANTS {}
| GLOBAL_SYM {}
| HANDLER_SYM {}
...
...
sql/structs.h
View file @
b6156392
...
...
@@ -24,6 +24,11 @@ typedef struct st_date_format { /* How to print date */
uint
pos
[
6
];
/* Positions to YY.MM.DD HH:MM:SS */
}
DATE_FORMAT
;
typedef
struct
st_datetime_format
{
byte
dt_pos
[
8
];
char
*
format
;
uint
format_length
;
}
DATETIME_FORMAT
;
typedef
struct
st_keyfile_info
{
/* used with ha_info() */
byte
ref
[
MAX_REFLENGTH
];
/* Pointer to current row */
...
...
@@ -110,8 +115,8 @@ typedef struct st_read_record { /* Parameter to read_record */
bool
print_error
,
ignore_not_found_rows
;
}
READ_RECORD
;
enum
timestamp_type
{
TIMESTAMP_NONE
,
TIMESTAMP_DATE
,
TIMESTAMP_FULL
,
TIMESTAMP_TIME
};
enum
timestamp_type
{
TIMESTAMP_NONE
,
WRONG_TIMESTAMP_FULL
,
TIMESTAMP_DATE
,
TIMESTAMP_FULL
,
TIMESTAMP_TIME
};
typedef
struct
st_time
{
uint
year
,
month
,
day
,
hour
,
minute
,
second
;
...
...
sql/time.cc
View file @
b6156392
...
...
@@ -27,6 +27,10 @@ uchar *days_in_month= (uchar*) "\037\034\037\036\037\036\037\037\036\037\036\037
/* Init some variabels needed when using my_local_time */
/* Currently only my_time_zone is inited */
bool
parse_datetime_formats
(
datetime_format_types
format_type
,
const
char
*
format_str
,
uint
format_length
,
byte
*
dt_pos
);
static
long
my_time_zone
=
0
;
void
init_time
(
void
)
...
...
@@ -316,10 +320,12 @@ ulong convert_month_to_period(ulong month)
*/
timestamp_type
str_to_TIME
(
const
char
*
str
,
uint
length
,
TIME
*
l_time
,
bool
fuzzy_date
)
str_to_TIME
(
const
char
*
str
,
uint
length
,
TIME
*
l_time
,
bool
fuzzy_date
,
THD
*
thd
)
{
uint
field_length
,
year_length
,
digits
,
i
,
number_of_fields
,
date
[
7
];
uint
field_length
=
0
,
year_length
=
0
,
digits
,
i
,
number_of_fields
;
uint
date
[
7
],
date_len
[
7
];
uint
not_zero_date
;
bool
is_internal_format
=
0
;
const
char
*
pos
;
const
char
*
end
=
str
+
length
;
bool
found_delimitier
=
0
;
...
...
@@ -336,24 +342,32 @@ str_to_TIME(const char *str, uint length, TIME *l_time,bool fuzzy_date)
(YYYY-MM-DD, YYYYMMDD, YYYYYMMDDHHMMSS)
*/
for
(
pos
=
str
;
pos
!=
end
&&
my_isdigit
(
&
my_charset_latin1
,
*
pos
)
;
pos
++
)
;
/* Check for internal format */
digits
=
(
uint
)
(
pos
-
str
);
if
(
pos
==
end
||
digits
>=
12
)
{
is_internal_format
=
1
;
year_length
=
(
digits
==
4
||
digits
==
8
||
digits
>=
14
)
?
4
:
2
;
field_length
=
year_length
-
1
;
date_len
[
0
]
=
year_length
;
}
not_zero_date
=
0
;
for
(
i
=
0
;
i
<
6
&&
str
!=
end
&&
my_isdigit
(
&
my_charset_latin1
,
*
str
)
;
i
++
)
{
if
(
!
is_internal_format
)
date_len
[
i
]
=
1
;
uint
tmp_value
=
(
uint
)
(
uchar
)
(
*
str
++
-
'0'
);
while
(
str
!=
end
&&
my_isdigit
(
&
my_charset_latin1
,
str
[
0
])
&&
field_length
--
)
while
(
str
!=
end
&&
my_isdigit
(
&
my_charset_latin1
,
str
[
0
])
&&
(
is_internal_format
&&
field_length
--
||
!
is_internal_format
)
)
{
tmp_value
=
tmp_value
*
10
+
(
uint
)
(
uchar
)
(
*
str
-
'0'
);
str
++
;
if
(
!
is_internal_format
)
date_len
[
i
]
+=
1
;
}
if
(
found_delimitier
&&
(
int
)
field_length
<
0
)
{
/* The number can't match any valid date or datetime string */
if
(
i
==
2
&&
*
str
==
'.'
)
DBUG_RETURN
(
TIMESTAMP_NONE
);
}
date
[
i
]
=
tmp_value
;
not_zero_date
|=
tmp_value
;
if
(
i
==
2
&&
str
!=
end
&&
*
str
==
'T'
)
...
...
@@ -371,6 +385,7 @@ str_to_TIME(const char *str, uint length, TIME *l_time,bool fuzzy_date)
found_delimitier
=
1
;
// Should be a 'normal' date
}
}
if
(
is_internal_format
)
field_length
=
1
;
// Rest fields can only be 2
}
/* Handle second fractions */
...
...
@@ -389,14 +404,69 @@ str_to_TIME(const char *str, uint length, TIME *l_time,bool fuzzy_date)
else
date
[
6
]
=
0
;
if
(
year_length
==
2
&&
i
>=
2
&&
(
date
[
1
]
||
date
[
2
]))
date
[
0
]
+=
(
date
[
0
]
<
YY_PART_YEAR
?
2000
:
1900
);
while
(
str
!=
end
&&
(
my_ispunct
(
&
my_charset_latin1
,
*
str
)
||
my_isspace
(
&
my_charset_latin1
,
*
str
)))
str
++
;
uint
add_hours
=
0
;
if
(
!
my_strnncoll
(
&
my_charset_latin1
,
(
const
uchar
*
)
str
,
2
,
(
const
uchar
*
)
"PM"
,
2
))
add_hours
=
12
;
number_of_fields
=
i
;
while
(
i
<
6
)
date
[
i
++
]
=
0
;
if
(
number_of_fields
<
3
||
date
[
1
]
>
12
||
date
[
2
]
>
31
||
date
[
3
]
>
23
||
date
[
4
]
>
59
||
date
[
5
]
>
59
||
(
!
fuzzy_date
&&
(
date
[
1
]
==
0
||
date
[
2
]
==
0
)))
if
(
!
is_internal_format
)
{
byte
*
frm_pos
;
if
(
number_of_fields
<=
3
)
{
frm_pos
=
t_datetime_frm
(
thd
,
DATE_FORMAT_TYPE
).
datetime_format
.
dt_pos
;
l_time
->
hour
=
0
;
l_time
->
minute
=
0
;
l_time
->
second
=
0
;
}
else
{
frm_pos
=
t_datetime_frm
(
thd
,
DATETIME_FORMAT_TYPE
).
datetime_format
.
dt_pos
;
l_time
->
hour
=
date
[(
int
)
frm_pos
[
3
]];
l_time
->
minute
=
date
[(
int
)
frm_pos
[
4
]];
l_time
->
second
=
date
[(
int
)
frm_pos
[
5
]];
if
(
frm_pos
[
6
]
==
1
)
{
if
(
l_time
->
hour
>
12
)
DBUG_RETURN
(
WRONG_TIMESTAMP_FULL
);
l_time
->
hour
=
l_time
->
hour
%
12
+
add_hours
;
}
}
l_time
->
year
=
date
[(
int
)
frm_pos
[
0
]];
l_time
->
month
=
date
[(
int
)
frm_pos
[
1
]];
l_time
->
day
=
date
[(
int
)
frm_pos
[
2
]];
year_length
=
date_len
[(
int
)
frm_pos
[
0
]];
}
else
{
l_time
->
year
=
date
[
0
];
l_time
->
month
=
date
[
1
];
l_time
->
day
=
date
[
2
];
l_time
->
hour
=
date
[
3
];
l_time
->
minute
=
date
[
4
];
l_time
->
second
=
date
[
5
];
}
l_time
->
second_part
=
date
[
6
];
l_time
->
neg
=
0
;
if
(
year_length
==
2
&&
i
>=
2
&&
(
l_time
->
month
||
l_time
->
day
))
l_time
->
year
+=
(
l_time
->
year
<
YY_PART_YEAR
?
2000
:
1900
);
if
(
number_of_fields
<
3
||
l_time
->
month
>
12
||
l_time
->
day
>
31
||
l_time
->
hour
>
23
||
l_time
->
minute
>
59
||
l_time
->
second
>
59
||
(
!
fuzzy_date
&&
(
l_time
->
month
==
0
||
l_time
->
day
==
0
)))
{
/* Only give warning for a zero date if there is some garbage after */
if
(
!
not_zero_date
)
// If zero date
...
...
@@ -411,53 +481,46 @@ str_to_TIME(const char *str, uint length, TIME *l_time,bool fuzzy_date)
}
}
if
(
not_zero_date
)
current_
thd
->
cuted_fields
++
;
DBUG_RETURN
(
TIMESTAMP_NONE
);
thd
->
cuted_fields
++
;
DBUG_RETURN
(
WRONG_TIMESTAMP_FULL
);
}
if
(
str
!=
end
&&
current_
thd
->
count_cuted_fields
)
if
(
str
!=
end
&&
thd
->
count_cuted_fields
)
{
for
(;
str
!=
end
;
str
++
)
{
if
(
!
my_isspace
(
&
my_charset_latin1
,
*
str
))
{
current_
thd
->
cuted_fields
++
;
thd
->
cuted_fields
++
;
break
;
}
}
}
l_time
->
year
=
date
[
0
];
l_time
->
month
=
date
[
1
];
l_time
->
day
=
date
[
2
];
l_time
->
hour
=
date
[
3
];
l_time
->
minute
=
date
[
4
];
l_time
->
second
=
date
[
5
];
l_time
->
second_part
=
date
[
6
];
l_time
->
neg
=
0
;
DBUG_RETURN
(
l_time
->
time_type
=
(
number_of_fields
<=
3
?
TIMESTAMP_DATE
:
TIMESTAMP_FULL
));
}
time_t
str_to_timestamp
(
const
char
*
str
,
uint
length
)
time_t
str_to_timestamp
(
const
char
*
str
,
uint
length
,
THD
*
thd
)
{
TIME
l_time
;
long
not_used
;
if
(
str_to_TIME
(
str
,
length
,
&
l_time
,
0
)
==
TIMESTAMP_NONE
)
if
(
str_to_TIME
(
str
,
length
,
&
l_time
,
0
,
thd
)
<=
WRONG_TIMESTAMP_FULL
)
return
(
0
);
if
(
l_time
.
year
>=
TIMESTAMP_MAX_YEAR
||
l_time
.
year
<
1900
+
YY_PART_YEAR
)
{
current_
thd
->
cuted_fields
++
;
thd
->
cuted_fields
++
;
return
(
0
);
}
return
(
my_gmt_sec
(
&
l_time
,
&
not_used
));
}
longlong
str_to_datetime
(
const
char
*
str
,
uint
length
,
bool
fuzzy_date
)
longlong
str_to_datetime
(
const
char
*
str
,
uint
length
,
bool
fuzzy_date
,
THD
*
thd
)
{
TIME
l_time
;
if
(
str_to_TIME
(
str
,
length
,
&
l_time
,
fuzzy_date
)
==
TIMESTAMP_NONE
)
if
(
str_to_TIME
(
str
,
length
,
&
l_time
,
fuzzy_date
,
thd
)
<=
WRONG_TIMESTAMP_FULL
)
return
(
0
);
return
(
longlong
)
(
l_time
.
year
*
LL
(
10000000000
)
+
l_time
.
month
*
LL
(
100000000
)
+
...
...
@@ -484,12 +547,13 @@ longlong str_to_datetime(const char *str,uint length,bool fuzzy_date)
1 error
*/
bool
str_to_time
(
const
char
*
str
,
uint
length
,
TIME
*
l_time
)
bool
str_to_time
(
const
char
*
str
,
uint
length
,
TIME
*
l_time
,
THD
*
thd
)
{
long
date
[
5
],
value
;
const
char
*
end
=
str
+
length
;
bool
found_days
,
found_hours
;
uint
state
;
byte
*
frm_pos
=
t_datetime_frm
(
thd
,
TIME_FORMAT_TYPE
).
datetime_format
.
dt_pos
;
l_time
->
neg
=
0
;
for
(;
str
!=
end
&&
...
...
@@ -507,8 +571,11 @@ bool str_to_time(const char *str,uint length,TIME *l_time)
/* Check first if this is a full TIMESTAMP */
if
(
length
>=
12
)
{
// Probably full timestamp
if
(
str_to_TIME
(
str
,
length
,
l_time
,
1
)
==
TIMESTAMP_FULL
)
return
0
;
// Was an ok timestamp
enum
timestamp_type
tres
=
str_to_TIME
(
str
,
length
,
l_time
,
1
,
thd
);
if
(
tres
==
TIMESTAMP_FULL
)
return
0
;
else
if
(
tres
==
WRONG_TIMESTAMP_FULL
)
return
1
;
}
/* Not a timestamp. Try to get this as a DAYS_TO_SECOND string */
...
...
@@ -533,7 +600,7 @@ bool str_to_time(const char *str,uint length,TIME *l_time)
found_days
=
1
;
str
++
;
// Skip space;
}
else
if
((
end
-
str
)
>
1
&&
*
str
==
':'
&&
else
if
((
end
-
str
)
>
1
&&
*
str
==
frm_pos
[
7
]
&&
my_isdigit
(
&
my_charset_latin1
,
str
[
1
]))
{
date
[
0
]
=
0
;
// Assume we found hours
...
...
@@ -559,7 +626,7 @@ bool str_to_time(const char *str,uint length,TIME *l_time)
for
(
value
=
0
;
str
!=
end
&&
my_isdigit
(
&
my_charset_latin1
,
*
str
)
;
str
++
)
value
=
value
*
10L
+
(
long
)
(
*
str
-
'0'
);
date
[
state
++
]
=
value
;
if
(
state
==
4
||
(
end
-
str
)
<
2
||
*
str
!=
':'
||
if
(
state
==
4
||
(
end
-
str
)
<
2
||
*
str
!=
frm_pos
[
7
]
||
!
my_isdigit
(
&
my_charset_latin1
,
str
[
1
]))
break
;
str
++
;
// Skip ':'
...
...
@@ -577,7 +644,6 @@ bool str_to_time(const char *str,uint length,TIME *l_time)
else
bzero
((
char
*
)
(
date
+
state
),
sizeof
(
long
)
*
(
4
-
state
));
}
fractional:
/* Get fractional second part */
if
((
end
-
str
)
>=
2
&&
*
str
==
'.'
&&
my_isdigit
(
&
my_charset_latin1
,
str
[
1
]))
...
...
@@ -593,6 +659,20 @@ bool str_to_time(const char *str,uint length,TIME *l_time)
else
date
[
4
]
=
0
;
while
(
str
!=
end
&&
!
my_isalpha
(
&
my_charset_latin1
,
*
str
))
str
++
;
if
(
(
end
-
str
)
>=
2
&&
!
my_strnncoll
(
&
my_charset_latin1
,
(
const
uchar
*
)
str
,
2
,
(
const
uchar
*
)
"PM"
,
2
)
&&
frm_pos
[
6
]
==
1
)
{
uint
days_i
=
date
[
1
]
/
24
;
uint
hours_i
=
date
[
1
]
%
24
;
date
[
1
]
=
hours_i
%
12
+
12
+
24
*
days_i
;
}
/* Some simple checks */
if
(
date
[
2
]
>=
60
||
date
[
3
]
>=
60
)
{
...
...
@@ -601,9 +681,9 @@ bool str_to_time(const char *str,uint length,TIME *l_time)
}
l_time
->
month
=
0
;
l_time
->
day
=
date
[
0
];
l_time
->
hour
=
date
[
1
];
l_time
->
minute
=
date
[
2
];
l_time
->
second
=
date
[
3
];
l_time
->
hour
=
date
[
frm_pos
[
3
]
+
1
];
l_time
->
minute
=
date
[
frm_pos
[
4
]
+
1
];
l_time
->
second
=
date
[
frm_pos
[
5
]
+
1
];
l_time
->
second_part
=
date
[
4
];
l_time
->
time_type
=
TIMESTAMP_TIME
;
...
...
@@ -648,3 +728,165 @@ void calc_time_from_sec(TIME *to, long seconds, long microseconds)
to
->
second
=
t_seconds
%
60L
;
to
->
second_part
=
microseconds
;
}
DATETIME_FORMAT
*
make_format
(
DATETIME_FORMAT
*
datetime_format
,
datetime_format_types
format_type
,
const
char
*
format_str
,
uint
format_length
,
bool
is_alloc
)
{
if
(
format_length
&&
!
parse_datetime_formats
(
format_type
,
format_str
,
format_length
,
datetime_format
->
dt_pos
))
{
if
(
is_alloc
)
{
if
(
!
(
datetime_format
->
format
=
my_strdup_with_length
(
format_str
,
format_length
,
MYF
(
0
))))
return
0
;
}
else
datetime_format
->
format
=
(
char
*
)
format_str
;
datetime_format
->
format_length
=
format_length
;
return
datetime_format
;
}
return
0
;
}
bool
parse_datetime_formats
(
datetime_format_types
format_type
,
const
char
*
format_str
,
uint
format_length
,
byte
*
dt_pos
)
{
uint
pos
=
0
;
dt_pos
[
0
]
=
dt_pos
[
1
]
=
dt_pos
[
2
]
=
dt_pos
[
3
]
=
dt_pos
[
4
]
=
dt_pos
[
5
]
=
dt_pos
[
6
]
=
dt_pos
[
7
]
=
-
1
;
const
char
*
ptr
=
format_str
;
const
char
*
end
=
ptr
+
format_length
;
bool
need_p
=
0
;
for
(;
ptr
!=
end
;
ptr
++
)
{
if
(
*
ptr
==
'%'
&&
ptr
+
1
!=
end
)
{
switch
(
*++
ptr
)
{
case
'y'
:
case
'Y'
:
if
(
dt_pos
[
0
]
>
-
1
)
return
1
;
dt_pos
[
0
]
=
pos
;
break
;
case
'c'
:
case
'm'
:
if
(
dt_pos
[
1
]
>
-
1
)
return
1
;
dt_pos
[
1
]
=
pos
;
break
;
case
'd'
:
case
'e'
:
if
(
dt_pos
[
2
]
>
-
1
)
return
1
;
dt_pos
[
2
]
=
pos
;
break
;
case
'H'
:
case
'k'
:
case
'h'
:
case
'I'
:
case
'l'
:
if
(
dt_pos
[
3
]
>
-
1
)
return
1
;
dt_pos
[
3
]
=
pos
;
need_p
=
(
*
ptr
==
'h'
||
*
ptr
==
'l'
||
*
ptr
==
'I'
);
break
;
case
'i'
:
if
(
dt_pos
[
4
]
>
-
1
)
return
1
;
dt_pos
[
4
]
=
pos
;
break
;
case
's'
:
case
'S'
:
if
(
dt_pos
[
5
]
>
-
1
)
return
1
;
dt_pos
[
5
]
=
pos
;
break
;
case
'p'
:
if
(
dt_pos
[
6
]
>
-
1
)
return
1
;
/* %p should be last in format string */
if
(
format_type
==
DATE_FORMAT_TYPE
||
(
pos
!=
6
&&
format_type
==
DATETIME_FORMAT_TYPE
)
||
(
pos
!=
3
&&
format_type
==
TIME_FORMAT_TYPE
))
return
1
;
dt_pos
[
6
]
=
1
;
break
;
default:
return
1
;
}
if
(
dt_pos
[
6
]
==
-
1
)
pos
++
;
}
}
if
(
pos
>
5
&&
format_type
==
DATETIME_FORMAT_TYPE
&&
(
dt_pos
[
0
]
+
dt_pos
[
1
]
+
dt_pos
[
2
]
+
dt_pos
[
3
]
+
dt_pos
[
4
]
+
dt_pos
[
5
]
!=
15
)
||
pos
>
2
&&
format_type
==
DATE_FORMAT_TYPE
&&
(
dt_pos
[
0
]
+
dt_pos
[
1
]
+
dt_pos
[
2
]
!=
3
)
||
pos
>
2
&&
format_type
==
TIME_FORMAT_TYPE
&&
(
dt_pos
[
3
]
+
dt_pos
[
4
]
+
dt_pos
[
5
]
!=
3
)
||
(
need_p
&&
dt_pos
[
6
]
!=
1
))
return
1
;
/*
Check for valid separators between date/time parst
*/
uint
tmp_len
=
format_length
;
if
(
dt_pos
[
6
]
==
1
)
{
end
=
end
-
2
;
if
(
my_ispunct
(
&
my_charset_latin1
,
*
end
)
||
my_isspace
(
&
my_charset_latin1
,
*
end
))
end
--
;
tmp_len
=
end
-
format_str
;
}
switch
(
format_type
)
{
case
DATE_FORMAT_TYPE
:
case
TIME_FORMAT_TYPE
:
if
((
tmp_len
==
6
&&
!
my_strnncoll
(
&
my_charset_bin
,
(
const
uchar
*
)
format_str
,
6
,
(
const
uchar
*
)
datetime_formats
[
format_type
][
INTERNAL_FORMAT
],
6
))
||
tmp_len
==
8
&&
my_ispunct
(
&
my_charset_latin1
,
*
(
format_str
+
2
))
&&
my_ispunct
(
&
my_charset_latin1
,
*
(
format_str
+
5
)))
{
if
(
format_type
==
TIME_FORMAT_TYPE
&&
tmp_len
==
8
)
{
if
(
*
(
format_str
+
2
)
!=
*
(
format_str
+
5
))
return
1
;
dt_pos
[
7
]
=
*
(
format_str
+
2
);
}
return
0
;
}
break
;
case
DATETIME_FORMAT_TYPE
:
if
((
tmp_len
==
12
&&
!
my_strnncoll
(
&
my_charset_bin
,
(
const
uchar
*
)
format_str
,
12
,
(
const
uchar
*
)
datetime_formats
[
DATETIME_FORMAT_TYPE
][
INTERNAL_FORMAT
],
12
))
||
tmp_len
==
17
&&
my_ispunct
(
&
my_charset_latin1
,
*
(
format_str
+
2
))
&&
my_ispunct
(
&
my_charset_latin1
,
*
(
format_str
+
5
))
&&
my_ispunct
(
&
my_charset_latin1
,
*
(
format_str
+
11
))
&&
my_ispunct
(
&
my_charset_latin1
,
*
(
format_str
+
14
))
&&
(
my_ispunct
(
&
my_charset_latin1
,
*
(
format_str
+
8
))
||
my_isspace
(
&
my_charset_latin1
,
*
(
format_str
+
8
))))
return
0
;
break
;
}
return
1
;
}
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