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.cc430
1 files changed, 277 insertions, 153 deletions
diff --git a/sql/item_func.cc b/sql/item_func.cc
index 7eea131e648..bbfa3b74c5e 100644
--- a/sql/item_func.cc
+++ b/sql/item_func.cc
@@ -1,4 +1,5 @@
-/* Copyright (c) 2000, 2011, Oracle and/or its affiliates. All rights reserved.
+/* Copyright (c) 2000, 2010, Oracle and/or its affiliates.
+ Copyright (c) 2011 Monty Program Ab
This program is free software; you can redistribute it and/or modify
it under the terms of the GNU General Public License as published by
@@ -38,7 +39,7 @@
#include "strfunc.h" // find_type
#include "sql_parse.h" // is_update_query
#include "sql_acl.h" // EXECUTE_ACL
-#include "mysqld.h" // LOCK_uuid_generator
+#include "mysqld.h" // LOCK_short_uuid_generator
#include "rpl_mi.h"
#include <m_ctype.h>
#include <hash.h>
@@ -103,6 +104,7 @@ void Item_func::set_arguments(List<Item> &list)
{
*(save_args++)= item;
with_sum_func|=item->with_sum_func;
+ with_field|= item->with_field;
}
}
list.empty(); // Fields are used
@@ -153,6 +155,7 @@ Item_func::Item_func(THD *thd, Item_func *item)
Sets as a side effect the following class variables:
maybe_null Set if any argument may return NULL
with_sum_func Set if any of the arguments contains a sum function
+ with_field Set if any of the arguments contains or is a field
used_tables_cache Set to union of the tables used by arguments
str_value.charset If this is a string function, set this to the
@@ -220,8 +223,8 @@ Item_func::fix_fields(THD *thd, Item **ref)
maybe_null=1;
with_sum_func= with_sum_func || item->with_sum_func;
+ with_field= with_field || item->with_field;
used_tables_cache|= item->used_tables();
- not_null_tables_cache|= item->not_null_tables();
const_item_cache&= item->const_item();
with_subselect|= item->with_subselect;
}
@@ -234,6 +237,37 @@ Item_func::fix_fields(THD *thd, Item **ref)
return FALSE;
}
+void
+Item_func::quick_fix_field()
+{
+ Item **arg,**arg_end;
+ if (arg_count)
+ {
+ for (arg=args, arg_end=args+arg_count; arg != arg_end ; arg++)
+ {
+ if (!(*arg)->fixed)
+ (*arg)->quick_fix_field();
+ }
+ }
+ fixed= 1;
+}
+
+
+bool
+Item_func::eval_not_null_tables(uchar *opt_arg)
+{
+ Item **arg,**arg_end;
+ not_null_tables_cache= 0;
+ if (arg_count)
+ {
+ for (arg=args, arg_end=args+arg_count; arg != arg_end ; arg++)
+ {
+ not_null_tables_cache|= (*arg)->not_null_tables();
+ }
+ }
+ return FALSE;
+}
+
void Item_func::fix_after_pullout(st_select_lex *new_parent, Item **ref)
{
@@ -356,6 +390,8 @@ Item *Item_func::transform(Item_transformer transformer, uchar *argument)
the old item is substituted for a new one.
After this the transformer is applied to the root node
of the Item_func object.
+ The compile function is not called if the analyzer returns NULL
+ in the parameter arg_p.
@param analyzer the analyzer callback function to be applied to the
nodes of the tree of the object
@@ -373,7 +409,7 @@ Item *Item_func::compile(Item_analyzer analyzer, uchar **arg_p,
{
if (!(this->*analyzer)(arg_p))
return 0;
- if (arg_count)
+ if (*arg_p && arg_count)
{
Item **arg,**arg_end;
for (arg= args, arg_end= args+arg_count; arg != arg_end; arg++)
@@ -381,7 +417,7 @@ Item *Item_func::compile(Item_analyzer analyzer, uchar **arg_p,
/*
The same parameter value of arg_p must be passed
to analyze any argument of the condition formula.
- */
+ */
uchar *arg_v= *arg_p;
Item *new_item= (*arg)->compile(analyzer, &arg_v, transformer, arg_t);
if (new_item && *arg != new_item)
@@ -509,7 +545,8 @@ Field *Item_func::tmp_table_field(TABLE *table)
field= Field_new_decimal::create_from_item(this);
break;
case ROW_RESULT:
- default:
+ case TIME_RESULT:
+ case IMPOSSIBLE_RESULT:
// This case should never be chosen
DBUG_ASSERT(0);
field= 0;
@@ -717,8 +754,8 @@ void Item_num_op::find_num_type(void)
DBUG_ENTER("Item_num_op::find_num_type");
DBUG_PRINT("info", ("name %s", func_name()));
DBUG_ASSERT(arg_count == 2);
- Item_result r0= args[0]->result_type();
- Item_result r1= args[1]->result_type();
+ Item_result r0= args[0]->cast_to_int_type();
+ Item_result r1= args[1]->cast_to_int_type();
if (r0 == REAL_RESULT || r1 == REAL_RESULT ||
r0 == STRING_RESULT || r1 ==STRING_RESULT)
@@ -727,7 +764,8 @@ void Item_num_op::find_num_type(void)
max_length= float_length(decimals);
hybrid_type= REAL_RESULT;
}
- else if (r0 == DECIMAL_RESULT || r1 == DECIMAL_RESULT)
+ else if (r0 == DECIMAL_RESULT || r1 == DECIMAL_RESULT ||
+ r0 == TIME_RESULT || r1 == TIME_RESULT)
{
hybrid_type= DECIMAL_RESULT;
result_precision();
@@ -758,7 +796,7 @@ void Item_func_num1::find_num_type()
{
DBUG_ENTER("Item_func_num1::find_num_type");
DBUG_PRINT("info", ("name %s", func_name()));
- switch (hybrid_type= args[0]->result_type()) {
+ switch (hybrid_type= args[0]->cast_to_int_type()) {
case INT_RESULT:
unsigned_flag= args[0]->unsigned_flag;
break;
@@ -767,9 +805,12 @@ void Item_func_num1::find_num_type()
hybrid_type= REAL_RESULT;
max_length= float_length(decimals);
break;
+ case TIME_RESULT:
+ hybrid_type= DECIMAL_RESULT;
case DECIMAL_RESULT:
break;
- default:
+ case ROW_RESULT:
+ case IMPOSSIBLE_RESULT:
DBUG_ASSERT(0);
}
DBUG_PRINT("info", ("Type: %s",
@@ -827,7 +868,9 @@ String *Item_func_numhybrid::val_str(String *str)
}
case STRING_RESULT:
return str_op(&str_value);
- default:
+ case TIME_RESULT:
+ case ROW_RESULT:
+ case IMPOSSIBLE_RESULT:
DBUG_ASSERT(0);
}
return str;
@@ -862,7 +905,9 @@ double Item_func_numhybrid::val_real()
return (res ? my_strntod(res->charset(), (char*) res->ptr(), res->length(),
&end_not_used, &err_not_used) : 0.0);
}
- default:
+ case TIME_RESULT:
+ case ROW_RESULT:
+ case IMPOSSIBLE_RESULT:
DBUG_ASSERT(0);
}
return 0.0;
@@ -897,7 +942,9 @@ longlong Item_func_numhybrid::val_int()
CHARSET_INFO *cs= res->charset();
return (*(cs->cset->strtoll10))(cs, res->ptr(), &end, &err_not_used);
}
- default:
+ case TIME_RESULT:
+ case ROW_RESULT:
+ case IMPOSSIBLE_RESULT:
DBUG_ASSERT(0);
}
return 0;
@@ -935,7 +982,8 @@ my_decimal *Item_func_numhybrid::val_decimal(my_decimal *decimal_value)
break;
}
case ROW_RESULT:
- default:
+ case TIME_RESULT:
+ case IMPOSSIBLE_RESULT:
DBUG_ASSERT(0);
}
return val;
@@ -996,21 +1044,32 @@ longlong Item_func_signed::val_int()
longlong value;
int error;
- if (args[0]->cast_to_int_type() != STRING_RESULT ||
- args[0]->result_as_longlong())
+ if (args[0]->cast_to_int_type() != STRING_RESULT)
+ {
+ value= args[0]->val_int();
+ null_value= args[0]->null_value;
+ return value;
+ }
+ else if (args[0]->dynamic_result())
{
+ /* We come here when argument has an unknown type */
+ args[0]->unsigned_flag= 0; // Mark that we want to have a signed value
value= args[0]->val_int();
null_value= args[0]->null_value;
+ if (!null_value && args[0]->unsigned_flag && value < 0)
+ goto err; // Warn about overflow
return value;
}
value= val_int_from_str(&error);
if (value < 0 && error == 0)
- {
- push_warning(current_thd, MYSQL_ERROR::WARN_LEVEL_WARN, ER_UNKNOWN_ERROR,
- "Cast to signed converted positive out-of-range integer to "
- "it's negative complement");
- }
+ goto err;
+ return value;
+
+err:
+ push_warning(current_thd, MYSQL_ERROR::WARN_LEVEL_WARN, ER_UNKNOWN_ERROR,
+ "Cast to signed converted positive out-of-range integer to "
+ "it's negative complement");
return value;
}
@@ -1038,19 +1097,35 @@ longlong Item_func_unsigned::val_int()
value= 0;
return value;
}
- else if (args[0]->cast_to_int_type() != STRING_RESULT ||
- args[0]->result_as_longlong())
+ else if (args[0]->dynamic_result())
+ {
+ /* We come here when argument has an unknown type */
+ args[0]->unsigned_flag= 1; // Mark that we want to have an unsigned value
+ value= args[0]->val_int();
+ null_value= args[0]->null_value;
+ if (!null_value && args[0]->unsigned_flag == 0 && value < 0)
+ goto err; // Warn about overflow
+ return value;
+ }
+ else if (args[0]->cast_to_int_type() != STRING_RESULT)
{
value= args[0]->val_int();
null_value= args[0]->null_value;
+ if (!null_value && args[0]->unsigned_flag == 0 && value < 0)
+ goto err; // Warn about overflow
return value;
}
value= val_int_from_str(&error);
if (error < 0)
- push_warning(current_thd, MYSQL_ERROR::WARN_LEVEL_WARN, ER_UNKNOWN_ERROR,
- "Cast to unsigned converted negative integer to it's "
- "positive complement");
+ goto err;
+
+ return value;
+
+err:
+ push_warning(current_thd, MYSQL_ERROR::WARN_LEVEL_WARN, ER_UNKNOWN_ERROR,
+ "Cast to unsigned converted negative integer to it's "
+ "positive complement");
return value;
}
@@ -1148,6 +1223,51 @@ void Item_decimal_typecast::print(String *str, enum_query_type query_type)
}
+double Item_double_typecast::val_real()
+{
+ int error;
+ double tmp= args[0]->val_real();
+ if ((null_value= args[0]->null_value))
+ return 0.0;
+
+ if ((error= truncate_double(&tmp, max_length, decimals, 0, DBL_MAX)))
+ {
+ push_warning_printf(current_thd,
+ MYSQL_ERROR::WARN_LEVEL_WARN,
+ ER_WARN_DATA_OUT_OF_RANGE,
+ ER(ER_WARN_DATA_OUT_OF_RANGE),
+ name, 1);
+ if (error < 0)
+ {
+ null_value= 1; // Illegal value
+ tmp= 0.0;
+ }
+ }
+ return tmp;
+}
+
+
+void Item_double_typecast::print(String *str, enum_query_type query_type)
+{
+ char len_buf[20*3 + 1];
+ char *end;
+
+ str->append(STRING_WITH_LEN("cast("));
+ args[0]->print(str, query_type);
+ str->append(STRING_WITH_LEN(" as double"));
+ if (decimals != NOT_FIXED_DEC)
+ {
+ str->append('(');
+ end= int10_to_str(max_length, len_buf,10);
+ str->append(len_buf, (uint32) (end - len_buf));
+ str->append(',');
+ end= int10_to_str(decimals, len_buf,10);
+ str->append(len_buf, (uint32) (end - len_buf));
+ str->append(')');
+ }
+ str->append(')');
+}
+
double Item_func_plus::real_op()
{
double value= args[0]->val_real() + args[1]->val_real();
@@ -1566,7 +1686,7 @@ void Item_func_div::fix_length_and_dec()
DBUG_ENTER("Item_func_div::fix_length_and_dec");
prec_increment= current_thd->variables.div_precincrement;
Item_num_op::fix_length_and_dec();
- switch(hybrid_type) {
+ switch (hybrid_type) {
case REAL_RESULT:
{
decimals=max(args[0]->decimals,args[1]->decimals)+prec_increment;
@@ -1589,7 +1709,10 @@ void Item_func_div::fix_length_and_dec()
case DECIMAL_RESULT:
result_precision();
break;
- default:
+ case STRING_RESULT:
+ case ROW_RESULT:
+ case TIME_RESULT:
+ case IMPOSSIBLE_RESULT:
DBUG_ASSERT(0);
}
maybe_null= 1; // devision by zero
@@ -2130,7 +2253,7 @@ void Item_func_int_val::find_num_type()
{
DBUG_ENTER("Item_func_int_val::find_num_type");
DBUG_PRINT("info", ("name %s", func_name()));
- switch(hybrid_type= args[0]->result_type())
+ switch (hybrid_type= args[0]->cast_to_int_type())
{
case STRING_RESULT:
case REAL_RESULT:
@@ -2138,6 +2261,7 @@ void Item_func_int_val::find_num_type()
max_length= float_length(decimals);
break;
case INT_RESULT:
+ case TIME_RESULT:
case DECIMAL_RESULT:
/*
-2 because in most high position can't be used any digit for longlong
@@ -2154,7 +2278,8 @@ void Item_func_int_val::find_num_type()
hybrid_type= INT_RESULT;
}
break;
- default:
+ case ROW_RESULT:
+ case IMPOSSIBLE_RESULT:
DBUG_ASSERT(0);
}
DBUG_PRINT("info", ("Type: %s",
@@ -2283,7 +2408,7 @@ void Item_func_round::fix_length_and_dec()
}
val1= args[1]->val_int();
- if ((null_value= args[1]->is_null()))
+ if ((null_value= args[1]->null_value))
return;
val1_unsigned= args[1]->unsigned_flag;
@@ -2333,7 +2458,9 @@ void Item_func_round::fix_length_and_dec()
unsigned_flag);
break;
}
- default:
+ case ROW_RESULT:
+ case TIME_RESULT:
+ case IMPOSSIBLE_RESULT:
DBUG_ASSERT(0); /* This result type isn't handled */
}
}
@@ -2541,10 +2668,10 @@ double Item_func_units::val_real()
void Item_func_min_max::fix_length_and_dec()
{
int max_int_part=0;
- bool datetime_found= FALSE;
decimals=0;
max_length=0;
maybe_null=0;
+ thd= current_thd;
cmp_type=args[0]->result_type();
for (uint i=0 ; i < arg_count ; i++)
@@ -2553,25 +2680,12 @@ void Item_func_min_max::fix_length_and_dec()
set_if_bigger(decimals, args[i]->decimals);
set_if_bigger(max_int_part, args[i]->decimal_int_part());
if (args[i]->maybe_null)
- maybe_null=1;
- cmp_type=item_cmp_type(cmp_type,args[i]->result_type());
- if (args[i]->result_type() != ROW_RESULT && args[i]->is_datetime())
- {
- datetime_found= TRUE;
- if (!datetime_item || args[i]->field_type() == MYSQL_TYPE_DATETIME)
- datetime_item= args[i];
- }
+ maybe_null= 1;
+ cmp_type= item_cmp_type(cmp_type,args[i]->result_type());
}
if (cmp_type == STRING_RESULT)
- {
agg_arg_charsets_for_string_result_with_comparison(collation,
args, arg_count);
- if (datetime_found)
- {
- thd= current_thd;
- compare_as_dates= TRUE;
- }
- }
else if ((cmp_type == DECIMAL_RESULT) || (cmp_type == INT_RESULT))
{
collation.set_numeric();
@@ -2582,61 +2696,73 @@ void Item_func_min_max::fix_length_and_dec()
}
else if (cmp_type == REAL_RESULT)
fix_char_length(float_length(decimals));
- cached_field_type= agg_field_type(args, arg_count);
+
+ compare_as_dates= find_date_time_item(args, arg_count, 0);
+ if (compare_as_dates)
+ {
+ cached_field_type= compare_as_dates->field_type();
+ if (mysql_type_to_time_type(cached_field_type) == MYSQL_TIMESTAMP_DATE)
+ decimals= 0;
+ else
+ set_if_smaller(decimals, TIME_SECOND_PART_DIGITS);
+ }
+ else
+ cached_field_type= agg_field_type(args, arg_count);
}
/*
Compare item arguments in the DATETIME context.
- SYNOPSIS
- cmp_datetimes()
- value [out] found least/greatest DATE/DATETIME value
-
DESCRIPTION
Compare item arguments as DATETIME values and return the index of the
least/greatest argument in the arguments array.
- The correct integer DATE/DATETIME value of the found argument is
+ The correct DATE/DATETIME value of the found argument is
stored to the value pointer, if latter is provided.
RETURN
- 0 If one of arguments is NULL or there was a execution error
- # index of the least/greatest argument
+ 1 If one of arguments is NULL or there was a execution error
+ 0 Otherwise
*/
-uint Item_func_min_max::cmp_datetimes(ulonglong *value)
+bool Item_func_min_max::get_date(MYSQL_TIME *ltime, uint fuzzy_date)
{
longlong UNINIT_VAR(min_max);
- uint min_max_idx= 0;
+ DBUG_ASSERT(fixed == 1);
+
+ /*
+ just like ::val_int() method of a string item can be called,
+ for example, SELECT CONCAT("10", "12") + 1,
+ ::get_date() can be called for non-temporal values,
+ for example, SELECT MONTH(GREATEST("2011-11-21", "2010-10-09"))
+
+ */
+ if (!compare_as_dates)
+ return Item_func::get_date(ltime, fuzzy_date);
for (uint i=0; i < arg_count ; i++)
{
Item **arg= args + i;
bool is_null;
- longlong res= get_datetime_value(thd, &arg, 0, datetime_item, &is_null);
+ longlong res= get_datetime_value(thd, &arg, 0, compare_as_dates, &is_null);
- /* Check if we need to stop (because of error or KILL) and stop the loop */
- if (thd->is_error())
+ /* Check if we need to stop (because of error or KILL) and stop the loop */
+ if (thd->is_error() || args[i]->null_value)
{
- null_value= 1;
- return 0;
+ return (null_value= 1);
}
- if ((null_value= args[i]->null_value))
- return 0;
if (i == 0 || (res < min_max ? cmp_sign : -cmp_sign) > 0)
- {
min_max= res;
- min_max_idx= i;
- }
}
- if (value)
+ unpack_time(min_max, ltime);
+ if (compare_as_dates->field_type() == MYSQL_TYPE_DATE)
{
- *value= min_max;
- if (datetime_item->field_type() == MYSQL_TYPE_DATE)
- *value/= 1000000L;
+ ltime->time_type= MYSQL_TIMESTAMP_DATE;
+ ltime->hour= ltime->minute= ltime->second= ltime->second_part= 0;
}
- return min_max_idx;
+
+ return (null_value= 0);
}
@@ -2644,46 +2770,14 @@ String *Item_func_min_max::val_str(String *str)
{
DBUG_ASSERT(fixed == 1);
if (compare_as_dates)
- {
- String *str_res;
- uint min_max_idx= cmp_datetimes(NULL);
- if (null_value)
- return 0;
- str_res= args[min_max_idx]->val_str(str);
- if (args[min_max_idx]->null_value)
- {
- // check if the call to val_str() above returns a NULL value
- null_value= 1;
- return NULL;
- }
- str_res->set_charset(collation.collation);
- return str_res;
- }
+ return val_string_from_date(str);
switch (cmp_type) {
case INT_RESULT:
- {
- longlong nr=val_int();
- if (null_value)
- return 0;
- str->set_int(nr, unsigned_flag, collation.collation);
- return str;
- }
+ return val_string_from_int(str);
case DECIMAL_RESULT:
- {
- my_decimal dec_buf, *dec_val= val_decimal(&dec_buf);
- if (null_value)
- return 0;
- my_decimal2string(E_DEC_FATAL_ERROR, dec_val, 0, 0, 0, str);
- return str;
- }
+ return val_string_from_decimal(str);
case REAL_RESULT:
- {
- double nr= val_real();
- if (null_value)
- return 0; /* purecov: inspected */
- str->set_real(nr, decimals, collation.collation);
- return str;
- }
+ return val_string_from_real(str);
case STRING_RESULT:
{
String *UNINIT_VAR(res);
@@ -2709,9 +2803,9 @@ String *Item_func_min_max::val_str(String *str)
return res;
}
case ROW_RESULT:
- default:
- // This case should never be chosen
- DBUG_ASSERT(0);
+ case TIME_RESULT:
+ case IMPOSSIBLE_RESULT:
+ DBUG_ASSERT(0); // This case should never be chosen
return 0;
}
return 0; // Keep compiler happy
@@ -2724,9 +2818,11 @@ double Item_func_min_max::val_real()
double value=0.0;
if (compare_as_dates)
{
- ulonglong result= 0;
- (void)cmp_datetimes(&result);
- return (double)result;
+ MYSQL_TIME ltime;
+ if (get_date(&ltime, TIME_FUZZY_DATE))
+ return 0;
+
+ return TIME_to_double(&ltime);
}
for (uint i=0; i < arg_count ; i++)
{
@@ -2751,9 +2847,11 @@ longlong Item_func_min_max::val_int()
longlong value=0;
if (compare_as_dates)
{
- ulonglong result= 0;
- (void)cmp_datetimes(&result);
- return (longlong)result;
+ MYSQL_TIME ltime;
+ if (get_date(&ltime, TIME_FUZZY_DATE))
+ return 0;
+
+ return TIME_to_ulonglong(&ltime);
}
for (uint i=0; i < arg_count ; i++)
{
@@ -2779,10 +2877,11 @@ my_decimal *Item_func_min_max::val_decimal(my_decimal *dec)
if (compare_as_dates)
{
- ulonglong value= 0;
- (void)cmp_datetimes(&value);
- ulonglong2decimal(value, dec);
- return dec;
+ MYSQL_TIME ltime;
+ if (get_date(&ltime, TIME_FUZZY_DATE))
+ return 0;
+
+ return date2my_decimal(&ltime, dec);
}
for (uint i=0; i < arg_count ; i++)
{
@@ -3230,6 +3329,7 @@ udf_handler::fix_fields(THD *thd, Item_result_field *func,
if (item->maybe_null)
func->maybe_null=1;
func->with_sum_func= func->with_sum_func || item->with_sum_func;
+ func->with_field= func->with_field || item->with_field;
used_tables_cache|=item->used_tables();
const_item_cache&=item->const_item();
f_args.arg_type[i]=item->result_type();
@@ -3275,8 +3375,7 @@ udf_handler::fix_fields(THD *thd, Item_result_field *func,
if (arguments[i]->const_item())
{
- switch (arguments[i]->result_type())
- {
+ switch (arguments[i]->result_type()) {
case STRING_RESULT:
case DECIMAL_RESULT:
{
@@ -3302,9 +3401,9 @@ udf_handler::fix_fields(THD *thd, Item_result_field *func,
to+= ALIGN_SIZE(sizeof(double));
break;
case ROW_RESULT:
- default:
- // This case should never be chosen
- DBUG_ASSERT(0);
+ case TIME_RESULT:
+ case IMPOSSIBLE_RESULT:
+ DBUG_ASSERT(0); // This case should never be chosen
break;
}
}
@@ -3377,9 +3476,9 @@ bool udf_handler::get_arguments()
}
break;
case ROW_RESULT:
- default:
- // This case should never be chosen
- DBUG_ASSERT(0);
+ case TIME_RESULT:
+ case IMPOSSIBLE_RESULT:
+ DBUG_ASSERT(0); // This case should never be chosen
break;
}
}
@@ -4112,9 +4211,9 @@ longlong Item_func_benchmark::val_int()
(void) args[1]->val_decimal(&tmp_decimal);
break;
case ROW_RESULT:
- default:
- // This case should never be chosen
- DBUG_ASSERT(0);
+ case TIME_RESULT:
+ case IMPOSSIBLE_RESULT:
+ DBUG_ASSERT(0); // This case should never be chosen
return 0;
}
}
@@ -4297,6 +4396,21 @@ bool Item_func_set_user_var::fix_fields(THD *thd, Item **ref)
DERIVATION_IMPLICIT);
collation.set(entry->collation.collation, DERIVATION_IMPLICIT);
cached_result_type= args[0]->result_type();
+ if (thd->lex->current_select)
+ {
+ /*
+ When this function is used in a derived table/view force the derived
+ table to be materialized to preserve possible side-effect of setting a
+ user variable.
+ */
+ SELECT_LEX_UNIT *unit= thd->lex->current_select->master_unit();
+ TABLE_LIST *derived;
+ for (derived= unit->derived;
+ derived;
+ derived= derived->select_lex->master_unit()->derived)
+ derived->set_materialized_derived();
+ }
+
return FALSE;
}
@@ -4481,6 +4595,8 @@ double user_var_entry::val_real(bool *null_value)
case STRING_RESULT:
return my_atof(value); // This is null terminated
case ROW_RESULT:
+ case TIME_RESULT:
+ case IMPOSSIBLE_RESULT:
DBUG_ASSERT(0); // Impossible
break;
}
@@ -4512,6 +4628,8 @@ longlong user_var_entry::val_int(bool *null_value) const
return my_strtoll10(value, (char**) 0, &error);// String is null terminated
}
case ROW_RESULT:
+ case TIME_RESULT:
+ case IMPOSSIBLE_RESULT:
DBUG_ASSERT(0); // Impossible
break;
}
@@ -4545,6 +4663,8 @@ String *user_var_entry::val_str(bool *null_value, String *str,
str= 0; // EOM error
break;
case ROW_RESULT:
+ case TIME_RESULT:
+ case IMPOSSIBLE_RESULT:
DBUG_ASSERT(0); // Impossible
break;
}
@@ -4572,6 +4692,8 @@ my_decimal *user_var_entry::val_decimal(bool *null_value, my_decimal *val)
str2my_decimal(E_DEC_FATAL_ERROR, value, length, collation.collation, val);
break;
case ROW_RESULT:
+ case TIME_RESULT:
+ case IMPOSSIBLE_RESULT:
DBUG_ASSERT(0); // Impossible
break;
}
@@ -4610,8 +4732,9 @@ Item_func_set_user_var::check(bool use_result_field)
{
save_result.vint= use_result_field ? result_field->val_int() :
args[0]->val_int();
- unsigned_flag= use_result_field ? ((Field_num*)result_field)->unsigned_flag:
- args[0]->unsigned_flag;
+ unsigned_flag= (use_result_field ?
+ ((Field_num*)result_field)->unsigned_flag:
+ args[0]->unsigned_flag);
break;
}
case STRING_RESULT:
@@ -4628,9 +4751,9 @@ Item_func_set_user_var::check(bool use_result_field)
break;
}
case ROW_RESULT:
- default:
- // This case should never be chosen
- DBUG_ASSERT(0);
+ case TIME_RESULT:
+ case IMPOSSIBLE_RESULT:
+ DBUG_ASSERT(0); // This case should never be chosen
break;
}
DBUG_RETURN(FALSE);
@@ -4663,9 +4786,9 @@ void Item_func_set_user_var::save_item_result(Item *item)
save_result.vdec= item->val_decimal_result(&decimal_buff);
break;
case ROW_RESULT:
- default:
- // Should never happen
- DBUG_ASSERT(0);
+ case TIME_RESULT:
+ case IMPOSSIBLE_RESULT:
+ DBUG_ASSERT(0); // This case should never be chosen
break;
}
DBUG_VOID_RETURN;
@@ -4731,9 +4854,9 @@ Item_func_set_user_var::update()
break;
}
case ROW_RESULT:
- default:
- // This case should never be chosen
- DBUG_ASSERT(0);
+ case TIME_RESULT:
+ case IMPOSSIBLE_RESULT:
+ DBUG_ASSERT(0); // This case should never be chosen
break;
}
DBUG_RETURN(res);
@@ -5167,7 +5290,7 @@ void Item_func_get_user_var::fix_length_and_dec()
max_length= var_entry->length;
collation.set(var_entry->collation);
- switch(m_cached_result_type) {
+ switch (m_cached_result_type) {
case REAL_RESULT:
fix_char_length(DBL_DIG + 8);
break;
@@ -5183,8 +5306,9 @@ void Item_func_get_user_var::fix_length_and_dec()
decimals= DECIMAL_MAX_SCALE;
break;
case ROW_RESULT: // Keep compiler happy
- default:
- DBUG_ASSERT(0);
+ case TIME_RESULT:
+ case IMPOSSIBLE_RESULT:
+ DBUG_ASSERT(0); // This case should never be chosen
break;
}
}
@@ -6261,7 +6385,7 @@ Item_func_sp::cleanup()
sp_result_field= NULL;
}
m_sp= NULL;
- dummy_table->alias= NULL;
+ dummy_table->alias.free();
Item_func::cleanup();
}
@@ -6287,7 +6411,7 @@ Item_func_sp::func_name() const
qname.append('.');
}
append_identifier(thd, &qname, m_name->m_name.str, m_name->m_name.length);
- return qname.ptr();
+ return qname.c_ptr_safe();
}
@@ -6343,7 +6467,7 @@ Item_func_sp::init_result_field(THD *thd)
*/
share= dummy_table->s;
- dummy_table->alias = "";
+ dummy_table->alias.set("", 0, table_alias_charset);
dummy_table->maybe_null = maybe_null;
dummy_table->in_use= thd;
dummy_table->copy_blobs= TRUE;
@@ -6665,8 +6789,8 @@ void uuid_short_init()
longlong Item_func_uuid_short::val_int()
{
ulonglong val;
- mysql_mutex_lock(&LOCK_uuid_generator);
+ mysql_mutex_lock(&LOCK_short_uuid_generator);
val= uuid_value++;
- mysql_mutex_unlock(&LOCK_uuid_generator);
+ mysql_mutex_unlock(&LOCK_short_uuid_generator);
return (longlong) val;
}