~ubuntu-branches/ubuntu/precise/mysql-5.1/precise

« back to all changes in this revision

Viewing changes to storage/innobase/handler/ha_innodb.cc

  • Committer: Bazaar Package Importer
  • Author(s): Norbert Tretkowski
  • Date: 2010-03-17 14:56:02 UTC
  • Revision ID: james.westby@ubuntu.com-20100317145602-x7e30l1b2sb5s6w6
Tags: upstream-5.1.45
ImportĀ upstreamĀ versionĀ 5.1.45

Show diffs side-by-side

added added

removed removed

Lines of Context:
 
1
/* Copyright (C) 2000-2005 MySQL AB & Innobase Oy
 
2
 
 
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.
 
6
 
 
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.
 
11
 
 
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 */
 
15
 
 
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. */
 
19
 
 
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
 
25
    in Windows?
 
26
*/
 
27
 
 
28
#ifdef USE_PRAGMA_IMPLEMENTATION
 
29
#pragma implementation                          // gcc: Class implementation
 
30
#endif
 
31
 
 
32
#include <mysql_priv.h>
 
33
#include <mysqld_error.h>
 
34
 
 
35
#include <m_ctype.h>
 
36
#include <hash.h>
 
37
#include <myisampack.h>
 
38
#include <mysys_err.h>
 
39
#include <my_sys.h>
 
40
#include "ha_innodb.h"
 
41
#include <mysql/plugin.h>
 
42
 
 
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;
 
53
 
 
54
/*
 
55
  This needs to exist until the query cache callback is removed
 
56
  or learns to pass hton.
 
57
*/
 
58
static handlerton *innodb_hton_ptr;
 
59
 
 
60
#define INSIDE_HA_INNOBASE_CC
 
61
 
 
62
/* Include necessary InnoDB headers */
 
63
extern "C" {
 
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"
 
88
}
 
89
 
 
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;
 
93
 
 
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;
 
100
 
 
101
static long long innobase_buffer_pool_size, innobase_log_file_size;
 
102
 
 
103
/* The default values for the following char* start-up parameters
 
104
are determined in innobase_init below: */
 
105
 
 
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
 
110
affects Windows: */
 
111
static char*    innobase_unix_file_flush_method         = NULL;
 
112
 
 
113
/* Below we have boolean-valued start-up parameters, and their default
 
114
values */
 
115
 
 
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;
 
129
 
 
130
static char*    internal_innobase_data_file_path        = NULL;
 
131
 
 
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. */
 
136
 
 
137
#define INNOBASE_WAKE_INTERVAL  32
 
138
static ulong    innobase_active_counter = 0;
 
139
 
 
140
static HASH     innobase_open_tables;
 
141
 
 
142
#ifdef __NETWARE__      /* some special cleanup for NetWare */
 
143
bool nw_panic = FALSE;
 
144
#endif
 
145
 
 
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,
 
154
           void *savepoint);
 
155
static int innobase_savepoint(handlerton *hton, THD* thd, void *savepoint);
 
156
static int innobase_release_savepoint(handlerton *hton, THD* thd,
 
157
           void *savepoint);
 
158
static handler *innobase_create_handler(handlerton *hton,
 
159
                                        TABLE_SHARE *table,
 
160
                                        MEM_ROOT *mem_root);
 
161
 
 
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. */
 
166
static
 
167
bool
 
168
innobase_index_name_is_reserved(
 
169
/*============================*/
 
170
                                        /* out: true if index name matches a
 
171
                                        reserved name */
 
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 */
 
176
 
 
177
static const char innobase_hton_name[]= "InnoDB";
 
178
 
 
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";
 
182
 
 
183
/** @brief Initialize the default value of innodb_commit_concurrency.
 
184
 
 
185
Once InnoDB is running, the innodb_commit_concurrency must not change
 
186
from zero to nonzero. (Bug #42101)
 
187
 
 
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. */
 
192
static
 
193
void
 
194
innobase_commit_concurrency_init_default(void);
 
195
/*==========================================*/
 
196
 
 
197
/*****************************************************************
 
198
Check for a valid value of innobase_commit_concurrency. */
 
199
static
 
200
int
 
201
innobase_commit_concurrency_validate(
 
202
/*=================================*/
 
203
                                                /* out: 0 for valid
 
204
                                                innodb_commit_concurrency */
 
205
        THD*                            thd,    /* in: thread handle */
 
206
        struct st_mysql_sys_var*        var,    /* in: pointer to system
 
207
                                                variable */
 
208
        void*                           save,   /* out: immediate result
 
209
                                                for update function */
 
210
        struct st_mysql_value*          value)  /* in: incoming string */
 
211
{
 
212
        long long       intbuf;
 
213
        ulong           commit_concurrency;
 
214
 
 
215
        DBUG_ENTER("innobase_commit_concurrency_validate");
 
216
 
 
217
        if (value->val_int(value, &intbuf)) {
 
218
                /* The value is NULL. That is invalid. */
 
219
                DBUG_RETURN(1);
 
220
        }
 
221
 
 
222
        *reinterpret_cast<ulong*>(save) = commit_concurrency
 
223
                = static_cast<ulong>(intbuf);
 
224
 
 
225
        /* Allow the value to be updated, as long as it remains zero
 
226
        or nonzero. */
 
227
        DBUG_RETURN(!(!commit_concurrency == !innobase_commit_concurrency));
 
228
}
 
229
 
 
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,
 
233
  /* default */ TRUE);
 
234
 
 
235
static MYSQL_THDVAR_BOOL(table_locks, PLUGIN_VAR_OPCMDARG,
 
236
  "Enable InnoDB locking in LOCK TABLES",
 
237
  /* check_func */ NULL, /* update_func */ NULL,
 
238
  /* default */ TRUE);
 
239
 
 
240
static handler *innobase_create_handler(handlerton *hton,
 
241
                                        TABLE_SHARE *table, 
 
242
                                        MEM_ROOT *mem_root)
 
243
{
 
244
  return new (mem_root) ha_innobase(hton, table);
 
245
}
 
246
 
 
247
/***********************************************************************
 
248
This function is used to prepare X/Open XA distributed transaction   */
 
249
static
 
250
int
 
251
innobase_xa_prepare(
 
252
/*================*/
 
253
                        /* out: 0 or error number */
 
254
        handlerton* hton,
 
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   */
 
261
static
 
262
int
 
263
innobase_xa_recover(
 
264
/*================*/
 
265
                                /* out: number of prepared transactions
 
266
                                stored in xid_list */
 
267
        handlerton* hton,
 
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 */
 
273
static
 
274
int
 
275
innobase_commit_by_xid(
 
276
/*===================*/
 
277
                        /* out: 0 or error number */
 
278
        handlerton* hton,
 
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 */
 
283
static
 
284
int
 
285
innobase_rollback_by_xid(
 
286
/*=====================*/
 
287
                        /* out: 0 or error number */
 
288
        handlerton* hton,
 
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
 
294
using a cursor. */
 
295
static
 
296
void*
 
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. */
 
307
static
 
308
void
 
309
innobase_set_cursor_view(
 
310
/*=====================*/
 
311
        handlerton* hton,
 
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. */
 
318
static
 
319
void
 
320
innobase_close_cursor_view(
 
321
/*=======================*/
 
322
        handlerton* hton,
 
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. */
 
327
static
 
328
void
 
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. */
 
339
static
 
340
int
 
341
innobase_end(handlerton *hton, ha_panic_function type);
 
342
 
 
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
 
347
have one. */
 
348
static
 
349
int
 
350
innobase_start_trx_and_assign_read_view(
 
351
/*====================================*/
 
352
                        /* out: 0 */
 
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. */
 
359
static
 
360
bool
 
361
innobase_flush_logs(
 
362
/*================*/
 
363
                                /* out: TRUE if error */
 
364
        handlerton*     hton);  /* in: InnoDB handlerton */
 
365
 
 
366
/****************************************************************************
 
367
Implements the SHOW INNODB STATUS command. Sends the output of the InnoDB
 
368
Monitor to the client. */
 
369
static
 
370
bool
 
371
innodb_show_status(
 
372
/*===============*/
 
373
        handlerton*     hton,   /* in: the innodb handlerton */
 
374
        THD*    thd,    /* in: the MySQL query thread of the caller */
 
375
        stat_print_fn *stat_print);
 
376
static
 
377
bool innobase_show_status(handlerton *hton, THD* thd, 
 
378
                          stat_print_fn* stat_print,
 
379
                          enum ha_stat_type stat_type);
 
380
 
 
381
/*********************************************************************
 
382
Commits a transaction in an InnoDB database. */
 
383
static
 
384
void
 
385
innobase_commit_low(
 
386
/*================*/
 
387
        trx_t*  trx);   /* in: transaction handle */
 
388
 
 
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},
 
398
#ifdef UNIV_DEBUG
 
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},
 
418
  {"data_fsyncs",
 
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},
 
426
  {"data_read",
 
427
  (char*) &export_vars.innodb_data_read,                  SHOW_LONG},
 
428
  {"data_reads",
 
429
  (char*) &export_vars.innodb_data_reads,                 SHOW_LONG},
 
430
  {"data_writes",
 
431
  (char*) &export_vars.innodb_data_writes,                SHOW_LONG},
 
432
  {"data_written",
 
433
  (char*) &export_vars.innodb_data_written,               SHOW_LONG},
 
434
  {"dblwr_pages_written",
 
435
  (char*) &export_vars.innodb_dblwr_pages_written,        SHOW_LONG},
 
436
  {"dblwr_writes",
 
437
  (char*) &export_vars.innodb_dblwr_writes,               SHOW_LONG},
 
438
  {"log_waits",
 
439
  (char*) &export_vars.innodb_log_waits,                  SHOW_LONG},
 
440
  {"log_write_requests",
 
441
  (char*) &export_vars.innodb_log_write_requests,         SHOW_LONG},
 
442
  {"log_writes",
 
443
  (char*) &export_vars.innodb_log_writes,                 SHOW_LONG},
 
444
  {"os_log_fsyncs",
 
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},
 
450
  {"os_log_written",
 
451
  (char*) &export_vars.innodb_os_log_written,             SHOW_LONG},
 
452
  {"page_size",
 
453
  (char*) &export_vars.innodb_page_size,                  SHOW_LONG},
 
454
  {"pages_created",
 
455
  (char*) &export_vars.innodb_pages_created,              SHOW_LONG},
 
456
  {"pages_read",
 
457
  (char*) &export_vars.innodb_pages_read,                 SHOW_LONG},
 
458
  {"pages_written",
 
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},
 
462
  {"row_lock_time",
 
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},
 
468
  {"row_lock_waits",
 
469
  (char*) &export_vars.innodb_row_lock_waits,             SHOW_LONG},
 
470
  {"rows_deleted",
 
471
  (char*) &export_vars.innodb_rows_deleted,               SHOW_LONG},
 
472
  {"rows_inserted",
 
473
  (char*) &export_vars.innodb_rows_inserted,              SHOW_LONG},
 
474
  {"rows_read",
 
475
  (char*) &export_vars.innodb_rows_read,                  SHOW_LONG},
 
476
  {"rows_updated",
 
477
  (char*) &export_vars.innodb_rows_updated,               SHOW_LONG},
 
478
  {NullS, NullS, SHOW_LONG}
 
479
};
 
480
 
 
481
/* General functions */
 
482
 
 
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(). */
 
489
extern "C"
 
490
ibool
 
491
thd_is_replication_slave_thread(
 
492
/*============================*/
 
493
                        /* out: true if thd is the replication thread */
 
494
        void*   thd)    /* in: thread handle (THD*) */
 
495
{
 
496
        return((ibool) thd_slave_thread((THD*) thd));
 
497
}
 
498
 
 
499
/**********************************************************************
 
500
Save some CPU by testing the value of srv_thread_concurrency in inline
 
501
functions. */
 
502
inline
 
503
void
 
504
innodb_srv_conc_enter_innodb(
 
505
/*=========================*/
 
506
        trx_t*  trx)    /* in: transaction handle */
 
507
{
 
508
        if (UNIV_LIKELY(!srv_thread_concurrency)) {
 
509
 
 
510
                return;
 
511
        }
 
512
 
 
513
        srv_conc_enter_innodb(trx);
 
514
}
 
515
 
 
516
/**********************************************************************
 
517
Save some CPU by testing the value of srv_thread_concurrency in inline
 
518
functions. */
 
519
inline
 
520
void
 
521
innodb_srv_conc_exit_innodb(
 
522
/*========================*/
 
523
        trx_t*  trx)    /* in: transaction handle */
 
524
{
 
525
        if (UNIV_LIKELY(!trx->declared_to_be_inside_innodb)) {
 
526
 
 
527
                return;
 
528
        }
 
529
 
 
530
        srv_conc_exit_innodb(trx);
 
531
}
 
532
 
 
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. */
 
538
inline
 
539
void
 
540
innobase_release_stat_resources(
 
541
/*============================*/
 
542
        trx_t*  trx)    /* in: transaction object */
 
543
{
 
544
        if (trx->has_search_latch) {
 
545
                trx_search_latch_release_if_reserved(trx);
 
546
        }
 
547
 
 
548
        if (trx->declared_to_be_inside_innodb) {
 
549
                /* Release our possible ticket in the FIFO */
 
550
 
 
551
                srv_conc_force_exit_innodb(trx);
 
552
        }
 
553
}
 
554
 
 
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. */
 
560
extern "C"
 
561
ibool
 
562
thd_has_edited_nontrans_tables(
 
563
/*===========================*/
 
564
                        /* out: true if non-transactional tables have
 
565
                        been edited */
 
566
        void*   thd)    /* in: thread handle (THD*) */
 
567
{
 
568
        return((ibool) thd_non_transactional_update((THD*) thd));
 
569
}
 
570
 
 
571
/**********************************************************************
 
572
Returns true if the thread is executing a SELECT statement. */
 
573
extern "C"
 
574
ibool
 
575
thd_is_select(
 
576
/*==========*/
 
577
                                /* out: true if thd is executing SELECT */
 
578
        const void*     thd)    /* in: thread handle (THD*) */
 
579
{
 
580
        return(thd_sql_command((const THD*) thd) == SQLCOM_SELECT);
 
581
}
 
582
 
 
583
/************************************************************************
 
584
Obtain the InnoDB transaction of a MySQL thread. */
 
585
inline
 
586
trx_t*&
 
587
thd_to_trx(
 
588
/*=======*/
 
589
                        /* out: reference to transaction pointer */
 
590
        THD*    thd)    /* in: MySQL thread */
 
591
{
 
592
        return(*(trx_t**) thd_ha_data(thd, innodb_hton_ptr));
 
593
}
 
594
 
 
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. */
 
599
static
 
600
int
 
601
innobase_release_temporary_latches(
 
602
/*===============================*/
 
603
                                /* out: 0 */
 
604
        handlerton*     hton,   /* in: handlerton */
 
605
        THD*            thd)    /* in: MySQL thread */
 
606
{
 
607
        trx_t*  trx;
 
608
 
 
609
        DBUG_ASSERT(hton == innodb_hton_ptr);
 
610
 
 
611
        if (!innodb_inited) {
 
612
 
 
613
                return 0;
 
614
        }
 
615
 
 
616
        trx = thd_to_trx(thd);
 
617
 
 
618
        if (trx) {
 
619
                innobase_release_stat_resources(trx);
 
620
        }
 
621
        return 0;
 
622
}
 
623
 
 
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. */
 
629
inline
 
630
void
 
631
innobase_active_small(void)
 
632
/*=======================*/
 
633
{
 
634
        innobase_active_counter++;
 
635
 
 
636
        if ((innobase_active_counter % INNOBASE_WAKE_INTERVAL) == 0) {
 
637
                srv_active_wake_master_thread();
 
638
        }
 
639
}
 
640
 
 
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. */
 
645
static
 
646
int
 
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 */
 
652
{
 
653
        if (error == DB_SUCCESS) {
 
654
 
 
655
                return(0);
 
656
 
 
657
        } else if (error == (int) DB_DUPLICATE_KEY) {
 
658
 
 
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
 
664
                handling stage. */
 
665
                return(HA_ERR_FOUND_DUPP_KEY);
 
666
 
 
667
        } else if (error == (int) DB_FOREIGN_DUPLICATE_KEY) {
 
668
 
 
669
                return(HA_ERR_FOREIGN_DUPLICATE_KEY);
 
670
 
 
671
        } else if (error == (int) DB_RECORD_NOT_FOUND) {
 
672
 
 
673
                return(HA_ERR_NO_ACTIVE_RECORD);
 
674
 
 
675
        } else if (error == (int) DB_ERROR) {
 
676
 
 
677
                return(-1); /* unspecified error */
 
678
 
 
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 */
 
683
 
 
684
                if (thd) {
 
685
                        thd_mark_transaction_to_rollback(thd, TRUE);
 
686
                }
 
687
 
 
688
                return(HA_ERR_LOCK_DEADLOCK);
 
689
        } else if (error == (int) DB_LOCK_WAIT_TIMEOUT) {
 
690
 
 
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. */
 
694
 
 
695
                if (thd) {
 
696
                        thd_mark_transaction_to_rollback(
 
697
                                thd, (bool)row_rollback_on_timeout);
 
698
                }
 
699
 
 
700
                return(HA_ERR_LOCK_WAIT_TIMEOUT);
 
701
 
 
702
        } else if (error == (int) DB_NO_REFERENCED_ROW) {
 
703
 
 
704
                return(HA_ERR_NO_REFERENCED_ROW);
 
705
 
 
706
        } else if (error == (int) DB_ROW_IS_REFERENCED) {
 
707
 
 
708
                return(HA_ERR_ROW_IS_REFERENCED);
 
709
 
 
710
        } else if (error == (int) DB_CANNOT_ADD_CONSTRAINT) {
 
711
 
 
712
                return(HA_ERR_CANNOT_ADD_FOREIGN);
 
713
 
 
714
        } else if (error == (int) DB_CANNOT_DROP_CONSTRAINT) {
 
715
 
 
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) {
 
720
 
 
721
                return(HA_ERR_CRASHED);
 
722
 
 
723
        } else if (error == (int) DB_OUT_OF_FILE_SPACE) {
 
724
 
 
725
                return(HA_ERR_RECORD_FILE_FULL);
 
726
 
 
727
        } else if (error == (int) DB_TABLE_IS_BEING_USED) {
 
728
 
 
729
                return(HA_ERR_WRONG_COMMAND);
 
730
 
 
731
        } else if (error == (int) DB_TABLE_NOT_FOUND) {
 
732
 
 
733
                return(HA_ERR_NO_SUCH_TABLE);
 
734
 
 
735
        } else if (error == (int) DB_TOO_BIG_RECORD) {
 
736
 
 
737
                return(HA_ERR_TO_BIG_ROW);
 
738
 
 
739
        } else if (error == (int) DB_CORRUPTION) {
 
740
 
 
741
                return(HA_ERR_CRASHED);
 
742
        } else if (error == (int) DB_NO_SAVEPOINT) {
 
743
 
 
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 */
 
749
 
 
750
                if (thd) {
 
751
                        thd_mark_transaction_to_rollback(thd, TRUE);
 
752
                }
 
753
 
 
754
                return(HA_ERR_LOCK_TABLE_FULL);
 
755
        } else if (error == DB_TOO_MANY_CONCURRENT_TRXS) {
 
756
 
 
757
                return(HA_ERR_TOO_MANY_CONCURRENT_TRXS);
 
758
 
 
759
        } else if (error == DB_UNSUPPORTED) {
 
760
 
 
761
                return(HA_ERR_UNSUPPORTED);
 
762
        } else {
 
763
                return(-1);                     // Unknown error
 
764
        }
 
765
}
 
766
 
 
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
 
770
this function! */
 
771
extern "C"
 
772
void
 
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 */
 
779
{
 
780
        THD*    thd;
 
781
        char    buffer[1024];
 
782
 
 
783
        thd = (THD*) input_thd;
 
784
        fputs(thd_security_context(thd, buffer, sizeof(buffer), 
 
785
                                   max_query_len), f);
 
786
        putc('\n', f);
 
787
}
 
788
 
 
789
/**********************************************************************
 
790
Get the variable length bounds of the given character set.
 
791
 
 
792
NOTE that the exact prototype of this function has to be in
 
793
/innobase/include/data0type.ic! */
 
794
extern "C"
 
795
void
 
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) */
 
801
{
 
802
        CHARSET_INFO*   cs;
 
803
        ut_ad(cset < 256);
 
804
        ut_ad(mbminlen);
 
805
        ut_ad(mbmaxlen);
 
806
 
 
807
        cs = all_charsets[cset];
 
808
        if (cs) {
 
809
                *mbminlen = cs->mbminlen;
 
810
                *mbmaxlen = cs->mbmaxlen;
 
811
        } else {
 
812
                if (current_thd
 
813
                    && (thd_sql_command(current_thd) == SQLCOM_DROP_TABLE)) {
 
814
 
 
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)
 
818
                            && (cset != 0)){
 
819
 
 
820
                                sql_print_warning(
 
821
                                        "Unknown collation #%lu.", cset);
 
822
                        }
 
823
                } else {
 
824
 
 
825
                        ut_a(cset == 0);
 
826
                }
 
827
 
 
828
                *mbminlen = *mbmaxlen = 0;
 
829
        }
 
830
}
 
831
 
 
832
/**********************************************************************
 
833
Converts an identifier to a table name.
 
834
 
 
835
NOTE that the exact prototype of this function has to be in
 
836
/innobase/dict/dict0dict.c! */
 
837
extern "C"
 
838
void
 
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 */
 
844
{
 
845
        uint    errors;
 
846
 
 
847
        strconvert(thd_charset(current_thd), from,
 
848
                   &my_charset_filename, to, (uint) len, &errors);
 
849
}
 
850
 
 
851
/**********************************************************************
 
852
Converts an identifier to UTF-8.
 
853
 
 
854
NOTE that the exact prototype of this function has to be in
 
855
/innobase/dict/dict0dict.c! */
 
856
extern "C"
 
857
void
 
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 */
 
863
{
 
864
        uint    errors;
 
865
 
 
866
        strconvert(thd_charset(current_thd), from,
 
867
                   system_charset_info, to, (uint) len, &errors);
 
868
}
 
869
 
 
870
/**********************************************************************
 
871
Compares NUL-terminated UTF-8 strings case insensitively.
 
872
 
 
873
NOTE that the exact prototype of this function has to be in
 
874
/innobase/dict/dict0dict.c! */
 
875
extern "C"
 
876
int
 
877
innobase_strcasecmp(
 
878
/*================*/
 
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 */
 
882
{
 
883
        return(my_strcasecmp(system_charset_info, a, b));
 
884
}
 
885
 
 
886
/**********************************************************************
 
887
Makes all characters in a NUL-terminated UTF-8 string lower case.
 
888
 
 
889
NOTE that the exact prototype of this function has to be in
 
890
/innobase/dict/dict0dict.c! */
 
891
extern "C"
 
892
void
 
893
innobase_casedn_str(
 
894
/*================*/
 
895
        char*   a)      /* in/out: string to put in lower case */
 
896
{
 
897
        my_casedn_str(system_charset_info, a);
 
898
}
 
899
 
 
900
/**************************************************************************
 
901
Determines the connection character set.
 
902
 
 
903
NOTE that the exact prototype of this function has to be in
 
904
/innobase/dict/dict0dict.c! */
 
905
extern "C"
 
906
struct charset_info_st*
 
907
innobase_get_charset(
 
908
/*=================*/
 
909
                                /* out: connection character set */
 
910
        void*   mysql_thd)      /* in: MySQL thread handle */
 
911
{
 
912
        return(thd_charset((THD*) mysql_thd));
 
913
}
 
914
 
 
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) */
 
920
extern "C"
 
921
void __cdecl
 
922
_dosmaperr(
 
923
        unsigned long); /*!< in: OS error value */
 
924
 
 
925
/*********************************************************************//**
 
926
Creates a temporary file.
 
927
@return temporary file descriptor, or < 0 on error */
 
928
extern "C"
 
929
int
 
930
innobase_mysql_tmpfile(void)
 
931
/*========================*/
 
932
{
 
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 */
 
943
                             | GENERIC_WRITE
 
944
                             | DELETE;
 
945
        DWORD   fileshare = FILE_SHARE_READ     /* OS file sharing mode */
 
946
                            | FILE_SHARE_WRITE
 
947
                            | FILE_SHARE_DELETE;
 
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;
 
954
 
 
955
        DBUG_ENTER("innobase_mysql_tmpfile");
 
956
 
 
957
        tmpdir = my_tmpdir(&mysql_tmpdir_list);
 
958
 
 
959
        /* The tmpdir parameter can not be NULL for GetTempFileName. */
 
960
        if (!tmpdir) {
 
961
                uint    ret;
 
962
 
 
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)) {
 
966
 
 
967
                        _dosmaperr(GetLastError());     /* map error */
 
968
                        DBUG_RETURN(-1);
 
969
                }
 
970
 
 
971
                tmpdir = path_buf;
 
972
        }
 
973
 
 
974
        /* Use GetTempFileName to generate a unique filename. */
 
975
        if (!GetTempFileName(tmpdir, "ib", 0, filename)) {
 
976
 
 
977
                _dosmaperr(GetLastError());     /* map error */
 
978
                DBUG_RETURN(-1);
 
979
        }
 
980
 
 
981
        DBUG_PRINT("info", ("filename: %s", filename));
 
982
 
 
983
        /* Open/Create the file. */
 
984
        osfh = CreateFile(filename, fileaccess, fileshare, NULL,
 
985
                          filecreate, fileattrib, NULL);
 
986
        if (osfh == INVALID_HANDLE_VALUE) {
 
987
 
 
988
                /* open/create file failed! */
 
989
                _dosmaperr(GetLastError());     /* map error */
 
990
                DBUG_RETURN(-1);
 
991
        }
 
992
 
 
993
        do {
 
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);
 
997
 
 
998
        if (fd == -1) {
 
999
                /* Open failed, close the file handle. */
 
1000
 
 
1001
                _dosmaperr(GetLastError());     /* map error */
 
1002
                CloseHandle(osfh);              /* no need to check if
 
1003
                                                CloseHandle fails */
 
1004
        }
 
1005
 
 
1006
        DBUG_RETURN(fd);
 
1007
}
 
1008
#else
 
1009
/*************************************************************************
 
1010
Creates a temporary file. */
 
1011
extern "C"
 
1012
int
 
1013
innobase_mysql_tmpfile(void)
 
1014
/*========================*/
 
1015
                        /* out: temporary file descriptor, or < 0 on error */
 
1016
{
 
1017
        int     fd2 = -1;
 
1018
        File    fd = mysql_tmpfile("ib");
 
1019
        if (fd >= 0) {
 
1020
                /* Copy the file descriptor, so that the additional resources
 
1021
                allocated by create_temp_file() can be freed by invoking
 
1022
                my_close().
 
1023
 
 
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
 
1027
                my_close(). */
 
1028
                fd2 = dup(fd);
 
1029
                if (fd2 < 0) {
 
1030
                        DBUG_PRINT("error",("Got error %d on dup",fd2));
 
1031
                        my_errno=errno;
 
1032
                        my_error(EE_OUT_OF_FILERESOURCES,
 
1033
                                 MYF(ME_BELL+ME_WAITTANG),
 
1034
                                 "ib*", my_errno);
 
1035
                }
 
1036
                my_close(fd, MYF(MY_WME));
 
1037
        }
 
1038
        return(fd2);
 
1039
}
 
1040
#endif
 
1041
 
 
1042
/*************************************************************************
 
1043
Wrapper around MySQL's copy_and_convert function, see it for
 
1044
documentation. */
 
1045
extern "C"
 
1046
ulint
 
1047
innobase_convert_string(
 
1048
/*====================*/
 
1049
        void*           to,
 
1050
        ulint           to_length,
 
1051
        CHARSET_INFO*   to_cs,
 
1052
        const void*     from,
 
1053
        ulint           from_length,
 
1054
        CHARSET_INFO*   from_cs,
 
1055
        uint*           errors)
 
1056
{
 
1057
  return(copy_and_convert((char*)to, (uint32) to_length, to_cs,
 
1058
                          (const char*)from, (uint32) from_length, from_cs,
 
1059
                          errors));
 
1060
}
 
1061
 
 
1062
/*************************************************************************
 
1063
Compute the next autoinc value.
 
1064
 
 
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.
 
1070
 
 
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.,
 
1073
 
 
1074
        INSERT INTO T VALUES(), (), ();
 
1075
 
 
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. */
 
1079
static
 
1080
ulonglong
 
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 */
 
1088
{
 
1089
        ulonglong       next_value;
 
1090
 
 
1091
        /* Should never be 0. */
 
1092
        ut_a(increment > 0);
 
1093
 
 
1094
        /* According to MySQL documentation, if the offset is greater than
 
1095
        the increment then the offset is ignored. */
 
1096
        if (offset > increment) {
 
1097
                offset = 0;
 
1098
        }
 
1099
 
 
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;
 
1107
                } else {
 
1108
                        next_value = current + increment;
 
1109
                }
 
1110
        } else {
 
1111
                if (current > offset) {
 
1112
                        next_value = ((current - offset) / increment) + 1;
 
1113
                } else {
 
1114
                        next_value = ((offset - current) / increment) + 1;
 
1115
                }
 
1116
 
 
1117
                ut_a(increment > 0);
 
1118
                ut_a(next_value > 0);
 
1119
 
 
1120
                /* Check for multiplication overflow. */
 
1121
                if (increment > (max_value / next_value)) {
 
1122
 
 
1123
                        next_value = max_value;
 
1124
                } else {
 
1125
                        next_value *= increment;
 
1126
 
 
1127
                        ut_a(max_value >= next_value);
 
1128
 
 
1129
                        /* Check for overflow. */
 
1130
                        if (max_value - next_value <= offset) {
 
1131
                                next_value = max_value;
 
1132
                        } else {
 
1133
                                next_value += offset;
 
1134
                        }
 
1135
                }
 
1136
        }
 
1137
 
 
1138
        ut_a(next_value <= max_value);
 
1139
 
 
1140
        return(next_value);
 
1141
}
 
1142
 
 
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
 
1146
lacks one. */
 
1147
static
 
1148
trx_t*
 
1149
check_trx_exists(
 
1150
/*=============*/
 
1151
                        /* out: InnoDB transaction handle */
 
1152
        THD*    thd)    /* in: user thread handle */
 
1153
{
 
1154
        trx_t*& trx = thd_to_trx(thd);
 
1155
 
 
1156
        ut_ad(thd == current_thd);
 
1157
 
 
1158
        if (trx == NULL) {
 
1159
                DBUG_ASSERT(thd != NULL);
 
1160
                trx = trx_allocate_for_mysql();
 
1161
 
 
1162
                trx->mysql_thd = thd;
 
1163
                trx->mysql_query_str = thd_query(thd);
 
1164
 
 
1165
                /* Update the info whether we should skip XA steps that eat
 
1166
                CPU time */
 
1167
                trx->support_xa = THDVAR(thd, support_xa);
 
1168
        } else {
 
1169
                if (trx->magic_n != TRX_MAGIC_N) {
 
1170
                        mem_analyze_corruption(trx);
 
1171
 
 
1172
                        ut_error;
 
1173
                }
 
1174
        }
 
1175
 
 
1176
        if (thd_test_options(thd, OPTION_NO_FOREIGN_KEY_CHECKS)) {
 
1177
                trx->check_foreigns = FALSE;
 
1178
        } else {
 
1179
                trx->check_foreigns = TRUE;
 
1180
        }
 
1181
 
 
1182
        if (thd_test_options(thd, OPTION_RELAXED_UNIQUE_CHECKS)) {
 
1183
                trx->check_unique_secondary = FALSE;
 
1184
        } else {
 
1185
                trx->check_unique_secondary = TRUE;
 
1186
        }
 
1187
 
 
1188
        return(trx);
 
1189
}
 
