diff options
Diffstat (limited to 'sql/item.cc')
-rw-r--r-- | sql/item.cc | 80 |
1 files changed, 67 insertions, 13 deletions
diff --git a/sql/item.cc b/sql/item.cc index 099e6b977d6..ecbe2d22fa4 100644 --- a/sql/item.cc +++ b/sql/item.cc @@ -62,10 +62,10 @@ Item::Item(): */ if (thd->lex->current_select) { - SELECT_LEX_NODE::enum_parsing_place place= + enum_parsing_place place= thd->lex->current_select->parsing_place; - if (place == SELECT_LEX_NODE::SELECT_LIST || - place == SELECT_LEX_NODE::IN_HAVING) + if (place == SELECT_LIST || + place == IN_HAVING) thd->lex->current_select->select_n_having_items++; } } @@ -179,10 +179,17 @@ void Item::set_name(const char *str, uint length, CHARSET_INFO *cs) name_length= 0; return; } - while (length && !my_isgraph(cs,*str)) - { // Fix problem with yacc - length--; - str++; + if (cs->ctype) + { + /* + This will probably need a better implementation in the future: + a function in CHARSET_INFO structure. + */ + while (length && !my_isgraph(cs,*str)) + { // Fix problem with yacc + length--; + str++; + } } if (!my_charset_same(cs, system_charset_info)) { @@ -291,8 +298,9 @@ Item_splocal::type() const } -bool DTCollation::aggregate(DTCollation &dt) +bool DTCollation::aggregate(DTCollation &dt, bool superset_conversion) { + nagg++; if (!my_charset_same(collation, dt.collation)) { /* @@ -306,15 +314,39 @@ bool DTCollation::aggregate(DTCollation &dt) if (derivation <= dt.derivation) ; // Do nothing else - set(dt); + { + set(dt); + strong= nagg; + } } else if (dt.collation == &my_charset_bin) { if (dt.derivation <= derivation) + { set(dt); + strong= nagg; + } else ; // Do nothing } + else if (superset_conversion) + { + if (derivation < dt.derivation && + collation->state & MY_CS_UNICODE) + ; // Do nothing + else if (dt.derivation < derivation && + dt.collation->state & MY_CS_UNICODE) + { + set(dt); + strong= nagg; + } + else + { + // Cannot convert to superset + set(0, DERIVATION_NONE); + return 1; + } + } else { set(0, DERIVATION_NONE); @@ -328,6 +360,7 @@ bool DTCollation::aggregate(DTCollation &dt) else if (dt.derivation < derivation) { set(dt); + strong= nagg; } else { @@ -979,7 +1012,7 @@ double Item_param::val() This works for example when user says SELECT ?+0.0 and supplies time value for the placeholder. */ - return (double) TIME_to_ulonglong(&value.time); + return ulonglong2double(TIME_to_ulonglong(&value.time)); case NULL_VALUE: return 0.0; default: @@ -1312,12 +1345,24 @@ bool Item_field::fix_fields(THD *thd, TABLE_LIST *tables, Item **ref) table_list= (last= sl)->get_table_list(); if (sl->resolve_mode == SELECT_LEX::INSERT_MODE && table_list) { - // it is primary INSERT st_select_lex => skip first table resolving + /* + it is primary INSERT st_select_lex => skip first table + resolving + */ table_list= table_list->next_local; } Item_subselect *prev_subselect_item= prev_unit->item; - if ((tmp= find_field_in_tables(thd, this, + enum_parsing_place place= prev_subselect_item->parsing_place; + /* + check table fields only if subquery used somewhere out of HAVING + or SELECT list or outer SELECT do not use groupping (i.e. tables + are accessable) + */ + if (((place != IN_HAVING && + place != SELECT_LIST) || + (sl->with_sum_func == 0 && sl->group_list.elements == 0)) && + (tmp= find_field_in_tables(thd, this, table_list, ref, 0, 1)) != not_found_field) { @@ -2029,7 +2074,16 @@ bool Item_ref::fix_fields(THD *thd, TABLE_LIST *tables, Item **reference) // it is primary INSERT st_select_lex => skip first table resolving table_list= table_list->next_local; } - if ((tmp= find_field_in_tables(thd, this, + enum_parsing_place place= prev_subselect_item->parsing_place; + /* + Check table fields only if subquery used somewhere out of HAVING + or SELECT list or outer SELECT do not use groupping (i.e. tables + are accessable) + */ + if (((place != IN_HAVING && + place != SELECT_LIST) || + (sl->with_sum_func == 0 && sl->group_list.elements == 0)) && + (tmp= find_field_in_tables(thd, this, table_list, reference, 0, 1)) != not_found_field) { |