Commit 0ffea01d authored by Marko Mäkelä's avatar Marko Mäkelä

Merge 10.2 into 10.3

parents ed661a0e fe1dfe39
......@@ -4655,10 +4655,7 @@ btr_cur_pessimistic_update(
}
rec = btr_cur_get_rec(cursor);
*offsets = rec_get_offsets(
rec, index, *offsets, page_is_leaf(page),
ULINT_UNDEFINED, offsets_heap);
ut_ad(rec_offs_validate(rec, index, *offsets));
dtuple_t* new_entry = row_rec_to_index_entry(
rec, index, *offsets, &n_ext, entry_heap);
......
......@@ -3840,65 +3840,6 @@ dict_stats_rename_table(
return(ret);
}
#ifdef MYSQL_RENAME_INDEX
/*********************************************************************//**
Renames an index in InnoDB persistent stats storage.
This function creates its own transaction and commits it.
@return DB_SUCCESS or error code. DB_STATS_DO_NOT_EXIST will be returned
if the persistent stats do not exist. */
dberr_t
dict_stats_rename_index(
/*====================*/
const dict_table_t* table, /*!< in: table whose index
is renamed */
const char* old_index_name, /*!< in: old index name */
const char* new_index_name) /*!< in: new index name */
{
rw_lock_x_lock(dict_operation_lock);
mutex_enter(&dict_sys->mutex);
if (!dict_stats_persistent_storage_check(true)) {
mutex_exit(&dict_sys->mutex);
rw_lock_x_unlock(dict_operation_lock);
return(DB_STATS_DO_NOT_EXIST);
}
char dbname_utf8[MAX_DB_UTF8_LEN];
char tablename_utf8[MAX_TABLE_UTF8_LEN];
dict_fs2utf8(table->name.m_name, dbname_utf8, sizeof(dbname_utf8),
tablename_utf8, sizeof(tablename_utf8));
pars_info_t* pinfo;
pinfo = pars_info_create();
pars_info_add_str_literal(pinfo, "dbname_utf8", dbname_utf8);
pars_info_add_str_literal(pinfo, "tablename_utf8", tablename_utf8);
pars_info_add_str_literal(pinfo, "new_index_name", new_index_name);
pars_info_add_str_literal(pinfo, "old_index_name", old_index_name);
dberr_t ret;
ret = dict_stats_exec_sql(
pinfo,
"PROCEDURE RENAME_INDEX_IN_INDEX_STATS () IS\n"
"BEGIN\n"
"UPDATE \"" INDEX_STATS_NAME "\" SET\n"
"index_name = :new_index_name\n"
"WHERE\n"
"database_name = :dbname_utf8 AND\n"
"table_name = :tablename_utf8 AND\n"
"index_name = :old_index_name;\n"
"END;\n", NULL);
mutex_exit(&dict_sys->mutex);
rw_lock_x_unlock(dict_operation_lock);
return(ret);
}
#endif /* MYSQL_RENAME_INDEX */
/* tests @{ */
#ifdef UNIV_ENABLE_UNIT_TEST_DICT_STATS
......
......@@ -128,9 +128,6 @@ static const alter_table_operations INNOBASE_ALTER_NOREBUILD
static const alter_table_operations INNOBASE_ALTER_INSTANT
= ALTER_VIRTUAL_COLUMN_ORDER
| ALTER_COLUMN_NAME
#ifdef MYSQL_RENAME_INDEX
| ALTER_RENAME_INDEX
#endif
| ALTER_ADD_VIRTUAL_COLUMN
| INNOBASE_FOREIGN_OPERATIONS
| ALTER_COLUMN_EQUAL_PACK_LENGTH
......@@ -2371,23 +2368,6 @@ innobase_check_index_keys(
}
}
#ifdef MYSQL_RENAME_INDEX
/* If a key by the same name is being created and
renamed, the name clash is OK. E.g.
ALTER TABLE t ADD INDEX i (col), RENAME INDEX i TO x
where the index "i" exists prior to the ALTER command.
In this case we:
1. rename the existing index from "i" to "x"
2. add the new index "i" */
for (uint i = 0; i < info->index_rename_count; i++) {
const KEY_PAIR* pair
= &info->index_rename_buffer[i];
if (0 == strcmp(key.name, pair->old_key->name)) {
goto name_ok;
}
}
#endif /* MYSQL_RENAME_INDEX */
my_error(ER_WRONG_NAME_FOR_INDEX, MYF(0),
key.name.str);
......@@ -5990,192 +5970,6 @@ innobase_check_foreign_key_index(
return(false);
}
#ifdef MYSQL_RENAME_INDEX
/**
Rename a given index in the InnoDB data dictionary.
@param index index to rename
@param new_name new name of the index
@param[in,out] trx dict transaction to use, not going to be committed here
@retval true Failure
@retval false Success */
static MY_ATTRIBUTE((warn_unused_result))
bool
rename_index_in_data_dictionary(
/*============================*/
const dict_index_t* index,
const char* new_name,
trx_t* trx)
{
DBUG_ENTER("rename_index_in_data_dictionary");
ut_ad(mutex_own(&dict_sys->mutex));
ut_ad(rw_lock_own(dict_operation_lock, RW_LOCK_X));
ut_ad(trx->dict_operation_lock_mode == RW_X_LATCH);
pars_info_t* pinfo;
dberr_t err;
pinfo = pars_info_create();
pars_info_add_ull_literal(pinfo, "table_id", index->table->id);
pars_info_add_ull_literal(pinfo, "index_id", index->id);
pars_info_add_str_literal(pinfo, "new_name", new_name);
trx->op_info = "Renaming an index in SYS_INDEXES";
DBUG_EXECUTE_IF(
"ib_rename_index_fail1",
DBUG_SET("+d,innodb_report_deadlock");
);
err = que_eval_sql(
pinfo,
"PROCEDURE RENAME_INDEX_IN_SYS_INDEXES () IS\n"
"BEGIN\n"
"UPDATE SYS_INDEXES SET\n"
"NAME = :new_name\n"
"WHERE\n"
"ID = :index_id AND\n"
"TABLE_ID = :table_id;\n"
"END;\n",
FALSE, trx); /* pinfo is freed by que_eval_sql() */
DBUG_EXECUTE_IF(
"ib_rename_index_fail1",
DBUG_SET("-d,innodb_report_deadlock");
);
trx->op_info = "";
if (err != DB_SUCCESS) {
my_error_innodb(err, index->table->name.m_name, 0);
DBUG_RETURN(true);
}
DBUG_RETURN(false);
}
/**
Rename all indexes in data dictionary of a given table that are
specified in ha_alter_info.
@param ctx alter context, used to fetch the list of indexes to
rename
@param ha_alter_info fetch the new names from here
@param[in,out] trx dict transaction to use, not going to be committed here
@retval true Failure
@retval false Success */
static MY_ATTRIBUTE((warn_unused_result))
bool
rename_indexes_in_data_dictionary(
/*==============================*/
const ha_innobase_inplace_ctx* ctx,
const Alter_inplace_info* ha_alter_info,
trx_t* trx)
{
DBUG_ENTER("rename_indexes_in_data_dictionary");
ut_ad(ctx->num_to_rename == ha_alter_info->index_rename_count);
for (ulint i = 0; i < ctx->num_to_rename; i++) {
KEY_PAIR* pair = &ha_alter_info->index_rename_buffer[i];
dict_index_t* index;
index = ctx->rename[i];
ut_ad(strcmp(index->name, pair->old_key->name) == 0);
if (rename_index_in_data_dictionary(index,
pair->new_key->name,
trx)) {
/* failed */
DBUG_RETURN(true);
}
}
DBUG_RETURN(false);
}
/**
Rename a given index in the InnoDB data dictionary cache.
@param[in,out] index index to rename
@param new_name new index name
*/
static
void
rename_index_in_cache(
/*==================*/
dict_index_t* index,
const char* new_name)
{
DBUG_ENTER("rename_index_in_cache");
ut_ad(mutex_own(&dict_sys->mutex));
ut_ad(rw_lock_own(dict_operation_lock, RW_LOCK_X));
size_t old_name_len = strlen(index->name);
size_t new_name_len = strlen(new_name);
if (old_name_len >= new_name_len) {
/* reuse the old buffer for the name if it is large enough */
memcpy(const_cast<char*>(index->name()), new_name,
new_name_len + 1);
} else {
/* Free the old chunk of memory if it is at the topmost
place in the heap, otherwise the old chunk will be freed
when the index is evicted from the cache. This code will
kick-in in a repeated ALTER sequences where the old name is
alternately longer/shorter than the new name:
1. ALTER TABLE t RENAME INDEX a TO aa;
2. ALTER TABLE t RENAME INDEX aa TO a;
3. go to 1. */
index->name = mem_heap_strdup_replace(
index->heap,
/* Presumed topmost element of the heap: */
index->name, old_name_len + 1,
new_name);
}
DBUG_VOID_RETURN;
}
/**
Rename all indexes in data dictionary cache of a given table that are
specified in ha_alter_info.
@param ctx alter context, used to fetch the list of indexes to rename
@param ha_alter_info fetch the new names from here
*/
static
void
rename_indexes_in_cache(
/*====================*/
const ha_innobase_inplace_ctx* ctx,
const Alter_inplace_info* ha_alter_info)
{
DBUG_ENTER("rename_indexes_in_cache");
ut_ad(ctx->num_to_rename == ha_alter_info->index_rename_count);
for (ulint i = 0; i < ctx->num_to_rename; i++) {
KEY_PAIR* pair = &ha_alter_info->index_rename_buffer[i];
dict_index_t* index;
index = ctx->rename[i];
ut_ad(strcmp(index->name, pair->old_key->name) == 0);
rename_index_in_cache(index, pair->new_key->name);
}
DBUG_VOID_RETURN;
}
#endif /* MYSQL_RENAME_INDEX */
/** Fill the stored column information in s_cols list.
@param[in] altered_table mysql table object
......@@ -6773,43 +6567,6 @@ ha_innobase::prepare_inplace_alter_table(
n_rename_index = 0;
rename_index = NULL;
#ifdef MYSQL_RENAME_INDEX
n_rename_index = ha_alter_info->index_rename_count;
/* Create a list of dict_index_t objects that are to be renamed,
also checking for requests to rename nonexistent indexes. If
the table is going to be rebuilt (new_clustered == true in
prepare_inplace_alter_table_dict()), then this can be skipped,
but we don't for simplicity (we have not determined the value of
new_clustered yet). */
if (n_rename_index > 0) {
rename_index = static_cast<dict_index_t**>(
mem_heap_alloc(
heap,
n_rename_index * sizeof(*rename_index)));
for (ulint i = 0; i < n_rename_index; i++) {
dict_index_t* index = NULL;
const char* old_name = NULL;
const char* old_name = ha_alter_info
->index_rename_buffer[i].old_key->name;
index = dict_table_get_index_on_name(indexed_table,
old_name);
if (index == NULL) {
my_error(ER_KEY_DOES_NOT_EXITS, MYF(0),
old_name,
m_prebuilt->table->name.m_name);
goto err_exit;
}
rename_index[i] = index;
}
}
#endif /* MYSQL_RENAME_INDEX */
n_add_fk = 0;
if (ha_alter_info->handler_flags
......@@ -9057,14 +8814,6 @@ commit_try_norebuild(
DBUG_RETURN(true);
}
#ifdef MYSQL_RENAME_INDEX
if ((ha_alter_info->handler_flags
& ALTER_RENAME_INDEX)
&& rename_indexes_in_data_dictionary(ctx, ha_alter_info, trx)) {
DBUG_RETURN(true);
}
#endif /* MYSQL_RENAME_INDEX */
if ((ha_alter_info->handler_flags
& ALTER_DROP_VIRTUAL_COLUMN)
&& innobase_drop_virtual_try(ha_alter_info, ctx->old_table, trx)) {
......@@ -9251,10 +9000,6 @@ commit_cache_norebuild(
vers_change_fields_cache(ha_alter_info, ctx, table);
}
#ifdef MYSQL_RENAME_INDEX
rename_indexes_in_cache(ctx, ha_alter_info);
#endif
ctx->new_table->fts_doc_id_index
= ctx->new_table->fts
? dict_table_get_index_on_name(
......@@ -9324,31 +9069,6 @@ alter_stats_norebuild(
}
}
#ifdef MYSQL_RENAME_INDEX
for (i = 0; i < ha_alter_info->index_rename_count; i++) {
KEY_PAIR* pair = &ha_alter_info->index_rename_buffer[i];
dberr_t err;
err = dict_stats_rename_index(ctx->new_table,
pair->old_key->name,
pair->new_key->name);
if (err != DB_SUCCESS) {
push_warning_printf(
thd,
Sql_condition::WARN_LEVEL_WARN,
ER_ERROR_ON_RENAME,
"Error renaming an index of table '%s'"
" from '%s' to '%s' in InnoDB persistent"
" statistics storage: %s",
table_name,
pair->old_key->name,
pair->new_key->name,
ut_strerr(err));
}
}
#endif /* MYSQL_RENAME_INDEX */
for (i = 0; i < ctx->num_to_add_index; i++) {
dict_index_t* index = ctx->add_index[i];
DBUG_ASSERT(index->table == ctx->new_table);
......
......@@ -187,21 +187,6 @@ dict_stats_rename_table(
char* errstr, /*!< out: error string if != DB_SUCCESS
is returned */
size_t errstr_sz); /*!< in: errstr size */
#ifdef MYSQL_RENAME_INDEX
/*********************************************************************//**
Renames an index in InnoDB persistent stats storage.
This function creates its own transaction and commits it.
@return DB_SUCCESS or error code. DB_STATS_DO_NOT_EXIST will be returned
if the persistent stats do not exist. */
dberr_t
dict_stats_rename_index(
/*====================*/
const dict_table_t* table, /*!< in: table whose index
is renamed */
const char* old_index_name, /*!< in: old index name */
const char* new_index_name) /*!< in: new index name */
__attribute__((warn_unused_result));
#endif /* MYSQL_RENAME_INDEX */
/** Save an individual index's statistic into the persistent statistics
storage.
......
......@@ -40,7 +40,6 @@ class THD;
// JAN: TODO missing features:
#undef MYSQL_FT_INIT_EXT
#undef MYSQL_PFS
#undef MYSQL_RENAME_INDEX
#undef MYSQL_STORE_FTS_DOC_ID
/*******************************************************************//**
......
......@@ -193,70 +193,6 @@ mem_heap_get_top(
mem_heap_t* heap,
ulint n);
/** Checks if a given chunk of memory is the topmost element stored in the
heap. If this is the case, then calling mem_heap_free_top() would free
that element from the heap.
@param[in] heap memory heap
@param[in] buf presumed topmost element
@param[in] buf_sz size of buf in bytes
@return true if topmost */
UNIV_INLINE
bool
mem_heap_is_top(
mem_heap_t* heap,
const void* buf,
ulint buf_sz)
MY_ATTRIBUTE((warn_unused_result));
/*****************************************************************//**
Allocate a new chunk of memory from a memory heap, possibly discarding
the topmost element. If the memory chunk specified with (top, top_sz)
is the topmost element, then it will be discarded, otherwise it will
be left untouched and this function will be equivallent to
mem_heap_alloc().
@return allocated storage, NULL if did not succeed (only possible for
MEM_HEAP_BTR_SEARCH type heaps) */
UNIV_INLINE
void*
mem_heap_replace(
/*=============*/
mem_heap_t* heap, /*!< in/out: memory heap */
const void* top, /*!< in: chunk to discard if possible */
ulint top_sz, /*!< in: size of top in bytes */
ulint new_sz);/*!< in: desired size of the new chunk */
/*****************************************************************//**
Allocate a new chunk of memory from a memory heap, possibly discarding
the topmost element and then copy the specified data to it. If the memory
chunk specified with (top, top_sz) is the topmost element, then it will be
discarded, otherwise it will be left untouched and this function will be
equivallent to mem_heap_dup().
@return allocated storage, NULL if did not succeed (only possible for
MEM_HEAP_BTR_SEARCH type heaps) */
UNIV_INLINE
void*
mem_heap_dup_replace(
/*=================*/
mem_heap_t* heap, /*!< in/out: memory heap */
const void* top, /*!< in: chunk to discard if possible */
ulint top_sz, /*!< in: size of top in bytes */
const void* data, /*!< in: new data to duplicate */
ulint data_sz);/*!< in: size of data in bytes */
/*****************************************************************//**
Allocate a new chunk of memory from a memory heap, possibly discarding
the topmost element and then copy the specified string to it. If the memory
chunk specified with (top, top_sz) is the topmost element, then it will be
discarded, otherwise it will be left untouched and this function will be
equivallent to mem_heap_strdup().
@return allocated string, NULL if did not succeed (only possible for
MEM_HEAP_BTR_SEARCH type heaps) */
UNIV_INLINE
char*
mem_heap_strdup_replace(
/*====================*/
mem_heap_t* heap, /*!< in/out: memory heap */
const void* top, /*!< in: chunk to discard if possible */
ulint top_sz, /*!< in: size of top in bytes */
const char* str); /*!< in: new data to duplicate */
/*****************************************************************//**
Frees the topmost element in a memory heap.
The size of the element must be given. */
......
......@@ -328,102 +328,6 @@ mem_heap_get_top(
return((void*) buf);
}
/** Checks if a given chunk of memory is the topmost element stored in the
heap. If this is the case, then calling mem_heap_free_top() would free
that element from the heap.
@param[in] heap memory heap
@param[in] buf presumed topmost element
@param[in] buf_sz size of buf in bytes
@return true if topmost */
UNIV_INLINE
bool
mem_heap_is_top(
mem_heap_t* heap,
const void* buf,
ulint buf_sz)
{
const byte* first_free_byte;
const byte* presumed_start_of_buf;
ut_d(mem_block_validate(heap));
first_free_byte = mem_heap_get_heap_top(heap);
presumed_start_of_buf = first_free_byte - MEM_SPACE_NEEDED(buf_sz);
return(presumed_start_of_buf == buf);
}
/*****************************************************************//**
Allocate a new chunk of memory from a memory heap, possibly discarding
the topmost element. If the memory chunk specified with (top, top_sz)
is the topmost element, then it will be discarded, otherwise it will
be left untouched and this function will be equivallent to
mem_heap_alloc().
@return allocated storage, NULL if did not succeed (only possible for
MEM_HEAP_BTR_SEARCH type heaps) */
UNIV_INLINE
void*
mem_heap_replace(
/*=============*/
mem_heap_t* heap, /*!< in/out: memory heap */
const void* top, /*!< in: chunk to discard if possible */
ulint top_sz, /*!< in: size of top in bytes */
ulint new_sz) /*!< in: desired size of the new chunk */
{
if (mem_heap_is_top(heap, top, top_sz)) {
mem_heap_free_top(heap, top_sz);
}
return(mem_heap_alloc(heap, new_sz));
}
/*****************************************************************//**
Allocate a new chunk of memory from a memory heap, possibly discarding
the topmost element and then copy the specified data to it. If the memory
chunk specified with (top, top_sz) is the topmost element, then it will be
discarded, otherwise it will be left untouched and this function will be
equivallent to mem_heap_dup().
@return allocated storage, NULL if did not succeed (only possible for
MEM_HEAP_BTR_SEARCH type heaps) */
UNIV_INLINE
void*
mem_heap_dup_replace(
/*=================*/
mem_heap_t* heap, /*!< in/out: memory heap */
const void* top, /*!< in: chunk to discard if possible */
ulint top_sz, /*!< in: size of top in bytes */
const void* data, /*!< in: new data to duplicate */
ulint data_sz)/*!< in: size of data in bytes */
{
void* p = mem_heap_replace(heap, top, top_sz, data_sz);
memcpy(p, data, data_sz);
return(p);
}
/*****************************************************************//**
Allocate a new chunk of memory from a memory heap, possibly discarding
the topmost element and then copy the specified string to it. If the memory
chunk specified with (top, top_sz) is the topmost element, then it will be
discarded, otherwise it will be left untouched and this function will be
equivallent to mem_heap_strdup().
@return allocated string, NULL if did not succeed (only possible for
MEM_HEAP_BTR_SEARCH type heaps) */
UNIV_INLINE
char*
mem_heap_strdup_replace(
/*====================*/
mem_heap_t* heap, /*!< in/out: memory heap */
const void* top, /*!< in: chunk to discard if possible */
ulint top_sz, /*!< in: size of top in bytes */
const char* str) /*!< in: new data to duplicate */
{
return(reinterpret_cast<char*>(mem_heap_dup_replace(
heap, top, top_sz, str, strlen(str) + 1)));
}
/*****************************************************************//**
Frees the topmost element in a memory heap. The size of the element must be
given. */
......
......@@ -3,6 +3,7 @@
--echo #
--source include/have_rocksdb.inc
--source include/big_test.inc
--echo # Disable for valgrind because this takes too long
--source include/not_valgrind.inc
......
if (`SELECT COUNT(*) = 0 FROM INFORMATION_SCHEMA.ENGINES WHERE engine = 'rocksdb' AND support IN ('YES', 'DEFAULT', 'ENABLED')`)
{
--skip Test requires engine RocksDB.
}
--disable_query_log
# Table statistics can vary depending on when the memtables are flushed, so
# flush them at the beginning of the test to ensure the test runs consistently.
set global rocksdb_force_flush_memtable_now = true;
--enable_query_log
--loose-enable-rocksdb
--loose-enable-rocksdb_global_info
--loose-enable-rocksdb_ddl
--loose-enable-rocksdb_cf_options
--loose-enable_rocksdb_perf_context
--loose-enable_rocksdb_perf_context_global
--loose-enable-rocksdb_index_file_map
--loose-enable-rocksdb_dbstats
--loose-enable-rocksdb_cfstats
--loose-enable-rocksdb_lock_info
--loose-enable-rocksdb_trx
--loose-enable-rocksdb_locks
......@@ -9,11 +9,12 @@
let $MYSQL_BASEDIR = `SELECT @@BASEDIR`;
let $exec =
python $MYSQL_BASEDIR/mysql-test/suite/rocksdb_stress/t/load_generator.py
-L $MYSQL_TMP_DIR/load_generator.log -H $master_host -t $table
-P $MASTER_MYPORT -n $num_records -m $max_records
-l $num_loaders -c $num_checkers -r $num_requests
-E $MYSQLTEST_VARDIR/tmp/mysqld.1.expect
python
$MYSQL_BASEDIR/storage/rocksdb/mysql-test/rocksdb_stress/t/load_generator.py \
-L $MYSQL_TMP_DIR/load_generator.log -H $master_host -t $table \
-P $MASTER_MYPORT -n $num_records -m $max_records \
-l $num_loaders -c $num_checkers -r $num_requests \
-E $MYSQLTEST_VARDIR/tmp/mysqld.1.expect \
-D $reap_delay;
exec $exec;
......
!include include/default_my.cnf
!include suite/rocksdb/my.cnf
!include ../storage/rocksdb/mysql-test/rocksdb/my.cnf
!include suite/rpl/my.cnf
[mysqld.1]
......
--plugin-load=$HA_ROCKSDB_SO --default-storage-engine=rocksdb
package My::Suite::Rocksdb;
use My::SysInfo;
#
# Note: ../rocksdb_sys_vars/suite.pm file has a similar
# function. If you modify this file, consider modifying that one, too.
#
@ISA = qw(My::Suite);
use My::Find;
use File::Basename;
use strict;
sub is_default { not $::opt_embedded_server }
my $sst_dump=
::mtr_exe_maybe_exists(
"$::bindir/storage/rocksdb$::opt_vs_config/sst_dump",
"$::path_client_bindir/sst_dump");
return "RocksDB is not compiled, no sst_dump" unless $sst_dump;
$ENV{MARIAROCKS_SST_DUMP}="$sst_dump";
# Temporarily disable testing under valgrind, due to MDEV-12439
return "RocksDB tests disabled under valgrind" if ($::opt_valgrind);
bless { };
......@@ -30,4 +30,4 @@ ENGINE=RocksDB DEFAULT CHARSET=latin1 COLLATE=latin1_bin;
--let $num_requests = 10000
--let $reap_delay = 0
--source suite/rocksdb_stress/include/rocksdb_stress.inc
--source include/rocksdb_stress.inc
......@@ -31,4 +31,4 @@ ENGINE=RocksDB DEFAULT CHARSET=latin1 COLLATE=latin1_bin;
--let $num_requests = 10000
--let $reap_delay = 180
--source suite/rocksdb_stress/include/rocksdb_stress.inc
--source include/rocksdb_stress.inc
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment