summaryrefslogtreecommitdiff
path: root/sql/item_func.cc
diff options
context:
space:
mode:
Diffstat (limited to 'sql/item_func.cc')
-rw-r--r--sql/item_func.cc823
1 files changed, 450 insertions, 373 deletions
diff --git a/sql/item_func.cc b/sql/item_func.cc
index b8355a38701..1660652001c 100644
--- a/sql/item_func.cc
+++ b/sql/item_func.cc
@@ -134,7 +134,7 @@ void Item_func::sync_with_sum_func_and_with_field(List<Item> &list)
Item *item;
while ((item= li++))
{
- with_sum_func|= item->with_sum_func;
+ join_with_sum_func(item);
with_window_func|= item->with_window_func;
with_field|= item->with_field;
with_param|= item->with_param;
@@ -356,7 +356,7 @@ Item_func::fix_fields(THD *thd, Item **ref)
if (item->maybe_null)
maybe_null=1;
- with_sum_func= with_sum_func || item->with_sum_func;
+ join_with_sum_func(item);
with_param= with_param || item->with_param;
with_window_func= with_window_func || item->with_window_func;
with_field= with_field || item->with_field;
@@ -381,7 +381,7 @@ Item_func::quick_fix_field()
{
for (arg=args, arg_end=args+arg_count; arg != arg_end ; arg++)
{
- if (!(*arg)->fixed)
+ if (!(*arg)->is_fixed())
(*arg)->quick_fix_field();
}
}
@@ -732,7 +732,7 @@ void Item_func::signal_divide_by_null()
Item *Item_func::get_tmp_table_item(THD *thd)
{
- if (!with_sum_func && !const_item())
+ if (!Item_func::with_sum_func() && !const_item())
return new (thd->mem_root) Item_temptable_field(thd, result_field);
return copy_or_same(thd);
}
@@ -804,51 +804,6 @@ bool Item_func_plus::fix_length_and_dec(void)
}
-String *Item_func_hybrid_field_type::val_str_from_decimal_op(String *str)
-{
- my_decimal decimal_value, *val;
- if (!(val= decimal_op_with_null_check(&decimal_value)))
- return 0; // null is set
- DBUG_ASSERT(!null_value);
- my_decimal_round(E_DEC_FATAL_ERROR, val, decimals, FALSE, val);
- str->set_charset(collation.collation);
- my_decimal2string(E_DEC_FATAL_ERROR, val, 0, 0, 0, str);
- return str;
-}
-
-double Item_func_hybrid_field_type::val_real_from_decimal_op()
-{
- my_decimal decimal_value, *val;
- if (!(val= decimal_op_with_null_check(&decimal_value)))
- return 0.0; // null is set
- double result;
- my_decimal2double(E_DEC_FATAL_ERROR, val, &result);
- return result;
-}
-
-longlong Item_func_hybrid_field_type::val_int_from_decimal_op()
-{
- my_decimal decimal_value, *val;
- if (!(val= decimal_op_with_null_check(&decimal_value)))
- return 0; // null is set
- longlong result;
- my_decimal2int(E_DEC_FATAL_ERROR, val, unsigned_flag, &result);
- return result;
-}
-
-bool Item_func_hybrid_field_type::get_date_from_decimal_op(MYSQL_TIME *ltime,
- ulonglong fuzzydate)
-{
- my_decimal value, *res;
- if (!(res= decimal_op_with_null_check(&value)) ||
- decimal_to_datetime_with_warn(res, ltime, fuzzydate,
- field_table_or_null(),
- field_name_or_null()))
- return make_zero_mysql_time(ltime, fuzzydate);
- return (null_value= 0);
-}
-
-
String *Item_func_hybrid_field_type::val_str_from_int_op(String *str)
{
longlong nr= int_op();
@@ -874,19 +829,6 @@ Item_func_hybrid_field_type::val_decimal_from_int_op(my_decimal *dec)
return dec;
}
-bool Item_func_hybrid_field_type::get_date_from_int_op(MYSQL_TIME *ltime,
- ulonglong fuzzydate)
-{
- longlong value= int_op();
- bool neg= !unsigned_flag && value < 0;
- if (null_value || int_to_datetime_with_warn(neg, neg ? -value : value,
- ltime, fuzzydate,
- field_table_or_null(),
- field_name_or_null()))
- return make_zero_mysql_time(ltime, fuzzydate);
- return (null_value= 0);
-}
-
String *Item_func_hybrid_field_type::val_str_from_real_op(String *str)
{
@@ -912,22 +854,11 @@ Item_func_hybrid_field_type::val_decimal_from_real_op(my_decimal *dec)
return dec;
}
-bool Item_func_hybrid_field_type::get_date_from_real_op(MYSQL_TIME *ltime,
- ulonglong fuzzydate)
-{
- double value= real_op();
- if (null_value || double_to_datetime_with_warn(value, ltime, fuzzydate,
- field_table_or_null(),
- field_name_or_null()))
- return make_zero_mysql_time(ltime, fuzzydate);
- return (null_value= 0);
-}
-
String *Item_func_hybrid_field_type::val_str_from_date_op(String *str)
{
MYSQL_TIME ltime;
- if (date_op_with_null_check(&ltime) ||
+ if (date_op_with_null_check(current_thd, &ltime) ||
(null_value= str->alloc(MAX_DATE_STRING_REP_LENGTH)))
return (String *) 0;
str->length(my_TIME_to_str(&ltime, const_cast<char*>(str->ptr()), decimals));
@@ -939,7 +870,7 @@ String *Item_func_hybrid_field_type::val_str_from_date_op(String *str)
double Item_func_hybrid_field_type::val_real_from_date_op()
{
MYSQL_TIME ltime;
- if (date_op_with_null_check(&ltime))
+ if (date_op_with_null_check(current_thd, &ltime))
return 0;
return TIME_to_double(&ltime);
}
@@ -947,7 +878,7 @@ double Item_func_hybrid_field_type::val_real_from_date_op()
longlong Item_func_hybrid_field_type::val_int_from_date_op()
{
MYSQL_TIME ltime;
- if (date_op_with_null_check(&ltime))
+ if (date_op_with_null_check(current_thd, &ltime))
return 0;
return TIME_to_ulonglong(&ltime);
}
@@ -956,7 +887,7 @@ my_decimal *
Item_func_hybrid_field_type::val_decimal_from_date_op(my_decimal *dec)
{
MYSQL_TIME ltime;
- if (date_op_with_null_check(&ltime))
+ if (date_op_with_null_check(current_thd, &ltime))
{
my_decimal_set_zero(dec);
return 0;
@@ -968,7 +899,7 @@ Item_func_hybrid_field_type::val_decimal_from_date_op(my_decimal *dec)
String *Item_func_hybrid_field_type::val_str_from_time_op(String *str)
{
MYSQL_TIME ltime;
- if (time_op_with_null_check(&ltime) ||
+ if (time_op_with_null_check(current_thd, &ltime) ||
(null_value= my_TIME_to_str(&ltime, str, decimals)))
return NULL;
return str;
@@ -977,20 +908,22 @@ String *Item_func_hybrid_field_type::val_str_from_time_op(String *str)
double Item_func_hybrid_field_type::val_real_from_time_op()
{
MYSQL_TIME ltime;
- return time_op_with_null_check(&ltime) ? 0 : TIME_to_double(&ltime);
+ return time_op_with_null_check(current_thd, &ltime) ? 0 :
+ TIME_to_double(&ltime);
}
longlong Item_func_hybrid_field_type::val_int_from_time_op()
{
MYSQL_TIME ltime;
- return time_op_with_null_check(&ltime) ? 0 : TIME_to_ulonglong(&ltime);
+ return time_op_with_null_check(current_thd, &ltime) ? 0 :
+ TIME_to_ulonglong(&ltime);
}
my_decimal *
Item_func_hybrid_field_type::val_decimal_from_time_op(my_decimal *dec)
{
MYSQL_TIME ltime;
- if (time_op_with_null_check(&ltime))
+ if (time_op_with_null_check(current_thd, &ltime))
{
my_decimal_set_zero(dec);
return 0;
@@ -1018,18 +951,6 @@ Item_func_hybrid_field_type::val_decimal_from_str_op(my_decimal *decimal_value)
return res ? decimal_from_string_with_check(decimal_value, res) : 0;
}
-bool Item_func_hybrid_field_type::get_date_from_str_op(MYSQL_TIME *ltime,
- ulonglong fuzzydate)
-{
- StringBuffer<40> tmp;
- String *res;
- if (!(res= str_op_with_null_check(&tmp)) ||
- str_to_datetime_with_warn(res->charset(), res->ptr(), res->length(),
- ltime, fuzzydate))
- return make_zero_mysql_time(ltime, fuzzydate);
- return (null_value= 0);
-}
-
void Item_func_signed::print(String *str, enum_query_type query_type)
{
@@ -1049,47 +970,15 @@ void Item_func_unsigned::print(String *str, enum_query_type query_type)
}
-String *Item_decimal_typecast::val_str(String *str)
-{
- my_decimal tmp_buf, *tmp= val_decimal(&tmp_buf);
- if (null_value)
- return NULL;
- my_decimal2string(E_DEC_FATAL_ERROR, tmp, 0, 0, 0, str);
- return str;
-}
-
-
-double Item_decimal_typecast::val_real()
-{
- my_decimal tmp_buf, *tmp= val_decimal(&tmp_buf);
- double res;
- if (null_value)
- return 0.0;
- my_decimal2double(E_DEC_FATAL_ERROR, tmp, &res);
- return res;
-}
-
-
-longlong Item_decimal_typecast::val_int()
-{
- my_decimal tmp_buf, *tmp= val_decimal(&tmp_buf);
- longlong res;
- if (null_value)
- return 0;
- my_decimal2int(E_DEC_FATAL_ERROR, tmp, unsigned_flag, &res);
- return res;
-}
-
-
my_decimal *Item_decimal_typecast::val_decimal(my_decimal *dec)
{
- my_decimal tmp_buf, *tmp= args[0]->val_decimal(&tmp_buf);
+ VDec tmp(args[0]);
bool sign;
uint precision;
- if ((null_value= args[0]->null_value))
+ if ((null_value= tmp.is_null()))
return NULL;
- my_decimal_round(E_DEC_FATAL_ERROR, tmp, decimals, FALSE, dec);
+ tmp.round_to(dec, decimals, HALF_UP);
sign= dec->sign();
if (unsigned_flag)
{
@@ -1206,17 +1095,20 @@ double Item_func_plus::real_op()
return check_float_overflow(value);
}
+#if defined(__powerpc64__) && GCC_VERSION >= 6003 && GCC_VERSION <= 10002
+#pragma GCC push_options
+#pragma GCC optimize ("no-expensive-optimizations")
+#endif
longlong Item_func_plus::int_op()
{
longlong val0= args[0]->val_int();
longlong val1= args[1]->val_int();
- longlong res= val0 + val1;
bool res_unsigned= FALSE;
+ longlong res;
if ((null_value= args[0]->null_value || args[1]->null_value))
return 0;
-
/*
First check whether the result can be represented as a
(bool unsigned_flag, longlong value) pair, then check if it is compatible
@@ -1257,16 +1149,29 @@ longlong Item_func_plus::int_op()
{
if (val0 >=0 && val1 >= 0)
res_unsigned= TRUE;
- else if (val0 < 0 && val1 < 0 && res >= 0)
+ else if (val0 < 0 && val1 < 0 && val0 < (LONGLONG_MIN - val1))
goto err;
}
}
+
+#ifndef WITH_UBSAN
+ res= val0 + val1;
+#else
+ if (res_unsigned)
+ res= (longlong) ((ulonglong) val0 + (ulonglong) val1);
+ else
+ res= val0+val1;
+#endif /* WITH_UBSAN */
+
return check_integer_overflow(res, res_unsigned);
err:
return raise_integer_overflow();
}
+#if defined(__powerpc64__) && GCC_VERSION >= 6003 && GCC_VERSION <= 10002
+#pragma GCC pop_options
+#endif
/**
Calculate plus of two decimals.
@@ -1281,17 +1186,13 @@ err:
my_decimal *Item_func_plus::decimal_op(my_decimal *decimal_value)
{
- my_decimal value1, *val1;
- my_decimal value2, *val2;
- val1= args[0]->val_decimal(&value1);
- if ((null_value= args[0]->null_value))
- return 0;
- val2= args[1]->val_decimal(&value2);
- if (!(null_value= (args[1]->null_value ||
+ VDec2_lazy val(args[0], args[1]);
+ if (!(null_value= (val.has_null() ||
check_decimal_overflow(my_decimal_add(E_DEC_FATAL_ERROR &
~E_DEC_OVERFLOW,
decimal_value,
- val1, val2)) > 3)))
+ val.m_a.ptr(),
+ val.m_b.ptr())) > 3)))
return decimal_value;
return 0;
}
@@ -1363,12 +1264,17 @@ double Item_func_minus::real_op()
}
+#if defined(__powerpc64__) && GCC_VERSION >= 6003 && GCC_VERSION <= 10002
+#pragma GCC push_options
+#pragma GCC optimize ("no-expensive-optimizations")
+#endif
+
longlong Item_func_minus::int_op()
{
longlong val0= args[0]->val_int();
longlong val1= args[1]->val_int();
- longlong res= val0 - val1;
bool res_unsigned= FALSE;
+ longlong res;
if ((null_value= args[0]->null_value || args[1]->null_value))
return 0;
@@ -1383,12 +1289,8 @@ longlong Item_func_minus::int_op()
if (args[1]->unsigned_flag)
{
if ((ulonglong) val0 < (ulonglong) val1)
- {
- if (res >= 0)
- goto err;
- }
- else
- res_unsigned= TRUE;
+ goto err;
+ res_unsigned= TRUE;
}
else
{
@@ -1409,23 +1311,35 @@ longlong Item_func_minus::int_op()
{
if (args[1]->unsigned_flag)
{
- if ((ulonglong) (val0 - LONGLONG_MIN) < (ulonglong) val1)
+ if (((ulonglong) val0 - (ulonglong) LONGLONG_MIN) < (ulonglong) val1)
goto err;
}
else
{
if (val0 > 0 && val1 < 0)
res_unsigned= TRUE;
- else if (val0 < 0 && val1 > 0 && res >= 0)
+ else if (val0 < 0 && val1 > 0 && val0 < (LONGLONG_MIN + val1))
goto err;
}
}
+#ifndef WITH_UBSAN
+ res= val0 - val1;
+#else
+ if (res_unsigned)
+ res= (longlong) ((ulonglong) val0 - (ulonglong) val1);
+ else
+ res= val0 - val1;
+#endif /* WITH_UBSAN */
+
return check_integer_overflow(res, res_unsigned);
err:
return raise_integer_overflow();
}
+#if defined(__powerpc64__) && GCC_VERSION >= 6003 && GCC_VERSION <= 10002
+#pragma GCC pop_options
+#endif
/**
See Item_func_plus::decimal_op for comments.
@@ -1433,18 +1347,13 @@ err:
my_decimal *Item_func_minus::decimal_op(my_decimal *decimal_value)
{
- my_decimal value1, *val1;
- my_decimal value2, *val2=
-
- val1= args[0]->val_decimal(&value1);
- if ((null_value= args[0]->null_value))
- return 0;
- val2= args[1]->val_decimal(&value2);
- if (!(null_value= (args[1]->null_value ||
- (check_decimal_overflow(my_decimal_sub(E_DEC_FATAL_ERROR &
- ~E_DEC_OVERFLOW,
- decimal_value, val1,
- val2)) > 3))))
+ VDec2_lazy val(args[0], args[1]);
+ if (!(null_value= (val.has_null() ||
+ check_decimal_overflow(my_decimal_sub(E_DEC_FATAL_ERROR &
+ ~E_DEC_OVERFLOW,
+ decimal_value,
+ val.m_a.ptr(),
+ val.m_b.ptr())) > 3)))
return decimal_value;
return 0;
}
@@ -1543,17 +1452,13 @@ err:
my_decimal *Item_func_mul::decimal_op(my_decimal *decimal_value)
{
- my_decimal value1, *val1;
- my_decimal value2, *val2;
- val1= args[0]->val_decimal(&value1);
- if ((null_value= args[0]->null_value))
- return 0;
- val2= args[1]->val_decimal(&value2);
- if (!(null_value= (args[1]->null_value ||
- (check_decimal_overflow(my_decimal_mul(E_DEC_FATAL_ERROR &
- ~E_DEC_OVERFLOW,
- decimal_value, val1,
- val2)) > 3))))
+ VDec2_lazy val(args[0], args[1]);
+ if (!(null_value= (val.has_null() ||
+ check_decimal_overflow(my_decimal_mul(E_DEC_FATAL_ERROR &
+ ~E_DEC_OVERFLOW,
+ decimal_value,
+ val.m_a.ptr(),
+ val.m_b.ptr())) > 3)))
return decimal_value;
return 0;
}
@@ -1604,21 +1509,15 @@ double Item_func_div::real_op()
my_decimal *Item_func_div::decimal_op(my_decimal *decimal_value)
{
- my_decimal value1, *val1;
- my_decimal value2, *val2;
int err;
-
- val1= args[0]->val_decimal(&value1);
- if ((null_value= args[0]->null_value))
- return 0;
- val2= args[1]->val_decimal(&value2);
- if ((null_value= args[1]->null_value))
+ 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,
- val1, val2,
+ val.m_a.ptr(), val.m_b.ptr(),
prec_increment))) > 3)
{
if (err == E_DEC_DIV_ZERO)
@@ -1708,20 +1607,14 @@ longlong Item_func_int_div::val_int()
if (args[0]->result_type() != INT_RESULT ||
args[1]->result_type() != INT_RESULT)
{
- my_decimal tmp;
- my_decimal *val0p= args[0]->val_decimal(&tmp);
- if ((null_value= args[0]->null_value))
+ VDec2_lazy val(args[0], args[1]);
+ if ((null_value= val.has_null()))
return 0;
- my_decimal val0= *val0p;
-
- my_decimal *val1p= args[1]->val_decimal(&tmp);
- if ((null_value= args[1]->null_value))
- return 0;
- my_decimal val1= *val1p;
int err;
+ my_decimal tmp;
if ((err= my_decimal_div(E_DEC_FATAL_ERROR & ~E_DEC_DIV_ZERO, &tmp,
- &val0, &val1, 0)) > 3)
+ val.m_a.ptr(), val.m_b.ptr(), 0)) > 3)
{
if (err == E_DEC_DIV_ZERO)
signal_divide_by_null();
@@ -1729,8 +1622,7 @@ longlong Item_func_int_div::val_int()
}
my_decimal truncated;
- const bool do_truncate= true;
- if (my_decimal_round(E_DEC_FATAL_ERROR, &tmp, 0, do_truncate, &truncated))
+ if (tmp.round_to(&truncated, 0, TRUNCATE))
DBUG_ASSERT(false);
longlong res;
@@ -1815,17 +1707,11 @@ double Item_func_mod::real_op()
my_decimal *Item_func_mod::decimal_op(my_decimal *decimal_value)
{
- my_decimal value1, *val1;
- my_decimal value2, *val2;
-
- val1= args[0]->val_decimal(&value1);
- if ((null_value= args[0]->null_value))
- return 0;
- val2= args[1]->val_decimal(&value2);
- if ((null_value= args[1]->null_value))
+ VDec2_lazy val(args[0], args[1]);
+ if ((null_value= val.has_null()))
return 0;
switch (my_decimal_mod(E_DEC_FATAL_ERROR & ~E_DEC_DIV_ZERO, decimal_value,
- val1, val2)) {
+ val.m_a.ptr(), val.m_b.ptr())) {
case E_DEC_TRUNCATED:
case E_DEC_OK:
return decimal_value;
@@ -1865,6 +1751,46 @@ bool Item_func_mod::fix_length_and_dec()
DBUG_RETURN(FALSE);
}
+static void calc_hash_for_unique(ulong &nr1, ulong &nr2, String *str)
+{
+ CHARSET_INFO *cs;
+ uchar l[4];
+ int4store(l, str->length());
+ cs= str->charset();
+ cs->coll->hash_sort(cs, l, sizeof(l), &nr1, &nr2);
+ cs= str->charset();
+ cs->coll->hash_sort(cs, (uchar *)str->ptr(), str->length(), &nr1, &nr2);
+}
+
+longlong Item_func_hash::val_int()
+{
+ DBUG_EXECUTE_IF("same_long_unique_hash", return 9;);
+ unsigned_flag= true;
+ ulong nr1= 1,nr2= 4;
+ String * str;
+ for(uint i= 0;i<arg_count;i++)
+ {
+ str = args[i]->val_str();
+ if(args[i]->null_value)
+ {
+ null_value= 1;
+ return 0;
+ }
+ calc_hash_for_unique(nr1, nr2, str);
+ }
+ null_value= 0;
+ return (longlong)nr1;
+}
+
+
+bool Item_func_hash::fix_length_and_dec()
+{
+ decimals= 0;
+ max_length= 8;
+ return false;
+}
+
+
double Item_func_neg::real_op()
{
@@ -1898,10 +1824,10 @@ longlong Item_func_neg::int_op()
my_decimal *Item_func_neg::decimal_op(my_decimal *decimal_value)
{
- my_decimal val, *value= args[0]->val_decimal(&val);
- if (!(null_value= args[0]->null_value))
+ VDec value(args[0]);
+ if (!(null_value= value.is_null()))
{
- my_decimal2decimal(value, decimal_value);
+ my_decimal2decimal(value.ptr(), decimal_value);
my_decimal_neg(decimal_value);
return decimal_value;
}
@@ -1925,7 +1851,7 @@ void Item_func_neg::fix_length_and_dec_int()
longlong val= args[0]->val_int();
if ((ulonglong) val >= (ulonglong) LONGLONG_MIN &&
((ulonglong) val != (ulonglong) LONGLONG_MIN ||
- args[0]->type() != INT_ITEM))
+ !args[0]->is_of_type(CONST_ITEM, INT_RESULT)))
{
/*
Ensure that result is converted to DECIMAL, as longlong can't hold
@@ -1996,10 +1922,10 @@ longlong Item_func_abs::int_op()
my_decimal *Item_func_abs::decimal_op(my_decimal *decimal_value)
{
- my_decimal val, *value= args[0]->val_decimal(&val);
- if (!(null_value= args[0]->null_value))
+ VDec value(args[0]);
+ if (!(null_value= value.is_null()))
{
- my_decimal2decimal(value, decimal_value);
+ my_decimal2decimal(value.ptr(), decimal_value);
if (decimal_value->sign())
my_decimal_neg(decimal_value);
return decimal_value;
@@ -2233,31 +2159,29 @@ double Item_func_cot::val_real()
longlong Item_func_shift_left::val_int()
{
DBUG_ASSERT(fixed == 1);
- uint shift;
- ulonglong res= ((ulonglong) args[0]->val_int() <<
- (shift=(uint) args[1]->val_int()));
+ uint shift= (uint) args[1]->val_int();
+ ulonglong value= args[0]->val_int();
if (args[0]->null_value || args[1]->null_value)
{
null_value=1;
return 0;
}
null_value=0;
- return (shift < sizeof(longlong)*8 ? (longlong) res : 0);
+ return (shift < sizeof(longlong)*8 ? (value << shift) : 0);
}
longlong Item_func_shift_right::val_int()
{
DBUG_ASSERT(fixed == 1);
- uint shift;
- ulonglong res= (ulonglong) args[0]->val_int() >>
- (shift=(uint) args[1]->val_int());
+ uint shift= (uint) args[1]->val_int();
+ ulonglong value= args[0]->val_int();
if (args[0]->null_value || args[1]->null_value)
{
null_value=1;
return 0;
}
null_value=0;
- return (shift < sizeof(longlong)*8 ? (longlong) res : 0);
+ return (shift < sizeof(longlong)*8 ? (value >> shift) : 0);
}
@@ -2275,35 +2199,64 @@ longlong Item_func_bit_neg::val_int()
void Item_func_int_val::fix_length_and_dec_int_or_decimal()
{
+ DBUG_ASSERT(args[0]->cmp_type() == DECIMAL_RESULT);
+ DBUG_ASSERT(args[0]->max_length <= DECIMAL_MAX_STR_LENGTH);
/*
- The INT branch of this code should be revised.
- It creates too large data types, e.g.
- CREATE OR REPLACE TABLE t2 AS SELECT FLOOR(9999999.999) AS fa;
- results in a BININT(10) column, while INT(7) should probably be enough.
+ FLOOR() for negative numbers can increase length: floor(-9.9) -> -10
+ CEILING() for positive numbers can increase length: ceil(9.9) -> 10
*/
- ulonglong tmp_max_length= (ulonglong ) args[0]->max_length -
- (args[0]->decimals ? args[0]->decimals + 1 : 0) + 2;
- max_length= tmp_max_length > (ulonglong) UINT_MAX32 ?
- (uint32) UINT_MAX32 : (uint32) tmp_max_length;
- uint tmp= float_length(decimals);
- set_if_smaller(max_length,tmp);
- decimals= 0;
+ decimal_round_mode mode= round_mode();
+ uint length_increase= args[0]->decimals > 0 &&
+ (mode == CEILING ||
+ (mode == FLOOR && !args[0]->unsigned_flag)) ? 1 : 0;
+ uint precision= args[0]->decimal_int_part() + length_increase;
+ set_if_bigger(precision, 1);
/*
- -2 because in most high position can't be used any digit for longlong
- and one position for increasing value during operation
+ The BIGINT data type can store:
+ UNSIGNED BIGINT: 0..18446744073709551615 - up to 19 digits
+ SIGNED BIGINT: -9223372036854775808..9223372036854775807 - up to 18 digits
+
+ The INT data type can store:
+ UNSIGNED INT: 0..4294967295 - up to 9 digits
+ SIGNED INT: -2147483648..2147483647 - up to 9 digits
*/
- if (args[0]->max_length - args[0]->decimals >= DECIMAL_LONGLONG_DIGITS - 2)
+ if (precision > 18)
{
+ unsigned_flag= args[0]->unsigned_flag;
fix_char_length(
- my_decimal_precision_to_length_no_truncation(
- args[0]->decimal_int_part(), 0, false));
+ my_decimal_precision_to_length_no_truncation(precision, 0,
+ unsigned_flag));
set_handler(&type_handler_newdecimal);
}
else
{
- unsigned_flag= args[0]->unsigned_flag;
- set_handler(type_handler_long_or_longlong());
+ uint sign_length= (unsigned_flag= args[0]->unsigned_flag) ? 0 : 1;
+ fix_char_length(precision + sign_length);
+ if (precision > 9)
+ {
+#if MYSQL_VERSION_ID > 100500
+#error Remove the '#else' branch and the conditional compilation
+ if (unsigned_flag)
+ set_handler(&type_handler_ulonglong);
+ else
+ set_handler(&type_handler_slonglong);
+#else
+ set_handler(&type_handler_longlong);
+#endif
+ }
+ else
+ {
+#if MYSQL_VERSION_ID > 100500
+#error Remove the '#else' branch and the conditional compilation
+ if (unsigned_flag)
+ set_handler(&type_handler_ulong);
+ else
+ set_handler(&type_handler_slong);
+#else
+ set_handler(&type_handler_long);
+#endif
+ }
}
}
@@ -2320,35 +2273,29 @@ bool Item_func_int_val::fix_length_and_dec()
{
DBUG_ENTER("Item_func_int_val::fix_length_and_dec");
DBUG_PRINT("info", ("name %s", func_name()));
- if (args[0]->cast_to_int_type_handler()->
- Item_func_int_val_fix_length_and_dec(this))
+ /*
+ We don't want to translate ENUM/SET to CHAR here.
+ So let's call real_type_handler(), not type_handler().
+ */
+ if (args[0]->real_type_handler()->Item_func_int_val_fix_length_and_dec(this))
DBUG_RETURN(TRUE);
- DBUG_PRINT("info", ("Type: %s", type_handler()->name().ptr()));
+ DBUG_PRINT("info", ("Type: %s", real_type_handler()->name().ptr()));
DBUG_RETURN(FALSE);
}
longlong Item_func_ceiling::int_op()
{
- longlong result;
switch (args[0]->result_type()) {
+ case STRING_RESULT: // hex hybrid
case INT_RESULT:
- result= args[0]->val_int();
- null_value= args[0]->null_value;
- break;
+ return val_int_from_item(args[0]);
case DECIMAL_RESULT:
- {
- my_decimal dec_buf, *dec;
- if ((dec= Item_func_ceiling::decimal_op(&dec_buf)))
- my_decimal2int(E_DEC_FATAL_ERROR, dec, unsigned_flag, &result);
- else
- result= 0;
+ return VDec_op(this).to_longlong(unsigned_flag);
+ default:
break;
}
- default:
- result= (longlong)Item_func_ceiling::real_op();
- };
- return result;
+ return (longlong) Item_func_ceiling::real_op();
}
@@ -2366,36 +2313,52 @@ double Item_func_ceiling::real_op()
my_decimal *Item_func_ceiling::decimal_op(my_decimal *decimal_value)
{
- my_decimal val, *value= args[0]->val_decimal(&val);
- if (!(null_value= (args[0]->null_value ||
- my_decimal_ceiling(E_DEC_FATAL_ERROR, value,
- decimal_value) > 1)))
+ VDec value(args[0]);
+ if (!(null_value= (value.is_null() ||
+ value.round_to(decimal_value, 0, CEILING) > 1)))
return decimal_value;
return 0;
}
+bool Item_func_ceiling::date_op(THD *thd, MYSQL_TIME *to, date_mode_t fuzzydate)
+{
+ Datetime::Options opt(thd, TIME_FRAC_TRUNCATE);
+ Datetime *tm= new (to) Datetime(thd, args[0], opt);
+ tm->ceiling(thd);
+ null_value= !tm->is_valid_datetime();
+ DBUG_ASSERT(maybe_null || !null_value);
+ return null_value;
+}
+
+
+bool Item_func_ceiling::time_op(THD *thd, MYSQL_TIME *to)
+{
+ static const Time::Options_for_round opt;
+ Time *tm= new (to) Time(thd, args[0], opt);
+ tm->ceiling();
+ null_value= !tm->is_valid_time();
+ DBUG_ASSERT(maybe_null || !null_value);
+ return null_value;
+}
+
+
longlong Item_func_floor::int_op()
{
- longlong result;
switch (args[0]->result_type()) {
+ case STRING_RESULT: // hex hybrid
case INT_RESULT:
- result= args[0]->val_int();
- null_value= args[0]->null_value;
- break;
+ return val_int_from_item(args[0]);
case DECIMAL_RESULT:
{
my_decimal dec_buf, *dec;
- if ((dec= Item_func_floor::decimal_op(&dec_buf)))
- my_decimal2int(E_DEC_FATAL_ERROR, dec, unsigned_flag, &result);
- else
- result= 0;
- break;
+ return (!(dec= Item_func_floor::decimal_op(&dec_buf))) ? 0 :
+ dec->to_longlong(unsigned_flag);
}
default:
- result= (longlong)Item_func_floor::real_op();
- };
- return result;
+ break;
+ }
+ return (longlong) Item_func_floor::real_op();
}
@@ -2413,15 +2376,36 @@ double Item_func_floor::real_op()
my_decimal *Item_func_floor::decimal_op(my_decimal *decimal_value)
{
- my_decimal val, *value= args[0]->val_decimal(&val);
- if (!(null_value= (args[0]->null_value ||
- my_decimal_floor(E_DEC_FATAL_ERROR, value,
- decimal_value) > 1)))
+ VDec value(args[0]);
+ if (!(null_value= (value.is_null() ||
+ value.round_to(decimal_value, 0, FLOOR) > 1)))
return decimal_value;
return 0;
}
+bool Item_func_floor::date_op(THD *thd, MYSQL_TIME *to, date_mode_t fuzzydate)
+{
+ // DATETIME is not negative, so FLOOR means just truncation
+ Datetime::Options opt(thd, TIME_FRAC_TRUNCATE);
+ Datetime *tm= new (to) Datetime(thd, args[0], opt, 0);
+ null_value= !tm->is_valid_datetime();
+ DBUG_ASSERT(maybe_null || !null_value);
+ return null_value;
+}
+
+
+bool Item_func_floor::time_op(THD *thd, MYSQL_TIME *to)
+{
+ static const Time::Options_for_round opt;
+ Time *tm= new (to) Time(thd, args[0], opt);
+ tm->floor();
+ null_value= !tm->is_valid_time();
+ DBUG_ASSERT(maybe_null || !null_value);
+ return null_value;
+}
+
+
void Item_func_round::fix_length_and_dec_decimal(uint decimals_to_set)
{
int decimals_delta= args[0]->decimals - decimals_to_set;
@@ -2481,29 +2465,109 @@ void Item_func_round::fix_arg_double()
}
-void Item_func_round::fix_arg_int()
+void Item_func_round::fix_arg_temporal(const Type_handler *h,
+ uint int_part_length)
{
- if (args[1]->const_item())
+ set_handler(h);
+ if (args[1]->const_item() && !args[1]->is_expensive())
{
+ Longlong_hybrid_null dec= args[1]->to_longlong_hybrid_null();
+ fix_attributes_temporal(int_part_length,
+ dec.is_null() ? args[0]->decimals :
+ dec.to_uint(TIME_SECOND_PART_DIGITS));
+ }
+ else
+ fix_attributes_temporal(int_part_length, args[0]->decimals);
+}
+
+
+void Item_func_round::fix_arg_time()
+{
+ fix_arg_temporal(&type_handler_time2, MIN_TIME_WIDTH);
+}
+
+
+void Item_func_round::fix_arg_datetime()
+{
+ /*
+ Day increment operations are not supported for '0000-00-00',
+ see get_date_from_daynr() for details. Therefore, expressions like
+ ROUND('0000-00-00 23:59:59.999999')
+ return NULL.
+ */
+ if (!truncate)
+ maybe_null= true;
+ fix_arg_temporal(&type_handler_datetime2, MAX_DATETIME_WIDTH);
+}
+
+
+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();
- 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)
- {
- // Length can increase in some cases: ROUND(9,-1) -> 10
- int length_can_increase= MY_TEST(!truncate && val1.neg());
- max_length= args[0]->max_length + length_can_increase;
- // Here we can keep INT_RESULT
- unsigned_flag= args[0]->unsigned_flag;
- decimals= 0;
- set_handler(type_handler_long_or_longlong());
- }
+ 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.
+
+ @param [IN] preferred - The preferred data type handler for simple cases
+ such as ROUND(x) and TRUNCATE(x,0), when the input
+ is short enough to fit into an integer type
+ (without extending to DECIMAL).
+ - If `preferred` is not NULL, then the code tries
+ to preserve the given data type handler and
+ the data type attributes `preferred_attrs`.
+ - If `preferred` is NULL, then the code fully
+ calculates attributes using
+ args[0]->decimal_precision() and chooses between
+ INT and BIGINT, depending on attributes.
+ @param [IN] preferred_attrs - The preferred data type attributes for
+ simple cases.
+*/
+void Item_func_round::fix_arg_int(const Type_handler *preferred,
+ const Type_std_attributes *preferred_attrs,
+ bool use_decimal_on_length_increase)
+{
+ DBUG_ASSERT(args[0]->decimals == 0);
+
+ Type_std_attributes::set(preferred_attrs);
+ if (!test_if_length_can_increase())
+ {
+ // 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());
}
@@ -2605,21 +2669,49 @@ longlong Item_func_round::int_op()
my_decimal *Item_func_round::decimal_op(my_decimal *decimal_value)
{
- my_decimal val, *value= args[0]->val_decimal(&val);
+ VDec value(args[0]);
longlong dec= args[1]->val_int();
if (dec >= 0 || args[1]->unsigned_flag)
dec= MY_MIN((ulonglong) dec, decimals);
else if (dec < INT_MIN)
dec= INT_MIN;
- if (!(null_value= (args[0]->null_value || args[1]->null_value ||
- my_decimal_round(E_DEC_FATAL_ERROR, value, (int) dec,
- truncate, decimal_value) > 1)))
+ if (!(null_value= (value.is_null() || args[1]->null_value ||
+ value.round_to(decimal_value, (uint) dec,
+ truncate ? TRUNCATE : HALF_UP) > 1)))
return decimal_value;
return 0;
}
+bool Item_func_round::time_op(THD *thd, MYSQL_TIME *to)
+{
+ DBUG_ASSERT(args[0]->type_handler()->mysql_timestamp_type() ==
+ MYSQL_TIMESTAMP_TIME);
+ Time::Options_for_round opt(truncate ? TIME_FRAC_TRUNCATE : TIME_FRAC_ROUND);
+ Longlong_hybrid_null dec= args[1]->to_longlong_hybrid_null();
+ Time *tm= new (to) Time(thd, args[0], opt,
+ dec.to_uint(TIME_SECOND_PART_DIGITS));
+ null_value= !tm->is_valid_time() || dec.is_null();
+ DBUG_ASSERT(maybe_null || !null_value);
+ return null_value;
+}
+
+
+bool Item_func_round::date_op(THD *thd, MYSQL_TIME *to, date_mode_t fuzzydate)
+{
+ DBUG_ASSERT(args[0]->type_handler()->mysql_timestamp_type() ==
+ MYSQL_TIMESTAMP_DATETIME);
+ Datetime::Options opt(thd, truncate ? TIME_FRAC_TRUNCATE : TIME_FRAC_ROUND);
+ Longlong_hybrid_null dec= args[1]->to_longlong_hybrid_null();
+ Datetime *tm= new (to) Datetime(thd, args[0], opt,
+ dec.to_uint(TIME_SECOND_PART_DIGITS));
+ null_value= !tm->is_valid_datetime() || dec.is_null();
+ DBUG_ASSERT(maybe_null || !null_value);
+ return null_value;
+}
+
+
void Item_func_rand::seed_random(Item *arg)
{
/*
@@ -2633,7 +2725,7 @@ void Item_func_rand::seed_random(Item *arg)
THD *thd= current_thd;
if (WSREP(thd))
{
- if (thd->wsrep_exec_mode==REPL_RECV)
+ if (wsrep_thd_is_applying(thd))
tmp= thd->wsrep_rand;
else
thd->wsrep_rand= tmp;
@@ -2753,14 +2845,15 @@ bool Item_func_min_max::fix_attributes(Item **items, uint nitems)
0 Otherwise
*/
-bool Item_func_min_max::get_date_native(MYSQL_TIME *ltime, ulonglong fuzzy_date)
+bool Item_func_min_max::get_date_native(THD *thd, MYSQL_TIME *ltime,
+ date_mode_t fuzzydate)
{
longlong UNINIT_VAR(min_max);
DBUG_ASSERT(fixed == 1);
for (uint i=0; i < arg_count ; i++)
{
- longlong res= args[i]->val_datetime_packed();
+ longlong res= args[i]->val_datetime_packed(thd);
/* Check if we need to stop (because of error or KILL) and stop the loop */
if (unlikely(args[i]->null_value))
@@ -2771,8 +2864,8 @@ bool Item_func_min_max::get_date_native(MYSQL_TIME *ltime, ulonglong fuzzy_date)
}
unpack_time(min_max, ltime, mysql_timestamp_type());
- if (!(fuzzy_date & TIME_TIME_ONLY) &&
- unlikely((null_value= check_date_with_warn(ltime, fuzzy_date,
+ if (!(fuzzydate & TIME_TIME_ONLY) &&
+ unlikely((null_value= check_date_with_warn(thd, ltime, fuzzydate,
MYSQL_TIMESTAMP_ERROR))))
return true;
@@ -2780,17 +2873,17 @@ bool Item_func_min_max::get_date_native(MYSQL_TIME *ltime, ulonglong fuzzy_date)
}
-bool Item_func_min_max::get_time_native(MYSQL_TIME *ltime)
+bool Item_func_min_max::get_time_native(THD *thd, MYSQL_TIME *ltime)
{
DBUG_ASSERT(fixed == 1);
- Time value(args[0]);
+ Time value(thd, args[0], Time::Options(thd), decimals);
if (!value.is_valid_time())
return (null_value= true);
for (uint i= 1; i < arg_count ; i++)
{
- Time tmp(args[i]);
+ Time tmp(thd, args[i], Time::Options(thd), decimals);
if (!tmp.is_valid_time())
return (null_value= true);
@@ -2904,6 +2997,28 @@ my_decimal *Item_func_min_max::val_decimal_native(my_decimal *dec)
}
+bool Item_func_min_max::val_native(THD *thd, Native *native)
+{
+ DBUG_ASSERT(fixed == 1);
+ const Type_handler *handler= Item_hybrid_func::type_handler();
+ NativeBuffer<STRING_BUFFER_USUAL_SIZE> cur;
+ for (uint i= 0; i < arg_count; i++)
+ {
+ if (val_native_with_conversion_from_item(thd, args[i],
+ i == 0 ? native : &cur,
+ handler))
+ return true;
+ if (i > 0)
+ {
+ int cmp= handler->cmp_native(*native, cur);
+ if ((cmp_sign < 0 ? cmp : -cmp) < 0 && native->copy(cur))
+ return null_value= true;
+ }
+ }
+ return null_value= false;
+}
+
+
longlong Item_func_bit_length::val_int()
{
DBUG_ASSERT(fixed == 1);
@@ -2966,10 +3081,11 @@ longlong Item_func_locate::val_int()
if (arg_count == 3)
{
- start0= start= args[2]->val_int() - 1;
+ start0= start= args[2]->val_int();
- if ((start < 0) || (start > a->length()))
+ if ((start <= 0) || (start > a->length()))
return 0;
+ start0--; start--;
/* start is now sufficiently valid to pass to charpos function */
start= a->charpos((int) start);
@@ -3035,14 +3151,14 @@ longlong Item_func_field::val_int()
}
else if (cmp_type == DECIMAL_RESULT)
{
- my_decimal dec_arg_buf, *dec_arg,
- dec_buf, *dec= args[0]->val_decimal(&dec_buf);
- if (args[0]->null_value)
+ VDec dec(args[0]);
+ if (dec.is_null())
return 0;
+ my_decimal dec_arg_buf;
for (uint i=1; i < arg_count; i++)
{
- dec_arg= args[i]->val_decimal(&dec_arg_buf);
- if (!args[i]->null_value && !my_decimal_cmp(dec_arg, dec))
+ my_decimal *dec_arg= args[i]->val_decimal(&dec_arg_buf);
+ if (!args[i]->null_value && !dec.cmp(dec_arg))
return (longlong) (i);
}
}
@@ -3134,7 +3250,7 @@ bool Item_func_find_in_set::fix_length_and_dec()
find->length(), 0);
enum_bit=0;
if (enum_value)
- enum_bit=1LL << (enum_value-1);
+ enum_bit= 1ULL << (enum_value-1);
}
}
}
@@ -3296,6 +3412,7 @@ udf_handler::fix_fields(THD *thd, Item_func_or_sum *func,
}
uint i;
Item **arg,**arg_end;
+ With_sum_func_cache *with_sum_func_cache= func->get_with_sum_func_cache();
for (i=0, arg=arguments, arg_end=arguments+arg_count;
arg != arg_end ;
arg++,i++)
@@ -3319,7 +3436,8 @@ udf_handler::fix_fields(THD *thd, Item_func_or_sum *func,
func->collation.set(&my_charset_bin);
if (item->maybe_null)
func->maybe_null=1;
- func->with_sum_func= func->with_sum_func || item->with_sum_func;
+ if (with_sum_func_cache)
+ with_sum_func_cache->join_with_sum_func(item);
func->with_window_func= func->with_window_func ||
item->with_window_func;
func->with_field= func->with_field || item->with_field;
@@ -3622,32 +3740,6 @@ String *Item_func_udf_int::val_str(String *str)
}
-longlong Item_func_udf_decimal::val_int()
-{
- my_bool tmp_null_value;
- longlong result;
- my_decimal dec_buf, *dec= udf.val_decimal(&tmp_null_value, &dec_buf);
- null_value= tmp_null_value;
- if (null_value)
- return 0;
- my_decimal2int(E_DEC_FATAL_ERROR, dec, unsigned_flag, &result);
- return result;
-}
-
-
-double Item_func_udf_decimal::val_real()
-{
- my_bool tmp_null_value;
- double result;
- my_decimal dec_buf, *dec= udf.val_decimal(&tmp_null_value, &dec_buf);
- null_value= tmp_null_value;
- if (null_value)
- return 0.0;
- my_decimal2double(E_DEC_FATAL_ERROR, dec, &result);
- return result;
-}
-
-
my_decimal *Item_func_udf_decimal::val_decimal(my_decimal *dec_buf)
{
my_decimal *res;
@@ -3663,21 +3755,6 @@ my_decimal *Item_func_udf_decimal::val_decimal(my_decimal *dec_buf)
}
-String *Item_func_udf_decimal::val_str(String *str)
-{
- my_bool tmp_null_value;
- my_decimal dec_buf, *dec= udf.val_decimal(&tmp_null_value, &dec_buf);
- null_value= tmp_null_value;
- if (null_value)
- return 0;
- if (str->length() < DECIMAL_MAX_STR_LENGTH)
- str->length(DECIMAL_MAX_STR_LENGTH);
- my_decimal_round(E_DEC_FATAL_ERROR, dec, decimals, FALSE, &dec_buf);
- my_decimal2string(E_DEC_FATAL_ERROR, &dec_buf, 0, 0, '0', str);
- return str;
-}
-
-
/* Default max_length is max argument length */
bool Item_func_udf_str::fix_length_and_dec()
@@ -3744,7 +3821,7 @@ longlong Item_master_pos_wait::val_int()
connection_name.length= con->length();
if (check_master_connection_name(&connection_name))
{
- my_error(ER_WRONG_ARGUMENTS, MYF(ME_JUST_WARNING),
+ my_error(ER_WRONG_ARGUMENTS, MYF(ME_WARNING),
"MASTER_CONNECTION_NAME");
goto err;
}
@@ -4457,7 +4534,7 @@ user_var_entry *get_variable(HASH *hash, LEX_CSTRING *name,
if (!my_hash_inited(hash))
return 0;
if (!(entry = (user_var_entry*) my_malloc(size,
- MYF(MY_WME | ME_FATALERROR |
+ MYF(MY_WME | ME_FATAL |
MY_THREAD_SPECIFIC))))
return 0;
entry->name.str=(char*) entry+ ALIGN_SIZE(sizeof(user_var_entry))+
@@ -4712,7 +4789,7 @@ update_hash(user_var_entry *entry, bool set_null, void *ptr, size_t length,
entry->value=0;
entry->value= (char*) my_realloc(entry->value, length,
MYF(MY_ALLOW_ZERO_PTR | MY_WME |
- ME_FATALERROR |
+ ME_FATAL |
MY_THREAD_SPECIFIC));
if (!entry->value)
return 1;
@@ -4778,11 +4855,7 @@ double user_var_entry::val_real(bool *null_value)
case INT_RESULT:
return (double) *(longlong*) value;
case DECIMAL_RESULT:
- {
- double result;
- my_decimal2double(E_DEC_FATAL_ERROR, (my_decimal *)value, &result);
- return result;
- }
+ return ((my_decimal *)value)->to_double();
case STRING_RESULT:
return my_atof(value); // This is null terminated
case ROW_RESULT:
@@ -4807,11 +4880,7 @@ longlong user_var_entry::val_int(bool *null_value) const
case INT_RESULT:
return *(longlong*) value;
case DECIMAL_RESULT:
- {
- longlong result;
- my_decimal2int(E_DEC_FATAL_ERROR, (my_decimal *)value, 0, &result);
- return result;
- }
+ return ((my_decimal *)value)->to_longlong(false);
case STRING_RESULT:
{
int error;
@@ -5548,10 +5617,9 @@ bool Item_func_get_user_var::set_value(THD *thd,
bool Item_user_var_as_out_param::fix_fields(THD *thd, Item **ref)
{
- DBUG_ASSERT(fixed == 0);
+ DBUG_ASSERT(!is_fixed());
DBUG_ASSERT(thd->lex->exchange);
- if (Item::fix_fields(thd, ref) ||
- !(entry= get_variable(&thd->user_vars, &org_name, 1)))
+ if (!(entry= get_variable(&thd->user_vars, &org_name, 1)))
return TRUE;
entry->type= STRING_RESULT;
/*
@@ -5609,7 +5677,8 @@ my_decimal* Item_user_var_as_out_param::val_decimal(my_decimal *decimal_buffer)
}
-bool Item_user_var_as_out_param::get_date(MYSQL_TIME *ltime, ulonglong fuzzy)
+bool Item_user_var_as_out_param::get_date(THD *thd, MYSQL_TIME *ltime,
+ date_mode_t fuzzydate)
{
DBUG_ASSERT(0);
return true;
@@ -5648,7 +5717,7 @@ void Item_func_get_system_var::update_null_value()
THD *thd= current_thd;
int save_no_errors= thd->no_errors;
thd->no_errors= TRUE;
- Item::update_null_value();
+ type_handler()->Item_update_null_value(this);
thd->no_errors= save_no_errors;
}
@@ -6494,7 +6563,7 @@ Item_func_sp::fix_fields(THD *thd, Item **ref)
(thd->lex->sql_command == SQLCOM_CREATE_VIEW))
{
Security_context *save_security_ctx= thd->security_ctx;
- if (context->security_ctx)
+ if (context && context->security_ctx)
thd->security_ctx= context->security_ctx;
/*
@@ -6509,7 +6578,7 @@ Item_func_sp::fix_fields(THD *thd, Item **ref)
if (res)
{
- context->process_error(thd);
+ process_error(thd);
DBUG_RETURN(res);
}
}
@@ -6526,7 +6595,7 @@ Item_func_sp::fix_fields(THD *thd, Item **ref)
if (!(m_sp= sp))
{
my_missing_function_error(m_name->m_name, ErrConvDQName(m_name).ptr());
- context->process_error(thd);
+ process_error(thd);
DBUG_RETURN(TRUE);
}
@@ -6682,6 +6751,14 @@ String *Item_func_last_value::val_str(String *str)
return tmp;
}
+
+bool Item_func_last_value::val_native(THD *thd, Native *to)
+{
+ evaluate_sideeffects();
+ return val_native_from_item(thd, last_value, to);
+}
+
+
longlong Item_func_last_value::val_int()
{
longlong tmp;
@@ -6710,10 +6787,10 @@ my_decimal *Item_func_last_value::val_decimal(my_decimal *decimal_value)
}
-bool Item_func_last_value::get_date(MYSQL_TIME *ltime, ulonglong fuzzydate)
+bool Item_func_last_value::get_date(THD *thd, MYSQL_TIME *ltime, date_mode_t fuzzydate)
{
evaluate_sideeffects();
- bool tmp= last_value->get_date(ltime, fuzzydate);
+ bool tmp= last_value->get_date(thd, ltime, fuzzydate);
null_value= last_value->null_value;
return tmp;
}