Skip to content

Commit c2640d2

Browse files
author
holyfoot@mysql.com
committed
Merge bk@192.168.21.1:/usr/home/bk/mysql-5.0
into mysql.com:/home/hf/work/mysql-5.0.13573
2 parents 69d985c + dc78f2e commit c2640d2

File tree

6 files changed

+102
-35
lines changed

6 files changed

+102
-35
lines changed

mysql-test/r/type_newdecimal.result

+25-3
Original file line numberDiff line numberDiff line change
@@ -846,15 +846,14 @@ select 0/0;
846846
NULL
847847
select 9999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999 as x;
848848
x
849-
999999999999999999999999999999999999999999999999999999999999999999999999999999999
849+
99999999999999999999999999999999999999999999999999999999999999999
850850
Warnings:
851851
Error 1292 Truncated incorrect DECIMAL value: ''
852852
select 9999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999 + 1 as x;
853853
x
854-
NULL
854+
100000000000000000000000000000000000000000000000000000000000000000
855855
Warnings:
856856
Error 1292 Truncated incorrect DECIMAL value: ''
857-
Error 1292 Truncated incorrect DECIMAL value: ''
858857
select 0.190287977636363637 + 0.040372670 * 0 - 0;
859858
0.190287977636363637 + 0.040372670 * 0 - 0
860859
0.190287977636363637
@@ -1021,3 +1020,26 @@ cast(@non_existing_user_var/2 as DECIMAL)
10211020
NULL
10221021
create table t (d decimal(0,10));
10231022
ERROR 42000: For float(M,D), double(M,D) or decimal(M,D), M must be >= D (column 'd').
1023+
create table t1 (c1 decimal(64));
1024+
insert into t1 values(
1025+
89000000000000000000000000000000000000000000000000000000000000000000000000000000000000000);
1026+
Warnings:
1027+
Error 1292 Truncated incorrect DECIMAL value: ''
1028+
Warning 1264 Out of range value adjusted for column 'c1' at row 1
1029+
insert into t1 values(
1030+
99999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999 *
1031+
99999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999);
1032+
Warnings:
1033+
Error 1292 Truncated incorrect DECIMAL value: ''
1034+
Error 1292 Truncated incorrect DECIMAL value: ''
1035+
Error 1292 Truncated incorrect DECIMAL value: ''
1036+
Warning 1264 Out of range value adjusted for column 'c1' at row 1
1037+
insert into t1 values(1e100);
1038+
Warnings:
1039+
Warning 1264 Out of range value adjusted for column 'c1' at row 1
1040+
select * from t1;
1041+
c1
1042+
9999999999999999999999999999999999999999999999999999999999999999
1043+
9999999999999999999999999999999999999999999999999999999999999999
1044+
9999999999999999999999999999999999999999999999999999999999999999
1045+
drop table t1;

mysql-test/t/type_newdecimal.test

+14
Original file line numberDiff line numberDiff line change
@@ -1050,3 +1050,17 @@ select cast(@non_existing_user_var/2 as DECIMAL);
10501050
#
10511051
--error 1427
10521052
create table t (d decimal(0,10));
1053+
1054+
#
1055+
# Bug #13573 (Wrong data inserted for too big values)
1056+
#
1057+
1058+
create table t1 (c1 decimal(64));
1059+
insert into t1 values(
1060+
89000000000000000000000000000000000000000000000000000000000000000000000000000000000000000);
1061+
insert into t1 values(
1062+
99999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999 *
1063+
99999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999);
1064+
insert into t1 values(1e100);
1065+
select * from t1;
1066+
drop table t1;

sql/item_func.cc

