diff options
author | Alexander Barkov <bar@mariadb.com> | 2018-11-14 13:55:05 +0400 |
---|---|---|
committer | Alexander Barkov <bar@mariadb.com> | 2018-11-14 13:56:18 +0400 |
commit | 45769429d9a3bfa37ead21aa0d36214f980a00d7 (patch) | |
tree | 4d5f351088880b443b11f13f81209fc433c1784c /sql | |
parent | f718477714aedd9fd598990169db6f512c9cae64 (diff) | |
download | mariadb-git-45769429d9a3bfa37ead21aa0d36214f980a00d7.tar.gz |
MDEV-17698 MEMORY engine performance regression
Diffstat (limited to 'sql')
-rw-r--r-- | sql/item.h | 4 | ||||
-rw-r--r-- | sql/item_cmpfunc.cc | 18 | ||||
-rw-r--r-- | sql/sql_type_int.h | 28 |
3 files changed, 39 insertions, 11 deletions
diff --git a/sql/item.h b/sql/item.h index d743cf6c19c..6bb97d3c3a3 100644 --- a/sql/item.h +++ b/sql/item.h @@ -1028,6 +1028,10 @@ public: If value is not null null_value flag will be reset to FALSE. */ virtual longlong val_int()=0; + Longlong_hybrid to_longlong_hybrid() + { + return Longlong_hybrid(val_int(), unsigned_flag); + } /** Get a value for CAST(x AS SIGNED). Too large positive unsigned integer values are converted diff --git a/sql/item_cmpfunc.cc b/sql/item_cmpfunc.cc index ccbae1bad34..b1f7e54546a 100644 --- a/sql/item_cmpfunc.cc +++ b/sql/item_cmpfunc.cc @@ -2067,7 +2067,7 @@ bool Item_func_between::fix_length_and_dec() if (!args[0] || !args[1] || !args[2]) return TRUE; if (m_comparator.aggregate_for_comparison(Item_func_between::func_name(), - args, 3, true)) + args, 3, false)) { DBUG_ASSERT(current_thd->is_error()); return TRUE; @@ -2171,23 +2171,19 @@ longlong Item_func_between::val_int_cmp_string() longlong Item_func_between::val_int_cmp_int() { - longlong value= args[0]->val_int(), a, b; + Longlong_hybrid value= args[0]->to_longlong_hybrid(); if ((null_value= args[0]->null_value)) return 0; /* purecov: inspected */ - a= args[1]->val_int(); - b= args[2]->val_int(); + Longlong_hybrid a= args[1]->to_longlong_hybrid(); + Longlong_hybrid b= args[2]->to_longlong_hybrid(); if (!args[1]->null_value && !args[2]->null_value) - return (longlong) ((value >= a && value <= b) != negated); + return (longlong) ((value.cmp(a) >= 0 && value.cmp(b) <= 0) != negated); if (args[1]->null_value && args[2]->null_value) null_value= true; else if (args[1]->null_value) - { - null_value= value <= b; // not null if false range. - } + null_value= value.cmp(b) <= 0; // not null if false range. else - { - null_value= value >= a; - } + null_value= value.cmp(a) >= 0; return (longlong) (!null_value && negated); } diff --git a/sql/sql_type_int.h b/sql/sql_type_int.h index 1eda5651df5..7433bd5249f 100644 --- a/sql/sql_type_int.h +++ b/sql/sql_type_int.h @@ -24,12 +24,25 @@ class Longlong_hybrid protected: longlong m_value; bool m_unsigned; + int cmp_signed(const Longlong_hybrid& other) const + { + return m_value < other.m_value ? -1 : m_value == other.m_value ? 0 : 1; + } + int cmp_unsigned(const Longlong_hybrid& other) const + { + return (ulonglong) m_value < (ulonglong) other.m_value ? -1 : + m_value == other.m_value ? 0 : 1; + } public: Longlong_hybrid(longlong nr, bool unsigned_flag) :m_value(nr), m_unsigned(unsigned_flag) { } longlong value() const { return m_value; } bool is_unsigned() const { return m_unsigned; } + bool is_unsigned_outside_of_signed_range() const + { + return m_unsigned && ((ulonglong) m_value) > (ulonglong) LONGLONG_MAX; + } bool neg() const { return m_value < 0 && !m_unsigned; } ulonglong abs() const { @@ -39,6 +52,21 @@ public: return ((ulonglong) LONGLONG_MAX) + 1; return m_value < 0 ? -m_value : m_value; } + int cmp(const Longlong_hybrid& other) const + { + if (m_unsigned == other.m_unsigned) + return m_unsigned ? cmp_unsigned(other) : cmp_signed(other); + if (is_unsigned_outside_of_signed_range()) + return 1; + if (other.is_unsigned_outside_of_signed_range()) + return -1; + /* + The unsigned argument is in the range 0..LONGLONG_MAX. + The signed argument is in the range LONGLONG_MIN..LONGLONG_MAX. + Safe to compare as signed. + */ + return cmp_signed(other); + } }; #endif // SQL_TYPE_INT_INCLUDED |