summaryrefslogtreecommitdiff
path: root/storage/innobase
diff options
context:
space:
mode:
Diffstat (limited to 'storage/innobase')
-rw-r--r--storage/innobase/CMakeLists.txt65
-rw-r--r--storage/innobase/btr/btr0cur.c351
-rw-r--r--storage/innobase/btr/btr0pcur.c21
-rw-r--r--storage/innobase/btr/btr0sea.c6
-rw-r--r--storage/innobase/buf/buf0lru.c18
-rw-r--r--storage/innobase/dict/dict0crea.c145
-rw-r--r--storage/innobase/dict/dict0dict.c529
-rw-r--r--storage/innobase/dict/dict0load.c20
-rw-r--r--storage/innobase/fil/fil0fil.c48
-rw-r--r--storage/innobase/ha/ha0ha.c6
-rw-r--r--storage/innobase/handler/ha_innodb.cc663
-rw-r--r--storage/innobase/handler/ha_innodb.h15
-rw-r--r--storage/innobase/handler/handler0alter.cc4
-rw-r--r--storage/innobase/handler/i_s.cc10
-rw-r--r--storage/innobase/ibuf/ibuf0ibuf.c8
-rw-r--r--storage/innobase/include/btr0cur.h22
-rw-r--r--storage/innobase/include/dict0crea.h11
-rw-r--r--storage/innobase/include/dict0dict.h12
-rw-r--r--storage/innobase/include/fil0fil.h8
-rw-r--r--storage/innobase/include/ha0ha.h10
-rw-r--r--storage/innobase/include/ha0ha.ic4
-rw-r--r--storage/innobase/include/ha_prototypes.h23
-rw-r--r--storage/innobase/include/log0log.h7
-rw-r--r--storage/innobase/include/log0log.ic20
-rw-r--r--storage/innobase/include/os0sync.h61
-rw-r--r--storage/innobase/include/os0sync.ic32
-rw-r--r--storage/innobase/include/srv0srv.h11
-rw-r--r--storage/innobase/include/sync0arr.h6
-rw-r--r--storage/innobase/include/sync0rw.h8
-rw-r--r--storage/innobase/include/sync0rw.ic13
-rw-r--r--storage/innobase/include/sync0sync.h5
-rw-r--r--storage/innobase/include/sync0sync.ic4
-rw-r--r--storage/innobase/include/trx0trx.h2
-rw-r--r--storage/innobase/include/univ.i2
-rw-r--r--storage/innobase/include/ut0ut.h10
-rw-r--r--storage/innobase/log/log0recv.c4
-rw-r--r--storage/innobase/mysql-test/storage_engine/alter_tablespace.opt2
-rw-r--r--storage/innobase/mysql-test/storage_engine/autoinc_secondary.rdiff30
-rw-r--r--storage/innobase/mysql-test/storage_engine/cache_index.rdiff71
-rw-r--r--storage/innobase/mysql-test/storage_engine/checksum_table_live.rdiff13
-rw-r--r--storage/innobase/mysql-test/storage_engine/define_engine.inc45
-rw-r--r--storage/innobase/mysql-test/storage_engine/disabled.def8
-rw-r--r--storage/innobase/mysql-test/storage_engine/fulltext_search.rdiff150
-rw-r--r--storage/innobase/mysql-test/storage_engine/index_enable_disable.rdiff33
-rw-r--r--storage/innobase/mysql-test/storage_engine/index_type_hash.rdiff60
-rw-r--r--storage/innobase/mysql-test/storage_engine/insert_delayed.rdiff26
-rw-r--r--storage/innobase/mysql-test/storage_engine/lock_concurrent.rdiff22
-rw-r--r--storage/innobase/mysql-test/storage_engine/optimize_table.rdiff37
-rw-r--r--storage/innobase/mysql-test/storage_engine/parts/checksum_table.rdiff22
-rw-r--r--storage/innobase/mysql-test/storage_engine/parts/create_table.rdiff20
-rw-r--r--storage/innobase/mysql-test/storage_engine/parts/optimize_table.rdiff58
-rw-r--r--storage/innobase/mysql-test/storage_engine/parts/repair_table.rdiff158
-rw-r--r--storage/innobase/mysql-test/storage_engine/parts/suite.opt4
-rw-r--r--storage/innobase/mysql-test/storage_engine/repair_table.rdiff129
-rw-r--r--storage/innobase/mysql-test/storage_engine/suite.opt4
-rw-r--r--storage/innobase/mysql-test/storage_engine/tbl_opt_data_index_dir.rdiff18
-rw-r--r--storage/innobase/mysql-test/storage_engine/tbl_opt_insert_method.rdiff11
-rw-r--r--storage/innobase/mysql-test/storage_engine/tbl_opt_key_block_size.opt3
-rw-r--r--storage/innobase/mysql-test/storage_engine/tbl_opt_row_format.opt3
-rw-r--r--storage/innobase/mysql-test/storage_engine/tbl_opt_row_format.rdiff10
-rw-r--r--storage/innobase/mysql-test/storage_engine/tbl_opt_union.rdiff16
-rw-r--r--storage/innobase/mysql-test/storage_engine/trx/cons_snapshot_serializable.rdiff18
-rw-r--r--storage/innobase/mysql-test/storage_engine/trx/level_read_committed.rdiff11
-rw-r--r--storage/innobase/mysql-test/storage_engine/trx/level_read_uncommitted.rdiff11
-rw-r--r--storage/innobase/mysql-test/storage_engine/trx/suite.opt5
-rw-r--r--storage/innobase/mysql-test/storage_engine/type_char_indexes.rdiff20
-rw-r--r--storage/innobase/mysql-test/storage_engine/type_float_indexes.rdiff11
-rw-r--r--storage/innobase/mysql-test/storage_engine/type_spatial_indexes.rdiff712
-rw-r--r--storage/innobase/mysql-test/storage_engine/vcol.rdiff82
-rw-r--r--storage/innobase/os/os0file.c96
-rw-r--r--storage/innobase/os/os0sync.c19
-rw-r--r--storage/innobase/os/os0thread.c6
-rw-r--r--storage/innobase/page/page0zip.c26
-rw-r--r--storage/innobase/plugin_exports13
-rw-r--r--storage/innobase/rem/rem0rec.c2
-rw-r--r--storage/innobase/row/row0mysql.c49
-rw-r--r--storage/innobase/row/row0sel.c35
-rw-r--r--storage/innobase/row/row0upd.c2
-rw-r--r--storage/innobase/srv/srv0srv.c20
-rw-r--r--storage/innobase/srv/srv0start.c24
-rw-r--r--storage/innobase/sync/sync0arr.c132
-rw-r--r--storage/innobase/sync/sync0rw.c61
-rw-r--r--storage/innobase/sync/sync0sync.c34
-rw-r--r--storage/innobase/trx/trx0i_s.c34
-rw-r--r--storage/innobase/trx/trx0sys.c2
-rw-r--r--storage/innobase/trx/trx0trx.c2
86 files changed, 4056 insertions, 508 deletions
diff --git a/storage/innobase/CMakeLists.txt b/storage/innobase/CMakeLists.txt
index a5fffac7ce1..cc494a7cd7a 100644
--- a/storage/innobase/CMakeLists.txt
+++ b/storage/innobase/CMakeLists.txt
@@ -97,6 +97,25 @@ IF(NOT CMAKE_CROSSCOMPILING)
}"
HAVE_IB_GCC_ATOMIC_TEST_AND_SET
)
+ 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)
@@ -107,6 +126,14 @@ IF(HAVE_IB_GCC_ATOMIC_TEST_AND_SET)
ADD_DEFINITIONS(-DHAVE_IB_GCC_ATOMIC_TEST_AND_SET=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(
@@ -133,6 +160,8 @@ IF(HAVE_IB_ATOMIC_PTHREAD_T_GCC)
ADD_DEFINITIONS(-DHAVE_IB_ATOMIC_PTHREAD_T_GCC=1)
ENDIF()
+CHECK_C_SOURCE_COMPILES("struct t1{ int a; char *b; }; struct t1 c= { .a=1, .b=0 }; main() { }" HAVE_C99_INITIALIZERS)
+
ENDIF(NOT MSVC)
# Solaris atomics
@@ -185,10 +214,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()
@@ -206,6 +246,7 @@ ENDIF()
IF(MSVC)
ADD_DEFINITIONS(-DHAVE_WINDOWS_ATOMICS)
+ ADD_DEFINITIONS(-DHAVE_WINDOWS_MM_FENCE)
ENDIF()
@@ -230,6 +271,15 @@ IF (MSVC AND CMAKE_SIZEOF_VOID_P EQUAL 8)
PROPERTIES COMPILE_FLAGS -Od)
ENDIF()
+IF(MSVC)
+ # 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()
+
SET(INNOBASE_SOURCES btr/btr0btr.c btr/btr0cur.c btr/btr0pcur.c btr/btr0sea.c
buf/buf0buddy.c buf/buf0buf.c buf/buf0flu.c buf/buf0lru.c buf/buf0rea.c
data/data0data.c data/data0type.c
@@ -276,7 +326,18 @@ IF(WITH_INNODB)
SET(WITH_INNOBASE_STORAGE_ENGINE TRUE)
ENDIF()
+
+# On solaris, reduce symbol visibility, so loader does not mix
+# the same symbols from builtin innodb and from shared one.
+# Only required for old GCC (3.4.3) that does not support hidden visibility
+IF(CMAKE_SYSTEM_NAME MATCHES "SunOS" AND CMAKE_COMPILER_IS_GNUCC
+ AND NOT HAVE_VISIBILITY_HIDDEN)
+ SET(LINKER_SCRIPT "-Wl,-M${CMAKE_CURRENT_SOURCE_DIR}/plugin_exports")
+ELSE()
+ SET(LINKER_SCRIPT)
+ENDIF()
+
MYSQL_ADD_PLUGIN(innobase ${INNOBASE_SOURCES} STORAGE_ENGINE
- DEFAULT
+ MODULE_ONLY
MODULE_OUTPUT_NAME ha_innodb
- LINK_LIBRARIES ${ZLIB_LIBRARY})
+ LINK_LIBRARIES ${ZLIB_LIBRARY} ${LINKER_SCRIPT})
diff --git a/storage/innobase/btr/btr0cur.c b/storage/innobase/btr/btr0cur.c
index b573329c527..3b533909e67 100644
--- a/storage/innobase/btr/btr0cur.c
+++ b/storage/innobase/btr/btr0cur.c
@@ -68,6 +68,7 @@ Created 10/16/1994 Heikki Tuuri
#include "ibuf0ibuf.h"
#include "lock0lock.h"
#include "zlib.h"
+#include "fil0fil.h"
/** Buffered B-tree operation types, introduced as part of delete buffering. */
typedef enum btr_op_enum {
@@ -258,23 +259,55 @@ btr_cur_latch_leaves(
get_block = btr_block_get(
space, zip_size, page_no, mode, cursor->index, mtr);
#ifdef UNIV_BTR_DEBUG
- ut_a(page_is_comp(get_block->frame) == page_is_comp(page));
+
+ if (page_is_comp(get_block->frame) != page_is_comp(page)) {
+ btr_pages_info(page, get_block->frame, space,
+ zip_size, page_no, latch_mode,
+ cursor->index,
+ btr_page_get_next(page, mtr),
+ btr_page_get_prev(page, mtr),
+ buf_block_get_space(get_block),
+ buf_block_get_zip_size(get_block),
+ btr_page_get_next(get_block->frame, mtr),
+ btr_page_get_prev(get_block->frame, mtr),
+ mtr, __FILE__, __LINE__);
+
+ fprintf(stderr, "InnoDB: Info: latch_mode == %lu mode == %lu\n", latch_mode, mode);
+
+ ut_a(page_is_comp(get_block->frame) == page_is_comp(page));
+ }
#endif /* UNIV_BTR_DEBUG */
get_block->check_index_page_at_flush = TRUE;
return;
case BTR_MODIFY_TREE:
/* x-latch also brothers from left to right */
left_page_no = btr_page_get_prev(page, mtr);
+ mode = latch_mode;
if (left_page_no != FIL_NULL) {
get_block = btr_block_get(
space, zip_size, left_page_no,
RW_X_LATCH, cursor->index, mtr);
#ifdef UNIV_BTR_DEBUG
- ut_a(page_is_comp(get_block->frame)
- == page_is_comp(page));
- ut_a(btr_page_get_next(get_block->frame, mtr)
- == page_get_page_no(page));
+ if (page_is_comp(get_block->frame) != page_is_comp(page)) {
+ btr_pages_info(page, get_block->frame, space,
+ zip_size, left_page_no, latch_mode,
+ cursor->index,
+ btr_page_get_next(page, mtr),
+ btr_page_get_prev(page, mtr),
+ buf_block_get_space(get_block),
+ buf_block_get_zip_size(get_block),
+ btr_page_get_next(get_block->frame, mtr),
+ btr_page_get_prev(get_block->frame, mtr),
+ mtr, __FILE__, __LINE__);
+
+ fprintf(stderr, "InnoDB: Info: latch_mode %lu mode %lu\n", latch_mode, mode);
+
+ ut_a(page_is_comp(get_block->frame)
+ == page_is_comp(page));
+ ut_a(btr_page_get_next(get_block->frame, mtr)
+ == page_get_page_no(page));
+ }
#endif /* UNIV_BTR_DEBUG */
get_block->check_index_page_at_flush = TRUE;
}
@@ -283,7 +316,21 @@ btr_cur_latch_leaves(
space, zip_size, page_no,
RW_X_LATCH, cursor->index, mtr);
#ifdef UNIV_BTR_DEBUG
- ut_a(page_is_comp(get_block->frame) == page_is_comp(page));
+ if (page_is_comp(get_block->frame) != page_is_comp(page)) {
+ btr_pages_info(page, get_block->frame, space,
+ zip_size, page_no, latch_mode,
+ cursor->index,
+ btr_page_get_next(page, mtr),
+ btr_page_get_prev(page, mtr),
+ buf_block_get_space(get_block),
+ buf_block_get_zip_size(get_block),
+ btr_page_get_next(get_block->frame, mtr),
+ btr_page_get_prev(get_block->frame, mtr),
+ mtr, __FILE__, __LINE__);
+
+ fprintf(stderr, "InnoDB: Info: mode %lu\n", mode);
+ ut_a(page_is_comp(get_block->frame) == page_is_comp(page));
+ }
#endif /* UNIV_BTR_DEBUG */
get_block->check_index_page_at_flush = TRUE;
@@ -294,10 +341,24 @@ btr_cur_latch_leaves(
space, zip_size, right_page_no,
RW_X_LATCH, cursor->index, mtr);
#ifdef UNIV_BTR_DEBUG
- ut_a(page_is_comp(get_block->frame)
- == page_is_comp(page));
- ut_a(btr_page_get_prev(get_block->frame, mtr)
- == page_get_page_no(page));
+ if (page_is_comp(get_block->frame) != page_is_comp(page)) {
+ btr_pages_info(page, get_block->frame, space,
+ zip_size, right_page_no, latch_mode,
+ cursor->index,
+ btr_page_get_next(page, mtr),
+ btr_page_get_prev(page, mtr),
+ buf_block_get_space(get_block),
+ buf_block_get_zip_size(get_block),
+ btr_page_get_next(get_block->frame, mtr),
+ btr_page_get_prev(get_block->frame, mtr),
+ mtr, __FILE__, __LINE__);
+
+ fprintf(stderr, "InnoDB: Info: latch_mode %lu mode %lu\n", latch_mode, mode);
+ ut_a(page_is_comp(get_block->frame)
+ == page_is_comp(page));
+ ut_a(btr_page_get_prev(get_block->frame, mtr)
+ == page_get_page_no(page));
+ }
#endif /* UNIV_BTR_DEBUG */
get_block->check_index_page_at_flush = TRUE;
}
@@ -316,10 +377,24 @@ btr_cur_latch_leaves(
left_page_no, mode, cursor->index, mtr);
cursor->left_block = get_block;
#ifdef UNIV_BTR_DEBUG
- ut_a(page_is_comp(get_block->frame)
- == page_is_comp(page));
- ut_a(btr_page_get_next(get_block->frame, mtr)
- == page_get_page_no(page));
+ if (page_is_comp(get_block->frame) != page_is_comp(page)) {
+ btr_pages_info(page, get_block->frame, space,
+ zip_size, left_page_no, latch_mode,
+ cursor->index,
+ btr_page_get_next(page, mtr),
+ btr_page_get_prev(page, mtr),
+ buf_block_get_space(get_block),
+ buf_block_get_zip_size(get_block),
+ btr_page_get_next(get_block->frame, mtr),
+ btr_page_get_prev(get_block->frame, mtr),
+ mtr, __FILE__, __LINE__);
+
+ fprintf(stderr, "InnoDB: Info: latch_mode %lu mode %lu\n", latch_mode, mode);
+ ut_a(page_is_comp(get_block->frame)
+ == page_is_comp(page));
+ ut_a(btr_page_get_next(get_block->frame, mtr)
+ == page_get_page_no(page));
+ }
#endif /* UNIV_BTR_DEBUG */
get_block->check_index_page_at_flush = TRUE;
}
@@ -327,7 +402,22 @@ btr_cur_latch_leaves(
get_block = btr_block_get(
space, zip_size, page_no, mode, cursor->index, mtr);
#ifdef UNIV_BTR_DEBUG
- ut_a(page_is_comp(get_block->frame) == page_is_comp(page));
+ if (page_is_comp(get_block->frame) != page_is_comp(page)) {
+ btr_pages_info(page, get_block->frame, space,
+ zip_size, page_no, latch_mode,
+ cursor->index,
+ btr_page_get_next(page, mtr),
+ btr_page_get_prev(page, mtr),
+ buf_block_get_space(get_block),
+ buf_block_get_zip_size(get_block),
+ btr_page_get_next(get_block->frame, mtr),
+ btr_page_get_prev(get_block->frame, mtr),
+ mtr, __FILE__, __LINE__);
+
+ fprintf(stderr, "InnoDB: Info: latch_mode %lu mode %lu\n", latch_mode, mode);
+
+ ut_a(page_is_comp(get_block->frame) == page_is_comp(page));
+ }
#endif /* UNIV_BTR_DEBUG */
get_block->check_index_page_at_flush = TRUE;
return;
@@ -3649,8 +3739,8 @@ btr_estimate_number_of_different_key_vals(
ib_int64_t* n_diff;
ib_int64_t* n_not_null;
ibool stats_null_not_equal;
- ullint n_sample_pages; /* number of pages to sample */
- ulint not_empty_flag = 0;
+ ullint n_sample_pages = 1; /* number of pages to sample */
+ ulint not_empty_flag = 0;
ulint total_external_size = 0;
ulint i;
ulint j;
@@ -3695,17 +3785,62 @@ btr_estimate_number_of_different_key_vals(
ut_error;
}
- /* It makes no sense to test more pages than are contained
- in the index, thus we lower the number if it is too high */
- if (srv_stats_sample_pages > index->stat_index_size) {
- if (index->stat_index_size > 0) {
- n_sample_pages = index->stat_index_size;
+ if (srv_stats_sample_traditional) {
+ /* It makes no sense to test more pages than are contained
+ in the index, thus we lower the number if it is too high */
+ if (srv_stats_sample_pages > index->stat_index_size) {
+ if (index->stat_index_size > 0) {
+ n_sample_pages = index->stat_index_size;
+ }
} else {
- n_sample_pages = 1;
+ n_sample_pages = srv_stats_sample_pages;
}
} else {
- n_sample_pages = srv_stats_sample_pages;
- }
+ /* New logaritmic number of pages that are estimated.
+ Number of pages estimated should be between 1 and
+ index->stat_index_size.
+
+ If we have only 0 or 1 index pages then we can only take 1
+ sample. We have already initialized n_sample_pages to 1.
+
+ So taking index size as I and sample as S and log(I)*S as L
+
+ requirement 1) we want the out limit of the expression to not exceed I;
+ requirement 2) we want the ideal pages to be at least S;
+ so the current expression is min(I, max( min(S,I), L)
+
+ looking for simplifications:
+
+ case 1: assume S < I
+ min(I, max( min(S,I), L) -> min(I , max( S, L))
+
+ but since L=LOG2(I)*S and log2(I) >=1 L>S always so max(S,L) = L.
+
+ so we have: min(I , L)
+
+ case 2: assume I < S
+ min(I, max( min(S,I), L) -> min(I, max( I, L))
+
+ case 2a: L > I
+ min(I, max( I, L)) -> min(I, L) -> I
+
+ case 2b: when L < I
+ min(I, max( I, L)) -> min(I, I ) -> I
+
+ so taking all case2 paths is I, our expression is:
+ n_pages = S < I? min(I,L) : I
+ */
+ if (index->stat_index_size > 1) {
+ n_sample_pages = (srv_stats_sample_pages < index->stat_index_size) ?
+ ut_min(index->stat_index_size,
+ log2(index->stat_index_size)*srv_stats_sample_pages)
+ : index->stat_index_size;
+
+ }
+ }
+
+ /* Sanity check */
+ ut_ad(n_sample_pages > 0 && n_sample_pages <= (index->stat_index_size <= 1 ? 1 : index->stat_index_size));
/* We sample some pages in the index to get an estimate */
@@ -5409,3 +5544,169 @@ btr_rec_copy_externally_stored_field(
zip_size, local_len, heap));
}
#endif /* !UNIV_HOTBACKUP */
+
+/*******************************************************************//**
+Print information about old page and a new page on a B-tree when
+we note that page types do not match.*/
+void
+btr_pages_info(
+ page_t* old_page, /*!< in: Page where we were */
+ page_t* new_page, /*!< in: Page where we travelsed */
+ ulint space_id, /*!< in: space id */
+ ulint zip_size, /*!< in: zip size */
+ ulint page_no, /*!< in: Page id where travelsed */
+ ulint latch_mode __attribute__((unused)), /*!< in: Used latch mode */
+ dict_index_t* index, /*!< in: Used index */
+ ulint old_next_page_no, /*!< in: Next page number from old page */
+ ulint old_prev_page_no, /*!< in: Prev page number from old page */
+ ulint new_space_id, /*!< in: Space id of new page */
+ ulint new_zip_size __attribute__((unused)), /*!< in: Zip size of new page */
+ ulint new_next_page_no, /*!< in: Next page number from new page */
+ ulint new_prev_page_no, /*!< in: Prev page number from new page */
+ mtr_t* mtr, /*!< in: mini transaction */
+ const char* file, /*!< in: file name where called */
+ ulint line) /*!< in: line number where called */
+{
+ const char* old_name = fil_space_get_name(space_id);
+ const char* new_name = fil_space_get_name(new_space_id);
+ const char* name=NULL;
+ ulint spaceid=0,space=0;
+ buf_block_t* block=NULL;
+ page_t* page=NULL;
+
+ fprintf(stderr,"InnoDB: === Error: Index corruption detected ! === \n");
+ fprintf(stderr,"InnoDB File %s Line %lu \n", file, line);
+ dict_index_name_print(stderr, NULL, index);
+ fprintf(stderr,"InnoDB: Current page = %p \n", old_page);
+ fprintf(stderr,"InnoDB: New page = %p \n", new_page);
+ fprintf(stderr,"InnoDB: Current page->page_no = %lu \n", page_get_page_no(old_page));
+ fprintf(stderr,"InnoDB: New page->page_no = %lu \n", page_get_page_no(new_page));
+ fprintf(stderr,"InnoDB: Current page->space_id = %lu \n", page_get_space_id(old_page));
+ fprintf(stderr,"InnoDB: New page->space_id = %lu \n", page_get_space_id(new_page));
+ fprintf(stderr,"InnoDB: Current page->n_recs = %lu \n", page_get_n_recs(old_page));
+ fprintf(stderr,"InnoDB: New page->n_recs = %lu \n", page_get_n_recs(new_page));
+ fprintf(stderr,"InnoDB: Current page->n_slots = %lu \n", page_dir_get_n_slots(old_page));
+ fprintf(stderr,"InnoDB: New page->n_slots = %lu \n", page_dir_get_n_slots(new_page));
+ fprintf(stderr,"InnoDB: Current page->is_compact = %lu \n", page_is_comp(old_page));
+ fprintf(stderr,"InnoDB: New page->is_compact = %lu \n", page_is_comp(new_page));
+ fprintf(stderr,"InnoDB: Current page->is_leaf = %lu \n", page_is_leaf(old_page));
+ fprintf(stderr,"InnoDB: New page->is_leaf = %lu \n", page_is_leaf(new_page));
+ fprintf(stderr,"InnoDB: Current page valid = %lu \n", page_validate(old_page, index));
+ fprintf(stderr,"InnoDB: New page valid = %lu \n", page_validate(new_page, index));
+ fprintf(stderr,"InnoDB: Current page number = %lu \n", page_no);
+ fprintf(stderr,"InnoDB: Current page next page number = %lu \n", old_next_page_no);
+ fprintf(stderr,"InnoDB: Current page prev page number = %lu \n", old_prev_page_no);
+ fprintf(stderr,"InnoDB: New page next page number = %lu \n", new_next_page_no);
+ fprintf(stderr,"InnoDB: New page prev page number = %lu \n", new_prev_page_no);
+ fprintf(stderr,"InnoDB: Current page space_id = %lu \n", space_id);
+ fprintf(stderr,"InnoDB: New page space_id = %lu \n", new_space_id);
+ if (old_name)
+ fprintf(stderr,"InnoDB: Current page file = %s \n", old_name);
+ if (new_name)
+ fprintf(stderr,"InnoDB: New page file = %s \n", new_name);
+
+ fprintf(stderr,"InnoDB: OLD NEXT PAGE ID INFO = %lu \n", old_next_page_no);
+ if (old_next_page_no != FIL_NULL) {
+ block = btr_block_get(space_id, zip_size, old_next_page_no,
+ BTR_NO_LATCHES,
+ index, mtr);
+
+ space = buf_block_get_space(block);
+ zip_size = buf_block_get_zip_size(block);
+
+ fprintf(stderr,"InnoDB: Block space_id = %lu \n", space);
+ fprintf(stderr,"InnoDB: Block zip_size = %lu \n", zip_size);
+
+ page = buf_block_get_frame(block);
+ spaceid = page_get_space_id(page);
+ name = fil_space_get_name(spaceid);
+
+ fprintf(stderr,"InnoDB: Page space_id = %lu \n", space_id);
+ if (name)
+ fprintf(stderr,"InnoDB: Page file = %s \n", name);
+ fprintf(stderr,"InnoDB: Page->page_no = %lu \n", page_get_page_no(page));
+ fprintf(stderr,"InnoDB: Page->space_id = %lu \n", page_get_space_id(page));
+ fprintf(stderr,"InnoDB: Page->n_recs = %lu \n", page_get_n_recs(page));
+ fprintf(stderr,"InnoDB: Page->n_slots = %lu \n", page_dir_get_n_slots(page));
+ fprintf(stderr,"InnoDB: Page->is_compact = %lu \n", page_is_comp(page));
+ fprintf(stderr,"InnoDB: Page->is_leaf = %lu \n", page_is_leaf(page));
+ fprintf(stderr,"InnoDB: Page valid = %lu \n", page_validate(page, index));
+ }
+
+ fprintf(stderr,"InnoDB: OLD PREV PAGE ID INFO = %lu \n", old_prev_page_no);
+ if (old_prev_page_no != FIL_NULL) {
+ block = btr_block_get(space_id, zip_size, old_prev_page_no,
+ BTR_NO_LATCHES,
+ index, mtr);
+
+ space = buf_block_get_space(block);
+ zip_size = buf_block_get_zip_size(block);
+
+ fprintf(stderr,"InnoDB: Block space_id = %lu \n", space);
+ fprintf(stderr,"InnoDB: Block zip_size = %lu \n", zip_size);
+
+ page = buf_block_get_frame(block);
+ spaceid = page_get_space_id(page);
+ name = fil_space_get_name(spaceid);
+
+ fprintf(stderr,"InnoDB: Page space_id = %lu \n", space_id);
+ if (name)
+ fprintf(stderr,"InnoDB: Page file = %s \n", name);
+ fprintf(stderr,"InnoDB: Page->page_no = %lu \n", page_get_page_no(page));
+ fprintf(stderr,"InnoDB: Page->space_id = %lu \n", page_get_space_id(page));
+ fprintf(stderr,"InnoDB: Page->n_recs = %lu \n", page_get_n_recs(page));
+ fprintf(stderr,"InnoDB: Page->n_slots = %lu \n", page_dir_get_n_slots(page));
+ fprintf(stderr,"InnoDB: Page->is_compact = %lu \n", page_is_comp(page));
+ fprintf(stderr,"InnoDB: Page->is_leaf = %lu \n", page_is_leaf(page));
+ fprintf(stderr,"InnoDB: Page valid = %lu \n", page_validate(page, index));
+ }
+
+ fprintf(stderr,"InnoDB: NEW NEXT PAGE ID INFO = %lu \n", new_next_page_no);
+ if (new_next_page_no != FIL_NULL) {
+ block = btr_block_get(space_id, zip_size, new_next_page_no,
+ BTR_NO_LATCHES,
+ index, mtr);
+
+ space = buf_block_get_space(block);
+ zip_size = buf_block_get_zip_size(block);
+
+ fprintf(stderr,"InnoDB: Block space_id = %lu \n", space);
+ fprintf(stderr,"InnoDB: Block zip_size = %lu \n", zip_size);
+
+ page = buf_block_get_frame(block);
+ spaceid = page_get_space_id(page);
+ name = fil_space_get_name(spaceid);
+
+ fprintf(stderr,"InnoDB: Page space_id = %lu \n", space_id);
+ if (name)
+ fprintf(stderr,"InnoDB: Page file = %s \n", name);
+ fprintf(stderr,"InnoDB: Page->page_no = %lu \n", page_get_page_no(page));
+ fprintf(stderr,"InnoDB: Page->space_id = %lu \n", page_get_space_id(page));
+ fprintf(stderr,"InnoDB: Page->n_recs = %lu \n", page_get_n_recs(page));
+ fprintf(stderr,"InnoDB: Page->n_slots = %lu \n", page_dir_get_n_slots(page));
+ fprintf(stderr,"InnoDB: Page->is_compact = %lu \n", page_is_comp(page));
+ fprintf(stderr,"InnoDB: Page->is_leaf = %lu \n", page_is_leaf(page));
+ fprintf(stderr,"InnoDB: Page valid = %lu \n", page_validate(page, index));
+ }
+
+ fprintf(stderr,"InnoDB: NEW PREV PAGE ID INFO = %lu \n", new_prev_page_no);
+ if (new_prev_page_no != FIL_NULL) {
+ block = btr_block_get(space_id, zip_size, new_prev_page_no,
+ BTR_NO_LATCHES,
+ index, mtr);
+ page = buf_block_get_frame(block);
+ spaceid = page_get_space_id(page);
+ name = fil_space_get_name(spaceid);
+
+ fprintf(stderr,"InnoDB: Page space_id = %lu \n", space_id);
+ if (name)
+ fprintf(stderr,"InnoDB: Page file = %s \n", name);
+ fprintf(stderr,"InnoDB: Page->page_no = %lu \n", page_get_page_no(page));
+ fprintf(stderr,"InnoDB: Page->space_id = %lu \n", page_get_space_id(page));
+ fprintf(stderr,"InnoDB: Page->n_recs = %lu \n", page_get_n_recs(page));
+ fprintf(stderr,"InnoDB: Page->n_slots = %lu \n", page_dir_get_n_slots(page));
+ fprintf(stderr,"InnoDB: Page->is_compact = %lu \n", page_is_comp(page));
+ fprintf(stderr,"InnoDB: Page->is_leaf = %lu \n", page_is_leaf(page));
+ fprintf(stderr,"InnoDB: Page valid = %lu \n", page_validate(page, index));
+ }
+}
diff --git a/storage/innobase/btr/btr0pcur.c b/storage/innobase/btr/btr0pcur.c
index 09b3715e096..53df4768938 100644
--- a/storage/innobase/btr/btr0pcur.c
+++ b/storage/innobase/btr/btr0pcur.c
@@ -425,9 +425,24 @@ btr_pcur_move_to_next_page(
btr_pcur_get_btr_cur(cursor)->index, mtr);
next_page = buf_block_get_frame(next_block);
#ifdef UNIV_BTR_DEBUG
- ut_a(page_is_comp(next_page) == page_is_comp(page));
- ut_a(btr_page_get_prev(next_page, mtr)
- == buf_block_get_page_no(btr_pcur_get_block(cursor)));
+
+ if (page_is_comp(next_page) != page_is_comp(page)) {
+ btr_pages_info(page, next_page, space,
+ zip_size, next_page_no, cursor->latch_mode,
+ btr_pcur_get_btr_cur(cursor)->index,
+ btr_page_get_next(page, mtr),
+ btr_page_get_prev(page, mtr),
+ buf_block_get_space(next_block),
+ buf_block_get_zip_size(next_block),
+ btr_page_get_next(next_page, mtr),
+ btr_page_get_prev(next_page, mtr),
+ mtr, __FILE__, __LINE__);
+
+
+ ut_a(page_is_comp(next_page) == page_is_comp(page));
+ ut_a(btr_page_get_prev(next_page, mtr)
+ == buf_block_get_page_no(btr_pcur_get_block(cursor)));
+ }
#endif /* UNIV_BTR_DEBUG */
next_block->check_index_page_at_flush = TRUE;
diff --git a/storage/innobase/btr/btr0sea.c b/storage/innobase/btr/btr0sea.c
index 530f344e970..7b6ff16704c 100644
--- a/storage/innobase/btr/btr0sea.c
+++ b/storage/innobase/btr/btr0sea.c
@@ -535,7 +535,7 @@ btr_search_update_hash_ref(
{
dict_index_t* index;
ulint fold;
- const rec_t* rec;
+ rec_t* rec;
ut_ad(cursor->flag == BTR_CUR_HASH_FAIL);
#ifdef UNIV_SYNC_DEBUG
@@ -839,7 +839,7 @@ btr_search_guess_on_hash(
{
buf_pool_t* buf_pool;
buf_block_t* block;
- const rec_t* rec;
+ rec_t* rec;
ulint fold;
index_id_t index_id;
#ifdef notdefined
@@ -925,7 +925,7 @@ btr_search_guess_on_hash(
ut_ad(page_rec_is_user_rec(rec));
- btr_cur_position(index, (rec_t*) rec, block, cursor);
+ btr_cur_position(index, rec, block, cursor);
/* Check the validity of the guess within the page */
diff --git a/storage/innobase/buf/buf0lru.c b/storage/innobase/buf/buf0lru.c
index 148ac3d44f6..09a136bfa59 100644
--- a/storage/innobase/buf/buf0lru.c
+++ b/storage/innobase/buf/buf0lru.c
@@ -2080,6 +2080,24 @@ buf_LRU_block_remove_hashed_page(
" in the hash table\n",
(ulong) bpage->space,
(ulong) bpage->offset);
+#ifdef UNIV_DEBUG
+ fprintf(stderr,
+ "InnoDB: in_page_hash %lu in_zip_hash %lu\n"
+ " in_free_list %lu in_flush_list %lu in_LRU_list %lu\n"
+ " zip.data %p zip_size %lu page_state %d\n",
+ bpage->in_page_hash, bpage->in_zip_hash,
+ bpage->in_free_list, bpage->in_flush_list,
+ bpage->in_LRU_list, bpage->zip.data,
+ buf_page_get_zip_size(bpage),
+ buf_page_get_state(bpage));
+#else
+ fprintf(stderr,
+ "InnoDB: zip.data %p zip_size %lu page_state %d\n",
+ bpage->zip.data,
+ buf_page_get_zip_size(bpage),
+ buf_page_get_state(bpage));
+#endif
+
if (hashed_bpage) {
fprintf(stderr,
"InnoDB: In hash table we find block"
diff --git a/storage/innobase/dict/dict0crea.c b/storage/innobase/dict/dict0crea.c
index ac8a1eac03c..dcce3c1dca1 100644
--- a/storage/innobase/dict/dict0crea.c
+++ b/storage/innobase/dict/dict0crea.c
@@ -1140,7 +1140,7 @@ dict_create_index_step(
>= DICT_TF_FORMAT_ZIP);
node->index = dict_index_get_if_in_cache_low(index_id);
- ut_a(!node->index == (err != DB_SUCCESS));
+ ut_a(err == DB_SUCCESS ? node->index != NULL : node->index == NULL);
if (err != DB_SUCCESS) {
@@ -1420,6 +1420,104 @@ dict_create_add_foreign_field_to_dictionary(
}
/********************************************************************//**
+Construct foreign key constraint defintion from data dictionary information.
+*/
+UNIV_INTERN
+char*
+dict_foreign_def_get(
+/*=================*/
+ dict_foreign_t* foreign,/*!< in: foreign */
+ trx_t* trx) /*!< in: trx */
+{
+ char* fk_def = mem_heap_alloc(foreign->heap, 4*1024);
+ const char* tbname;
+ char tablebuf[MAX_TABLE_NAME_LEN + 1] = "";
+ int i;
+ char* bufend;
+
+ tbname = dict_remove_db_name(foreign->id);
+ bufend = innobase_convert_name(tablebuf, MAX_TABLE_NAME_LEN,
+ tbname, strlen(tbname), trx->mysql_thd, FALSE);
+ tablebuf[bufend - tablebuf] = '\0';
+
+ sprintf(fk_def,
+ (char *)"CONSTRAINT %s FOREIGN KEY (", (char *)tablebuf);
+
+ for(i = 0; i < foreign->n_fields; i++) {
+ char buf[MAX_TABLE_NAME_LEN + 1] = "";
+ innobase_convert_name(buf, MAX_TABLE_NAME_LEN,
+ foreign->foreign_col_names[i],
+ strlen(foreign->foreign_col_names[i]),
+ trx->mysql_thd, FALSE);
+ strcat(fk_def, buf);
+ if (i < foreign->n_fields-1) {
+ strcat(fk_def, (char *)",");
+ }
+ }
+
+ strcat(fk_def,(char *)") REFERENCES ");
+
+ bufend = innobase_convert_name(tablebuf, MAX_TABLE_NAME_LEN,
+ foreign->referenced_table_name,
+ strlen(foreign->referenced_table_name),
+ trx->mysql_thd, TRUE);
+ tablebuf[bufend - tablebuf] = '\0';
+
+ strcat(fk_def, tablebuf);
+ strcat(fk_def, " (");
+
+ for(i = 0; i < foreign->n_fields; i++) {
+ char buf[MAX_TABLE_NAME_LEN + 1] = "";
+ bufend = innobase_convert_name(buf, MAX_TABLE_NAME_LEN,
+ foreign->referenced_col_names[i],
+ strlen(foreign->referenced_col_names[i]),
+ trx->mysql_thd, FALSE);
+ buf[bufend - buf] = '\0';
+ strcat(fk_def, buf);
+ if (i < foreign->n_fields-1) {
+ strcat(fk_def, (char *)",");
+ }
+ }
+ strcat(fk_def, (char *)")");
+
+ return fk_def;
+}
+
+/********************************************************************//**
+Convert foreign key column names from data dictionary to SQL-layer.
+*/
+static
+void
+dict_foreign_def_get_fields(
+/*========================*/
+ dict_foreign_t* foreign,/*!< in: foreign */
+ trx_t* trx, /*!< in: trx */
+ char** field, /*!< out: foreign column */
+ char** field2, /*!< out: referenced column */
+ int col_no) /*!< in: column number */
+{
+ char* bufend;
+ char* fieldbuf = mem_heap_alloc(foreign->heap, MAX_TABLE_NAME_LEN+1);
+ char* fieldbuf2 = mem_heap_alloc(foreign->heap, MAX_TABLE_NAME_LEN+1);
+
+ bufend = innobase_convert_name(fieldbuf, MAX_TABLE_NAME_LEN,
+ foreign->foreign_col_names[col_no],
+ strlen(foreign->foreign_col_names[col_no]),
+ trx->mysql_thd, FALSE);
+
+ fieldbuf[bufend - fieldbuf] = '\0';
+
+ bufend = innobase_convert_name(fieldbuf2, MAX_TABLE_NAME_LEN,
+ foreign->referenced_col_names[col_no],
+ strlen(foreign->referenced_col_names[col_no]),
+ trx->mysql_thd, FALSE);
+
+ fieldbuf2[bufend - fieldbuf2] = '\0';
+ *field = fieldbuf;
+ *field2 = fieldbuf2;
+}
+
+/********************************************************************//**
Add a single foreign key definition to the data dictionary tables in the
database. We also generate names to constraints that were not named by the
user. A generated constraint has a name of the format
@@ -1501,6 +1599,29 @@ dict_create_add_foreign_to_dictionary(
if (error != DB_SUCCESS) {
+ if (error == DB_DUPLICATE_KEY) {
+ char buf[MAX_TABLE_NAME_LEN + 1] = "";
+ char tablename[MAX_TABLE_NAME_LEN + 1] = "";
+ char* fk_def;
+
+ innobase_convert_name(tablename, MAX_TABLE_NAME_LEN,
+ table->name, strlen(table->name),
+ trx->mysql_thd, TRUE);
+
+ innobase_convert_name(buf, MAX_TABLE_NAME_LEN,
+ foreign->id, strlen(foreign->id), trx->mysql_thd, FALSE);
+
+ fk_def = dict_foreign_def_get(foreign, trx);
+
+ ib_push_warning(trx, error,
+ "Create or Alter table %s with foreign key constraint"
+ " failed. Foreign key constraint %s"
+ " already exists on data dictionary."
+ " Foreign key constraint names need to be unique in database."
+ " Error in foreign key definition: %s.",
+ tablename, buf, fk_def);
+ }
+
return(error);
}
@@ -1509,6 +1630,26 @@ dict_create_add_foreign_to_dictionary(
i, table, foreign, trx);
if (error != DB_SUCCESS) {
+ char buf[MAX_TABLE_NAME_LEN + 1] = "";
+ char tablename[MAX_TABLE_NAME_LEN + 1] = "";
+ char* field=NULL;
+ char* field2=NULL;
+ char* fk_def;
+
+ innobase_convert_name(tablename, MAX_TABLE_NAME_LEN,
+ table->name, strlen(table->name),
+ trx->mysql_thd, TRUE);
+ innobase_convert_name(buf, MAX_TABLE_NAME_LEN,
+ foreign->id, strlen(foreign->id), trx->mysql_thd, FALSE);
+ fk_def = dict_foreign_def_get(foreign, trx);
+ dict_foreign_def_get_fields(foreign, trx, &field, &field2, i);
+
+ ib_push_warning(trx, error,
+ "Create or Alter table %s with foreign key constraint"
+ " failed. Error adding foreign key constraint name %s"
+ " fields %s or %s to the dictionary."
+ " Error in foreign key definition: %s.",
+ tablename, buf, i+1, fk_def);
return(error);
}
@@ -1593,7 +1734,7 @@ dict_create_add_foreigns_to_dictionary(
foreign = UT_LIST_GET_NEXT(foreign_list, foreign)) {
error = dict_create_add_foreign_to_dictionary(&number, table,
- foreign, trx);
+ foreign, trx);
if (error != DB_SUCCESS) {
diff --git a/storage/innobase/dict/dict0dict.c b/storage/innobase/dict/dict0dict.c
index 5aca95aec0d..33b110ce97a 100644
--- a/storage/innobase/dict/dict0dict.c
+++ b/storage/innobase/dict/dict0dict.c
@@ -2010,7 +2010,7 @@ dict_index_find_cols(
dict_field_t* field = dict_index_get_nth_field(index, i);
for (j = 0; j < table->n_cols; j++) {
- if (!strcmp(dict_table_get_col_name(table, j),
+ if (!innobase_strcasecmp(dict_table_get_col_name(table, j),
field->name)) {
field->col = dict_table_get_nth_col(table, j);
@@ -2616,6 +2616,11 @@ dict_foreign_find(
DBUG_RETURN(NULL);
}
+#define DB_FOREIGN_KEY_IS_PREFIX_INDEX 200
+#define DB_FOREIGN_KEY_COL_NOT_NULL 201
+#define DB_FOREIGN_KEY_COLS_NOT_EQUAL 202
+#define DB_FOREIGN_KEY_INDEX_NOT_FOUND 203
+
/*********************************************************************//**
Tries to find an index whose first fields are the columns in the array,
in the same order and is not marked for deletion and is not the same
@@ -2633,12 +2638,21 @@ dict_foreign_find_index(
ibool check_charsets,
/*!< in: whether to check charsets.
only has an effect if types_idx != NULL */
- ulint check_null)
+ ulint check_null,
/*!< in: nonzero if none of the columns must
be declared NOT NULL */
+ ulint* error, /*!< out: error code */
+ ulint* err_col_no,
+ /*!< out: column number where error happened */
+ dict_index_t** err_index)
+ /*!< out: index where error happened */
{
dict_index_t* index;
+ if (error) {
+ *error = DB_FOREIGN_KEY_INDEX_NOT_FOUND;
+ }
+
index = dict_table_get_first_index(table);
while (index != NULL) {
@@ -2664,6 +2678,12 @@ dict_foreign_find_index(
/* We do not accept column prefix
indexes here */
+ if (error && err_col_no && err_index) {
+ *error = DB_FOREIGN_KEY_IS_PREFIX_INDEX;
+ *err_col_no = i;
+ *err_index = index;
+ }
+
break;
}
@@ -2675,6 +2695,11 @@ dict_foreign_find_index(
if (check_null
&& (field->col->prtype & DATA_NOT_NULL)) {
+ if (error && err_col_no && err_index) {
+ *error = DB_FOREIGN_KEY_COL_NOT_NULL;
+ *err_col_no = i;
+ *err_index = index;
+ }
return(NULL);
}
@@ -2684,6 +2709,12 @@ dict_foreign_find_index(
i),
check_charsets)) {
+ if (error && err_col_no && err_index) {
+ *error = DB_FOREIGN_KEY_COLS_NOT_EQUAL;
+ *err_col_no = i;
+ *err_index = index;
+ }
+
break;
}
}
@@ -2691,6 +2722,10 @@ dict_foreign_find_index(
if (i == n_cols) {
/* We found a matching index */
+ if (error) {
+ *error = DB_SUCCESS;
+ }
+
return(index);
}
}
@@ -2722,7 +2757,7 @@ dict_foreign_find_equiv_index(
foreign->foreign_table,
foreign->foreign_col_names, foreign->n_fields,
foreign->foreign_index, TRUE, /* check types */
- FALSE/* allow columns to be NULL */));
+ FALSE/* allow columns to be NULL */, NULL, NULL, NULL));
}
#endif /* !UNIV_HOTBACKUP */
@@ -2885,11 +2920,15 @@ dict_foreign_add_to_cache(
}
if (for_in_cache->referenced_table == NULL && ref_table) {
+ ulint index_error;
+ ulint err_col;
+ dict_index_t *err_index=NULL;
+
index = dict_foreign_find_index(
ref_table,
for_in_cache->referenced_col_names,
for_in_cache->n_fields, for_in_cache->foreign_index,
- check_charsets, FALSE);
+ check_charsets, FALSE, &index_error, &err_col, &err_index);
if (index == NULL
&& !(ignore_err & DICT_ERR_IGNORE_FK_NOKEY)) {
@@ -2921,6 +2960,9 @@ dict_foreign_add_to_cache(
}
if (for_in_cache->foreign_table == NULL && for_table) {
+ ulint index_error;
+ ulint err_col;
+ dict_index_t* err_index=NULL;
index = dict_foreign_find_index(
for_table,
@@ -2929,7 +2971,8 @@ dict_foreign_add_to_cache(
for_in_cache->referenced_index, check_charsets,
for_in_cache->type
& (DICT_FOREIGN_ON_DELETE_SET_NULL
- | DICT_FOREIGN_ON_UPDATE_SET_NULL));
+ | DICT_FOREIGN_ON_UPDATE_SET_NULL),
+ &index_error, &err_col, &err_index);
if (index == NULL
&& !(ignore_err & DICT_ERR_IGNORE_FK_NOKEY)) {
@@ -3540,6 +3583,8 @@ static
void
dict_foreign_report_syntax_err(
/*===========================*/
+ const char* fmt, /*!< in: syntax err msg */
+ const char* oper, /*!< in: operation */
const char* name, /*!< in: table name */
const char* start_of_latest_foreign,
/*!< in: start of the foreign key clause
@@ -3550,12 +3595,102 @@ dict_foreign_report_syntax_err(
mutex_enter(&dict_foreign_err_mutex);
dict_foreign_error_report_low(ef, name);
- fprintf(ef, "%s:\nSyntax error close to:\n%s\n",
- start_of_latest_foreign, ptr);
+ fprintf(ef, fmt, oper, name, start_of_latest_foreign, ptr);
mutex_exit(&dict_foreign_err_mutex);
}
/*********************************************************************//**
+Push warning message to SQL-layer based on foreign key constraint
+index match error. */
+static
+void
+dict_foreign_push_index_error(
+/*==========================*/
+ trx_t* trx, /*!< in: trx */
+ const char* operation, /*!< in: operation create or alter
+ */
+ const char* create_name, /*!< in: table name in create or
+ alter table */
+ const char* latest_foreign, /*!< in: start of latest foreign key
+ constraint name */
+ const char** columns, /*!< in: foreign key columns */
+ ulint index_error, /*!< in: error code */
+ ulint err_col, /*!< in: column where error happened
+ */
+ dict_index_t* err_index, /*!< in: index where error happened
+ */
+ dict_table_t* table, /*!< in: table */
+ FILE* ef) /*!< in: output stream */
+{
+ switch (index_error) {
+ case DB_FOREIGN_KEY_INDEX_NOT_FOUND: {
+ fprintf(ef,
+ "%s table '%s' with foreign key constraint"
+ " failed. There is no index in the referenced"
+ " table where the referenced columns appear"
+ " as the first columns near '%s'.\n",
+ operation, create_name, latest_foreign);
+ ib_push_warning(trx, DB_CANNOT_ADD_CONSTRAINT,
+ "%s table '%s' with foreign key constraint"
+ " failed. There is no index in the referenced"
+ " table where the referenced columns appear"
+ " as the first columns near '%s'.",
+ operation, create_name, latest_foreign);
+ break;
+ }
+ case DB_FOREIGN_KEY_IS_PREFIX_INDEX: {
+ fprintf(ef,
+ "%s table '%s' with foreign key constraint"
+ " failed. There is only prefix index in the referenced"
+ " table where the referenced columns appear"
+ " as the first columns near '%s'.\n",
+ operation, create_name, latest_foreign);
+ ib_push_warning(trx, DB_CANNOT_ADD_CONSTRAINT,
+ "%s table '%s' with foreign key constraint"
+ " failed. There is only prefix index in the referenced"
+ " table where the referenced columns appear"
+ " as the first columns near '%s'.",
+ operation, create_name, latest_foreign);
+ break;
+ }
+ case DB_FOREIGN_KEY_COL_NOT_NULL: {
+ fprintf(ef,
+ "%s table %s with foreign key constraint"
+ " failed. You have defined a SET NULL condition but "
+ "column '%s' on index is defined as NOT NULL near '%s'.\n",
+ operation, create_name, columns[err_col], latest_foreign);
+ ib_push_warning(trx, DB_CANNOT_ADD_CONSTRAINT,
+ "%s table %s with foreign key constraint"
+ " failed. You have defined a SET NULL condition but "
+ "column '%s' on index is defined as NOT NULL near '%s'.",
+ operation, create_name, columns[err_col], latest_foreign);
+ break;
+ }
+ case DB_FOREIGN_KEY_COLS_NOT_EQUAL: {
+ dict_field_t* field;
+ const char* col_name;
+ field = dict_index_get_nth_field(err_index, err_col);
+
+ col_name = dict_table_get_col_name(
+ table, dict_col_get_no(field->col));
+ fprintf(ef,
+ "%s table %s with foreign key constraint"
+ " failed. Field type or character set for column '%s' "
+ "does not mach referenced column '%s' near '%s'.\n",
+ operation, create_name, columns[err_col], col_name, latest_foreign);
+ ib_push_warning(trx, DB_CANNOT_ADD_CONSTRAINT,
+ "%s table %s with foreign key constraint"
+ " failed. Field type or character set for column '%s' "
+ "does not mach referenced column '%s' near '%s'.",
+ operation, create_name, columns[err_col], col_name, latest_foreign);
+ break;
+ }
+ default:
+ ut_error;
+ }
+}
+
+/*********************************************************************//**
Scans a table create SQL string and adds to the data dictionary the foreign
key constraints declared in the string. This function should be called after
the indexes for a table have been created. Each foreign key constraint must
@@ -3583,15 +3718,20 @@ dict_create_foreign_constraints_low(
DB_CANNOT_ADD_CONSTRAINT if any foreign
keys are found. */
{
- dict_table_t* table;
- dict_table_t* referenced_table;
- dict_table_t* table_to_alter;
+ dict_table_t* table = NULL;
+ dict_table_t* referenced_table = NULL;
+ dict_table_t* table_to_alter = NULL;
+ dict_table_t* table_to_create = NULL;
ulint highest_id_so_far = 0;
- dict_index_t* index;
- dict_foreign_t* foreign;
+ dict_index_t* index = NULL;
+ dict_foreign_t* foreign = NULL;
const char* ptr = sql_string;
const char* start_of_latest_foreign = sql_string;
+ const char* start_of_latest_set = NULL;
FILE* ef = dict_foreign_err_file;
+ ulint index_error = DB_SUCCESS;
+ dict_index_t* err_index = NULL;
+ ulint err_col;
const char* constraint_name;
ibool success;
ulint error;
@@ -3604,29 +3744,68 @@ dict_create_foreign_constraints_low(
ulint n_on_updates;
const dict_col_t*columns[500];
const char* column_names[500];
+ const char* ref_column_names[500];
const char* referenced_table_name;
+ const char* create_table_name;
+ const char* orig;
+ char create_name[MAX_TABLE_NAME_LEN + 1];
+ const char operation[8];
ut_ad(mutex_own(&(dict_sys->mutex)));
table = dict_table_get_low(name, DICT_ERR_IGNORE_NONE);
+ /* First check if we are actually doing an ALTER TABLE, and in that
+ case look for the table being altered */
+ ptr = dict_accept(cs, ptr, "ALTER", &success);
+
+ strcpy((char *)operation, success ? "Alter " : "Create ");
+
+ if (!success) {
+ orig = ptr;
+ ptr = dict_scan_to(ptr, "CREATE");
+ ptr = dict_scan_to(ptr, "TABLE");
+ ptr = dict_accept(cs, ptr, "TABLE", &success);
+
+ if (success) {
+ ptr = dict_scan_table_name(cs, ptr, &table_to_create, name,
+ &success, heap, &create_table_name);
+ }
+
+ if (success) {
+ char *bufend;
+ bufend = innobase_convert_name((char *)create_name, MAX_TABLE_NAME_LEN,
+ create_table_name, strlen(create_table_name),
+ trx->mysql_thd, TRUE);
+ create_name[bufend-create_name]='\0';
+ ptr = orig;
+ } else {
+ char *bufend;
+ ptr = orig;
+ bufend = innobase_convert_name((char *)create_name, MAX_TABLE_NAME_LEN,
+ name, strlen(name), trx->mysql_thd, TRUE);
+ create_name[bufend-create_name]='\0';
+ }
+
+ goto loop;
+ }
if (table == NULL) {
mutex_enter(&dict_foreign_err_mutex);
- dict_foreign_error_report_low(ef, name);
- fprintf(ef,
- "Cannot find the table in the internal"
- " data dictionary of InnoDB.\n"
- "Create table statement:\n%s\n", sql_string);
+ dict_foreign_error_report_low(ef, create_name);
+ fprintf(ef, "%s table %s with foreign key constraint"
+ " failed. Table %s not found from data dictionary."
+ " Error close to %s.\n",
+ operation, create_name, create_name, start_of_latest_foreign);
mutex_exit(&dict_foreign_err_mutex);
-
+ ib_push_warning(trx, DB_ERROR,
+ "%s table %s with foreign key constraint"
+ " failed. Table %s not found from data dictionary."
+ " Error close to %s.",
+ operation, create_name, create_name, start_of_latest_foreign);
return(DB_ERROR);
}
- /* First check if we are actually doing an ALTER TABLE, and in that
- case look for the table being altered */
-
- ptr = dict_accept(cs, ptr, "ALTER", &success);
-
+ /* If not alter table jump to loop */
if (!success) {
goto loop;
@@ -3641,13 +3820,40 @@ dict_create_foreign_constraints_low(
/* We are doing an ALTER TABLE: scan the table name we are altering */
+ orig = ptr;
ptr = dict_scan_table_name(cs, ptr, &table_to_alter, name,
&success, heap, &referenced_table_name);
+
+ if (table_to_alter) {
+ char *bufend;
+ bufend = innobase_convert_name((char *)create_name, MAX_TABLE_NAME_LEN,
+ table_to_alter->name, strlen(table_to_alter->name),
+ trx->mysql_thd, TRUE);
+ create_name[bufend-create_name]='\0';
+ } else {
+ char *bufend;
+ bufend = innobase_convert_name((char *)create_name, MAX_TABLE_NAME_LEN,
+ referenced_table_name, strlen(referenced_table_name),
+ trx->mysql_thd, TRUE);
+ create_name[bufend-create_name]='\0';
+
+ }
+
if (!success) {
- fprintf(stderr,
- "InnoDB: Error: could not find"
- " the table being ALTERED in:\n%s\n",
- sql_string);
+ mutex_enter(&dict_foreign_err_mutex);
+ dict_foreign_error_report_low(ef, create_name);
+ fprintf(ef,
+ "%s table %s with foreign key constraint"
+ " failed. Table %s not found from data dictionary."
+ " Error close to %s.\n",
+ operation, create_name, create_name, orig);
+ mutex_exit(&dict_foreign_err_mutex);
+
+ ib_push_warning(trx, DB_ERROR,
+ "%s table %s with foreign key constraint"
+ " failed. Table %s not found from data dictionary."
+ " Error close to %s.",
+ operation, create_name, create_name, orig);
return(DB_ERROR);
}
@@ -3713,7 +3919,19 @@ loop:
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)) {
+ mutex_enter(&dict_foreign_err_mutex);
+ dict_foreign_error_report_low(ef, create_name);
+ fprintf(ef, "%s table %s with foreign key constraint"
+ " failed. Temporary tables can't have foreign key constraints."
+ " Error close to %s.\n",
+ operation, create_name, start_of_latest_foreign);
+ mutex_exit(&dict_foreign_err_mutex);
+ ib_push_warning(trx, DB_CANNOT_ADD_CONSTRAINT,
+ "%s table %s with foreign key constraint"
+ " failed. Temporary tables can't have foreign key constraints."
+ " Error close to %s.",
+ operation, create_name, start_of_latest_foreign);
return(DB_CANNOT_ADD_CONSTRAINT);
}
@@ -3749,11 +3967,21 @@ loop:
if (!success) {
/* MySQL allows also an index id before the '('; we
skip it */
+ orig = ptr;
ptr = dict_skip_word(cs, ptr, &success);
if (!success) {
dict_foreign_report_syntax_err(
- name, start_of_latest_foreign, ptr);
+ "%s table %s with foreign key constraint"
+ " failed. Parse error in '%s'"
+ " near '%s'.\n",
+ operation, create_name, start_of_latest_foreign, orig);
+
+ ib_push_warning(trx, DB_CANNOT_ADD_CONSTRAINT,
+ "%s table %s with foreign key constraint"
+ " failed. Parse error in '%s'"
+ " near '%s'.",
+ operation, create_name, start_of_latest_foreign, orig);
return(DB_CANNOT_ADD_CONSTRAINT);
}
@@ -3773,15 +4001,26 @@ loop:
/* Scan the columns in the first list */
col_loop1:
ut_a(i < (sizeof column_names) / sizeof *column_names);
+ orig = ptr;
ptr = dict_scan_col(cs, ptr, &success, table, columns + i,
heap, column_names + i);
if (!success) {
mutex_enter(&dict_foreign_err_mutex);
- dict_foreign_error_report_low(ef, name);
- fprintf(ef, "%s:\nCannot resolve column name close to:\n%s\n",
- start_of_latest_foreign, ptr);
+ dict_foreign_error_report_low(ef, create_name);
+ fprintf(ef,
+ "%s table %s with foreign key constraint"
+ " failed. Parse error in '%s'"
+ " near '%s'.\n",
+ operation, create_name, start_of_latest_foreign, orig);
+
mutex_exit(&dict_foreign_err_mutex);
+ ib_push_warning(trx, DB_CANNOT_ADD_CONSTRAINT,
+ "%s table %s with foreign key constraint"
+ " failed. Parse error in '%s'"
+ " near '%s'.",
+ operation, create_name, start_of_latest_foreign, orig);
+
return(DB_CANNOT_ADD_CONSTRAINT);
}
@@ -3793,11 +4032,22 @@ col_loop1:
goto col_loop1;
}
+ orig = ptr;
ptr = dict_accept(cs, ptr, ")", &success);
if (!success) {
dict_foreign_report_syntax_err(
- name, start_of_latest_foreign, ptr);
+ "%s table %s with foreign key constraint"
+ " failed. Parse error in '%s'"
+ " near '%s'.\n",
+ operation, create_name, start_of_latest_foreign, orig);
+
+ ib_push_warning(trx, DB_CANNOT_ADD_CONSTRAINT,
+ "%s table %s with foreign key constraint"
+ " failed. Parse error in '%s'"
+ " near '%s'.",
+ operation, create_name, start_of_latest_foreign, orig);
+
return(DB_CANNOT_ADD_CONSTRAINT);
}
@@ -3805,27 +4055,41 @@ col_loop1:
as the first fields and in the right order */
index = dict_foreign_find_index(table, column_names, i,
- NULL, TRUE, FALSE);
+ NULL, TRUE, FALSE, &index_error, &err_col, &err_index);
if (!index) {
mutex_enter(&dict_foreign_err_mutex);
- dict_foreign_error_report_low(ef, name);
+ dict_foreign_error_report_low(ef, create_name);
fputs("There is no index in table ", ef);
- ut_print_name(ef, NULL, TRUE, name);
+ ut_print_name(ef, NULL, TRUE, create_name);
fprintf(ef, " where the columns appear\n"
"as the first columns. Constraint:\n%s\n"
"See " REFMAN "innodb-foreign-key-constraints.html\n"
"for correct foreign key definition.\n",
start_of_latest_foreign);
- mutex_exit(&dict_foreign_err_mutex);
- return(DB_CHILD_NO_INDEX);
+ dict_foreign_push_index_error(trx, operation, create_name, start_of_latest_foreign,
+ column_names, index_error, err_col, err_index, table, ef);
+
+ mutex_exit(&dict_foreign_err_mutex);
+ return(DB_CANNOT_ADD_CONSTRAINT);
}
+
+ orig = ptr;
ptr = dict_accept(cs, ptr, "REFERENCES", &success);
if (!success || !my_isspace(cs, *ptr)) {
dict_foreign_report_syntax_err(
- name, start_of_latest_foreign, ptr);
+ "%s table %s with foreign key constraint"
+ " failed. Parse error in '%s'"
+ " near '%s'.\n",
+ operation, create_name, start_of_latest_foreign, orig);
+
+ ib_push_warning(trx, DB_CANNOT_ADD_CONSTRAINT,
+ "%s table %s with foreign key constraint"
+ " failed. Parse error in '%s'"
+ " near '%s'.",
+ operation, create_name, start_of_latest_foreign, orig);
return(DB_CANNOT_ADD_CONSTRAINT);
}
@@ -3874,24 +4138,50 @@ col_loop1:
checking of foreign key constraints! */
if (!success || (!referenced_table && trx->check_foreigns)) {
+ char buf[MAX_TABLE_NAME_LEN + 1] = "";
+ char* bufend;
+
+ bufend = innobase_convert_name(buf, MAX_TABLE_NAME_LEN,
+ referenced_table_name, strlen(referenced_table_name),
+ trx->mysql_thd, TRUE);
+ buf[bufend - buf] = '\0';
+
+ ib_push_warning(trx, DB_CANNOT_ADD_CONSTRAINT,
+ "%s table %s with foreign key constraint failed. Referenced table %s not found in the data dictionary "
+ "near '%s'.",
+ operation, create_name, buf, start_of_latest_foreign);
+
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"
- "%s\n",
- start_of_latest_foreign, ptr);
+ dict_foreign_error_report_low(ef, create_name);
+ fprintf(ef,
+ "%s table %s with foreign key constraint failed. Referenced table %s not found in the data dictionary "
+ "near '%s'.\n",
+ operation, create_name, buf, start_of_latest_foreign);
+
mutex_exit(&dict_foreign_err_mutex);
return(DB_CANNOT_ADD_CONSTRAINT);
}
+ orig = ptr;
ptr = dict_accept(cs, ptr, "(", &success);
if (!success) {
dict_foreign_free(foreign);
- dict_foreign_report_syntax_err(name, start_of_latest_foreign,
- ptr);
+ dict_foreign_report_syntax_err(
+ "%s table %s with foreign key constraint"
+ " failed. Parse error in '%s'"
+ " near '%s'.\n",
+ operation, create_name, start_of_latest_foreign, orig);
+
+ ib_push_warning(trx, DB_CANNOT_ADD_CONSTRAINT,
+ "%s table %s with foreign key constraint"
+ " failed. Parse error in '%s'"
+ " near '%s'.",
+ operation, create_name, start_of_latest_foreign, orig);
+
return(DB_CANNOT_ADD_CONSTRAINT);
}
@@ -3899,20 +4189,29 @@ col_loop1:
i = 0;
col_loop2:
+ orig = ptr;
ptr = dict_scan_col(cs, ptr, &success, referenced_table, columns + i,
- heap, column_names + i);
+ heap, ref_column_names + i);
i++;
if (!success) {
dict_foreign_free(foreign);
mutex_enter(&dict_foreign_err_mutex);
- dict_foreign_error_report_low(ef, name);
- fprintf(ef, "%s:\nCannot resolve column name close to:\n"
- "%s\n",
- start_of_latest_foreign, ptr);
+ dict_foreign_error_report_low(ef, create_name);
+ fprintf(ef,
+ "%s table %s with foreign key constraint"
+ " failed. Parse error in '%s'"
+ " near '%s'.\n",
+ operation, create_name, start_of_latest_foreign, orig);
+
mutex_exit(&dict_foreign_err_mutex);
+ ib_push_warning(trx, DB_CANNOT_ADD_CONSTRAINT,
+ "%s table %s with foreign key constraint"
+ " failed. Parse error in '%s'"
+ " near '%s'.",
+ operation, create_name, start_of_latest_foreign, orig);
return(DB_CANNOT_ADD_CONSTRAINT);
}
@@ -3922,13 +4221,23 @@ col_loop2:
goto col_loop2;
}
+ orig = ptr;
ptr = dict_accept(cs, ptr, ")", &success);
if (!success || foreign->n_fields != i) {
+
+ dict_foreign_report_syntax_err(
+ "%s table %s with foreign key constraint"
+ " failed. Parse error in '%s' near '%s'. Referencing column count does not match referenced column count.\n",
+ operation, create_name, start_of_latest_foreign, orig);
+
+ ib_push_warning(trx, DB_CANNOT_ADD_CONSTRAINT,
+ "%s table %s with foreign key constraint"
+ " failed. Parse error in '%s' near '%s'. Referencing column count %d does not match referenced column count %d.\n",
+ operation, create_name, start_of_latest_foreign, orig, i, foreign->n_fields);
+
dict_foreign_free(foreign);
- dict_foreign_report_syntax_err(name, start_of_latest_foreign,
- ptr);
return(DB_CANNOT_ADD_CONSTRAINT);
}
@@ -3938,6 +4247,7 @@ col_loop2:
scan_on_conditions:
/* Loop here as long as we can find ON ... conditions */
+ start_of_latest_set = ptr;
ptr = dict_accept(cs, ptr, "ON", &success);
if (!success) {
@@ -3948,13 +4258,24 @@ scan_on_conditions:
ptr = dict_accept(cs, ptr, "DELETE", &success);
if (!success) {
+ orig = ptr;
ptr = dict_accept(cs, ptr, "UPDATE", &success);
if (!success) {
dict_foreign_free(foreign);
dict_foreign_report_syntax_err(
- name, start_of_latest_foreign, ptr);
+ "%s table %s with foreign key constraint"
+ " failed. Parse error in '%s'"
+ " near '%s'.\n",
+ operation, create_name, start_of_latest_foreign, start_of_latest_set);
+
+ ib_push_warning(trx, DB_CANNOT_ADD_CONSTRAINT,
+ "%s table %s with foreign key constraint"
+ " failed. Parse error in '%s'"
+ " near '%s'.",
+ operation, create_name, start_of_latest_foreign, start_of_latest_set);
+
return(DB_CANNOT_ADD_CONSTRAINT);
}
@@ -3986,12 +4307,22 @@ scan_on_conditions:
ptr = dict_accept(cs, ptr, "NO", &success);
if (success) {
+ orig = ptr;
ptr = dict_accept(cs, ptr, "ACTION", &success);
if (!success) {
dict_foreign_free(foreign);
dict_foreign_report_syntax_err(
- name, start_of_latest_foreign, ptr);
+ "%s table %s with foreign key constraint"
+ " failed. Parse error in '%s'"
+ " near '%s'.\n",
+ operation, create_name, start_of_latest_foreign, start_of_latest_set);
+
+ ib_push_warning(trx, DB_CANNOT_ADD_CONSTRAINT,
+ "%s table %s with foreign key constraint"
+ " failed. Parse error in '%s'"
+ " near '%s'.",
+ operation, create_name, start_of_latest_foreign, start_of_latest_set);
return(DB_CANNOT_ADD_CONSTRAINT);
}
@@ -4005,42 +4336,73 @@ scan_on_conditions:
goto scan_on_conditions;
}
+ orig = ptr;
ptr = dict_accept(cs, ptr, "SET", &success);
if (!success) {
dict_foreign_free(foreign);
- dict_foreign_report_syntax_err(name, start_of_latest_foreign,
- ptr);
+ dict_foreign_report_syntax_err(
+ "%s table %s with foreign key constraint"
+ " failed. Parse error in '%s'"
+ " near '%s'.\n",
+ operation, create_name, start_of_latest_foreign, start_of_latest_set);
+
+ ib_push_warning(trx, DB_CANNOT_ADD_CONSTRAINT,
+ "%s table %s with foreign key constraint"
+ " failed. Parse error in '%s'"
+ " near '%s'.",
+ operation, create_name, start_of_latest_foreign, start_of_latest_set);
+
return(DB_CANNOT_ADD_CONSTRAINT);
}
+ orig = ptr;
ptr = dict_accept(cs, ptr, "NULL", &success);
if (!success) {
dict_foreign_free(foreign);
- dict_foreign_report_syntax_err(name, start_of_latest_foreign,
- ptr);
+ dict_foreign_report_syntax_err(
+ "%s table %s with foreign key constraint"
+ " failed. Parse error in '%s'"
+ " near '%s'.\n",
+ operation, create_name, start_of_latest_foreign, start_of_latest_set);
+
+ ib_push_warning(trx, DB_CANNOT_ADD_CONSTRAINT,
+ "%s table %s with foreign key constraint"
+ " failed. Parse error in '%s'"
+ " near '%s'.",
+ operation, create_name, start_of_latest_foreign, start_of_latest_set);
return(DB_CANNOT_ADD_CONSTRAINT);
}
for (j = 0; j < foreign->n_fields; j++) {
if ((dict_index_get_nth_col(foreign->foreign_index, j)->prtype)
& DATA_NOT_NULL) {
+ const dict_col_t* col
+ = dict_index_get_nth_col(foreign->foreign_index, j);
+ const char* col_name = dict_table_get_col_name(foreign->foreign_index->table,
+ dict_col_get_no(col));
/* 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"
- "You have defined a SET NULL condition"
- " though some of the\n"
- "columns are defined as NOT NULL.\n",
- start_of_latest_foreign);
+ dict_foreign_error_report_low(ef, create_name);
+ fprintf(ef,
+ "%s table %s with foreign key constraint"
+ " failed. You have defined a SET NULL condition but column '%s' is defined as NOT NULL"
+ " in '%s' near '%s'.\n",
+ operation, create_name, col_name, start_of_latest_foreign, start_of_latest_set);
mutex_exit(&dict_foreign_err_mutex);
+
+ ib_push_warning(trx, DB_CANNOT_ADD_CONSTRAINT,
+ "%s table %s with foreign key constraint"
+ " failed. You have defined a SET NULL condition but column '%s' is defined as NOT NULL"
+ " in '%s' near '%s'.",
+ operation, create_name, col_name, start_of_latest_foreign, start_of_latest_set);
+
+ dict_foreign_free(foreign);
return(DB_CANNOT_ADD_CONSTRAINT);
}
}
@@ -4057,16 +4419,22 @@ 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"
- "You have twice an ON DELETE clause"
- " or twice an ON UPDATE clause.\n",
- start_of_latest_foreign);
+ dict_foreign_error_report_low(ef, create_name);
+ fprintf(ef,
+ "%s table %s with foreign key constraint"
+ " failed. You have more than one on delete or on update clause"
+ " in '%s' near '%s'.\n",
+ operation, create_name, start_of_latest_foreign, start_of_latest_set);
mutex_exit(&dict_foreign_err_mutex);
+ ib_push_warning(trx, DB_CANNOT_ADD_CONSTRAINT,
+ "%s table %s with foreign key constraint"
+ " failed. You have more than one on delete or on update clause"
+ " in '%s' near '%s'.",
+ operation, create_name, start_of_latest_foreign, start_of_latest_set);
+ dict_foreign_free(foreign);
return(DB_CANNOT_ADD_CONSTRAINT);
}
@@ -4076,13 +4444,13 @@ try_find_index:
if (referenced_table) {
index = dict_foreign_find_index(referenced_table,
- column_names, i,
- foreign->foreign_index,
- TRUE, FALSE);
+ ref_column_names, i,
+ foreign->foreign_index,
+ TRUE, FALSE, &index_error, &err_col, &err_index);
if (!index) {
dict_foreign_free(foreign);
mutex_enter(&dict_foreign_err_mutex);
- dict_foreign_error_report_low(ef, name);
+ dict_foreign_error_report_low(ef, create_name);
fprintf(ef, "%s:\n"
"Cannot find an index in the"
" referenced table where the\n"
@@ -4100,9 +4468,13 @@ try_find_index:
"innodb-foreign-key-constraints.html\n"
"for correct foreign key definition.\n",
start_of_latest_foreign);
+
+ dict_foreign_push_index_error(trx, operation, create_name, start_of_latest_foreign,
+ column_names, index_error, err_col, err_index, referenced_table, ef);
+
mutex_exit(&dict_foreign_err_mutex);
- return(DB_PARENT_NO_INDEX);
+ return(DB_CANNOT_ADD_CONSTRAINT);
}
} else {
ut_a(trx->check_foreigns == FALSE);
@@ -4120,7 +4492,7 @@ try_find_index:
i * sizeof(void*));
for (i = 0; i < foreign->n_fields; i++) {
foreign->referenced_col_names[i]
- = mem_heap_strdup(foreign->heap, column_names[i]);
+ = mem_heap_strdup(foreign->heap, ref_column_names[i]);
}
/* We found an ok constraint definition: add to the lists */
@@ -5253,7 +5625,8 @@ dict_table_replace_index_in_foreign_list(
foreign->referenced_table,
foreign->referenced_col_names,
foreign->n_fields, index,
- /*check_charsets=*/TRUE, /*check_null=*/FALSE);
+ /*check_charsets=*/TRUE, /*check_null=*/FALSE,
+ NULL, NULL, NULL);
ut_ad(new_index || !trx->check_foreigns);
ut_ad(!new_index || new_index->table == index->table);
diff --git a/storage/innobase/dict/dict0load.c b/storage/innobase/dict/dict0load.c
index 4d012c5cf50..22de23af7ee 100644
--- a/storage/innobase/dict/dict0load.c
+++ b/storage/innobase/dict/dict0load.c
@@ -1889,7 +1889,7 @@ err_exit:
/* Initialize table foreign_child value. Its value could be
changed when dict_load_foreigns() is called below */
table->fk_max_recusive_level = 0;
-
+
/* If the force recovery flag is set, we open the table irrespective
of the error condition, since the user may want to dump data from the
clustered index. However we load the foreign key information only if
@@ -2124,6 +2124,23 @@ dict_load_foreign_cols(
ut_a(!rec_get_deleted_flag(rec, 0));
field = rec_get_nth_field_old(rec, 0, &len);
+
+ if (len != id_len || ut_memcmp(id, field, len) != 0) {
+ char * tmp,*tmp2;
+
+ tmp = mem_heap_alloc(foreign->heap, id_len+4);
+ ut_memcpy(tmp, id, id_len);
+ tmp[id_len]='\0';
+ tmp2 = mem_heap_alloc(foreign->heap, len+4);
+ ut_memcpy(tmp2, id, len);
+ tmp2[len]='\0';
+ fprintf(stderr, "InnoDB: Error: len = %lu != id_len %lu\n",
+ len, id_len);
+ fprintf(stderr, "InnoDB: Error: id %s != field %s\n",
+ tmp, tmp2);
+
+ }
+
ut_a(len == id_len);
ut_a(ut_memcmp(id, field, len) == 0);
@@ -2495,6 +2512,7 @@ contain the same set of foreign key objects; and check if
dict_table_t::referenced_rbt and dict_table::referenced_list contain
the same set of foreign key objects.
@return TRUE if correct, FALSE otherwise. */
+UNIV_INTERN
ibool
dict_table_check_foreign_keys(
/*==========================*/
diff --git a/storage/innobase/fil/fil0fil.c b/storage/innobase/fil/fil0fil.c
index 9dfc3bb1d21..b30e8056c0a 100644
--- a/storage/innobase/fil/fil0fil.c
+++ b/storage/innobase/fil/fil0fil.c
@@ -458,6 +458,21 @@ fil_space_get_by_id(
}
/*******************************************************************//**
+Returns the table space name for a given id, NULL if not found. */
+const char*
+fil_space_get_name(
+/*================*/
+ ulint id) /*!< in: space id */
+{
+ fil_space_t* space;
+
+ mutex_enter(&fil_system->mutex);
+ space = fil_space_get_by_id(id);
+ mutex_exit(&fil_system->mutex);
+
+ return (space == NULL ? NULL : space->name);
+}
+/*******************************************************************//**
Returns the table space by a given name, NULL if not found. */
UNIV_INLINE
fil_space_t*
@@ -4108,6 +4123,37 @@ fil_extend_space_to_desired_size(
start_page_no = space->size;
file_start_page_no = space->size - node->size;
+#ifdef HAVE_POSIX_FALLOCATE
+ if (srv_use_posix_fallocate) {
+ ib_int64_t start_offset = start_page_no * page_size;
+ ib_int64_t end_offset = (size_after_extend - start_page_no) * page_size;
+ ib_int64_t desired_size = size_after_extend*page_size;
+
+ mutex_exit(&fil_system->mutex);
+
+ if (posix_fallocate(node->handle, start_offset, end_offset) == -1) {
+ fprintf(stderr, "InnoDB: Error: preallocating file "
+ "space for file \'%s\' failed. Current size "
+ " %lld, len %lld, desired size %lld\n",
+ node->name, start_offset, end_offset, desired_size);
+ success = FALSE;
+ } else {
+ success = TRUE;
+ }
+
+ mutex_enter(&fil_system->mutex);
+
+ if (success) {
+ node->size += (size_after_extend - start_page_no);
+ space->size += (size_after_extend - start_page_no);
+ os_has_said_disk_full = FALSE;
+ }
+
+ fil_node_complete_io(node, fil_system, OS_FILE_READ);
+ goto complete_io;
+ }
+#endif
+
/* Extend at most 64 pages at a time */
buf_size = ut_min(64, size_after_extend - start_page_no) * page_size;
buf2 = mem_alloc(buf_size + page_size);
@@ -4162,6 +4208,8 @@ fil_extend_space_to_desired_size(
fil_node_complete_io(node, fil_system, OS_FILE_WRITE);
+complete_io:
+
*actual_size = space->size;
#ifndef UNIV_HOTBACKUP
diff --git a/storage/innobase/ha/ha0ha.c b/storage/innobase/ha/ha0ha.c
index 47ea2937f17..22a237d189f 100644
--- a/storage/innobase/ha/ha0ha.c
+++ b/storage/innobase/ha/ha0ha.c
@@ -101,7 +101,7 @@ ha_insert_for_fold_func(
#if defined UNIV_AHI_DEBUG || defined UNIV_DEBUG
buf_block_t* block, /*!< in: buffer block containing the data */
#endif /* UNIV_AHI_DEBUG || UNIV_DEBUG */
- const rec_t* data) /*!< in: data, must not be NULL */
+ rec_t* data) /*!< in: data, must not be NULL */
{
hash_cell_t* cell;
ha_node_t* node;
@@ -227,11 +227,11 @@ ha_search_and_update_if_found_func(
/*===============================*/
hash_table_t* table, /*!< in/out: hash table */
ulint fold, /*!< in: folded value of the searched data */
- const rec_t* data, /*!< in: pointer to the data */
+ rec_t* data, /*!< in: pointer to the data */
#if defined UNIV_AHI_DEBUG || defined UNIV_DEBUG
buf_block_t* new_block,/*!< in: block containing new_data */
#endif /* UNIV_AHI_DEBUG || UNIV_DEBUG */
- const rec_t* new_data)/*!< in: new pointer to the data */
+ rec_t* new_data)/*!< in: new pointer to the data */
{
ha_node_t* node;
diff --git a/storage/innobase/handler/ha_innodb.cc b/storage/innobase/handler/ha_innodb.cc
index 1c6763ef93a..b3e6b3c7310 100644
--- a/storage/innobase/handler/ha_innodb.cc
+++ b/storage/innobase/handler/ha_innodb.cc
@@ -50,11 +50,14 @@ this program; if not, write to the Free Software Foundation, Inc.,
#include <debug_sync.h> // DEBUG_SYNC
#include <mysys_err.h>
#include <mysql/plugin.h>
-#include <mysql/innodb_priv.h>
+#include <innodb_priv.h>
#include <mysql/psi/psi.h>
#include <my_sys.h>
#include <my_check_opt.h>
+#ifdef _WIN32
+#include <io.h>
+#endif
/** @file ha_innodb.cc */
/* Include necessary InnoDB headers */
@@ -90,7 +93,6 @@ extern "C" {
#include "ibuf0ibuf.h"
enum_tx_isolation thd_get_trx_isolation(const THD* thd);
-
}
#include "ha_innodb.h"
@@ -103,7 +105,6 @@ enum_tx_isolation thd_get_trx_isolation(const THD* thd);
/** to protect innobase_open_files */
static mysql_mutex_t innobase_share_mutex;
/** to force correct commit order in binlog */
-static mysql_mutex_t prepare_commit_mutex;
static ulong commit_threads = 0;
static mysql_cond_t commit_cond;
static mysql_mutex_t commit_cond_m;
@@ -164,6 +165,8 @@ static my_bool innobase_file_format_check = TRUE;
static my_bool innobase_log_archive = FALSE;
static char* innobase_log_arch_dir = NULL;
#endif /* UNIV_LOG_ARCHIVE */
+static my_bool innobase_use_atomic_writes = FALSE;
+static my_bool innobase_use_fallocate = TRUE;
static my_bool innobase_use_doublewrite = TRUE;
static my_bool innobase_use_checksums = TRUE;
static my_bool innobase_locks_unsafe_for_binlog = FALSE;
@@ -220,14 +223,12 @@ static const char* innobase_change_buffering_values[IBUF_USE_COUNT] = {
/* Keys to register pthread mutexes/cond in the current file with
performance schema */
static mysql_pfs_key_t innobase_share_mutex_key;
-static mysql_pfs_key_t prepare_commit_mutex_key;
static mysql_pfs_key_t commit_cond_mutex_key;
static mysql_pfs_key_t commit_cond_key;
static PSI_mutex_info all_pthread_mutexes[] = {
{&commit_cond_mutex_key, "commit_cond_mutex", 0},
- {&innobase_share_mutex_key, "innobase_share_mutex", 0},
- {&prepare_commit_mutex_key, "prepare_commit_mutex", 0}
+ {&innobase_share_mutex_key, "innobase_share_mutex", 0}
};
static PSI_cond_info all_innodb_conds[] = {
@@ -340,6 +341,8 @@ static PSI_file_info all_innodb_files[] = {
static INNOBASE_SHARE *get_share(const char *table_name);
static void free_share(INNOBASE_SHARE *share);
static int innobase_close_connection(handlerton *hton, THD* thd);
+static void innobase_kill_query(handlerton *hton, THD* thd, enum thd_kill_levels level);
+static void innobase_commit_ordered(handlerton *hton, THD* thd, bool all);
static int innobase_commit(handlerton *hton, THD* thd, bool all);
static int innobase_rollback(handlerton *hton, THD* thd, bool all);
static int innobase_rollback_to_savepoint(handlerton *hton, THD* thd,
@@ -933,8 +936,7 @@ convert_error_code_to_mysql(
return(0);
case DB_INTERRUPTED:
- my_error(ER_QUERY_INTERRUPTED, MYF(0));
- return(-1);
+ return(HA_ERR_ABORTED_BY_USER);
case DB_FOREIGN_EXCEED_MAX_CASCADE:
push_warning_printf(thd, MYSQL_ERROR::WARN_LEVEL_WARN,
@@ -1041,7 +1043,7 @@ convert_error_code_to_mysql(
"or ROW_FORMAT=COMPRESSED ": "",
prefix ? DICT_MAX_FIXED_COL_LEN : 0);
return(HA_ERR_TO_BIG_ROW);
- }
+ }
case DB_TOO_BIG_INDEX_COL:
my_error(ER_INDEX_COLUMN_TOO_LONG, MYF(0),
@@ -1462,6 +1464,15 @@ innobase_next_autoinc(
ut_a(block > 0);
ut_a(max_value > 0);
+ /*
+ Allow auto_increment to go over max_value up to max ulonglong.
+ This allows us to detect that all values are exhausted.
+ If we don't do this, we will return max_value several times
+ and get duplicate key errors instead of auto increment value
+ out of range.
+ */
+ max_value= (~(ulonglong) 0);
+
/* According to MySQL documentation, if the offset is greater than
the step then the offset is ignored. */
if (offset > block) {
@@ -1493,10 +1504,11 @@ innobase_next_autoinc(
if (next_value == 0) {
ulonglong next;
- if (current > offset) {
+ if (current >= offset) {
next = (current - offset) / step;
} else {
- next = (offset - current) / step;
+ next = 0;
+ block -= step;
}
ut_a(max_value > next);
@@ -1536,7 +1548,6 @@ innobase_trx_init(
trx_t* trx) /*!< in/out: InnoDB transaction handle */
{
DBUG_ENTER("innobase_trx_init");
- DBUG_ASSERT(EQ_CURRENT_THD(thd));
DBUG_ASSERT(thd == trx->mysql_thd);
trx->check_foreigns = !thd_test_options(
@@ -1585,10 +1596,9 @@ check_trx_exists(
{
trx_t*& trx = thd_to_trx(thd);
- ut_ad(EQ_CURRENT_THD(thd));
-
if (trx == NULL) {
trx = innobase_trx_allocate(thd);
+ thd_set_ha_data(thd, innodb_hton_ptr, trx);
} else if (UNIV_UNLIKELY(trx->magic_n != TRX_MAGIC_N)) {
mem_analyze_corruption(trx);
ut_error;
@@ -1612,15 +1622,15 @@ trx_is_registered_for_2pc(
}
/*********************************************************************//**
-Note that a transaction owns the prepare_commit_mutex. */
+Note that innobase_commit_ordered() was run. */
static inline
void
-trx_owns_prepare_commit_mutex_set(
+trx_set_active_commit_ordered(
/*==============================*/
trx_t* trx) /* in: transaction */
{
ut_a(trx_is_registered_for_2pc(trx));
- trx->owns_prepare_mutex = 1;
+ trx->active_commit_ordered = 1;
}
/*********************************************************************//**
@@ -1632,7 +1642,7 @@ trx_register_for_2pc(
trx_t* trx) /* in: transaction */
{
trx->is_registered = 1;
- ut_ad(trx->owns_prepare_mutex == 0);
+ ut_ad(trx->active_commit_ordered == 0);
}
/*********************************************************************//**
@@ -1644,19 +1654,18 @@ trx_deregister_from_2pc(
trx_t* trx) /* in: transaction */
{
trx->is_registered = 0;
- trx->owns_prepare_mutex = 0;
+ trx->active_commit_ordered = 0;
}
/*********************************************************************//**
-Check whether atransaction owns the prepare_commit_mutex.
-@return true if transaction owns the prepare commit mutex */
+Check whether a transaction has active_commit_ordered set */
static inline
bool
-trx_has_prepare_commit_mutex(
+trx_is_active_commit_ordered(
/*=========================*/
const trx_t* trx) /* in: transaction */
{
- return(trx->owns_prepare_mutex == 1);
+ return(trx->active_commit_ordered == 1);
}
/*********************************************************************//**
@@ -2125,7 +2134,7 @@ trx_is_interrupted(
/*===============*/
trx_t* trx) /*!< in: transaction */
{
- return(trx && trx->mysql_thd && thd_killed((THD*) trx->mysql_thd));
+ return(trx && trx->mysql_thd && thd_kill_level((THD*) trx->mysql_thd));
}
/**********************************************************************//**
@@ -2236,6 +2245,8 @@ innobase_init(
innobase_hton->savepoint_set=innobase_savepoint;
innobase_hton->savepoint_rollback=innobase_rollback_to_savepoint;
innobase_hton->savepoint_release=innobase_release_savepoint;
+ innobase_hton->prepare_ordered=NULL;
+ innobase_hton->commit_ordered=innobase_commit_ordered;
innobase_hton->commit=innobase_commit;
innobase_hton->rollback=innobase_rollback;
innobase_hton->prepare=innobase_xa_prepare;
@@ -2251,9 +2262,10 @@ innobase_init(
innobase_hton->start_consistent_snapshot=innobase_start_trx_and_assign_read_view;
innobase_hton->flush_logs=innobase_flush_logs;
innobase_hton->show_status=innobase_show_status;
- innobase_hton->flags=HTON_SUPPORTS_FOREIGN_KEYS;
+ innobase_hton->flags=HTON_EXTENDED_KEYS | HTON_SUPPORTS_FOREIGN_KEYS;
innobase_hton->release_temporary_latches=innobase_release_temporary_latches;
innobase_hton->alter_table_flags = innobase_alter_table_flags;
+ innobase_hton->kill_query = innobase_kill_query;
ut_a(DATA_MYSQL_TRUE_VARCHAR == (ulint)MYSQL_TYPE_VARCHAR);
@@ -2520,6 +2532,38 @@ innobase_change_buffering_inited_ok:
innobase_commit_concurrency_init_default();
+#ifdef HAVE_POSIX_FALLOCATE
+ srv_use_posix_fallocate = (ibool) innobase_use_fallocate;
+#endif
+ srv_use_atomic_writes = (ibool) innobase_use_atomic_writes;
+ if (innobase_use_atomic_writes) {
+ fprintf(stderr, "InnoDB: using atomic writes.\n");
+
+ /* Force doublewrite buffer off, atomic writes replace it. */
+ if (srv_use_doublewrite_buf) {
+ fprintf(stderr, "InnoDB: Switching off doublewrite buffer "
+ "because of atomic writes.\n");
+ innobase_use_doublewrite = srv_use_doublewrite_buf = FALSE;
+ }
+
+ /* Force O_DIRECT on Unixes (on Windows writes are always unbuffered)*/
+#ifndef _WIN32
+ if(!innobase_file_flush_method ||
+ !strstr(innobase_file_flush_method, "O_DIRECT")) {
+ innobase_file_flush_method =
+ srv_file_flush_method_str = (char*)"O_DIRECT";
+ fprintf(stderr, "InnoDB: using O_DIRECT due to atomic writes.\n");
+ }
+#endif
+#ifdef HAVE_POSIX_FALLOCATE
+ /* Due to a bug in directFS, using atomics needs
+ * posix_fallocate to extend the file
+ * pwrite() past end of the file won't work
+ */
+ srv_use_posix_fallocate = TRUE;
+#endif
+ }
+
#ifdef HAVE_PSI_INTERFACE
/* Register keys with MySQL performance schema */
if (PSI_server) {
@@ -2578,8 +2622,6 @@ innobase_change_buffering_inited_ok:
mysql_mutex_init(innobase_share_mutex_key,
&innobase_share_mutex,
MY_MUTEX_INIT_FAST);
- mysql_mutex_init(prepare_commit_mutex_key,
- &prepare_commit_mutex, MY_MUTEX_INIT_FAST);
mysql_mutex_init(commit_cond_mutex_key,
&commit_cond_m, MY_MUTEX_INIT_FAST);
mysql_cond_init(commit_cond_key, &commit_cond, NULL);
@@ -2617,6 +2659,14 @@ innobase_end(
if (innodb_inited) {
+ THD *thd= current_thd;
+ if (thd) { // may be UNINSTALL PLUGIN statement
+ trx_t* trx = thd_to_trx(thd);
+ if (trx) {
+ trx_free_for_mysql(trx);
+ }
+ }
+
srv_fast_shutdown = (ulint) innobase_fast_shutdown;
innodb_inited = 0;
hash_table_free(innobase_open_tables);
@@ -2627,7 +2677,6 @@ innobase_end(
srv_free_paths_and_sizes();
my_free(internal_innobase_data_file_path);
mysql_mutex_destroy(&innobase_share_mutex);
- mysql_mutex_destroy(&prepare_commit_mutex);
mysql_mutex_destroy(&commit_cond_m);
mysql_cond_destroy(&commit_cond);
}
@@ -2744,6 +2793,109 @@ innobase_start_trx_and_assign_read_view(
DBUG_RETURN(0);
}
+static
+void
+innobase_commit_ordered_2(
+/*============*/
+ trx_t* trx, /*!< in: Innodb transaction */
+ THD* thd) /*!< in: MySQL thread handle */
+{
+ ulonglong tmp_pos;
+ DBUG_ENTER("innobase_commit_ordered");
+
+ /* We need current binlog position for ibbackup to work.
+ Note, the position is current because commit_ordered is guaranteed
+ to be called in same sequenece as writing to binlog. */
+
+retry:
+ if (innobase_commit_concurrency > 0) {
+ mysql_mutex_lock(&commit_cond_m);
+ commit_threads++;
+
+ if (commit_threads > innobase_commit_concurrency) {
+ commit_threads--;
+ mysql_cond_wait(&commit_cond,
+ &commit_cond_m);
+ mysql_mutex_unlock(&commit_cond_m);
+ goto retry;
+ }
+ else {
+ mysql_mutex_unlock(&commit_cond_m);
+ }
+ }
+
+ mysql_bin_log_commit_pos(thd, &tmp_pos, &(trx->mysql_log_file_name));
+ trx->mysql_log_offset = (ib_int64_t) tmp_pos;
+
+ /* Don't do write + flush right now. For group commit
+ to work we want to do the flush in the innobase_commit()
+ method, which runs without holding any locks. */
+ trx->flush_log_later = TRUE;
+ innobase_commit_low(trx);
+ trx->flush_log_later = FALSE;
+
+ if (innobase_commit_concurrency > 0) {
+ mysql_mutex_lock(&commit_cond_m);
+ commit_threads--;
+ mysql_cond_signal(&commit_cond);
+ mysql_mutex_unlock(&commit_cond_m);
+ }
+
+ DBUG_VOID_RETURN;
+}
+
+/*****************************************************************//**
+Perform the first, fast part of InnoDB commit.
+
+Doing it in this call ensures that we get the same commit order here
+as in binlog and any other participating transactional storage engines.
+
+Note that we want to do as little as really needed here, as we run
+under a global mutex. The expensive fsync() is done later, in
+innobase_commit(), without a lock so group commit can take place.
+
+Note also that this method can be called from a different thread than
+the one handling the rest of the transaction. */
+static
+void
+innobase_commit_ordered(
+/*============*/
+ handlerton *hton, /*!< in: Innodb handlerton */
+ THD* thd, /*!< in: MySQL thread handle of the user for whom
+ the transaction should be committed */
+ bool all) /*!< in: TRUE - commit transaction
+ FALSE - the current SQL statement ended */
+{
+ trx_t* trx;
+ DBUG_ENTER("innobase_commit_ordered");
+ DBUG_ASSERT(hton == innodb_hton_ptr);
+
+ trx = check_trx_exists(thd);
+
+ /* Since we will reserve the kernel mutex, we must not be holding the
+ search system latch, or we will disobey the latching order. But we
+ already released it in innobase_xa_prepare() (if not before), so just
+ have an assert here.*/
+ ut_ad(!trx->has_search_latch);
+
+ if (!trx_is_registered_for_2pc(trx) && trx_is_started(trx)) {
+ /* We cannot throw error here; instead we will catch this error
+ again in innobase_commit() and report it from there. */
+ DBUG_VOID_RETURN;
+ }
+
+ /* commit_ordered is only called when committing the whole transaction
+ (or an SQL statement when autocommit is on). */
+ DBUG_ASSERT(all ||
+ (!thd_test_options(thd, OPTION_NOT_AUTOCOMMIT | OPTION_BEGIN)));
+
+ innobase_commit_ordered_2(trx, thd);
+
+ trx_set_active_commit_ordered(trx);
+
+ DBUG_VOID_RETURN;
+}
+
/*****************************************************************//**
Commits a transaction in an InnoDB database or marks an SQL statement
ended.
@@ -2769,7 +2921,7 @@ innobase_commit(
/* Since we will reserve the kernel mutex, we have to release
the search system latch first to obey the latching order. */
- if (trx->has_search_latch) {
+ if (trx->has_search_latch && !trx_is_active_commit_ordered(trx)) {
trx_search_latch_release_if_reserved(trx);
}
@@ -2787,68 +2939,19 @@ innobase_commit(
if (all
|| (!thd_test_options(thd, OPTION_NOT_AUTOCOMMIT | OPTION_BEGIN))) {
- /* We were instructed to commit the whole transaction, or
- this is an SQL statement end and autocommit is on */
-
- /* We need current binlog position for ibbackup to work.
- Note, the position is current because of
- prepare_commit_mutex */
-retry:
- if (innobase_commit_concurrency > 0) {
- mysql_mutex_lock(&commit_cond_m);
- commit_threads++;
-
- if (commit_threads > innobase_commit_concurrency) {
- commit_threads--;
- mysql_cond_wait(&commit_cond,
- &commit_cond_m);
- mysql_mutex_unlock(&commit_cond_m);
- goto retry;
- }
- else {
- mysql_mutex_unlock(&commit_cond_m);
- }
- }
-
- /* The following calls to read the MySQL binary log
- file name and the position return consistent results:
- 1) Other InnoDB transactions cannot intervene between
- these calls as we are holding prepare_commit_mutex.
- 2) Binary logging of other engines is not relevant
- to InnoDB as all InnoDB requires is that committing
- InnoDB transactions appear in the same order in the
- MySQL binary log as they appear in InnoDB logs.
- 3) A MySQL log file rotation cannot happen because
- MySQL protects against this by having a counter of
- transactions in prepared state and it only allows
- a rotation when the counter drops to zero. See
- LOCK_prep_xids and COND_prep_xids in log.cc. */
- trx->mysql_log_file_name = mysql_bin_log_file_name();
- trx->mysql_log_offset = (ib_int64_t) mysql_bin_log_file_pos();
-
- /* Don't do write + flush right now. For group commit
- to work we want to do the flush after releasing the
- prepare_commit_mutex. */
- trx->flush_log_later = TRUE;
- innobase_commit_low(trx);
- trx->flush_log_later = FALSE;
-
- if (innobase_commit_concurrency > 0) {
- mysql_mutex_lock(&commit_cond_m);
- commit_threads--;
- mysql_cond_signal(&commit_cond);
- mysql_mutex_unlock(&commit_cond_m);
+ /* Run the fast part of commit if we did not already. */
+ if (!trx_is_active_commit_ordered(trx)) {
+ innobase_commit_ordered_2(trx, thd);
}
- if (trx_has_prepare_commit_mutex(trx)) {
-
- mysql_mutex_unlock(&prepare_commit_mutex);
- }
-
- trx_deregister_from_2pc(trx);
+ /* We were instructed to commit the whole transaction, or
+ this is an SQL statement end and autocommit is on */
- /* Now do a write + flush of logs. */
+ /* We did the first part already in innobase_commit_ordered(),
+ Now finish by doing a write + flush of logs. */
trx_commit_complete_for_mysql(trx);
+ trx_deregister_from_2pc(trx);
+
} else {
/* We just mark the SQL statement ended and do not do a
transaction commit */
@@ -2921,9 +3024,6 @@ innobase_rollback(
|| !thd_test_options(thd, OPTION_NOT_AUTOCOMMIT | OPTION_BEGIN)) {
error = trx_rollback_for_mysql(trx);
- if (trx_has_prepare_commit_mutex(trx)) {
- mysql_mutex_unlock(&prepare_commit_mutex);
- }
trx_deregister_from_2pc(trx);
} else {
error = trx_rollback_last_sql_stat_for_mysql(trx);
@@ -3125,6 +3225,35 @@ innobase_close_connection(
}
+/*****************************************************************//**
+Cancel any pending lock request associated with the current THD. */
+static
+void
+innobase_kill_query(
+/*======================*/
+ handlerton* hton, /*!< in: innobase handlerton */
+ THD* thd, /*!< in: MySQL thread being killed */
+ enum thd_kill_levels level) /*!< in: kill level */
+{
+ trx_t* trx;
+ DBUG_ENTER("innobase_kill_query");
+ DBUG_ASSERT(hton == innodb_hton_ptr);
+
+ mutex_enter(&kernel_mutex);
+
+ trx = thd_to_trx(thd);
+
+ /* Cancel a pending lock request. */
+ if (trx && trx->wait_lock) {
+ lock_cancel_waiting_and_release(trx->wait_lock);
+ }
+
+ mutex_exit(&kernel_mutex);
+
+ DBUG_VOID_RETURN;
+}
+
+
/*************************************************************************//**
** InnoDB database tables
*****************************************************************************/
@@ -3231,12 +3360,15 @@ UNIV_INTERN
ulong
ha_innobase::index_flags(
/*=====================*/
- uint,
+ uint index,
uint,
bool)
const
{
- return(HA_READ_NEXT | HA_READ_PREV | HA_READ_ORDER
+ ulong extra_flag= 0;
+ if (table && index == table->s->primary_key)
+ extra_flag= HA_CLUSTERED_INDEX;
+ return(HA_READ_NEXT | HA_READ_PREV | HA_READ_ORDER | extra_flag
| HA_READ_RANGE | HA_KEYREAD_ONLY);
}
@@ -3311,7 +3443,7 @@ Normalizes a table name string. A normalized name consists of the
database name catenated to '/' and table name. An example:
test/mytable. On Windows normalization puts both the database name and the
table name always to lower case if "set_lower_case" is set to TRUE. */
-static
+extern "C" UNIV_INTERN
void
normalize_table_name_low(
/*=====================*/
@@ -3922,7 +4054,7 @@ ha_innobase::open(
}
ib_table = dict_table_get(
- par_case_name, FALSE, ignore_err);
+ par_case_name, TRUE, ignore_err);
}
if (ib_table) {
#ifndef __WIN__
@@ -4373,90 +4505,64 @@ get_innobase_type_from_mysql_type(
8 bits: this is used in ibuf and also when DATA_NOT_NULL is ORed to
the type */
- DBUG_ASSERT((ulint)MYSQL_TYPE_STRING < 256);
- DBUG_ASSERT((ulint)MYSQL_TYPE_VAR_STRING < 256);
- DBUG_ASSERT((ulint)MYSQL_TYPE_DOUBLE < 256);
- DBUG_ASSERT((ulint)MYSQL_TYPE_FLOAT < 256);
- DBUG_ASSERT((ulint)MYSQL_TYPE_DECIMAL < 256);
+ compile_time_assert((ulint)MYSQL_TYPE_STRING < 256);
+ compile_time_assert((ulint)MYSQL_TYPE_VAR_STRING < 256);
+ compile_time_assert((ulint)MYSQL_TYPE_DOUBLE < 256);
+ compile_time_assert((ulint)MYSQL_TYPE_FLOAT < 256);
+ compile_time_assert((ulint)MYSQL_TYPE_DECIMAL < 256);
- if (field->flags & UNSIGNED_FLAG) {
+ *unsigned_flag = 0;
+ switch (field->key_type()) {
+ case HA_KEYTYPE_USHORT_INT:
+ case HA_KEYTYPE_ULONG_INT:
+ case HA_KEYTYPE_UINT24:
+ case HA_KEYTYPE_ULONGLONG:
*unsigned_flag = DATA_UNSIGNED;
- } else {
- *unsigned_flag = 0;
- }
-
- if (field->real_type() == MYSQL_TYPE_ENUM
- || field->real_type() == MYSQL_TYPE_SET) {
-
- /* MySQL has field->type() a string type for these, but the
- data is actually internally stored as an unsigned integer
- code! */
-
- *unsigned_flag = DATA_UNSIGNED; /* MySQL has its own unsigned
- flag set to zero, even though
- internally this is an unsigned
- integer type */
+ /* fall through */
+ case HA_KEYTYPE_SHORT_INT:
+ case HA_KEYTYPE_LONG_INT:
+ case HA_KEYTYPE_INT24:
+ case HA_KEYTYPE_INT8:
+ case HA_KEYTYPE_LONGLONG:
return(DATA_INT);
- }
-
- switch (field->type()) {
- /* NOTE that we only allow string types in DATA_MYSQL and
- DATA_VARMYSQL */
- case MYSQL_TYPE_VAR_STRING: /* old <= 4.1 VARCHAR */
- case MYSQL_TYPE_VARCHAR: /* new >= 5.0.3 true VARCHAR */
- if (field->binary()) {
- return(DATA_BINARY);
- } else if (strcmp(
- field->charset()->name,
- "latin1_swedish_ci") == 0) {
+ case HA_KEYTYPE_FLOAT:
+ return(DATA_FLOAT);
+ case HA_KEYTYPE_DOUBLE:
+ return(DATA_DOUBLE);
+ case HA_KEYTYPE_BINARY:
+ if (field->type() == MYSQL_TYPE_TINY)
+ { // compatibility workaround
+ *unsigned_flag= DATA_UNSIGNED;
+ return DATA_INT;
+ }
+ return(DATA_FIXBINARY);
+ case HA_KEYTYPE_VARBINARY2:
+ if (field->type() != MYSQL_TYPE_VARCHAR)
+ return(DATA_BLOB);
+ /* fall through */
+ case HA_KEYTYPE_VARBINARY1:
+ return(DATA_BINARY);
+ case HA_KEYTYPE_VARTEXT2:
+ if (field->type() != MYSQL_TYPE_VARCHAR)
+ return(DATA_BLOB);
+ /* fall through */
+ case HA_KEYTYPE_VARTEXT1:
+ if (field->charset() == &my_charset_latin1) {
return(DATA_VARCHAR);
} else {
return(DATA_VARMYSQL);
}
- case MYSQL_TYPE_BIT:
- case MYSQL_TYPE_STRING: if (field->binary()) {
-
- return(DATA_FIXBINARY);
- } else if (strcmp(
- field->charset()->name,
- "latin1_swedish_ci") == 0) {
+ case HA_KEYTYPE_TEXT:
+ if (field->charset() == &my_charset_latin1) {
return(DATA_CHAR);
} else {
return(DATA_MYSQL);
}
- case MYSQL_TYPE_NEWDECIMAL:
- return(DATA_FIXBINARY);
- case MYSQL_TYPE_LONG:
- case MYSQL_TYPE_LONGLONG:
- case MYSQL_TYPE_TINY:
- case MYSQL_TYPE_SHORT:
- case MYSQL_TYPE_INT24:
- case MYSQL_TYPE_DATE:
- case MYSQL_TYPE_DATETIME:
- case MYSQL_TYPE_YEAR:
- case MYSQL_TYPE_NEWDATE:
- case MYSQL_TYPE_TIME:
- case MYSQL_TYPE_TIMESTAMP:
- return(DATA_INT);
- case MYSQL_TYPE_FLOAT:
- return(DATA_FLOAT);
- case MYSQL_TYPE_DOUBLE:
- return(DATA_DOUBLE);
- case MYSQL_TYPE_DECIMAL:
+ case HA_KEYTYPE_NUM:
return(DATA_DECIMAL);
- case MYSQL_TYPE_GEOMETRY:
- case MYSQL_TYPE_TINY_BLOB:
- case MYSQL_TYPE_MEDIUM_BLOB:
- case MYSQL_TYPE_BLOB:
- case MYSQL_TYPE_LONG_BLOB:
- return(DATA_BLOB);
- case MYSQL_TYPE_NULL:
- /* MySQL currently accepts "NULL" datatype, but will
- reject such datatype in the next release. We will cope
- with it and not trigger assertion failure in 5.1 */
- break;
- default:
+ case HA_KEYTYPE_BIT:
+ case HA_KEYTYPE_END:
ut_error;
}
@@ -4999,12 +5105,15 @@ ha_innobase::innobase_lock_autoinc(void)
break;
case AUTOINC_NEW_STYLE_LOCKING:
- /* For simple (single/multi) row INSERTs, we fallback to the
- old style only if another transaction has already acquired
- the AUTOINC lock on behalf of a LOAD FILE or INSERT ... SELECT
- etc. type of statement. */
+ /* For simple (single/multi) row INSERTs/REPLACEs and RBR
+ events, we fallback to the old style only if another
+ transaction has already acquired the AUTOINC lock on
+ behalf of a LOAD FILE or INSERT ... SELECT etc. type of
+ statement. */
if (thd_sql_command(user_thd) == SQLCOM_INSERT
- || thd_sql_command(user_thd) == SQLCOM_REPLACE) {
+ || thd_sql_command(user_thd) == SQLCOM_REPLACE
+ || thd_sql_command(user_thd) == SQLCOM_END // RBR event
+ ) {
dict_table_t* table = prebuilt->table;
/* Acquire the AUTOINC mutex. */
@@ -5013,9 +5122,11 @@ ha_innobase::innobase_lock_autoinc(void)
/* We need to check that another transaction isn't
already holding the AUTOINC lock on the table. */
if (table->n_waiting_or_granted_auto_inc_locks) {
- /* Release the mutex to avoid deadlocks. */
+ /* Release the mutex to avoid deadlocks and
+ fall back to old style locking. */
dict_table_autoinc_unlock(table);
} else {
+ /* Do not fall back to old style locking. */
break;
}
}
@@ -5104,9 +5215,9 @@ ha_innobase::write_row(
DBUG_ENTER("ha_innobase::write_row");
if (prebuilt->trx != trx) {
- sql_print_error("The transaction object for the table handle is at "
- "%p, but for the current thread it is at %p",
- (const void*) prebuilt->trx, (const void*) trx);
+ sql_print_error("The transaction object for the table handle is at "
+ "%p, but for the current thread it is at %p",
+ (const void*) prebuilt->trx, (const void*) trx);
fputs("InnoDB: Dump of 200 bytes around prebuilt: ", stderr);
ut_print_buf(stderr, ((const byte*)prebuilt) - 100, 200);
@@ -5217,7 +5328,10 @@ no_commit:
goto report_error;
}
- /* MySQL errors are passed straight back. */
+ /* MySQL errors are passed straight back. except for
+ HA_ERR_AUTO_INC_READ_FAILED. This can only happen
+ for values out of range.
+ */
error_result = (int) error;
goto func_exit;
}
@@ -6119,7 +6233,8 @@ ha_innobase::change_active_index(
/* The caller seems to ignore this. Thus, we must check
this again in row_search_for_mysql(). */
- DBUG_RETURN(HA_ERR_TABLE_DEF_CHANGED);
+ DBUG_RETURN(convert_error_code_to_mysql(DB_MISSING_HISTORY,
+ 0, NULL));
}
ut_a(prebuilt->search_tuple != 0);
@@ -6185,6 +6300,11 @@ ha_innobase::general_fetch(
DBUG_ENTER("general_fetch");
+ /* If transaction is not startted do not continue, instead return a error code. */
+ if(!(prebuilt->sql_stat_start || (prebuilt->trx && prebuilt->trx->conc_state == 1))) {
+ DBUG_RETURN(HA_ERR_END_OF_FILE);
+ }
+
ut_a(prebuilt->trx == thd_to_trx(user_thd));
innodb_srv_conc_enter_innodb(prebuilt->trx);
@@ -7762,6 +7882,7 @@ ha_innobase::records_in_range(
ib_int64_t n_rows;
ulint mode1;
ulint mode2;
+ uint key_parts;
mem_heap_t* heap;
DBUG_ENTER("records_in_range");
@@ -7801,14 +7922,19 @@ ha_innobase::records_in_range(
goto func_exit;
}
- heap = mem_heap_create(2 * (key->key_parts * sizeof(dfield_t)
- + sizeof(dtuple_t)));
+ key_parts= key->key_parts;
+ if ((min_key && min_key->keypart_map>=(key_part_map) (1<<key_parts)) ||
+ (max_key && max_key->keypart_map>=(key_part_map) (1<<key_parts)))
+ key_parts= key->ext_key_parts;
+
+ heap = mem_heap_create(2 * (key_parts * sizeof(dfield_t)
+ + sizeof(dtuple_t)));
- range_start = dtuple_create(heap, key->key_parts);
- dict_index_copy_types(range_start, index, key->key_parts);
+ range_start = dtuple_create(heap, key_parts);
+ dict_index_copy_types(range_start, index, key_parts);
- range_end = dtuple_create(heap, key->key_parts);
- dict_index_copy_types(range_end, index, key->key_parts);
+ range_end = dtuple_create(heap, key_parts);
+ dict_index_copy_types(range_end, index, key_parts);
row_sel_convert_mysql_key_to_innobase(
range_start,
@@ -7966,11 +8092,6 @@ ha_innobase::read_time(
return(handler::read_time(index, ranges, rows));
}
- if (rows <= 2) {
-
- return((double) rows);
- }
-
/* Assume that the read time is proportional to the scan time for all
rows + at most one seek per range. */
@@ -8293,6 +8414,8 @@ ha_innobase::info_low(
}
stats.check_time = 0;
+ stats.mrr_length_per_rec= ref_length + 8; // 8 = max(sizeof(void *));
+
if (stats.records == 0) {
stats.mean_rec_length = 0;
@@ -8322,6 +8445,7 @@ ha_innobase::info_low(
for (i = 0; i < table->s->keys; i++) {
ulong j;
+ rec_per_key = 1;
/* We could get index quickly through internal
index mapping with the index translation table.
The identity of index (match up index name with
@@ -8375,6 +8499,51 @@ ha_innobase::info_low(
rec_per_key >= ~(ulong) 0 ? ~(ulong) 0 :
(ulong) rec_per_key;
}
+
+ KEY *key_info= table->key_info+i;
+ key_part_map ext_key_part_map=
+ key_info->ext_key_part_map;
+
+ if (key_info->key_parts != key_info->ext_key_parts) {
+
+ KEY *pk_key_info= key_info+
+ table->s->primary_key;
+ uint k = key_info->key_parts;
+ ha_rows k_rec_per_key = rec_per_key;
+ uint pk_parts = pk_key_info->key_parts;
+
+ index= innobase_get_index(
+ table->s->primary_key);
+
+ n_rows= ib_table->stat_n_rows;
+
+ for (j = 0; j < pk_parts; j++) {
+
+ if (ext_key_part_map & 1<<j) {
+
+ rec_per_key =
+ innodb_rec_per_key(index,
+ j, stats.records);
+
+ if (rec_per_key == 0) {
+ rec_per_key = 1;
+ }
+ else if (rec_per_key > 1) {
+ rec_per_key =
+ (ha_rows)
+ (k_rec_per_key *
+ (double)rec_per_key /
+ n_rows);
+ }
+
+ key_info->rec_per_key[k++]=
+ rec_per_key >= ~(ulong) 0 ?
+ ~(ulong) 0 :
+ (ulong) rec_per_key;
+
+ }
+ }
+ }
}
dict_table_stats_unlock(ib_table, RW_S_LATCH);
@@ -8641,7 +8810,7 @@ ha_innobase::check(
row_mysql_unlock_data_dictionary(prebuilt->trx);
}
- if (thd_killed(user_thd)) {
+ if (thd_kill_level(user_thd)) {
break;
}
@@ -8697,7 +8866,7 @@ ha_innobase::check(
}
#endif /* defined UNIV_AHI_DEBUG || defined UNIV_DEBUG */
prebuilt->trx->op_info = "";
- if (thd_killed(user_thd)) {
+ if (thd_kill_level(user_thd)) {
my_error(ER_QUERY_INTERRUPTED, MYF(0));
}
@@ -9829,6 +9998,11 @@ innodb_mutex_show_status(
DBUG_RETURN(FALSE);
}
+static MYSQL_SYSVAR_UINT(simulate_comp_failures, srv_simulate_comp_failures,
+ PLUGIN_VAR_NOCMDARG,
+ "Simulate compression failures.",
+ NULL, NULL, 0, 0, 99, 0);
+
static
bool innobase_show_status(handlerton *hton, THD* thd,
stat_print_fn* stat_print,
@@ -10261,13 +10435,17 @@ ha_innobase::get_auto_increment(
/* Not in the middle of a mult-row INSERT. */
} else if (prebuilt->autoinc_last_value == 0) {
set_if_bigger(*first_value, autoinc);
- /* Check for -ve values. */
- } else if (*first_value > col_max_value && trx->n_autoinc_rows > 0) {
- /* Set to next logical value. */
- ut_a(autoinc > trx->n_autoinc_rows);
- *first_value = (autoinc - trx->n_autoinc_rows) - 1;
}
+ if (*first_value > col_max_value)
+ {
+ /* Out of range number. Let handler::update_auto_increment()
+ take care of this */
+ prebuilt->autoinc_last_value = 0;
+ dict_table_autoinc_unlock(prebuilt->table);
+ *nb_reserved_values= 0;
+ return;
+ }
*nb_reserved_values = trx->n_autoinc_rows;
/* With old style AUTOINC locking we only update the table's
@@ -10276,17 +10454,14 @@ ha_innobase::get_auto_increment(
ulonglong current;
ulonglong next_value;
- current = *first_value > col_max_value ? autoinc : *first_value;
+ current = *first_value;
- /* If the increment step of the auto increment column
- decreases then it is not affecting the immediate
- next value in the series. */
- if (prebuilt->autoinc_increment > increment) {
+ if (prebuilt->autoinc_increment != increment) {
current = autoinc - prebuilt->autoinc_increment;
current = innobase_next_autoinc(
- current, 1, increment, 1, col_max_value);
+ current, 1, increment, offset, col_max_value);
dict_table_autoinc_initialize(prebuilt->table, current);
@@ -10629,33 +10804,6 @@ innobase_xa_prepare(
srv_active_wake_master_thread();
- if (thd_sql_command(thd) != SQLCOM_XA_PREPARE
- && (all
- || !thd_test_options(
- thd, OPTION_NOT_AUTOCOMMIT | OPTION_BEGIN))) {
-
- /* For ibbackup to work the order of transactions in binlog
- and InnoDB must be the same. Consider the situation
-
- thread1> prepare; write to binlog; ...
- <context switch>
- thread2> prepare; write to binlog; commit
- thread1> ... commit
-
- To ensure this will not happen we're taking the mutex on
- prepare, and releasing it on commit.
-
- Note: only do it for normal commits, done via ha_commit_trans.
- If 2pc protocol is executed by external transaction
- coordinator, it will be just a regular MySQL client
- executing XA PREPARE and XA COMMIT commands.
- In this case we cannot know how many minutes or hours
- will be between XA PREPARE and XA COMMIT, and we don't want
- to block for undefined period of time. */
- mysql_mutex_lock(&prepare_commit_mutex);
- trx_owns_prepare_commit_mutex_set(trx);
- }
-
return(error);
}
@@ -11484,6 +11632,20 @@ static MYSQL_SYSVAR_BOOL(doublewrite, innobase_use_doublewrite,
"Disable with --skip-innodb-doublewrite.",
NULL, NULL, TRUE);
+static MYSQL_SYSVAR_BOOL(use_atomic_writes, innobase_use_atomic_writes,
+ PLUGIN_VAR_NOCMDARG | PLUGIN_VAR_READONLY,
+ "Prevent partial page writes, via atomic writes."
+ "The option is used to prevent partial writes in case of a crash/poweroff, "
+ "as faster alternative to doublewrite buffer."
+ "Currently this option works only "
+ "on Linux only with FusionIO device, and directFS filesystem.",
+ NULL, NULL, FALSE);
+
+static MYSQL_SYSVAR_BOOL(use_fallocate, innobase_use_fallocate,
+ PLUGIN_VAR_NOCMDARG | PLUGIN_VAR_READONLY,
+ "Preallocate files fast, using operating system functionality. On POSIX systems, posix_fallocate system call is used.",
+ NULL, NULL, FALSE);
+
static MYSQL_SYSVAR_ULONG(io_capacity, srv_io_capacity,
PLUGIN_VAR_RQCMDARG,
"Number of IOPs the server can do. Tunes the background IO rate",
@@ -11626,6 +11788,16 @@ static MYSQL_SYSVAR_ULONGLONG(stats_sample_pages, srv_stats_sample_pages,
"The number of index pages to sample when calculating statistics (default 8)",
NULL, NULL, 8, 1, ~0ULL, 0);
+static MYSQL_SYSVAR_ULONGLONG(stats_modified_counter, srv_stats_modified_counter,
+ PLUGIN_VAR_RQCMDARG,
+ "The number of rows modified before we calculate new statistics (default 0 = current limits)",
+ NULL, NULL, 0, 0, ~0ULL, 0);
+
+static MYSQL_SYSVAR_BOOL(stats_traditional, srv_stats_sample_traditional,
+ PLUGIN_VAR_RQCMDARG,
+ "Enable traditional statistic calculation based on number of configured pages (default true)",
+ NULL, NULL, TRUE);
+
static MYSQL_SYSVAR_BOOL(adaptive_hash_index, btr_search_enabled,
PLUGIN_VAR_OPCMDARG,
"Enable InnoDB adaptive hash index (enabled by default). "
@@ -11817,7 +11989,7 @@ static MYSQL_SYSVAR_ULONG(read_ahead_threshold, srv_read_ahead_threshold,
#ifdef UNIV_DEBUG
static MYSQL_SYSVAR_UINT(trx_rseg_n_slots_debug, trx_rseg_n_slots_debug,
- PLUGIN_VAR_RQCMDARG,
+ PLUGIN_VAR_RQCMDARG | PLUGIN_VAR_NOCMDOPT,
"Debug flags for InnoDB to limit TRX_RSEG_N_SLOTS for trx_rsegf_undo_find_free()",
NULL, NULL, 0, 0, 1024, 0);
@@ -11827,7 +11999,7 @@ static MYSQL_SYSVAR_UINT(limit_optimistic_insert_debug,
NULL, NULL, 0, 0, UINT_MAX32, 0);
static MYSQL_SYSVAR_BOOL(trx_purge_view_update_only_debug,
- srv_purge_view_update_only_debug, PLUGIN_VAR_NOCMDARG,
+ srv_purge_view_update_only_debug, PLUGIN_VAR_NOCMDOPT,
"Pause actual purging any delete-marked records, but merely update the purge view. "
"It is to create artificially the situation the purge view have been updated "
"but the each purges were not done yet.",
@@ -11853,6 +12025,8 @@ static struct st_mysql_sys_var* innobase_system_variables[]= {
MYSQL_SYSVAR(data_file_path),
MYSQL_SYSVAR(data_home_dir),
MYSQL_SYSVAR(doublewrite),
+ MYSQL_SYSVAR(use_atomic_writes),
+ MYSQL_SYSVAR(use_fallocate),
MYSQL_SYSVAR(fast_shutdown),
MYSQL_SYSVAR(file_io_threads),
MYSQL_SYSVAR(read_io_threads),
@@ -11886,6 +12060,8 @@ static struct st_mysql_sys_var* innobase_system_variables[]= {
MYSQL_SYSVAR(rollback_on_timeout),
MYSQL_SYSVAR(stats_on_metadata),
MYSQL_SYSVAR(stats_sample_pages),
+ MYSQL_SYSVAR(stats_modified_counter),
+ MYSQL_SYSVAR(stats_traditional),
MYSQL_SYSVAR(adaptive_hash_index),
MYSQL_SYSVAR(stats_method),
MYSQL_SYSVAR(replication_delay),
@@ -11917,6 +12093,7 @@ static struct st_mysql_sys_var* innobase_system_variables[]= {
MYSQL_SYSVAR(trx_purge_view_update_only_debug),
#endif /* UNIV_DEBUG */
MYSQL_SYSVAR(print_all_deadlocks),
+ MYSQL_SYSVAR(simulate_comp_failures),
NULL
};
@@ -12108,7 +12285,7 @@ innobase_convert_to_filename_charset(
/**********************************************************************
Issue a warning that the row is too big. */
-extern "C"
+extern "C" UNIV_INTERN
void
ib_warn_row_too_big(const dict_table_t* table)
{
@@ -12135,3 +12312,29 @@ ib_warn_row_too_big(const dict_table_t* table)
" ROW_FORMAT=COMPRESSED ": ""
, prefix ? DICT_MAX_FIXED_COL_LEN : 0);
}
+
+/********************************************************************//**
+Helper function to push warnings from InnoDB internals to SQL-layer. */
+extern "C" UNIV_INTERN
+void
+ib_push_warning(
+ trx_t* trx, /*!< in: trx */
+ ulint error, /*!< in: error code to push as warning */
+ const char *format,/*!< in: warning message */
+ ...)
+{
+ va_list args;
+ THD *thd = (THD *)trx->mysql_thd;
+ char *buf;
+#define MAX_BUF_SIZE 4*1024
+
+ va_start(args, format);
+ buf = (char *)my_malloc(MAX_BUF_SIZE, MYF(MY_WME));
+ vsprintf(buf,format, args);
+
+ push_warning_printf(thd, MYSQL_ERROR::WARN_LEVEL_WARN,
+ convert_error_code_to_mysql(error, 0, thd),
+ buf);
+ my_free(buf);
+ va_end(args);
+}
diff --git a/storage/innobase/handler/ha_innodb.h b/storage/innobase/handler/ha_innodb.h
index 94db76fe63d..42aae4dc20e 100644
--- a/storage/innobase/handler/ha_innodb.h
+++ b/storage/innobase/handler/ha_innodb.h
@@ -242,16 +242,6 @@ extern "C" {
struct charset_info_st *thd_charset(MYSQL_THD thd);
LEX_STRING *thd_query_string(MYSQL_THD thd);
-/** Get the file name of the MySQL binlog.
- * @return the name of the binlog file
- */
-const char* mysql_bin_log_file_name(void);
-
-/** Get the current position of the MySQL binlog.
- * @return byte offset from the beginning of the binlog
- */
-ulonglong mysql_bin_log_file_pos(void);
-
/**
Check if a user thread is a replication slave thread
@param thd user thread
@@ -298,6 +288,11 @@ bool thd_binlog_filter_ok(const MYSQL_THD thd);
bool thd_sqlcom_can_generate_row_events(const MYSQL_THD thd);
}
+/** Get the file name and position of the MySQL binlog corresponding to the
+ * current commit.
+ */
+extern void mysql_bin_log_commit_pos(THD *thd, ulonglong *out_pos, const char **out_file);
+
typedef struct trx_struct trx_t;
/********************************************************************//**
@file handler/ha_innodb.h
diff --git a/storage/innobase/handler/handler0alter.cc b/storage/innobase/handler/handler0alter.cc
index 005f14a6f23..735d9fb95d0 100644
--- a/storage/innobase/handler/handler0alter.cc
+++ b/storage/innobase/handler/handler0alter.cc
@@ -24,7 +24,7 @@ Smart ALTER TABLE
#include <unireg.h>
#include <mysqld_error.h>
#include <sql_lex.h> // SQLCOM_CREATE_INDEX
-#include <mysql/innodb_priv.h>
+#include <innodb_priv.h>
extern "C" {
#include "log0log.h"
@@ -65,7 +65,7 @@ innobase_col_to_mysql(
*--ptr = *data++;
}
- if (!(field->flags & UNSIGNED_FLAG)) {
+ if (!(col->prtype & DATA_UNSIGNED)) {
((byte*) dest)[len - 1] ^= 0x80;
}
diff --git a/storage/innobase/handler/i_s.cc b/storage/innobase/handler/i_s.cc
index aa81056c135..afe9c568f18 100644
--- a/storage/innobase/handler/i_s.cc
+++ b/storage/innobase/handler/i_s.cc
@@ -33,7 +33,7 @@ Created July 18, 2007 Vasil Dimov
#include <my_sys.h>
#include "i_s.h"
#include <sql_plugin.h>
-#include <mysql/innodb_priv.h>
+#include <innodb_priv.h>
extern "C" {
#include "btr0types.h"
@@ -157,8 +157,12 @@ do { \
} \
} while (0)
-#if !defined __STRICT_ANSI__ && defined __GNUC__ && (__GNUC__) > 2 && !defined __INTEL_COMPILER
+#if !defined __STRICT_ANSI__ && defined __GNUC__ && (__GNUC__) > 2 && !defined __INTEL_COMPILER && !defined __clang__
+#ifdef HAVE_C99_INITIALIZERS
+#define STRUCT_FLD(name, value) .name = value
+#else
#define STRUCT_FLD(name, value) name: value
+#endif /* HAVE_C99_INITIALIZERS */
#else
#define STRUCT_FLD(name, value) value
#endif
@@ -249,7 +253,7 @@ field_store_time_t(
my_time.time_type = MYSQL_TIMESTAMP_DATETIME;
#endif
- return(field->store_time(&my_time, MYSQL_TIMESTAMP_DATETIME));
+ return(field->store_time(&my_time));
}
/*******************************************************************//**
diff --git a/storage/innobase/ibuf/ibuf0ibuf.c b/storage/innobase/ibuf/ibuf0ibuf.c
index d22fc8b9962..eee5402daa7 100644
--- a/storage/innobase/ibuf/ibuf0ibuf.c
+++ b/storage/innobase/ibuf/ibuf0ibuf.c
@@ -2731,6 +2731,14 @@ ibuf_contract_for_n_pages(
ulint n_bytes;
ulint n_pag2;
+#if defined UNIV_DEBUG || defined UNIV_IBUF_DEBUG
+ if (ibuf_debug) {
+ return(0);
+ }
+#endif /* UNIV_DEBUG || UNIV_IBUF_DEBUG */
+
+
+
while (sum_pages < n_pages) {
n_bytes = ibuf_contract_ext(&n_pag2, sync);
diff --git a/storage/innobase/include/btr0cur.h b/storage/innobase/include/btr0cur.h
index 78637ea7295..8c750568c6e 100644
--- a/storage/innobase/include/btr0cur.h
+++ b/storage/innobase/include/btr0cur.h
@@ -825,6 +825,28 @@ extern ulint btr_cur_n_sea_old;
extern uint btr_cur_limit_optimistic_insert_debug;
#endif /* UNIV_DEBUG */
+/*******************************************************************//**
+Print information about old page and a new page on a B-tree when
+we note that page types do not match.*/
+void
+btr_pages_info(
+ page_t* old_page, /*!< in: Page where we were */
+ page_t* new_page, /*!< in: Page where we travelsed */
+ ulint space_id, /*!< in: space id */
+ ulint zip_size, /*!< in: zip size */
+ ulint page_no, /*!< in: Page id where travelsed */
+ ulint latch_mode, /*!< in: Used latch mode */
+ dict_index_t* index, /*!< in: Used index */
+ ulint old_next_page_no, /*!< in: Next page number from old page */
+ ulint old_prev_page_no, /*!< in: Prev page number from old page */
+ ulint new_space_id, /*!< in: Space id of new page */
+ ulint new_zip_size, /*!< in: Zip size of new page */
+ ulint new_next_page_no, /*!< in: Next page number from new page */
+ ulint new_prev_page_no, /*!< in: Prev page number from new page */
+ mtr_t* mtr, /*!< in: mini transaction */
+ const char* file, /*!< in: file name where called */
+ ulint line); /*!< in: line number where called */
+
#ifndef UNIV_NONINL
#include "btr0cur.ic"
#endif
diff --git a/storage/innobase/include/dict0crea.h b/storage/innobase/include/dict0crea.h
index 9faf580b0cc..a58bcb181aa 100644
--- a/storage/innobase/include/dict0crea.h
+++ b/storage/innobase/include/dict0crea.h
@@ -106,6 +106,17 @@ UNIV_INTERN
ulint
dict_create_or_check_foreign_constraint_tables(void);
/*================================================*/
+
+/********************************************************************//**
+Construct foreign key constraint defintion from data dictionary information.
+*/
+UNIV_INTERN
+char*
+dict_foreign_def_get(
+/*=================*/
+ dict_foreign_t* foreign,/*!< in: foreign */
+ trx_t* trx); /*!< in: trx */
+
/********************************************************************//**
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
diff --git a/storage/innobase/include/dict0dict.h b/storage/innobase/include/dict0dict.h
index 003639d55b5..bb1119b3c19 100644
--- a/storage/innobase/include/dict0dict.h
+++ b/storage/innobase/include/dict0dict.h
@@ -1123,7 +1123,13 @@ dict_index_calc_min_rec_len(
/*========================*/
const dict_index_t* index); /*!< in: index */
-/** Calculate new statistics if 1 / 16 of table has been modified
+/**
+
+If user has provided upper bound for how many rows needs to be updated
+before we calculate new statistics we use minimum of provided value
+and 1/16 of table every 16th round. If no upper bound is provided
+(srv_stats_modified_counter = 0, default) then calculate new statistics
+if 1 / 16 of table has been modified
since the last time a statistics batch was run.
We calculate statistics at most every 16th round, since we may have
a counter table which is very small and updated very often.
@@ -1132,7 +1138,9 @@ a counter table which is very small and updated very often.
recalculated
*/
#define DICT_TABLE_CHANGED_TOO_MUCH(t) \
- ((ib_int64_t) (t)->stat_modified_counter > 16 + (t)->stat_n_rows / 16)
+ ((ib_int64_t) (t)->stat_modified_counter > (srv_stats_modified_counter ? \
+ (ib_int64_t) ut_min(srv_stats_modified_counter, (16 + (t)->stat_n_rows / 16)) : \
+ 16 + (t)->stat_n_rows / 16))
/*********************************************************************//**
Calculates new estimates for table and index statistics. The statistics
diff --git a/storage/innobase/include/fil0fil.h b/storage/innobase/include/fil0fil.h
index 485c8357e87..505b619d022 100644
--- a/storage/innobase/include/fil0fil.h
+++ b/storage/innobase/include/fil0fil.h
@@ -752,6 +752,14 @@ fil_mtr_rename_log(
const char* tmp_name); /*!< in: temp table name used while
swapping */
+
typedef struct fil_space_struct fil_space_t;
+/*******************************************************************//**
+Returns the table space name for a given id, NULL if not found. */
+const char*
+fil_space_get_name(
+/*================*/
+ ulint id); /*!< in: space id */
+
#endif
diff --git a/storage/innobase/include/ha0ha.h b/storage/innobase/include/ha0ha.h
index afa9152a317..2ca75cd62a9 100644
--- a/storage/innobase/include/ha0ha.h
+++ b/storage/innobase/include/ha0ha.h
@@ -38,7 +38,7 @@ Looks for an element in a hash table.
@return pointer to the data of the first hash table node in chain
having the fold number, NULL if not found */
UNIV_INLINE
-const rec_t*
+rec_t*
ha_search_and_get_data(
/*===================*/
hash_table_t* table, /*!< in: hash table */
@@ -52,11 +52,11 @@ ha_search_and_update_if_found_func(
/*===============================*/
hash_table_t* table, /*!< in/out: hash table */
ulint fold, /*!< in: folded value of the searched data */
- const rec_t* data, /*!< in: pointer to the data */
+ rec_t* data, /*!< in: pointer to the data */
#if defined UNIV_AHI_DEBUG || defined UNIV_DEBUG
buf_block_t* new_block,/*!< in: block containing new_data */
#endif /* UNIV_AHI_DEBUG || UNIV_DEBUG */
- const rec_t* new_data);/*!< in: new pointer to the data */
+ rec_t* new_data);/*!< in: new pointer to the data */
#if defined UNIV_AHI_DEBUG || defined UNIV_DEBUG
/** Looks for an element when we know the pointer to the data and
@@ -131,7 +131,7 @@ ha_insert_for_fold_func(
#if defined UNIV_AHI_DEBUG || defined UNIV_DEBUG
buf_block_t* block, /*!< in: buffer block containing the data */
#endif /* UNIV_AHI_DEBUG || UNIV_DEBUG */
- const rec_t* data); /*!< in: data, must not be NULL */
+ rec_t* data); /*!< in: data, must not be NULL */
#if defined UNIV_AHI_DEBUG || defined UNIV_DEBUG
/**
@@ -210,7 +210,7 @@ struct ha_node_struct {
#if defined UNIV_AHI_DEBUG || defined UNIV_DEBUG
buf_block_t* block; /*!< buffer block containing the data, or NULL */
#endif /* UNIV_AHI_DEBUG || UNIV_DEBUG */
- const rec_t* data; /*!< pointer to the data */
+ rec_t* data; /*!< pointer to the data */
ulint fold; /*!< fold value for the data */
};
diff --git a/storage/innobase/include/ha0ha.ic b/storage/innobase/include/ha0ha.ic
index 19e026e863a..dde59f85dca 100644
--- a/storage/innobase/include/ha0ha.ic
+++ b/storage/innobase/include/ha0ha.ic
@@ -58,7 +58,7 @@ ha_node_set_data_func(
#if defined UNIV_AHI_DEBUG || defined UNIV_DEBUG
buf_block_t* block, /*!< in: buffer block containing the data */
#endif /* UNIV_AHI_DEBUG || UNIV_DEBUG */
- const rec_t* data) /*!< in: pointer to the data */
+ rec_t* data) /*!< in: pointer to the data */
{
#if defined UNIV_AHI_DEBUG || defined UNIV_DEBUG
node->block = block;
@@ -111,7 +111,7 @@ Looks for an element in a hash table.
@return pointer to the data of the first hash table node in chain
having the fold number, NULL if not found */
UNIV_INLINE
-const rec_t*
+rec_t*
ha_search_and_get_data(
/*===================*/
hash_table_t* table, /*!< in: hash table */
diff --git a/storage/innobase/include/ha_prototypes.h b/storage/innobase/include/ha_prototypes.h
index 3859b45e8d1..83fa1d53f1e 100644
--- a/storage/innobase/include/ha_prototypes.h
+++ b/storage/innobase/include/ha_prototypes.h
@@ -326,5 +326,28 @@ innobase_convert_to_filename_charset(
const char* from, /* in: identifier to convert */
ulint len); /* in: length of 'to', in bytes */
+/********************************************************************//**
+Helper function to push warnings from InnoDB internals to SQL-layer. */
+UNIV_INTERN
+void
+ib_push_warning(
+ trx_t* trx, /*!< in: trx */
+ ulint error, /*!< in: error code to push as warning */
+ const char *format,/*!< in: warning message */
+ ...);
+
+/*****************************************************************//**
+Normalizes a table name string. A normalized name consists of the
+database name catenated to '/' and table name. An example:
+test/mytable. On Windows normalization puts both the database name and the
+table name always to lower case if "set_lower_case" is set to TRUE. */
+void
+normalize_table_name_low(
+/*=====================*/
+ char* norm_name, /*!< out: normalized name as a
+ null-terminated string */
+ const char* name, /*!< in: table name string */
+ ibool set_lower_case); /*!< in: TRUE if we want to set
+ name to lower case */
#endif
diff --git a/storage/innobase/include/log0log.h b/storage/innobase/include/log0log.h
index b0e5e9bda3b..fab91b5c5c2 100644
--- a/storage/innobase/include/log0log.h
+++ b/storage/innobase/include/log0log.h
@@ -154,6 +154,13 @@ UNIV_INLINE
ib_uint64_t
log_get_lsn(void);
/*=============*/
+/************************************************************//**
+Gets the current lsn.
+@return current lsn */
+UNIV_INLINE
+lsn_t
+log_get_lsn_nowait(void);
+/*=============*/
/****************************************************************
Gets the log group capacity. It is OK to read the value without
holding log_sys->mutex because it is constant.
diff --git a/storage/innobase/include/log0log.ic b/storage/innobase/include/log0log.ic
index 8eca3b911d0..8c8dc096a10 100644
--- a/storage/innobase/include/log0log.ic
+++ b/storage/innobase/include/log0log.ic
@@ -411,6 +411,26 @@ log_get_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=0;
+
+ if (!mutex_enter_nowait(&(log_sys->mutex))) {
+
+ 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.
diff --git a/storage/innobase/include/os0sync.h b/storage/innobase/include/os0sync.h
index 07628409192..22b0fa420eb 100644
--- a/storage/innobase/include/os0sync.h
+++ b/storage/innobase/include/os0sync.h
@@ -246,12 +246,29 @@ os_fast_mutex_trylock(
/*==================*/
os_fast_mutex_t* fast_mutex); /*!< in: mutex to acquire */
/**********************************************************//**
+Acquires ownership of a fast mutex. Implies a full memory barrier even on
+platforms such as PowerPC where this is not normally required.
+@return 0 if success, != 0 if was reserved by another thread */
+UNIV_INLINE
+ulint
+os_fast_mutex_trylock_full_barrier(
+/*==================*/
+ os_fast_mutex_t* fast_mutex); /*!< in: mutex to acquire */
+/**********************************************************//**
Releases ownership of a fast mutex. */
UNIV_INTERN
void
os_fast_mutex_unlock(
/*=================*/
os_fast_mutex_t* fast_mutex); /*!< in: mutex to release */
+/**********************************************************//**
+Releases ownership of a fast mutex. Implies a full memory barrier even on
+platforms such as PowerPC where this is not normally required. */
+UNIV_INTERN
+void
+os_fast_mutex_unlock_full_barrier(
+/*=================*/
+ os_fast_mutex_t* fast_mutex); /*!< in: mutex to release */
/*********************************************************//**
Initializes an operating system fast mutex semaphore. */
UNIV_INTERN
@@ -508,6 +525,50 @@ os_atomic_clear(volatile lock_word_t* ptr)
"Mutexes and rw_locks use InnoDB's own implementation"
#endif
+/** barrier definitions for memory ordering */
+#ifdef 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)
+# define os_mb __atomic_thread_fence(__ATOMIC_SEQ_CST)
+
+# 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_mb __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_mb __machine_rw_barrier()
+# define IB_MEMORY_BARRIER_STARTUP_MSG \
+ "Soralis 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_mb _mm_mfence()
+# define IB_MEMORY_BARRIER_STARTUP_MSG \
+ "_mm_lfence() and _mm_sfence() are used for memory barrier"
+
+#else
+# define os_rmb do { } while(0)
+# define os_wmb do { } while(0)
+# define os_mb 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/innobase/include/os0sync.ic b/storage/innobase/include/os0sync.ic
index 409ff19170a..836e51f3399 100644
--- a/storage/innobase/include/os0sync.ic
+++ b/storage/innobase/include/os0sync.ic
@@ -54,3 +54,35 @@ os_fast_mutex_trylock(
return((ulint) pthread_mutex_trylock(fast_mutex));
#endif
}
+
+/**********************************************************//**
+Acquires ownership of a fast mutex. Implies a full memory barrier even on
+platforms such as PowerPC where this is not normally required.
+@return 0 if success, != 0 if was reserved by another thread */
+UNIV_INLINE
+ulint
+os_fast_mutex_trylock_full_barrier(
+/*==================*/
+ os_fast_mutex_t* fast_mutex) /*!< in: mutex to acquire */
+{
+#ifdef __WIN__
+ if (TryEnterCriticalSection(fast_mutex)) {
+
+ return(0);
+ } else {
+
+ return(1);
+ }
+#else
+ /* NOTE that the MySQL my_pthread.h redefines pthread_mutex_trylock
+ so that it returns 0 on success. In the operating system
+ libraries, HP-UX-10.20 follows the old Posix 1003.4a Draft 4 and
+ returns 1 on success (but MySQL remaps that to 0), while Linux,
+ FreeBSD, Solaris, AIX, Tru64 Unix, HP-UX-11.0 return 0 on success. */
+
+#ifdef __powerpc__
+ os_mb;
+#endif
+ return((ulint) pthread_mutex_trylock(fast_mutex));
+#endif
+}
diff --git a/storage/innobase/include/srv0srv.h b/storage/innobase/include/srv0srv.h
index 0050174c73e..2b1a640ae8b 100644
--- a/storage/innobase/include/srv0srv.h
+++ b/storage/innobase/include/srv0srv.h
@@ -3,6 +3,7 @@
Copyright (c) 1995, 2011, Innobase Oy. All Rights Reserved.
Copyright (c) 2008, 2009, Google Inc.
Copyright (c) 2009, Percona Inc.
+Copyright (c) 2013, 2014, SkySQL Ab. All Rights Reserved.
Portions of this file contain modifications contributed and copyrighted by
Google, Inc. Those modifications are gratefully acknowledged and are described
@@ -210,8 +211,15 @@ extern ulint srv_fast_shutdown; /* If this is 1, do not do a
extern ibool srv_innodb_status;
extern unsigned long long srv_stats_sample_pages;
+extern unsigned long long srv_stats_modified_counter;
+extern my_bool srv_stats_sample_traditional;
extern ibool srv_use_doublewrite_buf;
+extern ibool srv_use_atomic_writes;
+#ifdef HAVE_POSIX_FALLOCATE
+extern ibool srv_use_posix_fallocate;
+#endif
+
extern ibool srv_use_checksums;
extern ulong srv_max_buf_pool_modified_pct;
@@ -340,6 +348,9 @@ extern ulint srv_buf_pool_reads;
/** print all user-level transactions deadlocks to mysqld stderr */
extern my_bool srv_print_all_deadlocks;
+/** Simulate compression failures. */
+extern uint srv_simulate_comp_failures;
+
/** Status variables to be passed to MySQL */
typedef struct export_var_struct export_struc;
diff --git a/storage/innobase/include/sync0arr.h b/storage/innobase/include/sync0arr.h
index 4bce9435577..a31c61a3806 100644
--- a/storage/innobase/include/sync0arr.h
+++ b/storage/innobase/include/sync0arr.h
@@ -138,6 +138,12 @@ sync_array_print_info(
sync_array_t* arr); /*!< in: wait array */
+/**********************************************************************//**
+Prints info of the wait array without using any mutexes/semaphores. */
+UNIV_INTERN
+void
+sync_array_print_innodb(void);
+
#ifndef UNIV_NONINL
#include "sync0arr.ic"
#endif
diff --git a/storage/innobase/include/sync0rw.h b/storage/innobase/include/sync0rw.h
index e755436bbe0..f65d62a39fa 100644
--- a/storage/innobase/include/sync0rw.h
+++ b/storage/innobase/include/sync0rw.h
@@ -70,14 +70,8 @@ extern mutex_t rw_lock_list_mutex;
#ifdef UNIV_SYNC_DEBUG
/* The global mutex which protects debug info lists of all rw-locks.
To modify the debug info list of an rw-lock, this mutex has to be
-
acquired in addition to the mutex protecting the lock. */
-extern mutex_t rw_lock_debug_mutex;
-extern os_event_t rw_lock_debug_event; /*!< If deadlock detection does
- not get immediately the mutex it
- may wait for this event */
-extern ibool rw_lock_debug_waiters; /*!< This is set to TRUE, if
- there may be waiters for the event */
+extern os_fast_mutex_t rw_lock_debug_mutex;
#endif /* UNIV_SYNC_DEBUG */
/** number of spin waits on rw-latches,
diff --git a/storage/innobase/include/sync0rw.ic b/storage/innobase/include/sync0rw.ic
index 28d0611a673..a7d81e4b031 100644
--- a/storage/innobase/include/sync0rw.ic
+++ b/storage/innobase/include/sync0rw.ic
@@ -200,14 +200,14 @@ rw_lock_lock_word_decr(
ulint amount) /*!< in: amount to decrement */
{
#ifdef INNODB_RW_LOCKS_USE_ATOMICS
- lint local_lock_word = lock->lock_word;
- while (local_lock_word > 0) {
+ lint local_lock_word;
+ os_rmb;
+ while ((local_lock_word= lock->lock_word) > 0) {
if (os_compare_and_swap_lint(&lock->lock_word,
local_lock_word,
local_lock_word - amount)) {
return(TRUE);
}
- local_lock_word = lock->lock_word;
}
return(FALSE);
#else /* INNODB_RW_LOCKS_USE_ATOMICS */
@@ -438,6 +438,7 @@ rw_lock_x_lock_func_nowait(
os_thread_id_t curr_thread = os_thread_get_curr_id();
ibool success;
+ ibool local_recursive= lock->recursive;
#ifdef INNODB_RW_LOCKS_USE_ATOMICS
success = os_compare_and_swap_lint(&lock->lock_word, X_LOCK_DECR, 0);
@@ -452,10 +453,14 @@ rw_lock_x_lock_func_nowait(
mutex_exit(&(lock->mutex));
#endif
+ /* Note: recursive must be loaded before writer_thread see
+ comment for rw_lock_set_writer_id_and_recursion_flag().
+ To achieve this we load it before os_compare_and_swap_lint(),
+ which implies full memory barrier in current implementation. */
if (success) {
rw_lock_set_writer_id_and_recursion_flag(lock, TRUE);
- } else if (lock->recursive
+ } else if (local_recursive
&& os_thread_eq(lock->writer_thread, curr_thread)) {
/* Relock: this lock_word modification is safe since no other
threads can modify (lock, unlock, or reserve) lock_word while
diff --git a/storage/innobase/include/sync0sync.h b/storage/innobase/include/sync0sync.h
index b50735f4ad0..bc8d0d27be3 100644
--- a/storage/innobase/include/sync0sync.h
+++ b/storage/innobase/include/sync0sync.h
@@ -770,6 +770,11 @@ extern ut_list_base_node_t mutex_list;
/** Mutex protecting the mutex_list variable */
extern mutex_t mutex_list_mutex;
+/*******************************************************************//**
+Get sync array */
+UNIV_INTERN
+sync_array_t*
+sync_array_get(void);
#ifndef UNIV_NONINL
#include "sync0sync.ic"
diff --git a/storage/innobase/include/sync0sync.ic b/storage/innobase/include/sync0sync.ic
index bd2df4488b4..1120da8a3be 100644
--- a/storage/innobase/include/sync0sync.ic
+++ b/storage/innobase/include/sync0sync.ic
@@ -84,7 +84,7 @@ mutex_test_and_set(
#else
ibool ret;
- ret = os_fast_mutex_trylock(&(mutex->os_fast_mutex));
+ ret = os_fast_mutex_trylock_full_barrier(&(mutex->os_fast_mutex));
if (ret == 0) {
/* We check that os_fast_mutex_trylock does not leak
@@ -112,7 +112,7 @@ mutex_reset_lock_word(
#else
mutex->lock_word = 0;
- os_fast_mutex_unlock(&(mutex->os_fast_mutex));
+ os_fast_mutex_unlock_full_barrier(&(mutex->os_fast_mutex));
#endif
}
diff --git a/storage/innobase/include/trx0trx.h b/storage/innobase/include/trx0trx.h
index 17a39c2949f..4ade245f03e 100644
--- a/storage/innobase/include/trx0trx.h
+++ b/storage/innobase/include/trx0trx.h
@@ -490,7 +490,7 @@ struct trx_struct{
transaction has been registered with
the coordinator using the XA API, and
is set to 0 after commit or rollback. */
- unsigned owns_prepare_mutex:1;/* 1 if owns prepare mutex, if
+ unsigned active_commit_ordered:1;/* 1 if owns prepare mutex, if
this is set to 1 then registered should
also be set to 1. This is used in the
XA code */
diff --git a/storage/innobase/include/univ.i b/storage/innobase/include/univ.i
index 67b94bcaa3e..a9d75955550 100644
--- a/storage/innobase/include/univ.i
+++ b/storage/innobase/include/univ.i
@@ -162,7 +162,7 @@ command. Not tested on Windows. */
#define UNIV_COMPILE_TEST_FUNCS
*/
-#if defined HAVE_VALGRIND
+#if defined(HAVE_valgrind)&& defined(HAVE_VALGRIND_MEMCHECK_H)
# define UNIV_DEBUG_VALGRIND
#endif /* HAVE_VALGRIND */
#if 0
diff --git a/storage/innobase/include/ut0ut.h b/storage/innobase/include/ut0ut.h
index 98e057ff221..9c091bc1df7 100644
--- a/storage/innobase/include/ut0ut.h
+++ b/storage/innobase/include/ut0ut.h
@@ -63,16 +63,16 @@ typedef time_t ib_time_t;
# define UT_RELAX_CPU() __asm__ __volatile__ ("pause")
#elif defined(HAVE_FAKE_PAUSE_INSTRUCTION)
# define UT_RELAX_CPU() __asm__ __volatile__ ("rep; nop")
-#elif defined(HAVE_ATOMIC_BUILTINS)
-# define UT_RELAX_CPU() do { \
- volatile lint volatile_var; \
- os_compare_and_swap_lint(&volatile_var, 0, 1); \
- } while (0)
#elif defined(HAVE_WINDOWS_ATOMICS)
/* In the Win32 API, the x86 PAUSE instruction is executed by calling
the YieldProcessor macro defined in WinNT.h. It is a CPU architecture-
independent way by using YieldProcessor. */
# define UT_RELAX_CPU() YieldProcessor()
+#elif defined(HAVE_ATOMIC_BUILTINS)
+# define UT_RELAX_CPU() do { \
+ volatile lint volatile_var; \
+ os_compare_and_swap_lint(&volatile_var, 0, 1); \
+ } while (0)
#else
# define UT_RELAX_CPU() ((void)0) /* avoid warning for an empty statement */
#endif
diff --git a/storage/innobase/log/log0recv.c b/storage/innobase/log/log0recv.c
index ae3912da552..da3ea786af4 100644
--- a/storage/innobase/log/log0recv.c
+++ b/storage/innobase/log/log0recv.c
@@ -1767,7 +1767,7 @@ loop:
goto loop;
}
- ut_ad(!allow_ibuf == mutex_own(&log_sys->mutex));
+ ut_ad(allow_ibuf == FALSE ? mutex_own(&log_sys->mutex) : !mutex_own(&log_sys->mutex));
if (!allow_ibuf) {
recv_no_ibuf_operations = TRUE;
@@ -2911,7 +2911,7 @@ recv_recovery_from_checkpoint_start_func(
ib_uint64_t checkpoint_lsn;
ib_uint64_t checkpoint_no;
ib_uint64_t old_scanned_lsn;
- ib_uint64_t group_scanned_lsn;
+ ib_uint64_t group_scanned_lsn= 0;
ib_uint64_t contiguous_lsn;
#ifdef UNIV_LOG_ARCHIVE
ib_uint64_t archived_lsn;
diff --git a/storage/innobase/mysql-test/storage_engine/alter_tablespace.opt b/storage/innobase/mysql-test/storage_engine/alter_tablespace.opt
new file mode 100644
index 00000000000..cf4b117e1b1
--- /dev/null
+++ b/storage/innobase/mysql-test/storage_engine/alter_tablespace.opt
@@ -0,0 +1,2 @@
+--innodb-file-per-table=1
+
diff --git a/storage/innobase/mysql-test/storage_engine/autoinc_secondary.rdiff b/storage/innobase/mysql-test/storage_engine/autoinc_secondary.rdiff
new file mode 100644
index 00000000000..00cda7c4435
--- /dev/null
+++ b/storage/innobase/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/innobase/mysql-test/storage_engine/cache_index.rdiff b/storage/innobase/mysql-test/storage_engine/cache_index.rdiff
new file mode 100644
index 00000000000..e04df87aa34
--- /dev/null
+++ b/storage/innobase/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/innobase/mysql-test/storage_engine/checksum_table_live.rdiff b/storage/innobase/mysql-test/storage_engine/checksum_table_live.rdiff
new file mode 100644
index 00000000000..71c782848a6
--- /dev/null
+++ b/storage/innobase/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/innobase/mysql-test/storage_engine/define_engine.inc b/storage/innobase/mysql-test/storage_engine/define_engine.inc
new file mode 100644
index 00000000000..7d7b0c7407a
--- /dev/null
+++ b/storage/innobase/mysql-test/storage_engine/define_engine.inc
@@ -0,0 +1,45 @@
+###########################################
+#
+# 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
+
+--enable_query_log
+--enable_result_log
diff --git a/storage/innobase/mysql-test/storage_engine/disabled.def b/storage/innobase/mysql-test/storage_engine/disabled.def
new file mode 100644
index 00000000000..b3b2c46f3f1
--- /dev/null
+++ b/storage/innobase/mysql-test/storage_engine/disabled.def
@@ -0,0 +1,8 @@
+alter_table_online : MDEV-397 (Changing a column name via ALTER ONLINE does not work for InnoDB)
+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/innobase/mysql-test/storage_engine/fulltext_search.rdiff b/storage/innobase/mysql-test/storage_engine/fulltext_search.rdiff
new file mode 100644
index 00000000000..f668e44109c
--- /dev/null
+++ b/storage/innobase/mysql-test/storage_engine/fulltext_search.rdiff
@@ -0,0 +1,150 @@
+--- suite/storage_engine/fulltext_search.result 2012-07-12 20:03:26.664053893 +0400
++++ suite/storage_engine/fulltext_search.reject 2012-07-15 17:49:03.616199102 +0400
+@@ -4,129 +4,27 @@
+ v2 TEXT <CUSTOM_COL_OPTIONS>,
+ FULLTEXT v1 (v1)
+ ) ENGINE=<STORAGE_ENGINE> <CUSTOM_TABLE_OPTIONS>;
+-SHOW INDEXES 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 v1 1 v1 # # NULL NULL YES FULLTEXT
+-INSERT INTO t1 (v0,v1,v2) VALUES ('text1','Here is a list of recommended books on MariaDB and MySQL. We\'ve provided links to Amazon.com here for convenience, but they can be found at many other bookstores, both online and off.
+-If you want to have your favorite MySQL / MariaDB book listed here, please leave a comment.
+-For developers who want to code on MariaDB or MySQL
+-* Understanding MySQL Internals by Sasha Pachev, former MySQL developer at MySQL AB.
+-o This is the only book we know about that describes the internals of MariaDB / MySQL. A must have for anyone who wants to understand and develop on MariaDB!
+-o Not all topics are covered and some parts are slightly outdated, but still the best book on this topic.
+-* MySQL 5.1 Plugin Development by Sergei Golubchik and Andrew Hutchings
+-o A must read for anyone wanting to write a plugin for MariaDB, written by the Sergei who designed the plugin interface for MySQL and MariaDB!
+-For MariaDB / MySQL end users
+-* MariaDB Crash Course by Ben Forta
+-o First MariaDB book!
+-o For people who want to learn SQL and the basics of MariaDB.
+-o Now shipping. Purchase at Amazon.com or your favorite bookseller.
+-* SQL-99 Complete, Really by Peter Gulutzan & Trudy Pelzer.
+-o Everything you wanted to know about the SQL 99 standard. Excellent reference book!
+-o Free to read in the Knowledgebase!
+-* MySQL (4th Edition) by Paul DuBois
+-o The \'default\' book to read if you wont to learn to use MySQL / MariaDB.
+-* MySQL Cookbook by Paul DuBois
+-o A lot of examples of how to use MySQL. As with all of Paul\'s books, it\'s worth its weight in gold and even enjoyable reading for such a \'dry\' subject.
+-* High Performance MySQL, Second Edition, By Baron Schwartz, Peter Zaitsev, Vadim Tkachenko, Jeremy D. Zawodny, Arjen Lentz, Derek J. Balling, et al.
+-o \"High Performance MySQL is the definitive guide to building fast, reliable systems with MySQL. Written by noted experts with years of real-world experience building very large systems, this book covers every aspect of MySQL performance in detail, and focuses on robustness, security, and data integrity. Learn advanced techniques in depth so you can bring out MySQL\'s full power.\" (From the book description at O\'Reilly)
+-
+- * MySQL Admin Cookbook
+- o A quick step-by-step guide for MySQL users and database administrators to tackle real-world challenges with MySQL configuration and administration
+-
+- * MySQL 5.0 Certification Study Guide, By Paul DuBois, Stefan Hinz, Carsten Pedersen
+- o This is the official guide to cover the passing of the two MySQL Certification examinations. It is valid till version 5.0 of the server, so while it misses all the features available in MySQL 5.1 and greater (including MariaDB 5.1 and greater), it provides a good basic understanding of MySQL for the end-user. ',
+-'There are several reasons why contributing code is one of the easiest and most rewarding ways to contribute to MariaDB:
+-
+- 1. We are very responsive toward reviews of submitted code and as soon as the review is done, the submitted code is merged into an existing MariaDB tree and made available to everyone, not just select customers.
+- 2. Code reviews are performed by the MariaDB core development team and the quality, detail, and timeliness of our reviews are better than you will find elsewhere.
+- 3. With MariaDB everyone has access to the latest code.
+- 4. If a patch is very safe and/or very useful we are willing to push it into the stable code (as long as it can\'t break any existing applications). We are willing to do this to ensure the freedom to add small, needed fixes on a stable release so users don\'t have to wait a year for something to be added which is critical to their business.
+- 5. If you are an active contributor, you can become a member of maria-captains, even if you aren\'t working for Monty Program Ab. All captains have the same rights as any other captain to accept and reject patches. Our development model is truly open for everyone.
+-The Contributing Code page details many of the actual steps involved in working with the MariaDB source code. It\'s important that you use the same tools and submit patches in the same way as other developers to keep development running smoothly.'
+- ), ('text2','test1','test2');
+-SELECT v0 FROM t1 WHERE MATCH(v1) AGAINST ('contributing' IN NATURAL LANGUAGE MODE);
+-v0
+-INSERT INTO t1 (v0,v1,v2) VALUES ('text3','test','test');
+-SELECT v0, MATCH(v1) AGAINST('contributing' IN NATURAL LANGUAGE MODE) AS rating FROM t1 WHERE MATCH(v1) AGAINST ('contributing' IN NATURAL LANGUAGE MODE);
+-v0 rating
+-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
+-SELECT v0 FROM t1 WHERE MATCH(v1,v2) AGAINST ('-test1 +critical +Cook*' IN BOOLEAN MODE);
+-v0
+-text1
+-SELECT v0 FROM t1 WHERE MATCH(v1,v2) AGAINST ('-patch +critical +Cook*' IN BOOLEAN MODE);
+-v0
+-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
+-DROP TABLE t1;
++ERROR HY000: The used table type doesn't support FULLTEXT indexes
++# ERROR: Statement ended with errno 1214, errname ER_TABLE_CANT_HANDLE_FT (expected to succeed)
++# ------------ UNEXPECTED RESULT ------------
++# The statement|command finished with ER_TABLE_CANT_HANDLE_FT.
++# FULLTEXT indexes or VARCHAR|TEXT data types 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 (v0 VARCHAR(64) <CUSTOM_COL_OPTIONS>,
+ v1 VARCHAR(16384) <CUSTOM_COL_OPTIONS>,
+ v2 TEXT <CUSTOM_COL_OPTIONS>,
+ FULLTEXT v1 (v1),
+ FULLTEXT v1_v2 (v1,v2)
+ ) ENGINE=<STORAGE_ENGINE> <CUSTOM_TABLE_OPTIONS>;
+-SHOW INDEXES 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 v1 1 v1 # # NULL NULL YES FULLTEXT
+-t1 1 v1_v2 1 v1 # # NULL NULL YES FULLTEXT
+-t1 1 v1_v2 2 v2 # # NULL NULL YES FULLTEXT
+-INSERT INTO t1 (v0,v1,v2) VALUES ('text1','Here is a list of recommended books on MariaDB and MySQL. We\'ve provided links to Amazon.com here for convenience, but they can be found at many other bookstores, both online and off.
+-If you want to have your favorite MySQL / MariaDB book listed here, please leave a comment.
+-For developers who want to code on MariaDB or MySQL
+-* Understanding MySQL Internals by Sasha Pachev, former MySQL developer at MySQL AB.
+-o This is the only book we know about that describes the internals of MariaDB / MySQL. A must have for anyone who wants to understand and develop on MariaDB!
+-o Not all topics are covered and some parts are slightly outdated, but still the best book on this topic.
+-* MySQL 5.1 Plugin Development by Sergei Golubchik and Andrew Hutchings
+-o A must read for anyone wanting to write a plugin for MariaDB, written by the Sergei who designed the plugin interface for MySQL and MariaDB!
+-For MariaDB / MySQL end users
+-* MariaDB Crash Course by Ben Forta
+-o First MariaDB book!
+-o For people who want to learn SQL and the basics of MariaDB.
+-o Now shipping. Purchase at Amazon.com or your favorite bookseller.
+-* SQL-99 Complete, Really by Peter Gulutzan & Trudy Pelzer.
+-o Everything you wanted to know about the SQL 99 standard. Excellent reference book!
+-o Free to read in the Knowledgebase!
+-* MySQL (4th Edition) by Paul DuBois
+-o The \'default\' book to read if you wont to learn to use MySQL / MariaDB.
+-* MySQL Cookbook by Paul DuBois
+-o A lot of examples of how to use MySQL. As with all of Paul\'s books, it\'s worth its weight in gold and even enjoyable reading for such a \'dry\' subject.
+-* High Performance MySQL, Second Edition, By Baron Schwartz, Peter Zaitsev, Vadim Tkachenko, Jeremy D. Zawodny, Arjen Lentz, Derek J. Balling, et al.
+-o \"High Performance MySQL is the definitive guide to building fast, reliable systems with MySQL. Written by noted experts with years of real-world experience building very large systems, this book covers every aspect of MySQL performance in detail, and focuses on robustness, security, and data integrity. Learn advanced techniques in depth so you can bring out MySQL\'s full power.\" (From the book description at O\'Reilly)
+-
+- * MySQL Admin Cookbook
+- o A quick step-by-step guide for MySQL users and database administrators to tackle real-world challenges with MySQL configuration and administration
+-
+- * MySQL 5.0 Certification Study Guide, By Paul DuBois, Stefan Hinz, Carsten Pedersen
+- o This is the official guide to cover the passing of the two MySQL Certification examinations. It is valid till version 5.0 of the server, so while it misses all the features available in MySQL 5.1 and greater (including MariaDB 5.1 and greater), it provides a good basic understanding of MySQL for the end-user. ',
+-'There are several reasons why contributing code is one of the easiest and most rewarding ways to contribute to MariaDB:
+-
+- 1. We are very responsive toward reviews of submitted code and as soon as the review is done, the submitted code is merged into an existing MariaDB tree and made available to everyone, not just select customers.
+- 2. Code reviews are performed by the MariaDB core development team and the quality, detail, and timeliness of our reviews are better than you will find elsewhere.
+- 3. With MariaDB everyone has access to the latest code.
+- 4. If a patch is very safe and/or very useful we are willing to push it into the stable code (as long as it can\'t break any existing applications). We are willing to do this to ensure the freedom to add small, needed fixes on a stable release so users don\'t have to wait a year for something to be added which is critical to their business.
+- 5. If you are an active contributor, you can become a member of maria-captains, even if you aren\'t working for Monty Program Ab. All captains have the same rights as any other captain to accept and reject patches. Our development model is truly open for everyone.
+-The Contributing Code page details many of the actual steps involved in working with the MariaDB source code. It\'s important that you use the same tools and submit patches in the same way as other developers to keep development running smoothly.'
+- ), ('text2','test1','test2');
+-SELECT v0 FROM t1 WHERE MATCH(v1,v2) AGAINST ('contributing' IN NATURAL LANGUAGE MODE);
+-v0
+-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
+-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
+-SELECT v0 FROM t1 WHERE MATCH(v1,v2) AGAINST ('-test1 +critical +Cook*' IN BOOLEAN MODE);
+-v0
+-text1
+-SELECT v0 FROM t1 WHERE MATCH(v1,v2) AGAINST ('-patch +critical +Cook*' IN BOOLEAN MODE);
+-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
+-DROP TABLE t1;
++ERROR HY000: The used table type doesn't support FULLTEXT indexes
++# ERROR: Statement ended with errno 1214, errname ER_TABLE_CANT_HANDLE_FT (expected to succeed)
++# ------------ UNEXPECTED RESULT ------------
++# The statement|command finished with ER_TABLE_CANT_HANDLE_FT.
++# FULLTEXT indexes or multiple keys or VARCHAR|TEXT data types 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).
++# -------------------------------------------
diff --git a/storage/innobase/mysql-test/storage_engine/index_enable_disable.rdiff b/storage/innobase/mysql-test/storage_engine/index_enable_disable.rdiff
new file mode 100644
index 00000000000..23aa66d2568
--- /dev/null
+++ b/storage/innobase/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 Table storage engine for '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 Table storage engine for '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 Table storage engine for '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/innobase/mysql-test/storage_engine/index_type_hash.rdiff b/storage/innobase/mysql-test/storage_engine/index_type_hash.rdiff
new file mode 100644
index 00000000000..02f9d93588f
--- /dev/null
+++ b/storage/innobase/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/innobase/mysql-test/storage_engine/insert_delayed.rdiff b/storage/innobase/mysql-test/storage_engine/insert_delayed.rdiff
new file mode 100644
index 00000000000..9e6cddf03f0
--- /dev/null
+++ b/storage/innobase/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/innobase/mysql-test/storage_engine/lock_concurrent.rdiff b/storage/innobase/mysql-test/storage_engine/lock_concurrent.rdiff
new file mode 100644
index 00000000000..fe4a0087fa9
--- /dev/null
+++ b/storage/innobase/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/innobase/mysql-test/storage_engine/optimize_table.rdiff b/storage/innobase/mysql-test/storage_engine/optimize_table.rdiff
new file mode 100644
index 00000000000..54d1f600516
--- /dev/null
+++ b/storage/innobase/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/innobase/mysql-test/storage_engine/parts/checksum_table.rdiff b/storage/innobase/mysql-test/storage_engine/parts/checksum_table.rdiff
new file mode 100644
index 00000000000..3d4d2a683d9
--- /dev/null
+++ b/storage/innobase/mysql-test/storage_engine/parts/checksum_table.rdiff
@@ -0,0 +1,22 @@
+--- suite/storage_engine/parts/checksum_table.result 2012-07-12 21:41:00.754458011 +0400
++++ suite/storage_engine/parts/checksum_table.reject 2012-07-15 20:04:35.881962676 +0400
+@@ -24,15 +24,15 @@
+ CREATE TABLE t2 (a <INT_COLUMN>, b <CHAR_COLUMN>) ENGINE=<STORAGE_ENGINE> <CUSTOM_TABLE_OPTIONS> CHECKSUM=1 PARTITION BY HASH(a) PARTITIONS 2;
+ CHECKSUM TABLE t1;
+ Table Checksum
+-test.t1 0
++test.t1 4272806499
+ CHECKSUM TABLE t2, t1;
+ Table Checksum
+ test.t2 0
+-test.t1 0
++test.t1 4272806499
+ CHECKSUM TABLE t1, t2 QUICK;
+ Table Checksum
+-test.t1 0
+-test.t2 0
++test.t1 NULL
++test.t2 NULL
+ CHECKSUM TABLE t1, t2 EXTENDED;
+ Table Checksum
+ test.t1 4272806499
diff --git a/storage/innobase/mysql-test/storage_engine/parts/create_table.rdiff b/storage/innobase/mysql-test/storage_engine/parts/create_table.rdiff
new file mode 100644
index 00000000000..0df91c6fc6e
--- /dev/null
+++ b/storage/innobase/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/innobase/mysql-test/storage_engine/parts/optimize_table.rdiff b/storage/innobase/mysql-test/storage_engine/parts/optimize_table.rdiff
new file mode 100644
index 00000000000..a35ba5167d9
--- /dev/null
+++ b/storage/innobase/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/innobase/mysql-test/storage_engine/parts/repair_table.rdiff b/storage/innobase/mysql-test/storage_engine/parts/repair_table.rdiff
new file mode 100644
index 00000000000..35b150e82d1
--- /dev/null
+++ b/storage/innobase/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/innobase/mysql-test/storage_engine/parts/suite.opt b/storage/innobase/mysql-test/storage_engine/parts/suite.opt
new file mode 100644
index 00000000000..28ae8786144
--- /dev/null
+++ b/storage/innobase/mysql-test/storage_engine/parts/suite.opt
@@ -0,0 +1,4 @@
+--ignore-builtin-innodb
+--plugin-load=ha_innodb
+--innodb
+
diff --git a/storage/innobase/mysql-test/storage_engine/repair_table.rdiff b/storage/innobase/mysql-test/storage_engine/repair_table.rdiff
new file mode 100644
index 00000000000..ae5b863eae1
--- /dev/null
+++ b/storage/innobase/mysql-test/storage_engine/repair_table.rdiff
@@ -0,0 +1,129 @@
+--- suite/storage_engine/repair_table.result 2012-07-15 01:26:44.347708000 +0400
++++ suite/storage_engine/repair_table.reject 2012-07-15 17:50:37.927013454 +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,14 @@
+ 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
+-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
+-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
+-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
+-# 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/innobase/mysql-test/storage_engine/suite.opt b/storage/innobase/mysql-test/storage_engine/suite.opt
new file mode 100644
index 00000000000..28ae8786144
--- /dev/null
+++ b/storage/innobase/mysql-test/storage_engine/suite.opt
@@ -0,0 +1,4 @@
+--ignore-builtin-innodb
+--plugin-load=ha_innodb
+--innodb
+
diff --git a/storage/innobase/mysql-test/storage_engine/tbl_opt_data_index_dir.rdiff b/storage/innobase/mysql-test/storage_engine/tbl_opt_data_index_dir.rdiff
new file mode 100644
index 00000000000..47f624c73d9
--- /dev/null
+++ b/storage/innobase/mysql-test/storage_engine/tbl_opt_data_index_dir.rdiff
@@ -0,0 +1,18 @@
+--- suite/storage_engine/tbl_opt_data_index_dir.result 2012-06-24 23:55:19.539380000 +0400
++++ suite/storage_engine/tbl_opt_data_index_dir.reject 2012-07-15 17:51:04.070684784 +0400
+@@ -4,7 +4,7 @@
+ 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
+ Warnings:
+ Warning 1618 <INDEX DIRECTORY> option ignored
+ SHOW CREATE TABLE t1;
+@@ -12,5 +12,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
+ DROP TABLE t1;
diff --git a/storage/innobase/mysql-test/storage_engine/tbl_opt_insert_method.rdiff b/storage/innobase/mysql-test/storage_engine/tbl_opt_insert_method.rdiff
new file mode 100644
index 00000000000..468b82926f0
--- /dev/null
+++ b/storage/innobase/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/innobase/mysql-test/storage_engine/tbl_opt_key_block_size.opt b/storage/innobase/mysql-test/storage_engine/tbl_opt_key_block_size.opt
new file mode 100644
index 00000000000..7cd737b2b87
--- /dev/null
+++ b/storage/innobase/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/innobase/mysql-test/storage_engine/tbl_opt_row_format.opt b/storage/innobase/mysql-test/storage_engine/tbl_opt_row_format.opt
new file mode 100644
index 00000000000..7cd737b2b87
--- /dev/null
+++ b/storage/innobase/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/innobase/mysql-test/storage_engine/tbl_opt_row_format.rdiff b/storage/innobase/mysql-test/storage_engine/tbl_opt_row_format.rdiff
new file mode 100644
index 00000000000..4c0e0c375f5
--- /dev/null
+++ b/storage/innobase/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 InnoDB: assuming ROW_FORMAT=COMPACT.
+ SHOW CREATE TABLE t1;
+ Table Create Table
+ t1 CREATE TABLE `t1` (
diff --git a/storage/innobase/mysql-test/storage_engine/tbl_opt_union.rdiff b/storage/innobase/mysql-test/storage_engine/tbl_opt_union.rdiff
new file mode 100644
index 00000000000..cbdf5818022
--- /dev/null
+++ b/storage/innobase/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/innobase/mysql-test/storage_engine/trx/cons_snapshot_serializable.rdiff b/storage/innobase/mysql-test/storage_engine/trx/cons_snapshot_serializable.rdiff
new file mode 100644
index 00000000000..e6149be58dc
--- /dev/null
+++ b/storage/innobase/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/innobase/mysql-test/storage_engine/trx/level_read_committed.rdiff b/storage/innobase/mysql-test/storage_engine/trx/level_read_committed.rdiff
new file mode 100644
index 00000000000..cb64d32138b
--- /dev/null
+++ b/storage/innobase/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/innobase/mysql-test/storage_engine/trx/level_read_uncommitted.rdiff b/storage/innobase/mysql-test/storage_engine/trx/level_read_uncommitted.rdiff
new file mode 100644
index 00000000000..6a79abe3ca5
--- /dev/null
+++ b/storage/innobase/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/innobase/mysql-test/storage_engine/trx/suite.opt b/storage/innobase/mysql-test/storage_engine/trx/suite.opt
new file mode 100644
index 00000000000..2bf66f067f6
--- /dev/null
+++ b/storage/innobase/mysql-test/storage_engine/trx/suite.opt
@@ -0,0 +1,5 @@
+--ignore-builtin-innodb
+--plugin-load=ha_innodb
+--innodb
+--innodb-lock-wait-timeout=1
+
diff --git a/storage/innobase/mysql-test/storage_engine/type_char_indexes.rdiff b/storage/innobase/mysql-test/storage_engine/type_char_indexes.rdiff
new file mode 100644
index 00000000000..53241fe331e
--- /dev/null
+++ b/storage/innobase/mysql-test/storage_engine/type_char_indexes.rdiff
@@ -0,0 +1,20 @@
+--- 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
+@@ -98,7 +98,7 @@
+ SET SESSION optimizer_switch = 'engine_condition_pushdown=on';
+ EXPLAIN SELECT c,c20,v16,v128 FROM t1 WHERE c > 'a';
+ id select_type table type possible_keys key key_len ref rows Extra
+-# # # range c_v c_v # # # Using index condition
++# # # range c_v c_v # # # Using where
+ SELECT c,c20,v16,v128 FROM t1 WHERE c > 'a';
+ c c20 v16 v128
+ b char3 varchar1a varchar1b
+@@ -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/innobase/mysql-test/storage_engine/type_float_indexes.rdiff b/storage/innobase/mysql-test/storage_engine/type_float_indexes.rdiff
new file mode 100644
index 00000000000..6ebfd61d876
--- /dev/null
+++ b/storage/innobase/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/innobase/mysql-test/storage_engine/type_spatial_indexes.rdiff b/storage/innobase/mysql-test/storage_engine/type_spatial_indexes.rdiff
new file mode 100644
index 00000000000..04572ee03be
--- /dev/null
+++ b/storage/innobase/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 used table type 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/innobase/mysql-test/storage_engine/vcol.rdiff b/storage/innobase/mysql-test/storage_engine/vcol.rdiff
new file mode 100644
index 00000000000..23b26a52228
--- /dev/null
+++ b/storage/innobase/mysql-test/storage_engine/vcol.rdiff
@@ -0,0 +1,82 @@
+--- suite/storage_engine/vcol.result 2012-07-12 20:24:16.628339715 +0400
++++ suite/storage_engine/vcol.reject 2012-07-15 17:53:17.457007891 +0400
+@@ -1,69 +1,12 @@
+ DROP TABLE IF EXISTS t1;
+ CREATE TABLE t1 (a <INT_COLUMN>, b <INT_COLUMN> GENERATED ALWAYS AS (a+1)) ENGINE=<STORAGE_ENGINE> <CUSTOM_TABLE_OPTIONS>;
+-SHOW COLUMNS IN t1;
+-Field Type Null Key Default Extra
+-a int(11) # #
+-b int(11) # # VIRTUAL
+-INSERT INTO t1 (a) VALUES (1),(2);
+-INSERT INTO t1 (a,b) VALUES (3,3),(4,4);
+-Warnings:
+-Warning 1906 The value specified for computed column 'b' in table 't1' ignored
+-Warning 1906 The value specified for computed column 'b' in table 't1' ignored
+-SELECT a,b FROM t1;
+-a b
+-1 2
+-2 3
+-3 4
+-4 5
+-DROP TABLE t1;
+-CREATE TABLE t1 (a <INT_COLUMN>, b <INT_COLUMN> GENERATED ALWAYS AS (a+1) PERSISTENT) ENGINE=<STORAGE_ENGINE> <CUSTOM_TABLE_OPTIONS>;
+-SHOW COLUMNS IN t1;
+-Field Type Null Key Default Extra
+-a int(11) # #
+-b int(11) # # PERSISTENT
+-INSERT INTO t1 (a) VALUES (1),(2);
+-INSERT INTO t1 (a,b) VALUES (3,3),(4,4);
+-Warnings:
+-Warning 1906 The value specified for computed column 'b' in table 't1' ignored
+-Warning 1906 The value specified for computed column 'b' in table 't1' ignored
+-SELECT a,b FROM t1;
+-a b
+-1 2
+-2 3
+-3 4
+-4 5
+-DROP TABLE t1;
+-CREATE TABLE t1 (a <INT_COLUMN>, b <INT_COLUMN> GENERATED ALWAYS AS (a+1) VIRTUAL) ENGINE=<STORAGE_ENGINE> <CUSTOM_TABLE_OPTIONS>;
+-SHOW COLUMNS IN t1;
+-Field Type Null Key Default Extra
+-a int(11) # #
+-b int(11) # # VIRTUAL
+-INSERT INTO t1 (a) VALUES (1),(2);
+-INSERT INTO t1 (a,b) VALUES (3,3),(4,4);
+-Warnings:
+-Warning 1906 The value specified for computed column 'b' in table 't1' ignored
+-Warning 1906 The value specified for computed column 'b' in table 't1' ignored
+-SELECT a,b FROM t1;
+-a b
+-1 2
+-2 3
+-3 4
+-4 5
+-DROP TABLE t1;
+-CREATE TABLE t1 (a <INT_COLUMN>, b <INT_COLUMN> AS (a+1) PERSISTENT) ENGINE=<STORAGE_ENGINE> <CUSTOM_TABLE_OPTIONS>;
+-SHOW COLUMNS IN t1;
+-Field Type Null Key Default Extra
+-a int(11) # #
+-b int(11) # # PERSISTENT
+-INSERT INTO t1 (a) VALUES (1),(2);
+-INSERT INTO t1 (a,b) VALUES (3,3),(4,4);
+-Warnings:
+-Warning 1906 The value specified for computed column 'b' in table 't1' ignored
+-Warning 1906 The value specified for computed column 'b' in table 't1' ignored
+-SELECT a,b FROM t1;
+-a b
+-1 2
+-2 3
+-3 4
+-4 5
+-DROP TABLE t1;
++ERROR HY000: InnoDB storage engine does not support computed columns
++# ERROR: Statement ended with errno 1910, errname ER_UNSUPPORTED_ENGINE_FOR_VIRTUAL_COLUMNS (expected to succeed)
++# ------------ UNEXPECTED RESULT ------------
++# [ CREATE TABLE t1 (a INT(11) /*!*/ /*Custom column options*/, b INT(11) /*!*/ /*Custom column options*/ GENERATED ALWAYS AS (a+1)) ENGINE=InnoDB /*!*/ /*Custom table options*/ ]
++# The statement|command finished with ER_UNSUPPORTED_ENGINE_FOR_VIRTUAL_COLUMNS.
++# Virtual columns 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).
++# -------------------------------------------
diff --git a/storage/innobase/os/os0file.c b/storage/innobase/os/os0file.c
index e09c6236522..d792e7a61d8 100644
--- a/storage/innobase/os/os0file.c
+++ b/storage/innobase/os/os0file.c
@@ -1372,6 +1372,42 @@ os_file_set_nocache(
#endif
}
+
+#ifdef __linux__
+#include <sys/ioctl.h>
+#ifndef DFS_IOCTL_ATOMIC_WRITE_SET
+#define DFS_IOCTL_ATOMIC_WRITE_SET _IOW(0x95, 2, uint)
+#endif
+static int os_file_set_atomic_writes(os_file_t file, const char *name)
+{
+ int atomic_option = 1;
+
+ int ret = ioctl (file, DFS_IOCTL_ATOMIC_WRITE_SET, &atomic_option);
+
+ if (ret) {
+ fprintf(stderr,
+ "InnoDB : can't use atomic write on %s, errno %d\n",
+ name, errno);
+ return ret;
+ }
+ return ret;
+}
+#else
+static int os_file_set_atomic_writes(os_file_t file, const char *name)
+{
+ fprintf(stderr,
+ "InnoDB : can't use atomic writes on %s - not implemented on this platform."
+ "innodb_use_atomic_writes needs to be 0.\n",
+ name);
+#ifdef _WIN32
+ SetLastError(ERROR_INVALID_FUNCTION);
+#else
+ errno = EINVAL;
+#endif
+ return -1;
+}
+#endif
+
/****************************************************************//**
NOTE! Use the corresponding macro os_file_create(), not directly
this function!
@@ -1523,6 +1559,13 @@ try_again:
*success = TRUE;
}
+ if (srv_use_atomic_writes && type == OS_DATA_FILE &&
+ os_file_set_atomic_writes(file, name)) {
+ CloseHandle(file);
+ *success = FALSE;
+ file = INVALID_HANDLE_VALUE;
+ }
+
return(file);
#else /* __WIN__ */
os_file_t file;
@@ -1637,6 +1680,12 @@ try_again:
file = -1;
}
#endif /* USE_FILE_LOCK */
+ if (srv_use_atomic_writes && type == OS_DATA_FILE
+ && os_file_set_atomic_writes(file, name)) {
+ close(file);
+ *success = FALSE;
+ file = -1;
+ }
return(file);
#endif /* __WIN__ */
@@ -1981,6 +2030,28 @@ os_file_set_size(
current_size = 0;
desired_size = (ib_int64_t)size + (((ib_int64_t)size_high) << 32);
+#ifdef HAVE_POSIX_FALLOCATE
+ if (srv_use_posix_fallocate) {
+ if (posix_fallocate(file, current_size, desired_size) == -1) {
+ fprintf(stderr,
+ "InnoDB: Error: preallocating data for"
+ " file %s failed at\n"
+ "InnoDB: offset 0 size %lld %lld. Operating system"
+ " error number %d.\n"
+ "InnoDB: Check that the disk is not full"
+ " or a disk quota exceeded.\n"
+ "InnoDB: Some operating system error numbers"
+ " are described at\n"
+ "InnoDB: "
+ REFMAN "operating-system-error-codes.html\n",
+ name, (long long)size_high, (long long)size, errno);
+
+ return (FALSE);
+ }
+ return (TRUE);
+ }
+#endif
+
/* Write up to 1 megabyte at a time. */
buf_size = ut_min(64, (ulint) (desired_size / UNIV_PAGE_SIZE))
* UNIV_PAGE_SIZE;
@@ -2823,7 +2894,7 @@ retry:
"InnoDB: Check also that the disk is not full"
" or a disk quota exceeded.\n",
name, (ulong) offset_high, (ulong) offset,
- (ulong) n, (ulong) len, (ulong) err);
+ (ulong) n, ret ? len : 0, (ulong) err);
if (strerror((int)err) != NULL) {
fprintf(stderr,
@@ -3387,12 +3458,23 @@ os_aio_array_create(
if (!os_aio_linux_create_io_ctx(n/n_segments,
&array->aio_ctx[i])) {
/* If something bad happened during aio setup
- we should call it a day and return right away.
- We don't care about any leaks because a failure
- to initialize the io subsystem means that the
- server (or atleast the innodb storage engine)
- is not going to startup. */
- return(NULL);
+ we disable linux native aio.
+ The disadvantage will be a small memory leak
+ at shutdown but that's ok compared to a crash
+ or a not working server.
+ This frequently happens when running the test suite
+ with many threads on a system with low fs.aio-max-nr!
+ */
+
+ fprintf(stderr,
+ " InnoDB: Warning: Linux Native AIO disabled "
+ "because os_aio_linux_create_io_ctx() "
+ "failed. To get rid of this warning you can "
+ "try increasing system "
+ "fs.aio-max-nr to 1048576 or larger or "
+ "setting innodb_use_native_aio = 0 in my.cnf\n");
+ srv_use_native_aio = FALSE;
+ goto skip_native_aio;
}
}
diff --git a/storage/innobase/os/os0sync.c b/storage/innobase/os/os0sync.c
index 3a182692da3..babae5cf924 100644
--- a/storage/innobase/os/os0sync.c
+++ b/storage/innobase/os/os0sync.c
@@ -888,6 +888,25 @@ os_fast_mutex_unlock(
}
/**********************************************************//**
+Releases ownership of a fast mutex. Implies a full memory barrier even on
+platforms such as PowerPC where this is not normally required. */
+UNIV_INTERN
+void
+os_fast_mutex_unlock_full_barrier(
+/*=================*/
+ os_fast_mutex_t* fast_mutex) /*!< in: mutex to release */
+{
+#ifdef __WIN__
+ LeaveCriticalSection(fast_mutex);
+#else
+ pthread_mutex_unlock(fast_mutex);
+#ifdef __powerpc__
+ os_mb;
+#endif
+#endif
+}
+
+/**********************************************************//**
Frees a mutex object. */
UNIV_INTERN
void
diff --git a/storage/innobase/os/os0thread.c b/storage/innobase/os/os0thread.c
index 030521aa30b..68a8c973558 100644
--- a/storage/innobase/os/os0thread.c
+++ b/storage/innobase/os/os0thread.c
@@ -136,8 +136,10 @@ os_thread_create(
if (thread_id) {
*thread_id = win_thread_id;
}
-
- return(thread);
+ if (thread) {
+ CloseHandle(thread);
+ }
+ return((os_thread_t)win_thread_id);
#else
int ret;
os_thread_t pthread;
diff --git a/storage/innobase/page/page0zip.c b/storage/innobase/page/page0zip.c
index 49049102443..7c04e0b9183 100644
--- a/storage/innobase/page/page0zip.c
+++ b/storage/innobase/page/page0zip.c
@@ -1,6 +1,7 @@
/*****************************************************************************
Copyright (c) 2005, 2013, Oracle and/or its affiliates. All Rights Reserved.
+Copyright (c) 2014, SkySQL Ab. 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
@@ -46,6 +47,7 @@ Created June 2005 by Marko Makela
# define lock_move_reorganize_page(block, temp_block) ((void) 0)
# define buf_LRU_stat_inc_unzip() ((void) 0)
#endif /* !UNIV_HOTBACKUP */
+#include "srv0srv.h"
#ifndef UNIV_HOTBACKUP
/** Statistics on compression, indexed by page_zip_des_t::ssize - 1 */
@@ -1265,6 +1267,30 @@ page_zip_compress(
goto err_exit;
}
+ /* Simulate a compression failure with a probability determined by
+ innodb_simulate_comp_failures, only if the page has 2 or more
+ records. */
+
+ if (srv_simulate_comp_failures
+ && !dict_index_is_ibuf(index)
+ && page_get_n_recs(page) >= 2
+ && ((ulint)(rand() % 100) < srv_simulate_comp_failures)
+ && strcasecmp(index->table_name, "IBUF_DUMMY") != 0) {
+
+#ifdef UNIV_DEBUG
+ fprintf(stderr,
+ "InnoDB: Simulating a compression failure"
+ " for table %s, index %s, page %lu (%s)\n",
+ index->table_name,
+ index->name,
+ page_get_page_no(page),
+ page_is_leaf(page) ? "leaf" : "non-leaf");
+
+#endif
+
+ goto err_exit;
+ }
+
heap = mem_heap_create(page_zip_get_size(page_zip)
+ n_fields * (2 + sizeof *offsets)
+ n_dense * ((sizeof *recs)
diff --git a/storage/innobase/plugin_exports b/storage/innobase/plugin_exports
new file mode 100644
index 00000000000..e059601c96e
--- /dev/null
+++ b/storage/innobase/plugin_exports
@@ -0,0 +1,13 @@
+{
+ global:
+ _mysql_plugin_interface_version_;
+ _mysql_sizeof_struct_st_plugin_;
+ _mysql_plugin_declarations_;
+ thd_wait_service;
+ my_snprintf_service;
+ thd_alloc_service;
+ thd_kill_statement_service;
+ debug_sync_service;
+ local:
+ *;
+};
diff --git a/storage/innobase/rem/rem0rec.c b/storage/innobase/rem/rem0rec.c
index d938aa696dd..f7252594c29 100644
--- a/storage/innobase/rem/rem0rec.c
+++ b/storage/innobase/rem/rem0rec.c
@@ -1257,7 +1257,7 @@ rec_convert_dtuple_to_rec_comp(
*lens-- = (byte) len;
} else {
ut_ad(len <= dtype_get_len(type)
- || dtype_get_mtype(type) == DATA_BLOB);
+ || dtype_get_mtype(type) == DATA_BLOB);
if (len < 128
|| (dtype_get_len(type) < 256
&& dtype_get_mtype(type) != DATA_BLOB)) {
diff --git a/storage/innobase/row/row0mysql.c b/storage/innobase/row/row0mysql.c
index 181ca966451..1a11e398959 100644
--- a/storage/innobase/row/row0mysql.c
+++ b/storage/innobase/row/row0mysql.c
@@ -3838,6 +3838,7 @@ row_rename_table_for_mysql(
ibool old_is_tmp, new_is_tmp;
pars_info_t* info = NULL;
int retry;
+ char* is_part = NULL;
ut_a(old_name != NULL);
ut_a(new_name != NULL);
@@ -3872,6 +3873,54 @@ row_rename_table_for_mysql(
table = dict_table_get_low(old_name, DICT_ERR_IGNORE_NONE);
+ /* We look for pattern #P# to see if the table is partitioned
+ MySQL table. */
+#ifdef __WIN__
+ is_part = strstr(old_name, "#p#");
+#else
+ is_part = strstr(old_name, "#P#");
+#endif /* __WIN__ */
+
+ /* MySQL partition engine hard codes the file name
+ separator as "#P#". The text case is fixed even if
+ lower_case_table_names is set to 1 or 2. This is true
+ for sub-partition names as well. InnoDB always
+ normalises file names to lower case on Windows, this
+ can potentially cause problems when copying/moving
+ tables between platforms.
+
+ 1) If boot against an installation from Windows
+ platform, then its partition table name could
+ be all be in lower case in system tables. So we
+ will need to check lower case name when load table.
+
+ 2) If we boot an installation from other case
+ sensitive platform in Windows, we might need to
+ check the existence of table name without lowering
+ case them in the system table. */
+ if (!table &&
+ is_part &&
+ innobase_get_lower_case_table_names() == 1) {
+ char par_case_name[MAX_FULL_NAME_LEN + 1];
+#ifndef __WIN__
+ /* Check for the table using lower
+ case name, including the partition
+ separator "P" */
+ memcpy(par_case_name, old_name,
+ strlen(old_name));
+ par_case_name[strlen(old_name)] = 0;
+ innobase_casedn_str(par_case_name);
+#else
+ /* On Windows platfrom, check
+ whether there exists table name in
+ system table whose name is
+ not being normalized to lower case */
+ normalize_table_name_low(
+ par_case_name, old_name, FALSE);
+#endif
+ table = dict_table_get_low(par_case_name, DICT_ERR_IGNORE_NONE);
+ }
+
if (!table) {
err = DB_TABLE_NOT_FOUND;
ut_print_timestamp(stderr);
diff --git a/storage/innobase/row/row0sel.c b/storage/innobase/row/row0sel.c
index b8336f88532..e027a382cee 100644
--- a/storage/innobase/row/row0sel.c
+++ b/storage/innobase/row/row0sel.c
@@ -877,16 +877,15 @@ row_sel_get_clust_rec(
if (!node->read_view) {
/* Try to place a lock on the index record */
-
- /* If innodb_locks_unsafe_for_binlog option is used
- or this session is using READ COMMITTED isolation level
- we lock only the record, i.e., next-key locking is
- not used. */
ulint lock_type;
trx_t* trx;
trx = thr_get_trx(thr);
+ /* If innodb_locks_unsafe_for_binlog option is used
+ or this session is using READ COMMITTED or lower isolation level
+ we lock only the record, i.e., next-key locking is
+ not used. */
if (srv_locks_unsafe_for_binlog
|| trx->isolation_level <= TRX_ISO_READ_COMMITTED) {
lock_type = LOCK_REC_NOT_GAP;
@@ -1491,12 +1490,6 @@ rec_loop:
search result set, resulting in the phantom problem. */
if (!consistent_read) {
-
- /* If innodb_locks_unsafe_for_binlog option is used
- or this session is using READ COMMITTED isolation
- level, we lock only the record, i.e., next-key
- locking is not used. */
-
rec_t* next_rec = page_rec_get_next(rec);
ulint lock_type;
trx_t* trx;
@@ -1506,6 +1499,10 @@ rec_loop:
offsets = rec_get_offsets(next_rec, index, offsets,
ULINT_UNDEFINED, &heap);
+ /* If innodb_locks_unsafe_for_binlog option is used
+ or this session is using READ COMMITTED or lower isolation
+ level, we lock only the record, i.e., next-key
+ locking is not used. */
if (srv_locks_unsafe_for_binlog
|| trx->isolation_level
<= TRX_ISO_READ_COMMITTED) {
@@ -1554,12 +1551,6 @@ skip_lock:
if (!consistent_read) {
/* Try to place a lock on the index record */
-
- /* If innodb_locks_unsafe_for_binlog option is used
- or this session is using READ COMMITTED isolation level,
- we lock only the record, i.e., next-key locking is
- not used. */
-
ulint lock_type;
trx_t* trx;
@@ -1568,6 +1559,10 @@ skip_lock:
trx = thr_get_trx(thr);
+ /* If innodb_locks_unsafe_for_binlog option is used
+ or this session is using READ COMMITTED or lower isolation level,
+ we lock only the record, i.e., next-key locking is
+ not used. */
if (srv_locks_unsafe_for_binlog
|| trx->isolation_level <= TRX_ISO_READ_COMMITTED) {
@@ -3992,7 +3987,7 @@ rec_loop:
/* Try to place a lock on the index record */
/* If innodb_locks_unsafe_for_binlog option is used
- or this session is using a READ COMMITTED isolation
+ or this session is using a READ COMMITTED or lower isolation
level we do not lock gaps. Supremum record is really
a gap and therefore we do not set locks there. */
@@ -4131,7 +4126,7 @@ wrong_offs:
/* Try to place a gap lock on the index
record only if innodb_locks_unsafe_for_binlog
option is not set or this session is not
- using a READ COMMITTED isolation level. */
+ using a READ COMMITTED or lower isolation level. */
err = sel_set_rec_lock(
btr_pcur_get_block(pcur),
@@ -4178,7 +4173,7 @@ wrong_offs:
/* Try to place a gap lock on the index
record only if innodb_locks_unsafe_for_binlog
option is not set or this session is not
- using a READ COMMITTED isolation level. */
+ using a READ COMMITTED or lower isolation level. */
err = sel_set_rec_lock(
btr_pcur_get_block(pcur),
diff --git a/storage/innobase/row/row0upd.c b/storage/innobase/row/row0upd.c
index 825902c4ff2..e7ac42a566f 100644
--- a/storage/innobase/row/row0upd.c
+++ b/storage/innobase/row/row0upd.c
@@ -1268,7 +1268,7 @@ row_upd_changes_ord_field_binary_func(
const upd_field_t* upd_field;
const dfield_t* dfield;
dfield_t dfield_ext;
- ulint dfield_len;
+ ulint dfield_len= 0;
const byte* buf;
ind_field = dict_index_get_nth_field(index, i);
diff --git a/storage/innobase/srv/srv0srv.c b/storage/innobase/srv/srv0srv.c
index f42a4a37c80..1cd21ac5a19 100644
--- a/storage/innobase/srv/srv0srv.c
+++ b/storage/innobase/srv/srv0srv.c
@@ -3,6 +3,7 @@
Copyright (c) 1995, 2016, Oracle and/or its affiliates. All Rights Reserved.
Copyright (c) 2008, 2009 Google Inc.
Copyright (c) 2009, Percona Inc.
+Copyright (c) 2013, 2014, SkySQL Ab. All Rights Reserved.
Portions of this file contain modifications contributed and copyrighted by
Google, Inc. Those modifications are gratefully acknowledged and are described
@@ -401,12 +402,21 @@ this many index pages */
UNIV_INTERN unsigned long long srv_stats_sample_pages = 8;
UNIV_INTERN ibool srv_use_doublewrite_buf = TRUE;
+UNIV_INTERN ibool srv_use_atomic_writes = FALSE;
+#ifdef HAVE_POSIX_FALLOCATE
+UNIV_INTERN ibool srv_use_posix_fallocate = TRUE;
+#endif
UNIV_INTERN ibool srv_use_checksums = TRUE;
UNIV_INTERN ulong srv_replication_delay = 0;
/*-------------------------------------------*/
+#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_n_free_tickets_to_enter = 500;
UNIV_INTERN ulong srv_thread_sleep_delay = 10000;
UNIV_INTERN ulong srv_spin_wait_delay = 6;
@@ -519,6 +529,9 @@ intervals. Following macros define thresholds for these conditions. */
#define SRV_RECENT_IO_ACTIVITY (PCT_IO(5))
#define SRV_PAST_IO_ACTIVITY (PCT_IO(200))
+/** Simulate compression failures. */
+UNIV_INTERN uint srv_simulate_comp_failures = 0;
+
/*
IMPLEMENTATION OF THE SERVER MAIN PROGRAM
=========================================
@@ -736,6 +749,13 @@ static ulint srv_meter_high_water[SRV_MASTER + 1];
static ulint srv_meter_high_water2[SRV_MASTER + 1];
static ulint srv_meter_foreground[SRV_MASTER + 1];
#endif
+/* The number of rows modified before we calculate new statistics (default 0
+= current limits) */
+UNIV_INTERN unsigned long long srv_stats_modified_counter = 0;
+
+/* Enable traditional statistic calculation based on number of configured
+pages default true. */
+UNIV_INTERN my_bool srv_stats_sample_traditional = TRUE;
/* The following values give info about the activity going on in
the database. They are protected by the server mutex. The arrays
diff --git a/storage/innobase/srv/srv0start.c b/storage/innobase/srv/srv0start.c
index 45f8c6d53ab..b9fd52aa833 100644
--- a/storage/innobase/srv/srv0start.c
+++ b/storage/innobase/srv/srv0start.c
@@ -624,16 +624,26 @@ open_or_create_log_file(
if (size != srv_calc_low32(srv_log_file_size)
|| size_high != srv_calc_high32(srv_log_file_size)) {
- fprintf(stderr,
+ /* By default 5.6 based InnoDB will create 48M log
+ file but 5.5 only 5M. Thus give hint to user. */
+ fprintf(stderr,
"InnoDB: Error: log file %s is"
- " of different size %lu %lu bytes\n"
- "InnoDB: than specified in the .cnf"
- " file %lu %lu bytes!\n",
- name, (ulong) size_high, (ulong) size,
- (ulong) srv_calc_high32(srv_log_file_size),
- (ulong) srv_calc_low32(srv_log_file_size));
+ " of different size %lu %lu bytes\n"
+ "InnoDB: than specified in the .cnf"
+ " file %lu %lu bytes!\n",
+ name, (ulong) size_high, (ulong) size,
+ (ulong) srv_calc_high32(srv_log_file_size),
+ (ulong) srv_calc_low32(srv_log_file_size));
+
+ fprintf(stderr,
+ "InnoDB: Possible causes for this error:\n"
+ " (a) Incorrect log file is used or log file size is changed\n"
+ " (b) In case default size is used this log file is from 10.0\n"
+ " (c) Log file is corrupted or there was not enough disk space\n"
+ " In case (b) you need to set innodb_log_file_size = 48M\n");
return(DB_ERROR);
+
}
} else {
*log_file_created = TRUE;
diff --git a/storage/innobase/sync/sync0arr.c b/storage/innobase/sync/sync0arr.c
index 901c1e9a706..62d35ccd302 100644
--- a/storage/innobase/sync/sync0arr.c
+++ b/storage/innobase/sync/sync0arr.c
@@ -2,6 +2,7 @@
Copyright (c) 1995, 2015, Oracle and/or its affiliates. All Rights Reserved.
Copyright (c) 2008, Google Inc.
+Copyright (c) 2013, 2014, MariaDB Corporation. All Rights Reserved.
Portions of this file contain modifications contributed and copyrighted by
Google, Inc. Those modifications are gratefully acknowledged and are described
@@ -466,11 +467,13 @@ static
void
sync_array_cell_print(
/*==================*/
- FILE* file, /*!< in: file where to print */
- sync_cell_t* cell) /*!< in: sync cell */
+ FILE* file, /*!< in: file where to print */
+ sync_cell_t* cell, /*!< in: sync cell */
+ os_thread_id_t* reserver) /*!< out: write reserver or
+ 0 */
{
- mutex_t* mutex;
- rw_lock_t* rwlock;
+ mutex_t* mutex = NULL;
+ rw_lock_t* rwlock = NULL;
ulint type;
ulint writer;
@@ -525,6 +528,8 @@ sync_array_cell_print(
writer == RW_LOCK_EX
? " exclusive\n"
: " wait exclusive\n");
+
+ *reserver = rwlock->writer_thread;
}
fprintf(file,
@@ -548,7 +553,6 @@ sync_array_cell_print(
}
}
-#ifdef UNIV_SYNC_DEBUG
/******************************************************************//**
Looks for a cell with the given thread id.
@return pointer to cell or NULL if not found */
@@ -576,6 +580,8 @@ sync_array_find_thread(
return(NULL); /* Not found */
}
+#ifdef UNIV_SYNC_DEBUG
+
/******************************************************************//**
Recursion step for deadlock detection.
@return TRUE if deadlock detected */
@@ -785,6 +791,7 @@ sync_arr_cell_can_wake_up(
lock = cell->wait_object;
+ os_rmb;
if (lock->lock_word > 0) {
/* Either unlocked or only read locked. */
@@ -796,6 +803,7 @@ sync_arr_cell_can_wake_up(
lock = cell->wait_object;
/* lock_word == 0 means all readers have left */
+ os_rmb;
if (lock->lock_word == 0) {
return(TRUE);
@@ -804,6 +812,7 @@ sync_arr_cell_can_wake_up(
lock = cell->wait_object;
/* lock_word > 0 means no writer or reserved writer */
+ os_rmb;
if (lock->lock_word > 0) {
return(TRUE);
@@ -947,6 +956,7 @@ sync_array_print_long_waits(
double diff;
void* wait_object;
+ os_thread_id_t reserver=0;
cell = sync_array_get_nth_cell(sync_primary_wait_array, i);
@@ -962,7 +972,7 @@ sync_array_print_long_waits(
if (diff > SYNC_ARRAY_TIMEOUT) {
fputs("InnoDB: Warning: a long semaphore wait:\n",
stderr);
- sync_array_cell_print(stderr, cell);
+ sync_array_cell_print(stderr, cell, &reserver);
noticed = TRUE;
}
@@ -977,6 +987,46 @@ sync_array_print_long_waits(
}
}
+ /* We found a long semaphore wait, wait all threads that are
+ waiting for a semaphore. */
+ if (noticed) {
+ for (i = 0; i < sync_primary_wait_array->n_cells; i++) {
+ void* wait_object;
+ os_thread_id_t reserver=0;
+
+ cell = sync_array_get_nth_cell(sync_primary_wait_array, i);
+
+ wait_object = cell->wait_object;
+
+ if (wait_object == NULL || !cell->waiting) {
+
+ continue;
+ }
+
+ fputs("InnoDB: Warning: semaphore wait:\n",
+ stderr);
+ sync_array_cell_print(stderr, cell, &reserver);
+ noticed = TRUE;
+
+ /* Try to output cell information for writer recursive way */
+ while (reserver != 0) {
+ sync_cell_t* reserver_wait;
+
+ reserver_wait = sync_array_find_thread(sync_primary_wait_array, reserver);
+
+ if (reserver_wait &&
+ reserver_wait->wait_object != NULL &&
+ reserver_wait->waiting) {
+ fputs("InnoDB: Warning: Writer thread is waiting this semaphore:\n",
+ stderr);
+ sync_array_cell_print(stderr, reserver_wait, &reserver);
+ } else {
+ reserver = 0;
+ }
+ }
+ }
+ }
+
sync_array_exit(sync_primary_wait_array);
if (noticed) {
@@ -1025,6 +1075,7 @@ sync_array_output_info(
sync_cell_t* cell;
ulint count;
ulint i;
+ os_thread_id_t r;
fprintf(file,
"OS WAIT ARRAY INFO: reservation count " ULINTPF
@@ -1037,9 +1088,9 @@ sync_array_output_info(
cell = sync_array_get_nth_cell(arr, i);
- if (cell->wait_object != NULL) {
- count++;
- sync_array_cell_print(file, cell);
+ if (cell->wait_object != NULL) {
+ count++;
+ sync_array_cell_print(file, cell, &r);
}
i++;
@@ -1061,3 +1112,66 @@ sync_array_print_info(
sync_array_exit(arr);
}
+
+/**********************************************************************//**
+Prints info of the wait array without using any mutexes/semaphores. */
+UNIV_INTERN
+void
+sync_array_print_innodb(void)
+/*=========================*/
+{
+ ulint i;
+ sync_array_t* arr = sync_array_get();
+
+ fputs("InnoDB: Semaphore wait debug output started for InnoDB:\n", stderr);
+
+ for (i = 0; i < arr->n_cells; i++) {
+ void* wait_object;
+ sync_cell_t* cell;
+ os_thread_id_t reserver=(os_thread_id_t)ULINT_UNDEFINED;
+ ulint loop=0;
+
+ cell = sync_array_get_nth_cell(arr, i);
+
+ wait_object = cell->wait_object;
+
+ if (wait_object == NULL || !cell->waiting) {
+
+ continue;
+ }
+
+ fputs("InnoDB: Warning: semaphore wait:\n",
+ stderr);
+ sync_array_cell_print(stderr, cell, &reserver);
+
+ /* Try to output cell information for writer recursive way */
+ while (reserver != (os_thread_id_t)ULINT_UNDEFINED) {
+ sync_cell_t* reserver_wait;
+
+ reserver_wait = sync_array_find_thread(arr, reserver);
+
+ if (reserver_wait &&
+ reserver_wait->wait_object != NULL &&
+ reserver_wait->waiting) {
+ fputs("InnoDB: Warning: Writer thread is waiting this semaphore:\n",
+ stderr);
+ sync_array_cell_print(stderr, reserver_wait, &reserver);
+
+ if (reserver_wait->thread == reserver) {
+ reserver = (os_thread_id_t)ULINT_UNDEFINED;
+ }
+ } else {
+ reserver = (os_thread_id_t)ULINT_UNDEFINED;
+ }
+
+ /* This is protection against loop */
+ if (loop > 100) {
+ fputs("InnoDB: Warning: Too many waiting threads.\n", stderr);
+ break;
+ }
+ }
+ }
+
+ fputs("InnoDB: Semaphore wait debug output ended:\n", stderr);
+
+}
diff --git a/storage/innobase/sync/sync0rw.c b/storage/innobase/sync/sync0rw.c
index 8de9b40ef67..5600db855b4 100644
--- a/storage/innobase/sync/sync0rw.c
+++ b/storage/innobase/sync/sync0rw.c
@@ -40,6 +40,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
@@ -179,18 +180,12 @@ UNIV_INTERN mysql_pfs_key_t rw_lock_mutex_key;
To modify the debug info list of an rw-lock, this mutex has to be
acquired in addition to the mutex protecting the lock. */
-UNIV_INTERN mutex_t rw_lock_debug_mutex;
+UNIV_INTERN os_fast_mutex_t rw_lock_debug_mutex;
# ifdef UNIV_PFS_MUTEX
UNIV_INTERN mysql_pfs_key_t rw_lock_debug_mutex_key;
# endif
-/* If deadlock detection does not get immediately the mutex,
-it may wait for this event */
-UNIV_INTERN os_event_t rw_lock_debug_event;
-/* This is set to TRUE, if there may be waiters for the event */
-UNIV_INTERN ibool rw_lock_debug_waiters;
-
/******************************************************************//**
Creates a debug info struct. */
static
@@ -390,15 +385,19 @@ rw_lock_s_lock_spin(
lock_loop:
/* 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, srv_spin_wait_delay));
}
i++;
+ os_rmb;
}
-
- if (i == SYNC_SPIN_ROUNDS) {
+ HMT_medium();
+ if (lock->lock_word <= 0)
+ {
os_thread_yield();
}
@@ -498,16 +497,19 @@ rw_lock_x_lock_wait(
ulint index;
ulint i = 0;
+ os_rmb;
ut_ad(lock->lock_word <= 0);
-
+ HMT_low();
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_x_spin_round_count += i;
@@ -544,7 +546,9 @@ rw_lock_x_lock_wait(
sync_array_free_cell(sync_primary_wait_array,
index);
}
+ HMT_low();
}
+ HMT_medium();
rw_x_spin_round_count += i;
}
@@ -562,6 +566,7 @@ rw_lock_x_lock_low(
ulint line) /*!< in: line where requested */
{
os_thread_id_t curr_thread = os_thread_get_curr_id();
+ ibool local_recursive= lock->recursive;
if (rw_lock_lock_word_decr(lock, X_LOCK_DECR)) {
@@ -582,8 +587,12 @@ rw_lock_x_lock_low(
file_name, line);
} else {
- /* Decrement failed: relock or failed lock */
- if (!pass && lock->recursive
+ /* Decrement failed: relock or failed lock
+ Note: recursive must be loaded before writer_thread see
+ comment for rw_lock_set_writer_id_and_recursion_flag().
+ To achieve this we load it before rw_lock_lock_word_decr(),
+ which implies full memory barrier in current implementation. */
+ if (!pass && local_recursive
&& os_thread_eq(lock->writer_thread, curr_thread)) {
/* Relock */
lock->lock_word -= X_LOCK_DECR;
@@ -647,6 +656,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) {
@@ -655,7 +666,9 @@ lock_loop:
}
i++;
+ os_rmb;
}
+ HMT_medium();
if (i == SYNC_SPIN_ROUNDS) {
os_thread_yield();
} else {
@@ -720,22 +733,7 @@ void
rw_lock_debug_mutex_enter(void)
/*===========================*/
{
-loop:
- if (0 == mutex_enter_nowait(&rw_lock_debug_mutex)) {
- return;
- }
-
- os_event_reset(rw_lock_debug_event);
-
- rw_lock_debug_waiters = TRUE;
-
- if (0 == mutex_enter_nowait(&rw_lock_debug_mutex)) {
- return;
- }
-
- os_event_wait(rw_lock_debug_event);
-
- goto loop;
+ os_fast_mutex_lock(&rw_lock_debug_mutex);
}
/******************************************************************//**
@@ -745,12 +743,7 @@ void
rw_lock_debug_mutex_exit(void)
/*==========================*/
{
- mutex_exit(&rw_lock_debug_mutex);
-
- if (rw_lock_debug_waiters) {
- rw_lock_debug_waiters = FALSE;
- os_event_set(rw_lock_debug_event);
- }
+ os_fast_mutex_unlock(&rw_lock_debug_mutex);
}
/******************************************************************//**
diff --git a/storage/innobase/sync/sync0sync.c b/storage/innobase/sync/sync0sync.c
index 8ce62d5ea45..2f2fef4b1c6 100644
--- a/storage/innobase/sync/sync0sync.c
+++ b/storage/innobase/sync/sync0sync.c
@@ -35,6 +35,9 @@ Created 9/5/1995 Heikki Tuuri
#include "sync0sync.ic"
#endif
+/* disable timed_mutexes - obsolete feature that doesn't link on windows */
+#define timed_mutexes 0
+
#include "sync0rw.h"
#include "buf0buf.h"
#include "srv0srv.h"
@@ -44,6 +47,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
@@ -313,9 +317,9 @@ mutex_create_func(
/* NOTE! The very first mutexes are not put to the mutex list */
- if ((mutex == &mutex_list_mutex)
+ if (mutex == &mutex_list_mutex
#ifdef UNIV_SYNC_DEBUG
- || (mutex == &sync_thread_mutex)
+ || mutex == &sync_thread_mutex
#endif /* UNIV_SYNC_DEBUG */
) {
@@ -517,13 +521,15 @@ mutex_loop:
spin_loop:
ut_d(mutex->count_spin_loop++);
+ HMT_low();
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));
}
-
+ os_rmb; // Ensure future reads sees new values
i++;
}
+ HMT_medium();
if (i == SYNC_SPIN_ROUNDS) {
#ifdef UNIV_DEBUG
@@ -587,6 +593,11 @@ spin_loop:
mutex_set_waiters(mutex, 1);
+ /* Make sure waiters store won't pass over mutex_test_and_set */
+#ifdef __powerpc__
+ os_mb;
+#endif
+
/* Try to reserve still a few times */
for (i = 0; i < 4; i++) {
if (mutex_test_and_set(mutex) == 0) {
@@ -1527,11 +1538,7 @@ sync_init(void)
SYNC_NO_ORDER_CHECK);
#ifdef UNIV_SYNC_DEBUG
- mutex_create(rw_lock_debug_mutex_key, &rw_lock_debug_mutex,
- SYNC_NO_ORDER_CHECK);
-
- rw_lock_debug_event = os_event_create(NULL);
- rw_lock_debug_waiters = FALSE;
+ os_fast_mutex_init(rw_lock_debug_mutex_key, &rw_lock_debug_mutex);
#endif /* UNIV_SYNC_DEBUG */
}
@@ -1599,6 +1606,7 @@ sync_close(void)
sync_order_checks_on = FALSE;
sync_thread_level_arrays_free();
+ os_fast_mutex_free(&rw_lock_debug_mutex);
#endif /* UNIV_SYNC_DEBUG */
sync_initialized = FALSE;
@@ -1660,3 +1668,13 @@ sync_print(
sync_print_wait_info(file);
}
+
+/*******************************************************************//**
+Get sync array */
+UNIV_INTERN
+sync_array_t*
+sync_array_get(void)
+/*================*/
+{
+ return sync_primary_wait_array;
+}
diff --git a/storage/innobase/trx/trx0i_s.c b/storage/innobase/trx/trx0i_s.c
index 8b3a83585cc..f3715c5a731 100644
--- a/storage/innobase/trx/trx0i_s.c
+++ b/storage/innobase/trx/trx0i_s.c
@@ -155,10 +155,6 @@ struct trx_i_s_cache_struct {
ullint last_read; /*!< last time the cache was read;
measured in microseconds since
epoch */
- mutex_t last_read_mutex;/*!< mutex protecting the
- last_read member - it is updated
- inside a shared lock of the
- rw_lock member */
i_s_table_cache_t innodb_trx; /*!< innodb_trx table */
i_s_table_cache_t innodb_locks; /*!< innodb_locks table */
i_s_table_cache_t innodb_lock_waits;/*!< innodb_lock_waits table */
@@ -1225,13 +1221,6 @@ can_cache_be_updated(
{
ullint now;
- /* Here we read cache->last_read without acquiring its mutex
- because last_read is only updated when a shared rw lock on the
- whole cache is being held (see trx_i_s_cache_end_read()) and
- we are currently holding an exclusive rw lock on the cache.
- So it is not possible for last_read to be updated while we are
- reading it. */
-
#ifdef UNIV_SYNC_DEBUG
ut_a(rw_lock_own(&cache->rw_lock, RW_LOCK_EX));
#endif
@@ -1329,6 +1318,12 @@ trx_i_s_possibly_fetch_data_into_cache(
/*===================================*/
trx_i_s_cache_t* cache) /*!< in/out: cache */
{
+ ullint now;
+
+#ifdef UNIV_SYNC_DEBUG
+ ut_a(rw_lock_own(&cache->rw_lock, RW_LOCK_EX));
+#endif
+
if (!can_cache_be_updated(cache)) {
return(1);
@@ -1341,6 +1336,10 @@ trx_i_s_possibly_fetch_data_into_cache(
mutex_exit(&kernel_mutex);
+ /* update cache last read time */
+ now = ut_time_us(NULL);
+ cache->last_read = now;
+
return(0);
}
@@ -1371,8 +1370,6 @@ trx_i_s_cache_init(
release kernel_mutex
release trx_i_s_cache_t::rw_lock
acquire trx_i_s_cache_t::rw_lock, S
- acquire trx_i_s_cache_t::last_read_mutex
- release trx_i_s_cache_t::last_read_mutex
release trx_i_s_cache_t::rw_lock */
rw_lock_create(trx_i_s_cache_lock_key, &cache->rw_lock,
@@ -1380,9 +1377,6 @@ trx_i_s_cache_init(
cache->last_read = 0;
- mutex_create(cache_last_read_mutex_key,
- &cache->last_read_mutex, SYNC_TRX_I_S_LAST_READ);
-
table_cache_init(&cache->innodb_trx, sizeof(i_s_trx_row_t));
table_cache_init(&cache->innodb_locks, sizeof(i_s_locks_row_t));
table_cache_init(&cache->innodb_lock_waits,
@@ -1433,18 +1427,10 @@ trx_i_s_cache_end_read(
/*===================*/
trx_i_s_cache_t* cache) /*!< in: cache */
{
- ullint now;
-
#ifdef UNIV_SYNC_DEBUG
ut_a(rw_lock_own(&cache->rw_lock, RW_LOCK_SHARED));
#endif
- /* update cache last read time */
- now = ut_time_us(NULL);
- mutex_enter(&cache->last_read_mutex);
- cache->last_read = now;
- mutex_exit(&cache->last_read_mutex);
-
rw_lock_s_unlock(&cache->rw_lock);
}
diff --git a/storage/innobase/trx/trx0sys.c b/storage/innobase/trx/trx0sys.c
index d5649ea9890..256e22d1b50 100644
--- a/storage/innobase/trx/trx0sys.c
+++ b/storage/innobase/trx/trx0sys.c
@@ -1415,7 +1415,7 @@ trx_sys_print_mysql_binlog_offset_from_page(
/* THESE ARE COPIED FROM NON-HOTBACKUP PART OF THE INNODB SOURCE TREE
- (This code duplicaton should be fixed at some point!)
+ (This code duplication should be fixed at some point!)
*/
#define TRX_SYS_SPACE 0 /* the SYSTEM tablespace */
diff --git a/storage/innobase/trx/trx0trx.c b/storage/innobase/trx/trx0trx.c
index 3fff702cacc..2d585b7507f 100644
--- a/storage/innobase/trx/trx0trx.c
+++ b/storage/innobase/trx/trx0trx.c
@@ -110,7 +110,7 @@ trx_create(
trx->conc_state = TRX_NOT_STARTED;
trx->is_registered = 0;
- trx->owns_prepare_mutex = 0;
+ trx->active_commit_ordered = 0;
trx->start_time = ut_time();