Drizzled Public API Documentation

decimal.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 #include <drizzled/field/decimal.h>
00024 #include <drizzled/error.h>
00025 #include <drizzled/table.h>
00026 #include <drizzled/session.h>
00027 
00028 namespace drizzled
00029 {
00030 
00031 /****************************************************************************
00032  ** File_decimal
00033  ****************************************************************************/
00034 
00035 Field_decimal::Field_decimal(unsigned char *ptr_arg,
00036                              uint32_t len_arg,
00037                              unsigned char *null_ptr_arg,
00038                              unsigned char null_bit_arg,
00039                              enum utype unireg_check_arg,
00040                              const char *field_name_arg,
00041                              uint8_t dec_arg) :
00042   Field_num(ptr_arg,
00043             len_arg,
00044             null_ptr_arg,
00045             null_bit_arg,
00046             unireg_check_arg,
00047             field_name_arg,
00048             dec_arg, false,
00049             false)
00050   {
00051     precision= class_decimal_length_to_precision(len_arg, dec_arg, false);
00052     set_if_smaller(precision, (uint32_t)DECIMAL_MAX_PRECISION);
00053     assert((precision <= DECIMAL_MAX_PRECISION) && (dec <= DECIMAL_MAX_SCALE));
00054     bin_size= class_decimal_get_binary_size(precision, dec);
00055   }
00056 
00057 Field_decimal::Field_decimal(uint32_t len_arg,
00058                              bool maybe_null_arg,
00059                              const char *name,
00060                              uint8_t dec_arg,
00061                              bool unsigned_arg) :
00062   Field_num((unsigned char*) 0,
00063             len_arg,
00064             maybe_null_arg ? (unsigned char*) "": 0,
00065             0,
00066             NONE,
00067             name,
00068             dec_arg,
00069             0,
00070             unsigned_arg)
00071 {
00072   precision= class_decimal_length_to_precision(len_arg, dec_arg, unsigned_arg);
00073   set_if_smaller(precision, (uint32_t)DECIMAL_MAX_PRECISION);
00074   assert((precision <= DECIMAL_MAX_PRECISION) &&
00075          (dec <= DECIMAL_MAX_SCALE));
00076   bin_size= class_decimal_get_binary_size(precision, dec);
00077 }
00078 
00079 
00080 int Field_decimal::reset(void)
00081 {
00082   store_value(&decimal_zero);
00083   return 0;
00084 }
00085 
00086 
00094 void Field_decimal::set_value_on_overflow(type::Decimal *decimal_value,
00095                                           bool sign)
00096 {
00097   max_Decimal(decimal_value, precision, decimals());
00098   if (sign)
00099     decimal_value->sign(true);
00100 
00101   return;
00102 }
00103 
00104 
00120 bool Field_decimal::store_value(const type::Decimal *decimal_value)
00121 {
00122   int error= decimal_value->val_binary(E_DEC_FATAL_ERROR & ~E_DEC_OVERFLOW, ptr, precision, dec);
00123 
00124   if (warn_if_overflow(error))
00125   {
00126     if (error != E_DEC_TRUNCATED)
00127     {
00128       type::Decimal buff;
00129       set_value_on_overflow(&buff, decimal_value->sign());
00130       buff.val_binary(E_DEC_FATAL_ERROR, ptr, precision, dec);
00131     }
00132     error= 1;
00133   }
00134 
00135   return(error);
00136 }
00137 
00138 
00139 int Field_decimal::store(const char *from, uint32_t length,
00140                          const CHARSET_INFO * const charset_arg)
00141 {
00142   int err;
00143   type::Decimal decimal_value;
00144 
00145   ASSERT_COLUMN_MARKED_FOR_WRITE;
00146 
00147   if ((err= decimal_value.store(E_DEC_FATAL_ERROR &
00148                            ~(E_DEC_OVERFLOW | E_DEC_BAD_NUM),
00149                            from, length, charset_arg)) &&
00150       getTable()->in_use->abortOnWarning())
00151   {
00152     /* Because "from" is not NUL-terminated and we use %s in the ER() */
00153     String from_as_str;
00154     from_as_str.copy(from, length, &my_charset_bin);
00155 
00156     push_warning_printf(getTable()->in_use, DRIZZLE_ERROR::WARN_LEVEL_ERROR,
00157                         ER_TRUNCATED_WRONG_VALUE_FOR_FIELD,
00158                         ER(ER_TRUNCATED_WRONG_VALUE_FOR_FIELD),
00159                         "decimal", from_as_str.c_ptr(), field_name,
00160                         (uint32_t) getTable()->in_use->row_count);
00161 
00162     return(err);
00163   }
00164 
00165   switch (err) {
00166   case E_DEC_TRUNCATED:
00167     set_warning(DRIZZLE_ERROR::WARN_LEVEL_WARN, ER_WARN_DATA_TRUNCATED, 1);
00168     set_value_on_overflow(&decimal_value, decimal_value.sign());
00169     break;
00170   case E_DEC_OVERFLOW:
00171     set_warning(DRIZZLE_ERROR::WARN_LEVEL_WARN, ER_WARN_DATA_OUT_OF_RANGE, 1);
00172     set_value_on_overflow(&decimal_value, decimal_value.sign());
00173     break;
00174   case E_DEC_BAD_NUM:
00175     {
00176       /* Because "from" is not NUL-terminated and we use %s in the ER() */
00177       String from_as_str;
00178       from_as_str.copy(from, length, &my_charset_bin);
00179 
00180       push_warning_printf(getTable()->in_use, DRIZZLE_ERROR::WARN_LEVEL_WARN,
00181                           ER_TRUNCATED_WRONG_VALUE_FOR_FIELD,
00182                           ER(ER_TRUNCATED_WRONG_VALUE_FOR_FIELD),
00183                           "decimal", from_as_str.c_ptr(), field_name,
00184                           (uint32_t) getTable()->in_use->row_count);
00185       decimal_value.set_zero();
00186 
00187       break;
00188     }
00189   }
00190 
00191   store_value(&decimal_value);
00192   return(err);
00193 }
00194 
00195 
00202 int Field_decimal::store(double nr)
00203 {
00204   type::Decimal decimal_value;
00205   int err;
00206 
00207   ASSERT_COLUMN_MARKED_FOR_WRITE;
00208 
00209   err= double2_class_decimal(E_DEC_FATAL_ERROR & ~E_DEC_OVERFLOW, nr,
00210                          &decimal_value);
00211   if (err)
00212   {
00213     if (check_overflow(err))
00214       set_value_on_overflow(&decimal_value, decimal_value.sign());
00215     /* Only issue a warning if store_value doesn't issue an warning */
00216     getTable()->in_use->got_warning= 0;
00217   }
00218   if (store_value(&decimal_value))
00219     err= 1;
00220   else if (err && !getTable()->in_use->got_warning)
00221     err= warn_if_overflow(err);
00222   return(err);
00223 }
00224 
00225 
00226 int Field_decimal::store(int64_t nr, bool unsigned_val)
00227 {
00228   type::Decimal decimal_value;
00229   int err;
00230 
00231   ASSERT_COLUMN_MARKED_FOR_WRITE;
00232 
00233   if ((err= int2_class_decimal(E_DEC_FATAL_ERROR & ~E_DEC_OVERFLOW,
00234                            nr, unsigned_val, &decimal_value)))
00235   {
00236     if (check_overflow(err))
00237       set_value_on_overflow(&decimal_value, decimal_value.sign());
00238     /* Only issue a warning if store_value doesn't issue an warning */
00239     getTable()->in_use->got_warning= 0;
00240   }
00241   if (store_value(&decimal_value))
00242     err= 1;
00243   else if (err && not getTable()->in_use->got_warning)
00244     err= warn_if_overflow(err);
00245   return err;
00246 }
00247 
00248 
00249 int Field_decimal::store_decimal(const type::Decimal *decimal_value)
00250 {
00251   return store_value(decimal_value);
00252 }
00253 
00254 
00255 int Field_decimal::store_time(type::Time &ltime,
00256                               type::timestamp_t )
00257 {
00258   type::Decimal decimal_value;
00259   return store_value(date2_class_decimal(&ltime, &decimal_value));
00260 }
00261 
00262 
00263 double Field_decimal::val_real(void) const
00264 {
00265   double dbl;
00266   type::Decimal decimal_value;
00267 
00268   ASSERT_COLUMN_MARKED_FOR_READ;
00269 
00270   class_decimal2double(E_DEC_FATAL_ERROR, val_decimal(&decimal_value), &dbl);
00271 
00272   return dbl;
00273 }
00274 
00275 
00276 int64_t Field_decimal::val_int(void) const
00277 {
00278   int64_t i;
00279   type::Decimal decimal_value;
00280 
00281   ASSERT_COLUMN_MARKED_FOR_READ;
00282 
00283   val_decimal(&decimal_value)->val_int32(E_DEC_FATAL_ERROR, false, &i);
00284 
00285   return i;
00286 }
00287 
00288 
00289 type::Decimal* Field_decimal::val_decimal(type::Decimal *decimal_value) const
00290 {
00291   ASSERT_COLUMN_MARKED_FOR_READ;
00292 
00293   binary2_class_decimal(E_DEC_FATAL_ERROR, ptr, decimal_value,
00294                     precision, dec);
00295   return(decimal_value);
00296 }
00297 
00298 
00299 String *Field_decimal::val_str(String *val_buffer, String *) const
00300 {
00301   type::Decimal decimal_value;
00302 
00303   ASSERT_COLUMN_MARKED_FOR_READ;
00304 
00305   class_decimal2string(val_decimal(&decimal_value),
00306                        dec, val_buffer);
00307   return val_buffer;
00308 }
00309 
00310 
00311 int Field_decimal::cmp(const unsigned char *a,const unsigned char*b)
00312 {
00313   return memcmp(a, b, bin_size);
00314 }
00315 
00316 
00317 void Field_decimal::sort_string(unsigned char *buff,
00318                                 uint32_t )
00319 {
00320   memcpy(buff, ptr, bin_size);
00321 }
00322 
00323 
00324 void Field_decimal::sql_type(String &str) const
00325 {
00326   const CHARSET_INFO * const cs= str.charset();
00327   str.length(cs->cset->snprintf(cs, (char*) str.ptr(), str.alloced_length(),
00328                                 "decimal(%d,%d)", precision, (int)dec));
00329 }
00330 
00331 
00344 uint32_t Field_decimal::pack_length_from_metadata(uint32_t field_metadata)
00345 {
00346   uint32_t const source_precision= (field_metadata >> 8U) & 0x00ff;
00347   uint32_t const source_decimal= field_metadata & 0x00ff;
00348   uint32_t const source_size= class_decimal_get_binary_size(source_precision,
00349                                                          source_decimal);
00350   return (source_size);
00351 }
00352 
00353 
00354 uint32_t Field_decimal::is_equal(CreateField *new_field_ptr)
00355 {
00356   return ((new_field_ptr->sql_type == real_type()) &&
00357           ((new_field_ptr->flags & UNSIGNED_FLAG) ==
00358            (uint32_t) (flags & UNSIGNED_FLAG)) &&
00359           ((new_field_ptr->flags & AUTO_INCREMENT_FLAG) ==
00360            (uint32_t) (flags & AUTO_INCREMENT_FLAG)) &&
00361           (new_field_ptr->length == max_display_length()) &&
00362           (new_field_ptr->decimals == dec));
00363 }
00364 
00365 
00378 const unsigned char *
00379 Field_decimal::unpack(unsigned char* to,
00380                       const unsigned char *from,
00381                       uint32_t param_data,
00382                       bool low_byte_first)
00383 {
00384   if (param_data == 0)
00385     return Field::unpack(to, from, param_data, low_byte_first);
00386 
00387   uint32_t from_precision= (param_data & 0xff00) >> 8U;
00388   uint32_t from_decimal= param_data & 0x00ff;
00389   uint32_t length=pack_length();
00390   uint32_t from_pack_len= class_decimal_get_binary_size(from_precision, from_decimal);
00391   uint32_t len= (param_data && (from_pack_len < length)) ?
00392     from_pack_len : length;
00393   if ((from_pack_len && (from_pack_len < length)) ||
00394       (from_precision < precision) ||
00395       (from_decimal < decimals()))
00396   {
00397     /*
00398       If the master's data is smaller than the slave, we need to convert
00399       the binary to decimal then resize the decimal converting it back to
00400       a decimal and write that to the raw data buffer.
00401     */
00402     decimal_digit_t dec_buf[DECIMAL_MAX_PRECISION];
00403     decimal_t conv_dec;
00404     conv_dec.len= from_precision;
00405     conv_dec.buf= dec_buf;
00406     /*
00407 Note: bin2decimal does not change the length of the field. So it is
00408 just the first step the resizing operation. The second step does the
00409 resizing using the precision and decimals from the slave.
00410     */
00411     bin2decimal((unsigned char *)from, &conv_dec, from_precision, from_decimal);
00412     decimal2bin(&conv_dec, to, precision, decimals());
00413   }
00414   else
00415     memcpy(to, from, len); // Sizes are the same, just copy the data.
00416   return from+len;
00417 }
00418 
00419 } /* namespace drizzled */