diff options
Diffstat (limited to 'sql/item.cc')
-rw-r--r-- | sql/item.cc | 157 |
1 files changed, 129 insertions, 28 deletions
diff --git a/sql/item.cc b/sql/item.cc index fa75819605f..64d059caea7 100644 --- a/sql/item.cc +++ b/sql/item.cc @@ -22,7 +22,6 @@ #include "mysql_priv.h" #include <m_ctype.h> #include "my_dir.h" -#include <assert.h> /***************************************************************************** ** Item functions @@ -47,6 +46,30 @@ Item::Item(): loop_id= 0; } +Item::Item(Item &item): + loop_id(0), + str_value(item.str_value), + name(item.name), + max_length(item.max_length), + marker(item.marker), + decimals(item.decimals), + maybe_null(item.maybe_null), + null_value(item.null_value), + unsigned_flag(item.unsigned_flag), + with_sum_func(item.with_sum_func), + fixed(item.fixed) +{ + next=current_thd->free_list; // Put in free list + current_thd->free_list= this; +} + +Item_ident::Item_ident(Item_ident &item): + Item(item), + db_name(item.db_name), + table_name(item.table_name), + field_name(item.field_name), + depended_from(item.depended_from) +{} bool Item::check_loop(uint id) { @@ -116,7 +139,7 @@ bool Item_string::eq(const Item *item, bool binary_cmp) const bool Item::get_date(TIME *ltime,bool fuzzydate) { char buff[40]; - String tmp(buff,sizeof(buff),NULL),*res; + String tmp(buff,sizeof(buff), my_charset_bin),*res; if (!(res=val_str(&tmp)) || str_to_TIME(res->ptr(),res->length(),ltime,fuzzydate) == TIMESTAMP_NONE) { @@ -134,7 +157,7 @@ bool Item::get_date(TIME *ltime,bool fuzzydate) bool Item::get_time(TIME *ltime) { char buff[40]; - String tmp(buff,sizeof(buff),NULL),*res; + String tmp(buff,sizeof(buff),my_charset_bin),*res; if (!(res=val_str(&tmp)) || str_to_time(res->ptr(),res->length(),ltime)) { @@ -155,6 +178,11 @@ Item_field::Item_field(Field *f) :Item_ident(NullS,f->table_name,f->field_name) fixed= 1; // This item is not needed in fix_fields } +Item_field::Item_field(Item_field &item): + Item_ident(item), + field(item.field), + result_field(item.result_field) +{} void Item_field::set_field(Field *field_par) { @@ -193,6 +221,7 @@ String *Item_field::val_str(String *str) { if ((null_value=field->is_null())) return 0; + str->set_charset(str_value.charset()); return field->val_str(str,&str_value); } @@ -215,6 +244,7 @@ String *Item_field::str_result(String *str) { if ((null_value=result_field->is_null())) return 0; + str->set_charset(str_value.charset()); return result_field->val_str(str,&str_value); } @@ -264,6 +294,13 @@ table_map Item_field::used_tables() const return (depended_from? RAND_TABLE_BIT : field->table->map); } +Item * Item_field::get_tmp_table_item() +{ + Item_field *new_item= new Item_field(*this); + if (new_item) + new_item->field= new_item->result_field; + return new_item; +} String *Item_int::val_str(String *str) { @@ -346,6 +383,25 @@ void Item_param::set_value(const char *str, uint length) } +void Item_param::set_time(TIME *tm, timestamp_type type) +{ + ltime.year= tm->year; + ltime.month= tm->month; + ltime.day= tm->day; + + ltime.hour= tm->hour; + ltime.minute= tm->minute; + ltime.second= tm->second; + + ltime.second_part= tm->second_part; + + ltime.time_type= type; + + item_is_time= true; + item_type= STRING_ITEM; +} + + void Item_param::set_longdata(const char *str, ulong length) { str_value.append(str,length); @@ -368,17 +424,29 @@ int Item_param::save_in_field(Field *field, bool no_conversions) { double nr=val(); return (field->store(nr)) ? -1 : 0; + } + if (item_is_time) + { + field->store_time(<ime, ltime.time_type); + return 0; } String *result=val_str(&str_value); return (field->store(result->ptr(),result->length(),field->charset())) ? -1 : 0; } +bool Item_param::get_time(TIME *res) +{ + *res=ltime; + return 0; +} double Item_param::val() { + int err; switch (item_result_type) { case STRING_RESULT: - return (double)my_strntod(str_value.charset(),str_value.ptr(),str_value.length(),(char**)0); + return (double) my_strntod(str_value.charset(), (char*) str_value.ptr(), + str_value.length(), (char**) 0, &err); case INT_RESULT: return (double)int_value; default: @@ -389,9 +457,12 @@ double Item_param::val() longlong Item_param::val_int() { + int err; switch (item_result_type) { case STRING_RESULT: - return my_strntoll(str_value.charset(),str_value.ptr(),str_value.length(),(char**) 0,10); + return my_strntoll(str_value.charset(), + str_value.ptr(),str_value.length(),10, + (char**) 0,&err); case REAL_RESULT: return (longlong) (real_value+(real_value > 0 ? 0.5 : -0.5)); default: @@ -502,20 +573,14 @@ bool Item_ref_on_list_position::fix_fields(THD *thd, struct st_table_list *tables, Item ** reference) { - List_iterator<Item> li(list); - Item *item; - for (uint i= 0; (item= li++) && i < pos; i++); - if (item) - { - ref= li.ref(); - return Item_ref_null_helper::fix_fields(thd, tables, reference); - } - else + if (select_lex->item_list.elements <= pos) { ref= 0; my_error(ER_CARDINALITY_COL, MYF(0), pos); return 1; } + ref= select_lex->ref_pointer_array + pos; + return Item_ref_null_helper::fix_fields(thd, tables, reference); } double Item_ref_null_helper::val() @@ -561,8 +626,11 @@ bool Item_field::fix_fields(THD *thd, TABLE_LIST *tables, Item **ref) cause error ER_NON_UNIQ_ERROR in find_field_in_tables. */ SELECT_LEX *last= 0; - +#ifdef EMBEDDED_LIBRARY + thd->net.last_errno= 0; +#endif Item **refer= (Item **)not_found_item; + uint counter= 0; // Prevent using outer fields in subselects, that is not supported now SELECT_LEX *cursel=(SELECT_LEX *) thd->lex.current_select; if (cursel->master_unit()->first_select()->linkage != DERIVED_TABLE_TYPE) @@ -574,7 +642,7 @@ bool Item_field::fix_fields(THD *thd, TABLE_LIST *tables, Item **ref) (last= sl)->get_table_list(), &where, 0)) != not_found_field) break; - if ((refer= find_item_in_list(this, sl->item_list, + if ((refer= find_item_in_list(this, sl->item_list, &counter, REPORT_EXCEPT_NOT_FOUND)) != (Item **)not_found_item) break; @@ -594,12 +662,20 @@ bool Item_field::fix_fields(THD *thd, TABLE_LIST *tables, Item **ref) } else if (refer != (Item **)not_found_item) { + if (!(*refer)->fixed) + { + my_error(ER_ILLEGAL_REFERENCE, MYF(0), name, + "forward reference in item list"); + return -1; + } + Item_ref *r; - *ref= r= new Item_ref(refer, (char *)table_name, + *ref= r= new Item_ref(last->ref_pointer_array + counter-1 + , (char *)table_name, (char *)field_name); if (!r) return 1; - if (r->check_cols(1) || r->fix_fields(thd, tables, ref)) + if (r->fix_fields(thd, tables, ref) || r->check_cols(1)) return 1; r->depended_from= last; cursel->mark_as_dependent(last); @@ -623,7 +699,7 @@ bool Item_field::fix_fields(THD *thd, TABLE_LIST *tables, Item **ref) if (!rf) return 1; (rf)->outer_resolving= outer_resolving; - return rf->check_cols(1) || rf->fix_fields(thd, tables, ref); + return rf->fix_fields(thd, tables, ref) || rf->check_cols(1); } } } @@ -1008,6 +1084,7 @@ bool Item_field::send(Protocol *protocol, String *buffer) bool Item_ref::fix_fields(THD *thd,TABLE_LIST *tables, Item **reference) { + uint counter= 0; if (!ref) { TABLE_LIST *where= 0; @@ -1022,6 +1099,7 @@ bool Item_ref::fix_fields(THD *thd,TABLE_LIST *tables, Item **reference) if (outer_resolving || (ref= find_item_in_list(this, *(thd->lex.current_select->get_item_list()), + &counter, ((sl && thd->lex.current_select->master_unit()-> first_select()->linkage != @@ -1044,12 +1122,14 @@ bool Item_ref::fix_fields(THD *thd,TABLE_LIST *tables, Item **reference) for ( ; sl ; sl= sl->outer_select()) { if ((ref= find_item_in_list(this, (last= sl)->item_list, - REPORT_EXCEPT_NOT_FOUND)) != + &counter, + REPORT_EXCEPT_NOT_FOUND)) != (Item **)not_found_item) break; if ((tmp= find_field_in_tables(thd, this, sl->get_table_list(), &where, - 0)) != not_found_field); + 0)) != not_found_field) + break; if (sl->master_unit()->first_select()->linkage == DERIVED_TABLE_TYPE) break; // do not look over derived table @@ -1064,6 +1144,7 @@ bool Item_ref::fix_fields(THD *thd,TABLE_LIST *tables, Item **reference) // Call to report error find_item_in_list(this, *(thd->lex.current_select->get_item_list()), + &counter, REPORT_ALL_ERRORS); ref= 0; return 1; @@ -1080,17 +1161,35 @@ bool Item_ref::fix_fields(THD *thd,TABLE_LIST *tables, Item **reference) } else { - depended_from= last; + if (!(*ref)->fixed) + { + my_error(ER_ILLEGAL_REFERENCE, MYF(0), name, + "forward reference in item list"); + return -1; + } + ref= (depended_from= last)->ref_pointer_array + counter-1; thd->lex.current_select->mark_as_dependent(last); thd->add_possible_loop(this); } } else if (!ref) return 1; + else + { + if (!(*ref)->fixed) + { + my_error(ER_ILLEGAL_REFERENCE, MYF(0), name, + "forward reference in item list"); + return -1; + } + ref= thd->lex.current_select->ref_pointer_array + counter-1; + } + max_length= (*ref)->max_length; maybe_null= (*ref)->maybe_null; decimals= (*ref)->decimals; } + if (((*ref)->with_sum_func && (depended_from || !(thd->lex.current_select->linkage != GLOBAL_OPTIONS_TYPE && @@ -1147,7 +1246,7 @@ Item *resolve_const_item(Item *item,Item *comp_item) if (res_type == STRING_RESULT) { char buff[MAX_FIELD_WIDTH]; - String tmp(buff,sizeof(buff),NULL),*result; + String tmp(buff,sizeof(buff),my_charset_bin),*result; result=item->val_str(&tmp); if (item->null_value) { @@ -1202,8 +1301,8 @@ bool field_is_equal_to_item(Field *field,Item *item) { char item_buff[MAX_FIELD_WIDTH]; char field_buff[MAX_FIELD_WIDTH]; - String item_tmp(item_buff,sizeof(item_buff),NULL),*item_result; - String field_tmp(field_buff,sizeof(field_buff),NULL); + String item_tmp(item_buff,sizeof(item_buff),my_charset_bin),*item_result; + String field_tmp(field_buff,sizeof(field_buff),my_charset_bin); item_result=item->val_str(&item_tmp); if (item->null_value) return 1; // This must be true @@ -1260,17 +1359,19 @@ void Item_cache_str::store(Item *item) } double Item_cache_str::val() { + int err; if (value) - return my_strntod(value->charset(), value->ptr(), - value->length(), (char**)0); + return my_strntod(value->charset(), (char*) value->ptr(), + value->length(), (char**) 0, &err); else return (double)0; } longlong Item_cache_str::val_int() { + int err; if (value) return my_strntoll(value->charset(), value->ptr(), - value->length(), (char**) 0, 10); + value->length(), 10, (char**) 0, &err); else return (longlong)0; } |