1190
 
 
1191
 
 
1192
/*************************************************************************
 
1193
Construct ha_innobase handler. */
 
1194
 
 
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 |
 
1198
                  HA_NULL_IN_KEY |
 
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),
 
1206
  start_of_scan(0),
 
1207
  num_write_row(0)
 
1208
{}
 
1209
 
 
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
 
1213
prebuilt struct. */
 
1214
inline
 
1215
int
 
1216
ha_innobase::update_thd(
 
1217
/*====================*/
 
1218
                        /* out: 0 or error code */
 
1219
        THD*    thd)    /* in: thd to use the handle */
 
1220
{
 
1221
        trx_t*          trx;
 
1222
 
 
1223
        trx = check_trx_exists(thd);
 
1224
 
 
1225
        if (prebuilt->trx != trx) {
 
1226
 
 
1227
                row_update_prebuilt_trx(prebuilt, trx);
 
1228
        }
 
1229
 
 
1230
        user_thd = thd;
 
1231
 
 
1232
        return(0);
 
1233
}
 
1234
 
 
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. */
 
1240
inline
 
1241
void
 
1242
innobase_register_stmt(
 
1243
/*===================*/
 
1244
        handlerton*     hton,   /* in: Innobase hton */
 
1245
        THD*    thd)    /* in: MySQL thd (connection) object */
 
1246
{
 
1247
        /* Register the statement */
 
1248
        trans_register_ha(thd, FALSE, hton);
 
1249
}
 
1250
 
 
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
 
1256
allowed, too.
 
1257
This function also registers the current SQL statement. */
 
1258
inline
 
1259
void
 
1260
innobase_register_trx_and_stmt(
 
1261
/*===========================*/
 
1262
        handlerton *hton, /* in: Innobase handlerton */
 
1263
        THD*    thd)    /* in: MySQL thd (connection) object */
 
1264
{
 
1265
        /* NOTE that actually innobase_register_stmt() registers also
 
1266
        the transaction in the AUTOCOMMIT=1 mode. */
 
1267
 
 
1268
        innobase_register_stmt(hton, thd);
 
1269
 
 
1270
        if (thd_test_options(thd, OPTION_NOT_AUTOCOMMIT | OPTION_BEGIN)) {
 
1271
 
 
1272
                /* No autocommit mode, register for a transaction */
 
1273
                trans_register_ha(thd, TRUE, hton);
 
1274
        }
 
1275
}
 
1276
 
 
1277
/*   BACKGROUND INFO: HOW THE MYSQL QUERY CACHE WORKS WITH INNODB
 
1278
     ------------------------------------------------------------
 
1279
 
 
1280
1) The use of the query cache for TBL is disabled when there is an
 
1281
uncommitted change to TBL.
 
1282
 
 
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.
 
1287
 
 
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
 
1290
of TBL immediately.
 
1291
 
 
1292
How this is implemented inside InnoDB:
 
1293
 
 
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.
 
1297
 
 
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.
 
1300
 
 
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.
 
1303
 
 
1304
How this is implemented inside sql_cache.cc:
 
1305
 
 
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.
 
1309
 
 
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
 
1313
that thd.
 
1314
 
 
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.
 
1318
*/
 
1319
 
 
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.
 
1324
 
 
1325
The query cache is allowed to operate on certain query only if this function
 
1326
returns TRUE for all tables in the query.
 
1327
 
 
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.
 
1331
 
 
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. */
 
1338
static
 
1339
my_bool
 
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
 
1348
                                retrieve it */
 
1349
        char*   full_name,      /* in: concatenation of database name,
 
1350
                                the null character '\0', and the table
 
1351
                                name */
 
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 */
 
1355
{
 
1356
        ibool   is_autocommit;
 
1357
        trx_t*  trx;
 
1358
        char    norm_name[1000];
 
1359
 
 
1360
        ut_a(full_name_len < 999);
 
1361
 
 
1362
        trx = check_trx_exists(thd);
 
1363
 
 
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. */
 
1367
 
 
1368
                return((my_bool)FALSE);
 
1369
        }
 
1370
 
 
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.");
 
1375
 
 
1376
                mutex_enter_noninline(&kernel_mutex);
 
1377
                trx_print(stderr, trx, 1024);
 
1378
                mutex_exit_noninline(&kernel_mutex);
 
1379
        }
 
1380
 
 
1381
        innobase_release_stat_resources(trx);
 
1382
 
 
1383
        if (!thd_test_options(thd, OPTION_NOT_AUTOCOMMIT | OPTION_BEGIN)) {
 
1384
 
 
1385
                is_autocommit = TRUE;
 
1386
        } else {
 
1387
                is_autocommit = FALSE;
 
1388
 
 
1389
        }
 
1390
 
 
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.
 
1395
 
 
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!
 
1402
 
 
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. */
 
1409
 
 
1410
                return((my_bool)TRUE);
 
1411
        }
 
1412
 
 
1413
        /* Normalize the table name to InnoDB format */
 
1414
 
 
1415
        memcpy(norm_name, full_name, full_name_len);
 
1416
 
 
1417
        norm_name[strlen(norm_name)] = '/'; /* InnoDB uses '/' as the
 
1418
                                            separator between db and table */
 
1419
        norm_name[full_name_len] = '\0';
 
1420
#ifdef __WIN__
 
1421
        innobase_casedn_str(norm_name);
 
1422
#endif
 
1423
        /* The call of row_search_.. will start a new transaction if it is
 
1424
        not yet started */
 
1425
 
 
1426
        if (trx->active_trans == 0) {
 
1427
 
 
1428
                innobase_register_trx_and_stmt(innodb_hton_ptr, thd);
 
1429
                trx->active_trans = 1;
 
1430
        }
 
1431
 
 
1432
        if (row_search_check_if_query_cache_permitted(trx, norm_name)) {
 
1433
 
 
1434
                /* printf("Query cache for %s permitted\n", norm_name); */
 
1435
 
 
1436
                return((my_bool)TRUE);
 
1437
        }
 
1438
 
 
1439
        /* printf("Query cache for %s NOT permitted\n", norm_name); */
 
1440
 
 
1441
        return((my_bool)FALSE);
 
1442
}
 
1443
 
 
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! */
 
1448
extern "C"
 
1449
void
 
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
 
1456
                                in LOWER CASE! */
 
1457
        ulint   full_name_len)  /* in: full name length where also the null
 
1458
                                chars count */
 
1459
{
 
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. */
 
1463
 
 
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,
 
1469
                                      TRUE);
 
1470
#endif
 
1471
}
 
1472
 
 
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 */
 
1477
static
 
1478
char*
 
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 */
 
1488
{
 
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 */
 
1495
 
 
1496
        const char*     s       = id;
 
1497
        int             q;
 
1498
 
 
1499
        if (file_id) {
 
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. */
 
1503
 
 
1504
                if (UNIV_UNLIKELY(idlen > (sizeof nz) - 1)) {
 
1505
                        idlen = (sizeof nz) - 1;
 
1506
                }
 
1507
 
 
1508
                memcpy(nz, id, idlen);
 
1509
                nz[idlen] = 0;
 
1510
 
 
1511
                s = nz2;
 
1512
#if MYSQL_VERSION_ID >= 50141
 
1513
                idlen = explain_filename((THD*) thd, nz, nz2, sizeof nz2,
 
1514
                                         EXPLAIN_PARTITIONS_AS_COMMENT);
 
1515
                goto no_quote;
 
1516
#else /* MYSQL_VERSION_ID >= 50141 */
 
1517
                idlen = filename_to_tablename(nz, nz2, sizeof nz2);
 
1518
#endif /* MYSQL_VERSION_ID >= 50141 */
 
1519
        }
 
1520
 
 
1521
        /* See if the identifier needs to be quoted. */
 
1522
        if (UNIV_UNLIKELY(!thd)) {
 
1523
                q = '"';
 
1524
        } else {
 
1525
                q = get_quote_char_for_identifier((THD*) thd, s, (int) idlen);
 
1526
        }
 
1527
 
 
1528
        if (q == EOF) {
 
1529
#if MYSQL_VERSION_ID >= 50141
 
1530
no_quote:
 
1531
#endif /* MYSQL_VERSION_ID >= 50141 */
 
1532
                if (UNIV_UNLIKELY(idlen > buflen)) {
 
1533
                        idlen = buflen;
 
1534
                }
 
1535
                memcpy(buf, s, idlen);
 
1536
                return(buf + idlen);
 
1537
        }
 
1538
 
 
1539
        /* Quote the identifier. */
 
1540
        if (buflen < 2) {
 
1541
                return(buf);
 
1542
        }
 
1543
 
 
1544
        *buf++ = q;
 
1545
        buflen--;
 
1546
 
 
1547
        for (; idlen; idlen--) {
 
1548
                int     c = *s++;
 
1549
                if (UNIV_UNLIKELY(c == q)) {
 
1550
                        if (UNIV_UNLIKELY(buflen < 3)) {
 
1551
                                break;
 
1552
                        }
 
1553
 
 
1554
                        *buf++ = c;
 
1555
                        *buf++ = c;
 
1556
                        buflen -= 2;
 
1557
                } else {
 
1558
                        if (UNIV_UNLIKELY(buflen < 2)) {
 
1559
                                break;
 
1560
                        }
 
1561
 
 
1562
                        *buf++ = c;
 
1563
                        buflen--;
 
1564
                }
 
1565
        }
 
1566
 
 
1567
        *buf++ = q;
 
1568
        return(buf);
 
1569
}
 
1570
 
 
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 */
 
1575
extern "C"
 
1576
char*
 
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 */
 
1586
{
 
1587
        char*           s       = buf;
 
1588
        const char*     bufend  = buf + buflen;
 
1589
 
 
1590
        if (table_id) {
 
1591
                const char*     slash = (const char*) memchr(id, '/', idlen);
 
1592
                if (!slash) {
 
1593
 
 
1594
                        goto no_db_name;
 
1595
                }
 
1596
 
 
1597
                /* Print the database name and table name separately. */
 
1598
                s = innobase_convert_identifier(s, bufend - s, id, slash - id,
 
1599
                                                thd, TRUE);
 
1600
                if (UNIV_LIKELY(s < bufend)) {
 
1601
                        *s++ = '.';
 
1602
                        s = innobase_convert_identifier(s, bufend - s,
 
1603
                                                        slash + 1, idlen
 
1604
                                                        - (slash - id) - 1,
 
1605
                                                        thd, TRUE);
 
1606
                }
 
1607
        } else {
 
1608
no_db_name:
 
1609
                s = innobase_convert_identifier(buf, buflen, id, idlen,
 
1610
                                                thd, table_id);
 
1611
        }
 
1612
 
 
1613
        return(s);
 
1614
 
 
1615
}
 
1616
 
 
1617
/**************************************************************************
 
1618
Determines if the currently running transaction has been interrupted. */
 
1619
extern "C"
 
1620
ibool
 
1621
trx_is_interrupted(
 
1622
/*===============*/
 
1623
                        /* out: TRUE if interrupted */
 
1624
        trx_t*  trx)    /* in: transaction */
 
1625
{
 
1626
        return(trx && trx->mysql_thd && thd_killed((THD*) trx->mysql_thd));
 
1627
}
 
1628
 
 
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. */
 
1632
static
 
1633
void
 
1634
reset_template(
 
1635
/*===========*/
 
1636
        row_prebuilt_t* prebuilt)       /* in/out: prebuilt struct */
 
1637
{
 
1638
        prebuilt->keep_other_fields_on_keyread = 0;
 
1639
        prebuilt->read_just_key = 0;
 
1640
}
 
1641
 
 
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. */
 
1648
 
 
1649
void
 
1650
ha_innobase::init_table_handle_for_HANDLER(void)
 
1651
/*============================================*/
 
1652
{
 
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. */
 
1657
 
 
1658
        update_thd(ha_thd());
 
1659
 
 
1660
        /* Initialize the prebuilt struct much like it would be inited in
 
1661
        external_lock */
 
1662
 
 
1663
        innobase_release_stat_resources(prebuilt->trx);
 
1664
 
 
1665
        /* If the transaction is not started yet, start it */
 
1666
 
 
1667
        trx_start_if_not_started_noninline(prebuilt->trx);
 
1668
 
 
1669
        /* Assign a read view if the transaction does not have it yet */
 
1670
 
 
1671
        trx_assign_read_view(prebuilt->trx);
 
1672
 
 
1673
        /* Set the MySQL flag to mark that there is an active transaction */
 
1674
 
 
1675
        if (prebuilt->trx->active_trans == 0) {
 
1676
 
 
1677
                innobase_register_trx_and_stmt(ht, user_thd);
 
1678
 
 
1679
                prebuilt->trx->active_trans = 1;
 
1680
        }
 
1681
 
 
1682
        /* We did the necessary inits in this function, no need to repeat them
 
1683
        in row_search_for_mysql */
 
1684
 
 
1685
        prebuilt->sql_stat_start = FALSE;
 
1686
 
 
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 */
 
1689
 
 
1690
        prebuilt->select_lock_type = LOCK_NONE;
 
1691
        prebuilt->stored_select_lock_type = LOCK_NONE;
 
1692
 
 
1693
        /* Always fetch all columns in the index record */
 
1694
 
 
1695
        prebuilt->hint_need_to_fetch_extra_cols = ROW_RETRIEVE_ALL_COLS;
 
1696
 
 
1697
        /* We want always to fetch all columns in the whole row? Or do
 
1698
        we???? */
 
1699
 
 
1700
        prebuilt->used_in_HANDLER = TRUE;
 
1701
        reset_template(prebuilt);
 
1702
}
 
1703
 
 
1704
/*************************************************************************
 
1705
Opens an InnoDB database. */
 
1706
static
 
1707
int
 
1708
innobase_init(
 
1709
/*==========*/
 
1710
                        /* out: 0 on success, error code on failure */
 
1711
        void    *p)     /* in: InnoDB handlerton */
 
1712
{
 
1713
        static char     current_dir[3];         /* Set if using current lib */
 
1714
        int             err;
 
1715
        bool            ret;
 
1716
        char            *default_path;
 
1717
 
 
1718
        DBUG_ENTER("innobase_init");
 
1719
        handlerton *innobase_hton= (handlerton *)p;
 
1720
        innodb_hton_ptr = innobase_hton;
 
1721
 
 
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;
 
1746
 
 
1747
        ut_a(DATA_MYSQL_TRUE_VARCHAR == (ulint)MYSQL_TYPE_VARCHAR);
 
1748
 
 
1749
#ifdef UNIV_DEBUG
 
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,
 
1761
                        test_filename)) {
 
1762
                sql_print_error("tablename encoding has been changed");
 
1763
                goto error;
 
1764
        }
 
1765
#endif /* UNIV_DEBUG */
 
1766
 
 
1767
        /* Check that values don't overflow on 32-bit systems. */
 
1768
        if (sizeof(ulint) == 4) {
 
1769
                if (innobase_buffer_pool_size > UINT_MAX32) {
 
1770
                        sql_print_error(
 
1771
                                "innobase_buffer_pool_size can't be over 4GB"
 
1772
                                " on 32-bit systems");
 
1773
 
 
1774
                        goto error;
 
1775
                }
 
1776
 
 
1777
                if (innobase_log_file_size > UINT_MAX32) {
 
1778
                        sql_print_error(
 
1779
                                "innobase_log_file_size can't be over 4GB"
 
1780
                                " on 32-bit systems");
 
1781
 
 
1782
                        goto error;
 
1783
                }
 
1784
        }
 
1785
 
 
1786
        os_innodb_umask = (ulint)my_umask;
 
1787
 
 
1788
        /* First calculate the default path for innodb_data_home_dir etc.,
 
1789
        in case the user has not given any value.
 
1790
 
 
1791
        Note that when using the embedded server, the datadirectory is not
 
1792
        necessarily the current directory of this program. */
 
1793
 
 
1794
        if (mysqld_embedded) {
 
1795
                default_path = mysql_real_data_home;
 
1796
                fil_path_to_mysql_datadir = mysql_real_data_home;
 
1797
        } else {
 
1798
                /* It's better to use current lib, to keep paths short */
 
1799
                current_dir[0] = FN_CURLIB;
 
1800
                current_dir[1] = FN_LIBCHAR;
 
1801
                current_dir[2] = 0;
 
1802
                default_path = current_dir;
 
1803
        }
 
1804
 
 
1805
        ut_a(default_path);
 
1806
 
 
1807
        if (specialflag & SPECIAL_NO_PRIOR) {
 
1808
                srv_set_thread_priorities = FALSE;
 
1809
        } else {
 
1810
                srv_set_thread_priorities = TRUE;
 
1811
                srv_query_thread_priority = QUERY_PRIOR;
 
1812
        }
 
1813
 
 
1814
        /* Set InnoDB initialization parameters according to the values
 
1815
        read from MySQL .cnf file */
 
1816
 
 
1817
        /*--------------- Data files -------------------------*/
 
1818
 
 
1819
        /* The default dir for data files is the datadir of MySQL */
 
1820
 
 
1821
        srv_data_home = (innobase_data_home_dir ? innobase_data_home_dir :
 
1822
                         default_path);
 
1823
 
 
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. */
 
1827
 
 
1828
        if (!innobase_data_file_path) {
 
1829
                innobase_data_file_path = (char*) "ibdata1:10M:autoextend";
 
1830
        }
 
1831
 
 
1832
        /* Since InnoDB edits the argument in the next call, we make another
 
1833
        copy of it: */
 
1834
 
 
1835
        internal_innobase_data_file_path = my_strdup(innobase_data_file_path,
 
1836
                                                   MYF(MY_FAE));
 
1837
 
 
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,
 
1843
                                &srv_n_data_files,
 
1844
                                &srv_auto_extend_last_data_file,
 
1845
                                &srv_last_file_size_max);
 
1846
        if (ret == FALSE) {
 
1847
                sql_print_error(
 
1848
                        "InnoDB: syntax error in innodb_data_file_path");
 
1849
                my_free(internal_innobase_data_file_path,
 
1850
                                                MYF(MY_ALLOW_ZERO_PTR));
 
1851
                goto error;
 
1852
        }
 
1853
 
 
1854
        /* -------------- Log files ---------------------------*/
 
1855
 
 
1856
        /* The default dir for log files is the datadir of MySQL */
 
1857
 
 
1858
        if (!innobase_log_group_home_dir) {
 
1859
                innobase_log_group_home_dir = default_path;
 
1860
        }
 
1861
 
 
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: */
 
1866
 
 
1867
        innobase_log_arch_dir = innobase_log_group_home_dir;
 
1868
 
 
1869
        srv_arch_dir = innobase_log_arch_dir;
 
1870
#endif /* UNIG_LOG_ARCHIVE */
 
1871
 
 
1872
        ret = (bool)
 
1873
                srv_parse_log_group_home_dirs(innobase_log_group_home_dir,
 
1874
                                                &srv_log_group_home_dirs);
 
1875
 
 
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");
 
1879
 
 
1880
                my_free(internal_innobase_data_file_path,
 
1881
                                                MYF(MY_ALLOW_ZERO_PTR));
 
1882
                goto error;
 
1883
        }
 
1884
 
 
1885
        /* --------------------------------------------------*/
 
1886
 
 
1887
        srv_file_flush_method_str = innobase_unix_file_flush_method;
 
1888
 
 
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;
 
1892
 
 
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;
 
1897
 
 
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. */
 
1900
 
 
1901
        if (innobase_buffer_pool_awe_mem_mb == 0) {
 
1902
                srv_pool_size = (ulint)(innobase_buffer_pool_size / 1024);
 
1903
        } else {
 
1904
                srv_use_awe = TRUE;
 
1905
                srv_pool_size = (ulint)
 
1906
                                (1024 * innobase_buffer_pool_awe_mem_mb);
 
1907
                srv_awe_window_size = (ulint) innobase_buffer_pool_size;
 
1908
 
 
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. */
 
1913
        }
 
1914
 
 
1915
        srv_mem_pool_size = (ulint) innobase_additional_mem_pool_size;
 
1916
 
 
1917
        srv_n_file_io_threads = (ulint) innobase_file_io_threads;
 
1918
 
 
1919
        srv_lock_wait_timeout = (ulint) innobase_lock_wait_timeout;
 
1920
        srv_force_recovery = (ulint) innobase_force_recovery;
 
1921
 
 
1922
        srv_use_doublewrite_buf = (ibool) innobase_use_doublewrite;
 
1923
        srv_use_checksums = (ibool) innobase_use_checksums;
 
1924
 
 
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;
 
1928
#endif
 
1929
 
 
1930
        row_rollback_on_timeout = (ibool) innobase_rollback_on_timeout;
 
1931
 
 
1932
        srv_file_per_table = (ibool) innobase_file_per_table;
 
1933
        srv_locks_unsafe_for_binlog = (ibool) innobase_locks_unsafe_for_binlog;
 
1934
 
 
1935
        srv_max_n_open_files = (ulint) innobase_open_files;
 
1936
        srv_innodb_status = (ibool) innobase_create_status_file;
 
1937
 
 
1938
        srv_use_adaptive_hash_indexes =
 
1939
                (ibool) innobase_adaptive_hash_index;
 
1940
 
 
1941
        srv_print_verbose_log = mysqld_embedded ? 0 : 1;
 
1942
 
 
1943
        /* Store the default charset-collation number of this MySQL
 
1944
        installation */
 
1945
 
 
1946
        data_mysql_default_charset_coll = (ulint)default_charset_info->number;
 
1947
 
 
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);
 
1951
 
 
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
 
1955
        InnoDB. */
 
1956
 
 
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);
 
1960
 
 
1961
        innobase_commit_concurrency_init_default();
 
1962
 
 
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. */
 
1968
 
 
1969
        srv_sizeof_trx_t_in_ha_innodb_cc = sizeof(trx_t);
 
1970
 
 
1971
        err = innobase_start_or_create_for_mysql();
 
1972
 
 
1973
        if (err != DB_SUCCESS) {
 
1974
                my_free(internal_innobase_data_file_path,
 
1975
                                                MYF(MY_ALLOW_ZERO_PTR));
 
1976
                goto error;
 
1977
        }
 
1978
 
 
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);
 
1987
        innodb_inited= 1;
 
1988
 
 
1989
        DBUG_RETURN(FALSE);
 
1990
error:
 
1991
        DBUG_RETURN(TRUE);
 
1992
}
 
1993
 
 
1994
/***********************************************************************
 
1995
Closes an InnoDB database. */
 
1996
static
 
1997
int
 
1998
innobase_end(handlerton *hton, ha_panic_function type)
 
1999
/*==============*/
 
2000
                                /* out: TRUE if error */
 
2001
{
 
2002
        int     err= 0;
 
2003
 
 
2004
        DBUG_ENTER("innobase_end");
 
2005
 
 
2006
#ifdef __NETWARE__      /* some special cleanup for NetWare */
 
2007
        if (nw_panic) {
 
2008
                set_panic_flag_for_netware();
 
2009
        }
 
2010
#endif
 
2011
        if (innodb_inited) {
 
2012
 
 
2013
                srv_fast_shutdown = (ulint) innobase_fast_shutdown;
 
2014
                innodb_inited = 0;
 
2015
                if (innobase_shutdown_for_mysql() != DB_SUCCESS) {
 
2016
                        err = 1;
 
2017
                }
 
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);
 
2027
        }
 
2028
 
 
2029
        DBUG_RETURN(err);
 
2030
}
 
2031
 
 
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. */
 
2035
static
 
2036
bool
 
2037
innobase_flush_logs(handlerton *hton)
 
2038
/*=====================*/
 
2039
                                /* out: TRUE if error */
 
2040
{
 
2041
        bool    result = 0;
 
2042
 
 
2043
        DBUG_ENTER("innobase_flush_logs");
 
2044
 
 
2045
        log_buffer_flush_to_disk();
 
2046
 
 
2047
        DBUG_RETURN(result);
 
2048
}
 
2049
 
 
2050
/*********************************************************************
 
2051
Commits a transaction in an InnoDB database. */
 
2052
static
 
2053
void
 
2054
innobase_commit_low(
 
2055
/*================*/
 
2056
        trx_t*  trx)    /* in: transaction handle */
 
2057
{
 
2058
        if (trx->conc_state == TRX_NOT_STARTED) {
 
2059
 
 
2060
                return;
 
2061
        }
 
2062
 
 
2063
        trx_commit_for_mysql(trx);
 
2064
}
 
2065
 
 
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
 
2070
have one. */
 
2071
static
 
2072
int
 
2073
innobase_start_trx_and_assign_read_view(
 
2074
/*====================================*/
 
2075
                        /* out: 0 */
 
2076
        handlerton *hton, /* in: Innodb handlerton */ 
 
2077
        THD*    thd)    /* in: MySQL thread handle of the user for whom
 
2078
                        the transaction should be committed */
 
2079
{
 
2080
        trx_t*  trx;
 
2081
 
 
2082
        DBUG_ENTER("innobase_start_trx_and_assign_read_view");
 
2083
 
 
2084
        /* Create a new trx struct for thd, if it does not yet have one */
 
2085
 
 
2086
        trx = check_trx_exists(thd);
 
2087
 
 
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. */
 
2091
 
 
2092
        innobase_release_stat_resources(trx);
 
2093
 
 
2094
        /* If the transaction is not started yet, start it */
 
2095
 
 
2096
        trx_start_if_not_started_noninline(trx);
 
2097
 
 
2098
        /* Assign a read view if the transaction does not have it yet */
 
2099
 
 
2100
        trx_assign_read_view(trx);
 
2101
 
 
2102
        /* Set the MySQL flag to mark that there is an active transaction */
 
2103
 
 
2104
        if (trx->active_trans == 0) {
 
2105
                innobase_register_trx_and_stmt(hton, current_thd);
 
2106
                trx->active_trans = 1;
 
2107
        }
 
2108
 
 
2109
        DBUG_RETURN(0);
 
2110
}
 
2111
 
 
2112
/*********************************************************************
 
2113
Commits a transaction in an InnoDB database or marks an SQL statement
 
2114
ended. */
 
2115
static
 
2116
int
 
2117
innobase_commit(
 
2118
/*============*/
 
2119
                        /* out: 0 */
 
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 */
 
2125
{
 
2126
        trx_t*          trx;
 
2127
 
 
2128
        DBUG_ENTER("innobase_commit");
 
2129
        DBUG_PRINT("trans", ("ending transaction"));
 
2130
 
 
2131
        trx = check_trx_exists(thd);
 
2132
 
 
2133
        /* Update the info whether we should skip XA steps that eat CPU time */
 
2134
        trx->support_xa = THDVAR(thd, support_xa);
 
2135
 
 
2136
        /* Since we will reserve the kernel mutex, we have to release
 
2137
        the search system latch first to obey the latching order. */
 
2138
 
 
2139
        if (trx->has_search_latch) {
 
2140
                trx_search_latch_release_if_reserved(trx);
 
2141
        }
 
2142
 
 
2143
        /* The flag trx->active_trans is set to 1 in
 
2144
 
 
2145
        1. ::external_lock(),
 
2146
        2. ::start_stmt(),
 
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()
 
2152
 
 
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. */
 
2157
 
 
2158
        if (trx->active_trans == 0
 
2159
                && trx->conc_state != TRX_NOT_STARTED) {
 
2160
 
 
2161
                sql_print_error("trx->active_trans == 0, but"
 
2162
                        " trx->conc_state != TRX_NOT_STARTED");
 
2163
        }
 
2164
        if (all
 
2165
                || (!thd_test_options(thd, OPTION_NOT_AUTOCOMMIT | OPTION_BEGIN))) {
 
2166
 
 
2167
                /* We were instructed to commit the whole transaction, or
 
2168
                this is an SQL statement end and autocommit is on */
 
2169
 
 
2170
                /* We need current binlog position for ibbackup to work.
 
2171
                Note, the position is current because of
 
2172
                prepare_commit_mutex */
 
2173
retry:
 
2174
                if (innobase_commit_concurrency > 0) {
 
2175
                        pthread_mutex_lock(&commit_cond_m);
 
2176
                        commit_threads++;
 
2177
 
 
2178
                        if (commit_threads > innobase_commit_concurrency) {
 
2179
                                commit_threads--;
 
2180
                                pthread_cond_wait(&commit_cond,
 
2181
                                        &commit_cond_m);
 
2182
                                pthread_mutex_unlock(&commit_cond_m);
 
2183
                                goto retry;
 
2184
                        }
 
2185
                        else {
 
2186
                                pthread_mutex_unlock(&commit_cond_m);
 
2187
                        }
 
2188
                }
 
2189
 
 
2190
                trx->mysql_log_file_name = mysql_bin_log_file_name();
 
2191
                trx->mysql_log_offset = (ib_longlong) mysql_bin_log_file_pos();
 
2192
 
 
2193
                innobase_commit_low(trx);
 
2194
 
 
2195
                if (innobase_commit_concurrency > 0) {
 
2196
                        pthread_mutex_lock(&commit_cond_m);
 
2197
                        commit_threads--;
 
2198
                        pthread_cond_signal(&commit_cond);
 
2199
                        pthread_mutex_unlock(&commit_cond_m);
 
2200
                }
 
2201
 
 
2202
                if (trx->active_trans == 2) {
 
2203
 
 
2204
                        pthread_mutex_unlock(&prepare_commit_mutex);
 
2205
                }
 
2206
 
 
2207
                trx->active_trans = 0;
 
2208
 
 
2209
        } else {
 
2210
                /* We just mark the SQL statement ended and do not do a
 
2211
                transaction commit */
 
2212
 
 
2213
                /* If we had reserved the auto-inc lock for some
 
2214
                table in this SQL statement we release it now */
 
2215
 
 
2216
                row_unlock_table_autoinc_for_mysql(trx);
 
2217
 
 
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
 
2220
                SQL statement */
 
2221
 
 
2222
                trx_mark_sql_stat_end(trx);
 
2223
        }
 
2224
 
 
2225
        trx->n_autoinc_rows = 0; /* Reset the number AUTO-INC rows required */
 
2226
 
 
2227
        if (trx->declared_to_be_inside_innodb) {
 
2228
                /* Release our possible ticket in the FIFO */
 
2229
 
 
2230
                srv_conc_force_exit_innodb(trx);
 
2231
        }
 
2232
 
 
2233
        /* Tell the InnoDB server that there might be work for utility
 
2234
        threads: */
 
2235
        srv_active_wake_master_thread();
 
2236
 
 
2237
        DBUG_RETURN(0);
 
2238
}
 
2239
 
 
2240
/*********************************************************************
 
2241
Rolls back a transaction or the latest SQL statement. */
 
2242
static
 
2243
int
 
2244
innobase_rollback(
 
2245
/*==============*/
 
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 */
 
2252
{
 
2253
        int     error = 0;
 
2254
        trx_t*  trx;
 
2255
 
 
2256
        DBUG_ENTER("innobase_rollback");
 
2257
        DBUG_PRINT("trans", ("aborting transaction"));
 
2258
 
 
2259
        trx = check_trx_exists(thd);
 
2260
 
 
2261
        /* Update the info whether we should skip XA steps that eat CPU time */
 
2262
        trx->support_xa = THDVAR(thd, support_xa);
 
2263
 
 
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. */
 
2267
 
 
2268
        innobase_release_stat_resources(trx);
 
2269
 
 
2270
        trx->n_autoinc_rows = 0; /* Reset the number AUTO-INC rows required */
 
2271
 
 
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 */
 
2275
 
 
2276
        row_unlock_table_autoinc_for_mysql(trx);
 
2277
 
 
2278
        if (all
 
2279
                || !thd_test_options(thd, OPTION_NOT_AUTOCOMMIT | OPTION_BEGIN)) {
 
2280
 
 
2281
                error = trx_rollback_for_mysql(trx);
 
2282
                trx->active_trans = 0;
 
2283
        } else {
 
2284
                error = trx_rollback_last_sql_stat_for_mysql(trx);
 
2285
        }
 
2286
 
 
2287
        DBUG_RETURN(convert_error_code_to_mysql(error, NULL));
 
2288
}
 
2289
 
 
2290
/*********************************************************************
 
2291
Rolls back a transaction */
 
2292
static
 
2293
int
 
2294
innobase_rollback_trx(
 
2295
/*==================*/
 
2296
                        /* out: 0 or error number */
 
2297
        trx_t*  trx)    /*  in: transaction */
 
2298
{
 
2299
        int     error = 0;
 
2300
 
 
2301
        DBUG_ENTER("innobase_rollback_trx");
 
2302
        DBUG_PRINT("trans", ("aborting transaction"));
 
2303
 
 
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. */
 
2307
 
 
2308
        innobase_release_stat_resources(trx);
 
2309
 
 
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 */
 
2313
 
 
2314
        row_unlock_table_autoinc_for_mysql(trx);
 
2315
 
 
2316
        error = trx_rollback_for_mysql(trx);
 
2317
 
 
2318
        DBUG_RETURN(convert_error_code_to_mysql(error, NULL));
 
2319
}
 
2320
 
 
2321
/*********************************************************************
 
2322
Rolls back a transaction to a savepoint. */
 
2323
static
 
2324
int
 
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 */
 
2333
{
 
2334
        ib_longlong     mysql_binlog_cache_pos;
 
2335
        int             error = 0;
 
2336
        trx_t*          trx;
 
2337
        char            name[64];
 
2338
 
 
2339
        DBUG_ENTER("innobase_rollback_to_savepoint");
 
2340
 
 
2341
        trx = check_trx_exists(thd);
 
2342
 
 
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. */
 
2346
 
 
2347
        innobase_release_stat_resources(trx);
 
2348
 
 
2349
        /* TODO: use provided savepoint data area to store savepoint data */
 
2350
 
 
2351
        longlong2str((ulint)savepoint, name, 36);
 
2352
 
 
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));
 
2356
}
 
