diff --git a/sql/field.cc b/sql/field.cc index c287c716cc1..1b388287811 100644 --- a/sql/field.cc +++ b/sql/field.cc @@ -840,17 +840,19 @@ int Field_decimal::store(longlong nr) double Field_decimal::val_real(void) { - int err; - return my_strntod(my_charset_bin, ptr, field_length, NULL, &err); + int not_used; + return my_strntod(my_charset_bin, ptr, field_length, NULL, ¬_used); } longlong Field_decimal::val_int(void) { - int err; + int not_used; if (unsigned_flag) - return my_strntoull(my_charset_bin, ptr, field_length, 10, NULL, &err); + return my_strntoull(my_charset_bin, ptr, field_length, 10, NULL, + ¬_used); else - return my_strntoll( my_charset_bin, ptr, field_length, 10, NULL, &err); + return my_strntoll( my_charset_bin, ptr, field_length, 10, NULL, + ¬_used); } @@ -952,9 +954,9 @@ void Field_decimal::sql_type(String &res) const int Field_tiny::store(const char *from,uint len,CHARSET_INFO *cs) { - int err; + int not_used; // We can ignore result from str2int char *end; - long tmp= my_strntol(cs, from, len, 10, &end, &err); + long tmp= my_strntol(cs, from, len, 10, &end, ¬_used); int error= 0; if (unsigned_flag) @@ -1154,10 +1156,11 @@ void Field_tiny::sql_type(String &res) const int Field_short::store(const char *from,uint len,CHARSET_INFO *cs) { - int err; + int not_used; // We can ignore result from str2int char *end; - long tmp= my_strntol(cs, from, len, 10, &end, &err); + long tmp= my_strntol(cs, from, len, 10, &end, ¬_used); int error= 0; + if (unsigned_flag) { if (tmp < 0) @@ -1427,9 +1430,9 @@ void Field_short::sql_type(String &res) const int Field_medium::store(const char *from,uint len,CHARSET_INFO *cs) { - int err; + int not_used; // We can ignore result from str2int char *end; - long tmp= my_strntol(cs, from, len, 10, &end, &err); + long tmp= my_strntol(cs, from, len, 10, &end, ¬_used); int error= 0; if (unsigned_flag) @@ -2134,7 +2137,7 @@ void Field_longlong::sql_type(String &res) const int Field_float::store(const char *from,uint len,CHARSET_INFO *cs) { - int err=0; + int err; Field_float::store(my_strntod(cs,(char*) from,len,(char**)NULL,&err)); if (err || current_thd->count_cuted_fields && !test_if_real(from,len,cs)) { @@ -2407,7 +2410,7 @@ void Field_float::sql_type(String &res) const int Field_double::store(const char *from,uint len,CHARSET_INFO *cs) { - int err= 0; + int err; double j= my_strntod(cs,(char*) from,len,(char**)0,&err); if (err || current_thd->count_cuted_fields && !test_if_real(from,len,cs)) { @@ -3193,9 +3196,9 @@ void Field_time::sql_type(String &res) const int Field_year::store(const char *from, uint len,CHARSET_INFO *cs) { - int err; + int not_used; // We can ignore result from str2int char *end; - long nr= my_strntol(cs, from, len, 10, &end, &err); + long nr= my_strntol(cs, from, len, 10, &end, ¬_used); if (nr < 0 || nr >= 100 && nr <= 1900 || nr > 2155) { @@ -3932,17 +3935,17 @@ int Field_string::store(longlong nr) double Field_string::val_real(void) { - int err; + int not_used; CHARSET_INFO *cs=charset(); - return my_strntod(cs,ptr,field_length,(char**)0,&err); + return my_strntod(cs,ptr,field_length,(char**)0,¬_used); } longlong Field_string::val_int(void) { - int err; + int not_used; CHARSET_INFO *cs=charset(); - return my_strntoll(cs,ptr,field_length,10,NULL,&err); + return my_strntoll(cs,ptr,field_length,10,NULL,¬_used); } @@ -4017,7 +4020,6 @@ int Field_string::pack_cmp(const char *a, const char *b, uint length) { uint a_length= (uint) (uchar) *a++; uint b_length= (uint) (uchar) *b++; - return my_strnncoll(field_charset, (const uchar*)a,a_length, (const uchar*)b,b_length); @@ -4031,7 +4033,6 @@ int Field_string::pack_cmp(const char *b, uint length) while (end > ptr && end[-1] == ' ') end--; uint a_length = (uint) (end - ptr); - return my_strnncoll(field_charset, (const uchar*)ptr,a_length, (const uchar*)b, b_length); @@ -4101,19 +4102,19 @@ int Field_varstring::store(longlong nr) double Field_varstring::val_real(void) { - int err; + int not_used; uint length=uint2korr(ptr)+2; CHARSET_INFO *cs=charset(); - return my_strntod(cs,ptr+2,length,(char**)0,&err); + return my_strntod(cs,ptr+2,length,(char**)0, ¬_used); } longlong Field_varstring::val_int(void) { - int err; + int not_used; uint length=uint2korr(ptr)+2; CHARSET_INFO *cs=charset(); - return my_strntoll(cs,ptr+2,length,10,NULL,&err); + return my_strntoll(cs,ptr+2,length,10,NULL, ¬_used); } @@ -4421,26 +4422,26 @@ int Field_blob::store(longlong nr) double Field_blob::val_real(void) { - int err; + int not_used; char *blob; memcpy_fixed(&blob,ptr+packlength,sizeof(char*)); if (!blob) return 0.0; uint32 length=get_length(ptr); CHARSET_INFO *cs=charset(); - return my_strntod(cs,blob,length,(char**)0,&err); + return my_strntod(cs,blob,length,(char**)0, ¬_used); } longlong Field_blob::val_int(void) { - int err; + int not_used; char *blob; memcpy_fixed(&blob,ptr+packlength,sizeof(char*)); if (!blob) return 0; uint32 length=get_length(ptr); - return my_strntoll(charset(),blob,length,10,NULL,&err); + return my_strntoll(charset(),blob,length,10,NULL,¬_used); } @@ -4610,10 +4611,8 @@ void Field_blob::sort_string(char *to,uint length) blob_length=my_strnxfrm(field_charset, (unsigned char *)to, length, (unsigned char *)blob, blob_length); - if (blob_length >= length) - return; - to+=blob_length; - bzero(to,length-blob_length); + if (blob_length < length) + bzero(to+blob_length, length-blob_length); } } diff --git a/sql/sql_base.cc b/sql/sql_base.cc index 038a286f4df..db32030efd1 100644 --- a/sql/sql_base.cc +++ b/sql/sql_base.cc @@ -242,6 +242,7 @@ static void free_cache_entry(TABLE *table) DBUG_VOID_RETURN; } +/* Free resources allocated by filesort() and read_record() */ void free_io_cache(TABLE *table) { diff --git a/sql/sql_lex.cc b/sql/sql_lex.cc index 1a33ac0760b..aebaf745fc0 100644 --- a/sql/sql_lex.cc +++ b/sql/sql_lex.cc @@ -107,7 +107,7 @@ void lex_init(void) state_map[i]=(uchar) STATE_CHAR; } state_map[(uchar)'_']=state_map[(uchar)'$']=(uchar) STATE_IDENT; - state_map[(uchar)'\'']=state_map[(uchar)'"']=(uchar) STATE_STRING; + state_map[(uchar)'\'']=(uchar) STATE_STRING; state_map[(uchar)'-']=state_map[(uchar)'+']=(uchar) STATE_SIGNED_NUMBER; state_map[(uchar)'.']=(uchar) STATE_REAL_OR_POINT; state_map[(uchar)'>']=state_map[(uchar)'=']=state_map[(uchar)'!']= (uchar) STATE_CMP_OP; @@ -122,10 +122,7 @@ void lex_init(void) state_map[(uchar)'*']= (uchar) STATE_END_LONG_COMMENT; state_map[(uchar)'@']= (uchar) STATE_USER_END; state_map[(uchar) '`']= (uchar) STATE_USER_VARIABLE_DELIMITER; - if (global_system_variables.sql_mode & MODE_ANSI_QUOTES) - { - state_map[(uchar) '"'] = STATE_USER_VARIABLE_DELIMITER; - } + state_map[(uchar)'"']= (uchar) STAT_STRING_OR_DELIMITER; /* Create a second map to make it faster to find identifiers @@ -652,12 +649,13 @@ int yylex(void *arg, void *yythd) return(IDENT); case STATE_USER_VARIABLE_DELIMITER: + { + char delim= c; // Used char lex->tok_start=lex->ptr; // Skip first ` #ifdef USE_MB if (use_mb(system_charset_info)) { - while ((c=yyGet()) && state_map[c] != STATE_USER_VARIABLE_DELIMITER && - c != (uchar) NAMES_SEP_CHAR) + while ((c=yyGet()) && c != delim && c != (uchar) NAMES_SEP_CHAR) { if (my_ismbhead(system_charset_info, c)) { @@ -673,16 +671,15 @@ int yylex(void *arg, void *yythd) else #endif { - while ((c=yyGet()) && state_map[c] != STATE_USER_VARIABLE_DELIMITER && - c != (uchar) NAMES_SEP_CHAR) ; + while ((c=yyGet()) && c != delim && c != (uchar) NAMES_SEP_CHAR) ; } yylval->lex_str=get_token(lex,yyLength()); if (lex->convert_set) lex->convert_set->convert((char*) yylval->lex_str.str,lex->yytoklen); - if (state_map[c] == STATE_USER_VARIABLE_DELIMITER) + if (c == delim) yySkip(); // Skip end ` return(IDENT); - + } case STATE_SIGNED_NUMBER: // Incomplete signed number if (prev_state == STATE_OPERATOR_OR_IDENT) { @@ -795,6 +792,13 @@ int yylex(void *arg, void *yythd) lex->next_state= STATE_START; // Allow signed numbers return(tokval); + case STAT_STRING_OR_DELIMITER: + if (((THD *) yythd)->variables.sql_mode & MODE_ANSI_QUOTES) + { + state= STATE_USER_VARIABLE_DELIMITER; + break; + } + /* " used for strings */ case STATE_STRING: // Incomplete text string if (!(yylval->lex_str.str = get_text(lex))) { @@ -889,6 +893,7 @@ int yylex(void *arg, void *yythd) switch (state_map[yyPeek()]) { case STATE_STRING: case STATE_USER_VARIABLE_DELIMITER: + case STAT_STRING_OR_DELIMITER: break; case STATE_USER_END: lex->next_state=STATE_SYSTEM_VAR; diff --git a/sql/sql_lex.h b/sql/sql_lex.h index e4a17838cd2..5c1c91bbe4a 100644 --- a/sql/sql_lex.h +++ b/sql/sql_lex.h @@ -86,7 +86,8 @@ enum lex_states STATE_REAL_OR_POINT, STATE_BOOL, STATE_EOL, STATE_ESCAPE, STATE_LONG_COMMENT, STATE_END_LONG_COMMENT, STATE_COLON, STATE_SET_VAR, STATE_USER_END, STATE_HOSTNAME, STATE_SKIP, STATE_USER_VARIABLE_DELIMITER, STATE_SYSTEM_VAR, - STATE_IDENT_OR_KEYWORD, STATE_IDENT_OR_HEX, STATE_IDENT_OR_BIN + STATE_IDENT_OR_KEYWORD, STATE_IDENT_OR_HEX, STATE_IDENT_OR_BIN, + STAT_STRING_OR_DELIMITER }; diff --git a/strings/ctype-simple.c b/strings/ctype-simple.c index df1609c983d..b47a15d2cfa 100644 --- a/strings/ctype-simple.c +++ b/strings/ctype-simple.c @@ -214,6 +214,7 @@ long my_strntol_8bit(CHARSET_INFO *cs, const char *save, *e; int overflow; + *err= 0; /* Initialize error indicator */ if (base < 0 || base == 1 || base > 36) base = 10; @@ -330,6 +331,7 @@ ulong my_strntoul_8bit(CHARSET_INFO *cs, const char *save, *e; int overflow; + *err= 0; /* Initialize error indicator */ if (base < 0 || base == 1 || base > 36) base = 10; @@ -437,6 +439,7 @@ longlong my_strntoll_8bit(CHARSET_INFO *cs __attribute__((unused)), const char *save; int overflow; + *err= 0; /* Initialize error indicator */ if (base < 0 || base == 1 || base > 36) base = 10; @@ -553,6 +556,7 @@ ulonglong my_strntoull_8bit(CHARSET_INFO *cs, const char *save; int overflow; + *err= 0; /* Initialize error indicator */ if (base < 0 || base == 1 || base > 36) base = 10; @@ -655,7 +659,8 @@ noconv: cs Character set information str String to convert to double length Optional length for string. - end pointer to end of converted string + end result pointer to end of converted string + err Error number if failed conversion NOTES: If length is not INT_MAX32 or str[length] != 0 then the given str must @@ -665,23 +670,28 @@ noconv: It's implemented this way to save a buffer allocation and a memory copy. RETURN - value of number in string + Value of number in string */ double my_strntod_8bit(CHARSET_INFO *cs __attribute__((unused)), char *str, uint length, - char **end, int *err __attribute__ ((unused))) + char **end, int *err) { char end_char; double result; + errno= 0; /* Safety */ if (length == INT_MAX32 || str[length] == 0) - return strtod(str, end); - end_char= str[length]; - str[length]= 0; - result= strtod(str, end); - str[length]= end_char; /* Restore end char */ + result= strtod(str, end); + else + { + end_char= str[length]; + str[length]= 0; + result= strtod(str, end); + str[length]= end_char; /* Restore end char */ + } + *err= errno; return result; } diff --git a/strings/ctype-utf8.c b/strings/ctype-utf8.c index e57f35bab19..b247075622e 100644 --- a/strings/ctype-utf8.c +++ b/strings/ctype-utf8.c @@ -2459,7 +2459,9 @@ long my_strntol_ucs2(CHARSET_INFO *cs, register const char *e=nptr+l; const char *save; - do { + *err= 0; + do + { if ((cnv=cs->mb_wc(cs,&wc,s,e))>0) { switch (wc) @@ -2570,7 +2572,9 @@ ulong my_strntoul_ucs2(CHARSET_INFO *cs, register const char *e=nptr+l; const char *save; - do { + *err= 0; + do + { if ((cnv=cs->mb_wc(cs,&wc,s,e))>0) { switch (wc) @@ -2675,7 +2679,9 @@ longlong my_strntoll_ucs2(CHARSET_INFO *cs, register const char *e=nptr+l; const char *save; - do { + *err= 0; + do + { if ((cnv=cs->mb_wc(cs,&wc,s,e))>0) { switch (wc) @@ -2788,7 +2794,9 @@ ulonglong my_strntoull_ucs2(CHARSET_INFO *cs, register const char *e=nptr+l; const char *save; - do { + *err= 0; + do + { if ((cnv=cs->mb_wc(cs,&wc,s,e))>0) { switch (wc) @@ -2821,7 +2829,8 @@ bs: cutoff = (~(ulonglong) 0) / (unsigned long int) base; cutlim = (uint) ((~(ulonglong) 0) % (unsigned long int) base); - do { + do + { if ((cnv=cs->mb_wc(cs,&wc,s,e))>0) { s+=cnv; @@ -2878,7 +2887,7 @@ bs: double my_strntod_ucs2(CHARSET_INFO *cs __attribute__((unused)), char *nptr, uint length, - char **endptr, int *err __attribute__ ((unused))) + char **endptr, int *err) { char buf[256]; double res; @@ -2887,7 +2896,8 @@ double my_strntod_ucs2(CHARSET_INFO *cs __attribute__((unused)), register const char *end; my_wc_t wc; int cnv; - + + *err= 0; /* Cut too long strings */ if (length >= sizeof(buf)) length= sizeof(buf)-1; @@ -2902,7 +2912,9 @@ double my_strntod_ucs2(CHARSET_INFO *cs __attribute__((unused)), } *b= 0; + errno= 0; res=strtod(buf, endptr); + *err= errno; if (endptr) *endptr=(char*) (*endptr-buf+nptr); return res;