~skinny.moey/drizzle/branch-rev

« back to all changes in this revision

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

  • Committer: brian
  • Date: 2008-06-25 05:29:13 UTC
  • Revision ID: brian@localhost.localdomain-20080625052913-6upwo0jsrl4lnapl
clean slate

Show diffs side-by-side

added added

removed removed

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