2357
 
 
2358
/*********************************************************************
 
2359
Release transaction savepoint name. */
 
2360
static
 
2361
int
 
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 */
 
2370
{
 
2371
        int             error = 0;
 
2372
        trx_t*          trx;
 
2373
        char            name[64];
 
2374
 
 
2375
        DBUG_ENTER("innobase_release_savepoint");
 
2376
 
 
2377
        trx = check_trx_exists(thd);
 
2378
 
 
2379
        /* TODO: use provided savepoint data area to store savepoint data */
 
2380
 
 
2381
        longlong2str((ulint)savepoint, name, 36);
 
2382
 
 
2383
        error = (int) trx_release_savepoint_for_mysql(trx, name);
 
2384
 
 
2385
        DBUG_RETURN(convert_error_code_to_mysql(error, NULL));
 
2386
}
 
2387
 
 
2388
/*********************************************************************
 
2389
Sets a transaction savepoint. */
 
2390
static
 
2391
int
 
2392
innobase_savepoint(
 
2393
/*===============*/
 
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 */
 
2398
{
 
2399
        int     error = 0;
 
2400
        trx_t*  trx;
 
2401
 
 
2402
        DBUG_ENTER("innobase_savepoint");
 
2403
 
 
2404
        /*
 
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.
 
2408
        */
 
2409
#ifdef MYSQL_SERVER /* plugins cannot access thd->in_sub_stmt */
 
2410
        DBUG_ASSERT(thd_test_options(thd, OPTION_NOT_AUTOCOMMIT | OPTION_BEGIN) ||
 
2411
                thd->in_sub_stmt);
 
2412
#endif /* MYSQL_SERVER */
 
2413
 
 
2414
        trx = check_trx_exists(thd);
 
2415
 
 
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. */
 
2419
 
 
2420
        innobase_release_stat_resources(trx);
 
2421
 
 
2422
        /* cannot happen outside of transaction */
 
2423
        DBUG_ASSERT(trx->active_trans);
 
2424
 
 
2425
        /* TODO: use provided savepoint data area to store savepoint data */
 
2426
        char name[64];
 
2427
        longlong2str((ulint)savepoint,name,36);
 
2428
 
 
2429
        error = (int) trx_savepoint_for_mysql(trx, name, (ib_longlong)0);
 
2430
 
 
2431
        DBUG_RETURN(convert_error_code_to_mysql(error, NULL));
 
2432
}
 
2433
 
 
2434
/*********************************************************************
 
2435
Frees a possible InnoDB trx object associated with the current THD. */
 
2436
static
 
2437
int
 
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 */
 
2444
{
 
2445
        trx_t*  trx;
 
2446
 
 
2447
        DBUG_ENTER("innobase_close_connection");
 
2448
        DBUG_ASSERT(hton == innodb_hton_ptr);
 
2449
        trx = thd_to_trx(thd);
 
2450
 
 
2451
        ut_a(trx);
 
2452
 
 
2453
        if (trx->active_trans == 0
 
2454
                && trx->conc_state != TRX_NOT_STARTED) {
 
2455
 
 
2456
                sql_print_error("trx->active_trans == 0, but"
 
2457
                        " trx->conc_state != TRX_NOT_STARTED");
 
2458
        }
 
2459
 
 
2460
 
 
2461
        if (trx->conc_state != TRX_NOT_STARTED &&
 
2462
                global_system_variables.log_warnings) {
 
2463
                sql_print_warning(
 
2464
                        "MySQL is closing a connection that has an active "
 
2465
                        "InnoDB transaction.  %lu row modifications will "
 
2466
                        "roll back.",
 
2467
                        (ulong) trx->undo_no.low);
 
2468
        }
 
2469
 
 
2470
        innobase_rollback_trx(trx);
 
2471
 
 
2472
        thr_local_free(trx->mysql_thread_id);
 
2473
        trx_free_for_mysql(trx);
 
2474
 
 
2475
        DBUG_RETURN(0);
 
2476
}
 
2477
 
 
2478
 
 
2479
/*****************************************************************************
 
2480
** InnoDB database tables
 
2481
*****************************************************************************/
 
2482
 
 
2483
/********************************************************************
 
2484
Get the record format from the data dictionary. */
 
2485
enum row_type
 
2486
ha_innobase::get_row_type() const
 
2487
/*=============================*/
 
2488
                        /* out: ROW_TYPE_REDUNDANT or ROW_TYPE_COMPACT */
 
2489
{
 
2490
        if (prebuilt && prebuilt->table) {
 
2491
                if (dict_table_is_comp_noninline(prebuilt->table)) {
 
2492
                        return(ROW_TYPE_COMPACT);
 
2493
                } else {
 
2494
                        return(ROW_TYPE_REDUNDANT);
 
2495
                }
 
2496
        }
 
2497
        ut_ad(0);
 
2498
        return(ROW_TYPE_NOT_USED);
 
2499
}
 
2500
 
 
2501
 
 
2502
 
 
2503
/********************************************************************
 
2504
Get the table flags to use for the statement. */
 
2505
handler::Table_flags
 
2506
ha_innobase::table_flags() const
 
2507
{
 
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;
 
2514
}
 
2515
 
 
2516
/********************************************************************
 
2517
Gives the file extension of an InnoDB single-table tablespace. */
 
2518
static const char* ha_innobase_exts[] = {
 
2519
  ".ibd",
 
2520
  NullS
 
2521
};
 
2522
 
 
2523
const char**
 
2524
ha_innobase::bas_ext() const
 
2525
/*========================*/
 
2526
                                /* out: file extension string */
 
2527
{
 
2528
  return ha_innobase_exts;
 
2529
}
 
2530
 
 
2531
 
 
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. */
 
2537
static
 
2538
void
 
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 */
 
2544
{
 
2545
        char*   name_ptr;
 
2546
        char*   db_ptr;
 
2547
        char*   ptr;
 
2548
 
 
2549
        /* Scan name from the end */
 
2550
 
 
2551
        ptr = strend(name)-1;
 
2552
 
 
2553
        while (ptr >= name && *ptr != '\\' && *ptr != '/') {
 
2554
                ptr--;
 
2555
        }
 
2556
 
 
2557
        name_ptr = ptr + 1;
 
2558
 
 
2559
        DBUG_ASSERT(ptr > name);
 
2560
 
 
2561
        ptr--;
 
2562
 
 
2563
        while (ptr >= name && *ptr != '\\' && *ptr != '/') {
 
2564
                ptr--;
 
2565
        }
 
2566
 
 
2567
        db_ptr = ptr + 1;
 
2568
 
 
2569
        memcpy(norm_name, db_ptr, strlen(name) + 1 - (db_ptr - name));
 
2570
 
 
2571
        norm_name[name_ptr - db_ptr - 1] = '/';
 
2572
 
 
2573
#ifdef __WIN__
 
2574
        innobase_casedn_str(norm_name);
 
2575
#endif
 
2576
}
 
2577
 
 
2578
/************************************************************************
 
2579
Get the upper limit of the MySQL integral and floating-point type. */
 
2580
static
 
2581
ulonglong
 
2582
innobase_get_int_col_max_value(
 
2583
/*===========================*/
 
2584
                                /* out: maximum allowed value for the field */
 
2585
        const Field*    field)  /* in: MySQL field */
 
2586
{
 
2587
        ulonglong       max_value = 0;
 
2588
 
 
2589
        switch(field->key_type()) {
 
2590
        /* TINY */
 
2591
        case HA_KEYTYPE_BINARY:
 
2592
                max_value = 0xFFULL;
 
2593
                break;
 
2594
        case HA_KEYTYPE_INT8:
 
2595
                max_value = 0x7FULL;
 
2596
                break;
 
2597
        /* SHORT */
 
2598
        case HA_KEYTYPE_USHORT_INT:
 
2599
                max_value = 0xFFFFULL;
 
2600
                break;
 
2601
        case HA_KEYTYPE_SHORT_INT:
 
2602
                max_value = 0x7FFFULL;
 
2603
                break;
 
2604
        /* MEDIUM */
 
2605
        case HA_KEYTYPE_UINT24:
 
2606
                max_value = 0xFFFFFFULL;
 
2607
                break;
 
2608
        case HA_KEYTYPE_INT24:
 
2609
                max_value = 0x7FFFFFULL;
 
2610
                break;
 
2611
        /* LONG */
 
2612
        case HA_KEYTYPE_ULONG_INT:
 
2613
                max_value = 0xFFFFFFFFULL;
 
2614
                break;
 
2615
        case HA_KEYTYPE_LONG_INT:
 
2616
                max_value = 0x7FFFFFFFULL;
 
2617
                break;
 
2618
        /* BIG */
 
2619
        case HA_KEYTYPE_ULONGLONG:
 
2620
                max_value = 0xFFFFFFFFFFFFFFFFULL;
 
2621
                break;
 
2622
        case HA_KEYTYPE_LONGLONG:
 
2623
                max_value = 0x7FFFFFFFFFFFFFFFULL;
 
2624
                break;
 
2625
        case HA_KEYTYPE_FLOAT:
 
2626
                /* We use the maximum as per IEEE754-2008 standard, 2^24 */
 
2627
                max_value = 0x1000000ULL;
 
2628
                break;
 
2629
        case HA_KEYTYPE_DOUBLE:
 
2630
                /* We use the maximum as per IEEE754-2008 standard, 2^53 */
 
2631
                max_value = 0x20000000000000ULL;
 
2632
                break;
 
2633
        default:
 
2634
                ut_error;
 
2635
        }
 
2636
 
 
2637
        return(max_value);
 
2638
}
 
2639
 
 
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. */
 
2643
 
 
2644
void
 
2645
ha_innobase::innobase_initialize_autoinc()
 
2646
/*======================================*/
 
2647
{
 
2648
        ulonglong       auto_inc;
 
2649
        const Field*    field = table->found_next_number_field;
 
2650
 
 
2651
        if (field != NULL) {
 
2652
                auto_inc = innobase_get_int_col_max_value(field);
 
2653
        } else {
 
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. */
 
2657
                auto_inc = 0;
 
2658
 
 
2659
                ut_print_timestamp(stderr);
 
2660
                fprintf(stderr, "  InnoDB: Unable to determine the AUTOINC "
 
2661
                                "column name\n");
 
2662
        }
 
2663
 
 
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.
 
2670
 
 
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. */
 
2675
                auto_inc = 0;
 
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));
 
2680
        } else {
 
2681
                dict_index_t*   index;
 
2682
                const char*     col_name;
 
2683
                ulonglong       read_auto_inc;
 
2684
                ulint           err;
 
2685
 
 
2686
                update_thd(ha_thd());
 
2687
                col_name = field->field_name;
 
2688
                index = innobase_get_index(table->s->next_number_index);
 
2689
 
 
2690
                /* Execute SELECT MAX(col_name) FROM TABLE; */
 
2691
                err = row_search_max_autoinc(index, col_name, &read_auto_inc);
 
2692
 
 
2693
                switch (err) {
 
2694
                case DB_SUCCESS:
 
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;
 
2698
                        break;
 
2699
 
 
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 "
 
2707
                                "value to 0,\n"
 
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);
 
2715
 
 
2716
                        /* This will disable the AUTOINC generation. */
 
2717
                        auto_inc = 0;
 
2718
 
 
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. */
 
2722
                        err = DB_SUCCESS;
 
2723
                        break;
 
2724
                default:
 
2725
                        /* row_search_max_autoinc() should only return
 
2726
                        one of DB_SUCCESS or DB_RECORD_NOT_FOUND. */
 
2727
                        ut_error;
 
2728
                }
 
2729
        }
 
2730
 
 
2731
        dict_table_autoinc_initialize(prebuilt->table, auto_inc);
 
2732
}
 
2733
 
 
2734
/*********************************************************************
 
2735
Creates and opens a handle to a table which already exists in an InnoDB
 
2736
database. */
 
2737
 
 
2738
int
 
2739
ha_innobase::open(
 
2740
/*==============*/
 
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 */
 
2745
{
 
2746
        dict_table_t*   ib_table;
 
2747
        char            norm_name[1000];
 
2748
        THD*            thd;
 
2749
        ulint           retries = 0;
 
2750
        char*           is_part = NULL;
 
2751
 
 
2752
        DBUG_ENTER("ha_innobase::open");
 
2753
 
 
2754
        UT_NOT_USED(mode);
 
2755
        UT_NOT_USED(test_if_locked);
 
2756
 
 
2757
        thd = ha_thd();
 
2758
 
 
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. */
 
2762
        if (thd != NULL) {
 
2763
                innobase_release_temporary_latches(ht, thd);
 
2764
        }
 
2765
 
 
2766
        normalize_table_name(norm_name, name);
 
2767
 
 
2768
        user_thd = NULL;
 
2769
 
 
2770
        if (!(share=get_share(name))) {
 
2771
 
 
2772
                DBUG_RETURN(1);
 
2773
        }
 
2774
 
 
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. */
 
2779
 
 
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,
 
2786
                        NullS)) {
 
2787
                free_share(share);
 
2788
 
 
2789
                DBUG_RETURN(1);
 
2790
        }
 
2791
 
 
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#");
 
2798
retry:
 
2799
        /* Get pointer to a table object in InnoDB dictionary cache */
 
2800
        ib_table = dict_table_get(norm_name, TRUE);
 
2801
        
 
2802
        if (NULL == ib_table) {
 
2803
                if (is_part && retries < 10) {
 
2804
                        ++retries;
 
2805
                        os_thread_sleep(100000);
 
2806
                        goto retry;
 
2807
                }
 
2808
 
 
2809
                if (is_part) {
 
2810
                        sql_print_error("Failed to open table %s after "
 
2811
                                        "%lu attemtps.\n", norm_name,
 
2812
                                        retries);
 
2813
                }
 
2814
 
 
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",
 
2829
                                norm_name);
 
2830
                free_share(share);
 
2831
                my_free(upd_buff, MYF(0));
 
2832
                my_errno = ENOENT;
 
2833
 
 
2834
                DBUG_RETURN(HA_ERR_NO_SUCH_TABLE);
 
2835
        }
 
2836
 
 
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",
 
2845
                                norm_name);
 
2846
                free_share(share);
 
2847
                my_free(upd_buff, MYF(0));
 
2848
                my_errno = ENOENT;
 
2849
 
 
2850
                dict_table_decrement_handle_count(ib_table);
 
2851
                DBUG_RETURN(HA_ERR_NO_SUCH_TABLE);
 
2852
        }
 
2853
 
 
2854
        prebuilt = row_create_prebuilt(ib_table);
 
2855
 
 
2856
        prebuilt->mysql_row_len = table->s->reclength;
 
2857
        prebuilt->default_rec = table->s->default_values;
 
2858
        ut_ad(prebuilt->default_rec);
 
2859
 
 
2860
        /* Looks like MySQL-3.23 sometimes has primary key number != 0 */
 
2861
 
 
2862
        primary_key = table->s->primary_key;
 
2863
        key_used_on_scan = primary_key;
 
2864
 
 
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! */
 
2870
 
 
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);
 
2875
                }
 
2876
 
 
2877
                prebuilt->clust_index_was_generated = FALSE;
 
2878
 
 
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. */
 
2884
 
 
2885
                ref_length = table->key_info[primary_key].key_length;
 
2886
        } else {
 
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);
 
2897
                }
 
2898
 
 
2899
                prebuilt->clust_index_was_generated = TRUE;
 
2900
 
 
2901
                ref_length = DATA_ROW_ID_LEN;
 
2902
 
 
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. */
 
2910
 
 
2911
                if (key_used_on_scan != MAX_KEY) {
 
2912
                        sql_print_warning(
 
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);
 
2916
                }
 
2917
        }
 
2918
 
 
2919
        stats.block_size = 16 * 1024;   /* Index block size in InnoDB: used by MySQL
 
2920
                                in query optimization */
 
2921
 
 
2922
        /* Init table lock structure */
 
2923
        thr_lock_data_init(&share->lock,&lock,(void*) 0);
 
2924
 
 
2925
        info(HA_STATUS_NO_LOCK | HA_STATUS_VARIABLE | HA_STATUS_CONST);
 
2926
 
 
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);
 
2930
 
 
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) {
 
2936
 
 
2937
                        innobase_initialize_autoinc();
 
2938
                }
 
2939
 
 
2940
                dict_table_autoinc_unlock(prebuilt->table);
 
2941
        }
 
2942
 
 
2943
        DBUG_RETURN(0);
 
2944
}
 
2945
 
 
2946
uint
 
2947
ha_innobase::max_supported_key_part_length() const
 
2948
{
 
2949
        return(DICT_MAX_INDEX_COL_LEN - 1);
 
2950
}
 
2951
 
 
2952
/**********************************************************************
 
2953
Closes a handle to an InnoDB table. */
 
2954
 
 
2955
int
 
2956
ha_innobase::close(void)
 
2957
/*====================*/
 
2958
                                /* out: 0 */
 
2959
{
 
2960
        THD*    thd;
 
2961
 
 
2962
        DBUG_ENTER("ha_innobase::close");
 
2963
 
 
2964
        thd = current_thd;  // avoid calling current_thd twice, it may be slow
 
2965
        if (thd != NULL) {
 
2966
                innobase_release_temporary_latches(ht, thd);
 
2967
        }
 
2968
 
 
2969
        row_prebuilt_free(prebuilt);
 
2970
 
 
2971
        my_free(upd_buff, MYF(0));
 
2972
        free_share(share);
 
2973
 
 
2974
        /* Tell InnoDB server that there might be work for
 
2975
        utility threads: */
 
2976
 
 
2977
        srv_active_wake_master_thread();
 
2978
 
 
2979
        DBUG_RETURN(0);
 
2980
}
 
2981
 
 
2982
/* The following accessor functions should really be inside MySQL code! */
 
2983
 
 
2984
/******************************************************************
 
2985
Gets field offset for a field in a table. */
 
2986
inline
 
2987
uint
 
2988
get_field_offset(
 
2989
/*=============*/
 
2990
                        /* out: offset */
 
2991
        TABLE*  table,  /* in: MySQL table object */
 
2992
        Field*  field)  /* in: MySQL field object */
 
2993
{
 
2994
        return((uint) (field->ptr - table->record[0]));
 
2995
}
 
2996
 
 
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. */
 
3000
static inline
 
3001
uint
 
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 */
 
3008
{
 
3009
        int     null_offset;
 
3010
 
 
3011
        if (!field->null_ptr) {
 
3012
 
 
3013
                return(0);
 
3014
        }
 
3015
 
 
3016
        null_offset = (uint) ((char*) field->null_ptr
 
3017
                                        - (char*) table->record[0]);
 
3018
 
 
3019
        if (record[null_offset] & field->null_bit) {
 
3020
 
 
3021
                return(1);
 
3022
        }
 
3023
 
 
3024
        return(0);
 
3025
}
 
3026
 
 
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. */
 
3030
inline
 
3031
void
 
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 */
 
3037
{
 
3038
        int     null_offset;
 
3039
 
 
3040
        null_offset = (uint) ((char*) field->null_ptr
 
3041
                                        - (char*) table->record[0]);
 
3042
 
 
3043
        record[null_offset] = record[null_offset] | field->null_bit;
 
3044
}
 
3045
 
 
3046
extern "C" {
 
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! */
 
3052
 
 
3053
int
 
3054
innobase_mysql_cmp(
 
3055
/*===============*/
 
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 */
 
3066
{
 
3067
        CHARSET_INFO*           charset;
 
3068
        enum_field_types        mysql_tp;
 
3069
        int                     ret;
 
3070
 
 
3071
        DBUG_ASSERT(a_length != UNIV_SQL_NULL);
 
3072
        DBUG_ASSERT(b_length != UNIV_SQL_NULL);
 
3073
 
 
3074
        mysql_tp = (enum_field_types) mysql_type;
 
3075
 
 
3076
        switch (mysql_tp) {
 
3077
 
 
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. */
 
3090
 
 
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;
 
3095
                } else {
 
3096
                        charset = get_charset(charset_number, MYF(MY_WME));
 
3097
 
 
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);
 
3103
                                ut_a(0);
 
3104
                        }
 
3105
                }
 
3106
 
 
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! */
 
3111
 
 
3112
                ret = charset->coll->strnncollsp(charset,
 
3113
                                  a, a_length,
 
3114
                                                 b, b_length, 0);
 
3115
                if (ret < 0) {
 
3116
                        return(-1);
 
3117
                } else if (ret > 0) {
 
3118
                        return(1);
 
3119
                } else {
 
3120
                        return(0);
 
3121
                }
 
3122
        default:
 
3123
                assert(0);
 
3124
        }
 
3125
 
 
3126
        return(0);
 
3127
}
 
3128
}
 
3129
 
 
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'. */
 
3134
inline
 
3135
ulint
 
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 */
 
3143
{
 
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
 
3146
        the type */
 
3147
 
 
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);
 
3153
 
 
3154
        if (field->flags & UNSIGNED_FLAG) {
 
3155
 
 
3156
                *unsigned_flag = DATA_UNSIGNED;
 
3157
        } else {
 
3158
                *unsigned_flag = 0;
 
3159
        }
 
3160
 
 
3161
        if (field->real_type() == MYSQL_TYPE_ENUM
 
3162
                || field->real_type() == MYSQL_TYPE_SET) {
 
3163
 
 
3164
                /* MySQL has field->type() a string type for these, but the
 
3165
                data is actually internally stored as an unsigned integer
 
3166
                code! */
 
3167
 
 
3168
                *unsigned_flag = DATA_UNSIGNED; /* MySQL has its own unsigned
 
3169
                                                flag set to zero, even though
 
3170
                                                internally this is an unsigned
 
3171
                                                integer type */
 
3172
                return(DATA_INT);
 
3173
        }
 
3174
 
 
3175
        switch (field->type()) {
 
3176
                /* NOTE that we only allow string types in DATA_MYSQL and
 
3177
                DATA_VARMYSQL */
 
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);
 
3182
                } else if (strcmp(
 
3183
                                   field->charset()->name,
 
3184
                                   "latin1_swedish_ci") == 0) {
 
3185
                        return(DATA_VARCHAR);
 
3186
                } else {
 
3187
                        return(DATA_VARMYSQL);
 
3188
                }
 
3189
        case MYSQL_TYPE_BIT:
 
3190
        case MYSQL_TYPE_STRING: if (field->binary()) {
 
3191
 
 
3192
                        return(DATA_FIXBINARY);
 
3193
                } else if (strcmp(
 
3194
                                   field->charset()->name,
 
3195
                                   "latin1_swedish_ci") == 0) {
 
3196
                        return(DATA_CHAR);
 
3197
                } else {
 
3198
                        return(DATA_MYSQL);
 
3199
                }
 
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:
 
3213
                return(DATA_INT);
 
3214
        case MYSQL_TYPE_FLOAT:
 
3215
                return(DATA_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:
 
3225
                return(DATA_BLOB);
 
3226
        default:
 
3227
                assert(0);
 
3228
        }
 
3229
 
 
3230
        return(0);
 
3231
}
 
3232
 
 
3233
/***********************************************************************
 
3234
Writes an unsigned integer value < 64k to 2 bytes, in the little-endian
 
3235
storage format. */
 
3236
inline
 
3237
void
 
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 */
 
3242
{
 
3243
        ut_a(val < 256 * 256);
 
3244
 
 
3245
        buf[0] = (byte)(val & 0xFF);
 
3246
        buf[1] = (byte)(val / 256);
 
3247
}
 
3248
 
 
3249
/***********************************************************************
 
3250
Reads an unsigned integer value < 64k from 2 bytes, in the little-endian
 
3251
storage format. */
 
3252
inline
 
3253
uint
 
3254
innobase_read_from_2_little_endian(
 
3255
/*===============================*/
 
3256
                                /* out: value */
 
3257
        const uchar*    buf)    /* in: from where to read */
 
3258
{
 
3259
        return (uint) ((ulint)(buf[0]) + 256 * ((ulint)(buf[1])));
 
3260
}
 
3261
 
 
3262
/***********************************************************************
 
3263
Stores a key value for a row to a buffer. */
 
3264
 
 
3265
uint
 
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
 
3271
                                format) */
 
3272
        uint            buff_len,/* in: buffer length */
 
3273
        const uchar*    record)/* in: row in MySQL format */
 
3274
{
 
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;
 
3280
        Field*          field;
 
3281
        ibool           is_null;
 
3282
 
 
3283
        DBUG_ENTER("store_key_val_for_row");
 
3284
 
 
3285
        /* The format for storing a key field in MySQL is the following:
 
3286
 
 
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.
 
3289
 
 
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.
 
3295
 
 
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.
 
3300
 
 
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.
 
3305
 
 
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. */
 
3309
 
 
3310
        bzero(buff, buff_len);
 
3311
 
 
3312
        for (; key_part != end; key_part++) {
 
3313
                is_null = FALSE;
 
3314
 
 
3315
                if (key_part->null_bit) {
 
3316
                        if (record[key_part->null_offset]
 
3317
                                                & key_part->null_bit) {
 
3318
                                *buff = 1;
 
3319
                                is_null = TRUE;
 
3320
                        } else {
 
3321
                                *buff = 0;
 
3322
                        }
 
3323
                        buff++;
 
3324
                }
 
3325
 
 
3326
                field = key_part->field;
 
3327
                mysql_type = field->type();
 
3328
 
 
3329
                if (mysql_type == MYSQL_TYPE_VARCHAR) {
 
3330
                                                /* >= 5.0.3 true VARCHAR */
 
3331
                        ulint   lenlen;
 
3332
                        ulint   len;
 
3333
                        byte*   data;
 
3334
                        ulint   key_len;
 
3335
                        ulint   true_len;
 
3336
                        CHARSET_INFO*   cs;
 
3337
                        int     error=0;
 
3338
 
 
3339
                        key_len = key_part->length;
 
3340
 
 
3341
                        if (is_null) {
 
3342
                                buff += key_len + 2;
 
3343
 
 
3344
                                continue;
 
3345
                        }
 
3346
                        cs = field->charset();
 
3347
 
 
3348
                        lenlen = (ulint)
 
3349
                                (((Field_varstring*)field)->length_bytes);
 
3350
 
 
3351
                        data = row_mysql_read_true_varchar(&len,
 
3352
                                (byte*) (record
 
3353
                                + (ulint)get_field_offset(table, field)),
 
3354
                                lenlen);
 
3355
 
 
3356
                        true_len = len;
 
3357
 
 
3358
                        /* For multi byte character sets we need to calculate
 
3359
                        the true length of the key */
 
3360
 
 
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,
 
3365
                                                (uint) (key_len /
 
3366
                                                        cs->mbmaxlen),
 
3367
                                                &error);
 
3368
                        }
 
3369
 
 
3370
                        /* In a column prefix index, we may need to truncate
 
3371
                        the stored value: */
 
3372
 
 
3373
                        if (true_len > key_len) {
 
3374
                                true_len = key_len;
 
3375
                        }
 
3376
 
 
3377
                        /* The length in a key value is always stored in 2
 
3378
                        bytes */
 
3379
 
 
3380
                        row_mysql_store_true_var_len((byte*)buff, true_len, 2);
 
3381
                        buff += 2;
 
3382
 
 
3383
                        memcpy(buff, data, true_len);
 
3384
 
 
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. */
 
3390
 
 
3391
                        buff += key_len;
 
3392
 
 
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) {
 
3400
 
 
3401
                        CHARSET_INFO*   cs;
 
3402
                        ulint           key_len;
 
3403
                        ulint           true_len;
 
3404
                        int             error=0;
 
3405
                        ulint           blob_len;
 
3406
                        byte*           blob_data;
 
3407
 
 
3408
                        ut_a(key_part->key_part_flag & HA_PART_KEY_SEG);
 
3409
 
 
3410
                        key_len = key_part->length;
 
3411
 
 
3412
                        if (is_null) {
 
3413
                                buff += key_len + 2;
 
3414
 
 
3415
                                continue;
 
3416
                        }
 
3417
 
 
3418
                        cs = field->charset();
 
3419
 
 
3420
                        blob_data = row_mysql_read_blob_ref(&blob_len,
 
3421
                                (byte*) (record
 
3422
                                + (ulint)get_field_offset(table, field)),
 
3423
                                        (ulint) field->pack_length());
 
3424
 
 
3425
                        true_len = blob_len;
 
3426
 
 
3427
                        ut_a(get_field_offset(table, field)
 
3428
                                == key_part->offset);
 
3429
 
 
3430
                        /* For multi byte character sets we need to calculate
 
3431
                        the true length of the key */
 
3432
 
 
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
 
3437
                                                        + blob_len,
 
3438
                                                (uint) (key_len /
 
3439
                                                        cs->mbmaxlen),
 
3440
                                                &error);
 
3441
                        }
 
3442
 
 
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: */
 
3446
 
 
3447
                        if (true_len > key_len) {
 
3448
                                true_len = key_len;
 
3449
                        }
 
3450
 
 
3451
                        /* MySQL reserves 2 bytes for the length and the
 
3452
                        storage of the number is little-endian */
 
3453
 
 
3454
                        innobase_write_to_2_little_endian(
 
3455
                                        (byte*)buff, true_len);
 
3456
                        buff += 2;
 
3457
 
 
3458
                        memcpy(buff, blob_data, true_len);
 
