summaryrefslogtreecommitdiff
path: root/sql
diff options
context:
space:
mode:
authorunknown <monty@mashka.mysql.fi>2003-01-14 14:28:36 +0200
committerunknown <monty@mashka.mysql.fi>2003-01-14 14:28:36 +0200
commit910c125bb6528b08f7c30b7b75650076b7b953fe (patch)
tree7a63ba29620ada893aa14d1984554e0af0a0deaa /sql
parent91f18f0a26e3714bd9edc78b1c6fe7a1fd243167 (diff)
downloadmariadb-git-910c125bb6528b08f7c30b7b75650076b7b953fe.tar.gz
Updates for multi-byte character sets
(Note: test 'union' fails, but Sanja promised to fix this) include/m_ctype.h: Changed prototype for strntod() to inform the user that source may be modified. include/m_string.h: Moved my_vsnprintf to strings library include/my_sys.h: Moved my_vsnprintf to strings library libmysql/Makefile.shared: Moved my_vsnprintf to strings library mysql-test/r/alter_table.result: Moved my_vsnprintf to strings library mysql-test/r/create.result: Moved my_vsnprintf to strings library mysql-test/r/ctype_many.result: Moved my_vsnprintf to strings library mysql-test/r/fulltext.result: Moved my_vsnprintf to strings library mysql-test/r/innodb.result: Moved my_vsnprintf to strings library mysql-test/r/merge.result: Moved my_vsnprintf to strings library mysql-test/r/select.result: Moved my_vsnprintf to strings library mysql-test/r/show_check.result: Moved my_vsnprintf to strings library mysql-test/r/type_blob.result: Moved my_vsnprintf to strings library mysql-test/r/type_enum.result: Moved my_vsnprintf to strings library mysql-test/r/type_ranges.result: Moved my_vsnprintf to strings library mysql-test/r/type_set.result: Moved my_vsnprintf to strings library mysys/Makefile.am: Moved my_vsnprintf to strings library sql/field.cc: Fixed for character set handling sql/field.h: Fixed for character set handling sql/item.cc: Fixed for character set handling sql/item.h: Fixed for character set handling sql/item_func.cc: Fixed for character set handling sql/item_func.h: Fixed for character set handling sql/item_strfunc.cc: Fixed for character set handling sql/item_sum.cc: Fixed for character set handling sql/item_sum.h: Fixed for character set handling sql/item_timefunc.cc: Fixed for character set handling sql/mysqld.cc: Update to use new test_if_int() sql/opt_range.cc: Fixed for character set handling sql/procedure.h: Fixed for character set handling sql/sql_class.cc: Fixed for character set handling sql/sql_string.cc: Added multi byte support to append. Added set_latin1() sql/sql_string.h: Added set_latin1() sql/sql_update.cc: Cosmetic changes strings/Makefile.am: Moved my_vsnprintf to strings library strings/ctype-simple.c: Code review + cleanup strings/ctype-utf8.c: Fixed strntod() strings/my_vsnprintf.c: Added support for %#d and %#u
Diffstat (limited to 'sql')
-rw-r--r--sql/field.cc406
-rw-r--r--sql/field.h5
-rw-r--r--sql/item.cc17
-rw-r--r--sql/item.h8
-rw-r--r--sql/item_func.cc8
-rw-r--r--sql/item_func.h2
-rw-r--r--sql/item_strfunc.cc3
-rw-r--r--sql/item_sum.cc3
-rw-r--r--sql/item_sum.h3
-rw-r--r--sql/item_timefunc.cc2
-rw-r--r--sql/mysqld.cc7
-rw-r--r--sql/opt_range.cc2
-rw-r--r--sql/procedure.h5
-rw-r--r--sql/sql_class.cc6
-rw-r--r--sql/sql_string.cc152
-rw-r--r--sql/sql_string.h1
-rw-r--r--sql/sql_update.cc1
17 files changed, 350 insertions, 281 deletions
diff --git a/sql/field.cc b/sql/field.cc
index 21330a2ffaa..f81f72635b9 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->csname);
- 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++;
@@ -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)
@@ -2854,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;
@@ -2995,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);
}
@@ -3125,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)))
{
@@ -3189,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);
}
/****************************************************************************
@@ -3202,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)
{
@@ -3210,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)
{
@@ -3287,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));
}
@@ -3375,6 +3356,7 @@ int Field_date::store(longlong nr)
return error;
}
+
bool Field_date::send_binary(Protocol *protocol)
{
longlong tmp= Field_date::val_int();
@@ -3469,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);
}
/****************************************************************************
@@ -3639,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);
}
@@ -3872,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);
}
/****************************************************************************
@@ -3929,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);
}
@@ -4118,7 +4094,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);
}
@@ -4464,22 +4440,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;
@@ -4496,8 +4473,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);
}
@@ -4507,9 +4483,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;
}
@@ -4567,7 +4543,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, CHARSET_INFO *cs,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);
@@ -4695,22 +4672,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);
}
@@ -5452,8 +5433,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);
@@ -5465,7 +5445,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);
}
}
}
diff --git a/sql/field.h b/sql/field.h
index 67bae7302f9..06a9b534b16 100644
--- a/sql/field.h
+++ b/sql/field.h
@@ -133,7 +133,9 @@ public:
tmp->unireg_check=Field::NONE;
tmp->flags&= (NOT_NULL_FLAG | BLOB_FLAG | UNSIGNED_FLAG |
ZEROFILL_FLAG | BINARY_FLAG | ENUM_FLAG | SET_FLAG);
+#ifdef PROBABLY_WRONG
tmp->table_name= new_table->table_name;
+#endif
tmp->reset_fields();
}
return tmp;
@@ -1094,7 +1096,8 @@ bool set_field_to_null(Field *field);
bool set_field_to_null_with_conversions(Field *field, bool no_conversions);
uint find_enum(TYPELIB *typelib,const char *x, uint length);
ulonglong find_set(TYPELIB *typelib,const char *x, uint length);
-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);
/*
The following are for the interface with the .frm file
diff --git a/sql/item.cc b/sql/item.cc
index b0b56bf9101..925ee9ac0f4 100644
--- a/sql/item.cc
+++ b/sql/item.cc
@@ -116,7 +116,7 @@ bool Item_string::eq(const Item *item, bool binary_cmp) const
bool Item::get_date(TIME *ltime,bool fuzzydate)
{
char buff[40];
- String tmp(buff,sizeof(buff),NULL),*res;
+ String tmp(buff,sizeof(buff), my_charset_bin),*res;
if (!(res=val_str(&tmp)) ||
str_to_TIME(res->ptr(),res->length(),ltime,fuzzydate) == TIMESTAMP_NONE)
{
@@ -134,7 +134,7 @@ bool Item::get_date(TIME *ltime,bool fuzzydate)
bool Item::get_time(TIME *ltime)
{
char buff[40];
- String tmp(buff,sizeof(buff),NULL),*res;
+ String tmp(buff,sizeof(buff),my_charset_bin),*res;
if (!(res=val_str(&tmp)) ||
str_to_time(res->ptr(),res->length(),ltime))
{
@@ -380,7 +380,8 @@ double Item_param::val()
{
switch (item_result_type) {
case STRING_RESULT:
- return (double)my_strntod(str_value.charset(),str_value.ptr(),str_value.length(),(char**)0);
+ return (double) my_strntod(str_value.charset(), (char*) str_value.ptr(),
+ str_value.length(), (char**) 0);
case INT_RESULT:
return (double)int_value;
default:
@@ -1149,7 +1150,7 @@ Item *resolve_const_item(Item *item,Item *comp_item)
if (res_type == STRING_RESULT)
{
char buff[MAX_FIELD_WIDTH];
- String tmp(buff,sizeof(buff),NULL),*result;
+ String tmp(buff,sizeof(buff),my_charset_bin),*result;
result=item->val_str(&tmp);
if (item->null_value)
{
@@ -1204,8 +1205,8 @@ bool field_is_equal_to_item(Field *field,Item *item)
{
char item_buff[MAX_FIELD_WIDTH];
char field_buff[MAX_FIELD_WIDTH];
- String item_tmp(item_buff,sizeof(item_buff),NULL),*item_result;
- String field_tmp(field_buff,sizeof(field_buff),NULL);
+ String item_tmp(item_buff,sizeof(item_buff),my_charset_bin),*item_result;
+ String field_tmp(field_buff,sizeof(field_buff),my_charset_bin);
item_result=item->val_str(&item_tmp);
if (item->null_value)
return 1; // This must be true
@@ -1263,8 +1264,8 @@ void Item_cache_str::store(Item *item)
double Item_cache_str::val()
{
if (value)
- return my_strntod(value->charset(), value->ptr(),
- value->length(), (char**)0);
+ return my_strntod(value->charset(), (char*) value->ptr(),
+ value->length(), (char**) 0);
else
return (double)0;
}
diff --git a/sql/item.h b/sql/item.h
index 3decdc388eb..907c293d454 100644
--- a/sql/item.h
+++ b/sql/item.h
@@ -344,7 +344,7 @@ public:
enum Type type() const { return STRING_ITEM; }
double val()
{
- return my_strntod(str_value.charset(), str_value.ptr(),
+ return my_strntod(str_value.charset(), (char*) str_value.ptr(),
str_value.length(), (char**) 0);
}
longlong val_int()
@@ -598,7 +598,11 @@ public:
enum Item_result result_type () const { return STRING_RESULT; }
enum_field_types field_type() const { return cached_field_type; }
double val()
- { return null_value ? 0.0 : my_strntod(str_value.charset(),str_value.ptr(),str_value.length(),NULL); }
+ {
+ return (null_value ? 0.0 :
+ my_strntod(str_value.charset(), (char*) str_value.ptr(),
+ str_value.length(),NULL));
+ }
longlong val_int()
{ return null_value ? LL(0) : my_strntoll(str_value.charset(),str_value.ptr(),str_value.length(),(char**) 0,10); }
String *val_str(String*);
diff --git a/sql/item_func.cc b/sql/item_func.cc
index dcf4638c48a..62cf4c0d291 100644
--- a/sql/item_func.cc
+++ b/sql/item_func.cc
@@ -1893,7 +1893,7 @@ longlong Item_func_set_last_insert_id::val_int()
longlong Item_func_benchmark::val_int()
{
char buff[MAX_FIELD_WIDTH];
- String tmp(buff,sizeof(buff), NULL);
+ String tmp(buff,sizeof(buff), my_charset_bin);
THD *thd=current_thd;
for (ulong loop=0 ; loop < loop_count && !thd->killed; loop++)
@@ -2039,7 +2039,7 @@ Item_func_set_user_var::update()
case STRING_RESULT:
{
char buffer[MAX_FIELD_WIDTH];
- String tmp(buffer,sizeof(buffer),NULL);
+ String tmp(buffer,sizeof(buffer),my_charset_bin);
(void) val_str(&tmp);
break;
}
@@ -2234,7 +2234,7 @@ longlong Item_func_inet_aton::val_int()
char c = '.'; // we mark c to indicate invalid IP in case length is 0
char buff[36];
- String *s,tmp(buff,sizeof(buff),NULL);
+ String *s,tmp(buff,sizeof(buff),my_charset_bin);
if (!(s = args[0]->val_str(&tmp))) // If null value
goto err;
null_value=0;
@@ -2288,7 +2288,7 @@ void Item_func_match::init_search(bool no_order)
String *ft_tmp= 0;
char tmp1[FT_QUERY_MAXLEN];
- String tmp2(tmp1,sizeof(tmp1),NULL);
+ String tmp2(tmp1,sizeof(tmp1),default_charset_info);
// MATCH ... AGAINST (NULL) is meaningless, but possible
if (!(ft_tmp=key_item()->val_str(&tmp2)))
diff --git a/sql/item_func.h b/sql/item_func.h
index bf64412cab3..11793b11bdb 100644
--- a/sql/item_func.h
+++ b/sql/item_func.h
@@ -813,7 +813,7 @@ public:
double val()
{
String *res; res=val_str(&str_value);
- return res ? my_strntod(res->charset(),res->ptr(),res->length(),0) : 0.0;
+ return res ? my_strntod(res->charset(),(char*) res->ptr(),res->length(),0) : 0.0;
}
longlong val_int()
{
diff --git a/sql/item_strfunc.cc b/sql/item_strfunc.cc
index 7818a23fcd8..2292c6115a0 100644
--- a/sql/item_strfunc.cc
+++ b/sql/item_strfunc.cc
@@ -54,7 +54,8 @@ double Item_str_func::val()
{
String *res;
res=val_str(&str_value);
- return res ? my_strntod(res->charset(),res->ptr(),res->length(),NULL) : 0.0;
+ return res ? my_strntod(res->charset(), (char*) res->ptr(),res->length(),
+ NULL) : 0.0;
}
longlong Item_str_func::val_int()
diff --git a/sql/item_sum.cc b/sql/item_sum.cc
index d78e535010f..b15fceda686 100644
--- a/sql/item_sum.cc
+++ b/sql/item_sum.cc
@@ -341,7 +341,8 @@ double Item_sum_hybrid::val()
switch (hybrid_type) {
case STRING_RESULT:
String *res; res=val_str(&str_value);
- return res ? my_strntod(res->charset(),res->ptr(),res->length(),(char**)0) : 0.0;
+ return (res ? my_strntod(res->charset(), (char*) res->ptr(),res->length(),
+ (char**) 0) : 0.0);
case INT_RESULT:
if (unsigned_flag)
return ulonglong2double(sum_int);
diff --git a/sql/item_sum.h b/sql/item_sum.h
index d16a1f2224e..ffc9558822d 100644
--- a/sql/item_sum.h
+++ b/sql/item_sum.h
@@ -484,7 +484,8 @@ public:
double val()
{
String *res; res=val_str(&str_value);
- return res ? my_strntod(res->charset(),res->ptr(),res->length(),(char**) 0) : 0.0;
+ return res ? my_strntod(res->charset(),(char*) res->ptr(),res->length(),
+ (char**) 0) : 0.0;
}
longlong val_int()
{
diff --git a/sql/item_timefunc.cc b/sql/item_timefunc.cc
index 796070acb8a..744c0c1fa49 100644
--- a/sql/item_timefunc.cc
+++ b/sql/item_timefunc.cc
@@ -529,7 +529,7 @@ void Item_func_now::fix_length_and_dec()
{
struct tm tm_tmp,*start;
time_t query_start=current_thd->query_start();
- CHARSET_INFO *cs=thd_charset();
+ CHARSET_INFO *cs=my_charset_bin;
decimals=0;
max_length=19*cs->mbmaxlen;
diff --git a/sql/mysqld.cc b/sql/mysqld.cc
index f66122e72a6..27c7fb369a1 100644
--- a/sql/mysqld.cc
+++ b/sql/mysqld.cc
@@ -4665,8 +4665,11 @@ get_one_option(int optid, const struct my_option *opt __attribute__((unused)),
berkeley_lock_type=berkeley_lock_types[type-1];
else
{
- if (test_if_int(argument,(uint) strlen(argument), my_charset_latin1))
- berkeley_lock_scan_time=atoi(argument);
+ char *end;
+ uint length= strlen(argument);
+ long value= my_strntol(my_charset_latin1, argument, length, &end, 10);
+ if (test_if_int(argument,(uint) length, end, my_charset_latin1))
+ berkeley_lock_scan_time= value;
else
{
fprintf(stderr,"Unknown lock type: %s\n",argument);
diff --git a/sql/opt_range.cc b/sql/opt_range.cc
index 0adde4d39e0..43066a29624 100644
--- a/sql/opt_range.cc
+++ b/sql/opt_range.cc
@@ -2796,7 +2796,7 @@ static void
print_key(KEY_PART *key_part,const char *key,uint used_length)
{
char buff[1024];
- String tmp(buff,sizeof(buff),NULL);
+ String tmp(buff,sizeof(buff),my_charset_bin);
for (uint length=0;
length < used_length ;
diff --git a/sql/procedure.h b/sql/procedure.h
index bc1b6062e1d..bc77803230f 100644
--- a/sql/procedure.h
+++ b/sql/procedure.h
@@ -59,7 +59,7 @@ public:
void set(double nr) { value=nr; }
void set(longlong nr) { value=(double) nr; }
void set(const char *str,uint length,CHARSET_INFO *cs)
- { value=my_strntod(cs,str,length,(char**)0); }
+ { value=my_strntod(cs,(char*) str,length,(char**)0); }
double val() { return value; }
longlong val_int() { return (longlong) value; }
String *val_str(String *s) { s->set(value,decimals,thd_charset()); return s; }
@@ -99,7 +99,8 @@ public:
double val()
{
CHARSET_INFO *cs=str_value.charset();
- return my_strntod(cs, str_value.ptr(), str_value.length(),(char**)0);
+ return my_strntod(cs, (char*) str_value.ptr(), str_value.length(),
+ (char**) 0);
}
longlong val_int()
{
diff --git a/sql/sql_class.cc b/sql/sql_class.cc
index ab789370660..4416f5259bd 100644
--- a/sql/sql_class.cc
+++ b/sql/sql_class.cc
@@ -526,7 +526,7 @@ bool select_send::send_data(List<Item> &items)
List_iterator_fast<Item> li(items);
Protocol *protocol= thd->protocol;
char buff[MAX_FIELD_WIDTH];
- String buffer(buff, sizeof(buff), NULL);
+ String buffer(buff, sizeof(buff), my_charset_bin);
DBUG_ENTER("send_data");
protocol->prepare_for_resend();
@@ -649,7 +649,7 @@ bool select_export::send_data(List<Item> &items)
DBUG_ENTER("send_data");
char buff[MAX_FIELD_WIDTH],null_buff[2],space[MAX_FIELD_WIDTH];
bool space_inited=0;
- String tmp(buff,sizeof(buff),NULL),*res;
+ String tmp(buff,sizeof(buff),my_charset_bin),*res;
tmp.length(0);
if (unit->offset_limit_cnt)
@@ -857,7 +857,7 @@ bool select_dump::send_data(List<Item> &items)
{
List_iterator_fast<Item> li(items);
char buff[MAX_FIELD_WIDTH];
- String tmp(buff,sizeof(buff),NULL),*res;
+ String tmp(buff,sizeof(buff),my_charset_bin),*res;
tmp.length(0);
Item *item;
DBUG_ENTER("send_data");
diff --git a/sql/sql_string.cc b/sql/sql_string.cc
index 5b84b86c277..4c499af8f9e 100644
--- a/sql/sql_string.cc
+++ b/sql/sql_string.cc
@@ -30,6 +30,9 @@
extern gptr sql_alloc(unsigned size);
extern void sql_element_free(void *ptr);
+static uint32
+copy_and_convert(char *to, uint32 to_length, CHARSET_INFO *to_cs,
+ const char *from, uint32 from_length, CHARSET_INFO *from_cs);
#include "sql_string.h"
@@ -223,55 +226,51 @@ bool String::copy(const char *str,uint32 arg_length, CHARSET_INFO *cs)
return FALSE;
}
-/* Copy with charset convertion */
-bool String::copy(const char *str,uint32 arg_length, CHARSET_INFO *from, CHARSET_INFO *to)
-{
- uint32 new_length=to->mbmaxlen*arg_length;
- int cnvres;
- my_wc_t wc;
- const uchar *s=(const uchar *)str;
- const uchar *se=s+arg_length;
- uchar *d, *de;
+ /* Copy with charset convertion */
+bool String::copy(const char *str, uint32 arg_length,
+ CHARSET_INFO *from_cs, CHARSET_INFO *to_cs)
+{
+ uint32 new_length= to_cs->mbmaxlen*arg_length;
if (alloc(new_length))
return TRUE;
+ str_length=copy_and_convert((char*) Ptr, new_length, to_cs,
+ str, arg_length, from_cs);
+ str_charset=to_cs;
+ return FALSE;
+}
- d=(uchar *)Ptr;
- de=d+new_length;
+
+/*
+ Set a string to the value of a latin1-string, keeping the original charset
- for (str_length=new_length ; s < se && d < de ; )
- {
- if ((cnvres=from->mb_wc(from,&wc,s,se)) > 0 )
- {
- s+=cnvres;
- }
- else if (cnvres==MY_CS_ILSEQ)
- {
- s++;
- wc='?';
- }
- else
- break;
+ SYNOPSIS
+ copy_or_set()
+ str String of a simple charset (latin1)
+ arg_length Length of string
-outp:
- if ((cnvres=to->wc_mb(to,wc,d,de)) >0 )
- {
- d+=cnvres;
- }
- else if (cnvres==MY_CS_ILUNI && wc!='?')
- {
- wc='?';
- goto outp;
- }
- else
- break;
+ IMPLEMENTATION
+ If string object is of a simple character set, set it to point to the
+ given string.
+ If not, make a copy and convert it to the new character set.
+
+ RETURN
+ 0 ok
+ 1 Could not allocate result buffer
+
+*/
+
+bool String::set_latin1(const char *str, uint32 arg_length)
+{
+ if (str_charset->mbmaxlen == 1)
+ {
+ set(str, arg_length, str_charset);
+ return 0;
}
- Ptr[new_length]=0;
- length((uint32) (d-(uchar *)Ptr));
- str_charset=to;
- return FALSE;
+ return copy(str, arg_length, my_charset_latin1, str_charset);
}
+
/* This is used by mysql.cc */
bool String::fill(uint32 max_length,char fill_char)
@@ -306,11 +305,26 @@ bool String::append(const String &s)
return FALSE;
}
+
+/*
+ Append a latin1 string to the a string of the current character set
+*/
+
+
bool String::append(const char *s,uint32 arg_length)
{
if (!arg_length) // Default argument
if (!(arg_length= (uint32) strlen(s)))
return FALSE;
+ if (str_charset->mbmaxlen > 1)
+ {
+ uint32 add_length=arg_length * str_charset->mbmaxlen;
+ if (realloc(str_length+ add_length))
+ return TRUE;
+ str_length+= copy_and_convert(Ptr+str_length, add_length, str_charset,
+ s, arg_length, my_charset_latin1);
+ return FALSE;
+ }
if (realloc(str_length+arg_length))
return TRUE;
memcpy(Ptr+str_length,s,arg_length);
@@ -318,6 +332,7 @@ bool String::append(const char *s,uint32 arg_length)
return FALSE;
}
+
#ifdef TO_BE_REMOVED
bool String::append(FILE* file, uint32 arg_length, myf my_flags)
{
@@ -658,4 +673,61 @@ String *copy_if_not_alloced(String *to,String *from,uint32 from_length)
}
+/****************************************************************************
+ Help functions
+****************************************************************************/
+
+/*
+ copy a string from one character set to another
+
+ SYNOPSIS
+ copy_and_convert()
+ to Store result here
+ to_cs Character set of result string
+ from Copy from here
+ from_length Length of from string
+ from_cs From character set
+
+ NOTES
+ 'to' must be big enough as form_length * to_cs->mbmaxlen
+
+ RETURN
+ length of bytes copied to 'to'
+*/
+
+static uint32
+copy_and_convert(char *to, uint32 to_length, CHARSET_INFO *to_cs,
+ const char *from, uint32 from_length, CHARSET_INFO *from_cs)
+{
+ int cnvres;
+ my_wc_t wc;
+ const uchar *from_end= (const uchar*) from+from_length;
+ char *to_start= to;
+ uchar *to_end= (uchar*) to+to_length;
+
+ while ((uchar*) from < from_end)
+ {
+ if ((cnvres=from_cs->mb_wc(from_cs, &wc, (uchar*) from, from_end)) > 0)
+ from+= cnvres;
+ else if (cnvres == MY_CS_ILSEQ)
+ {
+ from++;
+ wc= '?';
+ }
+ else
+ break; // Impossible char.
+
+outp:
+ if ((cnvres= to_cs->wc_mb(to_cs, wc, (uchar*) to, to_end)) > 0)
+ to+= cnvres;
+ else if (cnvres == MY_CS_ILUNI && wc != '?')
+ {
+ wc= '?';
+ goto outp;
+ }
+ else
+ break;
+ }
+ return (uint32) (to - to_start);
+}
diff --git a/sql/sql_string.h b/sql/sql_string.h
index afcc3d74530..ad91b20f18c 100644
--- a/sql/sql_string.h
+++ b/sql/sql_string.h
@@ -115,6 +115,7 @@ public:
Ptr=(char*) str; str_length=arg_length; Alloced_length=0 ; alloced=0;
str_charset=cs;
}
+ bool String::set_latin1(const char *str, uint32 arg_length);
inline void set_quick(char *str,uint32 arg_length, CHARSET_INFO *cs)
{
if (!alloced)
diff --git a/sql/sql_update.cc b/sql/sql_update.cc
index bf98ab7f7cb..3aae6f6f411 100644
--- a/sql/sql_update.cc
+++ b/sql/sql_update.cc
@@ -233,6 +233,7 @@ int mysql_update(THD *thd,
}
}
end_read_record(&info);
+
if (table->key_read)
{
table->key_read=0;