00001
00002
00003
00004
00005
00006
00007
00008
00009
00010
00011
00012
00013
00014
00015
00016
00017
00018
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
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
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
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 }