diff options
author | Alexey Kopytov <Alexey.Kopytov@Sun.com> | 2010-03-18 13:38:29 +0300 |
---|---|---|
committer | Alexey Kopytov <Alexey.Kopytov@Sun.com> | 2010-03-18 13:38:29 +0300 |
commit | 2acfdc50929dda084cdad96e4208c1dd6f26e183 (patch) | |
tree | b9789210c6251e842ccc7cee877d0f3ffa2b0887 /sql/item_func.h | |
parent | d1ad316a59b6bd48dec94433ffe982ddfc376e35 (diff) | |
download | mariadb-git-2acfdc50929dda084cdad96e4208c1dd6f26e183.tar.gz |
Bug #8433: Overflow must be an error
All numeric operators and functions on integer, floating point
and DECIMAL values now throw an 'out of range' error rather
than returning an incorrect value or NULL, when the result is
out of supported range for the corresponding data type.
Some test cases in the test suite had to be updated
accordingly either because the test case itself relied on a
value returned in case of a numeric overflow, or because a
numeric overflow was the root cause of the corresponding bugs.
The latter tests are no longer relevant, since the expressions
used to trigger the corresponding bugs are not valid anymore.
However, such test cases have been adjusted and kept "for the
record".
mysql-test/r/func_math.result:
Added test cases for bug #8433.
Updated results of the test case for bug #31236.
mysql-test/r/func_misc.result:
Streamlined test cases.
mysql-test/r/func_test.result:
Streamlined test cases.
mysql-test/r/select.result:
Streamlined test cases.
mysql-test/r/sp.result:
Streamlined test cases.
mysql-test/r/strict.result:
Streamlined test cases.
mysql-test/r/type_newdecimal.result:
Streamlined test cases.
mysql-test/suite/sys_vars/r/sql_slave_skip_counter_basic.result:
Streamlined test cases.
mysql-test/suite/sys_vars/t/sql_slave_skip_counter_basic.test:
Streamlined test cases.
mysql-test/t/func_math.test:
Added test cases for bug #8433.
Updated results of the test case for bug #31236.
mysql-test/t/func_misc.test:
Streamlined test cases.
mysql-test/t/func_test.test:
Streamlined test cases.
mysql-test/t/select.test:
Streamlined test cases.
mysql-test/t/sp.test:
Streamlined test cases.
mysql-test/t/strict.test:
Streamlined test cases.
mysql-test/t/type_newdecimal.test:
Streamlined test cases.
sql/item_create.cc:
Changed Item_func_cot() to be defined as a standalone Item
rather than a combination of "1 / TAN(x)".
sql/item_func.cc:
Throw an 'out of range' error rather than returning an
incorrect value or NULL, when the result of a numeric
operator or a function is out of supported range for
the corresponding data type.
sql/item_func.h:
Added validation helpers as inline methods of Item_func.
sql/share/errmsg-utf8.txt:
New ER_DATA_OUT_OF_RANGE error.
Diffstat (limited to 'sql/item_func.h')
-rw-r--r-- | sql/item_func.h | 59 |
1 files changed, 55 insertions, 4 deletions
diff --git a/sql/item_func.h b/sql/item_func.h index 6bfdae8d56d..2edb0ad41e3 100644 --- a/sql/item_func.h +++ b/sql/item_func.h @@ -185,13 +185,56 @@ public: void * arg, traverse_order order); bool is_expensive_processor(uchar *arg); virtual bool is_expensive() { return 0; } - inline double fix_result(double value) + inline void raise_numeric_overflow(const char *type_name) { - if (isfinite(value)) - return value; - null_value=1; + char buf[256]; + String str(buf, sizeof(buf), system_charset_info); + str.length(0); + print(&str, QT_ORDINARY); + my_error(ER_DATA_OUT_OF_RANGE, MYF(0), type_name, str.c_ptr_safe()); + } + inline double raise_float_overflow() + { + raise_numeric_overflow("DOUBLE"); return 0.0; } + inline longlong raise_integer_overflow() + { + raise_numeric_overflow(unsigned_flag ? "BIGINT UNSIGNED": "BIGINT"); + return 0; + } + inline int raise_decimal_overflow() + { + raise_numeric_overflow("DECIMAL"); + return E_DEC_OVERFLOW; + } + /** + Throw an error if the input double number is not finite, i.e. is either + +/-INF or NAN. + */ + inline double check_float_overflow(double value) + { + return isfinite(value) ? value : raise_float_overflow(); + } + /** + Throw an error if the input BIGINT value represented by the + (longlong value, bool unsigned flag) pair cannot be returned by the + function, i.e. is not compatible with this Item's unsigned_flag. + */ + inline longlong check_integer_overflow(longlong value, bool val_unsigned) + { + if ((unsigned_flag && !val_unsigned && value < 0) || + (!unsigned_flag && val_unsigned && (ulonglong) value > LONGLONG_MAX)) + return raise_integer_overflow(); + return value; + } + /** + Throw an error if the error code of a DECIMAL operation is E_DEC_OVERFLOW. + */ + inline int check_decimal_overflow(int error) + { + return (error == E_DEC_OVERFLOW) ? raise_decimal_overflow() : error; + } bool has_timestamp_args() { DBUG_ASSERT(fixed == TRUE); @@ -658,6 +701,14 @@ public: const char *func_name() const { return "tan"; } }; +class Item_func_cot :public Item_dec_func +{ +public: + Item_func_cot(Item *a) :Item_dec_func(a) {} + double val_real(); + const char *func_name() const { return "cot"; } +}; + class Item_func_integer :public Item_int_func { public: |