diff options
author | Konstantin Osipov <kostja@sun.com> | 2009-12-01 17:39:03 +0300 |
---|---|---|
committer | Konstantin Osipov <kostja@sun.com> | 2009-12-01 17:39:03 +0300 |
commit | 5969dcda21f67b18d2cb443db555d2b1c087bb62 (patch) | |
tree | 289ce39f293fe8250f3dac5ac3d34c4e90909125 /sql | |
parent | 1b078b3f2df729859807d3905cf3e0b9f1b8d29c (diff) | |
download | mariadb-git-5969dcda21f67b18d2cb443db555d2b1c087bb62.tar.gz |
Backport of:
----------------------------------------------------------
revno: 2630.4.26
committer: Konstantin Osipov <konstantin@mysql.com>
branch nick: mysql-6.0-prelocked_mode-to-push
timestamp: Fri 2008-06-06 23:19:04 +0400
message:
WL#3726: work on review comments.
Remove thd->locked_tables. Always store MYSQL_LOCK instances in
thd->lock.
Rename thd->prelocked_mode to thd->locked_tables_mode.
Use thd->locked_tables_mode to determine if we
are under LOCK TABLES. Update the code to not assume that
if thd->lock is set, LOCK TABLES mode is off.
Review comments.
sql/ha_ndbcluster_binlog.cc:
Don't unlock the lock under LOCK TABLES (safety).
sql/handler.cc:
There is no thd->locked_tables any more.
Update comments.
sql/lock.cc:
There is no thd->locked_tables any more.
sql/log.cc:
Rename thd->prelocked_mode to thd->locked_tables_mode.
sql/set_var.cc:
Use thd->locked_tables_mode to determine if we are under LOCK TABLES.
sql/sp_head.cc:
Rename thd->prelocked_mode to thd->locked_tables_mode.
sql/sql_base.cc:
Use thd->locked_tables_mode to determine if we are under LOCK TABLES.
Remove thd->locked_tables.
sql/sql_cache.cc:
Use thd->locked_tables_mode to determine if we are under LOCK TABLES.
sql/sql_class.cc:
Avoid code duplication.
Do not release the table locks prematurely if we're under LOCK TABLES.
Use thd->locked_tables_mode instead of thd->locked_tables.
sql/sql_class.h:
Remove thd->locked_tables.
Make prelocked mode a kind of LOCK TABLES mode.
Update comments.
sql/sql_cursor.cc:
Update comments.
sql/sql_insert.cc:
Use thd->locked_tables_mode to determine if we are under LOCK TABLES.
Rename thd->prelocked_mode to thd->locked_tables_mode.
sql/sql_load.cc:
Rename thd->prelocked_mode to thd->locked_tables_mode.
sql/sql_parse.cc:
Use thd->locked_tables_mode to determine if we are under LOCK TABLES.
Remove thd->locked_tables.
sql/sql_partition.cc:
Use thd->locked_tables_mode to determine if we are under LOCK TABLES.
sql/sql_rename.cc:
Use thd->locked_tables_mode to determine if we are under LOCK TABLES.
sql/sql_select.cc:
Use thd->locked_tables_mode to determine if we are under LOCK TABLES.
sql/sql_table.cc:
Use thd->locked_tables_mode to determine if we are under LOCK TABLES.
sql/sql_trigger.cc:
Use thd->locked_tables_mode to determine if we are under LOCK TABLES.
sql/sql_update.cc:
Use thd->locked_tables_mode to determine if we are under LOCK TABLES.
sql/sql_view.cc:
Use thd->locked_tables_mode to determine if we are under LOCK TABLES.
storage/myisam/ha_myisam.cc:
Use thd->locked_tables_mode to determine if we are under LOCK TABLES.
Diffstat (limited to 'sql')
-rw-r--r-- | sql/ha_ndbcluster_binlog.cc | 10 | ||||
-rw-r--r-- | sql/handler.cc | 13 | ||||
-rw-r--r-- | sql/lock.cc | 2 | ||||
-rw-r--r-- | sql/log.cc | 2 | ||||
-rw-r--r-- | sql/set_var.cc | 2 | ||||
-rw-r--r-- | sql/sp_head.cc | 6 | ||||
-rw-r--r-- | sql/sql_base.cc | 165 | ||||
-rw-r--r-- | sql/sql_cache.cc | 4 | ||||
-rw-r--r-- | sql/sql_class.cc | 14 | ||||
-rw-r--r-- | sql/sql_class.h | 80 | ||||
-rw-r--r-- | sql/sql_cursor.cc | 2 | ||||
-rw-r--r-- | sql/sql_insert.cc | 28 | ||||
-rw-r--r-- | sql/sql_load.cc | 5 | ||||
-rw-r--r-- | sql/sql_parse.cc | 42 | ||||
-rw-r--r-- | sql/sql_partition.cc | 2 | ||||
-rw-r--r-- | sql/sql_rename.cc | 2 | ||||
-rw-r--r-- | sql/sql_select.cc | 4 | ||||
-rw-r--r-- | sql/sql_table.cc | 26 | ||||
-rw-r--r-- | sql/sql_trigger.cc | 8 | ||||
-rw-r--r-- | sql/sql_update.cc | 2 | ||||
-rw-r--r-- | sql/sql_view.cc | 4 |
21 files changed, 209 insertions, 214 deletions
diff --git a/sql/ha_ndbcluster_binlog.cc b/sql/ha_ndbcluster_binlog.cc index 14d14db6b7d..6f0e4498d75 100644 --- a/sql/ha_ndbcluster_binlog.cc +++ b/sql/ha_ndbcluster_binlog.cc @@ -264,7 +264,7 @@ static void run_query(THD *thd, char *buf, char *end, DBUG_PRINT("query", ("%s", thd->query())); DBUG_ASSERT(!thd->in_sub_stmt); - DBUG_ASSERT(!thd->prelocked_mode); + DBUG_ASSERT(!thd->locked_tables_mode); mysql_parse(thd, thd->query(), thd->query_length(), &found_semicolon); @@ -2429,8 +2429,12 @@ int ndb_add_ndb_binlog_index(THD *thd, void *_row) goto add_ndb_binlog_index_err; } - mysql_unlock_tables(thd, thd->lock); - thd->lock= 0; + + if (! thd->locked_tables_mode) /* Is always TRUE */ + { + mysql_unlock_tables(thd, thd->lock); + thd->lock= 0; + } thd->options= saved_options; return 0; add_ndb_binlog_index_err: diff --git a/sql/handler.cc b/sql/handler.cc index 9c32171eefd..9366d91b290 100644 --- a/sql/handler.cc +++ b/sql/handler.cc @@ -4527,9 +4527,7 @@ static bool check_table_binlog_row_based(THD *thd, TABLE *table) DESCRIPTION This function will generate and write table maps for all tables - that are locked by the thread 'thd'. Either manually locked - (stored in THD::locked_tables) and automatically locked (stored - in THD::lock) are considered. + that are locked by the thread 'thd'. RETURN VALUE 0 All OK @@ -4537,25 +4535,22 @@ static bool check_table_binlog_row_based(THD *thd, TABLE *table) SEE ALSO THD::lock - THD::locked_tables */ static int write_locked_table_maps(THD *thd) { DBUG_ENTER("write_locked_table_maps"); - DBUG_PRINT("enter", ("thd: 0x%lx thd->lock: 0x%lx thd->locked_tables: 0x%lx " + DBUG_PRINT("enter", ("thd: 0x%lx thd->lock: 0x%lx " "thd->extra_lock: 0x%lx", - (long) thd, (long) thd->lock, - (long) thd->locked_tables, (long) thd->extra_lock)); + (long) thd, (long) thd->lock, (long) thd->extra_lock)); DBUG_PRINT("debug", ("get_binlog_table_maps(): %d", thd->get_binlog_table_maps())); if (thd->get_binlog_table_maps() == 0) { - MYSQL_LOCK *locks[3]; + MYSQL_LOCK *locks[2]; locks[0]= thd->extra_lock; locks[1]= thd->lock; - locks[2]= thd->locked_tables; for (uint i= 0 ; i < sizeof(locks)/sizeof(*locks) ; ++i ) { MYSQL_LOCK const *const lock= locks[i]; diff --git a/sql/lock.cc b/sql/lock.cc index f391b323a59..33c9edcea48 100644 --- a/sql/lock.cc +++ b/sql/lock.cc @@ -754,7 +754,7 @@ TABLE_LIST *mysql_lock_have_duplicate(THD *thd, TABLE_LIST *needle, goto end; /* Get command lock or LOCK TABLES lock. Maybe empty for INSERT DELAYED. */ - if (! (mylock= thd->lock ? thd->lock : thd->locked_tables)) + if (! (mylock= thd->lock)) goto end; /* If we have less than two tables, we cannot have duplicates. */ diff --git a/sql/log.cc b/sql/log.cc index c6802a9a6ed..dd82134ae56 100644 --- a/sql/log.cc +++ b/sql/log.cc @@ -4060,7 +4060,7 @@ bool MYSQL_BIN_LOG::write(Log_event *event_info) this will close all tables on the slave. */ bool const end_stmt= - thd->prelocked_mode && thd->lex->requires_prelocking(); + thd->locked_tables_mode && thd->lex->requires_prelocking(); if (thd->binlog_flush_pending_rows_event(end_stmt)) DBUG_RETURN(error); diff --git a/sql/set_var.cc b/sql/set_var.cc index 1490ffd9598..cff85df6e7c 100644 --- a/sql/set_var.cc +++ b/sql/set_var.cc @@ -4292,7 +4292,7 @@ bool sys_var_opt_readonly::update(THD *thd, set_var *var) DBUG_ENTER("sys_var_opt_readonly::update"); /* Prevent self dead-lock */ - if (thd->locked_tables || thd->active_transaction()) + if (thd->locked_tables_mode || thd->active_transaction()) { my_error(ER_LOCK_OR_ACTIVE_TRANSACTION, MYF(0)); DBUG_RETURN(true); diff --git a/sql/sp_head.cc b/sql/sp_head.cc index fdf9909f85e..a0832285742 100644 --- a/sql/sp_head.cc +++ b/sql/sp_head.cc @@ -1257,7 +1257,7 @@ sp_head::execute(THD *thd) Will write this SP statement into binlog separately (TODO: consider changing the condition to "not inside event union") */ - if (thd->prelocked_mode == NON_PRELOCKED) + if (thd->locked_tables_mode == LTM_NONE) thd->user_var_events_alloc= thd->mem_root; err_status= i->execute(thd, &ip); @@ -1269,7 +1269,7 @@ sp_head::execute(THD *thd) If we've set thd->user_var_events_alloc to mem_root of this SP statement, clean all the events allocated in it. */ - if (thd->prelocked_mode == NON_PRELOCKED) + if (thd->locked_tables_mode == LTM_NONE) { reset_dynamic(&thd->user_var_events); thd->user_var_events_alloc= NULL;//DEBUG @@ -2740,7 +2740,7 @@ sp_lex_keeper::reset_lex_and_exec_core(THD *thd, uint *nextp, thd->query_id= next_query_id(); pthread_mutex_unlock(&LOCK_thread_count); - if (thd->prelocked_mode == NON_PRELOCKED) + if (thd->locked_tables_mode == LTM_NONE) { /* This statement will enter/leave prelocked mode on its own. diff --git a/sql/sql_base.cc b/sql/sql_base.cc index e1a8e9e79cb..09bb05a91c1 100644 --- a/sql/sql_base.cc +++ b/sql/sql_base.cc @@ -1025,7 +1025,7 @@ bool close_cached_tables(THD *thd, TABLE_LIST *tables, bool have_lock, DBUG_ASSERT(!have_lock); pthread_mutex_unlock(&LOCK_open); - if (thd->locked_tables) + if (thd->locked_tables_mode) { /* If we are under LOCK TABLES we need to reopen tables without @@ -1141,7 +1141,7 @@ bool close_cached_tables(THD *thd, TABLE_LIST *tables, bool have_lock, } err_with_reopen: - if (thd->locked_tables) + if (thd->locked_tables_mode) { pthread_mutex_lock(&LOCK_open); /* @@ -1375,7 +1375,6 @@ void close_thread_tables(THD *thd, bool skip_mdl) { TABLE *table; - prelocked_mode_type prelocked_mode= thd->prelocked_mode; DBUG_ENTER("close_thread_tables"); #ifdef EXTRA_DEBUG @@ -1433,11 +1432,12 @@ void close_thread_tables(THD *thd, Reset transaction state, but only if we're not inside a sub-statement of a prelocked statement. */ - if (! prelocked_mode || thd->lex->requires_prelocking()) + if (thd->locked_tables_mode <= LTM_LOCK_TABLES || + thd->lex->requires_prelocking()) thd->transaction.stmt.reset(); } - if (thd->locked_tables || prelocked_mode) + if (thd->locked_tables_mode) { /* Ensure we are calling ha_reset() for all used tables */ @@ -1447,7 +1447,7 @@ void close_thread_tables(THD *thd, We are under simple LOCK TABLES or we're inside a sub-statement of a prelocked statement, so should not do anything else. */ - if (!prelocked_mode || !thd->lex->requires_prelocking()) + if (! thd->lex->requires_prelocking()) DBUG_VOID_RETURN; /* @@ -1455,18 +1455,19 @@ void close_thread_tables(THD *thd, so we have to leave the prelocked mode now with doing implicit UNLOCK TABLES if needed. */ - DBUG_PRINT("info",("thd->prelocked_mode= NON_PRELOCKED")); - thd->prelocked_mode= NON_PRELOCKED; + if (thd->locked_tables_mode == LTM_PRELOCKED_UNDER_LOCK_TABLES) + thd->locked_tables_mode= LTM_LOCK_TABLES; - if (prelocked_mode == PRELOCKED_UNDER_LOCK_TABLES) + if (thd->locked_tables_mode == LTM_LOCK_TABLES) DBUG_VOID_RETURN; + thd->locked_tables_mode= LTM_NONE; + thd->options&= ~OPTION_TABLE_LOCK; + /* Note that we are leaving prelocked mode so we don't need to care about THD::locked_tables_root. */ - thd->lock= thd->locked_tables; - thd->locked_tables= 0; /* Fallthrough */ } @@ -1501,16 +1502,6 @@ void close_thread_tables(THD *thd, mdl_remove_all_locks(&thd->mdl_context); } - if (prelocked_mode == PRELOCKED) - { - /* - If we are here then we are leaving normal prelocked mode, so it is - good idea to turn off OPTION_TABLE_LOCK flag. - */ - DBUG_ASSERT(thd->lex->requires_prelocking()); - thd->options&= ~(OPTION_TABLE_LOCK); - } - DBUG_VOID_RETURN; } @@ -1951,9 +1942,10 @@ 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. + - if the table is locked with LOCK TABLES or by prelocking, + unlock it and remove it from the list of locked tables + (THD::lock). Currently only transactional temporary tables + are locked. - Close the temporary table, remove its .FRM - remove the table from the list of temporary tables @@ -1992,7 +1984,7 @@ int drop_temporary_table(THD *thd, TABLE_LIST *table_list) 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); + mysql_lock_remove(thd, thd->lock, table, FALSE); close_temporary_table(thd, table, 1, 1); DBUG_RETURN(0); } @@ -2265,7 +2257,7 @@ bool close_cached_table(THD *thd, TABLE *table) DBUG_RETURN(TRUE); /* Close lock if this is not got with LOCK TABLES */ - if (thd->lock) + if (! thd->locked_tables_mode) { mysql_unlock_tables(thd, thd->lock); thd->lock=0; // Start locked threads @@ -2318,8 +2310,8 @@ void unlink_open_table(THD *thd, TABLE *find, bool unlock) if (list->s->table_cache_key.length == key_length && !memcmp(list->s->table_cache_key.str, key, key_length)) { - if (unlock && thd->locked_tables) - mysql_lock_remove(thd, thd->locked_tables, + if (unlock && thd->locked_tables_mode) + mysql_lock_remove(thd, thd->lock, list->parent ? list->parent : list, TRUE); /* Prepare MERGE table for close. Close parent if necessary. */ @@ -2690,7 +2682,7 @@ TABLE *open_table(THD *thd, TABLE_LIST *table_list, MEM_ROOT *mem_root, open not pre-opened tables in pre-locked/LOCK TABLES mode. TODO: move this block into a separate function. */ - if (thd->locked_tables || thd->prelocked_mode) + if (thd->locked_tables_mode) { // Using table locks TABLE *best_table= 0; int best_distance= INT_MIN; @@ -2705,7 +2697,8 @@ TABLE *open_table(THD *thd, TABLE_LIST *table_list, MEM_ROOT *mem_root, */ if (!my_strcasecmp(system_charset_info, table->alias, alias) && table->query_id != thd->query_id && /* skip tables already used */ - !(thd->prelocked_mode && table->query_id) && + (thd->locked_tables_mode == LTM_LOCK_TABLES || + table->query_id == 0) && !table->parent) { int distance= ((int) table->reginfo.lock_type - @@ -2788,7 +2781,7 @@ TABLE *open_table(THD *thd, TABLE_LIST *table_list, MEM_ROOT *mem_root, so we may only end up here if the table did not exist when locked tables list was created. */ - if (thd->prelocked_mode == PRELOCKED) + if (thd->locked_tables_mode == LTM_PRELOCKED) my_error(ER_NO_SUCH_TABLE, MYF(0), table_list->db, table_list->alias); else my_error(ER_TABLE_NOT_LOCKED, MYF(0), alias); @@ -3329,7 +3322,7 @@ void close_data_files_and_leave_as_placeholders(THD *thd, const char *db, safe_mutex_assert_owner(&LOCK_open); - if (thd->lock) + if (! thd->locked_tables_mode) { /* If we are not under LOCK TABLES we should have only one table @@ -3344,7 +3337,7 @@ void close_data_files_and_leave_as_placeholders(THD *thd, const char *db, if (!strcmp(table->s->table_name.str, table_name) && !strcmp(table->s->db.str, db)) { - if (thd->locked_tables) + if (thd->locked_tables_mode) { if (table->parent) { @@ -3354,11 +3347,11 @@ void close_data_files_and_leave_as_placeholders(THD *thd, const char *db, the parent and close it. OTOH in most cases a MERGE table won't have multiple children with the same db.table_name. */ - mysql_lock_remove(thd, thd->locked_tables, table->parent, TRUE); + mysql_lock_remove(thd, thd->lock, table->parent, TRUE); close_handle_and_leave_table_as_placeholder(table->parent); } else - mysql_lock_remove(thd, thd->locked_tables, table, TRUE); + mysql_lock_remove(thd, thd->lock, table, TRUE); } table->s->version= 0; close_handle_and_leave_table_as_placeholder(table); @@ -3554,7 +3547,7 @@ bool reopen_tables(THD *thd, bool get_locks) if ((lock= mysql_lock_tables(thd, tables, (uint) (tables_ptr - tables), flags, ¬_used))) { - thd->locked_tables=mysql_lock_merge(thd->locked_tables,lock); + thd->lock= mysql_lock_merge(thd->lock, lock); } else { @@ -3587,17 +3580,22 @@ void unlock_locked_tables(THD *thd) DBUG_ASSERT(!thd->in_sub_stmt && !(thd->state_flags & Open_tables_state::BACKUPS_AVAIL)); - if (thd->locked_tables) - { - thd->lock= thd->locked_tables; - thd->locked_tables=0; - close_thread_tables(thd); - /* - After closing tables we can free memory used for storing lock - request objects for metadata locks - */ - free_root(&thd->locked_tables_root, MYF(MY_MARK_BLOCKS_FREE)); - } + /* + Sic: we must be careful to not close open tables if + we're not in LOCK TABLES mode: unlock_locked_tables() is + sometimes called implicitly, expecting no effect on + open tables, e.g. from begin_trans(). + */ + if (thd->locked_tables_mode != LTM_LOCK_TABLES) + return; + + thd->locked_tables_mode= LTM_NONE; + close_thread_tables(thd); + /* + After closing tables we can free memory used for storing lock + request objects for metadata locks + */ + free_root(&thd->locked_tables_root, MYF(MY_MARK_BLOCKS_FREE)); } @@ -4494,11 +4492,6 @@ thr_lock_type read_lock_type_for_table(THD *thd, TABLE *table) prelocking it won't do such precaching and will simply reuse table list which is already built. - If any table has a trigger and start->trg_event_map is non-zero - the final lock will end up in thd->locked_tables, otherwise, the - lock will be placed in thd->lock. See also comments in - st_lex::set_trg_event_type_for_tables(). - RETURN 0 - OK -1 - error @@ -4543,10 +4536,10 @@ int open_tables(THD *thd, TABLE_LIST **start, uint *counter, uint flags) If we are not already executing prelocked statement and don't have statement for which table list for prelocking is already built, let us cache routines and try to build such table list. - */ - if (!thd->prelocked_mode && !thd->lex->requires_prelocking() && + if (thd->locked_tables_mode <= LTM_LOCK_TABLES && + !thd->lex->requires_prelocking() && thd->lex->uses_stored_routines()) { bool first_no_prelocking, need_prelocking; @@ -4759,7 +4752,8 @@ int open_tables(THD *thd, TABLE_LIST **start, uint *counter, uint flags) If we lock table for reading we won't update it so there is no need to process its triggers since they never will be activated. */ - if (!thd->prelocked_mode && !thd->lex->requires_prelocking() && + if (thd->locked_tables_mode <= LTM_LOCK_TABLES && + !thd->lex->requires_prelocking() && tables->trg_event_map && tables->table->triggers && tables->lock_type >= TL_WRITE_ALLOW_WRITE) { @@ -4780,7 +4774,7 @@ int open_tables(THD *thd, TABLE_LIST **start, uint *counter, uint flags) free_root(&new_frm_mem, MYF(MY_KEEP_PREALLOC)); } - if (tables->lock_type != TL_UNLOCK && ! thd->locked_tables) + if (tables->lock_type != TL_UNLOCK && ! thd->locked_tables_mode) { if (tables->lock_type == TL_WRITE_DEFAULT) tables->table->reginfo.lock_type= thd->update_lock_default; @@ -4803,10 +4797,7 @@ int open_tables(THD *thd, TABLE_LIST **start, uint *counter, uint flags) DBUG_PRINT("tcache", ("is parent: %d is child: %d", test(tables->table->child_l), test(tables->parent_l))); - DBUG_PRINT("tcache", ("in lock tables: %d in prelock mode: %d", - test(thd->locked_tables), test(thd->prelocked_mode))); - if (((!thd->locked_tables && !thd->prelocked_mode) || - tables->table->s->tmp_table) && + if ((!thd->locked_tables_mode || tables->table->s->tmp_table) && ((tables->table->child_l && add_merge_table_list(tables)) || (tables->parent_l && @@ -4822,7 +4813,8 @@ process_view_routines: Again we may need cache all routines used by this view and add tables used by them to table list. */ - if (tables->view && !thd->prelocked_mode && + if (tables->view && + thd->locked_tables_mode <= LTM_LOCK_TABLES && !thd->lex->requires_prelocking() && tables->view->uses_stored_routines()) { @@ -4996,7 +4988,7 @@ TABLE *open_ltable(THD *thd, TABLE_LIST *table_list, thr_lock_type lock_type, DBUG_ENTER("open_ltable"); /* should not be used in a prelocked_mode context, see NOTE above */ - DBUG_ASSERT(!thd->prelocked_mode); + DBUG_ASSERT(thd->locked_tables_mode < LTM_PRELOCKED); thd_proc_info(thd, "Opening table"); thd->current_tablenr= 0; @@ -5033,7 +5025,7 @@ retry: table_list->lock_type= lock_type; table_list->table= table; table->grant= table_list->grant; - if (thd->locked_tables) + if (thd->locked_tables_mode) { if (check_lock_and_start_stmt(thd, table, lock_type)) table= 0; @@ -5355,9 +5347,9 @@ int decide_logging_format(THD *thd, TABLE_LIST *tables) handling thr_lock gives us. You most always get all needed locks at once. - If query for which we are calling this function marked as requring - prelocking, this function will do implicit LOCK TABLES and change - thd::prelocked_mode accordingly. + If query for which we are calling this function marked as requiring + prelocking, this function will change locked_tables_mode to + LTM_PRELOCKED. RETURN VALUES 0 ok @@ -5374,22 +5366,24 @@ int lock_tables(THD *thd, TABLE_LIST *tables, uint count, We can't meet statement requiring prelocking if we already in prelocked mode. */ - DBUG_ASSERT(!thd->prelocked_mode || !thd->lex->requires_prelocking()); + DBUG_ASSERT(thd->locked_tables_mode <= LTM_LOCK_TABLES || + !thd->lex->requires_prelocking()); *need_reopen= FALSE; if (!tables && !thd->lex->requires_prelocking()) DBUG_RETURN(decide_logging_format(thd, tables)); /* - We need this extra check for thd->prelocked_mode because we want to avoid - attempts to lock tables in substatements. Checking for thd->locked_tables - is not enough in some situations. For example for SP containing + Check for thd->locked_tables_mode to avoid a redundant + and harmful attempt to lock the already locked tables again. + Checking for thd->lock is not enough in some situations. For example, + if a stored function contains "drop table t3; create temporary t3 ..; insert into t3 ...;" - thd->locked_tables may be 0 after drop tables, and without this extra - check insert will try to lock temporary table t3, that will lead - to memory leak... + thd->lock may be 0 after drop tables, whereas locked_tables_mode + is still on. In this situation an attempt to lock temporary + table t3 will lead to a memory leak. */ - if (!thd->locked_tables && !thd->prelocked_mode) + if (! thd->locked_tables_mode) { DBUG_ASSERT(thd->lock == 0); // You must lock everything at once TABLE **start,**ptr; @@ -5443,15 +5437,8 @@ int lock_tables(THD *thd, TABLE_LIST *tables, uint count, We just have done implicit LOCK TABLES, and now we have to emulate first open_and_lock_tables() after it. - Note that "LOCK TABLES" can also be marked as requiring prelocking - (e.g. if one locks view which uses functions). We should not emulate - such open_and_lock_tables() in this case. We also should not set - THD::prelocked_mode or first close_thread_tables() call will do - "UNLOCK TABLES". */ - thd->locked_tables= thd->lock; - thd->lock= 0; - thd->in_lock_tables=0; + thd->in_lock_tables= 0; /* When open_and_lock_tables() is called for a single table out of @@ -5474,8 +5461,7 @@ int lock_tables(THD *thd, TABLE_LIST *tables, uint count, This was an attempt to enter prelocked mode so there is no need to care about THD::locked_tables_root here. */ - mysql_unlock_tables(thd, thd->locked_tables); - thd->locked_tables= 0; + mysql_unlock_tables(thd, thd->lock); thd->options&= ~(OPTION_TABLE_LOCK); DBUG_RETURN(-1); } @@ -5486,8 +5472,8 @@ int lock_tables(THD *thd, TABLE_LIST *tables, uint count, and was marked as occupied during open_tables() as free for reuse. */ mark_real_tables_as_free_for_reuse(first_not_own); - DBUG_PRINT("info",("prelocked_mode= PRELOCKED")); - thd->prelocked_mode= PRELOCKED; + DBUG_PRINT("info",("locked_tables_mode= PRELOCKED")); + thd->locked_tables_mode= LTM_PRELOCKED; } } else @@ -5512,7 +5498,7 @@ int lock_tables(THD *thd, TABLE_LIST *tables, uint count, In a stored function or trigger we should ensure that we won't change a table that is already used by the calling statement. */ - if (thd->prelocked_mode && + if (thd->locked_tables_mode >= LTM_PRELOCKED && table->lock_type >= TL_WRITE_ALLOW_WRITE) { for (TABLE* opentab= thd->open_tables; opentab; opentab= opentab->next) @@ -5540,8 +5526,9 @@ int lock_tables(THD *thd, TABLE_LIST *tables, uint count, if (thd->lex->requires_prelocking()) { mark_real_tables_as_free_for_reuse(first_not_own); - DBUG_PRINT("info", ("thd->prelocked_mode= PRELOCKED_UNDER_LOCK_TABLES")); - thd->prelocked_mode= PRELOCKED_UNDER_LOCK_TABLES; + DBUG_PRINT("info", + ("thd->locked_tables_mode= LTM_PRELOCKED_UNDER_LOCK_TABLES")); + thd->locked_tables_mode= LTM_PRELOCKED_UNDER_LOCK_TABLES; } } diff --git a/sql/sql_cache.cc b/sql/sql_cache.cc index fb370cbd16a..871efeddd43 100644 --- a/sql/sql_cache.cc +++ b/sql/sql_cache.cc @@ -1136,7 +1136,7 @@ void Query_cache::store_query(THD *thd, TABLE_LIST *tables_used) See also a note on double-check locking usage above. */ - if (thd->locked_tables || query_cache_size == 0) + if (thd->locked_tables_mode || query_cache_size == 0) DBUG_VOID_RETURN; uint8 tables_type= 0; @@ -1364,7 +1364,7 @@ Query_cache::send_result_to_client(THD *thd, char *sql, uint query_length) See also a note on double-check locking usage above. */ - if (is_disabled() || thd->locked_tables || + if (is_disabled() || thd->locked_tables_mode || thd->variables.query_cache_type == 0 || query_cache_size == 0) goto err; diff --git a/sql/sql_class.cc b/sql/sql_class.cc index 9445f092546..1f0c8321608 100644 --- a/sql/sql_class.cc +++ b/sql/sql_class.cc @@ -995,11 +995,7 @@ void THD::cleanup(void) ha_rollback(this); xid_cache_delete(&transaction.xid_state); } - if (locked_tables) - { - lock=locked_tables; locked_tables=0; - close_thread_tables(this); - } + unlock_locked_tables(this); #if defined(ENABLED_DEBUG_SYNC) /* End the Debug Sync Facility. See debug_sync.cc. */ @@ -1742,7 +1738,7 @@ bool select_send::send_eof() ha_release_temporary_latches(thd); /* Unlock tables before sending packet to gain some speed */ - if (thd->lock) + if (thd->lock && ! thd->locked_tables_mode) { mysql_unlock_tables(thd, thd->lock); thd->lock=0; @@ -3036,8 +3032,8 @@ void THD::restore_backup_open_tables_state(Open_tables_state *backup) */ DBUG_ASSERT(open_tables == 0 && temporary_tables == 0 && handler_tables == 0 && derived_tables == 0 && - lock == 0 && locked_tables == 0 && - prelocked_mode == NON_PRELOCKED && + lock == 0 && + locked_tables_mode == LTM_NONE && m_reprepare_observer == NULL); mdl_context_destroy(&mdl_context); mdl_context_destroy(&handler_mdl_context); @@ -3912,7 +3908,7 @@ int THD::binlog_query(THD::enum_binlog_query_type qtype, char const *query_arg, If we are in prelocked mode, the flushing will be done inside the top-most close_thread_tables(). */ - if (this->prelocked_mode == NON_PRELOCKED) + if (this->locked_tables_mode <= LTM_LOCK_TABLES) if (int error= binlog_flush_pending_rows_event(TRUE)) DBUG_RETURN(error); diff --git a/sql/sql_class.h b/sql/sql_class.h index 0f7d9d9a8d5..0fa3231e458 100644 --- a/sql/sql_class.h +++ b/sql/sql_class.h @@ -862,12 +862,17 @@ typedef I_List<Item_change_record> Item_change_list; /** - Type of prelocked mode. - See comment for THD::prelocked_mode for complete description. + Type of locked tables mode. + See comment for THD::locked_tables_mode for complete description. */ -enum prelocked_mode_type {NON_PRELOCKED= 0, PRELOCKED= 1, - PRELOCKED_UNDER_LOCK_TABLES= 2}; +enum enum_locked_tables_mode +{ + LTM_NONE= 0, + LTM_LOCK_TABLES, + LTM_PRELOCKED, + LTM_PRELOCKED_UNDER_LOCK_TABLES +}; /** @@ -920,19 +925,13 @@ public: statement ends. Manual mode comes into play when a user issues a 'LOCK TABLES' statement. In this mode the user can only use the locked tables. - Trying to use any other tables will give an error. The locked tables are - stored in 'locked_tables' member. Manual locking is described in + Trying to use any other tables will give an error. + The locked tables are also stored in this member, however, + thd->locked_tables_mode is turned on. Manual locking is described in the 'LOCK_TABLES' chapter of the MySQL manual. See also lock_tables() for details. */ MYSQL_LOCK *lock; - /* - Tables that were locked with explicit or implicit LOCK TABLES. - (Implicit LOCK TABLES happens when we are prelocking tables for - execution of statement which uses stored routines. See description - THD::prelocked_mode for more info.) - */ - MYSQL_LOCK *locked_tables; /* CREATE-SELECT keeps an extra lock for the table being @@ -942,29 +941,34 @@ public: MYSQL_LOCK *extra_lock; /* - prelocked_mode_type enum and prelocked_mode member are used for - indicating whenever "prelocked mode" is on, and what type of - "prelocked mode" is it. - - Prelocked mode is used for execution of queries which explicitly - or implicitly (via views or triggers) use functions, thus may need - some additional tables (mentioned in query table list) for their - execution. - - First open_tables() call for such query will analyse all functions - used by it and add all additional tables to table its list. It will - also mark this query as requiring prelocking. After that lock_tables() - will issue implicit LOCK TABLES for the whole table list and change - thd::prelocked_mode to non-0. All queries called in functions invoked - by the main query will use prelocked tables. Non-0 prelocked_mode - will also surpress mentioned analysys in those queries thus saving - cycles. Prelocked mode will be turned off once close_thread_tables() - for the main query will be called. - - Note: Since not all "tables" present in table list are really locked - thd::prelocked_mode does not imply thd::locked_tables. - */ - prelocked_mode_type prelocked_mode; + Enum enum_locked_tables_mode and locked_tables_mode member are + used to indicate whether the so-called "locked tables mode" is on, + and what kind of mode is active. + + Locked tables mode is used when it's necessary to open and + lock many tables at once, for usage across multiple + (sub-)statements. + This may be necessary either for queries that use stored functions + and triggers, in which case the statements inside functions and + triggers may be executed many times, or for implementation of + LOCK TABLES, in which case the opened tables are reused by all + subsequent statements until a call to UNLOCK TABLES. + + The kind of locked tables mode employed for stored functions and + triggers is also called "prelocked mode". + In this mode, first open_tables() call to open the tables used + in a statement analyses all functions used by the statement + and adds all indirectly used tables to the list of tables to + open and lock. + It also marks the parse tree of the statement as requiring + prelocking. After that, lock_tables() locks the entire list + of tables and changes THD::locked_tables_modeto LTM_PRELOCKED. + All statements executed inside functions or triggers + use the prelocked tables, instead of opening their own ones. + Prelocked mode is turned off automatically once close_thread_tables() + of the main statement is called. + */ + enum enum_locked_tables_mode locked_tables_mode; ulong version; uint current_tablenr; @@ -996,8 +1000,8 @@ public: void reset_open_tables_state(THD *thd) { open_tables= temporary_tables= handler_tables= derived_tables= 0; - extra_lock= lock= locked_tables= 0; - prelocked_mode= NON_PRELOCKED; + extra_lock= lock= 0; + locked_tables_mode= LTM_NONE; state_flags= 0U; m_reprepare_observer= NULL; mdl_context_init(&mdl_context, thd); diff --git a/sql/sql_cursor.cc b/sql/sql_cursor.cc index ffc3fafe55f..098f049704c 100644 --- a/sql/sql_cursor.cc +++ b/sql/sql_cursor.cc @@ -289,7 +289,6 @@ Sensitive_cursor::Sensitive_cursor(THD *thd, select_result *result_arg) Save THD state into cursor. @todo - - XXX: thd->locked_tables is not changed. - What problems can we have with it if cursor is open? - TODO: must be fixed because of the prelocked mode. */ @@ -342,7 +341,6 @@ Sensitive_cursor::post_open(THD *thd) } } /* - XXX: thd->locked_tables is not changed. What problems can we have with it if cursor is open? TODO: must be fixed because of the prelocked mode. */ diff --git a/sql/sql_insert.cc b/sql/sql_insert.cc index 75ad46f1440..702e1e4f31a 100644 --- a/sql/sql_insert.cc +++ b/sql/sql_insert.cc @@ -441,7 +441,7 @@ void upgrade_lock_type(THD *thd, thr_lock_type *lock_type, */ if (specialflag & (SPECIAL_NO_NEW_FUNC | SPECIAL_SAFE_MODE) || thd->variables.max_insert_delayed_threads == 0 || - thd->prelocked_mode || + thd->locked_tables_mode > LTM_LOCK_TABLES || thd->lex->uses_stored_routines()) { *lock_type= TL_WRITE; @@ -611,7 +611,8 @@ bool mysql_insert(THD *thd,TABLE_LIST *table_list, never be able to get a lock on the table. QQQ: why not upgrade the lock here instead? */ - if (table_list->lock_type == TL_WRITE_DELAYED && thd->locked_tables && + if (table_list->lock_type == TL_WRITE_DELAYED && + thd->locked_tables_mode && find_locked_table(thd->open_tables, table_list->db, table_list->table_name)) { @@ -741,7 +742,14 @@ bool mysql_insert(THD *thd,TABLE_LIST *table_list, { if (duplic != DUP_ERROR || ignore) table->file->extra(HA_EXTRA_IGNORE_DUP_KEY); - if (!thd->prelocked_mode) + /** + This is a simple check for the case when the table has a trigger + that reads from it, or when the statement invokes a stored function + that reads from the table being inserted to. + Engines can't handle a bulk insert in parallel with a read form the + same table in the same connection. + */ + if (thd->locked_tables_mode <= LTM_LOCK_TABLES) table->file->ha_start_bulk_insert(values_list.elements); } @@ -856,7 +864,8 @@ bool mysql_insert(THD *thd,TABLE_LIST *table_list, auto_inc values from the delayed_insert thread as they share TABLE. */ table->file->ha_release_auto_increment(); - if (!thd->prelocked_mode && table->file->ha_end_bulk_insert() && !error) + if (thd->locked_tables_mode <= LTM_LOCK_TABLES && + table->file->ha_end_bulk_insert() && !error) { table->file->print_error(my_errno,MYF(0)); error=1; @@ -3076,7 +3085,7 @@ select_insert::prepare(List<Item> &values, SELECT_LEX_UNIT *u) lex->current_select->join->select_options|= OPTION_BUFFER_RESULT; } else if (!(lex->current_select->options & OPTION_BUFFER_RESULT) && - !thd->prelocked_mode) + thd->locked_tables_mode <= LTM_LOCK_TABLES) { /* We must not yet prepare the result table if it is the same as one of the @@ -3142,7 +3151,7 @@ int select_insert::prepare2(void) { DBUG_ENTER("select_insert::prepare2"); if (thd->lex->current_select->options & OPTION_BUFFER_RESULT && - !thd->prelocked_mode) + thd->locked_tables_mode <= LTM_LOCK_TABLES) table->file->ha_start_bulk_insert((ha_rows) 0); DBUG_RETURN(0); } @@ -3269,7 +3278,8 @@ bool select_insert::send_eof() DBUG_PRINT("enter", ("trans_table=%d, table_type='%s'", trans_table, table->file->table_type())); - error= (!thd->prelocked_mode) ? table->file->ha_end_bulk_insert():0; + error= (thd->locked_tables_mode <= LTM_LOCK_TABLES ? + table->file->ha_end_bulk_insert() : 0); table->file->extra(HA_EXTRA_NO_IGNORE_DUP_KEY); table->file->extra(HA_EXTRA_WRITE_CANNOT_REPLACE); @@ -3349,7 +3359,7 @@ void select_insert::abort() { If we are not in prelocked mode, we end the bulk insert started before. */ - if (!thd->prelocked_mode) + if (thd->locked_tables_mode <= LTM_LOCK_TABLES) table->file->ha_end_bulk_insert(); /* @@ -3730,7 +3740,7 @@ select_create::prepare(List<Item> &values, SELECT_LEX_UNIT *u) table->file->extra(HA_EXTRA_WRITE_CAN_REPLACE); if (info.handle_duplicates == DUP_UPDATE) table->file->extra(HA_EXTRA_INSERT_WITH_UPDATE); - if (!thd->prelocked_mode) + if (thd->locked_tables_mode <= LTM_LOCK_TABLES) table->file->ha_start_bulk_insert((ha_rows) 0); thd->abort_on_warning= (!info.ignore && (thd->variables.sql_mode & diff --git a/sql/sql_load.cc b/sql/sql_load.cc index 34e899fc536..ef4382c9b4d 100644 --- a/sql/sql_load.cc +++ b/sql/sql_load.cc @@ -448,7 +448,7 @@ int mysql_load(THD *thd,sql_exchange *ex,TABLE_LIST *table_list, (!table->triggers || !table->triggers->has_delete_triggers())) table->file->extra(HA_EXTRA_WRITE_CAN_REPLACE); - if (!thd->prelocked_mode) + if (thd->locked_tables_mode <= LTM_LOCK_TABLES) table->file->ha_start_bulk_insert((ha_rows) 0); table->copy_blobs=1; @@ -469,7 +469,8 @@ int mysql_load(THD *thd,sql_exchange *ex,TABLE_LIST *table_list, error= read_sep_field(thd, info, table_list, fields_vars, set_fields, set_values, read_info, *enclosed, skip_lines, ignore); - if (!thd->prelocked_mode && table->file->ha_end_bulk_insert() && !error) + if (thd->locked_tables_mode <= LTM_LOCK_TABLES && + table->file->ha_end_bulk_insert() && !error) { table->file->print_error(my_errno, MYF(0)); error= 1; diff --git a/sql/sql_parse.cc b/sql/sql_parse.cc index 31bd34531e3..95f142bc8a2 100644 --- a/sql/sql_parse.cc +++ b/sql/sql_parse.cc @@ -163,7 +163,7 @@ bool end_active_trans(THD *thd) { DBUG_PRINT("info",("options: 0x%llx", thd->options)); /* Safety if one did "drop table" on locked tables */ - if (!thd->locked_tables) + if (!thd->locked_tables_mode) thd->options&= ~OPTION_TABLE_LOCK; thd->server_status&= ~SERVER_STATUS_IN_TRANS; if (ha_commit(thd)) @@ -2211,7 +2211,7 @@ mysql_execute_command(THD *thd) if (res) break; - if (!thd->locked_tables && lex->protect_against_global_read_lock && + if (!thd->locked_tables_mode && lex->protect_against_global_read_lock && !(need_start_waiting= !wait_if_global_read_lock(thd, 0, 1))) break; @@ -2553,7 +2553,7 @@ case SQLCOM_PREPARE: TABLE in the same way. That way we avoid that a new table is created during a gobal read lock. */ - if (!thd->locked_tables && + if (!thd->locked_tables_mode && !(need_start_waiting= !wait_if_global_read_lock(thd, 0, 1))) { res= 1; @@ -2779,7 +2779,8 @@ end_with_restore_list: To prevent that, refuse SLAVE STOP if the client thread has locked tables */ - if (thd->locked_tables || thd->active_transaction() || thd->global_read_lock) + if (thd->locked_tables_mode || + thd->active_transaction() || thd->global_read_lock) { my_message(ER_LOCK_OR_ACTIVE_TRANSACTION, ER(ER_LOCK_OR_ACTIVE_TRANSACTION), MYF(0)); @@ -2855,7 +2856,7 @@ end_with_restore_list: if (end_active_trans(thd)) goto error; - if (!thd->locked_tables && + if (!thd->locked_tables_mode && !(need_start_waiting= !wait_if_global_read_lock(thd, 0, 1))) { res= 1; @@ -3089,7 +3090,7 @@ end_with_restore_list: DBUG_ASSERT(first_table == all_tables && first_table != 0); if (update_precheck(thd, all_tables)) break; - if (!thd->locked_tables && + if (!thd->locked_tables_mode && !(need_start_waiting= !wait_if_global_read_lock(thd, 0, 1))) goto error; DBUG_ASSERT(select_lex->offset_limit == 0); @@ -3126,7 +3127,7 @@ end_with_restore_list: Protection might have already been risen if its a fall through from the SQLCOM_UPDATE case above. */ - if (!thd->locked_tables && + if (!thd->locked_tables_mode && lex->sql_command == SQLCOM_UPDATE_MULTI && !(need_start_waiting= !wait_if_global_read_lock(thd, 0, 1))) goto error; @@ -3230,7 +3231,7 @@ end_with_restore_list: if ((res= insert_precheck(thd, all_tables))) break; - if (!thd->locked_tables && + if (!thd->locked_tables_mode && !(need_start_waiting= !wait_if_global_read_lock(thd, 0, 1))) { res= 1; @@ -3270,7 +3271,7 @@ end_with_restore_list: unit->set_limit(select_lex); - if (! thd->locked_tables && + if (! thd->locked_tables_mode && ! (need_start_waiting= ! wait_if_global_read_lock(thd, 0, 1))) { res= 1; @@ -3340,7 +3341,7 @@ end_with_restore_list: Don't allow this within a transaction because we want to use re-generate table */ - if (thd->locked_tables || thd->active_transaction()) + if (thd->locked_tables_mode || thd->active_transaction()) { my_message(ER_LOCK_OR_ACTIVE_TRANSACTION, ER(ER_LOCK_OR_ACTIVE_TRANSACTION), MYF(0)); @@ -3358,7 +3359,7 @@ end_with_restore_list: DBUG_ASSERT(select_lex->offset_limit == 0); unit->set_limit(select_lex); - if (!thd->locked_tables && + if (!thd->locked_tables_mode && !(need_start_waiting= !wait_if_global_read_lock(thd, 0, 1))) { res= 1; @@ -3379,7 +3380,7 @@ end_with_restore_list: (TABLE_LIST *)thd->lex->auxiliary_table_list.first; multi_delete *del_result; - if (!thd->locked_tables && + if (!thd->locked_tables_mode && !(need_start_waiting= !wait_if_global_read_lock(thd, 0, 1))) { res= 1; @@ -3526,7 +3527,7 @@ end_with_restore_list: if (check_one_table_access(thd, privilege, all_tables)) goto error; - if (!thd->locked_tables && + if (!thd->locked_tables_mode && !(need_start_waiting= !wait_if_global_read_lock(thd, 0, 1))) goto error; @@ -3615,8 +3616,7 @@ end_with_restore_list: if (thd->variables.query_cache_wlock_invalidate) query_cache.invalidate_locked_for_write(first_table); #endif /*HAVE_QUERY_CACHE*/ - thd->locked_tables=thd->lock; - thd->lock=0; + thd->locked_tables_mode= LTM_LOCK_TABLES; my_ok(thd); } else @@ -3707,7 +3707,7 @@ end_with_restore_list: if (check_access(thd,DROP_ACL,lex->name.str,0,1,0, is_schema_db(lex->name.str))) break; - if (thd->locked_tables || thd->active_transaction()) + if (thd->locked_tables_mode || thd->active_transaction()) { my_message(ER_LOCK_OR_ACTIVE_TRANSACTION, ER(ER_LOCK_OR_ACTIVE_TRANSACTION), MYF(0)); @@ -3746,7 +3746,7 @@ end_with_restore_list: res= 1; break; } - if (thd->locked_tables || thd->active_transaction()) + if (thd->locked_tables_mode || thd->active_transaction()) { res= 1; my_message(ER_LOCK_OR_ACTIVE_TRANSACTION, @@ -3786,7 +3786,7 @@ end_with_restore_list: #endif if (check_access(thd, ALTER_ACL, db->str, 0, 1, 0, is_schema_db(db->str))) break; - if (thd->locked_tables || thd->active_transaction()) + if (thd->locked_tables_mode || thd->active_transaction()) { my_message(ER_LOCK_OR_ACTIVE_TRANSACTION, ER(ER_LOCK_OR_ACTIVE_TRANSACTION), MYF(0)); @@ -4776,7 +4776,7 @@ create_sp_error: xa_state_names[thd->transaction.xid_state.xa_state]); break; } - if (thd->active_transaction() || thd->locked_tables) + if (thd->locked_tables_mode || thd->active_transaction()) { my_error(ER_XAER_OUTSIDE, MYF(0)); break; @@ -7078,7 +7078,7 @@ bool reload_acl_and_cache(THD *thd, ulong options, TABLE_LIST *tables, if we have a write locked table as this would lead to a deadlock when trying to reopen (and re-lock) the table after the flush. */ - if (thd->locked_tables) + if (thd->locked_tables_mode) { my_error(ER_LOCK_OR_ACTIVE_TRANSACTION, MYF(0)); return 1; @@ -7103,7 +7103,7 @@ bool reload_acl_and_cache(THD *thd, ulong options, TABLE_LIST *tables, } else { - if (thd && thd->locked_tables) + if (thd && thd->locked_tables_mode) { /* If we are under LOCK TABLES we should have a write diff --git a/sql/sql_partition.cc b/sql/sql_partition.cc index edc9055fb39..75ab9a73a5b 100644 --- a/sql/sql_partition.cc +++ b/sql/sql_partition.cc @@ -6216,7 +6216,7 @@ static void release_log_entries(partition_info *part_info) static void alter_partition_lock_handling(ALTER_PARTITION_PARAM_TYPE *lpt) { int err; - if (lpt->thd->locked_tables) + if (lpt->thd->locked_tables_mode) { /* When we have the table locked, it is necessary to reopen the table diff --git a/sql/sql_rename.cc b/sql/sql_rename.cc index 857cccde50f..fdf2f5ac155 100644 --- a/sql/sql_rename.cc +++ b/sql/sql_rename.cc @@ -44,7 +44,7 @@ bool mysql_rename_tables(THD *thd, TABLE_LIST *table_list, bool silent) if the user is trying to to do this in a transcation context */ - if (thd->locked_tables || thd->active_transaction()) + if (thd->locked_tables_mode || thd->active_transaction()) { my_message(ER_LOCK_OR_ACTIVE_TRANSACTION, ER(ER_LOCK_OR_ACTIVE_TRANSACTION), MYF(0)); diff --git a/sql/sql_select.cc b/sql/sql_select.cc index fc1a378c371..5320da45322 100644 --- a/sql/sql_select.cc +++ b/sql/sql_select.cc @@ -1019,7 +1019,7 @@ JOIN::optimize() error= -1; DBUG_RETURN(1); } - if (const_tables && !thd->locked_tables && + if (const_tables && !thd->locked_tables_mode && !(select_options & SELECT_NO_UNLOCK)) mysql_unlock_some_tables(thd, all_tables, const_tables); if (!conds && outer_join) @@ -6930,7 +6930,7 @@ void JOIN::join_free() We are not using tables anymore Unlock all tables. We may be in an INSERT .... SELECT statement. */ - if (can_unlock && lock && thd->lock && + if (can_unlock && lock && thd->lock && ! thd->locked_tables_mode && !(select_options & SELECT_NO_UNLOCK) && !select_lex->subquery_in_having && (select_lex == (thd->lex->unit.fake_select_lex ? diff --git a/sql/sql_table.cc b/sql/sql_table.cc index cac4bab27b7..dd8bd85aab6 100644 --- a/sql/sql_table.cc +++ b/sql/sql_table.cc @@ -1786,7 +1786,7 @@ bool mysql_rm_table(THD *thd,TABLE_LIST *tables, my_bool if_exists, if (!drop_temporary) { - if (!thd->locked_tables && + if (!thd->locked_tables_mode && !(need_start_waiting= !wait_if_global_read_lock(thd, 0, 1))) DBUG_RETURN(TRUE); } @@ -1891,7 +1891,7 @@ int mysql_rm_table_part2(THD *thd, TABLE_LIST *tables, bool if_exists, if (!drop_temporary) { - if (!thd->locked_tables) + if (!thd->locked_tables_mode) { if (lock_table_names(thd, tables)) DBUG_RETURN(1); @@ -1900,7 +1900,7 @@ int mysql_rm_table_part2(THD *thd, TABLE_LIST *tables, bool if_exists, expel_table_from_cache(0, table->db, table->table_name); pthread_mutex_unlock(&LOCK_open); } - else if (thd->locked_tables) + else { for (table= tables; table; table= table->next_local) if (find_temporary_table(thd, table->db, table->table_name)) @@ -2001,7 +2001,7 @@ int mysql_rm_table_part2(THD *thd, TABLE_LIST *tables, bool if_exists, table_type= table->db_type; if (!drop_temporary) { - if (thd->locked_tables) + if (thd->locked_tables_mode) { if (close_cached_table(thd, table->table)) { @@ -2192,8 +2192,8 @@ err_with_placeholders: locked. Additional check for 'non_temp_tables_count' is to avoid leaving LOCK TABLES mode if we have dropped only temporary tables. */ - if (thd->locked_tables && thd->locked_tables->table_count == 0 && - non_temp_tables_count > 0) + if (thd->locked_tables_mode && + thd->lock && thd->lock->table_count == 0 && non_temp_tables_count > 0) { unlock_locked_tables(thd); goto end; @@ -6571,7 +6571,7 @@ bool mysql_alter_table(THD *thd,char *new_db, char *new_name, if the user is trying to to do this in a transcation context */ - if (thd->locked_tables || thd->active_transaction()) + if (thd->locked_tables_mode || thd->active_transaction()) { my_message(ER_LOCK_OR_ACTIVE_TRANSACTION, ER(ER_LOCK_OR_ACTIVE_TRANSACTION), MYF(0)); @@ -6620,7 +6620,7 @@ view_err: set of tables from the old table or to open a new TABLE object for an extended list and verify that they belong to locked tables. */ - if (thd->locked_tables && + if (thd->locked_tables_mode && (create_info->used_fields & HA_CREATE_USED_UNION) && (table->s->tmp_table == NO_TMP_TABLE)) { @@ -6847,7 +6847,7 @@ view_err: table_list->table= NULL; // For query cache query_cache_invalidate3(thd, table_list, 0); - if (thd->locked_tables) + if (thd->locked_tables_mode) { /* Under LOCK TABLES we should adjust meta-data locks before finishing @@ -7330,7 +7330,7 @@ view_err: if (table->s->tmp_table != NO_TMP_TABLE) { /* Close lock if this is a transactional table */ - if (thd->lock) + if (thd->lock && ! thd->locked_tables_mode) { mysql_unlock_tables(thd, thd->lock); thd->lock=0; @@ -7467,7 +7467,7 @@ view_err: if (t_table->file->ha_create_handler_files(path, NULL, CHF_INDEX_FLAG, create_info)) goto err_with_placeholders; - if (thd->locked_tables) + if (thd->locked_tables_mode) { if (new_name == table_name && new_db == db) { @@ -7489,7 +7489,7 @@ view_err: (void) quick_rm_table(old_db_type, db, old_name, FN_IS_TMP); - if (thd->locked_tables && new_name == table_name && new_db == db) + if (thd->locked_tables_mode && new_name == table_name && new_db == db) { thd->in_lock_tables= 1; error= reopen_tables(thd, 1); @@ -7536,7 +7536,7 @@ view_err: table_list->table=0; // For query cache query_cache_invalidate3(thd, table_list, 0); - if (thd->locked_tables) + if (thd->locked_tables_mode) { if ((new_name != table_name || new_db != db)) { diff --git a/sql/sql_trigger.cc b/sql/sql_trigger.cc index 61cd9bffa57..9d47b637886 100644 --- a/sql/sql_trigger.cc +++ b/sql/sql_trigger.cc @@ -383,7 +383,7 @@ bool mysql_create_or_drop_trigger(THD *thd, TABLE_LIST *tables, bool create) LOCK_open is not enough because global read lock is held without holding LOCK_open). */ - if (!thd->locked_tables && + if (!thd->locked_tables_mode && !(need_start_waiting= !wait_if_global_read_lock(thd, 0, 1))) DBUG_RETURN(TRUE); @@ -444,7 +444,7 @@ bool mysql_create_or_drop_trigger(THD *thd, TABLE_LIST *tables, bool create) /* Keep consistent with respect to other DDL statements */ mysql_ha_rm_tables(thd, tables); - if (thd->locked_tables) + if (thd->locked_tables_mode) { /* Under LOCK TABLES we must only accept write locked tables. */ if (!(tables->table= find_write_locked_table(thd->open_tables, tables->db, @@ -493,7 +493,7 @@ bool mysql_create_or_drop_trigger(THD *thd, TABLE_LIST *tables, bool create) table->triggers->drop_trigger(thd, tables, &stmt_query)); /* Under LOCK TABLES we must reopen the table to activate the trigger. */ - if (!result && thd->locked_tables) + if (!result && thd->locked_tables_mode) { /* Make table suitable for reopening */ close_data_files_and_leave_as_placeholders(thd, tables->db, @@ -527,7 +527,7 @@ end: locks. Otherwise call to close_thread_tables() will take care about both TABLE instance created by reopen_name_locked_table() and metadata lock. */ - if (thd->locked_tables && tables && tables->table) + if (thd->locked_tables_mode && tables && tables->table) mdl_downgrade_exclusive_lock(&thd->mdl_context, tables->table->mdl_lock_data); diff --git a/sql/sql_update.cc b/sql/sql_update.cc index 5cf6ceaa394..7e033bc963a 100644 --- a/sql/sql_update.cc +++ b/sql/sql_update.cc @@ -978,7 +978,7 @@ int mysql_multi_update_prepare(THD *thd) count in open_tables() */ uint table_count= lex->table_count; - const bool using_lock_tables= thd->locked_tables != 0; + const bool using_lock_tables= thd->locked_tables_mode != LTM_NONE; bool original_multiupdate= (thd->lex->sql_command == SQLCOM_UPDATE_MULTI); bool need_reopen= FALSE; DBUG_ENTER("mysql_multi_update_prepare"); diff --git a/sql/sql_view.cc b/sql/sql_view.cc index 9382880ba1b..b370fc79b17 100644 --- a/sql/sql_view.cc +++ b/sql/sql_view.cc @@ -384,7 +384,7 @@ bool mysql_create_view(THD *thd, TABLE_LIST *views, alteration of views under LOCK TABLES. */ - if (thd->locked_tables) + if (thd->locked_tables_mode) { my_error(ER_LOCK_OR_ACTIVE_TRANSACTION, MYF(0)); res= TRUE; @@ -1583,7 +1583,7 @@ bool mysql_drop_view(THD *thd, TABLE_LIST *views, enum_drop_mode drop_mode) TABLES we have to simply prohibit dropping of views. */ - if (thd->locked_tables) + if (thd->locked_tables_mode) { my_error(ER_LOCK_OR_ACTIVE_TRANSACTION, MYF(0)); DBUG_RETURN(TRUE); |