diff options
Diffstat (limited to 'sql/item.cc')
-rw-r--r-- | sql/item.cc | 123 |
1 files changed, 114 insertions, 9 deletions
diff --git a/sql/item.cc b/sql/item.cc index 7db1a448e55..35e1312b540 100644 --- a/sql/item.cc +++ b/sql/item.cc @@ -228,7 +228,7 @@ bool Item::get_date(TIME *ltime,uint fuzzydate) char buff[40]; String tmp(buff,sizeof(buff), &my_charset_bin),*res; if (!(res=val_str(&tmp)) || - str_to_TIME(res->ptr(),res->length(),ltime,fuzzydate) <= + str_to_TIME_with_warn(res->ptr(),res->length(),ltime,fuzzydate) <= TIMESTAMP_DATETIME_ERROR) { bzero((char*) ltime,sizeof(*ltime)); @@ -247,7 +247,7 @@ bool Item::get_time(TIME *ltime) char buff[40]; String tmp(buff,sizeof(buff),&my_charset_bin),*res; if (!(res=val_str(&tmp)) || - str_to_time(res->ptr(),res->length(),ltime)) + str_to_time_with_warn(res->ptr(), res->length(), ltime)) { bzero((char*) ltime,sizeof(*ltime)); return 1; @@ -255,7 +255,7 @@ bool Item::get_time(TIME *ltime) return 0; } -CHARSET_INFO * Item::default_charset() const +CHARSET_INFO *Item::default_charset() { return current_thd->variables.collation_connection; } @@ -628,7 +628,9 @@ default_set_param_func(Item_param *param, Item_param::Item_param(unsigned pos_in_query_arg) : state(NO_VALUE), item_result_type(STRING_RESULT), - item_type(STRING_ITEM), + /* Don't pretend to be a literal unless value for this item is set. */ + item_type(PARAM_ITEM), + param_type(MYSQL_TYPE_STRING), pos_in_query(pos_in_query_arg), set_param_func(default_set_param_func) { @@ -736,6 +738,69 @@ bool Item_param::set_longdata(const char *str, ulong length) /* + Set parameter value from user variable value. + + SYNOPSIS + set_from_user_var + thd Current thread + entry User variable structure (NULL means use NULL value) + + RETURN + 0 OK + 1 Out of memort +*/ + +bool Item_param::set_from_user_var(THD *thd, const user_var_entry *entry) +{ + DBUG_ENTER("Item_param::set_from_user_var"); + if (entry && entry->value) + { + item_result_type= entry->type; + switch (entry->type) { + case REAL_RESULT: + set_double(*(double*)entry->value); + break; + case INT_RESULT: + set_int(*(longlong*)entry->value, 21); + break; + case STRING_RESULT: + { + CHARSET_INFO *fromcs= entry->collation.collation; + CHARSET_INFO *tocs= thd->variables.collation_connection; + uint32 dummy_offset; + + value.cs_info.character_set_client= fromcs; + /* + Setup source and destination character sets so that they + are different only if conversion is necessary: this will + make later checks easier. + */ + value.cs_info.final_character_set_of_str_value= + String::needs_conversion(0, fromcs, tocs, &dummy_offset) ? + tocs : fromcs; + /* + Exact value of max_length is not known unless data is converted to + charset of connection, so we have to set it later. + */ + item_type= Item::STRING_ITEM; + item_result_type= STRING_RESULT; + + if (set_str((const char *)entry->value, entry->length)) + DBUG_RETURN(1); + break; + } + default: + DBUG_ASSERT(0); + set_null(); + } + } + else + set_null(); + + DBUG_RETURN(0); +} + +/* Resets parameter after execution. SYNOPSIS @@ -762,13 +827,20 @@ void Item_param::reset() state= NO_VALUE; maybe_null= 1; null_value= 0; + /* + Don't reset item_type to PARAM_ITEM: it's only needed to guard + us from item optimizations at prepare stage, when item doesn't yet + contain a literal of some kind. + In all other cases when this object is accessed its value is + set (this assumption is guarded by 'state' and + DBUG_ASSERTS(state != NO_VALUE) in all Item_param::get_* + methods). + */ } int Item_param::save_in_field(Field *field, bool no_conversions) { - DBUG_ASSERT(current_thd->command == COM_EXECUTE); - field->set_notnull(); switch (state) { @@ -808,6 +880,17 @@ bool Item_param::get_time(TIME *res) } +bool Item_param::get_date(TIME *res, uint fuzzydate) +{ + if (state == TIME_VALUE) + { + *res= value.time; + return 0; + } + return Item::get_date(res, fuzzydate); +} + + double Item_param::val() { switch (state) { @@ -2345,6 +2428,7 @@ Item_type_holder::Item_type_holder(THD *thd, Item *item) field_example= ((Item_field*) item)->field; else field_example= 0; + max_length= real_length(item); collation.set(item->collation); } @@ -2364,6 +2448,7 @@ static Item_result type_convertor[4][4]= bool Item_type_holder::join_types(THD *thd, Item *item) { + uint32 new_length= real_length(item); bool change_field= 0, skip_store_field= 0; Item_result new_type= type_convertor[item_type][item->result_type()]; @@ -2389,7 +2474,7 @@ bool Item_type_holder::join_types(THD *thd, Item *item) // size/type should be changed if (change_field || (new_type != item_type) || - (max_length < item->max_length) || + (max_length < new_length) || ((new_type == INT_RESULT) && (decimals < item->decimals)) || (!maybe_null && item->maybe_null) || @@ -2398,7 +2483,7 @@ bool Item_type_holder::join_types(THD *thd, Item *item) { // new field has some parameters worse then current skip_store_field|= (change_field && - (max_length > item->max_length) || + (max_length > new_length) || ((new_type == INT_RESULT) && (decimals > item->decimals)) || (maybe_null && !item->maybe_null) || @@ -2427,7 +2512,7 @@ bool Item_type_holder::join_types(THD *thd, Item *item) return 1; } - max_length= max(max_length, item->max_length); + max_length= max(max_length, new_length); decimals= max(decimals, item->decimals); maybe_null|= item->maybe_null; item_type= new_type; @@ -2436,6 +2521,26 @@ bool Item_type_holder::join_types(THD *thd, Item *item) return 0; } +uint32 Item_type_holder::real_length(Item *item) +{ + if (item->type() == Item::FIELD_ITEM) + { + return ((Item_field *)item)->max_disp_length(); + } + switch (item->result_type()) + { + case STRING_RESULT: + return item->max_length; + case REAL_RESULT: + return 53; + case INT_RESULT: + return 20; + case ROW_RESULT: + default: + DBUG_ASSERT(0); // we should never go there + return 0; + } +} double Item_type_holder::val() { |