Drizzled Public API Documentation

format.cc

00001 /* -*- mode: c++; c-basic-offset: 2; indent-tabs-mode: nil; -*-
00002  *  vim:expandtab:shiftwidth=2:tabstop=2:smarttab:
00003  *
00004  *  Copyright (C) 2008 Sun Microsystems, Inc.
00005  *
00006  *  This program is free software; you can redistribute it and/or modify
00007  *  it under the terms of the GNU General Public License as published by
00008  *  the Free Software Foundation; version 2 of the License.
00009  *
00010  *  This program is distributed in the hope that it will be useful,
00011  *  but WITHOUT ANY WARRANTY; without even the implied warranty of
00012  *  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
00013  *  GNU General Public License for more details.
00014  *
00015  *  You should have received a copy of the GNU General Public License
00016  *  along with this program; if not, write to the Free Software
00017  *  Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA  02110-1301  USA
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   /* Number of decimal digits */
00062   int dec;
00063   /* Number of characters used to represent the decimals, including '.' */
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     /* Here default_charset() is right as this is not an automatic conversion */
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--;       // Don't count sign
00105   }
00106   /* We need this test to handle 'nan' values */
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 } /* namespace drizzled */