summaryrefslogtreecommitdiff
path: root/sql
diff options
context:
space:
mode:
authormonty@narttu.mysql.fi <>2003-11-03 22:48:03 +0200
committermonty@narttu.mysql.fi <>2003-11-03 22:48:03 +0200
commit6b79cd5c23c33d36c6dba2c990b20af8a88f97c1 (patch)
tree68c6948d4fbd18bb59fa1aeafdce4a07a41b835f /sql
parentdde384d9ea881353f04ee9827421c23ded4e8c29 (diff)
parent085b1c56084d99646f2e52aee42ef026b7526eeb (diff)
downloadmariadb-git-6b79cd5c23c33d36c6dba2c990b20af8a88f97c1.tar.gz
Merge
Diffstat (limited to 'sql')
-rw-r--r--sql/Makefile.am2
-rw-r--r--sql/derror.cc4
-rw-r--r--sql/field.cc159
-rw-r--r--sql/field.h11
-rw-r--r--sql/init.cc2
-rw-r--r--sql/item.cc63
-rw-r--r--sql/item.h29
-rw-r--r--sql/item_create.cc3
-rw-r--r--sql/item_func.cc15
-rw-r--r--sql/item_func.h4
-rw-r--r--sql/item_strfunc.h4
-rw-r--r--sql/item_timefunc.cc1046
-rw-r--r--sql/item_timefunc.h127
-rw-r--r--sql/mysql_priv.h45
-rw-r--r--sql/mysqld.cc128
-rw-r--r--sql/protocol.cc38
-rw-r--r--sql/set_var.cc238
-rw-r--r--sql/set_var.h46
-rw-r--r--sql/share/czech/errmsg.txt25
-rw-r--r--sql/share/danish/errmsg.txt25
-rw-r--r--sql/share/dutch/errmsg.txt25
-rw-r--r--sql/share/english/errmsg.txt47
-rw-r--r--sql/share/estonian/errmsg.txt25
-rw-r--r--sql/share/french/errmsg.txt25
-rw-r--r--sql/share/german/errmsg.txt11
-rw-r--r--sql/share/greek/errmsg.txt25
-rw-r--r--sql/share/hungarian/errmsg.txt25
-rw-r--r--sql/share/italian/errmsg.txt26
-rw-r--r--sql/share/japanese/errmsg.txt25
-rw-r--r--sql/share/korean/errmsg.txt26
-rw-r--r--sql/share/norwegian-ny/errmsg.txt25
-rw-r--r--sql/share/norwegian/errmsg.txt26
-rw-r--r--sql/share/polish/errmsg.txt25
-rw-r--r--sql/share/portuguese/errmsg.txt27
-rw-r--r--sql/share/romanian/errmsg.txt27
-rw-r--r--sql/share/russian/errmsg.txt25
-rw-r--r--sql/share/serbian/errmsg.txt25
-rw-r--r--sql/share/slovak/errmsg.txt25
-rw-r--r--sql/share/spanish/errmsg.txt27
-rw-r--r--sql/share/swedish/errmsg.txt29
-rw-r--r--sql/share/ukrainian/errmsg.txt25
-rw-r--r--sql/sql_base.cc3
-rw-r--r--sql/sql_class.cc12
-rw-r--r--sql/sql_class.h6
-rw-r--r--sql/sql_db.cc4
-rw-r--r--sql/sql_lex.cc78
-rw-r--r--sql/sql_parse.cc31
-rw-r--r--sql/sql_prepare.cc2
-rw-r--r--sql/sql_table.cc6
-rw-r--r--sql/sql_yacc.yy38
-rw-r--r--sql/strfunc.cc147
-rw-r--r--sql/structs.h47
-rw-r--r--sql/time.cc885
-rw-r--r--sql/unireg.h4
54 files changed, 2228 insertions, 1595 deletions
diff --git a/sql/Makefile.am b/sql/Makefile.am
index 69b9c58dd6d..0167124a892 100644
--- a/sql/Makefile.am
+++ b/sql/Makefile.am
@@ -63,7 +63,7 @@ mysqld_SOURCES = sql_lex.cc sql_handler.cc \
item_cmpfunc.cc item_strfunc.cc item_timefunc.cc \
thr_malloc.cc item_create.cc item_subselect.cc \
item_row.cc item_geofunc.cc \
- field.cc key.cc sql_class.cc sql_list.cc \
+ field.cc strfunc.cc key.cc sql_class.cc sql_list.cc \
net_serv.cc protocol.cc sql_state.c \
lock.cc my_lock.c \
sql_string.cc sql_manager.cc sql_map.cc \
diff --git a/sql/derror.cc b/sql/derror.cc
index f5fe92da238..8d4f8e664e2 100644
--- a/sql/derror.cc
+++ b/sql/derror.cc
@@ -117,7 +117,7 @@ Check that the above file is the right version for this program!",
point[i]= *point +uint2korr(head+10+i+i);
}
VOID(my_close(file,MYF(0)));
- DBUG_RETURN(FALSE);
+ DBUG_RETURN(0);
err:
switch (funktpos) {
@@ -136,7 +136,7 @@ err1:
if (file != FERR)
VOID(my_close(file,MYF(MY_WME)));
unireg_abort(1);
- return 1;
+ DEBUG_RETURN(1); // Impossible
} /* read_texts */
diff --git a/sql/field.cc b/sql/field.cc
index c30c06c6395..04e9c45327b 100644
--- a/sql/field.cc
+++ b/sql/field.cc
@@ -274,13 +274,14 @@ uint Field::fill_cache_field(CACHE_FIELD *copy)
return copy->length+(int) copy->strip;
}
-bool Field::get_date(TIME *ltime,bool fuzzydate)
+
+bool Field::get_date(TIME *ltime,uint 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,current_thd)<=
- WRONG_TIMESTAMP_FULL)
+ str_to_TIME(res->ptr(),res->length(),ltime,fuzzydate) <=
+ TIMESTAMP_DATETIME_ERROR)
return 1;
return 0;
}
@@ -290,39 +291,44 @@ 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,current_thd))
+ str_to_time(res->ptr(),res->length(),ltime))
return 1;
return 0;
}
+/*
+ This is called when storing a date in a string
+
+ NOTES
+ Needs to be changed if/when we want to support different time formats
+*/
-/* This is called when storing a date in a string */
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:
+ case TIMESTAMP_DATETIME_ERROR:
store("",0,&my_charset_bin); // Probably an error
- return;
+ break;
case TIMESTAMP_DATE:
- tmp_format= &t_datetime_frm(current_thd, DATE_FORMAT_TYPE).datetime_format;
+ sprintf(buff,"%04d-%02d-%02d", ltime->year,ltime->month,ltime->day);
+ store(buff,10,&my_charset_bin);
break;
- case TIMESTAMP_FULL:
- tmp_format=&t_datetime_frm(current_thd,DATETIME_FORMAT_TYPE).datetime_format;
+ case TIMESTAMP_DATETIME:
+ 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);
break;
case TIMESTAMP_TIME:
- tmp_format= &t_datetime_frm(current_thd, TIME_FORMAT_TYPE).datetime_format;
- is_time_only= 1;
+ {
+ ulong length= my_sprintf(buff, (buff, "%02d:%02d:%02d",
+ ltime->hour,ltime->minute,ltime->second));
+ store(buff,(uint) length, &my_charset_bin);
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);
+ }
}
@@ -2693,7 +2699,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,current_thd);
+ long tmp=(long) str_to_timestamp(from,len);
#ifdef WORDS_BIGENDIAN
if (table->db_low_byte_first)
{
@@ -2908,7 +2914,7 @@ String *Field_timestamp::val_str(String *val_buffer,
}
-bool Field_timestamp::get_date(TIME *ltime, bool fuzzydate)
+bool Field_timestamp::get_date(TIME *ltime, uint fuzzydate)
{
long temp;
#ifdef WORDS_BIGENDIAN
@@ -2937,7 +2943,7 @@ bool Field_timestamp::get_date(TIME *ltime, bool fuzzydate)
ltime->second= start->tm_sec;
ltime->second_part= 0;
ltime->neg= 0;
- ltime->time_type=TIMESTAMP_FULL;
+ ltime->time_type=TIMESTAMP_DATETIME;
}
return 0;
}
@@ -2951,7 +2957,7 @@ bool Field_timestamp::get_time(TIME *ltime)
bool Field_timestamp::send_binary(Protocol *protocol)
{
TIME tm;
- Field_timestamp::get_date(&tm, 1);
+ Field_timestamp::get_date(&tm, TIME_FUZZY_DATE);
return protocol->store(&tm);
}
@@ -3027,7 +3033,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,current_thd))
+ if (str_to_time(from,len,&ltime))
{
tmp=0L;
error= 1;
@@ -3137,27 +3143,23 @@ String *Field_time::val_str(String *val_buffer,
String *val_ptr __attribute__((unused)))
{
TIME ltime;
- val_buffer->alloc(16);
+ val_buffer->alloc(19);
long tmp=(long) sint3korr(ptr);
- const char *sign="";
ltime.neg= 0;
if (tmp < 0)
{
tmp= -tmp;
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);
+ make_time((DATE_TIME_FORMAT*) 0, &ltime, val_buffer);
return val_buffer;
}
+
bool Field_time::get_time(TIME *ltime)
{
long tmp=(long) sint3korr(ptr);
@@ -3320,7 +3322,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,current_thd) <= WRONG_TIMESTAMP_FULL)
+ if (str_to_TIME(from,len,&l_time,1) <= TIMESTAMP_DATETIME_ERROR)
{
tmp=0;
error= 1;
@@ -3432,7 +3434,6 @@ String *Field_date::val_str(String *val_buffer,
{
TIME ltime;
val_buffer->alloc(field_length);
- val_buffer->length(field_length);
int32 tmp;
#ifdef WORDS_BIGENDIAN
if (table->db_low_byte_first)
@@ -3440,18 +3441,15 @@ String *Field_date::val_str(String *val_buffer,
else
#endif
longget(tmp,ptr);
- 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);
+ make_date((DATE_TIME_FORMAT *) 0, &ltime, val_buffer);
return val_buffer;
}
+
int Field_date::cmp(const char *a_ptr, const char *b_ptr)
{
int32 a,b;
@@ -3507,7 +3505,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,current_thd) <= WRONG_TIMESTAMP_FULL)
+ if (str_to_TIME(from,len,&l_time,1) <= TIMESTAMP_DATETIME_ERROR)
{
tmp=0L;
error= 1;
@@ -3572,7 +3570,7 @@ int Field_newdate::store(longlong nr)
void Field_newdate::store_time(TIME *ltime,timestamp_type type)
{
long tmp;
- if (type == TIMESTAMP_DATE || type == TIMESTAMP_FULL)
+ if (type == TIMESTAMP_DATE || type == TIMESTAMP_DATETIME)
tmp=ltime->year*16*32+ltime->month*32+ltime->day;
else
{
@@ -3628,7 +3626,7 @@ String *Field_newdate::val_str(String *val_buffer,
return val_buffer;
}
-bool Field_newdate::get_date(TIME *ltime,bool fuzzydate)
+bool Field_newdate::get_date(TIME *ltime,uint fuzzydate)
{
if (is_null())
return 1;
@@ -3676,7 +3674,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,current_thd);
+ longlong tmp=str_to_datetime(from,len,1);
#ifdef WORDS_BIGENDIAN
if (table->db_low_byte_first)
{
@@ -3730,7 +3728,7 @@ int Field_datetime::store(longlong nr)
void Field_datetime::store_time(TIME *ltime,timestamp_type type)
{
longlong tmp;
- if (type == TIMESTAMP_DATE || type == TIMESTAMP_FULL)
+ if (type == TIMESTAMP_DATE || type == TIMESTAMP_DATETIME)
tmp=((ltime->year*10000L+ltime->month*100+ltime->day)*LL(1000000)+
(ltime->hour*10000L+ltime->minute*100+ltime->second));
else
@@ -3751,7 +3749,7 @@ void Field_datetime::store_time(TIME *ltime,timestamp_type type)
bool Field_datetime::send_binary(Protocol *protocol)
{
TIME tm;
- Field_datetime::get_date(&tm, 1);
+ Field_datetime::get_date(&tm, TIME_FUZZY_DATE);
return protocol->store(&tm);
}
@@ -3822,14 +3820,14 @@ String *Field_datetime::val_str(String *val_buffer,
return val_buffer;
}
-bool Field_datetime::get_date(TIME *ltime,bool fuzzydate)
+bool Field_datetime::get_date(TIME *ltime, uint fuzzydate)
{
longlong tmp=Field_datetime::val_int();
uint32 part1,part2;
part1=(uint32) (tmp/LL(1000000));
part2=(uint32) (tmp - (ulonglong) part1*LL(1000000));
- ltime->time_type= TIMESTAMP_FULL;
+ ltime->time_type= TIMESTAMP_DATETIME;
ltime->neg= 0;
ltime->second_part= 0;
ltime->second= (int) (part2%100);
@@ -4921,26 +4919,6 @@ void Field_enum::store_type(ulonglong value)
}
-uint find_enum(TYPELIB *lib,const char *x, uint length)
-{
- const char *end=x+length;
- while (end > x && my_isspace(system_charset_info,end[-1]))
- end--;
-
- const char *i;
- const char *j;
- for (uint pos=0 ; (j=lib->type_names[pos]) ; pos++)
- {
- for (i=x ; i != end &&
- my_toupper(system_charset_info,*i) ==
- my_toupper(system_charset_info,*j) ; i++, j++) ;
- if (i == end && ! *j)
- return(pos+1);
- }
- return(0);
-}
-
-
/*
** Note. Storing a empty string in a enum field gives a warning
** (if there isn't a empty value in the enum)
@@ -4958,7 +4936,11 @@ int Field_enum::store(const char *from,uint length,CHARSET_INFO *cs)
from= tmpstr.ptr();
length= tmpstr.length();
}
- uint tmp=find_enum(typelib,from,length);
+
+ /* Remove end space */
+ while (length > 0 && my_isspace(system_charset_info,from[length-1]))
+ length--;
+ uint tmp=find_type(typelib, from, length, 0);
if (!tmp)
{
if (length < 6) // Can't be more than 99999 enums
@@ -5111,49 +5093,8 @@ void Field_enum::sql_type(String &res) const
For example "One,two,five"
If one uses this string in a number context one gets the bits as a longlong
number.
-
- If there was a value in string that wasn't in set, the 'err_pos' points to
- the last invalid value found. 'err_len' will be set to length of the
- error string.
*/
-ulonglong find_set(TYPELIB *lib, const char *x, uint length, char **err_pos,
- uint *err_len, bool *set_warning)
-{
- const char *end= x + length;
- *err_pos= 0; // No error yet
- while (end > x && my_isspace(system_charset_info, end[-1]))
- end--;
-
- *err_len= 0;
- ulonglong found= 0;
- if (x != end)
- {
- const char *start= x;
- for (;;)
- {
- const char *pos= start;
- uint var_len;
-
- for (; pos != end && *pos != field_separator; pos++) ;
- var_len= (uint) (pos - start);
- uint find= find_enum(lib, start, var_len);
- if (!find)
- {
- *err_pos= (char*) start;
- *err_len= var_len;
- *set_warning= 1;
- }
- else
- found|= ((longlong) 1 << (find - 1));
- if (pos == end)
- break;
- start= pos + 1;
- }
- }
- return found;
-}
-
int Field_set::store(const char *from,uint length,CHARSET_INFO *cs)
{
@@ -5512,7 +5453,7 @@ create_field::create_field(Field *old_field,Field *orig_field)
case 3: sql_type= FIELD_TYPE_MEDIUM_BLOB; break;
default: sql_type= FIELD_TYPE_LONG_BLOB; break;
}
- length /= charset->mbmaxlen;
+ length /= charset->mbmaxlen; // QQ: Probably not needed
break;
case FIELD_TYPE_STRING:
case FIELD_TYPE_VAR_STRING:
diff --git a/sql/field.h b/sql/field.h
index e7d4bb2416a..692e64d1146 100644
--- a/sql/field.h
+++ b/sql/field.h
@@ -224,7 +224,7 @@ public:
uint offset(); // Should be inline ...
void copy_from_tmp(int offset);
uint fill_cache_field(struct st_cache_field *copy);
- virtual bool get_date(TIME *ltime,bool fuzzydate);
+ virtual bool get_date(TIME *ltime,uint fuzzydate);
virtual bool get_time(TIME *ltime);
virtual CHARSET_INFO *charset(void) const { return &my_charset_bin; }
virtual bool has_charset(void) const { return FALSE; }
@@ -647,7 +647,7 @@ public:
longget(tmp,ptr);
return tmp;
}
- bool get_date(TIME *ltime,bool fuzzydate);
+ bool get_date(TIME *ltime,uint fuzzydate);
bool get_time(TIME *ltime);
};
@@ -735,7 +735,7 @@ public:
void sql_type(String &str) const;
bool store_for_compare() { return 1; }
bool zero_pack() const { return 1; }
- bool get_date(TIME *ltime,bool fuzzydate);
+ bool get_date(TIME *ltime,uint fuzzydate);
bool get_time(TIME *ltime);
};
@@ -805,7 +805,7 @@ public:
void sql_type(String &str) const;
bool store_for_compare() { return 1; }
bool zero_pack() const { return 1; }
- bool get_date(TIME *ltime,bool fuzzydate);
+ bool get_date(TIME *ltime,uint fuzzydate);
bool get_time(TIME *ltime);
};
@@ -1160,9 +1160,6 @@ uint pack_length_to_packflag(uint type);
uint32 calc_pack_length(enum_field_types type,uint32 length);
bool set_field_to_null(Field *field);
bool set_field_to_null_with_conversions(Field *field, bool no_conversions);
-uint find_enum(TYPELIB *typelib,const char *x, uint length);
-ulonglong find_set(TYPELIB *typelib,const char *x, uint length,
- char **err_pos, uint *err_len, bool *set_warning);
bool test_if_int(const char *str, int length, const char *int_end,
CHARSET_INFO *cs);
diff --git a/sql/init.cc b/sql/init.cc
index 8b15fef4ee3..033dfd72843 100644
--- a/sql/init.cc
+++ b/sql/init.cc
@@ -42,8 +42,6 @@ void unireg_init(ulong options)
#endif
VOID(strmov(reg_ext,".frm"));
- for (i=0 ; i < 6 ; i++) // YYMMDDHHMMSS
- dayord.pos[i]=i;
specialflag=SPECIAL_SAME_DB_NAME;
/* Make a tab of powers of 10 */
for (i=0,nr=1.0; i < array_elements(log_10) ; i++)
diff --git a/sql/item.cc b/sql/item.cc
index 421574ed636..24710654d4a 100644
--- a/sql/item.cc
+++ b/sql/item.cc
@@ -46,8 +46,10 @@ Item::Item():
collation.set(default_charset(), DERIVATION_COERCIBLE);
name= 0;
decimals= 0; max_length= 0;
- thd= current_thd;
- next= thd->free_list; // Put in free list
+
+ /* Put item in free list so that we can free all items at end */
+ THD *thd= current_thd;
+ next= thd->free_list;
thd->free_list= this;
/*
Item constructor can be called during execution other then SQL_COM
@@ -69,7 +71,7 @@ Item::Item():
Used for duplicating lists in processing queries with temporary
tables
*/
-Item::Item(THD *c_thd, Item &item):
+Item::Item(THD *thd, Item &item):
str_value(item.str_value),
name(item.name),
max_length(item.max_length),
@@ -82,8 +84,7 @@ Item::Item(THD *c_thd, Item &item):
fixed(item.fixed),
collation(item.collation)
{
- next=c_thd->free_list; // Put in free list
- thd= c_thd;
+ next= thd->free_list; // Put in free list
thd->free_list= this;
}
@@ -183,13 +184,13 @@ bool Item_string::eq(const Item *item, bool binary_cmp) const
As a extra convenience the time structure is reset on error!
*/
-bool Item::get_date(TIME *ltime,bool fuzzydate)
+bool Item::get_date(TIME *ltime,uint 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, thd) <=
- WRONG_TIMESTAMP_FULL)
+ str_to_TIME(res->ptr(),res->length(),ltime,fuzzydate) <=
+ TIMESTAMP_DATETIME_ERROR)
{
bzero((char*) ltime,sizeof(*ltime));
return 1;
@@ -207,7 +208,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, thd))
+ str_to_time(res->ptr(),res->length(),ltime))
{
bzero((char*) ltime,sizeof(*ltime));
return 1;
@@ -360,7 +361,7 @@ String *Item_field::str_result(String *str)
return result_field->val_str(str,&str_value);
}
-bool Item_field::get_date(TIME *ltime,bool fuzzydate)
+bool Item_field::get_date(TIME *ltime,uint fuzzydate)
{
if ((null_value=field->is_null()) || field->get_date(ltime,fuzzydate))
{
@@ -370,7 +371,7 @@ bool Item_field::get_date(TIME *ltime,bool fuzzydate)
return 0;
}
-bool Item_field::get_date_result(TIME *ltime,bool fuzzydate)
+bool Item_field::get_date_result(TIME *ltime,uint fuzzydate)
{
if ((null_value=result_field->is_null()) ||
result_field->get_date(ltime,fuzzydate))
@@ -692,28 +693,25 @@ String *Item_param::query_val_str(String* str)
}
else
{
- DATETIME_FORMAT *tmp_format= 0;
- bool is_time_only= 0;
+ char buff[40];
+ String tmp(buff,sizeof(buff), &my_charset_bin);
switch (ltime.time_type) {
- case TIMESTAMP_NONE:
- case WRONG_TIMESTAMP_FULL:
- break;
- case TIMESTAMP_DATE:
- tmp_format= &t_datetime_frm(thd, DATE_FORMAT_TYPE).datetime_format;
- break;
- case TIMESTAMP_FULL:
- tmp_format= &t_datetime_frm(thd, DATETIME_FORMAT_TYPE).datetime_format;
- break;
- case TIMESTAMP_TIME:
- {
- tmp_format= &t_datetime_frm(thd, TIME_FORMAT_TYPE).datetime_format;
- is_time_only= 1;
- break;
- }
+ case TIMESTAMP_NONE:
+ case TIMESTAMP_DATETIME_ERROR:
+ tmp.length(0); // Should never happen
+ break;
+ case TIMESTAMP_DATE:
+ make_date((DATE_TIME_FORMAT*) 0, &ltime, &tmp);
+ break;
+ case TIMESTAMP_DATETIME:
+ make_datetime((DATE_TIME_FORMAT*) 0, &ltime, &tmp);
+ break;
+ case TIMESTAMP_TIME:
+ make_time((DATE_TIME_FORMAT*) 0, &ltime, &tmp);
+ break;
}
- make_datetime(str, &ltime, is_time_only, 0,
- tmp_format->format, tmp_format->format_length, 0);
+ str->append(tmp);
}
str->append('\'');
}
@@ -769,7 +767,7 @@ String* Item_ref_null_helper::val_str(String* s)
owner->was_null|= null_value= (*ref)->null_value;
return tmp;
}
-bool Item_ref_null_helper::get_date(TIME *ltime, bool fuzzydate)
+bool Item_ref_null_helper::get_date(TIME *ltime, uint fuzzydate)
{
return (owner->was_null|= null_value= (*ref)->get_date(ltime, fuzzydate));
}
@@ -990,6 +988,7 @@ enum_field_types Item::field_type() const
FIELD_TYPE_DOUBLE);
}
+
Field *Item::tmp_table_field_from_field_type(TABLE *table)
{
switch (field_type())
@@ -1366,7 +1365,7 @@ bool Item::send(Protocol *protocol, String *buffer)
case MYSQL_TYPE_TIMESTAMP:
{
TIME tm;
- get_date(&tm, 1);
+ get_date(&tm, TIME_FUZZY_DATE);
if (!null_value)
{
if (type == MYSQL_TYPE_DATE)
diff --git a/sql/item.h b/sql/item.h
index dcefde05605..f473ca33676 100644
--- a/sql/item.h
+++ b/sql/item.h
@@ -114,14 +114,6 @@ 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();
/*
@@ -132,7 +124,7 @@ public:
top AND/OR ctructure of WHERE clause to protect it of
optimisation changes in prepared statements
*/
- Item(THD *c_thd, Item &item);
+ Item(THD *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);
@@ -185,9 +177,9 @@ public:
void print_item_w_name(String *);
virtual void update_used_tables() {}
virtual void split_sum_func(Item **ref_pointer_array, List<Item> &fields) {}
- virtual bool get_date(TIME *ltime,bool fuzzydate);
+ virtual bool get_date(TIME *ltime,uint fuzzydate);
virtual bool get_time(TIME *ltime);
- virtual bool get_date_result(TIME *ltime,bool fuzzydate)
+ virtual bool get_date_result(TIME *ltime,uint fuzzydate)
{ return get_date(ltime,fuzzydate); }
virtual bool is_null() { return 0; }
virtual void top_level_item() {}
@@ -286,8 +278,8 @@ public:
}
Field *get_tmp_table_field() { return result_field; }
Field *tmp_table_field(TABLE *t_arg) { return result_field; }
- bool get_date(TIME *ltime,bool fuzzydate);
- bool get_date_result(TIME *ltime,bool fuzzydate);
+ bool get_date(TIME *ltime,uint fuzzydate);
+ bool get_date_result(TIME *ltime,uint fuzzydate);
bool get_time(TIME *ltime);
bool is_null() { return field->is_null(); }
Item *get_tmp_table_item(THD *thd);
@@ -469,6 +461,13 @@ public:
{
collation.set(cs, dv);
str_value.set(str,length,cs);
+ /*
+ We have to have a different max_length than 'length' here to
+ ensure that we get the right length if we do use the item
+ to create a new table. In this case max_length must be the maximum
+ number of chars for a string of this type because we in create_field::
+ divide the max_length with mbmaxlen).
+ */
max_length= str_value.numchars()*cs->mbmaxlen;
set_name(str, length, cs);
decimals=NOT_FIXED_DEC;
@@ -623,7 +622,7 @@ public:
(void) (*ref)->val_int_result();
return (*ref)->null_value;
}
- bool get_date(TIME *ltime,bool fuzzydate)
+ bool get_date(TIME *ltime,uint fuzzydate)
{
return (null_value=(*ref)->get_date_result(ltime,fuzzydate));
}
@@ -658,7 +657,7 @@ public:
double val();
longlong val_int();
String* val_str(String* s);
- bool get_date(TIME *ltime, bool fuzzydate);
+ bool get_date(TIME *ltime, uint fuzzydate);
void print(String *str);
};
diff --git a/sql/item_create.cc b/sql/item_create.cc
index a25ccfe984b..5c44d8b00ff 100644
--- a/sql/item_create.cc
+++ b/sql/item_create.cc
@@ -450,7 +450,8 @@ Item *create_load_file(Item* a)
}
-Item *create_func_cast(Item *a, Cast_target cast_type, int len, CHARSET_INFO *cs)
+Item *create_func_cast(Item *a, Cast_target cast_type, int len,
+ CHARSET_INFO *cs)
{
Item *res;
LINT_INIT(res);
diff --git a/sql/item_func.cc b/sql/item_func.cc
index bcb4ec9aa7f..e6120f2e93c 100644
--- a/sql/item_func.cc
+++ b/sql/item_func.cc
@@ -1323,8 +1323,8 @@ void Item_func_find_in_set::fix_length_and_dec()
String *find=args[0]->val_str(&value);
if (find)
{
- enum_value=find_enum(((Field_enum*) field)->typelib,find->ptr(),
- find->length());
+ enum_value= find_type(((Field_enum*) field)->typelib,find->ptr(),
+ find->length(), 0);
enum_bit=0;
if (enum_value)
enum_bit=LL(1) << (enum_value-1);
@@ -2146,8 +2146,8 @@ static user_var_entry *get_variable(HASH *hash, LEX_STRING &name,
}
/*
- When a user variable is updated (in a SET command or a query like SELECT @a:=
- ).
+ When a user variable is updated (in a SET command or a query like
+ SELECT @a:= ).
*/
bool Item_func_set_user_var::fix_fields(THD *thd, TABLE_LIST *tables,
@@ -2506,14 +2506,15 @@ void Item_func_get_user_var::fix_length_and_dec()
sql_set_variables() is what is called from 'case SQLCOM_SET_OPTION'
in dispatch_command()). Instead of building a one-element list to pass to
sql_set_variables(), we could instead manually call check() and update();
- this would save memory and time; but calling sql_set_variables() makes one
- unique place to maintain (sql_set_variables()).
+ this would save memory and time; but calling sql_set_variables() makes
+ one unique place to maintain (sql_set_variables()).
*/
List<set_var_base> tmp_var_list;
tmp_var_list.push_back(new set_var_user(new Item_func_set_user_var(name,
new Item_null())));
- if (sql_set_variables(thd, &tmp_var_list)) /* this will create the variable */
+ /* Create the variable */
+ if (sql_set_variables(thd, &tmp_var_list))
goto err;
if (!(var_entry= get_variable(&thd->user_vars, name, 0)))
goto err;
diff --git a/sql/item_func.h b/sql/item_func.h
index b9498ed0b5d..6b43ebaccbe 100644
--- a/sql/item_func.h
+++ b/sql/item_func.h
@@ -127,9 +127,9 @@ public:
void print_op(String *str);
void print_args(String *str, uint from);
void fix_num_length_and_dec();
- inline bool get_arg0_date(TIME *ltime,bool fuzzy_date)
+ inline bool get_arg0_date(TIME *ltime, uint fuzzy_date)
{
- return (null_value=args[0]->get_date(ltime,fuzzy_date));
+ return (null_value=args[0]->get_date(ltime, fuzzy_date));
}
inline bool get_arg0_time(TIME *ltime)
{
diff --git a/sql/item_strfunc.h b/sql/item_strfunc.h
index 00b1ebb0732..a7949511f02 100644
--- a/sql/item_strfunc.h
+++ b/sql/item_strfunc.h
@@ -361,7 +361,7 @@ public:
String *val_str(String *);
void fix_length_and_dec()
{
- max_length= MAX_FIELD_NAME * system_charset_info->mbmaxlen;
+ max_length= MAX_FIELD_NAME * system_charset_info->mbmaxlen;
}
const char *func_name() const { return "database"; }
};
@@ -373,7 +373,7 @@ public:
String *val_str(String *);
void fix_length_and_dec()
{
- max_length= (USERNAME_LENGTH+HOSTNAME_LENGTH+1)*system_charset_info->mbmaxlen;
+ max_length= (USERNAME_LENGTH+HOSTNAME_LENGTH+1)*system_charset_info->mbmaxlen;
}
const char *func_name() const { return "user"; }
};
diff --git a/sql/item_timefunc.cc b/sql/item_timefunc.cc
index 46d39b4ced6..cf71f2b3bef 100644
--- a/sql/item_timefunc.cc
+++ b/sql/item_timefunc.cc
@@ -1,4 +1,4 @@
-/* Copyright (C) 2000 MySQL AB & MySQL Finland AB & TCX DataKonsult AB
+/* Copyright (C) 2000-2003 MySQL AB
This program is free software; you can redistribute it and/or modify
it under the terms of the GNU General Public License as published by
@@ -25,310 +25,290 @@
#include <m_ctype.h>
#include <time.h>
-/*
-** Todo: Move month and days to language files
-*/
+/* TODO: Move month and days to language files */
#define MAX_DAY_NUMBER 3652424L
-static String month_names[] =
-{
- String("January", &my_charset_latin1),
- String("February", &my_charset_latin1),
- String("March", &my_charset_latin1),
- String("April", &my_charset_latin1),
- String("May", &my_charset_latin1),
- String("June", &my_charset_latin1),
- String("July", &my_charset_latin1),
- String("August", &my_charset_latin1),
- String("September", &my_charset_latin1),
- String("October", &my_charset_latin1),
- String("November", &my_charset_latin1),
- String("December", &my_charset_latin1)
+static const char *month_names[]=
+{
+ "January", "February", "March", "April", "May", "June", "July", "August",
+ "September", "October", "November", "December", NullS
};
-static String day_names[] =
+
+TYPELIB month_names_typelib=
+{ array_elements(month_names)-1,"", month_names };
+
+static const char *day_names[]=
+{
+ "Monday", "Tuesday", "Wednesday",
+ "Thursday", "Friday", "Saturday" ,"Sunday", NullS
+};
+
+TYPELIB day_names_typelib=
+{ array_elements(day_names)-1,"", day_names};
+
+
+enum date_time_format_types
{
- String("Monday", &my_charset_latin1),
- String("Tuesday", &my_charset_latin1),
- String("Wednesday", &my_charset_latin1),
- String("Thursday", &my_charset_latin1),
- String("Friday", &my_charset_latin1),
- String("Saturday", &my_charset_latin1),
- String("Sunday", &my_charset_latin1)
+ TIME_ONLY= 0, TIME_MICROSECOND, DATE_ONLY, DATE_TIME, DATE_TIME_MICROSECOND
};
-uint check_names(String *arr,int item_count,const char *val_ptr,
- const char *val_end, uint *val, bool check_part)
+/*
+ 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.
+
+ The reason for this functions existence is that as we don't have a
+ way to know if a datetime/time value has microseconds in them
+ we are now only adding microseconds to the output if the
+ value has microseconds.
+
+ We can't use a standard make_date_time() for this as we don't know
+ if someone will use %f in the format specifier in which case we would get
+ the microseconds twice.
+*/
+
+static bool make_datetime(date_time_format_types format, TIME *ltime,
+ String *str)
{
- 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;
- }
+ char *buff;
+ CHARSET_INFO *cs= &my_charset_bin;
+ uint length= 30;
- 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;
-}
+ if (str->alloc(length))
+ return 1;
+ buff= (char*) str->ptr();
-uint check_val_is_digit(const char *ptr, uint val_len, uint digit_count)
-{
- 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++;
+ switch (format) {
+ case TIME_ONLY:
+ length= cs->cset->snprintf(cs, buff, length, "%s%02d:%02d:%02d",
+ ltime->neg ? "-" : "",
+ ltime->hour, ltime->minute, ltime->second);
+ break;
+ case TIME_MICROSECOND:
+ length= cs->cset->snprintf(cs, buff, length, "%s%02d:%02d:%02d.%06d",
+ ltime->neg ? "-" : "",
+ ltime->hour, ltime->minute, ltime->second,
+ ltime->second_part);
+ break;
+ case DATE_ONLY:
+ length= cs->cset->snprintf(cs, buff, length, "%04d-%02d-%02d",
+ ltime->year, ltime->month, ltime->day);
+ break;
+ case DATE_TIME:
+ length= cs->cset->snprintf(cs, buff, length,
+ "%04d-%02d-%02d %02d:%02d:%02d",
+ ltime->year, ltime->month, ltime->day,
+ ltime->hour, ltime->minute, ltime->second);
+ break;
+ case DATE_TIME_MICROSECOND:
+ length= cs->cset->snprintf(cs, buff, length,
+ "%04d-%02d-%02d %02d:%02d:%02d.%06d",
+ ltime->year, ltime->month, ltime->day,
+ ltime->hour, ltime->minute, ltime->second,
+ ltime->second_part);
+ break;
}
- return digit_found;
+
+ str->length(length);
+ str->set_charset(cs);
+ return 0;
}
/*
Extract datetime value to TIME struct from string value
according to format string.
+
+ SYNOPSIS
+ extract_date_time()
+ format date/time format specification
+ val String to decode
+ length Length of string
+ l_time Store result here
+
+ RETURN
+ 0 ok
+ 1 error
*/
-bool extract_datetime(const char *str_val, uint str_val_len,
- const char *str_format, uint str_format_len,
- TIME *l_time)
+
+static bool extract_date_time(DATE_TIME_FORMAT *format,
+ const char *val, uint length, TIME *l_time)
{
- 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;
- int err= 0;
+ int error= 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;
+ const char *val_ptr= val;
+ const char *val_end= val + length;
+ const char *ptr= format->format.str;
+ const char *end= ptr+ format->format.length;
+ DBUG_ENTER("extract_date_time");
- DBUG_ENTER("extract_datetime");
- for (; ptr != end && val_ptr != val_end; ptr++)
+ bzero((char*) l_time, sizeof(*l_time));
+
+ for (; ptr != end && val != val_end; ptr++)
{
+
if (*ptr == '%' && ptr+1 != end)
{
- val_len= val_end - val_ptr;
- char *val_end1= (char *) val_end;
+ int val_len;
+ char *tmp;
+
+ /* Skip pre-space between each argument */
+ while (my_isspace(cs, *val) && val != val_end)
+ val++;
+
+ val_len= (uint) (val_end - val);
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;
+ /* Year */
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;
+ tmp= (char*) val + min(4, val_len);
+ l_time->year= (int) my_strtoll10(val, &tmp, &error);
+ val= tmp;
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;
+ tmp= (char*) val + min(2, val_len);
+ l_time->year= (int) my_strtoll10(val, &tmp, &error);
+ val= tmp;
l_time->year+= (l_time->year < YY_PART_YEAR ? 2000 : 1900);
- val_ptr+=2;
break;
+
+ /* Month */
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;
+ case 'c':
+ tmp= (char*) val + min(2, val_len);
+ l_time->month= (int) my_strtoll10(val, &tmp, &error);
+ val= tmp;
+ break;
+ case 'M':
+ case 'b':
+ if ((l_time->month= check_word(&month_names_typelib,
+ val, val_end, &val)) <= 0)
+ goto err;
break;
+ /* Day */
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;
+ case 'e':
+ tmp= (char*) val + min(2, val_len);
+ l_time->day= (int) my_strtoll10(val, &tmp, &error);
+ val= tmp;
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;
+ tmp= (char*) val + min(2, val_len);
+ l_time->day= (int) my_strtoll10(val, &tmp, &error);
+ /* Skip 'st, 'nd, 'th .. */
+ val= tmp + min((int) (end-tmp), 2);
+ break;
+
+ /* Hour */
+ case 'h':
+ case 'I':
+ case 'l':
+ usa_time= 1;
+ /* fall through */
+ case 'k':
+ case 'H':
+ tmp= (char*) val + min(2, val_len);
+ l_time->hour= (int) my_strtoll10(val, &tmp, &error);
+ val= tmp;
break;
+
+ /* Minute */
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;
+ tmp= (char*) val + min(2, val_len);
+ l_time->minute= (int) my_strtoll10(val, &tmp, &error);
+ val= tmp;
break;
+
+ /* Second */
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;
+ tmp= (char*) val + min(2, val_len);
+ l_time->second= (int) my_strtoll10(val, &tmp, &error);
+ val= tmp;
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;
+
+ /* Second part */
+ case 'f':
+ tmp= (char*) val_end;
+ l_time->second_part= my_strtoll10(val, &tmp, &error);
+ val= tmp;
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;
+
+ /* AM / PM */
+ case 'p':
+ if (val_len < 2 || ! usa_time)
+ goto err;
+ if (!my_strnncoll(&my_charset_latin1,
+ (const uchar *) val, 2,
+ (const uchar *) "PM", 2))
+ daypart= 12;
+ else if (my_strnncoll(&my_charset_latin1,
+ (const uchar *) val, 2,
+ (const uchar *) "AM", 2))
+ goto err;
break;
+
+ /* Exotic things */
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;
+ if ((weekday= check_word(&day_names_typelib, val, val_end, &val)) <= 0)
+ goto err;
break;
case 'w':
- weekday= my_strntoll(cs, val_ptr, 1, 10, &val_end1, &err);
- if (err)
- return 1;
- val_ptr++;
+ tmp= (char*) val + 1;
+ if ((weekday= (int) my_strtoll10(val, &tmp, &error)) <= 0 ||
+ weekday >= 7)
+ goto err;
+ val= tmp;
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;
- }
+ tmp= (char*) val + min(val_len, 3);
+ yearday= (int) my_strtoll10(val, &tmp, &error);
+ val= tmp;
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;
+ /* Fall through */
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;
+ tmp= (char*) val + min(val_len, 2);
+ week_number= (int) my_strtoll10(val, &tmp, &error);
+ val= tmp;
break;
+
default:
- if (*val_ptr != *ptr)
- return 1;
- val_ptr++;
+ goto err;
}
+ if (error) // Error from my_strtoll10
+ goto err;
}
- else
+ else if (!my_isspace(cs, *ptr))
{
- if (*val_ptr != *ptr)
- return 1;
- val_ptr++;
+ if (*val != *ptr)
+ goto err;
+ val++;
}
}
if (usa_time)
{
if (l_time->hour > 12 || l_time->hour < 1)
- return 1;
+ goto err;
l_time->hour= l_time->hour%12+daypart;
}
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 (days <= 0 || days >= MAX_DAY_NUMBER)
+ goto err;
+ get_date_from_daynr(days,&l_time->year,&l_time->month,&l_time->day);
}
if (week_number >= 0 && weekday)
@@ -337,7 +317,7 @@ bool extract_datetime(const char *str_val, uint str_val_len,
uint weekday_b;
if (weekday > 7 || weekday < 0)
- return 1;
+ goto err;
if (sunday_first)
weekday = weekday%7;
@@ -361,43 +341,43 @@ bool extract_datetime(const char *str_val, uint str_val_len,
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 (days <= 0 || days >= MAX_DAY_NUMBER)
+ goto err;
+ 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;
+ goto err;
DBUG_RETURN(0);
-}
+err:
+ DBUG_RETURN(1);
+}
/*
- Print datetime string from TIME struct
- according to format string.
+ Create a formated date/time value in a 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)
+bool make_date_time(DATE_TIME_FORMAT *format, TIME *l_time,
+ timestamp_type type, String *str)
{
char intbuff[15];
uint days_i;
uint hours_i;
uint weekday;
ulong length;
- if (set_len_to_zero)
- str->length(0);
+ const char *ptr, *end;
+
+ str->length(0);
+ str->set_charset(&my_charset_bin);
+
if (l_time->neg)
str->append("-", 1);
- const char *end=ptr+format_length;
+
+ end= (ptr= format->format.str) + format->format.length;
for (; ptr != end ; ptr++)
{
if (*ptr != '%' || ptr+1 == end)
@@ -407,29 +387,31 @@ String *make_datetime(String *str, TIME *l_time,
switch (*++ptr) {
case 'M':
if (!l_time->month)
- return 0;
+ return 1;
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);
+ return 1;
+ str->append(month_names[l_time->month-1],3);
break;
case 'W':
- if (is_time_only)
- return 0;
- weekday=calc_weekday(calc_daynr(l_time->year,l_time->month,l_time->day),0);
+ if (type == TIMESTAMP_TIME)
+ return 1;
+ weekday= calc_weekday(calc_daynr(l_time->year,l_time->month,
+ l_time->day),0);
str->append(day_names[weekday]);
break;
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);
+ if (type == TIMESTAMP_TIME)
+ return 1;
+ weekday=calc_weekday(calc_daynr(l_time->year,l_time->month,
+ l_time->day),0);
+ str->append(day_names[weekday],3);
break;
case 'D':
- if (is_time_only)
- return 0;
+ if (type == TIMESTAMP_TIME)
+ return 1;
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)
@@ -496,9 +478,10 @@ String *make_datetime(String *str, TIME *l_time,
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) -
+ if (type == TIMESTAMP_TIME)
+ return 1;
+ 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;
@@ -529,12 +512,6 @@ String *make_datetime(String *str, TIME *l_time,
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('.');
- 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,
@@ -549,8 +526,8 @@ String *make_datetime(String *str, TIME *l_time,
case 'u':
{
uint year;
- if (is_time_only)
- return 0;
+ if (type == TIMESTAMP_TIME)
+ return 1;
length= int10_to_str(calc_week(l_time, 0, (*ptr) == 'U', &year),
intbuff, 10) - intbuff;
str->append_with_prefill(intbuff, length, 2, '0');
@@ -560,8 +537,8 @@ String *make_datetime(String *str, TIME *l_time,
case 'V':
{
uint year;
- if (is_time_only)
- return 0;
+ if (type == TIMESTAMP_TIME)
+ return 1;
length= int10_to_str(calc_week(l_time, 1, (*ptr) == 'V', &year),
intbuff, 10) - intbuff;
str->append_with_prefill(intbuff, length, 2, '0');
@@ -571,27 +548,29 @@ String *make_datetime(String *str, TIME *l_time,
case 'X':
{
uint year;
- if (is_time_only)
- return 0;
+ if (type == TIMESTAMP_TIME)
+ return 1;
(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);
+ if (type == TIMESTAMP_TIME)
+ return 1;
+ 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;
+ return 0;
}
@@ -691,21 +670,24 @@ longlong Item_func_month::val_int()
return (longlong) ltime.month;
}
+
String* Item_func_monthname::val_str(String* str)
{
+ const char *name;
uint month=(uint) Item_func_month::val_int();
+
if (!month) // This is also true for NULL
{
null_value=1;
return (String*) 0;
}
null_value=0;
-
- String *m=&month_names[month-1];
- str->copy(m->ptr(), m->length(), m->charset(), default_charset());
+ name= month_names[month-1];
+ str->set(name, strlen(name), system_charset_info);
return str;
}
+
// Returns the quarter of the year
longlong Item_func_quarter::val_int()
@@ -785,14 +767,17 @@ longlong Item_func_weekday::val_int()
return (longlong) calc_weekday(tmp_value,odbc_type)+test(odbc_type);
}
+
String* Item_func_dayname::val_str(String* str)
{
uint weekday=(uint) val_int(); // Always Item_func_daynr()
+ const char *name;
+
if (null_value)
return (String*) 0;
- String *d=&day_names[weekday];
- str->copy(d->ptr(), d->length(), d->charset(), default_charset());
+ name= day_names[weekday];
+ str->set(name, strlen(name), system_charset_info);
return str;
}
@@ -808,7 +793,7 @@ longlong Item_func_year::val_int()
longlong Item_func_unix_timestamp::val_int()
{
if (arg_count == 0)
- return (longlong) thd->query_start();
+ return (longlong) current_thd->query_start();
if (args[0]->type() == FIELD_ITEM)
{ // Optimize timestamp field
Field *field=((Item_field*) args[0])->field;
@@ -820,7 +805,7 @@ longlong Item_func_unix_timestamp::val_int()
{
return 0; /* purecov: inspected */
}
- return (longlong) str_to_timestamp(str->ptr(),str->length(), thd);
+ return (longlong) str_to_timestamp(str->ptr(),str->length());
}
@@ -840,15 +825,18 @@ longlong Item_func_time_to_sec::val_int()
*/
static bool get_interval_value(Item *args,interval_type int_type,
- String *str_value, INTERVAL *t)
+ String *str_value, INTERVAL *interval)
{
long array[5],value;
const char *str;
uint32 length;
- LINT_INIT(value); LINT_INIT(str); LINT_INIT(length);
CHARSET_INFO *cs=str_value->charset();
- bzero((char*) t,sizeof(*t));
+ LINT_INIT(value);
+ LINT_INIT(str);
+ LINT_INIT(length);
+
+ bzero((char*) interval,sizeof(*interval));
if ((int) int_type <= INTERVAL_MICROSECOND)
{
value=(long) args->val_int();
@@ -856,7 +844,7 @@ static bool get_interval_value(Item *args,interval_type int_type,
return 1;
if (value < 0)
{
- t->neg=1;
+ interval->neg=1;
value= -value;
}
}
@@ -866,14 +854,14 @@ static bool get_interval_value(Item *args,interval_type int_type,
if (!(res=args->val_str(str_value)))
return (1);
- /* record negative intervalls in t->neg */
+ /* record negative intervalls in interval->neg */
str=res->ptr();
const char *end=str+res->length();
while (str != end && my_isspace(cs,*str))
str++;
if (str != end && *str == '-')
{
- t->neg=1;
+ interval->neg=1;
str++;
}
length=(uint32) (end-str); // Set up pointers to new str
@@ -881,101 +869,101 @@ static bool get_interval_value(Item *args,interval_type int_type,
switch (int_type) {
case INTERVAL_YEAR:
- t->year=value;
+ interval->year=value;
break;
case INTERVAL_MONTH:
- t->month=value;
+ interval->month=value;
break;
case INTERVAL_DAY:
- t->day=value;
+ interval->day=value;
break;
case INTERVAL_HOUR:
- t->hour=value;
+ interval->hour=value;
break;
case INTERVAL_MICROSECOND:
- t->second_part=value;
+ interval->second_part=value;
break;
case INTERVAL_MINUTE:
- t->minute=value;
+ interval->minute=value;
break;
case INTERVAL_SECOND:
- t->second=value;
+ interval->second=value;
break;
case INTERVAL_YEAR_MONTH: // Allow YEAR-MONTH YYYYYMM
if (get_interval_info(str,length,cs,2,array))
return (1);
- t->year=array[0];
- t->month=array[1];
+ interval->year=array[0];
+ interval->month=array[1];
break;
case INTERVAL_DAY_HOUR:
if (get_interval_info(str,length,cs,2,array))
return (1);
- t->day=array[0];
- t->hour=array[1];
+ interval->day=array[0];
+ interval->hour=array[1];
break;
case INTERVAL_DAY_MICROSECOND:
if (get_interval_info(str,length,cs,5,array))
return (1);
- t->day=array[0];
- t->hour=array[1];
- t->minute=array[2];
- t->second=array[3];
- t->second_part=array[4];
+ interval->day=array[0];
+ interval->hour=array[1];
+ interval->minute=array[2];
+ interval->second=array[3];
+ interval->second_part=array[4];
break;
case INTERVAL_DAY_MINUTE:
if (get_interval_info(str,length,cs,3,array))
return (1);
- t->day=array[0];
- t->hour=array[1];
- t->minute=array[2];
+ interval->day=array[0];
+ interval->hour=array[1];
+ interval->minute=array[2];
break;
case INTERVAL_DAY_SECOND:
if (get_interval_info(str,length,cs,4,array))
return (1);
- t->day=array[0];
- t->hour=array[1];
- t->minute=array[2];
- t->second=array[3];
+ interval->day=array[0];
+ interval->hour=array[1];
+ interval->minute=array[2];
+ interval->second=array[3];
break;
case INTERVAL_HOUR_MICROSECOND:
if (get_interval_info(str,length,cs,4,array))
return (1);
- t->hour=array[0];
- t->minute=array[1];
- t->second=array[2];
- t->second_part=array[3];
+ interval->hour=array[0];
+ interval->minute=array[1];
+ interval->second=array[2];
+ interval->second_part=array[3];
break;
case INTERVAL_HOUR_MINUTE:
if (get_interval_info(str,length,cs,2,array))
return (1);
- t->hour=array[0];
- t->minute=array[1];
+ interval->hour=array[0];
+ interval->minute=array[1];
break;
case INTERVAL_HOUR_SECOND:
if (get_interval_info(str,length,cs,3,array))
return (1);
- t->hour=array[0];
- t->minute=array[1];
- t->second=array[2];
+ interval->hour=array[0];
+ interval->minute=array[1];
+ interval->second=array[2];
break;
case INTERVAL_MINUTE_MICROSECOND:
if (get_interval_info(str,length,cs,3,array))
return (1);
- t->minute=array[0];
- t->second=array[1];
- t->second_part=array[2];
+ interval->minute=array[0];
+ interval->second=array[1];
+ interval->second_part=array[2];
break;
case INTERVAL_MINUTE_SECOND:
if (get_interval_info(str,length,cs,2,array))
return (1);
- t->minute=array[0];
- t->second=array[1];
+ interval->minute=array[0];
+ interval->second=array[1];
break;
case INTERVAL_SECOND_MICROSECOND:
if (get_interval_info(str,length,cs,2,array))
return (1);
- t->second=array[0];
- t->second_part=array[1];
+ interval->second=array[0];
+ interval->second_part=array[1];
break;
}
return 0;
@@ -984,34 +972,33 @@ 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)
- goto null_date;
+ return (String*) 0;
+
+ if (str->alloc(11))
+ {
+ null_value= 1;
+ return (String *) 0;
+ }
ltime.year= (value/10000L) % 10000;
ltime.month= (value/100)%100;
ltime.day= (value%100);
- ltime.neg=0;
+ ltime.neg= 0;
ltime.time_type=TIMESTAMP_DATE;
- 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;
+ make_date((DATE_TIME_FORMAT *) 0, &ltime, str);
+ return str;
}
int Item_date::save_in_field(Field *field, bool no_conversions)
{
TIME ltime;
- timestamp_type t_type=TIMESTAMP_FULL;
- if (get_date(&ltime,1))
+ timestamp_type t_type=TIMESTAMP_DATETIME;
+ if (get_date(&ltime, TIME_FUZZY_DATE))
{
if (null_value)
return set_field_to_null(field);
@@ -1039,11 +1026,11 @@ void Item_func_curdate::fix_length_and_dec()
{
struct tm start;
- collation.set(default_charset());
+ collation.set(&my_charset_bin);
decimals=0;
- max_length=10*default_charset()->mbmaxlen;
+ max_length=MAX_DATE_WIDTH*MY_CHARSET_BIN_MB_MAXLEN;
- store_now_in_tm(thd->query_start(),&start);
+ store_now_in_tm(current_thd->query_start(),&start);
value=(longlong) ((ulong) ((uint) start.tm_year+1900)*10000L+
((uint) start.tm_mon+1)*100+
@@ -1062,7 +1049,7 @@ void Item_func_curdate::fix_length_and_dec()
bool Item_func_curdate::get_date(TIME *res,
- bool fuzzy_date __attribute__((unused)))
+ uint fuzzy_date __attribute__((unused)))
{
*res=ltime;
return 0;
@@ -1091,19 +1078,19 @@ void Item_func_curdate_utc::store_now_in_tm(time_t now, struct tm *now_tm)
String *Item_func_curtime::val_str(String *str)
{
- str_value.set(buff,buff_length,default_charset());
+ str_value.set(buff, buff_length, &my_charset_bin);
return &str_value;
}
+
void Item_func_curtime::fix_length_and_dec()
{
struct tm start;
- DATETIME_FORMAT *tmp_format;
- String tmp((char*) buff,sizeof(buff),default_charset());
+ String tmp((char*) buff,sizeof(buff), &my_charset_bin);
TIME ltime;
decimals=0;
- store_now_in_tm(thd->query_start(),&start);
+ store_now_in_tm(current_thd->query_start(),&start);
value=(longlong) ((ulong) ((uint) start.tm_hour)*10000L+
(ulong) (((uint) start.tm_min)*100L+
(uint) start.tm_sec));
@@ -1113,12 +1100,8 @@ void Item_func_curtime::fix_length_and_dec()
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;
+ make_time((DATE_TIME_FORMAT *) 0, &ltime, &tmp);
+ max_length= buff_length= tmp.length();
}
@@ -1144,7 +1127,7 @@ void Item_func_curtime_utc::store_now_in_tm(time_t now, struct tm *now_tm)
String *Item_func_now::val_str(String *str)
{
- str_value.set(buff,buff_length,default_charset());
+ str_value.set(buff,buff_length, &my_charset_bin);
return &str_value;
}
@@ -1152,11 +1135,12 @@ String *Item_func_now::val_str(String *str)
void Item_func_now::fix_length_and_dec()
{
struct tm start;
- DATETIME_FORMAT *tmp_format;
String tmp((char*) buff,sizeof(buff),&my_charset_bin);
-
+
decimals=0;
- store_now_in_tm(thd->query_start(),&start);
+ collation.set(&my_charset_bin);
+
+ store_now_in_tm(current_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+
@@ -1173,17 +1157,15 @@ void Item_func_now::fix_length_and_dec()
ltime.second= start.tm_sec;
ltime.second_part= 0;
ltime.neg= 0;
- ltime.time_type= TIMESTAMP_FULL;
+ ltime.time_type= TIMESTAMP_DATETIME;
- 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;
+ make_datetime((DATE_TIME_FORMAT *) 0, &ltime, &tmp);
+ max_length= buff_length= tmp.length();
}
+
bool Item_func_now::get_date(TIME *res,
- bool fuzzy_date __attribute__((unused)))
+ uint fuzzy_date __attribute__((unused)))
{
*res=ltime;
return 0;
@@ -1193,7 +1175,7 @@ bool Item_func_now::get_date(TIME *res,
int Item_func_now::save_in_field(Field *to, bool no_conversions)
{
to->set_notnull();
- to->store_time(&ltime,TIMESTAMP_FULL);
+ to->store_time(&ltime,TIMESTAMP_DATETIME);
return 0;
}
@@ -1222,12 +1204,13 @@ String *Item_func_sec_to_time::val_str(String *str)
{
longlong seconds=(longlong) args[0]->val_int();
uint sec;
-
- DATETIME_FORMAT *tmp_format;
TIME ltime;
- if ((null_value=args[0]->null_value))
- goto null_date;
+ if ((null_value=args[0]->null_value) || str->alloc(19))
+ {
+ null_value= 1;
+ return (String*) 0;
+ }
ltime.neg= 0;
if (seconds < 0)
@@ -1242,14 +1225,8 @@ String *Item_func_sec_to_time::val_str(String *str)
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;
+ make_time((DATE_TIME_FORMAT *) 0, &ltime, str);
+ return str;
}
@@ -1359,9 +1336,9 @@ String *Item_func_date_format::val_str(String *str)
{
String *format;
TIME l_time;
- uint size,weekday;
+ uint size;
- if (!date_or_time)
+ if (!is_time_format)
{
if (get_arg0_date(&l_time,1))
return 0;
@@ -1369,10 +1346,8 @@ String *Item_func_date_format::val_str(String *str)
else
{
String *res;
- if (!(res=args[0]->val_str(str)))
- goto null_date;
-
- if (str_to_time(res->ptr(),res->length(),&l_time, thd))
+ if (!(res=args[0]->val_str(str)) ||
+ (str_to_time(res->ptr(),res->length(),&l_time)))
goto null_date;
l_time.year=l_time.month=l_time.day=0;
@@ -1391,10 +1366,13 @@ String *Item_func_date_format::val_str(String *str)
if (str->alloc(size))
goto null_date;
+ DATE_TIME_FORMAT date_time_format;
+ date_time_format.format.str= (char*) format->ptr();
+ date_time_format.format.length= format->length();
/* Create the result string */
- if (make_datetime(str, &l_time, 0, 0,
- format->ptr(), format->length(), 1))
+ if (!make_date_time(&date_time_format, &l_time,
+ is_time_format ? TIMESTAMP_TIME : TIMESTAMP_DATE, str))
return str;
null_date:
@@ -1406,10 +1384,8 @@ null_date:
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();
+ CHARSET_INFO *cs= &my_charset_bin;
TIME ltime;
if ((null_value=args[0]->null_value))
@@ -1427,14 +1403,13 @@ String *Item_func_from_unixtime::val_str(String *str)
ltime.second_part= 0;
ltime.neg=0;
- l=20*cs->mbmaxlen+32;
- 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;
+ if (str->alloc(20*MY_CHARSET_BIN_MB_MAXLEN))
+ goto null_date;
+ make_datetime((DATE_TIME_FORMAT *) 0, &ltime, str);
+ return str;
+
null_date:
+ null_value=1;
return 0;
}
@@ -1456,7 +1431,7 @@ longlong Item_func_from_unixtime::val_int()
}
bool Item_func_from_unixtime::get_date(TIME *ltime,
- bool fuzzy_date __attribute__((unused)))
+ uint fuzzy_date __attribute__((unused)))
{
time_t tmp=(time_t) (ulong) args[0]->val_int();
if ((null_value=args[0]->null_value))
@@ -1479,10 +1454,11 @@ bool Item_func_from_unixtime::get_date(TIME *ltime,
void Item_date_add_interval::fix_length_and_dec()
{
enum_field_types arg0_field_type;
- collation.set(default_charset());
+
+ collation.set(&my_charset_bin);
maybe_null=1;
- max_length=26*MY_CHARSET_BIN_MB_MAXLEN;
- value.alloc(32);
+ max_length=MAX_DATETIME_FULL_WIDTH*MY_CHARSET_BIN_MB_MAXLEN;
+ value.alloc(max_length);
/*
The field type for the result of an Item_date function is defined as
@@ -1512,10 +1488,11 @@ void Item_date_add_interval::fix_length_and_dec()
/* Here arg[1] is a Item_interval object */
-bool Item_date_add_interval::get_date(TIME *ltime, bool fuzzy_date)
+bool Item_date_add_interval::get_date(TIME *ltime, uint 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))
@@ -1541,7 +1518,7 @@ bool Item_date_add_interval::get_date(TIME *ltime, bool fuzzy_date)
case INTERVAL_DAY_MINUTE:
case INTERVAL_DAY_HOUR:
long sec,days,daynr,microseconds,extra_sec;
- ltime->time_type=TIMESTAMP_FULL; // Return full date
+ ltime->time_type=TIMESTAMP_DATETIME; // Return full date
microseconds= ltime->second_part + sign*interval.second_part;
extra_sec= microseconds/1000000L;
microseconds= microseconds%1000000L;
@@ -1616,23 +1593,26 @@ bool Item_date_add_interval::get_date(TIME *ltime, bool fuzzy_date)
String *Item_date_add_interval::val_str(String *str)
{
TIME ltime;
- DATETIME_FORMAT *tmp_format;
+ enum date_time_format_types format;
if (Item_date_add_interval::get_date(&ltime,0))
return 0;
if (ltime.time_type == TIMESTAMP_DATE)
- tmp_format= &t_datetime_frm(thd, DATE_FORMAT_TYPE).datetime_format;
- else
- 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))
+ format= DATE_ONLY;
+ else if (ltime.second_part)
+ format= DATE_TIME_MICROSECOND;
+ else
+ format= DATE_TIME;
+
+ if (!make_datetime(format, &ltime, str))
return str;
null_value=1;
return 0;
}
+
longlong Item_date_add_interval::val_int()
{
TIME ltime;
@@ -1715,7 +1695,7 @@ longlong Item_extract::val_int()
else
{
String *res= args[0]->val_str(&value);
- if (!res || str_to_time(res->ptr(),res->length(),&ltime, thd))
+ if (!res || str_to_time(res->ptr(),res->length(),&ltime))
{
null_value=1;
return 0;
@@ -1864,15 +1844,13 @@ void Item_char_typecast::fix_length_and_dec()
max_length= char_length * cast_cs->mbmaxlen;
}
+
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, 1, ltime.second_part,
- tmp_format->format, tmp_format->format_length, 1))
+ !make_datetime(ltime.second_part ? DATE_TIME_MICROSECOND : DATE_TIME,
+ &ltime, str))
return str;
null_date:
@@ -1892,12 +1870,10 @@ 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, 0, ltime.second_part,
- tmp_format->format, tmp_format->format_length, 1))
+ !make_datetime(ltime.second_part ? TIME_MICROSECOND : TIME_ONLY,
+ &ltime, str))
return str;
null_value=1;
@@ -1905,7 +1881,7 @@ String *Item_time_typecast::val_str(String *str)
}
-bool Item_date_typecast::get_date(TIME *ltime, bool fuzzy_date)
+bool Item_date_typecast::get_date(TIME *ltime, uint fuzzy_date)
{
bool res= get_arg0_date(ltime,1);
ltime->time_type= TIMESTAMP_DATE;
@@ -1916,19 +1892,18 @@ 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, 1, 0,
- tmp_format->format, tmp_format->format_length, 1))
- return str;
+ if (!get_arg0_date(&ltime,1) && !str->alloc(11))
+ {
+ make_date((DATE_TIME_FORMAT *) 0,&ltime, str);
+ return str;
+ }
-null_date:
null_value=1;
return 0;
}
+
/*
MAKEDATE(a,b) is a date function that creates a date value
from a year and day value.
@@ -1943,22 +1918,21 @@ String *Item_func_makedate::val_str(String *str)
if (args[0]->null_value || args[1]->null_value ||
yearnr < 0 || daynr <= 0)
- goto null_date;
+ goto err;
days= calc_daynr(yearnr,1,1) + daynr - 1;
- if (days > 0 || days < MAX_DAY_NUMBER) // Day number from year 0 to 9999-12-31
+ // Day number from year 0 to 9999-12-31
+ if (days >= 0 && days < MAX_DAY_NUMBER)
{
null_value=0;
get_date_from_daynr(days,&l_time.year,&l_time.month,&l_time.day);
-
- 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;
+ if (str->alloc(11))
+ goto err;
+ make_date((DATE_TIME_FORMAT *) 0, &l_time, str);
+ return str;
}
-null_date:
+err:
null_value=1;
return 0;
}
@@ -1968,11 +1942,11 @@ void Item_func_add_time::fix_length_and_dec()
{
enum_field_types arg0_field_type;
decimals=0;
- max_length=26*MY_CHARSET_BIN_MB_MAXLEN;
+ max_length=MAX_DATETIME_FULL_WIDTH*MY_CHARSET_BIN_MB_MAXLEN;
/*
- The field type for the result of an Item_func_add_time function is defined as
- follows:
+ The field type for the result of an Item_func_add_time function is defined
+ as follows:
- If first arg is a MYSQL_TYPE_DATETIME or MYSQL_TYPE_TIMESTAMP
result is MYSQL_TYPE_DATETIME
@@ -1991,7 +1965,8 @@ void Item_func_add_time::fix_length_and_dec()
}
/*
- ADDTIME(t,a) and SUBTIME(t,a) are time functions that calculate a time/datetime value
+ ADDTIME(t,a) and SUBTIME(t,a) are time functions that calculate a
+ time/datetime value
t: time_or_datetime_expression
a: time_expression
@@ -2005,7 +1980,6 @@ 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;
@@ -2021,7 +1995,7 @@ String *Item_func_add_time::val_str(String *str)
{
if (args[0]->get_time(&l_time1) ||
args[1]->get_time(&l_time2) ||
- l_time2.time_type == TIMESTAMP_FULL)
+ l_time2.time_type == TIMESTAMP_DATETIME)
goto null_date;
is_time= (l_time1.time_type == TIMESTAMP_TIME);
if (is_time && (l_time2.neg == l_time1.neg && l_time1.neg))
@@ -2037,7 +2011,8 @@ String *Item_func_add_time::val_str(String *str)
if (is_time)
seconds+= l_time1.day*86400L;
else
- days+= calc_daynr((uint) l_time1.year,(uint) l_time1.month, (uint) l_time1.day);
+ days+= calc_daynr((uint) l_time1.year,(uint) l_time1.month,
+ (uint) l_time1.day);
seconds= seconds + microseconds/1000000L;
microseconds= microseconds%1000000L;
days+= seconds/86400L;
@@ -2070,21 +2045,19 @@ 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, 1,
- l_time1.second_part || l_time2.second_part,
- tmp_format->format, tmp_format->format_length, 1))
+ !make_datetime(l_time1.second_part || l_time2.second_part ?
+ DATE_TIME_MICROSECOND : DATE_TIME,
+ &l_time3, str))
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, 0,
- l_time1.second_part || l_time2.second_part,
- tmp_format->format, tmp_format->format_length, 1))
+ if (!make_datetime(l_time1.second_part || l_time2.second_part ?
+ TIME_MICROSECOND : TIME_ONLY,
+ &l_time3, str))
return str;
null_date:
@@ -2129,7 +2102,6 @@ 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) ||
@@ -2176,10 +2148,9 @@ String *Item_func_timediff::val_str(String *str)
calc_time_from_sec(&l_time3, seconds, microseconds);
- 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))
+ if (!make_datetime(l_time1.second_part || l_time2.second_part ?
+ TIME_MICROSECOND : TIME_ONLY,
+ &l_time3, str))
return str;
null_date:
@@ -2196,7 +2167,6 @@ null_date:
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();
@@ -2206,8 +2176,9 @@ String *Item_func_maketime::val_str(String *str)
args[1]->null_value ||
args[2]->null_value ||
minute > 59 || minute < 0 ||
- second > 59 || second < 0)))
- goto null_date;
+ second > 59 || second < 0 ||
+ str->alloc(19))))
+ return 0;
ltime.neg= 0;
if (hour < 0)
@@ -2218,21 +2189,19 @@ String *Item_func_maketime::val_str(String *str)
ltime.hour= (ulong)hour;
ltime.minute= (ulong)minute;
ltime.second= (ulong)second;
- 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:
- return 0;
+ make_time((DATE_TIME_FORMAT *) 0, &ltime, str);
+ return str;
}
+
/*
- MICROSECOND(a) is a function ( extraction) that extracts the microseconds from a.
+ MICROSECOND(a) is a function ( extraction) that extracts the microseconds
+ from a.
a: Datetime or time value
Result: int value
*/
+
longlong Item_func_microsecond::val_int()
{
TIME ltime;
@@ -2241,78 +2210,103 @@ longlong Item_func_microsecond::val_int()
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];
+ const char *format_name;
+ KNOWN_DATE_TIME_FORMAT *format;
+ String *val= args[0]->val_str(str);
+ ulong val_len;
- if (!args[0]->null_value)
+ if ((null_value= args[0]->null_value))
+ return 0;
+
+ val_len= val->length();
+ for (format= &known_date_time_formats[0];
+ (format_name= format->format_name);
+ format++)
{
- const char *val_ptr= val->ptr();
- uint val_len= val->length();
- for (int i= 0; i < 5; i++)
+ uint format_name_len;
+ format_name_len= strlen(format_name);
+ if (val_len == format_name_len &&
+ !my_strnncoll(&my_charset_latin1,
+ (const uchar *) val->ptr(), val_len,
+ (const uchar *) format_name, val_len))
{
- 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;
- }
+ const char *format_str= get_date_time_format_str(format, type);
+ str->set(format_str, strlen(format_str), &my_charset_bin);
+ return str;
}
}
+ null_value= 1;
+ return 0;
+}
+
+
+void Item_func_get_format::print(String *str)
+{
+ str->append(func_name());
+ str->append('(');
+
+ switch (type) {
+ case TIMESTAMP_DATE:
+ str->append("DATE, ");
+ break;
+ case TIMESTAMP_DATETIME:
+ str->append("DATETIME, ");
+ break;
+ case TIMESTAMP_TIME:
+ str->append("TIME, ");
+ break;
+ default:
+ DBUG_ASSERT(0);
+ }
+ args[0]->print(str);
+ str->append(')');
+}
+
+
+bool Item_func_str_to_date::get_date(TIME *ltime, uint fuzzy_date)
+{
+ DATE_TIME_FORMAT date_time_format;
+ char val_buff[64], format_buff[64];
+ String val_str(val_buff, sizeof(val_buff), &my_charset_bin), *val;
+ String format_str(format_buff, sizeof(format_buff), &my_charset_bin), *format;
+
+ val= args[0]->val_str(&val_str);
+ format= args[1]->val_str(&format_str);
+ if (args[0]->null_value || args[1]->null_value)
+ goto null_date;
+
null_value= 0;
- str->length(0);
- str->append(format_str);
- return str;
+ bzero((char*) ltime, sizeof(ltime));
+ date_time_format.format.str= (char*) format->ptr();
+ date_time_format.format.length= format->length();
+ if (extract_date_time(&date_time_format, val->ptr(), val->length(),
+ ltime))
+ goto null_date;
+ return 0;
+
+null_date:
+ return (null_value=1);
}
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;
+ if (Item_func_str_to_date::get_date(&ltime, TIME_FUZZY_DATE))
+ return 0;
-null_date:
- null_value=1;
+ /*
+ The following DATE_TIME should be done dynamicly based on the
+ format string (wen it's a constant). For example, we should only return
+ microseconds if there was an %f in the format
+ */
+ if (!make_datetime(ltime.second_part ? DATE_TIME_MICROSECOND : DATE_TIME,
+ &ltime, str))
+ return str;
return 0;
}
diff --git a/sql/item_timefunc.h b/sql/item_timefunc.h
index af71322ff0c..ef7fa1abfa0 100644
--- a/sql/item_timefunc.h
+++ b/sql/item_timefunc.h
@@ -29,7 +29,7 @@ public:
const char *func_name() const { return "period_add"; }
void fix_length_and_dec()
{
- max_length=6*default_charset()->mbmaxlen;
+ max_length=6*MY_CHARSET_BIN_MB_MAXLEN;
}
};
@@ -43,7 +43,7 @@ public:
void fix_length_and_dec()
{
decimals=0;
- max_length=6*default_charset()->mbmaxlen;
+ max_length=6*MY_CHARSET_BIN_MB_MAXLEN;
}
};
@@ -57,7 +57,7 @@ public:
void fix_length_and_dec()
{
decimals=0;
- max_length=6*default_charset()->mbmaxlen;
+ max_length=6*MY_CHARSET_BIN_MB_MAXLEN;
maybe_null=1;
}
};
@@ -72,7 +72,7 @@ public:
void fix_length_and_dec()
{
decimals=0;
- max_length=2*default_charset()->mbmaxlen;
+ max_length=2*MY_CHARSET_BIN_MB_MAXLEN;
maybe_null=1;
}
};
@@ -86,16 +86,16 @@ public:
double val() { return (double) Item_func_month::val_int(); }
String *val_str(String *str)
{
- str->set(val_int(), default_charset());
+ str->set(val_int(), &my_charset_bin);
return null_value ? 0 : str;
}
const char *func_name() const { return "month"; }
enum Item_result result_type () const { return INT_RESULT; }
void fix_length_and_dec()
{
- collation.set(default_charset());
+ collation.set(&my_charset_bin);
decimals=0;
- max_length=2*default_charset()->mbmaxlen;
+ max_length=2*MY_CHARSET_BIN_MB_MAXLEN;
maybe_null=1;
}
};
@@ -110,9 +110,9 @@ public:
enum Item_result result_type () const { return STRING_RESULT; }
void fix_length_and_dec()
{
- collation.set(default_charset());
+ collation.set(&my_charset_bin);
decimals=0;
- max_length=10*default_charset()->mbmaxlen;
+ max_length=10*my_charset_bin.mbmaxlen;
maybe_null=1;
}
};
@@ -127,7 +127,7 @@ public:
void fix_length_and_dec()
{
decimals=0;
- max_length=3*default_charset()->mbmaxlen;
+ max_length=3*MY_CHARSET_BIN_MB_MAXLEN;
maybe_null=1;
}
};
@@ -142,7 +142,7 @@ public:
void fix_length_and_dec()
{
decimals=0;
- max_length=2*default_charset()->mbmaxlen;
+ max_length=2*MY_CHARSET_BIN_MB_MAXLEN;
maybe_null=1;
}
};
@@ -157,7 +157,7 @@ public:
void fix_length_and_dec()
{
decimals=0;
- max_length=2*default_charset()->mbmaxlen;
+ max_length=2*MY_CHARSET_BIN_MB_MAXLEN;
maybe_null=1;
}
};
@@ -172,7 +172,7 @@ public:
void fix_length_and_dec()
{
decimals=0;
- max_length=1*default_charset()->mbmaxlen;
+ max_length=1*MY_CHARSET_BIN_MB_MAXLEN;
maybe_null=1;
}
};
@@ -187,7 +187,7 @@ public:
void fix_length_and_dec()
{
decimals=0;
- max_length=2*default_charset()->mbmaxlen;
+ max_length=2*MY_CHARSET_BIN_MB_MAXLEN;
maybe_null=1;
}
};
@@ -202,7 +202,7 @@ public:
void fix_length_and_dec()
{
decimals=0;
- max_length=2*default_charset()->mbmaxlen;
+ max_length=2*MY_CHARSET_BIN_MB_MAXLEN;
maybe_null=1;
}
};
@@ -216,7 +216,7 @@ public:
void fix_length_and_dec()
{
decimals=0;
- max_length=6*default_charset()->mbmaxlen;
+ max_length=6*MY_CHARSET_BIN_MB_MAXLEN;
maybe_null=1;
}
};
@@ -231,7 +231,7 @@ public:
void fix_length_and_dec()
{
decimals=0;
- max_length=4*default_charset()->mbmaxlen;
+ max_length=4*MY_CHARSET_BIN_MB_MAXLEN;
maybe_null=1;
}
};
@@ -247,16 +247,16 @@ public:
double val() { return (double) val_int(); }
String *val_str(String *str)
{
- str->set(val_int(), default_charset());
+ str->set(val_int(), &my_charset_bin);
return null_value ? 0 : str;
}
const char *func_name() const { return "weekday"; }
enum Item_result result_type () const { return INT_RESULT; }
void fix_length_and_dec()
{
- collation.set(default_charset());
+ collation.set(&my_charset_bin);
decimals=0;
- max_length=1*default_charset()->mbmaxlen;
+ max_length=1*MY_CHARSET_BIN_MB_MAXLEN;
maybe_null=1;
}
};
@@ -270,9 +270,9 @@ class Item_func_dayname :public Item_func_weekday
enum Item_result result_type () const { return STRING_RESULT; }
void fix_length_and_dec()
{
- collation.set(default_charset());
+ collation.set(&my_charset_bin);
decimals=0;
- max_length=9*default_charset()->mbmaxlen;
+ max_length=9*MY_CHARSET_BIN_MB_MAXLEN;
maybe_null=1;
}
};
@@ -289,7 +289,7 @@ public:
void fix_length_and_dec()
{
decimals=0;
- max_length=10*default_charset()->mbmaxlen;
+ max_length=10*MY_CHARSET_BIN_MB_MAXLEN;
}
};
@@ -303,7 +303,7 @@ public:
void fix_length_and_dec()
{
decimals=0;
- max_length=10*default_charset()->mbmaxlen;
+ max_length=10*MY_CHARSET_BIN_MB_MAXLEN;
}
};
@@ -322,14 +322,14 @@ public:
const char *func_name() const { return "date"; }
void fix_length_and_dec()
{
- collation.set(default_charset());
+ collation.set(&my_charset_bin);
decimals=0;
- max_length=10*default_charset()->mbmaxlen;
+ max_length=MAX_DATE_WIDTH*MY_CHARSET_BIN_MB_MAXLEN;
}
int save_in_field(Field *to, bool no_conversions);
Field *tmp_table_field(TABLE *t_arg)
{
- return (new Field_date(maybe_null, name, t_arg, default_charset()));
+ return (new Field_date(maybe_null, name, t_arg, &my_charset_bin));
}
};
@@ -343,7 +343,7 @@ public:
enum_field_types field_type() const { return MYSQL_TYPE_DATETIME; }
Field *tmp_table_field(TABLE *t_arg)
{
- return (new Field_datetime(maybe_null, name, t_arg, default_charset()));
+ return (new Field_datetime(maybe_null, name, t_arg, &my_charset_bin));
}
};
@@ -366,7 +366,7 @@ public:
void fix_length_and_dec();
Field *tmp_table_field(TABLE *t_arg)
{
- return (new Field_time(maybe_null, name, t_arg, default_charset()));
+ return (new Field_time(maybe_null, name, t_arg, &my_charset_bin));
}
/*
Abstract method that defines which time zone is used for conversion.
@@ -408,7 +408,7 @@ public:
void set_result_from_tm(struct tm *now);
longlong val_int() { return (value) ; }
void fix_length_and_dec();
- bool get_date(TIME *res,bool fuzzy_date);
+ bool get_date(TIME *res, uint fuzzy_date);
virtual void store_now_in_tm(time_t now, struct tm *now_tm)=0;
};
@@ -448,7 +448,7 @@ public:
int save_in_field(Field *to, bool no_conversions);
String *val_str(String *str);
void fix_length_and_dec();
- bool get_date(TIME *res,bool fuzzy_date);
+ bool get_date(TIME *res, uint fuzzy_date);
virtual void store_now_in_tm(time_t now, struct tm *now_tm)=0;
};
@@ -485,11 +485,11 @@ public:
class Item_func_date_format :public Item_str_func
{
int fixed_length;
- const bool date_or_time;
+ const bool is_time_format;
String value;
public:
- Item_func_date_format(Item *a,Item *b,bool date_or_time_arg)
- :Item_str_func(a,b),date_or_time(date_or_time_arg) {}
+ Item_func_date_format(Item *a,Item *b,bool is_time_format_arg)
+ :Item_str_func(a,b),is_time_format(is_time_format_arg) {}
String *val_str(String *str);
const char *func_name() const { return "date_format"; }
void fix_length_and_dec();
@@ -507,11 +507,11 @@ class Item_func_from_unixtime :public Item_date_func
const char *func_name() const { return "from_unixtime"; }
void fix_length_and_dec()
{
- collation.set(default_charset());
+ collation.set(&my_charset_bin);
decimals=0;
- max_length=19*default_charset()->mbmaxlen;
+ max_length=MAX_DATETIME_WIDTH*MY_CHARSET_BIN_MB_MAXLEN;
}
- bool get_date(TIME *res,bool fuzzy_date);
+ bool get_date(TIME *res, uint fuzzy_date);
};
@@ -524,15 +524,15 @@ public:
String *val_str(String *);
void fix_length_and_dec()
{
- collation.set(default_charset());
+ collation.set(&my_charset_bin);
maybe_null=1;
- max_length=13*default_charset()->mbmaxlen;
+ max_length=MAX_TIME_WIDTH*MY_CHARSET_BIN_MB_MAXLEN;
}
enum_field_types field_type() const { return MYSQL_TYPE_TIME; }
const char *func_name() const { return "sec_to_time"; }
Field *tmp_table_field(TABLE *t_arg)
{
- return (new Field_time(maybe_null, name, t_arg, default_charset()));
+ return (new Field_time(maybe_null, name, t_arg, &my_charset_bin));
}
};
@@ -567,7 +567,7 @@ public:
enum_field_types field_type() const { return cached_field_type; }
double val() { return (double) val_int(); }
longlong val_int();
- bool get_date(TIME *res,bool fuzzy_date);
+ bool get_date(TIME *res, uint fuzzy_date);
void print(String *str);
};
@@ -602,7 +602,7 @@ public:
}
void fix_length_and_dec()
{
- collation.set(default_charset());
+ collation.set(&my_charset_bin);
max_length=args[0]->max_length;
}
virtual const char* cast_type() const= 0;
@@ -631,12 +631,12 @@ class Item_date_typecast :public Item_typecast
public:
Item_date_typecast(Item *a) :Item_typecast(a) {}
String *val_str(String *str);
- bool get_date(TIME *ltime, bool fuzzy_date);
+ bool get_date(TIME *ltime, uint fuzzy_date);
const char *cast_type() const { return "date"; }
enum_field_types field_type() const { return MYSQL_TYPE_DATE; }
Field *tmp_table_field(TABLE *t_arg)
{
- return (new Field_date(maybe_null, name, t_arg, default_charset()));
+ return (new Field_date(maybe_null, name, t_arg, &my_charset_bin));
}
};
@@ -651,7 +651,7 @@ public:
enum_field_types field_type() const { return MYSQL_TYPE_TIME; }
Field *tmp_table_field(TABLE *t_arg)
{
- return (new Field_time(maybe_null, name, t_arg, default_charset()));
+ return (new Field_time(maybe_null, name, t_arg, &my_charset_bin));
}
};
@@ -665,7 +665,7 @@ public:
enum_field_types field_type() const { return MYSQL_TYPE_DATETIME; }
Field *tmp_table_field(TABLE *t_arg)
{
- return (new Field_datetime(maybe_null, name, t_arg, default_charset()));
+ return (new Field_datetime(maybe_null, name, t_arg, &my_charset_bin));
}
};
@@ -679,7 +679,7 @@ public:
void fix_length_and_dec()
{
decimals=0;
- max_length=8*MY_CHARSET_BIN_MB_MAXLEN;
+ max_length=MAX_DATE_WIDTH*MY_CHARSET_BIN_MB_MAXLEN;
}
Field *tmp_table_field(TABLE *t_arg)
{
@@ -728,7 +728,7 @@ public:
void fix_length_and_dec()
{
decimals=0;
- max_length=17*MY_CHARSET_BIN_MB_MAXLEN;
+ max_length=MAX_TIME_WIDTH*MY_CHARSET_BIN_MB_MAXLEN;
}
Field *tmp_table_field(TABLE *t_arg)
{
@@ -747,11 +747,11 @@ public:
void fix_length_and_dec()
{
decimals=0;
- max_length=8*MY_CHARSET_BIN_MB_MAXLEN;
+ max_length=MAX_TIME_WIDTH*MY_CHARSET_BIN_MB_MAXLEN;
}
Field *tmp_table_field(TABLE *t_arg)
{
- return (new Field_time(maybe_null, name, t_arg, &my_charset_bin));
+ return (new Field_time(maybe_null, name, t_arg, &my_charset_bin));
}
};
@@ -769,44 +769,43 @@ public:
};
-enum datetime_format
+enum date_time_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;
+ const timestamp_type type;
public:
- Item_func_get_format(datetime_format_types type_arg1, Item *a)
- :Item_str_func(a), tm_format(type_arg1) {}
+ Item_func_get_format(timestamp_type type_arg, Item *a)
+ :Item_str_func(a), type(type_arg)
+ {}
String *val_str(String *str);
const char *func_name() const { return "get_format"; }
void fix_length_and_dec()
{
+ maybe_null= 1;
decimals=0;
max_length=17*MY_CHARSET_BIN_MB_MAXLEN;
}
+ void print(String *str);
};
-class Item_func_str_to_date :public Item_str_func
+class Item_func_str_to_date :public Item_date_func
{
public:
Item_func_str_to_date(Item *a, Item *b)
- :Item_str_func(a, b) {}
+ :Item_date_func(a, b)
+ {}
String *val_str(String *str);
+ bool get_date(TIME *ltime, uint fuzzy_date);
const char *func_name() const { return "str_to_date"; }
void fix_length_and_dec()
{
+ maybe_null= 1;
decimals=0;
- max_length=29*MY_CHARSET_BIN_MB_MAXLEN;
+ max_length=MAX_DATETIME_FULL_WIDTH*MY_CHARSET_BIN_MB_MAXLEN;
}
};
diff --git a/sql/mysql_priv.h b/sql/mysql_priv.h
index f71fca29f56..12c772e7253 100644
--- a/sql/mysql_priv.h
+++ b/sql/mysql_priv.h
@@ -756,6 +756,13 @@ bool open_log(MYSQL_LOG *log, const char *hostname,
/* mysqld.cc */
extern void yyerror(const char*);
+/* strfunc.cc */
+ulonglong find_set(TYPELIB *typelib,const char *x, uint length,
+ char **err_pos, uint *err_len, bool *set_warning);
+uint find_type(TYPELIB *lib, const char *find, uint length, bool part_match);
+uint check_word(TYPELIB *lib, const char *val, const char *end,
+ const char **end_of_word);
+
/*
External variables
*/
@@ -849,7 +856,6 @@ extern pthread_attr_t connection_attrib;
extern I_List<THD> threads;
extern I_List<NAMED_LIST> key_caches;
extern MY_BITMAP temp_pool;
-extern DATE_FORMAT dayord;
extern String my_empty_string;
extern String my_null_string;
extern SHOW_VAR init_vars[],status_vars[], internal_vars[];
@@ -861,12 +867,8 @@ 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 const char *opt_date_time_formats[];
+extern KNOWN_DATE_TIME_FORMAT known_date_time_formats[];
extern String null_string;
extern HASH open_cache;
@@ -938,23 +940,26 @@ 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, 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);
+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, uint fuzzy_date);
timestamp_type str_to_TIME(const char *str, uint length, TIME *l_time,
- bool fuzzy_date, THD *thd);
+ uint flags);
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);
+extern DATE_TIME_FORMAT *date_time_format_make(timestamp_type format_type,
+ const char *format_str,
+ uint format_length);
+extern DATE_TIME_FORMAT *date_time_format_copy(THD *thd,
+ DATE_TIME_FORMAT *format);
+const char *get_date_time_format_str(KNOWN_DATE_TIME_FORMAT *format,
+ timestamp_type type);
+extern bool make_date_time(DATE_TIME_FORMAT *format, TIME *l_time,
+ timestamp_type type, String *str);
+extern void make_time(DATE_TIME_FORMAT *format, TIME *l_time, String *str);
+void make_date(DATE_TIME_FORMAT *format, TIME *l_time, String *str);
+void make_datetime(DATE_TIME_FORMAT *format, TIME *l_time, String *str);
int test_if_number(char *str,int *res,bool allow_wildcards);
void change_byte(byte *,uint,char,char);
diff --git a/sql/mysqld.cc b/sql/mysqld.cc
index eb632912575..1052eeaf11b 100644
--- a/sql/mysqld.cc
+++ b/sql/mysqld.cc
@@ -318,10 +318,7 @@ 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"};
+const char *opt_date_time_formats[3];
char *language_ptr, *default_collation_name, *default_character_set_name;
char mysql_data_home_buff[2], *mysql_data_home=mysql_real_data_home;
@@ -357,7 +354,6 @@ struct system_variables global_system_variables;
struct system_variables max_system_variables;
MY_TMPDIR mysql_tmpdir_list;
-DATE_FORMAT dayord;
MY_BITMAP temp_pool;
CHARSET_INFO *system_charset_info, *files_charset_info ;
@@ -921,9 +917,12 @@ 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();
+ my_free((char*) global_system_variables.date_format,
+ MYF(MY_ALLOW_ZERO_PTR));
+ my_free((char*) global_system_variables.time_format,
+ MYF(MY_ALLOW_ZERO_PTR));
+ my_free((char*) global_system_variables.datetime_format,
+ MYF(MY_ALLOW_ZERO_PTR));
if (defaults_argv)
free_defaults(defaults_argv);
free_tmpdir(&mysql_tmpdir_list);
@@ -2019,33 +2018,46 @@ bool open_log(MYSQL_LOG *log, const char *hostname,
}
-int init_global_datetime_format(datetime_format_types format_type, bool is_alloc)
+/*
+ Initialize one of the global date/time format variables
+
+ SYNOPSIS
+ init_global_datetime_format()
+ format_type What kind of format should be supported
+ var_ptr Pointer to variable that should be updated
+
+ NOTES
+ The default value is taken from either opt_date_time_formats[] or
+ the ISO format (ANSI SQL)
+
+ RETURN
+ 0 ok
+ 1 error
+*/
+
+bool init_global_datetime_format(timestamp_type format_type,
+ DATE_TIME_FORMAT **var_ptr)
{
- const char *format_str= opt_datetime_formats[format_type];
- uint format_length= 0;
- DATETIME_FORMAT *tmp_format= &g_datetime_frm(format_type).datetime_format;
+ /* Get command line option */
+ const char *str= opt_date_time_formats[format_type];
+ DATE_TIME_FORMAT *format;
- if (format_str)
+ if (!str) // No specified format
{
- 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;
+ str= get_date_time_format_str(&known_date_time_formats[ISO_FORMAT],
+ format_type);
+ /*
+ Set the "command line" option to point to the generated string so
+ that we can set global formats back to default
+ */
+ opt_date_time_formats[format_type]= str;
}
- if (make_format(tmp_format, format_type, format_str,
- format_length, is_alloc))
+ if (!(*var_ptr= date_time_format_make(format_type, str, strlen(str))))
{
- 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;
+ fprintf(stderr, "Wrong date/time format specifier: %s\n", str);
+ return 1;
}
- return 1;
+ return 0;
}
@@ -2160,17 +2172,12 @@ static int init_common_variables(const char *conf_file_name, int argc,
}
default_charset_info= default_collation;
}
- global_system_variables.collation_server= default_charset_info;
- global_system_variables.collation_database= default_charset_info;
- global_system_variables.collation_connection= default_charset_info;
+ /* Set collactions that depends on the default collation */
+ global_system_variables.collation_server= default_charset_info;
+ global_system_variables.collation_database= default_charset_info;
+ 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;
+ global_system_variables.character_set_client= default_charset_info;
if (use_temp_pool && bitmap_init(&temp_pool,0,1024,1))
return 1;
@@ -4606,7 +4613,7 @@ The minimum value for this variable is 4096.",
(gptr*) &max_system_variables.net_wait_timeout, 0, GET_ULONG,
REQUIRED_ARG, NET_WAIT_TIMEOUT, 1, LONG_TIMEOUT, 0, 1, 0},
{"expire_logs_days", OPT_EXPIRE_LOGS_DAYS,
- "Logs will be rotated after expire-log-days days. ",
+ "Logs will be rotated after expire-log-days days ",
(gptr*) &expire_logs_days,
(gptr*) &expire_logs_days, 0, GET_ULONG,
REQUIRED_ARG, 0, 0, 99, 0, 1, 0},
@@ -4616,23 +4623,24 @@ The minimum value for this variable is 4096.",
(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],
+ "The DATE format (For future).",
+ (gptr*) &opt_date_time_formats[TIMESTAMP_DATE],
+ (gptr*) &opt_date_time_formats[TIMESTAMP_DATE],
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],
+ "The DATETIME/TIMESTAMP format (for future).",
+ (gptr*) &opt_date_time_formats[TIMESTAMP_DATETIME],
+ (gptr*) &opt_date_time_formats[TIMESTAMP_DATETIME],
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],
+ "The TIME format (for future).",
+ (gptr*) &opt_date_time_formats[TIMESTAMP_TIME],
+ (gptr*) &opt_date_time_formats[TIMESTAMP_TIME],
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}
};
+
struct show_var_st status_vars[]= {
{"Aborted_clients", (char*) &aborted_threads, SHOW_LONG},
{"Aborted_connects", (char*) &aborted_connects, SHOW_LONG},
@@ -4944,6 +4952,8 @@ static void mysql_init_variables(void)
national_charset_info= &my_charset_utf8_general_ci;
table_alias_charset= &my_charset_bin;
+ opt_date_time_formats[0]= opt_date_time_formats[1]= opt_date_time_formats[2]= 0;
+
/* Things with default values that are not zero */
delay_key_write_options= (uint) DELAY_KEY_WRITE_ON;
opt_specialflag= SPECIAL_ENGLISH;
@@ -5001,11 +5011,6 @@ static void mysql_init_variables(void)
/* Set default values for some option variables */
- global_system_variables.collation_server= default_charset_info;
- global_system_variables.collation_database= default_charset_info;
- 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.table_type= DB_TYPE_MYISAM;
global_system_variables.tx_isolation= ISO_REPEATABLE_READ;
global_system_variables.select_limit= (ulonglong) HA_POS_ERROR;
@@ -5014,10 +5019,6 @@ 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",
@@ -5626,7 +5627,7 @@ static void get_options(int argc,char **argv)
exit(ho_error);
if (argc > 0)
{
- fprintf(stderr, "%s: Too many arguments.\nUse --help to get a list of available options\n", my_progname);
+ fprintf(stderr, "%s: Too many arguments (first extra is '%s').\nUse --help to get a list of available options\n", my_progname, *argv);
exit(ho_error);
}
@@ -5681,6 +5682,15 @@ static void get_options(int argc,char **argv)
opt_specialflag|= SPECIAL_SHORT_LOG_FORMAT;
if (opt_log_queries_not_using_indexes)
opt_specialflag|= SPECIAL_LOG_QUERIES_NOT_USING_INDEXES;
+
+ if (init_global_datetime_format(TIMESTAMP_DATE,
+ &global_system_variables.date_format) ||
+ init_global_datetime_format(TIMESTAMP_TIME,
+ &global_system_variables.time_format) ||
+ init_global_datetime_format(TIMESTAMP_DATETIME,
+ &global_system_variables.datetime_format))
+ exit(1);
+
/* Set up default values for a key cache */
KEY_CACHE_VAR *key_cache= &dflt_key_cache_var;
dflt_key_cache_block_size= key_cache->block_size;
diff --git a/sql/protocol.cc b/sql/protocol.cc
index 0fe759cff67..d7a745d371d 100644
--- a/sql/protocol.cc
+++ b/sql/protocol.cc
@@ -833,12 +833,17 @@ bool Protocol_simple::store(TIME *tm)
field_pos++;
#endif
char buff[40];
- 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());
+ 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);
}
@@ -851,10 +856,7 @@ bool Protocol_simple::store_date(TIME *tm)
#endif
char buff[40];
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);
+ make_date((DATE_TIME_FORMAT *) 0, tm, &tmp);
return net_store_data((char*) tmp.ptr(), tmp.length());
}
@@ -873,14 +875,16 @@ bool Protocol_simple::store_time(TIME *tm)
field_pos++;
#endif
char buff[40];
- String tmp((char*) buff,sizeof(buff),&my_charset_bin);
- DATETIME_FORMAT *tmp_format= (&t_datetime_frm
- (current_thd, TIME_FORMAT_TYPE).datetime_format);
+ uint length;
uint day= (tm->year || tm->month) ? 0 : tm->day;
- 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());
+ 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);
}
diff --git a/sql/set_var.cc b/sql/set_var.cc
index 66c8ef87d5a..8d64a684476 100644
--- a/sql/set_var.cc
+++ b/sql/set_var.cc
@@ -299,14 +299,25 @@ sys_var_thd_ulong sys_tmp_table_size("tmp_table_size",
&SV::tmp_table_size);
sys_var_thd_ulong sys_net_wait_timeout("wait_timeout",
&SV::net_wait_timeout);
-
+
#ifdef HAVE_INNOBASE_DB
sys_var_long_ptr sys_innodb_max_dirty_pages_pct("innodb_max_dirty_pages_pct",
&srv_max_buf_pool_modified_pct);
#endif
-/*
- Variables that are bits in THD
-*/
+
+/* Time/date/datetime formats */
+
+sys_var_thd_date_time_format sys_time_format("time_format",
+ &SV::time_format,
+ TIMESTAMP_TIME);
+sys_var_thd_date_time_format sys_date_format("date_format",
+ &SV::date_format,
+ TIMESTAMP_DATE);
+sys_var_thd_date_time_format sys_datetime_format("datetime_format",
+ &SV::datetime_format,
+ TIMESTAMP_DATETIME);
+
+/* Variables that are bits in THD */
static sys_var_thd_bit sys_autocommit("autocommit",
set_option_autocommit,
@@ -413,9 +424,8 @@ 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_date_format,
+ &sys_datetime_format,
&sys_default_week_format,
&sys_delay_key_write,
&sys_delayed_insert_limit,
@@ -485,6 +495,7 @@ sys_var *sys_variables[]=
&sys_rand_seed1,
&sys_rand_seed2,
&sys_range_alloc_block_size,
+ &sys_readonly,
&sys_read_buff_size,
&sys_read_rnd_buff_size,
#ifdef HAVE_REPLICATION
@@ -500,7 +511,6 @@ sys_var *sys_variables[]=
&sys_slave_net_timeout,
&sys_slave_skip_counter,
#endif
- &sys_readonly,
&sys_slow_launch_time,
&sys_sort_buffer,
&sys_sql_big_tables,
@@ -511,6 +521,7 @@ sys_var *sys_variables[]=
&sys_table_cache_size,
&sys_table_type,
&sys_thread_cache_size,
+ &sys_time_format,
&sys_timestamp,
&sys_tmp_table_size,
&sys_trans_alloc_block_size,
@@ -556,9 +567,9 @@ 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_date_format.name, (char*) &sys_date_format, SHOW_SYS},
+ {sys_datetime_format.name, (char*) &sys_datetime_format, SHOW_SYS},
+ {sys_default_week_format.name, (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},
{sys_delayed_insert_timeout.name, (char*) &sys_delayed_insert_timeout, SHOW_SYS},
@@ -720,7 +731,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},
+ {sys_time_format.name, (char*) &sys_time_format, SHOW_SYS},
#ifdef HAVE_TZNAME
{"timezone", time_zone, SHOW_CHAR},
#endif
@@ -744,71 +755,6 @@ bool sys_var::check(THD *thd, set_var *var)
/*
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
@@ -1226,8 +1172,8 @@ bool sys_var::check_enum(THD *thd, set_var *var, TYPELIB *enum_names)
{
if (!(res=var->value->val_str(&str)) ||
((long) (var->save_result.ulong_value=
- (ulong) find_type(res->c_ptr(), enum_names, 3)-1))
- < 0)
+ (ulong) find_type(enum_names, res->ptr(),
+ res->length(),1)-1)) < 0)
{
value= res ? res->c_ptr() : "NULL";
goto err;
@@ -1341,8 +1287,12 @@ Item *sys_var::item(THD *thd, enum_var_type var_type, LEX_STRING *base)
return new Item_int((int32) *(my_bool*) value_ptr(thd, var_type, base),1);
case SHOW_CHAR:
{
+ Item_string *tmp;
+ pthread_mutex_lock(&LOCK_global_system_variables);
char *str= (char*) value_ptr(thd, var_type, base);
- return new Item_string(str, strlen(str), system_charset_info);
+ tmp= new Item_string(str, strlen(str), system_charset_info);
+ pthread_mutex_unlock(&LOCK_global_system_variables);
+ return tmp;
}
default:
net_printf(thd, ER_VAR_CANT_BE_READ, name);
@@ -1401,6 +1351,112 @@ byte *sys_var_thd_bit::value_ptr(THD *thd, enum_var_type type,
}
+/* Update a date_time format variable based on given value */
+
+void sys_var_thd_date_time_format::update2(THD *thd, enum_var_type type,
+ DATE_TIME_FORMAT *new_value)
+{
+ DATE_TIME_FORMAT *old;
+ DBUG_ENTER("sys_var_date_time_format::update2");
+ DBUG_DUMP("positions",(char*) new_value->positions,
+ sizeof(new_value->positions));
+
+ if (type == OPT_GLOBAL)
+ {
+ pthread_mutex_lock(&LOCK_global_system_variables);
+ old= (global_system_variables.*offset);
+ (global_system_variables.*offset)= new_value;
+ pthread_mutex_unlock(&LOCK_global_system_variables);
+ }
+ else
+ {
+ old= (thd->variables.*offset);
+ (thd->variables.*offset)= new_value;
+ }
+ my_free((char*) old, MYF(MY_ALLOW_ZERO_PTR));
+ DBUG_VOID_RETURN;
+}
+
+
+bool sys_var_thd_date_time_format::update(THD *thd, set_var *var)
+{
+ DATE_TIME_FORMAT *new_value;
+ /* We must make a copy of the last value to get it into normal memory */
+ new_value= date_time_format_copy((THD*) 0,
+ var->save_result.date_time_format);
+ if (!new_value)
+ return 1; // Out of memory
+ update2(thd, var->type, new_value); // Can't fail
+ return 0;
+}
+
+
+bool sys_var_thd_date_time_format::check(THD *thd, set_var *var)
+{
+ char buff[80];
+ String str(buff,sizeof(buff), system_charset_info), *res;
+ DATE_TIME_FORMAT *format;
+
+ if (!(res=var->value->val_str(&str)))
+ res= &my_empty_string;
+
+ if (!(format= date_time_format_make(date_time_type,
+ res->ptr(), res->length())))
+ {
+ my_error(ER_WRONG_VALUE_FOR_VAR, MYF(0), name, res->c_ptr());
+ return 1;
+ }
+
+ /*
+ We must copy result to thread space to not get a memory leak if
+ update is aborted
+ */
+ var->save_result.date_time_format= date_time_format_copy(thd, format);
+ my_free((char*) format, MYF(0));
+ return var->save_result.date_time_format == 0;
+}
+
+
+void sys_var_thd_date_time_format::set_default(THD *thd, enum_var_type type)
+{
+ DATE_TIME_FORMAT *res= 0;
+
+ if (type == OPT_GLOBAL)
+ {
+ const char *format;
+ if ((format= opt_date_time_formats[date_time_type]))
+ res= date_time_format_make(date_time_type, format, strlen(format));
+ }
+ else
+ {
+ /* Make copy with malloc */
+ res= date_time_format_copy((THD *) 0, global_system_variables.*offset);
+ }
+
+ if (res) // Should always be true
+ update2(thd, type, res);
+}
+
+
+byte *sys_var_thd_date_time_format::value_ptr(THD *thd, enum_var_type type,
+ LEX_STRING *base)
+{
+ if (type == OPT_GLOBAL)
+ {
+ char *res;
+ /*
+ We do a copy here just to be sure things will work even if someone
+ is modifying the original string while the copy is accessed
+ (Can't happen now in SQL SHOW, but this is a good safety for the future)
+ */
+ res= thd->strmake((global_system_variables.*offset)->format.str,
+ (global_system_variables.*offset)->format.length);
+ return (byte*) res;
+ }
+ return (byte*) (thd->variables.*offset)->format.str;
+}
+
+
typedef struct old_names_map_st
{
const char *old_name;
@@ -1409,17 +1465,17 @@ typedef struct old_names_map_st
static my_old_conv old_conv[]=
{
- { "cp1251_koi8" , "cp1251" },
- { "cp1250_latin2" , "cp1250" },
- { "kam_latin2" , "keybcs2" },
- { "mac_latin2" , "MacRoman" },
- { "macce_latin2" , "MacCE" },
- { "pc2_latin2" , "pclatin2" },
- { "vga_latin2" , "pclatin1" },
- { "koi8_cp1251" , "koi8r" },
- { "win1251ukr_koi8_ukr" , "win1251ukr" },
- { "koi8_ukr_win1251ukr" , "koi8u" },
- { NULL , NULL }
+ { "cp1251_koi8" , "cp1251" },
+ { "cp1250_latin2" , "cp1250" },
+ { "kam_latin2" , "keybcs2" },
+ { "mac_latin2" , "MacRoman" },
+ { "macce_latin2" , "MacCE" },
+ { "pc2_latin2" , "pclatin2" },
+ { "vga_latin2" , "pclatin1" },
+ { "koi8_cp1251" , "koi8r" },
+ { "win1251ukr_koi8_ukr" , "win1251ukr" },
+ { "koi8_ukr_win1251ukr" , "koi8u" },
+ { NULL , NULL }
};
CHARSET_INFO *get_old_charset_by_name(const char *name)
diff --git a/sql/set_var.h b/sql/set_var.h
index 16b2c1d5d37..c799eec750a 100644
--- a/sql/set_var.h
+++ b/sql/set_var.h
@@ -54,8 +54,6 @@ 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)
@@ -195,9 +193,6 @@ 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)
{}
@@ -621,46 +616,26 @@ public:
};
-class sys_var_datetime_format :public sys_var_thd
+class sys_var_thd_date_time_format :public sys_var_thd
{
+ DATE_TIME_FORMAT *SV::*offset;
+ enum timestamp_type date_time_type;
public:
- enum datetime_format_types format_type;
- DATETIME_FORMAT datetime_format;
- sys_var_datetime_format(): sys_var_thd()
+ sys_var_thd_date_time_format(const char *name_arg,
+ DATE_TIME_FORMAT *SV::*offset_arg,
+ timestamp_type date_time_type_arg)
+ :sys_var_thd(name_arg), offset(offset_arg),
+ date_time_type(date_time_type_arg)
{}
-
- 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 check(THD *thd, set_var *var);
bool update(THD *thd, set_var *var);
+ void update2(THD *thd, enum_var_type type, DATE_TIME_FORMAT *new_value);
byte *value_ptr(THD *thd, enum_var_type type, LEX_STRING *base);
void set_default(THD *thd, enum_var_type type);
};
@@ -718,6 +693,7 @@ public:
CHARSET_INFO *charset;
ulong ulong_value;
ulonglong ulonglong_value;
+ DATE_TIME_FORMAT *date_time_format;
} save_result;
LEX_STRING base; /* for structs */
diff --git a/sql/share/czech/errmsg.txt b/sql/share/czech/errmsg.txt
index 2176fcbd441..c01df3b53cd 100644
--- a/sql/share/czech/errmsg.txt
+++ b/sql/share/czech/errmsg.txt
@@ -276,21 +276,26 @@ character-set=latin2
"Record count is more than the column count at row %ld";
"Data truncated, NULL supplied to NOT NULL column '%s' at row %ld";
"Data truncated, out of range for column '%s' at row %ld";
-"Data truncated for column '%s' at row %ld"
+"Data truncated for column '%s' at row %ld",
"Using storage engine %s for table '%s'",
"Illegal mix of collations (%s,%s) and (%s,%s) for operation '%s'",
-"Can't drop one or more of the requested users"
-"Can't revoke all privileges, grant for one or more of the requested users"
+"Can't drop one or more of the requested users",
+"Can't revoke all privileges, grant for one or more of the requested users",
"Illegal mix of collations (%s,%s), (%s,%s), (%s,%s) for operation '%s'",
"Illegal mix of collations for operation '%s'",
"Variable '%-.64s' is not a variable component (Can't be used as XXXX.variable_name)",
"Unknown collation: '%-.64s'",
-"SSL parameters in CHANGE MASTER are ignored because this MySQL slave was compiled without SSL support. They can be used later when MySQL slave with SSL will be started."
-"Server is running in --secure-auth mode, but '%s@%s' has a password in the old format; please change the password to the new format"
+"SSL parameters in CHANGE MASTER are ignored because this MySQL slave was compiled without SSL support. They can be used later when MySQL slave with SSL will be started.",
+"Server is running in --secure-auth mode, but '%s@%s' has a password in the old format; please change the password to the new format",
"Field or reference '%-.64s%s%-.64s%s%-.64s' of SELECT #%d was resolved in SELECT #%d",
-"Wrong parameter or combination of parameters for START SLAVE UNTIL"
-"It is recommended to run with --skip-slave-start when doing step-by-step replication with START SLAVE UNTIL, otherwise you are not safe in case of unexpected slave's mysqld restart"
-"SQL thread is not to be started so UNTIL options are ignored"
-"Incorrect index name '%-.100s'",
+"Wrong parameter or combination of parameters for START SLAVE UNTIL",
+"It is recommended to run with --skip-slave-start when doing step-by-step replication with START SLAVE UNTIL, otherwise you are not safe in case of unexpected slave's mysqld restart",
+"SQL thread is not to be started so UNTIL options are ignored",
+"Incorrect %s name '%-.100s'",
+"table",
+"database",
+"column",
+"index",
+"catalog",
"Query cache failed to set size %lu, new query cache size is %lu",
-"Column '%-.64s' cannot be part of FULLTEXT index"
+"Column '%-.64s' cannot be part of FULLTEXT index",
diff --git a/sql/share/danish/errmsg.txt b/sql/share/danish/errmsg.txt
index 791060ac744..e67c430c4f7 100644
--- a/sql/share/danish/errmsg.txt
+++ b/sql/share/danish/errmsg.txt
@@ -270,21 +270,26 @@ character-set=latin1
"Record count is more than the column count at row %ld";
"Data truncated, NULL supplied to NOT NULL column '%s' at row %ld";
"Data truncated, out of range for column '%s' at row %ld";
-"Data truncated for column '%s' at row %ld"
+"Data truncated for column '%s' at row %ld",
"Using storage engine %s for table '%s'",
"Illegal mix of collations (%s,%s) and (%s,%s) for operation '%s'",
-"Can't drop one or more of the requested users"
-"Can't revoke all privileges, grant for one or more of the requested users"
+"Can't drop one or more of the requested users",
+"Can't revoke all privileges, grant for one or more of the requested users",
"Illegal mix of collations (%s,%s), (%s,%s), (%s,%s) for operation '%s'",
"Illegal mix of collations for operation '%s'",
"Variable '%-.64s' is not a variable component (Can't be used as XXXX.variable_name)",
"Unknown collation: '%-.64s'",
-"SSL parameters in CHANGE MASTER are ignored because this MySQL slave was compiled without SSL support. They can be used later when MySQL slave with SSL will be started."
-"Server is running in --secure-auth mode, but '%s@%s' has a password in the old format; please change the password to the new format"
+"SSL parameters in CHANGE MASTER are ignored because this MySQL slave was compiled without SSL support. They can be used later when MySQL slave with SSL will be started.",
+"Server is running in --secure-auth mode, but '%s@%s' has a password in the old format; please change the password to the new format",
"Field or reference '%-.64s%s%-.64s%s%-.64s' of SELECT #%d was resolved in SELECT #%d",
-"Wrong parameter or combination of parameters for START SLAVE UNTIL"
-"It is recommended to run with --skip-slave-start when doing step-by-step replication with START SLAVE UNTIL, otherwise you are not safe in case of unexpected slave's mysqld restart"
-"SQL thread is not to be started so UNTIL options are ignored"
-"Incorrect index name '%-.100s'",
+"Wrong parameter or combination of parameters for START SLAVE UNTIL",
+"It is recommended to run with --skip-slave-start when doing step-by-step replication with START SLAVE UNTIL, otherwise you are not safe in case of unexpected slave's mysqld restart",
+"SQL thread is not to be started so UNTIL options are ignored",
+"Incorrect %s name '%-.100s'",
+"table",
+"database",
+"column",
+"index",
+"catalog",
"Query cache failed to set size %lu, new query cache size is %lu",
-"Column '%-.64s' cannot be part of FULLTEXT index"
+"Column '%-.64s' cannot be part of FULLTEXT index",
diff --git a/sql/share/dutch/errmsg.txt b/sql/share/dutch/errmsg.txt
index 62e210f1016..5f77163eeda 100644
--- a/sql/share/dutch/errmsg.txt
+++ b/sql/share/dutch/errmsg.txt
@@ -278,21 +278,26 @@ character-set=latin1
"Record count is more than the column count at row %ld";
"Data truncated, NULL supplied to NOT NULL column '%s' at row %ld";
"Data truncated, out of range for column '%s' at row %ld";
-"Data truncated for column '%s' at row %ld"
+"Data truncated for column '%s' at row %ld",
"Using storage engine %s for table '%s'",
"Illegal mix of collations (%s,%s) and (%s,%s) for operation '%s'",
-"Can't drop one or more of the requested users"
-"Can't revoke all privileges, grant for one or more of the requested users"
+"Can't drop one or more of the requested users",
+"Can't revoke all privileges, grant for one or more of the requested users",
"Illegal mix of collations (%s,%s), (%s,%s), (%s,%s) for operation '%s'",
"Illegal mix of collations for operation '%s'",
"Variable '%-.64s' is not a variable component (Can't be used as XXXX.variable_name)",
"Unknown collation: '%-.64s'",
-"SSL parameters in CHANGE MASTER are ignored because this MySQL slave was compiled without SSL support. They can be used later when MySQL slave with SSL will be started."
-"Server is running in --secure-auth mode, but '%s@%s' has a password in the old format; please change the password to the new format"
+"SSL parameters in CHANGE MASTER are ignored because this MySQL slave was compiled without SSL support. They can be used later when MySQL slave with SSL will be started.",
+"Server is running in --secure-auth mode, but '%s@%s' has a password in the old format; please change the password to the new format",
"Field or reference '%-.64s%s%-.64s%s%-.64s' of SELECT #%d was resolved in SELECT #%d",
-"Wrong parameter or combination of parameters for START SLAVE UNTIL"
-"It is recommended to run with --skip-slave-start when doing step-by-step replication with START SLAVE UNTIL, otherwise you are not safe in case of unexpected slave's mysqld restart"
-"SQL thread is not to be started so UNTIL options are ignored"
-"Incorrect index name '%-.100s'",
+"Wrong parameter or combination of parameters for START SLAVE UNTIL",
+"It is recommended to run with --skip-slave-start when doing step-by-step replication with START SLAVE UNTIL, otherwise you are not safe in case of unexpected slave's mysqld restart",
+"SQL thread is not to be started so UNTIL options are ignored",
+"Incorrect %s name '%-.100s'",
+"table",
+"database",
+"column",
+"index",
+"catalog",
"Query cache failed to set size %lu, new query cache size is %lu",
-"Column '%-.64s' cannot be part of FULLTEXT index"
+"Column '%-.64s' cannot be part of FULLTEXT index",
diff --git a/sql/share/english/errmsg.txt b/sql/share/english/errmsg.txt
index a0d746ce0ca..baecefb8494 100644
--- a/sql/share/english/errmsg.txt
+++ b/sql/share/english/errmsg.txt
@@ -252,36 +252,41 @@ character-set=latin1
"Reference '%-.64s' not supported (%s)",
"Every derived table must have it's own alias",
"Select %u was reduced during optimisation",
-"Table '%-.64s' from one of SELECT's can not be used in %-.32s"
-"Client does not support authentication protocol requested by server; consider upgrading MySQL client"
-"All parts of a SPATIAL KEY must be NOT NULL"
-"COLLATION '%s' is not valid for CHARACTER SET '%s'"
-"Slave is already running"
-"Slave has already been stopped"
-"Too big size of uncompressed data. The maximum size is %d. (probably, length of uncompressed data was corrupted)"
-"Z_MEM_ERROR: Not enough memory available for zlib"
-"Z_BUF_ERROR: Not enough room in the output buffer for zlib (probably, length of uncompressed data was corrupted)"
-"Z_DATA_ERROR: Input data was corrupted for zlib"
-"%d line(s) was(were) cut by group_concat()"
+"Table '%-.64s' from one of SELECT's can not be used in %-.32s",
+"Client does not support authentication protocol requested by server; consider upgrading MySQL client",
+"All parts of a SPATIAL KEY must be NOT NULL",
+"COLLATION '%s' is not valid for CHARACTER SET '%s'",
+"Slave is already running",
+"Slave has already been stopped",
+"Too big size of uncompressed data. The maximum size is %d. (probably, length of uncompressed data was corrupted)",
+"ZLIB: Not enough memory available for zlib",
+"ZLIB: Not enough room in the output buffer for zlib (probably, length of uncompressed data was corrupted)",
+"ZLIB: Input data was corrupted for zlib",
+"%d line(s) was(were) cut by group_concat()",
"Record count is fewer than the column count at row %ld";
"Record count is more than the column count at row %ld";
"Data truncated, NULL supplied to NOT NULL column '%s' at row %ld";
"Data truncated, out of range for column '%s' at row %ld";
-"Data truncated for column '%s' at row %ld"
+"Data truncated for column '%s' at row %ld",
"Using storage engine %s for table '%s'",
"Illegal mix of collations (%s,%s) and (%s,%s) for operation '%s'",
-"Can't drop one or more of the requested users"
-"Can't revoke all privileges, grant for one or more of the requested users"
+"Can't drop one or more of the requested users",
+"Can't revoke all privileges, grant for one or more of the requested users",
"Illegal mix of collations (%s,%s), (%s,%s), (%s,%s) for operation '%s'",
"Illegal mix of collations for operation '%s'",
"Variable '%-.64s' is not a variable component (Can't be used as XXXX.variable_name)",
"Unknown collation: '%-.64s'",
-"SSL parameters in CHANGE MASTER are ignored because this MySQL slave was compiled without SSL support. They can be used later when MySQL slave with SSL will be started."
-"Server is running in --secure-auth mode, but '%s'@'%s' has a password in the old format; please change the password to the new format",
+"SSL parameters in CHANGE MASTER are ignored because this MySQL slave was compiled without SSL support. They can be used later when MySQL slave with SSL will be started.",
+"Server is running in --secure-auth mode, but '%s@%s' has a password in the old format; please change the password to the new format",
"Field or reference '%-.64s%s%-.64s%s%-.64s' of SELECT #%d was resolved in SELECT #%d",
-"Wrong parameter or combination of parameters for START SLAVE UNTIL"
-"It is recommended to run with --skip-slave-start when doing step-by-step replication with START SLAVE UNTIL, otherwise you are not safe in case of unexpected slave's mysqld restart"
-"SQL thread is not to be started so UNTIL options are ignored"
-"Incorrect index name '%-.100s'",
+"Wrong parameter or combination of parameters for START SLAVE UNTIL",
+"It is recommended to use --skip-slave-start when doing step-by-step replication with START SLAVE UNTIL. Otherwise you will get problems if you get an unexpected slave's mysqld restart",
+"SQL thread is not to be started so UNTIL options are ignored",
+"Incorrect %s name '%-.100s'",
+"table",
+"database",
+"column",
+"index",
+"catalog",
"Query cache failed to set size %lu, new query cache size is %lu",
-"Column '%-.64s' cannot be part of FULLTEXT index"
+"Column '%-.64s' cannot be part of FULLTEXT index",
diff --git a/sql/share/estonian/errmsg.txt b/sql/share/estonian/errmsg.txt
index 0510e3fc76b..09e63ddd804 100644
--- a/sql/share/estonian/errmsg.txt
+++ b/sql/share/estonian/errmsg.txt
@@ -272,21 +272,26 @@ character-set=latin7
"Record count is more than the column count at row %ld";
"Data truncated, NULL supplied to NOT NULL column '%s' at row %ld";
"Data truncated, out of range for column '%s' at row %ld";
-"Data truncated for column '%s' at row %ld"
+"Data truncated for column '%s' at row %ld",
"Using storage engine %s for table '%s'",
"Illegal mix of collations (%s,%s) and (%s,%s) for operation '%s'",
-"Can't drop one or more of the requested users"
-"Can't revoke all privileges, grant for one or more of the requested users"
+"Can't drop one or more of the requested users",
+"Can't revoke all privileges, grant for one or more of the requested users",
"Illegal mix of collations (%s,%s), (%s,%s), (%s,%s) for operation '%s'",
"Illegal mix of collations for operation '%s'",
"Variable '%-.64s' is not a variable component (Can't be used as XXXX.variable_name)",
"Unknown collation: '%-.64s'",
-"SSL parameters in CHANGE MASTER are ignored because this MySQL slave was compiled without SSL support. They can be used later when MySQL slave with SSL will be started."
-"Server is running in --secure-auth mode, but '%s@%s' has a password in the old format; please change the password to the new format"
+"SSL parameters in CHANGE MASTER are ignored because this MySQL slave was compiled without SSL support. They can be used later when MySQL slave with SSL will be started.",
+"Server is running in --secure-auth mode, but '%s@%s' has a password in the old format; please change the password to the new format",
"Field or reference '%-.64s%s%-.64s%s%-.64s' of SELECT #%d was resolved in SELECT #%d",
-"Wrong parameter or combination of parameters for START SLAVE UNTIL"
-"It is recommended to run with --skip-slave-start when doing step-by-step replication with START SLAVE UNTIL, otherwise you are not safe in case of unexpected slave's mysqld restart"
-"SQL thread is not to be started so UNTIL options are ignored"
-"Incorrect index name '%-.100s'",
+"Wrong parameter or combination of parameters for START SLAVE UNTIL",
+"It is recommended to run with --skip-slave-start when doing step-by-step replication with START SLAVE UNTIL, otherwise you are not safe in case of unexpected slave's mysqld restart",
+"SQL thread is not to be started so UNTIL options are ignored",
+"Incorrect %s name '%-.100s'",
+"table",
+"database",
+"column",
+"index",
+"catalog",
"Query cache failed to set size %lu, new query cache size is %lu",
-"Column '%-.64s' cannot be part of FULLTEXT index"
+"Column '%-.64s' cannot be part of FULLTEXT index",
diff --git a/sql/share/french/errmsg.txt b/sql/share/french/errmsg.txt
index 485cbe45724..0956db6681e 100644
--- a/sql/share/french/errmsg.txt
+++ b/sql/share/french/errmsg.txt
@@ -267,21 +267,26 @@ character-set=latin1
"Record count is more than the column count at row %ld";
"Data truncated, NULL supplied to NOT NULL column '%s' at row %ld";
"Data truncated, out of range for column '%s' at row %ld";
-"Data truncated for column '%s' at row %ld"
+"Data truncated for column '%s' at row %ld",
"Using storage engine %s for table '%s'",
"Illegal mix of collations (%s,%s) and (%s,%s) for operation '%s'",
-"Can't drop one or more of the requested users"
-"Can't revoke all privileges, grant for one or more of the requested users"
+"Can't drop one or more of the requested users",
+"Can't revoke all privileges, grant for one or more of the requested users",
"Illegal mix of collations (%s,%s), (%s,%s), (%s,%s) for operation '%s'",
"Illegal mix of collations for operation '%s'",
"Variable '%-.64s' is not a variable component (Can't be used as XXXX.variable_name)",
"Unknown collation: '%-.64s'",
-"SSL parameters in CHANGE MASTER are ignored because this MySQL slave was compiled without SSL support. They can be used later when MySQL slave with SSL will be started."
-"Server is running in --secure-auth mode, but '%s@%s' has a password in the old format; please change the password to the new format"
+"SSL parameters in CHANGE MASTER are ignored because this MySQL slave was compiled without SSL support. They can be used later when MySQL slave with SSL will be started.",
+"Server is running in --secure-auth mode, but '%s@%s' has a password in the old format; please change the password to the new format",
"Field or reference '%-.64s%s%-.64s%s%-.64s' of SELECT #%d was resolved in SELECT #%d",
-"Wrong parameter or combination of parameters for START SLAVE UNTIL"
-"It is recommended to run with --skip-slave-start when doing step-by-step replication with START SLAVE UNTIL, otherwise you are not safe in case of unexpected slave's mysqld restart"
-"SQL thread is not to be started so UNTIL options are ignored"
-"Incorrect index name '%-.100s'",
+"Wrong parameter or combination of parameters for START SLAVE UNTIL",
+"It is recommended to run with --skip-slave-start when doing step-by-step replication with START SLAVE UNTIL, otherwise you are not safe in case of unexpected slave's mysqld restart",
+"SQL thread is not to be started so UNTIL options are ignored",
+"Incorrect %s name '%-.100s'",
+"table",
+"database",
+"column",
+"index",
+"catalog",
"Query cache failed to set size %lu, new query cache size is %lu",
-"Column '%-.64s' cannot be part of FULLTEXT index"
+"Column '%-.64s' cannot be part of FULLTEXT index",
diff --git a/sql/share/german/errmsg.txt b/sql/share/german/errmsg.txt
index c9760879f3c..2cc98971915 100644
--- a/sql/share/german/errmsg.txt
+++ b/sql/share/german/errmsg.txt
@@ -293,7 +293,12 @@ character-set=latin1
"Feld oder Verweis '%-.64s%s%-.64s%s%-.64s' im SELECT-Befehl Nr. %d wurde im SELECT-Befehl Nr. %d aufgelöst",
"Falscher Parameter oder falsche Kombination von Parametern für START SLAVE UNTIL",
"Es wird empfohlen, mit --skip-slave-start zu starten, wenn mit START SLAVE UNTIL eine Schritt-für-Schritt-Replikation ausgeführt wird. Ansonsten gibt es Probleme, wenn der Slave-Server unerwartet neu startet",
-"SQL-Thread soll nicht gestartet werden. Daher werden UNTIL-Optionen ignoriert"
-"Incorrect index name '%-.100s'",
+"SQL-Thread soll nicht gestartet werden. Daher werden UNTIL-Optionen ignoriert",
+"Incorrect %s name '%-.100s'",
+"table",
+"database",
+"column",
+"index",
+"catalog",
"Query cache failed to set size %lu, new query cache size is %lu",
-"Column '%-.64s' cannot be part of FULLTEXT index"
+"Column '%-.64s' cannot be part of FULLTEXT index",
diff --git a/sql/share/greek/errmsg.txt b/sql/share/greek/errmsg.txt
index 90ab24610ff..84e48d2f284 100644
--- a/sql/share/greek/errmsg.txt
+++ b/sql/share/greek/errmsg.txt
@@ -267,21 +267,26 @@ character-set=greek
"Record count is more than the column count at row %ld";
"Data truncated, NULL supplied to NOT NULL column '%s' at row %ld";
"Data truncated, out of range for column '%s' at row %ld";
-"Data truncated for column '%s' at row %ld"
+"Data truncated for column '%s' at row %ld",
"Using storage engine %s for table '%s'",
"Illegal mix of collations (%s,%s) and (%s,%s) for operation '%s'",
-"Can't drop one or more of the requested users"
-"Can't revoke all privileges, grant for one or more of the requested users"
+"Can't drop one or more of the requested users",
+"Can't revoke all privileges, grant for one or more of the requested users",
"Illegal mix of collations (%s,%s), (%s,%s), (%s,%s) for operation '%s'",
"Illegal mix of collations for operation '%s'",
"Variable '%-.64s' is not a variable component (Can't be used as XXXX.variable_name)",
"Unknown collation: '%-.64s'",
-"SSL parameters in CHANGE MASTER are ignored because this MySQL slave was compiled without SSL support. They can be used later when MySQL slave with SSL will be started."
-"Server is running in --secure-auth mode, but '%s@%s' has a password in the old format; please change the password to the new format"
+"SSL parameters in CHANGE MASTER are ignored because this MySQL slave was compiled without SSL support. They can be used later when MySQL slave with SSL will be started.",
+"Server is running in --secure-auth mode, but '%s@%s' has a password in the old format; please change the password to the new format",
"Field or reference '%-.64s%s%-.64s%s%-.64s' of SELECT #%d was resolved in SELECT #%d",
-"Wrong parameter or combination of parameters for START SLAVE UNTIL"
-"It is recommended to run with --skip-slave-start when doing step-by-step replication with START SLAVE UNTIL, otherwise you are not safe in case of unexpected slave's mysqld restart"
-"SQL thread is not to be started so UNTIL options are ignored"
-"Incorrect index name '%-.100s'",
+"Wrong parameter or combination of parameters for START SLAVE UNTIL",
+"It is recommended to run with --skip-slave-start when doing step-by-step replication with START SLAVE UNTIL, otherwise you are not safe in case of unexpected slave's mysqld restart",
+"SQL thread is not to be started so UNTIL options are ignored",
+"Incorrect %s name '%-.100s'",
+"table",
+"database",
+"column",
+"index",
+"catalog",
"Query cache failed to set size %lu, new query cache size is %lu",
-"Column '%-.64s' cannot be part of FULLTEXT index"
+"Column '%-.64s' cannot be part of FULLTEXT index",
diff --git a/sql/share/hungarian/errmsg.txt b/sql/share/hungarian/errmsg.txt
index c456e9580b3..da71f4b7da6 100644
--- a/sql/share/hungarian/errmsg.txt
+++ b/sql/share/hungarian/errmsg.txt
@@ -269,21 +269,26 @@ character-set=latin2
"Record count is more than the column count at row %ld";
"Data truncated, NULL supplied to NOT NULL column '%s' at row %ld";
"Data truncated, out of range for column '%s' at row %ld";
-"Data truncated for column '%s' at row %ld"
+"Data truncated for column '%s' at row %ld",
"Using storage engine %s for table '%s'",
"Illegal mix of collations (%s,%s) and (%s,%s) for operation '%s'",
-"Can't drop one or more of the requested users"
-"Can't revoke all privileges, grant for one or more of the requested users"
+"Can't drop one or more of the requested users",
+"Can't revoke all privileges, grant for one or more of the requested users",
"Illegal mix of collations (%s,%s), (%s,%s), (%s,%s) for operation '%s'",
"Illegal mix of collations for operation '%s'",
"Variable '%-.64s' is not a variable component (Can't be used as XXXX.variable_name)",
"Unknown collation: '%-.64s'",
-"SSL parameters in CHANGE MASTER are ignored because this MySQL slave was compiled without SSL support. They can be used later when MySQL slave with SSL will be started."
-"Server is running in --secure-auth mode, but '%s@%s' has a password in the old format; please change the password to the new format"
+"SSL parameters in CHANGE MASTER are ignored because this MySQL slave was compiled without SSL support. They can be used later when MySQL slave with SSL will be started.",
+"Server is running in --secure-auth mode, but '%s@%s' has a password in the old format; please change the password to the new format",
"Field or reference '%-.64s%s%-.64s%s%-.64s' of SELECT #%d was resolved in SELECT #%d",
-"Wrong parameter or combination of parameters for START SLAVE UNTIL"
-"It is recommended to run with --skip-slave-start when doing step-by-step replication with START SLAVE UNTIL, otherwise you are not safe in case of unexpected slave's mysqld restart"
-"SQL thread is not to be started so UNTIL options are ignored"
-"Incorrect index name '%-.100s'",
+"Wrong parameter or combination of parameters for START SLAVE UNTIL",
+"It is recommended to run with --skip-slave-start when doing step-by-step replication with START SLAVE UNTIL, otherwise you are not safe in case of unexpected slave's mysqld restart",
+"SQL thread is not to be started so UNTIL options are ignored",
+"Incorrect %s name '%-.100s'",
+"table",
+"database",
+"column",
+"index",
+"catalog",
"Query cache failed to set size %lu, new query cache size is %lu",
-"Column '%-.64s' cannot be part of FULLTEXT index"
+"Column '%-.64s' cannot be part of FULLTEXT index",
diff --git a/sql/share/italian/errmsg.txt b/sql/share/italian/errmsg.txt
index 09b533c0fb7..f960c6c043d 100644
--- a/sql/share/italian/errmsg.txt
+++ b/sql/share/italian/errmsg.txt
@@ -267,21 +267,27 @@ character-set=latin1
"Record count is more than the column count at row %ld";
"Data truncated, NULL supplied to NOT NULL column '%s' at row %ld";
"Data truncated, out of range for column '%s' at row %ld";
-"Data truncated for column '%s' at row %ld"
+"Data truncated for column '%s' at row %ld",
"Using storage engine %s for table '%s'",
"Illegal mix of collations (%s,%s) and (%s,%s) for operation '%s'",
-"Can't drop one or more of the requested users"
-"Can't revoke all privileges, grant for one or more of the requested users"
+"Can't drop one or more of the requested users",
+"Can't revoke all privileges, grant for one or more of the requested users",
"Illegal mix of collations (%s,%s), (%s,%s), (%s,%s) for operation '%s'",
"Illegal mix of collations for operation '%s'",
"Variable '%-.64s' is not a variable component (Can't be used as XXXX.variable_name)",
"Unknown collation: '%-.64s'",
-"SSL parameters in CHANGE MASTER are ignored because this MySQL slave was compiled without SSL support. They can be used later when MySQL slave with SSL will be started."
-"Server is running in --secure-auth mode, but '%s@%s' has a password in the old format; please change the password to the new format"
+"SSL parameters in CHANGE MASTER are ignored because this MySQL slave was compiled without SSL support. They can be used later when MySQL slave with SSL will be started.",
+"Server is running in --secure-auth mode, but '%s@%s' has a password in the old format; please change the password to the new format",
"Field or reference '%-.64s%s%-.64s%s%-.64s' of SELECT #%d was resolved in SELECT #%d",
-"Wrong parameter or combination of parameters for START SLAVE UNTIL"
-"It is recommended to run with --skip-slave-start when doing step-by-step replication with START SLAVE UNTIL, otherwise you are not safe in case of unexpected slave's mysqld restart"
-"SQL thread is not to be started so UNTIL options are ignored"
-"Incorrect index name '%-.100s'",
+"Wrong parameter or combination of parameters for START SLAVE UNTIL",
+"It is recommended to run with --skip-slave-start when doing step-by-step replication with START SLAVE UNTIL, otherwise you are not safe in case of unexpected slave's mysqld restart",
+"SQL thread is not to be started so UNTIL options are ignored",
+"Incorrect %s name '%-.100s'",
+"table",
+"database",
+"column",
+"index",
+"catalog",
"Query cache failed to set size %lu, new query cache size is %lu",
-"Column '%-.64s' cannot be part of FULLTEXT index"
+"Column '%-.64s' cannot be part of FULLTEXT index",
+
diff --git a/sql/share/japanese/errmsg.txt b/sql/share/japanese/errmsg.txt
index 15b8640cb29..d28cc026159 100644
--- a/sql/share/japanese/errmsg.txt
+++ b/sql/share/japanese/errmsg.txt
@@ -269,21 +269,26 @@ character-set=ujis
"Record count is more than the column count at row %ld";
"Data truncated, NULL supplied to NOT NULL column '%s' at row %ld";
"Data truncated, out of range for column '%s' at row %ld";
-"Data truncated for column '%s' at row %ld"
+"Data truncated for column '%s' at row %ld",
"Using storage engine %s for table '%s'",
"Illegal mix of collations (%s,%s) and (%s,%s) for operation '%s'",
-"Can't drop one or more of the requested users"
-"Can't revoke all privileges, grant for one or more of the requested users"
+"Can't drop one or more of the requested users",
+"Can't revoke all privileges, grant for one or more of the requested users",
"Illegal mix of collations (%s,%s), (%s,%s), (%s,%s) for operation '%s'",
"Illegal mix of collations for operation '%s'",
"Variable '%-.64s' is not a variable component (Can't be used as XXXX.variable_name)",
"Unknown collation: '%-.64s'",
-"SSL parameters in CHANGE MASTER are ignored because this MySQL slave was compiled without SSL support. They can be used later when MySQL slave with SSL will be started."
-"Server is running in --secure-auth mode, but '%s@%s' has a password in the old format; please change the password to the new format"
+"SSL parameters in CHANGE MASTER are ignored because this MySQL slave was compiled without SSL support. They can be used later when MySQL slave with SSL will be started.",
+"Server is running in --secure-auth mode, but '%s@%s' has a password in the old format; please change the password to the new format",
"Field or reference '%-.64s%s%-.64s%s%-.64s' of SELECT #%d was resolved in SELECT #%d",
-"Wrong parameter or combination of parameters for START SLAVE UNTIL"
-"It is recommended to run with --skip-slave-start when doing step-by-step replication with START SLAVE UNTIL, otherwise you are not safe in case of unexpected slave's mysqld restart"
-"SQL thread is not to be started so UNTIL options are ignored"
-"Incorrect index name '%-.100s'",
+"Wrong parameter or combination of parameters for START SLAVE UNTIL",
+"It is recommended to run with --skip-slave-start when doing step-by-step replication with START SLAVE UNTIL, otherwise you are not safe in case of unexpected slave's mysqld restart",
+"SQL thread is not to be started so UNTIL options are ignored",
+"Incorrect %s name '%-.100s'",
+"table",
+"database",
+"column",
+"index",
+"catalog",
"Query cache failed to set size %lu, new query cache size is %lu",
-"Column '%-.64s' cannot be part of FULLTEXT index"
+"Column '%-.64s' cannot be part of FULLTEXT index",
diff --git a/sql/share/korean/errmsg.txt b/sql/share/korean/errmsg.txt
index d31efc94d46..c5f2b8d59ba 100644
--- a/sql/share/korean/errmsg.txt
+++ b/sql/share/korean/errmsg.txt
@@ -267,21 +267,27 @@ character-set=euckr
"Record count is more than the column count at row %ld";
"Data truncated, NULL supplied to NOT NULL column '%s' at row %ld";
"Data truncated, out of range for column '%s' at row %ld";
-"Data truncated for column '%s' at row %ld"
+"Data truncated for column '%s' at row %ld",
"Using storage engine %s for table '%s'",
"Illegal mix of collations (%s,%s) and (%s,%s) for operation '%s'",
-"Can't drop one or more of the requested users"
-"Can't revoke all privileges, grant for one or more of the requested users"
+"Can't drop one or more of the requested users",
+"Can't revoke all privileges, grant for one or more of the requested users",
"Illegal mix of collations (%s,%s), (%s,%s), (%s,%s) for operation '%s'",
"Illegal mix of collations for operation '%s'",
"Variable '%-.64s' is not a variable component (Can't be used as XXXX.variable_name)",
"Unknown collation: '%-.64s'",
-"SSL parameters in CHANGE MASTER are ignored because this MySQL slave was compiled without SSL support. They can be used later when MySQL slave with SSL will be started."
-"Server is running in --secure-auth mode, but '%s@%s' has a password in the old format; please change the password to the new format"
+"SSL parameters in CHANGE MASTER are ignored because this MySQL slave was compiled without SSL support. They can be used later when MySQL slave with SSL will be started.",
+"Server is running in --secure-auth mode, but '%s@%s' has a password in the old format; please change the password to the new format",
"Field or reference '%-.64s%s%-.64s%s%-.64s' of SELECT #%d was resolved in SELECT #%d",
-"Wrong parameter or combination of parameters for START SLAVE UNTIL"
-"It is recommended to run with --skip-slave-start when doing step-by-step replication with START SLAVE UNTIL, otherwise you are not safe in case of unexpected slave's mysqld restart"
-"SQL thread is not to be started so UNTIL options are ignored"
-"Incorrect index name '%-.100s'",
+"Wrong parameter or combination of parameters for START SLAVE UNTIL",
+"It is recommended to run with --skip-slave-start when doing step-by-step replication with START SLAVE UNTIL, otherwise you are not safe in case of unexpected slave's mysqld restart",
+"SQL thread is not to be started so UNTIL options are ignored",
+"Incorrect %s name '%-.100s'",
+"table",
+"database",
+"column",
+"index",
+"catalog",
"Query cache failed to set size %lu, new query cache size is %lu",
-"Column '%-.64s' cannot be part of FULLTEXT index"
+"Column '%-.64s' cannot be part of FULLTEXT index",
+
diff --git a/sql/share/norwegian-ny/errmsg.txt b/sql/share/norwegian-ny/errmsg.txt
index 515a322f136..1e9028de1d7 100644
--- a/sql/share/norwegian-ny/errmsg.txt
+++ b/sql/share/norwegian-ny/errmsg.txt
@@ -269,21 +269,26 @@ character-set=latin1
"Record count is more than the column count at row %ld";
"Data truncated, NULL supplied to NOT NULL column '%s' at row %ld";
"Data truncated, out of range for column '%s' at row %ld";
-"Data truncated for column '%s' at row %ld"
+"Data truncated for column '%s' at row %ld",
"Using storage engine %s for table '%s'",
"Illegal mix of collations (%s,%s) and (%s,%s) for operation '%s'",
-"Can't drop one or more of the requested users"
-"Can't revoke all privileges, grant for one or more of the requested users"
+"Can't drop one or more of the requested users",
+"Can't revoke all privileges, grant for one or more of the requested users",
"Illegal mix of collations (%s,%s), (%s,%s), (%s,%s) for operation '%s'",
"Illegal mix of collations for operation '%s'",
"Variable '%-.64s' is not a variable component (Can't be used as XXXX.variable_name)",
"Unknown collation: '%-.64s'",
-"SSL parameters in CHANGE MASTER are ignored because this MySQL slave was compiled without SSL support. They can be used later when MySQL slave with SSL will be started."
-"Server is running in --secure-auth mode, but '%s@%s' has a password in the old format; please change the password to the new format"
+"SSL parameters in CHANGE MASTER are ignored because this MySQL slave was compiled without SSL support. They can be used later when MySQL slave with SSL will be started.",
+"Server is running in --secure-auth mode, but '%s@%s' has a password in the old format; please change the password to the new format",
"Field or reference '%-.64s%s%-.64s%s%-.64s' of SELECT #%d was resolved in SELECT #%d",
-"Wrong parameter or combination of parameters for START SLAVE UNTIL"
-"It is recommended to run with --skip-slave-start when doing step-by-step replication with START SLAVE UNTIL, otherwise you are not safe in case of unexpected slave's mysqld restart"
-"SQL thread is not to be started so UNTIL options are ignored"
-"Incorrect index name '%-.100s'",
+"Wrong parameter or combination of parameters for START SLAVE UNTIL",
+"It is recommended to run with --skip-slave-start when doing step-by-step replication with START SLAVE UNTIL, otherwise you are not safe in case of unexpected slave's mysqld restart",
+"SQL thread is not to be started so UNTIL options are ignored",
+"Incorrect %s name '%-.100s'",
+"table",
+"database",
+"column",
+"index",
+"catalog",
"Query cache failed to set size %lu, new query cache size is %lu",
-"Column '%-.64s' cannot be part of FULLTEXT index"
+"Column '%-.64s' cannot be part of FULLTEXT index",
diff --git a/sql/share/norwegian/errmsg.txt b/sql/share/norwegian/errmsg.txt
index faea5402fc6..d0a5e27b5c1 100644
--- a/sql/share/norwegian/errmsg.txt
+++ b/sql/share/norwegian/errmsg.txt
@@ -269,21 +269,27 @@ character-set=latin1
"Record count is more than the column count at row %ld";
"Data truncated, NULL supplied to NOT NULL column '%s' at row %ld";
"Data truncated, out of range for column '%s' at row %ld";
-"Data truncated for column '%s' at row %ld"
+"Data truncated for column '%s' at row %ld",
"Using storage engine %s for table '%s'",
"Illegal mix of collations (%s,%s) and (%s,%s) for operation '%s'",
-"Can't drop one or more of the requested users"
-"Can't revoke all privileges, grant for one or more of the requested users"
+"Can't drop one or more of the requested users",
+"Can't revoke all privileges, grant for one or more of the requested users",
"Illegal mix of collations (%s,%s), (%s,%s), (%s,%s) for operation '%s'",
"Illegal mix of collations for operation '%s'",
"Variable '%-.64s' is not a variable component (Can't be used as XXXX.variable_name)",
"Unknown collation: '%-.64s'",
-"SSL parameters in CHANGE MASTER are ignored because this MySQL slave was compiled without SSL support. They can be used later when MySQL slave with SSL will be started."
-"Server is running in --secure-auth mode, but '%s@%s' has a password in the old format; please change the password to the new format"
+"SSL parameters in CHANGE MASTER are ignored because this MySQL slave was compiled without SSL support. They can be used later when MySQL slave with SSL will be started.",
+"Server is running in --secure-auth mode, but '%s@%s' has a password in the old format; please change the password to the new format",
"Field or reference '%-.64s%s%-.64s%s%-.64s' of SELECT #%d was resolved in SELECT #%d",
-"Wrong parameter or combination of parameters for START SLAVE UNTIL"
-"It is recommended to run with --skip-slave-start when doing step-by-step replication with START SLAVE UNTIL, otherwise you are not safe in case of unexpected slave's mysqld restart"
-"SQL thread is not to be started so UNTIL options are ignored"
-"Incorrect index name '%-.100s'",
+"Wrong parameter or combination of parameters for START SLAVE UNTIL",
+"It is recommended to run with --skip-slave-start when doing step-by-step replication with START SLAVE UNTIL, otherwise you are not safe in case of unexpected slave's mysqld restart",
+"SQL thread is not to be started so UNTIL options are ignored",
+"Incorrect %s name '%-.100s'",
+"table",
+"database",
+"column",
+"index",
+"catalog",
"Query cache failed to set size %lu, new query cache size is %lu",
-"Column '%-.64s' cannot be part of FULLTEXT index"
+"Column '%-.64s' cannot be part of FULLTEXT index",
+
diff --git a/sql/share/polish/errmsg.txt b/sql/share/polish/errmsg.txt
index 2a7ea3accb8..17e6df6c443 100644
--- a/sql/share/polish/errmsg.txt
+++ b/sql/share/polish/errmsg.txt
@@ -271,21 +271,26 @@ character-set=latin2
"Record count is more than the column count at row %ld";
"Data truncated, NULL supplied to NOT NULL column '%s' at row %ld";
"Data truncated, out of range for column '%s' at row %ld";
-"Data truncated for column '%s' at row %ld"
+"Data truncated for column '%s' at row %ld",
"Using storage engine %s for table '%s'",
"Illegal mix of collations (%s,%s) and (%s,%s) for operation '%s'",
-"Can't drop one or more of the requested users"
-"Can't revoke all privileges, grant for one or more of the requested users"
+"Can't drop one or more of the requested users",
+"Can't revoke all privileges, grant for one or more of the requested users",
"Illegal mix of collations (%s,%s), (%s,%s), (%s,%s) for operation '%s'",
"Illegal mix of collations for operation '%s'",
"Variable '%-.64s' is not a variable component (Can't be used as XXXX.variable_name)",
"Unknown collation: '%-.64s'",
-"SSL parameters in CHANGE MASTER are ignored because this MySQL slave was compiled without SSL support. They can be used later when MySQL slave with SSL will be started."
-"Server is running in --secure-auth mode, but '%s@%s' has a password in the old format; please change the password to the new format"
+"SSL parameters in CHANGE MASTER are ignored because this MySQL slave was compiled without SSL support. They can be used later when MySQL slave with SSL will be started.",
+"Server is running in --secure-auth mode, but '%s@%s' has a password in the old format; please change the password to the new format",
"Field or reference '%-.64s%s%-.64s%s%-.64s' of SELECT #%d was resolved in SELECT #%d",
-"Wrong parameter or combination of parameters for START SLAVE UNTIL"
-"It is recommended to run with --skip-slave-start when doing step-by-step replication with START SLAVE UNTIL, otherwise you are not safe in case of unexpected slave's mysqld restart"
-"SQL thread is not to be started so UNTIL options are ignored"
-"Incorrect index name '%-.100s'",
+"Wrong parameter or combination of parameters for START SLAVE UNTIL",
+"It is recommended to run with --skip-slave-start when doing step-by-step replication with START SLAVE UNTIL, otherwise you are not safe in case of unexpected slave's mysqld restart",
+"SQL thread is not to be started so UNTIL options are ignored",
+"Incorrect %s name '%-.100s'",
+"table",
+"database",
+"column",
+"index",
+"catalog",
"Query cache failed to set size %lu, new query cache size is %lu",
-"Column '%-.64s' cannot be part of FULLTEXT index"
+"Column '%-.64s' cannot be part of FULLTEXT index",
diff --git a/sql/share/portuguese/errmsg.txt b/sql/share/portuguese/errmsg.txt
index 1f3bbb5c02f..fdf428c9b6d 100644
--- a/sql/share/portuguese/errmsg.txt
+++ b/sql/share/portuguese/errmsg.txt
@@ -241,7 +241,7 @@ character-set=latin1
"Errado uso/colocação de '%s'",
"Esta versão de MySQL não suporta ainda '%s'",
"Obteve fatal erro %d: '%-.128s' do master quando lendo dados do binary log",
-"Slave SQL thread ignorado a consulta devido às normas de replicação-*-tabela"
+"Slave SQL thread ignorado a consulta devido às normas de replicação-*-tabela",
"Definição errada da chave estrangeira para '%-.64s': %s",
"Referência da chave e referência da tabela não coincidem",
"Operand should contain %d column(s)",
@@ -268,21 +268,26 @@ character-set=latin1
"Record count is more than the column count at row %ld";
"Data truncated, NULL supplied to NOT NULL column '%s' at row %ld";
"Data truncated, out of range for column '%s' at row %ld";
-"Data truncated for column '%s' at row %ld"
+"Data truncated for column '%s' at row %ld",
"Usando engine de armazenamento %s para tabela '%s'",
"Combinação ilegal de collations (%s,%s) e (%s,%s) para operação '%s'",
-"Can't drop one or more of the requested users"
-"Can't revoke all privileges, grant for one or more of the requested users"
+"Can't drop one or more of the requested users",
+"Can't revoke all privileges, grant for one or more of the requested users",
"Illegal mix of collations (%s,%s), (%s,%s), (%s,%s) for operation '%s'",
"Illegal mix of collations for operation '%s'",
"Variable '%-.64s' is not a variable component (Can't be used as XXXX.variable_name)",
"Unknown collation: '%-.64s'",
-"SSL parameters in CHANGE MASTER are ignored because this MySQL slave was compiled without SSL support. They can be used later when MySQL slave with SSL will be started."
-"Server is running in --secure-auth mode, but '%s@%s' has a password in the old format; please change the password to the new format"
+"SSL parameters in CHANGE MASTER are ignored because this MySQL slave was compiled without SSL support. They can be used later when MySQL slave with SSL will be started.",
+"Server is running in --secure-auth mode, but '%s@%s' has a password in the old format; please change the password to the new format",
"Field or reference '%-.64s%s%-.64s%s%-.64s' of SELECT #%d was resolved in SELECT #%d",
-"Wrong parameter or combination of parameters for START SLAVE UNTIL"
-"It is recommended to run with --skip-slave-start when doing step-by-step replication with START SLAVE UNTIL, otherwise you are not safe in case of unexpected slave's mysqld restart"
-"SQL thread is not to be started so UNTIL options are ignored"
-"Incorrect index name '%-.100s'",
+"Wrong parameter or combination of parameters for START SLAVE UNTIL",
+"It is recommended to run with --skip-slave-start when doing step-by-step replication with START SLAVE UNTIL, otherwise you are not safe in case of unexpected slave's mysqld restart",
+"SQL thread is not to be started so UNTIL options are ignored",
+"Incorrect %s name '%-.100s'",
+"table",
+"database",
+"column",
+"index",
+"catalog",
"Query cache failed to set size %lu, new query cache size is %lu",
-"Column '%-.64s' cannot be part of FULLTEXT index"
+"Column '%-.64s' cannot be part of FULLTEXT index",
diff --git a/sql/share/romanian/errmsg.txt b/sql/share/romanian/errmsg.txt
index 78daafe04d1..8f4fdb3a702 100644
--- a/sql/share/romanian/errmsg.txt
+++ b/sql/share/romanian/errmsg.txt
@@ -252,7 +252,7 @@ character-set=latin2
"Unknown prepared statement handler (%ld) given to %s",
"Help database is corrupt or does not exist",
"Cyclic reference on subqueries",
-"Converting column '%s' from %s to %s"
+"Converting column '%s' from %s to %s",
"Reference '%-.64s' not supported (%s)",
"Every derived table must have it's own alias",
"Select %u was reduced during optimisation",
@@ -271,21 +271,26 @@ character-set=latin2
"Record count is more than the column count at row %ld";
"Data truncated, NULL supplied to NOT NULL column '%s' at row %ld";
"Data truncated, out of range for column '%s' at row %ld";
-"Data truncated for column '%s' at row %ld"
+"Data truncated for column '%s' at row %ld",
"Using storage engine %s for table '%s'",
"Illegal mix of collations (%s,%s) and (%s,%s) for operation '%s'",
-"Can't drop one or more of the requested users"
-"Can't revoke all privileges, grant for one or more of the requested users"
+"Can't drop one or more of the requested users",
+"Can't revoke all privileges, grant for one or more of the requested users",
"Illegal mix of collations (%s,%s), (%s,%s), (%s,%s) for operation '%s'",
"Illegal mix of collations for operation '%s'",
"Variable '%-.64s' is not a variable component (Can't be used as XXXX.variable_name)",
"Unknown collation: '%-.64s'",
-"SSL parameters in CHANGE MASTER are ignored because this MySQL slave was compiled without SSL support. They can be used later when MySQL slave with SSL will be started."
-"Server is running in --secure-auth mode, but '%s@%s' has a password in the old format; please change the password to the new format"
+"SSL parameters in CHANGE MASTER are ignored because this MySQL slave was compiled without SSL support. They can be used later when MySQL slave with SSL will be started.",
+"Server is running in --secure-auth mode, but '%s@%s' has a password in the old format; please change the password to the new format",
"Field or reference '%-.64s%s%-.64s%s%-.64s' of SELECT #%d was resolved in SELECT #%d",
-"Wrong parameter or combination of parameters for START SLAVE UNTIL"
-"It is recommended to run with --skip-slave-start when doing step-by-step replication with START SLAVE UNTIL, otherwise you are not safe in case of unexpected slave's mysqld restart"
-"SQL thread is not to be started so UNTIL options are ignored"
-"Incorrect index name '%-.100s'",
+"Wrong parameter or combination of parameters for START SLAVE UNTIL",
+"It is recommended to run with --skip-slave-start when doing step-by-step replication with START SLAVE UNTIL, otherwise you are not safe in case of unexpected slave's mysqld restart",
+"SQL thread is not to be started so UNTIL options are ignored",
+"Incorrect %s name '%-.100s'",
+"table",
+"database",
+"column",
+"index",
+"catalog",
"Query cache failed to set size %lu, new query cache size is %lu",
-"Column '%-.64s' cannot be part of FULLTEXT index"
+"Column '%-.64s' cannot be part of FULLTEXT index",
diff --git a/sql/share/russian/errmsg.txt b/sql/share/russian/errmsg.txt
index 462afdfa782..2ef6a2c553b 100644
--- a/sql/share/russian/errmsg.txt
+++ b/sql/share/russian/errmsg.txt
@@ -269,21 +269,26 @@ character-set=koi8r
"Record count is more than the column count at row %ld";
"Data truncated, NULL supplied to NOT NULL column '%s' at row %ld";
"Data truncated, out of range for column '%s' at row %ld";
-"Data truncated for column '%s' at row %ld"
+"Data truncated for column '%s' at row %ld",
"Using storage engine %s for table '%s'",
"Illegal mix of collations (%s,%s) and (%s,%s) for operation '%s'",
-"Can't drop one or more of the requested users"
-"Can't revoke all privileges, grant for one or more of the requested users"
+"Can't drop one or more of the requested users",
+"Can't revoke all privileges, grant for one or more of the requested users",
"Illegal mix of collations (%s,%s), (%s,%s), (%s,%s) for operation '%s'",
"Illegal mix of collations for operation '%s'",
"Variable '%-.64s' is not a variable component (Can't be used as XXXX.variable_name)",
"Unknown collation: '%-.64s'",
-"SSL parameters in CHANGE MASTER are ignored because this MySQL slave was compiled without SSL support. They can be used later when MySQL slave with SSL will be started."
-"óÅÒ×ÅÒ ÚÁÐÕÝÅÎ × ÒÅÖÉÍÅ --secure-auth (ÂÅÚÏÐÁÓÎÏÊ Á×ÔÏÒÉÚÁÃÉÉ), ÎÏ ÄÌÑ ÐÏÌØÚÏ×ÁÔÅÌÑ '%s@%s' ÐÁÒÏÌØ ÓÏÈÒÁÎ£Î × ÓÔÁÒÏÍ ÆÏÒÍÁÔÅ; ÎÅÏÂÈÏÄÉÍÏ ÏÂÎÏ×ÉÔØ ÆÏÒÍÁÔ ÐÁÒÏÌÑ"
+"SSL parameters in CHANGE MASTER are ignored because this MySQL slave was compiled without SSL support. They can be used later when MySQL slave with SSL will be started.",
+"óÅÒ×ÅÒ ÚÁÐÕÝÅÎ × ÒÅÖÉÍÅ --secure-auth (ÂÅÚÏÐÁÓÎÏÊ Á×ÔÏÒÉÚÁÃÉÉ), ÎÏ ÄÌÑ ÐÏÌØÚÏ×ÁÔÅÌÑ '%s@%s' ÐÁÒÏÌØ ÓÏÈÒÁÎ£Î × ÓÔÁÒÏÍ ÆÏÒÍÁÔÅ; ÎÅÏÂÈÏÄÉÍÏ ÏÂÎÏ×ÉÔØ ÆÏÒÍÁÔ ÐÁÒÏÌÑ",
"ðÏÌÅ ÉÌÉ ÓÓÙÌËÁ '%-.64s%s%-.64s%s%-.64s' ÉÚ SELECTÁ #%d ÂÙÌÁ ÎÁÊÄÅÎÁ × SELECTÅ #%d",
-"Wrong parameter or combination of parameters for START SLAVE UNTIL"
-"It is recommended to run with --skip-slave-start when doing step-by-step replication with START SLAVE UNTIL, otherwise you are not safe in case of unexpected slave's mysqld restart"
-"SQL thread is not to be started so UNTIL options are ignored"
-"Incorrect index name '%-.100s'",
+"Wrong parameter or combination of parameters for START SLAVE UNTIL",
+"It is recommended to run with --skip-slave-start when doing step-by-step replication with START SLAVE UNTIL, otherwise you are not safe in case of unexpected slave's mysqld restart",
+"SQL thread is not to be started so UNTIL options are ignored",
+"Incorrect %s name '%-.100s'",
+"table",
+"database",
+"column",
+"index",
+"catalog",
"ëÅÛ ÚÁÐÒÏÓÏ× ÎÅ ÍÏÖÅÔ ÕÓÔÁÎÏ×ÉÔØ ÒÁÚÍÅÒ %lu, ÎÏ×ÙÊ ÒÁÚÍÅÒ ËÅÛÁ ÚÐÒÏÓÏ× - %lu",
-"Column '%-.64s' cannot be part of FULLTEXT index"
+"Column '%-.64s' cannot be part of FULLTEXT index",
diff --git a/sql/share/serbian/errmsg.txt b/sql/share/serbian/errmsg.txt
index 9d12654f150..cddc1059f44 100644
--- a/sql/share/serbian/errmsg.txt
+++ b/sql/share/serbian/errmsg.txt
@@ -262,21 +262,26 @@ character-set=cp1250
"Record count is more than the column count at row %ld";
"Data truncated, NULL supplied to NOT NULL column '%s' at row %ld";
"Data truncated, out of range for column '%s' at row %ld";
-"Data truncated for column '%s' at row %ld"
+"Data truncated for column '%s' at row %ld",
"Using storage engine %s for table '%s'",
"Illegal mix of collations (%s,%s) and (%s,%s) for operation '%s'",
-"Can't drop one or more of the requested users"
-"Can't revoke all privileges, grant for one or more of the requested users"
+"Can't drop one or more of the requested users",
+"Can't revoke all privileges, grant for one or more of the requested users",
"Illegal mix of collations (%s,%s), (%s,%s), (%s,%s) for operation '%s'",
"Illegal mix of collations for operation '%s'",
"Variable '%-.64s' is not a variable component (Can't be used as XXXX.variable_name)",
"Unknown collation: '%-.64s'",
-"SSL parameters in CHANGE MASTER are ignored because this MySQL slave was compiled without SSL support. They can be used later when MySQL slave with SSL will be started."
-"Server is running in --secure-auth mode, but '%s@%s' has a password in the old format; please change the password to the new format"
+"SSL parameters in CHANGE MASTER are ignored because this MySQL slave was compiled without SSL support. They can be used later when MySQL slave with SSL will be started.",
+"Server is running in --secure-auth mode, but '%s@%s' has a password in the old format; please change the password to the new format",
"Field or reference '%-.64s%s%-.64s%s%-.64s' of SELECT #%d was resolved in SELECT #%d",
-"Wrong parameter or combination of parameters for START SLAVE UNTIL"
-"It is recommended to run with --skip-slave-start when doing step-by-step replication with START SLAVE UNTIL, otherwise you are not safe in case of unexpected slave's mysqld restart"
-"SQL thread is not to be started so UNTIL options are ignored"
-"Incorrect index name '%-.100s'",
+"Wrong parameter or combination of parameters for START SLAVE UNTIL",
+"It is recommended to run with --skip-slave-start when doing step-by-step replication with START SLAVE UNTIL, otherwise you are not safe in case of unexpected slave's mysqld restart",
+"SQL thread is not to be started so UNTIL options are ignored",
+"Incorrect %s name '%-.100s'",
+"table",
+"database",
+"column",
+"index",
+"catalog",
"Query cache failed to set size %lu, new query cache size is %lu",
-"Column '%-.64s' cannot be part of FULLTEXT index"
+"Column '%-.64s' cannot be part of FULLTEXT index",
diff --git a/sql/share/slovak/errmsg.txt b/sql/share/slovak/errmsg.txt
index dd222c2ef30..466e7d478b6 100644
--- a/sql/share/slovak/errmsg.txt
+++ b/sql/share/slovak/errmsg.txt
@@ -275,21 +275,26 @@ character-set=latin2
"Record count is more than the column count at row %ld";
"Data truncated, NULL supplied to NOT NULL column '%s' at row %ld";
"Data truncated, out of range for column '%s' at row %ld";
-"Data truncated for column '%s' at row %ld"
+"Data truncated for column '%s' at row %ld",
"Using storage engine %s for table '%s'",
"Illegal mix of collations (%s,%s) and (%s,%s) for operation '%s'",
-"Can't drop one or more of the requested users"
-"Can't revoke all privileges, grant for one or more of the requested users"
+"Can't drop one or more of the requested users",
+"Can't revoke all privileges, grant for one or more of the requested users",
"Illegal mix of collations (%s,%s), (%s,%s), (%s,%s) for operation '%s'",
"Illegal mix of collations for operation '%s'",
"Variable '%-.64s' is not a variable component (Can't be used as XXXX.variable_name)",
"Unknown collation: '%-.64s'",
-"SSL parameters in CHANGE MASTER are ignored because this MySQL slave was compiled without SSL support. They can be used later when MySQL slave with SSL will be started."
-"Server is running in --secure-auth mode, but '%s@%s' has a password in the old format; please change the password to the new format"
+"SSL parameters in CHANGE MASTER are ignored because this MySQL slave was compiled without SSL support. They can be used later when MySQL slave with SSL will be started.",
+"Server is running in --secure-auth mode, but '%s@%s' has a password in the old format; please change the password to the new format",
"Field or reference '%-.64s%s%-.64s%s%-.64s' of SELECT #%d was resolved in SELECT #%d",
-"Wrong parameter or combination of parameters for START SLAVE UNTIL"
-"It is recommended to run with --skip-slave-start when doing step-by-step replication with START SLAVE UNTIL, otherwise you are not safe in case of unexpected slave's mysqld restart"
-"SQL thread is not to be started so UNTIL options are ignored"
-"Incorrect index name '%-.100s'",
+"Wrong parameter or combination of parameters for START SLAVE UNTIL",
+"It is recommended to run with --skip-slave-start when doing step-by-step replication with START SLAVE UNTIL, otherwise you are not safe in case of unexpected slave's mysqld restart",
+"SQL thread is not to be started so UNTIL options are ignored",
+"Incorrect %s name '%-.100s'",
+"table",
+"database",
+"column",
+"index",
+"catalog",
"Query cache failed to set size %lu, new query cache size is %lu",
-"Column '%-.64s' cannot be part of FULLTEXT index"
+"Column '%-.64s' cannot be part of FULLTEXT index",
diff --git a/sql/share/spanish/errmsg.txt b/sql/share/spanish/errmsg.txt
index a21d306a3db..de8a245c7f9 100644
--- a/sql/share/spanish/errmsg.txt
+++ b/sql/share/spanish/errmsg.txt
@@ -242,7 +242,7 @@ character-set=latin1
"Equivocado uso/colocación de '%s'",
"Esta versión de MySQL no soporta todavia '%s'",
"Recibió fatal error %d: '%-.128s' del master cuando leyendo datos del binary log",
-"Slave SQL thread ignorado el query debido a las reglas de replicación-*-tabla"
+"Slave SQL thread ignorado el query debido a las reglas de replicación-*-tabla",
"Wrong foreign key definition for '%-.64s': %s",
"Key reference and table reference doesn't match",
"Operand should contain %d column(s)",
@@ -269,21 +269,26 @@ character-set=latin1
"Record count is more than the column count at row %ld";
"Data truncated, NULL supplied to NOT NULL column '%s' at row %ld";
"Data truncated, out of range for column '%s' at row %ld";
-"Data truncated for column '%s' at row %ld"
+"Data truncated for column '%s' at row %ld",
"Using storage engine %s for table '%s'",
"Illegal mix of collations (%s,%s) and (%s,%s) for operation '%s'",
-"Can't drop one or more of the requested users"
-"Can't revoke all privileges, grant for one or more of the requested users"
+"Can't drop one or more of the requested users",
+"Can't revoke all privileges, grant for one or more of the requested users",
"Illegal mix of collations (%s,%s), (%s,%s), (%s,%s) for operation '%s'",
"Illegal mix of collations for operation '%s'",
"Variable '%-.64s' is not a variable component (Can't be used as XXXX.variable_name)",
"Unknown collation: '%-.64s'",
-"SSL parameters in CHANGE MASTER are ignored because this MySQL slave was compiled without SSL support. They can be used later when MySQL slave with SSL will be started."
-"Server is running in --secure-auth mode, but '%s@%s' has a password in the old format; please change the password to the new format"
+"SSL parameters in CHANGE MASTER are ignored because this MySQL slave was compiled without SSL support. They can be used later when MySQL slave with SSL will be started.",
+"Server is running in --secure-auth mode, but '%s@%s' has a password in the old format; please change the password to the new format",
"Field or reference '%-.64s%s%-.64s%s%-.64s' of SELECT #%d was resolved in SELECT #%d",
-"Wrong parameter or combination of parameters for START SLAVE UNTIL"
-"It is recommended to run with --skip-slave-start when doing step-by-step replication with START SLAVE UNTIL, otherwise you are not safe in case of unexpected slave's mysqld restart"
-"SQL thread is not to be started so UNTIL options are ignored"
-"Incorrect index name '%-.100s'",
+"Wrong parameter or combination of parameters for START SLAVE UNTIL",
+"It is recommended to run with --skip-slave-start when doing step-by-step replication with START SLAVE UNTIL, otherwise you are not safe in case of unexpected slave's mysqld restart",
+"SQL thread is not to be started so UNTIL options are ignored",
+"Incorrect %s name '%-.100s'",
+"table",
+"database",
+"column",
+"index",
+"catalog",
"Query cache failed to set size %lu, new query cache size is %lu",
-"Column '%-.64s' cannot be part of FULLTEXT index"
+"Column '%-.64s' cannot be part of FULLTEXT index",
diff --git a/sql/share/swedish/errmsg.txt b/sql/share/swedish/errmsg.txt
index 4d3e69a5b0f..d8695db30a4 100644
--- a/sql/share/swedish/errmsg.txt
+++ b/sql/share/swedish/errmsg.txt
@@ -225,7 +225,7 @@ character-set=latin1
"Fick fel vid utförande av command på mastern: %-.128s",
"Fick fel vid utförande av %s: %-.128s",
"Felaktig använding av %s and %s",
-"SELECT-kommandona har olika antal kolumner"
+"SELECT-kommandona har olika antal kolumner",
"Kan inte utföra kommandot emedan du har ett READ-lås",
"Blandning av transaktionella och icke-transaktionella tabeller är inaktiverat",
"Option '%s' användes två gånger",
@@ -267,21 +267,26 @@ character-set=latin1
"Record count is more than the column count at row %ld";
"Data truncated, NULL supplied to NOT NULL column '%s' at row %ld";
"Data truncated, out of range for column '%s' at row %ld";
-"Data truncated for column '%s' at row %ld"
+"Data truncated for column '%s' at row %ld",
"Använder handler %s för tabell '%s'",
"Illegal mix of collations (%s,%s) and (%s,%s) for operation '%s'",
-"Can't drop one or more of the requested users"
-"Can't revoke all privileges, grant for one or more of the requested users"
+"Can't drop one or more of the requested users",
+"Can't revoke all privileges, grant for one or more of the requested users",
"Illegal mix of collations (%s,%s), (%s,%s), (%s,%s) for operation '%s'",
"Illegal mix of collations for operation '%s'",
"Variable '%-.64s' is not a variable component (Can't be used as XXXX.variable_name)",
"Unknown collation: '%-.64s'",
-"SSL parameters in CHANGE MASTER are ignored because this MySQL slave was compiled without SSL support. They can be used later when MySQL slave with SSL will be started."
-"Server is running in --secure-auth mode, but '%s@%s' has a password in the old format; please change the password to the new format"
+"SSL parameters in CHANGE MASTER are ignored because this MySQL slave was compiled without SSL support. They can be used later when MySQL slave with SSL will be started.",
+"Server is running in --secure-auth mode, but '%s@%s' has a password in the old format; please change the password to the new format",
"Field or reference '%-.64s%s%-.64s%s%-.64s' of SELECT #%d was resolved in SELECT #%d",
-"Wrong parameter or combination of parameters for START SLAVE UNTIL"
-"It is recommended to run with --skip-slave-start when doing step-by-step replication with START SLAVE UNTIL, otherwise you are not safe in case of unexpected slave's mysqld restart"
-"SQL thread is not to be started so UNTIL options are ignored"
-"Incorrect index name '%-.100s'",
-"Query cache failed to set size %lu, new query cache size is %lu",
-"Column '%-.64s' cannot be part of FULLTEXT index"
+"Wrong parameter or combination of parameters for START SLAVE UNTIL",
+"It is recommended to run with --skip-slave-start when doing step-by-step replication with START SLAVE UNTIL, otherwise you are not safe in case of unexpected slave's mysqld restart",
+"SQL thread is not to be started so UNTIL options are ignored",
+"Felaktigt %s namn '%-.100s'",
+"tabell",
+"databas",
+"kolumn",
+"index",
+"katalog",
+"Storleken av "Query cache" kunde inte sättas till %lu, ny storlek är %lu",
+"Kolumn '%-.64s' kan inte vara del av ett FULLTEXT index",
diff --git a/sql/share/ukrainian/errmsg.txt b/sql/share/ukrainian/errmsg.txt
index 283700b7891..3a37ee02731 100644
--- a/sql/share/ukrainian/errmsg.txt
+++ b/sql/share/ukrainian/errmsg.txt
@@ -272,21 +272,26 @@ character-set=koi8u
"Record count is more than the column count at row %ld";
"Data truncated, NULL supplied to NOT NULL column '%s' at row %ld";
"Data truncated, out of range for column '%s' at row %ld";
-"Data truncated for column '%s' at row %ld"
+"Data truncated for column '%s' at row %ld",
"Using storage engine %s for table '%s'",
"Illegal mix of collations (%s,%s) and (%s,%s) for operation '%s'",
-"Can't drop one or more of the requested users"
-"Can't revoke all privileges, grant for one or more of the requested users"
+"Can't drop one or more of the requested users",
+"Can't revoke all privileges, grant for one or more of the requested users",
"Illegal mix of collations (%s,%s), (%s,%s), (%s,%s) for operation '%s'",
"Illegal mix of collations for operation '%s'",
"Variable '%-.64s' is not a variable component (Can't be used as XXXX.variable_name)",
"Unknown collation: '%-.64s'",
-"SSL parameters in CHANGE MASTER are ignored because this MySQL slave was compiled without SSL support. They can be used later when MySQL slave with SSL will be started."
-"Server is running in --secure-auth mode, but '%s@%s' has a password in the old format; please change the password to the new format"
+"SSL parameters in CHANGE MASTER are ignored because this MySQL slave was compiled without SSL support. They can be used later when MySQL slave with SSL will be started.",
+"Server is running in --secure-auth mode, but '%s@%s' has a password in the old format; please change the password to the new format",
"óÔÏ×ÂÅÃØ ÁÂÏ ÐÏÓÉÌÁÎÎÑ '%-.64s%s%-.64s%s%-.64s' ¦Ú SELECTÕ #%d ÂÕÌÏ ÚÎÁÊÄÅÎÅ Õ SELECT¦ #%d",
-"Wrong parameter or combination of parameters for START SLAVE UNTIL"
-"It is recommended to run with --skip-slave-start when doing step-by-step replication with START SLAVE UNTIL, otherwise you are not safe in case of unexpected slave's mysqld restart"
-"SQL thread is not to be started so UNTIL options are ignored"
-"Incorrect index name '%-.100s'",
+"Wrong parameter or combination of parameters for START SLAVE UNTIL",
+"It is recommended to run with --skip-slave-start when doing step-by-step replication with START SLAVE UNTIL, otherwise you are not safe in case of unexpected slave's mysqld restart",
+"SQL thread is not to be started so UNTIL options are ignored",
+"Incorrect %s name '%-.100s'",
+"table",
+"database",
+"column",
+"index",
+"catalog",
"ëÅÛ ÚÁÐÉÔ¦× ÎÅÓÐÒÏÍÏÖÅÎ ×ÓÔÁÎÏ×ÉÔÉ ÒÏÚÍ¦Ò %lu, ÎÏ×ÉÊ ÒÏÚÍ¦Ò ËÅÛÁ ÚÁÐÉÔ¦× - %lu",
-"Column '%-.64s' cannot be part of FULLTEXT index"
+"Column '%-.64s' cannot be part of FULLTEXT index",
diff --git a/sql/sql_base.cc b/sql/sql_base.cc
index cc068451ecf..88a1d21354b 100644
--- a/sql/sql_base.cc
+++ b/sql/sql_base.cc
@@ -2210,7 +2210,8 @@ void get_key_map_from_key_list(key_map *map, TABLE *table,
map->clear_all();
while ((name=it++))
{
- if ((pos=find_type(name->c_ptr(), &table->keynames, 1+2)) <= 0)
+ if ((pos= find_type(&table->keynames, name->ptr(), name->length(), 1)) <=
+ 0)
{
my_error(ER_KEY_COLUMN_DOES_NOT_EXITS, MYF(0), name->c_ptr(),
table->real_name);
diff --git a/sql/sql_class.cc b/sql/sql_class.cc
index ed8eaba9128..ed01e1bb038 100644
--- a/sql/sql_class.cc
+++ b/sql/sql_class.cc
@@ -210,6 +210,12 @@ void THD::init(void)
{
pthread_mutex_lock(&LOCK_global_system_variables);
variables= global_system_variables;
+ variables.time_format= date_time_format_copy((THD*) 0,
+ variables.time_format);
+ variables.date_format= date_time_format_copy((THD*) 0,
+ variables.date_format);
+ variables.datetime_format= date_time_format_copy((THD*) 0,
+ variables.datetime_format);
pthread_mutex_unlock(&LOCK_global_system_variables);
server_status= SERVER_STATUS_AUTOCOMMIT;
options= thd_startup_options;
@@ -281,9 +287,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();
+ my_free((char*) variables.time_format, MYF(MY_ALLOW_ZERO_PTR));
+ my_free((char*) variables.date_format, MYF(MY_ALLOW_ZERO_PTR));
+ my_free((char*) variables.datetime_format, MYF(MY_ALLOW_ZERO_PTR));
delete_dynamic(&user_var_events);
hash_free(&user_vars);
if (global_read_lock)
diff --git a/sql/sql_class.h b/sql/sql_class.h
index a103bab1d6c..c66ebb77020 100644
--- a/sql/sql_class.h
+++ b/sql/sql_class.h
@@ -421,7 +421,11 @@ struct system_variables
CHARSET_INFO *collation_server;
CHARSET_INFO *collation_database;
CHARSET_INFO *collation_connection;
- sys_var_datetime_format datetime_formats[3];
+
+ /* DATE, DATETIME and TIME formats */
+ DATE_TIME_FORMAT *date_format;
+ DATE_TIME_FORMAT *datetime_format;
+ DATE_TIME_FORMAT *time_format;
};
void free_tmp_table(THD *thd, TABLE *entry);
diff --git a/sql/sql_db.cc b/sql/sql_db.cc
index b0f4b4ef574..b7d6c642398 100644
--- a/sql/sql_db.cc
+++ b/sql/sql_db.cc
@@ -609,7 +609,7 @@ bool mysql_change_db(THD *thd, const char *name)
}
if ((db_length > NAME_LEN) || check_db_name(dbname))
{
- net_printf(thd,ER_WRONG_DB_NAME, dbname);
+ net_printf(thd, ER_WRONG_NAME, ER(ER_DATABASE), dbname);
x_free(dbname);
DBUG_RETURN(1);
}
@@ -675,7 +675,7 @@ int mysqld_show_create_db(THD *thd, char *dbname,
if (check_db_name(dbname))
{
- net_printf(thd,ER_WRONG_DB_NAME, dbname);
+ net_printf(thd,ER_WRONG_NAME, ER(ER_DATABASE), dbname);
DBUG_RETURN(1);
}
diff --git a/sql/sql_lex.cc b/sql/sql_lex.cc
index 93c4658d38c..a55b801a0fc 100644
--- a/sql/sql_lex.cc
+++ b/sql/sql_lex.cc
@@ -40,10 +40,18 @@ LEX_STRING tmp_table_alias= {(char*) "tmp-table",8};
pthread_key(LEX*,THR_LEX);
+/* Longest standard keyword name */
#define TOCK_NAME_LENGTH 24
/*
- The following is based on the latin1 character set, and is only
+ Map to default keyword characters. This is used to test if an identifer
+ is 'simple', in which case we don't have to do any character set conversions
+ on it
+*/
+uchar *bin_ident_map= my_charset_bin.ident_map;
+
+/*
+ The following data is based on the latin1 character set, and is only
used when comparing keywords
*/
@@ -66,6 +74,7 @@ uchar to_upper_lex[] = {
208,209,210,211,212,213,214,247,216,217,218,219,220,221,222,255
};
+
inline int lex_casecmp(const char *s, const char *t, uint len)
{
while (len-- != 0 &&
@@ -410,15 +419,18 @@ inline static uint int_token(const char *str,uint length)
}
-// yylex remember the following states from the following yylex()
-// MY_LEX_EOQ ; found end of query
-// MY_LEX_OPERATOR_OR_IDENT ; last state was an ident, text or number
-// (which can't be followed by a signed number)
+/*
+ yylex remember the following states from the following yylex()
+
+ - MY_LEX_EOQ Found end of query
+ - MY_LEX_OPERATOR_OR_IDENT Last state was an ident, text or number
+ (which can't be followed by a signed number)
+*/
int yylex(void *arg, void *yythd)
{
reg1 uchar c;
- int tokval;
+ int tokval, result_state;
uint length;
enum my_lex_states state,prev_state;
LEX *lex= &(((THD *)yythd)->lex);
@@ -503,6 +515,7 @@ int yylex(void *arg, void *yythd)
#if defined(USE_MB) && defined(USE_MB_IDENT)
if (use_mb(cs))
{
+ result_state= IDENT_QUOTED;
if (my_mbcharlen(cs, yyGetLast()) > 1)
{
int l = my_ismbchar(cs,
@@ -529,7 +542,15 @@ int yylex(void *arg, void *yythd)
}
else
#endif
- while (ident_map[c=yyGet()]) ;
+ {
+ result_state= bin_ident_map[c] ? IDENT : IDENT_QUOTED;
+ while (ident_map[c=yyGet()])
+ {
+ /* If not simple character, mark that we must convert it */
+ if (!bin_ident_map[c])
+ result_state= IDENT_QUOTED;
+ }
+ }
length= (uint) (lex->ptr - lex->tok_start)-1;
if (lex->ignore_space)
{
@@ -560,8 +581,7 @@ int yylex(void *arg, void *yythd)
(lex->charset=get_charset_by_csname(yylval->lex_str.str+1,
MY_CS_PRIMARY,MYF(0))))
return(UNDERSCORE_CHARSET);
- else
- return(IDENT);
+ return(result_state); // IDENT or IDENT_QUOTED
case MY_LEX_IDENT_SEP: // Found ident and now '.'
yylval->lex_str.str=(char*) lex->ptr;
@@ -611,21 +631,11 @@ int yylex(void *arg, void *yythd)
}
// fall through
case MY_LEX_IDENT_START: // We come here after '.'
+ result_state= IDENT;
#if defined(USE_MB) && defined(USE_MB_IDENT)
if (use_mb(cs))
{
- if (my_mbcharlen(cs, yyGetLast()) > 1)
- {
- int l = my_ismbchar(cs,
- (const char *)lex->ptr-1,
- (const char *)lex->end_of_query);
- if (l == 0)
- {
- state = MY_LEX_CHAR;
- continue;
- }
- lex->ptr += l - 1;
- }
+ result_state= IDENT_QUOTED;
while (ident_map[c=yyGet()])
{
if (my_mbcharlen(cs, c) > 1)
@@ -641,15 +651,17 @@ int yylex(void *arg, void *yythd)
}
else
#endif
- while (ident_map[c = yyGet()]) ;
-
+ while (ident_map[c = yyGet()])
+ {
+ /* If not simple character, mark that we must convert it */
+ if (!bin_ident_map[c])
+ result_state= IDENT_QUOTED;
+ }
if (c == '.' && ident_map[yyPeek()])
lex->next_state=MY_LEX_IDENT_SEP;// Next is '.'
- // fall through
- case MY_LEX_FOUND_IDENT: // Complete ident
- yylval->lex_str=get_token(lex,yyLength());
- return(IDENT);
+ yylval->lex_str= get_token(lex,yyLength());
+ return(result_state);
case MY_LEX_USER_VARIABLE_DELIMITER:
{
@@ -699,7 +711,7 @@ int yylex(void *arg, void *yythd)
if (c == delim)
yySkip(); // Skip end `
lex->next_state= MY_LEX_START;
- return(IDENT);
+ return(IDENT_QUOTED);
}
case MY_LEX_INT_OR_REAL: // Compleat int or incompleat real
if (c != '.')
@@ -924,7 +936,13 @@ int yylex(void *arg, void *yythd)
We should now be able to handle:
[(global | local | session) .]variable_name
*/
- while (ident_map[c=yyGet()]) ;
+ result_state= IDENT;
+ while (ident_map[c=yyGet()])
+ {
+ /* If not simple character, mark that we must convert it */
+ if (!bin_ident_map[c])
+ result_state= IDENT_QUOTED;
+ }
if (c == '.')
lex->next_state=MY_LEX_IDENT_SEP;
length= (uint) (lex->ptr - lex->tok_start)-1;
@@ -934,7 +952,7 @@ int yylex(void *arg, void *yythd)
return(tokval); // Was keyword
}
yylval->lex_str=get_token(lex,length);
- return(IDENT);
+ return(result_state);
}
}
}
diff --git a/sql/sql_parse.cc b/sql/sql_parse.cc
index f377714461d..d6f8e2f66c7 100644
--- a/sql/sql_parse.cc
+++ b/sql/sql_parse.cc
@@ -1041,7 +1041,7 @@ int mysql_table_dump(THD* thd, char* db, char* tbl_name, int fd)
if (!db || check_db_name(db))
{
- net_printf(thd,ER_WRONG_DB_NAME, db ? db : "NULL");
+ net_printf(thd,ER_WRONG_NAME, ER(ER_DATABASE), db ? db : "NULL");
goto err;
}
if (lower_case_table_names)
@@ -1382,7 +1382,7 @@ bool dispatch_command(enum enum_server_command command, THD *thd,
// null test to handle EOM
if (!db || !strip_sp(db) || check_db_name(db))
{
- net_printf(thd,ER_WRONG_DB_NAME, db ? db : "NULL");
+ net_printf(thd,ER_WRONG_NAME, ER(ER_DATABASE), db ? db : "NULL");
break;
}
if (check_access(thd,CREATE_ACL,db,0,1,0))
@@ -1398,7 +1398,7 @@ bool dispatch_command(enum enum_server_command command, THD *thd,
// null test to handle EOM
if (!db || !strip_sp(db) || check_db_name(db))
{
- net_printf(thd,ER_WRONG_DB_NAME, db ? db : "NULL");
+ net_printf(thd,ER_WRONG_NAME, ER(ER_DATABASE), db ? db : "NULL");
break;
}
if (check_access(thd,DROP_ACL,db,0,1,0))
@@ -1999,7 +1999,7 @@ mysql_execute_command(THD *thd)
#endif
if (strlen(tables->real_name) > NAME_LEN)
{
- net_printf(thd,ER_WRONG_TABLE_NAME,tables->real_name);
+ net_printf(thd,ER_WRONG_NAME, ER(ER_TABLE), tables->real_name);
break;
}
LOCK_ACTIVE_MI;
@@ -2044,7 +2044,7 @@ mysql_execute_command(THD *thd)
#endif
if (strlen(tables->real_name) > NAME_LEN)
{
- net_printf(thd, ER_WRONG_TABLE_NAME, tables->alias);
+ net_printf(thd, ER_WRONG_NAME, ER(ER_TABLE), tables->alias);
res=0;
break;
}
@@ -2176,7 +2176,7 @@ mysql_execute_command(THD *thd)
ulong priv=0;
if (lex->name && (!lex->name[0] || strlen(lex->name) > NAME_LEN))
{
- net_printf(thd,ER_WRONG_TABLE_NAME,lex->name);
+ net_printf(thd, ER_WRONG_NAME, ER(ER_TABLE), lex->name);
res=0;
break;
}
@@ -2750,7 +2750,7 @@ mysql_execute_command(THD *thd)
remove_escape(db); // Fix escaped '_'
if (check_db_name(db))
{
- net_printf(thd,ER_WRONG_DB_NAME, db);
+ net_printf(thd,ER_WRONG_NAME, ER(ER_DATABASE), db);
goto error;
}
#ifndef NO_EMBEDDED_ACCESS_CHECKS
@@ -2915,7 +2915,7 @@ mysql_execute_command(THD *thd)
{
if (!strip_sp(lex->name) || check_db_name(lex->name))
{
- net_printf(thd,ER_WRONG_DB_NAME, lex->name);
+ net_printf(thd,ER_WRONG_NAME, ER(ER_DATABASE), lex->name);
break;
}
/*
@@ -2943,7 +2943,7 @@ mysql_execute_command(THD *thd)
{
if (!strip_sp(lex->name) || check_db_name(lex->name))
{
- net_printf(thd,ER_WRONG_DB_NAME, lex->name);
+ net_printf(thd, ER_WRONG_NAME, ER(ER_DATABASE), lex->name);
break;
}
/*
@@ -2976,7 +2976,7 @@ mysql_execute_command(THD *thd)
{
if (!strip_sp(lex->name) || check_db_name(lex->name))
{
- net_printf(thd,ER_WRONG_DB_NAME, lex->name);
+ net_printf(thd, ER_WRONG_NAME, ER(ER_DATABASE), lex->name);
break;
}
if (check_access(thd,ALTER_ACL,lex->name,0,1,0))
@@ -2993,7 +2993,7 @@ mysql_execute_command(THD *thd)
{
if (!strip_sp(lex->name) || check_db_name(lex->name))
{
- net_printf(thd,ER_WRONG_DB_NAME, lex->name);
+ net_printf(thd,ER_WRONG_NAME, ER(ER_DATABASE), lex->name);
break;
}
if (check_access(thd,DROP_ACL,lex->name,0,1,0))
@@ -4059,7 +4059,7 @@ bool add_field_to_list(THD *thd, char *field_name, enum_field_types type,
{
char *not_used;
uint not_used2;
- bool not_used3;
+ bool not_used3;
thd->cuted_fields=0;
String str,*res;
@@ -4089,7 +4089,8 @@ bool add_field_to_list(THD *thd, char *field_name, enum_field_types type,
{
String str,*res;
res=default_value->val_str(&str);
- if (!find_enum(interval,res->ptr(),res->length()))
+ res->strip_sp();
+ if (!find_type(interval, res->ptr(), res->length(), 0))
{
net_printf(thd,ER_INVALID_DEFAULT,field_name);
DBUG_RETURN(1);
@@ -4242,7 +4243,7 @@ TABLE_LIST *st_select_lex::add_table_to_list(THD *thd,
if (check_table_name(table->table.str,table->table.length) ||
table->db.str && check_db_name(table->db.str))
{
- net_printf(thd,ER_WRONG_TABLE_NAME,table->table.str);
+ net_printf(thd, ER_WRONG_NAME, ER(ER_TABLE), table->table.str);
DBUG_RETURN(0);
}
@@ -4596,7 +4597,7 @@ static bool append_file_to_dir(THD *thd, char **filename_ptr, char *table_name)
if (strlen(*filename_ptr)+strlen(table_name) >= FN_REFLEN-1 ||
!test_if_hard_path(*filename_ptr))
{
- my_error(ER_WRONG_TABLE_NAME, MYF(0), *filename_ptr);
+ my_error(ER_WRONG_NAME, MYF(0), ER(ER_TABLE), *filename_ptr);
return 1;
}
/* Fix is using unix filename format on dos */
diff --git a/sql/sql_prepare.cc b/sql/sql_prepare.cc
index da62fc0a262..2fa08e2d649 100644
--- a/sql/sql_prepare.cc
+++ b/sql/sql_prepare.cc
@@ -332,7 +332,7 @@ SETUP_PARAM_FUNCTION(setup_param_datetime)
tm.day= (uint) to[3];
tm.neg= 0;
- param->set_time(&tm, TIMESTAMP_FULL);
+ param->set_time(&tm, TIMESTAMP_DATETIME);
}
*pos+= length;
}
diff --git a/sql/sql_table.cc b/sql/sql_table.cc
index 1a2021abf90..d2d1926ea06 100644
--- a/sql/sql_table.cc
+++ b/sql/sql_table.cc
@@ -437,7 +437,7 @@ int mysql_create_table(THD *thd,const char *db, const char *table_name,
if (check_column_name(sql_field->field_name))
{
- my_error(ER_WRONG_COLUMN_NAME, MYF(0), sql_field->field_name);
+ my_error(ER_WRONG_NAME, MYF(0), ER(ER_COLUMN), sql_field->field_name);
DBUG_RETURN(-1);
}
@@ -888,7 +888,7 @@ int mysql_create_table(THD *thd,const char *db, const char *table_name,
}
if (!key_info->name || check_column_name(key_info->name))
{
- my_error(ER_WRONG_INDEX_NAME, MYF(0), key_info->name);
+ my_error(ER_WRONG_NAME, MYF(0), ER(ER_INDEX), key_info->name);
DBUG_RETURN(-1);
}
if (!(key_info->flags & HA_NULL_PART_KEY))
@@ -1777,7 +1777,7 @@ int mysql_create_like_table(THD* thd, TABLE_LIST* table,
check_table_name(src_table,table_ident->table.length)) ||
table_ident->db.str && check_db_name((src_db= table_ident->db.str)))
{
- my_error(ER_WRONG_TABLE_NAME, MYF(0), src_table);
+ my_error(ER_WRONG_NAME, MYF(0), ER(ER_TABLE), src_table);
DBUG_RETURN(-1);
}
diff --git a/sql/sql_yacc.yy b/sql/sql_yacc.yy
index 2036d13232f..bb37c58004f 100644
--- a/sql/sql_yacc.yy
+++ b/sql/sql_yacc.yy
@@ -78,7 +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;
+ timestamp_type date_time_type;
st_select_lex *select_lex;
chooser_compare_func_creator boolfunc2creator;
}
@@ -246,6 +246,7 @@ bool my_yyoverflow(short **a, YYSTYPE **b,int *yystacksize);
%token HIGH_PRIORITY
%token HOSTS_SYM
%token IDENT
+%token IDENT_QUOTED
%token IGNORE_SYM
%token IMPORT
%token INDEX
@@ -584,8 +585,8 @@ bool my_yyoverflow(short **a, YYSTYPE **b,int *yystacksize);
%right BINARY COLLATE_SYM
%type <lex_str>
- IDENT TEXT_STRING REAL_NUM FLOAT_NUM NUM LONG_NUM HEX_NUM LEX_HOSTNAME
- ULONGLONG_NUM field_ident select_alias ident ident_or_text
+ IDENT IDENT_QUOTED TEXT_STRING REAL_NUM FLOAT_NUM NUM LONG_NUM HEX_NUM
+ LEX_HOSTNAME ULONGLONG_NUM field_ident select_alias ident ident_or_text
UNDERSCORE_CHARSET IDENT_sys TEXT_STRING_sys TEXT_STRING_literal
NCHAR_STRING opt_component
@@ -648,7 +649,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 <date_time_type> date_time_type;
%type <interval> interval
%type <db_type> table_types
@@ -2631,7 +2632,7 @@ simple_expr:
{ $$= new Item_func_spatial_collection(* $3,
Geometry::wkbGeometryCollection,
Geometry::wkbPoint); }
- | GET_FORMAT '(' datetime_format_type ',' expr ')'
+ | GET_FORMAT '(' date_time_type ',' expr ')'
{ $$= new Item_func_get_format($3, $5); }
| HOUR_SYM '(' expr ')'
{ $$= new Item_func_hour($3); }
@@ -3254,10 +3255,10 @@ 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;};
+date_time_type:
+ DATE_SYM {$$=TIMESTAMP_DATE;}
+ | TIME_SYM {$$=TIMESTAMP_TIME;}
+ | DATETIME {$$=TIMESTAMP_DATETIME;};
table_alias:
/* empty */
@@ -4479,15 +4480,16 @@ table_ident:
/* For Delphi */;
IDENT_sys:
- IDENT
- {
- THD *thd= YYTHD;
- if (thd->charset_is_system_charset)
- $$= $1;
- else
- thd->convert_string(&$$, system_charset_info,
- $1.str, $1.length, thd->charset());
- }
+ IDENT { $$= $1; }
+ | IDENT_QUOTED
+ {
+ THD *thd= YYTHD;
+ if (thd->charset_is_system_charset)
+ $$= $1;
+ else
+ thd->convert_string(&$$, system_charset_info,
+ $1.str, $1.length, thd->charset());
+ }
;
TEXT_STRING_sys:
diff --git a/sql/strfunc.cc b/sql/strfunc.cc
new file mode 100644
index 00000000000..1db2124bcee
--- /dev/null
+++ b/sql/strfunc.cc
@@ -0,0 +1,147 @@
+/* Copyright (C) 2003 MySQL AB
+
+ This program is free software; you can redistribute it and/or modify
+ it under the terms of the GNU General Public License as published by
+ the Free Software Foundation; either version 2 of the License, or
+ (at your option) any later version.
+
+ This program is distributed in the hope that it will be useful,
+ but WITHOUT ANY WARRANTY; without even the implied warranty of
+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ GNU General Public License for more details.
+
+ You should have received a copy of the GNU General Public License
+ along with this program; if not, write to the Free Software
+ Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA */
+
+/* Some useful string utility functions used by the MySQL server */
+
+#include "mysql_priv.h"
+
+/*
+ Return bitmap for strings used in a set
+
+ SYNOPSIS
+ find_set()
+ lib Strings in set
+ str Strings of set-strings separated by ','
+ err_pos If error, set to point to start of wrong set string
+ err_len If error, set to the length of wrong set string
+ set_warning Set to 1 if some string in set couldn't be used
+
+ NOTE
+ We delete all end space from str before comparison
+
+ RETURN
+ bitmap of all sets found in x.
+ set_warning is set to 1 if there was any sets that couldn't be set
+*/
+
+static const char field_separator=',';
+
+ulonglong find_set(TYPELIB *lib, const char *str, uint length, char **err_pos,
+ uint *err_len, bool *set_warning)
+{
+ const char *end= str + length;
+ *err_pos= 0; // No error yet
+ while (end > str && my_isspace(system_charset_info, end[-1]))
+ end--;
+
+ *err_len= 0;
+ ulonglong found= 0;
+ if (str != end)
+ {
+ const char *start= str;
+ for (;;)
+ {
+ const char *pos= start;
+ uint var_len;
+
+ for (; pos != end && *pos != field_separator; pos++) ;
+ var_len= (uint) (pos - start);
+ uint find= find_type(lib, start, var_len, 0);
+ if (!find)
+ {
+ *err_pos= (char*) start;
+ *err_len= var_len;
+ *set_warning= 1;
+ }
+ else
+ found|= ((longlong) 1 << (find - 1));
+ if (pos == end)
+ break;
+ start= pos + 1;
+ }
+ }
+ return found;
+}
+
+
+/*
+ Function to find a string in a TYPELIB
+ (Same format as mysys/typelib.c)
+
+ SYNOPSIS
+ find_type()
+ lib TYPELIB (struct of pointer to values + count)
+ find String to find
+ length Length of string to find
+ part_match Allow part matching of value
+
+ RETURN
+ 0 error
+ > 0 position in TYPELIB->type_names +1
+*/
+
+uint find_type(TYPELIB *lib, const char *find, uint length, bool part_match)
+{
+ uint found_count=0, found_pos=0;
+ const char *end= find+length;
+ const char *i;
+ const char *j;
+ for (uint pos=0 ; (j=lib->type_names[pos++]) ; )
+ {
+ for (i=find ; i != end &&
+ my_toupper(system_charset_info,*i) ==
+ my_toupper(system_charset_info,*j) ; i++, j++) ;
+ if (i == end)
+ {
+ if (! *j)
+ return(pos);
+ found_count++;
+ found_pos= pos;
+ }
+ }
+ return(found_count == 1 && part_match ? found_count : 0);
+}
+
+
+/*
+ Check if the first word in a string is one of the ones in TYPELIB
+
+ SYNOPSIS
+ check_word()
+ lib TYPELIB
+ val String to check
+ end End of input
+ end_of_word Store value of last used byte here if we found word
+
+ RETURN
+ 0 No matching value
+ > 1 lib->type_names[#-1] matched
+ end_of_word will point to separator character/end in 'val'
+*/
+
+uint check_word(TYPELIB *lib, const char *val, const char *end,
+ const char **end_of_word)
+{
+ int res;
+ const char *ptr;
+
+ /* Fiend end of word */
+ for (ptr= val ; ptr < end && my_isalpha(&my_charset_latin1, *ptr) ; ptr++)
+ ;
+ if ((res=find_type(lib, val, (uint) (ptr - val), 1)) > 0)
+ *end_of_word= ptr;
+ return res;
+}
diff --git a/sql/structs.h b/sql/structs.h
index d9be230c049..352823cceb2 100644
--- a/sql/structs.h
+++ b/sql/structs.h
@@ -20,15 +20,19 @@
struct st_table;
class Field;
-typedef struct st_date_format { /* How to print date */
- uint pos[6]; /* Positions to YY.MM.DD HH:MM:SS */
-} DATE_FORMAT;
+typedef struct lex_string {
+ char *str;
+ uint length;
+} LEX_STRING;
+
+
+typedef struct st_date_time_format {
+ uchar positions[8];
+ char time_separator; /* Separator between hour and minute */
+ uint flag; /* For future */
+ LEX_STRING format;
+} DATE_TIME_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 */
@@ -115,8 +119,17 @@ typedef struct st_read_record { /* Parameter to read_record */
bool print_error, ignore_not_found_rows;
} READ_RECORD;
-enum timestamp_type { TIMESTAMP_NONE, WRONG_TIMESTAMP_FULL, TIMESTAMP_DATE, TIMESTAMP_FULL,
- TIMESTAMP_TIME};
+
+enum timestamp_type
+{
+ TIMESTAMP_NONE= -2, TIMESTAMP_DATETIME_ERROR= -1,
+ TIMESTAMP_DATE= 0, TIMESTAMP_DATETIME= 1, TIMESTAMP_TIME= 2
+};
+
+/* Parameters to str_to_TIME */
+#define TIME_FUZZY_DATE 1
+#define TIME_DATETIME_ONLY 2
+
typedef struct st_time {
uint year,month,day,hour,minute,second;
@@ -125,12 +138,21 @@ typedef struct st_time {
timestamp_type time_type;
} TIME;
+
typedef struct {
long year,month,day,hour,minute,second,second_part;
bool neg;
} INTERVAL;
+typedef struct st_known_date_time_format {
+ const char *format_name;
+ const char *date_format;
+ const char *datetime_format;
+ const char *time_format;
+} KNOWN_DATE_TIME_FORMAT;
+
+
enum SHOW_TYPE
{
SHOW_UNDEF,
@@ -168,11 +190,6 @@ typedef struct show_var_st {
} SHOW_VAR;
-typedef struct lex_string {
- char *str;
- uint length;
-} LEX_STRING;
-
typedef struct st_lex_user {
LEX_STRING user, host, password;
} LEX_USER;
diff --git a/sql/time.cc b/sql/time.cc
index f2e41afa560..4f2a2a23910 100644
--- a/sql/time.cc
+++ b/sql/time.cc
@@ -23,14 +23,9 @@
static ulong const days_at_timestart=719528; /* daynr at 1970.01.01 */
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)
@@ -282,6 +277,7 @@ ulong convert_period_to_month(ulong period)
return a*12+b-1;
}
+
ulong convert_month_to_period(ulong month)
{
ulong year;
@@ -295,6 +291,13 @@ ulong convert_month_to_period(ulong month)
}
+/* Position for YYYY-DD-MM HH-MM-DD.FFFFFF AM in default format */
+
+static uchar internal_format_positions[]=
+{0, 1, 2, 3, 4, 5, 6, (uchar) 255};
+
+static char time_separator=':';
+
/*
Convert a timestamp string to a TIME value.
@@ -303,7 +306,9 @@ ulong convert_month_to_period(ulong month)
str String to parse
length Length of string
l_time Date is stored here
- fuzzy_date 1 if we should allow dates where one part is zero
+ flags Bitmap of following items
+ TIME_FUZZY_DATE Set if we should allow partial dates
+ TIME_DATETIME_ONLY Set if we only allow full datetimes.
DESCRIPTION
At least the following formats are recogniced (based on number of digits)
@@ -312,161 +317,248 @@ ulong convert_month_to_period(ulong month)
YYYYMMDDTHHMMSS where T is a the character T (ISO8601)
Also dates where all parts are zero are allowed
+ The second part may have an optional .###### fraction part.
+
+ NOTES
+ This function should work with a format position vector as long as the
+ following things holds:
+ - All date are kept together and all time parts are kept together
+ - Date and time parts must be separated by blank
+ - Second fractions must come after second part and be separated
+ by a '.'. (The second fractions are optional)
+ - AM/PM must come after second fractions (or after seconds if no fractions)
+ - Year must always been specified.
+ - If time is before date, then we will use datetime format only if
+ the argument consist of two parts, separated by space.
+ Otherwise we will assume the argument is a date.
+ - The hour part must be specified in hour-minute-second order.
+
RETURN VALUES
TIMESTAMP_NONE String wasn't a timestamp, like
[DD [HH:[MM:[SS]]]].fraction
TIMESTAMP_DATE DATE string (YY MM and DD parts ok)
- TIMESTAMP_FULL Full timestamp
+ TIMESTAMP_DATETIME Full timestamp
+ TIMESTAMP_DATETIME_ERROR Timestamp with wrong values
*/
+#define MAX_DATE_PARTS 8
+
timestamp_type
-str_to_TIME(const char *str, uint length, TIME *l_time,bool fuzzy_date,THD *thd)
+str_to_TIME(const char *str, uint length, TIME *l_time, uint flags)
{
- 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;
+ uint field_length, year_length, digits, i, number_of_fields;
+ uint date[MAX_DATE_PARTS], date_len[MAX_DATE_PARTS];
+ uint add_hours= 0, start_loop;
+ ulong not_zero_date, allow_space;
+ bool is_internal_format;
+ const char *pos, *last_field_pos;
const char *end=str+length;
- bool found_delimitier= 0;
+ const uchar *format_position;
+ bool found_delimitier= 0, found_space= 0;
+ DATE_TIME_FORMAT *format;
DBUG_ENTER("str_to_TIME");
- DBUG_PRINT("enter",("str: %.*s",length,str));
+ DBUG_PRINT("ENTER",("str: %.*s",length,str));
- // Skip garbage
- for (; str != end && !my_isdigit(&my_charset_latin1, *str) ; str++) ;
- if (str == end)
+ LINT_INIT(field_length);
+ LINT_INIT(year_length);
+ LINT_INIT(last_field_pos);
+
+ // Skip space at start
+ for (; str != end && my_isspace(&my_charset_latin1, *str) ; str++)
+ ;
+ if (str == end || ! my_isdigit(&my_charset_latin1, *str))
DBUG_RETURN(TIMESTAMP_NONE);
+
+ is_internal_format= 0;
+ /* This has to be changed if want to activate different timestamp formats */
+ format_position= internal_format_positions;
+
/*
- Calculate first number of digits.
+ Calculate number of digits in first part.
If length= 8 or >= 14 then year is of format YYYY.
(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);
+ for (pos=str; pos != end && my_isdigit(&my_charset_latin1,*pos) ; pos++)
+ ;
- if (pos == end || digits>=12)
+ digits= (uint) (pos-str);
+ start_loop= 0; // Start of scan loop
+ date_len[format_position[0]]= 0; // Length of year field
+ if (pos == end)
{
- is_internal_format= 1;
+ /* Found date in internal format (only numbers like YYYYMMDD) */
year_length= (digits == 4 || digits == 8 || digits >= 14) ? 4 : 2;
field_length=year_length-1;
- date_len[0]= year_length;
+ is_internal_format= 1;
+ format_position= internal_format_positions;
+ }
+ else
+ {
+ if (format_position[0] >= 3) // If year is after HHMMDD
+ {
+ /*
+ If year is not in first part then we have to determinate if we got
+ a date field or a datetime field.
+ We do this by checking if there is two numbers separated by
+ space in the input.
+ */
+ while (pos < end && !my_isspace(&my_charset_latin1, *pos))
+ pos++;
+ while (pos < end && !my_isdigit(&my_charset_latin1, *pos))
+ pos++;
+ if (pos == end)
+ {
+ if (flags & TIME_DATETIME_ONLY)
+ return TIMESTAMP_NONE; // Can't be a full datetime
+ /* Date field. Set hour, minutes and seconds to 0 */
+ date[0]= date[1]= date[2]= date[3]= 0;
+ start_loop= 5; // Start with first date part
+ }
+ }
}
+
+ /*
+ Only allow space in the first "part" of the datetime field and:
+ - after days, part seconds
+ - before and after AM/PM (handled by code later)
+
+ 2003-03-03 20:00:20 AM
+ 20:00:20.000000 AM 03-03-2000
+ */
+ i= max((uint) format_position[0], (uint) format_position[1]);
+ set_if_bigger(i, (uint) format_position[2]);
+ allow_space= ((1 << i) | (1 << format_position[6]));
+ allow_space&= (1 | 2 | 4 | 8);
+
not_zero_date= 0;
- for (i=0 ; i < 6 && str != end && my_isdigit(&my_charset_latin1,*str) ; i++)
+ for (i = start_loop;
+ i < MAX_DATE_PARTS-1 && 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])
- && (is_internal_format && field_length-- || !is_internal_format) )
+ const char *start= str;
+ ulong tmp_value= (uint) (uchar) (*str++ - '0');
+ while (str != end && my_isdigit(&my_charset_latin1,str[0]) &&
+ (!is_internal_format || field_length--))
{
- tmp_value=tmp_value*10 + (uint) (uchar) (*str - '0');
+ tmp_value=tmp_value*10 + (ulong) (uchar) (*str - '0');
str++;
- if (!is_internal_format)
- date_len[i]+= 1;
}
- if (i == 2 && *str == '.')
+ date_len[i]+= (uint) (str - start);
+ if (tmp_value > 999999) // Impossible date part
DBUG_RETURN(TIMESTAMP_NONE);
date[i]=tmp_value;
not_zero_date|= tmp_value;
- if (i == 2 && str != end && *str == 'T')
+
+ /* Length-1 of next field */
+ field_length= format_position[i+1] == 0 ? 3 : 1;
+
+ if ((last_field_pos= str) == end)
+ {
+ i++; // Register last found part
+ break;
+ }
+ /* Allow a 'T' after day to allow CCYYMMDDT type of fields */
+ if (i == format_position[2] && *str == 'T')
+ {
str++; // ISO8601: CCYYMMDDThhmmss
- else if ( i != 5 ) // Skip inter-field delimiters
+ continue;
+ }
+ if (i == format_position[5]) // Seconds
{
- while (str != end &&
- (my_ispunct(&my_charset_latin1,*str) ||
- my_isspace(&my_charset_latin1,*str)))
+ if (*str == '.') // Followed by part seconds
{
- // Only allow space between days and hours
- if (my_isspace(&my_charset_latin1,*str) && i != 2)
- DBUG_RETURN(TIMESTAMP_NONE);
str++;
- found_delimitier=1; // Should be a 'normal' date
+ field_length= 5; // 5 digits after first (=6)
}
+ continue;
+
+ /* No part seconds */
+ date[++i]= 0;
}
- if (is_internal_format)
- field_length=1; // Rest fields can only be 2
- }
- /* Handle second fractions */
- if (i == 6 && (uint) (end-str) >= 2 && *str == '.' &&
- my_isdigit(&my_charset_latin1,str[1]))
- {
- str++;
- uint tmp_value=(uint) (uchar) (*str - '0');
- field_length=5;
- while (str++ != end && my_isdigit(&my_charset_latin1,str[0]) &&
- field_length--)
- tmp_value=tmp_value*10 + (uint) (uchar) (*str - '0');
- date[6]=tmp_value;
- not_zero_date|= tmp_value;
+ while (str != end &&
+ (my_ispunct(&my_charset_latin1,*str) ||
+ my_isspace(&my_charset_latin1,*str)))
+ {
+ if (my_isspace(&my_charset_latin1,*str))
+ {
+ if (!(allow_space & (1 << i)))
+ DBUG_RETURN(TIMESTAMP_NONE);
+ found_space= 1;
+ }
+ str++;
+ found_delimitier= 1; // Should be a 'normal' date
+ }
+ /* Check if next position is AM/PM */
+ if (i == format_position[6]) // Seconds, time for AM/PM
+ {
+ i++; // Skip AM/PM part
+ if (format_position[7] != 255) // If using AM/PM
+ {
+ if (str+2 <= end && (str[1] == 'M' || str[1] == 'm'))
+ {
+ if (str[1] == 'p' || str[1] == 'P')
+ add_hours= 12;
+ else if (str[1] != 'a' || str[1] != 'A')
+ continue; // Not AM/PM
+ str+= 2; // Skip AM/PM
+ /* Skip space after AM/PM */
+ while (str != end && my_isspace(&my_charset_latin1,*str))
+ str++;
+ }
+ }
+ }
+ last_field_pos= str;
}
- else
- date[6]=0;
-
- while (str != end && (my_ispunct(&my_charset_latin1,*str) ||
- my_isspace(&my_charset_latin1,*str)))
- str++;
+ if (found_delimitier && !found_space && (flags & TIME_DATETIME_ONLY))
+ DBUG_RETURN(TIMESTAMP_NONE); // Can't be a datetime
- uint add_hours= 0;
- if (!my_strnncoll(&my_charset_latin1,
- (const uchar *)str, 2,
- (const uchar *)"PM", 2))
- add_hours= 12;
+ str= last_field_pos;
- number_of_fields=i;
- while (i < 6)
+ number_of_fields= i - start_loop;
+ while (i < MAX_DATE_PARTS)
date[i++]=0;
if (!is_internal_format)
{
- byte *frm_pos;
+ year_length= date_len[(uint) format_position[0]];
+ if (!year_length) // Year must be specified
+ DBUG_RETURN(TIMESTAMP_NONE);
- 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
+ l_time->year= date[(uint) format_position[0]];
+ l_time->month= date[(uint) format_position[1]];
+ l_time->day= date[(uint) format_position[2]];
+ l_time->hour= date[(uint) format_position[3]];
+ l_time->minute= date[(uint) format_position[4]];
+ l_time->second= date[(uint) format_position[5]];
+ l_time->second_part= date[(uint) format_position[6]];
+ if (format_position[7] != (uchar) 255)
{
- 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;
- }
+ if (l_time->hour > 12)
+ DBUG_RETURN(TIMESTAMP_DATETIME_ERROR);
+ 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->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 (year_length == 2 && i >= format_position[1] && i >=format_position[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)))
+ (!(flags & TIME_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
@@ -481,46 +573,46 @@ str_to_TIME(const char *str, uint length, TIME *l_time,bool fuzzy_date,THD *thd)
}
}
if (not_zero_date)
- thd->cuted_fields++;
- DBUG_RETURN(WRONG_TIMESTAMP_FULL);
+ current_thd->cuted_fields++;
+ DBUG_RETURN(TIMESTAMP_DATETIME_ERROR);
}
- if (str != end && thd->count_cuted_fields)
+ if (str != end && current_thd->count_cuted_fields)
{
for (; str != end ; str++)
{
if (!my_isspace(&my_charset_latin1,*str))
{
- thd->cuted_fields++;
+ current_thd->cuted_fields++;
break;
}
}
}
DBUG_RETURN(l_time->time_type=
- (number_of_fields <= 3 ? TIMESTAMP_DATE : TIMESTAMP_FULL));
+ (number_of_fields <= 3 ? TIMESTAMP_DATE : TIMESTAMP_DATETIME));
}
-time_t str_to_timestamp(const char *str,uint length, THD *thd)
+time_t str_to_timestamp(const char *str,uint length)
{
TIME l_time;
long not_used;
- if (str_to_TIME(str,length,&l_time,0,thd) <= WRONG_TIMESTAMP_FULL)
+ if (str_to_TIME(str,length,&l_time,0) <= TIMESTAMP_DATETIME_ERROR)
return(0);
if (l_time.year >= TIMESTAMP_MAX_YEAR || l_time.year < 1900+YY_PART_YEAR)
{
- thd->cuted_fields++;
+ current_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, THD *thd)
+longlong str_to_datetime(const char *str,uint length, uint fuzzy_date)
{
TIME l_time;
- if (str_to_TIME(str,length,&l_time,fuzzy_date,thd) <= WRONG_TIMESTAMP_FULL)
+ if (str_to_TIME(str,length,&l_time,fuzzy_date) <= TIMESTAMP_DATETIME_ERROR)
return(0);
return (longlong) (l_time.year*LL(10000000000) +
l_time.month*LL(100000000)+
@@ -542,22 +634,24 @@ longlong str_to_datetime(const char *str,uint length,bool fuzzy_date, THD *thd)
length Length of str
l_time Store result here
+ NOTES
+ Because of the extra days argument, this function can only
+ work with times where the time arguments are in the above order.
+
RETURN
0 ok
1 error
*/
-bool str_to_time(const char *str,uint length,TIME *l_time, THD *thd)
+bool str_to_time(const char *str,uint length,TIME *l_time)
{
long date[5],value;
- const char *end=str+length;
+ const char *end=str+length, *end_of_days;
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 &&
- !my_isdigit(&my_charset_latin1,*str) && *str != '-' ; str++)
+ for (; str != end && my_isspace(&my_charset_latin1,*str) ; str++)
length--;
if (str != end && *str == '-')
{
@@ -571,37 +665,33 @@ bool str_to_time(const char *str,uint length,TIME *l_time, THD *thd)
/* Check first if this is a full TIMESTAMP */
if (length >= 12)
{ // Probably full 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;
+ enum timestamp_type res= str_to_TIME(str,length,l_time,
+ (TIME_FUZZY_DATE |
+ TIME_DATETIME_ONLY));
+ if ((int) res >= (int) TIMESTAMP_DATETIME_ERROR)
+ return res == TIMESTAMP_DATETIME_ERROR;
}
/* Not a timestamp. Try to get this as a DAYS_TO_SECOND string */
for (value=0; str != end && my_isdigit(&my_charset_latin1,*str) ; str++)
value=value*10L + (long) (*str - '0');
- /* Move to last space */
- if (str != end && *str == ' ')
- {
- while (++str != end && str[0] == ' ')
- {}
- str--;
- }
+ /* Skipp all space after 'days' */
+ end_of_days= str;
+ for (; str != end && my_isspace(&my_charset_latin1, str[0]) ; str++)
+ ;
LINT_INIT(state);
found_days=found_hours=0;
- if ((uint) (end-str) > 1 && (*str == ' ' &&
- my_isdigit(&my_charset_latin1,str[1])))
- { // days !
- date[0]=value;
- state=1; // Assume next is hours
- found_days=1;
- str++; // Skip space;
- }
- else if ((end-str) > 1 && *str == frm_pos[7] &&
- my_isdigit(&my_charset_latin1,str[1]))
+ if ((uint) (end-str) > 1 && str != end_of_days &&
+ my_isdigit(&my_charset_latin1, *str))
+ { // Found days part
+ date[0]= value;
+ state= 1; // Assume next is hours
+ found_days= 1;
+ }
+ else if ((end-str) > 1 && *str == time_separator &&
+ my_isdigit(&my_charset_latin1, str[1]))
{
date[0]=0; // Assume we found hours
date[1]=value;
@@ -626,10 +716,10 @@ bool str_to_time(const char *str,uint length,TIME *l_time, THD *thd)
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 != frm_pos[7] ||
+ if (state == 4 || (end-str) < 2 || *str != time_separator ||
!my_isdigit(&my_charset_latin1,str[1]))
break;
- str++; // Skip ':'
+ str++; // Skip time_separator (':')
}
if (state != 4)
@@ -644,7 +734,8 @@ bool str_to_time(const char *str,uint length,TIME *l_time, THD *thd)
else
bzero((char*) (date+state), sizeof(long)*(4-state));
}
- fractional:
+
+fractional:
/* Get fractional second part */
if ((end-str) >= 2 && *str == '.' && my_isdigit(&my_charset_latin1,str[1]))
{
@@ -659,18 +750,21 @@ bool str_to_time(const char *str,uint length,TIME *l_time, THD *thd)
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)
+ if (internal_format_positions[7] != 255)
{
- uint days_i= date[1]/24;
- uint hours_i= date[1]%24;
- date[1]= hours_i%12 + 12 + 24*days_i;
+ /* Read a possible AM/PM */
+ while (str != end && my_isspace(&my_charset_latin1, *str))
+ str++;
+ if (str+2 <= end && (str[1] == 'M' || str[1] == 'm'))
+ {
+ if (str[1] == 'p' || str[1] == 'P')
+ {
+ str+= 2;
+ date[1]= date[1]%12 + 12;
+ }
+ else if (str[1] == 'a' || str[1] == 'A')
+ str+=2;
+ }
}
/* Some simple checks */
@@ -680,11 +774,11 @@ bool str_to_time(const char *str,uint length,TIME *l_time, THD *thd)
return 1;
}
l_time->month=0;
- l_time->day=date[0];
- 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->day= date[0];
+ l_time->hour= date[1];
+ l_time->minute= date[2];
+ l_time->second= date[3];
+ l_time->second_part= date[4];
l_time->time_type= TIMESTAMP_TIME;
/* Check if there is garbage at end of the TIME specification */
@@ -730,163 +824,404 @@ void calc_time_from_sec(TIME *to, long seconds, long 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;
-}
+/*
+ Parse a format string specification
+ SYNOPSIS
+ parse_date_time_format()
+ format_type Format of string (time, date or datetime)
+ format_str String to parse
+ format_length Length of string
+ date_time_format Format to fill in
+
+ NOTES
+ Fills in date_time_format->positions for all date time parts.
+
+ positions marks the position for a datetime element in the format string.
+ The position array elements are in the following order:
+ YYYY-DD-MM HH-MM-DD.FFFFFF AM
+ 0 1 2 3 4 5 6 7
+
+ If positions[0]= 5, it means that year will be the forth element to
+ read from the parsed date string.
+
+ RETURN
+ 0 ok
+ 1 error
+*/
-bool parse_datetime_formats(datetime_format_types format_type,
- const char *format_str, uint format_length,
- byte *dt_pos)
+bool parse_date_time_format(timestamp_type format_type,
+ const char *format, uint format_length,
+ DATE_TIME_FORMAT *date_time_format)
{
- 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;
+ uint offset= 0, separators= 0;
+ const char *ptr= format, *format_str;
+ const char *end= ptr+format_length;
+ uchar *dt_pos= date_time_format->positions;
+ /* need_p is set if we are using AM/PM format */
+ bool need_p= 0, allow_separator= 0;
+ ulong part_map= 0, separator_map= 0;
+ const char *parts[16];
+
+ date_time_format->time_separator= 0;
+ date_time_format->flag= 0; // For future
- const char *ptr=format_str;
- const char *end=ptr+format_length;
- bool need_p= 0;
+ /*
+ Fill position with 'dummy' arguments to found out if a format tag is
+ used twice (This limit's the format to 255 characters, but this is ok)
+ */
+ dt_pos[0]= dt_pos[1]= dt_pos[2]= dt_pos[3]=
+ dt_pos[4]= dt_pos[5]= dt_pos[6]= dt_pos[7]= 255;
for (; ptr != end; ptr++)
{
if (*ptr == '%' && ptr+1 != end)
{
+ uint position;
+ LINT_INIT(position);
switch (*++ptr) {
- case 'y':
+ case 'y': // Year
case 'Y':
- if (dt_pos[0] > -1)
- return 1;
- dt_pos[0]= pos;
+ position= 0;
break;
- case 'c':
+ case 'c': // Month
case 'm':
- if (dt_pos[1] > -1)
- return 1;
- dt_pos[1]= pos;
+ position= 1;
break;
case 'd':
case 'e':
- if (dt_pos[2] > -1)
- return 1;
- dt_pos[2]= pos;
+ position= 2;
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');
+ need_p= 1; // Need AM/PM
+ /* Fall through */
+ case 'k':
+ case 'H':
+ position= 3;
break;
case 'i':
- if (dt_pos[4] > -1)
- return 1;
- dt_pos[4]= pos;
+ position= 4;
break;
case 's':
case 'S':
- if (dt_pos[5] > -1)
- return 1;
- dt_pos[5]= pos;
+ position= 5;
+ break;
+ case 'f':
+ position= 6;
+ if (dt_pos[5] != offset-1 || ptr[-2] != '.')
+ return 1; // Wrong usage of %f
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;
+ case 'p': // AM/PM
+ if (offset == 0) // Can't be first
+ return 0;
+ position= 7;
break;
default:
- return 1;
+ return 1; // Unknown controll char
}
- if (dt_pos[6] == -1)
- pos++;
+ if (dt_pos[position] != 255) // Don't allow same tag twice
+ return 1;
+ parts[position]= ptr-1;
+
+ /*
+ If switching from time to date, ensure that all time parts
+ are used
+ */
+ if (part_map && position <= 2 && !(part_map & (1 | 2 | 4)))
+ offset=5;
+ part_map|= (ulong) 1 << position;
+ dt_pos[position]= offset++;
+ allow_separator= 1;
+ }
+ else
+ {
+ /*
+ Don't allow any characters in format as this could easily confuse
+ the date reader
+ */
+ if (!allow_separator)
+ return 1; // No separator here
+ allow_separator= 0; // Don't allow two separators
+ separators++;
+ /* Store in separator_map which parts are punct characters */
+ if (my_ispunct(&my_charset_latin1, *ptr))
+ separator_map|= (ulong) 1 << (offset-1);
+ else if (!my_isspace(&my_charset_latin1, *ptr))
+ return 1;
}
}
- 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;
+ /* If no %f, specify it after seconds. Move %p up, if necessary */
+ if ((part_map & 32) && !(part_map & 64))
+ {
+ dt_pos[6]= dt_pos[5] +1;
+ parts[6]= parts[5]; // For later test in (need_p)
+ if (dt_pos[6] == dt_pos[7]) // Move %p one step up if used
+ dt_pos[7]++;
+ }
/*
- Check for valid separators between date/time parst
+ Check that we have not used a non legal format specifier and that all
+ format specifiers have been used
+
+ The last test is to ensure that %p is used if and only if
+ it's needed.
*/
- uint tmp_len= format_length;
- if (dt_pos[6] == 1)
+ if ((format_type == TIMESTAMP_DATETIME &&
+ !test_all_bits(part_map, (1 | 2 | 4 | 8 | 16 | 32))) ||
+ (format_type == TIMESTAMP_DATE && part_map != (1 | 2 | 4)) ||
+ (format_type == TIMESTAMP_TIME &&
+ !test_all_bits(part_map, 8 | 16 | 32)) ||
+ !allow_separator || // %option should be last
+ (need_p && dt_pos[6] +1 != dt_pos[7]) ||
+ (need_p ^ (dt_pos[7] != 255)))
+ return 1;
+
+ if (dt_pos[6] != 255) // If fractional seconds
{
- end= end - 2;
- if (my_ispunct(&my_charset_latin1, *end) || my_isspace(&my_charset_latin1, *end))
- end--;
- tmp_len= end - format_str;
+ /* remove fractional seconds from later tests */
+ uint pos= dt_pos[6] -1;
+ /* Remove separator before %f from sep map */
+ separator_map= ((separator_map & ((ulong) (1 << pos)-1)) |
+ ((separator_map & ~((ulong) (1 << pos)-1)) >> 1));
+ if (part_map & 64)
+ {
+ separators--; // There is always a separator
+ need_p= 1; // force use of separators
+ }
}
+
+ /*
+ Remove possible separator before %p from sep_map
+ (This can either be at position 3, 4, 6 or 7) h.m.d.%f %p
+ */
+ if (dt_pos[7] != 255)
+ {
+ if (need_p && parts[7] != parts[6]+2)
+ separators--;
+ }
+ /*
+ Calculate if %p is in first or last part of the datetime field
+
+ At this point we have either %H-%i-%s %p 'year parts' or
+ 'year parts' &H-%i-%s %p" as %f was removed above
+ */
+ offset= dt_pos[6] <= 3 ? 3 : 6;
+ /* Remove separator before %p from sep map */
+ separator_map= ((separator_map & ((ulong) (1 << offset)-1)) |
+ ((separator_map & ~((ulong) (1 << offset)-1)) >> 1));
+
+ format_str= 0;
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)))
+ case TIMESTAMP_DATE:
+ format_str= known_date_time_formats[INTERNAL_FORMAT].date_format;
+ /* fall through */
+ case TIMESTAMP_TIME:
+ if (!format_str)
+ format_str=known_date_time_formats[INTERNAL_FORMAT].time_format;
+
+ /*
+ If there is no separators, allow the internal format as we can read
+ this. If separators are used, they must be between each part
+ */
+ if (format_length == 6 && !need_p &&
+ !my_strnncoll(&my_charset_bin,
+ (const uchar *) format, 6,
+ (const uchar *) format_str, 6))
+ return 0;
+ if (separator_map == (1 | 2))
{
- if (format_type == TIME_FORMAT_TYPE && tmp_len == 8)
+ if (format_type == TIMESTAMP_TIME)
{
- if (*(format_str+2) != *(format_str+5))
- return 1;
- dt_pos[7]= *(format_str+2);
+ if (*(format+2) != *(format+5))
+ break; // Error
+ /* Store the character used for time formats */
+ date_time_format->time_separator= *(format+2);
}
return 0;
}
break;
- case DATETIME_FORMAT_TYPE:
- if ((tmp_len == 12 &&
+ case TIMESTAMP_DATETIME:
+ /*
+ If there is no separators, allow the internal format as we can read
+ this. If separators are used, they must be between each part.
+ Between DATE and TIME we also allow space as separator
+ */
+ if ((format_length == 12 && !need_p &&
!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))))
+ (const uchar *) format, 12,
+ (const uchar*) known_date_time_formats[INTERNAL_FORMAT].datetime_format,
+ 12)) ||
+ (separators == 5 && separator_map == (1 | 2 | 8 | 16)))
return 0;
break;
- }
- return 1;
+ default:
+ DBUG_ASSERT(1);
+ break;
+ }
+ return 1; // Error
+}
+
+
+/*
+ Create a DATE_TIME_FORMAT object from a format string specification
+
+ SYNOPSIS
+ date_time_format_make()
+ format_type Format to parse (time, date or datetime)
+ format_str String to parse
+ format_length Length of string
+
+ NOTES
+ The returned object should be freed with my_free()
+
+ RETURN
+ NULL ponter: Error
+ new object
+*/
+
+DATE_TIME_FORMAT
+*date_time_format_make(timestamp_type format_type,
+ const char *format_str, uint format_length)
+{
+ DATE_TIME_FORMAT tmp;
+
+ if (format_length && format_length < 255 &&
+ !parse_date_time_format(format_type, format_str,
+ format_length, &tmp))
+ {
+ tmp.format.str= (char*) format_str;
+ tmp.format.length= format_length;
+ return date_time_format_copy((THD *)0, &tmp);
+ }
+ return 0;
+}
+
+
+/*
+ Create a copy of a DATE_TIME_FORMAT object
+
+ SYNOPSIS
+ date_and_time_format_copy()
+ thd Set if variable should be allocated in thread mem
+ format format to copy
+
+ NOTES
+ The returned object should be freed with my_free()
+
+ RETURN
+ NULL ponter: Error
+ new object
+*/
+
+DATE_TIME_FORMAT *date_time_format_copy(THD *thd, DATE_TIME_FORMAT *format)
+{
+ DATE_TIME_FORMAT *new_format;
+ ulong length= sizeof(*format) + format->format.length + 1;
+
+ if (thd)
+ new_format= (DATE_TIME_FORMAT *) thd->alloc(length);
+ else
+ new_format= (DATE_TIME_FORMAT *) my_malloc(length, MYF(MY_WME));
+ if (new_format)
+ {
+ /* Put format string after current pos */
+ new_format->format.str= (char*) (new_format+1);
+ memcpy((char*) new_format->positions, (char*) format->positions,
+ sizeof(format->positions));
+ new_format->time_separator= format->time_separator;
+ /* We make the string null terminated for easy printf in SHOW VARIABLES */
+ memcpy((char*) new_format->format.str, format->format.str,
+ format->format.length);
+ new_format->format.str[format->format.length]= 0;
+ new_format->format.length= format->format.length;
+ }
+ return new_format;
+}
+
+
+KNOWN_DATE_TIME_FORMAT known_date_time_formats[6]=
+{
+ {"USA", "%m.%d.%Y", "%Y-%m-%d %H.%i.%s", "%h:%i:%s %p" },
+ {"JIS", "%Y-%m-%d", "%Y-%m-%d %H:%i:%s", "%H:%i:%s" },
+ {"ISO", "%Y-%m-%d", "%Y-%m-%d %H:%i:%s", "%H:%i:%s" },
+ {"EUR", "%d.%m.%Y", "%Y-%m-%d %H.%i.%s", "%H.%i.%s" },
+ {"INTERNAL", "%Y%m%d", "%Y%m%d%H%i%s", "%H%i%s" },
+ { 0, 0, 0, 0 }
+};
+
+
+/*
+ Return format string according format name.
+ If name is unknown, result is NULL
+*/
+
+const char *get_date_time_format_str(KNOWN_DATE_TIME_FORMAT *format,
+ timestamp_type type)
+{
+ switch (type) {
+ case TIMESTAMP_DATE:
+ return format->date_format;
+ case TIMESTAMP_DATETIME:
+ return format->datetime_format;
+ case TIMESTAMP_TIME:
+ return format->time_format;
+ default:
+ DBUG_ASSERT(0); // Impossible
+ return 0;
+ }
+}
+
+/****************************************************************************
+ Functions to create default time/date/datetime strings
+
+ NOTE:
+ For the moment the DATE_TIME_FORMAT argument is ignored becasue
+ MySQL doesn't support comparing of date/time/datetime strings that
+ are not in arbutary order as dates are compared as strings in some
+ context)
+****************************************************************************/
+
+void make_time(DATE_TIME_FORMAT *format, TIME *l_time, String *str)
+{
+ long length= my_sprintf((char*) str->ptr(),
+ ((char*) str->ptr(),
+ "%s%02d:%02d:%02d",
+ (l_time->neg ? "-" : ""),
+ l_time->hour,
+ l_time->minute,
+ l_time->second));
+ str->length(length);
+ str->set_charset(&my_charset_bin);
+}
+
+
+void make_date(DATE_TIME_FORMAT *format, TIME *l_time, String *str)
+{
+ long length= my_sprintf((char*) str->ptr(),
+ ((char*) str->ptr(),
+ "%04d-%02d-%02d",
+ l_time->year,
+ l_time->month,
+ l_time->day));
+ str->length(length);
+ str->set_charset(&my_charset_bin);
+}
+
+
+void make_datetime(DATE_TIME_FORMAT *format, TIME *l_time, String *str)
+{
+ long length= my_sprintf((char*) str->ptr(),
+ ((char*) str->ptr(),
+ "%04d-%02d-%02d %02d:%02d:%02d",
+ l_time->year,
+ l_time->month,
+ l_time->day,
+ l_time->hour,
+ l_time->minute,
+ l_time->second));
+ str->length(length);
+ str->set_charset(&my_charset_bin);
}
diff --git a/sql/unireg.h b/sql/unireg.h
index ef6a2f44ea7..66a274f3863 100644
--- a/sql/unireg.h
+++ b/sql/unireg.h
@@ -63,6 +63,10 @@
/* Max column width +1 */
#define MAX_FIELD_WIDTH (MAX_FIELD_CHARLENGTH*MAX_MBWIDTH+1)
+#define MAX_DATE_WIDTH 10 /* YYYY-MM-DD */
+#define MAX_TIME_WIDTH 23 /* -DDDDDD HH:MM:SS.###### */
+#define MAX_DATETIME_FULL_WIDTH 29 /* YYYY-MM-DD HH:MM:SS.###### AM */
+#define MAX_DATETIME_WIDTH 19 /* YYYY-MM-DD HH:MM:SS */
#define MAX_TABLES (sizeof(table_map)*8-2) /* Max tables in join */
#define OUTER_REF_TABLE_BIT (((table_map) 1) << (sizeof(table_map)*8-2))