1
/* Copyright (C) 2000-2005 MySQL AB & Innobase Oy
3
This program is free software; you can redistribute it and/or modify
4
it under the terms of the GNU General Public License as published by
5
the Free Software Foundation; version 2 of the License.
7
This program is distributed in the hope that it will be useful,
8
but WITHOUT ANY WARRANTY; without even the implied warranty of
9
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
10
GNU General Public License for more details.
12
You should have received a copy of the GNU General Public License
13
along with this program; if not, write to the Free Software
14
Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA */
16
/* This file defines the InnoDB handler: the interface between MySQL and InnoDB
17
NOTE: You can only use noninlined InnoDB functions in this file, because we
18
have disabled the InnoDB inlining in this file. */
20
/* TODO list for the InnoDB handler in 5.0:
21
- Remove the flag trx->active_trans and look at trx->conc_state
22
- fix savepoint functions to use savepoint storage area
23
- Find out what kind of problems the OS X case-insensitivity causes to
24
table and database names; should we 'normalize' the names like we do
28
#ifdef USE_PRAGMA_IMPLEMENTATION
29
#pragma implementation // gcc: Class implementation
32
#include <mysql_priv.h>
33
#include <mysqld_error.h>
37
#include <myisampack.h>
38
#include <mysys_err.h>
40
#include "ha_innodb.h"
41
#include <mysql/plugin.h>
43
/** to protect innobase_open_files */
44
static pthread_mutex_t innobase_share_mutex;
45
/** to force correct commit order in binlog */
46
static pthread_mutex_t prepare_commit_mutex;
47
static ulong commit_threads = 0;
48
static pthread_mutex_t commit_threads_m;
49
static pthread_cond_t commit_cond;
50
static pthread_mutex_t commit_cond_m;
51
static pthread_mutex_t analyze_mutex;
52
static bool innodb_inited = 0;
55
This needs to exist until the query cache callback is removed
56
or learns to pass hton.
58
static handlerton *innodb_hton_ptr;
60
#define INSIDE_HA_INNOBASE_CC
62
/* Include necessary InnoDB headers */
64
#include "../storage/innobase/include/univ.i"
65
#include "../storage/innobase/include/os0file.h"
66
#include "../storage/innobase/include/os0thread.h"
67
#include "../storage/innobase/include/srv0start.h"
68
#include "../storage/innobase/include/srv0srv.h"
69
#include "../storage/innobase/include/trx0roll.h"
70
#include "../storage/innobase/include/trx0trx.h"
71
#include "../storage/innobase/include/trx0sys.h"
72
#include "../storage/innobase/include/mtr0mtr.h"
73
#include "../storage/innobase/include/row0ins.h"
74
#include "../storage/innobase/include/row0mysql.h"
75
#include "../storage/innobase/include/row0sel.h"
76
#include "../storage/innobase/include/row0upd.h"
77
#include "../storage/innobase/include/log0log.h"
78
#include "../storage/innobase/include/lock0lock.h"
79
#include "../storage/innobase/include/dict0crea.h"
80
#include "../storage/innobase/include/btr0cur.h"
81
#include "../storage/innobase/include/btr0btr.h"
82
#include "../storage/innobase/include/fsp0fsp.h"
83
#include "../storage/innobase/include/sync0sync.h"
84
#include "../storage/innobase/include/fil0fil.h"
85
#include "../storage/innobase/include/trx0xa.h"
86
#include "../storage/innobase/include/thr0loc.h"
87
#include "../storage/innobase/include/ha_prototypes.h"
90
static const long AUTOINC_OLD_STYLE_LOCKING = 0;
91
static const long AUTOINC_NEW_STYLE_LOCKING = 1;
92
static const long AUTOINC_NO_LOCKING = 2;
94
static long innobase_mirrored_log_groups, innobase_log_files_in_group,
95
innobase_log_buffer_size, innobase_buffer_pool_awe_mem_mb,
96
innobase_additional_mem_pool_size, innobase_file_io_threads,
97
innobase_lock_wait_timeout, innobase_force_recovery,
98
innobase_open_files, innobase_autoinc_lock_mode;
99
static ulong innobase_commit_concurrency = 0;
101
static long long innobase_buffer_pool_size, innobase_log_file_size;
103
/* The default values for the following char* start-up parameters
104
are determined in innobase_init below: */
106
static char* innobase_data_home_dir = NULL;
107
static char* innobase_data_file_path = NULL;
108
static char* innobase_log_group_home_dir = NULL;
109
/* The following has a misleading name: starting from 4.0.5, this also
111
static char* innobase_unix_file_flush_method = NULL;
113
/* Below we have boolean-valued start-up parameters, and their default
116
static ulong innobase_fast_shutdown = 1;
117
#ifdef UNIV_LOG_ARCHIVE
118
static my_bool innobase_log_archive = FALSE;
119
static char* innobase_log_arch_dir = NULL;
120
#endif /* UNIV_LOG_ARCHIVE */
121
static my_bool innobase_use_doublewrite = TRUE;
122
static my_bool innobase_use_checksums = TRUE;
123
static my_bool innobase_file_per_table = FALSE;
124
static my_bool innobase_locks_unsafe_for_binlog = FALSE;
125
static my_bool innobase_rollback_on_timeout = FALSE;
126
static my_bool innobase_create_status_file = FALSE;
127
static my_bool innobase_stats_on_metadata = TRUE;
128
static my_bool innobase_adaptive_hash_index = TRUE;
130
static char* internal_innobase_data_file_path = NULL;
132
/* The following counter is used to convey information to InnoDB
133
about server activity: in selects it is not sensible to call
134
srv_active_wake_master_thread after each fetch or search, we only do
135
it every INNOBASE_WAKE_INTERVAL'th step. */
137
#define INNOBASE_WAKE_INTERVAL 32
138
static ulong innobase_active_counter = 0;
140
static HASH innobase_open_tables;
142
#ifdef __NETWARE__ /* some special cleanup for NetWare */
143
bool nw_panic = FALSE;
146
static uchar* innobase_get_key(INNOBASE_SHARE *share, size_t *length,
147
my_bool not_used __attribute__((unused)));
148
static INNOBASE_SHARE *get_share(const char *table_name);
149
static void free_share(INNOBASE_SHARE *share);
150
static int innobase_close_connection(handlerton *hton, THD* thd);
151
static int innobase_commit(handlerton *hton, THD* thd, bool all);
152
static int innobase_rollback(handlerton *hton, THD* thd, bool all);
153
static int innobase_rollback_to_savepoint(handlerton *hton, THD* thd,
155
static int innobase_savepoint(handlerton *hton, THD* thd, void *savepoint);
156
static int innobase_release_savepoint(handlerton *hton, THD* thd,
158
static handler *innobase_create_handler(handlerton *hton,
162
/***********************************************************************
163
This function checks each index name for a table against reserved
164
system default primary index name 'GEN_CLUST_INDEX'. If a name matches,
165
this function pushes an error message to the client, and returns true. */
168
innobase_index_name_is_reserved(
169
/*============================*/
170
/* out: true if index name matches a
172
const trx_t* trx, /* in: InnoDB transaction handle */
173
const TABLE* form, /* in: information on table
174
columns and indexes */
175
const char* norm_name); /* in: table name */
177
static const char innobase_hton_name[]= "InnoDB";
179
/* "GEN_CLUST_INDEX" is the name reserved for Innodb default
180
system primary index. */
181
static const char innobase_index_reserve_name[]= "GEN_CLUST_INDEX";
183
/** @brief Initialize the default value of innodb_commit_concurrency.
185
Once InnoDB is running, the innodb_commit_concurrency must not change
186
from zero to nonzero. (Bug #42101)
188
The initial default value is 0, and without this extra initialization,
189
SET GLOBAL innodb_commit_concurrency=DEFAULT would set the parameter
190
to 0, even if it was initially set to nonzero at the command line
191
or configuration file. */
194
innobase_commit_concurrency_init_default(void);
195
/*==========================================*/
197
/*****************************************************************
198
Check for a valid value of innobase_commit_concurrency. */
201
innobase_commit_concurrency_validate(
202
/*=================================*/
204
innodb_commit_concurrency */
205
THD* thd, /* in: thread handle */
206
struct st_mysql_sys_var* var, /* in: pointer to system
208
void* save, /* out: immediate result
209
for update function */
210
struct st_mysql_value* value) /* in: incoming string */
213
ulong commit_concurrency;
215
DBUG_ENTER("innobase_commit_concurrency_validate");
217
if (value->val_int(value, &intbuf)) {
218
/* The value is NULL. That is invalid. */
222
*reinterpret_cast<ulong*>(save) = commit_concurrency
223
= static_cast<ulong>(intbuf);
225
/* Allow the value to be updated, as long as it remains zero
227
DBUG_RETURN(!(!commit_concurrency == !innobase_commit_concurrency));
230
static MYSQL_THDVAR_BOOL(support_xa, PLUGIN_VAR_OPCMDARG,
231
"Enable InnoDB support for the XA two-phase commit",
232
/* check_func */ NULL, /* update_func */ NULL,
235
static MYSQL_THDVAR_BOOL(table_locks, PLUGIN_VAR_OPCMDARG,
236
"Enable InnoDB locking in LOCK TABLES",
237
/* check_func */ NULL, /* update_func */ NULL,
240
static handler *innobase_create_handler(handlerton *hton,
244
return new (mem_root) ha_innobase(hton, table);
247
/***********************************************************************
248
This function is used to prepare X/Open XA distributed transaction */
253
/* out: 0 or error number */
255
THD* thd, /* in: handle to the MySQL thread of the user
256
whose XA transaction should be prepared */
257
bool all); /* in: TRUE - commit transaction
258
FALSE - the current SQL statement ended */
259
/***********************************************************************
260
This function is used to recover X/Open XA distributed transactions */
265
/* out: number of prepared transactions
266
stored in xid_list */
268
XID* xid_list, /* in/out: prepared transactions */
269
uint len); /* in: number of slots in xid_list */
270
/***********************************************************************
271
This function is used to commit one X/Open XA distributed transaction
272
which is in the prepared state */
275
innobase_commit_by_xid(
276
/*===================*/
277
/* out: 0 or error number */
279
XID* xid); /* in: X/Open XA transaction identification */
280
/***********************************************************************
281
This function is used to rollback one X/Open XA distributed transaction
282
which is in the prepared state */
285
innobase_rollback_by_xid(
286
/*=====================*/
287
/* out: 0 or error number */
289
XID *xid); /* in: X/Open XA transaction identification */
290
/***********************************************************************
291
Create a consistent view for a cursor based on current transaction
292
which is created if the corresponding MySQL thread still lacks one.
293
This consistent view is then used inside of MySQL when accessing records
297
innobase_create_cursor_view(
298
/*========================*/
299
/* out: pointer to cursor view or NULL */
300
handlerton* hton, /* in: innobase hton */
301
THD* thd); /* in: user thread handle */
302
/***********************************************************************
303
Set the given consistent cursor view to a transaction which is created
304
if the corresponding MySQL thread still lacks one. If the given
305
consistent cursor view is NULL global read view of a transaction is
306
restored to a transaction read view. */
309
innobase_set_cursor_view(
310
/*=====================*/
312
THD* thd, /* in: user thread handle */
313
void* curview);/* in: Consistent cursor view to be set */
314
/***********************************************************************
315
Close the given consistent cursor view of a transaction and restore
316
global read view to a transaction read view. Transaction is created if the
317
corresponding MySQL thread still lacks one. */
320
innobase_close_cursor_view(
321
/*=======================*/
323
THD* thd, /* in: user thread handle */
324
void* curview);/* in: Consistent read view to be closed */
325
/*********************************************************************
326
Removes all tables in the named database inside InnoDB. */
329
innobase_drop_database(
330
/*===================*/
331
/* out: error number */
332
handlerton* hton, /* in: handlerton of Innodb */
333
char* path); /* in: database path; inside InnoDB the name
334
of the last directory in the path is used as
335
the database name: for example, in 'mysql/data/test'
336
the database name is 'test' */
337
/***********************************************************************
338
Closes an InnoDB database. */
341
innobase_end(handlerton *hton, ha_panic_function type);
343
/*********************************************************************
344
Creates an InnoDB transaction struct for the thd if it does not yet have one.
345
Starts a new InnoDB transaction if a transaction is not yet started. And
346
assigns a new snapshot for a consistent read if the transaction does not yet
350
innobase_start_trx_and_assign_read_view(
351
/*====================================*/
353
handlerton* hton, /* in: Innodb handlerton */
354
THD* thd); /* in: MySQL thread handle of the user for whom
355
the transaction should be committed */
356
/********************************************************************
357
Flushes InnoDB logs to disk and makes a checkpoint. Really, a commit flushes
358
the logs, and the name of this function should be innobase_checkpoint. */
363
/* out: TRUE if error */
364
handlerton* hton); /* in: InnoDB handlerton */
366
/****************************************************************************
367
Implements the SHOW INNODB STATUS command. Sends the output of the InnoDB
368
Monitor to the client. */
373
handlerton* hton, /* in: the innodb handlerton */
374
THD* thd, /* in: the MySQL query thread of the caller */
375
stat_print_fn *stat_print);
377
bool innobase_show_status(handlerton *hton, THD* thd,
378
stat_print_fn* stat_print,
379
enum ha_stat_type stat_type);
381
/*********************************************************************
382
Commits a transaction in an InnoDB database. */
387
trx_t* trx); /* in: transaction handle */
389
static SHOW_VAR innodb_status_variables[]= {
390
{"buffer_pool_pages_data",
391
(char*) &export_vars.innodb_buffer_pool_pages_data, SHOW_LONG},
392
{"buffer_pool_pages_dirty",
393
(char*) &export_vars.innodb_buffer_pool_pages_dirty, SHOW_LONG},
394
{"buffer_pool_pages_flushed",
395
(char*) &export_vars.innodb_buffer_pool_pages_flushed, SHOW_LONG},
396
{"buffer_pool_pages_free",
397
(char*) &export_vars.innodb_buffer_pool_pages_free, SHOW_LONG},
399
{"buffer_pool_pages_latched",
400
(char*) &export_vars.innodb_buffer_pool_pages_latched, SHOW_LONG},
401
#endif /* UNIV_DEBUG */
402
{"buffer_pool_pages_misc",
403
(char*) &export_vars.innodb_buffer_pool_pages_misc, SHOW_LONG},
404
{"buffer_pool_pages_total",
405
(char*) &export_vars.innodb_buffer_pool_pages_total, SHOW_LONG},
406
{"buffer_pool_read_ahead_rnd",
407
(char*) &export_vars.innodb_buffer_pool_read_ahead_rnd, SHOW_LONG},
408
{"buffer_pool_read_ahead_seq",
409
(char*) &export_vars.innodb_buffer_pool_read_ahead_seq, SHOW_LONG},
410
{"buffer_pool_read_requests",
411
(char*) &export_vars.innodb_buffer_pool_read_requests, SHOW_LONG},
412
{"buffer_pool_reads",
413
(char*) &export_vars.innodb_buffer_pool_reads, SHOW_LONG},
414
{"buffer_pool_wait_free",
415
(char*) &export_vars.innodb_buffer_pool_wait_free, SHOW_LONG},
416
{"buffer_pool_write_requests",
417
(char*) &export_vars.innodb_buffer_pool_write_requests, SHOW_LONG},
419
(char*) &export_vars.innodb_data_fsyncs, SHOW_LONG},
420
{"data_pending_fsyncs",
421
(char*) &export_vars.innodb_data_pending_fsyncs, SHOW_LONG},
422
{"data_pending_reads",
423
(char*) &export_vars.innodb_data_pending_reads, SHOW_LONG},
424
{"data_pending_writes",
425
(char*) &export_vars.innodb_data_pending_writes, SHOW_LONG},
427
(char*) &export_vars.innodb_data_read, SHOW_LONG},
429
(char*) &export_vars.innodb_data_reads, SHOW_LONG},
431
(char*) &export_vars.innodb_data_writes, SHOW_LONG},
433
(char*) &export_vars.innodb_data_written, SHOW_LONG},
434
{"dblwr_pages_written",
435
(char*) &export_vars.innodb_dblwr_pages_written, SHOW_LONG},
437
(char*) &export_vars.innodb_dblwr_writes, SHOW_LONG},
439
(char*) &export_vars.innodb_log_waits, SHOW_LONG},
440
{"log_write_requests",
441
(char*) &export_vars.innodb_log_write_requests, SHOW_LONG},
443
(char*) &export_vars.innodb_log_writes, SHOW_LONG},
445
(char*) &export_vars.innodb_os_log_fsyncs, SHOW_LONG},
446
{"os_log_pending_fsyncs",
447
(char*) &export_vars.innodb_os_log_pending_fsyncs, SHOW_LONG},
448
{"os_log_pending_writes",
449
(char*) &export_vars.innodb_os_log_pending_writes, SHOW_LONG},
451
(char*) &export_vars.innodb_os_log_written, SHOW_LONG},
453
(char*) &export_vars.innodb_page_size, SHOW_LONG},
455
(char*) &export_vars.innodb_pages_created, SHOW_LONG},
457
(char*) &export_vars.innodb_pages_read, SHOW_LONG},
459
(char*) &export_vars.innodb_pages_written, SHOW_LONG},
460
{"row_lock_current_waits",
461
(char*) &export_vars.innodb_row_lock_current_waits, SHOW_LONG},
463
(char*) &export_vars.innodb_row_lock_time, SHOW_LONGLONG},
464
{"row_lock_time_avg",
465
(char*) &export_vars.innodb_row_lock_time_avg, SHOW_LONG},
466
{"row_lock_time_max",
467
(char*) &export_vars.innodb_row_lock_time_max, SHOW_LONG},
469
(char*) &export_vars.innodb_row_lock_waits, SHOW_LONG},
471
(char*) &export_vars.innodb_rows_deleted, SHOW_LONG},
473
(char*) &export_vars.innodb_rows_inserted, SHOW_LONG},
475
(char*) &export_vars.innodb_rows_read, SHOW_LONG},
477
(char*) &export_vars.innodb_rows_updated, SHOW_LONG},
478
{NullS, NullS, SHOW_LONG}
481
/* General functions */
483
/**********************************************************************
484
Returns true if the thread is the replication thread on the slave
485
server. Used in srv_conc_enter_innodb() to determine if the thread
486
should be allowed to enter InnoDB - the replication thread is treated
487
differently than other threads. Also used in
488
srv_conc_force_exit_innodb(). */
491
thd_is_replication_slave_thread(
492
/*============================*/
493
/* out: true if thd is the replication thread */
494
void* thd) /* in: thread handle (THD*) */
496
return((ibool) thd_slave_thread((THD*) thd));
499
/**********************************************************************
500
Save some CPU by testing the value of srv_thread_concurrency in inline
504
innodb_srv_conc_enter_innodb(
505
/*=========================*/
506
trx_t* trx) /* in: transaction handle */
508
if (UNIV_LIKELY(!srv_thread_concurrency)) {
513
srv_conc_enter_innodb(trx);
516
/**********************************************************************
517
Save some CPU by testing the value of srv_thread_concurrency in inline
521
innodb_srv_conc_exit_innodb(
522
/*========================*/
523
trx_t* trx) /* in: transaction handle */
525
if (UNIV_LIKELY(!trx->declared_to_be_inside_innodb)) {
530
srv_conc_exit_innodb(trx);
533
/**********************************************************************
534
Releases possible search latch and InnoDB thread FIFO ticket. These should
535
be released at each SQL statement end, and also when mysqld passes the
536
control to the client. It does no harm to release these also in the middle
537
of an SQL statement. */
540
innobase_release_stat_resources(
541
/*============================*/
542
trx_t* trx) /* in: transaction object */
544
if (trx->has_search_latch) {
545
trx_search_latch_release_if_reserved(trx);
548
if (trx->declared_to_be_inside_innodb) {
549
/* Release our possible ticket in the FIFO */
551
srv_conc_force_exit_innodb(trx);
555
/**********************************************************************
556
Returns true if the transaction this thread is processing has edited
557
non-transactional tables. Used by the deadlock detector when deciding
558
which transaction to rollback in case of a deadlock - we try to avoid
559
rolling back transactions that have edited non-transactional tables. */
562
thd_has_edited_nontrans_tables(
563
/*===========================*/
564
/* out: true if non-transactional tables have
566
void* thd) /* in: thread handle (THD*) */
568
return((ibool) thd_non_transactional_update((THD*) thd));
571
/**********************************************************************
572
Returns true if the thread is executing a SELECT statement. */
577
/* out: true if thd is executing SELECT */
578
const void* thd) /* in: thread handle (THD*) */
580
return(thd_sql_command((const THD*) thd) == SQLCOM_SELECT);
583
/************************************************************************
584
Obtain the InnoDB transaction of a MySQL thread. */
589
/* out: reference to transaction pointer */
590
THD* thd) /* in: MySQL thread */
592
return(*(trx_t**) thd_ha_data(thd, innodb_hton_ptr));
595
/************************************************************************
596
Call this function when mysqld passes control to the client. That is to
597
avoid deadlocks on the adaptive hash S-latch possibly held by thd. For more
598
documentation, see handler.cc. */
601
innobase_release_temporary_latches(
602
/*===============================*/
604
handlerton* hton, /* in: handlerton */
605
THD* thd) /* in: MySQL thread */
609
DBUG_ASSERT(hton == innodb_hton_ptr);
611
if (!innodb_inited) {
616
trx = thd_to_trx(thd);
619
innobase_release_stat_resources(trx);
624
/************************************************************************
625
Increments innobase_active_counter and every INNOBASE_WAKE_INTERVALth
626
time calls srv_active_wake_master_thread. This function should be used
627
when a single database operation may introduce a small need for
628
server utility activity, like checkpointing. */
631
innobase_active_small(void)
632
/*=======================*/
634
innobase_active_counter++;
636
if ((innobase_active_counter % INNOBASE_WAKE_INTERVAL) == 0) {
637
srv_active_wake_master_thread();
641
/************************************************************************
642
Converts an InnoDB error code to a MySQL error code and also tells to MySQL
643
about a possible transaction rollback inside InnoDB caused by a lock wait
644
timeout or a deadlock. */
647
convert_error_code_to_mysql(
648
/*========================*/
649
/* out: MySQL error code */
650
int error, /* in: InnoDB error code */
651
THD* thd) /* in: user thread handle or NULL */
653
if (error == DB_SUCCESS) {
657
} else if (error == (int) DB_DUPLICATE_KEY) {
659
/* Be cautious with returning this error, since
660
mysql could re-enter the storage layer to get
661
duplicated key info, the operation requires a
662
valid table handle and/or transaction information,
663
which might not always be available in the error
665
return(HA_ERR_FOUND_DUPP_KEY);
667
} else if (error == (int) DB_FOREIGN_DUPLICATE_KEY) {
669
return(HA_ERR_FOREIGN_DUPLICATE_KEY);
671
} else if (error == (int) DB_RECORD_NOT_FOUND) {
673
return(HA_ERR_NO_ACTIVE_RECORD);
675
} else if (error == (int) DB_ERROR) {
677
return(-1); /* unspecified error */
679
} else if (error == (int) DB_DEADLOCK) {
680
/* Since we rolled back the whole transaction, we must
681
tell it also to MySQL so that MySQL knows to empty the
682
cached binlog for this transaction */
685
thd_mark_transaction_to_rollback(thd, TRUE);
688
return(HA_ERR_LOCK_DEADLOCK);
689
} else if (error == (int) DB_LOCK_WAIT_TIMEOUT) {
691
/* Starting from 5.0.13, we let MySQL just roll back the
692
latest SQL statement in a lock wait timeout. Previously, we
693
rolled back the whole transaction. */
696
thd_mark_transaction_to_rollback(
697
thd, (bool)row_rollback_on_timeout);
700
return(HA_ERR_LOCK_WAIT_TIMEOUT);
702
} else if (error == (int) DB_NO_REFERENCED_ROW) {
704
return(HA_ERR_NO_REFERENCED_ROW);
706
} else if (error == (int) DB_ROW_IS_REFERENCED) {
708
return(HA_ERR_ROW_IS_REFERENCED);
710
} else if (error == (int) DB_CANNOT_ADD_CONSTRAINT) {
712
return(HA_ERR_CANNOT_ADD_FOREIGN);
714
} else if (error == (int) DB_CANNOT_DROP_CONSTRAINT) {
716
return(HA_ERR_ROW_IS_REFERENCED); /* TODO: This is a bit
717
misleading, a new MySQL error
718
code should be introduced */
719
} else if (error == (int) DB_COL_APPEARS_TWICE_IN_INDEX) {
721
return(HA_ERR_CRASHED);
723
} else if (error == (int) DB_OUT_OF_FILE_SPACE) {
725
return(HA_ERR_RECORD_FILE_FULL);
727
} else if (error == (int) DB_TABLE_IS_BEING_USED) {
729
return(HA_ERR_WRONG_COMMAND);
731
} else if (error == (int) DB_TABLE_NOT_FOUND) {
733
return(HA_ERR_NO_SUCH_TABLE);
735
} else if (error == (int) DB_TOO_BIG_RECORD) {
737
return(HA_ERR_TO_BIG_ROW);
739
} else if (error == (int) DB_CORRUPTION) {
741
return(HA_ERR_CRASHED);
742
} else if (error == (int) DB_NO_SAVEPOINT) {
744
return(HA_ERR_NO_SAVEPOINT);
745
} else if (error == (int) DB_LOCK_TABLE_FULL) {
746
/* Since we rolled back the whole transaction, we must
747
tell it also to MySQL so that MySQL knows to empty the
748
cached binlog for this transaction */
751
thd_mark_transaction_to_rollback(thd, TRUE);
754
return(HA_ERR_LOCK_TABLE_FULL);
755
} else if (error == DB_TOO_MANY_CONCURRENT_TRXS) {
757
return(HA_ERR_TOO_MANY_CONCURRENT_TRXS);
759
} else if (error == DB_UNSUPPORTED) {
761
return(HA_ERR_UNSUPPORTED);
763
return(-1); // Unknown error
767
/*****************************************************************
768
Prints info of a THD object (== user session thread) to the given file.
769
NOTE that /mysql/innobase/trx/trx0trx.c must contain the prototype for
773
innobase_mysql_print_thd(
774
/*=====================*/
775
FILE* f, /* in: output stream */
776
void* input_thd, /* in: pointer to a MySQL THD object */
777
uint max_query_len) /* in: max query length to print, or 0 to
778
use the default max length */
783
thd = (THD*) input_thd;
784
fputs(thd_security_context(thd, buffer, sizeof(buffer),
789
/**********************************************************************
790
Get the variable length bounds of the given character set.
792
NOTE that the exact prototype of this function has to be in
793
/innobase/include/data0type.ic! */
796
innobase_get_cset_width(
797
/*====================*/
798
ulint cset, /* in: MySQL charset-collation code */
799
ulint* mbminlen, /* out: minimum length of a char (in bytes) */
800
ulint* mbmaxlen) /* out: maximum length of a char (in bytes) */
807
cs = all_charsets[cset];
809
*mbminlen = cs->mbminlen;
810
*mbmaxlen = cs->mbmaxlen;
813
&& (thd_sql_command(current_thd) == SQLCOM_DROP_TABLE)) {
815
/* Fix bug#46256: allow tables to be dropped if the
816
collation is not found, but issue a warning. */
817
if ((global_system_variables.log_warnings)
821
"Unknown collation #%lu.", cset);
828
*mbminlen = *mbmaxlen = 0;
832
/**********************************************************************
833
Converts an identifier to a table name.
835
NOTE that the exact prototype of this function has to be in
836
/innobase/dict/dict0dict.c! */
839
innobase_convert_from_table_id(
840
/*===========================*/
841
char* to, /* out: converted identifier */
842
const char* from, /* in: identifier to convert */
843
ulint len) /* in: length of 'to', in bytes */
847
strconvert(thd_charset(current_thd), from,
848
&my_charset_filename, to, (uint) len, &errors);
851
/**********************************************************************
852
Converts an identifier to UTF-8.
854
NOTE that the exact prototype of this function has to be in
855
/innobase/dict/dict0dict.c! */
858
innobase_convert_from_id(
859
/*=====================*/
860
char* to, /* out: converted identifier */
861
const char* from, /* in: identifier to convert */
862
ulint len) /* in: length of 'to', in bytes */
866
strconvert(thd_charset(current_thd), from,
867
system_charset_info, to, (uint) len, &errors);
870
/**********************************************************************
871
Compares NUL-terminated UTF-8 strings case insensitively.
873
NOTE that the exact prototype of this function has to be in
874
/innobase/dict/dict0dict.c! */
879
/* out: 0 if a=b, <0 if a<b, >1 if a>b */
880
const char* a, /* in: first string to compare */
881
const char* b) /* in: second string to compare */
883
return(my_strcasecmp(system_charset_info, a, b));
886
/**********************************************************************
887
Makes all characters in a NUL-terminated UTF-8 string lower case.
889
NOTE that the exact prototype of this function has to be in
890
/innobase/dict/dict0dict.c! */
895
char* a) /* in/out: string to put in lower case */
897
my_casedn_str(system_charset_info, a);
900
/**************************************************************************
901
Determines the connection character set.
903
NOTE that the exact prototype of this function has to be in
904
/innobase/dict/dict0dict.c! */
906
struct charset_info_st*
907
innobase_get_charset(
908
/*=================*/
909
/* out: connection character set */
910
void* mysql_thd) /* in: MySQL thread handle */
912
return(thd_charset((THD*) mysql_thd));
915
#if defined (__WIN__) && defined (MYSQL_DYNAMIC_PLUGIN)
916
extern MYSQL_PLUGIN_IMPORT MY_TMPDIR mysql_tmpdir_list;
917
/*******************************************************************//**
918
Map an OS error to an errno value. The OS error number is stored in
919
_doserrno and the mapped value is stored in errno) */
923
unsigned long); /*!< in: OS error value */
925
/*********************************************************************//**
926
Creates a temporary file.
927
@return temporary file descriptor, or < 0 on error */
930
innobase_mysql_tmpfile(void)
931
/*========================*/
933
int fd; /* handle of opened file */
934
HANDLE osfh; /* OS handle of opened file */
935
char* tmpdir; /* point to the directory
936
where to create file */
937
TCHAR path_buf[MAX_PATH - 14]; /* buffer for tmp file path.
938
The length cannot be longer
939
than MAX_PATH - 14, or
940
GetTempFileName will fail. */
941
char filename[MAX_PATH]; /* name of the tmpfile */
942
DWORD fileaccess = GENERIC_READ /* OS file access */
945
DWORD fileshare = FILE_SHARE_READ /* OS file sharing mode */
948
DWORD filecreate = CREATE_ALWAYS; /* OS method of open/create */
949
DWORD fileattrib = /* OS file attribute flags */
950
FILE_ATTRIBUTE_NORMAL
951
| FILE_FLAG_DELETE_ON_CLOSE
952
| FILE_ATTRIBUTE_TEMPORARY
953
| FILE_FLAG_SEQUENTIAL_SCAN;
955
DBUG_ENTER("innobase_mysql_tmpfile");
957
tmpdir = my_tmpdir(&mysql_tmpdir_list);
959
/* The tmpdir parameter can not be NULL for GetTempFileName. */
963
/* Use GetTempPath to determine path for temporary files. */
964
ret = GetTempPath(sizeof(path_buf), path_buf);
965
if (ret > sizeof(path_buf) || (ret == 0)) {
967
_dosmaperr(GetLastError()); /* map error */
974
/* Use GetTempFileName to generate a unique filename. */
975
if (!GetTempFileName(tmpdir, "ib", 0, filename)) {
977
_dosmaperr(GetLastError()); /* map error */
981
DBUG_PRINT("info", ("filename: %s", filename));
983
/* Open/Create the file. */
984
osfh = CreateFile(filename, fileaccess, fileshare, NULL,
985
filecreate, fileattrib, NULL);
986
if (osfh == INVALID_HANDLE_VALUE) {
988
/* open/create file failed! */
989
_dosmaperr(GetLastError()); /* map error */
994
/* Associates a CRT file descriptor with the OS file handle. */
995
fd = _open_osfhandle((intptr_t) osfh, 0);
996
} while (fd == -1 && errno == EINTR);
999
/* Open failed, close the file handle. */
1001
_dosmaperr(GetLastError()); /* map error */
1002
CloseHandle(osfh); /* no need to check if
1003
CloseHandle fails */
1009
/*************************************************************************
1010
Creates a temporary file. */
1013
innobase_mysql_tmpfile(void)
1014
/*========================*/
1015
/* out: temporary file descriptor, or < 0 on error */
1018
File fd = mysql_tmpfile("ib");
1020
/* Copy the file descriptor, so that the additional resources
1021
allocated by create_temp_file() can be freed by invoking
1024
Because the file descriptor returned by this function
1025
will be passed to fdopen(), it will be closed by invoking
1026
fclose(), which in turn will invoke close() instead of
1030
DBUG_PRINT("error",("Got error %d on dup",fd2));
1032
my_error(EE_OUT_OF_FILERESOURCES,
1033
MYF(ME_BELL+ME_WAITTANG),
1036
my_close(fd, MYF(MY_WME));
1042
/*************************************************************************
1043
Wrapper around MySQL's copy_and_convert function, see it for
1047
innobase_convert_string(
1048
/*====================*/
1051
CHARSET_INFO* to_cs,
1054
CHARSET_INFO* from_cs,
1057
return(copy_and_convert((char*)to, (uint32) to_length, to_cs,
1058
(const char*)from, (uint32) from_length, from_cs,
1062
/*************************************************************************
1063
Compute the next autoinc value.
1065
For MySQL replication the autoincrement values can be partitioned among
1066
the nodes. The offset is the start or origin of the autoincrement value
1067
for a particular node. For n nodes the increment will be n and the offset
1068
will be in the interval [1, n]. The formula tries to allocate the next
1069
value for a particular node.
1071
Note: This function is also called with increment set to the number of
1072
values we want to reserve for multi-value inserts e.g.,
1074
INSERT INTO T VALUES(), (), ();
1076
innobase_next_autoinc() will be called with increment set to
1077
n * 3 where autoinc_lock_mode != TRADITIONAL because we want
1078
to reserve 3 values for the multi-value INSERT above. */
1081
innobase_next_autoinc(
1082
/*==================*/
1083
/* out: the next value */
1084
ulonglong current, /* in: Current value */
1085
ulonglong increment, /* in: increment current by */
1086
ulonglong offset, /* in: AUTOINC offset */
1087
ulonglong max_value) /* in: max value for type */
1089
ulonglong next_value;
1091
/* Should never be 0. */
1092
ut_a(increment > 0);
1094
/* According to MySQL documentation, if the offset is greater than
1095
the increment then the offset is ignored. */
1096
if (offset > increment) {
1100
if (max_value <= current) {
1101
next_value = max_value;
1102
} else if (offset <= 1) {
1103
/* Offset 0 and 1 are the same, because there must be at
1104
least one node in the system. */
1105
if (max_value - current <= increment) {
1106
next_value = max_value;
1108
next_value = current + increment;
1111
if (current > offset) {
1112
next_value = ((current - offset) / increment) + 1;
1114
next_value = ((offset - current) / increment) + 1;
1117
ut_a(increment > 0);
1118
ut_a(next_value > 0);
1120
/* Check for multiplication overflow. */
1121
if (increment > (max_value / next_value)) {
1123
next_value = max_value;
1125
next_value *= increment;
1127
ut_a(max_value >= next_value);
1129
/* Check for overflow. */
1130
if (max_value - next_value <= offset) {
1131
next_value = max_value;
1133
next_value += offset;
1138
ut_a(next_value <= max_value);
1143
/*************************************************************************
1144
Gets the InnoDB transaction handle for a MySQL handler object, creates
1145
an InnoDB transaction struct if the corresponding MySQL thread struct still
1151
/* out: InnoDB transaction handle */
1152
THD* thd) /* in: user thread handle */
1154
trx_t*& trx = thd_to_trx(thd);
1156
ut_ad(thd == current_thd);
1159
DBUG_ASSERT(thd != NULL);
1160
trx = trx_allocate_for_mysql();
1162
trx->mysql_thd = thd;
1163
trx->mysql_query_str = thd_query(thd);
1165
/* Update the info whether we should skip XA steps that eat
1167
trx->support_xa = THDVAR(thd, support_xa);
1169
if (trx->magic_n != TRX_MAGIC_N) {
1170
mem_analyze_corruption(trx);
1176
if (thd_test_options(thd, OPTION_NO_FOREIGN_KEY_CHECKS)) {
1177
trx->check_foreigns = FALSE;
1179
trx->check_foreigns = TRUE;
1182
if (thd_test_options(thd, OPTION_RELAXED_UNIQUE_CHECKS)) {
1183
trx->check_unique_secondary = FALSE;
1185
trx->check_unique_secondary = TRUE;
1192
/*************************************************************************
1193
Construct ha_innobase handler. */
1195
ha_innobase::ha_innobase(handlerton *hton, TABLE_SHARE *table_arg)
1196
:handler(hton, table_arg),
1197
int_table_flags(HA_REC_NOT_IN_SEQ |
1199
HA_CAN_INDEX_BLOBS |
1200
HA_CAN_SQL_HANDLER |
1201
HA_PRIMARY_KEY_REQUIRED_FOR_POSITION |
1202
HA_PRIMARY_KEY_IN_READ_INDEX |
1203
HA_BINLOG_ROW_CAPABLE |
1204
HA_CAN_GEOMETRY | HA_PARTIAL_COLUMN_READ |
1205
HA_TABLE_SCAN_ON_INDEX),
1210
/*************************************************************************
1211
Updates the user_thd field in a handle and also allocates a new InnoDB
1212
transaction handle if needed, and updates the transaction fields in the
1216
ha_innobase::update_thd(
1217
/*====================*/
1218
/* out: 0 or error code */
1219
THD* thd) /* in: thd to use the handle */
1223
trx = check_trx_exists(thd);
1225
if (prebuilt->trx != trx) {
1227
row_update_prebuilt_trx(prebuilt, trx);
1235
/*************************************************************************
1236
Registers that InnoDB takes part in an SQL statement, so that MySQL knows to
1237
roll back the statement if the statement results in an error. This MUST be
1238
called for every SQL statement that may be rolled back by MySQL. Calling this
1239
several times to register the same statement is allowed, too. */
1242
innobase_register_stmt(
1243
/*===================*/
1244
handlerton* hton, /* in: Innobase hton */
1245
THD* thd) /* in: MySQL thd (connection) object */
1247
/* Register the statement */
1248
trans_register_ha(thd, FALSE, hton);
1251
/*************************************************************************
1252
Registers an InnoDB transaction in MySQL, so that the MySQL XA code knows
1253
to call the InnoDB prepare and commit, or rollback for the transaction. This
1254
MUST be called for every transaction for which the user may call commit or
1255
rollback. Calling this several times to register the same transaction is
1257
This function also registers the current SQL statement. */
1260
innobase_register_trx_and_stmt(
1261
/*===========================*/
1262
handlerton *hton, /* in: Innobase handlerton */
1263
THD* thd) /* in: MySQL thd (connection) object */
1265
/* NOTE that actually innobase_register_stmt() registers also
1266
the transaction in the AUTOCOMMIT=1 mode. */
1268
innobase_register_stmt(hton, thd);
1270
if (thd_test_options(thd, OPTION_NOT_AUTOCOMMIT | OPTION_BEGIN)) {
1272
/* No autocommit mode, register for a transaction */
1273
trans_register_ha(thd, TRUE, hton);
1277
/* BACKGROUND INFO: HOW THE MYSQL QUERY CACHE WORKS WITH INNODB
1278
------------------------------------------------------------
1280
1) The use of the query cache for TBL is disabled when there is an
1281
uncommitted change to TBL.
1283
2) When a change to TBL commits, InnoDB stores the current value of
1284
its global trx id counter, let us denote it by INV_TRX_ID, to the table object
1285
in the InnoDB data dictionary, and does only allow such transactions whose
1286
id <= INV_TRX_ID to use the query cache.
1288
3) When InnoDB does an INSERT/DELETE/UPDATE to a table TBL, or an implicit
1289
modification because an ON DELETE CASCADE, we invalidate the MySQL query cache
1292
How this is implemented inside InnoDB:
1294
1) Since every modification always sets an IX type table lock on the InnoDB
1295
table, it is easy to check if there can be uncommitted modifications for a
1296
table: just check if there are locks in the lock list of the table.
1298
2) When a transaction inside InnoDB commits, it reads the global trx id
1299
counter and stores the value INV_TRX_ID to the tables on which it had a lock.
1301
3) If there is an implicit table change from ON DELETE CASCADE or SET NULL,
1302
InnoDB calls an invalidate method for the MySQL query cache for that table.
1304
How this is implemented inside sql_cache.cc:
1306
1) The query cache for an InnoDB table TBL is invalidated immediately at an
1307
INSERT/UPDATE/DELETE, just like in the case of MyISAM. No need to delay
1308
invalidation to the transaction commit.
1310
2) To store or retrieve a value from the query cache of an InnoDB table TBL,
1311
any query must first ask InnoDB's permission. We must pass the thd as a
1312
parameter because InnoDB will look at the trx id, if any, associated with
1315
3) Use of the query cache for InnoDB tables is now allowed also when
1316
AUTOCOMMIT==0 or we are inside BEGIN ... COMMIT. Thus transactions no longer
1317
put restrictions on the use of the query cache.
1320
/**********************************************************************
1321
The MySQL query cache uses this to check from InnoDB if the query cache at
1322
the moment is allowed to operate on an InnoDB table. The SQL query must
1323
be a non-locking SELECT.
1325
The query cache is allowed to operate on certain query only if this function
1326
returns TRUE for all tables in the query.
1328
If thd is not in the autocommit state, this function also starts a new
1329
transaction for thd if there is no active trx yet, and assigns a consistent
1330
read view to it if there is no read view yet.
1332
Why a deadlock of threads is not possible: the query cache calls this function
1333
at the start of a SELECT processing. Then the calling thread cannot be
1334
holding any InnoDB semaphores. The calling thread is holding the
1335
query cache mutex, and this function will reserver the InnoDB kernel mutex.
1336
Thus, the 'rank' in sync0sync.h of the MySQL query cache mutex is above
1337
the InnoDB kernel mutex. */
1340
innobase_query_caching_of_table_permitted(
1341
/*======================================*/
1342
/* out: TRUE if permitted, FALSE if not;
1343
note that the value FALSE does not mean
1344
we should invalidate the query cache:
1345
invalidation is called explicitly */
1346
THD* thd, /* in: thd of the user who is trying to
1347
store a result to the query cache or
1349
char* full_name, /* in: concatenation of database name,
1350
the null character '\0', and the table
1352
uint full_name_len, /* in: length of the full name, i.e.
1353
len(dbname) + len(tablename) + 1 */
1354
ulonglong *unused) /* unused for this engine */
1356
ibool is_autocommit;
1358
char norm_name[1000];
1360
ut_a(full_name_len < 999);
1362
trx = check_trx_exists(thd);
1364
if (trx->isolation_level == TRX_ISO_SERIALIZABLE) {
1365
/* In the SERIALIZABLE mode we add LOCK IN SHARE MODE to every
1366
plain SELECT if AUTOCOMMIT is not on. */
1368
return((my_bool)FALSE);
1371
if (trx->has_search_latch) {
1372
sql_print_error("The calling thread is holding the adaptive "
1373
"search, latch though calling "
1374
"innobase_query_caching_of_table_permitted.");
1376
mutex_enter_noninline(&kernel_mutex);
1377
trx_print(stderr, trx, 1024);
1378
mutex_exit_noninline(&kernel_mutex);
1381
innobase_release_stat_resources(trx);
1383
if (!thd_test_options(thd, OPTION_NOT_AUTOCOMMIT | OPTION_BEGIN)) {
1385
is_autocommit = TRUE;
1387
is_autocommit = FALSE;
1391
if (is_autocommit && trx->n_mysql_tables_in_use == 0) {
1392
/* We are going to retrieve the query result from the query
1393
cache. This cannot be a store operation to the query cache
1394
because then MySQL would have locks on tables already.
1396
TODO: if the user has used LOCK TABLES to lock the table,
1397
then we open a transaction in the call of row_.. below.
1398
That trx can stay open until UNLOCK TABLES. The same problem
1399
exists even if we do not use the query cache. MySQL should be
1400
modified so that it ALWAYS calls some cleanup function when
1401
the processing of a query ends!
1403
We can imagine we instantaneously serialize this consistent
1404
read trx to the current trx id counter. If trx2 would have
1405
changed the tables of a query result stored in the cache, and
1406
trx2 would have already committed, making the result obsolete,
1407
then trx2 would have already invalidated the cache. Thus we
1408
can trust the result in the cache is ok for this query. */
1410
return((my_bool)TRUE);
1413
/* Normalize the table name to InnoDB format */
1415
memcpy(norm_name, full_name, full_name_len);
1417
norm_name[strlen(norm_name)] = '/'; /* InnoDB uses '/' as the
1418
separator between db and table */
1419
norm_name[full_name_len] = '\0';
1421
innobase_casedn_str(norm_name);
1423
/* The call of row_search_.. will start a new transaction if it is
1426
if (trx->active_trans == 0) {
1428
innobase_register_trx_and_stmt(innodb_hton_ptr, thd);
1429
trx->active_trans = 1;
1432
if (row_search_check_if_query_cache_permitted(trx, norm_name)) {
1434
/* printf("Query cache for %s permitted\n", norm_name); */
1436
return((my_bool)TRUE);
1439
/* printf("Query cache for %s NOT permitted\n", norm_name); */
1441
return((my_bool)FALSE);
1444
/*********************************************************************
1445
Invalidates the MySQL query cache for the table.
1446
NOTE that the exact prototype of this function has to be in
1447
/innobase/row/row0ins.c! */
1450
innobase_invalidate_query_cache(
1451
/*============================*/
1452
trx_t* trx, /* in: transaction which modifies the table */
1453
char* full_name, /* in: concatenation of database name, null
1454
char '\0', table name, null char'\0';
1455
NOTE that in Windows this is always
1457
ulint full_name_len) /* in: full name length where also the null
1460
/* Note that the sync0sync.h rank of the query cache mutex is just
1461
above the InnoDB kernel mutex. The caller of this function must not
1462
have latches of a lower rank. */
1464
/* Argument TRUE below means we are using transactions */
1465
#ifdef HAVE_QUERY_CACHE
1466
mysql_query_cache_invalidate4((THD*) trx->mysql_thd,
1467
(const char*) full_name,
1468
(uint32) full_name_len,
1473
/*****************************************************************//**
1474
Convert an SQL identifier to the MySQL system_charset_info (UTF-8)
1475
and quote it if needed.
1476
@return pointer to the end of buf */
1479
innobase_convert_identifier(
1480
/*========================*/
1481
char* buf, /*!< out: buffer for converted identifier */
1482
ulint buflen, /*!< in: length of buf, in bytes */
1483
const char* id, /*!< in: identifier to convert */
1484
ulint idlen, /*!< in: length of id, in bytes */
1485
void* thd, /*!< in: MySQL connection thread, or NULL */
1486
ibool file_id)/*!< in: TRUE=id is a table or database name;
1487
FALSE=id is an UTF-8 string */
1489
char nz[NAME_LEN + 1];
1490
#if MYSQL_VERSION_ID >= 50141
1491
char nz2[NAME_LEN + 1 + EXPLAIN_FILENAME_MAX_EXTRA_LENGTH];
1492
#else /* MYSQL_VERSION_ID >= 50141 */
1493
char nz2[NAME_LEN + 1 + sizeof srv_mysql50_table_name_prefix];
1494
#endif /* MYSQL_VERSION_ID >= 50141 */
1500
/* Decode the table name. The MySQL function expects
1501
a NUL-terminated string. The input and output strings
1502
buffers must not be shared. */
1504
if (UNIV_UNLIKELY(idlen > (sizeof nz) - 1)) {
1505
idlen = (sizeof nz) - 1;
1508
memcpy(nz, id, idlen);
1512
#if MYSQL_VERSION_ID >= 50141
1513
idlen = explain_filename((THD*) thd, nz, nz2, sizeof nz2,
1514
EXPLAIN_PARTITIONS_AS_COMMENT);
1516
#else /* MYSQL_VERSION_ID >= 50141 */
1517
idlen = filename_to_tablename(nz, nz2, sizeof nz2);
1518
#endif /* MYSQL_VERSION_ID >= 50141 */
1521
/* See if the identifier needs to be quoted. */
1522
if (UNIV_UNLIKELY(!thd)) {
1525
q = get_quote_char_for_identifier((THD*) thd, s, (int) idlen);
1529
#if MYSQL_VERSION_ID >= 50141
1531
#endif /* MYSQL_VERSION_ID >= 50141 */
1532
if (UNIV_UNLIKELY(idlen > buflen)) {
1535
memcpy(buf, s, idlen);
1536
return(buf + idlen);
1539
/* Quote the identifier. */
1547
for (; idlen; idlen--) {
1549
if (UNIV_UNLIKELY(c == q)) {
1550
if (UNIV_UNLIKELY(buflen < 3)) {
1558
if (UNIV_UNLIKELY(buflen < 2)) {
1571
/*****************************************************************//**
1572
Convert a table or index name to the MySQL system_charset_info (UTF-8)
1573
and quote it if needed.
1574
@return pointer to the end of buf */
1577
innobase_convert_name(
1578
/*==================*/
1579
char* buf, /*!< out: buffer for converted identifier */
1580
ulint buflen, /*!< in: length of buf, in bytes */
1581
const char* id, /*!< in: identifier to convert */
1582
ulint idlen, /*!< in: length of id, in bytes */
1583
void* thd, /*!< in: MySQL connection thread, or NULL */
1584
ibool table_id)/*!< in: TRUE=id is a table or database name;
1585
FALSE=id is an index name */
1588
const char* bufend = buf + buflen;
1591
const char* slash = (const char*) memchr(id, '/', idlen);
1597
/* Print the database name and table name separately. */
1598
s = innobase_convert_identifier(s, bufend - s, id, slash - id,
1600
if (UNIV_LIKELY(s < bufend)) {
1602
s = innobase_convert_identifier(s, bufend - s,
1609
s = innobase_convert_identifier(buf, buflen, id, idlen,
1617
/**************************************************************************
1618
Determines if the currently running transaction has been interrupted. */
1623
/* out: TRUE if interrupted */
1624
trx_t* trx) /* in: transaction */
1626
return(trx && trx->mysql_thd && thd_killed((THD*) trx->mysql_thd));
1629
/******************************************************************
1630
Resets some fields of a prebuilt struct. The template is used in fast
1631
retrieval of just those column values MySQL needs in its processing. */
1636
row_prebuilt_t* prebuilt) /* in/out: prebuilt struct */
1638
prebuilt->keep_other_fields_on_keyread = 0;
1639
prebuilt->read_just_key = 0;
1642
/*********************************************************************
1643
Call this when you have opened a new table handle in HANDLER, before you
1644
call index_read_idx() etc. Actually, we can let the cursor stay open even
1645
over a transaction commit! Then you should call this before every operation,
1646
fetch next etc. This function inits the necessary things even after a
1647
transaction commit. */
1650
ha_innobase::init_table_handle_for_HANDLER(void)
1651
/*============================================*/
1653
/* If current thd does not yet have a trx struct, create one.
1654
If the current handle does not yet have a prebuilt struct, create
1655
one. Update the trx pointers in the prebuilt struct. Normally
1656
this operation is done in external_lock. */
1658
update_thd(ha_thd());
1660
/* Initialize the prebuilt struct much like it would be inited in
1663
innobase_release_stat_resources(prebuilt->trx);
1665
/* If the transaction is not started yet, start it */
1667
trx_start_if_not_started_noninline(prebuilt->trx);
1669
/* Assign a read view if the transaction does not have it yet */
1671
trx_assign_read_view(prebuilt->trx);
1673
/* Set the MySQL flag to mark that there is an active transaction */
1675
if (prebuilt->trx->active_trans == 0) {
1677
innobase_register_trx_and_stmt(ht, user_thd);
1679
prebuilt->trx->active_trans = 1;
1682
/* We did the necessary inits in this function, no need to repeat them
1683
in row_search_for_mysql */
1685
prebuilt->sql_stat_start = FALSE;
1687
/* We let HANDLER always to do the reads as consistent reads, even
1688
if the trx isolation level would have been specified as SERIALIZABLE */
1690
prebuilt->select_lock_type = LOCK_NONE;
1691
prebuilt->stored_select_lock_type = LOCK_NONE;
1693
/* Always fetch all columns in the index record */
1695
prebuilt->hint_need_to_fetch_extra_cols = ROW_RETRIEVE_ALL_COLS;
1697
/* We want always to fetch all columns in the whole row? Or do
1700
prebuilt->used_in_HANDLER = TRUE;
1701
reset_template(prebuilt);
1704
/*************************************************************************
1705
Opens an InnoDB database. */
1710
/* out: 0 on success, error code on failure */
1711
void *p) /* in: InnoDB handlerton */
1713
static char current_dir[3]; /* Set if using current lib */
1718
DBUG_ENTER("innobase_init");
1719
handlerton *innobase_hton= (handlerton *)p;
1720
innodb_hton_ptr = innobase_hton;
1722
innobase_hton->state = SHOW_OPTION_YES;
1723
innobase_hton->db_type= DB_TYPE_INNODB;
1724
innobase_hton->savepoint_offset=sizeof(trx_named_savept_t);
1725
innobase_hton->close_connection=innobase_close_connection;
1726
innobase_hton->savepoint_set=innobase_savepoint;
1727
innobase_hton->savepoint_rollback=innobase_rollback_to_savepoint;
1728
innobase_hton->savepoint_release=innobase_release_savepoint;
1729
innobase_hton->commit=innobase_commit;
1730
innobase_hton->rollback=innobase_rollback;
1731
innobase_hton->prepare=innobase_xa_prepare;
1732
innobase_hton->recover=innobase_xa_recover;
1733
innobase_hton->commit_by_xid=innobase_commit_by_xid;
1734
innobase_hton->rollback_by_xid=innobase_rollback_by_xid;
1735
innobase_hton->create_cursor_read_view=innobase_create_cursor_view;
1736
innobase_hton->set_cursor_read_view=innobase_set_cursor_view;
1737
innobase_hton->close_cursor_read_view=innobase_close_cursor_view;
1738
innobase_hton->create=innobase_create_handler;
1739
innobase_hton->drop_database=innobase_drop_database;
1740
innobase_hton->panic=innobase_end;
1741
innobase_hton->start_consistent_snapshot=innobase_start_trx_and_assign_read_view;
1742
innobase_hton->flush_logs=innobase_flush_logs;
1743
innobase_hton->show_status=innobase_show_status;
1744
innobase_hton->flags=HTON_NO_FLAGS;
1745
innobase_hton->release_temporary_latches=innobase_release_temporary_latches;
1747
ut_a(DATA_MYSQL_TRUE_VARCHAR == (ulint)MYSQL_TYPE_VARCHAR);
1750
static const char test_filename[] = "-@";
1751
char test_tablename[sizeof test_filename
1752
+ sizeof srv_mysql50_table_name_prefix];
1753
if ((sizeof test_tablename) - 1
1754
!= filename_to_tablename(test_filename, test_tablename,
1755
sizeof test_tablename)
1756
|| strncmp(test_tablename,
1757
srv_mysql50_table_name_prefix,
1758
sizeof srv_mysql50_table_name_prefix)
1759
|| strcmp(test_tablename
1760
+ sizeof srv_mysql50_table_name_prefix,
1762
sql_print_error("tablename encoding has been changed");
1765
#endif /* UNIV_DEBUG */
1767
/* Check that values don't overflow on 32-bit systems. */
1768
if (sizeof(ulint) == 4) {
1769
if (innobase_buffer_pool_size > UINT_MAX32) {
1771
"innobase_buffer_pool_size can't be over 4GB"
1772
" on 32-bit systems");
1777
if (innobase_log_file_size > UINT_MAX32) {
1779
"innobase_log_file_size can't be over 4GB"
1780
" on 32-bit systems");
1786
os_innodb_umask = (ulint)my_umask;
1788
/* First calculate the default path for innodb_data_home_dir etc.,
1789
in case the user has not given any value.
1791
Note that when using the embedded server, the datadirectory is not
1792
necessarily the current directory of this program. */
1794
if (mysqld_embedded) {
1795
default_path = mysql_real_data_home;
1796
fil_path_to_mysql_datadir = mysql_real_data_home;
1798
/* It's better to use current lib, to keep paths short */
1799
current_dir[0] = FN_CURLIB;
1800
current_dir[1] = FN_LIBCHAR;
1802
default_path = current_dir;
1807
if (specialflag & SPECIAL_NO_PRIOR) {
1808
srv_set_thread_priorities = FALSE;
1810
srv_set_thread_priorities = TRUE;
1811
srv_query_thread_priority = QUERY_PRIOR;
1814
/* Set InnoDB initialization parameters according to the values
1815
read from MySQL .cnf file */
1817
/*--------------- Data files -------------------------*/
1819
/* The default dir for data files is the datadir of MySQL */
1821
srv_data_home = (innobase_data_home_dir ? innobase_data_home_dir :
1824
/* Set default InnoDB data file size to 10 MB and let it be
1825
auto-extending. Thus users can use InnoDB in >= 4.0 without having
1826
to specify any startup options. */
1828
if (!innobase_data_file_path) {
1829
innobase_data_file_path = (char*) "ibdata1:10M:autoextend";
1832
/* Since InnoDB edits the argument in the next call, we make another
1835
internal_innobase_data_file_path = my_strdup(innobase_data_file_path,
1838
ret = (bool) srv_parse_data_file_paths_and_sizes(
1839
internal_innobase_data_file_path,
1840
&srv_data_file_names,
1841
&srv_data_file_sizes,
1842
&srv_data_file_is_raw_partition,
1844
&srv_auto_extend_last_data_file,
1845
&srv_last_file_size_max);
1848
"InnoDB: syntax error in innodb_data_file_path");
1849
my_free(internal_innobase_data_file_path,
1850
MYF(MY_ALLOW_ZERO_PTR));
1854
/* -------------- Log files ---------------------------*/
1856
/* The default dir for log files is the datadir of MySQL */
1858
if (!innobase_log_group_home_dir) {
1859
innobase_log_group_home_dir = default_path;
1862
#ifdef UNIV_LOG_ARCHIVE
1863
/* Since innodb_log_arch_dir has no relevance under MySQL,
1864
starting from 4.0.6 we always set it the same as
1865
innodb_log_group_home_dir: */
1867
innobase_log_arch_dir = innobase_log_group_home_dir;
1869
srv_arch_dir = innobase_log_arch_dir;
1870
#endif /* UNIG_LOG_ARCHIVE */
1873
srv_parse_log_group_home_dirs(innobase_log_group_home_dir,
1874
&srv_log_group_home_dirs);
1876
if (ret == FALSE || innobase_mirrored_log_groups != 1) {
1877
sql_print_error("syntax error in innodb_log_group_home_dir, or a "
1878
"wrong number of mirrored log groups");
1880
my_free(internal_innobase_data_file_path,
1881
MYF(MY_ALLOW_ZERO_PTR));
1885
/* --------------------------------------------------*/
1887
srv_file_flush_method_str = innobase_unix_file_flush_method;
1889
srv_n_log_groups = (ulint) innobase_mirrored_log_groups;
1890
srv_n_log_files = (ulint) innobase_log_files_in_group;
1891
srv_log_file_size = (ulint) innobase_log_file_size;
1893
#ifdef UNIV_LOG_ARCHIVE
1894
srv_log_archive_on = (ulint) innobase_log_archive;
1895
#endif /* UNIV_LOG_ARCHIVE */
1896
srv_log_buffer_size = (ulint) innobase_log_buffer_size;
1898
/* We set srv_pool_size here in units of 1 kB. InnoDB internally
1899
changes the value so that it becomes the number of database pages. */
1901
if (innobase_buffer_pool_awe_mem_mb == 0) {
1902
srv_pool_size = (ulint)(innobase_buffer_pool_size / 1024);
1905
srv_pool_size = (ulint)
1906
(1024 * innobase_buffer_pool_awe_mem_mb);
1907
srv_awe_window_size = (ulint) innobase_buffer_pool_size;
1909
/* Note that what the user specified as
1910
innodb_buffer_pool_size is actually the AWE memory window
1911
size in this case, and the real buffer pool size is
1912
determined by .._awe_mem_mb. */
1915
srv_mem_pool_size = (ulint) innobase_additional_mem_pool_size;
1917
srv_n_file_io_threads = (ulint) innobase_file_io_threads;
1919
srv_lock_wait_timeout = (ulint) innobase_lock_wait_timeout;
1920
srv_force_recovery = (ulint) innobase_force_recovery;
1922
srv_use_doublewrite_buf = (ibool) innobase_use_doublewrite;
1923
srv_use_checksums = (ibool) innobase_use_checksums;
1925
#ifdef HAVE_LARGE_PAGES
1926
if ((os_use_large_pages = (ibool) my_use_large_pages))
1927
os_large_page_size = (ulint) opt_large_page_size;
1930
row_rollback_on_timeout = (ibool) innobase_rollback_on_timeout;
1932
srv_file_per_table = (ibool) innobase_file_per_table;
1933
srv_locks_unsafe_for_binlog = (ibool) innobase_locks_unsafe_for_binlog;
1935
srv_max_n_open_files = (ulint) innobase_open_files;
1936
srv_innodb_status = (ibool) innobase_create_status_file;
1938
srv_use_adaptive_hash_indexes =
1939
(ibool) innobase_adaptive_hash_index;
1941
srv_print_verbose_log = mysqld_embedded ? 0 : 1;
1943
/* Store the default charset-collation number of this MySQL
1946
data_mysql_default_charset_coll = (ulint)default_charset_info->number;
1948
ut_a(DATA_MYSQL_LATIN1_SWEDISH_CHARSET_COLL ==
1949
my_charset_latin1.number);
1950
ut_a(DATA_MYSQL_BINARY_CHARSET_COLL == my_charset_bin.number);
1952
/* Store the latin1_swedish_ci character ordering table to InnoDB. For
1953
non-latin1_swedish_ci charsets we use the MySQL comparison functions,
1954
and consequently we do not need to know the ordering internally in
1957
ut_a(0 == strcmp((char*)my_charset_latin1.name,
1958
(char*)"latin1_swedish_ci"));
1959
memcpy(srv_latin1_ordering, my_charset_latin1.sort_order, 256);
1961
innobase_commit_concurrency_init_default();
1963
/* Since we in this module access directly the fields of a trx
1964
struct, and due to different headers and flags it might happen that
1965
mutex_t has a different size in this module and in InnoDB
1966
modules, we check at run time that the size is the same in
1967
these compilation modules. */
1969
srv_sizeof_trx_t_in_ha_innodb_cc = sizeof(trx_t);
1971
err = innobase_start_or_create_for_mysql();
1973
if (err != DB_SUCCESS) {
1974
my_free(internal_innobase_data_file_path,
1975
MYF(MY_ALLOW_ZERO_PTR));
1979
(void) hash_init(&innobase_open_tables,system_charset_info, 32, 0, 0,
1980
(hash_get_key) innobase_get_key, 0, 0);
1981
pthread_mutex_init(&innobase_share_mutex, MY_MUTEX_INIT_FAST);
1982
pthread_mutex_init(&prepare_commit_mutex, MY_MUTEX_INIT_FAST);
1983
pthread_mutex_init(&commit_threads_m, MY_MUTEX_INIT_FAST);
1984
pthread_mutex_init(&commit_cond_m, MY_MUTEX_INIT_FAST);
1985
pthread_mutex_init(&analyze_mutex, MY_MUTEX_INIT_FAST);
1986
pthread_cond_init(&commit_cond, NULL);
1994
/***********************************************************************
1995
Closes an InnoDB database. */
1998
innobase_end(handlerton *hton, ha_panic_function type)
2000
/* out: TRUE if error */
2004
DBUG_ENTER("innobase_end");
2006
#ifdef __NETWARE__ /* some special cleanup for NetWare */
2008
set_panic_flag_for_netware();
2011
if (innodb_inited) {
2013
srv_fast_shutdown = (ulint) innobase_fast_shutdown;
2015
if (innobase_shutdown_for_mysql() != DB_SUCCESS) {
2018
hash_free(&innobase_open_tables);
2019
my_free(internal_innobase_data_file_path,
2020
MYF(MY_ALLOW_ZERO_PTR));
2021
pthread_mutex_destroy(&innobase_share_mutex);
2022
pthread_mutex_destroy(&prepare_commit_mutex);
2023
pthread_mutex_destroy(&commit_threads_m);
2024
pthread_mutex_destroy(&commit_cond_m);
2025
pthread_mutex_destroy(&analyze_mutex);
2026
pthread_cond_destroy(&commit_cond);
2032
/********************************************************************
2033
Flushes InnoDB logs to disk and makes a checkpoint. Really, a commit flushes
2034
the logs, and the name of this function should be innobase_checkpoint. */
2037
innobase_flush_logs(handlerton *hton)
2038
/*=====================*/
2039
/* out: TRUE if error */
2043
DBUG_ENTER("innobase_flush_logs");
2045
log_buffer_flush_to_disk();
2047
DBUG_RETURN(result);
2050
/*********************************************************************
2051
Commits a transaction in an InnoDB database. */
2054
innobase_commit_low(
2055
/*================*/
2056
trx_t* trx) /* in: transaction handle */
2058
if (trx->conc_state == TRX_NOT_STARTED) {
2063
trx_commit_for_mysql(trx);
2066
/*********************************************************************
2067
Creates an InnoDB transaction struct for the thd if it does not yet have one.
2068
Starts a new InnoDB transaction if a transaction is not yet started. And
2069
assigns a new snapshot for a consistent read if the transaction does not yet
2073
innobase_start_trx_and_assign_read_view(
2074
/*====================================*/
2076
handlerton *hton, /* in: Innodb handlerton */
2077
THD* thd) /* in: MySQL thread handle of the user for whom
2078
the transaction should be committed */
2082
DBUG_ENTER("innobase_start_trx_and_assign_read_view");
2084
/* Create a new trx struct for thd, if it does not yet have one */
2086
trx = check_trx_exists(thd);
2088
/* This is just to play safe: release a possible FIFO ticket and
2089
search latch. Since we will reserve the kernel mutex, we have to
2090
release the search system latch first to obey the latching order. */
2092
innobase_release_stat_resources(trx);
2094
/* If the transaction is not started yet, start it */
2096
trx_start_if_not_started_noninline(trx);
2098
/* Assign a read view if the transaction does not have it yet */
2100
trx_assign_read_view(trx);
2102
/* Set the MySQL flag to mark that there is an active transaction */
2104
if (trx->active_trans == 0) {
2105
innobase_register_trx_and_stmt(hton, current_thd);
2106
trx->active_trans = 1;
2112
/*********************************************************************
2113
Commits a transaction in an InnoDB database or marks an SQL statement
2120
handlerton *hton, /* in: Innodb handlerton */
2121
THD* thd, /* in: MySQL thread handle of the user for whom
2122
the transaction should be committed */
2123
bool all) /* in: TRUE - commit transaction
2124
FALSE - the current SQL statement ended */
2128
DBUG_ENTER("innobase_commit");
2129
DBUG_PRINT("trans", ("ending transaction"));
2131
trx = check_trx_exists(thd);
2133
/* Update the info whether we should skip XA steps that eat CPU time */
2134
trx->support_xa = THDVAR(thd, support_xa);
2136
/* Since we will reserve the kernel mutex, we have to release
2137
the search system latch first to obey the latching order. */
2139
if (trx->has_search_latch) {
2140
trx_search_latch_release_if_reserved(trx);
2143
/* The flag trx->active_trans is set to 1 in
2145
1. ::external_lock(),
2147
3. innobase_query_caching_of_table_permitted(),
2148
4. innobase_savepoint(),
2149
5. ::init_table_handle_for_HANDLER(),
2150
6. innobase_start_trx_and_assign_read_view(),
2151
7. ::transactional_table_lock()
2153
and it is only set to 0 in a commit or a rollback. If it is 0 we know
2154
there cannot be resources to be freed and we could return immediately.
2155
For the time being, we play safe and do the cleanup though there should
2156
be nothing to clean up. */
2158
if (trx->active_trans == 0
2159
&& trx->conc_state != TRX_NOT_STARTED) {
2161
sql_print_error("trx->active_trans == 0, but"
2162
" trx->conc_state != TRX_NOT_STARTED");
2165
|| (!thd_test_options(thd, OPTION_NOT_AUTOCOMMIT | OPTION_BEGIN))) {
2167
/* We were instructed to commit the whole transaction, or
2168
this is an SQL statement end and autocommit is on */
2170
/* We need current binlog position for ibbackup to work.
2171
Note, the position is current because of
2172
prepare_commit_mutex */
2174
if (innobase_commit_concurrency > 0) {
2175
pthread_mutex_lock(&commit_cond_m);
2178
if (commit_threads > innobase_commit_concurrency) {
2180
pthread_cond_wait(&commit_cond,
2182
pthread_mutex_unlock(&commit_cond_m);
2186
pthread_mutex_unlock(&commit_cond_m);
2190
trx->mysql_log_file_name = mysql_bin_log_file_name();
2191
trx->mysql_log_offset = (ib_longlong) mysql_bin_log_file_pos();
2193
innobase_commit_low(trx);
2195
if (innobase_commit_concurrency > 0) {
2196
pthread_mutex_lock(&commit_cond_m);
2198
pthread_cond_signal(&commit_cond);
2199
pthread_mutex_unlock(&commit_cond_m);
2202
if (trx->active_trans == 2) {
2204
pthread_mutex_unlock(&prepare_commit_mutex);
2207
trx->active_trans = 0;
2210
/* We just mark the SQL statement ended and do not do a
2211
transaction commit */
2213
/* If we had reserved the auto-inc lock for some
2214
table in this SQL statement we release it now */
2216
row_unlock_table_autoinc_for_mysql(trx);
2218
/* Store the current undo_no of the transaction so that we
2219
know where to roll back if we have to roll back the next
2222
trx_mark_sql_stat_end(trx);
2225
trx->n_autoinc_rows = 0; /* Reset the number AUTO-INC rows required */
2227
if (trx->declared_to_be_inside_innodb) {
2228
/* Release our possible ticket in the FIFO */
2230
srv_conc_force_exit_innodb(trx);
2233
/* Tell the InnoDB server that there might be work for utility
2235
srv_active_wake_master_thread();
2240
/*********************************************************************
2241
Rolls back a transaction or the latest SQL statement. */
2246
/* out: 0 or error number */
2247
handlerton *hton, /* in: Innodb handlerton */
2248
THD* thd, /* in: handle to the MySQL thread of the user
2249
whose transaction should be rolled back */
2250
bool all) /* in: TRUE - commit transaction
2251
FALSE - the current SQL statement ended */
2256
DBUG_ENTER("innobase_rollback");
2257
DBUG_PRINT("trans", ("aborting transaction"));
2259
trx = check_trx_exists(thd);
2261
/* Update the info whether we should skip XA steps that eat CPU time */
2262
trx->support_xa = THDVAR(thd, support_xa);
2264
/* Release a possible FIFO ticket and search latch. Since we will
2265
reserve the kernel mutex, we have to release the search system latch
2266
first to obey the latching order. */
2268
innobase_release_stat_resources(trx);
2270
trx->n_autoinc_rows = 0; /* Reset the number AUTO-INC rows required */
2272
/* If we had reserved the auto-inc lock for some table (if
2273
we come here to roll back the latest SQL statement) we
2274
release it now before a possibly lengthy rollback */
2276
row_unlock_table_autoinc_for_mysql(trx);
2279
|| !thd_test_options(thd, OPTION_NOT_AUTOCOMMIT | OPTION_BEGIN)) {
2281
error = trx_rollback_for_mysql(trx);
2282
trx->active_trans = 0;
2284
error = trx_rollback_last_sql_stat_for_mysql(trx);
2287
DBUG_RETURN(convert_error_code_to_mysql(error, NULL));
2290
/*********************************************************************
2291
Rolls back a transaction */
2294
innobase_rollback_trx(
2295
/*==================*/
2296
/* out: 0 or error number */
2297
trx_t* trx) /* in: transaction */
2301
DBUG_ENTER("innobase_rollback_trx");
2302
DBUG_PRINT("trans", ("aborting transaction"));
2304
/* Release a possible FIFO ticket and search latch. Since we will
2305
reserve the kernel mutex, we have to release the search system latch
2306
first to obey the latching order. */
2308
innobase_release_stat_resources(trx);
2310
/* If we had reserved the auto-inc lock for some table (if
2311
we come here to roll back the latest SQL statement) we
2312
release it now before a possibly lengthy rollback */
2314
row_unlock_table_autoinc_for_mysql(trx);
2316
error = trx_rollback_for_mysql(trx);
2318
DBUG_RETURN(convert_error_code_to_mysql(error, NULL));
2321
/*********************************************************************
2322
Rolls back a transaction to a savepoint. */
2325
innobase_rollback_to_savepoint(
2326
/*===========================*/
2327
/* out: 0 if success, HA_ERR_NO_SAVEPOINT if
2328
no savepoint with the given name */
2329
handlerton *hton, /* in: Innodb handlerton */
2330
THD* thd, /* in: handle to the MySQL thread of the user
2331
whose transaction should be rolled back */
2332
void* savepoint) /* in: savepoint data */
2334
ib_longlong mysql_binlog_cache_pos;
2339
DBUG_ENTER("innobase_rollback_to_savepoint");
2341
trx = check_trx_exists(thd);
2343
/* Release a possible FIFO ticket and search latch. Since we will
2344
reserve the kernel mutex, we have to release the search system latch
2345
first to obey the latching order. */
2347
innobase_release_stat_resources(trx);
2349
/* TODO: use provided savepoint data area to store savepoint data */
2351
longlong2str((ulint)savepoint, name, 36);
2353
error = (int) trx_rollback_to_savepoint_for_mysql(trx, name,
2354
&mysql_binlog_cache_pos);
2355
DBUG_RETURN(convert_error_code_to_mysql(error, NULL));
2358
/*********************************************************************
2359
Release transaction savepoint name. */
2362
innobase_release_savepoint(
2363
/*=======================*/
2364
/* out: 0 if success, HA_ERR_NO_SAVEPOINT if
2365
no savepoint with the given name */
2366
handlerton* hton, /* in: handlerton for Innodb */
2367
THD* thd, /* in: handle to the MySQL thread of the user
2368
whose transaction should be rolled back */
2369
void* savepoint) /* in: savepoint data */
2375
DBUG_ENTER("innobase_release_savepoint");
2377
trx = check_trx_exists(thd);
2379
/* TODO: use provided savepoint data area to store savepoint data */
2381
longlong2str((ulint)savepoint, name, 36);
2383
error = (int) trx_release_savepoint_for_mysql(trx, name);
2385
DBUG_RETURN(convert_error_code_to_mysql(error, NULL));
2388
/*********************************************************************
2389
Sets a transaction savepoint. */
2394
/* out: always 0, that is, always succeeds */
2395
handlerton* hton, /* in: handle to the Innodb handlerton */
2396
THD* thd, /* in: handle to the MySQL thread */
2397
void* savepoint) /* in: savepoint data */
2402
DBUG_ENTER("innobase_savepoint");
2405
In the autocommit mode there is no sense to set a savepoint
2406
(unless we are in sub-statement), so SQL layer ensures that
2407
this method is never called in such situation.
2409
#ifdef MYSQL_SERVER /* plugins cannot access thd->in_sub_stmt */
2410
DBUG_ASSERT(thd_test_options(thd, OPTION_NOT_AUTOCOMMIT | OPTION_BEGIN) ||
2412
#endif /* MYSQL_SERVER */
2414
trx = check_trx_exists(thd);
2416
/* Release a possible FIFO ticket and search latch. Since we will
2417
reserve the kernel mutex, we have to release the search system latch
2418
first to obey the latching order. */
2420
innobase_release_stat_resources(trx);
2422
/* cannot happen outside of transaction */
2423
DBUG_ASSERT(trx->active_trans);
2425
/* TODO: use provided savepoint data area to store savepoint data */
2427
longlong2str((ulint)savepoint,name,36);
2429
error = (int) trx_savepoint_for_mysql(trx, name, (ib_longlong)0);
2431
DBUG_RETURN(convert_error_code_to_mysql(error, NULL));
2434
/*********************************************************************
2435
Frees a possible InnoDB trx object associated with the current THD. */
2438
innobase_close_connection(
2439
/*======================*/
2440
/* out: 0 or error number */
2441
handlerton* hton, /* in: innobase handlerton */
2442
THD* thd) /* in: handle to the MySQL thread of the user
2443
whose resources should be free'd */
2447
DBUG_ENTER("innobase_close_connection");
2448
DBUG_ASSERT(hton == innodb_hton_ptr);
2449
trx = thd_to_trx(thd);
2453
if (trx->active_trans == 0
2454
&& trx->conc_state != TRX_NOT_STARTED) {
2456
sql_print_error("trx->active_trans == 0, but"
2457
" trx->conc_state != TRX_NOT_STARTED");
2461
if (trx->conc_state != TRX_NOT_STARTED &&
2462
global_system_variables.log_warnings) {
2464
"MySQL is closing a connection that has an active "
2465
"InnoDB transaction. %lu row modifications will "
2467
(ulong) trx->undo_no.low);
2470
innobase_rollback_trx(trx);
2472
thr_local_free(trx->mysql_thread_id);
2473
trx_free_for_mysql(trx);
2479
/*****************************************************************************
2480
** InnoDB database tables
2481
*****************************************************************************/
2483
/********************************************************************
2484
Get the record format from the data dictionary. */
2486
ha_innobase::get_row_type() const
2487
/*=============================*/
2488
/* out: ROW_TYPE_REDUNDANT or ROW_TYPE_COMPACT */
2490
if (prebuilt && prebuilt->table) {
2491
if (dict_table_is_comp_noninline(prebuilt->table)) {
2492
return(ROW_TYPE_COMPACT);
2494
return(ROW_TYPE_REDUNDANT);
2498
return(ROW_TYPE_NOT_USED);
2503
/********************************************************************
2504
Get the table flags to use for the statement. */
2505
handler::Table_flags
2506
ha_innobase::table_flags() const
2508
/* Need to use tx_isolation here since table flags is (also)
2509
called before prebuilt is inited. */
2510
ulong const tx_isolation = thd_tx_isolation(current_thd);
2511
if (tx_isolation <= ISO_READ_COMMITTED)
2512
return int_table_flags;
2513
return int_table_flags | HA_BINLOG_STMT_CAPABLE;
2516
/********************************************************************
2517
Gives the file extension of an InnoDB single-table tablespace. */
2518
static const char* ha_innobase_exts[] = {
2524
ha_innobase::bas_ext() const
2525
/*========================*/
2526
/* out: file extension string */
2528
return ha_innobase_exts;
2532
/*********************************************************************
2533
Normalizes a table name string. A normalized name consists of the
2534
database name catenated to '/' and table name. An example:
2535
test/mytable. On Windows normalization puts both the database name and the
2536
table name always to lower case. */
2539
normalize_table_name(
2540
/*=================*/
2541
char* norm_name, /* out: normalized name as a
2542
null-terminated string */
2543
const char* name) /* in: table name string */
2549
/* Scan name from the end */
2551
ptr = strend(name)-1;
2553
while (ptr >= name && *ptr != '\\' && *ptr != '/') {
2559
DBUG_ASSERT(ptr > name);
2563
while (ptr >= name && *ptr != '\\' && *ptr != '/') {
2569
memcpy(norm_name, db_ptr, strlen(name) + 1 - (db_ptr - name));
2571
norm_name[name_ptr - db_ptr - 1] = '/';
2574
innobase_casedn_str(norm_name);
2578
/************************************************************************
2579
Get the upper limit of the MySQL integral and floating-point type. */
2582
innobase_get_int_col_max_value(
2583
/*===========================*/
2584
/* out: maximum allowed value for the field */
2585
const Field* field) /* in: MySQL field */
2587
ulonglong max_value = 0;
2589
switch(field->key_type()) {
2591
case HA_KEYTYPE_BINARY:
2592
max_value = 0xFFULL;
2594
case HA_KEYTYPE_INT8:
2595
max_value = 0x7FULL;
2598
case HA_KEYTYPE_USHORT_INT:
2599
max_value = 0xFFFFULL;
2601
case HA_KEYTYPE_SHORT_INT:
2602
max_value = 0x7FFFULL;
2605
case HA_KEYTYPE_UINT24:
2606
max_value = 0xFFFFFFULL;
2608
case HA_KEYTYPE_INT24:
2609
max_value = 0x7FFFFFULL;
2612
case HA_KEYTYPE_ULONG_INT:
2613
max_value = 0xFFFFFFFFULL;
2615
case HA_KEYTYPE_LONG_INT:
2616
max_value = 0x7FFFFFFFULL;
2619
case HA_KEYTYPE_ULONGLONG:
2620
max_value = 0xFFFFFFFFFFFFFFFFULL;
2622
case HA_KEYTYPE_LONGLONG:
2623
max_value = 0x7FFFFFFFFFFFFFFFULL;
2625
case HA_KEYTYPE_FLOAT:
2626
/* We use the maximum as per IEEE754-2008 standard, 2^24 */
2627
max_value = 0x1000000ULL;
2629
case HA_KEYTYPE_DOUBLE:
2630
/* We use the maximum as per IEEE754-2008 standard, 2^53 */
2631
max_value = 0x20000000000000ULL;
2640
/************************************************************************
2641
Set the autoinc column max value. This should only be called once from
2642
ha_innobase::open(). Therefore there's no need for a covering lock. */
2645
ha_innobase::innobase_initialize_autoinc()
2646
/*======================================*/
2649
const Field* field = table->found_next_number_field;
2651
if (field != NULL) {
2652
auto_inc = innobase_get_int_col_max_value(field);
2654
/* We have no idea what's been passed in to us as the
2655
autoinc column. We set it to the 0, effectively disabling
2656
updates to the table. */
2659
ut_print_timestamp(stderr);
2660
fprintf(stderr, " InnoDB: Unable to determine the AUTOINC "
2664
if (srv_force_recovery >= SRV_FORCE_NO_IBUF_MERGE) {
2665
/* If the recovery level is set so high that writes
2666
are disabled we force the AUTOINC counter to 0
2667
value effectively disabling writes to the table.
2668
Secondly, we avoid reading the table in case the read
2669
results in failure due to a corrupted table/index.
2671
We will not return an error to the client, so that the
2672
tables can be dumped with minimal hassle. If an error
2673
were returned in this case, the first attempt to read
2674
the table would fail and subsequent SELECTs would succeed. */
2676
} else if (field == NULL) {
2677
/* This is a far more serious error, best to avoid
2678
opening the table and return failure. */
2679
my_error(ER_AUTOINC_READ_FAILED, MYF(0));
2681
dict_index_t* index;
2682
const char* col_name;
2683
ulonglong read_auto_inc;
2686
update_thd(ha_thd());
2687
col_name = field->field_name;
2688
index = innobase_get_index(table->s->next_number_index);
2690
/* Execute SELECT MAX(col_name) FROM TABLE; */
2691
err = row_search_max_autoinc(index, col_name, &read_auto_inc);
2695
/* At the this stage we do not know the increment
2696
or the offset, so use a default increment of 1. */
2697
auto_inc = read_auto_inc + 1;
2700
case DB_RECORD_NOT_FOUND:
2701
ut_print_timestamp(stderr);
2702
fprintf(stderr, " InnoDB: MySQL and InnoDB data "
2703
"dictionaries are out of sync.\n"
2704
"InnoDB: Unable to find the AUTOINC column "
2705
"%s in the InnoDB table %s.\n"
2706
"InnoDB: We set the next AUTOINC column "
2708
"InnoDB: in effect disabling the AUTOINC "
2709
"next value generation.\n"
2710
"InnoDB: You can either set the next "
2711
"AUTOINC value explicitly using ALTER TABLE\n"
2712
"InnoDB: or fix the data dictionary by "
2713
"recreating the table.\n",
2714
col_name, index->table->name);
2716
/* This will disable the AUTOINC generation. */
2719
/* We want the open to succeed, so that the user can
2720
take corrective action. ie. reads should succeed but
2721
updates should fail. */
2725
/* row_search_max_autoinc() should only return
2726
one of DB_SUCCESS or DB_RECORD_NOT_FOUND. */
2731
dict_table_autoinc_initialize(prebuilt->table, auto_inc);
2734
/*********************************************************************
2735
Creates and opens a handle to a table which already exists in an InnoDB
2741
/* out: 1 if error, 0 if success */
2742
const char* name, /* in: table name */
2743
int mode, /* in: not used */
2744
uint test_if_locked) /* in: not used */
2746
dict_table_t* ib_table;
2747
char norm_name[1000];
2750
char* is_part = NULL;
2752
DBUG_ENTER("ha_innobase::open");
2755
UT_NOT_USED(test_if_locked);
2759
/* Under some cases MySQL seems to call this function while
2760
holding btr_search_latch. This breaks the latching order as
2761
we acquire dict_sys->mutex below and leads to a deadlock. */
2763
innobase_release_temporary_latches(ht, thd);
2766
normalize_table_name(norm_name, name);
2770
if (!(share=get_share(name))) {
2775
/* Create buffers for packing the fields of a record. Why
2776
table->reclength did not work here? Obviously, because char
2777
fields when packed actually became 1 byte longer, when we also
2778
stored the string length as the first byte. */
2780
upd_and_key_val_buff_len =
2781
table->s->reclength + table->s->max_key_length
2782
+ MAX_REF_PARTS * 3;
2783
if (!(uchar*) my_multi_malloc(MYF(MY_WME),
2784
&upd_buff, upd_and_key_val_buff_len,
2785
&key_val_buff, upd_and_key_val_buff_len,
2792
/* We look for pattern #P# to see if the table is partitioned
2793
MySQL table. The retry logic for partitioned tables is a
2794
workaround for http://bugs.mysql.com/bug.php?id=33349. Look
2795
at support issue https://support.mysql.com/view.php?id=21080
2796
for more details. */
2797
is_part = strstr(norm_name, "#P#");
2799
/* Get pointer to a table object in InnoDB dictionary cache */
2800
ib_table = dict_table_get(norm_name, TRUE);
2802
if (NULL == ib_table) {
2803
if (is_part && retries < 10) {
2805
os_thread_sleep(100000);
2810
sql_print_error("Failed to open table %s after "
2811
"%lu attemtps.\n", norm_name,
2815
sql_print_error("Cannot find or open table %s from\n"
2816
"the internal data dictionary of InnoDB "
2817
"though the .frm file for the\n"
2818
"table exists. Maybe you have deleted and "
2819
"recreated InnoDB data\n"
2820
"files but have forgotten to delete the "
2821
"corresponding .frm files\n"
2822
"of InnoDB tables, or you have moved .frm "
2823
"files to another database?\n"
2824
"or, the table contains indexes that this "
2825
"version of the engine\n"
2826
"doesn't support.\n"
2827
"See http://dev.mysql.com/doc/refman/5.1/en/innodb-troubleshooting.html\n"
2828
"how you can resolve the problem.\n",
2831
my_free(upd_buff, MYF(0));
2834
DBUG_RETURN(HA_ERR_NO_SUCH_TABLE);
2837
if (ib_table->ibd_file_missing && !thd_tablespace_op(thd)) {
2838
sql_print_error("MySQL is trying to open a table handle but "
2839
"the .ibd file for\ntable %s does not exist.\n"
2840
"Have you deleted the .ibd file from the "
2841
"database directory under\nthe MySQL datadir, "
2842
"or have you used DISCARD TABLESPACE?\n"
2843
"See http://dev.mysql.com/doc/refman/5.1/en/innodb-troubleshooting.html\n"
2844
"how you can resolve the problem.\n",
2847
my_free(upd_buff, MYF(0));
2850
dict_table_decrement_handle_count(ib_table);
2851
DBUG_RETURN(HA_ERR_NO_SUCH_TABLE);
2854
prebuilt = row_create_prebuilt(ib_table);
2856
prebuilt->mysql_row_len = table->s->reclength;
2857
prebuilt->default_rec = table->s->default_values;
2858
ut_ad(prebuilt->default_rec);
2860
/* Looks like MySQL-3.23 sometimes has primary key number != 0 */
2862
primary_key = table->s->primary_key;
2863
key_used_on_scan = primary_key;
2865
/* Allocate a buffer for a 'row reference'. A row reference is
2866
a string of bytes of length ref_length which uniquely specifies
2867
a row in our table. Note that MySQL may also compare two row
2868
references for equality by doing a simple memcmp on the strings
2869
of length ref_length! */
2871
if (!row_table_got_default_clust_index(ib_table)) {
2872
if (primary_key >= MAX_KEY) {
2873
sql_print_error("Table %s has a primary key in InnoDB data "
2874
"dictionary, but not in MySQL!", name);
2877
prebuilt->clust_index_was_generated = FALSE;
2879
/* MySQL allocates the buffer for ref. key_info->key_length
2880
includes space for all key columns + one byte for each column
2881
that may be NULL. ref_length must be as exact as possible to
2882
save space, because all row reference buffers are allocated
2883
based on ref_length. */
2885
ref_length = table->key_info[primary_key].key_length;
2887
if (primary_key != MAX_KEY) {
2888
sql_print_error("Table %s has no primary key in InnoDB data "
2889
"dictionary, but has one in MySQL! If you "
2890
"created the table with a MySQL version < "
2891
"3.23.54 and did not define a primary key, "
2892
"but defined a unique key with all non-NULL "
2893
"columns, then MySQL internally treats that "
2894
"key as the primary key. You can fix this "
2895
"error by dump + DROP + CREATE + reimport "
2896
"of the table.", name);
2899
prebuilt->clust_index_was_generated = TRUE;
2901
ref_length = DATA_ROW_ID_LEN;
2903
/* If we automatically created the clustered index, then
2904
MySQL does not know about it, and MySQL must NOT be aware
2905
of the index used on scan, to make it avoid checking if we
2906
update the column of the index. That is why we assert below
2907
that key_used_on_scan is the undefined value MAX_KEY.
2908
The column is the row id in the automatical generation case,
2909
and it will never be updated anyway. */
2911
if (key_used_on_scan != MAX_KEY) {
2913
"Table %s key_used_on_scan is %lu even "
2914
"though there is no primary key inside "
2915
"InnoDB.", name, (ulong) key_used_on_scan);
2919
stats.block_size = 16 * 1024; /* Index block size in InnoDB: used by MySQL
2920
in query optimization */
2922
/* Init table lock structure */
2923
thr_lock_data_init(&share->lock,&lock,(void*) 0);
2925
info(HA_STATUS_NO_LOCK | HA_STATUS_VARIABLE | HA_STATUS_CONST);
2927
/* Only if the table has an AUTOINC column. */
2928
if (prebuilt->table != NULL && table->found_next_number_field != NULL) {
2929
dict_table_autoinc_lock(prebuilt->table);
2931
/* Since a table can already be "open" in InnoDB's internal
2932
data dictionary, we only init the autoinc counter once, the
2933
first time the table is loaded. We can safely reuse the
2934
autoinc value from a previous MySQL open. */
2935
if (dict_table_autoinc_read(prebuilt->table) == 0) {
2937
innobase_initialize_autoinc();
2940
dict_table_autoinc_unlock(prebuilt->table);
2947
ha_innobase::max_supported_key_part_length() const
2949
return(DICT_MAX_INDEX_COL_LEN - 1);
2952
/**********************************************************************
2953
Closes a handle to an InnoDB table. */
2956
ha_innobase::close(void)
2957
/*====================*/
2962
DBUG_ENTER("ha_innobase::close");
2964
thd = current_thd; // avoid calling current_thd twice, it may be slow
2966
innobase_release_temporary_latches(ht, thd);
2969
row_prebuilt_free(prebuilt);
2971
my_free(upd_buff, MYF(0));
2974
/* Tell InnoDB server that there might be work for
2977
srv_active_wake_master_thread();
2982
/* The following accessor functions should really be inside MySQL code! */
2984
/******************************************************************
2985
Gets field offset for a field in a table. */
2991
TABLE* table, /* in: MySQL table object */
2992
Field* field) /* in: MySQL field object */
2994
return((uint) (field->ptr - table->record[0]));
2997
/******************************************************************
2998
Checks if a field in a record is SQL NULL. Uses the record format
2999
information in table to track the null bit in record. */
3002
field_in_record_is_null(
3003
/*====================*/
3004
/* out: 1 if NULL, 0 otherwise */
3005
TABLE* table, /* in: MySQL table object */
3006
Field* field, /* in: MySQL field object */
3007
char* record) /* in: a row in MySQL format */
3011
if (!field->null_ptr) {
3016
null_offset = (uint) ((char*) field->null_ptr
3017
- (char*) table->record[0]);
3019
if (record[null_offset] & field->null_bit) {
3027
/******************************************************************
3028
Sets a field in a record to SQL NULL. Uses the record format
3029
information in table to track the null bit in record. */
3032
set_field_in_record_to_null(
3033
/*========================*/
3034
TABLE* table, /* in: MySQL table object */
3035
Field* field, /* in: MySQL field object */
3036
char* record) /* in: a row in MySQL format */
3040
null_offset = (uint) ((char*) field->null_ptr
3041
- (char*) table->record[0]);
3043
record[null_offset] = record[null_offset] | field->null_bit;
3047
/*****************************************************************
3048
InnoDB uses this function to compare two data fields for which the data type
3049
is such that we must use MySQL code to compare them. NOTE that the prototype
3050
of this function is in rem0cmp.c in InnoDB source code! If you change this
3051
function, remember to update the prototype there! */
3056
/* out: 1, 0, -1, if a is greater,
3057
equal, less than b, respectively */
3058
int mysql_type, /* in: MySQL type */
3059
uint charset_number, /* in: number of the charset */
3060
unsigned char* a, /* in: data field */
3061
unsigned int a_length, /* in: data field length,
3062
not UNIV_SQL_NULL */
3063
unsigned char* b, /* in: data field */
3064
unsigned int b_length) /* in: data field length,
3065
not UNIV_SQL_NULL */
3067
CHARSET_INFO* charset;
3068
enum_field_types mysql_tp;
3071
DBUG_ASSERT(a_length != UNIV_SQL_NULL);
3072
DBUG_ASSERT(b_length != UNIV_SQL_NULL);
3074
mysql_tp = (enum_field_types) mysql_type;
3078
case MYSQL_TYPE_BIT:
3079
case MYSQL_TYPE_STRING:
3080
case MYSQL_TYPE_VAR_STRING:
3081
case MYSQL_TYPE_TINY_BLOB:
3082
case MYSQL_TYPE_MEDIUM_BLOB:
3083
case MYSQL_TYPE_BLOB:
3084
case MYSQL_TYPE_LONG_BLOB:
3085
case MYSQL_TYPE_VARCHAR:
3086
/* Use the charset number to pick the right charset struct for
3087
the comparison. Since the MySQL function get_charset may be
3088
slow before Bar removes the mutex operation there, we first
3089
look at 2 common charsets directly. */
3091
if (charset_number == default_charset_info->number) {
3092
charset = default_charset_info;
3093
} else if (charset_number == my_charset_latin1.number) {
3094
charset = &my_charset_latin1;
3096
charset = get_charset(charset_number, MYF(MY_WME));
3098
if (charset == NULL) {
3099
sql_print_error("InnoDB needs charset %lu for doing "
3100
"a comparison, but MySQL cannot "
3101
"find that charset.",
3102
(ulong) charset_number);
3107
/* Starting from 4.1.3, we use strnncollsp() in comparisons of
3108
non-latin1_swedish_ci strings. NOTE that the collation order
3109
changes then: 'b\0\0...' is ordered BEFORE 'b ...'. Users
3110
having indexes on such data need to rebuild their tables! */
3112
ret = charset->coll->strnncollsp(charset,
3117
} else if (ret > 0) {
3130
/******************************************************************
3131
Converts a MySQL type to an InnoDB type. Note that this function returns
3132
the 'mtype' of InnoDB. InnoDB differentiates between MySQL's old <= 4.1
3133
VARCHAR and the new true VARCHAR in >= 5.0.3 by the 'prtype'. */
3136
get_innobase_type_from_mysql_type(
3137
/*==============================*/
3138
/* out: DATA_BINARY, DATA_VARCHAR, ... */
3139
ulint* unsigned_flag, /* out: DATA_UNSIGNED if an 'unsigned type';
3140
at least ENUM and SET, and unsigned integer
3141
types are 'unsigned types' */
3142
Field* field) /* in: MySQL field */
3144
/* The following asserts try to check that the MySQL type code fits in
3145
8 bits: this is used in ibuf and also when DATA_NOT_NULL is ORed to
3148
DBUG_ASSERT((ulint)MYSQL_TYPE_STRING < 256);
3149
DBUG_ASSERT((ulint)MYSQL_TYPE_VAR_STRING < 256);
3150
DBUG_ASSERT((ulint)MYSQL_TYPE_DOUBLE < 256);
3151
DBUG_ASSERT((ulint)MYSQL_TYPE_FLOAT < 256);
3152
DBUG_ASSERT((ulint)MYSQL_TYPE_DECIMAL < 256);
3154
if (field->flags & UNSIGNED_FLAG) {
3156
*unsigned_flag = DATA_UNSIGNED;
3161
if (field->real_type() == MYSQL_TYPE_ENUM
3162
|| field->real_type() == MYSQL_TYPE_SET) {
3164
/* MySQL has field->type() a string type for these, but the
3165
data is actually internally stored as an unsigned integer
3168
*unsigned_flag = DATA_UNSIGNED; /* MySQL has its own unsigned
3169
flag set to zero, even though
3170
internally this is an unsigned
3175
switch (field->type()) {
3176
/* NOTE that we only allow string types in DATA_MYSQL and
3178
case MYSQL_TYPE_VAR_STRING: /* old <= 4.1 VARCHAR */
3179
case MYSQL_TYPE_VARCHAR: /* new >= 5.0.3 true VARCHAR */
3180
if (field->binary()) {
3181
return(DATA_BINARY);
3183
field->charset()->name,
3184
"latin1_swedish_ci") == 0) {
3185
return(DATA_VARCHAR);
3187
return(DATA_VARMYSQL);
3189
case MYSQL_TYPE_BIT:
3190
case MYSQL_TYPE_STRING: if (field->binary()) {
3192
return(DATA_FIXBINARY);
3194
field->charset()->name,
3195
"latin1_swedish_ci") == 0) {
3200
case MYSQL_TYPE_NEWDECIMAL:
3201
return(DATA_FIXBINARY);
3202
case MYSQL_TYPE_LONG:
3203
case MYSQL_TYPE_LONGLONG:
3204
case MYSQL_TYPE_TINY:
3205
case MYSQL_TYPE_SHORT:
3206
case MYSQL_TYPE_INT24:
3207
case MYSQL_TYPE_DATE:
3208
case MYSQL_TYPE_DATETIME:
3209
case MYSQL_TYPE_YEAR:
3210
case MYSQL_TYPE_NEWDATE:
3211
case MYSQL_TYPE_TIME:
3212
case MYSQL_TYPE_TIMESTAMP:
3214
case MYSQL_TYPE_FLOAT:
3216
case MYSQL_TYPE_DOUBLE:
3217
return(DATA_DOUBLE);
3218
case MYSQL_TYPE_DECIMAL:
3219
return(DATA_DECIMAL);
3220
case MYSQL_TYPE_GEOMETRY:
3221
case MYSQL_TYPE_TINY_BLOB:
3222
case MYSQL_TYPE_MEDIUM_BLOB:
3223
case MYSQL_TYPE_BLOB:
3224
case MYSQL_TYPE_LONG_BLOB:
3233
/***********************************************************************
3234
Writes an unsigned integer value < 64k to 2 bytes, in the little-endian
3238
innobase_write_to_2_little_endian(
3239
/*==============================*/
3240
byte* buf, /* in: where to store */
3241
ulint val) /* in: value to write, must be < 64k */
3243
ut_a(val < 256 * 256);
3245
buf[0] = (byte)(val & 0xFF);
3246
buf[1] = (byte)(val / 256);
3249
/***********************************************************************
3250
Reads an unsigned integer value < 64k from 2 bytes, in the little-endian
3254
innobase_read_from_2_little_endian(
3255
/*===============================*/
3257
const uchar* buf) /* in: from where to read */
3259
return (uint) ((ulint)(buf[0]) + 256 * ((ulint)(buf[1])));
3262
/***********************************************************************
3263
Stores a key value for a row to a buffer. */
3266
ha_innobase::store_key_val_for_row(
3267
/*===============================*/
3268
/* out: key value length as stored in buff */
3269
uint keynr, /* in: key number */
3270
char* buff, /* in/out: buffer for the key value (in MySQL
3272
uint buff_len,/* in: buffer length */
3273
const uchar* record)/* in: row in MySQL format */
3275
KEY* key_info = table->key_info + keynr;
3276
KEY_PART_INFO* key_part = key_info->key_part;
3277
KEY_PART_INFO* end = key_part + key_info->key_parts;
3278
char* buff_start = buff;
3279
enum_field_types mysql_type;
3283
DBUG_ENTER("store_key_val_for_row");
3285
/* The format for storing a key field in MySQL is the following:
3287
1. If the column can be NULL, then in the first byte we put 1 if the
3288
field value is NULL, 0 otherwise.
3290
2. If the column is of a BLOB type (it must be a column prefix field
3291
in this case), then we put the length of the data in the field to the
3292
next 2 bytes, in the little-endian format. If the field is SQL NULL,
3293
then these 2 bytes are set to 0. Note that the length of data in the
3294
field is <= column prefix length.
3296
3. In a column prefix field, prefix_len next bytes are reserved for
3297
data. In a normal field the max field length next bytes are reserved
3298
for data. For a VARCHAR(n) the max field length is n. If the stored
3299
value is the SQL NULL then these data bytes are set to 0.
3301
4. We always use a 2 byte length for a true >= 5.0.3 VARCHAR. Note that
3302
in the MySQL row format, the length is stored in 1 or 2 bytes,
3303
depending on the maximum allowed length. But in the MySQL key value
3304
format, the length always takes 2 bytes.
3306
We have to zero-fill the buffer so that MySQL is able to use a
3307
simple memcmp to compare two key values to determine if they are
3308
equal. MySQL does this to compare contents of two 'ref' values. */
3310
bzero(buff, buff_len);
3312
for (; key_part != end; key_part++) {
3315
if (key_part->null_bit) {
3316
if (record[key_part->null_offset]
3317
& key_part->null_bit) {
3326
field = key_part->field;
3327
mysql_type = field->type();
3329
if (mysql_type == MYSQL_TYPE_VARCHAR) {
3330
/* >= 5.0.3 true VARCHAR */
3339
key_len = key_part->length;
3342
buff += key_len + 2;
3346
cs = field->charset();
3349
(((Field_varstring*)field)->length_bytes);
3351
data = row_mysql_read_true_varchar(&len,
3353
+ (ulint)get_field_offset(table, field)),
3358
/* For multi byte character sets we need to calculate
3359
the true length of the key */
3361
if (len > 0 && cs->mbmaxlen > 1) {
3362
true_len = (ulint) cs->cset->well_formed_len(cs,
3363
(const char *) data,
3364
(const char *) data + len,
3370
/* In a column prefix index, we may need to truncate
3371
the stored value: */
3373
if (true_len > key_len) {
3377
/* The length in a key value is always stored in 2
3380
row_mysql_store_true_var_len((byte*)buff, true_len, 2);
3383
memcpy(buff, data, true_len);
3385
/* Note that we always reserve the maximum possible
3386
length of the true VARCHAR in the key value, though
3387
only len first bytes after the 2 length bytes contain
3388
actual data. The rest of the space was reset to zero
3389
in the bzero() call above. */
3393
} else if (mysql_type == MYSQL_TYPE_TINY_BLOB
3394
|| mysql_type == MYSQL_TYPE_MEDIUM_BLOB
3395
|| mysql_type == MYSQL_TYPE_BLOB
3396
|| mysql_type == MYSQL_TYPE_LONG_BLOB
3397
/* MYSQL_TYPE_GEOMETRY data is treated
3398
as BLOB data in innodb. */
3399
|| mysql_type == MYSQL_TYPE_GEOMETRY) {
3408
ut_a(key_part->key_part_flag & HA_PART_KEY_SEG);
3410
key_len = key_part->length;
3413
buff += key_len + 2;
3418
cs = field->charset();
3420
blob_data = row_mysql_read_blob_ref(&blob_len,
3422
+ (ulint)get_field_offset(table, field)),
3423
(ulint) field->pack_length());
3425
true_len = blob_len;
3427
ut_a(get_field_offset(table, field)
3428
== key_part->offset);
3430
/* For multi byte character sets we need to calculate
3431
the true length of the key */
3433
if (blob_len > 0 && cs->mbmaxlen > 1) {
3434
true_len = (ulint) cs->cset->well_formed_len(cs,
3435
(const char *) blob_data,
3436
(const char *) blob_data
3443
/* All indexes on BLOB and TEXT are column prefix
3444
indexes, and we may need to truncate the data to be
3445
stored in the key value: */
3447
if (true_len > key_len) {
3451
/* MySQL reserves 2 bytes for the length and the
3452
storage of the number is little-endian */
3454
innobase_write_to_2_little_endian(
3455
(byte*)buff, true_len);
3458
memcpy(buff, blob_data, true_len);
3460
/* Note that we always reserve the maximum possible
3461
length of the BLOB prefix in the key value. */
3465
/* Here we handle all other data types except the
3466
true VARCHAR, BLOB and TEXT. Note that the column
3467
value we store may be also in a column prefix
3473
const uchar* src_start;
3475
enum_field_types real_type;
3477
key_len = key_part->length;
3485
src_start = record + key_part->offset;
3486
real_type = field->real_type();
3489
/* Character set for the field is defined only
3490
to fields whose type is string and real field
3491
type is not enum or set. For these fields check
3492
if character set is multi byte. */
3494
if (real_type != MYSQL_TYPE_ENUM
3495
&& real_type != MYSQL_TYPE_SET
3496
&& ( mysql_type == MYSQL_TYPE_VAR_STRING
3497
|| mysql_type == MYSQL_TYPE_STRING)) {
3499
cs = field->charset();
3501
/* For multi byte character sets we need to
3502
calculate the true length of the key */
3504
if (key_len > 0 && cs->mbmaxlen > 1) {
3507
cs->cset->well_formed_len(cs,
3508
(const char *)src_start,
3509
(const char *)src_start
3517
memcpy(buff, src_start, true_len);
3520
/* Pad the unused space with spaces. Note that no
3521
padding is ever needed for UCS-2 because in MySQL,
3522
all UCS2 characters are 2 bytes, as MySQL does not
3523
support surrogate pairs, which are needed to represent
3524
characters in the range U+10000 to U+10FFFF. */
3526
if (true_len < key_len) {
3527
ulint pad_len = key_len - true_len;
3528
memset(buff, ' ', pad_len);
3534
ut_a(buff <= buff_start + buff_len);
3536
DBUG_RETURN((uint)(buff - buff_start));
3539
/******************************************************************
3540
Builds a 'template' to the prebuilt struct. The template is used in fast
3541
retrieval of just those column values MySQL needs in its processing. */
3546
row_prebuilt_t* prebuilt, /* in/out: prebuilt struct */
3547
THD* thd, /* in: current user thread, used
3548
only if templ_type is
3549
ROW_MYSQL_REC_FIELDS */
3550
TABLE* table, /* in: MySQL table */
3551
uint templ_type) /* in: ROW_MYSQL_WHOLE_ROW or
3552
ROW_MYSQL_REC_FIELDS */
3554
dict_index_t* index;
3555
dict_index_t* clust_index;
3556
mysql_row_templ_t* templ;
3559
ulint n_requested_fields = 0;
3560
ibool fetch_all_in_key = FALSE;
3561
ibool fetch_primary_key_cols = FALSE;
3563
/* byte offset of the end of last requested column */
3564
ulint mysql_prefix_len = 0;
3566
if (prebuilt->select_lock_type == LOCK_X) {
3567
/* We always retrieve the whole clustered index record if we
3568
use exclusive row level locks, for example, if the read is
3569
done in an UPDATE statement. */
3571
templ_type = ROW_MYSQL_WHOLE_ROW;
3574
if (templ_type == ROW_MYSQL_REC_FIELDS) {
3575
if (prebuilt->hint_need_to_fetch_extra_cols
3576
== ROW_RETRIEVE_ALL_COLS) {
3578
/* We know we must at least fetch all columns in the
3579
key, or all columns in the table */
3581
if (prebuilt->read_just_key) {
3582
/* MySQL has instructed us that it is enough
3583
to fetch the columns in the key; looks like
3584
MySQL can set this flag also when there is
3585
only a prefix of the column in the key: in
3586
that case we retrieve the whole column from
3587
the clustered index */
3589
fetch_all_in_key = TRUE;
3591
templ_type = ROW_MYSQL_WHOLE_ROW;
3593
} else if (prebuilt->hint_need_to_fetch_extra_cols
3594
== ROW_RETRIEVE_PRIMARY_KEY) {
3595
/* We must at least fetch all primary key cols. Note
3596
that if the clustered index was internally generated
3597
by InnoDB on the row id (no primary key was
3598
defined), then row_search_for_mysql() will always
3599
retrieve the row id to a special buffer in the
3602
fetch_primary_key_cols = TRUE;
3606
clust_index = dict_table_get_first_index_noninline(prebuilt->table);
3608
if (templ_type == ROW_MYSQL_REC_FIELDS) {
3609
index = prebuilt->index;
3611
index = clust_index;
3614
if (index == clust_index) {
3615
prebuilt->need_to_access_clustered = TRUE;
3617
prebuilt->need_to_access_clustered = FALSE;
3618
/* Below we check column by column if we need to access
3619
the clustered index */
3622
n_fields = (ulint)table->s->fields; /* number of columns */
3624
if (!prebuilt->mysql_template) {
3625
prebuilt->mysql_template = (mysql_row_templ_t*)
3626
mem_alloc_noninline(
3627
n_fields * sizeof(mysql_row_templ_t));
3630
prebuilt->template_type = templ_type;
3631
prebuilt->null_bitmap_len = table->s->null_bytes;
3633
prebuilt->templ_contains_blob = FALSE;
3635
/* Note that in InnoDB, i is the column number. MySQL calls columns
3637
for (i = 0; i < n_fields; i++) {
3638
templ = prebuilt->mysql_template + n_requested_fields;
3639
field = table->field[i];
3641
if (UNIV_LIKELY(templ_type == ROW_MYSQL_REC_FIELDS)) {
3642
/* Decide which columns we should fetch
3643
and which we can skip. */
3644
register const ibool index_contains_field =
3645
dict_index_contains_col_or_prefix(index, i);
3647
if (!index_contains_field && prebuilt->read_just_key) {
3648
/* If this is a 'key read', we do not need
3649
columns that are not in the key */
3654
if (index_contains_field && fetch_all_in_key) {
3655
/* This field is needed in the query */
3660
if (bitmap_is_set(table->read_set, i) ||
3661
bitmap_is_set(table->write_set, i)) {
3662
/* This field is needed in the query */
3667
if (fetch_primary_key_cols
3668
&& dict_table_col_in_clustered_key(
3670
/* This field is needed in the query */
3675
/* This field is not needed in the query, skip it */
3680
n_requested_fields++;
3684
if (index == clust_index) {
3685
templ->rec_field_no = dict_col_get_clust_pos_noninline(
3686
&index->table->cols[i], index);
3688
templ->rec_field_no = dict_index_get_nth_col_pos(
3692
if (templ->rec_field_no == ULINT_UNDEFINED) {
3693
prebuilt->need_to_access_clustered = TRUE;
3696
if (field->null_ptr) {
3697
templ->mysql_null_byte_offset =
3698
(ulint) ((char*) field->null_ptr
3699
- (char*) table->record[0]);
3701
templ->mysql_null_bit_mask = (ulint) field->null_bit;
3703
templ->mysql_null_bit_mask = 0;
3706
templ->mysql_col_offset = (ulint)
3707
get_field_offset(table, field);
3709
templ->mysql_col_len = (ulint) field->pack_length();
3710
if (mysql_prefix_len < templ->mysql_col_offset
3711
+ templ->mysql_col_len) {
3712
mysql_prefix_len = templ->mysql_col_offset
3713
+ templ->mysql_col_len;
3715
templ->type = index->table->cols[i].mtype;
3716
templ->mysql_type = (ulint)field->type();
3718
if (templ->mysql_type == DATA_MYSQL_TRUE_VARCHAR) {
3719
templ->mysql_length_bytes = (ulint)
3720
(((Field_varstring*)field)->length_bytes);
3723
templ->charset = dtype_get_charset_coll_noninline(
3724
index->table->cols[i].prtype);
3725
templ->mbminlen = index->table->cols[i].mbminlen;
3726
templ->mbmaxlen = index->table->cols[i].mbmaxlen;
3727
templ->is_unsigned = index->table->cols[i].prtype
3729
if (templ->type == DATA_BLOB) {
3730
prebuilt->templ_contains_blob = TRUE;
3736
prebuilt->n_template = n_requested_fields;
3737
prebuilt->mysql_prefix_len = mysql_prefix_len;
3739
if (index != clust_index && prebuilt->need_to_access_clustered) {
3740
/* Change rec_field_no's to correspond to the clustered index
3742
for (i = 0; i < n_requested_fields; i++) {
3743
templ = prebuilt->mysql_template + i;
3745
templ->rec_field_no = dict_col_get_clust_pos_noninline(
3746
&index->table->cols[templ->col_no],
3752
/************************************************************************
3753
This special handling is really to overcome the limitations of MySQL's
3754
binlogging. We need to eliminate the non-determinism that will arise in
3755
INSERT ... SELECT type of statements, since MySQL binlog only stores the
3756
min value of the autoinc interval. Once that is fixed we can get rid of
3757
the special lock handling.*/
3760
ha_innobase::innobase_lock_autoinc(void)
3761
/*====================================*/
3762
/* out: DB_SUCCESS if all OK else
3765
ulint error = DB_SUCCESS;
3767
switch (innobase_autoinc_lock_mode) {
3768
case AUTOINC_NO_LOCKING:
3769
/* Acquire only the AUTOINC mutex. */
3770
dict_table_autoinc_lock(prebuilt->table);
3773
case AUTOINC_NEW_STYLE_LOCKING:
3774
/* For simple (single/multi) row INSERTs, we fallback to the
3775
old style only if another transaction has already acquired
3776
the AUTOINC lock on behalf of a LOAD FILE or INSERT ... SELECT
3777
etc. type of statement. */
3778
if (thd_sql_command(user_thd) == SQLCOM_INSERT
3779
|| thd_sql_command(user_thd) == SQLCOM_REPLACE) {
3780
dict_table_t* table = prebuilt->table;
3782
/* Acquire the AUTOINC mutex. */
3783
dict_table_autoinc_lock(table);
3785
/* We need to check that another transaction isn't
3786
already holding the AUTOINC lock on the table. */
3787
if (table->n_waiting_or_granted_auto_inc_locks) {
3788
/* Release the mutex to avoid deadlocks. */
3789
dict_table_autoinc_unlock(table);
3794
/* Fall through to old style locking. */
3796
case AUTOINC_OLD_STYLE_LOCKING:
3797
error = row_lock_table_autoinc_for_mysql(prebuilt);
3799
if (error == DB_SUCCESS) {
3801
/* Acquire the AUTOINC mutex. */
3802
dict_table_autoinc_lock(prebuilt->table);
3810
return(ulong(error));
3813
/************************************************************************
3814
Reset the autoinc value in the table.*/
3817
ha_innobase::innobase_reset_autoinc(
3818
/*================================*/
3819
/* out: DB_SUCCESS if all went well
3821
ulonglong autoinc) /* in: value to store */
3825
error = innobase_lock_autoinc();
3827
if (error == DB_SUCCESS) {
3829
dict_table_autoinc_initialize(prebuilt->table, autoinc);
3831
dict_table_autoinc_unlock(prebuilt->table);
3834
return(ulong(error));
3837
/************************************************************************
3838
Store the autoinc value in the table. The autoinc value is only set if
3839
it's greater than the existing autoinc value in the table.*/
3842
ha_innobase::innobase_set_max_autoinc(
3843
/*==================================*/
3844
/* out: DB_SUCCES if all went well
3846
ulonglong auto_inc) /* in: value to store */
3850
error = innobase_lock_autoinc();
3852
if (error == DB_SUCCESS) {
3854
dict_table_autoinc_update_if_greater(prebuilt->table, auto_inc);
3856
dict_table_autoinc_unlock(prebuilt->table);
3859
return(ulong(error));
3862
/************************************************************************
3863
Stores a row in an InnoDB database, to the table specified in this
3867
ha_innobase::write_row(
3868
/*===================*/
3869
/* out: error code */
3870
uchar* record) /* in: a row in MySQL format */
3873
int error_result= 0;
3874
ibool auto_inc_used= FALSE;
3876
trx_t* trx = thd_to_trx(user_thd);
3878
DBUG_ENTER("ha_innobase::write_row");
3880
if (prebuilt->trx != trx) {
3881
sql_print_error("The transaction object for the table handle is at "
3882
"%p, but for the current thread it is at %p",
3883
prebuilt->trx, trx);
3885
fputs("InnoDB: Dump of 200 bytes around prebuilt: ", stderr);
3886
ut_print_buf(stderr, ((const byte*)prebuilt) - 100, 200);
3888
"InnoDB: Dump of 200 bytes around ha_data: ",
3890
ut_print_buf(stderr, ((const byte*) trx) - 100, 200);
3895
ha_statistic_increment(&SSV::ha_write_count);
3897
if (table->timestamp_field_type & TIMESTAMP_AUTO_SET_ON_INSERT)
3898
table->timestamp_field->set_time();
3900
sql_command = thd_sql_command(user_thd);
3902
if ((sql_command == SQLCOM_ALTER_TABLE
3903
|| sql_command == SQLCOM_OPTIMIZE
3904
|| sql_command == SQLCOM_CREATE_INDEX
3905
|| sql_command == SQLCOM_DROP_INDEX)
3906
&& num_write_row >= 10000) {
3907
/* ALTER TABLE is COMMITted at every 10000 copied rows.
3908
The IX table lock for the original table has to be re-issued.
3909
As this method will be called on a temporary table where the
3910
contents of the original table is being copied to, it is
3911
a bit tricky to determine the source table. The cursor
3912
position in the source table need not be adjusted after the
3913
intermediate COMMIT, since writes by other transactions are
3914
being blocked by a MySQL table lock TL_WRITE_ALLOW_READ. */
3916
dict_table_t* src_table;
3921
/* Commit the transaction. This will release the table
3922
locks, so they have to be acquired again. */
3924
/* Altering an InnoDB table */
3925
/* Get the source table. */
3926
src_table = lock_get_src_table(
3927
prebuilt->trx, prebuilt->table, &mode);
3930
/* Unknown situation: do not commit */
3932
ut_print_timestamp(stderr);
3934
" InnoDB: ALTER TABLE is holding lock"
3935
" on %lu tables!\n",
3936
prebuilt->trx->mysql_n_tables_locked);
3939
} else if (src_table == prebuilt->table) {
3940
/* Source table is not in InnoDB format:
3941
no need to re-acquire locks on it. */
3943
/* Altering to InnoDB format */
3944
innobase_commit(ht, user_thd, 1);
3945
/* Note that this transaction is still active. */
3946
prebuilt->trx->active_trans = 1;
3947
/* We will need an IX lock on the destination table. */
3948
prebuilt->sql_stat_start = TRUE;
3950
/* Ensure that there are no other table locks than
3951
LOCK_IX and LOCK_AUTO_INC on the destination table. */
3953
if (!lock_is_table_exclusive(prebuilt->table,
3958
/* Commit the transaction. This will release the table
3959
locks, so they have to be acquired again. */
3960
innobase_commit(ht, user_thd, 1);
3961
/* Note that this transaction is still active. */
3962
prebuilt->trx->active_trans = 1;
3963
/* Re-acquire the table lock on the source table. */
3964
row_lock_table_for_mysql(prebuilt, src_table, mode);
3965
/* We will need an IX lock on the destination table. */
3966
prebuilt->sql_stat_start = TRUE;
3972
/* This is the case where the table has an auto-increment column */
3973
if (table->next_number_field && record == table->record[0]) {
3975
/* Reset the error code before calling
3976
innobase_get_auto_increment(). */
3977
prebuilt->autoinc_error = DB_SUCCESS;
3979
if ((error = update_auto_increment())) {
3980
/* We don't want to mask autoinc overflow errors. */
3982
/* Handle the case where the AUTOINC sub-system
3983
failed during initialization. */
3984
if (prebuilt->autoinc_error == DB_UNSUPPORTED) {
3985
error_result = ER_AUTOINC_READ_FAILED;
3986
/* Set the error message to report too. */
3987
my_error(ER_AUTOINC_READ_FAILED, MYF(0));
3989
} else if (prebuilt->autoinc_error != DB_SUCCESS) {
3990
error = (int) prebuilt->autoinc_error;
3994
/* MySQL errors are passed straight back. */
3995
error_result = (int) error;
3999
auto_inc_used = TRUE;
4002
if (prebuilt->mysql_template == NULL
4003
|| prebuilt->template_type != ROW_MYSQL_WHOLE_ROW) {
4005
/* Build the template used in converting quickly between
4006
the two database formats */
4008
build_template(prebuilt, NULL, table, ROW_MYSQL_WHOLE_ROW);
4011
innodb_srv_conc_enter_innodb(prebuilt->trx);
4013
error = row_insert_for_mysql((byte*) record, prebuilt);
4015
/* Handle duplicate key errors */
4016
if (auto_inc_used) {
4019
ulonglong col_max_value;
4021
/* Note the number of rows processed for this statement, used
4022
by get_auto_increment() to determine the number of AUTO-INC
4023
values to reserve. This is only useful for a mult-value INSERT
4024
and is a statement level counter.*/
4025
if (trx->n_autoinc_rows > 0) {
4026
--trx->n_autoinc_rows;
4029
/* We need the upper limit of the col type to check for
4030
whether we update the table autoinc counter or not. */
4031
col_max_value = innobase_get_int_col_max_value(
4032
table->next_number_field);
4034
/* Get the value that MySQL attempted to store in the table.*/
4035
auto_inc = table->next_number_field->val_int();
4038
case DB_DUPLICATE_KEY:
4040
/* A REPLACE command and LOAD DATA INFILE REPLACE
4041
handle a duplicate key error themselves, but we
4042
must update the autoinc counter if we are performing
4043
those statements. */
4045
switch (sql_command) {
4047
if ((trx->duplicates
4048
& (TRX_DUP_IGNORE | TRX_DUP_REPLACE))) {
4050
goto set_max_autoinc;
4054
case SQLCOM_REPLACE:
4055
case SQLCOM_INSERT_SELECT:
4056
case SQLCOM_REPLACE_SELECT:
4057
goto set_max_autoinc;
4067
/* If the actual value inserted is greater than
4068
the upper limit of the interval, then we try and
4069
update the table upper limit. Note: last_value
4070
will be 0 if get_auto_increment() was not called.*/
4072
if (auto_inc >= prebuilt->autoinc_last_value) {
4074
/* This should filter out the negative
4075
values set explicitly by the user. */
4076
if (auto_inc <= col_max_value) {
4077
ut_a(prebuilt->autoinc_increment > 0);
4082
offset = prebuilt->autoinc_offset;
4083
need = prebuilt->autoinc_increment;
4085
auto_inc = innobase_next_autoinc(
4087
need, offset, col_max_value);
4089
err = innobase_set_max_autoinc(
4092
if (err != DB_SUCCESS) {
4101
innodb_srv_conc_exit_innodb(prebuilt->trx);
4104
error_result = convert_error_code_to_mysql((int) error, user_thd);
4107
innobase_active_small();
4109
DBUG_RETURN(error_result);
4112
/**************************************************************************
4113
Checks which fields have changed in a row and stores information
4114
of them to an update vector. */
4117
calc_row_difference(
4118
/*================*/
4119
/* out: error number or 0 */
4120
upd_t* uvect, /* in/out: update vector */
4121
uchar* old_row, /* in: old row in MySQL format */
4122
uchar* new_row, /* in: new row in MySQL format */
4123
struct st_table* table, /* in: table in MySQL data
4125
uchar* upd_buff, /* in: buffer to use */
4126
ulint buff_len, /* in: buffer length */
4127
row_prebuilt_t* prebuilt, /* in: InnoDB prebuilt struct */
4128
THD* thd) /* in: user thread */
4130
uchar* original_upd_buff = upd_buff;
4132
enum_field_types field_mysql_type;
4137
byte* new_mysql_row_col;
4141
upd_field_t* ufield;
4143
ulint n_changed = 0;
4145
dict_index_t* clust_index;
4148
n_fields = table->s->fields;
4149
clust_index = dict_table_get_first_index_noninline(prebuilt->table);
4151
/* We use upd_buff to convert changed fields */
4152
buf = (byte*) upd_buff;
4154
for (i = 0; i < n_fields; i++) {
4155
field = table->field[i];
4157
o_ptr = (byte*) old_row + get_field_offset(table, field);
4158
n_ptr = (byte*) new_row + get_field_offset(table, field);
4160
/* Use new_mysql_row_col and col_pack_len save the values */
4162
new_mysql_row_col = n_ptr;
4163
col_pack_len = field->pack_length();
4165
o_len = col_pack_len;
4166
n_len = col_pack_len;
4168
/* We use o_ptr and n_ptr to dig up the actual data for
4171
field_mysql_type = field->type();
4173
col_type = prebuilt->table->cols[i].mtype;
4178
o_ptr = row_mysql_read_blob_ref(&o_len, o_ptr, o_len);
4179
n_ptr = row_mysql_read_blob_ref(&n_len, n_ptr, n_len);
4186
if (field_mysql_type == MYSQL_TYPE_VARCHAR) {
4187
/* This is a >= 5.0.3 type true VARCHAR where
4188
the real payload data length is stored in
4191
o_ptr = row_mysql_read_true_varchar(
4194
(((Field_varstring*)field)->length_bytes));
4196
n_ptr = row_mysql_read_true_varchar(
4199
(((Field_varstring*)field)->length_bytes));
4207
if (field->null_ptr) {
4208
if (field_in_record_is_null(table, field,
4210
o_len = UNIV_SQL_NULL;
4213
if (field_in_record_is_null(table, field,
4215
n_len = UNIV_SQL_NULL;
4219
if (o_len != n_len || (o_len != UNIV_SQL_NULL &&
4220
0 != memcmp(o_ptr, n_ptr, o_len))) {
4221
/* The field has changed */
4223
ufield = uvect->fields + n_changed;
4225
/* Let us use a dummy dfield to make the conversion
4226
from the MySQL column format to the InnoDB format */
4228
dict_col_copy_type_noninline(prebuilt->table->cols + i,
4231
if (n_len != UNIV_SQL_NULL) {
4232
buf = row_mysql_store_col_in_innobase_format(
4238
dict_table_is_comp_noninline(
4240
ufield->new_val.data = dfield.data;
4241
ufield->new_val.len = dfield.len;
4243
ufield->new_val.data = NULL;
4244
ufield->new_val.len = UNIV_SQL_NULL;
4248
ufield->field_no = dict_col_get_clust_pos_noninline(
4249
&prebuilt->table->cols[i], clust_index);
4254
uvect->n_fields = n_changed;
4255
uvect->info_bits = 0;
4257
ut_a(buf <= (byte*)original_upd_buff + buff_len);
4262
/**************************************************************************
4263
Updates a row given as a parameter to a new value. Note that we are given
4264
whole rows, not just the fields which are updated: this incurs some
4265
overhead for CPU when we check which fields are actually updated.
4266
TODO: currently InnoDB does not prevent the 'Halloween problem':
4267
in a searched update a single row can get updated several times
4268
if its index columns are updated! */
4271
ha_innobase::update_row(
4272
/*====================*/
4273
/* out: error number or 0 */
4274
const uchar* old_row, /* in: old row in MySQL format */
4275
uchar* new_row) /* in: new row in MySQL format */
4279
trx_t* trx = thd_to_trx(user_thd);
4281
DBUG_ENTER("ha_innobase::update_row");
4283
ut_a(prebuilt->trx == trx);
4285
ha_statistic_increment(&SSV::ha_update_count);
4287
if (table->timestamp_field_type & TIMESTAMP_AUTO_SET_ON_UPDATE)
4288
table->timestamp_field->set_time();
4290
if (prebuilt->upd_node) {
4291
uvect = prebuilt->upd_node->update;
4293
uvect = row_get_prebuilt_update_vector(prebuilt);
4296
/* Build an update vector from the modified fields in the rows
4297
(uses upd_buff of the handle) */
4299
calc_row_difference(uvect, (uchar*) old_row, new_row, table,
4300
upd_buff, (ulint)upd_and_key_val_buff_len,
4301
prebuilt, user_thd);
4303
/* This is not a delete */
4304
prebuilt->upd_node->is_delete = FALSE;
4306
assert(prebuilt->template_type == ROW_MYSQL_WHOLE_ROW);
4308
innodb_srv_conc_enter_innodb(trx);
4310
error = row_update_for_mysql((byte*) old_row, prebuilt);
4312
/* We need to do some special AUTOINC handling for the following case:
4314
INSERT INTO t (c1,c2) VALUES(x,y) ON DUPLICATE KEY UPDATE ...
4316
We need to use the AUTOINC counter that was actually used by
4317
MySQL in the UPDATE statement, which can be different from the
4318
value used in the INSERT statement.*/
4320
if (error == DB_SUCCESS
4321
&& table->next_number_field
4322
&& new_row == table->record[0]
4323
&& thd_sql_command(user_thd) == SQLCOM_INSERT
4324
&& (trx->duplicates & (TRX_DUP_IGNORE | TRX_DUP_REPLACE))
4325
== TRX_DUP_IGNORE) {
4328
ulonglong col_max_value;
4330
auto_inc = table->next_number_field->val_int();
4332
/* We need the upper limit of the col type to check for
4333
whether we update the table autoinc counter or not. */
4334
col_max_value = innobase_get_int_col_max_value(
4335
table->next_number_field);
4337
if (auto_inc <= col_max_value && auto_inc != 0) {
4342
offset = prebuilt->autoinc_offset;
4343
need = prebuilt->autoinc_increment;
4345
auto_inc = innobase_next_autoinc(
4346
auto_inc, need, offset, col_max_value);
4348
error = innobase_set_max_autoinc(auto_inc);
4352
innodb_srv_conc_exit_innodb(trx);
4354
error = convert_error_code_to_mysql(error, user_thd);
4356
if (error == 0 /* success */
4357
&& uvect->n_fields == 0 /* no columns were updated */) {
4359
/* This is the same as success, but instructs
4360
MySQL that the row is not really updated and it
4361
should not increase the count of updated rows.
4362
This is fix for http://bugs.mysql.com/29157 */
4363
error = HA_ERR_RECORD_IS_THE_SAME;
4366
/* Tell InnoDB server that there might be work for
4369
innobase_active_small();
4374
/**************************************************************************
4375
Deletes a row given as the parameter. */
4378
ha_innobase::delete_row(
4379
/*====================*/
4380
/* out: error number or 0 */
4381
const uchar* record) /* in: a row in MySQL format */
4384
trx_t* trx = thd_to_trx(user_thd);
4386
DBUG_ENTER("ha_innobase::delete_row");
4388
ut_a(prebuilt->trx == trx);
4390
ha_statistic_increment(&SSV::ha_delete_count);
4392
if (!prebuilt->upd_node) {
4393
row_get_prebuilt_update_vector(prebuilt);
4396
/* This is a delete */
4398
prebuilt->upd_node->is_delete = TRUE;
4400
innodb_srv_conc_enter_innodb(trx);
4402
error = row_update_for_mysql((byte*) record, prebuilt);
4404
innodb_srv_conc_exit_innodb(trx);
4406
error = convert_error_code_to_mysql(error, user_thd);
4408
/* Tell the InnoDB server that there might be work for
4411
innobase_active_small();
4416
/**************************************************************************
4417
Removes a new lock set on a row, if it was not read optimistically. This can
4418
be called after a row has been read in the processing of an UPDATE or a DELETE
4419
query, if the option innodb_locks_unsafe_for_binlog is set. */
4422
ha_innobase::unlock_row(void)
4423
/*=========================*/
4425
DBUG_ENTER("ha_innobase::unlock_row");
4427
/* Consistent read does not take any locks, thus there is
4428
nothing to unlock. */
4430
if (prebuilt->select_lock_type == LOCK_NONE) {
4434
switch (prebuilt->row_read_type) {
4435
case ROW_READ_WITH_LOCKS:
4436
if (!srv_locks_unsafe_for_binlog
4437
&& prebuilt->trx->isolation_level
4438
!= TRX_ISO_READ_COMMITTED) {
4442
case ROW_READ_TRY_SEMI_CONSISTENT:
4443
row_unlock_for_mysql(prebuilt, FALSE);
4445
case ROW_READ_DID_SEMI_CONSISTENT:
4446
prebuilt->row_read_type = ROW_READ_TRY_SEMI_CONSISTENT;
4453
/* See handler.h and row0mysql.h for docs on this function. */
4455
ha_innobase::was_semi_consistent_read(void)
4456
/*=======================================*/
4458
return(prebuilt->row_read_type == ROW_READ_DID_SEMI_CONSISTENT);
4461
/* See handler.h and row0mysql.h for docs on this function. */
4463
ha_innobase::try_semi_consistent_read(bool yes)
4464
/*===========================================*/
4466
ut_a(prebuilt->trx == thd_to_trx(ha_thd()));
4468
/* Row read type is set to semi consistent read if this was
4469
requested by the MySQL and either innodb_locks_unsafe_for_binlog
4470
option is used or this session is using READ COMMITTED isolation
4474
&& (srv_locks_unsafe_for_binlog
4475
|| prebuilt->trx->isolation_level == TRX_ISO_READ_COMMITTED)) {
4476
prebuilt->row_read_type = ROW_READ_TRY_SEMI_CONSISTENT;
4478
prebuilt->row_read_type = ROW_READ_WITH_LOCKS;
4482
/**********************************************************************
4483
Initializes a handle to use an index. */
4486
ha_innobase::index_init(
4487
/*====================*/
4488
/* out: 0 or error number */
4489
uint keynr, /* in: key (index) number */
4490
bool sorted) /* in: 1 if result MUST be sorted according to index */
4493
DBUG_ENTER("index_init");
4495
error = change_active_index(keynr);
4500
/**********************************************************************
4501
Currently does nothing. */
4504
ha_innobase::index_end(void)
4505
/*========================*/
4508
DBUG_ENTER("index_end");
4509
active_index=MAX_KEY;
4513
/*************************************************************************
4514
Converts a search mode flag understood by MySQL to a flag understood
4518
convert_search_mode_to_innobase(
4519
/*============================*/
4520
enum ha_rkey_function find_flag)
4522
switch (find_flag) {
4523
case HA_READ_KEY_EXACT:
4524
/* this does not require the index to be UNIQUE */
4525
return(PAGE_CUR_GE);
4526
case HA_READ_KEY_OR_NEXT:
4527
return(PAGE_CUR_GE);
4528
case HA_READ_KEY_OR_PREV:
4529
return(PAGE_CUR_LE);
4530
case HA_READ_AFTER_KEY:
4532
case HA_READ_BEFORE_KEY:
4534
case HA_READ_PREFIX:
4535
return(PAGE_CUR_GE);
4536
case HA_READ_PREFIX_LAST:
4537
return(PAGE_CUR_LE);
4538
case HA_READ_PREFIX_LAST_OR_PREV:
4539
return(PAGE_CUR_LE);
4540
/* In MySQL-4.0 HA_READ_PREFIX and HA_READ_PREFIX_LAST always
4541
pass a complete-field prefix of a key value as the search
4542
tuple. I.e., it is not allowed that the last field would
4543
just contain n first bytes of the full field value.
4544
MySQL uses a 'padding' trick to convert LIKE 'abc%'
4545
type queries so that it can use as a search tuple
4546
a complete-field-prefix of a key value. Thus, the InnoDB
4547
search mode PAGE_CUR_LE_OR_EXTENDS is never used.
4548
TODO: when/if MySQL starts to use also partial-field
4549
prefixes, we have to deal with stripping of spaces
4550
and comparison of non-latin1 char type fields in
4551
innobase_mysql_cmp() to get PAGE_CUR_LE_OR_EXTENDS to
4553
case HA_READ_MBR_CONTAIN:
4554
case HA_READ_MBR_INTERSECT:
4555
case HA_READ_MBR_WITHIN:
4556
case HA_READ_MBR_DISJOINT:
4557
case HA_READ_MBR_EQUAL:
4558
return(PAGE_CUR_UNSUPP);
4559
/* do not use "default:" in order to produce a gcc warning:
4560
enumeration value '...' not handled in switch
4561
(if -Wswitch or -Wall is used) */
4564
my_error(ER_CHECK_NOT_IMPLEMENTED, MYF(0), "this functionality");
4566
return(PAGE_CUR_UNSUPP);
4570
BACKGROUND INFO: HOW A SELECT SQL QUERY IS EXECUTED
4571
---------------------------------------------------
4572
The following does not cover all the details, but explains how we determine
4573
the start of a new SQL statement, and what is associated with it.
4575
For each table in the database the MySQL interpreter may have several
4576
table handle instances in use, also in a single SQL query. For each table
4577
handle instance there is an InnoDB 'prebuilt' struct which contains most
4578
of the InnoDB data associated with this table handle instance.
4580
A) if the user has not explicitly set any MySQL table level locks:
4582
1) MySQL calls ::external_lock to set an 'intention' table level lock on
4583
the table of the handle instance. There we set
4584
prebuilt->sql_stat_start = TRUE. The flag sql_stat_start should be set
4585
true if we are taking this table handle instance to use in a new SQL
4586
statement issued by the user. We also increment trx->n_mysql_tables_in_use.
4588
2) If prebuilt->sql_stat_start == TRUE we 'pre-compile' the MySQL search
4589
instructions to prebuilt->template of the table handle instance in
4590
::index_read. The template is used to save CPU time in large joins.
4592
3) In row_search_for_mysql, if prebuilt->sql_stat_start is true, we
4593
allocate a new consistent read view for the trx if it does not yet have one,
4594
or in the case of a locking read, set an InnoDB 'intention' table level
4597
4) We do the SELECT. MySQL may repeatedly call ::index_read for the
4598
same table handle instance, if it is a join.
4600
5) When the SELECT ends, MySQL removes its intention table level locks
4601
in ::external_lock. When trx->n_mysql_tables_in_use drops to zero,
4602
(a) we execute a COMMIT there if the autocommit is on,
4603
(b) we also release possible 'SQL statement level resources' InnoDB may
4604
have for this SQL statement. The MySQL interpreter does NOT execute
4605
autocommit for pure read transactions, though it should. That is why the
4606
table handler in that case has to execute the COMMIT in ::external_lock.
4608
B) If the user has explicitly set MySQL table level locks, then MySQL
4609
does NOT call ::external_lock at the start of the statement. To determine
4610
when we are at the start of a new SQL statement we at the start of
4611
::index_read also compare the query id to the latest query id where the
4612
table handle instance was used. If it has changed, we know we are at the
4613
start of a new SQL statement. Since the query id can theoretically
4614
overwrap, we use this test only as a secondary way of determining the
4615
start of a new SQL statement. */
4618
/**************************************************************************
4619
Positions an index cursor to the index specified in the handle. Fetches the
4623
ha_innobase::index_read(
4624
/*====================*/
4625
/* out: 0, HA_ERR_KEY_NOT_FOUND,
4627
uchar* buf, /* in/out: buffer for the returned
4629
const uchar* key_ptr, /* in: key value; if this is NULL
4630
we position the cursor at the
4631
start or end of index; this can
4632
also contain an InnoDB row id, in
4633
which case key_len is the InnoDB
4634
row id length; the key value can
4635
also be a prefix of a full key value,
4636
and the last column can be a prefix
4638
uint key_len,/* in: key value length */
4639
enum ha_rkey_function find_flag)/* in: search flags from my_base.h */
4642
dict_index_t* index;
4643
ulint match_mode = 0;
4647
DBUG_ENTER("index_read");
4649
ut_a(prebuilt->trx == thd_to_trx(user_thd));
4651
ha_statistic_increment(&SSV::ha_read_key_count);
4653
index = prebuilt->index;
4655
/* Note that if the index for which the search template is built is not
4656
necessarily prebuilt->index, but can also be the clustered index */
4658
if (prebuilt->sql_stat_start) {
4659
build_template(prebuilt, user_thd, table,
4660
ROW_MYSQL_REC_FIELDS);
4664
/* Convert the search key value to InnoDB format into
4665
prebuilt->search_tuple */
4667
row_sel_convert_mysql_key_to_innobase(prebuilt->search_tuple,
4668
(byte*) key_val_buff,
4669
(ulint)upd_and_key_val_buff_len,
4672
(ulint) key_len, prebuilt->trx);
4674
/* We position the cursor to the last or the first entry
4677
dtuple_set_n_fields(prebuilt->search_tuple, 0);
4680
mode = convert_search_mode_to_innobase(find_flag);
4684
if (find_flag == HA_READ_KEY_EXACT) {
4685
match_mode = ROW_SEL_EXACT;
4687
} else if (find_flag == HA_READ_PREFIX
4688
|| find_flag == HA_READ_PREFIX_LAST) {
4689
match_mode = ROW_SEL_EXACT_PREFIX;
4692
last_match_mode = (uint) match_mode;
4694
if (mode != PAGE_CUR_UNSUPP) {
4696
innodb_srv_conc_enter_innodb(prebuilt->trx);
4698
ret = row_search_for_mysql((byte*) buf, mode, prebuilt,
4701
innodb_srv_conc_exit_innodb(prebuilt->trx);
4704
ret = DB_UNSUPPORTED;
4707
if (ret == DB_SUCCESS) {
4711
} else if (ret == DB_RECORD_NOT_FOUND) {
4712
error = HA_ERR_KEY_NOT_FOUND;
4713
table->status = STATUS_NOT_FOUND;
4715
} else if (ret == DB_END_OF_INDEX) {
4716
error = HA_ERR_KEY_NOT_FOUND;
4717
table->status = STATUS_NOT_FOUND;
4719
error = convert_error_code_to_mysql((int) ret, user_thd);
4720
table->status = STATUS_NOT_FOUND;
4726
/***********************************************************************
4727
The following functions works like index_read, but it find the last
4728
row with the current key value or prefix. */
4731
ha_innobase::index_read_last(
4732
/*=========================*/
4733
/* out: 0, HA_ERR_KEY_NOT_FOUND, or an
4735
uchar* buf, /* out: fetched row */
4736
const uchar* key_ptr,/* in: key value, or a prefix of a full
4738
uint key_len)/* in: length of the key val or prefix
4741
return(index_read(buf, key_ptr, key_len, HA_READ_PREFIX_LAST));
4744
/************************************************************************
4745
Get the index for a handle. Does not change active index.*/
4748
ha_innobase::innobase_get_index(
4749
/*============================*/
4750
/* out: NULL or index instance. */
4751
uint keynr) /* in: use this index; MAX_KEY means always
4752
clustered index, even if it was internally
4753
generated by InnoDB */
4756
dict_index_t* index = 0;
4758
DBUG_ENTER("innobase_get_index");
4759
ha_statistic_increment(&SSV::ha_read_key_count);
4761
ut_ad(user_thd == ha_thd());
4762
ut_a(prebuilt->trx == thd_to_trx(user_thd));
4764
if (keynr != MAX_KEY && table->s->keys > 0) {
4765
key = table->key_info + keynr;
4767
index = dict_table_get_index_noninline(
4768
prebuilt->table, key->name);
4770
index = dict_table_get_first_index_noninline(prebuilt->table);
4775
"Innodb could not find key n:o %u with name %s "
4776
"from dict cache for table %s",
4777
keynr, key ? key->name : "NULL",
4778
prebuilt->table->name);
4784
/************************************************************************
4785
Changes the active index of a handle. */
4788
ha_innobase::change_active_index(
4789
/*=============================*/
4790
/* out: 0 or error code */
4791
uint keynr) /* in: use this index; MAX_KEY means always clustered
4792
index, even if it was internally generated by
4795
DBUG_ENTER("change_active_index");
4797
ut_ad(user_thd == ha_thd());
4798
ut_a(prebuilt->trx == thd_to_trx(user_thd));
4800
active_index = keynr;
4802
prebuilt->index = innobase_get_index(keynr);
4804
if (!prebuilt->index) {
4808
assert(prebuilt->search_tuple != 0);
4810
dtuple_set_n_fields(prebuilt->search_tuple, prebuilt->index->n_fields);
4812
dict_index_copy_types(prebuilt->search_tuple, prebuilt->index,
4813
prebuilt->index->n_fields);
4815
/* MySQL changes the active index for a handle also during some
4816
queries, for example SELECT MAX(a), SUM(a) first retrieves the MAX()
4817
and then calculates the sum. Previously we played safe and used
4818
the flag ROW_MYSQL_WHOLE_ROW below, but that caused unnecessary
4819
copying. Starting from MySQL-4.1 we use a more efficient flag here. */
4821
build_template(prebuilt, user_thd, table, ROW_MYSQL_REC_FIELDS);
4826
/**************************************************************************
4827
Positions an index cursor to the index specified in keynr. Fetches the
4829
/* ??? This is only used to read whole keys ??? */
4832
ha_innobase::index_read_idx(
4833
/*========================*/
4834
/* out: error number or 0 */
4835
uchar* buf, /* in/out: buffer for the returned
4837
uint keynr, /* in: use this index */
4838
const uchar* key, /* in: key value; if this is NULL
4839
we position the cursor at the
4840
start or end of index */
4841
uint key_len, /* in: key value length */
4842
enum ha_rkey_function find_flag)/* in: search flags from my_base.h */
4844
if (change_active_index(keynr)) {
4849
return(index_read(buf, key, key_len, find_flag));
4852
/***************************************************************************
4853
Reads the next or previous row from a cursor, which must have previously been
4854
positioned using index_read. */
4857
ha_innobase::general_fetch(
4858
/*=======================*/
4859
/* out: 0, HA_ERR_END_OF_FILE, or error
4861
uchar* buf, /* in/out: buffer for next row in MySQL
4863
uint direction, /* in: ROW_SEL_NEXT or ROW_SEL_PREV */
4864
uint match_mode) /* in: 0, ROW_SEL_EXACT, or
4865
ROW_SEL_EXACT_PREFIX */
4870
DBUG_ENTER("general_fetch");
4872
ut_a(prebuilt->trx == thd_to_trx(user_thd));
4874
innodb_srv_conc_enter_innodb(prebuilt->trx);
4876
ret = row_search_for_mysql((byte*)buf, 0, prebuilt, match_mode,
4878
innodb_srv_conc_exit_innodb(prebuilt->trx);
4880
if (ret == DB_SUCCESS) {
4884
} else if (ret == DB_RECORD_NOT_FOUND) {
4885
error = HA_ERR_END_OF_FILE;
4886
table->status = STATUS_NOT_FOUND;
4888
} else if (ret == DB_END_OF_INDEX) {
4889
error = HA_ERR_END_OF_FILE;
4890
table->status = STATUS_NOT_FOUND;
4892
error = convert_error_code_to_mysql((int) ret, user_thd);
4893
table->status = STATUS_NOT_FOUND;
4899
/***************************************************************************
4900
Reads the next row from a cursor, which must have previously been
4901
positioned using index_read. */
4904
ha_innobase::index_next(
4905
/*====================*/
4906
/* out: 0, HA_ERR_END_OF_FILE, or error
4908
uchar* buf) /* in/out: buffer for next row in MySQL
4911
ha_statistic_increment(&SSV::ha_read_next_count);
4913
return(general_fetch(buf, ROW_SEL_NEXT, 0));
4916
/***********************************************************************
4917
Reads the next row matching to the key value given as the parameter. */
4920
ha_innobase::index_next_same(
4921
/*=========================*/
4922
/* out: 0, HA_ERR_END_OF_FILE, or error
4924
uchar* buf, /* in/out: buffer for the row */
4925
const uchar* key, /* in: key value */
4926
uint keylen) /* in: key value length */
4928
ha_statistic_increment(&SSV::ha_read_next_count);
4930
return(general_fetch(buf, ROW_SEL_NEXT, last_match_mode));
4933
/***************************************************************************
4934
Reads the previous row from a cursor, which must have previously been
4935
positioned using index_read. */
4938
ha_innobase::index_prev(
4939
/*====================*/
4940
/* out: 0, HA_ERR_END_OF_FILE, or error number */
4941
uchar* buf) /* in/out: buffer for previous row in MySQL format */
4943
ha_statistic_increment(&SSV::ha_read_prev_count);
4945
return(general_fetch(buf, ROW_SEL_PREV, 0));
4948
/************************************************************************
4949
Positions a cursor on the first record in an index and reads the
4950
corresponding row to buf. */
4953
ha_innobase::index_first(
4954
/*=====================*/
4955
/* out: 0, HA_ERR_END_OF_FILE, or error code */
4956
uchar* buf) /* in/out: buffer for the row */
4960
DBUG_ENTER("index_first");
4961
ha_statistic_increment(&SSV::ha_read_first_count);
4963
error = index_read(buf, NULL, 0, HA_READ_AFTER_KEY);
4965
/* MySQL does not seem to allow this to return HA_ERR_KEY_NOT_FOUND */
4967
if (error == HA_ERR_KEY_NOT_FOUND) {
4968
error = HA_ERR_END_OF_FILE;
4974
/************************************************************************
4975
Positions a cursor on the last record in an index and reads the
4976
corresponding row to buf. */
4979
ha_innobase::index_last(
4980
/*====================*/
4981
/* out: 0, HA_ERR_END_OF_FILE, or error code */
4982
uchar* buf) /* in/out: buffer for the row */
4986
DBUG_ENTER("index_last");
4987
ha_statistic_increment(&SSV::ha_read_last_count);
4989
error = index_read(buf, NULL, 0, HA_READ_BEFORE_KEY);
4991
/* MySQL does not seem to allow this to return HA_ERR_KEY_NOT_FOUND */
4993
if (error == HA_ERR_KEY_NOT_FOUND) {
4994
error = HA_ERR_END_OF_FILE;
5000
/********************************************************************
5001
Initialize a table scan. */
5004
ha_innobase::rnd_init(
5005
/*==================*/
5006
/* out: 0 or error number */
5007
bool scan) /* in: ???????? */
5011
/* Store the active index value so that we can restore the original
5012
value after a scan */
5014
if (prebuilt->clust_index_was_generated) {
5015
err = change_active_index(MAX_KEY);
5017
err = change_active_index(primary_key);
5020
/* Don't use semi-consistent read in random row reads (by position).
5021
This means we must disable semi_consistent_read if scan is false */
5024
try_semi_consistent_read(0);
5032
/*********************************************************************
5033
Ends a table scan. */
5036
ha_innobase::rnd_end(void)
5037
/*======================*/
5038
/* out: 0 or error number */
5040
return(index_end());
5043
/*********************************************************************
5044
Reads the next row in a table scan (also used to read the FIRST row
5045
in a table scan). */
5048
ha_innobase::rnd_next(
5049
/*==================*/
5050
/* out: 0, HA_ERR_END_OF_FILE, or error number */
5051
uchar* buf) /* in/out: returns the row in this buffer,
5056
DBUG_ENTER("rnd_next");
5057
ha_statistic_increment(&SSV::ha_read_rnd_next_count);
5059
if (start_of_scan) {
5060
error = index_first(buf);
5061
if (error == HA_ERR_KEY_NOT_FOUND) {
5062
error = HA_ERR_END_OF_FILE;
5066
error = general_fetch(buf, ROW_SEL_NEXT, 0);
5072
/**************************************************************************
5073
Fetches a row from the table based on a row reference. */
5076
ha_innobase::rnd_pos(
5077
/*=================*/
5078
/* out: 0, HA_ERR_KEY_NOT_FOUND, or error code */
5079
uchar* buf, /* in/out: buffer for the row */
5080
uchar* pos) /* in: primary key value of the row in the
5081
MySQL format, or the row id if the clustered
5082
index was internally generated by InnoDB; the
5083
length of data in pos has to be ref_length */
5086
uint keynr = active_index;
5087
DBUG_ENTER("rnd_pos");
5088
DBUG_DUMP("key", pos, ref_length);
5090
ha_statistic_increment(&SSV::ha_read_rnd_count);
5092
ut_a(prebuilt->trx == thd_to_trx(ha_thd()));
5094
if (prebuilt->clust_index_was_generated) {
5095
/* No primary key was defined for the table and we
5096
generated the clustered index from the row id: the
5097
row reference is the row id, not any key value
5098
that MySQL knows of */
5100
error = change_active_index(MAX_KEY);
5102
error = change_active_index(primary_key);
5106
DBUG_PRINT("error", ("Got error: %d", error));
5110
/* Note that we assume the length of the row reference is fixed
5111
for the table, and it is == ref_length */
5113
error = index_read(buf, pos, ref_length, HA_READ_KEY_EXACT);
5116
DBUG_PRINT("error", ("Got error: %d", error));
5119
change_active_index(keynr);
5124
/*************************************************************************
5125
Stores a reference to the current row to 'ref' field of the handle. Note
5126
that in the case where we have generated the clustered index for the
5127
table, the function parameter is illogical: we MUST ASSUME that 'record'
5128
is the current 'position' of the handle, because if row ref is actually
5129
the row id internally generated in InnoDB, then 'record' does not contain
5130
it. We just guess that the row id must be for the record where the handle
5131
was positioned the last time. */
5134
ha_innobase::position(
5135
/*==================*/
5136
const uchar* record) /* in: row in MySQL format */
5140
ut_a(prebuilt->trx == thd_to_trx(ha_thd()));
5142
if (prebuilt->clust_index_was_generated) {
5143
/* No primary key was defined for the table and we
5144
generated the clustered index from row id: the
5145
row reference will be the row id, not any key value
5146
that MySQL knows of */
5148
len = DATA_ROW_ID_LEN;
5150
memcpy(ref, prebuilt->row_id, len);
5152
len = store_key_val_for_row(primary_key, (char*)ref,
5153
ref_length, record);
5156
/* We assume that the 'ref' value len is always fixed for the same
5159
if (len != ref_length) {
5160
sql_print_error("Stored ref len is %lu, but table ref len is %lu",
5161
(ulong) len, (ulong) ref_length);
5165
/*********************************************************************
5166
If it's a DB_TOO_BIG_RECORD error then set a suitable message to
5167
return to the client.*/
5170
innodb_check_for_record_too_big_error(
5171
/*==================================*/
5172
ulint comp, /* in: ROW_FORMAT: nonzero=COMPACT, 0=REDUNDANT */
5173
int error) /* in: error code to check */
5175
if (error == (int)DB_TOO_BIG_RECORD) {
5177
= page_get_free_space_of_empty_noninline(comp) / 2;
5179
my_error(ER_TOO_BIG_ROWSIZE, MYF(0), max_row_size);
5183
/* limit innodb monitor access to users with PROCESS privilege.
5184
See http://bugs.mysql.com/32710 for expl. why we choose PROCESS. */
5185
#define IS_MAGIC_TABLE_AND_USER_DENIED_ACCESS(table_name, thd) \
5186
(row_is_magic_monitor_table(table_name) \
5187
&& check_global_access(thd, PROCESS_ACL))
5189
/*********************************************************************
5190
Creates a table definition to an InnoDB database. */
5195
trx_t* trx, /* in: InnoDB transaction handle */
5196
TABLE* form, /* in: information on table
5197
columns and indexes */
5198
const char* table_name, /* in: table name */
5199
const char* path_of_temp_table,/* in: if this is a table explicitly
5200
created by the user with the
5201
TEMPORARY keyword, then this
5202
parameter is the dir path where the
5203
table should be placed if we create
5204
an .ibd file for it (no .ibd extension
5205
in the path, though); otherwise this
5207
ulint flags) /* in: table flags */
5210
dict_table_t* table;
5215
ulint nulls_allowed;
5216
ulint unsigned_type;
5218
ulint long_true_varchar;
5222
DBUG_ENTER("create_table_def");
5223
DBUG_PRINT("enter", ("table_name: %s", table_name));
5225
ut_a(trx->mysql_thd != NULL);
5226
if (IS_MAGIC_TABLE_AND_USER_DENIED_ACCESS(table_name,
5227
(THD*) trx->mysql_thd)) {
5228
DBUG_RETURN(HA_ERR_GENERIC);
5231
n_cols = form->s->fields;
5233
/* We pass 0 as the space id, and determine at a lower level the space
5234
id where to store the table */
5236
table = dict_mem_table_create(table_name, 0, n_cols, flags);
5238
if (path_of_temp_table) {
5239
table->dir_path_of_temp_table =
5240
mem_heap_strdup(table->heap, path_of_temp_table);
5243
for (i = 0; i < n_cols; i++) {
5244
field = form->field[i];
5246
col_type = get_innobase_type_from_mysql_type(&unsigned_type,
5248
if (field->null_ptr) {
5251
nulls_allowed = DATA_NOT_NULL;
5254
if (field->binary()) {
5255
binary_type = DATA_BINARY_TYPE;
5262
if (dtype_is_string_type(col_type)) {
5264
charset_no = (ulint)field->charset()->number;
5266
ut_a(charset_no < 256); /* in data0type.h we assume
5267
that the number fits in one
5271
ut_a(field->type() < 256); /* we assume in dtype_form_prtype()
5272
that this fits in one byte */
5273
col_len = field->pack_length();
5275
/* The MySQL pack length contains 1 or 2 bytes length field
5276
for a true VARCHAR. Let us subtract that, so that the InnoDB
5277
column length in the InnoDB data dictionary is the real
5278
maximum byte length of the actual data. */
5280
long_true_varchar = 0;
5282
if (field->type() == MYSQL_TYPE_VARCHAR) {
5283
col_len -= ((Field_varstring*)field)->length_bytes;
5285
if (((Field_varstring*)field)->length_bytes == 2) {
5286
long_true_varchar = DATA_LONG_TRUE_VARCHAR;
5290
/* First check whether the column to be added has a
5291
system reserved name. */
5292
if (dict_col_name_is_reserved(field->field_name)){
5293
push_warning_printf(
5294
(THD*) trx->mysql_thd,
5295
MYSQL_ERROR::WARN_LEVEL_WARN,
5296
ER_CANT_CREATE_TABLE,
5297
"Error creating table '%s' with "
5298
"column name '%s'. '%s' is a "
5299
"reserved name. Please try to "
5300
"re-create the table with a "
5301
"different column name.",
5302
table->name, (char*) field->field_name,
5303
(char*) field->field_name);
5305
dict_mem_table_free(table);
5306
trx_commit_for_mysql(trx);
5312
dict_mem_table_add_col(table, table->heap,
5313
(char*) field->field_name,
5316
(ulint)field->type()
5317
| nulls_allowed | unsigned_type
5318
| binary_type | long_true_varchar,
5323
error = row_create_table_for_mysql(table, trx);
5325
innodb_check_for_record_too_big_error(flags & DICT_TF_COMPACT, error);
5328
error = convert_error_code_to_mysql(error, NULL);
5333
/*********************************************************************
5334
Creates an index in an InnoDB database. */
5339
trx_t* trx, /* in: InnoDB transaction handle */
5340
TABLE* form, /* in: information on table
5341
columns and indexes */
5342
const char* table_name, /* in: table name */
5343
uint key_num) /* in: index number */
5346
dict_index_t* index;
5350
KEY_PART_INFO* key_part;
5357
ulint* field_lengths;
5359
DBUG_ENTER("create_index");
5361
key = form->key_info + key_num;
5363
n_fields = key->key_parts;
5365
/* Assert that "GEN_CLUST_INDEX" cannot be used as non-primary index */
5366
ut_a(innobase_strcasecmp(key->name, innobase_index_reserve_name) != 0);
5370
if (key_num == form->s->primary_key) {
5371
ind_type = ind_type | DICT_CLUSTERED;
5374
if (key->flags & HA_NOSAME ) {
5375
ind_type = ind_type | DICT_UNIQUE;
5378
/* We pass 0 as the space id, and determine at a lower level the space
5379
id where to store the table */
5381
index = dict_mem_index_create((char*) table_name, key->name, 0,
5382
ind_type, n_fields);
5384
field_lengths = (ulint*) my_malloc(sizeof(ulint) * n_fields,
5387
for (i = 0; i < n_fields; i++) {
5388
key_part = key->key_part + i;
5390
/* (The flag HA_PART_KEY_SEG denotes in MySQL a column prefix
5391
field in an index: we only store a specified number of first
5392
bytes of the column to the index field.) The flag does not
5393
seem to be properly set by MySQL. Let us fall back on testing
5394
the length of the key part versus the column. */
5397
for (j = 0; j < form->s->fields; j++) {
5399
field = form->field[j];
5401
if (0 == innobase_strcasecmp(
5403
key_part->field->field_name)) {
5404
/* Found the corresponding column */
5410
ut_a(j < form->s->fields);
5412
col_type = get_innobase_type_from_mysql_type(
5413
&is_unsigned, key_part->field);
5415
if (DATA_BLOB == col_type
5416
|| (key_part->length < field->pack_length()
5417
&& field->type() != MYSQL_TYPE_VARCHAR)
5418
|| (field->type() == MYSQL_TYPE_VARCHAR
5419
&& key_part->length < field->pack_length()
5420
- ((Field_varstring*)field)->length_bytes)) {
5422
prefix_len = key_part->length;
5424
if (col_type == DATA_INT
5425
|| col_type == DATA_FLOAT
5426
|| col_type == DATA_DOUBLE
5427
|| col_type == DATA_DECIMAL) {
5429
"MySQL is trying to create a column "
5430
"prefix index field, on an "
5431
"inappropriate data type. Table "
5432
"name %s, column name %s.",
5434
key_part->field->field_name);
5442
field_lengths[i] = key_part->length;
5444
dict_mem_index_add_field(index,
5445
(char*) key_part->field->field_name, prefix_len);
5448
/* Even though we've defined max_supported_key_part_length, we
5449
still do our own checking using field_lengths to be absolutely
5450
sure we don't create too long indexes. */
5451
error = row_create_index_for_mysql(index, trx, field_lengths);
5453
innodb_check_for_record_too_big_error(form->s->row_type
5454
!= ROW_TYPE_REDUNDANT, error);
5456
error = convert_error_code_to_mysql(error, NULL);
5458
my_free(field_lengths, MYF(0));
5463
/*********************************************************************
5464
Creates an index to an InnoDB table when the user has defined no
5468
create_clustered_index_when_no_primary(
5469
/*===================================*/
5470
trx_t* trx, /* in: InnoDB transaction handle */
5471
ulint comp, /* in: ROW_FORMAT:
5472
nonzero=COMPACT, 0=REDUNDANT */
5473
const char* table_name) /* in: table name */
5475
dict_index_t* index;
5478
/* We pass 0 as the space id, and determine at a lower level the space
5479
id where to store the table */
5480
index = dict_mem_index_create(table_name,
5481
innobase_index_reserve_name,
5482
0, DICT_CLUSTERED, 0);
5483
error = row_create_index_for_mysql(index, trx, NULL);
5485
innodb_check_for_record_too_big_error(comp, error);
5487
error = convert_error_code_to_mysql(error, NULL);
5492
/*********************************************************************
5493
Update create_info. Used in SHOW CREATE TABLE et al. */
5496
ha_innobase::update_create_info(
5497
/*============================*/
5498
HA_CREATE_INFO* create_info) /* in/out: create info */
5500
if (!(create_info->used_fields & HA_CREATE_USED_AUTO)) {
5501
ha_innobase::info(HA_STATUS_AUTO);
5502
create_info->auto_increment_value = stats.auto_increment_value;
5506
/*********************************************************************
5507
Creates a new table to an InnoDB database. */
5510
ha_innobase::create(
5511
/*================*/
5512
/* out: error number */
5513
const char* name, /* in: table name */
5514
TABLE* form, /* in: information on table
5515
columns and indexes */
5516
HA_CREATE_INFO* create_info) /* in: more information of the
5517
created table, contains also the
5518
create statement string */
5521
dict_table_t* innobase_table;
5526
char name2[FN_REFLEN];
5527
char norm_name[FN_REFLEN];
5528
THD* thd = ha_thd();
5529
ib_longlong auto_inc_value;
5532
DBUG_ENTER("ha_innobase::create");
5534
DBUG_ASSERT(thd != NULL);
5535
DBUG_ASSERT(create_info != NULL);
5538
/* Names passed in from server are in two formats:
5539
1. <database_name>/<table_name>: for normal table creation
5540
2. full path: for temp table creation, or sym link
5542
When srv_file_per_table is on and mysqld_embedded is off,
5543
check for full path pattern, i.e.
5544
X:\dir\..., X is a driver letter, or
5545
\\dir1\dir2\..., UNC path
5546
returns error if it is in full path format, but not creating a temp.
5547
table. Currently InnoDB does not support symbolic link on Windows. */
5549
if (srv_file_per_table
5551
&& (!create_info->options & HA_LEX_CREATE_TMP_TABLE)) {
5553
if ((name[1] == ':')
5554
|| (name[0] == '\\' && name[1] == '\\')) {
5555
sql_print_error("Cannot create table %s\n", name);
5556
DBUG_RETURN(HA_ERR_GENERIC);
5561
if (form->s->fields > 1000) {
5562
/* The limit probably should be REC_MAX_N_FIELDS - 3 = 1020,
5563
but we play safe here */
5565
DBUG_RETURN(HA_ERR_TO_BIG_ROW);
5568
/* Get the transaction associated with the current thd, or create one
5569
if not yet created */
5571
parent_trx = check_trx_exists(thd);
5573
/* In case MySQL calls this in the middle of a SELECT query, release
5574
possible adaptive hash latch to avoid deadlocks of threads */
5576
trx_search_latch_release_if_reserved(parent_trx);
5578
trx = trx_allocate_for_mysql();
5580
trx->mysql_thd = thd;
5581
trx->mysql_query_str = thd_query(thd);
5583
if (thd_test_options(thd, OPTION_NO_FOREIGN_KEY_CHECKS)) {
5584
trx->check_foreigns = FALSE;
5587
if (thd_test_options(thd, OPTION_RELAXED_UNIQUE_CHECKS)) {
5588
trx->check_unique_secondary = FALSE;
5591
if (lower_case_table_names) {
5592
srv_lower_case_table_names = TRUE;
5594
srv_lower_case_table_names = FALSE;
5597
strcpy(name2, name);
5599
normalize_table_name(norm_name, name2);
5601
/* Latch the InnoDB data dictionary exclusively so that no deadlocks
5602
or lock waits can happen in it during a table create operation.
5603
Drop table etc. do this latching in row0mysql.c. */
5605
row_mysql_lock_data_dictionary(trx);
5607
/* Create the table definition in InnoDB */
5611
if (form->s->row_type != ROW_TYPE_REDUNDANT) {
5612
flags |= DICT_TF_COMPACT;
5615
/* Look for a primary key */
5617
primary_key_no= (form->s->primary_key != MAX_KEY ?
5618
(int) form->s->primary_key :
5621
/* Our function row_get_mysql_key_number_for_index assumes
5622
the primary key is always number 0, if it exists */
5624
DBUG_ASSERT(primary_key_no == -1 || primary_key_no == 0);
5626
/* Check for name conflicts (with reserved name) for
5627
any user indices to be created. */
5628
if (innobase_index_name_is_reserved(trx, form, norm_name)) {
5633
error = create_table_def(trx, form, norm_name,
5634
create_info->options & HA_LEX_CREATE_TMP_TABLE ? name2 : NULL,
5642
/* Create the keys */
5644
if (form->s->keys == 0 || primary_key_no == -1) {
5645
/* Create an index which is used as the clustered index;
5646
order the rows by their row id which is internally generated
5649
error = create_clustered_index_when_no_primary(
5650
trx, form->s->row_type != ROW_TYPE_REDUNDANT,
5657
if (primary_key_no != -1) {
5658
/* In InnoDB the clustered index must always be created
5660
if ((error = create_index(trx, form, norm_name,
5661
(uint) primary_key_no))) {
5666
for (i = 0; i < form->s->keys; i++) {
5668
if (i != (uint) primary_key_no) {
5670
if ((error = create_index(trx, form, norm_name, i))) {
5676
if (*trx->mysql_query_str) {
5677
error = row_table_add_foreign_constraints(trx,
5678
*trx->mysql_query_str, norm_name,
5679
create_info->options & HA_LEX_CREATE_TMP_TABLE);
5681
error = convert_error_code_to_mysql(error, NULL);
5688
innobase_commit_low(trx);
5690
row_mysql_unlock_data_dictionary(trx);
5692
/* Flush the log to reduce probability that the .frm files and
5693
the InnoDB data dictionary get out-of-sync if the user runs
5694
with innodb_flush_log_at_trx_commit = 0 */
5696
log_buffer_flush_to_disk();
5698
innobase_table = dict_table_get(norm_name, FALSE);
5700
DBUG_ASSERT(innobase_table != 0);
5702
/* Note: We can't call update_thd() as prebuilt will not be
5703
setup at this stage and so we use thd. */
5705
/* We need to copy the AUTOINC value from the old table if
5706
this is an ALTER TABLE or CREATE INDEX because CREATE INDEX
5707
does a table copy too. */
5709
if (((create_info->used_fields & HA_CREATE_USED_AUTO)
5710
|| thd_sql_command(thd) == SQLCOM_ALTER_TABLE
5711
|| thd_sql_command(thd) == SQLCOM_CREATE_INDEX)
5712
&& create_info->auto_increment_value > 0) {
5714
/* Query was one of :
5715
CREATE TABLE ...AUTO_INCREMENT = x; or
5716
ALTER TABLE...AUTO_INCREMENT = x; or
5717
CREATE INDEX x on t(...);
5718
Find out a table definition from the dictionary and get
5719
the current value of the auto increment field. Set a new
5720
value to the auto increment field if the value is greater
5721
than the maximum value in the column. */
5723
auto_inc_value = create_info->auto_increment_value;
5725
dict_table_autoinc_lock(innobase_table);
5726
dict_table_autoinc_initialize(innobase_table, auto_inc_value);
5727
dict_table_autoinc_unlock(innobase_table);
5730
/* Tell the InnoDB server that there might be work for
5733
srv_active_wake_master_thread();
5735
trx_free_for_mysql(trx);
5740
innobase_commit_low(trx);
5742
row_mysql_unlock_data_dictionary(trx);
5744
trx_free_for_mysql(trx);
5749
/*********************************************************************
5750
Discards or imports an InnoDB tablespace. */
5753
ha_innobase::discard_or_import_tablespace(
5754
/*======================================*/
5755
/* out: 0 == success, -1 == error */
5756
my_bool discard) /* in: TRUE if discard, else import */
5758
dict_table_t* dict_table;
5762
DBUG_ENTER("ha_innobase::discard_or_import_tablespace");
5764
ut_a(prebuilt->trx);
5765
ut_a(prebuilt->trx->magic_n == TRX_MAGIC_N);
5766
ut_a(prebuilt->trx == thd_to_trx(ha_thd()));
5768
dict_table = prebuilt->table;
5769
trx = prebuilt->trx;
5772
err = row_discard_tablespace_for_mysql(dict_table->name, trx);
5774
err = row_import_tablespace_for_mysql(dict_table->name, trx);
5777
err = convert_error_code_to_mysql(err, NULL);
5782
/*********************************************************************
5783
Deletes all rows of an InnoDB table. */
5786
ha_innobase::delete_all_rows(void)
5787
/*==============================*/
5788
/* out: error number */
5792
DBUG_ENTER("ha_innobase::delete_all_rows");
5794
/* Get the transaction associated with the current thd, or create one
5795
if not yet created, and update prebuilt->trx */
5797
update_thd(ha_thd());
5799
if (thd_sql_command(user_thd) != SQLCOM_TRUNCATE) {
5801
/* We only handle TRUNCATE TABLE t as a special case.
5802
DELETE FROM t will have to use ha_innobase::delete_row(),
5803
because DELETE is transactional while TRUNCATE is not. */
5804
DBUG_RETURN(my_errno=HA_ERR_WRONG_COMMAND);
5807
/* Truncate the table in InnoDB */
5809
error = row_truncate_table_for_mysql(prebuilt->table, prebuilt->trx);
5810
if (error == DB_ERROR) {
5811
/* Cannot truncate; resort to ha_innobase::delete_row() */
5815
error = convert_error_code_to_mysql(error, NULL);
5820
/*********************************************************************
5821
Drops a table from an InnoDB database. Before calling this function,
5822
MySQL calls innobase_commit to commit the transaction of the current user.
5823
Then the current user cannot have locks set on the table. Drop table
5824
operation inside InnoDB will remove all locks any user has on the table
5828
ha_innobase::delete_table(
5829
/*======================*/
5830
/* out: error number */
5831
const char* name) /* in: table name */
5837
THD *thd = ha_thd();
5838
char norm_name[1000];
5840
DBUG_ENTER("ha_innobase::delete_table");
5842
/* Strangely, MySQL passes the table name without the '.frm'
5843
extension, in contrast to ::create */
5844
normalize_table_name(norm_name, name);
5846
if (IS_MAGIC_TABLE_AND_USER_DENIED_ACCESS(norm_name, thd)) {
5847
DBUG_RETURN(HA_ERR_GENERIC);
5850
/* Get the transaction associated with the current thd, or create one
5851
if not yet created */
5853
parent_trx = check_trx_exists(thd);
5855
/* In case MySQL calls this in the middle of a SELECT query, release
5856
possible adaptive hash latch to avoid deadlocks of threads */
5858
trx_search_latch_release_if_reserved(parent_trx);
5860
if (lower_case_table_names) {
5861
srv_lower_case_table_names = TRUE;
5863
srv_lower_case_table_names = FALSE;
5866
trx = trx_allocate_for_mysql();
5868
trx->mysql_thd = thd;
5869
trx->mysql_query_str = thd_query(thd);
5871
if (thd_test_options(thd, OPTION_NO_FOREIGN_KEY_CHECKS)) {
5872
trx->check_foreigns = FALSE;
5875
if (thd_test_options(thd, OPTION_RELAXED_UNIQUE_CHECKS)) {
5876
trx->check_unique_secondary = FALSE;
5879
name_len = strlen(name);
5881
assert(name_len < 1000);
5883
/* Drop the table in InnoDB */
5885
error = row_drop_table_for_mysql(norm_name, trx,
5886
thd_sql_command(thd)
5889
/* Flush the log to reduce probability that the .frm files and
5890
the InnoDB data dictionary get out-of-sync if the user runs
5891
with innodb_flush_log_at_trx_commit = 0 */
5893
log_buffer_flush_to_disk();
5895
/* Tell the InnoDB server that there might be work for
5898
srv_active_wake_master_thread();
5900
innobase_commit_low(trx);
5902
trx_free_for_mysql(trx);
5904
error = convert_error_code_to_mysql(error, NULL);
5909
/*********************************************************************
5910
Removes all tables in the named database inside InnoDB. */
5913
innobase_drop_database(
5914
/*===================*/
5915
/* out: error number */
5916
handlerton *hton, /* in: handlerton of Innodb */
5917
char* path) /* in: database path; inside InnoDB the name
5918
of the last directory in the path is used as
5919
the database name: for example, in 'mysql/data/test'
5920
the database name is 'test' */
5928
THD* thd = current_thd;
5930
/* Get the transaction associated with the current thd, or create one
5931
if not yet created */
5933
parent_trx = check_trx_exists(thd);
5935
/* In case MySQL calls this in the middle of a SELECT query, release
5936
possible adaptive hash latch to avoid deadlocks of threads */
5938
trx_search_latch_release_if_reserved(parent_trx);
5940
ptr = strend(path) - 2;
5942
while (ptr >= path && *ptr != '\\' && *ptr != '/') {
5948
namebuf = (char*) my_malloc((uint) len + 2, MYF(0));
5950
memcpy(namebuf, ptr, len);
5952
namebuf[len + 1] = '\0';
5954
innobase_casedn_str(namebuf);
5956
trx = trx_allocate_for_mysql();
5957
trx->mysql_thd = thd;
5958
trx->mysql_query_str = thd_query(thd);
5960
if (thd_test_options(thd, OPTION_NO_FOREIGN_KEY_CHECKS)) {
5961
trx->check_foreigns = FALSE;
5964
error = row_drop_database_for_mysql(namebuf, trx);
5965
my_free(namebuf, MYF(0));
5967
/* Flush the log to reduce probability that the .frm files and
5968
the InnoDB data dictionary get out-of-sync if the user runs
5969
with innodb_flush_log_at_trx_commit = 0 */
5971
log_buffer_flush_to_disk();
5973
/* Tell the InnoDB server that there might be work for
5976
srv_active_wake_master_thread();
5978
innobase_commit_low(trx);
5979
trx_free_for_mysql(trx);
5980
#ifdef NO_LONGER_INTERESTED_IN_DROP_DB_ERROR
5981
error = convert_error_code_to_mysql(error, NULL);
5989
/*************************************************************************
5990
Renames an InnoDB table. */
5993
ha_innobase::rename_table(
5994
/*======================*/
5995
/* out: 0 or error code */
5996
const char* from, /* in: old name of the table */
5997
const char* to) /* in: new name of the table */
6004
char norm_from[1000];
6006
THD* thd = ha_thd();
6008
DBUG_ENTER("ha_innobase::rename_table");
6010
/* Get the transaction associated with the current thd, or create one
6011
if not yet created */
6013
parent_trx = check_trx_exists(thd);
6015
/* In case MySQL calls this in the middle of a SELECT query, release
6016
possible adaptive hash latch to avoid deadlocks of threads */
6018
trx_search_latch_release_if_reserved(parent_trx);
6020
if (lower_case_table_names) {
6021
srv_lower_case_table_names = TRUE;
6023
srv_lower_case_table_names = FALSE;
6026
trx = trx_allocate_for_mysql();
6027
trx->mysql_thd = thd;
6028
trx->mysql_query_str = thd_query(thd);
6030
if (thd_test_options(thd, OPTION_NO_FOREIGN_KEY_CHECKS)) {
6031
trx->check_foreigns = FALSE;
6034
name_len1 = strlen(from);
6035
name_len2 = strlen(to);
6037
assert(name_len1 < 1000);
6038
assert(name_len2 < 1000);
6040
normalize_table_name(norm_from, from);
6041
normalize_table_name(norm_to, to);
6043
/* Rename the table in InnoDB */
6045
error = row_rename_table_for_mysql(norm_from, norm_to, trx);
6047
/* Flush the log to reduce probability that the .frm files and
6048
the InnoDB data dictionary get out-of-sync if the user runs
6049
with innodb_flush_log_at_trx_commit = 0 */
6051
log_buffer_flush_to_disk();
6053
/* Tell the InnoDB server that there might be work for
6056
srv_active_wake_master_thread();
6058
innobase_commit_low(trx);
6059
trx_free_for_mysql(trx);
6061
/* Add a special case to handle the Duplicated Key error
6062
and return DB_ERROR instead.
6063
This is to avoid a possible SIGSEGV error from mysql error
6064
handling code. Currently, mysql handles the Duplicated Key
6065
error by re-entering the storage layer and getting dup key
6066
info by calling get_dup_key(). This operation requires a valid
6067
table handle ('row_prebuilt_t' structure) which could no
6068
longer be available in the error handling stage. The suggested
6069
solution is to report a 'table exists' error message (since
6070
the dup key error here is due to an existing table whose name
6071
is the one we are trying to rename to) and return the generic
6073
if (error == (int) DB_DUPLICATE_KEY) {
6074
my_error(ER_TABLE_EXISTS_ERROR, MYF(0), to);
6079
error = convert_error_code_to_mysql(error, NULL);
6084
/*************************************************************************
6085
Estimates the number of index records in a range. */
6088
ha_innobase::records_in_range(
6089
/*==========================*/
6090
/* out: estimated number of
6092
uint keynr, /* in: index number */
6093
key_range *min_key, /* in: start key value of the
6094
range, may also be 0 */
6095
key_range *max_key) /* in: range end key val, may
6099
dict_index_t* index;
6100
uchar* key_val_buff2 = (uchar*) my_malloc(
6102
+ table->s->max_key_length + 100,
6104
ulint buff2_len = table->s->reclength
6105
+ table->s->max_key_length + 100;
6106
dtuple_t* range_start;
6107
dtuple_t* range_end;
6114
DBUG_ENTER("records_in_range");
6116
ut_a(prebuilt->trx == thd_to_trx(ha_thd()));
6118
prebuilt->trx->op_info = (char*)"estimating records in index range";
6120
/* In case MySQL calls this in the middle of a SELECT query, release
6121
possible adaptive hash latch to avoid deadlocks of threads */
6123
trx_search_latch_release_if_reserved(prebuilt->trx);
6125
active_index = keynr;
6127
key = table->key_info + active_index;
6129
index = dict_table_get_index_noninline(prebuilt->table, key->name);
6131
range_start = dtuple_create_for_mysql(&heap1, key->key_parts);
6132
dict_index_copy_types(range_start, index, key->key_parts);
6134
range_end = dtuple_create_for_mysql(&heap2, key->key_parts);
6135
dict_index_copy_types(range_end, index, key->key_parts);
6137
row_sel_convert_mysql_key_to_innobase(
6138
range_start, (byte*) key_val_buff,
6139
(ulint)upd_and_key_val_buff_len,
6141
(byte*) (min_key ? min_key->key :
6143
(ulint) (min_key ? min_key->length : 0),
6146
row_sel_convert_mysql_key_to_innobase(
6147
range_end, (byte*) key_val_buff2,
6149
(byte*) (max_key ? max_key->key :
6151
(ulint) (max_key ? max_key->length : 0),
6154
mode1 = convert_search_mode_to_innobase(min_key ? min_key->flag :
6156
mode2 = convert_search_mode_to_innobase(max_key ? max_key->flag :
6159
if (mode1 != PAGE_CUR_UNSUPP && mode2 != PAGE_CUR_UNSUPP) {
6161
n_rows = btr_estimate_n_rows_in_range(index, range_start,
6166
n_rows = HA_POS_ERROR;
6169
dtuple_free_for_mysql(heap1);
6170
dtuple_free_for_mysql(heap2);
6172
my_free(key_val_buff2, MYF(0));
6174
prebuilt->trx->op_info = (char*)"";
6176
/* The MySQL optimizer seems to believe an estimate of 0 rows is
6177
always accurate and may return the result 'Empty set' based on that.
6178
The accuracy is not guaranteed, and even if it were, for a locking
6179
read we should anyway perform the search to set the next-key lock.
6180
Add 1 to the value to make sure MySQL does not make the assumption! */
6186
DBUG_RETURN((ha_rows) n_rows);
6189
/*************************************************************************
6190
Gives an UPPER BOUND to the number of rows in a table. This is used in
6194
ha_innobase::estimate_rows_upper_bound(void)
6195
/*======================================*/
6196
/* out: upper bound of rows */
6198
dict_index_t* index;
6200
ulonglong local_data_file_length;
6202
DBUG_ENTER("estimate_rows_upper_bound");
6204
/* We do not know if MySQL can call this function before calling
6205
external_lock(). To be safe, update the thd of the current table
6208
update_thd(ha_thd());
6210
prebuilt->trx->op_info = (char*)
6211
"calculating upper bound for table rows";
6213
/* In case MySQL calls this in the middle of a SELECT query, release
6214
possible adaptive hash latch to avoid deadlocks of threads */
6216
trx_search_latch_release_if_reserved(prebuilt->trx);
6218
index = dict_table_get_first_index_noninline(prebuilt->table);
6220
local_data_file_length = ((ulonglong) index->stat_n_leaf_pages)
6223
/* Calculate a minimum length for a clustered index record and from
6224
that an upper bound for the number of rows. Since we only calculate
6225
new statistics in row0mysql.c when a table has grown by a threshold
6226
factor, we must add a safety factor 2 in front of the formula below. */
6228
estimate = 2 * local_data_file_length /
6229
dict_index_calc_min_rec_len(index);
6231
prebuilt->trx->op_info = (char*)"";
6233
DBUG_RETURN((ha_rows) estimate);
6236
/*************************************************************************
6237
How many seeks it will take to read through the table. This is to be
6238
comparable to the number returned by records_in_range so that we can
6239
decide if we should scan the table or use keys. */
6242
ha_innobase::scan_time()
6243
/*====================*/
6244
/* out: estimated time measured in disk seeks */
6246
/* Since MySQL seems to favor table scans too much over index
6247
searches, we pretend that a sequential read takes the same time
6248
as a random disk read, that is, we do not divide the following
6249
by 10, which would be physically realistic. */
6251
return((double) (prebuilt->table->stat_clustered_index_size));
6254
/**********************************************************************
6255
Calculate the time it takes to read a set of ranges through an index
6256
This enables us to optimise reads for clustered indexes. */
6259
ha_innobase::read_time(
6260
/*===================*/
6261
/* out: estimated time measured in disk seeks */
6262
uint index, /* in: key number */
6263
uint ranges, /* in: how many ranges */
6264
ha_rows rows) /* in: estimated number of rows in the ranges */
6267
double time_for_scan;
6269
if (index != table->s->primary_key) {
6271
return(handler::read_time(index, ranges, rows));
6276
return((double) rows);
6279
/* Assume that the read time is proportional to the scan time for all
6280
rows + at most one seek per range. */
6282
time_for_scan = scan_time();
6284
if ((total_rows = estimate_rows_upper_bound()) < rows) {
6286
return(time_for_scan);
6289
return(ranges + (double) rows / (double) total_rows * time_for_scan);
6292
/*************************************************************************
6293
Returns statistics information of the table to the MySQL interpreter,
6294
in various fields of the handle object. */
6299
uint flag) /* in: what information MySQL requests */
6301
dict_table_t* ib_table;
6302
dict_index_t* index;
6303
ha_rows rec_per_key;
6307
char path[FN_REFLEN];
6308
os_file_stat_t stat_info;
6312
/* If we are forcing recovery at a high level, we will suppress
6313
statistics calculation on tables, because that may crash the
6314
server if an index is badly corrupted. */
6316
if (srv_force_recovery >= SRV_FORCE_NO_IBUF_MERGE) {
6318
/* We return success (0) instead of HA_ERR_CRASHED,
6319
because we want MySQL to process this query and not
6320
stop, like it would do if it received the error code
6326
/* We do not know if MySQL can call this function before calling
6327
external_lock(). To be safe, update the thd of the current table
6330
update_thd(ha_thd());
6332
/* In case MySQL calls this in the middle of a SELECT query, release
6333
possible adaptive hash latch to avoid deadlocks of threads */
6335
prebuilt->trx->op_info = (char*)"returning various info to MySQL";
6337
trx_search_latch_release_if_reserved(prebuilt->trx);
6339
ib_table = prebuilt->table;
6341
if (flag & HA_STATUS_TIME) {
6342
if (innobase_stats_on_metadata) {
6343
/* In sql_show we call with this flag: update
6344
then statistics so that they are up-to-date */
6346
prebuilt->trx->op_info = "updating table statistics";
6348
dict_update_statistics(ib_table);
6350
prebuilt->trx->op_info = "returning various info to MySQL";
6353
my_snprintf(path, sizeof(path), "%s/%s%s",
6354
mysql_data_home, ib_table->name, reg_ext);
6356
unpack_filename(path,path);
6358
/* Note that we do not know the access time of the table,
6359
nor the CHECK TABLE time, nor the UPDATE or INSERT time. */
6361
if (os_file_get_status(path,&stat_info)) {
6362
stats.create_time = (ulong) stat_info.ctime;
6366
if (flag & HA_STATUS_VARIABLE) {
6367
n_rows = ib_table->stat_n_rows;
6369
/* Because we do not protect stat_n_rows by any mutex in a
6370
delete, it is theoretically possible that the value can be
6371
smaller than zero! TODO: fix this race.
6373
The MySQL optimizer seems to assume in a left join that n_rows
6374
is an accurate estimate if it is zero. Of course, it is not,
6375
since we do not have any locks on the rows yet at this phase.
6376
Since SHOW TABLE STATUS seems to call this function with the
6377
HA_STATUS_TIME flag set, while the left join optimizer does not
6378
set that flag, we add one to a zero value if the flag is not
6379
set. That way SHOW TABLE STATUS will show the best estimate,
6380
while the optimizer never sees the table empty. */
6386
if (n_rows == 0 && !(flag & HA_STATUS_TIME)) {
6390
/* Fix bug#40386: Not flushing query cache after truncate.
6391
n_rows can not be 0 unless the table is empty, set to 1
6392
instead. The original problem of bug#29507 is actually
6393
fixed in the server code. */
6394
if (thd_sql_command(user_thd) == SQLCOM_TRUNCATE) {
6398
/* We need to reset the prebuilt value too, otherwise
6399
checks for values greater than the last value written
6400
to the table will fail and the autoinc counter will
6401
not be updated. This will force write_row() into
6402
attempting an update of the table's AUTOINC counter. */
6404
prebuilt->autoinc_last_value = 0;
6407
stats.records = (ha_rows)n_rows;
6409
stats.data_file_length = ((ulonglong)
6410
ib_table->stat_clustered_index_size)
6412
stats.index_file_length = ((ulonglong)
6413
ib_table->stat_sum_of_other_index_sizes)
6416
/* Since fsp_get_available_space_in_free_extents() is
6417
acquiring latches inside InnoDB, we do not call it if we
6418
are asked by MySQL to avoid locking. Another reason to
6419
avoid the call is that it uses quite a lot of CPU.
6421
We do not update delete_length if no locking is requested
6422
so the "old" value can remain. delete_length is initialized
6423
to 0 in the ha_statistics' constructor. */
6424
if (!(flag & HA_STATUS_NO_LOCK)) {
6426
/* lock the data dictionary to avoid races with
6427
ibd_file_missing and tablespace_discarded */
6428
row_mysql_lock_data_dictionary(prebuilt->trx);
6430
/* ib_table->space must be an existent tablespace */
6431
if (!ib_table->ibd_file_missing
6432
&& !ib_table->tablespace_discarded) {
6434
stats.delete_length =
6435
fsp_get_available_space_in_free_extents(
6436
ib_table->space) * 1024;
6443
push_warning_printf(
6445
MYSQL_ERROR::WARN_LEVEL_WARN,
6447
"InnoDB: Trying to get the free "
6448
"space for table %s but its "
6449
"tablespace has been discarded or "
6450
"the .ibd file is missing. Setting "
6451
"the free space to zero.",
6454
stats.delete_length = 0;
6457
row_mysql_unlock_data_dictionary(prebuilt->trx);
6460
stats.check_time = 0;
6462
if (stats.records == 0) {
6463
stats.mean_rec_length = 0;
6465
stats.mean_rec_length = (ulong) (stats.data_file_length / stats.records);
6469
if (flag & HA_STATUS_CONST) {
6470
index = dict_table_get_first_index_noninline(ib_table);
6472
if (prebuilt->clust_index_was_generated) {
6473
index = dict_table_get_next_index_noninline(index);
6476
for (i = 0; i < table->s->keys; i++) {
6477
if (index == NULL) {
6478
sql_print_error("Table %s contains fewer "
6479
"indexes inside InnoDB than "
6480
"are defined in the MySQL "
6481
".frm file. Have you mixed up "
6482
".frm files from different "
6483
"installations? See "
6484
"http://dev.mysql.com/doc/refman/5.1/en/innodb-troubleshooting.html\n",
6490
for (j = 0; j < table->key_info[i].key_parts; j++) {
6492
if (j + 1 > index->n_uniq) {
6494
"Index %s of %s has %lu columns unique inside InnoDB, but MySQL is asking "
6495
"statistics for %lu columns. Have you mixed up .frm files from different "
6497
"See http://dev.mysql.com/doc/refman/5.1/en/innodb-troubleshooting.html\n",
6501
index->n_uniq, j + 1);
6505
if (index->stat_n_diff_key_vals[j + 1] == 0) {
6507
rec_per_key = stats.records;
6509
rec_per_key = (ha_rows)(stats.records /
6510
index->stat_n_diff_key_vals[j + 1]);
6513
/* Since MySQL seems to favor table scans
6514
too much over index searches, we pretend
6515
index selectivity is 2 times better than
6518
rec_per_key = rec_per_key / 2;
6520
if (rec_per_key == 0) {
6524
table->key_info[i].rec_per_key[j]=
6525
rec_per_key >= ~(ulong) 0 ? ~(ulong) 0 :
6526
(ulong) rec_per_key;
6529
index = dict_table_get_next_index_noninline(index);
6533
if (flag & HA_STATUS_ERRKEY) {
6534
ut_a(prebuilt->trx);
6535
ut_a(prebuilt->trx->magic_n == TRX_MAGIC_N);
6537
errkey = (unsigned int) row_get_mysql_key_number_for_index(
6538
(dict_index_t*) trx_get_error_info(prebuilt->trx));
6541
if (flag & HA_STATUS_AUTO && table->found_next_number_field) {
6542
stats.auto_increment_value = innobase_peek_autoinc();
6545
prebuilt->trx->op_info = (char*)"";
6550
/**************************************************************************
6551
Updates index cardinalities of the table, based on 8 random dives into
6552
each index tree. This does NOT calculate exact statistics on the table. */
6555
ha_innobase::analyze(
6556
/*=================*/
6557
/* out: returns always 0 (success) */
6558
THD* thd, /* in: connection thread handle */
6559
HA_CHECK_OPT* check_opt) /* in: currently ignored */
6561
/* Serialize ANALYZE TABLE inside InnoDB, see
6562
Bug#38996 Race condition in ANALYZE TABLE */
6563
pthread_mutex_lock(&analyze_mutex);
6565
/* Simply call ::info() with all the flags */
6566
info(HA_STATUS_TIME | HA_STATUS_CONST | HA_STATUS_VARIABLE);
6568
pthread_mutex_unlock(&analyze_mutex);
6573
/**************************************************************************
6574
This is mapped to "ALTER TABLE tablename ENGINE=InnoDB", which rebuilds
6575
the table in MySQL. */
6578
ha_innobase::optimize(
6579
/*==================*/
6580
THD* thd, /* in: connection thread handle */
6581
HA_CHECK_OPT* check_opt) /* in: currently ignored */
6583
return(HA_ADMIN_TRY_ALTER);
6586
/***********************************************************************
6587
Tries to check that an InnoDB table is not corrupted. If corruption is
6588
noticed, prints to stderr information about it. In case of corruption
6589
may also assert a failure and crash the server. */
6594
/* out: HA_ADMIN_CORRUPT or
6596
THD* thd, /* in: user thread handle */
6597
HA_CHECK_OPT* check_opt) /* in: check options, currently
6602
DBUG_ASSERT(thd == ha_thd());
6603
ut_a(prebuilt->trx);
6604
ut_a(prebuilt->trx->magic_n == TRX_MAGIC_N);
6605
ut_a(prebuilt->trx == thd_to_trx(thd));
6607
if (prebuilt->mysql_template == NULL) {
6608
/* Build the template; we will use a dummy template
6609
in index scans done in checking */
6611
build_template(prebuilt, NULL, table, ROW_MYSQL_WHOLE_ROW);
6614
ret = row_check_table_for_mysql(prebuilt);
6616
if (ret == DB_SUCCESS) {
6617
return(HA_ADMIN_OK);
6620
return(HA_ADMIN_CORRUPT);
6623
/*****************************************************************
6624
Adds information about free space in the InnoDB tablespace to a table comment
6625
which is printed out when a user calls SHOW TABLE STATUS. Adds also info on
6629
ha_innobase::update_table_comment(
6630
/*==============================*/
6631
/* out: table comment + InnoDB free space +
6632
info on foreign keys */
6633
const char* comment)/* in: table comment defined by user */
6635
uint length = (uint) strlen(comment);
6639
/* We do not know if MySQL can call this function before calling
6640
external_lock(). To be safe, update the thd of the current table
6643
if (length > 64000 - 3) {
6644
return((char*)comment); /* string too long */
6647
update_thd(ha_thd());
6649
prebuilt->trx->op_info = (char*)"returning table comment";
6651
/* In case MySQL calls this in the middle of a SELECT query, release
6652
possible adaptive hash latch to avoid deadlocks of threads */
6654
trx_search_latch_release_if_reserved(prebuilt->trx);
6657
/* output the data to a temporary file */
6659
mutex_enter_noninline(&srv_dict_tmpfile_mutex);
6660
rewind(srv_dict_tmpfile);
6662
fprintf(srv_dict_tmpfile, "InnoDB free: %llu kB",
6663
fsp_get_available_space_in_free_extents(
6664
prebuilt->table->space));
6666
dict_print_info_on_foreign_keys(FALSE, srv_dict_tmpfile,
6667
prebuilt->trx, prebuilt->table);
6668
flen = ftell(srv_dict_tmpfile);
6671
} else if (length + flen + 3 > 64000) {
6672
flen = 64000 - 3 - length;
6675
/* allocate buffer for the full string, and
6676
read the contents of the temporary file */
6678
str = (char*) my_malloc(length + flen + 3, MYF(0));
6681
char* pos = str + length;
6683
memcpy(str, comment, length);
6687
rewind(srv_dict_tmpfile);
6688
flen = (uint) fread(pos, 1, flen, srv_dict_tmpfile);
6692
mutex_exit_noninline(&srv_dict_tmpfile_mutex);
6694
prebuilt->trx->op_info = (char*)"";
6696
return(str ? str : (char*) comment);
6699
/***********************************************************************
6700
Gets the foreign key create info for a table stored in InnoDB. */
6703
ha_innobase::get_foreign_key_create_info(void)
6704
/*==========================================*/
6705
/* out, own: character string in the form which
6706
can be inserted to the CREATE TABLE statement,
6707
MUST be freed with ::free_foreign_key_create_info */
6712
ut_a(prebuilt != NULL);
6714
/* We do not know if MySQL can call this function before calling
6715
external_lock(). To be safe, update the thd of the current table
6718
update_thd(ha_thd());
6720
prebuilt->trx->op_info = (char*)"getting info on foreign keys";
6722
/* In case MySQL calls this in the middle of a SELECT query,
6723
release possible adaptive hash latch to avoid
6724
deadlocks of threads */
6726
trx_search_latch_release_if_reserved(prebuilt->trx);
6728
mutex_enter_noninline(&srv_dict_tmpfile_mutex);
6729
rewind(srv_dict_tmpfile);
6731
/* output the data to a temporary file */
6732
dict_print_info_on_foreign_keys(TRUE, srv_dict_tmpfile,
6733
prebuilt->trx, prebuilt->table);
6734
prebuilt->trx->op_info = (char*)"";
6736
flen = ftell(srv_dict_tmpfile);
6739
} else if (flen > 64000 - 1) {
6743
/* allocate buffer for the string, and
6744
read the contents of the temporary file */
6746
str = (char*) my_malloc(flen + 1, MYF(0));
6749
rewind(srv_dict_tmpfile);
6750
flen = (uint) fread(str, 1, flen, srv_dict_tmpfile);
6754
mutex_exit_noninline(&srv_dict_tmpfile_mutex);
6761
ha_innobase::get_foreign_key_list(THD *thd, List<FOREIGN_KEY_INFO> *f_key_list)
6763
dict_foreign_t* foreign;
6765
DBUG_ENTER("get_foreign_key_list");
6766
ut_a(prebuilt != NULL);
6767
update_thd(ha_thd());
6768
prebuilt->trx->op_info = (char*)"getting list of foreign keys";
6769
trx_search_latch_release_if_reserved(prebuilt->trx);
6770
mutex_enter_noninline(&(dict_sys->mutex));
6771
foreign = UT_LIST_GET_FIRST(prebuilt->table->foreign_list);
6773
while (foreign != NULL) {
6775
FOREIGN_KEY_INFO f_key_info;
6776
LEX_STRING *name= 0;
6778
char uname[NAME_LEN+1]; /* Unencoded name */
6779
char db_name[NAME_LEN+1];
6780
const char *tmp_buff;
6782
tmp_buff= foreign->id;
6784
while (tmp_buff[i] != '/')
6787
f_key_info.forein_id = thd_make_lex_string(thd, 0,
6788
tmp_buff, (uint) strlen(tmp_buff), 1);
6789
tmp_buff= foreign->referenced_table_name;
6793
while (tmp_buff[i] != '/')
6795
db_name[i]= tmp_buff[i];
6799
ulen= filename_to_tablename(db_name, uname, sizeof(uname));
6800
f_key_info.referenced_db = thd_make_lex_string(thd, 0,
6805
ulen= filename_to_tablename(tmp_buff, uname, sizeof(uname));
6806
f_key_info.referenced_table = thd_make_lex_string(thd, 0,
6810
tmp_buff= foreign->foreign_col_names[i];
6811
name = thd_make_lex_string(thd, name,
6812
tmp_buff, (uint) strlen(tmp_buff), 1);
6813
f_key_info.foreign_fields.push_back(name);
6814
tmp_buff= foreign->referenced_col_names[i];
6815
name = thd_make_lex_string(thd, name,
6816
tmp_buff, (uint) strlen(tmp_buff), 1);
6817
f_key_info.referenced_fields.push_back(name);
6818
if (++i >= foreign->n_fields)
6823
if (foreign->type & DICT_FOREIGN_ON_DELETE_CASCADE)
6826
tmp_buff= "CASCADE";
6828
else if (foreign->type & DICT_FOREIGN_ON_DELETE_SET_NULL)
6831
tmp_buff= "SET NULL";
6833
else if (foreign->type & DICT_FOREIGN_ON_DELETE_NO_ACTION)
6836
tmp_buff= "NO ACTION";
6841
tmp_buff= "RESTRICT";
6843
f_key_info.delete_method = thd_make_lex_string(
6844
thd, f_key_info.delete_method, tmp_buff, length, 1);
6847
if (foreign->type & DICT_FOREIGN_ON_UPDATE_CASCADE)
6850
tmp_buff= "CASCADE";
6852
else if (foreign->type & DICT_FOREIGN_ON_UPDATE_SET_NULL)
6855
tmp_buff= "SET NULL";
6857
else if (foreign->type & DICT_FOREIGN_ON_UPDATE_NO_ACTION)
6860
tmp_buff= "NO ACTION";
6865
tmp_buff= "RESTRICT";
6867
f_key_info.update_method = thd_make_lex_string(
6868
thd, f_key_info.update_method, tmp_buff, length, 1);
6869
if (foreign->referenced_index &&
6870
foreign->referenced_index->name)
6872
f_key_info.referenced_key_name = thd_make_lex_string(
6873
thd, f_key_info.referenced_key_name,
6874
foreign->referenced_index->name,
6875
(uint) strlen(foreign->referenced_index->name), 1);
6878
f_key_info.referenced_key_name= 0;
6880
FOREIGN_KEY_INFO *pf_key_info = (FOREIGN_KEY_INFO *)
6881
thd_memdup(thd, &f_key_info, sizeof(FOREIGN_KEY_INFO));
6882
f_key_list->push_back(pf_key_info);
6883
foreign = UT_LIST_GET_NEXT(foreign_list, foreign);
6885
mutex_exit_noninline(&(dict_sys->mutex));
6886
prebuilt->trx->op_info = (char*)"";
6891
/*********************************************************************
6892
Checks if ALTER TABLE may change the storage engine of the table.
6893
Changing storage engines is not allowed for tables for which there
6894
are foreign key constraints (parent or child tables). */
6897
ha_innobase::can_switch_engines(void)
6898
/*=================================*/
6902
DBUG_ENTER("ha_innobase::can_switch_engines");
6904
ut_a(prebuilt->trx == thd_to_trx(ha_thd()));
6906
prebuilt->trx->op_info =
6907
"determining if there are foreign key constraints";
6908
row_mysql_lock_data_dictionary(prebuilt->trx);
6910
can_switch = !UT_LIST_GET_FIRST(prebuilt->table->referenced_list)
6911
&& !UT_LIST_GET_FIRST(prebuilt->table->foreign_list);
6913
row_mysql_unlock_data_dictionary(prebuilt->trx);
6914
prebuilt->trx->op_info = "";
6916
DBUG_RETURN(can_switch);
6919
/***********************************************************************
6920
Checks if a table is referenced by a foreign key. The MySQL manual states that
6921
a REPLACE is either equivalent to an INSERT, or DELETE(s) + INSERT. Only a
6922
delete is then allowed internally to resolve a duplicate key conflict in
6923
REPLACE, not an update. */
6926
ha_innobase::referenced_by_foreign_key(void)
6927
/*========================================*/
6928
/* out: > 0 if referenced by a FOREIGN KEY */
6930
if (dict_table_referenced_by_foreign_key(prebuilt->table)) {
6938
/***********************************************************************
6939
Frees the foreign key create info for a table stored in InnoDB, if it is
6943
ha_innobase::free_foreign_key_create_info(
6944
/*======================================*/
6945
char* str) /* in, own: create info string to free */
6948
my_free(str, MYF(0));
6952
/***********************************************************************
6953
Tells something additional to the handler about how to do things. */
6958
/* out: 0 or error number */
6959
enum ha_extra_function operation)
6960
/* in: HA_EXTRA_FLUSH or some other flag */
6962
/* Warning: since it is not sure that MySQL calls external_lock
6963
before calling this function, the trx field in prebuilt can be
6966
switch (operation) {
6967
case HA_EXTRA_FLUSH:
6968
if (prebuilt->blob_heap) {
6969
row_mysql_prebuilt_free_blob_heap(prebuilt);
6972
case HA_EXTRA_RESET_STATE:
6973
reset_template(prebuilt);
6975
case HA_EXTRA_NO_KEYREAD:
6976
prebuilt->read_just_key = 0;
6978
case HA_EXTRA_KEYREAD:
6979
prebuilt->read_just_key = 1;
6981
case HA_EXTRA_KEYREAD_PRESERVE_FIELDS:
6982
prebuilt->keep_other_fields_on_keyread = 1;
6985
/* IMPORTANT: prebuilt->trx can be obsolete in
6986
this method, because it is not sure that MySQL
6987
calls external_lock before this method with the
6988
parameters below. We must not invoke update_thd()
6989
either, because the calling threads may change.
6990
CAREFUL HERE, OR MEMORY CORRUPTION MAY OCCUR! */
6991
case HA_EXTRA_IGNORE_DUP_KEY:
6992
thd_to_trx(ha_thd())->duplicates |= TRX_DUP_IGNORE;
6994
case HA_EXTRA_WRITE_CAN_REPLACE:
6995
thd_to_trx(ha_thd())->duplicates |= TRX_DUP_REPLACE;
6997
case HA_EXTRA_WRITE_CANNOT_REPLACE:
6998
thd_to_trx(ha_thd())->duplicates &= ~TRX_DUP_REPLACE;
7000
case HA_EXTRA_NO_IGNORE_DUP_KEY:
7001
thd_to_trx(ha_thd())->duplicates &=
7002
~(TRX_DUP_IGNORE | TRX_DUP_REPLACE);
7004
default:/* Do nothing */
7011
/**********************************************************************
7012
Reset state of file to after 'open'.
7013
This function is called after every statement for all tables used
7014
by that statement. */
7015
int ha_innobase::reset()
7017
if (prebuilt->blob_heap) {
7018
row_mysql_prebuilt_free_blob_heap(prebuilt);
7021
reset_template(prebuilt);
7023
/* TODO: This should really be reset in reset_template() but for now
7024
it's safer to do it explicitly here. */
7026
/* This is a statement level counter. */
7027
prebuilt->autoinc_last_value = 0;
7032
/**********************************************************************
7033
MySQL calls this function at the start of each SQL statement inside LOCK
7034
TABLES. Inside LOCK TABLES the ::external_lock method does not work to
7035
mark SQL statement borders. Note also a special case: if a temporary table
7036
is created inside LOCK TABLES, MySQL has not called external_lock() at all
7038
MySQL-5.0 also calls this before each statement in an execution of a stored
7039
procedure. To make the execution more deterministic for binlogging, MySQL-5.0
7040
locks all tables involved in a stored procedure with full explicit table
7041
locks (thd_in_lock_tables(thd) holds in store_lock()) before executing the
7045
ha_innobase::start_stmt(
7046
/*====================*/
7047
/* out: 0 or error code */
7048
THD* thd, /* in: handle to the user thread */
7049
thr_lock_type lock_type)
7055
trx = prebuilt->trx;
7057
/* Here we release the search latch and the InnoDB thread FIFO ticket
7058
if they were reserved. They should have been released already at the
7059
end of the previous statement, but because inside LOCK TABLES the
7060
lock count method does not work to mark the end of a SELECT statement,
7061
that may not be the case. We MUST release the search latch before an
7062
INSERT, for example. */
7064
innobase_release_stat_resources(trx);
7066
/* Reset the AUTOINC statement level counter for multi-row INSERTs. */
7067
trx->n_autoinc_rows = 0;
7069
prebuilt->sql_stat_start = TRUE;
7070
prebuilt->hint_need_to_fetch_extra_cols = 0;
7071
reset_template(prebuilt);
7073
if (!prebuilt->mysql_has_locked) {
7074
/* This handle is for a temporary table created inside
7075
this same LOCK TABLES; since MySQL does NOT call external_lock
7076
in this case, we must use x-row locks inside InnoDB to be
7077
prepared for an update of a row */
7079
prebuilt->select_lock_type = LOCK_X;
7081
if (trx->isolation_level != TRX_ISO_SERIALIZABLE
7082
&& thd_sql_command(thd) == SQLCOM_SELECT
7083
&& lock_type == TL_READ) {
7085
/* For other than temporary tables, we obtain
7086
no lock for consistent read (plain SELECT). */
7088
prebuilt->select_lock_type = LOCK_NONE;
7090
/* Not a consistent read: restore the
7091
select_lock_type value. The value of
7092
stored_select_lock_type was decided in:
7094
2) ::external_lock(),
7095
3) ::init_table_handle_for_HANDLER(), and
7096
4) ::transactional_table_lock(). */
7098
prebuilt->select_lock_type =
7099
prebuilt->stored_select_lock_type;
7103
trx->detailed_error[0] = '\0';
7105
/* Set the MySQL flag to mark that there is an active transaction */
7106
if (trx->active_trans == 0) {
7108
innobase_register_trx_and_stmt(ht, thd);
7109
trx->active_trans = 1;
7111
innobase_register_stmt(ht, thd);
7117
/**********************************************************************
7118
Maps a MySQL trx isolation level code to the InnoDB isolation level code */
7121
innobase_map_isolation_level(
7122
/*=========================*/
7123
/* out: InnoDB isolation level */
7124
enum_tx_isolation iso) /* in: MySQL isolation level code */
7127
case ISO_REPEATABLE_READ: return(TRX_ISO_REPEATABLE_READ);
7128
case ISO_READ_COMMITTED: return(TRX_ISO_READ_COMMITTED);
7129
case ISO_SERIALIZABLE: return(TRX_ISO_SERIALIZABLE);
7130
case ISO_READ_UNCOMMITTED: return(TRX_ISO_READ_UNCOMMITTED);
7131
default: ut_a(0); return(0);
7135
/**********************************************************************
7136
As MySQL will execute an external lock for every new table it uses when it
7137
starts to process an SQL statement (an exception is when MySQL calls
7138
start_stmt for the handle) we can use this function to store the pointer to
7139
the THD in the handle. We will also use this function to communicate
7140
to InnoDB that a new SQL statement has started and that we must store a
7141
savepoint to our transaction handle, so that we are able to roll back
7142
the SQL statement in case of an error. */
7145
ha_innobase::external_lock(
7146
/*=======================*/
7148
THD* thd, /* in: handle to the user thread */
7149
int lock_type) /* in: lock type */
7153
DBUG_ENTER("ha_innobase::external_lock");
7154
DBUG_PRINT("enter",("lock_type: %d", lock_type));
7158
/* Statement based binlogging does not work in isolation level
7159
READ UNCOMMITTED and READ COMMITTED since the necessary
7160
locks cannot be taken. In this case, we print an
7161
informative error message and return with an error. */
7162
if (lock_type == F_WRLCK)
7164
ulong const binlog_format= thd_binlog_format(thd);
7165
ulong const tx_isolation = thd_tx_isolation(current_thd);
7166
if (tx_isolation <= ISO_READ_COMMITTED
7167
&& binlog_format == BINLOG_FORMAT_STMT
7168
&& thd_binlog_filter_ok(thd))
7171
my_snprintf(buf, sizeof(buf),
7172
"Transaction level '%s' in"
7173
" InnoDB is not safe for binlog mode '%s'",
7174
tx_isolation_names[tx_isolation],
7175
binlog_format_names[binlog_format]);
7176
my_error(ER_BINLOG_LOGGING_IMPOSSIBLE, MYF(0), buf);
7177
DBUG_RETURN(HA_ERR_LOGGING_IMPOSSIBLE);
7182
trx = prebuilt->trx;
7184
prebuilt->sql_stat_start = TRUE;
7185
prebuilt->hint_need_to_fetch_extra_cols = 0;
7187
reset_template(prebuilt);
7189
if (lock_type == F_WRLCK) {
7191
/* If this is a SELECT, then it is in UPDATE TABLE ...
7192
or SELECT ... FOR UPDATE */
7193
prebuilt->select_lock_type = LOCK_X;
7194
prebuilt->stored_select_lock_type = LOCK_X;
7197
if (lock_type != F_UNLCK) {
7198
/* MySQL is setting a new table lock */
7200
trx->detailed_error[0] = '\0';
7202
/* Set the MySQL flag to mark that there is an active
7204
if (trx->active_trans == 0) {
7206
innobase_register_trx_and_stmt(ht, thd);
7207
trx->active_trans = 1;
7208
} else if (trx->n_mysql_tables_in_use == 0) {
7209
innobase_register_stmt(ht, thd);
7212
if (trx->isolation_level == TRX_ISO_SERIALIZABLE
7213
&& prebuilt->select_lock_type == LOCK_NONE
7214
&& thd_test_options(thd,
7215
OPTION_NOT_AUTOCOMMIT | OPTION_BEGIN)) {
7217
/* To get serializable execution, we let InnoDB
7218
conceptually add 'LOCK IN SHARE MODE' to all SELECTs
7219
which otherwise would have been consistent reads. An
7220
exception is consistent reads in the AUTOCOMMIT=1 mode:
7221
we know that they are read-only transactions, and they
7222
can be serialized also if performed as consistent
7225
prebuilt->select_lock_type = LOCK_S;
7226
prebuilt->stored_select_lock_type = LOCK_S;
7229
/* Starting from 4.1.9, no InnoDB table lock is taken in LOCK
7230
TABLES if AUTOCOMMIT=1. It does not make much sense to acquire
7231
an InnoDB table lock if it is released immediately at the end
7232
of LOCK TABLES, and InnoDB's table locks in that case cause
7233
VERY easily deadlocks.
7235
We do not set InnoDB table locks if user has not explicitly
7236
requested a table lock. Note that thd_in_lock_tables(thd)
7237
can hold in some cases, e.g., at the start of a stored
7238
procedure call (SQLCOM_CALL). */
7240
if (prebuilt->select_lock_type != LOCK_NONE) {
7242
if (thd_sql_command(thd) == SQLCOM_LOCK_TABLES
7243
&& THDVAR(thd, table_locks)
7244
&& thd_test_options(thd, OPTION_NOT_AUTOCOMMIT)
7245
&& thd_in_lock_tables(thd)) {
7247
ulint error = row_lock_table_for_mysql(
7250
if (error != DB_SUCCESS) {
7251
error = convert_error_code_to_mysql(
7253
DBUG_RETURN((int) error);
7257
trx->mysql_n_tables_locked++;
7260
trx->n_mysql_tables_in_use++;
7261
prebuilt->mysql_has_locked = TRUE;
7266
/* MySQL is releasing a table lock */
7268
trx->n_mysql_tables_in_use--;
7269
prebuilt->mysql_has_locked = FALSE;
7271
/* Release a possible FIFO ticket and search latch. Since we
7272
may reserve the kernel mutex, we have to release the search
7273
system latch first to obey the latching order. */
7275
innobase_release_stat_resources(trx);
7277
/* If the MySQL lock count drops to zero we know that the current SQL
7278
statement has ended */
7280
if (trx->n_mysql_tables_in_use == 0) {
7282
trx->mysql_n_tables_locked = 0;
7283
prebuilt->used_in_HANDLER = FALSE;
7285
if (!thd_test_options(thd, OPTION_NOT_AUTOCOMMIT | OPTION_BEGIN)) {
7286
if (trx->active_trans != 0) {
7287
innobase_commit(ht, thd, TRUE);
7290
if (trx->isolation_level <= TRX_ISO_READ_COMMITTED
7291
&& trx->global_read_view) {
7293
/* At low transaction isolation levels we let
7294
each consistent read set its own snapshot */
7296
read_view_close_for_mysql(trx);
7304
/**********************************************************************
7305
With this function MySQL request a transactional lock to a table when
7306
user issued query LOCK TABLES..WHERE ENGINE = InnoDB. */
7309
ha_innobase::transactional_table_lock(
7310
/*==================================*/
7311
/* out: error code */
7312
THD* thd, /* in: handle to the user thread */
7313
int lock_type) /* in: lock type */
7317
DBUG_ENTER("ha_innobase::transactional_table_lock");
7318
DBUG_PRINT("enter",("lock_type: %d", lock_type));
7320
/* We do not know if MySQL can call this function before calling
7321
external_lock(). To be safe, update the thd of the current table
7326
if (prebuilt->table->ibd_file_missing && !thd_tablespace_op(thd)) {
7327
ut_print_timestamp(stderr);
7329
" InnoDB: MySQL is trying to use a table handle"
7330
" but the .ibd file for\n"
7331
"InnoDB: table %s does not exist.\n"
7332
"InnoDB: Have you deleted the .ibd file"
7333
" from the database directory under\n"
7334
"InnoDB: the MySQL datadir?"
7336
" http://dev.mysql.com/doc/refman/5.1/en/innodb-troubleshooting.html\n"
7337
"InnoDB: how you can resolve the problem.\n",
7338
prebuilt->table->name);
7339
DBUG_RETURN(HA_ERR_CRASHED);
7342
trx = prebuilt->trx;
7344
prebuilt->sql_stat_start = TRUE;
7345
prebuilt->hint_need_to_fetch_extra_cols = 0;
7347
reset_template(prebuilt);
7349
if (lock_type == F_WRLCK) {
7350
prebuilt->select_lock_type = LOCK_X;
7351
prebuilt->stored_select_lock_type = LOCK_X;
7352
} else if (lock_type == F_RDLCK) {
7353
prebuilt->select_lock_type = LOCK_S;
7354
prebuilt->stored_select_lock_type = LOCK_S;
7356
ut_print_timestamp(stderr);
7357
fprintf(stderr, " InnoDB error:\n"
7358
"MySQL is trying to set transactional table lock with corrupted lock type\n"
7359
"to table %s, lock type %d does not exist.\n",
7360
prebuilt->table->name, lock_type);
7361
DBUG_RETURN(HA_ERR_CRASHED);
7364
/* MySQL is setting a new transactional table lock */
7366
/* Set the MySQL flag to mark that there is an active transaction */
7367
if (trx->active_trans == 0) {
7369
innobase_register_trx_and_stmt(ht, thd);
7370
trx->active_trans = 1;
7373
if (THDVAR(thd, table_locks) && thd_in_lock_tables(thd)) {
7374
ulint error = DB_SUCCESS;
7376
error = row_lock_table_for_mysql(prebuilt, NULL, 0);
7378
if (error != DB_SUCCESS) {
7379
error = convert_error_code_to_mysql((int) error, thd);
7380
DBUG_RETURN((int) error);
7383
if (thd_test_options(thd, OPTION_NOT_AUTOCOMMIT | OPTION_BEGIN)) {
7385
/* Store the current undo_no of the transaction
7386
so that we know where to roll back if we have
7387
to roll back the next SQL statement */
7389
trx_mark_sql_stat_end(trx);
7396
/****************************************************************************
7397
Here we export InnoDB status variables to MySQL. */
7400
innodb_export_status()
7401
/*==================*/
7403
if (innodb_inited) {
7404
srv_export_innodb_status();
7410
/****************************************************************************
7411
Implements the SHOW INNODB STATUS command. Sends the output of the InnoDB
7412
Monitor to the client. */
7417
handlerton* hton, /* in: the innodb handlerton */
7418
THD* thd, /* in: the MySQL query thread of the caller */
7419
stat_print_fn *stat_print)
7422
static const char truncated_msg[] = "... truncated...\n";
7423
const long MAX_STATUS_SIZE = 64000;
7424
ulint trx_list_start = ULINT_UNDEFINED;
7425
ulint trx_list_end = ULINT_UNDEFINED;
7427
DBUG_ENTER("innodb_show_status");
7429
trx = check_trx_exists(thd);
7431
innobase_release_stat_resources(trx);
7433
/* We let the InnoDB Monitor to output at most MAX_STATUS_SIZE
7436
long flen, usable_len;
7439
mutex_enter_noninline(&srv_monitor_file_mutex);
7440
rewind(srv_monitor_file);
7441
srv_printf_innodb_monitor(srv_monitor_file, FALSE,
7442
&trx_list_start, &trx_list_end);
7443
flen = ftell(srv_monitor_file);
7444
os_file_set_eof(srv_monitor_file);
7450
if (flen > MAX_STATUS_SIZE) {
7451
usable_len = MAX_STATUS_SIZE;
7456
/* allocate buffer for the string, and
7457
read the contents of the temporary file */
7459
if (!(str = (char*) my_malloc(usable_len + 1, MYF(0)))) {
7460
mutex_exit_noninline(&srv_monitor_file_mutex);
7464
rewind(srv_monitor_file);
7465
if (flen < MAX_STATUS_SIZE) {
7466
/* Display the entire output. */
7467
flen = (long) fread(str, 1, flen, srv_monitor_file);
7468
} else if (trx_list_end < (ulint) flen
7469
&& trx_list_start < trx_list_end
7470
&& trx_list_start + (flen - trx_list_end)
7471
< MAX_STATUS_SIZE - sizeof truncated_msg - 1) {
7472
/* Omit the beginning of the list of active transactions. */
7473
long len = (long) fread(str, 1, trx_list_start, srv_monitor_file);
7474
memcpy(str + len, truncated_msg, sizeof truncated_msg - 1);
7475
len += sizeof truncated_msg - 1;
7476
usable_len = (MAX_STATUS_SIZE - 1) - len;
7477
fseek(srv_monitor_file, flen - usable_len, SEEK_SET);
7478
len += (long) fread(str + len, 1, usable_len, srv_monitor_file);
7481
/* Omit the end of the output. */
7482
flen = (long) fread(str, 1, MAX_STATUS_SIZE - 1, srv_monitor_file);
7485
mutex_exit_noninline(&srv_monitor_file_mutex);
7487
bool result = FALSE;
7489
if (stat_print(thd, innobase_hton_name, (uint) strlen(innobase_hton_name),
7490
STRING_WITH_LEN(""), str, flen)) {
7493
my_free(str, MYF(0));
7498
/****************************************************************************
7499
Implements the SHOW MUTEX STATUS command. . */
7502
innodb_mutex_show_status(
7503
/*=====================*/
7504
handlerton* hton, /* in: the innodb handlerton */
7505
THD* thd, /* in: the MySQL query thread of the
7507
stat_print_fn* stat_print)
7509
char buf1[IO_SIZE], buf2[IO_SIZE];
7512
ulint rw_lock_count= 0;
7513
ulint rw_lock_count_spin_loop= 0;
7514
ulint rw_lock_count_spin_rounds= 0;
7515
ulint rw_lock_count_os_wait= 0;
7516
ulint rw_lock_count_os_yield= 0;
7517
ulonglong rw_lock_wait_time= 0;
7518
#endif /* UNIV_DEBUG */
7519
uint hton_name_len= (uint) strlen(innobase_hton_name), buf1len, buf2len;
7520
DBUG_ENTER("innodb_mutex_show_status");
7522
mutex_enter_noninline(&mutex_list_mutex);
7524
mutex = UT_LIST_GET_FIRST(mutex_list);
7526
while (mutex != NULL) {
7528
if (mutex->mutex_type != 1) {
7529
if (mutex->count_using > 0) {
7530
buf1len= my_snprintf(buf1, sizeof(buf1),
7532
mutex->cmutex_name, mutex->cfile_name);
7533
buf2len= my_snprintf(buf2, sizeof(buf2),
7534
"count=%lu, spin_waits=%lu,"
7535
" spin_rounds=%lu, "
7536
"os_waits=%lu, os_yields=%lu,"
7537
" os_wait_times=%lu",
7539
mutex->count_spin_loop,
7540
mutex->count_spin_rounds,
7541
mutex->count_os_wait,
7542
mutex->count_os_yield,
7543
(ulong) (mutex->lspent_time/1000));
7545
if (stat_print(thd, innobase_hton_name,
7546
hton_name_len, buf1, buf1len,
7548
mutex_exit_noninline(
7555
rw_lock_count += mutex->count_using;
7556
rw_lock_count_spin_loop += mutex->count_spin_loop;
7557
rw_lock_count_spin_rounds += mutex->count_spin_rounds;
7558
rw_lock_count_os_wait += mutex->count_os_wait;
7559
rw_lock_count_os_yield += mutex->count_os_yield;
7560
rw_lock_wait_time += mutex->lspent_time;
7562
#else /* UNIV_DEBUG */
7563
buf1len= (uint) my_snprintf(buf1, sizeof(buf1), "%s:%lu",
7564
mutex->cfile_name, (ulong) mutex->cline);
7565
buf2len= (uint) my_snprintf(buf2, sizeof(buf2), "os_waits=%lu",
7566
mutex->count_os_wait);
7568
if (stat_print(thd, innobase_hton_name,
7569
hton_name_len, buf1, buf1len,
7571
mutex_exit_noninline(&mutex_list_mutex);
7574
#endif /* UNIV_DEBUG */
7576
mutex = UT_LIST_GET_NEXT(list, mutex);
7579
mutex_exit_noninline(&mutex_list_mutex);
7582
buf2len= my_snprintf(buf2, sizeof(buf2),
7583
"count=%lu, spin_waits=%lu, spin_rounds=%lu, "
7584
"os_waits=%lu, os_yields=%lu, os_wait_times=%lu",
7585
rw_lock_count, rw_lock_count_spin_loop,
7586
rw_lock_count_spin_rounds,
7587
rw_lock_count_os_wait, rw_lock_count_os_yield,
7588
(ulong) (rw_lock_wait_time/1000));
7590
if (stat_print(thd, innobase_hton_name, hton_name_len,
7591
STRING_WITH_LEN("rw_lock_mutexes"), buf2, buf2len)) {
7594
#endif /* UNIV_DEBUG */
7600
bool innobase_show_status(handlerton *hton, THD* thd,
7601
stat_print_fn* stat_print,
7602
enum ha_stat_type stat_type)
7604
switch (stat_type) {
7605
case HA_ENGINE_STATUS:
7606
return innodb_show_status(hton, thd, stat_print);
7607
case HA_ENGINE_MUTEX:
7608
return innodb_mutex_show_status(hton, thd, stat_print);
7615
/****************************************************************************
7616
Handling the shared INNOBASE_SHARE structure that is needed to provide table
7618
****************************************************************************/
7620
static uchar* innobase_get_key(INNOBASE_SHARE* share, size_t *length,
7621
my_bool not_used __attribute__((unused)))
7623
*length=share->table_name_length;
7625
return (uchar*) share->table_name;
7628
static INNOBASE_SHARE* get_share(const char* table_name)
7630
INNOBASE_SHARE *share;
7631
pthread_mutex_lock(&innobase_share_mutex);
7632
uint length=(uint) strlen(table_name);
7634
if (!(share=(INNOBASE_SHARE*) hash_search(&innobase_open_tables,
7635
(uchar*) table_name,
7638
share = (INNOBASE_SHARE *) my_malloc(sizeof(*share)+length+1,
7639
MYF(MY_FAE | MY_ZEROFILL));
7641
share->table_name_length=length;
7642
share->table_name=(char*) (share+1);
7643
strmov(share->table_name,table_name);
7645
if (my_hash_insert(&innobase_open_tables,
7647
pthread_mutex_unlock(&innobase_share_mutex);
7653
thr_lock_init(&share->lock);
7654
pthread_mutex_init(&share->mutex,MY_MUTEX_INIT_FAST);
7658
pthread_mutex_unlock(&innobase_share_mutex);
7663
static void free_share(INNOBASE_SHARE* share)
7665
pthread_mutex_lock(&innobase_share_mutex);
7667
if (!--share->use_count) {
7668
hash_delete(&innobase_open_tables, (uchar*) share);
7669
thr_lock_delete(&share->lock);
7670
pthread_mutex_destroy(&share->mutex);
7671
my_free(share, MYF(0));
7674
pthread_mutex_unlock(&innobase_share_mutex);
7677
/*********************************************************************
7678
Converts a MySQL table lock stored in the 'lock' field of the handle to
7679
a proper type before storing pointer to the lock into an array of pointers.
7680
MySQL also calls this if it wants to reset some table locks to a not-locked
7681
state during the processing of an SQL query. An example is that during a
7682
SELECT the read lock is released early on the 'const' tables where we only
7683
fetch one row. MySQL does not call this when it releases all locks at the
7684
end of an SQL statement. */
7687
ha_innobase::store_lock(
7688
/*====================*/
7689
/* out: pointer to the next
7690
element in the 'to' array */
7691
THD* thd, /* in: user thread handle */
7692
THR_LOCK_DATA** to, /* in: pointer to an array
7693
of pointers to lock structs;
7694
pointer to the 'lock' field
7695
of current handle is stored
7696
next to this array */
7697
enum thr_lock_type lock_type) /* in: lock type to store in
7698
'lock'; this may also be
7703
/* Note that trx in this function is NOT necessarily prebuilt->trx
7704
because we call update_thd() later, in ::external_lock()! Failure to
7705
understand this caused a serious memory corruption bug in 5.1.11. */
7707
trx = check_trx_exists(thd);
7709
/* NOTE: MySQL can call this function with lock 'type' TL_IGNORE!
7710
Be careful to ignore TL_IGNORE if we are going to do something with
7711
only 'real' locks! */
7713
/* If no MySQL table is in use, we need to set the isolation level
7714
of the transaction. */
7716
if (lock_type != TL_IGNORE
7717
&& trx->n_mysql_tables_in_use == 0) {
7718
trx->isolation_level = innobase_map_isolation_level(
7719
(enum_tx_isolation) thd_tx_isolation(thd));
7721
if (trx->isolation_level <= TRX_ISO_READ_COMMITTED
7722
&& trx->global_read_view) {
7724
/* At low transaction isolation levels we let
7725
each consistent read set its own snapshot */
7727
read_view_close_for_mysql(trx);
7731
DBUG_ASSERT(thd == current_thd);
7732
const bool in_lock_tables = thd_in_lock_tables(thd);
7733
const uint sql_command = thd_sql_command(thd);
7735
if (sql_command == SQLCOM_DROP_TABLE) {
7737
/* MySQL calls this function in DROP TABLE though this table
7738
handle may belong to another thd that is running a query. Let
7739
us in that case skip any changes to the prebuilt struct. */
7741
} else if ((lock_type == TL_READ && in_lock_tables)
7742
|| (lock_type == TL_READ_HIGH_PRIORITY && in_lock_tables)
7743
|| lock_type == TL_READ_WITH_SHARED_LOCKS
7744
|| lock_type == TL_READ_NO_INSERT
7745
|| (lock_type != TL_IGNORE
7746
&& sql_command != SQLCOM_SELECT)) {
7748
/* The OR cases above are in this order:
7749
1) MySQL is doing LOCK TABLES ... READ LOCAL, or we
7750
are processing a stored procedure or function, or
7751
2) (we do not know when TL_READ_HIGH_PRIORITY is used), or
7752
3) this is a SELECT ... IN SHARE MODE, or
7753
4) we are doing a complex SQL statement like
7754
INSERT INTO ... SELECT ... and the logical logging (MySQL
7755
binlog) requires the use of a locking read, or
7756
MySQL is doing LOCK TABLES ... READ.
7757
5) we let InnoDB do locking reads for all SQL statements that
7758
are not simple SELECTs; note that select_lock_type in this
7759
case may get strengthened in ::external_lock() to LOCK_X.
7760
Note that we MUST use a locking read in all data modifying
7761
SQL statements, because otherwise the execution would not be
7762
serializable, and also the results from the update could be
7763
unexpected if an obsolete consistent read view would be
7766
ulint isolation_level;
7768
isolation_level = trx->isolation_level;
7770
if ((srv_locks_unsafe_for_binlog
7771
|| isolation_level == TRX_ISO_READ_COMMITTED)
7772
&& isolation_level != TRX_ISO_SERIALIZABLE
7773
&& (lock_type == TL_READ || lock_type == TL_READ_NO_INSERT)
7774
&& (sql_command == SQLCOM_INSERT_SELECT
7775
|| sql_command == SQLCOM_UPDATE
7776
|| sql_command == SQLCOM_CREATE_TABLE)) {
7778
/* If we either have innobase_locks_unsafe_for_binlog
7779
option set or this session is using READ COMMITTED
7780
isolation level and isolation level of the transaction
7781
is not set to serializable and MySQL is doing
7782
INSERT INTO...SELECT or UPDATE ... = (SELECT ...) or
7783
CREATE ... SELECT... without FOR UPDATE or
7784
IN SHARE MODE in select, then we use consistent
7787
prebuilt->select_lock_type = LOCK_NONE;
7788
prebuilt->stored_select_lock_type = LOCK_NONE;
7789
} else if (sql_command == SQLCOM_CHECKSUM) {
7790
/* Use consistent read for checksum table */
7792
prebuilt->select_lock_type = LOCK_NONE;
7793
prebuilt->stored_select_lock_type = LOCK_NONE;
7795
prebuilt->select_lock_type = LOCK_S;
7796
prebuilt->stored_select_lock_type = LOCK_S;
7799
} else if (lock_type != TL_IGNORE) {
7801
/* We set possible LOCK_X value in external_lock, not yet
7802
here even if this would be SELECT ... FOR UPDATE */
7804
prebuilt->select_lock_type = LOCK_NONE;
7805
prebuilt->stored_select_lock_type = LOCK_NONE;
7808
if (lock_type != TL_IGNORE && lock.type == TL_UNLOCK) {
7810
/* Starting from 5.0.7, we weaken also the table locks
7811
set at the start of a MySQL stored procedure call, just like
7812
we weaken the locks set at the start of an SQL statement.
7813
MySQL does set in_lock_tables TRUE there, but in reality
7814
we do not need table locks to make the execution of a
7815
single transaction stored procedure call deterministic
7816
(if it does not use a consistent read). */
7818
if (lock_type == TL_READ
7819
&& sql_command == SQLCOM_LOCK_TABLES) {
7820
/* We come here if MySQL is processing LOCK TABLES
7821
... READ LOCAL. MyISAM under that table lock type
7822
reads the table as it was at the time the lock was
7823
granted (new inserts are allowed, but not seen by the
7824
reader). To get a similar effect on an InnoDB table,
7825
we must use LOCK TABLES ... READ. We convert the lock
7826
type here, so that for InnoDB, READ LOCAL is
7827
equivalent to READ. This will change the InnoDB
7828
behavior in mysqldump, so that dumps of InnoDB tables
7829
are consistent with dumps of MyISAM tables. */
7831
lock_type = TL_READ_NO_INSERT;
7834
/* If we are not doing a LOCK TABLE, DISCARD/IMPORT
7835
TABLESPACE or TRUNCATE TABLE then allow multiple
7836
writers. Note that ALTER TABLE uses a TL_WRITE_ALLOW_READ
7837
< TL_WRITE_CONCURRENT_INSERT.
7839
We especially allow multiple writers if MySQL is at the
7840
start of a stored procedure call (SQLCOM_CALL) or a
7841
stored function call (MySQL does have in_lock_tables
7844
if ((lock_type >= TL_WRITE_CONCURRENT_INSERT
7845
&& lock_type <= TL_WRITE)
7847
&& sql_command == SQLCOM_LOCK_TABLES)
7848
&& !thd_tablespace_op(thd)
7849
&& sql_command != SQLCOM_TRUNCATE
7850
&& sql_command != SQLCOM_OPTIMIZE
7851
&& sql_command != SQLCOM_CREATE_TABLE) {
7853
lock_type = TL_WRITE_ALLOW_WRITE;
7856
/* In queries of type INSERT INTO t1 SELECT ... FROM t2 ...
7857
MySQL would use the lock TL_READ_NO_INSERT on t2, and that
7858
would conflict with TL_WRITE_ALLOW_WRITE, blocking all inserts
7859
to t2. Convert the lock to a normal read lock to allow
7860
concurrent inserts to t2.
7862
We especially allow concurrent inserts if MySQL is at the
7863
start of a stored procedure call (SQLCOM_CALL)
7864
(MySQL does have thd_in_lock_tables() TRUE there). */
7866
if (lock_type == TL_READ_NO_INSERT
7867
&& sql_command != SQLCOM_LOCK_TABLES) {
7869
lock_type = TL_READ;
7872
lock.type = lock_type;
7880
/*******************************************************************************
7881
Read the next autoinc value. Acquire the relevant locks before reading
7882
the AUTOINC value. If SUCCESS then the table AUTOINC mutex will be locked
7883
on return and all relevant locks acquired. */
7886
ha_innobase::innobase_get_autoinc(
7887
/*==============================*/
7888
/* out: DB_SUCCESS or error code */
7889
ulonglong* value) /* out: autoinc value */
7893
prebuilt->autoinc_error = innobase_lock_autoinc();
7895
if (prebuilt->autoinc_error == DB_SUCCESS) {
7897
/* Determine the first value of the interval */
7898
*value = dict_table_autoinc_read(prebuilt->table);
7900
/* It should have been initialized during open. */
7902
prebuilt->autoinc_error = DB_UNSUPPORTED;
7903
dict_table_autoinc_unlock(prebuilt->table);
7907
return(ulong(prebuilt->autoinc_error));
7910
/***********************************************************************
7911
This function reads the global auto-inc counter. It doesn't use the
7912
AUTOINC lock even if the lock mode is set to TRADITIONAL. */
7915
ha_innobase::innobase_peek_autoinc()
7916
/*================================*/
7917
/* out: the autoinc value */
7920
dict_table_t* innodb_table;
7922
ut_a(prebuilt != NULL);
7923
ut_a(prebuilt->table != NULL);
7925
innodb_table = prebuilt->table;
7927
dict_table_autoinc_lock(innodb_table);
7929
auto_inc = dict_table_autoinc_read(innodb_table);
7933
dict_table_autoinc_unlock(innodb_table);
7938
/*******************************************************************************
7939
This function initializes the auto-inc counter if it has not been
7940
initialized yet. This function does not change the value of the auto-inc
7941
counter if it already has been initialized. Returns the value of the
7942
auto-inc counter in *first_value, and ULONGLONG_MAX in *nb_reserved_values (as
7943
we have a table-level lock). offset, increment, nb_desired_values are ignored.
7944
*first_value is set to -1 if error (deadlock or lock wait timeout) */
7947
ha_innobase::get_auto_increment(
7948
/*============================*/
7949
ulonglong offset, /* in: */
7950
ulonglong increment, /* in: table autoinc increment */
7951
ulonglong nb_desired_values, /* in: number of values reqd */
7952
ulonglong *first_value, /* out: the autoinc value */
7953
ulonglong *nb_reserved_values) /* out: count of reserved values */
7957
ulonglong autoinc = 0;
7959
/* Prepare prebuilt->trx in the table handle */
7960
update_thd(ha_thd());
7962
error = innobase_get_autoinc(&autoinc);
7964
if (error != DB_SUCCESS) {
7965
*first_value = (~(ulonglong) 0);
7969
/* This is a hack, since nb_desired_values seems to be accurate only
7970
for the first call to get_auto_increment() for multi-row INSERT and
7971
meaningless for other statements e.g, LOAD etc. Subsequent calls to
7972
this method for the same statement results in different values which
7973
don't make sense. Therefore we store the value the first time we are
7974
called and count down from that as rows are written (see write_row()).
7977
trx = prebuilt->trx;
7979
/* Note: We can't rely on *first_value since some MySQL engines,
7980
in particular the partition engine, don't initialize it to 0 when
7981
invoking this method. So we are not sure if it's guaranteed to
7984
/* We need the upper limit of the col type to check for
7985
whether we update the table autoinc counter or not. */
7986
ulonglong col_max_value = innobase_get_int_col_max_value(
7987
table->next_number_field);
7989
/* Called for the first time ? */
7990
if (trx->n_autoinc_rows == 0) {
7992
trx->n_autoinc_rows = (ulint) nb_desired_values;
7994
/* It's possible for nb_desired_values to be 0:
7995
e.g., INSERT INTO T1(C) SELECT C FROM T2; */
7996
if (nb_desired_values == 0) {
7998
trx->n_autoinc_rows = 1;
8001
set_if_bigger(*first_value, autoinc);
8002
/* Not in the middle of a mult-row INSERT. */
8003
} else if (prebuilt->autoinc_last_value == 0) {
8004
set_if_bigger(*first_value, autoinc);
8005
/* Check for -ve values. */
8006
} else if (*first_value > col_max_value && trx->n_autoinc_rows > 0) {
8007
/* Set to next logical value. */
8008
ut_a(autoinc > trx->n_autoinc_rows);
8009
*first_value = (autoinc - trx->n_autoinc_rows) - 1;
8012
*nb_reserved_values = trx->n_autoinc_rows;
8014
/* With old style AUTOINC locking we only update the table's
8015
AUTOINC counter after attempting to insert the row. */
8016
if (innobase_autoinc_lock_mode != AUTOINC_OLD_STYLE_LOCKING) {
8019
ulonglong next_value;
8021
current = *first_value > col_max_value ? autoinc : *first_value;
8022
need = *nb_reserved_values * increment;
8024
/* Compute the last value in the interval */
8025
next_value = innobase_next_autoinc(
8026
current, need, offset, col_max_value);
8028
prebuilt->autoinc_last_value = next_value;
8030
if (prebuilt->autoinc_last_value < *first_value) {
8031
*first_value = (~(ulonglong) 0);
8033
/* Update the table autoinc variable */
8034
dict_table_autoinc_update_if_greater(
8035
prebuilt->table, prebuilt->autoinc_last_value);
8038
/* This will force write_row() into attempting an update
8039
of the table's AUTOINC counter. */
8040
prebuilt->autoinc_last_value = 0;
8043
/* The increment to be used to increase the AUTOINC value, we use
8044
this in write_row() and update_row() to increase the autoinc counter
8045
for columns that are filled by the user. We need the offset and
8047
prebuilt->autoinc_offset = offset;
8048
prebuilt->autoinc_increment = increment;
8050
dict_table_autoinc_unlock(prebuilt->table);
8053
/* See comment in handler.h */
8055
ha_innobase::reset_auto_increment(
8056
/*==============================*/
8057
ulonglong value) /* in: new value for table autoinc */
8059
DBUG_ENTER("ha_innobase::reset_auto_increment");
8063
update_thd(ha_thd());
8065
error = row_lock_table_autoinc_for_mysql(prebuilt);
8067
if (error != DB_SUCCESS) {
8068
error = convert_error_code_to_mysql(error, user_thd);
8073
/* The next value can never be 0. */
8078
innobase_reset_autoinc(value);
8083
/* See comment in handler.cc */
8085
ha_innobase::get_error_message(int error, String *buf)
8087
trx_t* trx = check_trx_exists(ha_thd());
8089
buf->copy(trx->detailed_error, (uint) strlen(trx->detailed_error),
8090
system_charset_info);
8095
/***********************************************************************
8096
Compares two 'refs'. A 'ref' is the (internal) primary key value of the row.
8097
If there is no explicitly declared non-null unique key or a primary key, then
8098
InnoDB internally uses the row id as the primary key. */
8101
ha_innobase::cmp_ref(
8102
/*=================*/
8103
/* out: < 0 if ref1 < ref2, 0 if equal, else
8105
const uchar* ref1, /* in: an (internal) primary key value in the
8106
MySQL key value format */
8107
const uchar* ref2) /* in: an (internal) primary key value in the
8108
MySQL key value format */
8110
enum_field_types mysql_type;
8112
KEY_PART_INFO* key_part;
8113
KEY_PART_INFO* key_part_end;
8118
if (prebuilt->clust_index_was_generated) {
8119
/* The 'ref' is an InnoDB row id */
8121
return(memcmp(ref1, ref2, DATA_ROW_ID_LEN));
8124
/* Do a type-aware comparison of primary key fields. PK fields
8125
are always NOT NULL, so no checks for NULL are performed. */
8127
key_part = table->key_info[table->s->primary_key].key_part;
8129
key_part_end = key_part
8130
+ table->key_info[table->s->primary_key].key_parts;
8132
for (; key_part != key_part_end; ++key_part) {
8133
field = key_part->field;
8134
mysql_type = field->type();
8136
if (mysql_type == MYSQL_TYPE_TINY_BLOB
8137
|| mysql_type == MYSQL_TYPE_MEDIUM_BLOB
8138
|| mysql_type == MYSQL_TYPE_BLOB
8139
|| mysql_type == MYSQL_TYPE_LONG_BLOB) {
8141
/* In the MySQL key value format, a column prefix of
8142
a BLOB is preceded by a 2-byte length field */
8144
len1 = innobase_read_from_2_little_endian(ref1);
8145
len2 = innobase_read_from_2_little_endian(ref2);
8149
result = ((Field_blob*)field)->cmp( ref1, len1,
8152
result = field->key_cmp(ref1, ref2);
8160
ref1 += key_part->store_length;
8161
ref2 += key_part->store_length;
8167
/***********************************************************************
8168
Ask InnoDB if a query to a table can be cached. */
8171
ha_innobase::register_query_cache_table(
8172
/*====================================*/
8173
/* out: TRUE if query caching
8174
of the table is permitted */
8175
THD* thd, /* in: user thread handle */
8176
char* table_key, /* in: concatenation of database name,
8177
the null character '\0',
8178
and the table name */
8179
uint key_length, /* in: length of the full name, i.e.
8180
len(dbname) + len(tablename) + 1 */
8182
call_back, /* out: pointer to function for
8183
checking if query caching
8185
ulonglong *engine_data) /* in/out: data to call_back */
8187
*call_back = innobase_query_caching_of_table_permitted;
8189
return(innobase_query_caching_of_table_permitted(thd, table_key,
8195
ha_innobase::get_mysql_bin_log_name()
8197
return(trx_sys_mysql_bin_log_name);
8201
ha_innobase::get_mysql_bin_log_pos()
8203
/* trx... is ib_longlong, which is a typedef for a 64-bit integer
8204
(__int64 or longlong) so it's ok to cast it to ulonglong. */
8206
return(trx_sys_mysql_bin_log_pos);
8209
/**********************************************************************
8210
This function is used to find the storage length in bytes of the first n
8211
characters for prefix indexes using a multibyte character set. The function
8212
finds charset information and returns length of prefix_len characters in the
8213
index field in bytes.
8215
NOTE: the prototype of this function is copied to data0type.c! If you change
8216
this function, you MUST change also data0type.c! */
8219
innobase_get_at_most_n_mbchars(
8220
/*===========================*/
8221
/* out: number of bytes occupied by the first
8223
ulint charset_id, /* in: character set id */
8224
ulint prefix_len, /* in: prefix length in bytes of the index
8225
(this has to be divided by mbmaxlen to get the
8226
number of CHARACTERS n in the prefix) */
8227
ulint data_len, /* in: length of the string in bytes */
8228
const char* str) /* in: character string */
8230
ulint char_length; /* character length in bytes */
8231
ulint n_chars; /* number of characters in prefix */
8232
CHARSET_INFO* charset; /* charset used in the field */
8234
charset = get_charset((uint) charset_id, MYF(MY_WME));
8237
ut_ad(charset->mbmaxlen);
8239
/* Calculate how many characters at most the prefix index contains */
8241
n_chars = prefix_len / charset->mbmaxlen;
8243
/* If the charset is multi-byte, then we must find the length of the
8244
first at most n chars in the string. If the string contains less
8245
characters than n, then we return the length to the end of the last
8248
if (charset->mbmaxlen > 1) {
8249
/* my_charpos() returns the byte length of the first n_chars
8250
characters, or a value bigger than the length of str, if
8251
there were not enough full characters in str.
8253
Why does the code below work:
8254
Suppose that we are looking for n UTF-8 characters.
8256
1) If the string is long enough, then the prefix contains at
8257
least n complete UTF-8 characters + maybe some extra
8258
characters + an incomplete UTF-8 character. No problem in
8259
this case. The function returns the pointer to the
8260
end of the nth character.
8262
2) If the string is not long enough, then the string contains
8263
the complete value of a column, that is, only complete UTF-8
8264
characters, and we can store in the column prefix index the
8267
char_length = my_charpos(charset, str,
8268
str + data_len, (int) n_chars);
8269
if (char_length > data_len) {
8270
char_length = data_len;
8273
if (data_len < prefix_len) {
8274
char_length = data_len;
8276
char_length = prefix_len;
8280
return(char_length);
8283
/***********************************************************************
8284
This function is used to prepare X/Open XA distributed transaction */
8287
innobase_xa_prepare(
8288
/*================*/
8289
/* out: 0 or error number */
8291
THD* thd, /* in: handle to the MySQL thread of the user
8292
whose XA transaction should be prepared */
8293
bool all) /* in: TRUE - commit transaction
8294
FALSE - the current SQL statement ended */
8297
trx_t* trx = check_trx_exists(thd);
8299
if (thd_sql_command(thd) != SQLCOM_XA_PREPARE &&
8300
(all || !thd_test_options(thd, OPTION_NOT_AUTOCOMMIT | OPTION_BEGIN)))
8303
/* For ibbackup to work the order of transactions in binlog
8304
and InnoDB must be the same. Consider the situation
8306
thread1> prepare; write to binlog; ...
8308
thread2> prepare; write to binlog; commit
8311
To ensure this will not happen we're taking the mutex on
8312
prepare, and releasing it on commit.
8314
Note: only do it for normal commits, done via ha_commit_trans.
8315
If 2pc protocol is executed by external transaction
8316
coordinator, it will be just a regular MySQL client
8317
executing XA PREPARE and XA COMMIT commands.
8318
In this case we cannot know how many minutes or hours
8319
will be between XA PREPARE and XA COMMIT, and we don't want
8320
to block for undefined period of time. */
8321
pthread_mutex_lock(&prepare_commit_mutex);
8322
trx->active_trans = 2;
8325
if (!THDVAR(thd, support_xa)) {
8330
thd_get_xid(thd, (MYSQL_XID*) &trx->xid);
8332
/* Release a possible FIFO ticket and search latch. Since we will
8333
reserve the kernel mutex, we have to release the search system latch
8334
first to obey the latching order. */
8336
innobase_release_stat_resources(trx);
8338
if (trx->active_trans == 0 && trx->conc_state != TRX_NOT_STARTED) {
8340
sql_print_error("trx->active_trans == 0, but trx->conc_state != "
8345
|| (!thd_test_options(thd, OPTION_NOT_AUTOCOMMIT | OPTION_BEGIN))) {
8347
/* We were instructed to prepare the whole transaction, or
8348
this is an SQL statement end and autocommit is on */
8350
ut_ad(trx->active_trans);
8352
error = (int) trx_prepare_for_mysql(trx);
8354
/* We just mark the SQL statement ended and do not do a
8355
transaction prepare */
8357
/* If we had reserved the auto-inc lock for some
8358
table in this SQL statement we release it now */
8360
row_unlock_table_autoinc_for_mysql(trx);
8362
/* Store the current undo_no of the transaction so that we
8363
know where to roll back if we have to roll back the next
8366
trx_mark_sql_stat_end(trx);
8369
/* Tell the InnoDB server that there might be work for utility
8372
srv_active_wake_master_thread();
8377
/***********************************************************************
8378
This function is used to recover X/Open XA distributed transactions */
8381
innobase_xa_recover(
8382
/*================*/
8383
/* out: number of prepared transactions
8384
stored in xid_list */
8386
XID* xid_list, /* in/out: prepared transactions */
8387
uint len) /* in: number of slots in xid_list */
8389
if (len == 0 || xid_list == NULL) {
8394
return(trx_recover_for_mysql(xid_list, len));
8397
/***********************************************************************
8398
This function is used to commit one X/Open XA distributed transaction
8399
which is in the prepared state */
8402
innobase_commit_by_xid(
8403
/*===================*/
8404
/* out: 0 or error number */
8406
XID* xid) /* in: X/Open XA transaction identification */
8410
trx = trx_get_trx_by_xid(xid);
8413
innobase_commit_low(trx);
8421
/***********************************************************************
8422
This function is used to rollback one X/Open XA distributed transaction
8423
which is in the prepared state */
8426
innobase_rollback_by_xid(
8427
/*=====================*/
8428
/* out: 0 or error number */
8430
XID *xid) /* in: X/Open XA transaction identification */
8434
trx = trx_get_trx_by_xid(xid);
8437
return(innobase_rollback_trx(trx));
8443
/***********************************************************************
8444
Create a consistent view for a cursor based on current transaction
8445
which is created if the corresponding MySQL thread still lacks one.
8446
This consistent view is then used inside of MySQL when accessing records
8450
innobase_create_cursor_view(
8451
/*========================*/
8452
/* out: pointer to cursor view or NULL */
8453
handlerton *hton, /* in: innobase hton */
8454
THD* thd) /* in: user thread handle */
8456
return(read_cursor_view_create_for_mysql(check_trx_exists(thd)));
8459
/***********************************************************************
8460
Close the given consistent cursor view of a transaction and restore
8461
global read view to a transaction read view. Transaction is created if the
8462
corresponding MySQL thread still lacks one. */
8465
innobase_close_cursor_view(
8466
/*=======================*/
8468
THD* thd, /* in: user thread handle */
8469
void* curview)/* in: Consistent read view to be closed */
8471
read_cursor_view_close_for_mysql(check_trx_exists(thd),
8472
(cursor_view_t*) curview);
8475
/***********************************************************************
8476
Set the given consistent cursor view to a transaction which is created
8477
if the corresponding MySQL thread still lacks one. If the given
8478
consistent cursor view is NULL global read view of a transaction is
8479
restored to a transaction read view. */
8482
innobase_set_cursor_view(
8483
/*=====================*/
8485
THD* thd, /* in: user thread handle */
8486
void* curview)/* in: Consistent cursor view to be set */
8488
read_cursor_set_for_mysql(check_trx_exists(thd),
8489
(cursor_view_t*) curview);
8493
/***********************************************************************
8494
Check whether any of the given columns is being renamed in the table. */
8497
column_is_being_renamed(
8498
/*====================*/
8499
/* out: true if any of col_names is
8500
being renamed in table */
8501
TABLE* table, /* in: MySQL table */
8502
uint n_cols, /* in: number of columns */
8503
const char** col_names) /* in: names of the columns */
8508
const char* col_name;
8510
for (j = 0; j < n_cols; j++) {
8511
col_name = col_names[j];
8512
for (k = 0; k < table->s->fields; k++) {
8513
field = table->field[k];
8514
if ((field->flags & FIELD_IS_RENAMED)
8515
&& innobase_strcasecmp(field->field_name,
8525
/***********************************************************************
8526
Check whether a column in table "table" is being renamed and if this column
8527
is part of a foreign key, either part of another table, referencing this
8528
table or part of this table, referencing another table. */
8531
foreign_key_column_is_being_renamed(
8532
/*================================*/
8533
/* out: true if a column that
8534
participates in a foreign key definition
8536
row_prebuilt_t* prebuilt, /* in: InnoDB prebuilt struct */
8537
TABLE* table) /* in: MySQL table */
8539
dict_foreign_t* foreign;
8541
/* check whether there are foreign keys at all */
8542
if (UT_LIST_GET_LEN(prebuilt->table->foreign_list) == 0
8543
&& UT_LIST_GET_LEN(prebuilt->table->referenced_list) == 0) {
8544
/* no foreign keys involved with prebuilt->table */
8549
row_mysql_lock_data_dictionary(prebuilt->trx);
8551
/* Check whether any column in the foreign key constraints which refer
8552
to this table is being renamed. */
8553
for (foreign = UT_LIST_GET_FIRST(prebuilt->table->referenced_list);
8555
foreign = UT_LIST_GET_NEXT(referenced_list, foreign)) {
8557
if (column_is_being_renamed(table, foreign->n_fields,
8558
foreign->referenced_col_names)) {
8560
row_mysql_unlock_data_dictionary(prebuilt->trx);
8565
/* Check whether any column in the foreign key constraints in the
8566
table is being renamed. */
8567
for (foreign = UT_LIST_GET_FIRST(prebuilt->table->foreign_list);
8569
foreign = UT_LIST_GET_NEXT(foreign_list, foreign)) {
8571
if (column_is_being_renamed(table, foreign->n_fields,
8572
foreign->foreign_col_names)) {
8574
row_mysql_unlock_data_dictionary(prebuilt->trx);
8579
row_mysql_unlock_data_dictionary(prebuilt->trx);
8584
bool ha_innobase::check_if_incompatible_data(
8585
HA_CREATE_INFO* info,
8588
if (table_changes != IS_EQUAL_YES) {
8590
return COMPATIBLE_DATA_NO;
8593
/* Check that auto_increment value was not changed */
8594
if ((info->used_fields & HA_CREATE_USED_AUTO) &&
8595
info->auto_increment_value != 0) {
8597
return COMPATIBLE_DATA_NO;
8600
/* Check if a column participating in a foreign key is being renamed.
8601
There is no mechanism for updating InnoDB foreign key definitions. */
8602
if (foreign_key_column_is_being_renamed(prebuilt, table)) {
8604
return COMPATIBLE_DATA_NO;
8607
/* Check that row format didn't change */
8608
if ((info->used_fields & HA_CREATE_USED_ROW_FORMAT) &&
8609
get_row_type() != info->row_type) {
8611
return COMPATIBLE_DATA_NO;
8614
return COMPATIBLE_DATA_YES;
8617
static int show_innodb_vars(THD *thd, SHOW_VAR *var, char *buff)
8619
innodb_export_status();
8620
var->type= SHOW_ARRAY;
8621
var->value= (char *) &innodb_status_variables;
8625
/***********************************************************************
8626
This function checks each index name for a table against reserved
8627
system default primary index name 'GEN_CLUST_INDEX'. If a name matches,
8628
this function pushes an error message to the client, and returns true. */
8631
innobase_index_name_is_reserved(
8632
/*============================*/
8633
/* out: true if an index name
8634
matches the reserved name */
8635
const trx_t* trx, /* in: InnoDB transaction handle */
8636
const TABLE* form, /* in: information on table
8637
columns and indexes */
8638
const char* norm_name) /* in: table name */
8641
uint key_num; /* index number */
8643
for (key_num = 0; key_num < form->s->keys; key_num++) {
8644
key = form->key_info + key_num;
8646
if (innobase_strcasecmp(key->name,
8647
innobase_index_reserve_name) == 0) {
8648
/* Push warning to mysql */
8649
push_warning_printf((THD*) trx->mysql_thd,
8650
MYSQL_ERROR::WARN_LEVEL_WARN,
8651
ER_CANT_CREATE_TABLE,
8652
"Cannot Create Index with name "
8653
"'%s'. The name is reserved "
8654
"for the system default primary "
8656
innobase_index_reserve_name);
8665
static SHOW_VAR innodb_status_variables_export[]= {
8666
{"Innodb", (char*) &show_innodb_vars, SHOW_FUNC},
8667
{NullS, NullS, SHOW_LONG}
8670
static struct st_mysql_storage_engine innobase_storage_engine=
8671
{ MYSQL_HANDLERTON_INTERFACE_VERSION };
8673
/* plugin options */
8674
static MYSQL_SYSVAR_BOOL(checksums, innobase_use_checksums,
8675
PLUGIN_VAR_NOCMDARG | PLUGIN_VAR_READONLY,
8676
"Enable InnoDB checksums validation (enabled by default). "
8677
"Disable with --skip-innodb-checksums.",
8680
static MYSQL_SYSVAR_STR(data_home_dir, innobase_data_home_dir,
8681
PLUGIN_VAR_READONLY,
8682
"The common part for InnoDB table spaces.",
8685
static MYSQL_SYSVAR_BOOL(doublewrite, innobase_use_doublewrite,
8686
PLUGIN_VAR_NOCMDARG | PLUGIN_VAR_READONLY,
8687
"Enable InnoDB doublewrite buffer (enabled by default). "
8688
"Disable with --skip-innodb-doublewrite.",
8691
static MYSQL_SYSVAR_ULONG(fast_shutdown, innobase_fast_shutdown,
8692
PLUGIN_VAR_OPCMDARG,
8693
"Speeds up the shutdown process of the InnoDB storage engine. Possible "
8694
"values are 0, 1 (faster)"
8696
NetWare can't close unclosed files, can't automatically kill remaining
8697
threads, etc, so on this OS we disable the crash-like InnoDB shutdown.
8699
IF_NETWARE("", " or 2 (fastest - crash-like)")
8701
NULL, NULL, 1, 0, IF_NETWARE(1,2), 0);
8703
static MYSQL_SYSVAR_BOOL(file_per_table, innobase_file_per_table,
8704
PLUGIN_VAR_NOCMDARG | PLUGIN_VAR_READONLY,
8705
"Stores each InnoDB table to an .ibd file in the database dir.",
8708
static MYSQL_SYSVAR_ULONG(flush_log_at_trx_commit, srv_flush_log_at_trx_commit,
8709
PLUGIN_VAR_OPCMDARG,
8710
"Set to 0 (write and flush once per second),"
8711
" 1 (write and flush at each commit)"
8712
" or 2 (write at commit, flush once per second).",
8713
NULL, NULL, 1, 0, 2, 0);
8715
static MYSQL_SYSVAR_STR(flush_method, innobase_unix_file_flush_method,
8716
PLUGIN_VAR_RQCMDARG | PLUGIN_VAR_READONLY,
8717
"With which method to flush data.", NULL, NULL, NULL);
8719
static MYSQL_SYSVAR_BOOL(locks_unsafe_for_binlog, innobase_locks_unsafe_for_binlog,
8720
PLUGIN_VAR_NOCMDARG | PLUGIN_VAR_READONLY,
8721
"Force InnoDB to not use next-key locking, to use only row-level locking.",
8724
#ifdef UNIV_LOG_ARCHIVE
8725
static MYSQL_SYSVAR_STR(log_arch_dir, innobase_log_arch_dir,
8726
PLUGIN_VAR_RQCMDARG | PLUGIN_VAR_READONLY,
8727
"Where full logs should be archived.", NULL, NULL, NULL);
8729
static MYSQL_SYSVAR_BOOL(log_archive, innobase_log_archive,
8730
PLUGIN_VAR_OPCMDARG | PLUGIN_VAR_READONLY,
8731
"Set to 1 if you want to have logs archived.", NULL, NULL, FALSE);
8732
#endif /* UNIV_LOG_ARCHIVE */
8734
static MYSQL_SYSVAR_STR(log_group_home_dir, innobase_log_group_home_dir,
8735
PLUGIN_VAR_RQCMDARG | PLUGIN_VAR_READONLY,
8736
"Path to InnoDB log files.", NULL, NULL, NULL);
8738
static MYSQL_SYSVAR_ULONG(max_dirty_pages_pct, srv_max_buf_pool_modified_pct,
8739
PLUGIN_VAR_RQCMDARG,
8740
"Percentage of dirty pages allowed in bufferpool.",
8741
NULL, NULL, 90, 0, 100, 0);
8743
static MYSQL_SYSVAR_ULONG(max_purge_lag, srv_max_purge_lag,
8744
PLUGIN_VAR_RQCMDARG,
8745
"Desired maximum length of the purge queue (0 = no limit)",
8746
NULL, NULL, 0, 0, ~0L, 0);
8748
static MYSQL_SYSVAR_BOOL(rollback_on_timeout, innobase_rollback_on_timeout,
8749
PLUGIN_VAR_OPCMDARG | PLUGIN_VAR_READONLY,
8750
"Roll back the complete transaction on lock wait timeout, for 4.x compatibility (disabled by default)",
8753
static MYSQL_SYSVAR_BOOL(status_file, innobase_create_status_file,
8754
PLUGIN_VAR_OPCMDARG | PLUGIN_VAR_NOSYSVAR,
8755
"Enable SHOW INNODB STATUS output in the innodb_status.<pid> file",
8758
static MYSQL_SYSVAR_BOOL(stats_on_metadata, innobase_stats_on_metadata,
8759
PLUGIN_VAR_OPCMDARG,
8760
"Enable statistics gathering for metadata commands such as SHOW TABLE STATUS (on by default)",
8763
static MYSQL_SYSVAR_BOOL(use_legacy_cardinality_algorithm,
8764
srv_use_legacy_cardinality_algorithm,
8765
PLUGIN_VAR_OPCMDARG,
8766
"Use legacy algorithm for picking random pages during index cardinality "
8767
"estimation. Disable this to use a better algorithm, but note that your "
8768
"query plans may change (enabled by default).",
8771
static MYSQL_SYSVAR_BOOL(adaptive_hash_index, innobase_adaptive_hash_index,
8772
PLUGIN_VAR_OPCMDARG | PLUGIN_VAR_READONLY,
8773
"Enable InnoDB adaptive hash index (enabled by default). "
8774
"Disable with --skip-innodb-adaptive-hash-index.",
8777
static MYSQL_SYSVAR_LONG(additional_mem_pool_size, innobase_additional_mem_pool_size,
8778
PLUGIN_VAR_RQCMDARG | PLUGIN_VAR_READONLY,
8779
"Size of a memory pool InnoDB uses to store data dictionary information and other internal data structures.",
8780
NULL, NULL, 1*1024*1024L, 512*1024L, LONG_MAX, 1024);
8782
static MYSQL_SYSVAR_ULONG(autoextend_increment, srv_auto_extend_increment,
8783
PLUGIN_VAR_RQCMDARG,
8784
"Data file autoextend increment in megabytes",
8785
NULL, NULL, 8L, 1L, 1000L, 0);
8787
static MYSQL_SYSVAR_LONGLONG(buffer_pool_size, innobase_buffer_pool_size,
8788
PLUGIN_VAR_RQCMDARG | PLUGIN_VAR_READONLY,
8789
"The size of the memory buffer InnoDB uses to cache data and indexes of its tables.",
8790
NULL, NULL, 8*1024*1024L, 1024*1024L, LONGLONG_MAX, 1024*1024L);
8792
static MYSQL_SYSVAR_ULONG(commit_concurrency, innobase_commit_concurrency,
8793
PLUGIN_VAR_RQCMDARG,
8794
"Helps in performance tuning in heavily concurrent environments.",
8795
innobase_commit_concurrency_validate, NULL, 0, 0, 1000, 0);
8797
static MYSQL_SYSVAR_ULONG(concurrency_tickets, srv_n_free_tickets_to_enter,
8798
PLUGIN_VAR_RQCMDARG,
8799
"Number of times a thread is allowed to enter InnoDB within the same SQL query after it has once got the ticket",
8800
NULL, NULL, 500L, 1L, ~0L, 0);
8802
static MYSQL_SYSVAR_LONG(file_io_threads, innobase_file_io_threads,
8803
PLUGIN_VAR_RQCMDARG | PLUGIN_VAR_READONLY,
8804
"Number of file I/O threads in InnoDB.",
8805
NULL, NULL, 4, 4, 64, 0);
8807
static MYSQL_SYSVAR_LONG(force_recovery, innobase_force_recovery,
8808
PLUGIN_VAR_RQCMDARG | PLUGIN_VAR_READONLY,
8809
"Helps to save your data in case the disk image of the database becomes corrupt.",
8810
NULL, NULL, 0, 0, 6, 0);
8812
static MYSQL_SYSVAR_LONG(lock_wait_timeout, innobase_lock_wait_timeout,
8813
PLUGIN_VAR_RQCMDARG | PLUGIN_VAR_READONLY,
8814
"Timeout in seconds an InnoDB transaction may wait for a lock before being rolled back.",
8815
NULL, NULL, 50, 1, 1024 * 1024 * 1024, 0);
8817
static MYSQL_SYSVAR_LONG(log_buffer_size, innobase_log_buffer_size,
8818
PLUGIN_VAR_RQCMDARG | PLUGIN_VAR_READONLY,
8819
"The size of the buffer which InnoDB uses to write log to the log files on disk.",
8820
NULL, NULL, 1024*1024L, 256*1024L, LONG_MAX, 1024);
8822
static MYSQL_SYSVAR_LONGLONG(log_file_size, innobase_log_file_size,
8823
PLUGIN_VAR_RQCMDARG | PLUGIN_VAR_READONLY,
8824
"Size of each log file in a log group.",
8825
NULL, NULL, 5*1024*1024L, 1*1024*1024L, LONGLONG_MAX, 1024*1024L);
8827
static MYSQL_SYSVAR_LONG(log_files_in_group, innobase_log_files_in_group,
8828
PLUGIN_VAR_RQCMDARG | PLUGIN_VAR_READONLY,
8829
"Number of log files in the log group. InnoDB writes to the files in a circular fashion. Value 3 is recommended here.",
8830
NULL, NULL, 2, 2, 100, 0);
8832
static MYSQL_SYSVAR_LONG(mirrored_log_groups, innobase_mirrored_log_groups,
8833
PLUGIN_VAR_RQCMDARG | PLUGIN_VAR_READONLY,
8834
"Number of identical copies of log groups we keep for the database. Currently this should be set to 1.",
8835
NULL, NULL, 1, 1, 10, 0);
8837
static MYSQL_SYSVAR_LONG(open_files, innobase_open_files,
8838
PLUGIN_VAR_RQCMDARG | PLUGIN_VAR_READONLY,
8839
"How many files at the maximum InnoDB keeps open at the same time.",
8840
NULL, NULL, 300L, 10L, LONG_MAX, 0);
8842
static MYSQL_SYSVAR_ULONG(sync_spin_loops, srv_n_spin_wait_rounds,
8843
PLUGIN_VAR_RQCMDARG,
8844
"Count of spin-loop rounds in InnoDB mutexes",
8845
NULL, NULL, 20L, 0L, ~0L, 0);
8847
static MYSQL_SYSVAR_ULONG(thread_concurrency, srv_thread_concurrency,
8848
PLUGIN_VAR_RQCMDARG,
8849
"Helps in performance tuning in heavily concurrent environments. Sets the maximum number of threads allowed inside InnoDB. Value 0 will disable the thread throttling.",
8850
NULL, NULL, 8, 0, 1000, 0);
8852
static MYSQL_SYSVAR_ULONG(thread_sleep_delay, srv_thread_sleep_delay,
8853
PLUGIN_VAR_RQCMDARG,
8854
"Time of innodb thread sleeping before joining InnoDB queue (usec). Value 0 disable a sleep",
8855
NULL, NULL, 10000L, 0L, ~0L, 0);
8857
static MYSQL_SYSVAR_STR(data_file_path, innobase_data_file_path,
8858
PLUGIN_VAR_RQCMDARG | PLUGIN_VAR_READONLY,
8859
"Path to individual files and their sizes.",
8862
static MYSQL_SYSVAR_LONG(autoinc_lock_mode, innobase_autoinc_lock_mode,
8863
PLUGIN_VAR_RQCMDARG | PLUGIN_VAR_READONLY,
8864
"The AUTOINC lock modes supported by InnoDB: "
8865
"0 => Old style AUTOINC locking (for backward"
8867
"1 => New style AUTOINC locking "
8868
"2 => No AUTOINC locking (unsafe for SBR)",
8870
AUTOINC_NEW_STYLE_LOCKING, /* Default setting */
8871
AUTOINC_OLD_STYLE_LOCKING, /* Minimum value */
8872
AUTOINC_NO_LOCKING, 0); /* Maximum value */
8874
static struct st_mysql_sys_var* innobase_system_variables[]= {
8875
MYSQL_SYSVAR(additional_mem_pool_size),
8876
MYSQL_SYSVAR(autoextend_increment),
8877
MYSQL_SYSVAR(buffer_pool_size),
8878
MYSQL_SYSVAR(checksums),
8879
MYSQL_SYSVAR(commit_concurrency),
8880
MYSQL_SYSVAR(concurrency_tickets),
8881
MYSQL_SYSVAR(data_file_path),
8882
MYSQL_SYSVAR(data_home_dir),
8883
MYSQL_SYSVAR(doublewrite),
8884
MYSQL_SYSVAR(fast_shutdown),
8885
MYSQL_SYSVAR(file_io_threads),
8886
MYSQL_SYSVAR(file_per_table),
8887
MYSQL_SYSVAR(flush_log_at_trx_commit),
8888
MYSQL_SYSVAR(flush_method),
8889
MYSQL_SYSVAR(force_recovery),
8890
MYSQL_SYSVAR(locks_unsafe_for_binlog),
8891
MYSQL_SYSVAR(lock_wait_timeout),
8892
#ifdef UNIV_LOG_ARCHIVE
8893
MYSQL_SYSVAR(log_arch_dir),
8894
MYSQL_SYSVAR(log_archive),
8895
#endif /* UNIV_LOG_ARCHIVE */
8896
MYSQL_SYSVAR(log_buffer_size),
8897
MYSQL_SYSVAR(log_file_size),
8898
MYSQL_SYSVAR(log_files_in_group),
8899
MYSQL_SYSVAR(log_group_home_dir),
8900
MYSQL_SYSVAR(max_dirty_pages_pct),
8901
MYSQL_SYSVAR(max_purge_lag),
8902
MYSQL_SYSVAR(mirrored_log_groups),
8903
MYSQL_SYSVAR(open_files),
8904
MYSQL_SYSVAR(rollback_on_timeout),
8905
MYSQL_SYSVAR(stats_on_metadata),
8906
MYSQL_SYSVAR(use_legacy_cardinality_algorithm),
8907
MYSQL_SYSVAR(adaptive_hash_index),
8908
MYSQL_SYSVAR(status_file),
8909
MYSQL_SYSVAR(support_xa),
8910
MYSQL_SYSVAR(sync_spin_loops),
8911
MYSQL_SYSVAR(table_locks),
8912
MYSQL_SYSVAR(thread_concurrency),
8913
MYSQL_SYSVAR(thread_sleep_delay),
8914
MYSQL_SYSVAR(autoinc_lock_mode),
8918
mysql_declare_plugin(innobase)
8920
MYSQL_STORAGE_ENGINE_PLUGIN,
8921
&innobase_storage_engine,
8924
"Supports transactions, row-level locking, and foreign keys",
8926
innobase_init, /* Plugin Init */
8927
NULL, /* Plugin Deinit */
8929
innodb_status_variables_export,/* status variables */
8930
innobase_system_variables, /* system variables */
8933
mysql_declare_plugin_end;
8935
/** @brief Initialize the default value of innodb_commit_concurrency.
8937
Once InnoDB is running, the innodb_commit_concurrency must not change
8938
from zero to nonzero. (Bug #42101)
8940
The initial default value is 0, and without this extra initialization,
8941
SET GLOBAL innodb_commit_concurrency=DEFAULT would set the parameter
8942
to 0, even if it was initially set to nonzero at the command line
8943
or configuration file. */
8946
innobase_commit_concurrency_init_default(void)
8947
/*==========================================*/
8949
MYSQL_SYSVAR_NAME(commit_concurrency).def_val
8950
= innobase_commit_concurrency;