00001
00002
00003
00004
00005
00006
00007
00008
00009
00010
00011
00012
00013
00014
00015
00016
00017
00018
00019
00020 #include <config.h>
00021 #include "format.h"
00022
00023 #include <limits>
00024
00025 #include <drizzled/charset_info.h>
00026 #include <drizzled/type/decimal.h>
00027 #include <drizzled/table.h>
00028
00029 using namespace std;
00030
00031 namespace drizzled
00032 {
00033
00040 const int FORMAT_MAX_DECIMALS= 30;
00041
00042 void Item_func_format::fix_length_and_dec()
00043 {
00044 collation.set(default_charset());
00045 uint32_t char_length= args[0]->max_length/args[0]->collation.collation->mbmaxlen;
00046 max_length= ((char_length + (char_length-args[0]->decimals)/3) *
00047 collation.collation->mbmaxlen);
00048 }
00049
00050
00057 String *Item_func_format::val_str(String *str)
00058 {
00059 uint32_t length;
00060 uint32_t str_length;
00061
00062 int dec;
00063
00064 uint32_t dec_length;
00065 int diff;
00066 assert(fixed == 1);
00067
00068 dec= (int) args[1]->val_int();
00069 if (args[1]->null_value)
00070 {
00071 null_value=1;
00072 return NULL;
00073 }
00074
00075 dec= set_zone(dec, 0, FORMAT_MAX_DECIMALS);
00076 dec_length= dec ? dec+1 : 0;
00077 null_value=0;
00078
00079 if (args[0]->result_type() == DECIMAL_RESULT ||
00080 args[0]->result_type() == INT_RESULT)
00081 {
00082 type::Decimal dec_val, rnd_dec, *res;
00083 res= args[0]->val_decimal(&dec_val);
00084 if ((null_value=args[0]->null_value))
00085 return 0;
00086 class_decimal_round(E_DEC_FATAL_ERROR, res, dec, false, &rnd_dec);
00087 class_decimal2string(&rnd_dec, 0, str);
00088 str_length= str->length();
00089 if (rnd_dec.sign())
00090 str_length--;
00091 }
00092 else
00093 {
00094 double nr= args[0]->val_real();
00095 if ((null_value=args[0]->null_value))
00096 return 0;
00097 nr= my_double_round(nr, (int64_t) dec, false, false);
00098
00099 str->set_real(nr, dec, default_charset());
00100 if (nr == numeric_limits<double>::quiet_NaN())
00101 return str;
00102 str_length=str->length();
00103 if (nr < 0)
00104 str_length--;
00105 }
00106
00107 if (str_length >= dec_length+4)
00108 {
00109 char *tmp,*pos;
00110 length= str->length()+(diff=((int)(str_length- dec_length-1))/3);
00111 str= copy_if_not_alloced(&tmp_str,str,length);
00112 str->length(length);
00113 tmp= (char*) str->ptr()+length - dec_length-1;
00114 for (pos= (char*) str->ptr()+length-1; pos != tmp; pos--)
00115 pos[0]= pos[-diff];
00116 while (diff)
00117 {
00118 *pos= *(pos - diff);
00119 pos--;
00120 *pos= *(pos - diff);
00121 pos--;
00122 *pos= *(pos - diff);
00123 pos--;
00124 pos[0]=',';
00125 pos--;
00126 diff--;
00127 }
00128 }
00129 return str;
00130 }
00131
00132
00133 void Item_func_format::print(String *str)
00134 {
00135 str->append(STRING_WITH_LEN("format("));
00136 args[0]->print(str);
00137 str->append(',');
00138 args[1]->print(str);
00139 str->append(')');
00140 }
00141
00142 }