summaryrefslogtreecommitdiff
path: root/sql/item_strfunc.cc
diff options
context:
space:
mode:
authorAlexander Nozdrin <alik@sun.com>2009-12-11 12:39:38 +0300
committerAlexander Nozdrin <alik@sun.com>2009-12-11 12:39:38 +0300
commit567671368723c704d60902b4d0ccff951b414552 (patch)
tree965519a5b0af3f33624c7e16fd61b58d15f42372 /sql/item_strfunc.cc
parentefee0608316e4cc034a3e62d05980eef8530843d (diff)
parentceefe7bb50b17b72e88851e3b98642e89a4cddae (diff)
downloadmariadb-git-567671368723c704d60902b4d0ccff951b414552.tar.gz
Manual merge from mysql-trunk.
Conflicts: - client/mysqltest.cc - mysql-test/collections/default.experimental - mysql-test/suite/rpl/t/disabled.def - sql/mysqld.cc - sql/opt_range.cc - sql/sp.cc - sql/sql_acl.cc - sql/sql_partition.cc - sql/sql_table.cc
Diffstat (limited to 'sql/item_strfunc.cc')
-rw-r--r--sql/item_strfunc.cc112
1 files changed, 74 insertions, 38 deletions
diff --git a/sql/item_strfunc.cc b/sql/item_strfunc.cc
index 183a628f8e4..86a892a9dcc 100644
--- a/sql/item_strfunc.cc
+++ b/sql/item_strfunc.cc
@@ -528,11 +528,11 @@ String *Item_func_des_encrypt::val_str(String *str)
return &tmp_value;
error:
- push_warning_printf(current_thd,MYSQL_ERROR::WARN_LEVEL_ERROR,
+ push_warning_printf(current_thd,MYSQL_ERROR::WARN_LEVEL_WARN,
code, ER(code),
"des_encrypt");
#else
- push_warning_printf(current_thd,MYSQL_ERROR::WARN_LEVEL_ERROR,
+ push_warning_printf(current_thd,MYSQL_ERROR::WARN_LEVEL_WARN,
ER_FEATURE_DISABLED, ER(ER_FEATURE_DISABLED),
"des_encrypt","--with-openssl");
#endif /* HAVE_OPENSSL */
@@ -605,12 +605,12 @@ String *Item_func_des_decrypt::val_str(String *str)
return &tmp_value;
error:
- push_warning_printf(current_thd,MYSQL_ERROR::WARN_LEVEL_ERROR,
+ push_warning_printf(current_thd,MYSQL_ERROR::WARN_LEVEL_WARN,
code, ER(code),
"des_decrypt");
wrong_key:
#else
- push_warning_printf(current_thd,MYSQL_ERROR::WARN_LEVEL_ERROR,
+ push_warning_printf(current_thd,MYSQL_ERROR::WARN_LEVEL_WARN,
ER_FEATURE_DISABLED, ER(ER_FEATURE_DISABLED),
"des_decrypt","--with-openssl");
#endif /* HAVE_OPENSSL */
@@ -2041,9 +2041,22 @@ String *Item_func_soundex::val_str(String *str)
const int FORMAT_MAX_DECIMALS= 30;
-Item_func_format::Item_func_format(Item *org, Item *dec)
-: Item_str_func(org, dec)
+
+MY_LOCALE *Item_func_format::get_locale(Item *item)
{
+ DBUG_ASSERT(arg_count == 3);
+ String tmp, *locale_name= args[2]->val_str(&tmp);
+ MY_LOCALE *lc;
+ if (!locale_name ||
+ !(lc= my_locale_by_name(locale_name->c_ptr_safe())))
+ {
+ push_warning_printf(current_thd, MYSQL_ERROR::WARN_LEVEL_WARN,
+ ER_UNKNOWN_LOCALE,
+ ER(ER_UNKNOWN_LOCALE),
+ locale_name ? locale_name->c_ptr_safe() : "NULL");
+ lc= &my_locale_en_US;
+ }
+ return lc;
}
void Item_func_format::fix_length_and_dec()
@@ -2053,6 +2066,10 @@ void Item_func_format::fix_length_and_dec()
collation.set(default_charset());
max_length= (char_length + max_sep_count + decimals) *
collation.collation->mbmaxlen;
+ if (arg_count == 3)
+ locale= args[2]->basic_const_item() ? get_locale(args[2]) : NULL;
+ else
+ locale= &my_locale_en_US; /* Two arguments */
}
@@ -2064,13 +2081,12 @@ void Item_func_format::fix_length_and_dec()
String *Item_func_format::val_str(String *str)
{
- uint32 length;
uint32 str_length;
/* Number of decimal digits */
int dec;
/* Number of characters used to represent the decimals, including '.' */
uint32 dec_length;
- int diff;
+ MY_LOCALE *lc;
DBUG_ASSERT(fixed == 1);
dec= (int) args[1]->val_int();
@@ -2080,6 +2096,8 @@ String *Item_func_format::val_str(String *str)
return NULL;
}
+ lc= locale ? locale : get_locale(args[2]);
+
dec= set_zone(dec, 0, FORMAT_MAX_DECIMALS);
dec_length= dec ? dec+1 : 0;
null_value=0;
@@ -2094,8 +2112,6 @@ String *Item_func_format::val_str(String *str)
my_decimal_round(E_DEC_FATAL_ERROR, res, dec, false, &rnd_dec);
my_decimal2string(E_DEC_FATAL_ERROR, &rnd_dec, 0, 0, 0, str);
str_length= str->length();
- if (rnd_dec.sign())
- str_length--;
}
else
{
@@ -2108,31 +2124,51 @@ String *Item_func_format::val_str(String *str)
if (isnan(nr))
return str;
str_length=str->length();
- if (nr < 0)
- str_length--; // Don't count sign
- }
- /* We need this test to handle 'nan' values */
- if (str_length >= dec_length+4)
- {
- char *tmp,*pos;
- length= str->length()+(diff=((int)(str_length- dec_length-1))/3);
- str= copy_if_not_alloced(&tmp_str,str,length);
- str->length(length);
- tmp= (char*) str->ptr()+length - dec_length-1;
- for (pos= (char*) str->ptr()+length-1; pos != tmp; pos--)
- pos[0]= pos[-diff];
- while (diff)
+ }
+ /* We need this test to handle 'nan' and short values */
+ if (lc->grouping[0] > 0 &&
+ str_length >= dec_length + 1 + lc->grouping[0])
+ {
+ char buf[DECIMAL_MAX_STR_LENGTH * 2]; /* 2 - in the worst case when grouping=1 */
+ int count;
+ const char *grouping= lc->grouping;
+ char sign_length= *str->ptr() == '-' ? 1 : 0;
+ const char *src= str->ptr() + str_length - dec_length - 1;
+ const char *src_begin= str->ptr() + sign_length;
+ char *dst= buf + sizeof(buf);
+
+ /* Put the fractional part */
+ if (dec)
+ {
+ dst-= (dec + 1);
+ *dst= lc->decimal_point;
+ memcpy(dst + 1, src + 2, dec);
+ }
+
+ /* Put the integer part with grouping */
+ for (count= *grouping; src >= src_begin; count--)
{
- *pos= *(pos - diff);
- pos--;
- *pos= *(pos - diff);
- pos--;
- *pos= *(pos - diff);
- pos--;
- pos[0]=',';
- pos--;
- diff--;
+ /*
+ When *grouping==0x80 (which means "end of grouping")
+ count will be initialized to -1 and
+ we'll never get into this "if" anymore.
+ */
+ if (!count)
+ {
+ *--dst= lc->thousand_sep;
+ if (grouping[1])
+ grouping++;
+ count= *grouping;
+ }
+ DBUG_ASSERT(dst > buf);
+ *--dst= *src--;
}
+
+ if (sign_length) /* Put '-' */
+ *--dst= *str->ptr();
+
+ /* Put the rest of the integer part without grouping */
+ str->copy(dst, buf + sizeof(buf) - dst, &my_charset_latin1);
}
return str;
}
@@ -3238,7 +3274,7 @@ longlong Item_func_uncompressed_length::val_int()
*/
if (res->length() <= 4)
{
- push_warning_printf(current_thd, MYSQL_ERROR::WARN_LEVEL_ERROR,
+ push_warning_printf(current_thd, MYSQL_ERROR::WARN_LEVEL_WARN,
ER_ZLIB_Z_DATA_ERROR,
ER(ER_ZLIB_Z_DATA_ERROR));
null_value= 1;
@@ -3315,7 +3351,7 @@ String *Item_func_compress::val_str(String *str)
(const Bytef*)res->ptr(), res->length())) != Z_OK)
{
code= err==Z_MEM_ERROR ? ER_ZLIB_Z_MEM_ERROR : ER_ZLIB_Z_BUF_ERROR;
- push_warning(current_thd,MYSQL_ERROR::WARN_LEVEL_ERROR,code,ER(code));
+ push_warning(current_thd,MYSQL_ERROR::WARN_LEVEL_WARN,code,ER(code));
null_value= 1;
return 0;
}
@@ -3353,7 +3389,7 @@ String *Item_func_uncompress::val_str(String *str)
/* If length is less than 4 bytes, data is corrupt */
if (res->length() <= 4)
{
- push_warning_printf(current_thd,MYSQL_ERROR::WARN_LEVEL_ERROR,
+ push_warning_printf(current_thd,MYSQL_ERROR::WARN_LEVEL_WARN,
ER_ZLIB_Z_DATA_ERROR,
ER(ER_ZLIB_Z_DATA_ERROR));
goto err;
@@ -3363,7 +3399,7 @@ String *Item_func_uncompress::val_str(String *str)
new_size= uint4korr(res->ptr()) & 0x3FFFFFFF;
if (new_size > current_thd->variables.max_allowed_packet)
{
- push_warning_printf(current_thd,MYSQL_ERROR::WARN_LEVEL_ERROR,
+ push_warning_printf(current_thd,MYSQL_ERROR::WARN_LEVEL_WARN,
ER_TOO_BIG_FOR_UNCOMPRESS,
ER(ER_TOO_BIG_FOR_UNCOMPRESS),
current_thd->variables.max_allowed_packet);
@@ -3381,7 +3417,7 @@ String *Item_func_uncompress::val_str(String *str)
code= ((err == Z_BUF_ERROR) ? ER_ZLIB_Z_BUF_ERROR :
((err == Z_MEM_ERROR) ? ER_ZLIB_Z_MEM_ERROR : ER_ZLIB_Z_DATA_ERROR));
- push_warning(current_thd,MYSQL_ERROR::WARN_LEVEL_ERROR,code,ER(code));
+ push_warning(current_thd,MYSQL_ERROR::WARN_LEVEL_WARN,code,ER(code));
err:
null_value= 1;