~percona-dev/percona-innodb-plugin/percona-innodb-1.0

« back to all changes in this revision

Viewing changes to handler/ha_innodb.cc

  • Committer: Vadim Tkachenko
  • Date: 2008-12-01 02:05:57 UTC
  • Revision ID: vadim@percona.com-20081201020557-p7k2m94mjtdg1a83
New rw-locks

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
/* TODO list for the InnoDB handler in 5.0:
 
17
  - Remove the flag trx->active_trans and look at trx->conc_state
 
18
  - fix savepoint functions to use savepoint storage area
 
19
  - Find out what kind of problems the OS X case-insensitivity causes to
 
20
    table and database names; should we 'normalize' the names like we do
 
21
    in Windows?
 
22
*/
 
23
 
 
24
#ifdef USE_PRAGMA_IMPLEMENTATION
 
25
#pragma implementation                          // gcc: Class implementation
 
26
#endif
 
27
 
 
28
#include <mysql_priv.h>
 
29
#include <mysqld_error.h>
 
30
 
 
31
#include <m_ctype.h>
 
32
#include <hash.h>
 
33
#include <myisampack.h>
 
34
#include <mysys_err.h>
 
35
#include <my_sys.h>
 
36
#include <mysql/plugin.h>
 
37
 
 
38
/* Include necessary InnoDB headers */
 
39
extern "C" {
 
40
#include "../storage/innobase/include/univ.i"
 
41
#include "../storage/innobase/include/btr0sea.h"
 
42
#include "../storage/innobase/include/os0file.h"
 
43
#include "../storage/innobase/include/os0thread.h"
 
44
#include "../storage/innobase/include/srv0start.h"
 
45
#include "../storage/innobase/include/srv0srv.h"
 
46
#include "../storage/innobase/include/trx0roll.h"
 
47
#include "../storage/innobase/include/trx0trx.h"
 
48
#include "../storage/innobase/include/trx0sys.h"
 
49
#include "../storage/innobase/include/mtr0mtr.h"
 
50
#include "../storage/innobase/include/row0ins.h"
 
51
#include "../storage/innobase/include/row0mysql.h"
 
52
#include "../storage/innobase/include/row0sel.h"
 
53
#include "../storage/innobase/include/row0upd.h"
 
54
#include "../storage/innobase/include/log0log.h"
 
55
#include "../storage/innobase/include/lock0lock.h"
 
56
#include "../storage/innobase/include/dict0crea.h"
 
57
#include "../storage/innobase/include/btr0cur.h"
 
58
#include "../storage/innobase/include/btr0btr.h"
 
59
#include "../storage/innobase/include/fsp0fsp.h"
 
60
#include "../storage/innobase/include/sync0sync.h"
 
61
#include "../storage/innobase/include/fil0fil.h"
 
62
#include "../storage/innobase/include/trx0xa.h"
 
63
#include "../storage/innobase/include/row0merge.h"
 
64
#include "../storage/innobase/include/thr0loc.h"
 
65
#include "../storage/innobase/include/dict0boot.h"
 
66
#include "../storage/innobase/include/ha_prototypes.h"
 
67
#include "../storage/innobase/include/ut0mem.h"
 
68
}
 
69
 
 
70
#include "ha_innodb.h"
 
71
#include "i_s.h"
 
72
 
 
73
#ifndef MYSQL_SERVER
 
74
/* This is needed because of Bug #3596.  Let us hope that pthread_mutex_t
 
75
is defined the same in both builds: the MySQL server and the InnoDB plugin. */
 
76
extern pthread_mutex_t LOCK_thread_count;
 
77
 
 
78
#if MYSQL_VERSION_ID < 50124
 
79
/* this is defined in mysql_priv.h inside #ifdef MYSQL_SERVER
 
80
but we need it here */
 
81
bool check_global_access(THD *thd, ulong want_access);
 
82
#endif /* MYSQL_VERSION_ID < 50124 */
 
83
#endif /* MYSQL_SERVER */
 
84
 
 
85
/** to protect innobase_open_files */
 
86
static pthread_mutex_t innobase_share_mutex;
 
87
/** to force correct commit order in binlog */
 
88
static pthread_mutex_t prepare_commit_mutex;
 
89
static ulong commit_threads = 0;
 
90
static pthread_mutex_t commit_threads_m;
 
91
static pthread_cond_t commit_cond;
 
92
static pthread_mutex_t commit_cond_m;
 
93
static bool innodb_inited = 0;
 
94
 
 
95
#define INSIDE_HA_INNOBASE_CC
 
96
 
 
97
#ifdef MYSQL_DYNAMIC_PLUGIN
 
98
/* These must be weak global variables in the dynamic plugin. */
 
99
struct handlerton* innodb_hton_ptr;
 
100
int builtin_innobase_plugin;
 
101
/********************************************************************
 
102
Copy InnoDB system variables from the static InnoDB to the dynamic
 
103
plugin. */
 
104
static
 
105
bool
 
106
innodb_plugin_init(void);
 
107
/*====================*/
 
108
                /* out: TRUE if the dynamic InnoDB plugin should start */
 
109
#else /* MYSQL_DYNAMIC_PLUGIN */
 
110
/* This must be a global variable in the statically linked InnoDB. */
 
111
struct handlerton* innodb_hton_ptr = NULL;
 
112
#endif /* MYSQL_DYNAMIC_PLUGIN */
 
113
 
 
114
static const long AUTOINC_OLD_STYLE_LOCKING = 0;
 
115
static const long AUTOINC_NEW_STYLE_LOCKING = 1;
 
116
static const long AUTOINC_NO_LOCKING = 2;
 
117
 
 
118
static long innobase_mirrored_log_groups, innobase_log_files_in_group,
 
119
        innobase_log_buffer_size,
 
120
        innobase_additional_mem_pool_size, innobase_file_io_threads,
 
121
        innobase_lock_wait_timeout, innobase_force_recovery,
 
122
        innobase_open_files, innobase_autoinc_lock_mode;
 
123
 
 
124
static long long innobase_buffer_pool_size, innobase_log_file_size;
 
125
 
 
126
/* The default values for the following char* start-up parameters
 
127
are determined in innobase_init below: */
 
128
 
 
129
static char*    innobase_data_home_dir                  = NULL;
 
130
static char*    innobase_data_file_path                 = NULL;
 
131
static char*    innobase_log_group_home_dir             = NULL;
 
132
static char*    innobase_file_format_name               = NULL;
 
133
 
 
134
/* Note: This variable can be set to on/off and any of the supported
 
135
file formats in the configuration file, but can only be set to any
 
136
of the supported file formats during runtime. */
 
137
static char*    innobase_file_format_check              = NULL;
 
138
 
 
139
/* The following has a misleading name: starting from 4.0.5, this also
 
140
affects Windows: */
 
141
static char*    innobase_unix_file_flush_method         = NULL;
 
142
 
 
143
/* Below we have boolean-valued start-up parameters, and their default
 
144
values */
 
145
 
 
146
static ulong    innobase_fast_shutdown                  = 1;
 
147
#ifdef UNIV_LOG_ARCHIVE
 
148
static my_bool  innobase_log_archive                    = FALSE;
 
149
static char*    innobase_log_arch_dir                   = NULL;
 
150
#endif /* UNIV_LOG_ARCHIVE */
 
151
static my_bool  innobase_use_doublewrite                = TRUE;
 
152
static my_bool  innobase_use_checksums                  = TRUE;
 
153
static my_bool  innobase_locks_unsafe_for_binlog        = FALSE;
 
154
static my_bool  innobase_rollback_on_timeout            = FALSE;
 
155
static my_bool  innobase_create_status_file             = FALSE;
 
156
static my_bool innobase_stats_on_metadata               = TRUE;
 
157
static my_bool  innobase_adaptive_hash_index            = TRUE;
 
158
 
 
159
static char*    internal_innobase_data_file_path        = NULL;
 
160
 
 
161
static char*    innodb_version_str = (char*) INNODB_VERSION_STR;
 
162
 
 
163
/* The following counter is used to convey information to InnoDB
 
164
about server activity: in selects it is not sensible to call
 
165
srv_active_wake_master_thread after each fetch or search, we only do
 
166
it every INNOBASE_WAKE_INTERVAL'th step. */
 
167
 
 
168
#define INNOBASE_WAKE_INTERVAL  32
 
169
static ulong    innobase_active_counter = 0;
 
170
 
 
171
static HASH     innobase_open_tables;
 
172
 
 
173
#ifdef __NETWARE__      /* some special cleanup for NetWare */
 
174
bool nw_panic = FALSE;
 
175
#endif
 
176
 
 
177
static uchar* innobase_get_key(INNOBASE_SHARE *share, size_t *length,
 
178
        my_bool not_used __attribute__((unused)));
 
179
static INNOBASE_SHARE *get_share(const char *table_name);
 
180
static void free_share(INNOBASE_SHARE *share);
 
181
static int innobase_close_connection(handlerton *hton, THD* thd);
 
182
static int innobase_commit(handlerton *hton, THD* thd, bool all);
 
183
static int innobase_rollback(handlerton *hton, THD* thd, bool all);
 
184
static int innobase_rollback_to_savepoint(handlerton *hton, THD* thd, 
 
185
           void *savepoint);
 
186
static int innobase_savepoint(handlerton *hton, THD* thd, void *savepoint);
 
187
static int innobase_release_savepoint(handlerton *hton, THD* thd, 
 
188
           void *savepoint);
 
189
static handler *innobase_create_handler(handlerton *hton,
 
190
                                        TABLE_SHARE *table,
 
191
                                        MEM_ROOT *mem_root);
 
192
 
 
193
/****************************************************************
 
194
Validate the file format name and return its corresponding id. */
 
195
static
 
196
uint
 
197
innobase_file_format_name_lookup(
 
198
/*=============================*/
 
199
                                                /* out: valid file format id */
 
200
        const char*     format_name);           /* in: pointer to file format
 
201
                                                name */
 
202
/****************************************************************
 
203
Validate the file format check config parameters, as a side affect it
 
204
sets the srv_check_file_format_at_startup variable. */
 
205
static
 
206
bool
 
207
innobase_file_format_check_on_off(
 
208
/*==============================*/
 
209
                                                /* out: true if one of 
 
210
                                                "on" or "off" */
 
211
        const char*     format_check);          /* in: parameter value */
 
212
/****************************************************************
 
213
Validate the file format check config parameters, as a side affect it
 
214
sets the srv_check_file_format_at_startup variable. */
 
215
static
 
216
bool
 
217
innobase_file_format_check_validate(
 
218
/*================================*/
 
219
                                                /* out: true if valid
 
220
                                                config value */
 
221
        const char*     format_check);          /* in: parameter value */
 
222
/*****************************************************************
 
223
Check if it is a valid file format. This function is registered as
 
224
a callback with MySQL. */
 
225
static
 
226
int
 
227
innodb_file_format_name_validate(
 
228
/*=============================*/
 
229
                                                /* out: 0 for valid file
 
230
                                                format */
 
231
        THD*                            thd,    /* in: thread handle */
 
232
        struct st_mysql_sys_var*        var,    /* in: pointer to system
 
233
                                                variable */
 
234
        void*                           save,   /* out: immediate result
 
235
                                                for update function */
 
236
        struct st_mysql_value*          value); /* in: incoming string */
 
237
/********************************************************************
 
238
Update the system variable innodb_file_format using the "saved"
 
239
value. This function is registered as a callback with MySQL. */
 
240
static
 
241
bool
 
242
innodb_file_format_name_update(
 
243
/*===========================*/
 
244
                                                /* out: should never
 
245
                                                fail since it is
 
246
                                                already validated */
 
247
        THD*                            thd,    /* in: thread handle */
 
248
        struct st_mysql_sys_var*        var,    /* in: pointer to
 
249
                                                system variable */
 
250
        void*                           var_ptr,/* out: where the
 
251
                                                formal string goes */
 
252
        void*                           save);  /* in: immediate result
 
253
                                                from check function */
 
254
/*****************************************************************
 
255
Check if it is a valid file format. This function is registered as
 
256
a callback with MySQL. */
 
257
static
 
258
int
 
259
innodb_file_format_check_validate(
 
260
/*==============================*/
 
261
                                                /* out: 0 for valid file
 
262
                                                format */
 
263
        THD*                            thd,    /* in: thread handle */
 
264
        struct st_mysql_sys_var*        var,    /* in: pointer to system
 
265
                                                variable */
 
266
        void*                           save,   /* out: immediate result
 
267
                                                for update function */
 
268
        struct st_mysql_value*          value); /* in: incoming string */
 
269
/********************************************************************
 
270
Update the system variable innodb_file_format_check using the "saved"
 
271
value. This function is registered as a callback with MySQL. */
 
272
static
 
273
bool
 
274
innodb_file_format_check_update(
 
275
/*============================*/
 
276
                                                /* out: should never
 
277
                                                fail since it is
 
278
                                                already validated */
 
279
        THD*                            thd,    /* in: thread handle */
 
280
        struct st_mysql_sys_var*        var,    /* in: pointer to
 
281
                                                system variable */
 
282
        void*                           var_ptr,/* out: where the
 
283
                                                formal string goes */
 
284
        void*                           save);  /* in: immediate result
 
285
                                                from check function */
 
286
 
 
287
/********************************************************************
 
288
Return alter table flags supported in an InnoDB database. */
 
289
static
 
290
uint
 
291
innobase_alter_table_flags(
 
292
/*=======================*/
 
293
        uint    flags);
 
294
 
 
295
static const char innobase_hton_name[]= "InnoDB";
 
296
 
 
297
static MYSQL_THDVAR_BOOL(support_xa, PLUGIN_VAR_OPCMDARG,
 
298
  "Enable InnoDB support for the XA two-phase commit",
 
299
  /* check_func */ NULL, /* update_func */ NULL,
 
300
  /* default */ TRUE);
 
301
 
 
302
static MYSQL_THDVAR_BOOL(table_locks, PLUGIN_VAR_OPCMDARG,
 
303
  "Enable InnoDB locking in LOCK TABLES",
 
304
  /* check_func */ NULL, /* update_func */ NULL,
 
305
  /* default */ TRUE);
 
306
 
 
307
static MYSQL_THDVAR_BOOL(strict_mode,
 
308
  PLUGIN_VAR_NOCMDARG,
 
309
  "Use strict mode when evaluating create options.",
 
310
  NULL, NULL, FALSE);
 
311
 
 
312
 
 
313
static handler *innobase_create_handler(handlerton *hton,
 
314
                                        TABLE_SHARE *table, 
 
315
                                        MEM_ROOT *mem_root)
 
316
{
 
317
  return new (mem_root) ha_innobase(hton, table);
 
318
}
 
319
 
 
320
/***********************************************************************
 
321
This function is used to prepare X/Open XA distributed transaction   */
 
322
static
 
323
int
 
324
innobase_xa_prepare(
 
325
/*================*/
 
326
                        /* out: 0 or error number */
 
327
        handlerton* hton,
 
328
        THD*    thd,    /* in: handle to the MySQL thread of the user
 
329
                        whose XA transaction should be prepared */
 
330
        bool    all);   /* in: TRUE - commit transaction
 
331
                        FALSE - the current SQL statement ended */
 
332
/***********************************************************************
 
333
This function is used to recover X/Open XA distributed transactions   */
 
334
static
 
335
int
 
336
innobase_xa_recover(
 
337
/*================*/
 
338
                                /* out: number of prepared transactions
 
339
                                stored in xid_list */
 
340
        handlerton* hton,
 
341
        XID*    xid_list,       /* in/out: prepared transactions */
 
342
        uint    len);           /* in: number of slots in xid_list */
 
343
/***********************************************************************
 
344
This function is used to commit one X/Open XA distributed transaction
 
345
which is in the prepared state */
 
346
static
 
347
int
 
348
innobase_commit_by_xid(
 
349
/*===================*/
 
350
                        /* out: 0 or error number */
 
351
        handlerton* hton,
 
352
        XID*    xid);   /* in: X/Open XA transaction identification */
 
353
/***********************************************************************
 
354
This function is used to rollback one X/Open XA distributed transaction
 
355
which is in the prepared state */
 
356
static
 
357
int
 
358
innobase_rollback_by_xid(
 
359
/*=====================*/
 
360
                        /* out: 0 or error number */
 
361
        handlerton* hton,
 
362
        XID     *xid);  /* in: X/Open XA transaction identification */
 
363
/***********************************************************************
 
364
Create a consistent view for a cursor based on current transaction
 
365
which is created if the corresponding MySQL thread still lacks one.
 
366
This consistent view is then used inside of MySQL when accessing records
 
367
using a cursor. */
 
368
static
 
369
void*
 
370
innobase_create_cursor_view(
 
371
/*========================*/
 
372
                                /* out: pointer to cursor view or NULL */
 
373
        handlerton*     hton,   /* in: innobase hton */
 
374
        THD*            thd);   /* in: user thread handle */
 
375
/***********************************************************************
 
376
Set the given consistent cursor view to a transaction which is created
 
377
if the corresponding MySQL thread still lacks one. If the given
 
378
consistent cursor view is NULL global read view of a transaction is
 
379
restored to a transaction read view. */
 
380
static
 
381
void
 
382
innobase_set_cursor_view(
 
383
/*=====================*/
 
384
        handlerton* hton,
 
385
        THD*    thd,    /* in: user thread handle */
 
386
        void*   curview);/* in: Consistent cursor view to be set */
 
387
/***********************************************************************
 
388
Close the given consistent cursor view of a transaction and restore
 
389
global read view to a transaction read view. Transaction is created if the
 
390
corresponding MySQL thread still lacks one. */
 
391
static
 
392
void
 
393
innobase_close_cursor_view(
 
394
/*=======================*/
 
395
        handlerton* hton,
 
396
        THD*    thd,    /* in: user thread handle */
 
397
        void*   curview);/* in: Consistent read view to be closed */
 
398
/*********************************************************************
 
399
Removes all tables in the named database inside InnoDB. */
 
400
static
 
401
void
 
402
innobase_drop_database(
 
403
/*===================*/
 
404
                        /* out: error number */
 
405
        handlerton* hton, /* in: handlerton of Innodb */
 
406
        char*   path);  /* in: database path; inside InnoDB the name
 
407
                        of the last directory in the path is used as
 
408
                        the database name: for example, in 'mysql/data/test'
 
409
                        the database name is 'test' */
 
410
/***********************************************************************
 
411
Closes an InnoDB database. */
 
412
static
 
413
int
 
414
innobase_end(handlerton *hton, ha_panic_function type);
 
415
 
 
416
/*********************************************************************
 
417
Creates an InnoDB transaction struct for the thd if it does not yet have one.
 
418
Starts a new InnoDB transaction if a transaction is not yet started. And
 
419
assigns a new snapshot for a consistent read if the transaction does not yet
 
420
have one. */
 
421
static
 
422
int
 
423
innobase_start_trx_and_assign_read_view(
 
424
/*====================================*/
 
425
                        /* out: 0 */
 
426
        handlerton* hton, /* in: Innodb handlerton */ 
 
427
        THD*    thd);   /* in: MySQL thread handle of the user for whom
 
428
                        the transaction should be committed */
 
429
/********************************************************************
 
430
Flushes InnoDB logs to disk and makes a checkpoint. Really, a commit flushes
 
431
the logs, and the name of this function should be innobase_checkpoint. */
 
432
static
 
433
bool
 
434
innobase_flush_logs(
 
435
/*================*/
 
436
                                /* out: TRUE if error */
 
437
        handlerton*     hton);  /* in: InnoDB handlerton */
 
438
 
 
439
/****************************************************************************
 
440
Implements the SHOW INNODB STATUS command. Sends the output of the InnoDB
 
441
Monitor to the client. */
 
442
static
 
443
bool
 
444
innodb_show_status(
 
445
/*===============*/
 
446
        handlerton*     hton,   /* in: the innodb handlerton */
 
447
        THD*    thd,    /* in: the MySQL query thread of the caller */
 
448
        stat_print_fn *stat_print);
 
449
static
 
450
bool innobase_show_status(handlerton *hton, THD* thd, 
 
451
                          stat_print_fn* stat_print,
 
452
                          enum ha_stat_type stat_type);
 
453
 
 
454
/*********************************************************************
 
455
Commits a transaction in an InnoDB database. */
 
456
static
 
457
void
 
458
innobase_commit_low(
 
459
/*================*/
 
460
        trx_t*  trx);   /* in: transaction handle */
 
461
 
 
462
static SHOW_VAR innodb_status_variables[]= {
 
463
  {"buffer_pool_pages_data",
 
464
  (char*) &export_vars.innodb_buffer_pool_pages_data,     SHOW_LONG},
 
465
  {"buffer_pool_pages_dirty",
 
466
  (char*) &export_vars.innodb_buffer_pool_pages_dirty,    SHOW_LONG},
 
467
  {"buffer_pool_pages_flushed",
 
468
  (char*) &export_vars.innodb_buffer_pool_pages_flushed,  SHOW_LONG},
 
469
  {"buffer_pool_pages_free",
 
470
  (char*) &export_vars.innodb_buffer_pool_pages_free,     SHOW_LONG},
 
471
  {"buffer_pool_pages_latched",
 
472
  (char*) &export_vars.innodb_buffer_pool_pages_latched,  SHOW_LONG},
 
473
  {"buffer_pool_pages_misc",
 
474
  (char*) &export_vars.innodb_buffer_pool_pages_misc,     SHOW_LONG},
 
475
  {"buffer_pool_pages_total",
 
476
  (char*) &export_vars.innodb_buffer_pool_pages_total,    SHOW_LONG},
 
477
  {"buffer_pool_read_ahead_rnd",
 
478
  (char*) &export_vars.innodb_buffer_pool_read_ahead_rnd, SHOW_LONG},
 
479
  {"buffer_pool_read_ahead_seq",
 
480
  (char*) &export_vars.innodb_buffer_pool_read_ahead_seq, SHOW_LONG},
 
481
  {"buffer_pool_read_requests",
 
482
  (char*) &export_vars.innodb_buffer_pool_read_requests,  SHOW_LONG},
 
483
  {"buffer_pool_reads",
 
484
  (char*) &export_vars.innodb_buffer_pool_reads,          SHOW_LONG},
 
485
  {"buffer_pool_wait_free",
 
486
  (char*) &export_vars.innodb_buffer_pool_wait_free,      SHOW_LONG},
 
487
  {"buffer_pool_write_requests",
 
488
  (char*) &export_vars.innodb_buffer_pool_write_requests, SHOW_LONG},
 
489
  {"data_fsyncs",
 
490
  (char*) &export_vars.innodb_data_fsyncs,                SHOW_LONG},
 
491
  {"data_pending_fsyncs",
 
492
  (char*) &export_vars.innodb_data_pending_fsyncs,        SHOW_LONG},
 
493
  {"data_pending_reads",
 
494
  (char*) &export_vars.innodb_data_pending_reads,         SHOW_LONG},
 
495
  {"data_pending_writes",
 
496
  (char*) &export_vars.innodb_data_pending_writes,        SHOW_LONG},
 
497
  {"data_read",
 
498
  (char*) &export_vars.innodb_data_read,                  SHOW_LONG},
 
499
  {"data_reads",
 
500
  (char*) &export_vars.innodb_data_reads,                 SHOW_LONG},
 
501
  {"data_writes",
 
502
  (char*) &export_vars.innodb_data_writes,                SHOW_LONG},
 
503
  {"data_written",
 
504
  (char*) &export_vars.innodb_data_written,               SHOW_LONG},
 
505
  {"dblwr_pages_written",
 
506
  (char*) &export_vars.innodb_dblwr_pages_written,        SHOW_LONG},
 
507
  {"dblwr_writes",
 
508
  (char*) &export_vars.innodb_dblwr_writes,               SHOW_LONG},
 
509
  {"log_waits",
 
510
  (char*) &export_vars.innodb_log_waits,                  SHOW_LONG},
 
511
  {"log_write_requests",
 
512
  (char*) &export_vars.innodb_log_write_requests,         SHOW_LONG},
 
513
  {"log_writes",
 
514
  (char*) &export_vars.innodb_log_writes,                 SHOW_LONG},
 
515
  {"os_log_fsyncs",
 
516
  (char*) &export_vars.innodb_os_log_fsyncs,              SHOW_LONG},
 
517
  {"os_log_pending_fsyncs",
 
518
  (char*) &export_vars.innodb_os_log_pending_fsyncs,      SHOW_LONG},
 
519
  {"os_log_pending_writes",
 
520
  (char*) &export_vars.innodb_os_log_pending_writes,      SHOW_LONG},
 
521
  {"os_log_written",
 
522
  (char*) &export_vars.innodb_os_log_written,             SHOW_LONG},
 
523
  {"page_size",
 
524
  (char*) &export_vars.innodb_page_size,                  SHOW_LONG},
 
525
  {"pages_created",
 
526
  (char*) &export_vars.innodb_pages_created,              SHOW_LONG},
 
527
  {"pages_read",
 
528
  (char*) &export_vars.innodb_pages_read,                 SHOW_LONG},
 
529
  {"pages_written",
 
530
  (char*) &export_vars.innodb_pages_written,              SHOW_LONG},
 
531
  {"row_lock_current_waits",
 
532
  (char*) &export_vars.innodb_row_lock_current_waits,     SHOW_LONG},
 
533
  {"row_lock_time",
 
534
  (char*) &export_vars.innodb_row_lock_time,              SHOW_LONGLONG},
 
535
  {"row_lock_time_avg",
 
536
  (char*) &export_vars.innodb_row_lock_time_avg,          SHOW_LONG},
 
537
  {"row_lock_time_max",
 
538
  (char*) &export_vars.innodb_row_lock_time_max,          SHOW_LONG},
 
539
  {"row_lock_waits",
 
540
  (char*) &export_vars.innodb_row_lock_waits,             SHOW_LONG},
 
541
  {"rows_deleted",
 
542
  (char*) &export_vars.innodb_rows_deleted,               SHOW_LONG},
 
543
  {"rows_inserted",
 
544
  (char*) &export_vars.innodb_rows_inserted,              SHOW_LONG},
 
545
  {"rows_read",
 
546
  (char*) &export_vars.innodb_rows_read,                  SHOW_LONG},
 
547
  {"rows_updated",
 
548
  (char*) &export_vars.innodb_rows_updated,               SHOW_LONG},
 
549
  {NullS, NullS, SHOW_LONG}
 
550
};
 
551
 
 
552
/* General functions */
 
553
 
 
554
/**********************************************************************
 
555
Returns true if the thread is the replication thread on the slave
 
556
server. Used in srv_conc_enter_innodb() to determine if the thread
 
557
should be allowed to enter InnoDB - the replication thread is treated
 
558
differently than other threads. Also used in
 
559
srv_conc_force_exit_innodb(). */
 
560
extern "C" UNIV_INTERN
 
561
ibool
 
562
thd_is_replication_slave_thread(
 
563
/*============================*/
 
564
                        /* out: true if thd is the replication thread */
 
565
        void*   thd)    /* in: thread handle (THD*) */
 
566
{
 
567
        return((ibool) thd_slave_thread((THD*) thd));
 
568
}
 
569
 
 
570
/**********************************************************************
 
571
Save some CPU by testing the value of srv_thread_concurrency in inline
 
572
functions. */
 
573
inline
 
574
void
 
575
innodb_srv_conc_enter_innodb(
 
576
/*=========================*/
 
577
        trx_t*  trx)    /* in: transaction handle */
 
578
{
 
579
        if (UNIV_LIKELY(!srv_thread_concurrency)) {
 
580
 
 
581
                return;
 
582
        }
 
583
 
 
584
        srv_conc_enter_innodb(trx);
 
585
}
 
586
 
 
587
/**********************************************************************
 
588
Save some CPU by testing the value of srv_thread_concurrency in inline
 
589
functions. */
 
590
inline
 
591
void
 
592
innodb_srv_conc_exit_innodb(
 
593
/*========================*/
 
594
        trx_t*  trx)    /* in: transaction handle */
 
595
{
 
596
        if (UNIV_LIKELY(!srv_thread_concurrency)) {
 
597
 
 
598
                return;
 
599
        }
 
600
 
 
601
        srv_conc_exit_innodb(trx);
 
602
}
 
603
 
 
604
/**********************************************************************
 
605
Releases possible search latch and InnoDB thread FIFO ticket. These should
 
606
be released at each SQL statement end, and also when mysqld passes the
 
607
control to the client. It does no harm to release these also in the middle
 
608
of an SQL statement. */
 
609
inline
 
610
void
 
611
innobase_release_stat_resources(
 
612
/*============================*/
 
613
        trx_t*  trx)    /* in: transaction object */
 
614
{
 
615
        if (trx->has_search_latch) {
 
616
                trx_search_latch_release_if_reserved(trx);
 
617
        }
 
618
 
 
619
        if (trx->declared_to_be_inside_innodb) {
 
620
                /* Release our possible ticket in the FIFO */
 
621
 
 
622
                srv_conc_force_exit_innodb(trx);
 
623
        }
 
624
}
 
625
 
 
626
/**********************************************************************
 
627
Returns true if the transaction this thread is processing has edited
 
628
non-transactional tables. Used by the deadlock detector when deciding
 
629
which transaction to rollback in case of a deadlock - we try to avoid
 
630
rolling back transactions that have edited non-transactional tables. */
 
631
extern "C" UNIV_INTERN
 
632
ibool
 
633
thd_has_edited_nontrans_tables(
 
634
/*===========================*/
 
635
                        /* out: true if non-transactional tables have
 
636
                        been edited */
 
637
        void*   thd)    /* in: thread handle (THD*) */
 
638
{
 
639
        return((ibool) thd_non_transactional_update((THD*) thd));
 
640
}
 
641
 
 
642
/************************************************************************
 
643
Obtain the InnoDB transaction of a MySQL thread. */
 
644
inline
 
645
trx_t*&
 
646
thd_to_trx(
 
647
/*=======*/
 
648
                        /* out: reference to transaction pointer */
 
649
        THD*    thd)    /* in: MySQL thread */
 
650
{
 
651
        return(*(trx_t**) thd_ha_data(thd, innodb_hton_ptr));
 
652
}
 
653
 
 
654
/************************************************************************
 
655
Call this function when mysqld passes control to the client. That is to
 
656
avoid deadlocks on the adaptive hash S-latch possibly held by thd. For more
 
657
documentation, see handler.cc. */
 
658
static
 
659
int
 
660
innobase_release_temporary_latches(
 
661
/*===============================*/
 
662
                                /* out: 0 */
 
663
        handlerton*     hton,   /* in: handlerton */
 
664
        THD*            thd)    /* in: MySQL thread */
 
665
{
 
666
        trx_t*  trx;
 
667
 
 
668
        DBUG_ASSERT(hton == innodb_hton_ptr);
 
669
 
 
670
        if (!innodb_inited) {
 
671
 
 
672
                return(0);
 
673
        }
 
674
 
 
675
        trx = thd_to_trx(thd);
 
676
 
 
677
        if (trx) {
 
678
                innobase_release_stat_resources(trx);
 
679
        }
 
680
        return(0);
 
681
}
 
682
 
 
683
/************************************************************************
 
684
Increments innobase_active_counter and every INNOBASE_WAKE_INTERVALth
 
685
time calls srv_active_wake_master_thread. This function should be used
 
686
when a single database operation may introduce a small need for
 
687
server utility activity, like checkpointing. */
 
688
inline
 
689
void
 
690
innobase_active_small(void)
 
691
/*=======================*/
 
692
{
 
693
        innobase_active_counter++;
 
694
 
 
695
        if ((innobase_active_counter % INNOBASE_WAKE_INTERVAL) == 0) {
 
696
                srv_active_wake_master_thread();
 
697
        }
 
698
}
 
699
 
 
700
/************************************************************************
 
701
Converts an InnoDB error code to a MySQL error code and also tells to MySQL
 
702
about a possible transaction rollback inside InnoDB caused by a lock wait
 
703
timeout or a deadlock. */
 
704
extern "C" UNIV_INTERN
 
705
int
 
706
convert_error_code_to_mysql(
 
707
/*========================*/
 
708
                        /* out: MySQL error code */
 
709
        int     error,  /* in: InnoDB error code */
 
710
        ulint   flags,  /* in: InnoDB table flags, or 0 */
 
711
        THD*    thd)    /* in: user thread handle or NULL */
 
712
{
 
713
        switch (error) {
 
714
        case DB_SUCCESS:
 
715
                return(0);
 
716
 
 
717
        case DB_ERROR:
 
718
        default:
 
719
                return(-1); /* unspecified error */
 
720
 
 
721
        case DB_DUPLICATE_KEY:
 
722
                return(HA_ERR_FOUND_DUPP_KEY);
 
723
 
 
724
        case DB_FOREIGN_DUPLICATE_KEY:
 
725
                return(HA_ERR_FOREIGN_DUPLICATE_KEY);
 
726
 
 
727
        case DB_RECORD_NOT_FOUND:
 
728
                return(HA_ERR_NO_ACTIVE_RECORD);
 
729
 
 
730
        case DB_DEADLOCK:
 
731
                /* Since we rolled back the whole transaction, we must
 
732
                tell it also to MySQL so that MySQL knows to empty the
 
733
                cached binlog for this transaction */
 
734
 
 
735
                if (thd) {
 
736
                        thd_mark_transaction_to_rollback(thd, TRUE);
 
737
                }
 
738
 
 
739
                return(HA_ERR_LOCK_DEADLOCK);
 
740
 
 
741
        case DB_LOCK_WAIT_TIMEOUT:
 
742
                /* Starting from 5.0.13, we let MySQL just roll back the
 
743
                latest SQL statement in a lock wait timeout. Previously, we
 
744
                rolled back the whole transaction. */
 
745
 
 
746
                if (thd) {
 
747
                        thd_mark_transaction_to_rollback(
 
748
                                thd, (bool)row_rollback_on_timeout);
 
749
                }
 
750
 
 
751
                return(HA_ERR_LOCK_WAIT_TIMEOUT);
 
752
 
 
753
        case DB_NO_REFERENCED_ROW:
 
754
                return(HA_ERR_NO_REFERENCED_ROW);
 
755
 
 
756
        case DB_ROW_IS_REFERENCED:
 
757
                return(HA_ERR_ROW_IS_REFERENCED);
 
758
 
 
759
        case DB_CANNOT_ADD_CONSTRAINT:
 
760
                return(HA_ERR_CANNOT_ADD_FOREIGN);
 
761
 
 
762
        case DB_CANNOT_DROP_CONSTRAINT:
 
763
 
 
764
                return(HA_ERR_ROW_IS_REFERENCED); /* TODO: This is a bit
 
765
                                                misleading, a new MySQL error
 
766
                                                code should be introduced */
 
767
 
 
768
        case DB_COL_APPEARS_TWICE_IN_INDEX:
 
769
        case DB_CORRUPTION:
 
770
                return(HA_ERR_CRASHED);
 
771
 
 
772
        case DB_OUT_OF_FILE_SPACE:
 
773
                return(HA_ERR_RECORD_FILE_FULL);
 
774
 
 
775
        case DB_TABLE_IS_BEING_USED:
 
776
                return(HA_ERR_WRONG_COMMAND);
 
777
 
 
778
        case DB_TABLE_NOT_FOUND:
 
779
                return(HA_ERR_NO_SUCH_TABLE);
 
780
 
 
781
        case DB_TOO_BIG_RECORD:
 
782
                my_error(ER_TOO_BIG_ROWSIZE, MYF(0),
 
783
                         page_get_free_space_of_empty(flags
 
784
                                                      & DICT_TF_COMPACT) / 2);
 
785
                return(HA_ERR_TO_BIG_ROW);
 
786
 
 
787
        case DB_NO_SAVEPOINT:
 
788
                return(HA_ERR_NO_SAVEPOINT);
 
789
 
 
790
        case DB_LOCK_TABLE_FULL:
 
791
                /* Since we rolled back the whole transaction, we must
 
792
                tell it also to MySQL so that MySQL knows to empty the
 
793
                cached binlog for this transaction */
 
794
 
 
795
                if (thd) {
 
796
                        thd_mark_transaction_to_rollback(thd, TRUE);
 
797
                }
 
798
 
 
799
                return(HA_ERR_LOCK_TABLE_FULL);
 
800
 
 
801
        case DB_PRIMARY_KEY_IS_NULL:
 
802
                return(ER_PRIMARY_CANT_HAVE_NULL);
 
803
 
 
804
        case DB_TOO_MANY_CONCURRENT_TRXS:
 
805
                /* Once MySQL add the appropriate code to errmsg.txt then
 
806
                we can get rid of this #ifdef. NOTE: The code checked by
 
807
                the #ifdef is the suggested name for the error condition
 
808
                and the actual error code name could very well be different.
 
809
                This will require some monitoring, ie. the status
 
810
                of this request on our part.*/
 
811
#ifdef ER_TOO_MANY_CONCURRENT_TRXS
 
812
                return(ER_TOO_MANY_CONCURRENT_TRXS);
 
813
#else
 
814
                return(HA_ERR_RECORD_FILE_FULL);
 
815
#endif
 
816
        case DB_UNSUPPORTED:
 
817
                return(HA_ERR_UNSUPPORTED);
 
818
        }
 
819
}
 
820
 
 
821
/*****************************************************************
 
822
If you want to print a thd that is not associated with the current thread,
 
823
you must call this function before reserving the InnoDB kernel_mutex, to
 
824
protect MySQL from setting thd->query NULL. If you print a thd of the current
 
825
thread, we know that MySQL cannot modify thd->query, and it is not necessary
 
826
to call this. Call innobase_mysql_end_print_arbitrary_thd() after you release
 
827
the kernel_mutex. */
 
828
extern "C" UNIV_INTERN
 
829
void
 
830
innobase_mysql_prepare_print_arbitrary_thd(void)
 
831
/*============================================*/
 
832
{
 
833
        ut_ad(!mutex_own(&kernel_mutex));
 
834
        VOID(pthread_mutex_lock(&LOCK_thread_count));
 
835
}
 
836
 
 
837
/*****************************************************************
 
838
Releases the mutex reserved by innobase_mysql_prepare_print_arbitrary_thd().
 
839
In the InnoDB latching order, the mutex sits right above the
 
840
kernel_mutex.  In debug builds, we assert that the kernel_mutex is
 
841
released before this function is invoked. */
 
842
extern "C" UNIV_INTERN
 
843
void
 
844
innobase_mysql_end_print_arbitrary_thd(void)
 
845
/*========================================*/
 
846
{
 
847
        ut_ad(!mutex_own(&kernel_mutex));
 
848
        VOID(pthread_mutex_unlock(&LOCK_thread_count));
 
849
}
 
850
 
 
851
/*****************************************************************
 
852
Prints info of a THD object (== user session thread) to the given file. */
 
853
extern "C" UNIV_INTERN
 
854
void
 
855
innobase_mysql_print_thd(
 
856
/*=====================*/
 
857
        FILE*   f,              /* in: output stream */
 
858
        void*   thd,            /* in: pointer to a MySQL THD object */
 
859
        uint    max_query_len)  /* in: max query length to print, or 0 to
 
860
                                   use the default max length */
 
861
{
 
862
        char    buffer[1024];
 
863
 
 
864
        fputs(thd_security_context((THD*) thd, buffer, sizeof buffer,
 
865
                                   max_query_len), f);
 
866
        putc('\n', f);
 
867
}
 
868
 
 
869
/**********************************************************************
 
870
Get the variable length bounds of the given character set. */
 
871
extern "C" UNIV_INTERN
 
872
void
 
873
innobase_get_cset_width(
 
874
/*====================*/
 
875
        ulint   cset,           /* in: MySQL charset-collation code */
 
876
        ulint*  mbminlen,       /* out: minimum length of a char (in bytes) */
 
877
        ulint*  mbmaxlen)       /* out: maximum length of a char (in bytes) */
 
878
{
 
879
        CHARSET_INFO*   cs;
 
880
        ut_ad(cset < 256);
 
881
        ut_ad(mbminlen);
 
882
        ut_ad(mbmaxlen);
 
883
 
 
884
        cs = all_charsets[cset];
 
885
        if (cs) {
 
886
                *mbminlen = cs->mbminlen;
 
887
                *mbmaxlen = cs->mbmaxlen;
 
888
        } else {
 
889
                ut_a(cset == 0);
 
890
                *mbminlen = *mbmaxlen = 0;
 
891
        }
 
892
}
 
893
 
 
894
/**********************************************************************
 
895
Converts an identifier to a table name.
 
896
 
 
897
NOTE that the exact prototype of this function has to be in
 
898
/innobase/dict/dict0dict.c! */
 
899
extern "C" UNIV_INTERN
 
900
void
 
901
innobase_convert_from_table_id(
 
902
/*===========================*/
 
903
        char*           to,     /* out: converted identifier */
 
904
        const char*     from,   /* in: identifier to convert */
 
905
        ulint           len)    /* in: length of 'to', in bytes */
 
906
{
 
907
        uint    errors;
 
908
 
 
909
        strconvert(thd_charset(current_thd), from,
 
910
                   &my_charset_filename, to, (uint) len, &errors);
 
911
}
 
912
 
 
913
/**********************************************************************
 
914
Converts an identifier to UTF-8.
 
915
 
 
916
NOTE that the exact prototype of this function has to be in
 
917
/innobase/dict/dict0dict.c! */
 
918
extern "C" UNIV_INTERN
 
919
void
 
920
innobase_convert_from_id(
 
921
/*=====================*/
 
922
        char*           to,     /* out: converted identifier */
 
923
        const char*     from,   /* in: identifier to convert */
 
924
        ulint           len)    /* in: length of 'to', in bytes */
 
925
{
 
926
        uint    errors;
 
927
 
 
928
        strconvert(thd_charset(current_thd), from,
 
929
                   system_charset_info, to, (uint) len, &errors);
 
930
}
 
931
 
 
932
/**********************************************************************
 
933
Compares NUL-terminated UTF-8 strings case insensitively. */
 
934
extern "C" UNIV_INTERN
 
935
int
 
936
innobase_strcasecmp(
 
937
/*================*/
 
938
                                /* out: 0 if a=b, <0 if a<b, >1 if a>b */
 
939
        const char*     a,      /* in: first string to compare */
 
940
        const char*     b)      /* in: second string to compare */
 
941
{
 
942
        return(my_strcasecmp(system_charset_info, a, b));
 
943
}
 
944
 
 
945
/**********************************************************************
 
946
Makes all characters in a NUL-terminated UTF-8 string lower case.
 
947
 
 
948
NOTE that the exact prototype of this function has to be in
 
949
/innobase/dict/dict0dict.c! */
 
950
extern "C" UNIV_INTERN
 
951
void
 
952
innobase_casedn_str(
 
953
/*================*/
 
954
        char*   a)      /* in/out: string to put in lower case */
 
955
{
 
956
        my_casedn_str(system_charset_info, a);
 
957
}
 
958
 
 
959
/**************************************************************************
 
960
Determines the connection character set.
 
961
 
 
962
NOTE that the exact prototype of this function has to be in
 
963
/innobase/dict/dict0dict.c! */
 
964
extern "C" UNIV_INTERN
 
965
struct charset_info_st*
 
966
innobase_get_charset(
 
967
/*=================*/
 
968
                                /* out: connection character set */
 
969
        void*   mysql_thd)      /* in: MySQL thread handle */
 
970
{
 
971
        return(thd_charset((THD*) mysql_thd));
 
972
}
 
973
 
 
974
/*************************************************************************
 
975
Creates a temporary file. */
 
976
extern "C" UNIV_INTERN
 
977
int
 
978
innobase_mysql_tmpfile(void)
 
979
/*========================*/
 
980
                        /* out: temporary file descriptor, or < 0 on error */
 
981
{
 
982
        int     fd2 = -1;
 
983
        File    fd = mysql_tmpfile("ib");
 
984
        if (fd >= 0) {
 
985
                /* Copy the file descriptor, so that the additional resources
 
986
                allocated by create_temp_file() can be freed by invoking
 
987
                my_close().
 
988
 
 
989
                Because the file descriptor returned by this function
 
990
                will be passed to fdopen(), it will be closed by invoking
 
991
                fclose(), which in turn will invoke close() instead of
 
992
                my_close(). */
 
993
                fd2 = dup(fd);
 
994
                if (fd2 < 0) {
 
995
                        DBUG_PRINT("error",("Got error %d on dup",fd2));
 
996
                        my_errno=errno;
 
997
                        my_error(EE_OUT_OF_FILERESOURCES,
 
998
                                 MYF(ME_BELL+ME_WAITTANG),
 
999
                                 "ib*", my_errno);
 
1000
                }
 
1001
                my_close(fd, MYF(MY_WME));
 
1002
        }
 
1003
        return(fd2);
 
1004
}
 
1005
 
 
1006
/*************************************************************************
 
1007
Wrapper around MySQL's copy_and_convert function, see it for
 
1008
documentation. */
 
1009
extern "C" UNIV_INTERN
 
1010
ulint
 
1011
innobase_convert_string(
 
1012
/*====================*/
 
1013
        void*           to,
 
1014
        ulint           to_length,
 
1015
        CHARSET_INFO*   to_cs,
 
1016
        const void*     from,
 
1017
        ulint           from_length,
 
1018
        CHARSET_INFO*   from_cs,
 
1019
        uint*           errors)
 
1020
{
 
1021
  return(copy_and_convert((char*)to, (uint32) to_length, to_cs,
 
1022
                          (const char*)from, (uint32) from_length, from_cs,
 
1023
                          errors));
 
1024
}
 
1025
 
 
1026
/***********************************************************************
 
1027
Formats the raw data in "data" (in InnoDB on-disk format) that is of
 
1028
type DATA_(CHAR|VARCHAR|MYSQL|VARMYSQL) using "charset_coll" and writes
 
1029
the result to "buf". The result is converted to "system_charset_info".
 
1030
Not more than "buf_size" bytes are written to "buf".
 
1031
The result is always '\0'-terminated (provided buf_size > 0) and the
 
1032
number of bytes that were written to "buf" is returned (including the
 
1033
terminating '\0'). */
 
1034
extern "C" UNIV_INTERN
 
1035
ulint
 
1036
innobase_raw_format(
 
1037
/*================*/
 
1038
                                        /* out: number of bytes
 
1039
                                        that were written */
 
1040
        const char*     data,           /* in: raw data */
 
1041
        ulint           data_len,       /* in: raw data length
 
1042
                                        in bytes */
 
1043
        ulint           charset_coll,   /* in: charset collation */
 
1044
        char*           buf,            /* out: output buffer */
 
1045
        ulint           buf_size)       /* in: output buffer size
 
1046
                                        in bytes */
 
1047
{
 
1048
        /* XXX we use a hard limit instead of allocating
 
1049
        but_size bytes from the heap */
 
1050
        CHARSET_INFO*   data_cs;
 
1051
        char            buf_tmp[8192];
 
1052
        ulint           buf_tmp_used;
 
1053
        uint            num_errors;
 
1054
 
 
1055
        data_cs = all_charsets[charset_coll];
 
1056
 
 
1057
        buf_tmp_used = innobase_convert_string(buf_tmp, sizeof(buf_tmp),
 
1058
                                               system_charset_info,
 
1059
                                               data, data_len, data_cs,
 
1060
                                               &num_errors);
 
1061
 
 
1062
        return(ut_str_sql_format(buf_tmp, buf_tmp_used, buf, buf_size));
 
1063
}
 
1064
 
 
1065
/*************************************************************************
 
1066
Gets the InnoDB transaction handle for a MySQL handler object, creates
 
1067
an InnoDB transaction struct if the corresponding MySQL thread struct still
 
1068
lacks one. */
 
1069
static
 
1070
trx_t*
 
1071
check_trx_exists(
 
1072
/*=============*/
 
1073
                        /* out: InnoDB transaction handle */
 
1074
        THD*    thd)    /* in: user thread handle */
 
1075
{
 
1076
        trx_t*& trx = thd_to_trx(thd);
 
1077
 
 
1078
        ut_ad(thd == current_thd);
 
1079
 
 
1080
        if (trx == NULL) {
 
1081
                DBUG_ASSERT(thd != NULL);
 
1082
                trx = trx_allocate_for_mysql();
 
1083
 
 
1084
                trx->mysql_thd = thd;
 
1085
                trx->mysql_query_str = thd_query(thd);
 
1086
 
 
1087
                /* Update the info whether we should skip XA steps that eat
 
1088
                CPU time */
 
1089
                trx->support_xa = THDVAR(thd, support_xa);
 
1090
        } else {
 
1091
                if (trx->magic_n != TRX_MAGIC_N) {
 
1092
                        mem_analyze_corruption(trx);
 
1093
 
 
1094
                        ut_error;
 
1095
                }
 
1096
        }
 
1097
 
 
1098
        if (thd_test_options(thd, OPTION_NO_FOREIGN_KEY_CHECKS)) {
 
1099
                trx->check_foreigns = FALSE;
 
1100
        } else {
 
1101
                trx->check_foreigns = TRUE;
 
1102
        }
 
1103
 
 
1104
        if (thd_test_options(thd, OPTION_RELAXED_UNIQUE_CHECKS)) {
 
1105
                trx->check_unique_secondary = FALSE;
 
1106
        } else {
 
1107
                trx->check_unique_secondary = TRUE;
 
1108
        }
 
1109
 
 
1110
        return(trx);
 
1111
}
 
1112
 
 
1113
 
 
1114
/*************************************************************************
 
1115
Construct ha_innobase handler. */
 
1116
UNIV_INTERN
 
1117
ha_innobase::ha_innobase(handlerton *hton, TABLE_SHARE *table_arg)
 
1118
  :handler(hton, table_arg),
 
1119
  int_table_flags(HA_REC_NOT_IN_SEQ |
 
1120
                  HA_NULL_IN_KEY |
 
1121
                  HA_CAN_INDEX_BLOBS |
 
1122
                  HA_CAN_SQL_HANDLER |
 
1123
                  HA_PRIMARY_KEY_REQUIRED_FOR_POSITION |
 
1124
                  HA_PRIMARY_KEY_IN_READ_INDEX |
 
1125
                  HA_BINLOG_ROW_CAPABLE |
 
1126
                  HA_CAN_GEOMETRY | HA_PARTIAL_COLUMN_READ |
 
1127
                  HA_TABLE_SCAN_ON_INDEX),
 
1128
  start_of_scan(0),
 
1129
  num_write_row(0)
 
1130
{}
 
1131
 
 
1132
/*************************************************************************
 
1133
Destruct ha_innobase handler. */
 
1134
UNIV_INTERN
 
1135
ha_innobase::~ha_innobase()
 
1136
{
 
1137
}
 
1138
 
 
1139
/*************************************************************************
 
1140
Updates the user_thd field in a handle and also allocates a new InnoDB
 
1141
transaction handle if needed, and updates the transaction fields in the
 
1142
prebuilt struct. */
 
1143
inline
 
1144
void
 
1145
ha_innobase::update_thd(
 
1146
/*====================*/
 
1147
        THD*    thd)    /* in: thd to use the handle */
 
1148
{
 
1149
        trx_t*          trx;
 
1150
 
 
1151
        trx = check_trx_exists(thd);
 
1152
 
 
1153
        if (prebuilt->trx != trx) {
 
1154
 
 
1155
                row_update_prebuilt_trx(prebuilt, trx);
 
1156
        }
 
1157
 
 
1158
        user_thd = thd;
 
1159
}
 
1160
 
 
1161
/*************************************************************************
 
1162
Updates the user_thd field in a handle and also allocates a new InnoDB
 
1163
transaction handle if needed, and updates the transaction fields in the
 
1164
prebuilt struct. */
 
1165
UNIV_INTERN
 
1166
void
 
1167
ha_innobase::update_thd()
 
1168
/*=====================*/
 
1169
{
 
1170
        THD*    thd = ha_thd();
 
1171
        ut_ad(thd == current_thd);
 
1172
        update_thd(thd);
 
1173
}
 
1174
 
 
1175
/*************************************************************************
 
1176
Registers that InnoDB takes part in an SQL statement, so that MySQL knows to
 
1177
roll back the statement if the statement results in an error. This MUST be
 
1178
called for every SQL statement that may be rolled back by MySQL. Calling this
 
1179
several times to register the same statement is allowed, too. */
 
1180
inline
 
1181
void
 
1182
innobase_register_stmt(
 
1183
/*===================*/
 
1184
        handlerton*     hton,   /* in: Innobase hton */
 
1185
        THD*    thd)    /* in: MySQL thd (connection) object */
 
1186
{
 
1187
        DBUG_ASSERT(hton == innodb_hton_ptr);
 
1188
        /* Register the statement */
 
1189
        trans_register_ha(thd, FALSE, hton);
 
1190
}
 
1191
 
 
1192
/*************************************************************************
 
1193
Registers an InnoDB transaction in MySQL, so that the MySQL XA code knows
 
1194
to call the InnoDB prepare and commit, or rollback for the transaction. This
 
1195
MUST be called for every transaction for which the user may call commit or
 
1196
rollback. Calling this several times to register the same transaction is
 
1197
allowed, too.
 
1198
This function also registers the current SQL statement. */
 
1199
inline
 
1200
void
 
1201
innobase_register_trx_and_stmt(
 
1202
/*===========================*/
 
1203
        handlerton *hton, /* in: Innobase handlerton */
 
1204
        THD*    thd)    /* in: MySQL thd (connection) object */
 
1205
{
 
1206
        /* NOTE that actually innobase_register_stmt() registers also
 
1207
        the transaction in the AUTOCOMMIT=1 mode. */
 
1208
 
 
1209
        innobase_register_stmt(hton, thd);
 
1210
 
 
1211
        if (thd_test_options(thd, OPTION_NOT_AUTOCOMMIT | OPTION_BEGIN)) {
 
1212
 
 
1213
                /* No autocommit mode, register for a transaction */
 
1214
                trans_register_ha(thd, TRUE, hton);
 
1215
        }
 
1216
}
 
1217
 
 
1218
/*   BACKGROUND INFO: HOW THE MYSQL QUERY CACHE WORKS WITH INNODB
 
1219
     ------------------------------------------------------------
 
1220
 
 
1221
1) The use of the query cache for TBL is disabled when there is an
 
1222
uncommitted change to TBL.
 
1223
 
 
1224
2) When a change to TBL commits, InnoDB stores the current value of
 
1225
its global trx id counter, let us denote it by INV_TRX_ID, to the table object
 
1226
in the InnoDB data dictionary, and does only allow such transactions whose
 
1227
id <= INV_TRX_ID to use the query cache.
 
1228
 
 
1229
3) When InnoDB does an INSERT/DELETE/UPDATE to a table TBL, or an implicit
 
1230
modification because an ON DELETE CASCADE, we invalidate the MySQL query cache
 
1231
of TBL immediately.
 
1232
 
 
1233
How this is implemented inside InnoDB:
 
1234
 
 
1235
1) Since every modification always sets an IX type table lock on the InnoDB
 
1236
table, it is easy to check if there can be uncommitted modifications for a
 
1237
table: just check if there are locks in the lock list of the table.
 
1238
 
 
1239
2) When a transaction inside InnoDB commits, it reads the global trx id
 
1240
counter and stores the value INV_TRX_ID to the tables on which it had a lock.
 
1241
 
 
1242
3) If there is an implicit table change from ON DELETE CASCADE or SET NULL,
 
1243
InnoDB calls an invalidate method for the MySQL query cache for that table.
 
1244
 
 
1245
How this is implemented inside sql_cache.cc:
 
1246
 
 
1247
1) The query cache for an InnoDB table TBL is invalidated immediately at an
 
1248
INSERT/UPDATE/DELETE, just like in the case of MyISAM. No need to delay
 
1249
invalidation to the transaction commit.
 
1250
 
 
1251
2) To store or retrieve a value from the query cache of an InnoDB table TBL,
 
1252
any query must first ask InnoDB's permission. We must pass the thd as a
 
1253
parameter because InnoDB will look at the trx id, if any, associated with
 
1254
that thd.
 
1255
 
 
1256
3) Use of the query cache for InnoDB tables is now allowed also when
 
1257
AUTOCOMMIT==0 or we are inside BEGIN ... COMMIT. Thus transactions no longer
 
1258
put restrictions on the use of the query cache.
 
1259
*/
 
1260
 
 
1261
/**********************************************************************
 
1262
The MySQL query cache uses this to check from InnoDB if the query cache at
 
1263
the moment is allowed to operate on an InnoDB table. The SQL query must
 
1264
be a non-locking SELECT.
 
1265
 
 
1266
The query cache is allowed to operate on certain query only if this function
 
1267
returns TRUE for all tables in the query.
 
1268
 
 
1269
If thd is not in the autocommit state, this function also starts a new
 
1270
transaction for thd if there is no active trx yet, and assigns a consistent
 
1271
read view to it if there is no read view yet.
 
1272
 
 
1273
Why a deadlock of threads is not possible: the query cache calls this function
 
1274
at the start of a SELECT processing. Then the calling thread cannot be
 
1275
holding any InnoDB semaphores. The calling thread is holding the
 
1276
query cache mutex, and this function will reserver the InnoDB kernel mutex.
 
1277
Thus, the 'rank' in sync0sync.h of the MySQL query cache mutex is above
 
1278
the InnoDB kernel mutex. */
 
1279
static
 
1280
my_bool
 
1281
innobase_query_caching_of_table_permitted(
 
1282
/*======================================*/
 
1283
                                /* out: TRUE if permitted, FALSE if not;
 
1284
                                note that the value FALSE does not mean
 
1285
                                we should invalidate the query cache:
 
1286
                                invalidation is called explicitly */
 
1287
        THD*    thd,            /* in: thd of the user who is trying to
 
1288
                                store a result to the query cache or
 
1289
                                retrieve it */
 
1290
        char*   full_name,      /* in: concatenation of database name,
 
1291
                                the null character '\0', and the table
 
1292
                                name */
 
1293
        uint    full_name_len,  /* in: length of the full name, i.e.
 
1294
                                len(dbname) + len(tablename) + 1 */
 
1295
        ulonglong *unused)      /* unused for this engine */
 
1296
{
 
1297
        ibool   is_autocommit;
 
1298
        trx_t*  trx;
 
1299
        char    norm_name[1000];
 
1300
 
 
1301
        ut_a(full_name_len < 999);
 
1302
 
 
1303
        trx = check_trx_exists(thd);
 
1304
 
 
1305
        if (trx->isolation_level == TRX_ISO_SERIALIZABLE) {
 
1306
                /* In the SERIALIZABLE mode we add LOCK IN SHARE MODE to every
 
1307
                plain SELECT if AUTOCOMMIT is not on. */
 
1308
 
 
1309
                return((my_bool)FALSE);
 
1310
        }
 
1311
 
 
1312
        if (trx->has_search_latch) {
 
1313
                sql_print_error("The calling thread is holding the adaptive "
 
1314
                                "search, latch though calling "
 
1315
                                "innobase_query_caching_of_table_permitted.");
 
1316
 
 
1317
                mutex_enter(&kernel_mutex);
 
1318
                trx_print(stderr, trx, 1024);
 
1319
                mutex_exit(&kernel_mutex);
 
1320
        }
 
1321
 
 
1322
        innobase_release_stat_resources(trx);
 
1323
 
 
1324
        if (!thd_test_options(thd, OPTION_NOT_AUTOCOMMIT | OPTION_BEGIN)) {
 
1325
 
 
1326
                is_autocommit = TRUE;
 
1327
        } else {
 
1328
                is_autocommit = FALSE;
 
1329
 
 
1330
        }
 
1331
 
 
1332
        if (is_autocommit && trx->n_mysql_tables_in_use == 0) {
 
1333
                /* We are going to retrieve the query result from the query
 
1334
                cache. This cannot be a store operation to the query cache
 
1335
                because then MySQL would have locks on tables already.
 
1336
 
 
1337
                TODO: if the user has used LOCK TABLES to lock the table,
 
1338
                then we open a transaction in the call of row_.. below.
 
1339
                That trx can stay open until UNLOCK TABLES. The same problem
 
1340
                exists even if we do not use the query cache. MySQL should be
 
1341
                modified so that it ALWAYS calls some cleanup function when
 
1342
                the processing of a query ends!
 
1343
 
 
1344
                We can imagine we instantaneously serialize this consistent
 
1345
                read trx to the current trx id counter. If trx2 would have
 
1346
                changed the tables of a query result stored in the cache, and
 
1347
                trx2 would have already committed, making the result obsolete,
 
1348
                then trx2 would have already invalidated the cache. Thus we
 
1349
                can trust the result in the cache is ok for this query. */
 
1350
 
 
1351
                return((my_bool)TRUE);
 
1352
        }
 
1353
 
 
1354
        /* Normalize the table name to InnoDB format */
 
1355
 
 
1356
        memcpy(norm_name, full_name, full_name_len);
 
1357
 
 
1358
        norm_name[strlen(norm_name)] = '/'; /* InnoDB uses '/' as the
 
1359
                                            separator between db and table */
 
1360
        norm_name[full_name_len] = '\0';
 
1361
#ifdef __WIN__
 
1362
        innobase_casedn_str(norm_name);
 
1363
#endif
 
1364
        /* The call of row_search_.. will start a new transaction if it is
 
1365
        not yet started */
 
1366
 
 
1367
        if (trx->active_trans == 0) {
 
1368
 
 
1369
                innobase_register_trx_and_stmt(innodb_hton_ptr, thd);
 
1370
                trx->active_trans = 1;
 
1371
        }
 
1372
 
 
1373
        if (row_search_check_if_query_cache_permitted(trx, norm_name)) {
 
1374
 
 
1375
                /* printf("Query cache for %s permitted\n", norm_name); */
 
1376
 
 
1377
                return((my_bool)TRUE);
 
1378
        }
 
1379
 
 
1380
        /* printf("Query cache for %s NOT permitted\n", norm_name); */
 
1381
 
 
1382
        return((my_bool)FALSE);
 
1383
}
 
1384
 
 
1385
/*********************************************************************
 
1386
Invalidates the MySQL query cache for the table.
 
1387
NOTE that the exact prototype of this function has to be in
 
1388
/innobase/row/row0ins.c! */
 
1389
extern "C" UNIV_INTERN
 
1390
void
 
1391
innobase_invalidate_query_cache(
 
1392
/*============================*/
 
1393
        trx_t*  trx,            /* in: transaction which modifies the table */
 
1394
        char*   full_name,      /* in: concatenation of database name, null
 
1395
                                char '\0', table name, null char'\0';
 
1396
                                NOTE that in Windows this is always
 
1397
                                in LOWER CASE! */
 
1398
        ulint   full_name_len)  /* in: full name length where also the null
 
1399
                                chars count */
 
1400
{
 
1401
        /* Note that the sync0sync.h rank of the query cache mutex is just
 
1402
        above the InnoDB kernel mutex. The caller of this function must not
 
1403
        have latches of a lower rank. */
 
1404
 
 
1405
        /* Argument TRUE below means we are using transactions */
 
1406
#ifdef HAVE_QUERY_CACHE
 
1407
        mysql_query_cache_invalidate4((THD*) trx->mysql_thd,
 
1408
                                      (const char*) full_name,
 
1409
                                      (uint32) full_name_len,
 
1410
                                      TRUE);
 
1411
#endif
 
1412
}
 
1413
 
 
1414
/*********************************************************************
 
1415
Convert an SQL identifier to the MySQL system_charset_info (UTF-8)
 
1416
and quote it if needed. */
 
1417
static
 
1418
char*
 
1419
innobase_convert_identifier(
 
1420
/*========================*/
 
1421
                                /* out: pointer to the end of buf */
 
1422
        char*           buf,    /* out: buffer for converted identifier */
 
1423
        ulint           buflen, /* in: length of buf, in bytes */
 
1424
        const char*     id,     /* in: identifier to convert */
 
1425
        ulint           idlen,  /* in: length of id, in bytes */
 
1426
        void*           thd,    /* in: MySQL connection thread, or NULL */
 
1427
        ibool           file_id)/* in: TRUE=id is a table or database name;
 
1428
                                FALSE=id is an UTF-8 string */
 
1429
{
 
1430
        char nz[NAME_LEN + 1];
 
1431
        char nz2[NAME_LEN + 1 + sizeof srv_mysql50_table_name_prefix];
 
1432
 
 
1433
        const char*     s       = id;
 
1434
        int             q;
 
1435
 
 
1436
        if (file_id) {
 
1437
                /* Decode the table name.  The filename_to_tablename()
 
1438
                function expects a NUL-terminated string.  The input and
 
1439
                output strings buffers must not be shared. */
 
1440
 
 
1441
                if (UNIV_UNLIKELY(idlen > (sizeof nz) - 1)) {
 
1442
                        idlen = (sizeof nz) - 1;
 
1443
                }
 
1444
 
 
1445
                memcpy(nz, id, idlen);
 
1446
                nz[idlen] = 0;
 
1447
 
 
1448
                s = nz2;
 
1449
                idlen = filename_to_tablename(nz, nz2, sizeof nz2);
 
1450
        }
 
1451
 
 
1452
        /* See if the identifier needs to be quoted. */
 
1453
        if (UNIV_UNLIKELY(!thd)) {
 
1454
                q = '"';
 
1455
        } else {
 
1456
                q = get_quote_char_for_identifier((THD*) thd, s, (int) idlen);
 
1457
        }
 
1458
 
 
1459
        if (q == EOF) {
 
1460
                if (UNIV_UNLIKELY(idlen > buflen)) {
 
1461
                        idlen = buflen;
 
1462
                }
 
1463
                memcpy(buf, s, idlen);
 
1464
                return(buf + idlen);
 
1465
        }
 
1466
 
 
1467
        /* Quote the identifier. */
 
1468
        if (buflen < 2) {
 
1469
                return(buf);
 
1470
        }
 
1471
 
 
1472
        *buf++ = q;
 
1473
        buflen--;
 
1474
 
 
1475
        for (; idlen; idlen--) {
 
1476
                int     c = *s++;
 
1477
                if (UNIV_UNLIKELY(c == q)) {
 
1478
                        if (UNIV_UNLIKELY(buflen < 3)) {
 
1479
                                break;
 
1480
                        }
 
1481
 
 
1482
                        *buf++ = c;
 
1483
                        *buf++ = c;
 
1484
                        buflen -= 2;
 
1485
                } else {
 
1486
                        if (UNIV_UNLIKELY(buflen < 2)) {
 
1487
                                break;
 
1488
                        }
 
1489
 
 
1490
                        *buf++ = c;
 
1491
                        buflen--;
 
1492
                }
 
1493
        }
 
1494
 
 
1495
        *buf++ = q;
 
1496
        return(buf);
 
1497
}
 
1498
 
 
1499
/*********************************************************************
 
1500
Convert a table or index name to the MySQL system_charset_info (UTF-8)
 
1501
and quote it if needed. */
 
1502
extern "C" UNIV_INTERN
 
1503
char*
 
1504
innobase_convert_name(
 
1505
/*==================*/
 
1506
                                /* out: pointer to the end of buf */
 
1507
        char*           buf,    /* out: buffer for converted identifier */
 
1508
        ulint           buflen, /* in: length of buf, in bytes */
 
1509
        const char*     id,     /* in: identifier to convert */
 
1510
        ulint           idlen,  /* in: length of id, in bytes */
 
1511
        void*           thd,    /* in: MySQL connection thread, or NULL */
 
1512
        ibool           table_id)/* in: TRUE=id is a table or database name;
 
1513
                                FALSE=id is an index name */
 
1514
{
 
1515
        char*           s       = buf;
 
1516
        const char*     bufend  = buf + buflen;
 
1517
 
 
1518
        if (table_id) {
 
1519
                const char*     slash = (const char*) memchr(id, '/', idlen);
 
1520
                if (!slash) {
 
1521
 
 
1522
                        goto no_db_name;
 
1523
                }
 
1524
 
 
1525
                /* Print the database name and table name separately. */
 
1526
                s = innobase_convert_identifier(s, bufend - s, id, slash - id,
 
1527
                                                thd, TRUE);
 
1528
                if (UNIV_LIKELY(s < bufend)) {
 
1529
                        *s++ = '.';
 
1530
                        s = innobase_convert_identifier(s, bufend - s,
 
1531
                                                        slash + 1, idlen
 
1532
                                                        - (slash - id) - 1,
 
1533
                                                        thd, TRUE);
 
1534
                }
 
1535
        } else if (UNIV_UNLIKELY(*id == TEMP_INDEX_PREFIX)) {
 
1536
                /* Temporary index name (smart ALTER TABLE) */
 
1537
                const char temp_index_suffix[]= "--temporary--";
 
1538
 
 
1539
                s = innobase_convert_identifier(buf, buflen, id + 1, idlen - 1,
 
1540
                                                thd, FALSE);
 
1541
                if (s - buf + (sizeof temp_index_suffix - 1) < buflen) {
 
1542
                        memcpy(s, temp_index_suffix,
 
1543
                               sizeof temp_index_suffix - 1);
 
1544
                        s += sizeof temp_index_suffix - 1;
 
1545
                }
 
1546
        } else {
 
1547
no_db_name:
 
1548
                s = innobase_convert_identifier(buf, buflen, id, idlen,
 
1549
                                                thd, table_id);
 
1550
        }
 
1551
 
 
1552
        return(s);
 
1553
 
 
1554
}
 
1555
 
 
1556
/**************************************************************************
 
1557
Determines if the currently running transaction has been interrupted. */
 
1558
extern "C" UNIV_INTERN
 
1559
ibool
 
1560
trx_is_interrupted(
 
1561
/*===============*/
 
1562
                        /* out: TRUE if interrupted */
 
1563
        trx_t*  trx)    /* in: transaction */
 
1564
{
 
1565
        return(trx && trx->mysql_thd && thd_killed((THD*) trx->mysql_thd));
 
1566
}
 
1567
 
 
1568
/******************************************************************
 
1569
Resets some fields of a prebuilt struct. The template is used in fast
 
1570
retrieval of just those column values MySQL needs in its processing. */
 
1571
static
 
1572
void
 
1573
reset_template(
 
1574
/*===========*/
 
1575
        row_prebuilt_t* prebuilt)       /* in/out: prebuilt struct */
 
1576
{
 
1577
        prebuilt->keep_other_fields_on_keyread = 0;
 
1578
        prebuilt->read_just_key = 0;
 
1579
}
 
1580
 
 
1581
/*********************************************************************
 
1582
Call this when you have opened a new table handle in HANDLER, before you
 
1583
call index_read_idx() etc. Actually, we can let the cursor stay open even
 
1584
over a transaction commit! Then you should call this before every operation,
 
1585
fetch next etc. This function inits the necessary things even after a
 
1586
transaction commit. */
 
1587
UNIV_INTERN
 
1588
void
 
1589
ha_innobase::init_table_handle_for_HANDLER(void)
 
1590
/*============================================*/
 
1591
{
 
1592
        /* If current thd does not yet have a trx struct, create one.
 
1593
        If the current handle does not yet have a prebuilt struct, create
 
1594
        one. Update the trx pointers in the prebuilt struct. Normally
 
1595
        this operation is done in external_lock. */
 
1596
 
 
1597
        update_thd(ha_thd());
 
1598
 
 
1599
        /* Initialize the prebuilt struct much like it would be inited in
 
1600
        external_lock */
 
1601
 
 
1602
        innobase_release_stat_resources(prebuilt->trx);
 
1603
 
 
1604
        /* If the transaction is not started yet, start it */
 
1605
 
 
1606
        trx_start_if_not_started(prebuilt->trx);
 
1607
 
 
1608
        /* Assign a read view if the transaction does not have it yet */
 
1609
 
 
1610
        trx_assign_read_view(prebuilt->trx);
 
1611
 
 
1612
        /* Set the MySQL flag to mark that there is an active transaction */
 
1613
 
 
1614
        if (prebuilt->trx->active_trans == 0) {
 
1615
 
 
1616
                innobase_register_trx_and_stmt(ht, user_thd);
 
1617
 
 
1618
                prebuilt->trx->active_trans = 1;
 
1619
        }
 
1620
 
 
1621
        /* We did the necessary inits in this function, no need to repeat them
 
1622
        in row_search_for_mysql */
 
1623
 
 
1624
        prebuilt->sql_stat_start = FALSE;
 
1625
 
 
1626
        /* We let HANDLER always to do the reads as consistent reads, even
 
1627
        if the trx isolation level would have been specified as SERIALIZABLE */
 
1628
 
 
1629
        prebuilt->select_lock_type = LOCK_NONE;
 
1630
        prebuilt->stored_select_lock_type = LOCK_NONE;
 
1631
 
 
1632
        /* Always fetch all columns in the index record */
 
1633
 
 
1634
        prebuilt->hint_need_to_fetch_extra_cols = ROW_RETRIEVE_ALL_COLS;
 
1635
 
 
1636
        /* We want always to fetch all columns in the whole row? Or do
 
1637
        we???? */
 
1638
 
 
1639
        prebuilt->used_in_HANDLER = TRUE;
 
1640
        reset_template(prebuilt);
 
1641
}
 
1642
 
 
1643
/*************************************************************************
 
1644
Opens an InnoDB database. */
 
1645
static
 
1646
int
 
1647
innobase_init(
 
1648
/*==========*/
 
1649
                        /* out: 0 on success, error code on failure */
 
1650
        void    *p)     /* in: InnoDB handlerton */
 
1651
{
 
1652
        static char     current_dir[3];         /* Set if using current lib */
 
1653
        int             err;
 
1654
        bool            ret;
 
1655
        char            *default_path;
 
1656
        uint            format_id;
 
1657
 
 
1658
        DBUG_ENTER("innobase_init");
 
1659
        handlerton *innobase_hton= (handlerton *)p;
 
1660
 
 
1661
#ifdef MYSQL_DYNAMIC_PLUGIN
 
1662
        if (!innodb_plugin_init()) {
 
1663
                sql_print_error("InnoDB plugin init failed.");
 
1664
                DBUG_RETURN(-1);
 
1665
        }
 
1666
 
 
1667
        if (innodb_hton_ptr) {
 
1668
                /* Patch the statically linked handlerton and variables */
 
1669
                innobase_hton = innodb_hton_ptr;
 
1670
        }
 
1671
#endif /* MYSQL_DYNAMIC_PLUGIN */
 
1672
 
 
1673
        innodb_hton_ptr = innobase_hton;
 
1674
 
 
1675
        innobase_hton->state = SHOW_OPTION_YES;
 
1676
        innobase_hton->db_type= DB_TYPE_INNODB;
 
1677
        innobase_hton->savepoint_offset=sizeof(trx_named_savept_t);
 
1678
        innobase_hton->close_connection=innobase_close_connection;
 
1679
        innobase_hton->savepoint_set=innobase_savepoint;
 
1680
        innobase_hton->savepoint_rollback=innobase_rollback_to_savepoint;
 
1681
        innobase_hton->savepoint_release=innobase_release_savepoint;
 
1682
        innobase_hton->commit=innobase_commit;
 
1683
        innobase_hton->rollback=innobase_rollback;
 
1684
        innobase_hton->prepare=innobase_xa_prepare;
 
1685
        innobase_hton->recover=innobase_xa_recover;
 
1686
        innobase_hton->commit_by_xid=innobase_commit_by_xid;
 
1687
        innobase_hton->rollback_by_xid=innobase_rollback_by_xid;
 
1688
        innobase_hton->create_cursor_read_view=innobase_create_cursor_view;
 
1689
        innobase_hton->set_cursor_read_view=innobase_set_cursor_view;
 
1690
        innobase_hton->close_cursor_read_view=innobase_close_cursor_view;
 
1691
        innobase_hton->create=innobase_create_handler;
 
1692
        innobase_hton->drop_database=innobase_drop_database;
 
1693
        innobase_hton->panic=innobase_end;
 
1694
        innobase_hton->start_consistent_snapshot=innobase_start_trx_and_assign_read_view;
 
1695
        innobase_hton->flush_logs=innobase_flush_logs;
 
1696
        innobase_hton->show_status=innobase_show_status;
 
1697
        innobase_hton->flags=HTON_NO_FLAGS;
 
1698
        innobase_hton->release_temporary_latches=innobase_release_temporary_latches;
 
1699
        innobase_hton->alter_table_flags = innobase_alter_table_flags;
 
1700
 
 
1701
        ut_a(DATA_MYSQL_TRUE_VARCHAR == (ulint)MYSQL_TYPE_VARCHAR);
 
1702
 
 
1703
#ifdef UNIV_DEBUG
 
1704
        static const char       test_filename[] = "-@";
 
1705
        char                    test_tablename[sizeof test_filename
 
1706
                                + sizeof srv_mysql50_table_name_prefix];
 
1707
        if ((sizeof test_tablename) - 1
 
1708
                        != filename_to_tablename(test_filename, test_tablename,
 
1709
                        sizeof test_tablename)
 
1710
                        || strncmp(test_tablename,
 
1711
                        srv_mysql50_table_name_prefix,
 
1712
                        sizeof srv_mysql50_table_name_prefix)
 
1713
                        || strcmp(test_tablename
 
1714
                        + sizeof srv_mysql50_table_name_prefix,
 
1715
                        test_filename)) {
 
1716
                sql_print_error("tablename encoding has been changed");
 
1717
                goto error;
 
1718
        }
 
1719
#endif /* UNIV_DEBUG */
 
1720
 
 
1721
        /* Check that values don't overflow on 32-bit systems. */
 
1722
        if (sizeof(ulint) == 4) {
 
1723
                if (innobase_buffer_pool_size > UINT_MAX32) {
 
1724
                        sql_print_error(
 
1725
                                "innobase_buffer_pool_size can't be over 4GB"
 
1726
                                " on 32-bit systems");
 
1727
 
 
1728
                        goto error;
 
1729
                }
 
1730
 
 
1731
                if (innobase_log_file_size > UINT_MAX32) {
 
1732
                        sql_print_error(
 
1733
                                "innobase_log_file_size can't be over 4GB"
 
1734
                                " on 32-bit systems");
 
1735
 
 
1736
                        goto error;
 
1737
                }
 
1738
        }
 
1739
 
 
1740
        os_innodb_umask = (ulint)my_umask;
 
1741
 
 
1742
        /* First calculate the default path for innodb_data_home_dir etc.,
 
1743
        in case the user has not given any value.
 
1744
 
 
1745
        Note that when using the embedded server, the datadirectory is not
 
1746
        necessarily the current directory of this program. */
 
1747
 
 
1748
        if (mysqld_embedded) {
 
1749
                default_path = mysql_real_data_home;
 
1750
                fil_path_to_mysql_datadir = mysql_real_data_home;
 
1751
        } else {
 
1752
                /* It's better to use current lib, to keep paths short */
 
1753
                current_dir[0] = FN_CURLIB;
 
1754
                current_dir[1] = FN_LIBCHAR;
 
1755
                current_dir[2] = 0;
 
1756
                default_path = current_dir;
 
1757
        }
 
1758
 
 
1759
        ut_a(default_path);
 
1760
 
 
1761
        if (specialflag & SPECIAL_NO_PRIOR) {
 
1762
                srv_set_thread_priorities = FALSE;
 
1763
        } else {
 
1764
                srv_set_thread_priorities = TRUE;
 
1765
                srv_query_thread_priority = QUERY_PRIOR;
 
1766
        }
 
1767
 
 
1768
        /* Set InnoDB initialization parameters according to the values
 
1769
        read from MySQL .cnf file */
 
1770
 
 
1771
        /*--------------- Data files -------------------------*/
 
1772
 
 
1773
        /* The default dir for data files is the datadir of MySQL */
 
1774
 
 
1775
        srv_data_home = (innobase_data_home_dir ? innobase_data_home_dir :
 
1776
                         default_path);
 
1777
 
 
1778
        /* Set default InnoDB data file size to 10 MB and let it be
 
1779
        auto-extending. Thus users can use InnoDB in >= 4.0 without having
 
1780
        to specify any startup options. */
 
1781
 
 
1782
        if (!innobase_data_file_path) {
 
1783
                innobase_data_file_path = (char*) "ibdata1:10M:autoextend";
 
1784
        }
 
1785
 
 
1786
        /* Since InnoDB edits the argument in the next call, we make another
 
1787
        copy of it: */
 
1788
 
 
1789
        internal_innobase_data_file_path = my_strdup(innobase_data_file_path,
 
1790
                                                   MYF(MY_FAE));
 
1791
 
 
1792
        ret = (bool) srv_parse_data_file_paths_and_sizes(
 
1793
                                internal_innobase_data_file_path,
 
1794
                                &srv_data_file_names,
 
1795
                                &srv_data_file_sizes,
 
1796
                                &srv_data_file_is_raw_partition,
 
1797
                                &srv_n_data_files,
 
1798
                                &srv_auto_extend_last_data_file,
 
1799
                                &srv_last_file_size_max);
 
1800
        if (ret == FALSE) {
 
1801
                sql_print_error(
 
1802
                        "InnoDB: syntax error in innodb_data_file_path");
 
1803
                my_free(internal_innobase_data_file_path,
 
1804
                                                MYF(MY_ALLOW_ZERO_PTR));
 
1805
                goto error;
 
1806
        }
 
1807
 
 
1808
        /* -------------- Log files ---------------------------*/
 
1809
 
 
1810
        /* The default dir for log files is the datadir of MySQL */
 
1811
 
 
1812
        if (!innobase_log_group_home_dir) {
 
1813
                innobase_log_group_home_dir = default_path;
 
1814
        }
 
1815
 
 
1816
#ifdef UNIV_LOG_ARCHIVE
 
1817
        /* Since innodb_log_arch_dir has no relevance under MySQL,
 
1818
        starting from 4.0.6 we always set it the same as
 
1819
        innodb_log_group_home_dir: */
 
1820
 
 
1821
        innobase_log_arch_dir = innobase_log_group_home_dir;
 
1822
 
 
1823
        srv_arch_dir = innobase_log_arch_dir;
 
1824
#endif /* UNIG_LOG_ARCHIVE */
 
1825
 
 
1826
        ret = (bool)
 
1827
                srv_parse_log_group_home_dirs(innobase_log_group_home_dir,
 
1828
                                                &srv_log_group_home_dirs);
 
1829
 
 
1830
        if (ret == FALSE || innobase_mirrored_log_groups != 1) {
 
1831
          sql_print_error("syntax error in innodb_log_group_home_dir, or a "
 
1832
                          "wrong number of mirrored log groups");
 
1833
 
 
1834
                my_free(internal_innobase_data_file_path,
 
1835
                                                MYF(MY_ALLOW_ZERO_PTR));
 
1836
                goto error;
 
1837
        }
 
1838
 
 
1839
        /* Validate the file format by animal name */
 
1840
        if (innobase_file_format_name != NULL) {
 
1841
 
 
1842
                format_id = innobase_file_format_name_lookup(
 
1843
                        innobase_file_format_name);
 
1844
 
 
1845
                if (format_id > DICT_TF_FORMAT_MAX) {
 
1846
 
 
1847
                        sql_print_error("InnoDB: wrong innodb_file_format.");
 
1848
 
 
1849
                        my_free(internal_innobase_data_file_path,
 
1850
                                MYF(MY_ALLOW_ZERO_PTR));
 
1851
                        goto error;
 
1852
                }
 
1853
        } else {
 
1854
                /* Set it to the default file format id. Though this
 
1855
                should never happen. */
 
1856
                format_id = 0;
 
1857
        }
 
1858
 
 
1859
        srv_file_format = format_id;
 
1860
 
 
1861
        /* Given the type of innobase_file_format_name we have little
 
1862
        choice but to cast away the constness from the returned name.
 
1863
        innobase_file_format_name is used in the MySQL set variable
 
1864
        interface and so can't be const. */
 
1865
 
 
1866
        innobase_file_format_name = 
 
1867
                (char*) trx_sys_file_format_id_to_name(format_id);
 
1868
 
 
1869
        /* Process innobase_file_format_check variable */
 
1870
        ut_a(innobase_file_format_check != NULL);
 
1871
 
 
1872
        /* As a side affect it will set srv_check_file_format_at_startup
 
1873
        on valid input. First we check for "on"/"off". */
 
1874
        if (!innobase_file_format_check_on_off(innobase_file_format_check)) {
 
1875
 
 
1876
                /* Did the user specify a format name that we support ?
 
1877
                As a side affect it will update the variable
 
1878
                srv_check_file_format_at_startup*/
 
1879
                if (!innobase_file_format_check_validate(
 
1880
                        innobase_file_format_check)) {
 
1881
 
 
1882
                        sql_print_error("InnoDB: invalid "
 
1883
                                        "innodb_file_format_check value: "
 
1884
                                        "should be either 'on' or 'off' or "
 
1885
                                        "any value up to %s or its "
 
1886
                                        "equivalent numeric id",
 
1887
                                        trx_sys_file_format_id_to_name(
 
1888
                                                DICT_TF_FORMAT_MAX));
 
1889
 
 
1890
                        my_free(internal_innobase_data_file_path,
 
1891
                                MYF(MY_ALLOW_ZERO_PTR));
 
1892
 
 
1893
                        goto error;
 
1894
                }
 
1895
        }
 
1896
 
 
1897
        /* --------------------------------------------------*/
 
1898
 
 
1899
        srv_file_flush_method_str = innobase_unix_file_flush_method;
 
1900
 
 
1901
        srv_n_log_groups = (ulint) innobase_mirrored_log_groups;
 
1902
        srv_n_log_files = (ulint) innobase_log_files_in_group;
 
1903
        srv_log_file_size = (ulint) innobase_log_file_size;
 
1904
 
 
1905
#ifdef UNIV_LOG_ARCHIVE
 
1906
        srv_log_archive_on = (ulint) innobase_log_archive;
 
1907
#endif /* UNIV_LOG_ARCHIVE */
 
1908
        srv_log_buffer_size = (ulint) innobase_log_buffer_size;
 
1909
 
 
1910
        srv_buf_pool_size = (ulint) innobase_buffer_pool_size;
 
1911
 
 
1912
        srv_mem_pool_size = (ulint) innobase_additional_mem_pool_size;
 
1913
 
 
1914
        srv_n_file_io_threads = (ulint) innobase_file_io_threads;
 
1915
 
 
1916
        srv_lock_wait_timeout = (ulint) innobase_lock_wait_timeout;
 
1917
        srv_force_recovery = (ulint) innobase_force_recovery;
 
1918
 
 
1919
        srv_use_doublewrite_buf = (ibool) innobase_use_doublewrite;
 
1920
        srv_use_checksums = (ibool) innobase_use_checksums;
 
1921
 
 
1922
#ifdef HAVE_LARGE_PAGES
 
1923
        if ((os_use_large_pages = (ibool) my_use_large_pages))
 
1924
                os_large_page_size = (ulint) opt_large_page_size;
 
1925
#endif
 
1926
 
 
1927
        row_rollback_on_timeout = (ibool) innobase_rollback_on_timeout;
 
1928
 
 
1929
        srv_locks_unsafe_for_binlog = (ibool) innobase_locks_unsafe_for_binlog;
 
1930
 
 
1931
        srv_max_n_open_files = (ulint) innobase_open_files;
 
1932
        srv_innodb_status = (ibool) innobase_create_status_file;
 
1933
 
 
1934
        srv_stats_on_metadata = (ibool) innobase_stats_on_metadata;
 
1935
 
 
1936
        btr_search_disabled = (ibool) !innobase_adaptive_hash_index;
 
1937
 
 
1938
        srv_print_verbose_log = mysqld_embedded ? 0 : 1;
 
1939
 
 
1940
        /* Store the default charset-collation number of this MySQL
 
1941
        installation */
 
1942
 
 
1943
        data_mysql_default_charset_coll = (ulint)default_charset_info->number;
 
1944
 
 
1945
        ut_a(DATA_MYSQL_LATIN1_SWEDISH_CHARSET_COLL ==
 
1946
                                        my_charset_latin1.number);
 
1947
        ut_a(DATA_MYSQL_BINARY_CHARSET_COLL == my_charset_bin.number);
 
1948
 
 
1949
        /* Store the latin1_swedish_ci character ordering table to InnoDB. For
 
1950
        non-latin1_swedish_ci charsets we use the MySQL comparison functions,
 
1951
        and consequently we do not need to know the ordering internally in
 
1952
        InnoDB. */
 
1953
 
 
1954
        ut_a(0 == strcmp(my_charset_latin1.name, "latin1_swedish_ci"));
 
1955
        srv_latin1_ordering = my_charset_latin1.sort_order;
 
1956
 
 
1957
        /* Since we in this module access directly the fields of a trx
 
1958
        struct, and due to different headers and flags it might happen that
 
1959
        mutex_t has a different size in this module and in InnoDB
 
1960
        modules, we check at run time that the size is the same in
 
1961
        these compilation modules. */
 
1962
 
 
1963
        err = innobase_start_or_create_for_mysql();
 
1964
 
 
1965
        if (err != DB_SUCCESS) {
 
1966
                my_free(internal_innobase_data_file_path,
 
1967
                                                MYF(MY_ALLOW_ZERO_PTR));
 
1968
                goto error;
 
1969
        }
 
1970
 
 
1971
        (void) hash_init(&innobase_open_tables,system_charset_info, 32, 0, 0,
 
1972
                                        (hash_get_key) innobase_get_key, 0, 0);
 
1973
        pthread_mutex_init(&innobase_share_mutex, MY_MUTEX_INIT_FAST);
 
1974
        pthread_mutex_init(&prepare_commit_mutex, MY_MUTEX_INIT_FAST);
 
1975
        pthread_mutex_init(&commit_threads_m, MY_MUTEX_INIT_FAST);
 
1976
        pthread_mutex_init(&commit_cond_m, MY_MUTEX_INIT_FAST);
 
1977
        pthread_cond_init(&commit_cond, NULL);
 
1978
        innodb_inited= 1;
 
1979
#ifdef MYSQL_DYNAMIC_PLUGIN
 
1980
        if (innobase_hton != p) {
 
1981
                innobase_hton = reinterpret_cast<handlerton*>(p);
 
1982
                *innobase_hton = *innodb_hton_ptr;
 
1983
        }
 
1984
#endif /* MYSQL_DYNAMIC_PLUGIN */
 
1985
 
 
1986
        /* Get the current high water mark format. */
 
1987
        innobase_file_format_check = (char*) trx_sys_file_format_max_get();
 
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
        DBUG_ASSERT(hton == innodb_hton_ptr);
 
2006
 
 
2007
#ifdef __NETWARE__      /* some special cleanup for NetWare */
 
2008
        if (nw_panic) {
 
2009
                set_panic_flag_for_netware();
 
2010
        }
 
2011
#endif
 
2012
        if (innodb_inited) {
 
2013
 
 
2014
                srv_fast_shutdown = (ulint) innobase_fast_shutdown;
 
2015
                innodb_inited = 0;
 
2016
                if (innobase_shutdown_for_mysql() != DB_SUCCESS) {
 
2017
                        err = 1;
 
2018
                }
 
2019
                hash_free(&innobase_open_tables);
 
2020
                my_free(internal_innobase_data_file_path,
 
2021
                                                MYF(MY_ALLOW_ZERO_PTR));
 
2022
                pthread_mutex_destroy(&innobase_share_mutex);
 
2023
                pthread_mutex_destroy(&prepare_commit_mutex);
 
2024
                pthread_mutex_destroy(&commit_threads_m);
 
2025
                pthread_mutex_destroy(&commit_cond_m);
 
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
        DBUG_ASSERT(hton == innodb_hton_ptr);
 
2045
 
 
2046
        log_buffer_flush_to_disk();
 
2047
 
 
2048
        DBUG_RETURN(result);
 
2049
}
 
2050
 
 
2051
/********************************************************************
 
2052
Return alter table flags supported in an InnoDB database. */
 
2053
static
 
2054
uint
 
2055
innobase_alter_table_flags(
 
2056
/*=======================*/
 
2057
        uint    flags)
 
2058
{
 
2059
        return(HA_ONLINE_ADD_INDEX_NO_WRITES
 
2060
                | HA_ONLINE_DROP_INDEX_NO_WRITES
 
2061
                | HA_ONLINE_ADD_UNIQUE_INDEX_NO_WRITES
 
2062
                | HA_ONLINE_DROP_UNIQUE_INDEX_NO_WRITES
 
2063
                | HA_ONLINE_ADD_PK_INDEX_NO_WRITES);
 
2064
}
 
2065
 
 
2066
/*********************************************************************
 
2067
Commits a transaction in an InnoDB database. */
 
2068
static
 
2069
void
 
2070
innobase_commit_low(
 
2071
/*================*/
 
2072
        trx_t*  trx)    /* in: transaction handle */
 
2073
{
 
2074
        if (trx->conc_state == TRX_NOT_STARTED) {
 
2075
 
 
2076
                return;
 
2077
        }
 
2078
 
 
2079
        trx_commit_for_mysql(trx);
 
2080
}
 
2081
 
 
2082
/*********************************************************************
 
2083
Creates an InnoDB transaction struct for the thd if it does not yet have one.
 
2084
Starts a new InnoDB transaction if a transaction is not yet started. And
 
2085
assigns a new snapshot for a consistent read if the transaction does not yet
 
2086
have one. */
 
2087
static
 
2088
int
 
2089
innobase_start_trx_and_assign_read_view(
 
2090
/*====================================*/
 
2091
                        /* out: 0 */
 
2092
        handlerton *hton, /* in: Innodb handlerton */ 
 
2093
        THD*    thd)    /* in: MySQL thread handle of the user for whom
 
2094
                        the transaction should be committed */
 
2095
{
 
2096
        trx_t*  trx;
 
2097
 
 
2098
        DBUG_ENTER("innobase_start_trx_and_assign_read_view");
 
2099
        DBUG_ASSERT(hton == innodb_hton_ptr);
 
2100
 
 
2101
        /* Create a new trx struct for thd, if it does not yet have one */
 
2102
 
 
2103
        trx = check_trx_exists(thd);
 
2104
 
 
2105
        /* This is just to play safe: release a possible FIFO ticket and
 
2106
        search latch. Since we will reserve the kernel mutex, we have to
 
2107
        release the search system latch first to obey the latching order. */
 
2108
 
 
2109
        innobase_release_stat_resources(trx);
 
2110
 
 
2111
        /* If the transaction is not started yet, start it */
 
2112
 
 
2113
        trx_start_if_not_started(trx);
 
2114
 
 
2115
        /* Assign a read view if the transaction does not have it yet */
 
2116
 
 
2117
        trx_assign_read_view(trx);
 
2118
 
 
2119
        /* Set the MySQL flag to mark that there is an active transaction */
 
2120
 
 
2121
        if (trx->active_trans == 0) {
 
2122
                innobase_register_trx_and_stmt(hton, thd);
 
2123
                trx->active_trans = 1;
 
2124
        }
 
2125
 
 
2126
        DBUG_RETURN(0);
 
2127
}
 
2128
 
 
2129
/*********************************************************************
 
2130
Commits a transaction in an InnoDB database or marks an SQL statement
 
2131
ended. */
 
2132
static
 
2133
int
 
2134
innobase_commit(
 
2135
/*============*/
 
2136
                        /* out: 0 */
 
2137
        handlerton *hton, /* in: Innodb handlerton */ 
 
2138
        THD*    thd,    /* in: MySQL thread handle of the user for whom
 
2139
                        the transaction should be committed */
 
2140
        bool    all)    /* in:  TRUE - commit transaction
 
2141
                                FALSE - the current SQL statement ended */
 
2142
{
 
2143
        trx_t*          trx;
 
2144
 
 
2145
        DBUG_ENTER("innobase_commit");
 
2146
        DBUG_ASSERT(hton == innodb_hton_ptr);
 
2147
        DBUG_PRINT("trans", ("ending transaction"));
 
2148
 
 
2149
        trx = check_trx_exists(thd);
 
2150
 
 
2151
        /* Update the info whether we should skip XA steps that eat CPU time */
 
2152
        trx->support_xa = THDVAR(thd, support_xa);
 
2153
 
 
2154
        /* Since we will reserve the kernel mutex, we have to release
 
2155
        the search system latch first to obey the latching order. */
 
2156
 
 
2157
        if (trx->has_search_latch) {
 
2158
                trx_search_latch_release_if_reserved(trx);
 
2159
        }
 
2160
 
 
2161
        /* The flag trx->active_trans is set to 1 in
 
2162
 
 
2163
        1. ::external_lock(),
 
2164
        2. ::start_stmt(),
 
2165
        3. innobase_query_caching_of_table_permitted(),
 
2166
        4. innobase_savepoint(),
 
2167
        5. ::init_table_handle_for_HANDLER(),
 
2168
        6. innobase_start_trx_and_assign_read_view(),
 
2169
        7. ::transactional_table_lock()
 
2170
 
 
2171
        and it is only set to 0 in a commit or a rollback. If it is 0 we know
 
2172
        there cannot be resources to be freed and we could return immediately.
 
2173
        For the time being, we play safe and do the cleanup though there should
 
2174
        be nothing to clean up. */
 
2175
 
 
2176
        if (trx->active_trans == 0
 
2177
                && trx->conc_state != TRX_NOT_STARTED) {
 
2178
 
 
2179
                sql_print_error("trx->active_trans == 0, but"
 
2180
                        " trx->conc_state != TRX_NOT_STARTED");
 
2181
        }
 
2182
        if (all
 
2183
                || (!thd_test_options(thd, OPTION_NOT_AUTOCOMMIT | OPTION_BEGIN))) {
 
2184
 
 
2185
                /* We were instructed to commit the whole transaction, or
 
2186
                this is an SQL statement end and autocommit is on */
 
2187
 
 
2188
                /* We need current binlog position for ibbackup to work.
 
2189
                Note, the position is current because of
 
2190
                prepare_commit_mutex */
 
2191
retry:
 
2192
                if (srv_commit_concurrency > 0) {
 
2193
                        pthread_mutex_lock(&commit_cond_m);
 
2194
                        commit_threads++;
 
2195
 
 
2196
                        if (commit_threads > srv_commit_concurrency) {
 
2197
                                commit_threads--;
 
2198
                                pthread_cond_wait(&commit_cond,
 
2199
                                        &commit_cond_m);
 
2200
                                pthread_mutex_unlock(&commit_cond_m);
 
2201
                                goto retry;
 
2202
                        }
 
2203
                        else {
 
2204
                                pthread_mutex_unlock(&commit_cond_m);
 
2205
                        }
 
2206
                }
 
2207
 
 
2208
                trx->mysql_log_file_name = mysql_bin_log_file_name();
 
2209
                trx->mysql_log_offset = (ib_int64_t) mysql_bin_log_file_pos();
 
2210
 
 
2211
                innobase_commit_low(trx);
 
2212
 
 
2213
                if (srv_commit_concurrency > 0) {
 
2214
                        pthread_mutex_lock(&commit_cond_m);
 
2215
                        commit_threads--;
 
2216
                        pthread_cond_signal(&commit_cond);
 
2217
                        pthread_mutex_unlock(&commit_cond_m);
 
2218
                }
 
2219
 
 
2220
                if (trx->active_trans == 2) {
 
2221
 
 
2222
                        pthread_mutex_unlock(&prepare_commit_mutex);
 
2223
                }
 
2224
 
 
2225
                trx->active_trans = 0;
 
2226
 
 
2227
        } else {
 
2228
                /* We just mark the SQL statement ended and do not do a
 
2229
                transaction commit */
 
2230
 
 
2231
                /* If we had reserved the auto-inc lock for some
 
2232
                table in this SQL statement we release it now */
 
2233
 
 
2234
                row_unlock_table_autoinc_for_mysql(trx);
 
2235
 
 
2236
                /* Store the current undo_no of the transaction so that we
 
2237
                know where to roll back if we have to roll back the next
 
2238
                SQL statement */
 
2239
 
 
2240
                trx_mark_sql_stat_end(trx);
 
2241
        }
 
2242
 
 
2243
        trx->n_autoinc_rows = 0; /* Reset the number AUTO-INC rows required */
 
2244
 
 
2245
        if (trx->declared_to_be_inside_innodb) {
 
2246
                /* Release our possible ticket in the FIFO */
 
2247
 
 
2248
                srv_conc_force_exit_innodb(trx);
 
2249
        }
 
2250
 
 
2251
        /* Tell the InnoDB server that there might be work for utility
 
2252
        threads: */
 
2253
        srv_active_wake_master_thread();
 
2254
 
 
2255
        DBUG_RETURN(0);
 
2256
}
 
2257
 
 
2258
/*********************************************************************
 
2259
Rolls back a transaction or the latest SQL statement. */
 
2260
static
 
2261
int
 
2262
innobase_rollback(
 
2263
/*==============*/
 
2264
                        /* out: 0 or error number */
 
2265
        handlerton *hton, /* in: Innodb handlerton */ 
 
2266
        THD*    thd,    /* in: handle to the MySQL thread of the user
 
2267
                        whose transaction should be rolled back */
 
2268
        bool    all)    /* in:  TRUE - commit transaction
 
2269
                                FALSE - the current SQL statement ended */
 
2270
{
 
2271
        int     error = 0;
 
2272
        trx_t*  trx;
 
2273
 
 
2274
        DBUG_ENTER("innobase_rollback");
 
2275
        DBUG_ASSERT(hton == innodb_hton_ptr);
 
2276
        DBUG_PRINT("trans", ("aborting transaction"));
 
2277
 
 
2278
        trx = check_trx_exists(thd);
 
2279
 
 
2280
        /* Update the info whether we should skip XA steps that eat CPU time */
 
2281
        trx->support_xa = THDVAR(thd, support_xa);
 
2282
 
 
2283
        /* Release a possible FIFO ticket and search latch. Since we will
 
2284
        reserve the kernel mutex, we have to release the search system latch
 
2285
        first to obey the latching order. */
 
2286
 
 
2287
        innobase_release_stat_resources(trx);
 
2288
 
 
2289
        /* If we had reserved the auto-inc lock for some table (if
 
2290
        we come here to roll back the latest SQL statement) we
 
2291
        release it now before a possibly lengthy rollback */
 
2292
 
 
2293
        row_unlock_table_autoinc_for_mysql(trx);
 
2294
 
 
2295
        if (all
 
2296
                || !thd_test_options(thd, OPTION_NOT_AUTOCOMMIT | OPTION_BEGIN)) {
 
2297
 
 
2298
                error = trx_rollback_for_mysql(trx);
 
2299
                trx->active_trans = 0;
 
2300
        } else {
 
2301
                error = trx_rollback_last_sql_stat_for_mysql(trx);
 
2302
        }
 
2303
 
 
2304
        DBUG_RETURN(convert_error_code_to_mysql(error, 0, NULL));
 
2305
}
 
2306
 
 
2307
/*********************************************************************
 
2308
Rolls back a transaction */
 
2309
static
 
2310
int
 
2311
innobase_rollback_trx(
 
2312
/*==================*/
 
2313
                        /* out: 0 or error number */
 
2314
        trx_t*  trx)    /*  in: transaction */
 
2315
{
 
2316
        int     error = 0;
 
2317
 
 
2318
        DBUG_ENTER("innobase_rollback_trx");
 
2319
        DBUG_PRINT("trans", ("aborting transaction"));
 
2320
 
 
2321
        /* Release a possible FIFO ticket and search latch. Since we will
 
2322
        reserve the kernel mutex, we have to release the search system latch
 
2323
        first to obey the latching order. */
 
2324
 
 
2325
        innobase_release_stat_resources(trx);
 
2326
 
 
2327
        /* If we had reserved the auto-inc lock for some table (if
 
2328
        we come here to roll back the latest SQL statement) we
 
2329
        release it now before a possibly lengthy rollback */
 
2330
 
 
2331
        row_unlock_table_autoinc_for_mysql(trx);
 
2332
 
 
2333
        error = trx_rollback_for_mysql(trx);
 
2334
 
 
2335
        DBUG_RETURN(convert_error_code_to_mysql(error, 0, NULL));
 
2336
}
 
2337
 
 
2338
/*********************************************************************
 
2339
Rolls back a transaction to a savepoint. */
 
2340
static
 
2341
int
 
2342
innobase_rollback_to_savepoint(
 
2343
/*===========================*/
 
2344
                                /* out: 0 if success, HA_ERR_NO_SAVEPOINT if
 
2345
                                no savepoint with the given name */
 
2346
        handlerton *hton,       /* in: Innodb handlerton */ 
 
2347
        THD*    thd,            /* in: handle to the MySQL thread of the user
 
2348
                                whose transaction should be rolled back */
 
2349
        void*   savepoint)      /* in: savepoint data */
 
2350
{
 
2351
        ib_int64_t      mysql_binlog_cache_pos;
 
2352
        int             error = 0;
 
2353
        trx_t*          trx;
 
2354
        char            name[64];
 
2355
 
 
2356
        DBUG_ENTER("innobase_rollback_to_savepoint");
 
2357
        DBUG_ASSERT(hton == innodb_hton_ptr);
 
2358
 
 
2359
        trx = check_trx_exists(thd);
 
2360
 
 
2361
        /* Release a possible FIFO ticket and search latch. Since we will
 
2362
        reserve the kernel mutex, we have to release the search system latch
 
2363
        first to obey the latching order. */
 
2364
 
 
2365
        innobase_release_stat_resources(trx);
 
2366
 
 
2367
        /* TODO: use provided savepoint data area to store savepoint data */
 
2368
 
 
2369
        longlong2str((ulint)savepoint, name, 36);
 
2370
 
 
2371
        error = (int) trx_rollback_to_savepoint_for_mysql(trx, name,
 
2372
                                                &mysql_binlog_cache_pos);
 
2373
        DBUG_RETURN(convert_error_code_to_mysql(error, 0, NULL));
 
2374
}
 
2375
 
 
2376
/*********************************************************************
 
2377
Release transaction savepoint name. */
 
2378
static
 
2379
int
 
2380
innobase_release_savepoint(
 
2381
/*=======================*/
 
2382
                                /* out: 0 if success, HA_ERR_NO_SAVEPOINT if
 
2383
                                no savepoint with the given name */
 
2384
        handlerton*     hton,   /* in: handlerton for Innodb */
 
2385
        THD*    thd,            /* in: handle to the MySQL thread of the user
 
2386
                                whose transaction should be rolled back */
 
2387
        void*   savepoint)      /* in: savepoint data */
 
2388
{
 
2389
        int             error = 0;
 
2390
        trx_t*          trx;
 
2391
        char            name[64];
 
2392
 
 
2393
        DBUG_ENTER("innobase_release_savepoint");
 
2394
        DBUG_ASSERT(hton == innodb_hton_ptr);
 
2395
 
 
2396
        trx = check_trx_exists(thd);
 
2397
 
 
2398
        /* TODO: use provided savepoint data area to store savepoint data */
 
2399
 
 
2400
        longlong2str((ulint)savepoint, name, 36);
 
2401
 
 
2402
        error = (int) trx_release_savepoint_for_mysql(trx, name);
 
2403
 
 
2404
        DBUG_RETURN(convert_error_code_to_mysql(error, 0, NULL));
 
2405
}
 
2406
 
 
2407
/*********************************************************************
 
2408
Sets a transaction savepoint. */
 
2409
static
 
2410
int
 
2411
innobase_savepoint(
 
2412
/*===============*/
 
2413
                                /* out: always 0, that is, always succeeds */
 
2414
        handlerton*     hton,   /* in: handle to the Innodb handlerton */
 
2415
        THD*    thd,            /* in: handle to the MySQL thread */
 
2416
        void*   savepoint)      /* in: savepoint data */
 
2417
{
 
2418
        int     error = 0;
 
2419
        trx_t*  trx;
 
2420
 
 
2421
        DBUG_ENTER("innobase_savepoint");
 
2422
        DBUG_ASSERT(hton == innodb_hton_ptr);
 
2423
 
 
2424
        /*
 
2425
          In the autocommit mode there is no sense to set a savepoint
 
2426
          (unless we are in sub-statement), so SQL layer ensures that
 
2427
          this method is never called in such situation.
 
2428
        */
 
2429
#ifdef MYSQL_SERVER /* plugins cannot access thd->in_sub_stmt */
 
2430
        DBUG_ASSERT(thd_test_options(thd, OPTION_NOT_AUTOCOMMIT | OPTION_BEGIN) ||
 
2431
                thd->in_sub_stmt);
 
2432
#endif /* MYSQL_SERVER */
 
2433
 
 
2434
        trx = check_trx_exists(thd);
 
2435
 
 
2436
        /* Release a possible FIFO ticket and search latch. Since we will
 
2437
        reserve the kernel mutex, we have to release the search system latch
 
2438
        first to obey the latching order. */
 
2439
 
 
2440
        innobase_release_stat_resources(trx);
 
2441
 
 
2442
        /* cannot happen outside of transaction */
 
2443
        DBUG_ASSERT(trx->active_trans);
 
2444
 
 
2445
        /* TODO: use provided savepoint data area to store savepoint data */
 
2446
        char name[64];
 
2447
        longlong2str((ulint)savepoint,name,36);
 
2448
 
 
2449
        error = (int) trx_savepoint_for_mysql(trx, name, (ib_int64_t)0);
 
2450
 
 
2451
        DBUG_RETURN(convert_error_code_to_mysql(error, 0, NULL));
 
2452
}
 
2453
 
 
2454
/*********************************************************************
 
2455
Frees a possible InnoDB trx object associated with the current THD. */
 
2456
static
 
2457
int
 
2458
innobase_close_connection(
 
2459
/*======================*/
 
2460
                        /* out: 0 or error number */
 
2461
        handlerton*     hton,   /* in:  innobase handlerton */
 
2462
        THD*    thd)    /* in: handle to the MySQL thread of the user
 
2463
                        whose resources should be free'd */
 
2464
{
 
2465
        trx_t*  trx;
 
2466
 
 
2467
        DBUG_ENTER("innobase_close_connection");
 
2468
        DBUG_ASSERT(hton == innodb_hton_ptr);
 
2469
        trx = thd_to_trx(thd);
 
2470
 
 
2471
        ut_a(trx);
 
2472
 
 
2473
        if (trx->active_trans == 0
 
2474
                && trx->conc_state != TRX_NOT_STARTED) {
 
2475
 
 
2476
                sql_print_error("trx->active_trans == 0, but"
 
2477
                        " trx->conc_state != TRX_NOT_STARTED");
 
2478
        }
 
2479
 
 
2480
 
 
2481
        if (trx->conc_state != TRX_NOT_STARTED &&
 
2482
                global_system_variables.log_warnings) {
 
2483
                sql_print_warning(
 
2484
                        "MySQL is closing a connection that has an active "
 
2485
                        "InnoDB transaction.  %lu row modifications will "
 
2486
                        "roll back.",
 
2487
                        (ulong) trx->undo_no.low);
 
2488
        }
 
2489
 
 
2490
        innobase_rollback_trx(trx);
 
2491
 
 
2492
        thr_local_free(trx->mysql_thread_id);
 
2493
        trx_free_for_mysql(trx);
 
2494
 
 
2495
        DBUG_RETURN(0);
 
2496
}
 
2497
 
 
2498
 
 
2499
/*****************************************************************************
 
2500
** InnoDB database tables
 
2501
*****************************************************************************/
 
2502
 
 
2503
/********************************************************************
 
2504
Get the record format from the data dictionary. */
 
2505
UNIV_INTERN
 
2506
enum row_type
 
2507
ha_innobase::get_row_type() const
 
2508
/*=============================*/
 
2509
                        /* out: one of
 
2510
                        ROW_TYPE_REDUNDANT,
 
2511
                        ROW_TYPE_COMPACT,
 
2512
                        ROW_TYPE_COMPRESSED,
 
2513
                        ROW_TYPE_DYNAMIC */
 
2514
{
 
2515
        if (prebuilt && prebuilt->table) {
 
2516
                const ulint     flags = prebuilt->table->flags;
 
2517
 
 
2518
                if (UNIV_UNLIKELY(!flags)) {
 
2519
                        return(ROW_TYPE_REDUNDANT);
 
2520
                }
 
2521
 
 
2522
                ut_ad(flags & DICT_TF_COMPACT);
 
2523
 
 
2524
                switch (flags & DICT_TF_FORMAT_MASK) {
 
2525
                case DICT_TF_FORMAT_51 << DICT_TF_FORMAT_SHIFT:
 
2526
                        return(ROW_TYPE_COMPACT);
 
2527
                case DICT_TF_FORMAT_ZIP << DICT_TF_FORMAT_SHIFT:
 
2528
                        if (flags & DICT_TF_ZSSIZE_MASK) {
 
2529
                                return(ROW_TYPE_COMPRESSED);
 
2530
                        } else {
 
2531
                                return(ROW_TYPE_DYNAMIC);
 
2532
                        }
 
2533
#if DICT_TF_FORMAT_ZIP != DICT_TF_FORMAT_MAX
 
2534
# error "DICT_TF_FORMAT_ZIP != DICT_TF_FORMAT_MAX"
 
2535
#endif
 
2536
                }
 
2537
        }
 
2538
        ut_ad(0);
 
2539
        return(ROW_TYPE_NOT_USED);
 
2540
}
 
2541
 
 
2542
 
 
2543
 
 
2544
/********************************************************************
 
2545
Get the table flags to use for the statement. */
 
2546
UNIV_INTERN
 
2547
handler::Table_flags
 
2548
ha_innobase::table_flags() const
 
2549
{
 
2550
       /* Need to use tx_isolation here since table flags is (also)
 
2551
          called before prebuilt is inited. */
 
2552
        ulong const tx_isolation = thd_tx_isolation(current_thd);
 
2553
        if (tx_isolation <= ISO_READ_COMMITTED)
 
2554
                return int_table_flags;
 
2555
        return int_table_flags | HA_BINLOG_STMT_CAPABLE;
 
2556
}
 
2557
 
 
2558
/********************************************************************
 
2559
Gives the file extension of an InnoDB single-table tablespace. */
 
2560
static const char* ha_innobase_exts[] = {
 
2561
  ".ibd",
 
2562
  NullS
 
2563
};
 
2564
 
 
2565
UNIV_INTERN
 
2566
const char*
 
2567
ha_innobase::table_type() const
 
2568
/*===========================*/
 
2569
                                /* out: table type */
 
2570
{
 
2571
        return(innobase_hton_name);
 
2572
}
 
2573
 
 
2574
UNIV_INTERN
 
2575
const char*
 
2576
ha_innobase::index_type(uint)
 
2577
/*=========================*/
 
2578
                                /* out: index type */
 
2579
{
 
2580
        return("BTREE");
 
2581
}
 
2582
 
 
2583
UNIV_INTERN
 
2584
const char**
 
2585
ha_innobase::bas_ext() const
 
2586
/*========================*/
 
2587
                                /* out: file extension string */
 
2588
{
 
2589
        return(ha_innobase_exts);
 
2590
}
 
2591
 
 
2592
UNIV_INTERN
 
2593
ulong
 
2594
ha_innobase::index_flags(uint, uint, bool) const
 
2595
{
 
2596
        return(HA_READ_NEXT | HA_READ_PREV | HA_READ_ORDER
 
2597
               | HA_READ_RANGE | HA_KEYREAD_ONLY);
 
2598
}
 
2599
 
 
2600
UNIV_INTERN
 
2601
uint
 
2602
ha_innobase::max_supported_keys() const
 
2603
{
 
2604
        return(MAX_KEY);
 
2605
}
 
2606
 
 
2607
UNIV_INTERN
 
2608
uint
 
2609
ha_innobase::max_supported_key_length() const
 
2610
{
 
2611
        /* An InnoDB page must store >= 2 keys; a secondary key record
 
2612
        must also contain the primary key value: max key length is
 
2613
        therefore set to slightly less than 1 / 4 of page size which
 
2614
        is 16 kB; but currently MySQL does not work with keys whose
 
2615
        size is > MAX_KEY_LENGTH */
 
2616
        return(3500);
 
2617
}
 
2618
 
 
2619
UNIV_INTERN
 
2620
const key_map*
 
2621
ha_innobase::keys_to_use_for_scanning()
 
2622
{
 
2623
        return(&key_map_full);
 
2624
}
 
2625
 
 
2626
UNIV_INTERN
 
2627
uint8
 
2628
ha_innobase::table_cache_type()
 
2629
{
 
2630
        return(HA_CACHE_TBL_ASKTRANSACT);
 
2631
}
 
2632
 
 
2633
UNIV_INTERN
 
2634
bool
 
2635
ha_innobase::primary_key_is_clustered()
 
2636
{
 
2637
        return(true);
 
2638
}
 
2639
 
 
2640
/*********************************************************************
 
2641
Normalizes a table name string. A normalized name consists of the
 
2642
database name catenated to '/' and table name. An example:
 
2643
test/mytable. On Windows normalization puts both the database name and the
 
2644
table name always to lower case. */
 
2645
static
 
2646
void
 
2647
normalize_table_name(
 
2648
/*=================*/
 
2649
        char*           norm_name,      /* out: normalized name as a
 
2650
                                        null-terminated string */
 
2651
        const char*     name)           /* in: table name string */
 
2652
{
 
2653
        char*   name_ptr;
 
2654
        char*   db_ptr;
 
2655
        char*   ptr;
 
2656
 
 
2657
        /* Scan name from the end */
 
2658
 
 
2659
        ptr = strend(name)-1;
 
2660
 
 
2661
        while (ptr >= name && *ptr != '\\' && *ptr != '/') {
 
2662
                ptr--;
 
2663
        }
 
2664
 
 
2665
        name_ptr = ptr + 1;
 
2666
 
 
2667
        DBUG_ASSERT(ptr > name);
 
2668
 
 
2669
        ptr--;
 
2670
 
 
2671
        while (ptr >= name && *ptr != '\\' && *ptr != '/') {
 
2672
                ptr--;
 
2673
        }
 
2674
 
 
2675
        db_ptr = ptr + 1;
 
2676
 
 
2677
        memcpy(norm_name, db_ptr, strlen(name) + 1 - (db_ptr - name));
 
2678
 
 
2679
        norm_name[name_ptr - db_ptr - 1] = '/';
 
2680
 
 
2681
#ifdef __WIN__
 
2682
        innobase_casedn_str(norm_name);
 
2683
#endif
 
2684
}
 
2685
 
 
2686
/*********************************************************************
 
2687
Creates and opens a handle to a table which already exists in an InnoDB
 
2688
database. */
 
2689
UNIV_INTERN
 
2690
int
 
2691
ha_innobase::open(
 
2692
/*==============*/
 
2693
                                        /* out: 1 if error, 0 if success */
 
2694
        const char*     name,           /* in: table name */
 
2695
        int             mode,           /* in: not used */
 
2696
        uint            test_if_locked) /* in: not used */
 
2697
{
 
2698
        dict_table_t*   ib_table;
 
2699
        char            norm_name[1000];
 
2700
        THD*            thd;
 
2701
        ulint           retries = 0;
 
2702
        char*           is_part = NULL;
 
2703
 
 
2704
        DBUG_ENTER("ha_innobase::open");
 
2705
 
 
2706
        UT_NOT_USED(mode);
 
2707
        UT_NOT_USED(test_if_locked);
 
2708
 
 
2709
        thd = ha_thd();
 
2710
        normalize_table_name(norm_name, name);
 
2711
 
 
2712
        user_thd = NULL;
 
2713
 
 
2714
        if (!(share=get_share(name))) {
 
2715
 
 
2716
                DBUG_RETURN(1);
 
2717
        }
 
2718
 
 
2719
        /* Create buffers for packing the fields of a record. Why
 
2720
        table->reclength did not work here? Obviously, because char
 
2721
        fields when packed actually became 1 byte longer, when we also
 
2722
        stored the string length as the first byte. */
 
2723
 
 
2724
        upd_and_key_val_buff_len =
 
2725
                                table->s->reclength + table->s->max_key_length
 
2726
                                                        + MAX_REF_PARTS * 3;
 
2727
        if (!(uchar*) my_multi_malloc(MYF(MY_WME),
 
2728
                        &upd_buff, upd_and_key_val_buff_len,
 
2729
                        &key_val_buff, upd_and_key_val_buff_len,
 
2730
                        NullS)) {
 
2731
                free_share(share);
 
2732
 
 
2733
                DBUG_RETURN(1);
 
2734
        }
 
2735
 
 
2736
        /* We look for pattern #P# to see if the table is partitioned
 
2737
        MySQL table. The retry logic for partitioned tables is a
 
2738
        workaround for http://bugs.mysql.com/bug.php?id=33349. Look
 
2739
        at support issue https://support.mysql.com/view.php?id=21080
 
2740
        for more details. */
 
2741
        is_part = strstr(norm_name, "#P#");
 
2742
retry:
 
2743
        /* Get pointer to a table object in InnoDB dictionary cache */
 
2744
        ib_table = dict_table_get(norm_name, TRUE);
 
2745
        
 
2746
        if (NULL == ib_table) {
 
2747
                if (is_part && retries < 10) {
 
2748
                        ++retries;
 
2749
                        os_thread_sleep(100000);
 
2750
                        goto retry;
 
2751
                }
 
2752
 
 
2753
                if (is_part) {
 
2754
                        sql_print_error("Failed to open table %s after "
 
2755
                                        "%lu attemtps.\n", norm_name,
 
2756
                                        retries);
 
2757
                }
 
2758
 
 
2759
                sql_print_error("Cannot find or open table %s from\n"
 
2760
                                "the internal data dictionary of InnoDB "
 
2761
                                "though the .frm file for the\n"
 
2762
                                "table exists. Maybe you have deleted and "
 
2763
                                "recreated InnoDB data\n"
 
2764
                                "files but have forgotten to delete the "
 
2765
                                "corresponding .frm files\n"
 
2766
                                "of InnoDB tables, or you have moved .frm "
 
2767
                                "files to another database?\n"
 
2768
                                "or, the table contains indexes that this "
 
2769
                                "version of the engine\n"
 
2770
                                "doesn't support.\n"
 
2771
                                "See http://dev.mysql.com/doc/refman/5.1/en/innodb-troubleshooting.html\n"
 
2772
                                "how you can resolve the problem.\n",
 
2773
                                norm_name);
 
2774
                free_share(share);
 
2775
                my_free(upd_buff, MYF(0));
 
2776
                my_errno = ENOENT;
 
2777
 
 
2778
                DBUG_RETURN(HA_ERR_NO_SUCH_TABLE);
 
2779
        }
 
2780
 
 
2781
        if (ib_table->ibd_file_missing && !thd_tablespace_op(thd)) {
 
2782
                sql_print_error("MySQL is trying to open a table handle but "
 
2783
                                "the .ibd file for\ntable %s does not exist.\n"
 
2784
                                "Have you deleted the .ibd file from the "
 
2785
                                "database directory under\nthe MySQL datadir, "
 
2786
                                "or have you used DISCARD TABLESPACE?\n"
 
2787
                                "See http://dev.mysql.com/doc/refman/5.1/en/innodb-troubleshooting.html\n"
 
2788
                                "how you can resolve the problem.\n",
 
2789
                                norm_name);
 
2790
                free_share(share);
 
2791
                my_free(upd_buff, MYF(0));
 
2792
                my_errno = ENOENT;
 
2793
 
 
2794
                dict_table_decrement_handle_count(ib_table, FALSE);
 
2795
                DBUG_RETURN(HA_ERR_NO_SUCH_TABLE);
 
2796
        }
 
2797
 
 
2798
        prebuilt = row_create_prebuilt(ib_table);
 
2799
 
 
2800
        prebuilt->mysql_row_len = table->s->reclength;
 
2801
 
 
2802
        /* Looks like MySQL-3.23 sometimes has primary key number != 0 */
 
2803
 
 
2804
        primary_key = table->s->primary_key;
 
2805
        key_used_on_scan = primary_key;
 
2806
 
 
2807
        /* Allocate a buffer for a 'row reference'. A row reference is
 
2808
        a string of bytes of length ref_length which uniquely specifies
 
2809
        a row in our table. Note that MySQL may also compare two row
 
2810
        references for equality by doing a simple memcmp on the strings
 
2811
        of length ref_length! */
 
2812
 
 
2813
        if (!row_table_got_default_clust_index(ib_table)) {
 
2814
                if (primary_key >= MAX_KEY) {
 
2815
                  sql_print_error("Table %s has a primary key in InnoDB data "
 
2816
                                  "dictionary, but not in MySQL!", name);
 
2817
                }
 
2818
 
 
2819
                prebuilt->clust_index_was_generated = FALSE;
 
2820
 
 
2821
                /* MySQL allocates the buffer for ref. key_info->key_length
 
2822
                includes space for all key columns + one byte for each column
 
2823
                that may be NULL. ref_length must be as exact as possible to
 
2824
                save space, because all row reference buffers are allocated
 
2825
                based on ref_length. */
 
2826
 
 
2827
                ref_length = table->key_info[primary_key].key_length;
 
2828
        } else {
 
2829
                if (primary_key != MAX_KEY) {
 
2830
                  sql_print_error("Table %s has no primary key in InnoDB data "
 
2831
                                  "dictionary, but has one in MySQL! If you "
 
2832
                                  "created the table with a MySQL version < "
 
2833
                                  "3.23.54 and did not define a primary key, "
 
2834
                                  "but defined a unique key with all non-NULL "
 
2835
                                  "columns, then MySQL internally treats that "
 
2836
                                  "key as the primary key. You can fix this "
 
2837
                                  "error by dump + DROP + CREATE + reimport "
 
2838
                                  "of the table.", name);
 
2839
                }
 
2840
 
 
2841
                prebuilt->clust_index_was_generated = TRUE;
 
2842
 
 
2843
                ref_length = DATA_ROW_ID_LEN;
 
2844
 
 
2845
                /* If we automatically created the clustered index, then
 
2846
                MySQL does not know about it, and MySQL must NOT be aware
 
2847
                of the index used on scan, to make it avoid checking if we
 
2848
                update the column of the index. That is why we assert below
 
2849
                that key_used_on_scan is the undefined value MAX_KEY.
 
2850
                The column is the row id in the automatical generation case,
 
2851
                and it will never be updated anyway. */
 
2852
 
 
2853
                if (key_used_on_scan != MAX_KEY) {
 
2854
                        sql_print_warning(
 
2855
                                "Table %s key_used_on_scan is %lu even "
 
2856
                                "though there is no primary key inside "
 
2857
                                "InnoDB.", name, (ulong) key_used_on_scan);
 
2858
                }
 
2859
        }
 
2860
 
 
2861
        /* Index block size in InnoDB: used by MySQL in query optimization */
 
2862
        stats.block_size = 16 * 1024;
 
2863
 
 
2864
        /* Init table lock structure */
 
2865
        thr_lock_data_init(&share->lock,&lock,(void*) 0);
 
2866
 
 
2867
        if (prebuilt->table) {
 
2868
                /* We update the highest file format in the system table
 
2869
                space, if this table has higher file format setting. */
 
2870
 
 
2871
                trx_sys_file_format_max_update(
 
2872
                        prebuilt->table->flags, &innobase_file_format_check);
 
2873
        }
 
2874
 
 
2875
        info(HA_STATUS_NO_LOCK | HA_STATUS_VARIABLE | HA_STATUS_CONST);
 
2876
 
 
2877
        DBUG_RETURN(0);
 
2878
}
 
2879
 
 
2880
UNIV_INTERN
 
2881
uint
 
2882
ha_innobase::max_supported_key_part_length() const
 
2883
{
 
2884
        return(DICT_MAX_INDEX_COL_LEN - 1);
 
2885
}
 
2886
 
 
2887
/**********************************************************************
 
2888
Closes a handle to an InnoDB table. */
 
2889
UNIV_INTERN
 
2890
int
 
2891
ha_innobase::close(void)
 
2892
/*====================*/
 
2893
                                /* out: 0 */
 
2894
{
 
2895
        THD*    thd;
 
2896
 
 
2897
        DBUG_ENTER("ha_innobase::close");
 
2898
 
 
2899
        thd = current_thd;  // avoid calling current_thd twice, it may be slow
 
2900
        if (thd != NULL) {
 
2901
                innobase_release_temporary_latches(ht, thd);
 
2902
        }
 
2903
 
 
2904
        row_prebuilt_free(prebuilt, FALSE);
 
2905
 
 
2906
        my_free(upd_buff, MYF(0));
 
2907
        free_share(share);
 
2908
 
 
2909
        /* Tell InnoDB server that there might be work for
 
2910
        utility threads: */
 
2911
 
 
2912
        srv_active_wake_master_thread();
 
2913
 
 
2914
        DBUG_RETURN(0);
 
2915
}
 
2916
 
 
2917
/* The following accessor functions should really be inside MySQL code! */
 
2918
 
 
2919
/******************************************************************
 
2920
Gets field offset for a field in a table. */
 
2921
inline
 
2922
uint
 
2923
get_field_offset(
 
2924
/*=============*/
 
2925
                        /* out: offset */
 
2926
        TABLE*  table,  /* in: MySQL table object */
 
2927
        Field*  field)  /* in: MySQL field object */
 
2928
{
 
2929
        return((uint) (field->ptr - table->record[0]));
 
2930
}
 
2931
 
 
2932
/******************************************************************
 
2933
Checks if a field in a record is SQL NULL. Uses the record format
 
2934
information in table to track the null bit in record. */
 
2935
static inline
 
2936
uint
 
2937
field_in_record_is_null(
 
2938
/*====================*/
 
2939
                        /* out: 1 if NULL, 0 otherwise */
 
2940
        TABLE*  table,  /* in: MySQL table object */
 
2941
        Field*  field,  /* in: MySQL field object */
 
2942
        char*   record) /* in: a row in MySQL format */
 
2943
{
 
2944
        int     null_offset;
 
2945
 
 
2946
        if (!field->null_ptr) {
 
2947
 
 
2948
                return(0);
 
2949
        }
 
2950
 
 
2951
        null_offset = (uint) ((char*) field->null_ptr
 
2952
                                        - (char*) table->record[0]);
 
2953
 
 
2954
        if (record[null_offset] & field->null_bit) {
 
2955
 
 
2956
                return(1);
 
2957
        }
 
2958
 
 
2959
        return(0);
 
2960
}
 
2961
 
 
2962
/******************************************************************
 
2963
Sets a field in a record to SQL NULL. Uses the record format
 
2964
information in table to track the null bit in record. */
 
2965
inline
 
2966
void
 
2967
set_field_in_record_to_null(
 
2968
/*========================*/
 
2969
        TABLE*  table,  /* in: MySQL table object */
 
2970
        Field*  field,  /* in: MySQL field object */
 
2971
        char*   record) /* in: a row in MySQL format */
 
2972
{
 
2973
        int     null_offset;
 
2974
 
 
2975
        null_offset = (uint) ((char*) field->null_ptr
 
2976
                                        - (char*) table->record[0]);
 
2977
 
 
2978
        record[null_offset] = record[null_offset] | field->null_bit;
 
2979
}
 
2980
 
 
2981
/*****************************************************************
 
2982
InnoDB uses this function to compare two data fields for which the data type
 
2983
is such that we must use MySQL code to compare them. NOTE that the prototype
 
2984
of this function is in rem0cmp.c in InnoDB source code! If you change this
 
2985
function, remember to update the prototype there! */
 
2986
extern "C" UNIV_INTERN
 
2987
int
 
2988
innobase_mysql_cmp(
 
2989
/*===============*/
 
2990
                                        /* out: 1, 0, -1, if a is greater,
 
2991
                                        equal, less than b, respectively */
 
2992
        int             mysql_type,     /* in: MySQL type */
 
2993
        uint            charset_number, /* in: number of the charset */
 
2994
        const unsigned char* a,         /* in: data field */
 
2995
        unsigned int    a_length,       /* in: data field length,
 
2996
                                        not UNIV_SQL_NULL */
 
2997
        const unsigned char* b,         /* in: data field */
 
2998
        unsigned int    b_length)       /* in: data field length,
 
2999
                                        not UNIV_SQL_NULL */
 
3000
{
 
3001
        CHARSET_INFO*           charset;
 
3002
        enum_field_types        mysql_tp;
 
3003
        int                     ret;
 
3004
 
 
3005
        DBUG_ASSERT(a_length != UNIV_SQL_NULL);
 
3006
        DBUG_ASSERT(b_length != UNIV_SQL_NULL);
 
3007
 
 
3008
        mysql_tp = (enum_field_types) mysql_type;
 
3009
 
 
3010
        switch (mysql_tp) {
 
3011
 
 
3012
        case MYSQL_TYPE_BIT:
 
3013
        case MYSQL_TYPE_STRING:
 
3014
        case MYSQL_TYPE_VAR_STRING:
 
3015
        case MYSQL_TYPE_TINY_BLOB:
 
3016
        case MYSQL_TYPE_MEDIUM_BLOB:
 
3017
        case MYSQL_TYPE_BLOB:
 
3018
        case MYSQL_TYPE_LONG_BLOB:
 
3019
        case MYSQL_TYPE_VARCHAR:
 
3020
                /* Use the charset number to pick the right charset struct for
 
3021
                the comparison. Since the MySQL function get_charset may be
 
3022
                slow before Bar removes the mutex operation there, we first
 
3023
                look at 2 common charsets directly. */
 
3024
 
 
3025
                if (charset_number == default_charset_info->number) {
 
3026
                        charset = default_charset_info;
 
3027
                } else if (charset_number == my_charset_latin1.number) {
 
3028
                        charset = &my_charset_latin1;
 
3029
                } else {
 
3030
                        charset = get_charset(charset_number, MYF(MY_WME));
 
3031
 
 
3032
                        if (charset == NULL) {
 
3033
                          sql_print_error("InnoDB needs charset %lu for doing "
 
3034
                                          "a comparison, but MySQL cannot "
 
3035
                                          "find that charset.",
 
3036
                                          (ulong) charset_number);
 
3037
                                ut_a(0);
 
3038
                        }
 
3039
                }
 
3040
 
 
3041
                /* Starting from 4.1.3, we use strnncollsp() in comparisons of
 
3042
                non-latin1_swedish_ci strings. NOTE that the collation order
 
3043
                changes then: 'b\0\0...' is ordered BEFORE 'b  ...'. Users
 
3044
                having indexes on such data need to rebuild their tables! */
 
3045
 
 
3046
                ret = charset->coll->strnncollsp(charset,
 
3047
                                  a, a_length,
 
3048
                                                 b, b_length, 0);
 
3049
                if (ret < 0) {
 
3050
                        return(-1);
 
3051
                } else if (ret > 0) {
 
3052
                        return(1);
 
3053
                } else {
 
3054
                        return(0);
 
3055
                }
 
3056
        default:
 
3057
                ut_error;
 
3058
        }
 
3059
 
 
3060
        return(0);
 
3061
}
 
3062
 
 
3063
/******************************************************************
 
3064
Converts a MySQL type to an InnoDB type. Note that this function returns
 
3065
the 'mtype' of InnoDB. InnoDB differentiates between MySQL's old <= 4.1
 
3066
VARCHAR and the new true VARCHAR in >= 5.0.3 by the 'prtype'. */
 
3067
extern "C" UNIV_INTERN
 
3068
ulint
 
3069
get_innobase_type_from_mysql_type(
 
3070
/*==============================*/
 
3071
                                        /* out: DATA_BINARY,
 
3072
                                        DATA_VARCHAR, ... */
 
3073
        ulint*          unsigned_flag,  /* out: DATA_UNSIGNED if an
 
3074
                                        'unsigned type';
 
3075
                                        at least ENUM and SET,
 
3076
                                        and unsigned integer
 
3077
                                        types are 'unsigned types' */
 
3078
        const void*     f)              /* in: MySQL Field */
 
3079
{
 
3080
        const class Field* field = reinterpret_cast<const class Field*>(f);
 
3081
 
 
3082
        /* The following asserts try to check that the MySQL type code fits in
 
3083
        8 bits: this is used in ibuf and also when DATA_NOT_NULL is ORed to
 
3084
        the type */
 
3085
 
 
3086
        DBUG_ASSERT((ulint)MYSQL_TYPE_STRING < 256);
 
3087
        DBUG_ASSERT((ulint)MYSQL_TYPE_VAR_STRING < 256);
 
3088
        DBUG_ASSERT((ulint)MYSQL_TYPE_DOUBLE < 256);
 
3089
        DBUG_ASSERT((ulint)MYSQL_TYPE_FLOAT < 256);
 
3090
        DBUG_ASSERT((ulint)MYSQL_TYPE_DECIMAL < 256);
 
3091
 
 
3092
        if (field->flags & UNSIGNED_FLAG) {
 
3093
 
 
3094
                *unsigned_flag = DATA_UNSIGNED;
 
3095
        } else {
 
3096
                *unsigned_flag = 0;
 
3097
        }
 
3098
 
 
3099
        if (field->real_type() == MYSQL_TYPE_ENUM
 
3100
                || field->real_type() == MYSQL_TYPE_SET) {
 
3101
 
 
3102
                /* MySQL has field->type() a string type for these, but the
 
3103
                data is actually internally stored as an unsigned integer
 
3104
                code! */
 
3105
 
 
3106
                *unsigned_flag = DATA_UNSIGNED; /* MySQL has its own unsigned
 
3107
                                                flag set to zero, even though
 
3108
                                                internally this is an unsigned
 
3109
                                                integer type */
 
3110
                return(DATA_INT);
 
3111
        }
 
3112
 
 
3113
        switch (field->type()) {
 
3114
                /* NOTE that we only allow string types in DATA_MYSQL and
 
3115
                DATA_VARMYSQL */
 
3116
        case MYSQL_TYPE_VAR_STRING: /* old <= 4.1 VARCHAR */
 
3117
        case MYSQL_TYPE_VARCHAR:    /* new >= 5.0.3 true VARCHAR */
 
3118
                if (field->binary()) {
 
3119
                        return(DATA_BINARY);
 
3120
                } else if (strcmp(
 
3121
                                   field->charset()->name,
 
3122
                                   "latin1_swedish_ci") == 0) {
 
3123
                        return(DATA_VARCHAR);
 
3124
                } else {
 
3125
                        return(DATA_VARMYSQL);
 
3126
                }
 
3127
        case MYSQL_TYPE_BIT:
 
3128
        case MYSQL_TYPE_STRING: if (field->binary()) {
 
3129
 
 
3130
                        return(DATA_FIXBINARY);
 
3131
                } else if (strcmp(
 
3132
                                   field->charset()->name,
 
3133
                                   "latin1_swedish_ci") == 0) {
 
3134
                        return(DATA_CHAR);
 
3135
                } else {
 
3136
                        return(DATA_MYSQL);
 
3137
                }
 
3138
        case MYSQL_TYPE_NEWDECIMAL:
 
3139
                return(DATA_FIXBINARY);
 
3140
        case MYSQL_TYPE_LONG:
 
3141
        case MYSQL_TYPE_LONGLONG:
 
3142
        case MYSQL_TYPE_TINY:
 
3143
        case MYSQL_TYPE_SHORT:
 
3144
        case MYSQL_TYPE_INT24:
 
3145
        case MYSQL_TYPE_DATE:
 
3146
        case MYSQL_TYPE_DATETIME:
 
3147
        case MYSQL_TYPE_YEAR:
 
3148
        case MYSQL_TYPE_NEWDATE:
 
3149
        case MYSQL_TYPE_TIME:
 
3150
        case MYSQL_TYPE_TIMESTAMP:
 
3151
                return(DATA_INT);
 
3152
        case MYSQL_TYPE_FLOAT:
 
3153
                return(DATA_FLOAT);
 
3154
        case MYSQL_TYPE_DOUBLE:
 
3155
                return(DATA_DOUBLE);
 
3156
        case MYSQL_TYPE_DECIMAL:
 
3157
                return(DATA_DECIMAL);
 
3158
        case MYSQL_TYPE_GEOMETRY:
 
3159
        case MYSQL_TYPE_TINY_BLOB:
 
3160
        case MYSQL_TYPE_MEDIUM_BLOB:
 
3161
        case MYSQL_TYPE_BLOB:
 
3162
        case MYSQL_TYPE_LONG_BLOB:
 
3163
                return(DATA_BLOB);
 
3164
        default:
 
3165
                ut_error;
 
3166
        }
 
3167
 
 
3168
        return(0);
 
3169
}
 
3170
 
 
3171
/***********************************************************************
 
3172
Writes an unsigned integer value < 64k to 2 bytes, in the little-endian
 
3173
storage format. */
 
3174
inline
 
3175
void
 
3176
innobase_write_to_2_little_endian(
 
3177
/*==============================*/
 
3178
        byte*   buf,    /* in: where to store */
 
3179
        ulint   val)    /* in: value to write, must be < 64k */
 
3180
{
 
3181
        ut_a(val < 256 * 256);
 
3182
 
 
3183
        buf[0] = (byte)(val & 0xFF);
 
3184
        buf[1] = (byte)(val / 256);
 
3185
}
 
3186
 
 
3187
/***********************************************************************
 
3188
Reads an unsigned integer value < 64k from 2 bytes, in the little-endian
 
3189
storage format. */
 
3190
inline
 
3191
uint
 
3192
innobase_read_from_2_little_endian(
 
3193
/*===============================*/
 
3194
                                /* out: value */
 
3195
        const uchar*    buf)    /* in: from where to read */
 
3196
{
 
3197
        return (uint) ((ulint)(buf[0]) + 256 * ((ulint)(buf[1])));
 
3198
}
 
3199
 
 
3200
/***********************************************************************
 
3201
Stores a key value for a row to a buffer. */
 
3202
UNIV_INTERN
 
3203
uint
 
3204
ha_innobase::store_key_val_for_row(
 
3205
/*===============================*/
 
3206
                                /* out: key value length as stored in buff */
 
3207
        uint            keynr,  /* in: key number */
 
3208
        char*           buff,   /* in/out: buffer for the key value (in MySQL
 
3209
                                format) */
 
3210
        uint            buff_len,/* in: buffer length */
 
3211
        const uchar*    record)/* in: row in MySQL format */
 
3212
{
 
3213
        KEY*            key_info        = table->key_info + keynr;
 
3214
        KEY_PART_INFO*  key_part        = key_info->key_part;
 
3215
        KEY_PART_INFO*  end             = key_part + key_info->key_parts;
 
3216
        char*           buff_start      = buff;
 
3217
        enum_field_types mysql_type;
 
3218
        Field*          field;
 
3219
        ibool           is_null;
 
3220
 
 
3221
        DBUG_ENTER("store_key_val_for_row");
 
3222
 
 
3223
        /* The format for storing a key field in MySQL is the following:
 
3224
 
 
3225
        1. If the column can be NULL, then in the first byte we put 1 if the
 
3226
        field value is NULL, 0 otherwise.
 
3227
 
 
3228
        2. If the column is of a BLOB type (it must be a column prefix field
 
3229
        in this case), then we put the length of the data in the field to the
 
3230
        next 2 bytes, in the little-endian format. If the field is SQL NULL,
 
3231
        then these 2 bytes are set to 0. Note that the length of data in the
 
3232
        field is <= column prefix length.
 
3233
 
 
3234
        3. In a column prefix field, prefix_len next bytes are reserved for
 
3235
        data. In a normal field the max field length next bytes are reserved
 
3236
        for data. For a VARCHAR(n) the max field length is n. If the stored
 
3237
        value is the SQL NULL then these data bytes are set to 0.
 
3238
 
 
3239
        4. We always use a 2 byte length for a true >= 5.0.3 VARCHAR. Note that
 
3240
        in the MySQL row format, the length is stored in 1 or 2 bytes,
 
3241
        depending on the maximum allowed length. But in the MySQL key value
 
3242
        format, the length always takes 2 bytes.
 
3243
 
 
3244
        We have to zero-fill the buffer so that MySQL is able to use a
 
3245
        simple memcmp to compare two key values to determine if they are
 
3246
        equal. MySQL does this to compare contents of two 'ref' values. */
 
3247
 
 
3248
        bzero(buff, buff_len);
 
3249
 
 
3250
        for (; key_part != end; key_part++) {
 
3251
                is_null = FALSE;
 
3252
 
 
3253
                if (key_part->null_bit) {
 
3254
                        if (record[key_part->null_offset]
 
3255
                                                & key_part->null_bit) {
 
3256
                                *buff = 1;
 
3257
                                is_null = TRUE;
 
3258
                        } else {
 
3259
                                *buff = 0;
 
3260
                        }
 
3261
                        buff++;
 
3262
                }
 
3263
 
 
3264
                field = key_part->field;
 
3265
                mysql_type = field->type();
 
3266
 
 
3267
                if (mysql_type == MYSQL_TYPE_VARCHAR) {
 
3268
                                                /* >= 5.0.3 true VARCHAR */
 
3269
                        ulint           lenlen;
 
3270
                        ulint           len;
 
3271
                        const byte*     data;
 
3272
                        ulint           key_len;
 
3273
                        ulint           true_len;
 
3274
                        CHARSET_INFO*   cs;
 
3275
                        int             error=0;
 
3276
 
 
3277
                        key_len = key_part->length;
 
3278
 
 
3279
                        if (is_null) {
 
3280
                                buff += key_len + 2;
 
3281
 
 
3282
                                continue;
 
3283
                        }
 
3284
                        cs = field->charset();
 
3285
 
 
3286
                        lenlen = (ulint)
 
3287
                                (((Field_varstring*)field)->length_bytes);
 
3288
 
 
3289
                        data = row_mysql_read_true_varchar(&len,
 
3290
                                (byte*) (record
 
3291
                                + (ulint)get_field_offset(table, field)),
 
3292
                                lenlen);
 
3293
 
 
3294
                        true_len = len;
 
3295
 
 
3296
                        /* For multi byte character sets we need to calculate
 
3297
                        the true length of the key */
 
3298
 
 
3299
                        if (len > 0 && cs->mbmaxlen > 1) {
 
3300
                                true_len = (ulint) cs->cset->well_formed_len(cs,
 
3301
                                                (const char *) data,
 
3302
                                                (const char *) data + len,
 
3303
                                                (uint) (key_len /
 
3304
                                                        cs->mbmaxlen),
 
3305
                                                &error);
 
3306
                        }
 
3307
 
 
3308
                        /* In a column prefix index, we may need to truncate
 
3309
                        the stored value: */
 
3310
 
 
3311
                        if (true_len > key_len) {
 
3312
                                true_len = key_len;
 
3313
                        }
 
3314
 
 
3315
                        /* The length in a key value is always stored in 2
 
3316
                        bytes */
 
3317
 
 
3318
                        row_mysql_store_true_var_len((byte*)buff, true_len, 2);
 
3319
                        buff += 2;
 
3320
 
 
3321
                        memcpy(buff, data, true_len);
 
3322
 
 
3323
                        /* Note that we always reserve the maximum possible
 
3324
                        length of the true VARCHAR in the key value, though
 
3325
                        only len first bytes after the 2 length bytes contain
 
3326
                        actual data. The rest of the space was reset to zero
 
3327
                        in the bzero() call above. */
 
3328
 
 
3329
                        buff += key_len;
 
3330
 
 
3331
                } else if (mysql_type == MYSQL_TYPE_TINY_BLOB
 
3332
                        || mysql_type == MYSQL_TYPE_MEDIUM_BLOB
 
3333
                        || mysql_type == MYSQL_TYPE_BLOB
 
3334
                        || mysql_type == MYSQL_TYPE_LONG_BLOB) {
 
3335
 
 
3336
                        CHARSET_INFO*   cs;
 
3337
                        ulint           key_len;
 
3338
                        ulint           true_len;
 
3339
                        int             error=0;
 
3340
                        ulint           blob_len;
 
3341
                        const byte*     blob_data;
 
3342
 
 
3343
                        ut_a(key_part->key_part_flag & HA_PART_KEY_SEG);
 
3344
 
 
3345
                        key_len = key_part->length;
 
3346
 
 
3347
                        if (is_null) {
 
3348
                                buff += key_len + 2;
 
3349
 
 
3350
                                continue;
 
3351
                        }
 
3352
 
 
3353
                        cs = field->charset();
 
3354
 
 
3355
                        blob_data = row_mysql_read_blob_ref(&blob_len,
 
3356
                                (byte*) (record
 
3357
                                + (ulint)get_field_offset(table, field)),
 
3358
                                        (ulint) field->pack_length());
 
3359
 
 
3360
                        true_len = blob_len;
 
3361
 
 
3362
                        ut_a(get_field_offset(table, field)
 
3363
                                == key_part->offset);
 
3364
 
 
3365
                        /* For multi byte character sets we need to calculate
 
3366
                        the true length of the key */
 
3367
 
 
3368
                        if (blob_len > 0 && cs->mbmaxlen > 1) {
 
3369
                                true_len = (ulint) cs->cset->well_formed_len(cs,
 
3370
                                                (const char *) blob_data,
 
3371
                                                (const char *) blob_data
 
3372
                                                        + blob_len,
 
3373
                                                (uint) (key_len /
 
3374
                                                        cs->mbmaxlen),
 
3375
                                                &error);
 
3376
                        }
 
3377
 
 
3378
                        /* All indexes on BLOB and TEXT are column prefix
 
3379
                        indexes, and we may need to truncate the data to be
 
3380
                        stored in the key value: */
 
3381
 
 
3382
                        if (true_len > key_len) {
 
3383
                                true_len = key_len;
 
3384
                        }
 
3385
 
 
3386
                        /* MySQL reserves 2 bytes for the length and the
 
3387
                        storage of the number is little-endian */
 
3388
 
 
3389
                        innobase_write_to_2_little_endian(
 
3390
                                        (byte*)buff, true_len);
 
3391
                        buff += 2;
 
3392
 
 
3393
                        memcpy(buff, blob_data, true_len);
 
3394
 
 
3395
                        /* Note that we always reserve the maximum possible
 
3396
                        length of the BLOB prefix in the key value. */
 
3397
 
 
3398
                        buff += key_len;
 
3399
                } else {
 
3400
                        /* Here we handle all other data types except the
 
3401
                        true VARCHAR, BLOB and TEXT. Note that the column
 
3402
                        value we store may be also in a column prefix
 
3403
                        index. */
 
3404
 
 
3405
                        CHARSET_INFO*           cs;
 
3406
                        ulint                   true_len;
 
3407
                        ulint                   key_len;
 
3408
                        const uchar*            src_start;
 
3409
                        int                     error=0;
 
3410
                        enum_field_types        real_type;
 
3411
 
 
3412
                        key_len = key_part->length;
 
3413
 
 
3414
                        if (is_null) {
 
3415
                                 buff += key_len;
 
3416
 
 
3417
                                 continue;
 
3418
                        }
 
3419
 
 
3420
                        src_start = record + key_part->offset;
 
3421
                        real_type = field->real_type();
 
3422
                        true_len = key_len;
 
3423
 
 
3424
                        /* Character set for the field is defined only
 
3425
                        to fields whose type is string and real field
 
3426
                        type is not enum or set. For these fields check
 
3427
                        if character set is multi byte. */
 
3428
 
 
3429
                        if (real_type != MYSQL_TYPE_ENUM
 
3430
                                && real_type != MYSQL_TYPE_SET
 
3431
                                && ( mysql_type == MYSQL_TYPE_VAR_STRING
 
3432
                                        || mysql_type == MYSQL_TYPE_STRING)) {
 
3433
 
 
3434
                                cs = field->charset();
 
3435
 
 
3436
                                /* For multi byte character sets we need to
 
3437
                                calculate the true length of the key */
 
3438
 
 
3439
                                if (key_len > 0 && cs->mbmaxlen > 1) {
 
3440
 
 
3441
                                        true_len = (ulint)
 
3442
                                                cs->cset->well_formed_len(cs,
 
3443
                                                        (const char *)src_start,
 
3444
                                                        (const char *)src_start
 
3445
                                                                + key_len,
 
3446
                                                        (uint) (key_len /
 
3447
                                                                cs->mbmaxlen),
 
3448
                                                        &error);
 
3449
                                }
 
3450
                        }
 
3451
 
 
3452
                        memcpy(buff, src_start, true_len);
 
3453
                        buff += true_len;
 
3454
 
 
3455
                        /* Pad the unused space with spaces. Note that no
 
3456
                        padding is ever needed for UCS-2 because in MySQL,
 
3457
                        all UCS2 characters are 2 bytes, as MySQL does not
 
3458
                        support surrogate pairs, which are needed to represent
 
3459
                        characters in the range U+10000 to U+10FFFF. */
 
3460
 
 
3461
                        if (true_len < key_len) {
 
3462
                                ulint pad_len = key_len - true_len;
 
3463
                                memset(buff, ' ', pad_len);
 
3464
                                buff += pad_len;
 
3465
                        }
 
3466
                }
 
3467
        }
 
3468
 
 
3469
        ut_a(buff <= buff_start + buff_len);
 
3470
 
 
3471
        DBUG_RETURN((uint)(buff - buff_start));
 
3472
}
 
3473
 
 
3474
/******************************************************************
 
3475
Builds a 'template' to the prebuilt struct. The template is used in fast
 
3476
retrieval of just those column values MySQL needs in its processing. */
 
3477
static
 
3478
void
 
3479
build_template(
 
3480
/*===========*/
 
3481
        row_prebuilt_t* prebuilt,       /* in/out: prebuilt struct */
 
3482
        THD*            thd,            /* in: current user thread, used
 
3483
                                        only if templ_type is
 
3484
                                        ROW_MYSQL_REC_FIELDS */
 
3485
        TABLE*          table,          /* in: MySQL table */
 
3486
        uint            templ_type)     /* in: ROW_MYSQL_WHOLE_ROW or
 
3487
                                        ROW_MYSQL_REC_FIELDS */
 
3488
{
 
3489
        dict_index_t*   index;
 
3490
        dict_index_t*   clust_index;
 
3491
        mysql_row_templ_t* templ;
 
3492
        Field*          field;
 
3493
        ulint           n_fields;
 
3494
        ulint           n_requested_fields      = 0;
 
3495
        ibool           fetch_all_in_key        = FALSE;
 
3496
        ibool           fetch_primary_key_cols  = FALSE;
 
3497
        ulint           i;
 
3498
        /* byte offset of the end of last requested column */
 
3499
        ulint           mysql_prefix_len        = 0;
 
3500
 
 
3501
        if (prebuilt->select_lock_type == LOCK_X) {
 
3502
                /* We always retrieve the whole clustered index record if we
 
3503
                use exclusive row level locks, for example, if the read is
 
3504
                done in an UPDATE statement. */
 
3505
 
 
3506
                templ_type = ROW_MYSQL_WHOLE_ROW;
 
3507
        }
 
3508
 
 
3509
        if (templ_type == ROW_MYSQL_REC_FIELDS) {
 
3510
                if (prebuilt->hint_need_to_fetch_extra_cols
 
3511
                        == ROW_RETRIEVE_ALL_COLS) {
 
3512
 
 
3513
                        /* We know we must at least fetch all columns in the
 
3514
                        key, or all columns in the table */
 
3515
 
 
3516
                        if (prebuilt->read_just_key) {
 
3517
                                /* MySQL has instructed us that it is enough
 
3518
                                to fetch the columns in the key; looks like
 
3519
                                MySQL can set this flag also when there is
 
3520
                                only a prefix of the column in the key: in
 
3521
                                that case we retrieve the whole column from
 
3522
                                the clustered index */
 
3523
 
 
3524
                                fetch_all_in_key = TRUE;
 
3525
                        } else {
 
3526
                                templ_type = ROW_MYSQL_WHOLE_ROW;
 
3527
                        }
 
3528
                } else if (prebuilt->hint_need_to_fetch_extra_cols
 
3529
                        == ROW_RETRIEVE_PRIMARY_KEY) {
 
3530
                        /* We must at least fetch all primary key cols. Note
 
3531
                           that if the clustered index was internally generated
 
3532
                           by InnoDB on the row id (no primary key was
 
3533
                           defined), then row_search_for_mysql() will always
 
3534
                           retrieve the row id to a special buffer in the
 
3535
                           prebuilt struct. */
 
3536
 
 
3537
                        fetch_primary_key_cols = TRUE;
 
3538
                }
 
3539
        }
 
3540
 
 
3541
        clust_index = dict_table_get_first_index(prebuilt->table);
 
3542
 
 
3543
        if (templ_type == ROW_MYSQL_REC_FIELDS) {
 
3544
                index = prebuilt->index;
 
3545
        } else {
 
3546
                index = clust_index;
 
3547
        }
 
3548
 
 
3549
        if (index == clust_index) {
 
3550
                prebuilt->need_to_access_clustered = TRUE;
 
3551
        } else {
 
3552
                prebuilt->need_to_access_clustered = FALSE;
 
3553
                /* Below we check column by column if we need to access
 
3554
                the clustered index */
 
3555
        }
 
3556
 
 
3557
        n_fields = (ulint)table->s->fields; /* number of columns */
 
3558
 
 
3559
        if (!prebuilt->mysql_template) {
 
3560
                prebuilt->mysql_template = (mysql_row_templ_t*)
 
3561
                        mem_alloc(n_fields * sizeof(mysql_row_templ_t));
 
3562
        }
 
3563
 
 
3564
        prebuilt->template_type = templ_type;
 
3565
        prebuilt->null_bitmap_len = table->s->null_bytes;
 
3566
 
 
3567
        prebuilt->templ_contains_blob = FALSE;
 
3568
 
 
3569
        /* Note that in InnoDB, i is the column number. MySQL calls columns
 
3570
        'fields'. */
 
3571
        for (i = 0; i < n_fields; i++) {
 
3572
                templ = prebuilt->mysql_template + n_requested_fields;
 
3573
                field = table->field[i];
 
3574
 
 
3575
                if (UNIV_LIKELY(templ_type == ROW_MYSQL_REC_FIELDS)) {
 
3576
                        /* Decide which columns we should fetch
 
3577
                        and which we can skip. */
 
3578
                        register const ibool    index_contains_field =
 
3579
                                dict_index_contains_col_or_prefix(index, i);
 
3580
 
 
3581
                        if (!index_contains_field && prebuilt->read_just_key) {
 
3582
                                /* If this is a 'key read', we do not need
 
3583
                                columns that are not in the key */
 
3584
 
 
3585
                                goto skip_field;
 
3586
                        }
 
3587
 
 
3588
                        if (index_contains_field && fetch_all_in_key) {
 
3589
                                /* This field is needed in the query */
 
3590
 
 
3591
                                goto include_field;
 
3592
                        }
 
3593
 
 
3594
                        if (bitmap_is_set(table->read_set, i) ||
 
3595
                            bitmap_is_set(table->write_set, i)) {
 
3596
                                /* This field is needed in the query */
 
3597
 
 
3598
                                goto include_field;
 
3599
                        }
 
3600
 
 
3601
                        if (fetch_primary_key_cols
 
3602
                                && dict_table_col_in_clustered_key(
 
3603
                                        index->table, i)) {
 
3604
                                /* This field is needed in the query */
 
3605
 
 
3606
                                goto include_field;
 
3607
                        }
 
3608
 
 
3609
                        /* This field is not needed in the query, skip it */
 
3610
 
 
3611
                        goto skip_field;
 
3612
                }
 
3613
include_field:
 
3614
                n_requested_fields++;
 
3615
 
 
3616
                templ->col_no = i;
 
3617
 
 
3618
                if (index == clust_index) {
 
3619
                        templ->rec_field_no = dict_col_get_clust_pos(
 
3620
                                &index->table->cols[i], index);
 
3621
                } else {
 
3622
                        templ->rec_field_no = dict_index_get_nth_col_pos(
 
3623
                                                                index, i);
 
3624
                }
 
3625
 
 
3626
                if (templ->rec_field_no == ULINT_UNDEFINED) {
 
3627
                        prebuilt->need_to_access_clustered = TRUE;
 
3628
                }
 
3629
 
 
3630
                if (field->null_ptr) {
 
3631
                        templ->mysql_null_byte_offset =
 
3632
                                (ulint) ((char*) field->null_ptr
 
3633
                                        - (char*) table->record[0]);
 
3634
 
 
3635
                        templ->mysql_null_bit_mask = (ulint) field->null_bit;
 
3636
                } else {
 
3637
                        templ->mysql_null_bit_mask = 0;
 
3638
                }
 
3639
 
 
3640
                templ->mysql_col_offset = (ulint)
 
3641
                                        get_field_offset(table, field);
 
3642
 
 
3643
                templ->mysql_col_len = (ulint) field->pack_length();
 
3644
                if (mysql_prefix_len < templ->mysql_col_offset
 
3645
                                + templ->mysql_col_len) {
 
3646
                        mysql_prefix_len = templ->mysql_col_offset
 
3647
                                + templ->mysql_col_len;
 
3648
                }
 
3649
                templ->type = index->table->cols[i].mtype;
 
3650
                templ->mysql_type = (ulint)field->type();
 
3651
 
 
3652
                if (templ->mysql_type == DATA_MYSQL_TRUE_VARCHAR) {
 
3653
                        templ->mysql_length_bytes = (ulint)
 
3654
                                (((Field_varstring*)field)->length_bytes);
 
3655
                }
 
3656
 
 
3657
                templ->charset = dtype_get_charset_coll(
 
3658
                        index->table->cols[i].prtype);
 
3659
                templ->mbminlen = index->table->cols[i].mbminlen;
 
3660
                templ->mbmaxlen = index->table->cols[i].mbmaxlen;
 
3661
                templ->is_unsigned = index->table->cols[i].prtype
 
3662
                                                        & DATA_UNSIGNED;
 
3663
                if (templ->type == DATA_BLOB) {
 
3664
                        prebuilt->templ_contains_blob = TRUE;
 
3665
                }
 
3666
skip_field:
 
3667
                ;
 
3668
        }
 
3669
 
 
3670
        prebuilt->n_template = n_requested_fields;
 
3671
        prebuilt->mysql_prefix_len = mysql_prefix_len;
 
3672
 
 
3673
        if (index != clust_index && prebuilt->need_to_access_clustered) {
 
3674
                /* Change rec_field_no's to correspond to the clustered index
 
3675
                record */
 
3676
                for (i = 0; i < n_requested_fields; i++) {
 
3677
                        templ = prebuilt->mysql_template + i;
 
3678
 
 
3679
                        templ->rec_field_no = dict_col_get_clust_pos(
 
3680
                                &index->table->cols[templ->col_no],
 
3681
                                clust_index);
 
3682
                }
 
3683
        }
 
3684
}
 
3685
 
 
3686
/************************************************************************
 
3687
This special handling is really to overcome the limitations of MySQL's
 
3688
binlogging. We need to eliminate the non-determinism that will arise in
 
3689
INSERT ... SELECT type of statements, since MySQL binlog only stores the
 
3690
min value of the autoinc interval. Once that is fixed we can get rid of
 
3691
the special lock handling.*/
 
3692
UNIV_INTERN
 
3693
ulong
 
3694
ha_innobase::innobase_autoinc_lock(void)
 
3695
/*====================================*/
 
3696
                                        /* out: DB_SUCCESS if all OK else
 
3697
                                        error code */
 
3698
{
 
3699
        ulint           error = DB_SUCCESS;
 
3700
 
 
3701
        switch (innobase_autoinc_lock_mode) {
 
3702
        case AUTOINC_NO_LOCKING:
 
3703
                /* Acquire only the AUTOINC mutex. */
 
3704
                dict_table_autoinc_lock(prebuilt->table);
 
3705
                break;
 
3706
 
 
3707
        case AUTOINC_NEW_STYLE_LOCKING:
 
3708
                /* For simple (single/multi) row INSERTs, we fallback to the
 
3709
                old style only if another transaction has already acquired
 
3710
                the AUTOINC lock on behalf of a LOAD FILE or INSERT ... SELECT
 
3711
                etc. type of statement. */
 
3712
                if (thd_sql_command(user_thd) == SQLCOM_INSERT) {
 
3713
                        dict_table_t*   table = prebuilt->table;
 
3714
 
 
3715
                        /* Acquire the AUTOINC mutex. */
 
3716
                        dict_table_autoinc_lock(table);
 
3717
 
 
3718
                        /* We need to check that another transaction isn't
 
3719
                        already holding the AUTOINC lock on the table. */
 
3720
                        if (table->n_waiting_or_granted_auto_inc_locks) {
 
3721
                                /* Release the mutex to avoid deadlocks. */
 
3722
                                dict_table_autoinc_unlock(table);
 
3723
                        } else {
 
3724
                                break;
 
3725
                        }
 
3726
                }
 
3727
                /* Fall through to old style locking. */
 
3728
 
 
3729
        case AUTOINC_OLD_STYLE_LOCKING:
 
3730
                error = row_lock_table_autoinc_for_mysql(prebuilt);
 
3731
 
 
3732
                if (error == DB_SUCCESS) {
 
3733
 
 
3734
                        /* Acquire the AUTOINC mutex. */
 
3735
                        dict_table_autoinc_lock(prebuilt->table);
 
3736
                }
 
3737
                break;
 
3738
 
 
3739
        default:
 
3740
                ut_error;
 
3741
        }
 
3742
 
 
3743
        return(ulong(error));
 
3744
}
 
3745
 
 
3746
/************************************************************************
 
3747
Reset the autoinc value in the table.*/
 
3748
UNIV_INTERN
 
3749
ulong
 
3750
ha_innobase::innobase_reset_autoinc(
 
3751
/*================================*/
 
3752
                                        /* out: DB_SUCCESS if all went well
 
3753
                                        else error code */
 
3754
        ulonglong       autoinc)        /* in: value to store */
 
3755
{
 
3756
        ulint           error;
 
3757
 
 
3758
        error = innobase_autoinc_lock();
 
3759
 
 
3760
        if (error == DB_SUCCESS) {
 
3761
 
 
3762
                dict_table_autoinc_initialize(prebuilt->table, autoinc);
 
3763
 
 
3764
                dict_table_autoinc_unlock(prebuilt->table);
 
3765
        }
 
3766
 
 
3767
        return(ulong(error));
 
3768
}
 
3769
 
 
3770
/************************************************************************
 
3771
Store the autoinc value in the table. The autoinc value is only set if
 
3772
it's greater than the existing autoinc value in the table.*/
 
3773
UNIV_INTERN
 
3774
ulong
 
3775
ha_innobase::innobase_set_max_autoinc(
 
3776
/*==================================*/
 
3777
                                        /* out: DB_SUCCES if all went well
 
3778
                                        else error code */
 
3779
        ulonglong       auto_inc)       /* in: value to store */
 
3780
{
 
3781
        ulint           error;
 
3782
 
 
3783
        error = innobase_autoinc_lock();
 
3784
 
 
3785
        if (error == DB_SUCCESS) {
 
3786
 
 
3787
                dict_table_autoinc_update(prebuilt->table, auto_inc);
 
3788
 
 
3789
                dict_table_autoinc_unlock(prebuilt->table);
 
3790
        }
 
3791
 
 
3792
        return(ulong(error));
 
3793
}
 
3794
 
 
3795
/************************************************************************
 
3796
Stores a row in an InnoDB database, to the table specified in this
 
3797
handle. */
 
3798
UNIV_INTERN
 
3799
int
 
3800
ha_innobase::write_row(
 
3801
/*===================*/
 
3802
                        /* out: error code */
 
3803
        uchar*  record) /* in: a row in MySQL format */
 
3804
{
 
3805
        int             error = 0;
 
3806
        ibool           auto_inc_used= FALSE;
 
3807
        ulint           sql_command;
 
3808
        trx_t*          trx = thd_to_trx(user_thd);
 
3809
 
 
3810
        DBUG_ENTER("ha_innobase::write_row");
 
3811
 
 
3812
        if (prebuilt->trx != trx) {
 
3813
          sql_print_error("The transaction object for the table handle is at "
 
3814
                          "%p, but for the current thread it is at %p",
 
3815
                          (const void*) prebuilt->trx, (const void*) trx);
 
3816
 
 
3817
                fputs("InnoDB: Dump of 200 bytes around prebuilt: ", stderr);
 
3818
                ut_print_buf(stderr, ((const byte*)prebuilt) - 100, 200);
 
3819
                fputs("\n"
 
3820
                        "InnoDB: Dump of 200 bytes around ha_data: ",
 
3821
                        stderr);
 
3822
                ut_print_buf(stderr, ((const byte*) trx) - 100, 200);
 
3823
                putc('\n', stderr);
 
3824
                ut_error;
 
3825
        }
 
3826
 
 
3827
        ha_statistic_increment(&SSV::ha_write_count);
 
3828
 
 
3829
        if (table->timestamp_field_type & TIMESTAMP_AUTO_SET_ON_INSERT)
 
3830
                table->timestamp_field->set_time();
 
3831
 
 
3832
        sql_command = thd_sql_command(user_thd);
 
3833
 
 
3834
        if ((sql_command == SQLCOM_ALTER_TABLE
 
3835
             || sql_command == SQLCOM_OPTIMIZE
 
3836
             || sql_command == SQLCOM_CREATE_INDEX
 
3837
             || sql_command == SQLCOM_DROP_INDEX)
 
3838
            && num_write_row >= 10000) {
 
3839
                /* ALTER TABLE is COMMITted at every 10000 copied rows.
 
3840
                The IX table lock for the original table has to be re-issued.
 
3841
                As this method will be called on a temporary table where the
 
3842
                contents of the original table is being copied to, it is
 
3843
                a bit tricky to determine the source table.  The cursor
 
3844
                position in the source table need not be adjusted after the
 
3845
                intermediate COMMIT, since writes by other transactions are
 
3846
                being blocked by a MySQL table lock TL_WRITE_ALLOW_READ. */
 
3847
 
 
3848
                dict_table_t*   src_table;
 
3849
                enum lock_mode  mode;
 
3850
 
 
3851
                num_write_row = 0;
 
3852
 
 
3853
                /* Commit the transaction.  This will release the table
 
3854
                locks, so they have to be acquired again. */
 
3855
 
 
3856
                /* Altering an InnoDB table */
 
3857
                /* Get the source table. */
 
3858
                src_table = lock_get_src_table(
 
3859
                                prebuilt->trx, prebuilt->table, &mode);
 
3860
                if (!src_table) {
 
3861
no_commit:
 
3862
                        /* Unknown situation: do not commit */
 
3863
                        /*
 
3864
                        ut_print_timestamp(stderr);
 
3865
                        fprintf(stderr,
 
3866
                                "  InnoDB: ALTER TABLE is holding lock"
 
3867
                                " on %lu tables!\n",
 
3868
                                prebuilt->trx->mysql_n_tables_locked);
 
3869
                        */
 
3870
                        ;
 
3871
                } else if (src_table == prebuilt->table) {
 
3872
                        /* Source table is not in InnoDB format:
 
3873
                        no need to re-acquire locks on it. */
 
3874
 
 
3875
                        /* Altering to InnoDB format */
 
3876
                        innobase_commit(ht, user_thd, 1);
 
3877
                        /* Note that this transaction is still active. */
 
3878
                        prebuilt->trx->active_trans = 1;
 
3879
                        /* We will need an IX lock on the destination table. */
 
3880
                        prebuilt->sql_stat_start = TRUE;
 
3881
                } else {
 
3882
                        /* Ensure that there are no other table locks than
 
3883
                        LOCK_IX and LOCK_AUTO_INC on the destination table. */
 
3884
 
 
3885
                        if (!lock_is_table_exclusive(prebuilt->table,
 
3886
                                                        prebuilt->trx)) {
 
3887
                                goto no_commit;
 
3888
                        }
 
3889
 
 
3890
                        /* Commit the transaction.  This will release the table
 
3891
                        locks, so they have to be acquired again. */
 
3892
                        innobase_commit(ht, user_thd, 1);
 
3893
                        /* Note that this transaction is still active. */
 
3894
                        prebuilt->trx->active_trans = 1;
 
3895
                        /* Re-acquire the table lock on the source table. */
 
3896
                        row_lock_table_for_mysql(prebuilt, src_table, mode);
 
3897
                        /* We will need an IX lock on the destination table. */
 
3898
                        prebuilt->sql_stat_start = TRUE;
 
3899
                }
 
3900
        }
 
3901
 
 
3902
        num_write_row++;
 
3903
 
 
3904
        /* This is the case where the table has an auto-increment column */
 
3905
        if (table->next_number_field && record == table->record[0]) {
 
3906
 
 
3907
                if ((error = update_auto_increment())) {
 
3908
 
 
3909
                        goto func_exit;
 
3910
                }
 
3911
 
 
3912
                auto_inc_used = TRUE;
 
3913
        }
 
3914
 
 
3915
        if (prebuilt->mysql_template == NULL
 
3916
            || prebuilt->template_type != ROW_MYSQL_WHOLE_ROW) {
 
3917
 
 
3918
                /* Build the template used in converting quickly between
 
3919
                the two database formats */
 
3920
 
 
3921
                build_template(prebuilt, NULL, table, ROW_MYSQL_WHOLE_ROW);
 
3922
        }
 
3923
 
 
3924
        innodb_srv_conc_enter_innodb(prebuilt->trx);
 
3925
 
 
3926
        error = row_insert_for_mysql((byte*) record, prebuilt);
 
3927
 
 
3928
        /* Handle duplicate key errors */
 
3929
        if (auto_inc_used) {
 
3930
                ulint           err;
 
3931
                ulonglong       auto_inc;
 
3932
 
 
3933
                /* Note the number of rows processed for this statement, used
 
3934
                by get_auto_increment() to determine the number of AUTO-INC
 
3935
                values to reserve. This is only useful for a mult-value INSERT
 
3936
                and is a statement level counter.*/
 
3937
                if (trx->n_autoinc_rows > 0) {
 
3938
                        --trx->n_autoinc_rows;
 
3939
                }
 
3940
 
 
3941
                /* Get the value that MySQL attempted to store in the table.*/
 
3942
                auto_inc = table->next_number_field->val_int();
 
3943
 
 
3944
                switch (error) {
 
3945
                case DB_DUPLICATE_KEY:
 
3946
 
 
3947
                        /* A REPLACE command and LOAD DATA INFILE REPLACE
 
3948
                        handle a duplicate key error themselves, but we
 
3949
                        must update the autoinc counter if we are performing
 
3950
                        those statements. */
 
3951
 
 
3952
                        switch (sql_command) {
 
3953
                        case SQLCOM_LOAD:
 
3954
                                if ((trx->duplicates
 
3955
                                    & (TRX_DUP_IGNORE | TRX_DUP_REPLACE))) {
 
3956
 
 
3957
                                        goto set_max_autoinc;
 
3958
                                }
 
3959
                                break;
 
3960
 
 
3961
                        case SQLCOM_REPLACE:
 
3962
                        case SQLCOM_INSERT_SELECT:
 
3963
                        case SQLCOM_REPLACE_SELECT:
 
3964
                                goto set_max_autoinc;
 
3965
 
 
3966
                        default:
 
3967
                                break;
 
3968
                        }
 
3969
 
 
3970
                        break;
 
3971
 
 
3972
                case DB_SUCCESS:
 
3973
                        /* If the actual value inserted is greater than
 
3974
                        the upper limit of the interval, then we try and
 
3975
                        update the table upper limit. Note: last_value
 
3976
                        will be 0 if get_auto_increment() was not called.*/
 
3977
 
 
3978
                        if (auto_inc > prebuilt->last_value) {
 
3979
set_max_autoinc:
 
3980
                                ut_a(prebuilt->table->autoinc_increment > 0);
 
3981
 
 
3982
                                ulonglong       have;
 
3983
                                ulonglong       need;
 
3984
 
 
3985
                                /* Check for overflow conditions. */
 
3986
                                need = prebuilt->table->autoinc_increment;
 
3987
                                have = ~0x0ULL - auto_inc;
 
3988
 
 
3989
                                if (have < need) {
 
3990
                                        need = have;
 
3991
                                }
 
3992
 
 
3993
                                auto_inc += need;
 
3994
 
 
3995
                                err = innobase_set_max_autoinc(auto_inc);
 
3996
 
 
3997
                                if (err != DB_SUCCESS) {
 
3998
                                        error = (int) err;
 
3999
                                }
 
4000
                        }
 
4001
                        break;
 
4002
                }
 
4003
        }
 
4004
 
 
4005
        innodb_srv_conc_exit_innodb(prebuilt->trx);
 
4006
 
 
4007
        error = convert_error_code_to_mysql(error, prebuilt->table->flags,
 
4008
                                            user_thd);
 
4009
 
 
4010
func_exit:
 
4011
        innobase_active_small();
 
4012
 
 
4013
        DBUG_RETURN(error);
 
4014
}
 
4015
 
 
4016
/**************************************************************************
 
4017
Checks which fields have changed in a row and stores information
 
4018
of them to an update vector. */
 
4019
static
 
4020
int
 
4021
calc_row_difference(
 
4022
/*================*/
 
4023
                                        /* out: error number or 0 */
 
4024
        upd_t*          uvect,          /* in/out: update vector */
 
4025
        uchar*          old_row,        /* in: old row in MySQL format */
 
4026
        uchar*          new_row,        /* in: new row in MySQL format */
 
4027
        struct st_table* table,         /* in: table in MySQL data
 
4028
                                        dictionary */
 
4029
        uchar*          upd_buff,       /* in: buffer to use */
 
4030
        ulint           buff_len,       /* in: buffer length */
 
4031
        row_prebuilt_t* prebuilt,       /* in: InnoDB prebuilt struct */
 
4032
        THD*            thd)            /* in: user thread */
 
4033
{
 
4034
        uchar*          original_upd_buff = upd_buff;
 
4035
        Field*          field;
 
4036
        enum_field_types field_mysql_type;
 
4037
        uint            n_fields;
 
4038
        ulint           o_len;
 
4039
        ulint           n_len;
 
4040
        ulint           col_pack_len;
 
4041
        const byte*     new_mysql_row_col;
 
4042
        const byte*     o_ptr;
 
4043
        const byte*     n_ptr;
 
4044
        byte*           buf;
 
4045
        upd_field_t*    ufield;
 
4046
        ulint           col_type;
 
4047
        ulint           n_changed = 0;
 
4048
        dfield_t        dfield;
 
4049
        dict_index_t*   clust_index;
 
4050
        uint            i;
 
4051
 
 
4052
        n_fields = table->s->fields;
 
4053
        clust_index = dict_table_get_first_index(prebuilt->table);
 
4054
 
 
4055
        /* We use upd_buff to convert changed fields */
 
4056
        buf = (byte*) upd_buff;
 
4057
 
 
4058
        for (i = 0; i < n_fields; i++) {
 
4059
                field = table->field[i];
 
4060
 
 
4061
                o_ptr = (const byte*) old_row + get_field_offset(table, field);
 
4062
                n_ptr = (const byte*) new_row + get_field_offset(table, field);
 
4063
 
 
4064
                /* Use new_mysql_row_col and col_pack_len save the values */
 
4065
 
 
4066
                new_mysql_row_col = n_ptr;
 
4067
                col_pack_len = field->pack_length();
 
4068
 
 
4069
                o_len = col_pack_len;
 
4070
                n_len = col_pack_len;
 
4071
 
 
4072
                /* We use o_ptr and n_ptr to dig up the actual data for
 
4073
                comparison. */
 
4074
 
 
4075
                field_mysql_type = field->type();
 
4076
 
 
4077
                col_type = prebuilt->table->cols[i].mtype;
 
4078
 
 
4079
                switch (col_type) {
 
4080
 
 
4081
                case DATA_BLOB:
 
4082
                        o_ptr = row_mysql_read_blob_ref(&o_len, o_ptr, o_len);
 
4083
                        n_ptr = row_mysql_read_blob_ref(&n_len, n_ptr, n_len);
 
4084
 
 
4085
                        break;
 
4086
 
 
4087
                case DATA_VARCHAR:
 
4088
                case DATA_BINARY:
 
4089
                case DATA_VARMYSQL:
 
4090
                        if (field_mysql_type == MYSQL_TYPE_VARCHAR) {
 
4091
                                /* This is a >= 5.0.3 type true VARCHAR where
 
4092
                                the real payload data length is stored in
 
4093
                                1 or 2 bytes */
 
4094
 
 
4095
                                o_ptr = row_mysql_read_true_varchar(
 
4096
                                        &o_len, o_ptr,
 
4097
                                        (ulint)
 
4098
                                        (((Field_varstring*)field)->length_bytes));
 
4099
 
 
4100
                                n_ptr = row_mysql_read_true_varchar(
 
4101
                                        &n_len, n_ptr,
 
4102
                                        (ulint)
 
4103
                                        (((Field_varstring*)field)->length_bytes));
 
4104
                        }
 
4105
 
 
4106
                        break;
 
4107
                default:
 
4108
                        ;
 
4109
                }
 
4110
 
 
4111
                if (field->null_ptr) {
 
4112
                        if (field_in_record_is_null(table, field,
 
4113
                                                        (char*) old_row)) {
 
4114
                                o_len = UNIV_SQL_NULL;
 
4115
                        }
 
4116
 
 
4117
                        if (field_in_record_is_null(table, field,
 
4118
                                                        (char*) new_row)) {
 
4119
                                n_len = UNIV_SQL_NULL;
 
4120
                        }
 
4121
                }
 
4122
 
 
4123
                if (o_len != n_len || (o_len != UNIV_SQL_NULL &&
 
4124
                                        0 != memcmp(o_ptr, n_ptr, o_len))) {
 
4125
                        /* The field has changed */
 
4126
 
 
4127
                        ufield = uvect->fields + n_changed;
 
4128
 
 
4129
                        /* Let us use a dummy dfield to make the conversion
 
4130
                        from the MySQL column format to the InnoDB format */
 
4131
 
 
4132
                        dict_col_copy_type(prebuilt->table->cols + i,
 
4133
                                           dfield_get_type(&dfield));
 
4134
 
 
4135
                        if (n_len != UNIV_SQL_NULL) {
 
4136
                                buf = row_mysql_store_col_in_innobase_format(
 
4137
                                        &dfield,
 
4138
                                        (byte*)buf,
 
4139
                                        TRUE,
 
4140
                                        new_mysql_row_col,
 
4141
                                        col_pack_len,
 
4142
                                        dict_table_is_comp(prebuilt->table));
 
4143
                                dfield_copy_data(&ufield->new_val, &dfield);
 
4144
                        } else {
 
4145
                                dfield_set_null(&ufield->new_val);
 
4146
                        }
 
4147
 
 
4148
                        ufield->exp = NULL;
 
4149
                        ufield->orig_len = 0;
 
4150
                        ufield->field_no = dict_col_get_clust_pos(
 
4151
                                &prebuilt->table->cols[i], clust_index);
 
4152
                        n_changed++;
 
4153
                }
 
4154
        }
 
4155
 
 
4156
        uvect->n_fields = n_changed;
 
4157
        uvect->info_bits = 0;
 
4158
 
 
4159
        ut_a(buf <= (byte*)original_upd_buff + buff_len);
 
4160
 
 
4161
        return(0);
 
4162
}
 
4163
 
 
4164
/**************************************************************************
 
4165
Updates a row given as a parameter to a new value. Note that we are given
 
4166
whole rows, not just the fields which are updated: this incurs some
 
4167
overhead for CPU when we check which fields are actually updated.
 
4168
TODO: currently InnoDB does not prevent the 'Halloween problem':
 
4169
in a searched update a single row can get updated several times
 
4170
if its index columns are updated! */
 
4171
UNIV_INTERN
 
4172
int
 
4173
ha_innobase::update_row(
 
4174
/*====================*/
 
4175
                                        /* out: error number or 0 */
 
4176
        const uchar*    old_row,        /* in: old row in MySQL format */
 
4177
        uchar*          new_row)        /* in: new row in MySQL format */
 
4178
{
 
4179
        upd_t*          uvect;
 
4180
        int             error = 0;
 
4181
        trx_t*          trx = thd_to_trx(user_thd);
 
4182
 
 
4183
        DBUG_ENTER("ha_innobase::update_row");
 
4184
 
 
4185
        ut_a(prebuilt->trx == trx);
 
4186
 
 
4187
        ha_statistic_increment(&SSV::ha_update_count);
 
4188
 
 
4189
        if (table->timestamp_field_type & TIMESTAMP_AUTO_SET_ON_UPDATE)
 
4190
                table->timestamp_field->set_time();
 
4191
 
 
4192
        if (prebuilt->upd_node) {
 
4193
                uvect = prebuilt->upd_node->update;
 
4194
        } else {
 
4195
                uvect = row_get_prebuilt_update_vector(prebuilt);
 
4196
        }
 
4197
 
 
4198
        /* Build an update vector from the modified fields in the rows
 
4199
        (uses upd_buff of the handle) */
 
4200
 
 
4201
        calc_row_difference(uvect, (uchar*) old_row, new_row, table,
 
4202
                        upd_buff, (ulint)upd_and_key_val_buff_len,
 
4203
                        prebuilt, user_thd);
 
4204
 
 
4205
        /* This is not a delete */
 
4206
        prebuilt->upd_node->is_delete = FALSE;
 
4207
 
 
4208
        ut_a(prebuilt->template_type == ROW_MYSQL_WHOLE_ROW);
 
4209
 
 
4210
        innodb_srv_conc_enter_innodb(trx);
 
4211
 
 
4212
        error = row_update_for_mysql((byte*) old_row, prebuilt);
 
4213
 
 
4214
        /* We need to do some special AUTOINC handling for the following case:
 
4215
 
 
4216
        INSERT INTO t (c1,c2) VALUES(x,y) ON DUPLICATE KEY UPDATE ...
 
4217
 
 
4218
        We need to use the AUTOINC counter that was actually used by
 
4219
        MySQL in the UPDATE statement, which can be different from the
 
4220
        value used in the INSERT statement.*/
 
4221
 
 
4222
        if (error == DB_SUCCESS
 
4223
            && table->next_number_field
 
4224
            && new_row == table->record[0]
 
4225
            && thd_sql_command(user_thd) == SQLCOM_INSERT
 
4226
            && (trx->duplicates & (TRX_DUP_IGNORE | TRX_DUP_REPLACE))
 
4227
                == TRX_DUP_IGNORE)  {
 
4228
 
 
4229
                longlong        auto_inc;
 
4230
 
 
4231
                auto_inc = table->next_number_field->val_int();
 
4232
 
 
4233
                if (auto_inc != 0) {
 
4234
                        auto_inc += prebuilt->table->autoinc_increment;
 
4235
 
 
4236
                        error = innobase_set_max_autoinc(auto_inc);
 
4237
                }
 
4238
        }
 
4239
 
 
4240
        innodb_srv_conc_exit_innodb(trx);
 
4241
 
 
4242
        error = convert_error_code_to_mysql(error,
 
4243
                                            prebuilt->table->flags, user_thd);
 
4244
 
 
4245
        if (error == 0 /* success */
 
4246
            && uvect->n_fields == 0 /* no columns were updated */) {
 
4247
 
 
4248
                /* This is the same as success, but instructs
 
4249
                MySQL that the row is not really updated and it
 
4250
                should not increase the count of updated rows.
 
4251
                This is fix for http://bugs.mysql.com/29157 */
 
4252
                error = HA_ERR_RECORD_IS_THE_SAME;
 
4253
        }
 
4254
 
 
4255
        /* Tell InnoDB server that there might be work for
 
4256
        utility threads: */
 
4257
 
 
4258
        innobase_active_small();
 
4259
 
 
4260
        DBUG_RETURN(error);
 
4261
}
 
4262
 
 
4263
/**************************************************************************
 
4264
Deletes a row given as the parameter. */
 
4265
UNIV_INTERN
 
4266
int
 
4267
ha_innobase::delete_row(
 
4268
/*====================*/
 
4269
                                /* out: error number or 0 */
 
4270
        const uchar*    record) /* in: a row in MySQL format */
 
4271
{
 
4272
        int             error = 0;
 
4273
        trx_t*          trx = thd_to_trx(user_thd);
 
4274
 
 
4275
        DBUG_ENTER("ha_innobase::delete_row");
 
4276
 
 
4277
        ut_a(prebuilt->trx == trx);
 
4278
 
 
4279
        ha_statistic_increment(&SSV::ha_delete_count);
 
4280
 
 
4281
        /* Only if the table has an AUTOINC column */
 
4282
        if (table->found_next_number_field && record == table->record[0]) {
 
4283
                ulonglong       dummy = 0;
 
4284
 
 
4285
                /* First check whether the AUTOINC sub-system has been
 
4286
                initialized using the AUTOINC mutex. If not then we
 
4287
                do it the "proper" way, by acquiring the heavier locks. */
 
4288
                dict_table_autoinc_lock(prebuilt->table);
 
4289
 
 
4290
                if (!prebuilt->table->autoinc_inited) {
 
4291
                        dict_table_autoinc_unlock(prebuilt->table);
 
4292
 
 
4293
                        error = innobase_get_auto_increment(&dummy);
 
4294
 
 
4295
                        if (error == DB_SUCCESS) {
 
4296
                                dict_table_autoinc_unlock(prebuilt->table);
 
4297
                        } else {
 
4298
                                goto error_exit;
 
4299
                        }
 
4300
                } else  {
 
4301
                        dict_table_autoinc_unlock(prebuilt->table);
 
4302
                }
 
4303
        }
 
4304
 
 
4305
        if (!prebuilt->upd_node) {
 
4306
                row_get_prebuilt_update_vector(prebuilt);
 
4307
        }
 
4308
 
 
4309
        /* This is a delete */
 
4310
 
 
4311
        prebuilt->upd_node->is_delete = TRUE;
 
4312
 
 
4313
        innodb_srv_conc_enter_innodb(trx);
 
4314
 
 
4315
        error = row_update_for_mysql((byte*) record, prebuilt);
 
4316
 
 
4317
        innodb_srv_conc_exit_innodb(trx);
 
4318
 
 
4319
error_exit:
 
4320
        error = convert_error_code_to_mysql(error,
 
4321
                                            prebuilt->table->flags, user_thd);
 
4322
 
 
4323
        /* Tell the InnoDB server that there might be work for
 
4324
        utility threads: */
 
4325
 
 
4326
        innobase_active_small();
 
4327
 
 
4328
        DBUG_RETURN(error);
 
4329
}
 
4330
 
 
4331
/**************************************************************************
 
4332
Removes a new lock set on a row, if it was not read optimistically. This can
 
4333
be called after a row has been read in the processing of an UPDATE or a DELETE
 
4334
query, if the option innodb_locks_unsafe_for_binlog is set. */
 
4335
UNIV_INTERN
 
4336
void
 
4337
ha_innobase::unlock_row(void)
 
4338
/*=========================*/
 
4339
{
 
4340
        DBUG_ENTER("ha_innobase::unlock_row");
 
4341
 
 
4342
        /* Consistent read does not take any locks, thus there is
 
4343
        nothing to unlock. */
 
4344
 
 
4345
        if (prebuilt->select_lock_type == LOCK_NONE) {
 
4346
                DBUG_VOID_RETURN;
 
4347
        }
 
4348
 
 
4349
        switch (prebuilt->row_read_type) {
 
4350
        case ROW_READ_WITH_LOCKS:
 
4351
                if (!srv_locks_unsafe_for_binlog
 
4352
                || prebuilt->trx->isolation_level == TRX_ISO_READ_COMMITTED) {
 
4353
                        break;
 
4354
                }
 
4355
                /* fall through */
 
4356
        case ROW_READ_TRY_SEMI_CONSISTENT:
 
4357
                row_unlock_for_mysql(prebuilt, FALSE);
 
4358
                break;
 
4359
        case ROW_READ_DID_SEMI_CONSISTENT:
 
4360
                prebuilt->row_read_type = ROW_READ_TRY_SEMI_CONSISTENT;
 
4361
                break;
 
4362
        }
 
4363
 
 
4364
        DBUG_VOID_RETURN;
 
4365
}
 
4366
 
 
4367
/* See handler.h and row0mysql.h for docs on this function. */
 
4368
UNIV_INTERN
 
4369
bool
 
4370
ha_innobase::was_semi_consistent_read(void)
 
4371
/*=======================================*/
 
4372
{
 
4373
        return(prebuilt->row_read_type == ROW_READ_DID_SEMI_CONSISTENT);
 
4374
}
 
4375
 
 
4376
/* See handler.h and row0mysql.h for docs on this function. */
 
4377
UNIV_INTERN
 
4378
void
 
4379
ha_innobase::try_semi_consistent_read(bool yes)
 
4380
/*===========================================*/
 
4381
{
 
4382
        ut_a(prebuilt->trx == thd_to_trx(ha_thd()));
 
4383
 
 
4384
        /* Row read type is set to semi consistent read if this was
 
4385
        requested by the MySQL and either innodb_locks_unsafe_for_binlog
 
4386
        option is used or this session is using READ COMMITTED isolation
 
4387
        level. */
 
4388
 
 
4389
        if (yes
 
4390
            && (srv_locks_unsafe_for_binlog
 
4391
                || prebuilt->trx->isolation_level == TRX_ISO_READ_COMMITTED)) {
 
4392
                prebuilt->row_read_type = ROW_READ_TRY_SEMI_CONSISTENT;
 
4393
        } else {
 
4394
                prebuilt->row_read_type = ROW_READ_WITH_LOCKS;
 
4395
        }
 
4396
}
 
4397
 
 
4398
#ifdef ROW_MERGE_IS_INDEX_USABLE
 
4399
/**********************************************************************
 
4400
Check if an index can be used by the optimizer. */
 
4401
UNIV_INTERN
 
4402
bool
 
4403
ha_innobase::is_index_available(
 
4404
/*============================*/
 
4405
                                        /* out: true if available else false*/
 
4406
        uint            keynr)          /* in: index number to check */
 
4407
{
 
4408
        DBUG_ENTER("ha_innobase::is_index_available");
 
4409
 
 
4410
        if (table && keynr != MAX_KEY && table->s->keys > 0) {
 
4411
                const dict_index_t*     index;
 
4412
                const KEY*              key = table->key_info + keynr;
 
4413
 
 
4414
                ut_ad(user_thd == ha_thd());
 
4415
                ut_a(prebuilt->trx == thd_to_trx(user_thd));
 
4416
 
 
4417
                index = dict_table_get_index_on_name(
 
4418
                        prebuilt->table, key->name);
 
4419
 
 
4420
                if (!row_merge_is_index_usable(prebuilt->trx, index)) {
 
4421
 
 
4422
                        DBUG_RETURN(false);
 
4423
                }
 
4424
        }
 
4425
 
 
4426
        DBUG_RETURN(true);
 
4427
}
 
4428
#endif /* ROW_MERGE_IS_INDEX_USABLE */
 
4429
 
 
4430
/**********************************************************************
 
4431
Initializes a handle to use an index. */
 
4432
UNIV_INTERN
 
4433
int
 
4434
ha_innobase::index_init(
 
4435
/*====================*/
 
4436
                        /* out: 0 or error number */
 
4437
        uint    keynr,  /* in: key (index) number */
 
4438
        bool sorted)    /* in: 1 if result MUST be sorted according to index */
 
4439
{
 
4440
        DBUG_ENTER("index_init");
 
4441
 
 
4442
        DBUG_RETURN(change_active_index(keynr));
 
4443
}
 
4444
 
 
4445
/**********************************************************************
 
4446
Currently does nothing. */
 
4447
UNIV_INTERN
 
4448
int
 
4449
ha_innobase::index_end(void)
 
4450
/*========================*/
 
4451
{
 
4452
        int     error   = 0;
 
4453
        DBUG_ENTER("index_end");
 
4454
        active_index=MAX_KEY;
 
4455
        DBUG_RETURN(error);
 
4456
}
 
4457
 
 
4458
/*************************************************************************
 
4459
Converts a search mode flag understood by MySQL to a flag understood
 
4460
by InnoDB. */
 
4461
inline
 
4462
ulint
 
4463
convert_search_mode_to_innobase(
 
4464
/*============================*/
 
4465
        enum ha_rkey_function   find_flag)
 
4466
{
 
4467
        switch (find_flag) {
 
4468
        case HA_READ_KEY_EXACT:
 
4469
                /* this does not require the index to be UNIQUE */
 
4470
                return(PAGE_CUR_GE);
 
4471
        case HA_READ_KEY_OR_NEXT:
 
4472
                return(PAGE_CUR_GE);
 
4473
        case HA_READ_KEY_OR_PREV:
 
4474
                return(PAGE_CUR_LE);
 
4475
        case HA_READ_AFTER_KEY: 
 
4476
                return(PAGE_CUR_G);
 
4477
        case HA_READ_BEFORE_KEY:
 
4478
                return(PAGE_CUR_L);
 
4479
        case HA_READ_PREFIX:
 
4480
                return(PAGE_CUR_GE);
 
4481
        case HA_READ_PREFIX_LAST:
 
4482
                return(PAGE_CUR_LE);
 
4483
        case HA_READ_PREFIX_LAST_OR_PREV:
 
4484
                return(PAGE_CUR_LE);
 
4485
                /* In MySQL-4.0 HA_READ_PREFIX and HA_READ_PREFIX_LAST always
 
4486
                pass a complete-field prefix of a key value as the search
 
4487
                tuple. I.e., it is not allowed that the last field would
 
4488
                just contain n first bytes of the full field value.
 
4489
                MySQL uses a 'padding' trick to convert LIKE 'abc%'
 
4490
                type queries so that it can use as a search tuple
 
4491
                a complete-field-prefix of a key value. Thus, the InnoDB
 
4492
                search mode PAGE_CUR_LE_OR_EXTENDS is never used.
 
4493
                TODO: when/if MySQL starts to use also partial-field
 
4494
                prefixes, we have to deal with stripping of spaces
 
4495
                and comparison of non-latin1 char type fields in
 
4496
                innobase_mysql_cmp() to get PAGE_CUR_LE_OR_EXTENDS to
 
4497
                work correctly. */
 
4498
        case HA_READ_MBR_CONTAIN:
 
4499
        case HA_READ_MBR_INTERSECT:
 
4500
        case HA_READ_MBR_WITHIN:
 
4501
        case HA_READ_MBR_DISJOINT:
 
4502
        case HA_READ_MBR_EQUAL:
 
4503
                my_error(ER_TABLE_CANT_HANDLE_SPKEYS, MYF(0));
 
4504
                return(PAGE_CUR_UNSUPP);
 
4505
        /* do not use "default:" in order to produce a gcc warning:
 
4506
        enumeration value '...' not handled in switch
 
4507
        (if -Wswitch or -Wall is used) */
 
4508
        }
 
4509
 
 
4510
        my_error(ER_CHECK_NOT_IMPLEMENTED, MYF(0), "this functionality");
 
4511
 
 
4512
        return(PAGE_CUR_UNSUPP);
 
4513
}
 
4514
 
 
4515
/*
 
4516
   BACKGROUND INFO: HOW A SELECT SQL QUERY IS EXECUTED
 
4517
   ---------------------------------------------------
 
4518
The following does not cover all the details, but explains how we determine
 
4519
the start of a new SQL statement, and what is associated with it.
 
4520
 
 
4521
For each table in the database the MySQL interpreter may have several
 
4522
table handle instances in use, also in a single SQL query. For each table
 
4523
handle instance there is an InnoDB  'prebuilt' struct which contains most
 
4524
of the InnoDB data associated with this table handle instance.
 
4525
 
 
4526
  A) if the user has not explicitly set any MySQL table level locks:
 
4527
 
 
4528
  1) MySQL calls ::external_lock to set an 'intention' table level lock on
 
4529
the table of the handle instance. There we set
 
4530
prebuilt->sql_stat_start = TRUE. The flag sql_stat_start should be set
 
4531
true if we are taking this table handle instance to use in a new SQL
 
4532
statement issued by the user. We also increment trx->n_mysql_tables_in_use.
 
4533
 
 
4534
  2) If prebuilt->sql_stat_start == TRUE we 'pre-compile' the MySQL search
 
4535
instructions to prebuilt->template of the table handle instance in
 
4536
::index_read. The template is used to save CPU time in large joins.
 
4537
 
 
4538
  3) In row_search_for_mysql, if prebuilt->sql_stat_start is true, we
 
4539
allocate a new consistent read view for the trx if it does not yet have one,
 
4540
or in the case of a locking read, set an InnoDB 'intention' table level
 
4541
lock on the table.
 
4542
 
 
4543
  4) We do the SELECT. MySQL may repeatedly call ::index_read for the
 
4544
same table handle instance, if it is a join.
 
4545
 
 
4546
  5) When the SELECT ends, MySQL removes its intention table level locks
 
4547
in ::external_lock. When trx->n_mysql_tables_in_use drops to zero,
 
4548
 (a) we execute a COMMIT there if the autocommit is on,
 
4549
 (b) we also release possible 'SQL statement level resources' InnoDB may
 
4550
have for this SQL statement. The MySQL interpreter does NOT execute
 
4551
autocommit for pure read transactions, though it should. That is why the
 
4552
table handler in that case has to execute the COMMIT in ::external_lock.
 
4553
 
 
4554
  B) If the user has explicitly set MySQL table level locks, then MySQL
 
4555
does NOT call ::external_lock at the start of the statement. To determine
 
4556
when we are at the start of a new SQL statement we at the start of
 
4557
::index_read also compare the query id to the latest query id where the
 
4558
table handle instance was used. If it has changed, we know we are at the
 
4559
start of a new SQL statement. Since the query id can theoretically
 
4560
overwrap, we use this test only as a secondary way of determining the
 
4561
start of a new SQL statement. */
 
4562
 
 
4563
 
 
4564
/**************************************************************************
 
4565
Positions an index cursor to the index specified in the handle. Fetches the
 
4566
row if any. */
 
4567
UNIV_INTERN
 
4568
int
 
4569
ha_innobase::index_read(
 
4570
/*====================*/
 
4571
                                        /* out: 0, HA_ERR_KEY_NOT_FOUND,
 
4572
                                        or error number */
 
4573
        uchar*          buf,            /* in/out: buffer for the returned
 
4574
                                        row */
 
4575
        const uchar*    key_ptr,        /* in: key value; if this is NULL
 
4576
                                        we position the cursor at the
 
4577
                                        start or end of index; this can
 
4578
                                        also contain an InnoDB row id, in
 
4579
                                        which case key_len is the InnoDB
 
4580
                                        row id length; the key value can
 
4581
                                        also be a prefix of a full key value,
 
4582
                                        and the last column can be a prefix
 
4583
                                        of a full column */
 
4584
        uint                    key_len,/* in: key value length */
 
4585
        enum ha_rkey_function find_flag)/* in: search flags from my_base.h */
 
4586
{
 
4587
        ulint           mode;
 
4588
        dict_index_t*   index;
 
4589
        ulint           match_mode      = 0;
 
4590
        int             error;
 
4591
        ulint           ret;
 
4592
 
 
4593
        DBUG_ENTER("index_read");
 
4594
 
 
4595
        ut_a(prebuilt->trx == thd_to_trx(user_thd));
 
4596
 
 
4597
        ha_statistic_increment(&SSV::ha_read_key_count);
 
4598
 
 
4599
        index = prebuilt->index;
 
4600
 
 
4601
        /* Note that if the index for which the search template is built is not
 
4602
        necessarily prebuilt->index, but can also be the clustered index */
 
4603
 
 
4604
        if (prebuilt->sql_stat_start) {
 
4605
                build_template(prebuilt, user_thd, table, ROW_MYSQL_REC_FIELDS);
 
4606
        }
 
4607
 
 
4608
        if (key_ptr) {
 
4609
                /* Convert the search key value to InnoDB format into
 
4610
                prebuilt->search_tuple */
 
4611
 
 
4612
                row_sel_convert_mysql_key_to_innobase(
 
4613
                        prebuilt->search_tuple,
 
4614
                        (byte*) key_val_buff,
 
4615
                        (ulint)upd_and_key_val_buff_len,
 
4616
                        index,
 
4617
                        (byte*) key_ptr,
 
4618
                        (ulint) key_len,
 
4619
                        prebuilt->trx);
 
4620
        } else {
 
4621
                /* We position the cursor to the last or the first entry
 
4622
                in the index */
 
4623
 
 
4624
                dtuple_set_n_fields(prebuilt->search_tuple, 0);
 
4625
        }
 
4626
 
 
4627
        mode = convert_search_mode_to_innobase(find_flag);
 
4628
 
 
4629
        match_mode = 0;
 
4630
 
 
4631
        if (find_flag == HA_READ_KEY_EXACT) {
 
4632
 
 
4633
                match_mode = ROW_SEL_EXACT;
 
4634
 
 
4635
        } else if (find_flag == HA_READ_PREFIX
 
4636
                   || find_flag == HA_READ_PREFIX_LAST) {
 
4637
 
 
4638
                match_mode = ROW_SEL_EXACT_PREFIX;
 
4639
        }
 
4640
 
 
4641
        last_match_mode = (uint) match_mode;
 
4642
 
 
4643
        if (mode != PAGE_CUR_UNSUPP) {
 
4644
 
 
4645
                innodb_srv_conc_enter_innodb(prebuilt->trx);
 
4646
 
 
4647
                ret = row_search_for_mysql((byte*) buf, mode, prebuilt,
 
4648
                                           match_mode, 0);
 
4649
 
 
4650
                innodb_srv_conc_exit_innodb(prebuilt->trx);
 
4651
        } else {
 
4652
 
 
4653
                ret = DB_UNSUPPORTED;
 
4654
        }
 
4655
 
 
4656
        switch (ret) {
 
4657
        case DB_SUCCESS:
 
4658
                error = 0;
 
4659
                table->status = 0;
 
4660
                break;
 
4661
        case DB_RECORD_NOT_FOUND:
 
4662
                error = HA_ERR_KEY_NOT_FOUND;
 
4663
                table->status = STATUS_NOT_FOUND;
 
4664
                break;
 
4665
        case DB_END_OF_INDEX:
 
4666
                error = HA_ERR_KEY_NOT_FOUND;
 
4667
                table->status = STATUS_NOT_FOUND;
 
4668
                break;
 
4669
        default:
 
4670
                error = convert_error_code_to_mysql((int) ret,
 
4671
                                                    prebuilt->table->flags,
 
4672
                                                    user_thd);
 
4673
                table->status = STATUS_NOT_FOUND;
 
4674
                break;
 
4675
        }
 
4676
 
 
4677
        DBUG_RETURN(error);
 
4678
}
 
4679
 
 
4680
/***********************************************************************
 
4681
The following functions works like index_read, but it find the last
 
4682
row with the current key value or prefix. */
 
4683
UNIV_INTERN
 
4684
int
 
4685
ha_innobase::index_read_last(
 
4686
/*=========================*/
 
4687
                                /* out: 0, HA_ERR_KEY_NOT_FOUND, or an
 
4688
                                error code */
 
4689
        uchar*          buf,    /* out: fetched row */
 
4690
        const uchar*    key_ptr,/* in: key value, or a prefix of a full
 
4691
                                key value */
 
4692
        uint            key_len)/* in: length of the key val or prefix
 
4693
                                in bytes */
 
4694
{
 
4695
        return(index_read(buf, key_ptr, key_len, HA_READ_PREFIX_LAST));
 
4696
}
 
4697
 
 
4698
/************************************************************************
 
4699
Get the index for a handle. Does not change active index.*/
 
4700
UNIV_INTERN
 
4701
dict_index_t*
 
4702
ha_innobase::innobase_get_index(
 
4703
/*============================*/
 
4704
                                /* out: NULL or index instance. */
 
4705
        uint            keynr)  /* in: use this index; MAX_KEY means always
 
4706
                                clustered index, even if it was internally
 
4707
                                generated by InnoDB */
 
4708
{
 
4709
        KEY*            key = 0;
 
4710
        dict_index_t*   index = 0;
 
4711
 
 
4712
        DBUG_ENTER("innobase_get_index");
 
4713
        ha_statistic_increment(&SSV::ha_read_key_count);
 
4714
 
 
4715
        ut_ad(user_thd == ha_thd());
 
4716
        ut_a(prebuilt->trx == thd_to_trx(user_thd));
 
4717
 
 
4718
        if (keynr != MAX_KEY && table->s->keys > 0) {
 
4719
                key = table->key_info + keynr;
 
4720
 
 
4721
                index = dict_table_get_index_on_name(prebuilt->table,
 
4722
                                                     key->name);
 
4723
        } else {
 
4724
                index = dict_table_get_first_index(prebuilt->table);
 
4725
        }
 
4726
 
 
4727
        if (!index) {
 
4728
                sql_print_error(
 
4729
                        "Innodb could not find key n:o %u with name %s "
 
4730
                        "from dict cache for table %s",
 
4731
                        keynr, key ? key->name : "NULL",
 
4732
                        prebuilt->table->name);
 
4733
        }
 
4734
 
 
4735
        DBUG_RETURN(index);
 
4736
}
 
4737
 
 
4738
/************************************************************************
 
4739
Changes the active index of a handle. */
 
4740
UNIV_INTERN
 
4741
int
 
4742
ha_innobase::change_active_index(
 
4743
/*=============================*/
 
4744
                        /* out: 0 or error code */
 
4745
        uint    keynr)  /* in: use this index; MAX_KEY means always clustered
 
4746
                        index, even if it was internally generated by
 
4747
                        InnoDB */
 
4748
{
 
4749
        DBUG_ENTER("change_active_index");
 
4750
 
 
4751
        ut_ad(user_thd == ha_thd());
 
4752
        ut_a(prebuilt->trx == thd_to_trx(user_thd));
 
4753
 
 
4754
        active_index = keynr;
 
4755
 
 
4756
        prebuilt->index = innobase_get_index(keynr);
 
4757
 
 
4758
        if (UNIV_UNLIKELY(!prebuilt->index)) {
 
4759
                sql_print_warning("InnoDB: change_active_index(%u) failed",
 
4760
                                  keynr);
 
4761
                DBUG_RETURN(1);
 
4762
        }
 
4763
 
 
4764
        ut_a(prebuilt->search_tuple != 0);
 
4765
 
 
4766
        dtuple_set_n_fields(prebuilt->search_tuple, prebuilt->index->n_fields);
 
4767
 
 
4768
        dict_index_copy_types(prebuilt->search_tuple, prebuilt->index,
 
4769
                        prebuilt->index->n_fields);
 
4770
 
 
4771
        /* MySQL changes the active index for a handle also during some
 
4772
        queries, for example SELECT MAX(a), SUM(a) first retrieves the MAX()
 
4773
        and then calculates the sum. Previously we played safe and used
 
4774
        the flag ROW_MYSQL_WHOLE_ROW below, but that caused unnecessary
 
4775
        copying. Starting from MySQL-4.1 we use a more efficient flag here. */
 
4776
 
 
4777
        build_template(prebuilt, user_thd, table, ROW_MYSQL_REC_FIELDS);
 
4778
 
 
4779
        DBUG_RETURN(0);
 
4780
}
 
4781
 
 
4782
/**************************************************************************
 
4783
Positions an index cursor to the index specified in keynr. Fetches the
 
4784
row if any. */
 
4785
/* ??? This is only used to read whole keys ??? */
 
4786
UNIV_INTERN
 
4787
int
 
4788
ha_innobase::index_read_idx(
 
4789
/*========================*/
 
4790
                                        /* out: error number or 0 */
 
4791
        uchar*          buf,            /* in/out: buffer for the returned
 
4792
                                        row */
 
4793
        uint            keynr,          /* in: use this index */
 
4794
        const uchar*    key,            /* in: key value; if this is NULL
 
4795
                                        we position the cursor at the
 
4796
                                        start or end of index */
 
4797
        uint            key_len,        /* in: key value length */
 
4798
        enum ha_rkey_function find_flag)/* in: search flags from my_base.h */
 
4799
{
 
4800
        if (change_active_index(keynr)) {
 
4801
 
 
4802
                return(1);
 
4803
        }
 
4804
 
 
4805
        return(index_read(buf, key, key_len, find_flag));
 
4806
}
 
4807
 
 
4808
/***************************************************************************
 
4809
Reads the next or previous row from a cursor, which must have previously been
 
4810
positioned using index_read. */
 
4811
UNIV_INTERN
 
4812
int
 
4813
ha_innobase::general_fetch(
 
4814
/*=======================*/
 
4815
                                /* out: 0, HA_ERR_END_OF_FILE, or error
 
4816
                                number */
 
4817
        uchar*  buf,            /* in/out: buffer for next row in MySQL
 
4818
                                format */
 
4819
        uint    direction,      /* in: ROW_SEL_NEXT or ROW_SEL_PREV */
 
4820
        uint    match_mode)     /* in: 0, ROW_SEL_EXACT, or
 
4821
                                ROW_SEL_EXACT_PREFIX */
 
4822
{
 
4823
        ulint           ret;
 
4824
        int             error   = 0;
 
4825
 
 
4826
        DBUG_ENTER("general_fetch");
 
4827
 
 
4828
        ut_a(prebuilt->trx == thd_to_trx(user_thd));
 
4829
 
 
4830
        innodb_srv_conc_enter_innodb(prebuilt->trx);
 
4831
 
 
4832
        ret = row_search_for_mysql(
 
4833
                (byte*)buf, 0, prebuilt, match_mode, direction);
 
4834
 
 
4835
        innodb_srv_conc_exit_innodb(prebuilt->trx);
 
4836
 
 
4837
        switch (ret) {
 
4838
        case DB_SUCCESS:
 
4839
                error = 0;
 
4840
                table->status = 0;
 
4841
                break;
 
4842
        case DB_RECORD_NOT_FOUND:
 
4843
                error = HA_ERR_END_OF_FILE;
 
4844
                table->status = STATUS_NOT_FOUND;
 
4845
                break;
 
4846
        case DB_END_OF_INDEX:
 
4847
                error = HA_ERR_END_OF_FILE;
 
4848
                table->status = STATUS_NOT_FOUND;
 
4849
                break;
 
4850
        default:
 
4851
                error = convert_error_code_to_mysql(
 
4852
                        (int) ret, prebuilt->table->flags, user_thd);
 
4853
                table->status = STATUS_NOT_FOUND;
 
4854
                break;
 
4855
        }
 
4856
 
 
4857
        DBUG_RETURN(error);
 
4858
}
 
4859
 
 
4860
/***************************************************************************
 
4861
Reads the next row from a cursor, which must have previously been
 
4862
positioned using index_read. */
 
4863
UNIV_INTERN
 
4864
int
 
4865
ha_innobase::index_next(
 
4866
/*====================*/
 
4867
                                /* out: 0, HA_ERR_END_OF_FILE, or error
 
4868
                                number */
 
4869
        uchar*          buf)    /* in/out: buffer for next row in MySQL
 
4870
                                format */
 
4871
{
 
4872
        ha_statistic_increment(&SSV::ha_read_next_count);
 
4873
 
 
4874
        return(general_fetch(buf, ROW_SEL_NEXT, 0));
 
4875
}
 
4876
 
 
4877
/***********************************************************************
 
4878
Reads the next row matching to the key value given as the parameter. */
 
4879
UNIV_INTERN
 
4880
int
 
4881
ha_innobase::index_next_same(
 
4882
/*=========================*/
 
4883
                                /* out: 0, HA_ERR_END_OF_FILE, or error
 
4884
                                number */
 
4885
        uchar*          buf,    /* in/out: buffer for the row */
 
4886
        const uchar*    key,    /* in: key value */
 
4887
        uint            keylen) /* in: key value length */
 
4888
{
 
4889
        ha_statistic_increment(&SSV::ha_read_next_count);
 
4890
 
 
4891
        return(general_fetch(buf, ROW_SEL_NEXT, last_match_mode));
 
4892
}
 
4893
 
 
4894
/***************************************************************************
 
4895
Reads the previous row from a cursor, which must have previously been
 
4896
positioned using index_read. */
 
4897
UNIV_INTERN
 
4898
int
 
4899
ha_innobase::index_prev(
 
4900
/*====================*/
 
4901
                        /* out: 0, HA_ERR_END_OF_FILE, or error number */
 
4902
        uchar*  buf)    /* in/out: buffer for previous row in MySQL format */
 
4903
{
 
4904
        ha_statistic_increment(&SSV::ha_read_prev_count);
 
4905
 
 
4906
        return(general_fetch(buf, ROW_SEL_PREV, 0));
 
4907
}
 
4908
 
 
4909
/************************************************************************
 
4910
Positions a cursor on the first record in an index and reads the
 
4911
corresponding row to buf. */
 
4912
UNIV_INTERN
 
4913
int
 
4914
ha_innobase::index_first(
 
4915
/*=====================*/
 
4916
                        /* out: 0, HA_ERR_END_OF_FILE, or error code */
 
4917
        uchar*  buf)    /* in/out: buffer for the row */
 
4918
{
 
4919
        int     error;
 
4920
 
 
4921
        DBUG_ENTER("index_first");
 
4922
        ha_statistic_increment(&SSV::ha_read_first_count);
 
4923
 
 
4924
        error = index_read(buf, NULL, 0, HA_READ_AFTER_KEY);
 
4925
 
 
4926
        /* MySQL does not seem to allow this to return HA_ERR_KEY_NOT_FOUND */
 
4927
 
 
4928
        if (error == HA_ERR_KEY_NOT_FOUND) {
 
4929
                error = HA_ERR_END_OF_FILE;
 
4930
        }
 
4931
 
 
4932
        DBUG_RETURN(error);
 
4933
}
 
4934
 
 
4935
/************************************************************************
 
4936
Positions a cursor on the last record in an index and reads the
 
4937
corresponding row to buf. */
 
4938
UNIV_INTERN
 
4939
int
 
4940
ha_innobase::index_last(
 
4941
/*====================*/
 
4942
                        /* out: 0, HA_ERR_END_OF_FILE, or error code */
 
4943
        uchar*  buf)    /* in/out: buffer for the row */
 
4944
{
 
4945
        int     error;
 
4946
 
 
4947
        DBUG_ENTER("index_last");
 
4948
        ha_statistic_increment(&SSV::ha_read_last_count);
 
4949
 
 
4950
        error = index_read(buf, NULL, 0, HA_READ_BEFORE_KEY);
 
4951
 
 
4952
        /* MySQL does not seem to allow this to return HA_ERR_KEY_NOT_FOUND */
 
4953
 
 
4954
        if (error == HA_ERR_KEY_NOT_FOUND) {
 
4955
                error = HA_ERR_END_OF_FILE;
 
4956
        }
 
4957
 
 
4958
        DBUG_RETURN(error);
 
4959
}
 
4960
 
 
4961
/********************************************************************
 
4962
Initialize a table scan. */
 
4963
UNIV_INTERN
 
4964
int
 
4965
ha_innobase::rnd_init(
 
4966
/*==================*/
 
4967
                        /* out: 0 or error number */
 
4968
        bool    scan)   /* in: TRUE if table/index scan FALSE otherwise */
 
4969
{
 
4970
        int     err;
 
4971
 
 
4972
        /* Store the active index value so that we can restore the original
 
4973
        value after a scan */
 
4974
 
 
4975
        if (prebuilt->clust_index_was_generated) {
 
4976
                err = change_active_index(MAX_KEY);
 
4977
        } else {
 
4978
                err = change_active_index(primary_key);
 
4979
        }
 
4980
 
 
4981
        /* Don't use semi-consistent read in random row reads (by position).
 
4982
        This means we must disable semi_consistent_read if scan is false */
 
4983
 
 
4984
        if (!scan) {
 
4985
                try_semi_consistent_read(0);
 
4986
        }
 
4987
 
 
4988
        start_of_scan = 1;
 
4989
 
 
4990
        return(err);
 
4991
}
 
4992
 
 
4993
/*********************************************************************
 
4994
Ends a table scan. */
 
4995
UNIV_INTERN
 
4996
int
 
4997
ha_innobase::rnd_end(void)
 
4998
/*======================*/
 
4999
                                /* out: 0 or error number */
 
5000
{
 
5001
        return(index_end());
 
5002
}
 
5003
 
 
5004
/*********************************************************************
 
5005
Reads the next row in a table scan (also used to read the FIRST row
 
5006
in a table scan). */
 
5007
UNIV_INTERN
 
5008
int
 
5009
ha_innobase::rnd_next(
 
5010
/*==================*/
 
5011
                        /* out: 0, HA_ERR_END_OF_FILE, or error number */
 
5012
        uchar*  buf)    /* in/out: returns the row in this buffer,
 
5013
                        in MySQL format */
 
5014
{
 
5015
        int     error;
 
5016
 
 
5017
        DBUG_ENTER("rnd_next");
 
5018
        ha_statistic_increment(&SSV::ha_read_rnd_next_count);
 
5019
 
 
5020
        if (start_of_scan) {
 
5021
                error = index_first(buf);
 
5022
 
 
5023
                if (error == HA_ERR_KEY_NOT_FOUND) {
 
5024
                        error = HA_ERR_END_OF_FILE;
 
5025
                }
 
5026
 
 
5027
                start_of_scan = 0;
 
5028
        } else {
 
5029
                error = general_fetch(buf, ROW_SEL_NEXT, 0);
 
5030
        }
 
5031
 
 
5032
        DBUG_RETURN(error);
 
5033
}
 
5034
 
 
5035
/**************************************************************************
 
5036
Fetches a row from the table based on a row reference. */
 
5037
UNIV_INTERN
 
5038
int
 
5039
ha_innobase::rnd_pos(
 
5040
/*=================*/
 
5041
                        /* out: 0, HA_ERR_KEY_NOT_FOUND, or error code */
 
5042
        uchar*  buf,    /* in/out: buffer for the row */
 
5043
        uchar*  pos)    /* in: primary key value of the row in the
 
5044
                        MySQL format, or the row id if the clustered
 
5045
                        index was internally generated by InnoDB; the
 
5046
                        length of data in pos has to be ref_length */
 
5047
{
 
5048
        int             error;
 
5049
        uint            keynr   = active_index;
 
5050
        DBUG_ENTER("rnd_pos");
 
5051
        DBUG_DUMP("key", pos, ref_length);
 
5052
 
 
5053
        ha_statistic_increment(&SSV::ha_read_rnd_count);
 
5054
 
 
5055
        ut_a(prebuilt->trx == thd_to_trx(ha_thd()));
 
5056
 
 
5057
        if (prebuilt->clust_index_was_generated) {
 
5058
                /* No primary key was defined for the table and we
 
5059
                generated the clustered index from the row id: the
 
5060
                row reference is the row id, not any key value
 
5061
                that MySQL knows of */
 
5062
 
 
5063
                error = change_active_index(MAX_KEY);
 
5064
        } else {
 
5065
                error = change_active_index(primary_key);
 
5066
        }
 
5067
 
 
5068
        if (error) {
 
5069
                DBUG_PRINT("error", ("Got error: %d", error));
 
5070
                DBUG_RETURN(error);
 
5071
        }
 
5072
 
 
5073
        /* Note that we assume the length of the row reference is fixed
 
5074
        for the table, and it is == ref_length */
 
5075
 
 
5076
        error = index_read(buf, pos, ref_length, HA_READ_KEY_EXACT);
 
5077
 
 
5078
        if (error) {
 
5079
                DBUG_PRINT("error", ("Got error: %d", error));
 
5080
        }
 
5081
 
 
5082
        change_active_index(keynr);
 
5083
 
 
5084
        DBUG_RETURN(error);
 
5085
}
 
5086
 
 
5087
/*************************************************************************
 
5088
Stores a reference to the current row to 'ref' field of the handle. Note
 
5089
that in the case where we have generated the clustered index for the
 
5090
table, the function parameter is illogical: we MUST ASSUME that 'record'
 
5091
is the current 'position' of the handle, because if row ref is actually
 
5092
the row id internally generated in InnoDB, then 'record' does not contain
 
5093
it. We just guess that the row id must be for the record where the handle
 
5094
was positioned the last time. */
 
5095
UNIV_INTERN
 
5096
void
 
5097
ha_innobase::position(
 
5098
/*==================*/
 
5099
        const uchar*    record) /* in: row in MySQL format */
 
5100
{
 
5101
        uint            len;
 
5102
 
 
5103
        ut_a(prebuilt->trx == thd_to_trx(ha_thd()));
 
5104
 
 
5105
        if (prebuilt->clust_index_was_generated) {
 
5106
                /* No primary key was defined for the table and we
 
5107
                generated the clustered index from row id: the
 
5108
                row reference will be the row id, not any key value
 
5109
                that MySQL knows of */
 
5110
 
 
5111
                len = DATA_ROW_ID_LEN;
 
5112
 
 
5113
                memcpy(ref, prebuilt->row_id, len);
 
5114
        } else {
 
5115
                len = store_key_val_for_row(primary_key, (char*)ref,
 
5116
                                                         ref_length, record);
 
5117
        }
 
5118
 
 
5119
        /* We assume that the 'ref' value len is always fixed for the same
 
5120
        table. */
 
5121
 
 
5122
        if (len != ref_length) {
 
5123
          sql_print_error("Stored ref len is %lu, but table ref len is %lu",
 
5124
                          (ulong) len, (ulong) ref_length);
 
5125
        }
 
5126
}
 
5127
 
 
5128
/* limit innodb monitor access to users with PROCESS privilege.
 
5129
See http://bugs.mysql.com/32710 for expl. why we choose PROCESS. */
 
5130
#define IS_MAGIC_TABLE_AND_USER_DENIED_ACCESS(table_name, thd) \
 
5131
        (row_is_magic_monitor_table(table_name) \
 
5132
         && check_global_access(thd, PROCESS_ACL))
 
5133
 
 
5134
/*********************************************************************
 
5135
Creates a table definition to an InnoDB database. */
 
5136
static
 
5137
int
 
5138
create_table_def(
 
5139
/*=============*/
 
5140
        trx_t*          trx,            /* in: InnoDB transaction handle */
 
5141
        TABLE*          form,           /* in: information on table
 
5142
                                        columns and indexes */
 
5143
        const char*     table_name,     /* in: table name */
 
5144
        const char*     path_of_temp_table,/* in: if this is a table explicitly
 
5145
                                        created by the user with the
 
5146
                                        TEMPORARY keyword, then this
 
5147
                                        parameter is the dir path where the
 
5148
                                        table should be placed if we create
 
5149
                                        an .ibd file for it (no .ibd extension
 
5150
                                        in the path, though); otherwise this
 
5151
                                        is NULL */
 
5152
        ulint           flags)          /* in: table flags */
 
5153
{
 
5154
        Field*          field;
 
5155
        dict_table_t*   table;
 
5156
        ulint           n_cols;
 
5157
        int             error;
 
5158
        ulint           col_type;
 
5159
        ulint           col_len;
 
5160
        ulint           nulls_allowed;
 
5161
        ulint           unsigned_type;
 
5162
        ulint           binary_type;
 
5163
        ulint           long_true_varchar;
 
5164
        ulint           charset_no;
 
5165
        ulint           i;
 
5166
 
 
5167
        DBUG_ENTER("create_table_def");
 
5168
        DBUG_PRINT("enter", ("table_name: %s", table_name));
 
5169
 
 
5170
        ut_a(trx->mysql_thd != NULL);
 
5171
        if (IS_MAGIC_TABLE_AND_USER_DENIED_ACCESS(table_name,
 
5172
                                                  (THD*) trx->mysql_thd)) {
 
5173
                DBUG_RETURN(HA_ERR_GENERIC);
 
5174
        }
 
5175
 
 
5176
        n_cols = form->s->fields;
 
5177
 
 
5178
        /* We pass 0 as the space id, and determine at a lower level the space
 
5179
        id where to store the table */
 
5180
 
 
5181
        table = dict_mem_table_create(table_name, 0, n_cols, flags);
 
5182
 
 
5183
        if (path_of_temp_table) {
 
5184
                table->dir_path_of_temp_table =
 
5185
                        mem_heap_strdup(table->heap, path_of_temp_table);
 
5186
        }
 
5187
 
 
5188
        for (i = 0; i < n_cols; i++) {
 
5189
                field = form->field[i];
 
5190
 
 
5191
                col_type = get_innobase_type_from_mysql_type(&unsigned_type,
 
5192
                                                                        field);
 
5193
                if (field->null_ptr) {
 
5194
                        nulls_allowed = 0;
 
5195
                } else {
 
5196
                        nulls_allowed = DATA_NOT_NULL;
 
5197
                }
 
5198
 
 
5199
                if (field->binary()) {
 
5200
                        binary_type = DATA_BINARY_TYPE;
 
5201
                } else {
 
5202
                        binary_type = 0;
 
5203
                }
 
5204
 
 
5205
                charset_no = 0;
 
5206
 
 
5207
                if (dtype_is_string_type(col_type)) {
 
5208
 
 
5209
                        charset_no = (ulint)field->charset()->number;
 
5210
 
 
5211
                        ut_a(charset_no < 256); /* in data0type.h we assume
 
5212
                                                that the number fits in one
 
5213
                                                byte */
 
5214
                }
 
5215
 
 
5216
                ut_a(field->type() < 256); /* we assume in dtype_form_prtype()
 
5217
                                           that this fits in one byte */
 
5218
                col_len = field->pack_length();
 
5219
 
 
5220
                /* The MySQL pack length contains 1 or 2 bytes length field
 
5221
                for a true VARCHAR. Let us subtract that, so that the InnoDB
 
5222
                column length in the InnoDB data dictionary is the real
 
5223
                maximum byte length of the actual data. */
 
5224
 
 
5225
                long_true_varchar = 0;
 
5226
 
 
5227
                if (field->type() == MYSQL_TYPE_VARCHAR) {
 
5228
                        col_len -= ((Field_varstring*)field)->length_bytes;
 
5229
 
 
5230
                        if (((Field_varstring*)field)->length_bytes == 2) {
 
5231
                                long_true_varchar = DATA_LONG_TRUE_VARCHAR;
 
5232
                        }
 
5233
                }
 
5234
 
 
5235
                dict_mem_table_add_col(table, table->heap,
 
5236
                        (char*) field->field_name,
 
5237
                        col_type,
 
5238
                        dtype_form_prtype(
 
5239
                                (ulint)field->type()
 
5240
                                | nulls_allowed | unsigned_type
 
5241
                                | binary_type | long_true_varchar,
 
5242
                                charset_no),
 
5243
                        col_len);
 
5244
        }
 
5245
 
 
5246
        error = row_create_table_for_mysql(table, trx);
 
5247
 
 
5248
        error = convert_error_code_to_mysql(error, flags, NULL);
 
5249
 
 
5250
        DBUG_RETURN(error);
 
5251
}
 
5252
 
 
5253
/*********************************************************************
 
5254
Creates an index in an InnoDB database. */
 
5255
static
 
5256
int
 
5257
create_index(
 
5258
/*=========*/
 
5259
        trx_t*          trx,            /* in: InnoDB transaction handle */
 
5260
        TABLE*          form,           /* in: information on table
 
5261
                                        columns and indexes */
 
5262
        ulint           flags,          /* in: InnoDB table flags */
 
5263
        const char*     table_name,     /* in: table name */
 
5264
        uint            key_num)        /* in: index number */
 
5265
{
 
5266
        Field*          field;
 
5267
        dict_index_t*   index;
 
5268
        int             error;
 
5269
        ulint           n_fields;
 
5270
        KEY*            key;
 
5271
        KEY_PART_INFO*  key_part;
 
5272
        ulint           ind_type;
 
5273
        ulint           col_type;
 
5274
        ulint           prefix_len;
 
5275
        ulint           is_unsigned;
 
5276
        ulint           i;
 
5277
        ulint           j;
 
5278
        ulint*          field_lengths;
 
5279
 
 
5280
        DBUG_ENTER("create_index");
 
5281
 
 
5282
        key = form->key_info + key_num;
 
5283
 
 
5284
        n_fields = key->key_parts;
 
5285
 
 
5286
        ind_type = 0;
 
5287
 
 
5288
        if (key_num == form->s->primary_key) {
 
5289
                ind_type = ind_type | DICT_CLUSTERED;
 
5290
        }
 
5291
 
 
5292
        if (key->flags & HA_NOSAME ) {
 
5293
                ind_type = ind_type | DICT_UNIQUE;
 
5294
        }
 
5295
 
 
5296
        /* We pass 0 as the space id, and determine at a lower level the space
 
5297
        id where to store the table */
 
5298
 
 
5299
        index = dict_mem_index_create(table_name, key->name, 0,
 
5300
                                      ind_type, n_fields);
 
5301
 
 
5302
        field_lengths = (ulint*) my_malloc(sizeof(ulint) * n_fields,
 
5303
                MYF(MY_FAE));
 
5304
 
 
5305
        for (i = 0; i < n_fields; i++) {
 
5306
                key_part = key->key_part + i;
 
5307
 
 
5308
                /* (The flag HA_PART_KEY_SEG denotes in MySQL a column prefix
 
5309
                field in an index: we only store a specified number of first
 
5310
                bytes of the column to the index field.) The flag does not
 
5311
                seem to be properly set by MySQL. Let us fall back on testing
 
5312
                the length of the key part versus the column. */
 
5313
 
 
5314
                field = NULL;
 
5315
                for (j = 0; j < form->s->fields; j++) {
 
5316
 
 
5317
                        field = form->field[j];
 
5318
 
 
5319
                        if (0 == innobase_strcasecmp(
 
5320
                                        field->field_name,
 
5321
                                        key_part->field->field_name)) {
 
5322
                                /* Found the corresponding column */
 
5323
 
 
5324
                                break;
 
5325
                        }
 
5326
                }
 
5327
 
 
5328
                ut_a(j < form->s->fields);
 
5329
 
 
5330
                col_type = get_innobase_type_from_mysql_type(
 
5331
                                        &is_unsigned, key_part->field);
 
5332
 
 
5333
                if (DATA_BLOB == col_type
 
5334
                        || (key_part->length < field->pack_length()
 
5335
                                && field->type() != MYSQL_TYPE_VARCHAR)
 
5336
                        || (field->type() == MYSQL_TYPE_VARCHAR
 
5337
                                && key_part->length < field->pack_length()
 
5338
                                - ((Field_varstring*)field)->length_bytes)) {
 
5339
 
 
5340
                        prefix_len = key_part->length;
 
5341
 
 
5342
                        if (col_type == DATA_INT
 
5343
                                || col_type == DATA_FLOAT
 
5344
                                || col_type == DATA_DOUBLE
 
5345
                                || col_type == DATA_DECIMAL) {
 
5346
                                sql_print_error(
 
5347
                                        "MySQL is trying to create a column "
 
5348
                                        "prefix index field, on an "
 
5349
                                        "inappropriate data type. Table "
 
5350
                                        "name %s, column name %s.",
 
5351
                                        table_name,
 
5352
                                        key_part->field->field_name);
 
5353
 
 
5354
                                prefix_len = 0;
 
5355
                        }
 
5356
                } else {
 
5357
                        prefix_len = 0;
 
5358
                }
 
5359
 
 
5360
                field_lengths[i] = key_part->length;
 
5361
 
 
5362
                dict_mem_index_add_field(index,
 
5363
                        (char*) key_part->field->field_name, prefix_len);
 
5364
        }
 
5365
 
 
5366
        /* Even though we've defined max_supported_key_part_length, we
 
5367
        still do our own checking using field_lengths to be absolutely
 
5368
        sure we don't create too long indexes. */
 
5369
        error = row_create_index_for_mysql(index, trx, field_lengths);
 
5370
 
 
5371
        error = convert_error_code_to_mysql(error, flags, NULL);
 
5372
 
 
5373
        my_free(field_lengths, MYF(0));
 
5374
 
 
5375
        DBUG_RETURN(error);
 
5376
}
 
5377
 
 
5378
/*********************************************************************
 
5379
Creates an index to an InnoDB table when the user has defined no
 
5380
primary index. */
 
5381
static
 
5382
int
 
5383
create_clustered_index_when_no_primary(
 
5384
/*===================================*/
 
5385
        trx_t*          trx,            /* in: InnoDB transaction handle */
 
5386
        ulint           flags,          /* in: InnoDB table flags */
 
5387
        const char*     table_name)     /* in: table name */
 
5388
{
 
5389
        dict_index_t*   index;
 
5390
        int             error;
 
5391
 
 
5392
        /* We pass 0 as the space id, and determine at a lower level the space
 
5393
        id where to store the table */
 
5394
 
 
5395
        index = dict_mem_index_create(table_name, "GEN_CLUST_INDEX",
 
5396
                                      0, DICT_CLUSTERED, 0);
 
5397
 
 
5398
        error = row_create_index_for_mysql(index, trx, NULL);
 
5399
 
 
5400
        error = convert_error_code_to_mysql(error, flags, NULL);
 
5401
 
 
5402
        return(error);
 
5403
}
 
5404
 
 
5405
/*********************************************************************
 
5406
Validates the create options. We may build on this function
 
5407
in future. For now, it checks two specifiers:
 
5408
KEY_BLOCK_SIZE and ROW_FORMAT
 
5409
If innodb_strict_mode is not set then this function is a no-op */
 
5410
static
 
5411
ibool
 
5412
create_options_are_valid(
 
5413
/*=====================*/
 
5414
                                        /* out: TRUE if valid. */
 
5415
        THD*            thd,            /* in: connection thread. */
 
5416
        TABLE*          form,           /* in: information on table
 
5417
                                        columns and indexes */
 
5418
        HA_CREATE_INFO* create_info)    /* in: create info. */
 
5419
{
 
5420
        ibool   kbs_specified   = FALSE;
 
5421
        ibool   ret             = TRUE;
 
5422
 
 
5423
 
 
5424
        ut_ad(thd != NULL);
 
5425
 
 
5426
        /* If innodb_strict_mode is not set don't do any validation. */
 
5427
        if (!(THDVAR(thd, strict_mode))) {
 
5428
                return(TRUE);
 
5429
        }
 
5430
 
 
5431
        ut_ad(form != NULL);
 
5432
        ut_ad(create_info != NULL);
 
5433
 
 
5434
        /* First check if KEY_BLOCK_SIZE was specified. */
 
5435
        if (create_info->key_block_size
 
5436
            || (create_info->used_fields & HA_CREATE_USED_KEY_BLOCK_SIZE)) {
 
5437
 
 
5438
                kbs_specified = TRUE;
 
5439
                switch (create_info->key_block_size) {
 
5440
                case 1:
 
5441
                case 2:
 
5442
                case 4:
 
5443
                case 8:
 
5444
                case 16:
 
5445
                        /* Valid value. */
 
5446
                        break;
 
5447
                default:
 
5448
                        push_warning_printf(thd, MYSQL_ERROR::WARN_LEVEL_ERROR,
 
5449
                                            ER_ILLEGAL_HA_CREATE_OPTION,
 
5450
                                            "InnoDB: invalid"
 
5451
                                            " KEY_BLOCK_SIZE = %lu."
 
5452
                                            " Valid values are"
 
5453
                                            " [1, 2, 4, 8, 16]",
 
5454
                                            create_info->key_block_size);
 
5455
                        ret = FALSE;
 
5456
                }
 
5457
        }
 
5458
        
 
5459
        /* If KEY_BLOCK_SIZE was specified, check for its
 
5460
        dependencies. */
 
5461
        if (kbs_specified && !srv_file_per_table) {
 
5462
                push_warning(thd, MYSQL_ERROR::WARN_LEVEL_ERROR,
 
5463
                             ER_ILLEGAL_HA_CREATE_OPTION,
 
5464
                             "InnoDB: KEY_BLOCK_SIZE"
 
5465
                             " requires innodb_file_per_table.");
 
5466
                ret = FALSE;
 
5467
        }
 
5468
 
 
5469
        if (kbs_specified && srv_file_format < DICT_TF_FORMAT_ZIP) {
 
5470
                push_warning(thd, MYSQL_ERROR::WARN_LEVEL_ERROR,
 
5471
                             ER_ILLEGAL_HA_CREATE_OPTION,
 
5472
                             "InnoDB: KEY_BLOCK_SIZE"
 
5473
                             " requires innodb_file_format >"
 
5474
                             " Antelope.");
 
5475
                ret = FALSE;
 
5476
        }
 
5477
 
 
5478
        /* Now check for ROW_FORMAT specifier. */
 
5479
        if (create_info->used_fields & HA_CREATE_USED_ROW_FORMAT) {
 
5480
                switch (form->s->row_type) {
 
5481
                        const char* row_format_name;
 
5482
                case ROW_TYPE_COMPRESSED:
 
5483
                case ROW_TYPE_DYNAMIC:
 
5484
                        row_format_name
 
5485
                                = form->s->row_type == ROW_TYPE_COMPRESSED
 
5486
                                ? "COMPRESSED"
 
5487
                                : "DYNAMIC";
 
5488
 
 
5489
                        /* These two ROW_FORMATs require
 
5490
                        srv_file_per_table and srv_file_format */
 
5491
                        if (!srv_file_per_table) {
 
5492
                                push_warning_printf(
 
5493
                                        thd,
 
5494
                                        MYSQL_ERROR::WARN_LEVEL_ERROR,
 
5495
                                        ER_ILLEGAL_HA_CREATE_OPTION,
 
5496
                                        "InnoDB: ROW_FORMAT=%s"
 
5497
                                        " requires innodb_file_per_table.",
 
5498
                                        row_format_name);
 
5499
                                        ret = FALSE;
 
5500
 
 
5501
                        }
 
5502
 
 
5503
                        if (srv_file_format < DICT_TF_FORMAT_ZIP) {
 
5504
                                push_warning_printf(
 
5505
                                        thd,
 
5506
                                        MYSQL_ERROR::WARN_LEVEL_ERROR,
 
5507
                                        ER_ILLEGAL_HA_CREATE_OPTION,
 
5508
                                        "InnoDB: ROW_FORMAT=%s"
 
5509
                                        " requires innodb_file_format >"
 
5510
                                        " Antelope.",
 
5511
                                        row_format_name);
 
5512
                                        ret = FALSE;
 
5513
                        }
 
5514
 
 
5515
                        /* Cannot specify KEY_BLOCK_SIZE with
 
5516
                        ROW_FORMAT = DYNAMIC.
 
5517
                        However, we do allow COMPRESSED to be
 
5518
                        specified with KEY_BLOCK_SIZE. */
 
5519
                        if (kbs_specified
 
5520
                            && form->s->row_type == ROW_TYPE_DYNAMIC) {
 
5521
                                push_warning_printf(
 
5522
                                        thd,
 
5523
                                        MYSQL_ERROR::WARN_LEVEL_ERROR,
 
5524
                                        ER_ILLEGAL_HA_CREATE_OPTION,
 
5525
                                        "InnoDB: cannot specify"
 
5526
                                        " ROW_FORMAT = DYNAMIC with"
 
5527
                                        " KEY_BLOCK_SIZE.");
 
5528
                                        ret = FALSE;
 
5529
                        }
 
5530
 
 
5531
                        break;
 
5532
 
 
5533
                case ROW_TYPE_REDUNDANT:
 
5534
                case ROW_TYPE_COMPACT:
 
5535
                case ROW_TYPE_DEFAULT:
 
5536
                        /* Default is COMPACT. */
 
5537
                        row_format_name
 
5538
                                = form->s->row_type == ROW_TYPE_REDUNDANT
 
5539
                                ? "REDUNDANT"
 
5540
                                : "COMPACT";
 
5541
 
 
5542
                        /* Cannot specify KEY_BLOCK_SIZE with these
 
5543
                        format specifiers. */
 
5544
                        if (kbs_specified) {
 
5545
                                push_warning_printf(
 
5546
                                        thd,
 
5547
                                        MYSQL_ERROR::WARN_LEVEL_ERROR,
 
5548
                                        ER_ILLEGAL_HA_CREATE_OPTION,
 
5549
                                        "InnoDB: cannot specify"
 
5550
                                        " ROW_FORMAT = %s with"
 
5551
                                        " KEY_BLOCK_SIZE.",
 
5552
                                        row_format_name);
 
5553
                                        ret = FALSE;
 
5554
                        }
 
5555
 
 
5556
                        break;
 
5557
 
 
5558
                default:
 
5559
                        push_warning(thd,
 
5560
                                     MYSQL_ERROR::WARN_LEVEL_ERROR,
 
5561
                                     ER_ILLEGAL_HA_CREATE_OPTION,
 
5562
                                     "InnoDB: invalid ROW_FORMAT specifier.");
 
5563
                        ret = FALSE;
 
5564
 
 
5565
                }
 
5566
        }
 
5567
 
 
5568
        return(ret);
 
5569
}
 
5570
 
 
5571
/*********************************************************************
 
5572
Update create_info.  Used in SHOW CREATE TABLE et al. */
 
5573
UNIV_INTERN
 
5574
void
 
5575
ha_innobase::update_create_info(
 
5576
/*============================*/
 
5577
        HA_CREATE_INFO* create_info)    /* in/out: create info */
 
5578
{
 
5579
  if (!(create_info->used_fields & HA_CREATE_USED_AUTO)) {
 
5580
    ha_innobase::info(HA_STATUS_AUTO);
 
5581
    create_info->auto_increment_value = stats.auto_increment_value;
 
5582
  }
 
5583
}
 
5584
 
 
5585
/*********************************************************************
 
5586
Creates a new table to an InnoDB database. */
 
5587
UNIV_INTERN
 
5588
int
 
5589
ha_innobase::create(
 
5590
/*================*/
 
5591
                                        /* out: error number */
 
5592
        const char*     name,           /* in: table name */
 
5593
        TABLE*          form,           /* in: information on table
 
5594
                                        columns and indexes */
 
5595
        HA_CREATE_INFO* create_info)    /* in: more information of the
 
5596
                                        created table, contains also the
 
5597
                                        create statement string */
 
5598
{
 
5599
        int             error;
 
5600
        dict_table_t*   innobase_table;
 
5601
        trx_t*          parent_trx;
 
5602
        trx_t*          trx;
 
5603
        int             primary_key_no;
 
5604
        uint            i;
 
5605
        char            name2[FN_REFLEN];
 
5606
        char            norm_name[FN_REFLEN];
 
5607
        THD*            thd = ha_thd();
 
5608
        ib_int64_t      auto_inc_value;
 
5609
        ulint           flags;
 
5610
        /* Cache the value of innodb_file_format, in case it is
 
5611
        modified by another thread while the table is being created. */
 
5612
        const ulint     file_format = srv_file_format;
 
5613
 
 
5614
        DBUG_ENTER("ha_innobase::create");
 
5615
 
 
5616
        DBUG_ASSERT(thd != NULL);
 
5617
 
 
5618
        if (form->s->fields > 1000) {
 
5619
                /* The limit probably should be REC_MAX_N_FIELDS - 3 = 1020,
 
5620
                but we play safe here */
 
5621
 
 
5622
                DBUG_RETURN(HA_ERR_TO_BIG_ROW);
 
5623
        }
 
5624
 
 
5625
        /* Get the transaction associated with the current thd, or create one
 
5626
        if not yet created */
 
5627
 
 
5628
        parent_trx = check_trx_exists(thd);
 
5629
 
 
5630
        /* In case MySQL calls this in the middle of a SELECT query, release
 
5631
        possible adaptive hash latch to avoid deadlocks of threads */
 
5632
 
 
5633
        trx_search_latch_release_if_reserved(parent_trx);
 
5634
 
 
5635
        trx = trx_allocate_for_mysql();
 
5636
 
 
5637
        trx->mysql_thd = thd;
 
5638
        trx->mysql_query_str = thd_query(thd);
 
5639
 
 
5640
        if (thd_test_options(thd, OPTION_NO_FOREIGN_KEY_CHECKS)) {
 
5641
                trx->check_foreigns = FALSE;
 
5642
        }
 
5643
 
 
5644
        if (thd_test_options(thd, OPTION_RELAXED_UNIQUE_CHECKS)) {
 
5645
                trx->check_unique_secondary = FALSE;
 
5646
        }
 
5647
 
 
5648
        if (lower_case_table_names) {
 
5649
                srv_lower_case_table_names = TRUE;
 
5650
        } else {
 
5651
                srv_lower_case_table_names = FALSE;
 
5652
        }
 
5653
 
 
5654
        strcpy(name2, name);
 
5655
 
 
5656
        normalize_table_name(norm_name, name2);
 
5657
 
 
5658
        /* Latch the InnoDB data dictionary exclusively so that no deadlocks
 
5659
        or lock waits can happen in it during a table create operation.
 
5660
        Drop table etc. do this latching in row0mysql.c. */
 
5661
 
 
5662
        row_mysql_lock_data_dictionary(trx);
 
5663
 
 
5664
        /* Create the table definition in InnoDB */
 
5665
 
 
5666
        flags = 0;
 
5667
 
 
5668
        /* Validate create options if innodb_strict_mode is set. */
 
5669
        if (!create_options_are_valid(thd, form, create_info)) {
 
5670
                error = ER_ILLEGAL_HA_CREATE_OPTION;
 
5671
                goto cleanup;
 
5672
        }
 
5673
 
 
5674
        if (create_info->key_block_size
 
5675
            || (create_info->used_fields & HA_CREATE_USED_KEY_BLOCK_SIZE)) {
 
5676
                switch (create_info->key_block_size) {
 
5677
                case 1:
 
5678
                        flags = 1 << DICT_TF_ZSSIZE_SHIFT
 
5679
                                | DICT_TF_COMPACT
 
5680
                                | DICT_TF_FORMAT_ZIP
 
5681
                                  << DICT_TF_FORMAT_SHIFT;
 
5682
                        break;
 
5683
                case 2:
 
5684
                        flags = 2 << DICT_TF_ZSSIZE_SHIFT
 
5685
                                | DICT_TF_COMPACT
 
5686
                                | DICT_TF_FORMAT_ZIP
 
5687
                                  << DICT_TF_FORMAT_SHIFT;
 
5688
                        break;
 
5689
                case 4:
 
5690
                        flags = 3 << DICT_TF_ZSSIZE_SHIFT
 
5691
                                | DICT_TF_COMPACT
 
5692
                                | DICT_TF_FORMAT_ZIP
 
5693
                                  << DICT_TF_FORMAT_SHIFT;
 
5694
                        break;
 
5695
                case 8:
 
5696
                        flags = 4 << DICT_TF_ZSSIZE_SHIFT
 
5697
                                | DICT_TF_COMPACT
 
5698
                                | DICT_TF_FORMAT_ZIP
 
5699
                                  << DICT_TF_FORMAT_SHIFT;
 
5700
                        break;
 
5701
                case 16:
 
5702
                        flags = 5 << DICT_TF_ZSSIZE_SHIFT
 
5703
                                | DICT_TF_COMPACT
 
5704
                                | DICT_TF_FORMAT_ZIP
 
5705
                                  << DICT_TF_FORMAT_SHIFT;
 
5706
                        break;
 
5707
#if DICT_TF_ZSSIZE_MAX != 5
 
5708
# error "DICT_TF_ZSSIZE_MAX != 5"
 
5709
#endif
 
5710
                }
 
5711
 
 
5712
                if (!srv_file_per_table) {
 
5713
                        push_warning(thd, MYSQL_ERROR::WARN_LEVEL_WARN,
 
5714
                                     ER_ILLEGAL_HA_CREATE_OPTION,
 
5715
                                     "InnoDB: KEY_BLOCK_SIZE"
 
5716
                                     " requires innodb_file_per_table.");
 
5717
                        flags = 0;
 
5718
                }
 
5719
 
 
5720
                if (file_format < DICT_TF_FORMAT_ZIP) {
 
5721
                        push_warning(thd, MYSQL_ERROR::WARN_LEVEL_WARN,
 
5722
                                     ER_ILLEGAL_HA_CREATE_OPTION,
 
5723
                                     "InnoDB: KEY_BLOCK_SIZE"
 
5724
                                     " requires innodb_file_format >"
 
5725
                                     " Antelope.");
 
5726
                        flags = 0;
 
5727
                }
 
5728
 
 
5729
                if (!flags) {
 
5730
                        push_warning_printf(thd, MYSQL_ERROR::WARN_LEVEL_WARN,
 
5731
                                            ER_ILLEGAL_HA_CREATE_OPTION,
 
5732
                                            "InnoDB: ignoring"
 
5733
                                            " KEY_BLOCK_SIZE=%lu.",
 
5734
                                            create_info->key_block_size);
 
5735
                }
 
5736
        }
 
5737
 
 
5738
        if (create_info->used_fields & HA_CREATE_USED_ROW_FORMAT) {
 
5739
                if (flags) {
 
5740
                        /* KEY_BLOCK_SIZE was specified. */
 
5741
                        if (form->s->row_type != ROW_TYPE_COMPRESSED) {
 
5742
                                /* ROW_FORMAT other than COMPRESSED
 
5743
                                ignores KEY_BLOCK_SIZE.  It does not
 
5744
                                make sense to reject conflicting
 
5745
                                KEY_BLOCK_SIZE and ROW_FORMAT, because
 
5746
                                such combinations can be obtained
 
5747
                                with ALTER TABLE anyway. */
 
5748
                                push_warning_printf(
 
5749
                                        thd,
 
5750
                                        MYSQL_ERROR::WARN_LEVEL_WARN,
 
5751
                                        ER_ILLEGAL_HA_CREATE_OPTION,
 
5752
                                        "InnoDB: ignoring KEY_BLOCK_SIZE=%lu"
 
5753
                                        " unless ROW_FORMAT=COMPRESSED.",
 
5754
                                        create_info->key_block_size);
 
5755
                                flags = 0;
 
5756
                        }
 
5757
                } else {
 
5758
                        /* No KEY_BLOCK_SIZE */
 
5759
                        if (form->s->row_type == ROW_TYPE_COMPRESSED) {
 
5760
                                /* ROW_FORMAT=COMPRESSED without
 
5761
                                KEY_BLOCK_SIZE implies
 
5762
                                KEY_BLOCK_SIZE=8. */
 
5763
                                flags = 4 << DICT_TF_ZSSIZE_SHIFT
 
5764
                                        | DICT_TF_COMPACT
 
5765
                                        | DICT_TF_FORMAT_ZIP
 
5766
                                          << DICT_TF_FORMAT_SHIFT;
 
5767
                        }
 
5768
                }
 
5769
 
 
5770
                switch (form->s->row_type) {
 
5771
                        const char* row_format_name;
 
5772
                case ROW_TYPE_REDUNDANT:
 
5773
                        break;
 
5774
                case ROW_TYPE_COMPRESSED:
 
5775
                case ROW_TYPE_DYNAMIC:
 
5776
                        row_format_name
 
5777
                                = form->s->row_type == ROW_TYPE_COMPRESSED
 
5778
                                ? "COMPRESSED"
 
5779
                                : "DYNAMIC";
 
5780
 
 
5781
                        if (!srv_file_per_table) {
 
5782
                                push_warning_printf(
 
5783
                                        thd,
 
5784
                                        MYSQL_ERROR::WARN_LEVEL_WARN,
 
5785
                                        ER_ILLEGAL_HA_CREATE_OPTION,
 
5786
                                        "InnoDB: ROW_FORMAT=%s"
 
5787
                                        " requires innodb_file_per_table.",
 
5788
                                        row_format_name);
 
5789
                        } else if (file_format < DICT_TF_FORMAT_ZIP) {
 
5790
                                push_warning_printf(
 
5791
                                        thd,
 
5792
                                        MYSQL_ERROR::WARN_LEVEL_WARN,
 
5793
                                        ER_ILLEGAL_HA_CREATE_OPTION,
 
5794
                                        "InnoDB: ROW_FORMAT=%s"
 
5795
                                        " requires innodb_file_format >"
 
5796
                                        " Antelope.",
 
5797
                                        row_format_name);
 
5798
                        } else {
 
5799
                                flags |= DICT_TF_COMPACT
 
5800
                                        | (DICT_TF_FORMAT_ZIP
 
5801
                                           << DICT_TF_FORMAT_SHIFT);
 
5802
                                break;
 
5803
                        }
 
5804
 
 
5805
                        /* fall through */
 
5806
                case ROW_TYPE_NOT_USED:
 
5807
                case ROW_TYPE_FIXED:
 
5808
                default:
 
5809
                        push_warning(thd,
 
5810
                                     MYSQL_ERROR::WARN_LEVEL_WARN,
 
5811
                                     ER_ILLEGAL_HA_CREATE_OPTION,
 
5812
                                     "InnoDB: assuming ROW_FORMAT=COMPACT.");
 
5813
                case ROW_TYPE_DEFAULT:
 
5814
                case ROW_TYPE_COMPACT:
 
5815
                        flags = DICT_TF_COMPACT;
 
5816
                        break;
 
5817
                }
 
5818
        } else if (!flags) {
 
5819
                /* No KEY_BLOCK_SIZE or ROW_FORMAT specified:
 
5820
                use ROW_FORMAT=COMPACT by default. */
 
5821
                flags = DICT_TF_COMPACT;
 
5822
        }
 
5823
 
 
5824
        error = create_table_def(trx, form, norm_name,
 
5825
                create_info->options & HA_LEX_CREATE_TMP_TABLE ? name2 : NULL,
 
5826
                flags);
 
5827
 
 
5828
        if (error) {
 
5829
                goto cleanup;
 
5830
        }
 
5831
 
 
5832
        /* Look for a primary key */
 
5833
 
 
5834
        primary_key_no= (form->s->primary_key != MAX_KEY ?
 
5835
                         (int) form->s->primary_key :
 
5836
                         -1);
 
5837
 
 
5838
        /* Our function row_get_mysql_key_number_for_index assumes
 
5839
        the primary key is always number 0, if it exists */
 
5840
 
 
5841
        DBUG_ASSERT(primary_key_no == -1 || primary_key_no == 0);
 
5842
 
 
5843
        /* Create the keys */
 
5844
 
 
5845
        if (form->s->keys == 0 || primary_key_no == -1) {
 
5846
                /* Create an index which is used as the clustered index;
 
5847
                order the rows by their row id which is internally generated
 
5848
                by InnoDB */
 
5849
 
 
5850
                error = create_clustered_index_when_no_primary(
 
5851
                        trx, flags, norm_name);
 
5852
                if (error) {
 
5853
                        goto cleanup;
 
5854
                }
 
5855
        }
 
5856
 
 
5857
        if (primary_key_no != -1) {
 
5858
                /* In InnoDB the clustered index must always be created
 
5859
                first */
 
5860
                if ((error = create_index(trx, form, flags, norm_name,
 
5861
                                          (uint) primary_key_no))) {
 
5862
                        goto cleanup;
 
5863
                }
 
5864
        }
 
5865
 
 
5866
        for (i = 0; i < form->s->keys; i++) {
 
5867
 
 
5868
                if (i != (uint) primary_key_no) {
 
5869
 
 
5870
                        if ((error = create_index(trx, form, flags, norm_name,
 
5871
                                                  i))) {
 
5872
                                goto cleanup;
 
5873
                        }
 
5874
                }
 
5875
        }
 
5876
 
 
5877
        if (*trx->mysql_query_str) {
 
5878
                error = row_table_add_foreign_constraints(trx,
 
5879
                        *trx->mysql_query_str, norm_name,
 
5880
                        create_info->options & HA_LEX_CREATE_TMP_TABLE);
 
5881
 
 
5882
                error = convert_error_code_to_mysql(error, flags, NULL);
 
5883
 
 
5884
                if (error) {
 
5885
                        goto cleanup;
 
5886
                }
 
5887
        }
 
5888
 
 
5889
        innobase_commit_low(trx);
 
5890
 
 
5891
        row_mysql_unlock_data_dictionary(trx);
 
5892
 
 
5893
        /* Flush the log to reduce probability that the .frm files and
 
5894
        the InnoDB data dictionary get out-of-sync if the user runs
 
5895
        with innodb_flush_log_at_trx_commit = 0 */
 
5896
 
 
5897
        log_buffer_flush_to_disk();
 
5898
 
 
5899
        innobase_table = dict_table_get(norm_name, FALSE);
 
5900
 
 
5901
        DBUG_ASSERT(innobase_table != 0);
 
5902
 
 
5903
        /* We update the highest file format in the system table
 
5904
        space, if this table has a higher file format setting. */
 
5905
 
 
5906
        trx_sys_file_format_max_update(flags, &innobase_file_format_check);
 
5907
 
 
5908
        /* Note: We can't call update_thd() as prebuilt will not be
 
5909
        setup at this stage and so we use thd. */
 
5910
 
 
5911
        /* We need to copy the AUTOINC value from the old table if
 
5912
        this is an ALTER TABLE. */
 
5913
 
 
5914
        if (((create_info->used_fields & HA_CREATE_USED_AUTO)
 
5915
            || thd_sql_command(thd) == SQLCOM_ALTER_TABLE)
 
5916
            && create_info->auto_increment_value != 0) {
 
5917
 
 
5918
                /* Query was ALTER TABLE...AUTO_INCREMENT = x; or
 
5919
                CREATE TABLE ...AUTO_INCREMENT = x; Find out a table
 
5920
                definition from the dictionary and get the current value
 
5921
                of the auto increment field. Set a new value to the
 
5922
                auto increment field if the value is greater than the
 
5923
                maximum value in the column. */
 
5924
 
 
5925
                auto_inc_value = create_info->auto_increment_value;
 
5926
 
 
5927
                dict_table_autoinc_lock(innobase_table);
 
5928
                dict_table_autoinc_initialize(innobase_table, auto_inc_value);
 
5929
                dict_table_autoinc_unlock(innobase_table);
 
5930
        }
 
5931
 
 
5932
        /* Tell the InnoDB server that there might be work for
 
5933
        utility threads: */
 
5934
 
 
5935
        srv_active_wake_master_thread();
 
5936
 
 
5937
        trx_free_for_mysql(trx);
 
5938
 
 
5939
        DBUG_RETURN(0);
 
5940
 
 
5941
cleanup:
 
5942
        innobase_commit_low(trx);
 
5943
 
 
5944
        row_mysql_unlock_data_dictionary(trx);
 
5945
 
 
5946
        trx_free_for_mysql(trx);
 
5947
 
 
5948
        DBUG_RETURN(error);
 
5949
}
 
5950
 
 
5951
/*********************************************************************
 
5952
Discards or imports an InnoDB tablespace. */
 
5953
UNIV_INTERN
 
5954
int
 
5955
ha_innobase::discard_or_import_tablespace(
 
5956
/*======================================*/
 
5957
                                /* out: 0 == success, -1 == error */
 
5958
        my_bool discard)        /* in: TRUE if discard, else import */
 
5959
{
 
5960
        dict_table_t*   dict_table;
 
5961
        trx_t*          trx;
 
5962
        int             err;
 
5963
 
 
5964
        DBUG_ENTER("ha_innobase::discard_or_import_tablespace");
 
5965
 
 
5966
        ut_a(prebuilt->trx);
 
5967
        ut_a(prebuilt->trx->magic_n == TRX_MAGIC_N);
 
5968
        ut_a(prebuilt->trx == thd_to_trx(ha_thd()));
 
5969
 
 
5970
        dict_table = prebuilt->table;
 
5971
        trx = prebuilt->trx;
 
5972
 
 
5973
        if (discard) {
 
5974
                err = row_discard_tablespace_for_mysql(dict_table->name, trx);
 
5975
        } else {
 
5976
                err = row_import_tablespace_for_mysql(dict_table->name, trx);
 
5977
        }
 
5978
 
 
5979
        err = convert_error_code_to_mysql(err, dict_table->flags, NULL);
 
5980
 
 
5981
        DBUG_RETURN(err);
 
5982
}
 
5983
 
 
5984
/*********************************************************************
 
5985
Deletes all rows of an InnoDB table. */
 
5986
UNIV_INTERN
 
5987
int
 
5988
ha_innobase::delete_all_rows(void)
 
5989
/*==============================*/
 
5990
                                /* out: error number */
 
5991
{
 
5992
        int             error;
 
5993
 
 
5994
        DBUG_ENTER("ha_innobase::delete_all_rows");
 
5995
 
 
5996
        /* Get the transaction associated with the current thd, or create one
 
5997
        if not yet created, and update prebuilt->trx */
 
5998
 
 
5999
        update_thd(ha_thd());
 
6000
 
 
6001
        if (thd_sql_command(user_thd) != SQLCOM_TRUNCATE) {
 
6002
        fallback:
 
6003
                /* We only handle TRUNCATE TABLE t as a special case.
 
6004
                DELETE FROM t will have to use ha_innobase::delete_row(). */
 
6005
                DBUG_RETURN(my_errno=HA_ERR_WRONG_COMMAND);
 
6006
        }
 
6007
 
 
6008
        /* Truncate the table in InnoDB */
 
6009
 
 
6010
        error = row_truncate_table_for_mysql(prebuilt->table, prebuilt->trx);
 
6011
        if (error == DB_ERROR) {
 
6012
                /* Cannot truncate; resort to ha_innobase::delete_row() */
 
6013
                goto fallback;
 
6014
        }
 
6015
 
 
6016
        error = convert_error_code_to_mysql(error, prebuilt->table->flags,
 
6017
                                            NULL);
 
6018
 
 
6019
        DBUG_RETURN(error);
 
6020
}
 
6021
 
 
6022
/*********************************************************************
 
6023
Drops a table from an InnoDB database. Before calling this function,
 
6024
MySQL calls innobase_commit to commit the transaction of the current user.
 
6025
Then the current user cannot have locks set on the table. Drop table
 
6026
operation inside InnoDB will remove all locks any user has on the table
 
6027
inside InnoDB. */
 
6028
UNIV_INTERN
 
6029
int
 
6030
ha_innobase::delete_table(
 
6031
/*======================*/
 
6032
                                /* out: error number */
 
6033
        const char*     name)   /* in: table name */
 
6034
{
 
6035
        ulint   name_len;
 
6036
        int     error;
 
6037
        trx_t*  parent_trx;
 
6038
        trx_t*  trx;
 
6039
        THD     *thd = ha_thd();
 
6040
        char    norm_name[1000];
 
6041
 
 
6042
        DBUG_ENTER("ha_innobase::delete_table");
 
6043
 
 
6044
        /* Strangely, MySQL passes the table name without the '.frm'
 
6045
        extension, in contrast to ::create */
 
6046
        normalize_table_name(norm_name, name);
 
6047
 
 
6048
        if (IS_MAGIC_TABLE_AND_USER_DENIED_ACCESS(norm_name, thd)) {
 
6049
                DBUG_RETURN(HA_ERR_GENERIC);
 
6050
        }
 
6051
 
 
6052
        /* Get the transaction associated with the current thd, or create one
 
6053
        if not yet created */
 
6054
 
 
6055
        parent_trx = check_trx_exists(thd);
 
6056
 
 
6057
        /* In case MySQL calls this in the middle of a SELECT query, release
 
6058
        possible adaptive hash latch to avoid deadlocks of threads */
 
6059
 
 
6060
        trx_search_latch_release_if_reserved(parent_trx);
 
6061
 
 
6062
        if (lower_case_table_names) {
 
6063
                srv_lower_case_table_names = TRUE;
 
6064
        } else {
 
6065
                srv_lower_case_table_names = FALSE;
 
6066
        }
 
6067
 
 
6068
        trx = trx_allocate_for_mysql();
 
6069
 
 
6070
        trx->mysql_thd = thd;
 
6071
        trx->mysql_query_str = thd_query(thd);
 
6072
 
 
6073
        if (thd_test_options(thd, OPTION_NO_FOREIGN_KEY_CHECKS)) {
 
6074
                trx->check_foreigns = FALSE;
 
6075
        }
 
6076
 
 
6077
        if (thd_test_options(thd, OPTION_RELAXED_UNIQUE_CHECKS)) {
 
6078
                trx->check_unique_secondary = FALSE;
 
6079
        }
 
6080
 
 
6081
        name_len = strlen(name);
 
6082
 
 
6083
        ut_a(name_len < 1000);
 
6084
 
 
6085
        /* Drop the table in InnoDB */
 
6086
 
 
6087
        error = row_drop_table_for_mysql(norm_name, trx,
 
6088
                                         thd_sql_command(thd)
 
6089
                                         == SQLCOM_DROP_DB);
 
6090
 
 
6091
        /* Flush the log to reduce probability that the .frm files and
 
6092
        the InnoDB data dictionary get out-of-sync if the user runs
 
6093
        with innodb_flush_log_at_trx_commit = 0 */
 
6094
 
 
6095
        log_buffer_flush_to_disk();
 
6096
 
 
6097
        /* Tell the InnoDB server that there might be work for
 
6098
        utility threads: */
 
6099
 
 
6100
        srv_active_wake_master_thread();
 
6101
 
 
6102
        innobase_commit_low(trx);
 
6103
 
 
6104
        trx_free_for_mysql(trx);
 
6105
 
 
6106
        error = convert_error_code_to_mysql(error, 0, NULL);
 
6107
 
 
6108
        DBUG_RETURN(error);
 
6109
}
 
6110
 
 
6111
/*********************************************************************
 
6112
Removes all tables in the named database inside InnoDB. */
 
6113
static
 
6114
void
 
6115
innobase_drop_database(
 
6116
/*===================*/
 
6117
                        /* out: error number */
 
6118
        handlerton *hton, /* in: handlerton of Innodb */
 
6119
        char*   path)   /* in: database path; inside InnoDB the name
 
6120
                        of the last directory in the path is used as
 
6121
                        the database name: for example, in 'mysql/data/test'
 
6122
                        the database name is 'test' */
 
6123
{
 
6124
        ulint   len             = 0;
 
6125
        trx_t*  parent_trx;
 
6126
        trx_t*  trx;
 
6127
        char*   ptr;
 
6128
        int     error;
 
6129
        char*   namebuf;
 
6130
        THD*    thd             = current_thd;
 
6131
 
 
6132
        /* Get the transaction associated with the current thd, or create one
 
6133
        if not yet created */
 
6134
 
 
6135
        DBUG_ASSERT(hton == innodb_hton_ptr);
 
6136
 
 
6137
        parent_trx = check_trx_exists(thd);
 
6138
 
 
6139
        /* In case MySQL calls this in the middle of a SELECT query, release
 
6140
        possible adaptive hash latch to avoid deadlocks of threads */
 
6141
 
 
6142
        trx_search_latch_release_if_reserved(parent_trx);
 
6143
 
 
6144
        ptr = strend(path) - 2;
 
6145
 
 
6146
        while (ptr >= path && *ptr != '\\' && *ptr != '/') {
 
6147
                ptr--;
 
6148
                len++;
 
6149
        }
 
6150
 
 
6151
        ptr++;
 
6152
        namebuf = (char*) my_malloc((uint) len + 2, MYF(0));
 
6153
 
 
6154
        memcpy(namebuf, ptr, len);
 
6155
        namebuf[len] = '/';
 
6156
        namebuf[len + 1] = '\0';
 
6157
#ifdef  __WIN__
 
6158
        innobase_casedn_str(namebuf);
 
6159
#endif
 
6160
        trx = trx_allocate_for_mysql();
 
6161
        trx->mysql_thd = thd;
 
6162
        trx->mysql_query_str = thd_query(thd);
 
6163
 
 
6164
        if (thd_test_options(thd, OPTION_NO_FOREIGN_KEY_CHECKS)) {
 
6165
                trx->check_foreigns = FALSE;
 
6166
        }
 
6167
 
 
6168
        error = row_drop_database_for_mysql(namebuf, trx);
 
6169
        my_free(namebuf, MYF(0));
 
6170
 
 
6171
        /* Flush the log to reduce probability that the .frm files and
 
6172
        the InnoDB data dictionary get out-of-sync if the user runs
 
6173
        with innodb_flush_log_at_trx_commit = 0 */
 
6174
 
 
6175
        log_buffer_flush_to_disk();
 
6176
 
 
6177
        /* Tell the InnoDB server that there might be work for
 
6178
        utility threads: */
 
6179
 
 
6180
        srv_active_wake_master_thread();
 
6181
 
 
6182
        innobase_commit_low(trx);
 
6183
        trx_free_for_mysql(trx);
 
6184
}
 
6185
/*************************************************************************
 
6186
Renames an InnoDB table. */
 
6187
static
 
6188
int
 
6189
innobase_rename_table(
 
6190
/*==================*/
 
6191
                                /* out: 0 or error code */
 
6192
        trx_t*          trx,    /* in: transaction */
 
6193
        const char*     from,   /* in: old name of the table */
 
6194
        const char*     to,     /* in: new name of the table */
 
6195
        ibool           lock_and_commit)
 
6196
                                /* in: TRUE=lock data dictionary and commit */
 
6197
{
 
6198
        int     error;
 
6199
        char*   norm_to;
 
6200
        char*   norm_from;
 
6201
 
 
6202
        if (lower_case_table_names) {
 
6203
                srv_lower_case_table_names = TRUE;
 
6204
        } else {
 
6205
                srv_lower_case_table_names = FALSE;
 
6206
        }
 
6207
 
 
6208
        // Magic number 64 arbitrary
 
6209
        norm_to = (char*) my_malloc(strlen(to) + 64, MYF(0));
 
6210
        norm_from = (char*) my_malloc(strlen(from) + 64, MYF(0));
 
6211
 
 
6212
        normalize_table_name(norm_to, to);
 
6213
        normalize_table_name(norm_from, from);
 
6214
 
 
6215
        /* Serialize data dictionary operations with dictionary mutex:
 
6216
        no deadlocks can occur then in these operations */
 
6217
 
 
6218
        if (lock_and_commit) {
 
6219
                row_mysql_lock_data_dictionary(trx);
 
6220
        }
 
6221
 
 
6222
        error = row_rename_table_for_mysql(
 
6223
                norm_from, norm_to, trx, lock_and_commit);
 
6224
 
 
6225
        if (error != DB_SUCCESS) {
 
6226
                FILE* ef = dict_foreign_err_file;
 
6227
 
 
6228
                fputs("InnoDB: Renaming table ", ef);
 
6229
                ut_print_name(ef, trx, TRUE, norm_from);
 
6230
                fputs(" to ", ef);
 
6231
                ut_print_name(ef, trx, TRUE, norm_to);
 
6232
                fputs(" failed!\n", ef);
 
6233
        }
 
6234
 
 
6235
        if (lock_and_commit) {
 
6236
                row_mysql_unlock_data_dictionary(trx);
 
6237
 
 
6238
                /* Flush the log to reduce probability that the .frm
 
6239
                files and the InnoDB data dictionary get out-of-sync
 
6240
                if the user runs with innodb_flush_log_at_trx_commit = 0 */
 
6241
 
 
6242
                log_buffer_flush_to_disk();
 
6243
        }
 
6244
 
 
6245
        my_free(norm_to, MYF(0));
 
6246
        my_free(norm_from, MYF(0));
 
6247
 
 
6248
        return error;
 
6249
}
 
6250
/*************************************************************************
 
6251
Renames an InnoDB table. */
 
6252
UNIV_INTERN
 
6253
int
 
6254
ha_innobase::rename_table(
 
6255
/*======================*/
 
6256
                                /* out: 0 or error code */
 
6257
        const char*     from,   /* in: old name of the table */
 
6258
        const char*     to)     /* in: new name of the table */
 
6259
{
 
6260
        trx_t*  trx;
 
6261
        int     error;
 
6262
        trx_t*  parent_trx;
 
6263
        THD*    thd             = ha_thd();
 
6264
 
 
6265
        DBUG_ENTER("ha_innobase::rename_table");
 
6266
 
 
6267
        /* Get the transaction associated with the current thd, or create one
 
6268
        if not yet created */
 
6269
 
 
6270
        parent_trx = check_trx_exists(thd);
 
6271
 
 
6272
        /* In case MySQL calls this in the middle of a SELECT query, release
 
6273
        possible adaptive hash latch to avoid deadlocks of threads */
 
6274
 
 
6275
        trx_search_latch_release_if_reserved(parent_trx);
 
6276
 
 
6277
        trx = trx_allocate_for_mysql();
 
6278
        trx->mysql_thd = thd;
 
6279
        trx->mysql_query_str = thd_query(thd);
 
6280
 
 
6281
        if (thd_test_options(thd, OPTION_NO_FOREIGN_KEY_CHECKS)) {
 
6282
                trx->check_foreigns = FALSE;
 
6283
        }
 
6284
 
 
6285
        error = innobase_rename_table(trx, from, to, TRUE);
 
6286
 
 
6287
        /* Tell the InnoDB server that there might be work for
 
6288
        utility threads: */
 
6289
 
 
6290
        srv_active_wake_master_thread();
 
6291
 
 
6292
        innobase_commit_low(trx);
 
6293
        trx_free_for_mysql(trx);
 
6294
 
 
6295
        error = convert_error_code_to_mysql(error, 0, NULL);
 
6296
 
 
6297
        DBUG_RETURN(error);
 
6298
}
 
6299
 
 
6300
/*************************************************************************
 
6301
Estimates the number of index records in a range. */
 
6302
UNIV_INTERN
 
6303
ha_rows
 
6304
ha_innobase::records_in_range(
 
6305
/*==========================*/
 
6306
                                                /* out: estimated number of
 
6307
                                                rows */
 
6308
        uint                    keynr,          /* in: index number */
 
6309
        key_range               *min_key,       /* in: start key value of the
 
6310
                                                   range, may also be 0 */
 
6311
        key_range               *max_key)       /* in: range end key val, may
 
6312
                                                   also be 0 */
 
6313
{
 
6314
        KEY*            key;
 
6315
        dict_index_t*   index;
 
6316
        uchar*          key_val_buff2   = (uchar*) my_malloc(
 
6317
                                                  table->s->reclength
 
6318
                                        + table->s->max_key_length + 100,
 
6319
                                                                MYF(MY_FAE));
 
6320
        ulint           buff2_len = table->s->reclength
 
6321
                                        + table->s->max_key_length + 100;
 
6322
        dtuple_t*       range_start;
 
6323
        dtuple_t*       range_end;
 
6324
        ib_int64_t      n_rows;
 
6325
        ulint           mode1;
 
6326
        ulint           mode2;
 
6327
        mem_heap_t*     heap;
 
6328
 
 
6329
        DBUG_ENTER("records_in_range");
 
6330
 
 
6331
        ut_a(prebuilt->trx == thd_to_trx(ha_thd()));
 
6332
 
 
6333
        prebuilt->trx->op_info = (char*)"estimating records in index range";
 
6334
 
 
6335
        /* In case MySQL calls this in the middle of a SELECT query, release
 
6336
        possible adaptive hash latch to avoid deadlocks of threads */
 
6337
 
 
6338
        trx_search_latch_release_if_reserved(prebuilt->trx);
 
6339
 
 
6340
        active_index = keynr;
 
6341
 
 
6342
        key = table->key_info + active_index;
 
6343
 
 
6344
        index = dict_table_get_index_on_name(prebuilt->table, key->name);
 
6345
 
 
6346
        /* MySQL knows about this index and so we must be able to find it.*/
 
6347
        ut_a(index);
 
6348
 
 
6349
        heap = mem_heap_create(2 * (key->key_parts * sizeof(dfield_t)
 
6350
                                    + sizeof(dtuple_t)));
 
6351
 
 
6352
        range_start = dtuple_create(heap, key->key_parts);
 
6353
        dict_index_copy_types(range_start, index, key->key_parts);
 
6354
 
 
6355
        range_end = dtuple_create(heap, key->key_parts);
 
6356
        dict_index_copy_types(range_end, index, key->key_parts);
 
6357
 
 
6358
        row_sel_convert_mysql_key_to_innobase(
 
6359
                                range_start, (byte*) key_val_buff,
 
6360
                                (ulint)upd_and_key_val_buff_len,
 
6361
                                index,
 
6362
                                (byte*) (min_key ? min_key->key :
 
6363
                                         (const uchar*) 0),
 
6364
                                (ulint) (min_key ? min_key->length : 0),
 
6365
                                prebuilt->trx);
 
6366
 
 
6367
        row_sel_convert_mysql_key_to_innobase(
 
6368
                                range_end, (byte*) key_val_buff2,
 
6369
                                buff2_len, index,
 
6370
                                (byte*) (max_key ? max_key->key :
 
6371
                                         (const uchar*) 0),
 
6372
                                (ulint) (max_key ? max_key->length : 0),
 
6373
                                prebuilt->trx);
 
6374
 
 
6375
        mode1 = convert_search_mode_to_innobase(min_key ? min_key->flag :
 
6376
                                                HA_READ_KEY_EXACT);
 
6377
        mode2 = convert_search_mode_to_innobase(max_key ? max_key->flag :
 
6378
                                                HA_READ_KEY_EXACT);
 
6379
 
 
6380
        if (mode1 != PAGE_CUR_UNSUPP && mode2 != PAGE_CUR_UNSUPP) {
 
6381
 
 
6382
                n_rows = btr_estimate_n_rows_in_range(index, range_start,
 
6383
                                                      mode1, range_end,
 
6384
                                                      mode2);
 
6385
        } else {
 
6386
 
 
6387
                n_rows = 0;
 
6388
        }
 
6389
 
 
6390
        mem_heap_free(heap);
 
6391
 
 
6392
        my_free(key_val_buff2, MYF(0));
 
6393
 
 
6394
        prebuilt->trx->op_info = (char*)"";
 
6395
 
 
6396
        /* The MySQL optimizer seems to believe an estimate of 0 rows is
 
6397
        always accurate and may return the result 'Empty set' based on that.
 
6398
        The accuracy is not guaranteed, and even if it were, for a locking
 
6399
        read we should anyway perform the search to set the next-key lock.
 
6400
        Add 1 to the value to make sure MySQL does not make the assumption! */
 
6401
 
 
6402
        if (n_rows == 0) {
 
6403
                n_rows = 1;
 
6404
        }
 
6405
 
 
6406
        DBUG_RETURN((ha_rows) n_rows);
 
6407
}
 
6408
 
 
6409
/*************************************************************************
 
6410
Gives an UPPER BOUND to the number of rows in a table. This is used in
 
6411
filesort.cc. */
 
6412
UNIV_INTERN
 
6413
ha_rows
 
6414
ha_innobase::estimate_rows_upper_bound(void)
 
6415
/*======================================*/
 
6416
                        /* out: upper bound of rows */
 
6417
{
 
6418
        dict_index_t*   index;
 
6419
        ulonglong       estimate;
 
6420
        ulonglong       local_data_file_length;
 
6421
 
 
6422
        DBUG_ENTER("estimate_rows_upper_bound");
 
6423
 
 
6424
        /* We do not know if MySQL can call this function before calling
 
6425
        external_lock(). To be safe, update the thd of the current table
 
6426
        handle. */
 
6427
 
 
6428
        update_thd(ha_thd());
 
6429
 
 
6430
        prebuilt->trx->op_info = (char*)
 
6431
                                 "calculating upper bound for table rows";
 
6432
 
 
6433
        /* In case MySQL calls this in the middle of a SELECT query, release
 
6434
        possible adaptive hash latch to avoid deadlocks of threads */
 
6435
 
 
6436
        trx_search_latch_release_if_reserved(prebuilt->trx);
 
6437
 
 
6438
        index = dict_table_get_first_index(prebuilt->table);
 
6439
 
 
6440
        ut_a(index->stat_n_leaf_pages > 0);
 
6441
 
 
6442
        local_data_file_length =
 
6443
                ((ulonglong) index->stat_n_leaf_pages) * UNIV_PAGE_SIZE;
 
6444
 
 
6445
 
 
6446
        /* Calculate a minimum length for a clustered index record and from
 
6447
        that an upper bound for the number of rows. Since we only calculate
 
6448
        new statistics in row0mysql.c when a table has grown by a threshold
 
6449
        factor, we must add a safety factor 2 in front of the formula below. */
 
6450
 
 
6451
        estimate = 2 * local_data_file_length /
 
6452
                                         dict_index_calc_min_rec_len(index);
 
6453
 
 
6454
        prebuilt->trx->op_info = (char*)"";
 
6455
 
 
6456
        DBUG_RETURN((ha_rows) estimate);
 
6457
}
 
6458
 
 
6459
/*************************************************************************
 
6460
How many seeks it will take to read through the table. This is to be
 
6461
comparable to the number returned by records_in_range so that we can
 
6462
decide if we should scan the table or use keys. */
 
6463
UNIV_INTERN
 
6464
double
 
6465
ha_innobase::scan_time()
 
6466
/*====================*/
 
6467
                        /* out: estimated time measured in disk seeks */
 
6468
{
 
6469
        /* Since MySQL seems to favor table scans too much over index
 
6470
        searches, we pretend that a sequential read takes the same time
 
6471
        as a random disk read, that is, we do not divide the following
 
6472
        by 10, which would be physically realistic. */
 
6473
 
 
6474
        return((double) (prebuilt->table->stat_clustered_index_size));
 
6475
}
 
6476
 
 
6477
/**********************************************************************
 
6478
Calculate the time it takes to read a set of ranges through an index
 
6479
This enables us to optimise reads for clustered indexes. */
 
6480
UNIV_INTERN
 
6481
double
 
6482
ha_innobase::read_time(
 
6483
/*===================*/
 
6484
                        /* out: estimated time measured in disk seeks */
 
6485
        uint    index,  /* in: key number */
 
6486
        uint    ranges, /* in: how many ranges */
 
6487
        ha_rows rows)   /* in: estimated number of rows in the ranges */
 
6488
{
 
6489
        ha_rows total_rows;
 
6490
        double  time_for_scan;
 
6491
 
 
6492
        if (index != table->s->primary_key) {
 
6493
                /* Not clustered */
 
6494
                return(handler::read_time(index, ranges, rows));
 
6495
        }
 
6496
 
 
6497
        if (rows <= 2) {
 
6498
 
 
6499
                return((double) rows);
 
6500
        }
 
6501
 
 
6502
        /* Assume that the read time is proportional to the scan time for all
 
6503
        rows + at most one seek per range. */
 
6504
 
 
6505
        time_for_scan = scan_time();
 
6506
 
 
6507
        if ((total_rows = estimate_rows_upper_bound()) < rows) {
 
6508
 
 
6509
                return(time_for_scan);
 
6510
        }
 
6511
 
 
6512
        return(ranges + (double) rows / (double) total_rows * time_for_scan);
 
6513
}
 
6514
 
 
6515
/*************************************************************************
 
6516
Returns statistics information of the table to the MySQL interpreter,
 
6517
in various fields of the handle object. */
 
6518
UNIV_INTERN
 
6519
int
 
6520
ha_innobase::info(
 
6521
/*==============*/
 
6522
        uint flag)      /* in: what information MySQL requests */
 
6523
{
 
6524
        dict_table_t*   ib_table;
 
6525
        dict_index_t*   index;
 
6526
        ha_rows         rec_per_key;
 
6527
        ib_int64_t      n_rows;
 
6528
        ulong           j;
 
6529
        ulong           i;
 
6530
        char            path[FN_REFLEN];
 
6531
        os_file_stat_t  stat_info;
 
6532
 
 
6533
        DBUG_ENTER("info");
 
6534
 
 
6535
        /* If we are forcing recovery at a high level, we will suppress
 
6536
        statistics calculation on tables, because that may crash the
 
6537
        server if an index is badly corrupted. */
 
6538
 
 
6539
        if (srv_force_recovery >= SRV_FORCE_NO_IBUF_MERGE) {
 
6540
 
 
6541
                /* We return success (0) instead of HA_ERR_CRASHED,
 
6542
                because we want MySQL to process this query and not
 
6543
                stop, like it would do if it received the error code
 
6544
                HA_ERR_CRASHED. */
 
6545
 
 
6546
                DBUG_RETURN(0);
 
6547
        }
 
6548
 
 
6549
        /* We do not know if MySQL can call this function before calling
 
6550
        external_lock(). To be safe, update the thd of the current table
 
6551
        handle. */
 
6552
 
 
6553
        update_thd(ha_thd());
 
6554
 
 
6555
        /* In case MySQL calls this in the middle of a SELECT query, release
 
6556
        possible adaptive hash latch to avoid deadlocks of threads */
 
6557
 
 
6558
        prebuilt->trx->op_info = (char*)"returning various info to MySQL";
 
6559
 
 
6560
        trx_search_latch_release_if_reserved(prebuilt->trx);
 
6561
 
 
6562
        ib_table = prebuilt->table;
 
6563
 
 
6564
        if (flag & HA_STATUS_TIME) {
 
6565
                if (srv_stats_on_metadata) {
 
6566
                        /* In sql_show we call with this flag: update
 
6567
                        then statistics so that they are up-to-date */
 
6568
 
 
6569
                        prebuilt->trx->op_info = "updating table statistics";
 
6570
 
 
6571
                        dict_update_statistics(ib_table);
 
6572
 
 
6573
                        prebuilt->trx->op_info = "returning various info to MySQL";
 
6574
                }
 
6575
 
 
6576
                my_snprintf(path, sizeof(path), "%s/%s%s",
 
6577
                                mysql_data_home, ib_table->name, reg_ext);
 
6578
 
 
6579
                unpack_filename(path,path);
 
6580
 
 
6581
                /* Note that we do not know the access time of the table,
 
6582
                nor the CHECK TABLE time, nor the UPDATE or INSERT time. */
 
6583
 
 
6584
                if (os_file_get_status(path,&stat_info)) {
 
6585
                        stats.create_time = stat_info.ctime;
 
6586
                }
 
6587
        }
 
6588
 
 
6589
        if (flag & HA_STATUS_VARIABLE) {
 
6590
                n_rows = ib_table->stat_n_rows;
 
6591
 
 
6592
                /* Because we do not protect stat_n_rows by any mutex in a
 
6593
                delete, it is theoretically possible that the value can be
 
6594
                smaller than zero! TODO: fix this race.
 
6595
 
 
6596
                The MySQL optimizer seems to assume in a left join that n_rows
 
6597
                is an accurate estimate if it is zero. Of course, it is not,
 
6598
                since we do not have any locks on the rows yet at this phase.
 
6599
                Since SHOW TABLE STATUS seems to call this function with the
 
6600
                HA_STATUS_TIME flag set, while the left join optimizer does not
 
6601
                set that flag, we add one to a zero value if the flag is not
 
6602
                set. That way SHOW TABLE STATUS will show the best estimate,
 
6603
                while the optimizer never sees the table empty. */
 
6604
 
 
6605
                if (n_rows < 0) {
 
6606
                        n_rows = 0;
 
6607
                }
 
6608
 
 
6609
                if (n_rows == 0 && !(flag & HA_STATUS_TIME)) {
 
6610
                        n_rows++;
 
6611
                }
 
6612
 
 
6613
                /* Fix bug#29507: TRUNCATE shows too many rows affected.
 
6614
                Do not show the estimates for TRUNCATE command. */
 
6615
                if (thd_sql_command(user_thd) == SQLCOM_TRUNCATE) {
 
6616
 
 
6617
                        n_rows = 0;
 
6618
                }
 
6619
 
 
6620
                stats.records = (ha_rows)n_rows;
 
6621
                stats.deleted = 0;
 
6622
                stats.data_file_length = ((ulonglong)
 
6623
                                ib_table->stat_clustered_index_size)
 
6624
                                        * UNIV_PAGE_SIZE;
 
6625
                stats.index_file_length = ((ulonglong)
 
6626
                                ib_table->stat_sum_of_other_index_sizes)
 
6627
                                        * UNIV_PAGE_SIZE;
 
6628
                stats.delete_length =
 
6629
                        fsp_get_available_space_in_free_extents(
 
6630
                                ib_table->space) * 1024;
 
6631
                stats.check_time = 0;
 
6632
 
 
6633
                if (stats.records == 0) {
 
6634
                        stats.mean_rec_length = 0;
 
6635
                } else {
 
6636
                        stats.mean_rec_length = (ulong) (stats.data_file_length / stats.records);
 
6637
                }
 
6638
        }
 
6639
 
 
6640
        if (flag & HA_STATUS_CONST) {
 
6641
                index = dict_table_get_first_index(ib_table);
 
6642
 
 
6643
                if (prebuilt->clust_index_was_generated) {
 
6644
                        index = dict_table_get_next_index(index);
 
6645
                }
 
6646
 
 
6647
                for (i = 0; i < table->s->keys; i++) {
 
6648
                        if (index == NULL) {
 
6649
                                sql_print_error("Table %s contains fewer "
 
6650
                                                "indexes inside InnoDB than "
 
6651
                                                "are defined in the MySQL "
 
6652
                                                ".frm file. Have you mixed up "
 
6653
                                                ".frm files from different "
 
6654
                                                "installations? See "
 
6655
"http://dev.mysql.com/doc/refman/5.1/en/innodb-troubleshooting.html\n",
 
6656
 
 
6657
                                                ib_table->name);
 
6658
                                break;
 
6659
                        }
 
6660
 
 
6661
                        for (j = 0; j < table->key_info[i].key_parts; j++) {
 
6662
 
 
6663
                                if (j + 1 > index->n_uniq) {
 
6664
                                        sql_print_error(
 
6665
"Index %s of %s has %lu columns unique inside InnoDB, but MySQL is asking "
 
6666
"statistics for %lu columns. Have you mixed up .frm files from different "
 
6667
"installations? "
 
6668
"See http://dev.mysql.com/doc/refman/5.1/en/innodb-troubleshooting.html\n",
 
6669
                                                        index->name,
 
6670
                                                        ib_table->name,
 
6671
                                                        (unsigned long)
 
6672
                                                        index->n_uniq, j + 1);
 
6673
                                        break;
 
6674
                                }
 
6675
 
 
6676
                                if (index->stat_n_diff_key_vals[j + 1] == 0) {
 
6677
 
 
6678
                                        rec_per_key = stats.records;
 
6679
                                } else {
 
6680
                                        rec_per_key = (ha_rows)(stats.records /
 
6681
                                         index->stat_n_diff_key_vals[j + 1]);
 
6682
                                }
 
6683
 
 
6684
                                /* Since MySQL seems to favor table scans
 
6685
                                too much over index searches, we pretend
 
6686
                                index selectivity is 2 times better than
 
6687
                                our estimate: */
 
6688
 
 
6689
                                rec_per_key = rec_per_key / 2;
 
6690
 
 
6691
                                if (rec_per_key == 0) {
 
6692
                                        rec_per_key = 1;
 
6693
                                }
 
6694
 
 
6695
                                table->key_info[i].rec_per_key[j]=
 
6696
                                  rec_per_key >= ~(ulong) 0 ? ~(ulong) 0 :
 
6697
                                  (ulong) rec_per_key;
 
6698
                        }
 
6699
 
 
6700
                        index = dict_table_get_next_index(index);
 
6701
                }
 
6702
        }
 
6703
 
 
6704
        if (flag & HA_STATUS_ERRKEY) {
 
6705
                const dict_index_t*     err_index;
 
6706
 
 
6707
                ut_a(prebuilt->trx);
 
6708
                ut_a(prebuilt->trx->magic_n == TRX_MAGIC_N);
 
6709
 
 
6710
                err_index = trx_get_error_info(prebuilt->trx);
 
6711
 
 
6712
                if (err_index) {
 
6713
                        errkey = (unsigned int)
 
6714
                                row_get_mysql_key_number_for_index(err_index);
 
6715
                } else {
 
6716
                        errkey = (unsigned int) prebuilt->trx->error_key_num;
 
6717
                }
 
6718
        }
 
6719
 
 
6720
        if (flag & HA_STATUS_AUTO && table->found_next_number_field) {
 
6721
                ulonglong       auto_inc;
 
6722
                int             ret;
 
6723
 
 
6724
                /* The following function call can the first time fail in
 
6725
                a lock wait timeout error because it reserves the auto-inc
 
6726
                lock on the table. If it fails, then someone is already initing
 
6727
                the auto-inc counter, and the second call is guaranteed to
 
6728
                succeed. */
 
6729
 
 
6730
                ret = innobase_read_and_init_auto_inc(&auto_inc);
 
6731
 
 
6732
                if (ret != 0) {
 
6733
                        ret = innobase_read_and_init_auto_inc(&auto_inc);
 
6734
 
 
6735
                        if (ret != 0) {
 
6736
                                sql_print_error("Cannot get table %s auto-inc"
 
6737
                                                "counter value in ::info\n",
 
6738
                                                ib_table->name);
 
6739
                                auto_inc = 0;
 
6740
                        }
 
6741
                }
 
6742
 
 
6743
                stats.auto_increment_value = auto_inc;
 
6744
        }
 
6745
 
 
6746
        prebuilt->trx->op_info = (char*)"";
 
6747
 
 
6748
        DBUG_RETURN(0);
 
6749
}
 
6750
 
 
6751
/**************************************************************************
 
6752
Updates index cardinalities of the table, based on 8 random dives into
 
6753
each index tree. This does NOT calculate exact statistics on the table. */
 
6754
UNIV_INTERN
 
6755
int
 
6756
ha_innobase::analyze(
 
6757
/*=================*/
 
6758
                                        /* out: returns always 0 (success) */
 
6759
        THD*            thd,            /* in: connection thread handle */
 
6760
        HA_CHECK_OPT*   check_opt)      /* in: currently ignored */
 
6761
{
 
6762
        /* Simply call ::info() with all the flags */
 
6763
        info(HA_STATUS_TIME | HA_STATUS_CONST | HA_STATUS_VARIABLE);
 
6764
 
 
6765
        return(0);
 
6766
}
 
6767
 
 
6768
/**************************************************************************
 
6769
This is mapped to "ALTER TABLE tablename ENGINE=InnoDB", which rebuilds
 
6770
the table in MySQL. */
 
6771
UNIV_INTERN
 
6772
int
 
6773
ha_innobase::optimize(
 
6774
/*==================*/
 
6775
        THD*            thd,            /* in: connection thread handle */
 
6776
        HA_CHECK_OPT*   check_opt)      /* in: currently ignored */
 
6777
{
 
6778
        return(HA_ADMIN_TRY_ALTER);
 
6779
}
 
6780
 
 
6781
/***********************************************************************
 
6782
Tries to check that an InnoDB table is not corrupted. If corruption is
 
6783
noticed, prints to stderr information about it. In case of corruption
 
6784
may also assert a failure and crash the server. */
 
6785
UNIV_INTERN
 
6786
int
 
6787
ha_innobase::check(
 
6788
/*===============*/
 
6789
                                        /* out: HA_ADMIN_CORRUPT or
 
6790
                                        HA_ADMIN_OK */
 
6791
        THD*            thd,            /* in: user thread handle */
 
6792
        HA_CHECK_OPT*   check_opt)      /* in: check options, currently
 
6793
                                        ignored */
 
6794
{
 
6795
        ulint           ret;
 
6796
 
 
6797
        DBUG_ASSERT(thd == ha_thd());
 
6798
        ut_a(prebuilt->trx);
 
6799
        ut_a(prebuilt->trx->magic_n == TRX_MAGIC_N);
 
6800
        ut_a(prebuilt->trx == thd_to_trx(thd));
 
6801
 
 
6802
        if (prebuilt->mysql_template == NULL) {
 
6803
                /* Build the template; we will use a dummy template
 
6804
                in index scans done in checking */
 
6805
 
 
6806
                build_template(prebuilt, NULL, table, ROW_MYSQL_WHOLE_ROW);
 
6807
        }
 
6808
 
 
6809
        ret = row_check_table_for_mysql(prebuilt);
 
6810
 
 
6811
        if (ret == DB_SUCCESS) {
 
6812
                return(HA_ADMIN_OK);
 
6813
        }
 
6814
 
 
6815
        return(HA_ADMIN_CORRUPT);
 
6816
}
 
6817
 
 
6818
/*****************************************************************
 
6819
Adds information about free space in the InnoDB tablespace to a table comment
 
6820
which is printed out when a user calls SHOW TABLE STATUS. Adds also info on
 
6821
foreign keys. */
 
6822
UNIV_INTERN
 
6823
char*
 
6824
ha_innobase::update_table_comment(
 
6825
/*==============================*/
 
6826
                                /* out: table comment + InnoDB free space +
 
6827
                                info on foreign keys */
 
6828
        const char*     comment)/* in: table comment defined by user */
 
6829
{
 
6830
        uint    length = (uint) strlen(comment);
 
6831
        char*   str;
 
6832
        long    flen;
 
6833
 
 
6834
        /* We do not know if MySQL can call this function before calling
 
6835
        external_lock(). To be safe, update the thd of the current table
 
6836
        handle. */
 
6837
 
 
6838
        if (length > 64000 - 3) {
 
6839
                return((char*)comment); /* string too long */
 
6840
        }
 
6841
 
 
6842
        update_thd(ha_thd());
 
6843
 
 
6844
        prebuilt->trx->op_info = (char*)"returning table comment";
 
6845
 
 
6846
        /* In case MySQL calls this in the middle of a SELECT query, release
 
6847
        possible adaptive hash latch to avoid deadlocks of threads */
 
6848
 
 
6849
        trx_search_latch_release_if_reserved(prebuilt->trx);
 
6850
        str = NULL;
 
6851
 
 
6852
        /* output the data to a temporary file */
 
6853
 
 
6854
        mutex_enter(&srv_dict_tmpfile_mutex);
 
6855
        rewind(srv_dict_tmpfile);
 
6856
 
 
6857
        fprintf(srv_dict_tmpfile, "InnoDB free: %llu kB",
 
6858
                fsp_get_available_space_in_free_extents(
 
6859
                        prebuilt->table->space));
 
6860
 
 
6861
        dict_print_info_on_foreign_keys(FALSE, srv_dict_tmpfile,
 
6862
                                prebuilt->trx, prebuilt->table);
 
6863
        flen = ftell(srv_dict_tmpfile);
 
6864
        if (flen < 0) {
 
6865
                flen = 0;
 
6866
        } else if (length + flen + 3 > 64000) {
 
6867
                flen = 64000 - 3 - length;
 
6868
        }
 
6869
 
 
6870
        /* allocate buffer for the full string, and
 
6871
        read the contents of the temporary file */
 
6872
 
 
6873
        str = (char*) my_malloc(length + flen + 3, MYF(0));
 
6874
 
 
6875
        if (str) {
 
6876
                char* pos       = str + length;
 
6877
                if (length) {
 
6878
                        memcpy(str, comment, length);
 
6879
                        *pos++ = ';';
 
6880
                        *pos++ = ' ';
 
6881
                }
 
6882
                rewind(srv_dict_tmpfile);
 
6883
                flen = (uint) fread(pos, 1, flen, srv_dict_tmpfile);
 
6884
                pos[flen] = 0;
 
6885
        }
 
6886
 
 
6887
        mutex_exit(&srv_dict_tmpfile_mutex);
 
6888
 
 
6889
        prebuilt->trx->op_info = (char*)"";
 
6890
 
 
6891
        return(str ? str : (char*) comment);
 
6892
}
 
6893
 
 
6894
/***********************************************************************
 
6895
Gets the foreign key create info for a table stored in InnoDB. */
 
6896
UNIV_INTERN
 
6897
char*
 
6898
ha_innobase::get_foreign_key_create_info(void)
 
6899
/*==========================================*/
 
6900
                        /* out, own: character string in the form which
 
6901
                        can be inserted to the CREATE TABLE statement,
 
6902
                        MUST be freed with ::free_foreign_key_create_info */
 
6903
{
 
6904
        char*   str     = 0;
 
6905
        long    flen;
 
6906
 
 
6907
        ut_a(prebuilt != NULL);
 
6908
 
 
6909
        /* We do not know if MySQL can call this function before calling
 
6910
        external_lock(). To be safe, update the thd of the current table
 
6911
        handle. */
 
6912
 
 
6913
        update_thd(ha_thd());
 
6914
 
 
6915
        prebuilt->trx->op_info = (char*)"getting info on foreign keys";
 
6916
 
 
6917
        /* In case MySQL calls this in the middle of a SELECT query,
 
6918
        release possible adaptive hash latch to avoid
 
6919
        deadlocks of threads */
 
6920
 
 
6921
        trx_search_latch_release_if_reserved(prebuilt->trx);
 
6922
 
 
6923
        mutex_enter(&srv_dict_tmpfile_mutex);
 
6924
        rewind(srv_dict_tmpfile);
 
6925
 
 
6926
        /* output the data to a temporary file */
 
6927
        dict_print_info_on_foreign_keys(TRUE, srv_dict_tmpfile,
 
6928
                                prebuilt->trx, prebuilt->table);
 
6929
        prebuilt->trx->op_info = (char*)"";
 
6930
 
 
6931
        flen = ftell(srv_dict_tmpfile);
 
6932
        if (flen < 0) {
 
6933
                flen = 0;
 
6934
        } else if (flen > 64000 - 1) {
 
6935
                flen = 64000 - 1;
 
6936
        }
 
6937
 
 
6938
        /* allocate buffer for the string, and
 
6939
        read the contents of the temporary file */
 
6940
 
 
6941
        str = (char*) my_malloc(flen + 1, MYF(0));
 
6942
 
 
6943
        if (str) {
 
6944
                rewind(srv_dict_tmpfile);
 
6945
                flen = (uint) fread(str, 1, flen, srv_dict_tmpfile);
 
6946
                str[flen] = 0;
 
6947
        }
 
6948
 
 
6949
        mutex_exit(&srv_dict_tmpfile_mutex);
 
6950
 
 
6951
        return(str);
 
6952
}
 
6953
 
 
6954
 
 
6955
UNIV_INTERN
 
6956
int
 
6957
ha_innobase::get_foreign_key_list(THD *thd, List<FOREIGN_KEY_INFO> *f_key_list)
 
6958
{
 
6959
  dict_foreign_t* foreign;
 
6960
 
 
6961
  DBUG_ENTER("get_foreign_key_list");
 
6962
  ut_a(prebuilt != NULL);
 
6963
  update_thd(ha_thd());
 
6964
  prebuilt->trx->op_info = (char*)"getting list of foreign keys";
 
6965
  trx_search_latch_release_if_reserved(prebuilt->trx);
 
6966
  mutex_enter(&(dict_sys->mutex));
 
6967
  foreign = UT_LIST_GET_FIRST(prebuilt->table->foreign_list);
 
6968
 
 
6969
  while (foreign != NULL) {
 
6970
          uint i;
 
6971
          FOREIGN_KEY_INFO f_key_info;
 
6972
          LEX_STRING *name= 0;
 
6973
          uint ulen;
 
6974
          char uname[NAME_LEN+1];           /* Unencoded name */
 
6975
          char db_name[NAME_LEN+1];
 
6976
          const char *tmp_buff;
 
6977
 
 
6978
          tmp_buff= foreign->id;
 
6979
          i= 0;
 
6980
          while (tmp_buff[i] != '/')
 
6981
                  i++;
 
6982
          tmp_buff+= i + 1;
 
6983
          f_key_info.forein_id = thd_make_lex_string(thd, 0,
 
6984
                  tmp_buff, (uint) strlen(tmp_buff), 1);
 
6985
          tmp_buff= foreign->referenced_table_name;
 
6986
 
 
6987
          /* Database name */
 
6988
          i= 0;
 
6989
          while (tmp_buff[i] != '/')
 
6990
          {
 
6991
            db_name[i]= tmp_buff[i];
 
6992
            i++;
 
6993
          }
 
6994
          db_name[i]= 0;
 
6995
          ulen= filename_to_tablename(db_name, uname, sizeof(uname));
 
6996
          f_key_info.referenced_db = thd_make_lex_string(thd, 0,
 
6997
                  uname, ulen, 1);
 
6998
 
 
6999
          /* Table name */
 
7000
          tmp_buff+= i + 1;
 
7001
          ulen= filename_to_tablename(tmp_buff, uname, sizeof(uname));
 
7002
          f_key_info.referenced_table = thd_make_lex_string(thd, 0,
 
7003
                  uname, ulen, 1);
 
7004
 
 
7005
          for (i= 0;;) {
 
7006
                  tmp_buff= foreign->foreign_col_names[i];
 
7007
                  name = thd_make_lex_string(thd, name,
 
7008
                          tmp_buff, (uint) strlen(tmp_buff), 1);
 
7009
                  f_key_info.foreign_fields.push_back(name);
 
7010
                  tmp_buff= foreign->referenced_col_names[i];
 
7011
                  name = thd_make_lex_string(thd, name,
 
7012
                        tmp_buff, (uint) strlen(tmp_buff), 1);
 
7013
                  f_key_info.referenced_fields.push_back(name);
 
7014
                  if (++i >= foreign->n_fields)
 
7015
                          break;
 
7016
          }
 
7017
 
 
7018
          ulong length;
 
7019
          if (foreign->type & DICT_FOREIGN_ON_DELETE_CASCADE)
 
7020
          {
 
7021
            length=7;
 
7022
            tmp_buff= "CASCADE";
 
7023
          }
 
7024
          else if (foreign->type & DICT_FOREIGN_ON_DELETE_SET_NULL)
 
7025
          {
 
7026
            length=8;
 
7027
            tmp_buff= "SET NULL";
 
7028
          }
 
7029
          else if (foreign->type & DICT_FOREIGN_ON_DELETE_NO_ACTION)
 
7030
          {
 
7031
            length=9;
 
7032
            tmp_buff= "NO ACTION";
 
7033
          }
 
7034
          else
 
7035
          {
 
7036
            length=8;
 
7037
            tmp_buff= "RESTRICT";
 
7038
          }
 
7039
          f_key_info.delete_method = thd_make_lex_string(
 
7040
                  thd, f_key_info.delete_method, tmp_buff, length, 1);
 
7041
 
 
7042
 
 
7043
          if (foreign->type & DICT_FOREIGN_ON_UPDATE_CASCADE)
 
7044
          {
 
7045
            length=7;
 
7046
            tmp_buff= "CASCADE";
 
7047
          }
 
7048
          else if (foreign->type & DICT_FOREIGN_ON_UPDATE_SET_NULL)
 
7049
          {
 
7050
            length=8;
 
7051
            tmp_buff= "SET NULL";
 
7052
          }
 
7053
          else if (foreign->type & DICT_FOREIGN_ON_UPDATE_NO_ACTION)
 
7054
          {
 
7055
            length=9;
 
7056
            tmp_buff= "NO ACTION";
 
7057
          }
 
7058
          else
 
7059
          {
 
7060
            length=8;
 
7061
            tmp_buff= "RESTRICT";
 
7062
          }
 
7063
          f_key_info.update_method = thd_make_lex_string(
 
7064
                  thd, f_key_info.update_method, tmp_buff, length, 1);
 
7065
          if (foreign->referenced_index &&
 
7066
              foreign->referenced_index->name)
 
7067
          {
 
7068
            f_key_info.referenced_key_name = thd_make_lex_string(
 
7069
                    thd, f_key_info.referenced_key_name,
 
7070
                    foreign->referenced_index->name,
 
7071
                    strlen(foreign->referenced_index->name), 1);
 
7072
          }
 
7073
          else
 
7074
            f_key_info.referenced_key_name= 0;
 
7075
 
 
7076
          FOREIGN_KEY_INFO *pf_key_info = (FOREIGN_KEY_INFO *)
 
7077
                  thd_memdup(thd, &f_key_info, sizeof(FOREIGN_KEY_INFO));
 
7078
          f_key_list->push_back(pf_key_info);
 
7079
          foreign = UT_LIST_GET_NEXT(foreign_list, foreign);
 
7080
  }
 
7081
  mutex_exit(&(dict_sys->mutex));
 
7082
  prebuilt->trx->op_info = (char*)"";
 
7083
 
 
7084
  DBUG_RETURN(0);
 
7085
}
 
7086
 
 
7087
/*********************************************************************
 
7088
Checks if ALTER TABLE may change the storage engine of the table.
 
7089
Changing storage engines is not allowed for tables for which there
 
7090
are foreign key constraints (parent or child tables). */
 
7091
UNIV_INTERN
 
7092
bool
 
7093
ha_innobase::can_switch_engines(void)
 
7094
/*=================================*/
 
7095
{
 
7096
        bool    can_switch;
 
7097
 
 
7098
        DBUG_ENTER("ha_innobase::can_switch_engines");
 
7099
 
 
7100
        ut_a(prebuilt->trx == thd_to_trx(ha_thd()));
 
7101
 
 
7102
        prebuilt->trx->op_info =
 
7103
                        "determining if there are foreign key constraints";
 
7104
        row_mysql_lock_data_dictionary(prebuilt->trx);
 
7105
 
 
7106
        can_switch = !UT_LIST_GET_FIRST(prebuilt->table->referenced_list)
 
7107
                        && !UT_LIST_GET_FIRST(prebuilt->table->foreign_list);
 
7108
 
 
7109
        row_mysql_unlock_data_dictionary(prebuilt->trx);
 
7110
        prebuilt->trx->op_info = "";
 
7111
 
 
7112
        DBUG_RETURN(can_switch);
 
7113
}
 
7114
 
 
7115
/***********************************************************************
 
7116
Checks if a table is referenced by a foreign key. The MySQL manual states that
 
7117
a REPLACE is either equivalent to an INSERT, or DELETE(s) + INSERT. Only a
 
7118
delete is then allowed internally to resolve a duplicate key conflict in
 
7119
REPLACE, not an update. */
 
7120
UNIV_INTERN
 
7121
uint
 
7122
ha_innobase::referenced_by_foreign_key(void)
 
7123
/*========================================*/
 
7124
                        /* out: > 0 if referenced by a FOREIGN KEY */
 
7125
{
 
7126
        if (dict_table_is_referenced_by_foreign_key(prebuilt->table)) {
 
7127
 
 
7128
                return(1);
 
7129
        }
 
7130
 
 
7131
        return(0);
 
7132
}
 
7133
 
 
7134
/***********************************************************************
 
7135
Frees the foreign key create info for a table stored in InnoDB, if it is
 
7136
non-NULL. */
 
7137
UNIV_INTERN
 
7138
void
 
7139
ha_innobase::free_foreign_key_create_info(
 
7140
/*======================================*/
 
7141
        char*   str)    /* in, own: create info string to free  */
 
7142
{
 
7143
        if (str) {
 
7144
                my_free(str, MYF(0));
 
7145
        }
 
7146
}
 
7147
 
 
7148
/***********************************************************************
 
7149
Tells something additional to the handler about how to do things. */
 
7150
UNIV_INTERN
 
7151
int
 
7152
ha_innobase::extra(
 
7153
/*===============*/
 
7154
                           /* out: 0 or error number */
 
7155
        enum ha_extra_function operation)
 
7156
                           /* in: HA_EXTRA_FLUSH or some other flag */
 
7157
{
 
7158
        /* Warning: since it is not sure that MySQL calls external_lock
 
7159
        before calling this function, the trx field in prebuilt can be
 
7160
        obsolete! */
 
7161
 
 
7162
        switch (operation) {
 
7163
                case HA_EXTRA_FLUSH:
 
7164
                        if (prebuilt->blob_heap) {
 
7165
                                row_mysql_prebuilt_free_blob_heap(prebuilt);
 
7166
                        }
 
7167
                        break;
 
7168
                case HA_EXTRA_RESET_STATE:
 
7169
                        reset_template(prebuilt);
 
7170
                        break;
 
7171
                case HA_EXTRA_NO_KEYREAD:
 
7172
                        prebuilt->read_just_key = 0;
 
7173
                        break;
 
7174
                case HA_EXTRA_KEYREAD:
 
7175
                        prebuilt->read_just_key = 1;
 
7176
                        break;
 
7177
                case HA_EXTRA_KEYREAD_PRESERVE_FIELDS:
 
7178
                        prebuilt->keep_other_fields_on_keyread = 1;
 
7179
                        break;
 
7180
 
 
7181
                        /* IMPORTANT: prebuilt->trx can be obsolete in
 
7182
                        this method, because it is not sure that MySQL
 
7183
                        calls external_lock before this method with the
 
7184
                        parameters below.  We must not invoke update_thd()
 
7185
                        either, because the calling threads may change.
 
7186
                        CAREFUL HERE, OR MEMORY CORRUPTION MAY OCCUR! */
 
7187
                case HA_EXTRA_IGNORE_DUP_KEY:
 
7188
                        thd_to_trx(ha_thd())->duplicates |= TRX_DUP_IGNORE;
 
7189
                        break;
 
7190
                case HA_EXTRA_WRITE_CAN_REPLACE:
 
7191
                        thd_to_trx(ha_thd())->duplicates |= TRX_DUP_REPLACE;
 
7192
                        break;
 
7193
                case HA_EXTRA_WRITE_CANNOT_REPLACE:
 
7194
                        thd_to_trx(ha_thd())->duplicates &= ~TRX_DUP_REPLACE;
 
7195
                        break;
 
7196
                case HA_EXTRA_NO_IGNORE_DUP_KEY:
 
7197
                        thd_to_trx(ha_thd())->duplicates &=
 
7198
                                ~(TRX_DUP_IGNORE | TRX_DUP_REPLACE);
 
7199
                        break;
 
7200
                default:/* Do nothing */
 
7201
                        ;
 
7202
        }
 
7203
 
 
7204
        return(0);
 
7205
}
 
7206
 
 
7207
UNIV_INTERN
 
7208
int
 
7209
ha_innobase::reset()
 
7210
{
 
7211
  if (prebuilt->blob_heap) {
 
7212
    row_mysql_prebuilt_free_blob_heap(prebuilt);
 
7213
  }
 
7214
  reset_template(prebuilt);
 
7215
  return 0;
 
7216
}
 
7217
 
 
7218
 
 
7219
/**********************************************************************
 
7220
MySQL calls this function at the start of each SQL statement inside LOCK
 
7221
TABLES. Inside LOCK TABLES the ::external_lock method does not work to
 
7222
mark SQL statement borders. Note also a special case: if a temporary table
 
7223
is created inside LOCK TABLES, MySQL has not called external_lock() at all
 
7224
on that table.
 
7225
MySQL-5.0 also calls this before each statement in an execution of a stored
 
7226
procedure. To make the execution more deterministic for binlogging, MySQL-5.0
 
7227
locks all tables involved in a stored procedure with full explicit table
 
7228
locks (thd_in_lock_tables(thd) holds in store_lock()) before executing the
 
7229
procedure. */
 
7230
UNIV_INTERN
 
7231
int
 
7232
ha_innobase::start_stmt(
 
7233
/*====================*/
 
7234
                                /* out: 0 or error code */
 
7235
        THD*            thd,    /* in: handle to the user thread */
 
7236
        thr_lock_type   lock_type)
 
7237
{
 
7238
        trx_t*          trx;
 
7239
 
 
7240
        update_thd(thd);
 
7241
 
 
7242
        trx = prebuilt->trx;
 
7243
 
 
7244
        /* Here we release the search latch and the InnoDB thread FIFO ticket
 
7245
        if they were reserved. They should have been released already at the
 
7246
        end of the previous statement, but because inside LOCK TABLES the
 
7247
        lock count method does not work to mark the end of a SELECT statement,
 
7248
        that may not be the case. We MUST release the search latch before an
 
7249
        INSERT, for example. */
 
7250
 
 
7251
        innobase_release_stat_resources(trx);
 
7252
 
 
7253
        /* Reset the AUTOINC statement level counter for multi-row INSERTs. */
 
7254
        trx->n_autoinc_rows = 0;
 
7255
 
 
7256
        prebuilt->sql_stat_start = TRUE;
 
7257
        prebuilt->hint_need_to_fetch_extra_cols = 0;
 
7258
        reset_template(prebuilt);
 
7259
 
 
7260
        if (!prebuilt->mysql_has_locked) {
 
7261
                /* This handle is for a temporary table created inside
 
7262
                this same LOCK TABLES; since MySQL does NOT call external_lock
 
7263
                in this case, we must use x-row locks inside InnoDB to be
 
7264
                prepared for an update of a row */
 
7265
 
 
7266
                prebuilt->select_lock_type = LOCK_X;
 
7267
        } else {
 
7268
                if (trx->isolation_level != TRX_ISO_SERIALIZABLE
 
7269
                        && thd_sql_command(thd) == SQLCOM_SELECT
 
7270
                        && lock_type == TL_READ) {
 
7271
 
 
7272
                        /* For other than temporary tables, we obtain
 
7273
                        no lock for consistent read (plain SELECT). */
 
7274
 
 
7275
                        prebuilt->select_lock_type = LOCK_NONE;
 
7276
                } else {
 
7277
                        /* Not a consistent read: restore the
 
7278
                        select_lock_type value. The value of
 
7279
                        stored_select_lock_type was decided in:
 
7280
                        1) ::store_lock(),
 
7281
                        2) ::external_lock(),
 
7282
                        3) ::init_table_handle_for_HANDLER(), and
 
7283
                        4) ::transactional_table_lock(). */
 
7284
 
 
7285
                        prebuilt->select_lock_type =
 
7286
                                prebuilt->stored_select_lock_type;
 
7287
                }
 
7288
        }
 
7289
 
 
7290
        trx->detailed_error[0] = '\0';
 
7291
 
 
7292
        /* Set the MySQL flag to mark that there is an active transaction */
 
7293
        if (trx->active_trans == 0) {
 
7294
 
 
7295
                innobase_register_trx_and_stmt(ht, thd);
 
7296
                trx->active_trans = 1;
 
7297
        } else {
 
7298
                innobase_register_stmt(ht, thd);
 
7299
        }
 
7300
 
 
7301
        return(0);
 
7302
}
 
7303
 
 
7304
/**********************************************************************
 
7305
Maps a MySQL trx isolation level code to the InnoDB isolation level code */
 
7306
inline
 
7307
ulint
 
7308
innobase_map_isolation_level(
 
7309
/*=========================*/
 
7310
                                        /* out: InnoDB isolation level */
 
7311
        enum_tx_isolation       iso)    /* in: MySQL isolation level code */
 
7312
{
 
7313
        switch(iso) {
 
7314
                case ISO_REPEATABLE_READ: return(TRX_ISO_REPEATABLE_READ);
 
7315
                case ISO_READ_COMMITTED: return(TRX_ISO_READ_COMMITTED);
 
7316
                case ISO_SERIALIZABLE: return(TRX_ISO_SERIALIZABLE);
 
7317
                case ISO_READ_UNCOMMITTED: return(TRX_ISO_READ_UNCOMMITTED);
 
7318
                default: ut_a(0); return(0);
 
7319
        }
 
7320
}
 
7321
 
 
7322
/**********************************************************************
 
7323
As MySQL will execute an external lock for every new table it uses when it
 
7324
starts to process an SQL statement (an exception is when MySQL calls
 
7325
start_stmt for the handle) we can use this function to store the pointer to
 
7326
the THD in the handle. We will also use this function to communicate
 
7327
to InnoDB that a new SQL statement has started and that we must store a
 
7328
savepoint to our transaction handle, so that we are able to roll back
 
7329
the SQL statement in case of an error. */
 
7330
UNIV_INTERN
 
7331
int
 
7332
ha_innobase::external_lock(
 
7333
/*=======================*/
 
7334
                                /* out: 0 */
 
7335
        THD*    thd,            /* in: handle to the user thread */
 
7336
        int     lock_type)      /* in: lock type */
 
7337
{
 
7338
        trx_t*          trx;
 
7339
 
 
7340
        DBUG_ENTER("ha_innobase::external_lock");
 
7341
        DBUG_PRINT("enter",("lock_type: %d", lock_type));
 
7342
 
 
7343
        update_thd(thd);
 
7344
 
 
7345
        /* Statement based binlogging does not work in isolation level
 
7346
        READ UNCOMMITTED and READ COMMITTED since the necessary
 
7347
        locks cannot be taken. In this case, we print an
 
7348
        informative error message and return with an error. */
 
7349
        if (lock_type == F_WRLCK)
 
7350
        {
 
7351
                ulong const binlog_format= thd_binlog_format(thd);
 
7352
                ulong const tx_isolation = thd_tx_isolation(current_thd);
 
7353
                if (tx_isolation <= ISO_READ_COMMITTED &&
 
7354
                    binlog_format == BINLOG_FORMAT_STMT)
 
7355
                {
 
7356
                        char buf[256];
 
7357
                        my_snprintf(buf, sizeof(buf),
 
7358
                                    "Transaction level '%s' in"
 
7359
                                    " InnoDB is not safe for binlog mode '%s'",
 
7360
                                    tx_isolation_names[tx_isolation],
 
7361
                                    binlog_format_names[binlog_format]);
 
7362
                        my_error(ER_BINLOG_LOGGING_IMPOSSIBLE, MYF(0), buf);
 
7363
                        DBUG_RETURN(HA_ERR_LOGGING_IMPOSSIBLE);
 
7364
                }
 
7365
        }
 
7366
 
 
7367
 
 
7368
        trx = prebuilt->trx;
 
7369
 
 
7370
        prebuilt->sql_stat_start = TRUE;
 
7371
        prebuilt->hint_need_to_fetch_extra_cols = 0;
 
7372
 
 
7373
        reset_template(prebuilt);
 
7374
 
 
7375
        if (lock_type == F_WRLCK) {
 
7376
 
 
7377
                /* If this is a SELECT, then it is in UPDATE TABLE ...
 
7378
                or SELECT ... FOR UPDATE */
 
7379
                prebuilt->select_lock_type = LOCK_X;
 
7380
                prebuilt->stored_select_lock_type = LOCK_X;
 
7381
        }
 
7382
 
 
7383
        if (lock_type != F_UNLCK) {
 
7384
                /* MySQL is setting a new table lock */
 
7385
 
 
7386
                trx->detailed_error[0] = '\0';
 
7387
 
 
7388
                /* Set the MySQL flag to mark that there is an active
 
7389
                transaction */
 
7390
                if (trx->active_trans == 0) {
 
7391
 
 
7392
                        innobase_register_trx_and_stmt(ht, thd);
 
7393
                        trx->active_trans = 1;
 
7394
                } else if (trx->n_mysql_tables_in_use == 0) {
 
7395
                        innobase_register_stmt(ht, thd);
 
7396
                }
 
7397
 
 
7398
                if (trx->isolation_level == TRX_ISO_SERIALIZABLE
 
7399
                        && prebuilt->select_lock_type == LOCK_NONE
 
7400
                        && thd_test_options(thd,
 
7401
                                OPTION_NOT_AUTOCOMMIT | OPTION_BEGIN)) {
 
7402
 
 
7403
                        /* To get serializable execution, we let InnoDB
 
7404
                        conceptually add 'LOCK IN SHARE MODE' to all SELECTs
 
7405
                        which otherwise would have been consistent reads. An
 
7406
                        exception is consistent reads in the AUTOCOMMIT=1 mode:
 
7407
                        we know that they are read-only transactions, and they
 
7408
                        can be serialized also if performed as consistent
 
7409
                        reads. */
 
7410
 
 
7411
                        prebuilt->select_lock_type = LOCK_S;
 
7412
                        prebuilt->stored_select_lock_type = LOCK_S;
 
7413
                }
 
7414
 
 
7415
                /* Starting from 4.1.9, no InnoDB table lock is taken in LOCK
 
7416
                TABLES if AUTOCOMMIT=1. It does not make much sense to acquire
 
7417
                an InnoDB table lock if it is released immediately at the end
 
7418
                of LOCK TABLES, and InnoDB's table locks in that case cause
 
7419
                VERY easily deadlocks.
 
7420
 
 
7421
                We do not set InnoDB table locks if user has not explicitly
 
7422
                requested a table lock. Note that thd_in_lock_tables(thd)
 
7423
                can hold in some cases, e.g., at the start of a stored
 
7424
                procedure call (SQLCOM_CALL). */
 
7425
 
 
7426
                if (prebuilt->select_lock_type != LOCK_NONE) {
 
7427
 
 
7428
                        if (thd_sql_command(thd) == SQLCOM_LOCK_TABLES
 
7429
                            && THDVAR(thd, table_locks)
 
7430
                            && thd_test_options(thd, OPTION_NOT_AUTOCOMMIT)
 
7431
                            && thd_in_lock_tables(thd)) {
 
7432
 
 
7433
                                ulint   error = row_lock_table_for_mysql(
 
7434
                                        prebuilt, NULL, 0);
 
7435
 
 
7436
                                if (error != DB_SUCCESS) {
 
7437
                                        error = convert_error_code_to_mysql(
 
7438
                                                (int) error, 0, thd);
 
7439
                                        DBUG_RETURN((int) error);
 
7440
                                }
 
7441
                        }
 
7442
 
 
7443
                        trx->mysql_n_tables_locked++;
 
7444
                }
 
7445
 
 
7446
                trx->n_mysql_tables_in_use++;
 
7447
                prebuilt->mysql_has_locked = TRUE;
 
7448
 
 
7449
                DBUG_RETURN(0);
 
7450
        }
 
7451
 
 
7452
        /* MySQL is releasing a table lock */
 
7453
 
 
7454
        trx->n_mysql_tables_in_use--;
 
7455
        prebuilt->mysql_has_locked = FALSE;
 
7456
 
 
7457
        /* Release a possible FIFO ticket and search latch. Since we
 
7458
        may reserve the kernel mutex, we have to release the search
 
7459
        system latch first to obey the latching order. */
 
7460
 
 
7461
        innobase_release_stat_resources(trx);
 
7462
 
 
7463
        /* If the MySQL lock count drops to zero we know that the current SQL
 
7464
        statement has ended */
 
7465
 
 
7466
        if (trx->n_mysql_tables_in_use == 0) {
 
7467
 
 
7468
                trx->mysql_n_tables_locked = 0;
 
7469
                prebuilt->used_in_HANDLER = FALSE;
 
7470
 
 
7471
                if (!thd_test_options(thd, OPTION_NOT_AUTOCOMMIT | OPTION_BEGIN)) {
 
7472
                        if (trx->active_trans != 0) {
 
7473
                                innobase_commit(ht, thd, TRUE);
 
7474
                        }
 
7475
                } else {
 
7476
                        if (trx->isolation_level <= TRX_ISO_READ_COMMITTED
 
7477
                                                && trx->global_read_view) {
 
7478
 
 
7479
                                /* At low transaction isolation levels we let
 
7480
                                each consistent read set its own snapshot */
 
7481
 
 
7482
                                read_view_close_for_mysql(trx);
 
7483
                        }
 
7484
                }
 
7485
        }
 
7486
 
 
7487
        DBUG_RETURN(0);
 
7488
}
 
7489
 
 
7490
/**********************************************************************
 
7491
With this function MySQL request a transactional lock to a table when
 
7492
user issued query LOCK TABLES..WHERE ENGINE = InnoDB. */
 
7493
UNIV_INTERN
 
7494
int
 
7495
ha_innobase::transactional_table_lock(
 
7496
/*==================================*/
 
7497
                                /* out: error code */
 
7498
        THD*    thd,            /* in: handle to the user thread */
 
7499
        int     lock_type)      /* in: lock type */
 
7500
{
 
7501
        trx_t*          trx;
 
7502
 
 
7503
        DBUG_ENTER("ha_innobase::transactional_table_lock");
 
7504
        DBUG_PRINT("enter",("lock_type: %d", lock_type));
 
7505
 
 
7506
        /* We do not know if MySQL can call this function before calling
 
7507
        external_lock(). To be safe, update the thd of the current table
 
7508
        handle. */
 
7509
 
 
7510
        update_thd(thd);
 
7511
 
 
7512
        if (prebuilt->table->ibd_file_missing && !thd_tablespace_op(thd)) {
 
7513
                ut_print_timestamp(stderr);
 
7514
                fprintf(stderr,
 
7515
                        "  InnoDB: MySQL is trying to use a table handle"
 
7516
                        " but the .ibd file for\n"
 
7517
                        "InnoDB: table %s does not exist.\n"
 
7518
                        "InnoDB: Have you deleted the .ibd file"
 
7519
                        " from the database directory under\n"
 
7520
                        "InnoDB: the MySQL datadir?"
 
7521
                        "InnoDB: See"
 
7522
                        " http://dev.mysql.com/doc/refman/5.1/en/innodb-troubleshooting.html\n"
 
7523
                        "InnoDB: how you can resolve the problem.\n",
 
7524
                        prebuilt->table->name);
 
7525
                DBUG_RETURN(HA_ERR_CRASHED);
 
7526
        }
 
7527
 
 
7528
        trx = prebuilt->trx;
 
7529
 
 
7530
        prebuilt->sql_stat_start = TRUE;
 
7531
        prebuilt->hint_need_to_fetch_extra_cols = 0;
 
7532
 
 
7533
        reset_template(prebuilt);
 
7534
 
 
7535
        if (lock_type == F_WRLCK) {
 
7536
                prebuilt->select_lock_type = LOCK_X;
 
7537
                prebuilt->stored_select_lock_type = LOCK_X;
 
7538
        } else if (lock_type == F_RDLCK) {
 
7539
                prebuilt->select_lock_type = LOCK_S;
 
7540
                prebuilt->stored_select_lock_type = LOCK_S;
 
7541
        } else {
 
7542
                ut_print_timestamp(stderr);
 
7543
                fprintf(stderr, "  InnoDB error:\n"
 
7544
"MySQL is trying to set transactional table lock with corrupted lock type\n"
 
7545
"to table %s, lock type %d does not exist.\n",
 
7546
                                prebuilt->table->name, lock_type);
 
7547
                DBUG_RETURN(HA_ERR_CRASHED);
 
7548
        }
 
7549
 
 
7550
        /* MySQL is setting a new transactional table lock */
 
7551
 
 
7552
        /* Set the MySQL flag to mark that there is an active transaction */
 
7553
        if (trx->active_trans == 0) {
 
7554
 
 
7555
                innobase_register_trx_and_stmt(ht, thd);
 
7556
                trx->active_trans = 1;
 
7557
        }
 
7558
 
 
7559
        if (THDVAR(thd, table_locks) && thd_in_lock_tables(thd)) {
 
7560
                ulint   error = DB_SUCCESS;
 
7561
 
 
7562
                error = row_lock_table_for_mysql(prebuilt, NULL, 0);
 
7563
 
 
7564
                if (error != DB_SUCCESS) {
 
7565
                        error = convert_error_code_to_mysql(
 
7566
                                (int) error, prebuilt->table->flags, thd);
 
7567
                        DBUG_RETURN((int) error);
 
7568
                }
 
7569
 
 
7570
                if (thd_test_options(thd, OPTION_NOT_AUTOCOMMIT | OPTION_BEGIN)) {
 
7571
 
 
7572
                        /* Store the current undo_no of the transaction
 
7573
                        so that we know where to roll back if we have
 
7574
                        to roll back the next SQL statement */
 
7575
 
 
7576
                        trx_mark_sql_stat_end(trx);
 
7577
                }
 
7578
        }
 
7579
 
 
7580
        DBUG_RETURN(0);
 
7581
}
 
7582
 
 
7583
/****************************************************************************
 
7584
Here we export InnoDB status variables to MySQL.  */
 
7585
static
 
7586
int
 
7587
innodb_export_status()
 
7588
/*==================*/
 
7589
{
 
7590
        if (innodb_inited) {
 
7591
                srv_export_innodb_status();
 
7592
        }
 
7593
 
 
7594
        return(0);
 
7595
}
 
7596
 
 
7597
/****************************************************************************
 
7598
Implements the SHOW INNODB STATUS command. Sends the output of the InnoDB
 
7599
Monitor to the client. */
 
7600
static
 
7601
bool
 
7602
innodb_show_status(
 
7603
/*===============*/
 
7604
        handlerton*     hton,   /* in: the innodb handlerton */
 
7605
        THD*    thd,    /* in: the MySQL query thread of the caller */
 
7606
        stat_print_fn *stat_print)
 
7607
{
 
7608
        trx_t*                  trx;
 
7609
        static const char       truncated_msg[] = "... truncated...\n";
 
7610
        const long              MAX_STATUS_SIZE = 64000;
 
7611
        ulint                   trx_list_start = ULINT_UNDEFINED;
 
7612
        ulint                   trx_list_end = ULINT_UNDEFINED;
 
7613
 
 
7614
        DBUG_ENTER("innodb_show_status");
 
7615
        DBUG_ASSERT(hton == innodb_hton_ptr);
 
7616
 
 
7617
        trx = check_trx_exists(thd);
 
7618
 
 
7619
        innobase_release_stat_resources(trx);
 
7620
 
 
7621
        /* We let the InnoDB Monitor to output at most MAX_STATUS_SIZE
 
7622
        bytes of text. */
 
7623
 
 
7624
        long    flen, usable_len;
 
7625
        char*   str;
 
7626
 
 
7627
        mutex_enter(&srv_monitor_file_mutex);
 
7628
        rewind(srv_monitor_file);
 
7629
        srv_printf_innodb_monitor(srv_monitor_file,
 
7630
                                &trx_list_start, &trx_list_end);
 
7631
        flen = ftell(srv_monitor_file);
 
7632
        os_file_set_eof(srv_monitor_file);
 
7633
 
 
7634
        if (flen < 0) {
 
7635
                flen = 0;
 
7636
        }
 
7637
 
 
7638
        if (flen > MAX_STATUS_SIZE) {
 
7639
                usable_len = MAX_STATUS_SIZE;
 
7640
        } else {
 
7641
                usable_len = flen;
 
7642
        }
 
7643
 
 
7644
        /* allocate buffer for the string, and
 
7645
        read the contents of the temporary file */
 
7646
 
 
7647
        if (!(str = (char*) my_malloc(usable_len + 1, MYF(0)))) {
 
7648
          mutex_exit(&srv_monitor_file_mutex);
 
7649
          DBUG_RETURN(TRUE);
 
7650
        }
 
7651
 
 
7652
        rewind(srv_monitor_file);
 
7653
        if (flen < MAX_STATUS_SIZE) {
 
7654
                /* Display the entire output. */
 
7655
                flen = (long) fread(str, 1, flen, srv_monitor_file);
 
7656
        } else if (trx_list_end < (ulint) flen
 
7657
                        && trx_list_start < trx_list_end
 
7658
                        && trx_list_start + (flen - trx_list_end)
 
7659
                        < MAX_STATUS_SIZE - sizeof truncated_msg - 1) {
 
7660
                /* Omit the beginning of the list of active transactions. */
 
7661
                long len = (long) fread(str, 1, trx_list_start, srv_monitor_file);
 
7662
                memcpy(str + len, truncated_msg, sizeof truncated_msg - 1);
 
7663
                len += sizeof truncated_msg - 1;
 
7664
                usable_len = (MAX_STATUS_SIZE - 1) - len;
 
7665
                fseek(srv_monitor_file, flen - usable_len, SEEK_SET);
 
7666
                len += (long) fread(str + len, 1, usable_len, srv_monitor_file);
 
7667
                flen = len;
 
7668
        } else {
 
7669
                /* Omit the end of the output. */
 
7670
                flen = (long) fread(str, 1, MAX_STATUS_SIZE - 1, srv_monitor_file);
 
7671
        }
 
7672
 
 
7673
        mutex_exit(&srv_monitor_file_mutex);
 
7674
 
 
7675
        bool result = FALSE;
 
7676
 
 
7677
        if (stat_print(thd, innobase_hton_name, strlen(innobase_hton_name),
 
7678
                        STRING_WITH_LEN(""), str, flen)) {
 
7679
                result= TRUE;
 
7680
        }
 
7681
        my_free(str, MYF(0));
 
7682
 
 
7683
        DBUG_RETURN(FALSE);
 
7684
}
 
7685
 
 
7686
/****************************************************************************
 
7687
Implements the SHOW MUTEX STATUS command. . */
 
7688
static
 
7689
bool
 
7690
innodb_mutex_show_status(
 
7691
/*=====================*/
 
7692
        handlerton*     hton,   /* in: the innodb handlerton */
 
7693
        THD*            thd,            /* in: the MySQL query thread of the
 
7694
                                        caller */
 
7695
        stat_print_fn*  stat_print)
 
7696
{
 
7697
        char buf1[IO_SIZE], buf2[IO_SIZE];
 
7698
        mutex_t*  mutex;
 
7699
#ifdef UNIV_DEBUG
 
7700
        ulint     rw_lock_count= 0;
 
7701
        ulint     rw_lock_count_spin_loop= 0;
 
7702
        ulint     rw_lock_count_spin_rounds= 0;
 
7703
        ulint     rw_lock_count_os_wait= 0;
 
7704
        ulint     rw_lock_count_os_yield= 0;
 
7705
        ulonglong rw_lock_wait_time= 0;
 
7706
#endif /* UNIV_DEBUG */
 
7707
        uint      hton_name_len= strlen(innobase_hton_name), buf1len, buf2len;
 
7708
        DBUG_ENTER("innodb_mutex_show_status");
 
7709
        DBUG_ASSERT(hton == innodb_hton_ptr);
 
7710
 
 
7711
        mutex_enter(&mutex_list_mutex);
 
7712
 
 
7713
        mutex = UT_LIST_GET_FIRST(mutex_list);
 
7714
 
 
7715
        while (mutex != NULL) {
 
7716
#ifdef UNIV_DEBUG
 
7717
                if (mutex->mutex_type != 1) {
 
7718
                        if (mutex->count_using > 0) {
 
7719
                                buf1len= my_snprintf(buf1, sizeof(buf1),
 
7720
                                        "%s:%s",
 
7721
                                        mutex->cmutex_name, mutex->cfile_name);
 
7722
                                buf2len= my_snprintf(buf2, sizeof(buf2),
 
7723
                                        "count=%lu, spin_waits=%lu,"
 
7724
                                        " spin_rounds=%lu, "
 
7725
                                        "os_waits=%lu, os_yields=%lu,"
 
7726
                                        " os_wait_times=%lu",
 
7727
                                        mutex->count_using,
 
7728
                                        mutex->count_spin_loop,
 
7729
                                        mutex->count_spin_rounds,
 
7730
                                        mutex->count_os_wait,
 
7731
                                        mutex->count_os_yield,
 
7732
                                        (ulong) (mutex->lspent_time/1000));
 
7733
 
 
7734
                                if (stat_print(thd, innobase_hton_name,
 
7735
                                                hton_name_len, buf1, buf1len,
 
7736
                                                buf2, buf2len)) {
 
7737
                                        mutex_exit(&mutex_list_mutex);
 
7738
                                        DBUG_RETURN(1);
 
7739
                                }
 
7740
                        }
 
7741
                }
 
7742
                else {
 
7743
                        rw_lock_count += mutex->count_using;
 
7744
                        rw_lock_count_spin_loop += mutex->count_spin_loop;
 
7745
                        rw_lock_count_spin_rounds += mutex->count_spin_rounds;
 
7746
                        rw_lock_count_os_wait += mutex->count_os_wait;
 
7747
                        rw_lock_count_os_yield += mutex->count_os_yield;
 
7748
                        rw_lock_wait_time += mutex->lspent_time;
 
7749
                }
 
7750
#else /* UNIV_DEBUG */
 
7751
                buf1len= my_snprintf(buf1, sizeof(buf1), "%s:%lu",
 
7752
                                     mutex->cfile_name, (ulong) mutex->cline);
 
7753
                buf2len= my_snprintf(buf2, sizeof(buf2), "os_waits=%lu",
 
7754
                                     mutex->count_os_wait);
 
7755
 
 
7756
                if (stat_print(thd, innobase_hton_name,
 
7757
                               hton_name_len, buf1, buf1len,
 
7758
                               buf2, buf2len)) {
 
7759
                        mutex_exit(&mutex_list_mutex);
 
7760
                        DBUG_RETURN(1);
 
7761
                }
 
7762
#endif /* UNIV_DEBUG */
 
7763
 
 
7764
                mutex = UT_LIST_GET_NEXT(list, mutex);
 
7765
        }
 
7766
 
 
7767
        mutex_exit(&mutex_list_mutex);
 
7768
 
 
7769
#ifdef UNIV_DEBUG
 
7770
        buf2len= my_snprintf(buf2, sizeof(buf2),
 
7771
                "count=%lu, spin_waits=%lu, spin_rounds=%lu, "
 
7772
                "os_waits=%lu, os_yields=%lu, os_wait_times=%lu",
 
7773
                rw_lock_count, rw_lock_count_spin_loop,
 
7774
                rw_lock_count_spin_rounds,
 
7775
                rw_lock_count_os_wait, rw_lock_count_os_yield,
 
7776
                (ulong) (rw_lock_wait_time/1000));
 
7777
 
 
7778
        if (stat_print(thd, innobase_hton_name, hton_name_len,
 
7779
                        STRING_WITH_LEN("rw_lock_mutexes"), buf2, buf2len)) {
 
7780
                DBUG_RETURN(1);
 
7781
        }
 
7782
#endif /* UNIV_DEBUG */
 
7783
 
 
7784
        DBUG_RETURN(FALSE);
 
7785
}
 
7786
 
 
7787
static
 
7788
bool innobase_show_status(handlerton *hton, THD* thd, 
 
7789
                          stat_print_fn* stat_print,
 
7790
                          enum ha_stat_type stat_type)
 
7791
{
 
7792
        DBUG_ASSERT(hton == innodb_hton_ptr);
 
7793
 
 
7794
        switch (stat_type) {
 
7795
        case HA_ENGINE_STATUS:
 
7796
                return innodb_show_status(hton, thd, stat_print);
 
7797
        case HA_ENGINE_MUTEX:
 
7798
                return innodb_mutex_show_status(hton, thd, stat_print);
 
7799
        default:
 
7800
                return(FALSE);
 
7801
        }
 
7802
}
 
7803
 
 
7804
 
 
7805
/****************************************************************************
 
7806
 Handling the shared INNOBASE_SHARE structure that is needed to provide table
 
7807
 locking.
 
7808
****************************************************************************/
 
7809
 
 
7810
static uchar* innobase_get_key(INNOBASE_SHARE* share, size_t *length,
 
7811
        my_bool not_used __attribute__((unused)))
 
7812
{
 
7813
        *length=share->table_name_length;
 
7814
 
 
7815
        return (uchar*) share->table_name;
 
7816
}
 
7817
 
 
7818
static INNOBASE_SHARE* get_share(const char* table_name)
 
7819
{
 
7820
        INNOBASE_SHARE *share;
 
7821
        pthread_mutex_lock(&innobase_share_mutex);
 
7822
        uint length=(uint) strlen(table_name);
 
7823
 
 
7824
        if (!(share=(INNOBASE_SHARE*) hash_search(&innobase_open_tables,
 
7825
                                (uchar*) table_name,
 
7826
                                length))) {
 
7827
 
 
7828
                share = (INNOBASE_SHARE *) my_malloc(sizeof(*share)+length+1,
 
7829
                        MYF(MY_FAE | MY_ZEROFILL));
 
7830
 
 
7831
                share->table_name_length=length;
 
7832
                share->table_name=(char*) (share+1);
 
7833
                strmov(share->table_name,table_name);
 
7834
 
 
7835
                if (my_hash_insert(&innobase_open_tables,
 
7836
                                (uchar*) share)) {
 
7837
                        pthread_mutex_unlock(&innobase_share_mutex);
 
7838
                        my_free(share,0);
 
7839
 
 
7840
                        return(0);
 
7841
                }
 
7842
 
 
7843
                thr_lock_init(&share->lock);
 
7844
                pthread_mutex_init(&share->mutex,MY_MUTEX_INIT_FAST);
 
7845
        }
 
7846
 
 
7847
        share->use_count++;
 
7848
        pthread_mutex_unlock(&innobase_share_mutex);
 
7849
 
 
7850
        return(share);
 
7851
}
 
7852
 
 
7853
static void free_share(INNOBASE_SHARE* share)
 
7854
{
 
7855
        pthread_mutex_lock(&innobase_share_mutex);
 
7856
 
 
7857
        if (!--share->use_count) {
 
7858
                hash_delete(&innobase_open_tables, (uchar*) share);
 
7859
                thr_lock_delete(&share->lock);
 
7860
                pthread_mutex_destroy(&share->mutex);
 
7861
                my_free(share, MYF(0));
 
7862
        }
 
7863
 
 
7864
        pthread_mutex_unlock(&innobase_share_mutex);
 
7865
}
 
7866
 
 
7867
/*********************************************************************
 
7868
Converts a MySQL table lock stored in the 'lock' field of the handle to
 
7869
a proper type before storing pointer to the lock into an array of pointers.
 
7870
MySQL also calls this if it wants to reset some table locks to a not-locked
 
7871
state during the processing of an SQL query. An example is that during a
 
7872
SELECT the read lock is released early on the 'const' tables where we only
 
7873
fetch one row. MySQL does not call this when it releases all locks at the
 
7874
end of an SQL statement. */
 
7875
UNIV_INTERN
 
7876
THR_LOCK_DATA**
 
7877
ha_innobase::store_lock(
 
7878
/*====================*/
 
7879
                                                /* out: pointer to the next
 
7880
                                                element in the 'to' array */
 
7881
        THD*                    thd,            /* in: user thread handle */
 
7882
        THR_LOCK_DATA**         to,             /* in: pointer to an array
 
7883
                                                of pointers to lock structs;
 
7884
                                                pointer to the 'lock' field
 
7885
                                                of current handle is stored
 
7886
                                                next to this array */
 
7887
        enum thr_lock_type      lock_type)      /* in: lock type to store in
 
7888
                                                'lock'; this may also be
 
7889
                                                TL_IGNORE */
 
7890
{
 
7891
        trx_t*          trx;
 
7892
 
 
7893
        /* Note that trx in this function is NOT necessarily prebuilt->trx
 
7894
        because we call update_thd() later, in ::external_lock()! Failure to
 
7895
        understand this caused a serious memory corruption bug in 5.1.11. */
 
7896
 
 
7897
        trx = check_trx_exists(thd);
 
7898
 
 
7899
        /* NOTE: MySQL can call this function with lock 'type' TL_IGNORE!
 
7900
        Be careful to ignore TL_IGNORE if we are going to do something with
 
7901
        only 'real' locks! */
 
7902
 
 
7903
        /* If no MySQL table is in use, we need to set the isolation level
 
7904
        of the transaction. */
 
7905
 
 
7906
        if (lock_type != TL_IGNORE
 
7907
            && trx->n_mysql_tables_in_use == 0) {
 
7908
                trx->isolation_level = innobase_map_isolation_level(
 
7909
                        (enum_tx_isolation) thd_tx_isolation(thd));
 
7910
 
 
7911
                if (trx->isolation_level <= TRX_ISO_READ_COMMITTED
 
7912
                    && trx->global_read_view) {
 
7913
 
 
7914
                        /* At low transaction isolation levels we let
 
7915
                        each consistent read set its own snapshot */
 
7916
 
 
7917
                        read_view_close_for_mysql(trx);
 
7918
                }
 
7919
        }
 
7920
 
 
7921
        DBUG_ASSERT(thd == current_thd);
 
7922
        const bool in_lock_tables = thd_in_lock_tables(thd);
 
7923
        const uint sql_command = thd_sql_command(thd);
 
7924
 
 
7925
        if (sql_command == SQLCOM_DROP_TABLE) {
 
7926
 
 
7927
                /* MySQL calls this function in DROP TABLE though this table
 
7928
                handle may belong to another thd that is running a query. Let
 
7929
                us in that case skip any changes to the prebuilt struct. */ 
 
7930
 
 
7931
        } else if ((lock_type == TL_READ && in_lock_tables)
 
7932
                   || (lock_type == TL_READ_HIGH_PRIORITY && in_lock_tables)
 
7933
                   || lock_type == TL_READ_WITH_SHARED_LOCKS
 
7934
                   || lock_type == TL_READ_NO_INSERT
 
7935
                   || (lock_type != TL_IGNORE
 
7936
                       && sql_command != SQLCOM_SELECT)) {
 
7937
 
 
7938
                /* The OR cases above are in this order:
 
7939
                1) MySQL is doing LOCK TABLES ... READ LOCAL, or we
 
7940
                are processing a stored procedure or function, or
 
7941
                2) (we do not know when TL_READ_HIGH_PRIORITY is used), or
 
7942
                3) this is a SELECT ... IN SHARE MODE, or
 
7943
                4) we are doing a complex SQL statement like
 
7944
                INSERT INTO ... SELECT ... and the logical logging (MySQL
 
7945
                binlog) requires the use of a locking read, or
 
7946
                MySQL is doing LOCK TABLES ... READ.
 
7947
                5) we let InnoDB do locking reads for all SQL statements that
 
7948
                are not simple SELECTs; note that select_lock_type in this
 
7949
                case may get strengthened in ::external_lock() to LOCK_X.
 
7950
                Note that we MUST use a locking read in all data modifying
 
7951
                SQL statements, because otherwise the execution would not be
 
7952
                serializable, and also the results from the update could be
 
7953
                unexpected if an obsolete consistent read view would be
 
7954
                used. */
 
7955
 
 
7956
                ulint   isolation_level;
 
7957
 
 
7958
                isolation_level = trx->isolation_level;
 
7959
 
 
7960
                if ((srv_locks_unsafe_for_binlog
 
7961
                     || isolation_level == TRX_ISO_READ_COMMITTED)
 
7962
                    && isolation_level != TRX_ISO_SERIALIZABLE
 
7963
                    && (lock_type == TL_READ || lock_type == TL_READ_NO_INSERT)
 
7964
                    && (sql_command == SQLCOM_INSERT_SELECT
 
7965
                        || sql_command == SQLCOM_UPDATE
 
7966
                        || sql_command == SQLCOM_CREATE_TABLE)) {
 
7967
 
 
7968
                        /* If we either have innobase_locks_unsafe_for_binlog
 
7969
                        option set or this session is using READ COMMITTED
 
7970
                        isolation level and isolation level of the transaction
 
7971
                        is not set to serializable and MySQL is doing
 
7972
                        INSERT INTO...SELECT or UPDATE ... = (SELECT ...) or
 
7973
                        CREATE  ... SELECT... without FOR UPDATE or
 
7974
                        IN SHARE MODE in select, then we use consistent
 
7975
                        read for select. */
 
7976
 
 
7977
                        prebuilt->select_lock_type = LOCK_NONE;
 
7978
                        prebuilt->stored_select_lock_type = LOCK_NONE;
 
7979
                } else if (sql_command == SQLCOM_CHECKSUM) {
 
7980
                        /* Use consistent read for checksum table */
 
7981
 
 
7982
                        prebuilt->select_lock_type = LOCK_NONE;
 
7983
                        prebuilt->stored_select_lock_type = LOCK_NONE;
 
7984
                } else {
 
7985
                        prebuilt->select_lock_type = LOCK_S;
 
7986
                        prebuilt->stored_select_lock_type = LOCK_S;
 
7987
                }
 
7988
 
 
7989
        } else if (lock_type != TL_IGNORE) {
 
7990
 
 
7991
                /* We set possible LOCK_X value in external_lock, not yet
 
7992
                here even if this would be SELECT ... FOR UPDATE */
 
7993
 
 
7994
                prebuilt->select_lock_type = LOCK_NONE;
 
7995
                prebuilt->stored_select_lock_type = LOCK_NONE;
 
7996
        }
 
7997
 
 
7998
        if (lock_type != TL_IGNORE && lock.type == TL_UNLOCK) {
 
7999
 
 
8000
                /* Starting from 5.0.7, we weaken also the table locks
 
8001
                set at the start of a MySQL stored procedure call, just like
 
8002
                we weaken the locks set at the start of an SQL statement.
 
8003
                MySQL does set in_lock_tables TRUE there, but in reality
 
8004
                we do not need table locks to make the execution of a
 
8005
                single transaction stored procedure call deterministic
 
8006
                (if it does not use a consistent read). */
 
8007
 
 
8008
                if (lock_type == TL_READ
 
8009
                    && sql_command == SQLCOM_LOCK_TABLES) {
 
8010
                        /* We come here if MySQL is processing LOCK TABLES
 
8011
                        ... READ LOCAL. MyISAM under that table lock type
 
8012
                        reads the table as it was at the time the lock was
 
8013
                        granted (new inserts are allowed, but not seen by the
 
8014
                        reader). To get a similar effect on an InnoDB table,
 
8015
                        we must use LOCK TABLES ... READ. We convert the lock
 
8016
                        type here, so that for InnoDB, READ LOCAL is
 
8017
                        equivalent to READ. This will change the InnoDB
 
8018
                        behavior in mysqldump, so that dumps of InnoDB tables
 
8019
                        are consistent with dumps of MyISAM tables. */
 
8020
 
 
8021
                        lock_type = TL_READ_NO_INSERT;
 
8022
                }
 
8023
 
 
8024
                /* If we are not doing a LOCK TABLE, DISCARD/IMPORT
 
8025
                TABLESPACE or TRUNCATE TABLE then allow multiple
 
8026
                writers. Note that ALTER TABLE uses a TL_WRITE_ALLOW_READ
 
8027
                < TL_WRITE_CONCURRENT_INSERT.
 
8028
 
 
8029
                We especially allow multiple writers if MySQL is at the
 
8030
                start of a stored procedure call (SQLCOM_CALL) or a
 
8031
                stored function call (MySQL does have in_lock_tables
 
8032
                TRUE there). */
 
8033
 
 
8034
                if ((lock_type >= TL_WRITE_CONCURRENT_INSERT
 
8035
                     && lock_type <= TL_WRITE)
 
8036
                    && !(in_lock_tables
 
8037
                         && sql_command == SQLCOM_LOCK_TABLES)
 
8038
                    && !thd_tablespace_op(thd)
 
8039
                    && sql_command != SQLCOM_TRUNCATE
 
8040
                    && sql_command != SQLCOM_OPTIMIZE
 
8041
                    && sql_command != SQLCOM_CREATE_TABLE) {
 
8042
 
 
8043
                        lock_type = TL_WRITE_ALLOW_WRITE;
 
8044
                }
 
8045
 
 
8046
                /* In queries of type INSERT INTO t1 SELECT ... FROM t2 ...
 
8047
                MySQL would use the lock TL_READ_NO_INSERT on t2, and that
 
8048
                would conflict with TL_WRITE_ALLOW_WRITE, blocking all inserts
 
8049
                to t2. Convert the lock to a normal read lock to allow
 
8050
                concurrent inserts to t2.
 
8051
 
 
8052
                We especially allow concurrent inserts if MySQL is at the
 
8053
                start of a stored procedure call (SQLCOM_CALL)
 
8054
                (MySQL does have thd_in_lock_tables() TRUE there). */
 
8055
 
 
8056
                if (lock_type == TL_READ_NO_INSERT
 
8057
                    && sql_command != SQLCOM_LOCK_TABLES) {
 
8058
 
 
8059
                        lock_type = TL_READ;
 
8060
                }
 
8061
 
 
8062
                lock.type = lock_type;
 
8063
        }
 
8064
 
 
8065
        *to++= &lock;
 
8066
 
 
8067
        return(to);
 
8068
}
 
8069
 
 
8070
/***********************************************************************
 
8071
This function initializes the auto-inc counter if it has not been
 
8072
initialized yet. This function does not change the value of the auto-inc
 
8073
counter if it already has been initialized. In parameter ret returns
 
8074
the value of the auto-inc counter. */
 
8075
UNIV_INTERN
 
8076
int
 
8077
ha_innobase::innobase_read_and_init_auto_inc(
 
8078
/*=========================================*/
 
8079
                                                /* out: 0 or generic MySQL
 
8080
                                                error code */
 
8081
        ulonglong*      value)                  /* out: the autoinc value */
 
8082
{
 
8083
        ulonglong       auto_inc;
 
8084
        ibool           stmt_start;
 
8085
        int             mysql_error = 0;
 
8086
        dict_table_t*   innodb_table = prebuilt->table;
 
8087
        ibool           trx_was_not_started     = FALSE;
 
8088
 
 
8089
        ut_a(prebuilt);
 
8090
        ut_a(prebuilt->table);
 
8091
 
 
8092
        /* Remember if we are in the beginning of an SQL statement.
 
8093
        This function must not change that flag. */
 
8094
        stmt_start = prebuilt->sql_stat_start;
 
8095
 
 
8096
        /* Prepare prebuilt->trx in the table handle */
 
8097
        update_thd(ha_thd());
 
8098
 
 
8099
        if (prebuilt->trx->conc_state == TRX_NOT_STARTED) {
 
8100
                trx_was_not_started = TRUE;
 
8101
        }
 
8102
 
 
8103
        /* In case MySQL calls this in the middle of a SELECT query, release
 
8104
        possible adaptive hash latch to avoid deadlocks of threads */
 
8105
 
 
8106
        trx_search_latch_release_if_reserved(prebuilt->trx);
 
8107
 
 
8108
        dict_table_autoinc_lock(prebuilt->table);
 
8109
 
 
8110
        auto_inc = dict_table_autoinc_read(prebuilt->table);
 
8111
 
 
8112
        /* Was the AUTOINC counter reset during normal processing, if
 
8113
        so then we simply start count from 1. No need to go to the index.*/
 
8114
        if (auto_inc == 0 && innodb_table->autoinc_inited) {
 
8115
                ++auto_inc;
 
8116
                dict_table_autoinc_initialize(innodb_table, auto_inc);
 
8117
        }
 
8118
 
 
8119
        if (auto_inc == 0) {
 
8120
                dict_index_t* index;
 
8121
                ulint error;
 
8122
                const char* autoinc_col_name;
 
8123
 
 
8124
                ut_a(!innodb_table->autoinc_inited);
 
8125
 
 
8126
                index = innobase_get_index(table->s->next_number_index);
 
8127
 
 
8128
                autoinc_col_name = table->found_next_number_field->field_name;
 
8129
 
 
8130
                error = row_search_max_autoinc(
 
8131
                        index, autoinc_col_name, &auto_inc);
 
8132
 
 
8133
                if (error == DB_SUCCESS) {
 
8134
                        if (auto_inc < ~0x0ULL) {
 
8135
                                ++auto_inc;
 
8136
                        }
 
8137
                        dict_table_autoinc_initialize(innodb_table, auto_inc);
 
8138
                } else {
 
8139
                        ut_print_timestamp(stderr);
 
8140
                        fprintf(stderr, "  InnoDB: Error: (%lu) Couldn't read "
 
8141
                                "the max AUTOINC value from the index (%s).\n",
 
8142
                                error, index->name);
 
8143
 
 
8144
                        mysql_error = 1;
 
8145
                }
 
8146
        }
 
8147
 
 
8148
        *value = auto_inc;
 
8149
 
 
8150
        dict_table_autoinc_unlock(prebuilt->table);
 
8151
 
 
8152
        /* Since MySQL does not seem to call autocommit after SHOW TABLE
 
8153
        STATUS (even if we would register the trx here), we commit our
 
8154
        transaction here if it was started here. This is to eliminate a
 
8155
        dangling transaction. If the user had AUTOCOMMIT=0, then SHOW
 
8156
        TABLE STATUS does leave a dangling transaction if the user does not
 
8157
        himself call COMMIT. */
 
8158
 
 
8159
        if (trx_was_not_started) {
 
8160
 
 
8161
                innobase_commit_low(prebuilt->trx);
 
8162
        }
 
8163
 
 
8164
        prebuilt->sql_stat_start = stmt_start;
 
8165
 
 
8166
        return(mysql_error);
 
8167
}
 
8168
 
 
8169
/*******************************************************************************
 
8170
Read the next autoinc value, initialize the table if it's not initialized.
 
8171
On return if there is no error then the tables AUTOINC lock is locked.*/
 
8172
UNIV_INTERN
 
8173
ulong
 
8174
ha_innobase::innobase_get_auto_increment(
 
8175
/*=====================================*/
 
8176
        ulonglong*      value)          /* out: autoinc value */
 
8177
{
 
8178
        ulong           error;
 
8179
 
 
8180
        *value = 0;
 
8181
 
 
8182
        /* Note: If the table is not initialized when we attempt the
 
8183
        read below. We initialize the table's auto-inc counter  and
 
8184
        always do a reread of the AUTOINC value. */
 
8185
        do {
 
8186
                error = innobase_autoinc_lock();
 
8187
 
 
8188
                if (error == DB_SUCCESS) {
 
8189
                        ulonglong       autoinc;
 
8190
 
 
8191
                        /* Determine the first value of the interval */
 
8192
                        autoinc = dict_table_autoinc_read(prebuilt->table);
 
8193
 
 
8194
                        /* We need to initialize the AUTO-INC value, for
 
8195
                        that we release all locks.*/
 
8196
                        if (autoinc == 0) {
 
8197
                                trx_t*          trx;
 
8198
 
 
8199
                                trx = prebuilt->trx;
 
8200
                                dict_table_autoinc_unlock(prebuilt->table);
 
8201
 
 
8202
                                /* If we had reserved the AUTO-INC
 
8203
                                lock in this SQL statement we release
 
8204
                                it before retrying.*/
 
8205
                                row_unlock_table_autoinc_for_mysql(trx);
 
8206
 
 
8207
                                /* Just to make sure */
 
8208
                                ut_a(!trx->auto_inc_lock);
 
8209
 
 
8210
                                int     mysql_error;
 
8211
 
 
8212
                                mysql_error = innobase_read_and_init_auto_inc(
 
8213
                                        &autoinc);
 
8214
 
 
8215
                                if (mysql_error) {
 
8216
                                        error = DB_ERROR;
 
8217
                                }
 
8218
                        } else {
 
8219
                                *value = autoinc;
 
8220
                        }
 
8221
                /* A deadlock error during normal processing is OK
 
8222
                and can be ignored. */
 
8223
                } else if (error != DB_DEADLOCK) {
 
8224
 
 
8225
                        sql_print_error("InnoDB: Error: %lu in "
 
8226
                                        "::innobase_get_auto_increment()",
 
8227
                                        error);
 
8228
                }
 
8229
 
 
8230
        } while (*value == 0 && error == DB_SUCCESS);
 
8231
 
 
8232
        return(error);
 
8233
}
 
8234
 
 
8235
/*******************************************************************************
 
8236
This function initializes the auto-inc counter if it has not been
 
8237
initialized yet. This function does not change the value of the auto-inc
 
8238
counter if it already has been initialized. Returns the value of the
 
8239
auto-inc counter in *first_value, and ULONGLONG_MAX in *nb_reserved_values (as
 
8240
we have a table-level lock). offset, increment, nb_desired_values are ignored.
 
8241
*first_value is set to -1 if error (deadlock or lock wait timeout) */
 
8242
UNIV_INTERN
 
8243
void
 
8244
ha_innobase::get_auto_increment(
 
8245
/*============================*/
 
8246
        ulonglong       offset,              /* in: */
 
8247
        ulonglong       increment,           /* in: table autoinc increment */
 
8248
        ulonglong       nb_desired_values,   /* in: number of values reqd */
 
8249
        ulonglong       *first_value,        /* out: the autoinc value */
 
8250
        ulonglong       *nb_reserved_values) /* out: count of reserved values */
 
8251
{
 
8252
        trx_t*          trx;
 
8253
        ulint           error;
 
8254
        ulonglong       autoinc = 0;
 
8255
 
 
8256
        /* Prepare prebuilt->trx in the table handle */
 
8257
        update_thd(ha_thd());
 
8258
 
 
8259
        error = innobase_get_auto_increment(&autoinc);
 
8260
 
 
8261
        if (error != DB_SUCCESS) {
 
8262
                *first_value = (~(ulonglong) 0);
 
8263
                return;
 
8264
        }
 
8265
 
 
8266
        /* This is a hack, since nb_desired_values seems to be accurate only
 
8267
        for the first call to get_auto_increment() for multi-row INSERT and
 
8268
        meaningless for other statements e.g, LOAD etc. Subsequent calls to
 
8269
        this method for the same statement results in different values which
 
8270
        don't make sense. Therefore we store the value the first time we are
 
8271
        called and count down from that as rows are written (see write_row()).
 
8272
        */
 
8273
 
 
8274
        trx = prebuilt->trx;
 
8275
 
 
8276
        /* Note: We can't rely on *first_value since some MySQL engines,
 
8277
        in particular the partition engine, don't initialize it to 0 when
 
8278
        invoking this method. So we are not sure if it's guaranteed to
 
8279
        be 0 or not. */
 
8280
 
 
8281
        /* Called for the first time ? */
 
8282
        if (trx->n_autoinc_rows == 0) {
 
8283
 
 
8284
                trx->n_autoinc_rows = (ulint) nb_desired_values;
 
8285
 
 
8286
                /* It's possible for nb_desired_values to be 0:
 
8287
                e.g., INSERT INTO T1(C) SELECT C FROM T2; */
 
8288
                if (nb_desired_values == 0) {
 
8289
 
 
8290
                        trx->n_autoinc_rows = 1;
 
8291
                }
 
8292
 
 
8293
                set_if_bigger(*first_value, autoinc);
 
8294
        /* Not in the middle of a mult-row INSERT. */
 
8295
        } else if (prebuilt->last_value == 0) {
 
8296
                set_if_bigger(*first_value, autoinc);
 
8297
        }
 
8298
 
 
8299
        *nb_reserved_values = trx->n_autoinc_rows;
 
8300
 
 
8301
        /* With old style AUTOINC locking we only update the table's
 
8302
        AUTOINC counter after attempting to insert the row. */
 
8303
        if (innobase_autoinc_lock_mode != AUTOINC_OLD_STYLE_LOCKING) {
 
8304
                ulonglong       have;
 
8305
                ulonglong       need;
 
8306
 
 
8307
                /* Check for overflow conditions. */
 
8308
                need = *nb_reserved_values * increment;
 
8309
                have = ~0x0ULL - *first_value;
 
8310
 
 
8311
                if (have < need) {
 
8312
                        need = have;
 
8313
                }
 
8314
 
 
8315
                /* Compute the last value in the interval */
 
8316
                prebuilt->last_value = *first_value + need;
 
8317
 
 
8318
                ut_a(prebuilt->last_value >= *first_value);
 
8319
 
 
8320
                /* Update the table autoinc variable */
 
8321
                dict_table_autoinc_update(
 
8322
                        prebuilt->table, prebuilt->last_value);
 
8323
        } else {
 
8324
                /* This will force write_row() into attempting an update
 
8325
                of the table's AUTOINC counter. */
 
8326
                prebuilt->last_value = 0;
 
8327
        }
 
8328
 
 
8329
        /* The increment to be used to increase the AUTOINC value, we use
 
8330
        this in write_row() and update_row() to increase the autoinc counter
 
8331
        for columns that are filled by the user.*/
 
8332
        prebuilt->table->autoinc_increment = increment;
 
8333
 
 
8334
        dict_table_autoinc_unlock(prebuilt->table);
 
8335
}
 
8336
 
 
8337
/* See comment in handler.h */
 
8338
UNIV_INTERN
 
8339
int
 
8340
ha_innobase::reset_auto_increment(
 
8341
/*==============================*/
 
8342
        ulonglong       value)          /* in: new value for table autoinc */
 
8343
{
 
8344
        DBUG_ENTER("ha_innobase::reset_auto_increment");
 
8345
 
 
8346
        int     error;
 
8347
 
 
8348
        update_thd(ha_thd());
 
8349
 
 
8350
        error = row_lock_table_autoinc_for_mysql(prebuilt);
 
8351
 
 
8352
        if (error != DB_SUCCESS) {
 
8353
                error = convert_error_code_to_mysql(error,
 
8354
                                                    prebuilt->table->flags,
 
8355
                                                    user_thd);
 
8356
 
 
8357
                DBUG_RETURN(error);
 
8358
        }
 
8359
 
 
8360
        innobase_reset_autoinc(value);
 
8361
 
 
8362
        DBUG_RETURN(0);
 
8363
}
 
8364
 
 
8365
/* See comment in handler.cc */
 
8366
UNIV_INTERN
 
8367
bool
 
8368
ha_innobase::get_error_message(int error, String *buf)
 
8369
{
 
8370
        trx_t*  trx = check_trx_exists(ha_thd());
 
8371
 
 
8372
        buf->copy(trx->detailed_error, strlen(trx->detailed_error),
 
8373
                system_charset_info);
 
8374
 
 
8375
        return(FALSE);
 
8376
}
 
8377
 
 
8378
/***********************************************************************
 
8379
Compares two 'refs'. A 'ref' is the (internal) primary key value of the row.
 
8380
If there is no explicitly declared non-null unique key or a primary key, then
 
8381
InnoDB internally uses the row id as the primary key. */
 
8382
UNIV_INTERN
 
8383
int
 
8384
ha_innobase::cmp_ref(
 
8385
/*=================*/
 
8386
                                /* out: < 0 if ref1 < ref2, 0 if equal, else
 
8387
                                > 0 */
 
8388
        const uchar*    ref1,   /* in: an (internal) primary key value in the
 
8389
                                MySQL key value format */
 
8390
        const uchar*    ref2)   /* in: an (internal) primary key value in the
 
8391
                                MySQL key value format */
 
8392
{
 
8393
        enum_field_types mysql_type;
 
8394
        Field*          field;
 
8395
        KEY_PART_INFO*  key_part;
 
8396
        KEY_PART_INFO*  key_part_end;
 
8397
        uint            len1;
 
8398
        uint            len2;
 
8399
        int             result;
 
8400
 
 
8401
        if (prebuilt->clust_index_was_generated) {
 
8402
                /* The 'ref' is an InnoDB row id */
 
8403
 
 
8404
                return(memcmp(ref1, ref2, DATA_ROW_ID_LEN));
 
8405
        }
 
8406
 
 
8407
        /* Do a type-aware comparison of primary key fields. PK fields
 
8408
        are always NOT NULL, so no checks for NULL are performed. */
 
8409
 
 
8410
        key_part = table->key_info[table->s->primary_key].key_part;
 
8411
 
 
8412
        key_part_end = key_part
 
8413
                        + table->key_info[table->s->primary_key].key_parts;
 
8414
 
 
8415
        for (; key_part != key_part_end; ++key_part) {
 
8416
                field = key_part->field;
 
8417
                mysql_type = field->type();
 
8418
 
 
8419
                if (mysql_type == MYSQL_TYPE_TINY_BLOB
 
8420
                        || mysql_type == MYSQL_TYPE_MEDIUM_BLOB
 
8421
                        || mysql_type == MYSQL_TYPE_BLOB
 
8422
                        || mysql_type == MYSQL_TYPE_LONG_BLOB) {
 
8423
 
 
8424
                        /* In the MySQL key value format, a column prefix of
 
8425
                        a BLOB is preceded by a 2-byte length field */
 
8426
 
 
8427
                        len1 = innobase_read_from_2_little_endian(ref1);
 
8428
                        len2 = innobase_read_from_2_little_endian(ref2);
 
8429
 
 
8430
                        ref1 += 2;
 
8431
                        ref2 += 2;
 
8432
                        result = ((Field_blob*)field)->cmp( ref1, len1,
 
8433
                                                            ref2, len2);
 
8434
                } else {
 
8435
                        result = field->key_cmp(ref1, ref2);
 
8436
                }
 
8437
 
 
8438
                if (result) {
 
8439
 
 
8440
                        return(result);
 
8441
                }
 
8442
 
 
8443
                ref1 += key_part->store_length;
 
8444
                ref2 += key_part->store_length;
 
8445
        }
 
8446
 
 
8447
        return(0);
 
8448
}
 
8449
 
 
8450
/***********************************************************************
 
8451
Ask InnoDB if a query to a table can be cached. */
 
8452
UNIV_INTERN
 
8453
my_bool
 
8454
ha_innobase::register_query_cache_table(
 
8455
/*====================================*/
 
8456
                                        /* out: TRUE if query caching
 
8457
                                        of the table is permitted */
 
8458
        THD*            thd,            /* in: user thread handle */
 
8459
        char*           table_key,      /* in: concatenation of database name,
 
8460
                                        the null character '\0',
 
8461
                                        and the table name */
 
8462
        uint            key_length,     /* in: length of the full name, i.e.
 
8463
                                        len(dbname) + len(tablename) + 1 */
 
8464
        qc_engine_callback*
 
8465
                        call_back,      /* out: pointer to function for
 
8466
                                        checking if query caching
 
8467
                                        is permitted */
 
8468
        ulonglong       *engine_data)   /* in/out: data to call_back */
 
8469
{
 
8470
        *call_back = innobase_query_caching_of_table_permitted;
 
8471
        *engine_data = 0;
 
8472
        return(innobase_query_caching_of_table_permitted(thd, table_key,
 
8473
                                                         key_length,
 
8474
                                                         engine_data));
 
8475
}
 
8476
 
 
8477
UNIV_INTERN
 
8478
char*
 
8479
ha_innobase::get_mysql_bin_log_name()
 
8480
{
 
8481
        return(trx_sys_mysql_bin_log_name);
 
8482
}
 
8483
 
 
8484
UNIV_INTERN
 
8485
ulonglong
 
8486
ha_innobase::get_mysql_bin_log_pos()
 
8487
{
 
8488
        /* trx... is ib_int64_t, which is a typedef for a 64-bit integer
 
8489
        (__int64 or longlong) so it's ok to cast it to ulonglong. */
 
8490
 
 
8491
        return(trx_sys_mysql_bin_log_pos);
 
8492
}
 
8493
 
 
8494
/**********************************************************************
 
8495
This function is used to find the storage length in bytes of the first n
 
8496
characters for prefix indexes using a multibyte character set. The function
 
8497
finds charset information and returns length of prefix_len characters in the
 
8498
index field in bytes.
 
8499
 
 
8500
NOTE: the prototype of this function is copied to data0type.c! If you change
 
8501
this function, you MUST change also data0type.c! */
 
8502
extern "C" UNIV_INTERN
 
8503
ulint
 
8504
innobase_get_at_most_n_mbchars(
 
8505
/*===========================*/
 
8506
                                /* out: number of bytes occupied by the first
 
8507
                                n characters */
 
8508
        ulint charset_id,       /* in: character set id */
 
8509
        ulint prefix_len,       /* in: prefix length in bytes of the index
 
8510
                                (this has to be divided by mbmaxlen to get the
 
8511
                                number of CHARACTERS n in the prefix) */
 
8512
        ulint data_len,         /* in: length of the string in bytes */
 
8513
        const char* str)        /* in: character string */
 
8514
{
 
8515
        ulint char_length;      /* character length in bytes */
 
8516
        ulint n_chars;          /* number of characters in prefix */
 
8517
        CHARSET_INFO* charset;  /* charset used in the field */
 
8518
 
 
8519
        charset = get_charset((uint) charset_id, MYF(MY_WME));
 
8520
 
 
8521
        ut_ad(charset);
 
8522
        ut_ad(charset->mbmaxlen);
 
8523
 
 
8524
        /* Calculate how many characters at most the prefix index contains */
 
8525
 
 
8526
        n_chars = prefix_len / charset->mbmaxlen;
 
8527
 
 
8528
        /* If the charset is multi-byte, then we must find the length of the
 
8529
        first at most n chars in the string. If the string contains less
 
8530
        characters than n, then we return the length to the end of the last
 
8531
        character. */
 
8532
 
 
8533
        if (charset->mbmaxlen > 1) {
 
8534
                /* my_charpos() returns the byte length of the first n_chars
 
8535
                characters, or a value bigger than the length of str, if
 
8536
                there were not enough full characters in str.
 
8537
 
 
8538
                Why does the code below work:
 
8539
                Suppose that we are looking for n UTF-8 characters.
 
8540
 
 
8541
                1) If the string is long enough, then the prefix contains at
 
8542
                least n complete UTF-8 characters + maybe some extra
 
8543
                characters + an incomplete UTF-8 character. No problem in
 
8544
                this case. The function returns the pointer to the
 
8545
                end of the nth character.
 
8546
 
 
8547
                2) If the string is not long enough, then the string contains
 
8548
                the complete value of a column, that is, only complete UTF-8
 
8549
                characters, and we can store in the column prefix index the
 
8550
                whole string. */
 
8551
 
 
8552
                char_length = my_charpos(charset, str,
 
8553
                                                str + data_len, (int) n_chars);
 
8554
                if (char_length > data_len) {
 
8555
                        char_length = data_len;
 
8556
                }
 
8557
        } else {
 
8558
                if (data_len < prefix_len) {
 
8559
                        char_length = data_len;
 
8560
                } else {
 
8561
                        char_length = prefix_len;
 
8562
                }
 
8563
        }
 
8564
 
 
8565
        return(char_length);
 
8566
}
 
8567
 
 
8568
/***********************************************************************
 
8569
This function is used to prepare X/Open XA distributed transaction   */
 
8570
static
 
8571
int
 
8572
innobase_xa_prepare(
 
8573
/*================*/
 
8574
                        /* out: 0 or error number */
 
8575
        handlerton *hton,
 
8576
        THD*    thd,    /* in: handle to the MySQL thread of the user
 
8577
                        whose XA transaction should be prepared */
 
8578
        bool    all)    /* in: TRUE - commit transaction
 
8579
                        FALSE - the current SQL statement ended */
 
8580
{
 
8581
        int error = 0;
 
8582
        trx_t* trx = check_trx_exists(thd);
 
8583
 
 
8584
        DBUG_ASSERT(hton == innodb_hton_ptr);
 
8585
 
 
8586
        if (thd_sql_command(thd) != SQLCOM_XA_PREPARE &&
 
8587
            (all || !thd_test_options(thd, OPTION_NOT_AUTOCOMMIT | OPTION_BEGIN)))
 
8588
        {
 
8589
 
 
8590
                /* For ibbackup to work the order of transactions in binlog
 
8591
                and InnoDB must be the same. Consider the situation
 
8592
 
 
8593
                  thread1> prepare; write to binlog; ...
 
8594
                          <context switch>
 
8595
                  thread2> prepare; write to binlog; commit
 
8596
                  thread1>                           ... commit
 
8597
 
 
8598
                To ensure this will not happen we're taking the mutex on
 
8599
                prepare, and releasing it on commit.
 
8600
 
 
8601
                Note: only do it for normal commits, done via ha_commit_trans.
 
8602
                If 2pc protocol is executed by external transaction
 
8603
                coordinator, it will be just a regular MySQL client
 
8604
                executing XA PREPARE and XA COMMIT commands.
 
8605
                In this case we cannot know how many minutes or hours
 
8606
                will be between XA PREPARE and XA COMMIT, and we don't want
 
8607
                to block for undefined period of time.
 
8608
                */
 
8609
                pthread_mutex_lock(&prepare_commit_mutex);
 
8610
                trx->active_trans = 2;
 
8611
        }
 
8612
 
 
8613
        if (!THDVAR(thd, support_xa)) {
 
8614
 
 
8615
                return(0);
 
8616
        }
 
8617
 
 
8618
        thd_get_xid(thd, (MYSQL_XID*) &trx->xid);
 
8619
 
 
8620
        /* Release a possible FIFO ticket and search latch. Since we will
 
8621
        reserve the kernel mutex, we have to release the search system latch
 
8622
        first to obey the latching order. */
 
8623
 
 
8624
        innobase_release_stat_resources(trx);
 
8625
 
 
8626
        if (trx->active_trans == 0 && trx->conc_state != TRX_NOT_STARTED) {
 
8627
 
 
8628
          sql_print_error("trx->active_trans == 0, but trx->conc_state != "
 
8629
                          "TRX_NOT_STARTED");
 
8630
        }
 
8631
 
 
8632
        if (all
 
8633
                || (!thd_test_options(thd, OPTION_NOT_AUTOCOMMIT | OPTION_BEGIN))) {
 
8634
 
 
8635
                /* We were instructed to prepare the whole transaction, or
 
8636
                this is an SQL statement end and autocommit is on */
 
8637
 
 
8638
                ut_ad(trx->active_trans);
 
8639
 
 
8640
                error = (int) trx_prepare_for_mysql(trx);
 
8641
        } else {
 
8642
                /* We just mark the SQL statement ended and do not do a
 
8643
                transaction prepare */
 
8644
 
 
8645
                /* If we had reserved the auto-inc lock for some
 
8646
                table in this SQL statement we release it now */
 
8647
 
 
8648
                row_unlock_table_autoinc_for_mysql(trx);
 
8649
 
 
8650
                /* Store the current undo_no of the transaction so that we
 
8651
                know where to roll back if we have to roll back the next
 
8652
                SQL statement */
 
8653
 
 
8654
                trx_mark_sql_stat_end(trx);
 
8655
        }
 
8656
 
 
8657
        /* Tell the InnoDB server that there might be work for utility
 
8658
        threads: */
 
8659
 
 
8660
        srv_active_wake_master_thread();
 
8661
 
 
8662
        return(error);
 
8663
}
 
8664
 
 
8665
/***********************************************************************
 
8666
This function is used to recover X/Open XA distributed transactions   */
 
8667
static
 
8668
int
 
8669
innobase_xa_recover(
 
8670
/*================*/
 
8671
                                /* out: number of prepared transactions
 
8672
                                stored in xid_list */
 
8673
        handlerton *hton,
 
8674
        XID*    xid_list,       /* in/out: prepared transactions */
 
8675
        uint    len)            /* in: number of slots in xid_list */
 
8676
{
 
8677
        DBUG_ASSERT(hton == innodb_hton_ptr);
 
8678
 
 
8679
        if (len == 0 || xid_list == NULL) {
 
8680
 
 
8681
                return(0);
 
8682
        }
 
8683
 
 
8684
        return(trx_recover_for_mysql(xid_list, len));
 
8685
}
 
8686
 
 
8687
/***********************************************************************
 
8688
This function is used to commit one X/Open XA distributed transaction
 
8689
which is in the prepared state */
 
8690
static
 
8691
int
 
8692
innobase_commit_by_xid(
 
8693
/*===================*/
 
8694
                        /* out: 0 or error number */
 
8695
        handlerton *hton,
 
8696
        XID*    xid)    /* in: X/Open XA transaction identification */
 
8697
{
 
8698
        trx_t*  trx;
 
8699
 
 
8700
        DBUG_ASSERT(hton == innodb_hton_ptr);
 
8701
 
 
8702
        trx = trx_get_trx_by_xid(xid);
 
8703
 
 
8704
        if (trx) {
 
8705
                innobase_commit_low(trx);
 
8706
 
 
8707
                return(XA_OK);
 
8708
        } else {
 
8709
                return(XAER_NOTA);
 
8710
        }
 
8711
}
 
8712
 
 
8713
/***********************************************************************
 
8714
This function is used to rollback one X/Open XA distributed transaction
 
8715
which is in the prepared state */
 
8716
static
 
8717
int
 
8718
innobase_rollback_by_xid(
 
8719
/*=====================*/
 
8720
                        /* out: 0 or error number */
 
8721
        handlerton *hton,
 
8722
        XID     *xid)   /* in: X/Open XA transaction identification */
 
8723
{
 
8724
        trx_t*  trx;
 
8725
 
 
8726
        DBUG_ASSERT(hton == innodb_hton_ptr);
 
8727
 
 
8728
        trx = trx_get_trx_by_xid(xid);
 
8729
 
 
8730
        if (trx) {
 
8731
                return(innobase_rollback_trx(trx));
 
8732
        } else {
 
8733
                return(XAER_NOTA);
 
8734
        }
 
8735
}
 
8736
 
 
8737
/***********************************************************************
 
8738
Create a consistent view for a cursor based on current transaction
 
8739
which is created if the corresponding MySQL thread still lacks one.
 
8740
This consistent view is then used inside of MySQL when accessing records
 
8741
using a cursor. */
 
8742
static
 
8743
void*
 
8744
innobase_create_cursor_view(
 
8745
/*========================*/
 
8746
                          /* out: pointer to cursor view or NULL */
 
8747
        handlerton *hton, /* in: innobase hton */
 
8748
        THD* thd)         /* in: user thread handle */
 
8749
{
 
8750
        DBUG_ASSERT(hton == innodb_hton_ptr);
 
8751
 
 
8752
        return(read_cursor_view_create_for_mysql(check_trx_exists(thd)));
 
8753
}
 
8754
 
 
8755
/***********************************************************************
 
8756
Close the given consistent cursor view of a transaction and restore
 
8757
global read view to a transaction read view. Transaction is created if the
 
8758
corresponding MySQL thread still lacks one. */
 
8759
static
 
8760
void
 
8761
innobase_close_cursor_view(
 
8762
/*=======================*/
 
8763
        handlerton *hton,
 
8764
        THD*    thd,    /* in: user thread handle */
 
8765
        void*   curview)/* in: Consistent read view to be closed */
 
8766
{
 
8767
        DBUG_ASSERT(hton == innodb_hton_ptr);
 
8768
 
 
8769
        read_cursor_view_close_for_mysql(check_trx_exists(thd),
 
8770
                                         (cursor_view_t*) curview);
 
8771
}
 
8772
 
 
8773
/***********************************************************************
 
8774
Set the given consistent cursor view to a transaction which is created
 
8775
if the corresponding MySQL thread still lacks one. If the given
 
8776
consistent cursor view is NULL global read view of a transaction is
 
8777
restored to a transaction read view. */
 
8778
static
 
8779
void
 
8780
innobase_set_cursor_view(
 
8781
/*=====================*/
 
8782
        handlerton *hton,
 
8783
        THD*    thd,    /* in: user thread handle */
 
8784
        void*   curview)/* in: Consistent cursor view to be set */
 
8785
{
 
8786
        DBUG_ASSERT(hton == innodb_hton_ptr);
 
8787
 
 
8788
        read_cursor_set_for_mysql(check_trx_exists(thd),
 
8789
                                  (cursor_view_t*) curview);
 
8790
}
 
8791
 
 
8792
 
 
8793
UNIV_INTERN
 
8794
bool
 
8795
ha_innobase::check_if_incompatible_data(
 
8796
        HA_CREATE_INFO* info,
 
8797
        uint            table_changes)
 
8798
{
 
8799
        if (table_changes != IS_EQUAL_YES) {
 
8800
 
 
8801
                return(COMPATIBLE_DATA_NO);
 
8802
        }
 
8803
 
 
8804
        /* Check that auto_increment value was not changed */
 
8805
        if ((info->used_fields & HA_CREATE_USED_AUTO) &&
 
8806
                info->auto_increment_value != 0) {
 
8807
 
 
8808
                return(COMPATIBLE_DATA_NO);
 
8809
        }
 
8810
 
 
8811
        /* Check that row format didn't change */
 
8812
        if ((info->used_fields & HA_CREATE_USED_ROW_FORMAT) &&
 
8813
            get_row_type() != info->row_type) {
 
8814
 
 
8815
                return(COMPATIBLE_DATA_NO);
 
8816
        }
 
8817
 
 
8818
        /* Specifying KEY_BLOCK_SIZE requests a rebuild of the table. */
 
8819
        if (info->used_fields & HA_CREATE_USED_KEY_BLOCK_SIZE) {
 
8820
                return(COMPATIBLE_DATA_NO);
 
8821
        }
 
8822
 
 
8823
        return(COMPATIBLE_DATA_YES);
 
8824
}
 
8825
 
 
8826
/****************************************************************
 
8827
Validate the file format name and return its corresponding id. */
 
8828
static
 
8829
uint
 
8830
innobase_file_format_name_lookup(
 
8831
/*=============================*/
 
8832
                                        /* out: valid file format id*/
 
8833
        const char*     format_name)    /* in: pointer to file format name */
 
8834
{
 
8835
        char*   endp;
 
8836
        uint    format_id;
 
8837
 
 
8838
        ut_a(format_name != NULL);
 
8839
 
 
8840
        /* The format name can contain the format id itself instead of
 
8841
        the name and we check for that. */
 
8842
        format_id = (uint) strtoul(format_name, &endp, 10);
 
8843
 
 
8844
        /* Check for valid parse. */
 
8845
        if (*endp == '\0' && *format_name != '\0') {
 
8846
 
 
8847
                if (format_id <= DICT_TF_FORMAT_MAX) {
 
8848
 
 
8849
                        return(format_id);
 
8850
                }
 
8851
        } else {
 
8852
 
 
8853
                for (format_id = 0; format_id <= DICT_TF_FORMAT_MAX;
 
8854
                     format_id++) {
 
8855
                        const char*     name;
 
8856
 
 
8857
                        name = trx_sys_file_format_id_to_name(format_id);
 
8858
 
 
8859
                        if (!innobase_strcasecmp(format_name, name)) {
 
8860
 
 
8861
                                return(format_id);
 
8862
                        }
 
8863
                }
 
8864
        }
 
8865
 
 
8866
        return(DICT_TF_FORMAT_MAX + 1);
 
8867
}
 
8868
 
 
8869
/****************************************************************
 
8870
Validate the file format check value, is it one of "on" or "off",
 
8871
as a side affect it sets the srv_check_file_format_at_startup variable. */
 
8872
static
 
8873
bool
 
8874
innobase_file_format_check_on_off(
 
8875
/*==============================*/
 
8876
                                        /* out: true if config value one
 
8877
                                        of "on" or  "off" */
 
8878
        const char*     format_check)   /* in: parameter value */
 
8879
{
 
8880
        bool            ret = true;
 
8881
 
 
8882
        if (!innobase_strcasecmp(format_check, "off")) {
 
8883
 
 
8884
                /* Set the value to disable checking. */
 
8885
                srv_check_file_format_at_startup = DICT_TF_FORMAT_MAX + 1;
 
8886
 
 
8887
        } else if (!innobase_strcasecmp(format_check, "on")) {
 
8888
 
 
8889
                /* Set the value to the lowest supported format. */
 
8890
                srv_check_file_format_at_startup = DICT_TF_FORMAT_51;
 
8891
        } else {
 
8892
                ret = FALSE;
 
8893
        }
 
8894
 
 
8895
        return(ret);
 
8896
}
 
8897
 
 
8898
/****************************************************************
 
8899
Validate the file format check config parameters, as a side affect it
 
8900
sets the srv_check_file_format_at_startup variable. */
 
8901
static
 
8902
bool
 
8903
innobase_file_format_check_validate(
 
8904
/*================================*/
 
8905
                                        /* out: true if valid config value */
 
8906
        const char*     format_check)   /* in: parameter value */
 
8907
{
 
8908
        uint            format_id;
 
8909
        bool            ret = true;
 
8910
                
 
8911
        format_id = innobase_file_format_name_lookup(format_check);
 
8912
 
 
8913
        if (format_id < DICT_TF_FORMAT_MAX + 1) {
 
8914
                srv_check_file_format_at_startup = format_id;
 
8915
        } else {
 
8916
                ret = false;
 
8917
        }
 
8918
 
 
8919
        return(ret);
 
8920
}
 
8921
 
 
8922
/*****************************************************************
 
8923
Check if it is a valid file format. This function is registered as
 
8924
a callback with MySQL. */
 
8925
static
 
8926
int
 
8927
innodb_file_format_name_validate(
 
8928
/*=============================*/
 
8929
                                                /* out: 0 for valid file
 
8930
                                                format */
 
8931
        THD*                            thd,    /* in: thread handle */
 
8932
        struct st_mysql_sys_var*        var,    /* in: pointer to system
 
8933
                                                variable */
 
8934
        void*                           save,   /* out: immediate result
 
8935
                                                for update function */
 
8936
        struct st_mysql_value*          value)  /* in: incoming string */
 
8937
{
 
8938
        const char*     file_format_input;
 
8939
        char            buff[STRING_BUFFER_USUAL_SIZE];
 
8940
        int             len = sizeof(buff);
 
8941
 
 
8942
        ut_a(save != NULL);
 
8943
        ut_a(value != NULL);
 
8944
 
 
8945
        file_format_input = value->val_str(value, buff, &len);
 
8946
 
 
8947
        if (file_format_input != NULL) {
 
8948
                uint    format_id;
 
8949
 
 
8950
                format_id = innobase_file_format_name_lookup(
 
8951
                        file_format_input);
 
8952
 
 
8953
                if (format_id <= DICT_TF_FORMAT_MAX) {
 
8954
 
 
8955
                        *(uint*) save = format_id;
 
8956
                        return(0);
 
8957
                }
 
8958
        }
 
8959
 
 
8960
        return(1);
 
8961
}
 
8962
 
 
8963
/********************************************************************
 
8964
Update the system variable innodb_file_format using the "saved"
 
8965
value. This function is registered as a callback with MySQL. */
 
8966
static
 
8967
bool
 
8968
innodb_file_format_name_update(
 
8969
/*===========================*/
 
8970
                                                        /* out: should never
 
8971
                                                        fail since it is
 
8972
                                                        already validated */
 
8973
        THD*                            thd,            /* in: thread handle */
 
8974
        struct st_mysql_sys_var*        var,            /* in: pointer to
 
8975
                                                        system variable */
 
8976
        void*                           var_ptr,        /* out: where the
 
8977
                                                        formal string goes */
 
8978
        void*                           save)           /* in: immediate result
 
8979
                                                        from check function */
 
8980
{
 
8981
        ut_a(var_ptr != NULL);
 
8982
        ut_a(save != NULL);
 
8983
        ut_a((*(uint*) save) <= DICT_TF_FORMAT_MAX);
 
8984
 
 
8985
        srv_file_format = *(uint*) save;
 
8986
 
 
8987
        /* Given the type of var_ptr we have little choice but to cast
 
8988
        away the constness from the returned name. */
 
8989
        (*(char**) var_ptr) = 
 
8990
                (char*) trx_sys_file_format_id_to_name(srv_file_format);
 
8991
 
 
8992
        return(true);
 
8993
}
 
8994
 
 
8995
/*****************************************************************
 
8996
Check if valid argument to innodb_file_format_check. This
 
8997
function is registered as a callback with MySQL. */
 
8998
static
 
8999
int
 
9000
innodb_file_format_check_validate(
 
9001
/*==============================*/
 
9002
                                                /* out: 0 for valid file
 
9003
                                                format */
 
9004
        THD*                            thd,    /* in: thread handle */
 
9005
        struct st_mysql_sys_var*        var,    /* in: pointer to system
 
9006
                                                variable */
 
9007
        void*                           save,   /* out: immediate result
 
9008
                                                for update function */
 
9009
        struct st_mysql_value*          value)  /* in: incoming string */
 
9010
{
 
9011
        const char*     file_format_input;
 
9012
        char            buff[STRING_BUFFER_USUAL_SIZE];
 
9013
        int             len = sizeof(buff);
 
9014
 
 
9015
        ut_a(save != NULL);
 
9016
        ut_a(value != NULL);
 
9017
 
 
9018
        file_format_input = value->val_str(value, buff, &len);
 
9019
 
 
9020
        if (file_format_input != NULL) {
 
9021
 
 
9022
                /* Check if user set on/off, we want to print a suitable
 
9023
                message if they did so. */
 
9024
 
 
9025
                if (innobase_file_format_check_on_off(file_format_input)) {
 
9026
                        sql_print_warning(
 
9027
                                "InnoDB: invalid innodb_file_format_check"
 
9028
                                "value; on/off can only be set at startup or "
 
9029
                                "in the configuration file");
 
9030
                } else if (innobase_file_format_check_validate(
 
9031
                                file_format_input)) {
 
9032
 
 
9033
                        uint    format_id;
 
9034
 
 
9035
                        format_id = innobase_file_format_name_lookup(
 
9036
                                file_format_input);
 
9037
 
 
9038
                        ut_a(format_id <= DICT_TF_FORMAT_MAX);
 
9039
 
 
9040
                        *(uint*) save = format_id;
 
9041
 
 
9042
                        return(0);
 
9043
 
 
9044
                } else {
 
9045
                        sql_print_warning(
 
9046
                                "InnoDB: invalid innodb_file_format_check "
 
9047
                                "value; can be any format up to %s "
 
9048
                                "or its equivalent numeric id",
 
9049
                                trx_sys_file_format_id_to_name(
 
9050
                                        DICT_TF_FORMAT_MAX));
 
9051
                }
 
9052
        }
 
9053
 
 
9054
        return(1);
 
9055
}
 
9056
 
 
9057
/********************************************************************
 
9058
Update the system variable innodb_file_format_check using the "saved"
 
9059
value. This function is registered as a callback with MySQL. */
 
9060
static
 
9061
bool
 
9062
innodb_file_format_check_update(
 
9063
/*============================*/
 
9064
                                                        /* out: should never
 
9065
                                                        fail since it is
 
9066
                                                        already validated */
 
9067
        THD*                            thd,            /* in: thread handle */
 
9068
        struct st_mysql_sys_var*        var,            /* in: pointer to
 
9069
                                                        system variable */
 
9070
        void*                           var_ptr,        /* out: where the
 
9071
                                                        formal string goes */
 
9072
        void*                           save)           /* in: immediate result
 
9073
                                                        from check function */
 
9074
{
 
9075
        uint    format_id;
 
9076
 
 
9077
        ut_a(save != NULL);
 
9078
        ut_a(var_ptr != NULL);
 
9079
 
 
9080
        format_id = *(uint*) save;
 
9081
 
 
9082
        /* Update the max format id in the system tablespace. */
 
9083
        if (trx_sys_file_format_max_set(format_id, (char**) var_ptr)) {
 
9084
                ut_print_timestamp(stderr);
 
9085
                fprintf(stderr,
 
9086
                        " [Info] InnoDB: the file format in the system "
 
9087
                        "tablespace is now set to %s.\n", *(char**) var_ptr);
 
9088
        }
 
9089
 
 
9090
        return(true);
 
9091
}
 
9092
 
 
9093
static int show_innodb_vars(THD *thd, SHOW_VAR *var, char *buff)
 
9094
{
 
9095
  innodb_export_status();
 
9096
  var->type= SHOW_ARRAY;
 
9097
  var->value= (char *) &innodb_status_variables;
 
9098
  return 0;
 
9099
}
 
9100
 
 
9101
static SHOW_VAR innodb_status_variables_export[]= {
 
9102
  {"Innodb",                   (char*) &show_innodb_vars, SHOW_FUNC},
 
9103
  {NullS, NullS, SHOW_LONG}
 
9104
};
 
9105
 
 
9106
static struct st_mysql_storage_engine innobase_storage_engine=
 
9107
{ MYSQL_HANDLERTON_INTERFACE_VERSION };
 
9108
 
 
9109
/* plugin options */
 
9110
static MYSQL_SYSVAR_BOOL(checksums, innobase_use_checksums,
 
9111
  PLUGIN_VAR_NOCMDARG | PLUGIN_VAR_READONLY,
 
9112
  "Enable InnoDB checksums validation (enabled by default). "
 
9113
  "Disable with --skip-innodb-checksums.",
 
9114
  NULL, NULL, TRUE);
 
9115
 
 
9116
static MYSQL_SYSVAR_STR(data_home_dir, innobase_data_home_dir,
 
9117
  PLUGIN_VAR_READONLY,
 
9118
  "The common part for InnoDB table spaces.",
 
9119
  NULL, NULL, NULL);
 
9120
 
 
9121
static MYSQL_SYSVAR_BOOL(doublewrite, innobase_use_doublewrite,
 
9122
  PLUGIN_VAR_NOCMDARG | PLUGIN_VAR_READONLY,
 
9123
  "Enable InnoDB doublewrite buffer (enabled by default). "
 
9124
  "Disable with --skip-innodb-doublewrite.",
 
9125
  NULL, NULL, TRUE);
 
9126
 
 
9127
static MYSQL_SYSVAR_ULONG(fast_shutdown, innobase_fast_shutdown,
 
9128
  PLUGIN_VAR_OPCMDARG,
 
9129
  "Speeds up the shutdown process of the InnoDB storage engine. Possible "
 
9130
  "values are 0, 1 (faster)"
 
9131
  /*
 
9132
    NetWare can't close unclosed files, can't automatically kill remaining
 
9133
    threads, etc, so on this OS we disable the crash-like InnoDB shutdown.
 
9134
  */
 
9135
  IF_NETWARE("", " or 2 (fastest - crash-like)")
 
9136
  ".",
 
9137
  NULL, NULL, 1, 0, IF_NETWARE(1,2), 0);
 
9138
 
 
9139
static MYSQL_SYSVAR_BOOL(file_per_table, srv_file_per_table,
 
9140
  PLUGIN_VAR_NOCMDARG,
 
9141
  "Stores each InnoDB table to an .ibd file in the database dir.",
 
9142
  NULL, NULL, FALSE);
 
9143
 
 
9144
static MYSQL_SYSVAR_STR(file_format, innobase_file_format_name,
 
9145
  PLUGIN_VAR_RQCMDARG,
 
9146
  "File format to use for new tables in .ibd files.",
 
9147
  (mysql_var_check_func) &innodb_file_format_name_validate,
 
9148
  (mysql_var_update_func) &innodb_file_format_name_update, "Antelope");
 
9149
 
 
9150
static MYSQL_SYSVAR_STR(file_format_check, innobase_file_format_check,
 
9151
  PLUGIN_VAR_OPCMDARG,
 
9152
  "The highest file format in the tablespace.",
 
9153
  (mysql_var_check_func) &innodb_file_format_check_validate,
 
9154
  (mysql_var_update_func) &innodb_file_format_check_update,
 
9155
  "on");
 
9156
 
 
9157
static MYSQL_SYSVAR_ULONG(flush_log_at_trx_commit, srv_flush_log_at_trx_commit,
 
9158
  PLUGIN_VAR_OPCMDARG,
 
9159
  "Set to 0 (write and flush once per second),"
 
9160
  " 1 (write and flush at each commit)"
 
9161
  " or 2 (write at commit, flush once per second).",
 
9162
  NULL, NULL, 1, 0, 2, 0);
 
9163
 
 
9164
static MYSQL_SYSVAR_STR(flush_method, innobase_unix_file_flush_method,
 
9165
  PLUGIN_VAR_RQCMDARG | PLUGIN_VAR_READONLY,
 
9166
  "With which method to flush data.", NULL, NULL, NULL);
 
9167
 
 
9168
static MYSQL_SYSVAR_BOOL(locks_unsafe_for_binlog, innobase_locks_unsafe_for_binlog,
 
9169
  PLUGIN_VAR_NOCMDARG | PLUGIN_VAR_READONLY,
 
9170
  "Force InnoDB to not use next-key locking, to use only row-level locking.",
 
9171
  NULL, NULL, FALSE);
 
9172
 
 
9173
#ifdef UNIV_LOG_ARCHIVE
 
9174
static MYSQL_SYSVAR_STR(log_arch_dir, innobase_log_arch_dir,
 
9175
  PLUGIN_VAR_RQCMDARG | PLUGIN_VAR_READONLY,
 
9176
  "Where full logs should be archived.", NULL, NULL, NULL);
 
9177
 
 
9178
static MYSQL_SYSVAR_BOOL(log_archive, innobase_log_archive,
 
9179
  PLUGIN_VAR_OPCMDARG | PLUGIN_VAR_READONLY,
 
9180
  "Set to 1 if you want to have logs archived.", NULL, NULL, FALSE);
 
9181
#endif /* UNIV_LOG_ARCHIVE */
 
9182
 
 
9183
static MYSQL_SYSVAR_STR(log_group_home_dir, innobase_log_group_home_dir,
 
9184
  PLUGIN_VAR_RQCMDARG | PLUGIN_VAR_READONLY,
 
9185
  "Path to InnoDB log files.", NULL, NULL, NULL);
 
9186
 
 
9187
static MYSQL_SYSVAR_ULONG(max_dirty_pages_pct, srv_max_buf_pool_modified_pct,
 
9188
  PLUGIN_VAR_RQCMDARG,
 
9189
  "Percentage of dirty pages allowed in bufferpool.",
 
9190
  NULL, NULL, 90, 0, 100, 0);
 
9191
 
 
9192
static MYSQL_SYSVAR_ULONG(max_purge_lag, srv_max_purge_lag,
 
9193
  PLUGIN_VAR_RQCMDARG,
 
9194
  "Desired maximum length of the purge queue (0 = no limit)",
 
9195
  NULL, NULL, 0, 0, ~0L, 0);
 
9196
 
 
9197
static MYSQL_SYSVAR_BOOL(rollback_on_timeout, innobase_rollback_on_timeout,
 
9198
  PLUGIN_VAR_OPCMDARG | PLUGIN_VAR_READONLY,
 
9199
  "Roll back the complete transaction on lock wait timeout, for 4.x compatibility (disabled by default)",
 
9200
  NULL, NULL, FALSE);
 
9201
 
 
9202
static MYSQL_SYSVAR_BOOL(status_file, innobase_create_status_file,
 
9203
  PLUGIN_VAR_OPCMDARG | PLUGIN_VAR_NOSYSVAR,
 
9204
  "Enable SHOW INNODB STATUS output in the innodb_status.<pid> file",
 
9205
  NULL, NULL, FALSE);
 
9206
 
 
9207
static MYSQL_SYSVAR_BOOL(stats_on_metadata, innobase_stats_on_metadata,
 
9208
  PLUGIN_VAR_OPCMDARG | PLUGIN_VAR_NOSYSVAR,
 
9209
  "Enable statistics gathering for metadata commands such as SHOW TABLE STATUS (on by default)",
 
9210
  NULL, NULL, TRUE);
 
9211
 
 
9212
static MYSQL_SYSVAR_BOOL(adaptive_hash_index, innobase_adaptive_hash_index,
 
9213
  PLUGIN_VAR_OPCMDARG | PLUGIN_VAR_READONLY,
 
9214
  "Enable InnoDB adaptive hash index (enabled by default).  "
 
9215
  "Disable with --skip-innodb-adaptive-hash-index.",
 
9216
  NULL, NULL, TRUE);
 
9217
 
 
9218
static MYSQL_SYSVAR_ULONG(replication_delay, srv_replication_delay,
 
9219
  PLUGIN_VAR_RQCMDARG,
 
9220
  "Replication thread delay (ms) on the slave server if "
 
9221
  "innodb_thread_concurrency is reached (0 by default)",
 
9222
  NULL, NULL, 0, 0, ~0UL, 0);
 
9223
 
 
9224
static MYSQL_SYSVAR_LONG(additional_mem_pool_size, innobase_additional_mem_pool_size,
 
9225
  PLUGIN_VAR_RQCMDARG | PLUGIN_VAR_READONLY,
 
9226
  "Size of a memory pool InnoDB uses to store data dictionary information and other internal data structures.",
 
9227
  NULL, NULL, 1*1024*1024L, 512*1024L, ~0L, 1024);
 
9228
 
 
9229
static MYSQL_SYSVAR_ULONG(autoextend_increment, srv_auto_extend_increment,
 
9230
  PLUGIN_VAR_RQCMDARG,
 
9231
  "Data file autoextend increment in megabytes",
 
9232
  NULL, NULL, 8L, 1L, 1000L, 0);
 
9233
 
 
9234
static MYSQL_SYSVAR_LONGLONG(buffer_pool_size, innobase_buffer_pool_size,
 
9235
  PLUGIN_VAR_RQCMDARG | PLUGIN_VAR_READONLY,
 
9236
  "The size of the memory buffer InnoDB uses to cache data and indexes of its tables.",
 
9237
  NULL, NULL, 8*1024*1024L, 5*1024*1024L, LONGLONG_MAX, 1024*1024L);
 
9238
 
 
9239
static MYSQL_SYSVAR_ULONG(commit_concurrency, srv_commit_concurrency,
 
9240
  PLUGIN_VAR_RQCMDARG,
 
9241
  "Helps in performance tuning in heavily concurrent environments.",
 
9242
  NULL, NULL, 0, 0, 1000, 0);
 
9243
 
 
9244
static MYSQL_SYSVAR_ULONG(concurrency_tickets, srv_n_free_tickets_to_enter,
 
9245
  PLUGIN_VAR_RQCMDARG,
 
9246
  "Number of times a thread is allowed to enter InnoDB within the same SQL query after it has once got the ticket",
 
9247
  NULL, NULL, 500L, 1L, ~0L, 0);
 
9248
 
 
9249
static MYSQL_SYSVAR_LONG(file_io_threads, innobase_file_io_threads,
 
9250
  PLUGIN_VAR_RQCMDARG | PLUGIN_VAR_READONLY,
 
9251
  "Number of file I/O threads in InnoDB.",
 
9252
  NULL, NULL, 4, 4, 64, 0);
 
9253
 
 
9254
static MYSQL_SYSVAR_LONG(force_recovery, innobase_force_recovery,
 
9255
  PLUGIN_VAR_RQCMDARG | PLUGIN_VAR_READONLY,
 
9256
  "Helps to save your data in case the disk image of the database becomes corrupt.",
 
9257
  NULL, NULL, 0, 0, 6, 0);
 
9258
 
 
9259
static MYSQL_SYSVAR_LONG(lock_wait_timeout, innobase_lock_wait_timeout,
 
9260
  PLUGIN_VAR_RQCMDARG | PLUGIN_VAR_READONLY,
 
9261
  "Timeout in seconds an InnoDB transaction may wait for a lock before being rolled back.",
 
9262
  NULL, NULL, 50, 1, 1024 * 1024 * 1024, 0);
 
9263
 
 
9264
static MYSQL_SYSVAR_LONG(log_buffer_size, innobase_log_buffer_size,
 
9265
  PLUGIN_VAR_RQCMDARG | PLUGIN_VAR_READONLY,
 
9266
  "The size of the buffer which InnoDB uses to write log to the log files on disk.",
 
9267
  NULL, NULL, 1024*1024L, 256*1024L, ~0L, 1024);
 
9268
 
 
9269
static MYSQL_SYSVAR_LONGLONG(log_file_size, innobase_log_file_size,
 
9270
  PLUGIN_VAR_RQCMDARG | PLUGIN_VAR_READONLY,
 
9271
  "Size of each log file in a log group.",
 
9272
  NULL, NULL, 5*1024*1024L, 1*1024*1024L, LONGLONG_MAX, 1024*1024L);
 
9273
 
 
9274
static MYSQL_SYSVAR_LONG(log_files_in_group, innobase_log_files_in_group,
 
9275
  PLUGIN_VAR_RQCMDARG | PLUGIN_VAR_READONLY,
 
9276
  "Number of log files in the log group. InnoDB writes to the files in a circular fashion. Value 3 is recommended here.",
 
9277
  NULL, NULL, 2, 2, 100, 0);
 
9278
 
 
9279
static MYSQL_SYSVAR_LONG(mirrored_log_groups, innobase_mirrored_log_groups,
 
9280
  PLUGIN_VAR_RQCMDARG | PLUGIN_VAR_READONLY,
 
9281
  "Number of identical copies of log groups we keep for the database. Currently this should be set to 1.",
 
9282
  NULL, NULL, 1, 1, 10, 0);
 
9283
 
 
9284
static MYSQL_SYSVAR_LONG(open_files, innobase_open_files,
 
9285
  PLUGIN_VAR_RQCMDARG | PLUGIN_VAR_READONLY,
 
9286
  "How many files at the maximum InnoDB keeps open at the same time.",
 
9287
  NULL, NULL, 300L, 10L, ~0L, 0);
 
9288
 
 
9289
static MYSQL_SYSVAR_ULONG(sync_spin_loops, srv_n_spin_wait_rounds,
 
9290
  PLUGIN_VAR_RQCMDARG,
 
9291
  "Count of spin-loop rounds in InnoDB mutexes",
 
9292
  NULL, NULL, 20L, 0L, ~0L, 0);
 
9293
 
 
9294
static MYSQL_SYSVAR_ULONG(thread_concurrency, srv_thread_concurrency,
 
9295
  PLUGIN_VAR_RQCMDARG,
 
9296
  "Helps in performance tuning in heavily concurrent environments. Sets the maximum number of threads allowed inside InnoDB. Value 0 will disable the thread throttling.",
 
9297
  NULL, NULL, 8, 0, 1000, 0);
 
9298
 
 
9299
static MYSQL_SYSVAR_ULONG(thread_sleep_delay, srv_thread_sleep_delay,
 
9300
  PLUGIN_VAR_RQCMDARG,
 
9301
  "Time of innodb thread sleeping before joining InnoDB queue (usec). Value 0 disable a sleep",
 
9302
  NULL, NULL, 10000L, 0L, ~0L, 0);
 
9303
 
 
9304
static MYSQL_SYSVAR_STR(data_file_path, innobase_data_file_path,
 
9305
  PLUGIN_VAR_RQCMDARG | PLUGIN_VAR_READONLY,
 
9306
  "Path to individual files and their sizes.",
 
9307
  NULL, NULL, NULL);
 
9308
 
 
9309
static MYSQL_SYSVAR_LONG(autoinc_lock_mode, innobase_autoinc_lock_mode,
 
9310
  PLUGIN_VAR_RQCMDARG | PLUGIN_VAR_READONLY,
 
9311
  "The AUTOINC lock modes supported by InnoDB:               "
 
9312
  "0 => Old style AUTOINC locking (for backward"
 
9313
  " compatibility)                                           "
 
9314
  "1 => New style AUTOINC locking                            "
 
9315
  "2 => No AUTOINC locking (unsafe for SBR)",
 
9316
  NULL, NULL,
 
9317
  AUTOINC_NEW_STYLE_LOCKING,    /* Default setting */
 
9318
  AUTOINC_OLD_STYLE_LOCKING,    /* Minimum value */
 
9319
  AUTOINC_NO_LOCKING, 0);       /* Maximum value */
 
9320
 
 
9321
static MYSQL_SYSVAR_STR(version, innodb_version_str,
 
9322
  PLUGIN_VAR_NOCMDOPT | PLUGIN_VAR_READONLY,
 
9323
  "InnoDB version", NULL, NULL, INNODB_VERSION_STR);
 
9324
 
 
9325
static struct st_mysql_sys_var* innobase_system_variables[]= {
 
9326
  MYSQL_SYSVAR(additional_mem_pool_size),
 
9327
  MYSQL_SYSVAR(autoextend_increment),
 
9328
  MYSQL_SYSVAR(buffer_pool_size),
 
9329
  MYSQL_SYSVAR(checksums),
 
9330
  MYSQL_SYSVAR(commit_concurrency),
 
9331
  MYSQL_SYSVAR(concurrency_tickets),
 
9332
  MYSQL_SYSVAR(data_file_path),
 
9333
  MYSQL_SYSVAR(data_home_dir),
 
9334
  MYSQL_SYSVAR(doublewrite),
 
9335
  MYSQL_SYSVAR(fast_shutdown),
 
9336
  MYSQL_SYSVAR(file_io_threads),
 
9337
  MYSQL_SYSVAR(file_per_table),
 
9338
  MYSQL_SYSVAR(file_format),
 
9339
  MYSQL_SYSVAR(file_format_check),
 
9340
  MYSQL_SYSVAR(flush_log_at_trx_commit),
 
9341
  MYSQL_SYSVAR(flush_method),
 
9342
  MYSQL_SYSVAR(force_recovery),
 
9343
  MYSQL_SYSVAR(locks_unsafe_for_binlog),
 
9344
  MYSQL_SYSVAR(lock_wait_timeout),
 
9345
#ifdef UNIV_LOG_ARCHIVE
 
9346
  MYSQL_SYSVAR(log_arch_dir),
 
9347
  MYSQL_SYSVAR(log_archive),
 
9348
#endif /* UNIV_LOG_ARCHIVE */
 
9349
  MYSQL_SYSVAR(log_buffer_size),
 
9350
  MYSQL_SYSVAR(log_file_size),
 
9351
  MYSQL_SYSVAR(log_files_in_group),
 
9352
  MYSQL_SYSVAR(log_group_home_dir),
 
9353
  MYSQL_SYSVAR(max_dirty_pages_pct),
 
9354
  MYSQL_SYSVAR(max_purge_lag),
 
9355
  MYSQL_SYSVAR(mirrored_log_groups),
 
9356
  MYSQL_SYSVAR(open_files),
 
9357
  MYSQL_SYSVAR(rollback_on_timeout),
 
9358
  MYSQL_SYSVAR(stats_on_metadata),
 
9359
  MYSQL_SYSVAR(adaptive_hash_index),
 
9360
  MYSQL_SYSVAR(replication_delay),
 
9361
  MYSQL_SYSVAR(status_file),
 
9362
  MYSQL_SYSVAR(strict_mode),
 
9363
  MYSQL_SYSVAR(support_xa),
 
9364
  MYSQL_SYSVAR(sync_spin_loops),
 
9365
  MYSQL_SYSVAR(table_locks),
 
9366
  MYSQL_SYSVAR(thread_concurrency),
 
9367
  MYSQL_SYSVAR(thread_sleep_delay),
 
9368
  MYSQL_SYSVAR(autoinc_lock_mode),
 
9369
  MYSQL_SYSVAR(version),
 
9370
  NULL
 
9371
};
 
9372
 
 
9373
#ifdef MYSQL_DYNAMIC_PLUGIN
 
9374
struct st_mysql_sys_var
 
9375
{
 
9376
        MYSQL_PLUGIN_VAR_HEADER;
 
9377
        void* value;
 
9378
};
 
9379
 
 
9380
struct param_mapping
 
9381
{
 
9382
        const char*     server;         /* Parameter name in the server. */
 
9383
        const char*     plugin;         /* Paramater name in the plugin. */
 
9384
};
 
9385
 
 
9386
/********************************************************************
 
9387
Match the parameters from the static and dynamic versions. */
 
9388
static
 
9389
bool
 
9390
innobase_match_parameter(
 
9391
/*=====================*/
 
9392
                                        /* out: true if names match */
 
9393
        const char*     from_server,    /* in: variable name from server */
 
9394
        const char*     from_plugin)    /* in: variable name from plugin */
 
9395
{
 
9396
        static const param_mapping param_map[] = {
 
9397
                {"use_adaptive_hash_indexes", "adaptive_hash_index"}
 
9398
        };
 
9399
 
 
9400
        if (strcmp(from_server, from_plugin) == 0) {
 
9401
                return(true);
 
9402
        }
 
9403
 
 
9404
        const param_mapping*    param = param_map;
 
9405
        int     n_elems = sizeof(param_map) / sizeof(param_map[0]);
 
9406
 
 
9407
        for (int i = 0; i < n_elems; ++i, ++param) {
 
9408
 
 
9409
                if (strcmp(param->server, from_server) == 0
 
9410
                    && strcmp(param->plugin, from_plugin) == 0) {
 
9411
 
 
9412
                        return(true);
 
9413
                }
 
9414
        }
 
9415
 
 
9416
        return(false);
 
9417
}
 
9418
 
 
9419
/********************************************************************
 
9420
Copy InnoDB system variables from the static InnoDB to the dynamic
 
9421
plugin. */
 
9422
static
 
9423
bool
 
9424
innodb_plugin_init(void)
 
9425
/*====================*/
 
9426
                /* out: TRUE if the dynamic InnoDB plugin should start */
 
9427
{
 
9428
# if !MYSQL_STORAGE_ENGINE_PLUGIN
 
9429
#  error "MYSQL_STORAGE_ENGINE_PLUGIN must be nonzero."
 
9430
# endif
 
9431
        switch (builtin_innobase_plugin) {
 
9432
        case 0:
 
9433
                return(true);
 
9434
        case MYSQL_STORAGE_ENGINE_PLUGIN:
 
9435
                break;
 
9436
        default:
 
9437
                return(false);
 
9438
        }
 
9439
 
 
9440
        /* Copy the system variables. */
 
9441
        struct st_mysql_plugin* builtin
 
9442
                = (struct st_mysql_plugin*) &builtin_innobase_plugin;
 
9443
        struct st_mysql_sys_var** v = builtin->system_vars;
 
9444
        struct st_mysql_sys_var** w = innobase_system_variables;
 
9445
 
 
9446
        for (; *v; v++, w++) {
 
9447
                if (!*w) {
 
9448
                        fprintf(stderr, "InnoDB: unknown parameter %s,0x%x\n",
 
9449
                                (*v)->name, (*v)->flags);
 
9450
                        return(false);
 
9451
                } else if (!innobase_match_parameter((*v)->name, (*w)->name)) {
 
9452
                        /* Skip the destination parameter, since it doesn't
 
9453
                        exist in the source. */
 
9454
                        v--;
 
9455
                        continue;
 
9456
                /* Ignore changes that affect the READONLY flag. */
 
9457
                } else if (((*v)->flags ^ (*w)->flags) & ~PLUGIN_VAR_READONLY) {
 
9458
                        fprintf(stderr,
 
9459
                                "InnoDB: parameter mismatch:"
 
9460
                                " %s,%s,0x%x,0x%x\n",
 
9461
                                (*v)->name, (*w)->name,
 
9462
                                (*v)->flags, (*w)->flags);
 
9463
                        return(false);
 
9464
                } else if ((*v)->flags & PLUGIN_VAR_THDLOCAL) {
 
9465
                        /* Do not copy session variables. */
 
9466
                        continue;
 
9467
                }
 
9468
 
 
9469
                switch ((*v)->flags
 
9470
                        & ~(PLUGIN_VAR_MASK | PLUGIN_VAR_UNSIGNED)) {
 
9471
# define COPY_VAR(label, type)                                          \
 
9472
                case label:                                             \
 
9473
                        *(type*)(*w)->value = *(type*)(*v)->value;      \
 
9474
                        break;
 
9475
 
 
9476
                        COPY_VAR(PLUGIN_VAR_BOOL, char);
 
9477
                        COPY_VAR(PLUGIN_VAR_INT, int);
 
9478
                        COPY_VAR(PLUGIN_VAR_LONG, long);
 
9479
                        COPY_VAR(PLUGIN_VAR_LONGLONG, long long);
 
9480
                        COPY_VAR(PLUGIN_VAR_STR, char*);
 
9481
 
 
9482
                default:
 
9483
                        fprintf(stderr, "InnoDB: unknown flags 0x%x for %s\n",
 
9484
                                (*v)->flags, (*v)->name);
 
9485
                }
 
9486
 
 
9487
                /* Make the static InnoDB variable point to the dynamic one */
 
9488
                (*v)->value = (*w)->value;
 
9489
        }
 
9490
 
 
9491
        return(true);
 
9492
}
 
9493
#endif /* MYSQL_DYNAMIC_PLUGIN */
 
9494
 
 
9495
mysql_declare_plugin(innobase)
 
9496
{
 
9497
  MYSQL_STORAGE_ENGINE_PLUGIN,
 
9498
  &innobase_storage_engine,
 
9499
  innobase_hton_name,
 
9500
  "Innobase Oy",
 
9501
  "Supports transactions, row-level locking, and foreign keys",
 
9502
  PLUGIN_LICENSE_GPL,
 
9503
  innobase_init, /* Plugin Init */
 
9504
  NULL, /* Plugin Deinit */
 
9505
  INNODB_VERSION_SHORT,
 
9506
  innodb_status_variables_export,/* status variables             */
 
9507
  innobase_system_variables, /* system variables */
 
9508
  NULL /* reserved */
 
9509
},
 
9510
i_s_innodb_trx,
 
9511
i_s_innodb_locks,
 
9512
i_s_innodb_lock_waits,
 
9513
i_s_innodb_cmp,
 
9514
i_s_innodb_cmp_reset,
 
9515
i_s_innodb_cmpmem,
 
9516
i_s_innodb_cmpmem_reset
 
9517
mysql_declare_plugin_end;
 
9518
 
 
9519
#ifdef UNIV_COMPILE_TEST_FUNCS
 
9520
 
 
9521
typedef struct innobase_convert_name_test_struct {
 
9522
        char*           buf;
 
9523
        ulint           buflen;
 
9524
        const char*     id;
 
9525
        ulint           idlen;
 
9526
        void*           thd;
 
9527
        ibool           file_id;
 
9528
 
 
9529
        const char*     expected;
 
9530
} innobase_convert_name_test_t;
 
9531
 
 
9532
void
 
9533
test_innobase_convert_name()
 
9534
{
 
9535
        char    buf[1024];
 
9536
        ulint   i;
 
9537
 
 
9538
        innobase_convert_name_test_t test_input[] = {
 
9539
                {buf, sizeof(buf), "abcd", 4, NULL, TRUE, "\"abcd\""},
 
9540
                {buf, 7, "abcd", 4, NULL, TRUE, "\"abcd\""},
 
9541
                {buf, 6, "abcd", 4, NULL, TRUE, "\"abcd\""},
 
9542
                {buf, 5, "abcd", 4, NULL, TRUE, "\"abc\""},
 
9543
                {buf, 4, "abcd", 4, NULL, TRUE, "\"ab\""},
 
9544
 
 
9545
                {buf, sizeof(buf), "ab@0060cd", 9, NULL, TRUE, "\"ab`cd\""},
 
9546
                {buf, 9, "ab@0060cd", 9, NULL, TRUE, "\"ab`cd\""},
 
9547
                {buf, 8, "ab@0060cd", 9, NULL, TRUE, "\"ab`cd\""},
 
9548
                {buf, 7, "ab@0060cd", 9, NULL, TRUE, "\"ab`cd\""},
 
9549
                {buf, 6, "ab@0060cd", 9, NULL, TRUE, "\"ab`c\""},
 
9550
                {buf, 5, "ab@0060cd", 9, NULL, TRUE, "\"ab`\""},
 
9551
                {buf, 4, "ab@0060cd", 9, NULL, TRUE, "\"ab\""},
 
9552
 
 
9553
                {buf, sizeof(buf), "ab\"cd", 5, NULL, TRUE,
 
9554
                        "\"#mysql50#ab\"\"cd\""},
 
9555
                {buf, 17, "ab\"cd", 5, NULL, TRUE,
 
9556
                        "\"#mysql50#ab\"\"cd\""},
 
9557
                {buf, 16, "ab\"cd", 5, NULL, TRUE,
 
9558
                        "\"#mysql50#ab\"\"c\""},
 
9559
                {buf, 15, "ab\"cd", 5, NULL, TRUE,
 
9560
                        "\"#mysql50#ab\"\"\""},
 
9561
                {buf, 14, "ab\"cd", 5, NULL, TRUE,
 
9562
                        "\"#mysql50#ab\""},
 
9563
                {buf, 13, "ab\"cd", 5, NULL, TRUE,
 
9564
                        "\"#mysql50#ab\""},
 
9565
                {buf, 12, "ab\"cd", 5, NULL, TRUE,
 
9566
                        "\"#mysql50#a\""},
 
9567
                {buf, 11, "ab\"cd", 5, NULL, TRUE,
 
9568
                        "\"#mysql50#\""},
 
9569
                {buf, 10, "ab\"cd", 5, NULL, TRUE,
 
9570
                        "\"#mysql50\""},
 
9571
 
 
9572
                {buf, sizeof(buf), "ab/cd", 5, NULL, TRUE, "\"ab\".\"cd\""},
 
9573
                {buf, 9, "ab/cd", 5, NULL, TRUE, "\"ab\".\"cd\""},
 
9574
                {buf, 8, "ab/cd", 5, NULL, TRUE, "\"ab\".\"c\""},
 
9575
                {buf, 7, "ab/cd", 5, NULL, TRUE, "\"ab\".\"\""},
 
9576
                {buf, 6, "ab/cd", 5, NULL, TRUE, "\"ab\"."},
 
9577
                {buf, 5, "ab/cd", 5, NULL, TRUE, "\"ab\"."},
 
9578
                {buf, 4, "ab/cd", 5, NULL, TRUE, "\"ab\""},
 
9579
                {buf, 3, "ab/cd", 5, NULL, TRUE, "\"a\""},
 
9580
                {buf, 2, "ab/cd", 5, NULL, TRUE, "\"\""},
 
9581
                /* XXX probably "" is a better result in this case
 
9582
                {buf, 1, "ab/cd", 5, NULL, TRUE, "."},
 
9583
                */
 
9584
                {buf, 0, "ab/cd", 5, NULL, TRUE, ""},
 
9585
        };
 
9586
 
 
9587
        for (i = 0; i < sizeof(test_input) / sizeof(test_input[0]); i++) {
 
9588
 
 
9589
                char*   end;
 
9590
                ibool   ok = TRUE;
 
9591
                size_t  res_len;
 
9592
 
 
9593
                fprintf(stderr, "TESTING %lu, %s, %lu, %s\n",
 
9594
                        test_input[i].buflen,
 
9595
                        test_input[i].id,
 
9596
                        test_input[i].idlen,
 
9597
                        test_input[i].expected);
 
9598
 
 
9599
                end = innobase_convert_name(
 
9600
                        test_input[i].buf,
 
9601
                        test_input[i].buflen,
 
9602
                        test_input[i].id,
 
9603
                        test_input[i].idlen,
 
9604
                        test_input[i].thd,
 
9605
                        test_input[i].file_id);
 
9606
 
 
9607
                res_len = (size_t) (end - test_input[i].buf);
 
9608
 
 
9609
                if (res_len != strlen(test_input[i].expected)) {
 
9610
 
 
9611
                        fprintf(stderr, "unexpected len of the result: %u, "
 
9612
                                "expected: %u\n", (unsigned) res_len,
 
9613
                                (unsigned) strlen(test_input[i].expected));
 
9614
                        ok = FALSE;
 
9615
                }
 
9616
 
 
9617
                if (memcmp(test_input[i].buf,
 
9618
                           test_input[i].expected,
 
9619
                           strlen(test_input[i].expected)) != 0
 
9620
                    || !ok) {
 
9621
 
 
9622
                        fprintf(stderr, "unexpected result: %.*s, "
 
9623
                                "expected: %s\n", (int) res_len,
 
9624
                                test_input[i].buf,
 
9625
                                test_input[i].expected);
 
9626
                        ok = FALSE;
 
9627
                }
 
9628
 
 
9629
                if (ok) {
 
9630
                        fprintf(stderr, "OK: res: %.*s\n\n", (int) res_len,
 
9631
                                buf);
 
9632
                } else {
 
9633
                        fprintf(stderr, "FAILED\n\n");
 
9634
                        return;
 
9635
                }
 
9636
        }
 
9637
}
 
9638
 
 
9639
#endif /* UNIV_COMPILE_TEST_FUNCS */