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