summaryrefslogtreecommitdiff
path: root/sql/sql_table.cc
diff options
context:
space:
mode:
Diffstat (limited to 'sql/sql_table.cc')
-rw-r--r--sql/sql_table.cc143
1 files changed, 39 insertions, 104 deletions
diff --git a/sql/sql_table.cc b/sql/sql_table.cc
index 5052e29ac30..6fbee4f856e 100644
--- a/sql/sql_table.cc
+++ b/sql/sql_table.cc
@@ -27,8 +27,8 @@
// start_waiting_global_read_lock,
// unlock_table_names, mysql_unlock_tables
#include "strfunc.h" // find_type2, find_set
-#include "sql_view.h" // mysql_frm_type, view_checksum, mysql_frm_type
-#include "sql_delete.h" // mysql_truncate
+#include "sql_view.h" // view_checksum
+#include "sql_truncate.h" // regenerate_locked_table
#include "sql_partition.h" // mem_alloc_error,
// generate_partition_syntax,
// partition_info
@@ -52,6 +52,7 @@
#include "sql_show.h"
#include "transaction.h"
#include "keycaches.h"
+#include "datadict.h" // dd_frm_type()
#ifdef __WIN__
#include <io.h>
@@ -2125,7 +2126,7 @@ int mysql_rm_table_part2(THD *thd, TABLE_LIST *tables, bool if_exists,
((access(path, F_OK) &&
ha_create_table_from_engine(thd, db, alias)) ||
(!drop_view &&
- mysql_frm_type(thd, path, &frm_db_type) != FRMTYPE_TABLE)))
+ dd_frm_type(thd, path, &frm_db_type) != FRMTYPE_TABLE)))
{
// Table was not found on disk and table can't be created from engine
if (if_exists)
@@ -2145,7 +2146,7 @@ int mysql_rm_table_part2(THD *thd, TABLE_LIST *tables, bool if_exists,
*/
if (frm_db_type == DB_TYPE_UNKNOWN)
{
- mysql_frm_type(thd, path, &frm_db_type);
+ dd_frm_type(thd, path, &frm_db_type);
DBUG_PRINT("info", ("frm_db_type %d from %s", frm_db_type, path));
}
table_type= ha_resolve_by_legacy_type(thd, frm_db_type);
@@ -4454,10 +4455,10 @@ static int prepare_for_repair(THD *thd, TABLE_LIST *table_list,
char from[FN_REFLEN],tmp[FN_REFLEN+32];
const char **ext;
MY_STAT stat_info;
- Open_table_context ot_ctx_unused(thd, LONG_TIMEOUT);
+ Open_table_context ot_ctx(thd, (MYSQL_OPEN_IGNORE_FLUSH |
+ MYSQL_OPEN_HAS_MDL_LOCK |
+ MYSQL_LOCK_IGNORE_TIMEOUT));
DBUG_ENTER("prepare_for_repair");
- uint reopen_for_repair_flags= (MYSQL_OPEN_IGNORE_FLUSH |
- MYSQL_OPEN_HAS_MDL_LOCK);
if (!(check_opt->sql_flags & TT_USEFRM))
DBUG_RETURN(0);
@@ -4586,12 +4587,18 @@ static int prepare_for_repair(THD *thd, TABLE_LIST *table_list,
"Failed renaming data file");
goto end;
}
- if (mysql_truncate(thd, table_list, 1))
+ if (dd_recreate_table(thd, table_list->db, table_list->table_name))
{
error= send_check_errmsg(thd, table_list, "repair",
"Failed generating table from .frm file");
goto end;
}
+ /*
+ 'FALSE' for 'using_transactions' means don't postpone
+ invalidation till the end of a transaction, but do it
+ immediately.
+ */
+ query_cache_invalidate3(thd, table_list, FALSE);
if (mysql_file_rename(key_file_misc, tmp, from, MYF(MY_WME)))
{
error= send_check_errmsg(thd, table_list, "repair",
@@ -4606,8 +4613,7 @@ static int prepare_for_repair(THD *thd, TABLE_LIST *table_list,
Now we should be able to open the partially repaired table
to finish the repair in the handler later on.
*/
- if (open_table(thd, table_list, thd->mem_root,
- &ot_ctx_unused, reopen_for_repair_flags))
+ if (open_table(thd, table_list, thd->mem_root, &ot_ctx))
{
error= send_check_errmsg(thd, table_list, "repair",
"Failed to open partially repaired table");
@@ -4685,6 +4691,14 @@ static bool mysql_admin_table(THD* thd, TABLE_LIST* tables,
strxmov(table_name, db, ".", table->table_name, NullS);
thd->open_options|= extra_open_options;
table->lock_type= lock_type;
+ /*
+ To make code safe for re-execution we need to reset type of MDL
+ request as code below may change it.
+ To allow concurrent execution of read-only operations we acquire
+ weak metadata lock for them.
+ */
+ table->mdl_request.set_type((lock_type >= TL_WRITE_ALLOW_WRITE) ?
+ MDL_SHARED_NO_READ_WRITE : MDL_SHARED_READ);
/* open only one table from local list of command */
{
TABLE_LIST *save_next_global, *save_next_local;
@@ -4706,8 +4720,7 @@ static bool mysql_admin_table(THD* thd, TABLE_LIST* tables,
if (view_operator_func == NULL)
table->required_type=FRMTYPE_TABLE;
- open_error= open_and_lock_tables(thd, table, TRUE,
- MYSQL_OPEN_TAKE_UPGRADABLE_MDL);
+ open_error= open_and_lock_tables(thd, table, TRUE, 0);
thd->no_warnings_for_error= 0;
table->next_global= save_next_global;
table->next_local= save_next_local;
@@ -5053,6 +5066,7 @@ send_result_message:
/* Clear the ticket released in close_thread_tables(). */
table->mdl_request.ticket= NULL;
DEBUG_SYNC(thd, "ha_admin_open_ltable");
+ table->mdl_request.set_type(MDL_SHARED_WRITE);
if ((table->table= open_ltable(thd, table, lock_type, 0)))
{
result_code= table->table->file->ha_analyze(thd, check_opt);
@@ -5388,7 +5402,7 @@ bool mysql_create_like_table(THD* thd, TABLE_LIST* table, TABLE_LIST* src_table,
char buf[2048];
String query(buf, sizeof(buf), system_charset_info);
query.length(0); // Have to zero it since constructor doesn't
- Open_table_context ot_ctx_unused(thd, LONG_TIMEOUT);
+ Open_table_context ot_ctx(thd, MYSQL_OPEN_REOPEN);
/*
The condition avoids a crash as described in BUG#48506. Other
@@ -5403,8 +5417,7 @@ bool mysql_create_like_table(THD* thd, TABLE_LIST* table, TABLE_LIST* src_table,
to work. The table will be closed by close_thread_table() at
the end of this branch.
*/
- if (open_table(thd, table, thd->mem_root, &ot_ctx_unused,
- MYSQL_OPEN_REOPEN))
+ if (open_table(thd, table, thd->mem_root, &ot_ctx))
goto err;
int result __attribute__((unused))=
@@ -5490,6 +5503,7 @@ mysql_discard_or_import_tablespace(THD *thd,
not complain when we lock the table
*/
thd->tablespace_op= TRUE;
+ table_list->mdl_request.set_type(MDL_SHARED_WRITE);
if (!(table=open_ltable(thd, table_list, TL_WRITE, 0)))
{
thd->tablespace_op=FALSE;
@@ -6467,8 +6481,6 @@ bool mysql_alter_table(THD *thd,char *new_db, char *new_name,
char reg_path[FN_REFLEN+1];
ha_rows copied,deleted;
handlerton *old_db_type, *new_db_type, *save_old_db_type;
- legacy_db_type table_type;
- frm_type_enum frm_type;
enum_alter_table_change_level need_copy_table= ALTER_TABLE_METADATA_ONLY;
#ifdef WITH_PARTITION_STORAGE_ENGINE
uint fast_alter_partition= 0;
@@ -6548,85 +6560,6 @@ bool mysql_alter_table(THD *thd,char *new_db, char *new_name,
/* Conditionally writes to binlog. */
DBUG_RETURN(mysql_discard_or_import_tablespace(thd,table_list,
alter_info->tablespace_op));
- strxnmov(new_name_buff, sizeof (new_name_buff) - 1, mysql_data_home, "/", db,
- "/", table_name, reg_ext, NullS);
- (void) unpack_filename(new_name_buff, new_name_buff);
- /*
- If this is just a rename of a view, short cut to the
- following scenario: 1) lock LOCK_open 2) do a RENAME
- 2) unlock LOCK_open.
- This is a copy-paste added to make sure
- ALTER (sic:) TABLE .. RENAME works for views. ALTER VIEW is handled
- as an independent branch in mysql_execute_command. The need
- for a copy-paste arose because the main code flow of ALTER TABLE
- ... RENAME tries to use open_ltable, which does not work for views
- (open_ltable was never modified to merge table lists of child tables
- into the main table list, like open_tables does).
- This code is wrong and will be removed, please do not copy.
- */
- frm_type= mysql_frm_type(thd, new_name_buff, &table_type);
- /* Rename a view */
- /* Sic: there is a race here */
- if (frm_type == FRMTYPE_VIEW && !(alter_info->flags & ~ALTER_RENAME))
- {
- /*
- The following branch handles "ALTER VIEW v1 /no arguments/;"
- This feature is not documented one.
- However, before "OPTIMIZE TABLE t1;" was implemented,
- ALTER TABLE with no alter_specifications was used to force-rebuild
- the table. That's why this grammar is allowed. That's why we ignore
- it for views. So just do nothing in such a case.
- */
- if (!new_name)
- {
- my_ok(thd);
- DBUG_RETURN(FALSE);
- }
-
- /*
- Avoid problems with a rename on a table that we have locked or
- if the user is trying to to do this in a transcation context
- */
-
- if (thd->locked_tables_mode || thd->in_active_multi_stmt_transaction())
- {
- my_message(ER_LOCK_OR_ACTIVE_TRANSACTION,
- ER(ER_LOCK_OR_ACTIVE_TRANSACTION), MYF(0));
- DBUG_RETURN(TRUE);
- }
-
- if (thd->global_read_lock.wait_if_global_read_lock(thd, FALSE, TRUE))
- DBUG_RETURN(TRUE);
- if (lock_table_names(thd, table_list))
- {
- error= 1;
- goto view_err;
- }
-
- mysql_mutex_lock(&LOCK_open);
-
- if (!do_rename(thd, table_list, new_db, new_name, new_name, 1))
- {
- if (mysql_bin_log.is_open())
- {
- thd->clear_error();
- Query_log_event qinfo(thd, thd->query(), thd->query_length(),
- FALSE, TRUE, FALSE, 0);
- if ((error= mysql_bin_log.write(&qinfo)))
- goto view_err_unlock;
- }
- my_ok(thd);
- }
-
-view_err_unlock:
- mysql_mutex_unlock(&LOCK_open);
- unlock_table_names(thd);
-
-view_err:
- thd->global_read_lock.start_waiting_global_read_lock(thd);
- DBUG_RETURN(error);
- }
-
/*
Code below can handle only base tables so ensure that we won't open a view.
@@ -6637,8 +6570,7 @@ view_err:
Alter_table_prelocking_strategy alter_prelocking_strategy(alter_info);
- error= open_and_lock_tables(thd, table_list, FALSE,
- MYSQL_OPEN_TAKE_UPGRADABLE_MDL,
+ error= open_and_lock_tables(thd, table_list, FALSE, 0,
&alter_prelocking_strategy);
if (error)
@@ -7241,14 +7173,14 @@ view_err:
{
if (table->s->tmp_table)
{
- Open_table_context ot_ctx_unused(thd, LONG_TIMEOUT);
+ Open_table_context ot_ctx(thd, (MYSQL_OPEN_IGNORE_FLUSH |
+ MYSQL_LOCK_IGNORE_TIMEOUT));
TABLE_LIST tbl;
bzero((void*) &tbl, sizeof(tbl));
tbl.db= new_db;
tbl.table_name= tbl.alias= tmp_name;
/* Table is in thd->temporary_tables */
- (void) open_table(thd, &tbl, thd->mem_root, &ot_ctx_unused,
- MYSQL_OPEN_IGNORE_FLUSH);
+ (void) open_table(thd, &tbl, thd->mem_root, &ot_ctx);
new_table= tbl.table;
}
else
@@ -7527,7 +7459,7 @@ view_err:
To do this we need to obtain a handler object for it.
NO need to tamper with MERGE tables. The real open is done later.
*/
- Open_table_context ot_ctx_unused(thd, LONG_TIMEOUT);
+ Open_table_context ot_ctx(thd, MYSQL_OPEN_REOPEN);
TABLE *t_table;
if (new_name != table_name || new_db != db)
{
@@ -7547,8 +7479,7 @@ view_err:
*/
table_list->mdl_request.ticket= mdl_ticket;
}
- if (open_table(thd, table_list, thd->mem_root,
- &ot_ctx_unused, MYSQL_OPEN_REOPEN))
+ if (open_table(thd, table_list, thd->mem_root, &ot_ctx))
{
goto err_with_mdl;
}
@@ -7940,6 +7871,10 @@ bool mysql_recreate_table(THD *thd, TABLE_LIST *table_list)
table_list->table= NULL;
/* Same applies to MDL ticket. */
table_list->mdl_request.ticket= NULL;
+ /* Set lock type which is appropriate for ALTER TABLE. */
+ table_list->lock_type= TL_READ_NO_INSERT;
+ /* Same applies to MDL request. */
+ table_list->mdl_request.set_type(MDL_SHARED_NO_WRITE);
bzero((char*) &create_info, sizeof(create_info));
create_info.row_type=ROW_TYPE_NOT_USED;