My Project
my_decimal.h
Go to the documentation of this file.
00001 /* Copyright (c) 2005, 2011, Oracle and/or its affiliates. All rights reserved.
00002 
00003    This program is free software; you can redistribute it and/or modify
00004    it under the terms of the GNU General Public License as published by
00005    the Free Software Foundation; version 2 of the License.
00006 
00007    This program is distributed in the hope that it will be useful,
00008    but WITHOUT ANY WARRANTY; without even the implied warranty of
00009    MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
00010    GNU General Public License for more details.
00011 
00012    You should have received a copy of the GNU General Public License
00013    along with this program; if not, write to the Free Software
00014    Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301  USA */
00015 
00028 #ifndef my_decimal_h
00029 #define my_decimal_h
00030 
00031 #if defined(MYSQL_SERVER) || defined(EMBEDDED_LIBRARY)
00032 #include "sql_string.h"                         /* String */
00033 #endif
00034 
00035 C_MODE_START
00036 #include <decimal.h>
00037 C_MODE_END
00038 
00039 class String;
00040 typedef struct st_mysql_time MYSQL_TIME;
00041 
00042 #define DECIMAL_LONGLONG_DIGITS 22
00043 #define DECIMAL_LONG_DIGITS 10
00044 #define DECIMAL_LONG3_DIGITS 8
00045 
00047 #define DECIMAL_BUFF_LENGTH 9
00048 
00049 /* the number of digits that my_decimal can possibly contain */
00050 #define DECIMAL_MAX_POSSIBLE_PRECISION (DECIMAL_BUFF_LENGTH * 9)
00051 
00052 
00059 #define DECIMAL_MAX_PRECISION (DECIMAL_MAX_POSSIBLE_PRECISION - 8*2)
00060 #define DECIMAL_MAX_SCALE 30
00061 #define DECIMAL_NOT_SPECIFIED 31
00062 
00067 #define DECIMAL_MAX_STR_LENGTH (DECIMAL_MAX_POSSIBLE_PRECISION + 2)
00068 
00072 #define DECIMAL_MAX_FIELD_SIZE DECIMAL_MAX_PRECISION
00073 
00074 
00075 inline uint my_decimal_size(uint precision, uint scale)
00076 {
00077   /*
00078     Always allocate more space to allow library to put decimal point
00079     where it want
00080   */
00081   return decimal_size(precision, scale) + 1;
00082 }
00083 
00084 
00085 inline int my_decimal_int_part(uint precision, uint decimals)
00086 {
00087   return precision - ((decimals == DECIMAL_NOT_SPECIFIED) ? 0 : decimals);
00088 }
00089 
00090 
00099 class my_decimal :public decimal_t
00100 {
00101   /*
00102     Several of the routines in strings/decimal.c have had buffer
00103     overrun/underrun problems. These are *not* caught by valgrind.
00104     To catch them, we allocate dummy fields around the buffer,
00105     and test that their values do not change.
00106    */
00107 #if !defined(DBUG_OFF)
00108   int foo1;
00109 #endif
00110 
00111   decimal_digit_t buffer[DECIMAL_BUFF_LENGTH];
00112 
00113 #if !defined(DBUG_OFF)
00114   int foo2;
00115   static const int test_value= 123;
00116 #endif
00117 
00118 public:
00119 
00120   my_decimal(const my_decimal &rhs) : decimal_t(rhs)
00121   {
00122 #if !defined(DBUG_OFF)
00123     foo1= test_value;
00124     foo2= test_value;
00125 #endif
00126     for (uint i= 0; i < DECIMAL_BUFF_LENGTH; i++)
00127       buffer[i]= rhs.buffer[i];
00128     fix_buffer_pointer();
00129   }
00130 
00131   my_decimal& operator=(const my_decimal &rhs)
00132   {
00133 #if !defined(DBUG_OFF)
00134     foo1= test_value;
00135     foo2= test_value;
00136 #endif
00137     if (this == &rhs)
00138       return *this;
00139     decimal_t::operator=(rhs);
00140     for (uint i= 0; i < DECIMAL_BUFF_LENGTH; i++)
00141       buffer[i]= rhs.buffer[i];
00142     fix_buffer_pointer();
00143     return *this;
00144   }
00145 
00146   void init()
00147   {
00148 #if !defined(DBUG_OFF)
00149     foo1= test_value;
00150     foo2= test_value;
00151 #endif
00152     len= DECIMAL_BUFF_LENGTH;
00153     buf= buffer;
00154   }
00155 
00156   my_decimal()
00157   {
00158     init();
00159   }
00160   ~my_decimal()
00161   {
00162     sanity_check();
00163   }
00164 
00165   void sanity_check()
00166   {
00167     DBUG_ASSERT(foo1 == test_value);
00168     DBUG_ASSERT(foo2 == test_value);
00169   }
00170 
00171   void fix_buffer_pointer() { buf= buffer; }
00172 
00173   bool sign() const { return decimal_t::sign; }
00174   void sign(bool s) { decimal_t::sign= s; }
00175   uint precision() const { return intg + frac; }
00176 
00178   void swap(my_decimal &rhs)
00179   {
00180     swap_variables(my_decimal, *this, rhs);
00181   }
00182 };
00183 
00184 
00185 #ifndef DBUG_OFF
00186 void print_decimal(const my_decimal *dec);
00187 void print_decimal_buff(const my_decimal *dec, const uchar* ptr, int length);
00188 const char *dbug_decimal_as_string(char *buff, const my_decimal *val);
00189 #else
00190 #define dbug_decimal_as_string(A) NULL
00191 #endif
00192 
00193 bool str_set_decimal(uint mask, const my_decimal *val, uint fixed_prec,
00194                      uint fixed_dec, char filler, String *str,
00195                      const CHARSET_INFO *cs);
00196 
00197 extern my_decimal decimal_zero;
00198 
00199 #ifndef MYSQL_CLIENT
00200 int decimal_operation_results(int result);
00201 #else
00202 inline int decimal_operation_results(int result)
00203 {
00204   return result;
00205 }
00206 #endif /*MYSQL_CLIENT*/
00207 
00208 inline
00209 void max_my_decimal(my_decimal *to, int precision, int frac)
00210 {
00211   DBUG_ASSERT((precision <= DECIMAL_MAX_PRECISION)&&
00212               (frac <= DECIMAL_MAX_SCALE));
00213   max_decimal(precision, frac, to);
00214 }
00215 
00216 inline void max_internal_decimal(my_decimal *to)
00217 {
00218   max_my_decimal(to, DECIMAL_MAX_PRECISION, 0);
00219 }
00220 
00221 inline int check_result(uint mask, int result)
00222 {
00223   if (result & mask)
00224     decimal_operation_results(result);
00225   return result;
00226 }
00227 
00228 inline int check_result_and_overflow(uint mask, int result, my_decimal *val)
00229 {
00230   if (check_result(mask, result) & E_DEC_OVERFLOW)
00231   {
00232     bool sign= val->sign();
00233     val->fix_buffer_pointer();
00234     max_internal_decimal(val);
00235     val->sign(sign);
00236   }
00237   return result;
00238 }
00239 
00240 inline uint my_decimal_length_to_precision(uint length, uint scale,
00241                                            bool unsigned_flag)
00242 {
00243   /* Precision can't be negative thus ignore unsigned_flag when length is 0. */
00244   DBUG_ASSERT(length || !scale);
00245   return (uint) (length - (scale>0 ? 1:0) -
00246                  (unsigned_flag || !length ? 0:1));
00247 }
00248 
00249 inline uint32 my_decimal_precision_to_length_no_truncation(uint precision,
00250                                                            uint8 scale,
00251                                                            bool unsigned_flag)
00252 {
00253   /*
00254     When precision is 0 it means that original length was also 0. Thus
00255     unsigned_flag is ignored in this case.
00256   */
00257   DBUG_ASSERT(precision || !scale);
00258   return (uint32)(precision + (scale > 0 ? 1 : 0) +
00259                   (unsigned_flag || !precision ? 0 : 1));
00260 }
00261 
00262 inline uint32 my_decimal_precision_to_length(uint precision, uint8 scale,
00263                                              bool unsigned_flag)
00264 {
00265   /*
00266     When precision is 0 it means that original length was also 0. Thus
00267     unsigned_flag is ignored in this case.
00268   */
00269   DBUG_ASSERT(precision || !scale);
00270   set_if_smaller(precision, DECIMAL_MAX_PRECISION);
00271   return my_decimal_precision_to_length_no_truncation(precision, scale,
00272                                                       unsigned_flag);
00273 }
00274 
00275 inline
00276 int my_decimal_string_length(const my_decimal *d)
00277 {
00278   /* length of string representation including terminating '\0' */
00279   return decimal_string_size(d);
00280 }
00281 
00282 
00283 inline
00284 int my_decimal_max_length(const my_decimal *d)
00285 {
00286   /* -1 because we do not count \0 */
00287   return decimal_string_size(d) - 1;
00288 }
00289 
00290 
00291 inline
00292 int my_decimal_get_binary_size(uint precision, uint scale)
00293 {
00294   return decimal_bin_size((int)precision, (int)scale);
00295 }
00296 
00297 
00298 inline
00299 void my_decimal2decimal(const my_decimal *from, my_decimal *to)
00300 {
00301   *to= *from;
00302 }
00303 
00304 
00305 int my_decimal2binary(uint mask, const my_decimal *d, uchar *bin, int prec,
00306                       int scale);
00307 
00308 
00309 inline
00310 int binary2my_decimal(uint mask, const uchar *bin, my_decimal *d, int prec,
00311                       int scale)
00312 {
00313   return check_result(mask, bin2decimal(bin, d, prec, scale));
00314 }
00315 
00316 
00317 inline
00318 int my_decimal_set_zero(my_decimal *d)
00319 {
00320   /*
00321     We need the up-cast here, since my_decimal has sign() member functions,
00322     which conflicts with decimal_t::size
00323     (and decimal_make_zero is a macro, rather than a funcion).
00324   */
00325   decimal_make_zero(static_cast<decimal_t*>(d));
00326   return 0;
00327 }
00328 
00329 
00330 inline
00331 bool my_decimal_is_zero(const my_decimal *decimal_value)
00332 {
00333   return decimal_is_zero(decimal_value);
00334 }
00335 
00336 
00337 inline
00338 int my_decimal_round(uint mask, const my_decimal *from, int scale,
00339                      bool truncate, my_decimal *to)
00340 {
00341   return check_result(mask, decimal_round(from, to, scale,
00342                                           (truncate ? TRUNCATE : HALF_UP)));
00343 }
00344 
00345 
00346 inline
00347 int my_decimal_floor(uint mask, const my_decimal *from, my_decimal *to)
00348 {
00349   return check_result(mask, decimal_round(from, to, 0, FLOOR));
00350 }
00351 
00352 
00353 inline
00354 int my_decimal_ceiling(uint mask, const my_decimal *from, my_decimal *to)
00355 {
00356   return check_result(mask, decimal_round(from, to, 0, CEILING));
00357 }
00358 
00359 
00360 inline bool str_set_decimal(const my_decimal *val, String *str,
00361                             const CHARSET_INFO *cs)
00362 {
00363   return str_set_decimal(E_DEC_FATAL_ERROR, val, 0, 0, 0, str, cs);
00364 }
00365 
00366 #ifndef MYSQL_CLIENT
00367 class String;
00368 int my_decimal2string(uint mask, const my_decimal *d, uint fixed_prec,
00369                       uint fixed_dec, char filler, String *str);
00370 #endif
00371 
00372 inline
00373 int my_decimal2int(uint mask, const my_decimal *d, my_bool unsigned_flag,
00374                    longlong *l)
00375 {
00376   my_decimal rounded;
00377   /* decimal_round can return only E_DEC_TRUNCATED */
00378   decimal_round(d, &rounded, 0, HALF_UP);
00379   return check_result(mask, (unsigned_flag ?
00380                              decimal2ulonglong(&rounded, (ulonglong *)l) :
00381                              decimal2longlong(&rounded, l)));
00382 }
00383 
00384 
00385 inline
00386 int my_decimal2double(uint, const my_decimal *d, double *result)
00387 {
00388   /* No need to call check_result as this will always succeed */
00389   return decimal2double(d, result);
00390 }
00391 
00392 
00393 inline int my_decimal2lldiv_t(uint mask, const my_decimal *d, lldiv_t *to)
00394 {
00395   return check_result(mask, decimal2lldiv_t(d, to));
00396 }
00397 
00398 
00399 inline int str2my_decimal(uint mask, const char *str,
00400                           my_decimal *d, char **end)
00401 {
00402   return check_result_and_overflow(mask, string2decimal(str, d, end), d);
00403 }
00404 
00405 
00406 int str2my_decimal(uint mask, const char *from, uint length,
00407                    const CHARSET_INFO *charset, my_decimal *decimal_value);
00408 
00409 #if defined(MYSQL_SERVER) || defined(EMBEDDED_LIBRARY)
00410 inline
00411 int string2my_decimal(uint mask, const String *str, my_decimal *d)
00412 {
00413   return str2my_decimal(mask, str->ptr(), str->length(), str->charset(), d);
00414 }
00415 
00416 
00417 my_decimal *date2my_decimal(const MYSQL_TIME *ltime, my_decimal *dec);
00418 my_decimal *time2my_decimal(const MYSQL_TIME *ltime, my_decimal *dec);
00419 my_decimal *timeval2my_decimal(const struct timeval *tm, my_decimal *dec);
00420 
00421 #endif /*defined(MYSQL_SERVER) || defined(EMBEDDED_LIBRARY) */
00422 
00423 inline
00424 int double2my_decimal(uint mask, double val, my_decimal *d)
00425 {
00426   return check_result_and_overflow(mask, double2decimal(val, d), d);
00427 }
00428 
00429 
00430 inline
00431 int int2my_decimal(uint mask, longlong i, my_bool unsigned_flag, my_decimal *d)
00432 {
00433   return check_result(mask, (unsigned_flag ?
00434                              ulonglong2decimal((ulonglong)i, d) :
00435                              longlong2decimal(i, d)));
00436 }
00437 
00438 
00439 inline
00440 void my_decimal_neg(decimal_t *arg)
00441 {
00442   if (decimal_is_zero(arg))
00443   {
00444     arg->sign= 0;
00445     return;
00446   }
00447   decimal_neg(arg);
00448 }
00449 
00450 
00451 inline
00452 int my_decimal_add(uint mask, my_decimal *res, const my_decimal *a,
00453                    const my_decimal *b)
00454 {
00455   return check_result_and_overflow(mask,
00456                                    decimal_add(a, b, res),
00457                                    res);
00458 }
00459 
00460 
00461 inline
00462 int my_decimal_sub(uint mask, my_decimal *res, const my_decimal *a,
00463                    const my_decimal *b)
00464 {
00465   return check_result_and_overflow(mask,
00466                                    decimal_sub(a, b, res),
00467                                    res);
00468 }
00469 
00470 
00471 inline
00472 int my_decimal_mul(uint mask, my_decimal *res, const my_decimal *a,
00473                    const my_decimal *b)
00474 {
00475   return check_result_and_overflow(mask,
00476                                    decimal_mul(a, b, res),
00477                                    res);
00478 }
00479 
00480 
00481 inline
00482 int my_decimal_div(uint mask, my_decimal *res, const my_decimal *a,
00483                    const my_decimal *b, int div_scale_inc)
00484 {
00485   return check_result_and_overflow(mask,
00486                                    decimal_div(a, b, res, div_scale_inc),
00487                                    res);
00488 }
00489 
00490 
00491 inline
00492 int my_decimal_mod(uint mask, my_decimal *res, const my_decimal *a,
00493                    const my_decimal *b)
00494 {
00495   return check_result_and_overflow(mask,
00496                                    decimal_mod(a, b, res),
00497                                    res);
00498 }
00499 
00500 
00505 inline
00506 int my_decimal_cmp(const my_decimal *a, const my_decimal *b)
00507 {
00508   return decimal_cmp(a, b);
00509 }
00510 
00511 
00512 inline
00513 int my_decimal_intg(const my_decimal *a)
00514 {
00515   return decimal_intg(a);
00516 }
00517 
00518 
00519 void my_decimal_trim(ulong *precision, uint *scale);
00520 
00521 
00522 #endif /*my_decimal_h*/
00523 
 All Classes Namespaces Files Functions Variables Typedefs Enumerations Enumerator Friends Defines