summaryrefslogtreecommitdiff
path: root/sql/item_func.cc
diff options
context:
space:
mode:
authorOleksandr Byelkin <sanja@mariadb.com>2020-08-04 17:24:15 +0200
committerOleksandr Byelkin <sanja@mariadb.com>2020-08-04 17:24:15 +0200
commit48b5777ebda9bf14c60ad05298dac67933e9799f (patch)
tree2c023b5cc7811faea8a9b4ad82998e4624c29068 /sql/item_func.cc
parentbbd70fcc43cc889e4593594ee5ca436fe1433aac (diff)
parent9a156e1a23046ba3e37bdb1e4e1ad887d3f5829b (diff)
downloadmariadb-git-48b5777ebda9bf14c60ad05298dac67933e9799f.tar.gz
Merge branch '10.4' into 10.5
Diffstat (limited to 'sql/item_func.cc')
-rw-r--r--sql/item_func.cc95
1 files changed, 50 insertions, 45 deletions
diff --git a/sql/item_func.cc b/sql/item_func.cc
index 813927df32b..dc1de8a8e9f 100644
--- a/sql/item_func.cc
+++ b/sql/item_func.cc
@@ -525,7 +525,7 @@ Item *Item_func::transform(THD *thd, Item_transformer transformer, uchar *argume
callback functions.
First the function applies the analyzer to the root node of
- the Item_func object. Then if the analizer succeeeds (returns TRUE)
+ the Item_func object. Then if the analyzer succeeds (returns TRUE)
the function recursively applies the compile method to each argument
of the Item_func node.
If the call of the method for an argument item returns a new item
@@ -1493,13 +1493,14 @@ double Item_func_div::real_op()
my_decimal *Item_func_div::decimal_op(my_decimal *decimal_value)
{
int err;
+ my_decimal tmp;
VDec2_lazy val(args[0], args[1]);
if ((null_value= val.has_null()))
return 0;
if ((err= check_decimal_overflow(my_decimal_div(E_DEC_FATAL_ERROR &
~E_DEC_OVERFLOW &
~E_DEC_DIV_ZERO,
- decimal_value,
+ &tmp,
val.m_a.ptr(), val.m_b.ptr(),
prec_increment))) > 3)
{
@@ -1508,6 +1509,7 @@ my_decimal *Item_func_div::decimal_op(my_decimal *decimal_value)
null_value= 1;
return 0;
}
+ tmp.round_to(decimal_value, decimals, HALF_UP);
return decimal_value;
}
@@ -1564,7 +1566,7 @@ bool Item_func_div::fix_length_and_dec()
DBUG_ENTER("Item_func_div::fix_length_and_dec");
DBUG_PRINT("info", ("name %s", func_name()));
prec_increment= current_thd->variables.div_precincrement;
- maybe_null= 1; // devision by zero
+ maybe_null= 1; // division by zero
const Type_aggregator *aggregator= &type_handler_data->m_type_aggregator_for_div;
DBUG_EXECUTE_IF("num_op", aggregator= &type_handler_data->m_type_aggregator_non_commutative_test;);
@@ -2516,6 +2518,20 @@ void Item_func_round::fix_arg_datetime()
}
+bool Item_func_round::test_if_length_can_increase()
+{
+ if (truncate)
+ return false;
+ if (args[1]->const_item() && !args[1]->is_expensive())
+ {
+ // Length can increase in some cases: e.g. ROUND(9,-1) -> 10.
+ Longlong_hybrid val1= args[1]->to_longlong_hybrid();
+ return !args[1]->null_value && val1.neg();
+ }
+ return true; // ROUND(x,n), where n is not a constant.
+}
+
+
/**
Calculate data type and attributes for INT-alike input.
@@ -2534,52 +2550,41 @@ void Item_func_round::fix_arg_datetime()
simple cases.
*/
void Item_func_round::fix_arg_int(const Type_handler *preferred,
- const Type_std_attributes *preferred_attrs)
+ const Type_std_attributes *preferred_attrs,
+ bool use_decimal_on_length_increase)
{
DBUG_ASSERT(args[0]->decimals == 0);
- if (args[1]->const_item())
+
+ Type_std_attributes::set(preferred_attrs);
+ if (!test_if_length_can_increase())
{
- Longlong_hybrid val1= args[1]->to_longlong_hybrid();
- if (args[1]->null_value)
- fix_length_and_dec_double(NOT_FIXED_DEC);
- else if ((!val1.to_uint(DECIMAL_MAX_SCALE) && truncate) ||
- args[0]->decimal_precision() < DECIMAL_LONGLONG_DIGITS)
- {
- // Here we can keep INT_RESULT
- // Length can increase in some cases: ROUND(9,-1) -> 10
- int length_can_increase= MY_TEST(!truncate && val1.neg());
- if (preferred)
- {
- Type_std_attributes::set(preferred_attrs);
- if (!length_can_increase)
- {
- // Preserve the exact data type and attributes
- set_handler(preferred);
- }
- else
- {
- max_length++;
- set_handler(type_handler_long_or_longlong());
- }
- }
- else
- {
- /*
- This branch is currently used for hex hybrid only.
- It's known to be unsigned. So sign length is 0.
- */
- DBUG_ASSERT(args[0]->unsigned_flag); // no needs to add sign length
- max_length= args[0]->decimal_precision() + length_can_increase;
- unsigned_flag= true;
- decimals= 0;
- set_handler(type_handler_long_or_longlong());
- }
- }
+ // Preserve the exact data type and attributes
+ set_handler(preferred);
+ }
+ else
+ {
+ max_length++;
+ if (use_decimal_on_length_increase)
+ set_handler(&type_handler_newdecimal);
else
- fix_length_and_dec_decimal(val1.to_uint(DECIMAL_MAX_SCALE));
+ set_handler(type_handler_long_or_longlong());
}
+}
+
+
+void Item_func_round::fix_arg_hex_hybrid()
+{
+ DBUG_ASSERT(args[0]->decimals == 0);
+ DBUG_ASSERT(args[0]->decimal_precision() < DECIMAL_LONGLONG_DIGITS);
+ DBUG_ASSERT(args[0]->unsigned_flag); // no needs to add sign length
+ bool length_can_increase= test_if_length_can_increase();
+ max_length= args[0]->decimal_precision() + MY_TEST(length_can_increase);
+ unsigned_flag= true;
+ decimals= 0;
+ if (length_can_increase && args[0]->max_length >= 8)
+ set_handler(&type_handler_newdecimal);
else
- fix_length_and_dec_double(args[0]->decimals);
+ set_handler(type_handler_long_or_longlong());
}
@@ -4812,7 +4817,7 @@ bool Item_func_set_user_var::register_field_in_bitmap(void *arg)
@param type type of new value
@param cs charset info for new value
@param dv derivation for new value
- @param unsigned_arg indiates if a value of type INT_RESULT is unsigned
+ @param unsigned_arg indicates if a value of type INT_RESULT is unsigned
@note Sets error and fatal error if allocation fails.
@@ -6750,7 +6755,7 @@ Item_func_sp::fix_fields(THD *thd, Item **ref)
/*
Here we check privileges of the stored routine only during view
creation, in order to validate the view. A runtime check is
- perfomed in Item_func_sp::execute(), and this method is not
+ performed in Item_func_sp::execute(), and this method is not
called during context analysis. Notice, that during view
creation we do not infer into stored routine bodies and do not
check privileges of its statements, which would probably be a