3459
 
 
3460
                        /* Note that we always reserve the maximum possible
 
3461
                        length of the BLOB prefix in the key value. */
 
3462
 
 
3463
                        buff += key_len;
 
3464
                } else {
 
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
 
3468
                        index. */
 
3469
 
 
3470
                        CHARSET_INFO*           cs;
 
3471
                        ulint                   true_len;
 
3472
                        ulint                   key_len;
 
3473
                        const uchar*            src_start;
 
3474
                        int                     error=0;
 
3475
                        enum_field_types        real_type;
 
3476
 
 
3477
                        key_len = key_part->length;
 
3478
 
 
3479
                        if (is_null) {
 
3480
                                 buff += key_len;
 
3481
 
 
3482
                                 continue;
 
3483
                        }
 
3484
 
 
3485
                        src_start = record + key_part->offset;
 
3486
                        real_type = field->real_type();
 
3487
                        true_len = key_len;
 
3488
 
 
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. */
 
3493
 
 
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)) {
 
3498
 
 
3499
                                cs = field->charset();
 
3500
 
 
3501
                                /* For multi byte character sets we need to
 
3502
                                calculate the true length of the key */
 
3503
 
 
3504
                                if (key_len > 0 && cs->mbmaxlen > 1) {
 
3505
 
 
3506
                                        true_len = (ulint)
 
3507
                                                cs->cset->well_formed_len(cs,
 
3508
                                                        (const char *)src_start,
 
3509
                                                        (const char *)src_start
 
3510
                                                                + key_len,
 
3511
                                                        (uint) (key_len /
 
3512
                                                                cs->mbmaxlen),
 
3513
                                                        &error);
 
3514
                                }
 
3515
                        }
 
3516
 
 
3517
                        memcpy(buff, src_start, true_len);
 
3518
                        buff += true_len;
 
3519
 
 
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. */
 
3525
 
 
3526
                        if (true_len < key_len) {
 
3527
                                ulint pad_len = key_len - true_len;
 
3528
                                memset(buff, ' ', pad_len);
 
3529
                                buff += pad_len;
 
3530
                        }
 
3531
                }
 
3532
        }
 
3533
 
 
3534
        ut_a(buff <= buff_start + buff_len);
 
3535
 
 
3536
        DBUG_RETURN((uint)(buff - buff_start));
 
3537
}
 
3538
 
 
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. */
 
3542
static
 
3543
void
 
3544
build_template(
 
3545
/*===========*/
 
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 */
 
3553
{
 
3554
        dict_index_t*   index;
 
3555
        dict_index_t*   clust_index;
 
3556
        mysql_row_templ_t* templ;
 
3557
        Field*          field;
 
3558
        ulint           n_fields;
 
3559
        ulint           n_requested_fields      = 0;
 
3560
        ibool           fetch_all_in_key        = FALSE;
 
3561
        ibool           fetch_primary_key_cols  = FALSE;
 
3562
        ulint           i;
 
3563
        /* byte offset of the end of last requested column */
 
3564
        ulint           mysql_prefix_len        = 0;
 
3565
 
 
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. */
 
3570
 
 
3571
                templ_type = ROW_MYSQL_WHOLE_ROW;
 
3572
        }
 
3573
 
 
3574
        if (templ_type == ROW_MYSQL_REC_FIELDS) {
 
3575
                if (prebuilt->hint_need_to_fetch_extra_cols
 
3576
                        == ROW_RETRIEVE_ALL_COLS) {
 
3577
 
 
3578
                        /* We know we must at least fetch all columns in the
 
3579
                        key, or all columns in the table */
 
3580
 
 
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 */
 
3588
 
 
3589
                                fetch_all_in_key = TRUE;
 
3590
                        } else {
 
3591
                                templ_type = ROW_MYSQL_WHOLE_ROW;
 
3592
                        }
 
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
 
3600
                           prebuilt struct. */
 
3601
 
 
3602
                        fetch_primary_key_cols = TRUE;
 
3603
                }
 
3604
        }
 
3605
 
 
3606
        clust_index = dict_table_get_first_index_noninline(prebuilt->table);
 
3607
 
 
3608
        if (templ_type == ROW_MYSQL_REC_FIELDS) {
 
3609
                index = prebuilt->index;
 
3610
        } else {
 
3611
                index = clust_index;
 
3612
        }
 
3613
 
 
3614
        if (index == clust_index) {
 
3615
                prebuilt->need_to_access_clustered = TRUE;
 
3616
        } else {
 
3617
                prebuilt->need_to_access_clustered = FALSE;
 
3618
                /* Below we check column by column if we need to access
 
3619
                the clustered index */
 
3620
        }
 
3621
 
 
3622
        n_fields = (ulint)table->s->fields; /* number of columns */
 
3623
 
 
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));
 
3628
        }
 
3629
 
 
3630
        prebuilt->template_type = templ_type;
 
3631
        prebuilt->null_bitmap_len = table->s->null_bytes;
 
3632
 
 
3633
        prebuilt->templ_contains_blob = FALSE;
 
3634
 
 
3635
        /* Note that in InnoDB, i is the column number. MySQL calls columns
 
3636
        'fields'. */
 
3637
        for (i = 0; i < n_fields; i++) {
 
3638
                templ = prebuilt->mysql_template + n_requested_fields;
 
3639
                field = table->field[i];
 
3640
 
 
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);
 
3646
 
 
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 */
 
3650
 
 
3651
                                goto skip_field;
 
3652
                        }
 
3653
 
 
3654
                        if (index_contains_field && fetch_all_in_key) {
 
3655
                                /* This field is needed in the query */
 
3656
 
 
3657
                                goto include_field;
 
3658
                        }
 
3659
 
 
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 */
 
3663
 
 
3664
                                goto include_field;
 
3665
                        }
 
3666
 
 
3667
                        if (fetch_primary_key_cols
 
3668
                                && dict_table_col_in_clustered_key(
 
3669
                                        index->table, i)) {
 
3670
                                /* This field is needed in the query */
 
3671
 
 
3672
                                goto include_field;
 
3673
                        }
 
3674
 
 
3675
                        /* This field is not needed in the query, skip it */
 
3676
 
 
3677
                        goto skip_field;
 
3678
                }
 
3679
include_field:
 
3680
                n_requested_fields++;
 
3681
 
 
3682
                templ->col_no = i;
 
3683
 
 
3684
                if (index == clust_index) {
 
3685
                        templ->rec_field_no = dict_col_get_clust_pos_noninline(
 
3686
                                &index->table->cols[i], index);
 
3687
                } else {
 
3688
                        templ->rec_field_no = dict_index_get_nth_col_pos(
 
3689
                                                                index, i);
 
3690
                }
 
3691
 
 
3692
                if (templ->rec_field_no == ULINT_UNDEFINED) {
 
3693
                        prebuilt->need_to_access_clustered = TRUE;
 
3694
                }
 
3695
 
 
3696
                if (field->null_ptr) {
 
3697
                        templ->mysql_null_byte_offset =
 
3698
                                (ulint) ((char*) field->null_ptr
 
3699
                                        - (char*) table->record[0]);
 
3700
 
 
3701
                        templ->mysql_null_bit_mask = (ulint) field->null_bit;
 
3702
                } else {
 
3703
                        templ->mysql_null_bit_mask = 0;
 
3704
                }
 
3705
 
 
3706
                templ->mysql_col_offset = (ulint)
 
3707
                                        get_field_offset(table, field);
 
3708
 
 
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;
 
3714
                }
 
3715
                templ->type = index->table->cols[i].mtype;
 
3716
                templ->mysql_type = (ulint)field->type();
 
3717
 
 
3718
                if (templ->mysql_type == DATA_MYSQL_TRUE_VARCHAR) {
 
3719
                        templ->mysql_length_bytes = (ulint)
 
3720
                                (((Field_varstring*)field)->length_bytes);
 
3721
                }
 
3722
 
 
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
 
3728
                                                        & DATA_UNSIGNED;
 
3729
                if (templ->type == DATA_BLOB) {
 
3730
                        prebuilt->templ_contains_blob = TRUE;
 
3731
                }
 
3732
skip_field:
 
3733
                ;
 
3734
        }
 
3735
 
 
3736
        prebuilt->n_template = n_requested_fields;
 
3737
        prebuilt->mysql_prefix_len = mysql_prefix_len;
 
3738
 
 
3739
        if (index != clust_index && prebuilt->need_to_access_clustered) {
 
3740
                /* Change rec_field_no's to correspond to the clustered index
 
3741
                record */
 
3742
                for (i = 0; i < n_requested_fields; i++) {
 
3743
                        templ = prebuilt->mysql_template + i;
 
3744
 
 
3745
                        templ->rec_field_no = dict_col_get_clust_pos_noninline(
 
3746
                                &index->table->cols[templ->col_no],
 
3747
                                clust_index);
 
3748
                }
 
3749
        }
 
3750
}
 
3751
 
 
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.*/
 
3758
 
 
3759
ulong
 
3760
ha_innobase::innobase_lock_autoinc(void)
 
3761
/*====================================*/
 
3762
                                        /* out: DB_SUCCESS if all OK else
 
3763
                                        error code */
 
3764
{
 
3765
        ulint           error = DB_SUCCESS;
 
3766
 
 
3767
        switch (innobase_autoinc_lock_mode) {
 
3768
        case AUTOINC_NO_LOCKING:
 
3769
                /* Acquire only the AUTOINC mutex. */
 
3770
                dict_table_autoinc_lock(prebuilt->table);
 
3771
                break;
 
3772
 
 
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;
 
3781
 
 
3782
                        /* Acquire the AUTOINC mutex. */
 
3783
                        dict_table_autoinc_lock(table);
 
3784
 
 
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);
 
3790
                        } else {
 
3791
                                break;
 
3792
                        }
 
3793
                }
 
3794
                /* Fall through to old style locking. */
 
3795
 
 
3796
        case AUTOINC_OLD_STYLE_LOCKING:
 
3797
                error = row_lock_table_autoinc_for_mysql(prebuilt);
 
3798
 
 
3799
                if (error == DB_SUCCESS) {
 
3800
 
 
3801
                        /* Acquire the AUTOINC mutex. */
 
3802
                        dict_table_autoinc_lock(prebuilt->table);
 
3803
                }
 
3804
                break;
 
3805
 
 
3806
        default:
 
3807
                ut_error;
 
3808
        }
 
3809
 
 
3810
        return(ulong(error));
 
3811
}
 
3812
 
 
3813
/************************************************************************
 
3814
Reset the autoinc value in the table.*/
 
3815
 
 
3816
ulong
 
3817
ha_innobase::innobase_reset_autoinc(
 
3818
/*================================*/
 
3819
                                        /* out: DB_SUCCESS if all went well
 
3820
                                        else error code */
 
3821
        ulonglong       autoinc)        /* in: value to store */
 
3822
{
 
3823
        ulint           error;
 
3824
 
 
3825
        error = innobase_lock_autoinc();
 
3826
 
 
3827
        if (error == DB_SUCCESS) {
 
3828
 
 
3829
                dict_table_autoinc_initialize(prebuilt->table, autoinc);
 
3830
 
 
3831
                dict_table_autoinc_unlock(prebuilt->table);
 
3832
        }
 
3833
 
 
3834
        return(ulong(error));
 
3835
}
 
3836
 
 
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.*/
 
3840
 
 
3841
ulong
 
3842
ha_innobase::innobase_set_max_autoinc(
 
3843
/*==================================*/
 
3844
                                        /* out: DB_SUCCES if all went well
 
3845
                                        else error code */
 
3846
        ulonglong       auto_inc)       /* in: value to store */
 
3847
{
 
3848
        ulint           error;
 
3849
 
 
3850
        error = innobase_lock_autoinc();
 
3851
 
 
3852
        if (error == DB_SUCCESS) {
 
3853
 
 
3854
                dict_table_autoinc_update_if_greater(prebuilt->table, auto_inc);
 
3855
 
 
3856
                dict_table_autoinc_unlock(prebuilt->table);
 
3857
        }
 
3858
 
 
3859
        return(ulong(error));
 
3860
}
 
3861
 
 
3862
/************************************************************************
 
3863
Stores a row in an InnoDB database, to the table specified in this
 
3864
handle. */
 
3865
 
 
3866
int
 
3867
ha_innobase::write_row(
 
3868
/*===================*/
 
3869
                        /* out: error code */
 
3870
        uchar*  record) /* in: a row in MySQL format */
 
3871
{
 
3872
        ulint           error = 0;
 
3873
        int             error_result= 0;
 
3874
        ibool           auto_inc_used= FALSE;
 
3875
        ulint           sql_command;
 
3876
        trx_t*          trx = thd_to_trx(user_thd);
 
3877
 
 
3878
        DBUG_ENTER("ha_innobase::write_row");
 
3879
 
 
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);
 
3884
 
 
3885
                fputs("InnoDB: Dump of 200 bytes around prebuilt: ", stderr);
 
3886
                ut_print_buf(stderr, ((const byte*)prebuilt) - 100, 200);
 
3887
                fputs("\n"
 
3888
                        "InnoDB: Dump of 200 bytes around ha_data: ",
 
3889
                        stderr);
 
3890
                ut_print_buf(stderr, ((const byte*) trx) - 100, 200);
 
3891
                putc('\n', stderr);
 
3892
                ut_error;
 
3893
        }
 
3894
 
 
3895
        ha_statistic_increment(&SSV::ha_write_count);
 
3896
 
 
3897
        if (table->timestamp_field_type & TIMESTAMP_AUTO_SET_ON_INSERT)
 
3898
                table->timestamp_field->set_time();
 
3899
 
 
3900
        sql_command = thd_sql_command(user_thd);
 
3901
 
 
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. */
 
3915
 
 
3916
                dict_table_t*   src_table;
 
3917
                ulint           mode;
 
3918
 
 
3919
                num_write_row = 0;
 
3920
 
 
3921
                /* Commit the transaction.  This will release the table
 
3922
                locks, so they have to be acquired again. */
 
3923
 
 
3924
                /* Altering an InnoDB table */
 
3925
                /* Get the source table. */
 
3926
                src_table = lock_get_src_table(
 
3927
                                prebuilt->trx, prebuilt->table, &mode);
 
3928
                if (!src_table) {
 
3929
no_commit:
 
3930
                        /* Unknown situation: do not commit */
 
3931
                        /*
 
3932
                        ut_print_timestamp(stderr);
 
3933
                        fprintf(stderr,
 
3934
                                "  InnoDB: ALTER TABLE is holding lock"
 
3935
                                " on %lu tables!\n",
 
3936
                                prebuilt->trx->mysql_n_tables_locked);
 
3937
                        */
 
3938
                        ;
 
3939
                } else if (src_table == prebuilt->table) {
 
3940
                        /* Source table is not in InnoDB format:
 
3941
                        no need to re-acquire locks on it. */
 
3942
 
 
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;
 
3949
                } else {
 
3950
                        /* Ensure that there are no other table locks than
 
3951
                        LOCK_IX and LOCK_AUTO_INC on the destination table. */
 
3952
 
 
3953
                        if (!lock_is_table_exclusive(prebuilt->table,
 
3954
                                                        prebuilt->trx)) {
 
3955
                                goto no_commit;
 
3956
                        }
 
3957
 
 
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;
 
3967
                }
 
3968
        }
 
3969
 
 
3970
        num_write_row++;
 
3971
 
 
3972
        /* This is the case where the table has an auto-increment column */
 
3973
        if (table->next_number_field && record == table->record[0]) {
 
3974
 
 
3975
                /* Reset the error code before calling
 
3976
                innobase_get_auto_increment(). */
 
3977
                prebuilt->autoinc_error = DB_SUCCESS;
 
3978
 
 
3979
                if ((error = update_auto_increment())) {
 
3980
                        /* We don't want to mask autoinc overflow errors. */
 
3981
 
 
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));
 
3988
                                goto func_exit;
 
3989
                        } else if (prebuilt->autoinc_error != DB_SUCCESS) {
 
3990
                                error = (int) prebuilt->autoinc_error;
 
3991
                                goto report_error;
 
3992
                        }
 
3993
 
 
3994
                        /* MySQL errors are passed straight back. */
 
3995
                        error_result = (int) error;
 
3996
                        goto func_exit;
 
3997
                }
 
3998
 
 
3999
                auto_inc_used = TRUE;
 
4000
        }
 
4001
 
 
4002
        if (prebuilt->mysql_template == NULL
 
4003
            || prebuilt->template_type != ROW_MYSQL_WHOLE_ROW) {
 
4004
 
 
4005
                /* Build the template used in converting quickly between
 
4006
                the two database formats */
 
4007
 
 
4008
                build_template(prebuilt, NULL, table, ROW_MYSQL_WHOLE_ROW);
 
4009
        }
 
4010
 
 
4011
        innodb_srv_conc_enter_innodb(prebuilt->trx);
 
4012
 
 
4013
        error = row_insert_for_mysql((byte*) record, prebuilt);
 
4014
 
 
4015
        /* Handle duplicate key errors */
 
4016
        if (auto_inc_used) {
 
4017
                ulint           err;
 
4018
                ulonglong       auto_inc;
 
4019
                ulonglong       col_max_value;
 
4020
 
 
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;
 
4027
                }
 
4028
 
 
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);
 
4033
 
 
4034
                /* Get the value that MySQL attempted to store in the table.*/
 
4035
                auto_inc = table->next_number_field->val_int();
 
4036
 
 
4037
                switch (error) {
 
4038
                case DB_DUPLICATE_KEY:
 
4039
 
 
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. */
 
4044
 
 
4045
                        switch (sql_command) {
 
4046
                        case SQLCOM_LOAD:
 
4047
                                if ((trx->duplicates
 
4048
                                    & (TRX_DUP_IGNORE | TRX_DUP_REPLACE))) {
 
4049
 
 
4050
                                        goto set_max_autoinc;
 
4051
                                }
 
4052
                                break;
 
4053
 
 
4054
                        case SQLCOM_REPLACE:
 
4055
                        case SQLCOM_INSERT_SELECT:
 
4056
                        case SQLCOM_REPLACE_SELECT:
 
4057
                                goto set_max_autoinc;
 
4058
                                break;
 
4059
 
 
4060
                        default:
 
4061
                                break;
 
4062
                        }
 
4063
 
 
4064
                        break;
 
4065
 
 
4066
                case DB_SUCCESS:
 
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.*/
 
4071
 
 
4072
                        if (auto_inc >= prebuilt->autoinc_last_value) {
 
4073
set_max_autoinc:
 
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);
 
4078
 
 
4079
                                        ulonglong       need;
 
4080
                                        ulonglong       offset;
 
4081
 
 
4082
                                        offset = prebuilt->autoinc_offset;
 
4083
                                        need = prebuilt->autoinc_increment;
 
4084
 
 
4085
                                        auto_inc = innobase_next_autoinc(
 
4086
                                                auto_inc,
 
4087
                                                need, offset, col_max_value);
 
4088
 
 
4089
                                        err = innobase_set_max_autoinc(
 
4090
                                                auto_inc);
 
4091
 
 
4092
                                        if (err != DB_SUCCESS) {
 
4093
                                                error = err;
 
4094
                                        }
 
4095
                                }
 
4096
                        }
 
4097
                        break;
 
4098
                }
 
4099
        }
 
4100
 
 
4101
        innodb_srv_conc_exit_innodb(prebuilt->trx);
 
4102
 
 
4103
report_error:
 
4104
        error_result = convert_error_code_to_mysql((int) error, user_thd);
 
4105
 
 
4106
func_exit:
 
4107
        innobase_active_small();
 
4108
 
 
4109
        DBUG_RETURN(error_result);
 
4110
}
 
4111
 
 
4112
/**************************************************************************
 
4113
Checks which fields have changed in a row and stores information
 
4114
of them to an update vector. */
 
4115
static
 
4116
int
 
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
 
4124
                                        dictionary */
 
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 */
 
4129
{
 
4130
        uchar*          original_upd_buff = upd_buff;
 
4131
        Field*          field;
 
4132
        enum_field_types field_mysql_type;
 
4133
        uint            n_fields;
 
4134
        ulint           o_len;
 
4135
        ulint           n_len;
 
4136
        ulint           col_pack_len;
 
4137
        byte*           new_mysql_row_col;
 
4138
        byte*           o_ptr;
 
4139
        byte*           n_ptr;
 
4140
        byte*           buf;
 
4141
        upd_field_t*    ufield;
 
4142
        ulint           col_type;
 
4143
        ulint           n_changed = 0;
 
4144
        dfield_t        dfield;
 
4145
        dict_index_t*   clust_index;
 
4146
        uint            i;
 
4147
 
 
4148
        n_fields = table->s->fields;
 
4149
        clust_index = dict_table_get_first_index_noninline(prebuilt->table);
 
4150
 
 
4151
        /* We use upd_buff to convert changed fields */
 
4152
        buf = (byte*) upd_buff;
 
4153
 
 
4154
        for (i = 0; i < n_fields; i++) {
 
4155
                field = table->field[i];
 
4156
 
 
4157
                o_ptr = (byte*) old_row + get_field_offset(table, field);
 
4158
                n_ptr = (byte*) new_row + get_field_offset(table, field);
 
4159
 
 
4160
                /* Use new_mysql_row_col and col_pack_len save the values */
 
4161
 
 
4162
                new_mysql_row_col = n_ptr;
 
4163
                col_pack_len = field->pack_length();
 
4164
 
 
4165
                o_len = col_pack_len;
 
4166
                n_len = col_pack_len;
 
4167
 
 
4168
                /* We use o_ptr and n_ptr to dig up the actual data for
 
4169
                comparison. */
 
4170
 
 
4171
                field_mysql_type = field->type();
 
4172
 
 
4173
                col_type = prebuilt->table->cols[i].mtype;
 
4174
 
 
4175
                switch (col_type) {
 
4176
 
 
4177
                case DATA_BLOB:
 
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);
 
4180
 
 
4181
                        break;
 
4182
 
 
4183
                case DATA_VARCHAR:
 
4184
                case DATA_BINARY:
 
4185
                case DATA_VARMYSQL:
 
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
 
4189
                                1 or 2 bytes */
 
4190
 
 
4191
                                o_ptr = row_mysql_read_true_varchar(
 
4192
                                        &o_len, o_ptr,
 
4193
                                        (ulint)
 
4194
                                        (((Field_varstring*)field)->length_bytes));
 
4195
 
 
4196
                                n_ptr = row_mysql_read_true_varchar(
 
4197
                                        &n_len, n_ptr,
 
4198
                                        (ulint)
 
4199
                                        (((Field_varstring*)field)->length_bytes));
 
4200
                        }
 
4201
 
 
4202
                        break;
 
4203
                default:
 
4204
                        ;
 
4205
                }
 
4206
 
 
4207
                if (field->null_ptr) {
 
4208
                        if (field_in_record_is_null(table, field,
 
4209
                                                        (char*) old_row)) {
 
4210
                                o_len = UNIV_SQL_NULL;
 
4211
                        }
 
4212
 
 
4213
                        if (field_in_record_is_null(table, field,
 
4214
                                                        (char*) new_row)) {
 
4215
                                n_len = UNIV_SQL_NULL;
 
4216
                        }
 
4217
                }
 
4218
 
 
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 */
 
4222
 
 
4223
                        ufield = uvect->fields + n_changed;
 
4224
 
 
4225
                        /* Let us use a dummy dfield to make the conversion
 
4226
                        from the MySQL column format to the InnoDB format */
 
4227
 
 
4228
                        dict_col_copy_type_noninline(prebuilt->table->cols + i,
 
4229
                                                     &dfield.type);
 
4230
 
 
4231
                        if (n_len != UNIV_SQL_NULL) {
 
4232
                                buf = row_mysql_store_col_in_innobase_format(
 
4233
                                        &dfield,
 
4234
                                        (byte*)buf,
 
4235
                                        TRUE,
 
4236
                                        new_mysql_row_col,
 
4237
                                        col_pack_len,
 
4238
                                        dict_table_is_comp_noninline(
 
4239
                                                        prebuilt->table));
 
4240
                                ufield->new_val.data = dfield.data;
 
4241
                                ufield->new_val.len = dfield.len;
 
4242
                        } else {
 
4243
                                ufield->new_val.data = NULL;
 
4244
                                ufield->new_val.len = UNIV_SQL_NULL;
 
4245
                        }
 
4246
 
 
4247
                        ufield->exp = NULL;
 
4248
                        ufield->field_no = dict_col_get_clust_pos_noninline(
 
4249
                                &prebuilt->table->cols[i], clust_index);
 
4250
                        n_changed++;
 
4251
                }
 
4252
        }
 
4253
 
 
4254
        uvect->n_fields = n_changed;
 
4255
        uvect->info_bits = 0;
 
4256
 
 
4257
        ut_a(buf <= (byte*)original_upd_buff + buff_len);
 
4258
 
 
4259
        return(0);
 
4260
}
 
4261
 
 
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! */
 
4269
 
 
4270
int
 
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 */
 
4276
{
 
4277
        upd_t*          uvect;
 
4278
        int             error = 0;
 
4279
        trx_t*          trx = thd_to_trx(user_thd);
 
4280
 
 
4281
        DBUG_ENTER("ha_innobase::update_row");
 
4282
 
 
4283
        ut_a(prebuilt->trx == trx);
 
4284
 
 
4285
        ha_statistic_increment(&SSV::ha_update_count);
 
4286
 
 
4287
        if (table->timestamp_field_type & TIMESTAMP_AUTO_SET_ON_UPDATE)
 
4288
                table->timestamp_field->set_time();
 
4289
 
 
4290
        if (prebuilt->upd_node) {
 
4291
                uvect = prebuilt->upd_node->update;
 
4292
        } else {
 
4293
                uvect = row_get_prebuilt_update_vector(prebuilt);
 
4294
        }
 
4295
 
 
4296
        /* Build an update vector from the modified fields in the rows
 
4297
        (uses upd_buff of the handle) */
 
4298
 
 
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);
 
4302
 
 
4303
        /* This is not a delete */
 
4304
        prebuilt->upd_node->is_delete = FALSE;
 
4305
 
 
4306
        assert(prebuilt->template_type == ROW_MYSQL_WHOLE_ROW);
 
4307
 
 
4308
        innodb_srv_conc_enter_innodb(trx);
 
4309
 
 
4310
        error = row_update_for_mysql((byte*) old_row, prebuilt);
 
4311
 
 
4312
        /* We need to do some special AUTOINC handling for the following case:
 
4313
 
 
4314
        INSERT INTO t (c1,c2) VALUES(x,y) ON DUPLICATE KEY UPDATE ...
 
4315
 
 
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.*/
 
4319
 
 
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)  {
 
4326
 
 
4327
                ulonglong       auto_inc;
 
4328
                ulonglong       col_max_value;
 
4329
 
 
4330
                auto_inc = table->next_number_field->val_int();
 
4331
 
 
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);
 
4336
 
 
4337
                if (auto_inc <= col_max_value && auto_inc != 0) {
 
4338
 
 
4339
                        ulonglong       need;
 
4340
                        ulonglong       offset;
 
4341
 
 
4342
                        offset = prebuilt->autoinc_offset;
 
4343
                        need = prebuilt->autoinc_increment;
 
4344
 
 
4345
                        auto_inc = innobase_next_autoinc(
 
4346
                                auto_inc, need, offset, col_max_value);
 
4347
 
 
4348
                        error = innobase_set_max_autoinc(auto_inc);
 
4349
                }
 
4350
        }
 
4351
 
 
4352
        innodb_srv_conc_exit_innodb(trx);
 
4353
 
 
4354
        error = convert_error_code_to_mysql(error, user_thd);
 
4355
 
 
4356
        if (error == 0 /* success */
 
4357
            && uvect->n_fields == 0 /* no columns were updated */) {
 
4358
 
 
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;
 
4364
        }
 
4365
 
 
4366
        /* Tell InnoDB server that there might be work for
 
4367
        utility threads: */
 
4368
 
 
4369
        innobase_active_small();
 
4370
 
 
4371
        DBUG_RETURN(error);
 
4372
}
 
4373
 
 
4374
/**************************************************************************
 
4375
Deletes a row given as the parameter. */
 
4376
 
 
4377
int
 
4378
ha_innobase::delete_row(
 
4379
/*====================*/
 
4380
                                /* out: error number or 0 */
 
4381
        const uchar*    record) /* in: a row in MySQL format */
 
4382
{
 
4383
        int             error = 0;
 
4384
        trx_t*          trx = thd_to_trx(user_thd);
 
4385
 
 
4386
        DBUG_ENTER("ha_innobase::delete_row");
 
4387
 
 
4388
        ut_a(prebuilt->trx == trx);
 
4389
 
 
4390
        ha_statistic_increment(&SSV::ha_delete_count);
 
4391
 
 
4392
        if (!prebuilt->upd_node) {
 
4393
                row_get_prebuilt_update_vector(prebuilt);
 
4394
        }
 
4395
 
 
4396
        /* This is a delete */
 
4397
 
 
4398
        prebuilt->upd_node->is_delete = TRUE;
 
4399
 
 
4400
        innodb_srv_conc_enter_innodb(trx);
 
4401
 
 
4402
        error = row_update_for_mysql((byte*) record, prebuilt);
 
4403
 
 
4404
        innodb_srv_conc_exit_innodb(trx);
 
4405
 
 
4406
        error = convert_error_code_to_mysql(error, user_thd);
 
4407
 
 
4408
        /* Tell the InnoDB server that there might be work for
 
4409
        utility threads: */
 
4410
 
 
4411
        innobase_active_small();
 
4412
 
 
4413
        DBUG_RETURN(error);
 
4414
}
 
4415
 
 
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. */
 
4420
 
 
4421
void
 
4422
ha_innobase::unlock_row(void)
 
4423
/*=========================*/
 
4424
{
 
4425
        DBUG_ENTER("ha_innobase::unlock_row");
 
4426
 
 
4427
        /* Consistent read does not take any locks, thus there is
 
4428
        nothing to unlock. */
 
4429
 
 
4430
        if (prebuilt->select_lock_type == LOCK_NONE) {
 
4431
                DBUG_VOID_RETURN;
 
4432
        }
 
4433
 
 
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) {
 
4439
                        break;
 
4440
                }
 
4441
                /* fall through */
 
4442
        case ROW_READ_TRY_SEMI_CONSISTENT:
 
4443
                row_unlock_for_mysql(prebuilt, FALSE);
 
4444
                break;
 
4445
        case ROW_READ_DID_SEMI_CONSISTENT:
 
4446
                prebuilt->row_read_type = ROW_READ_TRY_SEMI_CONSISTENT;
 
4447
                break;
 
4448
        }
 
4449
 
 
4450
        DBUG_VOID_RETURN;
 
4451
}
 
4452
 
 
4453
/* See handler.h and row0mysql.h for docs on this function. */
 
4454
bool
 
4455
ha_innobase::was_semi_consistent_read(void)
 
4456
/*=======================================*/
 
4457
{
 
4458
        return(prebuilt->row_read_type == ROW_READ_DID_SEMI_CONSISTENT);
 
4459
}
 
4460
 
 
4461
/* See handler.h and row0mysql.h for docs on this function. */
 
4462
void
 
4463
ha_innobase::try_semi_consistent_read(bool yes)
 
4464
/*===========================================*/
 
4465
{
 
4466
        ut_a(prebuilt->trx == thd_to_trx(ha_thd()));
 
4467
 
 
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
 
4471
        level. */
 
4472
 
 
4473
        if (yes
 
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;
 
4477
        } else {
 
4478
                prebuilt->row_read_type = ROW_READ_WITH_LOCKS;
 
4479
        }
 
4480
}
 
4481
 
 
4482
/**********************************************************************
 
4483
Initializes a handle to use an index. */
 
