summaryrefslogtreecommitdiff
path: root/sql/field.cc
diff options
context:
space:
mode:
authorunknown <hf@deer.mysql.r18.ru>2003-01-15 13:15:35 +0400
committerunknown <hf@deer.mysql.r18.ru>2003-01-15 13:15:35 +0400
commit150a238f033c3e3f8d67dfaa7d1616237738c1cb (patch)
tree937beb6f27e5e7958081a4a5ba13ceb2f5251396 /sql/field.cc
parent09b79b65f225e7e7f66077f95b00e095cf454c3a (diff)
parent2d6f1c223d94fe874ac7acba089a1678f314dfac (diff)
downloadmariadb-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.cc491
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);
}
}
}