summaryrefslogtreecommitdiff
path: root/storage/xtradb
diff options
context:
space:
mode:
authorNirbhay Choubey <nirbhay@mariadb.com>2014-09-28 20:43:56 -0400
committerNirbhay Choubey <nirbhay@mariadb.com>2014-09-28 20:43:56 -0400
commitc916085e271cd049537b1e07b36cd060c44750bd (patch)
tree337ddfcd033174143cf9bd08e6ba50174459d7ff /storage/xtradb
parent023366e6eb68edca3858c32e7492788e047d927a (diff)
parentf1afc003eefe0aafd3e070c7453d9e029d8445a8 (diff)
downloadmariadb-git-c916085e271cd049537b1e07b36cd060c44750bd.tar.gz
bzr merge -rtag:mariadb-10.0.14 maria/10.0/
Diffstat (limited to 'storage/xtradb')
-rw-r--r--storage/xtradb/CMakeLists.txt63
-rw-r--r--storage/xtradb/api/api0api.cc23
-rw-r--r--storage/xtradb/btr/btr0cur.cc43
-rw-r--r--storage/xtradb/buf/buf0buf.cc50
-rw-r--r--storage/xtradb/buf/buf0lru.cc27
-rw-r--r--storage/xtradb/dict/dict0crea.cc44
-rw-r--r--storage/xtradb/dict/dict0dict.cc351
-rw-r--r--storage/xtradb/dict/dict0mem.cc27
-rw-r--r--storage/xtradb/fil/fil0fil.cc51
-rw-r--r--storage/xtradb/fts/fts0ast.cc136
-rw-r--r--storage/xtradb/fts/fts0blex.cc8
-rw-r--r--storage/xtradb/fts/fts0blex.l8
-rw-r--r--storage/xtradb/fts/fts0fts.cc46
-rw-r--r--storage/xtradb/fts/fts0pars.cc51
-rw-r--r--storage/xtradb/fts/fts0pars.y22
-rw-r--r--storage/xtradb/fts/fts0que.cc57
-rw-r--r--storage/xtradb/fts/fts0tlex.cc6
-rw-r--r--storage/xtradb/fts/fts0tlex.l6
-rw-r--r--storage/xtradb/handler/ha_innodb.cc41
-rw-r--r--storage/xtradb/handler/ha_innodb.h1
-rw-r--r--storage/xtradb/handler/handler0alter.cc70
-rw-r--r--storage/xtradb/handler/i_s.cc9
-rw-r--r--storage/xtradb/include/buf0buf.h11
-rw-r--r--storage/xtradb/include/buf0buf.ic6
-rw-r--r--storage/xtradb/include/dict0crea.h34
-rw-r--r--storage/xtradb/include/dict0mem.h134
-rw-r--r--storage/xtradb/include/fil0fil.h12
-rw-r--r--storage/xtradb/include/fts0ast.h69
-rw-r--r--storage/xtradb/include/fts0fts.h1
-rw-r--r--storage/xtradb/include/fts0pars.h6
-rw-r--r--storage/xtradb/include/log0log.h34
-rw-r--r--storage/xtradb/include/log0log.ic56
-rw-r--r--storage/xtradb/include/os0file.h2
-rw-r--r--storage/xtradb/include/os0sync.h65
-rw-r--r--storage/xtradb/include/sync0rw.ic11
-rw-r--r--storage/xtradb/include/sync0sync.h2
-rw-r--r--storage/xtradb/include/sync0sync.ic7
-rw-r--r--storage/xtradb/include/univ.i4
-rw-r--r--storage/xtradb/log/log0log.cc63
-rw-r--r--storage/xtradb/log/log0online.cc35
-rw-r--r--storage/xtradb/log/log0recv.cc20
-rw-r--r--storage/xtradb/mysql-test/storage_engine/alter_tablespace.opt2
-rw-r--r--storage/xtradb/mysql-test/storage_engine/autoinc_secondary.rdiff30
-rw-r--r--storage/xtradb/mysql-test/storage_engine/cache_index.rdiff71
-rw-r--r--storage/xtradb/mysql-test/storage_engine/checksum_table_live.rdiff13
-rw-r--r--storage/xtradb/mysql-test/storage_engine/col_opt_not_null.opt1
-rw-r--r--storage/xtradb/mysql-test/storage_engine/col_opt_null.opt1
-rw-r--r--storage/xtradb/mysql-test/storage_engine/define_engine.inc49
-rw-r--r--storage/xtradb/mysql-test/storage_engine/disabled.def8
-rw-r--r--storage/xtradb/mysql-test/storage_engine/fulltext_search.rdiff49
-rw-r--r--storage/xtradb/mysql-test/storage_engine/index_enable_disable.rdiff33
-rw-r--r--storage/xtradb/mysql-test/storage_engine/index_type_hash.rdiff60
-rw-r--r--storage/xtradb/mysql-test/storage_engine/insert_delayed.rdiff26
-rw-r--r--storage/xtradb/mysql-test/storage_engine/lock_concurrent.rdiff22
-rw-r--r--storage/xtradb/mysql-test/storage_engine/optimize_table.rdiff37
-rw-r--r--storage/xtradb/mysql-test/storage_engine/parts/checksum_table.rdiff13
-rw-r--r--storage/xtradb/mysql-test/storage_engine/parts/create_table.rdiff20
-rw-r--r--storage/xtradb/mysql-test/storage_engine/parts/disabled.def1
-rw-r--r--storage/xtradb/mysql-test/storage_engine/parts/optimize_table.rdiff58
-rw-r--r--storage/xtradb/mysql-test/storage_engine/parts/repair_table.rdiff158
-rw-r--r--storage/xtradb/mysql-test/storage_engine/parts/suite.opt2
-rw-r--r--storage/xtradb/mysql-test/storage_engine/repair_table.rdiff138
-rw-r--r--storage/xtradb/mysql-test/storage_engine/suite.opt1
-rw-r--r--storage/xtradb/mysql-test/storage_engine/tbl_opt_data_index_dir.rdiff23
-rw-r--r--storage/xtradb/mysql-test/storage_engine/tbl_opt_insert_method.rdiff11
-rw-r--r--storage/xtradb/mysql-test/storage_engine/tbl_opt_key_block_size.opt3
-rw-r--r--storage/xtradb/mysql-test/storage_engine/tbl_opt_row_format.opt3
-rw-r--r--storage/xtradb/mysql-test/storage_engine/tbl_opt_row_format.rdiff10
-rw-r--r--storage/xtradb/mysql-test/storage_engine/tbl_opt_union.rdiff16
-rw-r--r--storage/xtradb/mysql-test/storage_engine/trx/cons_snapshot_serializable.rdiff18
-rw-r--r--storage/xtradb/mysql-test/storage_engine/trx/level_read_committed.rdiff11
-rw-r--r--storage/xtradb/mysql-test/storage_engine/trx/level_read_uncommitted.rdiff11
-rw-r--r--storage/xtradb/mysql-test/storage_engine/trx/suite.opt3
-rw-r--r--storage/xtradb/mysql-test/storage_engine/type_blob.opt1
-rw-r--r--storage/xtradb/mysql-test/storage_engine/type_char_indexes.rdiff11
-rw-r--r--storage/xtradb/mysql-test/storage_engine/type_float_indexes.rdiff11
-rw-r--r--storage/xtradb/mysql-test/storage_engine/type_spatial_indexes.rdiff712
-rw-r--r--storage/xtradb/mysql-test/storage_engine/type_text.opt1
-rw-r--r--storage/xtradb/os/os0file.cc8
-rw-r--r--storage/xtradb/os/os0stacktrace.cc2
-rw-r--r--storage/xtradb/page/page0zip.cc16
-rw-r--r--storage/xtradb/row/row0ins.cc26
-rw-r--r--storage/xtradb/row/row0mysql.cc152
-rw-r--r--storage/xtradb/row/row0upd.cc71
-rw-r--r--storage/xtradb/srv/srv0srv.cc13
-rw-r--r--storage/xtradb/srv/srv0start.cc41
-rw-r--r--storage/xtradb/sync/sync0arr.cc4
-rw-r--r--storage/xtradb/sync/sync0rw.cc46
-rw-r--r--storage/xtradb/sync/sync0sync.cc9
-rw-r--r--storage/xtradb/trx/trx0sys.cc22
90 files changed, 3030 insertions, 730 deletions
diff --git a/storage/xtradb/CMakeLists.txt b/storage/xtradb/CMakeLists.txt
index f62fa2d72d1..3d9bf098fee 100644
--- a/storage/xtradb/CMakeLists.txt
+++ b/storage/xtradb/CMakeLists.txt
@@ -78,7 +78,6 @@ IF(NOT CMAKE_CROSSCOMPILING)
long x;
long y;
long res;
- char c;
x = 10;
y = 123;
@@ -99,6 +98,16 @@ IF(NOT CMAKE_CROSSCOMPILING)
if (res != 123 + 10 || x != 123 + 10) {
return(1);
}
+ return(0);
+ }"
+ HAVE_IB_GCC_ATOMIC_BUILTINS
+ )
+ CHECK_C_SOURCE_RUNS(
+ "
+ int main()
+ {
+ long res;
+ char c;
c = 10;
res = __sync_lock_test_and_set(&c, 123);
@@ -107,7 +116,7 @@ IF(NOT CMAKE_CROSSCOMPILING)
}
return(0);
}"
- HAVE_IB_GCC_ATOMIC_BUILTINS
+ HAVE_IB_GCC_ATOMIC_BUILTINS_BYTE
)
CHECK_C_SOURCE_RUNS(
"#include<stdint.h>
@@ -129,6 +138,25 @@ IF(NOT CMAKE_CROSSCOMPILING)
}"
HAVE_IB_GCC_ATOMIC_BUILTINS_64
)
+ CHECK_C_SOURCE_RUNS(
+ "#include<stdint.h>
+ int main()
+ {
+ __sync_synchronize();
+ return(0);
+ }"
+ HAVE_IB_GCC_SYNC_SYNCHRONISE
+ )
+ CHECK_C_SOURCE_RUNS(
+ "#include<stdint.h>
+ int main()
+ {
+ __atomic_thread_fence(__ATOMIC_ACQUIRE);
+ __atomic_thread_fence(__ATOMIC_RELEASE);
+ return(0);
+ }"
+ HAVE_IB_GCC_ATOMIC_THREAD_FENCE
+ )
ENDIF()
IF(HAVE_IB_GCC_ATOMIC_BUILTINS)
@@ -136,10 +164,22 @@ IF(HAVE_IB_GCC_ATOMIC_BUILTINS)
SET(XTRADB_OK 1)
ENDIF()
+IF(HAVE_IB_GCC_ATOMIC_BUILTINS_BYTE)
+ ADD_DEFINITIONS(-DHAVE_IB_GCC_ATOMIC_BUILTINS_BYTE=1)
+ENDIF()
+
IF(HAVE_IB_GCC_ATOMIC_BUILTINS_64)
ADD_DEFINITIONS(-DHAVE_IB_GCC_ATOMIC_BUILTINS_64=1)
ENDIF()
+IF(HAVE_IB_GCC_SYNC_SYNCHRONISE)
+ ADD_DEFINITIONS(-DHAVE_IB_GCC_SYNC_SYNCHRONISE=1)
+ENDIF()
+
+IF(HAVE_IB_GCC_ATOMIC_THREAD_FENCE)
+ ADD_DEFINITIONS(-DHAVE_IB_GCC_ATOMIC_THREAD_FENCE=1)
+ENDIF()
+
# either define HAVE_IB_ATOMIC_PTHREAD_T_GCC or not
IF(NOT CMAKE_CROSSCOMPILING)
CHECK_C_SOURCE_RUNS(
@@ -222,10 +262,21 @@ IF(CMAKE_SYSTEM_NAME STREQUAL "SunOS")
return(0);
}
" HAVE_IB_ATOMIC_PTHREAD_T_SOLARIS)
+ CHECK_C_SOURCE_COMPILES(
+ "#include <mbarrier.h>
+ int main() {
+ __machine_r_barrier();
+ __machine_w_barrier();
+ return(0);
+ }"
+ HAVE_IB_MACHINE_BARRIER_SOLARIS)
ENDIF()
IF(HAVE_IB_ATOMIC_PTHREAD_T_SOLARIS)
ADD_DEFINITIONS(-DHAVE_IB_ATOMIC_PTHREAD_T_SOLARIS=1)
ENDIF()
+ IF(HAVE_IB_MACHINE_BARRIER_SOLARIS)
+ ADD_DEFINITIONS(-DHAVE_IB_MACHINE_BARRIER_SOLARIS=1)
+ ENDIF()
ENDIF()
@@ -243,14 +294,8 @@ ENDIF()
IF(MSVC)
ADD_DEFINITIONS(-DHAVE_WINDOWS_ATOMICS)
+ ADD_DEFINITIONS(-DHAVE_WINDOWS_MM_FENCE)
SET(XTRADB_OK 1)
-
- # Avoid "unreferenced label" warning in generated file
- GET_FILENAME_COMPONENT(_SRC_DIR ${CMAKE_CURRENT_LIST_FILE} PATH)
- SET_SOURCE_FILES_PROPERTIES(${_SRC_DIR}/pars/pars0grm.c
- PROPERTIES COMPILE_FLAGS "/wd4102")
- SET_SOURCE_FILES_PROPERTIES(${_SRC_DIR}/pars/lexyy.c
- PROPERTIES COMPILE_FLAGS "/wd4003")
ENDIF()
diff --git a/storage/xtradb/api/api0api.cc b/storage/xtradb/api/api0api.cc
index bb65dd82216..a060cbc7270 100644
--- a/storage/xtradb/api/api0api.cc
+++ b/storage/xtradb/api/api0api.cc
@@ -1,6 +1,6 @@
/*****************************************************************************
-Copyright (c) 2008, 2013, Oracle and/or its affiliates. All Rights Reserved.
+Copyright (c) 2008, 2014, Oracle and/or its affiliates. All Rights Reserved.
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
@@ -2044,6 +2044,8 @@ ib_cursor_delete_row(
const rec_t* rec;
ib_bool_t page_format;
mtr_t mtr;
+ rec_t* copy = NULL;
+ byte ptr[UNIV_PAGE_SIZE_MAX];
page_format = static_cast<ib_bool_t>(
dict_table_is_comp(index->table));
@@ -2052,16 +2054,27 @@ ib_cursor_delete_row(
if (btr_pcur_restore_position(
BTR_SEARCH_LEAF, pcur, &mtr)) {
+ mem_heap_t* heap = NULL;
+ ulint offsets_[REC_OFFS_NORMAL_SIZE];
+ ulint* offsets = offsets_;
+
+ rec_offs_init(offsets_);
rec = btr_pcur_get_rec(pcur);
- } else {
- rec = NULL;
+
+ /* Since mtr will be commited, the rec
+ will not be protected. Make a copy of
+ the rec. */
+ offsets = rec_get_offsets(
+ rec, index, offsets, ULINT_UNDEFINED, &heap);
+ ut_ad(rec_offs_size(offsets) < UNIV_PAGE_SIZE_MAX);
+ copy = rec_copy(ptr, rec, offsets);
}
mtr_commit(&mtr);
- if (rec && !rec_get_deleted_flag(rec, page_format)) {
- err = ib_delete_row(cursor, pcur, rec);
+ if (copy && !rec_get_deleted_flag(copy, page_format)) {
+ err = ib_delete_row(cursor, pcur, copy);
} else {
err = DB_RECORD_NOT_FOUND;
}
diff --git a/storage/xtradb/btr/btr0cur.cc b/storage/xtradb/btr/btr0cur.cc
index a074414aa7a..5d8b5c04d68 100644
--- a/storage/xtradb/btr/btr0cur.cc
+++ b/storage/xtradb/btr/btr0cur.cc
@@ -2734,6 +2734,31 @@ make_external:
goto return_after_reservations;
}
+ if (big_rec_vec) {
+ const ulint redo_10p = srv_log_file_size * UNIV_PAGE_SIZE / 10;
+ ulint total_blob_len = 0;
+
+ /* Calculate the total number of bytes for blob data */
+ for (ulint i = 0; i < big_rec_vec->n_fields; i++) {
+ total_blob_len += big_rec_vec->fields[i].len;
+ }
+
+ if (total_blob_len > redo_10p) {
+ ib_logf(IB_LOG_LEVEL_ERROR, "The total blob data"
+ " length (" ULINTPF ") is greater than"
+ " 10%% of the redo log file size (" UINT64PF
+ "). Please increase innodb_log_file_size.",
+ total_blob_len, srv_log_file_size);
+ if (n_reserved > 0) {
+ fil_space_release_free_extents(
+ index->space, n_reserved);
+ }
+
+ err = DB_TOO_BIG_RECORD;
+ goto err_exit;
+ }
+ }
+
/* Store state of explicit locks on rec on the page infimum record,
before deleting rec. The page infimum acts as a dummy carrier of the
locks, taking care also of lock releases, before we can move the locks
@@ -4584,6 +4609,7 @@ btr_store_big_rec_extern_fields(
buf_block_t** freed_pages = NULL;
ulint n_freed_pages = 0;
dberr_t error = DB_SUCCESS;
+ ulint total_blob_len = 0;
ut_ad(rec_offs_validate(rec, index, offsets));
ut_ad(rec_offs_any_extern(offsets));
@@ -4603,6 +4629,23 @@ btr_store_big_rec_extern_fields(
rec_page_no = buf_block_get_page_no(rec_block);
ut_a(fil_page_get_type(page_align(rec)) == FIL_PAGE_INDEX);
+ const ulint redo_10p = (srv_log_file_size * UNIV_PAGE_SIZE / 10);
+
+ /* Calculate the total number of bytes for blob data */
+ for (ulint i = 0; i < big_rec_vec->n_fields; i++) {
+ total_blob_len += big_rec_vec->fields[i].len;
+ }
+
+ if (total_blob_len > redo_10p) {
+ ut_ad(op == BTR_STORE_INSERT);
+ ib_logf(IB_LOG_LEVEL_ERROR, "The total blob data length"
+ " (" ULINTPF ") is greater than 10%% of the"
+ " redo log file size (" UINT64PF "). Please"
+ " increase innodb_log_file_size.",
+ total_blob_len, srv_log_file_size);
+ return(DB_TOO_BIG_RECORD);
+ }
+
if (page_zip) {
int err;
diff --git a/storage/xtradb/buf/buf0buf.cc b/storage/xtradb/buf/buf0buf.cc
index 27e2af20298..bd0929dd36c 100644
--- a/storage/xtradb/buf/buf0buf.cc
+++ b/storage/xtradb/buf/buf0buf.cc
@@ -379,6 +379,48 @@ buf_pool_get_oldest_modification(void)
}
/********************************************************************//**
+Gets the smallest oldest_modification lsn for any page in the pool. Returns
+zero if all modified pages have been flushed to disk.
+@return oldest modification in pool, zero if none */
+UNIV_INTERN
+lsn_t
+buf_pool_get_oldest_modification_peek(void)
+/*=======================================*/
+{
+ ulint i;
+ buf_page_t* bpage;
+ lsn_t lsn = 0;
+ lsn_t oldest_lsn = 0;
+
+ /* Dirsty read to buffer pool array */
+ for (i = 0; i < srv_buf_pool_instances; i++) {
+ buf_pool_t* buf_pool;
+
+ buf_pool = buf_pool_from_array(i);
+
+ buf_flush_list_mutex_enter(buf_pool);
+
+ bpage = UT_LIST_GET_LAST(buf_pool->flush_list);
+
+ if (bpage != NULL) {
+ ut_ad(bpage->in_flush_list);
+ lsn = bpage->oldest_modification;
+ }
+
+ buf_flush_list_mutex_exit(buf_pool);
+
+ if (!oldest_lsn || oldest_lsn > lsn) {
+ oldest_lsn = lsn;
+ }
+ }
+
+ /* The returned answer may be out of date: the flush_list can
+ change after the mutex has been released. */
+
+ return(oldest_lsn);
+}
+
+/********************************************************************//**
Get total buffer pool statistics. */
UNIV_INTERN
void
@@ -2990,12 +3032,6 @@ got_block:
ut_ad(buf_block_get_state(fix_block) == BUF_BLOCK_FILE_PAGE);
-#if UNIV_WORD_SIZE == 4
- /* On 32-bit systems, there is no padding in buf_page_t. On
- other systems, Valgrind could complain about uninitialized pad
- bytes. */
- UNIV_MEM_ASSERT_RW(&fix_block->page, sizeof(fix_block->page));
-#endif
#if defined UNIV_DEBUG || defined UNIV_IBUF_DEBUG
if ((mode == BUF_GET_IF_IN_POOL || mode == BUF_GET_IF_IN_POOL_OR_WATCH)
@@ -5628,7 +5664,7 @@ buf_get_free_list_len(void)
#else /* !UNIV_HOTBACKUP */
/********************************************************************//**
-Inits a page to the buffer buf_pool, for use in ibbackup --restore. */
+Inits a page to the buffer buf_pool, for use in mysqlbackup --restore. */
UNIV_INTERN
void
buf_page_init_for_backup_restore(
diff --git a/storage/xtradb/buf/buf0lru.cc b/storage/xtradb/buf/buf0lru.cc
index be6d38f5ef7..3b0319e4e79 100644
--- a/storage/xtradb/buf/buf0lru.cc
+++ b/storage/xtradb/buf/buf0lru.cc
@@ -1973,13 +1973,6 @@ buf_LRU_free_page(
ut_ad(buf_page_in_file(bpage));
ut_ad(bpage->in_LRU_list);
-#if UNIV_WORD_SIZE == 4
- /* On 32-bit systems, there is no padding in buf_page_t. On
- other systems, Valgrind could complain about uninitialized pad
- bytes. */
- UNIV_MEM_ASSERT_RW(bpage, sizeof *bpage);
-#endif
-
if (!buf_page_can_relocate(bpage)) {
/* Do not free buffer fixed or I/O-fixed blocks. */
@@ -2012,12 +2005,6 @@ buf_LRU_free_page(
ut_ad(buf_page_in_file(bpage));
ut_ad(bpage->in_LRU_list);
ut_ad(!bpage->in_flush_list == !bpage->oldest_modification);
-#if UNIV_WORD_SIZE == 4
- /* On 32-bit systems, there is no padding in buf_page_t. On
- other systems, Valgrind could complain about uninitialized pad
- bytes. */
- UNIV_MEM_ASSERT_RW(bpage, sizeof *bpage);
-#endif
#ifdef UNIV_DEBUG
if (buf_debug_prints) {
@@ -2123,13 +2110,6 @@ not_freed:
ut_ad(prev_b->in_LRU_list);
ut_ad(buf_page_in_file(prev_b));
-#if UNIV_WORD_SIZE == 4
- /* On 32-bit systems, there is no
- padding in buf_page_t. On other
- systems, Valgrind could complain about
- uninitialized pad bytes. */
- UNIV_MEM_ASSERT_RW(prev_b, sizeof *prev_b);
-#endif
UT_LIST_INSERT_AFTER(LRU, buf_pool->LRU,
prev_b, b);
@@ -2340,13 +2320,6 @@ buf_LRU_block_remove_hashed(
ut_a(buf_page_get_io_fix(bpage) == BUF_IO_NONE);
ut_a(bpage->buf_fix_count == 0);
-#if UNIV_WORD_SIZE == 4
- /* On 32-bit systems, there is no padding in
- buf_page_t. On other systems, Valgrind could complain
- about uninitialized pad bytes. */
- UNIV_MEM_ASSERT_RW(bpage, sizeof *bpage);
-#endif
-
buf_LRU_remove_block(bpage);
buf_pool->freed_page_clock += 1;
diff --git a/storage/xtradb/dict/dict0crea.cc b/storage/xtradb/dict/dict0crea.cc
index ff892749d4f..30523ff2af4 100644
--- a/storage/xtradb/dict/dict0crea.cc
+++ b/storage/xtradb/dict/dict0crea.cc
@@ -1,6 +1,6 @@
/*****************************************************************************
-Copyright (c) 1996, 2013, Oracle and/or its affiliates. All Rights Reserved.
+Copyright (c) 1996, 2014, Oracle and/or its affiliates. All Rights Reserved.
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
@@ -1611,26 +1611,25 @@ dict_create_add_foreign_to_dictionary(
return(error);
}
-/********************************************************************//**
-Adds foreign key definitions to data dictionary tables in the database.
-@return error code or DB_SUCCESS */
+/** Adds the given set of foreign key objects to the dictionary tables
+in the database. This function does not modify the dictionary cache. The
+caller must ensure that all foreign key objects contain a valid constraint
+name in foreign->id.
+@param[in] local_fk_set set of foreign key objects, to be added to
+the dictionary tables
+@param[in] table table to which the foreign key objects in
+local_fk_set belong to
+@param[in,out] trx transaction
+@return error code or DB_SUCCESS */
UNIV_INTERN
dberr_t
dict_create_add_foreigns_to_dictionary(
/*===================================*/
- ulint start_id,/*!< in: if we are actually doing ALTER TABLE
- ADD CONSTRAINT, we want to generate constraint
- numbers which are bigger than in the table so
- far; we number the constraints from
- start_id + 1 up; start_id should be set to 0 if
- we are creating a new table, or if the table
- so far has no constraints for which the name
- was generated here */
- dict_table_t* table, /*!< in: table */
- trx_t* trx) /*!< in: transaction */
+ const dict_foreign_set& local_fk_set,
+ const dict_table_t* table,
+ trx_t* trx)
{
dict_foreign_t* foreign;
- ulint number = start_id + 1;
dberr_t error;
ut_ad(mutex_own(&(dict_sys->mutex)));
@@ -1643,17 +1642,12 @@ dict_create_add_foreigns_to_dictionary(
return(DB_ERROR);
}
- for (foreign = UT_LIST_GET_FIRST(table->foreign_list);
- foreign;
- foreign = UT_LIST_GET_NEXT(foreign_list, foreign)) {
+ for (dict_foreign_set::const_iterator it = local_fk_set.begin();
+ it != local_fk_set.end();
+ ++it) {
- error = dict_create_add_foreign_id(&number, table->name,
- foreign);
-
- if (error != DB_SUCCESS) {
-
- return(error);
- }
+ foreign = *it;
+ ut_ad(foreign->id != NULL);
error = dict_create_add_foreign_to_dictionary(table->name,
foreign, trx);
diff --git a/storage/xtradb/dict/dict0dict.cc b/storage/xtradb/dict/dict0dict.cc
index 83604b3057a..bee6d8f5534 100644
--- a/storage/xtradb/dict/dict0dict.cc
+++ b/storage/xtradb/dict/dict0dict.cc
@@ -27,6 +27,7 @@ Created 1/8/1996 Heikki Tuuri
#include "dict0dict.h"
#include "fts0fts.h"
#include "fil0fil.h"
+#include <algorithm>
#ifdef UNIV_NONINL
#include "dict0dict.ic"
@@ -1251,8 +1252,8 @@ dict_table_can_be_evicted(
#endif /* UNIV_SYNC_DEBUG */
ut_a(table->can_be_evicted);
- ut_a(UT_LIST_GET_LEN(table->foreign_list) == 0);
- ut_a(UT_LIST_GET_LEN(table->referenced_list) == 0);
+ ut_a(table->foreign_set.empty());
+ ut_a(table->referenced_set.empty());
if (table->n_ref_count == 0) {
dict_index_t* index;
@@ -1468,6 +1469,22 @@ dict_index_find_on_id_low(
return(NULL);
}
+/** Function object to remove a foreign key constraint from the
+referenced_set of the referenced table. The foreign key object is
+also removed from the dictionary cache. The foreign key constraint
+is not removed from the foreign_set of the table containing the
+constraint. */
+struct dict_foreign_remove_partial
+{
+ void operator()(dict_foreign_t* foreign) {
+ dict_table_t* table = foreign->referenced_table;
+ if (table != NULL) {
+ table->referenced_set.erase(foreign);
+ }
+ dict_foreign_free(foreign);
+ }
+};
+
/**********************************************************************//**
Renames a table object.
@return TRUE if success */
@@ -1642,27 +1659,25 @@ dict_table_rename_in_cache(
system tables through a call of dict_load_foreigns. */
/* Remove the foreign constraints from the cache */
- foreign = UT_LIST_GET_LAST(table->foreign_list);
-
- while (foreign != NULL) {
- dict_foreign_remove_from_cache(foreign);
- foreign = UT_LIST_GET_LAST(table->foreign_list);
- }
+ std::for_each(table->foreign_set.begin(),
+ table->foreign_set.end(),
+ dict_foreign_remove_partial());
+ table->foreign_set.clear();
/* Reset table field in referencing constraints */
+ for (dict_foreign_set::iterator it
+ = table->referenced_set.begin();
+ it != table->referenced_set.end();
+ ++it) {
- foreign = UT_LIST_GET_FIRST(table->referenced_list);
-
- while (foreign != NULL) {
+ foreign = *it;
foreign->referenced_table = NULL;
foreign->referenced_index = NULL;
- foreign = UT_LIST_GET_NEXT(referenced_list, foreign);
}
- /* Make the list of referencing constraints empty */
-
- UT_LIST_INIT(table->referenced_list);
+ /* Make the set of referencing constraints empty */
+ table->referenced_set.clear();
return(DB_SUCCESS);
}
@@ -1671,9 +1686,19 @@ dict_table_rename_in_cache(
the constraint id of new format >= 4.0.18 constraints. Note that at
this point we have already changed table->name to the new name. */
- foreign = UT_LIST_GET_FIRST(table->foreign_list);
+ dict_foreign_set fk_set;
+
+ for (;;) {
+
+ dict_foreign_set::iterator it
+ = table->foreign_set.begin();
+
+ if (it == table->foreign_set.end()) {
+ break;
+ }
+
+ foreign = *it;
- while (foreign != NULL) {
if (ut_strlen(foreign->foreign_table_name)
< ut_strlen(table->name)) {
/* Allocate a longer name buffer;
@@ -1823,12 +1848,18 @@ dict_table_rename_in_cache(
mem_free(old_id);
}
- foreign = UT_LIST_GET_NEXT(foreign_list, foreign);
+ table->foreign_set.erase(it);
+ fk_set.insert(foreign);
}
- for (foreign = UT_LIST_GET_FIRST(table->referenced_list);
- foreign != NULL;
- foreign = UT_LIST_GET_NEXT(referenced_list, foreign)) {
+ ut_a(table->foreign_set.empty());
+ table->foreign_set.swap(fk_set);
+
+ for (dict_foreign_set::iterator it = table->referenced_set.begin();
+ it != table->referenced_set.end();
+ ++it) {
+
+ foreign = *it;
if (ut_strlen(foreign->referenced_table_name)
< ut_strlen(table->name)) {
@@ -1898,27 +1929,17 @@ dict_table_remove_from_cache_low(
ut_ad(mutex_own(&(dict_sys->mutex)));
ut_ad(table->magic_n == DICT_TABLE_MAGIC_N);
-#if 0
- fputs("Removing table ", stderr);
- ut_print_name(stderr, table->name, ULINT_UNDEFINED);
- fputs(" from dictionary cache\n", stderr);
-#endif
-
/* Remove the foreign constraints from the cache */
-
- for (foreign = UT_LIST_GET_LAST(table->foreign_list);
- foreign != NULL;
- foreign = UT_LIST_GET_LAST(table->foreign_list)) {
-
- dict_foreign_remove_from_cache(foreign);
- }
+ std::for_each(table->foreign_set.begin(), table->foreign_set.end(),
+ dict_foreign_remove_partial());
+ table->foreign_set.clear();
/* Reset table field in referencing constraints */
+ for (dict_foreign_set::iterator it = table->referenced_set.begin();
+ it != table->referenced_set.end();
+ ++it) {
- for (foreign = UT_LIST_GET_FIRST(table->referenced_list);
- foreign != NULL;
- foreign = UT_LIST_GET_NEXT(referenced_list, foreign)) {
-
+ foreign = *it;
foreign->referenced_table = NULL;
foreign->referenced_index = NULL;
}
@@ -3138,7 +3159,7 @@ dict_table_is_referenced_by_foreign_key(
/*====================================*/
const dict_table_t* table) /*!< in: InnoDB table */
{
- return(UT_LIST_GET_LEN(table->referenced_list) > 0);
+ return(!table->referenced_set.empty());
}
/*********************************************************************//**
@@ -3158,9 +3179,11 @@ dict_table_get_referenced_constraint(
ut_ad(index != NULL);
ut_ad(table != NULL);
- for (foreign = UT_LIST_GET_FIRST(table->referenced_list);
- foreign;
- foreign = UT_LIST_GET_NEXT(referenced_list, foreign)) {
+ for (dict_foreign_set::iterator it = table->referenced_set.begin();
+ it != table->referenced_set.end();
+ ++it) {
+
+ foreign = *it;
if (foreign->referenced_index == index) {
@@ -3189,9 +3212,11 @@ dict_table_get_foreign_constraint(
ut_ad(index != NULL);
ut_ad(table != NULL);
- for (foreign = UT_LIST_GET_FIRST(table->foreign_list);
- foreign;
- foreign = UT_LIST_GET_NEXT(foreign_list, foreign)) {
+ for (dict_foreign_set::iterator it = table->foreign_set.begin();
+ it != table->foreign_set.end();
+ ++it) {
+
+ foreign = *it;
if (foreign->foreign_index == index) {
@@ -3202,17 +3227,6 @@ dict_table_get_foreign_constraint(
return(NULL);
}
-/*********************************************************************//**
-Frees a foreign key struct. */
-UNIV_INTERN
-void
-dict_foreign_free(
-/*==============*/
- dict_foreign_t* foreign) /*!< in, own: foreign key struct */
-{
- mem_heap_free(foreign->heap);
-}
-
/**********************************************************************//**
Removes a foreign constraint struct from the dictionary cache. */
UNIV_INTERN
@@ -3224,16 +3238,12 @@ dict_foreign_remove_from_cache(
ut_ad(mutex_own(&(dict_sys->mutex)));
ut_a(foreign);
- if (foreign->referenced_table) {
- UT_LIST_REMOVE(referenced_list,
- foreign->referenced_table->referenced_list,
- foreign);
+ if (foreign->referenced_table != NULL) {
+ foreign->referenced_table->referenced_set.erase(foreign);
}
- if (foreign->foreign_table) {
- UT_LIST_REMOVE(foreign_list,
- foreign->foreign_table->foreign_list,
- foreign);
+ if (foreign->foreign_table != NULL) {
+ foreign->foreign_table->foreign_set.erase(foreign);
}
dict_foreign_free(foreign);
@@ -3247,33 +3257,21 @@ static
dict_foreign_t*
dict_foreign_find(
/*==============*/
- dict_table_t* table, /*!< in: table object */
- const char* id) /*!< in: foreign constraint id */
+ dict_table_t* table, /*!< in: table object */
+ dict_foreign_t* foreign) /*!< in: foreign constraint */
{
- dict_foreign_t* foreign;
-
ut_ad(mutex_own(&(dict_sys->mutex)));
- foreign = UT_LIST_GET_FIRST(table->foreign_list);
+ dict_foreign_set::iterator it = table->foreign_set.find(foreign);
- while (foreign) {
- if (ut_strcmp(id, foreign->id) == 0) {
-
- return(foreign);
- }
-
- foreign = UT_LIST_GET_NEXT(foreign_list, foreign);
+ if (it != table->foreign_set.end()) {
+ return(*it);
}
- foreign = UT_LIST_GET_FIRST(table->referenced_list);
-
- while (foreign) {
- if (ut_strcmp(id, foreign->id) == 0) {
-
- return(foreign);
- }
+ it = table->referenced_set.find(foreign);
- foreign = UT_LIST_GET_NEXT(referenced_list, foreign);
+ if (it != table->referenced_set.end()) {
+ return(*it);
}
return(NULL);
@@ -3433,11 +3431,11 @@ dict_foreign_add_to_cache(
ut_a(for_table || ref_table);
if (for_table) {
- for_in_cache = dict_foreign_find(for_table, foreign->id);
+ for_in_cache = dict_foreign_find(for_table, foreign);
}
if (!for_in_cache && ref_table) {
- for_in_cache = dict_foreign_find(ref_table, foreign->id);
+ for_in_cache = dict_foreign_find(ref_table, foreign);
}
if (for_in_cache) {
@@ -3474,9 +3472,12 @@ dict_foreign_add_to_cache(
for_in_cache->referenced_table = ref_table;
for_in_cache->referenced_index = index;
- UT_LIST_ADD_LAST(referenced_list,
- ref_table->referenced_list,
- for_in_cache);
+
+ std::pair<dict_foreign_set::iterator, bool> ret
+ = ref_table->referenced_set.insert(for_in_cache);
+
+ ut_a(ret.second); /* second is true if the insertion
+ took place */
added_to_referenced_list = TRUE;
}
@@ -3505,10 +3506,13 @@ dict_foreign_add_to_cache(
if (for_in_cache == foreign) {
if (added_to_referenced_list) {
- UT_LIST_REMOVE(
- referenced_list,
- ref_table->referenced_list,
- for_in_cache);
+ const dict_foreign_set::size_type n
+ = ref_table->referenced_set
+ .erase(for_in_cache);
+
+ ut_a(n == 1); /* the number of
+ elements removed must
+ be one */
}
mem_heap_free(foreign->heap);
@@ -3519,9 +3523,11 @@ dict_foreign_add_to_cache(
for_in_cache->foreign_table = for_table;
for_in_cache->foreign_index = index;
- UT_LIST_ADD_LAST(foreign_list,
- for_table->foreign_list,
- for_in_cache);
+ std::pair<dict_foreign_set::iterator, bool> ret
+ = for_table->foreign_set.insert(for_in_cache);
+
+ ut_a(ret.second); /* second is true if the insertion
+ took place */
}
/* We need to move the table to the non-LRU end of the table LRU
@@ -4099,9 +4105,12 @@ dict_table_get_highest_foreign_id(
ut_a(table);
len = ut_strlen(table->name);
- foreign = UT_LIST_GET_FIRST(table->foreign_list);
- while (foreign) {
+ for (dict_foreign_set::iterator it = table->foreign_set.begin();
+ it != table->foreign_set.end();
+ ++it) {
+ foreign = *it;
+
if (ut_strlen(foreign->id) > ((sizeof dict_ibfk) - 1) + len
&& 0 == ut_memcmp(foreign->id, table->name, len)
&& 0 == ut_memcmp(foreign->id + len,
@@ -4120,8 +4129,6 @@ dict_table_get_highest_foreign_id(
}
}
}
-
- foreign = UT_LIST_GET_NEXT(foreign_list, foreign);
}
return(biggest_id);
@@ -4182,6 +4189,7 @@ dict_create_foreign_constraints_low(
dict_table_t* referenced_table;
dict_table_t* table_to_alter;
ulint highest_id_so_far = 0;
+ ulint number = 1;
dict_index_t* index;
dict_foreign_t* foreign;
const char* ptr = sql_string;
@@ -4200,6 +4208,8 @@ dict_create_foreign_constraints_low(
const dict_col_t*columns[500];
const char* column_names[500];
const char* referenced_table_name;
+ dict_foreign_set local_fk_set;
+ dict_foreign_set_free local_fk_set_free(local_fk_set);
ut_ad(!srv_read_only_mode);
ut_ad(mutex_own(&(dict_sys->mutex)));
@@ -4264,6 +4274,7 @@ dict_create_foreign_constraints_low(
table_to_alter);
}
+ number = highest_id_so_far + 1;
/* Scan for foreign key declarations in a loop */
loop:
/* Scan either to "CONSTRAINT" or "FOREIGN", whichever is closer */
@@ -4308,7 +4319,7 @@ loop:
command, determine if there are any foreign keys, and
if so, immediately reject the command if the table is a
temporary one. For now, this kludge will work. */
- if (reject_fks && (UT_LIST_GET_LEN(table->foreign_list) > 0)) {
+ if (reject_fks && !local_fk_set.empty()) {
return(DB_CANNOT_ADD_CONSTRAINT);
}
@@ -4318,7 +4329,17 @@ loop:
to the data dictionary system tables on disk */
error = dict_create_add_foreigns_to_dictionary(
- highest_id_so_far, table, trx);
+ local_fk_set, table, trx);
+
+ if (error == DB_SUCCESS) {
+
+ table->foreign_set.insert(local_fk_set.begin(),
+ local_fk_set.end());
+ std::for_each(local_fk_set.begin(),
+ local_fk_set.end(),
+ dict_foreign_add_to_referenced_table());
+ local_fk_set.clear();
+ }
return(error);
}
@@ -4477,6 +4498,24 @@ col_loop1:
strcpy(foreign->id + db_len + 1, constraint_name);
}
+ if (foreign->id == NULL) {
+ error = dict_create_add_foreign_id(&number,
+ table->name, foreign);
+ if (error != DB_SUCCESS) {
+ dict_foreign_free(foreign);
+ return(error);
+ }
+ }
+
+ std::pair<dict_foreign_set::iterator, bool> ret
+ = local_fk_set.insert(foreign);
+
+ if (!ret.second) {
+ /* A duplicate foreign key name has been found */
+ dict_foreign_free(foreign);
+ return(DB_CANNOT_ADD_CONSTRAINT);
+ }
+
foreign->foreign_table = table;
foreign->foreign_table_name = mem_heap_strdup(
foreign->heap, table->name);
@@ -4502,8 +4541,6 @@ col_loop1:
checking of foreign key constraints! */
if (!success || (!referenced_table && trx->check_foreigns)) {
- dict_foreign_free(foreign);
-
mutex_enter(&dict_foreign_err_mutex);
dict_foreign_error_report_low(ef, name);
fprintf(ef, "%s:\nCannot resolve table name close to:\n"
@@ -4517,7 +4554,6 @@ col_loop1:
ptr = dict_accept(cs, ptr, "(", &success);
if (!success) {
- dict_foreign_free(foreign);
dict_foreign_report_syntax_err(name, start_of_latest_foreign,
ptr);
return(DB_CANNOT_ADD_CONSTRAINT);
@@ -4532,7 +4568,6 @@ col_loop2:
i++;
if (!success) {
- dict_foreign_free(foreign);
mutex_enter(&dict_foreign_err_mutex);
dict_foreign_error_report_low(ef, name);
@@ -4553,7 +4588,6 @@ col_loop2:
ptr = dict_accept(cs, ptr, ")", &success);
if (!success || foreign->n_fields != i) {
- dict_foreign_free(foreign);
dict_foreign_report_syntax_err(name, start_of_latest_foreign,
ptr);
@@ -4579,7 +4613,6 @@ scan_on_conditions:
ptr = dict_accept(cs, ptr, "UPDATE", &success);
if (!success) {
- dict_foreign_free(foreign);
dict_foreign_report_syntax_err(
name, start_of_latest_foreign, ptr);
@@ -4617,7 +4650,6 @@ scan_on_conditions:
ptr = dict_accept(cs, ptr, "ACTION", &success);
if (!success) {
- dict_foreign_free(foreign);
dict_foreign_report_syntax_err(
name, start_of_latest_foreign, ptr);
@@ -4636,7 +4668,6 @@ scan_on_conditions:
ptr = dict_accept(cs, ptr, "SET", &success);
if (!success) {
- dict_foreign_free(foreign);
dict_foreign_report_syntax_err(name, start_of_latest_foreign,
ptr);
return(DB_CANNOT_ADD_CONSTRAINT);
@@ -4645,7 +4676,6 @@ scan_on_conditions:
ptr = dict_accept(cs, ptr, "NULL", &success);
if (!success) {
- dict_foreign_free(foreign);
dict_foreign_report_syntax_err(name, start_of_latest_foreign,
ptr);
return(DB_CANNOT_ADD_CONSTRAINT);
@@ -4658,8 +4688,6 @@ scan_on_conditions:
/* It is not sensible to define SET NULL
if the column is not allowed to be NULL! */
- dict_foreign_free(foreign);
-
mutex_enter(&dict_foreign_err_mutex);
dict_foreign_error_report_low(ef, name);
fprintf(ef, "%s:\n"
@@ -4685,8 +4713,6 @@ try_find_index:
if (n_on_deletes > 1 || n_on_updates > 1) {
/* It is an error to define more than 1 action */
- dict_foreign_free(foreign);
-
mutex_enter(&dict_foreign_err_mutex);
dict_foreign_error_report_low(ef, name);
fprintf(ef, "%s:\n"
@@ -4708,7 +4734,6 @@ try_find_index:
foreign->foreign_index,
TRUE, FALSE);
if (!index) {
- dict_foreign_free(foreign);
mutex_enter(&dict_foreign_err_mutex);
dict_foreign_error_report_low(ef, name);
fprintf(ef, "%s:\n"
@@ -4752,16 +4777,6 @@ try_find_index:
= mem_heap_strdup(foreign->heap, column_names[i]);
}
- /* We found an ok constraint definition: add to the lists */
-
- UT_LIST_ADD_LAST(foreign_list, table->foreign_list, foreign);
-
- if (referenced_table) {
- UT_LIST_ADD_LAST(referenced_list,
- referenced_table->referenced_list,
- foreign);
- }
-
goto loop;
}
/**************************************************************************
@@ -4847,7 +4862,6 @@ dict_foreign_parse_drop_constraints(
const char*** constraints_to_drop) /*!< out: id's of the
constraints to drop */
{
- dict_foreign_t* foreign;
ibool success;
char* str;
size_t len;
@@ -4924,25 +4938,10 @@ loop:
(*constraints_to_drop)[*n] = id;
(*n)++;
- /* Look for the given constraint id */
-
- foreign = UT_LIST_GET_FIRST(table->foreign_list);
-
- while (foreign != NULL) {
- if (0 == innobase_strcasecmp(foreign->id, id)
- || (strchr(foreign->id, '/')
- && 0 == innobase_strcasecmp(
- id,
- dict_remove_db_name(foreign->id)))) {
- /* Found */
- break;
- }
-
- foreign = UT_LIST_GET_NEXT(foreign_list, foreign);
- }
-
-
- if (foreign == NULL) {
+ if (std::find_if(table->foreign_set.begin(),
+ table->foreign_set.end(),
+ dict_foreign_matches_id(id))
+ == table->foreign_set.end()) {
if (!srv_read_only_mode) {
FILE* ef = dict_foreign_err_file;
@@ -5269,7 +5268,6 @@ dict_table_print(
dict_table_t* table) /*!< in: table */
{
dict_index_t* index;
- dict_foreign_t* foreign;
ulint i;
ut_ad(mutex_own(&(dict_sys->mutex)));
@@ -5308,19 +5306,13 @@ dict_table_print(
dict_table_stats_unlock(table, RW_X_LATCH);
- foreign = UT_LIST_GET_FIRST(table->foreign_list);
-
- while (foreign != NULL) {
- dict_foreign_print_low(foreign);
- foreign = UT_LIST_GET_NEXT(foreign_list, foreign);
- }
-
- foreign = UT_LIST_GET_FIRST(table->referenced_list);
+ std::for_each(table->foreign_set.begin(),
+ table->foreign_set.end(),
+ dict_foreign_print_low);
- while (foreign != NULL) {
- dict_foreign_print_low(foreign);
- foreign = UT_LIST_GET_NEXT(referenced_list, foreign);
- }
+ std::for_each(table->referenced_set.begin(),
+ table->referenced_set.end(),
+ dict_foreign_print_low);
}
/**********************************************************************//**
@@ -5528,15 +5520,12 @@ dict_print_info_on_foreign_keys(
mutex_enter(&(dict_sys->mutex));
- foreign = UT_LIST_GET_FIRST(table->foreign_list);
-
- if (foreign == NULL) {
- mutex_exit(&(dict_sys->mutex));
+ for (dict_foreign_set::iterator it = table->foreign_set.begin();
+ it != table->foreign_set.end();
+ ++it) {
- return;
- }
+ foreign = *it;
- while (foreign != NULL) {
if (create_table_format) {
dict_print_info_on_foreign_key_in_create_format(
file, trx, foreign, TRUE);
@@ -5593,8 +5582,6 @@ dict_print_info_on_foreign_keys(
fputs(" ON UPDATE NO ACTION", file);
}
}
-
- foreign = UT_LIST_GET_NEXT(foreign_list, foreign);
}
mutex_exit(&(dict_sys->mutex));
@@ -5965,10 +5952,11 @@ dict_foreign_replace_index(
ut_ad(index->to_be_dropped);
ut_ad(index->table == table);
- for (foreign = UT_LIST_GET_FIRST(table->foreign_list);
- foreign;
- foreign = UT_LIST_GET_NEXT(foreign_list, foreign)) {
+ for (dict_foreign_set::iterator it = table->foreign_set.begin();
+ it != table->foreign_set.end();
+ ++it) {
+ foreign = *it;
if (foreign->foreign_index == index) {
ut_ad(foreign->foreign_table == index->table);
@@ -5988,10 +5976,11 @@ dict_foreign_replace_index(
}
}
- for (foreign = UT_LIST_GET_FIRST(table->referenced_list);
- foreign;
- foreign = UT_LIST_GET_NEXT(referenced_list, foreign)) {
+ for (dict_foreign_set::iterator it = table->referenced_set.begin();
+ it != table->referenced_set.end();
+ ++it) {
+ foreign = *it;
if (foreign->referenced_index == index) {
ut_ad(foreign->referenced_table == index->table);
@@ -6303,24 +6292,24 @@ dict_table_schema_check(
}
}
- if (req_schema->n_foreign != UT_LIST_GET_LEN(table->foreign_list)) {
+ if (req_schema->n_foreign != table->foreign_set.size()) {
ut_snprintf(
errstr, errstr_sz,
- "Table %s has %lu foreign key(s) pointing to other "
- "tables, but it must have %lu.",
+ "Table %s has " ULINTPF " foreign key(s) pointing"
+ " to other tables, but it must have %lu.",
ut_format_name(req_schema->table_name,
TRUE, buf, sizeof(buf)),
- UT_LIST_GET_LEN(table->foreign_list),
+ static_cast<ulint>(table->foreign_set.size()),
req_schema->n_foreign);
return(DB_ERROR);
}
- if (req_schema->n_referenced != UT_LIST_GET_LEN(table->referenced_list)) {
+ if (req_schema->n_referenced != table->referenced_set.size()) {
ut_snprintf(
errstr, errstr_sz,
- "There are %lu foreign key(s) pointing to %s, "
+ "There are " ULINTPF " foreign key(s) pointing to %s, "
"but there must be %lu.",
- UT_LIST_GET_LEN(table->referenced_list),
+ static_cast<ulint>(table->referenced_set.size()),
ut_format_name(req_schema->table_name,
TRUE, buf, sizeof(buf)),
req_schema->n_referenced);
diff --git a/storage/xtradb/dict/dict0mem.cc b/storage/xtradb/dict/dict0mem.cc
index b80f9fc5750..5e0ffab4bf7 100644
--- a/storage/xtradb/dict/dict0mem.cc
+++ b/storage/xtradb/dict/dict0mem.cc
@@ -137,6 +137,9 @@ dict_mem_table_create(
#endif /* !UNIV_HOTBACKUP */
+ new(&table->foreign_set) dict_foreign_set();
+ new(&table->referenced_set) dict_foreign_set();
+
return(table);
}
@@ -172,6 +175,9 @@ dict_mem_table_free(
dict_table_stats_latch_destroy(table);
+ table->foreign_set.~dict_foreign_set();
+ table->referenced_set.~dict_foreign_set();
+
ut_free(table->name);
mem_heap_free(table->heap);
}
@@ -342,10 +348,15 @@ dict_mem_table_col_rename_low(
table->col_names = col_names;
}
+ dict_foreign_t* foreign;
+
/* Replace the field names in every foreign key constraint. */
- for (dict_foreign_t* foreign = UT_LIST_GET_FIRST(table->foreign_list);
- foreign != NULL;
- foreign = UT_LIST_GET_NEXT(foreign_list, foreign)) {
+ for (dict_foreign_set::iterator it = table->foreign_set.begin();
+ it != table->foreign_set.end();
+ ++it) {
+
+ foreign = *it;
+
for (unsigned f = 0; f < foreign->n_fields; f++) {
/* These can point straight to
table->col_names, because the foreign key
@@ -357,10 +368,12 @@ dict_mem_table_col_rename_low(
}
}
- for (dict_foreign_t* foreign = UT_LIST_GET_FIRST(
- table->referenced_list);
- foreign != NULL;
- foreign = UT_LIST_GET_NEXT(referenced_list, foreign)) {
+ for (dict_foreign_set::iterator it = table->referenced_set.begin();
+ it != table->referenced_set.end();
+ ++it) {
+
+ foreign = *it;
+
for (unsigned f = 0; f < foreign->n_fields; f++) {
/* foreign->referenced_col_names[] need to be
copies, because the constraint may become
diff --git a/storage/xtradb/fil/fil0fil.cc b/storage/xtradb/fil/fil0fil.cc
index 74d5b51d230..852311d3864 100644
--- a/storage/xtradb/fil/fil0fil.cc
+++ b/storage/xtradb/fil/fil0fil.cc
@@ -112,7 +112,7 @@ completes, we decrement the count and return the file node to the LRU-list if
the count drops to zero. */
/** When mysqld is run, the default directory "." is the mysqld datadir,
-but in the MySQL Embedded Server Library and ibbackup it is not the default
+but in the MySQL Embedded Server Library and mysqlbackup it is not the default
directory, and we must set the base file path explicitly */
UNIV_INTERN const char* fil_path_to_mysql_datadir = ".";
@@ -2061,8 +2061,8 @@ fil_check_first_page(
}
/*******************************************************************//**
-Reads the flushed lsn, arch no, and tablespace flag fields from a data
-file at database startup.
+Reads the flushed lsn, arch no, space_id and tablespace flag fields from
+the first page of a data file at database startup.
@retval NULL on success, or if innodb_force_recovery is set
@return pointer to an error message string */
UNIV_INTERN
@@ -2093,16 +2093,19 @@ fil_read_first_page(
os_file_read(data_file, page, 0, UNIV_PAGE_SIZE);
- *flags = fsp_header_get_flags(page);
-
- *space_id = fsp_header_get_space_id(page);
-
- flushed_lsn = mach_read_from_8(page + FIL_PAGE_FILE_FLUSH_LSN);
-
+ /* The FSP_HEADER on page 0 is only valid for the first file
+ in a tablespace. So if this is not the first datafile, leave
+ *flags and *space_id as they were read from the first file and
+ do not validate the first page. */
if (!one_read_already) {
+ *flags = fsp_header_get_flags(page);
+ *space_id = fsp_header_get_space_id(page);
+
check_msg = fil_check_first_page(page);
}
+ flushed_lsn = mach_read_from_8(page + FIL_PAGE_FILE_FLUSH_LSN);
+
ut_free(buf);
if (check_msg) {
@@ -2299,13 +2302,13 @@ exists and the space id in it matches. Replays the create operation if a file
at that path does not exist yet. If the database directory for the file to be
created does not exist, then we create the directory, too.
-Note that ibbackup --apply-log sets fil_path_to_mysql_datadir to point to the
-datadir that we should use in replaying the file operations.
+Note that mysqlbackup --apply-log sets fil_path_to_mysql_datadir to point to
+the datadir that we should use in replaying the file operations.
InnoDB recovery does not replay these fully since it always sets the space id
-to zero. But ibbackup does replay them. TODO: If remote tablespaces are used,
-ibbackup will only create tables in the default directory since MLOG_FILE_CREATE
-and MLOG_FILE_CREATE2 only know the tablename, not the path.
+to zero. But mysqlbackup does replay them. TODO: If remote tablespaces are
+used, mysqlbackup will only create tables in the default directory since
+MLOG_FILE_CREATE and MLOG_FILE_CREATE2 only know the tablename, not the path.
@return end of log record, or NULL if the record was not completely
contained between ptr and end_ptr */
@@ -2397,11 +2400,11 @@ fil_op_log_parse_or_replay(
}
/* Let us try to perform the file operation, if sensible. Note that
- ibbackup has at this stage already read in all space id info to the
+ mysqlbackup has at this stage already read in all space id info to the
fil0fil.cc data structures.
NOTE that our algorithm is not guaranteed to work correctly if there
- were renames of tables during the backup. See ibbackup code for more
+ were renames of tables during the backup. See mysqlbackup code for more
on the problem. */
switch (type) {
@@ -2816,12 +2819,12 @@ fil_delete_tablespace(
if (err == DB_SUCCESS) {
#ifndef UNIV_HOTBACKUP
/* Write a log record about the deletion of the .ibd
- file, so that ibbackup can replay it in the
+ file, so that mysqlbackup can replay it in the
--apply-log phase. We use a dummy mtr and the familiar
log write mechanism. */
mtr_t mtr;
- /* When replaying the operation in ibbackup, do not try
+ /* When replaying the operation in mysqlbackup, do not try
to write any log record */
mtr_start(&mtr);
@@ -4483,7 +4486,7 @@ will_not_choose:
" (< 4 pages 16 kB each),\n"
"InnoDB: or the space id in the file header"
" is not sensible.\n"
- "InnoDB: This can happen in an ibbackup run,"
+ "InnoDB: This can happen in an mysqlbackup run,"
" and is not dangerous.\n",
fsp->filepath, fsp->id, fsp->filepath, size);
os_file_close(fsp->file);
@@ -4520,7 +4523,7 @@ will_not_choose:
"InnoDB: because space %s with the same id\n"
"InnoDB: was scanned earlier. This can happen"
" if you have renamed tables\n"
- "InnoDB: during an ibbackup run.\n",
+ "InnoDB: during an mysqlbackup run.\n",
fsp->filepath, fsp->id, fsp->filepath,
space->name);
os_file_close(fsp->file);
@@ -5233,9 +5236,9 @@ file_extended:
#ifdef UNIV_HOTBACKUP
/********************************************************************//**
Extends all tablespaces to the size stored in the space header. During the
-ibbackup --apply-log phase we extended the spaces on-demand so that log records
-could be applied, but that may have left spaces still too small compared to
-the size stored in the space header. */
+mysqlbackup --apply-log phase we extended the spaces on-demand so that log
+records could be applied, but that may have left spaces still too small
+compared to the size stored in the space header. */
UNIV_INTERN
void
fil_extend_tablespaces_to_stored_len(void)
@@ -5764,7 +5767,7 @@ _fil_io(
offset, len, node, message, space_id, trx);
#else
- /* In ibbackup do normal i/o, not aio */
+ /* In mysqlbackup do normal i/o, not aio */
if (type == OS_FILE_READ) {
ret = os_file_read(node->handle, buf, offset, len);
} else {
diff --git a/storage/xtradb/fts/fts0ast.cc b/storage/xtradb/fts/fts0ast.cc
index d6c19c0050a..dd48ffee14d 100644
--- a/storage/xtradb/fts/fts0ast.cc
+++ b/storage/xtradb/fts/fts0ast.cc
@@ -1,6 +1,6 @@
/*****************************************************************************
-Copyright (c) 2007, 2013, Oracle and/or its affiliates. All Rights Reserved.
+Copyright (c) 2007, 2014, Oracle and/or its affiliates. All Rights Reserved.
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
@@ -83,11 +83,11 @@ UNIV_INTERN
fts_ast_node_t*
fts_ast_create_node_term(
/*=====================*/
- void* arg, /*!< in: ast state instance */
- const char* ptr) /*!< in: ast term string */
+ void* arg, /*!< in: ast state instance */
+ const fts_ast_string_t* ptr) /*!< in: ast term string */
{
fts_ast_state_t* state = static_cast<fts_ast_state_t*>(arg);
- ulint len = strlen(ptr);
+ ulint len = ptr->len;
ulint cur_pos = 0;
fts_ast_node_t* node = NULL;
fts_ast_node_t* node_list = NULL;
@@ -101,8 +101,9 @@ fts_ast_create_node_term(
cur_len = innobase_mysql_fts_get_token(
state->charset,
- reinterpret_cast<const byte*>(ptr) + cur_pos,
- reinterpret_cast<const byte*>(ptr) + len, &str, &offset);
+ reinterpret_cast<const byte*>(ptr->str) + cur_pos,
+ reinterpret_cast<const byte*>(ptr->str) + len,
+ &str, &offset);
if (cur_len == 0) {
break;
@@ -124,10 +125,8 @@ fts_ast_create_node_term(
node->type = FTS_AST_TERM;
- node->term.ptr = static_cast<byte*>(ut_malloc(
- str.f_len + 1));
- memcpy(node->term.ptr, str.f_str, str.f_len);
- node->term.ptr[str.f_len] = '\0';
+ node->term.ptr = fts_ast_string_create(
+ str.f_str, str.f_len);
fts_ast_state_add_node(
static_cast<fts_ast_state_t*>(arg), node);
@@ -160,25 +159,21 @@ UNIV_INTERN
fts_ast_node_t*
fts_ast_create_node_text(
/*=====================*/
- void* arg, /*!< in: ast state instance */
- const char* ptr) /*!< in: ast text string */
+ void* arg, /*!< in: ast state instance */
+ const fts_ast_string_t* ptr) /*!< in: ast text string */
{
- ulint len = strlen(ptr);
+ ulint len = ptr->len;
fts_ast_node_t* node = NULL;
+ /* Once we come here, the string must have at least 2 quotes ""
+ around the query string, which could be empty. Also the query
+ string may contain 0x00 in it, we don't treat it as null-terminated. */
+ ut_ad(len >= 2);
+ ut_ad(ptr->str[0] == '\"' && ptr->str[len - 1] == '\"');
- ut_ad(len >= 1);
-
- if (len <= 2) {
- /* There is a way to directly supply null terminator
- in the query string (by using 0x220022) and get here,
- and certainly it would not make a valid query text */
- ut_ad(ptr[0] == '\"');
-
- if (len == 2) {
- ut_ad(ptr[1] == '\"');
- }
-
+ if (len == 2) {
+ /* If the query string contains nothing except quotes,
+ it's obviously an invalid query. */
return(NULL);
}
@@ -188,11 +183,9 @@ fts_ast_create_node_text(
len -= 2;
node->type = FTS_AST_TEXT;
- node->text.ptr = static_cast<byte*>(ut_malloc(len + 1));
-
/*!< Skip copying the first quote */
- memcpy(node->text.ptr, ptr + 1, len);
- node->text.ptr[len] = 0;
+ node->text.ptr = fts_ast_string_create(
+ reinterpret_cast<const byte*>(ptr->str + 1), len);
node->text.distance = ULINT_UNDEFINED;
fts_ast_state_add_node((fts_ast_state_t*) arg, node);
@@ -275,14 +268,14 @@ fts_ast_free_node(
switch (node->type) {
case FTS_AST_TEXT:
if (node->text.ptr) {
- ut_free(node->text.ptr);
+ fts_ast_string_free(node->text.ptr);
node->text.ptr = NULL;
}
break;
case FTS_AST_TERM:
if (node->term.ptr) {
- ut_free(node->term.ptr);
+ fts_ast_string_free(node->term.ptr);
node->term.ptr = NULL;
}
break;
@@ -421,10 +414,10 @@ fts_ast_state_free(
fts_ast_node_t* next = node->next_alloc;
if (node->type == FTS_AST_TEXT && node->text.ptr) {
- ut_free(node->text.ptr);
+ fts_ast_string_free(node->text.ptr);
node->text.ptr = NULL;
} else if (node->type == FTS_AST_TERM && node->term.ptr) {
- ut_free(node->term.ptr);
+ fts_ast_string_free(node->term.ptr);
node->term.ptr = NULL;
}
@@ -445,11 +438,13 @@ fts_ast_node_print(
{
switch (node->type) {
case FTS_AST_TEXT:
- printf("TEXT: %s\n", node->text.ptr);
+ printf("TEXT: ");
+ fts_ast_string_print(node->text.ptr);
break;
case FTS_AST_TERM:
- printf("TERM: %s\n", node->term.ptr);
+ printf("TERM: ");
+ fts_ast_string_print(node->term.ptr);
break;
case FTS_AST_LIST:
@@ -628,3 +623,74 @@ fts_ast_visit(
return(error);
}
+
+/**
+Create an ast string object, with NUL-terminator, so the string
+has one more byte than len
+@param[in] str pointer to string
+@param[in] len length of the string
+@return ast string with NUL-terminator */
+UNIV_INTERN
+fts_ast_string_t*
+fts_ast_string_create(
+ const byte* str,
+ ulint len)
+{
+ fts_ast_string_t* ast_str;
+
+ ut_ad(len > 0);
+
+ ast_str = static_cast<fts_ast_string_t*>
+ (ut_malloc(sizeof(fts_ast_string_t)));
+ ast_str->str = static_cast<byte*>(ut_malloc(len + 1));
+
+ ast_str->len = len;
+ memcpy(ast_str->str, str, len);
+ ast_str->str[len] = '\0';
+
+ return(ast_str);
+}
+
+/**
+Free an ast string instance
+@param[in,out] ast_str string to free */
+UNIV_INTERN
+void
+fts_ast_string_free(
+ fts_ast_string_t* ast_str)
+{
+ if (ast_str != NULL) {
+ ut_free(ast_str->str);
+ ut_free(ast_str);
+ }
+}
+
+/**
+Translate ast string of type FTS_AST_NUMB to unsigned long by strtoul
+@param[in] str string to translate
+@param[in] base the base
+@return translated number */
+UNIV_INTERN
+ulint
+fts_ast_string_to_ul(
+ const fts_ast_string_t* ast_str,
+ int base)
+{
+ return(strtoul(reinterpret_cast<const char*>(ast_str->str),
+ NULL, base));
+}
+
+/**
+Print the ast string
+@param[in] str string to print */
+UNIV_INTERN
+void
+fts_ast_string_print(
+ const fts_ast_string_t* ast_str)
+{
+ for (ulint i = 0; i < ast_str->len; ++i) {
+ printf("%c", ast_str->str[i]);
+ }
+
+ printf("\n");
+}
diff --git a/storage/xtradb/fts/fts0blex.cc b/storage/xtradb/fts/fts0blex.cc
index f83523825d2..7d0acb00a3b 100644
--- a/storage/xtradb/fts/fts0blex.cc
+++ b/storage/xtradb/fts/fts0blex.cc
@@ -451,7 +451,7 @@ static yyconst flex_int16_t yy_chk[32] =
#line 1 "fts0blex.l"
/*****************************************************************************
-Copyright (c) 2007, 2011, Oracle and/or its affiliates. All Rights Reserved.
+Copyright (c) 2007, 2014, Oracle and/or its affiliates. All Rights Reserved.
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
@@ -806,7 +806,7 @@ case 3:
YY_RULE_SETUP
#line 53 "fts0blex.l"
{
- val->token = strdup(fts0bget_text(yyscanner));
+ val->token = fts_ast_string_create(reinterpret_cast<const byte*>(fts0bget_text(yyscanner)), fts0bget_leng(yyscanner));
return(FTS_NUMB);
}
@@ -815,7 +815,7 @@ case 4:
YY_RULE_SETUP
#line 59 "fts0blex.l"
{
- val->token = strdup(fts0bget_text(yyscanner));
+ val->token = fts_ast_string_create(reinterpret_cast<const byte*>(fts0bget_text(yyscanner)), fts0bget_leng(yyscanner));
return(FTS_TERM);
}
@@ -824,7 +824,7 @@ case 5:
YY_RULE_SETUP
#line 65 "fts0blex.l"
{
- val->token = strdup(fts0bget_text(yyscanner));
+ val->token = fts_ast_string_create(reinterpret_cast<const byte*>(fts0bget_text(yyscanner)), fts0bget_leng(yyscanner));
return(FTS_TEXT);
}
diff --git a/storage/xtradb/fts/fts0blex.l b/storage/xtradb/fts/fts0blex.l
index 6193f0df187..ae6e8ffaa48 100644
--- a/storage/xtradb/fts/fts0blex.l
+++ b/storage/xtradb/fts/fts0blex.l
@@ -1,6 +1,6 @@
/*****************************************************************************
-Copyright (c) 2007, 2011, Oracle and/or its affiliates. All Rights Reserved.
+Copyright (c) 2007, 2014, Oracle and/or its affiliates. All Rights Reserved.
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
@@ -51,19 +51,19 @@ this program; if not, write to the Free Software Foundation, Inc.,
}
[0-9]+ {
- val->token = strdup(fts0bget_text(yyscanner));
+ val->token = fts_ast_string_create(reinterpret_cast<const byte*>(fts0bget_text(yyscanner)), fts0bget_leng(yyscanner));
return(FTS_NUMB);
}
[^" \n*()+\-<>~@%]* {
- val->token = strdup(fts0bget_text(yyscanner));
+ val->token = fts_ast_string_create(reinterpret_cast<const byte*>(fts0bget_text(yyscanner)), fts0bget_leng(yyscanner));
return(FTS_TERM);
}
\"[^\"\n]*\" {
- val->token = strdup(fts0bget_text(yyscanner));
+ val->token = fts_ast_string_create(reinterpret_cast<const byte*>(fts0bget_text(yyscanner)), fts0bget_leng(yyscanner));
return(FTS_TEXT);
}
diff --git a/storage/xtradb/fts/fts0fts.cc b/storage/xtradb/fts/fts0fts.cc
index a19df8b39da..8884e944dfd 100644
--- a/storage/xtradb/fts/fts0fts.cc
+++ b/storage/xtradb/fts/fts0fts.cc
@@ -608,8 +608,10 @@ fts_cache_init(
cache->total_size = 0;
+ mutex_enter((ib_mutex_t*) &cache->deleted_lock);
cache->deleted_doc_ids = ib_vector_create(
cache->sync_heap, sizeof(fts_update_t), 4);
+ mutex_exit((ib_mutex_t*) &cache->deleted_lock);
/* Reset the cache data for all the FTS indexes. */
for (i = 0; i < ib_vector_size(cache->indexes); ++i) {
@@ -1137,7 +1139,10 @@ fts_cache_clear(
cache->sync_heap->arg = NULL;
cache->total_size = 0;
+
+ mutex_enter((ib_mutex_t*) &cache->deleted_lock);
cache->deleted_doc_ids = NULL;
+ mutex_exit((ib_mutex_t*) &cache->deleted_lock);
}
/*********************************************************************//**
@@ -1954,10 +1959,15 @@ fts_create_one_index_table(
char* table_name = fts_get_table_name(fts_table);
dberr_t error;
CHARSET_INFO* charset;
+ ulint flags2 = 0;
ut_ad(index->type & DICT_FTS);
- new_table = dict_mem_table_create(table_name, 0, 5, 1, 0, false);
+ if (srv_file_per_table) {
+ flags2 = DICT_TF2_USE_TABLESPACE;
+ }
+
+ new_table = dict_mem_table_create(table_name, 0, 5, 1, flags2, false);
field = dict_index_get_nth_field(index, 0);
charset = innobase_get_fts_charset(
@@ -1986,7 +1996,7 @@ fts_create_one_index_table(
dict_mem_table_add_col(new_table, heap, "ilist", DATA_BLOB,
4130048, 0);
- error = row_create_table_for_mysql(new_table, trx, true);
+ error = row_create_table_for_mysql(new_table, trx, false);
if (error != DB_SUCCESS) {
trx->error_state = error;
@@ -2251,11 +2261,15 @@ static
fts_trx_t*
fts_trx_create(
/*===========*/
- trx_t* trx) /*!< in: InnoDB transaction */
+ trx_t* trx) /*!< in/out: InnoDB
+ transaction */
{
- fts_trx_t* ftt;
- ib_alloc_t* heap_alloc;
- mem_heap_t* heap = mem_heap_create(1024);
+ fts_trx_t* ftt;
+ ib_alloc_t* heap_alloc;
+ mem_heap_t* heap = mem_heap_create(1024);
+ trx_named_savept_t* savep;
+
+ ut_a(trx->fts_trx == NULL);
ftt = static_cast<fts_trx_t*>(mem_heap_alloc(heap, sizeof(fts_trx_t)));
ftt->trx = trx;
@@ -2273,6 +2287,14 @@ fts_trx_create(
fts_savepoint_create(ftt->savepoints, NULL, NULL);
fts_savepoint_create(ftt->last_stmt, NULL, NULL);
+ /* Copy savepoints that already set before. */
+ for (savep = UT_LIST_GET_FIRST(trx->trx_savepoints);
+ savep != NULL;
+ savep = UT_LIST_GET_NEXT(trx_savepoints, savep)) {
+
+ fts_savepoint_take(trx, ftt, savep->name);
+ }
+
return(ftt);
}
@@ -4366,6 +4388,7 @@ fts_sync_commit(
/* We need to do this within the deleted lock since fts_delete() can
attempt to add a deleted doc id to the cache deleted id array. */
fts_cache_clear(cache);
+ DEBUG_SYNC_C("fts_deleted_doc_ids_clear");
fts_cache_init(cache);
rw_lock_x_unlock(&cache->lock);
@@ -5167,6 +5190,12 @@ fts_cache_append_deleted_doc_ids(
mutex_enter((ib_mutex_t*) &cache->deleted_lock);
+ if (cache->deleted_doc_ids == NULL) {
+ mutex_exit((ib_mutex_t*) &cache->deleted_lock);
+ return;
+ }
+
+
for (i = 0; i < ib_vector_size(cache->deleted_doc_ids); ++i) {
fts_update_t* update;
@@ -5452,16 +5481,15 @@ void
fts_savepoint_take(
/*===============*/
trx_t* trx, /*!< in: transaction */
+ fts_trx_t* fts_trx, /*!< in: fts transaction */
const char* name) /*!< in: savepoint name */
{
mem_heap_t* heap;
- fts_trx_t* fts_trx;
fts_savepoint_t* savepoint;
fts_savepoint_t* last_savepoint;
ut_a(name != NULL);
- fts_trx = trx->fts_trx;
heap = fts_trx->heap;
/* The implied savepoint must exist. */
@@ -5778,7 +5806,7 @@ fts_savepoint_rollback(
ut_a(ib_vector_size(savepoints) > 0);
/* Restore the savepoint. */
- fts_savepoint_take(trx, name);
+ fts_savepoint_take(trx, trx->fts_trx, name);
}
}
diff --git a/storage/xtradb/fts/fts0pars.cc b/storage/xtradb/fts/fts0pars.cc
index 83d465b0988..7f0ba4e0c1b 100644
--- a/storage/xtradb/fts/fts0pars.cc
+++ b/storage/xtradb/fts/fts0pars.cc
@@ -100,6 +100,8 @@ extern int ftserror(const char* p);
#define YYPARSE_PARAM state
#define YYLEX_PARAM ((fts_ast_state_t*) state)->lexer
+#define YYTOKENFREE(token) fts_ast_string_free((token))
+
typedef int (*fts_scanner_alt)(YYSTYPE* val, yyscan_t yyscanner);
typedef int (*fts_scanner)();
@@ -154,9 +156,9 @@ typedef union YYSTYPE
/* Line 293 of yacc.c */
#line 61 "fts0pars.y"
- int oper;
- char* token;
- fts_ast_node_t* node;
+ int oper;
+ fts_ast_string_t* token;
+ fts_ast_node_t* node;
@@ -632,6 +634,19 @@ while (YYID (0))
#define YYTERROR 1
#define YYERRCODE 256
+#define YYERRCLEANUP \
+do \
+ switch (yylastchar) \
+ { \
+ case FTS_NUMB: \
+ case FTS_TEXT: \
+ case FTS_TERM: \
+ YYTOKENFREE(yylval.token); \
+ break; \
+ default: \
+ break; \
+ } \
+while (YYID (0))
/* YYLLOC_DEFAULT -- Set CURRENT to span from RHS[1] to RHS[N].
If N is 0, then set CURRENT to the empty location which ends
@@ -1169,6 +1184,8 @@ yyparse ()
{
/* The lookahead symbol. */
int yychar;
+/* The backup of yychar when there is an error and we're in yyerrlab. */
+int yylastchar;
/* The semantic value of the lookahead symbol. */
YYSTYPE yylval;
@@ -1524,8 +1541,8 @@ yyreduce:
/* Line 1806 of yacc.c */
#line 141 "fts0pars.y"
{
- fts_ast_term_set_distance((yyvsp[(1) - (3)].node), strtoul((yyvsp[(3) - (3)].token), NULL, 10));
- free((yyvsp[(3) - (3)].token));
+ fts_ast_term_set_distance((yyvsp[(1) - (3)].node), fts_ast_string_to_ul((yyvsp[(3) - (3)].token), 10));
+ fts_ast_string_free((yyvsp[(3) - (3)].token));
}
break;
@@ -1557,8 +1574,8 @@ yyreduce:
{
(yyval.node) = fts_ast_create_node_list(state, (yyvsp[(1) - (4)].node));
fts_ast_add_node((yyval.node), (yyvsp[(2) - (4)].node));
- fts_ast_term_set_distance((yyvsp[(2) - (4)].node), strtoul((yyvsp[(4) - (4)].token), NULL, 10));
- free((yyvsp[(4) - (4)].token));
+ fts_ast_term_set_distance((yyvsp[(2) - (4)].node), fts_ast_string_to_ul((yyvsp[(4) - (4)].token), 10));
+ fts_ast_string_free((yyvsp[(4) - (4)].token));
}
break;
@@ -1623,7 +1640,7 @@ yyreduce:
#line 191 "fts0pars.y"
{
(yyval.node) = fts_ast_create_node_term(state, (yyvsp[(1) - (1)].token));
- free((yyvsp[(1) - (1)].token));
+ fts_ast_string_free((yyvsp[(1) - (1)].token));
}
break;
@@ -1633,7 +1650,7 @@ yyreduce:
#line 196 "fts0pars.y"
{
(yyval.node) = fts_ast_create_node_term(state, (yyvsp[(1) - (1)].token));
- free((yyvsp[(1) - (1)].token));
+ fts_ast_string_free((yyvsp[(1) - (1)].token));
}
break;
@@ -1652,7 +1669,7 @@ yyreduce:
#line 207 "fts0pars.y"
{
(yyval.node) = fts_ast_create_node_text(state, (yyvsp[(1) - (1)].token));
- free((yyvsp[(1) - (1)].token));
+ fts_ast_string_free((yyvsp[(1) - (1)].token));
}
break;
@@ -1700,6 +1717,8 @@ yyreduce:
| yyerrlab -- here on detecting error |
`------------------------------------*/
yyerrlab:
+ /* Backup yychar, in case we would change it. */
+ yylastchar = yychar;
/* Make sure we have latest lookahead translation. See comments at
user semantic actions for why this is necessary. */
yytoken = yychar == YYEMPTY ? YYEMPTY : YYTRANSLATE (yychar);
@@ -1755,7 +1774,11 @@ yyerrlab:
{
/* Return failure if at end of input. */
if (yychar == YYEOF)
- YYABORT;
+ {
+ /* Since we don't need the token, we have to free it first. */
+ YYERRCLEANUP;
+ YYABORT;
+ }
}
else
{
@@ -1812,7 +1835,11 @@ yyerrlab1:
/* Pop the current state because it cannot handle the error token. */
if (yyssp == yyss)
- YYABORT;
+ {
+ /* Since we don't need the error token, we have to free it first. */
+ YYERRCLEANUP;
+ YYABORT;
+ }
yydestruct ("Error: popping",
diff --git a/storage/xtradb/fts/fts0pars.y b/storage/xtradb/fts/fts0pars.y
index ff22e9a9873..e48036e82fe 100644
--- a/storage/xtradb/fts/fts0pars.y
+++ b/storage/xtradb/fts/fts0pars.y
@@ -1,6 +1,6 @@
/*****************************************************************************
-Copyright (c) 2007, 2013, Oracle and/or its affiliates. All Rights Reserved.
+Copyright (c) 2007, 2014, Oracle and/or its affiliates. All Rights Reserved.
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
@@ -59,9 +59,9 @@ struct fts_lexer_struct {
%}
%union {
- int oper;
- char* token;
- fts_ast_node_t* node;
+ int oper;
+ fts_ast_string_t* token;
+ fts_ast_node_t* node;
};
/* Enable re-entrant parser */
@@ -139,8 +139,8 @@ expr : term {
}
| text '@' FTS_NUMB {
- fts_ast_term_set_distance($1, strtoul($3, NULL, 10));
- free($3);
+ fts_ast_term_set_distance($1, fts_ast_string_to_ul($3, 10));
+ fts_ast_string_free($3);
}
| prefix term '*' {
@@ -157,8 +157,8 @@ expr : term {
| prefix text '@' FTS_NUMB {
$$ = fts_ast_create_node_list(state, $1);
fts_ast_add_node($$, $2);
- fts_ast_term_set_distance($2, strtoul($4, NULL, 10));
- free($4);
+ fts_ast_term_set_distance($2, fts_ast_string_to_ul($4, 10));
+ fts_ast_string_free($4);
}
| prefix text {
@@ -190,12 +190,12 @@ prefix : '-' {
term : FTS_TERM {
$$ = fts_ast_create_node_term(state, $1);
- free($1);
+ fts_ast_string_free($1);
}
| FTS_NUMB {
$$ = fts_ast_create_node_term(state, $1);
- free($1);
+ fts_ast_string_free($1);
}
/* Ignore leading '*' */
@@ -206,7 +206,7 @@ term : FTS_TERM {
text : FTS_TEXT {
$$ = fts_ast_create_node_text(state, $1);
- free($1);
+ fts_ast_string_free($1);
}
;
%%
diff --git a/storage/xtradb/fts/fts0que.cc b/storage/xtradb/fts/fts0que.cc
index c5c5f954789..beeb31abb9e 100644
--- a/storage/xtradb/fts/fts0que.cc
+++ b/storage/xtradb/fts/fts0que.cc
@@ -1,6 +1,6 @@
/*****************************************************************************
-Copyright (c) 2007, 2013, Oracle and/or its affiliates. All Rights Reserved.
+Copyright (c) 2007, 2014, Oracle and/or its affiliates. All Rights Reserved.
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
@@ -2800,20 +2800,19 @@ fts_query_get_token(
ulint str_len;
byte* new_ptr = NULL;
- str_len = ut_strlen((char*) node->term.ptr);
+ str_len = node->term.ptr->len;
ut_a(node->type == FTS_AST_TERM);
token->f_len = str_len;
- token->f_str = node->term.ptr;
+ token->f_str = node->term.ptr->str;
if (node->term.wildcard) {
token->f_str = static_cast<byte*>(ut_malloc(str_len + 2));
token->f_len = str_len + 1;
- /* Need to copy the NUL character too. */
- memcpy(token->f_str, node->term.ptr, str_len + 1);
+ memcpy(token->f_str, node->term.ptr->str, str_len);
token->f_str[str_len] = '%';
token->f_str[token->f_len] = 0;
@@ -2848,8 +2847,8 @@ fts_query_visitor(
switch (node->type) {
case FTS_AST_TEXT:
- token.f_str = node->text.ptr;
- token.f_len = ut_strlen((char*) token.f_str);
+ token.f_str = node->text.ptr->str;
+ token.f_len = node->text.ptr->len;
if (query->oper == FTS_EXIST) {
ut_ad(query->intersection == NULL);
@@ -2878,8 +2877,8 @@ fts_query_visitor(
break;
case FTS_AST_TERM:
- token.f_str = node->term.ptr;
- token.f_len = ut_strlen(reinterpret_cast<char*>(token.f_str));
+ token.f_str = node->term.ptr->str;
+ token.f_len = node->term.ptr->len;
/* Add the word to our RB tree that will be used to
calculate this terms per document frequency. */
@@ -3191,13 +3190,9 @@ fts_query_read_node(
to assign the frequency on search string behalf. */
if (query->cur_node->type == FTS_AST_TERM
&& query->cur_node->term.wildcard) {
-
- /* These cast are safe since we only care about the
- terminating NUL character as an end of string marker. */
- term.f_len = ut_strlen(reinterpret_cast<char*>
- (query->cur_node->term.ptr));
+ term.f_len = query->cur_node->term.ptr->len;
ut_ad(FTS_MAX_WORD_LEN >= term.f_len);
- memcpy(term.f_str, query->cur_node->term.ptr, term.f_len);
+ memcpy(term.f_str, query->cur_node->term.ptr->str, term.f_len);
} else {
term.f_len = word->f_len;
ut_ad(FTS_MAX_WORD_LEN >= word->f_len);
@@ -3507,14 +3502,15 @@ fts_query_prepare_result(
doc_freq = rbt_value(fts_doc_freq_t, node);
/* Don't put deleted docs into result */
- if (fts_bsearch(array, 0, static_cast<int>(size), doc_freq->doc_id)
- >= 0) {
+ if (fts_bsearch(array, 0, static_cast<int>(size),
+ doc_freq->doc_id) >= 0) {
+ /* one less matching doc count */
+ --word_freq->doc_count;
continue;
}
ranking.doc_id = doc_freq->doc_id;
- ranking.rank = static_cast<fts_rank_t>(
- doc_freq->freq * word_freq->idf * word_freq->idf);
+ ranking.rank = static_cast<fts_rank_t>(doc_freq->freq);
ranking.words = NULL;
fts_query_add_ranking(query, result->rankings_by_id,
@@ -3527,6 +3523,25 @@ fts_query_prepare_result(
}
}
+ /* Calculate IDF only after we exclude the deleted items */
+ fts_query_calculate_idf(query);
+
+ node = rbt_first(query->word_freqs);
+ word_freq = rbt_value(fts_word_freq_t, node);
+
+ /* Calculate the ranking for each doc */
+ for (node = rbt_first(result->rankings_by_id);
+ node != NULL;
+ node = rbt_next(result->rankings_by_id, node)) {
+
+ fts_ranking_t* ranking;
+
+ ranking = rbt_value(fts_ranking_t, node);
+
+ ranking->rank = static_cast<fts_rank_t>(
+ ranking->rank * word_freq->idf * word_freq->idf);
+ }
+
return(result);
}
@@ -3898,6 +3913,7 @@ fts_query(
/* Get the deleted doc ids that are in the cache. */
fts_cache_append_deleted_doc_ids(
index->table->fts->cache, query.deleted->doc_ids);
+ DEBUG_SYNC_C("fts_deleted_doc_ids_append");
/* Sort the vector so that we can do a binary search over the ids. */
ib_vector_sort(query.deleted->doc_ids, fts_update_doc_id_cmp);
@@ -3954,7 +3970,8 @@ fts_query(
}
/* Calculate the inverse document frequency of the terms. */
- if (query.error == DB_SUCCESS) {
+ if (query.error == DB_SUCCESS
+ && query.flags != FTS_OPT_RANKING) {
fts_query_calculate_idf(&query);
}
diff --git a/storage/xtradb/fts/fts0tlex.cc b/storage/xtradb/fts/fts0tlex.cc
index ef17ab1acf2..b744fbf0763 100644
--- a/storage/xtradb/fts/fts0tlex.cc
+++ b/storage/xtradb/fts/fts0tlex.cc
@@ -447,7 +447,7 @@ static yyconst flex_int16_t yy_chk[29] =
#line 1 "fts0tlex.l"
/*****************************************************************************
-Copyright (c) 2007, 2011, Oracle and/or its affiliates. All Rights Reserved.
+Copyright (c) 2007, 2014, Oracle and/or its affiliates. All Rights Reserved.
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
@@ -802,7 +802,7 @@ case 3:
YY_RULE_SETUP
#line 54 "fts0tlex.l"
{
- val->token = strdup(fts0tget_text(yyscanner));
+ val->token = fts_ast_string_create(reinterpret_cast<const byte*>(fts0tget_text(yyscanner)), fts0tget_leng(yyscanner));
return(FTS_TEXT);
}
@@ -811,7 +811,7 @@ case 4:
YY_RULE_SETUP
#line 60 "fts0tlex.l"
{
- val->token = strdup(fts0tget_text(yyscanner));
+ val->token = fts_ast_string_create(reinterpret_cast<const byte*>(fts0tget_text(yyscanner)), fts0tget_leng(yyscanner));
return(FTS_TERM);
}
diff --git a/storage/xtradb/fts/fts0tlex.l b/storage/xtradb/fts/fts0tlex.l
index a18c2a55081..4f55a83afe5 100644
--- a/storage/xtradb/fts/fts0tlex.l
+++ b/storage/xtradb/fts/fts0tlex.l
@@ -1,6 +1,6 @@
/*****************************************************************************
-Copyright (c) 2007, 2011, Oracle and/or its affiliates. All Rights Reserved.
+Copyright (c) 2007, 2014, Oracle and/or its affiliates. All Rights Reserved.
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
@@ -52,13 +52,13 @@ this program; if not, write to the Free Software Foundation, Inc.,
}
\"[^\"\n]*\" {
- val->token = strdup(fts0tget_text(yyscanner));
+ val->token = fts_ast_string_create(reinterpret_cast<const byte*>(fts0tget_text(yyscanner)), fts0tget_leng(yyscanner));
return(FTS_TEXT);
}
[^" \n\%]* {
- val->token = strdup(fts0tget_text(yyscanner));
+ val->token = fts_ast_string_create(reinterpret_cast<const byte*>(fts0tget_text(yyscanner)), fts0tget_leng(yyscanner));
return(FTS_TERM);
}
diff --git a/storage/xtradb/handler/ha_innodb.cc b/storage/xtradb/handler/ha_innodb.cc
index f78be55fa5f..73ef14a1271 100644
--- a/storage/xtradb/handler/ha_innodb.cc
+++ b/storage/xtradb/handler/ha_innodb.cc
@@ -4111,7 +4111,7 @@ innobase_commit_ordered_2(
{
DBUG_ENTER("innobase_commit_ordered_2");
- /* We need current binlog position for ibbackup to work. */
+ /* We need current binlog position for mysqlbackup to work. */
retry:
if (innobase_commit_concurrency > 0) {
mysql_mutex_lock(&commit_cond_m);
@@ -4743,6 +4743,7 @@ innobase_release_savepoint(
DBUG_ASSERT(hton == innodb_hton_ptr);
trx = check_trx_exists(thd);
+ trx_start_if_not_started(trx);
/* TODO: use provided savepoint data area to store savepoint data */
@@ -4798,7 +4799,7 @@ innobase_savepoint(
error = trx_savepoint_for_mysql(trx, name, (ib_int64_t)0);
if (error == DB_SUCCESS && trx->fts_trx != NULL) {
- fts_savepoint_take(trx, name);
+ fts_savepoint_take(trx, trx->fts_trx, name);
}
DBUG_RETURN(convert_error_code_to_mysql(error, 0, NULL));
@@ -12778,16 +12779,6 @@ ha_innobase::get_memory_buffer_size() const
return(innobase_buffer_pool_size);
}
-UNIV_INTERN
-bool
-ha_innobase::is_corrupt() const
-{
- if (share->ib_table)
- return ((bool)share->ib_table->is_corrupt);
- else
- return (FALSE);
-}
-
/*********************************************************************//**
Calculates the key number used inside MySQL for an Innobase index. We will
first check the "index translation table" for a match of the index to get
@@ -13966,9 +13957,13 @@ ha_innobase::get_foreign_key_list(
mutex_enter(&(dict_sys->mutex));
- for (foreign = UT_LIST_GET_FIRST(prebuilt->table->foreign_list);
- foreign != NULL;
- foreign = UT_LIST_GET_NEXT(foreign_list, foreign)) {
+ for (dict_foreign_set::iterator it
+ = prebuilt->table->foreign_set.begin();
+ it != prebuilt->table->foreign_set.end();
+ ++it) {
+
+ foreign = *it;
+
pf_key_info = get_foreign_key_info(thd, foreign);
if (pf_key_info) {
f_key_list->push_back(pf_key_info);
@@ -14004,9 +13999,13 @@ ha_innobase::get_parent_foreign_key_list(
mutex_enter(&(dict_sys->mutex));
- for (foreign = UT_LIST_GET_FIRST(prebuilt->table->referenced_list);
- foreign != NULL;
- foreign = UT_LIST_GET_NEXT(referenced_list, foreign)) {
+ for (dict_foreign_set::iterator it
+ = prebuilt->table->referenced_set.begin();
+ it != prebuilt->table->referenced_set.end();
+ ++it) {
+
+ foreign = *it;
+
pf_key_info = get_foreign_key_info(thd, foreign);
if (pf_key_info) {
f_key_list->push_back(pf_key_info);
@@ -14039,8 +14038,8 @@ ha_innobase::can_switch_engines(void)
"determining if there are foreign key constraints";
row_mysql_freeze_data_dictionary(prebuilt->trx);
- can_switch = !UT_LIST_GET_FIRST(prebuilt->table->referenced_list)
- && !UT_LIST_GET_FIRST(prebuilt->table->foreign_list);
+ can_switch = prebuilt->table->referenced_set.empty()
+ && prebuilt->table->foreign_set.empty();
row_mysql_unfreeze_data_dictionary(prebuilt->trx);
prebuilt->trx->op_info = "";
@@ -15868,7 +15867,7 @@ innobase_xa_prepare(
|| !thd_test_options(
thd, OPTION_NOT_AUTOCOMMIT | OPTION_BEGIN))) {
- /* For ibbackup to work the order of transactions in binlog
+ /* For mysqlbackup to work the order of transactions in binlog
and InnoDB must be the same. Consider the situation
thread1> prepare; write to binlog; ...
diff --git a/storage/xtradb/handler/ha_innodb.h b/storage/xtradb/handler/ha_innodb.h
index 103b72dd4f9..46dc6d60129 100644
--- a/storage/xtradb/handler/ha_innodb.h
+++ b/storage/xtradb/handler/ha_innodb.h
@@ -133,7 +133,6 @@ class ha_innobase: public handler
double read_time(uint index, uint ranges, ha_rows rows);
longlong get_memory_buffer_size() const;
my_bool is_fake_change_enabled(THD *thd);
- bool is_corrupt() const;
int write_row(uchar * buf);
int update_row(const uchar * old_data, uchar * new_data);
diff --git a/storage/xtradb/handler/handler0alter.cc b/storage/xtradb/handler/handler0alter.cc
index 85b98f19ae0..cd4d107b32a 100644
--- a/storage/xtradb/handler/handler0alter.cc
+++ b/storage/xtradb/handler/handler0alter.cc
@@ -595,15 +595,9 @@ innobase_init_foreign(
/* Check if any existing foreign key has the same id,
this is needed only if user supplies the constraint name */
- for (const dict_foreign_t* existing_foreign
- = UT_LIST_GET_FIRST(table->foreign_list);
- existing_foreign != 0;
- existing_foreign = UT_LIST_GET_NEXT(
- foreign_list, existing_foreign)) {
-
- if (ut_strcmp(existing_foreign->id, foreign->id) == 0) {
- return(false);
- }
+ if (table->foreign_set.find(foreign)
+ != table->foreign_set.end()) {
+ return(false);
}
}
@@ -2241,14 +2235,18 @@ innobase_check_foreigns_low(
const char* col_name,
bool drop)
{
+ dict_foreign_t* foreign;
ut_ad(mutex_own(&dict_sys->mutex));
/* Check if any FOREIGN KEY constraints are defined on this
column. */
- for (const dict_foreign_t* foreign = UT_LIST_GET_FIRST(
- user_table->foreign_list);
- foreign;
- foreign = UT_LIST_GET_NEXT(foreign_list, foreign)) {
+
+ for (dict_foreign_set::iterator it = user_table->foreign_set.begin();
+ it != user_table->foreign_set.end();
+ ++it) {
+
+ foreign = *it;
+
if (!drop && !(foreign->type
& (DICT_FOREIGN_ON_DELETE_SET_NULL
| DICT_FOREIGN_ON_UPDATE_SET_NULL))) {
@@ -2280,10 +2278,13 @@ innobase_check_foreigns_low(
/* Check if any FOREIGN KEY constraints in other tables are
referring to the column that is being dropped. */
- for (const dict_foreign_t* foreign = UT_LIST_GET_FIRST(
- user_table->referenced_list);
- foreign;
- foreign = UT_LIST_GET_NEXT(referenced_list, foreign)) {
+ for (dict_foreign_set::iterator it
+ = user_table->referenced_set.begin();
+ it != user_table->referenced_set.end();
+ ++it) {
+
+ foreign = *it;
+
if (innobase_dropping_foreign(foreign, drop_fk, n_drop_fk)) {
continue;
}
@@ -3618,11 +3619,12 @@ check_if_ok_to_rename:
continue;
}
- for (dict_foreign_t* foreign = UT_LIST_GET_FIRST(
- prebuilt->table->foreign_list);
- foreign != NULL;
- foreign = UT_LIST_GET_NEXT(
- foreign_list, foreign)) {
+ for (dict_foreign_set::iterator it
+ = prebuilt->table->foreign_set.begin();
+ it != prebuilt->table->foreign_set.end();
+ ++it) {
+
+ dict_foreign_t* foreign = *it;
const char* fid = strchr(foreign->id, '/');
DBUG_ASSERT(fid);
@@ -4463,10 +4465,12 @@ err_exit:
rename_foreign:
trx->op_info = "renaming column in SYS_FOREIGN_COLS";
- for (const dict_foreign_t* foreign = UT_LIST_GET_FIRST(
- user_table->foreign_list);
- foreign != NULL;
- foreign = UT_LIST_GET_NEXT(foreign_list, foreign)) {
+ for (dict_foreign_set::iterator it = user_table->foreign_set.begin();
+ it != user_table->foreign_set.end();
+ ++it) {
+
+ dict_foreign_t* foreign = *it;
+
for (unsigned i = 0; i < foreign->n_fields; i++) {
if (strcmp(foreign->foreign_col_names[i], from)) {
continue;
@@ -4496,10 +4500,12 @@ rename_foreign:
}
}
- for (const dict_foreign_t* foreign = UT_LIST_GET_FIRST(
- user_table->referenced_list);
- foreign != NULL;
- foreign = UT_LIST_GET_NEXT(referenced_list, foreign)) {
+ for (dict_foreign_set::iterator it
+ = user_table->referenced_set.begin();
+ it != user_table->referenced_set.end();
+ ++it) {
+
+ dict_foreign_t* foreign = *it;
for (unsigned i = 0; i < foreign->n_fields; i++) {
if (strcmp(foreign->referenced_col_names[i], from)) {
continue;
@@ -4823,8 +4829,8 @@ innobase_update_foreign_cache(
column names. No need to pass col_names or to drop
constraints from the data dictionary cache. */
DBUG_ASSERT(!ctx->col_names);
- DBUG_ASSERT(UT_LIST_GET_LEN(user_table->foreign_list) == 0);
- DBUG_ASSERT(UT_LIST_GET_LEN(user_table->referenced_list) == 0);
+ DBUG_ASSERT(user_table->foreign_set.empty());
+ DBUG_ASSERT(user_table->referenced_set.empty());
user_table = ctx->new_table;
} else {
/* Drop the foreign key constraints if the
diff --git a/storage/xtradb/handler/i_s.cc b/storage/xtradb/handler/i_s.cc
index 4a66065788f..69a75f5a4fe 100644
--- a/storage/xtradb/handler/i_s.cc
+++ b/storage/xtradb/handler/i_s.cc
@@ -8287,6 +8287,15 @@ i_s_innodb_changed_pages_fill(
limit_lsn_range_from_condition(table, cond, &min_lsn,
&max_lsn);
}
+
+ /* If the log tracker is running and our max_lsn > current tracked LSN,
+ cap the max lsn so that we don't try to read any partial runs as the
+ tracked LSN advances. */
+ if (srv_track_changed_pages) {
+ ib_uint64_t tracked_lsn = log_get_tracked_lsn();
+ if (max_lsn > tracked_lsn)
+ max_lsn = tracked_lsn;
+ }
if (!log_online_bitmap_iterator_init(&i, min_lsn, max_lsn)) {
my_error(ER_CANT_FIND_SYSTEM_REC, MYF(0));
diff --git a/storage/xtradb/include/buf0buf.h b/storage/xtradb/include/buf0buf.h
index 39b06b69924..0f77404b1de 100644
--- a/storage/xtradb/include/buf0buf.h
+++ b/storage/xtradb/include/buf0buf.h
@@ -272,6 +272,15 @@ buf_pool_get_oldest_modification(void);
/*==================================*/
/********************************************************************//**
+Gets the smallest oldest_modification lsn for any page in the pool. Returns
+zero if all modified pages have been flushed to disk.
+@return oldest modification in pool, zero if none */
+UNIV_INTERN
+lsn_t
+buf_pool_get_oldest_modification_peek(void);
+/*=======================================*/
+
+/********************************************************************//**
Allocates a buf_page_t descriptor. This function must succeed. In case
of failure we assert in this function. */
UNIV_INLINE
@@ -436,7 +445,7 @@ buf_page_create(
mtr_t* mtr); /*!< in: mini-transaction handle */
#else /* !UNIV_HOTBACKUP */
/********************************************************************//**
-Inits a page to the buffer buf_pool, for use in ibbackup --restore. */
+Inits a page to the buffer buf_pool, for use in mysqlbackup --restore. */
UNIV_INTERN
void
buf_page_init_for_backup_restore(
diff --git a/storage/xtradb/include/buf0buf.ic b/storage/xtradb/include/buf0buf.ic
index b0d8e03ecb9..10f0e02cb8f 100644
--- a/storage/xtradb/include/buf0buf.ic
+++ b/storage/xtradb/include/buf0buf.ic
@@ -1181,12 +1181,6 @@ buf_page_hash_get_low(
ut_a(buf_page_in_file(bpage));
ut_ad(bpage->in_page_hash);
ut_ad(!bpage->in_zip_hash);
-#if UNIV_WORD_SIZE == 4
- /* On 32-bit systems, there is no padding in
- buf_page_t. On other systems, Valgrind could complain
- about uninitialized pad bytes. */
- UNIV_MEM_ASSERT_RW(bpage, sizeof *bpage);
-#endif
}
return(bpage);
diff --git a/storage/xtradb/include/dict0crea.h b/storage/xtradb/include/dict0crea.h
index 6ec1079957b..67eab9058da 100644
--- a/storage/xtradb/include/dict0crea.h
+++ b/storage/xtradb/include/dict0crea.h
@@ -1,6 +1,6 @@
/*****************************************************************************
-Copyright (c) 1996, 2012, Oracle and/or its affiliates. All Rights Reserved.
+Copyright (c) 1996, 2014, Oracle and/or its affiliates. All Rights Reserved.
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
@@ -124,28 +124,24 @@ dict_create_add_foreign_id(
const char* name, /*!< in: table name */
dict_foreign_t* foreign)/*!< in/out: foreign key */
__attribute__((nonnull));
-/********************************************************************//**
-Adds foreign key definitions to data dictionary tables in the database. We
-look at table->foreign_list, and also generate names to constraints that were
-not named by the user. A generated constraint has a name of the format
-databasename/tablename_ibfk_NUMBER, where the numbers start from 1, and are
-given locally for this table, that is, the number is not global, as in the
-old format constraints < 4.0.18 it used to be.
-@return error code or DB_SUCCESS */
+
+/** Adds the given set of foreign key objects to the dictionary tables
+in the database. This function does not modify the dictionary cache. The
+caller must ensure that all foreign key objects contain a valid constraint
+name in foreign->id.
+@param[in] local_fk_set set of foreign key objects, to be added to
+the dictionary tables
+@param[in] table table to which the foreign key objects in
+local_fk_set belong to
+@param[in,out] trx transaction
+@return error code or DB_SUCCESS */
UNIV_INTERN
dberr_t
dict_create_add_foreigns_to_dictionary(
/*===================================*/
- ulint start_id,/*!< in: if we are actually doing ALTER TABLE
- ADD CONSTRAINT, we want to generate constraint
- numbers which are bigger than in the table so
- far; we number the constraints from
- start_id + 1 up; start_id should be set to 0 if
- we are creating a new table, or if the table
- so far has no constraints for which the name
- was generated here */
- dict_table_t* table, /*!< in: table */
- trx_t* trx) /*!< in: transaction */
+ const dict_foreign_set& local_fk_set,
+ const dict_table_t* table,
+ trx_t* trx)
__attribute__((nonnull, warn_unused_result));
/****************************************************************//**
Creates the tablespaces and datafiles system tables inside InnoDB
diff --git a/storage/xtradb/include/dict0mem.h b/storage/xtradb/include/dict0mem.h
index f6133e258c0..c6777154d36 100644
--- a/storage/xtradb/include/dict0mem.h
+++ b/storage/xtradb/include/dict0mem.h
@@ -50,6 +50,8 @@ Created 1/8/1996 Heikki Tuuri
#include "trx0types.h"
#include "fts0fts.h"
#include "os0once.h"
+#include <set>
+#include <algorithm>
/* Forward declaration. */
struct ib_rbt_t;
@@ -723,12 +725,106 @@ struct dict_foreign_t{
does not generate new indexes
implicitly */
dict_index_t* referenced_index;/*!< referenced index */
- UT_LIST_NODE_T(dict_foreign_t)
- foreign_list; /*!< list node for foreign keys of the
- table */
- UT_LIST_NODE_T(dict_foreign_t)
- referenced_list;/*!< list node for referenced
- keys of the table */
+};
+
+/** Compare two dict_foreign_t objects using their ids. Used in the ordering
+of dict_table_t::foreign_set and dict_table_t::referenced_set. It returns
+true if the first argument is considered to go before the second in the
+strict weak ordering it defines, and false otherwise. */
+struct dict_foreign_compare {
+
+ bool operator()(
+ const dict_foreign_t* lhs,
+ const dict_foreign_t* rhs) const
+ {
+ return(ut_strcmp(lhs->id, rhs->id) < 0);
+ }
+};
+
+/** A function object to find a foreign key with the given index as the
+referenced index. Return the foreign key with matching criteria or NULL */
+struct dict_foreign_with_index {
+
+ dict_foreign_with_index(const dict_index_t* index)
+ : m_index(index)
+ {}
+
+ bool operator()(const dict_foreign_t* foreign) const
+ {
+ return(foreign->referenced_index == m_index);
+ }
+
+ const dict_index_t* m_index;
+};
+
+/* A function object to check if the foreign constraint is between different
+tables. Returns true if foreign key constraint is between different tables,
+false otherwise. */
+struct dict_foreign_different_tables {
+
+ bool operator()(const dict_foreign_t* foreign) const
+ {
+ return(foreign->foreign_table != foreign->referenced_table);
+ }
+};
+
+/** A function object to check if the foreign key constraint has the same
+name as given. If the full name of the foreign key constraint doesn't match,
+then, check if removing the database name from the foreign key constraint
+matches. Return true if it matches, false otherwise. */
+struct dict_foreign_matches_id {
+
+ dict_foreign_matches_id(const char* id)
+ : m_id(id)
+ {}
+
+ bool operator()(const dict_foreign_t* foreign) const
+ {
+ if (0 == innobase_strcasecmp(foreign->id, m_id)) {
+ return(true);
+ }
+ if (const char* pos = strchr(foreign->id, '/')) {
+ if (0 == innobase_strcasecmp(m_id, pos + 1)) {
+ return(true);
+ }
+ }
+ return(false);
+ }
+
+ const char* m_id;
+};
+
+typedef std::set<dict_foreign_t*, dict_foreign_compare> dict_foreign_set;
+
+/*********************************************************************//**
+Frees a foreign key struct. */
+inline
+void
+dict_foreign_free(
+/*==============*/
+ dict_foreign_t* foreign) /*!< in, own: foreign key struct */
+{
+ mem_heap_free(foreign->heap);
+}
+
+/** The destructor will free all the foreign key constraints in the set
+by calling dict_foreign_free() on each of the foreign key constraints.
+This is used to free the allocated memory when a local set goes out
+of scope. */
+struct dict_foreign_set_free {
+
+ dict_foreign_set_free(const dict_foreign_set& foreign_set)
+ : m_foreign_set(foreign_set)
+ {}
+
+ ~dict_foreign_set_free()
+ {
+ std::for_each(m_foreign_set.begin(),
+ m_foreign_set.end(),
+ dict_foreign_free);
+ }
+
+ const dict_foreign_set& m_foreign_set;
};
/** The flags for ON_UPDATE and ON_DELETE can be ORed; the default is that
@@ -750,6 +846,8 @@ the table, DML from memcached will be blocked. */
/** Data structure for a database table. Most fields will be
initialized to 0, NULL or FALSE in dict_mem_table_create(). */
struct dict_table_t{
+
+
table_id_t id; /*!< id of the table */
mem_heap_t* heap; /*!< memory heap */
char* name; /*!< table name */
@@ -804,13 +902,16 @@ struct dict_table_t{
hash_node_t id_hash; /*!< hash chain node */
UT_LIST_BASE_NODE_T(dict_index_t)
indexes; /*!< list of indexes of the table */
- UT_LIST_BASE_NODE_T(dict_foreign_t)
- foreign_list;/*!< list of foreign key constraints
+
+ dict_foreign_set foreign_set;
+ /*!< set of foreign key constraints
in the table; these refer to columns
in other tables */
- UT_LIST_BASE_NODE_T(dict_foreign_t)
- referenced_list;/*!< list of foreign key constraints
+
+ dict_foreign_set referenced_set;
+ /*!< list of foreign key constraints
which refer to this table */
+
UT_LIST_NODE_T(dict_table_t)
table_LRU; /*!< node of the LRU list of tables */
unsigned fk_max_recusive_level:8;
@@ -1056,6 +1157,19 @@ struct dict_table_t{
#endif /* UNIV_DEBUG */
};
+/** A function object to add the foreign key constraint to the referenced set
+of the referenced table, if it exists in the dictionary cache. */
+struct dict_foreign_add_to_referenced_table {
+ void operator()(dict_foreign_t* foreign) const
+ {
+ if (dict_table_t* table = foreign->referenced_table) {
+ std::pair<dict_foreign_set::iterator, bool> ret
+ = table->referenced_set.insert(foreign);
+ ut_a(ret.second);
+ }
+ }
+};
+
#ifndef UNIV_NONINL
#include "dict0mem.ic"
#endif
diff --git a/storage/xtradb/include/fil0fil.h b/storage/xtradb/include/fil0fil.h
index f32dc1f699f..f7ff367484e 100644
--- a/storage/xtradb/include/fil0fil.h
+++ b/storage/xtradb/include/fil0fil.h
@@ -49,7 +49,7 @@ struct fil_space_t;
typedef std::list<const char*> space_name_list_t;
/** When mysqld is run, the default directory "." is the mysqld datadir,
-but in the MySQL Embedded Server Library and ibbackup it is not the default
+but in the MySQL Embedded Server Library and mysqlbackup it is not the default
directory, and we must set the base file path explicitly */
extern const char* fil_path_to_mysql_datadir;
@@ -426,8 +426,8 @@ exists and the space id in it matches. Replays the create operation if a file
at that path does not exist yet. If the database directory for the file to be
created does not exist, then we create the directory, too.
-Note that ibbackup --apply-log sets fil_path_to_mysql_datadir to point to the
-datadir that we should use in replaying the file operations.
+Note that mysqlbackup --apply-log sets fil_path_to_mysql_datadir to point to
+the datadir that we should use in replaying the file operations.
@return end of log record, or NULL if the record was not completely
contained between ptr and end_ptr */
UNIV_INTERN
@@ -680,9 +680,9 @@ fil_space_for_table_exists_in_mem(
#else /* !UNIV_HOTBACKUP */
/********************************************************************//**
Extends all tablespaces to the size stored in the space header. During the
-ibbackup --apply-log phase we extended the spaces on-demand so that log records
-could be appllied, but that may have left spaces still too small compared to
-the size stored in the space header. */
+mysqlbackup --apply-log phase we extended the spaces on-demand so that log
+records could be appllied, but that may have left spaces still too small
+compared to the size stored in the space header. */
UNIV_INTERN
void
fil_extend_tablespaces_to_stored_len(void);
diff --git a/storage/xtradb/include/fts0ast.h b/storage/xtradb/include/fts0ast.h
index c0aac6d8e4c..50ee587e282 100644
--- a/storage/xtradb/include/fts0ast.h
+++ b/storage/xtradb/include/fts0ast.h
@@ -1,6 +1,6 @@
/*****************************************************************************
-Copyright (c) 2007, 2013, Oracle and/or its affiliates. All Rights Reserved.
+Copyright (c) 2007, 2014, Oracle and/or its affiliates. All Rights Reserved.
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
@@ -76,6 +76,7 @@ enum fts_ast_oper_t {
struct fts_lexer_t;
struct fts_ast_node_t;
struct fts_ast_state_t;
+struct fts_ast_string_t;
typedef dberr_t (*fts_ast_callback)(fts_ast_oper_t, fts_ast_node_t*, void*);
@@ -101,16 +102,16 @@ extern
fts_ast_node_t*
fts_ast_create_node_term(
/*=====================*/
- void* arg, /*!< in: ast state */
- const char* ptr); /*!< in: term string */
+ void* arg, /*!< in: ast state */
+ const fts_ast_string_t* ptr); /*!< in: term string */
/********************************************************************
Create an AST text node */
extern
fts_ast_node_t*
fts_ast_create_node_text(
/*=====================*/
- void* arg, /*!< in: ast state */
- const char* ptr); /*!< in: text string */
+ void* arg, /*!< in: ast state */
+ const fts_ast_string_t* ptr); /*!< in: text string */
/********************************************************************
Create an AST expr list node */
extern
@@ -233,16 +234,66 @@ fts_lexer_free(
free */
__attribute__((nonnull));
+/**
+Create an ast string object, with NUL-terminator, so the string
+has one more byte than len
+@param[in] str pointer to string
+@param[in] len length of the string
+@return ast string with NUL-terminator */
+UNIV_INTERN
+fts_ast_string_t*
+fts_ast_string_create(
+ const byte* str,
+ ulint len);
+
+/**
+Free an ast string instance
+@param[in,out] ast_str string to free */
+UNIV_INTERN
+void
+fts_ast_string_free(
+ fts_ast_string_t* ast_str);
+
+/**
+Translate ast string of type FTS_AST_NUMB to unsigned long by strtoul
+@param[in] str string to translate
+@param[in] base the base
+@return translated number */
+UNIV_INTERN
+ulint
+fts_ast_string_to_ul(
+ const fts_ast_string_t* ast_str,
+ int base);
+
+/**
+Print the ast string
+@param[in] str string to print */
+UNIV_INTERN
+void
+fts_ast_string_print(
+ const fts_ast_string_t* ast_str);
+
+/* String of length len.
+We always store the string of length len with a terminating '\0',
+regardless of there is any 0x00 in the string itself */
+struct fts_ast_string_t {
+ /*!< Pointer to string. */
+ byte* str;
+
+ /*!< Length of the string. */
+ ulint len;
+};
+
/* Query term type */
struct fts_ast_term_t {
- byte* ptr; /*!< Pointer to term string.*/
- ibool wildcard; /*!< TRUE if wild card set.*/
+ fts_ast_string_t* ptr; /*!< Pointer to term string.*/
+ ibool wildcard; /*!< TRUE if wild card set.*/
};
/* Query text type */
struct fts_ast_text_t {
- byte* ptr; /*!< Pointer to term string.*/
- ulint distance; /*!< > 0 if proximity distance
+ fts_ast_string_t* ptr; /*!< Pointer to text string.*/
+ ulint distance; /*!< > 0 if proximity distance
set */
};
diff --git a/storage/xtradb/include/fts0fts.h b/storage/xtradb/include/fts0fts.h
index 5bea5bc0e97..a2996ecacc8 100644
--- a/storage/xtradb/include/fts0fts.h
+++ b/storage/xtradb/include/fts0fts.h
@@ -745,6 +745,7 @@ void
fts_savepoint_take(
/*===============*/
trx_t* trx, /*!< in: transaction */
+ fts_trx_t* fts_trx, /*!< in: fts transaction */
const char* name) /*!< in: savepoint name */
__attribute__((nonnull));
/**********************************************************************//**
diff --git a/storage/xtradb/include/fts0pars.h b/storage/xtradb/include/fts0pars.h
index 50f636944e5..8108e811599 100644
--- a/storage/xtradb/include/fts0pars.h
+++ b/storage/xtradb/include/fts0pars.h
@@ -53,9 +53,9 @@ typedef union YYSTYPE
/* Line 2068 of yacc.c */
#line 61 "fts0pars.y"
- int oper;
- char* token;
- fts_ast_node_t* node;
+ int oper;
+ fts_ast_string_t* token;
+ fts_ast_node_t* node;
diff --git a/storage/xtradb/include/log0log.h b/storage/xtradb/include/log0log.h
index b9e0c2ef516..f130c8de423 100644
--- a/storage/xtradb/include/log0log.h
+++ b/storage/xtradb/include/log0log.h
@@ -168,6 +168,13 @@ lsn_t
log_get_lsn(void);
/*=============*/
/************************************************************//**
+Gets the current lsn.
+@return current lsn */
+UNIV_INLINE
+lsn_t
+log_get_lsn_nowait(void);
+/*=============*/
+/************************************************************//**
Gets the last lsn that is fully flushed to disk.
@return last flushed lsn */
UNIV_INLINE
@@ -615,6 +622,27 @@ void
log_mem_free(void);
/*==============*/
+/****************************************************************//**
+Safely reads the log_sys->tracked_lsn value. Uses atomic operations
+if available, otherwise this field is protected with the log system
+mutex. The writer counterpart function is log_set_tracked_lsn() in
+log0online.c.
+
+@return log_sys->tracked_lsn value. */
+UNIV_INLINE
+lsn_t
+log_get_tracked_lsn(void);
+/*=====================*/
+/****************************************************************//**
+Unsafely reads the log_sys->tracked_lsn value. Uses atomic operations
+if available, or use dirty read. Use for printing only.
+
+@return log_sys->tracked_lsn value. */
+UNIV_INLINE
+lsn_t
+log_get_tracked_lsn_peek(void);
+/*==========================*/
+
extern log_t* log_sys;
/* Values used as flags */
@@ -696,13 +724,13 @@ extern log_t* log_sys;
megabyte.
This information might have been used
- since ibbackup version 0.35 but
+ since mysqlbackup version 0.35 but
before 1.41 to decide if unused ends of
non-auto-extending data files
in space 0 can be truncated.
This information was made obsolete
- by ibbackup --compress. */
+ by mysqlbackup --compress. */
#define LOG_CHECKPOINT_FSP_MAGIC_N (12 + LOG_CHECKPOINT_ARRAY_END)
/*!< Not used (0);
This magic number tells if the
@@ -731,7 +759,7 @@ extern log_t* log_sys;
/* a 32-byte field which contains
the string 'ibbackup' and the
creation time if the log file was
- created by ibbackup --restore;
+ created by mysqlbackup --restore;
when mysqld is first time started
on the restored database, it can
print helpful info for the user */
diff --git a/storage/xtradb/include/log0log.ic b/storage/xtradb/include/log0log.ic
index 7724d94b51a..853027daa7e 100644
--- a/storage/xtradb/include/log0log.ic
+++ b/storage/xtradb/include/log0log.ic
@@ -486,6 +486,26 @@ log_get_flush_lsn(void)
return(lsn);
}
+/************************************************************//**
+Gets the current lsn with a trylock
+@return current lsn or 0 if false*/
+UNIV_INLINE
+lsn_t
+log_get_lsn_nowait(void)
+/*=============*/
+{
+ lsn_t lsn;
+
+ if (mutex_enter_nowait(&(log_sys->mutex)))
+ return 0;
+
+ lsn = log_sys->lsn;
+
+ mutex_exit(&(log_sys->mutex));
+
+ return(lsn);
+}
+
/****************************************************************
Gets the log group capacity. It is OK to read the value without
holding log_sys->mutex because it is constant.
@@ -531,3 +551,39 @@ log_free_check(void)
}
}
#endif /* !UNIV_HOTBACKUP */
+
+/****************************************************************//**
+Unsafely reads the log_sys->tracked_lsn value. Uses atomic operations
+if available, or use dirty read. Use for printing only.
+
+@return log_sys->tracked_lsn value. */
+UNIV_INLINE
+lsn_t
+log_get_tracked_lsn_peek(void)
+/*==========================*/
+{
+#ifdef HAVE_ATOMIC_BUILTINS_64
+ return os_atomic_increment_uint64(&log_sys->tracked_lsn, 0);
+#else
+ return log_sys->tracked_lsn;
+#endif
+}
+
+/****************************************************************//**
+Safely reads the log_sys->tracked_lsn value. Uses atomic operations
+if available, otherwise this field is protected with the log system
+mutex. The writer counterpart function is log_set_tracked_lsn() in
+log0online.c.
+@return log_sys->tracked_lsn value. */
+UNIV_INLINE
+lsn_t
+log_get_tracked_lsn(void)
+/*=====================*/
+{
+#ifdef HAVE_ATOMIC_BUILTINS_64
+ return os_atomic_increment_uint64(&log_sys->tracked_lsn, 0);
+#else
+ ut_ad(mutex_own(&(log_sys->mutex)));
+ return log_sys->tracked_lsn;
+#endif
+}
diff --git a/storage/xtradb/include/os0file.h b/storage/xtradb/include/os0file.h
index 1ab71d80829..0c9f634266a 100644
--- a/storage/xtradb/include/os0file.h
+++ b/storage/xtradb/include/os0file.h
@@ -131,7 +131,7 @@ enum os_file_create_t {
#define OS_FILE_READ_ONLY 333
#define OS_FILE_READ_WRITE 444
-#define OS_FILE_READ_ALLOW_DELETE 555 /* for ibbackup */
+#define OS_FILE_READ_ALLOW_DELETE 555 /* for mysqlbackup */
/* Options for file_create */
#define OS_FILE_AIO 61
diff --git a/storage/xtradb/include/os0sync.h b/storage/xtradb/include/os0sync.h
index ba22c02a5a9..066fd34d668 100644
--- a/storage/xtradb/include/os0sync.h
+++ b/storage/xtradb/include/os0sync.h
@@ -357,6 +357,10 @@ Atomic compare-and-swap and increment for InnoDB. */
# define HAVE_ATOMIC_BUILTINS
+# ifdef HAVE_IB_GCC_ATOMIC_BUILTINS_BYTE
+# define HAVE_ATOMIC_BUILTINS_BYTE
+# endif
+
# ifdef HAVE_IB_GCC_ATOMIC_BUILTINS_64
# define HAVE_ATOMIC_BUILTINS_64
# endif
@@ -440,6 +444,7 @@ Returns the old value of *ptr, atomically sets *ptr to new_val */
#elif defined(HAVE_IB_SOLARIS_ATOMICS)
# define HAVE_ATOMIC_BUILTINS
+# define HAVE_ATOMIC_BUILTINS_BYTE
# define HAVE_ATOMIC_BUILTINS_64
/* If not compiling with GCC or GCC doesn't support the atomic
@@ -524,6 +529,7 @@ Returns the old value of *ptr, atomically sets *ptr to new_val */
#elif defined(HAVE_WINDOWS_ATOMICS)
# define HAVE_ATOMIC_BUILTINS
+# define HAVE_ATOMIC_BUILTINS_BYTE
# ifndef _WIN32
# define HAVE_ATOMIC_BUILTINS_64
@@ -694,6 +700,65 @@ for synchronization */
os_decrement_counter_by_amount(mutex, counter, 1);\
} while (0);
+/** barrier definitions for memory ordering */
+#if defined __i386__ || defined __x86_64__ || defined _M_IX86 || defined _M_X64 || defined __WIN__
+/* Performance regression was observed at some conditions for Intel
+architecture. Disable memory barrier for Intel architecture for now. */
+# define os_rmb do { } while(0)
+# define os_wmb do { } while(0)
+# define os_isync do { } while(0)
+# define IB_MEMORY_BARRIER_STARTUP_MSG \
+ "Memory barrier is not used"
+#elif defined(HAVE_IB_GCC_ATOMIC_THREAD_FENCE)
+# define HAVE_MEMORY_BARRIER
+# define os_rmb __atomic_thread_fence(__ATOMIC_ACQUIRE)
+# define os_wmb __atomic_thread_fence(__ATOMIC_RELEASE)
+#ifdef __powerpc__
+# define os_isync __asm __volatile ("isync":::"memory")
+#else
+#define os_isync do { } while(0)
+#endif
+
+# define IB_MEMORY_BARRIER_STARTUP_MSG \
+ "GCC builtin __atomic_thread_fence() is used for memory barrier"
+
+#elif defined(HAVE_IB_GCC_SYNC_SYNCHRONISE)
+# define HAVE_MEMORY_BARRIER
+# define os_rmb __sync_synchronize()
+# define os_wmb __sync_synchronize()
+# define os_isync __sync_synchronize()
+# define IB_MEMORY_BARRIER_STARTUP_MSG \
+ "GCC builtin __sync_synchronize() is used for memory barrier"
+
+#elif defined(HAVE_IB_MACHINE_BARRIER_SOLARIS)
+# define HAVE_MEMORY_BARRIER
+# include <mbarrier.h>
+# define os_rmb __machine_r_barrier()
+# define os_wmb __machine_w_barrier()
+# define os_isync os_rmb; os_wmb
+# define IB_MEMORY_BARRIER_STARTUP_MSG \
+ "Solaris memory ordering functions are used for memory barrier"
+
+#elif defined(HAVE_WINDOWS_MM_FENCE)
+# define HAVE_MEMORY_BARRIER
+# include <intrin.h>
+# define os_rmb _mm_lfence()
+# define os_wmb _mm_sfence()
+# define os_isync os_rmb; os_wmb
+# define IB_MEMORY_BARRIER_STARTUP_MSG \
+ "_mm_lfence() and _mm_sfence() are used for memory barrier"
+
+# define os_atomic_lock_release_byte(ptr) \
+ (void) InterlockedExchange(ptr, 0)
+
+#else
+# define os_rmb do { } while(0)
+# define os_wmb do { } while(0)
+# define os_isync do { } while(0)
+# define IB_MEMORY_BARRIER_STARTUP_MSG \
+ "Memory barrier is not used"
+#endif
+
#ifndef UNIV_NONINL
#include "os0sync.ic"
#endif
diff --git a/storage/xtradb/include/sync0rw.ic b/storage/xtradb/include/sync0rw.ic
index d1675f0a9c9..8aadc406132 100644
--- a/storage/xtradb/include/sync0rw.ic
+++ b/storage/xtradb/include/sync0rw.ic
@@ -112,6 +112,7 @@ rw_lock_set_waiter_flag(
(void) os_compare_and_swap_ulint(&lock->waiters, 0, 1);
#else /* INNODB_RW_LOCKS_USE_ATOMICS */
lock->waiters = 1;
+ os_wmb;
#endif /* INNODB_RW_LOCKS_USE_ATOMICS */
}
@@ -129,6 +130,7 @@ rw_lock_reset_waiter_flag(
(void) os_compare_and_swap_ulint(&lock->waiters, 1, 0);
#else /* INNODB_RW_LOCKS_USE_ATOMICS */
lock->waiters = 0;
+ os_wmb;
#endif /* INNODB_RW_LOCKS_USE_ATOMICS */
}
@@ -256,7 +258,10 @@ rw_lock_lock_word_decr(
ulint amount) /*!< in: amount to decrement */
{
#ifdef INNODB_RW_LOCKS_USE_ATOMICS
- lint local_lock_word = lock->lock_word;
+ lint local_lock_word;
+
+ os_rmb;
+ local_lock_word = lock->lock_word;
while (local_lock_word > 0) {
if (os_compare_and_swap_lint(&lock->lock_word,
local_lock_word,
@@ -620,10 +625,6 @@ rw_lock_s_unlock_func(
/* A waiting next-writer exists, either high priority or
regular, sharing the same wait event. */
- if (lock->high_priority_wait_ex_waiter) {
-
- lock->high_priority_wait_ex_waiter = 0;
- }
os_event_set(lock->base_lock.wait_ex_event);
sync_array_object_signalled();
diff --git a/storage/xtradb/include/sync0sync.h b/storage/xtradb/include/sync0sync.h
index 788f765f919..8c5dde4c142 100644
--- a/storage/xtradb/include/sync0sync.h
+++ b/storage/xtradb/include/sync0sync.h
@@ -50,6 +50,8 @@ extern "C" my_bool timed_mutexes;
#ifdef _WIN32
typedef LONG lock_word_t; /*!< On Windows, InterlockedExchange operates
on LONG variable */
+#elif defined(HAVE_ATOMIC_BUILTINS) && !defined(HAVE_ATOMIC_BUILTINS_BYTE)
+typedef ulint lock_word_t;
#else
typedef byte lock_word_t;
#endif
diff --git a/storage/xtradb/include/sync0sync.ic b/storage/xtradb/include/sync0sync.ic
index 34541a98789..0c4a8ace887 100644
--- a/storage/xtradb/include/sync0sync.ic
+++ b/storage/xtradb/include/sync0sync.ic
@@ -83,7 +83,11 @@ ib_mutex_test_and_set(
ib_mutex_t* mutex) /*!< in: mutex */
{
#if defined(HAVE_ATOMIC_BUILTINS)
+# if defined(HAVE_ATOMIC_BUILTINS_BYTE)
return(os_atomic_test_and_set_byte(&mutex->lock_word, 1));
+# else
+ return(os_atomic_test_and_set_ulint(&mutex->lock_word, 1));
+# endif
#else
ibool ret;
@@ -95,6 +99,7 @@ ib_mutex_test_and_set(
ut_a(mutex->lock_word == 0);
mutex->lock_word = 1;
+ os_wmb;
}
return((byte) ret);
@@ -147,6 +152,7 @@ mutex_get_waiters(
ptr = &(mutex->waiters);
+ os_rmb;
return(*ptr); /* Here we assume that the read of a single
word from memory is atomic */
}
@@ -181,6 +187,7 @@ mutex_exit_func(
to wake up possible hanging threads if
they are missed in mutex_signal_object. */
+ os_isync;
if (mutex_get_waiters(mutex) != 0) {
mutex_signal_object(mutex);
diff --git a/storage/xtradb/include/univ.i b/storage/xtradb/include/univ.i
index a808e773db2..8511f87ef87 100644
--- a/storage/xtradb/include/univ.i
+++ b/storage/xtradb/include/univ.i
@@ -44,10 +44,10 @@ Created 1/20/1994 Heikki Tuuri
#define INNODB_VERSION_MAJOR 5
#define INNODB_VERSION_MINOR 6
-#define INNODB_VERSION_BUGFIX 19
+#define INNODB_VERSION_BUGFIX 20
#ifndef PERCONA_INNODB_VERSION
-#define PERCONA_INNODB_VERSION 67.0
+#define PERCONA_INNODB_VERSION 68.0
#endif
/* Enable UNIV_LOG_ARCHIVE in XtraDB */
diff --git a/storage/xtradb/log/log0log.cc b/storage/xtradb/log/log0log.cc
index 58ef40e468c..2dc129b1bb3 100644
--- a/storage/xtradb/log/log0log.cc
+++ b/storage/xtradb/log/log0log.cc
@@ -197,22 +197,24 @@ log_buf_pool_get_oldest_modification(void)
}
/****************************************************************//**
-Safely reads the log_sys->tracked_lsn value. Uses atomic operations
-if available, otherwise this field is protected with the log system
-mutex. The writer counterpart function is log_set_tracked_lsn() in
-log0online.c.
-
-@return log_sys->tracked_lsn value. */
-UNIV_INLINE
+Returns the oldest modified block lsn in the pool, or log_sys->lsn if none
+exists.
+@return LSN of oldest modification */
+static
lsn_t
-log_get_tracked_lsn()
+log_buf_pool_get_oldest_modification_peek(void)
+/*===========================================*/
{
-#ifdef HAVE_ATOMIC_BUILTINS_64
- return os_atomic_increment_uint64(&log_sys->tracked_lsn, 0);
-#else
- ut_ad(mutex_own(&(log_sys->mutex)));
- return log_sys->tracked_lsn;
-#endif
+ lsn_t lsn;
+
+ lsn = buf_pool_get_oldest_modification_peek();
+
+ if (!lsn) {
+
+ lsn = log_sys->lsn;
+ }
+
+ return(lsn);
}
/****************************************************************//**
@@ -639,7 +641,7 @@ log_pad_current_log_block(void)
byte b = MLOG_DUMMY_RECORD;
ulint pad_length;
ulint i;
- ib_uint64_t lsn;
+ lsn_t lsn;
/* We retrieve lsn only because otherwise gcc crashed on HP-UX */
lsn = log_reserve_and_open(OS_FILE_LOG_BLOCK_SIZE);
@@ -647,6 +649,12 @@ log_pad_current_log_block(void)
pad_length = OS_FILE_LOG_BLOCK_SIZE
- (log_sys->buf_free % OS_FILE_LOG_BLOCK_SIZE)
- LOG_BLOCK_TRL_SIZE;
+ if (pad_length
+ == (OS_FILE_LOG_BLOCK_SIZE - LOG_BLOCK_HDR_SIZE
+ - LOG_BLOCK_TRL_SIZE)) {
+
+ pad_length = 0;
+ }
for (i = 0; i < pad_length; i++) {
log_write_low(&b, 1);
@@ -1347,7 +1355,7 @@ log_group_file_header_flush(
mach_write_to_4(buf + LOG_GROUP_ID, group->id);
mach_write_to_8(buf + LOG_FILE_START_LSN, start_lsn);
- /* Wipe over possible label of ibbackup --restore */
+ /* Wipe over possible label of mysqlbackup --restore */
memcpy(buf + LOG_FILE_WAS_CREATED_BY_HOT_BACKUP, " ", 4);
mach_write_to_4(buf + LOG_FILE_OS_FILE_LOG_BLOCK_SIZE,
@@ -2122,7 +2130,7 @@ log_reset_first_header_and_checkpoint(
lsn = start + LOG_BLOCK_HDR_SIZE;
- /* Write the label of ibbackup --restore */
+ /* Write the label of mysqlbackup --restore */
strcpy((char*) hdr_buf + LOG_FILE_WAS_CREATED_BY_HOT_BACKUP,
"ibbackup ");
ut_sprintf_timestamp((char*) hdr_buf
@@ -3153,8 +3161,7 @@ void
log_archive_all(void)
/*=================*/
{
- ib_uint64_t present_lsn;
- ulint dummy;
+ lsn_t present_lsn;
mutex_enter(&(log_sys->mutex));
@@ -3171,6 +3178,9 @@ log_archive_all(void)
log_pad_current_log_block();
for (;;) {
+
+ ulint archived_bytes;
+
mutex_enter(&(log_sys->mutex));
if (present_lsn <= log_sys->archived_lsn) {
@@ -3182,7 +3192,10 @@ log_archive_all(void)
mutex_exit(&(log_sys->mutex));
- log_archive_do(TRUE, &dummy);
+ log_archive_do(TRUE, &archived_bytes);
+
+ if (archived_bytes == 0)
+ return;
}
}
@@ -3883,7 +3896,7 @@ log_print(
double time_elapsed;
time_t current_time;
- mutex_enter(&(log_sys->mutex));
+ // mutex_enter(&(log_sys->mutex));
fprintf(file,
"Log sequence number " LSN_PF "\n"
@@ -3892,7 +3905,7 @@ log_print(
"Last checkpoint at " LSN_PF "\n",
log_sys->lsn,
log_sys->flushed_to_disk_lsn,
- log_buf_pool_get_oldest_modification(),
+ log_buf_pool_get_oldest_modification_peek(),
log_sys->last_checkpoint_lsn);
fprintf(file,
@@ -3902,7 +3915,7 @@ log_print(
"Checkpoint age " LSN_PF "\n",
log_sys->max_checkpoint_age,
log_sys->max_checkpoint_age_async,
- log_sys->lsn -log_buf_pool_get_oldest_modification(),
+ log_sys->lsn -log_buf_pool_get_oldest_modification_peek(),
log_sys->lsn - log_sys->last_checkpoint_lsn);
current_time = time(NULL);
@@ -3931,14 +3944,14 @@ log_print(
"Log tracking enabled\n"
"Log tracked up to " LSN_PF "\n"
"Max tracked LSN age " LSN_PF "\n",
- log_get_tracked_lsn(),
+ log_get_tracked_lsn_peek(),
log_sys->max_checkpoint_age);
}
log_sys->n_log_ios_old = log_sys->n_log_ios;
log_sys->last_printout_time = current_time;
- mutex_exit(&(log_sys->mutex));
+ //mutex_exit(&(log_sys->mutex));
}
/**********************************************************************//**
diff --git a/storage/xtradb/log/log0online.cc b/storage/xtradb/log/log0online.cc
index 127e09e0448..189723a8006 100644
--- a/storage/xtradb/log/log0online.cc
+++ b/storage/xtradb/log/log0online.cc
@@ -1188,6 +1188,9 @@ log_online_write_bitmap(void)
bmp_tree_node = (ib_rbt_node_t*)
rbt_next(log_bmp_sys->modified_pages, bmp_tree_node);
+
+ DBUG_EXECUTE_IF("bitmap_page_2_write_error",
+ DBUG_SET("+d,bitmap_page_write_error"););
}
rbt_reset(log_bmp_sys->modified_pages);
@@ -1253,6 +1256,7 @@ log_online_follow_redo_log(void)
/*********************************************************************//**
Diagnose a bitmap file range setup failure and free the partially-initialized
bitmap file range. */
+UNIV_COLD
static
void
log_online_diagnose_inconsistent_dir(
@@ -1434,26 +1438,30 @@ log_online_setup_bitmap_file_range(
return FALSE;
}
-#ifdef UNIV_DEBUG
- if (!bitmap_files->files[0].seq_num) {
+ if (!bitmap_files->files[0].seq_num
+ || bitmap_files->files[0].seq_num != first_file_seq_num) {
log_online_diagnose_inconsistent_dir(bitmap_files);
return FALSE;
}
- ut_ad(bitmap_files->files[0].seq_num == first_file_seq_num);
+
{
size_t i;
for (i = 1; i < bitmap_files->count; i++) {
if (!bitmap_files->files[i].seq_num) {
break;
}
- ut_ad(bitmap_files->files[i].seq_num
- > bitmap_files->files[i - 1].seq_num);
- ut_ad(bitmap_files->files[i].start_lsn
- >= bitmap_files->files[i - 1].start_lsn);
+ if ((bitmap_files->files[i].seq_num
+ <= bitmap_files->files[i - 1].seq_num)
+ || (bitmap_files->files[i].start_lsn
+ < bitmap_files->files[i - 1].start_lsn)) {
+
+ log_online_diagnose_inconsistent_dir(
+ bitmap_files);
+ return FALSE;
+ }
}
}
-#endif
return TRUE;
}
@@ -1576,6 +1584,17 @@ log_online_bitmap_iterator_init(
{
ut_a(i);
+ if (UNIV_UNLIKELY(min_lsn > max_lsn)) {
+
+ /* Empty range */
+ i->in_files.count = 0;
+ i->in_files.files = NULL;
+ i->in.file = os_file_invalid;
+ i->page = NULL;
+ i->failed = FALSE;
+ return TRUE;
+ }
+
if (!log_online_setup_bitmap_file_range(&i->in_files, min_lsn,
max_lsn)) {
diff --git a/storage/xtradb/log/log0recv.cc b/storage/xtradb/log/log0recv.cc
index 0db2b6ef5ed..3e0ec3d15fa 100644
--- a/storage/xtradb/log/log0recv.cc
+++ b/storage/xtradb/log/log0recv.cc
@@ -66,7 +66,7 @@ Created 9/20/1997 Heikki Tuuri
/** This is set to FALSE if the backup was originally taken with the
-ibbackup --include regexp option: then we do not want to create tables in
+mysqlbackup --include regexp option: then we do not want to create tables in
directories which were not included */
UNIV_INTERN ibool recv_replay_file_ops = TRUE;
#endif /* !UNIV_HOTBACKUP */
@@ -2127,7 +2127,7 @@ recv_apply_log_recs_for_backup(void)
/* Extend the tablespace's last file if the page_no
does not fall inside its bounds; we assume the last
- file is auto-extending, and ibbackup copied the file
+ file is auto-extending, and mysqlbackup copied the file
when it still was smaller */
success = fil_extend_space_to_desired_size(
@@ -2498,10 +2498,10 @@ loop:
#ifdef UNIV_HOTBACKUP
if (recv_replay_file_ops) {
- /* In ibbackup --apply-log, replay an .ibd file
- operation, if possible; note that
- fil_path_to_mysql_datadir is set in ibbackup to
- point to the datadir we should use there */
+ /* In mysqlbackup --apply-log, replay an .ibd
+ file operation, if possible; note that
+ fil_path_to_mysql_datadir is set in mysqlbackup
+ to point to the datadir we should use there */
if (NULL == fil_op_log_parse_or_replay(
body, end_ptr, type,
@@ -3166,17 +3166,17 @@ recv_recovery_from_checkpoint_start_func(
if (srv_read_only_mode) {
ib_logf(IB_LOG_LEVEL_ERROR,
- "Cannot restore from ibbackup, InnoDB running "
- "in read-only mode!");
+ "Cannot restore from mysqlbackup, InnoDB "
+ "running in read-only mode!");
return(DB_ERROR);
}
- /* This log file was created by ibbackup --restore: print
+ /* This log file was created by mysqlbackup --restore: print
a note to the user about it */
ib_logf(IB_LOG_LEVEL_INFO,
- "The log file was created by ibbackup --apply-log "
+ "The log file was created by mysqlbackup --apply-log "
"at %s. The following crash recovery is part of a "
"normal restore.",
log_hdr_buf + LOG_FILE_WAS_CREATED_BY_HOT_BACKUP);
diff --git a/storage/xtradb/mysql-test/storage_engine/alter_tablespace.opt b/storage/xtradb/mysql-test/storage_engine/alter_tablespace.opt
new file mode 100644
index 00000000000..cf4b117e1b1
--- /dev/null
+++ b/storage/xtradb/mysql-test/storage_engine/alter_tablespace.opt
@@ -0,0 +1,2 @@
+--innodb-file-per-table=1
+
diff --git a/storage/xtradb/mysql-test/storage_engine/autoinc_secondary.rdiff b/storage/xtradb/mysql-test/storage_engine/autoinc_secondary.rdiff
new file mode 100644
index 00000000000..00cda7c4435
--- /dev/null
+++ b/storage/xtradb/mysql-test/storage_engine/autoinc_secondary.rdiff
@@ -0,0 +1,30 @@
+--- suite/storage_engine/autoinc_secondary.result 2012-07-12 04:34:18.153885986 +0400
++++ suite/storage_engine/autoinc_secondary.reject 2012-07-15 17:47:03.937703666 +0400
+@@ -13,18 +13,15 @@
+ 5 a
+ DROP TABLE t1;
+ CREATE TABLE t1 (a <CHAR_COLUMN>, b <INT_COLUMN> AUTO_INCREMENT, PRIMARY KEY (a,b)) ENGINE=<STORAGE_ENGINE> <CUSTOM_TABLE_OPTIONS>;
+-INSERT INTO t1 (a) VALUES ('a'),('b'),('b'),('c'),('a');
+-SELECT LAST_INSERT_ID();
+-LAST_INSERT_ID()
+-1
+-SELECT a,b FROM t1;
+-a b
+-a 1
+-a 2
+-b 1
+-b 2
+-c 1
+-DROP TABLE t1;
++ERROR 42000: Incorrect table definition; there can be only one auto column and it must be defined as a key
++# ERROR: Statement ended with errno 1075, errname ER_WRONG_AUTO_KEY (expected to succeed)
++# ------------ UNEXPECTED RESULT ------------
++# The statement|command finished with ER_WRONG_AUTO_KEY.
++# Multi-part keys or PK or AUTO_INCREMENT (on a secondary column) or the mix could be unsupported|malfunctioning, or the problem was caused by previous errors.
++# You can change the engine code, or create an rdiff, or disable the test by adding it to disabled.def.
++# Further in this test, the message might sometimes be suppressed; a part of the test might be skipped.
++# Also, this problem may cause a chain effect (more errors of different kinds in the test).
++# -------------------------------------------
+ CREATE TABLE t1 (a <CHAR_COLUMN>, b <INT_COLUMN> AUTO_INCREMENT, PRIMARY KEY (a,b), <CUSTOM_INDEX>(b)) ENGINE=<STORAGE_ENGINE> <CUSTOM_TABLE_OPTIONS>;
+ INSERT INTO t1 (a) VALUES ('a'),('b'),('b'),('c'),('a');
+ SELECT LAST_INSERT_ID();
diff --git a/storage/xtradb/mysql-test/storage_engine/cache_index.rdiff b/storage/xtradb/mysql-test/storage_engine/cache_index.rdiff
new file mode 100644
index 00000000000..e04df87aa34
--- /dev/null
+++ b/storage/xtradb/mysql-test/storage_engine/cache_index.rdiff
@@ -0,0 +1,71 @@
+--- suite/storage_engine/cache_index.result 2012-07-15 00:22:19.822493731 +0400
++++ suite/storage_engine/cache_index.reject 2012-07-15 17:47:18.321522834 +0400
+@@ -12,31 +12,31 @@
+ SET GLOBAL <CACHE_NAME>.key_buffer_size=128*1024;
+ CACHE INDEX t1 INDEX (a), t2 IN <CACHE_NAME>;
+ Table Op Msg_type Msg_text
+-test.t1 assign_to_keycache status OK
+-test.t2 assign_to_keycache status OK
++test.t1 assign_to_keycache note The storage engine for the table doesn't support assign_to_keycache
++test.t2 assign_to_keycache note The storage engine for the table doesn't support assign_to_keycache
+ LOAD INDEX INTO CACHE t1, t2;
+ Table Op Msg_type Msg_text
+-test.t1 preload_keys status OK
+-test.t2 preload_keys status OK
++test.t1 preload_keys note The storage engine for the table doesn't support preload_keys
++test.t2 preload_keys note The storage engine for the table doesn't support preload_keys
+ INSERT INTO t1 (a,b) VALUES (3,'c'),(4,'d');
+ SET GLOBAL <CACHE_NAME>.key_buffer_size=8*1024;
+ LOAD INDEX INTO CACHE t1, t2 IGNORE LEAVES;
+ Table Op Msg_type Msg_text
+-test.t1 preload_keys status OK
+-test.t2 preload_keys status OK
++test.t1 preload_keys note The storage engine for the table doesn't support preload_keys
++test.t2 preload_keys note The storage engine for the table doesn't support preload_keys
+ SET GLOBAL <CACHE_NAME>.key_cache_age_threshold = 100, <CACHE_NAME>.key_cache_block_size = 512, <CACHE_NAME>.key_cache_division_limit = 1, <CACHE_NAME>.key_cache_segments=2;
+ INSERT INTO t1 (a,b) VALUES (5,'e'),(6,'f');
+ LOAD INDEX INTO CACHE t1;
+ Table Op Msg_type Msg_text
+-test.t1 preload_keys status OK
++test.t1 preload_keys note The storage engine for the table doesn't support preload_keys
+ SET GLOBAL new_<CACHE_NAME>.key_buffer_size=128*1024;
+ CACHE INDEX t1 IN new_<CACHE_NAME>;
+ Table Op Msg_type Msg_text
+-test.t1 assign_to_keycache status OK
++test.t1 assign_to_keycache note The storage engine for the table doesn't support assign_to_keycache
+ INSERT INTO t1 (a,b) VALUES (7,'g'),(8,'h');
+ LOAD INDEX INTO CACHE t1 IGNORE LEAVES;
+ Table Op Msg_type Msg_text
+-test.t1 preload_keys status OK
++test.t1 preload_keys note The storage engine for the table doesn't support preload_keys
+ INSERT INTO t1 (a,b) VALUES (9,'i');
+ DROP TABLE t2;
+ DROP TABLE t1;
+@@ -47,11 +47,11 @@
+ ) ENGINE=<STORAGE_ENGINE> <CUSTOM_TABLE_OPTIONS>;
+ CACHE INDEX t1 IN <CACHE_NAME>;
+ Table Op Msg_type Msg_text
+-test.t1 assign_to_keycache status OK
++test.t1 assign_to_keycache note The storage engine for the table doesn't support assign_to_keycache
+ INSERT INTO t1 (a,b) VALUES (1,'a'),(2,'b');
+ LOAD INDEX INTO CACHE t1;
+ Table Op Msg_type Msg_text
+-test.t1 preload_keys status OK
++test.t1 preload_keys note The storage engine for the table doesn't support preload_keys
+ DROP TABLE t1;
+ CREATE TABLE t1 (a <INT_COLUMN>,
+ b <CHAR_COLUMN>,
+@@ -59,11 +59,11 @@
+ ) ENGINE=<STORAGE_ENGINE> <CUSTOM_TABLE_OPTIONS>;
+ CACHE INDEX t1 IN <CACHE_NAME>;
+ Table Op Msg_type Msg_text
+-test.t1 assign_to_keycache status OK
++test.t1 assign_to_keycache note The storage engine for the table doesn't support assign_to_keycache
+ INSERT INTO t1 (a,b) VALUES (1,'a'),(2,'b');
+ LOAD INDEX INTO CACHE t1;
+ Table Op Msg_type Msg_text
+-test.t1 preload_keys status OK
++test.t1 preload_keys note The storage engine for the table doesn't support preload_keys
+ DROP TABLE t1;
+ SET GLOBAL <CACHE_NAME>.key_buffer_size=0;
+ SET GLOBAL new_<CACHE_NAME>.key_buffer_size=0;
diff --git a/storage/xtradb/mysql-test/storage_engine/checksum_table_live.rdiff b/storage/xtradb/mysql-test/storage_engine/checksum_table_live.rdiff
new file mode 100644
index 00000000000..71c782848a6
--- /dev/null
+++ b/storage/xtradb/mysql-test/storage_engine/checksum_table_live.rdiff
@@ -0,0 +1,13 @@
+--- suite/storage_engine/checksum_table_live.result 2012-07-12 21:05:44.497062968 +0400
++++ suite/storage_engine/checksum_table_live.reject 2012-07-15 17:47:28.105399836 +0400
+@@ -11,8 +11,8 @@
+ test.t1 4272806499
+ CHECKSUM TABLE t1, t2 QUICK;
+ Table Checksum
+-test.t1 4272806499
+-test.t2 0
++test.t1 NULL
++test.t2 NULL
+ CHECKSUM TABLE t1, t2 EXTENDED;
+ Table Checksum
+ test.t1 4272806499
diff --git a/storage/xtradb/mysql-test/storage_engine/col_opt_not_null.opt b/storage/xtradb/mysql-test/storage_engine/col_opt_not_null.opt
new file mode 100644
index 00000000000..40445305fc6
--- /dev/null
+++ b/storage/xtradb/mysql-test/storage_engine/col_opt_not_null.opt
@@ -0,0 +1 @@
+--innodb_log_file_size=100M
diff --git a/storage/xtradb/mysql-test/storage_engine/col_opt_null.opt b/storage/xtradb/mysql-test/storage_engine/col_opt_null.opt
new file mode 100644
index 00000000000..40445305fc6
--- /dev/null
+++ b/storage/xtradb/mysql-test/storage_engine/col_opt_null.opt
@@ -0,0 +1 @@
+--innodb_log_file_size=100M
diff --git a/storage/xtradb/mysql-test/storage_engine/define_engine.inc b/storage/xtradb/mysql-test/storage_engine/define_engine.inc
new file mode 100644
index 00000000000..77e384d2351
--- /dev/null
+++ b/storage/xtradb/mysql-test/storage_engine/define_engine.inc
@@ -0,0 +1,49 @@
+###########################################
+#
+# This is a template of the include file define_engine.inc which
+# should be placed in storage/<engine>/mysql-test/storage_engine folder.
+#
+################################
+#
+# The name of the engine under test must be defined in $ENGINE variable.
+# You can set it either here (uncomment and edit) or in your environment.
+#
+let $ENGINE = InnoDB;
+#
+################################
+#
+# The following three variables define specific options for columns and tables.
+# Normally there should be none needed, but for some engines it can be different.
+# If the engine requires specific column option for all or indexed columns,
+# set them inside the comment, e.g. /*!NOT NULL*/.
+# Do the same for table options if needed, e.g. /*!INSERT_METHOD=LAST*/
+
+let $default_col_opts = /*!*/;
+let $default_col_indexed_opts = /*!*/;
+let $default_tbl_opts = /*!*/;
+
+# INDEX, UNIQUE INDEX, PRIMARY KEY, special index type - choose the fist that the engine allows,
+# or set it to /*!*/ if none is supported
+
+let $default_index = /*!INDEX*/;
+
+# If the engine does not support the following types, replace them with the closest possible
+
+let $default_int_type = INT(11);
+let $default_char_type = CHAR(8);
+
+################################
+
+--disable_query_log
+--disable_result_log
+
+# Here you can place your custom MTR code which needs to be executed before each test,
+# e.g. creation of an additional schema or table, etc.
+# The cleanup part should be defined in cleanup_engine.inc
+
+CALL mtr.add_suppression("InnoDB: Resizing redo log from .* to .* pages, LSN=.*");
+CALL mtr.add_suppression("InnoDB: Starting to delete and rewrite log files.");
+CALL mtr.add_suppression("InnoDB: New log files created, LSN=.*");
+
+--enable_query_log
+--enable_result_log
diff --git a/storage/xtradb/mysql-test/storage_engine/disabled.def b/storage/xtradb/mysql-test/storage_engine/disabled.def
new file mode 100644
index 00000000000..2f3793047f4
--- /dev/null
+++ b/storage/xtradb/mysql-test/storage_engine/disabled.def
@@ -0,0 +1,8 @@
+autoinc_vars : MySQL:65225 (InnoDB miscalculates auto-increment)
+tbl_opt_ai : MySQL:65901 (AUTO_INCREMENT option on InnoDB table is ignored if added before autoinc column)
+delete_low_prio : InnoDB does not use table-level locking
+insert_high_prio : InnoDB does not use table-level locking
+insert_low_prio : InnoDB does not use table-level locking
+select_high_prio : InnoDB does not use table-level locking
+update_low_prio : InnoDB does not use table-level locking
+
diff --git a/storage/xtradb/mysql-test/storage_engine/fulltext_search.rdiff b/storage/xtradb/mysql-test/storage_engine/fulltext_search.rdiff
new file mode 100644
index 00000000000..a68fe83070e
--- /dev/null
+++ b/storage/xtradb/mysql-test/storage_engine/fulltext_search.rdiff
@@ -0,0 +1,49 @@
+--- suite/storage_engine/fulltext_search.result 2013-11-27 18:50:16.000000000 +0400
++++ suite/storage_engine/fulltext_search.reject 2014-02-05 15:33:26.000000000 +0400
+@@ -52,15 +52,14 @@
+ INSERT INTO t1 (v0,v1,v2) VALUES ('text4','Contributing more...','...is a good idea'),('text5','test','test');
+ SELECT v0, MATCH(v1) AGAINST('contributing') AS rating FROM t1 WHERE MATCH(v1) AGAINST ('contributing');
+ v0 rating
+-text4 1.3705332279205322
++text4 0.4885590672492981
+ SELECT v0 FROM t1 WHERE MATCH(v1,v2) AGAINST ('-test1 +critical +Cook*' IN BOOLEAN MODE);
+-v0
+-text1
++ERROR HY000: Can't find FULLTEXT index matching the column list
+ SELECT v0 FROM t1 WHERE MATCH(v1,v2) AGAINST ('-patch +critical +Cook*' IN BOOLEAN MODE);
+-v0
++ERROR HY000: Can't find FULLTEXT index matching the column list
+ SELECT v0, MATCH(v1) AGAINST('database' WITH QUERY EXPANSION) AS rating FROM t1 WHERE MATCH(v1) AGAINST ('database' WITH QUERY EXPANSION);
+ v0 rating
+-text1 178.11756896972656
++text1 151.4530487060547
+ DROP TABLE t1;
+ CREATE TABLE t1 (v0 VARCHAR(64) <CUSTOM_COL_OPTIONS>,
+ v1 VARCHAR(16384) <CUSTOM_COL_OPTIONS>,
+@@ -112,14 +111,15 @@
+ ), ('text2','test1','test2');
+ SELECT v0 FROM t1 WHERE MATCH(v1,v2) AGAINST ('contributing' IN NATURAL LANGUAGE MODE);
+ v0
++text1
+ INSERT INTO t1 (v0,v1,v2) VALUES ('text3','test','test');
+ SELECT v0, MATCH(v1,v2) AGAINST('contributing' IN NATURAL LANGUAGE MODE) AS rating FROM t1 WHERE MATCH(v1,v2) AGAINST ('contributing' IN NATURAL LANGUAGE MODE);
+ v0 rating
+-text1 0.2809644043445587
++text1 0.45528939366340637
+ INSERT INTO t1 (v0,v1,v2) VALUES ('text4','Contributing more...','...is a good idea'),('text5','test','test');
+ SELECT v0, MATCH(v1) AGAINST('contributing') AS rating FROM t1 WHERE MATCH(v1) AGAINST ('contributing');
+ v0 rating
+-text4 1.3705332279205322
++text4 0.4885590672492981
+ SELECT v0 FROM t1 WHERE MATCH(v1,v2) AGAINST ('-test1 +critical +Cook*' IN BOOLEAN MODE);
+ v0
+ text1
+@@ -127,6 +127,6 @@
+ v0
+ SELECT v0, MATCH(v1,v2) AGAINST('database' WITH QUERY EXPANSION) AS rating FROM t1 WHERE MATCH(v1,v2) AGAINST ('database' WITH QUERY EXPANSION);
+ v0 rating
+-text1 190.56150817871094
+-text4 1.1758291721343994
++text1 229.60874938964844
++text4 0.31671249866485596
+ DROP TABLE t1;
diff --git a/storage/xtradb/mysql-test/storage_engine/index_enable_disable.rdiff b/storage/xtradb/mysql-test/storage_engine/index_enable_disable.rdiff
new file mode 100644
index 00000000000..f8e812e7edb
--- /dev/null
+++ b/storage/xtradb/mysql-test/storage_engine/index_enable_disable.rdiff
@@ -0,0 +1,33 @@
+--- suite/storage_engine/index_enable_disable.result 2012-07-15 00:30:05.296641931 +0400
++++ suite/storage_engine/index_enable_disable.reject 2012-07-15 17:49:12.988081281 +0400
+@@ -11,15 +11,19 @@
+ Table Non_unique Key_name Seq_in_index Column_name Collation Cardinality Sub_part Packed Null Index_type Comment Index_comment
+ t1 1 a 1 a # # NULL NULL YES BTREE
+ ALTER TABLE t1 DISABLE KEYS;
++Warnings:
++Note 1031 Storage engine <STORAGE_ENGINE> of the table `test`.`t1` doesn't have this option
+ SHOW INDEX IN t1;
+ Table Non_unique Key_name Seq_in_index Column_name Collation Cardinality Sub_part Packed Null Index_type Comment Index_comment
+-t1 1 a 1 a # # NULL NULL YES BTREE disabled
++t1 1 a 1 a # # NULL NULL YES BTREE
+ EXPLAIN SELECT a FROM t1 ORDER BY a;
+ id select_type table type possible_keys key key_len ref rows Extra
+-1 SIMPLE t1 ALL NULL NULL NULL NULL 19 Using filesort
++1 SIMPLE t1 index NULL a 5 NULL 19 Using index
+ INSERT INTO t1 (a) VALUES
+ (11),(12),(13),(14),(15),(16),(17),(18),(19),(20);
+ ALTER TABLE t1 ENABLE KEYS;
++Warnings:
++Note 1031 Storage engine <STORAGE_ENGINE> of the table `test`.`t1` doesn't have this option
+ SHOW INDEX IN t1;
+ Table Non_unique Key_name Seq_in_index Column_name Collation Cardinality Sub_part Packed Null Index_type Comment Index_comment
+ t1 1 a 1 a # # NULL NULL YES BTREE
+@@ -32,6 +36,8 @@
+ (1),(2),(3),(4),(5),(6),(7),(8),(9),
+ (21),(22),(23),(24),(25),(26),(27),(28),(29);
+ ALTER TABLE t1 DISABLE KEYS;
++Warnings:
++Note 1031 Storage engine <STORAGE_ENGINE> of the table `test`.`t1` doesn't have this option
+ INSERT INTO t1 (a) VALUES (29);
+ ERROR 23000: Duplicate entry '29' for key 'a'
+ # Statement ended with one of expected results (ER_DUP_ENTRY,ER_DUP_KEY).
diff --git a/storage/xtradb/mysql-test/storage_engine/index_type_hash.rdiff b/storage/xtradb/mysql-test/storage_engine/index_type_hash.rdiff
new file mode 100644
index 00000000000..02f9d93588f
--- /dev/null
+++ b/storage/xtradb/mysql-test/storage_engine/index_type_hash.rdiff
@@ -0,0 +1,60 @@
+--- suite/storage_engine/index_type_hash.result 2012-07-15 01:10:17.919128889 +0400
++++ suite/storage_engine/index_type_hash.reject 2012-07-15 17:49:26.135915989 +0400
+@@ -4,7 +4,7 @@
+ ) ENGINE=<STORAGE_ENGINE> <CUSTOM_TABLE_OPTIONS>;
+ SHOW KEYS IN t1;
+ Table Non_unique Key_name Seq_in_index Column_name Collation Cardinality Sub_part Packed Null Index_type Comment Index_comment
+-t1 1 a 1 a # # NULL NULL # HASH
++t1 1 a 1 a # # NULL NULL # BTREE
+ DROP TABLE t1;
+ CREATE TABLE t1 (a <INT_COLUMN>,
+ b <CHAR_COLUMN>,
+@@ -12,8 +12,8 @@
+ ) ENGINE=<STORAGE_ENGINE> <CUSTOM_TABLE_OPTIONS>;
+ SHOW KEYS IN t1;
+ Table Non_unique Key_name Seq_in_index Column_name Collation Cardinality Sub_part Packed Null Index_type Comment Index_comment
+-t1 1 a_b 1 a # # NULL NULL # HASH a_b index
+-t1 1 a_b 2 b # # NULL NULL # HASH a_b index
++t1 1 a_b 1 a # # NULL NULL # BTREE a_b index
++t1 1 a_b 2 b # # NULL NULL # BTREE a_b index
+ DROP TABLE t1;
+ CREATE TABLE t1 (a <INT_COLUMN>,
+ b <CHAR_COLUMN>,
+@@ -22,8 +22,8 @@
+ ) ENGINE=<STORAGE_ENGINE> <CUSTOM_TABLE_OPTIONS>;
+ SHOW KEYS IN t1;
+ Table Non_unique Key_name Seq_in_index Column_name Collation Cardinality Sub_part Packed Null Index_type Comment Index_comment
+-t1 1 a 1 a # # NULL NULL # HASH
+-t1 1 b 1 b # # NULL NULL # HASH
++t1 1 a 1 a # # NULL NULL # BTREE
++t1 1 b 1 b # # NULL NULL # BTREE
+ DROP TABLE t1;
+ CREATE TABLE t1 (a <INT_COLUMN>,
+ b <CHAR_COLUMN>,
+@@ -31,7 +31,7 @@
+ ) ENGINE=<STORAGE_ENGINE> <CUSTOM_TABLE_OPTIONS>;
+ SHOW KEYS IN t1;
+ Table Non_unique Key_name Seq_in_index Column_name Collation Cardinality Sub_part Packed Null Index_type Comment Index_comment
+-t1 0 a 1 a # # NULL NULL # HASH
++t1 0 a 1 a # # NULL NULL # BTREE
+ INSERT INTO t1 (a,b) VALUES (1,'a'),(2,'b');
+ INSERT INTO t1 (a,b) VALUES (1,'c');
+ ERROR 23000: Duplicate entry '1' for key 'a'
+@@ -43,7 +43,7 @@
+ ALTER TABLE t1 ADD <CUSTOM_INDEX> (a) USING HASH COMMENT 'simple index on a';
+ SHOW INDEX FROM t1;
+ Table Non_unique Key_name Seq_in_index Column_name Collation Cardinality Sub_part Packed Null Index_type Comment Index_comment
+-t1 1 a 1 a # # NULL NULL # HASH simple index on a
++t1 1 a 1 a # # NULL NULL # BTREE simple index on a
+ ALTER TABLE t1 DROP KEY a;
+ DROP TABLE t1;
+ CREATE TABLE t1 (a <INT_COLUMN>,
+@@ -52,7 +52,7 @@
+ ) ENGINE=<STORAGE_ENGINE> <CUSTOM_TABLE_OPTIONS>;
+ SHOW KEYS IN t1;
+ Table Non_unique Key_name Seq_in_index Column_name Collation Cardinality Sub_part Packed Null Index_type Comment Index_comment
+-t1 0 a 1 a # # NULL NULL # HASH
++t1 0 a 1 a # # NULL NULL # BTREE
+ INSERT INTO t1 (a,b) VALUES (1,'a'),(2,'b');
+ INSERT INTO t1 (a,b) VALUES (1,'c');
+ ERROR 23000: Duplicate entry '1' for key 'a'
diff --git a/storage/xtradb/mysql-test/storage_engine/insert_delayed.rdiff b/storage/xtradb/mysql-test/storage_engine/insert_delayed.rdiff
new file mode 100644
index 00000000000..9e6cddf03f0
--- /dev/null
+++ b/storage/xtradb/mysql-test/storage_engine/insert_delayed.rdiff
@@ -0,0 +1,26 @@
+--- suite/storage_engine/insert_delayed.result 2013-01-23 01:23:49.461254916 +0400
++++ suite/storage_engine/insert_delayed.reject 2013-01-23 01:47:05.975698364 +0400
+@@ -5,7 +5,16 @@
+ connect con0,localhost,root,,;
+ SET lock_wait_timeout = 1;
+ INSERT DELAYED INTO t1 (a,b) VALUES (3,'c');
++ERROR HY000: DELAYED option not supported for table 't1'
++# ------------ UNEXPECTED RESULT ------------
++# The statement|command finished with ER_DELAYED_NOT_SUPPORTED.
++# INSERT DELAYED or the mix could be unsupported|malfunctioning, or the problem was caused by previous errors.
++# You can change the engine code, or create an rdiff, or disable the test by adding it to disabled.def.
++# Further in this test, the message might sometimes be suppressed; a part of the test might be skipped.
++# Also, this problem may cause a chain effect (more errors of different kinds in the test).
++# -------------------------------------------
+ INSERT DELAYED INTO t1 SET a=4, b='d';
++ERROR HY000: DELAYED option not supported for table 't1'
+ INSERT DELAYED INTO t1 (a,b) SELECT 5, 'e';
+ ERROR HY000: Lock wait timeout exceeded; try restarting transaction
+ disconnect con0;
+@@ -20,6 +29,4 @@
+ a b
+ 1 f
+ 2 b
+-3 c
+-4 d
+ DROP TABLE t1;
diff --git a/storage/xtradb/mysql-test/storage_engine/lock_concurrent.rdiff b/storage/xtradb/mysql-test/storage_engine/lock_concurrent.rdiff
new file mode 100644
index 00000000000..fe4a0087fa9
--- /dev/null
+++ b/storage/xtradb/mysql-test/storage_engine/lock_concurrent.rdiff
@@ -0,0 +1,22 @@
+--- suite/storage_engine/lock_concurrent.result 2012-06-24 23:55:19.539380000 +0400
++++ suite/storage_engine/lock_concurrent.reject 2012-07-15 17:50:21.279222746 +0400
+@@ -3,10 +3,19 @@
+ LOCK TABLES t1 WRITE CONCURRENT, t1 AS t2 READ;
+ SET lock_wait_timeout = 1;
+ LOCK TABLES t1 READ LOCAL;
++ERROR HY000: Lock wait timeout exceeded; try restarting transaction
++# ------------ UNEXPECTED RESULT ------------
++# The statement|command finished with ER_LOCK_WAIT_TIMEOUT.
++# LOCK .. WRITE CONCURRENT or the mix could be unsupported|malfunctioning, or the problem was caused by previous errors.
++# You can change the engine code, or create an rdiff, or disable the test by adding it to disabled.def.
++# Further in this test, the message might sometimes be suppressed; a part of the test might be skipped.
++# Also, this problem may cause a chain effect (more errors of different kinds in the test).
++# -------------------------------------------
+ UNLOCK TABLES;
+ UNLOCK TABLES;
+ LOCK TABLES t1 READ LOCAL;
+ LOCK TABLES t1 WRITE CONCURRENT, t1 AS t2 READ;
++ERROR HY000: Lock wait timeout exceeded; try restarting transaction
+ UNLOCK TABLES;
+ UNLOCK TABLES;
+ DROP TABLE t1;
diff --git a/storage/xtradb/mysql-test/storage_engine/optimize_table.rdiff b/storage/xtradb/mysql-test/storage_engine/optimize_table.rdiff
new file mode 100644
index 00000000000..54d1f600516
--- /dev/null
+++ b/storage/xtradb/mysql-test/storage_engine/optimize_table.rdiff
@@ -0,0 +1,37 @@
+--- suite/storage_engine/optimize_table.result 2012-07-12 19:13:53.741428591 +0400
++++ suite/storage_engine/optimize_table.reject 2012-07-15 17:50:30.843102510 +0400
+@@ -5,25 +5,32 @@
+ INSERT INTO t1 (a,b) VALUES (3,'c'),(4,'d');
+ OPTIMIZE TABLE t1;
+ Table Op Msg_type Msg_text
++test.t1 optimize note Table does not support optimize, doing recreate + analyze instead
+ test.t1 optimize status OK
+ INSERT INTO t2 (a,b) VALUES (4,'d');
+ OPTIMIZE NO_WRITE_TO_BINLOG TABLE t2;
+ Table Op Msg_type Msg_text
++test.t2 optimize note Table does not support optimize, doing recreate + analyze instead
+ test.t2 optimize status OK
+ INSERT INTO t2 (a,b) VALUES (5,'e');
+ INSERT INTO t1 (a,b) VALUES (6,'f');
+ OPTIMIZE LOCAL TABLE t1, t2;
+ Table Op Msg_type Msg_text
++test.t1 optimize note Table does not support optimize, doing recreate + analyze instead
+ test.t1 optimize status OK
++test.t2 optimize note Table does not support optimize, doing recreate + analyze instead
+ test.t2 optimize status OK
+ OPTIMIZE TABLE t1, t2;
+ Table Op Msg_type Msg_text
+-test.t1 optimize status Table is already up to date
+-test.t2 optimize status Table is already up to date
++test.t1 optimize note Table does not support optimize, doing recreate + analyze instead
++test.t1 optimize status OK
++test.t2 optimize note Table does not support optimize, doing recreate + analyze instead
++test.t2 optimize status OK
+ DROP TABLE t1, t2;
+ CREATE TABLE t1 (a <INT_COLUMN>, b <CHAR_COLUMN>, <CUSTOM_INDEX> (a)) ENGINE=<STORAGE_ENGINE> <CUSTOM_TABLE_OPTIONS>;
+ INSERT INTO t1 (a,b) VALUES (1,'a'),(100,'b'),(2,'c'),(3,'d');
+ OPTIMIZE TABLE t1;
+ Table Op Msg_type Msg_text
++test.t1 optimize note Table does not support optimize, doing recreate + analyze instead
+ test.t1 optimize status OK
+ DROP TABLE t1;
diff --git a/storage/xtradb/mysql-test/storage_engine/parts/checksum_table.rdiff b/storage/xtradb/mysql-test/storage_engine/parts/checksum_table.rdiff
new file mode 100644
index 00000000000..c8aabb787e9
--- /dev/null
+++ b/storage/xtradb/mysql-test/storage_engine/parts/checksum_table.rdiff
@@ -0,0 +1,13 @@
+--- suite/storage_engine/parts/checksum_table.result 2013-11-08 22:30:34.000000000 +0400
++++ suite/storage_engine/parts/checksum_table.reject 2013-11-08 22:32:30.000000000 +0400
+@@ -31,8 +31,8 @@
+ test.t1 4272806499
+ CHECKSUM TABLE t1, t2 QUICK;
+ Table Checksum
+-test.t1 4272806499
+-test.t2 0
++test.t1 NULL
++test.t2 NULL
+ CHECKSUM TABLE t1, t2 EXTENDED;
+ Table Checksum
+ test.t1 4272806499
diff --git a/storage/xtradb/mysql-test/storage_engine/parts/create_table.rdiff b/storage/xtradb/mysql-test/storage_engine/parts/create_table.rdiff
new file mode 100644
index 00000000000..0df91c6fc6e
--- /dev/null
+++ b/storage/xtradb/mysql-test/storage_engine/parts/create_table.rdiff
@@ -0,0 +1,20 @@
+--- suite/storage_engine/parts/create_table.result 2012-07-12 21:56:38.618667460 +0400
++++ suite/storage_engine/parts/create_table.reject 2012-07-15 20:06:43.496358345 +0400
+@@ -65,7 +65,7 @@
+ 1 SIMPLE t1 abc,def # # # # # # #
+ EXPLAIN PARTITIONS SELECT a FROM t1 WHERE a = 100;
+ id select_type table partitions type possible_keys key key_len ref rows Extra
+-1 SIMPLE NULL NULL # # # # # # #
++1 SIMPLE t1 def # # # # # # #
+ INSERT INTO t1 (a) VALUES (50);
+ ERROR HY000: Table has no partition for value 50
+ DROP TABLE t1;
+@@ -81,7 +81,7 @@
+ 1 SIMPLE t1 abc_abcsp0,def_defsp0 # # # # # # #
+ EXPLAIN PARTITIONS SELECT a FROM t1 WHERE a = 100;
+ id select_type table partitions type possible_keys key key_len ref rows Extra
+-1 SIMPLE NULL NULL # # # # # # #
++1 SIMPLE t1 def_defsp0 # # # # # # #
+ SELECT TABLE_SCHEMA, TABLE_NAME, PARTITION_NAME, SUBPARTITION_NAME, PARTITION_METHOD, SUBPARTITION_METHOD
+ FROM INFORMATION_SCHEMA.PARTITIONS WHERE TABLE_NAME = 't1';
+ TABLE_SCHEMA TABLE_NAME PARTITION_NAME SUBPARTITION_NAME PARTITION_METHOD SUBPARTITION_METHOD
diff --git a/storage/xtradb/mysql-test/storage_engine/parts/disabled.def b/storage/xtradb/mysql-test/storage_engine/parts/disabled.def
new file mode 100644
index 00000000000..796bdfc751b
--- /dev/null
+++ b/storage/xtradb/mysql-test/storage_engine/parts/disabled.def
@@ -0,0 +1 @@
+repair_table : InnoDB of 5.6.10 does not support repair on partitioned tables (fixed by 5.6.14)
diff --git a/storage/xtradb/mysql-test/storage_engine/parts/optimize_table.rdiff b/storage/xtradb/mysql-test/storage_engine/parts/optimize_table.rdiff
new file mode 100644
index 00000000000..a35ba5167d9
--- /dev/null
+++ b/storage/xtradb/mysql-test/storage_engine/parts/optimize_table.rdiff
@@ -0,0 +1,58 @@
+--- suite/storage_engine/parts/optimize_table.result 2013-07-18 22:55:38.000000000 +0400
++++ suite/storage_engine/parts/optimize_table.reject 2013-08-05 19:45:19.000000000 +0400
+@@ -9,18 +9,22 @@
+ INSERT INTO t1 (a,b) VALUES (3,'c'),(4,'d');
+ ALTER TABLE t1 OPTIMIZE PARTITION p1;
+ Table Op Msg_type Msg_text
++test.t1 optimize note Table does not support optimize on partitions. All partitions will be rebuilt and analyzed.
+ test.t1 optimize status OK
+ INSERT INTO t2 (a,b) VALUES (4,'d');
+ ALTER TABLE t2 OPTIMIZE PARTITION p0 NO_WRITE_TO_BINLOG;
+ Table Op Msg_type Msg_text
++test.t2 optimize note Table does not support optimize on partitions. All partitions will be rebuilt and analyzed.
+ test.t2 optimize status OK
+ INSERT INTO t1 (a,b) VALUES (6,'f');
+ ALTER TABLE t1 OPTIMIZE PARTITION ALL LOCAL;
+ Table Op Msg_type Msg_text
++test.t1 optimize note Table does not support optimize on partitions. All partitions will be rebuilt and analyzed.
+ test.t1 optimize status OK
+ INSERT INTO t2 (a,b) VALUES (5,'e');
+ ALTER TABLE t2 OPTIMIZE PARTITION p1,p0;
+ Table Op Msg_type Msg_text
++test.t2 optimize note Table does not support optimize on partitions. All partitions will be rebuilt and analyzed.
+ test.t2 optimize status OK
+ DROP TABLE t1, t2;
+ DROP TABLE IF EXISTS t1,t2;
+@@ -30,25 +34,32 @@
+ INSERT INTO t1 (a,b) VALUES (3,'c'),(4,'d');
+ OPTIMIZE TABLE t1;
+ Table Op Msg_type Msg_text
++test.t1 optimize note Table does not support optimize, doing recreate + analyze instead
+ test.t1 optimize status OK
+ INSERT INTO t2 (a,b) VALUES (4,'d');
+ OPTIMIZE NO_WRITE_TO_BINLOG TABLE t2;
+ Table Op Msg_type Msg_text
++test.t2 optimize note Table does not support optimize, doing recreate + analyze instead
+ test.t2 optimize status OK
+ INSERT INTO t2 (a,b) VALUES (5,'e');
+ INSERT INTO t1 (a,b) VALUES (6,'f');
+ OPTIMIZE LOCAL TABLE t1, t2;
+ Table Op Msg_type Msg_text
++test.t1 optimize note Table does not support optimize, doing recreate + analyze instead
+ test.t1 optimize status OK
++test.t2 optimize note Table does not support optimize, doing recreate + analyze instead
+ test.t2 optimize status OK
+ OPTIMIZE TABLE t1, t2;
+ Table Op Msg_type Msg_text
++test.t1 optimize note Table does not support optimize, doing recreate + analyze instead
+ test.t1 optimize status OK
++test.t2 optimize note Table does not support optimize, doing recreate + analyze instead
+ test.t2 optimize status OK
+ DROP TABLE t1, t2;
+ CREATE TABLE t1 (a <INT_COLUMN>, b <CHAR_COLUMN>, <CUSTOM_INDEX> (a)) ENGINE=<STORAGE_ENGINE> <CUSTOM_TABLE_OPTIONS> PARTITION BY HASH(a) PARTITIONS 2;
+ INSERT INTO t1 (a,b) VALUES (1,'a'),(100,'b'),(2,'c'),(3,'d');
+ OPTIMIZE TABLE t1;
+ Table Op Msg_type Msg_text
++test.t1 optimize note Table does not support optimize, doing recreate + analyze instead
+ test.t1 optimize status OK
+ DROP TABLE t1;
diff --git a/storage/xtradb/mysql-test/storage_engine/parts/repair_table.rdiff b/storage/xtradb/mysql-test/storage_engine/parts/repair_table.rdiff
new file mode 100644
index 00000000000..35b150e82d1
--- /dev/null
+++ b/storage/xtradb/mysql-test/storage_engine/parts/repair_table.rdiff
@@ -0,0 +1,158 @@
+--- suite/storage_engine/parts/repair_table.result 2013-07-18 22:55:38.000000000 +0400
++++ suite/storage_engine/parts/repair_table.reject 2013-08-05 19:54:09.000000000 +0400
+@@ -25,7 +25,7 @@
+ INSERT INTO t1 (a,b) VALUES (10,'j');
+ ALTER TABLE t1 REPAIR PARTITION p1 QUICK USE_FRM;
+ Table Op Msg_type Msg_text
+-test.t1 repair status OK
++test.t1 repair note The storage engine for the table doesn't support repair
+ INSERT INTO t2 (a,b) VALUES (12,'l');
+ ALTER TABLE t2 REPAIR PARTITION NO_WRITE_TO_BINLOG ALL QUICK EXTENDED USE_FRM;
+ Table Op Msg_type Msg_text
+@@ -58,8 +58,8 @@
+ INSERT INTO t2 (a,b) VALUES (11,'k');
+ REPAIR TABLE t1, t2 QUICK USE_FRM;
+ Table Op Msg_type Msg_text
+-test.t1 repair status OK
+-test.t2 repair status OK
++test.t1 repair note The storage engine for the table doesn't support repair
++test.t2 repair note The storage engine for the table doesn't support repair
+ INSERT INTO t1 (a,b) VALUES (12,'l');
+ INSERT INTO t2 (a,b) VALUES (13,'m');
+ REPAIR NO_WRITE_TO_BINLOG TABLE t1, t2 QUICK EXTENDED USE_FRM;
+@@ -101,119 +101,13 @@
+ INSERT INTO t1 (a,b) VALUES (10,'j');
+ REPAIR TABLE t1 USE_FRM;
+ Table Op Msg_type Msg_text
+-test.t1 repair status OK
+-t1#P#p0.MYD
+-t1#P#p0.MYI
+-t1#P#p1.MYD
+-t1#P#p1.MYI
++test.t1 repair note The storage engine for the table doesn't support repair
+ t1.frm
+ t1.par
+ INSERT INTO t1 (a,b) VALUES (14,'n'),(15,'o');
+ # Statement ended with one of expected results (0,144).
+ # If you got a difference in error message, just add it to rdiff file
+ FLUSH TABLE t1;
+-Restoring <DATADIR>/test/t1#P#p0.MYD
+-CHECK TABLE t1;
+-Table Op Msg_type Msg_text
+-test.t1 check error Size of datafile is: 26 Should be: 39
+-test.t1 check error Partition p0 returned error
+-test.t1 check error Corrupt
+-SELECT a,b FROM t1;
+-a b
+-8 h
+-10 j
+-7 g
+-15 o
+-Warnings:
+-Error 145 Table './test/t1#P#p0' is marked as crashed and should be repaired
+-Error 1194 Table 't1' is marked as crashed and should be repaired
+-Error 1034 Number of rows changed from 3 to 2
+-# Statement ended with one of expected results (0,ER_NOT_KEYFILE,144).
+-# If you got a difference in error message, just add it to rdiff file
+-INSERT INTO t1 (a,b) VALUES (14,'n'),(15,'o');
+-# Statement ended with one of expected results (0,144).
+-# If you got a difference in error message, just add it to rdiff file
+-FLUSH TABLE t1;
+-Restoring <DATADIR>/test/t1#P#p0.MYI
+-CHECK TABLE t1;
+-Table Op Msg_type Msg_text
+-test.t1 check warning Size of datafile is: 39 Should be: 26
+-test.t1 check error Record-count is not ok; is 3 Should be: 2
+-test.t1 check warning Found 3 key parts. Should be: 2
+-test.t1 check error Partition p0 returned error
+-test.t1 check error Corrupt
+-SELECT a,b FROM t1;
+-a b
+-8 h
+-10 j
+-14 n
+-7 g
+-15 o
+-15 o
+-Warnings:
+-Error 145 Table './test/t1#P#p0' is marked as crashed and should be repaired
+-Error 1194 Table 't1' is marked as crashed and should be repaired
+-Error 1034 Number of rows changed from 2 to 3
+-# Statement ended with one of expected results (0,ER_NOT_KEYFILE,144).
+-# If you got a difference in error message, just add it to rdiff file
+-INSERT INTO t1 (a,b) VALUES (14,'n'),(15,'o');
+-# Statement ended with one of expected results (0,144).
+-# If you got a difference in error message, just add it to rdiff file
+-FLUSH TABLE t1;
+-Restoring <DATADIR>/test/t1#P#p1.MYD
+-CHECK TABLE t1;
+-Table Op Msg_type Msg_text
+-test.t1 check error Size of datafile is: 39 Should be: 52
+-test.t1 check error Partition p1 returned error
+-test.t1 check error Corrupt
+-SELECT a,b FROM t1;
+-a b
+-8 h
+-10 j
+-14 n
+-14 n
+-7 g
+-15 o
+-15 o
+-Warnings:
+-Error 145 Table './test/t1#P#p1' is marked as crashed and should be repaired
+-Error 1194 Table 't1' is marked as crashed and should be repaired
+-Error 1034 Number of rows changed from 4 to 3
+-# Statement ended with one of expected results (0,ER_NOT_KEYFILE,144).
+-# If you got a difference in error message, just add it to rdiff file
+-INSERT INTO t1 (a,b) VALUES (14,'n'),(15,'o');
+-# Statement ended with one of expected results (0,144).
+-# If you got a difference in error message, just add it to rdiff file
+-FLUSH TABLE t1;
+-Restoring <DATADIR>/test/t1#P#p1.MYI
+-CHECK TABLE t1;
+-Table Op Msg_type Msg_text
+-test.t1 check warning Size of datafile is: 52 Should be: 39
+-test.t1 check error Record-count is not ok; is 4 Should be: 3
+-test.t1 check warning Found 4 key parts. Should be: 3
+-test.t1 check error Partition p1 returned error
+-test.t1 check error Corrupt
+-SELECT a,b FROM t1;
+-a b
+-8 h
+-10 j
+-14 n
+-14 n
+-14 n
+-7 g
+-15 o
+-15 o
+-15 o
+-Warnings:
+-Error 145 Table './test/t1#P#p1' is marked as crashed and should be repaired
+-Error 1194 Table 't1' is marked as crashed and should be repaired
+-Error 1034 Number of rows changed from 3 to 4
+-# Statement ended with one of expected results (0,ER_NOT_KEYFILE,144).
+-# If you got a difference in error message, just add it to rdiff file
+-INSERT INTO t1 (a,b) VALUES (14,'n'),(15,'o');
+-# Statement ended with one of expected results (0,144).
+-# If you got a difference in error message, just add it to rdiff file
+-FLUSH TABLE t1;
+ Restoring <DATADIR>/test/t1.par
+ CHECK TABLE t1;
+ Table Op Msg_type Msg_text
+@@ -223,14 +117,8 @@
+ 8 h
+ 10 j
+ 14 n
+-14 n
+-14 n
+-14 n
+ 7 g
+ 15 o
+-15 o
+-15 o
+-15 o
+ # Statement ended with one of expected results (0,ER_NOT_KEYFILE,144).
+ # If you got a difference in error message, just add it to rdiff file
+ DROP TABLE t1;
diff --git a/storage/xtradb/mysql-test/storage_engine/parts/suite.opt b/storage/xtradb/mysql-test/storage_engine/parts/suite.opt
new file mode 100644
index 00000000000..66f581b56d0
--- /dev/null
+++ b/storage/xtradb/mysql-test/storage_engine/parts/suite.opt
@@ -0,0 +1,2 @@
+--innodb
+
diff --git a/storage/xtradb/mysql-test/storage_engine/repair_table.rdiff b/storage/xtradb/mysql-test/storage_engine/repair_table.rdiff
new file mode 100644
index 00000000000..be3709c5833
--- /dev/null
+++ b/storage/xtradb/mysql-test/storage_engine/repair_table.rdiff
@@ -0,0 +1,138 @@
+--- suite/storage_engine/repair_table.result 2013-10-03 20:35:06.000000000 +0400
++++ suite/storage_engine/repair_table.reject 2013-11-08 22:04:22.000000000 +0400
+@@ -4,56 +4,57 @@
+ CREATE TABLE t2 (a <INT_COLUMN>, b <CHAR_COLUMN>) ENGINE=<STORAGE_ENGINE> <CUSTOM_TABLE_OPTIONS>;
+ REPAIR TABLE t1;
+ Table Op Msg_type Msg_text
+-test.t1 repair status OK
++test.t1 repair note The storage engine for the table doesn't support repair
+ INSERT INTO t1 (a,b) VALUES (3,'c');
+ INSERT INTO t2 (a,b) VALUES (4,'d');
+ REPAIR NO_WRITE_TO_BINLOG TABLE t1, t2;
+ Table Op Msg_type Msg_text
+-test.t1 repair status OK
+-test.t2 repair status OK
++test.t1 repair note The storage engine for the table doesn't support repair
++test.t2 repair note The storage engine for the table doesn't support repair
+ INSERT INTO t2 (a,b) VALUES (5,'e'),(6,'f');
+ REPAIR LOCAL TABLE t2;
+ Table Op Msg_type Msg_text
+-test.t2 repair status OK
++test.t2 repair note The storage engine for the table doesn't support repair
+ INSERT INTO t1 (a,b) VALUES (7,'g'),(8,'h');
+ INSERT INTO t2 (a,b) VALUES (9,'i');
+ REPAIR LOCAL TABLE t2, t1 EXTENDED;
+ Table Op Msg_type Msg_text
+-test.t2 repair status OK
+-test.t1 repair status OK
++test.t2 repair note The storage engine for the table doesn't support repair
++test.t1 repair note The storage engine for the table doesn't support repair
+ INSERT INTO t1 (a,b) VALUES (10,'j');
+ INSERT INTO t2 (a,b) VALUES (11,'k');
+ REPAIR TABLE t1, t2 QUICK USE_FRM;
+ Table Op Msg_type Msg_text
+-test.t1 repair warning Number of rows changed from 0 to 6
+-test.t1 repair status OK
+-test.t2 repair warning Number of rows changed from 0 to 5
+-test.t2 repair status OK
++test.t1 repair note The storage engine for the table doesn't support repair
++test.t2 repair note The storage engine for the table doesn't support repair
+ INSERT INTO t1 (a,b) VALUES (12,'l');
+ INSERT INTO t2 (a,b) VALUES (13,'m');
+ REPAIR NO_WRITE_TO_BINLOG TABLE t1, t2 QUICK EXTENDED USE_FRM;
+ Table Op Msg_type Msg_text
+-test.t1 repair warning Number of rows changed from 0 to 7
+-test.t1 repair status OK
+-test.t2 repair warning Number of rows changed from 0 to 6
+-test.t2 repair status OK
++test.t1 repair note The storage engine for the table doesn't support repair
++test.t2 repair note The storage engine for the table doesn't support repair
+ FLUSH TABLE t1;
+ INSERT INTO t1 (a,b) VALUES (14,'n');
+-ERROR HY000: Incorrect file format 't1'
+ # Statement ended with one of expected results (0,130,ER_FAILED_READ_FROM_PAR_FILE,ER_OPEN_AS_READONLY).
+ # If you got a difference in error message, just add it to rdiff file
+ CHECK TABLE t1;
+ Table Op Msg_type Msg_text
+-test.t1 check Error Incorrect file format 't1'
+-test.t1 check error Corrupt
++test.t1 check status OK
+ SELECT a,b FROM t1;
+-ERROR HY000: Incorrect file format 't1'
++a b
++1 a
++2 b
++3 c
++7 g
++8 h
++10 j
++12 l
++14 n
+ # Statement ended with one of expected results (0,130,ER_FAILED_READ_FROM_PAR_FILE,ER_OPEN_AS_READONLY).
+ # If you got a difference in error message, just add it to rdiff file
+ REPAIR TABLE t1;
+ Table Op Msg_type Msg_text
+-test.t1 repair Error Incorrect file format 't1'
+-test.t1 repair error Corrupt
++test.t1 repair note The storage engine for the table doesn't support repair
+ DROP TABLE t1, t2;
+ call mtr.add_suppression("Got an error from thread_id=.*");
+ call mtr.add_suppression("MySQL thread id .*, query id .* localhost.*root Checking table");
+@@ -62,45 +63,32 @@
+ CREATE TABLE t1 (a <INT_COLUMN>, b <CHAR_COLUMN>, <CUSTOM_INDEX> (a)) ENGINE=<STORAGE_ENGINE> <CUSTOM_TABLE_OPTIONS>;
+ REPAIR TABLE t1;
+ Table Op Msg_type Msg_text
+-test.t1 repair status OK
++test.t1 repair note The storage engine for the table doesn't support repair
+ INSERT INTO t1 (a,b) VALUES (7,'g'),(8,'h');
+ REPAIR TABLE t1 EXTENDED;
+ Table Op Msg_type Msg_text
+-test.t1 repair status OK
++test.t1 repair note The storage engine for the table doesn't support repair
+ INSERT INTO t1 (a,b) VALUES (10,'j');
+ REPAIR TABLE t1 USE_FRM;
+ Table Op Msg_type Msg_text
+-test.t1 repair warning Number of rows changed from 0 to 3
+-test.t1 repair status OK
+-t1.MYD
+-t1.MYI
++test.t1 repair note The storage engine for the table doesn't support repair
+ t1.frm
++t1.ibd
+ INSERT INTO t1 (a,b) VALUES (14,'n'),(15,'o');
+ # Statement ended with one of expected results (0,144).
+ # If you got a difference in error message, just add it to rdiff file
+ FLUSH TABLE t1;
+-Restoring <DATADIR>/test/t1.MYD
++Restoring <DATADIR>/test/t1.ibd
+ CHECK TABLE t1;
+ Table Op Msg_type Msg_text
+-test.t1 check error Size of datafile is: 39 Should be: 65
+-test.t1 check error Corrupt
++test.t1 check status OK
+ SELECT a,b FROM t1;
+-ERROR HY000: Incorrect key file for table 't1'; try to repair it
+-# Statement ended with one of expected results (0,ER_NOT_KEYFILE,144).
+-# If you got a difference in error message, just add it to rdiff file
+-INSERT INTO t1 (a,b) VALUES (14,'n'),(15,'o');
+-ERROR HY000: Table './test/t1' is marked as crashed and last (automatic?) repair failed
+-# Statement ended with one of expected results (0,144).
+-# If you got a difference in error message, just add it to rdiff file
+-FLUSH TABLE t1;
+-Restoring <DATADIR>/test/t1.MYI
+-CHECK TABLE t1;
+-Table Op Msg_type Msg_text
+-test.t1 check warning Table is marked as crashed and last repair failed
+-test.t1 check error Size of datafile is: 39 Should be: 65
+-test.t1 check error Corrupt
+-SELECT a,b FROM t1;
+-ERROR HY000: Table './test/t1' is marked as crashed and last (automatic?) repair failed
++a b
++7 g
++8 h
++10 j
++14 n
++15 o
+ # Statement ended with one of expected results (0,ER_NOT_KEYFILE,144).
+ # If you got a difference in error message, just add it to rdiff file
+ DROP TABLE t1;
diff --git a/storage/xtradb/mysql-test/storage_engine/suite.opt b/storage/xtradb/mysql-test/storage_engine/suite.opt
new file mode 100644
index 00000000000..8c10cefc626
--- /dev/null
+++ b/storage/xtradb/mysql-test/storage_engine/suite.opt
@@ -0,0 +1 @@
+--innodb
diff --git a/storage/xtradb/mysql-test/storage_engine/tbl_opt_data_index_dir.rdiff b/storage/xtradb/mysql-test/storage_engine/tbl_opt_data_index_dir.rdiff
new file mode 100644
index 00000000000..e09e50b17ec
--- /dev/null
+++ b/storage/xtradb/mysql-test/storage_engine/tbl_opt_data_index_dir.rdiff
@@ -0,0 +1,23 @@
+--- suite/storage_engine/tbl_opt_data_index_dir.result 2013-10-03 20:35:06.000000000 +0400
++++ suite/storage_engine/tbl_opt_data_index_dir.reject 2013-11-08 22:06:54.000000000 +0400
+@@ -1,10 +1,12 @@
+ DROP TABLE IF EXISTS t1;
++Warnings:
++Warning 1618 <INDEX DIRECTORY> option ignored
+ SHOW CREATE TABLE t1;
+ Table Create Table
+ t1 CREATE TABLE `t1` (
+ `a` int(11) DEFAULT NULL,
+ `b` char(8) DEFAULT NULL
+-) ENGINE=<STORAGE_ENGINE> DEFAULT CHARSET=latin1 DATA DIRECTORY='<DATA_DIR>' INDEX DIRECTORY='<INDEX_DIR>'
++) ENGINE=<STORAGE_ENGINE> DEFAULT CHARSET=latin1 DATA DIRECTORY='<DATA_DIR>'
+ Warnings:
+ Warning 1618 <INDEX DIRECTORY> option ignored
+ SHOW CREATE TABLE t1;
+@@ -12,5 +14,5 @@
+ t1 CREATE TABLE `t1` (
+ `a` int(11) DEFAULT NULL,
+ `b` char(8) DEFAULT NULL
+-) ENGINE=<STORAGE_ENGINE> DEFAULT CHARSET=latin1 DATA DIRECTORY='<DATA_DIR>' INDEX DIRECTORY='<INDEX_DIR>'
++) ENGINE=<STORAGE_ENGINE> DEFAULT CHARSET=latin1 DATA DIRECTORY='<DATA_DIR>'
+ DROP TABLE t1;
diff --git a/storage/xtradb/mysql-test/storage_engine/tbl_opt_insert_method.rdiff b/storage/xtradb/mysql-test/storage_engine/tbl_opt_insert_method.rdiff
new file mode 100644
index 00000000000..468b82926f0
--- /dev/null
+++ b/storage/xtradb/mysql-test/storage_engine/tbl_opt_insert_method.rdiff
@@ -0,0 +1,11 @@
+--- suite/storage_engine/tbl_opt_insert_method.result 2012-06-24 23:55:19.539380000 +0400
++++ suite/storage_engine/tbl_opt_insert_method.reject 2012-07-15 17:51:09.978610512 +0400
+@@ -5,7 +5,7 @@
+ t1 CREATE TABLE `t1` (
+ `a` int(11) DEFAULT NULL,
+ `b` char(8) DEFAULT NULL
+-) ENGINE=<STORAGE_ENGINE> DEFAULT CHARSET=latin1 INSERT_METHOD=FIRST
++) ENGINE=<STORAGE_ENGINE> DEFAULT CHARSET=latin1
+ ALTER TABLE t1 INSERT_METHOD=NO;
+ SHOW CREATE TABLE t1;
+ Table Create Table
diff --git a/storage/xtradb/mysql-test/storage_engine/tbl_opt_key_block_size.opt b/storage/xtradb/mysql-test/storage_engine/tbl_opt_key_block_size.opt
new file mode 100644
index 00000000000..7cd737b2b87
--- /dev/null
+++ b/storage/xtradb/mysql-test/storage_engine/tbl_opt_key_block_size.opt
@@ -0,0 +1,3 @@
+--innodb-file-per-table=1
+--innodb-file-format=Barracuda
+
diff --git a/storage/xtradb/mysql-test/storage_engine/tbl_opt_row_format.opt b/storage/xtradb/mysql-test/storage_engine/tbl_opt_row_format.opt
new file mode 100644
index 00000000000..7cd737b2b87
--- /dev/null
+++ b/storage/xtradb/mysql-test/storage_engine/tbl_opt_row_format.opt
@@ -0,0 +1,3 @@
+--innodb-file-per-table=1
+--innodb-file-format=Barracuda
+
diff --git a/storage/xtradb/mysql-test/storage_engine/tbl_opt_row_format.rdiff b/storage/xtradb/mysql-test/storage_engine/tbl_opt_row_format.rdiff
new file mode 100644
index 00000000000..a6572ffa7f0
--- /dev/null
+++ b/storage/xtradb/mysql-test/storage_engine/tbl_opt_row_format.rdiff
@@ -0,0 +1,10 @@
+--- suite/storage_engine/tbl_opt_row_format.result 2012-06-24 23:55:19.539380000 +0400
++++ suite/storage_engine/tbl_opt_row_format.reject 2012-07-15 19:26:02.235049157 +0400
+@@ -1,5 +1,7 @@
+ DROP TABLE IF EXISTS t1;
+ CREATE TABLE t1 (a <INT_COLUMN>, b <CHAR_COLUMN>) ENGINE=<STORAGE_ENGINE> <CUSTOM_TABLE_OPTIONS> ROW_FORMAT=FIXED;
++Warnings:
++Warning 1478 <STORAGE_ENGINE>: assuming ROW_FORMAT=COMPACT.
+ SHOW CREATE TABLE t1;
+ Table Create Table
+ t1 CREATE TABLE `t1` (
diff --git a/storage/xtradb/mysql-test/storage_engine/tbl_opt_union.rdiff b/storage/xtradb/mysql-test/storage_engine/tbl_opt_union.rdiff
new file mode 100644
index 00000000000..cbdf5818022
--- /dev/null
+++ b/storage/xtradb/mysql-test/storage_engine/tbl_opt_union.rdiff
@@ -0,0 +1,16 @@
+--- suite/storage_engine/tbl_opt_union.result 2012-06-24 23:55:19.539380000 +0400
++++ suite/storage_engine/tbl_opt_union.reject 2012-07-15 17:51:31.014346053 +0400
+@@ -4,11 +4,11 @@
+ Table Create Table
+ t1 CREATE TABLE `t1` (
+ `a` int(11) DEFAULT NULL
+-) ENGINE=<STORAGE_ENGINE> DEFAULT CHARSET=latin1 UNION=(`child1`)
++) ENGINE=<STORAGE_ENGINE> DEFAULT CHARSET=latin1
+ ALTER TABLE t1 UNION = (child1,child2);
+ SHOW CREATE TABLE t1;
+ Table Create Table
+ t1 CREATE TABLE `t1` (
+ `a` int(11) DEFAULT NULL
+-) ENGINE=<STORAGE_ENGINE> DEFAULT CHARSET=latin1 UNION=(`child1`,`child2`)
++) ENGINE=<STORAGE_ENGINE> DEFAULT CHARSET=latin1
+ DROP TABLE t1, child1, child2;
diff --git a/storage/xtradb/mysql-test/storage_engine/trx/cons_snapshot_serializable.rdiff b/storage/xtradb/mysql-test/storage_engine/trx/cons_snapshot_serializable.rdiff
new file mode 100644
index 00000000000..e6149be58dc
--- /dev/null
+++ b/storage/xtradb/mysql-test/storage_engine/trx/cons_snapshot_serializable.rdiff
@@ -0,0 +1,18 @@
+--- suite/storage_engine/trx/cons_snapshot_serializable.result 2013-11-27 18:46:36.000000000 +0400
++++ suite/storage_engine/trx/cons_snapshot_serializable.reject 2013-11-28 19:17:02.000000000 +0400
+@@ -5,12 +5,15 @@
+ CREATE TABLE t1 (a <INT_COLUMN>) ENGINE=<STORAGE_ENGINE> <CUSTOM_TABLE_OPTIONS>;
+ SET SESSION TRANSACTION ISOLATION LEVEL SERIALIZABLE;
+ START TRANSACTION WITH CONSISTENT SNAPSHOT;
++Warnings:
++Warning 138 InnoDB: WITH CONSISTENT SNAPSHOT was ignored because this phrase can only be used with REPEATABLE READ isolation level.
+ connection con2;
+ INSERT INTO t1 (a) VALUES (1);
+ connection con1;
+ # If consistent read works on this isolation level (SERIALIZABLE), the following SELECT should not return the value we inserted (1)
+ SELECT a FROM t1;
+ a
++1
+ COMMIT;
+ connection default;
+ disconnect con1;
diff --git a/storage/xtradb/mysql-test/storage_engine/trx/level_read_committed.rdiff b/storage/xtradb/mysql-test/storage_engine/trx/level_read_committed.rdiff
new file mode 100644
index 00000000000..cb64d32138b
--- /dev/null
+++ b/storage/xtradb/mysql-test/storage_engine/trx/level_read_committed.rdiff
@@ -0,0 +1,11 @@
+--- suite/storage_engine/trx/level_read_committed.result 2013-11-28 19:18:48.000000000 +0400
++++ suite/storage_engine/trx/level_read_committed.reject 2013-11-28 19:18:59.000000000 +0400
+@@ -77,6 +77,8 @@
+ CREATE TABLE t1 (a <INT_COLUMN>) ENGINE=<STORAGE_ENGINE> <CUSTOM_TABLE_OPTIONS>;
+ SET SESSION TRANSACTION ISOLATION LEVEL READ COMMITTED;
+ START TRANSACTION WITH CONSISTENT SNAPSHOT;
++Warnings:
++Warning 138 InnoDB: WITH CONSISTENT SNAPSHOT was ignored because this phrase can only be used with REPEATABLE READ isolation level.
+ connection con2;
+ INSERT INTO t1 (a) VALUES (1);
+ connection con1;
diff --git a/storage/xtradb/mysql-test/storage_engine/trx/level_read_uncommitted.rdiff b/storage/xtradb/mysql-test/storage_engine/trx/level_read_uncommitted.rdiff
new file mode 100644
index 00000000000..6a79abe3ca5
--- /dev/null
+++ b/storage/xtradb/mysql-test/storage_engine/trx/level_read_uncommitted.rdiff
@@ -0,0 +1,11 @@
+--- suite/storage_engine/trx/level_read_uncommitted.result 2013-11-28 19:18:48.000000000 +0400
++++ suite/storage_engine/trx/level_read_uncommitted.reject 2013-11-28 19:19:50.000000000 +0400
+@@ -102,6 +102,8 @@
+ CREATE TABLE t1 (a <INT_COLUMN>) ENGINE=<STORAGE_ENGINE> <CUSTOM_TABLE_OPTIONS>;
+ SET SESSION TRANSACTION ISOLATION LEVEL READ UNCOMMITTED;
+ START TRANSACTION WITH CONSISTENT SNAPSHOT;
++Warnings:
++Warning 138 InnoDB: WITH CONSISTENT SNAPSHOT was ignored because this phrase can only be used with REPEATABLE READ isolation level.
+ connection con2;
+ INSERT INTO t1 (a) VALUES (1);
+ connection con1;
diff --git a/storage/xtradb/mysql-test/storage_engine/trx/suite.opt b/storage/xtradb/mysql-test/storage_engine/trx/suite.opt
new file mode 100644
index 00000000000..64bbe8b554c
--- /dev/null
+++ b/storage/xtradb/mysql-test/storage_engine/trx/suite.opt
@@ -0,0 +1,3 @@
+--innodb
+--innodb-lock-wait-timeout=1
+
diff --git a/storage/xtradb/mysql-test/storage_engine/type_blob.opt b/storage/xtradb/mysql-test/storage_engine/type_blob.opt
new file mode 100644
index 00000000000..40445305fc6
--- /dev/null
+++ b/storage/xtradb/mysql-test/storage_engine/type_blob.opt
@@ -0,0 +1 @@
+--innodb_log_file_size=100M
diff --git a/storage/xtradb/mysql-test/storage_engine/type_char_indexes.rdiff b/storage/xtradb/mysql-test/storage_engine/type_char_indexes.rdiff
new file mode 100644
index 00000000000..7a388552c57
--- /dev/null
+++ b/storage/xtradb/mysql-test/storage_engine/type_char_indexes.rdiff
@@ -0,0 +1,11 @@
+--- suite/storage_engine/type_char_indexes.result 2012-07-12 19:27:42.191013570 +0400
++++ suite/storage_engine/type_char_indexes.reject 2012-07-15 17:51:55.810034331 +0400
+@@ -135,7 +135,7 @@
+ r3a
+ EXPLAIN SELECT c,c20,v16,v128 FROM t1 WHERE v16 = 'varchar1a' OR v16 = 'varchar3a' ORDER BY v16;
+ id select_type table type possible_keys key key_len ref rows Extra
+-# # # range # v16 # # # #
++# # # ALL # NULL # # # #
+ SELECT c,c20,v16,v128 FROM t1 WHERE v16 = 'varchar1a' OR v16 = 'varchar3a' ORDER BY v16;
+ c c20 v16 v128
+ a char1 varchar1a varchar1b
diff --git a/storage/xtradb/mysql-test/storage_engine/type_float_indexes.rdiff b/storage/xtradb/mysql-test/storage_engine/type_float_indexes.rdiff
new file mode 100644
index 00000000000..6ebfd61d876
--- /dev/null
+++ b/storage/xtradb/mysql-test/storage_engine/type_float_indexes.rdiff
@@ -0,0 +1,11 @@
+--- suite/storage_engine/type_float_indexes.result 2012-07-12 19:37:27.031661128 +0400
++++ suite/storage_engine/type_float_indexes.reject 2012-07-15 17:52:12.189828410 +0400
+@@ -60,7 +60,7 @@
+ ALTER TABLE t1 ADD UNIQUE KEY(d);
+ EXPLAIN SELECT d FROM t1 WHERE r > 0 and d > 0 ORDER BY d;
+ id select_type table type possible_keys key key_len ref rows Extra
+-# # # # # d # # # #
++# # # # # NULL # # # #
+ SELECT d FROM t1 WHERE r > 0 and d > 0 ORDER BY d;
+ d
+ 1.2345
diff --git a/storage/xtradb/mysql-test/storage_engine/type_spatial_indexes.rdiff b/storage/xtradb/mysql-test/storage_engine/type_spatial_indexes.rdiff
new file mode 100644
index 00000000000..d3fb59e6ce3
--- /dev/null
+++ b/storage/xtradb/mysql-test/storage_engine/type_spatial_indexes.rdiff
@@ -0,0 +1,712 @@
+--- suite/storage_engine/type_spatial_indexes.result 2013-08-05 18:08:49.000000000 +0400
++++ suite/storage_engine/type_spatial_indexes.reject 2013-08-05 18:25:24.000000000 +0400
+@@ -702,699 +702,15 @@
+ DROP DATABASE IF EXISTS gis_ogs;
+ CREATE DATABASE gis_ogs;
+ CREATE TABLE gis_point (fid <INT_COLUMN>, g POINT NOT NULL, SPATIAL INDEX(g)) ENGINE=<STORAGE_ENGINE> <CUSTOM_TABLE_OPTIONS>;
+-CREATE TABLE gis_line (fid <INT_COLUMN>, g LINESTRING NOT NULL, SPATIAL INDEX(g)) ENGINE=<STORAGE_ENGINE> <CUSTOM_TABLE_OPTIONS>;
+-CREATE TABLE gis_polygon (fid <INT_COLUMN>, g POLYGON NOT NULL, SPATIAL INDEX(g)) ENGINE=<STORAGE_ENGINE> <CUSTOM_TABLE_OPTIONS>;
+-CREATE TABLE gis_multi_point (fid <INT_COLUMN>, g MULTIPOINT NOT NULL, SPATIAL INDEX(g)) ENGINE=<STORAGE_ENGINE> <CUSTOM_TABLE_OPTIONS>;
+-CREATE TABLE gis_multi_line (fid <INT_COLUMN>, g MULTILINESTRING NOT NULL, SPATIAL INDEX(g)) ENGINE=<STORAGE_ENGINE> <CUSTOM_TABLE_OPTIONS>;
+-CREATE TABLE gis_multi_polygon (fid <INT_COLUMN>, g MULTIPOLYGON NOT NULL, SPATIAL INDEX(g)) ENGINE=<STORAGE_ENGINE> <CUSTOM_TABLE_OPTIONS>;
+-CREATE TABLE gis_geometrycollection (fid <INT_COLUMN>, g GEOMETRYCOLLECTION NOT NULL, SPATIAL INDEX(g)) ENGINE=<STORAGE_ENGINE> <CUSTOM_TABLE_OPTIONS>;
+-CREATE TABLE gis_geometry (fid <INT_COLUMN>, g GEOMETRY NOT NULL) ENGINE=<STORAGE_ENGINE> <CUSTOM_TABLE_OPTIONS>;
+-USE gis_ogs;
+-CREATE TABLE lakes (fid INT <CUSTOM_COL_OPTIONS>,
+-name CHAR(64) <CUSTOM_COL_OPTIONS>,
+-shore POLYGON NOT NULL, SPATIAL INDEX s(shore)) ENGINE=<STORAGE_ENGINE> <CUSTOM_TABLE_OPTIONS>;
+-CREATE TABLE road_segments (fid INT <CUSTOM_COL_OPTIONS>,
+-name CHAR(64) <CUSTOM_COL_OPTIONS>,
+-aliases CHAR(64) <CUSTOM_COL_OPTIONS>,
+-num_lanes INT <CUSTOM_COL_OPTIONS>,
+-centerline LINESTRING NOT NULL, SPATIAL INDEX c(centerline)) ENGINE=<STORAGE_ENGINE> <CUSTOM_TABLE_OPTIONS>;
+-CREATE TABLE divided_routes (fid INT <CUSTOM_COL_OPTIONS>,
+-name CHAR(64) <CUSTOM_COL_OPTIONS>,
+-num_lanes INT <CUSTOM_COL_OPTIONS>,
+-centerlines MULTILINESTRING NOT NULL, SPATIAL INDEX c(centerlines)) ENGINE=<STORAGE_ENGINE> <CUSTOM_TABLE_OPTIONS>;
+-CREATE TABLE forests (fid INT <CUSTOM_COL_OPTIONS>,
+-name CHAR(64) <CUSTOM_COL_OPTIONS>,
+-boundary MULTIPOLYGON NOT NULL, SPATIAL INDEX b(boundary)) ENGINE=<STORAGE_ENGINE> <CUSTOM_TABLE_OPTIONS>;
+-CREATE TABLE bridges (fid INT <CUSTOM_COL_OPTIONS>,
+-name CHAR(64) <CUSTOM_COL_OPTIONS>,
+-position POINT NOT NULL, SPATIAL INDEX p(position)) ENGINE=<STORAGE_ENGINE> <CUSTOM_TABLE_OPTIONS>;
+-CREATE TABLE streams (fid INT <CUSTOM_COL_OPTIONS>,
+-name CHAR(64) <CUSTOM_COL_OPTIONS>,
+-centerline LINESTRING NOT NULL, SPATIAL INDEX c(centerline)) ENGINE=<STORAGE_ENGINE> <CUSTOM_TABLE_OPTIONS>;
+-CREATE TABLE buildings (fid INT <CUSTOM_COL_OPTIONS>,
+-name CHAR(64) <CUSTOM_COL_OPTIONS>,
+-position POINT NOT NULL,
+-footprint POLYGON NOT NULL, SPATIAL INDEX p(position), SPATIAL INDEX f(footprint)) ENGINE=<STORAGE_ENGINE> <CUSTOM_TABLE_OPTIONS>;
+-CREATE TABLE ponds (fid INT <CUSTOM_COL_OPTIONS>,
+-name CHAR(64) <CUSTOM_COL_OPTIONS>,
+-type CHAR(64) <CUSTOM_COL_OPTIONS>,
+-shores MULTIPOLYGON NOT NULL, SPATIAL INDEX s(shores)) ENGINE=<STORAGE_ENGINE> <CUSTOM_TABLE_OPTIONS>;
+-CREATE TABLE named_places (fid INT <CUSTOM_COL_OPTIONS>,
+-name CHAR(64) <CUSTOM_COL_OPTIONS>,
+-boundary POLYGON NOT NULL, SPATIAL INDEX b(boundary)) ENGINE=<STORAGE_ENGINE> <CUSTOM_TABLE_OPTIONS>;
+-CREATE TABLE map_neatlines (fid INT <CUSTOM_COL_OPTIONS>,
+-neatline POLYGON NOT NULL, SPATIAL INDEX n(neatline)) ENGINE=<STORAGE_ENGINE> <CUSTOM_TABLE_OPTIONS>;
+-USE test;
+-SHOW FIELDS FROM gis_point;
+-Field Type Null Key Default Extra
+-fid int(11) YES NULL
+-g point NO MUL NULL
+-SHOW FIELDS FROM gis_line;
+-Field Type Null Key Default Extra
+-fid int(11) YES NULL
+-g linestring NO MUL NULL
+-SHOW FIELDS FROM gis_polygon;
+-Field Type Null Key Default Extra
+-fid int(11) YES NULL
+-g polygon NO MUL NULL
+-SHOW FIELDS FROM gis_multi_point;
+-Field Type Null Key Default Extra
+-fid int(11) YES NULL
+-g multipoint NO MUL NULL
+-SHOW FIELDS FROM gis_multi_line;
+-Field Type Null Key Default Extra
+-fid int(11) YES NULL
+-g multilinestring NO MUL NULL
+-SHOW FIELDS FROM gis_multi_polygon;
+-Field Type Null Key Default Extra
+-fid int(11) YES NULL
+-g multipolygon NO MUL NULL
+-SHOW FIELDS FROM gis_geometrycollection;
+-Field Type Null Key Default Extra
+-fid int(11) YES NULL
+-g geometrycollection NO MUL NULL
+-SHOW FIELDS FROM gis_geometry;
+-Field Type Null Key Default Extra
+-fid int(11) YES NULL
+-g geometry NO NULL
+-INSERT INTO gis_point (fid,g) VALUES
+-(101, PointFromText('POINT(10 10)')),
+-(102, PointFromText('POINT(20 10)')),
+-(103, PointFromText('POINT(20 20)')),
+-(104, PointFromWKB(AsWKB(PointFromText('POINT(10 20)'))));
+-INSERT INTO gis_line (fid,g) VALUES
+-(105, LineFromText('LINESTRING(0 0,0 10,10 0)')),
+-(106, LineStringFromText('LINESTRING(10 10,20 10,20 20,10 20,10 10)')),
+-(107, LineStringFromWKB(AsWKB(LineString(Point(10, 10), Point(40, 10)))));
+-INSERT INTO gis_polygon (fid,g) VALUES
+-(108, PolygonFromText('POLYGON((10 10,20 10,20 20,10 20,10 10))')),
+-(109, PolyFromText('POLYGON((0 0,50 0,50 50,0 50,0 0), (10 10,20 10,20 20,10 20,10 10))')),
+-(110, PolyFromWKB(AsWKB(Polygon(LineString(Point(0, 0), Point(30, 0), Point(30, 30), Point(0, 0))))));
+-INSERT INTO gis_multi_point (fid,g) VALUES
+-(111, MultiPointFromText('MULTIPOINT(0 0,10 10,10 20,20 20)')),
+-(112, MPointFromText('MULTIPOINT(1 1,11 11,11 21,21 21)')),
+-(113, MPointFromWKB(AsWKB(MultiPoint(Point(3, 6), Point(4, 10)))));
+-INSERT INTO gis_multi_line (fid,g) VALUES
+-(114, MultiLineStringFromText('MULTILINESTRING((10 48,10 21,10 0),(16 0,16 23,16 48))')),
+-(115, MLineFromText('MULTILINESTRING((10 48,10 21,10 0))')),
+-(116, MLineFromWKB(AsWKB(MultiLineString(LineString(Point(1, 2), Point(3, 5)), LineString(Point(2, 5), Point(5, 8), Point(21, 7))))));
+-INSERT INTO gis_multi_polygon (fid,g) VALUES
+-(117, MultiPolygonFromText('MULTIPOLYGON(((28 26,28 0,84 0,84 42,28 26),(52 18,66 23,73 9,48 6,52 18)),((59 18,67 18,67 13,59 13,59 18)))')),
+-(118, MPolyFromText('MULTIPOLYGON(((28 26,28 0,84 0,84 42,28 26),(52 18,66 23,73 9,48 6,52 18)),((59 18,67 18,67 13,59 13,59 18)))')),
+-(119, MPolyFromWKB(AsWKB(MultiPolygon(Polygon(LineString(Point(0, 3), Point(3, 3), Point(3, 0), Point(0, 3)))))));
+-INSERT INTO gis_geometrycollection (fid,g) VALUES
+-(120, GeomCollFromText('GEOMETRYCOLLECTION(POINT(0 0), LINESTRING(0 0,10 10))')),
+-(121, GeometryFromWKB(AsWKB(GeometryCollection(Point(44, 6), LineString(Point(3, 6), Point(7, 9)))))),
+-(122, GeomFromText('GeometryCollection()')),
+-(123, GeomFromText('GeometryCollection EMPTY'));
+-INSERT into gis_geometry (fid,g) SELECT fid,g FROM gis_point;
+-INSERT into gis_geometry (fid,g) SELECT fid,g FROM gis_line;
+-INSERT into gis_geometry (fid,g) SELECT fid,g FROM gis_polygon;
+-INSERT into gis_geometry (fid,g) SELECT fid,g FROM gis_multi_point;
+-INSERT into gis_geometry (fid,g) SELECT fid,g FROM gis_multi_line;
+-INSERT into gis_geometry (fid,g) SELECT fid,g FROM gis_multi_polygon;
+-INSERT into gis_geometry (fid,g) SELECT fid,g FROM gis_geometrycollection;
+-SELECT fid, AsText(g) FROM gis_point;
+-fid AsText(g)
+-101 POINT(10 10)
+-102 POINT(20 10)
+-103 POINT(20 20)
+-104 POINT(10 20)
+-SELECT fid, AsText(g) FROM gis_line;
+-fid AsText(g)
+-105 LINESTRING(0 0,0 10,10 0)
+-106 LINESTRING(10 10,20 10,20 20,10 20,10 10)
+-107 LINESTRING(10 10,40 10)
+-SELECT fid, AsText(g) FROM gis_polygon;
+-fid AsText(g)
+-108 POLYGON((10 10,20 10,20 20,10 20,10 10))
+-109 POLYGON((0 0,50 0,50 50,0 50,0 0),(10 10,20 10,20 20,10 20,10 10))
+-110 POLYGON((0 0,30 0,30 30,0 0))
+-SELECT fid, AsText(g) FROM gis_multi_point;
+-fid AsText(g)
+-111 MULTIPOINT(0 0,10 10,10 20,20 20)
+-112 MULTIPOINT(1 1,11 11,11 21,21 21)
+-113 MULTIPOINT(3 6,4 10)
+-SELECT fid, AsText(g) FROM gis_multi_line;
+-fid AsText(g)
+-114 MULTILINESTRING((10 48,10 21,10 0),(16 0,16 23,16 48))
+-115 MULTILINESTRING((10 48,10 21,10 0))
+-116 MULTILINESTRING((1 2,3 5),(2 5,5 8,21 7))
+-SELECT fid, AsText(g) FROM gis_multi_polygon;
+-fid AsText(g)
+-117 MULTIPOLYGON(((28 26,28 0,84 0,84 42,28 26),(52 18,66 23,73 9,48 6,52 18)),((59 18,67 18,67 13,59 13,59 18)))
+-118 MULTIPOLYGON(((28 26,28 0,84 0,84 42,28 26),(52 18,66 23,73 9,48 6,52 18)),((59 18,67 18,67 13,59 13,59 18)))
+-119 MULTIPOLYGON(((0 3,3 3,3 0,0 3)))
+-SELECT fid, AsText(g) FROM gis_geometrycollection;
+-fid AsText(g)
+-120 GEOMETRYCOLLECTION(POINT(0 0),LINESTRING(0 0,10 10))
+-121 GEOMETRYCOLLECTION(POINT(44 6),LINESTRING(3 6,7 9))
+-122 GEOMETRYCOLLECTION EMPTY
+-123 GEOMETRYCOLLECTION EMPTY
+-SELECT fid, AsText(g) FROM gis_geometry;
+-fid AsText(g)
+-101 POINT(10 10)
+-102 POINT(20 10)
+-103 POINT(20 20)
+-104 POINT(10 20)
+-105 LINESTRING(0 0,0 10,10 0)
+-106 LINESTRING(10 10,20 10,20 20,10 20,10 10)
+-107 LINESTRING(10 10,40 10)
+-108 POLYGON((10 10,20 10,20 20,10 20,10 10))
+-109 POLYGON((0 0,50 0,50 50,0 50,0 0),(10 10,20 10,20 20,10 20,10 10))
+-110 POLYGON((0 0,30 0,30 30,0 0))
+-111 MULTIPOINT(0 0,10 10,10 20,20 20)
+-112 MULTIPOINT(1 1,11 11,11 21,21 21)
+-113 MULTIPOINT(3 6,4 10)
+-114 MULTILINESTRING((10 48,10 21,10 0),(16 0,16 23,16 48))
+-115 MULTILINESTRING((10 48,10 21,10 0))
+-116 MULTILINESTRING((1 2,3 5),(2 5,5 8,21 7))
+-117 MULTIPOLYGON(((28 26,28 0,84 0,84 42,28 26),(52 18,66 23,73 9,48 6,52 18)),((59 18,67 18,67 13,59 13,59 18)))
+-118 MULTIPOLYGON(((28 26,28 0,84 0,84 42,28 26),(52 18,66 23,73 9,48 6,52 18)),((59 18,67 18,67 13,59 13,59 18)))
+-119 MULTIPOLYGON(((0 3,3 3,3 0,0 3)))
+-120 GEOMETRYCOLLECTION(POINT(0 0),LINESTRING(0 0,10 10))
+-121 GEOMETRYCOLLECTION(POINT(44 6),LINESTRING(3 6,7 9))
+-122 GEOMETRYCOLLECTION EMPTY
+-123 GEOMETRYCOLLECTION EMPTY
+-SELECT fid, Dimension(g) FROM gis_geometry;
+-fid Dimension(g)
+-101 0
+-102 0
+-103 0
+-104 0
+-105 1
+-106 1
+-107 1
+-108 2
+-109 2
+-110 2
+-111 0
+-112 0
+-113 0
+-114 1
+-115 1
+-116 1
+-117 2
+-118 2
+-119 2
+-120 1
+-121 1
+-122 0
+-123 0
+-SELECT fid, GeometryType(g) FROM gis_geometry;
+-fid GeometryType(g)
+-101 POINT
+-102 POINT
+-103 POINT
+-104 POINT
+-105 LINESTRING
+-106 LINESTRING
+-107 LINESTRING
+-108 POLYGON
+-109 POLYGON
+-110 POLYGON
+-111 MULTIPOINT
+-112 MULTIPOINT
+-113 MULTIPOINT
+-114 MULTILINESTRING
+-115 MULTILINESTRING
+-116 MULTILINESTRING
+-117 MULTIPOLYGON
+-118 MULTIPOLYGON
+-119 MULTIPOLYGON
+-120 GEOMETRYCOLLECTION
+-121 GEOMETRYCOLLECTION
+-122 GEOMETRYCOLLECTION
+-123 GEOMETRYCOLLECTION
+-SELECT fid, IsEmpty(g) FROM gis_geometry;
+-fid IsEmpty(g)
+-101 0
+-102 0
+-103 0
+-104 0
+-105 0
+-106 0
+-107 0
+-108 0
+-109 0
+-110 0
+-111 0
+-112 0
+-113 0
+-114 0
+-115 0
+-116 0
+-117 0
+-118 0
+-119 0
+-120 0
+-121 0
+-122 0
+-123 0
+-SELECT fid, AsText(Envelope(g)) FROM gis_geometry;
+-fid AsText(Envelope(g))
+-101 POLYGON((10 10,10 10,10 10,10 10,10 10))
+-102 POLYGON((20 10,20 10,20 10,20 10,20 10))
+-103 POLYGON((20 20,20 20,20 20,20 20,20 20))
+-104 POLYGON((10 20,10 20,10 20,10 20,10 20))
+-105 POLYGON((0 0,10 0,10 10,0 10,0 0))
+-106 POLYGON((10 10,20 10,20 20,10 20,10 10))
+-107 POLYGON((10 10,40 10,40 10,10 10,10 10))
+-108 POLYGON((10 10,20 10,20 20,10 20,10 10))
+-109 POLYGON((0 0,50 0,50 50,0 50,0 0))
+-110 POLYGON((0 0,30 0,30 30,0 30,0 0))
+-111 POLYGON((0 0,20 0,20 20,0 20,0 0))
+-112 POLYGON((1 1,21 1,21 21,1 21,1 1))
+-113 POLYGON((3 6,4 6,4 10,3 10,3 6))
+-114 POLYGON((10 0,16 0,16 48,10 48,10 0))
+-115 POLYGON((10 0,10 0,10 48,10 48,10 0))
+-116 POLYGON((1 2,21 2,21 8,1 8,1 2))
+-117 POLYGON((28 0,84 0,84 42,28 42,28 0))
+-118 POLYGON((28 0,84 0,84 42,28 42,28 0))
+-119 POLYGON((0 0,3 0,3 3,0 3,0 0))
+-120 POLYGON((0 0,10 0,10 10,0 10,0 0))
+-121 POLYGON((3 6,44 6,44 9,3 9,3 6))
+-122 GEOMETRYCOLLECTION EMPTY
+-123 GEOMETRYCOLLECTION EMPTY
+-SELECT fid, X(g) FROM gis_point;
+-fid X(g)
+-101 10
+-102 20
+-103 20
+-104 10
+-SELECT fid, Y(g) FROM gis_point;
+-fid Y(g)
+-101 10
+-102 10
+-103 20
+-104 20
+-SELECT fid, AsText(StartPoint(g)) FROM gis_line;
+-fid AsText(StartPoint(g))
+-105 POINT(0 0)
+-106 POINT(10 10)
+-107 POINT(10 10)
+-SELECT fid, AsText(EndPoint(g)) FROM gis_line;
+-fid AsText(EndPoint(g))
+-105 POINT(10 0)
+-106 POINT(10 10)
+-107 POINT(40 10)
+-SELECT fid, GLength(g) FROM gis_line;
+-fid GLength(g)
+-105 24.14213562373095
+-106 40
+-107 30
+-SELECT fid, NumPoints(g) FROM gis_line;
+-fid NumPoints(g)
+-105 3
+-106 5
+-107 2
+-SELECT fid, AsText(PointN(g, 2)) FROM gis_line;
+-fid AsText(PointN(g, 2))
+-105 POINT(0 10)
+-106 POINT(20 10)
+-107 POINT(40 10)
+-SELECT fid, IsClosed(g) FROM gis_line;
+-fid IsClosed(g)
+-105 0
+-106 1
+-107 0
+-SELECT fid, AsText(Centroid(g)) FROM gis_polygon;
+-fid AsText(Centroid(g))
+-108 POINT(15 15)
+-109 POINT(25.416666666666668 25.416666666666668)
+-110 POINT(20 10)
+-SELECT fid, Area(g) FROM gis_polygon;
+-fid Area(g)
+-108 100
+-109 2400
+-110 450
+-SELECT fid, AsText(ExteriorRing(g)) FROM gis_polygon;
+-fid AsText(ExteriorRing(g))
+-108 LINESTRING(10 10,20 10,20 20,10 20,10 10)
+-109 LINESTRING(0 0,50 0,50 50,0 50,0 0)
+-110 LINESTRING(0 0,30 0,30 30,0 0)
+-SELECT fid, NumInteriorRings(g) FROM gis_polygon;
+-fid NumInteriorRings(g)
+-108 0
+-109 1
+-110 0
+-SELECT fid, AsText(InteriorRingN(g, 1)) FROM gis_polygon;
+-fid AsText(InteriorRingN(g, 1))
+-108 NULL
+-109 LINESTRING(10 10,20 10,20 20,10 20,10 10)
+-110 NULL
+-SELECT fid, IsClosed(g) FROM gis_multi_line;
+-fid IsClosed(g)
+-114 0
+-115 0
+-116 0
+-SELECT fid, AsText(Centroid(g)) FROM gis_multi_polygon;
+-fid AsText(Centroid(g))
+-117 POINT(55.58852775304245 17.426536064113982)
+-118 POINT(55.58852775304245 17.426536064113982)
+-119 POINT(2 2)
+-SELECT fid, Area(g) FROM gis_multi_polygon;
+-fid Area(g)
+-117 1684.5
+-118 1684.5
+-119 4.5
+-SELECT fid, NumGeometries(g) from gis_multi_point;
+-fid NumGeometries(g)
+-111 4
+-112 4
+-113 2
+-SELECT fid, NumGeometries(g) from gis_multi_line;
+-fid NumGeometries(g)
+-114 2
+-115 1
+-116 2
+-SELECT fid, NumGeometries(g) from gis_multi_polygon;
+-fid NumGeometries(g)
+-117 2
+-118 2
+-119 1
+-SELECT fid, NumGeometries(g) from gis_geometrycollection;
+-fid NumGeometries(g)
+-120 2
+-121 2
+-122 0
+-123 0
+-SELECT fid, AsText(GeometryN(g, 2)) from gis_multi_point;
+-fid AsText(GeometryN(g, 2))
+-111 POINT(10 10)
+-112 POINT(11 11)
+-113 POINT(4 10)
+-SELECT fid, AsText(GeometryN(g, 2)) from gis_multi_line;
+-fid AsText(GeometryN(g, 2))
+-114 LINESTRING(16 0,16 23,16 48)
+-115 NULL
+-116 LINESTRING(2 5,5 8,21 7)
+-SELECT fid, AsText(GeometryN(g, 2)) from gis_multi_polygon;
+-fid AsText(GeometryN(g, 2))
+-117 POLYGON((59 18,67 18,67 13,59 13,59 18))
+-118 POLYGON((59 18,67 18,67 13,59 13,59 18))
+-119 NULL
+-SELECT fid, AsText(GeometryN(g, 2)) from gis_geometrycollection;
+-fid AsText(GeometryN(g, 2))
+-120 LINESTRING(0 0,10 10)
+-121 LINESTRING(3 6,7 9)
+-122 NULL
+-123 NULL
+-SELECT fid, AsText(GeometryN(g, 1)) from gis_geometrycollection;
+-fid AsText(GeometryN(g, 1))
+-120 POINT(0 0)
+-121 POINT(44 6)
+-122 NULL
+-123 NULL
+-SELECT g1.fid as first, g2.fid as second,
+-Within(g1.g, g2.g) as w, Contains(g1.g, g2.g) as c, Overlaps(g1.g, g2.g) as o,
+-Equals(g1.g, g2.g) as e, Disjoint(g1.g, g2.g) as d, Touches(g1.g, g2.g) as t,
+-Intersects(g1.g, g2.g) as i, Crosses(g1.g, g2.g) as r
+-FROM gis_geometrycollection g1, gis_geometrycollection g2 ORDER BY first, second;
+-first second w c o e d t i r
+-120 120 1 1 0 1 0 1 1 0
+-120 121 0 0 1 0 0 0 1 0
+-120 122 NULL NULL NULL NULL NULL NULL NULL NULL
+-120 123 NULL NULL NULL NULL NULL NULL NULL NULL
+-121 120 0 0 1 0 0 0 1 0
+-121 121 1 1 0 1 0 1 1 0
+-121 122 NULL NULL NULL NULL NULL NULL NULL NULL
+-121 123 NULL NULL NULL NULL NULL NULL NULL NULL
+-122 120 NULL NULL NULL NULL NULL NULL NULL NULL
+-122 121 NULL NULL NULL NULL NULL NULL NULL NULL
+-122 122 NULL NULL NULL NULL NULL NULL NULL NULL
+-122 123 NULL NULL NULL NULL NULL NULL NULL NULL
+-123 120 NULL NULL NULL NULL NULL NULL NULL NULL
+-123 121 NULL NULL NULL NULL NULL NULL NULL NULL
+-123 122 NULL NULL NULL NULL NULL NULL NULL NULL
+-123 123 NULL NULL NULL NULL NULL NULL NULL NULL
+-DROP TABLE gis_point, gis_line, gis_polygon, gis_multi_point, gis_multi_line, gis_multi_polygon, gis_geometrycollection, gis_geometry;
+-USE gis_ogs;
+-# Lakes
+-INSERT INTO lakes (fid,name,shore) VALUES (
+-101, 'BLUE LAKE',
+-PolyFromText(
+-'POLYGON(
+- (52 18,66 23,73 9,48 6,52 18),
+- (59 18,67 18,67 13,59 13,59 18)
+- )',
+-101));
+-# Road Segments
+-INSERT INTO road_segments (fid,name,aliases,num_lanes,centerline) VALUES(102, 'Route 5', NULL, 2,
+-LineFromText(
+-'LINESTRING( 0 18, 10 21, 16 23, 28 26, 44 31 )' ,101));
+-INSERT INTO road_segments (fid,name,aliases,num_lanes,centerline) VALUES(103, 'Route 5', 'Main Street', 4,
+-LineFromText(
+-'LINESTRING( 44 31, 56 34, 70 38 )' ,101));
+-INSERT INTO road_segments (fid,name,aliases,num_lanes,centerline) VALUES(104, 'Route 5', NULL, 2,
+-LineFromText(
+-'LINESTRING( 70 38, 72 48 )' ,101));
+-INSERT INTO road_segments (fid,name,aliases,num_lanes,centerline) VALUES(105, 'Main Street', NULL, 4,
+-LineFromText(
+-'LINESTRING( 70 38, 84 42 )' ,101));
+-INSERT INTO road_segments (fid,name,aliases,num_lanes,centerline) VALUES(106, 'Dirt Road by Green Forest', NULL,
+-1,
+-LineFromText(
+-'LINESTRING( 28 26, 28 0 )',101));
+-# DividedRoutes
+-INSERT INTO divided_routes (fid,name,num_lanes,centerlines) VALUES(119, 'Route 75', 4,
+-MLineFromText(
+-'MULTILINESTRING((10 48,10 21,10 0),
+- (16 0,16 23,16 48))', 101));
+-# Forests
+-INSERT INTO forests (fid,name,boundary) VALUES(109, 'Green Forest',
+-MPolyFromText(
+-'MULTIPOLYGON(((28 26,28 0,84 0,84 42,28 26),
+- (52 18,66 23,73 9,48 6,52 18)),((59 18,67 18,67 13,59 13,59 18)))',
+-101));
+-# Bridges
+-INSERT INTO bridges (fid,name,position) VALUES(110, 'Cam Bridge', PointFromText(
+-'POINT( 44 31 )', 101));
+-# Streams
+-INSERT INTO streams (fid,name,centerline) VALUES(111, 'Cam Stream',
+-LineFromText(
+-'LINESTRING( 38 48, 44 41, 41 36, 44 31, 52 18 )', 101));
+-INSERT INTO streams (fid,name,centerline) VALUES(112, NULL,
+-LineFromText(
+-'LINESTRING( 76 0, 78 4, 73 9 )', 101));
+-# Buildings
+-INSERT INTO buildings (fid,name,position,footprint) VALUES(113, '123 Main Street',
+-PointFromText(
+-'POINT( 52 30 )', 101),
+-PolyFromText(
+-'POLYGON( ( 50 31, 54 31, 54 29, 50 29, 50 31) )', 101));
+-INSERT INTO buildings (fid,name,position,footprint) VALUES(114, '215 Main Street',
+-PointFromText(
+-'POINT( 64 33 )', 101),
+-PolyFromText(
+-'POLYGON( ( 66 34, 62 34, 62 32, 66 32, 66 34) )', 101));
+-# Ponds
+-INSERT INTO ponds (fid,name,type,shores) VALUES(120, NULL, 'Stock Pond',
+-MPolyFromText(
+-'MULTIPOLYGON( ( ( 24 44, 22 42, 24 40, 24 44) ),
+- ( ( 26 44, 26 40, 28 42, 26 44) ) )', 101));
+-# Named Places
+-INSERT INTO named_places (fid,name,boundary) VALUES(117, 'Ashton',
+-PolyFromText(
+-'POLYGON( ( 62 48, 84 48, 84 30, 56 30, 56 34, 62 48) )', 101));
+-INSERT INTO named_places (fid,name,boundary) VALUES(118, 'Goose Island',
+-PolyFromText(
+-'POLYGON( ( 67 13, 67 18, 59 18, 59 13, 67 13) )', 101));
+-# Map Neatlines
+-INSERT INTO map_neatlines (fid,neatline) VALUES(115,
+-PolyFromText(
+-'POLYGON( ( 0 0, 0 48, 84 48, 84 0, 0 0 ) )', 101));
+-SELECT Dimension(shore)
+-FROM lakes
+-WHERE name = 'Blue Lake';
+-Dimension(shore)
+-2
+-SELECT GeometryType(centerlines)
+-FROM divided_routes
+-WHERE name = 'Route 75';
+-GeometryType(centerlines)
+-MULTILINESTRING
+-SELECT AsText(boundary)
+-FROM named_places
+-WHERE name = 'Goose Island';
+-AsText(boundary)
+-POLYGON((67 13,67 18,59 18,59 13,67 13))
+-SELECT AsText(PolyFromWKB(AsBinary(boundary),101))
+-FROM named_places
+-WHERE name = 'Goose Island';
+-AsText(PolyFromWKB(AsBinary(boundary),101))
+-POLYGON((67 13,67 18,59 18,59 13,67 13))
+-SELECT SRID(boundary)
+-FROM named_places
+-WHERE name = 'Goose Island';
+-SRID(boundary)
+-101
+-SELECT IsEmpty(centerline)
+-FROM road_segments
+-WHERE name = 'Route 5'
+-AND aliases = 'Main Street';
+-IsEmpty(centerline)
+-0
+-SELECT AsText(Envelope(boundary))
+-FROM named_places
+-WHERE name = 'Goose Island';
+-AsText(Envelope(boundary))
+-POLYGON((59 13,67 13,67 18,59 18,59 13))
+-SELECT X(position)
+-FROM bridges
+-WHERE name = 'Cam Bridge';
+-X(position)
+-44
+-SELECT Y(position)
+-FROM bridges
+-WHERE name = 'Cam Bridge';
+-Y(position)
+-31
+-SELECT AsText(StartPoint(centerline))
+-FROM road_segments
+-WHERE fid = 102;
+-AsText(StartPoint(centerline))
+-POINT(0 18)
+-SELECT AsText(EndPoint(centerline))
+-FROM road_segments
+-WHERE fid = 102;
+-AsText(EndPoint(centerline))
+-POINT(44 31)
+-SELECT GLength(centerline)
+-FROM road_segments
+-WHERE fid = 106;
+-GLength(centerline)
+-26
+-SELECT NumPoints(centerline)
+-FROM road_segments
+-WHERE fid = 102;
+-NumPoints(centerline)
+-5
+-SELECT AsText(PointN(centerline, 1))
+-FROM road_segments
+-WHERE fid = 102;
+-AsText(PointN(centerline, 1))
+-POINT(0 18)
+-SELECT AsText(Centroid(boundary))
+-FROM named_places
+-WHERE name = 'Goose Island';
+-AsText(Centroid(boundary))
+-POINT(63 15.5)
+-SELECT Area(boundary)
+-FROM named_places
+-WHERE name = 'Goose Island';
+-Area(boundary)
+-40
+-SELECT AsText(ExteriorRing(shore))
+-FROM lakes
+-WHERE name = 'Blue Lake';
+-AsText(ExteriorRing(shore))
+-LINESTRING(52 18,66 23,73 9,48 6,52 18)
+-SELECT NumInteriorRings(shore)
+-FROM lakes
+-WHERE name = 'Blue Lake';
+-NumInteriorRings(shore)
+-1
+-SELECT AsText(InteriorRingN(shore, 1))
+-FROM lakes
+-WHERE name = 'Blue Lake';
+-AsText(InteriorRingN(shore, 1))
+-LINESTRING(59 18,67 18,67 13,59 13,59 18)
+-SELECT NumGeometries(centerlines)
+-FROM divided_routes
+-WHERE name = 'Route 75';
+-NumGeometries(centerlines)
+-2
+-SELECT AsText(GeometryN(centerlines, 2))
+-FROM divided_routes
+-WHERE name = 'Route 75';
+-AsText(GeometryN(centerlines, 2))
+-LINESTRING(16 0,16 23,16 48)
+-SELECT IsClosed(centerlines)
+-FROM divided_routes
+-WHERE name = 'Route 75';
+-IsClosed(centerlines)
+-0
+-SELECT GLength(centerlines)
+-FROM divided_routes
+-WHERE name = 'Route 75';
+-GLength(centerlines)
+-96
+-SELECT AsText(Centroid(shores))
+-FROM ponds
+-WHERE fid = 120;
+-AsText(Centroid(shores))
+-POINT(25 42)
+-SELECT Area(shores)
+-FROM ponds
+-WHERE fid = 120;
+-Area(shores)
+-8
+-SELECT ST_Equals(boundary,
+-PolyFromText('POLYGON( ( 67 13, 67 18, 59 18, 59 13, 67 13) )',1))
+-FROM named_places
+-WHERE name = 'Goose Island';
+-ST_Equals(boundary,
+-PolyFromText('POLYGON( ( 67 13, 67 18, 59 18, 59 13, 67 13) )',1))
+-1
+-SELECT ST_Disjoint(centerlines, boundary)
+-FROM divided_routes, named_places
+-WHERE divided_routes.name = 'Route 75'
+-AND named_places.name = 'Ashton';
+-ST_Disjoint(centerlines, boundary)
+-1
+-SELECT ST_Touches(centerline, shore)
+-FROM streams, lakes
+-WHERE streams.name = 'Cam Stream'
+-AND lakes.name = 'Blue Lake';
+-ST_Touches(centerline, shore)
+-1
+-SELECT Crosses(road_segments.centerline, divided_routes.centerlines)
+-FROM road_segments, divided_routes
+-WHERE road_segments.fid = 102
+-AND divided_routes.name = 'Route 75';
+-Crosses(road_segments.centerline, divided_routes.centerlines)
+-1
+-SELECT ST_Intersects(road_segments.centerline, divided_routes.centerlines)
+-FROM road_segments, divided_routes
+-WHERE road_segments.fid = 102
+-AND divided_routes.name = 'Route 75';
+-ST_Intersects(road_segments.centerline, divided_routes.centerlines)
+-1
+-SELECT ST_Contains(forests.boundary, named_places.boundary)
+-FROM forests, named_places
+-WHERE forests.name = 'Green Forest'
+-AND named_places.name = 'Ashton';
+-ST_Contains(forests.boundary, named_places.boundary)
+-0
+-SELECT ST_Distance(position, boundary)
+-FROM bridges, named_places
+-WHERE bridges.name = 'Cam Bridge'
+-AND named_places.name = 'Ashton';
+-ST_Distance(position, boundary)
+-12
+-SELECT AsText(ST_Difference(named_places.boundary, forests.boundary))
+-FROM named_places, forests
+-WHERE named_places.name = 'Ashton'
+-AND forests.name = 'Green Forest';
+-AsText(ST_Difference(named_places.boundary, forests.boundary))
+-POLYGON((56 34,62 48,84 48,84 42,56 34))
+-SELECT AsText(ST_Union(shore, boundary))
+-FROM lakes, named_places
+-WHERE lakes.name = 'Blue Lake'
+-AND named_places.name = 'Goose Island';
+-AsText(ST_Union(shore, boundary))
+-POLYGON((48 6,52 18,66 23,73 9,48 6))
+-SELECT AsText(ST_SymDifference(shore, boundary))
+-FROM lakes, named_places
+-WHERE lakes.name = 'Blue Lake'
+-AND named_places.name = 'Ashton';
+-AsText(ST_SymDifference(shore, boundary))
+-MULTIPOLYGON(((48 6,52 18,66 23,73 9,48 6),(59 13,59 18,67 18,67 13,59 13)),((56 30,56 34,62 48,84 48,84 30,56 30)))
+-SELECT count(*)
+-FROM buildings, bridges
+-WHERE ST_Contains(ST_Buffer(bridges.position, 15.0), buildings.footprint) = 1;
+-count(*)
+-1
++ERROR HY000: The storage engine <STORAGE_ENGINE> doesn't support SPATIAL indexes
++# ERROR: Statement ended with errno 1464, errname ER_TABLE_CANT_HANDLE_SPKEYS (expected to succeed)
++# ------------ UNEXPECTED RESULT ------------
++# [ CREATE TABLE gis_point (fid INT(11) /*!*/ /*Custom column options*/, g POINT NOT NULL, SPATIAL INDEX(g)) ENGINE=InnoDB /*!*/ /*Custom table options*/ ]
++# The statement|command finished with ER_TABLE_CANT_HANDLE_SPKEYS.
++# Geometry types or spatial indexes or the mix could be unsupported|malfunctioning, or the problem was caused by previous errors.
++# You can change the engine code, or create an rdiff, or disable the test by adding it to disabled.def.
++# Further in this test, the message might sometimes be suppressed; a part of the test might be skipped.
++# Also, this problem may cause a chain effect (more errors of different kinds in the test).
++# -------------------------------------------
+ DROP DATABASE gis_ogs;
+ USE test;
diff --git a/storage/xtradb/mysql-test/storage_engine/type_text.opt b/storage/xtradb/mysql-test/storage_engine/type_text.opt
new file mode 100644
index 00000000000..40445305fc6
--- /dev/null
+++ b/storage/xtradb/mysql-test/storage_engine/type_text.opt
@@ -0,0 +1 @@
+--innodb_log_file_size=100M
diff --git a/storage/xtradb/os/os0file.cc b/storage/xtradb/os/os0file.cc
index 9a999fe832f..2ddba0e0f6d 100644
--- a/storage/xtradb/os/os0file.cc
+++ b/storage/xtradb/os/os0file.cc
@@ -1997,7 +1997,7 @@ os_file_delete_if_exists_func(
bool ret;
ulint count = 0;
loop:
- /* In Windows, deleting an .ibd file may fail if ibbackup is copying
+ /* In Windows, deleting an .ibd file may fail if mysqlbackup is copying
it */
ret = DeleteFile((LPCTSTR) name);
@@ -2022,7 +2022,7 @@ loop:
ib_logf(IB_LOG_LEVEL_WARN, "Delete of file %s failed.", name);
}
- os_thread_sleep(1000000); /* sleep for a second */
+ os_thread_sleep(500000); /* sleep for 0.5 second */
if (count > 2000) {
@@ -2060,7 +2060,7 @@ os_file_delete_func(
BOOL ret;
ulint count = 0;
loop:
- /* In Windows, deleting an .ibd file may fail if ibbackup is copying
+ /* In Windows, deleting an .ibd file may fail if mysqlbackup is copying
it */
ret = DeleteFile((LPCTSTR) name);
@@ -2083,7 +2083,7 @@ loop:
fprintf(stderr,
"InnoDB: Warning: cannot delete file %s\n"
- "InnoDB: Are you running ibbackup"
+ "InnoDB: Are you running mysqlbackup"
" to back up the file?\n", name);
}
diff --git a/storage/xtradb/os/os0stacktrace.cc b/storage/xtradb/os/os0stacktrace.cc
index f7fb1212e5f..c4c428e0db3 100644
--- a/storage/xtradb/os/os0stacktrace.cc
+++ b/storage/xtradb/os/os0stacktrace.cc
@@ -85,7 +85,7 @@ os_stacktrace_print(
caller_address = (void*) uc->uc_mcontext.gregs[REG_RIP] ;
#elif defined(__hppa__)
ucontext_t* uc = (ucontext_t*) ucontext;
- caller_address = (void*) uc->uc_mcontext.sc_iaoq[0] & ~0x3UL ;
+ caller_address = (void*) (uc->uc_mcontext.sc_iaoq[0] & ~0x3UL) ;
#elif (defined (__ppc__)) || (defined (__powerpc__))
ucontext_t* uc = (ucontext_t*) ucontext;
caller_address = (void*) uc->uc_mcontext.regs->nip ;
diff --git a/storage/xtradb/page/page0zip.cc b/storage/xtradb/page/page0zip.cc
index c4c8354aa1e..cb97e666e75 100644
--- a/storage/xtradb/page/page0zip.cc
+++ b/storage/xtradb/page/page0zip.cc
@@ -3283,24 +3283,8 @@ page_zip_validate_low(
temp_page_buf = static_cast<byte*>(ut_malloc(2 * UNIV_PAGE_SIZE));
temp_page = static_cast<byte*>(ut_align(temp_page_buf, UNIV_PAGE_SIZE));
-#ifdef UNIV_DEBUG_VALGRIND
- /* Get detailed information on the valid bits in case the
- UNIV_MEM_ASSERT_RW() checks fail. The v-bits of page[],
- page_zip->data[] or page_zip could be viewed at temp_page[] or
- temp_page_zip in a debugger when running valgrind --db-attach. */
- (void) VALGRIND_GET_VBITS(page, temp_page, UNIV_PAGE_SIZE);
UNIV_MEM_ASSERT_RW(page, UNIV_PAGE_SIZE);
-# if UNIV_WORD_SIZE == 4
- VALGRIND_GET_VBITS(page_zip, &temp_page_zip, sizeof temp_page_zip);
- /* On 32-bit systems, there is no padding in page_zip_des_t.
- On other systems, Valgrind could complain about uninitialized
- pad bytes. */
- UNIV_MEM_ASSERT_RW(page_zip, sizeof *page_zip);
-# endif
- (void) VALGRIND_GET_VBITS(page_zip->data, temp_page,
- page_zip_get_size(page_zip));
UNIV_MEM_ASSERT_RW(page_zip->data, page_zip_get_size(page_zip));
-#endif /* UNIV_DEBUG_VALGRIND */
temp_page_zip = *page_zip;
valid = page_zip_decompress(&temp_page_zip, temp_page, TRUE);
diff --git a/storage/xtradb/row/row0ins.cc b/storage/xtradb/row/row0ins.cc
index ecbf9425f43..c0396a96cfc 100644
--- a/storage/xtradb/row/row0ins.cc
+++ b/storage/xtradb/row/row0ins.cc
@@ -1745,12 +1745,11 @@ do_possible_lock_wait:
table case (check_ref == 0), since MDL lock will prevent
concurrent DDL and DML on the same table */
if (!check_ref) {
- for (const dict_foreign_t* check_foreign
- = UT_LIST_GET_FIRST( table->referenced_list);
- check_foreign;
- check_foreign = UT_LIST_GET_NEXT(
- referenced_list, check_foreign)) {
- if (check_foreign == foreign) {
+ for (dict_foreign_set::iterator it
+ = table->referenced_set.begin();
+ it != table->referenced_set.end();
+ ++it) {
+ if (*it == foreign) {
verified = true;
break;
}
@@ -1803,12 +1802,15 @@ row_ins_check_foreign_constraints(
trx = thr_get_trx(thr);
- foreign = UT_LIST_GET_FIRST(table->foreign_list);
-
DEBUG_SYNC_C_IF_THD(thr_get_trx(thr)->mysql_thd,
"foreign_constraint_check_for_ins");
- while (foreign) {
+ for (dict_foreign_set::iterator it = table->foreign_set.begin();
+ it != table->foreign_set.end();
+ ++it) {
+
+ foreign = *it;
+
if (foreign->foreign_index == index) {
dict_table_t* ref_table = NULL;
dict_table_t* foreign_table = foreign->foreign_table;
@@ -1864,8 +1866,6 @@ row_ins_check_foreign_constraints(
return(err);
}
}
-
- foreign = UT_LIST_GET_NEXT(foreign_list, foreign);
}
return(DB_SUCCESS);
@@ -2915,7 +2915,7 @@ row_ins_clust_index_entry(
dberr_t err;
ulint n_uniq;
- if (UT_LIST_GET_FIRST(index->table->foreign_list)) {
+ if (!index->table->foreign_set.empty()) {
err = row_ins_check_foreign_constraints(
index->table, index, entry, thr);
if (err != DB_SUCCESS) {
@@ -2973,7 +2973,7 @@ row_ins_sec_index_entry(
mem_heap_t* offsets_heap;
mem_heap_t* heap;
- if (UT_LIST_GET_FIRST(index->table->foreign_list)) {
+ if (!index->table->foreign_set.empty()) {
err = row_ins_check_foreign_constraints(index->table, index,
entry, thr);
if (err != DB_SUCCESS) {
diff --git a/storage/xtradb/row/row0mysql.cc b/storage/xtradb/row/row0mysql.cc
index 671714c5b3d..ebf991e6ff8 100644
--- a/storage/xtradb/row/row0mysql.cc
+++ b/storage/xtradb/row/row0mysql.cc
@@ -1,6 +1,6 @@
/*****************************************************************************
-Copyright (c) 2000, 2013, Oracle and/or its affiliates. All Rights Reserved.
+Copyright (c) 2000, 2014, Oracle and/or its affiliates. All Rights Reserved.
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
@@ -62,6 +62,7 @@ Created 9/17/2000 Heikki Tuuri
#include "m_string.h"
#include "my_sys.h"
#include "ha_prototypes.h"
+#include <algorithm>
/** Provide optional 4.x backwards compatibility for 5.0 and above */
UNIV_INTERN ibool row_rollback_on_timeout = FALSE;
@@ -1576,8 +1577,6 @@ init_fts_doc_id_for_ref(
{
dict_foreign_t* foreign;
- foreign = UT_LIST_GET_FIRST(table->referenced_list);
-
table->fk_max_recusive_level = 0;
(*depth)++;
@@ -1589,17 +1588,25 @@ init_fts_doc_id_for_ref(
/* Loop through this table's referenced list and also
recursively traverse each table's foreign table list */
- while (foreign && foreign->foreign_table) {
- if (foreign->foreign_table->fts) {
- fts_init_doc_id(foreign->foreign_table);
+ for (dict_foreign_set::iterator it = table->referenced_set.begin();
+ it != table->referenced_set.end();
+ ++it) {
+
+ foreign = *it;
+
+ if (foreign->foreign_table == NULL) {
+ break;
}
- if (UT_LIST_GET_LEN(foreign->foreign_table->referenced_list)
- > 0 && foreign->foreign_table != table) {
- init_fts_doc_id_for_ref(foreign->foreign_table, depth);
+ if (foreign->foreign_table->fts != NULL) {
+ fts_init_doc_id(foreign->foreign_table);
}
- foreign = UT_LIST_GET_NEXT(referenced_list, foreign);
+ if (!foreign->foreign_table->referenced_set.empty()
+ && foreign->foreign_table != table) {
+ init_fts_doc_id_for_ref(
+ foreign->foreign_table, depth);
+ }
}
}
@@ -2839,43 +2846,47 @@ row_discard_tablespace_foreign_key_checks(
const trx_t* trx, /*!< in: transaction handle */
const dict_table_t* table) /*!< in: table to be discarded */
{
- const dict_foreign_t* foreign;
+
+ if (srv_read_only_mode || !trx->check_foreigns) {
+ return(DB_SUCCESS);
+ }
/* Check if the table is referenced by foreign key constraints from
some other table (not the table itself) */
+ dict_foreign_set::iterator it
+ = std::find_if(table->referenced_set.begin(),
+ table->referenced_set.end(),
+ dict_foreign_different_tables());
- for (foreign = UT_LIST_GET_FIRST(table->referenced_list);
- foreign && foreign->foreign_table == table;
- foreign = UT_LIST_GET_NEXT(referenced_list, foreign)) {
-
+ if (it == table->referenced_set.end()) {
+ return(DB_SUCCESS);
}
- if (!srv_read_only_mode && foreign && trx->check_foreigns) {
+ const dict_foreign_t* foreign = *it;
+ FILE* ef = dict_foreign_err_file;
- FILE* ef = dict_foreign_err_file;
+ ut_ad(foreign->foreign_table != table);
+ ut_ad(foreign->referenced_table == table);
- /* We only allow discarding a referenced table if
- FOREIGN_KEY_CHECKS is set to 0 */
+ /* We only allow discarding a referenced table if
+ FOREIGN_KEY_CHECKS is set to 0 */
- mutex_enter(&dict_foreign_err_mutex);
+ mutex_enter(&dict_foreign_err_mutex);
- rewind(ef);
+ rewind(ef);
- ut_print_timestamp(ef);
+ ut_print_timestamp(ef);
- fputs(" Cannot DISCARD table ", ef);
- ut_print_name(stderr, trx, TRUE, table->name);
- fputs("\n"
- "because it is referenced by ", ef);
- ut_print_name(stderr, trx, TRUE, foreign->foreign_table_name);
- putc('\n', ef);
+ fputs(" Cannot DISCARD table ", ef);
+ ut_print_name(stderr, trx, TRUE, table->name);
+ fputs("\n"
+ "because it is referenced by ", ef);
+ ut_print_name(stderr, trx, TRUE, foreign->foreign_table_name);
+ putc('\n', ef);
- mutex_exit(&dict_foreign_err_mutex);
-
- return(DB_CANNOT_DROP_CONSTRAINT);
- }
+ mutex_exit(&dict_foreign_err_mutex);
- return(DB_SUCCESS);
+ return(DB_CANNOT_DROP_CONSTRAINT);
}
/*********************************************************************//**
@@ -3178,7 +3189,6 @@ row_truncate_table_for_mysql(
dict_table_t* table, /*!< in: table handle */
trx_t* trx) /*!< in: transaction handle */
{
- dict_foreign_t* foreign;
dberr_t err;
mem_heap_t* heap;
byte* buf;
@@ -3270,18 +3280,17 @@ row_truncate_table_for_mysql(
/* Check if the table is referenced by foreign key constraints from
some other table (not the table itself) */
- for (foreign = UT_LIST_GET_FIRST(table->referenced_list);
- foreign != 0 && foreign->foreign_table == table;
- foreign = UT_LIST_GET_NEXT(referenced_list, foreign)) {
-
- /* Do nothing. */
- }
+ dict_foreign_set::iterator it
+ = std::find_if(table->referenced_set.begin(),
+ table->referenced_set.end(),
+ dict_foreign_different_tables());
if (!srv_read_only_mode
- && foreign
+ && it != table->referenced_set.end()
&& trx->check_foreigns) {
- FILE* ef = dict_foreign_err_file;
+ FILE* ef = dict_foreign_err_file;
+ dict_foreign_t* foreign = *it;
/* We only allow truncating a referenced table if
FOREIGN_KEY_CHECKS is set to 0 */
@@ -3882,42 +3891,45 @@ row_drop_table_for_mysql(
/* Check if the table is referenced by foreign key constraints from
some other table (not the table itself) */
- foreign = UT_LIST_GET_FIRST(table->referenced_list);
+ if (!srv_read_only_mode && trx->check_foreigns) {
- while (foreign && foreign->foreign_table == table) {
-check_next_foreign:
- foreign = UT_LIST_GET_NEXT(referenced_list, foreign);
- }
+ for (dict_foreign_set::iterator it
+ = table->referenced_set.begin();
+ it != table->referenced_set.end();
+ ++it) {
- if (!srv_read_only_mode
- && foreign
- && trx->check_foreigns
- && !(drop_db && dict_tables_have_same_db(
- name, foreign->foreign_table_name_lookup))) {
- FILE* ef = dict_foreign_err_file;
+ foreign = *it;
- /* We only allow dropping a referenced table if
- FOREIGN_KEY_CHECKS is set to 0 */
+ const bool ref_ok = drop_db
+ && dict_tables_have_same_db(
+ name,
+ foreign->foreign_table_name_lookup);
- err = DB_CANNOT_DROP_CONSTRAINT;
+ if (foreign->foreign_table != table && !ref_ok) {
- mutex_enter(&dict_foreign_err_mutex);
- rewind(ef);
- ut_print_timestamp(ef);
+ FILE* ef = dict_foreign_err_file;
- fputs(" Cannot drop table ", ef);
- ut_print_name(ef, trx, TRUE, name);
- fputs("\n"
- "because it is referenced by ", ef);
- ut_print_name(ef, trx, TRUE, foreign->foreign_table_name);
- putc('\n', ef);
- mutex_exit(&dict_foreign_err_mutex);
+ /* We only allow dropping a referenced table
+ if FOREIGN_KEY_CHECKS is set to 0 */
- goto funct_exit;
- }
+ err = DB_CANNOT_DROP_CONSTRAINT;
+
+ mutex_enter(&dict_foreign_err_mutex);
+ rewind(ef);
+ ut_print_timestamp(ef);
- if (foreign && trx->check_foreigns) {
- goto check_next_foreign;
+ fputs(" Cannot drop table ", ef);
+ ut_print_name(ef, trx, TRUE, name);
+ fputs("\n"
+ "because it is referenced by ", ef);
+ ut_print_name(ef, trx, TRUE,
+ foreign->foreign_table_name);
+ putc('\n', ef);
+ mutex_exit(&dict_foreign_err_mutex);
+
+ goto funct_exit;
+ }
+ }
}
/* TODO: could we replace the counter n_foreign_key_checks_running
diff --git a/storage/xtradb/row/row0upd.cc b/storage/xtradb/row/row0upd.cc
index bdd2a691368..53da8fea77e 100644
--- a/storage/xtradb/row/row0upd.cc
+++ b/storage/xtradb/row/row0upd.cc
@@ -53,11 +53,12 @@ Created 12/27/1996 Heikki Tuuri
#include "pars0sym.h"
#include "eval0eval.h"
#include "buf0lru.h"
+#include <algorithm>
+
#ifdef WITH_WSREP
extern my_bool wsrep_debug;
#endif
-
/* What kind of latch and lock can we assume when the control comes to
-------------------------------------------------------------------
an update node?
@@ -141,12 +142,10 @@ row_upd_index_is_referenced(
trx_t* trx) /*!< in: transaction */
{
dict_table_t* table = index->table;
- dict_foreign_t* foreign;
ibool froze_data_dict = FALSE;
ibool is_referenced = FALSE;
- if (!UT_LIST_GET_FIRST(table->referenced_list)) {
-
+ if (table->referenced_set.empty()) {
return(FALSE);
}
@@ -155,19 +154,13 @@ row_upd_index_is_referenced(
froze_data_dict = TRUE;
}
- foreign = UT_LIST_GET_FIRST(table->referenced_list);
+ dict_foreign_set::iterator it
+ = std::find_if(table->referenced_set.begin(),
+ table->referenced_set.end(),
+ dict_foreign_with_index(index));
- while (foreign) {
- if (foreign->referenced_index == index) {
+ is_referenced = (it != table->referenced_set.end());
- is_referenced = TRUE;
- goto func_exit;
- }
-
- foreign = UT_LIST_GET_NEXT(referenced_list, foreign);
- }
-
-func_exit:
if (froze_data_dict) {
row_mysql_unfreeze_data_dictionary(trx);
}
@@ -188,8 +181,7 @@ wsrep_row_upd_index_is_foreign(
ibool froze_data_dict = FALSE;
ibool is_referenced = FALSE;
- if (!UT_LIST_GET_FIRST(table->foreign_list)) {
-
+ if (table->foreign_set.empty()) {
return(FALSE);
}
@@ -198,17 +190,18 @@ wsrep_row_upd_index_is_foreign(
froze_data_dict = TRUE;
}
- foreign = UT_LIST_GET_FIRST(table->foreign_list);
+ for (dict_foreign_set::iterator it= table->foreign_set.begin();
+ it != table->foreign_set.end();
+ ++ it)
+ {
+ foreign= *it;
- while (foreign) {
- if (foreign->foreign_index == index) {
-
- is_referenced = TRUE;
- goto func_exit;
- }
-
- foreign = UT_LIST_GET_NEXT(foreign_list, foreign);
- }
+ if (foreign->foreign_index == index)
+ {
+ is_referenced= TRUE;
+ goto func_exit;
+ }
+ }
func_exit:
if (froze_data_dict) {
@@ -249,7 +242,7 @@ row_upd_check_references_constraints(
dberr_t err;
ibool got_s_lock = FALSE;
- if (UT_LIST_GET_FIRST(table->referenced_list) == NULL) {
+ if (table->referenced_set.empty()) {
return(DB_SUCCESS);
}
@@ -276,9 +269,13 @@ row_upd_check_references_constraints(
}
run_again:
- foreign = UT_LIST_GET_FIRST(table->referenced_list);
- while (foreign) {
+ for (dict_foreign_set::iterator it = table->referenced_set.begin();
+ it != table->referenced_set.end();
+ ++it) {
+
+ foreign = *it;
+
/* Note that we may have an update which updates the index
record, but does NOT update the first fields which are
referenced in a foreign key constraint. Then the update does
@@ -331,8 +328,6 @@ run_again:
goto func_exit;
}
}
-
- foreign = UT_LIST_GET_NEXT(referenced_list, foreign);
}
err = DB_SUCCESS;
@@ -369,8 +364,7 @@ wsrep_row_upd_check_foreign_constraints(
ibool got_s_lock = FALSE;
ibool opened = FALSE;
- if (UT_LIST_GET_FIRST(table->foreign_list) == NULL) {
-
+ if (table->foreign_set.empty()) {
return(DB_SUCCESS);
}
@@ -396,9 +390,12 @@ wsrep_row_upd_check_foreign_constraints(
row_mysql_freeze_data_dictionary(trx);
}
- foreign = UT_LIST_GET_FIRST(table->foreign_list);
+ for (dict_foreign_set::iterator it= table->foreign_set.begin();
+ it != table->foreign_set.end();
+ ++ it)
+ {
+ foreign= *it;
- while (foreign) {
/* Note that we may have an update which updates the index
record, but does NOT update the first fields which are
referenced in a foreign key constraint. Then the update does
@@ -448,8 +445,6 @@ wsrep_row_upd_check_foreign_constraints(
goto func_exit;
}
}
-
- foreign = UT_LIST_GET_NEXT(foreign_list, foreign);
}
err = DB_SUCCESS;
diff --git a/storage/xtradb/srv/srv0srv.cc b/storage/xtradb/srv/srv0srv.cc
index e8343b4c620..8b230c60221 100644
--- a/storage/xtradb/srv/srv0srv.cc
+++ b/storage/xtradb/srv/srv0srv.cc
@@ -491,7 +491,12 @@ UNIV_INTERN ulong srv_log_checksum_algorithm =
SRV_CHECKSUM_ALGORITHM_INNODB;
/*-------------------------------------------*/
+#ifdef HAVE_MEMORY_BARRIER
+/* No idea to wait long with memory barriers */
+UNIV_INTERN ulong srv_n_spin_wait_rounds = 15;
+#else
UNIV_INTERN ulong srv_n_spin_wait_rounds = 30;
+#endif
UNIV_INTERN ulong srv_spin_wait_delay = 6;
UNIV_INTERN ibool srv_priority_boost = TRUE;
@@ -2116,9 +2121,10 @@ loop:
/* Try to track a strange bug reported by Harald Fuchs and others,
where the lsn seems to decrease at times */
- new_lsn = log_get_lsn();
+ /* We have to use nowait to ensure we don't block */
+ new_lsn= log_get_lsn_nowait();
- if (new_lsn < old_lsn) {
+ if (new_lsn && new_lsn < old_lsn) {
ut_print_timestamp(stderr);
fprintf(stderr,
" InnoDB: Error: old log sequence number " LSN_PF
@@ -2130,7 +2136,8 @@ loop:
ut_ad(0);
}
- old_lsn = new_lsn;
+ if (new_lsn)
+ old_lsn = new_lsn;
if (difftime(time(NULL), srv_last_monitor_time) > 60) {
/* We referesh InnoDB Monitor values so that averages are
diff --git a/storage/xtradb/srv/srv0start.cc b/storage/xtradb/srv/srv0start.cc
index f2a511520de..003ad305309 100644
--- a/storage/xtradb/srv/srv0start.cc
+++ b/storage/xtradb/srv/srv0start.cc
@@ -1566,6 +1566,7 @@ innobase_start_or_create_for_mysql(void)
char logfilename[10000];
char* logfile0 = NULL;
size_t dirnamelen;
+ bool sys_datafiles_created = false;
if (srv_force_recovery > SRV_FORCE_NO_TRX_UNDO) {
srv_read_only_mode = true;
@@ -1712,6 +1713,19 @@ innobase_start_or_create_for_mysql(void)
"" IB_ATOMICS_STARTUP_MSG "");
ib_logf(IB_LOG_LEVEL_INFO,
+ "" IB_MEMORY_BARRIER_STARTUP_MSG "");
+
+#ifndef HAVE_MEMORY_BARRIER
+#if defined __i386__ || defined __x86_64__ || defined _M_IX86 || defined _M_X64 || defined __WIN__
+#else
+ ib_logf(IB_LOG_LEVEL_WARN,
+ "MySQL was built without a memory barrier capability on this"
+ " architecture, which might allow a mutex/rw_lock violation"
+ " under high thread concurrency. This may cause a hang.");
+#endif /* IA32 or AMD64 */
+#endif /* HAVE_MEMORY_BARRIER */
+
+ ib_logf(IB_LOG_LEVEL_INFO,
"Compressed tables use zlib " ZLIB_VERSION
#ifdef UNIV_ZIP_DEBUG
" with validation"
@@ -2515,6 +2529,15 @@ files_checked:
dict_check = DICT_CHECK_NONE_LOADED;
}
+ /* Create the SYS_TABLESPACES and SYS_DATAFILES system table */
+ err = dict_create_or_check_sys_tablespace();
+ if (err != DB_SUCCESS) {
+ return(err);
+ }
+
+ sys_datafiles_created = true;
+
+ /* This function assumes that SYS_DATAFILES exists */
dict_check_tablespaces_and_store_max_id(dict_check);
}
@@ -2696,13 +2719,6 @@ files_checked:
srv_undo_logs = ULONG_UNDEFINED;
}
- /* Flush the changes made to TRX_SYS_PAGE by trx_sys_create_rsegs()*/
- if (!srv_force_recovery && !srv_read_only_mode) {
- bool success = buf_flush_list(ULINT_MAX, LSN_MAX, NULL);
- ut_a(success);
- buf_flush_wait_batch_end(NULL, BUF_FLUSH_LIST);
- }
-
if (!srv_read_only_mode) {
/* Create the thread which watches the timeouts
for lock waits */
@@ -2727,10 +2743,13 @@ files_checked:
return(err);
}
- /* Create the SYS_TABLESPACES system table */
- err = dict_create_or_check_sys_tablespace();
- if (err != DB_SUCCESS) {
- return(err);
+ /* Create the SYS_TABLESPACES and SYS_DATAFILES system tables if we
+ have not done that already on crash recovery. */
+ if (sys_datafiles_created == false) {
+ err = dict_create_or_check_sys_tablespace();
+ if (err != DB_SUCCESS) {
+ return(err);
+ }
}
srv_is_being_started = FALSE;
diff --git a/storage/xtradb/sync/sync0arr.cc b/storage/xtradb/sync/sync0arr.cc
index 95ecf496e82..7ad9fe8d40b 100644
--- a/storage/xtradb/sync/sync0arr.cc
+++ b/storage/xtradb/sync/sync0arr.cc
@@ -839,6 +839,7 @@ sync_arr_cell_can_wake_up(
cell->wait_object))->base_mutex;
}
+ os_rmb;
if (mutex_get_lock_word(mutex) == 0) {
return(TRUE);
@@ -849,6 +850,7 @@ sync_arr_cell_can_wake_up(
lock = static_cast<rw_lock_t*>(cell->wait_object);
+ os_rmb;
if (lock->lock_word > 0) {
/* Either unlocked or only read locked. */
@@ -860,6 +862,7 @@ sync_arr_cell_can_wake_up(
lock = static_cast<rw_lock_t*>(cell->wait_object);
/* lock_word == 0 means all readers have left */
+ os_rmb;
if (lock->lock_word == 0) {
return(TRUE);
@@ -869,6 +872,7 @@ sync_arr_cell_can_wake_up(
lock = static_cast<rw_lock_t*>(cell->wait_object);
/* lock_word > 0 means no writer or reserved writer */
+ os_rmb;
if (lock->lock_word > 0) {
return(TRUE);
diff --git a/storage/xtradb/sync/sync0rw.cc b/storage/xtradb/sync/sync0rw.cc
index 79741e3cdce..7fad78ea577 100644
--- a/storage/xtradb/sync/sync0rw.cc
+++ b/storage/xtradb/sync/sync0rw.cc
@@ -41,6 +41,7 @@ Created 9/11/1995 Heikki Tuuri
#include "srv0srv.h"
#include "os0sync.h" /* for INNODB_RW_LOCKS_USE_ATOMICS */
#include "ha_prototypes.h"
+#include "my_cpu.h"
/*
IMPLEMENTATION OF THE RW_LOCK
@@ -448,6 +449,8 @@ lock_loop:
lock)) {
/* Spin waiting for the writer field to become free */
+ os_rmb;
+ HMT_low();
while (i < SYNC_SPIN_ROUNDS && lock->lock_word <= 0) {
if (srv_spin_wait_delay) {
ut_delay(ut_rnd_interval(0,
@@ -455,9 +458,11 @@ lock_loop:
}
i++;
+ os_rmb;
}
- if (i == SYNC_SPIN_ROUNDS) {
+ HMT_medium();
+ if (i >= SYNC_SPIN_ROUNDS) {
os_thread_yield();
}
@@ -603,16 +608,26 @@ rw_lock_x_lock_wait(
counter_index = (size_t) os_thread_get_curr_id();
+ os_rmb;
ut_ad(lock->lock_word <= 0);
+ HMT_low();
+ if (high_priority) {
+
+ prio_rw_lock = reinterpret_cast<prio_rw_lock_t *>(lock);
+ prio_rw_lock->high_priority_wait_ex_waiter = 1;
+ }
+
while (lock->lock_word < 0) {
if (srv_spin_wait_delay) {
ut_delay(ut_rnd_interval(0, srv_spin_wait_delay));
}
if(i < SYNC_SPIN_ROUNDS) {
i++;
+ os_rmb;
continue;
}
+ HMT_medium();
/* If there is still a reader, then go to sleep.*/
rw_lock_stats.rw_x_spin_round_count.add(counter_index, i);
@@ -622,13 +637,6 @@ rw_lock_x_lock_wait(
file_name,
line, &index);
- if (high_priority) {
-
- prio_rw_lock
- = reinterpret_cast<prio_rw_lock_t *>(lock);
- prio_rw_lock->high_priority_wait_ex_waiter = 1;
- }
-
i = 0;
/* Check lock_word to ensure wake-up isn't missed.*/
@@ -655,12 +663,16 @@ rw_lock_x_lock_wait(
We must pass the while-loop check to proceed.*/
} else {
sync_array_free_cell(sync_arr, index);
- if (prio_rw_lock) {
-
- prio_rw_lock->high_priority_wait_ex_waiter = 0;
- }
}
+ HMT_low();
+ }
+ HMT_medium();
+
+ if (prio_rw_lock) {
+
+ prio_rw_lock->high_priority_wait_ex_waiter = 0;
}
+
rw_lock_stats.rw_x_spin_round_count.add(counter_index, i);
}
@@ -702,6 +714,10 @@ rw_lock_x_lock_low(
} else {
os_thread_id_t thread_id = os_thread_get_curr_id();
+ if (!pass) {
+ os_rmb;
+ }
+
/* Decrement failed: relock or failed lock */
if (!pass && lock->recursive
&& os_thread_eq(lock->writer_thread, thread_id)) {
@@ -792,6 +808,8 @@ lock_loop:
}
/* Spin waiting for the lock_word to become free */
+ os_rmb;
+ HMT_low();
while (i < SYNC_SPIN_ROUNDS
&& lock->lock_word <= 0) {
if (srv_spin_wait_delay) {
@@ -800,8 +818,10 @@ lock_loop:
}
i++;
+ os_rmb;
}
- if (i == SYNC_SPIN_ROUNDS) {
+ HMT_medium();
+ if (i >= SYNC_SPIN_ROUNDS) {
os_thread_yield();
} else {
goto lock_loop;
diff --git a/storage/xtradb/sync/sync0sync.cc b/storage/xtradb/sync/sync0sync.cc
index e078f223efc..67d4835ed95 100644
--- a/storage/xtradb/sync/sync0sync.cc
+++ b/storage/xtradb/sync/sync0sync.cc
@@ -46,6 +46,7 @@ Created 9/5/1995 Heikki Tuuri
# include "srv0start.h" /* srv_is_being_started */
#endif /* UNIV_SYNC_DEBUG */
#include "ha_prototypes.h"
+#include "my_cpu.h"
/*
REASONS FOR IMPLEMENTING THE SPIN LOCK MUTEX
@@ -535,6 +536,8 @@ mutex_set_waiters(
ptr = &(mutex->waiters);
+ os_wmb;
+
*ptr = n; /* Here we assume that the write of a single
word in memory is atomic */
}
@@ -587,15 +590,17 @@ mutex_loop:
spin_loop:
+ HMT_low();
+ os_rmb;
while (mutex_get_lock_word(mutex) != 0 && i < SYNC_SPIN_ROUNDS) {
if (srv_spin_wait_delay) {
ut_delay(ut_rnd_interval(0, srv_spin_wait_delay));
}
-
i++;
}
+ HMT_medium();
- if (i == SYNC_SPIN_ROUNDS) {
+ if (i >= SYNC_SPIN_ROUNDS) {
os_thread_yield();
}
diff --git a/storage/xtradb/trx/trx0sys.cc b/storage/xtradb/trx/trx0sys.cc
index 19d14bf6f38..e15dd65bbd7 100644
--- a/storage/xtradb/trx/trx0sys.cc
+++ b/storage/xtradb/trx/trx0sys.cc
@@ -1095,7 +1095,7 @@ trx_sys_print_mysql_binlog_offset_from_page(
== TRX_SYS_MYSQL_LOG_MAGIC_N) {
fprintf(stderr,
- "ibbackup: Last MySQL binlog file position %lu %lu,"
+ "mysqlbackup: Last MySQL binlog file position %lu %lu,"
" file name %s\n",
(ulong) mach_read_from_4(
sys_header + TRX_SYS_MYSQL_LOG_INFO
@@ -1146,9 +1146,9 @@ trx_sys_read_file_format_id(
ut_print_timestamp(stderr);
fprintf(stderr,
- " ibbackup: Error: trying to read system tablespace "
- "file format,\n"
- " ibbackup: but could not open the tablespace "
+ " mysqlbackup: Error: trying to read system "
+ "tablespace file format,\n"
+ " mysqlbackup: but could not open the tablespace "
"file %s!\n", pathname);
return(FALSE);
}
@@ -1165,9 +1165,9 @@ trx_sys_read_file_format_id(
ut_print_timestamp(stderr);
fprintf(stderr,
- " ibbackup: Error: trying to read system tablespace "
- "file format,\n"
- " ibbackup: but failed to read the tablespace "
+ " mysqlbackup: Error: trying to read system "
+ "tablespace file format,\n"
+ " mysqlbackup: but failed to read the tablespace "
"file %s!\n", pathname);
os_file_close(file);
@@ -1226,9 +1226,9 @@ trx_sys_read_pertable_file_format_id(
ut_print_timestamp(stderr);
fprintf(stderr,
- " ibbackup: Error: trying to read per-table "
+ " mysqlbackup: Error: trying to read per-table "
"tablespace format,\n"
- " ibbackup: but could not open the tablespace "
+ " mysqlbackup: but could not open the tablespace "
"file %s!\n", pathname);
return(FALSE);
@@ -1245,9 +1245,9 @@ trx_sys_read_pertable_file_format_id(
ut_print_timestamp(stderr);
fprintf(stderr,
- " ibbackup: Error: trying to per-table data file "
+ " mysqlbackup: Error: trying to per-table data file "
"format,\n"
- " ibbackup: but failed to read the tablespace "
+ " mysqlbackup: but failed to read the tablespace "
"file %s!\n", pathname);
os_file_close(file);