+14-15
Original file line numberDiff line numberDiff line change
@@ -972,8 +972,8 @@ my_decimal *Item_func_plus::decimal_op(my_decimal *decimal_value)
972972
return 0;
973973
val2= args[1]->val_decimal(&value2);
974974
if (!(null_value= (args[1]->null_value ||
975-
my_decimal_add(E_DEC_FATAL_ERROR, decimal_value, val1,
976-
val2) > 1)))
975+
(my_decimal_add(E_DEC_FATAL_ERROR, decimal_value, val1,
976+
val2) > 3))))
977977
return decimal_value;
978978
return 0;
979979
}
@@ -1045,8 +1045,8 @@ my_decimal *Item_func_minus::decimal_op(my_decimal *decimal_value)
10451045
return 0;
10461046
val2= args[1]->val_decimal(&value2);
10471047
if (!(null_value= (args[1]->null_value ||
1048-
my_decimal_sub(E_DEC_FATAL_ERROR, decimal_value, val1,
1049-
val2) > 1)))
1048+
(my_decimal_sub(E_DEC_FATAL_ERROR, decimal_value, val1,
1049+
val2) > 3))))
10501050
return decimal_value;
10511051
return 0;
10521052
}
@@ -1083,8 +1083,8 @@ my_decimal *Item_func_mul::decimal_op(my_decimal *decimal_value)
10831083
return 0;
10841084
val2= args[1]->val_decimal(&value2);
10851085
if (!(null_value= (args[1]->null_value ||
1086-
my_decimal_mul(E_DEC_FATAL_ERROR, decimal_value, val1,
1087-
val2) > 1)))
1086+
(my_decimal_mul(E_DEC_FATAL_ERROR, decimal_value, val1,
1087+
val2) > 3))))
10881088
return decimal_value;
10891089
return 0;
10901090
}
@@ -1124,24 +1124,23 @@ my_decimal *Item_func_div::decimal_op(my_decimal *decimal_value)
11241124
{
11251125
my_decimal value1, *val1;
11261126
my_decimal value2, *val2;
1127+
int err;
11271128

11281129
val1= args[0]->val_decimal(&value1);
11291130
if ((null_value= args[0]->null_value))
11301131
return 0;
11311132
val2= args[1]->val_decimal(&value2);
11321133
if ((null_value= args[1]->null_value))
11331134
return 0;
1134-
switch (my_decimal_div(E_DEC_FATAL_ERROR & ~E_DEC_DIV_ZERO, decimal_value,
1135-
val1, val2, prec_increment)) {
1136-
case E_DEC_TRUNCATED:
1137-
case E_DEC_OK:
1138-
return decimal_value;
1139-
case E_DEC_DIV_ZERO:
1140-
signal_divide_by_null();
1141-
default:
1142-
null_value= 1; // Safety
1135+
if ((err= my_decimal_div(E_DEC_FATAL_ERROR & ~E_DEC_DIV_ZERO, decimal_value,
1136+
val1, val2, prec_increment)) > 3)
1137+
{
1138+
if (err == E_DEC_DIV_ZERO)
1139+
signal_divide_by_null();
1140+
null_value= 1;
11431141
return 0;
11441142
}
1143+
return decimal_value;
11451144
}
11461145

11471146

sql/my_decimal.cc

+1-1
Original file line numberDiff line numberDiff line change
@@ -185,7 +185,7 @@ int str2my_decimal(uint mask, const char *from, uint length,
185185
}
186186
}
187187
}
188-
check_result(mask, err);
188+
check_result_and_overflow(mask, err, decimal_value);
189189
return err;
190190
}
191191

sql/my_decimal.h

+44-16
Original file line numberDiff line numberDiff line change
@@ -126,13 +126,38 @@ inline int decimal_operation_results(int result)
126126
}
127127
#endif /*MYSQL_CLIENT*/
128128

129+
inline
130+
void max_my_decimal(my_decimal *to, int precision, int frac)
131+
{
132+
DBUG_ASSERT((precision <= DECIMAL_MAX_PRECISION)&&
133+
(frac <= DECIMAL_MAX_SCALE));
134+
max_decimal(precision, frac, (decimal_t*) to);
135+
}
136+
137+
inline void max_internal_decimal(my_decimal *to)
138+
{
139+
max_my_decimal(to, DECIMAL_MAX_PRECISION, 0);
140+
}
141+
129142
inline int check_result(uint mask, int result)
130143
{
131144
if (result & mask)
132145
decimal_operation_results(result);
133146
return result;
134147
}
135148

