From 974c29b97b1ce2fe09693d4f711c54ae697fdb5b Mon Sep 17 00:00:00 2001 From: "timour@mysql.com" <> Date: Tue, 9 Nov 2004 17:56:33 +0200 Subject: [PATCH] WL#1972 "Evaluate HAVING before SELECT select-list" - post-review fix regarding Item_fields - added test for the changed name resolution --- mysql-test/r/having.result | 7 + mysql-test/t/having.test | 6 +- sql/item.cc | 604 +++++++++++++++++++------------------ 3 files changed, 318 insertions(+), 299 deletions(-) diff --git a/mysql-test/r/having.result b/mysql-test/r/having.result index 6f548d20668..86c9adf8cf6 100644 --- a/mysql-test/r/having.result +++ b/mysql-test/r/having.result @@ -245,6 +245,13 @@ col1 10 10 10 +select sum(col1) from t1 +group by col_t1 +having (select col_t1 from t2 where col_t1 = col_t2 order by col_t2 limit 1); +sum(col1) +40 +20 +30 select t1.col1 from t1 where t1.col2 in (select t2.col2 from t2 diff --git a/mysql-test/t/having.test b/mysql-test/t/having.test index d2a5ca4361e..b0fc600030b 100644 --- a/mysql-test/t/having.test +++ b/mysql-test/t/having.test @@ -211,6 +211,11 @@ where t1.col2 in (select t2.col2 from t2 group by t2.col1, t2.col2 having col_t1 <= 10); +# Item_field must be resolved in the same way as Item_ref +select sum(col1) from t1 +group by col_t1 +having (select col_t1 from t2 where col_t1 = col_t2 order by col_t2 limit 1); + # nested queries with HAVING, inner having column resolved in outer FROM clause # the outer having column is not referenced in GROUP BY which results in an error --error 1054 @@ -256,7 +261,6 @@ group by col_t1 having col_t1 in (select sum(t2.col1) from t2 group by t2.col2, t2.col1 having t2.col1 = col_t1); - # # queries with joins and ambiguous column names # diff --git a/sql/item.cc b/sql/item.cc index 8b611f0ddb5..919bce36280 100644 --- a/sql/item.cc +++ b/sql/item.cc @@ -1390,113 +1390,312 @@ static void mark_as_dependent(THD *thd, SELECT_LEX *last, SELECT_LEX *current, } -bool Item_field::fix_fields(THD *thd, TABLE_LIST *tables, Item **ref) +/* + Search a GROUP BY clause for a field with a certain name. + + SYNOPSIS + find_field_in_group_list() + find_item the item being searched for + group_list GROUP BY clause + + DESCRIPTION + Search the GROUP BY list for a column named as find_item. When searching + preference is given to columns that are qualified with the same table (and + database) name as the one being searched for. + + RETURN + - the found item on success + - NULL if find_item is not in group_list +*/ + +static Item** find_field_in_group_list(Item *find_item, ORDER *group_list) +{ + const char *db_name; + const char *table_name; + const char *field_name; + ORDER *found_group= NULL; + int found_match_degree= 0; + Item_field *cur_field; + int cur_match_degree= 0; + + if (find_item->type() == Item::FIELD_ITEM || + find_item->type() == Item::REF_ITEM) + { + db_name= ((Item_ident*) find_item)->db_name; + table_name= ((Item_ident*) find_item)->table_name; + field_name= ((Item_ident*) find_item)->field_name; + } + else + return NULL; + + DBUG_ASSERT(field_name); + + for (ORDER *cur_group= group_list ; cur_group ; cur_group= cur_group->next) + { + if ((*(cur_group->item))->type() == Item::FIELD_ITEM) + { + cur_field= (Item_field*) *cur_group->item; + cur_match_degree= 0; + + DBUG_ASSERT(cur_field->field_name); + + if (!my_strcasecmp(system_charset_info, + cur_field->field_name, field_name)) + ++cur_match_degree; + else + continue; + + if (cur_field->table_name && table_name) + { + /* If field_name is qualified by a table name. */ + if (strcmp(cur_field->table_name, table_name)) + /* Same field names, different tables. */ + return NULL; + + ++cur_match_degree; + if (cur_field->db_name && db_name) + { + /* If field_name is also qualified by a database name. */ + if (strcmp(cur_field->db_name, db_name)) + /* Same field names, different databases. */ + return NULL; + ++cur_match_degree; + } + } + + if (cur_match_degree > found_match_degree) + { + found_match_degree= cur_match_degree; + found_group= cur_group; + } + else if (found_group && (cur_match_degree == found_match_degree) && + ! (*(found_group->item))->eq(cur_field, 0)) + { + /* + If the current resolve candidate matches equally well as the current + best match, they must reference the same column, otherwise the field + is ambiguous. + */ + my_printf_error(ER_NON_UNIQ_ERROR, ER(ER_NON_UNIQ_ERROR), + MYF(0), find_item->full_name(), current_thd->where); + return NULL; + } + } + } + + if (found_group) + return found_group->item; + else + return NULL; +} + + +/* + Resolve a column reference in a sub-select. + + SYNOPSIS + resolve_ref_in_select_and_group() + thd current thread + ref column reference being resolved + select the sub-select that ref is resolved against + + DESCRIPTION + Resolve a column reference (usually inside a HAVING clause) against the + SELECT and GROUP BY clauses of the query described by 'select'. The name + resolution algorithm searches both the SELECT and GROUP BY clauses, and in + case of a name conflict prefers GROUP BY column names over SELECT names. If + both clauses contain different fields with the same names, a warning is + issued that name of 'ref' is ambiguous. We extend ANSI SQL in that when no + GROUP BY column is found, then a HAVING name is resolved as a possibly + derived SELECT column. + + NOTES + The resolution procedure is: + - Search for a column or derived column named col_ref_i [in table T_j] + in the SELECT clause of Q. + - Search for a column named col_ref_i [in table T_j] + in the GROUP BY clause of Q. + - If found different columns with the same name in GROUP BY and SELECT + - issue a warning and return the GROUP BY column, + - otherwise return the found SELECT column. + + + RETURN + NULL - there was an error, and the error was already reported + not_found_item - the item was not resolved, no error was reported + resolved item - if the item was resolved +*/ + +static Item** +resolve_ref_in_select_and_group(THD *thd, Item_ident *ref, SELECT_LEX *select) +{ + Item **group_by_ref= NULL; + Item **select_ref= NULL; + ORDER *group_list= (ORDER*) select->group_list.first; + bool ambiguous_fields= FALSE; + uint counter; + + /* + Search for a column or derived column named as 'ref' in the SELECT + clause of the current select. + */ + if (!(select_ref= find_item_in_list(ref, *(select->get_item_list()), &counter, + REPORT_EXCEPT_NOT_FOUND))) + return NULL; /* Some error occurred. */ + + /* If this is a non-aggregated field inside HAVING, search in GROUP BY. */ + if (select->having_fix_field && !ref->with_sum_func && group_list) + { + group_by_ref= find_field_in_group_list(ref, group_list); + + /* Check if the fields found in SELECT and GROUP BY are the same field. */ + if (group_by_ref && (select_ref != not_found_item) && + !((*group_by_ref)->eq(*select_ref, 0))) + { + ambiguous_fields= TRUE; + push_warning_printf(thd, MYSQL_ERROR::WARN_LEVEL_WARN, ER_NON_UNIQ_ERROR, + ER(ER_NON_UNIQ_ERROR), ref->full_name(), + current_thd->where); + + } + } + + if (select_ref != not_found_item || group_by_ref) + { + if (select_ref != not_found_item && !ambiguous_fields) + { + if (*select_ref && !(*select_ref)->fixed) + { + my_error(ER_ILLEGAL_REFERENCE, MYF(0), ref->name, + "forward reference in item list"); + return NULL; + } + return (select->ref_pointer_array + counter); + } + else if (group_by_ref) + return group_by_ref; + else + DBUG_ASSERT(FALSE); + } + else + return (Item**) not_found_item; +} + + +bool Item_field::fix_fields(THD *thd, TABLE_LIST *tables, Item **reference) { DBUG_ASSERT(fixed == 0); if (!field) // If field is not checked { - bool upward_lookup= 0; - Field *tmp= (Field *)not_found_field; - if ((tmp= find_field_in_tables(thd, this, tables, ref, + bool upward_lookup= FALSE; + Field *from_field= (Field *)not_found_field; + if ((from_field= find_field_in_tables(thd, this, tables, reference, IGNORE_EXCEPT_NON_UNIQUE, !any_privileges)) == not_found_field) { - /* - We can't find table field in table list of current select, - consequently we have to find it in outer subselect(s). - We can't join lists of outer & current select, because of scope - of view rules. For example if both tables (outer & current) have - field 'field' it is not mistake to refer to this field without - mention of table name, but if we join tables in one list it will - cause error ER_NON_UNIQ_ERROR in find_field_in_tables. - */ - SELECT_LEX *last= 0; #ifdef EMBEDDED_LIBRARY thd->net.last_errno= 0; #endif + SELECT_LEX *last= 0; TABLE_LIST *table_list; - Item **refer= (Item **)not_found_item; - uint counter; - // 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) + Item **ref= (Item **) not_found_item; + SELECT_LEX *current_sel= (SELECT_LEX *) thd->lex->current_select; + /* + If there is an outer select, and it is not a derived table (which do + not support the use of outer fields for now), try to resolve this + reference in the outer select(s). + + We treat each subselect as a separate namespace, so that different + subselects may contain columns with the same names. The subselects are + searched starting from the innermost. + */ + if (current_sel->master_unit()->first_select()->linkage != + DERIVED_TABLE_TYPE) { - SELECT_LEX_UNIT *prev_unit= cursel->master_unit(); - for (SELECT_LEX *sl= prev_unit->outer_select(); - sl; - sl= (prev_unit= sl->master_unit())->outer_select()) + SELECT_LEX_UNIT *prev_unit= current_sel->master_unit(); + SELECT_LEX *outer_sel= prev_unit->outer_select(); + for ( ; outer_sel ; + outer_sel= (prev_unit= outer_sel->master_unit())->outer_select()) { - upward_lookup= 1; - table_list= (last= sl)->get_table_list(); - if (sl->resolve_mode == SELECT_LEX::INSERT_MODE && table_list) - { + last= outer_sel; + Item_subselect *prev_subselect_item= prev_unit->item; + upward_lookup= TRUE; + + /* Search in the tables of the FROM clause of the outer select. */ + table_list= outer_sel->get_table_list(); + if (outer_sel->resolve_mode == SELECT_LEX::INSERT_MODE && table_list) /* - it is primary INSERT st_select_lex => skip first table - resolving + It is a primary INSERT st_select_lex => do not resolve against the + first table. */ table_list= table_list->next_local; - } - Item_subselect *prev_subselect_item= prev_unit->item; 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) + Check table fields only if the subquery is used somewhere out of + HAVING or SELECT list, or the outer SELECT does not use grouping + (i.e. tables are accessible). */ - 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, - IGNORE_EXCEPT_NON_UNIQUE, 1)) != + if (((place != IN_HAVING && place != SELECT_LIST) || + (outer_sel->with_sum_func == 0 && + outer_sel->group_list.elements == 0)) && + (from_field= find_field_in_tables(thd, this, table_list, + reference, + IGNORE_EXCEPT_NON_UNIQUE, + TRUE)) != not_found_field) { - if (tmp) + if (from_field) { - if (tmp != view_ref_found) + if (from_field != view_ref_found) { - prev_subselect_item->used_tables_cache|= tmp->table->map; + prev_subselect_item->used_tables_cache|= from_field->table->map; prev_subselect_item->const_item_cache= 0; } else { prev_subselect_item->used_tables_cache|= - (*ref)->used_tables(); + (*reference)->used_tables(); prev_subselect_item->const_item_cache&= - (*ref)->const_item(); + (*reference)->const_item(); } } break; } - if (sl->resolve_mode == SELECT_LEX::SELECT_MODE && - (refer= find_item_in_list(this, sl->item_list, &counter, - REPORT_EXCEPT_NOT_FOUND)) != - (Item **) not_found_item) + + /* Search in the SELECT and GROUP lists of the outer select. */ + if (outer_sel->resolve_mode == SELECT_LEX::SELECT_MODE) { - if (*refer && (*refer)->fixed) // Avoid crash in case of error - { - prev_subselect_item->used_tables_cache|= (*refer)->used_tables(); - prev_subselect_item->const_item_cache&= (*refer)->const_item(); - } - break; + if (!(ref= resolve_ref_in_select_and_group(thd, this, outer_sel))) + return TRUE; /* Some error occured (e.g. ambigous names). */ + if (ref != not_found_item) + { + DBUG_ASSERT(*ref && (*ref)->fixed); + /* + Avoid crash in case of error. + TODO: what does this comment mean? + */ + prev_subselect_item->used_tables_cache|= (*ref)->used_tables(); + prev_subselect_item->const_item_cache&= (*ref)->const_item(); + break; + } } // Reference is not found => depend from outer (or just error) prev_subselect_item->used_tables_cache|= OUTER_REF_TABLE_BIT; prev_subselect_item->const_item_cache= 0; - if (sl->master_unit()->first_select()->linkage == + if (outer_sel->master_unit()->first_select()->linkage == DERIVED_TABLE_TYPE) break; // do not look over derived table } } - if (!tmp) - return -1; - if (!refer) - return 1; - if (tmp == not_found_field && refer == (Item **)not_found_item) + + DBUG_ASSERT(ref); + if (!from_field) + return TRUE; + if (ref == not_found_item && from_field == not_found_field) { if (upward_lookup) { @@ -1507,59 +1706,54 @@ bool Item_field::fix_fields(THD *thd, TABLE_LIST *tables, Item **ref) else { // Call to report error - find_field_in_tables(thd, this, tables, ref, REPORT_ALL_ERRORS, 1); + find_field_in_tables(thd, this, tables, reference, REPORT_ALL_ERRORS, + TRUE); } - return -1; + return TRUE; } - else if (refer != (Item **)not_found_item) + else if (ref != not_found_item) { - if (!(*refer)->fixed) - { - my_error(ER_ILLEGAL_REFERENCE, MYF(0), name, - "forward reference in item list"); - return -1; - } + /* Should be checked in resolve_ref_in_select_and_group(). */ + DBUG_ASSERT(*ref && (*ref)->fixed); Item_ref *rf; - *ref= rf= new Item_ref(last->ref_pointer_array + counter, - ref, - (char *)table_name, - (char *)field_name); - register_item_tree_changing(ref); + *reference= rf= new Item_ref(ref, reference, (char *) table_name, + (char *) field_name); + register_item_tree_changing(reference); if (!rf) - return 1; + return TRUE; /* rf is Item_ref => never substitute other items (in this case) during fix_fields() => we can use rf after fix_fields() */ - if (rf->fix_fields(thd, tables, ref) || rf->check_cols(1)) - return 1; + if (rf->fix_fields(thd, tables, reference) || rf->check_cols(1)) + return TRUE; - mark_as_dependent(thd, last, cursel, rf); - return 0; + mark_as_dependent(thd, last, current_sel, rf); + return FALSE; } else { - mark_as_dependent(thd, last, cursel, this); + mark_as_dependent(thd, last, current_sel, this); if (last->having_fix_field) { Item_ref *rf; - *ref= rf= new Item_ref(ref, *ref, - (cached_table->db[0]?cached_table->db:0), - (char *)cached_table->alias, - (char *)field_name); + *reference= rf= new Item_ref(reference, *reference, + (cached_table->db[0]?cached_table->db:0), + (char *)cached_table->alias, + (char *)field_name); if (!rf) - return 1; + return TRUE; /* rf is Item_ref => never substitute other items (in this case) during fix_fields() => we can use rf after fix_fields() */ - return rf->fix_fields(thd, tables, ref) || rf->check_cols(1); + return rf->fix_fields(thd, tables, reference) || rf->check_cols(1); } } } - else if (!tmp) - return -1; + else if (!from_field) + return TRUE; /* if it is not expression from merged VIEW we will set this field. @@ -1573,8 +1767,8 @@ bool Item_field::fix_fields(THD *thd, TABLE_LIST *tables, Item **ref) Also we suppose that view can't be changed during PS/SP life. */ - if (tmp != view_ref_found) - set_field(tmp); + if (from_field != view_ref_found) + set_field(from_field); } else if (thd->set_query_id && field->query_id != thd->query_id) { @@ -1610,12 +1804,12 @@ bool Item_field::fix_fields(THD *thd, TABLE_LIST *tables, Item **ref) thd->host_or_ip, field_name, tab); - return 1; + return TRUE; } } #endif fixed= 1; - return 0; + return FALSE; } void Item_field::cleanup() @@ -2265,197 +2459,6 @@ bool Item_field::send(Protocol *protocol, String *buffer) } -/* - Search a GROUP BY clause for a field with a certain name. - - SYNOPSIS - find_field_in_group_list() - find_item the item being searched for - group_list GROUP BY clause - - DESCRIPTION - Search the GROUP BY list for a column named as find_item. When searching - preference is given to columns that are qualified with the same table (and - database) name as the one being searched for. - - RETURN - - the found item on success - - NULL if find_item is not in group_list -*/ - -static Item** find_field_in_group_list(Item *find_item, ORDER *group_list) -{ - const char *db_name; - const char *table_name; - const char *field_name; - ORDER *found_group= NULL; - int found_match_degree= 0; - Item_field *cur_field; - int cur_match_degree= 0; - - if (find_item->type() == Item::FIELD_ITEM || - find_item->type() == Item::REF_ITEM) - { - db_name= ((Item_ident*) find_item)->db_name; - table_name= ((Item_ident*) find_item)->table_name; - field_name= ((Item_ident*) find_item)->field_name; - } - else - return NULL; - - DBUG_ASSERT(field_name); - - for (ORDER *cur_group= group_list ; cur_group ; cur_group= cur_group->next) - { - if ((*(cur_group->item))->type() == Item::FIELD_ITEM) - { - cur_field= (Item_field*) *cur_group->item; - cur_match_degree= 0; - - DBUG_ASSERT(cur_field->field_name); - - if (!my_strcasecmp(system_charset_info, - cur_field->field_name, field_name)) - ++cur_match_degree; - else - continue; - - if (cur_field->table_name && table_name) - { - /* If field_name is qualified by a table name. */ - if (strcmp(cur_field->table_name, table_name)) - /* Same field names, different tables. */ - return NULL; - - ++cur_match_degree; - if (cur_field->db_name && db_name) - { - /* If field_name is also qualified by a database name. */ - if (strcmp(cur_field->db_name, db_name)) - /* Same field names, different databases. */ - return NULL; - ++cur_match_degree; - } - } - - if (cur_match_degree > found_match_degree) - { - found_match_degree= cur_match_degree; - found_group= cur_group; - } - else if (found_group && (cur_match_degree == found_match_degree) && - ! (*(found_group->item))->eq(cur_field, 0)) - { - /* - If the current resolve candidate matches equally well as the current - best match, they must reference the same column, otherwise the field - is ambiguous. - */ - my_printf_error(ER_NON_UNIQ_ERROR, ER(ER_NON_UNIQ_ERROR), - MYF(0), find_item->full_name(), current_thd->where); - return NULL; - } - } - } - - if (found_group) - return found_group->item; - else - return NULL; -} - - -/* - Resolve a column reference in a sub-select. - - SYNOPSIS - resolve_ref_in_select_and_group() - thd current thread - ref column reference being resolved - select the sub-select that ref is resolved against - - DESCRIPTION - Resolve a column reference (usually inside a HAVING clause) against the - SELECT and GROUP BY clauses of the query described by 'select'. The name - resolution algorithm searches both the SELECT and GROUP BY clauses, and in - case of a name conflict prefers GROUP BY column names over SELECT names. If - both clauses contain different fields with the same names, a warning is - issued that name of 'ref' is ambiguous. We extend ANSI SQL in that when no - GROUP BY column is found, then a HAVING name is resolved as a possibly - derived SELECT column. - - NOTES - The resolution procedure is: - - Search for a column or derived column named col_ref_i [in table T_j] - in the SELECT clause of Q. - - Search for a column named col_ref_i [in table T_j] - in the GROUP BY clause of Q. - - If found different columns with the same name in GROUP BY and SELECT - - issue a warning and return the GROUP BY column, - - otherwise return the found SELECT column. - - - RETURN - NULL - there was an error, and the error was already reported - not_found_item - the item was not resolved, no error was reported - resolved item - if the item was resolved -*/ -static Item** -resolve_ref_in_select_and_group(THD *thd, Item_ref *ref, SELECT_LEX *select) -{ - Item **group_by_ref= NULL; - Item **select_ref= NULL; - ORDER *group_list= (ORDER*) select->group_list.first; - bool ambiguous_fields= FALSE; - uint counter; - - /* - Search for a column or derived column named as 'ref' in the SELECT - clause of the current select. - */ - if (!(select_ref= find_item_in_list(ref, *(select->get_item_list()), &counter, - REPORT_EXCEPT_NOT_FOUND))) - return NULL; /* Some error occurred. */ - - /* If this is a non-aggregated field inside HAVING, search in GROUP BY. */ - if (select->having_fix_field && !ref->with_sum_func && group_list) - { - group_by_ref= find_field_in_group_list(ref, group_list); - - /* Check if the fields found in SELECT and GROUP BY are the same field. */ - if (group_by_ref && (select_ref != not_found_item) && - !((*group_by_ref)->eq(*select_ref, 0))) - { - ambiguous_fields= TRUE; - push_warning_printf(thd, MYSQL_ERROR::WARN_LEVEL_WARN, ER_NON_UNIQ_ERROR, - ER(ER_NON_UNIQ_ERROR), ref->full_name(), - current_thd->where); - - } - } - - if (select_ref != not_found_item || group_by_ref) - { - if (select_ref != not_found_item && !ambiguous_fields) - { - if (*select_ref && !(*select_ref)->fixed) - { - my_error(ER_ILLEGAL_REFERENCE, MYF(0), ref->name, - "forward reference in item list"); - return NULL; - } - return (select->ref_pointer_array + counter); - } - else if (group_by_ref) - return group_by_ref; - else - DBUG_ASSERT(FALSE); - } - else - return (Item**) not_found_item; -} - - /* Resolve the name of a column reference. @@ -2539,7 +2542,7 @@ bool Item_ref::fix_fields(THD *thd, TABLE_LIST *tables, Item **reference) DERIVED_TABLE_TYPE)) { TABLE_LIST *table_list; - Field *tmp= (Field*) not_found_field; + Field *from_field= (Field*) not_found_field; SELECT_LEX *last= 0; for ( ; outer_sel ; @@ -2569,14 +2572,16 @@ bool Item_ref::fix_fields(THD *thd, TABLE_LIST *tables, Item **reference) /* Search in the tables of the FROM clause of the outer select. */ table_list= outer_sel->get_table_list(); if (outer_sel->resolve_mode == SELECT_LEX::INSERT_MODE && table_list) - { - /* It is primary INSERT st_select_lex => skip the first table. */ + /* + It is a primary INSERT st_select_lex => do not resolve against the + first table. + */ table_list= table_list->next_local; - } + enum_parsing_place place= prev_subselect_item->parsing_place; /* Check table fields only if the subquery is used somewhere out of - HAVING or SELECT list, or outer SELECT does not use grouping + HAVING or SELECT list, or the outer SELECT does not use grouping (i.e. tables are accessible). TODO: Here we could first find the field anyway, and then test this @@ -2588,13 +2593,15 @@ bool Item_ref::fix_fields(THD *thd, TABLE_LIST *tables, Item **reference) (!outer_sel->with_sum_func && outer_sel->group_list.elements == 0))) { - if ((tmp= find_field_in_tables(thd, this, table_list, reference, - IGNORE_EXCEPT_NON_UNIQUE, TRUE)) != + if ((from_field= find_field_in_tables(thd, this, table_list, + reference, + IGNORE_EXCEPT_NON_UNIQUE, + TRUE)) != not_found_field) { - if (tmp != view_ref_found) + if (from_field != view_ref_found) { - prev_subselect_item->used_tables_cache|= tmp->table->map; + prev_subselect_item->used_tables_cache|= from_field->table->map; prev_subselect_item->const_item_cache= 0; } else @@ -2618,21 +2625,21 @@ bool Item_ref::fix_fields(THD *thd, TABLE_LIST *tables, Item **reference) } DBUG_ASSERT(ref); - if (!tmp) + if (!from_field) return TRUE; - else if (ref == not_found_item && tmp == not_found_field) + if (ref == not_found_item && from_field == not_found_field) { my_printf_error(ER_BAD_FIELD_ERROR, ER(ER_BAD_FIELD_ERROR), MYF(0), this->full_name(), current_thd->where); ref= 0; return TRUE; } - else if (tmp != not_found_field) + else if (from_field != not_found_field) { ref= 0; // To prevent "delete *ref;" on ~Item_ref() of this item - if (tmp != view_ref_found) + if (from_field != view_ref_found) { - Item_field* fld= new Item_field(tmp); + Item_field* fld= new Item_field(from_field); if (!((*reference)= fld)) return TRUE; mark_as_dependent(thd, last, current_sel, fld); @@ -2652,6 +2659,7 @@ bool Item_ref::fix_fields(THD *thd, TABLE_LIST *tables, Item **reference) } else { + /* Should be checked in resolve_ref_in_select_and_group(). */ DBUG_ASSERT(*ref && (*ref)->fixed); mark_as_dependent(thd, last, current_sel, this); } -- 2.30.9