Backport for "MDEV-17698 MEMORY engine performance regression"
Also, backporting a part of: MDEV-11485 Split Item_func_between::val_int() into virtual methods in Type_handler for easier merge to 10.3.
This commit is contained in:
parent
b68d8a05d3
commit
7f175595c8
@ -794,6 +794,10 @@ public:
|
|||||||
If value is not null null_value flag will be reset to FALSE.
|
If value is not null null_value flag will be reset to FALSE.
|
||||||
*/
|
*/
|
||||||
virtual longlong val_int()=0;
|
virtual longlong val_int()=0;
|
||||||
|
Longlong_hybrid to_longlong_hybrid()
|
||||||
|
{
|
||||||
|
return Longlong_hybrid(val_int(), unsigned_flag);
|
||||||
|
}
|
||||||
/*
|
/*
|
||||||
This is just a shortcut to avoid the cast. You should still use
|
This is just a shortcut to avoid the cast. You should still use
|
||||||
unsigned_flag to check the sign of the item.
|
unsigned_flag to check the sign of the item.
|
||||||
|
@ -158,7 +158,10 @@ static int cmp_row_type(Item* item1, Item* item2)
|
|||||||
0 otherwise
|
0 otherwise
|
||||||
*/
|
*/
|
||||||
|
|
||||||
static int agg_cmp_type(Item_result *type, Item **items, uint nitems)
|
static int agg_cmp_type(Item_result *type,
|
||||||
|
Item **items,
|
||||||
|
uint nitems,
|
||||||
|
bool int_uint_as_dec)
|
||||||
{
|
{
|
||||||
uint unsigned_count= items[0]->unsigned_flag;
|
uint unsigned_count= items[0]->unsigned_flag;
|
||||||
type[0]= items[0]->cmp_type();
|
type[0]= items[0]->cmp_type();
|
||||||
@ -180,7 +183,9 @@ static int agg_cmp_type(Item_result *type, Item **items, uint nitems)
|
|||||||
If all arguments are of INT type but have different unsigned_flag values,
|
If all arguments are of INT type but have different unsigned_flag values,
|
||||||
switch to DECIMAL_RESULT.
|
switch to DECIMAL_RESULT.
|
||||||
*/
|
*/
|
||||||
if (type[0] == INT_RESULT && unsigned_count != nitems && unsigned_count != 0)
|
if (int_uint_as_dec &&
|
||||||
|
type[0] == INT_RESULT &&
|
||||||
|
unsigned_count != nitems && unsigned_count != 0)
|
||||||
type[0]= DECIMAL_RESULT;
|
type[0]= DECIMAL_RESULT;
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
@ -2295,7 +2300,7 @@ void Item_func_between::fix_length_and_dec()
|
|||||||
*/
|
*/
|
||||||
if (!args[0] || !args[1] || !args[2])
|
if (!args[0] || !args[1] || !args[2])
|
||||||
return;
|
return;
|
||||||
if ( agg_cmp_type(&cmp_type, args, 3))
|
if (agg_cmp_type(&cmp_type, args, 3, false))
|
||||||
return;
|
return;
|
||||||
if (cmp_type == STRING_RESULT &&
|
if (cmp_type == STRING_RESULT &&
|
||||||
agg_arg_charsets_for_comparison(cmp_collation, args, 3))
|
agg_arg_charsets_for_comparison(cmp_collation, args, 3))
|
||||||
@ -2329,6 +2334,97 @@ void Item_func_between::fix_length_and_dec()
|
|||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
longlong Item_func_between::val_int_cmp_string()
|
||||||
|
{
|
||||||
|
String *value,*a,*b;
|
||||||
|
value=args[0]->val_str(&value0);
|
||||||
|
if ((null_value=args[0]->null_value))
|
||||||
|
return 0;
|
||||||
|
a= args[1]->val_str(&value1);
|
||||||
|
b= args[2]->val_str(&value2);
|
||||||
|
if (!args[1]->null_value && !args[2]->null_value)
|
||||||
|
return (longlong) ((sortcmp(value,a,cmp_collation.collation) >= 0 &&
|
||||||
|
sortcmp(value,b,cmp_collation.collation) <= 0) !=
|
||||||
|
negated);
|
||||||
|
if (args[1]->null_value && args[2]->null_value)
|
||||||
|
null_value= true;
|
||||||
|
else if (args[1]->null_value)
|
||||||
|
{
|
||||||
|
// Set to not null if false range.
|
||||||
|
null_value= sortcmp(value,b,cmp_collation.collation) <= 0;
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
// Set to not null if false range.
|
||||||
|
null_value= sortcmp(value,a,cmp_collation.collation) >= 0;
|
||||||
|
}
|
||||||
|
return (longlong) (!null_value && negated);
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
longlong Item_func_between::val_int_cmp_int()
|
||||||
|
{
|
||||||
|
Longlong_hybrid value= args[0]->to_longlong_hybrid();
|
||||||
|
if ((null_value= args[0]->null_value))
|
||||||
|
return 0; /* purecov: inspected */
|
||||||
|
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.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.cmp(b) <= 0; // not null if false range.
|
||||||
|
else
|
||||||
|
null_value= value.cmp(a) >= 0;
|
||||||
|
return (longlong) (!null_value && negated);
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
longlong Item_func_between::val_int_cmp_decimal()
|
||||||
|
{
|
||||||
|
my_decimal dec_buf, *dec= args[0]->val_decimal(&dec_buf),
|
||||||
|
a_buf, *a_dec, b_buf, *b_dec;
|
||||||
|
if ((null_value=args[0]->null_value))
|
||||||
|
return 0; /* purecov: inspected */
|
||||||
|
a_dec= args[1]->val_decimal(&a_buf);
|
||||||
|
b_dec= args[2]->val_decimal(&b_buf);
|
||||||
|
if (!args[1]->null_value && !args[2]->null_value)
|
||||||
|
return (longlong) ((my_decimal_cmp(dec, a_dec) >= 0 &&
|
||||||
|
my_decimal_cmp(dec, b_dec) <= 0) != negated);
|
||||||
|
if (args[1]->null_value && args[2]->null_value)
|
||||||
|
null_value= true;
|
||||||
|
else if (args[1]->null_value)
|
||||||
|
null_value= (my_decimal_cmp(dec, b_dec) <= 0);
|
||||||
|
else
|
||||||
|
null_value= (my_decimal_cmp(dec, a_dec) >= 0);
|
||||||
|
return (longlong) (!null_value && negated);
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
longlong Item_func_between::val_int_cmp_real()
|
||||||
|
{
|
||||||
|
double value= args[0]->val_real(),a,b;
|
||||||
|
if ((null_value=args[0]->null_value))
|
||||||
|
return 0; /* purecov: inspected */
|
||||||
|
a= args[1]->val_real();
|
||||||
|
b= args[2]->val_real();
|
||||||
|
if (!args[1]->null_value && !args[2]->null_value)
|
||||||
|
return (longlong) ((value >= a && value <= b) != 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.
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
null_value= value >= a;
|
||||||
|
}
|
||||||
|
return (longlong) (!null_value && negated);
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
longlong Item_func_between::val_int()
|
longlong Item_func_between::val_int()
|
||||||
{
|
{
|
||||||
DBUG_ASSERT(fixed == 1);
|
DBUG_ASSERT(fixed == 1);
|
||||||
@ -2370,94 +2466,14 @@ longlong Item_func_between::val_int()
|
|||||||
null_value= value >= a;
|
null_value= value >= a;
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
|
|
||||||
case STRING_RESULT:
|
case STRING_RESULT:
|
||||||
{
|
return val_int_cmp_string();
|
||||||
String *value,*a,*b;
|
|
||||||
value=args[0]->val_str(&value0);
|
|
||||||
if ((null_value=args[0]->null_value))
|
|
||||||
return 0;
|
|
||||||
a=args[1]->val_str(&value1);
|
|
||||||
b=args[2]->val_str(&value2);
|
|
||||||
if (!args[1]->null_value && !args[2]->null_value)
|
|
||||||
return (longlong) ((sortcmp(value,a,cmp_collation.collation) >= 0 &&
|
|
||||||
sortcmp(value,b,cmp_collation.collation) <= 0) !=
|
|
||||||
negated);
|
|
||||||
if (args[1]->null_value && args[2]->null_value)
|
|
||||||
null_value=1;
|
|
||||||
else if (args[1]->null_value)
|
|
||||||
{
|
|
||||||
// Set to not null if false range.
|
|
||||||
null_value= sortcmp(value,b,cmp_collation.collation) <= 0;
|
|
||||||
}
|
|
||||||
else
|
|
||||||
{
|
|
||||||
// Set to not null if false range.
|
|
||||||
null_value= sortcmp(value,a,cmp_collation.collation) >= 0;
|
|
||||||
}
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
case INT_RESULT:
|
case INT_RESULT:
|
||||||
{
|
return val_int_cmp_int();
|
||||||
longlong value=args[0]->val_int(), a, b;
|
|
||||||
if ((null_value=args[0]->null_value))
|
|
||||||
return 0; /* purecov: inspected */
|
|
||||||
a=args[1]->val_int();
|
|
||||||
b=args[2]->val_int();
|
|
||||||
if (!args[1]->null_value && !args[2]->null_value)
|
|
||||||
return (longlong) ((value >= a && value <= b) != negated);
|
|
||||||
if (args[1]->null_value && args[2]->null_value)
|
|
||||||
null_value=1;
|
|
||||||
else if (args[1]->null_value)
|
|
||||||
{
|
|
||||||
null_value= value <= b; // not null if false range.
|
|
||||||
}
|
|
||||||
else
|
|
||||||
{
|
|
||||||
null_value= value >= a;
|
|
||||||
}
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
case DECIMAL_RESULT:
|
case DECIMAL_RESULT:
|
||||||
{
|
return val_int_cmp_decimal();
|
||||||
my_decimal dec_buf, *dec= args[0]->val_decimal(&dec_buf),
|
|
||||||
a_buf, *a_dec, b_buf, *b_dec;
|
|
||||||
if ((null_value=args[0]->null_value))
|
|
||||||
return 0; /* purecov: inspected */
|
|
||||||
a_dec= args[1]->val_decimal(&a_buf);
|
|
||||||
b_dec= args[2]->val_decimal(&b_buf);
|
|
||||||
if (!args[1]->null_value && !args[2]->null_value)
|
|
||||||
return (longlong) ((my_decimal_cmp(dec, a_dec) >= 0 &&
|
|
||||||
my_decimal_cmp(dec, b_dec) <= 0) != negated);
|
|
||||||
if (args[1]->null_value && args[2]->null_value)
|
|
||||||
null_value=1;
|
|
||||||
else if (args[1]->null_value)
|
|
||||||
null_value= (my_decimal_cmp(dec, b_dec) <= 0);
|
|
||||||
else
|
|
||||||
null_value= (my_decimal_cmp(dec, a_dec) >= 0);
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
case REAL_RESULT:
|
case REAL_RESULT:
|
||||||
{
|
return val_int_cmp_real();
|
||||||
double value= args[0]->val_real(),a,b;
|
|
||||||
if ((null_value=args[0]->null_value))
|
|
||||||
return 0; /* purecov: inspected */
|
|
||||||
a= args[1]->val_real();
|
|
||||||
b= args[2]->val_real();
|
|
||||||
if (!args[1]->null_value && !args[2]->null_value)
|
|
||||||
return (longlong) ((value >= a && value <= b) != negated);
|
|
||||||
if (args[1]->null_value && args[2]->null_value)
|
|
||||||
null_value=1;
|
|
||||||
else if (args[1]->null_value)
|
|
||||||
{
|
|
||||||
null_value= value <= b; // not null if false range.
|
|
||||||
}
|
|
||||||
else
|
|
||||||
{
|
|
||||||
null_value= value >= a;
|
|
||||||
}
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
case ROW_RESULT:
|
case ROW_RESULT:
|
||||||
case IMPOSSIBLE_RESULT:
|
case IMPOSSIBLE_RESULT:
|
||||||
DBUG_ASSERT(0);
|
DBUG_ASSERT(0);
|
||||||
|
@ -694,6 +694,11 @@ public:
|
|||||||
bool eval_not_null_tables(uchar *opt_arg);
|
bool eval_not_null_tables(uchar *opt_arg);
|
||||||
void fix_after_pullout(st_select_lex *new_parent, Item **ref);
|
void fix_after_pullout(st_select_lex *new_parent, Item **ref);
|
||||||
bool count_sargable_conds(uchar *arg);
|
bool count_sargable_conds(uchar *arg);
|
||||||
|
|
||||||
|
longlong val_int_cmp_string();
|
||||||
|
longlong val_int_cmp_int();
|
||||||
|
longlong val_int_cmp_real();
|
||||||
|
longlong val_int_cmp_decimal();
|
||||||
};
|
};
|
||||||
|
|
||||||
|
|
||||||
|
@ -24,12 +24,25 @@ class Longlong_hybrid
|
|||||||
protected:
|
protected:
|
||||||
longlong m_value;
|
longlong m_value;
|
||||||
bool m_unsigned;
|
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:
|
public:
|
||||||
Longlong_hybrid(longlong nr, bool unsigned_flag)
|
Longlong_hybrid(longlong nr, bool unsigned_flag)
|
||||||
:m_value(nr), m_unsigned(unsigned_flag)
|
:m_value(nr), m_unsigned(unsigned_flag)
|
||||||
{ }
|
{ }
|
||||||
longlong value() const { return m_value; }
|
longlong value() const { return m_value; }
|
||||||
bool is_unsigned() const { return m_unsigned; }
|
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; }
|
bool neg() const { return m_value < 0 && !m_unsigned; }
|
||||||
ulonglong abs() const
|
ulonglong abs() const
|
||||||
{
|
{
|
||||||
@ -39,6 +52,21 @@ public:
|
|||||||
return ((ulonglong) LONGLONG_MAX) + 1;
|
return ((ulonglong) LONGLONG_MAX) + 1;
|
||||||
return m_value < 0 ? -m_value : m_value;
|
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
|
#endif // SQL_TYPE_INT_INCLUDED
|
||||||
|
Loading…
x
Reference in New Issue
Block a user