00001 /* Copyright (C) 2004 MySQL AB & MySQL Finland AB & TCX DataKonsult AB 00002 00003 This program is free software; you can redistribute it and/or modify 00004 it under the terms of the GNU General Public License as published by 00005 the Free Software Foundation; either version 2 of the License, or 00006 (at your option) any later version. 00007 00008 This program is distributed in the hope that it will be useful, 00009 but WITHOUT ANY WARRANTY; without even the implied warranty of 00010 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 00011 GNU General Public License for more details. 00012 00013 You should have received a copy of the GNU General Public License 00014 along with this program; if not, write to the Free Software 00015 Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA */ 00016 00017 #include "mysql_priv.h" 00018 00019 #ifndef MYSQL_CLIENT 00020 /* 00021 report result of decimal operation 00022 00023 SYNOPSIS 00024 decimal_operation_results() 00025 result decimal library return code (E_DEC_* see include/decimal.h) 00026 00027 TODO 00028 Fix error messages 00029 00030 RETURN 00031 result 00032 */ 00033 00034 int decimal_operation_results(int result) 00035 { 00036 switch (result) { 00037 case E_DEC_OK: 00038 break; 00039 case E_DEC_TRUNCATED: 00040 push_warning_printf(current_thd, MYSQL_ERROR::WARN_LEVEL_WARN, 00041 WARN_DATA_TRUNCATED, ER(WARN_DATA_TRUNCATED), 00042 "", (long)-1); 00043 break; 00044 case E_DEC_OVERFLOW: 00045 push_warning_printf(current_thd, MYSQL_ERROR::WARN_LEVEL_ERROR, 00046 ER_TRUNCATED_WRONG_VALUE, 00047 ER(ER_TRUNCATED_WRONG_VALUE), 00048 "DECIMAL", ""); 00049 break; 00050 case E_DEC_DIV_ZERO: 00051 push_warning_printf(current_thd, MYSQL_ERROR::WARN_LEVEL_ERROR, 00052 ER_DIVISION_BY_ZERO, ER(ER_DIVISION_BY_ZERO)); 00053 break; 00054 case E_DEC_BAD_NUM: 00055 push_warning_printf(current_thd, MYSQL_ERROR::WARN_LEVEL_ERROR, 00056 ER_TRUNCATED_WRONG_VALUE_FOR_FIELD, 00057 ER(ER_TRUNCATED_WRONG_VALUE_FOR_FIELD), 00058 "decimal", "", "", (long)-1); 00059 break; 00060 case E_DEC_OOM: 00061 my_error(ER_OUT_OF_RESOURCES, MYF(0)); 00062 break; 00063 default: 00064 DBUG_ASSERT(0); 00065 } 00066 return result; 00067 } 00068 00069 00070 /* 00071 Converting decimal to string 00072 00073 SYNOPSIS 00074 my_decimal2string() 00075 00076 return 00077 E_DEC_OK 00078 E_DEC_TRUNCATED 00079 E_DEC_OVERFLOW 00080 E_DEC_OOM 00081 */ 00082 00083 int my_decimal2string(uint mask, const my_decimal *d, 00084 uint fixed_prec, uint fixed_dec, 00085 char filler, String *str) 00086 { 00087 int length= (fixed_prec ? (fixed_prec + 1) : my_decimal_string_length(d)); 00088 int result; 00089 if (str->alloc(length)) 00090 return check_result(mask, E_DEC_OOM); 00091 result= decimal2string((decimal_t*) d, (char*) str->ptr(), 00092 &length, (int)fixed_prec, fixed_dec, 00093 filler); 00094 str->length(length); 00095 return check_result(mask, result); 00096 } 00097 00098 00099 /* 00100 Convert from decimal to binary representation 00101 00102 SYNOPSIS 00103 my_decimal2binary() 00104 mask error processing mask 00105 d number for conversion 00106 bin pointer to buffer where to write result 00107 prec overall number of decimal digits 00108 scale number of decimal digits after decimal point 00109 00110 NOTE 00111 Before conversion we round number if it need but produce truncation 00112 error in this case 00113 00114 RETURN 00115 E_DEC_OK 00116 E_DEC_TRUNCATED 00117 E_DEC_OVERFLOW 00118 */ 00119 00120 int my_decimal2binary(uint mask, const my_decimal *d, char *bin, int prec, 00121 int scale) 00122 { 00123 int err1= E_DEC_OK, err2; 00124 my_decimal rounded; 00125 my_decimal2decimal(d, &rounded); 00126 rounded.frac= decimal_actual_fraction(&rounded); 00127 if (scale < rounded.frac) 00128 { 00129 err1= E_DEC_TRUNCATED; 00130 /* decimal_round can return only E_DEC_TRUNCATED */ 00131 decimal_round(&rounded, &rounded, scale, HALF_UP); 00132 } 00133 err2= decimal2bin(&rounded, bin, prec, scale); 00134 if (!err2) 00135 err2= err1; 00136 return check_result(mask, err2); 00137 } 00138 00139 00140 /* 00141 Convert string for decimal when string can be in some multibyte charset 00142 00143 SYNOPSIS 00144 str2my_decimal() 00145 mask error processing mask 00146 from string to process 00147 length length of given string 00148 charset charset of given string 00149 decimal_value buffer for result storing 00150 00151 RESULT 00152 E_DEC_OK 00153 E_DEC_TRUNCATED 00154 E_DEC_OVERFLOW 00155 E_DEC_BAD_NUM 00156 E_DEC_OOM 00157 */ 00158 00159 int str2my_decimal(uint mask, const char *from, uint length, 00160 CHARSET_INFO *charset, my_decimal *decimal_value) 00161 { 00162 char *end, *from_end; 00163 int err; 00164 char buff[STRING_BUFFER_USUAL_SIZE]; 00165 String tmp(buff, sizeof(buff), &my_charset_bin); 00166 if (charset->mbminlen > 1) 00167 { 00168 uint dummy_errors; 00169 tmp.copy(from, length, charset, &my_charset_latin1, &dummy_errors); 00170 from= tmp.ptr(); 00171 length= tmp.length(); 00172 charset= &my_charset_bin; 00173 } 00174 from_end= end= (char*) from+length; 00175 err= string2decimal((char *)from, (decimal_t*) decimal_value, &end); 00176 if (end != from_end && !err) 00177 { 00178 /* Give warning if there is something other than end space */ 00179 for ( ; end < from_end; end++) 00180 { 00181 if (!my_isspace(&my_charset_latin1, *end)) 00182 { 00183 err= E_DEC_TRUNCATED; 00184 break; 00185 } 00186 } 00187 } 00188 check_result_and_overflow(mask, err, decimal_value); 00189 return err; 00190 } 00191 00192 00193 #ifndef DBUG_OFF 00194 /* routines for debugging print */ 00195 00196 #define DIG_PER_DEC1 9 00197 #define ROUND_UP(X) (((X)+DIG_PER_DEC1-1)/DIG_PER_DEC1) 00198 00199 /* print decimal */ 00200 void 00201 print_decimal(const my_decimal *dec) 00202 { 00203 int i, end; 00204 char buff[512], *pos; 00205 pos= buff; 00206 pos+= my_sprintf(buff, (buff, "Decimal: sign: %d intg: %d frac: %d { ", 00207 dec->sign(), dec->intg, dec->frac)); 00208 end= ROUND_UP(dec->frac)+ROUND_UP(dec->intg)-1; 00209 for (i=0; i < end; i++) 00210 pos+= my_sprintf(pos, (pos, "%09d, ", dec->buf[i])); 00211 pos+= my_sprintf(pos, (pos, "%09d }\n", dec->buf[i])); 00212 fputs(buff, DBUG_FILE); 00213 } 00214 00215 00216 /* print decimal with its binary representation */ 00217 void 00218 print_decimal_buff(const my_decimal *dec, const byte* ptr, int length) 00219 { 00220 print_decimal(dec); 00221 fprintf(DBUG_FILE, "Record: "); 00222 for (int i= 0; i < length; i++) 00223 { 00224 fprintf(DBUG_FILE, "%02X ", (uint)((uchar *)ptr)[i]); 00225 } 00226 fprintf(DBUG_FILE, "\n"); 00227 } 00228 00229 00230 const char *dbug_decimal_as_string(char *buff, const my_decimal *val) 00231 { 00232 int length= DECIMAL_MAX_STR_LENGTH; 00233 if (!val) 00234 return "NULL"; 00235 (void)decimal2string((decimal_t*) val, buff, &length, 0,0,0); 00236 return buff; 00237 } 00238 00239 #endif /*DBUG_OFF*/ 00240 00241 00242 #endif /*MYSQL_CLIENT*/
1.4.7

