diff options
author | unknown <gluh@gluh.mysql.r18.ru> | 2004-03-15 18:28:21 +0400 |
---|---|---|
committer | unknown <gluh@gluh.mysql.r18.ru> | 2004-03-15 18:28:21 +0400 |
commit | eb1f6c53b241f28f46726f82e9a4ed894b23a5f4 (patch) | |
tree | c617b4731b141e48f4e7d0e9c03dffad70b9d936 /sql | |
parent | cbda819394001dc1bba6453c7d86d0b1bf2934c1 (diff) | |
download | mariadb-git-eb1f6c53b241f28f46726f82e9a4ed894b23a5f4.tar.gz |
Task #835: additional changes fot str_to_date
include/mysqld_error.h:
Task #835: additional changes fot str_to_date
New error message
mysql-test/r/date_formats.result:
Task #835: additional changes fot str_to_date
tests
mysql-test/r/func_sapdb.result:
Task #835: additional changes fot str_to_date
tests
mysql-test/r/func_time.result:
Task #835: additional changes fot str_to_date
tests
mysql-test/r/type_time.result:
Task #835: additional changes fot str_to_date
tests
mysql-test/t/date_formats.test:
Task #835: additional changes fot str_to_date
tests
mysql-test/t/func_sapdb.test:
Task #835: additional changes fot str_to_date
tests
mysql-test/t/func_time.test:
Task #835: additional changes fot str_to_date
tests
sql/share/czech/errmsg.txt:
Task #835: additional changes fot str_to_date
New error message
sql/share/danish/errmsg.txt:
Task #835: additional changes fot str_to_date
New error message
sql/share/dutch/errmsg.txt:
Task #835: additional changes fot str_to_date
New error message
sql/share/english/errmsg.txt:
Task #835: additional changes fot str_to_date
New error message
sql/share/estonian/errmsg.txt:
Task #835: additional changes fot str_to_date
New error message
sql/share/french/errmsg.txt:
Task #835: additional changes fot str_to_date
New error message
sql/share/german/errmsg.txt:
Task #835: additional changes fot str_to_date
New error message
sql/share/greek/errmsg.txt:
Task #835: additional changes fot str_to_date
New error message
sql/share/hungarian/errmsg.txt:
Task #835: additional changes fot str_to_date
New error message
sql/share/italian/errmsg.txt:
Task #835: additional changes fot str_to_date
New error message
sql/share/japanese/errmsg.txt:
Task #835: additional changes fot str_to_date
New error message
sql/share/korean/errmsg.txt:
Task #835: additional changes fot str_to_date
New error message
sql/share/norwegian-ny/errmsg.txt:
Task #835: additional changes fot str_to_date
New error message
sql/share/norwegian/errmsg.txt:
Task #835: additional changes fot str_to_date
New error message
sql/share/polish/errmsg.txt:
Task #835: additional changes fot str_to_date
New error message
sql/share/portuguese/errmsg.txt:
Task #835: additional changes fot str_to_date
New error message
sql/share/romanian/errmsg.txt:
Task #835: additional changes fot str_to_date
New error message
sql/share/russian/errmsg.txt:
Task #835: additional changes fot str_to_date
New error message
sql/share/serbian/errmsg.txt:
Task #835: additional changes fot str_to_date
New error message
sql/share/slovak/errmsg.txt:
Task #835: additional changes fot str_to_date
New error message
sql/share/spanish/errmsg.txt:
Task #835: additional changes fot str_to_date
New error message
sql/share/swedish/errmsg.txt:
Task #835: additional changes fot str_to_date
New error message
sql/share/ukrainian/errmsg.txt:
Task #835: additional changes fot str_to_date
New error message
Diffstat (limited to 'sql')
28 files changed, 339 insertions, 105 deletions
diff --git a/sql/item_timefunc.cc b/sql/item_timefunc.cc index 32fbe192d8f..d0674411fcf 100644 --- a/sql/item_timefunc.cc +++ b/sql/item_timefunc.cc @@ -48,11 +48,6 @@ TYPELIB day_names_typelib= { array_elements(day_names)-1,"", day_names}; -enum date_time_format_types -{ - TIME_ONLY= 0, TIME_MICROSECOND, DATE_ONLY, DATE_TIME, DATE_TIME_MICROSECOND -}; - /* OPTIMIZATION TODO: - Replace the switch with a function that should be called for each @@ -128,6 +123,9 @@ static bool make_datetime(date_time_format_types format, TIME *ltime, val String to decode length Length of string l_time Store result here + cached_timestamp_type + It uses to get an appropriate warning + in the case when the value is truncated. RETURN 0 ok @@ -135,7 +133,8 @@ static bool make_datetime(date_time_format_types format, TIME *ltime, */ static bool extract_date_time(DATE_TIME_FORMAT *format, - const char *val, uint length, TIME *l_time) + const char *val, uint length, TIME *l_time, + timestamp_type cached_timestamp_type) { int weekday= 0, yearday= 0, daypart= 0; int week_number= -1; @@ -143,9 +142,11 @@ static bool extract_date_time(DATE_TIME_FORMAT *format, int error= 0; bool usa_time= 0; bool sunday_first= 0; + int frac_part; + const char *val_begin= val; const char *val_end= val + length; const char *ptr= format->format.str; - const char *end= ptr+ format->format.length; + const char *end= ptr + format->format.length; DBUG_ENTER("extract_date_time"); bzero((char*) l_time, sizeof(*l_time)); @@ -235,7 +236,12 @@ static bool extract_date_time(DATE_TIME_FORMAT *format, /* Second part */ case 'f': tmp= (char*) val_end; + if (tmp - val > 6) + tmp= (char*) val + 6; l_time->second_part= (int) my_strtoll10(val, &tmp, &error); + frac_part= 6 - (tmp - val); + if (frac_part > 0) + l_time->second_part*= (ulong) log_10_int[frac_part]; val= tmp; break; @@ -251,6 +257,7 @@ static bool extract_date_time(DATE_TIME_FORMAT *format, (const uchar *) val, 2, (const uchar *) "AM", 2)) goto err; + val+= 2; break; /* Exotic things */ @@ -281,6 +288,18 @@ static bool extract_date_time(DATE_TIME_FORMAT *format, val= tmp; break; + case '.': + while (my_ispunct(cs, *val) && val != val_end) + val++; + break; + case '@': + while (my_isalpha(cs, *val) && val != val_end) + val++; + break; + case '#': + while (my_isdigit(cs, *val) && val != val_end) + val++; + break; default: goto err; } @@ -348,6 +367,18 @@ static bool extract_date_time(DATE_TIME_FORMAT *format, l_time->minute > 59 || l_time->second > 59) goto err; + if (val != val_end) + { + do + { + if (!my_isspace(&my_charset_latin1,*val)) + { + make_truncated_value_warning(current_thd, val_begin, length, + cached_timestamp_type); + break; + } + } while (++val != val_end); + } DBUG_RETURN(0); err: @@ -584,16 +615,27 @@ bool make_date_time(DATE_TIME_FORMAT *format, TIME *l_time, /* -** Get a array of positive numbers from a string object. -** Each number is separated by 1 non digit character -** Return error if there is too many numbers. -** If there is too few numbers, assume that the numbers are left out -** from the high end. This allows one to give: -** DAY_TO_SECOND as "D MM:HH:SS", "MM:HH:SS" "HH:SS" or as seconds. + Get a array of positive numbers from a string object. + Each number is separated by 1 non digit character + Return error if there is too many numbers. + If there is too few numbers, assume that the numbers are left out + from the high end. This allows one to give: + DAY_TO_SECOND as "D MM:HH:SS", "MM:HH:SS" "HH:SS" or as seconds. + + SYNOPSIS + str: string value + length: length of str + cs: charset of str + values: array of results + count: count of elements in result array + transform_msec: if value is true we suppose + that the last part of string value is microseconds + and we should transform value to six digit value. + For example, '1.1' -> '1.100000' */ bool get_interval_info(const char *str,uint length,CHARSET_INFO *cs, - uint count, long *values) + uint count, long *values, bool transform_msec) { const char *end=str+length; uint i; @@ -603,8 +645,15 @@ bool get_interval_info(const char *str,uint length,CHARSET_INFO *cs, for (i=0 ; i < count ; i++) { long value; + const char *start= str; for (value=0; str != end && my_isdigit(cs,*str) ; str++) value=value*10L + (long) (*str - '0'); + if (transform_msec && i == count - 1) // microseconds always last + { + long msec_length= 6 - (str - start); + if (msec_length > 0) + value*= (long) log_10_int[msec_length]; + } values[i]= value; while (str != end && !my_isdigit(cs,*str)) str++; @@ -925,19 +974,19 @@ static bool get_interval_value(Item *args,interval_type int_type, interval->second=value; break; case INTERVAL_YEAR_MONTH: // Allow YEAR-MONTH YYYYYMM - if (get_interval_info(str,length,cs,2,array)) + if (get_interval_info(str,length,cs,2,array,0)) return (1); interval->year=array[0]; interval->month=array[1]; break; case INTERVAL_DAY_HOUR: - if (get_interval_info(str,length,cs,2,array)) + if (get_interval_info(str,length,cs,2,array,0)) return (1); interval->day=array[0]; interval->hour=array[1]; break; case INTERVAL_DAY_MICROSECOND: - if (get_interval_info(str,length,cs,5,array)) + if (get_interval_info(str,length,cs,5,array,1)) return (1); interval->day=array[0]; interval->hour=array[1]; @@ -946,14 +995,14 @@ static bool get_interval_value(Item *args,interval_type int_type, interval->second_part=array[4]; break; case INTERVAL_DAY_MINUTE: - if (get_interval_info(str,length,cs,3,array)) + if (get_interval_info(str,length,cs,3,array,0)) return (1); 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)) + if (get_interval_info(str,length,cs,4,array,0)) return (1); interval->day=array[0]; interval->hour=array[1]; @@ -961,7 +1010,7 @@ static bool get_interval_value(Item *args,interval_type int_type, interval->second=array[3]; break; case INTERVAL_HOUR_MICROSECOND: - if (get_interval_info(str,length,cs,4,array)) + if (get_interval_info(str,length,cs,4,array,1)) return (1); interval->hour=array[0]; interval->minute=array[1]; @@ -969,33 +1018,33 @@ static bool get_interval_value(Item *args,interval_type int_type, interval->second_part=array[3]; break; case INTERVAL_HOUR_MINUTE: - if (get_interval_info(str,length,cs,2,array)) + if (get_interval_info(str,length,cs,2,array,0)) return (1); interval->hour=array[0]; interval->minute=array[1]; break; case INTERVAL_HOUR_SECOND: - if (get_interval_info(str,length,cs,3,array)) + if (get_interval_info(str,length,cs,3,array,0)) return (1); 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)) + if (get_interval_info(str,length,cs,3,array,1)) return (1); 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)) + if (get_interval_info(str,length,cs,2,array,0)) return (1); interval->minute=array[0]; interval->second=array[1]; break; case INTERVAL_SECOND_MICROSECOND: - if (get_interval_info(str,length,cs,2,array)) + if (get_interval_info(str,length,cs,2,array,1)) return (1); interval->second=array[0]; interval->second_part=array[1]; @@ -1008,22 +1057,13 @@ static bool get_interval_value(Item *args,interval_type int_type, String *Item_date::val_str(String *str) { TIME ltime; - ulong value=(ulong) val_int(); - if (null_value) - return (String*) 0; - + if (get_date(<ime, TIME_FUZZY_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.time_type=TIMESTAMP_DATE; - make_date((DATE_TIME_FORMAT *) 0, <ime, str); return str; } @@ -1032,28 +1072,31 @@ String *Item_date::val_str(String *str) int Item_date::save_in_field(Field *field, bool no_conversions) { TIME ltime; - timestamp_type t_type=TIMESTAMP_DATETIME; if (get_date(<ime, TIME_FUZZY_DATE)) - { - if (null_value) - return set_field_to_null(field); - t_type=TIMESTAMP_NONE; // Error - } + return set_field_to_null(field); field->set_notnull(); - field->store_time(<ime,t_type); + field->store_time(<ime, TIMESTAMP_DATE); return 0; } -longlong Item_func_from_days::val_int() +longlong Item_date::val_int() +{ + TIME ltime; + if (get_date(<ime, TIME_FUZZY_DATE)) + return 0; + return (longlong) (ltime.year*10000L+ltime.month*100+ltime.day); +} + + +bool Item_func_from_days::get_date(TIME *ltime, uint fuzzy_date) { longlong value=args[0]->val_int(); if ((null_value=args[0]->null_value)) - return 0; /* purecov: inspected */ - - uint year,month,day; - get_date_from_daynr((long) value,&year,&month,&day); - return (longlong) (year*10000L+month*100+day); + return 1; + get_date_from_daynr((long) value, <ime->year, <ime->month, <ime->day); + ltime->time_type= TIMESTAMP_DATE; + return 0; } @@ -1082,6 +1125,16 @@ void Item_func_curdate::fix_length_and_dec() ltime.time_type=TIMESTAMP_DATE; } +String *Item_func_curdate::val_str(String *str) +{ + if (str->alloc(11)) + { + null_value= 1; + return (String *) 0; + } + make_date((DATE_TIME_FORMAT *) 0, <ime, str); + return str; +} bool Item_func_curdate::get_date(TIME *res, uint fuzzy_date __attribute__((unused))) @@ -2311,6 +2364,103 @@ void Item_func_get_format::print(String *str) } +/* + check_result_type(s, l) returns DATE/TIME type + according to format string + + s: DATE/TIME format string + l: length of s + Result: date_time_format_types value: + DATE_TIME_MICROSECOND, DATE_TIME, + TIME_MICROSECOND, TIME_ONLY + + We don't process day format's characters('D', 'd', 'e') + because day may be a member of all date/time types. + If only day format's character and no time part present + the result type is MYSQL_TYPE_DATE +*/ + +date_time_format_types check_result_type(const char *format, uint length) +{ + const char *time_part_frms= "HISThiklrs"; + const char *date_part_frms= "MUYWabcjmuyw"; + bool date_part_used= 0, time_part_used= 0, frac_second_used= 0; + + const char *val= format; + const char *end= format + length; + + for (; val != end && val != end; val++) + { + if (*val == '%' && val+1 != end) + { + val++; + if ((frac_second_used= (*val == 'f')) || + (!time_part_used && strchr(time_part_frms, *val))) + time_part_used= 1; + else if (!date_part_used && strchr(date_part_frms, *val)) + date_part_used= 1; + if (time_part_used && date_part_used && frac_second_used) + return DATE_TIME_MICROSECOND; + } + } + + if (time_part_used) + { + if (date_part_used) + return DATE_TIME; + if (frac_second_used) + return TIME_MICROSECOND; + return TIME_ONLY; + } + return DATE_ONLY; +} + + +Field *Item_func_str_to_date::tmp_table_field(TABLE *t_arg) +{ + if (cached_field_type == MYSQL_TYPE_TIME) + return (new Field_time(maybe_null, name, t_arg, &my_charset_bin)); + if (cached_field_type == MYSQL_TYPE_DATE) + return (new Field_date(maybe_null, name, t_arg, &my_charset_bin)); + if (cached_field_type == MYSQL_TYPE_DATETIME) + return (new Field_datetime(maybe_null, name, t_arg, &my_charset_bin)); + return (new Field_string(max_length, maybe_null, name, t_arg, &my_charset_bin)); +} + + +void Item_func_str_to_date::fix_length_and_dec() +{ + char format_buff[64]; + String format_str(format_buff, sizeof(format_buff), &my_charset_bin), *format; + maybe_null= 1; + decimals=0; + cached_field_type= MYSQL_TYPE_STRING; + max_length= MAX_DATETIME_FULL_WIDTH*MY_CHARSET_BIN_MB_MAXLEN; + cached_timestamp_type= TIMESTAMP_NONE; + if ((const_item= args[1]->const_item())) + { + format= args[1]->val_str(&format_str); + cached_format_type= check_result_type(format->ptr(), format->length()); + switch (cached_format_type) { + case DATE_ONLY: + cached_timestamp_type= TIMESTAMP_DATE; + cached_field_type= MYSQL_TYPE_DATE; + max_length= MAX_DATE_WIDTH*MY_CHARSET_BIN_MB_MAXLEN; + break; + case TIME_ONLY: + case TIME_MICROSECOND: + cached_timestamp_type= TIMESTAMP_TIME; + cached_field_type= MYSQL_TYPE_TIME; + max_length= MAX_TIME_WIDTH*MY_CHARSET_BIN_MB_MAXLEN; + break; + default: + cached_timestamp_type= TIMESTAMP_DATETIME; + cached_field_type= MYSQL_TYPE_DATETIME; + break; + } + } +} + bool Item_func_str_to_date::get_date(TIME *ltime, uint fuzzy_date) { DATE_TIME_FORMAT date_time_format; @@ -2328,8 +2478,18 @@ bool Item_func_str_to_date::get_date(TIME *ltime, uint fuzzy_date) 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)) + ltime, cached_timestamp_type)) goto null_date; + if (cached_timestamp_type == TIMESTAMP_TIME && ltime->day) + { + /* + Day part for time type can be nonzero value and so + we should add hours from day part to hour part to + keep valid time value. + */ + ltime->hour+= ltime->day*24; + ltime->day= 0; + } return 0; null_date: @@ -2344,29 +2504,22 @@ String *Item_func_str_to_date::val_str(String *str) if (Item_func_str_to_date::get_date(<ime, TIME_FUZZY_DATE)) return 0; - /* - 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, + if (!make_datetime((const_item ? cached_format_type : + (ltime.second_part ? DATE_TIME_MICROSECOND : DATE_TIME)), <ime, str)) return str; return 0; } -String *Item_func_last_day::val_str(String *str) +bool Item_func_last_day::get_date(TIME *ltime, uint fuzzy_date) { - TIME ltime; - if (!get_arg0_date(<ime,0)) - { - uint month_idx= ltime.month-1; - ltime.day= days_in_month[month_idx]; - if ( month_idx == 1 && calc_days_in_year(ltime.year) == 366) - ltime.day+= 1; - if (!make_datetime(DATE_ONLY, <ime, str)) - return str; - } + if (get_arg0_date(ltime,fuzzy_date)) + return 1; + uint month_idx= ltime->month-1; + ltime->day= days_in_month[month_idx]; + if ( month_idx == 1 && calc_days_in_year(ltime->year) == 366) + ltime->day= 29; + ltime->time_type= TIMESTAMP_DATE; return 0; } diff --git a/sql/item_timefunc.h b/sql/item_timefunc.h index 854a54bbe80..1b044b49fb1 100644 --- a/sql/item_timefunc.h +++ b/sql/item_timefunc.h @@ -21,6 +21,11 @@ #pragma interface /* gcc class implementation */ #endif +enum date_time_format_types +{ + TIME_ONLY= 0, TIME_MICROSECOND, DATE_ONLY, DATE_TIME, DATE_TIME_MICROSECOND +}; + class Item_func_period_add :public Item_int_func { public: @@ -318,6 +323,7 @@ public: enum Item_result result_type () const { return STRING_RESULT; } enum_field_types field_type() const { return MYSQL_TYPE_DATE; } String *val_str(String *str); + longlong val_int(); double val() { return (double) val_int(); } const char *func_name() const { return "date"; } void fix_length_and_dec() @@ -407,6 +413,7 @@ public: Item_func_curdate() :Item_date() {} void set_result_from_tm(struct tm *now); longlong val_int() { return (value) ; } + String *val_str(String *str); void fix_length_and_dec(); bool get_date(TIME *res, uint fuzzy_date); virtual void store_now_in_tm(time_t now, struct tm *now_tm)=0; @@ -477,8 +484,8 @@ class Item_func_from_days :public Item_date { public: Item_func_from_days(Item *a) :Item_date(a) {} - longlong val_int(); const char *func_name() const { return "from_days"; } + bool get_date(TIME *res, uint fuzzy_date); }; @@ -806,37 +813,29 @@ public: }; -class Item_func_str_to_date :public Item_date_func +class Item_func_str_to_date :public Item_str_func { + enum_field_types cached_field_type; + date_time_format_types cached_format_type; + timestamp_type cached_timestamp_type; + bool const_item; public: Item_func_str_to_date(Item *a, Item *b) - :Item_date_func(a, b) + :Item_str_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=MAX_DATETIME_FULL_WIDTH*MY_CHARSET_BIN_MB_MAXLEN; - } + enum_field_types field_type() const { return cached_field_type; } + void fix_length_and_dec(); + Field *tmp_table_field(TABLE *t_arg); }; -class Item_func_last_day :public Item_str_func + +class Item_func_last_day :public Item_date { public: - Item_func_last_day(Item *a) :Item_str_func(a) {} - String *val_str(String *str); + Item_func_last_day(Item *a) :Item_date(a) {} const char *func_name() const { return "last_day"; } - enum_field_types field_type() const { return MYSQL_TYPE_DATE; } - void fix_length_and_dec() - { - decimals=0; - max_length=MAX_DATE_WIDTH*MY_CHARSET_BIN_MB_MAXLEN; - } - Field *tmp_table_field(TABLE *t_arg) - { - return (new Field_date(maybe_null, name, t_arg, &my_charset_bin)); - } + bool get_date(TIME *res, uint fuzzy_date); }; diff --git a/sql/mysql_priv.h b/sql/mysql_priv.h index eb879a1fd59..9fd7e6f5b93 100644 --- a/sql/mysql_priv.h +++ b/sql/mysql_priv.h @@ -799,6 +799,7 @@ extern char glob_hostname[FN_REFLEN], mysql_home[FN_REFLEN]; extern char pidfile_name[FN_REFLEN], time_zone[30], *opt_init_file; extern char log_error_file[FN_REFLEN]; extern double log_10[32]; +extern ulonglong log_10_int[20]; extern ulonglong keybuff_size; extern ulong refresh_version,flush_version, thread_id,query_id,opened_tables; extern ulong created_tmp_tables, created_tmp_disk_tables, bytes_sent; @@ -958,6 +959,8 @@ timestamp_type str_to_TIME(const char *str, uint length, TIME *l_time, void localtime_to_TIME(TIME *to, struct tm *from); void calc_time_from_sec(TIME *to, long seconds, long microseconds); +void make_truncated_value_warning(THD *thd, const char *str_val, + uint str_length, timestamp_type time_type); extern DATE_TIME_FORMAT *date_time_format_make(timestamp_type format_type, const char *format_str, uint format_length); diff --git a/sql/mysqld.cc b/sql/mysqld.cc index 5b6c592cd51..9a469e529cf 100644 --- a/sql/mysqld.cc +++ b/sql/mysqld.cc @@ -305,6 +305,14 @@ ulong my_bind_addr; /* the address we bind to */ volatile ulong cached_thread_count= 0; double log_10[32]; /* 10 potences */ +ulonglong log_10_int[20]= +{ + 1, 10, 100, 1000, 10000UL, 100000UL, 1000000UL, 10000000UL, + 100000000UL, 1000000000UL, 10000000000UL, 100000000000UL, + 1000000000000UL, 10000000000000UL, 100000000000000UL, + 1000000000000000UL, 10000000000000000UL, 100000000000000000UL, + 1000000000000000000UL, 10000000000000000000UL +}; time_t start_time; diff --git a/sql/share/czech/errmsg.txt b/sql/share/czech/errmsg.txt index 3a2d7a44c44..2d2a4472d9d 100644 --- a/sql/share/czech/errmsg.txt +++ b/sql/share/czech/errmsg.txt @@ -304,3 +304,4 @@ character-set=latin2 "The '%s' feature was disabled; you need MySQL built with '%s' to have it working", "The MySQL server is running with the %s option so it cannot execute this statement", "Column '%-.100s' has duplicated value '%-.64s' in %s" +"Truncated wrong %-.32s value: '%-.128s'" diff --git a/sql/share/danish/errmsg.txt b/sql/share/danish/errmsg.txt index 917ea3bf407..ca7c67552c3 100644 --- a/sql/share/danish/errmsg.txt +++ b/sql/share/danish/errmsg.txt @@ -298,3 +298,4 @@ character-set=latin1 "The '%s' feature was disabled; you need MySQL built with '%s' to have it working", "The MySQL server is running with the %s option so it cannot execute this statement", "Column '%-.100s' has duplicated value '%-.64s' in %s" +"Truncated wrong %-.32s value: '%-.128s'" diff --git a/sql/share/dutch/errmsg.txt b/sql/share/dutch/errmsg.txt index 16cf2fd15de..2cb9e7e511b 100644 --- a/sql/share/dutch/errmsg.txt +++ b/sql/share/dutch/errmsg.txt @@ -306,3 +306,4 @@ character-set=latin1 "The '%s' feature was disabled; you need MySQL built with '%s' to have it working", "The MySQL server is running with the %s option so it cannot execute this statement", "Column '%-.100s' has duplicated value '%-.64s' in %s" +"Truncated wrong %-.32s value: '%-.128s'" diff --git a/sql/share/english/errmsg.txt b/sql/share/english/errmsg.txt index 8c4e0530ed4..4e0da64408e 100644 --- a/sql/share/english/errmsg.txt +++ b/sql/share/english/errmsg.txt @@ -295,3 +295,4 @@ character-set=latin1 "The '%s' feature was disabled; you need MySQL built with '%s' to have it working", "The MySQL server is running with the %s option so it cannot execute this statement", "Column '%-.100s' has duplicated value '%-.64s' in %s" +"Truncated wrong %-.32s value: '%-.128s'" diff --git a/sql/share/estonian/errmsg.txt b/sql/share/estonian/errmsg.txt index 8c7cc53ef06..8b912d10e97 100644 --- a/sql/share/estonian/errmsg.txt +++ b/sql/share/estonian/errmsg.txt @@ -300,3 +300,4 @@ character-set=latin7 "The '%s' feature was disabled; you need MySQL built with '%s' to have it working", "The MySQL server is running with the %s option so it cannot execute this statement", "Column '%-.100s' has duplicated value '%-.64s' in %s" +"Truncated wrong %-.32s value: '%-.128s'" diff --git a/sql/share/french/errmsg.txt b/sql/share/french/errmsg.txt index 78d729fc9f8..ef7385422fb 100644 --- a/sql/share/french/errmsg.txt +++ b/sql/share/french/errmsg.txt @@ -295,3 +295,4 @@ character-set=latin1 "The '%s' feature was disabled; you need MySQL built with '%s' to have it working", "The MySQL server is running with the %s option so it cannot execute this statement", "Column '%-.100s' has duplicated value '%-.64s' in %s" +"Truncated wrong %-.32s value: '%-.128s'" diff --git a/sql/share/german/errmsg.txt b/sql/share/german/errmsg.txt index 142076a1f14..60454d0d011 100644 --- a/sql/share/german/errmsg.txt +++ b/sql/share/german/errmsg.txt @@ -307,3 +307,4 @@ character-set=latin1 "The '%s' feature was disabled; you need MySQL built with '%s' to have it working", "The MySQL server is running with the %s option so it cannot execute this statement", "Column '%-.100s' has duplicated value '%-.64s' in %s" +"Truncated wrong %-.32s value: '%-.128s'" diff --git a/sql/share/greek/errmsg.txt b/sql/share/greek/errmsg.txt index b9f47a54b35..4f695465bf5 100644 --- a/sql/share/greek/errmsg.txt +++ b/sql/share/greek/errmsg.txt @@ -295,3 +295,4 @@ character-set=greek "The '%s' feature was disabled; you need MySQL built with '%s' to have it working", "The MySQL server is running with the %s option so it cannot execute this statement", "Column '%-.100s' has duplicated value '%-.64s' in %s" +"Truncated wrong %-.32s value: '%-.128s'" diff --git a/sql/share/hungarian/errmsg.txt b/sql/share/hungarian/errmsg.txt index 9deb3da88a2..fdd48f38ef1 100644 --- a/sql/share/hungarian/errmsg.txt +++ b/sql/share/hungarian/errmsg.txt @@ -297,3 +297,4 @@ character-set=latin2 "The '%s' feature was disabled; you need MySQL built with '%s' to have it working", "The MySQL server is running with the %s option so it cannot execute this statement", "Column '%-.100s' has duplicated value '%-.64s' in %s" +"Truncated wrong %-.32s value: '%-.128s'" diff --git a/sql/share/italian/errmsg.txt b/sql/share/italian/errmsg.txt index 9b5a081ec9d..b88117c0972 100644 --- a/sql/share/italian/errmsg.txt +++ b/sql/share/italian/errmsg.txt @@ -295,3 +295,4 @@ character-set=latin1 "The '%s' feature was disabled; you need MySQL built with '%s' to have it working", "The MySQL server is running with the %s option so it cannot execute this statement", "Column '%-.100s' has duplicated value '%-.64s' in %s" +"Truncated wrong %-.32s value: '%-.128s'" diff --git a/sql/share/japanese/errmsg.txt b/sql/share/japanese/errmsg.txt index 1a17277cb90..c1b38e9ecbb 100644 --- a/sql/share/japanese/errmsg.txt +++ b/sql/share/japanese/errmsg.txt @@ -297,3 +297,4 @@ character-set=ujis "The '%s' feature was disabled; you need MySQL built with '%s' to have it working", "The MySQL server is running with the %s option so it cannot execute this statement", "Column '%-.100s' has duplicated value '%-.64s' in %s" +"Truncated wrong %-.32s value: '%-.128s'" diff --git a/sql/share/korean/errmsg.txt b/sql/share/korean/errmsg.txt index 9b07afd16c9..932243eca38 100644 --- a/sql/share/korean/errmsg.txt +++ b/sql/share/korean/errmsg.txt @@ -295,3 +295,4 @@ character-set=euckr "The '%s' feature was disabled; you need MySQL built with '%s' to have it working", "The MySQL server is running with the %s option so it cannot execute this statement", "Column '%-.100s' has duplicated value '%-.64s' in %s" +"Truncated wrong %-.32s value: '%-.128s'" diff --git a/sql/share/norwegian-ny/errmsg.txt b/sql/share/norwegian-ny/errmsg.txt index aaba0f1afbe..05b55a582bd 100644 --- a/sql/share/norwegian-ny/errmsg.txt +++ b/sql/share/norwegian-ny/errmsg.txt @@ -297,3 +297,4 @@ character-set=latin1 "The '%s' feature was disabled; you need MySQL built with '%s' to have it working", "The MySQL server is running with the %s option so it cannot execute this statement", "Column '%-.100s' has duplicated value '%-.64s' in %s" +"Truncated wrong %-.32s value: '%-.128s'" diff --git a/sql/share/norwegian/errmsg.txt b/sql/share/norwegian/errmsg.txt index f205e07b3bb..c11e529efd5 100644 --- a/sql/share/norwegian/errmsg.txt +++ b/sql/share/norwegian/errmsg.txt @@ -297,3 +297,4 @@ character-set=latin1 "The '%s' feature was disabled; you need MySQL built with '%s' to have it working", "The MySQL server is running with the %s option so it cannot execute this statement", "Column '%-.100s' has duplicated value '%-.64s' in %s" +"Truncated wrong %-.32s value: '%-.128s'" diff --git a/sql/share/polish/errmsg.txt b/sql/share/polish/errmsg.txt index 2c942d40f80..319deedc321 100644 --- a/sql/share/polish/errmsg.txt +++ b/sql/share/polish/errmsg.txt @@ -299,3 +299,4 @@ character-set=latin2 "The '%s' feature was disabled; you need MySQL built with '%s' to have it working", "The MySQL server is running with the %s option so it cannot execute this statement", "Column '%-.100s' has duplicated value '%-.64s' in %s" +"Truncated wrong %-.32s value: '%-.128s'" diff --git a/sql/share/portuguese/errmsg.txt b/sql/share/portuguese/errmsg.txt index f3a8a484696..5151e612813 100644 --- a/sql/share/portuguese/errmsg.txt +++ b/sql/share/portuguese/errmsg.txt @@ -296,3 +296,4 @@ character-set=latin1 "The '%s' feature was disabled; you need MySQL built with '%s' to have it working", "The MySQL server is running with the %s option so it cannot execute this statement", "Column '%-.100s' has duplicated value '%-.64s' in %s" +"Truncated wrong %-.32s value: '%-.128s'" diff --git a/sql/share/romanian/errmsg.txt b/sql/share/romanian/errmsg.txt index 72df2447f99..2c6ec81cc1d 100644 --- a/sql/share/romanian/errmsg.txt +++ b/sql/share/romanian/errmsg.txt @@ -299,3 +299,4 @@ character-set=latin2 "The '%s' feature was disabled; you need MySQL built with '%s' to have it working", "The MySQL server is running with the %s option so it cannot execute this statement", "Column '%-.100s' has duplicated value '%-.64s' in %s" +"Truncated wrong %-.32s value: '%-.128s'" diff --git a/sql/share/russian/errmsg.txt b/sql/share/russian/errmsg.txt index 3d37b2d60ce..00e931eb65a 100644 --- a/sql/share/russian/errmsg.txt +++ b/sql/share/russian/errmsg.txt @@ -297,3 +297,4 @@ character-set=koi8r "The '%s' feature was disabled; you need MySQL built with '%s' to have it working", "The MySQL server is running with the %s option so it cannot execute this statement", "Column '%-.100s' has duplicated value '%-.64s' in %s" +"Truncated wrong %-.32s value: '%-.128s'" diff --git a/sql/share/serbian/errmsg.txt b/sql/share/serbian/errmsg.txt index c68f9538dd2..dc15bbf4977 100644 --- a/sql/share/serbian/errmsg.txt +++ b/sql/share/serbian/errmsg.txt @@ -289,3 +289,4 @@ character-set=cp1250 "The '%s' feature was disabled; you need MySQL built with '%s' to have it working" "The MySQL server is running with the %s option so it cannot execute this statement" "Column '%-.100s' has duplicated value '%-.64s' in %s" +"Truncated wrong %-.32s value: '%-.128s'" diff --git a/sql/share/slovak/errmsg.txt b/sql/share/slovak/errmsg.txt index 35263024bb8..00b0dd9a0ae 100644 --- a/sql/share/slovak/errmsg.txt +++ b/sql/share/slovak/errmsg.txt @@ -303,3 +303,4 @@ character-set=latin2 "The '%s' feature was disabled; you need MySQL built with '%s' to have it working", "The MySQL server is running with the %s option so it cannot execute this statement", "Column '%-.100s' has duplicated value '%-.64s' in %s" +"Truncated wrong %-.32s value: '%-.128s'" diff --git a/sql/share/spanish/errmsg.txt b/sql/share/spanish/errmsg.txt index 3e0f67b453a..cb5d5b6df28 100644 --- a/sql/share/spanish/errmsg.txt +++ b/sql/share/spanish/errmsg.txt @@ -297,3 +297,4 @@ character-set=latin1 "The '%s' feature was disabled; you need MySQL built with '%s' to have it working", "The MySQL server is running with the %s option so it cannot execute this statement", "Column '%-.100s' has duplicated value '%-.64s' in %s" +"Truncated wrong %-.32s value: '%-.128s'" diff --git a/sql/share/swedish/errmsg.txt b/sql/share/swedish/errmsg.txt index dc6759f91e0..5c60519e217 100644 --- a/sql/share/swedish/errmsg.txt +++ b/sql/share/swedish/errmsg.txt @@ -295,3 +295,4 @@ character-set=latin1 "MySQL är started i --skip-grant-tables mod. Pga av detta kan du inte använda detta program", "Column '%-.100s' has duplicated value '%-.64s' in %s" +"Truncated wrong %-.32s value: '%-.128s'" diff --git a/sql/share/ukrainian/errmsg.txt b/sql/share/ukrainian/errmsg.txt index fbf31744dca..7dd694e75ac 100644 --- a/sql/share/ukrainian/errmsg.txt +++ b/sql/share/ukrainian/errmsg.txt @@ -300,3 +300,4 @@ character-set=koi8u "The '%s' feature was disabled; you need MySQL built with '%s' to have it working", "The MySQL server is running with the %s option so it cannot execute this statement", "Column '%-.100s' has duplicated value '%-.64s' in %s" +"Truncated wrong %-.32s value: '%-.128s'" diff --git a/sql/time.cc b/sql/time.cc index 1dff0c62edf..376ad6926b8 100644 --- a/sql/time.cc +++ b/sql/time.cc @@ -391,9 +391,11 @@ str_to_TIME(const char *str, uint length, TIME *l_time, uint flags) ulong not_zero_date, allow_space; bool is_internal_format; const char *pos, *last_field_pos; + const char *str_begin= str; const char *end=str+length; const uchar *format_position; bool found_delimitier= 0, found_space= 0; + uint frac_pos, frac_len; DBUG_ENTER("str_to_TIME"); DBUG_PRINT("ENTER",("str: %.*s",length,str)); @@ -482,7 +484,7 @@ str_to_TIME(const char *str, uint length, TIME *l_time, uint flags) tmp_value=tmp_value*10 + (ulong) (uchar) (*str - '0'); str++; } - date_len[i]+= (uint) (str - start); + date_len[i]= (uint) (str - start); if (tmp_value > 999999) // Impossible date part DBUG_RETURN(TIMESTAMP_NONE); date[i]=tmp_value; @@ -535,9 +537,9 @@ str_to_TIME(const char *str, uint length, TIME *l_time, uint flags) { if (str+2 <= end && (str[1] == 'M' || str[1] == 'm')) { - if (str[1] == 'p' || str[1] == 'P') + if (str[0] == 'p' || str[0] == 'P') add_hours= 12; - else if (str[1] != 'a' || str[1] != 'A') + else if (str[0] != 'a' || str[0] != 'A') continue; // Not AM/PM str+= 2; // Skip AM/PM /* Skip space after AM/PM */ @@ -569,7 +571,13 @@ str_to_TIME(const char *str, uint length, TIME *l_time, uint flags) 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]]; + + frac_pos= (uint) format_position[6]; + frac_len= date_len[frac_pos]; + if (frac_len < 6) + date[frac_pos]*= (uint) log_10_int[6 - frac_len]; + l_time->second_part= date[frac_pos]; + if (format_position[7] != (uchar) 255) { if (l_time->hour > 12) @@ -585,6 +593,8 @@ str_to_TIME(const char *str, uint length, TIME *l_time, uint flags) l_time->hour= date[3]; l_time->minute= date[4]; l_time->second= date[5]; + if (date_len[6] < 6) + date[6]*= (uint) log_10_int[6 - date_len[6]]; l_time->second_part=date[6]; } l_time->neg= 0; @@ -614,15 +624,17 @@ str_to_TIME(const char *str, uint length, TIME *l_time, uint flags) current_thd->cuted_fields++; goto err; } - if (str != end && current_thd->count_cuted_fields) + + l_time->time_type= (number_of_fields <= 3 ? + TIMESTAMP_DATE : TIMESTAMP_DATETIME); + + for (; str != end ; str++) { - for (; str != end ; str++) + if (!my_isspace(&my_charset_latin1,*str)) { - if (!my_isspace(&my_charset_latin1,*str)) - { - current_thd->cuted_fields++; - break; - } + make_truncated_value_warning(current_thd, str_begin, length, + l_time->time_type); + break; } } @@ -686,6 +698,7 @@ bool str_to_time(const char *str,uint length,TIME *l_time) { long date[5],value; const char *end=str+length, *end_of_days; + const char *str_begin= str; bool found_days,found_hours; uint state; @@ -706,7 +719,7 @@ bool str_to_time(const char *str,uint length,TIME *l_time) { // Probably full timestamp enum timestamp_type res= str_to_TIME(str,length,l_time, (TIME_FUZZY_DATE | - TIME_DATETIME_ONLY)); + TIME_DATETIME_ONLY)); if ((int) res >= (int) TIMESTAMP_DATETIME_ERROR) return res == TIMESTAMP_DATETIME_ERROR; } @@ -784,6 +797,8 @@ fractional: my_isdigit(&my_charset_latin1,str[0]) && field_length--) value=value*10 + (uint) (uchar) (*str - '0'); + if (field_length) + value*= (long) log_10_int[field_length]; date[4]=value; } else @@ -796,12 +811,12 @@ fractional: str++; if (str+2 <= end && (str[1] == 'M' || str[1] == 'm')) { - if (str[1] == 'p' || str[1] == 'P') + if (str[0] == 'p' || str[0] == 'P') { str+= 2; date[1]= date[1]%12 + 12; } - else if (str[1] == 'a' || str[1] == 'A') + else if (str[0] == 'a' || str[0] == 'A') str+=2; } } @@ -822,13 +837,14 @@ fractional: l_time->time_type= TIMESTAMP_TIME; /* Check if there is garbage at end of the TIME specification */ - if (str != end && current_thd->count_cuted_fields) + if (str != end) { do { if (!my_isspace(&my_charset_latin1,*str)) { - current_thd->cuted_fields++; + make_truncated_value_warning(current_thd, str_begin, length, + TIMESTAMP_TIME); break; } } while (++str != end); @@ -1265,3 +1281,35 @@ void make_datetime(DATE_TIME_FORMAT *format, TIME *l_time, String *str) str->length(length); str->set_charset(&my_charset_bin); } + +void make_truncated_value_warning(THD *thd, const char *str_val, + uint str_length, timestamp_type time_type) +{ + char warn_buff[MYSQL_ERRMSG_SIZE]; + const char *type_str; + + char buff[128]; + String str(buff,(uint32) sizeof(buff), system_charset_info); + str.length(0); + str.append(str_val, str_length); + str.append('\0'); + + switch (time_type) { + case TIMESTAMP_DATE: + type_str= "date"; + break; + case TIMESTAMP_DATETIME: + type_str= "datetime"; + break; + case TIMESTAMP_TIME: + type_str= "time"; + break; + default: + type_str= "string"; + break; + } + sprintf(warn_buff, ER(ER_TRUNCATED_WRONG_VALUE), + type_str, str.ptr()); + push_warning_printf(thd, MYSQL_ERROR::WARN_LEVEL_NOTE, + ER_TRUNCATED_WRONG_VALUE, warn_buff); +} |