My Project
|
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