mirror of
https://github.com/MariaDB/server.git
synced 2025-07-29 05:21:33 +03:00
Merge commit
This commit is contained in:
157
mysql-test/r/date_formats.result
Normal file
157
mysql-test/r/date_formats.result
Normal file
@ -0,0 +1,157 @@
|
||||
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
|
1
mysql-test/t/date_formats-master.opt
Normal file
1
mysql-test/t/date_formats-master.opt
Normal file
@ -0,0 +1 @@
|
||||
--date_format=%d.%m.%Y --time_format=%H.%i.%s --datetime_format=%Y/%d/%m-%H:%i:%s
|
82
mysql-test/t/date_formats.test
Normal file
82
mysql-test/t/date_formats.test
Normal file
@ -0,0 +1,82 @@
|
||||
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;
|
||||
|
71
sql/field.cc
71
sql/field.cc
@ -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);
|
||||
}
|
||||
|
||||
|
||||
@ -2691,7 +2693,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)
|
||||
{
|
||||
@ -3025,7 +3027,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,<ime))
|
||||
if (str_to_time(from,len,<ime,current_thd))
|
||||
{
|
||||
tmp=0L;
|
||||
error= 1;
|
||||
@ -3134,19 +3136,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= "-";
|
||||
ltime.neg= 1;
|
||||
}
|
||||
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);
|
||||
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, <ime, 0, 0,
|
||||
tmp_format->format,
|
||||
tmp_format->format_length, 1);
|
||||
return val_buffer;
|
||||
}
|
||||
|
||||
@ -3312,7 +3320,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;
|
||||
@ -3422,6 +3430,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;
|
||||
@ -3431,9 +3440,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, <ime, 0, 0,
|
||||
tmp_format->format,
|
||||
tmp_format->format_length, 1);
|
||||
return val_buffer;
|
||||
}
|
||||
|
||||
@ -3492,7 +3507,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;
|
||||
@ -3661,7 +3676,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)
|
||||
{
|
||||
|
32
sql/item.cc
32
sql/item.cc
@ -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, <ime, is_time_only, 0,
|
||||
tmp_format->format, tmp_format->format_length, 0);
|
||||
}
|
||||
str->append("'");
|
||||
}
|
||||
|
10
sql/item.h
10
sql/item.h
@ -114,6 +114,14 @@ public:
|
||||
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 @@ public:
|
||||
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);
|
||||
|
@ -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);
|
||||
}
|
||||
|
@ -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);
|
||||
|
1115
sql/item_timefunc.cc
1115
sql/item_timefunc.cc
File diff suppressed because it is too large
Load Diff
@ -763,3 +763,46 @@ public:
|
||||
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;
|
||||
}
|
||||
};
|
||||
|
@ -177,6 +177,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},
|
||||
@ -640,6 +641,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},
|
||||
|
@ -822,7 +822,7 @@ extern pthread_mutex_t LOCK_mysql_create_db,LOCK_Acl,LOCK_open,
|
||||
LOCK_delayed_status, LOCK_delayed_create, LOCK_crypt, LOCK_timezone,
|
||||
LOCK_slave_list, LOCK_active_mi, LOCK_manager,
|
||||
LOCK_global_system_variables, LOCK_user_conn;
|
||||
extern rw_lock_t LOCK_grant;
|
||||
extern rw_lock_t LOCK_grant;
|
||||
extern pthread_cond_t COND_refresh, COND_thread_count, COND_manager;
|
||||
extern pthread_attr_t connection_attrib;
|
||||
extern I_List<THD> threads;
|
||||
@ -839,6 +839,14 @@ extern SHOW_COMP_OPTION have_berkeley_db;
|
||||
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];
|
||||
|
||||
extern String null_string;
|
||||
extern HASH open_cache;
|
||||
extern TABLE *unused_tables;
|
||||
@ -909,14 +917,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);
|
||||
|
@ -319,6 +319,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;
|
||||
@ -906,6 +912,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);
|
||||
@ -1998,6 +2007,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)
|
||||
{
|
||||
@ -2113,6 +2152,12 @@ static int init_common_variables(const char *conf_file_name, int argc,
|
||||
global_system_variables.collation_connection= default_charset_info;
|
||||
global_system_variables.character_set_results= default_charset_info;
|
||||
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;
|
||||
@ -3578,6 +3623,9 @@ enum options_mysqld
|
||||
OPT_GROUP_CONCAT_MAX_LEN,
|
||||
OPT_DEFAULT_COLLATION,
|
||||
OPT_SECURE_AUTH,
|
||||
OPT_DATE_FORMAT,
|
||||
OPT_TIME_FORMAT,
|
||||
OPT_DATETIME_FORMAT,
|
||||
OPT_LOG_QUERIES_NOT_USING_INDEXES
|
||||
};
|
||||
|
||||
@ -4530,6 +4578,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}
|
||||
};
|
||||
|
||||
@ -4907,6 +4970,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",
|
||||
|
@ -833,17 +833,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());
|
||||
}
|
||||
|
||||
|
||||
@ -855,12 +850,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());
|
||||
}
|
||||
|
||||
|
||||
@ -878,16 +873,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());
|
||||
}
|
||||
|
||||
|
||||
|
@ -403,6 +403,9 @@ sys_var *sys_variables[]=
|
||||
&sys_collation_server,
|
||||
&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,
|
||||
@ -540,6 +543,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},
|
||||
@ -696,6 +701,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
|
||||
@ -709,9 +715,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
|
||||
|
@ -49,6 +49,8 @@ public:
|
||||
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 @@ public:
|
||||
class sys_var_thd :public sys_var
|
||||
{
|
||||
public:
|
||||
sys_var_thd()
|
||||
:sys_var()
|
||||
{}
|
||||
sys_var_thd(const char *name_arg)
|
||||
:sys_var(name_arg)
|
||||
{}
|
||||
@ -555,6 +560,51 @@ public:
|
||||
};
|
||||
|
||||
|
||||
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
|
||||
|
@ -279,6 +279,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)
|
||||
|
@ -421,6 +421,7 @@ struct system_variables
|
||||
CHARSET_INFO *collation_server;
|
||||
CHARSET_INFO *collation_database;
|
||||
CHARSET_INFO *collation_connection;
|
||||
sys_var_datetime_format datetime_formats[3];
|
||||
};
|
||||
|
||||
void free_tmp_table(THD *thd, TABLE *entry);
|
||||
|
@ -78,6 +78,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;
|
||||
}
|
||||
@ -482,6 +483,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
|
||||
@ -644,6 +646,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
|
||||
@ -2581,6 +2584,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 ')'
|
||||
@ -3194,6 +3199,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
|
||||
@ -4541,6 +4551,7 @@ keyword:
|
||||
| FLUSH_SYM {}
|
||||
| GEOMETRY_SYM {}
|
||||
| GEOMETRYCOLLECTION {}
|
||||
| GET_FORMAT {}
|
||||
| GRANTS {}
|
||||
| GLOBAL_SYM {}
|
||||
| HANDLER_SYM {}
|
||||
|
@ -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;
|
||||
|
328
sql/time.cc
328
sql/time.cc
@ -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);
|
||||
year_length= (digits == 4 || digits == 8 || digits >= 14) ? 4 : 2;
|
||||
field_length=year_length-1;
|
||||
|
||||
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,7 +385,8 @@ str_to_TIME(const char *str, uint length, TIME *l_time,bool fuzzy_date)
|
||||
found_delimitier=1; // Should be a 'normal' date
|
||||
}
|
||||
}
|
||||
field_length=1; // Rest fields can only be 2
|
||||
if (is_internal_format)
|
||||
field_length=1; // Rest fields can only be 2
|
||||
}
|
||||
/* Handle second fractions */
|
||||
if (i == 6 && (uint) (end-str) >= 2 && *str == '.' &&
|
||||
@ -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, ¬_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,8 +626,8 @@ 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 != ':' ||
|
||||
!my_isdigit(&my_charset_latin1,str[1]))
|
||||
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;
|
||||
}
|
||||
|
Reference in New Issue
Block a user