summaryrefslogtreecommitdiff
path: root/sql/item.cc
diff options
context:
space:
mode:
authorGeorgi Kodinov <kgeorge@mysql.com>2008-07-30 14:07:37 +0300
committerGeorgi Kodinov <kgeorge@mysql.com>2008-07-30 14:07:37 +0300
commitae4a35fd5cba393f5e924241b21a7a59fc921b15 (patch)
tree9a3ca37f325646d96b550afd705ade75dc8b3d5e /sql/item.cc
parent7f615b2c14d3c8d7b7fbd777faa0adeba9a35fdc (diff)
downloadmariadb-git-ae4a35fd5cba393f5e924241b21a7a59fc921b15.tar.gz
Bug#37662 nested if() inside sum() is parsed in exponential time
min() and max() functions are implemented in MySQL as macros. This means that max(a,b) is expanded to: ((a) > (b) ? (a) : (b)) Note how 'a' is quoted two times. Now imagine 'a' is a recursive function call that's several 10s of levels deep. And the recursive function does max() with a function arg as well to dive into recursion. This means that simple function call can take most of the clock time. Identified and fixed several such calls to max()/min() : including the IF() sql function implementation. mysql-test/r/func_if.result: Bug#37662 test case mysql-test/t/func_if.test: Bug#37662 test case sql/item.cc: Bug#37662 don't call expensive functions as arguments to min/max sql/item_cmpfunc.cc: Bug#37662 don't call expensive functions as arguments to min/max sql/item_func.cc: Bug#37662 don't call expensive functions as arguments to min/max
Diffstat (limited to 'sql/item.cc')
-rw-r--r--sql/item.cc12
1 files changed, 8 insertions, 4 deletions
diff --git a/sql/item.cc b/sql/item.cc
index bf447581afa..a5c88f55487 100644
--- a/sql/item.cc
+++ b/sql/item.cc
@@ -429,8 +429,11 @@ uint Item::decimal_precision() const
Item_result restype= result_type();
if ((restype == DECIMAL_RESULT) || (restype == INT_RESULT))
- return min(my_decimal_length_to_precision(max_length, decimals, unsigned_flag),
- DECIMAL_MAX_PRECISION);
+ {
+ uint prec=
+ my_decimal_length_to_precision(max_length, decimals, unsigned_flag);
+ return min(prec, DECIMAL_MAX_PRECISION);
+ }
return min(max_length, DECIMAL_MAX_PRECISION);
}
@@ -6838,8 +6841,9 @@ bool Item_type_holder::join_types(THD *thd, Item *item)
if (Field::result_merge_type(fld_type) == DECIMAL_RESULT)
{
decimals= min(max(decimals, item->decimals), DECIMAL_MAX_SCALE);
- int precision= min(max(prev_decimal_int_part, item->decimal_int_part())
- + decimals, DECIMAL_MAX_PRECISION);
+ int item_int_part= item->decimal_int_part();
+ int item_prec = max(prev_decimal_int_part, item_int_part) + decimals;
+ int precision= min(item_prec, DECIMAL_MAX_PRECISION);
unsigned_flag&= item->unsigned_flag;
max_length= my_decimal_precision_to_length(precision, decimals,
unsigned_flag);