diff options
author | monty@mysql.com <> | 2004-07-07 11:29:39 +0300 |
---|---|---|
committer | monty@mysql.com <> | 2004-07-07 11:29:39 +0300 |
commit | 1e311999950833cd81ca0788cd3656585c46d9ae (patch) | |
tree | ca8974710746bb69b04a49bc64f938d0b1a8420a /sql-common | |
parent | 24a8dc2337a717ff340bac228383ef04437a4666 (diff) | |
parent | 8462b8aeb83355fa6c5cb4f45ea0ed63ba9e0712 (diff) | |
download | mariadb-git-1e311999950833cd81ca0788cd3656585c46d9ae.tar.gz |
Merge with 4.1.3-beta
Diffstat (limited to 'sql-common')
-rw-r--r-- | sql-common/Makefile.am | 2 | ||||
-rw-r--r-- | sql-common/client.c | 123 | ||||
-rw-r--r-- | sql-common/my_time.c | 561 |
3 files changed, 653 insertions, 33 deletions
diff --git a/sql-common/Makefile.am b/sql-common/Makefile.am index 1f397c0ea87..6bd42d70e4f 100644 --- a/sql-common/Makefile.am +++ b/sql-common/Makefile.am @@ -15,7 +15,7 @@ # Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA ## Process this file with automake to create Makefile.in -EXTRA_DIST = client.c pack.c +EXTRA_DIST = client.c pack.c my_time.c # Don't update the files from bitkeeper %::SCCS/s.% diff --git a/sql-common/client.c b/sql-common/client.c index 02fb1964eaa..3aaa9f23665 100644 --- a/sql-common/client.c +++ b/sql-common/client.c @@ -39,6 +39,10 @@ #include "mysql.h" +/* Remove client convenience wrappers */ +#undef max_allowed_packet +#undef net_buffer_length + #ifdef EMBEDDED_LIBRARY #undef MYSQL_SERVER @@ -63,7 +67,6 @@ my_bool net_flush(NET *net); #include "mysqld_error.h" #include "errmsg.h" #include <violite.h> -#include <assert.h> #if defined(THREAD) && !defined(__WIN__) #include <my_pthread.h> /* because of signal() */ #endif /* defined(THREAD) && !defined(__WIN__) */ @@ -445,13 +448,13 @@ HANDLE create_shared_memory(MYSQL *mysql,NET *net, uint connect_timeout) if (WaitForSingleObject(event_connect_answer,connect_timeout*1000) != WAIT_OBJECT_0) { - error_allow = CR_SHARED_MEMORY_CONNECT_ABANDODED_ERROR; + error_allow = CR_SHARED_MEMORY_CONNECT_ABANDONED_ERROR; goto err; } /* Get number of connection */ connect_number = uint4korr(handle_connect_map);/*WAX2*/ - p= int2str(connect_number, connect_number_char, 10); + p= int10_to_str(connect_number, connect_number_char, 10); /* The name of event and file-mapping events create agree next rule: @@ -751,6 +754,58 @@ static my_bool is_NT(void) } #endif + +#ifdef CHECK_LICENSE +/* + Check server side variable 'license'. + If the variable does not exist or does not contain 'Commercial', + we're talking to non-commercial server from commercial client. + SYNOPSIS + check_license() + RETURN VALUE + 0 success + !0 network error or the server is not commercial. + Error code is saved in mysql->net.last_errno. +*/ + +static int check_license(MYSQL *mysql) +{ + MYSQL_ROW row; + MYSQL_RES *res; + NET *net= &mysql->net; + static const char query[]= "SELECT @@license"; + static const char required_license[]= STRINGIFY_ARG(LICENSE); + + if (mysql_real_query(mysql, query, sizeof(query)-1)) + { + if (net->last_errno == ER_UNKNOWN_SYSTEM_VARIABLE) + { + net->last_errno= CR_WRONG_LICENSE; + sprintf(net->last_error, ER(net->last_errno), required_license); + } + return 1; + } + if (!(res= mysql_use_result(mysql))) + return 1; + row= mysql_fetch_row(res); + /* + If no rows in result set, or column value is NULL (none of these + two is ever true for server variables now), or column value + mismatch, set wrong license error. + */ + if (!net->last_errno && + (!row || !row[0] || + strncmp(row[0], required_license, sizeof(required_license)))) + { + net->last_errno= CR_WRONG_LICENSE; + sprintf(net->last_error, ER(net->last_errno), required_license); + } + mysql_free_result(res); + return net->last_errno; +} +#endif /* CHECK_LICENSE */ + + /************************************************************************** Shut down connection **************************************************************************/ @@ -1681,7 +1736,8 @@ CLI_MYSQL_REAL_CONNECT(MYSQL *mysql,const char *host, const char *user, sprintf(net->last_error, ER(CR_UNKNOWN_HOST), host, tmp_errno); goto error; } - memcpy(&sock_addr.sin_addr,hp->h_addr, (size_t) hp->h_length); + memcpy(&sock_addr.sin_addr, hp->h_addr, + min(sizeof(sock_addr.sin_addr), (size_t) hp->h_length)); my_gethostbyname_r_free(); } sock_addr.sin_port = (ushort) htons((ushort) port); @@ -1783,40 +1839,39 @@ CLI_MYSQL_REAL_CONNECT(MYSQL *mysql,const char *host, const char *user, } /* Set character set */ - if (mysql->options.charset_name) + if (!mysql->options.charset_name && + !(mysql->options.charset_name= + my_strdup(MYSQL_DEFAULT_CHARSET_NAME,MYF(MY_WME)))) + goto error; + { const char *save= charsets_dir; if (mysql->options.charset_dir) charsets_dir=mysql->options.charset_dir; mysql->charset=get_charset_by_csname(mysql->options.charset_name, - MY_CS_PRIMARY, - MYF(MY_WME)); + MY_CS_PRIMARY, MYF(MY_WME)); charsets_dir= save; - - if (!mysql->charset) - { - net->last_errno=CR_CANT_READ_CHARSET; - strmov(net->sqlstate, unknown_sqlstate); - if (mysql->options.charset_dir) - my_snprintf(net->last_error, sizeof(net->last_error)-1, - ER(net->last_errno), - mysql->options.charset_name, - mysql->options.charset_dir); - else - { - char cs_dir_name[FN_REFLEN]; - get_charsets_dir(cs_dir_name); - my_snprintf(net->last_error, sizeof(net->last_error)-1, - ER(net->last_errno), - mysql->options.charset_name, - cs_dir_name); - } - goto error; - } } - else + + if (!mysql->charset) { - mysql->charset= default_charset_info; + net->last_errno=CR_CANT_READ_CHARSET; + strmov(net->sqlstate, unknown_sqlstate); + if (mysql->options.charset_dir) + my_snprintf(net->last_error, sizeof(net->last_error)-1, + ER(net->last_errno), + mysql->options.charset_name, + mysql->options.charset_dir); + else + { + char cs_dir_name[FN_REFLEN]; + get_charsets_dir(cs_dir_name); + my_snprintf(net->last_error, sizeof(net->last_error)-1, + ER(net->last_errno), + mysql->options.charset_name, + cs_dir_name); + } + goto error; } @@ -1996,10 +2051,14 @@ CLI_MYSQL_REAL_CONNECT(MYSQL *mysql,const char *host, const char *user, goto error; } - if (client_flag & CLIENT_COMPRESS) /* We will use compression */ net->compress=1; +#ifdef CHECK_LICENSE + if (check_license(mysql)) + goto error; +#endif + if (db && mysql_select_db(mysql,db)) goto error; @@ -2469,7 +2528,7 @@ mysql_fetch_row(MYSQL_RES *res) { set_mysql_error(mysql, res->unbuffered_fetch_cancelled ? - CR_FETCH_CANCELLED : CR_COMMANDS_OUT_OF_SYNC, + CR_FETCH_CANCELED : CR_COMMANDS_OUT_OF_SYNC, unknown_sqlstate); } else if (!(read_one_row(mysql, res->field_count, res->row, res->lengths))) diff --git a/sql-common/my_time.c b/sql-common/my_time.c new file mode 100644 index 00000000000..46c84ac9ba7 --- /dev/null +++ b/sql-common/my_time.c @@ -0,0 +1,561 @@ +/* Copyright (C) 2004 MySQL AB & MySQL Finland AB & TCX DataKonsult 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 */ + +#include <my_time.h> +#include <m_string.h> +#include <m_ctype.h> + +ulonglong log_10_int[20]= +{ + 1, 10, 100, 1000, 10000UL, 100000UL, 1000000UL, 10000000UL, + ULL(100000000), ULL(1000000000), ULL(10000000000), ULL(100000000000), + ULL(1000000000000), ULL(10000000000000), ULL(100000000000000), + ULL(1000000000000000), ULL(10000000000000000), ULL(100000000000000000), + ULL(1000000000000000000), ULL(10000000000000000000) +}; + + +/* 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 MYSQL_TIME value. + + SYNOPSIS + str_to_datetime() + str String to parse + length Length of string + l_time Date is stored here + 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. + was_cut Set to 1 if value was cut during conversion or to 0 + otherwise. + + DESCRIPTION + At least the following formats are recogniced (based on number of digits) + YYMMDD, YYYYMMDD, YYMMDDHHMMSS, YYYYMMDDHHMMSS + YY-MM-DD, YYYY-MM-DD, YY-MM-DD HH.MM.SS + 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 + MYSQL_TIMESTAMP_NONE String wasn't a timestamp, like + [DD [HH:[MM:[SS]]]].fraction. + l_time is not changed. + MYSQL_TIMESTAMP_DATE DATE string (YY MM and DD parts ok) + MYSQL_TIMESTAMP_DATETIME Full timestamp + MYSQL_TIMESTAMP_ERROR Timestamp with wrong values. + All elements in l_time is set to 0 +*/ + +#define MAX_DATE_PARTS 8 + +enum enum_mysql_timestamp_type +str_to_datetime(const char *str, uint length, MYSQL_TIME *l_time, + uint flags, int *was_cut) +{ + 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; + const uchar *format_position; + bool found_delimitier= 0, found_space= 0; + uint frac_pos, frac_len; + DBUG_ENTER("str_to_datetime"); + DBUG_PRINT("ENTER",("str: %.*s",length,str)); + + LINT_INIT(field_length); + LINT_INIT(year_length); + LINT_INIT(last_field_pos); + + *was_cut= 0; + + /* Skip space at start */ + for (; str != end && my_isspace(&my_charset_latin1, *str) ; str++) + ; + if (str == end || ! my_isdigit(&my_charset_latin1, *str)) + { + *was_cut= 1; + DBUG_RETURN(MYSQL_TIMESTAMP_NONE); + } + + is_internal_format= 0; + /* This has to be changed if want to activate different timestamp formats */ + format_position= internal_format_positions; + + /* + 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++) + ; + + digits= (uint) (pos-str); + start_loop= 0; /* Start of scan loop */ + date_len[format_position[0]]= 0; /* Length of year field */ + if (pos == end) + { + /* Found date in internal format (only numbers like YYYYMMDD) */ + year_length= (digits == 4 || digits == 8 || digits >= 14) ? 4 : 2; + field_length=year_length-1; + 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) + { + *was_cut= 1; + DBUG_RETURN(MYSQL_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]= date[4]= 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 = start_loop; + i < MAX_DATE_PARTS-1 && str != end && + my_isdigit(&my_charset_latin1,*str); + i++) + { + 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 + (ulong) (uchar) (*str - '0'); + str++; + } + date_len[i]= (uint) (str - start); + if (tmp_value > 999999) /* Impossible date part */ + { + *was_cut= 1; + DBUG_RETURN(MYSQL_TIMESTAMP_NONE); + } + date[i]=tmp_value; + not_zero_date|= tmp_value; + + /* 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 */ + continue; + } + if (i == format_position[5]) /* Seconds */ + { + if (*str == '.') /* Followed by part seconds */ + { + str++; + field_length= 5; /* 5 digits after first (=6) */ + } + continue; + + /* No part seconds */ + date[++i]= 0; + } + 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))) + { + *was_cut= 1; + DBUG_RETURN(MYSQL_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[0] == 'p' || str[0] == 'P') + add_hours= 12; + else if (str[0] != 'a' || str[0] != '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; + } + if (found_delimitier && !found_space && (flags & TIME_DATETIME_ONLY)) + { + *was_cut= 1; + DBUG_RETURN(MYSQL_TIMESTAMP_NONE); /* Can't be a datetime */ + } + + str= last_field_pos; + + number_of_fields= i - start_loop; + while (i < MAX_DATE_PARTS) + { + date_len[i]= 0; + date[i++]= 0; + } + + if (!is_internal_format) + { + year_length= date_len[(uint) format_position[0]]; + if (!year_length) /* Year must be specified */ + { + *was_cut= 1; + DBUG_RETURN(MYSQL_TIMESTAMP_NONE); + } + + 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]]; + + 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) + { + *was_cut= 1; + goto err; + } + l_time->hour= l_time->hour%12 + add_hours; + } + } + 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]; + 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; + + 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 || + (!(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 */ + { + for (; str != end ; str++) + { + if (!my_isspace(&my_charset_latin1, *str)) + { + not_zero_date= 1; /* Give warning */ + break; + } + } + } + if (not_zero_date) + *was_cut= 1; + goto err; + } + + l_time->time_type= (number_of_fields <= 3 ? + MYSQL_TIMESTAMP_DATE : MYSQL_TIMESTAMP_DATETIME); + + for (; str != end ; str++) + { + if (!my_isspace(&my_charset_latin1,*str)) + { + *was_cut= 1; + break; + } + } + + DBUG_RETURN(l_time->time_type= + (number_of_fields <= 3 ? MYSQL_TIMESTAMP_DATE : + MYSQL_TIMESTAMP_DATETIME)); + +err: + bzero((char*) l_time, sizeof(*l_time)); + DBUG_RETURN(MYSQL_TIMESTAMP_ERROR); +} + + +/* + Convert a time string to a TIME struct. + + SYNOPSIS + str_to_time() + str A string in full TIMESTAMP format or + [-] DAYS [H]H:MM:SS, [H]H:MM:SS, [M]M:SS, [H]HMMSS, + [M]MSS or [S]S + There may be an optional [.second_part] after seconds + length Length of str + l_time Store result here + was_cut Set to 1 if value was cut during conversion or to 0 + otherwise. + + 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, MYSQL_TIME *l_time, + int *was_cut) +{ + long date[5],value; + const char *end=str+length, *end_of_days; + bool found_days,found_hours; + uint state; + + l_time->neg=0; + *was_cut= 0; + for (; str != end && my_isspace(&my_charset_latin1,*str) ; str++) + length--; + if (str != end && *str == '-') + { + l_time->neg=1; + str++; + length--; + } + if (str == end) + return 1; + + /* Check first if this is a full TIMESTAMP */ + if (length >= 12) + { /* Probably full timestamp */ + enum enum_mysql_timestamp_type + res= str_to_datetime(str, length, l_time, + (TIME_FUZZY_DATE | TIME_DATETIME_ONLY), was_cut); + if ((int) res >= (int) MYSQL_TIMESTAMP_ERROR) + return res == MYSQL_TIMESTAMP_ERROR; + /* We need to restore was_cut flag since str_to_datetime can modify it */ + *was_cut= 0; + } + + /* 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'); + + /* Skip 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 != 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; + state=2; + found_hours=1; + str++; /* skip ':' */ + } + else + { + /* String given as one number; assume HHMMSS format */ + date[0]= 0; + date[1]= value/10000; + date[2]= value/100 % 100; + date[3]= value % 100; + state=4; + goto fractional; + } + + /* Read hours, minutes and seconds */ + for (;;) + { + 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 != time_separator || + !my_isdigit(&my_charset_latin1,str[1])) + break; + str++; /* Skip time_separator (':') */ + } + + if (state != 4) + { /* Not HH:MM:SS */ + /* Fix the date to assume that seconds was given */ + if (!found_hours && !found_days) + { + bmove_upp((char*) (date+4), (char*) (date+state), + sizeof(long)*(state-1)); + bzero((char*) date, sizeof(long)*(4-state)); + } + else + bzero((char*) (date+state), sizeof(long)*(4-state)); + } + +fractional: + /* Get fractional second part */ + if ((end-str) >= 2 && *str == '.' && my_isdigit(&my_charset_latin1,str[1])) + { + uint field_length=5; + str++; value=(uint) (uchar) (*str - '0'); + while (++str != end && + 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 + date[4]=0; + + if (internal_format_positions[7] != 255) + { + /* 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[0] == 'p' || str[0] == 'P') + { + str+= 2; + date[1]= date[1]%12 + 12; + } + else if (str[0] == 'a' || str[0] == 'A') + str+=2; + } + } + + /* Some simple checks */ + if (date[2] >= 60 || date[3] >= 60) + { + *was_cut= 1; + return 1; + } + l_time->year= 0; /* For protocol::store_time */ + l_time->month= 0; + l_time->day= date[0]; + l_time->hour= date[1]; + l_time->minute= date[2]; + l_time->second= date[3]; + l_time->second_part= date[4]; + l_time->time_type= MYSQL_TIMESTAMP_TIME; + + /* Check if there is garbage at end of the TIME specification */ + if (str != end) + { + do + { + if (!my_isspace(&my_charset_latin1,*str)) + { + *was_cut= 1; + break; + } + } while (++str != end); + } + return 0; +} + + |