MySQL 5.6.14 Source Code Document
 All Classes Namespaces Files Functions Variables Typedefs Enumerations Enumerator Friends Macros Groups Pages
ha_innodb.cc
Go to the documentation of this file.
1 /*****************************************************************************
2 
3 Copyright (c) 2000, 2013, Oracle and/or its affiliates. All rights reserved.
4 Copyright (c) 2008, 2009 Google Inc.
5 Copyright (c) 2009, Percona Inc.
6 Copyright (c) 2012, Facebook Inc.
7 
8 Portions of this file contain modifications contributed and copyrighted by
9 Google, Inc. Those modifications are gratefully acknowledged and are described
10 briefly in the InnoDB documentation. The contributions by Google are
11 incorporated with their permission, and subject to the conditions contained in
12 the file COPYING.Google.
13 
14 Portions of this file contain modifications contributed and copyrighted
15 by Percona Inc.. Those modifications are
16 gratefully acknowledged and are described briefly in the InnoDB
17 documentation. The contributions by Percona Inc. are incorporated with
18 their permission, and subject to the conditions contained in the file
19 COPYING.Percona.
20 
21 This program is free software; you can redistribute it and/or modify it under
22 the terms of the GNU General Public License as published by the Free Software
23 Foundation; version 2 of the License.
24 
25 This program is distributed in the hope that it will be useful, but WITHOUT
26 ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS
27 FOR A PARTICULAR PURPOSE. See the GNU General Public License for more details.
28 
29 You should have received a copy of the GNU General Public License along with
30 this program; if not, write to the Free Software Foundation, Inc.,
31 51 Franklin Street, Suite 500, Boston, MA 02110-1335 USA
32 
33 *****************************************************************************/
34 
35 #include <sql_table.h> // explain_filename, nz2, EXPLAIN_PARTITIONS_AS_COMMENT,
36  // EXPLAIN_FILENAME_MAX_EXTRA_LENGTH
37 
38 #include <sql_acl.h> // PROCESS_ACL
39 #include <debug_sync.h> // DEBUG_SYNC
40 #include <my_base.h> // HA_OPTION_*
41 #include <mysys_err.h>
42 #include <mysql/innodb_priv.h>
43 
46 /* Include necessary InnoDB headers */
47 #include "univ.i"
48 #include "buf0dump.h"
49 #include "buf0lru.h"
50 #include "buf0flu.h"
51 #include "buf0dblwr.h"
52 #include "btr0sea.h"
53 #include "os0file.h"
54 #include "os0thread.h"
55 #include "srv0start.h"
56 #include "srv0srv.h"
57 #include "trx0roll.h"
58 #include "trx0trx.h"
59 
60 #include "trx0sys.h"
61 #include "mtr0mtr.h"
62 #include "rem0types.h"
63 #include "row0ins.h"
64 #include "row0mysql.h"
65 #include "row0sel.h"
66 #include "row0upd.h"
67 #include "log0log.h"
68 #include "lock0lock.h"
69 #include "dict0crea.h"
70 #include "btr0cur.h"
71 #include "btr0btr.h"
72 #include "fsp0fsp.h"
73 #include "sync0sync.h"
74 #include "fil0fil.h"
75 #include "trx0xa.h"
76 #include "row0merge.h"
77 #include "dict0boot.h"
78 #include "dict0stats.h"
79 #include "dict0stats_bg.h"
80 #include "ha_prototypes.h"
81 #include "ut0mem.h"
82 #include "ibuf0ibuf.h"
83 #include "dict0dict.h"
84 #include "srv0mon.h"
85 #include "api0api.h"
86 #include "api0misc.h"
87 #include "pars0pars.h"
88 #include "fts0fts.h"
89 #include "fts0types.h"
90 #include "row0import.h"
91 #include "row0quiesce.h"
92 #ifdef UNIV_DEBUG
93 #include "trx0purge.h"
94 #endif /* UNIV_DEBUG */
95 #include "fts0priv.h"
96 #include "page0zip.h"
97 
98 enum_tx_isolation thd_get_trx_isolation(const THD* thd);
99 
100 #include "ha_innodb.h"
101 #include "i_s.h"
102 
103 # ifndef MYSQL_PLUGIN_IMPORT
104 # define MYSQL_PLUGIN_IMPORT /* nothing */
105 # endif /* MYSQL_PLUGIN_IMPORT */
106 
108 static mysql_mutex_t innobase_share_mutex;
110 static ulong commit_threads = 0;
111 static mysql_cond_t commit_cond;
112 static mysql_mutex_t commit_cond_m;
113 static bool innodb_inited = 0;
114 
115 #define INSIDE_HA_INNOBASE_CC
116 
117 #define EQ_CURRENT_THD(thd) ((thd) == current_thd)
118 
119 static struct handlerton* innodb_hton_ptr;
120 
121 static const long AUTOINC_OLD_STYLE_LOCKING = 0;
122 static const long AUTOINC_NEW_STYLE_LOCKING = 1;
123 static const long AUTOINC_NO_LOCKING = 2;
124 
125 static long innobase_mirrored_log_groups;
126 static long innobase_log_buffer_size;
127 static long innobase_additional_mem_pool_size;
128 static long innobase_file_io_threads;
129 static long innobase_open_files;
130 static long innobase_autoinc_lock_mode;
131 static ulong innobase_commit_concurrency = 0;
132 static ulong innobase_read_io_threads;
133 static ulong innobase_write_io_threads;
134 static long innobase_buffer_pool_instances = 1;
135 
136 static long long innobase_buffer_pool_size, innobase_log_file_size;
137 
140 static uint innobase_old_blocks_pct;
141 
144 static uint innobase_change_buffer_max_size = CHANGE_BUFFER_DEFAULT_SIZE;
145 
146 /* The default values for the following char* start-up parameters
147 are determined in innobase_init below: */
148 
149 static char* innobase_data_home_dir = NULL;
150 static char* innobase_data_file_path = NULL;
151 static char* innobase_file_format_name = NULL;
152 static char* innobase_change_buffering = NULL;
153 static char* innobase_enable_monitor_counter = NULL;
154 static char* innobase_disable_monitor_counter = NULL;
155 static char* innobase_reset_monitor_counter = NULL;
156 static char* innobase_reset_all_monitor_counter = NULL;
157 
158 /* The highest file format being used in the database. The value can be
159 set by user, however, it will be adjusted to the newer file format if
160 a table of such format is created/opened. */
161 static char* innobase_file_format_max = NULL;
162 
163 static char* innobase_file_flush_method = NULL;
164 
165 /* This variable can be set in the server configure file, specifying
166 stopword table to be used */
167 static char* innobase_server_stopword_table = NULL;
168 
169 /* Below we have boolean-valued start-up parameters, and their default
170 values */
171 
172 static ulong innobase_fast_shutdown = 1;
173 static my_bool innobase_file_format_check = TRUE;
174 #ifdef UNIV_LOG_ARCHIVE
175 static my_bool innobase_log_archive = FALSE;
176 static char* innobase_log_arch_dir = NULL;
177 #endif /* UNIV_LOG_ARCHIVE */
178 static my_bool innobase_use_doublewrite = TRUE;
179 static my_bool innobase_use_checksums = TRUE;
180 static my_bool innobase_locks_unsafe_for_binlog = FALSE;
181 static my_bool innobase_rollback_on_timeout = FALSE;
182 static my_bool innobase_create_status_file = FALSE;
183 static my_bool innobase_stats_on_metadata = TRUE;
184 static my_bool innobase_large_prefix = FALSE;
185 static my_bool innodb_optimize_fulltext_only = FALSE;
186 
187 static char* internal_innobase_data_file_path = NULL;
188 
189 static char* innodb_version_str = (char*) INNODB_VERSION_STR;
190 
191 static char* fts_server_stopword_table = NULL;
192 
196 static const char* innodb_stats_method_names[] = {
197  "nulls_equal",
198  "nulls_unequal",
199  "nulls_ignored",
200  NullS
201 };
202 
205 static TYPELIB innodb_stats_method_typelib = {
206  array_elements(innodb_stats_method_names) - 1,
207  "innodb_stats_method_typelib",
208  innodb_stats_method_names,
209  NULL
210 };
211 
213 static const char* innodb_checksum_algorithm_names[] = {
214  "crc32",
215  "strict_crc32",
216  "innodb",
217  "strict_innodb",
218  "none",
219  "strict_none",
220  NullS
221 };
222 
225 static TYPELIB innodb_checksum_algorithm_typelib = {
226  array_elements(innodb_checksum_algorithm_names) - 1,
227  "innodb_checksum_algorithm_typelib",
228  innodb_checksum_algorithm_names,
229  NULL
230 };
231 
232 /* The following counter is used to convey information to InnoDB
233 about server activity: in selects it is not sensible to call
234 srv_active_wake_master_thread after each fetch or search, we only do
235 it every INNOBASE_WAKE_INTERVAL'th step. */
236 
237 #define INNOBASE_WAKE_INTERVAL 32
238 static ulong innobase_active_counter = 0;
239 
240 static hash_table_t* innobase_open_tables;
241 
243 static const char* innobase_change_buffering_values[IBUF_USE_COUNT] = {
244  "none", /* IBUF_USE_NONE */
245  "inserts", /* IBUF_USE_INSERT */
246  "deletes", /* IBUF_USE_DELETE_MARK */
247  "changes", /* IBUF_USE_INSERT_DELETE_MARK */
248  "purges", /* IBUF_USE_DELETE */
249  "all" /* IBUF_USE_ALL */
250 };
251 
252 /* Call back function array defined by MySQL and used to
253 retrieve FTS results. */
254 const struct _ft_vft ft_vft_result = {NULL,
255  innobase_fts_find_ranking,
256  innobase_fts_close_ranking,
257  innobase_fts_retrieve_ranking,
258  NULL};
259 
260 const struct _ft_vft_ext ft_vft_ext_result = {innobase_fts_get_version,
261  innobase_fts_flags,
262  innobase_fts_retrieve_docid,
263  innobase_fts_count_matches};
264 
265 #ifdef HAVE_PSI_INTERFACE
266 /* Keys to register pthread mutexes/cond in the current file with
267 performance schema */
268 static mysql_pfs_key_t innobase_share_mutex_key;
269 static mysql_pfs_key_t commit_cond_mutex_key;
270 static mysql_pfs_key_t commit_cond_key;
271 
272 static PSI_mutex_info all_pthread_mutexes[] = {
273  {&commit_cond_mutex_key, "commit_cond_mutex", 0},
274  {&innobase_share_mutex_key, "innobase_share_mutex", 0}
275 };
276 
277 static PSI_cond_info all_innodb_conds[] = {
278  {&commit_cond_key, "commit_cond", 0}
279 };
280 
281 # ifdef UNIV_PFS_MUTEX
282 /* all_innodb_mutexes array contains mutexes that are
283 performance schema instrumented if "UNIV_PFS_MUTEX"
284 is defined */
285 static PSI_mutex_info all_innodb_mutexes[] = {
286  {&autoinc_mutex_key, "autoinc_mutex", 0},
287 # ifndef PFS_SKIP_BUFFER_MUTEX_RWLOCK
288  {&buffer_block_mutex_key, "buffer_block_mutex", 0},
289 # endif /* !PFS_SKIP_BUFFER_MUTEX_RWLOCK */
290  {&buf_pool_mutex_key, "buf_pool_mutex", 0},
291  {&buf_pool_zip_mutex_key, "buf_pool_zip_mutex", 0},
292  {&cache_last_read_mutex_key, "cache_last_read_mutex", 0},
293  {&dict_foreign_err_mutex_key, "dict_foreign_err_mutex", 0},
294  {&dict_sys_mutex_key, "dict_sys_mutex", 0},
295  {&file_format_max_mutex_key, "file_format_max_mutex", 0},
296  {&fil_system_mutex_key, "fil_system_mutex", 0},
297  {&flush_list_mutex_key, "flush_list_mutex", 0},
298  {&fts_bg_threads_mutex_key, "fts_bg_threads_mutex", 0},
299  {&fts_delete_mutex_key, "fts_delete_mutex", 0},
300  {&fts_optimize_mutex_key, "fts_optimize_mutex", 0},
301  {&fts_doc_id_mutex_key, "fts_doc_id_mutex", 0},
302  {&log_flush_order_mutex_key, "log_flush_order_mutex", 0},
303  {&hash_table_mutex_key, "hash_table_mutex", 0},
304  {&ibuf_bitmap_mutex_key, "ibuf_bitmap_mutex", 0},
305  {&ibuf_mutex_key, "ibuf_mutex", 0},
306  {&ibuf_pessimistic_insert_mutex_key,
307  "ibuf_pessimistic_insert_mutex", 0},
308 # ifndef HAVE_ATOMIC_BUILTINS
309  {&server_mutex_key, "server_mutex", 0},
310 # endif /* !HAVE_ATOMIC_BUILTINS */
311  {&log_sys_mutex_key, "log_sys_mutex", 0},
312 # ifdef UNIV_MEM_DEBUG
313  {&mem_hash_mutex_key, "mem_hash_mutex", 0},
314 # endif /* UNIV_MEM_DEBUG */
315  {&mem_pool_mutex_key, "mem_pool_mutex", 0},
316  {&mutex_list_mutex_key, "mutex_list_mutex", 0},
317  {&page_zip_stat_per_index_mutex_key, "page_zip_stat_per_index_mutex", 0},
318  {&purge_sys_bh_mutex_key, "purge_sys_bh_mutex", 0},
319  {&recv_sys_mutex_key, "recv_sys_mutex", 0},
320  {&recv_writer_mutex_key, "recv_writer_mutex", 0},
321  {&rseg_mutex_key, "rseg_mutex", 0},
322 # ifdef UNIV_SYNC_DEBUG
323  {&rw_lock_debug_mutex_key, "rw_lock_debug_mutex", 0},
324 # endif /* UNIV_SYNC_DEBUG */
325  {&rw_lock_list_mutex_key, "rw_lock_list_mutex", 0},
326  {&rw_lock_mutex_key, "rw_lock_mutex", 0},
327  {&srv_dict_tmpfile_mutex_key, "srv_dict_tmpfile_mutex", 0},
328  {&srv_innodb_monitor_mutex_key, "srv_innodb_monitor_mutex", 0},
329  {&srv_misc_tmpfile_mutex_key, "srv_misc_tmpfile_mutex", 0},
330  {&srv_monitor_file_mutex_key, "srv_monitor_file_mutex", 0},
331 # ifdef UNIV_SYNC_DEBUG
332  {&sync_thread_mutex_key, "sync_thread_mutex", 0},
333 # endif /* UNIV_SYNC_DEBUG */
334  {&buf_dblwr_mutex_key, "buf_dblwr_mutex", 0},
335  {&trx_undo_mutex_key, "trx_undo_mutex", 0},
336  {&srv_sys_mutex_key, "srv_sys_mutex", 0},
337  {&lock_sys_mutex_key, "lock_mutex", 0},
338  {&lock_sys_wait_mutex_key, "lock_wait_mutex", 0},
339  {&trx_mutex_key, "trx_mutex", 0},
340  {&srv_sys_tasks_mutex_key, "srv_threads_mutex", 0},
341  /* mutex with os_fast_mutex_ interfaces */
342 # ifndef PFS_SKIP_EVENT_MUTEX
343  {&event_os_mutex_key, "event_os_mutex", 0},
344 # endif /* PFS_SKIP_EVENT_MUTEX */
345  {&os_mutex_key, "os_mutex", 0},
346 #ifndef HAVE_ATOMIC_BUILTINS
347  {&srv_conc_mutex_key, "srv_conc_mutex", 0},
348 #endif /* !HAVE_ATOMIC_BUILTINS */
349 #ifndef HAVE_ATOMIC_BUILTINS_64
350  {&monitor_mutex_key, "monitor_mutex", 0},
351 #endif /* !HAVE_ATOMIC_BUILTINS_64 */
352  {&ut_list_mutex_key, "ut_list_mutex", 0},
353  {&trx_sys_mutex_key, "trx_sys_mutex", 0},
354  {&zip_pad_mutex_key, "zip_pad_mutex", 0},
355 };
356 # endif /* UNIV_PFS_MUTEX */
357 
358 # ifdef UNIV_PFS_RWLOCK
359 /* all_innodb_rwlocks array contains rwlocks that are
360 performance schema instrumented if "UNIV_PFS_RWLOCK"
361 is defined */
362 static PSI_rwlock_info all_innodb_rwlocks[] = {
363 # ifdef UNIV_LOG_ARCHIVE
364  {&archive_lock_key, "archive_lock", 0},
365 # endif /* UNIV_LOG_ARCHIVE */
366  {&btr_search_latch_key, "btr_search_latch", 0},
367 # ifndef PFS_SKIP_BUFFER_MUTEX_RWLOCK
368  {&buf_block_lock_key, "buf_block_lock", 0},
369 # endif /* !PFS_SKIP_BUFFER_MUTEX_RWLOCK */
370 # ifdef UNIV_SYNC_DEBUG
371  {&buf_block_debug_latch_key, "buf_block_debug_latch", 0},
372 # endif /* UNIV_SYNC_DEBUG */
373  {&dict_operation_lock_key, "dict_operation_lock", 0},
374  {&fil_space_latch_key, "fil_space_latch", 0},
375  {&checkpoint_lock_key, "checkpoint_lock", 0},
376  {&fts_cache_rw_lock_key, "fts_cache_rw_lock", 0},
377  {&fts_cache_init_rw_lock_key, "fts_cache_init_rw_lock", 0},
378  {&trx_i_s_cache_lock_key, "trx_i_s_cache_lock", 0},
379  {&trx_purge_latch_key, "trx_purge_latch", 0},
380  {&index_tree_rw_lock_key, "index_tree_rw_lock", 0},
381  {&index_online_log_key, "index_online_log", 0},
382  {&dict_table_stats_latch_key, "dict_table_stats", 0},
383  {&hash_table_rw_lock_key, "hash_table_locks", 0}
384 };
385 # endif /* UNIV_PFS_RWLOCK */
386 
387 # ifdef UNIV_PFS_THREAD
388 /* all_innodb_threads array contains threads that are
389 performance schema instrumented if "UNIV_PFS_THREAD"
390 is defined */
391 static PSI_thread_info all_innodb_threads[] = {
392  {&trx_rollback_clean_thread_key, "trx_rollback_clean_thread", 0},
393  {&io_handler_thread_key, "io_handler_thread", 0},
394  {&srv_lock_timeout_thread_key, "srv_lock_timeout_thread", 0},
395  {&srv_error_monitor_thread_key, "srv_error_monitor_thread", 0},
396  {&srv_monitor_thread_key, "srv_monitor_thread", 0},
397  {&srv_master_thread_key, "srv_master_thread", 0},
398  {&srv_purge_thread_key, "srv_purge_thread", 0},
399  {&buf_page_cleaner_thread_key, "page_cleaner_thread", 0},
400  {&recv_writer_thread_key, "recv_writer_thread", 0}
401 };
402 # endif /* UNIV_PFS_THREAD */
403 
404 # ifdef UNIV_PFS_IO
405 /* all_innodb_files array contains the type of files that are
406 performance schema instrumented if "UNIV_PFS_IO" is defined */
407 static PSI_file_info all_innodb_files[] = {
408  {&innodb_file_data_key, "innodb_data_file", 0},
409  {&innodb_file_log_key, "innodb_log_file", 0},
410  {&innodb_file_temp_key, "innodb_temp_file", 0}
411 };
412 # endif /* UNIV_PFS_IO */
413 #endif /* HAVE_PSI_INTERFACE */
414 
416 #ifdef __WIN__
417 #define normalize_table_name(norm_name, name) \
418  normalize_table_name_low(norm_name, name, TRUE)
419 #else
420 #define normalize_table_name(norm_name, name) \
421  normalize_table_name_low(norm_name, name, FALSE)
422 #endif /* __WIN__ */
423 
485 };
486 
487 /*************************************************************/
491 static
492 int
493 innodb_stopword_table_validate(
494 /*===========================*/
495  THD* thd,
496  struct st_mysql_sys_var* var,
498  void* save,
500  struct st_mysql_value* value);
504 const char innobase_index_reserve_name[] = "GEN_CLUST_INDEX";
505 
506 /******************************************************************/
509 static inline
510 ulint
511 innobase_map_isolation_level(
512 /*=========================*/
513  enum_tx_isolation iso);
515 static const char innobase_hton_name[]= "InnoDB";
516 
517 static MYSQL_THDVAR_BOOL(support_xa, PLUGIN_VAR_OPCMDARG,
518  "Enable InnoDB support for the XA two-phase commit",
519  /* check_func */ NULL, /* update_func */ NULL,
520  /* default */ TRUE);
521 
522 static MYSQL_THDVAR_BOOL(table_locks, PLUGIN_VAR_OPCMDARG,
523  "Enable InnoDB locking in LOCK TABLES",
524  /* check_func */ NULL, /* update_func */ NULL,
525  /* default */ TRUE);
526 
527 static MYSQL_THDVAR_BOOL(strict_mode, PLUGIN_VAR_OPCMDARG,
528  "Use strict mode when evaluating create options.",
529  NULL, NULL, FALSE);
530 
531 static MYSQL_THDVAR_BOOL(ft_enable_stopword, PLUGIN_VAR_OPCMDARG,
532  "Create FTS index with stopword.",
533  NULL, NULL,
534  /* default */ TRUE);
535 
536 static MYSQL_THDVAR_ULONG(lock_wait_timeout, PLUGIN_VAR_RQCMDARG,
537  "Timeout in seconds an InnoDB transaction may wait for a lock before being rolled back. Values above 100000000 disable the timeout.",
538  NULL, NULL, 50, 1, 1024 * 1024 * 1024, 0);
539 
540 static MYSQL_THDVAR_STR(ft_user_stopword_table,
541  PLUGIN_VAR_OPCMDARG|PLUGIN_VAR_MEMALLOC,
542  "User supplied stopword table name, effective in the session level.",
543  innodb_stopword_table_validate, NULL, NULL);
544 
545 static SHOW_VAR innodb_status_variables[]= {
546  {"buffer_pool_dump_status",
547  (char*) &export_vars.innodb_buffer_pool_dump_status, SHOW_CHAR},
548  {"buffer_pool_load_status",
549  (char*) &export_vars.innodb_buffer_pool_load_status, SHOW_CHAR},
550  {"buffer_pool_pages_data",
551  (char*) &export_vars.innodb_buffer_pool_pages_data, SHOW_LONG},
552  {"buffer_pool_bytes_data",
553  (char*) &export_vars.innodb_buffer_pool_bytes_data, SHOW_LONG},
554  {"buffer_pool_pages_dirty",
555  (char*) &export_vars.innodb_buffer_pool_pages_dirty, SHOW_LONG},
556  {"buffer_pool_bytes_dirty",
557  (char*) &export_vars.innodb_buffer_pool_bytes_dirty, SHOW_LONG},
558  {"buffer_pool_pages_flushed",
559  (char*) &export_vars.innodb_buffer_pool_pages_flushed, SHOW_LONG},
560  {"buffer_pool_pages_free",
561  (char*) &export_vars.innodb_buffer_pool_pages_free, SHOW_LONG},
562 #ifdef UNIV_DEBUG
563  {"buffer_pool_pages_latched",
564  (char*) &export_vars.innodb_buffer_pool_pages_latched, SHOW_LONG},
565 #endif /* UNIV_DEBUG */
566  {"buffer_pool_pages_misc",
567  (char*) &export_vars.innodb_buffer_pool_pages_misc, SHOW_LONG},
568  {"buffer_pool_pages_total",
569  (char*) &export_vars.innodb_buffer_pool_pages_total, SHOW_LONG},
570  {"buffer_pool_read_ahead_rnd",
571  (char*) &export_vars.innodb_buffer_pool_read_ahead_rnd, SHOW_LONG},
572  {"buffer_pool_read_ahead",
573  (char*) &export_vars.innodb_buffer_pool_read_ahead, SHOW_LONG},
574  {"buffer_pool_read_ahead_evicted",
576  {"buffer_pool_read_requests",
577  (char*) &export_vars.innodb_buffer_pool_read_requests, SHOW_LONG},
578  {"buffer_pool_reads",
579  (char*) &export_vars.innodb_buffer_pool_reads, SHOW_LONG},
580  {"buffer_pool_wait_free",
581  (char*) &export_vars.innodb_buffer_pool_wait_free, SHOW_LONG},
582  {"buffer_pool_write_requests",
583  (char*) &export_vars.innodb_buffer_pool_write_requests, SHOW_LONG},
584  {"data_fsyncs",
585  (char*) &export_vars.innodb_data_fsyncs, SHOW_LONG},
586  {"data_pending_fsyncs",
587  (char*) &export_vars.innodb_data_pending_fsyncs, SHOW_LONG},
588  {"data_pending_reads",
589  (char*) &export_vars.innodb_data_pending_reads, SHOW_LONG},
590  {"data_pending_writes",
591  (char*) &export_vars.innodb_data_pending_writes, SHOW_LONG},
592  {"data_read",
593  (char*) &export_vars.innodb_data_read, SHOW_LONG},
594  {"data_reads",
595  (char*) &export_vars.innodb_data_reads, SHOW_LONG},
596  {"data_writes",
597  (char*) &export_vars.innodb_data_writes, SHOW_LONG},
598  {"data_written",
599  (char*) &export_vars.innodb_data_written, SHOW_LONG},
600  {"dblwr_pages_written",
601  (char*) &export_vars.innodb_dblwr_pages_written, SHOW_LONG},
602  {"dblwr_writes",
603  (char*) &export_vars.innodb_dblwr_writes, SHOW_LONG},
604  {"have_atomic_builtins",
605  (char*) &export_vars.innodb_have_atomic_builtins, SHOW_BOOL},
606  {"log_waits",
607  (char*) &export_vars.innodb_log_waits, SHOW_LONG},
608  {"log_write_requests",
609  (char*) &export_vars.innodb_log_write_requests, SHOW_LONG},
610  {"log_writes",
611  (char*) &export_vars.innodb_log_writes, SHOW_LONG},
612  {"os_log_fsyncs",
613  (char*) &export_vars.innodb_os_log_fsyncs, SHOW_LONG},
614  {"os_log_pending_fsyncs",
615  (char*) &export_vars.innodb_os_log_pending_fsyncs, SHOW_LONG},
616  {"os_log_pending_writes",
617  (char*) &export_vars.innodb_os_log_pending_writes, SHOW_LONG},
618  {"os_log_written",
619  (char*) &export_vars.innodb_os_log_written, SHOW_LONGLONG},
620  {"page_size",
621  (char*) &export_vars.innodb_page_size, SHOW_LONG},
622  {"pages_created",
623  (char*) &export_vars.innodb_pages_created, SHOW_LONG},
624  {"pages_read",
625  (char*) &export_vars.innodb_pages_read, SHOW_LONG},
626  {"pages_written",
627  (char*) &export_vars.innodb_pages_written, SHOW_LONG},
628  {"row_lock_current_waits",
629  (char*) &export_vars.innodb_row_lock_current_waits, SHOW_LONG},
630  {"row_lock_time",
631  (char*) &export_vars.innodb_row_lock_time, SHOW_LONGLONG},
632  {"row_lock_time_avg",
633  (char*) &export_vars.innodb_row_lock_time_avg, SHOW_LONG},
634  {"row_lock_time_max",
635  (char*) &export_vars.innodb_row_lock_time_max, SHOW_LONG},
636  {"row_lock_waits",
637  (char*) &export_vars.innodb_row_lock_waits, SHOW_LONG},
638  {"rows_deleted",
639  (char*) &export_vars.innodb_rows_deleted, SHOW_LONG},
640  {"rows_inserted",
641  (char*) &export_vars.innodb_rows_inserted, SHOW_LONG},
642  {"rows_read",
643  (char*) &export_vars.innodb_rows_read, SHOW_LONG},
644  {"rows_updated",
645  (char*) &export_vars.innodb_rows_updated, SHOW_LONG},
646  {"num_open_files",
647  (char*) &export_vars.innodb_num_open_files, SHOW_LONG},
648  {"truncated_status_writes",
649  (char*) &export_vars.innodb_truncated_status_writes, SHOW_LONG},
650  {"available_undo_logs",
651  (char*) &export_vars.innodb_available_undo_logs, SHOW_LONG},
652 #ifdef UNIV_DEBUG
653  {"purge_trx_id_age",
654  (char*) &export_vars.innodb_purge_trx_id_age, SHOW_LONG},
655  {"purge_view_trx_id_age",
656  (char*) &export_vars.innodb_purge_view_trx_id_age, SHOW_LONG},
657 #endif /* UNIV_DEBUG */
658  {NullS, NullS, SHOW_LONG}
659 };
660 
661 /************************************************************************/
664 static
666 get_share(
667 /*======*/
668  const char* table_name);
670 /************************************************************************/
672 static
673 void
674 free_share(
675 /*=======*/
676  INNOBASE_SHARE* share);
678 /*****************************************************************/
681 static
682 int
683 innobase_close_connection(
684 /*======================*/
685  handlerton* hton,
686  THD* thd);
689 /*****************************************************************/
693 static
694 int
695 innobase_commit(
696 /*============*/
697  handlerton* hton,
698  THD* thd,
701  bool commit_trx);
705 /*****************************************************************/
709 static
710 int
711 innobase_rollback(
712 /*==============*/
713  handlerton* hton,
714  THD* thd,
717  bool rollback_trx);
721 /*****************************************************************/
725 static
726 int
727 innobase_rollback_to_savepoint(
728 /*===========================*/
729  handlerton* hton,
730  THD* thd,
733  void* savepoint);
735 /*****************************************************************/
738 static
739 int
740 innobase_savepoint(
741 /*===============*/
742  handlerton* hton,
743  THD* thd,
746  void* savepoint);
748 /*****************************************************************/
752 static
753 int
754 innobase_release_savepoint(
755 /*=======================*/
756  handlerton* hton,
757  THD* thd,
760  void* savepoint);
762 /************************************************************************/
764 static
765 handler*
766 innobase_create_handler(
767 /*====================*/
768  handlerton* hton,
770  MEM_ROOT* mem_root);
771 
781 static
782 void
783 innobase_commit_concurrency_init_default();
784 /*=======================================*/
785 
791 static
792 void
793 innobase_undo_logs_init_default_max();
794 /*==================================*/
795 
796 /************************************************************/
799 static
800 uint
801 innobase_file_format_name_lookup(
802 /*=============================*/
803  const char* format_name);
805 /************************************************************/
809 static
810 int
811 innobase_file_format_validate_and_set(
812 /*==================================*/
813  const char* format_max);
815 /*******************************************************************/
818 static
819 int
820 innobase_xa_prepare(
821 /*================*/
822  handlerton* hton,
823  THD* thd,
826  bool all);
829 /*******************************************************************/
832 static
833 int
834 innobase_xa_recover(
835 /*================*/
836  handlerton* hton,
837  XID* xid_list,
838  uint len);
839 /*******************************************************************/
843 static
844 int
845 innobase_commit_by_xid(
846 /*===================*/
847  handlerton* hton,
848  XID* xid);
850 /*******************************************************************/
854 static
855 int
856 innobase_rollback_by_xid(
857 /*=====================*/
858  handlerton* hton,
859  XID* xid);
861 /*******************************************************************/
867 static
868 void*
869 innobase_create_cursor_view(
870 /*========================*/
871  handlerton* hton,
872  THD* thd);
873 /*******************************************************************/
878 static
879 void
880 innobase_set_cursor_view(
881 /*=====================*/
882  handlerton* hton,
883  THD* thd,
884  void* curview);
886 /*******************************************************************/
890 static
891 void
892 innobase_close_cursor_view(
893 /*=======================*/
894  handlerton* hton,
895  THD* thd,
896  void* curview);
898 /*****************************************************************/
900 static
901 void
902 innobase_drop_database(
903 /*===================*/
904  handlerton* hton,
905  char* path);
910 /*******************************************************************/
912 static
913 int
914 innobase_end(
915 /*=========*/
916  handlerton* hton, /* in: Innodb handlerton */
917  ha_panic_function type);
918 
919 /*****************************************************************/
925 static
926 int
927 innobase_start_trx_and_assign_read_view(
928 /*====================================*/
929  handlerton* hton, /* in: Innodb handlerton */
930  THD* thd); /* in: MySQL thread handle of the
931  user for whom the transaction should
932  be committed */
933 /****************************************************************/
937 static
938 bool
939 innobase_flush_logs(
940 /*================*/
941  handlerton* hton);
943 /************************************************************************/
947 static
948 int
949 innodb_show_status(
950 /*===============*/
951  handlerton* hton,
952  THD* thd,
954  stat_print_fn* stat_print);
955 /************************************************************************/
958 static
959 bool
960 innobase_show_status(
961 /*=================*/
962  handlerton* hton,
963  THD* thd,
965  stat_print_fn* stat_print,
966  enum ha_stat_type stat_type);
967 
968 /*****************************************************************/
970 static
971 void
972 innobase_commit_low(
973 /*================*/
974  trx_t* trx);
976 /****************************************************************/
981 static
982 void
983 innodb_enable_monitor_at_startup(
984 /*=============================*/
985  char* str);
987 /*********************************************************************
988 Normalizes a table name string. A normalized name consists of the
989 database name catenated to '/' and table name. An example:
990 test/mytable. On Windows normalization puts both the database name and the
991 table name always to lower case if "set_lower_case" is set to TRUE. */
992 static
993 void
994 normalize_table_name_low(
995 /*=====================*/
996  char* norm_name, /* out: normalized name as a
997  null-terminated string */
998  const char* name, /* in: table name string */
999  ibool set_lower_case); /* in: TRUE if we want to set
1000  name to lower case */
1001 
1002 /*************************************************************/
1005 static
1006 int
1007 innobase_commit_concurrency_validate(
1008 /*=================================*/
1009  THD* thd,
1010  struct st_mysql_sys_var* var,
1012  void* save,
1014  struct st_mysql_value* value)
1015 {
1016  long long intbuf;
1017  ulong commit_concurrency;
1018 
1019  DBUG_ENTER("innobase_commit_concurrency_validate");
1020 
1021  if (value->val_int(value, &intbuf)) {
1022  /* The value is NULL. That is invalid. */
1023  DBUG_RETURN(1);
1024  }
1025 
1026  *reinterpret_cast<ulong*>(save) = commit_concurrency
1027  = static_cast<ulong>(intbuf);
1028 
1029  /* Allow the value to be updated, as long as it remains zero
1030  or nonzero. */
1031  DBUG_RETURN(!(!commit_concurrency == !innobase_commit_concurrency));
1032 }
1033 
1034 /*******************************************************************/
1036 static
1037 handler*
1038 innobase_create_handler(
1039 /*====================*/
1040  handlerton* hton,
1041  TABLE_SHARE* table,
1042  MEM_ROOT* mem_root)
1043 {
1044  return(new (mem_root) ha_innobase(hton, table));
1045 }
1046 
1047 /* General functions */
1048 
1049 /*************************************************************/
1053 inline
1054 int
1056 /*======================*/
1057  ulong page_size)
1058 {
1059  ulong n;
1060 
1061  DBUG_ENTER("innodb_page_size_validate");
1062 
1063  for (n = UNIV_PAGE_SIZE_SHIFT_MIN;
1064  n <= UNIV_PAGE_SIZE_SHIFT_MAX;
1065  n++) {
1066  if (page_size == (ulong) (1 << n)) {
1067  DBUG_RETURN(n);
1068  }
1069  }
1070 
1071  DBUG_RETURN(0);
1072 }
1073 
1074 /******************************************************************/
1081 UNIV_INTERN
1082 ibool
1084 /*============================*/
1085  THD* thd)
1086 {
1087  return((ibool) thd_slave_thread(thd));
1088 }
1089 
1090 /******************************************************************/
1094 UNIV_INTERN
1095 enum durability_properties
1097 /*=====================*/
1098  const THD* thd)
1099 {
1100  return(thd_get_durability_property(thd));
1101 }
1102 
1103 /******************************************************************/
1106 UNIV_INTERN
1107 ibool
1109 /*=================*/
1110  THD* thd)
1111 {
1112  return(thd != 0 && thd_tx_is_read_only(thd));
1113 }
1114 
1115 /******************************************************************/
1119 UNIV_INTERN
1120 ibool
1122 /*===================*/
1123  THD* thd)
1124 {
1125  return(thd != NULL
1126  && !thd_test_options(
1127  thd,
1128  OPTION_NOT_AUTOCOMMIT | OPTION_BEGIN)
1129  && thd_is_select(thd));
1130 }
1131 
1132 /******************************************************************/
1135 static inline
1136 void
1137 innobase_srv_conc_enter_innodb(
1138 /*===========================*/
1139  trx_t* trx)
1140 {
1141  if (srv_thread_concurrency) {
1142  if (trx->n_tickets_to_enter_innodb > 0) {
1143 
1144  /* If trx has 'free tickets' to enter the engine left,
1145  then use one such ticket */
1146 
1148 
1149  } else if (trx->mysql_thd != NULL
1151 
1152  UT_WAIT_FOR(
1155  srv_replication_delay * 1000);
1156 
1157  } else {
1158  srv_conc_enter_innodb(trx);
1159  }
1160  }
1161 }
1162 
1163 /******************************************************************/
1166 static inline
1167 void
1168 innobase_srv_conc_exit_innodb(
1169 /*==========================*/
1170  trx_t* trx)
1171 {
1172 #ifdef UNIV_SYNC_DEBUG
1173  ut_ad(!sync_thread_levels_nonempty_trx(trx->has_search_latch));
1174 #endif /* UNIV_SYNC_DEBUG */
1175 
1176  /* This is to avoid making an unnecessary function call. */
1178  && trx->n_tickets_to_enter_innodb == 0) {
1179 
1181  }
1182 }
1183 
1184 /******************************************************************/
1186 static inline
1187 void
1188 innobase_srv_conc_force_exit_innodb(
1189 /*================================*/
1190  trx_t* trx)
1191 {
1192 #ifdef UNIV_SYNC_DEBUG
1193  ut_ad(!sync_thread_levels_nonempty_trx(trx->has_search_latch));
1194 #endif /* UNIV_SYNC_DEBUG */
1195 
1196  /* This is to avoid making an unnecessary function call. */
1197  if (trx->declared_to_be_inside_innodb) {
1199  }
1200 }
1201 
1202 /******************************************************************/
1205 UNIV_INTERN
1206 const char*
1208 /*=================*/
1209 {
1210  return(glob_hostname);
1211 }
1212 
1213 /******************************************************************/
1219 UNIV_INTERN
1220 ibool
1222 /*===========================*/
1223  THD* thd)
1224 {
1225  return((ibool) thd_non_transactional_update(thd));
1226 }
1227 
1228 /******************************************************************/
1231 UNIV_INTERN
1232 ibool
1234 /*==========*/
1235  const THD* thd)
1236 {
1237  return(thd_sql_command(thd) == SQLCOM_SELECT);
1238 }
1239 
1240 /******************************************************************/
1244 UNIV_INTERN
1245 ibool
1247 /*============*/
1248  THD* thd)
1250 {
1251  return(THDVAR(thd, support_xa));
1252 }
1253 
1254 /******************************************************************/
1257 UNIV_INTERN
1258 ulong
1260 /*==================*/
1261  THD* thd)
1263 {
1264  /* According to <mysql/plugin.h>, passing thd == NULL
1265  returns the global value of the session variable. */
1266  return(THDVAR(thd, lock_wait_timeout));
1267 }
1268 
1269 /******************************************************************/
1271 UNIV_INTERN
1272 void
1274 /*===================*/
1275  THD* thd,
1276  ulint value)
1277 {
1278  if (thd) {
1279  thd_storage_lock_wait(thd, value);
1280  }
1281 }
1282 
1283 /********************************************************************/
1286 __attribute__((warn_unused_result, nonnull))
1287 static inline
1288 trx_t*&
1289 thd_to_trx(
1290 /*=======*/
1291  THD* thd)
1292 {
1293  return(*(trx_t**) thd_ha_data(thd, innodb_hton_ptr));
1294 }
1295 
1296 /********************************************************************/
1301 static
1302 int
1303 innobase_release_temporary_latches(
1304 /*===============================*/
1305  handlerton* hton,
1306  THD* thd)
1307 {
1308  DBUG_ASSERT(hton == innodb_hton_ptr);
1309 
1310  if (!innodb_inited) {
1311 
1312  return(0);
1313  }
1314 
1315  trx_t* trx = thd_to_trx(thd);
1316 
1317  if (trx != NULL) {
1319  }
1320 
1321  return(0);
1322 }
1323 
1324 /********************************************************************/
1329 static inline
1330 void
1331 innobase_active_small(void)
1332 /*=======================*/
1333 {
1334  innobase_active_counter++;
1335 
1336  if ((innobase_active_counter % INNOBASE_WAKE_INTERVAL) == 0) {
1338  }
1339 }
1340 
1341 /********************************************************************/
1346 static
1347 int
1348 convert_error_code_to_mysql(
1349 /*========================*/
1350  dberr_t error,
1351  ulint flags,
1352  THD* thd)
1353 {
1354  switch (error) {
1355  case DB_SUCCESS:
1356  return(0);
1357 
1358  case DB_INTERRUPTED:
1359  my_error(ER_QUERY_INTERRUPTED, MYF(0));
1360  return(-1);
1361 
1363  ut_ad(thd);
1364  push_warning_printf(thd, Sql_condition::WARN_LEVEL_WARN,
1365  HA_ERR_ROW_IS_REFERENCED,
1366  "InnoDB: Cannot delete/update "
1367  "rows with cascading foreign key "
1368  "constraints that exceed max "
1369  "depth of %d. Please "
1370  "drop extra constraints and try "
1371  "again", DICT_FK_MAX_RECURSIVE_LOAD);
1372 
1373  /* fall through */
1374 
1375  case DB_ERROR:
1376  default:
1377  return(-1); /* unspecified error */
1378 
1379  case DB_DUPLICATE_KEY:
1380  /* Be cautious with returning this error, since
1381  mysql could re-enter the storage layer to get
1382  duplicated key info, the operation requires a
1383  valid table handle and/or transaction information,
1384  which might not always be available in the error
1385  handling stage. */
1386  return(HA_ERR_FOUND_DUPP_KEY);
1387 
1388  case DB_READ_ONLY:
1389  return(HA_ERR_TABLE_READONLY);
1390 
1392  return(HA_ERR_FOREIGN_DUPLICATE_KEY);
1393 
1394  case DB_MISSING_HISTORY:
1395  return(HA_ERR_TABLE_DEF_CHANGED);
1396 
1397  case DB_RECORD_NOT_FOUND:
1398  return(HA_ERR_NO_ACTIVE_RECORD);
1399 
1400  case DB_DEADLOCK:
1401  /* Since we rolled back the whole transaction, we must
1402  tell it also to MySQL so that MySQL knows to empty the
1403  cached binlog for this transaction */
1404 
1405  if (thd) {
1406  thd_mark_transaction_to_rollback(thd, TRUE);
1407  }
1408 
1409  return(HA_ERR_LOCK_DEADLOCK);
1410 
1411  case DB_LOCK_WAIT_TIMEOUT:
1412  /* Starting from 5.0.13, we let MySQL just roll back the
1413  latest SQL statement in a lock wait timeout. Previously, we
1414  rolled back the whole transaction. */
1415 
1416  if (thd) {
1417  thd_mark_transaction_to_rollback(
1418  thd, (bool) row_rollback_on_timeout);
1419  }
1420 
1421  return(HA_ERR_LOCK_WAIT_TIMEOUT);
1422 
1423  case DB_NO_REFERENCED_ROW:
1424  return(HA_ERR_NO_REFERENCED_ROW);
1425 
1426  case DB_ROW_IS_REFERENCED:
1427  return(HA_ERR_ROW_IS_REFERENCED);
1428 
1430  case DB_CHILD_NO_INDEX:
1431  case DB_PARENT_NO_INDEX:
1432  return(HA_ERR_CANNOT_ADD_FOREIGN);
1433 
1435 
1436  return(HA_ERR_ROW_IS_REFERENCED); /* TODO: This is a bit
1437  misleading, a new MySQL error
1438  code should be introduced */
1439 
1440  case DB_CORRUPTION:
1441  return(HA_ERR_CRASHED);
1442 
1443  case DB_OUT_OF_FILE_SPACE:
1444  return(HA_ERR_RECORD_FILE_FULL);
1445 
1446  case DB_TABLE_IN_FK_CHECK:
1447  return(HA_ERR_TABLE_IN_FK_CHECK);
1448 
1449  case DB_TABLE_IS_BEING_USED:
1450  return(HA_ERR_WRONG_COMMAND);
1451 
1452  case DB_TABLESPACE_DELETED:
1453  case DB_TABLE_NOT_FOUND:
1454  return(HA_ERR_NO_SUCH_TABLE);
1455 
1456  case DB_TABLESPACE_NOT_FOUND:
1457  return(HA_ERR_NO_SUCH_TABLE);
1458 
1459  case DB_TOO_BIG_RECORD: {
1460  /* If prefix is true then a 768-byte prefix is stored
1461  locally for BLOB fields. Refer to dict_table_get_format() */
1462  bool prefix = (dict_tf_get_format(flags) == UNIV_FORMAT_A);
1463  my_printf_error(ER_TOO_BIG_ROWSIZE,
1464  "Row size too large (> %lu). Changing some columns "
1465  "to TEXT or BLOB %smay help. In current row "
1466  "format, BLOB prefix of %d bytes is stored inline.",
1467  MYF(0),
1469  DICT_TF_COMPACT) / 2,
1470  prefix ? "or using ROW_FORMAT=DYNAMIC "
1471  "or ROW_FORMAT=COMPRESSED ": "",
1472  prefix ? DICT_MAX_FIXED_COL_LEN : 0);
1473  return(HA_ERR_TO_BIG_ROW);
1474  }
1475 
1476  case DB_TOO_BIG_INDEX_COL:
1477  my_error(ER_INDEX_COLUMN_TOO_LONG, MYF(0),
1478  DICT_MAX_FIELD_LEN_BY_FORMAT_FLAG(flags));
1479  return(HA_ERR_INDEX_COL_TOO_LONG);
1480 
1481  case DB_NO_SAVEPOINT:
1482  return(HA_ERR_NO_SAVEPOINT);
1483 
1484  case DB_LOCK_TABLE_FULL:
1485  /* Since we rolled back the whole transaction, we must
1486  tell it also to MySQL so that MySQL knows to empty the
1487  cached binlog for this transaction */
1488 
1489  if (thd) {
1490  thd_mark_transaction_to_rollback(thd, TRUE);
1491  }
1492 
1493  return(HA_ERR_LOCK_TABLE_FULL);
1494 
1495  case DB_FTS_INVALID_DOCID:
1496  return(HA_FTS_INVALID_DOCID);
1498  return(HA_ERR_FTS_EXCEED_RESULT_CACHE_LIMIT);
1500  return(HA_ERR_TOO_MANY_CONCURRENT_TRXS);
1501  case DB_UNSUPPORTED:
1502  return(HA_ERR_UNSUPPORTED);
1503  case DB_INDEX_CORRUPT:
1504  return(HA_ERR_INDEX_CORRUPT);
1506  return(HA_ERR_UNDO_REC_TOO_BIG);
1507  case DB_OUT_OF_MEMORY:
1508  return(HA_ERR_OUT_OF_MEM);
1509  case DB_TABLESPACE_EXISTS:
1510  return(HA_ERR_TABLESPACE_EXISTS);
1512  return(HA_ERR_INTERNAL_ERROR);
1513  }
1514 }
1515 
1516 /*************************************************************/
1518 UNIV_INTERN
1519 void
1521 /*=====================*/
1522  FILE* f,
1523  THD* thd,
1524  uint max_query_len)
1526 {
1527  char buffer[1024];
1528 
1529  fputs(thd_security_context(thd, buffer, sizeof buffer,
1530  max_query_len), f);
1531  putc('\n', f);
1532 }
1533 
1534 /******************************************************************/
1537 UNIV_INTERN
1538 const char*
1540 /*=================*/
1541  int error_code)
1542 {
1543  return(my_get_err_msg(error_code));
1544 }
1545 
1546 /******************************************************************/
1548 UNIV_INTERN
1549 void
1551 /*====================*/
1552  ulint cset,
1553  ulint* mbminlen,
1554  ulint* mbmaxlen)
1555 {
1556  CHARSET_INFO* cs;
1557  ut_ad(cset <= MAX_CHAR_COLL_NUM);
1558  ut_ad(mbminlen);
1559  ut_ad(mbmaxlen);
1560 
1561  cs = all_charsets[cset];
1562  if (cs) {
1563  *mbminlen = cs->mbminlen;
1564  *mbmaxlen = cs->mbmaxlen;
1565  ut_ad(*mbminlen < DATA_MBMAX);
1566  ut_ad(*mbmaxlen < DATA_MBMAX);
1567  } else {
1568  THD* thd = current_thd;
1569 
1570  if (thd && thd_sql_command(thd) == SQLCOM_DROP_TABLE) {
1571 
1572  /* Fix bug#46256: allow tables to be dropped if the
1573  collation is not found, but issue a warning. */
1574  if ((log_warnings)
1575  && (cset != 0)){
1576 
1577  sql_print_warning(
1578  "Unknown collation #%lu.", cset);
1579  }
1580  } else {
1581 
1582  ut_a(cset == 0);
1583  }
1584 
1585  *mbminlen = *mbmaxlen = 0;
1586  }
1587 }
1588 
1589 /******************************************************************/
1591 UNIV_INTERN
1592 void
1594 /*===========================*/
1595  struct charset_info_st* cs,
1596  char* to,
1597  const char* from,
1598  ulint len)
1599 {
1600  uint errors;
1601 
1602  strconvert(cs, from, &my_charset_filename, to, (uint) len, &errors);
1603 }
1604 
1605 /**********************************************************************
1606 Check if the length of the identifier exceeds the maximum allowed.
1607 return true when length of identifier is too long. */
1608 UNIV_INTERN
1609 my_bool
1610 innobase_check_identifier_length(
1611 /*=============================*/
1612  const char* id) /* in: FK identifier to check excluding the
1613  database portion. */
1614 {
1615  int well_formed_error = 0;
1616  CHARSET_INFO *cs = system_charset_info;
1617  DBUG_ENTER("innobase_check_identifier_length");
1618 
1619  uint res = cs->cset->well_formed_len(cs, id, id + strlen(id),
1620  NAME_CHAR_LEN,
1621  &well_formed_error);
1622 
1623  if (well_formed_error || res == NAME_CHAR_LEN) {
1624  my_error(ER_TOO_LONG_IDENT, MYF(0), id);
1625  DBUG_RETURN(true);
1626  }
1627  DBUG_RETURN(false);
1628 }
1629 
1630 /******************************************************************/
1632 UNIV_INTERN
1633 void
1635 /*=====================*/
1636  struct charset_info_st* cs,
1637  char* to,
1638  const char* from,
1639  ulint len)
1640 {
1641  uint errors;
1642 
1643  strconvert(cs, from, system_charset_info, to, (uint) len, &errors);
1644 }
1645 
1646 /******************************************************************/
1649 UNIV_INTERN
1650 int
1652 /*================*/
1653  const char* a,
1654  const char* b)
1655 {
1656  if (!a) {
1657  if (!b) {
1658  return(0);
1659  } else {
1660  return(-1);
1661  }
1662  } else if (!b) {
1663  return(1);
1664  }
1665 
1666  return(my_strcasecmp(system_charset_info, a, b));
1667 }
1668 
1669 /******************************************************************/
1673 UNIV_INTERN
1674 int
1676 /*=================*/
1677  const char* a,
1678  const char* b)
1679 {
1680  return(wild_case_compare(system_charset_info, a, b));
1681 }
1682 
1683 /******************************************************************/
1686 UNIV_INTERN
1687 const char*
1689 /*==============*/
1690  const char* path_name)
1691 {
1692  const char* name = base_name(path_name);
1693 
1694  return((name) ? name : "null");
1695 }
1696 
1697 /******************************************************************/
1699 UNIV_INTERN
1700 void
1702 /*================*/
1703  char* a)
1704 {
1705  my_casedn_str(system_charset_info, a);
1706 }
1707 
1708 /**********************************************************************/
1711 UNIV_INTERN
1712 struct charset_info_st*
1714 /*=================*/
1715  THD* mysql_thd)
1716 {
1717  return(thd_charset(mysql_thd));
1718 }
1719 
1720 /**********************************************************************/
1723 UNIV_INTERN
1724 const char*
1726 /*==============*/
1727  THD* thd,
1728  size_t* length)
1729 {
1730  LEX_STRING* stmt;
1731 
1732  stmt = thd_query_string(thd);
1733  *length = stmt->length;
1734  return(stmt->str);
1735 }
1736 
1737 /**********************************************************************/
1742 UNIV_INTERN
1743 ulint
1745 /*===============================*/
1746 {
1747  return(table_def_size);
1748 }
1749 
1750 /**********************************************************************/
1756 UNIV_INTERN
1757 ulint
1759 /*=====================================*/
1760 {
1761  return(lower_case_table_names);
1762 }
1763 
1764 /*********************************************************************/
1767 UNIV_INTERN
1768 int
1770 /*========================*/
1771 {
1772  int fd2 = -1;
1773  File fd;
1774 
1775  DBUG_EXECUTE_IF(
1776  "innobase_tmpfile_creation_failure",
1777  return(-1);
1778  );
1779 
1780  fd = mysql_tmpfile("ib");
1781 
1782  if (fd >= 0) {
1783  /* Copy the file descriptor, so that the additional resources
1784  allocated by create_temp_file() can be freed by invoking
1785  my_close().
1786 
1787  Because the file descriptor returned by this function
1788  will be passed to fdopen(), it will be closed by invoking
1789  fclose(), which in turn will invoke close() instead of
1790  my_close(). */
1791 
1792 #ifdef _WIN32
1793  /* Note that on Windows, the integer returned by mysql_tmpfile
1794  has no relation to C runtime file descriptor. Here, we need
1795  to call my_get_osfhandle to get the HANDLE and then convert it
1796  to C runtime filedescriptor. */
1797  {
1798  HANDLE hFile = my_get_osfhandle(fd);
1799  HANDLE hDup;
1800  BOOL bOK = DuplicateHandle(
1801  GetCurrentProcess(),
1802  hFile, GetCurrentProcess(),
1803  &hDup, 0, FALSE, DUPLICATE_SAME_ACCESS);
1804  if (bOK) {
1805  fd2 = _open_osfhandle((intptr_t) hDup, 0);
1806  } else {
1807  my_osmaperr(GetLastError());
1808  fd2 = -1;
1809  }
1810  }
1811 #else
1812  fd2 = dup(fd);
1813 #endif
1814  if (fd2 < 0) {
1815  char errbuf[MYSYS_STRERROR_SIZE];
1816  DBUG_PRINT("error",("Got error %d on dup",fd2));
1817  my_errno=errno;
1818  my_error(EE_OUT_OF_FILERESOURCES,
1819  MYF(ME_BELL+ME_WAITTANG),
1820  "ib*", my_errno,
1821  my_strerror(errbuf, sizeof(errbuf), my_errno));
1822  }
1823  my_close(fd, MYF(MY_WME));
1824  }
1825  return(fd2);
1826 }
1827 
1828 /*********************************************************************/
1831 UNIV_INTERN
1832 ulint
1834 /*====================*/
1835  void* to,
1836  ulint to_length,
1838  CHARSET_INFO* to_cs,
1839  const void* from,
1840  ulint from_length,
1841  CHARSET_INFO* from_cs,
1843  uint* errors)
1845 {
1846  return(copy_and_convert(
1847  (char*) to, (uint32) to_length, to_cs,
1848  (const char*) from, (uint32) from_length, from_cs,
1849  errors));
1850 }
1851 
1852 /*******************************************************************/
1861 UNIV_INTERN
1862 ulint
1864 /*================*/
1865  const char* data,
1866  ulint data_len,
1868  ulint charset_coll,
1869  char* buf,
1870  ulint buf_size)
1872 {
1873  /* XXX we use a hard limit instead of allocating
1874  but_size bytes from the heap */
1875  CHARSET_INFO* data_cs;
1876  char buf_tmp[8192];
1877  ulint buf_tmp_used;
1878  uint num_errors;
1879 
1880  data_cs = all_charsets[charset_coll];
1881 
1882  buf_tmp_used = innobase_convert_string(buf_tmp, sizeof(buf_tmp),
1883  system_charset_info,
1884  data, data_len, data_cs,
1885  &num_errors);
1886 
1887  return(ut_str_sql_format(buf_tmp, buf_tmp_used, buf, buf_size));
1888 }
1889 
1890 /*********************************************************************/
1908 UNIV_INTERN
1909 ulonglong
1911 /*==================*/
1912  ulonglong current,
1913  ulonglong need,
1914  ulonglong step,
1915  ulonglong offset,
1916  ulonglong max_value)
1917 {
1918  ulonglong next_value;
1919  ulonglong block = need * step;
1920 
1921  /* Should never be 0. */
1922  ut_a(need > 0);
1923  ut_a(block > 0);
1924  ut_a(max_value > 0);
1925 
1926  /* According to MySQL documentation, if the offset is greater than
1927  the step then the offset is ignored. */
1928  if (offset > block) {
1929  offset = 0;
1930  }
1931 
1932  /* Check for overflow. Current can be > max_value if the value is
1933  in reality a negative value.The visual studio compilers converts
1934  large double values automatically into unsigned long long datatype
1935  maximum value */
1936 
1937  if (block >= max_value
1938  || offset > max_value
1939  || current >= max_value
1940  || max_value - offset <= offset) {
1941 
1942  next_value = max_value;
1943  } else {
1944  ut_a(max_value > current);
1945 
1946  ulonglong free = max_value - current;
1947 
1948  if (free < offset || free - offset <= block) {
1949  next_value = max_value;
1950  } else {
1951  next_value = 0;
1952  }
1953  }
1954 
1955  if (next_value == 0) {
1956  ulonglong next;
1957 
1958  if (current > offset) {
1959  next = (current - offset) / step;
1960  } else {
1961  next = (offset - current) / step;
1962  }
1963 
1964  ut_a(max_value > next);
1965  next_value = next * step;
1966  /* Check for multiplication overflow. */
1967  ut_a(next_value >= next);
1968  ut_a(max_value > next_value);
1969 
1970  /* Check for overflow */
1971  if (max_value - next_value >= block) {
1972 
1973  next_value += block;
1974 
1975  if (max_value - next_value >= offset) {
1976  next_value += offset;
1977  } else {
1978  next_value = max_value;
1979  }
1980  } else {
1981  next_value = max_value;
1982  }
1983  }
1984 
1985  ut_a(next_value != 0);
1986  ut_a(next_value <= max_value);
1987 
1988  return(next_value);
1989 }
1990 
1991 /*********************************************************************/
1993 static
1994 void
1995 innobase_trx_init(
1996 /*==============*/
1997  THD* thd,
1998  trx_t* trx)
1999 {
2000  DBUG_ENTER("innobase_trx_init");
2001  DBUG_ASSERT(EQ_CURRENT_THD(thd));
2002  DBUG_ASSERT(thd == trx->mysql_thd);
2003 
2004  trx->check_foreigns = !thd_test_options(
2006 
2007  trx->check_unique_secondary = !thd_test_options(
2009 
2010  DBUG_VOID_RETURN;
2011 }
2012 
2013 /*********************************************************************/
2016 UNIV_INTERN
2017 trx_t*
2019 /*==================*/
2020  THD* thd)
2021 {
2022  trx_t* trx;
2023 
2024  DBUG_ENTER("innobase_trx_allocate");
2025  DBUG_ASSERT(thd != NULL);
2026  DBUG_ASSERT(EQ_CURRENT_THD(thd));
2027 
2028  trx = trx_allocate_for_mysql();
2029 
2030  trx->mysql_thd = thd;
2031 
2032  innobase_trx_init(thd, trx);
2033 
2034  DBUG_RETURN(trx);
2035 }
2036 
2037 /*********************************************************************/
2042 static inline
2043 trx_t*
2044 check_trx_exists(
2045 /*=============*/
2046  THD* thd)
2047 {
2048  trx_t*& trx = thd_to_trx(thd);
2049 
2050  ut_ad(EQ_CURRENT_THD(thd));
2051 
2052  if (trx == NULL) {
2053  trx = innobase_trx_allocate(thd);
2054  } else if (UNIV_UNLIKELY(trx->magic_n != TRX_MAGIC_N)) {
2056  ut_error;
2057  }
2058 
2059  innobase_trx_init(thd, trx);
2060 
2061  return(trx);
2062 }
2063 
2064 /*********************************************************************/
2067 static inline
2068 bool
2069 trx_is_registered_for_2pc(
2070 /*=========================*/
2071  const trx_t* trx) /* in: transaction */
2072 {
2073  return(trx->is_registered == 1);
2074 }
2075 
2076 /*********************************************************************/
2078 static inline
2079 void
2080 trx_register_for_2pc(
2081 /*==================*/
2082  trx_t* trx) /* in: transaction */
2083 {
2084  trx->is_registered = 1;
2085  ut_ad(trx->owns_prepare_mutex == 0);
2086 }
2087 
2088 /*********************************************************************/
2090 static inline
2091 void
2092 trx_deregister_from_2pc(
2093 /*====================*/
2094  trx_t* trx) /* in: transaction */
2095 {
2096  trx->is_registered = 0;
2097  trx->owns_prepare_mutex = 0;
2098 }
2099 
2100 
2101 /*********************************************************************/
2104 static
2105 bool
2106 trx_is_started(
2107 /*===========*/
2108  trx_t* trx) /* in: transaction */
2109 {
2110  return(trx->state != TRX_STATE_NOT_STARTED);
2111 }
2112 
2113 /*********************************************************************/
2118 UNIV_INTERN
2119 void
2121 /*=====================================*/
2122  dict_table_t* innodb_table,
2123  const HA_CREATE_INFO* create_info)
2124 {
2125  ibool ps_on;
2126  ibool ps_off;
2127 
2128  if (dict_table_is_temporary(innodb_table)) {
2129  /* Temp tables do not use persistent stats. */
2130  ps_on = FALSE;
2131  ps_off = TRUE;
2132  } else {
2133  ps_on = create_info->table_options
2134  & HA_OPTION_STATS_PERSISTENT;
2135  ps_off = create_info->table_options
2136  & HA_OPTION_NO_STATS_PERSISTENT;
2137  }
2138 
2139  dict_stats_set_persistent(innodb_table, ps_on, ps_off);
2140 
2142  innodb_table,
2143  create_info->stats_auto_recalc == HA_STATS_AUTO_RECALC_ON,
2144  create_info->stats_auto_recalc == HA_STATS_AUTO_RECALC_OFF);
2145 
2146  innodb_table->stats_sample_pages = create_info->stats_sample_pages;
2147 }
2148 
2149 /*********************************************************************/
2154 UNIV_INTERN
2155 void
2157 /*=====================================*/
2158  dict_table_t* innodb_table,
2159  const TABLE_SHARE* table_share)
2160 {
2161  ibool ps_on;
2162  ibool ps_off;
2163 
2164  if (dict_table_is_temporary(innodb_table)) {
2165  /* Temp tables do not use persistent stats */
2166  ps_on = FALSE;
2167  ps_off = TRUE;
2168  } else {
2169  ps_on = table_share->db_create_options
2170  & HA_OPTION_STATS_PERSISTENT;
2171  ps_off = table_share->db_create_options
2172  & HA_OPTION_NO_STATS_PERSISTENT;
2173  }
2174 
2175  dict_stats_set_persistent(innodb_table, ps_on, ps_off);
2176 
2178  innodb_table,
2179  table_share->stats_auto_recalc == HA_STATS_AUTO_RECALC_ON,
2180  table_share->stats_auto_recalc == HA_STATS_AUTO_RECALC_OFF);
2181 
2182  innodb_table->stats_sample_pages = table_share->stats_sample_pages;
2183 }
2184 
2185 /*********************************************************************/
2187 UNIV_INTERN
2189 /*=====================*/
2190  handlerton* hton,
2191  TABLE_SHARE* table_arg)
2192  :handler(hton, table_arg),
2193  int_table_flags(HA_REC_NOT_IN_SEQ |
2194  HA_NULL_IN_KEY |
2195  HA_CAN_INDEX_BLOBS |
2196  HA_CAN_SQL_HANDLER |
2197  HA_PRIMARY_KEY_REQUIRED_FOR_POSITION |
2198  HA_PRIMARY_KEY_IN_READ_INDEX |
2199  HA_BINLOG_ROW_CAPABLE |
2200  HA_CAN_GEOMETRY | HA_PARTIAL_COLUMN_READ |
2201  HA_TABLE_SCAN_ON_INDEX | HA_CAN_FULLTEXT |
2202  HA_CAN_FULLTEXT_EXT | HA_CAN_EXPORT),
2203  start_of_scan(0),
2204  num_write_row(0)
2205 {}
2206 
2207 /*********************************************************************/
2209 UNIV_INTERN
2211 /*======================*/
2212 {
2213 }
2214 
2215 /*********************************************************************/
2219 UNIV_INTERN inline
2220 void
2221 ha_innobase::update_thd(
2222 /*====================*/
2223  THD* thd)
2224 {
2225  trx_t* trx;
2226 
2227  DBUG_ENTER("ha_innobase::update_thd");
2228  DBUG_PRINT("ha_innobase::update_thd", ("user_thd: %p -> %p",
2229  user_thd, thd));
2230 
2231  /* The table should have been opened in ha_innobase::open(). */
2232  DBUG_ASSERT(prebuilt->table->n_ref_count > 0);
2233 
2234  trx = check_trx_exists(thd);
2235 
2236  if (prebuilt->trx != trx) {
2237 
2238  row_update_prebuilt_trx(prebuilt, trx);
2239  }
2240 
2241  user_thd = thd;
2242  DBUG_VOID_RETURN;
2243 }
2244 
2245 /*********************************************************************/
2249 UNIV_INTERN
2250 void
2251 ha_innobase::update_thd()
2252 /*=====================*/
2253 {
2254  THD* thd = ha_thd();
2255 
2256  ut_ad(EQ_CURRENT_THD(thd));
2257  update_thd(thd);
2258 }
2259 
2260 /*********************************************************************/
2267 static inline
2268 void
2269 innobase_register_trx(
2270 /*==================*/
2271  handlerton* hton, /* in: Innobase handlerton */
2272  THD* thd, /* in: MySQL thd (connection) object */
2273  trx_t* trx) /* in: transaction to register */
2274 {
2275  trans_register_ha(thd, FALSE, hton);
2276 
2277  if (!trx_is_registered_for_2pc(trx)
2278  && thd_test_options(thd, OPTION_NOT_AUTOCOMMIT | OPTION_BEGIN)) {
2279 
2280  trans_register_ha(thd, TRUE, hton);
2281  }
2282 
2283  trx_register_for_2pc(trx);
2284 }
2285 
2286 /* BACKGROUND INFO: HOW THE MYSQL QUERY CACHE WORKS WITH INNODB
2287  ------------------------------------------------------------
2288 
2289 1) The use of the query cache for TBL is disabled when there is an
2290 uncommitted change to TBL.
2291 
2292 2) When a change to TBL commits, InnoDB stores the current value of
2293 its global trx id counter, let us denote it by INV_TRX_ID, to the table object
2294 in the InnoDB data dictionary, and does only allow such transactions whose
2295 id <= INV_TRX_ID to use the query cache.
2296 
2297 3) When InnoDB does an INSERT/DELETE/UPDATE to a table TBL, or an implicit
2298 modification because an ON DELETE CASCADE, we invalidate the MySQL query cache
2299 of TBL immediately.
2300 
2301 How this is implemented inside InnoDB:
2302 
2303 1) Since every modification always sets an IX type table lock on the InnoDB
2304 table, it is easy to check if there can be uncommitted modifications for a
2305 table: just check if there are locks in the lock list of the table.
2306 
2307 2) When a transaction inside InnoDB commits, it reads the global trx id
2308 counter and stores the value INV_TRX_ID to the tables on which it had a lock.
2309 
2310 3) If there is an implicit table change from ON DELETE CASCADE or SET NULL,
2311 InnoDB calls an invalidate method for the MySQL query cache for that table.
2312 
2313 How this is implemented inside sql_cache.cc:
2314 
2315 1) The query cache for an InnoDB table TBL is invalidated immediately at an
2316 INSERT/UPDATE/DELETE, just like in the case of MyISAM. No need to delay
2317 invalidation to the transaction commit.
2318 
2319 2) To store or retrieve a value from the query cache of an InnoDB table TBL,
2320 any query must first ask InnoDB's permission. We must pass the thd as a
2321 parameter because InnoDB will look at the trx id, if any, associated with
2322 that thd. Also the full_name which is used as key to search for the table
2323 object. The full_name is a string containing the normalized path to the
2324 table in the canonical format.
2325 
2326 3) Use of the query cache for InnoDB tables is now allowed also when
2327 AUTOCOMMIT==0 or we are inside BEGIN ... COMMIT. Thus transactions no longer
2328 put restrictions on the use of the query cache.
2329 */
2330 
2331 /******************************************************************/
2352 static
2353 my_bool
2354 innobase_query_caching_of_table_permitted(
2355 /*======================================*/
2356  THD* thd,
2359  char* full_name,
2360  uint full_name_len,
2362  ulonglong *unused)
2363 {
2364  ibool is_autocommit;
2365  trx_t* trx;
2366  char norm_name[1000];
2367 
2368  ut_a(full_name_len < 999);
2369 
2370  trx = check_trx_exists(thd);
2371 
2372  if (trx->isolation_level == TRX_ISO_SERIALIZABLE) {
2373  /* In the SERIALIZABLE mode we add LOCK IN SHARE MODE to every
2374  plain SELECT if AUTOCOMMIT is not on. */
2375 
2376  return((my_bool)FALSE);
2377  }
2378 
2379  if (UNIV_UNLIKELY(trx->has_search_latch)) {
2380  sql_print_error("The calling thread is holding the adaptive "
2381  "search, latch though calling "
2382  "innobase_query_caching_of_table_permitted.");
2383  trx_print(stderr, trx, 1024);
2384  }
2385 
2387 
2388  innobase_srv_conc_force_exit_innodb(trx);
2389 
2390  if (!thd_test_options(thd, OPTION_NOT_AUTOCOMMIT | OPTION_BEGIN)) {
2391 
2392  is_autocommit = TRUE;
2393  } else {
2394  is_autocommit = FALSE;
2395 
2396  }
2397 
2398  if (is_autocommit && trx->n_mysql_tables_in_use == 0) {
2399  /* We are going to retrieve the query result from the query
2400  cache. This cannot be a store operation to the query cache
2401  because then MySQL would have locks on tables already.
2402 
2403  TODO: if the user has used LOCK TABLES to lock the table,
2404  then we open a transaction in the call of row_.. below.
2405  That trx can stay open until UNLOCK TABLES. The same problem
2406  exists even if we do not use the query cache. MySQL should be
2407  modified so that it ALWAYS calls some cleanup function when
2408  the processing of a query ends!
2409 
2410  We can imagine we instantaneously serialize this consistent
2411  read trx to the current trx id counter. If trx2 would have
2412  changed the tables of a query result stored in the cache, and
2413  trx2 would have already committed, making the result obsolete,
2414  then trx2 would have already invalidated the cache. Thus we
2415  can trust the result in the cache is ok for this query. */
2416 
2417  return((my_bool)TRUE);
2418  }
2419 
2420  /* Normalize the table name to InnoDB format */
2421  normalize_table_name(norm_name, full_name);
2422 
2423  innobase_register_trx(innodb_hton_ptr, thd, trx);
2424 
2425  if (row_search_check_if_query_cache_permitted(trx, norm_name)) {
2426 
2427  /* printf("Query cache for %s permitted\n", norm_name); */
2428 
2429  return((my_bool)TRUE);
2430  }
2431 
2432  /* printf("Query cache for %s NOT permitted\n", norm_name); */
2433 
2434  return((my_bool)FALSE);
2435 }
2436 
2437 /*****************************************************************/
2439 UNIV_INTERN
2440 void
2442 /*============================*/
2443  trx_t* trx,
2445  const char* full_name,
2450  ulint full_name_len)
2452 {
2453  /* Note that the sync0sync.h rank of the query cache mutex is just
2454  above the InnoDB trx_sys_t->lock. The caller of this function must
2455  not have latches of a lower rank. */
2456 
2457  /* Argument TRUE below means we are using transactions */
2458 #ifdef HAVE_QUERY_CACHE
2459  mysql_query_cache_invalidate4(trx->mysql_thd,
2460  full_name,
2461  (uint32) full_name_len,
2462  TRUE);
2463 #endif
2464 }
2465 
2466 /*****************************************************************/
2470 static
2471 char*
2472 innobase_convert_identifier(
2473 /*========================*/
2474  char* buf,
2475  ulint buflen,
2476  const char* id,
2477  ulint idlen,
2478  THD* thd,
2479  ibool file_id)
2481 {
2482  const char* s = id;
2483  int q;
2484 
2485  if (file_id) {
2486 
2487  char nz[MAX_TABLE_NAME_LEN + 1];
2488  char nz2[MAX_TABLE_NAME_LEN + 1];
2489 
2490  /* Decode the table name. The MySQL function expects
2491  a NUL-terminated string. The input and output strings
2492  buffers must not be shared. */
2493  ut_a(idlen <= MAX_TABLE_NAME_LEN);
2494  memcpy(nz, id, idlen);
2495  nz[idlen] = 0;
2496 
2497  s = nz2;
2498  idlen = explain_filename(thd, nz, nz2, sizeof nz2,
2499  EXPLAIN_PARTITIONS_AS_COMMENT);
2500  goto no_quote;
2501  }
2502 
2503  /* See if the identifier needs to be quoted. */
2504  if (UNIV_UNLIKELY(!thd)) {
2505  q = '"';
2506  } else {
2507  q = get_quote_char_for_identifier(thd, s, (int) idlen);
2508  }
2509 
2510  if (q == EOF) {
2511 no_quote:
2512  if (UNIV_UNLIKELY(idlen > buflen)) {
2513  idlen = buflen;
2514  }
2515  memcpy(buf, s, idlen);
2516  return(buf + idlen);
2517  }
2518 
2519  /* Quote the identifier. */
2520  if (buflen < 2) {
2521  return(buf);
2522  }
2523 
2524  *buf++ = q;
2525  buflen--;
2526 
2527  for (; idlen; idlen--) {
2528  int c = *s++;
2529  if (UNIV_UNLIKELY(c == q)) {
2530  if (UNIV_UNLIKELY(buflen < 3)) {
2531  break;
2532  }
2533 
2534  *buf++ = c;
2535  *buf++ = c;
2536  buflen -= 2;
2537  } else {
2538  if (UNIV_UNLIKELY(buflen < 2)) {
2539  break;
2540  }
2541 
2542  *buf++ = c;
2543  buflen--;
2544  }
2545  }
2546 
2547  *buf++ = q;
2548  return(buf);
2549 }
2550 
2551 /*****************************************************************/
2555 UNIV_INTERN
2556 char*
2558 /*==================*/
2559  char* buf,
2560  ulint buflen,
2561  const char* id,
2562  ulint idlen,
2563  THD* thd,
2564  ibool table_id)
2566 {
2567  char* s = buf;
2568  const char* bufend = buf + buflen;
2569 
2570  if (table_id) {
2571  const char* slash = (const char*) memchr(id, '/', idlen);
2572  if (!slash) {
2573 
2574  goto no_db_name;
2575  }
2576 
2577  /* Print the database name and table name separately. */
2578  s = innobase_convert_identifier(s, bufend - s, id, slash - id,
2579  thd, TRUE);
2580  if (UNIV_LIKELY(s < bufend)) {
2581  *s++ = '.';
2582  s = innobase_convert_identifier(s, bufend - s,
2583  slash + 1, idlen
2584  - (slash - id) - 1,
2585  thd, TRUE);
2586  }
2587  } else if (UNIV_UNLIKELY(*id == TEMP_INDEX_PREFIX)) {
2588  /* Temporary index name (smart ALTER TABLE) */
2589  const char temp_index_suffix[]= "--temporary--";
2590 
2591  s = innobase_convert_identifier(buf, buflen, id + 1, idlen - 1,
2592  thd, FALSE);
2593  if (s - buf + (sizeof temp_index_suffix - 1) < buflen) {
2594  memcpy(s, temp_index_suffix,
2595  sizeof temp_index_suffix - 1);
2596  s += sizeof temp_index_suffix - 1;
2597  }
2598  } else {
2599 no_db_name:
2600  s = innobase_convert_identifier(buf, buflen, id, idlen,
2601  thd, table_id);
2602  }
2603 
2604  return(s);
2605 }
2606 
2607 /*****************************************************************/
2611 UNIV_INTERN
2612 void
2614 /*==================*/
2615  char* buf,
2616  ulint buflen,
2617  const char* name,
2618  ibool is_index_name)
2619 {
2620  const char* bufend;
2621 
2622  bufend = innobase_convert_name(buf, buflen, name, strlen(name),
2623  NULL, !is_index_name);
2624 
2625  ut_ad((ulint) (bufend - buf) < buflen);
2626 
2627  buf[bufend - buf] = '\0';
2628 }
2629 
2630 /**********************************************************************/
2633 UNIV_INTERN
2634 ibool
2636 /*===============*/
2637  const trx_t* trx)
2638 {
2639  return(trx && trx->mysql_thd && thd_killed(trx->mysql_thd));
2640 }
2641 
2642 /**********************************************************************/
2645 UNIV_INTERN
2646 ibool
2648 /*==========*/
2649  trx_t* trx)
2650 {
2651  return(trx && trx->mysql_thd && THDVAR(trx->mysql_thd, strict_mode));
2652 }
2653 
2654 /**********************************************************************/
2658 UNIV_INLINE
2659 ibool
2661 /*==========*/
2662  THD* thd)
2663 {
2664  return(THDVAR(thd, strict_mode));
2665 }
2666 
2667 /**************************************************************/
2670 inline
2671 void
2672 ha_innobase::reset_template(void)
2673 /*=============================*/
2674 {
2675  ut_ad(prebuilt->magic_n == ROW_PREBUILT_ALLOCATED);
2676  ut_ad(prebuilt->magic_n2 == prebuilt->magic_n);
2677 
2678  prebuilt->keep_other_fields_on_keyread = 0;
2679  prebuilt->read_just_key = 0;
2680  prebuilt->in_fts_query = 0;
2681  /* Reset index condition pushdown state. */
2682  if (prebuilt->idx_cond) {
2683  prebuilt->idx_cond = NULL;
2684  prebuilt->idx_cond_n_cols = 0;
2685  /* Invalidate prebuilt->mysql_template
2686  in ha_innobase::write_row(). */
2687  prebuilt->template_type = ROW_MYSQL_NO_TEMPLATE;
2688  }
2689 }
2690 
2691 /*****************************************************************/
2697 UNIV_INTERN
2698 void
2700 /*============================================*/
2701 {
2702  /* If current thd does not yet have a trx struct, create one.
2703  If the current handle does not yet have a prebuilt struct, create
2704  one. Update the trx pointers in the prebuilt struct. Normally
2705  this operation is done in external_lock. */
2706 
2707  update_thd(ha_thd());
2708 
2709  /* Initialize the prebuilt struct much like it would be inited in
2710  external_lock */
2711 
2713 
2714  innobase_srv_conc_force_exit_innodb(prebuilt->trx);
2715 
2716  /* If the transaction is not started yet, start it */
2717 
2718  trx_start_if_not_started_xa(prebuilt->trx);
2719 
2720  /* Assign a read view if the transaction does not have it yet */
2721 
2722  trx_assign_read_view(prebuilt->trx);
2723 
2724  innobase_register_trx(ht, user_thd, prebuilt->trx);
2725 
2726  /* We did the necessary inits in this function, no need to repeat them
2727  in row_search_for_mysql */
2728 
2729  prebuilt->sql_stat_start = FALSE;
2730 
2731  /* We let HANDLER always to do the reads as consistent reads, even
2732  if the trx isolation level would have been specified as SERIALIZABLE */
2733 
2734  prebuilt->select_lock_type = LOCK_NONE;
2735  prebuilt->stored_select_lock_type = LOCK_NONE;
2736 
2737  /* Always fetch all columns in the index record */
2738 
2739  prebuilt->hint_need_to_fetch_extra_cols = ROW_RETRIEVE_ALL_COLS;
2740 
2741  /* We want always to fetch all columns in the whole row? Or do
2742  we???? */
2743 
2744  prebuilt->used_in_HANDLER = TRUE;
2745  reset_template();
2746 }
2747 
2748 /*********************************************************************/
2751 static
2752 int
2753 innobase_init(
2754 /*==========*/
2755  void *p)
2756 {
2757  static char current_dir[3];
2758  int err;
2759  bool ret;
2760  char *default_path;
2761  uint format_id;
2762  ulong num_pll_degree;
2763 
2764  DBUG_ENTER("innobase_init");
2765  handlerton *innobase_hton= (handlerton*) p;
2766  innodb_hton_ptr = innobase_hton;
2767 
2768  innobase_hton->state = SHOW_OPTION_YES;
2769  innobase_hton->db_type= DB_TYPE_INNODB;
2770  innobase_hton->savepoint_offset = sizeof(trx_named_savept_t);
2771  innobase_hton->close_connection = innobase_close_connection;
2772  innobase_hton->savepoint_set = innobase_savepoint;
2773  innobase_hton->savepoint_rollback = innobase_rollback_to_savepoint;
2774  innobase_hton->savepoint_release = innobase_release_savepoint;
2775  innobase_hton->commit = innobase_commit;
2776  innobase_hton->rollback = innobase_rollback;
2777  innobase_hton->prepare = innobase_xa_prepare;
2778  innobase_hton->recover = innobase_xa_recover;
2779  innobase_hton->commit_by_xid = innobase_commit_by_xid;
2780  innobase_hton->rollback_by_xid = innobase_rollback_by_xid;
2781  innobase_hton->create_cursor_read_view = innobase_create_cursor_view;
2782  innobase_hton->set_cursor_read_view = innobase_set_cursor_view;
2783  innobase_hton->close_cursor_read_view = innobase_close_cursor_view;
2784  innobase_hton->create = innobase_create_handler;
2785  innobase_hton->drop_database = innobase_drop_database;
2786  innobase_hton->panic = innobase_end;
2787 
2788  innobase_hton->start_consistent_snapshot =
2789  innobase_start_trx_and_assign_read_view;
2790 
2791  innobase_hton->flush_logs = innobase_flush_logs;
2792  innobase_hton->show_status = innobase_show_status;
2793  innobase_hton->flags = HTON_SUPPORTS_EXTENDED_KEYS;
2794 
2795  innobase_hton->release_temporary_latches =
2796  innobase_release_temporary_latches;
2797 
2798  innobase_hton->data = &innodb_api_cb;
2799 
2800  ut_a(DATA_MYSQL_TRUE_VARCHAR == (ulint)MYSQL_TYPE_VARCHAR);
2801 
2802 #ifndef DBUG_OFF
2803  static const char test_filename[] = "-@";
2804  char test_tablename[sizeof test_filename
2805  + sizeof(srv_mysql50_table_name_prefix) - 1];
2806  if ((sizeof(test_tablename)) - 1
2807  != filename_to_tablename(test_filename,
2808  test_tablename,
2809  sizeof(test_tablename), true)
2810  || strncmp(test_tablename,
2812  sizeof(srv_mysql50_table_name_prefix) - 1)
2813  || strcmp(test_tablename
2814  + sizeof(srv_mysql50_table_name_prefix) - 1,
2815  test_filename)) {
2816 
2817  sql_print_error("tablename encoding has been changed");
2818 
2819  goto error;
2820  }
2821 #endif /* DBUG_OFF */
2822 
2823  /* Check that values don't overflow on 32-bit systems. */
2824  if (sizeof(ulint) == 4) {
2825  if (innobase_buffer_pool_size > UINT_MAX32) {
2826  sql_print_error(
2827  "innobase_buffer_pool_size can't be over 4GB"
2828  " on 32-bit systems");
2829 
2830  goto error;
2831  }
2832  }
2833 
2834  os_innodb_umask = (ulint) my_umask;
2835 
2836  /* First calculate the default path for innodb_data_home_dir etc.,
2837  in case the user has not given any value.
2838 
2839  Note that when using the embedded server, the datadirectory is not
2840  necessarily the current directory of this program. */
2841 
2842  if (mysqld_embedded) {
2843  default_path = mysql_real_data_home;
2844  fil_path_to_mysql_datadir = mysql_real_data_home;
2845  } else {
2846  /* It's better to use current lib, to keep paths short */
2847  current_dir[0] = FN_CURLIB;
2848  current_dir[1] = FN_LIBCHAR;
2849  current_dir[2] = 0;
2850  default_path = current_dir;
2851  }
2852 
2853  ut_a(default_path);
2854 
2855  /* Set InnoDB initialization parameters according to the values
2856  read from MySQL .cnf file */
2857 
2858  /*--------------- Data files -------------------------*/
2859 
2860  /* The default dir for data files is the datadir of MySQL */
2861 
2862  srv_data_home = (innobase_data_home_dir ? innobase_data_home_dir :
2863  default_path);
2864 
2865  /* Set default InnoDB data file size to 12 MB and let it be
2866  auto-extending. Thus users can use InnoDB in >= 4.0 without having
2867  to specify any startup options. */
2868 
2869  if (!innobase_data_file_path) {
2870  innobase_data_file_path = (char*) "ibdata1:12M:autoextend";
2871  }
2872 
2873  /* Since InnoDB edits the argument in the next call, we make another
2874  copy of it: */
2875 
2876  internal_innobase_data_file_path = my_strdup(innobase_data_file_path,
2877  MYF(MY_FAE));
2878 
2880  internal_innobase_data_file_path);
2881  if (ret == FALSE) {
2882  sql_print_error(
2883  "InnoDB: syntax error in innodb_data_file_path");
2884 mem_free_and_error:
2886  my_free(internal_innobase_data_file_path);
2887  goto error;
2888  }
2889 
2890  /* -------------- All log files ---------------------------*/
2891 
2892  /* The default dir for log files is the datadir of MySQL */
2893 
2894  if (!srv_log_group_home_dir) {
2895  srv_log_group_home_dir = default_path;
2896  }
2897 
2898 #ifdef UNIV_LOG_ARCHIVE
2899  /* Since innodb_log_arch_dir has no relevance under MySQL,
2900  starting from 4.0.6 we always set it the same as
2901  innodb_log_group_home_dir: */
2902 
2903  innobase_log_arch_dir = innobase_log_group_home_dir;
2904 
2905  srv_arch_dir = innobase_log_arch_dir;
2906 #endif /* UNIG_LOG_ARCHIVE */
2907 
2908  srv_normalize_path_for_win(srv_log_group_home_dir);
2909 
2910  if (strchr(srv_log_group_home_dir, ';')) {
2911  sql_print_error("syntax error in innodb_log_group_home_dir");
2912  goto mem_free_and_error;
2913  }
2914 
2915  if (innobase_mirrored_log_groups == 1) {
2916  sql_print_warning(
2917  "innodb_mirrored_log_groups is an unimplemented "
2918  "feature and the variable will be completely "
2919  "removed in a future version.");
2920  }
2921 
2922  if (innobase_mirrored_log_groups > 1) {
2923  sql_print_error(
2924  "innodb_mirrored_log_groups is an unimplemented feature and "
2925  "the variable will be completely removed in a future version. "
2926  "Using values other than 1 is not supported.");
2927  goto mem_free_and_error;
2928  }
2929 
2930  if (innobase_mirrored_log_groups == 0) {
2931  /* To throw a deprecation warning message when the option is
2932  passed, the default was changed to '0' (as a workaround). Since
2933  the only value accepted for this option is '1', reset it to 1 */
2934  innobase_mirrored_log_groups = 1;
2935  }
2936 
2937  /* Validate the file format by animal name */
2938  if (innobase_file_format_name != NULL) {
2939 
2940  format_id = innobase_file_format_name_lookup(
2941  innobase_file_format_name);
2942 
2943  if (format_id > UNIV_FORMAT_MAX) {
2944 
2945  sql_print_error("InnoDB: wrong innodb_file_format.");
2946 
2947  goto mem_free_and_error;
2948  }
2949  } else {
2950  /* Set it to the default file format id. Though this
2951  should never happen. */
2952  format_id = 0;
2953  }
2954 
2955  srv_file_format = format_id;
2956 
2957  /* Given the type of innobase_file_format_name we have little
2958  choice but to cast away the constness from the returned name.
2959  innobase_file_format_name is used in the MySQL set variable
2960  interface and so can't be const. */
2961 
2962  innobase_file_format_name =
2963  (char*) trx_sys_file_format_id_to_name(format_id);
2964 
2965  /* Check innobase_file_format_check variable */
2966  if (!innobase_file_format_check) {
2967 
2968  /* Set the value to disable checking. */
2969  srv_max_file_format_at_startup = UNIV_FORMAT_MAX + 1;
2970 
2971  } else {
2972 
2973  /* Set the value to the lowest supported format. */
2974  srv_max_file_format_at_startup = UNIV_FORMAT_MIN;
2975  }
2976 
2977  /* Did the user specify a format name that we support?
2978  As a side effect it will update the variable
2979  srv_max_file_format_at_startup */
2980  if (innobase_file_format_validate_and_set(
2981  innobase_file_format_max) < 0) {
2982 
2983  sql_print_error("InnoDB: invalid "
2984  "innodb_file_format_max value: "
2985  "should be any value up to %s or its "
2986  "equivalent numeric id",
2988  UNIV_FORMAT_MAX));
2989 
2990  goto mem_free_and_error;
2991  }
2992 
2993  /* Remember stopword table name supplied at startup */
2994  if (innobase_server_stopword_table) {
2995  fts_server_stopword_table =
2996  my_strdup(innobase_server_stopword_table, MYF(0));
2997  }
2998 
2999  if (innobase_change_buffering) {
3000  ulint use;
3001 
3002  for (use = 0;
3003  use < UT_ARR_SIZE(innobase_change_buffering_values);
3004  use++) {
3005  if (!innobase_strcasecmp(
3006  innobase_change_buffering,
3007  innobase_change_buffering_values[use])) {
3008  ibuf_use = (ibuf_use_t) use;
3009  goto innobase_change_buffering_inited_ok;
3010  }
3011  }
3012 
3013  sql_print_error("InnoDB: invalid value "
3014  "innodb_change_buffering=%s",
3015  innobase_change_buffering);
3016  goto mem_free_and_error;
3017  }
3018 
3019 innobase_change_buffering_inited_ok:
3020  ut_a((ulint) ibuf_use < UT_ARR_SIZE(innobase_change_buffering_values));
3021  innobase_change_buffering = (char*)
3022  innobase_change_buffering_values[ibuf_use];
3023 
3024  /* Check that interdependent parameters have sane values. */
3025  if (srv_max_buf_pool_modified_pct < srv_max_dirty_pages_pct_lwm) {
3026  sql_print_warning("InnoDB: innodb_max_dirty_pages_pct_lwm"
3027  " cannot be set higher than"
3028  " innodb_max_dirty_pages_pct.\n"
3029  "InnoDB: Setting"
3030  " innodb_max_dirty_pages_pct_lwm to %lu\n",
3031  srv_max_buf_pool_modified_pct);
3032 
3033  srv_max_dirty_pages_pct_lwm = srv_max_buf_pool_modified_pct;
3034  }
3035 
3036  if (srv_max_io_capacity == SRV_MAX_IO_CAPACITY_DUMMY_DEFAULT) {
3037 
3038  if (srv_io_capacity >= SRV_MAX_IO_CAPACITY_LIMIT / 2) {
3039  /* Avoid overflow. */
3040  srv_max_io_capacity = SRV_MAX_IO_CAPACITY_LIMIT;
3041  } else {
3042  /* The user has not set the value. We should
3043  set it based on innodb_io_capacity. */
3044  srv_max_io_capacity =
3045  ut_max(2 * srv_io_capacity, 2000);
3046  }
3047 
3048  } else if (srv_max_io_capacity < srv_io_capacity) {
3049  sql_print_warning("InnoDB: innodb_io_capacity"
3050  " cannot be set higher than"
3051  " innodb_io_capacity_max.\n"
3052  "InnoDB: Setting"
3053  " innodb_io_capacity to %lu\n",
3054  srv_max_io_capacity);
3055 
3056  srv_io_capacity = srv_max_io_capacity;
3057  }
3058 
3059  if (!is_filename_allowed(srv_buf_dump_filename,
3060  strlen(srv_buf_dump_filename), FALSE)) {
3061  sql_print_error("InnoDB: innodb_buffer_pool_filename"
3062  " cannot have colon (:) in the file name.");
3063  goto mem_free_and_error;
3064  }
3065 
3066  /* --------------------------------------------------*/
3067 
3068  srv_file_flush_method_str = innobase_file_flush_method;
3069 
3070  srv_log_file_size = (ib_uint64_t) innobase_log_file_size;
3071 
3072 #ifdef UNIV_LOG_ARCHIVE
3073  srv_log_archive_on = (ulint) innobase_log_archive;
3074 #endif /* UNIV_LOG_ARCHIVE */
3075 
3076  /* Check that the value of system variable innodb_page_size was
3077  set correctly. Its value was put into srv_page_size. If valid,
3078  return the associated srv_page_size_shift.*/
3079  srv_page_size_shift = innodb_page_size_validate(srv_page_size);
3080  if (!srv_page_size_shift) {
3081  sql_print_error("InnoDB: Invalid page size=%lu.\n",
3082  srv_page_size);
3083  goto mem_free_and_error;
3084  }
3085  if (UNIV_PAGE_SIZE_DEF != srv_page_size) {
3086  ut_print_timestamp(stderr);
3087  fprintf(stderr,
3088  " InnoDB: innodb-page-size has been changed"
3089  " from the default value %d to %lu.\n",
3090  UNIV_PAGE_SIZE_DEF, srv_page_size);
3091  }
3092 
3093  srv_log_buffer_size = (ulint) innobase_log_buffer_size;
3094 
3095  if (innobase_buffer_pool_instances == 0) {
3096  innobase_buffer_pool_instances = 8;
3097 
3098 #if defined(__WIN__) && !defined(_WIN64)
3099  if (innobase_buffer_pool_size > 1331 * 1024 * 1024) {
3100  innobase_buffer_pool_instances
3102  (long) (innobase_buffer_pool_size
3103  / (128 * 1024 * 1024)));
3104  }
3105 #endif /* defined(__WIN__) && !defined(_WIN64) */
3106  }
3107  srv_buf_pool_size = (ulint) innobase_buffer_pool_size;
3108  srv_buf_pool_instances = (ulint) innobase_buffer_pool_instances;
3109 
3110  srv_mem_pool_size = (ulint) innobase_additional_mem_pool_size;
3111 
3112  if (innobase_additional_mem_pool_size
3113  != 8*1024*1024L /* the default */ ) {
3114 
3115  ut_print_timestamp(stderr);
3116  fprintf(stderr,
3117  " InnoDB: Warning: Using "
3118  "innodb_additional_mem_pool_size is DEPRECATED. "
3119  "This option may be removed in future releases, "
3120  "together with the option innodb_use_sys_malloc "
3121  "and with the InnoDB's internal memory "
3122  "allocator.\n");
3123  }
3124 
3125  if (!srv_use_sys_malloc ) {
3126  ut_print_timestamp(stderr);
3127  fprintf(stderr,
3128  " InnoDB: Warning: Setting "
3129  "innodb_use_sys_malloc to FALSE is DEPRECATED. "
3130  "This option may be removed in future releases, "
3131  "together with the InnoDB's internal memory "
3132  "allocator.\n");
3133  }
3134 
3135  srv_n_file_io_threads = (ulint) innobase_file_io_threads;
3136  srv_n_read_io_threads = (ulint) innobase_read_io_threads;
3137  srv_n_write_io_threads = (ulint) innobase_write_io_threads;
3138 
3139  srv_use_doublewrite_buf = (ibool) innobase_use_doublewrite;
3140 
3141  if (!innobase_use_checksums) {
3142  ut_print_timestamp(stderr);
3143  fprintf(stderr,
3144  " InnoDB: Warning: Setting "
3145  "innodb_checksums to OFF is DEPRECATED. "
3146  "This option may be removed in future releases. "
3147  "You should set innodb_checksum_algorithm=NONE "
3148  "instead.\n");
3150  }
3151 
3152 #ifdef HAVE_LARGE_PAGES
3153  if ((os_use_large_pages = (ibool) my_use_large_pages)) {
3154  os_large_page_size = (ulint) opt_large_page_size;
3155  }
3156 #endif
3157 
3158  row_rollback_on_timeout = (ibool) innobase_rollback_on_timeout;
3159 
3160  srv_locks_unsafe_for_binlog = (ibool) innobase_locks_unsafe_for_binlog;
3161  if (innobase_locks_unsafe_for_binlog) {
3162  ut_print_timestamp(stderr);
3163  fprintf(stderr,
3164  " InnoDB: Warning: Using "
3165  "innodb_locks_unsafe_for_binlog is DEPRECATED. "
3166  "This option may be removed in future releases. "
3167  "Please use READ COMMITTED transaction isolation "
3168  "level instead, see " REFMAN "set-transaction.html.\n");
3169  }
3170 
3171  if (innobase_open_files < 10) {
3172  innobase_open_files = 300;
3173  if (srv_file_per_table && table_cache_size > 300) {
3174  innobase_open_files = table_cache_size;
3175  }
3176  }
3177  srv_max_n_open_files = (ulint) innobase_open_files;
3178  srv_innodb_status = (ibool) innobase_create_status_file;
3179 
3180  srv_print_verbose_log = mysqld_embedded ? 0 : 1;
3181 
3182  /* Round up fts_sort_pll_degree to nearest power of 2 number */
3183  for (num_pll_degree = 1;
3184  num_pll_degree < fts_sort_pll_degree;
3185  num_pll_degree <<= 1) {
3186 
3187  /* No op */
3188  }
3189 
3190  fts_sort_pll_degree = num_pll_degree;
3191 
3192  /* Store the default charset-collation number of this MySQL
3193  installation */
3194 
3195  data_mysql_default_charset_coll = (ulint) default_charset_info->number;
3196 
3197  ut_a(DATA_MYSQL_LATIN1_SWEDISH_CHARSET_COLL ==
3198  my_charset_latin1.number);
3199  ut_a(DATA_MYSQL_BINARY_CHARSET_COLL == my_charset_bin.number);
3200 
3201  /* Store the latin1_swedish_ci character ordering table to InnoDB. For
3202  non-latin1_swedish_ci charsets we use the MySQL comparison functions,
3203  and consequently we do not need to know the ordering internally in
3204  InnoDB. */
3205 
3206  ut_a(0 == strcmp(my_charset_latin1.name, "latin1_swedish_ci"));
3207  srv_latin1_ordering = my_charset_latin1.sort_order;
3208 
3209  innobase_commit_concurrency_init_default();
3210 
3211 #ifdef HAVE_PSI_INTERFACE
3212  /* Register keys with MySQL performance schema */
3213  int count;
3214 
3215  count = array_elements(all_pthread_mutexes);
3216  mysql_mutex_register("innodb", all_pthread_mutexes, count);
3217 
3218 # ifdef UNIV_PFS_MUTEX
3219  count = array_elements(all_innodb_mutexes);
3220  mysql_mutex_register("innodb", all_innodb_mutexes, count);
3221 # endif /* UNIV_PFS_MUTEX */
3222 
3223 # ifdef UNIV_PFS_RWLOCK
3224  count = array_elements(all_innodb_rwlocks);
3225  mysql_rwlock_register("innodb", all_innodb_rwlocks, count);
3226 # endif /* UNIV_PFS_MUTEX */
3227 
3228 # ifdef UNIV_PFS_THREAD
3229  count = array_elements(all_innodb_threads);
3230  mysql_thread_register("innodb", all_innodb_threads, count);
3231 # endif /* UNIV_PFS_THREAD */
3232 
3233 # ifdef UNIV_PFS_IO
3234  count = array_elements(all_innodb_files);
3235  mysql_file_register("innodb", all_innodb_files, count);
3236 # endif /* UNIV_PFS_IO */
3237 
3238  count = array_elements(all_innodb_conds);
3239  mysql_cond_register("innodb", all_innodb_conds, count);
3240 #endif /* HAVE_PSI_INTERFACE */
3241 
3242  /* Since we in this module access directly the fields of a trx
3243  struct, and due to different headers and flags it might happen that
3244  ib_mutex_t has a different size in this module and in InnoDB
3245  modules, we check at run time that the size is the same in
3246  these compilation modules. */
3247 
3249 
3250  if (err != DB_SUCCESS) {
3251  goto mem_free_and_error;
3252  }
3253 
3254  /* Adjust the innodb_undo_logs config object */
3255  innobase_undo_logs_init_default_max();
3256 
3257  innobase_old_blocks_pct = buf_LRU_old_ratio_update(
3258  innobase_old_blocks_pct, TRUE);
3259 
3260  ibuf_max_size_update(innobase_change_buffer_max_size);
3261 
3262  innobase_open_tables = hash_create(200);
3263  mysql_mutex_init(innobase_share_mutex_key,
3264  &innobase_share_mutex,
3265  MY_MUTEX_INIT_FAST);
3266  mysql_mutex_init(commit_cond_mutex_key,
3267  &commit_cond_m, MY_MUTEX_INIT_FAST);
3268  mysql_cond_init(commit_cond_key, &commit_cond, NULL);
3269  innodb_inited= 1;
3270 #ifdef MYSQL_DYNAMIC_PLUGIN
3271  if (innobase_hton != p) {
3272  innobase_hton = reinterpret_cast<handlerton*>(p);
3273  *innobase_hton = *innodb_hton_ptr;
3274  }
3275 #endif /* MYSQL_DYNAMIC_PLUGIN */
3276 
3277  /* Get the current high water mark format. */
3278  innobase_file_format_max = (char*) trx_sys_file_format_max_get();
3279 
3280  /* Currently, monitor counter information are not persistent. */
3281  memset(monitor_set_tbl, 0, sizeof monitor_set_tbl);
3282 
3283  memset(innodb_counter_value, 0, sizeof innodb_counter_value);
3284 
3285  /* Do this as late as possible so server is fully starts up,
3286  since we might get some initial stats if user choose to turn
3287  on some counters from start up */
3288  if (innobase_enable_monitor_counter) {
3289  innodb_enable_monitor_at_startup(
3290  innobase_enable_monitor_counter);
3291  }
3292 
3293  /* Turn on monitor counters that are default on */
3295 
3296  DBUG_RETURN(FALSE);
3297 error:
3298  DBUG_RETURN(TRUE);
3299 }
3300 
3301 /*******************************************************************/
3304 static
3305 int
3306 innobase_end(
3307 /*=========*/
3308  handlerton* hton,
3309  ha_panic_function type __attribute__((unused)))
3311 {
3312  int err= 0;
3313 
3314  DBUG_ENTER("innobase_end");
3315  DBUG_ASSERT(hton == innodb_hton_ptr);
3316 
3317  if (innodb_inited) {
3318 
3319  srv_fast_shutdown = (ulint) innobase_fast_shutdown;
3320 
3321  innodb_inited = 0;
3322  hash_table_free(innobase_open_tables);
3323  innobase_open_tables = NULL;
3324  if (innobase_shutdown_for_mysql() != DB_SUCCESS) {
3325  err = 1;
3326  }
3328  my_free(internal_innobase_data_file_path);
3329  mysql_mutex_destroy(&innobase_share_mutex);
3330  mysql_mutex_destroy(&commit_cond_m);
3331  mysql_cond_destroy(&commit_cond);
3332  }
3333 
3334  DBUG_RETURN(err);
3335 }
3336 
3337 /****************************************************************/
3341 static
3342 bool
3343 innobase_flush_logs(
3344 /*================*/
3345  handlerton* hton)
3346 {
3347  bool result = 0;
3348 
3349  DBUG_ENTER("innobase_flush_logs");
3350  DBUG_ASSERT(hton == innodb_hton_ptr);
3351 
3352  if (!srv_read_only_mode) {
3354  }
3355 
3356  DBUG_RETURN(result);
3357 }
3358 
3359 /*****************************************************************/
3361 static
3362 void
3363 innobase_commit_low(
3364 /*================*/
3365  trx_t* trx)
3366 {
3367  if (trx_is_started(trx)) {
3368 
3369  trx_commit_for_mysql(trx);
3370  }
3371 }
3372 
3373 /*****************************************************************/
3379 static
3380 int
3381 innobase_start_trx_and_assign_read_view(
3382 /*====================================*/
3383  handlerton* hton,
3384  THD* thd)
3386 {
3387  trx_t* trx;
3388 
3389  DBUG_ENTER("innobase_start_trx_and_assign_read_view");
3390  DBUG_ASSERT(hton == innodb_hton_ptr);
3391 
3392  /* Create a new trx struct for thd, if it does not yet have one */
3393 
3394  trx = check_trx_exists(thd);
3395 
3396  /* This is just to play safe: release a possible FIFO ticket and
3397  search latch. Since we can potentially reserve the trx_sys->mutex,
3398  we have to release the search system latch first to obey the latching
3399  order. */
3400 
3402 
3403  innobase_srv_conc_force_exit_innodb(trx);
3404 
3405  /* If the transaction is not started yet, start it */
3406 
3407  trx_start_if_not_started_xa(trx);
3408 
3409  /* Assign a read view if the transaction does not have it yet.
3410  Do this only if transaction is using REPEATABLE READ isolation
3411  level. */
3412  trx->isolation_level = innobase_map_isolation_level(
3413  thd_get_trx_isolation(thd));
3414 
3415  if (trx->isolation_level == TRX_ISO_REPEATABLE_READ) {
3416  trx_assign_read_view(trx);
3417  } else {
3418  push_warning_printf(thd, Sql_condition::WARN_LEVEL_WARN,
3419  HA_ERR_UNSUPPORTED,
3420  "InnoDB: WITH CONSISTENT SNAPSHOT "
3421  "was ignored because this phrase "
3422  "can only be used with "
3423  "REPEATABLE READ isolation level.");
3424  }
3425 
3426  /* Set the MySQL flag to mark that there is an active transaction */
3427 
3428  innobase_register_trx(hton, current_thd, trx);
3429 
3430  DBUG_RETURN(0);
3431 }
3432 
3433 /*****************************************************************/
3437 static
3438 int
3439 innobase_commit(
3440 /*============*/
3441  handlerton* hton,
3442  THD* thd,
3445  bool commit_trx)
3448 {
3449  trx_t* trx;
3450 
3451  DBUG_ENTER("innobase_commit");
3452  DBUG_ASSERT(hton == innodb_hton_ptr);
3453  DBUG_PRINT("trans", ("ending transaction"));
3454 
3455  trx = check_trx_exists(thd);
3456 
3457  /* Since we will reserve the trx_sys->mutex, we have to release
3458  the search system latch first to obey the latching order. */
3459 
3460  if (trx->has_search_latch) {
3462  }
3463 
3464  /* Transaction is deregistered only in a commit or a rollback. If
3465  it is deregistered we know there cannot be resources to be freed
3466  and we could return immediately. For the time being, we play safe
3467  and do the cleanup though there should be nothing to clean up. */
3468 
3469  if (!trx_is_registered_for_2pc(trx) && trx_is_started(trx)) {
3470 
3471  sql_print_error("Transaction not registered for MySQL 2PC, "
3472  "but transaction is active");
3473  }
3474 
3475  if (commit_trx
3476  || (!thd_test_options(thd, OPTION_NOT_AUTOCOMMIT | OPTION_BEGIN))) {
3477 
3478  /* We were instructed to commit the whole transaction, or
3479  this is an SQL statement end and autocommit is on */
3480 
3481  /* We need current binlog position for ibbackup to work. */
3482 retry:
3483  if (innobase_commit_concurrency > 0) {
3484  mysql_mutex_lock(&commit_cond_m);
3485  commit_threads++;
3486 
3487  if (commit_threads > innobase_commit_concurrency) {
3488  commit_threads--;
3489  mysql_cond_wait(&commit_cond,
3490  &commit_cond_m);
3491  mysql_mutex_unlock(&commit_cond_m);
3492  goto retry;
3493  }
3494  else {
3495  mysql_mutex_unlock(&commit_cond_m);
3496  }
3497  }
3498 
3499  /* The following call read the binary log position of
3500  the transaction being committed.
3501 
3502  Binary logging of other engines is not relevant to
3503  InnoDB as all InnoDB requires is that committing
3504  InnoDB transactions appear in the same order in the
3505  MySQL binary log as they appear in InnoDB logs, which
3506  is guaranteed by the server.
3507 
3508  If the binary log is not enabled, or the transaction
3509  is not written to the binary log, the file name will
3510  be a NULL pointer. */
3511  unsigned long long pos;
3512  thd_binlog_pos(thd, &trx->mysql_log_file_name, &pos);
3513  trx->mysql_log_offset= static_cast<ib_int64_t>(pos);
3514  /* Don't do write + flush right now. For group commit
3515  to work we want to do the flush later. */
3516  trx->flush_log_later = TRUE;
3517  innobase_commit_low(trx);
3518  trx->flush_log_later = FALSE;
3519 
3520  if (innobase_commit_concurrency > 0) {
3521  mysql_mutex_lock(&commit_cond_m);
3522  commit_threads--;
3523  mysql_cond_signal(&commit_cond);
3524  mysql_mutex_unlock(&commit_cond_m);
3525  }
3526 
3527  trx_deregister_from_2pc(trx);
3528 
3529  /* Now do a write + flush of logs. */
3531  } else {
3532  /* We just mark the SQL statement ended and do not do a
3533  transaction commit */
3534 
3535  /* If we had reserved the auto-inc lock for some
3536  table in this SQL statement we release it now */
3537 
3539 
3540  /* Store the current undo_no of the transaction so that we
3541  know where to roll back if we have to roll back the next
3542  SQL statement */
3543 
3544  trx_mark_sql_stat_end(trx);
3545  }
3546 
3547  trx->n_autoinc_rows = 0; /* Reset the number AUTO-INC rows required */
3548 
3549  /* This is a statement level variable. */
3550  trx->fts_next_doc_id = 0;
3551 
3552  innobase_srv_conc_force_exit_innodb(trx);
3553 
3554  /* Tell the InnoDB server that there might be work for utility
3555  threads: */
3557 
3558  DBUG_RETURN(0);
3559 }
3560 
3561 /*****************************************************************/
3564 static
3565 int
3566 innobase_rollback(
3567 /*==============*/
3568  handlerton* hton,
3569  THD* thd,
3572  bool rollback_trx)
3575 {
3576  dberr_t error;
3577  trx_t* trx;
3578 
3579  DBUG_ENTER("innobase_rollback");
3580  DBUG_ASSERT(hton == innodb_hton_ptr);
3581  DBUG_PRINT("trans", ("aborting transaction"));
3582 
3583  trx = check_trx_exists(thd);
3584 
3585  /* Release a possible FIFO ticket and search latch. Since we will
3586  reserve the trx_sys->mutex, we have to release the search system
3587  latch first to obey the latching order. */
3588 
3590 
3591  innobase_srv_conc_force_exit_innodb(trx);
3592 
3593  trx->n_autoinc_rows = 0; /* Reset the number AUTO-INC rows required */
3594 
3595  /* If we had reserved the auto-inc lock for some table (if
3596  we come here to roll back the latest SQL statement) we
3597  release it now before a possibly lengthy rollback */
3598 
3600 
3601  /* This is a statement level variable. */
3602  trx->fts_next_doc_id = 0;
3603 
3604  if (rollback_trx
3605  || !thd_test_options(thd, OPTION_NOT_AUTOCOMMIT | OPTION_BEGIN)) {
3606 
3607  error = trx_rollback_for_mysql(trx);
3608  trx_deregister_from_2pc(trx);
3609  } else {
3611  }
3612 
3613  DBUG_RETURN(convert_error_code_to_mysql(error, 0, NULL));
3614 }
3615 
3616 /*****************************************************************/
3619 static
3620 int
3621 innobase_rollback_trx(
3622 /*==================*/
3623  trx_t* trx)
3624 {
3625  dberr_t error = DB_SUCCESS;
3626 
3627  DBUG_ENTER("innobase_rollback_trx");
3628  DBUG_PRINT("trans", ("aborting transaction"));
3629 
3630  /* Release a possible FIFO ticket and search latch. Since we will
3631  reserve the trx_sys->mutex, we have to release the search system
3632  latch first to obey the latching order. */
3633 
3635 
3636  innobase_srv_conc_force_exit_innodb(trx);
3637 
3638  /* If we had reserved the auto-inc lock for some table (if
3639  we come here to roll back the latest SQL statement) we
3640  release it now before a possibly lengthy rollback */
3641 
3643 
3644  if (!trx->read_only) {
3645  error = trx_rollback_for_mysql(trx);
3646  }
3647 
3648  DBUG_RETURN(convert_error_code_to_mysql(error, 0, NULL));
3649 }
3650 
3651 /*****************************************************************/
3655 static
3656 int
3657 innobase_rollback_to_savepoint(
3658 /*===========================*/
3659  handlerton* hton,
3660  THD* thd,
3663  void* savepoint)
3664 {
3665  ib_int64_t mysql_binlog_cache_pos;
3666  dberr_t error;
3667  trx_t* trx;
3668  char name[64];
3669 
3670  DBUG_ENTER("innobase_rollback_to_savepoint");
3671  DBUG_ASSERT(hton == innodb_hton_ptr);
3672 
3673  trx = check_trx_exists(thd);
3674 
3675  /* Release a possible FIFO ticket and search latch. Since we will
3676  reserve the trx_sys->mutex, we have to release the search system
3677  latch first to obey the latching order. */
3678 
3680 
3681  innobase_srv_conc_force_exit_innodb(trx);
3682 
3683  /* TODO: use provided savepoint data area to store savepoint data */
3684 
3685  longlong2str((ulint) savepoint, name, 36);
3686 
3688  trx, name, &mysql_binlog_cache_pos);
3689 
3690  if (error == DB_SUCCESS && trx->fts_trx != NULL) {
3691  fts_savepoint_rollback(trx, name);
3692  }
3693 
3694  DBUG_RETURN(convert_error_code_to_mysql(error, 0, NULL));
3695 }
3696 
3697 /*****************************************************************/
3701 static
3702 int
3703 innobase_release_savepoint(
3704 /*=======================*/
3705  handlerton* hton,
3706  THD* thd,
3709  void* savepoint)
3710 {
3711  dberr_t error;
3712  trx_t* trx;
3713  char name[64];
3714 
3715  DBUG_ENTER("innobase_release_savepoint");
3716  DBUG_ASSERT(hton == innodb_hton_ptr);
3717 
3718  trx = check_trx_exists(thd);
3719 
3720  /* TODO: use provided savepoint data area to store savepoint data */
3721 
3722  longlong2str((ulint) savepoint, name, 36);
3723 
3724  error = trx_release_savepoint_for_mysql(trx, name);
3725 
3726  if (error == DB_SUCCESS && trx->fts_trx != NULL) {
3727  fts_savepoint_release(trx, name);
3728  }
3729 
3730  DBUG_RETURN(convert_error_code_to_mysql(error, 0, NULL));
3731 }
3732 
3733 /*****************************************************************/
3736 static
3737 int
3738 innobase_savepoint(
3739 /*===============*/
3740  handlerton* hton,
3741  THD* thd,
3742  void* savepoint)
3743 {
3744  dberr_t error;
3745  trx_t* trx;
3746 
3747  DBUG_ENTER("innobase_savepoint");
3748  DBUG_ASSERT(hton == innodb_hton_ptr);
3749 
3750  /* In the autocommit mode there is no sense to set a savepoint
3751  (unless we are in sub-statement), so SQL layer ensures that
3752  this method is never called in such situation. */
3753 
3754  trx = check_trx_exists(thd);
3755 
3756  /* Release a possible FIFO ticket and search latch. Since we will
3757  reserve the trx_sys->mutex, we have to release the search system
3758  latch first to obey the latching order. */
3759 
3761 
3762  innobase_srv_conc_force_exit_innodb(trx);
3763 
3764  /* Cannot happen outside of transaction */
3765  DBUG_ASSERT(trx_is_registered_for_2pc(trx));
3766 
3767  /* TODO: use provided savepoint data area to store savepoint data */
3768  char name[64];
3769  longlong2str((ulint) savepoint,name,36);
3770 
3771  error = trx_savepoint_for_mysql(trx, name, (ib_int64_t)0);
3772 
3773  if (error == DB_SUCCESS && trx->fts_trx != NULL) {
3774  fts_savepoint_take(trx, name);
3775  }
3776 
3777  DBUG_RETURN(convert_error_code_to_mysql(error, 0, NULL));
3778 }
3779 
3780 /*****************************************************************/
3783 static
3784 int
3785 innobase_close_connection(
3786 /*======================*/
3787  handlerton* hton,
3788  THD* thd)
3790 {
3791  trx_t* trx;
3792 
3793  DBUG_ENTER("innobase_close_connection");
3794  DBUG_ASSERT(hton == innodb_hton_ptr);
3795  trx = thd_to_trx(thd);
3796 
3797  ut_a(trx);
3798 
3799  if (!trx_is_registered_for_2pc(trx) && trx_is_started(trx)) {
3800 
3801  sql_print_error("Transaction not registered for MySQL 2PC, "
3802  "but transaction is active");
3803  }
3804 
3805  if (trx_is_started(trx) && log_warnings) {
3806 
3807  sql_print_warning(
3808  "MySQL is closing a connection that has an active "
3809  "InnoDB transaction. "TRX_ID_FMT" row modifications "
3810  "will roll back.",
3811  trx->undo_no);
3812  }
3813 
3814  innobase_rollback_trx(trx);
3815 
3816  trx_free_for_mysql(trx);
3817 
3818  DBUG_RETURN(0);
3819 }
3820 
3821 /*****************************************************************/
3824 UNIV_INTERN
3825 int
3827 /*===============*/
3828  THD* thd)
3830 {
3831  trx_t* trx = thd_to_trx(thd);
3832 
3833  if (!trx) {
3834  return(0);
3835  }
3836 
3837  return(innobase_close_connection(innodb_hton_ptr, thd));
3838 }
3839 
3840 /*************************************************************************/
3844 /****************************************************************/
3848 UNIV_INTERN
3849 enum row_type
3851 /*=============================*/
3852 {
3853  if (prebuilt && prebuilt->table) {
3854  const ulint flags = prebuilt->table->flags;
3855 
3856  switch (dict_tf_get_rec_format(flags)) {
3857  case REC_FORMAT_REDUNDANT:
3858  return(ROW_TYPE_REDUNDANT);
3859  case REC_FORMAT_COMPACT:
3860  return(ROW_TYPE_COMPACT);
3861  case REC_FORMAT_COMPRESSED:
3862  return(ROW_TYPE_COMPRESSED);
3863  case REC_FORMAT_DYNAMIC:
3864  return(ROW_TYPE_DYNAMIC);
3865  }
3866  }
3867  ut_ad(0);
3868  return(ROW_TYPE_NOT_USED);
3869 }
3870 
3871 
3872 
3873 /****************************************************************/
3876 UNIV_INTERN
3877 handler::Table_flags
3879 /*============================*/
3880 {
3881  /* Need to use tx_isolation here since table flags is (also)
3882  called before prebuilt is inited. */
3883  ulong const tx_isolation = thd_tx_isolation(ha_thd());
3884 
3885  if (tx_isolation <= ISO_READ_COMMITTED) {
3886  return(int_table_flags);
3887  }
3888 
3889  return(int_table_flags | HA_BINLOG_STMT_CAPABLE);
3890 }
3891 
3892 /****************************************************************/
3894 static const char* ha_innobase_exts[] = {
3895  ".ibd",
3896  ".isl",
3897  NullS
3898 };
3899 
3900 /****************************************************************/
3903 UNIV_INTERN
3904 const char*
3906 /*===========================*/
3907 {
3908  return(innobase_hton_name);
3909 }
3910 
3911 /****************************************************************/
3914 UNIV_INTERN
3915 const char*
3917 /*====================*/
3918  uint keynr)
3919 {
3920  dict_index_t* index = innobase_get_index(keynr);
3921 
3922  if (index && index->type & DICT_FTS) {
3923  return("FULLTEXT");
3924  } else {
3925  return("BTREE");
3926  }
3927 }
3928 
3929 /****************************************************************/
3932 UNIV_INTERN
3933 const char**
3935 /*========================*/
3936 {
3937  return(ha_innobase_exts);
3938 }
3939 
3940 /****************************************************************/
3943 UNIV_INTERN
3944 ulong
3946 /*=====================*/
3947  uint key,
3948  uint,
3949  bool) const
3950 {
3951  return((table_share->key_info[key].algorithm == HA_KEY_ALG_FULLTEXT)
3952  ? 0
3953  : (HA_READ_NEXT | HA_READ_PREV | HA_READ_ORDER
3954  | HA_READ_RANGE | HA_KEYREAD_ONLY
3955  | HA_DO_INDEX_COND_PUSHDOWN));
3956 }
3957 
3958 /****************************************************************/
3961 UNIV_INTERN
3962 uint
3964 /*===================================*/
3965 {
3966  return(MAX_KEY);
3967 }
3968 
3969 /****************************************************************/
3972 UNIV_INTERN
3973 uint
3975 /*=========================================*/
3976 {
3977  /* An InnoDB page must store >= 2 keys; a secondary key record
3978  must also contain the primary key value. Therefore, if both
3979  the primary key and the secondary key are at this maximum length,
3980  it must be less than 1/4th of the free space on a page including
3981  record overhead.
3982 
3983  MySQL imposes its own limit to this number; MAX_KEY_LENGTH = 3072.
3984 
3985  For page sizes = 16k, InnoDB historically reported 3500 bytes here,
3986  But the MySQL limit of 3072 was always used through the handler
3987  interface. */
3988 
3989  switch (UNIV_PAGE_SIZE) {
3990  case 4096:
3991  return(768);
3992  case 8192:
3993  return(1536);
3994  default:
3995  return(3500);
3996  }
3997 }
3998 
3999 /****************************************************************/
4002 UNIV_INTERN
4003 const key_map*
4005 /*===================================*/
4006 {
4007  return(&key_map_full);
4008 }
4009 
4010 /****************************************************************/
4013 UNIV_INTERN
4014 uint8
4016 /*===========================*/
4017 {
4018  return(HA_CACHE_TBL_ASKTRANSACT);
4019 }
4020 
4021 /****************************************************************/
4024 UNIV_INTERN
4025 bool
4027 /*===================================*/
4028 {
4029  return(true);
4030 }
4031 
4032 /*****************************************************************/
4037 static
4038 void
4039 normalize_table_name_low(
4040 /*=====================*/
4041  char* norm_name,
4043  const char* name,
4044  ibool set_lower_case)
4046 {
4047  char* name_ptr;
4048  ulint name_len;
4049  char* db_ptr;
4050  ulint db_len;
4051  char* ptr;
4052  ulint norm_len;
4053 
4054  /* Scan name from the end */
4055 
4056  ptr = strend(name) - 1;
4057 
4058  /* seek to the last path separator */
4059  while (ptr >= name && *ptr != '\\' && *ptr != '/') {
4060  ptr--;
4061  }
4062 
4063  name_ptr = ptr + 1;
4064  name_len = strlen(name_ptr);
4065 
4066  /* skip any number of path separators */
4067  while (ptr >= name && (*ptr == '\\' || *ptr == '/')) {
4068  ptr--;
4069  }
4070 
4071  DBUG_ASSERT(ptr >= name);
4072 
4073  /* seek to the last but one path separator or one char before
4074  the beginning of name */
4075  db_len = 0;
4076  while (ptr >= name && *ptr != '\\' && *ptr != '/') {
4077  ptr--;
4078  db_len++;
4079  }
4080 
4081  db_ptr = ptr + 1;
4082 
4083  norm_len = db_len + name_len + sizeof "/";
4084  ut_a(norm_len < FN_REFLEN - 1);
4085 
4086  memcpy(norm_name, db_ptr, db_len);
4087 
4088  norm_name[db_len] = '/';
4089 
4090  /* Copy the name and null-byte. */
4091  memcpy(norm_name + db_len + 1, name_ptr, name_len + 1);
4092 
4093  if (set_lower_case) {
4094  innobase_casedn_str(norm_name);
4095  }
4096 }
4097 
4098 #if !defined(DBUG_OFF)
4099 /*********************************************************************
4100 Test normalize_table_name_low(). */
4101 static
4102 void
4103 test_normalize_table_name_low()
4104 /*===========================*/
4105 {
4106  char norm_name[FN_REFLEN];
4107  const char* test_data[][2] = {
4108  /* input, expected result */
4109  {"./mysqltest/t1", "mysqltest/t1"},
4110  {"./test/#sql-842b_2", "test/#sql-842b_2"},
4111  {"./test/#sql-85a3_10", "test/#sql-85a3_10"},
4112  {"./test/#sql2-842b-2", "test/#sql2-842b-2"},
4113  {"./test/bug29807", "test/bug29807"},
4114  {"./test/foo", "test/foo"},
4115  {"./test/innodb_bug52663", "test/innodb_bug52663"},
4116  {"./test/t", "test/t"},
4117  {"./test/t1", "test/t1"},
4118  {"./test/t10", "test/t10"},
4119  {"/a/b/db/table", "db/table"},
4120  {"/a/b/db///////table", "db/table"},
4121  {"/a/b////db///////table", "db/table"},
4122  {"/var/tmp/mysqld.1/#sql842b_2_10", "mysqld.1/#sql842b_2_10"},
4123  {"db/table", "db/table"},
4124  {"ddd/t", "ddd/t"},
4125  {"d/ttt", "d/ttt"},
4126  {"d/t", "d/t"},
4127  {".\\mysqltest\\t1", "mysqltest/t1"},
4128  {".\\test\\#sql-842b_2", "test/#sql-842b_2"},
4129  {".\\test\\#sql-85a3_10", "test/#sql-85a3_10"},
4130  {".\\test\\#sql2-842b-2", "test/#sql2-842b-2"},
4131  {".\\test\\bug29807", "test/bug29807"},
4132  {".\\test\\foo", "test/foo"},
4133  {".\\test\\innodb_bug52663", "test/innodb_bug52663"},
4134  {".\\test\\t", "test/t"},
4135  {".\\test\\t1", "test/t1"},
4136  {".\\test\\t10", "test/t10"},
4137  {"C:\\a\\b\\db\\table", "db/table"},
4138  {"C:\\a\\b\\db\\\\\\\\\\\\\\table", "db/table"},
4139  {"C:\\a\\b\\\\\\\\db\\\\\\\\\\\\\\table", "db/table"},
4140  {"C:\\var\\tmp\\mysqld.1\\#sql842b_2_10", "mysqld.1/#sql842b_2_10"},
4141  {"db\\table", "db/table"},
4142  {"ddd\\t", "ddd/t"},
4143  {"d\\ttt", "d/ttt"},
4144  {"d\\t", "d/t"},
4145  };
4146 
4147  for (size_t i = 0; i < UT_ARR_SIZE(test_data); i++) {
4148  printf("test_normalize_table_name_low(): "
4149  "testing \"%s\", expected \"%s\"... ",
4150  test_data[i][0], test_data[i][1]);
4151 
4152  normalize_table_name_low(norm_name, test_data[i][0], FALSE);
4153 
4154  if (strcmp(norm_name, test_data[i][1]) == 0) {
4155  printf("ok\n");
4156  } else {
4157  printf("got \"%s\"\n", norm_name);
4158  ut_error;
4159  }
4160  }
4161 }
4162 
4163 /*********************************************************************
4164 Test ut_format_name(). */
4165 static
4166 void
4167 test_ut_format_name()
4168 /*=================*/
4169 {
4170  char buf[NAME_LEN * 3];
4171 
4172  struct {
4173  const char* name;
4174  ibool is_table;
4175  ulint buf_size;
4176  const char* expected;
4177  } test_data[] = {
4178  {"test/t1", TRUE, sizeof(buf), "\"test\".\"t1\""},
4179  {"test/t1", TRUE, 12, "\"test\".\"t1\""},
4180  {"test/t1", TRUE, 11, "\"test\".\"t1"},
4181  {"test/t1", TRUE, 10, "\"test\".\"t"},
4182  {"test/t1", TRUE, 9, "\"test\".\""},
4183  {"test/t1", TRUE, 8, "\"test\"."},
4184  {"test/t1", TRUE, 7, "\"test\""},
4185  {"test/t1", TRUE, 6, "\"test"},
4186  {"test/t1", TRUE, 5, "\"tes"},
4187  {"test/t1", TRUE, 4, "\"te"},
4188  {"test/t1", TRUE, 3, "\"t"},
4189  {"test/t1", TRUE, 2, "\""},
4190  {"test/t1", TRUE, 1, ""},
4191  {"test/t1", TRUE, 0, "BUF_NOT_CHANGED"},
4192  {"table", TRUE, sizeof(buf), "\"table\""},
4193  {"ta'le", TRUE, sizeof(buf), "\"ta'le\""},
4194  {"ta\"le", TRUE, sizeof(buf), "\"ta\"\"le\""},
4195  {"ta`le", TRUE, sizeof(buf), "\"ta`le\""},
4196  {"index", FALSE, sizeof(buf), "\"index\""},
4197  {"ind/ex", FALSE, sizeof(buf), "\"ind/ex\""},
4198  };
4199 
4200  for (size_t i = 0; i < UT_ARR_SIZE(test_data); i++) {
4201 
4202  memcpy(buf, "BUF_NOT_CHANGED", strlen("BUF_NOT_CHANGED") + 1);
4203 
4204  char* ret;
4205 
4206  ret = ut_format_name(test_data[i].name,
4207  test_data[i].is_table,
4208  buf,
4209  test_data[i].buf_size);
4210 
4211  ut_a(ret == buf);
4212 
4213  if (strcmp(buf, test_data[i].expected) == 0) {
4214  fprintf(stderr,
4215  "ut_format_name(%s, %s, buf, %lu), "
4216  "expected %s, OK\n",
4217  test_data[i].name,
4218  test_data[i].is_table ? "TRUE" : "FALSE",
4219  test_data[i].buf_size,
4220  test_data[i].expected);
4221  } else {
4222  fprintf(stderr,
4223  "ut_format_name(%s, %s, buf, %lu), "
4224  "expected %s, ERROR: got %s\n",
4225  test_data[i].name,
4226  test_data[i].is_table ? "TRUE" : "FALSE",
4227  test_data[i].buf_size,
4228  test_data[i].expected,
4229  buf);
4230  ut_error;
4231  }
4232  }
4233 }
4234 #endif /* !DBUG_OFF */
4235 
4236 /********************************************************************/
4239 UNIV_INTERN
4240 ulonglong
4242 /*===========================*/
4243  const Field* field)
4244 {
4245  ulonglong max_value = 0;
4246 
4247  switch (field->key_type()) {
4248  /* TINY */
4249  case HA_KEYTYPE_BINARY:
4250  max_value = 0xFFULL;
4251  break;
4252  case HA_KEYTYPE_INT8:
4253  max_value = 0x7FULL;
4254  break;
4255  /* SHORT */
4256  case HA_KEYTYPE_USHORT_INT:
4257  max_value = 0xFFFFULL;
4258  break;
4259  case HA_KEYTYPE_SHORT_INT:
4260  max_value = 0x7FFFULL;
4261  break;
4262  /* MEDIUM */
4263  case HA_KEYTYPE_UINT24:
4264  max_value = 0xFFFFFFULL;
4265  break;
4266  case HA_KEYTYPE_INT24:
4267  max_value = 0x7FFFFFULL;
4268  break;
4269  /* LONG */
4270  case HA_KEYTYPE_ULONG_INT:
4271  max_value = 0xFFFFFFFFULL;
4272  break;
4273  case HA_KEYTYPE_LONG_INT:
4274  max_value = 0x7FFFFFFFULL;
4275  break;
4276  /* BIG */
4277  case HA_KEYTYPE_ULONGLONG:
4278  max_value = 0xFFFFFFFFFFFFFFFFULL;
4279  break;
4280  case HA_KEYTYPE_LONGLONG:
4281  max_value = 0x7FFFFFFFFFFFFFFFULL;
4282  break;
4283  case HA_KEYTYPE_FLOAT:
4284  /* We use the maximum as per IEEE754-2008 standard, 2^24 */
4285  max_value = 0x1000000ULL;
4286  break;
4287  case HA_KEYTYPE_DOUBLE:
4288  /* We use the maximum as per IEEE754-2008 standard, 2^53 */
4289  max_value = 0x20000000000000ULL;
4290  break;
4291  default:
4292  ut_error;
4293  }
4294 
4295  return(max_value);
4296 }
4297 
4298 /*******************************************************************/
4302 static
4303 ibool
4304 innobase_match_index_columns(
4305 /*=========================*/
4306  const KEY* key_info,
4308  const dict_index_t* index_info)
4310 {
4311  const KEY_PART_INFO* key_part;
4312  const KEY_PART_INFO* key_end;
4313  const dict_field_t* innodb_idx_fld;
4314  const dict_field_t* innodb_idx_fld_end;
4315 
4316  DBUG_ENTER("innobase_match_index_columns");
4317 
4318  /* Check whether user defined index column count matches */
4319  if (key_info->user_defined_key_parts !=
4320  index_info->n_user_defined_cols) {
4321  DBUG_RETURN(FALSE);
4322  }
4323 
4324  key_part = key_info->key_part;
4325  key_end = key_part + key_info->user_defined_key_parts;
4326  innodb_idx_fld = index_info->fields;
4327  innodb_idx_fld_end = index_info->fields + index_info->n_fields;
4328 
4329  /* Check each index column's datatype. We do not check
4330  column name because there exists case that index
4331  column name got modified in mysql but such change does not
4332  propagate to InnoDB.
4333  One hidden assumption here is that the index column sequences
4334  are matched up between those in mysql and Innodb. */
4335  for (; key_part != key_end; ++key_part) {
4336  ulint col_type;
4337  ibool is_unsigned;
4338  ulint mtype = innodb_idx_fld->col->mtype;
4339 
4340  /* Need to translate to InnoDB column type before
4341  comparison. */
4342  col_type = get_innobase_type_from_mysql_type(&is_unsigned,
4343  key_part->field);
4344 
4345  /* Ignore Innodb specific system columns. */
4346  while (mtype == DATA_SYS) {
4347  innodb_idx_fld++;
4348 
4349  if (innodb_idx_fld >= innodb_idx_fld_end) {
4350  DBUG_RETURN(FALSE);
4351  }
4352  }
4353 
4354  if (col_type != mtype) {
4355  /* Column Type mismatches */
4356  DBUG_RETURN(FALSE);
4357  }
4358 
4359  innodb_idx_fld++;
4360  }
4361 
4362  DBUG_RETURN(TRUE);
4363 }
4364 
4365 /*******************************************************************/
4376 static
4377 ibool
4378 innobase_build_index_translation(
4379 /*=============================*/
4380  const TABLE* table,
4382  dict_table_t* ib_table,
4384  INNOBASE_SHARE* share)
4387 {
4388  ulint mysql_num_index;
4389  ulint ib_num_index;
4390  dict_index_t** index_mapping;
4391  ibool ret = TRUE;
4392 
4393  DBUG_ENTER("innobase_build_index_translation");
4394 
4395  mutex_enter(&dict_sys->mutex);
4396 
4397  mysql_num_index = table->s->keys;
4398  ib_num_index = UT_LIST_GET_LEN(ib_table->indexes);
4399 
4400  index_mapping = share->idx_trans_tbl.index_mapping;
4401 
4402  /* If there exists inconsistency between MySQL and InnoDB dictionary
4403  (metadata) information, the number of index defined in MySQL
4404  could exceed that in InnoDB, do not build index translation
4405  table in such case */
4406  if (UNIV_UNLIKELY(ib_num_index < mysql_num_index)) {
4407  ret = FALSE;
4408  goto func_exit;
4409  }
4410 
4411  /* If index entry count is non-zero, nothing has
4412  changed since last update, directly return TRUE */
4413  if (share->idx_trans_tbl.index_count) {
4414  /* Index entry count should still match mysql_num_index */
4415  ut_a(share->idx_trans_tbl.index_count == mysql_num_index);
4416  goto func_exit;
4417  }
4418 
4419  /* The number of index increased, rebuild the mapping table */
4420  if (mysql_num_index > share->idx_trans_tbl.array_size) {
4421  index_mapping = (dict_index_t**) my_realloc(index_mapping,
4422  mysql_num_index *
4423  sizeof(*index_mapping),
4424  MYF(MY_ALLOW_ZERO_PTR));
4425 
4426  if (!index_mapping) {
4427  /* Report an error if index_mapping continues to be
4428  NULL and mysql_num_index is a non-zero value */
4429  sql_print_error("InnoDB: fail to allocate memory for "
4430  "index translation table. Number of "
4431  "Index:%lu, array size:%lu",
4432  mysql_num_index,
4433  share->idx_trans_tbl.array_size);
4434  ret = FALSE;
4435  goto func_exit;
4436  }
4437 
4438  share->idx_trans_tbl.array_size = mysql_num_index;
4439  }
4440 
4441  /* For each index in the mysql key_info array, fetch its
4442  corresponding InnoDB index pointer into index_mapping
4443  array. */
4444  for (ulint count = 0; count < mysql_num_index; count++) {
4445 
4446  /* Fetch index pointers into index_mapping according to mysql
4447  index sequence */
4448  index_mapping[count] = dict_table_get_index_on_name(
4449  ib_table, table->key_info[count].name);
4450 
4451  if (!index_mapping[count]) {
4452  sql_print_error("Cannot find index %s in InnoDB "
4453  "index dictionary.",
4454  table->key_info[count].name);
4455  ret = FALSE;
4456  goto func_exit;
4457  }
4458 
4459  /* Double check fetched index has the same
4460  column info as those in mysql key_info. */
4461  if (!innobase_match_index_columns(&table->key_info[count],
4462  index_mapping[count])) {
4463  sql_print_error("Found index %s whose column info "
4464  "does not match that of MySQL.",
4465  table->key_info[count].name);
4466  ret = FALSE;
4467  goto func_exit;
4468  }
4469  }
4470 
4471  /* Successfully built the translation table */
4472  share->idx_trans_tbl.index_count = mysql_num_index;
4473 
4474 func_exit:
4475  if (!ret) {
4476  /* Build translation table failed. */
4477  my_free(index_mapping);
4478 
4479  share->idx_trans_tbl.array_size = 0;
4480  share->idx_trans_tbl.index_count = 0;
4481  index_mapping = NULL;
4482  }
4483 
4484  share->idx_trans_tbl.index_mapping = index_mapping;
4485 
4486  mutex_exit(&dict_sys->mutex);
4487 
4488  DBUG_RETURN(ret);
4489 }
4490 
4491 /*******************************************************************/
4500 static
4501 dict_index_t*
4502 innobase_index_lookup(
4503 /*==================*/
4504  INNOBASE_SHARE* share,
4506  uint keynr)
4508 {
4509  if (!share->idx_trans_tbl.index_mapping
4510  || keynr >= share->idx_trans_tbl.index_count) {
4511  return(NULL);
4512  }
4513 
4514  return(share->idx_trans_tbl.index_mapping[keynr]);
4515 }
4516 
4517 /************************************************************************
4518 Set the autoinc column max value. This should only be called once from
4519 ha_innobase::open(). Therefore there's no need for a covering lock. */
4520 UNIV_INTERN
4521 void
4522 ha_innobase::innobase_initialize_autoinc()
4523 /*======================================*/
4524 {
4525  ulonglong auto_inc;
4526  const Field* field = table->found_next_number_field;
4527 
4528  if (field != NULL) {
4529  auto_inc = innobase_get_int_col_max_value(field);
4530  } else {
4531  /* We have no idea what's been passed in to us as the
4532  autoinc column. We set it to the 0, effectively disabling
4533  updates to the table. */
4534  auto_inc = 0;
4535 
4536  ut_print_timestamp(stderr);
4537  fprintf(stderr, " InnoDB: Unable to determine the AUTOINC "
4538  "column name\n");
4539  }
4540 
4542  /* If the recovery level is set so high that writes
4543  are disabled we force the AUTOINC counter to 0
4544  value effectively disabling writes to the table.
4545  Secondly, we avoid reading the table in case the read
4546  results in failure due to a corrupted table/index.
4547 
4548  We will not return an error to the client, so that the
4549  tables can be dumped with minimal hassle. If an error
4550  were returned in this case, the first attempt to read
4551  the table would fail and subsequent SELECTs would succeed. */
4552  auto_inc = 0;
4553  } else if (field == NULL) {
4554  /* This is a far more serious error, best to avoid
4555  opening the table and return failure. */
4556  my_error(ER_AUTOINC_READ_FAILED, MYF(0));
4557  } else {
4559  const char* col_name;
4560  ib_uint64_t read_auto_inc;
4561  ulint err;
4562 
4563  update_thd(ha_thd());
4564 
4565  ut_a(prebuilt->trx == thd_to_trx(user_thd));
4566 
4567  col_name = field->field_name;
4568  index = innobase_get_index(table->s->next_number_index);
4569 
4570  /* Execute SELECT MAX(col_name) FROM TABLE; */
4571  err = row_search_max_autoinc(index, col_name, &read_auto_inc);
4572 
4573  switch (err) {
4574  case DB_SUCCESS: {
4575  ulonglong col_max_value;
4576 
4577  col_max_value = innobase_get_int_col_max_value(field);
4578 
4579  /* At the this stage we do not know the increment
4580  nor the offset, so use a default increment of 1. */
4581 
4582  auto_inc = innobase_next_autoinc(
4583  read_auto_inc, 1, 1, 0, col_max_value);
4584 
4585  break;
4586  }
4587  case DB_RECORD_NOT_FOUND:
4588  ut_print_timestamp(stderr);
4589  fprintf(stderr, " InnoDB: MySQL and InnoDB data "
4590  "dictionaries are out of sync.\n"
4591  "InnoDB: Unable to find the AUTOINC column "
4592  "%s in the InnoDB table %s.\n"
4593  "InnoDB: We set the next AUTOINC column "
4594  "value to 0,\n"
4595  "InnoDB: in effect disabling the AUTOINC "
4596  "next value generation.\n"
4597  "InnoDB: You can either set the next "
4598  "AUTOINC value explicitly using ALTER TABLE\n"
4599  "InnoDB: or fix the data dictionary by "
4600  "recreating the table.\n",
4601  col_name, index->table->name);
4602 
4603  /* This will disable the AUTOINC generation. */
4604  auto_inc = 0;
4605 
4606  /* We want the open to succeed, so that the user can
4607  take corrective action. ie. reads should succeed but
4608  updates should fail. */
4609  err = DB_SUCCESS;
4610  break;
4611  default:
4612  /* row_search_max_autoinc() should only return
4613  one of DB_SUCCESS or DB_RECORD_NOT_FOUND. */
4614  ut_error;
4615  }
4616  }
4617 
4618  dict_table_autoinc_initialize(prebuilt->table, auto_inc);
4619 }
4620 
4621 /*****************************************************************/
4625 UNIV_INTERN
4626 int
4628 /*==============*/
4629  const char* name,
4630  int mode,
4631  uint test_if_locked)
4632 {
4633  dict_table_t* ib_table;
4634  char norm_name[FN_REFLEN];
4635  THD* thd;
4636  char* is_part = NULL;
4637  ibool par_case_name_set = FALSE;
4638  char par_case_name[FN_REFLEN];
4640 
4641  DBUG_ENTER("ha_innobase::open");
4642 
4643  UT_NOT_USED(mode);
4644  UT_NOT_USED(test_if_locked);
4645 
4646  thd = ha_thd();
4647 
4648  /* Under some cases MySQL seems to call this function while
4649  holding btr_search_latch. This breaks the latching order as
4650  we acquire dict_sys->mutex below and leads to a deadlock. */
4651  if (thd != NULL) {
4652  innobase_release_temporary_latches(ht, thd);
4653  }
4654 
4655  normalize_table_name(norm_name, name);
4656 
4657  user_thd = NULL;
4658 
4659  if (!(share=get_share(name))) {
4660 
4661  DBUG_RETURN(1);
4662  }
4663 
4664  /* Will be allocated if it is needed in ::update_row() */
4665  upd_buf = NULL;
4666  upd_buf_size = 0;
4667 
4668  /* We look for pattern #P# to see if the table is partitioned
4669  MySQL table. */
4670 #ifdef __WIN__
4671  is_part = strstr(norm_name, "#p#");
4672 #else
4673  is_part = strstr(norm_name, "#P#");
4674 #endif /* __WIN__ */
4675 
4676  /* Check whether FOREIGN_KEY_CHECKS is set to 0. If so, the table
4677  can be opened even if some FK indexes are missing. If not, the table
4678  can't be opened in the same situation */
4679  if (thd_test_options(thd, OPTION_NO_FOREIGN_KEY_CHECKS)) {
4680  ignore_err = DICT_ERR_IGNORE_FK_NOKEY;
4681  }
4682 
4683  /* Get pointer to a table object in InnoDB dictionary cache */
4684  ib_table = dict_table_open_on_name(norm_name, FALSE, TRUE, ignore_err);
4685 
4686  if (ib_table
4687  && ((!DICT_TF2_FLAG_IS_SET(ib_table, DICT_TF2_FTS_HAS_DOC_ID)
4688  && table->s->fields != dict_table_get_n_user_cols(ib_table))
4689  || (DICT_TF2_FLAG_IS_SET(ib_table, DICT_TF2_FTS_HAS_DOC_ID)
4690  && (table->s->fields
4691  != dict_table_get_n_user_cols(ib_table) - 1)))) {
4692  ib_logf(IB_LOG_LEVEL_WARN,
4693  "table %s contains %lu user defined columns "
4694  "in InnoDB, but %lu columns in MySQL. Please "
4695  "check INFORMATION_SCHEMA.INNODB_SYS_COLUMNS and "
4696  REFMAN "innodb-troubleshooting.html "
4697  "for how to resolve it",
4698  norm_name, (ulong) dict_table_get_n_user_cols(ib_table),
4699  (ulong) table->s->fields);
4700 
4701  /* Mark this table as corrupted, so the drop table
4702  or force recovery can still use it, but not others. */
4703  ib_table->corrupted = true;
4704  dict_table_close(ib_table, FALSE, FALSE);
4705  ib_table = NULL;
4706  is_part = NULL;
4707  }
4708 
4709  if (NULL == ib_table) {
4710  if (is_part) {
4711  /* MySQL partition engine hard codes the file name
4712  separator as "#P#". The text case is fixed even if
4713  lower_case_table_names is set to 1 or 2. This is true
4714  for sub-partition names as well. InnoDB always
4715  normalises file names to lower case on Windows, this
4716  can potentially cause problems when copying/moving
4717  tables between platforms.
4718 
4719  1) If boot against an installation from Windows
4720  platform, then its partition table name could
4721  be in lower case in system tables. So we will
4722  need to check lower case name when load table.
4723 
4724  2) If we boot an installation from other case
4725  sensitive platform in Windows, we might need to
4726  check the existence of table name without lower
4727  case in the system table. */
4729 
4730  if (!par_case_name_set) {
4731 #ifndef __WIN__
4732  /* Check for the table using lower
4733  case name, including the partition
4734  separator "P" */
4735  strcpy(par_case_name, norm_name);
4736  innobase_casedn_str(par_case_name);
4737 #else
4738  /* On Windows platfrom, check
4739  whether there exists table name in
4740  system table whose name is
4741  not being normalized to lower case */
4742  normalize_table_name_low(
4743  par_case_name, name, FALSE);
4744 #endif
4745  par_case_name_set = TRUE;
4746  }
4747 
4748  ib_table = dict_table_open_on_name(
4749  par_case_name, FALSE, TRUE,
4750  ignore_err);
4751  }
4752 
4753  if (ib_table) {
4754 #ifndef __WIN__
4755  sql_print_warning("Partition table %s opened "
4756  "after converting to lower "
4757  "case. The table may have "
4758  "been moved from a case "
4759  "in-sensitive file system. "
4760  "Please recreate table in "
4761  "the current file system\n",
4762  norm_name);
4763 #else
4764  sql_print_warning("Partition table %s opened "
4765  "after skipping the step to "
4766  "lower case the table name. "
4767  "The table may have been "
4768  "moved from a case sensitive "
4769  "file system. Please "
4770  "recreate table in the "
4771  "current file system\n",
4772  norm_name);
4773 #endif
4774  goto table_opened;
4775  }
4776  }
4777 
4778  if (is_part) {
4779  sql_print_error("Failed to open table %s.\n",
4780  norm_name);
4781  }
4782 
4783  ib_logf(IB_LOG_LEVEL_WARN,
4784  "Cannot open table %s from the internal data "
4785  "dictionary of InnoDB though the .frm file "
4786  "for the table exists. See "
4787  REFMAN "innodb-troubleshooting.html for how "
4788  "you can resolve the problem.", norm_name);
4789 
4790  free_share(share);
4791  my_errno = ENOENT;
4792 
4793  DBUG_RETURN(HA_ERR_NO_SUCH_TABLE);
4794  }
4795 
4796 table_opened:
4797 
4798  innobase_copy_frm_flags_from_table_share(ib_table, table->s);
4799 
4800  dict_stats_init(ib_table);
4801 
4802  MONITOR_INC(MONITOR_TABLE_OPEN);
4803 
4804  bool no_tablespace;
4805 
4806  if (dict_table_is_discarded(ib_table)) {
4807 
4808  ib_senderrf(thd,
4809  IB_LOG_LEVEL_WARN, ER_TABLESPACE_DISCARDED,
4810  table->s->table_name.str);
4811 
4812  /* Allow an open because a proper DISCARD should have set
4813  all the flags and index root page numbers to FIL_NULL that
4814  should prevent any DML from running but it should allow DDL
4815  operations. */
4816 
4817  no_tablespace = false;
4818 
4819  } else if (ib_table->ibd_file_missing) {
4820 
4821  ib_senderrf(
4822  thd, IB_LOG_LEVEL_WARN,
4823  ER_TABLESPACE_MISSING, norm_name);
4824 
4825  /* This means we have no idea what happened to the tablespace
4826  file, best to play it safe. */
4827 
4828  no_tablespace = true;
4829  } else {
4830  no_tablespace = false;
4831  }
4832 
4833  if (!thd_tablespace_op(thd) && no_tablespace) {
4834  free_share(share);
4835  my_errno = ENOENT;
4836 
4837  dict_table_close(ib_table, FALSE, FALSE);
4838 
4839  DBUG_RETURN(HA_ERR_NO_SUCH_TABLE);
4840  }
4841 
4842  prebuilt = row_create_prebuilt(ib_table, table->s->reclength);
4843 
4844  prebuilt->default_rec = table->s->default_values;
4845  ut_ad(prebuilt->default_rec);
4846 
4847  /* Looks like MySQL-3.23 sometimes has primary key number != 0 */
4848  primary_key = table->s->primary_key;
4849  key_used_on_scan = primary_key;
4850 
4851  if (!innobase_build_index_translation(table, ib_table, share)) {
4852  sql_print_error("Build InnoDB index translation table for"
4853  " Table %s failed", name);
4854  }
4855 
4856  /* Allocate a buffer for a 'row reference'. A row reference is
4857  a string of bytes of length ref_length which uniquely specifies
4858  a row in our table. Note that MySQL may also compare two row
4859  references for equality by doing a simple memcmp on the strings
4860  of length ref_length! */
4861 
4862  if (!row_table_got_default_clust_index(ib_table)) {
4863 
4864  prebuilt->clust_index_was_generated = FALSE;
4865 
4866  if (UNIV_UNLIKELY(primary_key >= MAX_KEY)) {
4867  sql_print_error("Table %s has a primary key in "
4868  "InnoDB data dictionary, but not "
4869  "in MySQL!", name);
4870 
4871  /* This mismatch could cause further problems
4872  if not attended, bring this to the user's attention
4873  by printing a warning in addition to log a message
4874  in the errorlog */
4875  push_warning_printf(thd, Sql_condition::WARN_LEVEL_WARN,
4876  ER_NO_SUCH_INDEX,
4877  "InnoDB: Table %s has a "
4878  "primary key in InnoDB data "
4879  "dictionary, but not in "
4880  "MySQL!", name);
4881 
4882  /* If primary_key >= MAX_KEY, its (primary_key)
4883  value could be out of bound if continue to index
4884  into key_info[] array. Find InnoDB primary index,
4885  and assign its key_length to ref_length.
4886  In addition, since MySQL indexes are sorted starting
4887  with primary index, unique index etc., initialize
4888  ref_length to the first index key length in
4889  case we fail to find InnoDB cluster index.
4890 
4891  Please note, this will not resolve the primary
4892  index mismatch problem, other side effects are
4893  possible if users continue to use the table.
4894  However, we allow this table to be opened so
4895  that user can adopt necessary measures for the
4896  mismatch while still being accessible to the table
4897  date. */
4898  if (!table->key_info) {
4899  ut_ad(!table->s->keys);
4900  ref_length = 0;
4901  } else {
4902  ref_length = table->key_info[0].key_length;
4903  }
4904 
4905  /* Find corresponding cluster index
4906  key length in MySQL's key_info[] array */
4907  for (ulint i = 0; i < table->s->keys; i++) {
4909  index = innobase_get_index(i);
4910  if (dict_index_is_clust(index)) {
4911  ref_length =
4912  table->key_info[i].key_length;
4913  }
4914  }
4915  } else {
4916  /* MySQL allocates the buffer for ref.
4917  key_info->key_length includes space for all key
4918  columns + one byte for each column that may be
4919  NULL. ref_length must be as exact as possible to
4920  save space, because all row reference buffers are
4921  allocated based on ref_length. */
4922 
4923  ref_length = table->key_info[primary_key].key_length;
4924  }
4925  } else {
4926  if (primary_key != MAX_KEY) {
4927  sql_print_error(
4928  "Table %s has no primary key in InnoDB data "
4929  "dictionary, but has one in MySQL! If you "
4930  "created the table with a MySQL version < "
4931  "3.23.54 and did not define a primary key, "
4932  "but defined a unique key with all non-NULL "
4933  "columns, then MySQL internally treats that "
4934  "key as the primary key. You can fix this "
4935  "error by dump + DROP + CREATE + reimport "
4936  "of the table.", name);
4937 
4938  /* This mismatch could cause further problems
4939  if not attended, bring this to the user attention
4940  by printing a warning in addition to log a message
4941  in the errorlog */
4942  push_warning_printf(thd, Sql_condition::WARN_LEVEL_WARN,
4943  ER_NO_SUCH_INDEX,
4944  "InnoDB: Table %s has no "
4945  "primary key in InnoDB data "
4946  "dictionary, but has one in "
4947  "MySQL!", name);
4948  }
4949 
4950  prebuilt->clust_index_was_generated = TRUE;
4951 
4952  ref_length = DATA_ROW_ID_LEN;
4953 
4954  /* If we automatically created the clustered index, then
4955  MySQL does not know about it, and MySQL must NOT be aware
4956  of the index used on scan, to make it avoid checking if we
4957  update the column of the index. That is why we assert below
4958  that key_used_on_scan is the undefined value MAX_KEY.
4959  The column is the row id in the automatical generation case,
4960  and it will never be updated anyway. */
4961 
4962  if (key_used_on_scan != MAX_KEY) {
4963  sql_print_warning(
4964  "Table %s key_used_on_scan is %lu even "
4965  "though there is no primary key inside "
4966  "InnoDB.", name, (ulong) key_used_on_scan);
4967  }
4968  }
4969 
4970  /* Index block size in InnoDB: used by MySQL in query optimization */
4971  stats.block_size = UNIV_PAGE_SIZE;
4972 
4973  /* Init table lock structure */
4974  thr_lock_data_init(&share->lock,&lock,(void*) 0);
4975 
4976  if (prebuilt->table) {
4977  /* We update the highest file format in the system table
4978  space, if this table has higher file format setting. */
4979 
4981  (const char**) &innobase_file_format_max,
4982  dict_table_get_format(prebuilt->table));
4983  }
4984 
4985  /* Only if the table has an AUTOINC column. */
4986  if (prebuilt->table != NULL
4987  && !prebuilt->table->ibd_file_missing
4988  && table->found_next_number_field != NULL) {
4989  dict_table_autoinc_lock(prebuilt->table);
4990 
4991  /* Since a table can already be "open" in InnoDB's internal
4992  data dictionary, we only init the autoinc counter once, the
4993  first time the table is loaded. We can safely reuse the
4994  autoinc value from a previous MySQL open. */
4995  if (dict_table_autoinc_read(prebuilt->table) == 0) {
4996 
4997  innobase_initialize_autoinc();
4998  }
4999 
5000  dict_table_autoinc_unlock(prebuilt->table);
5001  }
5002 
5003  info(HA_STATUS_NO_LOCK | HA_STATUS_VARIABLE | HA_STATUS_CONST);
5004 
5005  DBUG_RETURN(0);
5006 }
5007 
5008 UNIV_INTERN
5009 handler*
5011 /*===============*/
5012  const char* name,
5013  MEM_ROOT* mem_root)
5014 {
5015  ha_innobase* new_handler;
5016 
5017  DBUG_ENTER("ha_innobase::clone");
5018 
5019  new_handler = static_cast<ha_innobase*>(handler::clone(name,
5020  mem_root));
5021  if (new_handler) {
5022  DBUG_ASSERT(new_handler->prebuilt != NULL);
5023 
5024  new_handler->prebuilt->select_lock_type
5025  = prebuilt->select_lock_type;
5026  }
5027 
5028  DBUG_RETURN(new_handler);
5029 }
5030 
5031 UNIV_INTERN
5032 uint
5033 ha_innobase::max_supported_key_part_length() const
5034 /*==============================================*/
5035 {
5036  /* A table format specific index column length check will be performed
5037  at ha_innobase::add_index() and row_create_index_for_mysql() */
5038  return(innobase_large_prefix
5040  : REC_ANTELOPE_MAX_INDEX_COL_LEN - 1);
5041 }
5042 
5043 /******************************************************************/
5046 UNIV_INTERN
5047 int
5049 /*================*/
5050 {
5051  THD* thd;
5052 
5053  DBUG_ENTER("ha_innobase::close");
5054 
5055  thd = ha_thd();
5056  if (thd != NULL) {
5057  innobase_release_temporary_latches(ht, thd);
5058  }
5059 
5060  row_prebuilt_free(prebuilt, FALSE);
5061 
5062  if (upd_buf != NULL) {
5063  ut_ad(upd_buf_size != 0);
5064  my_free(upd_buf);
5065  upd_buf = NULL;
5066  upd_buf_size = 0;
5067  }
5068 
5069  free_share(share);
5070 
5071  MONITOR_INC(MONITOR_TABLE_CLOSE);
5072 
5073  /* Tell InnoDB server that there might be work for
5074  utility threads: */
5075 
5077 
5078  DBUG_RETURN(0);
5079 }
5080 
5081 /* The following accessor functions should really be inside MySQL code! */
5082 
5083 /**************************************************************/
5086 static inline
5087 uint
5088 get_field_offset(
5089 /*=============*/
5090  const TABLE* table,
5091  const Field* field)
5092 {
5093  return((uint) (field->ptr - table->record[0]));
5094 }
5095 
5096 /*************************************************************/
5102 UNIV_INTERN
5103 int
5105 /*===============*/
5106  int mysql_type,
5107  uint charset_number,
5108  const unsigned char* a,
5109  unsigned int a_length,
5111  const unsigned char* b,
5112  unsigned int b_length)
5114 {
5115  CHARSET_INFO* charset;
5116  enum_field_types mysql_tp;
5117  int ret;
5118 
5119  DBUG_ASSERT(a_length != UNIV_SQL_NULL);
5120  DBUG_ASSERT(b_length != UNIV_SQL_NULL);
5121 
5122  mysql_tp = (enum_field_types) mysql_type;
5123 
5124  switch (mysql_tp) {
5125 
5126  case MYSQL_TYPE_BIT:
5127  case MYSQL_TYPE_STRING:
5128  case MYSQL_TYPE_VAR_STRING:
5129  case MYSQL_TYPE_TINY_BLOB:
5130  case MYSQL_TYPE_MEDIUM_BLOB:
5131  case MYSQL_TYPE_BLOB:
5132  case MYSQL_TYPE_LONG_BLOB:
5133  case MYSQL_TYPE_VARCHAR:
5134  /* Use the charset number to pick the right charset struct for
5135  the comparison. Since the MySQL function get_charset may be
5136  slow before Bar removes the mutex operation there, we first
5137  look at 2 common charsets directly. */
5138 
5139  if (charset_number == default_charset_info->number) {
5140  charset = default_charset_info;
5141  } else if (charset_number == my_charset_latin1.number) {
5142  charset = &my_charset_latin1;
5143  } else {
5144  charset = get_charset(charset_number, MYF(MY_WME));
5145 
5146  if (charset == NULL) {
5147  sql_print_error("InnoDB needs charset %lu for doing "
5148  "a comparison, but MySQL cannot "
5149  "find that charset.",
5150  (ulong) charset_number);
5151  ut_a(0);
5152  }
5153  }
5154 
5155  /* Starting from 4.1.3, we use strnncollsp() in comparisons of
5156  non-latin1_swedish_ci strings. NOTE that the collation order
5157  changes then: 'b\0\0...' is ordered BEFORE 'b ...'. Users
5158  having indexes on such data need to rebuild their tables! */
5159 
5160  ret = charset->coll->strnncollsp(
5161  charset, a, a_length, b, b_length, 0);
5162 
5163  if (ret < 0) {
5164  return(-1);
5165  } else if (ret > 0) {
5166  return(1);
5167  } else {
5168  return(0);
5169  }
5170  default:
5171  ut_error;
5172  }
5173 
5174  return(0);
5175 }
5176 
5177 
5178 /*************************************************************/
5180 UNIV_INTERN
5181 CHARSET_INFO*
5183 /*=====================*/
5184  int mysql_type,
5185  uint charset_number)
5186 {
5187  enum_field_types mysql_tp;
5188  CHARSET_INFO* charset;
5189 
5190  mysql_tp = (enum_field_types) mysql_type;
5191 
5192  switch (mysql_tp) {
5193 
5194  case MYSQL_TYPE_BIT:
5195  case MYSQL_TYPE_STRING:
5196  case MYSQL_TYPE_VAR_STRING:
5197  case MYSQL_TYPE_TINY_BLOB:
5198  case MYSQL_TYPE_MEDIUM_BLOB:
5199  case MYSQL_TYPE_BLOB:
5200  case MYSQL_TYPE_LONG_BLOB:
5201  case MYSQL_TYPE_VARCHAR:
5202  /* Use the charset number to pick the right charset struct for
5203  the comparison. Since the MySQL function get_charset may be
5204  slow before Bar removes the mutex operation there, we first
5205  look at 2 common charsets directly. */
5206 
5207  if (charset_number == default_charset_info->number) {
5208  charset = default_charset_info;
5209  } else if (charset_number == my_charset_latin1.number) {
5210  charset = &my_charset_latin1;
5211  } else {
5212  charset = get_charset(charset_number, MYF(MY_WME));
5213 
5214  if (charset == NULL) {
5215  sql_print_error("InnoDB needs charset %lu for doing "
5216  "a comparison, but MySQL cannot "
5217  "find that charset.",
5218  (ulong) charset_number);
5219  ut_a(0);
5220  }
5221  }
5222  break;
5223  default:
5224  ut_error;
5225  }
5226 
5227  return(charset);
5228 }
5229 
5230 /*************************************************************/
5236 UNIV_INTERN
5237 int
5239 /*======================*/
5240  int mysql_type,
5241  uint charset_number,
5242  const unsigned char* a,
5243  unsigned int a_length,
5245  const unsigned char* b,
5246  unsigned int b_length)
5248 {
5249  CHARSET_INFO* charset;
5250  int result;
5251 
5252  charset = innobase_get_fts_charset(mysql_type, charset_number);
5253 
5254  result = ha_compare_text(charset, (uchar*) a, a_length,
5255  (uchar*) b, b_length, 1, 0);
5256 
5257  return(result);
5258 }
5259 /******************************************************************/
5261 UNIV_INTERN
5262 int
5264 /*==================*/
5265  const void* cs,
5266  const void* p1,
5267  const void* p2)
5268 {
5269  const CHARSET_INFO* charset = (const CHARSET_INFO*) cs;
5270  const fts_string_t* s1 = (const fts_string_t*) p1;
5271  const fts_string_t* s2 = (const fts_string_t*) p2;
5272 
5273  return(ha_compare_text(charset, s1->f_str, s1->f_len,
5274  s2->f_str, s2->f_len, 0, 0));
5275 }
5276 /******************************************************************/
5278 UNIV_INTERN
5279 int
5281 /*=======================*/
5282  const void* cs,
5283  const void* p1,
5284  const void* p2)
5285 {
5286  const CHARSET_INFO* charset = (const CHARSET_INFO*) cs;
5287  const fts_string_t* s1 = (const fts_string_t*) p1;
5288  const fts_string_t* s2 = (const fts_string_t*) p2;
5289  ulint newlen;
5290 
5291  my_casedn_str(charset, (char*) s2->f_str);
5292 
5293  newlen = strlen((const char*) s2->f_str);
5294 
5295  return(ha_compare_text(charset, s1->f_str, s1->f_len,
5296  s2->f_str, newlen, 0, 0));
5297 }
5298 /******************************************************************/
5300 UNIV_INTERN
5301 ulint
5303 /*==============*/
5304  const CHARSET_INFO*
5305  cs,
5306  const uchar* str,
5307  const ulint len)
5308 {
5309  uchar mystr[2];
5310  ulint value;
5311 
5312  if (!str || len == 0) {
5313  return(0);
5314  }
5315 
5316  my_strnxfrm(cs, (uchar*) mystr, 2, str, len);
5317 
5318  value = mach_read_from_2(mystr);
5319 
5320  if (value > 255) {
5321  value = value / 256;
5322  }
5323 
5324  return(value);
5325 }
5326 
5327 /******************************************************************/
5329 UNIV_INTERN
5330 int
5332 /*=========================*/
5333  const void* cs,
5334  const void* p1,
5335  const void* p2)
5336 {
5337  const CHARSET_INFO* charset = (const CHARSET_INFO*) cs;
5338  const fts_string_t* s1 = (const fts_string_t*) p1;
5339  const fts_string_t* s2 = (const fts_string_t*) p2;
5340  int result;
5341 
5342  result = ha_compare_text(charset, s2->f_str, s2->f_len,
5343  s1->f_str, s1->f_len, 1, 0);
5344 
5345  /* We switched s1, s2 position in ha_compare_text. So we need
5346  to negate the result */
5347  return(-result);
5348 }
5349 /******************************************************************/
5351 UNIV_INTERN
5352 int
5354 /*====================*/
5355  const void* cs,
5356  const void* p1,
5357  const void* p2)
5358 {
5359  const CHARSET_INFO* charset = (const CHARSET_INFO*) cs;
5360  uchar* s1 = (uchar*) p1;
5361  uchar* s2 = *(uchar**) p2;
5362 
5363  return(ha_compare_text(charset, s1, strlen((const char*) s1),
5364  s2, strlen((const char*) s2), 0, 0));
5365 }
5366 /******************************************************************/
5368 UNIV_INTERN
5369 size_t
5371 /*====================*/
5372  CHARSET_INFO* cs,
5373  char* src,
5374  size_t src_len,
5375  char* dst,
5376  size_t dst_len)
5377 {
5378  if (cs->casedn_multiply == 1) {
5379  memcpy(dst, src, src_len);
5380  dst[src_len] = 0;
5381  my_casedn_str(cs, dst);
5382 
5383  return(strlen(dst));
5384  } else {
5385  return(cs->cset->casedn(cs, src, src_len, dst, dst_len));
5386  }
5387 }
5388 
5389 #define true_word_char(c, ch) ((c) & (_MY_U | _MY_L | _MY_NMR) || (ch) == '_')
5390 
5391 #define misc_word_char(X) 0
5392 
5393 /*************************************************************/
5397 UNIV_INTERN
5398 ulint
5400 /*=========================*/
5401  CHARSET_INFO* cs,
5402  const byte* start,
5403  const byte* end,
5405  fts_string_t* token,
5406  ulint* offset)
5409 {
5410  int mbl;
5411  const uchar* doc = start;
5412 
5413  ut_a(cs);
5414 
5415  token->f_n_char = token->f_len = 0;
5416 
5417  for (;;) {
5418 
5419  if (doc >= end) {
5420  return(doc - start);
5421  }
5422 
5423  int ctype;
5424 
5425  mbl = cs->cset->ctype(
5426  cs, &ctype, doc, (const uchar*) end);
5427 
5428  if (true_word_char(ctype, *doc)) {
5429  break;
5430  }
5431 
5432  doc += mbl > 0 ? mbl : (mbl < 0 ? -mbl : 1);
5433  }
5434 
5435  ulint mwc = 0;
5436  ulint length = 0;
5437 
5438  token->f_str = const_cast<byte*>(doc);
5439 
5440  while (doc < end) {
5441 
5442  int ctype;
5443 
5444  mbl = cs->cset->ctype(
5445  cs, &ctype, (uchar*) doc, (uchar*) end);
5446  if (true_word_char(ctype, *doc)) {
5447  mwc = 0;
5448  } else if (!misc_word_char(*doc) || mwc) {
5449  break;
5450  } else {
5451  ++mwc;
5452  }
5453 
5454  ++length;
5455 
5456  doc += mbl > 0 ? mbl : (mbl < 0 ? -mbl : 1);
5457  }
5458 
5459  token->f_len = (uint) (doc - token->f_str) - mwc;
5460  token->f_n_char = length;
5461 
5462  return(doc - start);
5463 }
5464 
5465 /**************************************************************/
5470 UNIV_INTERN
5471 ulint
5473 /*==============================*/
5474  ulint* unsigned_flag,
5479  const void* f)
5480 {
5481  const class Field* field = reinterpret_cast<const class Field*>(f);
5482 
5483  /* The following asserts try to check that the MySQL type code fits in
5484  8 bits: this is used in ibuf and also when DATA_NOT_NULL is ORed to
5485  the type */
5486 
5487  DBUG_ASSERT((ulint)MYSQL_TYPE_STRING < 256);
5488  DBUG_ASSERT((ulint)MYSQL_TYPE_VAR_STRING < 256);
5489  DBUG_ASSERT((ulint)MYSQL_TYPE_DOUBLE < 256);
5490  DBUG_ASSERT((ulint)MYSQL_TYPE_FLOAT < 256);
5491  DBUG_ASSERT((ulint)MYSQL_TYPE_DECIMAL < 256);
5492 
5493  if (field->flags & UNSIGNED_FLAG) {
5494 
5495  *unsigned_flag = DATA_UNSIGNED;
5496  } else {
5497  *unsigned_flag = 0;
5498  }
5499 
5500  if (field->real_type() == MYSQL_TYPE_ENUM
5501  || field->real_type() == MYSQL_TYPE_SET) {
5502 
5503  /* MySQL has field->type() a string type for these, but the
5504  data is actually internally stored as an unsigned integer
5505  code! */
5506 
5507  *unsigned_flag = DATA_UNSIGNED; /* MySQL has its own unsigned
5508  flag set to zero, even though
5509  internally this is an unsigned
5510  integer type */
5511  return(DATA_INT);
5512  }
5513 
5514  switch (field->type()) {
5515  /* NOTE that we only allow string types in DATA_MYSQL and
5516  DATA_VARMYSQL */
5517  case MYSQL_TYPE_VAR_STRING: /* old <= 4.1 VARCHAR */
5518  case MYSQL_TYPE_VARCHAR: /* new >= 5.0.3 true VARCHAR */
5519  if (field->binary()) {
5520  return(DATA_BINARY);
5521  } else if (strcmp(field->charset()->name,
5522  "latin1_swedish_ci") == 0) {
5523  return(DATA_VARCHAR);
5524  } else {
5525  return(DATA_VARMYSQL);
5526  }
5527  case MYSQL_TYPE_BIT:
5528  case MYSQL_TYPE_STRING: if (field->binary()) {
5529 
5530  return(DATA_FIXBINARY);
5531  } else if (strcmp(field->charset()->name,
5532  "latin1_swedish_ci") == 0) {
5533  return(DATA_CHAR);
5534  } else {
5535  return(DATA_MYSQL);
5536  }
5537  case MYSQL_TYPE_NEWDECIMAL:
5538  return(DATA_FIXBINARY);
5539  case MYSQL_TYPE_LONG:
5540  case MYSQL_TYPE_LONGLONG:
5541  case MYSQL_TYPE_TINY:
5542  case MYSQL_TYPE_SHORT:
5543  case MYSQL_TYPE_INT24:
5544  case MYSQL_TYPE_DATE:
5545  case MYSQL_TYPE_YEAR:
5546  case MYSQL_TYPE_NEWDATE:
5547  return(DATA_INT);
5548  case MYSQL_TYPE_TIME:
5549  case MYSQL_TYPE_DATETIME:
5550  case MYSQL_TYPE_TIMESTAMP:
5551  switch (field->real_type()) {
5552  case MYSQL_TYPE_TIME:
5553  case MYSQL_TYPE_DATETIME:
5554  case MYSQL_TYPE_TIMESTAMP:
5555  return(DATA_INT);
5556  default: /* Fall through */
5557  DBUG_ASSERT((ulint)MYSQL_TYPE_DECIMAL < 256);
5558  case MYSQL_TYPE_TIME2:
5559  case MYSQL_TYPE_DATETIME2:
5560  case MYSQL_TYPE_TIMESTAMP2:
5561  return(DATA_FIXBINARY);
5562  }
5563  case MYSQL_TYPE_FLOAT:
5564  return(DATA_FLOAT);
5565  case MYSQL_TYPE_DOUBLE:
5566  return(DATA_DOUBLE);
5567  case MYSQL_TYPE_DECIMAL:
5568  return(DATA_DECIMAL);
5569  case MYSQL_TYPE_GEOMETRY:
5570  case MYSQL_TYPE_TINY_BLOB:
5571  case MYSQL_TYPE_MEDIUM_BLOB:
5572  case MYSQL_TYPE_BLOB:
5573  case MYSQL_TYPE_LONG_BLOB:
5574  return(DATA_BLOB);
5575  case MYSQL_TYPE_NULL:
5576  /* MySQL currently accepts "NULL" datatype, but will
5577  reject such datatype in the next release. We will cope
5578  with it and not trigger assertion failure in 5.1 */
5579  break;
5580  default:
5581  ut_error;
5582  }
5583 
5584  return(0);
5585 }
5586 
5587 /*******************************************************************/
5590 static inline
5591 void
5592 innobase_write_to_2_little_endian(
5593 /*==============================*/
5594  byte* buf,
5595  ulint val)
5596 {
5597  ut_a(val < 256 * 256);
5598 
5599  buf[0] = (byte)(val & 0xFF);
5600  buf[1] = (byte)(val / 256);
5601 }
5602 
5603 /*******************************************************************/
5607 static inline
5608 uint
5609 innobase_read_from_2_little_endian(
5610 /*===============================*/
5611  const uchar* buf)
5612 {
5613  return((uint) ((ulint)(buf[0]) + 256 * ((ulint)(buf[1]))));
5614 }
5615 
5616 /*******************************************************************/
5619 UNIV_INTERN
5620 uint
5621 ha_innobase::store_key_val_for_row(
5622 /*===============================*/
5623  uint keynr,
5624  char* buff,
5626  uint buff_len,
5627  const uchar* record)
5628 {
5629  KEY* key_info = table->key_info + keynr;
5630  KEY_PART_INFO* key_part = key_info->key_part;
5631  KEY_PART_INFO* end =
5632  key_part + key_info->user_defined_key_parts;
5633  char* buff_start = buff;
5634  enum_field_types mysql_type;
5635  Field* field;
5636  ibool is_null;
5637 
5638  DBUG_ENTER("store_key_val_for_row");
5639 
5640  /* The format for storing a key field in MySQL is the following:
5641 
5642  1. If the column can be NULL, then in the first byte we put 1 if the
5643  field value is NULL, 0 otherwise.
5644 
5645  2. If the column is of a BLOB type (it must be a column prefix field
5646  in this case), then we put the length of the data in the field to the
5647  next 2 bytes, in the little-endian format. If the field is SQL NULL,
5648  then these 2 bytes are set to 0. Note that the length of data in the
5649  field is <= column prefix length.
5650 
5651  3. In a column prefix field, prefix_len next bytes are reserved for
5652  data. In a normal field the max field length next bytes are reserved
5653  for data. For a VARCHAR(n) the max field length is n. If the stored
5654  value is the SQL NULL then these data bytes are set to 0.
5655 
5656  4. We always use a 2 byte length for a true >= 5.0.3 VARCHAR. Note that
5657  in the MySQL row format, the length is stored in 1 or 2 bytes,
5658  depending on the maximum allowed length. But in the MySQL key value
5659  format, the length always takes 2 bytes.
5660 
5661  We have to zero-fill the buffer so that MySQL is able to use a
5662  simple memcmp to compare two key values to determine if they are
5663  equal. MySQL does this to compare contents of two 'ref' values. */
5664 
5665  memset(buff, 0, buff_len);
5666 
5667  for (; key_part != end; key_part++) {
5668  is_null = FALSE;
5669 
5670  if (key_part->null_bit) {
5671  if (record[key_part->null_offset]
5672  & key_part->null_bit) {
5673  *buff = 1;
5674  is_null = TRUE;
5675  } else {
5676  *buff = 0;
5677  }
5678  buff++;
5679  }
5680 
5681  field = key_part->field;
5682  mysql_type = field->type();
5683 
5684  if (mysql_type == MYSQL_TYPE_VARCHAR) {
5685  /* >= 5.0.3 true VARCHAR */
5686  ulint lenlen;
5687  ulint len;
5688  const byte* data;
5689  ulint key_len;
5690  ulint true_len;
5691  const CHARSET_INFO* cs;
5692  int error=0;
5693 
5694  key_len = key_part->length;
5695 
5696  if (is_null) {
5697  buff += key_len + 2;
5698 
5699  continue;
5700  }
5701  cs = field->charset();
5702 
5703  lenlen = (ulint)
5704  (((Field_varstring*) field)->length_bytes);
5705 
5706  data = row_mysql_read_true_varchar(&len,
5707  (byte*) (record
5708  + (ulint) get_field_offset(table, field)),
5709  lenlen);
5710 
5711  true_len = len;
5712 
5713  /* For multi byte character sets we need to calculate
5714  the true length of the key */
5715 
5716  if (len > 0 && cs->mbmaxlen > 1) {
5717  true_len = (ulint) cs->cset->well_formed_len(cs,
5718  (const char*) data,
5719  (const char*) data + len,
5720  (uint) (key_len / cs->mbmaxlen),
5721  &error);
5722  }
5723 
5724  /* In a column prefix index, we may need to truncate
5725  the stored value: */
5726 
5727  if (true_len > key_len) {
5728  true_len = key_len;
5729  }
5730 
5731  /* The length in a key value is always stored in 2
5732  bytes */
5733 
5734  row_mysql_store_true_var_len((byte*) buff, true_len, 2);
5735  buff += 2;
5736 
5737  memcpy(buff, data, true_len);
5738 
5739  /* Note that we always reserve the maximum possible
5740  length of the true VARCHAR in the key value, though
5741  only len first bytes after the 2 length bytes contain
5742  actual data. The rest of the space was reset to zero
5743  in the memset() call above. */
5744 
5745  buff += key_len;
5746 
5747  } else if (mysql_type == MYSQL_TYPE_TINY_BLOB
5748  || mysql_type == MYSQL_TYPE_MEDIUM_BLOB
5749  || mysql_type == MYSQL_TYPE_BLOB
5750  || mysql_type == MYSQL_TYPE_LONG_BLOB
5751  /* MYSQL_TYPE_GEOMETRY data is treated
5752  as BLOB data in innodb. */
5753  || mysql_type == MYSQL_TYPE_GEOMETRY) {
5754 
5755  const CHARSET_INFO* cs;
5756  ulint key_len;
5757  ulint true_len;
5758  int error=0;
5759  ulint blob_len;
5760  const byte* blob_data;
5761 
5762  ut_a(key_part->key_part_flag & HA_PART_KEY_SEG);
5763 
5764  key_len = key_part->length;
5765 
5766  if (is_null) {
5767  buff += key_len + 2;
5768 
5769  continue;
5770  }
5771 
5772  cs = field->charset();
5773 
5774  blob_data = row_mysql_read_blob_ref(&blob_len,
5775  (byte*) (record
5776  + (ulint) get_field_offset(table, field)),
5777  (ulint) field->pack_length());
5778 
5779  true_len = blob_len;
5780 
5781  ut_a(get_field_offset(table, field)
5782  == key_part->offset);
5783 
5784  /* For multi byte character sets we need to calculate
5785  the true length of the key */
5786 
5787  if (blob_len > 0 && cs->mbmaxlen > 1) {
5788  true_len = (ulint) cs->cset->well_formed_len(cs,
5789  (const char*) blob_data,
5790  (const char*) blob_data
5791  + blob_len,
5792  (uint) (key_len / cs->mbmaxlen),
5793  &error);
5794  }
5795 
5796  /* All indexes on BLOB and TEXT are column prefix
5797  indexes, and we may need to truncate the data to be
5798  stored in the key value: */
5799 
5800  if (true_len > key_len) {
5801  true_len = key_len;
5802  }
5803 
5804  /* MySQL reserves 2 bytes for the length and the
5805  storage of the number is little-endian */
5806 
5807  innobase_write_to_2_little_endian(
5808  (byte*) buff, true_len);
5809  buff += 2;
5810 
5811  memcpy(buff, blob_data, true_len);
5812 
5813  /* Note that we always reserve the maximum possible
5814  length of the BLOB prefix in the key value. */
5815 
5816  buff += key_len;
5817  } else {
5818  /* Here we handle all other data types except the
5819  true VARCHAR, BLOB and TEXT. Note that the column
5820  value we store may be also in a column prefix
5821  index. */
5822 
5823  const CHARSET_INFO* cs = NULL;
5824  ulint true_len;
5825  ulint key_len;
5826  const uchar* src_start;
5827  int error=0;
5828  enum_field_types real_type;
5829 
5830  key_len = key_part->length;
5831 
5832  if (is_null) {
5833  buff += key_len;
5834 
5835  continue;
5836  }
5837 
5838  src_start = record + key_part->offset;
5839  real_type = field->real_type();
5840  true_len = key_len;
5841 
5842  /* Character set for the field is defined only
5843  to fields whose type is string and real field
5844  type is not enum or set. For these fields check
5845  if character set is multi byte. */
5846 
5847  if (real_type != MYSQL_TYPE_ENUM
5848  && real_type != MYSQL_TYPE_SET
5849  && ( mysql_type == MYSQL_TYPE_VAR_STRING
5850  || mysql_type == MYSQL_TYPE_STRING)) {
5851 
5852  cs = field->charset();
5853 
5854  /* For multi byte character sets we need to
5855  calculate the true length of the key */
5856 
5857  if (key_len > 0 && cs->mbmaxlen > 1) {
5858 
5859  true_len = (ulint)
5860  cs->cset->well_formed_len(cs,
5861  (const char*) src_start,
5862  (const char*) src_start
5863  + key_len,
5864  (uint) (key_len
5865  / cs->mbmaxlen),
5866  &error);
5867  }
5868  }
5869 
5870  memcpy(buff, src_start, true_len);
5871  buff += true_len;
5872 
5873  /* Pad the unused space with spaces. */
5874 
5875  if (true_len < key_len) {
5876  ulint pad_len = key_len - true_len;
5877  ut_a(cs != NULL);
5878  ut_a(!(pad_len % cs->mbminlen));
5879 
5880  cs->cset->fill(cs, buff, pad_len,
5881  0x20 /* space */);
5882  buff += pad_len;
5883  }
5884  }
5885  }
5886 
5887  ut_a(buff <= buff_start + buff_len);
5888 
5889  DBUG_RETURN((uint)(buff - buff_start));
5890 }
5891 
5892 /**************************************************************/
5895 static
5896 const Field*
5897 build_template_needs_field(
5898 /*=======================*/
5899  ibool index_contains,
5902  ibool read_just_key,
5908  ibool fetch_all_in_key,
5911  ibool fetch_primary_key_cols,
5914  dict_index_t* index,
5915  const TABLE* table,
5916  ulint i)
5917 {
5918  const Field* field = table->field[i];
5919 
5920  ut_ad(index_contains == dict_index_contains_col_or_prefix(index, i));
5921 
5922  if (!index_contains) {
5923  if (read_just_key) {
5924  /* If this is a 'key read', we do not need
5925  columns that are not in the key */
5926 
5927  return(NULL);
5928  }
5929  } else if (fetch_all_in_key) {
5930  /* This field is needed in the query */
5931 
5932  return(field);
5933  }
5934 
5935  if (bitmap_is_set(table->read_set, i)
5936  || bitmap_is_set(table->write_set, i)) {
5937  /* This field is needed in the query */
5938 
5939  return(field);
5940  }
5941 
5942  if (fetch_primary_key_cols
5943  && dict_table_col_in_clustered_key(index->table, i)) {
5944  /* This field is needed in the query */
5945 
5946  return(field);
5947  }
5948 
5949  /* This field is not needed in the query, skip it */
5950 
5951  return(NULL);
5952 }
5953 
5954 /**************************************************************/
5957 inline
5958 bool
5960 /*==============================*/
5961  const dict_index_t* index,
5962  const row_prebuilt_t* prebuilt,
5963  bool contains,
5965  ulint i)
5966 {
5967  ut_ad(contains == dict_index_contains_col_or_prefix(index, i));
5968 
5969  return(index == prebuilt->index
5970  ? contains
5971  : dict_index_contains_col_or_prefix(prebuilt->index, i));
5972 }
5973 
5974 /**************************************************************/
5977 static
5979 build_template_field(
5980 /*=================*/
5981  row_prebuilt_t* prebuilt,
5982  dict_index_t* clust_index,
5983  dict_index_t* index,
5984  TABLE* table,
5985  const Field* field,
5986  ulint i)
5987 {
5988  mysql_row_templ_t* templ;
5989  const dict_col_t* col;
5990 
5991  ut_ad(field == table->field[i]);
5992  ut_ad(clust_index->table == index->table);
5993 
5994  col = dict_table_get_nth_col(index->table, i);
5995 
5996  templ = prebuilt->mysql_template + prebuilt->n_template++;
5997  UNIV_MEM_INVALID(templ, sizeof *templ);
5998  templ->col_no = i;
5999  templ->clust_rec_field_no = dict_col_get_clust_pos(col, clust_index);
6000  ut_a(templ->clust_rec_field_no != ULINT_UNDEFINED);
6001 
6002  if (dict_index_is_clust(index)) {
6003  templ->rec_field_no = templ->clust_rec_field_no;
6004  } else {
6005  templ->rec_field_no = dict_index_get_nth_col_pos(index, i);
6006  }
6007 
6008  if (field->real_maybe_null()) {
6009  templ->mysql_null_byte_offset =
6010  field->null_offset();
6011 
6012  templ->mysql_null_bit_mask = (ulint) field->null_bit;
6013  } else {
6014  templ->mysql_null_bit_mask = 0;
6015  }
6016 
6017  templ->mysql_col_offset = (ulint) get_field_offset(table, field);
6018 
6019  templ->mysql_col_len = (ulint) field->pack_length();
6020  templ->type = col->mtype;
6021  templ->mysql_type = (ulint) field->type();
6022 
6023  if (templ->mysql_type == DATA_MYSQL_TRUE_VARCHAR) {
6024  templ->mysql_length_bytes = (ulint)
6025  (((Field_varstring*) field)->length_bytes);
6026  }
6027 
6028  templ->charset = dtype_get_charset_coll(col->prtype);
6029  templ->mbminlen = dict_col_get_mbminlen(col);
6030  templ->mbmaxlen = dict_col_get_mbmaxlen(col);
6031  templ->is_unsigned = col->prtype & DATA_UNSIGNED;
6032 
6033  if (!dict_index_is_clust(index)
6034  && templ->rec_field_no == ULINT_UNDEFINED) {
6035  prebuilt->need_to_access_clustered = TRUE;
6036  }
6037 
6038  if (prebuilt->mysql_prefix_len < templ->mysql_col_offset
6039  + templ->mysql_col_len) {
6040  prebuilt->mysql_prefix_len = templ->mysql_col_offset
6041  + templ->mysql_col_len;
6042  }
6043 
6044  if (templ->type == DATA_BLOB) {
6045  prebuilt->templ_contains_blob = TRUE;
6046  }
6047 
6048  return(templ);
6049 }
6050 
6051 /**************************************************************/
6054 UNIV_INTERN
6055 void
6056 ha_innobase::build_template(
6057 /*========================*/
6058  bool whole_row)
6060 {
6062  dict_index_t* clust_index;
6063  ulint n_fields;
6064  ibool fetch_all_in_key = FALSE;
6065  ibool fetch_primary_key_cols = FALSE;
6066  ulint i;
6067 
6068  if (prebuilt->select_lock_type == LOCK_X) {
6069  /* We always retrieve the whole clustered index record if we
6070  use exclusive row level locks, for example, if the read is
6071  done in an UPDATE statement. */
6072 
6073  whole_row = true;
6074  } else if (!whole_row) {
6075  if (prebuilt->hint_need_to_fetch_extra_cols
6076  == ROW_RETRIEVE_ALL_COLS) {
6077 
6078  /* We know we must at least fetch all columns in the
6079  key, or all columns in the table */
6080 
6081  if (prebuilt->read_just_key) {
6082  /* MySQL has instructed us that it is enough
6083  to fetch the columns in the key; looks like
6084  MySQL can set this flag also when there is
6085  only a prefix of the column in the key: in
6086  that case we retrieve the whole column from
6087  the clustered index */
6088 
6089  fetch_all_in_key = TRUE;
6090  } else {
6091  whole_row = true;
6092  }
6093  } else if (prebuilt->hint_need_to_fetch_extra_cols
6094  == ROW_RETRIEVE_PRIMARY_KEY) {
6095  /* We must at least fetch all primary key cols. Note
6096  that if the clustered index was internally generated
6097  by InnoDB on the row id (no primary key was
6098  defined), then row_search_for_mysql() will always
6099  retrieve the row id to a special buffer in the
6100  prebuilt struct. */
6101 
6102  fetch_primary_key_cols = TRUE;
6103  }
6104  }
6105 
6106  clust_index = dict_table_get_first_index(prebuilt->table);
6107 
6108  index = whole_row ? clust_index : prebuilt->index;
6109 
6110  prebuilt->need_to_access_clustered = (index == clust_index);
6111 
6112  /* Either prebuilt->index should be a secondary index, or it
6113  should be the clustered index. */
6114  ut_ad(dict_index_is_clust(index) == (index == clust_index));
6115 
6116  /* Below we check column by column if we need to access
6117  the clustered index. */
6118 
6119  n_fields = (ulint) table->s->fields; /* number of columns */
6120 
6121  if (!prebuilt->mysql_template) {
6122  prebuilt->mysql_template = (mysql_row_templ_t*)
6123  mem_alloc(n_fields * sizeof(mysql_row_templ_t));
6124  }
6125 
6126  prebuilt->template_type = whole_row
6127  ? ROW_MYSQL_WHOLE_ROW : ROW_MYSQL_REC_FIELDS;
6128  prebuilt->null_bitmap_len = table->s->null_bytes;
6129 
6130  /* Prepare to build prebuilt->mysql_template[]. */
6131  prebuilt->templ_contains_blob = FALSE;
6132  prebuilt->mysql_prefix_len = 0;
6133  prebuilt->n_template = 0;
6134  prebuilt->idx_cond_n_cols = 0;
6135 
6136  /* Note that in InnoDB, i is the column number in the table.
6137  MySQL calls columns 'fields'. */
6138 
6139  if (active_index != MAX_KEY && active_index == pushed_idx_cond_keyno) {
6140  /* Push down an index condition or an end_range check. */
6141  for (i = 0; i < n_fields; i++) {
6142  const ibool index_contains
6144 
6145  /* Test if an end_range or an index condition
6146  refers to the field. Note that "index" and
6147  "index_contains" may refer to the clustered index.
6148  Index condition pushdown is relative to prebuilt->index
6149  (the index that is being looked up first). */
6150 
6151  /* When join_read_always_key() invokes this
6152  code via handler::ha_index_init() and
6153  ha_innobase::index_init(), end_range is not
6154  yet initialized. Because of that, we must
6155  always check for index_contains, instead of
6156  the subset
6157  field->part_of_key.is_set(active_index)
6158  which would be acceptable if end_range==NULL. */
6160  index, prebuilt, index_contains, i)) {
6161  /* Needed in ICP */
6162  const Field* field;
6163  mysql_row_templ_t* templ;
6164 
6165  if (whole_row) {
6166  field = table->field[i];
6167  } else {
6168  field = build_template_needs_field(
6169  index_contains,
6170  prebuilt->read_just_key,
6171  fetch_all_in_key,
6172  fetch_primary_key_cols,
6173  index, table, i);
6174  if (!field) {
6175  continue;
6176  }
6177  }
6178 
6179  templ = build_template_field(
6180  prebuilt, clust_index, index,
6181  table, field, i);
6182  prebuilt->idx_cond_n_cols++;
6183  ut_ad(prebuilt->idx_cond_n_cols
6184  == prebuilt->n_template);
6185 
6186  if (index == prebuilt->index) {
6187  templ->icp_rec_field_no
6188  = templ->rec_field_no;
6189  } else {
6190  templ->icp_rec_field_no
6192  prebuilt->index, i);
6193  }
6194 
6195  if (dict_index_is_clust(prebuilt->index)) {
6196  ut_ad(templ->icp_rec_field_no
6197  != ULINT_UNDEFINED);
6198  /* If the primary key includes
6199  a column prefix, use it in
6200  index condition pushdown,
6201  because the condition is
6202  evaluated before fetching any
6203  off-page (externally stored)
6204  columns. */
6205  if (templ->icp_rec_field_no
6206  < prebuilt->index->n_uniq) {
6207  /* This is a key column;
6208  all set. */
6209  continue;
6210  }
6211  } else if (templ->icp_rec_field_no
6212  != ULINT_UNDEFINED) {
6213  continue;
6214  }
6215 
6216  /* This is a column prefix index.
6217  The column prefix can be used in
6218  an end_range comparison. */
6219 
6220  templ->icp_rec_field_no
6222  prebuilt->index, i, TRUE);
6223  ut_ad(templ->icp_rec_field_no
6224  != ULINT_UNDEFINED);
6225 
6226  /* Index condition pushdown can be used on
6227  all columns of a secondary index, and on
6228  the PRIMARY KEY columns. On the clustered
6229  index, it must never be used on other than
6230  PRIMARY KEY columns, because those columns
6231  may be stored off-page, and we will not
6232  fetch externally stored columns before
6233  checking the index condition. */
6234  /* TODO: test the above with an assertion
6235  like this. Note that index conditions are
6236  currently pushed down as part of the
6237  "optimizer phase" while end_range is done
6238  as part of the execution phase. Therefore,
6239  we were unable to use an accurate condition
6240  for end_range in the "if" condition above,
6241  and the following assertion would fail.
6242  ut_ad(!dict_index_is_clust(prebuilt->index)
6243  || templ->rec_field_no
6244  < prebuilt->index->n_uniq);
6245  */
6246  }
6247  }
6248 
6249  ut_ad(prebuilt->idx_cond_n_cols > 0);
6250  ut_ad(prebuilt->idx_cond_n_cols == prebuilt->n_template);
6251 
6252  /* Include the fields that are not needed in index condition
6253  pushdown. */
6254  for (i = 0; i < n_fields; i++) {
6255  const ibool index_contains
6257 
6259  index, prebuilt, index_contains, i)) {
6260  /* Not needed in ICP */
6261  const Field* field;
6262 
6263  if (whole_row) {
6264  field = table->field[i];
6265  } else {
6266  field = build_template_needs_field(
6267  index_contains,
6268  prebuilt->read_just_key,
6269  fetch_all_in_key,
6270  fetch_primary_key_cols,
6271  index, table, i);
6272  if (!field) {
6273  continue;
6274  }
6275  }
6276 
6277  build_template_field(prebuilt,
6278  clust_index, index,
6279  table, field, i);
6280  }
6281  }
6282 
6283  prebuilt->idx_cond = this;
6284  } else {
6285  /* No index condition pushdown */
6286  prebuilt->idx_cond = NULL;
6287 
6288  for (i = 0; i < n_fields; i++) {
6289  const Field* field;
6290 
6291  if (whole_row) {
6292  field = table->field[i];
6293  } else {
6294  field = build_template_needs_field(
6296  index, i),
6297  prebuilt->read_just_key,
6298  fetch_all_in_key,
6299  fetch_primary_key_cols,
6300  index, table, i);
6301  if (!field) {
6302  continue;
6303  }
6304  }
6305 
6306  build_template_field(prebuilt, clust_index, index,
6307  table, field, i);
6308  }
6309  }
6310 
6311  if (index != clust_index && prebuilt->need_to_access_clustered) {
6312  /* Change rec_field_no's to correspond to the clustered index
6313  record */
6314  for (i = 0; i < prebuilt->n_template; i++) {
6315 
6316  mysql_row_templ_t* templ
6317  = &prebuilt->mysql_template[i];
6318 
6319  templ->rec_field_no = templ->clust_rec_field_no;
6320  }
6321  }
6322 }
6323 
6324 /********************************************************************/
6331 UNIV_INTERN
6332 dberr_t
6333 ha_innobase::innobase_lock_autoinc(void)
6334 /*====================================*/
6335 {
6336  dberr_t error = DB_SUCCESS;
6337 
6339 
6340  switch (innobase_autoinc_lock_mode) {
6341  case AUTOINC_NO_LOCKING:
6342  /* Acquire only the AUTOINC mutex. */
6343  dict_table_autoinc_lock(prebuilt->table);
6344  break;
6345 
6346  case AUTOINC_NEW_STYLE_LOCKING:
6347  /* For simple (single/multi) row INSERTs, we fallback to the
6348  old style only if another transaction has already acquired
6349  the AUTOINC lock on behalf of a LOAD FILE or INSERT ... SELECT
6350  etc. type of statement. */
6351  if (thd_sql_command(user_thd) == SQLCOM_INSERT
6352  || thd_sql_command(user_thd) == SQLCOM_REPLACE) {
6353  dict_table_t* ib_table = prebuilt->table;
6354 
6355  /* Acquire the AUTOINC mutex. */
6356  dict_table_autoinc_lock(ib_table);
6357 
6358  /* We need to check that another transaction isn't
6359  already holding the AUTOINC lock on the table. */
6360  if (ib_table->n_waiting_or_granted_auto_inc_locks) {
6361  /* Release the mutex to avoid deadlocks. */
6362  dict_table_autoinc_unlock(ib_table);
6363  } else {
6364  break;
6365  }
6366  }
6367  /* Fall through to old style locking. */
6368 
6369  case AUTOINC_OLD_STYLE_LOCKING:
6370  error = row_lock_table_autoinc_for_mysql(prebuilt);
6371 
6372  if (error == DB_SUCCESS) {
6373 
6374  /* Acquire the AUTOINC mutex. */
6375  dict_table_autoinc_lock(prebuilt->table);
6376  }
6377  break;
6378 
6379  default:
6380  ut_error;
6381  }
6382 
6383  return(error);
6384 }
6385 
6386 /********************************************************************/
6389 UNIV_INTERN
6390 dberr_t
6391 ha_innobase::innobase_reset_autoinc(
6392 /*================================*/
6393  ulonglong autoinc)
6394 {
6395  dberr_t error;
6396 
6397  error = innobase_lock_autoinc();
6398 
6399  if (error == DB_SUCCESS) {
6400 
6401  dict_table_autoinc_initialize(prebuilt->table, autoinc);
6402 
6403  dict_table_autoinc_unlock(prebuilt->table);
6404  }
6405 
6406  return(error);
6407 }
6408 
6409 /********************************************************************/
6413 UNIV_INTERN
6414 dberr_t
6415 ha_innobase::innobase_set_max_autoinc(
6416 /*==================================*/
6417  ulonglong auto_inc)
6418 {
6419  dberr_t error;
6420 
6421  error = innobase_lock_autoinc();
6422 
6423  if (error == DB_SUCCESS) {
6424 
6425  dict_table_autoinc_update_if_greater(prebuilt->table, auto_inc);
6426 
6427  dict_table_autoinc_unlock(prebuilt->table);
6428  }
6429 
6430  return(error);
6431 }
6432 
6433 /********************************************************************/
6437 UNIV_INTERN
6438 int
6440 /*===================*/
6441  uchar* record)
6442 {
6443  dberr_t error;
6444  int error_result= 0;
6445  ibool auto_inc_used= FALSE;
6446  ulint sql_command;
6447  trx_t* trx = thd_to_trx(user_thd);
6448 
6449  DBUG_ENTER("ha_innobase::write_row");
6450 
6451  if (srv_read_only_mode) {
6452  ib_senderrf(ha_thd(), IB_LOG_LEVEL_WARN, ER_READ_ONLY_MODE);
6453  DBUG_RETURN(HA_ERR_TABLE_READONLY);
6454  } else if (prebuilt->trx != trx) {
6455  sql_print_error("The transaction object for the table handle "
6456  "is at %p, but for the current thread it is at "
6457  "%p",
6458  (const void*) prebuilt->trx, (const void*) trx);
6459 
6460  fputs("InnoDB: Dump of 200 bytes around prebuilt: ", stderr);
6461  ut_print_buf(stderr, ((const byte*) prebuilt) - 100, 200);
6462  fputs("\n"
6463  "InnoDB: Dump of 200 bytes around ha_data: ",
6464  stderr);
6465  ut_print_buf(stderr, ((const byte*) trx) - 100, 200);
6466  putc('\n', stderr);
6467  ut_error;
6468  } else if (!trx_is_started(trx)) {
6469  ++trx->will_lock;
6470  }
6471 
6472  ha_statistic_increment(&SSV::ha_write_count);
6473 
6474  sql_command = thd_sql_command(user_thd);
6475 
6476  if ((sql_command == SQLCOM_ALTER_TABLE
6477  || sql_command == SQLCOM_OPTIMIZE
6478  || sql_command == SQLCOM_CREATE_INDEX
6479  || sql_command == SQLCOM_DROP_INDEX)
6480  && num_write_row >= 10000) {
6481  /* ALTER TABLE is COMMITted at every 10000 copied rows.
6482  The IX table lock for the original table has to be re-issued.
6483  As this method will be called on a temporary table where the
6484  contents of the original table is being copied to, it is
6485  a bit tricky to determine the source table. The cursor
6486  position in the source table need not be adjusted after the
6487  intermediate COMMIT, since writes by other transactions are
6488  being blocked by a MySQL table lock TL_WRITE_ALLOW_READ. */
6489 
6490  dict_table_t* src_table;
6491  enum lock_mode mode;
6492 
6493  num_write_row = 0;
6494 
6495  /* Commit the transaction. This will release the table
6496  locks, so they have to be acquired again. */
6497 
6498  /* Altering an InnoDB table */
6499  /* Get the source table. */
6500  src_table = lock_get_src_table(
6501  prebuilt->trx, prebuilt->table, &mode);
6502  if (!src_table) {
6503 no_commit:
6504  /* Unknown situation: do not commit */
6505  /*
6506  ut_print_timestamp(stderr);
6507  fprintf(stderr,
6508  " InnoDB: ALTER TABLE is holding lock"
6509  " on %lu tables!\n",
6510  prebuilt->trx->mysql_n_tables_locked);
6511  */
6512  ;
6513  } else if (src_table == prebuilt->table) {
6514  /* Source table is not in InnoDB format:
6515  no need to re-acquire locks on it. */
6516 
6517  /* Altering to InnoDB format */
6518  innobase_commit(ht, user_thd, 1);
6519  /* Note that this transaction is still active. */
6520  trx_register_for_2pc(prebuilt->trx);
6521  /* We will need an IX lock on the destination table. */
6522  prebuilt->sql_stat_start = TRUE;
6523  } else {
6524  /* Ensure that there are no other table locks than
6525  LOCK_IX and LOCK_AUTO_INC on the destination table. */
6526 
6527  if (!lock_is_table_exclusive(prebuilt->table,
6528  prebuilt->trx)) {
6529  goto no_commit;
6530  }
6531 
6532  /* Commit the transaction. This will release the table
6533  locks, so they have to be acquired again. */
6534  innobase_commit(ht, user_thd, 1);
6535  /* Note that this transaction is still active. */
6536  trx_register_for_2pc(prebuilt->trx);
6537  /* Re-acquire the table lock on the source table. */
6538  row_lock_table_for_mysql(prebuilt, src_table, mode);
6539  /* We will need an IX lock on the destination table. */
6540  prebuilt->sql_stat_start = TRUE;
6541  }
6542  }
6543 
6544  num_write_row++;
6545 
6546  /* This is the case where the table has an auto-increment column */
6547  if (table->next_number_field && record == table->record[0]) {
6548 
6549  /* Reset the error code before calling
6550  innobase_get_auto_increment(). */
6551  prebuilt->autoinc_error = DB_SUCCESS;
6552 
6553  if ((error_result = update_auto_increment())) {
6554  /* We don't want to mask autoinc overflow errors. */
6555 
6556  /* Handle the case where the AUTOINC sub-system
6557  failed during initialization. */
6558  if (prebuilt->autoinc_error == DB_UNSUPPORTED) {
6559  error_result = ER_AUTOINC_READ_FAILED;
6560  /* Set the error message to report too. */
6561  my_error(ER_AUTOINC_READ_FAILED, MYF(0));
6562  goto func_exit;
6563  } else if (prebuilt->autoinc_error != DB_SUCCESS) {
6564  error = prebuilt->autoinc_error;
6565  goto report_error;
6566  }
6567 
6568  /* MySQL errors are passed straight back. */
6569  goto func_exit;
6570  }
6571 
6572  auto_inc_used = TRUE;
6573  }
6574 
6575  if (prebuilt->mysql_template == NULL
6576  || prebuilt->template_type != ROW_MYSQL_WHOLE_ROW) {
6577 
6578  /* Build the template used in converting quickly between
6579  the two database formats */
6580 
6581  build_template(true);
6582  }
6583 
6584  innobase_srv_conc_enter_innodb(prebuilt->trx);
6585 
6586  error = row_insert_for_mysql((byte*) record, prebuilt);
6587  DEBUG_SYNC(user_thd, "ib_after_row_insert");
6588 
6589  /* Handle duplicate key errors */
6590  if (auto_inc_used) {
6591  ulonglong auto_inc;
6592  ulonglong col_max_value;
6593 
6594  /* Note the number of rows processed for this statement, used
6595  by get_auto_increment() to determine the number of AUTO-INC
6596  values to reserve. This is only useful for a mult-value INSERT
6597  and is a statement level counter.*/
6598  if (trx->n_autoinc_rows > 0) {
6599  --trx->n_autoinc_rows;
6600  }
6601 
6602  /* We need the upper limit of the col type to check for
6603  whether we update the table autoinc counter or not. */
6604  col_max_value = innobase_get_int_col_max_value(
6605  table->next_number_field);
6606 
6607  /* Get the value that MySQL attempted to store in the table.*/
6608  auto_inc = table->next_number_field->val_int();
6609 
6610  switch (error) {
6611  case DB_DUPLICATE_KEY:
6612 
6613  /* A REPLACE command and LOAD DATA INFILE REPLACE
6614  handle a duplicate key error themselves, but we
6615  must update the autoinc counter if we are performing
6616  those statements. */
6617 
6618  switch (sql_command) {
6619  case SQLCOM_LOAD:
6620  if (trx->duplicates) {
6621 
6622  goto set_max_autoinc;
6623  }
6624  break;
6625 
6626  case SQLCOM_REPLACE:
6627  case SQLCOM_INSERT_SELECT:
6628  case SQLCOM_REPLACE_SELECT:
6629  goto set_max_autoinc;
6630 
6631  default:
6632  break;
6633  }
6634 
6635  break;
6636 
6637  case DB_SUCCESS:
6638  /* If the actual value inserted is greater than
6639  the upper limit of the interval, then we try and
6640  update the table upper limit. Note: last_value
6641  will be 0 if get_auto_increment() was not called.*/
6642 
6643  if (auto_inc >= prebuilt->autoinc_last_value) {
6644 set_max_autoinc:
6645  /* This should filter out the negative
6646  values set explicitly by the user. */
6647  if (auto_inc <= col_max_value) {
6648  ut_a(prebuilt->autoinc_increment > 0);
6649 
6650  ulonglong offset;
6651  ulonglong increment;
6652  dberr_t err;
6653 
6654  offset = prebuilt->autoinc_offset;
6655  increment = prebuilt->autoinc_increment;
6656 
6657  auto_inc = innobase_next_autoinc(
6658  auto_inc,
6659  1, increment, offset,
6660  col_max_value);
6661 
6662  err = innobase_set_max_autoinc(
6663  auto_inc);
6664 
6665  if (err != DB_SUCCESS) {
6666  error = err;
6667  }
6668  }
6669  }
6670  break;
6671  default:
6672  break;
6673  }
6674  }
6675 
6676  innobase_srv_conc_exit_innodb(prebuilt->trx);
6677 
6678 report_error:
6679  if (error == DB_TABLESPACE_DELETED) {
6680  ib_senderrf(
6681  trx->mysql_thd, IB_LOG_LEVEL_ERROR,
6682  ER_TABLESPACE_DISCARDED,
6683  table->s->table_name.str);
6684  }
6685 
6686  error_result = convert_error_code_to_mysql(error,
6687  prebuilt->table->flags,
6688  user_thd);
6689 
6690  if (error_result == HA_FTS_INVALID_DOCID) {
6691  my_error(HA_FTS_INVALID_DOCID, MYF(0));
6692  }
6693 
6694 func_exit:
6695  innobase_active_small();
6696 
6697  DBUG_RETURN(error_result);
6698 }
6699 
6700 /**********************************************************************/
6704 static
6705 dberr_t
6706 calc_row_difference(
6707 /*================*/
6708  upd_t* uvect,
6709  uchar* old_row,
6710  uchar* new_row,
6711  TABLE* table,
6713  uchar* upd_buff,
6714  ulint buff_len,
6715  row_prebuilt_t* prebuilt,
6716  THD* thd)
6717 {
6718  uchar* original_upd_buff = upd_buff;
6719  Field* field;
6720  enum_field_types field_mysql_type;
6721  uint n_fields;
6722  ulint o_len;
6723  ulint n_len;
6724  ulint col_pack_len;
6725  const byte* new_mysql_row_col;
6726  const byte* o_ptr;
6727  const byte* n_ptr;
6728  byte* buf;
6729  upd_field_t* ufield;
6730  ulint col_type;
6731  ulint n_changed = 0;
6732  dfield_t dfield;
6733  dict_index_t* clust_index;
6734  uint i;
6735  ibool changes_fts_column = FALSE;
6736  ibool changes_fts_doc_col = FALSE;
6737  trx_t* trx = thd_to_trx(thd);
6738  doc_id_t doc_id = FTS_NULL_DOC_ID;
6739 
6741 
6742  n_fields = table->s->fields;
6743  clust_index = dict_table_get_first_index(prebuilt->table);
6744 
6745  /* We use upd_buff to convert changed fields */
6746  buf = (byte*) upd_buff;
6747 
6748  for (i = 0; i < n_fields; i++) {
6749  field = table->field[i];
6750 
6751  o_ptr = (const byte*) old_row + get_field_offset(table, field);
6752  n_ptr = (const byte*) new_row + get_field_offset(table, field);
6753 
6754  /* Use new_mysql_row_col and col_pack_len save the values */
6755 
6756  new_mysql_row_col = n_ptr;
6757  col_pack_len = field->pack_length();
6758 
6759  o_len = col_pack_len;
6760  n_len = col_pack_len;
6761 
6762  /* We use o_ptr and n_ptr to dig up the actual data for
6763  comparison. */
6764 
6765  field_mysql_type = field->type();
6766 
6767  col_type = prebuilt->table->cols[i].mtype;
6768 
6769  switch (col_type) {
6770 
6771  case DATA_BLOB:
6772  o_ptr = row_mysql_read_blob_ref(&o_len, o_ptr, o_len);
6773  n_ptr = row_mysql_read_blob_ref(&n_len, n_ptr, n_len);
6774 
6775  break;
6776 
6777  case DATA_VARCHAR:
6778  case DATA_BINARY:
6779  case DATA_VARMYSQL:
6780  if (field_mysql_type == MYSQL_TYPE_VARCHAR) {
6781  /* This is a >= 5.0.3 type true VARCHAR where
6782  the real payload data length is stored in
6783  1 or 2 bytes */
6784 
6786  &o_len, o_ptr,
6787  (ulint)
6788  (((Field_varstring*) field)->length_bytes));
6789 
6791  &n_len, n_ptr,
6792  (ulint)
6793  (((Field_varstring*) field)->length_bytes));
6794  }
6795 
6796  break;
6797  default:
6798  ;
6799  }
6800 
6801  if (field_mysql_type == MYSQL_TYPE_LONGLONG
6802  && prebuilt->table->fts
6804  field->field_name, FTS_DOC_ID_COL_NAME) == 0) {
6806  n_ptr, 8);
6807  if (doc_id == 0) {
6808  return(DB_FTS_INVALID_DOCID);
6809  }
6810  }
6811 
6812 
6813  if (field->real_maybe_null()) {
6814  if (field->is_null_in_record(old_row)) {
6815  o_len = UNIV_SQL_NULL;
6816  }
6817 
6818  if (field->is_null_in_record(new_row)) {
6819  n_len = UNIV_SQL_NULL;
6820  }
6821  }
6822 
6823  if (o_len != n_len || (o_len != UNIV_SQL_NULL &&
6824  0 != memcmp(o_ptr, n_ptr, o_len))) {
6825  /* The field has changed */
6826 
6827  ufield = uvect->fields + n_changed;
6828  UNIV_MEM_INVALID(ufield, sizeof *ufield);
6829 
6830  /* Let us use a dummy dfield to make the conversion
6831  from the MySQL column format to the InnoDB format */
6832 
6833  if (n_len != UNIV_SQL_NULL) {
6834  dict_col_copy_type(prebuilt->table->cols + i,
6835  dfield_get_type(&dfield));
6836 
6838  &dfield,
6839  (byte*) buf,
6840  TRUE,
6841  new_mysql_row_col,
6842  col_pack_len,
6843  dict_table_is_comp(prebuilt->table));
6844  dfield_copy(&ufield->new_val, &dfield);
6845  } else {
6846  dfield_set_null(&ufield->new_val);
6847  }
6848 
6849  ufield->exp = NULL;
6850  ufield->orig_len = 0;
6851  ufield->field_no = dict_col_get_clust_pos(
6852  &prebuilt->table->cols[i], clust_index);
6853  n_changed++;
6854 
6855  /* If an FTS indexed column was changed by this
6856  UPDATE then we need to inform the FTS sub-system.
6857 
6858  NOTE: Currently we re-index all FTS indexed columns
6859  even if only a subset of the FTS indexed columns
6860  have been updated. That is the reason we are
6861  checking only once here. Later we will need to
6862  note which columns have been updated and do
6863  selective processing. */
6864  if (prebuilt->table->fts != NULL) {
6865  ulint offset;
6866  dict_table_t* innodb_table;
6867 
6868  innodb_table = prebuilt->table;
6869 
6870  if (!changes_fts_column) {
6871  offset = row_upd_changes_fts_column(
6872  innodb_table, ufield);
6873 
6874  if (offset != ULINT_UNDEFINED) {
6875  changes_fts_column = TRUE;
6876  }
6877  }
6878 
6879  if (!changes_fts_doc_col) {
6880  changes_fts_doc_col =
6882  innodb_table, ufield);
6883  }
6884  }
6885  }
6886  }
6887 
6888  /* If the update changes a column with an FTS index on it, we
6889  then add an update column node with a new document id to the
6890  other changes. We piggy back our changes on the normal UPDATE
6891  to reduce processing and IO overhead. */
6892  if (!prebuilt->table->fts) {
6893  trx->fts_next_doc_id = 0;
6894  } else if (changes_fts_column || changes_fts_doc_col) {
6895  dict_table_t* innodb_table = prebuilt->table;
6896 
6897  ufield = uvect->fields + n_changed;
6898 
6899  if (!DICT_TF2_FLAG_IS_SET(
6900  innodb_table, DICT_TF2_FTS_HAS_DOC_ID)) {
6901 
6902  /* If Doc ID is managed by user, and if any
6903  FTS indexed column has been updated, its corresponding
6904  Doc ID must also be updated. Otherwise, return
6905  error */
6906  if (changes_fts_column && !changes_fts_doc_col) {
6907  ut_print_timestamp(stderr);
6908  fprintf(stderr, " InnoDB: A new Doc ID"
6909  " must be supplied while updating"
6910  " FTS indexed columns.\n");
6911  return(DB_FTS_INVALID_DOCID);
6912  }
6913 
6914  /* Doc ID must monotonically increase */
6915  ut_ad(innodb_table->fts->cache);
6916  if (doc_id < prebuilt->table->fts->cache->next_doc_id) {
6917  fprintf(stderr,
6918  "InnoDB: FTS Doc ID must be larger than"
6919  " "IB_ID_FMT" for table",
6920  innodb_table->fts->cache->next_doc_id
6921  - 1);
6922  ut_print_name(stderr, trx,
6923  TRUE, innodb_table->name);
6924  putc('\n', stderr);
6925 
6926  return(DB_FTS_INVALID_DOCID);
6927  } else if ((doc_id
6928  - prebuilt->table->fts->cache->next_doc_id)
6929  >= FTS_DOC_ID_MAX_STEP) {
6930  fprintf(stderr,
6931  "InnoDB: Doc ID "UINT64PF" is too"
6932  " big. Its difference with largest"
6933  " Doc ID used "UINT64PF" cannot"
6934  " exceed or equal to %d\n",
6935  doc_id,
6936  prebuilt->table->fts->cache->next_doc_id - 1,
6937  FTS_DOC_ID_MAX_STEP);
6938  }
6939 
6940 
6941  trx->fts_next_doc_id = doc_id;
6942  } else {
6943  /* If the Doc ID is a hidden column, it can't be
6944  changed by user */
6945  ut_ad(!changes_fts_doc_col);
6946 
6947  /* Doc ID column is hidden, a new Doc ID will be
6948  generated by following fts_update_doc_id() call */
6949  trx->fts_next_doc_id = 0;
6950  }
6951 
6953  innodb_table, ufield, &trx->fts_next_doc_id);
6954 
6955  ++n_changed;
6956  } else {
6957  /* We have a Doc ID column, but none of FTS indexed
6958  columns are touched, nor the Doc ID column, so set
6959  fts_next_doc_id to UINT64_UNDEFINED, which means do not
6960  update the Doc ID column */
6961  trx->fts_next_doc_id = UINT64_UNDEFINED;
6962  }
6963 
6964  uvect->n_fields = n_changed;
6965  uvect->info_bits = 0;
6966 
6967  ut_a(buf <= (byte*) original_upd_buff + buff_len);
6968 
6969  return(DB_SUCCESS);
6970 }
6971 
6972 /**********************************************************************/
6980 UNIV_INTERN
6981 int
6983 /*====================*/
6984  const uchar* old_row,
6985  uchar* new_row)
6986 {
6987  upd_t* uvect;
6988  dberr_t error;
6989  trx_t* trx = thd_to_trx(user_thd);
6990 
6991  DBUG_ENTER("ha_innobase::update_row");
6992 
6993  ut_a(prebuilt->trx == trx);
6994 
6995  if (srv_read_only_mode) {
6996  ib_senderrf(ha_thd(), IB_LOG_LEVEL_WARN, ER_READ_ONLY_MODE);
6997  DBUG_RETURN(HA_ERR_TABLE_READONLY);
6998  } else if (!trx_is_started(trx)) {
6999  ++trx->will_lock;
7000  }
7001 
7002  if (upd_buf == NULL) {
7003  ut_ad(upd_buf_size == 0);
7004 
7005  /* Create a buffer for packing the fields of a record. Why
7006  table->reclength did not work here? Obviously, because char
7007  fields when packed actually became 1 byte longer, when we also
7008  stored the string length as the first byte. */
7009 
7010  upd_buf_size = table->s->reclength + table->s->max_key_length
7011  + MAX_REF_PARTS * 3;
7012  upd_buf = (uchar*) my_malloc(upd_buf_size, MYF(MY_WME));
7013  if (upd_buf == NULL) {
7014  upd_buf_size = 0;
7015  DBUG_RETURN(HA_ERR_OUT_OF_MEM);
7016  }
7017  }
7018 
7019  ha_statistic_increment(&SSV::ha_update_count);
7020 
7021  if (prebuilt->upd_node) {
7022  uvect = prebuilt->upd_node->update;
7023  } else {
7024  uvect = row_get_prebuilt_update_vector(prebuilt);
7025  }
7026 
7027  /* Build an update vector from the modified fields in the rows
7028  (uses upd_buf of the handle) */
7029 
7030  error = calc_row_difference(uvect, (uchar*) old_row, new_row, table,
7031  upd_buf, upd_buf_size, prebuilt, user_thd);
7032 
7033  if (error != DB_SUCCESS) {
7034  goto func_exit;
7035  }
7036 
7037  /* This is not a delete */
7038  prebuilt->upd_node->is_delete = FALSE;
7039 
7040  ut_a(prebuilt->template_type == ROW_MYSQL_WHOLE_ROW);
7041 
7042  innobase_srv_conc_enter_innodb(trx);
7043 
7044  error = row_update_for_mysql((byte*) old_row, prebuilt);
7045 
7046  /* We need to do some special AUTOINC handling for the following case:
7047 
7048  INSERT INTO t (c1,c2) VALUES(x,y) ON DUPLICATE KEY UPDATE ...
7049 
7050  We need to use the AUTOINC counter that was actually used by
7051  MySQL in the UPDATE statement, which can be different from the
7052  value used in the INSERT statement.*/
7053 
7054  if (error == DB_SUCCESS
7055  && table->next_number_field
7056  && new_row == table->record[0]
7057  && thd_sql_command(user_thd) == SQLCOM_INSERT
7058  && trx->duplicates) {
7059 
7060  ulonglong auto_inc;
7061  ulonglong col_max_value;
7062 
7063  auto_inc = table->next_number_field->val_int();
7064 
7065  /* We need the upper limit of the col type to check for
7066  whether we update the table autoinc counter or not. */
7067  col_max_value = innobase_get_int_col_max_value(
7068  table->next_number_field);
7069 
7070  if (auto_inc <= col_max_value && auto_inc != 0) {
7071 
7072  ulonglong offset;
7073  ulonglong increment;
7074 
7075  offset = prebuilt->autoinc_offset;
7076  increment = prebuilt->autoinc_increment;
7077 
7078  auto_inc = innobase_next_autoinc(
7079  auto_inc, 1, increment, offset, col_max_value);
7080 
7081  error = innobase_set_max_autoinc(auto_inc);
7082  }
7083  }
7084 
7085  innobase_srv_conc_exit_innodb(trx);
7086 
7087 func_exit:
7088  int err = convert_error_code_to_mysql(error,
7089  prebuilt->table->flags, user_thd);
7090 
7091  /* If success and no columns were updated. */
7092  if (err == 0 && uvect->n_fields == 0) {
7093 
7094  /* This is the same as success, but instructs
7095  MySQL that the row is not really updated and it
7096  should not increase the count of updated rows.
7097  This is fix for http://bugs.mysql.com/29157 */
7098  err = HA_ERR_RECORD_IS_THE_SAME;
7099  } else if (err == HA_FTS_INVALID_DOCID) {
7100  my_error(HA_FTS_INVALID_DOCID, MYF(0));
7101  }
7102 
7103  /* Tell InnoDB server that there might be work for
7104  utility threads: */
7105 
7106  innobase_active_small();
7107 
7108  DBUG_RETURN(err);
7109 }
7110 
7111 /**********************************************************************/
7114 UNIV_INTERN
7115 int
7117 /*====================*/
7118  const uchar* record)
7119 {
7120  dberr_t error;
7121  trx_t* trx = thd_to_trx(user_thd);
7122 
7123  DBUG_ENTER("ha_innobase::delete_row");
7124 
7125  ut_a(prebuilt->trx == trx);
7126 
7127  if (srv_read_only_mode) {
7128  ib_senderrf(ha_thd(), IB_LOG_LEVEL_WARN, ER_READ_ONLY_MODE);
7129  DBUG_RETURN(HA_ERR_TABLE_READONLY);
7130  } else if (!trx_is_started(trx)) {
7131  ++trx->will_lock;
7132  }
7133 
7134  ha_statistic_increment(&SSV::ha_delete_count);
7135 
7136  if (!prebuilt->upd_node) {
7138  }
7139 
7140  /* This is a delete */
7141 
7142  prebuilt->upd_node->is_delete = TRUE;
7143 
7144  innobase_srv_conc_enter_innodb(trx);
7145 
7146  error = row_update_for_mysql((byte*) record, prebuilt);
7147 
7148  innobase_srv_conc_exit_innodb(trx);
7149 
7150  /* Tell the InnoDB server that there might be work for
7151  utility threads: */
7152 
7153  innobase_active_small();
7154 
7155  DBUG_RETURN(convert_error_code_to_mysql(
7156  error, prebuilt->table->flags, user_thd));
7157 }
7158 
7159 /**********************************************************************/
7163 UNIV_INTERN
7164 void
7166 /*=========================*/
7167 {
7168  DBUG_ENTER("ha_innobase::unlock_row");
7169 
7170  /* Consistent read does not take any locks, thus there is
7171  nothing to unlock. */
7172 
7173  if (prebuilt->select_lock_type == LOCK_NONE) {
7174  DBUG_VOID_RETURN;
7175  }
7176 
7177  /* Ideally, this assert must be in the beginning of the function.
7178  But there are some calls to this function from the SQL layer when the
7179  transaction is in state TRX_STATE_NOT_STARTED. The check on
7180  prebuilt->select_lock_type above gets around this issue. */
7181  ut_ad(trx_state_eq(prebuilt->trx, TRX_STATE_ACTIVE));
7182 
7183  switch (prebuilt->row_read_type) {
7184  case ROW_READ_WITH_LOCKS:
7186  && prebuilt->trx->isolation_level
7187  > TRX_ISO_READ_COMMITTED) {
7188  break;
7189  }
7190  /* fall through */
7191  case ROW_READ_TRY_SEMI_CONSISTENT:
7192  row_unlock_for_mysql(prebuilt, FALSE);
7193  break;
7194  case ROW_READ_DID_SEMI_CONSISTENT:
7195  prebuilt->row_read_type = ROW_READ_TRY_SEMI_CONSISTENT;
7196  break;
7197  }
7198 
7199  DBUG_VOID_RETURN;
7200 }
7201 
7202 /* See handler.h and row0mysql.h for docs on this function. */
7203 UNIV_INTERN
7204 bool
7206 /*=======================================*/
7207 {
7208  return(prebuilt->row_read_type == ROW_READ_DID_SEMI_CONSISTENT);
7209 }
7210 
7211 /* See handler.h and row0mysql.h for docs on this function. */
7212 UNIV_INTERN
7213 void
7215 /*===========================================*/
7216 {
7217  ut_a(prebuilt->trx == thd_to_trx(ha_thd()));
7218 
7219  /* Row read type is set to semi consistent read if this was
7220  requested by the MySQL and either innodb_locks_unsafe_for_binlog
7221  option is used or this session is using READ COMMITTED isolation
7222  level. */
7223 
7224  if (yes
7226  || prebuilt->trx->isolation_level <= TRX_ISO_READ_COMMITTED)) {
7227  prebuilt->row_read_type = ROW_READ_TRY_SEMI_CONSISTENT;
7228  } else {
7229  prebuilt->row_read_type = ROW_READ_WITH_LOCKS;
7230  }
7231 }
7232 
7233 /******************************************************************/
7236 UNIV_INTERN
7237 int
7239 /*====================*/
7240  uint keynr,
7241  bool sorted)
7242 {
7243  DBUG_ENTER("index_init");
7244 
7245  DBUG_RETURN(change_active_index(keynr));
7246 }
7247 
7248 /******************************************************************/
7251 UNIV_INTERN
7252 int
7254 /*========================*/
7255 {
7256  int error = 0;
7257  DBUG_ENTER("index_end");
7258  active_index = MAX_KEY;
7259  in_range_check_pushed_down = FALSE;
7260  ds_mrr.dsmrr_close();
7261  DBUG_RETURN(error);
7262 }
7263 
7264 /*********************************************************************/
7267 static inline
7268 ulint
7269 convert_search_mode_to_innobase(
7270 /*============================*/
7271  enum ha_rkey_function find_flag)
7272 {
7273  switch (find_flag) {
7274  case HA_READ_KEY_EXACT:
7275  /* this does not require the index to be UNIQUE */
7276  return(PAGE_CUR_GE);
7277  case HA_READ_KEY_OR_NEXT:
7278  return(PAGE_CUR_GE);
7279  case HA_READ_KEY_OR_PREV:
7280  return(PAGE_CUR_LE);
7281  case HA_READ_AFTER_KEY:
7282  return(PAGE_CUR_G);
7283  case HA_READ_BEFORE_KEY:
7284  return(PAGE_CUR_L);
7285  case HA_READ_PREFIX:
7286  return(PAGE_CUR_GE);
7287  case HA_READ_PREFIX_LAST:
7288  return(PAGE_CUR_LE);
7289  case HA_READ_PREFIX_LAST_OR_PREV:
7290  return(PAGE_CUR_LE);
7291  /* In MySQL-4.0 HA_READ_PREFIX and HA_READ_PREFIX_LAST always
7292  pass a complete-field prefix of a key value as the search
7293  tuple. I.e., it is not allowed that the last field would
7294  just contain n first bytes of the full field value.
7295  MySQL uses a 'padding' trick to convert LIKE 'abc%'
7296  type queries so that it can use as a search tuple
7297  a complete-field-prefix of a key value. Thus, the InnoDB
7298  search mode PAGE_CUR_LE_OR_EXTENDS is never used.
7299  TODO: when/if MySQL starts to use also partial-field
7300  prefixes, we have to deal with stripping of spaces
7301  and comparison of non-latin1 char type fields in
7302  innobase_mysql_cmp() to get PAGE_CUR_LE_OR_EXTENDS to
7303  work correctly. */
7304  case HA_READ_MBR_CONTAIN:
7305  case HA_READ_MBR_INTERSECT:
7306  case HA_READ_MBR_WITHIN:
7307  case HA_READ_MBR_DISJOINT:
7308  case HA_READ_MBR_EQUAL:
7309  return(PAGE_CUR_UNSUPP);
7310  /* do not use "default:" in order to produce a gcc warning:
7311  enumeration value '...' not handled in switch
7312  (if -Wswitch or -Wall is used) */
7313  }
7314 
7315  my_error(ER_CHECK_NOT_IMPLEMENTED, MYF(0), "this functionality");
7316 
7317  return(PAGE_CUR_UNSUPP);
7318 }
7319 
7320 /*
7321  BACKGROUND INFO: HOW A SELECT SQL QUERY IS EXECUTED
7322  ---------------------------------------------------
7323 The following does not cover all the details, but explains how we determine
7324 the start of a new SQL statement, and what is associated with it.
7325 
7326 For each table in the database the MySQL interpreter may have several
7327 table handle instances in use, also in a single SQL query. For each table
7328 handle instance there is an InnoDB 'prebuilt' struct which contains most
7329 of the InnoDB data associated with this table handle instance.
7330 
7331  A) if the user has not explicitly set any MySQL table level locks:
7332 
7333  1) MySQL calls ::external_lock to set an 'intention' table level lock on
7334 the table of the handle instance. There we set
7335 prebuilt->sql_stat_start = TRUE. The flag sql_stat_start should be set
7336 true if we are taking this table handle instance to use in a new SQL
7337 statement issued by the user. We also increment trx->n_mysql_tables_in_use.
7338 
7339  2) If prebuilt->sql_stat_start == TRUE we 'pre-compile' the MySQL search
7340 instructions to prebuilt->template of the table handle instance in
7341 ::index_read. The template is used to save CPU time in large joins.
7342 
7343  3) In row_search_for_mysql, if prebuilt->sql_stat_start is true, we
7344 allocate a new consistent read view for the trx if it does not yet have one,
7345 or in the case of a locking read, set an InnoDB 'intention' table level
7346 lock on the table.
7347 
7348  4) We do the SELECT. MySQL may repeatedly call ::index_read for the
7349 same table handle instance, if it is a join.
7350 
7351  5) When the SELECT ends, MySQL removes its intention table level locks
7352 in ::external_lock. When trx->n_mysql_tables_in_use drops to zero,
7353  (a) we execute a COMMIT there if the autocommit is on,
7354  (b) we also release possible 'SQL statement level resources' InnoDB may
7355 have for this SQL statement. The MySQL interpreter does NOT execute
7356 autocommit for pure read transactions, though it should. That is why the
7357 table handler in that case has to execute the COMMIT in ::external_lock.
7358 
7359  B) If the user has explicitly set MySQL table level locks, then MySQL
7360 does NOT call ::external_lock at the start of the statement. To determine
7361 when we are at the start of a new SQL statement we at the start of
7362 ::index_read also compare the query id to the latest query id where the
7363 table handle instance was used. If it has changed, we know we are at the
7364 start of a new SQL statement. Since the query id can theoretically
7365 overwrap, we use this test only as a secondary way of determining the
7366 start of a new SQL statement. */
7367 
7368 
7369 /**********************************************************************/
7373 UNIV_INTERN
7374 int
7376 /*====================*/
7377  uchar* buf,
7379  const uchar* key_ptr,
7388  uint key_len,
7389  enum ha_rkey_function find_flag)
7390 {
7391  ulint mode;
7393  ulint match_mode = 0;
7394  int error;
7395  dberr_t ret;
7396 
7397  DBUG_ENTER("index_read");
7398  DEBUG_SYNC_C("ha_innobase_index_read_begin");
7399 
7400  ut_a(prebuilt->trx == thd_to_trx(user_thd));
7401  ut_ad(key_len != 0 || find_flag != HA_READ_KEY_EXACT);
7402 
7403  ha_statistic_increment(&SSV::ha_read_key_count);
7404 
7405  index = prebuilt->index;
7406 
7407  if (UNIV_UNLIKELY(index == NULL) || dict_index_is_corrupted(index)) {
7408  prebuilt->index_usable = FALSE;
7409  DBUG_RETURN(HA_ERR_CRASHED);
7410  }
7411  if (UNIV_UNLIKELY(!prebuilt->index_usable)) {
7412  DBUG_RETURN(dict_index_is_corrupted(index)
7413  ? HA_ERR_INDEX_CORRUPT
7414  : HA_ERR_TABLE_DEF_CHANGED);
7415  }
7416 
7417  if (index->type & DICT_FTS) {
7418  DBUG_RETURN(HA_ERR_KEY_NOT_FOUND);
7419  }
7420 
7421  /* Note that if the index for which the search template is built is not
7422  necessarily prebuilt->index, but can also be the clustered index */
7423 
7424  if (prebuilt->sql_stat_start) {
7425  build_template(false);
7426  }
7427 
7428  if (key_ptr) {
7429  /* Convert the search key value to InnoDB format into
7430  prebuilt->search_tuple */
7431 
7433  prebuilt->search_tuple,
7434  srch_key_val1, sizeof(srch_key_val1),
7435  index,
7436  (byte*) key_ptr,
7437  (ulint) key_len,
7438  prebuilt->trx);
7439  DBUG_ASSERT(prebuilt->search_tuple->n_fields > 0);
7440  } else {
7441  /* We position the cursor to the last or the first entry
7442  in the index */
7443 
7444  dtuple_set_n_fields(prebuilt->search_tuple, 0);
7445  }
7446 
7447  mode = convert_search_mode_to_innobase(find_flag);
7448 
7449  match_mode = 0;
7450 
7451  if (find_flag == HA_READ_KEY_EXACT) {
7452 
7453  match_mode = ROW_SEL_EXACT;
7454 
7455  } else if (find_flag == HA_READ_PREFIX
7456  || find_flag == HA_READ_PREFIX_LAST) {
7457 
7458  match_mode = ROW_SEL_EXACT_PREFIX;
7459  }
7460 
7461  last_match_mode = (uint) match_mode;
7462 
7463  if (mode != PAGE_CUR_UNSUPP) {
7464 
7465  innobase_srv_conc_enter_innodb(prebuilt->trx);
7466 
7467  ret = row_search_for_mysql((byte*) buf, mode, prebuilt,
7468  match_mode, 0);
7469 
7470  innobase_srv_conc_exit_innodb(prebuilt->trx);
7471  } else {
7472 
7473  ret = DB_UNSUPPORTED;
7474  }
7475 
7476  switch (ret) {
7477  case DB_SUCCESS:
7478  error = 0;
7479  table->status = 0;
7480  srv_stats.n_rows_read.add((size_t) prebuilt->trx->id, 1);
7481  break;
7482  case DB_RECORD_NOT_FOUND:
7483  error = HA_ERR_KEY_NOT_FOUND;
7484  table->status = STATUS_NOT_FOUND;
7485  break;
7486  case DB_END_OF_INDEX:
7487  error = HA_ERR_KEY_NOT_FOUND;
7488  table->status = STATUS_NOT_FOUND;
7489  break;
7490  case DB_TABLESPACE_DELETED:
7491 
7492  ib_senderrf(
7493  prebuilt->trx->mysql_thd, IB_LOG_LEVEL_ERROR,
7494  ER_TABLESPACE_DISCARDED,
7495  table->s->table_name.str);
7496 
7497  table->status = STATUS_NOT_FOUND;
7498  error = HA_ERR_NO_SUCH_TABLE;
7499  break;
7500  case DB_TABLESPACE_NOT_FOUND:
7501 
7502  ib_senderrf(
7503  prebuilt->trx->mysql_thd, IB_LOG_LEVEL_ERROR,
7504  ER_TABLESPACE_MISSING, MYF(0),
7505  table->s->table_name.str);
7506 
7507  table->status = STATUS_NOT_FOUND;
7508  error = HA_ERR_NO_SUCH_TABLE;
7509  break;
7510  default:
7511  error = convert_error_code_to_mysql(
7512  ret, prebuilt->table->flags, user_thd);
7513 
7514  table->status = STATUS_NOT_FOUND;
7515  break;
7516  }
7517 
7518  DBUG_RETURN(error);
7519 }
7520 
7521 /*******************************************************************/
7525 UNIV_INTERN
7526 int
7528 /*=========================*/
7529  uchar* buf,
7530  const uchar* key_ptr,
7532  uint key_len)
7534 {
7535  return(index_read(buf, key_ptr, key_len, HA_READ_PREFIX_LAST));
7536 }
7537 
7538 /********************************************************************/
7541 UNIV_INTERN
7542 dict_index_t*
7543 ha_innobase::innobase_get_index(
7544 /*============================*/
7545  uint keynr)
7548 {
7549  KEY* key = 0;
7550  dict_index_t* index = 0;
7551 
7552  DBUG_ENTER("innobase_get_index");
7553 
7554  if (keynr != MAX_KEY && table->s->keys > 0) {
7555  key = table->key_info + keynr;
7556 
7557  index = innobase_index_lookup(share, keynr);
7558 
7559  if (index) {
7560  ut_a(ut_strcmp(index->name, key->name) == 0);
7561  } else {
7562  /* Can't find index with keynr in the translation
7563  table. Only print message if the index translation
7564  table exists */
7565  if (share->idx_trans_tbl.index_mapping) {
7566  sql_print_warning("InnoDB could not find "
7567  "index %s key no %u for "
7568  "table %s through its "
7569  "index translation table",
7570  key ? key->name : "NULL",
7571  keynr,
7572  prebuilt->table->name);
7573  }
7574 
7575  index = dict_table_get_index_on_name(prebuilt->table,
7576  key->name);
7577  }
7578  } else {
7579  index = dict_table_get_first_index(prebuilt->table);
7580  }
7581 
7582  if (!index) {
7583  sql_print_error(
7584  "Innodb could not find key n:o %u with name %s "
7585  "from dict cache for table %s",
7586  keynr, key ? key->name : "NULL",
7587  prebuilt->table->name);
7588  }
7589 
7590  DBUG_RETURN(index);
7591 }
7592 
7593 /********************************************************************/
7596 UNIV_INTERN
7597 int
7598 ha_innobase::change_active_index(
7599 /*=============================*/
7600  uint keynr)
7603 {
7604  DBUG_ENTER("change_active_index");
7605 
7606  ut_ad(user_thd == ha_thd());
7607  ut_a(prebuilt->trx == thd_to_trx(user_thd));
7608 
7609  active_index = keynr;
7610 
7611  prebuilt->index = innobase_get_index(keynr);
7612 
7613  if (UNIV_UNLIKELY(!prebuilt->index)) {
7614  sql_print_warning("InnoDB: change_active_index(%u) failed",
7615  keynr);
7616  prebuilt->index_usable = FALSE;
7617  DBUG_RETURN(1);
7618  }
7619 
7620  prebuilt->index_usable = row_merge_is_index_usable(prebuilt->trx,
7621  prebuilt->index);
7622 
7623  if (UNIV_UNLIKELY(!prebuilt->index_usable)) {
7624  if (dict_index_is_corrupted(prebuilt->index)) {
7625  char index_name[MAX_FULL_NAME_LEN + 1];
7626  char table_name[MAX_FULL_NAME_LEN + 1];
7627 
7629  index_name, sizeof index_name,
7630  prebuilt->index->name, TRUE);
7631 
7633  table_name, sizeof table_name,
7634  prebuilt->index->table->name, FALSE);
7635 
7636  push_warning_printf(
7637  user_thd, Sql_condition::WARN_LEVEL_WARN,
7638  HA_ERR_INDEX_CORRUPT,
7639  "InnoDB: Index %s for table %s is"
7640  " marked as corrupted",
7641  index_name, table_name);
7642  DBUG_RETURN(HA_ERR_INDEX_CORRUPT);
7643  } else {
7644  push_warning_printf(
7645  user_thd, Sql_condition::WARN_LEVEL_WARN,
7646  HA_ERR_TABLE_DEF_CHANGED,
7647  "InnoDB: insufficient history for index %u",
7648  keynr);
7649  }
7650 
7651  /* The caller seems to ignore this. Thus, we must check
7652  this again in row_search_for_mysql(). */
7653  DBUG_RETURN(HA_ERR_TABLE_DEF_CHANGED);
7654  }
7655 
7656  ut_a(prebuilt->search_tuple != 0);
7657 
7658  dtuple_set_n_fields(prebuilt->search_tuple, prebuilt->index->n_fields);
7659 
7660  dict_index_copy_types(prebuilt->search_tuple, prebuilt->index,
7661  prebuilt->index->n_fields);
7662 
7663  /* MySQL changes the active index for a handle also during some
7664  queries, for example SELECT MAX(a), SUM(a) first retrieves the MAX()
7665  and then calculates the sum. Previously we played safe and used
7666  the flag ROW_MYSQL_WHOLE_ROW below, but that caused unnecessary
7667  copying. Starting from MySQL-4.1 we use a more efficient flag here. */
7668 
7669  build_template(false);
7670 
7671  DBUG_RETURN(0);
7672 }
7673 
7674 /**********************************************************************/
7679 UNIV_INTERN
7680 int
7682 /*========================*/
7683  uchar* buf,
7685  uint keynr,
7686  const uchar* key,
7689  uint key_len,
7690  enum ha_rkey_function find_flag)
7691 {
7692  if (change_active_index(keynr)) {
7693 
7694  return(1);
7695  }
7696 
7697  return(index_read(buf, key, key_len, find_flag));
7698 }
7699 
7700 /***********************************************************************/
7704 UNIV_INTERN
7705 int
7706 ha_innobase::general_fetch(
7707 /*=======================*/
7708  uchar* buf,
7710  uint direction,
7711  uint match_mode)
7713 {
7714  dberr_t ret;
7715  int error;
7716 
7717  DBUG_ENTER("general_fetch");
7718 
7719  ut_a(prebuilt->trx == thd_to_trx(user_thd));
7720 
7721  innobase_srv_conc_enter_innodb(prebuilt->trx);
7722 
7723  ret = row_search_for_mysql(
7724  (byte*) buf, 0, prebuilt, match_mode, direction);
7725 
7726  innobase_srv_conc_exit_innodb(prebuilt->trx);
7727 
7728  switch (ret) {
7729  case DB_SUCCESS:
7730  error = 0;
7731  table->status = 0;
7732  srv_stats.n_rows_read.add((size_t) prebuilt->trx->id, 1);
7733  break;
7734  case DB_RECORD_NOT_FOUND:
7735  error = HA_ERR_END_OF_FILE;
7736  table->status = STATUS_NOT_FOUND;
7737  break;
7738  case DB_END_OF_INDEX:
7739  error = HA_ERR_END_OF_FILE;
7740  table->status = STATUS_NOT_FOUND;
7741  break;
7742  case DB_TABLESPACE_DELETED:
7743 
7744  ib_senderrf(
7745  prebuilt->trx->mysql_thd, IB_LOG_LEVEL_ERROR,
7746  ER_TABLESPACE_DISCARDED,
7747  table->s->table_name.str);
7748 
7749  table->status = STATUS_NOT_FOUND;
7750  error = HA_ERR_NO_SUCH_TABLE;
7751  break;
7752  case DB_TABLESPACE_NOT_FOUND:
7753 
7754  ib_senderrf(
7755  prebuilt->trx->mysql_thd, IB_LOG_LEVEL_ERROR,
7756  ER_TABLESPACE_MISSING,
7757  table->s->table_name.str);
7758 
7759  table->status = STATUS_NOT_FOUND;
7760  error = HA_ERR_NO_SUCH_TABLE;
7761  break;
7762  default:
7763  error = convert_error_code_to_mysql(
7764  ret, prebuilt->table->flags, user_thd);
7765 
7766  table->status = STATUS_NOT_FOUND;
7767  break;
7768  }
7769 
7770  DBUG_RETURN(error);
7771 }
7772 
7773 /***********************************************************************/
7777 UNIV_INTERN
7778 int
7780 /*====================*/
7781  uchar* buf)
7783 {
7784  ha_statistic_increment(&SSV::ha_read_next_count);
7785 
7786  return(general_fetch(buf, ROW_SEL_NEXT, 0));
7787 }
7788 
7789 /*******************************************************************/
7792 UNIV_INTERN
7793 int
7795 /*=========================*/
7796  uchar* buf,
7797  const uchar* key,
7798  uint keylen)
7799 {
7800  ha_statistic_increment(&SSV::ha_read_next_count);
7801 
7802  return(general_fetch(buf, ROW_SEL_NEXT, last_match_mode));
7803 }
7804 
7805 /***********************************************************************/
7809 UNIV_INTERN
7810 int
7812 /*====================*/
7813  uchar* buf)
7814 {
7815  ha_statistic_increment(&SSV::ha_read_prev_count);
7816 
7817  return(general_fetch(buf, ROW_SEL_PREV, 0));
7818 }
7819 
7820 /********************************************************************/
7824 UNIV_INTERN
7825 int
7827 /*=====================*/
7828  uchar* buf)
7829 {
7830  int error;
7831 
7832  DBUG_ENTER("index_first");
7833  ha_statistic_increment(&SSV::ha_read_first_count);
7834 
7835  error = index_read(buf, NULL, 0, HA_READ_AFTER_KEY);
7836 
7837  /* MySQL does not seem to allow this to return HA_ERR_KEY_NOT_FOUND */
7838 
7839  if (error == HA_ERR_KEY_NOT_FOUND) {
7840  error = HA_ERR_END_OF_FILE;
7841  }
7842 
7843  DBUG_RETURN(error);
7844 }
7845 
7846 /********************************************************************/
7850 UNIV_INTERN
7851 int
7853 /*====================*/
7854  uchar* buf)
7855 {
7856  int error;
7857 
7858  DBUG_ENTER("index_last");
7859  ha_statistic_increment(&SSV::ha_read_last_count);
7860 
7861  error = index_read(buf, NULL, 0, HA_READ_BEFORE_KEY);
7862 
7863  /* MySQL does not seem to allow this to return HA_ERR_KEY_NOT_FOUND */
7864 
7865  if (error == HA_ERR_KEY_NOT_FOUND) {
7866  error = HA_ERR_END_OF_FILE;
7867  }
7868 
7869  DBUG_RETURN(error);
7870 }
7871 
7872 /****************************************************************/
7875 UNIV_INTERN
7876 int
7878 /*==================*/
7879  bool scan)
7880 {
7881  int err;
7882 
7883  /* Store the active index value so that we can restore the original
7884  value after a scan */
7885 
7886  if (prebuilt->clust_index_was_generated) {
7887  err = change_active_index(MAX_KEY);
7888  } else {
7889  err = change_active_index(primary_key);
7890  }
7891 
7892  /* Don't use semi-consistent read in random row reads (by position).
7893  This means we must disable semi_consistent_read if scan is false */
7894 
7895  if (!scan) {
7897  }
7898 
7899  start_of_scan = 1;
7900 
7901  return(err);
7902 }
7903 
7904 /*****************************************************************/
7907 UNIV_INTERN
7908 int
7910 /*======================*/
7911 {
7912  return(index_end());
7913 }
7914 
7915 /*****************************************************************/
7919 UNIV_INTERN
7920 int
7922 /*==================*/
7923  uchar* buf)
7925 {
7926  int error;
7927 
7928  DBUG_ENTER("rnd_next");
7929  ha_statistic_increment(&SSV::ha_read_rnd_next_count);
7930 
7931  if (start_of_scan) {
7932  error = index_first(buf);
7933 
7934  if (error == HA_ERR_KEY_NOT_FOUND) {
7935  error = HA_ERR_END_OF_FILE;
7936  }
7937 
7938  start_of_scan = 0;
7939  } else {
7940  error = general_fetch(buf, ROW_SEL_NEXT, 0);
7941  }
7942 
7943  DBUG_RETURN(error);
7944 }
7945 
7946 /**********************************************************************/
7949 UNIV_INTERN
7950 int
7952 /*=================*/
7953  uchar* buf,
7954  uchar* pos)
7958 {
7959  int error;
7960  DBUG_ENTER("rnd_pos");
7961  DBUG_DUMP("key", pos, ref_length);
7962 
7963  ha_statistic_increment(&SSV::ha_read_rnd_count);
7964 
7965  ut_a(prebuilt->trx == thd_to_trx(ha_thd()));
7966 
7967  /* Note that we assume the length of the row reference is fixed
7968  for the table, and it is == ref_length */
7969 
7970  error = index_read(buf, pos, ref_length, HA_READ_KEY_EXACT);
7971 
7972  if (error) {
7973  DBUG_PRINT("error", ("Got error: %d", error));
7974  }
7975 
7976  DBUG_RETURN(error);
7977 }
7978 
7979 /**********************************************************************/
7982 UNIV_INTERN
7983 int
7985 /*==================*/
7986 {
7987  DBUG_ENTER("ft_init");
7988 
7989  trx_t* trx = check_trx_exists(ha_thd());
7990 
7991  /* FTS queries are not treated as autocommit non-locking selects.
7992  This is because the FTS implementation can acquire locks behind
7993  the scenes. This has not been verified but it is safer to treat
7994  them as regular read only transactions for now. */
7995 
7996  if (!trx_is_started(trx)) {
7997  ++trx->will_lock;
7998  }
7999 
8000  DBUG_RETURN(rnd_init(false));
8001 }
8002 
8003 /**********************************************************************/
8006 UNIV_INTERN
8007 FT_INFO*
8009 /*=====================*/
8010  uint flags, /* in: */
8011  uint keynr, /* in: */
8012  String* key) /* in: */
8013 {
8014  trx_t* trx;
8015  dict_table_t* table;
8016  dberr_t error;
8017  byte* query = (byte*) key->ptr();
8018  ulint query_len = key->length();
8019  const CHARSET_INFO* char_set = key->charset();
8020  NEW_FT_INFO* fts_hdl = NULL;
8022  fts_result_t* result;
8023  char buf_tmp[8192];
8024  ulint buf_tmp_used;
8025  uint num_errors;
8026 
8027  if (fts_enable_diag_print) {
8028  fprintf(stderr, "keynr=%u, '%.*s'\n",
8029  keynr, (int) key->length(), (byte*) key->ptr());
8030 
8031  if (flags & FT_BOOL) {
8032  fprintf(stderr, "BOOL search\n");
8033  } else {
8034  fprintf(stderr, "NL search\n");
8035  }
8036  }
8037 
8038  /* FIXME: utf32 and utf16 are not compatible with some
8039  string function used. So to convert them to uft8 before
8040  proceed. */
8041  if (strcmp(char_set->csname, "utf32") == 0
8042  || strcmp(char_set->csname, "utf16") == 0) {
8043  buf_tmp_used = innobase_convert_string(
8044  buf_tmp, sizeof(buf_tmp) - 1,
8045  &my_charset_utf8_general_ci,
8046  query, query_len, (CHARSET_INFO*) char_set,
8047  &num_errors);
8048 
8049  query = (byte*) buf_tmp;
8050  query_len = buf_tmp_used;
8051  query[query_len] = 0;
8052  }
8053 
8054  trx = prebuilt->trx;
8055 
8056  /* FTS queries are not treated as autocommit non-locking selects.
8057  This is because the FTS implementation can acquire locks behind
8058  the scenes. This has not been verified but it is safer to treat
8059  them as regular read only transactions for now. */
8060 
8061  if (!trx_is_started(trx)) {
8062  ++trx->will_lock;
8063  }
8064 
8065  table = prebuilt->table;
8066 
8067  /* Table does not have an FTS index */
8068  if (!table->fts || ib_vector_is_empty(table->fts->indexes)) {
8069  my_error(ER_TABLE_HAS_NO_FT, MYF(0));
8070  return(NULL);
8071  }
8072 
8073  if (keynr == NO_SUCH_KEY) {
8074  /* FIXME: Investigate the NO_SUCH_KEY usage */
8075  index = (dict_index_t*) ib_vector_getp(table->fts->indexes, 0);
8076  } else {
8077  index = innobase_get_index(keynr);
8078  }
8079 
8080  if (!index || index->type != DICT_FTS) {
8081  my_error(ER_TABLE_HAS_NO_FT, MYF(0));
8082  return(NULL);
8083  }
8084 
8085  if (!(table->fts->fts_status & ADDED_TABLE_SYNCED)) {
8086  fts_init_index(table, FALSE);
8087 
8088  table->fts->fts_status |= ADDED_TABLE_SYNCED;
8089  }
8090 
8091  error = fts_query(trx, index, flags, query, query_len, &result);
8092 
8093  if (error != DB_SUCCESS) {
8094  my_error(convert_error_code_to_mysql(error, 0, NULL),
8095  MYF(0));
8096  return(NULL);
8097  }
8098 
8099  /* Allocate FTS handler, and instantiate it before return */
8100  fts_hdl = static_cast<NEW_FT_INFO*>(my_malloc(sizeof(NEW_FT_INFO),
8101  MYF(0)));
8102 
8103  fts_hdl->please = const_cast<_ft_vft*>(&ft_vft_result);
8104  fts_hdl->could_you = const_cast<_ft_vft_ext*>(&ft_vft_ext_result);
8105  fts_hdl->ft_prebuilt = prebuilt;
8106  fts_hdl->ft_result = result;
8107 
8108  /* FIXME: Re-evluate the condition when Bug 14469540
8109  is resolved */
8110  prebuilt->in_fts_query = true;
8111 
8112  return((FT_INFO*) fts_hdl);
8113 }
8114 
8115 /*****************************************************************/
8119 static
8120 void
8121 innobase_fts_create_doc_id_key(
8122 /*===========================*/
8123  dtuple_t* tuple, /* in/out: prebuilt->search_tuple */
8124  const dict_index_t*
8125  index, /* in: index (FTS_DOC_ID_INDEX) */
8126  doc_id_t* doc_id) /* in/out: doc id to search, value
8127  could be changed to storage format
8128  used for search. */
8129 {
8130  doc_id_t temp_doc_id;
8131  dfield_t* dfield = dtuple_get_nth_field(tuple, 0);
8132 
8133  ut_a(dict_index_get_n_unique(index) == 1);
8134 
8135  dtuple_set_n_fields(tuple, index->n_fields);
8136  dict_index_copy_types(tuple, index, index->n_fields);
8137 
8138 #ifdef UNIV_DEBUG
8139  /* The unique Doc ID field should be an eight-bytes integer */
8140  dict_field_t* field = dict_index_get_nth_field(index, 0);
8141  ut_a(field->col->mtype == DATA_INT);
8142  ut_ad(sizeof(*doc_id) == field->fixed_len);
8144 #endif /* UNIV_DEBUG */
8145 
8146  /* Convert to storage byte order */
8147  mach_write_to_8(reinterpret_cast<byte*>(&temp_doc_id), *doc_id);
8148  *doc_id = temp_doc_id;
8149  dfield_set_data(dfield, doc_id, sizeof(*doc_id));
8150 
8151  dtuple_set_n_fields_cmp(tuple, 1);
8152 
8153  for (ulint i = 1; i < index->n_fields; i++) {
8154  dfield = dtuple_get_nth_field(tuple, i);
8155  dfield_set_null(dfield);
8156  }
8157 }
8158 
8159 /**********************************************************************/
8162 UNIV_INTERN
8163 int
8165 /*=================*/
8166  uchar* buf)
8167 {
8168  fts_result_t* result;
8169  int error;
8170  row_prebuilt_t* ft_prebuilt;
8171 
8172  ft_prebuilt = ((NEW_FT_INFO*) ft_handler)->ft_prebuilt;
8173 
8174  ut_a(ft_prebuilt == prebuilt);
8175 
8176  result = ((NEW_FT_INFO*) ft_handler)->ft_result;
8177 
8178  if (result->current == NULL) {
8179  /* This is the case where the FTS query did not
8180  contain and matching documents. */
8181  if (result->rankings_by_id != NULL) {
8182  /* Now that we have the complete result, we
8183  need to sort the document ids on their rank
8184  calculation. */
8185 
8187 
8188  result->current = const_cast<ib_rbt_node_t*>(
8189  rbt_first(result->rankings_by_rank));
8190  } else {
8191  ut_a(result->current == NULL);
8192  }
8193  } else {
8194  result->current = const_cast<ib_rbt_node_t*>(
8195  rbt_next(result->rankings_by_rank, result->current));
8196  }
8197 
8198 next_record:
8199 
8200  if (result->current != NULL) {
8202  dtuple_t* tuple = prebuilt->search_tuple;
8203  doc_id_t search_doc_id;
8204 
8205  /* If we only need information from result we can return
8206  without fetching the table row */
8207  if (ft_prebuilt->read_just_key) {
8208  table->status= 0;
8209  return(0);
8210  }
8211 
8213  prebuilt->table, FTS_DOC_ID_INDEX_NAME);
8214 
8215  /* Must find the index */
8216  ut_a(index);
8217 
8218  /* Switch to the FTS doc id index */
8219  prebuilt->index = index;
8220 
8221  fts_ranking_t* ranking = rbt_value(
8222  fts_ranking_t, result->current);
8223 
8224  search_doc_id = ranking->doc_id;
8225 
8226  /* We pass a pointer of search_doc_id because it will be
8227  converted to storage byte order used in the search
8228  tuple. */
8229  innobase_fts_create_doc_id_key(tuple, index, &search_doc_id);
8230 
8231  innobase_srv_conc_enter_innodb(prebuilt->trx);
8232 
8234  (byte*) buf, PAGE_CUR_GE, prebuilt, ROW_SEL_EXACT, 0);
8235 
8236  innobase_srv_conc_exit_innodb(prebuilt->trx);
8237 
8238  switch (ret) {
8239  case DB_SUCCESS:
8240  error = 0;
8241  table->status = 0;
8242  break;
8243  case DB_RECORD_NOT_FOUND:
8244  result->current = const_cast<ib_rbt_node_t*>(
8245  rbt_next(result->rankings_by_rank,
8246  result->current));
8247 
8248  if (!result->current) {
8249  /* exhaust the result set, should return
8250  HA_ERR_END_OF_FILE just like
8251  ha_innobase::general_fetch() and/or
8252  ha_innobase::index_first() etc. */
8253  error = HA_ERR_END_OF_FILE;
8254  table->status = STATUS_NOT_FOUND;
8255  } else {
8256  goto next_record;
8257  }
8258  break;
8259  case DB_END_OF_INDEX:
8260  error = HA_ERR_END_OF_FILE;
8261  table->status = STATUS_NOT_FOUND;
8262  break;
8263  case DB_TABLESPACE_DELETED:
8264 
8265  ib_senderrf(
8266  prebuilt->trx->mysql_thd, IB_LOG_LEVEL_ERROR,
8267  ER_TABLESPACE_DISCARDED,
8268  table->s->table_name.str);
8269 
8270  table->status = STATUS_NOT_FOUND;
8271  error = HA_ERR_NO_SUCH_TABLE;
8272  break;
8273  case DB_TABLESPACE_NOT_FOUND:
8274 
8275  ib_senderrf(
8276  prebuilt->trx->mysql_thd, IB_LOG_LEVEL_ERROR,
8277  ER_TABLESPACE_MISSING,
8278  table->s->table_name.str);
8279 
8280  table->status = STATUS_NOT_FOUND;
8281  error = HA_ERR_NO_SUCH_TABLE;
8282  break;
8283  default:
8284  error = convert_error_code_to_mysql(
8285  ret, 0, user_thd);
8286 
8287  table->status = STATUS_NOT_FOUND;
8288  break;
8289  }
8290 
8291  return(error);
8292  }
8293 
8294  return(HA_ERR_END_OF_FILE);
8295 }
8296 
8297 /*************************************************************************
8298 */
8299 
8300 void
8301 ha_innobase::ft_end()
8302 {
8303  fprintf(stderr, "ft_end()\n");
8304 
8305  rnd_end();
8306 }
8307 
8308 /*********************************************************************/
8316 UNIV_INTERN
8317 void
8319 /*==================*/
8320  const uchar* record)
8321 {
8322  uint len;
8323 
8324  ut_a(prebuilt->trx == thd_to_trx(ha_thd()));
8325 
8326  if (prebuilt->clust_index_was_generated) {
8327  /* No primary key was defined for the table and we
8328  generated the clustered index from row id: the
8329  row reference will be the row id, not any key value
8330  that MySQL knows of */
8331 
8332  len = DATA_ROW_ID_LEN;
8333 
8334  memcpy(ref, prebuilt->row_id, len);
8335  } else {
8336  len = store_key_val_for_row(primary_key, (char*) ref,
8337  ref_length, record);
8338  }
8339 
8340  /* We assume that the 'ref' value len is always fixed for the same
8341  table. */
8342 
8343  if (len != ref_length) {
8344  sql_print_error("Stored ref len is %lu, but table ref len is "
8345  "%lu", (ulong) len, (ulong) ref_length);
8346  }
8347 }
8348 
8349 /* limit innodb monitor access to users with PROCESS privilege.
8350 See http://bugs.mysql.com/32710 for expl. why we choose PROCESS. */
8351 #define IS_MAGIC_TABLE_AND_USER_DENIED_ACCESS(table_name, thd) \
8352  (row_is_magic_monitor_table(table_name) \
8353  && check_global_access(thd, PROCESS_ACL))
8354 
8355 /*****************************************************************/
8359 static
8360 bool
8361 create_table_check_doc_id_col(
8362 /*==========================*/
8363  trx_t* trx,
8364  const TABLE* form,
8366  ulint* doc_id_col)
8370 {
8371  for (ulint i = 0; i < form->s->fields; i++) {
8372  const Field* field;
8373  ulint col_type;
8374  ulint col_len;
8375  ulint unsigned_type;
8376 
8377  field = form->field[i];
8378 
8379  col_type = get_innobase_type_from_mysql_type(&unsigned_type,
8380  field);
8381 
8382  col_len = field->pack_length();
8383 
8384  if (innobase_strcasecmp(field->field_name,
8385  FTS_DOC_ID_COL_NAME) == 0) {
8386 
8387  /* Note the name is case sensitive due to
8388  our internal query parser */
8389  if (col_type == DATA_INT
8390  && !field->real_maybe_null()
8391  && col_len == sizeof(doc_id_t)
8392  && (strcmp(field->field_name,
8393  FTS_DOC_ID_COL_NAME) == 0)) {
8394  *doc_id_col = i;
8395  } else {
8396  push_warning_printf(
8397  trx->mysql_thd,
8398  Sql_condition::WARN_LEVEL_WARN,
8399  ER_ILLEGAL_HA_CREATE_OPTION,
8400  "InnoDB: FTS_DOC_ID column must be "
8401  "of BIGINT NOT NULL type, and named "
8402  "in all capitalized characters");
8403  my_error(ER_WRONG_COLUMN_NAME, MYF(0),
8404  field->field_name);
8405  *doc_id_col = ULINT_UNDEFINED;
8406  }
8407 
8408  return(true);
8409  }
8410  }
8411 
8412  return(false);
8413 }
8414 
8415 /*****************************************************************/
8417 static __attribute__((nonnull, warn_unused_result))
8418 int
8419 create_table_def(
8420 /*=============*/
8421  trx_t* trx,
8422  const TABLE* form,
8424  const char* table_name,
8425  const char* temp_path,
8433  const char* remote_path,
8434  ulint flags,
8435  ulint flags2)
8436 {
8437  THD* thd = trx->mysql_thd;
8439  ulint n_cols;
8440  dberr_t err;
8441  ulint col_type;
8442  ulint col_len;
8443  ulint nulls_allowed;
8444  ulint unsigned_type;
8445  ulint binary_type;
8446  ulint long_true_varchar;
8447  ulint charset_no;
8448  ulint i;
8449  ulint doc_id_col = 0;
8450  ibool has_doc_id_col = FALSE;
8451  mem_heap_t* heap;
8452 
8453  DBUG_ENTER("create_table_def");
8454  DBUG_PRINT("enter", ("table_name: %s", table_name));
8455 
8456  DBUG_ASSERT(thd != NULL);
8457 
8458  /* MySQL does the name length check. But we do additional check
8459  on the name length here */
8460  if (strlen(table_name) > MAX_FULL_NAME_LEN) {
8461  push_warning_printf(
8462  thd, Sql_condition::WARN_LEVEL_WARN,
8463  ER_TABLE_NAME,
8464  "InnoDB: Table Name or Database Name is too long");
8465 
8466  DBUG_RETURN(ER_TABLE_NAME);
8467  }
8468 
8469  /* table_name must contain '/'. Later in the code we assert if it
8470  does not */
8471  if (strcmp(strchr(table_name, '/') + 1,
8472  "innodb_table_monitor") == 0) {
8473  push_warning(
8474  thd, Sql_condition::WARN_LEVEL_WARN,
8475  HA_ERR_WRONG_COMMAND,
8476  DEPRECATED_MSG_INNODB_TABLE_MONITOR);
8477  }
8478 
8479  n_cols = form->s->fields;
8480 
8481  /* Check whether there already exists a FTS_DOC_ID column */
8482  if (create_table_check_doc_id_col(trx, form, &doc_id_col)){
8483 
8484  /* Raise error if the Doc ID column is of wrong type or name */
8485  if (doc_id_col == ULINT_UNDEFINED) {
8486  trx_commit_for_mysql(trx);
8487 
8488  err = DB_ERROR;
8489  goto error_ret;
8490  } else {
8491  has_doc_id_col = TRUE;
8492  }
8493  }
8494 
8495  /* We pass 0 as the space id, and determine at a lower level the space
8496  id where to store the table */
8497 
8498  if (flags2 & DICT_TF2_FTS) {
8499  /* Adjust for the FTS hidden field */
8500  if (!has_doc_id_col) {
8501  table = dict_mem_table_create(table_name, 0, n_cols + 1,
8502  flags, flags2);
8503 
8504  /* Set the hidden doc_id column. */
8505  table->fts->doc_col = n_cols;
8506  } else {
8507  table = dict_mem_table_create(table_name, 0, n_cols,
8508  flags, flags2);
8509  table->fts->doc_col = doc_id_col;
8510  }
8511  } else {
8512  table = dict_mem_table_create(table_name, 0, n_cols,
8513  flags, flags2);
8514  }
8515 
8516  if (flags2 & DICT_TF2_TEMPORARY) {
8517  ut_a(strlen(temp_path));
8518  table->dir_path_of_temp_table =
8519  mem_heap_strdup(table->heap, temp_path);
8520  }
8521 
8522  if (DICT_TF_HAS_DATA_DIR(flags)) {
8523  ut_a(strlen(remote_path));
8524  table->data_dir_path = mem_heap_strdup(table->heap, remote_path);
8525  } else {
8526  table->data_dir_path = NULL;
8527  }
8528  heap = mem_heap_create(1000);
8529 
8530  for (i = 0; i < n_cols; i++) {
8531  Field* field = form->field[i];
8532 
8533  col_type = get_innobase_type_from_mysql_type(&unsigned_type,
8534  field);
8535 
8536  if (!col_type) {
8537  push_warning_printf(
8538  thd, Sql_condition::WARN_LEVEL_WARN,
8539  ER_CANT_CREATE_TABLE,
8540  "Error creating table '%s' with "
8541  "column '%s'. Please check its "
8542  "column type and try to re-create "
8543  "the table with an appropriate "
8544  "column type.",
8545  table->name, field->field_name);
8546  goto err_col;
8547  }
8548 
8549  nulls_allowed = field->real_maybe_null() ? 0 : DATA_NOT_NULL;
8550  binary_type = field->binary() ? DATA_BINARY_TYPE : 0;
8551 
8552  charset_no = 0;
8553 
8554  if (dtype_is_string_type(col_type)) {
8555 
8556  charset_no = (ulint) field->charset()->number;
8557 
8558  if (UNIV_UNLIKELY(charset_no > MAX_CHAR_COLL_NUM)) {
8559  /* in data0type.h we assume that the
8560  number fits in one byte in prtype */
8561  push_warning_printf(
8562  thd, Sql_condition::WARN_LEVEL_WARN,
8563  ER_CANT_CREATE_TABLE,
8564  "In InnoDB, charset-collation codes"
8565  " must be below 256."
8566  " Unsupported code %lu.",
8567  (ulong) charset_no);
8568  mem_heap_free(heap);
8569  DBUG_RETURN(ER_CANT_CREATE_TABLE);
8570  }
8571  }
8572 
8573  /* we assume in dtype_form_prtype() that this fits in
8574  two bytes */
8575  ut_a(field->type() <= MAX_CHAR_COLL_NUM);
8576  col_len = field->pack_length();
8577 
8578  /* The MySQL pack length contains 1 or 2 bytes length field
8579  for a true VARCHAR. Let us subtract that, so that the InnoDB
8580  column length in the InnoDB data dictionary is the real
8581  maximum byte length of the actual data. */
8582 
8583  long_true_varchar = 0;
8584 
8585  if (field->type() == MYSQL_TYPE_VARCHAR) {
8586  col_len -= ((Field_varstring*) field)->length_bytes;
8587 
8588  if (((Field_varstring*) field)->length_bytes == 2) {
8589  long_true_varchar = DATA_LONG_TRUE_VARCHAR;
8590  }
8591  }
8592 
8593  /* First check whether the column to be added has a
8594  system reserved name. */
8595  if (dict_col_name_is_reserved(field->field_name)){
8596  my_error(ER_WRONG_COLUMN_NAME, MYF(0),
8597  field->field_name);
8598 err_col:
8599  dict_mem_table_free(table);
8600  mem_heap_free(heap);
8601  trx_commit_for_mysql(trx);
8602 
8603  err = DB_ERROR;
8604  goto error_ret;
8605  }
8606 
8607  dict_mem_table_add_col(table, heap,
8608  field->field_name,
8609  col_type,
8611  (ulint) field->type()
8612  | nulls_allowed | unsigned_type
8613  | binary_type | long_true_varchar,
8614  charset_no),
8615  col_len);
8616  }
8617 
8618  /* Add the FTS doc_id hidden column. */
8619  if (flags2 & DICT_TF2_FTS && !has_doc_id_col) {
8620  fts_add_doc_id_column(table, heap);
8621  }
8622 
8623  err = row_create_table_for_mysql(table, trx, false);
8624 
8625  mem_heap_free(heap);
8626 
8627  DBUG_EXECUTE_IF("ib_create_err_tablespace_exist",
8628  err = DB_TABLESPACE_EXISTS;);
8629 
8630  if (err == DB_DUPLICATE_KEY || err == DB_TABLESPACE_EXISTS) {
8631  char display_name[FN_REFLEN];
8632  char* buf_end = innobase_convert_identifier(
8633  display_name, sizeof(display_name) - 1,
8634  table_name, strlen(table_name),
8635  thd, TRUE);
8636 
8637  *buf_end = '\0';
8638 
8639  my_error(err == DB_DUPLICATE_KEY
8640  ? ER_TABLE_EXISTS_ERROR
8641  : ER_TABLESPACE_EXISTS, MYF(0), display_name);
8642  }
8643 
8644  if (err == DB_SUCCESS && (flags2 & DICT_TF2_FTS)) {
8645  fts_optimize_add_table(table);
8646  }
8647 
8648 error_ret:
8649  DBUG_RETURN(convert_error_code_to_mysql(err, flags, thd));
8650 }
8651 
8652 /*****************************************************************/
8654 static
8655 int
8656 create_index(
8657 /*=========*/
8658  trx_t* trx,
8659  const TABLE* form,
8661  ulint flags,
8662  const char* table_name,
8663  uint key_num)
8664 {
8666  int error;
8667  const KEY* key;
8668  ulint ind_type;
8669  ulint* field_lengths;
8670 
8671  DBUG_ENTER("create_index");
8672 
8673  key = form->key_info + key_num;
8674 
8675  /* Assert that "GEN_CLUST_INDEX" cannot be used as non-primary index */
8676  ut_a(innobase_strcasecmp(key->name, innobase_index_reserve_name) != 0);
8677 
8678  if (key->flags & HA_FULLTEXT) {
8679  index = dict_mem_index_create(table_name, key->name, 0,
8680  DICT_FTS,
8681  key->user_defined_key_parts);
8682 
8683  for (ulint i = 0; i < key->user_defined_key_parts; i++) {
8684  KEY_PART_INFO* key_part = key->key_part + i;
8686  index, key_part->field->field_name, 0);
8687  }
8688 
8689  DBUG_RETURN(convert_error_code_to_mysql(
8691  index, trx, NULL),
8692  flags, NULL));
8693 
8694  }
8695 
8696  ind_type = 0;
8697 
8698  if (key_num == form->s->primary_key) {
8699  ind_type |= DICT_CLUSTERED;
8700  }
8701 
8702  if (key->flags & HA_NOSAME) {
8703  ind_type |= DICT_UNIQUE;
8704  }
8705 
8706  field_lengths = (ulint*) my_malloc(
8707  key->user_defined_key_parts * sizeof *
8708  field_lengths, MYF(MY_FAE));
8709 
8710  /* We pass 0 as the space id, and determine at a lower level the space
8711  id where to store the table */
8712 
8713  index = dict_mem_index_create(table_name, key->name, 0,
8714  ind_type, key->user_defined_key_parts);
8715 
8716  for (ulint i = 0; i < key->user_defined_key_parts; i++) {
8717  KEY_PART_INFO* key_part = key->key_part + i;
8718  ulint prefix_len;
8719  ulint col_type;
8720  ulint is_unsigned;
8721 
8722 
8723  /* (The flag HA_PART_KEY_SEG denotes in MySQL a
8724  column prefix field in an index: we only store a
8725  specified number of first bytes of the column to
8726  the index field.) The flag does not seem to be
8727  properly set by MySQL. Let us fall back on testing
8728  the length of the key part versus the column. */
8729 
8730  Field* field = NULL;
8731 
8732  for (ulint j = 0; j < form->s->fields; j++) {
8733 
8734  field = form->field[j];
8735 
8736  if (0 == innobase_strcasecmp(
8737  field->field_name,
8738  key_part->field->field_name)) {
8739  /* Found the corresponding column */
8740 
8741  goto found;
8742  }
8743  }
8744 
8745  ut_error;
8746 found:
8748  &is_unsigned, key_part->field);
8749 
8750  if (DATA_BLOB == col_type
8751  || (key_part->length < field->pack_length()
8752  && field->type() != MYSQL_TYPE_VARCHAR)
8753  || (field->type() == MYSQL_TYPE_VARCHAR
8754  && key_part->length < field->pack_length()
8755  - ((Field_varstring*) field)->length_bytes)) {
8756 
8757  switch (col_type) {
8758  default:
8759  prefix_len = key_part->length;
8760  break;
8761  case DATA_INT:
8762  case DATA_FLOAT:
8763  case DATA_DOUBLE:
8764  case DATA_DECIMAL:
8765  sql_print_error(
8766  "MySQL is trying to create a column "
8767  "prefix index field, on an "
8768  "inappropriate data type. Table "
8769  "name %s, column name %s.",
8770  table_name,
8771  key_part->field->field_name);
8772 
8773  prefix_len = 0;
8774  }
8775  } else {
8776  prefix_len = 0;
8777  }
8778 
8779  field_lengths[i] = key_part->length;
8780 
8782  index, key_part->field->field_name, prefix_len);
8783  }
8784 
8785  ut_ad(key->flags & HA_FULLTEXT || !(index->type & DICT_FTS));
8786 
8787  /* Even though we've defined max_supported_key_part_length, we
8788  still do our own checking using field_lengths to be absolutely
8789  sure we don't create too long indexes. */
8790 
8791  error = convert_error_code_to_mysql(
8792  row_create_index_for_mysql(index, trx, field_lengths),
8793  flags, NULL);
8794 
8795  my_free(field_lengths);
8796 
8797  DBUG_RETURN(error);
8798 }
8799 
8800 /*****************************************************************/
8803 static
8804 int
8805 create_clustered_index_when_no_primary(
8806 /*===================================*/
8807  trx_t* trx,
8808  ulint flags,
8809  const char* table_name)
8810 {
8812  dberr_t error;
8813 
8814  /* We pass 0 as the space id, and determine at a lower level the space
8815  id where to store the table */
8816  index = dict_mem_index_create(table_name,
8817  innobase_index_reserve_name,
8818  0, DICT_CLUSTERED, 0);
8819 
8820  error = row_create_index_for_mysql(index, trx, NULL);
8821 
8822  return(convert_error_code_to_mysql(error, flags, NULL));
8823 }
8824 
8825 /*****************************************************************/
8828 UNIV_INTERN
8829 const char*
8830 get_row_format_name(
8831 /*================*/
8832  enum row_type row_format)
8833 {
8834  switch (row_format) {
8835  case ROW_TYPE_COMPACT:
8836  return("COMPACT");
8837  case ROW_TYPE_COMPRESSED:
8838  return("COMPRESSED");
8839  case ROW_TYPE_DYNAMIC:
8840  return("DYNAMIC");
8841  case ROW_TYPE_REDUNDANT:
8842  return("REDUNDANT");
8843  case ROW_TYPE_DEFAULT:
8844  return("DEFAULT");
8845  case ROW_TYPE_FIXED:
8846  return("FIXED");
8847  case ROW_TYPE_PAGE:
8848  case ROW_TYPE_NOT_USED:
8849  break;
8850  }
8851  return("NOT USED");
8852 }
8853 
8855 #define CHECK_ERROR_ROW_TYPE_NEEDS_FILE_PER_TABLE(use_tablespace)\
8856  if (!use_tablespace) { \
8857  push_warning_printf( \
8858  thd, Sql_condition::WARN_LEVEL_WARN, \
8859  ER_ILLEGAL_HA_CREATE_OPTION, \
8860  "InnoDB: ROW_FORMAT=%s requires" \
8861  " innodb_file_per_table.", \
8862  get_row_format_name(row_format)); \
8863  ret = "ROW_FORMAT"; \
8864  }
8865 
8867 #define CHECK_ERROR_ROW_TYPE_NEEDS_GT_ANTELOPE \
8868  if (srv_file_format < UNIV_FORMAT_B) { \
8869  push_warning_printf( \
8870  thd, Sql_condition::WARN_LEVEL_WARN, \
8871  ER_ILLEGAL_HA_CREATE_OPTION, \
8872  "InnoDB: ROW_FORMAT=%s requires" \
8873  " innodb_file_format > Antelope.", \
8874  get_row_format_name(row_format)); \
8875  ret = "ROW_FORMAT"; \
8876  }
8877 
8878 
8879 /*****************************************************************/
8885 UNIV_INTERN
8886 const char*
8887 create_options_are_invalid(
8888 /*=======================*/
8889  THD* thd,
8890  TABLE* form,
8892  HA_CREATE_INFO* create_info,
8893  bool use_tablespace)
8894 {
8895  ibool kbs_specified = FALSE;
8896  const char* ret = NULL;
8897  enum row_type row_format = form->s->row_type;
8898 
8899  ut_ad(thd != NULL);
8900 
8901  /* If innodb_strict_mode is not set don't do any validation. */
8902  if (!(THDVAR(thd, strict_mode))) {
8903  return(NULL);
8904  }
8905 
8906  ut_ad(form != NULL);
8907  ut_ad(create_info != NULL);
8908 
8909  /* First check if a non-zero KEY_BLOCK_SIZE was specified. */
8910  if (create_info->key_block_size) {
8911  kbs_specified = TRUE;
8912  switch (create_info->key_block_size) {
8913  ulint kbs_max;
8914  case 1:
8915  case 2:
8916  case 4:
8917  case 8:
8918  case 16:
8919  /* Valid KEY_BLOCK_SIZE, check its dependencies. */
8920  if (!use_tablespace) {
8921  push_warning(
8922  thd, Sql_condition::WARN_LEVEL_WARN,
8923  ER_ILLEGAL_HA_CREATE_OPTION,
8924  "InnoDB: KEY_BLOCK_SIZE requires"
8925  " innodb_file_per_table.");
8926  ret = "KEY_BLOCK_SIZE";
8927  }
8928  if (srv_file_format < UNIV_FORMAT_B) {
8929  push_warning(
8930  thd, Sql_condition::WARN_LEVEL_WARN,
8931  ER_ILLEGAL_HA_CREATE_OPTION,
8932  "InnoDB: KEY_BLOCK_SIZE requires"
8933  " innodb_file_format > Antelope.");
8934  ret = "KEY_BLOCK_SIZE";
8935  }
8936 
8937  /* The maximum KEY_BLOCK_SIZE (KBS) is 16. But if
8938  UNIV_PAGE_SIZE is smaller than 16k, the maximum
8939  KBS is also smaller. */
8940  kbs_max = ut_min(
8941  1 << (UNIV_PAGE_SSIZE_MAX - 1),
8942  1 << (PAGE_ZIP_SSIZE_MAX - 1));
8943  if (create_info->key_block_size > kbs_max) {
8944  push_warning_printf(
8945  thd, Sql_condition::WARN_LEVEL_WARN,
8946  ER_ILLEGAL_HA_CREATE_OPTION,
8947  "InnoDB: KEY_BLOCK_SIZE=%ld"
8948  " cannot be larger than %ld.",
8949  create_info->key_block_size,
8950  kbs_max);
8951  ret = "KEY_BLOCK_SIZE";
8952  }
8953  break;
8954  default:
8955  push_warning_printf(
8956  thd, Sql_condition::WARN_LEVEL_WARN,
8957  ER_ILLEGAL_HA_CREATE_OPTION,
8958  "InnoDB: invalid KEY_BLOCK_SIZE = %lu."
8959  " Valid values are [1, 2, 4, 8, 16]",
8960  create_info->key_block_size);
8961  ret = "KEY_BLOCK_SIZE";
8962  break;
8963  }
8964  }
8965 
8966  /* Check for a valid Innodb ROW_FORMAT specifier and
8967  other incompatibilities. */
8968  switch (row_format) {
8969  case ROW_TYPE_COMPRESSED:
8970  CHECK_ERROR_ROW_TYPE_NEEDS_FILE_PER_TABLE(use_tablespace);
8971  CHECK_ERROR_ROW_TYPE_NEEDS_GT_ANTELOPE;
8972  break;
8973  case ROW_TYPE_DYNAMIC:
8974  CHECK_ERROR_ROW_TYPE_NEEDS_FILE_PER_TABLE(use_tablespace);
8975  CHECK_ERROR_ROW_TYPE_NEEDS_GT_ANTELOPE;
8976  /* fall through since dynamic also shuns KBS */
8977  case ROW_TYPE_COMPACT:
8978  case ROW_TYPE_REDUNDANT:
8979  if (kbs_specified) {
8980  push_warning_printf(
8981  thd, Sql_condition::WARN_LEVEL_WARN,
8982  ER_ILLEGAL_HA_CREATE_OPTION,
8983  "InnoDB: cannot specify ROW_FORMAT = %s"
8984  " with KEY_BLOCK_SIZE.",
8985  get_row_format_name(row_format));
8986  ret = "KEY_BLOCK_SIZE";
8987  }
8988  break;
8989  case ROW_TYPE_DEFAULT:
8990  break;
8991  case ROW_TYPE_FIXED:
8992  case ROW_TYPE_PAGE:
8993  case ROW_TYPE_NOT_USED:
8994  push_warning(
8995  thd, Sql_condition::WARN_LEVEL_WARN,
8996  ER_ILLEGAL_HA_CREATE_OPTION, \
8997  "InnoDB: invalid ROW_FORMAT specifier.");
8998  ret = "ROW_TYPE";
8999  break;
9000  }
9001 
9002  /* Use DATA DIRECTORY only with file-per-table. */
9003  if (create_info->data_file_name && !use_tablespace) {
9004  push_warning(
9005  thd, Sql_condition::WARN_LEVEL_WARN,
9006  ER_ILLEGAL_HA_CREATE_OPTION,
9007  "InnoDB: DATA DIRECTORY requires"
9008  " innodb_file_per_table.");
9009  ret = "DATA DIRECTORY";
9010  }
9011 
9012  /* Do not use DATA DIRECTORY with TEMPORARY TABLE. */
9013  if (create_info->data_file_name
9014  && create_info->options & HA_LEX_CREATE_TMP_TABLE) {
9015  push_warning(
9016  thd, Sql_condition::WARN_LEVEL_WARN,
9017  ER_ILLEGAL_HA_CREATE_OPTION,
9018  "InnoDB: DATA DIRECTORY cannot be used"
9019  " for TEMPORARY tables.");
9020  ret = "DATA DIRECTORY";
9021  }
9022 
9023  /* Do not allow INDEX_DIRECTORY */
9024  if (create_info->index_file_name) {
9025  push_warning_printf(
9026  thd, Sql_condition::WARN_LEVEL_WARN,
9027  ER_ILLEGAL_HA_CREATE_OPTION,
9028  "InnoDB: INDEX DIRECTORY is not supported");
9029  ret = "INDEX DIRECTORY";
9030  }
9031 
9032  return(ret);
9033 }
9034 
9035 /*****************************************************************/
9037 UNIV_INTERN
9038 void
9039 ha_innobase::update_create_info(
9040 /*============================*/
9041  HA_CREATE_INFO* create_info)
9042 {
9043  if (!(create_info->used_fields & HA_CREATE_USED_AUTO)) {
9044  ha_innobase::info(HA_STATUS_AUTO);
9045  create_info->auto_increment_value = stats.auto_increment_value;
9046  }
9047 
9048  /* Update the DATA DIRECTORY name from SYS_DATAFILES. */
9049  dict_get_and_save_data_dir_path(prebuilt->table, false);
9050 
9051  if (prebuilt->table->data_dir_path) {
9052  create_info->data_file_name = prebuilt->table->data_dir_path;
9053  }
9054 }
9055 
9056 /*****************************************************************/
9059 UNIV_INTERN
9060 ibool
9061 innobase_fts_load_stopword(
9062 /*=======================*/
9063  dict_table_t* table,
9064  trx_t* trx,
9065  THD* thd)
9066 {
9067  return(fts_load_stopword(table, trx,
9068  fts_server_stopword_table,
9069  THDVAR(thd, ft_user_stopword_table),
9070  THDVAR(thd, ft_enable_stopword), FALSE));
9071 }
9072 
9073 /*****************************************************************/
9077 UNIV_INTERN
9078 int
9079 ha_innobase::parse_table_name(
9080 /*==========================*/
9081  const char* name,
9082  HA_CREATE_INFO* create_info,
9085  ulint flags,
9086  ulint flags2,
9087  char* norm_name,
9088  char* temp_path,
9089  char* remote_path)
9090 {
9091  THD* thd = ha_thd();
9092  bool use_tablespace = flags2 & DICT_TF2_USE_TABLESPACE;
9093  DBUG_ENTER("ha_innobase::parse_table_name");
9094 
9095 #ifdef __WIN__
9096  /* Names passed in from server are in two formats:
9097  1. <database_name>/<table_name>: for normal table creation
9098  2. full path: for temp table creation, or DATA DIRECTORY.
9099 
9100  When srv_file_per_table is on and mysqld_embedded is off,
9101  check for full path pattern, i.e.
9102  X:\dir\..., X is a driver letter, or
9103  \\dir1\dir2\..., UNC path
9104  returns error if it is in full path format, but not creating a temp.
9105  table. Currently InnoDB does not support symbolic link on Windows. */
9106 
9107  if (use_tablespace
9108  && !mysqld_embedded
9109  && !(create_info->options & HA_LEX_CREATE_TMP_TABLE)) {
9110 
9111  if ((name[1] == ':')
9112  || (name[0] == '\\' && name[1] == '\\')) {
9113  sql_print_error("Cannot create table %s\n", name);
9114  DBUG_RETURN(HA_ERR_GENERIC);
9115  }
9116  }
9117 #endif
9118 
9119  normalize_table_name(norm_name, name);
9120  temp_path[0] = '\0';
9121  remote_path[0] = '\0';
9122 
9123  /* A full path is used for TEMPORARY TABLE and DATA DIRECTORY.
9124  In the case of;
9125  CREATE TEMPORARY TABLE ... DATA DIRECTORY={path} ... ;
9126  We ignore the DATA DIRECTORY. */
9127  if (create_info->options & HA_LEX_CREATE_TMP_TABLE) {
9128  strncpy(temp_path, name, FN_REFLEN - 1);
9129  }
9130 
9131  if (create_info->data_file_name) {
9132  bool ignore = false;
9133 
9134  /* Use DATA DIRECTORY only with file-per-table. */
9135  if (!use_tablespace) {
9136  push_warning(
9137  thd, Sql_condition::WARN_LEVEL_WARN,
9138  ER_ILLEGAL_HA_CREATE_OPTION,
9139  "InnoDB: DATA DIRECTORY requires"
9140  " innodb_file_per_table.");
9141  ignore = true;
9142  }
9143 
9144  /* Do not use DATA DIRECTORY with TEMPORARY TABLE. */
9145  if (create_info->options & HA_LEX_CREATE_TMP_TABLE) {
9146  push_warning(
9147  thd, Sql_condition::WARN_LEVEL_WARN,
9148  ER_ILLEGAL_HA_CREATE_OPTION,
9149  "InnoDB: DATA DIRECTORY cannot be"
9150  " used for TEMPORARY tables.");
9151  ignore = true;
9152  }
9153 
9154  if (ignore) {
9155  push_warning_printf(
9156  thd, Sql_condition::WARN_LEVEL_WARN,
9157  WARN_OPTION_IGNORED,
9158  ER_DEFAULT(WARN_OPTION_IGNORED),
9159  "DATA DIRECTORY");
9160  } else {
9161  strncpy(remote_path, create_info->data_file_name,
9162  FN_REFLEN - 1);
9163  }
9164  }
9165 
9166  if (create_info->index_file_name) {
9167  push_warning_printf(
9168  thd, Sql_condition::WARN_LEVEL_WARN,
9169  WARN_OPTION_IGNORED,
9170  ER_DEFAULT(WARN_OPTION_IGNORED),
9171  "INDEX DIRECTORY");
9172  }
9173 
9174  DBUG_RETURN(0);
9175 }
9176 
9177 /*****************************************************************/
9180 UNIV_INTERN
9181 bool
9182 innobase_table_flags(
9183 /*=================*/
9184  const TABLE* form,
9185  const HA_CREATE_INFO* create_info,
9187  THD* thd,
9188  bool use_tablespace,
9190  ulint* flags,
9191  ulint* flags2)
9192 {
9193  DBUG_ENTER("innobase_table_flags");
9194 
9195  const char* fts_doc_id_index_bad = NULL;
9196  bool zip_allowed = true;
9197  ulint zip_ssize = 0;
9198  enum row_type row_format;
9199  rec_format_t innodb_row_format = REC_FORMAT_COMPACT;
9200  bool use_data_dir;
9201 
9202  /* Cache the value of innodb_file_format, in case it is
9203  modified by another thread while the table is being created. */
9204  const ulint file_format_allowed = srv_file_format;
9205 
9206  *flags = 0;
9207  *flags2 = 0;
9208 
9209  /* Check if there are any FTS indexes defined on this table. */
9210  for (uint i = 0; i < form->s->keys; i++) {
9211  const KEY* key = &form->key_info[i];
9212 
9213  if (key->flags & HA_FULLTEXT) {
9214  *flags2 |= DICT_TF2_FTS;
9215 
9216  /* We don't support FTS indexes in temporary
9217  tables. */
9218  if (create_info->options & HA_LEX_CREATE_TMP_TABLE) {
9219 
9220  my_error(ER_INNODB_NO_FT_TEMP_TABLE, MYF(0));
9221  DBUG_RETURN(false);
9222  }
9223 
9224  if (key->flags & HA_USES_PARSER) {
9225  my_error(ER_INNODB_NO_FT_USES_PARSER, MYF(0));
9226  DBUG_RETURN(false);
9227  }
9228 
9229  if (fts_doc_id_index_bad) {
9230  goto index_bad;
9231  }
9232  }
9233 
9235  continue;
9236  }
9237 
9238  /* Do a pre-check on FTS DOC ID index */
9239  if (!(key->flags & HA_NOSAME)
9240  || strcmp(key->name, FTS_DOC_ID_INDEX_NAME)
9241  || strcmp(key->key_part[0].field->field_name,
9243  fts_doc_id_index_bad = key->name;
9244  }
9245 
9246  if (fts_doc_id_index_bad && (*flags2 & DICT_TF2_FTS)) {
9247 index_bad:
9248  my_error(ER_INNODB_FT_WRONG_DOCID_INDEX, MYF(0),
9249  fts_doc_id_index_bad);
9250  DBUG_RETURN(false);
9251  }
9252  }
9253 
9254  if (create_info->key_block_size) {
9255  /* The requested compressed page size (key_block_size)
9256  is given in kilobytes. If it is a valid number, store
9257  that value as the number of log2 shifts from 512 in
9258  zip_ssize. Zero means it is not compressed. */
9259  ulint zssize; /* Zip Shift Size */
9260  ulint kbsize; /* Key Block Size */
9261  for (zssize = kbsize = 1;
9262  zssize <= ut_min(UNIV_PAGE_SSIZE_MAX,
9264  zssize++, kbsize <<= 1) {
9265  if (kbsize == create_info->key_block_size) {
9266  zip_ssize = zssize;
9267  break;
9268  }
9269  }
9270 
9271  /* Make sure compressed row format is allowed. */
9272  if (!use_tablespace) {
9273  push_warning(
9274  thd, Sql_condition::WARN_LEVEL_WARN,
9275  ER_ILLEGAL_HA_CREATE_OPTION,
9276  "InnoDB: KEY_BLOCK_SIZE requires"
9277  " innodb_file_per_table.");
9278  zip_allowed = FALSE;
9279  }
9280 
9281  if (file_format_allowed < UNIV_FORMAT_B) {
9282  push_warning(
9283  thd, Sql_condition::WARN_LEVEL_WARN,
9284  ER_ILLEGAL_HA_CREATE_OPTION,
9285  "InnoDB: KEY_BLOCK_SIZE requires"
9286  " innodb_file_format > Antelope.");
9287  zip_allowed = FALSE;
9288  }
9289 
9290  if (!zip_allowed
9291  || zssize > ut_min(UNIV_PAGE_SSIZE_MAX,
9292  PAGE_ZIP_SSIZE_MAX)) {
9293  push_warning_printf(
9294  thd, Sql_condition::WARN_LEVEL_WARN,
9295  ER_ILLEGAL_HA_CREATE_OPTION,
9296  "InnoDB: ignoring KEY_BLOCK_SIZE=%lu.",
9297  create_info->key_block_size);
9298  }
9299  }
9300 
9301  row_format = form->s->row_type;
9302 
9303  if (zip_ssize && zip_allowed) {
9304  /* if ROW_FORMAT is set to default,
9305  automatically change it to COMPRESSED.*/
9306  if (row_format == ROW_TYPE_DEFAULT) {
9307  row_format = ROW_TYPE_COMPRESSED;
9308  } else if (row_format != ROW_TYPE_COMPRESSED) {
9309  /* ROW_FORMAT other than COMPRESSED
9310  ignores KEY_BLOCK_SIZE. It does not
9311  make sense to reject conflicting
9312  KEY_BLOCK_SIZE and ROW_FORMAT, because
9313  such combinations can be obtained
9314  with ALTER TABLE anyway. */
9315  push_warning_printf(
9316  thd, Sql_condition::WARN_LEVEL_WARN,
9317  ER_ILLEGAL_HA_CREATE_OPTION,
9318  "InnoDB: ignoring KEY_BLOCK_SIZE=%lu"
9319  " unless ROW_FORMAT=COMPRESSED.",
9320  create_info->key_block_size);
9321  zip_allowed = FALSE;
9322  }
9323  } else {
9324  /* zip_ssize == 0 means no KEY_BLOCK_SIZE.*/
9325  if (row_format == ROW_TYPE_COMPRESSED && zip_allowed) {
9326  /* ROW_FORMAT=COMPRESSED without KEY_BLOCK_SIZE
9327  implies half the maximum KEY_BLOCK_SIZE(*1k) or
9328  UNIV_PAGE_SIZE, whichever is less. */
9329  zip_ssize = ut_min(UNIV_PAGE_SSIZE_MAX,
9330  PAGE_ZIP_SSIZE_MAX) - 1;
9331  }
9332  }
9333 
9334  /* Validate the row format. Correct it if necessary */
9335  switch (row_format) {
9336  case ROW_TYPE_REDUNDANT:
9337  innodb_row_format = REC_FORMAT_REDUNDANT;
9338  break;
9339 
9340  case ROW_TYPE_COMPRESSED:
9341  case ROW_TYPE_DYNAMIC:
9342  if (!use_tablespace) {
9343  push_warning_printf(
9344  thd, Sql_condition::WARN_LEVEL_WARN,
9345  ER_ILLEGAL_HA_CREATE_OPTION,
9346  "InnoDB: ROW_FORMAT=%s requires"
9347  " innodb_file_per_table.",
9348  get_row_format_name(row_format));
9349  } else if (file_format_allowed == UNIV_FORMAT_A) {
9350  push_warning_printf(
9351  thd, Sql_condition::WARN_LEVEL_WARN,
9352  ER_ILLEGAL_HA_CREATE_OPTION,
9353  "InnoDB: ROW_FORMAT=%s requires"
9354  " innodb_file_format > Antelope.",
9355  get_row_format_name(row_format));
9356  } else {
9357  innodb_row_format = (row_format == ROW_TYPE_DYNAMIC
9360  break;
9361  }
9362  zip_allowed = FALSE;
9363  /* fall through to set row_format = COMPACT */
9364  case ROW_TYPE_NOT_USED:
9365  case ROW_TYPE_FIXED:
9366  case ROW_TYPE_PAGE:
9367  push_warning(
9368  thd, Sql_condition::WARN_LEVEL_WARN,
9369  ER_ILLEGAL_HA_CREATE_OPTION,
9370  "InnoDB: assuming ROW_FORMAT=COMPACT.");
9371  case ROW_TYPE_DEFAULT:
9372  /* If we fell through, set row format to Compact. */
9373  row_format = ROW_TYPE_COMPACT;
9374  case ROW_TYPE_COMPACT:
9375  break;
9376  }
9377 
9378  /* Set the table flags */
9379  if (!zip_allowed) {
9380  zip_ssize = 0;
9381  }
9382 
9383  use_data_dir = use_tablespace
9384  && ((create_info->data_file_name != NULL)
9385  && !(create_info->options & HA_LEX_CREATE_TMP_TABLE));
9386 
9387  dict_tf_set(flags, innodb_row_format, zip_ssize, use_data_dir);
9388 
9389  if (create_info->options & HA_LEX_CREATE_TMP_TABLE) {
9390  *flags2 |= DICT_TF2_TEMPORARY;
9391  }
9392 
9393  if (use_tablespace) {
9394  *flags2 |= DICT_TF2_USE_TABLESPACE;
9395  }
9396 
9397  DBUG_RETURN(true);
9398 }
9399 
9400 /*****************************************************************/
9403 UNIV_INTERN
9404 int
9405 ha_innobase::create(
9406 /*================*/
9407  const char* name,
9408  TABLE* form,
9410  HA_CREATE_INFO* create_info)
9413 {
9414  int error;
9415  trx_t* parent_trx;
9416  trx_t* trx;
9417  int primary_key_no;
9418  uint i;
9419  char norm_name[FN_REFLEN]; /* {database}/{tablename} */
9420  char temp_path[FN_REFLEN]; /* absolute path of temp frm */
9421  char remote_path[FN_REFLEN]; /* absolute path of table */
9422  THD* thd = ha_thd();
9423  ib_int64_t auto_inc_value;
9424 
9425  /* Cache the global variable "srv_file_per_table" to a local
9426  variable before using it. Note that "srv_file_per_table"
9427  is not under dict_sys mutex protection, and could be changed
9428  while creating the table. So we read the current value here
9429  and make all further decisions based on this. */
9430  bool use_tablespace = srv_file_per_table;
9431 
9432  /* Zip Shift Size - log2 - 9 of compressed page size,
9433  zero for uncompressed */
9434  ulint flags;
9435  ulint flags2;
9436  dict_table_t* innobase_table = NULL;
9437 
9438  const char* stmt;
9439  size_t stmt_len;
9440 
9441  DBUG_ENTER("ha_innobase::create");
9442 
9443  DBUG_ASSERT(thd != NULL);
9444  DBUG_ASSERT(create_info != NULL);
9445 
9446  if (form->s->fields > REC_MAX_N_USER_FIELDS) {
9447  DBUG_RETURN(HA_ERR_TOO_MANY_FIELDS);
9448  } else if (srv_read_only_mode) {
9449  DBUG_RETURN(HA_ERR_INNODB_READ_ONLY);
9450  }
9451 
9452  /* Create the table definition in InnoDB */
9453 
9454  /* Validate create options if innodb_strict_mode is set. */
9455  if (create_options_are_invalid(
9456  thd, form, create_info, use_tablespace)) {
9457  DBUG_RETURN(HA_WRONG_CREATE_OPTION);
9458  }
9459 
9460  if (!innobase_table_flags(form, create_info,
9461  thd, use_tablespace,
9462  &flags, &flags2)) {
9463  DBUG_RETURN(-1);
9464  }
9465 
9466  error = parse_table_name(name, create_info, flags, flags2,
9467  norm_name, temp_path, remote_path);
9468  if (error) {
9469  DBUG_RETURN(error);
9470  }
9471 
9472  /* Look for a primary key */
9473  primary_key_no = (form->s->primary_key != MAX_KEY ?
9474  (int) form->s->primary_key :
9475  -1);
9476 
9477  /* Our function innobase_get_mysql_key_number_for_index assumes
9478  the primary key is always number 0, if it exists */
9479  ut_a(primary_key_no == -1 || primary_key_no == 0);
9480 
9481  /* Check for name conflicts (with reserved name) for
9482  any user indices to be created. */
9483  if (innobase_index_name_is_reserved(thd, form->key_info,
9484  form->s->keys)) {
9485  DBUG_RETURN(-1);
9486  }
9487 
9488  if (IS_MAGIC_TABLE_AND_USER_DENIED_ACCESS(norm_name, thd)) {
9489  DBUG_RETURN(HA_ERR_GENERIC);
9490  }
9491 
9492  /* Get the transaction associated with the current thd, or create one
9493  if not yet created */
9494 
9495  parent_trx = check_trx_exists(thd);
9496 
9497  /* In case MySQL calls this in the middle of a SELECT query, release
9498  possible adaptive hash latch to avoid deadlocks of threads */
9499 
9501 
9502  trx = innobase_trx_allocate(thd);
9503 
9504  /* Latch the InnoDB data dictionary exclusively so that no deadlocks
9505  or lock waits can happen in it during a table create operation.
9506  Drop table etc. do this latching in row0mysql.cc. */
9507 
9508  row_mysql_lock_data_dictionary(trx);
9509 
9510  error = create_table_def(trx, form, norm_name, temp_path,
9511  remote_path, flags, flags2);
9512  if (error) {
9513  goto cleanup;
9514  }
9515 
9516  /* Create the keys */
9517 
9518  if (form->s->keys == 0 || primary_key_no == -1) {
9519  /* Create an index which is used as the clustered index;
9520  order the rows by their row id which is internally generated
9521  by InnoDB */
9522 
9523  error = create_clustered_index_when_no_primary(
9524  trx, flags, norm_name);
9525  if (error) {
9526  goto cleanup;
9527  }
9528  }
9529 
9530  if (primary_key_no != -1) {
9531  /* In InnoDB the clustered index must always be created
9532  first */
9533  if ((error = create_index(trx, form, flags, norm_name,
9534  (uint) primary_key_no))) {
9535  goto cleanup;
9536  }
9537  }
9538 
9539  /* Create the ancillary tables that are common to all FTS indexes on
9540  this table. */
9541  if (flags2 & DICT_TF2_FTS) {
9542  enum fts_doc_id_index_enum ret;
9543 
9544  innobase_table = dict_table_open_on_name(
9545  norm_name, TRUE, FALSE, DICT_ERR_IGNORE_NONE);
9546 
9547  ut_a(innobase_table);
9548 
9549  /* Check whether there already exists FTS_DOC_ID_INDEX */
9550  ret = innobase_fts_check_doc_id_index_in_def(
9551  form->s->keys, form->key_info);
9552 
9553  switch (ret) {
9554  case FTS_INCORRECT_DOC_ID_INDEX:
9555  push_warning_printf(thd,
9556  Sql_condition::WARN_LEVEL_WARN,
9557  ER_WRONG_NAME_FOR_INDEX,
9558  " InnoDB: Index name %s is reserved"
9559  " for the unique index on"
9560  " FTS_DOC_ID column for FTS"
9561  " Document ID indexing"
9562  " on table %s. Please check"
9563  " the index definition to"
9564  " make sure it is of correct"
9565  " type\n",
9567  innobase_table->name);
9568 
9569  if (innobase_table->fts) {
9570  fts_free(innobase_table);
9571  }
9572 
9573  dict_table_close(innobase_table, TRUE, FALSE);
9574  my_error(ER_WRONG_NAME_FOR_INDEX, MYF(0),
9576  error = -1;
9577  goto cleanup;
9578  case FTS_EXIST_DOC_ID_INDEX:
9579  case FTS_NOT_EXIST_DOC_ID_INDEX:
9580  break;
9581  }
9582 
9584  trx, innobase_table, norm_name,
9585  (ret == FTS_EXIST_DOC_ID_INDEX));
9586 
9587  error = convert_error_code_to_mysql(err, 0, NULL);
9588 
9589  dict_table_close(innobase_table, TRUE, FALSE);
9590 
9591  if (error) {
9592  goto cleanup;
9593  }
9594  }
9595 
9596  for (i = 0; i < form->s->keys; i++) {
9597 
9598  if (i != static_cast<uint>(primary_key_no)) {
9599 
9600  if ((error = create_index(trx, form, flags,
9601  norm_name, i))) {
9602  goto cleanup;
9603  }
9604  }
9605  }
9606 
9607  /* Cache all the FTS indexes on this table in the FTS specific
9608  structure. They are used for FTS indexed column update handling. */
9609  if (flags2 & DICT_TF2_FTS) {
9610  fts_t* fts = innobase_table->fts;
9611 
9612  ut_a(fts != NULL);
9613 
9614  dict_table_get_all_fts_indexes(innobase_table, fts->indexes);
9615  }
9616 
9617  stmt = innobase_get_stmt(thd, &stmt_len);
9618 
9619  if (stmt) {
9621  trx, stmt, stmt_len, norm_name,
9622  create_info->options & HA_LEX_CREATE_TMP_TABLE);
9623 
9624  switch (err) {
9625 
9626  case DB_PARENT_NO_INDEX:
9627  push_warning_printf(
9628  thd, Sql_condition::WARN_LEVEL_WARN,
9629  HA_ERR_CANNOT_ADD_FOREIGN,
9630  "Create table '%s' with foreign key constraint"
9631  " failed. There is no index in the referenced"
9632  " table where the referenced columns appear"
9633  " as the first columns.\n", norm_name);
9634  break;
9635 
9636  case DB_CHILD_NO_INDEX:
9637  push_warning_printf(
9638  thd, Sql_condition::WARN_LEVEL_WARN,
9639  HA_ERR_CANNOT_ADD_FOREIGN,
9640  "Create table '%s' with foreign key constraint"
9641  " failed. There is no index in the referencing"
9642  " table where referencing columns appear"
9643  " as the first columns.\n", norm_name);
9644  break;
9645  default:
9646  break;
9647  }
9648 
9649  error = convert_error_code_to_mysql(err, flags, NULL);
9650 
9651  if (error) {
9652  goto cleanup;
9653  }
9654  }
9655 
9656  innobase_commit_low(trx);
9657 
9659 
9660  /* Flush the log to reduce probability that the .frm files and
9661  the InnoDB data dictionary get out-of-sync if the user runs
9662  with innodb_flush_log_at_trx_commit = 0 */
9663 
9665 
9666  innobase_table = dict_table_open_on_name(
9667  norm_name, FALSE, FALSE, DICT_ERR_IGNORE_NONE);
9668 
9669  DBUG_ASSERT(innobase_table != 0);
9670 
9671  innobase_copy_frm_flags_from_create_info(innobase_table, create_info);
9672 
9673  dict_stats_update(innobase_table, DICT_STATS_EMPTY_TABLE);
9674 
9675  if (innobase_table) {
9676  /* We update the highest file format in the system table
9677  space, if this table has higher file format setting. */
9678 
9680  (const char**) &innobase_file_format_max,
9681  dict_table_get_format(innobase_table));
9682  }
9683 
9684  /* Load server stopword into FTS cache */
9685  if (flags2 & DICT_TF2_FTS) {
9686  if (!innobase_fts_load_stopword(innobase_table, NULL, thd)) {
9687  dict_table_close(innobase_table, FALSE, FALSE);
9689  trx_free_for_mysql(trx);
9690  DBUG_RETURN(-1);
9691  }
9692  }
9693 
9694  /* Note: We can't call update_thd() as prebuilt will not be
9695  setup at this stage and so we use thd. */
9696 
9697  /* We need to copy the AUTOINC value from the old table if
9698  this is an ALTER|OPTIMIZE TABLE or CREATE INDEX because CREATE INDEX
9699  does a table copy too. If query was one of :
9700 
9701  CREATE TABLE ...AUTO_INCREMENT = x; or
9702  ALTER TABLE...AUTO_INCREMENT = x; or
9703  OPTIMIZE TABLE t; or
9704  CREATE INDEX x on t(...);
9705 
9706  Find out a table definition from the dictionary and get
9707  the current value of the auto increment field. Set a new
9708  value to the auto increment field if the value is greater
9709  than the maximum value in the column. */
9710 
9711  if (((create_info->used_fields & HA_CREATE_USED_AUTO)
9712  || thd_sql_command(thd) == SQLCOM_ALTER_TABLE
9713  || thd_sql_command(thd) == SQLCOM_OPTIMIZE
9714  || thd_sql_command(thd) == SQLCOM_CREATE_INDEX)
9715  && create_info->auto_increment_value > 0) {
9716 
9717  auto_inc_value = create_info->auto_increment_value;
9718 
9719  dict_table_autoinc_lock(innobase_table);
9720  dict_table_autoinc_initialize(innobase_table, auto_inc_value);
9721  dict_table_autoinc_unlock(innobase_table);
9722  }
9723 
9724  dict_table_close(innobase_table, FALSE, FALSE);
9725 
9726  /* Tell the InnoDB server that there might be work for
9727  utility threads: */
9728 
9730 
9731  trx_free_for_mysql(trx);
9732 
9733  DBUG_RETURN(0);
9734 
9735 cleanup:
9737 
9739 
9740  trx_free_for_mysql(trx);
9741 
9742  DBUG_RETURN(error);
9743 }
9744 
9745 /*****************************************************************/
9748 UNIV_INTERN
9749 int
9750 ha_innobase::discard_or_import_tablespace(
9751 /*======================================*/
9752  my_bool discard)
9753 {
9754  dberr_t err;
9755  dict_table_t* dict_table;
9756 
9757  DBUG_ENTER("ha_innobase::discard_or_import_tablespace");
9758 
9759  ut_a(prebuilt->trx);
9760  ut_a(prebuilt->trx->magic_n == TRX_MAGIC_N);
9761  ut_a(prebuilt->trx == thd_to_trx(ha_thd()));
9762 
9763  if (srv_read_only_mode) {
9764  DBUG_RETURN(HA_ERR_TABLE_READONLY);
9765  }
9766 
9767  dict_table = prebuilt->table;
9768 
9769  if (dict_table->space == TRX_SYS_SPACE) {
9770 
9771  ib_senderrf(
9772  prebuilt->trx->mysql_thd, IB_LOG_LEVEL_ERROR,
9773  ER_TABLE_IN_SYSTEM_TABLESPACE,
9774  table->s->table_name.str);
9775 
9776  DBUG_RETURN(HA_ERR_TABLE_NEEDS_UPGRADE);
9777  }
9778 
9779  trx_start_if_not_started(prebuilt->trx);
9780 
9781  /* In case MySQL calls this in the middle of a SELECT query, release
9782  possible adaptive hash latch to avoid deadlocks of threads. */
9784 
9785  /* Obtain an exclusive lock on the table. */
9786  err = row_mysql_lock_table(
9787  prebuilt->trx, dict_table, LOCK_X,
9788  discard ? "setting table lock for DISCARD TABLESPACE"
9789  : "setting table lock for IMPORT TABLESPACE");
9790 
9791  if (err != DB_SUCCESS) {
9792  /* unable to lock the table: do nothing */
9793  } else if (discard) {
9794 
9795  /* Discarding an already discarded tablespace should be an
9796  idempotent operation. Also, if the .ibd file is missing the
9797  user may want to set the DISCARD flag in order to IMPORT
9798  a new tablespace. */
9799 
9800  if (dict_table->ibd_file_missing) {
9801  ib_senderrf(
9802  prebuilt->trx->mysql_thd,
9803  IB_LOG_LEVEL_WARN, ER_TABLESPACE_MISSING,
9804  table->s->table_name.str);
9805  }
9806 
9808  dict_table->name, prebuilt->trx);
9809 
9810  } else if (!dict_table->ibd_file_missing) {
9811  /* Commit the transaction in order to
9812  release the table lock. */
9813  trx_commit_for_mysql(prebuilt->trx);
9814 
9815  ib_senderrf(
9816  prebuilt->trx->mysql_thd, IB_LOG_LEVEL_ERROR,
9817  ER_TABLESPACE_EXISTS, table->s->table_name.str);
9818 
9819  DBUG_RETURN(HA_ERR_TABLE_EXIST);
9820  } else {
9821  err = row_import_for_mysql(dict_table, prebuilt);
9822 
9823  if (err == DB_SUCCESS) {
9824 
9825  if (table->found_next_number_field) {
9826  dict_table_autoinc_lock(dict_table);
9827  innobase_initialize_autoinc();
9828  dict_table_autoinc_unlock(dict_table);
9829  }
9830 
9831  info(HA_STATUS_TIME
9832  | HA_STATUS_CONST
9833  | HA_STATUS_VARIABLE
9834  | HA_STATUS_AUTO);
9835  }
9836  }
9837 
9838  /* Commit the transaction in order to release the table lock. */
9839  trx_commit_for_mysql(prebuilt->trx);
9840 
9841  DBUG_RETURN(convert_error_code_to_mysql(err, dict_table->flags, NULL));
9842 }
9843 
9844 /*****************************************************************/
9847 UNIV_INTERN
9848 int
9850 /*===================*/
9851 {
9852  dberr_t err;
9853  int error;
9854 
9855  DBUG_ENTER("ha_innobase::truncate");
9856 
9857  if (srv_read_only_mode) {
9858  DBUG_RETURN(HA_ERR_TABLE_READONLY);
9859  }
9860 
9861  /* Get the transaction associated with the current thd, or create one
9862  if not yet created, and update prebuilt->trx */
9863 
9864  update_thd(ha_thd());
9865 
9866  if (!trx_is_started(prebuilt->trx)) {
9867  ++prebuilt->trx->will_lock;
9868  }
9869  /* Truncate the table in InnoDB */
9870 
9871  err = row_truncate_table_for_mysql(prebuilt->table, prebuilt->trx);
9872 
9873  switch (err) {
9874 
9875  case DB_TABLESPACE_DELETED:
9876  case DB_TABLESPACE_NOT_FOUND:
9877  ib_senderrf(
9878  prebuilt->trx->mysql_thd, IB_LOG_LEVEL_ERROR,
9879  (err == DB_TABLESPACE_DELETED ?
9880  ER_TABLESPACE_DISCARDED : ER_TABLESPACE_MISSING),
9881  table->s->table_name.str);
9882  table->status = STATUS_NOT_FOUND;
9883  error = HA_ERR_NO_SUCH_TABLE;
9884  break;
9885 
9886  default:
9887  error = convert_error_code_to_mysql(
9888  err, prebuilt->table->flags,
9889  prebuilt->trx->mysql_thd);
9890  table->status = STATUS_NOT_FOUND;
9891  break;
9892  }
9893  DBUG_RETURN(error);
9894 }
9895 
9896 /*****************************************************************/
9903 UNIV_INTERN
9904 int
9906 /*======================*/
9907  const char* name)
9908 {
9909  ulint name_len;
9910  dberr_t err;
9911  trx_t* parent_trx;
9912  trx_t* trx;
9913  THD* thd = ha_thd();
9914  char norm_name[FN_REFLEN];
9915 
9916  DBUG_ENTER("ha_innobase::delete_table");
9917 
9918  DBUG_EXECUTE_IF(
9919  "test_normalize_table_name_low",
9920  test_normalize_table_name_low();
9921  );
9922  DBUG_EXECUTE_IF(
9923  "test_ut_format_name",
9924  test_ut_format_name();
9925  );
9926 
9927  /* Strangely, MySQL passes the table name without the '.frm'
9928  extension, in contrast to ::create */
9929  normalize_table_name(norm_name, name);
9930 
9931  if (srv_read_only_mode) {
9932  DBUG_RETURN(HA_ERR_TABLE_READONLY);
9933  } else if (IS_MAGIC_TABLE_AND_USER_DENIED_ACCESS(norm_name, thd)) {
9934  DBUG_RETURN(HA_ERR_GENERIC);
9935  }
9936 
9937  parent_trx = check_trx_exists(thd);
9938 
9939  /* In case MySQL calls this in the middle of a SELECT query, release
9940  possible adaptive hash latch to avoid deadlocks of threads */
9941 
9943 
9944  trx = innobase_trx_allocate(thd);
9945 
9946  name_len = strlen(name);
9947 
9948  ut_a(name_len < 1000);
9949 
9950  /* Either the transaction is already flagged as a locking transaction
9951  or it hasn't been started yet. */
9952 
9953  ut_a(!trx_is_started(trx) || trx->will_lock > 0);
9954 
9955  /* We are doing a DDL operation. */
9956  ++trx->will_lock;
9957  trx->ddl = true;
9958 
9959  /* Drop the table in InnoDB */
9961  norm_name, trx, thd_sql_command(thd) == SQLCOM_DROP_DB);
9962 
9963 
9964  if (err == DB_TABLE_NOT_FOUND
9966  char* is_part = NULL;
9967 #ifdef __WIN__
9968  is_part = strstr(norm_name, "#p#");
9969 #else
9970  is_part = strstr(norm_name, "#P#");
9971 #endif /* __WIN__ */
9972 
9973  if (is_part) {
9974  char par_case_name[FN_REFLEN];
9975 
9976 #ifndef __WIN__
9977  /* Check for the table using lower
9978  case name, including the partition
9979  separator "P" */
9980  strcpy(par_case_name, norm_name);
9981  innobase_casedn_str(par_case_name);
9982 #else
9983  /* On Windows platfrom, check
9984  whether there exists table name in
9985  system table whose name is
9986  not being normalized to lower case */
9987  normalize_table_name_low(
9988  par_case_name, name, FALSE);
9989 #endif
9991  par_case_name, trx,
9992  thd_sql_command(thd) == SQLCOM_DROP_DB);
9993  }
9994  }
9995 
9996  /* Flush the log to reduce probability that the .frm files and
9997  the InnoDB data dictionary get out-of-sync if the user runs
9998  with innodb_flush_log_at_trx_commit = 0 */
9999 
10001 
10002  /* Tell the InnoDB server that there might be work for
10003  utility threads: */
10004 
10006 
10007  innobase_commit_low(trx);
10008 
10009  trx_free_for_mysql(trx);
10010 
10011  DBUG_RETURN(convert_error_code_to_mysql(err, 0, NULL));
10012 }
10013 
10014 /*****************************************************************/
10016 static
10017 void
10018 innobase_drop_database(
10019 /*===================*/
10020  handlerton* hton,
10021  char* path)
10025 {
10026  ulint len = 0;
10027  trx_t* trx;
10028  char* ptr;
10029  char* namebuf;
10030  THD* thd = current_thd;
10031 
10032  /* Get the transaction associated with the current thd, or create one
10033  if not yet created */
10034 
10035  DBUG_ASSERT(hton == innodb_hton_ptr);
10036 
10037  if (srv_read_only_mode) {
10038  return;
10039  }
10040 
10041  /* In the Windows plugin, thd = current_thd is always NULL */
10042  if (thd) {
10043  trx_t* parent_trx = check_trx_exists(thd);
10044 
10045  /* In case MySQL calls this in the middle of a SELECT
10046  query, release possible adaptive hash latch to avoid
10047  deadlocks of threads */
10048 
10050  }
10051 
10052  ptr = strend(path) - 2;
10053 
10054  while (ptr >= path && *ptr != '\\' && *ptr != '/') {
10055  ptr--;
10056  len++;
10057  }
10058 
10059  ptr++;
10060  namebuf = (char*) my_malloc((uint) len + 2, MYF(0));
10061 
10062  memcpy(namebuf, ptr, len);
10063  namebuf[len] = '/';
10064  namebuf[len + 1] = '\0';
10065 #ifdef __WIN__
10066  innobase_casedn_str(namebuf);
10067 #endif
10068  trx = innobase_trx_allocate(thd);
10069 
10070  /* Either the transaction is already flagged as a locking transaction
10071  or it hasn't been started yet. */
10072 
10073  ut_a(!trx_is_started(trx) || trx->will_lock > 0);
10074 
10075  /* We are doing a DDL operation. */
10076  ++trx->will_lock;
10077 
10078  row_drop_database_for_mysql(namebuf, trx);
10079 
10080  my_free(namebuf);
10081 
10082  /* Flush the log to reduce probability that the .frm files and
10083  the InnoDB data dictionary get out-of-sync if the user runs
10084  with innodb_flush_log_at_trx_commit = 0 */
10085 
10087 
10088  /* Tell the InnoDB server that there might be work for
10089  utility threads: */
10090 
10092 
10093  innobase_commit_low(trx);
10094  trx_free_for_mysql(trx);
10095 }
10096 
10097 /*********************************************************************/
10100 static __attribute__((nonnull, warn_unused_result))
10101 dberr_t
10102 innobase_rename_table(
10103 /*==================*/
10104  trx_t* trx,
10105  const char* from,
10106  const char* to)
10107 {
10108  dberr_t error;
10109  char norm_to[FN_REFLEN];
10110  char norm_from[FN_REFLEN];
10111 
10112  DBUG_ENTER("innobase_rename_table");
10113  DBUG_ASSERT(trx_get_dict_operation(trx) == TRX_DICT_OP_INDEX);
10114 
10116 
10117  normalize_table_name(norm_to, to);
10118  normalize_table_name(norm_from, from);
10119 
10120  DEBUG_SYNC_C("innodb_rename_table_ready");
10121 
10122  trx_start_if_not_started(trx);
10123 
10124  /* Serialize data dictionary operations with dictionary mutex:
10125  no deadlocks can occur then in these operations. */
10126 
10127  row_mysql_lock_data_dictionary(trx);
10128 
10129  /* Transaction must be flagged as a locking transaction or it hasn't
10130  been started yet. */
10131 
10132  ut_a(trx->will_lock > 0);
10133 
10135  norm_from, norm_to, trx, TRUE);
10136 
10137  if (error != DB_SUCCESS) {
10138  if (error == DB_TABLE_NOT_FOUND
10140  char* is_part = NULL;
10141 #ifdef __WIN__
10142  is_part = strstr(norm_from, "#p#");
10143 #else
10144  is_part = strstr(norm_from, "#P#");
10145 #endif /* __WIN__ */
10146 
10147  if (is_part) {
10148  char par_case_name[FN_REFLEN];
10149 #ifndef __WIN__
10150  /* Check for the table using lower
10151  case name, including the partition
10152  separator "P" */
10153  strcpy(par_case_name, norm_from);
10154  innobase_casedn_str(par_case_name);
10155 #else
10156  /* On Windows platfrom, check
10157  whether there exists table name in
10158  system table whose name is
10159  not being normalized to lower case */
10160  normalize_table_name_low(
10161  par_case_name, from, FALSE);
10162 #endif
10163  trx_start_if_not_started(trx);
10165  par_case_name, norm_to, trx, TRUE);
10166  }
10167  }
10168 
10169  if (error != DB_SUCCESS) {
10170  if (!srv_read_only_mode) {
10171  FILE* ef = dict_foreign_err_file;
10172 
10173  fputs("InnoDB: Renaming table ", ef);
10174  ut_print_name(ef, trx, TRUE, norm_from);
10175  fputs(" to ", ef);
10176  ut_print_name(ef, trx, TRUE, norm_to);
10177  fputs(" failed!\n", ef);
10178  }
10179  } else {
10180 #ifndef __WIN__
10181  sql_print_warning("Rename partition table %s "
10182  "succeeds after converting to lower "
10183  "case. The table may have "
10184  "been moved from a case "
10185  "in-sensitive file system.\n",
10186  norm_from);
10187 #else
10188  sql_print_warning("Rename partition table %s "
10189  "succeeds after skipping the step to "
10190  "lower case the table name. "
10191  "The table may have been "
10192  "moved from a case sensitive "
10193  "file system.\n",
10194  norm_from);
10195 #endif /* __WIN__ */
10196  }
10197  }
10198 
10200 
10201  /* Flush the log to reduce probability that the .frm
10202  files and the InnoDB data dictionary get out-of-sync
10203  if the user runs with innodb_flush_log_at_trx_commit = 0 */
10204 
10206 
10207  DBUG_RETURN(error);
10208 }
10209 
10210 /*********************************************************************/
10213 UNIV_INTERN
10214 int
10216 /*======================*/
10217  const char* from,
10218  const char* to)
10219 {
10220  trx_t* trx;
10221  dberr_t error;
10222  trx_t* parent_trx;
10223  THD* thd = ha_thd();
10224 
10225  DBUG_ENTER("ha_innobase::rename_table");
10226 
10227  if (srv_read_only_mode) {
10228  ib_senderrf(thd, IB_LOG_LEVEL_WARN, ER_READ_ONLY_MODE);
10229  DBUG_RETURN(HA_ERR_TABLE_READONLY);
10230  }
10231 
10232  /* Get the transaction associated with the current thd, or create one
10233  if not yet created */
10234 
10235  parent_trx = check_trx_exists(thd);
10236 
10237  /* In case MySQL calls this in the middle of a SELECT query, release
10238  possible adaptive hash latch to avoid deadlocks of threads */
10239 
10241 
10242  trx = innobase_trx_allocate(thd);
10243 
10244  /* We are doing a DDL operation. */
10245  ++trx->will_lock;
10247 
10248  error = innobase_rename_table(trx, from, to);
10249 
10250  DEBUG_SYNC(thd, "after_innobase_rename_table");
10251 
10252  /* Tell the InnoDB server that there might be work for
10253  utility threads: */
10254 
10256 
10257  innobase_commit_low(trx);
10258  trx_free_for_mysql(trx);
10259 
10260  if (error == DB_SUCCESS) {
10261  char norm_from[MAX_FULL_NAME_LEN];
10262  char norm_to[MAX_FULL_NAME_LEN];
10263  char errstr[512];
10264  dberr_t ret;
10265 
10266  normalize_table_name(norm_from, from);
10267  normalize_table_name(norm_to, to);
10268 
10269  ret = dict_stats_rename_table(norm_from, norm_to,
10270  errstr, sizeof(errstr));
10271 
10272  if (ret != DB_SUCCESS) {
10273  ut_print_timestamp(stderr);
10274  fprintf(stderr, " InnoDB: %s\n", errstr);
10275 
10276  push_warning(thd, Sql_condition::WARN_LEVEL_WARN,
10277  ER_LOCK_WAIT_TIMEOUT, errstr);
10278  }
10279  }
10280 
10281  /* Add a special case to handle the Duplicated Key error
10282  and return DB_ERROR instead.
10283  This is to avoid a possible SIGSEGV error from mysql error
10284  handling code. Currently, mysql handles the Duplicated Key
10285  error by re-entering the storage layer and getting dup key
10286  info by calling get_dup_key(). This operation requires a valid
10287  table handle ('row_prebuilt_t' structure) which could no
10288  longer be available in the error handling stage. The suggested
10289  solution is to report a 'table exists' error message (since
10290  the dup key error here is due to an existing table whose name
10291  is the one we are trying to rename to) and return the generic
10292  error code. */
10293  if (error == DB_DUPLICATE_KEY) {
10294  my_error(ER_TABLE_EXISTS_ERROR, MYF(0), to);
10295 
10296  error = DB_ERROR;
10297  }
10298 
10299  DBUG_RETURN(convert_error_code_to_mysql(error, 0, NULL));
10300 }
10301 
10302 /*********************************************************************/
10305 UNIV_INTERN
10306 ha_rows
10307 ha_innobase::records_in_range(
10308 /*==========================*/
10309  uint keynr,
10310  key_range *min_key,
10312  key_range *max_key)
10314 {
10315  KEY* key;
10317  dtuple_t* range_start;
10318  dtuple_t* range_end;
10319  ib_int64_t n_rows;
10320  ulint mode1;
10321  ulint mode2;
10322  mem_heap_t* heap;
10323 
10324  DBUG_ENTER("records_in_range");
10325 
10326  ut_a(prebuilt->trx == thd_to_trx(ha_thd()));
10327 
10328  prebuilt->trx->op_info = (char*)"estimating records in index range";
10329 
10330  /* In case MySQL calls this in the middle of a SELECT query, release
10331  possible adaptive hash latch to avoid deadlocks of threads */
10332 
10334 
10335  active_index = keynr;
10336 
10337  key = table->key_info + active_index;
10338 
10339  index = innobase_get_index(keynr);
10340 
10341  /* There exists possibility of not being able to find requested
10342  index due to inconsistency between MySQL and InoDB dictionary info.
10343  Necessary message should have been printed in innobase_get_index() */
10344  if (UNIV_UNLIKELY(!index)) {
10345  n_rows = HA_POS_ERROR;
10346  goto func_exit;
10347  }
10348  if (dict_index_is_corrupted(index)) {
10349  n_rows = HA_ERR_INDEX_CORRUPT;
10350  goto func_exit;
10351  }
10352  if (UNIV_UNLIKELY(!row_merge_is_index_usable(prebuilt->trx, index))) {
10353  n_rows = HA_ERR_TABLE_DEF_CHANGED;
10354  goto func_exit;
10355  }
10356 
10357  heap = mem_heap_create(2 * (key->actual_key_parts * sizeof(dfield_t)
10358  + sizeof(dtuple_t)));
10359 
10360  range_start = dtuple_create(heap, key->actual_key_parts);
10361  dict_index_copy_types(range_start, index, key->actual_key_parts);
10362 
10363  range_end = dtuple_create(heap, key->actual_key_parts);
10364  dict_index_copy_types(range_end, index, key->actual_key_parts);
10365 
10367  range_start,
10368  srch_key_val1, sizeof(srch_key_val1),
10369  index,
10370  (byte*) (min_key ? min_key->key :
10371  (const uchar*) 0),
10372  (ulint) (min_key ? min_key->length : 0),
10373  prebuilt->trx);
10374  DBUG_ASSERT(min_key
10375  ? range_start->n_fields > 0
10376  : range_start->n_fields == 0);
10377 
10379  range_end,
10380  srch_key_val2, sizeof(srch_key_val2),
10381  index,
10382  (byte*) (max_key ? max_key->key :
10383  (const uchar*) 0),
10384  (ulint) (max_key ? max_key->length : 0),
10385  prebuilt->trx);
10386  DBUG_ASSERT(max_key
10387  ? range_end->n_fields > 0
10388  : range_end->n_fields == 0);
10389 
10390  mode1 = convert_search_mode_to_innobase(min_key ? min_key->flag :
10391  HA_READ_KEY_EXACT);
10392  mode2 = convert_search_mode_to_innobase(max_key ? max_key->flag :
10393  HA_READ_KEY_EXACT);
10394 
10395  if (mode1 != PAGE_CUR_UNSUPP && mode2 != PAGE_CUR_UNSUPP) {
10396 
10397  n_rows = btr_estimate_n_rows_in_range(index, range_start,
10398  mode1, range_end,
10399  mode2);
10400  } else {
10401 
10402  n_rows = HA_POS_ERROR;
10403  }
10404 
10405  mem_heap_free(heap);
10406 
10407 func_exit:
10408 
10409  prebuilt->trx->op_info = (char*)"";
10410 
10411  /* The MySQL optimizer seems to believe an estimate of 0 rows is
10412  always accurate and may return the result 'Empty set' based on that.
10413  The accuracy is not guaranteed, and even if it were, for a locking
10414  read we should anyway perform the search to set the next-key lock.
10415  Add 1 to the value to make sure MySQL does not make the assumption! */
10416 
10417  if (n_rows == 0) {
10418  n_rows = 1;
10419  }
10420 
10421  DBUG_RETURN((ha_rows) n_rows);
10422 }
10423 
10424 /*********************************************************************/
10428 UNIV_INTERN
10429 ha_rows
10431 /*====================================*/
10432 {
10433  const dict_index_t* index;
10434  ulonglong estimate;
10435  ulonglong local_data_file_length;
10436  ulint stat_n_leaf_pages;
10437 
10438  DBUG_ENTER("estimate_rows_upper_bound");
10439 
10440  /* We do not know if MySQL can call this function before calling
10441  external_lock(). To be safe, update the thd of the current table
10442  handle. */
10443 
10444  update_thd(ha_thd());
10445 
10446  prebuilt->trx->op_info = "calculating upper bound for table rows";
10447 
10448  /* In case MySQL calls this in the middle of a SELECT query, release
10449  possible adaptive hash latch to avoid deadlocks of threads */
10450 
10452 
10453  index = dict_table_get_first_index(prebuilt->table);
10454 
10455  stat_n_leaf_pages = index->stat_n_leaf_pages;
10456 
10457  ut_a(stat_n_leaf_pages > 0);
10458 
10459  local_data_file_length =
10460  ((ulonglong) stat_n_leaf_pages) * UNIV_PAGE_SIZE;
10461 
10462  /* Calculate a minimum length for a clustered index record and from
10463  that an upper bound for the number of rows. Since we only calculate
10464  new statistics in row0mysql.cc when a table has grown by a threshold
10465  factor, we must add a safety factor 2 in front of the formula below. */
10466 
10467  estimate = 2 * local_data_file_length
10468  / dict_index_calc_min_rec_len(index);
10469 
10470  prebuilt->trx->op_info = "";
10471 
10472  DBUG_RETURN((ha_rows) estimate);
10473 }
10474 
10475 /*********************************************************************/
10480 UNIV_INTERN
10481 double
10482 ha_innobase::scan_time()
10483 /*====================*/
10484 {
10485  /* Since MySQL seems to favor table scans too much over index
10486  searches, we pretend that a sequential read takes the same time
10487  as a random disk read, that is, we do not divide the following
10488  by 10, which would be physically realistic. */
10489 
10490  /* The locking below is disabled for performance reasons. Without
10491  it we could end up returning uninitialized value to the caller,
10492  which in the worst case could make some query plan go bogus or
10493  issue a Valgrind warning. */
10494 #if 0
10495  /* avoid potential lock order violation with dict_table_stats_lock()
10496  below */
10497  update_thd(ha_thd());
10499 #endif
10500 
10501  ulint stat_clustered_index_size;
10502 
10503 #if 0
10504  dict_table_stats_lock(prebuilt->table, RW_S_LATCH);
10505 #endif
10506 
10507  ut_a(prebuilt->table->stat_initialized);
10508 
10509  stat_clustered_index_size = prebuilt->table->stat_clustered_index_size;
10510 
10511 #if 0
10512  dict_table_stats_unlock(prebuilt->table, RW_S_LATCH);
10513 #endif
10514 
10515  return((double) stat_clustered_index_size);
10516 }
10517 
10518 /******************************************************************/
10522 UNIV_INTERN
10523 double
10525 /*===================*/
10526  uint index,
10527  uint ranges,
10528  ha_rows rows)
10529 {
10530  ha_rows total_rows;
10531  double time_for_scan;
10532 
10533  if (index != table->s->primary_key) {
10534  /* Not clustered */
10535  return(handler::read_time(index, ranges, rows));
10536  }
10537 
10538  if (rows <= 2) {
10539 
10540  return((double) rows);
10541  }
10542 
10543  /* Assume that the read time is proportional to the scan time for all
10544  rows + at most one seek per range. */
10545 
10546  time_for_scan = scan_time();
10547 
10548  if ((total_rows = estimate_rows_upper_bound()) < rows) {
10549 
10550  return(time_for_scan);
10551  }
10552 
10553  return(ranges + (double) rows / (double) total_rows * time_for_scan);
10554 }
10555 
10556 /******************************************************************/
10558 UNIV_INTERN
10559 longlong
10561 /*=======================================*/
10562 {
10563  return(innobase_buffer_pool_size);
10564 }
10565 
10566 /*********************************************************************/
10575 static
10576 int
10577 innobase_get_mysql_key_number_for_index(
10578 /*====================================*/
10579  INNOBASE_SHARE* share,
10581  const TABLE* table,
10583  dict_table_t* ib_table,
10585  const dict_index_t* index)
10586 {
10587  const dict_index_t* ind;
10588  unsigned int i;
10589 
10590  ut_a(index);
10591 
10592  /* If index does not belong to the table object of share structure
10593  (ib_table comes from the share structure) search the index->table
10594  object instead */
10595  if (index->table != ib_table) {
10596  i = 0;
10597  ind = dict_table_get_first_index(index->table);
10598 
10599  while (index != ind) {
10600  ind = dict_table_get_next_index(ind);
10601  i++;
10602  }
10603 
10605  ut_a(i > 0);
10606  i--;
10607  }
10608 
10609  return(i);
10610  }
10611 
10612  /* If index translation table exists, we will first check
10613  the index through index translation table for a match. */
10614  if (share->idx_trans_tbl.index_mapping) {
10615  for (i = 0; i < share->idx_trans_tbl.index_count; i++) {
10616  if (share->idx_trans_tbl.index_mapping[i] == index) {
10617  return(i);
10618  }
10619  }
10620 
10621  /* Print an error message if we cannot find the index
10622  in the "index translation table". */
10623  if (*index->name != TEMP_INDEX_PREFIX) {
10624  sql_print_error("Cannot find index %s in InnoDB index "
10625  "translation table.", index->name);
10626  }
10627  }
10628 
10629  /* If we do not have an "index translation table", or not able
10630  to find the index in the translation table, we'll directly find
10631  matching index with information from mysql TABLE structure and
10632  InnoDB dict_index_t list */
10633  for (i = 0; i < table->s->keys; i++) {
10635  ib_table, table->key_info[i].name);
10636 
10637  if (index == ind) {
10638  return(i);
10639  }
10640  }
10641 
10642  /* Loop through each index of the table and lock them */
10643  for (ind = dict_table_get_first_index(ib_table);
10644  ind != NULL;
10645  ind = dict_table_get_next_index(ind)) {
10646  if (index == ind) {
10647  /* Temp index is internal to InnoDB, that is
10648  not present in the MySQL index list, so no
10649  need to print such mismatch warning. */
10650  if (*(index->name) != TEMP_INDEX_PREFIX) {
10651  sql_print_warning(
10652  "Find index %s in InnoDB index list "
10653  "but not its MySQL index number "
10654  "It could be an InnoDB internal index.",
10655  index->name);
10656  }
10657  return(-1);
10658  }
10659  }
10660 
10661  ut_error;
10662 
10663  return(-1);
10664 }
10665 
10666 /*********************************************************************/
10670 static
10671 ha_rows
10672 innodb_rec_per_key(
10673 /*===============*/
10674  dict_index_t* index,
10675  ulint i,
10677  ha_rows records)
10678 {
10679  ha_rows rec_per_key;
10680  ib_uint64_t n_diff;
10681 
10682  ut_a(index->table->stat_initialized);
10683 
10684  ut_ad(i < dict_index_get_n_unique(index));
10685 
10686  n_diff = index->stat_n_diff_key_vals[i];
10687 
10688  if (n_diff == 0) {
10689 
10690  rec_per_key = records;
10691  } else if (srv_innodb_stats_method == SRV_STATS_NULLS_IGNORED) {
10692  ib_uint64_t n_null;
10693  ib_uint64_t n_non_null;
10694 
10695  n_non_null = index->stat_n_non_null_key_vals[i];
10696 
10697  /* In theory, index->stat_n_non_null_key_vals[i]
10698  should always be less than the number of records.
10699  Since this is statistics value, the value could
10700  have slight discrepancy. But we will make sure
10701  the number of null values is not a negative number. */
10702  if (records < n_non_null) {
10703  n_null = 0;
10704  } else {
10705  n_null = records - n_non_null;
10706  }
10707 
10708  /* If the number of NULL values is the same as or
10709  large than that of the distinct values, we could
10710  consider that the table consists mostly of NULL value.
10711  Set rec_per_key to 1. */
10712  if (n_diff <= n_null) {
10713  rec_per_key = 1;
10714  } else {
10715  /* Need to exclude rows with NULL values from
10716  rec_per_key calculation */
10717  rec_per_key = (ha_rows)
10718  ((records - n_null) / (n_diff - n_null));
10719  }
10720  } else {
10721  DEBUG_SYNC_C("after_checking_for_0");
10722  rec_per_key = (ha_rows) (records / n_diff);
10723  }
10724 
10725  return(rec_per_key);
10726 }
10727 
10728 /*********************************************************************/
10732 UNIV_INTERN
10733 int
10734 ha_innobase::info_low(
10735 /*==================*/
10736  uint flag,
10737  bool is_analyze)
10738 {
10739  dict_table_t* ib_table;
10740  ha_rows rec_per_key;
10741  ib_uint64_t n_rows;
10742  char path[FN_REFLEN];
10743  os_file_stat_t stat_info;
10744 
10745  DBUG_ENTER("info");
10746 
10747  /* If we are forcing recovery at a high level, we will suppress
10748  statistics calculation on tables, because that may crash the
10749  server if an index is badly corrupted. */
10750 
10751  /* We do not know if MySQL can call this function before calling
10752  external_lock(). To be safe, update the thd of the current table
10753  handle. */
10754 
10755  update_thd(ha_thd());
10756 
10757  /* In case MySQL calls this in the middle of a SELECT query, release
10758  possible adaptive hash latch to avoid deadlocks of threads */
10759 
10760  prebuilt->trx->op_info = (char*)"returning various info to MySQL";
10761 
10763 
10764  ib_table = prebuilt->table;
10765  DBUG_ASSERT(ib_table->n_ref_count > 0);
10766 
10767  if (flag & HA_STATUS_TIME) {
10768  if (is_analyze || innobase_stats_on_metadata) {
10769 
10770  dict_stats_upd_option_t opt;
10771  dberr_t ret;
10772 
10773  prebuilt->trx->op_info = "updating table statistics";
10774 
10775  if (dict_stats_is_persistent_enabled(ib_table)) {
10776 
10777  if (is_analyze) {
10778  opt = DICT_STATS_RECALC_PERSISTENT;
10779  } else {
10780  /* This is e.g. 'SHOW INDEXES', fetch
10781  the persistent stats from disk. */
10782  opt = DICT_STATS_FETCH_ONLY_IF_NOT_IN_MEMORY;
10783  }
10784  } else {
10785  opt = DICT_STATS_RECALC_TRANSIENT;
10786  }
10787 
10788  ut_ad(!mutex_own(&dict_sys->mutex));
10789  ret = dict_stats_update(ib_table, opt);
10790 
10791  if (ret != DB_SUCCESS) {
10792  prebuilt->trx->op_info = "";
10793  DBUG_RETURN(HA_ERR_GENERIC);
10794  }
10795 
10796  prebuilt->trx->op_info =
10797  "returning various info to MySQL";
10798  }
10799 
10800  my_snprintf(path, sizeof(path), "%s/%s%s",
10801  mysql_data_home, ib_table->name, reg_ext);
10802 
10803  unpack_filename(path,path);
10804 
10805  /* Note that we do not know the access time of the table,
10806  nor the CHECK TABLE time, nor the UPDATE or INSERT time. */
10807 
10808  if (os_file_get_status(path, &stat_info, false) == DB_SUCCESS) {
10809  stats.create_time = (ulong) stat_info.ctime;
10810  }
10811  }
10812 
10813  if (flag & HA_STATUS_VARIABLE) {
10814 
10815  ulint page_size;
10816  ulint stat_clustered_index_size;
10817  ulint stat_sum_of_other_index_sizes;
10818 
10819  if (!(flag & HA_STATUS_NO_LOCK)) {
10820  dict_table_stats_lock(ib_table, RW_S_LATCH);
10821  }
10822 
10823  ut_a(ib_table->stat_initialized);
10824 
10825  n_rows = ib_table->stat_n_rows;
10826 
10827  stat_clustered_index_size
10828  = ib_table->stat_clustered_index_size;
10829 
10830  stat_sum_of_other_index_sizes
10831  = ib_table->stat_sum_of_other_index_sizes;
10832 
10833  if (!(flag & HA_STATUS_NO_LOCK)) {
10834  dict_table_stats_unlock(ib_table, RW_S_LATCH);
10835  }
10836 
10837  /*
10838  The MySQL optimizer seems to assume in a left join that n_rows
10839  is an accurate estimate if it is zero. Of course, it is not,
10840  since we do not have any locks on the rows yet at this phase.
10841  Since SHOW TABLE STATUS seems to call this function with the
10842  HA_STATUS_TIME flag set, while the left join optimizer does not
10843  set that flag, we add one to a zero value if the flag is not
10844  set. That way SHOW TABLE STATUS will show the best estimate,
10845  while the optimizer never sees the table empty. */
10846 
10847  if (n_rows == 0 && !(flag & HA_STATUS_TIME)) {
10848  n_rows++;
10849  }
10850 
10851  /* Fix bug#40386: Not flushing query cache after truncate.
10852  n_rows can not be 0 unless the table is empty, set to 1
10853  instead. The original problem of bug#29507 is actually
10854  fixed in the server code. */
10855  if (thd_sql_command(user_thd) == SQLCOM_TRUNCATE) {
10856 
10857  n_rows = 1;
10858 
10859  /* We need to reset the prebuilt value too, otherwise
10860  checks for values greater than the last value written
10861  to the table will fail and the autoinc counter will
10862  not be updated. This will force write_row() into
10863  attempting an update of the table's AUTOINC counter. */
10864 
10865  prebuilt->autoinc_last_value = 0;
10866  }
10867 
10868  page_size = dict_table_zip_size(ib_table);
10869  if (page_size == 0) {
10870  page_size = UNIV_PAGE_SIZE;
10871  }
10872 
10873  stats.records = (ha_rows) n_rows;
10874  stats.deleted = 0;
10875  stats.data_file_length
10876  = ((ulonglong) stat_clustered_index_size)
10877  * page_size;
10878  stats.index_file_length
10879  = ((ulonglong) stat_sum_of_other_index_sizes)
10880  * page_size;
10881 
10882  /* Since fsp_get_available_space_in_free_extents() is
10883  acquiring latches inside InnoDB, we do not call it if we
10884  are asked by MySQL to avoid locking. Another reason to
10885  avoid the call is that it uses quite a lot of CPU.
10886  See Bug#38185. */
10887  if (flag & HA_STATUS_NO_LOCK
10888  || !(flag & HA_STATUS_VARIABLE_EXTRA)) {
10889  /* We do not update delete_length if no
10890  locking is requested so the "old" value can
10891  remain. delete_length is initialized to 0 in
10892  the ha_statistics' constructor. Also we only
10893  need delete_length to be set when
10894  HA_STATUS_VARIABLE_EXTRA is set */
10895  } else if (UNIV_UNLIKELY
10897  /* Avoid accessing the tablespace if
10898  innodb_crash_recovery is set to a high value. */
10899  stats.delete_length = 0;
10900  } else {
10901  ullint avail_space;
10902 
10904  ib_table->space);
10905 
10906  if (avail_space == ULLINT_UNDEFINED) {
10907  THD* thd;
10908  char errbuf[MYSYS_STRERROR_SIZE];
10909 
10910  thd = ha_thd();
10911 
10912  push_warning_printf(
10913  thd,
10914  Sql_condition::WARN_LEVEL_WARN,
10915  ER_CANT_GET_STAT,
10916  "InnoDB: Trying to get the free "
10917  "space for table %s but its "
10918  "tablespace has been discarded or "
10919  "the .ibd file is missing. Setting "
10920  "the free space to zero. "
10921  "(errno: %d - %s)",
10922  ib_table->name, errno,
10923  my_strerror(errbuf, sizeof(errbuf),
10924  errno));
10925 
10926  stats.delete_length = 0;
10927  } else {
10928  stats.delete_length = avail_space * 1024;
10929  }
10930  }
10931 
10932  stats.check_time = 0;
10933  stats.mrr_length_per_rec = ref_length + sizeof(void*);
10934 
10935  if (stats.records == 0) {
10936  stats.mean_rec_length = 0;
10937  } else {
10938  stats.mean_rec_length = (ulong)
10939  (stats.data_file_length / stats.records);
10940  }
10941  }
10942 
10943  if (flag & HA_STATUS_CONST) {
10944  ulong i;
10945  /* Verify the number of index in InnoDB and MySQL
10946  matches up. If prebuilt->clust_index_was_generated
10947  holds, InnoDB defines GEN_CLUST_INDEX internally */
10948  ulint num_innodb_index = UT_LIST_GET_LEN(ib_table->indexes)
10949  - prebuilt->clust_index_was_generated;
10950  if (table->s->keys < num_innodb_index) {
10951  /* If there are too many indexes defined
10952  inside InnoDB, ignore those that are being
10953  created, because MySQL will only consider
10954  the fully built indexes here. */
10955 
10956  for (const dict_index_t* index
10957  = UT_LIST_GET_FIRST(ib_table->indexes);
10958  index != NULL;
10959  index = UT_LIST_GET_NEXT(indexes, index)) {
10960 
10961  /* First, online index creation is
10962  completed inside InnoDB, and then
10963  MySQL attempts to upgrade the
10964  meta-data lock so that it can rebuild
10965  the .frm file. If we get here in that
10966  time frame, dict_index_is_online_ddl()
10967  would not hold and the index would
10968  still not be included in TABLE_SHARE. */
10969  if (*index->name == TEMP_INDEX_PREFIX) {
10970  num_innodb_index--;
10971  }
10972  }
10973 
10974  if (table->s->keys < num_innodb_index
10975  && innobase_fts_check_doc_id_index(
10976  ib_table, NULL, NULL)
10977  == FTS_EXIST_DOC_ID_INDEX) {
10978  num_innodb_index--;
10979  }
10980  }
10981 
10982  if (table->s->keys != num_innodb_index) {
10983  sql_print_error("InnoDB: Table %s contains %lu "
10984  "indexes inside InnoDB, which "
10985  "is different from the number of "
10986  "indexes %u defined in the MySQL ",
10987  ib_table->name, num_innodb_index,
10988  table->s->keys);
10989  }
10990 
10991  if (!(flag & HA_STATUS_NO_LOCK)) {
10992  dict_table_stats_lock(ib_table, RW_S_LATCH);
10993  }
10994 
10995  ut_a(ib_table->stat_initialized);
10996 
10997  for (i = 0; i < table->s->keys; i++) {
10998  ulong j;
10999  /* We could get index quickly through internal
11000  index mapping with the index translation table.
11001  The identity of index (match up index name with
11002  that of table->key_info[i]) is already verified in
11003  innobase_get_index(). */
11004  dict_index_t* index = innobase_get_index(i);
11005 
11006  if (index == NULL) {
11007  sql_print_error("Table %s contains fewer "
11008  "indexes inside InnoDB than "
11009  "are defined in the MySQL "
11010  ".frm file. Have you mixed up "
11011  ".frm files from different "
11012  "installations? See "
11013  REFMAN
11014  "innodb-troubleshooting.html\n",
11015  ib_table->name);
11016  break;
11017  }
11018 
11019  for (j = 0; j < table->key_info[i].actual_key_parts; j++) {
11020 
11021  if (table->key_info[i].flags & HA_FULLTEXT) {
11022  /* The whole concept has no validity
11023  for FTS indexes. */
11024  table->key_info[i].rec_per_key[j] = 1;
11025  continue;
11026  }
11027 
11028  if (j + 1 > index->n_uniq) {
11029  sql_print_error(
11030  "Index %s of %s has %lu columns"
11031  " unique inside InnoDB, but "
11032  "MySQL is asking statistics for"
11033  " %lu columns. Have you mixed "
11034  "up .frm files from different "
11035  "installations? "
11036  "See " REFMAN
11037  "innodb-troubleshooting.html\n",
11038  index->name,
11039  ib_table->name,
11040  (unsigned long)
11041  index->n_uniq, j + 1);
11042  break;
11043  }
11044 
11045  rec_per_key = innodb_rec_per_key(
11046  index, j, stats.records);
11047 
11048  /* Since MySQL seems to favor table scans
11049  too much over index searches, we pretend
11050  index selectivity is 2 times better than
11051  our estimate: */
11052 
11053  rec_per_key = rec_per_key / 2;
11054 
11055  if (rec_per_key == 0) {
11056  rec_per_key = 1;
11057  }
11058 
11059  table->key_info[i].rec_per_key[j] =
11060  rec_per_key >= ~(ulong) 0 ? ~(ulong) 0 :
11061  (ulong) rec_per_key;
11062  }
11063  }
11064 
11065  if (!(flag & HA_STATUS_NO_LOCK)) {
11066  dict_table_stats_unlock(ib_table, RW_S_LATCH);
11067  }
11068  }
11069 
11071 
11072  goto func_exit;
11073  }
11074 
11075  if (flag & HA_STATUS_ERRKEY) {
11076  const dict_index_t* err_index;
11077 
11078  ut_a(prebuilt->trx);
11079  ut_a(prebuilt->trx->magic_n == TRX_MAGIC_N);
11080 
11081  err_index = trx_get_error_info(prebuilt->trx);
11082 
11083  if (err_index) {
11084  errkey = innobase_get_mysql_key_number_for_index(
11085  share, table, ib_table, err_index);
11086  } else {
11087  errkey = (unsigned int) (
11088  (prebuilt->trx->error_key_num
11089  == ULINT_UNDEFINED)
11090  ? ~0
11091  : prebuilt->trx->error_key_num);
11092  }
11093  }
11094 
11095  if ((flag & HA_STATUS_AUTO) && table->found_next_number_field) {
11096  stats.auto_increment_value = innobase_peek_autoinc();
11097  }
11098 
11099 func_exit:
11100  prebuilt->trx->op_info = (char*)"";
11101 
11102  DBUG_RETURN(0);
11103 }
11104 
11105 /*********************************************************************/
11109 UNIV_INTERN
11110 int
11111 ha_innobase::info(
11112 /*==============*/
11113  uint flag)
11114 {
11115  return(this->info_low(flag, false /* not ANALYZE */));
11116 }
11117 
11118 /**********************************************************************/
11122 UNIV_INTERN
11123 int
11124 ha_innobase::analyze(
11125 /*=================*/
11126  THD* thd,
11127  HA_CHECK_OPT* check_opt)
11128 {
11129  int ret;
11130 
11131  /* Simply call this->info_low() with all the flags
11132  and request recalculation of the statistics */
11133  ret = this->info_low(
11134  HA_STATUS_TIME | HA_STATUS_CONST | HA_STATUS_VARIABLE,
11135  true /* this is ANALYZE */);
11136 
11137  if (ret != 0) {
11138  return(HA_ADMIN_FAILED);
11139  }
11140 
11141  return(HA_ADMIN_OK);
11142 }
11143 
11144 /**********************************************************************/
11147 UNIV_INTERN
11148 int
11149 ha_innobase::optimize(
11150 /*==================*/
11151  THD* thd,
11152  HA_CHECK_OPT* check_opt)
11153 {
11154  /*FTS-FIXME: Since MySQL doesn't support engine-specific commands,
11155  we have to hijack some existing command in order to be able to test
11156  the new admin commands added in InnoDB's FTS support. For now, we
11157  use MySQL's OPTIMIZE command, normally mapped to ALTER TABLE in
11158  InnoDB (so it recreates the table anew), and map it to OPTIMIZE.
11159 
11160  This works OK otherwise, but MySQL locks the entire table during
11161  calls to OPTIMIZE, which is undesirable. */
11162 
11163  if (innodb_optimize_fulltext_only) {
11164  if (prebuilt->table->fts && prebuilt->table->fts->cache) {
11165  fts_sync_table(prebuilt->table);
11166  fts_optimize_table(prebuilt->table);
11167  }
11168  return(HA_ADMIN_OK);
11169  } else {
11170 
11171  return(HA_ADMIN_TRY_ALTER);
11172  }
11173 }
11174 
11175 /*******************************************************************/
11180 UNIV_INTERN
11181 int
11182 ha_innobase::check(
11183 /*===============*/
11184  THD* thd,
11185  HA_CHECK_OPT* check_opt)
11187 {
11189  ulint n_rows;
11190  ulint n_rows_in_table = ULINT_UNDEFINED;
11191  ibool is_ok = TRUE;
11192  ulint old_isolation_level;
11193  ibool table_corrupted;
11194 
11195  DBUG_ENTER("ha_innobase::check");
11196  DBUG_ASSERT(thd == ha_thd());
11197  ut_a(prebuilt->trx);
11198  ut_a(prebuilt->trx->magic_n == TRX_MAGIC_N);
11199  ut_a(prebuilt->trx == thd_to_trx(thd));
11200 
11201  if (prebuilt->mysql_template == NULL) {
11202  /* Build the template; we will use a dummy template
11203  in index scans done in checking */
11204 
11205  build_template(true);
11206  }
11207 
11208  if (dict_table_is_discarded(prebuilt->table)) {
11209 
11210  ib_senderrf(
11211  thd,
11212  IB_LOG_LEVEL_ERROR,
11213  ER_TABLESPACE_DISCARDED,
11214  table->s->table_name.str);
11215 
11216  DBUG_RETURN(HA_ADMIN_CORRUPT);
11217 
11218  } else if (prebuilt->table->ibd_file_missing) {
11219 
11220  ib_senderrf(
11221  thd, IB_LOG_LEVEL_ERROR,
11222  ER_TABLESPACE_MISSING,
11223  table->s->table_name.str);
11224 
11225  DBUG_RETURN(HA_ADMIN_CORRUPT);
11226  }
11227 
11228  prebuilt->trx->op_info = "checking table";
11229 
11230  old_isolation_level = prebuilt->trx->isolation_level;
11231 
11232  /* We must run the index record counts at an isolation level
11233  >= READ COMMITTED, because a dirty read can see a wrong number
11234  of records in some index; to play safe, we use always
11235  REPEATABLE READ here */
11236 
11237  prebuilt->trx->isolation_level = TRX_ISO_REPEATABLE_READ;
11238 
11239  /* Check whether the table is already marked as corrupted
11240  before running the check table */
11241  table_corrupted = prebuilt->table->corrupted;
11242 
11243  /* Reset table->corrupted bit so that check table can proceed to
11244  do additional check */
11245  prebuilt->table->corrupted = FALSE;
11246 
11247  /* Enlarge the fatal lock wait timeout during CHECK TABLE. */
11249  server_mutex,
11250  srv_fatal_semaphore_wait_threshold,
11251  SRV_SEMAPHORE_WAIT_EXTENSION);
11252 
11253  for (index = dict_table_get_first_index(prebuilt->table);
11254  index != NULL;
11255  index = dict_table_get_next_index(index)) {
11256  char index_name[MAX_FULL_NAME_LEN + 1];
11257 
11258  /* If this is an index being created or dropped, break */
11259  if (*index->name == TEMP_INDEX_PREFIX) {
11260  break;
11261  } else if (!btr_validate_index(index, prebuilt->trx)) {
11262  is_ok = FALSE;
11263 
11265  index_name, sizeof index_name,
11266  index->name, TRUE);
11267 
11268  push_warning_printf(thd, Sql_condition::WARN_LEVEL_WARN,
11269  ER_NOT_KEYFILE,
11270  "InnoDB: The B-tree of"
11271  " index %s is corrupted.",
11272  index_name);
11273  continue;
11274  }
11275 
11276  /* Instead of invoking change_active_index(), set up
11277  a dummy template for non-locking reads, disabling
11278  access to the clustered index. */
11279  prebuilt->index = index;
11280 
11282  prebuilt->trx, prebuilt->index);
11283 
11284  if (UNIV_UNLIKELY(!prebuilt->index_usable)) {
11286  index_name, sizeof index_name,
11287  prebuilt->index->name, TRUE);
11288 
11289  if (dict_index_is_corrupted(prebuilt->index)) {
11290  push_warning_printf(
11291  user_thd,
11292  Sql_condition::WARN_LEVEL_WARN,
11293  HA_ERR_INDEX_CORRUPT,
11294  "InnoDB: Index %s is marked as"
11295  " corrupted",
11296  index_name);
11297  is_ok = FALSE;
11298  } else {
11299  push_warning_printf(
11300  thd,
11301  Sql_condition::WARN_LEVEL_WARN,
11302  HA_ERR_TABLE_DEF_CHANGED,
11303  "InnoDB: Insufficient history for"
11304  " index %s",
11305  index_name);
11306  }
11307  continue;
11308  }
11309 
11310  prebuilt->sql_stat_start = TRUE;
11311  prebuilt->template_type = ROW_MYSQL_DUMMY_TEMPLATE;
11312  prebuilt->n_template = 0;
11313  prebuilt->need_to_access_clustered = FALSE;
11314 
11315  dtuple_set_n_fields(prebuilt->search_tuple, 0);
11316 
11317  prebuilt->select_lock_type = LOCK_NONE;
11318 
11319  if (!row_check_index_for_mysql(prebuilt, index, &n_rows)) {
11321  index_name, sizeof index_name,
11322  index->name, TRUE);
11323 
11324  push_warning_printf(
11325  thd, Sql_condition::WARN_LEVEL_WARN,
11326  ER_NOT_KEYFILE,
11327  "InnoDB: The B-tree of"
11328  " index %s is corrupted.",
11329  index_name);
11330  is_ok = FALSE;
11332  index, prebuilt->trx, "CHECK TABLE-check index");
11333  }
11334 
11335  if (thd_killed(user_thd)) {
11336  break;
11337  }
11338 
11339 #if 0
11340  fprintf(stderr, "%lu entries in index %s\n", n_rows,
11341  index->name);
11342 #endif
11343 
11344  if (index == dict_table_get_first_index(prebuilt->table)) {
11345  n_rows_in_table = n_rows;
11346  } else if (!(index->type & DICT_FTS)
11347  && (n_rows != n_rows_in_table)) {
11348  push_warning_printf(
11349  thd, Sql_condition::WARN_LEVEL_WARN,
11350  ER_NOT_KEYFILE,
11351  "InnoDB: Index '%-.200s' contains %lu"
11352  " entries, should be %lu.",
11353  index->name,
11354  (ulong) n_rows,
11355  (ulong) n_rows_in_table);
11356  is_ok = FALSE;
11358  index, prebuilt->trx,
11359  "CHECK TABLE; Wrong count");
11360  }
11361  }
11362 
11363  if (table_corrupted) {
11364  /* If some previous operation has marked the table as
11365  corrupted in memory, and has not propagated such to
11366  clustered index, we will do so here */
11367  index = dict_table_get_first_index(prebuilt->table);
11368 
11369  if (!dict_index_is_corrupted(index)) {
11371  index, prebuilt->trx, "CHECK TABLE");
11372  }
11373  prebuilt->table->corrupted = TRUE;
11374  }
11375 
11376  /* Restore the original isolation level */
11377  prebuilt->trx->isolation_level = old_isolation_level;
11378 
11379  /* We validate also the whole adaptive hash index for all tables
11380  at every CHECK TABLE */
11381 
11382  if (!btr_search_validate()) {
11383  push_warning(thd, Sql_condition::WARN_LEVEL_WARN,
11384  ER_NOT_KEYFILE,
11385  "InnoDB: The adaptive hash index is corrupted.");
11386  is_ok = FALSE;
11387  }
11388 
11389  /* Restore the fatal lock wait timeout after CHECK TABLE. */
11390  os_decrement_counter_by_amount(
11391  server_mutex,
11392  srv_fatal_semaphore_wait_threshold,
11393  SRV_SEMAPHORE_WAIT_EXTENSION);
11394 
11395  prebuilt->trx->op_info = "";
11396  if (thd_killed(user_thd)) {
11397  my_error(ER_QUERY_INTERRUPTED, MYF(0));
11398  }
11399 
11400  DBUG_RETURN(is_ok ? HA_ADMIN_OK : HA_ADMIN_CORRUPT);
11401 }
11402 
11403 /*************************************************************/
11408 UNIV_INTERN
11409 char*
11410 ha_innobase::update_table_comment(
11411 /*==============================*/
11412  const char* comment)
11413 {
11414  uint length = (uint) strlen(comment);
11415  char* str;
11416  long flen;
11417 
11418  /* We do not know if MySQL can call this function before calling
11419  external_lock(). To be safe, update the thd of the current table
11420  handle. */
11421 
11422  if (length > 64000 - 3) {
11423  return((char*) comment); /* string too long */
11424  }
11425 
11426  update_thd(ha_thd());
11427 
11428  prebuilt->trx->op_info = (char*)"returning table comment";
11429 
11430  /* In case MySQL calls this in the middle of a SELECT query, release
11431  possible adaptive hash latch to avoid deadlocks of threads */
11432 
11434  str = NULL;
11435 
11436  /* output the data to a temporary file */
11437 
11438  if (!srv_read_only_mode) {
11439 
11440  mutex_enter(&srv_dict_tmpfile_mutex);
11441 
11442  rewind(srv_dict_tmpfile);
11443 
11444  fprintf(srv_dict_tmpfile, "InnoDB free: %llu kB",
11446  prebuilt->table->space));
11447 
11449  FALSE, srv_dict_tmpfile, prebuilt->trx,
11450  prebuilt->table);
11451 
11452  flen = ftell(srv_dict_tmpfile);
11453 
11454  if (flen < 0) {
11455  flen = 0;
11456  } else if (length + flen + 3 > 64000) {
11457  flen = 64000 - 3 - length;
11458  }
11459 
11460  /* allocate buffer for the full string, and
11461  read the contents of the temporary file */
11462 
11463  str = (char*) my_malloc(length + flen + 3, MYF(0));
11464 
11465  if (str) {
11466  char* pos = str + length;
11467  if (length) {
11468  memcpy(str, comment, length);
11469  *pos++ = ';';
11470  *pos++ = ' ';
11471  }
11472  rewind(srv_dict_tmpfile);
11473  flen = (uint) fread(pos, 1, flen, srv_dict_tmpfile);
11474  pos[flen] = 0;
11475  }
11476 
11477  mutex_exit(&srv_dict_tmpfile_mutex);
11478  }
11479 
11480  prebuilt->trx->op_info = (char*)"";
11481 
11482  return(str ? str : (char*) comment);
11483 }
11484 
11485 /*******************************************************************/
11490 UNIV_INTERN
11491 char*
11492 ha_innobase::get_foreign_key_create_info(void)
11493 /*==========================================*/
11494 {
11495  long flen;
11496  char* str = 0;
11497 
11498  ut_a(prebuilt != NULL);
11499 
11500  /* We do not know if MySQL can call this function before calling
11501  external_lock(). To be safe, update the thd of the current table
11502  handle. */
11503 
11504  update_thd(ha_thd());
11505 
11506  prebuilt->trx->op_info = (char*)"getting info on foreign keys";
11507 
11508  /* In case MySQL calls this in the middle of a SELECT query,
11509  release possible adaptive hash latch to avoid
11510  deadlocks of threads */
11511 
11513 
11514  if (!srv_read_only_mode) {
11515  mutex_enter(&srv_dict_tmpfile_mutex);
11516  rewind(srv_dict_tmpfile);
11517 
11518  /* Output the data to a temporary file */
11520  TRUE, srv_dict_tmpfile, prebuilt->trx,
11521  prebuilt->table);
11522 
11523  prebuilt->trx->op_info = (char*)"";
11524 
11525  flen = ftell(srv_dict_tmpfile);
11526 
11527  if (flen < 0) {
11528  flen = 0;
11529  }
11530 
11531  /* Allocate buffer for the string, and
11532  read the contents of the temporary file */
11533 
11534  str = (char*) my_malloc(flen + 1, MYF(0));
11535 
11536  if (str) {
11537  rewind(srv_dict_tmpfile);
11538  flen = (uint) fread(str, 1, flen, srv_dict_tmpfile);
11539  str[flen] = 0;
11540  }
11541 
11542  mutex_exit(&srv_dict_tmpfile_mutex);
11543  }
11544 
11545  return(str);
11546 }
11547 
11548 
11549 /***********************************************************************/
11552 static
11554 get_foreign_key_info(
11555 /*=================*/
11556  THD* thd,
11557  dict_foreign_t* foreign)
11558 {
11559  FOREIGN_KEY_INFO f_key_info;
11560  FOREIGN_KEY_INFO* pf_key_info;
11561  uint i = 0;
11562  ulint len;
11563  char tmp_buff[NAME_LEN+1];
11564  char name_buff[NAME_LEN+1];
11565  const char* ptr;
11566  LEX_STRING* referenced_key_name;
11567  LEX_STRING* name = NULL;
11568 
11569  ptr = dict_remove_db_name(foreign->id);
11570  f_key_info.foreign_id = thd_make_lex_string(thd, 0, ptr,
11571  (uint) strlen(ptr), 1);
11572 
11573  /* Name format: database name, '/', table name, '\0' */
11574 
11575  /* Referenced (parent) database name */
11577  ut_a(len < sizeof(tmp_buff));
11578  ut_memcpy(tmp_buff, foreign->referenced_table_name, len);
11579  tmp_buff[len] = 0;
11580 
11581  len = filename_to_tablename(tmp_buff, name_buff, sizeof(name_buff));
11582  f_key_info.referenced_db = thd_make_lex_string(thd, 0, name_buff, len, 1);
11583 
11584  /* Referenced (parent) table name */
11586  len = filename_to_tablename(ptr, name_buff, sizeof(name_buff));
11587  f_key_info.referenced_table = thd_make_lex_string(thd, 0, name_buff, len, 1);
11588 
11589  /* Dependent (child) database name */
11590  len = dict_get_db_name_len(foreign->foreign_table_name);
11591  ut_a(len < sizeof(tmp_buff));
11592  ut_memcpy(tmp_buff, foreign->foreign_table_name, len);
11593  tmp_buff[len] = 0;
11594 
11595  len = filename_to_tablename(tmp_buff, name_buff, sizeof(name_buff));
11596  f_key_info.foreign_db = thd_make_lex_string(thd, 0, name_buff, len, 1);
11597 
11598  /* Dependent (child) table name */
11599  ptr = dict_remove_db_name(foreign->foreign_table_name);
11600  len = filename_to_tablename(ptr, name_buff, sizeof(name_buff));
11601  f_key_info.foreign_table = thd_make_lex_string(thd, 0, name_buff, len, 1);
11602 
11603  do {
11604  ptr = foreign->foreign_col_names[i];
11605  name = thd_make_lex_string(thd, name, ptr,
11606  (uint) strlen(ptr), 1);
11607  f_key_info.foreign_fields.push_back(name);
11608  ptr = foreign->referenced_col_names[i];
11609  name = thd_make_lex_string(thd, name, ptr,
11610  (uint) strlen(ptr), 1);
11611  f_key_info.referenced_fields.push_back(name);
11612  } while (++i < foreign->n_fields);
11613 
11614  if (foreign->type & DICT_FOREIGN_ON_DELETE_CASCADE) {
11615  len = 7;
11616  ptr = "CASCADE";
11617  } else if (foreign->type & DICT_FOREIGN_ON_DELETE_SET_NULL) {
11618  len = 8;
11619  ptr = "SET NULL";
11620  } else if (foreign->type & DICT_FOREIGN_ON_DELETE_NO_ACTION) {
11621  len = 9;
11622  ptr = "NO ACTION";
11623  } else {
11624  len = 8;
11625  ptr = "RESTRICT";
11626  }
11627 
11628  f_key_info.delete_method = thd_make_lex_string(thd,
11629  f_key_info.delete_method,
11630  ptr, len, 1);
11631 
11632  if (foreign->type & DICT_FOREIGN_ON_UPDATE_CASCADE) {
11633  len = 7;
11634  ptr = "CASCADE";
11635  } else if (foreign->type & DICT_FOREIGN_ON_UPDATE_SET_NULL) {
11636  len = 8;
11637  ptr = "SET NULL";
11638  } else if (foreign->type & DICT_FOREIGN_ON_UPDATE_NO_ACTION) {
11639  len = 9;
11640  ptr = "NO ACTION";
11641  } else {
11642  len = 8;
11643  ptr = "RESTRICT";
11644  }
11645 
11646  f_key_info.update_method = thd_make_lex_string(thd,
11647  f_key_info.update_method,
11648  ptr, len, 1);
11649 
11650  if (foreign->referenced_index && foreign->referenced_index->name) {
11651  referenced_key_name = thd_make_lex_string(thd,
11652  f_key_info.referenced_key_name,
11653  foreign->referenced_index->name,
11654  (uint) strlen(foreign->referenced_index->name),
11655  1);
11656  } else {
11657  referenced_key_name = NULL;
11658  }
11659 
11660  f_key_info.referenced_key_name = referenced_key_name;
11661 
11662  pf_key_info = (FOREIGN_KEY_INFO*) thd_memdup(thd, &f_key_info,
11663  sizeof(FOREIGN_KEY_INFO));
11664 
11665  return(pf_key_info);
11666 }
11667 
11668 /*******************************************************************/
11671 UNIV_INTERN
11672 int
11674 /*==============================*/
11675  THD* thd,
11676  List<FOREIGN_KEY_INFO>* f_key_list)
11677 {
11678  FOREIGN_KEY_INFO* pf_key_info;
11679  dict_foreign_t* foreign;
11680 
11681  ut_a(prebuilt != NULL);
11682  update_thd(ha_thd());
11683 
11684  prebuilt->trx->op_info = "getting list of foreign keys";
11685 
11687 
11688  mutex_enter(&(dict_sys->mutex));
11689 
11690  for (foreign = UT_LIST_GET_FIRST(prebuilt->table->foreign_list);
11691  foreign != NULL;
11692  foreign = UT_LIST_GET_NEXT(foreign_list, foreign)) {
11693  pf_key_info = get_foreign_key_info(thd, foreign);
11694  if (pf_key_info) {
11695  f_key_list->push_back(pf_key_info);
11696  }
11697  }
11698 
11699  mutex_exit(&(dict_sys->mutex));
11700 
11701  prebuilt->trx->op_info = "";
11702 
11703  return(0);
11704 }
11705 
11706 /*******************************************************************/
11709 UNIV_INTERN
11710 int
11712 /*=====================================*/
11713  THD* thd,
11714  List<FOREIGN_KEY_INFO>* f_key_list)
11715 {
11716  FOREIGN_KEY_INFO* pf_key_info;
11717  dict_foreign_t* foreign;
11718 
11719  ut_a(prebuilt != NULL);
11720  update_thd(ha_thd());
11721 
11722  prebuilt->trx->op_info = "getting list of referencing foreign keys";
11723 
11725 
11726  mutex_enter(&(dict_sys->mutex));
11727 
11728  for (foreign = UT_LIST_GET_FIRST(prebuilt->table->referenced_list);
11729  foreign != NULL;
11730  foreign = UT_LIST_GET_NEXT(referenced_list, foreign)) {
11731  pf_key_info = get_foreign_key_info(thd, foreign);
11732  if (pf_key_info) {
11733  f_key_list->push_back(pf_key_info);
11734  }
11735  }
11736 
11737  mutex_exit(&(dict_sys->mutex));
11738 
11739  prebuilt->trx->op_info = "";
11740 
11741  return(0);
11742 }
11743 
11744 /*****************************************************************/
11749 UNIV_INTERN
11750 bool
11752 /*=================================*/
11753 {
11754  bool can_switch;
11755 
11756  DBUG_ENTER("ha_innobase::can_switch_engines");
11757  update_thd();
11758 
11759  prebuilt->trx->op_info =
11760  "determining if there are foreign key constraints";
11761  row_mysql_freeze_data_dictionary(prebuilt->trx);
11762 
11763  can_switch = !UT_LIST_GET_FIRST(prebuilt->table->referenced_list)
11764  && !UT_LIST_GET_FIRST(prebuilt->table->foreign_list);
11765 
11767  prebuilt->trx->op_info = "";
11768 
11769  DBUG_RETURN(can_switch);
11770 }
11771 
11772 /*******************************************************************/
11778 UNIV_INTERN
11779 uint
11780 ha_innobase::referenced_by_foreign_key(void)
11781 /*========================================*/
11782 {
11784 
11785  return(1);
11786  }
11787 
11788  return(0);
11789 }
11790 
11791 /*******************************************************************/
11794 UNIV_INTERN
11795 void
11796 ha_innobase::free_foreign_key_create_info(
11797 /*======================================*/
11798  char* str)
11799 {
11800  if (str) {
11801  my_free(str);
11802  }
11803 }
11804 
11805 /*******************************************************************/
11808 UNIV_INTERN
11809 int
11810 ha_innobase::extra(
11811 /*===============*/
11812  enum ha_extra_function operation)
11814 {
11815  check_trx_exists(ha_thd());
11816 
11817  /* Warning: since it is not sure that MySQL calls external_lock
11818  before calling this function, the trx field in prebuilt can be
11819  obsolete! */
11820 
11821  switch (operation) {
11822  case HA_EXTRA_FLUSH:
11823  if (prebuilt->blob_heap) {
11825  }
11826  break;
11827  case HA_EXTRA_RESET_STATE:
11828  reset_template();
11829  thd_to_trx(ha_thd())->duplicates = 0;
11830  break;
11831  case HA_EXTRA_NO_KEYREAD:
11832  prebuilt->read_just_key = 0;
11833  break;
11834  case HA_EXTRA_KEYREAD:
11835  prebuilt->read_just_key = 1;
11836  break;
11837  case HA_EXTRA_KEYREAD_PRESERVE_FIELDS:
11838  prebuilt->keep_other_fields_on_keyread = 1;
11839  break;
11840 
11841  /* IMPORTANT: prebuilt->trx can be obsolete in
11842  this method, because it is not sure that MySQL
11843  calls external_lock before this method with the
11844  parameters below. We must not invoke update_thd()
11845  either, because the calling threads may change.
11846  CAREFUL HERE, OR MEMORY CORRUPTION MAY OCCUR! */
11847  case HA_EXTRA_INSERT_WITH_UPDATE:
11848  thd_to_trx(ha_thd())->duplicates |= TRX_DUP_IGNORE;
11849  break;
11850  case HA_EXTRA_NO_IGNORE_DUP_KEY:
11851  thd_to_trx(ha_thd())->duplicates &= ~TRX_DUP_IGNORE;
11852  break;
11853  case HA_EXTRA_WRITE_CAN_REPLACE:
11854  thd_to_trx(ha_thd())->duplicates |= TRX_DUP_REPLACE;
11855  break;
11856  case HA_EXTRA_WRITE_CANNOT_REPLACE:
11857  thd_to_trx(ha_thd())->duplicates &= ~TRX_DUP_REPLACE;
11858  break;
11859  default:/* Do nothing */
11860  ;
11861  }
11862 
11863  return(0);
11864 }
11865 
11866 /******************************************************************/
11868 UNIV_INTERN
11869 int
11871 /*================*/
11872 {
11873  if (prebuilt->blob_heap) {
11875  }
11876 
11877  reset_template();
11878  ds_mrr.reset();
11879 
11880  /* TODO: This should really be reset in reset_template() but for now
11881  it's safer to do it explicitly here. */
11882 
11883  /* This is a statement level counter. */
11884  prebuilt->autoinc_last_value = 0;
11885 
11886  return(0);
11887 }
11888 
11889 /******************************************************************/
11901 UNIV_INTERN
11902 int
11903 ha_innobase::start_stmt(
11904 /*====================*/
11905  THD* thd,
11906  thr_lock_type lock_type)
11907 {
11908  trx_t* trx;
11909 
11910  update_thd(thd);
11911 
11912  trx = prebuilt->trx;
11913 
11914  /* Here we release the search latch and the InnoDB thread FIFO ticket
11915  if they were reserved. They should have been released already at the
11916  end of the previous statement, but because inside LOCK TABLES the
11917  lock count method does not work to mark the end of a SELECT statement,
11918  that may not be the case. We MUST release the search latch before an
11919  INSERT, for example. */
11920 
11922 
11923  innobase_srv_conc_force_exit_innodb(trx);
11924 
11925  /* Reset the AUTOINC statement level counter for multi-row INSERTs. */
11926  trx->n_autoinc_rows = 0;
11927 
11928  prebuilt->sql_stat_start = TRUE;
11929  prebuilt->hint_need_to_fetch_extra_cols = 0;
11930  reset_template();
11931 
11932  if (!prebuilt->mysql_has_locked) {
11933  /* This handle is for a temporary table created inside
11934  this same LOCK TABLES; since MySQL does NOT call external_lock
11935  in this case, we must use x-row locks inside InnoDB to be
11936  prepared for an update of a row */
11937 
11938  prebuilt->select_lock_type = LOCK_X;
11939 
11940  } else if (trx->isolation_level != TRX_ISO_SERIALIZABLE
11941  && thd_sql_command(thd) == SQLCOM_SELECT
11942  && lock_type == TL_READ) {
11943 
11944  /* For other than temporary tables, we obtain
11945  no lock for consistent read (plain SELECT). */
11946 
11947  prebuilt->select_lock_type = LOCK_NONE;
11948  } else {
11949  /* Not a consistent read: restore the
11950  select_lock_type value. The value of
11951  stored_select_lock_type was decided in:
11952  1) ::store_lock(),
11953  2) ::external_lock(),
11954  3) ::init_table_handle_for_HANDLER(), and
11955  4) ::transactional_table_lock(). */
11956 
11957  ut_a(prebuilt->stored_select_lock_type != LOCK_NONE_UNSET);
11958  prebuilt->select_lock_type = prebuilt->stored_select_lock_type;
11959  }
11960 
11961  *trx->detailed_error = 0;
11962 
11963  innobase_register_trx(ht, thd, trx);
11964 
11965  if (!trx_is_started(trx)) {
11966  ++trx->will_lock;
11967  }
11968 
11969  return(0);
11970 }
11971 
11972 /******************************************************************/
11975 static inline
11976 ulint
11977 innobase_map_isolation_level(
11978 /*=========================*/
11979  enum_tx_isolation iso)
11980 {
11981  switch (iso) {
11982  case ISO_REPEATABLE_READ: return(TRX_ISO_REPEATABLE_READ);
11983  case ISO_READ_COMMITTED: return(TRX_ISO_READ_COMMITTED);
11984  case ISO_SERIALIZABLE: return(TRX_ISO_SERIALIZABLE);
11985  case ISO_READ_UNCOMMITTED: return(TRX_ISO_READ_UNCOMMITTED);
11986  }
11987 
11988  ut_error;
11989 
11990  return(0);
11991 }
11992 
11993 /******************************************************************/
12002 UNIV_INTERN
12003 int
12004 ha_innobase::external_lock(
12005 /*=======================*/
12006  THD* thd,
12007  int lock_type)
12008 {
12009  trx_t* trx;
12010 
12011  DBUG_ENTER("ha_innobase::external_lock");
12012  DBUG_PRINT("enter",("lock_type: %d", lock_type));
12013 
12014  update_thd(thd);
12015 
12016  /* Statement based binlogging does not work in isolation level
12017  READ UNCOMMITTED and READ COMMITTED since the necessary
12018  locks cannot be taken. In this case, we print an
12019  informative error message and return with an error.
12020  Note: decide_logging_format would give the same error message,
12021  except it cannot give the extra details. */
12022 
12023  if (lock_type == F_WRLCK
12024  && !(table_flags() & HA_BINLOG_STMT_CAPABLE)
12025  && thd_binlog_format(thd) == BINLOG_FORMAT_STMT
12026  && thd_binlog_filter_ok(thd)
12027  && thd_sqlcom_can_generate_row_events(thd)) {
12028  bool skip = 0;
12029  /* used by test case */
12030  DBUG_EXECUTE_IF("no_innodb_binlog_errors", skip = true;);
12031  if (!skip) {
12032  my_error(ER_BINLOG_STMT_MODE_AND_ROW_ENGINE, MYF(0),
12033  " InnoDB is limited to row-logging when "
12034  "transaction isolation level is "
12035  "READ COMMITTED or READ UNCOMMITTED.");
12036  DBUG_RETURN(HA_ERR_LOGGING_IMPOSSIBLE);
12037  }
12038  }
12039 
12040  /* Check for UPDATEs in read-only mode. */
12041  if (srv_read_only_mode
12042  && (thd_sql_command(thd) == SQLCOM_UPDATE
12043  || thd_sql_command(thd) == SQLCOM_INSERT
12044  || thd_sql_command(thd) == SQLCOM_REPLACE
12045  || thd_sql_command(thd) == SQLCOM_DROP_TABLE
12046  || thd_sql_command(thd) == SQLCOM_ALTER_TABLE
12047  || thd_sql_command(thd) == SQLCOM_OPTIMIZE
12048  || (thd_sql_command(thd) == SQLCOM_CREATE_TABLE
12049  && lock_type == F_WRLCK)
12050  || thd_sql_command(thd) == SQLCOM_CREATE_INDEX
12051  || thd_sql_command(thd) == SQLCOM_DROP_INDEX
12052  || thd_sql_command(thd) == SQLCOM_DELETE)) {
12053 
12054  if (thd_sql_command(thd) == SQLCOM_CREATE_TABLE)
12055  {
12056  ib_senderrf(thd, IB_LOG_LEVEL_WARN,
12057  ER_INNODB_READ_ONLY);
12058  DBUG_RETURN(HA_ERR_INNODB_READ_ONLY);
12059  } else {
12060  ib_senderrf(thd, IB_LOG_LEVEL_WARN,
12061  ER_READ_ONLY_MODE);
12062  DBUG_RETURN(HA_ERR_TABLE_READONLY);
12063  }
12064 
12065  }
12066 
12067  trx = prebuilt->trx;
12068 
12069  prebuilt->sql_stat_start = TRUE;
12070  prebuilt->hint_need_to_fetch_extra_cols = 0;
12071 
12072  reset_template();
12073 
12074  switch (prebuilt->table->quiesce) {
12075  case QUIESCE_START:
12076  /* Check for FLUSH TABLE t WITH READ LOCK; */
12077  if (!srv_read_only_mode
12078  && thd_sql_command(thd) == SQLCOM_FLUSH
12079  && lock_type == F_RDLCK) {
12080 
12081  row_quiesce_table_start(prebuilt->table, trx);
12082 
12083  /* Use the transaction instance to track UNLOCK
12084  TABLES. It can be done via START TRANSACTION; too
12085  implicitly. */
12086 
12087  ++trx->flush_tables;
12088  }
12089  break;
12090 
12091  case QUIESCE_COMPLETE:
12092  /* Check for UNLOCK TABLES; implicit or explicit
12093  or trx interruption. */
12094  if (trx->flush_tables > 0
12095  && (lock_type == F_UNLCK || trx_is_interrupted(trx))) {
12096 
12097  row_quiesce_table_complete(prebuilt->table, trx);
12098 
12099  ut_a(trx->flush_tables > 0);
12100  --trx->flush_tables;
12101  }
12102 
12103  break;
12104 
12105  case QUIESCE_NONE:
12106  break;
12107  }
12108 
12109  if (lock_type == F_WRLCK) {
12110 
12111  /* If this is a SELECT, then it is in UPDATE TABLE ...
12112  or SELECT ... FOR UPDATE */
12113  prebuilt->select_lock_type = LOCK_X;
12114  prebuilt->stored_select_lock_type = LOCK_X;
12115  }
12116 
12117  if (lock_type != F_UNLCK) {
12118  /* MySQL is setting a new table lock */
12119 
12120  *trx->detailed_error = 0;
12121 
12122  innobase_register_trx(ht, thd, trx);
12123 
12124  if (trx->isolation_level == TRX_ISO_SERIALIZABLE
12125  && prebuilt->select_lock_type == LOCK_NONE
12126  && thd_test_options(
12127  thd, OPTION_NOT_AUTOCOMMIT | OPTION_BEGIN)) {
12128 
12129  /* To get serializable execution, we let InnoDB
12130  conceptually add 'LOCK IN SHARE MODE' to all SELECTs
12131  which otherwise would have been consistent reads. An
12132  exception is consistent reads in the AUTOCOMMIT=1 mode:
12133  we know that they are read-only transactions, and they
12134  can be serialized also if performed as consistent
12135  reads. */
12136 
12137  prebuilt->select_lock_type = LOCK_S;
12138  prebuilt->stored_select_lock_type = LOCK_S;
12139  }
12140 
12141  /* Starting from 4.1.9, no InnoDB table lock is taken in LOCK
12142  TABLES if AUTOCOMMIT=1. It does not make much sense to acquire
12143  an InnoDB table lock if it is released immediately at the end
12144  of LOCK TABLES, and InnoDB's table locks in that case cause
12145  VERY easily deadlocks.
12146 
12147  We do not set InnoDB table locks if user has not explicitly
12148  requested a table lock. Note that thd_in_lock_tables(thd)
12149  can hold in some cases, e.g., at the start of a stored
12150  procedure call (SQLCOM_CALL). */
12151 
12152  if (prebuilt->select_lock_type != LOCK_NONE) {
12153 
12154  if (thd_sql_command(thd) == SQLCOM_LOCK_TABLES
12155  && THDVAR(thd, table_locks)
12156  && thd_test_options(thd, OPTION_NOT_AUTOCOMMIT)
12157  && thd_in_lock_tables(thd)) {
12158 
12160  prebuilt, NULL, 0);
12161 
12162  if (error != DB_SUCCESS) {
12163  DBUG_RETURN(
12164  convert_error_code_to_mysql(
12165  error, 0, thd));
12166  }
12167  }
12168 
12169  trx->mysql_n_tables_locked++;
12170  }
12171 
12172  trx->n_mysql_tables_in_use++;
12173  prebuilt->mysql_has_locked = TRUE;
12174 
12175  if (!trx_is_started(trx)
12176  && (prebuilt->select_lock_type != LOCK_NONE
12177  || prebuilt->stored_select_lock_type != LOCK_NONE)) {
12178 
12179  ++trx->will_lock;
12180  }
12181 
12182  DBUG_RETURN(0);
12183  }
12184 
12185  /* MySQL is releasing a table lock */
12186 
12187  trx->n_mysql_tables_in_use--;
12188  prebuilt->mysql_has_locked = FALSE;
12189 
12190  /* Release a possible FIFO ticket and search latch. Since we
12191  may reserve the trx_sys->mutex, we have to release the search
12192  system latch first to obey the latching order. */
12193 
12195 
12196  innobase_srv_conc_force_exit_innodb(trx);
12197 
12198  /* If the MySQL lock count drops to zero we know that the current SQL
12199  statement has ended */
12200 
12201  if (trx->n_mysql_tables_in_use == 0) {
12202 
12203  trx->mysql_n_tables_locked = 0;
12204  prebuilt->used_in_HANDLER = FALSE;
12205 
12206  if (!thd_test_options(
12207  thd, OPTION_NOT_AUTOCOMMIT | OPTION_BEGIN)) {
12208 
12209  if (trx_is_started(trx)) {
12210  innobase_commit(ht, thd, TRUE);
12211  }
12212 
12213  } else if (trx->isolation_level <= TRX_ISO_READ_COMMITTED
12214  && trx->global_read_view) {
12215 
12216  /* At low transaction isolation levels we let
12217  each consistent read set its own snapshot */
12218 
12220  }
12221  }
12222 
12223  if (!trx_is_started(trx)
12224  && (prebuilt->select_lock_type != LOCK_NONE
12225  || prebuilt->stored_select_lock_type != LOCK_NONE)) {
12226 
12227  ++trx->will_lock;
12228  }
12229 
12230  DBUG_RETURN(0);
12231 }
12232 
12233 /******************************************************************/
12237 UNIV_INTERN
12238 int
12239 ha_innobase::transactional_table_lock(
12240 /*==================================*/
12241  THD* thd,
12242  int lock_type)
12243 {
12244  trx_t* trx;
12245 
12246  DBUG_ENTER("ha_innobase::transactional_table_lock");
12247  DBUG_PRINT("enter",("lock_type: %d", lock_type));
12248 
12249  /* We do not know if MySQL can call this function before calling
12250  external_lock(). To be safe, update the thd of the current table
12251  handle. */
12252 
12253  update_thd(thd);
12254 
12255  if (!thd_tablespace_op(thd)) {
12256 
12257  if (dict_table_is_discarded(prebuilt->table)) {
12258 
12259  ib_senderrf(
12260  thd, IB_LOG_LEVEL_ERROR,
12261  ER_TABLESPACE_DISCARDED,
12262  table->s->table_name.str);
12263 
12264  } else if (prebuilt->table->ibd_file_missing) {
12265 
12266  ib_senderrf(
12267  thd, IB_LOG_LEVEL_ERROR,
12268  ER_TABLESPACE_MISSING,
12269  table->s->table_name.str);
12270  }
12271 
12272  DBUG_RETURN(HA_ERR_CRASHED);
12273  }
12274 
12275  trx = prebuilt->trx;
12276 
12277  prebuilt->sql_stat_start = TRUE;
12278  prebuilt->hint_need_to_fetch_extra_cols = 0;
12279 
12280  reset_template();
12281 
12282  if (lock_type == F_WRLCK) {
12283  prebuilt->select_lock_type = LOCK_X;
12284  prebuilt->stored_select_lock_type = LOCK_X;
12285  } else if (lock_type == F_RDLCK) {
12286  prebuilt->select_lock_type = LOCK_S;
12287  prebuilt->stored_select_lock_type = LOCK_S;
12288  } else {
12289  ib_logf(IB_LOG_LEVEL_ERROR,
12290  "MySQL is trying to set transactional table lock "
12291  "with corrupted lock type to table %s, lock type "
12292  "%d does not exist.",
12293  table->s->table_name.str, lock_type);
12294 
12295  DBUG_RETURN(HA_ERR_CRASHED);
12296  }
12297 
12298  /* MySQL is setting a new transactional table lock */
12299 
12300  innobase_register_trx(ht, thd, trx);
12301 
12302  if (THDVAR(thd, table_locks) && thd_in_lock_tables(thd)) {
12303  dberr_t error;
12304 
12305  error = row_lock_table_for_mysql(prebuilt, NULL, 0);
12306 
12307  if (error != DB_SUCCESS) {
12308  DBUG_RETURN(
12309  convert_error_code_to_mysql(
12310  error, prebuilt->table->flags, thd));
12311  }
12312 
12313  if (thd_test_options(
12314  thd, OPTION_NOT_AUTOCOMMIT | OPTION_BEGIN)) {
12315 
12316  /* Store the current undo_no of the transaction
12317  so that we know where to roll back if we have
12318  to roll back the next SQL statement */
12319 
12320  trx_mark_sql_stat_end(trx);
12321  }
12322  }
12323 
12324  DBUG_RETURN(0);
12325 }
12326 
12327 /************************************************************************/
12329 static
12330 void
12331 innodb_export_status()
12332 /*==================*/
12333 {
12334  if (innodb_inited) {
12336  }
12337 }
12338 
12339 /************************************************************************/
12343 static
12344 int
12345 innodb_show_status(
12346 /*===============*/
12347  handlerton* hton,
12348  THD* thd,
12349  stat_print_fn* stat_print)
12350 {
12351  trx_t* trx;
12352  static const char truncated_msg[] = "... truncated...\n";
12353  const long MAX_STATUS_SIZE = 1048576;
12354  ulint trx_list_start = ULINT_UNDEFINED;
12355  ulint trx_list_end = ULINT_UNDEFINED;
12356 
12357  DBUG_ENTER("innodb_show_status");
12358  DBUG_ASSERT(hton == innodb_hton_ptr);
12359 
12360  /* We don't create the temp files or associated
12361  mutexes in read-only-mode */
12362 
12363  if (srv_read_only_mode) {
12364  DBUG_RETURN(0);
12365  }
12366 
12367  trx = check_trx_exists(thd);
12368 
12370 
12371  innobase_srv_conc_force_exit_innodb(trx);
12372 
12373  /* We let the InnoDB Monitor to output at most MAX_STATUS_SIZE
12374  bytes of text. */
12375 
12376  char* str;
12377  ssize_t flen, usable_len;
12378 
12379  mutex_enter(&srv_monitor_file_mutex);
12380  rewind(srv_monitor_file);
12381 
12383  &trx_list_start, &trx_list_end);
12384 
12386 
12387  if ((flen = ftell(srv_monitor_file)) < 0) {
12388  flen = 0;
12389  }
12390 
12391  if (flen > MAX_STATUS_SIZE) {
12392  usable_len = MAX_STATUS_SIZE;
12393  srv_truncated_status_writes++;
12394  } else {
12395  usable_len = flen;
12396  }
12397 
12398  /* allocate buffer for the string, and
12399  read the contents of the temporary file */
12400 
12401  if (!(str = (char*) my_malloc(usable_len + 1, MYF(0)))) {
12402  mutex_exit(&srv_monitor_file_mutex);
12403  DBUG_RETURN(1);
12404  }
12405 
12406  rewind(srv_monitor_file);
12407 
12408  if (flen < MAX_STATUS_SIZE) {
12409  /* Display the entire output. */
12410  flen = fread(str, 1, flen, srv_monitor_file);
12411  } else if (trx_list_end < (ulint) flen
12412  && trx_list_start < trx_list_end
12413  && trx_list_start + (flen - trx_list_end)
12414  < MAX_STATUS_SIZE - sizeof truncated_msg - 1) {
12415 
12416  /* Omit the beginning of the list of active transactions. */
12417  ssize_t len = fread(str, 1, trx_list_start, srv_monitor_file);
12418 
12419  memcpy(str + len, truncated_msg, sizeof truncated_msg - 1);
12420  len += sizeof truncated_msg - 1;
12421  usable_len = (MAX_STATUS_SIZE - 1) - len;
12422  fseek(srv_monitor_file, flen - usable_len, SEEK_SET);
12423  len += fread(str + len, 1, usable_len, srv_monitor_file);
12424  flen = len;
12425  } else {
12426  /* Omit the end of the output. */
12427  flen = fread(str, 1, MAX_STATUS_SIZE - 1, srv_monitor_file);
12428  }
12429 
12430  mutex_exit(&srv_monitor_file_mutex);
12431 
12432  stat_print(thd, innobase_hton_name, (uint) strlen(innobase_hton_name),
12433  STRING_WITH_LEN(""), str, flen);
12434 
12435  my_free(str);
12436 
12437  DBUG_RETURN(0);
12438 }
12439 
12440 /************************************************************************/
12443 static
12444 int
12445 innodb_mutex_show_status(
12446 /*=====================*/
12447  handlerton* hton,
12448  THD* thd,
12450  stat_print_fn* stat_print)
12452 {
12453  char buf1[IO_SIZE];
12454  char buf2[IO_SIZE];
12455  ib_mutex_t* mutex;
12456  rw_lock_t* lock;
12457  ulint block_mutex_oswait_count = 0;
12458  ulint block_lock_oswait_count = 0;
12459  ib_mutex_t* block_mutex = NULL;
12460  rw_lock_t* block_lock = NULL;
12461 #ifdef UNIV_DEBUG
12462  ulint rw_lock_count= 0;
12463  ulint rw_lock_count_spin_loop= 0;
12464  ulint rw_lock_count_spin_rounds= 0;
12465  ulint rw_lock_count_os_wait= 0;
12466  ulint rw_lock_count_os_yield= 0;
12467  ulonglong rw_lock_wait_time= 0;
12468 #endif /* UNIV_DEBUG */
12469  uint buf1len;
12470  uint buf2len;
12471  uint hton_name_len;
12472 
12473  hton_name_len = (uint) strlen(innobase_hton_name);
12474 
12475  DBUG_ENTER("innodb_mutex_show_status");
12476  DBUG_ASSERT(hton == innodb_hton_ptr);
12477 
12478  mutex_enter(&mutex_list_mutex);
12479 
12480  for (mutex = UT_LIST_GET_FIRST(mutex_list); mutex != NULL;
12481  mutex = UT_LIST_GET_NEXT(list, mutex)) {
12482  if (mutex->count_os_wait == 0) {
12483  continue;
12484  }
12485 
12486  if (buf_pool_is_block_mutex(mutex)) {
12487  block_mutex = mutex;
12488  block_mutex_oswait_count += mutex->count_os_wait;
12489  continue;
12490  }
12491 
12492  buf1len= (uint) my_snprintf(buf1, sizeof(buf1), "%s:%lu",
12493  innobase_basename(mutex->cfile_name),
12494  (ulong) mutex->cline);
12495  buf2len= (uint) my_snprintf(buf2, sizeof(buf2), "os_waits=%lu",
12496  (ulong) mutex->count_os_wait);
12497 
12498  if (stat_print(thd, innobase_hton_name,
12499  hton_name_len, buf1, buf1len,
12500  buf2, buf2len)) {
12501  mutex_exit(&mutex_list_mutex);
12502  DBUG_RETURN(1);
12503  }
12504  }
12505 
12506  if (block_mutex) {
12507  buf1len = (uint) my_snprintf(buf1, sizeof buf1,
12508  "combined %s:%lu",
12510  block_mutex->cfile_name),
12511  (ulong) block_mutex->cline);
12512  buf2len = (uint) my_snprintf(buf2, sizeof buf2,
12513  "os_waits=%lu",
12514  (ulong) block_mutex_oswait_count);
12515 
12516  if (stat_print(thd, innobase_hton_name,
12517  hton_name_len, buf1, buf1len,
12518  buf2, buf2len)) {
12519  mutex_exit(&mutex_list_mutex);
12520  DBUG_RETURN(1);
12521  }
12522  }
12523 
12524  mutex_exit(&mutex_list_mutex);
12525 
12526  mutex_enter(&rw_lock_list_mutex);
12527 
12528  for (lock = UT_LIST_GET_FIRST(rw_lock_list); lock != NULL;
12529  lock = UT_LIST_GET_NEXT(list, lock)) {
12530  if (lock->count_os_wait == 0) {
12531  continue;
12532  }
12533 
12534  if (buf_pool_is_block_lock(lock)) {
12535  block_lock = lock;
12536  block_lock_oswait_count += lock->count_os_wait;
12537  continue;
12538  }
12539 
12540  buf1len = my_snprintf(buf1, sizeof buf1, "%s:%lu",
12542  (ulong) lock->cline);
12543  buf2len = my_snprintf(buf2, sizeof buf2, "os_waits=%lu",
12544  (ulong) lock->count_os_wait);
12545 
12546  if (stat_print(thd, innobase_hton_name,
12547  hton_name_len, buf1, buf1len,
12548  buf2, buf2len)) {
12549  mutex_exit(&rw_lock_list_mutex);
12550  DBUG_RETURN(1);
12551  }
12552  }
12553 
12554  if (block_lock) {
12555  buf1len = (uint) my_snprintf(buf1, sizeof buf1,
12556  "combined %s:%lu",
12558  block_lock->cfile_name),
12559  (ulong) block_lock->cline);
12560  buf2len = (uint) my_snprintf(buf2, sizeof buf2,
12561  "os_waits=%lu",
12562  (ulong) block_lock_oswait_count);
12563 
12564  if (stat_print(thd, innobase_hton_name,
12565  hton_name_len, buf1, buf1len,
12566  buf2, buf2len)) {
12567  mutex_exit(&rw_lock_list_mutex);
12568  DBUG_RETURN(1);
12569  }
12570  }
12571 
12572  mutex_exit(&rw_lock_list_mutex);
12573 
12574 #ifdef UNIV_DEBUG
12575  buf2len = my_snprintf(buf2, sizeof buf2,
12576  "count=%lu, spin_waits=%lu, spin_rounds=%lu, "
12577  "os_waits=%lu, os_yields=%lu, os_wait_times=%lu",
12578  (ulong) rw_lock_count,
12579  (ulong) rw_lock_count_spin_loop,
12580  (ulong) rw_lock_count_spin_rounds,
12581  (ulong) rw_lock_count_os_wait,
12582  (ulong) rw_lock_count_os_yield,
12583  (ulong) (rw_lock_wait_time / 1000));
12584 
12585  if (stat_print(thd, innobase_hton_name, hton_name_len,
12586  STRING_WITH_LEN("rw_lock_mutexes"), buf2, buf2len)) {
12587  DBUG_RETURN(1);
12588  }
12589 #endif /* UNIV_DEBUG */
12590 
12591  /* Success */
12592  DBUG_RETURN(0);
12593 }
12594 
12595 /************************************************************************/
12598 static
12599 bool
12600 innobase_show_status(
12601 /*=================*/
12602  handlerton* hton,
12603  THD* thd,
12605  stat_print_fn* stat_print,
12606  enum ha_stat_type stat_type)
12607 {
12608  DBUG_ASSERT(hton == innodb_hton_ptr);
12609 
12610  switch (stat_type) {
12611  case HA_ENGINE_STATUS:
12612  /* Non-zero return value means there was an error. */
12613  return(innodb_show_status(hton, thd, stat_print) != 0);
12614 
12615  case HA_ENGINE_MUTEX:
12616  /* Non-zero return value means there was an error. */
12617  return(innodb_mutex_show_status(hton, thd, stat_print) != 0);
12618 
12619  case HA_ENGINE_LOGS:
12620  /* Not handled */
12621  break;
12622  }
12623 
12624  /* Success */
12625  return(false);
12626 }
12627 
12628 /************************************************************************/
12631 static
12633 get_share(
12634 /*======*/
12635  const char* table_name)
12636 {
12637  INNOBASE_SHARE* share;
12638 
12639  mysql_mutex_lock(&innobase_share_mutex);
12640 
12641  ulint fold = ut_fold_string(table_name);
12642 
12643  HASH_SEARCH(table_name_hash, innobase_open_tables, fold,
12644  INNOBASE_SHARE*, share,
12645  ut_ad(share->use_count > 0),
12646  !strcmp(share->table_name, table_name));
12647 
12648  if (!share) {
12649 
12650  uint length = (uint) strlen(table_name);
12651 
12652  /* TODO: invoke HASH_MIGRATE if innobase_open_tables
12653  grows too big */
12654 
12655  share = (INNOBASE_SHARE*) my_malloc(sizeof(*share)+length+1,
12656  MYF(MY_FAE | MY_ZEROFILL));
12657 
12658  share->table_name = (char*) memcpy(share + 1,
12659  table_name, length + 1);
12660 
12661  HASH_INSERT(INNOBASE_SHARE, table_name_hash,
12662  innobase_open_tables, fold, share);
12663 
12664  thr_lock_init(&share->lock);
12665 
12666  /* Index translation table initialization */
12667  share->idx_trans_tbl.index_mapping = NULL;
12668  share->idx_trans_tbl.index_count = 0;
12669  share->idx_trans_tbl.array_size = 0;
12670  }
12671 
12672  share->use_count++;
12673  mysql_mutex_unlock(&innobase_share_mutex);
12674 
12675  return(share);
12676 }
12677 
12678 /************************************************************************/
12680 static
12681 void
12682 free_share(
12683 /*=======*/
12684  INNOBASE_SHARE* share)
12685 {
12686  mysql_mutex_lock(&innobase_share_mutex);
12687 
12688 #ifdef UNIV_DEBUG
12689  INNOBASE_SHARE* share2;
12690  ulint fold = ut_fold_string(share->table_name);
12691 
12692  HASH_SEARCH(table_name_hash, innobase_open_tables, fold,
12693  INNOBASE_SHARE*, share2,
12694  ut_ad(share->use_count > 0),
12695  !strcmp(share->table_name, share2->table_name));
12696 
12697  ut_a(share2 == share);
12698 #endif /* UNIV_DEBUG */
12699 
12700  if (!--share->use_count) {
12701  ulint fold = ut_fold_string(share->table_name);
12702 
12703  HASH_DELETE(INNOBASE_SHARE, table_name_hash,
12704  innobase_open_tables, fold, share);
12705  thr_lock_delete(&share->lock);
12706 
12707  /* Free any memory from index translation table */
12708  my_free(share->idx_trans_tbl.index_mapping);
12709 
12710  my_free(share);
12711 
12712  /* TODO: invoke HASH_MIGRATE if innobase_open_tables
12713  shrinks too much */
12714  }
12715 
12716  mysql_mutex_unlock(&innobase_share_mutex);
12717 }
12718 
12719 /*****************************************************************/
12728 UNIV_INTERN
12729 THR_LOCK_DATA**
12731 /*====================*/
12732  THD* thd,
12733  THR_LOCK_DATA** to,
12738  enum thr_lock_type lock_type)
12741 {
12742  trx_t* trx;
12743 
12744  /* Note that trx in this function is NOT necessarily prebuilt->trx
12745  because we call update_thd() later, in ::external_lock()! Failure to
12746  understand this caused a serious memory corruption bug in 5.1.11. */
12747 
12748  trx = check_trx_exists(thd);
12749 
12750  /* NOTE: MySQL can call this function with lock 'type' TL_IGNORE!
12751  Be careful to ignore TL_IGNORE if we are going to do something with
12752  only 'real' locks! */
12753 
12754  /* If no MySQL table is in use, we need to set the isolation level
12755  of the transaction. */
12756 
12757  if (lock_type != TL_IGNORE
12758  && trx->n_mysql_tables_in_use == 0) {
12759  trx->isolation_level = innobase_map_isolation_level(
12760  (enum_tx_isolation) thd_tx_isolation(thd));
12761 
12762  if (trx->isolation_level <= TRX_ISO_READ_COMMITTED
12763  && trx->global_read_view) {
12764 
12765  /* At low transaction isolation levels we let
12766  each consistent read set its own snapshot */
12767 
12769  }
12770  }
12771 
12772  DBUG_ASSERT(EQ_CURRENT_THD(thd));
12773  const bool in_lock_tables = thd_in_lock_tables(thd);
12774  const uint sql_command = thd_sql_command(thd);
12775 
12776  if (srv_read_only_mode
12777  && (sql_command == SQLCOM_UPDATE
12778  || sql_command == SQLCOM_INSERT
12779  || sql_command == SQLCOM_REPLACE
12780  || sql_command == SQLCOM_DROP_TABLE
12781  || sql_command == SQLCOM_ALTER_TABLE
12782  || sql_command == SQLCOM_OPTIMIZE
12783  || (sql_command == SQLCOM_CREATE_TABLE
12784  && (lock_type >= TL_WRITE_CONCURRENT_INSERT
12785  && lock_type <= TL_WRITE))
12786  || sql_command == SQLCOM_CREATE_INDEX
12787  || sql_command == SQLCOM_DROP_INDEX
12788  || sql_command == SQLCOM_DELETE)) {
12789 
12790  ib_senderrf(trx->mysql_thd,
12791  IB_LOG_LEVEL_WARN, ER_READ_ONLY_MODE);
12792 
12793  } else if (sql_command == SQLCOM_FLUSH
12794  && lock_type == TL_READ_NO_INSERT) {
12795 
12796  /* Check for FLUSH TABLES ... WITH READ LOCK */
12797 
12798  /* Note: This call can fail, but there is no way to return
12799  the error to the caller. We simply ignore it for now here
12800  and push the error code to the caller where the error is
12801  detected in the function. */
12802 
12804  prebuilt->table, QUIESCE_START, trx);
12805 
12806  ut_a(err == DB_SUCCESS || err == DB_UNSUPPORTED);
12807 
12808  if (trx->isolation_level == TRX_ISO_SERIALIZABLE) {
12809  prebuilt->select_lock_type = LOCK_S;
12810  prebuilt->stored_select_lock_type = LOCK_S;
12811  } else {
12812  prebuilt->select_lock_type = LOCK_NONE;
12813  prebuilt->stored_select_lock_type = LOCK_NONE;
12814  }
12815 
12816  /* Check for DROP TABLE */
12817  } else if (sql_command == SQLCOM_DROP_TABLE) {
12818 
12819  /* MySQL calls this function in DROP TABLE though this table
12820  handle may belong to another thd that is running a query. Let
12821  us in that case skip any changes to the prebuilt struct. */
12822 
12823  /* Check for LOCK TABLE t1,...,tn WITH SHARED LOCKS */
12824  } else if ((lock_type == TL_READ && in_lock_tables)
12825  || (lock_type == TL_READ_HIGH_PRIORITY && in_lock_tables)
12826  || lock_type == TL_READ_WITH_SHARED_LOCKS
12827  || lock_type == TL_READ_NO_INSERT
12828  || (lock_type != TL_IGNORE
12829  && sql_command != SQLCOM_SELECT)) {
12830 
12831  /* The OR cases above are in this order:
12832  1) MySQL is doing LOCK TABLES ... READ LOCAL, or we
12833  are processing a stored procedure or function, or
12834  2) (we do not know when TL_READ_HIGH_PRIORITY is used), or
12835  3) this is a SELECT ... IN SHARE MODE, or
12836  4) we are doing a complex SQL statement like
12837  INSERT INTO ... SELECT ... and the logical logging (MySQL
12838  binlog) requires the use of a locking read, or
12839  MySQL is doing LOCK TABLES ... READ.
12840  5) we let InnoDB do locking reads for all SQL statements that
12841  are not simple SELECTs; note that select_lock_type in this
12842  case may get strengthened in ::external_lock() to LOCK_X.
12843  Note that we MUST use a locking read in all data modifying
12844  SQL statements, because otherwise the execution would not be
12845  serializable, and also the results from the update could be
12846  unexpected if an obsolete consistent read view would be
12847  used. */
12848 
12849  /* Use consistent read for checksum table */
12850 
12851  if (sql_command == SQLCOM_CHECKSUM
12853  || trx->isolation_level <= TRX_ISO_READ_COMMITTED)
12854  && trx->isolation_level != TRX_ISO_SERIALIZABLE
12855  && (lock_type == TL_READ
12856  || lock_type == TL_READ_NO_INSERT)
12857  && (sql_command == SQLCOM_INSERT_SELECT
12858  || sql_command == SQLCOM_REPLACE_SELECT
12859  || sql_command == SQLCOM_UPDATE
12860  || sql_command == SQLCOM_CREATE_TABLE))) {
12861 
12862  /* If we either have innobase_locks_unsafe_for_binlog
12863  option set or this session is using READ COMMITTED
12864  isolation level and isolation level of the transaction
12865  is not set to serializable and MySQL is doing
12866  INSERT INTO...SELECT or REPLACE INTO...SELECT
12867  or UPDATE ... = (SELECT ...) or CREATE ...
12868  SELECT... without FOR UPDATE or IN SHARE
12869  MODE in select, then we use consistent read
12870  for select. */
12871 
12872  prebuilt->select_lock_type = LOCK_NONE;
12873  prebuilt->stored_select_lock_type = LOCK_NONE;
12874  } else {
12875  prebuilt->select_lock_type = LOCK_S;
12876  prebuilt->stored_select_lock_type = LOCK_S;
12877  }
12878 
12879  } else if (lock_type != TL_IGNORE) {
12880 
12881  /* We set possible LOCK_X value in external_lock, not yet
12882  here even if this would be SELECT ... FOR UPDATE */
12883 
12884  prebuilt->select_lock_type = LOCK_NONE;
12885  prebuilt->stored_select_lock_type = LOCK_NONE;
12886  }
12887 
12888  if (lock_type != TL_IGNORE && lock.type == TL_UNLOCK) {
12889 
12890  /* Starting from 5.0.7, we weaken also the table locks
12891  set at the start of a MySQL stored procedure call, just like
12892  we weaken the locks set at the start of an SQL statement.
12893  MySQL does set in_lock_tables TRUE there, but in reality
12894  we do not need table locks to make the execution of a
12895  single transaction stored procedure call deterministic
12896  (if it does not use a consistent read). */
12897 
12898  if (lock_type == TL_READ
12899  && sql_command == SQLCOM_LOCK_TABLES) {
12900  /* We come here if MySQL is processing LOCK TABLES
12901  ... READ LOCAL. MyISAM under that table lock type
12902  reads the table as it was at the time the lock was
12903  granted (new inserts are allowed, but not seen by the
12904  reader). To get a similar effect on an InnoDB table,
12905  we must use LOCK TABLES ... READ. We convert the lock
12906  type here, so that for InnoDB, READ LOCAL is
12907  equivalent to READ. This will change the InnoDB
12908  behavior in mysqldump, so that dumps of InnoDB tables
12909  are consistent with dumps of MyISAM tables. */
12910 
12911  lock_type = TL_READ_NO_INSERT;
12912  }
12913 
12914  /* If we are not doing a LOCK TABLE, DISCARD/IMPORT
12915  TABLESPACE or TRUNCATE TABLE then allow multiple
12916  writers. Note that ALTER TABLE uses a TL_WRITE_ALLOW_READ
12917  < TL_WRITE_CONCURRENT_INSERT.
12918 
12919  We especially allow multiple writers if MySQL is at the
12920  start of a stored procedure call (SQLCOM_CALL) or a
12921  stored function call (MySQL does have in_lock_tables
12922  TRUE there). */
12923 
12924  if ((lock_type >= TL_WRITE_CONCURRENT_INSERT
12925  && lock_type <= TL_WRITE)
12926  && !(in_lock_tables
12927  && sql_command == SQLCOM_LOCK_TABLES)
12928  && !thd_tablespace_op(thd)
12929  && sql_command != SQLCOM_TRUNCATE
12930  && sql_command != SQLCOM_OPTIMIZE
12931  && sql_command != SQLCOM_CREATE_TABLE) {
12932 
12933  lock_type = TL_WRITE_ALLOW_WRITE;
12934  }
12935 
12936  /* In queries of type INSERT INTO t1 SELECT ... FROM t2 ...
12937  MySQL would use the lock TL_READ_NO_INSERT on t2, and that
12938  would conflict with TL_WRITE_ALLOW_WRITE, blocking all inserts
12939  to t2. Convert the lock to a normal read lock to allow
12940  concurrent inserts to t2.
12941 
12942  We especially allow concurrent inserts if MySQL is at the
12943  start of a stored procedure call (SQLCOM_CALL)
12944  (MySQL does have thd_in_lock_tables() TRUE there). */
12945 
12946  if (lock_type == TL_READ_NO_INSERT
12947  && sql_command != SQLCOM_LOCK_TABLES) {
12948 
12949  lock_type = TL_READ;
12950  }
12951 
12952  lock.type = lock_type;
12953  }
12954 
12955  *to++= &lock;
12956 
12957  if (!trx_is_started(trx)
12958  && (prebuilt->select_lock_type != LOCK_NONE
12959  || prebuilt->stored_select_lock_type != LOCK_NONE)) {
12960 
12961  ++trx->will_lock;
12962  }
12963 
12964  return(to);
12965 }
12966 
12967 /*********************************************************************/
12972 UNIV_INTERN
12973 dberr_t
12974 ha_innobase::innobase_get_autoinc(
12975 /*==============================*/
12976  ulonglong* value)
12977 {
12978  *value = 0;
12979 
12980  prebuilt->autoinc_error = innobase_lock_autoinc();
12981 
12982  if (prebuilt->autoinc_error == DB_SUCCESS) {
12983 
12984  /* Determine the first value of the interval */
12985  *value = dict_table_autoinc_read(prebuilt->table);
12986 
12987  /* It should have been initialized during open. */
12988  if (*value == 0) {
12989  prebuilt->autoinc_error = DB_UNSUPPORTED;
12990  dict_table_autoinc_unlock(prebuilt->table);
12991  }
12992  }
12993 
12994  return(prebuilt->autoinc_error);
12995 }
12996 
12997 /*******************************************************************/
13001 UNIV_INTERN
13002 ulonglong
13003 ha_innobase::innobase_peek_autoinc(void)
13004 /*====================================*/
13005 {
13006  ulonglong auto_inc;
13007  dict_table_t* innodb_table;
13008 
13009  ut_a(prebuilt != NULL);
13010  ut_a(prebuilt->table != NULL);
13011 
13012  innodb_table = prebuilt->table;
13013 
13014  dict_table_autoinc_lock(innodb_table);
13015 
13016  auto_inc = dict_table_autoinc_read(innodb_table);
13017 
13018  if (auto_inc == 0) {
13019  ut_print_timestamp(stderr);
13020  fprintf(stderr, " InnoDB: AUTOINC next value generation "
13021  "is disabled for '%s'\n", innodb_table->name);
13022  }
13023 
13024  dict_table_autoinc_unlock(innodb_table);
13025 
13026  return(auto_inc);
13027 }
13028 
13029 /*********************************************************************/
13031 UNIV_INTERN
13032 void
13034 /*============================*/
13035  ulonglong offset,
13036  ulonglong increment,
13038  ulonglong nb_desired_values,
13040  ulonglong* first_value,
13041  ulonglong* nb_reserved_values)
13043 {
13044  trx_t* trx;
13045  dberr_t error;
13046  ulonglong autoinc = 0;
13047 
13048  /* Prepare prebuilt->trx in the table handle */
13049  update_thd(ha_thd());
13050 
13051  error = innobase_get_autoinc(&autoinc);
13052 
13053  if (error != DB_SUCCESS) {
13054  *first_value = (~(ulonglong) 0);
13055  return;
13056  }
13057 
13058  /* This is a hack, since nb_desired_values seems to be accurate only
13059  for the first call to get_auto_increment() for multi-row INSERT and
13060  meaningless for other statements e.g, LOAD etc. Subsequent calls to
13061  this method for the same statement results in different values which
13062  don't make sense. Therefore we store the value the first time we are
13063  called and count down from that as rows are written (see write_row()).
13064  */
13065 
13066  trx = prebuilt->trx;
13067 
13068  /* Note: We can't rely on *first_value since some MySQL engines,
13069  in particular the partition engine, don't initialize it to 0 when
13070  invoking this method. So we are not sure if it's guaranteed to
13071  be 0 or not. */
13072 
13073  /* We need the upper limit of the col type to check for
13074  whether we update the table autoinc counter or not. */
13075  ulonglong col_max_value = innobase_get_int_col_max_value(
13076  table->next_number_field);
13077 
13078  /* Called for the first time ? */
13079  if (trx->n_autoinc_rows == 0) {
13080 
13081  trx->n_autoinc_rows = (ulint) nb_desired_values;
13082 
13083  /* It's possible for nb_desired_values to be 0:
13084  e.g., INSERT INTO T1(C) SELECT C FROM T2; */
13085  if (nb_desired_values == 0) {
13086 
13087  trx->n_autoinc_rows = 1;
13088  }
13089 
13090  set_if_bigger(*first_value, autoinc);
13091  /* Not in the middle of a mult-row INSERT. */
13092  } else if (prebuilt->autoinc_last_value == 0) {
13093  set_if_bigger(*first_value, autoinc);
13094  /* Check for -ve values. */
13095  } else if (*first_value > col_max_value && trx->n_autoinc_rows > 0) {
13096  /* Set to next logical value. */
13097  ut_a(autoinc > trx->n_autoinc_rows);
13098  *first_value = (autoinc - trx->n_autoinc_rows) - 1;
13099  }
13100 
13101  *nb_reserved_values = trx->n_autoinc_rows;
13102 
13103  /* With old style AUTOINC locking we only update the table's
13104  AUTOINC counter after attempting to insert the row. */
13105  if (innobase_autoinc_lock_mode != AUTOINC_OLD_STYLE_LOCKING) {
13106  ulonglong current;
13107  ulonglong next_value;
13108 
13109  current = *first_value > col_max_value ? autoinc : *first_value;
13110 
13111  /* Compute the last value in the interval */
13112  next_value = innobase_next_autoinc(
13113  current, *nb_reserved_values, increment, offset,
13114  col_max_value);
13115 
13116  prebuilt->autoinc_last_value = next_value;
13117 
13118  if (prebuilt->autoinc_last_value < *first_value) {
13119  *first_value = (~(ulonglong) 0);
13120  } else {
13121  /* Update the table autoinc variable */
13123  prebuilt->table, prebuilt->autoinc_last_value);
13124  }
13125  } else {
13126  /* This will force write_row() into attempting an update
13127  of the table's AUTOINC counter. */
13128  prebuilt->autoinc_last_value = 0;
13129  }
13130 
13131  /* The increment to be used to increase the AUTOINC value, we use
13132  this in write_row() and update_row() to increase the autoinc counter
13133  for columns that are filled by the user. We need the offset and
13134  the increment. */
13135  prebuilt->autoinc_offset = offset;
13136  prebuilt->autoinc_increment = increment;
13137 
13138  dict_table_autoinc_unlock(prebuilt->table);
13139 }
13140 
13141 /*******************************************************************/
13147 UNIV_INTERN
13148 int
13150 /*==============================*/
13151  ulonglong value)
13152 {
13153  DBUG_ENTER("ha_innobase::reset_auto_increment");
13154 
13155  dberr_t error;
13156 
13157  update_thd(ha_thd());
13158 
13159  error = row_lock_table_autoinc_for_mysql(prebuilt);
13160 
13161  if (error != DB_SUCCESS) {
13162  DBUG_RETURN(convert_error_code_to_mysql(
13163  error, prebuilt->table->flags, user_thd));
13164  }
13165 
13166  /* The next value can never be 0. */
13167  if (value == 0) {
13168  value = 1;
13169  }
13170 
13171  innobase_reset_autoinc(value);
13172 
13173  DBUG_RETURN(0);
13174 }
13175 
13176 /*******************************************************************/
13178 UNIV_INTERN
13179 bool
13181 /*===========================*/
13182  int error,
13183  String* buf)
13184 {
13185  trx_t* trx = check_trx_exists(ha_thd());
13186 
13187  buf->copy(trx->detailed_error, (uint) strlen(trx->detailed_error),
13188  system_charset_info);
13189 
13190  return(FALSE);
13191 }
13192 
13193 /*******************************************************************/
13211 bool
13213 /*=============================*/
13214  char* child_table_name,
13215  uint child_table_name_len,
13216  char* child_key_name,
13217  uint child_key_name_len)
13218 {
13219  const dict_index_t* err_index;
13220 
13221  ut_a(prebuilt->trx != NULL);
13222  ut_a(prebuilt->trx->magic_n == TRX_MAGIC_N);
13223 
13224  err_index = trx_get_error_info(prebuilt->trx);
13225 
13226  if (err_index == NULL) {
13227  return(false);
13228  }
13229  /* else */
13230 
13231  /* copy table name (and convert from filename-safe encoding to
13232  system_charset_info) */
13233  char* p;
13234  p = strchr(err_index->table->name, '/');
13235  /* strip ".../" prefix if any */
13236  if (p != NULL) {
13237  p++;
13238  } else {
13239  p = err_index->table->name;
13240  }
13241  uint len;
13242  len = filename_to_tablename(p, child_table_name, child_table_name_len);
13243  child_table_name[len] = '\0';
13244 
13245  /* copy index name */
13246  ut_snprintf(child_key_name, child_key_name_len, "%s", err_index->name);
13247 
13248  return(true);
13249 }
13250 
13251 /*******************************************************************/
13256 UNIV_INTERN
13257 int
13258 ha_innobase::cmp_ref(
13259 /*=================*/
13260  const uchar* ref1,
13262  const uchar* ref2)
13264 {
13265  enum_field_types mysql_type;
13266  Field* field;
13267  KEY_PART_INFO* key_part;
13268  KEY_PART_INFO* key_part_end;
13269  uint len1;
13270  uint len2;
13271  int result;
13272 
13273  if (prebuilt->clust_index_was_generated) {
13274  /* The 'ref' is an InnoDB row id */
13275 
13276  return(memcmp(ref1, ref2, DATA_ROW_ID_LEN));
13277  }
13278 
13279  /* Do a type-aware comparison of primary key fields. PK fields
13280  are always NOT NULL, so no checks for NULL are performed. */
13281 
13282  key_part = table->key_info[table->s->primary_key].key_part;
13283 
13284  key_part_end = key_part
13285  + table->key_info[table->s->primary_key].user_defined_key_parts;
13286 
13287  for (; key_part != key_part_end; ++key_part) {
13288  field = key_part->field;
13289  mysql_type = field->type();
13290 
13291  if (mysql_type == MYSQL_TYPE_TINY_BLOB
13292  || mysql_type == MYSQL_TYPE_MEDIUM_BLOB
13293  || mysql_type == MYSQL_TYPE_BLOB
13294  || mysql_type == MYSQL_TYPE_LONG_BLOB) {
13295 
13296  /* In the MySQL key value format, a column prefix of
13297  a BLOB is preceded by a 2-byte length field */
13298 
13299  len1 = innobase_read_from_2_little_endian(ref1);
13300  len2 = innobase_read_from_2_little_endian(ref2);
13301 
13302  ref1 += 2;
13303  ref2 += 2;
13304  result = ((Field_blob*) field)->cmp(
13305  ref1, len1, ref2, len2);
13306  } else {
13307  result = field->key_cmp(ref1, ref2);
13308  }
13309 
13310  if (result) {
13311 
13312  return(result);
13313  }
13314 
13315  ref1 += key_part->store_length;
13316  ref2 += key_part->store_length;
13317  }
13318 
13319  return(0);
13320 }
13321 
13322 /*******************************************************************/
13325 UNIV_INTERN
13326 my_bool
13328 /*====================================*/
13329  THD* thd,
13330  char* table_key,
13332  uint key_length,
13334  qc_engine_callback*
13335  call_back,
13338  ulonglong *engine_data)
13339 {
13340  *call_back = innobase_query_caching_of_table_permitted;
13341  *engine_data = 0;
13342  return(innobase_query_caching_of_table_permitted(thd, table_key,
13343  key_length,
13344  engine_data));
13345 }
13346 
13347 /*******************************************************************/
13349 UNIV_INTERN
13350 const char*
13351 ha_innobase::get_mysql_bin_log_name()
13352 /*=================================*/
13353 {
13355 }
13356 
13357 /*******************************************************************/
13359 UNIV_INTERN
13360 ulonglong
13361 ha_innobase::get_mysql_bin_log_pos()
13362 /*================================*/
13363 {
13364  /* trx... is ib_int64_t, which is a typedef for a 64-bit integer
13365  (__int64 or longlong) so it's ok to cast it to ulonglong. */
13366 
13367  return(trx_sys_mysql_bin_log_pos);
13368 }
13369 
13370 /******************************************************************/
13376 UNIV_INTERN
13377 ulint
13379 /*===========================*/
13380  ulint charset_id,
13381  ulint prefix_len,
13384  ulint data_len,
13385  const char* str)
13386 {
13387  ulint char_length;
13388  ulint n_chars;
13389  CHARSET_INFO* charset;
13391  charset = get_charset((uint) charset_id, MYF(MY_WME));
13392 
13393  ut_ad(charset);
13394  ut_ad(charset->mbmaxlen);
13395 
13396  /* Calculate how many characters at most the prefix index contains */
13397 
13398  n_chars = prefix_len / charset->mbmaxlen;
13399 
13400  /* If the charset is multi-byte, then we must find the length of the
13401  first at most n chars in the string. If the string contains less
13402  characters than n, then we return the length to the end of the last
13403  character. */
13404 
13405  if (charset->mbmaxlen > 1) {
13406  /* my_charpos() returns the byte length of the first n_chars
13407  characters, or a value bigger than the length of str, if
13408  there were not enough full characters in str.
13409 
13410  Why does the code below work:
13411  Suppose that we are looking for n UTF-8 characters.
13412 
13413  1) If the string is long enough, then the prefix contains at
13414  least n complete UTF-8 characters + maybe some extra
13415  characters + an incomplete UTF-8 character. No problem in
13416  this case. The function returns the pointer to the
13417  end of the nth character.
13418 
13419  2) If the string is not long enough, then the string contains
13420  the complete value of a column, that is, only complete UTF-8
13421  characters, and we can store in the column prefix index the
13422  whole string. */
13423 
13424  char_length = my_charpos(charset, str,
13425  str + data_len, (int) n_chars);
13426  if (char_length > data_len) {
13427  char_length = data_len;
13428  }
13429  } else {
13430  if (data_len < prefix_len) {
13431  char_length = data_len;
13432  } else {
13433  char_length = prefix_len;
13434  }
13435  }
13436 
13437  return(char_length);
13438 }
13439 
13440 /*******************************************************************/
13443 static
13444 int
13445 innobase_xa_prepare(
13446 /*================*/
13447  handlerton* hton,
13448  THD* thd,
13451  bool prepare_trx)
13454 {
13455  int error = 0;
13456  trx_t* trx = check_trx_exists(thd);
13457 
13458  DBUG_ASSERT(hton == innodb_hton_ptr);
13459 
13460  /* we use support_xa value as it was seen at transaction start
13461  time, not the current session variable value. Any possible changes
13462  to the session variable take effect only in the next transaction */
13463  if (!trx->support_xa) {
13464 
13465  return(0);
13466  }
13467 
13468  thd_get_xid(thd, (MYSQL_XID*) &trx->xid);
13469 
13470  /* Release a possible FIFO ticket and search latch. Since we will
13471  reserve the trx_sys->mutex, we have to release the search system
13472  latch first to obey the latching order. */
13473 
13475 
13476  innobase_srv_conc_force_exit_innodb(trx);
13477 
13478  if (!trx_is_registered_for_2pc(trx) && trx_is_started(trx)) {
13479 
13480  sql_print_error("Transaction not registered for MySQL 2PC, "
13481  "but transaction is active");
13482  }
13483 
13484  if (prepare_trx
13485  || (!thd_test_options(thd, OPTION_NOT_AUTOCOMMIT | OPTION_BEGIN))) {
13486 
13487  /* We were instructed to prepare the whole transaction, or
13488  this is an SQL statement end and autocommit is on */
13489 
13490  ut_ad(trx_is_registered_for_2pc(trx));
13491 
13492  trx_prepare_for_mysql(trx);
13493 
13494  error = 0;
13495  } else {
13496  /* We just mark the SQL statement ended and do not do a
13497  transaction prepare */
13498 
13499  /* If we had reserved the auto-inc lock for some
13500  table in this SQL statement we release it now */
13501 
13503 
13504  /* Store the current undo_no of the transaction so that we
13505  know where to roll back if we have to roll back the next
13506  SQL statement */
13507 
13508  trx_mark_sql_stat_end(trx);
13509  }
13510 
13511  /* Tell the InnoDB server that there might be work for utility
13512  threads: */
13513 
13515 
13516  if (thd_sql_command(thd) != SQLCOM_XA_PREPARE
13517  && (prepare_trx
13518  || !thd_test_options(
13519  thd, OPTION_NOT_AUTOCOMMIT | OPTION_BEGIN))) {
13520 
13521  /* For ibbackup to work the order of transactions in binlog
13522  and InnoDB must be the same. Consider the situation
13523 
13524  thread1> prepare; write to binlog; ...
13525  <context switch>
13526  thread2> prepare; write to binlog; commit
13527  thread1> ... commit
13528 
13529  The server guarantees that writes to the binary log
13530  and commits are in the same order, so we do not have
13531  to handle this case. */
13532  }
13533 
13534  return(error);
13535 }
13536 
13537 /*******************************************************************/
13540 static
13541 int
13542 innobase_xa_recover(
13543 /*================*/
13544  handlerton* hton,
13545  XID* xid_list,
13546  uint len)
13547 {
13548  DBUG_ASSERT(hton == innodb_hton_ptr);
13549 
13550  if (len == 0 || xid_list == NULL) {
13551 
13552  return(0);
13553  }
13554 
13555  return(trx_recover_for_mysql(xid_list, len));
13556 }
13557 
13558 /*******************************************************************/
13562 static
13563 int
13564 innobase_commit_by_xid(
13565 /*===================*/
13566  handlerton* hton,
13567  XID* xid)
13568 {
13569  trx_t* trx;
13570 
13571  DBUG_ASSERT(hton == innodb_hton_ptr);
13572 
13573  trx = trx_get_trx_by_xid(xid);
13574 
13575  if (trx) {
13576  innobase_commit_low(trx);
13578  return(XA_OK);
13579  } else {
13580  return(XAER_NOTA);
13581  }
13582 }
13583 
13584 /*******************************************************************/
13588 static
13589 int
13590 innobase_rollback_by_xid(
13591 /*=====================*/
13592  handlerton* hton,
13593  XID* xid)
13595 {
13596  trx_t* trx;
13597 
13598  DBUG_ASSERT(hton == innodb_hton_ptr);
13599 
13600  trx = trx_get_trx_by_xid(xid);
13601 
13602  if (trx) {
13603  int ret = innobase_rollback_trx(trx);
13605  return(ret);
13606  } else {
13607  return(XAER_NOTA);
13608  }
13609 }
13610 
13611 /*******************************************************************/
13617 static
13618 void*
13619 innobase_create_cursor_view(
13620 /*========================*/
13621  handlerton* hton,
13622  THD* thd)
13623 {
13624  DBUG_ASSERT(hton == innodb_hton_ptr);
13625 
13626  return(read_cursor_view_create_for_mysql(check_trx_exists(thd)));
13627 }
13628 
13629 /*******************************************************************/
13633 static
13634 void
13635 innobase_close_cursor_view(
13636 /*=======================*/
13637  handlerton* hton,
13638  THD* thd,
13639  void* curview)
13640 {
13641  DBUG_ASSERT(hton == innodb_hton_ptr);
13642 
13643  read_cursor_view_close_for_mysql(check_trx_exists(thd),
13644  (cursor_view_t*) curview);
13645 }
13646 
13647 /*******************************************************************/
13652 static
13653 void
13654 innobase_set_cursor_view(
13655 /*=====================*/
13656  handlerton* hton,
13657  THD* thd,
13658  void* curview)
13659 {
13660  DBUG_ASSERT(hton == innodb_hton_ptr);
13661 
13662  read_cursor_set_for_mysql(check_trx_exists(thd),
13663  (cursor_view_t*) curview);
13664 }
13665 
13666 /*******************************************************************/
13668 UNIV_INTERN
13669 bool
13671 /*====================================*/
13672  HA_CREATE_INFO* info,
13673  uint table_changes)
13674 {
13676 
13677  if (table_changes != IS_EQUAL_YES) {
13678 
13679  return(COMPATIBLE_DATA_NO);
13680  }
13681 
13682  /* Check that auto_increment value was not changed */
13683  if ((info->used_fields & HA_CREATE_USED_AUTO) &&
13684  info->auto_increment_value != 0) {
13685 
13686  return(COMPATIBLE_DATA_NO);
13687  }
13688 
13689  /* Check that row format didn't change */
13690  if ((info->used_fields & HA_CREATE_USED_ROW_FORMAT)
13691  && info->row_type != get_row_type()) {
13692 
13693  return(COMPATIBLE_DATA_NO);
13694  }
13695 
13696  /* Specifying KEY_BLOCK_SIZE requests a rebuild of the table. */
13697  if (info->used_fields & HA_CREATE_USED_KEY_BLOCK_SIZE) {
13698  return(COMPATIBLE_DATA_NO);
13699  }
13700 
13701  return(COMPATIBLE_DATA_YES);
13702 }
13703 
13704 /****************************************************************/
13707 static
13708 void
13709 innodb_io_capacity_max_update(
13710 /*===========================*/
13711  THD* thd,
13712  struct st_mysql_sys_var* var,
13714  void* var_ptr,
13716  const void* save)
13718 {
13719  ulong in_val = *static_cast<const ulong*>(save);
13720  if (in_val < srv_io_capacity) {
13721  in_val = srv_io_capacity;
13722  push_warning_printf(thd, Sql_condition::WARN_LEVEL_WARN,
13723  ER_WRONG_ARGUMENTS,
13724  "innodb_io_capacity_max cannot be"
13725  " set lower than innodb_io_capacity.");
13726  push_warning_printf(thd, Sql_condition::WARN_LEVEL_WARN,
13727  ER_WRONG_ARGUMENTS,
13728  "Setting innodb_io_capacity_max to %lu",
13729  srv_io_capacity);
13730  }
13731 
13732  srv_max_io_capacity = in_val;
13733 }
13734 
13735 /****************************************************************/
13738 static
13739 void
13740 innodb_io_capacity_update(
13741 /*======================*/
13742  THD* thd,
13743  struct st_mysql_sys_var* var,
13745  void* var_ptr,
13747  const void* save)
13749 {
13750  ulong in_val = *static_cast<const ulong*>(save);
13751  if (in_val > srv_max_io_capacity) {
13752  in_val = srv_max_io_capacity;
13753  push_warning_printf(thd, Sql_condition::WARN_LEVEL_WARN,
13754  ER_WRONG_ARGUMENTS,
13755  "innodb_io_capacity cannot be set"
13756  " higher than innodb_io_capacity_max.");
13757  push_warning_printf(thd, Sql_condition::WARN_LEVEL_WARN,
13758  ER_WRONG_ARGUMENTS,
13759  "Setting innodb_io_capacity to %lu",
13760  srv_max_io_capacity);
13761  }
13762 
13763  srv_io_capacity = in_val;
13764 }
13765 
13766 /****************************************************************/
13769 static
13770 void
13771 innodb_max_dirty_pages_pct_update(
13772 /*==============================*/
13773  THD* thd,
13774  struct st_mysql_sys_var* var,
13776  void* var_ptr,
13778  const void* save)
13780 {
13781  ulong in_val = *static_cast<const ulong*>(save);
13782  if (in_val < srv_max_dirty_pages_pct_lwm) {
13783  push_warning_printf(thd, Sql_condition::WARN_LEVEL_WARN,
13784  ER_WRONG_ARGUMENTS,
13785  "innodb_max_dirty_pages_pct cannot be"
13786  " set lower than"
13787  " innodb_max_dirty_pages_pct_lwm.");
13788  push_warning_printf(thd, Sql_condition::WARN_LEVEL_WARN,
13789  ER_WRONG_ARGUMENTS,
13790  "Lowering"
13791  " innodb_max_dirty_page_pct_lwm to %lu",
13792  in_val);
13793 
13794  srv_max_dirty_pages_pct_lwm = in_val;
13795  }
13796 
13797  srv_max_buf_pool_modified_pct = in_val;
13798 }
13799 
13800 /****************************************************************/
13803 static
13804 void
13805 innodb_max_dirty_pages_pct_lwm_update(
13806 /*==================================*/
13807  THD* thd,
13808  struct st_mysql_sys_var* var,
13810  void* var_ptr,
13812  const void* save)
13814 {
13815  ulong in_val = *static_cast<const ulong*>(save);
13816  if (in_val > srv_max_buf_pool_modified_pct) {
13817  in_val = srv_max_buf_pool_modified_pct;
13818  push_warning_printf(thd, Sql_condition::WARN_LEVEL_WARN,
13819  ER_WRONG_ARGUMENTS,
13820  "innodb_max_dirty_pages_pct_lwm"
13821  " cannot be set higher than"
13822  " innodb_max_dirty_pages_pct.");
13823  push_warning_printf(thd, Sql_condition::WARN_LEVEL_WARN,
13824  ER_WRONG_ARGUMENTS,
13825  "Setting innodb_max_dirty_page_pct_lwm"
13826  " to %lu",
13827  in_val);
13828  }
13829 
13830  srv_max_dirty_pages_pct_lwm = in_val;
13831 }
13832 
13833 /************************************************************/
13836 static
13837 uint
13838 innobase_file_format_name_lookup(
13839 /*=============================*/
13840  const char* format_name)
13841 {
13842  char* endp;
13843  uint format_id;
13844 
13845  ut_a(format_name != NULL);
13846 
13847  /* The format name can contain the format id itself instead of
13848  the name and we check for that. */
13849  format_id = (uint) strtoul(format_name, &endp, 10);
13850 
13851  /* Check for valid parse. */
13852  if (*endp == '\0' && *format_name != '\0') {
13853 
13854  if (format_id <= UNIV_FORMAT_MAX) {
13855 
13856  return(format_id);
13857  }
13858  } else {
13859 
13860  for (format_id = 0; format_id <= UNIV_FORMAT_MAX;
13861  format_id++) {
13862  const char* name;
13863 
13864  name = trx_sys_file_format_id_to_name(format_id);
13865 
13866  if (!innobase_strcasecmp(format_name, name)) {
13867 
13868  return(format_id);
13869  }
13870  }
13871  }
13872 
13873  return(UNIV_FORMAT_MAX + 1);
13874 }
13875 
13876 /************************************************************/
13880 static
13881 int
13882 innobase_file_format_validate_and_set(
13883 /*==================================*/
13884  const char* format_max)
13885 {
13886  uint format_id;
13887 
13888  format_id = innobase_file_format_name_lookup(format_max);
13889 
13890  if (format_id < UNIV_FORMAT_MAX + 1) {
13891  srv_max_file_format_at_startup = format_id;
13892 
13893  return((int) format_id);
13894  } else {
13895  return(-1);
13896  }
13897 }
13898 
13899 /*************************************************************/
13903 static
13904 int
13905 innodb_file_format_name_validate(
13906 /*=============================*/
13907  THD* thd,
13908  struct st_mysql_sys_var* var,
13910  void* save,
13912  struct st_mysql_value* value)
13913 {
13914  const char* file_format_input;
13915  char buff[STRING_BUFFER_USUAL_SIZE];
13916  int len = sizeof(buff);
13917 
13918  ut_a(save != NULL);
13919  ut_a(value != NULL);
13920 
13921  file_format_input = value->val_str(value, buff, &len);
13922 
13923  if (file_format_input != NULL) {
13924  uint format_id;
13925 
13926  format_id = innobase_file_format_name_lookup(
13927  file_format_input);
13928 
13929  if (format_id <= UNIV_FORMAT_MAX) {
13930 
13931  /* Save a pointer to the name in the
13932  'file_format_name_map' constant array. */
13933  *static_cast<const char**>(save) =
13934  trx_sys_file_format_id_to_name(format_id);
13935 
13936  return(0);
13937  }
13938  }
13939 
13940  *static_cast<const char**>(save) = NULL;
13941  return(1);
13942 }
13943 
13944 /****************************************************************/
13947 static
13948 void
13949 innodb_file_format_name_update(
13950 /*===========================*/
13951  THD* thd,
13952  struct st_mysql_sys_var* var,
13954  void* var_ptr,
13956  const void* save)
13958 {
13959  const char* format_name;
13960 
13961  ut_a(var_ptr != NULL);
13962  ut_a(save != NULL);
13963 
13964  format_name = *static_cast<const char*const*>(save);
13965 
13966  if (format_name) {
13967  uint format_id;
13968 
13969  format_id = innobase_file_format_name_lookup(format_name);
13970 
13971  if (format_id <= UNIV_FORMAT_MAX) {
13972  srv_file_format = format_id;
13973  }
13974  }
13975 
13976  *static_cast<const char**>(var_ptr)
13978 }
13979 
13980 /*************************************************************/
13984 static
13985 int
13986 innodb_file_format_max_validate(
13987 /*============================*/
13988  THD* thd,
13989  struct st_mysql_sys_var* var,
13991  void* save,
13993  struct st_mysql_value* value)
13994 {
13995  const char* file_format_input;
13996  char buff[STRING_BUFFER_USUAL_SIZE];
13997  int len = sizeof(buff);
13998  int format_id;
13999 
14000  ut_a(save != NULL);
14001  ut_a(value != NULL);
14002 
14003  file_format_input = value->val_str(value, buff, &len);
14004 
14005  if (file_format_input != NULL) {
14006 
14007  format_id = innobase_file_format_validate_and_set(
14008  file_format_input);
14009 
14010  if (format_id >= 0) {
14011  /* Save a pointer to the name in the
14012  'file_format_name_map' constant array. */
14013  *static_cast<const char**>(save) =
14015  (uint) format_id);
14016 
14017  return(0);
14018 
14019  } else {
14020  push_warning_printf(thd,
14021  Sql_condition::WARN_LEVEL_WARN,
14022  ER_WRONG_ARGUMENTS,
14023  "InnoDB: invalid innodb_file_format_max "
14024  "value; can be any format up to %s "
14025  "or equivalent id of %d",
14026  trx_sys_file_format_id_to_name(UNIV_FORMAT_MAX),
14027  UNIV_FORMAT_MAX);
14028  }
14029  }
14030 
14031  *static_cast<const char**>(save) = NULL;
14032  return(1);
14033 }
14034 
14035 /****************************************************************/
14038 static
14039 void
14040 innodb_file_format_max_update(
14041 /*==========================*/
14042  THD* thd,
14043  struct st_mysql_sys_var* var,
14045  void* var_ptr,
14047  const void* save)
14049 {
14050  const char* format_name_in;
14051  const char** format_name_out;
14052  uint format_id;
14053 
14054  ut_a(save != NULL);
14055  ut_a(var_ptr != NULL);
14056 
14057  format_name_in = *static_cast<const char*const*>(save);
14058 
14059  if (!format_name_in) {
14060 
14061  return;
14062  }
14063 
14064  format_id = innobase_file_format_name_lookup(format_name_in);
14065 
14066  if (format_id > UNIV_FORMAT_MAX) {
14067  /* DEFAULT is "on", which is invalid at runtime. */
14068  push_warning_printf(thd, Sql_condition::WARN_LEVEL_WARN,
14069  ER_WRONG_ARGUMENTS,
14070  "Ignoring SET innodb_file_format=%s",
14071  format_name_in);
14072  return;
14073  }
14074 
14075  format_name_out = static_cast<const char**>(var_ptr);
14076 
14077  /* Update the max format id in the system tablespace. */
14078  if (trx_sys_file_format_max_set(format_id, format_name_out)) {
14079  ut_print_timestamp(stderr);
14080  fprintf(stderr,
14081  " [Info] InnoDB: the file format in the system "
14082  "tablespace is now set to %s.\n", *format_name_out);
14083  }
14084 }
14085 
14086 /*************************************************************/
14090 static
14091 int
14092 innodb_stopword_table_validate(
14093 /*===========================*/
14094  THD* thd,
14095  struct st_mysql_sys_var* var,
14097  void* save,
14099  struct st_mysql_value* value)
14100 {
14101  const char* stopword_table_name;
14102  char buff[STRING_BUFFER_USUAL_SIZE];
14103  int len = sizeof(buff);
14104  trx_t* trx;
14105  int ret = 1;
14106 
14107  ut_a(save != NULL);
14108  ut_a(value != NULL);
14109 
14110  stopword_table_name = value->val_str(value, buff, &len);
14111 
14112  trx = check_trx_exists(thd);
14113 
14114  row_mysql_lock_data_dictionary(trx);
14115 
14116  /* Validate the stopword table's (if supplied) existence and
14117  of the right format */
14118  if (!stopword_table_name
14119  || fts_valid_stopword_table(stopword_table_name)) {
14120  *static_cast<const char**>(save) = stopword_table_name;
14121  ret = 0;
14122  }
14123 
14125 
14126  return(ret);
14127 }
14128 
14129 /****************************************************************/
14133 static
14134 void
14135 innodb_stopword_table_update(
14136 /*=========================*/
14137  THD* thd,
14138  struct st_mysql_sys_var* var,
14140  void* var_ptr,
14142  const void* save)
14144 {
14145  const char* stopword_table_name;
14146  char* old;
14147 
14148  ut_a(save != NULL);
14149  ut_a(var_ptr != NULL);
14150 
14151  stopword_table_name = *static_cast<const char*const*>(save);
14152  old = *(char**) var_ptr;
14153 
14154  if (stopword_table_name) {
14155  *(char**) var_ptr = my_strdup(stopword_table_name, MYF(0));
14156  } else {
14157  *(char**) var_ptr = NULL;
14158  }
14159 
14160  if (old) {
14161  my_free(old);
14162  }
14163 
14164  fts_server_stopword_table = *(char**) var_ptr;
14165 }
14166 
14167 /*************************************************************/
14171 static
14172 int
14173 innodb_internal_table_validate(
14174 /*===========================*/
14175  THD* thd,
14176  struct st_mysql_sys_var* var,
14178  void* save,
14180  struct st_mysql_value* value)
14181 {
14182  const char* table_name;
14183  char buff[STRING_BUFFER_USUAL_SIZE];
14184  int len = sizeof(buff);
14185  int ret = 1;
14186  dict_table_t* user_table;
14187 
14188  ut_a(save != NULL);
14189  ut_a(value != NULL);
14190 
14191  table_name = value->val_str(value, buff, &len);
14192 
14193  if (!table_name) {
14194  *static_cast<const char**>(save) = NULL;
14195  return(0);
14196  }
14197 
14198  user_table = dict_table_open_on_name(
14199  table_name, FALSE, TRUE, DICT_ERR_IGNORE_NONE);
14200 
14201  if (user_table) {
14202  if (dict_table_has_fts_index(user_table)) {
14203  *static_cast<const char**>(save) = table_name;
14204  ret = 0;
14205  }
14206 
14207  dict_table_close(user_table, FALSE, TRUE);
14208  }
14209 
14210  return(ret);
14211 }
14212 
14213 /****************************************************************/
14217 static
14218 void
14219 innodb_internal_table_update(
14220 /*=========================*/
14221  THD* thd,
14222  struct st_mysql_sys_var* var,
14224  void* var_ptr,
14226  const void* save)
14228 {
14229  const char* table_name;
14230  char* old;
14231 
14232  ut_a(save != NULL);
14233  ut_a(var_ptr != NULL);
14234 
14235  table_name = *static_cast<const char*const*>(save);
14236  old = *(char**) var_ptr;
14237 
14238  if (table_name) {
14239  *(char**) var_ptr = my_strdup(table_name, MYF(0));
14240  } else {
14241  *(char**) var_ptr = NULL;
14242  }
14243 
14244  if (old) {
14245  my_free(old);
14246  }
14247 
14248  fts_internal_tbl_name = *(char**) var_ptr;
14249 }
14250 
14251 /****************************************************************/
14254 static
14255 void
14256 innodb_adaptive_hash_index_update(
14257 /*==============================*/
14258  THD* thd,
14259  struct st_mysql_sys_var* var,
14261  void* var_ptr,
14263  const void* save)
14265 {
14266  if (*(my_bool*) save) {
14268  } else {
14270  }
14271 }
14272 
14273 /****************************************************************/
14276 static
14277 void
14278 innodb_cmp_per_index_update(
14279 /*========================*/
14280  THD* thd,
14281  struct st_mysql_sys_var* var,
14283  void* var_ptr,
14285  const void* save)
14287 {
14288  /* Reset the stats whenever we enable the table
14289  INFORMATION_SCHEMA.innodb_cmp_per_index. */
14290  if (!srv_cmp_per_index_enabled && *(my_bool*) save) {
14292  }
14293 
14294  srv_cmp_per_index_enabled = !!(*(my_bool*) save);
14295 }
14296 
14297 /****************************************************************/
14300 static
14301 void
14302 innodb_old_blocks_pct_update(
14303 /*=========================*/
14304  THD* thd,
14305  struct st_mysql_sys_var* var,
14307  void* var_ptr,
14309  const void* save)
14311 {
14312  innobase_old_blocks_pct = buf_LRU_old_ratio_update(
14313  *static_cast<const uint*>(save), TRUE);
14314 }
14315 
14316 /****************************************************************/
14319 static
14320 void
14321 innodb_change_buffer_max_size_update(
14322 /*=================================*/
14323  THD* thd,
14324  struct st_mysql_sys_var* var,
14326  void* var_ptr,
14328  const void* save)
14330 {
14331  innobase_change_buffer_max_size =
14332  (*static_cast<const uint*>(save));
14333  ibuf_max_size_update(innobase_change_buffer_max_size);
14334 }
14335 
14336 
14337 /*************************************************************/
14343 static
14344 ibuf_use_t
14345 innodb_find_change_buffering_value(
14346 /*===============================*/
14347  const char* input_name)
14349 {
14350  ulint use;
14351 
14352  for (use = 0; use < UT_ARR_SIZE(innobase_change_buffering_values);
14353  use++) {
14354  /* found a match */
14355  if (!innobase_strcasecmp(
14356  input_name, innobase_change_buffering_values[use])) {
14357  return((ibuf_use_t) use);
14358  }
14359  }
14360 
14361  /* Did not find any match */
14362  return(IBUF_USE_COUNT);
14363 }
14364 
14365 /*************************************************************/
14369 static
14370 int
14371 innodb_change_buffering_validate(
14372 /*=============================*/
14373  THD* thd,
14374  struct st_mysql_sys_var* var,
14376  void* save,
14378  struct st_mysql_value* value)
14379 {
14380  const char* change_buffering_input;
14381  char buff[STRING_BUFFER_USUAL_SIZE];
14382  int len = sizeof(buff);
14383 
14384  ut_a(save != NULL);
14385  ut_a(value != NULL);
14386 
14387  change_buffering_input = value->val_str(value, buff, &len);
14388 
14389  if (change_buffering_input != NULL) {
14390  ibuf_use_t use;
14391 
14392  use = innodb_find_change_buffering_value(
14393  change_buffering_input);
14394 
14395  if (use != IBUF_USE_COUNT) {
14396  /* Find a matching change_buffering option value. */
14397  *static_cast<const char**>(save) =
14398  innobase_change_buffering_values[use];
14399 
14400  return(0);
14401  }
14402  }
14403 
14404  /* No corresponding change buffering option for user supplied
14405  "change_buffering_input" */
14406  return(1);
14407 }
14408 
14409 /****************************************************************/
14412 static
14413 void
14414 innodb_change_buffering_update(
14415 /*===========================*/
14416  THD* thd,
14417  struct st_mysql_sys_var* var,
14419  void* var_ptr,
14421  const void* save)
14423 {
14424  ibuf_use_t use;
14425 
14426  ut_a(var_ptr != NULL);
14427  ut_a(save != NULL);
14428 
14429  use = innodb_find_change_buffering_value(
14430  *static_cast<const char*const*>(save));
14431 
14432  ut_a(use < IBUF_USE_COUNT);
14433 
14434  ibuf_use = use;
14435  *static_cast<const char**>(var_ptr) =
14436  *static_cast<const char*const*>(save);
14437 }
14438 
14439 /*************************************************************/
14442 static
14443 void
14444 innodb_stats_sample_pages_update(
14445 /*=============================*/
14446  THD* thd,
14447  struct st_mysql_sys_var* var,
14449  void* var_ptr,
14451  const void* save)
14453 {
14454 #define STATS_SAMPLE_PAGES_DEPRECATED_MSG \
14455  "Using innodb_stats_sample_pages is deprecated and " \
14456  "the variable may be removed in future releases. " \
14457  "Please use innodb_stats_transient_sample_pages " \
14458  "instead."
14459 
14460  push_warning(thd, Sql_condition::WARN_LEVEL_WARN,
14461  HA_ERR_WRONG_COMMAND, STATS_SAMPLE_PAGES_DEPRECATED_MSG);
14462 
14463  ut_print_timestamp(stderr);
14464  fprintf(stderr,
14465  " InnoDB: Warning: %s\n",
14466  STATS_SAMPLE_PAGES_DEPRECATED_MSG);
14467 
14468  srv_stats_transient_sample_pages =
14469  *static_cast<const unsigned long long*>(save);
14470 }
14471 
14472 /****************************************************************/
14475 static
14476 void
14477 innodb_monitor_set_option(
14478 /*======================*/
14479  const monitor_info_t* monitor_info,
14481  mon_option_t set_option)
14483 {
14484  monitor_id_t monitor_id = monitor_info->monitor_id;
14485 
14486  /* If module type is MONITOR_GROUP_MODULE, it cannot be
14487  turned on/off individually. It should never use this
14488  function to set options */
14489  ut_a(!(monitor_info->monitor_type & MONITOR_GROUP_MODULE));
14490 
14491  switch (set_option) {
14492  case MONITOR_TURN_ON:
14493  MONITOR_ON(monitor_id);
14494  MONITOR_INIT(monitor_id);
14495  MONITOR_SET_START(monitor_id);
14496 
14497  /* If the monitor to be turned on uses
14498  exisitng monitor counter (status variable),
14499  make special processing to remember existing
14500  counter value. */
14501  if (monitor_info->monitor_type
14502  & MONITOR_EXISTING) {
14504  monitor_id, MONITOR_TURN_ON);
14505  }
14506  break;
14507 
14508  case MONITOR_TURN_OFF:
14509  if (monitor_info->monitor_type & MONITOR_EXISTING) {
14511  monitor_id, MONITOR_TURN_OFF);
14512  }
14513 
14514  MONITOR_OFF(monitor_id);
14515  MONITOR_SET_OFF(monitor_id);
14516  break;
14517 
14518  case MONITOR_RESET_VALUE:
14519  srv_mon_reset(monitor_id);
14520  break;
14521 
14523  srv_mon_reset_all(monitor_id);
14524  break;
14525 
14526  default:
14527  ut_error;
14528  }
14529 }
14530 
14531 /****************************************************************/
14535 static
14536 void
14537 innodb_monitor_update_wildcard(
14538 /*===========================*/
14539  const char* name,
14540  mon_option_t set_option)
14542 {
14543  ut_a(name);
14544 
14545  for (ulint use = 0; use < NUM_MONITOR; use++) {
14546  ulint type;
14547  monitor_id_t monitor_id = static_cast<monitor_id_t>(use);
14548  monitor_info_t* monitor_info;
14549 
14550  if (!innobase_wildcasecmp(
14551  srv_mon_get_name(monitor_id), name)) {
14552  monitor_info = srv_mon_get_info(monitor_id);
14553 
14554  type = monitor_info->monitor_type;
14555 
14556  /* If the monitor counter is of MONITOR_MODULE
14557  type, skip it. Except for those also marked with
14558  MONITOR_GROUP_MODULE flag, which can be turned
14559  on only as a module. */
14560  if (!(type & MONITOR_MODULE)
14561  && !(type & MONITOR_GROUP_MODULE)) {
14562  innodb_monitor_set_option(monitor_info,
14563  set_option);
14564  }
14565 
14566  /* Need to special handle counters marked with
14567  MONITOR_GROUP_MODULE, turn on the whole module if
14568  any one of it comes here. Currently, only
14569  "module_buf_page" is marked with MONITOR_GROUP_MODULE */
14570  if (type & MONITOR_GROUP_MODULE) {
14571  if ((monitor_id >= MONITOR_MODULE_BUF_PAGE)
14572  && (monitor_id < MONITOR_MODULE_OS)) {
14573  if (set_option == MONITOR_TURN_ON
14574  && MONITOR_IS_ON(
14575  MONITOR_MODULE_BUF_PAGE)) {
14576  continue;
14577  }
14578 
14580  MONITOR_MODULE_BUF_PAGE,
14581  set_option);
14582  } else {
14583  /* If new monitor is added with
14584  MONITOR_GROUP_MODULE, it needs
14585  to be added here. */
14586  ut_ad(0);
14587  }
14588  }
14589  }
14590  }
14591 }
14592 
14593 /*************************************************************/
14597 static
14598 ulint
14599 innodb_monitor_id_by_name_get(
14600 /*==========================*/
14601  const char* name)
14602 {
14603  ut_a(name);
14604 
14605  /* Search for wild character '%' in the name, if
14606  found, we treat it as a wildcard match. We do not search for
14607  single character wildcard '_' since our monitor names already contain
14608  such character. To avoid confusion, we request user must include
14609  at least one '%' character to activate the wildcard search. */
14610  if (strchr(name, '%')) {
14611  return(MONITOR_WILDCARD_MATCH);
14612  }
14613 
14614  /* Not wildcard match, check for an exact match */
14615  for (ulint i = 0; i < NUM_MONITOR; i++) {
14616  if (!innobase_strcasecmp(
14617  name, srv_mon_get_name(static_cast<monitor_id_t>(i)))) {
14618  return(i);
14619  }
14620  }
14621 
14622  return(MONITOR_NO_MATCH);
14623 }
14624 /*************************************************************/
14628 static
14629 ibool
14630 innodb_monitor_validate_wildcard_name(
14631 /*==================================*/
14632  const char* name)
14633 {
14634  for (ulint i = 0; i < NUM_MONITOR; i++) {
14635  if (!innobase_wildcasecmp(
14636  srv_mon_get_name(static_cast<monitor_id_t>(i)), name)) {
14637  return(TRUE);
14638  }
14639  }
14640 
14641  return(FALSE);
14642 }
14643 /*************************************************************/
14647 static
14648 int
14649 innodb_monitor_valid_byname(
14650 /*========================*/
14651  void* save,
14653  const char* name)
14654 {
14655  ulint use;
14656  monitor_info_t* monitor_info;
14657 
14658  if (!name) {
14659  return(1);
14660  }
14661 
14662  use = innodb_monitor_id_by_name_get(name);
14663 
14664  /* No monitor name matches, nor it is wildcard match */
14665  if (use == MONITOR_NO_MATCH) {
14666  return(1);
14667  }
14668 
14669  if (use < NUM_MONITOR) {
14670  monitor_info = srv_mon_get_info((monitor_id_t) use);
14671 
14672  /* If the monitor counter is marked with
14673  MONITOR_GROUP_MODULE flag, then this counter
14674  cannot be turned on/off individually, instead
14675  it shall be turned on/off as a group using
14676  its module name */
14677  if ((monitor_info->monitor_type & MONITOR_GROUP_MODULE)
14678  && (!(monitor_info->monitor_type & MONITOR_MODULE))) {
14679  sql_print_warning(
14680  "Monitor counter '%s' cannot"
14681  " be turned on/off individually."
14682  " Please use its module name"
14683  " to turn on/off the counters"
14684  " in the module as a group.\n",
14685  name);
14686 
14687  return(1);
14688  }
14689 
14690  } else {
14691  ut_a(use == MONITOR_WILDCARD_MATCH);
14692 
14693  /* For wildcard match, if there is not a single monitor
14694  counter name that matches, treat it as an invalid
14695  value for the system configuration variables */
14696  if (!innodb_monitor_validate_wildcard_name(name)) {
14697  return(1);
14698  }
14699  }
14700 
14701  /* Save the configure name for innodb_monitor_update() */
14702  *static_cast<const char**>(save) = name;
14703 
14704  return(0);
14705 }
14706 /*************************************************************/
14710 static
14711 int
14712 innodb_monitor_validate(
14713 /*====================*/
14714  THD* thd,
14715  struct st_mysql_sys_var* var,
14717  void* save,
14719  struct st_mysql_value* value)
14720 {
14721  const char* name;
14722  char* monitor_name;
14723  char buff[STRING_BUFFER_USUAL_SIZE];
14724  int len = sizeof(buff);
14725  int ret;
14726 
14727  ut_a(save != NULL);
14728  ut_a(value != NULL);
14729 
14730  name = value->val_str(value, buff, &len);
14731 
14732  /* monitor_name could point to memory from MySQL
14733  or buff[]. Always dup the name to memory allocated
14734  by InnoDB, so we can access it in another callback
14735  function innodb_monitor_update() and free it appropriately */
14736  if (name) {
14737  monitor_name = my_strdup(name, MYF(0));
14738  } else {
14739  return(1);
14740  }
14741 
14742  ret = innodb_monitor_valid_byname(save, monitor_name);
14743 
14744  if (ret) {
14745  /* Validation failed */
14746  my_free(monitor_name);
14747  } else {
14748  /* monitor_name will be freed in separate callback function
14749  innodb_monitor_update(). Assert "save" point to
14750  the "monitor_name" variable */
14751  ut_ad(*static_cast<char**>(save) == monitor_name);
14752  }
14753 
14754  return(ret);
14755 }
14756 
14757 /****************************************************************/
14761 static
14762 void
14763 innodb_monitor_update(
14764 /*==================*/
14765  THD* thd,
14766  void* var_ptr,
14768  const void* save,
14770  mon_option_t set_option,
14773  ibool free_mem)
14775 {
14776  monitor_info_t* monitor_info;
14777  ulint monitor_id;
14778  ulint err_monitor = 0;
14779  const char* name;
14780 
14781  ut_a(save != NULL);
14782 
14783  name = *static_cast<const char*const*>(save);
14784 
14785  if (!name) {
14786  monitor_id = MONITOR_DEFAULT_START;
14787  } else {
14788  monitor_id = innodb_monitor_id_by_name_get(name);
14789 
14790  /* Double check we have a valid monitor ID */
14791  if (monitor_id == MONITOR_NO_MATCH) {
14792  return;
14793  }
14794  }
14795 
14796  if (monitor_id == MONITOR_DEFAULT_START) {
14797  /* If user set the variable to "default", we will
14798  print a message and make this set operation a "noop".
14799  The check is being made here is because "set default"
14800  does not go through validation function */
14801  if (thd) {
14802  push_warning_printf(
14803  thd, Sql_condition::WARN_LEVEL_WARN,
14804  ER_NO_DEFAULT,
14805  "Default value is not defined for "
14806  "this set option. Please specify "
14807  "correct counter or module name.");
14808  } else {
14809  sql_print_error(
14810  "Default value is not defined for "
14811  "this set option. Please specify "
14812  "correct counter or module name.\n");
14813  }
14814 
14815  if (var_ptr) {
14816  *(const char**) var_ptr = NULL;
14817  }
14818  } else if (monitor_id == MONITOR_WILDCARD_MATCH) {
14819  innodb_monitor_update_wildcard(name, set_option);
14820  } else {
14821  monitor_info = srv_mon_get_info(
14822  static_cast<monitor_id_t>(monitor_id));
14823 
14824  ut_a(monitor_info);
14825 
14826  /* If monitor is already truned on, someone could already
14827  collect monitor data, exit and ask user to turn off the
14828  monitor before turn it on again. */
14829  if (set_option == MONITOR_TURN_ON
14830  && MONITOR_IS_ON(monitor_id)) {
14831  err_monitor = monitor_id;
14832  goto exit;
14833  }
14834 
14835  if (var_ptr) {
14836  *(const char**) var_ptr = monitor_info->monitor_name;
14837  }
14838 
14839  /* Depending on the monitor name is for a module or
14840  a counter, process counters in the whole module or
14841  individual counter. */
14842  if (monitor_info->monitor_type & MONITOR_MODULE) {
14844  static_cast<monitor_id_t>(monitor_id),
14845  set_option);
14846  } else {
14847  innodb_monitor_set_option(monitor_info, set_option);
14848  }
14849  }
14850 exit:
14851  /* Only if we are trying to turn on a monitor that already
14852  been turned on, we will set err_monitor. Print related
14853  information */
14854  if (err_monitor) {
14855  sql_print_warning("Monitor %s is already enabled.",
14856  srv_mon_get_name((monitor_id_t) err_monitor));
14857  }
14858 
14859  if (free_mem && name) {
14860  my_free((void*) name);
14861  }
14862 
14863  return;
14864 }
14865 
14866 #ifdef __WIN__
14867 /*************************************************************/
14873 static
14874 int
14875 innodb_srv_buf_dump_filename_validate(
14876 /*==================================*/
14877  THD* thd,
14878  struct st_mysql_sys_var* var,
14880  void* save,
14882  struct st_mysql_value* value)
14883 {
14884  const char* buf_name;
14885  char buff[OS_FILE_MAX_PATH];
14886  int len= sizeof(buff);
14887 
14888  ut_a(save != NULL);
14889  ut_a(value != NULL);
14890 
14891  buf_name = value->val_str(value, buff, &len);
14892 
14893  if (buf_name) {
14894  if (is_filename_allowed(buf_name, len, FALSE)){
14895  *static_cast<const char**>(save) = buf_name;
14896  return(0);
14897  } else {
14898  push_warning_printf(thd,
14899  Sql_condition::WARN_LEVEL_WARN,
14900  ER_WRONG_ARGUMENTS,
14901  "InnoDB: innodb_buffer_pool_filename "
14902  "cannot have colon (:) in the file name.");
14903 
14904  }
14905  }
14906 
14907  return(1);
14908 }
14909 #else /* __WIN__ */
14910 # define innodb_srv_buf_dump_filename_validate NULL
14911 #endif /* __WIN__ */
14912 
14913 #ifdef UNIV_DEBUG
14914 static char* srv_buffer_pool_evict;
14915 
14916 /****************************************************************/
14920 static __attribute__((warn_unused_result))
14921 bool
14922 innodb_buffer_pool_evict_uncompressed(void)
14923 /*=======================================*/
14924 {
14925  bool all_evicted = true;
14926 
14927  for (ulint i = 0; i < srv_buf_pool_instances; i++) {
14928  buf_pool_t* buf_pool = &buf_pool_ptr[i];
14929 
14930  buf_pool_mutex_enter(buf_pool);
14931 
14933  buf_pool->unzip_LRU);
14934  block != NULL; ) {
14935  buf_block_t* prev_block = UT_LIST_GET_PREV(
14936  unzip_LRU, block);
14938  == BUF_BLOCK_FILE_PAGE);
14939  ut_ad(block->in_unzip_LRU_list);
14940  ut_ad(block->page.in_LRU_list);
14941 
14942  if (!buf_LRU_free_page(&block->page, false)) {
14943  all_evicted = false;
14944  }
14945 
14946  block = prev_block;
14947  }
14948 
14949  buf_pool_mutex_exit(buf_pool);
14950  }
14951 
14952  return(all_evicted);
14953 }
14954 
14955 /****************************************************************/
14960 static
14961 void
14962 innodb_buffer_pool_evict_update(
14963 /*============================*/
14964  THD* thd,
14965  struct st_mysql_sys_var*var,
14966  void* var_ptr,
14967  const void* save)
14969 {
14970  if (const char* op = *static_cast<const char*const*>(save)) {
14971  if (!strcmp(op, "uncompressed")) {
14972  for (uint tries = 0; tries < 10000; tries++) {
14973  if (innodb_buffer_pool_evict_uncompressed()) {
14974  return;
14975  }
14976 
14977  os_thread_sleep(10000);
14978  }
14979 
14980  /* We failed to evict all uncompressed pages. */
14981  ut_ad(0);
14982  }
14983  }
14984 }
14985 #endif /* UNIV_DEBUG */
14986 
14987 /****************************************************************/
14991 static
14992 void
14993 innodb_enable_monitor_update(
14994 /*=========================*/
14995  THD* thd,
14996  struct st_mysql_sys_var* var,
14998  void* var_ptr,
15000  const void* save)
15002 {
15003  innodb_monitor_update(thd, var_ptr, save, MONITOR_TURN_ON, TRUE);
15004 }
15005 
15006 /****************************************************************/
15009 static
15010 void
15011 innodb_disable_monitor_update(
15012 /*==========================*/
15013  THD* thd,
15014  struct st_mysql_sys_var* var,
15016  void* var_ptr,
15018  const void* save)
15020 {
15021  innodb_monitor_update(thd, var_ptr, save, MONITOR_TURN_OFF, TRUE);
15022 }
15023 
15024 /****************************************************************/
15028 static
15029 void
15030 innodb_reset_monitor_update(
15031 /*========================*/
15032  THD* thd,
15033  struct st_mysql_sys_var* var,
15035  void* var_ptr,
15037  const void* save)
15039 {
15040  innodb_monitor_update(thd, var_ptr, save, MONITOR_RESET_VALUE, TRUE);
15041 }
15042 
15043 /****************************************************************/
15047 static
15048 void
15049 innodb_reset_all_monitor_update(
15050 /*============================*/
15051  THD* thd,
15052  struct st_mysql_sys_var* var,
15054  void* var_ptr,
15056  const void* save)
15058 {
15059  innodb_monitor_update(thd, var_ptr, save, MONITOR_RESET_ALL_VALUE,
15060  TRUE);
15061 }
15062 
15063 /****************************************************************/
15069 static
15070 void
15071 innodb_enable_monitor_at_startup(
15072 /*=============================*/
15073  char* str)
15074 {
15075  static const char* sep = " ;,";
15076  char* last;
15077 
15078  ut_a(str);
15079 
15080  /* Walk through the string, and separate each monitor counter
15081  and/or counter group name, and calling innodb_monitor_update()
15082  if successfully updated. Please note that the "str" would be
15083  changed by strtok_r() as it walks through it. */
15084  for (char* option = strtok_r(str, sep, &last);
15085  option;
15086  option = strtok_r(NULL, sep, &last)) {
15087  ulint ret;
15088  char* option_name;
15089 
15090  ret = innodb_monitor_valid_byname(&option_name, option);
15091 
15092  /* The name is validated if ret == 0 */
15093  if (!ret) {
15094  innodb_monitor_update(NULL, NULL, &option,
15095  MONITOR_TURN_ON, FALSE);
15096  } else {
15097  sql_print_warning("Invalid monitor counter"
15098  " name: '%s'", option);
15099  }
15100  }
15101 }
15102 
15103 /****************************************************************/
15106 static
15107 int
15108 show_innodb_vars(
15109 /*=============*/
15110  THD* thd,
15111  SHOW_VAR* var,
15112  char* buff)
15113 {
15114  innodb_export_status();
15115  var->type = SHOW_ARRAY;
15116  var->value = (char*) &innodb_status_variables;
15117 
15118  return(0);
15119 }
15120 
15121 /****************************************************************/
15127 UNIV_INTERN
15128 bool
15129 innobase_index_name_is_reserved(
15130 /*============================*/
15131  THD* thd,
15132  const KEY* key_info,
15133  ulint num_of_keys)
15135 {
15136  const KEY* key;
15137  uint key_num; /* index number */
15138 
15139  for (key_num = 0; key_num < num_of_keys; key_num++) {
15140  key = &key_info[key_num];
15141 
15142  if (innobase_strcasecmp(key->name,
15143  innobase_index_reserve_name) == 0) {
15144  /* Push warning to mysql */
15145  push_warning_printf(thd,
15146  Sql_condition::WARN_LEVEL_WARN,
15147  ER_WRONG_NAME_FOR_INDEX,
15148  "Cannot Create Index with name "
15149  "'%s'. The name is reserved "
15150  "for the system default primary "
15151  "index.",
15152  innobase_index_reserve_name);
15153 
15154  my_error(ER_WRONG_NAME_FOR_INDEX, MYF(0),
15155  innobase_index_reserve_name);
15156 
15157  return(true);
15158  }
15159  }
15160 
15161  return(false);
15162 }
15163 
15164 /***********************************************************************
15165 Retrieve the FTS Relevance Ranking result for doc with doc_id
15166 of prebuilt->fts_doc_id
15167 @return the relevance ranking value */
15168 UNIV_INTERN
15169 float
15170 innobase_fts_retrieve_ranking(
15171 /*============================*/
15172  FT_INFO * fts_hdl)
15173 {
15174  row_prebuilt_t* ft_prebuilt;
15175  fts_result_t* result;
15176 
15177  result = ((NEW_FT_INFO*) fts_hdl)->ft_result;
15178 
15179  ft_prebuilt = ((NEW_FT_INFO*) fts_hdl)->ft_prebuilt;
15180 
15181  if (ft_prebuilt->read_just_key) {
15182  fts_ranking_t* ranking =
15183  rbt_value(fts_ranking_t, result->current);
15184  return(ranking->rank);
15185  }
15186 
15187  /* Retrieve the ranking value for doc_id with value of
15188  prebuilt->fts_doc_id */
15189  return(fts_retrieve_ranking(result, ft_prebuilt->fts_doc_id));
15190 }
15191 
15192 /***********************************************************************
15193 Free the memory for the FTS handler */
15194 UNIV_INTERN
15195 void
15196 innobase_fts_close_ranking(
15197 /*=======================*/
15198  FT_INFO * fts_hdl)
15199 {
15200  fts_result_t* result;
15201 
15202  ((NEW_FT_INFO*) fts_hdl)->ft_prebuilt->in_fts_query = false;
15203 
15204  result = ((NEW_FT_INFO*) fts_hdl)->ft_result;
15205 
15206  fts_query_free_result(result);
15207 
15208  my_free((uchar*) fts_hdl);
15209 
15210 
15211  return;
15212 }
15213 
15214 /***********************************************************************
15215 Find and Retrieve the FTS Relevance Ranking result for doc with doc_id
15216 of prebuilt->fts_doc_id
15217 @return the relevance ranking value */
15218 UNIV_INTERN
15219 float
15220 innobase_fts_find_ranking(
15221 /*======================*/
15222  FT_INFO* fts_hdl,
15223  uchar* record,
15224  uint len)
15225 {
15226  row_prebuilt_t* ft_prebuilt;
15227  fts_result_t* result;
15228 
15229  ft_prebuilt = ((NEW_FT_INFO*) fts_hdl)->ft_prebuilt;
15230  result = ((NEW_FT_INFO*) fts_hdl)->ft_result;
15231 
15232  /* Retrieve the ranking value for doc_id with value of
15233  prebuilt->fts_doc_id */
15234  return(fts_retrieve_ranking(result, ft_prebuilt->fts_doc_id));
15235 }
15236 
15237 #ifdef UNIV_DEBUG
15238 static my_bool innodb_purge_run_now = TRUE;
15239 static my_bool innodb_purge_stop_now = TRUE;
15240 static my_bool innodb_log_checkpoint_now = TRUE;
15241 
15242 /****************************************************************/
15245 static
15246 void
15247 purge_run_now_set(
15248 /*==============*/
15249  THD* thd
15250  __attribute__((unused)),
15251  struct st_mysql_sys_var* var
15253  __attribute__((unused)),
15254  void* var_ptr
15256  __attribute__((unused)),
15257  const void* save)
15259 {
15260  if (*(my_bool*) save && trx_purge_state() != PURGE_STATE_DISABLED) {
15261  trx_purge_run();
15262  }
15263 }
15264 
15265 /****************************************************************/
15268 static
15269 void
15270 purge_stop_now_set(
15271 /*===============*/
15272  THD* thd
15273  __attribute__((unused)),
15274  struct st_mysql_sys_var* var
15276  __attribute__((unused)),
15277  void* var_ptr
15279  __attribute__((unused)),
15280  const void* save)
15282 {
15283  if (*(my_bool*) save && trx_purge_state() != PURGE_STATE_DISABLED) {
15284  trx_purge_stop();
15285  }
15286 }
15287 
15288 /****************************************************************/
15290 static
15291 void
15292 checkpoint_now_set(
15293 /*===============*/
15294  THD* thd
15295  __attribute__((unused)),
15296  struct st_mysql_sys_var* var
15298  __attribute__((unused)),
15299  void* var_ptr
15301  __attribute__((unused)),
15302  const void* save)
15304 {
15305  if (*(my_bool*) save) {
15306  while (log_sys->last_checkpoint_lsn < log_sys->lsn) {
15307  log_make_checkpoint_at(LSN_MAX, TRUE);
15309  }
15312  }
15313 }
15314 #endif /* UNIV_DEBUG */
15315 
15316 /***********************************************************************
15317 @return version of the extended FTS API */
15318 uint
15319 innobase_fts_get_version()
15320 /*======================*/
15321 {
15322  /* Currently this doesn't make much sense as returning
15323  HA_CAN_FULLTEXT_EXT automatically mean this version is supported.
15324  This supposed to ease future extensions. */
15325  return(2);
15326 }
15327 
15328 /***********************************************************************
15329 @return Which part of the extended FTS API is supported */
15330 ulonglong
15331 innobase_fts_flags()
15332 /*================*/
15333 {
15334  return(FTS_ORDERED_RESULT | FTS_DOCID_IN_RESULT);
15335 }
15336 
15337 
15338 /***********************************************************************
15339 Find and Retrieve the FTS doc_id for the current result row
15340 @return the document ID */
15341 ulonglong
15342 innobase_fts_retrieve_docid(
15343 /*========================*/
15344  FT_INFO_EXT * fts_hdl)
15345 {
15346  row_prebuilt_t* ft_prebuilt;
15347  fts_result_t* result;
15348 
15349  ft_prebuilt = ((NEW_FT_INFO *)fts_hdl)->ft_prebuilt;
15350  result = ((NEW_FT_INFO *)fts_hdl)->ft_result;
15351 
15352  if (ft_prebuilt->read_just_key) {
15353  fts_ranking_t* ranking =
15354  rbt_value(fts_ranking_t, result->current);
15355  return(ranking->doc_id);
15356  }
15357 
15358  return(ft_prebuilt->fts_doc_id);
15359 }
15360 
15361 /***********************************************************************
15362 Find and retrieve the size of the current result
15363 @return number of matching rows */
15364 ulonglong
15365 innobase_fts_count_matches(
15366 /*=======================*/
15367  FT_INFO_EXT* fts_hdl)
15368 {
15369  NEW_FT_INFO* handle = (NEW_FT_INFO *) fts_hdl;
15370 
15371  if (handle->ft_result->rankings_by_id != 0) {
15372  return rbt_size(handle->ft_result->rankings_by_id);
15373  } else {
15374  return(0);
15375  }
15376 }
15377 
15378 /* These variables are never read by InnoDB or changed. They are a kind of
15379 dummies that are needed by the MySQL infrastructure to call
15380 buffer_pool_dump_now(), buffer_pool_load_now() and buffer_pool_load_abort()
15381 by the user by doing:
15382  SET GLOBAL innodb_buffer_pool_dump_now=ON;
15383  SET GLOBAL innodb_buffer_pool_load_now=ON;
15384  SET GLOBAL innodb_buffer_pool_load_abort=ON;
15385 Their values are read by MySQL and displayed to the user when the variables
15386 are queried, e.g.:
15387  SELECT @@innodb_buffer_pool_dump_now;
15388  SELECT @@innodb_buffer_pool_load_now;
15389  SELECT @@innodb_buffer_pool_load_abort; */
15390 static my_bool innodb_buffer_pool_dump_now = FALSE;
15391 static my_bool innodb_buffer_pool_load_now = FALSE;
15392 static my_bool innodb_buffer_pool_load_abort = FALSE;
15393 
15394 /****************************************************************/
15397 static
15398 void
15399 buffer_pool_dump_now(
15400 /*=================*/
15401  THD* thd
15402  __attribute__((unused)),
15403  struct st_mysql_sys_var* var
15405  __attribute__((unused)),
15406  void* var_ptr
15408  __attribute__((unused)),
15409  const void* save)
15411 {
15412  if (*(my_bool*) save && !srv_read_only_mode) {
15413  buf_dump_start();
15414  }
15415 }
15416 
15417 /****************************************************************/
15420 static
15421 void
15422 buffer_pool_load_now(
15423 /*=================*/
15424  THD* thd
15425  __attribute__((unused)),
15426  struct st_mysql_sys_var* var
15428  __attribute__((unused)),
15429  void* var_ptr
15431  __attribute__((unused)),
15432  const void* save)
15434 {
15435  if (*(my_bool*) save) {
15436  buf_load_start();
15437  }
15438 }
15439 
15440 /****************************************************************/
15443 static
15444 void
15445 buffer_pool_load_abort(
15446 /*===================*/
15447  THD* thd
15448  __attribute__((unused)),
15449  struct st_mysql_sys_var* var
15451  __attribute__((unused)),
15452  void* var_ptr
15454  __attribute__((unused)),
15455  const void* save)
15457 {
15458  if (*(my_bool*) save) {
15459  buf_load_abort();
15460  }
15461 }
15462 
15463 static SHOW_VAR innodb_status_variables_export[]= {
15464  {"Innodb", (char*) &show_innodb_vars, SHOW_FUNC},
15465  {NullS, NullS, SHOW_LONG}
15466 };
15467 
15468 static struct st_mysql_storage_engine innobase_storage_engine=
15469 { MYSQL_HANDLERTON_INTERFACE_VERSION };
15470 
15471 /* plugin options */
15472 
15473 static MYSQL_SYSVAR_ENUM(checksum_algorithm, srv_checksum_algorithm,
15474  PLUGIN_VAR_RQCMDARG,
15475  "The algorithm InnoDB uses for page checksumming. Possible values are "
15476  "CRC32 (hardware accelerated if the CPU supports it) "
15477  "write crc32, allow any of the other checksums to match when reading; "
15478  "STRICT_CRC32 "
15479  "write crc32, do not allow other algorithms to match when reading; "
15480  "INNODB "
15481  "write a software calculated checksum, allow any other checksums "
15482  "to match when reading; "
15483  "STRICT_INNODB "
15484  "write a software calculated checksum, do not allow other algorithms "
15485  "to match when reading; "
15486  "NONE "
15487  "write a constant magic number, do not do any checksum verification "
15488  "when reading (same as innodb_checksums=OFF); "
15489  "STRICT_NONE "
15490  "write a constant magic number, do not allow values other than that "
15491  "magic number when reading; "
15492  "Files updated when this option is set to crc32 or strict_crc32 will "
15493  "not be readable by MySQL versions older than 5.6.3",
15494  NULL, NULL, SRV_CHECKSUM_ALGORITHM_INNODB,
15495  &innodb_checksum_algorithm_typelib);
15496 
15497 static MYSQL_SYSVAR_BOOL(checksums, innobase_use_checksums,
15498  PLUGIN_VAR_NOCMDARG | PLUGIN_VAR_READONLY,
15499  "DEPRECATED. Use innodb_checksum_algorithm=NONE instead of setting "
15500  "this to OFF. "
15501  "Enable InnoDB checksums validation (enabled by default). "
15502  "Disable with --skip-innodb-checksums.",
15503  NULL, NULL, TRUE);
15504 
15505 static MYSQL_SYSVAR_STR(data_home_dir, innobase_data_home_dir,
15506  PLUGIN_VAR_READONLY,
15507  "The common part for InnoDB table spaces.",
15508  NULL, NULL, NULL);
15509 
15510 static MYSQL_SYSVAR_BOOL(doublewrite, innobase_use_doublewrite,
15511  PLUGIN_VAR_NOCMDARG | PLUGIN_VAR_READONLY,
15512  "Enable InnoDB doublewrite buffer (enabled by default). "
15513  "Disable with --skip-innodb-doublewrite.",
15514  NULL, NULL, TRUE);
15515 
15516 static MYSQL_SYSVAR_ULONG(io_capacity, srv_io_capacity,
15517  PLUGIN_VAR_RQCMDARG,
15518  "Number of IOPs the server can do. Tunes the background IO rate",
15519  NULL, innodb_io_capacity_update, 200, 100, ~0UL, 0);
15520 
15521 static MYSQL_SYSVAR_ULONG(io_capacity_max, srv_max_io_capacity,
15522  PLUGIN_VAR_RQCMDARG,
15523  "Limit to which innodb_io_capacity can be inflated.",
15524  NULL, innodb_io_capacity_max_update,
15525  SRV_MAX_IO_CAPACITY_DUMMY_DEFAULT, 100,
15526  SRV_MAX_IO_CAPACITY_LIMIT, 0);
15527 
15528 #ifdef UNIV_DEBUG
15529 static MYSQL_SYSVAR_BOOL(purge_run_now, innodb_purge_run_now,
15530  PLUGIN_VAR_OPCMDARG,
15531  "Set purge state to RUN",
15532  NULL, purge_run_now_set, FALSE);
15533 
15534 static MYSQL_SYSVAR_BOOL(purge_stop_now, innodb_purge_stop_now,
15535  PLUGIN_VAR_OPCMDARG,
15536  "Set purge state to STOP",
15537  NULL, purge_stop_now_set, FALSE);
15538 
15539 static MYSQL_SYSVAR_BOOL(log_checkpoint_now, innodb_log_checkpoint_now,
15540  PLUGIN_VAR_OPCMDARG,
15541  "Force checkpoint now",
15542  NULL, checkpoint_now_set, FALSE);
15543 #endif /* UNIV_DEBUG */
15544 
15545 static MYSQL_SYSVAR_ULONG(purge_batch_size, srv_purge_batch_size,
15546  PLUGIN_VAR_OPCMDARG,
15547  "Number of UNDO log pages to purge in one batch from the history list.",
15548  NULL, NULL,
15549  300, /* Default setting */
15550  1, /* Minimum value */
15551  5000, 0); /* Maximum value */
15552 
15553 static MYSQL_SYSVAR_ULONG(purge_threads, srv_n_purge_threads,
15554  PLUGIN_VAR_OPCMDARG | PLUGIN_VAR_READONLY,
15555  "Purge threads can be from 1 to 32. Default is 1.",
15556  NULL, NULL,
15557  1, /* Default setting */
15558  1, /* Minimum value */
15559  32, 0); /* Maximum value */
15560 
15561 static MYSQL_SYSVAR_ULONG(sync_array_size, srv_sync_array_size,
15562  PLUGIN_VAR_OPCMDARG | PLUGIN_VAR_READONLY,
15563  "Size of the mutex/lock wait array.",
15564  NULL, NULL,
15565  1, /* Default setting */
15566  1, /* Minimum value */
15567  1024, 0); /* Maximum value */
15568 
15569 static MYSQL_SYSVAR_ULONG(fast_shutdown, innobase_fast_shutdown,
15570  PLUGIN_VAR_OPCMDARG,
15571  "Speeds up the shutdown process of the InnoDB storage engine. Possible "
15572  "values are 0, 1 (faster) or 2 (fastest - crash-like).",
15573  NULL, NULL, 1, 0, 2, 0);
15574 
15575 static MYSQL_SYSVAR_BOOL(file_per_table, srv_file_per_table,
15576  PLUGIN_VAR_NOCMDARG,
15577  "Stores each InnoDB table to an .ibd file in the database dir.",
15578  NULL, NULL, TRUE);
15579 
15580 static MYSQL_SYSVAR_STR(file_format, innobase_file_format_name,
15581  PLUGIN_VAR_RQCMDARG,
15582  "File format to use for new tables in .ibd files.",
15583  innodb_file_format_name_validate,
15584  innodb_file_format_name_update, "Antelope");
15585 
15586 /* "innobase_file_format_check" decides whether we would continue
15587 booting the server if the file format stamped on the system
15588 table space exceeds the maximum file format supported
15589 by the server. Can be set during server startup at command
15590 line or configure file, and a read only variable after
15591 server startup */
15592 static MYSQL_SYSVAR_BOOL(file_format_check, innobase_file_format_check,
15593  PLUGIN_VAR_NOCMDARG | PLUGIN_VAR_READONLY,
15594  "Whether to perform system file format check.",
15595  NULL, NULL, TRUE);
15596 
15597 /* If a new file format is introduced, the file format
15598 name needs to be updated accordingly. Please refer to
15599 file_format_name_map[] defined in trx0sys.cc for the next
15600 file format name. */
15601 static MYSQL_SYSVAR_STR(file_format_max, innobase_file_format_max,
15602  PLUGIN_VAR_OPCMDARG,
15603  "The highest file format in the tablespace.",
15604  innodb_file_format_max_validate,
15605  innodb_file_format_max_update, "Antelope");
15606 
15607 static MYSQL_SYSVAR_STR(ft_server_stopword_table, innobase_server_stopword_table,
15608  PLUGIN_VAR_OPCMDARG,
15609  "The user supplied stopword table name.",
15610  innodb_stopword_table_validate,
15611  innodb_stopword_table_update,
15612  NULL);
15613 
15614 static MYSQL_SYSVAR_UINT(flush_log_at_timeout, srv_flush_log_at_timeout,
15615  PLUGIN_VAR_OPCMDARG,
15616  "Write and flush logs every (n) second.",
15617  NULL, NULL, 1, 0, 2700, 0);
15618 
15619 static MYSQL_SYSVAR_ULONG(flush_log_at_trx_commit, srv_flush_log_at_trx_commit,
15620  PLUGIN_VAR_OPCMDARG,
15621  "Set to 0 (write and flush once per second),"
15622  " 1 (write and flush at each commit)"
15623  " or 2 (write at commit, flush once per second).",
15624  NULL, NULL, 1, 0, 2, 0);
15625 
15626 static MYSQL_SYSVAR_STR(flush_method, innobase_file_flush_method,
15627  PLUGIN_VAR_RQCMDARG | PLUGIN_VAR_READONLY,
15628  "With which method to flush data.", NULL, NULL, NULL);
15629 
15630 static MYSQL_SYSVAR_BOOL(large_prefix, innobase_large_prefix,
15631  PLUGIN_VAR_NOCMDARG,
15632  "Support large index prefix length of REC_VERSION_56_MAX_INDEX_COL_LEN (3072) bytes.",
15633  NULL, NULL, FALSE);
15634 
15635 static MYSQL_SYSVAR_BOOL(force_load_corrupted, srv_load_corrupted,
15636  PLUGIN_VAR_NOCMDARG | PLUGIN_VAR_READONLY,
15637  "Force InnoDB to load metadata of corrupted table.",
15638  NULL, NULL, FALSE);
15639 
15640 static MYSQL_SYSVAR_BOOL(locks_unsafe_for_binlog, innobase_locks_unsafe_for_binlog,
15641  PLUGIN_VAR_NOCMDARG | PLUGIN_VAR_READONLY,
15642  "DEPRECATED. This option may be removed in future releases. "
15643  "Please use READ COMMITTED transaction isolation level instead. "
15644  "Force InnoDB to not use next-key locking, to use only row-level locking.",
15645  NULL, NULL, FALSE);
15646 
15647 #ifdef UNIV_LOG_ARCHIVE
15648 static MYSQL_SYSVAR_STR(log_arch_dir, innobase_log_arch_dir,
15649  PLUGIN_VAR_RQCMDARG | PLUGIN_VAR_READONLY,
15650  "Where full logs should be archived.", NULL, NULL, NULL);
15651 
15652 static MYSQL_SYSVAR_BOOL(log_archive, innobase_log_archive,
15653  PLUGIN_VAR_OPCMDARG | PLUGIN_VAR_READONLY,
15654  "Set to 1 if you want to have logs archived.", NULL, NULL, FALSE);
15655 #endif /* UNIV_LOG_ARCHIVE */
15656 
15657 static MYSQL_SYSVAR_STR(log_group_home_dir, srv_log_group_home_dir,
15658  PLUGIN_VAR_RQCMDARG | PLUGIN_VAR_READONLY,
15659  "Path to InnoDB log files.", NULL, NULL, NULL);
15660 
15661 static MYSQL_SYSVAR_ULONG(max_dirty_pages_pct, srv_max_buf_pool_modified_pct,
15662  PLUGIN_VAR_RQCMDARG,
15663  "Percentage of dirty pages allowed in bufferpool.",
15664  NULL, innodb_max_dirty_pages_pct_update, 75, 0, 99, 0);
15665 
15666 static MYSQL_SYSVAR_ULONG(max_dirty_pages_pct_lwm,
15667  srv_max_dirty_pages_pct_lwm,
15668  PLUGIN_VAR_RQCMDARG,
15669  "Percentage of dirty pages at which flushing kicks in.",
15670  NULL, innodb_max_dirty_pages_pct_lwm_update, 0, 0, 99, 0);
15671 
15672 static MYSQL_SYSVAR_ULONG(adaptive_flushing_lwm,
15673  srv_adaptive_flushing_lwm,
15674  PLUGIN_VAR_RQCMDARG,
15675  "Percentage of log capacity below which no adaptive flushing happens.",
15676  NULL, NULL, 10, 0, 70, 0);
15677 
15678 static MYSQL_SYSVAR_BOOL(adaptive_flushing, srv_adaptive_flushing,
15679  PLUGIN_VAR_NOCMDARG,
15680  "Attempt flushing dirty pages to avoid IO bursts at checkpoints.",
15681  NULL, NULL, TRUE);
15682 
15683 static MYSQL_SYSVAR_ULONG(flushing_avg_loops,
15684  srv_flushing_avg_loops,
15685  PLUGIN_VAR_RQCMDARG,
15686  "Number of iterations over which the background flushing is averaged.",
15687  NULL, NULL, 30, 1, 1000, 0);
15688 
15689 static MYSQL_SYSVAR_ULONG(max_purge_lag, srv_max_purge_lag,
15690  PLUGIN_VAR_RQCMDARG,
15691  "Desired maximum length of the purge queue (0 = no limit)",
15692  NULL, NULL, 0, 0, ~0UL, 0);
15693 
15694 static MYSQL_SYSVAR_ULONG(max_purge_lag_delay, srv_max_purge_lag_delay,
15695  PLUGIN_VAR_RQCMDARG,
15696  "Maximum delay of user threads in micro-seconds",
15697  NULL, NULL,
15698  0L, /* Default seting */
15699  0L, /* Minimum value */
15700  10000000UL, 0); /* Maximum value */
15701 
15702 static MYSQL_SYSVAR_BOOL(rollback_on_timeout, innobase_rollback_on_timeout,
15703  PLUGIN_VAR_OPCMDARG | PLUGIN_VAR_READONLY,
15704  "Roll back the complete transaction on lock wait timeout, for 4.x compatibility (disabled by default)",
15705  NULL, NULL, FALSE);
15706 
15707 static MYSQL_SYSVAR_BOOL(status_file, innobase_create_status_file,
15708  PLUGIN_VAR_OPCMDARG | PLUGIN_VAR_NOSYSVAR,
15709  "Enable SHOW ENGINE INNODB STATUS output in the innodb_status.<pid> file",
15710  NULL, NULL, FALSE);
15711 
15712 static MYSQL_SYSVAR_BOOL(stats_on_metadata, innobase_stats_on_metadata,
15713  PLUGIN_VAR_OPCMDARG,
15714  "Enable statistics gathering for metadata commands such as "
15715  "SHOW TABLE STATUS for tables that use transient statistics (off by default)",
15716  NULL, NULL, FALSE);
15717 
15718 static MYSQL_SYSVAR_ULONGLONG(stats_sample_pages, srv_stats_transient_sample_pages,
15719  PLUGIN_VAR_RQCMDARG,
15720  "Deprecated, use innodb_stats_transient_sample_pages instead",
15721  NULL, innodb_stats_sample_pages_update, 8, 1, ~0ULL, 0);
15722 
15723 static MYSQL_SYSVAR_ULONGLONG(stats_transient_sample_pages,
15724  srv_stats_transient_sample_pages,
15725  PLUGIN_VAR_RQCMDARG,
15726  "The number of leaf index pages to sample when calculating transient "
15727  "statistics (if persistent statistics are not used, default 8)",
15728  NULL, NULL, 8, 1, ~0ULL, 0);
15729 
15730 static MYSQL_SYSVAR_BOOL(stats_persistent, srv_stats_persistent,
15731  PLUGIN_VAR_OPCMDARG,
15732  "InnoDB persistent statistics enabled for all tables unless overridden "
15733  "at table level",
15734  NULL, NULL, TRUE);
15735 
15736 static MYSQL_SYSVAR_BOOL(stats_auto_recalc, srv_stats_auto_recalc,
15737  PLUGIN_VAR_OPCMDARG,
15738  "InnoDB automatic recalculation of persistent statistics enabled for all "
15739  "tables unless overridden at table level (automatic recalculation is only "
15740  "done when InnoDB decides that the table has changed too much and needs a "
15741  "new statistics)",
15742  NULL, NULL, TRUE);
15743 
15744 static MYSQL_SYSVAR_ULONGLONG(stats_persistent_sample_pages,
15745  srv_stats_persistent_sample_pages,
15746  PLUGIN_VAR_RQCMDARG,
15747  "The number of leaf index pages to sample when calculating persistent "
15748  "statistics (by ANALYZE, default 20)",
15749  NULL, NULL, 20, 1, ~0ULL, 0);
15750 
15751 static MYSQL_SYSVAR_BOOL(adaptive_hash_index, btr_search_enabled,
15752  PLUGIN_VAR_OPCMDARG,
15753  "Enable InnoDB adaptive hash index (enabled by default). "
15754  "Disable with --skip-innodb-adaptive-hash-index.",
15755  NULL, innodb_adaptive_hash_index_update, TRUE);
15756 
15757 static MYSQL_SYSVAR_ULONG(replication_delay, srv_replication_delay,
15758  PLUGIN_VAR_RQCMDARG,
15759  "Replication thread delay (ms) on the slave server if "
15760  "innodb_thread_concurrency is reached (0 by default)",
15761  NULL, NULL, 0, 0, ~0UL, 0);
15762 
15763 static MYSQL_SYSVAR_UINT(compression_level, page_zip_level,
15764  PLUGIN_VAR_RQCMDARG,
15765  "Compression level used for compressed row format. 0 is no compression"
15766  ", 1 is fastest, 9 is best compression and default is 6.",
15767  NULL, NULL, DEFAULT_COMPRESSION_LEVEL, 0, 9, 0);
15768 
15769 static MYSQL_SYSVAR_BOOL(log_compressed_pages, page_zip_log_pages,
15770  PLUGIN_VAR_OPCMDARG,
15771  "Enables/disables the logging of entire compressed page images."
15772  " InnoDB logs the compressed pages to prevent corruption if"
15773  " the zlib compression algorithm changes."
15774  " When turned OFF, InnoDB will assume that the zlib"
15775  " compression algorithm doesn't change.",
15776  NULL, NULL, TRUE);
15777 
15778 static MYSQL_SYSVAR_LONG(additional_mem_pool_size, innobase_additional_mem_pool_size,
15779  PLUGIN_VAR_RQCMDARG | PLUGIN_VAR_READONLY,
15780  "DEPRECATED. This option may be removed in future releases, "
15781  "together with the option innodb_use_sys_malloc and with the InnoDB's "
15782  "internal memory allocator. "
15783  "Size of a memory pool InnoDB uses to store data dictionary information and other internal data structures.",
15784  NULL, NULL, 8*1024*1024L, 512*1024L, LONG_MAX, 1024);
15785 
15786 static MYSQL_SYSVAR_ULONG(autoextend_increment, srv_auto_extend_increment,
15787  PLUGIN_VAR_RQCMDARG,
15788  "Data file autoextend increment in megabytes",
15789  NULL, NULL, 64L, 1L, 1000L, 0);
15790 
15791 static MYSQL_SYSVAR_LONGLONG(buffer_pool_size, innobase_buffer_pool_size,
15792  PLUGIN_VAR_RQCMDARG | PLUGIN_VAR_READONLY,
15793  "The size of the memory buffer InnoDB uses to cache data and indexes of its tables.",
15794  NULL, NULL, 128*1024*1024L, 5*1024*1024L, LONGLONG_MAX, 1024*1024L);
15795 
15796 #if defined UNIV_DEBUG || defined UNIV_PERF_DEBUG
15797 static MYSQL_SYSVAR_ULONG(page_hash_locks, srv_n_page_hash_locks,
15798  PLUGIN_VAR_OPCMDARG | PLUGIN_VAR_READONLY,
15799  "Number of rw_locks protecting buffer pool page_hash. Rounded up to the next power of 2",
15800  NULL, NULL, 16, 1, MAX_PAGE_HASH_LOCKS, 0);
15801 
15802 static MYSQL_SYSVAR_ULONG(doublewrite_batch_size, srv_doublewrite_batch_size,
15803  PLUGIN_VAR_OPCMDARG | PLUGIN_VAR_READONLY,
15804  "Number of pages reserved in doublewrite buffer for batch flushing",
15805  NULL, NULL, 120, 1, 127, 0);
15806 #endif /* defined UNIV_DEBUG || defined UNIV_PERF_DEBUG */
15807 
15808 static MYSQL_SYSVAR_LONG(buffer_pool_instances, innobase_buffer_pool_instances,
15809  PLUGIN_VAR_RQCMDARG | PLUGIN_VAR_READONLY,
15810  "Number of buffer pool instances, set to higher value on high-end machines to increase scalability",
15811  NULL, NULL, 0L, 0L, MAX_BUFFER_POOLS, 1L);
15812 
15813 static MYSQL_SYSVAR_STR(buffer_pool_filename, srv_buf_dump_filename,
15814  PLUGIN_VAR_RQCMDARG | PLUGIN_VAR_MEMALLOC,
15815  "Filename to/from which to dump/load the InnoDB buffer pool",
15816  innodb_srv_buf_dump_filename_validate, NULL, SRV_BUF_DUMP_FILENAME_DEFAULT);
15817 
15818 static MYSQL_SYSVAR_BOOL(buffer_pool_dump_now, innodb_buffer_pool_dump_now,
15819  PLUGIN_VAR_RQCMDARG,
15820  "Trigger an immediate dump of the buffer pool into a file named @@innodb_buffer_pool_filename",
15821  NULL, buffer_pool_dump_now, FALSE);
15822 
15823 static MYSQL_SYSVAR_BOOL(buffer_pool_dump_at_shutdown, srv_buffer_pool_dump_at_shutdown,
15824  PLUGIN_VAR_RQCMDARG,
15825  "Dump the buffer pool into a file named @@innodb_buffer_pool_filename",
15826  NULL, NULL, FALSE);
15827 
15828 #ifdef UNIV_DEBUG
15829 static MYSQL_SYSVAR_STR(buffer_pool_evict, srv_buffer_pool_evict,
15830  PLUGIN_VAR_RQCMDARG,
15831  "Evict pages from the buffer pool",
15832  NULL, innodb_buffer_pool_evict_update, "");
15833 #endif /* UNIV_DEBUG */
15834 
15835 static MYSQL_SYSVAR_BOOL(buffer_pool_load_now, innodb_buffer_pool_load_now,
15836  PLUGIN_VAR_RQCMDARG,
15837  "Trigger an immediate load of the buffer pool from a file named @@innodb_buffer_pool_filename",
15838  NULL, buffer_pool_load_now, FALSE);
15839 
15840 static MYSQL_SYSVAR_BOOL(buffer_pool_load_abort, innodb_buffer_pool_load_abort,
15841  PLUGIN_VAR_RQCMDARG,
15842  "Abort a currently running load of the buffer pool",
15843  NULL, buffer_pool_load_abort, FALSE);
15844 
15845 /* there is no point in changing this during runtime, thus readonly */
15846 static MYSQL_SYSVAR_BOOL(buffer_pool_load_at_startup, srv_buffer_pool_load_at_startup,
15847  PLUGIN_VAR_RQCMDARG | PLUGIN_VAR_READONLY,
15848  "Load the buffer pool from a file named @@innodb_buffer_pool_filename",
15849  NULL, NULL, FALSE);
15850 
15851 static MYSQL_SYSVAR_ULONG(lru_scan_depth, srv_LRU_scan_depth,
15852  PLUGIN_VAR_RQCMDARG,
15853  "How deep to scan LRU to keep it clean",
15854  NULL, NULL, 1024, 100, ~0UL, 0);
15855 
15856 static MYSQL_SYSVAR_ULONG(flush_neighbors, srv_flush_neighbors,
15857  PLUGIN_VAR_OPCMDARG,
15858  "Set to 0 (don't flush neighbors from buffer pool),"
15859  " 1 (flush contiguous neighbors from buffer pool)"
15860  " or 2 (flush neighbors from buffer pool),"
15861  " when flushing a block",
15862  NULL, NULL, 1, 0, 2, 0);
15863 
15864 static MYSQL_SYSVAR_ULONG(commit_concurrency, innobase_commit_concurrency,
15865  PLUGIN_VAR_RQCMDARG,
15866  "Helps in performance tuning in heavily concurrent environments.",
15867  innobase_commit_concurrency_validate, NULL, 0, 0, 1000, 0);
15868 
15869 static MYSQL_SYSVAR_ULONG(concurrency_tickets, srv_n_free_tickets_to_enter,
15870  PLUGIN_VAR_RQCMDARG,
15871  "Number of times a thread is allowed to enter InnoDB within the same SQL query after it has once got the ticket",
15872  NULL, NULL, 5000L, 1L, ~0UL, 0);
15873 
15874 static MYSQL_SYSVAR_LONG(file_io_threads, innobase_file_io_threads,
15875  PLUGIN_VAR_RQCMDARG | PLUGIN_VAR_READONLY | PLUGIN_VAR_NOSYSVAR,
15876  "Number of file I/O threads in InnoDB.",
15877  NULL, NULL, 4, 4, 64, 0);
15878 
15879 static MYSQL_SYSVAR_BOOL(ft_enable_diag_print, fts_enable_diag_print,
15880  PLUGIN_VAR_OPCMDARG,
15881  "Whether to enable additional FTS diagnostic printout ",
15882  NULL, NULL, FALSE);
15883 
15884 static MYSQL_SYSVAR_BOOL(disable_sort_file_cache, srv_disable_sort_file_cache,
15885  PLUGIN_VAR_OPCMDARG,
15886  "Whether to disable OS system file cache for sort I/O",
15887  NULL, NULL, FALSE);
15888 
15889 static MYSQL_SYSVAR_STR(ft_aux_table, fts_internal_tbl_name,
15890  PLUGIN_VAR_NOCMDARG,
15891  "FTS internal auxiliary table to be checked",
15892  innodb_internal_table_validate,
15893  innodb_internal_table_update, NULL);
15894 
15895 static MYSQL_SYSVAR_ULONG(ft_cache_size, fts_max_cache_size,
15896  PLUGIN_VAR_RQCMDARG | PLUGIN_VAR_READONLY,
15897  "InnoDB Fulltext search cache size in bytes",
15898  NULL, NULL, 8000000, 1600000, 80000000, 0);
15899 
15900 static MYSQL_SYSVAR_ULONG(ft_total_cache_size, fts_max_total_cache_size,
15901  PLUGIN_VAR_RQCMDARG | PLUGIN_VAR_READONLY,
15902  "Total memory allocated for InnoDB Fulltext Search cache",
15903  NULL, NULL, 640000000, 32000000, 1600000000, 0);
15904 
15905 static MYSQL_SYSVAR_ULONG(ft_result_cache_limit, fts_result_cache_limit,
15906  PLUGIN_VAR_RQCMDARG,
15907  "InnoDB Fulltext search query result cache limit in bytes",
15908  NULL, NULL, 2000000000L, 1000000L, ~0UL, 0);
15909 
15910 static MYSQL_SYSVAR_ULONG(ft_min_token_size, fts_min_token_size,
15911  PLUGIN_VAR_RQCMDARG | PLUGIN_VAR_READONLY,
15912  "InnoDB Fulltext search minimum token size in characters",
15913  NULL, NULL, 3, 0, 16, 0);
15914 
15915 static MYSQL_SYSVAR_ULONG(ft_max_token_size, fts_max_token_size,
15916  PLUGIN_VAR_RQCMDARG | PLUGIN_VAR_READONLY,
15917  "InnoDB Fulltext search maximum token size in characters",
15919 
15920 
15921 static MYSQL_SYSVAR_ULONG(ft_num_word_optimize, fts_num_word_optimize,
15922  PLUGIN_VAR_OPCMDARG,
15923  "InnoDB Fulltext search number of words to optimize for each optimize table call ",
15924  NULL, NULL, 2000, 1000, 10000, 0);
15925 
15926 static MYSQL_SYSVAR_ULONG(ft_sort_pll_degree, fts_sort_pll_degree,
15927  PLUGIN_VAR_RQCMDARG | PLUGIN_VAR_READONLY,
15928  "InnoDB Fulltext search parallel sort degree, will round up to nearest power of 2 number",
15929  NULL, NULL, 2, 1, 16, 0);
15930 
15931 static MYSQL_SYSVAR_ULONG(sort_buffer_size, srv_sort_buf_size,
15932  PLUGIN_VAR_RQCMDARG | PLUGIN_VAR_READONLY,
15933  "Memory buffer size for index creation",
15934  NULL, NULL, 1048576, 65536, 64<<20, 0);
15935 
15936 static MYSQL_SYSVAR_ULONGLONG(online_alter_log_max_size, srv_online_max_size,
15937  PLUGIN_VAR_RQCMDARG,
15938  "Maximum modification log file size for online index creation",
15939  NULL, NULL, 128<<20, 65536, ~0ULL, 0);
15940 
15941 static MYSQL_SYSVAR_BOOL(optimize_fulltext_only, innodb_optimize_fulltext_only,
15942  PLUGIN_VAR_NOCMDARG,
15943  "Only optimize the Fulltext index of the table",
15944  NULL, NULL, FALSE);
15945 
15946 static MYSQL_SYSVAR_ULONG(read_io_threads, innobase_read_io_threads,
15947  PLUGIN_VAR_RQCMDARG | PLUGIN_VAR_READONLY,
15948  "Number of background read I/O threads in InnoDB.",
15949  NULL, NULL, 4, 1, 64, 0);
15950 
15951 static MYSQL_SYSVAR_ULONG(write_io_threads, innobase_write_io_threads,
15952  PLUGIN_VAR_RQCMDARG | PLUGIN_VAR_READONLY,
15953  "Number of background write I/O threads in InnoDB.",
15954  NULL, NULL, 4, 1, 64, 0);
15955 
15956 static MYSQL_SYSVAR_ULONG(force_recovery, srv_force_recovery,
15957  PLUGIN_VAR_RQCMDARG | PLUGIN_VAR_READONLY,
15958  "Helps to save your data in case the disk image of the database becomes corrupt.",
15959  NULL, NULL, 0, 0, 6, 0);
15960 
15961 #ifndef DBUG_OFF
15962 static MYSQL_SYSVAR_ULONG(force_recovery_crash, srv_force_recovery_crash,
15963  PLUGIN_VAR_RQCMDARG | PLUGIN_VAR_READONLY,
15964  "Kills the server during crash recovery.",
15965  NULL, NULL, 0, 0, 10, 0);
15966 #endif /* !DBUG_OFF */
15967 
15968 static MYSQL_SYSVAR_ULONG(page_size, srv_page_size,
15969  PLUGIN_VAR_OPCMDARG | PLUGIN_VAR_READONLY,
15970  "Page size to use for all InnoDB tablespaces.",
15971  NULL, NULL, UNIV_PAGE_SIZE_DEF,
15972  UNIV_PAGE_SIZE_MIN, UNIV_PAGE_SIZE_MAX, 0);
15973 
15974 static MYSQL_SYSVAR_LONG(log_buffer_size, innobase_log_buffer_size,
15975  PLUGIN_VAR_RQCMDARG | PLUGIN_VAR_READONLY,
15976  "The size of the buffer which InnoDB uses to write log to the log files on disk.",
15977  NULL, NULL, 8*1024*1024L, 256*1024L, LONG_MAX, 1024);
15978 
15979 static MYSQL_SYSVAR_LONGLONG(log_file_size, innobase_log_file_size,
15980  PLUGIN_VAR_RQCMDARG | PLUGIN_VAR_READONLY,
15981  "Size of each log file in a log group.",
15982  NULL, NULL, 48*1024*1024L, 1*1024*1024L, LONGLONG_MAX, 1024*1024L);
15983 
15984 static MYSQL_SYSVAR_ULONG(log_files_in_group, srv_n_log_files,
15985  PLUGIN_VAR_RQCMDARG | PLUGIN_VAR_READONLY,
15986  "Number of log files in the log group. InnoDB writes to the files in a circular fashion.",
15987  NULL, NULL, 2, 2, SRV_N_LOG_FILES_MAX, 0);
15988 
15989 /* Note that the default and minimum values are set to 0 to
15990 detect if the option is passed and print deprecation message */
15991 static MYSQL_SYSVAR_LONG(mirrored_log_groups, innobase_mirrored_log_groups,
15992  PLUGIN_VAR_RQCMDARG | PLUGIN_VAR_READONLY,
15993  "Number of identical copies of log groups we keep for the database. Currently this should be set to 1.",
15994  NULL, NULL, 0, 0, 10, 0);
15995 
15996 static MYSQL_SYSVAR_UINT(old_blocks_pct, innobase_old_blocks_pct,
15997  PLUGIN_VAR_RQCMDARG,
15998  "Percentage of the buffer pool to reserve for 'old' blocks.",
15999  NULL, innodb_old_blocks_pct_update, 100 * 3 / 8, 5, 95, 0);
16000 
16001 static MYSQL_SYSVAR_UINT(old_blocks_time, buf_LRU_old_threshold_ms,
16002  PLUGIN_VAR_RQCMDARG,
16003  "Move blocks to the 'new' end of the buffer pool if the first access"
16004  " was at least this many milliseconds ago."
16005  " The timeout is disabled if 0.",
16006  NULL, NULL, 1000, 0, UINT_MAX32, 0);
16007 
16008 static MYSQL_SYSVAR_LONG(open_files, innobase_open_files,
16009  PLUGIN_VAR_RQCMDARG | PLUGIN_VAR_READONLY,
16010  "How many files at the maximum InnoDB keeps open at the same time.",
16011  NULL, NULL, 0L, 0L, LONG_MAX, 0);
16012 
16013 static MYSQL_SYSVAR_ULONG(sync_spin_loops, srv_n_spin_wait_rounds,
16014  PLUGIN_VAR_RQCMDARG,
16015  "Count of spin-loop rounds in InnoDB mutexes (30 by default)",
16016  NULL, NULL, 30L, 0L, ~0UL, 0);
16017 
16018 static MYSQL_SYSVAR_ULONG(spin_wait_delay, srv_spin_wait_delay,
16019  PLUGIN_VAR_OPCMDARG,
16020  "Maximum delay between polling for a spin lock (6 by default)",
16021  NULL, NULL, 6L, 0L, ~0UL, 0);
16022 
16023 static MYSQL_SYSVAR_ULONG(thread_concurrency, srv_thread_concurrency,
16024  PLUGIN_VAR_RQCMDARG,
16025  "Helps in performance tuning in heavily concurrent environments. Sets the maximum number of threads allowed inside InnoDB. Value 0 will disable the thread throttling.",
16026  NULL, NULL, 0, 0, 1000, 0);
16027 
16028 #ifdef HAVE_ATOMIC_BUILTINS
16029 static MYSQL_SYSVAR_ULONG(
16030  adaptive_max_sleep_delay, srv_adaptive_max_sleep_delay,
16031  PLUGIN_VAR_RQCMDARG,
16032  "The upper limit of the sleep delay in usec. Value of 0 disables it.",
16033  NULL, NULL,
16034  150000, /* Default setting */
16035  0, /* Minimum value */
16036  1000000, 0); /* Maximum value */
16037 #endif /* HAVE_ATOMIC_BUILTINS */
16038 
16039 static MYSQL_SYSVAR_ULONG(thread_sleep_delay, srv_thread_sleep_delay,
16040  PLUGIN_VAR_RQCMDARG,
16041  "Time of innodb thread sleeping before joining InnoDB queue (usec). "
16042  "Value 0 disable a sleep",
16043  NULL, NULL,
16044  10000L,
16045  0L,
16046  ~0UL, 0);
16047 
16048 static MYSQL_SYSVAR_STR(data_file_path, innobase_data_file_path,
16049  PLUGIN_VAR_RQCMDARG | PLUGIN_VAR_READONLY,
16050  "Path to individual files and their sizes.",
16051  NULL, NULL, NULL);
16052 
16053 static MYSQL_SYSVAR_STR(undo_directory, srv_undo_dir,
16054  PLUGIN_VAR_RQCMDARG | PLUGIN_VAR_READONLY,
16055  "Directory where undo tablespace files live, this path can be absolute.",
16056  NULL, NULL, ".");
16057 
16058 static MYSQL_SYSVAR_ULONG(undo_tablespaces, srv_undo_tablespaces,
16059  PLUGIN_VAR_RQCMDARG | PLUGIN_VAR_READONLY,
16060  "Number of undo tablespaces to use. ",
16061  NULL, NULL,
16062  0L, /* Default seting */
16063  0L, /* Minimum value */
16064  126L, 0); /* Maximum value */
16065 
16066 static MYSQL_SYSVAR_ULONG(undo_logs, srv_undo_logs,
16067  PLUGIN_VAR_OPCMDARG,
16068  "Number of undo logs to use.",
16069  NULL, NULL,
16070  TRX_SYS_N_RSEGS, /* Default setting */
16071  1, /* Minimum value */
16072  TRX_SYS_N_RSEGS, 0); /* Maximum value */
16073 
16074 /* Alias for innodb_undo_logs, this config variable is deprecated. */
16075 static MYSQL_SYSVAR_ULONG(rollback_segments, srv_undo_logs,
16076  PLUGIN_VAR_OPCMDARG,
16077  "Number of undo logs to use (deprecated).",
16078  NULL, NULL,
16079  TRX_SYS_N_RSEGS, /* Default setting */
16080  1, /* Minimum value */
16081  TRX_SYS_N_RSEGS, 0); /* Maximum value */
16082 
16083 static MYSQL_SYSVAR_LONG(autoinc_lock_mode, innobase_autoinc_lock_mode,
16084  PLUGIN_VAR_RQCMDARG | PLUGIN_VAR_READONLY,
16085  "The AUTOINC lock modes supported by InnoDB: "
16086  "0 => Old style AUTOINC locking (for backward"
16087  " compatibility) "
16088  "1 => New style AUTOINC locking "
16089  "2 => No AUTOINC locking (unsafe for SBR)",
16090  NULL, NULL,
16091  AUTOINC_NEW_STYLE_LOCKING, /* Default setting */
16092  AUTOINC_OLD_STYLE_LOCKING, /* Minimum value */
16093  AUTOINC_NO_LOCKING, 0); /* Maximum value */
16094 
16095 static MYSQL_SYSVAR_STR(version, innodb_version_str,
16096  PLUGIN_VAR_NOCMDOPT | PLUGIN_VAR_READONLY,
16097  "InnoDB version", NULL, NULL, INNODB_VERSION_STR);
16098 
16099 static MYSQL_SYSVAR_BOOL(use_sys_malloc, srv_use_sys_malloc,
16100  PLUGIN_VAR_NOCMDARG | PLUGIN_VAR_READONLY,
16101  "DEPRECATED. This option may be removed in future releases, "
16102  "together with the InnoDB's internal memory allocator. "
16103  "Use OS memory allocator instead of InnoDB's internal memory allocator",
16104  NULL, NULL, TRUE);
16105 
16106 static MYSQL_SYSVAR_BOOL(use_native_aio, srv_use_native_aio,
16107  PLUGIN_VAR_NOCMDARG | PLUGIN_VAR_READONLY,
16108  "Use native AIO if supported on this platform.",
16109  NULL, NULL, TRUE);
16110 
16111 static MYSQL_SYSVAR_BOOL(api_enable_binlog, ib_binlog_enabled,
16112  PLUGIN_VAR_NOCMDARG | PLUGIN_VAR_READONLY,
16113  "Enable binlog for applications direct access InnoDB through InnoDB APIs",
16114  NULL, NULL, FALSE);
16115 
16116 static MYSQL_SYSVAR_BOOL(api_enable_mdl, ib_mdl_enabled,
16117  PLUGIN_VAR_NOCMDARG | PLUGIN_VAR_READONLY,
16118  "Enable MDL for applications direct access InnoDB through InnoDB APIs",
16119  NULL, NULL, FALSE);
16120 
16121 static MYSQL_SYSVAR_BOOL(api_disable_rowlock, ib_disable_row_lock,
16122  PLUGIN_VAR_NOCMDARG | PLUGIN_VAR_READONLY,
16123  "Disable row lock when direct access InnoDB through InnoDB APIs",
16124  NULL, NULL, FALSE);
16125 
16126 static MYSQL_SYSVAR_ULONG(api_trx_level, ib_trx_level_setting,
16127  PLUGIN_VAR_OPCMDARG,
16128  "InnoDB API transaction isolation level",
16129  NULL, NULL,
16130  0, /* Default setting */
16131  0, /* Minimum value */
16132  3, 0); /* Maximum value */
16133 
16134 static MYSQL_SYSVAR_ULONG(api_bk_commit_interval, ib_bk_commit_interval,
16135  PLUGIN_VAR_OPCMDARG,
16136  "Background commit interval in seconds",
16137  NULL, NULL,
16138  5, /* Default setting */
16139  1, /* Minimum value */
16140  1024 * 1024 * 1024, 0); /* Maximum value */
16141 
16142 static MYSQL_SYSVAR_STR(change_buffering, innobase_change_buffering,
16143  PLUGIN_VAR_RQCMDARG,
16144  "Buffer changes to reduce random access: "
16145  "OFF, ON, inserting, deleting, changing, or purging.",
16146  innodb_change_buffering_validate,
16147  innodb_change_buffering_update, "all");
16148 
16149 static MYSQL_SYSVAR_UINT(change_buffer_max_size,
16150  innobase_change_buffer_max_size,
16151  PLUGIN_VAR_RQCMDARG,
16152  "Maximum on-disk size of change buffer in terms of percentage"
16153  " of the buffer pool.",
16154  NULL, innodb_change_buffer_max_size_update,
16155  CHANGE_BUFFER_DEFAULT_SIZE, 0, 50, 0);
16156 
16157 static MYSQL_SYSVAR_ENUM(stats_method, srv_innodb_stats_method,
16158  PLUGIN_VAR_RQCMDARG,
16159  "Specifies how InnoDB index statistics collection code should "
16160  "treat NULLs. Possible values are NULLS_EQUAL (default), "
16161  "NULLS_UNEQUAL and NULLS_IGNORED",
16162  NULL, NULL, SRV_STATS_NULLS_EQUAL, &innodb_stats_method_typelib);
16163 
16164 #if defined UNIV_DEBUG || defined UNIV_IBUF_DEBUG
16165 static MYSQL_SYSVAR_UINT(change_buffering_debug, ibuf_debug,
16166  PLUGIN_VAR_RQCMDARG,
16167  "Debug flags for InnoDB change buffering (0=none, 2=crash at merge)",
16168  NULL, NULL, 0, 0, 2, 0);
16169 
16170 static MYSQL_SYSVAR_BOOL(disable_background_merge,
16171  srv_ibuf_disable_background_merge,
16172  PLUGIN_VAR_NOCMDARG | PLUGIN_VAR_RQCMDARG,
16173  "Disable change buffering merges by the master thread",
16174  NULL, NULL, FALSE);
16175 #endif /* UNIV_DEBUG || UNIV_IBUF_DEBUG */
16176 
16177 static MYSQL_SYSVAR_BOOL(random_read_ahead, srv_random_read_ahead,
16178  PLUGIN_VAR_NOCMDARG,
16179  "Whether to use read ahead for random access within an extent.",
16180  NULL, NULL, FALSE);
16181 
16182 static MYSQL_SYSVAR_ULONG(read_ahead_threshold, srv_read_ahead_threshold,
16183  PLUGIN_VAR_RQCMDARG,
16184  "Number of pages that must be accessed sequentially for InnoDB to "
16185  "trigger a readahead.",
16186  NULL, NULL, 56, 0, 64, 0);
16187 
16188 static MYSQL_SYSVAR_STR(monitor_enable, innobase_enable_monitor_counter,
16189  PLUGIN_VAR_RQCMDARG,
16190  "Turn on a monitor counter",
16191  innodb_monitor_validate,
16192  innodb_enable_monitor_update, NULL);
16193 
16194 static MYSQL_SYSVAR_STR(monitor_disable, innobase_disable_monitor_counter,
16195  PLUGIN_VAR_RQCMDARG,
16196  "Turn off a monitor counter",
16197  innodb_monitor_validate,
16198  innodb_disable_monitor_update, NULL);
16199 
16200 static MYSQL_SYSVAR_STR(monitor_reset, innobase_reset_monitor_counter,
16201  PLUGIN_VAR_RQCMDARG,
16202  "Reset a monitor counter",
16203  innodb_monitor_validate,
16204  innodb_reset_monitor_update, NULL);
16205 
16206 static MYSQL_SYSVAR_STR(monitor_reset_all, innobase_reset_all_monitor_counter,
16207  PLUGIN_VAR_RQCMDARG,
16208  "Reset all values for a monitor counter",
16209  innodb_monitor_validate,
16210  innodb_reset_all_monitor_update, NULL);
16211 
16212 static MYSQL_SYSVAR_BOOL(print_all_deadlocks, srv_print_all_deadlocks,
16213  PLUGIN_VAR_OPCMDARG,
16214  "Print all deadlocks to MySQL error log (off by default)",
16215  NULL, NULL, FALSE);
16216 
16217 static MYSQL_SYSVAR_ULONG(compression_failure_threshold_pct,
16218  zip_failure_threshold_pct, PLUGIN_VAR_OPCMDARG,
16219  "If the compression failure rate of a table is greater than this number"
16220  " more padding is added to the pages to reduce the failures. A value of"
16221  " zero implies no padding",
16222  NULL, NULL, 5, 0, 100, 0);
16223 
16224 static MYSQL_SYSVAR_ULONG(compression_pad_pct_max,
16225  zip_pad_max, PLUGIN_VAR_OPCMDARG,
16226  "Percentage of empty space on a data page that can be reserved"
16227  " to make the page compressible.",
16228  NULL, NULL, 50, 0, 75, 0);
16229 
16230 static MYSQL_SYSVAR_BOOL(read_only, srv_read_only_mode,
16231  PLUGIN_VAR_OPCMDARG | PLUGIN_VAR_READONLY,
16232  "Start InnoDB in read only mode (off by default)",
16233  NULL, NULL, FALSE);
16234 
16235 static MYSQL_SYSVAR_BOOL(cmp_per_index_enabled, srv_cmp_per_index_enabled,
16236  PLUGIN_VAR_OPCMDARG,
16237  "Enable INFORMATION_SCHEMA.innodb_cmp_per_index, "
16238  "may have negative impact on performance (off by default)",
16239  NULL, innodb_cmp_per_index_update, FALSE);
16240 
16241 #ifdef UNIV_DEBUG
16242 static MYSQL_SYSVAR_UINT(trx_rseg_n_slots_debug, trx_rseg_n_slots_debug,
16243  PLUGIN_VAR_RQCMDARG,
16244  "Debug flags for InnoDB to limit TRX_RSEG_N_SLOTS for trx_rsegf_undo_find_free()",
16245  NULL, NULL, 0, 0, 1024, 0);
16246 
16247 static MYSQL_SYSVAR_UINT(limit_optimistic_insert_debug,
16248  btr_cur_limit_optimistic_insert_debug, PLUGIN_VAR_RQCMDARG,
16249  "Artificially limit the number of records per B-tree page (0=unlimited).",
16250  NULL, NULL, 0, 0, UINT_MAX32, 0);
16251 
16252 static MYSQL_SYSVAR_BOOL(trx_purge_view_update_only_debug,
16253  srv_purge_view_update_only_debug, PLUGIN_VAR_NOCMDARG,
16254  "Pause actual purging any delete-marked records, but merely update the purge view. "
16255  "It is to create artificially the situation the purge view have been updated "
16256  "but the each purges were not done yet.",
16257  NULL, NULL, FALSE);
16258 #endif /* UNIV_DEBUG */
16259 
16260 static struct st_mysql_sys_var* innobase_system_variables[]= {
16261  MYSQL_SYSVAR(additional_mem_pool_size),
16262  MYSQL_SYSVAR(api_trx_level),
16263  MYSQL_SYSVAR(api_bk_commit_interval),
16264  MYSQL_SYSVAR(autoextend_increment),
16265  MYSQL_SYSVAR(buffer_pool_size),
16266  MYSQL_SYSVAR(buffer_pool_instances),
16267  MYSQL_SYSVAR(buffer_pool_filename),
16268  MYSQL_SYSVAR(buffer_pool_dump_now),
16269  MYSQL_SYSVAR(buffer_pool_dump_at_shutdown),
16270 #ifdef UNIV_DEBUG
16271  MYSQL_SYSVAR(buffer_pool_evict),
16272 #endif /* UNIV_DEBUG */
16273  MYSQL_SYSVAR(buffer_pool_load_now),
16274  MYSQL_SYSVAR(buffer_pool_load_abort),
16275  MYSQL_SYSVAR(buffer_pool_load_at_startup),
16276  MYSQL_SYSVAR(lru_scan_depth),
16277  MYSQL_SYSVAR(flush_neighbors),
16278  MYSQL_SYSVAR(checksum_algorithm),
16279  MYSQL_SYSVAR(checksums),
16280  MYSQL_SYSVAR(commit_concurrency),
16281  MYSQL_SYSVAR(concurrency_tickets),
16282  MYSQL_SYSVAR(compression_level),
16283  MYSQL_SYSVAR(data_file_path),
16284  MYSQL_SYSVAR(data_home_dir),
16285  MYSQL_SYSVAR(doublewrite),
16286  MYSQL_SYSVAR(api_enable_binlog),
16287  MYSQL_SYSVAR(api_enable_mdl),
16288  MYSQL_SYSVAR(api_disable_rowlock),
16289  MYSQL_SYSVAR(fast_shutdown),
16290  MYSQL_SYSVAR(file_io_threads),
16291  MYSQL_SYSVAR(read_io_threads),
16292  MYSQL_SYSVAR(write_io_threads),
16293  MYSQL_SYSVAR(file_per_table),
16294  MYSQL_SYSVAR(file_format),
16295  MYSQL_SYSVAR(file_format_check),
16296  MYSQL_SYSVAR(file_format_max),
16297  MYSQL_SYSVAR(flush_log_at_timeout),
16298  MYSQL_SYSVAR(flush_log_at_trx_commit),
16299  MYSQL_SYSVAR(flush_method),
16300  MYSQL_SYSVAR(force_recovery),
16301 #ifndef DBUG_OFF
16302  MYSQL_SYSVAR(force_recovery_crash),
16303 #endif /* !DBUG_OFF */
16304  MYSQL_SYSVAR(ft_cache_size),
16305  MYSQL_SYSVAR(ft_total_cache_size),
16306  MYSQL_SYSVAR(ft_result_cache_limit),
16307  MYSQL_SYSVAR(ft_enable_stopword),
16308  MYSQL_SYSVAR(ft_max_token_size),
16309  MYSQL_SYSVAR(ft_min_token_size),
16310  MYSQL_SYSVAR(ft_num_word_optimize),
16311  MYSQL_SYSVAR(ft_sort_pll_degree),
16312  MYSQL_SYSVAR(large_prefix),
16313  MYSQL_SYSVAR(force_load_corrupted),
16314  MYSQL_SYSVAR(locks_unsafe_for_binlog),
16315  MYSQL_SYSVAR(lock_wait_timeout),
16316 #ifdef UNIV_LOG_ARCHIVE
16317  MYSQL_SYSVAR(log_arch_dir),
16318  MYSQL_SYSVAR(log_archive),
16319 #endif /* UNIV_LOG_ARCHIVE */
16320  MYSQL_SYSVAR(page_size),
16321  MYSQL_SYSVAR(log_buffer_size),
16322  MYSQL_SYSVAR(log_file_size),
16323  MYSQL_SYSVAR(log_files_in_group),
16324  MYSQL_SYSVAR(log_group_home_dir),
16325  MYSQL_SYSVAR(log_compressed_pages),
16326  MYSQL_SYSVAR(max_dirty_pages_pct),
16327  MYSQL_SYSVAR(max_dirty_pages_pct_lwm),
16328  MYSQL_SYSVAR(adaptive_flushing_lwm),
16329  MYSQL_SYSVAR(adaptive_flushing),
16330  MYSQL_SYSVAR(flushing_avg_loops),
16331  MYSQL_SYSVAR(max_purge_lag),
16332  MYSQL_SYSVAR(max_purge_lag_delay),
16333  MYSQL_SYSVAR(mirrored_log_groups),
16334  MYSQL_SYSVAR(old_blocks_pct),
16335  MYSQL_SYSVAR(old_blocks_time),
16336  MYSQL_SYSVAR(open_files),
16337  MYSQL_SYSVAR(optimize_fulltext_only),
16338  MYSQL_SYSVAR(rollback_on_timeout),
16339  MYSQL_SYSVAR(ft_aux_table),
16340  MYSQL_SYSVAR(ft_enable_diag_print),
16341  MYSQL_SYSVAR(ft_server_stopword_table),
16342  MYSQL_SYSVAR(ft_user_stopword_table),
16343  MYSQL_SYSVAR(disable_sort_file_cache),
16344  MYSQL_SYSVAR(stats_on_metadata),
16345  MYSQL_SYSVAR(stats_sample_pages),
16346  MYSQL_SYSVAR(stats_transient_sample_pages),
16347  MYSQL_SYSVAR(stats_persistent),
16348  MYSQL_SYSVAR(stats_persistent_sample_pages),
16349  MYSQL_SYSVAR(stats_auto_recalc),
16350  MYSQL_SYSVAR(adaptive_hash_index),
16351  MYSQL_SYSVAR(stats_method),
16352  MYSQL_SYSVAR(replication_delay),
16353  MYSQL_SYSVAR(status_file),
16354  MYSQL_SYSVAR(strict_mode),
16355  MYSQL_SYSVAR(support_xa),
16356  MYSQL_SYSVAR(sort_buffer_size),
16357  MYSQL_SYSVAR(online_alter_log_max_size),
16358  MYSQL_SYSVAR(sync_spin_loops),
16359  MYSQL_SYSVAR(spin_wait_delay),
16360  MYSQL_SYSVAR(table_locks),
16361  MYSQL_SYSVAR(thread_concurrency),
16362 #ifdef HAVE_ATOMIC_BUILTINS
16363  MYSQL_SYSVAR(adaptive_max_sleep_delay),
16364 #endif /* HAVE_ATOMIC_BUILTINS */
16365  MYSQL_SYSVAR(thread_sleep_delay),
16366  MYSQL_SYSVAR(autoinc_lock_mode),
16367  MYSQL_SYSVAR(version),
16368  MYSQL_SYSVAR(use_sys_malloc),
16369  MYSQL_SYSVAR(use_native_aio),
16370  MYSQL_SYSVAR(change_buffering),
16371  MYSQL_SYSVAR(change_buffer_max_size),
16372 #if defined UNIV_DEBUG || defined UNIV_IBUF_DEBUG
16373  MYSQL_SYSVAR(change_buffering_debug),
16374  MYSQL_SYSVAR(disable_background_merge),
16375 #endif /* UNIV_DEBUG || UNIV_IBUF_DEBUG */
16376  MYSQL_SYSVAR(random_read_ahead),
16377  MYSQL_SYSVAR(read_ahead_threshold),
16378  MYSQL_SYSVAR(read_only),
16379  MYSQL_SYSVAR(io_capacity),
16380  MYSQL_SYSVAR(io_capacity_max),
16381  MYSQL_SYSVAR(monitor_enable),
16382  MYSQL_SYSVAR(monitor_disable),
16383  MYSQL_SYSVAR(monitor_reset),
16384  MYSQL_SYSVAR(monitor_reset_all),
16385  MYSQL_SYSVAR(purge_threads),
16386  MYSQL_SYSVAR(purge_batch_size),
16387 #ifdef UNIV_DEBUG
16388  MYSQL_SYSVAR(purge_run_now),
16389  MYSQL_SYSVAR(purge_stop_now),
16390  MYSQL_SYSVAR(log_checkpoint_now),
16391 #endif /* UNIV_DEBUG */
16392 #if defined UNIV_DEBUG || defined UNIV_PERF_DEBUG
16393  MYSQL_SYSVAR(page_hash_locks),
16394  MYSQL_SYSVAR(doublewrite_batch_size),
16395 #endif /* defined UNIV_DEBUG || defined UNIV_PERF_DEBUG */
16396  MYSQL_SYSVAR(print_all_deadlocks),
16397  MYSQL_SYSVAR(cmp_per_index_enabled),
16398  MYSQL_SYSVAR(undo_logs),
16399  MYSQL_SYSVAR(rollback_segments),
16400  MYSQL_SYSVAR(undo_directory),
16401  MYSQL_SYSVAR(undo_tablespaces),
16402  MYSQL_SYSVAR(sync_array_size),
16403  MYSQL_SYSVAR(compression_failure_threshold_pct),
16404  MYSQL_SYSVAR(compression_pad_pct_max),
16405 #ifdef UNIV_DEBUG
16406  MYSQL_SYSVAR(trx_rseg_n_slots_debug),
16407  MYSQL_SYSVAR(limit_optimistic_insert_debug),
16408  MYSQL_SYSVAR(trx_purge_view_update_only_debug),
16409 #endif /* UNIV_DEBUG */
16410  NULL
16411 };
16412 
16413 mysql_declare_plugin(innobase)
16414 {
16415  MYSQL_STORAGE_ENGINE_PLUGIN,
16416  &innobase_storage_engine,
16417  innobase_hton_name,
16418  plugin_author,
16419  "Supports transactions, row-level locking, and foreign keys",
16420  PLUGIN_LICENSE_GPL,
16421  innobase_init, /* Plugin Init */
16422  NULL, /* Plugin Deinit */
16423  INNODB_VERSION_SHORT,
16424  innodb_status_variables_export,/* status variables */
16425  innobase_system_variables, /* system variables */
16426  NULL, /* reserved */
16427  0, /* flags */
16428 },
16429 i_s_innodb_trx,
16430 i_s_innodb_locks,
16431 i_s_innodb_lock_waits,
16432 i_s_innodb_cmp,
16433 i_s_innodb_cmp_reset,
16434 i_s_innodb_cmpmem,
16435 i_s_innodb_cmpmem_reset,
16436 i_s_innodb_cmp_per_index,
16437 i_s_innodb_cmp_per_index_reset,
16438 i_s_innodb_buffer_page,
16439 i_s_innodb_buffer_page_lru,
16440 i_s_innodb_buffer_stats,
16441 i_s_innodb_metrics,
16442 i_s_innodb_ft_default_stopword,
16443 i_s_innodb_ft_deleted,
16444 i_s_innodb_ft_being_deleted,
16445 i_s_innodb_ft_config,
16446 i_s_innodb_ft_index_cache,
16447 i_s_innodb_ft_index_table,
16448 i_s_innodb_sys_tables,
16449 i_s_innodb_sys_tablestats,
16450 i_s_innodb_sys_indexes,
16451 i_s_innodb_sys_columns,
16452 i_s_innodb_sys_fields,
16453 i_s_innodb_sys_foreign,
16454 i_s_innodb_sys_foreign_cols,
16455 i_s_innodb_sys_tablespaces,
16456 i_s_innodb_sys_datafiles
16457 
16458 mysql_declare_plugin_end;
16459 
16469 static
16470 void
16471 innobase_commit_concurrency_init_default()
16472 /*======================================*/
16473 {
16474  MYSQL_SYSVAR_NAME(commit_concurrency).def_val
16475  = innobase_commit_concurrency;
16476 }
16477 
16483 static
16484 void
16485 innobase_undo_logs_init_default_max()
16486 /*=================================*/
16487 {
16488  MYSQL_SYSVAR_NAME(undo_logs).max_val
16489  = MYSQL_SYSVAR_NAME(undo_logs).def_val
16490  = srv_available_undo_logs;
16491 }
16492 
16493 #ifdef UNIV_COMPILE_TEST_FUNCS
16494 
16495 struct innobase_convert_name_test_t {
16496  char* buf;
16497  ulint buflen;
16498  const char* id;
16499  ulint idlen;
16500  void* thd;
16501  ibool file_id;
16502 
16503  const char* expected;
16504 };
16505 
16506 void
16507 test_innobase_convert_name()
16508 {
16509  char buf[1024];
16510  ulint i;
16511 
16512  innobase_convert_name_test_t test_input[] = {
16513  {buf, sizeof(buf), "abcd", 4, NULL, TRUE, "\"abcd\""},
16514  {buf, 7, "abcd", 4, NULL, TRUE, "\"abcd\""},
16515  {buf, 6, "abcd", 4, NULL, TRUE, "\"abcd\""},
16516  {buf, 5, "abcd", 4, NULL, TRUE, "\"abc\""},
16517  {buf, 4, "abcd", 4, NULL, TRUE, "\"ab\""},
16518 
16519  {buf, sizeof(buf), "ab@0060cd", 9, NULL, TRUE, "\"ab`cd\""},
16520  {buf, 9, "ab@0060cd", 9, NULL, TRUE, "\"ab`cd\""},
16521  {buf, 8, "ab@0060cd", 9, NULL, TRUE, "\"ab`cd\""},
16522  {buf, 7, "ab@0060cd", 9, NULL, TRUE, "\"ab`cd\""},
16523  {buf, 6, "ab@0060cd", 9, NULL, TRUE, "\"ab`c\""},
16524  {buf, 5, "ab@0060cd", 9, NULL, TRUE, "\"ab`\""},
16525  {buf, 4, "ab@0060cd", 9, NULL, TRUE, "\"ab\""},
16526 
16527  {buf, sizeof(buf), "ab\"cd", 5, NULL, TRUE,
16528  "\"#mysql50#ab\"\"cd\""},
16529  {buf, 17, "ab\"cd", 5, NULL, TRUE,
16530  "\"#mysql50#ab\"\"cd\""},
16531  {buf, 16, "ab\"cd", 5, NULL, TRUE,
16532  "\"#mysql50#ab\"\"c\""},
16533  {buf, 15, "ab\"cd", 5, NULL, TRUE,
16534  "\"#mysql50#ab\"\"\""},
16535  {buf, 14, "ab\"cd", 5, NULL, TRUE,
16536  "\"#mysql50#ab\""},
16537  {buf, 13, "ab\"cd", 5, NULL, TRUE,
16538  "\"#mysql50#ab\""},
16539  {buf, 12, "ab\"cd", 5, NULL, TRUE,
16540  "\"#mysql50#a\""},
16541  {buf, 11, "ab\"cd", 5, NULL, TRUE,
16542  "\"#mysql50#\""},
16543  {buf, 10, "ab\"cd", 5, NULL, TRUE,
16544  "\"#mysql50\""},
16545 
16546  {buf, sizeof(buf), "ab/cd", 5, NULL, TRUE, "\"ab\".\"cd\""},
16547  {buf, 9, "ab/cd", 5, NULL, TRUE, "\"ab\".\"cd\""},
16548  {buf, 8, "ab/cd", 5, NULL, TRUE, "\"ab\".\"c\""},
16549  {buf, 7, "ab/cd", 5, NULL, TRUE, "\"ab\".\"\""},
16550  {buf, 6, "ab/cd", 5, NULL, TRUE, "\"ab\"."},
16551  {buf, 5, "ab/cd", 5, NULL, TRUE, "\"ab\"."},
16552  {buf, 4, "ab/cd", 5, NULL, TRUE, "\"ab\""},
16553  {buf, 3, "ab/cd", 5, NULL, TRUE, "\"a\""},
16554  {buf, 2, "ab/cd", 5, NULL, TRUE, "\"\""},
16555  /* XXX probably "" is a better result in this case
16556  {buf, 1, "ab/cd", 5, NULL, TRUE, "."},
16557  */
16558  {buf, 0, "ab/cd", 5, NULL, TRUE, ""},
16559  };
16560 
16561  for (i = 0; i < sizeof(test_input) / sizeof(test_input[0]); i++) {
16562 
16563  char* end;
16564  ibool ok = TRUE;
16565  size_t res_len;
16566 
16567  fprintf(stderr, "TESTING %lu, %s, %lu, %s\n",
16568  test_input[i].buflen,
16569  test_input[i].id,
16570  test_input[i].idlen,
16571  test_input[i].expected);
16572 
16573  end = innobase_convert_name(
16574  test_input[i].buf,
16575  test_input[i].buflen,
16576  test_input[i].id,
16577  test_input[i].idlen,
16578  test_input[i].thd,
16579  test_input[i].file_id);
16580 
16581  res_len = (size_t) (end - test_input[i].buf);
16582 
16583  if (res_len != strlen(test_input[i].expected)) {
16584 
16585  fprintf(stderr, "unexpected len of the result: %u, "
16586  "expected: %u\n", (unsigned) res_len,
16587  (unsigned) strlen(test_input[i].expected));
16588  ok = FALSE;
16589  }
16590 
16591  if (memcmp(test_input[i].buf,
16592  test_input[i].expected,
16593  strlen(test_input[i].expected)) != 0
16594  || !ok) {
16595 
16596  fprintf(stderr, "unexpected result: %.*s, "
16597  "expected: %s\n", (int) res_len,
16598  test_input[i].buf,
16599  test_input[i].expected);
16600  ok = FALSE;
16601  }
16602 
16603  if (ok) {
16604  fprintf(stderr, "OK: res: %.*s\n\n", (int) res_len,
16605  buf);
16606  } else {
16607  fprintf(stderr, "FAILED\n\n");
16608  return;
16609  }
16610  }
16611 }
16612 
16613 #endif /* UNIV_COMPILE_TEST_FUNCS */
16614 
16615 /****************************************************************************
16616  * DS-MRR implementation
16617  ***************************************************************************/
16618 
16623 int
16625  RANGE_SEQ_IF* seq,
16626  void* seq_init_param,
16627  uint n_ranges,
16628  uint mode,
16629  HANDLER_BUFFER* buf)
16630 {
16631  return(ds_mrr.dsmrr_init(this, seq, seq_init_param,
16632  n_ranges, mode, buf));
16633 }
16634 
16635 int
16637  char** range_info)
16638 {
16639  return(ds_mrr.dsmrr_next(range_info));
16640 }
16641 
16642 ha_rows
16644  uint keyno,
16645  RANGE_SEQ_IF* seq,
16646  void* seq_init_param,
16647  uint n_ranges,
16648  uint* bufsz,
16649  uint* flags,
16650  Cost_estimate* cost)
16651 {
16652  /* See comments in ha_myisam::multi_range_read_info_const */
16653  ds_mrr.init(this, table);
16654  return(ds_mrr.dsmrr_info_const(keyno, seq, seq_init_param,
16655  n_ranges, bufsz, flags, cost));
16656 }
16657 
16658 ha_rows
16660  uint keyno,
16661  uint n_ranges,
16662  uint keys,
16663  uint* bufsz,
16664  uint* flags,
16665  Cost_estimate* cost)
16666 {
16667  ds_mrr.init(this, table);
16668  return(ds_mrr.dsmrr_info(keyno, n_ranges, keys, bufsz, flags, cost));
16669 }
16670 
16671 
16676 /*************************************************************/
16679 UNIV_INTERN
16680 enum icp_result
16682 /*================*/
16683  void* file)
16684 {
16685  DBUG_ENTER("innobase_index_cond");
16686 
16687  ha_innobase* h = reinterpret_cast<class ha_innobase*>(file);
16688 
16689  DBUG_ASSERT(h->pushed_idx_cond);
16690  DBUG_ASSERT(h->pushed_idx_cond_keyno != MAX_KEY);
16691 
16692  if (h->end_range && h->compare_key_icp(h->end_range) > 0) {
16693 
16694  /* caller should return HA_ERR_END_OF_FILE already */
16695  DBUG_RETURN(ICP_OUT_OF_RANGE);
16696  }
16697 
16698  DBUG_RETURN(h->pushed_idx_cond->val_int() ? ICP_MATCH : ICP_NO_MATCH);
16699 }
16700 
16706 UNIV_INTERN
16707 class Item*
16709  uint keyno,
16710  class Item* idx_cond)
16711 {
16712  DBUG_ENTER("ha_innobase::idx_cond_push");
16713  DBUG_ASSERT(keyno != MAX_KEY);
16714  DBUG_ASSERT(idx_cond != NULL);
16715 
16716  pushed_idx_cond = idx_cond;
16717  pushed_idx_cond_keyno = keyno;
16718  in_range_check_pushed_down = TRUE;
16719  /* We will evaluate the condition entirely */
16720  DBUG_RETURN(NULL);
16721 }
16722 
16723 /******************************************************************/
16733 UNIV_INTERN
16734 void
16736 /*========*/
16737  THD* thd,
16739  ib_uint32_t code,
16740  ...)
16741 {
16742  char* str;
16743  va_list args;
16744  const char* format = innobase_get_err_msg(code);
16745 
16746  /* If the caller wants to push a message to the client then
16747  the caller must pass a valid session handle. */
16748 
16749  ut_a(thd != 0);
16750 
16751  /* The error code must exist in the errmsg-utf8.txt file. */
16752  ut_a(format != 0);
16753 
16754  va_start(args, code);
16755 
16756 #ifdef __WIN__
16757  int size = _vscprintf(format, args) + 1;
16758  str = static_cast<char*>(malloc(size));
16759  str[size - 1] = 0x0;
16760  vsnprintf(str, size, format, args);
16761 #elif HAVE_VASPRINTF
16762  (void) vasprintf(&str, format, args);
16763 #else
16764  /* Use a fixed length string. */
16765  str = static_cast<char*>(malloc(BUFSIZ));
16766  my_vsnprintf(str, BUFSIZ, format, args);
16767 #endif /* __WIN__ */
16768 
16769  Sql_condition::enum_warning_level l;
16770 
16771  l = Sql_condition::WARN_LEVEL_NOTE;
16772 
16773  switch(level) {
16774  case IB_LOG_LEVEL_INFO:
16775  break;
16776  case IB_LOG_LEVEL_WARN:
16777  l = Sql_condition::WARN_LEVEL_WARN;
16778  break;
16779  case IB_LOG_LEVEL_ERROR:
16780  /* We can't use push_warning_printf(), it is a hard error. */
16781  my_printf_error(code, "%s", MYF(0), str);
16782  break;
16783  case IB_LOG_LEVEL_FATAL:
16784  l = Sql_condition::WARN_LEVEL_END;
16785  break;
16786  }
16787 
16788  if (level != IB_LOG_LEVEL_ERROR) {
16789  push_warning_printf(thd, l, code, "InnoDB: %s", str);
16790  }
16791 
16792  va_end(args);
16793  free(str);
16794 
16795  if (level == IB_LOG_LEVEL_FATAL) {
16796  ut_error;
16797  }
16798 }
16799 
16800 /******************************************************************/
16811 UNIV_INTERN
16812 void
16814 /*====*/
16815  THD* thd,
16817  ib_uint32_t code,
16818  const char* format,
16819  ...)
16820 {
16821  char* str;
16822  va_list args;
16823 
16824  /* If the caller wants to push a message to the client then
16825  the caller must pass a valid session handle. */
16826 
16827  ut_a(thd != 0);
16828  ut_a(format != 0);
16829 
16830  va_start(args, format);
16831 
16832 #ifdef __WIN__
16833  int size = _vscprintf(format, args) + 1;
16834  str = static_cast<char*>(malloc(size));
16835  str[size - 1] = 0x0;
16836  vsnprintf(str, size, format, args);
16837 #elif HAVE_VASPRINTF
16838  (void) vasprintf(&str, format, args);
16839 #else
16840  /* Use a fixed length string. */
16841  str = static_cast<char*>(malloc(BUFSIZ));
16842  my_vsnprintf(str, BUFSIZ, format, args);
16843 #endif /* __WIN__ */
16844 
16845  ib_senderrf(thd, level, code, str);
16846 
16847  va_end(args);
16848  free(str);
16849 }
16850 
16851 /******************************************************************/
16853 UNIV_INTERN
16854 void
16856 /*====*/
16858  const char* format,
16859  ...)
16860 {
16861  char* str;
16862  va_list args;
16863 
16864  va_start(args, format);
16865 
16866 #ifdef __WIN__
16867  int size = _vscprintf(format, args) + 1;
16868  str = static_cast<char*>(malloc(size));
16869  str[size - 1] = 0x0;
16870  vsnprintf(str, size, format, args);
16871 #elif HAVE_VASPRINTF
16872  (void) vasprintf(&str, format, args);
16873 #else
16874  /* Use a fixed length string. */
16875  str = static_cast<char*>(malloc(BUFSIZ));
16876  my_vsnprintf(str, BUFSIZ, format, args);
16877 #endif /* __WIN__ */
16878 
16879  switch(level) {
16880  case IB_LOG_LEVEL_INFO:
16881  sql_print_information("InnoDB: %s", str);
16882  break;
16883  case IB_LOG_LEVEL_WARN:
16884  sql_print_warning("InnoDB: %s", str);
16885  break;
16886  case IB_LOG_LEVEL_ERROR:
16887  sql_print_error("InnoDB: %s", str);
16888  break;
16889  case IB_LOG_LEVEL_FATAL:
16890  sql_print_error("InnoDB: %s", str);
16891  break;
16892  }
16893 
16894  va_end(args);
16895  free(str);
16896 
16897  if (level == IB_LOG_LEVEL_FATAL) {
16898  ut_error;
16899  }
16900 }
16901 
16902 /**********************************************************************
16903 Converts an identifier from my_charset_filename to UTF-8 charset.
16904 @return result string length, as returned by strconvert() */
16905 uint
16906 innobase_convert_to_filename_charset(
16907 /*=================================*/
16908  char* to, /* out: converted identifier */
16909  const char* from, /* in: identifier to convert */
16910  ulint len) /* in: length of 'to', in bytes */
16911 {
16912  uint errors;
16913  CHARSET_INFO* cs_to = &my_charset_filename;
16914  CHARSET_INFO* cs_from = system_charset_info;
16915 
16916  return(strconvert(cs_from, from, cs_to, to, len, &errors));
16917 }
16918 
16919 /**********************************************************************
16920 Converts an identifier from my_charset_filename to UTF-8 charset.
16921 @return result string length, as returned by strconvert() */
16922 uint
16923 innobase_convert_to_system_charset(
16924 /*===============================*/
16925  char* to, /* out: converted identifier */
16926  const char* from, /* in: identifier to convert */
16927  ulint len, /* in: length of 'to', in bytes */
16928  uint* errors) /* out: error return */
16929 {
16930  CHARSET_INFO* cs1 = &my_charset_filename;
16931  CHARSET_INFO* cs2 = system_charset_info;
16932 
16933  return(strconvert(cs1, from, cs2, to, len, errors));
16934 }