diff options
author | cmiller@zippy.cornsilk.net <> | 2007-11-09 14:55:32 -0500 |
---|---|---|
committer | cmiller@zippy.cornsilk.net <> | 2007-11-09 14:55:32 -0500 |
commit | 1426320008b7d17497d0e3c802ccf9b94c20e032 (patch) | |
tree | 80d51cbfd49ff9e193edbb78843eb3e2ebbae2c9 /sql/sql_base.cc | |
parent | f12087af5886e46d458471a0d61b3703d128918f (diff) | |
parent | 6921dd0156939aa8d9230d8690c2eb47d2342d8a (diff) | |
download | mariadb-git-1426320008b7d17497d0e3c802ccf9b94c20e032.tar.gz |
Merge bk-internal.mysql.com:/home/bk/mysql-5.1-community
into zippy.cornsilk.net:/home/cmiller/work/mysql/mysql-5.1-forcollapseandmerge
Diffstat (limited to 'sql/sql_base.cc')
-rw-r--r-- | sql/sql_base.cc | 156 |
1 files changed, 97 insertions, 59 deletions
diff --git a/sql/sql_base.cc b/sql/sql_base.cc index c4c860c48f4..ed0ddbbd15d 100644 --- a/sql/sql_base.cc +++ b/sql/sql_base.cc @@ -44,7 +44,7 @@ public: virtual ~Prelock_error_handler() {} - virtual bool handle_error(uint sql_errno, + virtual bool handle_error(uint sql_errno, const char *message, MYSQL_ERROR::enum_warning_level level, THD *thd); @@ -58,6 +58,7 @@ private: bool Prelock_error_handler::handle_error(uint sql_errno, + const char * /* message */, MYSQL_ERROR::enum_warning_level /* level */, THD * /* thd */) { @@ -1054,6 +1055,29 @@ bool close_cached_connection_tables(THD *thd, bool if_wait_for_refresh, } +/** + Mark all temporary tables which were used by the current statement or + substatement as free for reuse, but only if the query_id can be cleared. + + @param thd thread context + + @remark For temp tables associated with a open SQL HANDLER the query_id + is not reset until the HANDLER is closed. +*/ + +static void mark_temp_tables_as_free_for_reuse(THD *thd) +{ + for (TABLE *table= thd->temporary_tables ; table ; table= table->next) + { + if ((table->query_id == thd->query_id) && ! table->open_by_handler) + { + table->query_id= 0; + table->file->ha_reset(); + } + } +} + + /* Mark all tables in the list which were used by current substatement as free for reuse. @@ -1090,6 +1114,42 @@ static void mark_used_tables_as_free_for_reuse(THD *thd, TABLE *table) } +/** + Auxiliary function to close all tables in the open_tables list. + + @param thd Thread context. + + @remark It should not ordinarily be called directly. +*/ + +static void close_open_tables(THD *thd) +{ + bool found_old_table= 0; + + safe_mutex_assert_not_owner(&LOCK_open); + + VOID(pthread_mutex_lock(&LOCK_open)); + + DBUG_PRINT("info", ("thd->open_tables: 0x%lx", (long) thd->open_tables)); + + while (thd->open_tables) + found_old_table|= close_thread_table(thd, &thd->open_tables); + thd->some_tables_deleted= 0; + + /* Free tables to hold down open files */ + while (open_cache.records > table_cache_size && unused_tables) + VOID(hash_delete(&open_cache,(uchar*) unused_tables)); /* purecov: tested */ + check_unused(); + if (found_old_table) + { + /* Tell threads waiting for refresh that something has happened */ + broadcast_refresh(); + } + + VOID(pthread_mutex_unlock(&LOCK_open)); +} + + /* Close all tables used by the current substatement, or all tables used by this thread if we are on the upper level. @@ -1097,26 +1157,19 @@ static void mark_used_tables_as_free_for_reuse(THD *thd, TABLE *table) SYNOPSIS close_thread_tables() thd Thread handler - lock_in_use Set to 1 (0 = default) if caller has a lock on - LOCK_open - skip_derived Set to 1 (0 = default) if we should not free derived - tables. - stopper When closing tables from thd->open_tables(->next)*, - don't close/remove tables starting from stopper. IMPLEMENTATION Unlocks tables and frees derived tables. Put all normal tables used by thread in free list. - When in prelocked mode it will only close/mark as free for reuse - tables opened by this substatement, it will also check if we are - closing tables after execution of complete query (i.e. we are on - upper level) and will leave prelocked mode if needed. + It will only close/mark as free for reuse tables opened by this + substatement, it will also check if we are closing tables after + execution of complete query (i.e. we are on upper level) and will + leave prelocked mode if needed. */ -void close_thread_tables(THD *thd, bool lock_in_use, bool skip_derived) +void close_thread_tables(THD *thd) { - bool found_old_table; prelocked_mode_type prelocked_mode= thd->prelocked_mode; DBUG_ENTER("close_thread_tables"); @@ -1131,7 +1184,7 @@ void close_thread_tables(THD *thd, bool lock_in_use, bool skip_derived) derived tables with (sub-)statement instead of thread and destroy them at the end of its execution. */ - if (thd->derived_tables && !skip_derived) + if (thd->derived_tables) { TABLE *table, *next; /* @@ -1146,13 +1199,10 @@ void close_thread_tables(THD *thd, bool lock_in_use, bool skip_derived) thd->derived_tables= 0; } - if (prelocked_mode) - { - /* - Mark all temporary tables used by this substatement as free for reuse. - */ - mark_used_tables_as_free_for_reuse(thd, thd->temporary_tables); - } + /* + Mark all temporary tables used by this statement as free for reuse. + */ + mark_temp_tables_as_free_for_reuse(thd); if (thd->locked_tables || prelocked_mode) { @@ -1216,28 +1266,8 @@ void close_thread_tables(THD *thd, bool lock_in_use, bool skip_derived) if (!thd->active_transaction()) thd->transaction.xid_state.xid.null(); - if (!lock_in_use) - VOID(pthread_mutex_lock(&LOCK_open)); - - DBUG_PRINT("info", ("thd->open_tables: 0x%lx", (long) thd->open_tables)); - - found_old_table= 0; - while (thd->open_tables) - found_old_table|= close_thread_table(thd, &thd->open_tables); - thd->some_tables_deleted=0; - - /* Free tables to hold down open files */ - while (open_cache.records > table_cache_size && unused_tables) - VOID(hash_delete(&open_cache,(uchar*) unused_tables)); /* purecov: tested */ - check_unused(); - if (found_old_table) - { - /* Tell threads waiting for refresh that something has happened */ - broadcast_refresh(); - } - if (!lock_in_use) - VOID(pthread_mutex_unlock(&LOCK_open)); - /* VOID(pthread_sigmask(SIG_SETMASK,&thd->signals,NULL)); */ + if (thd->open_tables) + close_open_tables(thd); if (prelocked_mode == PRELOCKED) { @@ -1674,6 +1704,7 @@ TABLE *find_temporary_table(THD *thd, TABLE_LIST *table_list) Try to locate the table in the list of thd->temporary_tables. If the table is found: + - if the table is being used by some outer statement, fail. - if the table is in thd->locked_tables, unlock it and remove it from the list of locked tables. Currently only transactional temporary tables are present in the locked_tables list. @@ -1688,24 +1719,34 @@ TABLE *find_temporary_table(THD *thd, TABLE_LIST *table_list) thd->temporary_tables list, it's impossible to tell here whether we're dealing with an internal or a user temporary table. - @retval TRUE the table was not found in the list of temporary tables - of this thread - @retval FALSE the table was found and dropped successfully. + @retval 0 the table was found and dropped successfully. + @retval 1 the table was not found in the list of temporary tables + of this thread + @retval -1 the table is in use by a outer query */ -bool close_temporary_table(THD *thd, TABLE_LIST *table_list) +int drop_temporary_table(THD *thd, TABLE_LIST *table_list) { TABLE *table; + DBUG_ENTER("drop_temporary_table"); if (!(table= find_temporary_table(thd, table_list))) - return 1; + DBUG_RETURN(1); + + /* Table might be in use by some outer statement. */ + if (table->query_id && table->query_id != thd->query_id) + { + my_error(ER_CANT_REOPEN_TABLE, MYF(0), table->alias); + DBUG_RETURN(-1); + } + /* If LOCK TABLES list is not empty and contains this table, unlock the table and remove the table from this list. */ mysql_lock_remove(thd, thd->locked_tables, table, FALSE); close_temporary_table(thd, table, 1, 1); - return 0; + DBUG_RETURN(0); } /* @@ -2284,8 +2325,7 @@ TABLE *open_table(THD *thd, TABLE_LIST *table_list, MEM_ROOT *mem_root, is always represented by only one TABLE object in THD, and it can not be cloned. Emit an error for an unsupported behaviour. */ - if (table->query_id == thd->query_id || - thd->prelocked_mode && table->query_id) + if (table->query_id) { DBUG_PRINT("error", ("query_id: %lu server_id: %u pseudo_thread_id: %lu", @@ -2295,7 +2335,6 @@ TABLE *open_table(THD *thd, TABLE_LIST *table_list, MEM_ROOT *mem_root, DBUG_RETURN(0); } table->query_id= thd->query_id; - table->clear_query_id= 1; thd->thread_specific_used= TRUE; DBUG_PRINT("info",("Using temporary table")); goto reset; @@ -4305,7 +4344,6 @@ void close_tables_for_reopen(THD *thd, TABLE_LIST **tables) sp_remove_not_own_routines(thd->lex); for (TABLE_LIST *tmp= *tables; tmp; tmp= tmp->next_global) tmp->table= 0; - mark_used_tables_as_free_for_reuse(thd, thd->temporary_tables); close_thread_tables(thd); } @@ -6260,7 +6298,7 @@ bool setup_fields(THD *thd, Item **ref_pointer_array, thd->lex->allow_sum_func= save_allow_sum_func; thd->mark_used_columns= save_mark_used_columns; DBUG_PRINT("info", ("thd->mark_used_columns: %d", thd->mark_used_columns)); - DBUG_RETURN(test(thd->net.report_error)); + DBUG_RETURN(test(thd->is_error())); } @@ -6804,7 +6842,7 @@ int setup_conds(THD *thd, TABLE_LIST *tables, TABLE_LIST *leaves, select_lex->conds_processed_with_permanent_arena= 1; } thd->lex->current_select->is_item_list_lookup= save_is_item_list_lookup; - DBUG_RETURN(test(thd->net.report_error)); + DBUG_RETURN(test(thd->is_error())); err_no_arena: select_lex->is_item_list_lookup= save_is_item_list_lookup; @@ -6886,7 +6924,7 @@ fill_record(THD * thd, List<Item> &fields, List<Item> &values, goto err; } } - DBUG_RETURN(thd->net.report_error); + DBUG_RETURN(thd->is_error()); err: if (table) table->auto_increment_field_not_null= FALSE; @@ -6971,7 +7009,7 @@ fill_record(THD *thd, Field **ptr, List<Item> &values, bool ignore_errors) table= (*ptr)->table; table->auto_increment_field_not_null= FALSE; } - while ((field = *ptr++) && !thd->net.report_error) + while ((field = *ptr++) && ! thd->is_error()) { value=v++; table= field->table; @@ -6980,7 +7018,7 @@ fill_record(THD *thd, Field **ptr, List<Item> &values, bool ignore_errors) if (value->save_in_field(field, 0) < 0) goto err; } - DBUG_RETURN(thd->net.report_error); + DBUG_RETURN(thd->is_error()); err: if (table) @@ -7390,7 +7428,7 @@ open_new_frm(THD *thd, TABLE_SHARE *share, const char *alias, else { /* only VIEWs are supported now */ - my_error(ER_FRM_UNKNOWN_TYPE, MYF(0), share->path, parser->type()->str); + my_error(ER_FRM_UNKNOWN_TYPE, MYF(0), share->path.str, parser->type()->str); goto err; } DBUG_RETURN(0); |