summaryrefslogtreecommitdiff
path: root/sql/item.cc
diff options
context:
space:
mode:
authorJonathan Perkin <jonathan.perkin@oracle.com>2010-12-16 11:13:58 +0100
committerJonathan Perkin <jonathan.perkin@oracle.com>2010-12-16 11:13:58 +0100
commit33827e7dbfc177ef52718f63eaf87e005ab3e8b5 (patch)
tree83c2beab0fb52424ab77dcb1449a3f394f0d0fe1 /sql/item.cc
parentdec388d5beac2e9d0d32ce1610b871c3d1042544 (diff)
parentcf175bf4b8fef9c054fa4779fbea011ad43432a0 (diff)
downloadmariadb-git-33827e7dbfc177ef52718f63eaf87e005ab3e8b5.tar.gz
Merge from mysql-5.5.8-release
Diffstat (limited to 'sql/item.cc')
-rw-r--r--sql/item.cc82
1 files changed, 57 insertions, 25 deletions
diff --git a/sql/item.cc b/sql/item.cc
index b166f3e645f..8957e6e7133 100644
--- a/sql/item.cc
+++ b/sql/item.cc
@@ -226,8 +226,6 @@ bool Item::val_bool()
*/
String *Item::val_str_ascii(String *str)
{
- DBUG_ASSERT(fixed == 1);
-
if (!(collation.collation->state & MY_CS_NONASCII))
return val_str(str);
@@ -1853,11 +1851,12 @@ bool agg_item_set_converter(DTCollation &coll, const char *fname,
*arg= conv;
else
thd->change_item_tree(arg, conv);
- /*
- We do not check conv->fixed, because Item_func_conv_charset which can
- be return by safe_charset_converter can't be fixed at creation
- */
- conv->fix_fields(thd, arg);
+
+ if (conv->fix_fields(thd, arg))
+ {
+ res= TRUE;
+ break; // we cannot return here, we need to restore "arena".
+ }
}
if (arena)
thd->restore_active_arena(arena, &backup);
@@ -3458,19 +3457,16 @@ Item_param::set_value(THD *thd, sp_rcontext *ctx, Item **it)
str_value.charset());
collation.set(str_value.charset(), DERIVATION_COERCIBLE);
decimals= 0;
- param_type= MYSQL_TYPE_STRING;
break;
}
case REAL_RESULT:
set_double(arg->val_real());
- param_type= MYSQL_TYPE_DOUBLE;
break;
case INT_RESULT:
set_int(arg->val_int(), arg->max_length);
- param_type= MYSQL_TYPE_LONG;
break;
case DECIMAL_RESULT:
@@ -3482,8 +3478,6 @@ Item_param::set_value(THD *thd, sp_rcontext *ctx, Item **it)
return TRUE;
set_decimal(dv);
- param_type= MYSQL_TYPE_NEWDECIMAL;
-
break;
}
@@ -3515,6 +3509,7 @@ void
Item_param::set_out_param_info(Send_field *info)
{
m_out_param_info= info;
+ param_type= m_out_param_info->type;
}
@@ -3560,6 +3555,7 @@ void Item_param::make_field(Send_field *field)
field->org_table_name= m_out_param_info->org_table_name;
field->col_name= m_out_param_info->col_name;
field->org_col_name= m_out_param_info->org_col_name;
+
field->length= m_out_param_info->length;
field->charsetnr= m_out_param_info->charsetnr;
field->flags= m_out_param_info->flags;
@@ -5531,17 +5527,43 @@ static uint nr_of_decimals(const char *str, const char *end)
break;
}
decimal_point= str;
- for (; my_isdigit(system_charset_info, *str) ; str++)
+ for ( ; str < end && my_isdigit(system_charset_info, *str) ; str++)
;
- if (*str == 'e' || *str == 'E')
+ if (str < end && (*str == 'e' || *str == 'E'))
return NOT_FIXED_DEC;
+ /*
+ QQ:
+ The number of decimal digist in fact should be (str - decimal_point - 1).
+ But it seems the result of nr_of_decimals() is never used!
+
+ In case of 'e' and 'E' nr_of_decimals returns NOT_FIXED_DEC.
+ In case if there is no 'e' or 'E' parser code in sql_yacc.yy
+ never calls Item_float::Item_float() - it creates Item_decimal instead.
+
+ The only piece of code where we call Item_float::Item_float(str, len)
+ without having 'e' or 'E' is item_xmlfunc.cc, but this Item_float
+ never appears in metadata itself. Changing the code to return
+ (str - decimal_point - 1) does not make any changes in the test results.
+
+ This should be addressed somehow.
+ Looks like a reminder from before real DECIMAL times.
+ */
return (uint) (str - decimal_point);
}
/**
- This function is only called during parsing. We will signal an error if
- value is not a true double value (overflow)
+ This function is only called during parsing:
+ - when parsing SQL query from sql_yacc.yy
+ - when parsing XPath query from item_xmlfunc.cc
+ We will signal an error if value is not a true double value (overflow):
+ eng: Illegal %s '%-.192s' value found during parsing
+
+ Note: the string is NOT null terminated when called from item_xmlfunc.cc,
+ so this->name will contain some SQL query tail behind the "length" bytes.
+ This is Ok for now, as this Item is never seen in SHOW,
+ or EXPLAIN, or anywhere else in metadata.
+ Item->name should be fixed to use LEX_STRING eventually.
*/
Item_float::Item_float(const char *str_arg, uint length)
@@ -5552,12 +5574,9 @@ Item_float::Item_float(const char *str_arg, uint length)
&error);
if (error)
{
- /*
- Note that we depend on that str_arg is null terminated, which is true
- when we are in the parser
- */
- DBUG_ASSERT(str_arg[length] == 0);
- my_error(ER_ILLEGAL_VALUE_FOR_TYPE, MYF(0), "double", (char*) str_arg);
+ char tmp[NAME_LEN + 1];
+ my_snprintf(tmp, sizeof(tmp), "%.*s", length, str_arg);
+ my_error(ER_ILLEGAL_VALUE_FOR_TYPE, MYF(0), "double", tmp);
}
presentation= name=(char*) str_arg;
decimals=(uint8) nr_of_decimals(str_arg, str_arg+length);
@@ -7493,9 +7512,19 @@ void Item_cache_datetime::store(Item *item, longlong val_arg)
}
+void Item_cache_datetime::store(Item *item)
+{
+ Item_cache::store(item);
+ str_value_cached= FALSE;
+}
+
String *Item_cache_datetime::val_str(String *str)
{
DBUG_ASSERT(fixed == 1);
+
+ if ((value_cached || str_value_cached) && null_value)
+ return NULL;
+
if (!str_value_cached)
{
/*
@@ -7509,6 +7538,8 @@ String *Item_cache_datetime::val_str(String *str)
if (value_cached)
{
MYSQL_TIME ltime;
+ /* Return NULL in case of OOM/conversion error. */
+ null_value= TRUE;
if (str_value.alloc(MAX_DATE_STRING_REP_LENGTH))
return NULL;
if (cached_field_type == MYSQL_TYPE_TIME)
@@ -7531,13 +7562,14 @@ String *Item_cache_datetime::val_str(String *str)
{
int was_cut;
longlong res;
- res= number_to_datetime(val_int(), &ltime, TIME_FUZZY_DATE, &was_cut);
+ res= number_to_datetime(int_value, &ltime, TIME_FUZZY_DATE, &was_cut);
if (res == -1)
return NULL;
}
str_value.length(my_TIME_to_str(&ltime,
const_cast<char*>(str_value.ptr())));
str_value_cached= TRUE;
+ null_value= FALSE;
}
else if (!cache_value())
return NULL;
@@ -7558,7 +7590,7 @@ my_decimal *Item_cache_datetime::val_decimal(my_decimal *decimal_val)
double Item_cache_datetime::val_real()
{
DBUG_ASSERT(fixed == 1);
- if (!value_cached && !cache_value_int())
+ if ((!value_cached && !cache_value_int()) || null_value)
return 0.0;
return (double) int_value;
}
@@ -7566,7 +7598,7 @@ double Item_cache_datetime::val_real()
longlong Item_cache_datetime::val_int()
{
DBUG_ASSERT(fixed == 1);
- if (!value_cached && !cache_value_int())
+ if ((!value_cached && !cache_value_int()) || null_value)
return 0;
return int_value;
}