diff options
author | Georgi Kodinov <kgeorge@mysql.com> | 2008-07-30 14:07:37 +0300 |
---|---|---|
committer | Georgi Kodinov <kgeorge@mysql.com> | 2008-07-30 14:07:37 +0300 |
commit | ae4a35fd5cba393f5e924241b21a7a59fc921b15 (patch) | |
tree | 9a3ca37f325646d96b550afd705ade75dc8b3d5e /sql/item.cc | |
parent | 7f615b2c14d3c8d7b7fbd777faa0adeba9a35fdc (diff) | |
download | mariadb-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.cc | 12 |
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); |