4484
 
 
4485
int
 
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 */
 
4491
{
 
4492
        int     error   = 0;
 
4493
        DBUG_ENTER("index_init");
 
4494
 
 
4495
        error = change_active_index(keynr);
 
4496
 
 
4497
        DBUG_RETURN(error);
 
4498
}
 
4499
 
 
4500
/**********************************************************************
 
4501
Currently does nothing. */
 
4502
 
 
4503
int
 
4504
ha_innobase::index_end(void)
 
4505
/*========================*/
 
4506
{
 
4507
        int     error   = 0;
 
4508
        DBUG_ENTER("index_end");
 
4509
        active_index=MAX_KEY;
 
4510
        DBUG_RETURN(error);
 
4511
}
 
4512
 
 
4513
/*************************************************************************
 
4514
Converts a search mode flag understood by MySQL to a flag understood
 
4515
by InnoDB. */
 
4516
inline
 
4517
ulint
 
4518
convert_search_mode_to_innobase(
 
4519
/*============================*/
 
4520
        enum ha_rkey_function   find_flag)
 
4521
{
 
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: 
 
4531
                return(PAGE_CUR_G);
 
4532
        case HA_READ_BEFORE_KEY:
 
4533
                return(PAGE_CUR_L);
 
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
 
4552
                work correctly. */
 
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) */
 
4562
        }
 
4563
 
 
4564
        my_error(ER_CHECK_NOT_IMPLEMENTED, MYF(0), "this functionality");
 
4565
 
 
4566
        return(PAGE_CUR_UNSUPP);
 
4567
}
 
4568
 
 
4569
/*
 
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.
 
4574
 
 
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.
 
4579
 
 
4580
  A) if the user has not explicitly set any MySQL table level locks:
 
4581
 
 
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.
 
4587
 
 
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.
 
4591
 
 
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
 
4595
lock on the table.
 
4596
 
 
4597
  4) We do the SELECT. MySQL may repeatedly call ::index_read for the
 
4598
same table handle instance, if it is a join.
 
4599
 
 
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.
 
4607
 
 
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. */
 
4616
 
 
4617
 
 
4618
/**************************************************************************
 
4619
Positions an index cursor to the index specified in the handle. Fetches the
 
4620
row if any. */
 
4621
 
 
4622
int
 
4623
ha_innobase::index_read(
 
4624
/*====================*/
 
4625
                                        /* out: 0, HA_ERR_KEY_NOT_FOUND,
 
4626
                                        or error number */
 
4627
        uchar*          buf,            /* in/out: buffer for the returned
 
4628
                                        row */
 
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
 
4637
                                        of a full column */
 
4638
        uint                    key_len,/* in: key value length */
 
4639
        enum ha_rkey_function find_flag)/* in: search flags from my_base.h */
 
4640
{
 
4641
        ulint           mode;
 
4642
        dict_index_t*   index;
 
4643
        ulint           match_mode      = 0;
 
4644
        int             error;
 
4645
        ulint           ret;
 
4646
 
 
4647
        DBUG_ENTER("index_read");
 
4648
 
 
4649
        ut_a(prebuilt->trx == thd_to_trx(user_thd));
 
4650
 
 
4651
        ha_statistic_increment(&SSV::ha_read_key_count);
 
4652
 
 
4653
        index = prebuilt->index;
 
4654
 
 
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 */
 
4657
 
 
4658
        if (prebuilt->sql_stat_start) {
 
4659
                build_template(prebuilt, user_thd, table,
 
4660
                                                        ROW_MYSQL_REC_FIELDS);
 
4661
        }
 
4662
 
 
4663
        if (key_ptr) {
 
4664
                /* Convert the search key value to InnoDB format into
 
4665
                prebuilt->search_tuple */
 
4666
 
 
4667
                row_sel_convert_mysql_key_to_innobase(prebuilt->search_tuple,
 
4668
                                        (byte*) key_val_buff,
 
4669
                                        (ulint)upd_and_key_val_buff_len,
 
4670
                                        index,
 
4671
                                        (byte*) key_ptr,
 
4672
                                        (ulint) key_len, prebuilt->trx);
 
4673
        } else {
 
4674
                /* We position the cursor to the last or the first entry
 
4675
                in the index */
 
4676
 
 
4677
                dtuple_set_n_fields(prebuilt->search_tuple, 0);
 
4678
        }
 
4679
 
 
4680
        mode = convert_search_mode_to_innobase(find_flag);
 
4681
 
 
4682
        match_mode = 0;
 
4683
 
 
4684
        if (find_flag == HA_READ_KEY_EXACT) {
 
4685
                match_mode = ROW_SEL_EXACT;
 
4686
 
 
4687
        } else if (find_flag == HA_READ_PREFIX
 
4688
                                || find_flag == HA_READ_PREFIX_LAST) {
 
4689
                match_mode = ROW_SEL_EXACT_PREFIX;
 
4690
        }
 
4691
 
 
4692
        last_match_mode = (uint) match_mode;
 
4693
 
 
4694
        if (mode != PAGE_CUR_UNSUPP) {
 
4695
 
 
4696
                innodb_srv_conc_enter_innodb(prebuilt->trx);
 
4697
 
 
4698
                ret = row_search_for_mysql((byte*) buf, mode, prebuilt,
 
4699
                                           match_mode, 0);
 
4700
 
 
4701
                innodb_srv_conc_exit_innodb(prebuilt->trx);
 
4702
        } else {
 
4703
 
 
4704
                ret = DB_UNSUPPORTED;
 
4705
        }
 
4706
 
 
4707
        if (ret == DB_SUCCESS) {
 
4708
                error = 0;
 
4709
                table->status = 0;
 
4710
 
 
4711
        } else if (ret == DB_RECORD_NOT_FOUND) {
 
4712
                error = HA_ERR_KEY_NOT_FOUND;
 
4713
                table->status = STATUS_NOT_FOUND;
 
4714
 
 
4715
        } else if (ret == DB_END_OF_INDEX) {
 
4716
                error = HA_ERR_KEY_NOT_FOUND;
 
4717
                table->status = STATUS_NOT_FOUND;
 
4718
        } else {
 
4719
                error = convert_error_code_to_mysql((int) ret, user_thd);
 
4720
                table->status = STATUS_NOT_FOUND;
 
4721
        }
 
4722
 
 
4723
        DBUG_RETURN(error);
 
4724
}
 
4725
 
 
4726
/***********************************************************************
 
4727
The following functions works like index_read, but it find the last
 
4728
row with the current key value or prefix. */
 
4729
 
 
4730
int
 
4731
ha_innobase::index_read_last(
 
4732
/*=========================*/
 
4733
                                /* out: 0, HA_ERR_KEY_NOT_FOUND, or an
 
4734
                                error code */
 
4735
        uchar*          buf,    /* out: fetched row */
 
4736
        const uchar*    key_ptr,/* in: key value, or a prefix of a full
 
4737
                                key value */
 
4738
        uint            key_len)/* in: length of the key val or prefix
 
4739
                                in bytes */
 
4740
{
 
4741
        return(index_read(buf, key_ptr, key_len, HA_READ_PREFIX_LAST));
 
4742
}
 
4743
 
 
4744
/************************************************************************
 
4745
Get the index for a handle. Does not change active index.*/
 
4746
 
 
4747
dict_index_t*
 
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 */
 
4754
{
 
4755
        KEY*            key = 0;
 
4756
        dict_index_t*   index = 0;
 
4757
 
 
4758
        DBUG_ENTER("innobase_get_index");
 
4759
        ha_statistic_increment(&SSV::ha_read_key_count);
 
4760
 
 
4761
        ut_ad(user_thd == ha_thd());
 
4762
        ut_a(prebuilt->trx == thd_to_trx(user_thd));
 
4763
 
 
4764
        if (keynr != MAX_KEY && table->s->keys > 0) {
 
4765
                key = table->key_info + keynr;
 
4766
 
 
4767
                index = dict_table_get_index_noninline(
 
4768
                        prebuilt->table, key->name);
 
4769
        } else {
 
4770
                index = dict_table_get_first_index_noninline(prebuilt->table);
 
4771
        }
 
4772
 
 
4773
        if (!index) {
 
4774
                sql_print_error(
 
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);
 
4779
        }
 
4780
 
 
4781
        DBUG_RETURN(index);
 
4782
}
 
4783
 
 
4784
/************************************************************************
 
4785
Changes the active index of a handle. */
 
4786
 
 
4787
int
 
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
 
4793
                        InnoDB */
 
4794
{
 
4795
        DBUG_ENTER("change_active_index");
 
4796
 
 
4797
        ut_ad(user_thd == ha_thd());
 
4798
        ut_a(prebuilt->trx == thd_to_trx(user_thd));
 
4799
 
 
4800
        active_index = keynr;
 
4801
 
 
4802
        prebuilt->index = innobase_get_index(keynr);
 
4803
 
 
4804
        if (!prebuilt->index) {
 
4805
                DBUG_RETURN(1);
 
4806
        }
 
4807
 
 
4808
        assert(prebuilt->search_tuple != 0);
 
4809
 
 
4810
        dtuple_set_n_fields(prebuilt->search_tuple, prebuilt->index->n_fields);
 
4811
 
 
4812
        dict_index_copy_types(prebuilt->search_tuple, prebuilt->index,
 
4813
                        prebuilt->index->n_fields);
 
4814
 
 
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. */
 
4820
 
 
4821
        build_template(prebuilt, user_thd, table, ROW_MYSQL_REC_FIELDS);
 
4822
 
 
4823
        DBUG_RETURN(0);
 
4824
}
 
4825
 
 
4826
/**************************************************************************
 
4827
Positions an index cursor to the index specified in keynr. Fetches the
 
4828
row if any. */
 
4829
/* ??? This is only used to read whole keys ??? */
 
4830
 
 
4831
int
 
4832
ha_innobase::index_read_idx(
 
4833
/*========================*/
 
4834
                                        /* out: error number or 0 */
 
4835
        uchar*          buf,            /* in/out: buffer for the returned
 
4836
                                        row */
 
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 */
 
4843
{
 
4844
        if (change_active_index(keynr)) {
 
4845
 
 
4846
                return(1);
 
4847
        }
 
4848
 
 
4849
        return(index_read(buf, key, key_len, find_flag));
 
4850
}
 
4851
 
 
4852
/***************************************************************************
 
4853
Reads the next or previous row from a cursor, which must have previously been
 
4854
positioned using index_read. */
 
4855
 
 
4856
int
 
4857
ha_innobase::general_fetch(
 
4858
/*=======================*/
 
4859
                                /* out: 0, HA_ERR_END_OF_FILE, or error
 
4860
                                number */
 
4861
        uchar*  buf,            /* in/out: buffer for next row in MySQL
 
4862
                                format */
 
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 */
 
4866
{
 
4867
        ulint           ret;
 
4868
        int             error   = 0;
 
4869
 
 
4870
        DBUG_ENTER("general_fetch");
 
4871
 
 
4872
        ut_a(prebuilt->trx == thd_to_trx(user_thd));
 
4873
 
 
4874
        innodb_srv_conc_enter_innodb(prebuilt->trx);
 
4875
 
 
4876
        ret = row_search_for_mysql((byte*)buf, 0, prebuilt, match_mode,
 
4877
                                                                direction);
 
4878
        innodb_srv_conc_exit_innodb(prebuilt->trx);
 
4879
 
 
4880
        if (ret == DB_SUCCESS) {
 
4881
                error = 0;
 
4882
                table->status = 0;
 
4883
 
 
4884
        } else if (ret == DB_RECORD_NOT_FOUND) {
 
4885
                error = HA_ERR_END_OF_FILE;
 
4886
                table->status = STATUS_NOT_FOUND;
 
4887
 
 
4888
        } else if (ret == DB_END_OF_INDEX) {
 
4889
                error = HA_ERR_END_OF_FILE;
 
4890
                table->status = STATUS_NOT_FOUND;
 
4891
        } else {
 
4892
                error = convert_error_code_to_mysql((int) ret, user_thd);
 
4893
                table->status = STATUS_NOT_FOUND;
 
4894
        }
 
4895
 
 
4896
        DBUG_RETURN(error);
 
4897
}
 
4898
 
 
4899
/***************************************************************************
 
4900
Reads the next row from a cursor, which must have previously been
 
4901
positioned using index_read. */
 
4902
 
 
4903
int
 
4904
ha_innobase::index_next(
 
4905
/*====================*/
 
4906
                                /* out: 0, HA_ERR_END_OF_FILE, or error
 
4907
                                number */
 
4908
        uchar*          buf)    /* in/out: buffer for next row in MySQL
 
4909
                                format */
 
4910
{
 
4911
        ha_statistic_increment(&SSV::ha_read_next_count);
 
4912
 
 
4913
        return(general_fetch(buf, ROW_SEL_NEXT, 0));
 
4914
}
 
4915
 
 
4916
/***********************************************************************
 
4917
Reads the next row matching to the key value given as the parameter. */
 
4918
 
 
4919
int
 
4920
ha_innobase::index_next_same(
 
4921
/*=========================*/
 
4922
                                /* out: 0, HA_ERR_END_OF_FILE, or error
 
4923
                                number */
 
4924
        uchar*          buf,    /* in/out: buffer for the row */
 
4925
        const uchar*    key,    /* in: key value */
 
4926
        uint            keylen) /* in: key value length */
 
4927
{
 
4928
        ha_statistic_increment(&SSV::ha_read_next_count);
 
4929
 
 
4930
        return(general_fetch(buf, ROW_SEL_NEXT, last_match_mode));
 
4931
}
 
4932
 
 
4933
/***************************************************************************
 
4934
Reads the previous row from a cursor, which must have previously been
 
4935
positioned using index_read. */
 
4936
 
 
4937
int
 
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 */
 
4942
{
 
4943
        ha_statistic_increment(&SSV::ha_read_prev_count);
 
4944
 
 
4945
        return(general_fetch(buf, ROW_SEL_PREV, 0));
 
4946
}
 
4947
 
 
4948
/************************************************************************
 
4949
Positions a cursor on the first record in an index and reads the
 
4950
corresponding row to buf. */
 
4951
 
 
4952
int
 
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 */
 
4957
{
 
4958
        int     error;
 
4959
 
 
4960
        DBUG_ENTER("index_first");
 
4961
        ha_statistic_increment(&SSV::ha_read_first_count);
 
4962
 
 
4963
        error = index_read(buf, NULL, 0, HA_READ_AFTER_KEY);
 
4964
 
 
4965
        /* MySQL does not seem to allow this to return HA_ERR_KEY_NOT_FOUND */
 
4966
 
 
4967
        if (error == HA_ERR_KEY_NOT_FOUND) {
 
4968
                error = HA_ERR_END_OF_FILE;
 
4969
        }
 
4970
 
 
4971
        DBUG_RETURN(error);
 
4972
}
 
4973
 
 
4974
/************************************************************************
 
4975
Positions a cursor on the last record in an index and reads the
 
4976
corresponding row to buf. */
 
4977
 
 
4978
int
 
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 */
 
4983
{
 
4984
        int     error;
 
4985
 
 
4986
        DBUG_ENTER("index_last");
 
4987
        ha_statistic_increment(&SSV::ha_read_last_count);
 
4988
 
 
4989
        error = index_read(buf, NULL, 0, HA_READ_BEFORE_KEY);
 
4990
 
 
4991
        /* MySQL does not seem to allow this to return HA_ERR_KEY_NOT_FOUND */
 
4992
 
 
4993
        if (error == HA_ERR_KEY_NOT_FOUND) {
 
4994
                error = HA_ERR_END_OF_FILE;
 
4995
        }
 
4996
 
 
4997
        DBUG_RETURN(error);
 
4998
}
 
4999
 
 
5000
/********************************************************************
 
5001
Initialize a table scan. */
 
5002
 
 
5003
int
 
5004
ha_innobase::rnd_init(
 
5005
/*==================*/
 
5006
                        /* out: 0 or error number */
 
5007
        bool    scan)   /* in: ???????? */
 
5008
{
 
5009
        int     err;
 
5010
 
 
5011
        /* Store the active index value so that we can restore the original
 
5012
        value after a scan */
 
5013
 
 
5014
        if (prebuilt->clust_index_was_generated) {
 
5015
                err = change_active_index(MAX_KEY);
 
5016
        } else {
 
5017
                err = change_active_index(primary_key);
 
5018
        }
 
5019
 
 
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 */
 
5022
 
 
5023
        if (!scan) {
 
5024
                try_semi_consistent_read(0);
 
5025
        }
 
5026
 
 
5027
        start_of_scan = 1;
 
5028
 
 
5029
        return(err);
 
5030
}
 
5031
 
 
5032
/*********************************************************************
 
5033
Ends a table scan. */
 
5034
 
 
5035
int
 
5036
ha_innobase::rnd_end(void)
 
5037
/*======================*/
 
5038
                                /* out: 0 or error number */
 
5039
{
 
5040
        return(index_end());
 
5041
}
 
5042
 
 
5043
/*********************************************************************
 
5044
Reads the next row in a table scan (also used to read the FIRST row
 
5045
in a table scan). */
 
5046
 
 
5047
int
 
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,
 
5052
                        in MySQL format */
 
5053
{
 
5054
        int     error;
 
5055
 
 
5056
        DBUG_ENTER("rnd_next");
 
5057
        ha_statistic_increment(&SSV::ha_read_rnd_next_count);
 
5058
 
 
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;
 
5063
                }
 
5064
                start_of_scan = 0;
 
5065
        } else {
 
5066
                error = general_fetch(buf, ROW_SEL_NEXT, 0);
 
5067
        }
 
5068
 
 
5069
        DBUG_RETURN(error);
 
5070
}
 
5071
 
 
5072
/**************************************************************************
 
5073
Fetches a row from the table based on a row reference. */
 
5074
 
 
5075
int
 
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 */
 
5084
{
 
5085
        int             error;
 
5086
        uint            keynr   = active_index;
 
5087
        DBUG_ENTER("rnd_pos");
 
5088
        DBUG_DUMP("key", pos, ref_length);
 
5089
 
 
5090
        ha_statistic_increment(&SSV::ha_read_rnd_count);
 
5091
 
 
5092
        ut_a(prebuilt->trx == thd_to_trx(ha_thd()));
 
5093
 
 
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 */
 
5099
 
 
5100
                error = change_active_index(MAX_KEY);
 
5101
        } else {
 
5102
                error = change_active_index(primary_key);
 
5103
        }
 
5104
 
 
5105
        if (error) {
 
5106
                DBUG_PRINT("error", ("Got error: %d", error));
 
5107
                DBUG_RETURN(error);
 
5108
        }
 
5109
 
 
5110
        /* Note that we assume the length of the row reference is fixed
 
5111
        for the table, and it is == ref_length */
 
5112
 
 
5113
        error = index_read(buf, pos, ref_length, HA_READ_KEY_EXACT);
 
5114
 
 
5115
        if (error) {
 
5116
                DBUG_PRINT("error", ("Got error: %d", error));
 
5117
        }
 
5118
 
 
5119
        change_active_index(keynr);
 
5120
 
 
5121
        DBUG_RETURN(error);
 
5122
}
 
5123
 
 
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. */
 
5132
 
 
5133
void
 
5134
ha_innobase::position(
 
5135
/*==================*/
 
5136
        const uchar*    record) /* in: row in MySQL format */
 
5137
{
 
5138
        uint            len;
 
5139
 
 
5140
        ut_a(prebuilt->trx == thd_to_trx(ha_thd()));
 
5141
 
 
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 */
 
5147
 
 
5148
                len = DATA_ROW_ID_LEN;
 
5149
 
 
5150
                memcpy(ref, prebuilt->row_id, len);
 
5151
        } else {
 
5152
                len = store_key_val_for_row(primary_key, (char*)ref,
 
5153
                                                         ref_length, record);
 
5154
        }
 
5155
 
 
5156
        /* We assume that the 'ref' value len is always fixed for the same
 
5157
        table. */
 
5158
 
 
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);
 
5162
        }
 
5163
}
 
5164
 
 
5165
/*********************************************************************
 
5166
If it's a DB_TOO_BIG_RECORD error then set a suitable message to
 
5167
return to the client.*/
 
5168
inline
 
5169
void
 
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 */
 
5174
{
 
5175
        if (error == (int)DB_TOO_BIG_RECORD) {
 
5176
                ulint   max_row_size
 
5177
                        = page_get_free_space_of_empty_noninline(comp) / 2;
 
5178
 
 
5179
                my_error(ER_TOO_BIG_ROWSIZE, MYF(0), max_row_size);
 
5180
        }
 
5181
}
 
5182
 
 
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))
 
5188
 
 
5189
/*********************************************************************
 
5190
Creates a table definition to an InnoDB database. */
 
5191
static
 
5192
int
 
5193
create_table_def(
 
5194
/*=============*/
 
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
 
5206
                                        is NULL */
 
5207
        ulint           flags)          /* in: table flags */
 
5208
{
 
5209
        Field*          field;
 
5210
        dict_table_t*   table;
 
5211
        ulint           n_cols;
 
5212
        int             error;
 
5213
        ulint           col_type;
 
5214
        ulint           col_len;
 
5215
        ulint           nulls_allowed;
 
5216
        ulint           unsigned_type;
 
5217
        ulint           binary_type;
 
5218
        ulint           long_true_varchar;
 
5219
        ulint           charset_no;
 
5220
        ulint           i;
 
5221
 
 
5222
        DBUG_ENTER("create_table_def");
 
5223
        DBUG_PRINT("enter", ("table_name: %s", table_name));
 
5224
 
 
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);
 
5229
        }
 
5230
 
 
5231
        n_cols = form->s->fields;
 
5232
 
 
5233
        /* We pass 0 as the space id, and determine at a lower level the space
 
5234
        id where to store the table */
 
5235
 
 
5236
        table = dict_mem_table_create(table_name, 0, n_cols, flags);
 
5237
 
 
5238
        if (path_of_temp_table) {
 
5239
                table->dir_path_of_temp_table =
 
5240
                        mem_heap_strdup(table->heap, path_of_temp_table);
 
5241
        }
 
5242
 
 
5243
        for (i = 0; i < n_cols; i++) {
 
5244
                field = form->field[i];
 
5245
 
 
5246
                col_type = get_innobase_type_from_mysql_type(&unsigned_type,
 
5247
                                                                        field);
 
5248
                if (field->null_ptr) {
 
5249
                        nulls_allowed = 0;
 
5250
                } else {
 
5251
                        nulls_allowed = DATA_NOT_NULL;
 
5252
                }
 
5253
 
 
5254
                if (field->binary()) {
 
5255
                        binary_type = DATA_BINARY_TYPE;
 
5256
                } else {
 
5257
                        binary_type = 0;
 
5258
                }
 
5259
 
 
5260
                charset_no = 0;
 
5261
 
 
5262
                if (dtype_is_string_type(col_type)) {
 
5263
 
 
5264
                        charset_no = (ulint)field->charset()->number;
 
5265
 
 
5266
                        ut_a(charset_no < 256); /* in data0type.h we assume
 
5267
                                                that the number fits in one
 
5268
                                                byte */
 
5269
                }
 
5270
 
 
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();
 
5274
 
 
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. */
 
5279
 
 
5280
                long_true_varchar = 0;
 
5281
 
 
5282
                if (field->type() == MYSQL_TYPE_VARCHAR) {
 
5283
                        col_len -= ((Field_varstring*)field)->length_bytes;
 
5284
 
 
5285
                        if (((Field_varstring*)field)->length_bytes == 2) {
 
5286
                                long_true_varchar = DATA_LONG_TRUE_VARCHAR;
 
5287
                        }
 
5288
                }
 
5289
 
 
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);
 
5304
 
 
5305
                        dict_mem_table_free(table);
 
5306
                        trx_commit_for_mysql(trx);
 
5307
 
 
5308
                        error = DB_ERROR;
 
5309
                        goto error_ret;
 
5310
                }
 
5311
 
 
5312
                dict_mem_table_add_col(table, table->heap,
 
5313
                        (char*) field->field_name,
 
5314
                        col_type,
 
5315
                        dtype_form_prtype(
 
5316
                                (ulint)field->type()
 
5317
                                | nulls_allowed | unsigned_type
 
5318
                                | binary_type | long_true_varchar,
 
5319
                                charset_no),
 
5320
                        col_len);
 
5321
        }
 
5322
 
 
5323
        error = row_create_table_for_mysql(table, trx);
 
5324
 
 
5325
        innodb_check_for_record_too_big_error(flags & DICT_TF_COMPACT, error);
 
5326
 
 
5327
error_ret:
 
5328
        error = convert_error_code_to_mysql(error, NULL);
 
5329
 
 
5330
        DBUG_RETURN(error);
 
5331
}
 
5332
 
 
5333
/*********************************************************************
 
5334
Creates an index in an InnoDB database. */
 
5335
static
 
5336
int
 
5337
create_index(
 
5338
/*=========*/
 
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 */
 
5344
{
 
5345
        Field*          field;
 
5346
        dict_index_t*   index;
 
5347
        int             error;
 
5348
        ulint           n_fields;
 
5349
        KEY*            key;
 
5350
        KEY_PART_INFO*  key_part;
 
5351
        ulint           ind_type;
 
5352
        ulint           col_type;
 
5353
        ulint           prefix_len;
 
5354
        ulint           is_unsigned;
 
5355
        ulint           i;
 
5356
        ulint           j;
 
5357
        ulint*          field_lengths;
 
5358
 
 
5359
        DBUG_ENTER("create_index");
 
5360
 
 
5361
        key = form->key_info + key_num;
 
5362
 
 
5363
        n_fields = key->key_parts;
 
5364
 
 
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);
 
5367
 
 
5368
        ind_type = 0;
 
5369
 
 
5370
        if (key_num == form->s->primary_key) {
 
5371
                ind_type = ind_type | DICT_CLUSTERED;
 
5372
        }
 
5373
 
 
5374
        if (key->flags & HA_NOSAME ) {
 
5375
                ind_type = ind_type | DICT_UNIQUE;
 
5376
        }
 
5377
 
 
5378
        /* We pass 0 as the space id, and determine at a lower level the space
 
5379
        id where to store the table */
 
5380
 
 
5381
        index = dict_mem_index_create((char*) table_name, key->name, 0,
 
5382
                                                ind_type, n_fields);
 
5383
 
 
5384
        field_lengths = (ulint*) my_malloc(sizeof(ulint) * n_fields,
 
5385
                MYF(MY_FAE));
 
5386
 
 
5387
        for (i = 0; i < n_fields; i++) {
 
5388
                key_part = key->key_part + i;
 
5389
 
 
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. */
 
5395
 
 
5396
                field = NULL;
 
5397
                for (j = 0; j < form->s->fields; j++) {
 
5398
 
 
5399
                        field = form->field[j];
 
5400
 
 
5401
                        if (0 == innobase_strcasecmp(
 
5402
                                        field->field_name,
 
5403
                                        key_part->field->field_name)) {
 
5404
                                /* Found the corresponding column */
 
5405
 
 
5406
                                break;
 
5407
                        }
 
5408
                }
 
5409
 
 
5410
                ut_a(j < form->s->fields);
 
5411
 
 
5412
                col_type = get_innobase_type_from_mysql_type(
 
5413
                                        &is_unsigned, key_part->field);
 
5414
 
 
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)) {
 
5421
 
 
5422
                        prefix_len = key_part->length;
 
5423
 
 
5424
                        if (col_type == DATA_INT
 
5425
                                || col_type == DATA_FLOAT
 
5426
                                || col_type == DATA_DOUBLE
 
5427
                                || col_type == DATA_DECIMAL) {
 
5428
                                sql_print_error(
 
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.",
 
5433
                                        table_name,
 
5434
                                        key_part->field->field_name);
 
5435
 
 
5436
                                prefix_len = 0;
 
5437
                        }
 
5438
                } else {
 
5439
                        prefix_len = 0;
 
5440
                }
 
5441
 
 
5442
                field_lengths[i] = key_part->length;
 
5443
 
 
5444
                dict_mem_index_add_field(index,
 
5445
                        (char*) key_part->field->field_name, prefix_len);
 
5446
        }
 
5447
 
 
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);
 
5452
 
 
5453
        innodb_check_for_record_too_big_error(form->s->row_type
 
5454
                                              != ROW_TYPE_REDUNDANT, error);
 
5455
 
 
5456
        error = convert_error_code_to_mysql(error, NULL);
 
5457
 
 
5458
        my_free(field_lengths, MYF(0));
 
5459
 
 
5460
        DBUG_RETURN(error);
 
5461
}
 
5462
 
 
5463
/*********************************************************************
 
5464
Creates an index to an InnoDB table when the user has defined no
 
5465
primary index. */
 
5466
static
 
5467
int
 
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 */
 
5474
{
 
5475
        dict_index_t*   index;
 
5476
        int             error;
 
5477
 
 
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);
 
5484
 
 
5485
        innodb_check_for_record_too_big_error(comp, error);
 
5486
 
 
5487
        error = convert_error_code_to_mysql(error, NULL);
 
5488
 
 
5489
        return(error);
 
5490
}
 
5491
 
 
5492
/*********************************************************************
 
5493
Update create_info.  Used in SHOW CREATE TABLE et al. */
 
5494
 
 
5495
void
 
5496
ha_innobase::update_create_info(
 
5497
/*============================*/
 
5498
        HA_CREATE_INFO* create_info)    /* in/out: create info */
 
5499
{
 
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;
 
5503
  }
 
5504
}
 
5505
 
 
5506
/*********************************************************************
 
5507
Creates a new table to an InnoDB database. */
 
5508
 
 
5509
int
 
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 */
 
5519
{
 
5520
        int             error;
 
5521
        dict_table_t*   innobase_table;
 
5522
        trx_t*          parent_trx;
 
5523
        trx_t*          trx;
 
5524
        int             primary_key_no;
 
5525
        uint            i;
 
5526
        char            name2[FN_REFLEN];
 
5527
        char            norm_name[FN_REFLEN];
 
5528
        THD*            thd = ha_thd();
 
5529
        ib_longlong     auto_inc_value;
 
5530
        ulint           flags;
 
5531
 
 
5532
        DBUG_ENTER("ha_innobase::create");
 
5533
 
 
5534
        DBUG_ASSERT(thd != NULL);
 
5535
        DBUG_ASSERT(create_info != NULL);
 
5536
 
 
5537
#ifdef __WIN__
 
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
 
5541
 
 
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. */
 
5548
 
 
5549
        if (srv_file_per_table
 
5550
            && !mysqld_embedded
 
5551
            && (!create_info->options & HA_LEX_CREATE_TMP_TABLE)) {
 
5552
 
 
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);
 
5557
                }
 
5558
        }
 
5559
#endif
 
5560
 
 
5561
        if (form->s->fields > 1000) {
 
5562
                /* The limit probably should be REC_MAX_N_FIELDS - 3 = 1020,
 
5563
                but we play safe here */
 
5564
 
 
5565
                DBUG_RETURN(HA_ERR_TO_BIG_ROW);
 
5566
        }
 
5567
 
 
5568
        /* Get the transaction associated with the current thd, or create one
 
5569
        if not yet created */
 
5570
 
 
5571
        parent_trx = check_trx_exists(thd);
 
5572
 
 
5573
        /* In case MySQL calls this in the middle of a SELECT query, release
 
5574
        possible adaptive hash latch to avoid deadlocks of threads */
 
5575
 
 
5576
        trx_search_latch_release_if_reserved(parent_trx);
 
5577
 
 
5578
        trx = trx_allocate_for_mysql();
 
5579
 
 
5580
        trx->mysql_thd = thd;
 
5581
        trx->mysql_query_str = thd_query(thd);
 
