Commit 45769429 authored by Alexander Barkov's avatar Alexander Barkov

MDEV-17698 MEMORY engine performance regression

parent f7184777
......@@ -1028,6 +1028,10 @@ class Item: public Value_source,
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
......
......@@ -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);
}
......
......@@ -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 @@ class Longlong_hybrid
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
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment