diff --git a/storage/innobase/dict/dict0mem.cc b/storage/innobase/dict/dict0mem.cc index b01cd657369..c9988997801 100644 --- a/storage/innobase/dict/dict0mem.cc +++ b/storage/innobase/dict/dict0mem.cc @@ -2,7 +2,7 @@ Copyright (c) 1996, 2018, Oracle and/or its affiliates. All Rights Reserved. Copyright (c) 2012, Facebook Inc. -Copyright (c) 2013, 2018, MariaDB Corporation. +Copyright (c) 2013, 2019, MariaDB Corporation. 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 the Free Software @@ -1044,14 +1044,7 @@ dict_mem_index_free( mem_heap_free(index->heap); } -/** Create a temporary tablename like "#sql-ibtid-inc where - tid = the Table ID - inc = a randomly initialized number that is incremented for each file -The table ID is a 64 bit integer, can use up to 20 digits, and is -initialized at bootstrap. The second number is 32 bits, can use up to 10 -digits, and is initialized at startup to a randomly distributed number. -It is hoped that the combination of these two numbers will provide a -reasonably unique temporary file name. +/** Create a temporary tablename like "#sql-ibNNN". @param[in] heap A memory heap @param[in] dbtab Table name in the form database/table name @param[in] id Table id @@ -1066,8 +1059,19 @@ dict_mem_create_temporary_tablename( char* name; const char* dbend = strchr(dbtab, '/'); ut_ad(dbend); - size_t dblen = dbend - dbtab + 1; - + size_t dblen = size_t(dbend - dbtab) + 1; + + if (srv_safe_truncate) { + /* InnoDB will drop all #sql tables at startup. + Therefore, the id alone should generate a unique + and previously non-existent name. */ + size = dblen + (sizeof(TEMP_FILE_PREFIX) + 3 + 20); + name = static_cast(mem_heap_alloc(heap, size)); + memcpy(name, dbtab, dblen); + snprintf(name + dblen, size - dblen, + TEMP_FILE_PREFIX_INNODB UINT64PF, id); + return name; + } /* Increment a randomly initialized number for each temp file. */ my_atomic_add32((int32*) &dict_temp_file_num, 1); diff --git a/storage/innobase/handler/ha_innodb.cc b/storage/innobase/handler/ha_innodb.cc index 9bd85142e9f..33e0cc4c513 100644 --- a/storage/innobase/handler/ha_innodb.cc +++ b/storage/innobase/handler/ha_innodb.cc @@ -13623,12 +13623,26 @@ int ha_innobase::truncate() if (!err) { /* Reopen the newly created table, and drop the original table that was renamed to temp_name. */ - close(); + + row_prebuilt_t* prebuilt = m_prebuilt; + uchar* upd_buf = m_upd_buf; + ulint upd_buf_size = m_upd_buf_size; + /* Mimic ha_innobase::close(). */ + m_prebuilt = NULL; + m_upd_buf = NULL; + m_upd_buf_size = 0; err = open(name, 0, 0); if (!err) { m_prebuilt->stored_select_lock_type = stored_lock; m_prebuilt->table->update_time = update_time; + row_prebuilt_free(prebuilt, FALSE); delete_table(temp_name, SQLCOM_TRUNCATE); + my_free(upd_buf); + } else { + /* Revert to the old table before truncation. */ + m_prebuilt = prebuilt; + m_upd_buf = upd_buf; + m_upd_buf_size = upd_buf_size; } } diff --git a/storage/innobase/handler/ha_innodb.h b/storage/innobase/handler/ha_innodb.h index 1648d7db252..0162695c0e9 100644 --- a/storage/innobase/handler/ha_innodb.h +++ b/storage/innobase/handler/ha_innodb.h @@ -458,10 +458,6 @@ protected: /** Save CPU time with prebuilt/cached data structures */ row_prebuilt_t* m_prebuilt; - /** prebuilt pointer for the right prebuilt. For native - partitioning, points to the current partition prebuilt. */ - row_prebuilt_t** m_prebuilt_ptr; - /** Thread handle of the user currently using the handler; this is set in external_lock function */ THD* m_user_thd; diff --git a/storage/innobase/handler/handler0alter.cc b/storage/innobase/handler/handler0alter.cc index 72acca5d967..49ed93aa195 100644 --- a/storage/innobase/handler/handler0alter.cc +++ b/storage/innobase/handler/handler0alter.cc @@ -6153,7 +6153,7 @@ err_exit: if (heap) { ha_alter_info->handler_ctx = new ha_innobase_inplace_ctx( - (*m_prebuilt_ptr), + m_prebuilt, drop_index, n_drop_index, rename_index, n_rename_index, drop_fk, n_drop_fk, @@ -6287,7 +6287,7 @@ found_col: DBUG_ASSERT(!ha_alter_info->handler_ctx); ha_alter_info->handler_ctx = new ha_innobase_inplace_ctx( - (*m_prebuilt_ptr), + m_prebuilt, drop_index, n_drop_index, rename_index, n_rename_index, drop_fk, n_drop_fk, add_fk, n_add_fk, diff --git a/storage/innobase/include/dict0mem.h b/storage/innobase/include/dict0mem.h index 7fde68b3301..f59ff6fcd7f 100644 --- a/storage/innobase/include/dict0mem.h +++ b/storage/innobase/include/dict0mem.h @@ -2,7 +2,7 @@ Copyright (c) 1996, 2017, Oracle and/or its affiliates. All Rights Reserved. Copyright (c) 2012, Facebook Inc. -Copyright (c) 2013, 2018, MariaDB Corporation. +Copyright (c) 2013, 2019, MariaDB Corporation. 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 the Free Software @@ -495,14 +495,7 @@ void dict_mem_table_free_foreign_vcol_set( dict_table_t* table); -/** Create a temporary tablename like "#sql-ibtid-inc where - tid = the Table ID - inc = a randomly initialized number that is incremented for each file -The table ID is a 64 bit integer, can use up to 20 digits, and is -initialized at bootstrap. The second number is 32 bits, can use up to 10 -digits, and is initialized at startup to a randomly distributed number. -It is hoped that the combination of these two numbers will provide a -reasonably unique temporary file name. +/** Create a temporary tablename like "#sql-ibNNN". @param[in] heap A memory heap @param[in] dbtab Table name in the form database/table name @param[in] id Table id diff --git a/storage/innobase/row/row0mysql.cc b/storage/innobase/row/row0mysql.cc index cf40eb071e8..dcfc16ca42f 100644 --- a/storage/innobase/row/row0mysql.cc +++ b/storage/innobase/row/row0mysql.cc @@ -2590,10 +2590,15 @@ next: goto next; } + char* name = mem_strdup(table->name.m_name); + dict_table_close(table, FALSE, FALSE); - if (DB_SUCCESS != row_drop_table_for_mysql_in_background( - table->name.m_name)) { + dberr_t err = row_drop_table_for_mysql_in_background(name); + + ut_free(name); + + if (err != DB_SUCCESS) { /* If the DROP fails for some table, we return, and let the main thread retry later */ return(n_tables + n_tables_dropped);