97
97
implementation-defined.
100
#include <drizzled/global.h>
102
#include "drizzled/definitions.h"
103
#include "drizzled/internal/m_string.h"
104
#include "drizzled/charset_info.h"
105
#include "drizzled/decimal.h"
102
#include "m_string.h"
107
106
#include <plugin/myisam/myisampack.h>
108
107
#include <drizzled/util/test.h>
111
109
#include <alloca.h>
116
#include "drizzled/current_session.h"
117
#include "drizzled/error.h"
118
#include "drizzled/field.h"
119
#include "drizzled/internal/my_sys.h"
126
report result of decimal operation.
128
@param result decimal library return code (E_DEC_* see include/decimal.h)
137
int decimal_operation_results(int result)
142
case E_DEC_TRUNCATED:
143
push_warning_printf(current_session, DRIZZLE_ERROR::WARN_LEVEL_WARN,
144
ER_WARN_DATA_TRUNCATED, ER(ER_WARN_DATA_TRUNCATED),
148
push_warning_printf(current_session, DRIZZLE_ERROR::WARN_LEVEL_ERROR,
149
ER_TRUNCATED_WRONG_VALUE,
150
ER(ER_TRUNCATED_WRONG_VALUE),
154
push_warning_printf(current_session, DRIZZLE_ERROR::WARN_LEVEL_ERROR,
155
ER_DIVISION_BY_ZERO, ER(ER_DIVISION_BY_ZERO));
158
push_warning_printf(current_session, DRIZZLE_ERROR::WARN_LEVEL_ERROR,
159
ER_TRUNCATED_WRONG_VALUE_FOR_FIELD,
160
ER(ER_TRUNCATED_WRONG_VALUE_FOR_FIELD),
161
"decimal", "", "", (long)-1);
164
my_error(ER_OUT_OF_RESOURCES, MYF(0));
174
@brief Converting decimal to string
176
@details Convert given my_decimal to String; allocate buffer as needed.
178
@param[in] mask what problems to warn on (mask of E_DEC_* values)
179
@param[in] d the decimal to print
180
@param[in] fixed_prec overall number of digits if ZEROFILL, 0 otherwise
181
@param[in] fixed_dec number of decimal places (if fixed_prec != 0)
182
@param[in] filler what char to pad with (ZEROFILL et al.)
183
@param[out] *str where to store the resulting string
187
@retval E_DEC_TRUNCATED
188
@retval E_DEC_OVERFLOW
192
int my_decimal2string(uint32_t mask, const my_decimal *d,
193
uint32_t fixed_prec, uint32_t fixed_dec,
194
char filler, String *str)
197
Calculate the size of the string: For DECIMAL(a,b), fixed_prec==a
198
holds true iff the type is also ZEROFILL, which in turn implies
199
UNSIGNED. Hence the buffer for a ZEROFILLed value is the length
200
the user requested, plus one for a possible decimal point, plus
201
one if the user only wanted decimal places, but we force a leading
202
zero on them. Because the type is implicitly UNSIGNED, we do not
203
need to reserve a character for the sign. For all other cases,
204
fixed_prec will be 0, and my_decimal_string_length() will be called
205
instead to calculate the required size of the buffer.
207
int length= (fixed_prec
208
? (fixed_prec + ((fixed_prec == fixed_dec) ? 1 : 0) + 1)
209
: my_decimal_string_length(d));
211
if (str->alloc(length))
212
return check_result(mask, E_DEC_OOM);
213
result= decimal2string((decimal_t*) d, (char*) str->ptr(),
214
&length, (int)fixed_prec, fixed_dec,
217
return check_result(mask, result);
222
Convert from decimal to binary representation
226
mask error processing mask
227
d number for conversion
228
bin pointer to buffer where to write result
229
prec overall number of decimal digits
230
scale number of decimal digits after decimal point
233
Before conversion we round number if it need but produce truncation
242
int my_decimal2binary(uint32_t mask, const my_decimal *d, unsigned char *bin, int prec,
245
int err1= E_DEC_OK, err2;
247
my_decimal2decimal(d, &rounded);
248
rounded.frac= decimal_actual_fraction(&rounded);
249
if (scale < rounded.frac)
251
err1= E_DEC_TRUNCATED;
252
/* decimal_round can return only E_DEC_TRUNCATED */
253
decimal_round(&rounded, &rounded, scale, HALF_UP);
255
err2= decimal2bin(&rounded, bin, prec, scale);
258
return check_result(mask, err2);
263
Convert string for decimal when string can be in some multibyte charset
267
mask error processing mask
268
from string to process
269
length length of given string
270
charset charset of given string
271
decimal_value buffer for result storing
281
int str2my_decimal(uint32_t mask, const char *from, uint32_t length,
282
const CHARSET_INFO * charset, my_decimal *decimal_value)
284
char *end, *from_end;
286
char buff[STRING_BUFFER_USUAL_SIZE];
287
String tmp(buff, sizeof(buff), &my_charset_bin);
288
if (charset->mbminlen > 1)
290
uint32_t dummy_errors;
291
tmp.copy(from, length, charset, &my_charset_utf8_general_ci, &dummy_errors);
293
length= tmp.length();
294
charset= &my_charset_bin;
296
from_end= end= (char*) from+length;
297
err= string2decimal((char *)from, (decimal_t*) decimal_value, &end);
298
if (end != from_end && !err)
300
/* Give warning if there is something other than end space */
301
for ( ; end < from_end; end++)
303
if (!my_isspace(&my_charset_utf8_general_ci, *end))
305
err= E_DEC_TRUNCATED;
310
check_result_and_overflow(mask, err, decimal_value);
315
my_decimal *date2my_decimal(DRIZZLE_TIME *ltime, my_decimal *dec)
318
date = (ltime->year*100L + ltime->month)*100L + ltime->day;
319
if (ltime->time_type > DRIZZLE_TIMESTAMP_DATE)
320
date= ((date*100L + ltime->hour)*100L+ ltime->minute)*100L + ltime->second;
321
if (int2my_decimal(E_DEC_FATAL_ERROR, date, false, dec))
323
if (ltime->second_part)
325
dec->buf[(dec->intg-1) / 9 + 1]= ltime->second_part * 1000;
332
void my_decimal_trim(uint32_t *precision, uint32_t *scale)
334
if (!(*precision) && !(*scale))
344
111
Internally decimal numbers are stored base 10^9 (see DIG_BASE below)
345
112
So one variable of type decimal_digit_t is limited:
1884
static int do_add(const decimal_t *from1, const decimal_t *from2, decimal_t *to)
1663
Returns the size of the result of the operation
1666
decimal_result_size()
1667
from1 - operand of the unary operation or first operand of the
1669
from2 - second operand of the binary operation
1670
op - operation. one char '+', '-', '*', '/' are allowed
1671
others may be added later
1672
param - extra param to the operation. unused for '+', '-', '*'
1673
scale increment for '/'
1676
returned valued may be larger than the actual buffer requred
1677
in the operation, as decimal_result_size, by design, operates on
1678
precision/scale values only and not on the actual decimal number
1681
size of to->buf array in dec1 elements. to get size in bytes
1682
multiply by sizeof(dec1)
1685
int decimal_result_size(decimal_t *from1, decimal_t *from2, char op, int param)
1689
return ROUND_UP(cmax(from1->intg, from2->intg)) +
1690
ROUND_UP(cmax(from1->frac, from2->frac));
1692
return ROUND_UP(cmax(from1->intg, from2->intg)+1) +
1693
ROUND_UP(cmax(from1->frac, from2->frac));
1695
return ROUND_UP(from1->intg+from2->intg)+
1696
ROUND_UP(from1->frac)+ROUND_UP(from2->frac);
1698
return ROUND_UP(from1->intg+from2->intg+1+from1->frac+from2->frac+param);
1701
return -1; /* shut up the warning */
1704
static int do_add(decimal_t *from1, decimal_t *from2, decimal_t *to)
1886
1706
int intg1=ROUND_UP(from1->intg), intg2=ROUND_UP(from2->intg),
1887
1707
frac1=ROUND_UP(from1->frac), frac2=ROUND_UP(from2->frac),
1888
frac0=max(frac1, frac2), intg0=max(intg1, intg2), error;
1708
frac0=cmax(frac1, frac2), intg0=cmax(intg1, intg2), error;
1889
1709
dec1 *buf1, *buf2, *buf0, *stop, *stop2, x, carry;
2109
int decimal_add(const decimal_t *from1, const decimal_t *from2, decimal_t *to)
1929
int decimal_add(decimal_t *from1, decimal_t *from2, decimal_t *to)
2111
1931
if (likely(from1->sign == from2->sign))
2112
1932
return do_add(from1, from2, to);
2113
1933
return do_sub(from1, from2, to);
2116
int decimal_sub(const decimal_t *from1, const decimal_t *from2, decimal_t *to)
1936
int decimal_sub(decimal_t *from1, decimal_t *from2, decimal_t *to)
2118
1938
if (likely(from1->sign == from2->sign))
2119
1939
return do_sub(from1, from2, to);
2120
1940
return do_add(from1, from2, to);
2123
int decimal_cmp(const decimal_t *from1, const decimal_t *from2)
1943
int decimal_cmp(decimal_t *from1, decimal_t *from2)
2125
1945
if (likely(from1->sign == from2->sign))
2126
1946
return do_sub(from1, from2, 0);
2127
1947
return from1->sign > from2->sign ? -1 : 1;
2130
int decimal_is_zero(const decimal_t *from)
1950
int decimal_is_zero(decimal_t *from)
2132
1952
dec1 *buf1=from->buf,
2133
1953
*end=buf1+ROUND_UP(from->intg)+ROUND_UP(from->frac);