Drizzled Public API Documentation

double.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 MySQL
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; either version 2 of the License, or
00009  *  (at your option) any later version.
00010  *
00011  *  This program is distributed in the hope that it will be useful,
00012  *  but WITHOUT ANY WARRANTY; without even the implied warranty of
00013  *  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
00014  *  GNU General Public License for more details.
00015  *
00016  *  You should have received a copy of the GNU General Public License
00017  *  along with this program; if not, write to the Free Software
00018  *  Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA  02110-1301  USA
00019  */
00020 
00021 
00022 #include <config.h>
00023 
00024 #include <float.h>
00025 #include <math.h>
00026 
00027 #include <algorithm>
00028 
00029 #include <drizzled/field/double.h>
00030 #include <drizzled/error.h>
00031 #include <drizzled/table.h>
00032 #include <drizzled/session.h>
00033 #include <drizzled/current_session.h>
00034 #include <drizzled/internal/m_string.h>
00035 
00036 using namespace std;
00037 
00038 namespace drizzled
00039 {
00040 
00041 /****************************************************************************
00042   double precision floating point numbers
00043 ****************************************************************************/
00044 
00045 int Field_double::store(const char *from,uint32_t len, const CHARSET_INFO * const cs)
00046 {
00047   int error;
00048   char *end;
00049   double nr= my_strntod(cs,(char*) from, len, &end, &error);
00050 
00051   ASSERT_COLUMN_MARKED_FOR_WRITE;
00052   if (error || (!len || (((uint32_t) (end-from) != len) && getTable()->in_use->count_cuted_fields)))
00053   {
00054     set_warning(DRIZZLE_ERROR::WARN_LEVEL_WARN,
00055                 (error ? ER_WARN_DATA_OUT_OF_RANGE : ER_WARN_DATA_TRUNCATED), 1);
00056     error= error ? 1 : 2;
00057   }
00058   Field_double::store(nr);
00059   return error;
00060 }
00061 
00062 
00063 int Field_double::store(double nr)
00064 {
00065   int error= truncate(&nr, DBL_MAX);
00066 
00067   ASSERT_COLUMN_MARKED_FOR_WRITE;
00068 
00069 #ifdef WORDS_BIGENDIAN
00070   if (getTable()->getShare()->db_low_byte_first)
00071   {
00072     float8store(ptr,nr);
00073   }
00074   else
00075 #endif
00076     doublestore(ptr,nr);
00077   return error;
00078 }
00079 
00080 
00081 int Field_double::store(int64_t nr, bool unsigned_val)
00082 {
00083   return Field_double::store(unsigned_val ? uint64_t2double((uint64_t) nr) :
00084                              (double) nr);
00085 }
00086 
00087 double Field_double::val_real(void) const
00088 {
00089   double j;
00090 
00091   ASSERT_COLUMN_MARKED_FOR_READ;
00092 
00093 #ifdef WORDS_BIGENDIAN
00094   if (getTable()->getShare()->db_low_byte_first)
00095   {
00096     float8get(j,ptr);
00097   }
00098   else
00099 #endif
00100     doubleget(j,ptr);
00101   return j;
00102 }
00103 
00104 int64_t Field_double::val_int(void) const
00105 {
00106   double j;
00107   int64_t res;
00108 
00109   ASSERT_COLUMN_MARKED_FOR_READ;
00110 
00111 #ifdef WORDS_BIGENDIAN
00112   if (getTable()->getShare()->db_low_byte_first)
00113   {
00114     float8get(j,ptr);
00115   }
00116   else
00117 #endif
00118     doubleget(j,ptr);
00119   /* Check whether we fit into int64_t range */
00120   if (j <= (double) INT64_MIN)
00121   {
00122     res= (int64_t) INT64_MIN;
00123     goto warn;
00124   }
00125   if (j >= (double) (uint64_t) INT64_MAX)
00126   {
00127     res= (int64_t) INT64_MAX;
00128     goto warn;
00129   }
00130   return (int64_t) rint(j);
00131 
00132 warn:
00133   {
00134     char buf[DOUBLE_TO_STRING_CONVERSION_BUFFER_SIZE];
00135     String tmp(buf, sizeof(buf), &my_charset_utf8_general_ci), *str;
00136     str= val_str(&tmp, &tmp);
00137     Session *session= getTable() ? getTable()->in_use : current_session;
00138     push_warning_printf(session, DRIZZLE_ERROR::WARN_LEVEL_WARN,
00139                         ER_TRUNCATED_WRONG_VALUE,
00140                         ER(ER_TRUNCATED_WRONG_VALUE), "INTEGER",
00141                         str->c_ptr());
00142   }
00143   return res;
00144 }
00145 
00146 
00147 String *Field_double::val_str(String *val_buffer, String *) const
00148 {
00149   double nr;
00150 
00151   ASSERT_COLUMN_MARKED_FOR_READ;
00152 
00153 #ifdef WORDS_BIGENDIAN
00154   if (getTable()->getShare()->db_low_byte_first)
00155   {
00156     float8get(nr,ptr);
00157   }
00158   else
00159 #endif
00160     doubleget(nr,ptr);
00161 
00162   uint32_t to_length= max(field_length, (uint32_t)DOUBLE_TO_STRING_CONVERSION_BUFFER_SIZE);
00163   val_buffer->alloc(to_length);
00164   char *to=(char*) val_buffer->ptr();
00165   size_t len;
00166 
00167   if (dec >= NOT_FIXED_DEC)
00168     len= internal::my_gcvt(nr, internal::MY_GCVT_ARG_DOUBLE, to_length - 1, to, NULL);
00169   else
00170     len= internal::my_fcvt(nr, dec, to, NULL);
00171 
00172   val_buffer->length((uint32_t) len);
00173 
00174   return val_buffer;
00175 }
00176 
00177 int Field_double::cmp(const unsigned char *a_ptr, const unsigned char *b_ptr)
00178 {
00179   double a,b;
00180 #ifdef WORDS_BIGENDIAN
00181   if (getTable()->getShare()->db_low_byte_first)
00182   {
00183     float8get(a,a_ptr);
00184     float8get(b,b_ptr);
00185   }
00186   else
00187 #endif
00188   {
00189     doubleget(a, a_ptr);
00190     doubleget(b, b_ptr);
00191   }
00192   return (a < b) ? -1 : (a > b) ? 1 : 0;
00193 }
00194 
00195 
00196 /* The following should work for IEEE */
00197 
00198 void Field_double::sort_string(unsigned char *to,uint32_t )
00199 {
00200   double nr;
00201 #ifdef WORDS_BIGENDIAN
00202   if (getTable()->getShare()->db_low_byte_first)
00203   {
00204     float8get(nr,ptr);
00205   }
00206   else
00207 #endif
00208     doubleget(nr,ptr);
00209   change_double_for_sort(nr, to);
00210 }
00211 
00212 
00213 void Field_double::sql_type(String &res) const
00214 {
00215   const CHARSET_INFO * const cs=res.charset();
00216   if (dec == NOT_FIXED_DEC)
00217   {
00218     res.set_ascii(STRING_WITH_LEN("double"));
00219   }
00220   else
00221   {
00222     res.length(cs->cset->snprintf(cs,(char*) res.ptr(),res.alloced_length(),
00223           "double(%d,%d)",(int) field_length,dec));
00224   }
00225 }
00226 
00227 } /* namespace drizzled */