diff options
author | unknown <bell@sanja.is.com.ua> | 2004-02-01 15:30:32 +0200 |
---|---|---|
committer | unknown <bell@sanja.is.com.ua> | 2004-02-01 15:30:32 +0200 |
commit | 68c0a299876b01dbf72cd948708afef4a2c27b47 (patch) | |
tree | 6695a3de384136658355d41c6bd8beba4f4f92ac /sql/sql_derived.cc | |
parent | e7a336d869830cd75581f5dc61bf79000d7050ae (diff) | |
download | mariadb-git-68c0a299876b01dbf72cd948708afef4a2c27b47.tar.gz |
now all tables of query are locked in one place (including derived tables)
fixed BUG#2120 and other problem with EXPLAINing derived tables
mysql-test/r/derived.result:
correct tables names & Co in derived tables
test case for BUG#2120
mysql-test/t/derived.test:
test case for BUG#2120
sql/mysql_priv.h:
derived tables processing moved after open/locking all tables (in open_and_lock_tables)
sql/repl_failsafe.cc:
correct initialization of TABLE_LIST
sql/sql_acl.cc:
used simple table opening without derived table processing to avoid unneeded initialization of SELECT_LEX
sql/sql_base.cc:
derived tables processing moved after open/locking all tables (in open_and_lock_tables)
sql/sql_delete.cc:
all tables processing is done during opening
sql/sql_derived.cc:
derived tables processing moved after open/locking all tables (in open_and_lock_tables) to sutisfy "all query tables locking" at the moment
sql/sql_insert.cc:
all tables processing is done during opening
correct initialization of TABLE_LIST
sql/sql_lex.cc:
now table list will be created for whole query
layout fix
correct check of updated table in subqueries
sql/sql_lex.h:
now table list will be created for whole query
correct check of updated table in subqueries
sql/sql_olap.cc:
THIS FUNCTION IS USED NOWHERE
it will be good to remove it at all (handle_olaps)
sql/sql_parse.cc:
derived tables processing moved after open/locking all tables (in open_and_lock_tables)
sql/sql_prepare.cc:
new creating list parameters
all tables processing is done during opening
sql/sql_select.cc:
all tables processing is done during opening
sql/sql_select.h:
now it used only within file where is defined
sql/sql_udf.cc:
used simple table opening without derived table processing to avoid unneeded initialization of SELECT_LEX
sql/sql_update.cc:
all tables processing is done during opening
Diffstat (limited to 'sql/sql_derived.cc')
-rw-r--r-- | sql/sql_derived.cc | 237 |
1 files changed, 110 insertions, 127 deletions
diff --git a/sql/sql_derived.cc b/sql/sql_derived.cc index 374e56ecdd4..8fa5694714c 100644 --- a/sql/sql_derived.cc +++ b/sql/sql_derived.cc @@ -25,6 +25,49 @@ #include "sql_select.h" #include "sql_acl.h" +int mysql_derived(THD *thd, LEX *lex, SELECT_LEX_UNIT *s, TABLE_LIST *t); + +/* + Resolve derived tables in all queries + + SYNOPSIS + mysql_handle_derived() + lex LEX for this thread + + RETURN + 0 ok + -1 Error + 1 Error and error message given +*/ +int +mysql_handle_derived(LEX *lex) +{ + int res= 0; + if (lex->derived_tables) + { + for (SELECT_LEX *sl= lex->all_selects_list; + sl; + sl= sl->next_select_in_list()) + { + for (TABLE_LIST *cursor= sl->get_table_list(); + cursor; + cursor= cursor->next) + { + if (cursor->derived && (res=mysql_derived(lex->thd, lex, + cursor->derived, + cursor))) + { + if (res < 0 || lex->thd->net.report_error) + send_error(lex->thd, lex->thd->killed ? ER_SERVER_SHUTDOWN : 0); + return 1; + } + } + } + } + return 0; +} + + /* Resolve derived tables in all queries @@ -49,9 +92,6 @@ Derived tables is stored in thd->derived_tables and freed in close_thread_tables() - TODO - Move creation of derived tables in open_and_lock_tables() - RETURN 0 ok 1 Error @@ -72,143 +112,87 @@ int mysql_derived(THD *thd, LEX *lex, SELECT_LEX_UNIT *unit, bool is_subsel= first_select->first_inner_unit() ? 1: 0; SELECT_LEX *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. - */ - if ((is_union || is_subsel) && unit->create_total_list(thd, lex, &tables, 1)) - DBUG_RETURN(-1); + if (!(derived_result= new select_union(0))) + DBUG_RETURN(1); // out of memory + + // st_select_lex_unit::prepare correctly work for single select + if ((res= unit->prepare(thd, derived_result, 0))) + goto exit; + + + derived_result->tmp_table_param.init(); + derived_result->tmp_table_param.field_count= unit->types.elements; /* - We have to do access checks here as this code is executed before any - sql command is started to execute. + Temp table is created so that it hounours if UNION without ALL is to be + processed */ -#ifndef NO_EMBEDDED_ACCESS_CHECKS - if (tables) - res= check_table_access(thd,SELECT_ACL, tables,0); - else - res= check_access(thd, SELECT_ACL, any_db,0,0,0); - if (res) - DBUG_RETURN(1); -#endif - - if (!(res=open_and_lock_tables(thd,tables))) + if (!(table= create_tmp_table(thd, &derived_result->tmp_table_param, + unit->types, (ORDER*) 0, + is_union && !unit->union_option, 1, + (first_select->options | thd->options | + TMP_TABLE_ALL_COLUMNS), + HA_POS_ERROR, + org_table_list->alias))) { - if (is_union || is_subsel) - { - /* - 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(unit); - } + res= -1; + goto exit; + } + derived_result->set_table(table); - if (!(derived_result= new select_union(0))) - DBUG_RETURN(1); // out of memory - // st_select_lex_unit::prepare correctly work for single select - if ((res= unit->prepare(thd, derived_result, 0))) - goto exit; + if (is_union) + res= mysql_union(thd, lex, derived_result, unit); + else + { + unit->offset_limit_cnt= first_select->offset_limit; + unit->select_limit_cnt= first_select->select_limit+ + first_select->offset_limit; + if (unit->select_limit_cnt < first_select->select_limit) + unit->select_limit_cnt= HA_POS_ERROR; + if (unit->select_limit_cnt == HA_POS_ERROR) + first_select->options&= ~OPTION_FOUND_ROWS; + + lex->current_select= first_select; + res= mysql_select(thd, &first_select->ref_pointer_array, + (TABLE_LIST*) first_select->table_list.first, + first_select->with_wild, + first_select->item_list, first_select->where, + (first_select->order_list.elements+ + first_select->group_list.elements), + (ORDER *) first_select->order_list.first, + (ORDER *) first_select->group_list.first, + first_select->having, (ORDER*) NULL, + (first_select->options | thd->options | + SELECT_NO_UNLOCK), + derived_result, unit, first_select); + } - /* - This is done in order to redo all field optimisations when any of the - involved tables is used in the outer query - */ - if (tables) - { - for (TABLE_LIST *cursor= tables; cursor; cursor= cursor->next) - cursor->table->clear_query_id= 1; - } - - derived_result->tmp_table_param.init(); - derived_result->tmp_table_param.field_count= unit->types.elements; + if (!res) + { /* - Temp table is created so that it hounours if UNION without ALL is to be - processed + Here we entirely fix both TABLE_LIST and list of SELECT's as + there were no derived tables */ - if (!(table= create_tmp_table(thd, &derived_result->tmp_table_param, - unit->types, (ORDER*) 0, - is_union && !unit->union_option, 1, - (first_select->options | thd->options | - TMP_TABLE_ALL_COLUMNS), - HA_POS_ERROR, - org_table_list->alias))) - { - res= -1; - goto exit; - } - derived_result->set_table(table); - - if (is_union) - res= mysql_union(thd, lex, derived_result, unit); + if (derived_result->flush()) + res= 1; else { - unit->offset_limit_cnt= first_select->offset_limit; - unit->select_limit_cnt= first_select->select_limit+ - first_select->offset_limit; - if (unit->select_limit_cnt < first_select->select_limit) - unit->select_limit_cnt= HA_POS_ERROR; - if (unit->select_limit_cnt == HA_POS_ERROR) - first_select->options&= ~OPTION_FOUND_ROWS; - - lex->current_select= first_select; - res= mysql_select(thd, &first_select->ref_pointer_array, - (TABLE_LIST*) first_select->table_list.first, - first_select->with_wild, - first_select->item_list, first_select->where, - (first_select->order_list.elements+ - first_select->group_list.elements), - (ORDER *) first_select->order_list.first, - (ORDER *) first_select->group_list.first, - first_select->having, (ORDER*) NULL, - (first_select->options | thd->options | - SELECT_NO_UNLOCK), - derived_result, unit, first_select); - } - - if (!res) - { - /* - Here we entirely fix both TABLE_LIST and list of SELECT's as - there were no derived tables - */ - if (derived_result->flush()) - res= 1; - else + org_table_list->real_name= table->real_name; + org_table_list->table= table; + if (org_table_list->table_list) { - org_table_list->real_name=table->real_name; - org_table_list->table=table; - table->derived_select_number= first_select->select_number; - table->tmp_table= TMP_TABLE; + org_table_list->table_list->real_name= table->real_name; + org_table_list->table_list->table= table; + } + table->derived_select_number= first_select->select_number; + table->tmp_table= TMP_TABLE; #ifndef NO_EMBEDDED_ACCESS_CHECKS - org_table_list->grant.privilege= SELECT_ACL; + org_table_list->grant.privilege= SELECT_ACL; #endif - if (lex->describe) - { - // to fix a problem in EXPLAIN - if (tables) - { - for (TABLE_LIST *cursor= tables; cursor; cursor= cursor->next) - if (cursor->table_list) - cursor->table_list->table=cursor->table; - } - } - else - { - unit->exclude_tree(); - unit->cleanup(); - } - org_table_list->db= (char *)""; - // Force read of table stats in the optimizer - table->file->info(HA_STATUS_VARIABLE); - } + org_table_list->db= (char *)""; + // Force read of table stats in the optimizer + table->file->info(HA_STATUS_VARIABLE); } if (res) @@ -223,7 +207,6 @@ int mysql_derived(THD *thd, LEX *lex, SELECT_LEX_UNIT *unit, exit: delete derived_result; lex->current_select= save_current_select; - close_thread_tables(thd, 0, 1); } DBUG_RETURN(res); } |