5582
 
 
5583
        if (thd_test_options(thd, OPTION_NO_FOREIGN_KEY_CHECKS)) {
 
5584
                trx->check_foreigns = FALSE;
 
5585
        }
 
5586
 
 
5587
        if (thd_test_options(thd, OPTION_RELAXED_UNIQUE_CHECKS)) {
 
5588
                trx->check_unique_secondary = FALSE;
 
5589
        }
 
5590
 
 
5591
        if (lower_case_table_names) {
 
5592
                srv_lower_case_table_names = TRUE;
 
5593
        } else {
 
5594
                srv_lower_case_table_names = FALSE;
 
5595
        }
 
5596
 
 
5597
        strcpy(name2, name);
 
5598
 
 
5599
        normalize_table_name(norm_name, name2);
 
5600
 
 
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. */
 
5604
 
 
5605
        row_mysql_lock_data_dictionary(trx);
 
5606
 
 
5607
        /* Create the table definition in InnoDB */
 
5608
 
 
5609
        flags = 0;
 
5610
 
 
5611
        if (form->s->row_type != ROW_TYPE_REDUNDANT) {
 
5612
                flags |= DICT_TF_COMPACT;
 
5613
        }
 
5614
 
 
5615
        /* Look for a primary key */
 
5616
 
 
5617
        primary_key_no= (form->s->primary_key != MAX_KEY ?
 
5618
                         (int) form->s->primary_key :
 
5619
                         -1);
 
5620
 
 
5621
        /* Our function row_get_mysql_key_number_for_index assumes
 
5622
        the primary key is always number 0, if it exists */
 
5623
 
 
5624
        DBUG_ASSERT(primary_key_no == -1 || primary_key_no == 0);
 
5625
 
 
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)) {
 
5629
                error = -1;
 
5630
                goto cleanup;
 
5631
        }
 
5632
 
 
5633
        error = create_table_def(trx, form, norm_name,
 
5634
                create_info->options & HA_LEX_CREATE_TMP_TABLE ? name2 : NULL,
 
5635
                flags);
 
5636
 
 
5637
        if (error) {
 
5638
                goto cleanup;
 
5639
        }
 
5640
 
 
5641
 
 
5642
        /* Create the keys */
 
5643
 
 
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
 
5647
                by InnoDB */
 
5648
 
 
5649
                error = create_clustered_index_when_no_primary(
 
5650
                        trx, form->s->row_type != ROW_TYPE_REDUNDANT,
 
5651
                        norm_name);
 
5652
                if (error) {
 
5653
                        goto cleanup;
 
5654
                }
 
5655
        }
 
5656
 
 
5657
        if (primary_key_no != -1) {
 
5658
                /* In InnoDB the clustered index must always be created
 
5659
                first */
 
5660
                if ((error = create_index(trx, form, norm_name,
 
5661
                                          (uint) primary_key_no))) {
 
5662
                        goto cleanup;
 
5663
                }
 
5664
        }
 
5665
 
 
5666
        for (i = 0; i < form->s->keys; i++) {
 
5667
 
 
5668
                if (i != (uint) primary_key_no) {
 
5669
 
 
5670
                        if ((error = create_index(trx, form, norm_name, i))) {
 
5671
                                goto cleanup;
 
5672
                        }
 
5673
                }
 
5674
        }
 
5675
 
 
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);
 
5680
 
 
5681
                error = convert_error_code_to_mysql(error, NULL);
 
5682
 
 
5683
                if (error) {
 
5684
                        goto cleanup;
 
5685
                }
 
5686
        }
 
5687
 
 
5688
        innobase_commit_low(trx);
 
5689
 
 
5690
        row_mysql_unlock_data_dictionary(trx);
 
5691
 
 
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 */
 
5695
 
 
5696
        log_buffer_flush_to_disk();
 
5697
 
 
5698
        innobase_table = dict_table_get(norm_name, FALSE);
 
5699
 
 
5700
        DBUG_ASSERT(innobase_table != 0);
 
5701
 
 
5702
        /* Note: We can't call update_thd() as prebuilt will not be
 
5703
        setup at this stage and so we use thd. */
 
5704
 
 
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. */
 
5708
 
 
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) {
 
5713
 
 
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. */
 
5722
 
 
5723
                auto_inc_value = create_info->auto_increment_value;
 
5724
 
 
5725
                dict_table_autoinc_lock(innobase_table);
 
5726
                dict_table_autoinc_initialize(innobase_table, auto_inc_value);
 
5727
                dict_table_autoinc_unlock(innobase_table);
 
5728
        }
 
5729
 
 
5730
        /* Tell the InnoDB server that there might be work for
 
5731
        utility threads: */
 
5732
 
 
5733
        srv_active_wake_master_thread();
 
5734
 
 
5735
        trx_free_for_mysql(trx);
 
5736
 
 
5737
        DBUG_RETURN(0);
 
5738
 
 
5739
cleanup:
 
5740
        innobase_commit_low(trx);
 
5741
 
 
5742
        row_mysql_unlock_data_dictionary(trx);
 
5743
 
 
5744
        trx_free_for_mysql(trx);
 
5745
 
 
5746
        DBUG_RETURN(error);
 
5747
}
 
5748
 
 
5749
/*********************************************************************
 
5750
Discards or imports an InnoDB tablespace. */
 
5751
 
 
5752
int
 
5753
ha_innobase::discard_or_import_tablespace(
 
5754
/*======================================*/
 
5755
                                /* out: 0 == success, -1 == error */
 
5756
        my_bool discard)        /* in: TRUE if discard, else import */
 
5757
{
 
5758
        dict_table_t*   dict_table;
 
5759
        trx_t*          trx;
 
5760
        int             err;
 
5761
 
 
5762
        DBUG_ENTER("ha_innobase::discard_or_import_tablespace");
 
5763
 
 
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()));
 
5767
 
 
5768
        dict_table = prebuilt->table;
 
5769
        trx = prebuilt->trx;
 
5770
 
 
5771
        if (discard) {
 
5772
                err = row_discard_tablespace_for_mysql(dict_table->name, trx);
 
5773
        } else {
 
5774
                err = row_import_tablespace_for_mysql(dict_table->name, trx);
 
5775
        }
 
5776
 
 
5777
        err = convert_error_code_to_mysql(err, NULL);
 
5778
 
 
5779
        DBUG_RETURN(err);
 
5780
}
 
5781
 
 
5782
/*********************************************************************
 
5783
Deletes all rows of an InnoDB table. */
 
5784
 
 
5785
int
 
5786
ha_innobase::delete_all_rows(void)
 
5787
/*==============================*/
 
5788
                                /* out: error number */
 
5789
{
 
5790
        int             error;
 
5791
 
 
5792
        DBUG_ENTER("ha_innobase::delete_all_rows");
 
5793
 
 
5794
        /* Get the transaction associated with the current thd, or create one
 
5795
        if not yet created, and update prebuilt->trx */
 
5796
 
 
5797
        update_thd(ha_thd());
 
5798
 
 
5799
        if (thd_sql_command(user_thd) != SQLCOM_TRUNCATE) {
 
5800
        fallback:
 
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);
 
5805
        }
 
5806
 
 
5807
        /* Truncate the table in InnoDB */
 
5808
 
 
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() */
 
5812
                goto fallback;
 
5813
        }
 
5814
 
 
5815
        error = convert_error_code_to_mysql(error, NULL);
 
5816
 
 
5817
        DBUG_RETURN(error);
 
5818
}
 
5819
 
 
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
 
5825
inside InnoDB. */
 
5826
 
 
5827
int
 
5828
ha_innobase::delete_table(
 
5829
/*======================*/
 
5830
                                /* out: error number */
 
5831
        const char*     name)   /* in: table name */
 
5832
{
 
5833
        ulint   name_len;
 
5834
        int     error;
 
5835
        trx_t*  parent_trx;
 
5836
        trx_t*  trx;
 
5837
        THD     *thd = ha_thd();
 
5838
        char    norm_name[1000];
 
5839
 
 
5840
        DBUG_ENTER("ha_innobase::delete_table");
 
5841
 
 
5842
        /* Strangely, MySQL passes the table name without the '.frm'
 
5843
        extension, in contrast to ::create */
 
5844
        normalize_table_name(norm_name, name);
 
5845
 
 
5846
        if (IS_MAGIC_TABLE_AND_USER_DENIED_ACCESS(norm_name, thd)) {
 
5847
                DBUG_RETURN(HA_ERR_GENERIC);
 
5848
        }
 
5849
 
 
5850
        /* Get the transaction associated with the current thd, or create one
 
5851
        if not yet created */
 
5852
 
 
5853
        parent_trx = check_trx_exists(thd);
 
5854
 
 
5855
        /* In case MySQL calls this in the middle of a SELECT query, release
 
5856
        possible adaptive hash latch to avoid deadlocks of threads */
 
5857
 
 
5858
        trx_search_latch_release_if_reserved(parent_trx);
 
5859
 
 
5860
        if (lower_case_table_names) {
 
5861
                srv_lower_case_table_names = TRUE;
 
5862
        } else {
 
5863
                srv_lower_case_table_names = FALSE;
 
5864
        }
 
5865
 
 
5866
        trx = trx_allocate_for_mysql();
 
5867
 
 
5868
        trx->mysql_thd = thd;
 
5869
        trx->mysql_query_str = thd_query(thd);
 
5870
 
 
5871
        if (thd_test_options(thd, OPTION_NO_FOREIGN_KEY_CHECKS)) {
 
5872
                trx->check_foreigns = FALSE;
 
5873
        }
 
5874
 
 
5875
        if (thd_test_options(thd, OPTION_RELAXED_UNIQUE_CHECKS)) {
 
5876
                trx->check_unique_secondary = FALSE;
 
5877
        }
 
5878
 
 
5879
        name_len = strlen(name);
 
5880
 
 
5881
        assert(name_len < 1000);
 
5882
 
 
5883
        /* Drop the table in InnoDB */
 
5884
 
 
5885
        error = row_drop_table_for_mysql(norm_name, trx,
 
5886
                                         thd_sql_command(thd)
 
5887
                                         == SQLCOM_DROP_DB);
 
5888
 
 
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 */
 
5892
 
 
5893
        log_buffer_flush_to_disk();
 
5894
 
 
5895
        /* Tell the InnoDB server that there might be work for
 
5896
        utility threads: */
 
5897
 
 
5898
        srv_active_wake_master_thread();
 
5899
 
 
5900
        innobase_commit_low(trx);
 
5901
 
 
5902
        trx_free_for_mysql(trx);
 
5903
 
 
5904
        error = convert_error_code_to_mysql(error, NULL);
 
5905
 
 
5906
        DBUG_RETURN(error);
 
5907
}
 
5908
 
 
5909
/*********************************************************************
 
5910
Removes all tables in the named database inside InnoDB. */
 
5911
static
 
5912
void
 
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' */
 
5921
{
 
5922
        ulint   len             = 0;
 
5923
        trx_t*  parent_trx;
 
5924
        trx_t*  trx;
 
5925
        char*   ptr;
 
5926
        int     error;
 
5927
        char*   namebuf;
 
5928
        THD*    thd             = current_thd;
 
5929
 
 
5930
        /* Get the transaction associated with the current thd, or create one
 
5931
        if not yet created */
 
5932
 
 
5933
        parent_trx = check_trx_exists(thd);
 
5934
 
 
5935
        /* In case MySQL calls this in the middle of a SELECT query, release
 
5936
        possible adaptive hash latch to avoid deadlocks of threads */
 
5937
 
 
5938
        trx_search_latch_release_if_reserved(parent_trx);
 
5939
 
 
5940
        ptr = strend(path) - 2;
 
5941
 
 
5942
        while (ptr >= path && *ptr != '\\' && *ptr != '/') {
 
5943
                ptr--;
 
5944
                len++;
 
5945
        }
 
5946
 
 
5947
        ptr++;
 
5948
        namebuf = (char*) my_malloc((uint) len + 2, MYF(0));
 
5949
 
 
5950
        memcpy(namebuf, ptr, len);
 
5951
        namebuf[len] = '/';
 
5952
        namebuf[len + 1] = '\0';
 
5953
#ifdef  __WIN__
 
5954
        innobase_casedn_str(namebuf);
 
5955
#endif
 
5956
        trx = trx_allocate_for_mysql();
 
5957
        trx->mysql_thd = thd;
 
5958
        trx->mysql_query_str = thd_query(thd);
 
5959
 
 
5960
        if (thd_test_options(thd, OPTION_NO_FOREIGN_KEY_CHECKS)) {
 
5961
                trx->check_foreigns = FALSE;
 
5962
        }
 
5963
 
 
5964
        error = row_drop_database_for_mysql(namebuf, trx);
 
5965
        my_free(namebuf, MYF(0));
 
5966
 
 
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 */
 
5970
 
 
5971
        log_buffer_flush_to_disk();
 
5972
 
 
5973
        /* Tell the InnoDB server that there might be work for
 
5974
        utility threads: */
 
5975
 
 
5976
        srv_active_wake_master_thread();
 
5977
 
 
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);
 
5982
 
 
5983
        return(error);
 
5984
#else
 
5985
        return;
 
5986
#endif
 
5987
}
 
5988
 
 
5989
/*************************************************************************
 
5990
Renames an InnoDB table. */
 
5991
 
 
5992
int
 
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 */
 
5998
{
 
5999
        ulint   name_len1;
 
6000
        ulint   name_len2;
 
6001
        int     error;
 
6002
        trx_t*  parent_trx;
 
6003
        trx_t*  trx;
 
6004
        char    norm_from[1000];
 
6005
        char    norm_to[1000];
 
6006
        THD*    thd             = ha_thd();
 
6007
 
 
6008
        DBUG_ENTER("ha_innobase::rename_table");
 
6009
 
 
6010
        /* Get the transaction associated with the current thd, or create one
 
6011
        if not yet created */
 
6012
 
 
6013
        parent_trx = check_trx_exists(thd);
 
6014
 
 
6015
        /* In case MySQL calls this in the middle of a SELECT query, release
 
6016
        possible adaptive hash latch to avoid deadlocks of threads */
 
6017
 
 
6018
        trx_search_latch_release_if_reserved(parent_trx);
 
6019
 
 
6020
        if (lower_case_table_names) {
 
6021
                srv_lower_case_table_names = TRUE;
 
6022
        } else {
 
6023
                srv_lower_case_table_names = FALSE;
 
6024
        }
 
6025
 
 
6026
        trx = trx_allocate_for_mysql();
 
6027
        trx->mysql_thd = thd;
 
6028
        trx->mysql_query_str = thd_query(thd);
 
6029
 
 
6030
        if (thd_test_options(thd, OPTION_NO_FOREIGN_KEY_CHECKS)) {
 
6031
                trx->check_foreigns = FALSE;
 
6032
        }
 
6033
 
 
6034
        name_len1 = strlen(from);
 
6035
        name_len2 = strlen(to);
 
6036
 
 
6037
        assert(name_len1 < 1000);
 
6038
        assert(name_len2 < 1000);
 
6039
 
 
6040
        normalize_table_name(norm_from, from);
 
6041
        normalize_table_name(norm_to, to);
 
6042
 
 
6043
        /* Rename the table in InnoDB */
 
6044
 
 
6045
        error = row_rename_table_for_mysql(norm_from, norm_to, trx);
 
6046
 
 
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 */
 
6050
 
 
6051
        log_buffer_flush_to_disk();
 
6052
 
 
6053
        /* Tell the InnoDB server that there might be work for
 
6054
        utility threads: */
 
6055
 
 
6056
        srv_active_wake_master_thread();
 
6057
 
 
6058
        innobase_commit_low(trx);
 
6059
        trx_free_for_mysql(trx);
 
6060
 
 
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
 
6072
        error code. */
 
6073
        if (error == (int) DB_DUPLICATE_KEY) {
 
6074
                my_error(ER_TABLE_EXISTS_ERROR, MYF(0), to);
 
6075
 
 
6076
                error = DB_ERROR;
 
6077
        }
 
6078
 
 
6079
        error = convert_error_code_to_mysql(error, NULL);
 
6080
 
 
6081
        DBUG_RETURN(error);
 
6082
}
 
6083
 
 
6084
/*************************************************************************
 
6085
Estimates the number of index records in a range. */
 
6086
 
 
6087
ha_rows
 
6088
ha_innobase::records_in_range(
 
6089
/*==========================*/
 
6090
                                                /* out: estimated number of
 
6091
                                                rows */
 
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
 
6096
                                                   also be 0 */
 
6097
{
 
6098
        KEY*            key;
 
6099
        dict_index_t*   index;
 
6100
        uchar*          key_val_buff2   = (uchar*) my_malloc(
 
6101
                                                  table->s->reclength
 
6102
                                        + table->s->max_key_length + 100,
 
6103
                                                                MYF(MY_FAE));
 
6104
        ulint           buff2_len = table->s->reclength
 
6105
                                        + table->s->max_key_length + 100;
 
6106
        dtuple_t*       range_start;
 
6107
        dtuple_t*       range_end;
 
6108
        ib_longlong     n_rows;
 
6109
        ulint           mode1;
 
6110
        ulint           mode2;
 
6111
        void*           heap1;
 
6112
        void*           heap2;
 
6113
 
 
6114
        DBUG_ENTER("records_in_range");
 
6115
 
 
6116
        ut_a(prebuilt->trx == thd_to_trx(ha_thd()));
 
6117
 
 
6118
        prebuilt->trx->op_info = (char*)"estimating records in index range";
 
6119
 
 
6120
        /* In case MySQL calls this in the middle of a SELECT query, release
 
6121
        possible adaptive hash latch to avoid deadlocks of threads */
 
6122
 
 
6123
        trx_search_latch_release_if_reserved(prebuilt->trx);
 
6124
 
 
6125
        active_index = keynr;
 
6126
 
 
6127
        key = table->key_info + active_index;
 
6128
 
 
6129
        index = dict_table_get_index_noninline(prebuilt->table, key->name);
 
6130
 
 
6131
        range_start = dtuple_create_for_mysql(&heap1, key->key_parts);
 
6132
        dict_index_copy_types(range_start, index, key->key_parts);
 
6133
 
 
6134
        range_end = dtuple_create_for_mysql(&heap2, key->key_parts);
 
6135
        dict_index_copy_types(range_end, index, key->key_parts);
 
6136
 
 
6137
        row_sel_convert_mysql_key_to_innobase(
 
6138
                                range_start, (byte*) key_val_buff,
 
6139
                                (ulint)upd_and_key_val_buff_len,
 
6140
                                index,
 
6141
                                (byte*) (min_key ? min_key->key :
 
6142
                                         (const uchar*) 0),
 
6143
                                (ulint) (min_key ? min_key->length : 0),
 
6144
                                prebuilt->trx);
 
6145
 
 
6146
        row_sel_convert_mysql_key_to_innobase(
 
6147
                                range_end, (byte*) key_val_buff2,
 
6148
                                buff2_len, index,
 
6149
                                (byte*) (max_key ? max_key->key :
 
6150
                                         (const uchar*) 0),
 
6151
                                (ulint) (max_key ? max_key->length : 0),
 
6152
                                prebuilt->trx);
 
6153
 
 
6154
        mode1 = convert_search_mode_to_innobase(min_key ? min_key->flag :
 
6155
                                                HA_READ_KEY_EXACT);
 
6156
        mode2 = convert_search_mode_to_innobase(max_key ? max_key->flag :
 
6157
                                                HA_READ_KEY_EXACT);
 
6158
 
 
6159
        if (mode1 != PAGE_CUR_UNSUPP && mode2 != PAGE_CUR_UNSUPP) {
 
6160
 
 
6161
                n_rows = btr_estimate_n_rows_in_range(index, range_start,
 
6162
                                                      mode1, range_end,
 
6163
                                                      mode2);
 
6164
        } else {
 
6165
 
 
6166
                n_rows = HA_POS_ERROR;
 
6167
        }
 
6168
 
 
6169
        dtuple_free_for_mysql(heap1);
 
6170
        dtuple_free_for_mysql(heap2);
 
6171
 
 
6172
        my_free(key_val_buff2, MYF(0));
 
6173
 
 
6174
        prebuilt->trx->op_info = (char*)"";
 
6175
 
 
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! */
 
6181
 
 
6182
        if (n_rows == 0) {
 
6183
                n_rows = 1;
 
6184
        }
 
6185
 
 
6186
        DBUG_RETURN((ha_rows) n_rows);
 
6187
}
 
6188
 
 
6189
/*************************************************************************
 
6190
Gives an UPPER BOUND to the number of rows in a table. This is used in
 
6191
filesort.cc. */
 
6192
 
 
6193
ha_rows
 
6194
ha_innobase::estimate_rows_upper_bound(void)
 
6195
/*======================================*/
 
6196
                        /* out: upper bound of rows */
 
6197
{
 
6198
        dict_index_t*   index;
 
6199
        ulonglong       estimate;
 
6200
        ulonglong       local_data_file_length;
 
6201
 
 
6202
        DBUG_ENTER("estimate_rows_upper_bound");
 
6203
 
 
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
 
6206
        handle. */
 
6207
 
 
6208
        update_thd(ha_thd());
 
6209
 
 
6210
        prebuilt->trx->op_info = (char*)
 
6211
                                 "calculating upper bound for table rows";
 
6212
 
 
6213
        /* In case MySQL calls this in the middle of a SELECT query, release
 
6214
        possible adaptive hash latch to avoid deadlocks of threads */
 
6215
 
 
6216
        trx_search_latch_release_if_reserved(prebuilt->trx);
 
6217
 
 
6218
        index = dict_table_get_first_index_noninline(prebuilt->table);
 
6219
 
 
6220
        local_data_file_length = ((ulonglong) index->stat_n_leaf_pages)
 
6221
                                                        * UNIV_PAGE_SIZE;
 
6222
 
 
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. */
 
6227
 
 
6228
        estimate = 2 * local_data_file_length /
 
6229
                                         dict_index_calc_min_rec_len(index);
 
6230
 
 
6231
        prebuilt->trx->op_info = (char*)"";
 
6232
 
 
6233
        DBUG_RETURN((ha_rows) estimate);
 
6234
}
 
6235
 
 
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. */
 
6240
 
 
6241
double
 
6242
ha_innobase::scan_time()
 
6243
/*====================*/
 
6244
                        /* out: estimated time measured in disk seeks */
 
6245
{
 
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. */
 
6250
 
 
6251
        return((double) (prebuilt->table->stat_clustered_index_size));
 
6252
}
 
6253
 
 
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. */
 
6257
 
 
6258
double
 
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 */
 
6265
{
 
6266
        ha_rows total_rows;
 
6267
        double  time_for_scan;
 
6268
 
 
6269
        if (index != table->s->primary_key) {
 
6270
                /* Not clustered */
 
6271
                return(handler::read_time(index, ranges, rows));
 
6272
        }
 
6273
 
 
6274
        if (rows <= 2) {
 
6275
 
 
6276
                return((double) rows);
 
6277
        }
 
6278
 
 
6279
        /* Assume that the read time is proportional to the scan time for all
 
6280
        rows + at most one seek per range. */
 
6281
 
 
6282
        time_for_scan = scan_time();
 
6283
 
 
6284
        if ((total_rows = estimate_rows_upper_bound()) < rows) {
 
6285
 
 
6286
                return(time_for_scan);
 
6287
        }
 
6288
 
 
6289
        return(ranges + (double) rows / (double) total_rows * time_for_scan);
 
6290
}
 
6291
 
 
6292
/*************************************************************************
 
6293
Returns statistics information of the table to the MySQL interpreter,
 
6294
in various fields of the handle object. */
 
6295
 
 
6296
int
 
6297
ha_innobase::info(
 
6298
/*==============*/
 
6299
        uint flag)      /* in: what information MySQL requests */
 
6300
{
 
6301
        dict_table_t*   ib_table;
 
6302
        dict_index_t*   index;
 
6303
        ha_rows         rec_per_key;
 
6304
        ib_longlong     n_rows;
 
6305
        ulong           j;
 
6306
        ulong           i;
 
6307
        char            path[FN_REFLEN];
 
6308
        os_file_stat_t  stat_info;
 
6309
 
 
6310
        DBUG_ENTER("info");
 
6311
 
 
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. */
 
6315
 
 
6316
        if (srv_force_recovery >= SRV_FORCE_NO_IBUF_MERGE) {
 
6317
 
 
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
 
6321
                HA_ERR_CRASHED. */
 
6322
 
 
6323
                DBUG_RETURN(0);
 
6324
        }
 
6325
 
 
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
 
6328
        handle. */
 
6329
 
 
6330
        update_thd(ha_thd());
 
6331
 
 
6332
        /* In case MySQL calls this in the middle of a SELECT query, release
 
6333
        possible adaptive hash latch to avoid deadlocks of threads */
 
6334
 
 
6335
        prebuilt->trx->op_info = (char*)"returning various info to MySQL";
 
6336
 
 
6337
        trx_search_latch_release_if_reserved(prebuilt->trx);
 
6338
 
 
6339
        ib_table = prebuilt->table;
 
6340
 
 
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 */
 
6345
 
 
6346
                        prebuilt->trx->op_info = "updating table statistics";
 
6347
 
 
6348
                        dict_update_statistics(ib_table);
 
6349
 
 
6350
                        prebuilt->trx->op_info = "returning various info to MySQL";
 
6351
                }
 
6352
 
 
6353
                my_snprintf(path, sizeof(path), "%s/%s%s",
 
6354
                                mysql_data_home, ib_table->name, reg_ext);
 
6355
 
 
6356
                unpack_filename(path,path);
 
6357
 
 
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. */
 
6360
 
 
6361
                if (os_file_get_status(path,&stat_info)) {
 
6362
                        stats.create_time = (ulong) stat_info.ctime;
 
6363
                }
 
6364
        }
 
6365
 
 
6366
        if (flag & HA_STATUS_VARIABLE) {
 
6367
                n_rows = ib_table->stat_n_rows;
 
6368
 
 
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.
 
6372
 
 
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. */
 
6381
 
 
6382
                if (n_rows < 0) {
 
6383
                        n_rows = 0;
 
6384
                }
 
6385
 
 
6386
                if (n_rows == 0 && !(flag & HA_STATUS_TIME)) {
 
6387
                        n_rows++;
 
6388
                }
 
6389
 
 
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) {
 
6395
 
 
6396
                        n_rows = 1;
 
6397
 
 
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. */
 
6403
 
 
6404
                        prebuilt->autoinc_last_value = 0;
 
6405
                }
 
6406
 
 
6407
                stats.records = (ha_rows)n_rows;
 
6408
                stats.deleted = 0;
 
6409
                stats.data_file_length = ((ulonglong)
 
6410
                                ib_table->stat_clustered_index_size)
 
6411
                                        * UNIV_PAGE_SIZE;
 
6412
                stats.index_file_length = ((ulonglong)
 
6413
                                ib_table->stat_sum_of_other_index_sizes)
 
6414
                                        * UNIV_PAGE_SIZE;
 
6415
 
 
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.
 
6420
                See Bug#38185.
 
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)) {
 
6425
 
 
6426
                        /* lock the data dictionary to avoid races with
 
6427
                        ibd_file_missing and tablespace_discarded */
 
6428
                        row_mysql_lock_data_dictionary(prebuilt->trx);
 
6429
 
 
6430
                        /* ib_table->space must be an existent tablespace */
 
6431
                        if (!ib_table->ibd_file_missing
 
6432
                            && !ib_table->tablespace_discarded) {
 
6433
 
 
6434
                                stats.delete_length =
 
6435
                                        fsp_get_available_space_in_free_extents(
 
6436
                                                ib_table->space) * 1024;
 
6437
                        } else {
 
6438
 
 
6439
                                THD*    thd;
 
6440
 
 
6441
                                thd = ha_thd();
 
6442
 
 
6443
                                push_warning_printf(
 
6444
                                        thd,
 
6445
                                        MYSQL_ERROR::WARN_LEVEL_WARN,
 
6446
                                        ER_CANT_GET_STAT,
 
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.",
 
6452
                                        ib_table->name);
 
6453
 
 
6454
                                stats.delete_length = 0;
 
6455
                        }
 
6456
 
 
6457
                        row_mysql_unlock_data_dictionary(prebuilt->trx);
 
6458
                }
 
6459
 
 
6460
                stats.check_time = 0;
 
6461
 
 
6462
                if (stats.records == 0) {
 
6463
                        stats.mean_rec_length = 0;
 
6464
                } else {
 
6465
                        stats.mean_rec_length = (ulong) (stats.data_file_length / stats.records);
 
6466
                }
 
6467
        }
 
6468
 
 
6469
        if (flag & HA_STATUS_CONST) {
 
6470
                index = dict_table_get_first_index_noninline(ib_table);
 
6471
 
 
6472
                if (prebuilt->clust_index_was_generated) {
 
6473
                        index = dict_table_get_next_index_noninline(index);
 
6474
                }
 
6475
 
 
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",
 
6485
 
 
6486
                                                ib_table->name);
 
6487
                                break;
 
6488
                        }
 
6489
 
 
6490
                        for (j = 0; j < table->key_info[i].key_parts; j++) {
 
6491
 
 
6492
                                if (j + 1 > index->n_uniq) {
 
6493
                                        sql_print_error(
 
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 "
 
6496
"installations? "
 
6497
"See http://dev.mysql.com/doc/refman/5.1/en/innodb-troubleshooting.html\n",
 
6498
                                                        index->name,
 
6499
                                                        ib_table->name,
 
6500
                                                        (unsigned long)
 
6501
                                                        index->n_uniq, j + 1);
 
6502
                                        break;
 
6503
                                }
 
6504
 
 
6505
                                if (index->stat_n_diff_key_vals[j + 1] == 0) {
 
6506
 
 
6507
                                        rec_per_key = stats.records;
 
6508
                                } else {
 
6509
                                        rec_per_key = (ha_rows)(stats.records /
 
6510
                                         index->stat_n_diff_key_vals[j + 1]);
 
6511
                                }
 
6512
 
 
6513
                                /* Since MySQL seems to favor table scans
 
6514
                                too much over index searches, we pretend
 
6515
                                index selectivity is 2 times better than
 
6516
                                our estimate: */
 
6517
 
 
6518
                                rec_per_key = rec_per_key / 2;
 
6519
 
 
6520
                                if (rec_per_key == 0) {
 
6521
                                        rec_per_key = 1;
 
6522
                                }
 
6523
 
 
6524
                                table->key_info[i].rec_per_key[j]=
 
6525
                                  rec_per_key >= ~(ulong) 0 ? ~(ulong) 0 :
 
6526
                                  (ulong) rec_per_key;
 
6527
                        }
 
6528
 
 
6529
                        index = dict_table_get_next_index_noninline(index);
 
6530
                }
 
6531
        }
 
6532
 
 
6533
        if (flag & HA_STATUS_ERRKEY) {
 
6534
                ut_a(prebuilt->trx);
 
6535
                ut_a(prebuilt->trx->magic_n == TRX_MAGIC_N);
 
6536
 
 
6537
                errkey = (unsigned int) row_get_mysql_key_number_for_index(
 
6538
                        (dict_index_t*) trx_get_error_info(prebuilt->trx));
 
6539
        }
 
6540
 
 
6541
        if (flag & HA_STATUS_AUTO && table->found_next_number_field) {
 
6542
                stats.auto_increment_value = innobase_peek_autoinc();
 
6543
        }
 
6544
 
 
6545
        prebuilt->trx->op_info = (char*)"";
 
6546
 
 
6547
        DBUG_RETURN(0);
 
6548
}
 
6549
 
 
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. */
 
6553
 
 
6554
int
 
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 */
 
