diff options
Diffstat (limited to 'sql/sql_derived.cc')
-rw-r--r-- | sql/sql_derived.cc | 117 |
1 files changed, 61 insertions, 56 deletions
diff --git a/sql/sql_derived.cc b/sql/sql_derived.cc index f7d845e9e36..0a2e2947add 100644 --- a/sql/sql_derived.cc +++ b/sql/sql_derived.cc @@ -1,4 +1,4 @@ -/* Copyright (C) 2000 MySQL AB +/* Copyright (C) 2002-2003 MySQL AB This program is free software; you can redistribute it and/or modify it under the terms of the GNU General Public License as published by @@ -17,7 +17,7 @@ /* Derived tables - These were introduced by Monty and Sinisa <sinisa@mysql.com> + These were introduced by Sinisa <sinisa@mysql.com> */ @@ -38,17 +38,26 @@ static const char *any_db="*any*"; // Special symbol for check_access t TABLE_LIST for the upper SELECT IMPLEMENTATION - - Derived table is resolved with temporary table. It is created based on the - queries defined. After temporary table is created, if this is not EXPLAIN, - then the entire unit / node is deleted. unit is deleted if UNION is used - for derived table and node is deleted is it is a simple SELECT. + Derived table is resolved with temporary table. It is created based on the + queries defined. After temporary table is created, if this is not EXPLAIN, + then the entire unit / node is deleted. unit is deleted if UNION is used + for derived table and node is deleted is it is a simple SELECT. + + After table creation, the above TABLE_LIST is updated with a new table. - After table creation, the above TABLE_LIST is updated with a new table. + This function is called before any command containing derived table + is executed. - This function is called before any command containing derived table is executed. + Derived tables is stored in thd->derived_tables and freed in + close_thread_tables() - TODO: To move creation of derived tables IN open_and_lock_tables() + TODO + Move creation of derived tables in open_and_lock_tables() + + RETURN + 0 ok + 1 Error + -1 Error and error message given */ @@ -57,20 +66,21 @@ int mysql_derived(THD *thd, LEX *lex, SELECT_LEX_UNIT *unit, TABLE_LIST *t) SELECT_LEX *sl= unit->first_select(); List<Item> item_list; TABLE *table; - int res= 0; + int res; select_union *derived_result; TABLE_LIST *tables= (TABLE_LIST *)sl->table_list.first; TMP_TABLE_PARAM tmp_table_param; bool is_union=sl->next_select() && sl->next_select()->linkage == UNION_TYPE; + SELECT_LEX_NODE *save_current_select= lex->current_select; DBUG_ENTER("mysql_derived"); - -/* - In create_total_list, derived tables have to be treated in case of EXPLAIN, - This is because unit/node is not deleted in that case. Current code in this - function has to be improved to recognize better when this function is called - from derived tables and when from other functions. -*/ + /* + In create_total_list, derived tables have to be treated in case of + EXPLAIN, This is because unit/node is not deleted in that + case. Current code in this function has to be improved to + recognize better when this function is called from derived tables + and when from other functions. + */ if (is_union && unit->create_total_list(thd, lex, &tables)) DBUG_RETURN(-1); @@ -91,40 +101,33 @@ int mysql_derived(THD *thd, LEX *lex, SELECT_LEX_UNIT *unit, TABLE_LIST *t) { if (is_union) { -/* - The following code is a re-do of fix_tables_pointers() found in sql_select.cc - for UNION's within derived tables. The only difference is in navigation, as in - derived tables we care for this level only. - - fix_tables_pointers makes sure that in UNION's we do not open single table twice - if found in different SELECT's. - -*/ - for (SELECT_LEX *sel= sl; - sel; - sel= sel->next_select()) - { - for (TABLE_LIST *cursor= (TABLE_LIST *)sel->table_list.first; - cursor; - cursor=cursor->next) - cursor->table= cursor->table_list->table; - } + /* + The following code is a re-do of fix_tables_pointers() found + in sql_select.cc for UNION's within derived tables. The only + difference is in navigation, as in derived tables we care for + this level only. + + */ + for (SELECT_LEX *sel= sl; sel; sel= sel->next_select()) + relink_tables(sel); } + lex->current_select= sl; if (setup_fields(thd,tables,item_list,0,0,1)) { - res=-1; + res= -1; goto exit; } bzero((char*) &tmp_table_param,sizeof(tmp_table_param)); tmp_table_param.field_count=item_list.elements; if (!(table=create_tmp_table(thd, &tmp_table_param, item_list, - (ORDER*) 0, is_union && !unit->union_option, 1, + (ORDER*) 0, + is_union && !unit->union_option, 1, (sl->options | thd->options | TMP_TABLE_ALL_COLUMNS), HA_POS_ERROR))) { - res=-1; + res= -1; goto exit; } @@ -138,10 +141,8 @@ int mysql_derived(THD *thd, LEX *lex, SELECT_LEX_UNIT *unit, TABLE_LIST *t) if (unit->select_limit_cnt == HA_POS_ERROR) sl->options&= ~OPTION_FOUND_ROWS; - SELECT_LEX_NODE *save_current_select= lex->current_select; - lex->current_select= sl; if (is_union) - res=mysql_union(thd,lex,derived_result,unit); + res= mysql_union(thd,lex,derived_result,unit); else res= mysql_select(thd, tables, sl->item_list, sl->where, (ORDER *) sl->order_list.first, @@ -149,13 +150,15 @@ int mysql_derived(THD *thd, LEX *lex, SELECT_LEX_UNIT *unit, TABLE_LIST *t) sl->having, (ORDER*) NULL, sl->options | thd->options | SELECT_NO_UNLOCK, derived_result, unit, sl, 0); - lex->current_select= save_current_select; if (!res) { -// Here we entirely fix both TABLE_LIST and list of SELECT's as there were no derived tables + /* + Here we entirely fix both TABLE_LIST and list of SELECT's as + there were no derived tables + */ if (derived_result->flush()) - res=1; + res= 1; else { t->real_name=table->real_name; @@ -164,27 +167,29 @@ int mysql_derived(THD *thd, LEX *lex, SELECT_LEX_UNIT *unit, TABLE_LIST *t) table->tmp_table=TMP_TABLE; if (lex->describe) { + // to fix a problem in EXPLAIN if (tables) - tables->table_list->table=tables->table; // to fix a problem in EXPLAIN + tables->table_list->table=tables->table; } else - { - if (is_union) - unit->exclude(); - else - sl->exclude(); - } - t->db=(char *)""; - t->derived=(SELECT_LEX *)0; // just in case ... + unit->exclude(); + t->db= (char *)""; + t->derived=(SELECT_LEX *) 1; // just in case ... table->file->info(HA_STATUS_VARIABLE); } } delete derived_result; } if (res) - free_tmp_table(thd,table); + free_tmp_table(thd, table); + else + { + table->next= thd->derived_tables; + thd->derived_tables= table; + } exit: - close_thread_tables(thd); + lex->current_select= save_current_select; + close_thread_tables(thd, 0, 1); } DBUG_RETURN(res); } |