114
114
#include <algorithm>
116
#include "drizzled/current_session.h"
117
#include "drizzled/error.h"
118
#include "drizzled/field.h"
119
#include "drizzled/internal/my_sys.h"
116
121
using namespace std;
118
123
namespace drizzled
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))
122
344
Internally decimal numbers are stored base 10^9 (see DIG_BASE below)