6560
{
 
6561
        /* Serialize ANALYZE TABLE inside InnoDB, see
 
6562
        Bug#38996 Race condition in ANALYZE TABLE */
 
6563
        pthread_mutex_lock(&analyze_mutex);
 
6564
 
 
6565
        /* Simply call ::info() with all the flags */
 
6566
        info(HA_STATUS_TIME | HA_STATUS_CONST | HA_STATUS_VARIABLE);
 
6567
 
 
6568
        pthread_mutex_unlock(&analyze_mutex);
 
6569
 
 
6570
        return(0);
 
6571
}
 
6572
 
 
6573
/**************************************************************************
 
6574
This is mapped to "ALTER TABLE tablename ENGINE=InnoDB", which rebuilds
 
6575
the table in MySQL. */
 
6576
 
 
6577
int
 
6578
ha_innobase::optimize(
 
6579
/*==================*/
 
6580
        THD*            thd,            /* in: connection thread handle */
 
6581
        HA_CHECK_OPT*   check_opt)      /* in: currently ignored */
 
6582
{
 
6583
        return(HA_ADMIN_TRY_ALTER);
 
6584
}
 
6585
 
 
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. */
 
6590
 
 
6591
int
 
6592
ha_innobase::check(
 
6593
/*===============*/
 
6594
                                        /* out: HA_ADMIN_CORRUPT or
 
6595
                                        HA_ADMIN_OK */
 
6596
        THD*            thd,            /* in: user thread handle */
 
6597
        HA_CHECK_OPT*   check_opt)      /* in: check options, currently
 
6598
                                        ignored */
 
6599
{
 
6600
        ulint           ret;
 
6601
 
 
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));
 
6606
 
 
6607
        if (prebuilt->mysql_template == NULL) {
 
6608
                /* Build the template; we will use a dummy template
 
6609
                in index scans done in checking */
 
6610
 
 
6611
                build_template(prebuilt, NULL, table, ROW_MYSQL_WHOLE_ROW);
 
6612
        }
 
6613
 
 
6614
        ret = row_check_table_for_mysql(prebuilt);
 
6615
 
 
6616
        if (ret == DB_SUCCESS) {
 
6617
                return(HA_ADMIN_OK);
 
6618
        }
 
6619
 
 
6620
        return(HA_ADMIN_CORRUPT);
 
6621
}
 
6622
 
 
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
 
6626
foreign keys. */
 
6627
 
 
6628
char*
 
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 */
 
6634
{
 
6635
        uint    length = (uint) strlen(comment);
 
6636
        char*   str;
 
6637
        long    flen;
 
6638
 
 
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
 
6641
        handle. */
 
6642
 
 
6643
        if (length > 64000 - 3) {
 
6644
                return((char*)comment); /* string too long */
 
6645
        }
 
6646
 
 
6647
        update_thd(ha_thd());
 
6648
 
 
6649
        prebuilt->trx->op_info = (char*)"returning table comment";
 
6650
 
 
6651
        /* In case MySQL calls this in the middle of a SELECT query, release
 
6652
        possible adaptive hash latch to avoid deadlocks of threads */
 
6653
 
 
6654
        trx_search_latch_release_if_reserved(prebuilt->trx);
 
6655
        str = NULL;
 
6656
 
 
6657
        /* output the data to a temporary file */
 
6658
 
 
6659
        mutex_enter_noninline(&srv_dict_tmpfile_mutex);
 
6660
        rewind(srv_dict_tmpfile);
 
6661
 
 
6662
        fprintf(srv_dict_tmpfile, "InnoDB free: %llu kB",
 
6663
                fsp_get_available_space_in_free_extents(
 
6664
                        prebuilt->table->space));
 
6665
 
 
6666
        dict_print_info_on_foreign_keys(FALSE, srv_dict_tmpfile,
 
6667
                                prebuilt->trx, prebuilt->table);
 
6668
        flen = ftell(srv_dict_tmpfile);
 
6669
        if (flen < 0) {
 
6670
                flen = 0;
 
6671
        } else if (length + flen + 3 > 64000) {
 
6672
                flen = 64000 - 3 - length;
 
6673
        }
 
6674
 
 
6675
        /* allocate buffer for the full string, and
 
6676
        read the contents of the temporary file */
 
6677
 
 
6678
        str = (char*) my_malloc(length + flen + 3, MYF(0));
 
6679
 
 
6680
        if (str) {
 
6681
                char* pos       = str + length;
 
6682
                if (length) {
 
6683
                        memcpy(str, comment, length);
 
6684
                        *pos++ = ';';
 
6685
                        *pos++ = ' ';
 
6686
                }
 
6687
                rewind(srv_dict_tmpfile);
 
6688
                flen = (uint) fread(pos, 1, flen, srv_dict_tmpfile);
 
6689
                pos[flen] = 0;
 
6690
        }
 
6691
 
 
6692
        mutex_exit_noninline(&srv_dict_tmpfile_mutex);
 
6693
 
 
6694
        prebuilt->trx->op_info = (char*)"";
 
6695
 
 
6696
        return(str ? str : (char*) comment);
 
6697
}
 
6698
 
 
6699
/***********************************************************************
 
6700
Gets the foreign key create info for a table stored in InnoDB. */
 
6701
 
 
6702
char*
 
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 */
 
6708
{
 
6709
        char*   str     = 0;
 
6710
        long    flen;
 
6711
 
 
6712
        ut_a(prebuilt != NULL);
 
6713
 
 
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
 
6716
        handle. */
 
6717
 
 
6718
        update_thd(ha_thd());
 
6719
 
 
6720
        prebuilt->trx->op_info = (char*)"getting info on foreign keys";
 
6721
 
 
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 */
 
6725
 
 
6726
        trx_search_latch_release_if_reserved(prebuilt->trx);
 
6727
 
 
6728
        mutex_enter_noninline(&srv_dict_tmpfile_mutex);
 
6729
        rewind(srv_dict_tmpfile);
 
6730
 
 
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*)"";
 
6735
 
 
6736
        flen = ftell(srv_dict_tmpfile);
 
6737
        if (flen < 0) {
 
6738
                flen = 0;
 
6739
        } else if (flen > 64000 - 1) {
 
6740
                flen = 64000 - 1;
 
6741
        }
 
6742
 
 
6743
        /* allocate buffer for the string, and
 
6744
        read the contents of the temporary file */
 
6745
 
 
6746
        str = (char*) my_malloc(flen + 1, MYF(0));
 
6747
 
 
6748
        if (str) {
 
6749
                rewind(srv_dict_tmpfile);
 
6750
                flen = (uint) fread(str, 1, flen, srv_dict_tmpfile);
 
6751
                str[flen] = 0;
 
6752
        }
 
6753
 
 
6754
        mutex_exit_noninline(&srv_dict_tmpfile_mutex);
 
6755
 
 
6756
        return(str);
 
6757
}
 
6758
 
 
6759
 
 
6760
int
 
6761
ha_innobase::get_foreign_key_list(THD *thd, List<FOREIGN_KEY_INFO> *f_key_list)
 
6762
{
 
6763
  dict_foreign_t* foreign;
 
6764
 
 
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);
 
6772
 
 
6773
  while (foreign != NULL) {
 
6774
          uint i;
 
6775
          FOREIGN_KEY_INFO f_key_info;
 
6776
          LEX_STRING *name= 0;
 
6777
          uint ulen;
 
6778
          char uname[NAME_LEN+1];           /* Unencoded name */
 
6779
          char db_name[NAME_LEN+1];
 
6780
          const char *tmp_buff;
 
6781
 
 
6782
          tmp_buff= foreign->id;
 
6783
          i= 0;
 
6784
          while (tmp_buff[i] != '/')
 
6785
                  i++;
 
6786
          tmp_buff+= i + 1;
 
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;
 
6790
 
 
6791
          /* Database name */
 
6792
          i= 0;
 
6793
          while (tmp_buff[i] != '/')
 
6794
          {
 
6795
            db_name[i]= tmp_buff[i];
 
6796
            i++;
 
6797
          }
 
6798
          db_name[i]= 0;
 
6799
          ulen= filename_to_tablename(db_name, uname, sizeof(uname));
 
6800
          f_key_info.referenced_db = thd_make_lex_string(thd, 0,
 
6801
                  uname, ulen, 1);
 
6802
 
 
6803
          /* Table name */
 
6804
          tmp_buff+= i + 1;
 
6805
          ulen= filename_to_tablename(tmp_buff, uname, sizeof(uname));
 
6806
          f_key_info.referenced_table = thd_make_lex_string(thd, 0,
 
6807
                  uname, ulen, 1);
 
6808
 
 
6809
          for (i= 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)
 
6819
                          break;
 
6820
          }
 
6821
 
 
6822
          ulong length;
 
6823
          if (foreign->type & DICT_FOREIGN_ON_DELETE_CASCADE)
 
6824
          {
 
6825
            length=7;
 
6826
            tmp_buff= "CASCADE";
 
6827
          }     
 
6828
          else if (foreign->type & DICT_FOREIGN_ON_DELETE_SET_NULL)
 
6829
          {
 
6830
            length=8;
 
6831
            tmp_buff= "SET NULL";
 
6832
          }
 
6833
          else if (foreign->type & DICT_FOREIGN_ON_DELETE_NO_ACTION)
 
6834
          {
 
6835
            length=9;
 
6836
            tmp_buff= "NO ACTION";
 
6837
          }
 
6838
          else
 
6839
          {
 
6840
            length=8;
 
6841
            tmp_buff= "RESTRICT";
 
6842
          }
 
6843
          f_key_info.delete_method = thd_make_lex_string(
 
6844
                  thd, f_key_info.delete_method, tmp_buff, length, 1);
 
6845
 
 
6846
 
 
6847
          if (foreign->type & DICT_FOREIGN_ON_UPDATE_CASCADE)
 
6848
          {
 
6849
            length=7;
 
6850
            tmp_buff= "CASCADE";
 
6851
          }
 
6852
          else if (foreign->type & DICT_FOREIGN_ON_UPDATE_SET_NULL)
 
6853
          {
 
6854
            length=8;
 
6855
            tmp_buff= "SET NULL";
 
6856
          }
 
6857
          else if (foreign->type & DICT_FOREIGN_ON_UPDATE_NO_ACTION)
 
6858
          {
 
6859
            length=9;
 
6860
            tmp_buff= "NO ACTION";
 
6861
          }
 
6862
          else
 
6863
          {
 
6864
            length=8;
 
6865
            tmp_buff= "RESTRICT";
 
6866
          }
 
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)
 
6871
          {
 
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);
 
6876
          }
 
6877
          else
 
6878
            f_key_info.referenced_key_name= 0;
 
6879
 
 
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);
 
6884
  }
 
6885
  mutex_exit_noninline(&(dict_sys->mutex));
 
6886
  prebuilt->trx->op_info = (char*)"";
 
6887
 
 
6888
  DBUG_RETURN(0);
 
6889
}
 
6890
 
 
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). */
 
6895
 
 
6896
bool
 
6897
ha_innobase::can_switch_engines(void)
 
6898
/*=================================*/
 
6899
{
 
6900
        bool    can_switch;
 
6901
 
 
6902
        DBUG_ENTER("ha_innobase::can_switch_engines");
 
6903
 
 
6904
        ut_a(prebuilt->trx == thd_to_trx(ha_thd()));
 
6905
 
 
6906
        prebuilt->trx->op_info =
 
6907
                        "determining if there are foreign key constraints";
 
6908
        row_mysql_lock_data_dictionary(prebuilt->trx);
 
6909
 
 
6910
        can_switch = !UT_LIST_GET_FIRST(prebuilt->table->referenced_list)
 
6911
                        && !UT_LIST_GET_FIRST(prebuilt->table->foreign_list);
 
6912
 
 
6913
        row_mysql_unlock_data_dictionary(prebuilt->trx);
 
6914
        prebuilt->trx->op_info = "";
 
6915
 
 
6916
        DBUG_RETURN(can_switch);
 
6917
}
 
6918
 
 
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. */
 
6924
 
 
6925
uint
 
6926
ha_innobase::referenced_by_foreign_key(void)
 
6927
/*========================================*/
 
6928
                        /* out: > 0 if referenced by a FOREIGN KEY */
 
6929
{
 
6930
        if (dict_table_referenced_by_foreign_key(prebuilt->table)) {
 
6931
 
 
6932
                return(1);
 
6933
        }
 
6934
 
 
6935
        return(0);
 
6936
}
 
6937
 
 
6938
/***********************************************************************
 
6939
Frees the foreign key create info for a table stored in InnoDB, if it is
 
6940
non-NULL. */
 
6941
 
 
6942
void
 
6943
ha_innobase::free_foreign_key_create_info(
 
6944
/*======================================*/
 
6945
        char*   str)    /* in, own: create info string to free  */
 
6946
{
 
6947
        if (str) {
 
6948
                my_free(str, MYF(0));
 
6949
        }
 
6950
}
 
6951
 
 
6952
/***********************************************************************
 
6953
Tells something additional to the handler about how to do things. */
 
6954
 
 
6955
int
 
6956
ha_innobase::extra(
 
6957
/*===============*/
 
6958
                           /* out: 0 or error number */
 
6959
        enum ha_extra_function operation)
 
6960
                           /* in: HA_EXTRA_FLUSH or some other flag */
 
6961
{
 
6962
        /* Warning: since it is not sure that MySQL calls external_lock
 
6963
        before calling this function, the trx field in prebuilt can be
 
6964
        obsolete! */
 
6965
 
 
6966
        switch (operation) {
 
6967
                case HA_EXTRA_FLUSH:
 
6968
                        if (prebuilt->blob_heap) {
 
6969
                                row_mysql_prebuilt_free_blob_heap(prebuilt);
 
6970
                        }
 
6971
                        break;
 
6972
                case HA_EXTRA_RESET_STATE:
 
6973
                        reset_template(prebuilt);
 
6974
                        break;
 
6975
                case HA_EXTRA_NO_KEYREAD:
 
6976
                        prebuilt->read_just_key = 0;
 
6977
                        break;
 
6978
                case HA_EXTRA_KEYREAD:
 
6979
                        prebuilt->read_just_key = 1;
 
6980
                        break;
 
6981
                case HA_EXTRA_KEYREAD_PRESERVE_FIELDS:
 
6982
                        prebuilt->keep_other_fields_on_keyread = 1;
 
6983
                        break;
 
6984
 
 
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;
 
6993
                        break;
 
6994
                case HA_EXTRA_WRITE_CAN_REPLACE:
 
6995
                        thd_to_trx(ha_thd())->duplicates |= TRX_DUP_REPLACE;
 
6996
                        break;
 
6997
                case HA_EXTRA_WRITE_CANNOT_REPLACE:
 
6998
                        thd_to_trx(ha_thd())->duplicates &= ~TRX_DUP_REPLACE;
 
6999
                        break;
 
7000
                case HA_EXTRA_NO_IGNORE_DUP_KEY:
 
7001
                        thd_to_trx(ha_thd())->duplicates &=
 
7002
                                ~(TRX_DUP_IGNORE | TRX_DUP_REPLACE);
 
7003
                        break;
 
7004
                default:/* Do nothing */
 
7005
                        ;
 
7006
        }
 
7007
 
 
7008
        return(0);
 
7009
}
 
7010
 
 
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()
 
7016
{
 
7017
        if (prebuilt->blob_heap) {
 
7018
                row_mysql_prebuilt_free_blob_heap(prebuilt);
 
7019
        }
 
7020
 
 
7021
        reset_template(prebuilt);
 
7022
 
 
7023
        /* TODO: This should really be reset in reset_template() but for now
 
7024
        it's safer to do it explicitly here. */
 
7025
 
 
7026
        /* This is a statement level counter. */
 
7027
        prebuilt->autoinc_last_value = 0;
 
7028
 
 
7029
        return(0);
 
7030
}
 
7031
 
 
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
 
7037
on that table.
 
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
 
7042
procedure. */
 
7043
 
 
7044
int
 
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)
 
7050
{
 
7051
        trx_t*          trx;
 
7052
 
 
7053
        update_thd(thd);
 
7054
 
 
7055
        trx = prebuilt->trx;
 
7056
 
 
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. */
 
7063
 
 
7064
        innobase_release_stat_resources(trx);
 
7065
 
 
7066
        /* Reset the AUTOINC statement level counter for multi-row INSERTs. */
 
7067
        trx->n_autoinc_rows = 0;
 
7068
 
 
7069
        prebuilt->sql_stat_start = TRUE;
 
7070
        prebuilt->hint_need_to_fetch_extra_cols = 0;
 
7071
        reset_template(prebuilt);
 
7072
 
 
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 */
 
7078
 
 
7079
                prebuilt->select_lock_type = LOCK_X;
 
7080
        } else {
 
7081
                if (trx->isolation_level != TRX_ISO_SERIALIZABLE
 
7082
                        && thd_sql_command(thd) == SQLCOM_SELECT
 
7083
                        && lock_type == TL_READ) {
 
7084
 
 
7085
                        /* For other than temporary tables, we obtain
 
7086
                        no lock for consistent read (plain SELECT). */
 
7087
 
 
7088
                        prebuilt->select_lock_type = LOCK_NONE;
 
7089
                } else {
 
7090
                        /* Not a consistent read: restore the
 
7091
                        select_lock_type value. The value of
 
7092
                        stored_select_lock_type was decided in:
 
7093
                        1) ::store_lock(),
 
7094
                        2) ::external_lock(),
 
7095
                        3) ::init_table_handle_for_HANDLER(), and
 
7096
                        4) ::transactional_table_lock(). */
 
7097
 
 
7098
                        prebuilt->select_lock_type =
 
7099
                                prebuilt->stored_select_lock_type;
 
7100
                }
 
7101
        }
 
7102
 
 
7103
        trx->detailed_error[0] = '\0';
 
7104
 
 
7105
        /* Set the MySQL flag to mark that there is an active transaction */
 
7106
        if (trx->active_trans == 0) {
 
7107
 
 
7108
                innobase_register_trx_and_stmt(ht, thd);
 
7109
                trx->active_trans = 1;
 
7110
        } else {
 
7111
                innobase_register_stmt(ht, thd);
 
7112
        }
 
7113
 
 
7114
        return(0);
 
7115
}
 
7116
 
 
7117
/**********************************************************************
 
7118
Maps a MySQL trx isolation level code to the InnoDB isolation level code */
 
7119
inline
 
7120
ulint
 
7121
innobase_map_isolation_level(
 
7122
/*=========================*/
 
7123
                                        /* out: InnoDB isolation level */
 
7124
        enum_tx_isolation       iso)    /* in: MySQL isolation level code */
 
7125
{
 
7126
        switch(iso) {
 
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);
 
7132
        }
 
7133
}
 
7134
 
 
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. */
 
7143
 
 
7144
int
 
7145
ha_innobase::external_lock(
 
7146
/*=======================*/
 
7147
                                /* out: 0 */
 
7148
        THD*    thd,            /* in: handle to the user thread */
 
7149
        int     lock_type)      /* in: lock type */
 
7150
{
 
7151
        trx_t*          trx;
 
7152
 
 
7153
        DBUG_ENTER("ha_innobase::external_lock");
 
7154
        DBUG_PRINT("enter",("lock_type: %d", lock_type));
 
7155
 
 
7156
        update_thd(thd);
 
7157
 
 
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)
 
7163
        {
 
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))
 
7169
                {
 
7170
                        char buf[256];
 
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);
 
7178
                }
 
7179
        }
 
7180
 
 
7181
 
 
7182
        trx = prebuilt->trx;
 
7183
 
 
7184
        prebuilt->sql_stat_start = TRUE;
 
7185
        prebuilt->hint_need_to_fetch_extra_cols = 0;
 
7186
 
 
7187
        reset_template(prebuilt);
 
7188
 
 
7189
        if (lock_type == F_WRLCK) {
 
7190
 
 
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;
 
7195
        }
 
7196
 
 
7197
        if (lock_type != F_UNLCK) {
 
7198
                /* MySQL is setting a new table lock */
 
7199
 
 
7200
                trx->detailed_error[0] = '\0';
 
7201
 
 
7202
                /* Set the MySQL flag to mark that there is an active
 
7203
                transaction */
 
7204
                if (trx->active_trans == 0) {
 
7205
 
 
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);
 
7210
                }
 
7211
 
 
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)) {
 
7216
 
 
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
 
7223
                        reads. */
 
7224
 
 
7225
                        prebuilt->select_lock_type = LOCK_S;
 
7226
                        prebuilt->stored_select_lock_type = LOCK_S;
 
7227
                }
 
7228
 
 
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.
 
7234
 
 
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). */
 
7239
 
 
7240
                if (prebuilt->select_lock_type != LOCK_NONE) {
 
7241
 
 
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)) {
 
7246
 
 
7247
                                ulint   error = row_lock_table_for_mysql(
 
7248
                                        prebuilt, NULL, 0);
 
7249
 
 
7250
                                if (error != DB_SUCCESS) {
 
7251
                                        error = convert_error_code_to_mysql(
 
7252
                                                (int) error, thd);
 
7253
                                        DBUG_RETURN((int) error);
 
7254
                                }
 
7255
                        }
 
7256
 
 
7257
                        trx->mysql_n_tables_locked++;
 
7258
                }
 
7259
 
 
7260
                trx->n_mysql_tables_in_use++;
 
7261
                prebuilt->mysql_has_locked = TRUE;
 
7262
 
 
7263
                DBUG_RETURN(0);
 
7264
        }
 
7265
 
 
7266
        /* MySQL is releasing a table lock */
 
7267
 
 
7268
        trx->n_mysql_tables_in_use--;
 
7269
        prebuilt->mysql_has_locked = FALSE;
 
7270
 
 
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. */
 
7274
 
 
7275
        innobase_release_stat_resources(trx);
 
7276
 
 
7277
        /* If the MySQL lock count drops to zero we know that the current SQL
 
7278
        statement has ended */
 
7279
 
 
7280
        if (trx->n_mysql_tables_in_use == 0) {
 
7281
 
 
7282
                trx->mysql_n_tables_locked = 0;
 
7283
                prebuilt->used_in_HANDLER = FALSE;
 
7284
 
 
7285
                if (!thd_test_options(thd, OPTION_NOT_AUTOCOMMIT | OPTION_BEGIN)) {
 
7286
                        if (trx->active_trans != 0) {
 
7287
                                innobase_commit(ht, thd, TRUE);
 
7288
                        }
 
7289
                } else {
 
7290
                        if (trx->isolation_level <= TRX_ISO_READ_COMMITTED
 
7291
                                                && trx->global_read_view) {
 
7292
 
 
7293
                                /* At low transaction isolation levels we let
 
7294
                                each consistent read set its own snapshot */
 
7295
 
 
7296
                                read_view_close_for_mysql(trx);
 
7297
                        }
 
7298
                }
 
7299
        }
 
7300
 
 
7301
        DBUG_RETURN(0);
 
7302
}
 
7303
 
 
7304
/**********************************************************************
 
7305
With this function MySQL request a transactional lock to a table when
 
7306
user issued query LOCK TABLES..WHERE ENGINE = InnoDB. */
 
7307
 
 
7308
int
 
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 */
 
7314
{
 
7315
        trx_t*          trx;
 
7316
 
 
7317
        DBUG_ENTER("ha_innobase::transactional_table_lock");
 
7318
        DBUG_PRINT("enter",("lock_type: %d", lock_type));
 
7319
 
 
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
 
7322
        handle. */
 
7323
 
 
7324
        update_thd(thd);
 
7325
 
 
7326
        if (prebuilt->table->ibd_file_missing && !thd_tablespace_op(thd)) {
 
7327
                ut_print_timestamp(stderr);
 
7328
                fprintf(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?"
 
7335
                        "InnoDB: See"
 
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);
 
7340
        }
 
7341
 
 
7342
        trx = prebuilt->trx;
 
7343
 
 
7344
        prebuilt->sql_stat_start = TRUE;
 
7345
        prebuilt->hint_need_to_fetch_extra_cols = 0;
 
7346
 
 
7347
        reset_template(prebuilt);
 
7348
 
 
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;
 
7355
        } else {
 
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);
 
7362
        }
 
7363
 
 
7364
        /* MySQL is setting a new transactional table lock */
 
7365
 
 
7366
        /* Set the MySQL flag to mark that there is an active transaction */
 
7367
        if (trx->active_trans == 0) {
 
7368
 
 
7369
                innobase_register_trx_and_stmt(ht, thd);
 
7370
                trx->active_trans = 1;
 
7371
        }
 
7372
 
 
7373
        if (THDVAR(thd, table_locks) && thd_in_lock_tables(thd)) {
 
7374
                ulint   error = DB_SUCCESS;
 
7375
 
 
7376
                error = row_lock_table_for_mysql(prebuilt, NULL, 0);
 
7377
 
 
7378
                if (error != DB_SUCCESS) {
 
7379
                        error = convert_error_code_to_mysql((int) error, thd);
 
7380
                        DBUG_RETURN((int) error);
 
7381
                }
 
7382
 
 
7383
                if (thd_test_options(thd, OPTION_NOT_AUTOCOMMIT | OPTION_BEGIN)) {
 
7384
 
 
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 */
 
7388
 
 
7389
                        trx_mark_sql_stat_end(trx);
 
7390
                }
 
7391
        }
 
7392
 
 
7393
        DBUG_RETURN(0);
 
7394
}
 
7395
 
 
7396
/****************************************************************************
 
7397
Here we export InnoDB status variables to MySQL.  */
 
7398
static
 
7399
int
 
7400
innodb_export_status()
 
7401
/*==================*/
 
7402
{
 
7403
        if (innodb_inited) {
 
7404
                srv_export_innodb_status();
 
7405
        }
 
7406
 
 
7407
        return 0;
 
7408
}
 
7409
 
 
7410
/****************************************************************************
 
7411
Implements the SHOW INNODB STATUS command. Sends the output of the InnoDB
 
7412
Monitor to the client. */
 
7413
static
 
7414
bool
 
7415
innodb_show_status(
 
7416
/*===============*/
 
7417
        handlerton*     hton,   /* in: the innodb handlerton */
 
7418
        THD*    thd,    /* in: the MySQL query thread of the caller */
 
7419
        stat_print_fn *stat_print)
 
7420
{
 
7421
        trx_t*                  trx;
 
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;
 
7426
 
 
7427
        DBUG_ENTER("innodb_show_status");
 
7428
 
 
7429
        trx = check_trx_exists(thd);
 
7430
 
 
7431
        innobase_release_stat_resources(trx);
 
7432
 
 
7433
        /* We let the InnoDB Monitor to output at most MAX_STATUS_SIZE
 
7434
        bytes of text. */
 
7435
 
 
7436
        long    flen, usable_len;
 
7437
        char*   str;
 
7438
 
 
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);
 
7445
 
 
7446
        if (flen < 0) {
 
7447
                flen = 0;
 
7448
        }
 
7449
 
 
7450
        if (flen > MAX_STATUS_SIZE) {
 
7451
                usable_len = MAX_STATUS_SIZE;
 
7452
        } else {
 
7453
                usable_len = flen;
 
7454
        }
 
7455
 
 
7456
        /* allocate buffer for the string, and
 
7457
        read the contents of the temporary file */
 
7458
 
 
7459
        if (!(str = (char*) my_malloc(usable_len + 1, MYF(0)))) {
 
7460
          mutex_exit_noninline(&srv_monitor_file_mutex);
 
7461
          DBUG_RETURN(TRUE);
 
7462
        }
 
7463
 
 
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);
 
7479
                flen = len;
 
7480
        } else {
 
7481
                /* Omit the end of the output. */
 
7482
                flen = (long) fread(str, 1, MAX_STATUS_SIZE - 1, srv_monitor_file);
 
7483
        }
 
7484
 
 
7485
        mutex_exit_noninline(&srv_monitor_file_mutex);
 
7486
 
 
7487
        bool result = FALSE;
 
7488
 
 
7489
        if (stat_print(thd, innobase_hton_name, (uint) strlen(innobase_hton_name),
 
7490
                        STRING_WITH_LEN(""), str, flen)) {
 
7491
                result= TRUE;
 
7492
        }
 
7493
        my_free(str, MYF(0));
 
7494
 
 
7495
        DBUG_RETURN(FALSE);
 
7496
}
 
7497
 
 
7498
/****************************************************************************
 
7499
Implements the SHOW MUTEX STATUS command. . */
 
7500
static
 
7501
bool
 
7502
innodb_mutex_show_status(
 
7503
/*=====================*/
 
7504
        handlerton*     hton,   /* in: the innodb handlerton */
 
7505
        THD*            thd,            /* in: the MySQL query thread of the
 
7506
                                        caller */
 
7507
        stat_print_fn*  stat_print)
 
7508
{
 
7509
        char buf1[IO_SIZE], buf2[IO_SIZE];
 
7510
        mutex_t*  mutex;
 
7511
#ifdef UNIV_DEBUG
 
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");
 
7521
 
 
7522
        mutex_enter_noninline(&mutex_list_mutex);
 
7523
 
 
7524
        mutex = UT_LIST_GET_FIRST(mutex_list);
 
7525
 
 
7526
        while (mutex != NULL) {
 
7527
#ifdef UNIV_DEBUG
 
7528
                if (mutex->mutex_type != 1) {
 
7529
                        if (mutex->count_using > 0) {
 
7530
                                buf1len= my_snprintf(buf1, sizeof(buf1),
 
7531
                                        "%s:%s",
 
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",
 
7538
                                        mutex->count_using,
 
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));
 
7544
 
 
7545
                                if (stat_print(thd, innobase_hton_name,
 
7546
                                                hton_name_len, buf1, buf1len,
 
7547
                                                buf2, buf2len)) {
 
7548
                                        mutex_exit_noninline(
 
7549
                                                &mutex_list_mutex);
 
7550
                                        DBUG_RETURN(1);
 
7551
                                }
 
7552
                        }
 
7553
                }
 
7554
                else {
 
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;
 
7561
                }
 
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);
 
7567
 
 
7568
                if (stat_print(thd, innobase_hton_name,
 
7569
                               hton_name_len, buf1, buf1len,
 
7570
                               buf2, buf2len)) {
 
7571
                        mutex_exit_noninline(&mutex_list_mutex);
 
7572
                        DBUG_RETURN(1);
 
7573
                }
 
7574
#endif /* UNIV_DEBUG */
 
7575
 
 
7576
                mutex = UT_LIST_GET_NEXT(list, mutex);
 
7577
        }
 
7578
 
 
7579
        mutex_exit_noninline(&mutex_list_mutex);
 
7580
 
 
7581
#ifdef UNIV_DEBUG
 
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));
 
7589
 
 
7590
        if (stat_print(thd, innobase_hton_name, hton_name_len,
 
7591
                        STRING_WITH_LEN("rw_lock_mutexes"), buf2, buf2len)) {
 
7592
                DBUG_RETURN(1);
 
7593
        }
 
7594
#endif /* UNIV_DEBUG */
 
7595
 
 
7596
        DBUG_RETURN(FALSE);
 
7597
}
 
7598
 
 
7599
static
 
7600
bool innobase_show_status(handlerton *hton, THD* thd, 
 
7601
                          stat_print_fn* stat_print,
 
7602
                          enum ha_stat_type stat_type)
 
7603
{
 
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);
 
7609
        default:
 
7610
                return FALSE;
 
7611
        }
 
7612
}
 
7613
 
 
7614
 
 
7615
/****************************************************************************
 
7616
 Handling the shared INNOBASE_SHARE structure that is needed to provide table
 
7617
 locking.
 
7618
****************************************************************************/
 
7619
 
 
7620
static uchar* innobase_get_key(INNOBASE_SHARE* share, size_t *length,
 
7621
        my_bool not_used __attribute__((unused)))
 
