120
114
#include <algorithm>
122
#include "drizzled/current_session.h"
123
#include "drizzled/error.h"
124
#include "drizzled/field.h"
125
#include "drizzled/internal/my_sys.h"
127
116
using namespace std;
129
118
namespace drizzled
132
report result of decimal operation.
134
@param result decimal library return code (E_DEC_* see include/decimal.h)
143
int decimal_operation_results(int result)
148
case E_DEC_TRUNCATED:
149
push_warning_printf(current_session, DRIZZLE_ERROR::WARN_LEVEL_WARN,
150
ER_WARN_DATA_TRUNCATED, ER(ER_WARN_DATA_TRUNCATED),
154
push_warning_printf(current_session, DRIZZLE_ERROR::WARN_LEVEL_ERROR,
155
ER_TRUNCATED_WRONG_VALUE,
156
ER(ER_TRUNCATED_WRONG_VALUE),
160
my_error(ER_DIVISION_BY_ZERO, MYF(0));
163
push_warning_printf(current_session, DRIZZLE_ERROR::WARN_LEVEL_ERROR,
164
ER_TRUNCATED_WRONG_VALUE_FOR_FIELD,
165
ER(ER_TRUNCATED_WRONG_VALUE_FOR_FIELD),
166
"decimal", "", "", (long)-1);
169
my_error(ER_OUT_OF_RESOURCES, MYF(0));
179
@brief Converting decimal to string
181
@details Convert given my_decimal to String; allocate buffer as needed.
183
@param[in] mask what problems to warn on (mask of E_DEC_* values)
184
@param[in] d the decimal to print
185
@param[in] fixed_prec overall number of digits if ZEROFILL, 0 otherwise
186
@param[in] fixed_dec number of decimal places (if fixed_prec != 0)
187
@param[in] filler what char to pad with (ZEROFILL et al.)
188
@param[out] *str where to store the resulting string
192
@retval E_DEC_TRUNCATED
193
@retval E_DEC_OVERFLOW
197
int my_decimal2string(uint32_t mask, const my_decimal *d,
198
uint32_t fixed_prec, uint32_t fixed_dec,
199
char filler, String *str)
202
Calculate the size of the string: For DECIMAL(a,b), fixed_prec==a
203
holds true iff the type is also ZEROFILL, which in turn implies
204
UNSIGNED. Hence the buffer for a ZEROFILLed value is the length
205
the user requested, plus one for a possible decimal point, plus
206
one if the user only wanted decimal places, but we force a leading
207
zero on them. Because the type is implicitly UNSIGNED, we do not
208
need to reserve a character for the sign. For all other cases,
209
fixed_prec will be 0, and my_decimal_string_length() will be called
210
instead to calculate the required size of the buffer.
212
int length= (int)(fixed_prec
213
? (uint32_t)(fixed_prec + ((fixed_prec == fixed_dec) ? 1 : 0) + 1)
214
: (uint32_t)my_decimal_string_length(d));
216
if (str->alloc(length))
217
return check_result(mask, E_DEC_OOM);
218
result= decimal2string((decimal_t*) d, (char*) str->ptr(),
219
&length, (int)fixed_prec, fixed_dec,
222
return check_result(mask, result);
227
@brief Convert from decimal to binary representation
229
@param[in] mask error processing mask
230
@param[in] d number for conversion
231
@param[out] bin pointer to buffer where to write result
232
@param[in] prec overall number of decimal digits
233
@param[in] scale number of decimal digits after decimal point
236
Before conversion we round number if it need but produce truncation
241
@retval E_DEC_TRUNCATED
242
@retval E_DEC_OVERFLOW
245
int my_decimal2binary(uint32_t mask, const my_decimal *d, unsigned char *bin, int prec,
248
int err1= E_DEC_OK, err2;
250
my_decimal2decimal(d, &rounded);
251
rounded.frac= decimal_actual_fraction(&rounded);
252
if (scale < rounded.frac)
254
err1= E_DEC_TRUNCATED;
255
/* decimal_round can return only E_DEC_TRUNCATED */
256
decimal_round(&rounded, &rounded, scale, HALF_UP);
258
err2= decimal2bin(&rounded, bin, prec, scale);
261
return check_result(mask, err2);
266
@brief Convert string for decimal when string can be in some multibyte charset
268
@param mask error processing mask
269
@param from string to process
270
@param length length of given string
271
@param charset charset of given string
272
@param decimal_value buffer for result storing
276
@retval E_DEC_TRUNCATED
277
@retval E_DEC_OVERFLOW
278
@retval E_DEC_BAD_NUM
282
int str2my_decimal(uint32_t mask, const char *from, uint32_t length,
283
const CHARSET_INFO * charset, my_decimal *decimal_value)
285
char *end, *from_end;
287
char buff[STRING_BUFFER_USUAL_SIZE];
288
String tmp(buff, sizeof(buff), &my_charset_bin);
289
if (charset->mbminlen > 1)
292
tmp.copy(from, length, charset, &my_charset_utf8_general_ci, &dummy_errors);
294
length= tmp.length();
295
charset= &my_charset_bin;
297
from_end= end= (char*) from+length;
298
err= string2decimal((char *)from, (decimal_t*) decimal_value, &end);
299
if (end != from_end && !err)
301
/* Give warning if there is something other than end space */
302
for ( ; end < from_end; end++)
304
if (!my_isspace(&my_charset_utf8_general_ci, *end))
306
err= E_DEC_TRUNCATED;
311
check_result_and_overflow(mask, err, decimal_value);
316
my_decimal *date2my_decimal(DRIZZLE_TIME *ltime, my_decimal *dec)
319
date = (ltime->year*100L + ltime->month)*100L + ltime->day;
320
if (ltime->time_type > DRIZZLE_TIMESTAMP_DATE)
321
date= ((date*100L + ltime->hour)*100L+ ltime->minute)*100L + ltime->second;
322
if (int2my_decimal(E_DEC_FATAL_ERROR, date, false, dec))
324
if (ltime->second_part)
326
dec->buf[(dec->intg-1) / 9 + 1]= ltime->second_part * 1000;
333
void my_decimal_trim(uint32_t *precision, uint32_t *scale)
335
if (!(*precision) && !(*scale))
345
122
Internally decimal numbers are stored base 10^9 (see DIG_BASE below)
378
149
999900000, 999990000, 999999000,
379
150
999999900, 999999990 };
382
153
#define sanity(d) assert((d)->len > 0)
384
155
#define sanity(d) assert((d)->len >0 && ((d)->buf[0] | \
385
156
(d)->buf[(d)->len-1] | 1))
388
inline static void fix_intg_frac_error(const int len, int &intg1, int &frac1, int &error)
390
if (unlikely(intg1+frac1 > len))
392
if (unlikely(intg1 > len))
396
error=E_DEC_OVERFLOW;
401
error=E_DEC_TRUNCATED;
408
/* assume carry <= 1 */
409
inline static void add(dec1 &to, const dec1 &from1, const dec1& from2, dec1 &carry)
411
dec1 a=from1+from2+carry;
413
if ((carry= (a >= DIG_BASE))) /* no division here! */
418
inline static void add2(dec1 &to, const dec1 &from1, const dec1 &from2, dec1 &carry)
420
dec2 a=dec2(from1)+from2+carry;
421
if ((carry= (a >= DIG_BASE)))
423
if (unlikely(a >= DIG_BASE))
432
inline static void sub(dec1 &to, const dec1 &from1, const dec1 &from2, dec1 &carry)
434
dec1 a=from1-from2-carry;
435
if ((carry= (a < 0)))
441
inline static void sub2(dec1 &to, const dec1 &from1, const dec1 &from2, dec1 &carry)
443
dec1 a=from1-from2-carry;
444
if ((carry= (a < 0)))
159
#define FIX_INTG_FRAC_ERROR(len, intg1, frac1, error) \
162
if (unlikely(intg1+frac1 > (len))) \
164
if (unlikely(intg1 > (len))) \
168
error=E_DEC_OVERFLOW; \
173
error=E_DEC_TRUNCATED; \
180
#define ADD(to, from1, from2, carry) /* assume carry <= 1 */ \
183
dec1 a=(from1)+(from2)+(carry); \
184
assert((carry) <= 1); \
185
if (((carry)= a >= DIG_BASE)) /* no division here! */ \
190
#define ADD2(to, from1, from2, carry) \
193
dec2 a=((dec2)(from1))+(from2)+(carry); \
194
if (((carry)= a >= DIG_BASE)) \
196
if (unlikely(a >= DIG_BASE)) \
204
#define SUB(to, from1, from2, carry) /* to=from1-from2 */ \
207
dec1 a=(from1)-(from2)-(carry); \
208
if (((carry)= a < 0)) \
213
#define SUB2(to, from1, from2, carry) /* to=from1-from2 */ \
216
dec1 a=(from1)-(from2)-(carry); \
217
if (((carry)= a < 0)) \
219
if (unlikely(a < 0)) \
455
@brief Get maximum value for given precision and scale
457
@param precision/scale see decimal_bin_size() below
458
@param to decimal where where the result will be stored
228
Swap the contents of two variables.
230
#define swap_variables(TYPE, a, b) \
240
Get maximum value for given precision and scale
244
precision/scale - see decimal_bin_size() below
245
to - decimal where where the result will be stored
459
246
to->buf and to->len must be set.
542
@brief Convert decimal to its printable string representation
331
Convert decimal to its printable string representation
544
@param from value to convert
545
@param to points to buffer where string representation
547
@param to_len in: size of to buffer
548
out: length of the actually written string
549
@param fixed_precision 0 if representation can be variable length and
335
from - value to convert
336
to - points to buffer where string representation
338
*to_len - in: size of to buffer
339
out: length of the actually written string
340
fixed_precision - 0 if representation can be variable length and
550
341
fixed_decimals will not be checked in this case.
551
342
Put number as with fixed point position with this
552
343
number of digits (sign counted and decimal point is
554
@param fixed_decimals number digits after point.
555
@param filler character to fill gaps in case of fixed_precision > 0
345
fixed_decimals - number digits after point.
346
filler - character to fill gaps in case of fixed_precision > 0
559
@retval E_DEC_TRUNCATED
560
@retval E_DEC_OVERFLOW
349
E_DEC_OK/E_DEC_TRUNCATED/E_DEC_OVERFLOW
562
352
int decimal2string(const decimal_t *from, char *to, int *to_len,
563
353
int fixed_precision, int fixed_decimals,
731
@param Left shift for alignment of data in buffer
733
@param dec pointer to decimal number which have to be shifted
734
@param shift number of decimal digits on which it should be shifted
735
@param beg beginning of decimal digits (see digits_bounds())
736
@param end end of decimal digits (see digits_bounds())
739
Result fitting in the buffer should be garanted.
740
'shift' have to be from 1 to DIG_PER_DEC1-1 (inclusive)
742
@todo Above note is unclear - is 'garanted' a typo for 'guaranteed'
524
Left shift for alignment of data in buffer
528
dec pointer to decimal number which have to be shifted
529
shift number of decimal digits on which it should be shifted
530
beg/end bounds of decimal digits (see digits_bounds())
533
Result fitting in the buffer should be garanted.
534
'shift' have to be from 1 to DIG_PER_DEC1-1 (inclusive)
745
537
static void do_mini_left_shift(decimal_t *dec, int shift, int beg, int last)
747
dec1 *from= dec->buf + round_up(beg + 1) - 1;
748
dec1 *end= dec->buf + round_up(last) - 1;
539
dec1 *from= dec->buf + ROUND_UP(beg + 1) - 1;
540
dec1 *end= dec->buf + ROUND_UP(last) - 1;
749
541
int c_shift= DIG_PER_DEC1 - shift;
750
542
assert(from >= dec->buf);
751
543
assert(end < dec->buf + dec->len);
1641
1447
frac0*sizeof(dec1)+dig2bytes[frac0x];
1645
@brief Rounds the decimal to "scale" digits
1647
@param from - decimal to round,
1648
@param to - result buffer. from==to is allowed
1649
@param scale - to what position to round. can be negative!
1650
@param mode - round to nearest even or truncate
1451
Rounds the decimal to "scale" digits
1455
from - decimal to round,
1456
to - result buffer. from==to is allowed
1457
scale - to what position to round. can be negative!
1458
mode - round to nearest even or truncate
1653
1461
scale can be negative !
1654
1462
one TRUNCATED error (line XXX below) isn't treated very logical :(
1657
1465
E_DEC_OK/E_DEC_TRUNCATED
1660
1469
decimal_round(const decimal_t *from, decimal_t *to, int scale,
1661
1470
decimal_round_mode mode)
1663
int frac0=scale>0 ? round_up(scale) : scale/DIG_PER_DEC1,
1664
frac1=round_up(from->frac), round_digit= 0,
1665
intg0=round_up(from->intg), error=E_DEC_OK, len=to->len,
1666
intg1=round_up(from->intg +
1472
int frac0=scale>0 ? ROUND_UP(scale) : scale/DIG_PER_DEC1,
1473
frac1=ROUND_UP(from->frac), round_digit= 0,
1474
intg0=ROUND_UP(from->intg), error=E_DEC_OK, len=to->len,
1475
intg1=ROUND_UP(from->intg +
1667
1476
(((intg0 + frac0)>0) && (from->buf[0] == DIG_MAX)));
1668
1477
dec1 *buf0=from->buf, *buf1=to->buf, x, y, carry=0;
2245
2054
static int do_div_mod(const decimal_t *from1, const decimal_t *from2,
2246
2055
decimal_t *to, decimal_t *mod, int scale_incr)
2248
int frac1=round_up(from1->frac)*DIG_PER_DEC1, prec1=from1->intg+frac1,
2249
frac2=round_up(from2->frac)*DIG_PER_DEC1, prec2=from2->intg+frac2,
2057
int frac1=ROUND_UP(from1->frac)*DIG_PER_DEC1, prec1=from1->intg+frac1,
2058
frac2=ROUND_UP(from2->frac)*DIG_PER_DEC1, prec2=from2->intg+frac2,
2250
2059
error= 0, i, intg0, frac0, len1, len2, dintg, div_mod=(!mod);
2251
2060
dec1 *buf0, *buf1=from1->buf, *buf2=from2->buf, *tmp1,
2252
2061
*start2, *stop2, *stop1, *stop0, norm2, carry, *start1, dcarry;
2488
@brief division of two decimals
2490
@param[in] from1 dividend
2491
@param[in] from2 divisor
2492
@param[out] to quotient
2297
division of two decimals
2495
2306
E_DEC_OK/E_DEC_TRUNCATED/E_DEC_OVERFLOW/E_DEC_DIV_ZERO;
2498
2309
see do_div_mod()
2501
2313
decimal_div(const decimal_t *from1, const decimal_t *from2, decimal_t *to, int scale_incr)
2503
2315
return do_div_mod(from1, from2, to, 0, scale_incr);
2509
the modulus R in R = M mod N
2515
R = M - k*N, where k is integer
2517
thus, there's no requirement for M or N to be integers
2520
@param from1 dividend
2521
@param from2 divisor
2525
2328
E_DEC_OK/E_DEC_TRUNCATED/E_DEC_OVERFLOW/E_DEC_DIV_ZERO;
2528
2331
see do_div_mod()
2334
the modulus R in R = M mod N
2340
R = M - k*N, where k is integer
2342
thus, there's no requirement for M or N to be integers
2531
2345
int decimal_mod(const decimal_t *from1, const decimal_t *from2, decimal_t *to)
2533
2347
return do_div_mod(from1, from2, 0, to, 0);