diff options
author | Alexander Barkov <bar@mariadb.com> | 2018-11-15 06:35:37 +0400 |
---|---|---|
committer | Alexander Barkov <bar@mariadb.com> | 2018-11-15 06:35:37 +0400 |
commit | 7f175595c83b3ef55d6aa00cc7707ec565398bf5 (patch) | |
tree | f38b02fdd380103d281fac6923371f0c47693a92 /sql/item_cmpfunc.cc | |
parent | b68d8a05d326bed43aefa73d717c0307278ca6bb (diff) | |
download | mariadb-git-7f175595c83b3ef55d6aa00cc7707ec565398bf5.tar.gz |
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.
Diffstat (limited to 'sql/item_cmpfunc.cc')
-rw-r--r-- | sql/item_cmpfunc.cc | 190 |
1 files changed, 103 insertions, 87 deletions
diff --git a/sql/item_cmpfunc.cc b/sql/item_cmpfunc.cc index d4a2c767b15..3af79c23ee7 100644 --- a/sql/item_cmpfunc.cc +++ b/sql/item_cmpfunc.cc @@ -158,7 +158,10 @@ static int cmp_row_type(Item* item1, Item* item2) 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; 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, 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; return 0; } @@ -2295,7 +2300,7 @@ void Item_func_between::fix_length_and_dec() */ if (!args[0] || !args[1] || !args[2]) return; - if ( agg_cmp_type(&cmp_type, args, 3)) + if (agg_cmp_type(&cmp_type, args, 3, false)) return; if (cmp_type == STRING_RESULT && 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() { DBUG_ASSERT(fixed == 1); @@ -2370,94 +2466,14 @@ longlong Item_func_between::val_int() null_value= value >= a; break; } - case STRING_RESULT: - { - 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; - } + return val_int_cmp_string(); case INT_RESULT: - { - 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; - } + return val_int_cmp_int(); case DECIMAL_RESULT: - { - 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; - } + return val_int_cmp_decimal(); case REAL_RESULT: - { - 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; - } + return val_int_cmp_real(); case ROW_RESULT: case IMPOSSIBLE_RESULT: DBUG_ASSERT(0); |