149+
inline int check_result_and_overflow(uint mask, int result, my_decimal *val)
150+
{
151+
if (check_result(mask, result) & E_DEC_OVERFLOW)
152+
{
153+
bool sign= val->sign();
154+
val->fix_buffer_pointer();
155+
max_internal_decimal(val);
156+
val->sign(sign);
157+
}
158+
return result;
159+
}
160+
136161
inline uint my_decimal_length_to_precision(uint length, uint scale,
137162
bool unsigned_flag)
138163
{
@@ -256,7 +281,8 @@ int my_decimal2double(uint mask, const my_decimal *d, double *result)
256281
inline
257282
int str2my_decimal(uint mask, const char *str, my_decimal *d, char **end)
258283
{
259-
return check_result(mask, string2decimal(str, (decimal_t*) d, end));
284+
return check_result_and_overflow(mask, string2decimal(str,(decimal_t*)d,end),
285+
d);
260286
}
261287

262288

@@ -274,7 +300,7 @@ int string2my_decimal(uint mask, const String *str, my_decimal *d)
274300
inline
275301
int double2my_decimal(uint mask, double val, my_decimal *d)
276302
{
277-
return check_result(mask, double2decimal(val, (decimal_t*) d));
303+
return check_result_and_overflow(mask, double2decimal(val, (decimal_t*)d), d);
278304
}
279305

280306

@@ -303,40 +329,50 @@ inline
303329
int my_decimal_add(uint mask, my_decimal *res, const my_decimal *a,
304330
const my_decimal *b)
305331
{
306-
return check_result(mask, decimal_add((decimal_t*) a, (decimal_t*) b, res));
332+
return check_result_and_overflow(mask,
333+
decimal_add((decimal_t*)a,(decimal_t*)b,res),
334+
res);
307335
}
308336

309337

310338
inline
311339
int my_decimal_sub(uint mask, my_decimal *res, const my_decimal *a,
312340
const my_decimal *b)
313341
{
314-
return check_result(mask, decimal_sub((decimal_t*) a, (decimal_t*) b, res));
342+
return check_result_and_overflow(mask,
343+
decimal_sub((decimal_t*)a,(decimal_t*)b,res),
344+
res);
315345
}
316346

317347

318348
inline
319349
int my_decimal_mul(uint mask, my_decimal *res, const my_decimal *a,
320350
const my_decimal *b)
321351
{
322-
return check_result(mask, decimal_mul((decimal_t*) a, (decimal_t*) b, res));
352+
return check_result_and_overflow(mask,
353+
decimal_mul((decimal_t*)a,(decimal_t*)b,res),
354+
res);
323355
}
324356

325357

326358
inline
327359
int my_decimal_div(uint mask, my_decimal *res, const my_decimal *a,
328360
const my_decimal *b, int div_scale_inc)
329361
{
330-
return check_result(mask, decimal_div((decimal_t*) a, (decimal_t*) b, res,
331-
div_scale_inc));
362+
return check_result_and_overflow(mask,
363+
decimal_div((decimal_t*)a,(decimal_t*)b,res,
364+
div_scale_inc),
365+
res);
332366
}
333367

334368

335369
inline
336370
int my_decimal_mod(uint mask, my_decimal *res, const my_decimal *a,
337371
const my_decimal *b)
338372
{
339-
return check_result(mask, decimal_mod((decimal_t*) a, (decimal_t*) b, res));
373+
return check_result_and_overflow(mask,
374+
decimal_mod((decimal_t*)a,(decimal_t*)b,res),
375+
res);
340376
}
341377

342378

@@ -347,13 +383,5 @@ int my_decimal_cmp(const my_decimal *a, const my_decimal *b)
347383
return decimal_cmp((decimal_t*) a, (decimal_t*) b);
348384
}
349385

350-
inline
351-
void max_my_decimal(my_decimal *to, int precision, int frac)
352-
{
353-
DBUG_ASSERT((precision <= DECIMAL_MAX_PRECISION)&&
354-
(frac <= DECIMAL_MAX_SCALE));
355-
max_decimal(precision, frac, (decimal_t*) to);
356-
}
357-
358386
#endif /*my_decimal_h*/
359387

strings/decimal.c

+4
Original file line numberDiff line numberDiff line change
@@ -1986,7 +1986,11 @@ int decimal_mul(decimal_t *from1, decimal_t *from2, decimal_t *to)
19861986
carry+=hi;
19871987
}
19881988
for (; carry; buf0--)
1989+
{
1990+
if (buf0 < to->buf)
1991+
return E_DEC_OVERFLOW;
19891992
ADD(*buf0, *buf0, 0, carry);
1993+
}
19901994
}
19911995

19921996
/* Now we have to check for -0.000 case */

0 commit comments

Comments
 (0)