diff options
author | unknown <hf@deer.mysql.r18.ru> | 2003-01-15 13:15:35 +0400 |
---|---|---|
committer | unknown <hf@deer.mysql.r18.ru> | 2003-01-15 13:15:35 +0400 |
commit | 150a238f033c3e3f8d67dfaa7d1616237738c1cb (patch) | |
tree | 937beb6f27e5e7958081a4a5ba13ceb2f5251396 /sql/field.cc | |
parent | 09b79b65f225e7e7f66077f95b00e095cf454c3a (diff) | |
parent | 2d6f1c223d94fe874ac7acba089a1678f314dfac (diff) | |
download | mariadb-git-150a238f033c3e3f8d67dfaa7d1616237738c1cb.tar.gz |
resolving conflicts
BitKeeper/etc/logging_ok:
auto-union
client/mysql.cc:
Auto merged
client/mysqltest.c:
Auto merged
include/mysql.h:
Auto merged
include/mysql_com.h:
Auto merged
libmysqld/libmysqld.c:
Auto merged
sql/field.cc:
Auto merged
sql/field.h:
Auto merged
sql/ha_berkeley.cc:
Auto merged
sql/ha_innodb.cc:
Auto merged
sql/ha_myisam.cc:
Auto merged
sql/item.cc:
Auto merged
sql/item.h:
Auto merged
sql/item_func.cc:
Auto merged
sql/item_strfunc.cc:
Auto merged
sql/log.cc:
Auto merged
sql/mini_client.cc:
Auto merged
sql/mysql_priv.h:
Auto merged
sql/net_serv.cc:
Auto merged
sql/repl_failsafe.cc:
Auto merged
sql/set_var.cc:
Auto merged
sql/set_var.h:
Auto merged
sql/slave.cc:
Auto merged
sql/slave.h:
Auto merged
sql/sql_acl.cc:
Auto merged
sql/sql_base.cc:
Auto merged
sql/sql_cache.cc:
Auto merged
sql/sql_class.cc:
Auto merged
sql/sql_class.h:
Auto merged
sql/sql_db.cc:
Auto merged
sql/sql_error.cc:
Auto merged
sql/sql_handler.cc:
Auto merged
sql/sql_help.cc:
Auto merged
sql/sql_load.cc:
Auto merged
sql/sql_parse.cc:
Auto merged
sql/sql_prepare.cc:
Auto merged
sql/sql_repl.cc:
Auto merged
sql/sql_select.cc:
Auto merged
sql/sql_table.cc:
Auto merged
sql/log_event.cc:
Conflicts resolving
sql/log_event.h:
conflicts
sql/mysqld.cc:
conflicts
sql/opt_range.cc:
conflicts
sql/protocol.cc:
conflicts
sql/sql_show.cc:
conflicts
Diffstat (limited to 'sql/field.cc')
-rw-r--r-- | sql/field.cc | 491 |
1 files changed, 234 insertions, 257 deletions
diff --git a/sql/field.cc b/sql/field.cc index c3feb0b8826..dfc41f37205 100644 --- a/sql/field.cc +++ b/sql/field.cc @@ -34,8 +34,6 @@ // Maximum allowed exponent value for converting string to decimal #define MAX_EXPONENT 1024 - - /***************************************************************************** Instansiate templates and static variables *****************************************************************************/ @@ -67,39 +65,44 @@ void Field_num::prepend_zeros(String *value) /* Test if given number is a int (or a fixed format float with .000) - This is only used to give warnings in ALTER TABLE or LOAD DATA... + + SYNOPSIS + test_if_int() + str String to test + end Pointer to char after last used digit + cs Character set + + NOTES + This is called after one has called my_strntol() or similar function. + This is only used to give warnings in ALTER TABLE or LOAD DATA... + + TODO + Make this multi-byte-character safe + + RETURN + 0 ok + 1 error */ -bool test_if_int(const char *str,int length, CHARSET_INFO *cs) +bool test_if_int(const char *str, int length, const char *int_end, + CHARSET_INFO *cs) { + if (str == int_end) + return 0; // Empty string const char *end=str+length; + if ((str= int_end) == end) + return 1; // All digits was used - cs=system_charset_info; // QQ move test_if_int into CHARSET_INFO struct - - // Allow start space - while (str != end && my_isspace(cs,*str)) - str++; /* purecov: inspected */ - if (str != end && (*str == '-' || *str == '+')) - str++; - if (str == end) - return 0; // Error: Empty string - for (; str != end ; str++) + /* Allow end .0000 */ + if (*str == '.') { - if (!my_isdigit(cs,*str)) - { - if (*str == '.') - { // Allow '.0000' - for (str++ ; str != end && *str == '0'; str++) ; - if (str == end) - return 1; - } - if (!my_isspace(cs,*str)) - return 0; - for (str++ ; str != end ; str++) - if (!my_isspace(cs,*str)) - return 0; - return 1; - } + for (str++ ; str != end && *str == '0'; str++) ; + } + /* Allow end space */ + for (str++ ; str != end ; str++) + { + if (!my_isspace(cs,*str)) + return 0; } return 1; } @@ -107,7 +110,7 @@ bool test_if_int(const char *str,int length, CHARSET_INFO *cs) static bool test_if_real(const char *str,int length, CHARSET_INFO *cs) { - cs=system_charset_info; // QQ move test_if_int into CHARSET_INFO struct + cs= system_charset_info; // QQ move test_if_real into CHARSET_INFO struct while (length && my_isspace(cs,*str)) { // Allow start space @@ -207,17 +210,10 @@ bool Field::send_binary(Protocol *protocol) void Field_num::add_zerofill_and_unsigned(String &res) const { - uint oldlen=res.length(); - if (oldlen < res.alloced_length()) - { - uint len=res.alloced_length()-oldlen; - char *end=(char*)(res.ptr()+oldlen); - CHARSET_INFO *cs=res.charset(); - len=cs->snprintf(cs,end,len,"%s%s", - unsigned_flag ? " unsigned" : "", - zerofill ? " zerofill" : ""); - res.length(len+oldlen); - } + if (unsigned_flag) + res.append(" unsigned"); + if (zerofill) + res.append(" zerofill"); } void Field_num::make_field(Send_field *field) @@ -247,19 +243,15 @@ void Field_str::make_field(Send_field *field) field->decimals=0; } + void Field_str::add_binary_or_charset(String &res) const { - uint oldlen=res.length(); - if (oldlen < res.alloced_length()) + if (binary()) + res.append(" binary"); + else if (field_charset != table->table_charset) { - CHARSET_INFO *cs=res.charset(); - uint len=res.alloced_length() - oldlen; - char *end=(char*)(res.ptr()+oldlen); - if (binary()) - len=cs->snprintf(cs,end,len," binary"); - else - len=cs->snprintf(cs,end,len," character set %s",field_charset->name); - res.length(oldlen+len); + res.append(" character set "); + res.append(field_charset->csname); } } @@ -287,7 +279,7 @@ uint Field::fill_cache_field(CACHE_FIELD *copy) bool Field::get_date(TIME *ltime,bool fuzzydate) { char buff[40]; - String tmp(buff,sizeof(buff),my_charset_latin1),tmp2,*res; + String tmp(buff,sizeof(buff),my_charset_bin),tmp2,*res; if (!(res=val_str(&tmp,&tmp2)) || str_to_TIME(res->ptr(),res->length(),ltime,fuzzydate) == TIMESTAMP_NONE) return 1; @@ -297,7 +289,7 @@ bool Field::get_date(TIME *ltime,bool fuzzydate) bool Field::get_time(TIME *ltime) { char buff[40]; - String tmp(buff,sizeof(buff),my_charset_latin1),tmp2,*res; + String tmp(buff,sizeof(buff),my_charset_bin),tmp2,*res; if (!(res=val_str(&tmp,&tmp2)) || str_to_time(res->ptr(),res->length(),ltime)) return 1; @@ -311,23 +303,23 @@ void Field::store_time(TIME *ltime,timestamp_type type) char buff[25]; switch (type) { case TIMESTAMP_NONE: - store("",0,my_charset_latin1); // Probably an error + store("",0,my_charset_bin); // Probably an error break; case TIMESTAMP_DATE: sprintf(buff,"%04d-%02d-%02d", ltime->year,ltime->month,ltime->day); - store(buff,10,my_charset_latin1); + store(buff,10,my_charset_bin); break; case TIMESTAMP_FULL: sprintf(buff,"%04d-%02d-%02d %02d:%02d:%02d", ltime->year,ltime->month,ltime->day, ltime->hour,ltime->minute,ltime->second); - store(buff,19,my_charset_latin1); + store(buff,19,my_charset_bin); break; case TIMESTAMP_TIME: { ulong length= my_sprintf(buff, (buff, "%02d:%02d:%02d", ltime->hour,ltime->minute,ltime->second)); - store(buff,(uint) length, my_charset_latin1); + store(buff,(uint) length, my_charset_bin); break; } } @@ -340,15 +332,12 @@ bool Field::optimize_range(uint idx) } /**************************************************************************** - Functions for the Field_null + Field_null, a field that always return NULL ****************************************************************************/ void Field_null::sql_type(String &res) const { - CHARSET_INFO *cs=res.charset(); - uint len; - len=cs->snprintf(cs,(char*)res.ptr(),res.alloced_length(),"null"); - res.length(len); + res.set_latin1("null", 4); } @@ -360,7 +349,7 @@ void Field_null::sql_type(String &res) const void Field_decimal::reset(void) { - Field_decimal::store("0",1,my_charset_latin1); + Field_decimal::store("0",1,my_charset_bin); } void Field_decimal::overflow(bool negative) @@ -404,11 +393,16 @@ void Field_decimal::overflow(bool negative) int Field_decimal::store(const char *from, uint len, CHARSET_INFO *cs) { - String l1from; + char buff[80]; + String tmp(buff,sizeof(buff), my_charset_bin); - l1from.copy(from,len,cs,my_charset_latin1); - from=l1from.ptr(); - len=l1from.length(); + /* Convert character set if the old one is multi byte */ + if (cs->mbmaxlen > 1) + { + tmp.copy(from, len, cs, my_charset_bin); + from= tmp.ptr(); + len= tmp.length(); + } const char *end= from+len; /* The pointer where the field value starts (i.e., "where to write") */ @@ -461,7 +455,7 @@ int Field_decimal::store(const char *from, uint len, CHARSET_INFO *cs) There are three steps in this function : - parse the input string - modify the position of digits around the decimal dot '.' - according to the exponent value (if specified) + according to the exponent value (if specified) - write the formatted number */ @@ -469,7 +463,7 @@ int Field_decimal::store(const char *from, uint len, CHARSET_INFO *cs) tmp_dec++; /* skip pre-space */ - while (from != end && my_isspace(my_charset_latin1,*from)) + while (from != end && my_isspace(my_charset_bin,*from)) from++; if (from == end) { @@ -506,13 +500,13 @@ int Field_decimal::store(const char *from, uint len, CHARSET_INFO *cs) for (; from!=end && *from == '0'; from++) ; // Read prezeros pre_zeros_end=int_digits_from=from; /* Read non zero digits at the left of '.'*/ - for (; from != end && my_isdigit(my_charset_latin1, *from) ; from++) ; + for (; from != end && my_isdigit(my_charset_bin, *from) ; from++) ; int_digits_end=from; if (from!=end && *from == '.') // Some '.' ? from++; frac_digits_from= from; /* Read digits at the right of '.' */ - for (;from!=end && my_isdigit(my_charset_latin1, *from); from++) ; + for (;from!=end && my_isdigit(my_charset_bin, *from); from++) ; frac_digits_end=from; // Some exponentiation symbol ? if (from != end && (*from == 'e' || *from == 'E')) @@ -528,7 +522,7 @@ int Field_decimal::store(const char *from, uint len, CHARSET_INFO *cs) exponents will become small (e.g. 1e4294967296 will become 1e0, and the field will finally contain 1 instead of its max possible value). */ - for (;from!=end && my_isdigit(my_charset_latin1, *from); from++) + for (;from!=end && my_isdigit(my_charset_bin, *from); from++) { exponent=10*exponent+(*from-'0'); if (exponent>MAX_EXPONENT) @@ -546,7 +540,7 @@ int Field_decimal::store(const char *from, uint len, CHARSET_INFO *cs) if (current_thd->count_cuted_fields) { // Skip end spaces - for (;from != end && my_isspace(my_charset_latin1, *from); from++) ; + for (;from != end && my_isspace(my_charset_bin, *from); from++) ; if (from != end) // If still something left, warn { current_thd->cuted_fields++; @@ -838,30 +832,29 @@ int Field_decimal::store(longlong nr) double Field_decimal::val_real(void) { - CHARSET_INFO *cs=charset(); - return my_strntod(cs,ptr,field_length,NULL); + return my_strntod(my_charset_bin, ptr, field_length, NULL); } longlong Field_decimal::val_int(void) { - CHARSET_INFO *cs=charset(); if (unsigned_flag) - return my_strntoull(cs,ptr,field_length,NULL,10); + return my_strntoull(my_charset_bin, ptr, field_length, NULL, 10); else - return my_strntoll(cs,ptr,field_length,NULL,10); + return my_strntoll( my_charset_bin, ptr, field_length, NULL, 10); } + String *Field_decimal::val_str(String *val_buffer __attribute__((unused)), String *val_ptr) { char *str; - CHARSET_INFO *cs=current_thd->variables.thd_charset; for (str=ptr ; *str == ' ' ; str++) ; uint tmp_length=(uint) (str-ptr); + val_ptr->set_charset(my_charset_bin); if (field_length < tmp_length) // Error in data val_ptr->length(0); else - val_ptr->copy((const char*) str,field_length-tmp_length,my_charset_latin1,cs); + val_ptr->set_latin1((const char*) str, field_length-tmp_length); return val_ptr; } @@ -878,9 +871,9 @@ int Field_decimal::cmp(const char *a_ptr,const char *b_ptr) for (end=a_ptr+field_length; a_ptr != end && (*a_ptr == *b_ptr || - ((my_isspace(my_charset_latin1,*a_ptr) || *a_ptr == '+' || + ((my_isspace(my_charset_bin,*a_ptr) || *a_ptr == '+' || *a_ptr == '0') && - (my_isspace(my_charset_latin1,*b_ptr) || *b_ptr == '+' || + (my_isspace(my_charset_bin,*b_ptr) || *b_ptr == '+' || *b_ptr == '0'))); a_ptr++,b_ptr++) { @@ -908,7 +901,7 @@ void Field_decimal::sort_string(char *to,uint length) char *str,*end; for (str=ptr,end=ptr+length; str != end && - ((my_isspace(my_charset_latin1,*str) || *str == '+' || + ((my_isspace(my_charset_bin,*str) || *str == '+' || *str == '0')) ; str++) *to++=' '; @@ -920,7 +913,7 @@ void Field_decimal::sort_string(char *to,uint length) *to++=1; // Smaller than any number str++; while (str != end) - if (my_isdigit(my_charset_latin1,*str)) + if (my_isdigit(my_charset_bin,*str)) *to++= (char) ('9' - *str++); else *to++= *str++; @@ -933,14 +926,12 @@ void Field_decimal::sql_type(String &res) const { CHARSET_INFO *cs=res.charset(); uint tmp=field_length; - uint len; if (!unsigned_flag) tmp--; if (dec) tmp--; - len=cs->snprintf(cs,(char*) res.ptr(),res.alloced_length(), - "decimal(%d,%d)",tmp,dec); - res.length(len); + res.length(cs->snprintf(cs,(char*) res.ptr(),res.alloced_length(), + "decimal(%d,%d)",tmp,dec)); add_zerofill_and_unsigned(res); } @@ -951,7 +942,8 @@ void Field_decimal::sql_type(String &res) const int Field_tiny::store(const char *from,uint len,CHARSET_INFO *cs) { - long tmp= my_strntol(cs,from,len,(char **)NULL,10); + char *end; + long tmp= my_strntol(cs, from, len, &end,10); int error= 0; if (unsigned_flag) @@ -968,7 +960,7 @@ int Field_tiny::store(const char *from,uint len,CHARSET_INFO *cs) current_thd->cuted_fields++; error= 1; } - else if (current_thd->count_cuted_fields && !test_if_int(from,len,cs)) + else if (current_thd->count_cuted_fields && !test_if_int(from,len,end,cs)) { current_thd->cuted_fields++; error= 1; @@ -988,7 +980,7 @@ int Field_tiny::store(const char *from,uint len,CHARSET_INFO *cs) current_thd->cuted_fields++; error= 1; } - else if (current_thd->count_cuted_fields && !test_if_int(from,len,cs)) + else if (current_thd->count_cuted_fields && !test_if_int(from,len,end,cs)) { current_thd->cuted_fields++; error= 1; @@ -1098,7 +1090,7 @@ longlong Field_tiny::val_int(void) String *Field_tiny::val_str(String *val_buffer, String *val_ptr __attribute__((unused))) { - CHARSET_INFO *cs=current_thd->variables.thd_charset; + CHARSET_INFO *cs= my_charset_bin; uint length; uint mlength=max(field_length+1,5*cs->mbmaxlen); val_buffer->alloc(mlength); @@ -1140,22 +1132,19 @@ void Field_tiny::sort_string(char *to,uint length __attribute__((unused))) void Field_tiny::sql_type(String &res) const { CHARSET_INFO *cs=res.charset(); - uint len=cs->snprintf(cs,(char*) res.ptr(),res.alloced_length(), - "tinyint(%d)",(int) field_length); - res.length(len); + res.length(cs->snprintf(cs,(char*) res.ptr(),res.alloced_length(), + "tinyint(%d)",(int) field_length)); add_zerofill_and_unsigned(res); } /**************************************************************************** -** short int + Field type short int (2 byte) ****************************************************************************/ - -// Note: Sometimes this should be fixed to check for garbage after number. - int Field_short::store(const char *from,uint len,CHARSET_INFO *cs) { - long tmp= my_strntol(cs,from,len,NULL,10); + char *end; + long tmp= my_strntol(cs, from, len, &end, 10); int error= 0; if (unsigned_flag) { @@ -1171,7 +1160,7 @@ int Field_short::store(const char *from,uint len,CHARSET_INFO *cs) current_thd->cuted_fields++; error= 1; } - else if (current_thd->count_cuted_fields && !test_if_int(from,len,cs)) + else if (current_thd->count_cuted_fields && !test_if_int(from,len,end,cs)) { current_thd->cuted_fields++; error= 1; @@ -1191,7 +1180,7 @@ int Field_short::store(const char *from,uint len,CHARSET_INFO *cs) current_thd->cuted_fields++; error= 1; } - else if (current_thd->count_cuted_fields && !test_if_int(from,len,cs)) + else if (current_thd->count_cuted_fields && !test_if_int(from,len,end,cs)) { current_thd->cuted_fields++; error= 1; @@ -1337,7 +1326,7 @@ longlong Field_short::val_int(void) String *Field_short::val_str(String *val_buffer, String *val_ptr __attribute__((unused))) { - CHARSET_INFO *cs=current_thd->variables.thd_charset; + CHARSET_INFO *cs= my_charset_bin; uint length; uint mlength=max(field_length+1,7*cs->mbmaxlen); val_buffer->alloc(mlength); @@ -1351,9 +1340,9 @@ String *Field_short::val_str(String *val_buffer, shortget(j,ptr); if (unsigned_flag) - length=(uint) cs->l10tostr(cs,to,mlength, 10, (long) (uint16) j); + length=(uint) cs->l10tostr(cs, to, mlength, 10, (long) (uint16) j); else - length=(uint) cs->l10tostr(cs,to,mlength,-10, (long) j); + length=(uint) cs->l10tostr(cs, to, mlength,-10, (long) j); val_buffer->length(length); if (zerofill) prepend_zeros(val_buffer); @@ -1414,22 +1403,20 @@ void Field_short::sort_string(char *to,uint length __attribute__((unused))) void Field_short::sql_type(String &res) const { CHARSET_INFO *cs=res.charset(); - uint len=cs->snprintf(cs,(char*) res.ptr(),res.alloced_length(), - "smallint(%d)",(int) field_length); - res.length(len); + res.length(cs->snprintf(cs,(char*) res.ptr(),res.alloced_length(), + "smallint(%d)",(int) field_length)); add_zerofill_and_unsigned(res); } /**************************************************************************** -** medium int + Field type medium int (3 byte) ****************************************************************************/ -// Note: Sometimes this should be fixed to check for garbage after number. - int Field_medium::store(const char *from,uint len,CHARSET_INFO *cs) { - long tmp= my_strntol(cs,from,len,NULL,10); + char *end; + long tmp= my_strntol(cs, from, len, &end, 10); int error= 0; if (unsigned_flag) @@ -1446,7 +1433,7 @@ int Field_medium::store(const char *from,uint len,CHARSET_INFO *cs) current_thd->cuted_fields++; error= 1; } - else if (current_thd->count_cuted_fields && !test_if_int(from,len,cs)) + else if (current_thd->count_cuted_fields && !test_if_int(from,len,end,cs)) { current_thd->cuted_fields++; error= 1; @@ -1466,7 +1453,7 @@ int Field_medium::store(const char *from,uint len,CHARSET_INFO *cs) current_thd->cuted_fields++; error= 1; } - else if (current_thd->count_cuted_fields && !test_if_int(from,len,cs)) + else if (current_thd->count_cuted_fields && !test_if_int(from,len,end,cs)) { current_thd->cuted_fields++; error= 1; @@ -1572,16 +1559,18 @@ double Field_medium::val_real(void) return (double) j; } + longlong Field_medium::val_int(void) { long j= unsigned_flag ? (long) uint3korr(ptr) : sint3korr(ptr); return (longlong) j; } + String *Field_medium::val_str(String *val_buffer, String *val_ptr __attribute__((unused))) { - CHARSET_INFO *cs=current_thd->variables.thd_charset; + CHARSET_INFO *cs= my_charset_bin; uint length; uint mlength=max(field_length+1,10*cs->mbmaxlen); val_buffer->alloc(mlength); @@ -1632,9 +1621,8 @@ void Field_medium::sort_string(char *to,uint length __attribute__((unused))) void Field_medium::sql_type(String &res) const { CHARSET_INFO *cs=res.charset(); - uint len=cs->snprintf(cs,(char*) res.ptr(),res.alloced_length(), - "mediumint(%d)",(int) field_length); - res.length(len); + res.length(cs->snprintf(cs,(char*) res.ptr(),res.alloced_length(), + "mediumint(%d)",(int) field_length)); add_zerofill_and_unsigned(res); } @@ -1643,26 +1631,23 @@ void Field_medium::sql_type(String &res) const ****************************************************************************/ -// Note: Sometimes this should be fixed to check for garbage after number. - int Field_long::store(const char *from,uint len,CHARSET_INFO *cs) { + long tmp; + int error= 0; char *end; + /* TODO: Make multi-byte-character safe */ while (len && my_isspace(cs,*from)) { len--; from++; } - long tmp; - String tmp_str(from, len, cs); - from= tmp_str.c_ptr(); // Add end null if needed - int error= 0; - errno=0; + my_errno=0; if (unsigned_flag) { if (!len || *from == '-') { tmp=0; // Set negative to 0 - errno=ERANGE; + my_errno=ERANGE; error= 1; } else @@ -1670,9 +1655,9 @@ int Field_long::store(const char *from,uint len,CHARSET_INFO *cs) } else tmp=my_strntol(cs,from,len,&end,10); - if (errno || + if (my_errno || (from+len != end && current_thd->count_cuted_fields && - !test_if_int(from,len,cs))) + !test_if_int(from,len,end,cs))) { current_thd->cuted_fields++; error= 1; @@ -1817,7 +1802,7 @@ longlong Field_long::val_int(void) String *Field_long::val_str(String *val_buffer, String *val_ptr __attribute__((unused))) { - CHARSET_INFO *cs=current_thd->variables.thd_charset; + CHARSET_INFO *cs= my_charset_bin; uint length; uint mlength=max(field_length+1,12*cs->mbmaxlen); val_buffer->alloc(mlength); @@ -1896,34 +1881,32 @@ void Field_long::sort_string(char *to,uint length __attribute__((unused))) void Field_long::sql_type(String &res) const { CHARSET_INFO *cs=res.charset(); - uint len=cs->snprintf(cs,(char*) res.ptr(),res.alloced_length(), - "int(%d)",(int) field_length); - res.length(len); + res.length(cs->snprintf(cs,(char*) res.ptr(),res.alloced_length(), + "int(%d)",(int) field_length)); add_zerofill_and_unsigned(res); } /**************************************************************************** -** longlong int + Field type longlong int (8 bytes) ****************************************************************************/ int Field_longlong::store(const char *from,uint len,CHARSET_INFO *cs) { + longlong tmp; + int error= 0; char *end; + /* TODO: Make multi byte safe */ while (len && my_isspace(cs,*from)) { // For easy error check len--; from++; } - longlong tmp; - String tmp_str(from, len, cs); - from= tmp_str.c_ptr(); // Add end null if needed - int error= 0; - errno=0; + my_errno=0; if (unsigned_flag) { if (!len || *from == '-') { tmp=0; // Set negative to 0 - errno=ERANGE; + my_errno= ERANGE; error= 1; } else @@ -1931,9 +1914,9 @@ int Field_longlong::store(const char *from,uint len,CHARSET_INFO *cs) } else tmp=my_strntoll(cs,from,len,&end,10); - if (errno || + if (my_errno || (from+len != end && current_thd->count_cuted_fields && - !test_if_int(from,len,cs))) + !test_if_int(from,len,end,cs))) current_thd->cuted_fields++; #ifdef WORDS_BIGENDIAN if (table->db_low_byte_first) @@ -2042,7 +2025,7 @@ longlong Field_longlong::val_int(void) String *Field_longlong::val_str(String *val_buffer, String *val_ptr __attribute__((unused))) { - CHARSET_INFO *cs=current_thd->variables.thd_charset; + CHARSET_INFO *cs= my_charset_bin; uint length; uint mlength=max(field_length+1,22*cs->mbmaxlen); val_buffer->alloc(mlength); @@ -2128,9 +2111,8 @@ void Field_longlong::sort_string(char *to,uint length __attribute__((unused))) void Field_longlong::sql_type(String &res) const { CHARSET_INFO *cs=res.charset(); - uint len=cs->snprintf(cs,(char*) res.ptr(),res.alloced_length(), - "bigint(%d)",(int) field_length); - res.length(len); + res.length(cs->snprintf(cs,(char*) res.ptr(),res.alloced_length(), + "bigint(%d)",(int) field_length)); add_zerofill_and_unsigned(res); } @@ -2140,8 +2122,8 @@ void Field_longlong::sql_type(String &res) const int Field_float::store(const char *from,uint len,CHARSET_INFO *cs) { - errno=0; - Field_float::store(my_strntod(cs,from,len,(char**)NULL)); + errno=0; // my_strntod() changes errno + Field_float::store(my_strntod(cs,(char*) from,len,(char**)NULL)); if (errno || current_thd->count_cuted_fields && !test_if_real(from,len,cs)) { current_thd->cuted_fields++; @@ -2394,18 +2376,16 @@ bool Field_float::send_binary(Protocol *protocol) void Field_float::sql_type(String &res) const { - CHARSET_INFO *cs=res.charset(); - uint len; if (dec == NOT_FIXED_DEC) { - len=cs->snprintf(cs,(char*) res.ptr(),res.alloced_length(),"float"); + res.set_latin1("float", 5); } else { - len=cs->snprintf(cs,(char*) res.ptr(),res.alloced_length(), - "float(%d,%d)",(int) field_length,dec); + CHARSET_INFO *cs= res.charset(); + res.length(cs->snprintf(cs,(char*) res.ptr(),res.alloced_length(), + "float(%d,%d)",(int) field_length,dec)); } - res.length(len); add_zerofill_and_unsigned(res); } @@ -2415,9 +2395,9 @@ void Field_float::sql_type(String &res) const int Field_double::store(const char *from,uint len,CHARSET_INFO *cs) { - errno=0; + errno=0; // my_strntod() changes errno int error= 0; - double j= my_strntod(cs,from,len,(char**)0); + double j= my_strntod(cs,(char*) from,len,(char**)0); if (errno || current_thd->count_cuted_fields && !test_if_real(from,len,cs)) { current_thd->cuted_fields++; @@ -2599,7 +2579,7 @@ String *Field_double::val_str(String *val_buffer, bool Field_double::send_binary(Protocol *protocol) { - return protocol->store((float) Field_double::val_real(), dec, (String*) 0); + return protocol->store((double) Field_double::val_real(), dec, (String*) 0); } @@ -2655,17 +2635,15 @@ void Field_double::sort_string(char *to,uint length __attribute__((unused))) void Field_double::sql_type(String &res) const { CHARSET_INFO *cs=res.charset(); - uint len; if (dec == NOT_FIXED_DEC) { - len=cs->snprintf(cs,(char*) res.ptr(),res.alloced_length(),"double"); + res.set_latin1("double",6); } else { - len=cs->snprintf(cs,(char*) res.ptr(),res.alloced_length(), - "double(%d,%d)",(int) field_length,dec); + res.length(cs->snprintf(cs,(char*) res.ptr(),res.alloced_length(), + "double(%d,%d)",(int) field_length,dec)); } - res.length(len); add_zerofill_and_unsigned(res); } @@ -2722,9 +2700,9 @@ int Field_timestamp::store(double nr) /* -** Convert a datetime of formats YYMMDD, YYYYMMDD or YYMMDDHHMSS to -** YYYYMMDDHHMMSS. The high date '99991231235959' is checked before this -** function. + Convert a datetime of formats YYMMDD, YYYYMMDD or YYMMDDHHMSS to + YYYYMMDDHHMMSS. The high date '99991231235959' is checked before this + function. */ static longlong fix_datetime(longlong nr) @@ -2797,7 +2775,6 @@ double Field_timestamp::val_real(void) longlong Field_timestamp::val_int(void) { - uint len,pos; int part_time; uint32 temp; time_t time_arg; @@ -2855,9 +2832,10 @@ String *Field_timestamp::val_str(String *val_buffer, if (temp == 0L) { /* Zero time is "000000" */ - strmov(to, "0000-00-00 00:00:00"); - return val_buffer; + val_ptr->set("0000-00-00 00:00:00", 19, my_charset_bin); + return val_ptr; } + val_buffer->set_charset(my_charset_bin); // Safety time_arg=(time_t) temp; localtime_r(&time_arg,&tm_tmp); l_time=&tm_tmp; @@ -2996,9 +2974,7 @@ void Field_timestamp::sort_string(char *to,uint length __attribute__((unused))) void Field_timestamp::sql_type(String &res) const { - CHARSET_INFO *cs=res.charset(); - uint len=cs->snprintf(cs,(char*)res.ptr(),res.alloced_length(),"timestamp"); - res.length(len); + res.set_latin1("timestamp", 9); } @@ -3126,6 +3102,12 @@ longlong Field_time::val_int(void) return (longlong) sint3korr(ptr); } + +/* + This function is multi-byte safe as the result string is always of type + my_charset_bin +*/ + String *Field_time::val_str(String *val_buffer, String *val_ptr __attribute__((unused))) { @@ -3169,7 +3151,7 @@ bool Field_time::send_binary(Protocol *protocol) Field_time::get_time(&tm); tm.day= tm.hour/3600; // Move hours to days tm.hour-= tm.day*3600; - return protocol->store(&tm); + return protocol->store_time(&tm); } @@ -3190,9 +3172,7 @@ void Field_time::sort_string(char *to,uint length __attribute__((unused))) void Field_time::sql_type(String &res) const { - CHARSET_INFO *cs=res.charset(); - uint len=cs->snprintf(cs,(char*)res.ptr(),res.alloced_length(),"time"); - res.length(len); + res.set_latin1("time", 4); } /**************************************************************************** @@ -3203,7 +3183,8 @@ void Field_time::sql_type(String &res) const int Field_year::store(const char *from, uint len,CHARSET_INFO *cs) { - long nr= my_strntol(cs,from,len,NULL,10); + char *end; + long nr= my_strntol(cs, from, len, &end, 10); if (nr < 0 || nr >= 100 && nr <= 1900 || nr > 2155) { @@ -3211,7 +3192,7 @@ int Field_year::store(const char *from, uint len,CHARSET_INFO *cs) current_thd->cuted_fields++; return 1; } - else if (current_thd->count_cuted_fields && !test_if_int(from,len,cs)) + else if (current_thd->count_cuted_fields && !test_if_int(from,len,end,cs)) current_thd->cuted_fields++; if (nr != 0 || len != 4) { @@ -3254,6 +3235,11 @@ int Field_year::store(longlong nr) return 0; } +bool Field_year::send_binary(Protocol *protocol) +{ + ulonglong tmp= Field_year::val_int(); + return protocol->store_short(tmp); +} double Field_year::val_real(void) { @@ -3283,9 +3269,8 @@ String *Field_year::val_str(String *val_buffer, void Field_year::sql_type(String &res) const { CHARSET_INFO *cs=res.charset(); - ulong len=cs->snprintf(cs,(char*)res.ptr(),res.alloced_length(), - "year(%d)",(int) field_length); - res.length(len); + res.length(cs->snprintf(cs,(char*)res.ptr(),res.alloced_length(), + "year(%d)",(int) field_length)); } @@ -3372,6 +3357,17 @@ int Field_date::store(longlong nr) } +bool Field_date::send_binary(Protocol *protocol) +{ + longlong tmp= Field_date::val_int(); + TIME tm; + tm.year= (uint32) tmp/10000L % 10000; + tm.month= (uint32) tmp/100 % 100; + tm.day= (uint32) tmp % 100; + return protocol->store_date(&tm); +} + + double Field_date::val_real(void) { int32 j; @@ -3455,9 +3451,7 @@ void Field_date::sort_string(char *to,uint length __attribute__((unused))) void Field_date::sql_type(String &res) const { - CHARSET_INFO *cs=res.charset(); - uint len=cs->snprintf(cs,(char*)res.ptr(),res.alloced_length(),"date"); - res.length(len); + res.set_latin1("date", 4); } /**************************************************************************** @@ -3544,7 +3538,12 @@ void Field_newdate::store_time(TIME *ltime,timestamp_type type) int3store(ptr,tmp); } - +bool Field_newdate::send_binary(Protocol *protocol) +{ + TIME tm; + Field_newdate::get_date(&tm,0); + return protocol->store_date(&tm); +} double Field_newdate::val_real(void) { @@ -3620,9 +3619,7 @@ void Field_newdate::sort_string(char *to,uint length __attribute__((unused))) void Field_newdate::sql_type(String &res) const { - CHARSET_INFO *cs=res.charset(); - uint len=cs->snprintf(cs,(char*)res.ptr(),res.alloced_length(),"date"); - res.length(len); + res.set_latin1("date", 4); } @@ -3705,6 +3702,13 @@ void Field_datetime::store_time(TIME *ltime,timestamp_type type) longlongstore(ptr,tmp); } +bool Field_datetime::send_binary(Protocol *protocol) +{ + TIME tm; + Field_datetime::get_date(&tm, 1); + return protocol->store(&tm); +} + double Field_datetime::val_real(void) { @@ -3846,9 +3850,7 @@ void Field_datetime::sort_string(char *to,uint length __attribute__((unused))) void Field_datetime::sql_type(String &res) const { - CHARSET_INFO *cs=res.charset(); - uint len=cs->snprintf(cs,(char*)res.ptr(),res.alloced_length(),"datetime"); - res.length(len); + res.set_latin1("datetime", 8); } /**************************************************************************** @@ -3903,7 +3905,7 @@ int Field_string::store(double nr) int width=min(field_length,DBL_DIG+5); sprintf(buff,"%-*.*g",width,max(width-5,0),nr); end=strcend(buff,' '); - return Field_string::store(buff,(uint) (end - buff), my_charset_latin1); + return Field_string::store(buff,(uint) (end - buff), my_charset_bin); } @@ -3926,7 +3928,6 @@ double Field_string::val_real(void) longlong Field_string::val_int(void) { - longlong value; CHARSET_INFO *cs=charset(); return my_strntoll(cs,ptr,field_length,NULL,10); } @@ -4016,11 +4017,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++; - if (binary()) - { - int cmp= memcmp(a,b,min(a_length,b_length)); - return cmp ? cmp : (int) (a_length - b_length); - } return my_strnncoll(field_charset, (const uchar*)a,a_length, (const uchar*)b,b_length); @@ -4035,11 +4031,6 @@ int Field_string::pack_cmp(const char *b, uint length) end--; uint a_length = (uint) (end - ptr); - if (binary()) - { - int cmp= memcmp(ptr,b,min(a_length,b_length)); - return cmp ? cmp : (int) (a_length - b_length); - } return my_strnncoll(field_charset, (const uchar*)ptr,a_length, (const uchar*)b, b_length); @@ -4093,7 +4084,7 @@ int Field_varstring::store(double nr) int width=min(field_length,DBL_DIG+5); sprintf(buff,"%-*.*g",width,max(width-5,0),nr); end=strcend(buff,' '); - return Field_varstring::store(buff,(uint) (end - buff), my_charset_latin1); + return Field_varstring::store(buff,(uint) (end - buff), my_charset_bin); } @@ -4230,11 +4221,6 @@ int Field_varstring::pack_cmp(const char *a, const char *b, uint key_length) a_length= (uint) (uchar) *a++; b_length= (uint) (uchar) *b++; } - if (binary()) - { - int cmp= memcmp(a,b,min(a_length,b_length)); - return cmp ? cmp : (int) (a_length - b_length); - } return my_strnncoll(field_charset, (const uchar *)a,a_length, (const uchar *)b,b_length); @@ -4253,11 +4239,6 @@ int Field_varstring::pack_cmp(const char *b, uint key_length) { b_length= (uint) (uchar) *b++; } - if (binary()) - { - int cmp= memcmp(a,b,min(a_length,b_length)); - return cmp ? cmp : (int) (a_length - b_length); - } return my_strnncoll(field_charset, (const uchar *)a,a_length, (const uchar *)b,b_length); @@ -4276,7 +4257,7 @@ uint Field_varstring::max_packed_col_length(uint max_length) return (max_length > 255 ? 2 : 1)+max_length; } -void Field_varstring::get_key_image(char *buff, uint length, imagetype type) +void Field_varstring::get_key_image(char *buff, uint length, CHARSET_INFO *cs,imagetype type) { length-= HA_KEY_BLOB_LENGTH; uint f_length=uint2korr(ptr); @@ -4290,10 +4271,10 @@ void Field_varstring::get_key_image(char *buff, uint length, imagetype type) #endif } -void Field_varstring::set_key_image(char *buff,uint length) +void Field_varstring::set_key_image(char *buff,uint length, CHARSET_INFO *cs) { length=uint2korr(buff); // Real length is here - (void) Field_varstring::store(buff+2, length, default_charset_info); + (void) Field_varstring::store(buff+2, length, cs); } @@ -4439,22 +4420,23 @@ int Field_blob::store(const char *from,uint len,CHARSET_INFO *cs) int Field_blob::store(double nr) { - value.set(nr,2,current_thd->variables.thd_charset); - return Field_blob::store(value.ptr(),(uint) value.length(), value.charset()); + CHARSET_INFO *cs=charset(); + value.set(nr, 2, cs); + return Field_blob::store(value.ptr(),(uint) value.length(), cs); } int Field_blob::store(longlong nr) { - value.set(nr,current_thd->variables.thd_charset); - return Field_blob::store(value.ptr(), (uint) value.length(), value.charset()); + CHARSET_INFO *cs=charset(); + value.set(nr, cs); + return Field_blob::store(value.ptr(), (uint) value.length(), cs); } double Field_blob::val_real(void) { char *blob; - memcpy_fixed(&blob,ptr+packlength,sizeof(char*)); if (!blob) return 0.0; @@ -4471,8 +4453,7 @@ longlong Field_blob::val_int(void) if (!blob) return 0; uint32 length=get_length(ptr); - CHARSET_INFO *cs=charset(); - return my_strntoll(cs,blob,length,NULL,10); + return my_strntoll(charset(),blob,length,NULL,10); } @@ -4482,9 +4463,9 @@ String *Field_blob::val_str(String *val_buffer __attribute__((unused)), char *blob; memcpy_fixed(&blob,ptr+packlength,sizeof(char*)); if (!blob) - val_ptr->set("",0,field_charset); // A bit safer than ->length(0) + val_ptr->set("",0,charset()); // A bit safer than ->length(0) else - val_ptr->set((const char*) blob,get_length(ptr),field_charset); + val_ptr->set((const char*) blob,get_length(ptr),charset()); return val_ptr; } @@ -4542,7 +4523,8 @@ int Field_blob::cmp_binary(const char *a_ptr, const char *b_ptr, /* The following is used only when comparing a key */ -void Field_blob::get_key_image(char *buff,uint length, imagetype type) +void Field_blob::get_key_image(char *buff,uint length, + CHARSET_INFO *cs,imagetype type) { length-= HA_KEY_BLOB_LENGTH; uint32 blob_length= get_length(ptr); @@ -4567,9 +4549,11 @@ void Field_blob::get_key_image(char *buff,uint length, imagetype type) if ((uint32) length > blob_length) { -#ifdef HAVE_purify + /* + Must clear this as we do a memcmp in opt_range.cc to detect + identical keys + */ bzero(buff+2+blob_length, (length-blob_length)); -#endif length=(uint) blob_length; } int2store(buff,length); @@ -4577,14 +4561,14 @@ void Field_blob::get_key_image(char *buff,uint length, imagetype type) memcpy(buff+2,blob,length); } -void Field_blob::set_key_image(char *buff,uint length) +void Field_blob::set_key_image(char *buff,uint length, CHARSET_INFO *cs) { length=uint2korr(buff); - (void) Field_blob::store(buff+2,length, default_charset_info); + (void) Field_blob::store(buff+2,length,cs); } -void Field_geom::get_key_image(char *buff,uint length, imagetype type) +void Field_geom::get_key_image(char *buff,uint length,CHARSET_INFO *cs, imagetype type) { length-=HA_KEY_BLOB_LENGTH; ulong blob_length=get_length(ptr); @@ -4603,7 +4587,7 @@ void Field_geom::get_key_image(char *buff,uint length, imagetype type) return; } -void Field_geom::set_key_image(char *buff,uint length) +void Field_geom::set_key_image(char *buff,uint length,CHARSET_INFO *cs) { Field_blob::set_key_image(buff, length); } @@ -4673,22 +4657,26 @@ void Field_blob::sort_string(char *to,uint length) void Field_blob::sql_type(String &res) const { - CHARSET_INFO *cs=res.charset(); const char *str; - uint len; + uint length; switch (packlength) { - default: str="tiny"; break; - case 2: str=""; break; - case 3: str="medium"; break; - case 4: str="long"; break; + default: str="tiny"; length=4; break; + case 2: str=""; length=0; break; + case 3: str="medium"; length= 6; break; + case 4: str="long"; length=4; break; + } + res.set_latin1(str,length); + if (binary()) + res.append("blob"); + else + { + res.append("text"); + if (field_charset != table->table_charset) + { + res.append(" character set "); + res.append(field_charset->csname); + } } - - len=cs->snprintf(cs,(char*)res.ptr(),res.alloced_length(),"%s%s%s%s", - str, - binary() ? "blob" : "text", - binary() ? "" : " character set ", - binary() ? "" : field_charset->name); - res.length(len); } @@ -4744,11 +4732,6 @@ int Field_blob::pack_cmp(const char *a, const char *b, uint key_length) a_length= (uint) (uchar) *a++; b_length= (uint) (uchar) *b++; } - if (binary()) - { - int cmp= memcmp(a,b,min(a_length,b_length)); - return cmp ? cmp : (int) (a_length - b_length); - } return my_strnncoll(field_charset, (const uchar *)a,a_length, (const uchar *)b,b_length); @@ -4772,11 +4755,6 @@ int Field_blob::pack_cmp(const char *b, uint key_length) { b_length= (uint) (uchar) *b++; } - if (binary()) - { - int cmp= memcmp(a,b,min(a_length,b_length)); - return cmp ? cmp : (int) (a_length - b_length); - } return my_strnncoll(field_charset, (const uchar *)a,a_length, (const uchar *)b,b_length); @@ -5430,8 +5408,7 @@ create_field::create_field(Field *old_field,Field *orig_field) orig_field) { char buff[MAX_FIELD_WIDTH],*pos; - CHARSET_INFO *field_charset= charset; - String tmp(buff,sizeof(buff),field_charset); + String tmp(buff,sizeof(buff), charset); /* Get the value from record[2] (the default value row) */ my_ptrdiff_t diff= (my_ptrdiff_t) (orig_field->table->rec_buff_length*2); @@ -5443,7 +5420,7 @@ create_field::create_field(Field *old_field,Field *orig_field) { pos= (char*) sql_memdup(tmp.ptr(),tmp.length()+1); pos[tmp.length()]=0; - def=new Item_string(pos,tmp.length(),field_charset); + def=new Item_string(pos,tmp.length(), charset); } } } |