7622
{
 
7623
        *length=share->table_name_length;
 
7624
 
 
7625
        return (uchar*) share->table_name;
 
7626
}
 
7627
 
 
7628
static INNOBASE_SHARE* get_share(const char* table_name)
 
7629
{
 
7630
        INNOBASE_SHARE *share;
 
7631
        pthread_mutex_lock(&innobase_share_mutex);
 
7632
        uint length=(uint) strlen(table_name);
 
7633
 
 
7634
        if (!(share=(INNOBASE_SHARE*) hash_search(&innobase_open_tables,
 
7635
                                (uchar*) table_name,
 
7636
                                length))) {
 
7637
 
 
7638
                share = (INNOBASE_SHARE *) my_malloc(sizeof(*share)+length+1,
 
7639
                        MYF(MY_FAE | MY_ZEROFILL));
 
7640
 
 
7641
                share->table_name_length=length;
 
7642
                share->table_name=(char*) (share+1);
 
7643
                strmov(share->table_name,table_name);
 
7644
 
 
7645
                if (my_hash_insert(&innobase_open_tables,
 
7646
                                (uchar*) share)) {
 
7647
                        pthread_mutex_unlock(&innobase_share_mutex);
 
7648
                        my_free(share,0);
 
7649
 
 
7650
                        return 0;
 
7651
                }
 
7652
 
 
7653
                thr_lock_init(&share->lock);
 
7654
                pthread_mutex_init(&share->mutex,MY_MUTEX_INIT_FAST);
 
7655
        }
 
7656
 
 
7657
        share->use_count++;
 
7658
        pthread_mutex_unlock(&innobase_share_mutex);
 
7659
 
 
7660
        return share;
 
7661
}
 
7662
 
 
7663
static void free_share(INNOBASE_SHARE* share)
 
7664
{
 
7665
        pthread_mutex_lock(&innobase_share_mutex);
 
7666
 
 
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));
 
7672
        }
 
7673
 
 
7674
        pthread_mutex_unlock(&innobase_share_mutex);
 
7675
}
 
7676
 
 
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. */
 
7685
 
 
7686
THR_LOCK_DATA**
 
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
 
7699
                                                TL_IGNORE */
 
7700
{
 
7701
        trx_t*          trx;
 
7702
 
 
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. */
 
7706
 
 
7707
        trx = check_trx_exists(thd);
 
7708
 
 
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! */
 
7712
 
 
7713
        /* If no MySQL table is in use, we need to set the isolation level
 
7714
        of the transaction. */
 
7715
 
 
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));
 
7720
 
 
7721
                if (trx->isolation_level <= TRX_ISO_READ_COMMITTED
 
7722
                    && trx->global_read_view) {
 
7723
 
 
7724
                        /* At low transaction isolation levels we let
 
7725
                        each consistent read set its own snapshot */
 
7726
 
 
7727
                        read_view_close_for_mysql(trx);
 
7728
                }
 
7729
        }
 
7730
 
 
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);
 
7734
 
 
7735
        if (sql_command == SQLCOM_DROP_TABLE) {
 
7736
 
 
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. */ 
 
7740
 
 
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)) {
 
7747
 
 
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
 
7764
                used. */
 
7765
 
 
7766
                ulint   isolation_level;
 
7767
 
 
7768
                isolation_level = trx->isolation_level;
 
7769
 
 
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)) {
 
7777
 
 
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
 
7785
                        read for select. */
 
7786
 
 
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 */
 
7791
 
 
7792
                        prebuilt->select_lock_type = LOCK_NONE;
 
7793
                        prebuilt->stored_select_lock_type = LOCK_NONE;
 
7794
                } else {
 
7795
                        prebuilt->select_lock_type = LOCK_S;
 
7796
                        prebuilt->stored_select_lock_type = LOCK_S;
 
7797
                }
 
7798
 
 
7799
        } else if (lock_type != TL_IGNORE) {
 
7800
 
 
7801
                /* We set possible LOCK_X value in external_lock, not yet
 
7802
                here even if this would be SELECT ... FOR UPDATE */
 
7803
 
 
7804
                prebuilt->select_lock_type = LOCK_NONE;
 
7805
                prebuilt->stored_select_lock_type = LOCK_NONE;
 
7806
        }
 
7807
 
 
7808
        if (lock_type != TL_IGNORE && lock.type == TL_UNLOCK) {
 
7809
 
 
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). */
 
7817
 
 
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. */
 
7830
 
 
7831
                        lock_type = TL_READ_NO_INSERT;
 
7832
                }
 
7833
 
 
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.
 
7838
 
 
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
 
7842
                TRUE there). */
 
7843
 
 
7844
                if ((lock_type >= TL_WRITE_CONCURRENT_INSERT
 
7845
                     && lock_type <= TL_WRITE)
 
7846
                    && !(in_lock_tables
 
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) {
 
7852
 
 
7853
                        lock_type = TL_WRITE_ALLOW_WRITE;
 
7854
                }
 
7855
 
 
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.
 
7861
 
 
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). */
 
7865
 
 
7866
                if (lock_type == TL_READ_NO_INSERT
 
7867
                    && sql_command != SQLCOM_LOCK_TABLES) {
 
7868
 
 
7869
                        lock_type = TL_READ;
 
7870
                }
 
7871
 
 
7872
                lock.type = lock_type;
 
7873
        }
 
7874
 
 
7875
        *to++= &lock;
 
7876
 
 
7877
        return(to);
 
7878
}
 
7879
 
 
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. */
 
7884
 
 
7885
ulong
 
7886
ha_innobase::innobase_get_autoinc(
 
7887
/*==============================*/
 
7888
                                        /* out: DB_SUCCESS or error code */
 
7889
        ulonglong*      value)          /* out: autoinc value */
 
7890
{
 
7891
        *value = 0;
 
7892
 
 
7893
        prebuilt->autoinc_error = innobase_lock_autoinc();
 
7894
 
 
7895
        if (prebuilt->autoinc_error == DB_SUCCESS) {
 
7896
 
 
7897
                /* Determine the first value of the interval */
 
7898
                *value = dict_table_autoinc_read(prebuilt->table);
 
7899
 
 
7900
                /* It should have been initialized during open. */
 
7901
                if (*value == 0) {
 
7902
                        prebuilt->autoinc_error = DB_UNSUPPORTED;
 
7903
                        dict_table_autoinc_unlock(prebuilt->table);
 
7904
                }
 
7905
        }
 
7906
  
 
7907
        return(ulong(prebuilt->autoinc_error));
 
7908
}
 
7909
 
 
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. */
 
7913
 
 
7914
ulonglong
 
7915
ha_innobase::innobase_peek_autoinc()
 
7916
/*================================*/
 
7917
                                        /* out: the autoinc value */
 
7918
{
 
7919
        ulonglong       auto_inc;
 
7920
        dict_table_t*   innodb_table;
 
7921
 
 
7922
        ut_a(prebuilt != NULL);
 
7923
        ut_a(prebuilt->table != NULL);
 
7924
 
 
7925
        innodb_table = prebuilt->table;
 
7926
 
 
7927
        dict_table_autoinc_lock(innodb_table);
 
7928
 
 
7929
        auto_inc = dict_table_autoinc_read(innodb_table);
 
7930
 
 
7931
        ut_a(auto_inc > 0);
 
7932
 
 
7933
        dict_table_autoinc_unlock(innodb_table);
 
7934
 
 
7935
        return(auto_inc);
 
7936
}
 
7937
 
 
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)            */
 
7945
 
 
7946
void
 
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 */
 
7954
{
 
7955
        trx_t*          trx;
 
7956
        ulint           error;
 
7957
        ulonglong       autoinc = 0;
 
7958
 
 
7959
        /* Prepare prebuilt->trx in the table handle */
 
7960
        update_thd(ha_thd());
 
7961
 
 
7962
        error = innobase_get_autoinc(&autoinc);
 
7963
 
 
7964
        if (error != DB_SUCCESS) {
 
7965
                *first_value = (~(ulonglong) 0);
 
7966
                return;
 
7967
        }
 
7968
 
 
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()).
 
7975
        */
 
7976
 
 
7977
        trx = prebuilt->trx;
 
7978
 
 
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
 
7982
        be 0 or not. */
 
7983
 
 
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);
 
7988
 
 
7989
        /* Called for the first time ? */
 
7990
        if (trx->n_autoinc_rows == 0) {
 
7991
 
 
7992
                trx->n_autoinc_rows = (ulint) nb_desired_values;
 
7993
 
 
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) {
 
7997
 
 
7998
                        trx->n_autoinc_rows = 1;
 
7999
                }
 
8000
 
 
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;
 
8010
        }
 
8011
 
 
8012
        *nb_reserved_values = trx->n_autoinc_rows;
 
8013
 
 
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) {
 
8017
                ulonglong       need;
 
8018
                ulonglong       current;
 
8019
                ulonglong       next_value;
 
8020
 
 
8021
                current = *first_value > col_max_value ? autoinc : *first_value;
 
8022
                need = *nb_reserved_values * increment;
 
8023
 
 
8024
                /* Compute the last value in the interval */
 
8025
                next_value = innobase_next_autoinc(
 
8026
                        current, need, offset, col_max_value);
 
8027
 
 
8028
                prebuilt->autoinc_last_value = next_value;
 
8029
 
 
8030
                if (prebuilt->autoinc_last_value < *first_value) {
 
8031
                        *first_value = (~(ulonglong) 0);
 
8032
                } else {
 
8033
                        /* Update the table autoinc variable */
 
8034
                        dict_table_autoinc_update_if_greater(
 
8035
                                prebuilt->table, prebuilt->autoinc_last_value);
 
8036
                }
 
8037
        } else {
 
8038
                /* This will force write_row() into attempting an update
 
8039
                of the table's AUTOINC counter. */
 
8040
                prebuilt->autoinc_last_value = 0;
 
8041
        }
 
8042
 
 
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
 
8046
        the increment. */
 
8047
        prebuilt->autoinc_offset = offset;
 
8048
        prebuilt->autoinc_increment = increment;
 
8049
 
 
8050
        dict_table_autoinc_unlock(prebuilt->table);
 
8051
}
 
8052
 
 
8053
/* See comment in handler.h */
 
8054
int
 
8055
ha_innobase::reset_auto_increment(
 
8056
/*==============================*/
 
8057
        ulonglong       value)          /* in: new value for table autoinc */
 
8058
{
 
8059
        DBUG_ENTER("ha_innobase::reset_auto_increment");
 
8060
 
 
8061
        int     error;
 
8062
 
 
8063
        update_thd(ha_thd());
 
8064
 
 
8065
        error = row_lock_table_autoinc_for_mysql(prebuilt);
 
8066
 
 
8067
        if (error != DB_SUCCESS) {
 
8068
                error = convert_error_code_to_mysql(error, user_thd);
 
8069
 
 
8070
                DBUG_RETURN(error);
 
8071
        }
 
8072
 
 
8073
        /* The next value can never be 0. */
 
8074
        if (value == 0) {
 
8075
                value = 1;
 
8076
        }
 
8077
 
 
8078
        innobase_reset_autoinc(value);
 
8079
 
 
8080
        DBUG_RETURN(0);
 
8081
}
 
8082
 
 
8083
/* See comment in handler.cc */
 
8084
bool
 
8085
ha_innobase::get_error_message(int error, String *buf)
 
8086
{
 
8087
        trx_t*  trx = check_trx_exists(ha_thd());
 
8088
 
 
8089
        buf->copy(trx->detailed_error, (uint) strlen(trx->detailed_error),
 
8090
                system_charset_info);
 
8091
 
 
8092
        return FALSE;
 
8093
}
 
8094
 
 
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. */
 
8099
 
 
8100
int
 
8101
ha_innobase::cmp_ref(
 
8102
/*=================*/
 
8103
                                /* out: < 0 if ref1 < ref2, 0 if equal, else
 
8104
                                > 0 */
 
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 */
 
8109
{
 
8110
        enum_field_types mysql_type;
 
8111
        Field*          field;
 
8112
        KEY_PART_INFO*  key_part;
 
8113
        KEY_PART_INFO*  key_part_end;
 
8114
        uint            len1;
 
8115
        uint            len2;
 
8116
        int             result;
 
8117
 
 
8118
        if (prebuilt->clust_index_was_generated) {
 
8119
                /* The 'ref' is an InnoDB row id */
 
8120
 
 
8121
                return(memcmp(ref1, ref2, DATA_ROW_ID_LEN));
 
8122
        }
 
8123
 
 
8124
        /* Do a type-aware comparison of primary key fields. PK fields
 
8125
        are always NOT NULL, so no checks for NULL are performed. */
 
8126
 
 
8127
        key_part = table->key_info[table->s->primary_key].key_part;
 
8128
 
 
8129
        key_part_end = key_part
 
8130
                        + table->key_info[table->s->primary_key].key_parts;
 
8131
 
 
8132
        for (; key_part != key_part_end; ++key_part) {
 
8133
                field = key_part->field;
 
8134
                mysql_type = field->type();
 
8135
 
 
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) {
 
8140
 
 
8141
                        /* In the MySQL key value format, a column prefix of
 
8142
                        a BLOB is preceded by a 2-byte length field */
 
8143
 
 
8144
                        len1 = innobase_read_from_2_little_endian(ref1);
 
8145
                        len2 = innobase_read_from_2_little_endian(ref2);
 
8146
 
 
8147
                        ref1 += 2;
 
8148
                        ref2 += 2;
 
8149
                        result = ((Field_blob*)field)->cmp( ref1, len1,
 
8150
                                                            ref2, len2);
 
8151
                } else {
 
8152
                        result = field->key_cmp(ref1, ref2);
 
8153
                }
 
8154
 
 
8155
                if (result) {
 
8156
 
 
8157
                        return(result);
 
8158
                }
 
8159
 
 
8160
                ref1 += key_part->store_length;
 
8161
                ref2 += key_part->store_length;
 
8162
        }
 
8163
 
 
8164
        return(0);
 
8165
}
 
8166
 
 
8167
/***********************************************************************
 
8168
Ask InnoDB if a query to a table can be cached. */
 
8169
 
 
8170
my_bool
 
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 */
 
8181
        qc_engine_callback*
 
8182
                        call_back,      /* out: pointer to function for
 
8183
                                        checking if query caching
 
8184
                                        is permitted */
 
8185
        ulonglong       *engine_data)   /* in/out: data to call_back */
 
8186
{
 
8187
        *call_back = innobase_query_caching_of_table_permitted;
 
8188
        *engine_data = 0;
 
8189
        return(innobase_query_caching_of_table_permitted(thd, table_key,
 
8190
                                                         key_length,
 
8191
                                                         engine_data));
 
8192
}
 
8193
 
 
8194
char*
 
8195
ha_innobase::get_mysql_bin_log_name()
 
8196
{
 
8197
        return(trx_sys_mysql_bin_log_name);
 
8198
}
 
8199
 
 
8200
ulonglong
 
8201
ha_innobase::get_mysql_bin_log_pos()
 
8202
{
 
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. */
 
8205
 
 
8206
        return(trx_sys_mysql_bin_log_pos);
 
8207
}
 
8208
 
 
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.
 
8214
 
 
8215
NOTE: the prototype of this function is copied to data0type.c! If you change
 
8216
this function, you MUST change also data0type.c! */
 
8217
extern "C"
 
8218
ulint
 
8219
innobase_get_at_most_n_mbchars(
 
8220
/*===========================*/
 
8221
                                /* out: number of bytes occupied by the first
 
8222
                                n characters */
 
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 */
 
8229
{
 
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 */
 
8233
 
 
8234
        charset = get_charset((uint) charset_id, MYF(MY_WME));
 
8235
 
 
8236
        ut_ad(charset);
 
8237
        ut_ad(charset->mbmaxlen);
 
8238
 
 
8239
        /* Calculate how many characters at most the prefix index contains */
 
8240
 
 
8241
        n_chars = prefix_len / charset->mbmaxlen;
 
8242
 
 
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
 
8246
        character. */
 
8247
 
 
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.
 
8252
 
 
8253
                Why does the code below work:
 
8254
                Suppose that we are looking for n UTF-8 characters.
 
8255
 
 
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.
 
8261
 
 
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
 
8265
                whole string. */
 
8266
 
 
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;
 
8271
                }
 
8272
        } else {
 
8273
                if (data_len < prefix_len) {
 
8274
                        char_length = data_len;
 
8275
                } else {
 
8276
                        char_length = prefix_len;
 
8277
                }
 
8278
        }
 
8279
 
 
8280
        return(char_length);
 
8281
}
 
8282
 
 
8283
/***********************************************************************
 
8284
This function is used to prepare X/Open XA distributed transaction   */
 
8285
static
 
8286
int
 
8287
innobase_xa_prepare(
 
8288
/*================*/
 
8289
                        /* out: 0 or error number */
 
8290
        handlerton *hton,
 
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 */
 
8295
{
 
8296
        int error = 0;
 
8297
        trx_t* trx = check_trx_exists(thd);
 
8298
 
 
8299
        if (thd_sql_command(thd) != SQLCOM_XA_PREPARE &&
 
8300
            (all || !thd_test_options(thd, OPTION_NOT_AUTOCOMMIT | OPTION_BEGIN)))
 
8301
        {
 
8302
 
 
8303
                /* For ibbackup to work the order of transactions in binlog
 
8304
                and InnoDB must be the same. Consider the situation
 
8305
 
 
8306
                  thread1> prepare; write to binlog; ...
 
8307
                          <context switch>
 
8308
                  thread2> prepare; write to binlog; commit
 
8309
                  thread1>                           ... commit
 
8310
 
 
8311
                To ensure this will not happen we're taking the mutex on
 
8312
                prepare, and releasing it on commit.
 
8313
 
 
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;
 
8323
        }
 
8324
 
 
8325
        if (!THDVAR(thd, support_xa)) {
 
8326
 
 
8327
                return(0);
 
8328
        }
 
8329
 
 
8330
        thd_get_xid(thd, (MYSQL_XID*) &trx->xid);
 
8331
 
 
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. */
 
8335
 
 
8336
        innobase_release_stat_resources(trx);
 
8337
 
 
8338
        if (trx->active_trans == 0 && trx->conc_state != TRX_NOT_STARTED) {
 
8339
 
 
8340
          sql_print_error("trx->active_trans == 0, but trx->conc_state != "
 
8341
                          "TRX_NOT_STARTED");
 
8342
        }
 
8343
 
 
8344
        if (all
 
8345
                || (!thd_test_options(thd, OPTION_NOT_AUTOCOMMIT | OPTION_BEGIN))) {
 
8346
 
 
8347
                /* We were instructed to prepare the whole transaction, or
 
8348
                this is an SQL statement end and autocommit is on */
 
8349
 
 
8350
                ut_ad(trx->active_trans);
 
8351
 
 
8352
                error = (int) trx_prepare_for_mysql(trx);
 
8353
        } else {
 
8354
                /* We just mark the SQL statement ended and do not do a
 
8355
                transaction prepare */
 
8356
 
 
8357
                /* If we had reserved the auto-inc lock for some
 
8358
                table in this SQL statement we release it now */
 
8359
 
 
8360
                row_unlock_table_autoinc_for_mysql(trx);
 
8361
 
 
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
 
8364
                SQL statement */
 
8365
 
 
8366
                trx_mark_sql_stat_end(trx);
 
8367
        }
 
8368
 
 
8369
        /* Tell the InnoDB server that there might be work for utility
 
8370
        threads: */
 
8371
 
 
8372
        srv_active_wake_master_thread();
 
8373
 
 
8374
        return error;
 
8375
}
 
8376
 
 
8377
/***********************************************************************
 
8378
This function is used to recover X/Open XA distributed transactions   */
 
8379
static
 
8380
int
 
8381
innobase_xa_recover(
 
8382
/*================*/
 
8383
                                /* out: number of prepared transactions
 
8384
                                stored in xid_list */
 
8385
        handlerton *hton,
 
8386
        XID*    xid_list,       /* in/out: prepared transactions */
 
8387
        uint    len)            /* in: number of slots in xid_list */
 
8388
{
 
8389
        if (len == 0 || xid_list == NULL) {
 
8390
 
 
8391
                return(0);
 
8392
        }
 
8393
 
 
8394
        return(trx_recover_for_mysql(xid_list, len));
 
8395
}
 
8396
 
 
8397
/***********************************************************************
 
8398
This function is used to commit one X/Open XA distributed transaction
 
8399
which is in the prepared state */
 
8400
static
 
8401
int
 
8402
innobase_commit_by_xid(
 
8403
/*===================*/
 
8404
                        /* out: 0 or error number */
 
8405
        handlerton *hton,
 
8406
        XID*    xid)    /* in: X/Open XA transaction identification */
 
8407
{
 
8408
        trx_t*  trx;
 
8409
 
 
8410
        trx = trx_get_trx_by_xid(xid);
 
8411
 
 
8412
        if (trx) {
 
8413
                innobase_commit_low(trx);
 
8414
 
 
8415
                return(XA_OK);
 
8416
        } else {
 
8417
                return(XAER_NOTA);
 
8418
        }
 
8419
}
 
8420
 
 
8421
/***********************************************************************
 
8422
This function is used to rollback one X/Open XA distributed transaction
 
8423
which is in the prepared state */
 
8424
static
 
8425
int
 
8426
innobase_rollback_by_xid(
 
8427
/*=====================*/
 
8428
                        /* out: 0 or error number */
 
8429
        handlerton *hton,
 
8430
        XID     *xid)   /* in: X/Open XA transaction identification */
 
8431
{
 
8432
        trx_t*  trx;
 
8433
 
 
8434
        trx = trx_get_trx_by_xid(xid);
 
8435
 
 
8436
        if (trx) {
 
8437
                return(innobase_rollback_trx(trx));
 
8438
        } else {
 
8439
                return(XAER_NOTA);
 
8440
        }
 
8441
}
 
8442
 
 
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
 
8447
using a cursor. */
 
8448
static
 
8449
void*
 
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 */
 
8455
{
 
8456
        return(read_cursor_view_create_for_mysql(check_trx_exists(thd)));
 
8457
}
 
8458
 
 
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. */
 
8463
static
 
8464
void
 
8465
innobase_close_cursor_view(
 
8466
/*=======================*/
 
8467
        handlerton *hton,
 
8468
        THD*    thd,    /* in: user thread handle */
 
8469
        void*   curview)/* in: Consistent read view to be closed */
 
8470
{
 
8471
        read_cursor_view_close_for_mysql(check_trx_exists(thd),
 
8472
                                         (cursor_view_t*) curview);
 
8473
}
 
8474
 
 
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. */
 
8480
static
 
8481
void
 
8482
innobase_set_cursor_view(
 
8483
/*=====================*/
 
8484
        handlerton *hton,
 
8485
        THD*    thd,    /* in: user thread handle */
 
8486
        void*   curview)/* in: Consistent cursor view to be set */
 
8487
{
 
8488
        read_cursor_set_for_mysql(check_trx_exists(thd),
 
8489
                                  (cursor_view_t*) curview);
 
8490
}
 
8491
 
 
8492
 
 
8493
/***********************************************************************
 
8494
Check whether any of the given columns is being renamed in the table. */
 
8495
static
 
8496
bool
 
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 */
 
8504
{
 
8505
        uint            j;
 
8506
        uint            k;
 
8507
        Field*          field;
 
8508
        const char*     col_name;
 
8509
 
 
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,
 
8516
                                                   col_name) == 0) {
 
8517
                                return(true);
 
8518
                        }
 
8519
                }
 
8520
        }
 
8521
 
 
8522
        return(false);
 
8523
}
 
8524
 
 
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. */
 
8529
static
 
8530
bool
 
8531
foreign_key_column_is_being_renamed(
 
8532
/*================================*/
 
8533
                                        /* out: true if a column that
 
8534
                                        participates in a foreign key definition
 
8535
                                        is being renamed */
 
8536
        row_prebuilt_t* prebuilt,       /* in: InnoDB prebuilt struct */
 
8537
        TABLE*          table)          /* in: MySQL table */
 
8538
{
 
8539
        dict_foreign_t* foreign;
 
8540
 
 
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 */
 
8545
 
 
8546
                return(false);
 
8547
        }
 
8548
 
 
8549
        row_mysql_lock_data_dictionary(prebuilt->trx);
 
8550
 
 
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);
 
8554
             foreign != NULL;
 
8555
             foreign = UT_LIST_GET_NEXT(referenced_list, foreign)) {
 
8556
 
 
8557
                if (column_is_being_renamed(table, foreign->n_fields,
 
8558
                                            foreign->referenced_col_names)) {
 
8559
 
 
8560
                        row_mysql_unlock_data_dictionary(prebuilt->trx);
 
8561
                        return(true);
 
8562
                }
 
8563
        }
 
8564
 
 
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);
 
8568
             foreign != NULL;
 
8569
             foreign = UT_LIST_GET_NEXT(foreign_list, foreign)) {
 
8570
 
 
8571
                if (column_is_being_renamed(table, foreign->n_fields,
 
8572
                                            foreign->foreign_col_names)) {
 
8573
 
 
8574
                        row_mysql_unlock_data_dictionary(prebuilt->trx);
 
8575
                        return(true);
 
8576
                }
 
8577
        }
 
8578
 
 
8579
        row_mysql_unlock_data_dictionary(prebuilt->trx);
 
8580
 
 
8581
        return(false);
 
8582
}
 
8583
 
 
8584
bool ha_innobase::check_if_incompatible_data(
 
8585
        HA_CREATE_INFO* info,
 
8586
        uint            table_changes)
 
8587
{
 
8588
        if (table_changes != IS_EQUAL_YES) {
 
8589
 
 
8590
                return COMPATIBLE_DATA_NO;
 
8591
        }
 
8592
 
 
8593
        /* Check that auto_increment value was not changed */
 
8594
        if ((info->used_fields & HA_CREATE_USED_AUTO) &&
 
8595
                info->auto_increment_value != 0) {
 
8596
 
 
8597
                return COMPATIBLE_DATA_NO;
 
8598
        }
 
8599
 
 
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)) {
 
8603
 
 
8604
                return COMPATIBLE_DATA_NO;
 
8605
        }
 
8606
 
 
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) {
 
8610
 
 
8611
                return COMPATIBLE_DATA_NO;
 
8612
        }
 
8613
 
 
8614
        return COMPATIBLE_DATA_YES;
 
8615
}
 
8616
 
 
8617
static int show_innodb_vars(THD *thd, SHOW_VAR *var, char *buff)
 
8618
{
 
8619
  innodb_export_status();
 
8620
  var->type= SHOW_ARRAY;
 
8621
  var->value= (char *) &innodb_status_variables;
 
8622
  return 0;
 
8623
}
 
8624
 
 
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. */
 
8629
static
 
8630
bool
 
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 */
 
8639
{
 
8640
        KEY*            key;
 
8641
        uint            key_num;        /* index number */
 
8642
 
 
8643
        for (key_num = 0; key_num < form->s->keys; key_num++) {
 
8644
                key = form->key_info + key_num;
 
8645
 
 
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 "
 
8655
                                            "index.",
 
8656
                                            innobase_index_reserve_name);
 
8657
 
 
8658
                        return(true);
 
8659
                }
 
8660
        }
 
8661
 
 
8662
        return(false);
 
8663
}
 
8664
 
 
8665
static SHOW_VAR innodb_status_variables_export[]= {
 
8666
  {"Innodb",                   (char*) &show_innodb_vars, SHOW_FUNC},
 
8667
  {NullS, NullS, SHOW_LONG}
 
8668
};
 
8669
 
 
8670
static struct st_mysql_storage_engine innobase_storage_engine=
 
8671
{ MYSQL_HANDLERTON_INTERFACE_VERSION };
 
8672
 
 
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.",
 
8678
  NULL, NULL, TRUE);
 
8679
 
 
8680
static MYSQL_SYSVAR_STR(data_home_dir, innobase_data_home_dir,
 
8681
  PLUGIN_VAR_READONLY,
 
8682
  "The common part for InnoDB table spaces.",
 
8683
  NULL, NULL, NULL);
 
8684
 
 
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.",
 
8689
  NULL, NULL, TRUE);
 
8690
 
 
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)"
 
8695
  /*
 
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.
 
8698
  */
 
8699
  IF_NETWARE("", " or 2 (fastest - crash-like)")
 
8700
  ".",
 
8701
  NULL, NULL, 1, 0, IF_NETWARE(1,2), 0);
 
8702
 
 
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.",
 
8706
  NULL, NULL, FALSE);
 
8707
 
 
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);
 
8714
 
 
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);
 
8718
 
 
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.",
 
8722
  NULL, NULL, FALSE);
 
8723
 
 
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);
 
8728
 
 
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 */
 
8733
 
 
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);
 
8737
 
 
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);
 
8742
 
 
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);
 
8747
 
 
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)",
 
8751
  NULL, NULL, FALSE);
 
8752
 
 
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",
 
8756
  NULL, NULL, FALSE);
 
8757
 
 
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)",
 
8761
  NULL, NULL, TRUE);
 
8762
 
 
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).",
 
8769
  NULL, NULL, TRUE);
 
8770
 
 
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.",
 
8775
  NULL, NULL, TRUE);
 
8776
 
 
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);
 
8781
 
 
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);
 
8786
 
 
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);
 
8791
 
 
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);
 
8796
 
 
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);
 
8801
 
 
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);
 
8806
 
 
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);
 
8811
 
 
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);
 
8816
 
 
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);
 
8821
 
 
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);
 
8826
 
 
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);
 
8831
 
 
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);
 
8836
 
 
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);
 
8841
 
 
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);
 
8846
 
 
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);
 
8851
 
 
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);
 
8856
 
 
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.",
 
8860
  NULL, NULL, NULL);
 
8861
 
 
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"
 
8866
  " compatibility)                                           "
 
8867
  "1 => New style AUTOINC locking                            "
 
8868
  "2 => No AUTOINC locking (unsafe for SBR)",
 
8869
  NULL, NULL,
 
8870
  AUTOINC_NEW_STYLE_LOCKING,    /* Default setting */
 
8871
  AUTOINC_OLD_STYLE_LOCKING,    /* Minimum value */
 
8872
  AUTOINC_NO_LOCKING, 0);       /* Maximum value */
 
8873
 
 
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),
 
8915
  NULL
 
8916
};
 
8917
 
 
8918
mysql_declare_plugin(innobase)
 
8919
{
 
8920
  MYSQL_STORAGE_ENGINE_PLUGIN,
 
8921
  &innobase_storage_engine,
 
8922
  innobase_hton_name,
 
8923
  "Innobase OY",
 
8924
  "Supports transactions, row-level locking, and foreign keys",
 
8925
  PLUGIN_LICENSE_GPL,
 
8926
  innobase_init, /* Plugin Init */
 
8927
  NULL, /* Plugin Deinit */
 
8928
  0x0100 /* 1.0 */,
 
8929
  innodb_status_variables_export,/* status variables             */
 
8930
  innobase_system_variables, /* system variables */
 
8931
  NULL /* reserved */
 
8932
}
 
8933
mysql_declare_plugin_end;
 
8934
 
 
8935
/** @brief Initialize the default value of innodb_commit_concurrency.
 
8936
 
 
8937
Once InnoDB is running, the innodb_commit_concurrency must not change
 
8938
from zero to nonzero. (Bug #42101)
 
8939
 
 
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. */
 
8944
static
 
8945
void
 
8946
innobase_commit_concurrency_init_default(void)
 
8947
/*==========================================*/
 
8948
{
 
8949
        MYSQL_SYSVAR_NAME(commit_concurrency).def_val
 
8950
                = innobase_commit_concurrency;
 
8951
}