1
/* Copyright (C) 2005-2006 MySQL AB
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.
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.
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., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA */
16
#include "mysql_priv.h"
22
report result of decimal operation.
24
@param result decimal library return code (E_DEC_* see include/decimal.h)
33
int decimal_operation_results(int result)
39
push_warning_printf(current_thd, MYSQL_ERROR::WARN_LEVEL_WARN,
40
WARN_DATA_TRUNCATED, ER(WARN_DATA_TRUNCATED),
44
push_warning_printf(current_thd, MYSQL_ERROR::WARN_LEVEL_ERROR,
45
ER_TRUNCATED_WRONG_VALUE,
46
ER(ER_TRUNCATED_WRONG_VALUE),
50
push_warning_printf(current_thd, MYSQL_ERROR::WARN_LEVEL_ERROR,
51
ER_DIVISION_BY_ZERO, ER(ER_DIVISION_BY_ZERO));
54
push_warning_printf(current_thd, MYSQL_ERROR::WARN_LEVEL_ERROR,
55
ER_TRUNCATED_WRONG_VALUE_FOR_FIELD,
56
ER(ER_TRUNCATED_WRONG_VALUE_FOR_FIELD),
57
"decimal", "", "", (long)-1);
60
my_error(ER_OUT_OF_RESOURCES, MYF(0));
70
@brief Converting decimal to string
72
@details Convert given my_decimal to String; allocate buffer as needed.
74
@param[in] mask what problems to warn on (mask of E_DEC_* values)
75
@param[in] d the decimal to print
76
@param[in] fixed_prec overall number of digits if ZEROFILL, 0 otherwise
77
@param[in] fixed_dec number of decimal places (if fixed_prec != 0)
78
@param[in] filler what char to pad with (ZEROFILL et al.)
79
@param[out] *str where to store the resulting string
83
@retval E_DEC_TRUNCATED
84
@retval E_DEC_OVERFLOW
88
int my_decimal2string(uint mask, const my_decimal *d,
89
uint fixed_prec, uint fixed_dec,
90
char filler, String *str)
93
Calculate the size of the string: For DECIMAL(a,b), fixed_prec==a
94
holds true iff the type is also ZEROFILL, which in turn implies
95
UNSIGNED. Hence the buffer for a ZEROFILLed value is the length
96
the user requested, plus one for a possible decimal point, plus
97
one if the user only wanted decimal places, but we force a leading
98
zero on them. Because the type is implicitly UNSIGNED, we do not
99
need to reserve a character for the sign. For all other cases,
100
fixed_prec will be 0, and my_decimal_string_length() will be called
101
instead to calculate the required size of the buffer.
103
int length= (fixed_prec
104
? (fixed_prec + ((fixed_prec == fixed_dec) ? 1 : 0) + 1)
105
: my_decimal_string_length(d));
107
if (str->alloc(length))
108
return check_result(mask, E_DEC_OOM);
109
result= decimal2string((decimal_t*) d, (char*) str->ptr(),
110
&length, (int)fixed_prec, fixed_dec,
113
return check_result(mask, result);
118
Convert from decimal to binary representation
122
mask error processing mask
123
d number for conversion
124
bin pointer to buffer where to write result
125
prec overall number of decimal digits
126
scale number of decimal digits after decimal point
129
Before conversion we round number if it need but produce truncation
138
int my_decimal2binary(uint mask, const my_decimal *d, uchar *bin, int prec,
141
int err1= E_DEC_OK, err2;
143
my_decimal2decimal(d, &rounded);
144
rounded.frac= decimal_actual_fraction(&rounded);
145
if (scale < rounded.frac)
147
err1= E_DEC_TRUNCATED;
148
/* decimal_round can return only E_DEC_TRUNCATED */
149
decimal_round(&rounded, &rounded, scale, HALF_UP);
151
err2= decimal2bin(&rounded, bin, prec, scale);
154
return check_result(mask, err2);
159
Convert string for decimal when string can be in some multibyte charset
163
mask error processing mask
164
from string to process
165
length length of given string
166
charset charset of given string
167
decimal_value buffer for result storing
177
int str2my_decimal(uint mask, const char *from, uint length,
178
CHARSET_INFO *charset, my_decimal *decimal_value)
180
char *end, *from_end;
182
char buff[STRING_BUFFER_USUAL_SIZE];
183
String tmp(buff, sizeof(buff), &my_charset_bin);
184
if (charset->mbminlen > 1)
187
tmp.copy(from, length, charset, &my_charset_latin1, &dummy_errors);
189
length= tmp.length();
190
charset= &my_charset_bin;
192
from_end= end= (char*) from+length;
193
err= string2decimal((char *)from, (decimal_t*) decimal_value, &end);
194
if (end != from_end && !err)
196
/* Give warning if there is something other than end space */
197
for ( ; end < from_end; end++)
199
if (!my_isspace(&my_charset_latin1, *end))
201
err= E_DEC_TRUNCATED;
206
check_result_and_overflow(mask, err, decimal_value);
211
my_decimal *date2my_decimal(MYSQL_TIME *ltime, my_decimal *dec)
214
date = (ltime->year*100L + ltime->month)*100L + ltime->day;
215
if (ltime->time_type > MYSQL_TIMESTAMP_DATE)
216
date= ((date*100L + ltime->hour)*100L+ ltime->minute)*100L + ltime->second;
217
if (int2my_decimal(E_DEC_FATAL_ERROR, date, FALSE, dec))
219
if (ltime->second_part)
221
dec->buf[(dec->intg-1) / 9 + 1]= ltime->second_part * 1000;
228
void my_decimal_trim(ulong *precision, uint *scale)
230
if (!(*precision) && !(*scale))
240
/* routines for debugging print */
242
#define DIG_PER_DEC1 9
243
#define ROUND_UP(X) (((X)+DIG_PER_DEC1-1)/DIG_PER_DEC1)
247
print_decimal(const my_decimal *dec)
250
char buff[512], *pos;
252
pos+= my_sprintf(buff, (buff, "Decimal: sign: %d intg: %d frac: %d { ",
253
dec->sign(), dec->intg, dec->frac));
254
end= ROUND_UP(dec->frac)+ROUND_UP(dec->intg)-1;
255
for (i=0; i < end; i++)
256
pos+= my_sprintf(pos, (pos, "%09d, ", dec->buf[i]));
257
pos+= my_sprintf(pos, (pos, "%09d }\n", dec->buf[i]));
258
fputs(buff, DBUG_FILE);
262
/* print decimal with its binary representation */
264
print_decimal_buff(const my_decimal *dec, const uchar* ptr, int length)
267
fprintf(DBUG_FILE, "Record: ");
268
for (int i= 0; i < length; i++)
270
fprintf(DBUG_FILE, "%02X ", (uint)((uchar *)ptr)[i]);
272
fprintf(DBUG_FILE, "\n");
276
const char *dbug_decimal_as_string(char *buff, const my_decimal *val)
278
int length= DECIMAL_MAX_STR_LENGTH;
281
(void)decimal2string((decimal_t*) val, buff, &length, 0,0,0);
288
#endif /*MYSQL_CLIENT*/