MySQL 5.6.14 Source Code Document
 All Classes Namespaces Files Functions Variables Typedefs Enumerations Enumerator Friends Macros Groups Pages
my_decimal.h
Go to the documentation of this file.
1 /* Copyright (c) 2005, 2011, Oracle and/or its affiliates. All rights reserved.
2 
3  This program is free software; you can redistribute it and/or modify
4  it under the terms of the GNU General Public License as published by
5  the Free Software Foundation; version 2 of the License.
6 
7  This program is distributed in the hope that it will be useful,
8  but WITHOUT ANY WARRANTY; without even the implied warranty of
9  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
10  GNU General Public License for more details.
11 
12  You should have received a copy of the GNU General Public License
13  along with this program; if not, write to the Free Software
14  Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA */
15 
28 #ifndef my_decimal_h
29 #define my_decimal_h
30 
31 #if defined(MYSQL_SERVER) || defined(EMBEDDED_LIBRARY)
32 #include "sql_string.h" /* String */
33 #endif
34 
35 C_MODE_START
36 #include <decimal.h>
37 C_MODE_END
38 
39 class String;
40 typedef struct st_mysql_time MYSQL_TIME;
41 
42 #define DECIMAL_LONGLONG_DIGITS 22
43 #define DECIMAL_LONG_DIGITS 10
44 #define DECIMAL_LONG3_DIGITS 8
45 
47 #define DECIMAL_BUFF_LENGTH 9
48 
49 /* the number of digits that my_decimal can possibly contain */
50 #define DECIMAL_MAX_POSSIBLE_PRECISION (DECIMAL_BUFF_LENGTH * 9)
51 
52 
59 #define DECIMAL_MAX_PRECISION (DECIMAL_MAX_POSSIBLE_PRECISION - 8*2)
60 #define DECIMAL_MAX_SCALE 30
61 #define DECIMAL_NOT_SPECIFIED 31
62 
67 #define DECIMAL_MAX_STR_LENGTH (DECIMAL_MAX_POSSIBLE_PRECISION + 2)
68 
72 #define DECIMAL_MAX_FIELD_SIZE DECIMAL_MAX_PRECISION
73 
74 
75 inline uint my_decimal_size(uint precision, uint scale)
76 {
77  /*
78  Always allocate more space to allow library to put decimal point
79  where it want
80  */
81  return decimal_size(precision, scale) + 1;
82 }
83 
84 
85 inline int my_decimal_int_part(uint precision, uint decimals)
86 {
87  return precision - ((decimals == DECIMAL_NOT_SPECIFIED) ? 0 : decimals);
88 }
89 
90 
99 class my_decimal :public decimal_t
100 {
101  /*
102  Several of the routines in strings/decimal.c have had buffer
103  overrun/underrun problems. These are *not* caught by valgrind.
104  To catch them, we allocate dummy fields around the buffer,
105  and test that their values do not change.
106  */
107 #if !defined(DBUG_OFF)
108  int foo1;
109 #endif
110 
111  decimal_digit_t buffer[DECIMAL_BUFF_LENGTH];
112 
113 #if !defined(DBUG_OFF)
114  int foo2;
115  static const int test_value= 123;
116 #endif
117 
118 public:
119 
120  my_decimal(const my_decimal &rhs) : decimal_t(rhs)
121  {
122 #if !defined(DBUG_OFF)
123  foo1= test_value;
124  foo2= test_value;
125 #endif
126  for (uint i= 0; i < DECIMAL_BUFF_LENGTH; i++)
127  buffer[i]= rhs.buffer[i];
128  fix_buffer_pointer();
129  }
130 
131  my_decimal& operator=(const my_decimal &rhs)
132  {
133 #if !defined(DBUG_OFF)
134  foo1= test_value;
135  foo2= test_value;
136 #endif
137  if (this == &rhs)
138  return *this;
139  decimal_t::operator=(rhs);
140  for (uint i= 0; i < DECIMAL_BUFF_LENGTH; i++)
141  buffer[i]= rhs.buffer[i];
142  fix_buffer_pointer();
143  return *this;
144  }
145 
146  void init()
147  {
148 #if !defined(DBUG_OFF)
149  foo1= test_value;
150  foo2= test_value;
151 #endif
152  len= DECIMAL_BUFF_LENGTH;
153  buf= buffer;
154  }
155 
156  my_decimal()
157  {
158  init();
159  }
160  ~my_decimal()
161  {
162  sanity_check();
163  }
164 
165  void sanity_check()
166  {
167  DBUG_ASSERT(foo1 == test_value);
168  DBUG_ASSERT(foo2 == test_value);
169  }
170 
171  void fix_buffer_pointer() { buf= buffer; }
172 
173  bool sign() const { return decimal_t::sign; }
174  void sign(bool s) { decimal_t::sign= s; }
175  uint precision() const { return intg + frac; }
176 
178  void swap(my_decimal &rhs)
179  {
180  swap_variables(my_decimal, *this, rhs);
181  }
182 };
183 
184 
185 #ifndef DBUG_OFF
186 void print_decimal(const my_decimal *dec);
187 void print_decimal_buff(const my_decimal *dec, const uchar* ptr, int length);
188 const char *dbug_decimal_as_string(char *buff, const my_decimal *val);
189 #else
190 #define dbug_decimal_as_string(A) NULL
191 #endif
192 
193 bool str_set_decimal(uint mask, const my_decimal *val, uint fixed_prec,
194  uint fixed_dec, char filler, String *str,
195  const CHARSET_INFO *cs);
196 
197 extern my_decimal decimal_zero;
198 
199 #ifndef MYSQL_CLIENT
200 int decimal_operation_results(int result);
201 #else
202 inline int decimal_operation_results(int result)
203 {
204  return result;
205 }
206 #endif /*MYSQL_CLIENT*/
207 
208 inline
209 void max_my_decimal(my_decimal *to, int precision, int frac)
210 {
211  DBUG_ASSERT((precision <= DECIMAL_MAX_PRECISION)&&
212  (frac <= DECIMAL_MAX_SCALE));
213  max_decimal(precision, frac, to);
214 }
215 
216 inline void max_internal_decimal(my_decimal *to)
217 {
218  max_my_decimal(to, DECIMAL_MAX_PRECISION, 0);
219 }
220 
221 inline int check_result(uint mask, int result)
222 {
223  if (result & mask)
224  decimal_operation_results(result);
225  return result;
226 }
227 
228 inline int check_result_and_overflow(uint mask, int result, my_decimal *val)
229 {
230  if (check_result(mask, result) & E_DEC_OVERFLOW)
231  {
232  bool sign= val->sign();
233  val->fix_buffer_pointer();
234  max_internal_decimal(val);
235  val->sign(sign);
236  }
237  return result;
238 }
239 
240 inline uint my_decimal_length_to_precision(uint length, uint scale,
241  bool unsigned_flag)
242 {
243  /* Precision can't be negative thus ignore unsigned_flag when length is 0. */
244  DBUG_ASSERT(length || !scale);
245  return (uint) (length - (scale>0 ? 1:0) -
246  (unsigned_flag || !length ? 0:1));
247 }
248 
249 inline uint32 my_decimal_precision_to_length_no_truncation(uint precision,
250  uint8 scale,
251  bool unsigned_flag)
252 {
253  /*
254  When precision is 0 it means that original length was also 0. Thus
255  unsigned_flag is ignored in this case.
256  */
257  DBUG_ASSERT(precision || !scale);
258  return (uint32)(precision + (scale > 0 ? 1 : 0) +
259  (unsigned_flag || !precision ? 0 : 1));
260 }
261 
262 inline uint32 my_decimal_precision_to_length(uint precision, uint8 scale,
263  bool unsigned_flag)
264 {
265  /*
266  When precision is 0 it means that original length was also 0. Thus
267  unsigned_flag is ignored in this case.
268  */
269  DBUG_ASSERT(precision || !scale);
270  set_if_smaller(precision, DECIMAL_MAX_PRECISION);
271  return my_decimal_precision_to_length_no_truncation(precision, scale,
272  unsigned_flag);
273 }
274 
275 inline
276 int my_decimal_string_length(const my_decimal *d)
277 {
278  /* length of string representation including terminating '\0' */
279  return decimal_string_size(d);
280 }
281 
282 
283 inline
284 int my_decimal_max_length(const my_decimal *d)
285 {
286  /* -1 because we do not count \0 */
287  return decimal_string_size(d) - 1;
288 }
289 
290 
291 inline
292 int my_decimal_get_binary_size(uint precision, uint scale)
293 {
294  return decimal_bin_size((int)precision, (int)scale);
295 }
296 
297 
298 inline
299 void my_decimal2decimal(const my_decimal *from, my_decimal *to)
300 {
301  *to= *from;
302 }
303 
304 
305 int my_decimal2binary(uint mask, const my_decimal *d, uchar *bin, int prec,
306  int scale);
307 
308 
309 inline
310 int binary2my_decimal(uint mask, const uchar *bin, my_decimal *d, int prec,
311  int scale)
312 {
313  return check_result(mask, bin2decimal(bin, d, prec, scale));
314 }
315 
316 
317 inline
318 int my_decimal_set_zero(my_decimal *d)
319 {
320  /*
321  We need the up-cast here, since my_decimal has sign() member functions,
322  which conflicts with decimal_t::size
323  (and decimal_make_zero is a macro, rather than a funcion).
324  */
325  decimal_make_zero(static_cast<decimal_t*>(d));
326  return 0;
327 }
328 
329 
330 inline
331 bool my_decimal_is_zero(const my_decimal *decimal_value)
332 {
333  return decimal_is_zero(decimal_value);
334 }
335 
336 
337 inline
338 int my_decimal_round(uint mask, const my_decimal *from, int scale,
339  bool truncate, my_decimal *to)
340 {
341  return check_result(mask, decimal_round(from, to, scale,
342  (truncate ? TRUNCATE : HALF_UP)));
343 }
344 
345 
346 inline
347 int my_decimal_floor(uint mask, const my_decimal *from, my_decimal *to)
348 {
349  return check_result(mask, decimal_round(from, to, 0, FLOOR));
350 }
351 
352 
353 inline
354 int my_decimal_ceiling(uint mask, const my_decimal *from, my_decimal *to)
355 {
356  return check_result(mask, decimal_round(from, to, 0, CEILING));
357 }
358 
359 
360 inline bool str_set_decimal(const my_decimal *val, String *str,
361  const CHARSET_INFO *cs)
362 {
363  return str_set_decimal(E_DEC_FATAL_ERROR, val, 0, 0, 0, str, cs);
364 }
365 
366 #ifndef MYSQL_CLIENT
367 class String;
368 int my_decimal2string(uint mask, const my_decimal *d, uint fixed_prec,
369  uint fixed_dec, char filler, String *str);
370 #endif
371 
372 inline
373 int my_decimal2int(uint mask, const my_decimal *d, my_bool unsigned_flag,
374  longlong *l)
375 {
376  my_decimal rounded;
377  /* decimal_round can return only E_DEC_TRUNCATED */
378  decimal_round(d, &rounded, 0, HALF_UP);
379  return check_result(mask, (unsigned_flag ?
380  decimal2ulonglong(&rounded, (ulonglong *)l) :
381  decimal2longlong(&rounded, l)));
382 }
383 
384 
385 inline
386 int my_decimal2double(uint, const my_decimal *d, double *result)
387 {
388  /* No need to call check_result as this will always succeed */
389  return decimal2double(d, result);
390 }
391 
392 
393 inline int my_decimal2lldiv_t(uint mask, const my_decimal *d, lldiv_t *to)
394 {
395  return check_result(mask, decimal2lldiv_t(d, to));
396 }
397 
398 
399 inline int str2my_decimal(uint mask, const char *str,
400  my_decimal *d, char **end)
401 {
402  return check_result_and_overflow(mask, string2decimal(str, d, end), d);
403 }
404 
405 
406 int str2my_decimal(uint mask, const char *from, uint length,
407  const CHARSET_INFO *charset, my_decimal *decimal_value);
408 
409 #if defined(MYSQL_SERVER) || defined(EMBEDDED_LIBRARY)
410 inline
411 int string2my_decimal(uint mask, const String *str, my_decimal *d)
412 {
413  return str2my_decimal(mask, str->ptr(), str->length(), str->charset(), d);
414 }
415 
416 
417 my_decimal *date2my_decimal(const MYSQL_TIME *ltime, my_decimal *dec);
418 my_decimal *time2my_decimal(const MYSQL_TIME *ltime, my_decimal *dec);
419 my_decimal *timeval2my_decimal(const struct timeval *tm, my_decimal *dec);
420 
421 #endif /*defined(MYSQL_SERVER) || defined(EMBEDDED_LIBRARY) */
422 
423 inline
424 int double2my_decimal(uint mask, double val, my_decimal *d)
425 {
426  return check_result_and_overflow(mask, double2decimal(val, d), d);
427 }
428 
429 
430 inline
431 int int2my_decimal(uint mask, longlong i, my_bool unsigned_flag, my_decimal *d)
432 {
433  return check_result(mask, (unsigned_flag ?
434  ulonglong2decimal((ulonglong)i, d) :
435  longlong2decimal(i, d)));
436 }
437 
438 
439 inline
440 void my_decimal_neg(decimal_t *arg)
441 {
442  if (decimal_is_zero(arg))
443  {
444  arg->sign= 0;
445  return;
446  }
447  decimal_neg(arg);
448 }
449 
450 
451 inline
452 int my_decimal_add(uint mask, my_decimal *res, const my_decimal *a,
453  const my_decimal *b)
454 {
455  return check_result_and_overflow(mask,
456  decimal_add(a, b, res),
457  res);
458 }
459 
460 
461 inline
462 int my_decimal_sub(uint mask, my_decimal *res, const my_decimal *a,
463  const my_decimal *b)
464 {
465  return check_result_and_overflow(mask,
466  decimal_sub(a, b, res),
467  res);
468 }
469 
470 
471 inline
472 int my_decimal_mul(uint mask, my_decimal *res, const my_decimal *a,
473  const my_decimal *b)
474 {
475  return check_result_and_overflow(mask,
476  decimal_mul(a, b, res),
477  res);
478 }
479 
480 
481 inline
482 int my_decimal_div(uint mask, my_decimal *res, const my_decimal *a,
483  const my_decimal *b, int div_scale_inc)
484 {
485  return check_result_and_overflow(mask,
486  decimal_div(a, b, res, div_scale_inc),
487  res);
488 }
489 
490 
491 inline
492 int my_decimal_mod(uint mask, my_decimal *res, const my_decimal *a,
493  const my_decimal *b)
494 {
495  return check_result_and_overflow(mask,
496  decimal_mod(a, b, res),
497  res);
498 }
499 
500 
505 inline
506 int my_decimal_cmp(const my_decimal *a, const my_decimal *b)
507 {
508  return decimal_cmp(a, b);
509 }
510 
511 
512 inline
513 int my_decimal_intg(const my_decimal *a)
514 {
515  return decimal_intg(a);
516 }
517 
518 
519 void my_decimal_trim(ulong *precision, uint *scale);
520 
521 
522 #endif /*my_decimal_h*/
523