diff options
Diffstat (limited to 'storage/innobase/handler')
| -rw-r--r-- | storage/innobase/handler/ha_innodb.cc | 1152 | ||||
| -rw-r--r-- | storage/innobase/handler/ha_innodb.h | 18 | ||||
| -rw-r--r-- | storage/innobase/handler/handler0alter.cc | 253 | ||||
| -rw-r--r-- | storage/innobase/handler/i_s.cc | 347 | ||||
| -rw-r--r-- | storage/innobase/handler/i_s.h | 56 |
5 files changed, 1162 insertions, 664 deletions
diff --git a/storage/innobase/handler/ha_innodb.cc b/storage/innobase/handler/ha_innodb.cc index 22d51a439e1..f6c2a08ee38 100644 --- a/storage/innobase/handler/ha_innodb.cc +++ b/storage/innobase/handler/ha_innodb.cc @@ -4,6 +4,7 @@ Copyright (c) 2000, 2015, Oracle and/or its affiliates. All Rights Reserved. Copyright (c) 2008, 2009 Google Inc. Copyright (c) 2009, Percona Inc. Copyright (c) 2012, Facebook Inc. +Copyright (c) 2013, 2015, MariaDB Corporation. Portions of this file contain modifications contributed and copyrighted by Google, Inc. Those modifications are gratefully acknowledged and are described @@ -39,8 +40,14 @@ this program; if not, write to the Free Software Foundation, Inc., #include <debug_sync.h> // DEBUG_SYNC #include <my_base.h> // HA_OPTION_* #include <mysys_err.h> -#include <mysql/innodb_priv.h> +#include <innodb_priv.h> +#include <table_cache.h> #include <my_check_opt.h> + +#ifdef _WIN32 +#include <io.h> +#endif + /** @file ha_innodb.cc */ /* Include necessary InnoDB headers */ @@ -95,7 +102,12 @@ this program; if not, write to the Free Software Foundation, Inc., #include "fts0priv.h" #include "page0zip.h" -enum_tx_isolation thd_get_trx_isolation(const THD* thd); +#define thd_get_trx_isolation(X) ((enum_tx_isolation)thd_tx_isolation(X)) + +#ifdef MYSQL_DYNAMIC_PLUGIN +#define tc_size 400 +#define tdc_size 400 +#endif #include "ha_innodb.h" #include "i_s.h" @@ -110,6 +122,7 @@ static mysql_mutex_t innobase_share_mutex; static ulong commit_threads = 0; static mysql_cond_t commit_cond; static mysql_mutex_t commit_cond_m; +static mysql_mutex_t pending_checkpoint_mutex; static bool innodb_inited = 0; #define INSIDE_HA_INNOBASE_CC @@ -175,6 +188,8 @@ static my_bool innobase_file_format_check = TRUE; static my_bool innobase_log_archive = FALSE; static char* innobase_log_arch_dir = NULL; #endif /* UNIV_LOG_ARCHIVE */ +static my_bool innobase_use_atomic_writes = FALSE; +static my_bool innobase_use_fallocate = TRUE; static my_bool innobase_use_doublewrite = TRUE; static my_bool innobase_use_checksums = TRUE; static my_bool innobase_locks_unsafe_for_binlog = FALSE; @@ -266,6 +281,7 @@ performance schema */ static mysql_pfs_key_t innobase_share_mutex_key; static mysql_pfs_key_t commit_cond_mutex_key; static mysql_pfs_key_t commit_cond_key; +static mysql_pfs_key_t pending_checkpoint_mutex_key; static PSI_mutex_info all_pthread_mutexes[] = { {&commit_cond_mutex_key, "commit_cond_mutex", 0}, @@ -514,6 +530,15 @@ innobase_map_isolation_level( /*=========================*/ enum_tx_isolation iso); /*!< in: MySQL isolation level code */ +/******************************************************************//** +Maps a MySQL trx isolation level code to the InnoDB isolation level code +@return InnoDB isolation level */ +static inline +ulint +innobase_map_isolation_level( +/*=========================*/ + enum_tx_isolation iso); /*!< in: MySQL isolation level code */ + static const char innobase_hton_name[]= "InnoDB"; static MYSQL_THDVAR_BOOL(support_xa, PLUGIN_VAR_OPCMDARG, @@ -619,6 +644,12 @@ static SHOW_VAR innodb_status_variables[]= { (char*) &export_vars.innodb_os_log_pending_writes, SHOW_LONG}, {"os_log_written", (char*) &export_vars.innodb_os_log_written, SHOW_LONGLONG}, + {"os_merge_buffers_written", + (char*) &export_vars.innodb_merge_buffers_written, SHOW_LONGLONG}, + {"os_merge_buffers_read", + (char*) &export_vars.innodb_merge_buffers_read, SHOW_LONGLONG}, + {"os_merge_buffers_merged", + (char*) &export_vars.innodb_merge_buffers_merged, SHOW_LONGLONG}, {"page_size", (char*) &export_vars.innodb_page_size, SHOW_LONG}, {"pages_created", @@ -645,6 +676,14 @@ static SHOW_VAR innodb_status_variables[]= { (char*) &export_vars.innodb_rows_read, SHOW_LONG}, {"rows_updated", (char*) &export_vars.innodb_rows_updated, SHOW_LONG}, + {"system_rows_deleted", + (char*) &export_vars.innodb_system_rows_deleted, SHOW_LONG}, + {"system_rows_inserted", + (char*) &export_vars.innodb_system_rows_inserted, SHOW_LONG}, + {"system_rows_read", + (char*) &export_vars.innodb_system_rows_read, SHOW_LONG}, + {"system_rows_updated", + (char*) &export_vars.innodb_system_rows_updated, SHOW_LONG}, {"num_open_files", (char*) &export_vars.innodb_num_open_files, SHOW_LONG}, {"truncated_status_writes", @@ -688,6 +727,9 @@ innobase_close_connection( THD* thd); /*!< in: MySQL thread handle for which to close the connection */ +static void innobase_kill_query(handlerton *hton, THD* thd, enum thd_kill_levels level); +static void innobase_commit_ordered(handlerton *hton, THD* thd, bool all); + /*****************************************************************//** Commits a transaction in an InnoDB database or marks an SQL statement ended. @@ -774,6 +816,8 @@ innobase_release_savepoint( savepoint should be released */ void* savepoint); /*!< in: savepoint data */ +static void innobase_checkpoint_request(handlerton *hton, void *cookie); + /************************************************************************//** Function for constructing an InnoDB table handler instance. */ static @@ -1371,8 +1415,7 @@ convert_error_code_to_mysql( return(0); case DB_INTERRUPTED: - my_error(ER_QUERY_INTERRUPTED, MYF(0)); - return(-1); + return(HA_ERR_ABORTED_BY_USER); case DB_FOREIGN_EXCEED_MAX_CASCADE: ut_ad(thd); @@ -1401,9 +1444,6 @@ convert_error_code_to_mysql( return(HA_ERR_FOUND_DUPP_KEY); case DB_READ_ONLY: - if(srv_force_recovery) { - return(HA_ERR_INNODB_FORCED_RECOVERY); - } return(HA_ERR_TABLE_READONLY); case DB_FOREIGN_DUPLICATE_KEY: @@ -1462,7 +1502,11 @@ convert_error_code_to_mysql( return(HA_ERR_RECORD_FILE_FULL); case DB_TEMP_FILE_WRITE_FAILURE: - return(HA_ERR_TEMP_FILE_WRITE_FAILURE); + my_error(ER_GET_ERRMSG, MYF(0), + DB_TEMP_FILE_WRITE_FAILURE, + ut_strerr(DB_TEMP_FILE_WRITE_FAILURE), + "InnoDB"); + return(HA_ERR_INTERNAL_ERROR); case DB_TABLE_IN_FK_CHECK: return(HA_ERR_TABLE_IN_FK_CHECK); @@ -1525,7 +1569,7 @@ convert_error_code_to_mysql( case DB_FTS_INVALID_DOCID: return(HA_FTS_INVALID_DOCID); case DB_FTS_EXCEED_RESULT_CACHE_LIMIT: - return(HA_ERR_FTS_EXCEED_RESULT_CACHE_LIMIT); + return(HA_ERR_OUT_OF_MEM); case DB_TOO_MANY_CONCURRENT_TRXS: return(HA_ERR_TOO_MANY_CONCURRENT_TRXS); case DB_UNSUPPORTED: @@ -1558,8 +1602,8 @@ innobase_mysql_print_thd( { char buffer[1024]; - fputs(thd_security_context(thd, buffer, sizeof buffer, - max_query_len), f); + fputs(thd_get_error_context_description(thd, buffer, sizeof buffer, + max_query_len), f); putc('\n', f); } @@ -1603,7 +1647,7 @@ innobase_get_cset_width( /* Fix bug#46256: allow tables to be dropped if the collation is not found, but issue a warning. */ - if ((log_warnings) + if ((global_system_variables.log_warnings) && (cset != 0)){ sql_print_warning( @@ -1631,7 +1675,7 @@ innobase_convert_from_table_id( { uint errors; - strconvert(cs, from, &my_charset_filename, to, (uint) len, &errors); + strconvert(cs, from, FN_REFLEN, &my_charset_filename, to, (uint) len, &errors); } /********************************************************************** @@ -1672,7 +1716,7 @@ innobase_convert_from_id( { uint errors; - strconvert(cs, from, system_charset_info, to, (uint) len, &errors); + strconvert(cs, from, FN_REFLEN, system_charset_info, to, (uint) len, &errors); } /******************************************************************//** @@ -1767,16 +1811,16 @@ innobase_get_stmt( } /**********************************************************************//** -Get the current setting of the table_def_size global parameter. We do +Get the current setting of the tdc_size global parameter. We do a dirty read because for one there is no synchronization object and secondly there is little harm in doing so even if we get a torn read. -@return value of table_def_size */ +@return value of tdc_size */ UNIV_INTERN ulint innobase_get_table_cache_size(void) /*===============================*/ { - return(table_def_size); + return(tdc_size); } /**********************************************************************//** @@ -1844,13 +1888,11 @@ innobase_mysql_tmpfile(void) fd2 = dup(fd); #endif if (fd2 < 0) { - char errbuf[MYSYS_STRERROR_SIZE]; DBUG_PRINT("error",("Got error %d on dup",fd2)); my_errno=errno; my_error(EE_OUT_OF_FILERESOURCES, MYF(ME_BELL+ME_WAITTANG), - "ib*", my_errno, - my_strerror(errbuf, sizeof(errbuf), my_errno)); + "ib*", my_errno); } my_close(fd, MYF(MY_WME)); } @@ -1955,6 +1997,15 @@ innobase_next_autoinc( ut_a(block > 0); ut_a(max_value > 0); + /* + Allow auto_increment to go over max_value up to max ulonglong. + This allows us to detect that all values are exhausted. + If we don't do this, we will return max_value several times + and get duplicate key errors instead of auto increment value + out of range. + */ + max_value= (~(ulonglong) 0); + /* According to MySQL documentation, if the offset is greater than the step then the offset is ignored. */ if (offset > block) { @@ -1987,10 +2038,11 @@ innobase_next_autoinc( if (next_value == 0) { ulonglong next; - if (current > offset) { + if (current >= offset) { next = (current - offset) / step; } else { - next = (offset - current) / step; + next = 0; + block -= step; } ut_a(max_value > next); @@ -2030,7 +2082,6 @@ innobase_trx_init( trx_t* trx) /*!< in/out: InnoDB transaction handle */ { DBUG_ENTER("innobase_trx_init"); - DBUG_ASSERT(EQ_CURRENT_THD(thd)); DBUG_ASSERT(thd == trx->mysql_thd); trx->check_foreigns = !thd_test_options( @@ -2079,10 +2130,9 @@ check_trx_exists( { trx_t*& trx = thd_to_trx(thd); - ut_ad(EQ_CURRENT_THD(thd)); - if (trx == NULL) { trx = innobase_trx_allocate(thd); + thd_set_ha_data(thd, innodb_hton_ptr, trx); } else if (UNIV_UNLIKELY(trx->magic_n != TRX_MAGIC_N)) { mem_analyze_corruption(trx); ut_error; @@ -2106,6 +2156,18 @@ trx_is_registered_for_2pc( } /*********************************************************************//** +Note that innobase_commit_ordered() was run. */ +static inline +void +trx_set_active_commit_ordered( +/*==============================*/ + trx_t* trx) /* in: transaction */ +{ + ut_a(trx_is_registered_for_2pc(trx)); + trx->active_commit_ordered = 1; +} + +/*********************************************************************//** Note that a transaction has been registered with MySQL 2PC coordinator. */ static inline void @@ -2114,7 +2176,7 @@ trx_register_for_2pc( trx_t* trx) /* in: transaction */ { trx->is_registered = 1; - ut_ad(trx->owns_prepare_mutex == 0); + ut_ad(trx->active_commit_ordered == 0); } /*********************************************************************//** @@ -2126,9 +2188,19 @@ trx_deregister_from_2pc( trx_t* trx) /* in: transaction */ { trx->is_registered = 0; - trx->owns_prepare_mutex = 0; + trx->active_commit_ordered = 0; } +/*********************************************************************//** +Check whether a transaction has active_commit_ordered set */ +static inline +bool +trx_is_active_commit_ordered( +/*=========================*/ + const trx_t* trx) /* in: transaction */ +{ + return(trx->active_commit_ordered == 1); +} /*********************************************************************//** Check if transaction is started. @@ -2223,7 +2295,7 @@ ha_innobase::ha_innobase( TABLE_SHARE* table_arg) :handler(hton, table_arg), int_table_flags(HA_REC_NOT_IN_SEQ | - HA_NULL_IN_KEY | + HA_NULL_IN_KEY | HA_CAN_VIRTUAL_COLUMNS | HA_CAN_INDEX_BLOBS | HA_CAN_SQL_HANDLER | HA_PRIMARY_KEY_REQUIRED_FOR_POSITION | @@ -2682,7 +2754,7 @@ trx_is_interrupted( /*===============*/ const trx_t* trx) /*!< in: transaction */ { - return(trx && trx->mysql_thd && thd_killed(trx->mysql_thd)); + return(trx && trx->mysql_thd && thd_kill_level(trx->mysql_thd)); } /**********************************************************************//** @@ -2778,6 +2850,14 @@ ha_innobase::init_table_handle_for_HANDLER(void) reset_template(); } +/****************************************************************//** +Gives the file extension of an InnoDB single-table tablespace. */ +static const char* ha_innobase_exts[] = { + ".ibd", + ".isl", + NullS +}; + /*********************************************************************//** Opens an InnoDB database. @return 0 on success, error code on failure */ @@ -2807,12 +2887,15 @@ innobase_init( innobase_hton->savepoint_rollback_can_release_mdl = innobase_rollback_to_savepoint_can_release_mdl; innobase_hton->savepoint_release = innobase_release_savepoint; + innobase_hton->prepare_ordered= NULL; + innobase_hton->commit_ordered= innobase_commit_ordered; innobase_hton->commit = innobase_commit; innobase_hton->rollback = innobase_rollback; innobase_hton->prepare = innobase_xa_prepare; innobase_hton->recover = innobase_xa_recover; innobase_hton->commit_by_xid = innobase_commit_by_xid; innobase_hton->rollback_by_xid = innobase_rollback_by_xid; + innobase_hton->commit_checkpoint_request=innobase_checkpoint_request; innobase_hton->create_cursor_read_view = innobase_create_cursor_view; innobase_hton->set_cursor_read_view = innobase_set_cursor_view; innobase_hton->close_cursor_read_view = innobase_close_cursor_view; @@ -2830,8 +2913,10 @@ innobase_init( innobase_hton->release_temporary_latches = innobase_release_temporary_latches; + innobase_hton->kill_query = innobase_kill_query; - innobase_hton->data = &innodb_api_cb; + if (srv_file_per_table) + innobase_hton->tablefile_extensions = ha_innobase_exts; ut_a(DATA_MYSQL_TRUE_VARCHAR == (ulint)MYSQL_TYPE_VARCHAR); @@ -3058,7 +3143,7 @@ innobase_change_buffering_inited_ok: " cannot be set higher than" " innodb_max_dirty_pages_pct.\n" "InnoDB: Setting" - " innodb_max_dirty_pages_pct_lwm to %lu\n", + " innodb_max_dirty_pages_pct_lwm to %lf\n", srv_max_buf_pool_modified_pct); srv_max_dirty_pages_pct_lwm = srv_max_buf_pool_modified_pct; @@ -3201,8 +3286,8 @@ innobase_change_buffering_inited_ok: if (innobase_open_files < 10) { innobase_open_files = 300; - if (srv_file_per_table && table_cache_size > 300) { - innobase_open_files = table_cache_size; + if (srv_file_per_table && tc_size > 300) { + innobase_open_files = tc_size; } } srv_max_n_open_files = (ulint) innobase_open_files; @@ -3239,6 +3324,39 @@ innobase_change_buffering_inited_ok: innobase_commit_concurrency_init_default(); +#ifdef HAVE_POSIX_FALLOCATE + srv_use_posix_fallocate = (ibool) innobase_use_fallocate; +#endif + srv_use_atomic_writes = (ibool) innobase_use_atomic_writes; + + if (innobase_use_atomic_writes) { + fprintf(stderr, "InnoDB: using atomic writes.\n"); + + /* Force doublewrite buffer off, atomic writes replace it. */ + if (srv_use_doublewrite_buf) { + fprintf(stderr, "InnoDB: Switching off doublewrite buffer " + "because of atomic writes.\n"); + innobase_use_doublewrite = srv_use_doublewrite_buf = FALSE; + } + + /* Force O_DIRECT on Unixes (on Windows writes are always unbuffered)*/ +#ifndef _WIN32 + if(!innobase_file_flush_method || + !strstr(innobase_file_flush_method, "O_DIRECT")) { + innobase_file_flush_method = + srv_file_flush_method_str = (char*)"O_DIRECT"; + fprintf(stderr, "InnoDB: using O_DIRECT due to atomic writes.\n"); + } +#endif +#ifdef HAVE_POSIX_FALLOCATE + /* Due to a bug in directFS, using atomics needs + * posix_fallocate to extend the file + * pwrite() past end of the file won't work + */ + srv_use_posix_fallocate = TRUE; +#endif + } + #ifdef HAVE_PSI_INTERFACE /* Register keys with MySQL performance schema */ int count; @@ -3297,6 +3415,9 @@ innobase_change_buffering_inited_ok: mysql_mutex_init(commit_cond_mutex_key, &commit_cond_m, MY_MUTEX_INIT_FAST); mysql_cond_init(commit_cond_key, &commit_cond, NULL); + mysql_mutex_init(pending_checkpoint_mutex_key, + &pending_checkpoint_mutex, + MY_MUTEX_INIT_FAST); innodb_inited= 1; #ifdef MYSQL_DYNAMIC_PLUGIN if (innobase_hton != p) { @@ -3347,6 +3468,14 @@ innobase_end( if (innodb_inited) { + THD *thd= current_thd; + if (thd) { // may be UNINSTALL PLUGIN statement + trx_t* trx = thd_to_trx(thd); + if (trx) { + trx_free_for_mysql(trx); + } + } + srv_fast_shutdown = (ulint) innobase_fast_shutdown; innodb_inited = 0; @@ -3360,6 +3489,7 @@ innobase_end( mysql_mutex_destroy(&innobase_share_mutex); mysql_mutex_destroy(&commit_cond_m); mysql_cond_destroy(&commit_cond); + mysql_mutex_destroy(&pending_checkpoint_mutex); } DBUG_RETURN(err); @@ -3461,6 +3591,108 @@ innobase_start_trx_and_assign_read_view( DBUG_RETURN(0); } +static +void +innobase_commit_ordered_2( +/*============*/ + trx_t* trx, /*!< in: Innodb transaction */ + THD* thd) /*!< in: MySQL thread handle */ +{ + DBUG_ENTER("innobase_commit_ordered_2"); + + /* We need current binlog position for mysqlbackup to work. + Note, the position is current because commit_ordered is guaranteed + to be called in same sequenece as writing to binlog. */ + +retry: + if (innobase_commit_concurrency > 0) { + mysql_mutex_lock(&commit_cond_m); + commit_threads++; + + if (commit_threads > innobase_commit_concurrency) { + commit_threads--; + mysql_cond_wait(&commit_cond, + &commit_cond_m); + mysql_mutex_unlock(&commit_cond_m); + goto retry; + } + else { + mysql_mutex_unlock(&commit_cond_m); + } + } + + unsigned long long pos; + thd_binlog_pos(thd, &trx->mysql_log_file_name, &pos); + trx->mysql_log_offset= static_cast<ib_int64_t>(pos); + /* Don't do write + flush right now. For group commit + to work we want to do the flush in the innobase_commit() + method, which runs without holding any locks. */ + trx->flush_log_later = TRUE; + innobase_commit_low(trx); + trx->flush_log_later = FALSE; + + if (innobase_commit_concurrency > 0) { + mysql_mutex_lock(&commit_cond_m); + commit_threads--; + mysql_cond_signal(&commit_cond); + mysql_mutex_unlock(&commit_cond_m); + } + + DBUG_VOID_RETURN; +} + +/*****************************************************************//** +Perform the first, fast part of InnoDB commit. + +Doing it in this call ensures that we get the same commit order here +as in binlog and any other participating transactional storage engines. + +Note that we want to do as little as really needed here, as we run +under a global mutex. The expensive fsync() is done later, in +innobase_commit(), without a lock so group commit can take place. + +Note also that this method can be called from a different thread than +the one handling the rest of the transaction. */ +static +void +innobase_commit_ordered( +/*============*/ + handlerton *hton, /*!< in: Innodb handlerton */ + THD* thd, /*!< in: MySQL thread handle of the user for whom + the transaction should be committed */ + bool all) /*!< in: TRUE - commit transaction + FALSE - the current SQL statement ended */ +{ + trx_t* trx; + DBUG_ENTER("innobase_commit_ordered"); + DBUG_ASSERT(hton == innodb_hton_ptr); + + trx = check_trx_exists(thd); + + /* Since we will reserve the kernel mutex, we must not be holding the + search system latch, or we will disobey the latching order. But we + already released it in innobase_xa_prepare() (if not before), so just + have an assert here.*/ + ut_ad(!trx->has_search_latch); + + if (!trx_is_registered_for_2pc(trx) && trx_is_started(trx)) { + /* We cannot throw error here; instead we will catch this error + again in innobase_commit() and report it from there. */ + DBUG_VOID_RETURN; + } + + /* commit_ordered is only called when committing the whole transaction + (or an SQL statement when autocommit is on). */ + DBUG_ASSERT(all || + (!thd_test_options(thd, OPTION_NOT_AUTOCOMMIT | OPTION_BEGIN))); + + innobase_commit_ordered_2(trx, thd); + + trx_set_active_commit_ordered(trx); + + DBUG_VOID_RETURN; +} + /*****************************************************************//** Commits a transaction in an InnoDB database or marks an SQL statement ended. @@ -3488,7 +3720,7 @@ innobase_commit( /* Since we will reserve the trx_sys->mutex, we have to release the search system latch first to obey the latching order. */ - if (trx->has_search_latch) { + if (trx->has_search_latch && !trx_is_active_commit_ordered(trx)) { trx_search_latch_release_if_reserved(trx); } @@ -3506,59 +3738,23 @@ innobase_commit( if (commit_trx || (!thd_test_options(thd, OPTION_NOT_AUTOCOMMIT | OPTION_BEGIN))) { - /* We were instructed to commit the whole transaction, or - this is an SQL statement end and autocommit is on */ - - /* We need current binlog position for mysqlbackup to work. */ -retry: - if (innobase_commit_concurrency > 0) { - mysql_mutex_lock(&commit_cond_m); - commit_threads++; - - if (commit_threads > innobase_commit_concurrency) { - commit_threads--; - mysql_cond_wait(&commit_cond, - &commit_cond_m); - mysql_mutex_unlock(&commit_cond_m); - goto retry; - } - else { - mysql_mutex_unlock(&commit_cond_m); - } + /* Run the fast part of commit if we did not already. */ + if (!trx_is_active_commit_ordered(trx)) { + innobase_commit_ordered_2(trx, thd); } - /* The following call read the binary log position of - the transaction being committed. - - Binary logging of other engines is not relevant to - InnoDB as all InnoDB requires is that committing - InnoDB transactions appear in the same order in the - MySQL binary log as they appear in InnoDB logs, which - is guaranteed by the server. - - If the binary log is not enabled, or the transaction - is not written to the binary log, the file name will - be a NULL pointer. */ - unsigned long long pos; - thd_binlog_pos(thd, &trx->mysql_log_file_name, &pos); - trx->mysql_log_offset= static_cast<ib_int64_t>(pos); - /* Don't do write + flush right now. For group commit - to work we want to do the flush later. */ - trx->flush_log_later = TRUE; - innobase_commit_low(trx); - trx->flush_log_later = FALSE; - - if (innobase_commit_concurrency > 0) { - mysql_mutex_lock(&commit_cond_m); - commit_threads--; - mysql_cond_signal(&commit_cond); - mysql_mutex_unlock(&commit_cond_m); - } + /* We were instructed to commit the whole transaction, or + this is an SQL statement end and autocommit is on */ - trx_deregister_from_2pc(trx); + /* At this point commit order is fixed and transaction is + visible to others. So we can wakeup other commits waiting for + this one, to allow then to group commit with us. */ + thd_wakeup_subsequent_commits(thd, 0); - /* Now do a write + flush of logs. */ + /* We did the first part already in innobase_commit_ordered(), + Now finish by doing a write + flush of logs. */ trx_commit_complete_for_mysql(trx); + trx_deregister_from_2pc(trx); } else { /* We just mark the SQL statement ended and do not do a transaction commit */ @@ -3675,6 +3871,147 @@ innobase_rollback_trx( DBUG_RETURN(convert_error_code_to_mysql(error, 0, NULL)); } + +struct pending_checkpoint { + struct pending_checkpoint *next; + handlerton *hton; + void *cookie; + ib_uint64_t lsn; +}; +static struct pending_checkpoint *pending_checkpoint_list; +static struct pending_checkpoint *pending_checkpoint_list_end; + +/*****************************************************************//** +Handle a commit checkpoint request from server layer. +We put the request in a queue, so that we can notify upper layer about +checkpoint complete when we have flushed the redo log. +If we have already flushed all relevant redo log, we notify immediately.*/ +static +void +innobase_checkpoint_request( + handlerton *hton, + void *cookie) +{ + ib_uint64_t lsn; + ib_uint64_t flush_lsn; + struct pending_checkpoint * entry; + + /* Do the allocation outside of lock to reduce contention. The normal + case is that not everything is flushed, so we will need to enqueue. */ + entry = static_cast<struct pending_checkpoint *> + (my_malloc(sizeof(*entry), MYF(MY_WME))); + if (!entry) { + sql_print_error("Failed to allocate %u bytes." + " Commit checkpoint will be skipped.", + static_cast<unsigned>(sizeof(*entry))); + return; + } + + entry->next = NULL; + entry->hton = hton; + entry->cookie = cookie; + + mysql_mutex_lock(&pending_checkpoint_mutex); + lsn = log_get_lsn(); + flush_lsn = log_get_flush_lsn(); + if (lsn > flush_lsn) { + /* Put the request in queue. + When the log gets flushed past the lsn, we will remove the + entry from the queue and notify the upper layer. */ + entry->lsn = lsn; + if (pending_checkpoint_list_end) { + pending_checkpoint_list_end->next = entry; + /* There is no need to order the entries in the list + by lsn. The upper layer can accept notifications in + any order, and short delays in notifications do not + significantly impact performance. */ + } else { + pending_checkpoint_list = entry; + } + pending_checkpoint_list_end = entry; + entry = NULL; + } + mysql_mutex_unlock(&pending_checkpoint_mutex); + + if (entry) { + /* We are already flushed. Notify the checkpoint immediately. */ + commit_checkpoint_notify_ha(entry->hton, entry->cookie); + my_free(entry); + } +} + +/*****************************************************************//** +Log code calls this whenever log has been written and/or flushed up +to a new position. We use this to notify upper layer of a new commit +checkpoint when necessary.*/ +UNIV_INTERN +void +innobase_mysql_log_notify( +/*===============*/ + ib_uint64_t write_lsn, /*!< in: LSN written to log file */ + ib_uint64_t flush_lsn) /*!< in: LSN flushed to disk */ +{ + struct pending_checkpoint * pending; + struct pending_checkpoint * entry; + struct pending_checkpoint * last_ready; + + /* It is safe to do a quick check for NULL first without lock. + Even if we should race, we will at most skip one checkpoint and + take the next one, which is harmless. */ + if (!pending_checkpoint_list) + return; + + mysql_mutex_lock(&pending_checkpoint_mutex); + pending = pending_checkpoint_list; + if (!pending) + { + mysql_mutex_unlock(&pending_checkpoint_mutex); + return; + } + + last_ready = NULL; + for (entry = pending; entry != NULL; entry = entry -> next) + { + /* Notify checkpoints up until the first entry that has not + been fully flushed to the redo log. Since we do not maintain + the list ordered, in principle there could be more entries + later than were also flushed. But there is no harm in + delaying notifications for those a bit. And in practise, the + list is unlikely to have more than one element anyway, as we + flush the redo log at least once every second. */ + if (entry->lsn > flush_lsn) + break; + last_ready = entry; + } + + if (last_ready) + { + /* We found some pending checkpoints that are now flushed to + disk. So remove them from the list. */ + pending_checkpoint_list = entry; + if (!entry) + pending_checkpoint_list_end = NULL; + } + + mysql_mutex_unlock(&pending_checkpoint_mutex); + + if (!last_ready) + return; + + /* Now that we have released the lock, notify upper layer about all + commit checkpoints that have now completed. */ + for (;;) { + entry = pending; + pending = pending->next; + + commit_checkpoint_notify_ha(entry->hton, entry->cookie); + + my_free(entry); + if (entry == last_ready) + break; + } +} + /*****************************************************************//** Rolls back a transaction to a savepoint. @return 0 if success, HA_ERR_NO_SAVEPOINT if no savepoint with the @@ -3776,6 +4113,10 @@ innobase_release_savepoint( trx = check_trx_exists(thd); + if (trx->state == TRX_STATE_NOT_STARTED) { + trx_start_if_not_started(trx); + } + /* TODO: use provided savepoint data area to store savepoint data */ longlong2str((ulint) savepoint, name, 36); @@ -3861,7 +4202,7 @@ innobase_close_connection( "but transaction is active"); } - if (trx_is_started(trx) && log_warnings) { + if (trx_is_started(trx) && global_system_variables.log_warnings) { sql_print_warning( "MySQL is closing a connection that has an active " @@ -3896,6 +4237,46 @@ innobase_close_thd( return(innobase_close_connection(innodb_hton_ptr, thd)); } +UNIV_INTERN void lock_cancel_waiting_and_release(lock_t* lock); + +/*****************************************************************//** +Cancel any pending lock request associated with the current THD. */ +static +void +innobase_kill_query( +/*======================*/ + handlerton* hton, /*!< in: innobase handlerton */ + THD* thd, /*!< in: MySQL thread being killed */ + enum thd_kill_levels level) /*!< in: kill level */ +{ + trx_t* trx; + DBUG_ENTER("innobase_kill_query"); + DBUG_ASSERT(hton == innodb_hton_ptr); + + trx = thd_to_trx(thd); + + if (trx) { + THD *cur = current_thd; + THD *owner = trx->current_lock_mutex_owner; + + /* Cancel a pending lock request. */ + if (owner != cur) { + lock_mutex_enter(); + } + trx_mutex_enter(trx); + if (trx->lock.wait_lock) { + lock_cancel_waiting_and_release(trx->lock.wait_lock); + } + trx_mutex_exit(trx); + if (owner != cur) { + lock_mutex_exit(); + } + } + + DBUG_VOID_RETURN; +} + + /*************************************************************************//** ** InnoDB database tables *****************************************************************************/ @@ -3949,14 +4330,6 @@ ha_innobase::table_flags() const } /****************************************************************//** -Gives the file extension of an InnoDB single-table tablespace. */ -static const char* ha_innobase_exts[] = { - ".ibd", - ".isl", - NullS -}; - -/****************************************************************//** Returns the table type (storage engine name). @return table type */ UNIV_INTERN @@ -4007,10 +4380,13 @@ ha_innobase::index_flags( uint, bool) const { + ulong extra_flag= 0; + if (table && key == table->s->primary_key) + extra_flag= HA_CLUSTERED_INDEX; return((table_share->key_info[key].algorithm == HA_KEY_ALG_FULLTEXT) ? 0 : (HA_READ_NEXT | HA_READ_PREV | HA_READ_ORDER - | HA_READ_RANGE | HA_KEYREAD_ONLY + | HA_READ_RANGE | HA_KEYREAD_ONLY | extra_flag | HA_DO_INDEX_COND_PUSHDOWN)); } @@ -4408,8 +4784,16 @@ innobase_match_index_columns( if (innodb_idx_fld >= innodb_idx_fld_end) { DBUG_RETURN(FALSE); } + + mtype = innodb_idx_fld->col->mtype; } + // MariaDB-5.5 compatibility + if ((key_part->field->real_type() == MYSQL_TYPE_ENUM || + key_part->field->real_type() == MYSQL_TYPE_SET) && + mtype == DATA_FIXBINARY) + col_type= DATA_FIXBINARY; + if (col_type != mtype) { /* Column Type mismatches */ DBUG_RETURN(FALSE); @@ -4744,7 +5128,7 @@ ha_innobase::open( if (ib_table && ((!DICT_TF2_FLAG_IS_SET(ib_table, DICT_TF2_FTS_HAS_DOC_ID) - && table->s->fields != dict_table_get_n_user_cols(ib_table)) + && table->s->stored_fields != dict_table_get_n_user_cols(ib_table)) || (DICT_TF2_FLAG_IS_SET(ib_table, DICT_TF2_FTS_HAS_DOC_ID) && (table->s->fields != dict_table_get_n_user_cols(ib_table) - 1)))) { @@ -4898,7 +5282,7 @@ table_opened: DBUG_RETURN(HA_ERR_NO_SUCH_TABLE); } - prebuilt = row_create_prebuilt(ib_table, table->s->reclength); + prebuilt = row_create_prebuilt(ib_table, table->s->stored_rec_length); prebuilt->default_rec = table->s->default_values; ut_ad(prebuilt->default_rec); @@ -5592,21 +5976,13 @@ get_innobase_type_from_mysql_type( case MYSQL_TYPE_YEAR: case MYSQL_TYPE_NEWDATE: return(DATA_INT); + case MYSQL_TYPE_TIMESTAMP: case MYSQL_TYPE_TIME: case MYSQL_TYPE_DATETIME: - case MYSQL_TYPE_TIMESTAMP: - switch (field->real_type()) { - case MYSQL_TYPE_TIME: - case MYSQL_TYPE_DATETIME: - case MYSQL_TYPE_TIMESTAMP: - return(DATA_INT); - default: /* Fall through */ - DBUG_ASSERT((ulint)MYSQL_TYPE_DECIMAL < 256); - case MYSQL_TYPE_TIME2: - case MYSQL_TYPE_DATETIME2: - case MYSQL_TYPE_TIMESTAMP2: + if (field->key_type() == HA_KEYTYPE_BINARY) return(DATA_FIXBINARY); - } + else + return(DATA_INT); case MYSQL_TYPE_FLOAT: return(DATA_FLOAT); case MYSQL_TYPE_DOUBLE: @@ -5960,9 +6336,10 @@ build_template_needs_field( primary key columns */ dict_index_t* index, /*!< in: InnoDB index to use */ const TABLE* table, /*!< in: MySQL table object */ - ulint i) /*!< in: field index in InnoDB table */ + ulint i, /*!< in: field index in InnoDB table */ + ulint sql_idx) /*!< in: field index in SQL table */ { - const Field* field = table->field[i]; + const Field* field = table->field[sql_idx]; ut_ad(index_contains == dict_index_contains_col_or_prefix(index, i)); @@ -5979,8 +6356,8 @@ build_template_needs_field( return(field); } - if (bitmap_is_set(table->read_set, static_cast<uint>(i)) - || bitmap_is_set(table->write_set, static_cast<uint>(i))) { + if (bitmap_is_set(table->read_set, static_cast<uint>(sql_idx)) + || bitmap_is_set(table->write_set, static_cast<uint>(sql_idx))) { /* This field is needed in the query */ return(field); @@ -6035,7 +6412,7 @@ build_template_field( mysql_row_templ_t* templ; const dict_col_t* col; - ut_ad(field == table->field[i]); + //ut_ad(field == table->field[i]); ut_ad(clust_index->table == index->table); col = dict_table_get_nth_col(index->table, i); @@ -6107,10 +6484,10 @@ ha_innobase::build_template( { dict_index_t* index; dict_index_t* clust_index; - ulint n_fields; + ulint n_stored_fields; ibool fetch_all_in_key = FALSE; ibool fetch_primary_key_cols = FALSE; - ulint i; + ulint i, sql_idx; if (prebuilt->select_lock_type == LOCK_X) { /* We always retrieve the whole clustered index record if we @@ -6163,11 +6540,11 @@ ha_innobase::build_template( /* Below we check column by column if we need to access the clustered index. */ - n_fields = (ulint) table->s->fields; /* number of columns */ + n_stored_fields= (ulint)table->s->stored_fields; /* number of stored columns */ if (!prebuilt->mysql_template) { prebuilt->mysql_template = (mysql_row_templ_t*) - mem_alloc(n_fields * sizeof(mysql_row_templ_t)); + mem_alloc(n_stored_fields * sizeof(mysql_row_templ_t)); } prebuilt->template_type = whole_row @@ -6185,7 +6562,12 @@ ha_innobase::build_template( if (active_index != MAX_KEY && active_index == pushed_idx_cond_keyno) { /* Push down an index condition or an end_range check. */ - for (i = 0; i < n_fields; i++) { + for (i = 0, sql_idx = 0; i < n_stored_fields; i++, sql_idx++) { + + while (!table->field[sql_idx]->stored_in_db) { + sql_idx++; + } + const ibool index_contains = dict_index_contains_col_or_prefix(index, i); @@ -6210,14 +6592,14 @@ ha_innobase::build_template( mysql_row_templ_t* templ; if (whole_row) { - field = table->field[i]; + field = table->field[sql_idx]; } else { field = build_template_needs_field( index_contains, prebuilt->read_just_key, fetch_all_in_key, fetch_primary_key_cols, - index, table, i); + index, table, i, sql_idx); if (!field) { continue; } @@ -6298,7 +6680,12 @@ ha_innobase::build_template( /* Include the fields that are not needed in index condition pushdown. */ - for (i = 0; i < n_fields; i++) { + for (i = 0, sql_idx = 0; i < n_stored_fields; i++, sql_idx++) { + + while (!table->field[sql_idx]->stored_in_db) { + sql_idx++; + } + const ibool index_contains = dict_index_contains_col_or_prefix(index, i); @@ -6308,14 +6695,14 @@ ha_innobase::build_template( const Field* field; if (whole_row) { - field = table->field[i]; + field = table->field[sql_idx]; } else { field = build_template_needs_field( index_contains, prebuilt->read_just_key, fetch_all_in_key, fetch_primary_key_cols, - index, table, i); + index, table, i, sql_idx); if (!field) { continue; } @@ -6332,11 +6719,15 @@ ha_innobase::build_template( /* No index condition pushdown */ prebuilt->idx_cond = NULL; - for (i = 0; i < n_fields; i++) { + for (i = 0, sql_idx = 0; i < n_stored_fields; i++, sql_idx++) { const Field* field; + while (!table->field[sql_idx]->stored_in_db) { + sql_idx++; + } + if (whole_row) { - field = table->field[i]; + field = table->field[sql_idx]; } else { field = build_template_needs_field( dict_index_contains_col_or_prefix( @@ -6344,7 +6735,7 @@ ha_innobase::build_template( prebuilt->read_just_key, fetch_all_in_key, fetch_primary_key_cols, - index, table, i); + index, table, i, sql_idx); if (!field) { continue; } @@ -6391,12 +6782,15 @@ ha_innobase::innobase_lock_autoinc(void) break; case AUTOINC_NEW_STYLE_LOCKING: - /* For simple (single/multi) row INSERTs, we fallback to the - old style only if another transaction has already acquired - the AUTOINC lock on behalf of a LOAD FILE or INSERT ... SELECT - etc. type of statement. */ + /* For simple (single/multi) row INSERTs/REPLACEs and RBR + events, we fallback to the old style only if another + transaction has already acquired the AUTOINC lock on + behalf of a LOAD FILE or INSERT ... SELECT etc. type of + statement. */ if (thd_sql_command(user_thd) == SQLCOM_INSERT - || thd_sql_command(user_thd) == SQLCOM_REPLACE) { + || thd_sql_command(user_thd) == SQLCOM_REPLACE + || thd_sql_command(user_thd) == SQLCOM_END // RBR event + ) { dict_table_t* ib_table = prebuilt->table; /* Acquire the AUTOINC mutex. */ @@ -6405,9 +6799,11 @@ ha_innobase::innobase_lock_autoinc(void) /* We need to check that another transaction isn't already holding the AUTOINC lock on the table. */ if (ib_table->n_waiting_or_granted_auto_inc_locks) { - /* Release the mutex to avoid deadlocks. */ + /* Release the mutex to avoid deadlocks and + fall back to old style locking. */ dict_table_autoinc_unlock(ib_table); } else { + /* Do not fall back to old style locking. */ break; } } @@ -6778,7 +7174,7 @@ calc_row_difference( ulint n_changed = 0; dfield_t dfield; dict_index_t* clust_index; - uint i; + uint sql_idx, innodb_idx= 0; ibool changes_fts_column = FALSE; ibool changes_fts_doc_col = FALSE; trx_t* trx = thd_to_trx(thd); @@ -6792,8 +7188,10 @@ calc_row_difference( /* We use upd_buff to convert changed fields */ buf = (byte*) upd_buff; - for (i = 0; i < n_fields; i++) { - field = table->field[i]; + for (sql_idx = 0; sql_idx < n_fields; sql_idx++) { + field = table->field[sql_idx]; + if (!field->stored_in_db) + continue; o_ptr = (const byte*) old_row + get_field_offset(table, field); n_ptr = (const byte*) new_row + get_field_offset(table, field); @@ -6811,7 +7209,7 @@ calc_row_difference( field_mysql_type = field->type(); - col_type = prebuilt->table->cols[i].mtype; + col_type = prebuilt->table->cols[innodb_idx].mtype; switch (col_type) { @@ -6878,7 +7276,8 @@ calc_row_difference( from the MySQL column format to the InnoDB format */ if (n_len != UNIV_SQL_NULL) { - dict_col_copy_type(prebuilt->table->cols + i, + dict_col_copy_type(prebuilt->table->cols + + innodb_idx, dfield_get_type(&dfield)); buf = row_mysql_store_col_in_innobase_format( @@ -6896,7 +7295,7 @@ calc_row_difference( ufield->exp = NULL; ufield->orig_len = 0; ufield->field_no = dict_col_get_clust_pos( - &prebuilt->table->cols[i], clust_index); + &prebuilt->table->cols[innodb_idx], clust_index); n_changed++; /* If an FTS indexed column was changed by this @@ -6930,6 +7329,8 @@ calc_row_difference( } } } + if (field->stored_in_db) + innodb_idx++; } /* If the update changes a column with an FTS index on it, we @@ -7049,13 +7450,14 @@ ha_innobase::update_row( if (upd_buf == NULL) { ut_ad(upd_buf_size == 0); - /* Create a buffer for packing the fields of a record. Why - table->reclength did not work here? Obviously, because char - fields when packed actually became 1 byte longer, when we also - stored the string length as the first byte. */ + /* Create a buffer for packing the fields of a record. Why + table->stored_rec_length did not work here? Obviously, + because char fields when packed actually became 1 byte + longer, when we also stored the string length as the first + byte. */ - upd_buf_size = table->s->reclength + table->s->max_key_length - + MAX_REF_PARTS * 3; + upd_buf_size = table->s->stored_rec_length + + table->s->max_key_length + MAX_REF_PARTS * 3; upd_buf = (uchar*) my_malloc(upd_buf_size, MYF(MY_WME)); if (upd_buf == NULL) { upd_buf_size = 0; @@ -7525,7 +7927,13 @@ ha_innobase::index_read( case DB_SUCCESS: error = 0; table->status = 0; - srv_stats.n_rows_read.add((size_t) prebuilt->trx->id, 1); + if (prebuilt->table->is_system_db) { + srv_stats.n_system_rows_read.add( + (size_t) prebuilt->trx->id, 1); + } else { + srv_stats.n_rows_read.add( + (size_t) prebuilt->trx->id, 1); + } break; case DB_RECORD_NOT_FOUND: error = HA_ERR_KEY_NOT_FOUND; @@ -7605,6 +8013,29 @@ ha_innobase::innobase_get_index( index = innobase_index_lookup(share, keynr); if (index) { + if (!key || ut_strcmp(index->name, key->name) != 0) { + fprintf(stderr, "InnoDB: [Error] Index for key no %u" + " mysql name %s , InnoDB name %s for table %s\n", + keynr, key ? key->name : "NULL", + index->name, + prebuilt->table->name); + + for(ulint i=0; i < table->s->keys; i++) { + index = innobase_index_lookup(share, i); + key = table->key_info + keynr; + + if (index) { + + fprintf(stderr, "InnoDB: [Note] Index for key no %u" + " mysql name %s , InnoDB name %s for table %s\n", + keynr, key ? key->name : "NULL", + index->name, + prebuilt->table->name); + } + } + + } + ut_a(ut_strcmp(index->name, key->name) == 0); } else { /* Can't find index with keynr in the translation @@ -7698,7 +8129,8 @@ ha_innobase::change_active_index( /* The caller seems to ignore this. Thus, we must check this again in row_search_for_mysql(). */ - DBUG_RETURN(HA_ERR_TABLE_DEF_CHANGED); + DBUG_RETURN(convert_error_code_to_mysql(DB_MISSING_HISTORY, + 0, NULL)); } ut_a(prebuilt->search_tuple != 0); @@ -7764,6 +8196,11 @@ ha_innobase::general_fetch( DBUG_ENTER("general_fetch"); + /* If transaction is not startted do not continue, instead return a error code. */ + if(!(prebuilt->sql_stat_start || (prebuilt->trx && prebuilt->trx->state == 1))) { + DBUG_RETURN(HA_ERR_END_OF_FILE); + } + ut_a(prebuilt->trx == thd_to_trx(user_thd)); innobase_srv_conc_enter_innodb(prebuilt->trx); @@ -7777,7 +8214,13 @@ ha_innobase::general_fetch( case DB_SUCCESS: error = 0; table->status = 0; - srv_stats.n_rows_read.add((size_t) prebuilt->trx->id, 1); + if (prebuilt->table->is_system_db) { + srv_stats.n_system_rows_read.add( + (size_t) prebuilt->trx->id, 1); + } else { + srv_stats.n_rows_read.add( + (size_t) prebuilt->trx->id, 1); + } break; case DB_RECORD_NOT_FOUND: error = HA_ERR_END_OF_FILE; @@ -8547,18 +8990,18 @@ create_table_def( if (flags2 & DICT_TF2_FTS) { /* Adjust for the FTS hidden field */ if (!has_doc_id_col) { - table = dict_mem_table_create(table_name, 0, n_cols + 1, + table = dict_mem_table_create(table_name, 0, form->s->stored_fields + 1, flags, flags2); /* Set the hidden doc_id column. */ - table->fts->doc_col = n_cols; + table->fts->doc_col = form->s->stored_fields; } else { - table = dict_mem_table_create(table_name, 0, n_cols, + table = dict_mem_table_create(table_name, 0, form->s->stored_fields, flags, flags2); table->fts->doc_col = doc_id_col; } } else { - table = dict_mem_table_create(table_name, 0, n_cols, + table = dict_mem_table_create(table_name, 0, form->s->stored_fields, flags, flags2); } @@ -8578,6 +9021,8 @@ create_table_def( for (i = 0; i < n_cols; i++) { Field* field = form->field[i]; + if (!field->stored_in_db) + continue; col_type = get_innobase_type_from_mysql_type(&unsigned_type, field); @@ -9201,10 +9646,7 @@ ha_innobase::parse_table_name( } if (ignore) { - push_warning_printf( - thd, Sql_condition::WARN_LEVEL_WARN, - WARN_OPTION_IGNORED, - ER_DEFAULT(WARN_OPTION_IGNORED), + my_error(WARN_OPTION_IGNORED, ME_JUST_WARNING, "DATA DIRECTORY"); } else { strncpy(remote_path, create_info->data_file_name, @@ -9213,10 +9655,7 @@ ha_innobase::parse_table_name( } if (create_info->index_file_name) { - push_warning_printf( - thd, Sql_condition::WARN_LEVEL_WARN, - WARN_OPTION_IGNORED, - ER_DEFAULT(WARN_OPTION_IGNORED), + my_error(WARN_OPTION_IGNORED, ME_JUST_WARNING, "INDEX DIRECTORY"); } @@ -9275,6 +9714,11 @@ innobase_table_flags( DBUG_RETURN(false); } + if (key->flags & HA_USES_PARSER) { + my_error(ER_INNODB_NO_FT_USES_PARSER, MYF(0)); + DBUG_RETURN(false); + } + if (fts_doc_id_index_bad) { goto index_bad; } @@ -9497,10 +9941,10 @@ ha_innobase::create( DBUG_ASSERT(thd != NULL); DBUG_ASSERT(create_info != NULL); - if (form->s->fields > REC_MAX_N_USER_FIELDS) { + if (form->s->stored_fields > REC_MAX_N_USER_FIELDS) { DBUG_RETURN(HA_ERR_TOO_MANY_FIELDS); } else if (high_level_read_only) { - DBUG_RETURN(HA_ERR_INNODB_READ_ONLY); + DBUG_RETURN(HA_ERR_TABLE_READONLY); } /* Create the table definition in InnoDB */ @@ -10403,14 +10847,14 @@ ha_innobase::records_in_range( goto func_exit; } - heap = mem_heap_create(2 * (key->actual_key_parts * sizeof(dfield_t) + heap = mem_heap_create(2 * (key->ext_key_parts * sizeof(dfield_t) + sizeof(dtuple_t))); - range_start = dtuple_create(heap, key->actual_key_parts); - dict_index_copy_types(range_start, index, key->actual_key_parts); + range_start = dtuple_create(heap, key->ext_key_parts); + dict_index_copy_types(range_start, index, key->ext_key_parts); - range_end = dtuple_create(heap, key->actual_key_parts); - dict_index_copy_types(range_end, index, key->actual_key_parts); + range_end = dtuple_create(heap, key->ext_key_parts); + dict_index_copy_types(range_end, index, key->ext_key_parts); row_sel_convert_mysql_key_to_innobase( range_start, @@ -10447,7 +10891,7 @@ ha_innobase::records_in_range( n_rows = btr_estimate_n_rows_in_range(index, range_start, mode1, range_end, - mode2); + mode2, prebuilt->trx); } else { n_rows = HA_POS_ERROR; @@ -10593,11 +11037,6 @@ ha_innobase::read_time( return(handler::read_time(index, ranges, rows)); } - if (rows <= 2) { - - return((double) rows); - } - /* Assume that the read time is proportional to the scan time for all rows + at most one seek per range. */ @@ -10951,7 +11390,6 @@ ha_innobase::info_low( if (avail_space == ULLINT_UNDEFINED) { THD* thd; - char errbuf[MYSYS_STRERROR_SIZE]; thd = ha_thd(); @@ -10964,10 +11402,8 @@ ha_innobase::info_low( "tablespace has been discarded or " "the .ibd file is missing. Setting " "the free space to zero. " - "(errno: %d - %s)", - ib_table->name, errno, - my_strerror(errbuf, sizeof(errbuf), - errno)); + "(errno: %M)", + ib_table->name, errno); stats.delete_length = 0; } else { @@ -10976,7 +11412,7 @@ ha_innobase::info_low( } stats.check_time = 0; - stats.mrr_length_per_rec = ref_length + sizeof(void*); + stats.mrr_length_per_rec= ref_length + 8; // 8 = max(sizeof(void *)); if (stats.records == 0) { stats.mean_rec_length = 0; @@ -11043,6 +11479,7 @@ ha_innobase::info_low( for (i = 0; i < table->s->keys; i++) { ulong j; + rec_per_key = 1; /* We could get index quickly through internal index mapping with the index translation table. The identity of index (match up index name with @@ -11063,7 +11500,7 @@ ha_innobase::info_low( break; } - for (j = 0; j < table->key_info[i].actual_key_parts; j++) { + for (j = 0; j < table->key_info[i].ext_key_parts; j++) { if (table->key_info[i].flags & HA_FULLTEXT) { /* The whole concept has no validity @@ -11089,6 +11526,34 @@ ha_innobase::info_low( break; } + DBUG_EXECUTE_IF("ib_ha_innodb_stat_not_initialized", + index->table->stat_initialized = FALSE;); + + if (!ib_table->stat_initialized || + (index->table != ib_table || + !index->table->stat_initialized)) { + fprintf(stderr, + "InnoDB: Warning: Index %s points to table %s" " and ib_table %s statistics is initialized %d " + " but index table %s initialized %d " + " mysql table is %s. Have you mixed " + "up .frm files from different " + "installations? " + "See " REFMAN + "innodb-troubleshooting.html\n", + index->name, + index->table->name, + ib_table->name, + ib_table->stat_initialized, + index->table->name, + index->table->stat_initialized, + table->s->table_name.str + ); + + /* This is better than + assert on below function */ + dict_stats_init(index->table); + } + rec_per_key = innodb_rec_per_key( index, j, stats.records); @@ -11107,6 +11572,7 @@ ha_innobase::info_low( rec_per_key >= ~(ulong) 0 ? ~(ulong) 0 : (ulong) rec_per_key; } + } if (!(flag & HA_STATUS_NO_LOCK)) { @@ -11407,7 +11873,7 @@ ha_innobase::check( index, prebuilt->trx, "CHECK TABLE-check index"); } - if (thd_killed(user_thd)) { + if (thd_kill_level(user_thd)) { break; } @@ -11464,7 +11930,7 @@ ha_innobase::check( #endif /* defined UNIV_AHI_DEBUG || defined UNIV_DEBUG */ prebuilt->trx->op_info = ""; - if (thd_killed(user_thd)) { + if (thd_kill_level(user_thd)) { my_error(ER_QUERY_INTERRUPTED, MYF(0)); } @@ -11958,7 +12424,7 @@ ha_innobase::reset() } reset_template(); - ds_mrr.reset(); + ds_mrr.dsmrr_close(); /* TODO: This should really be reset in reset_template() but for now it's safer to do it explicitly here. */ @@ -12161,8 +12627,8 @@ ha_innobase::external_lock( if (thd_sql_command(thd) == SQLCOM_CREATE_TABLE) { ib_senderrf(thd, IB_LOG_LEVEL_WARN, - ER_INNODB_READ_ONLY); - DBUG_RETURN(HA_ERR_INNODB_READ_ONLY); + ER_READ_ONLY_MODE); + DBUG_RETURN(HA_ERR_TABLE_READONLY); } else { ib_senderrf(thd, IB_LOG_LEVEL_WARN, ER_READ_ONLY_MODE); @@ -13204,13 +13670,17 @@ ha_innobase::get_auto_increment( /* Not in the middle of a mult-row INSERT. */ } else if (prebuilt->autoinc_last_value == 0) { set_if_bigger(*first_value, autoinc); - /* Check for -ve values. */ - } else if (*first_value > col_max_value && trx->n_autoinc_rows > 0) { - /* Set to next logical value. */ - ut_a(autoinc > trx->n_autoinc_rows); - *first_value = (autoinc - trx->n_autoinc_rows) - 1; } + if (*first_value > col_max_value) + { + /* Out of range number. Let handler::update_auto_increment() + take care of this */ + prebuilt->autoinc_last_value = 0; + dict_table_autoinc_unlock(prebuilt->table); + *nb_reserved_values= 0; + return; + } *nb_reserved_values = trx->n_autoinc_rows; /* With old style AUTOINC locking we only update the table's @@ -13219,17 +13689,14 @@ ha_innobase::get_auto_increment( ulonglong current; ulonglong next_value; - current = *first_value > col_max_value ? autoinc : *first_value; + current = *first_value; - /* If the increment step of the auto increment column - decreases then it is not affecting the immediate - next value in the series. */ - if (prebuilt->autoinc_increment > increment) { + if (prebuilt->autoinc_increment != increment) { current = autoinc - prebuilt->autoinc_increment; current = innobase_next_autoinc( - current, 1, increment, 1, col_max_value); + current, 1, increment, offset, col_max_value); dict_table_autoinc_initialize(prebuilt->table, current); @@ -13634,24 +14101,6 @@ innobase_xa_prepare( trx_mark_sql_stat_end(trx); } - if (thd_sql_command(thd) != SQLCOM_XA_PREPARE - && (prepare_trx - || !thd_test_options( - thd, OPTION_NOT_AUTOCOMMIT | OPTION_BEGIN))) { - - /* For mysqlbackup to work the order of transactions in binlog - and InnoDB must be the same. Consider the situation - - thread1> prepare; write to binlog; ... - <context switch> - thread2> prepare; write to binlog; commit - thread1> ... commit - - The server guarantees that writes to the binary log - and commits are in the same order, so we do not have - to handle this case. */ - } - return(error); } @@ -13839,14 +14288,17 @@ innodb_io_capacity_max_update( { ulong in_val = *static_cast<const ulong*>(save); if (in_val < srv_io_capacity) { - in_val = srv_io_capacity; push_warning_printf(thd, Sql_condition::WARN_LEVEL_WARN, ER_WRONG_ARGUMENTS, - "innodb_io_capacity_max cannot be" - " set lower than innodb_io_capacity."); + "Setting innodb_io_capacity_max %lu" + " lower than innodb_io_capacity %lu.", + in_val, srv_io_capacity); + + srv_io_capacity = in_val; + push_warning_printf(thd, Sql_condition::WARN_LEVEL_WARN, ER_WRONG_ARGUMENTS, - "Setting innodb_io_capacity_max to %lu", + "Setting innodb_io_capacity to %lu", srv_io_capacity); } @@ -13869,15 +14321,19 @@ innodb_io_capacity_update( from check function */ { ulong in_val = *static_cast<const ulong*>(save); + if (in_val > srv_max_io_capacity) { - in_val = srv_max_io_capacity; push_warning_printf(thd, Sql_condition::WARN_LEVEL_WARN, ER_WRONG_ARGUMENTS, - "innodb_io_capacity cannot be set" - " higher than innodb_io_capacity_max."); + "Setting innodb_io_capacity to %lu" + " higher than innodb_io_capacity_max %lu", + in_val, srv_max_io_capacity); + + srv_max_io_capacity = in_val * 2; + push_warning_printf(thd, Sql_condition::WARN_LEVEL_WARN, ER_WRONG_ARGUMENTS, - "Setting innodb_io_capacity to %lu", + "Setting innodb_max_io_capacity to %lu", srv_max_io_capacity); } @@ -13899,7 +14355,7 @@ innodb_max_dirty_pages_pct_update( const void* save) /*!< in: immediate result from check function */ { - ulong in_val = *static_cast<const ulong*>(save); + double in_val = *static_cast<const double*>(save); if (in_val < srv_max_dirty_pages_pct_lwm) { push_warning_printf(thd, Sql_condition::WARN_LEVEL_WARN, ER_WRONG_ARGUMENTS, @@ -13909,7 +14365,7 @@ innodb_max_dirty_pages_pct_update( push_warning_printf(thd, Sql_condition::WARN_LEVEL_WARN, ER_WRONG_ARGUMENTS, "Lowering" - " innodb_max_dirty_page_pct_lwm to %lu", + " innodb_max_dirty_page_pct_lwm to %lf", in_val); srv_max_dirty_pages_pct_lwm = in_val; @@ -13933,7 +14389,7 @@ innodb_max_dirty_pages_pct_lwm_update( const void* save) /*!< in: immediate result from check function */ { - ulong in_val = *static_cast<const ulong*>(save); + double in_val = *static_cast<const double*>(save); if (in_val > srv_max_buf_pool_modified_pct) { in_val = srv_max_buf_pool_modified_pct; push_warning_printf(thd, Sql_condition::WARN_LEVEL_WARN, @@ -13944,7 +14400,7 @@ innodb_max_dirty_pages_pct_lwm_update( push_warning_printf(thd, Sql_condition::WARN_LEVEL_WARN, ER_WRONG_ARGUMENTS, "Setting innodb_max_dirty_page_pct_lwm" - " to %lu", + " to %lf", in_val); } @@ -15649,9 +16105,8 @@ innodb_status_output_update( const void* save __attribute__((unused))) { *static_cast<my_bool*>(var_ptr) = *static_cast<const my_bool*>(save); - /* The lock timeout monitor thread also takes care of this - output. */ - os_event_set(lock_sys->timeout_event); + /* Wakeup server monitor thread. */ + os_event_set(srv_monitor_event); } static SHOW_VAR innodb_status_variables_export[]= { @@ -15707,6 +16162,20 @@ static MYSQL_SYSVAR_BOOL(doublewrite, innobase_use_doublewrite, "Disable with --skip-innodb-doublewrite.", NULL, NULL, TRUE); +static MYSQL_SYSVAR_BOOL(use_atomic_writes, innobase_use_atomic_writes, + PLUGIN_VAR_NOCMDARG | PLUGIN_VAR_READONLY, + "Prevent partial page writes, via atomic writes." + "The option is used to prevent partial writes in case of a crash/poweroff, " + "as faster alternative to doublewrite buffer." + "Currently this option works only " + "on Linux only with FusionIO device, and directFS filesystem.", + NULL, NULL, FALSE); + +static MYSQL_SYSVAR_BOOL(use_fallocate, innobase_use_fallocate, + PLUGIN_VAR_NOCMDARG | PLUGIN_VAR_READONLY, + "Preallocate files fast, using operating system functionality. On POSIX systems, posix_fallocate system call is used.", + NULL, NULL, FALSE); + static MYSQL_SYSVAR_ULONG(io_capacity, srv_io_capacity, PLUGIN_VAR_RQCMDARG, "Number of IOPs the server can do. Tunes the background IO rate", @@ -15817,10 +16286,17 @@ static MYSQL_SYSVAR_UINT(flush_log_at_timeout, srv_flush_log_at_timeout, static MYSQL_SYSVAR_ULONG(flush_log_at_trx_commit, srv_flush_log_at_trx_commit, PLUGIN_VAR_OPCMDARG, - "Set to 0 (write and flush once per second)," - " 1 (write and flush at each commit)" - " or 2 (write at commit, flush once per second).", - NULL, NULL, 1, 0, 2, 0); + "Controls the durability/speed trade-off for commits." + " Set to 0 (write and flush redo log to disk only once per second)," + " 1 (flush to disk at each commit)," + " 2 (write to log at commit but flush to disk only once per second)" + " or 3 (flush to disk at prepare and at commit, slower and usually redundant)." + " 1 and 3 guarantees that after a crash, committed transactions will" + " not be lost and will be consistent with the binlog and other transactional" + " engines. 2 can get inconsistent and lose transactions if there is a" + " power failure or kernel crash but not if mysqld crashes. 0 has no" + " guarantees in case of crash. 0 and 2 can be faster than 1 or 3.", + NULL, NULL, 1, 0, 3, 0); static MYSQL_SYSVAR_STR(flush_method, innobase_file_flush_method, PLUGIN_VAR_RQCMDARG | PLUGIN_VAR_READONLY, @@ -15857,22 +16333,22 @@ static MYSQL_SYSVAR_STR(log_group_home_dir, srv_log_group_home_dir, PLUGIN_VAR_RQCMDARG | PLUGIN_VAR_READONLY, "Path to InnoDB log files.", NULL, NULL, NULL); -static MYSQL_SYSVAR_ULONG(max_dirty_pages_pct, srv_max_buf_pool_modified_pct, +static MYSQL_SYSVAR_DOUBLE(max_dirty_pages_pct, srv_max_buf_pool_modified_pct, PLUGIN_VAR_RQCMDARG, "Percentage of dirty pages allowed in bufferpool.", - NULL, innodb_max_dirty_pages_pct_update, 75, 0, 99, 0); + NULL, innodb_max_dirty_pages_pct_update, 75.0, 0.001, 99.999, 0); -static MYSQL_SYSVAR_ULONG(max_dirty_pages_pct_lwm, +static MYSQL_SYSVAR_DOUBLE(max_dirty_pages_pct_lwm, srv_max_dirty_pages_pct_lwm, PLUGIN_VAR_RQCMDARG, "Percentage of dirty pages at which flushing kicks in.", - NULL, innodb_max_dirty_pages_pct_lwm_update, 0, 0, 99, 0); + NULL, innodb_max_dirty_pages_pct_lwm_update, 0.001, 0.000, 99.999, 0); -static MYSQL_SYSVAR_ULONG(adaptive_flushing_lwm, +static MYSQL_SYSVAR_DOUBLE(adaptive_flushing_lwm, srv_adaptive_flushing_lwm, PLUGIN_VAR_RQCMDARG, "Percentage of log capacity below which no adaptive flushing happens.", - NULL, NULL, 10, 0, 70, 0); + NULL, NULL, 10.0, 0.0, 70.0, 0); static MYSQL_SYSVAR_BOOL(adaptive_flushing, srv_adaptive_flushing, PLUGIN_VAR_NOCMDARG, @@ -15947,6 +16423,16 @@ static MYSQL_SYSVAR_ULONGLONG(stats_persistent_sample_pages, "statistics (by ANALYZE, default 20)", NULL, NULL, 20, 1, ~0ULL, 0); +static MYSQL_SYSVAR_ULONGLONG(stats_modified_counter, srv_stats_modified_counter, + PLUGIN_VAR_RQCMDARG, + "The number of rows modified before we calculate new statistics (default 0 = current limits)", + NULL, NULL, 0, 0, ~0ULL, 0); + +static MYSQL_SYSVAR_BOOL(stats_traditional, srv_stats_sample_traditional, + PLUGIN_VAR_RQCMDARG, + "Enable traditional statistic calculation based on number of configured pages (default true)", + NULL, NULL, TRUE); + static MYSQL_SYSVAR_BOOL(adaptive_hash_index, btr_search_enabled, PLUGIN_VAR_OPCMDARG, "Enable InnoDB adaptive hash index (enabled by default). " @@ -16455,7 +16941,7 @@ static MYSQL_SYSVAR_BOOL(cmp_per_index_enabled, srv_cmp_per_index_enabled, #ifdef UNIV_DEBUG static MYSQL_SYSVAR_UINT(trx_rseg_n_slots_debug, trx_rseg_n_slots_debug, - PLUGIN_VAR_RQCMDARG, + PLUGIN_VAR_RQCMDARG | PLUGIN_VAR_NOCMDOPT, "Debug flags for InnoDB to limit TRX_RSEG_N_SLOTS for trx_rsegf_undo_find_free()", NULL, NULL, 0, 0, 1024, 0); @@ -16465,7 +16951,7 @@ static MYSQL_SYSVAR_UINT(limit_optimistic_insert_debug, NULL, NULL, 0, 0, UINT_MAX32, 0); static MYSQL_SYSVAR_BOOL(trx_purge_view_update_only_debug, - srv_purge_view_update_only_debug, PLUGIN_VAR_NOCMDARG, + srv_purge_view_update_only_debug, PLUGIN_VAR_NOCMDOPT, "Pause actual purging any delete-marked records, but merely update the purge view. " "It is to create artificially the situation the purge view have been updated " "but the each purges were not done yet.", @@ -16482,6 +16968,11 @@ static MYSQL_SYSVAR_ULONG(saved_page_number_debug, NULL, innodb_save_page_no, 0, 0, UINT_MAX32, 0); #endif /* UNIV_DEBUG */ +static MYSQL_SYSVAR_UINT(simulate_comp_failures, srv_simulate_comp_failures, + PLUGIN_VAR_NOCMDARG, + "Simulate compression failures.", + NULL, NULL, 0, 0, 99, 0); + static struct st_mysql_sys_var* innobase_system_variables[]= { MYSQL_SYSVAR(additional_mem_pool_size), MYSQL_SYSVAR(api_trx_level), @@ -16508,6 +16999,8 @@ static struct st_mysql_sys_var* innobase_system_variables[]= { MYSQL_SYSVAR(data_file_path), MYSQL_SYSVAR(data_home_dir), MYSQL_SYSVAR(doublewrite), + MYSQL_SYSVAR(use_atomic_writes), + MYSQL_SYSVAR(use_fallocate), MYSQL_SYSVAR(api_enable_binlog), MYSQL_SYSVAR(api_enable_mdl), MYSQL_SYSVAR(api_disable_rowlock), @@ -16572,6 +17065,8 @@ static struct st_mysql_sys_var* innobase_system_variables[]= { MYSQL_SYSVAR(stats_persistent), MYSQL_SYSVAR(stats_persistent_sample_pages), MYSQL_SYSVAR(stats_auto_recalc), + MYSQL_SYSVAR(stats_modified_counter), + MYSQL_SYSVAR(stats_traditional), MYSQL_SYSVAR(adaptive_hash_index), MYSQL_SYSVAR(stats_method), MYSQL_SYSVAR(replication_delay), @@ -16640,10 +17135,11 @@ static struct st_mysql_sys_var* innobase_system_variables[]= { MYSQL_SYSVAR(fil_make_page_dirty_debug), MYSQL_SYSVAR(saved_page_number_debug), #endif /* UNIV_DEBUG */ + MYSQL_SYSVAR(simulate_comp_failures), NULL }; -mysql_declare_plugin(innobase) +maria_declare_plugin(innobase) { MYSQL_STORAGE_ENGINE_PLUGIN, &innobase_storage_engine, @@ -16656,8 +17152,8 @@ mysql_declare_plugin(innobase) INNODB_VERSION_SHORT, innodb_status_variables_export,/* status variables */ innobase_system_variables, /* system variables */ - NULL, /* reserved */ - 0, /* flags */ + INNODB_VERSION_STR, /* string version */ + MariaDB_PLUGIN_MATURITY_STABLE /* maturity */ }, i_s_innodb_trx, i_s_innodb_locks, @@ -16688,7 +17184,7 @@ i_s_innodb_sys_foreign_cols, i_s_innodb_sys_tablespaces, i_s_innodb_sys_datafiles -mysql_declare_plugin_end; +maria_declare_plugin_end; /** @brief Initialize the default value of innodb_commit_concurrency. @@ -16853,54 +17349,51 @@ test_innobase_convert_name() * Multi Range Read interface, DS-MRR calls */ -int -ha_innobase::multi_range_read_init( - RANGE_SEQ_IF* seq, - void* seq_init_param, - uint n_ranges, - uint mode, - HANDLER_BUFFER* buf) +int ha_innobase::multi_range_read_init(RANGE_SEQ_IF *seq, void *seq_init_param, + uint n_ranges, uint mode, + HANDLER_BUFFER *buf) { - return(ds_mrr.dsmrr_init(this, seq, seq_init_param, - n_ranges, mode, buf)); + return ds_mrr.dsmrr_init(this, seq, seq_init_param, n_ranges, mode, buf); } -int -ha_innobase::multi_range_read_next( - char** range_info) +int ha_innobase::multi_range_read_next(range_id_t *range_info) { - return(ds_mrr.dsmrr_next(range_info)); + return ds_mrr.dsmrr_next(range_info); } -ha_rows -ha_innobase::multi_range_read_info_const( - uint keyno, - RANGE_SEQ_IF* seq, - void* seq_init_param, - uint n_ranges, - uint* bufsz, - uint* flags, - Cost_estimate* cost) +ha_rows ha_innobase::multi_range_read_info_const(uint keyno, RANGE_SEQ_IF *seq, + void *seq_init_param, + uint n_ranges, uint *bufsz, + uint *flags, + Cost_estimate *cost) { - /* See comments in ha_myisam::multi_range_read_info_const */ - ds_mrr.init(this, table); - return(ds_mrr.dsmrr_info_const(keyno, seq, seq_init_param, - n_ranges, bufsz, flags, cost)); + /* See comments in ha_myisam::multi_range_read_info_const */ + ds_mrr.init(this, table); + + if (prebuilt->select_lock_type != LOCK_NONE) + *flags |= HA_MRR_USE_DEFAULT_IMPL; + + ha_rows res= ds_mrr.dsmrr_info_const(keyno, seq, seq_init_param, n_ranges, + bufsz, flags, cost); + return res; } -ha_rows -ha_innobase::multi_range_read_info( - uint keyno, - uint n_ranges, - uint keys, - uint* bufsz, - uint* flags, - Cost_estimate* cost) +ha_rows ha_innobase::multi_range_read_info(uint keyno, uint n_ranges, + uint keys, uint key_parts, + uint *bufsz, uint *flags, + Cost_estimate *cost) { - ds_mrr.init(this, table); - return(ds_mrr.dsmrr_info(keyno, n_ranges, keys, bufsz, flags, cost)); + ds_mrr.init(this, table); + ha_rows res= ds_mrr.dsmrr_info(keyno, n_ranges, keys, key_parts, bufsz, + flags, cost); + return res; } +int ha_innobase::multi_range_read_explain_info(uint mrr_mode, char *str, + size_t size) +{ + return ds_mrr.dsmrr_explain_info(mrr_mode, str, size); +} /** * Index Condition Pushdown interface implementation @@ -16915,20 +17408,7 @@ innobase_index_cond( /*================*/ void* file) /*!< in/out: pointer to ha_innobase */ { - DBUG_ENTER("innobase_index_cond"); - - ha_innobase* h = reinterpret_cast<class ha_innobase*>(file); - - DBUG_ASSERT(h->pushed_idx_cond); - DBUG_ASSERT(h->pushed_idx_cond_keyno != MAX_KEY); - - if (h->end_range && h->compare_key_icp(h->end_range) > 0) { - - /* caller should return HA_ERR_END_OF_FILE already */ - DBUG_RETURN(ICP_OUT_OF_RANGE); - } - - DBUG_RETURN(h->pushed_idx_cond->val_int() ? ICP_MATCH : ICP_NO_MATCH); + return handler_index_cond_check(file); } /** Attempt to push down an index condition. @@ -16972,7 +17452,6 @@ ib_senderrf( ib_uint32_t code, /*!< MySQL error code */ ...) /*!< Args */ { - char* str; va_list args; const char* format = innobase_get_err_msg(code); @@ -16986,46 +17465,24 @@ ib_senderrf( va_start(args, code); -#ifdef __WIN__ - int size = _vscprintf(format, args) + 1; - str = static_cast<char*>(malloc(size)); - str[size - 1] = 0x0; - vsnprintf(str, size, format, args); -#elif HAVE_VASPRINTF - int ret; - ret = vasprintf(&str, format, args); - ut_a(ret != -1); -#else - /* Use a fixed length string. */ - str = static_cast<char*>(malloc(BUFSIZ)); - my_vsnprintf(str, BUFSIZ, format, args); -#endif /* __WIN__ */ - - Sql_condition::enum_warning_level l; - - l = Sql_condition::WARN_LEVEL_NOTE; + myf l=0; switch(level) { case IB_LOG_LEVEL_INFO: + l = ME_JUST_INFO; break; case IB_LOG_LEVEL_WARN: - l = Sql_condition::WARN_LEVEL_WARN; + l = ME_JUST_WARNING; break; case IB_LOG_LEVEL_ERROR: - /* We can't use push_warning_printf(), it is a hard error. */ - my_printf_error(code, "%s", MYF(0), str); - break; case IB_LOG_LEVEL_FATAL: - l = Sql_condition::WARN_LEVEL_END; + l = 0; break; } - if (level != IB_LOG_LEVEL_ERROR) { - push_warning_printf(thd, l, code, "InnoDB: %s", str); - } + my_printv_error(code, format, MYF(l), args); va_end(args); - free(str); if (level == IB_LOG_LEVEL_FATAL) { ut_error; @@ -17070,9 +17527,11 @@ ib_errf( str[size - 1] = 0x0; vsnprintf(str, size, format, args); #elif HAVE_VASPRINTF - int ret; - ret = vasprintf(&str, format, args); - ut_a(ret != -1); + if (vasprintf(&str, format, args) == -1) { + /* In case of failure use a fixed length string */ + str = static_cast<char*>(malloc(BUFSIZ)); + my_vsnprintf(str, BUFSIZ, format, args); + } #else /* Use a fixed length string. */ str = static_cast<char*>(malloc(BUFSIZ)); @@ -17106,9 +17565,11 @@ ib_logf( str[size - 1] = 0x0; vsnprintf(str, size, format, args); #elif HAVE_VASPRINTF - int ret; - ret = vasprintf(&str, format, args); - ut_a(ret != -1); + if (vasprintf(&str, format, args) == -1) { + /* In case of failure use a fixed length string */ + str = static_cast<char*>(malloc(BUFSIZ)); + my_vsnprintf(str, BUFSIZ, format, args); + } #else /* Use a fixed length string. */ str = static_cast<char*>(malloc(BUFSIZ)); @@ -17152,8 +17613,8 @@ innobase_convert_to_filename_charset( CHARSET_INFO* cs_to = &my_charset_filename; CHARSET_INFO* cs_from = system_charset_info; - return(strconvert( - cs_from, from, cs_to, to, static_cast<uint>(len), &errors)); + return(strconvert( cs_from, from, strlen(from), cs_to, to, + static_cast<uint>(len), &errors)); } /********************************************************************** @@ -17170,12 +17631,13 @@ innobase_convert_to_system_charset( CHARSET_INFO* cs1 = &my_charset_filename; CHARSET_INFO* cs2 = system_charset_info; - return(strconvert( - cs1, from, cs2, to, static_cast<uint>(len), errors)); + return(strconvert(cs1, from, strlen(from), cs2, to, + static_cast<uint>(len), errors)); } /********************************************************************** Issue a warning that the row is too big. */ +UNIV_INTERN void ib_warn_row_too_big(const dict_table_t* table) { @@ -17189,6 +17651,10 @@ ib_warn_row_too_big(const dict_table_t* table) THD* thd = current_thd; + if (thd == NULL) { + return; + } + push_warning_printf( thd, Sql_condition::WARN_LEVEL_WARN, HA_ERR_TO_BIG_ROW, "Row size too large (> %lu). Changing some columns to TEXT" @@ -17198,3 +17664,29 @@ ib_warn_row_too_big(const dict_table_t* table) " ROW_FORMAT=COMPRESSED ": "" , prefix ? DICT_MAX_FIXED_COL_LEN : 0); } + +/********************************************************************//** +Helper function to push warnings from InnoDB internals to SQL-layer. */ +UNIV_INTERN +void +ib_push_warning( + trx_t* trx, /*!< in: trx */ + ulint error, /*!< in: error code to push as warning */ + const char *format,/*!< in: warning message */ + ...) +{ + va_list args; + THD *thd = (THD *)trx->mysql_thd; + char *buf; +#define MAX_BUF_SIZE 4*1024 + + va_start(args, format); + buf = (char *)my_malloc(MAX_BUF_SIZE, MYF(MY_WME)); + vsprintf(buf,format, args); + + push_warning_printf(thd, Sql_condition::WARN_LEVEL_WARN, + convert_error_code_to_mysql((dberr_t)error, 0, thd), + buf); + my_free(buf); + va_end(args); +} diff --git a/storage/innobase/handler/ha_innodb.h b/storage/innobase/handler/ha_innodb.h index f735b6fef2d..5cebc425769 100644 --- a/storage/innobase/handler/ha_innodb.h +++ b/storage/innobase/handler/ha_innodb.h @@ -315,7 +315,7 @@ public: /** Process next multi range read @see DsMrr_impl::dsmrr_next * @param range_info */ - int multi_range_read_next(char** range_info); + int multi_range_read_next(range_id_t *range_info); /** Initialize multi range read and get information. * @see ha_myisam::multi_range_read_info_const * @see DsMrr_impl::dsmrr_info_const @@ -342,9 +342,11 @@ public: * @param cost */ ha_rows multi_range_read_info(uint keyno, uint n_ranges, uint keys, - uint* bufsz, uint* flags, + uint key_parts, uint* bufsz, uint* flags, Cost_estimate* cost); + int multi_range_read_explain_info(uint mrr_mode, char *str, + size_t size); /** Attempt to push down an index condition. * @param[in] keyno MySQL key number * @param[in] idx_cond Index condition to be checked @@ -425,13 +427,6 @@ bool thd_sqlcom_can_generate_row_events(const MYSQL_THD thd); */ enum durability_properties thd_get_durability_property(const MYSQL_THD thd); -/** Get the auto_increment_offset auto_increment_increment. -@param thd Thread object -@param off auto_increment_offset -@param inc auto_increment_increment */ -void thd_get_autoinc(const MYSQL_THD thd, ulong* off, ulong* inc) -__attribute__((nonnull)); - /** Is strict sql_mode set. @param thd Thread object @return True if sql_mode has strict mode (all or trans), false otherwise. @@ -440,6 +435,11 @@ bool thd_is_strict_mode(const MYSQL_THD thd) __attribute__((nonnull)); } /* extern "C" */ +/** Get the file name and position of the MySQL binlog corresponding to the + * current commit. + */ +extern void mysql_bin_log_commit_pos(THD *thd, ulonglong *out_pos, const char **out_file); + struct trx_t; extern const struct _ft_vft ft_vft_result; diff --git a/storage/innobase/handler/handler0alter.cc b/storage/innobase/handler/handler0alter.cc index e48ae04ed6a..f8efc38afff 100644 --- a/storage/innobase/handler/handler0alter.cc +++ b/storage/innobase/handler/handler0alter.cc @@ -21,11 +21,12 @@ this program; if not, write to the Free Software Foundation, Inc., Smart ALTER TABLE *******************************************************/ +#include <my_global.h> #include <unireg.h> #include <mysqld_error.h> #include <log.h> #include <debug_sync.h> -#include <mysql/innodb_priv.h> +#include <innodb_priv.h> #include <sql_alter.h> #include <sql_class.h> #include <sql_table.h> @@ -80,6 +81,7 @@ static const Alter_inplace_info::HA_ALTER_FLAGS INNOBASE_ALTER_DATA /** Operations for altering a table that InnoDB does not care about */ static const Alter_inplace_info::HA_ALTER_FLAGS INNOBASE_INPLACE_IGNORE = Alter_inplace_info::ALTER_COLUMN_DEFAULT + | Alter_inplace_info::ALTER_PARTITIONED | Alter_inplace_info::ALTER_COLUMN_COLUMN_FORMAT | Alter_inplace_info::ALTER_COLUMN_STORAGE_TYPE | Alter_inplace_info::ALTER_RENAME; @@ -127,9 +129,13 @@ my_error_innodb( break; case DB_OUT_OF_FILE_SPACE: my_error(ER_RECORD_FILE_FULL, MYF(0), table); + ut_error; break; case DB_TEMP_FILE_WRITE_FAILURE: - my_error(ER_TEMP_FILE_WRITE_FAILURE, MYF(0)); + my_error(ER_GET_ERRMSG, MYF(0), + DB_TEMP_FILE_WRITE_FAILURE, + ut_strerr(DB_TEMP_FILE_WRITE_FAILURE), + "InnoDB"); break; case DB_TOO_BIG_INDEX_COL: my_error(ER_INDEX_COLUMN_TOO_LONG, MYF(0), @@ -168,7 +174,7 @@ my_error_innodb( ut_error; #endif /* UNIV_DEBUG */ default: - my_error(ER_GET_ERRNO, MYF(0), error); + my_error(ER_GET_ERRNO, MYF(0), error, "InnoDB"); break; } } @@ -243,13 +249,12 @@ ha_innobase::check_if_supported_inplace_alter( DBUG_RETURN(HA_ALTER_INPLACE_NOT_SUPPORTED); } else if (srv_created_new_raw || srv_force_recovery) { - ha_alter_info->unsupported_reason =(srv_force_recovery)? - innobase_get_err_msg(ER_INNODB_FORCED_RECOVERY): + ha_alter_info->unsupported_reason = innobase_get_err_msg(ER_READ_ONLY_MODE); DBUG_RETURN(HA_ALTER_INPLACE_NOT_SUPPORTED); } - if (altered_table->s->fields > REC_MAX_N_USER_FIELDS) { + if (altered_table->s->stored_fields > REC_MAX_N_USER_FIELDS) { /* Deny the inplace ALTER TABLE. MySQL will try to re-create the table and ha_innobase::create() will return an error too. This is how we effectively @@ -341,6 +346,65 @@ ha_innobase::check_if_supported_inplace_alter( } } + /* + InnoDB in different MariaDB versions was generating different mtype + codes for certain types. In some cases the signed/unsigned bit was + generated differently too. + + Online ALTER would change the mtype/unsigned_flag (to what the + current code generates) without changing the underlying data + represenation, and it might result in data corruption. + + Don't do online ALTER if mtype/unsigned_flag are wrong. + */ + for (ulint i = 0, icol= 0; i < table->s->fields; i++) { + const Field* field = table->field[i]; + const dict_col_t* col = dict_table_get_nth_col(prebuilt->table, icol); + ulint unsigned_flag; + if (!field->stored_in_db) + continue; + icol++; + + if (col->mtype != get_innobase_type_from_mysql_type(&unsigned_flag, field)) { + + DBUG_RETURN(HA_ALTER_INPLACE_NOT_SUPPORTED); + } + + if ((col->prtype & DATA_UNSIGNED) != unsigned_flag) { + + DBUG_RETURN(HA_ALTER_INPLACE_NOT_SUPPORTED); + } + } + + /* If we have column that has changed from NULL -> NOT NULL + and column default has changed we need to do additional + check. */ + if ((ha_alter_info->handler_flags + & Alter_inplace_info::ALTER_COLUMN_NOT_NULLABLE) && + (ha_alter_info->handler_flags + & Alter_inplace_info::ALTER_COLUMN_DEFAULT)) { + Alter_info *alter_info = ha_alter_info->alter_info; + List_iterator<Create_field> def_it(alter_info->create_list); + Create_field *def; + while ((def=def_it++)) { + + /* If this is first column definition whose SQL type + is TIMESTAMP and it is defined as NOT NULL and + it has either constant default or function default + we must use "Copy" method. */ + if (is_timestamp_type(def->sql_type)) { + if ((def->flags & NOT_NULL_FLAG) != 0 && // NOT NULL + (def->def != NULL || // constant default ? + def->unireg_check != Field::NONE)) { // function default + ha_alter_info->unsupported_reason = innobase_get_err_msg( + ER_ALTER_OPERATION_NOT_SUPPORTED_REASON_NOT_NULL); + DBUG_RETURN(HA_ALTER_INPLACE_NOT_SUPPORTED); + } + break; + } + } + } + /* We should be able to do the operation in-place. See if we can do it online (LOCK=NONE). */ bool online = true; @@ -358,8 +422,7 @@ ha_innobase::check_if_supported_inplace_alter( key_part++) { const Create_field* new_field; - DBUG_ASSERT(key_part->fieldnr - < altered_table->s->fields); + DBUG_ASSERT(key_part->fieldnr < altered_table->s->fields); cf_it.rewind(); for (uint fieldnr = 0; (new_field = cf_it++); @@ -420,7 +483,7 @@ ha_innobase::check_if_supported_inplace_alter( } DBUG_ASSERT(!prebuilt->table->fts || prebuilt->table->fts->doc_col - <= table->s->fields); + <= table->s->stored_fields); DBUG_ASSERT(!prebuilt->table->fts || prebuilt->table->fts->doc_col < dict_table_get_n_user_cols(prebuilt->table)); @@ -762,7 +825,8 @@ innobase_find_fk_index( if (!(index->type & DICT_FTS) && dict_foreign_qualify_index( table, col_names, columns, n_cols, - index, NULL, true, 0)) { + index, NULL, true, 0, + NULL, NULL, NULL)) { for (ulint i = 0; i < n_drop_index; i++) { if (index == drop_index[i]) { /* Skip to-be-dropped indexes. */ @@ -955,7 +1019,8 @@ innobase_get_foreign_key_info( referenced_table, 0, referenced_column_names, i, index, - TRUE, FALSE); + TRUE, FALSE, + NULL, NULL, NULL); DBUG_EXECUTE_IF( "innodb_test_no_reference_idx", @@ -1057,7 +1122,7 @@ innobase_col_to_mysql( *--ptr = *data++; } - if (!(field->flags & UNSIGNED_FLAG)) { + if (!(col->prtype & DATA_UNSIGNED)) { ((byte*) dest)[len - 1] ^= 0x80; } @@ -1131,18 +1196,22 @@ innobase_rec_to_mysql( const ulint* offsets)/*!< in: rec_get_offsets( rec, index, ...) */ { - uint n_fields = table->s->fields; + uint n_fields = table->s->stored_fields; + uint sql_idx = 0; ut_ad(n_fields == dict_table_get_n_user_cols(index->table) - !!(DICT_TF2_FLAG_IS_SET(index->table, DICT_TF2_FTS_HAS_DOC_ID))); - for (uint i = 0; i < n_fields; i++) { - Field* field = table->field[i]; + for (uint i = 0; i < n_fields; i++, sql_idx++) { + Field* field; ulint ipos; ulint ilen; const uchar* ifield; + while (!((field= table->field[sql_idx])->stored_in_db)) + sql_idx++; + field->reset(); ipos = dict_index_get_nth_col_or_prefix_pos(index, i, TRUE); @@ -1181,16 +1250,20 @@ innobase_fields_to_mysql( const dict_index_t* index, /*!< in: InnoDB index */ const dfield_t* fields) /*!< in: InnoDB index fields */ { - uint n_fields = table->s->fields; + uint n_fields = table->s->stored_fields; + uint sql_idx = 0; ut_ad(n_fields == dict_table_get_n_user_cols(index->table) - !!(DICT_TF2_FLAG_IS_SET(index->table, DICT_TF2_FTS_HAS_DOC_ID))); - for (uint i = 0; i < n_fields; i++) { - Field* field = table->field[i]; + for (uint i = 0; i < n_fields; i++, sql_idx++) { + Field* field; ulint ipos; + while (!((field= table->field[sql_idx])->stored_in_db)) + sql_idx++; + field->reset(); ipos = dict_index_get_nth_col_or_prefix_pos(index, i, TRUE); @@ -1224,17 +1297,21 @@ innobase_row_to_mysql( const dict_table_t* itab, /*!< in: InnoDB table */ const dtuple_t* row) /*!< in: InnoDB row */ { - uint n_fields = table->s->fields; + uint n_fields = table->s->stored_fields; + uint sql_idx = 0; /* The InnoDB row may contain an extra FTS_DOC_ID column at the end. */ ut_ad(row->n_fields == dict_table_get_n_cols(itab)); ut_ad(n_fields == row->n_fields - DATA_N_SYS_COLS - !!(DICT_TF2_FLAG_IS_SET(itab, DICT_TF2_FTS_HAS_DOC_ID))); - for (uint i = 0; i < n_fields; i++) { - Field* field = table->field[i]; + for (uint i = 0; i < n_fields; i++, sql_idx++) { + Field* field; const dfield_t* df = dtuple_get_nth_field(row, i); + while (!((field= table->field[sql_idx])->stored_in_db)) + sql_idx++; + field->reset(); if (dfield_is_ext(df) || dfield_is_null(df)) { @@ -1362,7 +1439,7 @@ name_ok: } } - my_error(ER_WRONG_KEY_COLUMN, MYF(0), + my_error(ER_WRONG_KEY_COLUMN, MYF(0), "InnoDB", field->field_name); return(ER_WRONG_KEY_COLUMN); } @@ -1378,7 +1455,7 @@ name_ok: continue; } - my_error(ER_WRONG_KEY_COLUMN, MYF(0), + my_error(ER_WRONG_KEY_COLUMN, MYF(0), "InnoDB", field->field_name); return(ER_WRONG_KEY_COLUMN); } @@ -1399,8 +1476,9 @@ innobase_create_index_field_def( if a new clustered index is not being created */ const KEY_PART_INFO* key_part, /*!< in: MySQL key definition */ - index_field_t* index_field) /*!< out: index field + index_field_t* index_field, /*!< out: index field definition for key_part */ + const Field** fields) /*!< in: MySQL table fields */ { const Field* field; ibool is_unsigned; @@ -1417,6 +1495,7 @@ innobase_create_index_field_def( ut_a(field); index_field->col_no = key_part->fieldnr; + index_field->col_name = altered_table ? field->field_name : fields[key_part->fieldnr]->field_name; col_type = get_innobase_type_from_mysql_type(&is_unsigned, field); @@ -1451,8 +1530,9 @@ innobase_create_index_def( bool key_clustered, /*!< in: true if this is the new clustered index */ index_def_t* index, /*!< out: index definition */ - mem_heap_t* heap) /*!< in: heap where memory + mem_heap_t* heap, /*!< in: heap where memory is allocated */ + const Field** fields) /*!z in: MySQL table fields */ { const KEY* key = &keys[key_number]; ulint i; @@ -1465,6 +1545,7 @@ innobase_create_index_def( index->fields = static_cast<index_field_t*>( mem_heap_alloc(heap, n_fields * sizeof *index->fields)); + memset(index->fields, 0, n_fields * sizeof *index->fields); index->ind_type = 0; index->key_number = key_number; @@ -1502,7 +1583,7 @@ innobase_create_index_def( for (i = 0; i < n_fields; i++) { innobase_create_index_field_def( - altered_table, &key->key_part[i], &index->fields[i]); + altered_table, &key->key_part[i], &index->fields[i], fields); } DBUG_VOID_RETURN; @@ -1527,12 +1608,15 @@ innobase_fts_check_doc_id_col( { *fts_doc_col_no = ULINT_UNDEFINED; - const uint n_cols = altered_table->s->fields; + const uint n_cols = altered_table->s->stored_fields; + uint sql_idx = 0; uint i; - for (i = 0; i < n_cols; i++) { - const Field* field = altered_table->field[i]; - + for (i = 0; i < n_cols; i++, sql_idx++) { + const Field* field; + while (!((field= altered_table->field[sql_idx])-> + stored_in_db)) + sql_idx++; if (my_strcasecmp(system_charset_info, field->field_name, FTS_DOC_ID_COL_NAME)) { continue; @@ -1830,7 +1914,7 @@ innobase_create_key_defs( /* Create the PRIMARY key index definition */ innobase_create_index_def( altered_table, key_info, primary_key_number, - TRUE, TRUE, indexdef++, heap); + TRUE, TRUE, indexdef++, heap, (const Field **)altered_table->field); created_clustered: n_add = 1; @@ -1842,7 +1926,7 @@ created_clustered: /* Copy the index definitions. */ innobase_create_index_def( altered_table, key_info, i, TRUE, FALSE, - indexdef, heap); + indexdef, heap, (const Field **)altered_table->field); if (indexdef->ind_type & DICT_FTS) { n_fts_add++; @@ -1857,7 +1941,8 @@ created_clustered: && !innobase_fts_check_doc_id_col( NULL, altered_table, &fts_doc_id_col)) { - fts_doc_id_col = altered_table->s->fields; + fts_doc_id_col = + altered_table->s->stored_fields; add_fts_doc_id = true; } @@ -1886,7 +1971,7 @@ created_clustered: for (ulint i = 0; i < n_add; i++) { innobase_create_index_def( altered_table, key_info, add[i], FALSE, FALSE, - indexdef, heap); + indexdef, heap, (const Field **)altered_table->field); if (indexdef->ind_type & DICT_FTS) { n_fts_add++; @@ -1903,6 +1988,7 @@ created_clustered: index->fields = static_cast<index_field_t*>( mem_heap_alloc(heap, sizeof *index->fields)); + memset(index->fields, 0, sizeof *index->fields); index->n_fields = 1; index->fields->col_no = fts_doc_id_col; index->fields->prefix_len = 0; @@ -1912,7 +1998,7 @@ created_clustered: index->name = mem_heap_strdup( heap, FTS_DOC_ID_INDEX_NAME); ut_ad(!add_fts_doc_id - || fts_doc_id_col == altered_table->s->fields); + || fts_doc_id_col == altered_table->s->stored_fields); } else { char* index_name; index->name = index_name = static_cast<char*>( @@ -2192,7 +2278,7 @@ innobase_check_foreigns_low( /* Check if any FOREIGN KEY constraints are defined on this column. */ - for (dict_foreign_set::iterator it = user_table->foreign_set.begin(); + for (dict_foreign_set::const_iterator it = user_table->foreign_set.begin(); it != user_table->foreign_set.end(); ++it) { @@ -2229,7 +2315,7 @@ innobase_check_foreigns_low( /* Check if any FOREIGN KEY constraints in other tables are referring to the column that is being dropped. */ - for (dict_foreign_set::iterator it + for (dict_foreign_set::const_iterator it = user_table->referenced_set.begin(); it != user_table->referenced_set.end(); ++it) { @@ -2367,13 +2453,14 @@ innobase_build_col_map( dtuple_t* add_cols, mem_heap_t* heap) { + uint old_i, old_innobase_i; DBUG_ENTER("innobase_build_col_map"); DBUG_ASSERT(altered_table != table); DBUG_ASSERT(new_table != old_table); DBUG_ASSERT(dict_table_get_n_cols(new_table) - >= altered_table->s->fields + DATA_N_SYS_COLS); + >= altered_table->s->stored_fields + DATA_N_SYS_COLS); DBUG_ASSERT(dict_table_get_n_cols(old_table) - >= table->s->fields + DATA_N_SYS_COLS); + >= table->s->stored_fields + DATA_N_SYS_COLS); DBUG_ASSERT(!!add_cols == !!(ha_alter_info->handler_flags & Alter_inplace_info::ADD_COLUMN)); DBUG_ASSERT(!add_cols || dtuple_get_n_fields(add_cols) @@ -2384,34 +2471,46 @@ innobase_build_col_map( List_iterator_fast<Create_field> cf_it( ha_alter_info->alter_info->create_list); - uint i = 0; + uint i = 0, sql_idx = 0; /* Any dropped columns will map to ULINT_UNDEFINED. */ - for (uint old_i = 0; old_i + DATA_N_SYS_COLS < old_table->n_cols; - old_i++) { - col_map[old_i] = ULINT_UNDEFINED; + for (old_innobase_i = 0; + old_innobase_i + DATA_N_SYS_COLS < old_table->n_cols; + old_innobase_i++) { + col_map[old_innobase_i] = ULINT_UNDEFINED; } while (const Create_field* new_field = cf_it++) { - for (uint old_i = 0; table->field[old_i]; old_i++) { + if (!new_field->stored_in_db) + { + sql_idx++; + continue; + } + for (old_i = 0, old_innobase_i= 0; + table->field[old_i]; + old_i++) { const Field* field = table->field[old_i]; + if (!table->field[old_i]->stored_in_db) + continue; if (new_field->field == field) { - col_map[old_i] = i; + col_map[old_innobase_i] = i; goto found_col; } + old_innobase_i++; } innobase_build_col_map_add( heap, dtuple_get_nth_field(add_cols, i), - altered_table->field[i], + altered_table->field[sql_idx], dict_table_is_comp(new_table)); found_col: i++; + sql_idx++; } - DBUG_ASSERT(i == altered_table->s->fields); + DBUG_ASSERT(i == altered_table->s->stored_fields); - i = table->s->fields; + i = table->s->stored_fields; /* Add the InnoDB hidden FTS_DOC_ID column, if any. */ if (i + DATA_N_SYS_COLS < old_table->n_cols) { @@ -2421,17 +2520,17 @@ found_col: DICT_TF2_FTS_HAS_DOC_ID)); DBUG_ASSERT(i + DATA_N_SYS_COLS + 1 == old_table->n_cols); DBUG_ASSERT(!strcmp(dict_table_get_col_name( - old_table, table->s->fields), + old_table, table->s->stored_fields), FTS_DOC_ID_COL_NAME)); - if (altered_table->s->fields + DATA_N_SYS_COLS + if (altered_table->s->stored_fields + DATA_N_SYS_COLS < new_table->n_cols) { DBUG_ASSERT(DICT_TF2_FLAG_IS_SET( new_table, DICT_TF2_FTS_HAS_DOC_ID)); - DBUG_ASSERT(altered_table->s->fields + DBUG_ASSERT(altered_table->s->stored_fields + DATA_N_SYS_COLS + 1 == new_table->n_cols); - col_map[i] = altered_table->s->fields; + col_map[i] = altered_table->s->stored_fields; } else { DBUG_ASSERT(!DICT_TF2_FLAG_IS_SET( new_table, @@ -2577,6 +2676,7 @@ prepare_inplace_alter_table_dict( ulint new_clustered = 0; dberr_t error; ulint num_fts_index; + uint sql_idx; ha_innobase_inplace_ctx*ctx; DBUG_ENTER("prepare_inplace_alter_table_dict"); @@ -2714,7 +2814,7 @@ prepare_inplace_alter_table_dict( goto new_clustered_failed; } - n_cols = altered_table->s->fields; + n_cols = altered_table->s->stored_fields; if (add_fts_doc_id) { n_cols++; @@ -2749,8 +2849,12 @@ prepare_inplace_alter_table_dict( user_table->data_dir_path); } - for (uint i = 0; i < altered_table->s->fields; i++) { - const Field* field = altered_table->field[i]; + sql_idx= 0; + for (uint i = 0; i < altered_table->s->stored_fields; i++, sql_idx++) { + const Field* field; + while (!((field= altered_table->field[sql_idx])-> + stored_in_db)) + sql_idx++; ulint is_unsigned; ulint field_type = (ulint) field->type(); @@ -2828,7 +2932,7 @@ prepare_inplace_alter_table_dict( if (add_fts_doc_id) { fts_add_doc_id_column(ctx->new_table, ctx->heap); ctx->new_table->fts->doc_col = fts_doc_id_col; - ut_ad(fts_doc_id_col == altered_table->s->fields); + ut_ad(fts_doc_id_col == altered_table->s->stored_fields); } else if (ctx->new_table->fts) { ctx->new_table->fts->doc_col = fts_doc_id_col; } @@ -3225,7 +3329,8 @@ innobase_check_foreign_key_index( foreign->referenced_col_names, foreign->n_fields, index, /*check_charsets=*/TRUE, - /*check_null=*/FALSE) + /*check_null=*/FALSE, + NULL, NULL, NULL) && NULL == innobase_find_equiv_index( foreign->referenced_col_names, foreign->n_fields, @@ -3259,7 +3364,8 @@ innobase_check_foreign_key_index( foreign->foreign_col_names, foreign->n_fields, index, /*check_charsets=*/TRUE, - /*check_null=*/FALSE) + /*check_null=*/FALSE, + NULL, NULL, NULL) && NULL == innobase_find_equiv_index( foreign->foreign_col_names, foreign->n_fields, @@ -3786,7 +3892,7 @@ func_exit: if (!innobase_fts_check_doc_id_col( prebuilt->table, altered_table, &fts_doc_col_no)) { - fts_doc_col_no = altered_table->s->fields; + fts_doc_col_no = altered_table->s->stored_fields; add_fts_doc_id = true; add_fts_doc_id_idx = true; @@ -3820,15 +3926,22 @@ func_exit: } /* See if an AUTO_INCREMENT column was added. */ - uint i = 0; + uint i = 0, innodb_idx= 0; List_iterator_fast<Create_field> cf_it( ha_alter_info->alter_info->create_list); while (const Create_field* new_field = cf_it++) { const Field* field; + if (!new_field->stored_in_db) { + i++; + continue; + } DBUG_ASSERT(i < altered_table->s->fields); + DBUG_ASSERT(innodb_idx < altered_table->s->stored_fields); for (uint old_i = 0; table->field[old_i]; old_i++) { + if (!table->field[old_i]->stored_in_db) + continue; if (new_field->field == table->field[old_i]) { goto found_col; } @@ -3852,13 +3965,14 @@ func_exit: my_error(ER_WRONG_AUTO_KEY, MYF(0)); goto err_exit; } - add_autoinc_col_no = i; + add_autoinc_col_no = innodb_idx; autoinc_col_max_value = innobase_get_int_col_max_value( field); } found_col: i++; + innodb_idx++; } DBUG_ASSERT(heap); @@ -4394,7 +4508,7 @@ rename_foreign: std::list<dict_foreign_t*> fk_evict; bool foreign_modified; - for (dict_foreign_set::iterator it = user_table->foreign_set.begin(); + for (dict_foreign_set::const_iterator it = user_table->foreign_set.begin(); it != user_table->foreign_set.end(); ++it) { @@ -4435,7 +4549,7 @@ rename_foreign: } } - for (dict_foreign_set::iterator it + for (dict_foreign_set::const_iterator it = user_table->referenced_set.begin(); it != user_table->referenced_set.end(); ++it) { @@ -4513,7 +4627,7 @@ innobase_rename_columns_try( & Alter_inplace_info::ALTER_COLUMN_NAME); for (Field** fp = table->field; *fp; fp++, i++) { - if (!((*fp)->flags & FIELD_IS_RENAMED)) { + if (!((*fp)->flags & FIELD_IS_RENAMED) || !((*fp)->stored_in_db)) { continue; } @@ -4710,7 +4824,8 @@ innobase_update_foreign_try( fk->n_fields, fk->referenced_index, TRUE, fk->type & (DICT_FOREIGN_ON_DELETE_SET_NULL - | DICT_FOREIGN_ON_UPDATE_SET_NULL)); + | DICT_FOREIGN_ON_UPDATE_SET_NULL), + NULL, NULL, NULL); if (!fk->foreign_index) { my_error(ER_FK_INCORRECT_OPTION, MYF(0), table_name, fk->id); @@ -4722,7 +4837,7 @@ innobase_update_foreign_try( names, while the columns in ctx->old_table have not been renamed yet. */ error = dict_create_add_foreign_to_dictionary( - ctx->old_table->name, fk, trx); + (dict_table_t*)ctx->old_table,ctx->old_table->name, fk, trx); DBUG_EXECUTE_IF( "innodb_test_cannot_add_fk_system", @@ -5476,9 +5591,9 @@ ha_innobase::commit_inplace_alter_table( if (ha_alter_info->group_commit_ctx) { ctx_array = ha_alter_info->group_commit_ctx; } else { - ctx_single[0] = ctx0; - ctx_single[1] = NULL; - ctx_array = ctx_single; + ctx_single[0] = ctx0; + ctx_single[1] = NULL; + ctx_array = ctx_single; } DBUG_ASSERT(ctx0 == ctx_array[0]); diff --git a/storage/innobase/handler/i_s.cc b/storage/innobase/handler/i_s.cc index 192003a19d2..6168ce0f0d2 100644 --- a/storage/innobase/handler/i_s.cc +++ b/storage/innobase/handler/i_s.cc @@ -33,7 +33,7 @@ Created July 18, 2007 Vasil Dimov #include <my_sys.h> #include "i_s.h" #include <sql_plugin.h> -#include <mysql/innodb_priv.h> +#include <innodb_priv.h> #include "btr0pcur.h" #include "btr0types.h" @@ -157,9 +157,12 @@ do { \ } \ } while (0) -#if !defined __STRICT_ANSI__ && defined __GNUC__ && (__GNUC__) > 2 && \ - !defined __INTEL_COMPILER && !defined __clang__ +#if !defined __STRICT_ANSI__ && defined __GNUC__ && (__GNUC__) > 2 && !defined __INTEL_COMPILER && !defined __clang__ +#ifdef HAVE_C99_INITIALIZERS +#define STRUCT_FLD(name, value) .name = value +#else #define STRUCT_FLD(name, value) name: value +#endif /* HAVE_C99_INITIALIZERS */ #else #define STRUCT_FLD(name, value) value #endif @@ -254,7 +257,7 @@ field_store_time_t( memset(&my_time, 0, sizeof(my_time)); } - return(field->store_time(&my_time, MYSQL_TIMESTAMP_DATETIME)); + return(field->store_time(&my_time)); } /*******************************************************************//** @@ -756,7 +759,7 @@ static struct st_mysql_information_schema i_s_info = MYSQL_INFORMATION_SCHEMA_INTERFACE_VERSION }; -UNIV_INTERN struct st_mysql_plugin i_s_innodb_trx = +UNIV_INTERN struct st_maria_plugin i_s_innodb_trx = { /* the plugin type (a MYSQL_XXX_PLUGIN value) */ /* int */ @@ -800,13 +803,9 @@ UNIV_INTERN struct st_mysql_plugin i_s_innodb_trx = /* struct st_mysql_sys_var** */ STRUCT_FLD(system_vars, NULL), - /* reserved for dependency checking */ - /* void* */ - STRUCT_FLD(__reserved1, NULL), - - /* Plugin flags */ - /* unsigned long */ - STRUCT_FLD(flags, 0UL), + /* Maria extension */ + STRUCT_FLD(version_info, INNODB_VERSION_STR), + STRUCT_FLD(maturity, MariaDB_PLUGIN_MATURITY_STABLE), }; /* Fields of the dynamic table INFORMATION_SCHEMA.innodb_locks */ @@ -1020,7 +1019,7 @@ innodb_locks_init( DBUG_RETURN(0); } -UNIV_INTERN struct st_mysql_plugin i_s_innodb_locks = +UNIV_INTERN struct st_maria_plugin i_s_innodb_locks = { /* the plugin type (a MYSQL_XXX_PLUGIN value) */ /* int */ @@ -1064,13 +1063,9 @@ UNIV_INTERN struct st_mysql_plugin i_s_innodb_locks = /* struct st_mysql_sys_var** */ STRUCT_FLD(system_vars, NULL), - /* reserved for dependency checking */ - /* void* */ - STRUCT_FLD(__reserved1, NULL), - - /* Plugin flags */ - /* unsigned long */ - STRUCT_FLD(flags, 0UL), + /* Maria extension */ + STRUCT_FLD(version_info, INNODB_VERSION_STR), + STRUCT_FLD(maturity, MariaDB_PLUGIN_MATURITY_STABLE), }; /* Fields of the dynamic table INFORMATION_SCHEMA.innodb_lock_waits */ @@ -1207,7 +1202,7 @@ innodb_lock_waits_init( DBUG_RETURN(0); } -UNIV_INTERN struct st_mysql_plugin i_s_innodb_lock_waits = +UNIV_INTERN struct st_maria_plugin i_s_innodb_lock_waits = { /* the plugin type (a MYSQL_XXX_PLUGIN value) */ /* int */ @@ -1251,13 +1246,9 @@ UNIV_INTERN struct st_mysql_plugin i_s_innodb_lock_waits = /* struct st_mysql_sys_var** */ STRUCT_FLD(system_vars, NULL), - /* reserved for dependency checking */ - /* void* */ - STRUCT_FLD(__reserved1, NULL), - - /* Plugin flags */ - /* unsigned long */ - STRUCT_FLD(flags, 0UL), + /* Maria extension */ + STRUCT_FLD(version_info, INNODB_VERSION_STR), + STRUCT_FLD(maturity, MariaDB_PLUGIN_MATURITY_STABLE), }; /*******************************************************************//** @@ -1547,7 +1538,7 @@ i_s_cmp_reset_init( DBUG_RETURN(0); } -UNIV_INTERN struct st_mysql_plugin i_s_innodb_cmp = +UNIV_INTERN struct st_maria_plugin i_s_innodb_cmp = { /* the plugin type (a MYSQL_XXX_PLUGIN value) */ /* int */ @@ -1591,16 +1582,12 @@ UNIV_INTERN struct st_mysql_plugin i_s_innodb_cmp = /* struct st_mysql_sys_var** */ STRUCT_FLD(system_vars, NULL), - /* reserved for dependency checking */ - /* void* */ - STRUCT_FLD(__reserved1, NULL), - - /* Plugin flags */ - /* unsigned long */ - STRUCT_FLD(flags, 0UL), + /* Maria extension */ + STRUCT_FLD(version_info, INNODB_VERSION_STR), + STRUCT_FLD(maturity, MariaDB_PLUGIN_MATURITY_STABLE), }; -UNIV_INTERN struct st_mysql_plugin i_s_innodb_cmp_reset = +UNIV_INTERN struct st_maria_plugin i_s_innodb_cmp_reset = { /* the plugin type (a MYSQL_XXX_PLUGIN value) */ /* int */ @@ -1645,13 +1632,9 @@ UNIV_INTERN struct st_mysql_plugin i_s_innodb_cmp_reset = /* struct st_mysql_sys_var** */ STRUCT_FLD(system_vars, NULL), - /* reserved for dependency checking */ - /* void* */ - STRUCT_FLD(__reserved1, NULL), - - /* Plugin flags */ - /* unsigned long */ - STRUCT_FLD(flags, 0UL), + /* Maria extension */ + STRUCT_FLD(version_info, INNODB_VERSION_STR), + STRUCT_FLD(maturity, MariaDB_PLUGIN_MATURITY_STABLE), }; /* Fields of the dynamic tables @@ -1905,7 +1888,7 @@ i_s_cmp_per_index_reset_init( DBUG_RETURN(0); } -UNIV_INTERN struct st_mysql_plugin i_s_innodb_cmp_per_index = +UNIV_INTERN struct st_maria_plugin i_s_innodb_cmp_per_index = { /* the plugin type (a MYSQL_XXX_PLUGIN value) */ /* int */ @@ -1949,16 +1932,12 @@ UNIV_INTERN struct st_mysql_plugin i_s_innodb_cmp_per_index = /* struct st_mysql_sys_var** */ STRUCT_FLD(system_vars, NULL), - /* reserved for dependency checking */ - /* void* */ - STRUCT_FLD(__reserved1, NULL), - - /* Plugin flags */ - /* unsigned long */ - STRUCT_FLD(flags, 0UL), + /* Maria extension */ + STRUCT_FLD(version_info, INNODB_VERSION_STR), + STRUCT_FLD(maturity, MariaDB_PLUGIN_MATURITY_STABLE), }; -UNIV_INTERN struct st_mysql_plugin i_s_innodb_cmp_per_index_reset = +UNIV_INTERN struct st_maria_plugin i_s_innodb_cmp_per_index_reset = { /* the plugin type (a MYSQL_XXX_PLUGIN value) */ /* int */ @@ -2003,13 +1982,9 @@ UNIV_INTERN struct st_mysql_plugin i_s_innodb_cmp_per_index_reset = /* struct st_mysql_sys_var** */ STRUCT_FLD(system_vars, NULL), - /* reserved for dependency checking */ - /* void* */ - STRUCT_FLD(__reserved1, NULL), - - /* Plugin flags */ - /* unsigned long */ - STRUCT_FLD(flags, 0UL), + /* Maria extension */ + STRUCT_FLD(version_info, INNODB_VERSION_STR), + STRUCT_FLD(maturity, MariaDB_PLUGIN_MATURITY_STABLE), }; /* Fields of the dynamic table information_schema.innodb_cmpmem. */ @@ -2206,7 +2181,7 @@ i_s_cmpmem_reset_init( DBUG_RETURN(0); } -UNIV_INTERN struct st_mysql_plugin i_s_innodb_cmpmem = +UNIV_INTERN struct st_maria_plugin i_s_innodb_cmpmem = { /* the plugin type (a MYSQL_XXX_PLUGIN value) */ /* int */ @@ -2250,16 +2225,12 @@ UNIV_INTERN struct st_mysql_plugin i_s_innodb_cmpmem = /* struct st_mysql_sys_var** */ STRUCT_FLD(system_vars, NULL), - /* reserved for dependency checking */ - /* void* */ - STRUCT_FLD(__reserved1, NULL), - - /* Plugin flags */ - /* unsigned long */ - STRUCT_FLD(flags, 0UL), + /* Maria extension */ + STRUCT_FLD(version_info, INNODB_VERSION_STR), + STRUCT_FLD(maturity, MariaDB_PLUGIN_MATURITY_STABLE), }; -UNIV_INTERN struct st_mysql_plugin i_s_innodb_cmpmem_reset = +UNIV_INTERN struct st_maria_plugin i_s_innodb_cmpmem_reset = { /* the plugin type (a MYSQL_XXX_PLUGIN value) */ /* int */ @@ -2304,13 +2275,9 @@ UNIV_INTERN struct st_mysql_plugin i_s_innodb_cmpmem_reset = /* struct st_mysql_sys_var** */ STRUCT_FLD(system_vars, NULL), - /* reserved for dependency checking */ - /* void* */ - STRUCT_FLD(__reserved1, NULL), - - /* Plugin flags */ - /* unsigned long */ - STRUCT_FLD(flags, 0UL), + /* Maria extension */ + STRUCT_FLD(version_info, INNODB_VERSION_STR), + STRUCT_FLD(maturity, MariaDB_PLUGIN_MATURITY_STABLE), }; /* Fields of the dynamic table INFORMATION_SCHEMA.innodb_metrics */ @@ -2788,7 +2755,7 @@ innodb_metrics_init( DBUG_RETURN(0); } -UNIV_INTERN struct st_mysql_plugin i_s_innodb_metrics = +UNIV_INTERN struct st_maria_plugin i_s_innodb_metrics = { /* the plugin type (a MYSQL_XXX_PLUGIN value) */ /* int */ @@ -2832,13 +2799,9 @@ UNIV_INTERN struct st_mysql_plugin i_s_innodb_metrics = /* struct st_mysql_sys_var** */ STRUCT_FLD(system_vars, NULL), - /* reserved for dependency checking */ - /* void* */ - STRUCT_FLD(__reserved1, NULL), - - /* Plugin flags */ - /* unsigned long */ - STRUCT_FLD(flags, 0UL), + /* Maria extension */ + STRUCT_FLD(version_info, INNODB_VERSION_STR), + STRUCT_FLD(maturity, MariaDB_PLUGIN_MATURITY_STABLE), }; /* Fields of the dynamic table INFORMATION_SCHEMA.innodb_ft_default_stopword */ static ST_FIELD_INFO i_s_stopword_fields_info[] = @@ -2905,7 +2868,7 @@ i_s_stopword_init( DBUG_RETURN(0); } -UNIV_INTERN struct st_mysql_plugin i_s_innodb_ft_default_stopword = +UNIV_INTERN struct st_maria_plugin i_s_innodb_ft_default_stopword = { /* the plugin type (a MYSQL_XXX_PLUGIN value) */ /* int */ @@ -2949,13 +2912,9 @@ UNIV_INTERN struct st_mysql_plugin i_s_innodb_ft_default_stopword = /* struct st_mysql_sys_var** */ STRUCT_FLD(system_vars, NULL), - /* reserved for dependency checking */ - /* void* */ - STRUCT_FLD(__reserved1, NULL), - - /* Plugin flags */ - /* unsigned long */ - STRUCT_FLD(flags, 0UL), + /* Maria extension */ + STRUCT_FLD(version_info, INNODB_VERSION_STR), + STRUCT_FLD(maturity, MariaDB_PLUGIN_MATURITY_STABLE), }; /* Fields of the dynamic table INFORMATION_SCHEMA.INNODB_FT_DELETED @@ -3077,7 +3036,7 @@ i_s_fts_deleted_init( DBUG_RETURN(0); } -UNIV_INTERN struct st_mysql_plugin i_s_innodb_ft_deleted = +UNIV_INTERN struct st_maria_plugin i_s_innodb_ft_deleted = { /* the plugin type (a MYSQL_XXX_PLUGIN value) */ /* int */ @@ -3121,13 +3080,9 @@ UNIV_INTERN struct st_mysql_plugin i_s_innodb_ft_deleted = /* struct st_mysql_sys_var** */ STRUCT_FLD(system_vars, NULL), - /* reserved for dependency checking */ - /* void* */ - STRUCT_FLD(__reserved1, NULL), - - /* Plugin flags */ - /* unsigned long */ - STRUCT_FLD(flags, 0UL), + /* Maria extension */ + STRUCT_FLD(version_info, INNODB_VERSION_STR), + STRUCT_FLD(maturity, MariaDB_PLUGIN_MATURITY_STABLE), }; /*******************************************************************//** @@ -3164,7 +3119,7 @@ i_s_fts_being_deleted_init( DBUG_RETURN(0); } -UNIV_INTERN struct st_mysql_plugin i_s_innodb_ft_being_deleted = +UNIV_INTERN struct st_maria_plugin i_s_innodb_ft_being_deleted = { /* the plugin type (a MYSQL_XXX_PLUGIN value) */ /* int */ @@ -3208,13 +3163,9 @@ UNIV_INTERN struct st_mysql_plugin i_s_innodb_ft_being_deleted = /* struct st_mysql_sys_var** */ STRUCT_FLD(system_vars, NULL), - /* reserved for dependency checking */ - /* void* */ - STRUCT_FLD(__reserved1, NULL), - - /* Plugin flags */ - /* unsigned long */ - STRUCT_FLD(flags, 0UL), + /* Maria extension */ + STRUCT_FLD(version_info, INNODB_VERSION_STR), + STRUCT_FLD(maturity, MariaDB_PLUGIN_MATURITY_STABLE), }; /* Fields of the dynamic table INFORMATION_SCHEMA.INNODB_FT_INDEX_CACHED and @@ -3457,7 +3408,7 @@ i_s_fts_index_cache_init( DBUG_RETURN(0); } -UNIV_INTERN struct st_mysql_plugin i_s_innodb_ft_index_cache = +UNIV_INTERN struct st_maria_plugin i_s_innodb_ft_index_cache = { /* the plugin type (a MYSQL_XXX_PLUGIN value) */ /* int */ @@ -3501,13 +3452,9 @@ UNIV_INTERN struct st_mysql_plugin i_s_innodb_ft_index_cache = /* struct st_mysql_sys_var** */ STRUCT_FLD(system_vars, NULL), - /* reserved for dependency checking */ - /* void* */ - STRUCT_FLD(__reserved1, NULL), - - /* Plugin flags */ - /* unsigned long */ - STRUCT_FLD(flags, 0UL), + /* Maria extension */ + STRUCT_FLD(version_info, INNODB_VERSION_STR), + STRUCT_FLD(maturity, MariaDB_PLUGIN_MATURITY_STABLE), }; /*******************************************************************//** @@ -3896,7 +3843,7 @@ i_s_fts_index_table_init( DBUG_RETURN(0); } -UNIV_INTERN struct st_mysql_plugin i_s_innodb_ft_index_table = +UNIV_INTERN struct st_maria_plugin i_s_innodb_ft_index_table = { /* the plugin type (a MYSQL_XXX_PLUGIN value) */ /* int */ @@ -3940,13 +3887,9 @@ UNIV_INTERN struct st_mysql_plugin i_s_innodb_ft_index_table = /* struct st_mysql_sys_var** */ STRUCT_FLD(system_vars, NULL), - /* reserved for dependency checking */ - /* void* */ - STRUCT_FLD(__reserved1, NULL), - - /* Plugin flags */ - /* unsigned long */ - STRUCT_FLD(flags, 0UL), + /* Maria extension */ + STRUCT_FLD(version_info, INNODB_VERSION_STR), + STRUCT_FLD(maturity, MariaDB_PLUGIN_MATURITY_STABLE), }; /* Fields of the dynamic table INFORMATION_SCHEMA.INNODB_FT_CONFIG */ @@ -4098,7 +4041,7 @@ i_s_fts_config_init( DBUG_RETURN(0); } -UNIV_INTERN struct st_mysql_plugin i_s_innodb_ft_config = +UNIV_INTERN struct st_maria_plugin i_s_innodb_ft_config = { /* the plugin type (a MYSQL_XXX_PLUGIN value) */ /* int */ @@ -4142,13 +4085,9 @@ UNIV_INTERN struct st_mysql_plugin i_s_innodb_ft_config = /* struct st_mysql_sys_var** */ STRUCT_FLD(system_vars, NULL), - /* reserved for dependency checking */ - /* void* */ - STRUCT_FLD(__reserved1, NULL), - - /* Plugin flags */ - /* unsigned long */ - STRUCT_FLD(flags, 0UL), + /* Maria extension */ + STRUCT_FLD(version_info, INNODB_VERSION_STR), + STRUCT_FLD(maturity, MariaDB_PLUGIN_MATURITY_STABLE), }; /* Fields of the dynamic table INNODB_BUFFER_POOL_STATS. */ @@ -4647,7 +4586,7 @@ i_s_innodb_buffer_pool_stats_init( DBUG_RETURN(0); } -UNIV_INTERN struct st_mysql_plugin i_s_innodb_buffer_stats = +UNIV_INTERN struct st_maria_plugin i_s_innodb_buffer_stats = { /* the plugin type (a MYSQL_XXX_PLUGIN value) */ /* int */ @@ -4691,13 +4630,9 @@ UNIV_INTERN struct st_mysql_plugin i_s_innodb_buffer_stats = /* struct st_mysql_sys_var** */ STRUCT_FLD(system_vars, NULL), - /* reserved for dependency checking */ - /* void* */ - STRUCT_FLD(__reserved1, NULL), - - /* Plugin flags */ - /* unsigned long */ - STRUCT_FLD(flags, 0UL), + /* Maria extension */ + STRUCT_FLD(version_info, INNODB_VERSION_STR), + STRUCT_FLD(maturity, MariaDB_PLUGIN_MATURITY_STABLE), }; /* Fields of the dynamic table INNODB_BUFFER_POOL_PAGE. */ @@ -5363,7 +5298,7 @@ i_s_innodb_buffer_page_init( DBUG_RETURN(0); } -UNIV_INTERN struct st_mysql_plugin i_s_innodb_buffer_page = +UNIV_INTERN struct st_maria_plugin i_s_innodb_buffer_page = { /* the plugin type (a MYSQL_XXX_PLUGIN value) */ /* int */ @@ -5407,13 +5342,9 @@ UNIV_INTERN struct st_mysql_plugin i_s_innodb_buffer_page = /* struct st_mysql_sys_var** */ STRUCT_FLD(system_vars, NULL), - /* reserved for dependency checking */ - /* void* */ - STRUCT_FLD(__reserved1, NULL), - - /* Plugin flags */ - /* unsigned long */ - STRUCT_FLD(flags, 0UL), + /* Maria extension */ + STRUCT_FLD(version_info, INNODB_VERSION_STR), + STRUCT_FLD(maturity, MariaDB_PLUGIN_MATURITY_STABLE), }; static ST_FIELD_INFO i_s_innodb_buf_page_lru_fields_info[] = @@ -5914,7 +5845,7 @@ i_s_innodb_buffer_page_lru_init( DBUG_RETURN(0); } -UNIV_INTERN struct st_mysql_plugin i_s_innodb_buffer_page_lru = +UNIV_INTERN struct st_maria_plugin i_s_innodb_buffer_page_lru = { /* the plugin type (a MYSQL_XXX_PLUGIN value) */ /* int */ @@ -5958,13 +5889,9 @@ UNIV_INTERN struct st_mysql_plugin i_s_innodb_buffer_page_lru = /* struct st_mysql_sys_var** */ STRUCT_FLD(system_vars, NULL), - /* reserved for dependency checking */ - /* void* */ - STRUCT_FLD(__reserved1, NULL), - - /* Plugin flags */ - /* unsigned long */ - STRUCT_FLD(flags, 0UL), + /* Maria extension */ + STRUCT_FLD(version_info, INNODB_VERSION_STR), + STRUCT_FLD(maturity, MariaDB_PLUGIN_MATURITY_STABLE), }; /*******************************************************************//** @@ -6212,7 +6139,7 @@ innodb_sys_tables_init( DBUG_RETURN(0); } -UNIV_INTERN struct st_mysql_plugin i_s_innodb_sys_tables = +UNIV_INTERN struct st_maria_plugin i_s_innodb_sys_tables = { /* the plugin type (a MYSQL_XXX_PLUGIN value) */ /* int */ @@ -6256,13 +6183,9 @@ UNIV_INTERN struct st_mysql_plugin i_s_innodb_sys_tables = /* struct st_mysql_sys_var** */ STRUCT_FLD(system_vars, NULL), - /* reserved for dependency checking */ - /* void* */ - STRUCT_FLD(__reserved1, NULL), - - /* Plugin flags */ - /* unsigned long */ - STRUCT_FLD(flags, 0UL), + /* Maria extension */ + STRUCT_FLD(version_info, INNODB_VERSION_STR), + STRUCT_FLD(maturity, MariaDB_PLUGIN_MATURITY_STABLE), }; /** SYS_TABLESTATS ***********************************************/ @@ -6506,7 +6429,7 @@ innodb_sys_tablestats_init( DBUG_RETURN(0); } -UNIV_INTERN struct st_mysql_plugin i_s_innodb_sys_tablestats = +UNIV_INTERN struct st_maria_plugin i_s_innodb_sys_tablestats = { /* the plugin type (a MYSQL_XXX_PLUGIN value) */ /* int */ @@ -6550,13 +6473,9 @@ UNIV_INTERN struct st_mysql_plugin i_s_innodb_sys_tablestats = /* struct st_mysql_sys_var** */ STRUCT_FLD(system_vars, NULL), - /* reserved for dependency checking */ - /* void* */ - STRUCT_FLD(__reserved1, NULL), - - /* Plugin flags */ - /* unsigned long */ - STRUCT_FLD(flags, 0UL), + /* Maria extension */ + STRUCT_FLD(version_info, INNODB_VERSION_STR), + STRUCT_FLD(maturity, MariaDB_PLUGIN_MATURITY_STABLE), }; /** SYS_INDEXES **************************************************/ @@ -6762,7 +6681,7 @@ innodb_sys_indexes_init( DBUG_RETURN(0); } -UNIV_INTERN struct st_mysql_plugin i_s_innodb_sys_indexes = +UNIV_INTERN struct st_maria_plugin i_s_innodb_sys_indexes = { /* the plugin type (a MYSQL_XXX_PLUGIN value) */ /* int */ @@ -6806,13 +6725,9 @@ UNIV_INTERN struct st_mysql_plugin i_s_innodb_sys_indexes = /* struct st_mysql_sys_var** */ STRUCT_FLD(system_vars, NULL), - /* reserved for dependency checking */ - /* void* */ - STRUCT_FLD(__reserved1, NULL), - - /* Plugin flags */ - /* unsigned long */ - STRUCT_FLD(flags, 0UL), + /* Maria extension */ + STRUCT_FLD(version_info, INNODB_VERSION_STR), + STRUCT_FLD(maturity, MariaDB_PLUGIN_MATURITY_STABLE), }; /** SYS_COLUMNS **************************************************/ @@ -7003,7 +6918,7 @@ innodb_sys_columns_init( DBUG_RETURN(0); } -UNIV_INTERN struct st_mysql_plugin i_s_innodb_sys_columns = +UNIV_INTERN struct st_maria_plugin i_s_innodb_sys_columns = { /* the plugin type (a MYSQL_XXX_PLUGIN value) */ /* int */ @@ -7047,13 +6962,9 @@ UNIV_INTERN struct st_mysql_plugin i_s_innodb_sys_columns = /* struct st_mysql_sys_var** */ STRUCT_FLD(system_vars, NULL), - /* reserved for dependency checking */ - /* void* */ - STRUCT_FLD(__reserved1, NULL), - - /* Plugin flags */ - /* unsigned long */ - STRUCT_FLD(flags, 0UL), + /* Maria extension */ + STRUCT_FLD(version_info, INNODB_VERSION_STR), + STRUCT_FLD(maturity, MariaDB_PLUGIN_MATURITY_STABLE), }; /** SYS_FIELDS ***************************************************/ @@ -7217,7 +7128,7 @@ innodb_sys_fields_init( DBUG_RETURN(0); } -UNIV_INTERN struct st_mysql_plugin i_s_innodb_sys_fields = +UNIV_INTERN struct st_maria_plugin i_s_innodb_sys_fields = { /* the plugin type (a MYSQL_XXX_PLUGIN value) */ /* int */ @@ -7261,13 +7172,9 @@ UNIV_INTERN struct st_mysql_plugin i_s_innodb_sys_fields = /* struct st_mysql_sys_var** */ STRUCT_FLD(system_vars, NULL), - /* reserved for dependency checking */ - /* void* */ - STRUCT_FLD(__reserved1, NULL), - - /* Plugin flags */ - /* unsigned long */ - STRUCT_FLD(flags, 0UL), + /* Maria extension */ + STRUCT_FLD(version_info, INNODB_VERSION_STR), + STRUCT_FLD(maturity, MariaDB_PLUGIN_MATURITY_STABLE), }; /** SYS_FOREIGN ********************************************/ @@ -7446,7 +7353,7 @@ innodb_sys_foreign_init( DBUG_RETURN(0); } -UNIV_INTERN struct st_mysql_plugin i_s_innodb_sys_foreign = +UNIV_INTERN struct st_maria_plugin i_s_innodb_sys_foreign = { /* the plugin type (a MYSQL_XXX_PLUGIN value) */ /* int */ @@ -7490,13 +7397,9 @@ UNIV_INTERN struct st_mysql_plugin i_s_innodb_sys_foreign = /* struct st_mysql_sys_var** */ STRUCT_FLD(system_vars, NULL), - /* reserved for dependency checking */ - /* void* */ - STRUCT_FLD(__reserved1, NULL), - - /* Plugin flags */ - /* unsigned long */ - STRUCT_FLD(flags, 0UL), + /* Maria extension */ + STRUCT_FLD(version_info, INNODB_VERSION_STR), + STRUCT_FLD(maturity, MariaDB_PLUGIN_MATURITY_STABLE), }; /** SYS_FOREIGN_COLS ********************************************/ @@ -7667,7 +7570,7 @@ innodb_sys_foreign_cols_init( DBUG_RETURN(0); } -UNIV_INTERN struct st_mysql_plugin i_s_innodb_sys_foreign_cols = +UNIV_INTERN struct st_maria_plugin i_s_innodb_sys_foreign_cols = { /* the plugin type (a MYSQL_XXX_PLUGIN value) */ /* int */ @@ -7711,13 +7614,9 @@ UNIV_INTERN struct st_mysql_plugin i_s_innodb_sys_foreign_cols = /* struct st_mysql_sys_var** */ STRUCT_FLD(system_vars, NULL), - /* reserved for dependency checking */ - /* void* */ - STRUCT_FLD(__reserved1, NULL), - - /* Plugin flags */ - /* unsigned long */ - STRUCT_FLD(flags, 0UL), + /* Maria extension */ + STRUCT_FLD(version_info, INNODB_VERSION_STR), + STRUCT_FLD(maturity, MariaDB_PLUGIN_MATURITY_STABLE), }; /** SYS_TABLESPACES ********************************************/ @@ -7939,7 +7838,7 @@ innodb_sys_tablespaces_init( DBUG_RETURN(0); } -UNIV_INTERN struct st_mysql_plugin i_s_innodb_sys_tablespaces = +UNIV_INTERN struct st_maria_plugin i_s_innodb_sys_tablespaces = { /* the plugin type (a MYSQL_XXX_PLUGIN value) */ /* int */ @@ -7983,13 +7882,9 @@ UNIV_INTERN struct st_mysql_plugin i_s_innodb_sys_tablespaces = /* struct st_mysql_sys_var** */ STRUCT_FLD(system_vars, NULL), - /* reserved for dependency checking */ - /* void* */ - STRUCT_FLD(__reserved1, NULL), - - /* Plugin flags */ - /* unsigned long */ - STRUCT_FLD(flags, 0UL), + /* Maria extension */ + STRUCT_FLD(version_info, INNODB_VERSION_STR), + STRUCT_FLD(maturity, MariaDB_PLUGIN_MATURITY_STABLE), }; /** SYS_DATAFILES ************************************************/ @@ -8132,7 +8027,7 @@ innodb_sys_datafiles_init( DBUG_RETURN(0); } -UNIV_INTERN struct st_mysql_plugin i_s_innodb_sys_datafiles = +UNIV_INTERN struct st_maria_plugin i_s_innodb_sys_datafiles = { /* the plugin type (a MYSQL_XXX_PLUGIN value) */ /* int */ @@ -8176,11 +8071,7 @@ UNIV_INTERN struct st_mysql_plugin i_s_innodb_sys_datafiles = /* struct st_mysql_sys_var** */ STRUCT_FLD(system_vars, NULL), - /* reserved for dependency checking */ - /* void* */ - STRUCT_FLD(__reserved1, NULL), - - /* Plugin flags */ - /* unsigned long */ - STRUCT_FLD(flags, 0UL), + /* Maria extension */ + STRUCT_FLD(version_info, INNODB_VERSION_STR), + STRUCT_FLD(maturity, MariaDB_PLUGIN_MATURITY_STABLE), }; diff --git a/storage/innobase/handler/i_s.h b/storage/innobase/handler/i_s.h index 9c8849345f0..a2b324cb314 100644 --- a/storage/innobase/handler/i_s.h +++ b/storage/innobase/handler/i_s.h @@ -28,33 +28,33 @@ Created July 18, 2007 Vasil Dimov const char plugin_author[] = "Oracle Corporation"; -extern struct st_mysql_plugin i_s_innodb_trx; -extern struct st_mysql_plugin i_s_innodb_locks; -extern struct st_mysql_plugin i_s_innodb_lock_waits; -extern struct st_mysql_plugin i_s_innodb_cmp; -extern struct st_mysql_plugin i_s_innodb_cmp_reset; -extern struct st_mysql_plugin i_s_innodb_cmp_per_index; -extern struct st_mysql_plugin i_s_innodb_cmp_per_index_reset; -extern struct st_mysql_plugin i_s_innodb_cmpmem; -extern struct st_mysql_plugin i_s_innodb_cmpmem_reset; -extern struct st_mysql_plugin i_s_innodb_metrics; -extern struct st_mysql_plugin i_s_innodb_ft_default_stopword; -extern struct st_mysql_plugin i_s_innodb_ft_deleted; -extern struct st_mysql_plugin i_s_innodb_ft_being_deleted; -extern struct st_mysql_plugin i_s_innodb_ft_index_cache; -extern struct st_mysql_plugin i_s_innodb_ft_index_table; -extern struct st_mysql_plugin i_s_innodb_ft_config; -extern struct st_mysql_plugin i_s_innodb_buffer_page; -extern struct st_mysql_plugin i_s_innodb_buffer_page_lru; -extern struct st_mysql_plugin i_s_innodb_buffer_stats; -extern struct st_mysql_plugin i_s_innodb_sys_tables; -extern struct st_mysql_plugin i_s_innodb_sys_tablestats; -extern struct st_mysql_plugin i_s_innodb_sys_indexes; -extern struct st_mysql_plugin i_s_innodb_sys_columns; -extern struct st_mysql_plugin i_s_innodb_sys_fields; -extern struct st_mysql_plugin i_s_innodb_sys_foreign; -extern struct st_mysql_plugin i_s_innodb_sys_foreign_cols; -extern struct st_mysql_plugin i_s_innodb_sys_tablespaces; -extern struct st_mysql_plugin i_s_innodb_sys_datafiles; +extern struct st_maria_plugin i_s_innodb_trx; +extern struct st_maria_plugin i_s_innodb_locks; +extern struct st_maria_plugin i_s_innodb_lock_waits; +extern struct st_maria_plugin i_s_innodb_cmp; +extern struct st_maria_plugin i_s_innodb_cmp_reset; +extern struct st_maria_plugin i_s_innodb_cmp_per_index; +extern struct st_maria_plugin i_s_innodb_cmp_per_index_reset; +extern struct st_maria_plugin i_s_innodb_cmpmem; +extern struct st_maria_plugin i_s_innodb_cmpmem_reset; +extern struct st_maria_plugin i_s_innodb_metrics; +extern struct st_maria_plugin i_s_innodb_ft_default_stopword; +extern struct st_maria_plugin i_s_innodb_ft_deleted; +extern struct st_maria_plugin i_s_innodb_ft_being_deleted; +extern struct st_maria_plugin i_s_innodb_ft_index_cache; +extern struct st_maria_plugin i_s_innodb_ft_index_table; +extern struct st_maria_plugin i_s_innodb_ft_config; +extern struct st_maria_plugin i_s_innodb_buffer_page; +extern struct st_maria_plugin i_s_innodb_buffer_page_lru; +extern struct st_maria_plugin i_s_innodb_buffer_stats; +extern struct st_maria_plugin i_s_innodb_sys_tables; +extern struct st_maria_plugin i_s_innodb_sys_tablestats; +extern struct st_maria_plugin i_s_innodb_sys_indexes; +extern struct st_maria_plugin i_s_innodb_sys_columns; +extern struct st_maria_plugin i_s_innodb_sys_fields; +extern struct st_maria_plugin i_s_innodb_sys_foreign; +extern struct st_maria_plugin i_s_innodb_sys_foreign_cols; +extern struct st_maria_plugin i_s_innodb_sys_tablespaces; +extern struct st_maria_plugin i_s_innodb_sys_datafiles; #endif /* i_s_h */ |
