~drizzle-trunk/drizzle/development

« back to all changes in this revision

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

  • Committer: Joe Daly
  • Date: 2010-03-08 04:23:54 UTC
  • mto: This revision was merged to the branch mainline in revision 1380.
  • Revision ID: skinny.moey@gmail.com-20100308042354-7k0jibdqaxkhac7o
scoreboardĀ implementationĀ forĀ statistics

Show diffs side-by-side

added added

removed removed

Lines of Context:
1
1
/*****************************************************************************
2
2
 
3
 
Copyright (c) 2000, 2010, MySQL AB & Innobase Oy. All Rights Reserved.
 
3
Copyright (c) 2000, 2009, MySQL AB & Innobase Oy. All Rights Reserved.
4
4
Copyright (c) 2008, 2009 Google Inc.
5
 
Copyright (c) 2009, Percona Inc.
6
5
 
7
6
Portions of this file contain modifications contributed and copyrighted by
8
7
Google, Inc. Those modifications are gratefully acknowledged and are described
10
9
incorporated with their permission, and subject to the conditions contained in
11
10
the file COPYING.Google.
12
11
 
13
 
Portions of this file contain modifications contributed and copyrighted
14
 
by Percona Inc.. Those modifications are
15
 
gratefully acknowledged and are described briefly in the InnoDB
16
 
documentation. The contributions by Percona Inc. are incorporated with
17
 
their permission, and subject to the conditions contained in the file
18
 
COPYING.Percona.
19
 
 
20
12
This program is free software; you can redistribute it and/or modify it under
21
13
the terms of the GNU General Public License as published by the Free Software
22
14
Foundation; version 2 of the License.
26
18
FOR A PARTICULAR PURPOSE. See the GNU General Public License for more details.
27
19
 
28
20
You should have received a copy of the GNU General Public License along with
29
 
this program; if not, write to the Free Software Foundation, Inc., 51 Franklin
30
 
St, Fifth Floor, Boston, MA 02110-1301 USA
 
21
this program; if not, write to the Free Software Foundation, Inc., 59 Temple
 
22
Place, Suite 330, Boston, MA 02111-1307 USA
31
23
 
32
24
*****************************************************************************/
 
25
/***********************************************************************
 
26
 
 
27
Copyright (c) 1995, 2009, Innobase Oy. All Rights Reserved.
 
28
Copyright (c) 2009, Percona Inc.
 
29
 
 
30
Portions of this file contain modifications contributed and copyrighted
 
31
by Percona Inc.. Those modifications are
 
32
gratefully acknowledged and are described briefly in the InnoDB
 
33
documentation. The contributions by Percona Inc. are incorporated with
 
34
their permission, and subject to the conditions contained in the file
 
35
COPYING.Percona.
 
36
 
 
37
This program is free software; you can redistribute it and/or modify it
 
38
under the terms of the GNU General Public License as published by the
 
39
Free Software Foundation; version 2 of the License.
 
40
 
 
41
This program is distributed in the hope that it will be useful, but
 
42
WITHOUT ANY WARRANTY; without even the implied warranty of
 
43
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General
 
44
Public License for more details.
 
45
 
 
46
You should have received a copy of the GNU General Public License along
 
47
with this program; if not, write to the Free Software Foundation, Inc.,
 
48
59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
 
49
 
 
50
***********************************************************************/
33
51
 
34
52
/* TODO list for the InnoDB Cursor in 5.0:
 
53
  - Remove the flag trx->active_trans and look at trx->conc_state
35
54
  - fix savepoint functions to use savepoint storage area
36
55
  - Find out what kind of problems the OS X case-insensitivity causes to
37
56
    table and database names; should we 'normalize' the names like we do
62
81
#include "drizzled/field/varstring.h"
63
82
#include "drizzled/field/timestamp.h"
64
83
#include "drizzled/plugin/xa_storage_engine.h"
65
 
#include "drizzled/plugin/daemon.h"
66
84
#include "drizzled/memory/multi_malloc.h"
67
85
#include "drizzled/pthread_globals.h"
68
86
#include "drizzled/named_savepoint.h"
69
87
 
70
88
#include <drizzled/transaction_services.h>
71
 
#include "drizzled/message/statement_transform.h"
72
 
 
73
 
#include <boost/algorithm/string.hpp>
74
 
#include <boost/program_options.hpp>
75
 
#include <boost/filesystem.hpp>
76
 
#include <drizzled/module/option_map.h>
77
 
#include <iostream>
78
 
 
79
 
namespace po= boost::program_options;
80
 
namespace fs=boost::filesystem;
81
 
using namespace std;
82
89
 
83
90
/** @file ha_innodb.cc */
84
91
 
85
92
/* Include necessary InnoDB headers */
86
93
extern "C" {
87
94
#include "univ.i"
88
 
#include "buf0lru.h"
89
95
#include "btr0sea.h"
90
96
#include "os0file.h"
91
97
#include "os0thread.h"
114
120
#include "ha_prototypes.h"
115
121
#include "ut0mem.h"
116
122
#include "ibuf0ibuf.h"
117
 
#include "mysql_addons.h"
118
123
}
119
124
 
120
125
#include "ha_innodb.h"
121
126
#include "data_dictionary.h"
122
 
#include "internal_dictionary.h"
123
127
#include "handler0vars.h"
124
128
 
125
129
#include <iostream>
131
135
using namespace std;
132
136
using namespace drizzled;
133
137
 
 
138
#ifndef DRIZZLE_SERVER
 
139
/* This is needed because of Bug #3596.  Let us hope that pthread_mutex_t
 
140
is defined the same in both builds: the MySQL server and the InnoDB plugin. */
 
141
extern pthread_mutex_t LOCK_thread_count;
 
142
 
 
143
#endif /* DRIZZLE_SERVER */
 
144
 
134
145
/** to protect innobase_open_files */
135
146
static pthread_mutex_t innobase_share_mutex;
136
147
/** to force correct commit order in binlog */
163
174
static plugin::TableFunction* innodb_locks_tool= NULL;
164
175
static plugin::TableFunction* innodb_lock_waits_tool= NULL;
165
176
 
 
177
static const long AUTOINC_OLD_STYLE_LOCKING = 0;
 
178
static const long AUTOINC_NEW_STYLE_LOCKING = 1;
 
179
static const long AUTOINC_NO_LOCKING = 2;
 
180
 
166
181
static long innobase_mirrored_log_groups, innobase_log_files_in_group,
167
 
  innobase_log_buffer_size,
168
 
  innobase_force_recovery, innobase_open_files;
169
 
static long innobase_additional_mem_pool_size= 8*1024*1024L;
 
182
        innobase_log_buffer_size,
 
183
        innobase_additional_mem_pool_size, innobase_file_io_threads,
 
184
        innobase_force_recovery, innobase_open_files,
 
185
        innobase_autoinc_lock_mode;
170
186
static ulong innobase_commit_concurrency = 0;
171
187
static ulong innobase_read_io_threads;
172
188
static ulong innobase_write_io_threads;
174
190
/**
175
191
 * @TODO: Turn this into size_t as soon as we have a Variable<size_t>
176
192
 */
177
 
static int64_t innobase_buffer_pool_size= 128*1024*1024;
178
 
static int64_t innobase_log_file_size;
179
 
 
180
 
/** Percentage of the buffer pool to reserve for 'old' blocks.
181
 
Connected to buf_LRU_old_ratio. */
182
 
static uint innobase_old_blocks_pct;
 
193
static int64_t innobase_buffer_pool_size, innobase_log_file_size;
183
194
 
184
195
/* The default values for the following char* start-up parameters
185
196
are determined in innobase_init below: */
186
197
 
187
 
static char*  innobase_data_home_dir      = NULL;
188
 
static char*  innobase_data_file_path     = NULL;
189
 
static char*  innobase_log_group_home_dir   = NULL;
190
 
static char*  innobase_file_format_name   = NULL;
191
 
static char*  innobase_change_buffering   = NULL;
 
198
static char*    innobase_data_home_dir                  = NULL;
 
199
static char*    innobase_data_file_path                 = NULL;
 
200
static char*    innobase_log_group_home_dir             = NULL;
 
201
static char*    innobase_file_format_name               = NULL;
 
202
static char*    innobase_change_buffering               = NULL;
192
203
 
193
204
/* Note: This variable can be set to on/off and any of the supported
194
205
file formats in the configuration file, but can only be set to any
195
206
of the supported file formats during runtime. */
196
 
static char*  innobase_file_format_check    = NULL;
 
207
static char*    innobase_file_format_check              = NULL;
197
208
 
198
 
static char*  innobase_file_flush_method   = NULL;
 
209
/* The following has a misleading name: starting from 4.0.5, this also
 
210
affects Windows: */
 
211
static char*    innobase_unix_file_flush_method         = NULL;
199
212
 
200
213
/* Below we have boolean-valued start-up parameters, and their default
201
214
values */
202
215
 
203
 
static ulong  innobase_fast_shutdown      = 1;
 
216
static ulong    innobase_fast_shutdown                  = 1;
204
217
#ifdef UNIV_LOG_ARCHIVE
205
 
static my_bool  innobase_log_archive      = FALSE;
206
 
static char*  innobase_log_arch_dir     = NULL;
 
218
static my_bool  innobase_log_archive                    = FALSE;
 
219
static char*    innobase_log_arch_dir                   = NULL;
207
220
#endif /* UNIV_LOG_ARCHIVE */
208
 
static my_bool  innobase_use_doublewrite    = TRUE;
209
 
static my_bool  innobase_use_checksums      = TRUE;
210
 
static my_bool  innobase_rollback_on_timeout    = FALSE;
211
 
static my_bool  innobase_create_status_file   = FALSE;
212
 
 
213
 
static char*  internal_innobase_data_file_path  = NULL;
214
 
 
215
 
static char*  innodb_version_str = (char*) INNODB_VERSION_STR;
 
221
static my_bool  innobase_use_doublewrite                = TRUE;
 
222
static my_bool  innobase_use_checksums                  = TRUE;
 
223
static my_bool  innobase_locks_unsafe_for_binlog        = TRUE;
 
224
static my_bool  innobase_rollback_on_timeout            = FALSE;
 
225
static my_bool  innobase_create_status_file             = FALSE;
 
226
static my_bool  innobase_stats_on_metadata              = TRUE;
 
227
 
 
228
static char*    internal_innobase_data_file_path        = NULL;
 
229
 
 
230
static char*    innodb_version_str = (char*) INNODB_VERSION_STR;
216
231
 
217
232
/* The following counter is used to convey information to InnoDB
218
233
about server activity: in selects it is not sensible to call
219
234
srv_active_wake_master_thread after each fetch or search, we only do
220
235
it every INNOBASE_WAKE_INTERVAL'th step. */
221
236
 
222
 
#define INNOBASE_WAKE_INTERVAL  32
223
 
static ulong  innobase_active_counter = 0;
224
 
 
225
 
static hash_table_t*  innobase_open_tables;
226
 
 
227
 
#ifdef __NETWARE__  /* some special cleanup for NetWare */
 
237
#define INNOBASE_WAKE_INTERVAL  32
 
238
static ulong    innobase_active_counter = 0;
 
239
 
 
240
static hash_table_t*    innobase_open_tables;
 
241
 
 
242
#ifdef __NETWARE__      /* some special cleanup for NetWare */
228
243
bool nw_panic = FALSE;
229
244
#endif
230
245
 
231
246
/** Allowed values of innodb_change_buffering */
232
247
static const char* innobase_change_buffering_values[IBUF_USE_COUNT] = {
233
 
  "none",   /* IBUF_USE_NONE */
234
 
  "inserts" /* IBUF_USE_INSERT */
 
248
        "none",         /* IBUF_USE_NONE */
 
249
        "inserts"       /* IBUF_USE_INSERT */
235
250
};
236
251
 
237
 
/* "GEN_CLUST_INDEX" is the name reserved for Innodb default
238
 
system primary index. */
239
 
static const char innobase_index_reserve_name[]= "GEN_CLUST_INDEX";
240
 
 
241
252
/********************************************************************
242
253
Gives the file extension of an InnoDB single-table tablespace. */
243
254
static const char* ha_innobase_exts[] = {
245
256
  NULL
246
257
};
247
258
 
248
 
#define DEFAULT_FILE_EXTENSION ".dfe" // Deep Fried Elephant
249
 
 
250
259
static INNOBASE_SHARE *get_share(const char *table_name);
251
260
static void free_share(INNOBASE_SHARE *share);
252
261
 
253
262
class InnobaseEngine : public plugin::XaStorageEngine
254
263
{
255
264
public:
256
 
  explicit InnobaseEngine(string name_arg) :
 
265
  InnobaseEngine(string name_arg) :
257
266
    plugin::XaStorageEngine(name_arg,
258
 
                            HTON_NULL_IN_KEY |
259
 
                            HTON_CAN_INDEX_BLOBS |
260
 
                            HTON_PRIMARY_KEY_IN_READ_INDEX |
261
 
                            HTON_PARTIAL_COLUMN_READ |
262
 
                            HTON_TABLE_SCAN_ON_INDEX |
263
 
                            HTON_HAS_FOREIGN_KEYS |
264
 
                            HTON_HAS_DOES_TRANSACTIONS)
 
267
                          HTON_NULL_IN_KEY |
 
268
                          HTON_CAN_INDEX_BLOBS |
 
269
                          HTON_PRIMARY_KEY_REQUIRED_FOR_POSITION |
 
270
                          HTON_PRIMARY_KEY_IN_READ_INDEX |
 
271
                          HTON_PARTIAL_COLUMN_READ |
 
272
                          HTON_TABLE_SCAN_ON_INDEX |
 
273
                          HTON_HAS_DOES_TRANSACTIONS)
265
274
  {
266
275
    table_definition_ext= plugin::DEFAULT_DEFINITION_FILE_EXT;
267
276
    addAlias("INNOBASE");
268
277
  }
269
 
 
270
 
  virtual ~InnobaseEngine()
271
 
  {
272
 
    int err= 0;
273
 
    if (innodb_inited) {
274
 
      srv_fast_shutdown = (ulint) innobase_fast_shutdown;
275
 
      innodb_inited = 0;
276
 
      hash_table_free(innobase_open_tables);
277
 
      innobase_open_tables = NULL;
278
 
      if (innobase_shutdown_for_mysql() != DB_SUCCESS) {
279
 
        err = 1;
280
 
      }
281
 
      srv_free_paths_and_sizes();
282
 
      if (internal_innobase_data_file_path)
283
 
        free(internal_innobase_data_file_path);
284
 
      pthread_mutex_destroy(&innobase_share_mutex);
285
 
      pthread_mutex_destroy(&prepare_commit_mutex);
286
 
      pthread_mutex_destroy(&commit_threads_m);
287
 
      pthread_mutex_destroy(&commit_cond_m);
288
 
      pthread_cond_destroy(&commit_cond);
289
 
    }
290
 
    
291
 
    /* These get strdup'd from vm variables */
292
 
    free(innobase_data_home_dir);
293
 
    free(innobase_log_group_home_dir);
294
 
 
295
 
  }
296
 
 
297
278
private:
298
279
  virtual int doStartTransaction(Session *session, start_transaction_option_t options);
299
280
  virtual void doStartStatement(Session *session);
303
284
  int
304
285
  close_connection(
305
286
/*======================*/
306
 
      /* out: 0 or error number */
307
 
  Session*  session); /* in: handle to the MySQL thread of the user
308
 
      whose resources should be free'd */
 
287
                        /* out: 0 or error number */
 
288
        Session*        session);       /* in: handle to the MySQL thread of the user
 
289
                        whose resources should be free'd */
309
290
 
310
291
  virtual int doSetSavepoint(Session* session,
311
292
                                 drizzled::NamedSavepoint &savepoint);
313
294
                                     drizzled::NamedSavepoint &savepoint);
314
295
  virtual int doReleaseSavepoint(Session* session,
315
296
                                     drizzled::NamedSavepoint &savepoint);
316
 
  virtual int doXaCommit(Session* session, bool all)
317
 
  {
318
 
    return doCommit(session, all); /* XA commit just does a SQL COMMIT */
319
 
  }
320
 
  virtual int doXaRollback(Session *session, bool all)
321
 
  {
322
 
    return doRollback(session, all); /* XA rollback just does a SQL ROLLBACK */
323
 
  }
324
 
  virtual uint64_t doGetCurrentTransactionId(Session *session);
325
 
  virtual uint64_t doGetNewTransactionId(Session *session);
326
297
  virtual int doCommit(Session* session, bool all);
327
298
  virtual int doRollback(Session* session, bool all);
328
299
 
330
301
  This function is used to prepare X/Open XA distributed transaction   */
331
302
  virtual
332
303
  int
333
 
  doXaPrepare(
 
304
  doPrepare(
334
305
  /*================*/
335
 
        /* out: 0 or error number */
336
 
    Session*  session,  /* in: handle to the MySQL thread of the user
337
 
        whose XA transaction should be prepared */
338
 
    bool  all); /* in: TRUE - commit transaction
339
 
        FALSE - the current SQL statement ended */
 
306
                        /* out: 0 or error number */
 
307
        Session*        session,        /* in: handle to the MySQL thread of the user
 
308
                        whose XA transaction should be prepared */
 
309
        bool    all);   /* in: TRUE - commit transaction
 
310
                        FALSE - the current SQL statement ended */
340
311
  /***********************************************************************
341
312
  This function is used to recover X/Open XA distributed transactions   */
342
313
  virtual
343
314
  int
344
 
  doXaRecover(
 
315
  doRecover(
345
316
  /*================*/
346
 
          /* out: number of prepared transactions
347
 
          stored in xid_list */
348
 
    ::drizzled::XID*  xid_list, /* in/out: prepared transactions */
349
 
    size_t len);    /* in: number of slots in xid_list */
 
317
                                /* out: number of prepared transactions
 
318
                                stored in xid_list */
 
319
        ::drizzled::XID*        xid_list,       /* in/out: prepared transactions */
 
320
        size_t len);            /* in: number of slots in xid_list */
350
321
  /***********************************************************************
351
322
  This function is used to commit one X/Open XA distributed transaction
352
323
  which is in the prepared state */
353
324
  virtual
354
325
  int
355
 
  doXaCommitXid(
 
326
  doCommitXid(
356
327
  /*===================*/
357
 
        /* out: 0 or error number */
358
 
    ::drizzled::XID*  xid); /* in: X/Open XA transaction identification */
 
328
                        /* out: 0 or error number */
 
329
        ::drizzled::XID*        xid);   /* in: X/Open XA transaction identification */
359
330
  /***********************************************************************
360
331
  This function is used to rollback one X/Open XA distributed transaction
361
332
  which is in the prepared state */
362
333
  virtual
363
334
  int
364
 
  doXaRollbackXid(
 
335
  doRollbackXid(
365
336
  /*=====================*/
366
 
        /* out: 0 or error number */
367
 
    ::drizzled::XID *xid);  /* in: X/Open XA transaction identification */
 
337
                        /* out: 0 or error number */
 
338
        ::drizzled::XID *xid);  /* in: X/Open XA transaction identification */
368
339
 
369
 
  virtual Cursor *create(Table &table)
 
340
  virtual Cursor *create(TableShare &table,
 
341
                         memory::Root *mem_root)
370
342
  {
371
 
    return new ha_innobase(*this, table);
 
343
    return new (mem_root) ha_innobase(*this, table);
372
344
  }
373
345
 
374
346
  /*********************************************************************
376
348
  bool
377
349
  doDropSchema(
378
350
  /*===================*/
379
 
        /* out: error number */
380
 
    const SchemaIdentifier  &identifier); /* in: database path; inside InnoDB the name
381
 
        of the last directory in the path is used as
382
 
        the database name: for example, in 'mysql/data/test'
383
 
        the database name is 'test' */
 
351
                        /* out: error number */
 
352
        const std::string       &schema_name);  /* in: database path; inside InnoDB the name
 
353
                        of the last directory in the path is used as
 
354
                        the database name: for example, in 'mysql/data/test'
 
355
                        the database name is 'test' */
384
356
 
385
357
  /********************************************************************
386
358
  Flushes InnoDB logs to disk and makes a checkpoint. Really, a commit flushes
389
361
  bool
390
362
  flush_logs();
391
363
  /*================*/
392
 
          /* out: TRUE if error */
 
364
                                /* out: TRUE if error */
393
365
  
394
366
  /****************************************************************************
395
367
  Implements the SHOW INNODB STATUS command. Sends the output of the InnoDB
398
370
  bool
399
371
  show_status(
400
372
  /*===============*/
401
 
    Session*  session,  /* in: the MySQL query thread of the caller */
402
 
    stat_print_fn *stat_print,
403
 
  enum ha_stat_type stat_type);
 
373
        Session*        session,        /* in: the MySQL query thread of the caller */
 
374
        stat_print_fn *stat_print,
 
375
        enum ha_stat_type stat_type);
404
376
 
405
377
  virtual
406
378
  int
407
379
  doReleaseTemporaryLatches(
408
380
  /*===============================*/
409
 
        /* out: 0 */
410
 
  Session*    session); /* in: MySQL thread */
 
381
                                /* out: 0 */
 
382
        Session*                session);       /* in: MySQL thread */
411
383
 
412
384
 
413
385
  const char** bas_ext() const {
414
 
  return(ha_innobase_exts);
 
386
        return(ha_innobase_exts);
415
387
  }
416
388
 
417
 
  UNIV_INTERN int doCreateTable(Session &session,
418
 
                                Table &form,
419
 
                                const TableIdentifier &identifier,
 
389
  UNIV_INTERN int doCreateTable(Session *session,
 
390
                                const char *table_name,
 
391
                                Table& form,
420
392
                                message::Table&);
421
 
  UNIV_INTERN int doRenameTable(Session&, const TableIdentifier &from, const TableIdentifier &to);
422
 
  UNIV_INTERN int doDropTable(Session &session, const TableIdentifier &identifier);
 
393
  UNIV_INTERN int doRenameTable(Session* session,
 
394
                                const char* from,
 
395
                                const char* to);
 
396
  UNIV_INTERN int doDropTable(Session& session, const string &table_path);
423
397
 
424
398
  UNIV_INTERN virtual bool get_error_message(int error, String *buf);
425
399
 
436
410
            HA_READ_RANGE |
437
411
            HA_KEYREAD_ONLY);
438
412
  }
439
 
 
440
 
  int doGetTableDefinition(drizzled::Session& session,
441
 
                           const TableIdentifier &identifier,
442
 
                           drizzled::message::Table &table_proto);
443
 
 
444
 
  bool doDoesTableExist(drizzled::Session& session, const TableIdentifier &identifier);
445
 
 
446
 
  void doGetTableIdentifiers(drizzled::CachedDirectory &directory,
447
 
                             const drizzled::SchemaIdentifier &schema_identifier,
448
 
                             drizzled::TableIdentifiers &set_of_identifiers);
449
 
  bool validateCreateTableOption(const std::string &key, const std::string &state);
450
 
  void dropTemporarySchema();
451
 
 
452
413
};
453
414
 
454
 
 
455
 
bool InnobaseEngine::validateCreateTableOption(const std::string &key, const std::string &state)
456
 
{
457
 
  if (boost::iequals(key, "ROW_FORMAT"))
458
 
  {
459
 
    if (boost::iequals(state, "COMPRESSED"))
460
 
      return true;
461
 
 
462
 
    if (boost::iequals(state, "COMPACT"))
463
 
      return true;
464
 
 
465
 
    if (boost::iequals(state, "DYNAMIC"))
466
 
      return true;
467
 
 
468
 
    if (boost::iequals(state, "REDUNDANT"))
469
 
      return true;
470
 
  }
471
 
 
472
 
  return false;
473
 
}
474
 
 
475
 
void InnobaseEngine::doGetTableIdentifiers(drizzled::CachedDirectory &directory,
476
 
                                           const drizzled::SchemaIdentifier &schema_identifier,
477
 
                                           drizzled::TableIdentifiers &set_of_identifiers)
478
 
{
479
 
  CachedDirectory::Entries entries= directory.getEntries();
480
 
 
481
 
  for (CachedDirectory::Entries::iterator entry_iter= entries.begin(); 
482
 
       entry_iter != entries.end(); ++entry_iter)
483
 
  {
484
 
    CachedDirectory::Entry *entry= *entry_iter;
485
 
    const string *filename= &entry->filename;
486
 
 
487
 
    assert(filename->size());
488
 
 
489
 
    const char *ext= strchr(filename->c_str(), '.');
490
 
 
491
 
    if (ext == NULL || my_strcasecmp(system_charset_info, ext, DEFAULT_FILE_EXTENSION) ||
492
 
        (filename->compare(0, strlen(TMP_FILE_PREFIX), TMP_FILE_PREFIX) == 0))
493
 
    { }
494
 
    else
495
 
    {
496
 
      std::string path;
497
 
      path+= directory.getPath();
498
 
      path+= FN_LIBCHAR;
499
 
      path+= entry->filename;
500
 
 
501
 
      message::Table definition;
502
 
      if (StorageEngine::readTableFile(path, definition))
503
 
      {
504
 
        /* 
505
 
           Using schema_identifier here to stop unused warning, could use
506
 
           definition.schema() instead
507
 
        */
508
 
        TableIdentifier identifier(schema_identifier.getSchemaName(), definition.name());
509
 
        set_of_identifiers.push_back(identifier);
510
 
      }
511
 
    }
512
 
  }
513
 
}
514
 
 
515
 
bool InnobaseEngine::doDoesTableExist(Session &session, const TableIdentifier &identifier)
516
 
{
517
 
  string proto_path(identifier.getPath());
518
 
  proto_path.append(DEFAULT_FILE_EXTENSION);
519
 
 
520
 
  if (session.getMessageCache().doesTableMessageExist(identifier))
521
 
    return true;
522
 
 
523
 
  if (access(proto_path.c_str(), F_OK))
524
 
  {
525
 
    return false;
526
 
  }
527
 
 
528
 
  return true;
529
 
}
530
 
 
531
 
int InnobaseEngine::doGetTableDefinition(Session &session,
532
 
                                         const TableIdentifier &identifier,
533
 
                                         message::Table &table_proto)
534
 
{
535
 
  string proto_path(identifier.getPath());
536
 
  proto_path.append(DEFAULT_FILE_EXTENSION);
537
 
 
538
 
  // First we check the temporary tables.
539
 
  if (session.getMessageCache().getTableMessage(identifier, table_proto))
540
 
    return EEXIST;
541
 
 
542
 
  if (access(proto_path.c_str(), F_OK))
543
 
  {
544
 
    return errno;
545
 
  }
546
 
 
547
 
  if (StorageEngine::readTableFile(proto_path, table_proto))
548
 
    return EEXIST;
549
 
 
550
 
  return ENOENT;
551
 
}
552
 
 
553
415
/** @brief Initialize the default value of innodb_commit_concurrency.
554
416
 
555
417
Once InnoDB is running, the innodb_commit_concurrency must not change
566
428
 
567
429
/************************************************************//**
568
430
Validate the file format name and return its corresponding id.
569
 
@return valid file format id */
 
431
@return valid file format id */
570
432
static
571
433
uint
572
434
innobase_file_format_name_lookup(
573
435
/*=============================*/
574
 
  const char* format_name);   /*!< in: pointer to file format
575
 
            name */
 
436
        const char*     format_name);           /*!< in: pointer to file format
 
437
                                                name */
576
438
/************************************************************//**
577
439
Validate the file format check config parameters, as a side effect it
578
440
sets the srv_check_file_format_at_startup variable.
579
 
@return true if one of  "on" or "off" */
 
441
@return true if one of  "on" or "off" */
580
442
static
581
443
bool
582
444
innobase_file_format_check_on_off(
583
445
/*==============================*/
584
 
  const char* format_check);    /*!< in: parameter value */
 
446
        const char*     format_check);          /*!< in: parameter value */
585
447
/************************************************************//**
586
448
Validate the file format check config parameters, as a side effect it
587
449
sets the srv_check_file_format_at_startup variable.
588
 
@return the format_id if valid config value, otherwise, return -1 */
 
450
@return true if valid config value */
589
451
static
590
 
int
591
 
innobase_file_format_validate_and_set(
 
452
bool
 
453
innobase_file_format_check_validate(
592
454
/*================================*/
593
 
  const char* format_check);    /*!< in: parameter value */
 
455
        const char*     format_check);          /*!< in: parameter value */
594
456
 
595
457
static const char innobase_engine_name[]= "InnoDB";
596
458
 
597
459
/*************************************************************//**
598
460
Check for a valid value of innobase_commit_concurrency.
599
 
@return 0 for valid innodb_commit_concurrency */
 
461
@return 0 for valid innodb_commit_concurrency */
600
462
static
601
463
int
602
464
innobase_commit_concurrency_validate(
603
465
/*=================================*/
604
 
  Session*      , /*!< in: thread handle */
605
 
  drizzle_sys_var*  , /*!< in: pointer to system
606
 
            variable */
607
 
  void*       save, /*!< out: immediate result
608
 
            for update function */
609
 
  drizzle_value*    value)  /*!< in: incoming string */
 
466
        Session*                        ,       /*!< in: thread handle */
 
467
        drizzle_sys_var*        ,       /*!< in: pointer to system
 
468
                                                variable */
 
469
        void*                           save,   /*!< out: immediate result
 
470
                                                for update function */
 
471
        drizzle_value*          value)  /*!< in: incoming string */
610
472
{
611
 
  int64_t   intbuf;
612
 
  ulong   commit_concurrency;
613
 
 
614
 
  if (value->val_int(value, &intbuf)) {
615
 
    /* The value is NULL. That is invalid. */
616
 
    return(1);
617
 
  }
618
 
 
619
 
  *reinterpret_cast<ulong*>(save) = commit_concurrency
620
 
    = static_cast<ulong>(intbuf);
621
 
 
622
 
  /* Allow the value to be updated, as long as it remains zero
623
 
  or nonzero. */
624
 
  return(!(!commit_concurrency == !innobase_commit_concurrency));
 
473
        int64_t         intbuf;
 
474
        ulong           commit_concurrency;
 
475
 
 
476
        if (value->val_int(value, &intbuf)) {
 
477
                /* The value is NULL. That is invalid. */
 
478
                return(1);
 
479
        }
 
480
 
 
481
        *reinterpret_cast<ulong*>(save) = commit_concurrency
 
482
                = static_cast<ulong>(intbuf);
 
483
 
 
484
        /* Allow the value to be updated, as long as it remains zero
 
485
        or nonzero. */
 
486
        return(!(!commit_concurrency == !innobase_commit_concurrency));
625
487
}
626
488
 
627
489
static DRIZZLE_SessionVAR_BOOL(support_xa, PLUGIN_VAR_OPCMDARG,
643
505
  NULL, NULL, 50, 1, 1024 * 1024 * 1024, 0);
644
506
 
645
507
 
 
508
/***********************************************************************
 
509
Closes an InnoDB database. */
 
510
static
 
511
int
 
512
innobase_deinit(plugin::Registry &registry);
 
513
 
646
514
/*****************************************************************//**
647
515
Commits a transaction in an InnoDB database. */
648
516
static
649
517
void
650
518
innobase_commit_low(
651
519
/*================*/
652
 
  trx_t*  trx); /*!< in: transaction handle */
 
520
        trx_t*  trx);   /*!< in: transaction handle */
653
521
 
654
522
static drizzle_show_var innodb_status_variables[]= {
655
523
  {"buffer_pool_pages_data",
656
 
  (char*) &export_vars.innodb_buffer_pool_pages_data,   SHOW_LONG},
 
524
  (char*) &export_vars.innodb_buffer_pool_pages_data,     SHOW_LONG},
657
525
  {"buffer_pool_pages_dirty",
658
 
  (char*) &export_vars.innodb_buffer_pool_pages_dirty,    SHOW_LONG},
 
526
  (char*) &export_vars.innodb_buffer_pool_pages_dirty,    SHOW_LONG},
659
527
  {"buffer_pool_pages_flushed",
660
528
  (char*) &export_vars.innodb_buffer_pool_pages_flushed,  SHOW_LONG},
661
529
  {"buffer_pool_pages_free",
662
 
  (char*) &export_vars.innodb_buffer_pool_pages_free,   SHOW_LONG},
 
530
  (char*) &export_vars.innodb_buffer_pool_pages_free,     SHOW_LONG},
663
531
#ifdef UNIV_DEBUG
664
532
  {"buffer_pool_pages_latched",
665
533
  (char*) &export_vars.innodb_buffer_pool_pages_latched,  SHOW_LONG},
666
534
#endif /* UNIV_DEBUG */
667
535
  {"buffer_pool_pages_misc",
668
 
  (char*) &export_vars.innodb_buffer_pool_pages_misc,   SHOW_LONG},
 
536
  (char*) &export_vars.innodb_buffer_pool_pages_misc,     SHOW_LONG},
669
537
  {"buffer_pool_pages_total",
670
 
  (char*) &export_vars.innodb_buffer_pool_pages_total,    SHOW_LONG},
671
 
  {"buffer_pool_read_ahead",
672
 
  (char*) &export_vars.innodb_buffer_pool_read_ahead, SHOW_LONG},
673
 
  {"buffer_pool_read_ahead_evicted",
674
 
  (char*) &export_vars.innodb_buffer_pool_read_ahead_evicted, SHOW_LONG},
 
538
  (char*) &export_vars.innodb_buffer_pool_pages_total,    SHOW_LONG},
 
539
  {"buffer_pool_read_ahead_rnd",
 
540
  (char*) &export_vars.innodb_buffer_pool_read_ahead_rnd, SHOW_LONG},
 
541
  {"buffer_pool_read_ahead_seq",
 
542
  (char*) &export_vars.innodb_buffer_pool_read_ahead_seq, SHOW_LONG},
675
543
  {"buffer_pool_read_requests",
676
544
  (char*) &export_vars.innodb_buffer_pool_read_requests,  SHOW_LONG},
677
545
  {"buffer_pool_reads",
678
 
  (char*) &export_vars.innodb_buffer_pool_reads,    SHOW_LONG},
 
546
  (char*) &export_vars.innodb_buffer_pool_reads,          SHOW_LONG},
679
547
  {"buffer_pool_wait_free",
680
 
  (char*) &export_vars.innodb_buffer_pool_wait_free,    SHOW_LONG},
 
548
  (char*) &export_vars.innodb_buffer_pool_wait_free,      SHOW_LONG},
681
549
  {"buffer_pool_write_requests",
682
550
  (char*) &export_vars.innodb_buffer_pool_write_requests, SHOW_LONG},
683
551
  {"data_fsyncs",
684
 
  (char*) &export_vars.innodb_data_fsyncs,      SHOW_LONG},
 
552
  (char*) &export_vars.innodb_data_fsyncs,                SHOW_LONG},
685
553
  {"data_pending_fsyncs",
686
 
  (char*) &export_vars.innodb_data_pending_fsyncs,    SHOW_LONG},
 
554
  (char*) &export_vars.innodb_data_pending_fsyncs,        SHOW_LONG},
687
555
  {"data_pending_reads",
688
 
  (char*) &export_vars.innodb_data_pending_reads,   SHOW_LONG},
 
556
  (char*) &export_vars.innodb_data_pending_reads,         SHOW_LONG},
689
557
  {"data_pending_writes",
690
 
  (char*) &export_vars.innodb_data_pending_writes,    SHOW_LONG},
 
558
  (char*) &export_vars.innodb_data_pending_writes,        SHOW_LONG},
691
559
  {"data_read",
692
 
  (char*) &export_vars.innodb_data_read,      SHOW_LONG},
 
560
  (char*) &export_vars.innodb_data_read,                  SHOW_LONG},
693
561
  {"data_reads",
694
 
  (char*) &export_vars.innodb_data_reads,     SHOW_LONG},
 
562
  (char*) &export_vars.innodb_data_reads,                 SHOW_LONG},
695
563
  {"data_writes",
696
 
  (char*) &export_vars.innodb_data_writes,      SHOW_LONG},
 
564
  (char*) &export_vars.innodb_data_writes,                SHOW_LONG},
697
565
  {"data_written",
698
 
  (char*) &export_vars.innodb_data_written,     SHOW_LONG},
 
566
  (char*) &export_vars.innodb_data_written,               SHOW_LONG},
699
567
  {"dblwr_pages_written",
700
 
  (char*) &export_vars.innodb_dblwr_pages_written,    SHOW_LONG},
 
568
  (char*) &export_vars.innodb_dblwr_pages_written,        SHOW_LONG},
701
569
  {"dblwr_writes",
702
 
  (char*) &export_vars.innodb_dblwr_writes,     SHOW_LONG},
 
570
  (char*) &export_vars.innodb_dblwr_writes,               SHOW_LONG},
703
571
  {"have_atomic_builtins",
704
 
  (char*) &export_vars.innodb_have_atomic_builtins,   SHOW_BOOL},
 
572
  (char*) &export_vars.innodb_have_atomic_builtins,       SHOW_BOOL},
705
573
  {"log_waits",
706
 
  (char*) &export_vars.innodb_log_waits,      SHOW_LONG},
 
574
  (char*) &export_vars.innodb_log_waits,                  SHOW_LONG},
707
575
  {"log_write_requests",
708
 
  (char*) &export_vars.innodb_log_write_requests,   SHOW_LONG},
 
576
  (char*) &export_vars.innodb_log_write_requests,         SHOW_LONG},
709
577
  {"log_writes",
710
 
  (char*) &export_vars.innodb_log_writes,     SHOW_LONG},
 
578
  (char*) &export_vars.innodb_log_writes,                 SHOW_LONG},
711
579
  {"os_log_fsyncs",
712
 
  (char*) &export_vars.innodb_os_log_fsyncs,      SHOW_LONG},
 
580
  (char*) &export_vars.innodb_os_log_fsyncs,              SHOW_LONG},
713
581
  {"os_log_pending_fsyncs",
714
 
  (char*) &export_vars.innodb_os_log_pending_fsyncs,    SHOW_LONG},
 
582
  (char*) &export_vars.innodb_os_log_pending_fsyncs,      SHOW_LONG},
715
583
  {"os_log_pending_writes",
716
 
  (char*) &export_vars.innodb_os_log_pending_writes,    SHOW_LONG},
 
584
  (char*) &export_vars.innodb_os_log_pending_writes,      SHOW_LONG},
717
585
  {"os_log_written",
718
 
  (char*) &export_vars.innodb_os_log_written,     SHOW_LONG},
 
586
  (char*) &export_vars.innodb_os_log_written,             SHOW_LONG},
719
587
  {"page_size",
720
 
  (char*) &export_vars.innodb_page_size,      SHOW_LONG},
 
588
  (char*) &export_vars.innodb_page_size,                  SHOW_LONG},
721
589
  {"pages_created",
722
 
  (char*) &export_vars.innodb_pages_created,      SHOW_LONG},
 
590
  (char*) &export_vars.innodb_pages_created,              SHOW_LONG},
723
591
  {"pages_read",
724
 
  (char*) &export_vars.innodb_pages_read,     SHOW_LONG},
 
592
  (char*) &export_vars.innodb_pages_read,                 SHOW_LONG},
725
593
  {"pages_written",
726
 
  (char*) &export_vars.innodb_pages_written,      SHOW_LONG},
 
594
  (char*) &export_vars.innodb_pages_written,              SHOW_LONG},
727
595
  {"row_lock_current_waits",
728
 
  (char*) &export_vars.innodb_row_lock_current_waits,   SHOW_LONG},
 
596
  (char*) &export_vars.innodb_row_lock_current_waits,     SHOW_LONG},
729
597
  {"row_lock_time",
730
 
  (char*) &export_vars.innodb_row_lock_time,      SHOW_LONGLONG},
 
598
  (char*) &export_vars.innodb_row_lock_time,              SHOW_LONGLONG},
731
599
  {"row_lock_time_avg",
732
 
  (char*) &export_vars.innodb_row_lock_time_avg,    SHOW_LONG},
 
600
  (char*) &export_vars.innodb_row_lock_time_avg,          SHOW_LONG},
733
601
  {"row_lock_time_max",
734
 
  (char*) &export_vars.innodb_row_lock_time_max,    SHOW_LONG},
 
602
  (char*) &export_vars.innodb_row_lock_time_max,          SHOW_LONG},
735
603
  {"row_lock_waits",
736
 
  (char*) &export_vars.innodb_row_lock_waits,     SHOW_LONG},
 
604
  (char*) &export_vars.innodb_row_lock_waits,             SHOW_LONG},
737
605
  {"rows_deleted",
738
 
  (char*) &export_vars.innodb_rows_deleted,     SHOW_LONG},
 
606
  (char*) &export_vars.innodb_rows_deleted,               SHOW_LONG},
739
607
  {"rows_inserted",
740
 
  (char*) &export_vars.innodb_rows_inserted,      SHOW_LONG},
 
608
  (char*) &export_vars.innodb_rows_inserted,              SHOW_LONG},
741
609
  {"rows_read",
742
 
  (char*) &export_vars.innodb_rows_read,      SHOW_LONG},
 
610
  (char*) &export_vars.innodb_rows_read,                  SHOW_LONG},
743
611
  {"rows_updated",
744
 
  (char*) &export_vars.innodb_rows_updated,     SHOW_LONG},
 
612
  (char*) &export_vars.innodb_rows_updated,               SHOW_LONG},
745
613
  {NULL, NULL, SHOW_LONG}
746
614
};
747
615
 
804
672
 
805
673
DRIZZLE: Note, we didn't change this name to avoid more ifdef forking 
806
674
         in non-Cursor code.
807
 
@return true if session is the replication thread */
 
675
@return true if session is the replication thread */
808
676
extern "C" UNIV_INTERN
809
677
ibool
810
678
thd_is_replication_slave_thread(
811
679
/*============================*/
812
 
  void* ) /*!< in: thread handle (Session*) */
 
680
        void*   )       /*!< in: thread handle (Session*) */
813
681
{
814
 
  return false;
 
682
        return false;
815
683
}
816
684
 
817
685
/******************************************************************//**
821
689
void
822
690
innodb_srv_conc_enter_innodb(
823
691
/*=========================*/
824
 
  trx_t*  trx)  /*!< in: transaction handle */
 
692
        trx_t*  trx)    /*!< in: transaction handle */
825
693
{
826
 
  if (UNIV_LIKELY(!srv_thread_concurrency)) {
827
 
 
828
 
    return;
829
 
  }
830
 
 
831
 
  srv_conc_enter_innodb(trx);
 
694
        if (UNIV_LIKELY(!srv_thread_concurrency)) {
 
695
 
 
696
                return;
 
697
        }
 
698
 
 
699
        srv_conc_enter_innodb(trx);
832
700
}
833
701
 
834
702
/******************************************************************//**
838
706
void
839
707
innodb_srv_conc_exit_innodb(
840
708
/*========================*/
841
 
  trx_t*  trx)  /*!< in: transaction handle */
 
709
        trx_t*  trx)    /*!< in: transaction handle */
842
710
{
843
 
  if (UNIV_LIKELY(!trx->declared_to_be_inside_innodb)) {
844
 
 
845
 
    return;
846
 
  }
847
 
 
848
 
  srv_conc_exit_innodb(trx);
 
711
        if (UNIV_LIKELY(!trx->declared_to_be_inside_innodb)) {
 
712
 
 
713
                return;
 
714
        }
 
715
 
 
716
        srv_conc_exit_innodb(trx);
849
717
}
850
718
 
851
719
/******************************************************************//**
857
725
void
858
726
innobase_release_stat_resources(
859
727
/*============================*/
860
 
  trx_t*  trx)  /*!< in: transaction object */
 
728
        trx_t*  trx)    /*!< in: transaction object */
861
729
{
862
 
  if (trx->has_search_latch) {
863
 
    trx_search_latch_release_if_reserved(trx);
864
 
  }
865
 
 
866
 
  if (trx->declared_to_be_inside_innodb) {
867
 
    /* Release our possible ticket in the FIFO */
868
 
 
869
 
    srv_conc_force_exit_innodb(trx);
870
 
  }
 
730
        if (trx->has_search_latch) {
 
731
                trx_search_latch_release_if_reserved(trx);
 
732
        }
 
733
 
 
734
        if (trx->declared_to_be_inside_innodb) {
 
735
                /* Release our possible ticket in the FIFO */
 
736
 
 
737
                srv_conc_force_exit_innodb(trx);
 
738
        }
871
739
}
872
740
 
873
741
/******************************************************************//**
878
746
 
879
747
DRIZZLE: Note, we didn't change this name to avoid more ifdef forking 
880
748
         in non-Cursor code.
881
 
@return true if non-transactional tables have been edited */
 
749
@return true if non-transactional tables have been edited */
882
750
extern "C" UNIV_INTERN
883
751
ibool
884
752
thd_has_edited_nontrans_tables(
885
753
/*===========================*/
886
 
  void*   session)  /*!< in: thread handle (Session*) */
 
754
        void*           session)        /*!< in: thread handle (Session*) */
887
755
{
888
 
  return((ibool)((Session *)session)->transaction.all.hasModifiedNonTransData());
 
756
        return((ibool) session_non_transactional_update((Session*) session));
889
757
}
890
758
 
891
759
/******************************************************************//**
892
760
Returns true if the thread is executing a SELECT statement.
893
 
@return true if session is executing SELECT */
 
761
@return true if session is executing SELECT */
894
762
extern "C" UNIV_INTERN
895
763
ibool
896
764
thd_is_select(
897
765
/*==========*/
898
 
  const void* session)  /*!< in: thread handle (Session*) */
 
766
        const void*     session)        /*!< in: thread handle (Session*) */
899
767
{
900
 
  return(session_sql_command((const Session*) session) == SQLCOM_SELECT);
 
768
        return(session_sql_command((const Session*) session) == SQLCOM_SELECT);
901
769
}
902
770
 
903
771
/******************************************************************//**
904
772
Returns true if the thread supports XA,
905
773
global value of innodb_supports_xa if session is NULL.
906
 
@return true if session has XA support */
 
774
@return true if session has XA support */
907
775
extern "C" UNIV_INTERN
908
776
ibool
909
777
thd_supports_xa(
910
778
/*============*/
911
 
  void* session)  /*!< in: thread handle (Session*), or NULL to query
912
 
        the global innodb_supports_xa */
 
779
        void*   session)        /*!< in: thread handle (Session*), or NULL to query
 
780
                                the global innodb_supports_xa */
913
781
{
914
 
  return(SessionVAR((Session*) session, support_xa));
 
782
        return(SessionVAR((Session*) session, support_xa));
915
783
}
916
784
 
917
785
/******************************************************************//**
918
786
Returns the lock wait timeout for the current connection.
919
 
@return the lock wait timeout, in seconds */
 
787
@return the lock wait timeout, in seconds */
920
788
extern "C" UNIV_INTERN
921
789
ulong
922
790
thd_lock_wait_timeout(
923
791
/*==================*/
924
 
  void* session)  /*!< in: thread handle (Session*), or NULL to query
925
 
      the global innodb_lock_wait_timeout */
 
792
        void*   session)        /*!< in: thread handle (Session*), or NULL to query
 
793
                        the global innodb_lock_wait_timeout */
926
794
{
927
 
  /* According to <drizzle/plugin.h>, passing session == NULL
928
 
  returns the global value of the session variable. */
929
 
  return(SessionVAR((Session*) session, lock_wait_timeout));
 
795
        /* According to <drizzle/plugin.h>, passing session == NULL
 
796
        returns the global value of the session variable. */
 
797
        return(SessionVAR((Session*) session, lock_wait_timeout));
930
798
}
931
799
 
932
800
/********************************************************************//**
933
801
Obtain the InnoDB transaction of a MySQL thread.
934
 
@return reference to transaction pointer */
 
802
@return reference to transaction pointer */
935
803
static inline
936
804
trx_t*&
937
805
session_to_trx(
938
806
/*=======*/
939
 
  Session*  session)  /*!< in: Drizzle Session */
 
807
        Session*        session)        /*!< in: Drizzle Session */
940
808
{
941
 
  return *(trx_t**) session->getEngineData(innodb_engine_ptr);
 
809
        return *(trx_t**) session->getEngineData(innodb_engine_ptr);
942
810
}
943
811
 
944
812
/********************************************************************//**
945
813
Call this function when mysqld passes control to the client. That is to
946
814
avoid deadlocks on the adaptive hash S-latch possibly held by session. For more
947
815
documentation, see Cursor.cc.
948
 
@return 0 */
 
816
@return 0 */
949
817
int
950
818
InnobaseEngine::doReleaseTemporaryLatches(
951
819
/*===============================*/
952
 
  Session*    session)  /*!< in: MySQL thread */
 
820
        Session*                session)        /*!< in: MySQL thread */
953
821
{
954
 
  trx_t*  trx;
955
 
 
956
 
  assert(this == innodb_engine_ptr);
957
 
 
958
 
  if (!innodb_inited) {
959
 
 
960
 
    return(0);
961
 
  }
962
 
 
963
 
  trx = session_to_trx(session);
964
 
 
965
 
  if (trx) {
966
 
    innobase_release_stat_resources(trx);
967
 
  }
968
 
  return(0);
 
822
        trx_t*  trx;
 
823
 
 
824
        assert(this == innodb_engine_ptr);
 
825
 
 
826
        if (!innodb_inited) {
 
827
 
 
828
                return(0);
 
829
        }
 
830
 
 
831
        trx = session_to_trx(session);
 
832
 
 
833
        if (trx) {
 
834
                innobase_release_stat_resources(trx);
 
835
        }
 
836
        return(0);
969
837
}
970
838
 
971
839
/********************************************************************//**
978
846
innobase_active_small(void)
979
847
/*=======================*/
980
848
{
981
 
  innobase_active_counter++;
 
849
        innobase_active_counter++;
982
850
 
983
 
  if ((innobase_active_counter % INNOBASE_WAKE_INTERVAL) == 0) {
984
 
    srv_active_wake_master_thread();
985
 
  }
 
851
        if ((innobase_active_counter % INNOBASE_WAKE_INTERVAL) == 0) {
 
852
                srv_active_wake_master_thread();
 
853
        }
986
854
}
987
855
 
988
856
/********************************************************************//**
989
857
Converts an InnoDB error code to a MySQL error code and also tells to MySQL
990
858
about a possible transaction rollback inside InnoDB caused by a lock wait
991
859
timeout or a deadlock.
992
 
@return MySQL error code */
 
860
@return MySQL error code */
993
861
extern "C" UNIV_INTERN
994
862
int
995
863
convert_error_code_to_mysql(
996
864
/*========================*/
997
 
  int   error,  /*!< in: InnoDB error code */
998
 
  ulint   flags,  /*!< in: InnoDB table flags, or 0 */
999
 
  Session*  session)/*!< in: user thread handle or NULL */
1000
 
{
1001
 
  switch (error) {
1002
 
  case DB_SUCCESS:
1003
 
    return(0);
1004
 
 
1005
 
  case DB_INTERRUPTED:
1006
 
    my_error(ER_QUERY_INTERRUPTED, MYF(0));
1007
 
    /* fall through */
1008
 
  case DB_ERROR:
1009
 
  default:
1010
 
    return(-1); /* unspecified error */
1011
 
 
1012
 
  case DB_DUPLICATE_KEY:
1013
 
    /* Be cautious with returning this error, since
1014
 
       mysql could re-enter the storage layer to get
1015
 
       duplicated key info, the operation requires a
1016
 
       valid table handle and/or transaction information,
1017
 
       which might not always be available in the error
1018
 
       handling stage. */
1019
 
    return(HA_ERR_FOUND_DUPP_KEY);
1020
 
 
1021
 
  case DB_FOREIGN_DUPLICATE_KEY:
1022
 
    return(HA_ERR_FOREIGN_DUPLICATE_KEY);
1023
 
 
1024
 
  case DB_MISSING_HISTORY:
1025
 
    return(HA_ERR_TABLE_DEF_CHANGED);
1026
 
 
1027
 
  case DB_RECORD_NOT_FOUND:
1028
 
    return(HA_ERR_NO_ACTIVE_RECORD);
1029
 
 
1030
 
  case DB_DEADLOCK:
1031
 
    /* Since we rolled back the whole transaction, we must
1032
 
    tell it also to MySQL so that MySQL knows to empty the
1033
 
    cached binlog for this transaction */
1034
 
 
1035
 
    mark_transaction_to_rollback(session, TRUE);
1036
 
 
1037
 
    return(HA_ERR_LOCK_DEADLOCK);
1038
 
 
1039
 
  case DB_LOCK_WAIT_TIMEOUT:
1040
 
    /* Starting from 5.0.13, we let MySQL just roll back the
1041
 
    latest SQL statement in a lock wait timeout. Previously, we
1042
 
    rolled back the whole transaction. */
1043
 
 
1044
 
    mark_transaction_to_rollback(session, (bool)row_rollback_on_timeout);
1045
 
 
1046
 
    return(HA_ERR_LOCK_WAIT_TIMEOUT);
1047
 
 
1048
 
  case DB_NO_REFERENCED_ROW:
1049
 
    return(HA_ERR_NO_REFERENCED_ROW);
1050
 
 
1051
 
  case DB_ROW_IS_REFERENCED:
1052
 
    return(HA_ERR_ROW_IS_REFERENCED);
1053
 
 
1054
 
  case DB_CANNOT_ADD_CONSTRAINT:
1055
 
    return(HA_ERR_CANNOT_ADD_FOREIGN);
1056
 
 
1057
 
  case DB_CANNOT_DROP_CONSTRAINT:
1058
 
 
1059
 
    return(HA_ERR_ROW_IS_REFERENCED); /* TODO: This is a bit
1060
 
            misleading, a new MySQL error
1061
 
            code should be introduced */
1062
 
 
1063
 
  case DB_COL_APPEARS_TWICE_IN_INDEX:
1064
 
  case DB_CORRUPTION:
1065
 
    return(HA_ERR_CRASHED);
1066
 
 
1067
 
  case DB_OUT_OF_FILE_SPACE:
1068
 
    return(HA_ERR_RECORD_FILE_FULL);
1069
 
 
1070
 
  case DB_TABLE_IS_BEING_USED:
1071
 
    return(HA_ERR_WRONG_COMMAND);
1072
 
 
1073
 
  case DB_TABLE_NOT_FOUND:
1074
 
    return(HA_ERR_NO_SUCH_TABLE);
1075
 
 
1076
 
  case DB_TOO_BIG_RECORD:
1077
 
    my_error(ER_TOO_BIG_ROWSIZE, MYF(0),
1078
 
       page_get_free_space_of_empty(flags
1079
 
                  & DICT_TF_COMPACT) / 2);
1080
 
    return(HA_ERR_TO_BIG_ROW);
1081
 
 
1082
 
  case DB_NO_SAVEPOINT:
1083
 
    return(HA_ERR_NO_SAVEPOINT);
1084
 
 
1085
 
  case DB_LOCK_TABLE_FULL:
1086
 
    /* Since we rolled back the whole transaction, we must
1087
 
    tell it also to MySQL so that MySQL knows to empty the
1088
 
    cached binlog for this transaction */
1089
 
 
1090
 
    mark_transaction_to_rollback(session, TRUE);
1091
 
 
1092
 
    return(HA_ERR_LOCK_TABLE_FULL);
1093
 
 
1094
 
  case DB_PRIMARY_KEY_IS_NULL:
1095
 
    return(ER_PRIMARY_CANT_HAVE_NULL);
1096
 
 
1097
 
  case DB_TOO_MANY_CONCURRENT_TRXS:
1098
 
 
1099
 
    /* Once MySQL add the appropriate code to errmsg.txt then
1100
 
    we can get rid of this #ifdef. NOTE: The code checked by
1101
 
    the #ifdef is the suggested name for the error condition
1102
 
    and the actual error code name could very well be different.
1103
 
    This will require some monitoring, ie. the status
1104
 
    of this request on our part.*/
1105
 
 
1106
 
    /* New error code HA_ERR_TOO_MANY_CONCURRENT_TRXS is only
1107
 
       available in 5.1.38 and later, but the plugin should still
1108
 
       work with previous versions of MySQL.
1109
 
       In Drizzle we seem to not have this yet.
1110
 
    */
1111
 
#ifdef HA_ERR_TOO_MANY_CONCURRENT_TRXS
1112
 
    return(HA_ERR_TOO_MANY_CONCURRENT_TRXS);
1113
 
#else /* HA_ERR_TOO_MANY_CONCURRENT_TRXS */
1114
 
    return(HA_ERR_RECORD_FILE_FULL);
1115
 
#endif /* HA_ERR_TOO_MANY_CONCURRENT_TRXS */
1116
 
  case DB_UNSUPPORTED:
1117
 
    return(HA_ERR_UNSUPPORTED);
1118
 
  }
1119
 
}
1120
 
 
 
865
        int             error,  /*!< in: InnoDB error code */
 
866
        ulint           flags,  /*!< in: InnoDB table flags, or 0 */
 
867
        Session*        session)/*!< in: user thread handle or NULL */
 
868
{
 
869
        switch (error) {
 
870
        case DB_SUCCESS:
 
871
                return(0);
 
872
 
 
873
        case DB_ERROR:
 
874
        default:
 
875
                return(-1); /* unspecified error */
 
876
 
 
877
        case DB_DUPLICATE_KEY:
 
878
                return(HA_ERR_FOUND_DUPP_KEY);
 
879
 
 
880
        case DB_FOREIGN_DUPLICATE_KEY:
 
881
                return(HA_ERR_FOREIGN_DUPLICATE_KEY);
 
882
 
 
883
        case DB_MISSING_HISTORY:
 
884
                return(HA_ERR_TABLE_DEF_CHANGED);
 
885
 
 
886
        case DB_RECORD_NOT_FOUND:
 
887
                return(HA_ERR_NO_ACTIVE_RECORD);
 
888
 
 
889
        case DB_DEADLOCK:
 
890
                /* Since we rolled back the whole transaction, we must
 
891
                tell it also to MySQL so that MySQL knows to empty the
 
892
                cached binlog for this transaction */
 
893
 
 
894
                session_mark_transaction_to_rollback(session, TRUE);
 
895
 
 
896
                return(HA_ERR_LOCK_DEADLOCK);
 
897
 
 
898
        case DB_LOCK_WAIT_TIMEOUT:
 
899
                /* Starting from 5.0.13, we let MySQL just roll back the
 
900
                latest SQL statement in a lock wait timeout. Previously, we
 
901
                rolled back the whole transaction. */
 
902
 
 
903
                session_mark_transaction_to_rollback(session,
 
904
                                             (bool)row_rollback_on_timeout);
 
905
 
 
906
                return(HA_ERR_LOCK_WAIT_TIMEOUT);
 
907
 
 
908
        case DB_NO_REFERENCED_ROW:
 
909
                return(HA_ERR_NO_REFERENCED_ROW);
 
910
 
 
911
        case DB_ROW_IS_REFERENCED:
 
912
                return(HA_ERR_ROW_IS_REFERENCED);
 
913
 
 
914
        case DB_CANNOT_ADD_CONSTRAINT:
 
915
                return(HA_ERR_CANNOT_ADD_FOREIGN);
 
916
 
 
917
        case DB_CANNOT_DROP_CONSTRAINT:
 
918
 
 
919
                return(HA_ERR_ROW_IS_REFERENCED); /* TODO: This is a bit
 
920
                                                misleading, a new MySQL error
 
921
                                                code should be introduced */
 
922
 
 
923
        case DB_COL_APPEARS_TWICE_IN_INDEX:
 
924
        case DB_CORRUPTION:
 
925
                return(HA_ERR_CRASHED);
 
926
 
 
927
        case DB_OUT_OF_FILE_SPACE:
 
928
                return(HA_ERR_RECORD_FILE_FULL);
 
929
 
 
930
        case DB_TABLE_IS_BEING_USED:
 
931
                return(HA_ERR_WRONG_COMMAND);
 
932
 
 
933
        case DB_TABLE_NOT_FOUND:
 
934
                return(HA_ERR_NO_SUCH_TABLE);
 
935
 
 
936
        case DB_TOO_BIG_RECORD:
 
937
                my_error(ER_TOO_BIG_ROWSIZE, MYF(0),
 
938
                         page_get_free_space_of_empty(flags
 
939
                                                      & DICT_TF_COMPACT) / 2);
 
940
                return(HA_ERR_TO_BIG_ROW);
 
941
 
 
942
        case DB_NO_SAVEPOINT:
 
943
                return(HA_ERR_NO_SAVEPOINT);
 
944
 
 
945
        case DB_LOCK_TABLE_FULL:
 
946
                /* Since we rolled back the whole transaction, we must
 
947
                tell it also to MySQL so that MySQL knows to empty the
 
948
                cached binlog for this transaction */
 
949
 
 
950
                session_mark_transaction_to_rollback(session, TRUE);
 
951
 
 
952
                return(HA_ERR_LOCK_TABLE_FULL);
 
953
 
 
954
        case DB_PRIMARY_KEY_IS_NULL:
 
955
                return(ER_PRIMARY_CANT_HAVE_NULL);
 
956
 
 
957
        case DB_TOO_MANY_CONCURRENT_TRXS:
 
958
 
 
959
                /* Once MySQL add the appropriate code to errmsg.txt then
 
960
                we can get rid of this #ifdef. NOTE: The code checked by
 
961
                the #ifdef is the suggested name for the error condition
 
962
                and the actual error code name could very well be different.
 
963
                This will require some monitoring, ie. the status
 
964
                of this request on our part.*/
 
965
#ifdef ER_TOO_MANY_CONCURRENT_TRXS
 
966
                return(ER_TOO_MANY_CONCURRENT_TRXS);
 
967
#else
 
968
                return(HA_ERR_RECORD_FILE_FULL);
 
969
#endif
 
970
        case DB_UNSUPPORTED:
 
971
                return(HA_ERR_UNSUPPORTED);
 
972
        }
 
973
}
 
974
 
 
975
/*************************************************************//**
 
976
If you want to print a session that is not associated with the current thread,
 
977
you must call this function before reserving the InnoDB kernel_mutex, to
 
978
protect Drizzle from setting session->query NULL. If you print a session of the
 
979
current thread, we know that Drizzle cannot modify sesion->query, and it is
 
980
not necessary to call this. Call innobase_mysql_end_print_arbitrary_thd()
 
981
after you release the kernel_mutex.
 
982
 
 
983
DRIZZLE: Note, we didn't change this name to avoid more ifdef forking 
 
984
         in non-Cursor code.
 
985
 */
 
986
extern "C" UNIV_INTERN
 
987
void
 
988
innobase_mysql_prepare_print_arbitrary_thd(void)
 
989
/*============================================*/
 
990
{
 
991
        ut_ad(!mutex_own(&kernel_mutex));
 
992
        pthread_mutex_lock(&LOCK_thread_count);
 
993
}
 
994
 
 
995
/*************************************************************//**
 
996
Releases the mutex reserved by innobase_mysql_prepare_print_arbitrary_thd().
 
997
In the InnoDB latching order, the mutex sits right above the
 
998
kernel_mutex.  In debug builds, we assert that the kernel_mutex is
 
999
released before this function is invoked. 
 
1000
 
 
1001
DRIZZLE: Note, we didn't change this name to avoid more ifdef forking 
 
1002
         in non-Cursor code.
 
1003
*/
 
1004
extern "C" UNIV_INTERN
 
1005
void
 
1006
innobase_mysql_end_print_arbitrary_thd(void)
 
1007
/*========================================*/
 
1008
{
 
1009
        ut_ad(!mutex_own(&kernel_mutex));
 
1010
        pthread_mutex_unlock(&LOCK_thread_count);
 
1011
}
1121
1012
 
1122
1013
/*************************************************************//**
1123
1014
Prints info of a Session object (== user session thread) to the given file. */
1125
1016
void
1126
1017
innobase_mysql_print_thd(
1127
1018
/*=====================*/
1128
 
  FILE* f,    /*!< in: output stream */
1129
 
  void * in_session,  /*!< in: pointer to a Drizzle Session object */
1130
 
  uint  )   /*!< in: max query length to print, or 0 to
1131
 
           use the default max length */
 
1019
        FILE*   f,              /*!< in: output stream */
 
1020
        void * in_session,      /*!< in: pointer to a Drizzle Session object */
 
1021
        uint    )               /*!< in: max query length to print, or 0 to
 
1022
                                   use the default max length */
1132
1023
{
1133
1024
  Session *session= reinterpret_cast<Session *>(in_session);
1134
1025
  fprintf(f,
1135
1026
          "Drizzle thread %"PRIu64", query id %"PRIu64", %s, %s, %s ",
1136
 
          static_cast<uint64_t>(session->getSessionId()),
 
1027
          static_cast<uint64_t>(session_get_thread_id( session)),
1137
1028
          static_cast<uint64_t>(session->getQueryId()),
1138
1029
          glob_hostname,
1139
1030
          session->getSecurityContext().getIp().c_str(),
1140
1031
          session->getSecurityContext().getUser().c_str()
1141
1032
  );
1142
 
  fprintf(f, "\n%s", session->getQueryString()->c_str());
1143
 
  putc('\n', f);
 
1033
  fprintf(f,
 
1034
          "\n%s", session->getQueryString().c_str()
 
1035
  );
 
1036
        putc('\n', f);
1144
1037
}
1145
1038
 
1146
1039
/******************************************************************//**
1149
1042
void
1150
1043
innobase_get_cset_width(
1151
1044
/*====================*/
1152
 
  ulint cset,   /*!< in: MySQL charset-collation code */
1153
 
  ulint*  mbminlen, /*!< out: minimum length of a char (in bytes) */
1154
 
  ulint*  mbmaxlen) /*!< out: maximum length of a char (in bytes) */
 
1045
        ulint   cset,           /*!< in: MySQL charset-collation code */
 
1046
        ulint*  mbminlen,       /*!< out: minimum length of a char (in bytes) */
 
1047
        ulint*  mbmaxlen)       /*!< out: maximum length of a char (in bytes) */
1155
1048
{
1156
 
  CHARSET_INFO* cs;
1157
 
  ut_ad(cset < 256);
1158
 
  ut_ad(mbminlen);
1159
 
  ut_ad(mbmaxlen);
 
1049
        CHARSET_INFO*   cs;
 
1050
        ut_ad(cset < 256);
 
1051
        ut_ad(mbminlen);
 
1052
        ut_ad(mbmaxlen);
1160
1053
 
1161
 
  cs = all_charsets[cset];
1162
 
  if (cs) {
1163
 
    *mbminlen = cs->mbminlen;
1164
 
    *mbmaxlen = cs->mbmaxlen;
1165
 
  } else {
1166
 
    ut_a(cset == 0);
1167
 
    *mbminlen = *mbmaxlen = 0;
1168
 
  }
 
1054
        cs = all_charsets[cset];
 
1055
        if (cs) {
 
1056
                *mbminlen = cs->mbminlen;
 
1057
                *mbmaxlen = cs->mbmaxlen;
 
1058
        } else {
 
1059
                ut_a(cset == 0);
 
1060
                *mbminlen = *mbmaxlen = 0;
 
1061
        }
1169
1062
}
1170
1063
 
1171
1064
/******************************************************************//**
1174
1067
void
1175
1068
innobase_convert_from_table_id(
1176
1069
/*===========================*/
1177
 
  const void*,      /*!< in: the 'from' character set */
1178
 
  char*     to, /*!< out: converted identifier */
1179
 
  const char*   from, /*!< in: identifier to convert */
1180
 
  ulint     len)  /*!< in: length of 'to', in bytes */
 
1070
        const void*,                    /*!< in: the 'from' character set */
 
1071
        char*                   to,     /*!< out: converted identifier */
 
1072
        const char*             from,   /*!< in: identifier to convert */
 
1073
        ulint                   len)    /*!< in: length of 'to', in bytes */
1181
1074
{
1182
 
  strncpy(to, from, len);
 
1075
        strncpy(to, from, len);
1183
1076
}
1184
1077
 
1185
1078
/******************************************************************//**
1188
1081
void
1189
1082
innobase_convert_from_id(
1190
1083
/*=====================*/
1191
 
  const void*,      /*!< in: the 'from' character set */
1192
 
  char*     to, /*!< out: converted identifier */
1193
 
  const char*   from, /*!< in: identifier to convert */
1194
 
  ulint     len)  /*!< in: length of 'to', in bytes */
 
1084
        const void*,                    /*!< in: the 'from' character set */
 
1085
        char*                   to,     /*!< out: converted identifier */
 
1086
        const char*             from,   /*!< in: identifier to convert */
 
1087
        ulint                   len)    /*!< in: length of 'to', in bytes */
1195
1088
{
1196
 
  strncpy(to, from, len);
 
1089
        strncpy(to, from, len);
1197
1090
}
1198
1091
 
1199
1092
/******************************************************************//**
1200
1093
Compares NUL-terminated UTF-8 strings case insensitively.
1201
 
@return 0 if a=b, <0 if a<b, >1 if a>b */
 
1094
@return 0 if a=b, <0 if a<b, >1 if a>b */
1202
1095
extern "C" UNIV_INTERN
1203
1096
int
1204
1097
innobase_strcasecmp(
1205
1098
/*================*/
1206
 
  const char* a,  /*!< in: first string to compare */
1207
 
  const char* b)  /*!< in: second string to compare */
 
1099
        const char*     a,      /*!< in: first string to compare */
 
1100
        const char*     b)      /*!< in: second string to compare */
1208
1101
{
1209
 
  return(my_strcasecmp(system_charset_info, a, b));
 
1102
        return(my_strcasecmp(system_charset_info, a, b));
1210
1103
}
1211
1104
 
1212
1105
/******************************************************************//**
1215
1108
void
1216
1109
innobase_casedn_str(
1217
1110
/*================*/
1218
 
  char* a)  /*!< in/out: string to put in lower case */
 
1111
        char*   a)      /*!< in/out: string to put in lower case */
1219
1112
{
1220
 
  my_casedn_str(system_charset_info, a);
 
1113
        my_casedn_str(system_charset_info, a);
1221
1114
}
1222
1115
 
1223
1116
/**********************************************************************//**
1224
1117
Determines the connection character set.
1225
 
@return connection character set */
 
1118
@return connection character set */
1226
1119
extern "C" UNIV_INTERN
1227
1120
const void*
1228
1121
innobase_get_charset(
1229
1122
/*=================*/
1230
 
  void* mysql_session)  /*!< in: MySQL thread handle */
 
1123
        void*   mysql_session)  /*!< in: MySQL thread handle */
1231
1124
{
1232
 
  return static_cast<Session*>(mysql_session)->charset();
 
1125
        return session_charset(static_cast<Session*>(mysql_session));
1233
1126
}
1234
1127
 
1235
1128
extern "C" UNIV_INTERN
1236
1129
bool
1237
1130
innobase_isspace(
1238
 
  const void *cs,
1239
 
  char char_to_test)
 
1131
        const void *cs,
 
1132
        char char_to_test)
1240
1133
{
1241
 
  return my_isspace(static_cast<const CHARSET_INFO *>(cs), char_to_test);
 
1134
        return my_isspace(static_cast<const CHARSET_INFO *>(cs), char_to_test);
1242
1135
}
1243
1136
 
1244
1137
UNIV_INTERN
1246
1139
innobase_fast_mutex_init(
1247
1140
        os_fast_mutex_t*        fast_mutex)
1248
1141
{
1249
 
  return pthread_mutex_init(fast_mutex, MY_MUTEX_INIT_FAST);
1250
 
}
1251
 
 
1252
 
/**********************************************************************//**
1253
 
Determines the current SQL statement.
1254
 
@return SQL statement string */
1255
 
extern "C" UNIV_INTERN
1256
 
const char*
1257
 
innobase_get_stmt(
1258
 
/*==============*/
1259
 
        void*   session,        /*!< in: MySQL thread handle */
1260
 
        size_t* length)         /*!< out: length of the SQL statement */
1261
 
{
1262
 
  return static_cast<Session*>(session)->getQueryStringCopy(*length);
 
1142
        return pthread_mutex_init(fast_mutex, MY_MUTEX_INIT_FAST);
1263
1143
}
1264
1144
 
1265
1145
#if defined (__WIN__) && defined (MYSQL_DYNAMIC_PLUGIN)
1269
1149
extern "C"
1270
1150
void __cdecl
1271
1151
_dosmaperr(
1272
 
  unsigned long); /*!< in: OS error value */
 
1152
        unsigned long); /*!< in: OS error value */
1273
1153
 
1274
1154
/*********************************************************************//**
1275
1155
Creates a temporary file.
1276
 
@return temporary file descriptor, or < 0 on error */
 
1156
@return temporary file descriptor, or < 0 on error */
1277
1157
extern "C" UNIV_INTERN
1278
1158
int
1279
1159
innobase_mysql_tmpfile(void)
1280
1160
/*========================*/
1281
1161
{
1282
 
  int fd;       /* handle of opened file */
1283
 
  HANDLE  osfh;       /* OS handle of opened file */
1284
 
  char* tmpdir;       /* point to the directory
1285
 
            where to create file */
1286
 
  TCHAR path_buf[MAX_PATH - 14];  /* buffer for tmp file path.
1287
 
            The length cannot be longer
1288
 
            than MAX_PATH - 14, or
1289
 
            GetTempFileName will fail. */
1290
 
  char  filename[MAX_PATH];   /* name of the tmpfile */
1291
 
  DWORD fileaccess = GENERIC_READ /* OS file access */
1292
 
           | GENERIC_WRITE
1293
 
           | DELETE;
1294
 
  DWORD fileshare = FILE_SHARE_READ /* OS file sharing mode */
1295
 
          | FILE_SHARE_WRITE
1296
 
          | FILE_SHARE_DELETE;
1297
 
  DWORD filecreate = CREATE_ALWAYS; /* OS method of open/create */
1298
 
  DWORD fileattrib =      /* OS file attribute flags */
1299
 
           FILE_ATTRIBUTE_NORMAL
1300
 
           | FILE_FLAG_DELETE_ON_CLOSE
1301
 
           | FILE_ATTRIBUTE_TEMPORARY
1302
 
           | FILE_FLAG_SEQUENTIAL_SCAN;
1303
 
 
1304
 
  tmpdir = my_tmpdir(&mysql_tmpdir_list);
1305
 
 
1306
 
  /* The tmpdir parameter can not be NULL for GetTempFileName. */
1307
 
  if (!tmpdir) {
1308
 
    uint  ret;
1309
 
 
1310
 
    /* Use GetTempPath to determine path for temporary files. */
1311
 
    ret = GetTempPath(sizeof(path_buf), path_buf);
1312
 
    if (ret > sizeof(path_buf) || (ret == 0)) {
1313
 
 
1314
 
      _dosmaperr(GetLastError()); /* map error */
1315
 
      return(-1);
1316
 
    }
1317
 
 
1318
 
    tmpdir = path_buf;
1319
 
  }
1320
 
 
1321
 
  /* Use GetTempFileName to generate a unique filename. */
1322
 
  if (!GetTempFileName(tmpdir, "ib", 0, filename)) {
1323
 
 
1324
 
    _dosmaperr(GetLastError()); /* map error */
1325
 
    return(-1);
1326
 
  }
1327
 
 
1328
 
  /* Open/Create the file. */
1329
 
  osfh = CreateFile(filename, fileaccess, fileshare, NULL,
1330
 
        filecreate, fileattrib, NULL);
1331
 
  if (osfh == INVALID_HANDLE_VALUE) {
1332
 
 
1333
 
    /* open/create file failed! */
1334
 
    _dosmaperr(GetLastError()); /* map error */
1335
 
    return(-1);
1336
 
  }
1337
 
 
1338
 
  do {
1339
 
    /* Associates a CRT file descriptor with the OS file handle. */
1340
 
    fd = _open_osfhandle((intptr_t) osfh, 0);
1341
 
  } while (fd == -1 && errno == EINTR);
1342
 
 
1343
 
  if (fd == -1) {
1344
 
    /* Open failed, close the file handle. */
1345
 
 
1346
 
    _dosmaperr(GetLastError()); /* map error */
1347
 
    CloseHandle(osfh);    /* no need to check if
1348
 
            CloseHandle fails */
1349
 
  }
1350
 
 
1351
 
  return(fd);
 
1162
        int     fd;                             /* handle of opened file */
 
1163
        HANDLE  osfh;                           /* OS handle of opened file */
 
1164
        char*   tmpdir;                         /* point to the directory
 
1165
                                                where to create file */
 
1166
        TCHAR   path_buf[MAX_PATH - 14];        /* buffer for tmp file path.
 
1167
                                                The length cannot be longer
 
1168
                                                than MAX_PATH - 14, or
 
1169
                                                GetTempFileName will fail. */
 
1170
        char    filename[MAX_PATH];             /* name of the tmpfile */
 
1171
        DWORD   fileaccess = GENERIC_READ       /* OS file access */
 
1172
                             | GENERIC_WRITE
 
1173
                             | DELETE;
 
1174
        DWORD   fileshare = FILE_SHARE_READ     /* OS file sharing mode */
 
1175
                            | FILE_SHARE_WRITE
 
1176
                            | FILE_SHARE_DELETE;
 
1177
        DWORD   filecreate = CREATE_ALWAYS;     /* OS method of open/create */
 
1178
        DWORD   fileattrib =                    /* OS file attribute flags */
 
1179
                             FILE_ATTRIBUTE_NORMAL
 
1180
                             | FILE_FLAG_DELETE_ON_CLOSE
 
1181
                             | FILE_ATTRIBUTE_TEMPORARY
 
1182
                             | FILE_FLAG_SEQUENTIAL_SCAN;
 
1183
 
 
1184
        tmpdir = my_tmpdir(&mysql_tmpdir_list);
 
1185
 
 
1186
        /* The tmpdir parameter can not be NULL for GetTempFileName. */
 
1187
        if (!tmpdir) {
 
1188
                uint    ret;
 
1189
 
 
1190
                /* Use GetTempPath to determine path for temporary files. */
 
1191
                ret = GetTempPath(sizeof(path_buf), path_buf);
 
1192
                if (ret > sizeof(path_buf) || (ret == 0)) {
 
1193
 
 
1194
                        _dosmaperr(GetLastError());     /* map error */
 
1195
                        return(-1);
 
1196
                }
 
1197
 
 
1198
                tmpdir = path_buf;
 
1199
        }
 
1200
 
 
1201
        /* Use GetTempFileName to generate a unique filename. */
 
1202
        if (!GetTempFileName(tmpdir, "ib", 0, filename)) {
 
1203
 
 
1204
                _dosmaperr(GetLastError());     /* map error */
 
1205
                return(-1);
 
1206
        }
 
1207
 
 
1208
        /* Open/Create the file. */
 
1209
        osfh = CreateFile(filename, fileaccess, fileshare, NULL,
 
1210
                          filecreate, fileattrib, NULL);
 
1211
        if (osfh == INVALID_HANDLE_VALUE) {
 
1212
 
 
1213
                /* open/create file failed! */
 
1214
                _dosmaperr(GetLastError());     /* map error */
 
1215
                return(-1);
 
1216
        }
 
1217
 
 
1218
        do {
 
1219
                /* Associates a CRT file descriptor with the OS file handle. */
 
1220
                fd = _open_osfhandle((intptr_t) osfh, 0);
 
1221
        } while (fd == -1 && errno == EINTR);
 
1222
 
 
1223
        if (fd == -1) {
 
1224
                /* Open failed, close the file handle. */
 
1225
 
 
1226
                _dosmaperr(GetLastError());     /* map error */
 
1227
                CloseHandle(osfh);              /* no need to check if
 
1228
                                                CloseHandle fails */
 
1229
        }
 
1230
 
 
1231
        return(fd);
1352
1232
}
1353
1233
#else
1354
1234
/*********************************************************************//**
1355
1235
Creates a temporary file.
1356
 
@return temporary file descriptor, or < 0 on error */
 
1236
@return temporary file descriptor, or < 0 on error */
1357
1237
extern "C" UNIV_INTERN
1358
1238
int
1359
1239
innobase_mysql_tmpfile(void)
1360
1240
/*========================*/
1361
1241
{
1362
 
  int fd2 = -1;
1363
 
  int fd = mysql_tmpfile("ib");
1364
 
  if (fd >= 0) {
1365
 
    /* Copy the file descriptor, so that the additional resources
1366
 
    allocated by create_temp_file() can be freed by invoking
1367
 
    internal::my_close().
 
1242
        int     fd2 = -1;
 
1243
        int     fd = mysql_tmpfile("ib");
 
1244
        if (fd >= 0) {
 
1245
                /* Copy the file descriptor, so that the additional resources
 
1246
                allocated by create_temp_file() can be freed by invoking
 
1247
                internal::my_close().
1368
1248
 
1369
 
    Because the file descriptor returned by this function
1370
 
    will be passed to fdopen(), it will be closed by invoking
1371
 
    fclose(), which in turn will invoke close() instead of
1372
 
    internal::my_close(). */
1373
 
    fd2 = dup(fd);
1374
 
    if (fd2 < 0) {
1375
 
      errno=errno;
1376
 
      my_error(EE_OUT_OF_FILERESOURCES,
1377
 
         MYF(ME_BELL+ME_WAITTANG),
1378
 
         "ib*", errno);
1379
 
    }
1380
 
    internal::my_close(fd, MYF(MY_WME));
1381
 
  }
1382
 
  return(fd2);
 
1249
                Because the file descriptor returned by this function
 
1250
                will be passed to fdopen(), it will be closed by invoking
 
1251
                fclose(), which in turn will invoke close() instead of
 
1252
                internal::my_close(). */
 
1253
                fd2 = dup(fd);
 
1254
                if (fd2 < 0) {
 
1255
                        errno=errno;
 
1256
                        my_error(EE_OUT_OF_FILERESOURCES,
 
1257
                                 MYF(ME_BELL+ME_WAITTANG),
 
1258
                                 "ib*", errno);
 
1259
                }
 
1260
                internal::my_close(fd, MYF(MY_WME));
 
1261
        }
 
1262
        return(fd2);
1383
1263
}
1384
1264
#endif /* defined (__WIN__) && defined (MYSQL_DYNAMIC_PLUGIN) */
1385
1265
 
1392
1272
The result is always NUL-terminated (provided buf_size > 0) and the
1393
1273
number of bytes that were written to "buf" is returned (including the
1394
1274
terminating NUL).
1395
 
@return number of bytes that were written */
 
1275
@return number of bytes that were written */
1396
1276
extern "C" UNIV_INTERN
1397
1277
ulint
1398
1278
innobase_raw_format(
1399
1279
/*================*/
1400
 
  const char* data,   /*!< in: raw data */
1401
 
  ulint   data_len, /*!< in: raw data length
1402
 
          in bytes */
1403
 
  ulint   ,   /*!< in: charset collation */
1404
 
  char*   buf,    /*!< out: output buffer */
1405
 
  ulint   buf_size) /*!< in: output buffer size
1406
 
          in bytes */
 
1280
        const char*     data,           /*!< in: raw data */
 
1281
        ulint           data_len,       /*!< in: raw data length
 
1282
                                        in bytes */
 
1283
        ulint           ,               /*!< in: charset collation */
 
1284
        char*           buf,            /*!< out: output buffer */
 
1285
        ulint           buf_size)       /*!< in: output buffer size
 
1286
                                        in bytes */
1407
1287
{
1408
 
  return(ut_str_sql_format(data, data_len, buf, buf_size));
 
1288
        return(ut_str_sql_format(data, data_len, buf, buf_size));
1409
1289
}
1410
1290
 
1411
1291
/*********************************************************************//**
1420
1300
Note: This function is also called with increment set to the number of
1421
1301
values we want to reserve for multi-value inserts e.g.,
1422
1302
 
1423
 
  INSERT INTO T VALUES(), (), ();
 
1303
        INSERT INTO T VALUES(), (), ();
1424
1304
 
1425
1305
innobase_next_autoinc() will be called with increment set to
 
1306
n * 3 where autoinc_lock_mode != TRADITIONAL because we want
1426
1307
to reserve 3 values for the multi-value INSERT above.
1427
 
@return the next value */
 
1308
@return the next value */
1428
1309
static
1429
1310
uint64_t
1430
1311
innobase_next_autoinc(
1431
1312
/*==================*/
1432
 
  uint64_t  current,  /*!< in: Current value */
1433
 
  uint64_t  increment,  /*!< in: increment current by */
1434
 
  uint64_t  offset,   /*!< in: AUTOINC offset */
1435
 
  uint64_t  max_value)  /*!< in: max value for type */
 
1313
        uint64_t        current,        /*!< in: Current value */
 
1314
        uint64_t        increment,      /*!< in: increment current by */
 
1315
        uint64_t        offset,         /*!< in: AUTOINC offset */
 
1316
        uint64_t        max_value)      /*!< in: max value for type */
1436
1317
{
1437
 
  uint64_t  next_value;
1438
 
 
1439
 
  /* Should never be 0. */
1440
 
  ut_a(increment > 0);
1441
 
 
1442
 
  /* According to MySQL documentation, if the offset is greater than
1443
 
  the increment then the offset is ignored. */
1444
 
  if (offset > increment) {
1445
 
    offset = 0;
1446
 
  }
1447
 
 
1448
 
  if (max_value <= current) {
1449
 
    next_value = max_value;
1450
 
  } else if (offset <= 1) {
1451
 
    /* Offset 0 and 1 are the same, because there must be at
1452
 
    least one node in the system. */
1453
 
    if (max_value - current <= increment) {
1454
 
      next_value = max_value;
1455
 
    } else {
1456
 
      next_value = current + increment;
1457
 
    }
1458
 
  } else if (max_value > current) {
1459
 
    if (current > offset) {
1460
 
      next_value = ((current - offset) / increment) + 1;
1461
 
    } else {
1462
 
      next_value = ((offset - current) / increment) + 1;
1463
 
    }
1464
 
 
1465
 
    ut_a(increment > 0);
1466
 
    ut_a(next_value > 0);
1467
 
 
1468
 
    /* Check for multiplication overflow. */
1469
 
    if (increment > (max_value / next_value)) {
1470
 
 
1471
 
      next_value = max_value;
1472
 
    } else {
1473
 
      next_value *= increment;
1474
 
 
1475
 
      ut_a(max_value >= next_value);
1476
 
 
1477
 
      /* Check for overflow. */
1478
 
      if (max_value - next_value <= offset) {
1479
 
        next_value = max_value;
1480
 
      } else {
1481
 
        next_value += offset;
1482
 
      }
1483
 
    }
1484
 
  } else {
1485
 
    next_value = max_value;
1486
 
  }
1487
 
 
1488
 
  ut_a(next_value <= max_value);
1489
 
 
1490
 
  return(next_value);
 
1318
        uint64_t        next_value;
 
1319
 
 
1320
        /* Should never be 0. */
 
1321
        ut_a(increment > 0);
 
1322
 
 
1323
        /* According to MySQL documentation, if the offset is greater than
 
1324
        the increment then the offset is ignored. */
 
1325
        if (offset > increment) {
 
1326
                offset = 0;
 
1327
        }
 
1328
 
 
1329
        if (max_value <= current) {
 
1330
                next_value = max_value;
 
1331
        } else if (offset <= 1) {
 
1332
                /* Offset 0 and 1 are the same, because there must be at
 
1333
                least one node in the system. */
 
1334
                if (max_value - current <= increment) {
 
1335
                        next_value = max_value;
 
1336
                } else {
 
1337
                        next_value = current + increment;
 
1338
                }
 
1339
        } else if (max_value > current) {
 
1340
                if (current > offset) {
 
1341
                        next_value = ((current - offset) / increment) + 1;
 
1342
                } else {
 
1343
                        next_value = ((offset - current) / increment) + 1;
 
1344
                }
 
1345
 
 
1346
                ut_a(increment > 0);
 
1347
                ut_a(next_value > 0);
 
1348
 
 
1349
                /* Check for multiplication overflow. */
 
1350
                if (increment > (max_value / next_value)) {
 
1351
 
 
1352
                        next_value = max_value;
 
1353
                } else {
 
1354
                        next_value *= increment;
 
1355
 
 
1356
                        ut_a(max_value >= next_value);
 
1357
 
 
1358
                        /* Check for overflow. */
 
1359
                        if (max_value - next_value <= offset) {
 
1360
                                next_value = max_value;
 
1361
                        } else {
 
1362
                                next_value += offset;
 
1363
                        }
 
1364
                }
 
1365
        } else {
 
1366
                next_value = max_value;
 
1367
        }
 
1368
 
 
1369
        ut_a(next_value <= max_value);
 
1370
 
 
1371
        return(next_value);
1491
1372
}
1492
1373
 
1493
1374
/*********************************************************************//**
1496
1377
void
1497
1378
innobase_trx_init(
1498
1379
/*==============*/
1499
 
  Session*  session,  /*!< in: user thread handle */
1500
 
  trx_t*  trx)  /*!< in/out: InnoDB transaction handle */
 
1380
        Session*        session,        /*!< in: user thread handle */
 
1381
        trx_t*  trx)    /*!< in/out: InnoDB transaction handle */
1501
1382
{
1502
 
  assert(session == trx->mysql_thd);
1503
 
 
1504
 
  trx->check_foreigns = !session_test_options(
1505
 
    session, OPTION_NO_FOREIGN_KEY_CHECKS);
1506
 
 
1507
 
  trx->check_unique_secondary = !session_test_options(
1508
 
    session, OPTION_RELAXED_UNIQUE_CHECKS);
1509
 
 
1510
 
  return;
 
1383
        assert(session == trx->mysql_thd);
 
1384
 
 
1385
        trx->check_foreigns = !session_test_options(
 
1386
                session, OPTION_NO_FOREIGN_KEY_CHECKS);
 
1387
 
 
1388
        trx->check_unique_secondary = !session_test_options(
 
1389
                session, OPTION_RELAXED_UNIQUE_CHECKS);
 
1390
 
 
1391
        return;
1511
1392
}
1512
1393
 
1513
1394
/*********************************************************************//**
1514
1395
Allocates an InnoDB transaction for a MySQL Cursor object.
1515
 
@return InnoDB transaction handle */
 
1396
@return InnoDB transaction handle */
1516
1397
extern "C" UNIV_INTERN
1517
1398
trx_t*
1518
1399
innobase_trx_allocate(
1519
1400
/*==================*/
1520
 
  Session*  session)  /*!< in: user thread handle */
 
1401
        Session*        session)        /*!< in: user thread handle */
1521
1402
{
1522
 
  trx_t*  trx;
1523
 
 
1524
 
  assert(session != NULL);
1525
 
  assert(EQ_CURRENT_SESSION(session));
1526
 
 
1527
 
  trx = trx_allocate_for_mysql();
1528
 
 
1529
 
  trx->mysql_thd = session;
1530
 
 
1531
 
  innobase_trx_init(session, trx);
1532
 
 
1533
 
  return(trx);
 
1403
        trx_t*  trx;
 
1404
 
 
1405
        assert(session != NULL);
 
1406
        assert(EQ_CURRENT_SESSION(session));
 
1407
 
 
1408
        trx = trx_allocate_for_mysql();
 
1409
 
 
1410
        trx->mysql_thd = session;
 
1411
        trx->mysql_query_str = session->query.c_str();
 
1412
 
 
1413
        innobase_trx_init(session, trx);
 
1414
 
 
1415
        return(trx);
1534
1416
}
1535
1417
 
1536
1418
/*********************************************************************//**
1537
1419
Gets the InnoDB transaction handle for a MySQL Cursor object, creates
1538
1420
an InnoDB transaction struct if the corresponding MySQL thread struct still
1539
1421
lacks one.
1540
 
@return InnoDB transaction handle */
 
1422
@return InnoDB transaction handle */
1541
1423
static
1542
1424
trx_t*
1543
1425
check_trx_exists(
1544
1426
/*=============*/
1545
 
  Session*  session)  /*!< in: user thread handle */
 
1427
        Session*        session)        /*!< in: user thread handle */
1546
1428
{
1547
 
  trx_t*& trx = session_to_trx(session);
1548
 
 
1549
 
  ut_ad(EQ_CURRENT_SESSION(session));
1550
 
 
1551
 
  if (trx == NULL) {
1552
 
    trx = innobase_trx_allocate(session);
1553
 
  } else if (UNIV_UNLIKELY(trx->magic_n != TRX_MAGIC_N)) {
1554
 
    mem_analyze_corruption(trx);
1555
 
    ut_error;
1556
 
  }
1557
 
 
1558
 
  innobase_trx_init(session, trx);
1559
 
 
1560
 
  return(trx);
 
1429
        trx_t*& trx = session_to_trx(session);
 
1430
 
 
1431
        ut_ad(EQ_CURRENT_SESSION(session));
 
1432
 
 
1433
        if (trx == NULL) {
 
1434
                trx = innobase_trx_allocate(session);
 
1435
        } else if (UNIV_UNLIKELY(trx->magic_n != TRX_MAGIC_N)) {
 
1436
                mem_analyze_corruption(trx);
 
1437
                ut_error;
 
1438
        }
 
1439
 
 
1440
        innobase_trx_init(session, trx);
 
1441
 
 
1442
        return(trx);
1561
1443
}
1562
1444
 
1563
1445
 
1565
1447
Construct ha_innobase Cursor. */
1566
1448
UNIV_INTERN
1567
1449
ha_innobase::ha_innobase(plugin::StorageEngine &engine_arg,
1568
 
                         Table &table_arg)
 
1450
                         TableShare &table_arg)
1569
1451
  :Cursor(engine_arg, table_arg),
1570
1452
  primary_key(0), /* needs initialization because index_flags() may be called 
1571
1453
                     before this is set to the real value. It's ok to have any 
1590
1472
void
1591
1473
ha_innobase::update_session(
1592
1474
/*====================*/
1593
 
  Session*  session)  /*!< in: thd to use the handle */
1594
 
{
1595
 
  trx_t*    trx;
1596
 
 
1597
 
  assert(session);
1598
 
  trx = check_trx_exists(session);
1599
 
 
1600
 
  if (prebuilt->trx != trx) {
1601
 
 
1602
 
    row_update_prebuilt_trx(prebuilt, trx);
1603
 
  }
1604
 
 
1605
 
  user_session = session;
 
1475
        Session*        session)        /*!< in: thd to use the handle */
 
1476
{
 
1477
        trx_t*          trx;
 
1478
 
 
1479
        trx = check_trx_exists(session);
 
1480
 
 
1481
        if (prebuilt->trx != trx) {
 
1482
 
 
1483
                row_update_prebuilt_trx(prebuilt, trx);
 
1484
        }
 
1485
 
 
1486
        user_session = session;
 
1487
}
 
1488
 
 
1489
/*********************************************************************//**
 
1490
Updates the user_thd field in a handle and also allocates a new InnoDB
 
1491
transaction handle if needed, and updates the transaction fields in the
 
1492
prebuilt struct. */
 
1493
UNIV_INTERN
 
1494
void
 
1495
ha_innobase::update_session()
 
1496
/*=====================*/
 
1497
{
 
1498
        Session*        session = ha_session();
 
1499
        ut_ad(EQ_CURRENT_SESSION(session));
 
1500
        update_session(session);
1606
1501
}
1607
1502
 
1608
1503
/*****************************************************************//**
1609
1504
Convert an SQL identifier to the MySQL system_charset_info (UTF-8)
1610
1505
and quote it if needed.
1611
 
@return pointer to the end of buf */
 
1506
@return pointer to the end of buf */
1612
1507
static
1613
1508
char*
1614
1509
innobase_convert_identifier(
1615
1510
/*========================*/
1616
 
  char*   buf,  /*!< out: buffer for converted identifier */
1617
 
  ulint   buflen, /*!< in: length of buf, in bytes */
1618
 
  const char* id, /*!< in: identifier to convert */
1619
 
  ulint   idlen,  /*!< in: length of id, in bytes */
1620
 
  void*   session,/*!< in: MySQL connection thread, or NULL */
1621
 
  ibool   file_id)/*!< in: TRUE=id is a table or database name;
1622
 
        FALSE=id is an UTF-8 string */
 
1511
        char*           buf,    /*!< out: buffer for converted identifier */
 
1512
        ulint           buflen, /*!< in: length of buf, in bytes */
 
1513
        const char*     id,     /*!< in: identifier to convert */
 
1514
        ulint           idlen,  /*!< in: length of id, in bytes */
 
1515
        void*           session,/*!< in: MySQL connection thread, or NULL */
 
1516
        ibool           file_id)/*!< in: TRUE=id is a table or database name;
 
1517
                                FALSE=id is an UTF-8 string */
1623
1518
{
1624
 
  char nz[NAME_LEN + 1];
1625
 
  char nz2[NAME_LEN + 1 + sizeof srv_mysql50_table_name_prefix];
1626
 
 
1627
 
  const char* s = id;
1628
 
  int   q;
1629
 
 
1630
 
  if (file_id) {
1631
 
    /* Decode the table name.  The filename_to_tablename()
1632
 
    function expects a NUL-terminated string.  The input and
1633
 
    output strings buffers must not be shared. */
1634
 
 
1635
 
    if (UNIV_UNLIKELY(idlen > (sizeof nz) - 1)) {
1636
 
      idlen = (sizeof nz) - 1;
1637
 
    }
1638
 
 
1639
 
    memcpy(nz, id, idlen);
1640
 
    nz[idlen] = 0;
1641
 
 
1642
 
    s = nz2;
1643
 
    idlen = TableIdentifier::filename_to_tablename(nz, nz2, sizeof nz2);
1644
 
  }
1645
 
 
1646
 
  /* See if the identifier needs to be quoted. */
1647
 
  if (UNIV_UNLIKELY(!session)) {
1648
 
    q = '"';
1649
 
  } else {
1650
 
    q = get_quote_char_for_identifier();
1651
 
  }
1652
 
 
1653
 
  if (q == EOF) {
1654
 
    if (UNIV_UNLIKELY(idlen > buflen)) {
1655
 
      idlen = buflen;
1656
 
    }
1657
 
    memcpy(buf, s, idlen);
1658
 
    return(buf + idlen);
1659
 
  }
1660
 
 
1661
 
  /* Quote the identifier. */
1662
 
  if (buflen < 2) {
1663
 
    return(buf);
1664
 
  }
1665
 
 
1666
 
  *buf++ = q;
1667
 
  buflen--;
1668
 
 
1669
 
  for (; idlen; idlen--) {
1670
 
    int c = *s++;
1671
 
    if (UNIV_UNLIKELY(c == q)) {
1672
 
      if (UNIV_UNLIKELY(buflen < 3)) {
1673
 
        break;
1674
 
      }
1675
 
 
1676
 
      *buf++ = c;
1677
 
      *buf++ = c;
1678
 
      buflen -= 2;
1679
 
    } else {
1680
 
      if (UNIV_UNLIKELY(buflen < 2)) {
1681
 
        break;
1682
 
      }
1683
 
 
1684
 
      *buf++ = c;
1685
 
      buflen--;
1686
 
    }
1687
 
  }
1688
 
 
1689
 
  *buf++ = q;
1690
 
  return(buf);
 
1519
        char nz[NAME_LEN + 1];
 
1520
        char nz2[NAME_LEN + 1 + sizeof srv_mysql50_table_name_prefix];
 
1521
 
 
1522
        const char*     s       = id;
 
1523
        int             q;
 
1524
 
 
1525
        if (file_id) {
 
1526
                /* Decode the table name.  The filename_to_tablename()
 
1527
                function expects a NUL-terminated string.  The input and
 
1528
                output strings buffers must not be shared. */
 
1529
 
 
1530
                if (UNIV_UNLIKELY(idlen > (sizeof nz) - 1)) {
 
1531
                        idlen = (sizeof nz) - 1;
 
1532
                }
 
1533
 
 
1534
                memcpy(nz, id, idlen);
 
1535
                nz[idlen] = 0;
 
1536
 
 
1537
                s = nz2;
 
1538
                idlen = filename_to_tablename(nz, nz2, sizeof nz2);
 
1539
        }
 
1540
 
 
1541
        /* See if the identifier needs to be quoted. */
 
1542
        if (UNIV_UNLIKELY(!session)) {
 
1543
                q = '"';
 
1544
        } else {
 
1545
                q = get_quote_char_for_identifier();
 
1546
        }
 
1547
 
 
1548
        if (q == EOF) {
 
1549
                if (UNIV_UNLIKELY(idlen > buflen)) {
 
1550
                        idlen = buflen;
 
1551
                }
 
1552
                memcpy(buf, s, idlen);
 
1553
                return(buf + idlen);
 
1554
        }
 
1555
 
 
1556
        /* Quote the identifier. */
 
1557
        if (buflen < 2) {
 
1558
                return(buf);
 
1559
        }
 
1560
 
 
1561
        *buf++ = q;
 
1562
        buflen--;
 
1563
 
 
1564
        for (; idlen; idlen--) {
 
1565
                int     c = *s++;
 
1566
                if (UNIV_UNLIKELY(c == q)) {
 
1567
                        if (UNIV_UNLIKELY(buflen < 3)) {
 
1568
                                break;
 
1569
                        }
 
1570
 
 
1571
                        *buf++ = c;
 
1572
                        *buf++ = c;
 
1573
                        buflen -= 2;
 
1574
                } else {
 
1575
                        if (UNIV_UNLIKELY(buflen < 2)) {
 
1576
                                break;
 
1577
                        }
 
1578
 
 
1579
                        *buf++ = c;
 
1580
                        buflen--;
 
1581
                }
 
1582
        }
 
1583
 
 
1584
        *buf++ = q;
 
1585
        return(buf);
1691
1586
}
1692
1587
 
1693
1588
/*****************************************************************//**
1694
1589
Convert a table or index name to the MySQL system_charset_info (UTF-8)
1695
1590
and quote it if needed.
1696
 
@return pointer to the end of buf */
 
1591
@return pointer to the end of buf */
1697
1592
extern "C" UNIV_INTERN
1698
1593
char*
1699
1594
innobase_convert_name(
1700
1595
/*==================*/
1701
 
  char*   buf,  /*!< out: buffer for converted identifier */
1702
 
  ulint   buflen, /*!< in: length of buf, in bytes */
1703
 
  const char* id, /*!< in: identifier to convert */
1704
 
  ulint   idlen,  /*!< in: length of id, in bytes */
1705
 
  void*   session,/*!< in: MySQL connection thread, or NULL */
1706
 
  ibool   table_id)/*!< in: TRUE=id is a table or database name;
1707
 
        FALSE=id is an index name */
 
1596
        char*           buf,    /*!< out: buffer for converted identifier */
 
1597
        ulint           buflen, /*!< in: length of buf, in bytes */
 
1598
        const char*     id,     /*!< in: identifier to convert */
 
1599
        ulint           idlen,  /*!< in: length of id, in bytes */
 
1600
        void*           session,/*!< in: MySQL connection thread, or NULL */
 
1601
        ibool           table_id)/*!< in: TRUE=id is a table or database name;
 
1602
                                FALSE=id is an index name */
1708
1603
{
1709
 
  char*   s = buf;
1710
 
  const char* bufend  = buf + buflen;
1711
 
 
1712
 
  if (table_id) {
1713
 
    const char* slash = (const char*) memchr(id, '/', idlen);
1714
 
    if (!slash) {
1715
 
 
1716
 
      goto no_db_name;
1717
 
    }
1718
 
 
1719
 
    /* Print the database name and table name separately. */
1720
 
    s = innobase_convert_identifier(s, bufend - s, id, slash - id,
1721
 
            session, TRUE);
1722
 
    if (UNIV_LIKELY(s < bufend)) {
1723
 
      *s++ = '.';
1724
 
      s = innobase_convert_identifier(s, bufend - s,
1725
 
              slash + 1, idlen
1726
 
              - (slash - id) - 1,
1727
 
              session, TRUE);
1728
 
    }
1729
 
  } else if (UNIV_UNLIKELY(*id == TEMP_INDEX_PREFIX)) {
1730
 
    /* Temporary index name (smart ALTER TABLE) */
1731
 
    const char temp_index_suffix[]= "--temporary--";
1732
 
 
1733
 
    s = innobase_convert_identifier(buf, buflen, id + 1, idlen - 1,
1734
 
            session, FALSE);
1735
 
    if (s - buf + (sizeof temp_index_suffix - 1) < buflen) {
1736
 
      memcpy(s, temp_index_suffix,
1737
 
             sizeof temp_index_suffix - 1);
1738
 
      s += sizeof temp_index_suffix - 1;
1739
 
    }
1740
 
  } else {
 
1604
        char*           s       = buf;
 
1605
        const char*     bufend  = buf + buflen;
 
1606
 
 
1607
        if (table_id) {
 
1608
                const char*     slash = (const char*) memchr(id, '/', idlen);
 
1609
                if (!slash) {
 
1610
 
 
1611
                        goto no_db_name;
 
1612
                }
 
1613
 
 
1614
                /* Print the database name and table name separately. */
 
1615
                s = innobase_convert_identifier(s, bufend - s, id, slash - id,
 
1616
                                                session, TRUE);
 
1617
                if (UNIV_LIKELY(s < bufend)) {
 
1618
                        *s++ = '.';
 
1619
                        s = innobase_convert_identifier(s, bufend - s,
 
1620
                                                        slash + 1, idlen
 
1621
                                                        - (slash - id) - 1,
 
1622
                                                        session, TRUE);
 
1623
                }
 
1624
        } else if (UNIV_UNLIKELY(*id == TEMP_INDEX_PREFIX)) {
 
1625
                /* Temporary index name (smart ALTER TABLE) */
 
1626
                const char temp_index_suffix[]= "--temporary--";
 
1627
 
 
1628
                s = innobase_convert_identifier(buf, buflen, id + 1, idlen - 1,
 
1629
                                                session, FALSE);
 
1630
                if (s - buf + (sizeof temp_index_suffix - 1) < buflen) {
 
1631
                        memcpy(s, temp_index_suffix,
 
1632
                               sizeof temp_index_suffix - 1);
 
1633
                        s += sizeof temp_index_suffix - 1;
 
1634
                }
 
1635
        } else {
1741
1636
no_db_name:
1742
 
    s = innobase_convert_identifier(buf, buflen, id, idlen,
1743
 
            session, table_id);
1744
 
  }
 
1637
                s = innobase_convert_identifier(buf, buflen, id, idlen,
 
1638
                                                session, table_id);
 
1639
        }
1745
1640
 
1746
 
  return(s);
 
1641
        return(s);
1747
1642
 
1748
1643
}
1749
1644
 
1750
1645
/**********************************************************************//**
1751
1646
Determines if the currently running transaction has been interrupted.
1752
 
@return TRUE if interrupted */
 
1647
@return TRUE if interrupted */
1753
1648
extern "C" UNIV_INTERN
1754
1649
ibool
1755
1650
trx_is_interrupted(
1756
1651
/*===============*/
1757
 
  trx_t*  trx)  /*!< in: transaction */
1758
 
{
1759
 
  return(trx && trx->mysql_thd && static_cast<Session*>(trx->mysql_thd)->getKilled());
1760
 
}
1761
 
 
1762
 
/**********************************************************************//**
1763
 
Determines if the currently running transaction is in strict mode.
1764
 
@return TRUE if strict */
1765
 
extern "C" UNIV_INTERN
1766
 
ibool
1767
 
trx_is_strict(
1768
 
/*==========*/
1769
1652
        trx_t*  trx)    /*!< in: transaction */
1770
1653
{
1771
 
  return(trx && trx->mysql_thd && true);
 
1654
        return(trx && trx->mysql_thd && session_killed((Session*) trx->mysql_thd));
1772
1655
}
1773
1656
 
1774
1657
/**************************************************************//**
1778
1661
void
1779
1662
reset_template(
1780
1663
/*===========*/
1781
 
  row_prebuilt_t* prebuilt) /*!< in/out: prebuilt struct */
1782
 
{
1783
 
  prebuilt->keep_other_fields_on_keyread = 0;
1784
 
  prebuilt->read_just_key = 0;
1785
 
}
1786
 
 
1787
 
template<class T>
1788
 
void align_value(T& value, size_t align_val= 1024)
1789
 
{
1790
 
  value= value - (value % align_val);
 
1664
        row_prebuilt_t* prebuilt)       /*!< in/out: prebuilt struct */
 
1665
{
 
1666
        prebuilt->keep_other_fields_on_keyread = 0;
 
1667
        prebuilt->read_just_key = 0;
1791
1668
}
1792
1669
 
1793
1670
/*********************************************************************//**
1794
1671
Opens an InnoDB database.
1795
 
@return 0 on success, error code on failure */
 
1672
@return 0 on success, error code on failure */
1796
1673
static
1797
1674
int
1798
1675
innobase_init(
1799
1676
/*==========*/
1800
 
  module::Context &context) /*!< in: Drizzle Plugin Context */
 
1677
        plugin::Registry        &registry)      /*!< in: Drizzle Plugin Registry */
1801
1678
{
1802
 
  int   err;
1803
 
  bool    ret;
1804
 
  uint    format_id;
1805
 
  InnobaseEngine *actuall_engine_ptr;
1806
 
  const module::option_map &vm= context.getOptions();
1807
 
 
1808
 
  /* Inverted Booleans */
1809
 
 
1810
 
  innobase_use_checksums= (vm.count("disable-checksums")) ? false : true;
1811
 
  innobase_use_doublewrite= (vm.count("disable-doublewrite")) ? false : true;
1812
 
  srv_adaptive_flushing= (vm.count("disable-adaptive-flushing")) ? false : true;
1813
 
  srv_use_sys_malloc= (vm.count("use-internal-malloc")) ? false : true;
1814
 
  (SessionVAR(NULL,support_xa))= (vm.count("disable-xa")) ? false : true;
1815
 
  (SessionVAR(NULL,table_locks))= (vm.count("disable-table-locks")) ? false : true;
1816
 
 
1817
 
  if (vm.count("io-capacity"))
1818
 
  {
1819
 
    if (srv_io_capacity < 100)
1820
 
    {
1821
 
      errmsg_printf(ERRMSG_LVL_ERROR, _("Invalid value for io-capacity\n"));
1822
 
      exit(-1);
1823
 
    }
1824
 
  }
1825
 
 
1826
 
  if (vm.count("data-home-dir"))
1827
 
  {
1828
 
    innobase_data_home_dir= strdup(vm["data-home-dir"].as<string>().c_str());
1829
 
  }
1830
 
  else
1831
 
  {
1832
 
    innobase_data_home_dir= strdup(getDataHome().file_string().c_str());
1833
 
  }
1834
 
 
1835
 
  if (vm.count("fast-shutdown"))
1836
 
  {
1837
 
    if (innobase_fast_shutdown > 2)
1838
 
    {
1839
 
      errmsg_printf(ERRMSG_LVL_ERROR, _("Invalid value for fast-shutdown\n"));
1840
 
      exit(-1);
1841
 
    }
1842
 
  }
1843
 
 
1844
 
  if (vm.count("file-format-check"))
1845
 
  {
1846
 
    innobase_file_format_check= const_cast<char *>(vm["file-format-check"].as<string>().c_str());
1847
 
  }
1848
 
 
1849
 
  if (vm.count("flush-log-at-trx-commit"))
1850
 
  {
1851
 
    if (srv_flush_log_at_trx_commit > 2)
1852
 
    {
1853
 
      errmsg_printf(ERRMSG_LVL_ERROR, _("Invalid value for flush-log-at-trx-commit\n"));
1854
 
      exit(-1);
1855
 
    }
1856
 
  }
1857
 
 
1858
 
  if (vm.count("flush-method"))
1859
 
  {
1860
 
    innobase_file_flush_method= const_cast<char *>(vm["flush-method"].as<string>().c_str());
1861
 
  }
1862
 
  else
1863
 
  {
1864
 
    innobase_file_flush_method= NULL;
1865
 
  }
1866
 
 
1867
 
#ifdef UNIV_LOG_ARCHIVE
1868
 
  if (vm.count("log-arch-dir"))
1869
 
  {
1870
 
    innobase_log_arch_dir= const_cast<char *>(vm["log-arch-dir"].as<string>().c_str());
1871
 
  }
1872
 
 
1873
 
  else
1874
 
  {
1875
 
    innobase_log_arch_dir= NULL;
1876
 
  }
1877
 
#endif /* UNIV_LOG_ARCHIVE */
1878
 
 
1879
 
  if (vm.count("max-dirty-pages-pct"))
1880
 
  {
1881
 
    if (srv_max_buf_pool_modified_pct > 99)
1882
 
    {
1883
 
      errmsg_printf(ERRMSG_LVL_ERROR, _("Invalid value for max-dirty-pages-pct\n"));
1884
 
      exit(-1);
1885
 
    }
1886
 
  }
1887
 
 
1888
 
  if (vm.count("stats-sample-pages"))
1889
 
  {
1890
 
    if (srv_stats_sample_pages < 8)
1891
 
    {
1892
 
      errmsg_printf(ERRMSG_LVL_ERROR, _("Invalid value for stats-sample-pages\n"));
1893
 
      exit(-1);
1894
 
    }
1895
 
  }
1896
 
 
1897
 
  if (vm.count("additional-mem-pool-size"))
1898
 
  {
1899
 
    align_value(innobase_additional_mem_pool_size);
1900
 
 
1901
 
    if (innobase_additional_mem_pool_size < 512*1024L)
1902
 
    {
1903
 
      errmsg_printf(ERRMSG_LVL_ERROR, _("Invalid value for additional-mem-pool-size\n"));
1904
 
      exit(-1);
1905
 
    }
1906
 
 
1907
 
  }
1908
 
 
1909
 
  if (vm.count("autoextend-increment"))
1910
 
  {
1911
 
    if (srv_auto_extend_increment < 1 || srv_auto_extend_increment > 1000)
1912
 
    {
1913
 
      errmsg_printf(ERRMSG_LVL_ERROR, _("Invalid value for autoextend-increment\n"));
1914
 
      exit(-1);
1915
 
    }
1916
 
  }
1917
 
 
1918
 
  if (vm.count("buffer-pool-size"))
1919
 
  {
1920
 
    align_value(innobase_buffer_pool_size, 1024*1024);
1921
 
    if (innobase_buffer_pool_size < 5*1024*1024)
1922
 
    {
1923
 
      errmsg_printf(ERRMSG_LVL_ERROR, _("Invalid value for buffer-pool-size\n"));
1924
 
      exit(-1);
1925
 
    }
1926
 
    
1927
 
  }
1928
 
 
1929
 
  if (vm.count("commit-concurrency"))
1930
 
  {
1931
 
    if (srv_replication_delay > 1000)
1932
 
    {
1933
 
      errmsg_printf(ERRMSG_LVL_ERROR, _("Invalid value for commit-concurrency\n"));
1934
 
      exit(-1);
1935
 
    }
1936
 
  }
1937
 
 
1938
 
  if (vm.count("concurrency-tickets"))
1939
 
  {
1940
 
    if (srv_n_free_tickets_to_enter < 1)
1941
 
    {
1942
 
      errmsg_printf(ERRMSG_LVL_ERROR, _("Invalid value for concurrency-tickets\n"));
1943
 
      exit(-1);
1944
 
    }
1945
 
  }
1946
 
 
1947
 
  if (vm.count("read-io-threads"))
1948
 
  {
1949
 
    if (innobase_read_io_threads < 1 || innobase_read_io_threads > 64)
1950
 
    {
1951
 
      errmsg_printf(ERRMSG_LVL_ERROR, _("Invalid value for read-io-threads\n"));
1952
 
      exit(-1);
1953
 
    }
1954
 
  }
1955
 
 
1956
 
  if (vm.count("write-io-threads"))
1957
 
  {
1958
 
    if (innobase_write_io_threads < 1 || innobase_write_io_threads > 64)
1959
 
    {
1960
 
      errmsg_printf(ERRMSG_LVL_ERROR, _("Invalid value for write-io-threads\n"));
1961
 
      exit(-1);
1962
 
    }
1963
 
  }
1964
 
 
1965
 
  if (vm.count("force-recovery"))
1966
 
  {
1967
 
    if (innobase_force_recovery > 6)
1968
 
    {
1969
 
      errmsg_printf(ERRMSG_LVL_ERROR, _("Invalid value for force-recovery\n"));
1970
 
      exit(-1);
1971
 
    }
1972
 
  }
1973
 
 
1974
 
  if (vm.count("log-buffer-size"))
1975
 
  {
1976
 
    align_value(innobase_log_buffer_size);
1977
 
    if (innobase_log_buffer_size < 256*1024L)
1978
 
    {
1979
 
      errmsg_printf(ERRMSG_LVL_ERROR, _("Invalid value for log-file-size\n"));
1980
 
      exit(-1);
1981
 
    }
1982
 
  }
1983
 
 
1984
 
  if (vm.count("log-file-size"))
1985
 
  {
1986
 
    align_value(innobase_log_file_size, 1024*1024);
1987
 
    if (innobase_log_file_size < 1*1024*1024L)
1988
 
    {
1989
 
      errmsg_printf(ERRMSG_LVL_ERROR, _("Invalid value for log-file-size\n"));
1990
 
      exit(-1);
1991
 
    }
1992
 
  }
1993
 
 
1994
 
  if (vm.count("log-files-in-group"))
1995
 
  {
1996
 
    if (innobase_log_files_in_group < 2 || innobase_log_files_in_group > 100)
1997
 
    {
1998
 
      errmsg_printf(ERRMSG_LVL_ERROR, _("Invalid value for log-files-in-group\n"));
1999
 
      exit(-1);
2000
 
    }
2001
 
  }
2002
 
 
2003
 
  if (vm.count("mirrored-log-groups"))
2004
 
  {
2005
 
    if (innobase_mirrored_log_groups < 1 || innobase_mirrored_log_groups > 10)
2006
 
    {
2007
 
      errmsg_printf(ERRMSG_LVL_ERROR, _("Invalid value for mirrored-log-groups\n"));
2008
 
      exit(-1);
2009
 
    }
2010
 
  }
2011
 
 
2012
 
  if (vm.count("open-files"))
2013
 
  {
2014
 
    if (innobase_open_files < 10)
2015
 
    {
2016
 
      errmsg_printf(ERRMSG_LVL_ERROR, _("Invalid value for open-files\n"));
2017
 
      exit(-1);
2018
 
    }
2019
 
  }
2020
 
 
2021
 
  if (vm.count("thread-concurrency"))
2022
 
  {
2023
 
    if (srv_thread_concurrency > 1000)
2024
 
    {
2025
 
      errmsg_printf(ERRMSG_LVL_ERROR, _("Invalid value for thread-concurrency\n"));
2026
 
      exit(-1);
2027
 
    }
2028
 
  }
2029
 
 
2030
 
  if (vm.count("data-file-path"))
2031
 
  {
2032
 
    innobase_data_file_path= const_cast<char *>(vm["data-file-path"].as<string>().c_str());
2033
 
  }
2034
 
  else
2035
 
  {
2036
 
    innobase_data_file_path= NULL;
2037
 
  }
2038
 
 
2039
 
  if (vm.count("version"))
2040
 
  {
2041
 
    innodb_version_str= const_cast<char *>(vm["version"].as<string>().c_str());
2042
 
  }
2043
 
 
2044
 
  if (vm.count("read-ahead-threshold"))
2045
 
  {
2046
 
    if (srv_read_ahead_threshold > 64)
2047
 
    {
2048
 
      errmsg_printf(ERRMSG_LVL_ERROR, _("Invalid value for read-ahead-threshold\n"));
2049
 
      exit(-1);
2050
 
    }
2051
 
  }
2052
 
 
2053
 
  if (vm.count("strict-mode"))
2054
 
  {
2055
 
    (SessionVAR(NULL,strict_mode))= vm["strict-mode"].as<bool>();
2056
 
  }
2057
 
 
2058
 
  if (vm.count("lock-wait-timeout"))
2059
 
  {
2060
 
    if (vm["lock-wait-timeout"].as<unsigned long>() < 1 || vm["lock-wait-timeout"].as<unsigned long>() > 1024*1024*1024)
2061
 
    {
2062
 
      errmsg_printf(ERRMSG_LVL_ERROR, _("Invalid value for lock-wait-timeout\n"));
2063
 
      exit(-1);
2064
 
    }
2065
 
 
2066
 
    (SessionVAR(NULL,lock_wait_timeout))= vm["lock-wait-timeout"].as<unsigned long>();
2067
 
  }
2068
 
 
2069
 
  innodb_engine_ptr= actuall_engine_ptr= new InnobaseEngine(innobase_engine_name);
2070
 
 
2071
 
  ut_a(DATA_MYSQL_TRUE_VARCHAR == (ulint)DRIZZLE_TYPE_VARCHAR);
 
1679
        static char     current_dir[3];         /*!< Set if using current lib */
 
1680
        int             err;
 
1681
        bool            ret;
 
1682
        char            *default_path;
 
1683
        uint            format_id;
 
1684
 
 
1685
        innodb_engine_ptr= new InnobaseEngine(innobase_engine_name);
 
1686
 
 
1687
 
 
1688
        ut_a(DATA_MYSQL_TRUE_VARCHAR == (ulint)DRIZZLE_TYPE_VARCHAR);
2072
1689
 
2073
1690
#ifdef UNIV_DEBUG
2074
 
  static const char test_filename[] = "-@";
2075
 
  char      test_tablename[sizeof test_filename
2076
 
    + sizeof srv_mysql50_table_name_prefix];
2077
 
  if ((sizeof test_tablename) - 1
2078
 
      != filename_to_tablename(test_filename, test_tablename,
2079
 
                               sizeof test_tablename)
2080
 
      || strncmp(test_tablename,
2081
 
                 srv_mysql50_table_name_prefix,
2082
 
                 sizeof srv_mysql50_table_name_prefix)
2083
 
      || strcmp(test_tablename
2084
 
                + sizeof srv_mysql50_table_name_prefix,
2085
 
                test_filename)) {
2086
 
    errmsg_printf(ERRMSG_LVL_ERROR, "tablename encoding has been changed");
2087
 
    goto error;
2088
 
  }
 
1691
        static const char       test_filename[] = "-@";
 
1692
        char                    test_tablename[sizeof test_filename
 
1693
                                + sizeof srv_mysql50_table_name_prefix];
 
1694
        if ((sizeof test_tablename) - 1
 
1695
                        != filename_to_tablename(test_filename, test_tablename,
 
1696
                        sizeof test_tablename)
 
1697
                        || strncmp(test_tablename,
 
1698
                        srv_mysql50_table_name_prefix,
 
1699
                        sizeof srv_mysql50_table_name_prefix)
 
1700
                        || strcmp(test_tablename
 
1701
                        + sizeof srv_mysql50_table_name_prefix,
 
1702
                        test_filename)) {
 
1703
                errmsg_printf(ERRMSG_LVL_ERROR, "tablename encoding has been changed");
 
1704
                goto error;
 
1705
        }
2089
1706
#endif /* UNIV_DEBUG */
2090
1707
 
2091
 
  /* Check that values don't overflow on 32-bit systems. */
2092
 
  if (sizeof(ulint) == 4) {
2093
 
    if (innobase_buffer_pool_size > UINT32_MAX) {
2094
 
      errmsg_printf(ERRMSG_LVL_ERROR, 
2095
 
                    "innobase_buffer_pool_size can't be over 4GB"
2096
 
                    " on 32-bit systems");
2097
 
 
2098
 
      goto error;
2099
 
    }
2100
 
 
2101
 
    if (innobase_log_file_size > UINT32_MAX) {
2102
 
      errmsg_printf(ERRMSG_LVL_ERROR, 
2103
 
                    "innobase_log_file_size can't be over 4GB"
2104
 
                    " on 32-bit systems");
2105
 
 
2106
 
      goto error;
2107
 
    }
2108
 
  }
2109
 
 
2110
 
  os_innodb_umask = (ulint)internal::my_umask;
2111
 
 
2112
 
 
2113
 
  /* Set InnoDB initialization parameters according to the values
2114
 
    read from MySQL .cnf file */
2115
 
 
2116
 
  /*--------------- Data files -------------------------*/
2117
 
 
2118
 
  /* The default dir for data files is the datadir of MySQL */
2119
 
 
2120
 
  srv_data_home = (char *)innobase_data_home_dir;
2121
 
 
2122
 
  /* Set default InnoDB data file size to 10 MB and let it be
2123
 
    auto-extending. Thus users can use InnoDB in >= 4.0 without having
2124
 
    to specify any startup options. */
2125
 
 
2126
 
  if (!innobase_data_file_path) {
2127
 
    innobase_data_file_path = (char*) "ibdata1:10M:autoextend";
2128
 
  }
2129
 
 
2130
 
  /* Since InnoDB edits the argument in the next call, we make another
2131
 
    copy of it: */
2132
 
 
2133
 
  internal_innobase_data_file_path = strdup(innobase_data_file_path);
2134
 
 
2135
 
  ret = (bool) srv_parse_data_file_paths_and_sizes(
2136
 
                                                   internal_innobase_data_file_path);
2137
 
  if (ret == FALSE) {
2138
 
    errmsg_printf(ERRMSG_LVL_ERROR, 
2139
 
                  "InnoDB: syntax error in innodb_data_file_path");
 
1708
        /* Check that values don't overflow on 32-bit systems. */
 
1709
        if (sizeof(ulint) == 4) {
 
1710
                if (innobase_buffer_pool_size > UINT32_MAX) {
 
1711
                        errmsg_printf(ERRMSG_LVL_ERROR, 
 
1712
                                "innobase_buffer_pool_size can't be over 4GB"
 
1713
                                " on 32-bit systems");
 
1714
 
 
1715
                        goto error;
 
1716
                }
 
1717
 
 
1718
                if (innobase_log_file_size > UINT32_MAX) {
 
1719
                        errmsg_printf(ERRMSG_LVL_ERROR, 
 
1720
                                "innobase_log_file_size can't be over 4GB"
 
1721
                                " on 32-bit systems");
 
1722
 
 
1723
                        goto error;
 
1724
                }
 
1725
        }
 
1726
 
 
1727
        os_innodb_umask = (ulint)internal::my_umask;
 
1728
 
 
1729
        /* First calculate the default path for innodb_data_home_dir etc.,
 
1730
        in case the user has not given any value.
 
1731
 
 
1732
        Note that when using the embedded server, the datadirectory is not
 
1733
        necessarily the current directory of this program. */
 
1734
 
 
1735
        /* It's better to use current lib, to keep paths short */
 
1736
        current_dir[0] = FN_CURLIB;
 
1737
        current_dir[1] = FN_LIBCHAR;
 
1738
        current_dir[2] = 0;
 
1739
        default_path = current_dir;
 
1740
 
 
1741
        ut_a(default_path);
 
1742
 
 
1743
        srv_set_thread_priorities = TRUE;
 
1744
        srv_query_thread_priority = QUERY_PRIOR;
 
1745
 
 
1746
        /* Set InnoDB initialization parameters according to the values
 
1747
        read from MySQL .cnf file */
 
1748
 
 
1749
        /*--------------- Data files -------------------------*/
 
1750
 
 
1751
        /* The default dir for data files is the datadir of MySQL */
 
1752
 
 
1753
        srv_data_home = (innobase_data_home_dir ? innobase_data_home_dir :
 
1754
                         default_path);
 
1755
 
 
1756
        /* Set default InnoDB data file size to 10 MB and let it be
 
1757
        auto-extending. Thus users can use InnoDB in >= 4.0 without having
 
1758
        to specify any startup options. */
 
1759
 
 
1760
        if (!innobase_data_file_path) {
 
1761
                innobase_data_file_path = (char*) "ibdata1:10M:autoextend";
 
1762
        }
 
1763
 
 
1764
        /* Since InnoDB edits the argument in the next call, we make another
 
1765
        copy of it: */
 
1766
 
 
1767
        internal_innobase_data_file_path = strdup(innobase_data_file_path);
 
1768
 
 
1769
        ret = (bool) srv_parse_data_file_paths_and_sizes(
 
1770
                internal_innobase_data_file_path);
 
1771
        if (ret == FALSE) {
 
1772
                errmsg_printf(ERRMSG_LVL_ERROR, 
 
1773
                        "InnoDB: syntax error in innodb_data_file_path");
2140
1774
mem_free_and_error:
2141
 
    srv_free_paths_and_sizes();
2142
 
    if (internal_innobase_data_file_path)
2143
 
      free(internal_innobase_data_file_path);
2144
 
    goto error;
2145
 
  }
2146
 
 
2147
 
  /* -------------- Log files ---------------------------*/
2148
 
 
2149
 
  /* The default dir for log files is the datadir of MySQL */
2150
 
 
2151
 
  if (vm.count("log-group-home-dir"))
2152
 
  {
2153
 
    innobase_log_group_home_dir= strdup(vm["log-group-home-dir"].as<string>().c_str());
2154
 
  }
2155
 
  else
2156
 
  {
2157
 
    innobase_log_group_home_dir = strdup(getDataHome().file_string().c_str());
2158
 
  }
 
1775
                srv_free_paths_and_sizes();
 
1776
                if (internal_innobase_data_file_path)
 
1777
                  free(internal_innobase_data_file_path);
 
1778
                goto error;
 
1779
        }
 
1780
 
 
1781
        /* -------------- Log files ---------------------------*/
 
1782
 
 
1783
        /* The default dir for log files is the datadir of MySQL */
 
1784
 
 
1785
        if (!innobase_log_group_home_dir) {
 
1786
                innobase_log_group_home_dir = default_path;
 
1787
        }
2159
1788
 
2160
1789
#ifdef UNIV_LOG_ARCHIVE
2161
 
  /* Since innodb_log_arch_dir has no relevance under MySQL,
2162
 
    starting from 4.0.6 we always set it the same as
2163
 
innodb_log_group_home_dir: */
2164
 
 
2165
 
  innobase_log_arch_dir = innobase_log_group_home_dir;
2166
 
 
2167
 
  srv_arch_dir = innobase_log_arch_dir;
 
1790
        /* Since innodb_log_arch_dir has no relevance under MySQL,
 
1791
        starting from 4.0.6 we always set it the same as
 
1792
        innodb_log_group_home_dir: */
 
1793
 
 
1794
        innobase_log_arch_dir = innobase_log_group_home_dir;
 
1795
 
 
1796
        srv_arch_dir = innobase_log_arch_dir;
2168
1797
#endif /* UNIG_LOG_ARCHIVE */
2169
1798
 
2170
 
  ret = (bool)
2171
 
    srv_parse_log_group_home_dirs(innobase_log_group_home_dir);
2172
 
 
2173
 
  if (ret == FALSE || innobase_mirrored_log_groups != 1) {
2174
 
    errmsg_printf(ERRMSG_LVL_ERROR, "syntax error in innodb_log_group_home_dir, or a "
2175
 
                  "wrong number of mirrored log groups");
2176
 
 
2177
 
    goto mem_free_and_error;
2178
 
  }
2179
 
 
2180
 
 
2181
 
  /* Validate the file format by animal name */
2182
 
  if (vm.count("file-format"))
2183
 
  {
2184
 
    format_id = innobase_file_format_name_lookup(
2185
 
                                                 vm["file-format"].as<string>().c_str());
2186
 
 
2187
 
    if (format_id > DICT_TF_FORMAT_MAX) {
2188
 
 
2189
 
      errmsg_printf(ERRMSG_LVL_ERROR, "InnoDB: wrong innodb_file_format.");
2190
 
 
2191
 
      goto mem_free_and_error;
2192
 
    }
2193
 
  } else {
2194
 
    /* Set it to the default file format id.*/
2195
 
    format_id = 0;
2196
 
  }
2197
 
 
2198
 
  srv_file_format = format_id;
2199
 
 
2200
 
  /* Given the type of innobase_file_format_name we have little
2201
 
    choice but to cast away the constness from the returned name.
2202
 
    innobase_file_format_name is used in the MySQL set variable
2203
 
    interface and so can't be const. */
2204
 
 
2205
 
  innobase_file_format_name = 
2206
 
    (char*) trx_sys_file_format_id_to_name(format_id);
2207
 
 
2208
 
  /* Process innobase_file_format_check variable */
2209
 
  ut_a(innobase_file_format_check != NULL);
2210
 
 
2211
 
  /* As a side effect it will set srv_check_file_format_at_startup
2212
 
    on valid input. First we check for "on"/"off". */
2213
 
  if (!innobase_file_format_check_on_off(innobase_file_format_check)) {
2214
 
 
2215
 
    /* Did the user specify a format name that we support ?
2216
 
      As a side effect it will update the variable
2217
 
      srv_check_file_format_at_startup */
2218
 
    if (innobase_file_format_validate_and_set(
2219
 
                                innobase_file_format_check) < 0) {
2220
 
      errmsg_printf(ERRMSG_LVL_ERROR, "InnoDB: invalid "
2221
 
                    "innodb_file_format_check value: "
2222
 
                    "should be either 'on' or 'off' or "
2223
 
                    "any value up to %s or its "
2224
 
                    "equivalent numeric id",
2225
 
                    trx_sys_file_format_id_to_name(
2226
 
                                                   DICT_TF_FORMAT_MAX));
2227
 
 
2228
 
      goto mem_free_and_error;
2229
 
    }
2230
 
  }
2231
 
 
2232
 
  if (vm.count("change-buffering"))
2233
 
  {
2234
 
    ulint use;
2235
 
 
2236
 
    for (use = 0;
2237
 
         use < UT_ARR_SIZE(innobase_change_buffering_values);
2238
 
         use++) {
2239
 
      if (!innobase_strcasecmp(
2240
 
                               vm["change-buffering"].as<string>().c_str(),
2241
 
                               innobase_change_buffering_values[use])) {
2242
 
        ibuf_use = (ibuf_use_t) use;
2243
 
        goto innobase_change_buffering_inited_ok;
2244
 
      }
2245
 
    }
2246
 
 
2247
 
    errmsg_printf(ERRMSG_LVL_ERROR,
2248
 
                  "InnoDB: invalid value "
2249
 
                  "innodb_file_format_check=%s",
2250
 
                  vm["change-buffering"].as<string>().c_str());
2251
 
    goto mem_free_and_error;
2252
 
  }
 
1799
        ret = (bool)
 
1800
                srv_parse_log_group_home_dirs(innobase_log_group_home_dir);
 
1801
 
 
1802
        if (ret == FALSE || innobase_mirrored_log_groups != 1) {
 
1803
          errmsg_printf(ERRMSG_LVL_ERROR, "syntax error in innodb_log_group_home_dir, or a "
 
1804
                          "wrong number of mirrored log groups");
 
1805
 
 
1806
                goto mem_free_and_error;
 
1807
        }
 
1808
 
 
1809
        /* Validate the file format by animal name */
 
1810
        if (innobase_file_format_name != NULL) {
 
1811
 
 
1812
                format_id = innobase_file_format_name_lookup(
 
1813
                        innobase_file_format_name);
 
1814
 
 
1815
                if (format_id > DICT_TF_FORMAT_MAX) {
 
1816
 
 
1817
                        errmsg_printf(ERRMSG_LVL_ERROR, "InnoDB: wrong innodb_file_format.");
 
1818
 
 
1819
                        goto mem_free_and_error;
 
1820
                }
 
1821
        } else {
 
1822
                /* Set it to the default file format id. Though this
 
1823
                should never happen. */
 
1824
                format_id = 0;
 
1825
        }
 
1826
 
 
1827
        srv_file_format = format_id;
 
1828
 
 
1829
        /* Given the type of innobase_file_format_name we have little
 
1830
        choice but to cast away the constness from the returned name.
 
1831
        innobase_file_format_name is used in the MySQL set variable
 
1832
        interface and so can't be const. */
 
1833
 
 
1834
        innobase_file_format_name = 
 
1835
                (char*) trx_sys_file_format_id_to_name(format_id);
 
1836
 
 
1837
        /* Process innobase_file_format_check variable */
 
1838
        ut_a(innobase_file_format_check != NULL);
 
1839
 
 
1840
        /* As a side effect it will set srv_check_file_format_at_startup
 
1841
        on valid input. First we check for "on"/"off". */
 
1842
        if (!innobase_file_format_check_on_off(innobase_file_format_check)) {
 
1843
 
 
1844
                /* Did the user specify a format name that we support ?
 
1845
                As a side effect it will update the variable
 
1846
                srv_check_file_format_at_startup */
 
1847
                if (!innobase_file_format_check_validate(
 
1848
                        innobase_file_format_check)) {
 
1849
 
 
1850
                        errmsg_printf(ERRMSG_LVL_ERROR, "InnoDB: invalid "
 
1851
                                        "innodb_file_format_check value: "
 
1852
                                        "should be either 'on' or 'off' or "
 
1853
                                        "any value up to %s or its "
 
1854
                                        "equivalent numeric id",
 
1855
                                        trx_sys_file_format_id_to_name(
 
1856
                                                DICT_TF_FORMAT_MAX));
 
1857
 
 
1858
                        goto mem_free_and_error;
 
1859
                }
 
1860
        }
 
1861
 
 
1862
        if (innobase_change_buffering) {
 
1863
                ulint   use;
 
1864
 
 
1865
                for (use = 0;
 
1866
                     use < UT_ARR_SIZE(innobase_change_buffering_values);
 
1867
                     use++) {
 
1868
                        if (!innobase_strcasecmp(
 
1869
                                    innobase_change_buffering,
 
1870
                                    innobase_change_buffering_values[use])) {
 
1871
                                ibuf_use = (ibuf_use_t) use;
 
1872
                                goto innobase_change_buffering_inited_ok;
 
1873
                        }
 
1874
                }
 
1875
 
 
1876
                errmsg_printf(ERRMSG_LVL_ERROR,
 
1877
                                "InnoDB: invalid value "
 
1878
                                "innodb_file_format_check=%s",
 
1879
                                innobase_change_buffering);
 
1880
                goto mem_free_and_error;
 
1881
        }
2253
1882
 
2254
1883
innobase_change_buffering_inited_ok:
2255
 
  ut_a((ulint) ibuf_use < UT_ARR_SIZE(innobase_change_buffering_values));
2256
 
  innobase_change_buffering = (char*)
2257
 
    innobase_change_buffering_values[ibuf_use];
2258
 
 
2259
 
  /* --------------------------------------------------*/
2260
 
 
2261
 
  srv_file_flush_method_str = innobase_file_flush_method;
2262
 
 
2263
 
  srv_n_log_groups = (ulint) innobase_mirrored_log_groups;
2264
 
  srv_n_log_files = (ulint) innobase_log_files_in_group;
2265
 
  srv_log_file_size = (ulint) innobase_log_file_size;
 
1884
        ut_a((ulint) ibuf_use < UT_ARR_SIZE(innobase_change_buffering_values));
 
1885
        innobase_change_buffering = (char*)
 
1886
                innobase_change_buffering_values[ibuf_use];
 
1887
 
 
1888
        /* --------------------------------------------------*/
 
1889
 
 
1890
        srv_file_flush_method_str = innobase_unix_file_flush_method;
 
1891
 
 
1892
        srv_n_log_groups = (ulint) innobase_mirrored_log_groups;
 
1893
        srv_n_log_files = (ulint) innobase_log_files_in_group;
 
1894
        srv_log_file_size = (ulint) innobase_log_file_size;
2266
1895
 
2267
1896
#ifdef UNIV_LOG_ARCHIVE
2268
 
  srv_log_archive_on = (ulint) innobase_log_archive;
 
1897
        srv_log_archive_on = (ulint) innobase_log_archive;
2269
1898
#endif /* UNIV_LOG_ARCHIVE */
2270
 
  srv_log_buffer_size = (ulint) innobase_log_buffer_size;
2271
 
 
2272
 
  srv_buf_pool_size = (ulint) innobase_buffer_pool_size;
2273
 
 
2274
 
  srv_mem_pool_size = (ulint) innobase_additional_mem_pool_size;
2275
 
 
2276
 
  srv_n_read_io_threads = (ulint) innobase_read_io_threads;
2277
 
  srv_n_write_io_threads = (ulint) innobase_write_io_threads;
2278
 
 
2279
 
  srv_force_recovery = (ulint) innobase_force_recovery;
2280
 
 
2281
 
  srv_use_doublewrite_buf = (ibool) innobase_use_doublewrite;
2282
 
  srv_use_checksums = (ibool) innobase_use_checksums;
 
1899
        srv_log_buffer_size = (ulint) innobase_log_buffer_size;
 
1900
 
 
1901
        srv_buf_pool_size = (ulint) innobase_buffer_pool_size;
 
1902
 
 
1903
        srv_mem_pool_size = (ulint) innobase_additional_mem_pool_size;
 
1904
 
 
1905
        srv_n_file_io_threads = (ulint) innobase_file_io_threads;
 
1906
        srv_n_read_io_threads = (ulint) innobase_read_io_threads;
 
1907
        srv_n_write_io_threads = (ulint) innobase_write_io_threads;
 
1908
 
 
1909
        srv_force_recovery = (ulint) innobase_force_recovery;
 
1910
 
 
1911
        srv_use_doublewrite_buf = (ibool) innobase_use_doublewrite;
 
1912
        srv_use_checksums = (ibool) innobase_use_checksums;
2283
1913
 
2284
1914
#ifdef HAVE_LARGE_PAGES
2285
 
  if ((os_use_large_pages = (ibool) my_use_large_pages))
2286
 
    os_large_page_size = (ulint) opt_large_page_size;
 
1915
        if ((os_use_large_pages = (ibool) my_use_large_pages))
 
1916
                os_large_page_size = (ulint) opt_large_page_size;
2287
1917
#endif
2288
1918
 
2289
 
  row_rollback_on_timeout = (ibool) innobase_rollback_on_timeout;
2290
 
 
2291
 
  srv_locks_unsafe_for_binlog = (ibool) TRUE;
2292
 
 
2293
 
  srv_max_n_open_files = (ulint) innobase_open_files;
2294
 
  srv_innodb_status = (ibool) innobase_create_status_file;
2295
 
 
2296
 
  srv_print_verbose_log = true;
2297
 
 
2298
 
  /* Store the default charset-collation number of this MySQL
2299
 
    installation */
2300
 
 
2301
 
  data_mysql_default_charset_coll = (ulint)default_charset_info->number;
2302
 
 
2303
 
  innobase_old_blocks_pct = buf_LRU_old_ratio_update(innobase_old_blocks_pct,
2304
 
                                                     FALSE);
2305
 
 
2306
 
  innobase_commit_concurrency_init_default();
2307
 
 
2308
 
  /* Since we in this module access directly the fields of a trx
2309
 
    struct, and due to different headers and flags it might happen that
2310
 
    mutex_t has a different size in this module and in InnoDB
2311
 
    modules, we check at run time that the size is the same in
2312
 
    these compilation modules. */
2313
 
 
2314
 
  err = innobase_start_or_create_for_mysql();
2315
 
 
2316
 
  if (err != DB_SUCCESS) {
2317
 
    goto mem_free_and_error;
2318
 
  }
2319
 
 
2320
 
  innobase_open_tables = hash_create(200);
2321
 
  pthread_mutex_init(&innobase_share_mutex, MY_MUTEX_INIT_FAST);
2322
 
  pthread_mutex_init(&prepare_commit_mutex, MY_MUTEX_INIT_FAST);
2323
 
  pthread_mutex_init(&commit_threads_m, MY_MUTEX_INIT_FAST);
2324
 
  pthread_mutex_init(&commit_cond_m, MY_MUTEX_INIT_FAST);
2325
 
  pthread_cond_init(&commit_cond, NULL);
2326
 
  innodb_inited= 1;
2327
 
 
2328
 
  actuall_engine_ptr->dropTemporarySchema();
2329
 
 
2330
 
  status_table_function_ptr= new InnodbStatusTool;
2331
 
 
2332
 
  context.add(innodb_engine_ptr);
2333
 
 
2334
 
  context.add(status_table_function_ptr);
2335
 
 
2336
 
  cmp_tool= new(std::nothrow)CmpTool(false);
2337
 
  context.add(cmp_tool);
2338
 
 
2339
 
  cmp_reset_tool= new(std::nothrow)CmpTool(true);
2340
 
  context.add(cmp_reset_tool);
2341
 
 
2342
 
  cmp_mem_tool= new(std::nothrow)CmpmemTool(false);
2343
 
  context.add(cmp_mem_tool);
2344
 
 
2345
 
  cmp_mem_reset_tool= new(std::nothrow)CmpmemTool(true);
2346
 
  context.add(cmp_mem_reset_tool);
2347
 
 
2348
 
  innodb_trx_tool= new(std::nothrow)InnodbTrxTool("INNODB_TRX");
2349
 
  context.add(innodb_trx_tool);
2350
 
 
2351
 
  innodb_locks_tool= new(std::nothrow)InnodbTrxTool("INNODB_LOCKS");
2352
 
  context.add(innodb_locks_tool);
2353
 
 
2354
 
  innodb_lock_waits_tool= new(std::nothrow)InnodbTrxTool("INNODB_LOCK_WAITS");
2355
 
  context.add(innodb_lock_waits_tool);
2356
 
 
2357
 
  context.add(new(std::nothrow)InnodbInternalTables());
2358
 
 
2359
 
  /* Get the current high water mark format. */
2360
 
  innobase_file_format_check = (char*) trx_sys_file_format_max_get();
2361
 
 
2362
 
  return(FALSE);
 
1919
        row_rollback_on_timeout = (ibool) innobase_rollback_on_timeout;
 
1920
 
 
1921
        srv_locks_unsafe_for_binlog = (ibool) innobase_locks_unsafe_for_binlog;
 
1922
 
 
1923
        srv_max_n_open_files = (ulint) innobase_open_files;
 
1924
        srv_innodb_status = (ibool) innobase_create_status_file;
 
1925
 
 
1926
        srv_print_verbose_log = true;
 
1927
 
 
1928
        /* Store the default charset-collation number of this MySQL
 
1929
        installation */
 
1930
 
 
1931
        data_mysql_default_charset_coll = (ulint)default_charset_info->number;
 
1932
 
 
1933
 
 
1934
        innobase_commit_concurrency_init_default();
 
1935
 
 
1936
        /* Since we in this module access directly the fields of a trx
 
1937
        struct, and due to different headers and flags it might happen that
 
1938
        mutex_t has a different size in this module and in InnoDB
 
1939
        modules, we check at run time that the size is the same in
 
1940
        these compilation modules. */
 
1941
 
 
1942
        err = innobase_start_or_create_for_mysql();
 
1943
 
 
1944
        if (err != DB_SUCCESS) {
 
1945
                goto mem_free_and_error;
 
1946
        }
 
1947
 
 
1948
        innobase_open_tables = hash_create(200);
 
1949
        pthread_mutex_init(&innobase_share_mutex, MY_MUTEX_INIT_FAST);
 
1950
        pthread_mutex_init(&prepare_commit_mutex, MY_MUTEX_INIT_FAST);
 
1951
        pthread_mutex_init(&commit_threads_m, MY_MUTEX_INIT_FAST);
 
1952
        pthread_mutex_init(&commit_cond_m, MY_MUTEX_INIT_FAST);
 
1953
        pthread_cond_init(&commit_cond, NULL);
 
1954
        innodb_inited= 1;
 
1955
 
 
1956
        status_table_function_ptr= new InnodbStatusTool;
 
1957
 
 
1958
        registry.add(innodb_engine_ptr);
 
1959
 
 
1960
        registry.add(status_table_function_ptr);
 
1961
 
 
1962
        cmp_tool= new(std::nothrow)CmpTool(false);
 
1963
        registry.add(cmp_tool);
 
1964
 
 
1965
        cmp_reset_tool= new(std::nothrow)CmpTool(true);
 
1966
        registry.add(cmp_reset_tool);
 
1967
 
 
1968
        cmp_mem_tool= new(std::nothrow)CmpmemTool(false);
 
1969
        registry.add(cmp_mem_tool);
 
1970
 
 
1971
        cmp_mem_reset_tool= new(std::nothrow)CmpmemTool(true);
 
1972
        registry.add(cmp_mem_reset_tool);
 
1973
 
 
1974
        innodb_trx_tool= new(std::nothrow)InnodbTrxTool("INNODB_TRX");
 
1975
        registry.add(innodb_trx_tool);
 
1976
 
 
1977
        innodb_locks_tool= new(std::nothrow)InnodbTrxTool("INNODB_LOCKS");
 
1978
        registry.add(innodb_locks_tool);
 
1979
 
 
1980
        innodb_lock_waits_tool= new(std::nothrow)InnodbTrxTool("INNODB_LOCK_WAITS");
 
1981
        registry.add(innodb_lock_waits_tool);
 
1982
 
 
1983
        /* Get the current high water mark format. */
 
1984
        innobase_file_format_check = (char*) trx_sys_file_format_max_get();
 
1985
 
 
1986
        return(FALSE);
2363
1987
error:
2364
 
  return(TRUE);
2365
 
}
2366
 
 
 
1988
        return(TRUE);
 
1989
}
 
1990
 
 
1991
/*******************************************************************//**
 
1992
Closes an InnoDB database.
 
1993
@return TRUE if error */
 
1994
static
 
1995
int
 
1996
innobase_deinit(plugin::Registry &registry)
 
1997
{
 
1998
        int     err= 0;
 
1999
 
 
2000
        registry.remove(status_table_function_ptr);
 
2001
        delete status_table_function_ptr;
 
2002
 
 
2003
        registry.remove(cmp_tool);
 
2004
        delete cmp_tool;
 
2005
 
 
2006
        registry.remove(cmp_reset_tool);
 
2007
        delete cmp_reset_tool;
 
2008
 
 
2009
        registry.remove(cmp_mem_tool);
 
2010
        delete cmp_mem_tool;
 
2011
 
 
2012
        registry.remove(cmp_mem_reset_tool);
 
2013
        delete cmp_mem_reset_tool;
 
2014
 
 
2015
        registry.remove(innodb_trx_tool);
 
2016
        delete innodb_trx_tool;
 
2017
 
 
2018
        registry.remove(innodb_locks_tool);
 
2019
        delete innodb_locks_tool;
 
2020
 
 
2021
        registry.remove(innodb_lock_waits_tool);
 
2022
        delete innodb_lock_waits_tool;
 
2023
 
 
2024
        registry.remove(innodb_engine_ptr);
 
2025
        delete innodb_engine_ptr;
 
2026
 
 
2027
        if (innodb_inited) {
 
2028
 
 
2029
                srv_fast_shutdown = (ulint) innobase_fast_shutdown;
 
2030
                innodb_inited = 0;
 
2031
                hash_table_free(innobase_open_tables);
 
2032
                innobase_open_tables = NULL;
 
2033
                if (innobase_shutdown_for_mysql() != DB_SUCCESS) {
 
2034
                        err = 1;
 
2035
                }
 
2036
                srv_free_paths_and_sizes();
 
2037
                if (internal_innobase_data_file_path)
 
2038
                  free(internal_innobase_data_file_path);
 
2039
                pthread_mutex_destroy(&innobase_share_mutex);
 
2040
                pthread_mutex_destroy(&prepare_commit_mutex);
 
2041
                pthread_mutex_destroy(&commit_threads_m);
 
2042
                pthread_mutex_destroy(&commit_cond_m);
 
2043
                pthread_cond_destroy(&commit_cond);
 
2044
        }
 
2045
 
 
2046
        return(err);
 
2047
}
2367
2048
 
2368
2049
/****************************************************************//**
2369
2050
Flushes InnoDB logs to disk and makes a checkpoint. Really, a commit flushes
2370
2051
the logs, and the name of this function should be innobase_checkpoint.
2371
 
@return TRUE if error */
 
2052
@return TRUE if error */
2372
2053
bool
2373
2054
InnobaseEngine::flush_logs()
2374
2055
/*=====================*/
2375
2056
{
2376
 
  bool  result = 0;
2377
 
 
2378
 
  assert(this == innodb_engine_ptr);
2379
 
 
2380
 
  log_buffer_flush_to_disk();
2381
 
 
2382
 
  return(result);
 
2057
        bool    result = 0;
 
2058
 
 
2059
        assert(this == innodb_engine_ptr);
 
2060
 
 
2061
        log_buffer_flush_to_disk();
 
2062
 
 
2063
        return(result);
2383
2064
}
2384
2065
 
2385
2066
/*****************************************************************//**
2388
2069
void
2389
2070
innobase_commit_low(
2390
2071
/*================*/
2391
 
  trx_t*  trx)  /*!< in: transaction handle */
 
2072
        trx_t*  trx)    /*!< in: transaction handle */
2392
2073
{
2393
 
  if (trx->conc_state == TRX_NOT_STARTED) {
2394
 
 
2395
 
    return;
2396
 
  }
2397
 
 
2398
 
  trx_commit_for_mysql(trx);
 
2074
        if (trx->conc_state == TRX_NOT_STARTED) {
 
2075
 
 
2076
                return;
 
2077
        }
 
2078
 
 
2079
        trx_commit_for_mysql(trx);
2399
2080
}
2400
2081
 
2401
2082
/*****************************************************************//**
2403
2084
Starts a new InnoDB transaction if a transaction is not yet started. And
2404
2085
assigns a new snapshot for a consistent read if the transaction does not yet
2405
2086
have one.
2406
 
@return 0 */
 
2087
@return 0 */
2407
2088
int
2408
2089
InnobaseEngine::doStartTransaction(
2409
2090
/*====================================*/
2410
 
  Session*  session,  /*!< in: MySQL thread handle of the user for whom
2411
 
                               the transaction should be committed */
 
2091
        Session*        session,        /*!< in: MySQL thread handle of the user for whom
 
2092
                                                 the transaction should be committed */
2412
2093
  start_transaction_option_t options)
2413
2094
{
2414
 
  assert(this == innodb_engine_ptr);
2415
 
 
2416
 
  /* Create a new trx struct for session, if it does not yet have one */
2417
 
  trx_t *trx = check_trx_exists(session);
2418
 
 
2419
 
  /* This is just to play safe: release a possible FIFO ticket and
2420
 
  search latch. Since we will reserve the kernel mutex, we have to
2421
 
  release the search system latch first to obey the latching order. */
2422
 
  innobase_release_stat_resources(trx);
2423
 
 
2424
 
  /* If the transaction is not started yet, start it */
2425
 
  trx_start_if_not_started(trx);
2426
 
 
2427
 
  /* Assign a read view if the transaction does not have it yet */
 
2095
        assert(this == innodb_engine_ptr);
 
2096
 
 
2097
        /* Create a new trx struct for session, if it does not yet have one */
 
2098
        trx_t *trx = check_trx_exists(session);
 
2099
 
 
2100
        /* This is just to play safe: release a possible FIFO ticket and
 
2101
        search latch. Since we will reserve the kernel mutex, we have to
 
2102
        release the search system latch first to obey the latching order. */
 
2103
        innobase_release_stat_resources(trx);
 
2104
 
 
2105
        /* If the transaction is not started yet, start it */
 
2106
        trx_start_if_not_started(trx);
 
2107
 
 
2108
        /* Assign a read view if the transaction does not have it yet */
2428
2109
  if (options == START_TRANS_OPT_WITH_CONS_SNAPSHOT)
2429
 
    trx_assign_read_view(trx);
2430
 
 
2431
 
  return 0;
 
2110
          trx_assign_read_view(trx);
 
2111
 
 
2112
        /* Set the Drizzle flag to mark that there is an active transaction */
 
2113
        if (trx->active_trans == 0) {
 
2114
                trx->active_trans= 1;
 
2115
        }
 
2116
 
 
2117
        return 0;
2432
2118
}
2433
2119
 
2434
2120
/*****************************************************************//**
2435
2121
Commits a transaction in an InnoDB database or marks an SQL statement
2436
2122
ended.
2437
 
@return 0 */
 
2123
@return 0 */
2438
2124
int
2439
2125
InnobaseEngine::doCommit(
2440
2126
/*============*/
2441
 
  Session*  session,  /*!< in: MySQL thread handle of the user for whom
2442
 
      the transaction should be committed */
2443
 
  bool  all)  /*!< in:  TRUE - commit transaction
2444
 
        FALSE - the current SQL statement ended */
 
2127
        Session*        session,        /*!< in: MySQL thread handle of the user for whom
 
2128
                        the transaction should be committed */
 
2129
        bool    all)    /*!< in:        TRUE - commit transaction
 
2130
                                FALSE - the current SQL statement ended */
2445
2131
{
2446
 
  trx_t*    trx;
2447
 
 
2448
 
  assert(this == innodb_engine_ptr);
2449
 
 
2450
 
  trx = check_trx_exists(session);
2451
 
 
2452
 
  /* Since we will reserve the kernel mutex, we have to release
2453
 
  the search system latch first to obey the latching order. */
2454
 
 
2455
 
  if (trx->has_search_latch) {
2456
 
    trx_search_latch_release_if_reserved(trx);
2457
 
  }
2458
 
 
2459
 
  if (all
2460
 
    || (!session_test_options(session, OPTION_NOT_AUTOCOMMIT | OPTION_BEGIN))) {
2461
 
 
2462
 
    /* We were instructed to commit the whole transaction, or
2463
 
    this is an SQL statement end and autocommit is on */
2464
 
 
2465
 
    /* We need current binlog position for ibbackup to work.
2466
 
    Note, the position is current because of
2467
 
    prepare_commit_mutex */
 
2132
        trx_t*          trx;
 
2133
 
 
2134
        assert(this == innodb_engine_ptr);
 
2135
 
 
2136
        trx = check_trx_exists(session);
 
2137
 
 
2138
        /* Since we will reserve the kernel mutex, we have to release
 
2139
        the search system latch first to obey the latching order. */
 
2140
 
 
2141
        if (trx->has_search_latch) {
 
2142
                trx_search_latch_release_if_reserved(trx);
 
2143
        }
 
2144
 
 
2145
        /* The flag trx->active_trans is set to 1 in
 
2146
 
 
2147
        1. ::external_lock()
 
2148
  2  InnobaseEngine::doStartStatement()
 
2149
        3. InnobaseEngine::setSavepoint()
 
2150
        4. InnobaseEngine::doStartTransaction()
 
2151
 
 
2152
        and it is only set to 0 in a commit or a rollback. If it is 0 we know
 
2153
        there cannot be resources to be freed and we could return immediately.
 
2154
        For the time being, we play safe and do the cleanup though there should
 
2155
        be nothing to clean up. */
 
2156
 
 
2157
        if (trx->active_trans == 0
 
2158
                && trx->conc_state != TRX_NOT_STARTED) {
 
2159
 
 
2160
                errmsg_printf(ERRMSG_LVL_ERROR, "trx->active_trans == 0, but"
 
2161
                        " trx->conc_state != TRX_NOT_STARTED");
 
2162
        }
 
2163
        if (all
 
2164
                || (!session_test_options(session, OPTION_NOT_AUTOCOMMIT | OPTION_BEGIN))) {
 
2165
 
 
2166
                /* We were instructed to commit the whole transaction, or
 
2167
                this is an SQL statement end and autocommit is on */
 
2168
 
 
2169
                /* We need current binlog position for ibbackup to work.
 
2170
                Note, the position is current because of
 
2171
                prepare_commit_mutex */
2468
2172
retry:
2469
 
    if (innobase_commit_concurrency > 0) {
2470
 
      pthread_mutex_lock(&commit_cond_m);
2471
 
      commit_threads++;
 
2173
                if (innobase_commit_concurrency > 0) {
 
2174
                        pthread_mutex_lock(&commit_cond_m);
 
2175
                        commit_threads++;
2472
2176
 
2473
 
      if (commit_threads > innobase_commit_concurrency) {
2474
 
        commit_threads--;
2475
 
        pthread_cond_wait(&commit_cond,
2476
 
          &commit_cond_m);
2477
 
        pthread_mutex_unlock(&commit_cond_m);
2478
 
        goto retry;
2479
 
      }
2480
 
      else {
2481
 
        pthread_mutex_unlock(&commit_cond_m);
2482
 
      }
2483
 
    }
 
2177
                        if (commit_threads > innobase_commit_concurrency) {
 
2178
                                commit_threads--;
 
2179
                                pthread_cond_wait(&commit_cond,
 
2180
                                        &commit_cond_m);
 
2181
                                pthread_mutex_unlock(&commit_cond_m);
 
2182
                                goto retry;
 
2183
                        }
 
2184
                        else {
 
2185
                                pthread_mutex_unlock(&commit_cond_m);
 
2186
                        }
 
2187
                }
2484
2188
 
2485
2189
                /* Store transaction point for binlog
2486
 
    Later logic tests that this is set to _something_. We need
2487
 
    that logic to fire, even though we do not have a real name. */
2488
 
    trx->mysql_log_file_name = "UNUSED";
2489
 
    trx->mysql_log_offset = 0;
2490
 
 
2491
 
    /* Don't do write + flush right now. For group commit
2492
 
    to work we want to do the flush after releasing the
2493
 
    prepare_commit_mutex. */
2494
 
    trx->flush_log_later = TRUE;
2495
 
    innobase_commit_low(trx);
2496
 
    trx->flush_log_later = FALSE;
2497
 
 
2498
 
    if (innobase_commit_concurrency > 0) {
2499
 
      pthread_mutex_lock(&commit_cond_m);
2500
 
      commit_threads--;
2501
 
      pthread_cond_signal(&commit_cond);
2502
 
      pthread_mutex_unlock(&commit_cond_m);
2503
 
    }
2504
 
 
2505
 
    /* Now do a write + flush of logs. */
2506
 
    trx_commit_complete_for_mysql(trx);
2507
 
 
2508
 
  } else {
2509
 
    /* We just mark the SQL statement ended and do not do a
2510
 
    transaction commit */
2511
 
 
2512
 
    /* If we had reserved the auto-inc lock for some
2513
 
    table in this SQL statement we release it now */
2514
 
 
2515
 
    row_unlock_table_autoinc_for_mysql(trx);
2516
 
 
2517
 
    /* Store the current undo_no of the transaction so that we
2518
 
    know where to roll back if we have to roll back the next
2519
 
    SQL statement */
2520
 
 
2521
 
    trx_mark_sql_stat_end(trx);
2522
 
 
2523
 
    if (! session_test_options(session, OPTION_NOT_AUTOCOMMIT | OPTION_BEGIN))
2524
 
    {
2525
 
      if (trx->conc_state != TRX_NOT_STARTED)
2526
 
      {
2527
 
        commit(session, TRUE);
2528
 
      }
2529
 
    }
2530
 
  }
2531
 
 
2532
 
  trx->n_autoinc_rows = 0; /* Reset the number AUTO-INC rows required */
2533
 
 
2534
 
  if (trx->declared_to_be_inside_innodb) {
2535
 
    /* Release our possible ticket in the FIFO */
2536
 
 
2537
 
    srv_conc_force_exit_innodb(trx);
2538
 
  }
2539
 
 
2540
 
  /* Tell the InnoDB server that there might be work for utility
2541
 
  threads: */
2542
 
  srv_active_wake_master_thread();
2543
 
 
2544
 
  if (trx->isolation_level <= TRX_ISO_READ_COMMITTED &&
2545
 
      trx->global_read_view)
2546
 
  {
2547
 
    /* At low transaction isolation levels we let
2548
 
       each consistent read set its own snapshot */
2549
 
    read_view_close_for_mysql(trx);
2550
 
  }
2551
 
 
2552
 
  return(0);
 
2190
                Later logic tests that this is set to _something_. We need
 
2191
                that logic to fire, even though we do not have a real name. */
 
2192
                trx->mysql_log_file_name = "UNUSED";
 
2193
                trx->mysql_log_offset = 0;
 
2194
 
 
2195
                /* Don't do write + flush right now. For group commit
 
2196
                to work we want to do the flush after releasing the
 
2197
                prepare_commit_mutex. */
 
2198
                trx->flush_log_later = TRUE;
 
2199
                innobase_commit_low(trx);
 
2200
                trx->flush_log_later = FALSE;
 
2201
 
 
2202
                if (innobase_commit_concurrency > 0) {
 
2203
                        pthread_mutex_lock(&commit_cond_m);
 
2204
                        commit_threads--;
 
2205
                        pthread_cond_signal(&commit_cond);
 
2206
                        pthread_mutex_unlock(&commit_cond_m);
 
2207
                }
 
2208
 
 
2209
                if (trx->active_trans == 2) {
 
2210
 
 
2211
                        pthread_mutex_unlock(&prepare_commit_mutex);
 
2212
                }
 
2213
 
 
2214
                /* Now do a write + flush of logs. */
 
2215
                trx_commit_complete_for_mysql(trx);
 
2216
                trx->active_trans = 0;
 
2217
 
 
2218
        } else {
 
2219
                /* We just mark the SQL statement ended and do not do a
 
2220
                transaction commit */
 
2221
 
 
2222
                /* If we had reserved the auto-inc lock for some
 
2223
                table in this SQL statement we release it now */
 
2224
 
 
2225
                row_unlock_table_autoinc_for_mysql(trx);
 
2226
 
 
2227
                /* Store the current undo_no of the transaction so that we
 
2228
                know where to roll back if we have to roll back the next
 
2229
                SQL statement */
 
2230
 
 
2231
                trx_mark_sql_stat_end(trx);
 
2232
        }
 
2233
 
 
2234
        trx->n_autoinc_rows = 0; /* Reset the number AUTO-INC rows required */
 
2235
 
 
2236
        if (trx->declared_to_be_inside_innodb) {
 
2237
                /* Release our possible ticket in the FIFO */
 
2238
 
 
2239
                srv_conc_force_exit_innodb(trx);
 
2240
        }
 
2241
 
 
2242
        /* Tell the InnoDB server that there might be work for utility
 
2243
        threads: */
 
2244
        srv_active_wake_master_thread();
 
2245
 
 
2246
        return(0);
2553
2247
}
2554
2248
 
2555
2249
/*****************************************************************//**
2556
2250
Rolls back a transaction or the latest SQL statement.
2557
 
@return 0 or error number */
 
2251
@return 0 or error number */
2558
2252
int
2559
2253
InnobaseEngine::doRollback(
2560
2254
/*==============*/
2561
 
  Session*  session,/*!< in: handle to the MySQL thread of the user
2562
 
      whose transaction should be rolled back */
2563
 
  bool  all)  /*!< in:  TRUE - commit transaction
2564
 
        FALSE - the current SQL statement ended */
 
2255
        Session*        session,/*!< in: handle to the MySQL thread of the user
 
2256
                        whose transaction should be rolled back */
 
2257
        bool    all)    /*!< in:        TRUE - commit transaction
 
2258
                                FALSE - the current SQL statement ended */
2565
2259
{
2566
 
  int error = 0;
2567
 
  trx_t*  trx;
2568
 
 
2569
 
  assert(this == innodb_engine_ptr);
2570
 
 
2571
 
  trx = check_trx_exists(session);
2572
 
 
2573
 
  /* Release a possible FIFO ticket and search latch. Since we will
2574
 
  reserve the kernel mutex, we have to release the search system latch
2575
 
  first to obey the latching order. */
2576
 
 
2577
 
  innobase_release_stat_resources(trx);
2578
 
 
2579
 
  trx->n_autoinc_rows = 0;
2580
 
 
2581
 
  /* If we had reserved the auto-inc lock for some table (if
2582
 
  we come here to roll back the latest SQL statement) we
2583
 
  release it now before a possibly lengthy rollback */
2584
 
 
2585
 
  row_unlock_table_autoinc_for_mysql(trx);
2586
 
 
2587
 
  if (all
2588
 
    || !session_test_options(session, OPTION_NOT_AUTOCOMMIT | OPTION_BEGIN)) {
2589
 
 
2590
 
    error = trx_rollback_for_mysql(trx);
2591
 
  } else {
2592
 
    error = trx_rollback_last_sql_stat_for_mysql(trx);
2593
 
  }
2594
 
 
2595
 
  if (trx->isolation_level <= TRX_ISO_READ_COMMITTED &&
2596
 
      trx->global_read_view)
2597
 
  {
2598
 
    /* At low transaction isolation levels we let
2599
 
       each consistent read set its own snapshot */
2600
 
    read_view_close_for_mysql(trx);
2601
 
  }
2602
 
 
2603
 
  return(convert_error_code_to_mysql(error, 0, NULL));
 
2260
        int     error = 0;
 
2261
        trx_t*  trx;
 
2262
 
 
2263
        assert(this == innodb_engine_ptr);
 
2264
 
 
2265
        trx = check_trx_exists(session);
 
2266
 
 
2267
        /* Release a possible FIFO ticket and search latch. Since we will
 
2268
        reserve the kernel mutex, we have to release the search system latch
 
2269
        first to obey the latching order. */
 
2270
 
 
2271
        innobase_release_stat_resources(trx);
 
2272
 
 
2273
        /* If we had reserved the auto-inc lock for some table (if
 
2274
        we come here to roll back the latest SQL statement) we
 
2275
        release it now before a possibly lengthy rollback */
 
2276
 
 
2277
        row_unlock_table_autoinc_for_mysql(trx);
 
2278
 
 
2279
        if (all
 
2280
                || !session_test_options(session, OPTION_NOT_AUTOCOMMIT | OPTION_BEGIN)) {
 
2281
 
 
2282
                error = trx_rollback_for_mysql(trx);
 
2283
                trx->active_trans = 0;
 
2284
        } else {
 
2285
                error = trx_rollback_last_sql_stat_for_mysql(trx);
 
2286
        }
 
2287
 
 
2288
        return(convert_error_code_to_mysql(error, 0, NULL));
2604
2289
}
2605
2290
 
2606
2291
/*****************************************************************//**
2607
2292
Rolls back a transaction
2608
 
@return 0 or error number */
 
2293
@return 0 or error number */
2609
2294
static
2610
2295
int
2611
2296
innobase_rollback_trx(
2612
2297
/*==================*/
2613
 
  trx_t*  trx)  /*!< in: transaction */
 
2298
        trx_t*  trx)    /*!< in: transaction */
2614
2299
{
2615
 
  int error = 0;
2616
 
 
2617
 
  /* Release a possible FIFO ticket and search latch. Since we will
2618
 
  reserve the kernel mutex, we have to release the search system latch
2619
 
  first to obey the latching order. */
2620
 
 
2621
 
  innobase_release_stat_resources(trx);
2622
 
 
2623
 
  /* If we had reserved the auto-inc lock for some table (if
2624
 
  we come here to roll back the latest SQL statement) we
2625
 
  release it now before a possibly lengthy rollback */
2626
 
 
2627
 
  row_unlock_table_autoinc_for_mysql(trx);
2628
 
 
2629
 
  error = trx_rollback_for_mysql(trx);
2630
 
 
2631
 
  return(convert_error_code_to_mysql(error, 0, NULL));
 
2300
        int     error = 0;
 
2301
 
 
2302
        /* Release a possible FIFO ticket and search latch. Since we will
 
2303
        reserve the kernel mutex, we have to release the search system latch
 
2304
        first to obey the latching order. */
 
2305
 
 
2306
        innobase_release_stat_resources(trx);
 
2307
 
 
2308
        /* If we had reserved the auto-inc lock for some table (if
 
2309
        we come here to roll back the latest SQL statement) we
 
2310
        release it now before a possibly lengthy rollback */
 
2311
 
 
2312
        row_unlock_table_autoinc_for_mysql(trx);
 
2313
 
 
2314
        error = trx_rollback_for_mysql(trx);
 
2315
 
 
2316
        return(convert_error_code_to_mysql(error, 0, NULL));
2632
2317
}
2633
2318
 
2634
2319
/*****************************************************************//**
2638
2323
int
2639
2324
InnobaseEngine::doRollbackToSavepoint(
2640
2325
/*===========================*/
2641
 
  Session*  session,    /*!< in: handle to the MySQL thread of the user
2642
 
        whose transaction should be rolled back */
2643
 
  drizzled::NamedSavepoint &named_savepoint)  /*!< in: savepoint data */
 
2326
        Session*        session,                /*!< in: handle to the MySQL thread of the user
 
2327
                                whose transaction should be rolled back */
 
2328
        drizzled::NamedSavepoint &named_savepoint)      /*!< in: savepoint data */
2644
2329
{
2645
 
  ib_int64_t  mysql_binlog_cache_pos;
2646
 
  int   error = 0;
2647
 
  trx_t*    trx;
2648
 
 
2649
 
  assert(this == innodb_engine_ptr);
2650
 
 
2651
 
  trx = check_trx_exists(session);
2652
 
 
2653
 
  /* Release a possible FIFO ticket and search latch. Since we will
2654
 
  reserve the kernel mutex, we have to release the search system latch
2655
 
  first to obey the latching order. */
2656
 
 
2657
 
  innobase_release_stat_resources(trx);
2658
 
 
2659
 
  error= (int)trx_rollback_to_savepoint_for_mysql(trx, named_savepoint.getName().c_str(),
 
2330
        ib_int64_t      mysql_binlog_cache_pos;
 
2331
        int             error = 0;
 
2332
        trx_t*          trx;
 
2333
 
 
2334
        assert(this == innodb_engine_ptr);
 
2335
 
 
2336
        trx = check_trx_exists(session);
 
2337
 
 
2338
        /* Release a possible FIFO ticket and search latch. Since we will
 
2339
        reserve the kernel mutex, we have to release the search system latch
 
2340
        first to obey the latching order. */
 
2341
 
 
2342
        innobase_release_stat_resources(trx);
 
2343
 
 
2344
        /* TODO: use provided savepoint data area to store savepoint data */
 
2345
        error= (int)trx_rollback_to_savepoint_for_mysql(trx, named_savepoint.getName().c_str(),
2660
2346
                                                        &mysql_binlog_cache_pos);
2661
 
  return(convert_error_code_to_mysql(error, 0, NULL));
 
2347
        return(convert_error_code_to_mysql(error, 0, NULL));
2662
2348
}
2663
2349
 
2664
2350
/*****************************************************************//**
2668
2354
int
2669
2355
InnobaseEngine::doReleaseSavepoint(
2670
2356
/*=======================*/
2671
 
  Session*  session,    /*!< in: handle to the MySQL thread of the user
2672
 
        whose transaction should be rolled back */
2673
 
  drizzled::NamedSavepoint &named_savepoint)  /*!< in: savepoint data */
 
2357
        Session*        session,                /*!< in: handle to the MySQL thread of the user
 
2358
                                whose transaction should be rolled back */
 
2359
        drizzled::NamedSavepoint &named_savepoint)      /*!< in: savepoint data */
2674
2360
{
2675
 
  int   error = 0;
2676
 
  trx_t*    trx;
2677
 
 
2678
 
  assert(this == innodb_engine_ptr);
2679
 
 
2680
 
  trx = check_trx_exists(session);
2681
 
 
2682
 
  error = (int) trx_release_savepoint_for_mysql(trx, named_savepoint.getName().c_str());
2683
 
 
2684
 
  return(convert_error_code_to_mysql(error, 0, NULL));
 
2361
        int             error = 0;
 
2362
        trx_t*          trx;
 
2363
 
 
2364
        assert(this == innodb_engine_ptr);
 
2365
 
 
2366
        trx = check_trx_exists(session);
 
2367
 
 
2368
        /* TODO: use provided savepoint data area to store savepoint data */
 
2369
        error = (int) trx_release_savepoint_for_mysql(trx, named_savepoint.getName().c_str());
 
2370
 
 
2371
        return(convert_error_code_to_mysql(error, 0, NULL));
2685
2372
}
2686
2373
 
2687
2374
/*****************************************************************//**
2688
2375
Sets a transaction savepoint.
2689
 
@return always 0, that is, always succeeds */
 
2376
@return always 0, that is, always succeeds */
2690
2377
int
2691
2378
InnobaseEngine::doSetSavepoint(
2692
2379
/*===============*/
2693
 
  Session*  session,/*!< in: handle to the MySQL thread */
2694
 
  drizzled::NamedSavepoint &named_savepoint)  /*!< in: savepoint data */
 
2380
        Session*        session,/*!< in: handle to the MySQL thread */
 
2381
        drizzled::NamedSavepoint &named_savepoint)      /*!< in: savepoint data */
2695
2382
{
2696
 
  int error = 0;
2697
 
  trx_t*  trx;
2698
 
 
2699
 
  assert(this == innodb_engine_ptr);
2700
 
 
2701
 
  /*
2702
 
    In the autocommit mode there is no sense to set a savepoint
2703
 
    (unless we are in sub-statement), so SQL layer ensures that
2704
 
    this method is never called in such situation.
2705
 
  */
2706
 
 
2707
 
  trx = check_trx_exists(session);
2708
 
 
2709
 
  /* Release a possible FIFO ticket and search latch. Since we will
2710
 
  reserve the kernel mutex, we have to release the search system latch
2711
 
  first to obey the latching order. */
2712
 
 
2713
 
  innobase_release_stat_resources(trx);
2714
 
 
2715
 
  /* cannot happen outside of transaction */
2716
 
  assert(trx->conc_state != TRX_NOT_STARTED);
2717
 
 
2718
 
  error = (int) trx_savepoint_for_mysql(trx, named_savepoint.getName().c_str(), (ib_int64_t)0);
2719
 
 
2720
 
  return(convert_error_code_to_mysql(error, 0, NULL));
 
2383
        int     error = 0;
 
2384
        trx_t*  trx;
 
2385
 
 
2386
        assert(this == innodb_engine_ptr);
 
2387
 
 
2388
        /*
 
2389
          In the autocommit mode there is no sense to set a savepoint
 
2390
          (unless we are in sub-statement), so SQL layer ensures that
 
2391
          this method is never called in such situation.
 
2392
        */
 
2393
 
 
2394
        trx = check_trx_exists(session);
 
2395
 
 
2396
        /* Release a possible FIFO ticket and search latch. Since we will
 
2397
        reserve the kernel mutex, we have to release the search system latch
 
2398
        first to obey the latching order. */
 
2399
 
 
2400
        innobase_release_stat_resources(trx);
 
2401
 
 
2402
        /* cannot happen outside of transaction */
 
2403
        assert(trx->active_trans);
 
2404
 
 
2405
        /* TODO: use provided savepoint data area to store savepoint data */
 
2406
        error = (int) trx_savepoint_for_mysql(trx, named_savepoint.getName().c_str(), (ib_int64_t)0);
 
2407
 
 
2408
        return(convert_error_code_to_mysql(error, 0, NULL));
2721
2409
}
2722
2410
 
2723
2411
/*****************************************************************//**
2724
2412
Frees a possible InnoDB trx object associated with the current Session.
2725
 
@return 0 or error number */
 
2413
@return 0 or error number */
2726
2414
int
2727
2415
InnobaseEngine::close_connection(
2728
2416
/*======================*/
2729
 
  Session*  session)/*!< in: handle to the MySQL thread of the user
2730
 
      whose resources should be free'd */
 
2417
        Session*        session)/*!< in: handle to the MySQL thread of the user
 
2418
                        whose resources should be free'd */
2731
2419
{
2732
 
  trx_t*  trx;
2733
 
 
2734
 
  assert(this == innodb_engine_ptr);
2735
 
  trx = session_to_trx(session);
2736
 
 
2737
 
  ut_a(trx);
2738
 
 
2739
 
  assert(session->getKilled() != Session::NOT_KILLED ||
2740
 
         trx->conc_state == TRX_NOT_STARTED);
2741
 
 
2742
 
  /* Warn if rolling back some things... */
2743
 
  if (session->getKilled() != Session::NOT_KILLED &&
2744
 
      trx->conc_state != TRX_NOT_STARTED &&
2745
 
      trx->undo_no.low > 0 &&
2746
 
      global_system_variables.log_warnings)
2747
 
  {
2748
 
      errmsg_printf(ERRMSG_LVL_WARN, 
2749
 
      "Drizzle is closing a connection during a KILL operation\n"
2750
 
      "that has an active InnoDB transaction.  %lu row modifications will "
2751
 
      "roll back.\n",
2752
 
      (ulong) trx->undo_no.low);
2753
 
  }
2754
 
 
2755
 
  innobase_rollback_trx(trx);
2756
 
 
2757
 
  thr_local_free(trx->mysql_thread_id);
2758
 
  trx_free_for_mysql(trx);
2759
 
 
2760
 
  return(0);
 
2420
        trx_t*  trx;
 
2421
 
 
2422
        assert(this == innodb_engine_ptr);
 
2423
        trx = session_to_trx(session);
 
2424
 
 
2425
        ut_a(trx);
 
2426
 
 
2427
        if (trx->active_trans == 0
 
2428
                && trx->conc_state != TRX_NOT_STARTED) {
 
2429
 
 
2430
                errmsg_printf(ERRMSG_LVL_ERROR, "trx->active_trans == 0, but"
 
2431
                        " trx->conc_state != TRX_NOT_STARTED");
 
2432
        }
 
2433
 
 
2434
 
 
2435
        if (trx->conc_state != TRX_NOT_STARTED &&
 
2436
                global_system_variables.log_warnings) {
 
2437
                errmsg_printf(ERRMSG_LVL_WARN, 
 
2438
                        "MySQL is closing a connection that has an active "
 
2439
                        "InnoDB transaction.  %lu row modifications will "
 
2440
                        "roll back.",
 
2441
                        (ulong) trx->undo_no.low);
 
2442
        }
 
2443
 
 
2444
        innobase_rollback_trx(trx);
 
2445
 
 
2446
        thr_local_free(trx->mysql_thread_id);
 
2447
        trx_free_for_mysql(trx);
 
2448
 
 
2449
        return(0);
2761
2450
}
2762
2451
 
2763
2452
 
2766
2455
*****************************************************************************/
2767
2456
 
2768
2457
/****************************************************************//**
 
2458
Get the record format from the data dictionary.
 
2459
@return one of ROW_TYPE_REDUNDANT, ROW_TYPE_COMPACT,
 
2460
ROW_TYPE_COMPRESSED, ROW_TYPE_DYNAMIC */
 
2461
UNIV_INTERN
 
2462
enum row_type
 
2463
ha_innobase::get_row_type() const
 
2464
/*=============================*/
 
2465
{
 
2466
        if (prebuilt && prebuilt->table) {
 
2467
                const ulint     flags = prebuilt->table->flags;
 
2468
 
 
2469
                if (UNIV_UNLIKELY(!flags)) {
 
2470
                        return(ROW_TYPE_REDUNDANT);
 
2471
                }
 
2472
 
 
2473
                ut_ad(flags & DICT_TF_COMPACT);
 
2474
 
 
2475
                switch (flags & DICT_TF_FORMAT_MASK) {
 
2476
                case DICT_TF_FORMAT_51 << DICT_TF_FORMAT_SHIFT:
 
2477
                        return(ROW_TYPE_COMPACT);
 
2478
                case DICT_TF_FORMAT_ZIP << DICT_TF_FORMAT_SHIFT:
 
2479
                        if (flags & DICT_TF_ZSSIZE_MASK) {
 
2480
                                return(ROW_TYPE_COMPRESSED);
 
2481
                        } else {
 
2482
                                return(ROW_TYPE_DYNAMIC);
 
2483
                        }
 
2484
#if DICT_TF_FORMAT_ZIP != DICT_TF_FORMAT_MAX
 
2485
# error "DICT_TF_FORMAT_ZIP != DICT_TF_FORMAT_MAX"
 
2486
#endif
 
2487
                }
 
2488
        }
 
2489
        ut_ad(0);
 
2490
        return(ROW_TYPE_NOT_USED);
 
2491
}
 
2492
 
 
2493
 
 
2494
/****************************************************************//**
2769
2495
Returns the index type. */
2770
2496
UNIV_INTERN
2771
2497
const char*
2772
2498
ha_innobase::index_type(
2773
2499
/*====================*/
2774
 
  uint)
2775
 
        /*!< out: index type */
 
2500
        uint)
 
2501
                                /*!< out: index type */
2776
2502
{
2777
 
  return("BTREE");
 
2503
        return("BTREE");
2778
2504
}
2779
2505
 
2780
2506
/****************************************************************//**
2781
2507
Returns the maximum number of keys.
2782
 
@return MAX_KEY */
 
2508
@return MAX_KEY */
2783
2509
UNIV_INTERN
2784
2510
uint
2785
2511
InnobaseEngine::max_supported_keys() const
2786
2512
/*===================================*/
2787
2513
{
2788
 
  return(MAX_KEY);
 
2514
        return(MAX_KEY);
2789
2515
}
2790
2516
 
2791
2517
/****************************************************************//**
2792
2518
Returns the maximum key length.
2793
 
@return maximum supported key length, in bytes */
 
2519
@return maximum supported key length, in bytes */
2794
2520
UNIV_INTERN
2795
2521
uint32_t
2796
2522
InnobaseEngine::max_supported_key_length() const
2797
2523
/*=========================================*/
2798
2524
{
2799
 
  /* An InnoDB page must store >= 2 keys; a secondary key record
2800
 
  must also contain the primary key value: max key length is
2801
 
  therefore set to slightly less than 1 / 4 of page size which
2802
 
  is 16 kB; but currently MySQL does not work with keys whose
2803
 
  size is > MAX_KEY_LENGTH */
2804
 
  return(3500);
 
2525
        /* An InnoDB page must store >= 2 keys; a secondary key record
 
2526
        must also contain the primary key value: max key length is
 
2527
        therefore set to slightly less than 1 / 4 of page size which
 
2528
        is 16 kB; but currently MySQL does not work with keys whose
 
2529
        size is > MAX_KEY_LENGTH */
 
2530
        return(3500);
2805
2531
}
2806
2532
 
2807
2533
/****************************************************************//**
2808
2534
Returns the key map of keys that are usable for scanning.
2809
 
@return key_map_full */
 
2535
@return key_map_full */
2810
2536
UNIV_INTERN
2811
2537
const key_map*
2812
2538
ha_innobase::keys_to_use_for_scanning()
2813
2539
{
2814
 
  return(&key_map_full);
 
2540
        return(&key_map_full);
2815
2541
}
2816
2542
 
2817
2543
 
2818
2544
/****************************************************************//**
2819
2545
Determines if the primary key is clustered index.
2820
 
@return true */
 
2546
@return true */
2821
2547
UNIV_INTERN
2822
2548
bool
2823
2549
ha_innobase::primary_key_is_clustered()
2824
2550
{
2825
 
  return(true);
 
2551
        return(true);
2826
2552
}
2827
2553
 
2828
2554
/*****************************************************************//**
2834
2560
void
2835
2561
normalize_table_name(
2836
2562
/*=================*/
2837
 
  char*   norm_name,  /*!< out: normalized name as a
2838
 
          null-terminated string */
2839
 
  const char* name)   /*!< in: table name string */
 
2563
        char*           norm_name,      /*!< out: normalized name as a
 
2564
                                        null-terminated string */
 
2565
        const char*     name)           /*!< in: table name string */
2840
2566
{
2841
 
  const char* name_ptr;
2842
 
  const char* db_ptr;
2843
 
  const char* ptr;
2844
 
 
2845
 
  /* Scan name from the end */
2846
 
 
2847
 
  ptr = strchr(name, '\0')-1;
2848
 
 
2849
 
  while (ptr >= name && *ptr != '\\' && *ptr != '/') {
2850
 
    ptr--;
2851
 
  }
2852
 
 
2853
 
  name_ptr = ptr + 1;
2854
 
 
2855
 
  assert(ptr > name);
2856
 
 
2857
 
  ptr--;
2858
 
 
2859
 
  while (ptr >= name && *ptr != '\\' && *ptr != '/') {
2860
 
    ptr--;
2861
 
  }
2862
 
 
2863
 
  db_ptr = ptr + 1;
2864
 
 
2865
 
  memcpy(norm_name, db_ptr, strlen(name) + 1 - (db_ptr - name));
2866
 
 
2867
 
  norm_name[name_ptr - db_ptr - 1] = '/';
 
2567
        const char*     name_ptr;
 
2568
        const char*     db_ptr;
 
2569
        const char*     ptr;
 
2570
 
 
2571
        /* Scan name from the end */
 
2572
 
 
2573
        ptr = strchr(name, '\0')-1;
 
2574
 
 
2575
        while (ptr >= name && *ptr != '\\' && *ptr != '/') {
 
2576
                ptr--;
 
2577
        }
 
2578
 
 
2579
        name_ptr = ptr + 1;
 
2580
 
 
2581
        assert(ptr > name);
 
2582
 
 
2583
        ptr--;
 
2584
 
 
2585
        while (ptr >= name && *ptr != '\\' && *ptr != '/') {
 
2586
                ptr--;
 
2587
        }
 
2588
 
 
2589
        db_ptr = ptr + 1;
 
2590
 
 
2591
        memcpy(norm_name, db_ptr, strlen(name) + 1 - (db_ptr - name));
 
2592
 
 
2593
        norm_name[name_ptr - db_ptr - 1] = '/';
2868
2594
 
2869
2595
#ifdef __WIN__
2870
 
  innobase_casedn_str(norm_name);
 
2596
        innobase_casedn_str(norm_name);
2871
2597
#endif
2872
2598
}
2873
2599
 
2874
2600
/********************************************************************//**
2875
 
Get the upper limit of the MySQL integral and floating-point type.
2876
 
@return maximum allowed value for the field */
2877
 
static
2878
 
uint64_t
2879
 
innobase_get_int_col_max_value(
2880
 
/*===========================*/
2881
 
        const Field*    field)  /*!< in: MySQL field */
2882
 
{
2883
 
        uint64_t        max_value = 0;
2884
 
 
2885
 
        switch(field->key_type()) {
2886
 
        /* TINY */
2887
 
        case HA_KEYTYPE_BINARY:
2888
 
                max_value = 0xFFULL;
2889
 
                break;
2890
 
        /* LONG */
2891
 
        case HA_KEYTYPE_ULONG_INT:
2892
 
                max_value = 0xFFFFFFFFULL;
2893
 
                break;
2894
 
        case HA_KEYTYPE_LONG_INT:
2895
 
                max_value = 0x7FFFFFFFULL;
2896
 
                break;
2897
 
        /* BIG */
2898
 
        case HA_KEYTYPE_ULONGLONG:
2899
 
                max_value = 0xFFFFFFFFFFFFFFFFULL;
2900
 
                break;
2901
 
        case HA_KEYTYPE_LONGLONG:
2902
 
                max_value = 0x7FFFFFFFFFFFFFFFULL;
2903
 
                break;
2904
 
        case HA_KEYTYPE_DOUBLE:
2905
 
                /* We use the maximum as per IEEE754-2008 standard, 2^53 */
2906
 
                max_value = 0x20000000000000ULL;
2907
 
                break;
2908
 
        default:
2909
 
                ut_error;
2910
 
        }
2911
 
 
2912
 
        return(max_value);
2913
 
}
2914
 
 
2915
 
/*******************************************************************//**
2916
 
This function checks whether the index column information
2917
 
is consistent between KEY info from mysql and that from innodb index.
2918
 
@return TRUE if all column types match. */
2919
 
static
2920
 
ibool
2921
 
innobase_match_index_columns(
2922
 
/*=========================*/
2923
 
        const KeyInfo*          key_info,       /*!< in: Index info
2924
 
                                                from mysql */
2925
 
        const dict_index_t*     index_info)     /*!< in: Index info
2926
 
                                                from Innodb */
2927
 
{
2928
 
        const KeyPartInfo*      key_part;
2929
 
        const KeyPartInfo*      key_end;
2930
 
        const dict_field_t*     innodb_idx_fld;
2931
 
        const dict_field_t*     innodb_idx_fld_end;
2932
 
 
2933
 
        /* Check whether user defined index column count matches */
2934
 
        if (key_info->key_parts != index_info->n_user_defined_cols) {
2935
 
                return(FALSE);
2936
 
        }
2937
 
 
2938
 
        key_part = key_info->key_part;
2939
 
        key_end = key_part + key_info->key_parts;
2940
 
        innodb_idx_fld = index_info->fields;
2941
 
        innodb_idx_fld_end = index_info->fields + index_info->n_fields;
2942
 
 
2943
 
        /* Check each index column's datatype. We do not check
2944
 
        column name because there exists case that index
2945
 
        column name got modified in mysql but such change does not
2946
 
        propagate to InnoDB.
2947
 
        One hidden assumption here is that the index column sequences
2948
 
        are matched up between those in mysql and Innodb. */
2949
 
        for (; key_part != key_end; ++key_part) {
2950
 
                ulint   col_type;
2951
 
                ibool   is_unsigned;
2952
 
                ulint   mtype = innodb_idx_fld->col->mtype;
2953
 
 
2954
 
                /* Need to translate to InnoDB column type before
2955
 
                comparison. */
2956
 
                col_type = get_innobase_type_from_mysql_type(&is_unsigned,
2957
 
                                                             key_part->field);
2958
 
 
2959
 
                /* Ignore Innodb specific system columns. */
2960
 
                while (mtype == DATA_SYS) {
2961
 
                        innodb_idx_fld++;
2962
 
 
2963
 
                        if (innodb_idx_fld >= innodb_idx_fld_end) {
2964
 
                                return(FALSE);
2965
 
                        }
2966
 
                }
2967
 
 
2968
 
                if (col_type != mtype) {
2969
 
                        /* Column Type mismatches */
2970
 
                        return(FALSE);
2971
 
                }
2972
 
 
2973
 
                innodb_idx_fld++;
2974
 
        }
2975
 
 
2976
 
        return(TRUE);
2977
 
}
2978
 
 
2979
 
/*******************************************************************//**
2980
 
This function builds a translation table in INNOBASE_SHARE
2981
 
structure for fast index location with mysql array number from its
2982
 
table->key_info structure. This also provides the necessary translation
2983
 
between the key order in mysql key_info and Innodb ib_table->indexes if
2984
 
they are not fully matched with each other.
2985
 
Note we do not have any mutex protecting the translation table
2986
 
building based on the assumption that there is no concurrent
2987
 
index creation/drop and DMLs that requires index lookup. All table
2988
 
handle will be closed before the index creation/drop.
2989
 
@return TRUE if index translation table built successfully */
2990
 
static
2991
 
ibool
2992
 
innobase_build_index_translation(
2993
 
/*=============================*/
2994
 
        const Table*            table,    /*!< in: table in MySQL data
2995
 
                                          dictionary */
2996
 
        dict_table_t*           ib_table, /*!< in: table in Innodb data
2997
 
                                          dictionary */
2998
 
        INNOBASE_SHARE*         share)    /*!< in/out: share structure
2999
 
                                          where index translation table
3000
 
                                          will be constructed in. */
3001
 
{
3002
 
        ulint           mysql_num_index;
3003
 
        ulint           ib_num_index;
3004
 
        dict_index_t**  index_mapping;
3005
 
        ibool           ret = TRUE;
3006
 
 
3007
 
        mysql_num_index = table->getShare()->keys;
3008
 
        ib_num_index = UT_LIST_GET_LEN(ib_table->indexes);
3009
 
 
3010
 
        index_mapping = share->idx_trans_tbl.index_mapping;
3011
 
 
3012
 
        /* If there exists inconsistency between MySQL and InnoDB dictionary
3013
 
        (metadata) information, the number of index defined in MySQL
3014
 
        could exceed that in InnoDB, do not build index translation
3015
 
        table in such case */
3016
 
        if (UNIV_UNLIKELY(ib_num_index < mysql_num_index)) {
3017
 
                ret = FALSE;
3018
 
                goto func_exit;
3019
 
        }
3020
 
 
3021
 
        /* If index entry count is non-zero, nothing has
3022
 
        changed since last update, directly return TRUE */
3023
 
        if (share->idx_trans_tbl.index_count) {
3024
 
                /* Index entry count should still match mysql_num_index */
3025
 
                ut_a(share->idx_trans_tbl.index_count == mysql_num_index);
3026
 
                goto func_exit;
3027
 
        }
3028
 
 
3029
 
        /* The number of index increased, rebuild the mapping table */
3030
 
        if (mysql_num_index > share->idx_trans_tbl.array_size) {
3031
 
                index_mapping = (dict_index_t**) realloc(index_mapping,
3032
 
                                                        mysql_num_index *
3033
 
                                                         sizeof(*index_mapping));
3034
 
 
3035
 
                if (!index_mapping) {
3036
 
                        ret = FALSE;
3037
 
                        goto func_exit;
3038
 
                }
3039
 
 
3040
 
                share->idx_trans_tbl.array_size = mysql_num_index;
3041
 
        }
3042
 
 
3043
 
 
3044
 
        /* For each index in the mysql key_info array, fetch its
3045
 
        corresponding InnoDB index pointer into index_mapping
3046
 
        array. */
3047
 
        for (ulint count = 0; count < mysql_num_index; count++) {
3048
 
 
3049
 
                /* Fetch index pointers into index_mapping according to mysql
3050
 
                index sequence */
3051
 
                index_mapping[count] = dict_table_get_index_on_name(
3052
 
                        ib_table, table->key_info[count].name);
3053
 
 
3054
 
                if (!index_mapping[count]) {
3055
 
                        errmsg_printf(ERRMSG_LVL_ERROR, "Cannot find index %s in InnoDB "
3056
 
                                        "index dictionary.",
3057
 
                                        table->key_info[count].name);
3058
 
                        ret = FALSE;
3059
 
                        goto func_exit;
3060
 
                }
3061
 
 
3062
 
                /* Double check fetched index has the same
3063
 
                column info as those in mysql key_info. */
3064
 
                if (!innobase_match_index_columns(&table->key_info[count],
3065
 
                                                  index_mapping[count])) {
3066
 
                        errmsg_printf(ERRMSG_LVL_ERROR, "Found index %s whose column info "
3067
 
                                        "does not match that of MySQL.",
3068
 
                                        table->key_info[count].name);
3069
 
                        ret = FALSE;
3070
 
                        goto func_exit;
3071
 
                }
3072
 
        }
3073
 
 
3074
 
        /* Successfully built the translation table */
3075
 
        share->idx_trans_tbl.index_count = mysql_num_index;
3076
 
 
3077
 
func_exit:
3078
 
        if (!ret) {
3079
 
                /* Build translation table failed. */
3080
 
                free(index_mapping);
3081
 
 
3082
 
                share->idx_trans_tbl.array_size = 0;
3083
 
                share->idx_trans_tbl.index_count = 0;
3084
 
                index_mapping = NULL;
3085
 
        }
3086
 
 
3087
 
        share->idx_trans_tbl.index_mapping = index_mapping;
3088
 
 
3089
 
        return(ret);
3090
 
}
3091
 
 
3092
 
/*******************************************************************//**
3093
 
This function uses index translation table to quickly locate the
3094
 
requested index structure.
3095
 
Note we do not have mutex protection for the index translatoin table
3096
 
access, it is based on the assumption that there is no concurrent
3097
 
translation table rebuild (fter create/drop index) and DMLs that
3098
 
require index lookup.
3099
 
@return dict_index_t structure for requested index. NULL if
3100
 
fail to locate the index structure. */
3101
 
static
3102
 
dict_index_t*
3103
 
innobase_index_lookup(
3104
 
/*==================*/
3105
 
        INNOBASE_SHARE* share,  /*!< in: share structure for index
3106
 
                                translation table. */
3107
 
        uint            keynr)  /*!< in: index number for the requested
3108
 
                                index */
3109
 
{
3110
 
        if (!share->idx_trans_tbl.index_mapping
3111
 
            || keynr >= share->idx_trans_tbl.index_count) {
3112
 
                return(NULL);
3113
 
        }
3114
 
 
3115
 
        return(share->idx_trans_tbl.index_mapping[keynr]);
3116
 
}
3117
 
 
3118
 
/********************************************************************//**
3119
2601
Set the autoinc column max value. This should only be called once from
3120
 
ha_innobase::open(). Therefore there's no need for a covering lock. */
 
2602
ha_innobase::open(). Therefore there's no need for a covering lock.
 
2603
@return DB_SUCCESS or error code */
3121
2604
UNIV_INTERN
3122
 
void
 
2605
ulint
3123
2606
ha_innobase::innobase_initialize_autoinc()
3124
2607
/*======================================*/
3125
2608
{
3126
 
  uint64_t  auto_inc;
3127
 
  const Field*  field = getTable()->found_next_number_field;
3128
 
 
3129
 
  if (field != NULL) {
3130
 
    auto_inc = innobase_get_int_col_max_value(field);
3131
 
  } else {
3132
 
    /* We have no idea what's been passed in to us as the
3133
 
       autoinc column. We set it to the 0, effectively disabling
3134
 
       updates to the table. */
3135
 
    auto_inc = 0;
3136
 
 
3137
 
    ut_print_timestamp(stderr);
3138
 
    fprintf(stderr, "  InnoDB: Unable to determine the AUTOINC "
3139
 
            "column name\n");
3140
 
  }
3141
 
 
3142
 
  if (srv_force_recovery >= SRV_FORCE_NO_IBUF_MERGE) {
3143
 
    /* If the recovery level is set so high that writes
3144
 
       are disabled we force the AUTOINC counter to 0
3145
 
       value effectively disabling writes to the table.
3146
 
       Secondly, we avoid reading the table in case the read
3147
 
       results in failure due to a corrupted table/index.
3148
 
 
3149
 
       We will not return an error to the client, so that the
3150
 
       tables can be dumped with minimal hassle.  If an error
3151
 
       were returned in this case, the first attempt to read
3152
 
       the table would fail and subsequent SELECTs would succeed. */
3153
 
    auto_inc = 0;
3154
 
  } else if (field == NULL) {
3155
 
    /* This is a far more serious error, best to avoid
3156
 
       opening the table and return failure. */
3157
 
    my_error(ER_AUTOINC_READ_FAILED, MYF(0));
3158
 
  } else {
3159
 
    dict_index_t*       index;
3160
 
    const char* col_name;
3161
 
    uint64_t    read_auto_inc;
3162
 
    ulint               err;
3163
 
 
3164
 
    update_session(getTable()->in_use);
3165
 
    col_name = field->field_name;
3166
 
 
3167
 
    ut_a(prebuilt->trx == session_to_trx(user_session));
3168
 
 
3169
 
    index = innobase_get_index(getTable()->getShare()->next_number_index);
3170
 
 
3171
 
    /* Execute SELECT MAX(col_name) FROM TABLE; */
3172
 
    err = row_search_max_autoinc(index, col_name, &read_auto_inc);
3173
 
 
3174
 
    switch (err) {
3175
 
    case DB_SUCCESS:
3176
 
      /* At the this stage we do not know the increment
3177
 
         or the offset, so use a default increment of 1. */
3178
 
      auto_inc = read_auto_inc + 1;
3179
 
      break;
3180
 
 
3181
 
    case DB_RECORD_NOT_FOUND:
3182
 
      ut_print_timestamp(stderr);
3183
 
      fprintf(stderr, "  InnoDB: MySQL and InnoDB data "
3184
 
              "dictionaries are out of sync.\n"
3185
 
              "InnoDB: Unable to find the AUTOINC column "
3186
 
              "%s in the InnoDB table %s.\n"
3187
 
              "InnoDB: We set the next AUTOINC column "
3188
 
              "value to 0,\n"
3189
 
              "InnoDB: in effect disabling the AUTOINC "
3190
 
              "next value generation.\n"
3191
 
              "InnoDB: You can either set the next "
3192
 
              "AUTOINC value explicitly using ALTER TABLE\n"
3193
 
              "InnoDB: or fix the data dictionary by "
3194
 
              "recreating the table.\n",
3195
 
              col_name, index->table->name);
3196
 
 
3197
 
      /* This will disable the AUTOINC generation. */
3198
 
      auto_inc = 0;
3199
 
 
3200
 
      /* We want the open to succeed, so that the user can
3201
 
         take corrective action. ie. reads should succeed but
3202
 
         updates should fail. */
3203
 
      err = DB_SUCCESS;
3204
 
      break;
3205
 
    default:
3206
 
      /* row_search_max_autoinc() should only return
3207
 
         one of DB_SUCCESS or DB_RECORD_NOT_FOUND. */
3208
 
      ut_error;
3209
 
    }
3210
 
  }
3211
 
 
3212
 
  dict_table_autoinc_initialize(prebuilt->table, auto_inc);
 
2609
        dict_index_t*   index;
 
2610
        uint64_t        auto_inc;
 
2611
        const char*     col_name;
 
2612
        ulint           error;
 
2613
 
 
2614
        col_name = table->found_next_number_field->field_name;
 
2615
        index = innobase_get_index(table->s->next_number_index);
 
2616
 
 
2617
        /* Execute SELECT MAX(col_name) FROM TABLE; */
 
2618
        error = row_search_max_autoinc(index, col_name, &auto_inc);
 
2619
 
 
2620
        switch (error) {
 
2621
        case DB_SUCCESS:
 
2622
 
 
2623
                /* At the this stage we don't know the increment
 
2624
                or the offset, so use default inrement of 1. */
 
2625
                ++auto_inc;
 
2626
                break;
 
2627
 
 
2628
        case DB_RECORD_NOT_FOUND:
 
2629
                ut_print_timestamp(stderr);
 
2630
                fprintf(stderr, "  InnoDB: MySQL and InnoDB data "
 
2631
                        "dictionaries are out of sync.\n"
 
2632
                        "InnoDB: Unable to find the AUTOINC column %s in the "
 
2633
                        "InnoDB table %s.\n"
 
2634
                        "InnoDB: We set the next AUTOINC column value to the "
 
2635
                        "maximum possible value,\n"
 
2636
                        "InnoDB: in effect disabling the AUTOINC next value "
 
2637
                        "generation.\n"
 
2638
                        "InnoDB: You can either set the next AUTOINC value "
 
2639
                        "explicitly using ALTER TABLE\n"
 
2640
                        "InnoDB: or fix the data dictionary by recreating "
 
2641
                        "the table.\n",
 
2642
                        col_name, index->table->name);
 
2643
 
 
2644
                auto_inc = 0xFFFFFFFFFFFFFFFFULL;
 
2645
                break;
 
2646
 
 
2647
        default:
 
2648
                return(error);
 
2649
        }
 
2650
 
 
2651
        dict_table_autoinc_initialize(prebuilt->table, auto_inc);
 
2652
 
 
2653
        return(DB_SUCCESS);
3213
2654
}
3214
2655
 
3215
2656
/*****************************************************************//**
3216
2657
Creates and opens a handle to a table which already exists in an InnoDB
3217
2658
database.
3218
 
@return 1 if error, 0 if success */
 
2659
@return 1 if error, 0 if success */
3219
2660
UNIV_INTERN
3220
2661
int
3221
 
ha_innobase::doOpen(const TableIdentifier &identifier,
3222
 
                    int   mode,   /*!< in: not used */
3223
 
                    uint    test_if_locked) /*!< in: not used */
 
2662
ha_innobase::open(
 
2663
/*==============*/
 
2664
        const char*     name,           /*!< in: table name */
 
2665
        int             mode,           /*!< in: not used */
 
2666
        uint            test_if_locked) /*!< in: not used */
3224
2667
{
3225
 
  dict_table_t* ib_table;
3226
 
  char    norm_name[FN_REFLEN];
3227
 
  Session*    session;
3228
 
 
3229
 
  UT_NOT_USED(mode);
3230
 
  UT_NOT_USED(test_if_locked);
3231
 
 
3232
 
  session= getTable()->in_use;
3233
 
 
3234
 
  /* Under some cases Drizzle seems to call this function while
3235
 
  holding btr_search_latch. This breaks the latching order as
3236
 
  we acquire dict_sys->mutex below and leads to a deadlock. */
3237
 
  if (session != NULL) {
3238
 
    getTransactionalEngine()->releaseTemporaryLatches(session);
3239
 
  }
3240
 
 
3241
 
  normalize_table_name(norm_name, identifier.getPath().c_str());
3242
 
 
3243
 
  user_session = NULL;
3244
 
 
3245
 
  if (!(share=get_share(identifier.getPath().c_str()))) {
3246
 
 
3247
 
    return(1);
3248
 
  }
3249
 
 
3250
 
  /* Create buffers for packing the fields of a record. Why
3251
 
  table->stored_rec_length did not work here? Obviously, because char
3252
 
  fields when packed actually became 1 byte longer, when we also
3253
 
  stored the string length as the first byte. */
3254
 
 
3255
 
  upd_and_key_val_buff_len =
3256
 
        getTable()->getShare()->stored_rec_length
3257
 
        + getTable()->getShare()->max_key_length
3258
 
        + MAX_REF_PARTS * 3;
3259
 
 
3260
 
  upd_buff.resize(upd_and_key_val_buff_len);
3261
 
 
3262
 
  if (upd_buff.size() < upd_and_key_val_buff_len)
3263
 
  {
3264
 
    free_share(share);
3265
 
  }
3266
 
 
3267
 
  key_val_buff.resize(upd_and_key_val_buff_len);
3268
 
  if (key_val_buff.size() < upd_and_key_val_buff_len)
3269
 
  {
3270
 
    return(1);
3271
 
  }
3272
 
 
3273
 
  /* Get pointer to a table object in InnoDB dictionary cache */
3274
 
  ib_table = dict_table_get(norm_name, TRUE);
3275
 
  
3276
 
  if (NULL == ib_table) {
3277
 
    errmsg_printf(ERRMSG_LVL_ERROR, "Cannot find or open table %s from\n"
3278
 
        "the internal data dictionary of InnoDB "
3279
 
        "though the .frm file for the\n"
3280
 
        "table exists. Maybe you have deleted and "
3281
 
        "recreated InnoDB data\n"
3282
 
        "files but have forgotten to delete the "
3283
 
        "corresponding .frm files\n"
3284
 
        "of InnoDB tables, or you have moved .frm "
3285
 
        "files to another database?\n"
3286
 
        "or, the table contains indexes that this "
3287
 
        "version of the engine\n"
3288
 
        "doesn't support.\n"
3289
 
        "See " REFMAN "innodb-troubleshooting.html\n"
3290
 
        "how you can resolve the problem.\n",
3291
 
        norm_name);
3292
 
    free_share(share);
3293
 
    upd_buff.resize(0);
3294
 
    key_val_buff.resize(0);
3295
 
    errno = ENOENT;
3296
 
 
3297
 
    return(HA_ERR_NO_SUCH_TABLE);
3298
 
  }
3299
 
 
3300
 
  if (ib_table->ibd_file_missing && !session_tablespace_op(session)) {
3301
 
    errmsg_printf(ERRMSG_LVL_ERROR, "MySQL is trying to open a table handle but "
3302
 
        "the .ibd file for\ntable %s does not exist.\n"
3303
 
        "Have you deleted the .ibd file from the "
3304
 
        "database directory under\nthe MySQL datadir, "
3305
 
        "or have you used DISCARD TABLESPACE?\n"
3306
 
        "See " REFMAN "innodb-troubleshooting.html\n"
3307
 
        "how you can resolve the problem.\n",
3308
 
        norm_name);
3309
 
    free_share(share);
3310
 
    upd_buff.resize(0);
3311
 
    key_val_buff.resize(0);
3312
 
    errno = ENOENT;
3313
 
 
3314
 
    dict_table_decrement_handle_count(ib_table, FALSE);
3315
 
    return(HA_ERR_NO_SUCH_TABLE);
3316
 
  }
3317
 
 
3318
 
  prebuilt = row_create_prebuilt(ib_table);
3319
 
 
3320
 
  prebuilt->mysql_row_len = getTable()->getShare()->stored_rec_length;
3321
 
  prebuilt->default_rec = getTable()->getDefaultValues();
3322
 
  ut_ad(prebuilt->default_rec);
3323
 
 
3324
 
  /* Looks like MySQL-3.23 sometimes has primary key number != 0 */
3325
 
 
3326
 
  primary_key = getTable()->getShare()->getPrimaryKey();
3327
 
  key_used_on_scan = primary_key;
3328
 
 
3329
 
  if (!innobase_build_index_translation(getTable(), ib_table, share)) {
3330
 
    errmsg_printf(ERRMSG_LVL_ERROR, "Build InnoDB index translation table for"
3331
 
                    " Table %s failed", identifier.getPath().c_str());
3332
 
  }
3333
 
 
3334
 
  /* Allocate a buffer for a 'row reference'. A row reference is
3335
 
  a string of bytes of length ref_length which uniquely specifies
3336
 
  a row in our table. Note that MySQL may also compare two row
3337
 
  references for equality by doing a simple memcmp on the strings
3338
 
  of length ref_length! */
3339
 
 
3340
 
  if (!row_table_got_default_clust_index(ib_table)) {
3341
 
 
3342
 
    prebuilt->clust_index_was_generated = FALSE;
3343
 
 
3344
 
    if (UNIV_UNLIKELY(primary_key >= MAX_KEY)) {
3345
 
      errmsg_printf(ERRMSG_LVL_ERROR, "Table %s has a primary key in "
3346
 
                    "InnoDB data dictionary, but not "
3347
 
                    "in MySQL!", identifier.getTableName().c_str());
3348
 
 
3349
 
      /* This mismatch could cause further problems
3350
 
         if not attended, bring this to the user's attention
3351
 
         by printing a warning in addition to log a message
3352
 
         in the errorlog */
3353
 
      push_warning_printf(session, DRIZZLE_ERROR::WARN_LEVEL_WARN,
3354
 
                          ER_NO_SUCH_INDEX,
3355
 
                          "InnoDB: Table %s has a "
3356
 
                          "primary key in InnoDB data "
3357
 
                          "dictionary, but not in "
3358
 
                          "MySQL!", identifier.getTableName().c_str());
3359
 
 
3360
 
      /* If primary_key >= MAX_KEY, its (primary_key)
3361
 
         value could be out of bound if continue to index
3362
 
         into key_info[] array. Find InnoDB primary index,
3363
 
         and assign its key_length to ref_length.
3364
 
         In addition, since MySQL indexes are sorted starting
3365
 
         with primary index, unique index etc., initialize
3366
 
         ref_length to the first index key length in
3367
 
         case we fail to find InnoDB cluster index.
3368
 
 
3369
 
         Please note, this will not resolve the primary
3370
 
         index mismatch problem, other side effects are
3371
 
         possible if users continue to use the table.
3372
 
         However, we allow this table to be opened so
3373
 
         that user can adopt necessary measures for the
3374
 
         mismatch while still being accessible to the table
3375
 
         date. */
3376
 
      ref_length = getTable()->key_info[0].key_length;
3377
 
 
3378
 
      /* Find correspoinding cluster index
3379
 
         key length in MySQL's key_info[] array */
3380
 
      for (ulint i = 0; i < getTable()->getShare()->keys; i++) {
3381
 
        dict_index_t*   index;
3382
 
        index = innobase_get_index(i);
3383
 
        if (dict_index_is_clust(index)) {
3384
 
          ref_length =
3385
 
            getTable()->key_info[i].key_length;
3386
 
        }
3387
 
      }
3388
 
    } else {
3389
 
      /* MySQL allocates the buffer for ref.
3390
 
         key_info->key_length includes space for all key
3391
 
         columns + one byte for each column that may be
3392
 
         NULL. ref_length must be as exact as possible to
3393
 
         save space, because all row reference buffers are
3394
 
         allocated based on ref_length. */
3395
 
 
3396
 
      ref_length = getTable()->key_info[primary_key].key_length;
3397
 
    }
3398
 
  } else {
3399
 
    if (primary_key != MAX_KEY) {
3400
 
      errmsg_printf(ERRMSG_LVL_ERROR,
3401
 
                    "Table %s has no primary key in InnoDB data "
3402
 
                    "dictionary, but has one in MySQL! If you "
3403
 
                    "created the table with a MySQL version < "
3404
 
                    "3.23.54 and did not define a primary key, "
3405
 
                    "but defined a unique key with all non-NULL "
3406
 
                    "columns, then MySQL internally treats that "
3407
 
                    "key as the primary key. You can fix this "
3408
 
                    "error by dump + DROP + CREATE + reimport "
3409
 
                    "of the table.", identifier.getTableName().c_str());
3410
 
 
3411
 
      /* This mismatch could cause further problems
3412
 
         if not attended, bring this to the user attention
3413
 
         by printing a warning in addition to log a message
3414
 
         in the errorlog */
3415
 
      push_warning_printf(session, DRIZZLE_ERROR::WARN_LEVEL_WARN,
3416
 
                          ER_NO_SUCH_INDEX,
3417
 
                          "InnoDB: Table %s has no "
3418
 
                          "primary key in InnoDB data "
3419
 
                          "dictionary, but has one in "
3420
 
                          "MySQL!", identifier.getTableName().c_str());
3421
 
    }
3422
 
 
3423
 
    prebuilt->clust_index_was_generated = TRUE;
3424
 
 
3425
 
    ref_length = DATA_ROW_ID_LEN;
3426
 
 
3427
 
    /* If we automatically created the clustered index, then
3428
 
    MySQL does not know about it, and MySQL must NOT be aware
3429
 
    of the index used on scan, to make it avoid checking if we
3430
 
    update the column of the index. That is why we assert below
3431
 
    that key_used_on_scan is the undefined value MAX_KEY.
3432
 
    The column is the row id in the automatical generation case,
3433
 
    and it will never be updated anyway. */
3434
 
 
3435
 
    if (key_used_on_scan != MAX_KEY) {
3436
 
      errmsg_printf(ERRMSG_LVL_WARN, 
3437
 
        "Table %s key_used_on_scan is %lu even "
3438
 
        "though there is no primary key inside "
3439
 
        "InnoDB.", identifier.getTableName().c_str(), (ulong) key_used_on_scan);
3440
 
    }
3441
 
  }
3442
 
 
3443
 
  /* Index block size in InnoDB: used by MySQL in query optimization */
3444
 
  stats.block_size = 16 * 1024;
3445
 
 
3446
 
  /* Init table lock structure */
3447
 
  lock.init(&share->lock);
3448
 
 
3449
 
  if (prebuilt->table) {
3450
 
    /* We update the highest file format in the system table
3451
 
    space, if this table has higher file format setting. */
3452
 
 
3453
 
    trx_sys_file_format_max_upgrade(
3454
 
      (const char**) &innobase_file_format_check,
3455
 
      dict_table_get_format(prebuilt->table));
3456
 
  }
3457
 
 
3458
 
  info(HA_STATUS_NO_LOCK | HA_STATUS_VARIABLE | HA_STATUS_CONST);
3459
 
 
3460
 
  /* Only if the table has an AUTOINC column. */
3461
 
  if (prebuilt->table != NULL && getTable()->found_next_number_field != NULL) {
3462
 
 
3463
 
    dict_table_autoinc_lock(prebuilt->table);
3464
 
 
3465
 
    /* Since a table can already be "open" in InnoDB's internal
3466
 
    data dictionary, we only init the autoinc counter once, the
3467
 
    first time the table is loaded. We can safely reuse the
3468
 
    autoinc value from a previous Drizzle open. */
3469
 
    if (dict_table_autoinc_read(prebuilt->table) == 0) {
3470
 
 
3471
 
      innobase_initialize_autoinc();
3472
 
    }
3473
 
 
3474
 
    dict_table_autoinc_unlock(prebuilt->table);
3475
 
  }
3476
 
 
3477
 
  return(0);
 
2668
        dict_table_t*   ib_table;
 
2669
        char            norm_name[1000];
 
2670
        Session*                session;
 
2671
        ulint           retries = 0;
 
2672
        char*           is_part = NULL;
 
2673
 
 
2674
        UT_NOT_USED(mode);
 
2675
        UT_NOT_USED(test_if_locked);
 
2676
 
 
2677
        session = ha_session();
 
2678
 
 
2679
        /* Under some cases Drizzle seems to call this function while
 
2680
        holding btr_search_latch. This breaks the latching order as
 
2681
        we acquire dict_sys->mutex below and leads to a deadlock. */
 
2682
        if (session != NULL) {
 
2683
                getTransactionalEngine()->releaseTemporaryLatches(session);
 
2684
        }
 
2685
 
 
2686
        normalize_table_name(norm_name, name);
 
2687
 
 
2688
        user_session = NULL;
 
2689
 
 
2690
        if (!(share=get_share(name))) {
 
2691
 
 
2692
                return(1);
 
2693
        }
 
2694
 
 
2695
        /* Create buffers for packing the fields of a record. Why
 
2696
        table->stored_rec_length did not work here? Obviously, because char
 
2697
        fields when packed actually became 1 byte longer, when we also
 
2698
        stored the string length as the first byte. */
 
2699
 
 
2700
        upd_and_key_val_buff_len =
 
2701
                                table->s->stored_rec_length
 
2702
                                + table->s->max_key_length
 
2703
                                + MAX_REF_PARTS * 3;
 
2704
        if (!(unsigned char*) memory::multi_malloc(false,
 
2705
                        &upd_buff, upd_and_key_val_buff_len,
 
2706
                        &key_val_buff, upd_and_key_val_buff_len,
 
2707
                        NULL)) {
 
2708
                free_share(share);
 
2709
 
 
2710
                return(1);
 
2711
        }
 
2712
 
 
2713
        /* We look for pattern #P# to see if the table is partitioned
 
2714
        MySQL table. The retry logic for partitioned tables is a
 
2715
        workaround for http://bugs.mysql.com/bug.php?id=33349. Look
 
2716
        at support issue https://support.mysql.com/view.php?id=21080
 
2717
        for more details. */
 
2718
        is_part = strstr(norm_name, "#P#");
 
2719
retry:
 
2720
        /* Get pointer to a table object in InnoDB dictionary cache */
 
2721
        ib_table = dict_table_get(norm_name, TRUE);
 
2722
        
 
2723
        if (NULL == ib_table) {
 
2724
                if (is_part && retries < 10) {
 
2725
                        ++retries;
 
2726
                        os_thread_sleep(100000);
 
2727
                        goto retry;
 
2728
                }
 
2729
 
 
2730
                if (is_part) {
 
2731
                        errmsg_printf(ERRMSG_LVL_ERROR, "Failed to open table %s after "
 
2732
                                        "%lu attemtps.\n", norm_name,
 
2733
                                        retries);
 
2734
                }
 
2735
 
 
2736
                errmsg_printf(ERRMSG_LVL_ERROR, "Cannot find or open table %s from\n"
 
2737
                                "the internal data dictionary of InnoDB "
 
2738
                                "though the .frm file for the\n"
 
2739
                                "table exists. Maybe you have deleted and "
 
2740
                                "recreated InnoDB data\n"
 
2741
                                "files but have forgotten to delete the "
 
2742
                                "corresponding .frm files\n"
 
2743
                                "of InnoDB tables, or you have moved .frm "
 
2744
                                "files to another database?\n"
 
2745
                                "or, the table contains indexes that this "
 
2746
                                "version of the engine\n"
 
2747
                                "doesn't support.\n"
 
2748
                                "See " REFMAN "innodb-troubleshooting.html\n"
 
2749
                                "how you can resolve the problem.\n",
 
2750
                                norm_name);
 
2751
                free_share(share);
 
2752
                free(upd_buff);
 
2753
                errno = ENOENT;
 
2754
 
 
2755
                return(HA_ERR_NO_SUCH_TABLE);
 
2756
        }
 
2757
 
 
2758
        if (ib_table->ibd_file_missing && !session_tablespace_op(session)) {
 
2759
                errmsg_printf(ERRMSG_LVL_ERROR, "MySQL is trying to open a table handle but "
 
2760
                                "the .ibd file for\ntable %s does not exist.\n"
 
2761
                                "Have you deleted the .ibd file from the "
 
2762
                                "database directory under\nthe MySQL datadir, "
 
2763
                                "or have you used DISCARD TABLESPACE?\n"
 
2764
                                "See " REFMAN "innodb-troubleshooting.html\n"
 
2765
                                "how you can resolve the problem.\n",
 
2766
                                norm_name);
 
2767
                free_share(share);
 
2768
                free(upd_buff);
 
2769
                errno = ENOENT;
 
2770
 
 
2771
                dict_table_decrement_handle_count(ib_table, FALSE);
 
2772
                return(HA_ERR_NO_SUCH_TABLE);
 
2773
        }
 
2774
 
 
2775
        prebuilt = row_create_prebuilt(ib_table);
 
2776
 
 
2777
        prebuilt->mysql_row_len = table->s->stored_rec_length;
 
2778
        prebuilt->default_rec = table->s->default_values;
 
2779
        ut_ad(prebuilt->default_rec);
 
2780
 
 
2781
        /* Looks like MySQL-3.23 sometimes has primary key number != 0 */
 
2782
 
 
2783
        primary_key = table->s->primary_key;
 
2784
        key_used_on_scan = primary_key;
 
2785
 
 
2786
        /* Allocate a buffer for a 'row reference'. A row reference is
 
2787
        a string of bytes of length ref_length which uniquely specifies
 
2788
        a row in our table. Note that MySQL may also compare two row
 
2789
        references for equality by doing a simple memcmp on the strings
 
2790
        of length ref_length! */
 
2791
 
 
2792
        if (!row_table_got_default_clust_index(ib_table)) {
 
2793
                if (primary_key >= MAX_KEY) {
 
2794
                  errmsg_printf(ERRMSG_LVL_ERROR, "Table %s has a primary key in InnoDB data "
 
2795
                                  "dictionary, but not in MySQL!", name);
 
2796
                }
 
2797
 
 
2798
                prebuilt->clust_index_was_generated = FALSE;
 
2799
 
 
2800
                /* MySQL allocates the buffer for ref. key_info->key_length
 
2801
                includes space for all key columns + one byte for each column
 
2802
                that may be NULL. ref_length must be as exact as possible to
 
2803
                save space, because all row reference buffers are allocated
 
2804
                based on ref_length. */
 
2805
 
 
2806
                ref_length = table->key_info[primary_key].key_length;
 
2807
        } else {
 
2808
                if (primary_key != MAX_KEY) {
 
2809
                  errmsg_printf(ERRMSG_LVL_ERROR, "Table %s has no primary key in InnoDB data "
 
2810
                                  "dictionary, but has one in MySQL! If you "
 
2811
                                  "created the table with a MySQL version < "
 
2812
                                  "3.23.54 and did not define a primary key, "
 
2813
                                  "but defined a unique key with all non-NULL "
 
2814
                                  "columns, then MySQL internally treats that "
 
2815
                                  "key as the primary key. You can fix this "
 
2816
                                  "error by dump + DROP + CREATE + reimport "
 
2817
                                  "of the table.", name);
 
2818
                }
 
2819
 
 
2820
                prebuilt->clust_index_was_generated = TRUE;
 
2821
 
 
2822
                ref_length = DATA_ROW_ID_LEN;
 
2823
 
 
2824
                /* If we automatically created the clustered index, then
 
2825
                MySQL does not know about it, and MySQL must NOT be aware
 
2826
                of the index used on scan, to make it avoid checking if we
 
2827
                update the column of the index. That is why we assert below
 
2828
                that key_used_on_scan is the undefined value MAX_KEY.
 
2829
                The column is the row id in the automatical generation case,
 
2830
                and it will never be updated anyway. */
 
2831
 
 
2832
                if (key_used_on_scan != MAX_KEY) {
 
2833
                        errmsg_printf(ERRMSG_LVL_WARN, 
 
2834
                                "Table %s key_used_on_scan is %lu even "
 
2835
                                "though there is no primary key inside "
 
2836
                                "InnoDB.", name, (ulong) key_used_on_scan);
 
2837
                }
 
2838
        }
 
2839
 
 
2840
        /* Index block size in InnoDB: used by MySQL in query optimization */
 
2841
        stats.block_size = 16 * 1024;
 
2842
 
 
2843
        /* Init table lock structure */
 
2844
        thr_lock_data_init(&share->lock,&lock,(void*) 0);
 
2845
 
 
2846
        if (prebuilt->table) {
 
2847
                /* We update the highest file format in the system table
 
2848
                space, if this table has higher file format setting. */
 
2849
 
 
2850
                trx_sys_file_format_max_upgrade(
 
2851
                        (const char**) &innobase_file_format_check,
 
2852
                        dict_table_get_format(prebuilt->table));
 
2853
        }
 
2854
 
 
2855
        info(HA_STATUS_NO_LOCK | HA_STATUS_VARIABLE | HA_STATUS_CONST);
 
2856
 
 
2857
        /* Only if the table has an AUTOINC column. */
 
2858
        if (prebuilt->table != NULL && table->found_next_number_field != NULL) {
 
2859
                ulint   error;
 
2860
 
 
2861
                dict_table_autoinc_lock(prebuilt->table);
 
2862
 
 
2863
                /* Since a table can already be "open" in InnoDB's internal
 
2864
                data dictionary, we only init the autoinc counter once, the
 
2865
                first time the table is loaded. We can safely reuse the
 
2866
                autoinc value from a previous Drizzle open. */
 
2867
                if (dict_table_autoinc_read(prebuilt->table) == 0) {
 
2868
 
 
2869
                        error = innobase_initialize_autoinc();
 
2870
                        ut_a(error == DB_SUCCESS);
 
2871
                }
 
2872
 
 
2873
                dict_table_autoinc_unlock(prebuilt->table);
 
2874
        }
 
2875
 
 
2876
        return(0);
3478
2877
}
3479
2878
 
3480
2879
UNIV_INTERN
3481
2880
uint32_t
3482
2881
InnobaseEngine::max_supported_key_part_length() const
3483
2882
{
3484
 
  return(DICT_MAX_INDEX_COL_LEN - 1);
 
2883
        return(DICT_MAX_INDEX_COL_LEN - 1);
3485
2884
}
3486
2885
 
3487
2886
/******************************************************************//**
3488
2887
Closes a handle to an InnoDB table.
3489
 
@return 0 */
 
2888
@return 0 */
3490
2889
UNIV_INTERN
3491
2890
int
3492
2891
ha_innobase::close(void)
3493
2892
/*====================*/
3494
2893
{
3495
 
  Session*  session;
3496
 
 
3497
 
  session= getTable()->in_use;
3498
 
  if (session != NULL) {
3499
 
    getTransactionalEngine()->releaseTemporaryLatches(session);
3500
 
  }
3501
 
 
3502
 
  row_prebuilt_free(prebuilt, FALSE);
3503
 
 
3504
 
  upd_buff.clear();
3505
 
  key_val_buff.clear();
3506
 
  free_share(share);
3507
 
 
3508
 
  /* Tell InnoDB server that there might be work for
3509
 
  utility threads: */
3510
 
 
3511
 
  srv_active_wake_master_thread();
3512
 
 
3513
 
  return(0);
 
2894
        Session*        session;
 
2895
 
 
2896
        session = ha_session();
 
2897
        if (session != NULL) {
 
2898
                getTransactionalEngine()->releaseTemporaryLatches(session);
 
2899
        }
 
2900
 
 
2901
        row_prebuilt_free(prebuilt, FALSE);
 
2902
 
 
2903
        free(upd_buff);
 
2904
        free_share(share);
 
2905
 
 
2906
        /* Tell InnoDB server that there might be work for
 
2907
        utility threads: */
 
2908
 
 
2909
        srv_active_wake_master_thread();
 
2910
 
 
2911
        return(0);
3514
2912
}
3515
2913
 
3516
2914
/* The following accessor functions should really be inside MySQL code! */
3517
2915
 
3518
2916
/**************************************************************//**
3519
2917
Gets field offset for a field in a table.
3520
 
@return offset */
 
2918
@return offset */
3521
2919
static inline
3522
2920
uint
3523
2921
get_field_offset(
3524
2922
/*=============*/
3525
 
  Table*  table,  /*!< in: MySQL table object */
3526
 
  Field*  field)  /*!< in: MySQL field object */
 
2923
        Table*  table,  /*!< in: MySQL table object */
 
2924
        Field*  field)  /*!< in: MySQL field object */
3527
2925
{
3528
 
  return((uint) (field->ptr - table->getInsertRecord()));
 
2926
        return((uint) (field->ptr - table->record[0]));
3529
2927
}
3530
2928
 
3531
2929
/**************************************************************//**
3532
2930
Checks if a field in a record is SQL NULL. Uses the record format
3533
2931
information in table to track the null bit in record.
3534
 
@return 1 if NULL, 0 otherwise */
 
2932
@return 1 if NULL, 0 otherwise */
3535
2933
static inline
3536
2934
uint
3537
2935
field_in_record_is_null(
3538
2936
/*====================*/
3539
 
  Table*  table,  /*!< in: MySQL table object */
3540
 
  Field*  field,  /*!< in: MySQL field object */
3541
 
  char* record) /*!< in: a row in MySQL format */
 
2937
        Table*  table,  /*!< in: MySQL table object */
 
2938
        Field*  field,  /*!< in: MySQL field object */
 
2939
        char*   record) /*!< in: a row in MySQL format */
3542
2940
{
3543
 
  int null_offset;
3544
 
 
3545
 
  if (!field->null_ptr) {
3546
 
 
3547
 
    return(0);
3548
 
  }
3549
 
 
3550
 
  null_offset = (uint) ((char*) field->null_ptr
3551
 
          - (char*) table->getInsertRecord());
3552
 
 
3553
 
  if (record[null_offset] & field->null_bit) {
3554
 
 
3555
 
    return(1);
3556
 
  }
3557
 
 
3558
 
  return(0);
 
2941
        int     null_offset;
 
2942
 
 
2943
        if (!field->null_ptr) {
 
2944
 
 
2945
                return(0);
 
2946
        }
 
2947
 
 
2948
        null_offset = (uint) ((char*) field->null_ptr
 
2949
                                        - (char*) table->record[0]);
 
2950
 
 
2951
        if (record[null_offset] & field->null_bit) {
 
2952
 
 
2953
                return(1);
 
2954
        }
 
2955
 
 
2956
        return(0);
3559
2957
}
3560
2958
 
3561
2959
/**************************************************************//**
3565
2963
void
3566
2964
set_field_in_record_to_null(
3567
2965
/*========================*/
3568
 
  Table*  table,  /*!< in: MySQL table object */
3569
 
  Field*  field,  /*!< in: MySQL field object */
3570
 
  char* record) /*!< in: a row in MySQL format */
 
2966
        Table*  table,  /*!< in: MySQL table object */
 
2967
        Field*  field,  /*!< in: MySQL field object */
 
2968
        char*   record) /*!< in: a row in MySQL format */
3571
2969
{
3572
 
  int null_offset;
3573
 
 
3574
 
  null_offset = (uint) ((char*) field->null_ptr
3575
 
          - (char*) table->getInsertRecord());
3576
 
 
3577
 
  record[null_offset] = record[null_offset] | field->null_bit;
 
2970
        int     null_offset;
 
2971
 
 
2972
        null_offset = (uint) ((char*) field->null_ptr
 
2973
                                        - (char*) table->record[0]);
 
2974
 
 
2975
        record[null_offset] = record[null_offset] | field->null_bit;
3578
2976
}
3579
2977
 
3580
2978
/*************************************************************//**
3582
2980
is such that we must use MySQL code to compare them. NOTE that the prototype
3583
2981
of this function is in rem0cmp.c in InnoDB source code! If you change this
3584
2982
function, remember to update the prototype there!
3585
 
@return 1, 0, -1, if a is greater, equal, less than b, respectively */
 
2983
@return 1, 0, -1, if a is greater, equal, less than b, respectively */
3586
2984
extern "C" UNIV_INTERN
3587
2985
int
3588
2986
innobase_mysql_cmp(
3589
2987
/*===============*/
3590
 
  int   mysql_type, /*!< in: MySQL type */
3591
 
  uint    charset_number, /*!< in: number of the charset */
3592
 
  const unsigned char* a,   /*!< in: data field */
3593
 
  unsigned int  a_length, /*!< in: data field length,
3594
 
          not UNIV_SQL_NULL */
3595
 
  const unsigned char* b,   /* in: data field */
3596
 
  unsigned int  b_length);  /* in: data field length,
3597
 
          not UNIV_SQL_NULL */
 
2988
        int             mysql_type,     /*!< in: MySQL type */
 
2989
        uint            charset_number, /*!< in: number of the charset */
 
2990
        const unsigned char* a,         /*!< in: data field */
 
2991
        unsigned int    a_length,       /*!< in: data field length,
 
2992
                                        not UNIV_SQL_NULL */
 
2993
        const unsigned char* b,         /* in: data field */
 
2994
        unsigned int    b_length);      /* in: data field length,
 
2995
                                        not UNIV_SQL_NULL */
3598
2996
 
3599
2997
int
3600
2998
innobase_mysql_cmp(
3601
2999
/*===============*/
3602
 
          /* out: 1, 0, -1, if a is greater, equal, less than b, respectively */
3603
 
  int   mysql_type, /* in: MySQL type */
3604
 
  uint    charset_number, /* in: number of the charset */
3605
 
  const unsigned char* a,   /* in: data field */
3606
 
  unsigned int  a_length, /* in: data field length, not UNIV_SQL_NULL */
3607
 
  const unsigned char* b,   /* in: data field */
3608
 
  unsigned int  b_length) /* in: data field length, not UNIV_SQL_NULL */
 
3000
                                        /* out: 1, 0, -1, if a is greater,
 
3001
                                        equal, less than b, respectively */
 
3002
        int             mysql_type,     /* in: MySQL type */
 
3003
        uint            charset_number, /* in: number of the charset */
 
3004
        const unsigned char* a,         /* in: data field */
 
3005
        unsigned int    a_length,       /* in: data field length,
 
3006
                                        not UNIV_SQL_NULL */
 
3007
        const unsigned char* b,         /* in: data field */
 
3008
        unsigned int    b_length)       /* in: data field length,
 
3009
                                        not UNIV_SQL_NULL */
3609
3010
{
3610
 
  const CHARSET_INFO* charset;
3611
 
  enum_field_types  mysql_tp;
3612
 
  int     ret;
3613
 
 
3614
 
  assert(a_length != UNIV_SQL_NULL);
3615
 
  assert(b_length != UNIV_SQL_NULL);
3616
 
 
3617
 
  mysql_tp = (enum_field_types) mysql_type;
3618
 
 
3619
 
  switch (mysql_tp) {
3620
 
 
3621
 
  case DRIZZLE_TYPE_BLOB:
3622
 
  case DRIZZLE_TYPE_VARCHAR:
3623
 
    /* Use the charset number to pick the right charset struct for
3624
 
      the comparison. Since the MySQL function get_charset may be
3625
 
      slow before Bar removes the mutex operation there, we first
3626
 
      look at 2 common charsets directly. */
3627
 
 
3628
 
    if (charset_number == default_charset_info->number) {
3629
 
      charset = default_charset_info;
3630
 
    } else {
3631
 
      charset = get_charset(charset_number);
3632
 
 
3633
 
      if (charset == NULL) {
3634
 
        errmsg_printf(ERRMSG_LVL_ERROR, "InnoDB needs charset %lu for doing "
3635
 
                      "a comparison, but MySQL cannot "
3636
 
                      "find that charset.",
3637
 
                      (ulong) charset_number);
3638
 
        ut_a(0);
3639
 
      }
3640
 
    }
3641
 
 
3642
 
    /* Starting from 4.1.3, we use strnncollsp() in comparisons of
3643
 
      non-latin1_swedish_ci strings. NOTE that the collation order
3644
 
      changes then: 'b\0\0...' is ordered BEFORE 'b  ...'. Users
3645
 
      having indexes on such data need to rebuild their tables! */
3646
 
 
3647
 
    ret = charset->coll->strnncollsp(charset,
3648
 
                                     a, a_length,
3649
 
                                     b, b_length, 0);
3650
 
    if (ret < 0) {
3651
 
      return(-1);
3652
 
    } else if (ret > 0) {
3653
 
      return(1);
3654
 
    } else {
3655
 
      return(0);
3656
 
    }
3657
 
  default:
3658
 
    ut_error;
3659
 
  }
3660
 
 
3661
 
  return(0);
 
3011
        const CHARSET_INFO*     charset;
 
3012
        enum_field_types        mysql_tp;
 
3013
        int                     ret;
 
3014
 
 
3015
        assert(a_length != UNIV_SQL_NULL);
 
3016
        assert(b_length != UNIV_SQL_NULL);
 
3017
 
 
3018
        mysql_tp = (enum_field_types) mysql_type;
 
3019
 
 
3020
        switch (mysql_tp) {
 
3021
 
 
3022
        case DRIZZLE_TYPE_BLOB:
 
3023
        case DRIZZLE_TYPE_VARCHAR:
 
3024
                /* Use the charset number to pick the right charset struct for
 
3025
                the comparison. Since the MySQL function get_charset may be
 
3026
                slow before Bar removes the mutex operation there, we first
 
3027
                look at 2 common charsets directly. */
 
3028
 
 
3029
                if (charset_number == default_charset_info->number) {
 
3030
                        charset = default_charset_info;
 
3031
                } else {
 
3032
                        charset = get_charset(charset_number);
 
3033
 
 
3034
                        if (charset == NULL) {
 
3035
                          errmsg_printf(ERRMSG_LVL_ERROR, "InnoDB needs charset %lu for doing "
 
3036
                                          "a comparison, but MySQL cannot "
 
3037
                                          "find that charset.",
 
3038
                                          (ulong) charset_number);
 
3039
                                ut_a(0);
 
3040
                        }
 
3041
                }
 
3042
 
 
3043
                /* Starting from 4.1.3, we use strnncollsp() in comparisons of
 
3044
                non-latin1_swedish_ci strings. NOTE that the collation order
 
3045
                changes then: 'b\0\0...' is ordered BEFORE 'b  ...'. Users
 
3046
                having indexes on such data need to rebuild their tables! */
 
3047
 
 
3048
                ret = charset->coll->strnncollsp(charset,
 
3049
                                  a, a_length,
 
3050
                                                 b, b_length, 0);
 
3051
                if (ret < 0) {
 
3052
                        return(-1);
 
3053
                } else if (ret > 0) {
 
3054
                        return(1);
 
3055
                } else {
 
3056
                        return(0);
 
3057
                }
 
3058
        default:
 
3059
                ut_error;
 
3060
        }
 
3061
 
 
3062
        return(0);
3662
3063
}
3663
3064
 
3664
3065
/**************************************************************//**
3665
3066
Converts a MySQL type to an InnoDB type. Note that this function returns
3666
3067
the 'mtype' of InnoDB. InnoDB differentiates between MySQL's old <= 4.1
3667
3068
VARCHAR and the new true VARCHAR in >= 5.0.3 by the 'prtype'.
3668
 
@return DATA_BINARY, DATA_VARCHAR, ... */
 
3069
@return DATA_BINARY, DATA_VARCHAR, ... */
3669
3070
extern "C" UNIV_INTERN
3670
3071
ulint
3671
3072
get_innobase_type_from_mysql_type(
3672
3073
/*==============================*/
3673
 
  ulint*    unsigned_flag,  /*!< out: DATA_UNSIGNED if an
3674
 
          'unsigned type';
3675
 
          at least ENUM and SET,
3676
 
          and unsigned integer
3677
 
          types are 'unsigned types' */
3678
 
  const void* f)    /*!< in: MySQL Field */
 
3074
        ulint*          unsigned_flag,  /*!< out: DATA_UNSIGNED if an
 
3075
                                        'unsigned type';
 
3076
                                        at least ENUM and SET,
 
3077
                                        and unsigned integer
 
3078
                                        types are 'unsigned types' */
 
3079
        const void*     f)              /*!< in: MySQL Field */
3679
3080
{
3680
 
  const class Field* field = reinterpret_cast<const class Field*>(f);
3681
 
 
3682
 
  /* The following asserts try to check that the MySQL type code fits in
3683
 
  8 bits: this is used in ibuf and also when DATA_NOT_NULL is ORed to
3684
 
  the type */
3685
 
 
3686
 
  assert((ulint)DRIZZLE_TYPE_DOUBLE < 256);
3687
 
 
3688
 
  if (field->flags & UNSIGNED_FLAG) {
3689
 
 
3690
 
    *unsigned_flag = DATA_UNSIGNED;
3691
 
  } else {
3692
 
    *unsigned_flag = 0;
3693
 
  }
3694
 
 
3695
 
  if (field->real_type() == DRIZZLE_TYPE_ENUM)
3696
 
  {
3697
 
    /* MySQL has field->type() a string type for these, but the
3698
 
    data is actually internally stored as an unsigned integer
3699
 
    code! */
3700
 
 
3701
 
    *unsigned_flag = DATA_UNSIGNED; /* MySQL has its own unsigned
3702
 
            flag set to zero, even though
3703
 
            internally this is an unsigned
3704
 
            integer type */
3705
 
    return(DATA_INT);
3706
 
  }
3707
 
 
3708
 
  switch (field->type()) {
3709
 
    /* NOTE that we only allow string types in DATA_DRIZZLE and
3710
 
    DATA_VARDRIZZLE */
3711
 
  case DRIZZLE_TYPE_VARCHAR:    /* new >= 5.0.3 true VARCHAR */
3712
 
    if (field->binary()) {
3713
 
      return(DATA_BINARY);
3714
 
    } else {
3715
 
      return(DATA_VARMYSQL);
3716
 
    }
3717
 
  case DRIZZLE_TYPE_DECIMAL:
3718
 
    return(DATA_FIXBINARY);
3719
 
  case DRIZZLE_TYPE_LONG:
3720
 
  case DRIZZLE_TYPE_LONGLONG:
3721
 
  case DRIZZLE_TYPE_DATETIME:
3722
 
  case DRIZZLE_TYPE_DATE:
3723
 
  case DRIZZLE_TYPE_TIMESTAMP:
3724
 
    return(DATA_INT);
3725
 
  case DRIZZLE_TYPE_DOUBLE:
3726
 
    return(DATA_DOUBLE);
3727
 
  case DRIZZLE_TYPE_BLOB:
 
3081
        const class Field* field = reinterpret_cast<const class Field*>(f);
 
3082
 
 
3083
        /* The following asserts try to check that the MySQL type code fits in
 
3084
        8 bits: this is used in ibuf and also when DATA_NOT_NULL is ORed to
 
3085
        the type */
 
3086
 
 
3087
        assert((ulint)DRIZZLE_TYPE_DOUBLE < 256);
 
3088
 
 
3089
        if (field->flags & UNSIGNED_FLAG) {
 
3090
 
 
3091
                *unsigned_flag = DATA_UNSIGNED;
 
3092
        } else {
 
3093
                *unsigned_flag = 0;
 
3094
        }
 
3095
 
 
3096
        if (field->real_type() == DRIZZLE_TYPE_ENUM)
 
3097
        {
 
3098
                /* MySQL has field->type() a string type for these, but the
 
3099
                data is actually internally stored as an unsigned integer
 
3100
                code! */
 
3101
 
 
3102
                *unsigned_flag = DATA_UNSIGNED; /* MySQL has its own unsigned
 
3103
                                                flag set to zero, even though
 
3104
                                                internally this is an unsigned
 
3105
                                                integer type */
 
3106
                return(DATA_INT);
 
3107
        }
 
3108
 
 
3109
        switch (field->type()) {
 
3110
                /* NOTE that we only allow string types in DATA_DRIZZLE and
 
3111
                DATA_VARDRIZZLE */
 
3112
        case DRIZZLE_TYPE_VARCHAR:    /* new >= 5.0.3 true VARCHAR */
 
3113
                if (field->binary()) {
 
3114
                        return(DATA_BINARY);
 
3115
                } else {
 
3116
                        return(DATA_VARMYSQL);
 
3117
                }
 
3118
        case DRIZZLE_TYPE_DECIMAL:
 
3119
                return(DATA_FIXBINARY);
 
3120
        case DRIZZLE_TYPE_LONG:
 
3121
        case DRIZZLE_TYPE_LONGLONG:
 
3122
        case DRIZZLE_TYPE_DATETIME:
 
3123
        case DRIZZLE_TYPE_DATE:
 
3124
        case DRIZZLE_TYPE_TIMESTAMP:
 
3125
                return(DATA_INT);
 
3126
        case DRIZZLE_TYPE_DOUBLE:
 
3127
                return(DATA_DOUBLE);
 
3128
        case DRIZZLE_TYPE_BLOB:
3728
3129
                return(DATA_BLOB);
3729
 
  default:
3730
 
    ut_error;
3731
 
  }
 
3130
        default:
 
3131
                ut_error;
 
3132
        }
3732
3133
 
3733
 
  return(0);
 
3134
        return(0);
3734
3135
}
3735
3136
 
3736
3137
/*******************************************************************//**
3740
3141
void
3741
3142
innobase_write_to_2_little_endian(
3742
3143
/*==============================*/
3743
 
  byte* buf,  /*!< in: where to store */
3744
 
  ulint val)  /*!< in: value to write, must be < 64k */
 
3144
        byte*   buf,    /*!< in: where to store */
 
3145
        ulint   val)    /*!< in: value to write, must be < 64k */
3745
3146
{
3746
 
  ut_a(val < 256 * 256);
 
3147
        ut_a(val < 256 * 256);
3747
3148
 
3748
 
  buf[0] = (byte)(val & 0xFF);
3749
 
  buf[1] = (byte)(val / 256);
 
3149
        buf[0] = (byte)(val & 0xFF);
 
3150
        buf[1] = (byte)(val / 256);
3750
3151
}
3751
3152
 
3752
3153
/*******************************************************************//**
3753
3154
Reads an unsigned integer value < 64k from 2 bytes, in the little-endian
3754
3155
storage format.
3755
 
@return value */
 
3156
@return value */
3756
3157
static inline
3757
3158
uint
3758
3159
innobase_read_from_2_little_endian(
3759
3160
/*===============================*/
3760
 
  const unsigned char*  buf)  /*!< in: from where to read */
 
3161
        const unsigned char*    buf)    /*!< in: from where to read */
3761
3162
{
3762
 
  return (uint) ((ulint)(buf[0]) + 256 * ((ulint)(buf[1])));
 
3163
        return (uint) ((ulint)(buf[0]) + 256 * ((ulint)(buf[1])));
3763
3164
}
3764
3165
 
3765
3166
/*******************************************************************//**
3766
3167
Stores a key value for a row to a buffer.
3767
 
@return key value length as stored in buff */
 
3168
@return key value length as stored in buff */
3768
3169
UNIV_INTERN
3769
3170
uint
3770
3171
ha_innobase::store_key_val_for_row(
3771
3172
/*===============================*/
3772
 
  uint    keynr,  /*!< in: key number */
3773
 
  char*   buff, /*!< in/out: buffer for the key value (in MySQL
3774
 
        format) */
3775
 
  uint    buff_len,/*!< in: buffer length */
3776
 
  const unsigned char*  record)/*!< in: row in MySQL format */
 
3173
        uint            keynr,  /*!< in: key number */
 
3174
        char*           buff,   /*!< in/out: buffer for the key value (in MySQL
 
3175
                                format) */
 
3176
        uint            buff_len,/*!< in: buffer length */
 
3177
        const unsigned char*    record)/*!< in: row in MySQL format */
3777
3178
{
3778
 
  KeyInfo*    key_info  = &getTable()->key_info[keynr];
3779
 
  KeyPartInfo*  key_part  = key_info->key_part;
3780
 
  KeyPartInfo*  end   = key_part + key_info->key_parts;
3781
 
  char*   buff_start  = buff;
3782
 
  enum_field_types mysql_type;
3783
 
  Field*    field;
3784
 
  ibool   is_null;
3785
 
 
3786
 
  /* The format for storing a key field in MySQL is the following:
3787
 
 
3788
 
  1. If the column can be NULL, then in the first byte we put 1 if the
3789
 
  field value is NULL, 0 otherwise.
3790
 
 
3791
 
  2. If the column is of a BLOB type (it must be a column prefix field
3792
 
  in this case), then we put the length of the data in the field to the
3793
 
  next 2 bytes, in the little-endian format. If the field is SQL NULL,
3794
 
  then these 2 bytes are set to 0. Note that the length of data in the
3795
 
  field is <= column prefix length.
3796
 
 
3797
 
  3. In a column prefix field, prefix_len next bytes are reserved for
3798
 
  data. In a normal field the max field length next bytes are reserved
3799
 
  for data. For a VARCHAR(n) the max field length is n. If the stored
3800
 
  value is the SQL NULL then these data bytes are set to 0.
3801
 
 
3802
 
  4. We always use a 2 byte length for a true >= 5.0.3 VARCHAR. Note that
3803
 
  in the MySQL row format, the length is stored in 1 or 2 bytes,
3804
 
  depending on the maximum allowed length. But in the MySQL key value
3805
 
  format, the length always takes 2 bytes.
3806
 
 
3807
 
  We have to zero-fill the buffer so that MySQL is able to use a
3808
 
  simple memcmp to compare two key values to determine if they are
3809
 
  equal. MySQL does this to compare contents of two 'ref' values. */
3810
 
 
3811
 
  bzero(buff, buff_len);
3812
 
 
3813
 
  for (; key_part != end; key_part++) {
3814
 
    is_null = FALSE;
3815
 
 
3816
 
    if (key_part->null_bit) {
3817
 
      if (record[key_part->null_offset]
3818
 
            & key_part->null_bit) {
3819
 
        *buff = 1;
3820
 
        is_null = TRUE;
3821
 
      } else {
3822
 
        *buff = 0;
3823
 
      }
3824
 
      buff++;
3825
 
    }
3826
 
 
3827
 
    field = key_part->field;
3828
 
    mysql_type = field->type();
3829
 
 
3830
 
    if (mysql_type == DRIZZLE_TYPE_VARCHAR) {
3831
 
            /* >= 5.0.3 true VARCHAR */
3832
 
      ulint   lenlen;
3833
 
      ulint   len;
3834
 
      const byte* data;
3835
 
      ulint   key_len;
3836
 
      ulint   true_len;
3837
 
      const CHARSET_INFO* cs;
3838
 
      int   error=0;
3839
 
 
3840
 
      key_len = key_part->length;
3841
 
 
3842
 
      if (is_null) {
3843
 
        buff += key_len + 2;
3844
 
 
3845
 
        continue;
3846
 
      }
3847
 
      cs = field->charset();
3848
 
 
3849
 
      lenlen = (ulint)
3850
 
        (((Field_varstring*)field)->pack_length_no_ptr());
3851
 
 
3852
 
      data = row_mysql_read_true_varchar(&len,
3853
 
        (byte*) (record
3854
 
        + (ulint)get_field_offset(getTable(), field)),
3855
 
        lenlen);
3856
 
 
3857
 
      true_len = len;
3858
 
 
3859
 
      /* For multi byte character sets we need to calculate
3860
 
      the true length of the key */
3861
 
 
3862
 
      if (len > 0 && cs->mbmaxlen > 1) {
3863
 
        true_len = (ulint) cs->cset->well_formed_len(cs,
3864
 
            (const char *) data,
3865
 
            (const char *) data + len,
3866
 
                                                (uint) (key_len /
3867
 
                                                        cs->mbmaxlen),
3868
 
            &error);
3869
 
      }
3870
 
 
3871
 
      /* In a column prefix index, we may need to truncate
3872
 
      the stored value: */
3873
 
 
3874
 
      if (true_len > key_len) {
3875
 
        true_len = key_len;
3876
 
      }
3877
 
 
3878
 
      /* The length in a key value is always stored in 2
3879
 
      bytes */
3880
 
 
3881
 
      row_mysql_store_true_var_len((byte*)buff, true_len, 2);
3882
 
      buff += 2;
3883
 
 
3884
 
      memcpy(buff, data, true_len);
3885
 
 
3886
 
      /* Note that we always reserve the maximum possible
3887
 
      length of the true VARCHAR in the key value, though
3888
 
      only len first bytes after the 2 length bytes contain
3889
 
      actual data. The rest of the space was reset to zero
3890
 
      in the bzero() call above. */
3891
 
 
3892
 
      buff += key_len;
3893
 
 
3894
 
    } else if (mysql_type == DRIZZLE_TYPE_BLOB) {
3895
 
 
3896
 
      const CHARSET_INFO* cs;
3897
 
      ulint   key_len;
3898
 
      ulint   true_len;
3899
 
      int   error=0;
3900
 
      ulint   blob_len;
3901
 
      const byte* blob_data;
3902
 
 
3903
 
      ut_a(key_part->key_part_flag & HA_PART_KEY_SEG);
3904
 
 
3905
 
      key_len = key_part->length;
3906
 
 
3907
 
      if (is_null) {
3908
 
        buff += key_len + 2;
3909
 
 
3910
 
        continue;
3911
 
      }
3912
 
 
3913
 
      cs = field->charset();
3914
 
 
3915
 
      blob_data = row_mysql_read_blob_ref(&blob_len,
3916
 
        (byte*) (record
3917
 
        + (ulint)get_field_offset(getTable(), field)),
3918
 
          (ulint) field->pack_length());
3919
 
 
3920
 
      true_len = blob_len;
3921
 
 
3922
 
      ut_a(get_field_offset(getTable(), field)
3923
 
        == key_part->offset);
3924
 
 
3925
 
      /* For multi byte character sets we need to calculate
3926
 
      the true length of the key */
3927
 
 
3928
 
      if (blob_len > 0 && cs->mbmaxlen > 1) {
3929
 
        true_len = (ulint) cs->cset->well_formed_len(cs,
3930
 
                                                     (const char *) blob_data,
3931
 
                                                     (const char *) blob_data
3932
 
                                                     + blob_len,
3933
 
                                                     (uint) (key_len /
3934
 
                                                             cs->mbmaxlen),
3935
 
                                                     &error);
3936
 
      }
3937
 
 
3938
 
      /* All indexes on BLOB and TEXT are column prefix
3939
 
      indexes, and we may need to truncate the data to be
3940
 
      stored in the key value: */
3941
 
 
3942
 
      if (true_len > key_len) {
3943
 
        true_len = key_len;
3944
 
      }
3945
 
 
3946
 
      /* MySQL reserves 2 bytes for the length and the
3947
 
      storage of the number is little-endian */
3948
 
 
3949
 
      innobase_write_to_2_little_endian(
3950
 
          (byte*)buff, true_len);
3951
 
      buff += 2;
3952
 
 
3953
 
      memcpy(buff, blob_data, true_len);
3954
 
 
3955
 
      /* Note that we always reserve the maximum possible
3956
 
      length of the BLOB prefix in the key value. */
3957
 
 
3958
 
      buff += key_len;
3959
 
    } else {
3960
 
      /* Here we handle all other data types except the
3961
 
      true VARCHAR, BLOB and TEXT. Note that the column
3962
 
      value we store may be also in a column prefix
3963
 
      index. */
3964
 
 
3965
 
      ulint     true_len;
3966
 
      ulint     key_len;
3967
 
      const unsigned char*    src_start;
3968
 
      enum_field_types  real_type;
3969
 
 
3970
 
      key_len = key_part->length;
3971
 
 
3972
 
      if (is_null) {
3973
 
         buff += key_len;
3974
 
 
3975
 
         continue;
3976
 
      }
3977
 
 
3978
 
      src_start = record + key_part->offset;
3979
 
      real_type = field->real_type();
3980
 
      true_len = key_len;
3981
 
 
3982
 
      /* Character set for the field is defined only
3983
 
      to fields whose type is string and real field
3984
 
      type is not enum or set. For these fields check
3985
 
      if character set is multi byte. */
3986
 
 
3987
 
      memcpy(buff, src_start, true_len);
3988
 
      buff += true_len;
3989
 
 
3990
 
      /* Pad the unused space with spaces. Note that no
3991
 
      padding is ever needed for UCS-2 because in MySQL,
3992
 
      all UCS2 characters are 2 bytes, as MySQL does not
3993
 
      support surrogate pairs, which are needed to represent
3994
 
      characters in the range U+10000 to U+10FFFF. */
3995
 
 
3996
 
      if (true_len < key_len) {
3997
 
        ulint pad_len = key_len - true_len;
3998
 
        memset(buff, ' ', pad_len);
3999
 
        buff += pad_len;
4000
 
      }
4001
 
    }
4002
 
  }
4003
 
 
4004
 
  ut_a(buff <= buff_start + buff_len);
4005
 
 
4006
 
  return((uint)(buff - buff_start));
 
3179
        KEY*            key_info        = table->key_info + keynr;
 
3180
        KEY_PART_INFO*  key_part        = key_info->key_part;
 
3181
        KEY_PART_INFO*  end             = key_part + key_info->key_parts;
 
3182
        char*           buff_start      = buff;
 
3183
        enum_field_types mysql_type;
 
3184
        Field*          field;
 
3185
        ibool           is_null;
 
3186
 
 
3187
        /* The format for storing a key field in MySQL is the following:
 
3188
 
 
3189
        1. If the column can be NULL, then in the first byte we put 1 if the
 
3190
        field value is NULL, 0 otherwise.
 
3191
 
 
3192
        2. If the column is of a BLOB type (it must be a column prefix field
 
3193
        in this case), then we put the length of the data in the field to the
 
3194
        next 2 bytes, in the little-endian format. If the field is SQL NULL,
 
3195
        then these 2 bytes are set to 0. Note that the length of data in the
 
3196
        field is <= column prefix length.
 
3197
 
 
3198
        3. In a column prefix field, prefix_len next bytes are reserved for
 
3199
        data. In a normal field the max field length next bytes are reserved
 
3200
        for data. For a VARCHAR(n) the max field length is n. If the stored
 
3201
        value is the SQL NULL then these data bytes are set to 0.
 
3202
 
 
3203
        4. We always use a 2 byte length for a true >= 5.0.3 VARCHAR. Note that
 
3204
        in the MySQL row format, the length is stored in 1 or 2 bytes,
 
3205
        depending on the maximum allowed length. But in the MySQL key value
 
3206
        format, the length always takes 2 bytes.
 
3207
 
 
3208
        We have to zero-fill the buffer so that MySQL is able to use a
 
3209
        simple memcmp to compare two key values to determine if they are
 
3210
        equal. MySQL does this to compare contents of two 'ref' values. */
 
3211
 
 
3212
        bzero(buff, buff_len);
 
3213
 
 
3214
        for (; key_part != end; key_part++) {
 
3215
                is_null = FALSE;
 
3216
 
 
3217
                if (key_part->null_bit) {
 
3218
                        if (record[key_part->null_offset]
 
3219
                                                & key_part->null_bit) {
 
3220
                                *buff = 1;
 
3221
                                is_null = TRUE;
 
3222
                        } else {
 
3223
                                *buff = 0;
 
3224
                        }
 
3225
                        buff++;
 
3226
                }
 
3227
 
 
3228
                field = key_part->field;
 
3229
                mysql_type = field->type();
 
3230
 
 
3231
                if (mysql_type == DRIZZLE_TYPE_VARCHAR) {
 
3232
                                                /* >= 5.0.3 true VARCHAR */
 
3233
                        ulint           lenlen;
 
3234
                        ulint           len;
 
3235
                        const byte*     data;
 
3236
                        ulint           key_len;
 
3237
                        ulint           true_len;
 
3238
                        const CHARSET_INFO*     cs;
 
3239
                        int             error=0;
 
3240
 
 
3241
                        key_len = key_part->length;
 
3242
 
 
3243
                        if (is_null) {
 
3244
                                buff += key_len + 2;
 
3245
 
 
3246
                                continue;
 
3247
                        }
 
3248
                        cs = field->charset();
 
3249
 
 
3250
                        lenlen = (ulint)
 
3251
                                (((Field_varstring*)field)->length_bytes);
 
3252
 
 
3253
                        data = row_mysql_read_true_varchar(&len,
 
3254
                                (byte*) (record
 
3255
                                + (ulint)get_field_offset(table, field)),
 
3256
                                lenlen);
 
3257
 
 
3258
                        true_len = len;
 
3259
 
 
3260
                        /* For multi byte character sets we need to calculate
 
3261
                        the true length of the key */
 
3262
 
 
3263
                        if (len > 0 && cs->mbmaxlen > 1) {
 
3264
                                true_len = (ulint) cs->cset->well_formed_len(cs,
 
3265
                                                (const char *) data,
 
3266
                                                (const char *) data + len,
 
3267
                                                (uint) (key_len /
 
3268
                                                        cs->mbmaxlen),
 
3269
                                                &error);
 
3270
                        }
 
3271
 
 
3272
                        /* In a column prefix index, we may need to truncate
 
3273
                        the stored value: */
 
3274
 
 
3275
                        if (true_len > key_len) {
 
3276
                                true_len = key_len;
 
3277
                        }
 
3278
 
 
3279
                        /* The length in a key value is always stored in 2
 
3280
                        bytes */
 
3281
 
 
3282
                        row_mysql_store_true_var_len((byte*)buff, true_len, 2);
 
3283
                        buff += 2;
 
3284
 
 
3285
                        memcpy(buff, data, true_len);
 
3286
 
 
3287
                        /* Note that we always reserve the maximum possible
 
3288
                        length of the true VARCHAR in the key value, though
 
3289
                        only len first bytes after the 2 length bytes contain
 
3290
                        actual data. The rest of the space was reset to zero
 
3291
                        in the bzero() call above. */
 
3292
 
 
3293
                        buff += key_len;
 
3294
 
 
3295
                } else if (mysql_type == DRIZZLE_TYPE_BLOB) {
 
3296
 
 
3297
                        const CHARSET_INFO*     cs;
 
3298
                        ulint           key_len;
 
3299
                        ulint           true_len;
 
3300
                        int             error=0;
 
3301
                        ulint           blob_len;
 
3302
                        const byte*     blob_data;
 
3303
 
 
3304
                        ut_a(key_part->key_part_flag & HA_PART_KEY_SEG);
 
3305
 
 
3306
                        key_len = key_part->length;
 
3307
 
 
3308
                        if (is_null) {
 
3309
                                buff += key_len + 2;
 
3310
 
 
3311
                                continue;
 
3312
                        }
 
3313
 
 
3314
                        cs = field->charset();
 
3315
 
 
3316
                        blob_data = row_mysql_read_blob_ref(&blob_len,
 
3317
                                (byte*) (record
 
3318
                                + (ulint)get_field_offset(table, field)),
 
3319
                                        (ulint) field->pack_length());
 
3320
 
 
3321
                        true_len = blob_len;
 
3322
 
 
3323
                        ut_a(get_field_offset(table, field)
 
3324
                                == key_part->offset);
 
3325
 
 
3326
                        /* For multi byte character sets we need to calculate
 
3327
                        the true length of the key */
 
3328
 
 
3329
                        if (blob_len > 0 && cs->mbmaxlen > 1) {
 
3330
                                true_len = (ulint) cs->cset->well_formed_len(cs,
 
3331
                                                (const char *) blob_data,
 
3332
                                                (const char *) blob_data
 
3333
                                                        + blob_len,
 
3334
                                                (uint) (key_len /
 
3335
                                                        cs->mbmaxlen),
 
3336
                                                &error);
 
3337
                        }
 
3338
 
 
3339
                        /* All indexes on BLOB and TEXT are column prefix
 
3340
                        indexes, and we may need to truncate the data to be
 
3341
                        stored in the key value: */
 
3342
 
 
3343
                        if (true_len > key_len) {
 
3344
                                true_len = key_len;
 
3345
                        }
 
3346
 
 
3347
                        /* MySQL reserves 2 bytes for the length and the
 
3348
                        storage of the number is little-endian */
 
3349
 
 
3350
                        innobase_write_to_2_little_endian(
 
3351
                                        (byte*)buff, true_len);
 
3352
                        buff += 2;
 
3353
 
 
3354
                        memcpy(buff, blob_data, true_len);
 
3355
 
 
3356
                        /* Note that we always reserve the maximum possible
 
3357
                        length of the BLOB prefix in the key value. */
 
3358
 
 
3359
                        buff += key_len;
 
3360
                } else {
 
3361
                        /* Here we handle all other data types except the
 
3362
                        true VARCHAR, BLOB and TEXT. Note that the column
 
3363
                        value we store may be also in a column prefix
 
3364
                        index. */
 
3365
 
 
3366
                        ulint                   true_len;
 
3367
                        ulint                   key_len;
 
3368
                        const unsigned char*            src_start;
 
3369
                        enum_field_types        real_type;
 
3370
 
 
3371
                        key_len = key_part->length;
 
3372
 
 
3373
                        if (is_null) {
 
3374
                                 buff += key_len;
 
3375
 
 
3376
                                 continue;
 
3377
                        }
 
3378
 
 
3379
                        src_start = record + key_part->offset;
 
3380
                        real_type = field->real_type();
 
3381
                        true_len = key_len;
 
3382
 
 
3383
                        /* Character set for the field is defined only
 
3384
                        to fields whose type is string and real field
 
3385
                        type is not enum or set. For these fields check
 
3386
                        if character set is multi byte. */
 
3387
 
 
3388
                        memcpy(buff, src_start, true_len);
 
3389
                        buff += true_len;
 
3390
 
 
3391
                        /* Pad the unused space with spaces. Note that no
 
3392
                        padding is ever needed for UCS-2 because in MySQL,
 
3393
                        all UCS2 characters are 2 bytes, as MySQL does not
 
3394
                        support surrogate pairs, which are needed to represent
 
3395
                        characters in the range U+10000 to U+10FFFF. */
 
3396
 
 
3397
                        if (true_len < key_len) {
 
3398
                                ulint pad_len = key_len - true_len;
 
3399
                                memset(buff, ' ', pad_len);
 
3400
                                buff += pad_len;
 
3401
                        }
 
3402
                }
 
3403
        }
 
3404
 
 
3405
        ut_a(buff <= buff_start + buff_len);
 
3406
 
 
3407
        return((uint)(buff - buff_start));
4007
3408
}
4008
3409
 
4009
3410
/**************************************************************//**
4013
3414
void
4014
3415
build_template(
4015
3416
/*===========*/
4016
 
  row_prebuilt_t* prebuilt, /*!< in/out: prebuilt struct */
4017
 
  Session*  ,   /*!< in: current user thread, used
4018
 
          only if templ_type is
4019
 
          ROW_DRIZZLE_REC_FIELDS */
4020
 
  Table*    table,    /*!< in: MySQL table */
4021
 
  uint    templ_type) /*!< in: ROW_MYSQL_WHOLE_ROW or
4022
 
          ROW_DRIZZLE_REC_FIELDS */
 
3417
        row_prebuilt_t* prebuilt,       /*!< in/out: prebuilt struct */
 
3418
        Session*        ,               /*!< in: current user thread, used
 
3419
                                        only if templ_type is
 
3420
                                        ROW_DRIZZLE_REC_FIELDS */
 
3421
        Table*          table,          /*!< in: MySQL table */
 
3422
        uint            templ_type)     /*!< in: ROW_MYSQL_WHOLE_ROW or
 
3423
                                        ROW_DRIZZLE_REC_FIELDS */
4023
3424
{
4024
 
  dict_index_t* index;
4025
 
  dict_index_t* clust_index;
4026
 
  mysql_row_templ_t* templ;
4027
 
  Field*    field;
4028
 
  ulint   n_fields;
4029
 
  ulint   n_requested_fields  = 0;
4030
 
  ibool   fetch_all_in_key  = FALSE;
4031
 
  ibool   fetch_primary_key_cols  = FALSE;
4032
 
  ulint   i= 0;
4033
 
  /* byte offset of the end of last requested column */
4034
 
  ulint   mysql_prefix_len  = 0;
4035
 
 
4036
 
  if (prebuilt->select_lock_type == LOCK_X) {
4037
 
    /* We always retrieve the whole clustered index record if we
4038
 
    use exclusive row level locks, for example, if the read is
4039
 
    done in an UPDATE statement. */
4040
 
 
4041
 
    templ_type = ROW_MYSQL_WHOLE_ROW;
4042
 
  }
4043
 
 
4044
 
  if (templ_type == ROW_MYSQL_REC_FIELDS) {
4045
 
    if (prebuilt->hint_need_to_fetch_extra_cols
4046
 
      == ROW_RETRIEVE_ALL_COLS) {
4047
 
 
4048
 
      /* We know we must at least fetch all columns in the
4049
 
      key, or all columns in the table */
4050
 
 
4051
 
      if (prebuilt->read_just_key) {
4052
 
        /* MySQL has instructed us that it is enough
4053
 
        to fetch the columns in the key; looks like
4054
 
        MySQL can set this flag also when there is
4055
 
        only a prefix of the column in the key: in
4056
 
        that case we retrieve the whole column from
4057
 
        the clustered index */
4058
 
 
4059
 
        fetch_all_in_key = TRUE;
4060
 
      } else {
4061
 
        templ_type = ROW_MYSQL_WHOLE_ROW;
4062
 
      }
4063
 
    } else if (prebuilt->hint_need_to_fetch_extra_cols
4064
 
      == ROW_RETRIEVE_PRIMARY_KEY) {
4065
 
      /* We must at least fetch all primary key cols. Note
4066
 
         that if the clustered index was internally generated
4067
 
         by InnoDB on the row id (no primary key was
4068
 
         defined), then row_search_for_mysql() will always
4069
 
         retrieve the row id to a special buffer in the
4070
 
         prebuilt struct. */
4071
 
 
4072
 
      fetch_primary_key_cols = TRUE;
4073
 
    }
4074
 
  }
4075
 
 
4076
 
  clust_index = dict_table_get_first_index(prebuilt->table);
4077
 
 
4078
 
  if (templ_type == ROW_MYSQL_REC_FIELDS) {
4079
 
    index = prebuilt->index;
4080
 
  } else {
4081
 
    index = clust_index;
4082
 
  }
4083
 
 
4084
 
  if (index == clust_index) {
4085
 
    prebuilt->need_to_access_clustered = TRUE;
4086
 
  } else {
4087
 
    prebuilt->need_to_access_clustered = FALSE;
4088
 
    /* Below we check column by column if we need to access
4089
 
    the clustered index */
4090
 
  }
4091
 
 
4092
 
  n_fields = (ulint)table->getShare()->sizeFields(); /* number of columns */
4093
 
 
4094
 
  if (!prebuilt->mysql_template) {
4095
 
    prebuilt->mysql_template = (mysql_row_templ_t*)
4096
 
      mem_alloc(n_fields * sizeof(mysql_row_templ_t));
4097
 
  }
4098
 
 
4099
 
  prebuilt->template_type = templ_type;
4100
 
  prebuilt->null_bitmap_len = table->getShare()->null_bytes;
4101
 
 
4102
 
  prebuilt->templ_contains_blob = FALSE;
4103
 
 
4104
 
  /* Note that in InnoDB, i is the column number. MySQL calls columns
4105
 
  'fields'. */
4106
 
  for (i = 0; i < n_fields; i++) 
4107
 
  {
4108
 
    templ = prebuilt->mysql_template + n_requested_fields;
4109
 
    field = table->getField(i);
4110
 
 
4111
 
    if (UNIV_LIKELY(templ_type == ROW_MYSQL_REC_FIELDS)) {
4112
 
      /* Decide which columns we should fetch
4113
 
      and which we can skip. */
4114
 
      register const ibool  index_contains_field =
4115
 
        dict_index_contains_col_or_prefix(index, i);
4116
 
 
4117
 
      if (!index_contains_field && prebuilt->read_just_key) {
4118
 
        /* If this is a 'key read', we do not need
4119
 
        columns that are not in the key */
4120
 
 
4121
 
        goto skip_field;
4122
 
      }
4123
 
 
4124
 
      if (index_contains_field && fetch_all_in_key) {
4125
 
        /* This field is needed in the query */
4126
 
 
4127
 
        goto include_field;
4128
 
      }
 
3425
        dict_index_t*   index;
 
3426
        dict_index_t*   clust_index;
 
3427
        mysql_row_templ_t* templ;
 
3428
        Field*          field;
 
3429
        ulint           n_fields;
 
3430
        ulint           n_requested_fields      = 0;
 
3431
        ibool           fetch_all_in_key        = FALSE;
 
3432
        ibool           fetch_primary_key_cols  = FALSE;
 
3433
        ulint           i= 0;
 
3434
        /* byte offset of the end of last requested column */
 
3435
        ulint           mysql_prefix_len        = 0;
 
3436
 
 
3437
        if (prebuilt->select_lock_type == LOCK_X) {
 
3438
                /* We always retrieve the whole clustered index record if we
 
3439
                use exclusive row level locks, for example, if the read is
 
3440
                done in an UPDATE statement. */
 
3441
 
 
3442
                templ_type = ROW_MYSQL_WHOLE_ROW;
 
3443
        }
 
3444
 
 
3445
        if (templ_type == ROW_MYSQL_REC_FIELDS) {
 
3446
                if (prebuilt->hint_need_to_fetch_extra_cols
 
3447
                        == ROW_RETRIEVE_ALL_COLS) {
 
3448
 
 
3449
                        /* We know we must at least fetch all columns in the
 
3450
                        key, or all columns in the table */
 
3451
 
 
3452
                        if (prebuilt->read_just_key) {
 
3453
                                /* MySQL has instructed us that it is enough
 
3454
                                to fetch the columns in the key; looks like
 
3455
                                MySQL can set this flag also when there is
 
3456
                                only a prefix of the column in the key: in
 
3457
                                that case we retrieve the whole column from
 
3458
                                the clustered index */
 
3459
 
 
3460
                                fetch_all_in_key = TRUE;
 
3461
                        } else {
 
3462
                                templ_type = ROW_MYSQL_WHOLE_ROW;
 
3463
                        }
 
3464
                } else if (prebuilt->hint_need_to_fetch_extra_cols
 
3465
                        == ROW_RETRIEVE_PRIMARY_KEY) {
 
3466
                        /* We must at least fetch all primary key cols. Note
 
3467
                           that if the clustered index was internally generated
 
3468
                           by InnoDB on the row id (no primary key was
 
3469
                           defined), then row_search_for_mysql() will always
 
3470
                           retrieve the row id to a special buffer in the
 
3471
                           prebuilt struct. */
 
3472
 
 
3473
                        fetch_primary_key_cols = TRUE;
 
3474
                }
 
3475
        }
 
3476
 
 
3477
        clust_index = dict_table_get_first_index(prebuilt->table);
 
3478
 
 
3479
        if (templ_type == ROW_MYSQL_REC_FIELDS) {
 
3480
                index = prebuilt->index;
 
3481
        } else {
 
3482
                index = clust_index;
 
3483
        }
 
3484
 
 
3485
        if (index == clust_index) {
 
3486
                prebuilt->need_to_access_clustered = TRUE;
 
3487
        } else {
 
3488
                prebuilt->need_to_access_clustered = FALSE;
 
3489
                /* Below we check column by column if we need to access
 
3490
                the clustered index */
 
3491
        }
 
3492
 
 
3493
        n_fields = (ulint)table->s->fields; /* number of columns */
 
3494
 
 
3495
        if (!prebuilt->mysql_template) {
 
3496
                prebuilt->mysql_template = (mysql_row_templ_t*)
 
3497
                        mem_alloc(n_fields * sizeof(mysql_row_templ_t));
 
3498
        }
 
3499
 
 
3500
        prebuilt->template_type = templ_type;
 
3501
        prebuilt->null_bitmap_len = table->s->null_bytes;
 
3502
 
 
3503
        prebuilt->templ_contains_blob = FALSE;
 
3504
 
 
3505
        /* Note that in InnoDB, i is the column number. MySQL calls columns
 
3506
        'fields'. */
 
3507
        for (i = 0; i < n_fields; i++) {
 
3508
                templ = prebuilt->mysql_template + n_requested_fields;
 
3509
                field = table->field[i];
 
3510
 
 
3511
                if (UNIV_LIKELY(templ_type == ROW_MYSQL_REC_FIELDS)) {
 
3512
                        /* Decide which columns we should fetch
 
3513
                        and which we can skip. */
 
3514
                        register const ibool    index_contains_field =
 
3515
                                dict_index_contains_col_or_prefix(index, i);
 
3516
 
 
3517
                        if (!index_contains_field && prebuilt->read_just_key) {
 
3518
                                /* If this is a 'key read', we do not need
 
3519
                                columns that are not in the key */
 
3520
 
 
3521
                                goto skip_field;
 
3522
                        }
 
3523
 
 
3524
                        if (index_contains_field && fetch_all_in_key) {
 
3525
                                /* This field is needed in the query */
 
3526
 
 
3527
                                goto include_field;
 
3528
                        }
4129
3529
 
4130
3530
                        if (field->isReadSet() || field->isWriteSet())
4131
 
        /* This field is needed in the query */
4132
 
        goto include_field;
 
3531
                                /* This field is needed in the query */
 
3532
                                goto include_field;
4133
3533
 
4134
3534
                        assert(table->isReadSet(i) == field->isReadSet());
4135
3535
                        assert(table->isWriteSet(i) == field->isWriteSet());
4136
3536
 
4137
 
      if (fetch_primary_key_cols
4138
 
        && dict_table_col_in_clustered_key(
4139
 
          index->table, i)) {
4140
 
        /* This field is needed in the query */
4141
 
 
4142
 
        goto include_field;
4143
 
      }
4144
 
 
4145
 
      /* This field is not needed in the query, skip it */
4146
 
 
4147
 
      goto skip_field;
4148
 
    }
 
3537
                        if (fetch_primary_key_cols
 
3538
                                && dict_table_col_in_clustered_key(
 
3539
                                        index->table, i)) {
 
3540
                                /* This field is needed in the query */
 
3541
 
 
3542
                                goto include_field;
 
3543
                        }
 
3544
 
 
3545
                        /* This field is not needed in the query, skip it */
 
3546
 
 
3547
                        goto skip_field;
 
3548
                }
4149
3549
include_field:
4150
 
    n_requested_fields++;
4151
 
 
4152
 
    templ->col_no = i;
4153
 
 
4154
 
    if (index == clust_index) {
4155
 
      templ->rec_field_no = dict_col_get_clust_pos(
4156
 
        &index->table->cols[i], index);
4157
 
    } else {
4158
 
      templ->rec_field_no = dict_index_get_nth_col_pos(
4159
 
                index, i);
4160
 
    }
4161
 
 
4162
 
    if (templ->rec_field_no == ULINT_UNDEFINED) {
4163
 
      prebuilt->need_to_access_clustered = TRUE;
4164
 
    }
4165
 
 
4166
 
    if (field->null_ptr) {
4167
 
      templ->mysql_null_byte_offset =
4168
 
        (ulint) ((char*) field->null_ptr
4169
 
          - (char*) table->getInsertRecord());
4170
 
 
4171
 
      templ->mysql_null_bit_mask = (ulint) field->null_bit;
4172
 
    } else {
4173
 
      templ->mysql_null_bit_mask = 0;
4174
 
    }
4175
 
 
4176
 
    templ->mysql_col_offset = (ulint)
4177
 
          get_field_offset(table, field);
4178
 
 
4179
 
    templ->mysql_col_len = (ulint) field->pack_length();
4180
 
    if (mysql_prefix_len < templ->mysql_col_offset
4181
 
        + templ->mysql_col_len) {
4182
 
      mysql_prefix_len = templ->mysql_col_offset
4183
 
        + templ->mysql_col_len;
4184
 
    }
4185
 
    templ->type = index->table->cols[i].mtype;
4186
 
    templ->mysql_type = (ulint)field->type();
4187
 
 
4188
 
    if (templ->mysql_type == DATA_MYSQL_TRUE_VARCHAR) {
4189
 
      templ->mysql_length_bytes = (ulint)
4190
 
        (((Field_varstring*)field)->pack_length_no_ptr());
4191
 
    }
4192
 
 
4193
 
    templ->charset = dtype_get_charset_coll(
4194
 
      index->table->cols[i].prtype);
4195
 
    templ->mbminlen = index->table->cols[i].mbminlen;
4196
 
    templ->mbmaxlen = index->table->cols[i].mbmaxlen;
4197
 
    templ->is_unsigned = index->table->cols[i].prtype
4198
 
              & DATA_UNSIGNED;
4199
 
    if (templ->type == DATA_BLOB) {
4200
 
      prebuilt->templ_contains_blob = TRUE;
4201
 
    }
 
3550
                n_requested_fields++;
 
3551
 
 
3552
                templ->col_no = i;
 
3553
 
 
3554
                if (index == clust_index) {
 
3555
                        templ->rec_field_no = dict_col_get_clust_pos(
 
3556
                                &index->table->cols[i], index);
 
3557
                } else {
 
3558
                        templ->rec_field_no = dict_index_get_nth_col_pos(
 
3559
                                                                index, i);
 
3560
                }
 
3561
 
 
3562
                if (templ->rec_field_no == ULINT_UNDEFINED) {
 
3563
                        prebuilt->need_to_access_clustered = TRUE;
 
3564
                }
 
3565
 
 
3566
                if (field->null_ptr) {
 
3567
                        templ->mysql_null_byte_offset =
 
3568
                                (ulint) ((char*) field->null_ptr
 
3569
                                        - (char*) table->record[0]);
 
3570
 
 
3571
                        templ->mysql_null_bit_mask = (ulint) field->null_bit;
 
3572
                } else {
 
3573
                        templ->mysql_null_bit_mask = 0;
 
3574
                }
 
3575
 
 
3576
                templ->mysql_col_offset = (ulint)
 
3577
                                        get_field_offset(table, field);
 
3578
 
 
3579
                templ->mysql_col_len = (ulint) field->pack_length();
 
3580
                if (mysql_prefix_len < templ->mysql_col_offset
 
3581
                                + templ->mysql_col_len) {
 
3582
                        mysql_prefix_len = templ->mysql_col_offset
 
3583
                                + templ->mysql_col_len;
 
3584
                }
 
3585
                templ->type = index->table->cols[i].mtype;
 
3586
                templ->mysql_type = (ulint)field->type();
 
3587
 
 
3588
                if (templ->mysql_type == DATA_MYSQL_TRUE_VARCHAR) {
 
3589
                        templ->mysql_length_bytes = (ulint)
 
3590
                                (((Field_varstring*)field)->length_bytes);
 
3591
                }
 
3592
 
 
3593
                templ->charset = dtype_get_charset_coll(
 
3594
                        index->table->cols[i].prtype);
 
3595
                templ->mbminlen = index->table->cols[i].mbminlen;
 
3596
                templ->mbmaxlen = index->table->cols[i].mbmaxlen;
 
3597
                templ->is_unsigned = index->table->cols[i].prtype
 
3598
                                                        & DATA_UNSIGNED;
 
3599
                if (templ->type == DATA_BLOB) {
 
3600
                        prebuilt->templ_contains_blob = TRUE;
 
3601
                }
4202
3602
skip_field:
4203
 
    ;
4204
 
  }
4205
 
 
4206
 
  prebuilt->n_template = n_requested_fields;
4207
 
  prebuilt->mysql_prefix_len = mysql_prefix_len;
4208
 
 
4209
 
  if (index != clust_index && prebuilt->need_to_access_clustered) {
4210
 
    /* Change rec_field_no's to correspond to the clustered index
4211
 
    record */
4212
 
    for (i = 0; i < n_requested_fields; i++) {
4213
 
      templ = prebuilt->mysql_template + i;
4214
 
 
4215
 
      templ->rec_field_no = dict_col_get_clust_pos(
4216
 
        &index->table->cols[templ->col_no],
4217
 
        clust_index);
4218
 
    }
4219
 
  }
 
3603
                ;
 
3604
        }
 
3605
 
 
3606
        prebuilt->n_template = n_requested_fields;
 
3607
        prebuilt->mysql_prefix_len = mysql_prefix_len;
 
3608
 
 
3609
        if (index != clust_index && prebuilt->need_to_access_clustered) {
 
3610
                /* Change rec_field_no's to correspond to the clustered index
 
3611
                record */
 
3612
                for (i = 0; i < n_requested_fields; i++) {
 
3613
                        templ = prebuilt->mysql_template + i;
 
3614
 
 
3615
                        templ->rec_field_no = dict_col_get_clust_pos(
 
3616
                                &index->table->cols[templ->col_no],
 
3617
                                clust_index);
 
3618
                }
 
3619
        }
 
3620
}
 
3621
 
 
3622
/********************************************************************//**
 
3623
Get the upper limit of the MySQL integral and floating-point type. */
 
3624
UNIV_INTERN
 
3625
uint64_t
 
3626
ha_innobase::innobase_get_int_col_max_value(
 
3627
/*========================================*/
 
3628
        const Field*    field)
 
3629
{
 
3630
        uint64_t        max_value = 0;
 
3631
 
 
3632
        switch(field->key_type()) {
 
3633
        /* TINY */
 
3634
        case HA_KEYTYPE_BINARY:
 
3635
                max_value = 0xFFULL;
 
3636
                break;
 
3637
        /* MEDIUM */
 
3638
        case HA_KEYTYPE_UINT24:
 
3639
                max_value = 0xFFFFFFULL;
 
3640
                break;
 
3641
        /* LONG */
 
3642
        case HA_KEYTYPE_ULONG_INT:
 
3643
                max_value = 0xFFFFFFFFULL;
 
3644
                break;
 
3645
        case HA_KEYTYPE_LONG_INT:
 
3646
                max_value = 0x7FFFFFFFULL;
 
3647
                break;
 
3648
        /* BIG */
 
3649
        case HA_KEYTYPE_ULONGLONG:
 
3650
                max_value = 0xFFFFFFFFFFFFFFFFULL;
 
3651
                break;
 
3652
        case HA_KEYTYPE_LONGLONG:
 
3653
                max_value = 0x7FFFFFFFFFFFFFFFULL;
 
3654
                break;
 
3655
        case HA_KEYTYPE_DOUBLE:
 
3656
                /* We use the maximum as per IEEE754-2008 standard, 2^53 */
 
3657
                max_value = 0x20000000000000ULL;
 
3658
                break;
 
3659
        default:
 
3660
                ut_error;
 
3661
        }
 
3662
 
 
3663
        return(max_value);
4220
3664
}
4221
3665
 
4222
3666
/********************************************************************//**
4225
3669
INSERT ... SELECT type of statements, since MySQL binlog only stores the
4226
3670
min value of the autoinc interval. Once that is fixed we can get rid of
4227
3671
the special lock handling.
4228
 
@return DB_SUCCESS if all OK else error code */
 
3672
@return DB_SUCCESS if all OK else error code */
4229
3673
UNIV_INTERN
4230
3674
ulint
4231
3675
ha_innobase::innobase_lock_autoinc(void)
4232
3676
/*====================================*/
4233
3677
{
4234
 
  ulint   error = DB_SUCCESS;
4235
 
 
4236
 
  dict_table_autoinc_lock(prebuilt->table);
4237
 
 
4238
 
  return(ulong(error));
 
3678
        ulint           error = DB_SUCCESS;
 
3679
 
 
3680
        switch (innobase_autoinc_lock_mode) {
 
3681
        case AUTOINC_NO_LOCKING:
 
3682
                /* Acquire only the AUTOINC mutex. */
 
3683
                dict_table_autoinc_lock(prebuilt->table);
 
3684
                break;
 
3685
 
 
3686
        case AUTOINC_NEW_STYLE_LOCKING:
 
3687
                /* For simple (single/multi) row INSERTs, we fallback to the
 
3688
                old style only if another transaction has already acquired
 
3689
                the AUTOINC lock on behalf of a LOAD FILE or INSERT ... SELECT
 
3690
                etc. type of statement. */
 
3691
                if (session_sql_command(user_session) == SQLCOM_INSERT
 
3692
                    || session_sql_command(user_session) == SQLCOM_REPLACE) {
 
3693
                        dict_table_t*   d_table = prebuilt->table;
 
3694
 
 
3695
                        /* Acquire the AUTOINC mutex. */
 
3696
                        dict_table_autoinc_lock(d_table);
 
3697
 
 
3698
                        /* We need to check that another transaction isn't
 
3699
                        already holding the AUTOINC lock on the table. */
 
3700
                        if (d_table->n_waiting_or_granted_auto_inc_locks) {
 
3701
                                /* Release the mutex to avoid deadlocks. */
 
3702
                                dict_table_autoinc_unlock(d_table);
 
3703
                        } else {
 
3704
                                break;
 
3705
                        }
 
3706
                }
 
3707
                /* Fall through to old style locking. */
 
3708
 
 
3709
        case AUTOINC_OLD_STYLE_LOCKING:
 
3710
                error = row_lock_table_autoinc_for_mysql(prebuilt);
 
3711
 
 
3712
                if (error == DB_SUCCESS) {
 
3713
 
 
3714
                        /* Acquire the AUTOINC mutex. */
 
3715
                        dict_table_autoinc_lock(prebuilt->table);
 
3716
                }
 
3717
                break;
 
3718
 
 
3719
        default:
 
3720
                ut_error;
 
3721
        }
 
3722
 
 
3723
        return(ulong(error));
4239
3724
}
4240
3725
 
4241
3726
/********************************************************************//**
4242
3727
Reset the autoinc value in the table.
4243
 
@return DB_SUCCESS if all went well else error code */
 
3728
@return DB_SUCCESS if all went well else error code */
4244
3729
UNIV_INTERN
4245
3730
ulint
4246
3731
ha_innobase::innobase_reset_autoinc(
4247
3732
/*================================*/
4248
 
  uint64_t  autoinc)  /*!< in: value to store */
 
3733
        uint64_t        autoinc)        /*!< in: value to store */
4249
3734
{
4250
 
  dict_table_autoinc_lock(prebuilt->table);
4251
 
  dict_table_autoinc_initialize(prebuilt->table, autoinc);
4252
 
  dict_table_autoinc_unlock(prebuilt->table);
4253
 
 
4254
 
  return(ulong(DB_SUCCESS));
 
3735
        ulint           error;
 
3736
 
 
3737
        error = innobase_lock_autoinc();
 
3738
 
 
3739
        if (error == DB_SUCCESS) {
 
3740
 
 
3741
                dict_table_autoinc_initialize(prebuilt->table, autoinc);
 
3742
 
 
3743
                dict_table_autoinc_unlock(prebuilt->table);
 
3744
        }
 
3745
 
 
3746
        return(ulong(error));
4255
3747
}
4256
3748
 
4257
3749
/********************************************************************//**
4258
3750
Store the autoinc value in the table. The autoinc value is only set if
4259
3751
it's greater than the existing autoinc value in the table.
4260
 
@return DB_SUCCESS if all went well else error code */
 
3752
@return DB_SUCCESS if all went well else error code */
4261
3753
UNIV_INTERN
4262
3754
ulint
4263
3755
ha_innobase::innobase_set_max_autoinc(
4264
3756
/*==================================*/
4265
 
  uint64_t  auto_inc) /*!< in: value to store */
 
3757
        uint64_t        auto_inc)       /*!< in: value to store */
4266
3758
{
4267
 
  dict_table_autoinc_lock(prebuilt->table);
4268
 
  dict_table_autoinc_update_if_greater(prebuilt->table, auto_inc);
4269
 
  dict_table_autoinc_unlock(prebuilt->table);
4270
 
 
4271
 
  return(ulong(DB_SUCCESS));
 
3759
        ulint           error;
 
3760
 
 
3761
        error = innobase_lock_autoinc();
 
3762
 
 
3763
        if (error == DB_SUCCESS) {
 
3764
 
 
3765
                dict_table_autoinc_update_if_greater(prebuilt->table, auto_inc);
 
3766
 
 
3767
                dict_table_autoinc_unlock(prebuilt->table);
 
3768
        }
 
3769
 
 
3770
        return(ulong(error));
4272
3771
}
4273
3772
 
4274
3773
/********************************************************************//**
4275
3774
Stores a row in an InnoDB database, to the table specified in this
4276
3775
handle.
4277
 
@return error code */
 
3776
@return error code */
4278
3777
UNIV_INTERN
4279
3778
int
4280
 
ha_innobase::doInsertRecord(
 
3779
ha_innobase::write_row(
4281
3780
/*===================*/
4282
 
  unsigned char*  record) /*!< in: a row in MySQL format */
 
3781
        unsigned char*  record) /*!< in: a row in MySQL format */
4283
3782
{
4284
 
  ulint   error = 0;
 
3783
        ulint           error = 0;
4285
3784
        int             error_result= 0;
4286
 
  ibool   auto_inc_used= FALSE;
4287
 
  ulint   sql_command;
4288
 
  trx_t*    trx = session_to_trx(user_session);
4289
 
 
4290
 
  if (prebuilt->trx != trx) {
4291
 
    errmsg_printf(ERRMSG_LVL_ERROR, "The transaction object for the table handle is at "
4292
 
        "%p, but for the current thread it is at %p",
4293
 
        (const void*) prebuilt->trx, (const void*) trx);
4294
 
 
4295
 
    fputs("InnoDB: Dump of 200 bytes around prebuilt: ", stderr);
4296
 
    ut_print_buf(stderr, ((const byte*)prebuilt) - 100, 200);
4297
 
    fputs("\n"
4298
 
      "InnoDB: Dump of 200 bytes around ha_data: ",
4299
 
      stderr);
4300
 
    ut_print_buf(stderr, ((const byte*) trx) - 100, 200);
4301
 
    putc('\n', stderr);
4302
 
    ut_error;
4303
 
  }
4304
 
 
4305
 
  sql_command = session_sql_command(user_session);
4306
 
 
4307
 
  if ((sql_command == SQLCOM_ALTER_TABLE
4308
 
       || sql_command == SQLCOM_CREATE_INDEX
4309
 
       || sql_command == SQLCOM_DROP_INDEX)
4310
 
      && num_write_row >= 10000) {
4311
 
    /* ALTER TABLE is COMMITted at every 10000 copied rows.
4312
 
    The IX table lock for the original table has to be re-issued.
4313
 
    As this method will be called on a temporary table where the
4314
 
    contents of the original table is being copied to, it is
4315
 
    a bit tricky to determine the source table.  The cursor
4316
 
    position in the source table need not be adjusted after the
4317
 
    intermediate COMMIT, since writes by other transactions are
4318
 
    being blocked by a MySQL table lock TL_WRITE_ALLOW_READ. */
4319
 
 
4320
 
    dict_table_t* src_table;
4321
 
    enum lock_mode  mode;
4322
 
 
4323
 
    num_write_row = 0;
4324
 
 
4325
 
    /* Commit the transaction.  This will release the table
4326
 
    locks, so they have to be acquired again. */
4327
 
 
4328
 
    /* Altering an InnoDB table */
4329
 
    /* Get the source table. */
4330
 
    src_table = lock_get_src_table(
4331
 
        prebuilt->trx, prebuilt->table, &mode);
4332
 
    if (!src_table) {
 
3785
        ibool           auto_inc_used= FALSE;
 
3786
        ulint           sql_command;
 
3787
        trx_t*          trx = session_to_trx(user_session);
 
3788
 
 
3789
        if (prebuilt->trx != trx) {
 
3790
          errmsg_printf(ERRMSG_LVL_ERROR, "The transaction object for the table handle is at "
 
3791
                          "%p, but for the current thread it is at %p",
 
3792
                          (const void*) prebuilt->trx, (const void*) trx);
 
3793
 
 
3794
                fputs("InnoDB: Dump of 200 bytes around prebuilt: ", stderr);
 
3795
                ut_print_buf(stderr, ((const byte*)prebuilt) - 100, 200);
 
3796
                fputs("\n"
 
3797
                        "InnoDB: Dump of 200 bytes around ha_data: ",
 
3798
                        stderr);
 
3799
                ut_print_buf(stderr, ((const byte*) trx) - 100, 200);
 
3800
                putc('\n', stderr);
 
3801
                ut_error;
 
3802
        }
 
3803
 
 
3804
        ha_statistic_increment(&system_status_var::ha_write_count);
 
3805
 
 
3806
        sql_command = session_sql_command(user_session);
 
3807
 
 
3808
        if ((sql_command == SQLCOM_ALTER_TABLE
 
3809
             || sql_command == SQLCOM_CREATE_INDEX
 
3810
             || sql_command == SQLCOM_DROP_INDEX)
 
3811
            && num_write_row >= 10000) {
 
3812
                /* ALTER TABLE is COMMITted at every 10000 copied rows.
 
3813
                The IX table lock for the original table has to be re-issued.
 
3814
                As this method will be called on a temporary table where the
 
3815
                contents of the original table is being copied to, it is
 
3816
                a bit tricky to determine the source table.  The cursor
 
3817
                position in the source table need not be adjusted after the
 
3818
                intermediate COMMIT, since writes by other transactions are
 
3819
                being blocked by a MySQL table lock TL_WRITE_ALLOW_READ. */
 
3820
 
 
3821
                dict_table_t*   src_table;
 
3822
                enum lock_mode  mode;
 
3823
 
 
3824
                num_write_row = 0;
 
3825
 
 
3826
                /* Commit the transaction.  This will release the table
 
3827
                locks, so they have to be acquired again. */
 
3828
 
 
3829
                /* Altering an InnoDB table */
 
3830
                /* Get the source table. */
 
3831
                src_table = lock_get_src_table(
 
3832
                                prebuilt->trx, prebuilt->table, &mode);
 
3833
                if (!src_table) {
4333
3834
no_commit:
4334
 
      /* Unknown situation: do not commit */
4335
 
      /*
4336
 
      ut_print_timestamp(stderr);
4337
 
      fprintf(stderr,
4338
 
        "  InnoDB: ALTER TABLE is holding lock"
4339
 
        " on %lu tables!\n",
4340
 
        prebuilt->trx->mysql_n_tables_locked);
4341
 
      */
4342
 
      ;
4343
 
    } else if (src_table == prebuilt->table) {
4344
 
      /* Source table is not in InnoDB format:
4345
 
      no need to re-acquire locks on it. */
4346
 
 
4347
 
      /* Altering to InnoDB format */
4348
 
      getTransactionalEngine()->commit(user_session, 1);
4349
 
      /* We will need an IX lock on the destination table. */
4350
 
      prebuilt->sql_stat_start = TRUE;
4351
 
    } else {
4352
 
      /* Ensure that there are no other table locks than
4353
 
      LOCK_IX and LOCK_AUTO_INC on the destination table. */
4354
 
 
4355
 
      if (!lock_is_table_exclusive(prebuilt->table,
4356
 
              prebuilt->trx)) {
4357
 
        goto no_commit;
4358
 
      }
4359
 
 
4360
 
      /* Commit the transaction.  This will release the table
4361
 
      locks, so they have to be acquired again. */
4362
 
      getTransactionalEngine()->commit(user_session, 1);
4363
 
      /* Re-acquire the table lock on the source table. */
4364
 
      row_lock_table_for_mysql(prebuilt, src_table, mode);
4365
 
      /* We will need an IX lock on the destination table. */
4366
 
      prebuilt->sql_stat_start = TRUE;
4367
 
    }
4368
 
  }
4369
 
 
4370
 
  num_write_row++;
4371
 
 
4372
 
  /* This is the case where the table has an auto-increment column */
4373
 
  if (getTable()->next_number_field && record == getTable()->getInsertRecord()) {
4374
 
 
4375
 
    /* Reset the error code before calling
4376
 
    innobase_get_auto_increment(). */
4377
 
    prebuilt->autoinc_error = DB_SUCCESS;
4378
 
 
4379
 
    if ((error = update_auto_increment())) {
4380
 
      /* We don't want to mask autoinc overflow errors. */
4381
 
 
4382
 
      /* Handle the case where the AUTOINC sub-system
4383
 
         failed during initialization. */
4384
 
      if (prebuilt->autoinc_error == DB_UNSUPPORTED) {
4385
 
        error_result = ER_AUTOINC_READ_FAILED;
4386
 
        /* Set the error message to report too. */
4387
 
        my_error(ER_AUTOINC_READ_FAILED, MYF(0));
4388
 
        goto func_exit;
4389
 
      } else if (prebuilt->autoinc_error != DB_SUCCESS) {
4390
 
        error = (int) prebuilt->autoinc_error;
4391
 
 
4392
 
        goto report_error;
4393
 
      }
4394
 
 
4395
 
      /* MySQL errors are passed straight back. */
4396
 
      error_result = (int) error;
4397
 
      goto func_exit;
4398
 
    }
4399
 
 
4400
 
    auto_inc_used = TRUE;
4401
 
  }
4402
 
 
4403
 
  if (prebuilt->mysql_template == NULL
4404
 
      || prebuilt->template_type != ROW_MYSQL_WHOLE_ROW) {
4405
 
 
4406
 
    /* Build the template used in converting quickly between
4407
 
    the two database formats */
4408
 
 
4409
 
    build_template(prebuilt, NULL, getTable(), ROW_MYSQL_WHOLE_ROW);
4410
 
  }
4411
 
 
4412
 
  innodb_srv_conc_enter_innodb(prebuilt->trx);
4413
 
 
4414
 
  error = row_insert_for_mysql((byte*) record, prebuilt);
4415
 
 
4416
 
  user_session->setXaId((ib_uint64_t) ut_conv_dulint_to_longlong(trx->id));
4417
 
 
4418
 
  /* Handle duplicate key errors */
4419
 
  if (auto_inc_used) {
4420
 
    ulint   err;
4421
 
    uint64_t  auto_inc;
4422
 
    uint64_t  col_max_value;
4423
 
 
4424
 
    /* Note the number of rows processed for this statement, used
4425
 
    by get_auto_increment() to determine the number of AUTO-INC
4426
 
    values to reserve. This is only useful for a mult-value INSERT
4427
 
    and is a statement level counter.*/
4428
 
    if (trx->n_autoinc_rows > 0) {
4429
 
      --trx->n_autoinc_rows;
4430
 
    }
4431
 
 
4432
 
    /* We need the upper limit of the col type to check for
4433
 
    whether we update the table autoinc counter or not. */
4434
 
    col_max_value = innobase_get_int_col_max_value(
4435
 
      getTable()->next_number_field); 
4436
 
    /* Get the value that MySQL attempted to store in the table.*/
4437
 
    auto_inc = getTable()->next_number_field->val_int();
4438
 
 
4439
 
    switch (error) {
4440
 
    case DB_DUPLICATE_KEY:
4441
 
 
4442
 
      /* A REPLACE command and LOAD DATA INFILE REPLACE
4443
 
      handle a duplicate key error themselves, but we
4444
 
      must update the autoinc counter if we are performing
4445
 
      those statements. */
4446
 
 
4447
 
      switch (sql_command) {
4448
 
      case SQLCOM_LOAD:
4449
 
        if ((trx->duplicates
4450
 
            & (TRX_DUP_IGNORE | TRX_DUP_REPLACE))) {
4451
 
 
4452
 
          goto set_max_autoinc;
4453
 
        }
4454
 
        break;
4455
 
 
4456
 
      case SQLCOM_REPLACE:
4457
 
      case SQLCOM_INSERT_SELECT:
4458
 
      case SQLCOM_REPLACE_SELECT:
4459
 
        goto set_max_autoinc;
4460
 
 
4461
 
      default:
4462
 
        break;
4463
 
      }
4464
 
 
4465
 
      break;
4466
 
 
4467
 
    case DB_SUCCESS:
4468
 
      /* If the actual value inserted is greater than
4469
 
      the upper limit of the interval, then we try and
4470
 
      update the table upper limit. Note: last_value
4471
 
      will be 0 if get_auto_increment() was not called.*/
4472
 
 
4473
 
      if (auto_inc >= prebuilt->autoinc_last_value) {
 
3835
                        /* Unknown situation: do not commit */
 
3836
                        /*
 
3837
                        ut_print_timestamp(stderr);
 
3838
                        fprintf(stderr,
 
3839
                                "  InnoDB: ALTER TABLE is holding lock"
 
3840
                                " on %lu tables!\n",
 
3841
                                prebuilt->trx->mysql_n_tables_locked);
 
3842
                        */
 
3843
                        ;
 
3844
                } else if (src_table == prebuilt->table) {
 
3845
                        /* Source table is not in InnoDB format:
 
3846
                        no need to re-acquire locks on it. */
 
3847
 
 
3848
                        /* Altering to InnoDB format */
 
3849
                        getTransactionalEngine()->commit(user_session, 1);
 
3850
                        /* Note that this transaction is still active. */
 
3851
                        prebuilt->trx->active_trans = 1;
 
3852
                        /* We will need an IX lock on the destination table. */
 
3853
                        prebuilt->sql_stat_start = TRUE;
 
3854
                } else {
 
3855
                        /* Ensure that there are no other table locks than
 
3856
                        LOCK_IX and LOCK_AUTO_INC on the destination table. */
 
3857
 
 
3858
                        if (!lock_is_table_exclusive(prebuilt->table,
 
3859
                                                        prebuilt->trx)) {
 
3860
                                goto no_commit;
 
3861
                        }
 
3862
 
 
3863
                        /* Commit the transaction.  This will release the table
 
3864
                        locks, so they have to be acquired again. */
 
3865
                        getTransactionalEngine()->commit(user_session, 1);
 
3866
                        /* Note that this transaction is still active. */
 
3867
                        prebuilt->trx->active_trans = 1;
 
3868
                        /* Re-acquire the table lock on the source table. */
 
3869
                        row_lock_table_for_mysql(prebuilt, src_table, mode);
 
3870
                        /* We will need an IX lock on the destination table. */
 
3871
                        prebuilt->sql_stat_start = TRUE;
 
3872
                }
 
3873
        }
 
3874
 
 
3875
        num_write_row++;
 
3876
 
 
3877
        /* This is the case where the table has an auto-increment column */
 
3878
        if (table->next_number_field && record == table->record[0]) {
 
3879
 
 
3880
                /* Reset the error code before calling
 
3881
                innobase_get_auto_increment(). */
 
3882
                prebuilt->autoinc_error = DB_SUCCESS;
 
3883
 
 
3884
                if ((error = update_auto_increment())) {
 
3885
 
 
3886
                        /* We don't want to mask autoinc overflow errors. */
 
3887
                        if (prebuilt->autoinc_error != DB_SUCCESS) {
 
3888
                                error = (int) prebuilt->autoinc_error;
 
3889
 
 
3890
                                goto report_error;
 
3891
                        }
 
3892
 
 
3893
                        /* MySQL errors are passed straight back. */
 
3894
                        error_result = (int) error;
 
3895
                        goto func_exit;
 
3896
                }
 
3897
 
 
3898
                auto_inc_used = TRUE;
 
3899
        }
 
3900
 
 
3901
        if (prebuilt->mysql_template == NULL
 
3902
            || prebuilt->template_type != ROW_MYSQL_WHOLE_ROW) {
 
3903
 
 
3904
                /* Build the template used in converting quickly between
 
3905
                the two database formats */
 
3906
 
 
3907
                build_template(prebuilt, NULL, table,
 
3908
                               ROW_MYSQL_WHOLE_ROW);
 
3909
        }
 
3910
 
 
3911
        innodb_srv_conc_enter_innodb(prebuilt->trx);
 
3912
 
 
3913
        error = row_insert_for_mysql((byte*) record, prebuilt);
 
3914
 
 
3915
        /* Handle duplicate key errors */
 
3916
        if (auto_inc_used) {
 
3917
                ulint           err;
 
3918
                uint64_t        auto_inc;
 
3919
                uint64_t        col_max_value;
 
3920
 
 
3921
                /* Note the number of rows processed for this statement, used
 
3922
                by get_auto_increment() to determine the number of AUTO-INC
 
3923
                values to reserve. This is only useful for a mult-value INSERT
 
3924
                and is a statement level counter.*/
 
3925
                if (trx->n_autoinc_rows > 0) {
 
3926
                        --trx->n_autoinc_rows;
 
3927
                }
 
3928
 
 
3929
                /* We need the upper limit of the col type to check for
 
3930
                whether we update the table autoinc counter or not. */
 
3931
                col_max_value = innobase_get_int_col_max_value(
 
3932
                        table->next_number_field);
 
3933
 
 
3934
                /* Get the value that MySQL attempted to store in the table.*/
 
3935
                auto_inc = table->next_number_field->val_int();
 
3936
 
 
3937
                switch (error) {
 
3938
                case DB_DUPLICATE_KEY:
 
3939
 
 
3940
                        /* A REPLACE command and LOAD DATA INFILE REPLACE
 
3941
                        handle a duplicate key error themselves, but we
 
3942
                        must update the autoinc counter if we are performing
 
3943
                        those statements. */
 
3944
 
 
3945
                        switch (sql_command) {
 
3946
                        case SQLCOM_LOAD:
 
3947
                                if ((trx->duplicates
 
3948
                                    & (TRX_DUP_IGNORE | TRX_DUP_REPLACE))) {
 
3949
 
 
3950
                                        goto set_max_autoinc;
 
3951
                                }
 
3952
                                break;
 
3953
 
 
3954
                        case SQLCOM_REPLACE:
 
3955
                        case SQLCOM_INSERT_SELECT:
 
3956
                        case SQLCOM_REPLACE_SELECT:
 
3957
                                goto set_max_autoinc;
 
3958
 
 
3959
                        default:
 
3960
                                break;
 
3961
                        }
 
3962
 
 
3963
                        break;
 
3964
 
 
3965
                case DB_SUCCESS:
 
3966
                        /* If the actual value inserted is greater than
 
3967
                        the upper limit of the interval, then we try and
 
3968
                        update the table upper limit. Note: last_value
 
3969
                        will be 0 if get_auto_increment() was not called.*/
 
3970
 
 
3971
                        if (auto_inc <= col_max_value
 
3972
                            && auto_inc >= prebuilt->autoinc_last_value) {
4474
3973
set_max_autoinc:
4475
 
        /* This should filter out the negative
4476
 
           values set explicitly by the user. */
4477
 
        if (auto_inc <= col_max_value) {
4478
 
          ut_a(prebuilt->autoinc_increment > 0);
4479
 
 
4480
 
          uint64_t      need;
4481
 
          uint64_t      offset;
4482
 
 
4483
 
          offset = prebuilt->autoinc_offset;
4484
 
          need = prebuilt->autoinc_increment;
4485
 
 
4486
 
          auto_inc = innobase_next_autoinc(
4487
 
                                           auto_inc,
4488
 
                                           need, offset, col_max_value);
4489
 
 
4490
 
          err = innobase_set_max_autoinc(
4491
 
                                         auto_inc);
4492
 
 
4493
 
          if (err != DB_SUCCESS) {
4494
 
            error = err;
4495
 
          }
4496
 
        }
4497
 
      }
4498
 
      break;
4499
 
    }
4500
 
  }
4501
 
 
4502
 
  innodb_srv_conc_exit_innodb(prebuilt->trx);
 
3974
                                ut_a(prebuilt->autoinc_increment > 0);
 
3975
 
 
3976
                                uint64_t        need;
 
3977
                                uint64_t        offset;
 
3978
 
 
3979
                                offset = prebuilt->autoinc_offset;
 
3980
                                need = prebuilt->autoinc_increment;
 
3981
 
 
3982
                                auto_inc = innobase_next_autoinc(
 
3983
                                        auto_inc, need, offset, col_max_value);
 
3984
 
 
3985
                                err = innobase_set_max_autoinc(auto_inc);
 
3986
 
 
3987
                                if (err != DB_SUCCESS) {
 
3988
                                        error = err;
 
3989
                                }
 
3990
                        }
 
3991
                        break;
 
3992
                }
 
3993
        }
 
3994
 
 
3995
        innodb_srv_conc_exit_innodb(prebuilt->trx);
4503
3996
 
4504
3997
report_error:
4505
 
  error_result = convert_error_code_to_mysql((int) error,
4506
 
               prebuilt->table->flags,
4507
 
               user_session);
 
3998
        error_result = convert_error_code_to_mysql((int) error,
 
3999
                                                   prebuilt->table->flags,
 
4000
                                                   user_session);
4508
4001
 
4509
4002
func_exit:
4510
 
  innobase_active_small();
 
4003
        innobase_active_small();
4511
4004
 
4512
 
  return(error_result);
 
4005
        return(error_result);
4513
4006
}
4514
4007
 
4515
4008
/**********************************************************************//**
4516
4009
Checks which fields have changed in a row and stores information
4517
4010
of them to an update vector.
4518
 
@return error number or 0 */
 
4011
@return error number or 0 */
4519
4012
static
4520
4013
int
4521
4014
calc_row_difference(
4522
4015
/*================*/
4523
 
  upd_t*    uvect,    /*!< in/out: update vector */
4524
 
  unsigned char*    old_row,  /*!< in: old row in MySQL format */
4525
 
  unsigned char*    new_row,  /*!< in: new row in MySQL format */
4526
 
  Table* table,   /*!< in: table in MySQL data
4527
 
          dictionary */
4528
 
  unsigned char*  upd_buff, /*!< in: buffer to use */
4529
 
  ulint   buff_len, /*!< in: buffer length */
4530
 
  row_prebuilt_t* prebuilt, /*!< in: InnoDB prebuilt struct */
4531
 
  Session*  )   /*!< in: user thread */
 
4016
        upd_t*          uvect,          /*!< in/out: update vector */
 
4017
        unsigned char*          old_row,        /*!< in: old row in MySQL format */
 
4018
        unsigned char*          new_row,        /*!< in: new row in MySQL format */
 
4019
        Table* table,           /*!< in: table in MySQL data
 
4020
                                        dictionary */
 
4021
        unsigned char*  upd_buff,       /*!< in: buffer to use */
 
4022
        ulint           buff_len,       /*!< in: buffer length */
 
4023
        row_prebuilt_t* prebuilt,       /*!< in: InnoDB prebuilt struct */
 
4024
        Session*        )               /*!< in: user thread */
4532
4025
{
4533
 
  unsigned char*    original_upd_buff = upd_buff;
4534
 
  enum_field_types field_mysql_type;
4535
 
  uint    n_fields;
4536
 
  ulint   o_len;
4537
 
  ulint   n_len;
4538
 
  ulint   col_pack_len;
4539
 
  const byte* new_mysql_row_col;
4540
 
  const byte* o_ptr;
4541
 
  const byte* n_ptr;
4542
 
  byte*   buf;
4543
 
  upd_field_t*  ufield;
4544
 
  ulint   col_type;
4545
 
  ulint   n_changed = 0;
4546
 
  dfield_t  dfield;
4547
 
  dict_index_t* clust_index;
4548
 
  uint    i= 0;
4549
 
 
4550
 
  n_fields = table->getShare()->sizeFields();
4551
 
  clust_index = dict_table_get_first_index(prebuilt->table);
4552
 
 
4553
 
  /* We use upd_buff to convert changed fields */
4554
 
  buf = (byte*) upd_buff;
4555
 
 
4556
 
  for (i = 0; i < n_fields; i++) {
4557
 
    Field *field= table->getField(i);
4558
 
 
4559
 
    o_ptr = (const byte*) old_row + get_field_offset(table, field);
4560
 
    n_ptr = (const byte*) new_row + get_field_offset(table, field);
4561
 
 
4562
 
    /* Use new_mysql_row_col and col_pack_len save the values */
4563
 
 
4564
 
    new_mysql_row_col = n_ptr;
4565
 
    col_pack_len = field->pack_length();
4566
 
 
4567
 
    o_len = col_pack_len;
4568
 
    n_len = col_pack_len;
4569
 
 
4570
 
    /* We use o_ptr and n_ptr to dig up the actual data for
4571
 
    comparison. */
4572
 
 
4573
 
    field_mysql_type = field->type();
4574
 
 
4575
 
    col_type = prebuilt->table->cols[i].mtype;
4576
 
 
4577
 
    switch (col_type) {
4578
 
 
4579
 
    case DATA_BLOB:
4580
 
      o_ptr = row_mysql_read_blob_ref(&o_len, o_ptr, o_len);
4581
 
      n_ptr = row_mysql_read_blob_ref(&n_len, n_ptr, n_len);
4582
 
 
4583
 
      break;
4584
 
 
4585
 
    case DATA_VARCHAR:
4586
 
    case DATA_BINARY:
4587
 
    case DATA_VARMYSQL:
4588
 
      if (field_mysql_type == DRIZZLE_TYPE_VARCHAR) {
4589
 
        /* This is a >= 5.0.3 type true VARCHAR where
4590
 
        the real payload data length is stored in
4591
 
        1 or 2 bytes */
4592
 
 
4593
 
        o_ptr = row_mysql_read_true_varchar(
4594
 
          &o_len, o_ptr,
4595
 
          (ulint)
4596
 
          (((Field_varstring*)field)->pack_length_no_ptr()));
4597
 
 
4598
 
        n_ptr = row_mysql_read_true_varchar(
4599
 
          &n_len, n_ptr,
4600
 
          (ulint)
4601
 
          (((Field_varstring*)field)->pack_length_no_ptr()));
4602
 
      }
4603
 
 
4604
 
      break;
4605
 
    default:
4606
 
      ;
4607
 
    }
4608
 
 
4609
 
    if (field->null_ptr) {
4610
 
      if (field_in_record_is_null(table, field,
4611
 
              (char*) old_row)) {
4612
 
        o_len = UNIV_SQL_NULL;
4613
 
      }
4614
 
 
4615
 
      if (field_in_record_is_null(table, field,
4616
 
              (char*) new_row)) {
4617
 
        n_len = UNIV_SQL_NULL;
4618
 
      }
4619
 
    }
4620
 
 
4621
 
    if (o_len != n_len || (o_len != UNIV_SQL_NULL &&
4622
 
          0 != memcmp(o_ptr, n_ptr, o_len))) {
4623
 
      /* The field has changed */
4624
 
 
4625
 
      ufield = uvect->fields + n_changed;
4626
 
 
4627
 
      /* Let us use a dummy dfield to make the conversion
4628
 
      from the MySQL column format to the InnoDB format */
4629
 
 
4630
 
      dict_col_copy_type(prebuilt->table->cols + i,
4631
 
                 &dfield.type);
4632
 
 
4633
 
      if (n_len != UNIV_SQL_NULL) {
4634
 
        buf = row_mysql_store_col_in_innobase_format(
4635
 
          &dfield,
4636
 
          (byte*)buf,
4637
 
          TRUE,
4638
 
          new_mysql_row_col,
4639
 
          col_pack_len,
4640
 
          dict_table_is_comp(prebuilt->table));
4641
 
        dfield_copy_data(&ufield->new_val, &dfield);
4642
 
      } else {
4643
 
        dfield_set_null(&ufield->new_val);
4644
 
      }
4645
 
 
4646
 
      ufield->exp = NULL;
4647
 
      ufield->orig_len = 0;
4648
 
      ufield->field_no = dict_col_get_clust_pos(
4649
 
        &prebuilt->table->cols[i], clust_index);
4650
 
      n_changed++;
4651
 
    }
4652
 
  }
4653
 
 
4654
 
  uvect->n_fields = n_changed;
4655
 
  uvect->info_bits = 0;
4656
 
 
4657
 
  ut_a(buf <= (byte*)original_upd_buff + buff_len);
4658
 
 
4659
 
  return(0);
 
4026
        unsigned char*          original_upd_buff = upd_buff;
 
4027
        Field*          field;
 
4028
        enum_field_types field_mysql_type;
 
4029
        uint            n_fields;
 
4030
        ulint           o_len;
 
4031
        ulint           n_len;
 
4032
        ulint           col_pack_len;
 
4033
        const byte*     new_mysql_row_col;
 
4034
        const byte*     o_ptr;
 
4035
        const byte*     n_ptr;
 
4036
        byte*           buf;
 
4037
        upd_field_t*    ufield;
 
4038
        ulint           col_type;
 
4039
        ulint           n_changed = 0;
 
4040
        dfield_t        dfield;
 
4041
        dict_index_t*   clust_index;
 
4042
        uint            i= 0;
 
4043
 
 
4044
        n_fields = table->s->fields;
 
4045
        clust_index = dict_table_get_first_index(prebuilt->table);
 
4046
 
 
4047
        /* We use upd_buff to convert changed fields */
 
4048
        buf = (byte*) upd_buff;
 
4049
 
 
4050
        for (i = 0; i < n_fields; i++) {
 
4051
                field = table->field[i];
 
4052
 
 
4053
                o_ptr = (const byte*) old_row + get_field_offset(table, field);
 
4054
                n_ptr = (const byte*) new_row + get_field_offset(table, field);
 
4055
 
 
4056
                /* Use new_mysql_row_col and col_pack_len save the values */
 
4057
 
 
4058
                new_mysql_row_col = n_ptr;
 
4059
                col_pack_len = field->pack_length();
 
4060
 
 
4061
                o_len = col_pack_len;
 
4062
                n_len = col_pack_len;
 
4063
 
 
4064
                /* We use o_ptr and n_ptr to dig up the actual data for
 
4065
                comparison. */
 
4066
 
 
4067
                field_mysql_type = field->type();
 
4068
 
 
4069
                col_type = prebuilt->table->cols[i].mtype;
 
4070
 
 
4071
                switch (col_type) {
 
4072
 
 
4073
                case DATA_BLOB:
 
4074
                        o_ptr = row_mysql_read_blob_ref(&o_len, o_ptr, o_len);
 
4075
                        n_ptr = row_mysql_read_blob_ref(&n_len, n_ptr, n_len);
 
4076
 
 
4077
                        break;
 
4078
 
 
4079
                case DATA_VARCHAR:
 
4080
                case DATA_BINARY:
 
4081
                case DATA_VARMYSQL:
 
4082
                        if (field_mysql_type == DRIZZLE_TYPE_VARCHAR) {
 
4083
                                /* This is a >= 5.0.3 type true VARCHAR where
 
4084
                                the real payload data length is stored in
 
4085
                                1 or 2 bytes */
 
4086
 
 
4087
                                o_ptr = row_mysql_read_true_varchar(
 
4088
                                        &o_len, o_ptr,
 
4089
                                        (ulint)
 
4090
                                        (((Field_varstring*)field)->length_bytes));
 
4091
 
 
4092
                                n_ptr = row_mysql_read_true_varchar(
 
4093
                                        &n_len, n_ptr,
 
4094
                                        (ulint)
 
4095
                                        (((Field_varstring*)field)->length_bytes));
 
4096
                        }
 
4097
 
 
4098
                        break;
 
4099
                default:
 
4100
                        ;
 
4101
                }
 
4102
 
 
4103
                if (field->null_ptr) {
 
4104
                        if (field_in_record_is_null(table, field,
 
4105
                                                        (char*) old_row)) {
 
4106
                                o_len = UNIV_SQL_NULL;
 
4107
                        }
 
4108
 
 
4109
                        if (field_in_record_is_null(table, field,
 
4110
                                                        (char*) new_row)) {
 
4111
                                n_len = UNIV_SQL_NULL;
 
4112
                        }
 
4113
                }
 
4114
 
 
4115
                if (o_len != n_len || (o_len != UNIV_SQL_NULL &&
 
4116
                                        0 != memcmp(o_ptr, n_ptr, o_len))) {
 
4117
                        /* The field has changed */
 
4118
 
 
4119
                        ufield = uvect->fields + n_changed;
 
4120
 
 
4121
                        /* Let us use a dummy dfield to make the conversion
 
4122
                        from the MySQL column format to the InnoDB format */
 
4123
 
 
4124
                        dict_col_copy_type(prebuilt->table->cols + i,
 
4125
                                                     &dfield.type);
 
4126
 
 
4127
                        if (n_len != UNIV_SQL_NULL) {
 
4128
                                buf = row_mysql_store_col_in_innobase_format(
 
4129
                                        &dfield,
 
4130
                                        (byte*)buf,
 
4131
                                        TRUE,
 
4132
                                        new_mysql_row_col,
 
4133
                                        col_pack_len,
 
4134
                                        dict_table_is_comp(prebuilt->table));
 
4135
                                dfield_copy_data(&ufield->new_val, &dfield);
 
4136
                        } else {
 
4137
                                dfield_set_null(&ufield->new_val);
 
4138
                        }
 
4139
 
 
4140
                        ufield->exp = NULL;
 
4141
                        ufield->orig_len = 0;
 
4142
                        ufield->field_no = dict_col_get_clust_pos(
 
4143
                                &prebuilt->table->cols[i], clust_index);
 
4144
                        n_changed++;
 
4145
                }
 
4146
        }
 
4147
 
 
4148
        uvect->n_fields = n_changed;
 
4149
        uvect->info_bits = 0;
 
4150
 
 
4151
        ut_a(buf <= (byte*)original_upd_buff + buff_len);
 
4152
 
 
4153
        return(0);
4660
4154
}
4661
4155
 
4662
4156
/**********************************************************************//**
4666
4160
TODO: currently InnoDB does not prevent the 'Halloween problem':
4667
4161
in a searched update a single row can get updated several times
4668
4162
if its index columns are updated!
4669
 
@return error number or 0 */
 
4163
@return error number or 0 */
4670
4164
UNIV_INTERN
4671
4165
int
4672
 
ha_innobase::doUpdateRecord(
 
4166
ha_innobase::update_row(
4673
4167
/*====================*/
4674
 
  const unsigned char*  old_row,/*!< in: old row in MySQL format */
4675
 
  unsigned char*    new_row)/*!< in: new row in MySQL format */
 
4168
        const unsigned char*    old_row,/*!< in: old row in MySQL format */
 
4169
        unsigned char*          new_row)/*!< in: new row in MySQL format */
4676
4170
{
4677
 
  upd_t*    uvect;
4678
 
  int   error = 0;
4679
 
  trx_t*    trx = session_to_trx(user_session);
4680
 
 
4681
 
  ut_a(prebuilt->trx == trx);
4682
 
 
4683
 
  if (prebuilt->upd_node) {
4684
 
    uvect = prebuilt->upd_node->update;
4685
 
  } else {
4686
 
    uvect = row_get_prebuilt_update_vector(prebuilt);
4687
 
  }
4688
 
 
4689
 
  /* Build an update vector from the modified fields in the rows
4690
 
  (uses upd_buff of the handle) */
4691
 
 
4692
 
  calc_row_difference(uvect, (unsigned char*) old_row, new_row, getTable(),
4693
 
      &upd_buff[0], (ulint)upd_and_key_val_buff_len,
4694
 
      prebuilt, user_session);
4695
 
 
4696
 
  /* This is not a delete */
4697
 
  prebuilt->upd_node->is_delete = FALSE;
4698
 
 
4699
 
  ut_a(prebuilt->template_type == ROW_MYSQL_WHOLE_ROW);
4700
 
 
4701
 
  if (getTable()->found_next_number_field)
4702
 
  {
4703
 
    uint64_t  auto_inc;
4704
 
    uint64_t  col_max_value;
4705
 
 
4706
 
    auto_inc = getTable()->found_next_number_field->val_int();
4707
 
 
4708
 
    /* We need the upper limit of the col type to check for
4709
 
    whether we update the table autoinc counter or not. */
4710
 
    col_max_value = innobase_get_int_col_max_value(
4711
 
      getTable()->found_next_number_field);
4712
 
 
4713
 
    uint64_t current_autoinc;
4714
 
    ulint autoinc_error= innobase_get_autoinc(&current_autoinc);
4715
 
    if (autoinc_error == DB_SUCCESS
4716
 
        && auto_inc <= col_max_value && auto_inc != 0
4717
 
        && auto_inc >= current_autoinc)
4718
 
    {
4719
 
 
4720
 
      uint64_t  need;
4721
 
      uint64_t  offset;
4722
 
 
4723
 
      offset = prebuilt->autoinc_offset;
4724
 
      need = prebuilt->autoinc_increment;
4725
 
 
4726
 
      auto_inc = innobase_next_autoinc(
4727
 
        auto_inc, need, offset, col_max_value);
4728
 
 
4729
 
      dict_table_autoinc_update_if_greater(prebuilt->table, auto_inc);
4730
 
    }
4731
 
 
4732
 
    dict_table_autoinc_unlock(prebuilt->table);
4733
 
  }
4734
 
 
4735
 
  innodb_srv_conc_enter_innodb(trx);
4736
 
 
4737
 
  error = row_update_for_mysql((byte*) old_row, prebuilt);
4738
 
 
4739
 
  user_session->setXaId((ib_uint64_t) ut_conv_dulint_to_longlong(trx->id));
4740
 
 
4741
 
  /* We need to do some special AUTOINC handling for the following case:
4742
 
 
4743
 
  INSERT INTO t (c1,c2) VALUES(x,y) ON DUPLICATE KEY UPDATE ...
4744
 
 
4745
 
  We need to use the AUTOINC counter that was actually used by
4746
 
  MySQL in the UPDATE statement, which can be different from the
4747
 
  value used in the INSERT statement.*/
4748
 
 
4749
 
  if (error == DB_SUCCESS
4750
 
      && getTable()->next_number_field
4751
 
      && new_row == getTable()->getInsertRecord()
4752
 
      && session_sql_command(user_session) == SQLCOM_INSERT
4753
 
      && (trx->duplicates & (TRX_DUP_IGNORE | TRX_DUP_REPLACE))
4754
 
    == TRX_DUP_IGNORE)  {
4755
 
 
4756
 
    uint64_t  auto_inc;
4757
 
    uint64_t  col_max_value;
4758
 
 
4759
 
    auto_inc = getTable()->next_number_field->val_int();
4760
 
 
4761
 
    /* We need the upper limit of the col type to check for
4762
 
    whether we update the table autoinc counter or not. */
4763
 
    col_max_value = innobase_get_int_col_max_value(
4764
 
      getTable()->next_number_field);
4765
 
 
4766
 
    if (auto_inc <= col_max_value && auto_inc != 0) {
4767
 
 
4768
 
      uint64_t  need;
4769
 
      uint64_t  offset;
4770
 
 
4771
 
      offset = prebuilt->autoinc_offset;
4772
 
      need = prebuilt->autoinc_increment;
4773
 
 
4774
 
      auto_inc = innobase_next_autoinc(
4775
 
        auto_inc, need, offset, col_max_value);
4776
 
 
4777
 
      error = innobase_set_max_autoinc(auto_inc);
4778
 
    }
4779
 
  }
4780
 
 
4781
 
  innodb_srv_conc_exit_innodb(trx);
4782
 
 
4783
 
  error = convert_error_code_to_mysql(error,
4784
 
              prebuilt->table->flags,
 
4171
        upd_t*          uvect;
 
4172
        int             error = 0;
 
4173
        trx_t*          trx = session_to_trx(user_session);
 
4174
 
 
4175
        ut_a(prebuilt->trx == trx);
 
4176
 
 
4177
        ha_statistic_increment(&system_status_var::ha_update_count);
 
4178
 
 
4179
        if (table->timestamp_field_type & TIMESTAMP_AUTO_SET_ON_UPDATE)
 
4180
                table->timestamp_field->set_time();
 
4181
 
 
4182
        if (prebuilt->upd_node) {
 
4183
                uvect = prebuilt->upd_node->update;
 
4184
        } else {
 
4185
                uvect = row_get_prebuilt_update_vector(prebuilt);
 
4186
        }
 
4187
 
 
4188
        /* Build an update vector from the modified fields in the rows
 
4189
        (uses upd_buff of the handle) */
 
4190
 
 
4191
        calc_row_difference(uvect, (unsigned char*) old_row, new_row, table,
 
4192
                        upd_buff, (ulint)upd_and_key_val_buff_len,
 
4193
                        prebuilt, user_session);
 
4194
 
 
4195
        /* This is not a delete */
 
4196
        prebuilt->upd_node->is_delete = FALSE;
 
4197
 
 
4198
        ut_a(prebuilt->template_type == ROW_MYSQL_WHOLE_ROW);
 
4199
 
 
4200
        innodb_srv_conc_enter_innodb(trx);
 
4201
 
 
4202
        error = row_update_for_mysql((byte*) old_row, prebuilt);
 
4203
 
 
4204
        /* We need to do some special AUTOINC handling for the following case:
 
4205
 
 
4206
        INSERT INTO t (c1,c2) VALUES(x,y) ON DUPLICATE KEY UPDATE ...
 
4207
 
 
4208
        We need to use the AUTOINC counter that was actually used by
 
4209
        MySQL in the UPDATE statement, which can be different from the
 
4210
        value used in the INSERT statement.*/
 
4211
 
 
4212
        if (error == DB_SUCCESS
 
4213
            && table->next_number_field
 
4214
            && new_row == table->record[0]
 
4215
            && session_sql_command(user_session) == SQLCOM_INSERT
 
4216
            && (trx->duplicates & (TRX_DUP_IGNORE | TRX_DUP_REPLACE))
 
4217
                == TRX_DUP_IGNORE)  {
 
4218
 
 
4219
                uint64_t        auto_inc;
 
4220
                uint64_t        col_max_value;
 
4221
 
 
4222
                auto_inc = table->next_number_field->val_int();
 
4223
 
 
4224
                /* We need the upper limit of the col type to check for
 
4225
                whether we update the table autoinc counter or not. */
 
4226
                col_max_value = innobase_get_int_col_max_value(
 
4227
                        table->next_number_field);
 
4228
 
 
4229
                if (auto_inc <= col_max_value && auto_inc != 0) {
 
4230
 
 
4231
                        uint64_t        need;
 
4232
                        uint64_t        offset;
 
4233
 
 
4234
                        offset = prebuilt->autoinc_offset;
 
4235
                        need = prebuilt->autoinc_increment;
 
4236
 
 
4237
                        auto_inc = innobase_next_autoinc(
 
4238
                                auto_inc, need, offset, col_max_value);
 
4239
 
 
4240
                        error = innobase_set_max_autoinc(auto_inc);
 
4241
                }
 
4242
        }
 
4243
 
 
4244
        innodb_srv_conc_exit_innodb(trx);
 
4245
 
 
4246
        error = convert_error_code_to_mysql(error,
 
4247
                                            prebuilt->table->flags,
4785
4248
                                            user_session);
4786
4249
 
4787
 
  if (error == 0 /* success */
4788
 
      && uvect->n_fields == 0 /* no columns were updated */) {
4789
 
 
4790
 
    /* This is the same as success, but instructs
4791
 
    MySQL that the row is not really updated and it
4792
 
    should not increase the count of updated rows.
4793
 
    This is fix for http://bugs.mysql.com/29157 */
4794
 
    error = HA_ERR_RECORD_IS_THE_SAME;
4795
 
  }
4796
 
 
4797
 
  /* Tell InnoDB server that there might be work for
4798
 
  utility threads: */
4799
 
 
4800
 
  innobase_active_small();
4801
 
 
4802
 
  return(error);
 
4250
        if (error == 0 /* success */
 
4251
            && uvect->n_fields == 0 /* no columns were updated */) {
 
4252
 
 
4253
                /* This is the same as success, but instructs
 
4254
                MySQL that the row is not really updated and it
 
4255
                should not increase the count of updated rows.
 
4256
                This is fix for http://bugs.mysql.com/29157 */
 
4257
                error = HA_ERR_RECORD_IS_THE_SAME;
 
4258
        }
 
4259
 
 
4260
        /* Tell InnoDB server that there might be work for
 
4261
        utility threads: */
 
4262
 
 
4263
        innobase_active_small();
 
4264
 
 
4265
        return(error);
4803
4266
}
4804
4267
 
4805
4268
/**********************************************************************//**
4806
4269
Deletes a row given as the parameter.
4807
 
@return error number or 0 */
 
4270
@return error number or 0 */
4808
4271
UNIV_INTERN
4809
4272
int
4810
 
ha_innobase::doDeleteRecord(
 
4273
ha_innobase::delete_row(
4811
4274
/*====================*/
4812
 
  const unsigned char*  record) /*!< in: a row in MySQL format */
 
4275
        const unsigned char*    record) /*!< in: a row in MySQL format */
4813
4276
{
4814
 
  int   error = 0;
4815
 
  trx_t*    trx = session_to_trx(user_session);
4816
 
 
4817
 
  ut_a(prebuilt->trx == trx);
4818
 
 
4819
 
  if (!prebuilt->upd_node) {
4820
 
    row_get_prebuilt_update_vector(prebuilt);
4821
 
  }
4822
 
 
4823
 
  /* This is a delete */
4824
 
 
4825
 
  prebuilt->upd_node->is_delete = TRUE;
4826
 
 
4827
 
  innodb_srv_conc_enter_innodb(trx);
4828
 
 
4829
 
  error = row_update_for_mysql((byte*) record, prebuilt);
4830
 
 
4831
 
  user_session->setXaId((ib_uint64_t) ut_conv_dulint_to_longlong(trx->id));
4832
 
 
4833
 
  innodb_srv_conc_exit_innodb(trx);
4834
 
 
4835
 
  error = convert_error_code_to_mysql(
4836
 
    error, prebuilt->table->flags, user_session);
4837
 
 
4838
 
  /* Tell the InnoDB server that there might be work for
4839
 
  utility threads: */
4840
 
 
4841
 
  innobase_active_small();
4842
 
 
4843
 
  return(error);
 
4277
        int             error = 0;
 
4278
        trx_t*          trx = session_to_trx(user_session);
 
4279
 
 
4280
        ut_a(prebuilt->trx == trx);
 
4281
 
 
4282
        ha_statistic_increment(&system_status_var::ha_delete_count);
 
4283
 
 
4284
        if (!prebuilt->upd_node) {
 
4285
                row_get_prebuilt_update_vector(prebuilt);
 
4286
        }
 
4287
 
 
4288
        /* This is a delete */
 
4289
 
 
4290
        prebuilt->upd_node->is_delete = TRUE;
 
4291
 
 
4292
        innodb_srv_conc_enter_innodb(trx);
 
4293
 
 
4294
        error = row_update_for_mysql((byte*) record, prebuilt);
 
4295
 
 
4296
        innodb_srv_conc_exit_innodb(trx);
 
4297
 
 
4298
        error = convert_error_code_to_mysql(
 
4299
                error, prebuilt->table->flags, user_session);
 
4300
 
 
4301
        /* Tell the InnoDB server that there might be work for
 
4302
        utility threads: */
 
4303
 
 
4304
        innobase_active_small();
 
4305
 
 
4306
        return(error);
4844
4307
}
4845
4308
 
4846
4309
/**********************************************************************//**
4852
4315
ha_innobase::unlock_row(void)
4853
4316
/*=========================*/
4854
4317
{
4855
 
  /* Consistent read does not take any locks, thus there is
4856
 
  nothing to unlock. */
4857
 
 
4858
 
  if (prebuilt->select_lock_type == LOCK_NONE) {
4859
 
    return;
4860
 
  }
4861
 
 
4862
 
  switch (prebuilt->row_read_type) {
4863
 
  case ROW_READ_WITH_LOCKS:
4864
 
    if (!srv_locks_unsafe_for_binlog
4865
 
        && prebuilt->trx->isolation_level
4866
 
        > TRX_ISO_READ_COMMITTED) {
4867
 
      break;
4868
 
    }
4869
 
    /* fall through */
4870
 
  case ROW_READ_TRY_SEMI_CONSISTENT:
4871
 
    row_unlock_for_mysql(prebuilt, FALSE);
4872
 
    break;
4873
 
  case ROW_READ_DID_SEMI_CONSISTENT:
4874
 
    prebuilt->row_read_type = ROW_READ_TRY_SEMI_CONSISTENT;
4875
 
    break;
4876
 
  }
4877
 
 
4878
 
  return;
 
4318
        /* Consistent read does not take any locks, thus there is
 
4319
        nothing to unlock. */
 
4320
 
 
4321
        if (prebuilt->select_lock_type == LOCK_NONE) {
 
4322
          return;
 
4323
        }
 
4324
 
 
4325
        switch (prebuilt->row_read_type) {
 
4326
        case ROW_READ_WITH_LOCKS:
 
4327
                if (!srv_locks_unsafe_for_binlog
 
4328
                    && prebuilt->trx->isolation_level
 
4329
                    != TRX_ISO_READ_COMMITTED) {
 
4330
                        break;
 
4331
                }
 
4332
                /* fall through */
 
4333
        case ROW_READ_TRY_SEMI_CONSISTENT:
 
4334
                row_unlock_for_mysql(prebuilt, FALSE);
 
4335
                break;
 
4336
        case ROW_READ_DID_SEMI_CONSISTENT:
 
4337
                prebuilt->row_read_type = ROW_READ_TRY_SEMI_CONSISTENT;
 
4338
                break;
 
4339
        }
 
4340
 
 
4341
        return;
4879
4342
}
4880
4343
 
4881
4344
/* See Cursor.h and row0mysql.h for docs on this function. */
4884
4347
ha_innobase::was_semi_consistent_read(void)
4885
4348
/*=======================================*/
4886
4349
{
4887
 
  return(prebuilt->row_read_type == ROW_READ_DID_SEMI_CONSISTENT);
 
4350
        return(prebuilt->row_read_type == ROW_READ_DID_SEMI_CONSISTENT);
4888
4351
}
4889
4352
 
4890
4353
/* See Cursor.h and row0mysql.h for docs on this function. */
4893
4356
ha_innobase::try_semi_consistent_read(bool yes)
4894
4357
/*===========================================*/
4895
4358
{
4896
 
  ut_a(prebuilt->trx == session_to_trx(getTable()->in_use));
4897
 
 
4898
 
  /* Row read type is set to semi consistent read if this was
4899
 
  requested by the MySQL and either innodb_locks_unsafe_for_binlog
4900
 
  option is used or this session is using READ COMMITTED isolation
4901
 
  level. */
4902
 
 
4903
 
  if (yes
4904
 
      && (srv_locks_unsafe_for_binlog
4905
 
    || prebuilt->trx->isolation_level <= TRX_ISO_READ_COMMITTED)) {
4906
 
    prebuilt->row_read_type = ROW_READ_TRY_SEMI_CONSISTENT;
4907
 
  } else {
4908
 
    prebuilt->row_read_type = ROW_READ_WITH_LOCKS;
4909
 
  }
 
4359
        ut_a(prebuilt->trx == session_to_trx(ha_session()));
 
4360
 
 
4361
        /* Row read type is set to semi consistent read if this was
 
4362
        requested by the MySQL and either innodb_locks_unsafe_for_binlog
 
4363
        option is used or this session is using READ COMMITTED isolation
 
4364
        level. */
 
4365
 
 
4366
        if (yes
 
4367
            && (srv_locks_unsafe_for_binlog
 
4368
                || prebuilt->trx->isolation_level == TRX_ISO_READ_COMMITTED)) {
 
4369
                prebuilt->row_read_type = ROW_READ_TRY_SEMI_CONSISTENT;
 
4370
        } else {
 
4371
                prebuilt->row_read_type = ROW_READ_WITH_LOCKS;
 
4372
        }
4910
4373
}
4911
4374
 
4912
4375
/******************************************************************//**
4913
4376
Initializes a handle to use an index.
4914
 
@return 0 or error number */
 
4377
@return 0 or error number */
4915
4378
UNIV_INTERN
4916
4379
int
4917
 
ha_innobase::doStartIndexScan(
 
4380
ha_innobase::index_init(
4918
4381
/*====================*/
4919
 
  uint  keynr,  /*!< in: key (index) number */
4920
 
  bool )    /*!< in: 1 if result MUST be sorted according to index */
 
4382
        uint    keynr,  /*!< in: key (index) number */
 
4383
        bool )          /*!< in: 1 if result MUST be sorted according to index */
4921
4384
{
4922
 
  return(change_active_index(keynr));
 
4385
        return(change_active_index(keynr));
4923
4386
}
4924
4387
 
4925
4388
/******************************************************************//**
4926
4389
Currently does nothing.
4927
 
@return 0 */
 
4390
@return 0 */
4928
4391
UNIV_INTERN
4929
4392
int
4930
 
ha_innobase::doEndIndexScan(void)
 
4393
ha_innobase::index_end(void)
4931
4394
/*========================*/
4932
4395
{
4933
 
  int error = 0;
4934
 
  active_index=MAX_KEY;
4935
 
  return(error);
 
4396
        int     error   = 0;
 
4397
        active_index=MAX_KEY;
 
4398
        return(error);
4936
4399
}
4937
4400
 
4938
4401
/*********************************************************************//**
4942
4405
ulint
4943
4406
convert_search_mode_to_innobase(
4944
4407
/*============================*/
4945
 
  enum ha_rkey_function find_flag)
 
4408
        enum ha_rkey_function   find_flag)
4946
4409
{
4947
 
  switch (find_flag) {
4948
 
  case HA_READ_KEY_EXACT:
4949
 
    /* this does not require the index to be UNIQUE */
4950
 
    return(PAGE_CUR_GE);
4951
 
  case HA_READ_KEY_OR_NEXT:
4952
 
    return(PAGE_CUR_GE);
4953
 
  case HA_READ_KEY_OR_PREV:
4954
 
    return(PAGE_CUR_LE);
4955
 
  case HA_READ_AFTER_KEY: 
4956
 
    return(PAGE_CUR_G);
4957
 
  case HA_READ_BEFORE_KEY:
4958
 
    return(PAGE_CUR_L);
4959
 
  case HA_READ_PREFIX:
4960
 
    return(PAGE_CUR_GE);
4961
 
  case HA_READ_PREFIX_LAST:
4962
 
    return(PAGE_CUR_LE);
4963
 
  case HA_READ_PREFIX_LAST_OR_PREV:
4964
 
    return(PAGE_CUR_LE);
4965
 
    /* In MySQL-4.0 HA_READ_PREFIX and HA_READ_PREFIX_LAST always
4966
 
    pass a complete-field prefix of a key value as the search
4967
 
    tuple. I.e., it is not allowed that the last field would
4968
 
    just contain n first bytes of the full field value.
4969
 
    MySQL uses a 'padding' trick to convert LIKE 'abc%'
4970
 
    type queries so that it can use as a search tuple
4971
 
    a complete-field-prefix of a key value. Thus, the InnoDB
4972
 
    search mode PAGE_CUR_LE_OR_EXTENDS is never used.
4973
 
    TODO: when/if MySQL starts to use also partial-field
4974
 
    prefixes, we have to deal with stripping of spaces
4975
 
    and comparison of non-latin1 char type fields in
4976
 
    innobase_mysql_cmp() to get PAGE_CUR_LE_OR_EXTENDS to
4977
 
    work correctly. */
4978
 
  case HA_READ_MBR_CONTAIN:
4979
 
  case HA_READ_MBR_INTERSECT:
4980
 
  case HA_READ_MBR_WITHIN:
4981
 
  case HA_READ_MBR_DISJOINT:
4982
 
  case HA_READ_MBR_EQUAL:
4983
 
    return(PAGE_CUR_UNSUPP);
4984
 
  /* do not use "default:" in order to produce a gcc warning:
4985
 
  enumeration value '...' not handled in switch
4986
 
  (if -Wswitch or -Wall is used) */
4987
 
  }
4988
 
 
4989
 
  my_error(ER_CHECK_NOT_IMPLEMENTED, MYF(0), "this functionality");
4990
 
 
4991
 
  return(PAGE_CUR_UNSUPP);
 
4410
        switch (find_flag) {
 
4411
        case HA_READ_KEY_EXACT:
 
4412
                /* this does not require the index to be UNIQUE */
 
4413
                return(PAGE_CUR_GE);
 
4414
        case HA_READ_KEY_OR_NEXT:
 
4415
                return(PAGE_CUR_GE);
 
4416
        case HA_READ_KEY_OR_PREV:
 
4417
                return(PAGE_CUR_LE);
 
4418
        case HA_READ_AFTER_KEY: 
 
4419
                return(PAGE_CUR_G);
 
4420
        case HA_READ_BEFORE_KEY:
 
4421
                return(PAGE_CUR_L);
 
4422
        case HA_READ_PREFIX:
 
4423
                return(PAGE_CUR_GE);
 
4424
        case HA_READ_PREFIX_LAST:
 
4425
                return(PAGE_CUR_LE);
 
4426
        case HA_READ_PREFIX_LAST_OR_PREV:
 
4427
                return(PAGE_CUR_LE);
 
4428
                /* In MySQL-4.0 HA_READ_PREFIX and HA_READ_PREFIX_LAST always
 
4429
                pass a complete-field prefix of a key value as the search
 
4430
                tuple. I.e., it is not allowed that the last field would
 
4431
                just contain n first bytes of the full field value.
 
4432
                MySQL uses a 'padding' trick to convert LIKE 'abc%'
 
4433
                type queries so that it can use as a search tuple
 
4434
                a complete-field-prefix of a key value. Thus, the InnoDB
 
4435
                search mode PAGE_CUR_LE_OR_EXTENDS is never used.
 
4436
                TODO: when/if MySQL starts to use also partial-field
 
4437
                prefixes, we have to deal with stripping of spaces
 
4438
                and comparison of non-latin1 char type fields in
 
4439
                innobase_mysql_cmp() to get PAGE_CUR_LE_OR_EXTENDS to
 
4440
                work correctly. */
 
4441
        case HA_READ_MBR_CONTAIN:
 
4442
        case HA_READ_MBR_INTERSECT:
 
4443
        case HA_READ_MBR_WITHIN:
 
4444
        case HA_READ_MBR_DISJOINT:
 
4445
        case HA_READ_MBR_EQUAL:
 
4446
                return(PAGE_CUR_UNSUPP);
 
4447
        /* do not use "default:" in order to produce a gcc warning:
 
4448
        enumeration value '...' not handled in switch
 
4449
        (if -Wswitch or -Wall is used) */
 
4450
        }
 
4451
 
 
4452
        my_error(ER_CHECK_NOT_IMPLEMENTED, MYF(0), "this functionality");
 
4453
 
 
4454
        return(PAGE_CUR_UNSUPP);
4992
4455
}
4993
4456
 
4994
4457
/*
5052
4515
/**********************************************************************//**
5053
4516
Positions an index cursor to the index specified in the handle. Fetches the
5054
4517
row if any.
5055
 
@return 0, HA_ERR_KEY_NOT_FOUND, or error number */
 
4518
@return 0, HA_ERR_KEY_NOT_FOUND, or error number */
5056
4519
UNIV_INTERN
5057
4520
int
5058
4521
ha_innobase::index_read(
5059
4522
/*====================*/
5060
 
  unsigned char*    buf,  /*!< in/out: buffer for the returned
5061
 
          row */
5062
 
  const unsigned char*  key_ptr,/*!< in: key value; if this is NULL
5063
 
          we position the cursor at the
5064
 
          start or end of index; this can
5065
 
          also contain an InnoDB row id, in
5066
 
          which case key_len is the InnoDB
5067
 
          row id length; the key value can
5068
 
          also be a prefix of a full key value,
5069
 
          and the last column can be a prefix
5070
 
          of a full column */
5071
 
  uint      key_len,/*!< in: key value length */
5072
 
  enum ha_rkey_function find_flag)/*!< in: search flags from my_base.h */
 
4523
        unsigned char*          buf,    /*!< in/out: buffer for the returned
 
4524
                                        row */
 
4525
        const unsigned char*    key_ptr,/*!< in: key value; if this is NULL
 
4526
                                        we position the cursor at the
 
4527
                                        start or end of index; this can
 
4528
                                        also contain an InnoDB row id, in
 
4529
                                        which case key_len is the InnoDB
 
4530
                                        row id length; the key value can
 
4531
                                        also be a prefix of a full key value,
 
4532
                                        and the last column can be a prefix
 
4533
                                        of a full column */
 
4534
        uint                    key_len,/*!< in: key value length */
 
4535
        enum ha_rkey_function find_flag)/*!< in: search flags from my_base.h */
5073
4536
{
5074
 
  ulint   mode;
5075
 
  dict_index_t* index;
5076
 
  ulint   match_mode  = 0;
5077
 
  int   error;
5078
 
  ulint   ret;
5079
 
 
5080
 
  ut_a(prebuilt->trx == session_to_trx(user_session));
5081
 
 
5082
 
  ha_statistic_increment(&system_status_var::ha_read_key_count);
5083
 
 
5084
 
  index = prebuilt->index;
5085
 
 
5086
 
  if (UNIV_UNLIKELY(index == NULL)) {
5087
 
    prebuilt->index_usable = FALSE;
5088
 
    return(HA_ERR_CRASHED);
5089
 
  }
5090
 
 
5091
 
 
5092
 
  /* Note that if the index for which the search template is built is not
5093
 
  necessarily prebuilt->index, but can also be the clustered index */
5094
 
 
5095
 
  if (prebuilt->sql_stat_start) {
5096
 
    build_template(prebuilt, user_session, getTable(),
5097
 
             ROW_MYSQL_REC_FIELDS);
5098
 
  }
5099
 
 
5100
 
  if (key_ptr) {
5101
 
    /* Convert the search key value to InnoDB format into
5102
 
    prebuilt->search_tuple */
5103
 
 
5104
 
    row_sel_convert_mysql_key_to_innobase(
5105
 
      prebuilt->search_tuple,
5106
 
      (byte*) &key_val_buff[0],
5107
 
      (ulint)upd_and_key_val_buff_len,
5108
 
      index,
5109
 
      (byte*) key_ptr,
5110
 
      (ulint) key_len,
5111
 
      prebuilt->trx);
5112
 
  } else {
5113
 
    /* We position the cursor to the last or the first entry
5114
 
    in the index */
5115
 
 
5116
 
    dtuple_set_n_fields(prebuilt->search_tuple, 0);
5117
 
  }
5118
 
 
5119
 
  mode = convert_search_mode_to_innobase(find_flag);
5120
 
 
5121
 
  match_mode = 0;
5122
 
 
5123
 
  if (find_flag == HA_READ_KEY_EXACT) {
5124
 
 
5125
 
    match_mode = ROW_SEL_EXACT;
5126
 
 
5127
 
  } else if (find_flag == HA_READ_PREFIX
5128
 
       || find_flag == HA_READ_PREFIX_LAST) {
5129
 
 
5130
 
    match_mode = ROW_SEL_EXACT_PREFIX;
5131
 
  }
5132
 
 
5133
 
  last_match_mode = (uint) match_mode;
5134
 
 
5135
 
  if (mode != PAGE_CUR_UNSUPP) {
5136
 
 
5137
 
    innodb_srv_conc_enter_innodb(prebuilt->trx);
5138
 
 
5139
 
    ret = row_search_for_mysql((byte*) buf, mode, prebuilt,
5140
 
             match_mode, 0);
5141
 
 
5142
 
    innodb_srv_conc_exit_innodb(prebuilt->trx);
5143
 
  } else {
5144
 
 
5145
 
    ret = DB_UNSUPPORTED;
5146
 
  }
5147
 
 
5148
 
  switch (ret) {
5149
 
  case DB_SUCCESS:
5150
 
    error = 0;
5151
 
    getTable()->status = 0;
5152
 
    break;
5153
 
  case DB_RECORD_NOT_FOUND:
5154
 
    error = HA_ERR_KEY_NOT_FOUND;
5155
 
    getTable()->status = STATUS_NOT_FOUND;
5156
 
    break;
5157
 
  case DB_END_OF_INDEX:
5158
 
    error = HA_ERR_KEY_NOT_FOUND;
5159
 
    getTable()->status = STATUS_NOT_FOUND;
5160
 
    break;
5161
 
  default:
5162
 
    error = convert_error_code_to_mysql((int) ret,
5163
 
                prebuilt->table->flags,
5164
 
                user_session);
5165
 
    getTable()->status = STATUS_NOT_FOUND;
5166
 
    break;
5167
 
  }
5168
 
 
5169
 
  return(error);
 
4537
        ulint           mode;
 
4538
        dict_index_t*   index;
 
4539
        ulint           match_mode      = 0;
 
4540
        int             error;
 
4541
        ulint           ret;
 
4542
 
 
4543
        ut_a(prebuilt->trx == session_to_trx(user_session));
 
4544
 
 
4545
        ha_statistic_increment(&system_status_var::ha_read_key_count);
 
4546
 
 
4547
        index = prebuilt->index;
 
4548
 
 
4549
        /* Note that if the index for which the search template is built is not
 
4550
        necessarily prebuilt->index, but can also be the clustered index */
 
4551
 
 
4552
        if (prebuilt->sql_stat_start) {
 
4553
                build_template(prebuilt, user_session, table,
 
4554
                               ROW_MYSQL_REC_FIELDS);
 
4555
        }
 
4556
 
 
4557
        if (key_ptr) {
 
4558
                /* Convert the search key value to InnoDB format into
 
4559
                prebuilt->search_tuple */
 
4560
 
 
4561
                row_sel_convert_mysql_key_to_innobase(
 
4562
                        prebuilt->search_tuple,
 
4563
                        (byte*) key_val_buff,
 
4564
                        (ulint)upd_and_key_val_buff_len,
 
4565
                        index,
 
4566
                        (byte*) key_ptr,
 
4567
                        (ulint) key_len,
 
4568
                        prebuilt->trx);
 
4569
        } else {
 
4570
                /* We position the cursor to the last or the first entry
 
4571
                in the index */
 
4572
 
 
4573
                dtuple_set_n_fields(prebuilt->search_tuple, 0);
 
4574
        }
 
4575
 
 
4576
        mode = convert_search_mode_to_innobase(find_flag);
 
4577
 
 
4578
        match_mode = 0;
 
4579
 
 
4580
        if (find_flag == HA_READ_KEY_EXACT) {
 
4581
 
 
4582
                match_mode = ROW_SEL_EXACT;
 
4583
 
 
4584
        } else if (find_flag == HA_READ_PREFIX
 
4585
                   || find_flag == HA_READ_PREFIX_LAST) {
 
4586
 
 
4587
                match_mode = ROW_SEL_EXACT_PREFIX;
 
4588
        }
 
4589
 
 
4590
        last_match_mode = (uint) match_mode;
 
4591
 
 
4592
        if (mode != PAGE_CUR_UNSUPP) {
 
4593
 
 
4594
                innodb_srv_conc_enter_innodb(prebuilt->trx);
 
4595
 
 
4596
                ret = row_search_for_mysql((byte*) buf, mode, prebuilt,
 
4597
                                           match_mode, 0);
 
4598
 
 
4599
                innodb_srv_conc_exit_innodb(prebuilt->trx);
 
4600
        } else {
 
4601
 
 
4602
                ret = DB_UNSUPPORTED;
 
4603
        }
 
4604
 
 
4605
        switch (ret) {
 
4606
        case DB_SUCCESS:
 
4607
                error = 0;
 
4608
                table->status = 0;
 
4609
                break;
 
4610
        case DB_RECORD_NOT_FOUND:
 
4611
                error = HA_ERR_KEY_NOT_FOUND;
 
4612
                table->status = STATUS_NOT_FOUND;
 
4613
                break;
 
4614
        case DB_END_OF_INDEX:
 
4615
                error = HA_ERR_KEY_NOT_FOUND;
 
4616
                table->status = STATUS_NOT_FOUND;
 
4617
                break;
 
4618
        default:
 
4619
                error = convert_error_code_to_mysql((int) ret,
 
4620
                                                    prebuilt->table->flags,
 
4621
                                                    user_session);
 
4622
                table->status = STATUS_NOT_FOUND;
 
4623
                break;
 
4624
        }
 
4625
 
 
4626
        return(error);
5170
4627
}
5171
4628
 
5172
4629
/*******************************************************************//**
5173
4630
The following functions works like index_read, but it find the last
5174
4631
row with the current key value or prefix.
5175
 
@return 0, HA_ERR_KEY_NOT_FOUND, or an error code */
 
4632
@return 0, HA_ERR_KEY_NOT_FOUND, or an error code */
5176
4633
UNIV_INTERN
5177
4634
int
5178
4635
ha_innobase::index_read_last(
5179
4636
/*=========================*/
5180
 
  unsigned char*  buf,  /*!< out: fetched row */
5181
 
  const unsigned char*  key_ptr,/*!< in: key value, or a prefix of a full
5182
 
        key value */
5183
 
  uint    key_len)/*!< in: length of the key val or prefix
5184
 
        in bytes */
 
4637
        unsigned char*  buf,    /*!< out: fetched row */
 
4638
        const unsigned char*    key_ptr,/*!< in: key value, or a prefix of a full
 
4639
                                key value */
 
4640
        uint            key_len)/*!< in: length of the key val or prefix
 
4641
                                in bytes */
5185
4642
{
5186
 
  return(index_read(buf, key_ptr, key_len, HA_READ_PREFIX_LAST));
 
4643
        return(index_read(buf, key_ptr, key_len, HA_READ_PREFIX_LAST));
5187
4644
}
5188
4645
 
5189
4646
/********************************************************************//**
5190
4647
Get the index for a handle. Does not change active index.
5191
 
@return NULL or index instance. */
 
4648
@return NULL or index instance. */
5192
4649
UNIV_INTERN
5193
4650
dict_index_t*
5194
4651
ha_innobase::innobase_get_index(
5195
4652
/*============================*/
5196
 
  uint    keynr)  /*!< in: use this index; MAX_KEY means always
5197
 
        clustered index, even if it was internally
5198
 
        generated by InnoDB */
 
4653
        uint            keynr)  /*!< in: use this index; MAX_KEY means always
 
4654
                                clustered index, even if it was internally
 
4655
                                generated by InnoDB */
5199
4656
{
5200
 
  dict_index_t* index = 0;
5201
 
 
5202
 
  ha_statistic_increment(&system_status_var::ha_read_key_count);
5203
 
 
5204
 
  if (keynr != MAX_KEY && getTable()->getShare()->sizeKeys() > 0) 
5205
 
  {
5206
 
    KeyInfo *key = getTable()->key_info + keynr;
5207
 
    index = innobase_index_lookup(share, keynr);
5208
 
 
5209
 
    if (index) {
5210
 
      ut_a(ut_strcmp(index->name, key->name) == 0);
5211
 
    } else {
5212
 
      /* Can't find index with keynr in the translation
5213
 
         table. Only print message if the index translation
5214
 
         table exists */
5215
 
      if (share->idx_trans_tbl.index_mapping) {
5216
 
        errmsg_printf(ERRMSG_LVL_ERROR,
5217
 
                      "InnoDB could not find "
5218
 
                      "index %s key no %u for "
5219
 
                      "table %s through its "
5220
 
                      "index translation table",
5221
 
                      key ? key->name : "NULL",
5222
 
                      keynr,
5223
 
                      prebuilt->table->name);
5224
 
      }
5225
 
 
5226
 
      index = dict_table_get_index_on_name(prebuilt->table,
5227
 
                                           key->name);
5228
 
    }
5229
 
  } else {
5230
 
    index = dict_table_get_first_index(prebuilt->table);
5231
 
  }
5232
 
 
5233
 
  if (!index) {
5234
 
    errmsg_printf(ERRMSG_LVL_ERROR, 
5235
 
      "Innodb could not find key n:o %u with name %s "
5236
 
      "from dict cache for table %s",
5237
 
      keynr, getTable()->getShare()->getTableProto()->indexes(keynr).name().c_str(),
5238
 
      prebuilt->table->name);
5239
 
  }
5240
 
 
5241
 
  return(index);
 
4657
        KEY*            key = 0;
 
4658
        dict_index_t*   index = 0;
 
4659
 
 
4660
        ha_statistic_increment(&system_status_var::ha_read_key_count);
 
4661
 
 
4662
        ut_ad(user_session == ha_session());
 
4663
        ut_a(prebuilt->trx == session_to_trx(user_session));
 
4664
 
 
4665
        if (keynr != MAX_KEY && table->s->keys > 0) {
 
4666
                key = table->key_info + keynr;
 
4667
 
 
4668
                index = dict_table_get_index_on_name(prebuilt->table,
 
4669
                                                     key->name);
 
4670
        } else {
 
4671
                index = dict_table_get_first_index(prebuilt->table);
 
4672
        }
 
4673
 
 
4674
        if (!index) {
 
4675
                errmsg_printf(ERRMSG_LVL_ERROR, 
 
4676
                        "Innodb could not find key n:o %u with name %s "
 
4677
                        "from dict cache for table %s",
 
4678
                        keynr, key ? key->name : "NULL",
 
4679
                        prebuilt->table->name);
 
4680
        }
 
4681
 
 
4682
        return(index);
5242
4683
}
5243
4684
 
5244
4685
/********************************************************************//**
5245
4686
Changes the active index of a handle.
5246
 
@return 0 or error code */
 
4687
@return 0 or error code */
5247
4688
UNIV_INTERN
5248
4689
int
5249
4690
ha_innobase::change_active_index(
5250
4691
/*=============================*/
5251
 
  uint  keynr)  /*!< in: use this index; MAX_KEY means always clustered
5252
 
      index, even if it was internally generated by
5253
 
      InnoDB */
 
4692
        uint    keynr)  /*!< in: use this index; MAX_KEY means always clustered
 
4693
                        index, even if it was internally generated by
 
4694
                        InnoDB */
5254
4695
{
5255
 
  ut_ad(user_session == table->in_use);
5256
 
  ut_a(prebuilt->trx == session_to_trx(user_session));
5257
 
 
5258
 
  active_index = keynr;
5259
 
 
5260
 
  prebuilt->index = innobase_get_index(keynr);
5261
 
 
5262
 
  if (UNIV_UNLIKELY(!prebuilt->index)) {
5263
 
    errmsg_printf(ERRMSG_LVL_WARN, "InnoDB: change_active_index(%u) failed",
5264
 
          keynr);
5265
 
    prebuilt->index_usable = FALSE;
5266
 
    return(1);
5267
 
  }
5268
 
 
5269
 
  prebuilt->index_usable = row_merge_is_index_usable(prebuilt->trx,
5270
 
                 prebuilt->index);
5271
 
 
5272
 
  if (UNIV_UNLIKELY(!prebuilt->index_usable)) {
5273
 
    push_warning_printf(user_session, DRIZZLE_ERROR::WARN_LEVEL_WARN,
5274
 
                        HA_ERR_TABLE_DEF_CHANGED,
5275
 
                        "InnoDB: insufficient history for index %u",
5276
 
                        keynr);
5277
 
    /* The caller seems to ignore this.  Thus, we must check
5278
 
    this again in row_search_for_mysql(). */
5279
 
    return(2);
5280
 
  }
5281
 
 
5282
 
  ut_a(prebuilt->search_tuple != 0);
5283
 
 
5284
 
  dtuple_set_n_fields(prebuilt->search_tuple, prebuilt->index->n_fields);
5285
 
 
5286
 
  dict_index_copy_types(prebuilt->search_tuple, prebuilt->index,
5287
 
      prebuilt->index->n_fields);
5288
 
 
5289
 
  /* MySQL changes the active index for a handle also during some
5290
 
  queries, for example SELECT MAX(a), SUM(a) first retrieves the MAX()
5291
 
  and then calculates the sum. Previously we played safe and used
5292
 
  the flag ROW_MYSQL_WHOLE_ROW below, but that caused unnecessary
5293
 
  copying. Starting from MySQL-4.1 we use a more efficient flag here. */
5294
 
 
5295
 
  build_template(prebuilt, user_session, getTable(), ROW_MYSQL_REC_FIELDS);
5296
 
 
5297
 
  return(0);
 
4696
        ut_ad(user_session == ha_session());
 
4697
        ut_a(prebuilt->trx == session_to_trx(user_session));
 
4698
 
 
4699
        active_index = keynr;
 
4700
 
 
4701
        prebuilt->index = innobase_get_index(keynr);
 
4702
 
 
4703
        if (UNIV_UNLIKELY(!prebuilt->index)) {
 
4704
                errmsg_printf(ERRMSG_LVL_WARN, "InnoDB: change_active_index(%u) failed",
 
4705
                                  keynr);
 
4706
                return(1);
 
4707
        }
 
4708
 
 
4709
        prebuilt->index_usable = row_merge_is_index_usable(prebuilt->trx,
 
4710
                                                           prebuilt->index);
 
4711
 
 
4712
        if (UNIV_UNLIKELY(!prebuilt->index_usable)) {
 
4713
                errmsg_printf(ERRMSG_LVL_WARN,
 
4714
                                 "InnoDB: insufficient history for index %u",
 
4715
                                  keynr);
 
4716
                /* The caller seems to ignore this.  Thus, we must check
 
4717
                this again in row_search_for_mysql(). */
 
4718
                return(2);
 
4719
        }
 
4720
 
 
4721
        ut_a(prebuilt->search_tuple != 0);
 
4722
 
 
4723
        dtuple_set_n_fields(prebuilt->search_tuple, prebuilt->index->n_fields);
 
4724
 
 
4725
        dict_index_copy_types(prebuilt->search_tuple, prebuilt->index,
 
4726
                        prebuilt->index->n_fields);
 
4727
 
 
4728
        /* MySQL changes the active index for a handle also during some
 
4729
        queries, for example SELECT MAX(a), SUM(a) first retrieves the MAX()
 
4730
        and then calculates the sum. Previously we played safe and used
 
4731
        the flag ROW_MYSQL_WHOLE_ROW below, but that caused unnecessary
 
4732
        copying. Starting from MySQL-4.1 we use a more efficient flag here. */
 
4733
 
 
4734
        build_template(prebuilt, user_session, table, ROW_MYSQL_REC_FIELDS);
 
4735
 
 
4736
        return(0);
5298
4737
}
5299
4738
 
5300
4739
/**********************************************************************//**
5301
4740
Positions an index cursor to the index specified in keynr. Fetches the
5302
4741
row if any.
5303
4742
??? This is only used to read whole keys ???
5304
 
@return error number or 0 */
 
4743
@return error number or 0 */
5305
4744
UNIV_INTERN
5306
4745
int
5307
4746
ha_innobase::index_read_idx(
5308
4747
/*========================*/
5309
 
  unsigned char*  buf,    /*!< in/out: buffer for the returned
5310
 
          row */
5311
 
  uint    keynr,    /*!< in: use this index */
5312
 
  const unsigned char*  key,  /*!< in: key value; if this is NULL
5313
 
          we position the cursor at the
5314
 
          start or end of index */
5315
 
  uint    key_len,  /*!< in: key value length */
5316
 
  enum ha_rkey_function find_flag)/*!< in: search flags from my_base.h */
 
4748
        unsigned char*  buf,            /*!< in/out: buffer for the returned
 
4749
                                        row */
 
4750
        uint            keynr,          /*!< in: use this index */
 
4751
        const unsigned char*    key,    /*!< in: key value; if this is NULL
 
4752
                                        we position the cursor at the
 
4753
                                        start or end of index */
 
4754
        uint            key_len,        /*!< in: key value length */
 
4755
        enum ha_rkey_function find_flag)/*!< in: search flags from my_base.h */
5317
4756
{
5318
 
  if (change_active_index(keynr)) {
5319
 
 
5320
 
    return(1);
5321
 
  }
5322
 
 
5323
 
  return(index_read(buf, key, key_len, find_flag));
 
4757
        if (change_active_index(keynr)) {
 
4758
 
 
4759
                return(1);
 
4760
        }
 
4761
 
 
4762
        return(index_read(buf, key, key_len, find_flag));
5324
4763
}
5325
4764
 
5326
4765
/***********************************************************************//**
5327
4766
Reads the next or previous row from a cursor, which must have previously been
5328
4767
positioned using index_read.
5329
 
@return 0, HA_ERR_END_OF_FILE, or error number */
 
4768
@return 0, HA_ERR_END_OF_FILE, or error number */
5330
4769
UNIV_INTERN
5331
4770
int
5332
4771
ha_innobase::general_fetch(
5333
4772
/*=======================*/
5334
 
  unsigned char*  buf,  /*!< in/out: buffer for next row in MySQL
5335
 
        format */
5336
 
  uint  direction,  /*!< in: ROW_SEL_NEXT or ROW_SEL_PREV */
5337
 
  uint  match_mode) /*!< in: 0, ROW_SEL_EXACT, or
5338
 
        ROW_SEL_EXACT_PREFIX */
 
4773
        unsigned char*  buf,    /*!< in/out: buffer for next row in MySQL
 
4774
                                format */
 
4775
        uint    direction,      /*!< in: ROW_SEL_NEXT or ROW_SEL_PREV */
 
4776
        uint    match_mode)     /*!< in: 0, ROW_SEL_EXACT, or
 
4777
                                ROW_SEL_EXACT_PREFIX */
5339
4778
{
5340
 
  ulint   ret;
5341
 
  int   error = 0;
5342
 
 
5343
 
  ut_a(prebuilt->trx == session_to_trx(user_session));
5344
 
 
5345
 
  innodb_srv_conc_enter_innodb(prebuilt->trx);
5346
 
 
5347
 
  ret = row_search_for_mysql(
5348
 
    (byte*)buf, 0, prebuilt, match_mode, direction);
5349
 
 
5350
 
  innodb_srv_conc_exit_innodb(prebuilt->trx);
5351
 
 
5352
 
  switch (ret) {
5353
 
  case DB_SUCCESS:
5354
 
    error = 0;
5355
 
    getTable()->status = 0;
5356
 
    break;
5357
 
  case DB_RECORD_NOT_FOUND:
5358
 
    error = HA_ERR_END_OF_FILE;
5359
 
    getTable()->status = STATUS_NOT_FOUND;
5360
 
    break;
5361
 
  case DB_END_OF_INDEX:
5362
 
    error = HA_ERR_END_OF_FILE;
5363
 
    getTable()->status = STATUS_NOT_FOUND;
5364
 
    break;
5365
 
  default:
5366
 
    error = convert_error_code_to_mysql(
5367
 
      (int) ret, prebuilt->table->flags, user_session);
5368
 
    getTable()->status = STATUS_NOT_FOUND;
5369
 
    break;
5370
 
  }
5371
 
 
5372
 
  return(error);
 
4779
        ulint           ret;
 
4780
        int             error   = 0;
 
4781
 
 
4782
        ut_a(prebuilt->trx == session_to_trx(user_session));
 
4783
 
 
4784
        innodb_srv_conc_enter_innodb(prebuilt->trx);
 
4785
 
 
4786
        ret = row_search_for_mysql(
 
4787
                (byte*)buf, 0, prebuilt, match_mode, direction);
 
4788
 
 
4789
        innodb_srv_conc_exit_innodb(prebuilt->trx);
 
4790
 
 
4791
        switch (ret) {
 
4792
        case DB_SUCCESS:
 
4793
                error = 0;
 
4794
                table->status = 0;
 
4795
                break;
 
4796
        case DB_RECORD_NOT_FOUND:
 
4797
                error = HA_ERR_END_OF_FILE;
 
4798
                table->status = STATUS_NOT_FOUND;
 
4799
                break;
 
4800
        case DB_END_OF_INDEX:
 
4801
                error = HA_ERR_END_OF_FILE;
 
4802
                table->status = STATUS_NOT_FOUND;
 
4803
                break;
 
4804
        default:
 
4805
                error = convert_error_code_to_mysql(
 
4806
                        (int) ret, prebuilt->table->flags, user_session);
 
4807
                table->status = STATUS_NOT_FOUND;
 
4808
                break;
 
4809
        }
 
4810
 
 
4811
        return(error);
5373
4812
}
5374
4813
 
5375
4814
/***********************************************************************//**
5376
4815
Reads the next row from a cursor, which must have previously been
5377
4816
positioned using index_read.
5378
 
@return 0, HA_ERR_END_OF_FILE, or error number */
 
4817
@return 0, HA_ERR_END_OF_FILE, or error number */
5379
4818
UNIV_INTERN
5380
4819
int
5381
4820
ha_innobase::index_next(
5382
4821
/*====================*/
5383
 
  unsigned char*  buf)  /*!< in/out: buffer for next row in MySQL
5384
 
        format */
 
4822
        unsigned char*  buf)    /*!< in/out: buffer for next row in MySQL
 
4823
                                format */
5385
4824
{
5386
 
  ha_statistic_increment(&system_status_var::ha_read_next_count);
 
4825
        ha_statistic_increment(&system_status_var::ha_read_next_count);
5387
4826
 
5388
 
  return(general_fetch(buf, ROW_SEL_NEXT, 0));
 
4827
        return(general_fetch(buf, ROW_SEL_NEXT, 0));
5389
4828
}
5390
4829
 
5391
4830
/*******************************************************************//**
5392
4831
Reads the next row matching to the key value given as the parameter.
5393
 
@return 0, HA_ERR_END_OF_FILE, or error number */
 
4832
@return 0, HA_ERR_END_OF_FILE, or error number */
5394
4833
UNIV_INTERN
5395
4834
int
5396
4835
ha_innobase::index_next_same(
5397
4836
/*=========================*/
5398
 
  unsigned char*    buf,  /*!< in/out: buffer for the row */
5399
 
  const unsigned char*  , /*!< in: key value */
5400
 
  uint    ) /*!< in: key value length */
 
4837
        unsigned char*          buf,    /*!< in/out: buffer for the row */
 
4838
        const unsigned char*    ,       /*!< in: key value */
 
4839
        uint            )       /*!< in: key value length */
5401
4840
{
5402
 
  ha_statistic_increment(&system_status_var::ha_read_next_count);
 
4841
        ha_statistic_increment(&system_status_var::ha_read_next_count);
5403
4842
 
5404
 
  return(general_fetch(buf, ROW_SEL_NEXT, last_match_mode));
 
4843
        return(general_fetch(buf, ROW_SEL_NEXT, last_match_mode));
5405
4844
}
5406
4845
 
5407
4846
/***********************************************************************//**
5408
4847
Reads the previous row from a cursor, which must have previously been
5409
4848
positioned using index_read.
5410
 
@return 0, HA_ERR_END_OF_FILE, or error number */
 
4849
@return 0, HA_ERR_END_OF_FILE, or error number */
5411
4850
UNIV_INTERN
5412
4851
int
5413
4852
ha_innobase::index_prev(
5414
4853
/*====================*/
5415
 
  unsigned char*  buf)  /*!< in/out: buffer for previous row in MySQL format */
 
4854
        unsigned char*  buf)    /*!< in/out: buffer for previous row in MySQL format */
5416
4855
{
5417
 
  ha_statistic_increment(&system_status_var::ha_read_prev_count);
 
4856
        ha_statistic_increment(&system_status_var::ha_read_prev_count);
5418
4857
 
5419
 
  return(general_fetch(buf, ROW_SEL_PREV, 0));
 
4858
        return(general_fetch(buf, ROW_SEL_PREV, 0));
5420
4859
}
5421
4860
 
5422
4861
/********************************************************************//**
5423
4862
Positions a cursor on the first record in an index and reads the
5424
4863
corresponding row to buf.
5425
 
@return 0, HA_ERR_END_OF_FILE, or error code */
 
4864
@return 0, HA_ERR_END_OF_FILE, or error code */
5426
4865
UNIV_INTERN
5427
4866
int
5428
4867
ha_innobase::index_first(
5429
4868
/*=====================*/
5430
 
  unsigned char*  buf)  /*!< in/out: buffer for the row */
 
4869
        unsigned char*  buf)    /*!< in/out: buffer for the row */
5431
4870
{
5432
 
  int error;
5433
 
 
5434
 
  ha_statistic_increment(&system_status_var::ha_read_first_count);
5435
 
 
5436
 
  error = index_read(buf, NULL, 0, HA_READ_AFTER_KEY);
5437
 
 
5438
 
  /* MySQL does not seem to allow this to return HA_ERR_KEY_NOT_FOUND */
5439
 
 
5440
 
  if (error == HA_ERR_KEY_NOT_FOUND) {
5441
 
    error = HA_ERR_END_OF_FILE;
5442
 
  }
5443
 
 
5444
 
  return(error);
 
4871
        int     error;
 
4872
 
 
4873
        ha_statistic_increment(&system_status_var::ha_read_first_count);
 
4874
 
 
4875
        error = index_read(buf, NULL, 0, HA_READ_AFTER_KEY);
 
4876
 
 
4877
        /* MySQL does not seem to allow this to return HA_ERR_KEY_NOT_FOUND */
 
4878
 
 
4879
        if (error == HA_ERR_KEY_NOT_FOUND) {
 
4880
                error = HA_ERR_END_OF_FILE;
 
4881
        }
 
4882
 
 
4883
        return(error);
5445
4884
}
5446
4885
 
5447
4886
/********************************************************************//**
5448
4887
Positions a cursor on the last record in an index and reads the
5449
4888
corresponding row to buf.
5450
 
@return 0, HA_ERR_END_OF_FILE, or error code */
 
4889
@return 0, HA_ERR_END_OF_FILE, or error code */
5451
4890
UNIV_INTERN
5452
4891
int
5453
4892
ha_innobase::index_last(
5454
4893
/*====================*/
5455
 
  unsigned char*  buf)  /*!< in/out: buffer for the row */
 
4894
        unsigned char*  buf)    /*!< in/out: buffer for the row */
5456
4895
{
5457
 
  int error;
5458
 
 
5459
 
  ha_statistic_increment(&system_status_var::ha_read_last_count);
5460
 
 
5461
 
  error = index_read(buf, NULL, 0, HA_READ_BEFORE_KEY);
5462
 
 
5463
 
  /* MySQL does not seem to allow this to return HA_ERR_KEY_NOT_FOUND */
5464
 
 
5465
 
  if (error == HA_ERR_KEY_NOT_FOUND) {
5466
 
    error = HA_ERR_END_OF_FILE;
5467
 
  }
5468
 
 
5469
 
  return(error);
 
4896
        int     error;
 
4897
 
 
4898
        ha_statistic_increment(&system_status_var::ha_read_last_count);
 
4899
 
 
4900
        error = index_read(buf, NULL, 0, HA_READ_BEFORE_KEY);
 
4901
 
 
4902
        /* MySQL does not seem to allow this to return HA_ERR_KEY_NOT_FOUND */
 
4903
 
 
4904
        if (error == HA_ERR_KEY_NOT_FOUND) {
 
4905
                error = HA_ERR_END_OF_FILE;
 
4906
        }
 
4907
 
 
4908
        return(error);
5470
4909
}
5471
4910
 
5472
4911
/****************************************************************//**
5473
4912
Initialize a table scan.
5474
 
@return 0 or error number */
 
4913
@return 0 or error number */
5475
4914
UNIV_INTERN
5476
4915
int
5477
 
ha_innobase::doStartTableScan(
 
4916
ha_innobase::rnd_init(
5478
4917
/*==================*/
5479
 
  bool  scan) /*!< in: TRUE if table/index scan FALSE otherwise */
 
4918
        bool    scan)   /*!< in: TRUE if table/index scan FALSE otherwise */
5480
4919
{
5481
 
  int err;
5482
 
 
5483
 
  /* Store the active index value so that we can restore the original
5484
 
  value after a scan */
5485
 
 
5486
 
  if (prebuilt->clust_index_was_generated) {
5487
 
    err = change_active_index(MAX_KEY);
5488
 
  } else {
5489
 
    err = change_active_index(primary_key);
5490
 
  }
5491
 
 
5492
 
  /* Don't use semi-consistent read in random row reads (by position).
5493
 
  This means we must disable semi_consistent_read if scan is false */
5494
 
 
5495
 
  if (!scan) {
5496
 
    try_semi_consistent_read(0);
5497
 
  }
5498
 
 
5499
 
  start_of_scan = 1;
5500
 
 
5501
 
  return(err);
 
4920
        int     err;
 
4921
 
 
4922
        /* Store the active index value so that we can restore the original
 
4923
        value after a scan */
 
4924
 
 
4925
        if (prebuilt->clust_index_was_generated) {
 
4926
                err = change_active_index(MAX_KEY);
 
4927
        } else {
 
4928
                err = change_active_index(primary_key);
 
4929
        }
 
4930
 
 
4931
        /* Don't use semi-consistent read in random row reads (by position).
 
4932
        This means we must disable semi_consistent_read if scan is false */
 
4933
 
 
4934
        if (!scan) {
 
4935
                try_semi_consistent_read(0);
 
4936
        }
 
4937
 
 
4938
        start_of_scan = 1;
 
4939
 
 
4940
        return(err);
5502
4941
}
5503
4942
 
5504
4943
/*****************************************************************//**
5505
4944
Ends a table scan.
5506
 
@return 0 or error number */
 
4945
@return 0 or error number */
5507
4946
UNIV_INTERN
5508
4947
int
5509
 
ha_innobase::doEndTableScan(void)
 
4948
ha_innobase::rnd_end(void)
5510
4949
/*======================*/
5511
4950
{
5512
 
  return(doEndIndexScan());
 
4951
        return(index_end());
5513
4952
}
5514
4953
 
5515
4954
/*****************************************************************//**
5516
4955
Reads the next row in a table scan (also used to read the FIRST row
5517
4956
in a table scan).
5518
 
@return 0, HA_ERR_END_OF_FILE, or error number */
 
4957
@return 0, HA_ERR_END_OF_FILE, or error number */
5519
4958
UNIV_INTERN
5520
4959
int
5521
4960
ha_innobase::rnd_next(
5522
4961
/*==================*/
5523
 
  unsigned char*  buf)  /*!< in/out: returns the row in this buffer,
5524
 
      in MySQL format */
 
4962
        unsigned char*  buf)    /*!< in/out: returns the row in this buffer,
 
4963
                        in MySQL format */
5525
4964
{
5526
 
  int error;
5527
 
 
5528
 
  ha_statistic_increment(&system_status_var::ha_read_rnd_next_count);
5529
 
 
5530
 
  if (start_of_scan) {
5531
 
    error = index_first(buf);
5532
 
 
5533
 
    if (error == HA_ERR_KEY_NOT_FOUND) {
5534
 
      error = HA_ERR_END_OF_FILE;
5535
 
    }
5536
 
 
5537
 
    start_of_scan = 0;
5538
 
  } else {
5539
 
    error = general_fetch(buf, ROW_SEL_NEXT, 0);
5540
 
  }
5541
 
 
5542
 
  return(error);
 
4965
        int     error;
 
4966
 
 
4967
        ha_statistic_increment(&system_status_var::ha_read_rnd_next_count);
 
4968
 
 
4969
        if (start_of_scan) {
 
4970
                error = index_first(buf);
 
4971
 
 
4972
                if (error == HA_ERR_KEY_NOT_FOUND) {
 
4973
                        error = HA_ERR_END_OF_FILE;
 
4974
                }
 
4975
 
 
4976
                start_of_scan = 0;
 
4977
        } else {
 
4978
                error = general_fetch(buf, ROW_SEL_NEXT, 0);
 
4979
        }
 
4980
 
 
4981
        return(error);
5543
4982
}
5544
4983
 
5545
4984
/**********************************************************************//**
5546
4985
Fetches a row from the table based on a row reference.
5547
 
@return 0, HA_ERR_KEY_NOT_FOUND, or error code */
 
4986
@return 0, HA_ERR_KEY_NOT_FOUND, or error code */
5548
4987
UNIV_INTERN
5549
4988
int
5550
4989
ha_innobase::rnd_pos(
5551
4990
/*=================*/
5552
 
  unsigned char*  buf,  /*!< in/out: buffer for the row */
5553
 
  unsigned char*  pos)  /*!< in: primary key value of the row in the
5554
 
      MySQL format, or the row id if the clustered
5555
 
      index was internally generated by InnoDB; the
5556
 
      length of data in pos has to be ref_length */
 
4991
        unsigned char*  buf,    /*!< in/out: buffer for the row */
 
4992
        unsigned char*  pos)    /*!< in: primary key value of the row in the
 
4993
                        MySQL format, or the row id if the clustered
 
4994
                        index was internally generated by InnoDB; the
 
4995
                        length of data in pos has to be ref_length */
5557
4996
{
5558
 
  int   error;
5559
 
  uint    keynr = active_index;
5560
 
 
5561
 
  ha_statistic_increment(&system_status_var::ha_read_rnd_count);
5562
 
 
5563
 
  ut_a(prebuilt->trx == session_to_trx(getTable()->in_use));
5564
 
 
5565
 
  if (prebuilt->clust_index_was_generated) {
5566
 
    /* No primary key was defined for the table and we
5567
 
    generated the clustered index from the row id: the
5568
 
    row reference is the row id, not any key value
5569
 
    that MySQL knows of */
5570
 
 
5571
 
    error = change_active_index(MAX_KEY);
5572
 
  } else {
5573
 
    error = change_active_index(primary_key);
5574
 
  }
5575
 
 
5576
 
  if (error) {
5577
 
    return(error);
5578
 
  }
5579
 
 
5580
 
  /* Note that we assume the length of the row reference is fixed
5581
 
  for the table, and it is == ref_length */
5582
 
 
5583
 
  error = index_read(buf, pos, ref_length, HA_READ_KEY_EXACT);
5584
 
 
5585
 
  if (error) {
5586
 
  }
5587
 
 
5588
 
  change_active_index(keynr);
5589
 
 
5590
 
  return(error);
 
4997
        int             error;
 
4998
        uint            keynr   = active_index;
 
4999
 
 
5000
        ha_statistic_increment(&system_status_var::ha_read_rnd_count);
 
5001
 
 
5002
        ut_a(prebuilt->trx == session_to_trx(ha_session()));
 
5003
 
 
5004
        if (prebuilt->clust_index_was_generated) {
 
5005
                /* No primary key was defined for the table and we
 
5006
                generated the clustered index from the row id: the
 
5007
                row reference is the row id, not any key value
 
5008
                that MySQL knows of */
 
5009
 
 
5010
                error = change_active_index(MAX_KEY);
 
5011
        } else {
 
5012
                error = change_active_index(primary_key);
 
5013
        }
 
5014
 
 
5015
        if (error) {
 
5016
                return(error);
 
5017
        }
 
5018
 
 
5019
        /* Note that we assume the length of the row reference is fixed
 
5020
        for the table, and it is == ref_length */
 
5021
 
 
5022
        error = index_read(buf, pos, ref_length, HA_READ_KEY_EXACT);
 
5023
 
 
5024
        if (error) {
 
5025
        }
 
5026
 
 
5027
        change_active_index(keynr);
 
5028
 
 
5029
        return(error);
5591
5030
}
5592
5031
 
5593
5032
/*********************************************************************//**
5602
5041
void
5603
5042
ha_innobase::position(
5604
5043
/*==================*/
5605
 
  const unsigned char*  record) /*!< in: row in MySQL format */
 
5044
        const unsigned char*    record) /*!< in: row in MySQL format */
5606
5045
{
5607
 
  uint    len;
5608
 
 
5609
 
  ut_a(prebuilt->trx == session_to_trx(getTable()->in_use));
5610
 
 
5611
 
  if (prebuilt->clust_index_was_generated) {
5612
 
    /* No primary key was defined for the table and we
5613
 
    generated the clustered index from row id: the
5614
 
    row reference will be the row id, not any key value
5615
 
    that MySQL knows of */
5616
 
 
5617
 
    len = DATA_ROW_ID_LEN;
5618
 
 
5619
 
    memcpy(ref, prebuilt->row_id, len);
5620
 
  } else {
5621
 
    len = store_key_val_for_row(primary_key, (char*)ref,
5622
 
               ref_length, record);
5623
 
  }
5624
 
 
5625
 
  /* We assume that the 'ref' value len is always fixed for the same
5626
 
  table. */
5627
 
 
5628
 
  if (len != ref_length) {
5629
 
    errmsg_printf(ERRMSG_LVL_ERROR, "Stored ref len is %lu, but table ref len is %lu",
5630
 
        (ulong) len, (ulong) ref_length);
5631
 
  }
 
5046
        uint            len;
 
5047
 
 
5048
        ut_a(prebuilt->trx == session_to_trx(ha_session()));
 
5049
 
 
5050
        if (prebuilt->clust_index_was_generated) {
 
5051
                /* No primary key was defined for the table and we
 
5052
                generated the clustered index from row id: the
 
5053
                row reference will be the row id, not any key value
 
5054
                that MySQL knows of */
 
5055
 
 
5056
                len = DATA_ROW_ID_LEN;
 
5057
 
 
5058
                memcpy(ref, prebuilt->row_id, len);
 
5059
        } else {
 
5060
                len = store_key_val_for_row(primary_key, (char*)ref,
 
5061
                                                         ref_length, record);
 
5062
        }
 
5063
 
 
5064
        /* We assume that the 'ref' value len is always fixed for the same
 
5065
        table. */
 
5066
 
 
5067
        if (len != ref_length) {
 
5068
          errmsg_printf(ERRMSG_LVL_ERROR, "Stored ref len is %lu, but table ref len is %lu",
 
5069
                          (ulong) len, (ulong) ref_length);
 
5070
        }
5632
5071
}
5633
5072
 
5634
5073
 
5638
5077
int
5639
5078
create_table_def(
5640
5079
/*=============*/
5641
 
  trx_t*    trx,    /*!< in: InnoDB transaction handle */
5642
 
  Table*    form,   /*!< in: information on table
5643
 
          columns and indexes */
5644
 
  const char* table_name, /*!< in: table name */
5645
 
  const char* path_of_temp_table,/*!< in: if this is a table explicitly
5646
 
          created by the user with the
5647
 
          TEMPORARY keyword, then this
5648
 
          parameter is the dir path where the
5649
 
          table should be placed if we create
5650
 
          an .ibd file for it (no .ibd extension
5651
 
          in the path, though); otherwise this
5652
 
          is NULL */
5653
 
  ulint   flags)    /*!< in: table flags */
 
5080
        trx_t*          trx,            /*!< in: InnoDB transaction handle */
 
5081
        Table*          form,           /*!< in: information on table
 
5082
                                        columns and indexes */
 
5083
        const char*     table_name,     /*!< in: table name */
 
5084
        const char*     path_of_temp_table,/*!< in: if this is a table explicitly
 
5085
                                        created by the user with the
 
5086
                                        TEMPORARY keyword, then this
 
5087
                                        parameter is the dir path where the
 
5088
                                        table should be placed if we create
 
5089
                                        an .ibd file for it (no .ibd extension
 
5090
                                        in the path, though); otherwise this
 
5091
                                        is NULL */
 
5092
        ulint           flags)          /*!< in: table flags */
5654
5093
{
5655
 
  Field*    field;
5656
 
  dict_table_t* table;
5657
 
  ulint   n_cols;
5658
 
  int   error;
5659
 
  ulint   col_type;
5660
 
  ulint   col_len;
5661
 
  ulint   nulls_allowed;
5662
 
  ulint   unsigned_type;
5663
 
  ulint   binary_type;
5664
 
  ulint   long_true_varchar;
5665
 
  ulint   charset_no;
5666
 
  ulint   i;
5667
 
 
5668
 
  n_cols = form->getShare()->sizeFields();
5669
 
 
5670
 
  /* We pass 0 as the space id, and determine at a lower level the space
5671
 
  id where to store the table */
5672
 
 
5673
 
  table = dict_mem_table_create(table_name, 0, n_cols, flags);
5674
 
 
5675
 
  if (path_of_temp_table) {
5676
 
    table->dir_path_of_temp_table =
5677
 
      mem_heap_strdup(table->heap, path_of_temp_table);
5678
 
  }
5679
 
 
5680
 
  for (i = 0; i < n_cols; i++) {
5681
 
    field = form->getField(i);
5682
 
 
5683
 
    col_type = get_innobase_type_from_mysql_type(&unsigned_type,
5684
 
                  field);
5685
 
    if (field->null_ptr) {
5686
 
      nulls_allowed = 0;
5687
 
    } else {
5688
 
      nulls_allowed = DATA_NOT_NULL;
5689
 
    }
5690
 
 
5691
 
    if (field->binary()) {
5692
 
      binary_type = DATA_BINARY_TYPE;
5693
 
    } else {
5694
 
      binary_type = 0;
5695
 
    }
5696
 
 
5697
 
    charset_no = 0;
5698
 
 
5699
 
    if (dtype_is_string_type(col_type)) {
5700
 
 
5701
 
      charset_no = (ulint)field->charset()->number;
5702
 
 
5703
 
      if (UNIV_UNLIKELY(charset_no >= 256)) {
5704
 
        /* in data0type.h we assume that the
5705
 
        number fits in one byte in prtype */
5706
 
        push_warning_printf(
5707
 
          (Session*) trx->mysql_thd,
5708
 
          DRIZZLE_ERROR::WARN_LEVEL_ERROR,
5709
 
          ER_CANT_CREATE_TABLE,
5710
 
          "In InnoDB, charset-collation codes"
5711
 
          " must be below 256."
5712
 
          " Unsupported code %lu.",
5713
 
          (ulong) charset_no);
5714
 
        return(ER_CANT_CREATE_TABLE);
5715
 
      }
5716
 
    }
5717
 
 
5718
 
    ut_a(field->type() < 256); /* we assume in dtype_form_prtype()
5719
 
             that this fits in one byte */
5720
 
    col_len = field->pack_length();
5721
 
 
5722
 
    /* The MySQL pack length contains 1 or 2 bytes length field
5723
 
    for a true VARCHAR. Let us subtract that, so that the InnoDB
5724
 
    column length in the InnoDB data dictionary is the real
5725
 
    maximum byte length of the actual data. */
5726
 
 
5727
 
    long_true_varchar = 0;
5728
 
 
5729
 
    if (field->type() == DRIZZLE_TYPE_VARCHAR) {
5730
 
      col_len -= ((Field_varstring*)field)->pack_length_no_ptr();
5731
 
 
5732
 
      if (((Field_varstring*)field)->pack_length_no_ptr() == 2) {
5733
 
        long_true_varchar = DATA_LONG_TRUE_VARCHAR;
5734
 
      }
5735
 
    }
5736
 
 
5737
 
    /* First check whether the column to be added has a
5738
 
       system reserved name. */
5739
 
    if (dict_col_name_is_reserved(field->field_name)){
5740
 
      my_error(ER_WRONG_COLUMN_NAME, MYF(0), field->field_name);
5741
 
 
5742
 
      dict_mem_table_free(table);
5743
 
      trx_commit_for_mysql(trx);
5744
 
 
5745
 
      error = DB_ERROR;
5746
 
      goto error_ret;
5747
 
    }
5748
 
 
5749
 
    dict_mem_table_add_col(table, table->heap,
5750
 
      (char*) field->field_name,
5751
 
      col_type,
5752
 
      dtype_form_prtype(
5753
 
        (ulint)field->type()
5754
 
        | nulls_allowed | unsigned_type
5755
 
        | binary_type | long_true_varchar,
5756
 
        charset_no),
5757
 
      col_len);
5758
 
  }
5759
 
 
5760
 
  error = row_create_table_for_mysql(table, trx);
5761
 
 
5762
 
        if (error == DB_DUPLICATE_KEY) {
5763
 
                char buf[100];
5764
 
                char* buf_end = innobase_convert_identifier(
5765
 
                        buf, sizeof buf - 1, table_name, strlen(table_name),
5766
 
                        trx->mysql_thd, TRUE);
5767
 
 
5768
 
                *buf_end = '\0';
5769
 
                my_error(ER_TABLE_EXISTS_ERROR, MYF(0), buf);
5770
 
        }
5771
 
 
5772
 
error_ret:
5773
 
  error = convert_error_code_to_mysql(error, flags, NULL);
5774
 
 
5775
 
  return(error);
 
5094
        Field*          field;
 
5095
        dict_table_t*   table;
 
5096
        ulint           n_cols;
 
5097
        int             error;
 
5098
        ulint           col_type;
 
5099
        ulint           col_len;
 
5100
        ulint           nulls_allowed;
 
5101
        ulint           unsigned_type;
 
5102
        ulint           binary_type;
 
5103
        ulint           long_true_varchar;
 
5104
        ulint           charset_no;
 
5105
        ulint           i;
 
5106
 
 
5107
        n_cols = form->s->fields;
 
5108
 
 
5109
        /* We pass 0 as the space id, and determine at a lower level the space
 
5110
        id where to store the table */
 
5111
 
 
5112
        table = dict_mem_table_create(table_name, 0, n_cols, flags);
 
5113
 
 
5114
        if (path_of_temp_table) {
 
5115
                table->dir_path_of_temp_table =
 
5116
                        mem_heap_strdup(table->heap, path_of_temp_table);
 
5117
        }
 
5118
 
 
5119
        for (i = 0; i < n_cols; i++) {
 
5120
                field = form->field[i];
 
5121
 
 
5122
                col_type = get_innobase_type_from_mysql_type(&unsigned_type,
 
5123
                                                                        field);
 
5124
                if (field->null_ptr) {
 
5125
                        nulls_allowed = 0;
 
5126
                } else {
 
5127
                        nulls_allowed = DATA_NOT_NULL;
 
5128
                }
 
5129
 
 
5130
                if (field->binary()) {
 
5131
                        binary_type = DATA_BINARY_TYPE;
 
5132
                } else {
 
5133
                        binary_type = 0;
 
5134
                }
 
5135
 
 
5136
                charset_no = 0;
 
5137
 
 
5138
                if (dtype_is_string_type(col_type)) {
 
5139
 
 
5140
                        charset_no = (ulint)field->charset()->number;
 
5141
 
 
5142
                        if (UNIV_UNLIKELY(charset_no >= 256)) {
 
5143
                                /* in data0type.h we assume that the
 
5144
                                number fits in one byte in prtype */
 
5145
                                push_warning_printf(
 
5146
                                        (Session*) trx->mysql_thd,
 
5147
                                        DRIZZLE_ERROR::WARN_LEVEL_ERROR,
 
5148
                                        ER_CANT_CREATE_TABLE,
 
5149
                                        "In InnoDB, charset-collation codes"
 
5150
                                        " must be below 256."
 
5151
                                        " Unsupported code %lu.",
 
5152
                                        (ulong) charset_no);
 
5153
                                return(ER_CANT_CREATE_TABLE);
 
5154
                        }
 
5155
                }
 
5156
 
 
5157
                ut_a(field->type() < 256); /* we assume in dtype_form_prtype()
 
5158
                                           that this fits in one byte */
 
5159
                col_len = field->pack_length();
 
5160
 
 
5161
                /* The MySQL pack length contains 1 or 2 bytes length field
 
5162
                for a true VARCHAR. Let us subtract that, so that the InnoDB
 
5163
                column length in the InnoDB data dictionary is the real
 
5164
                maximum byte length of the actual data. */
 
5165
 
 
5166
                long_true_varchar = 0;
 
5167
 
 
5168
                if (field->type() == DRIZZLE_TYPE_VARCHAR) {
 
5169
                        col_len -= ((Field_varstring*)field)->length_bytes;
 
5170
 
 
5171
                        if (((Field_varstring*)field)->length_bytes == 2) {
 
5172
                                long_true_varchar = DATA_LONG_TRUE_VARCHAR;
 
5173
                        }
 
5174
                }
 
5175
 
 
5176
                dict_mem_table_add_col(table, table->heap,
 
5177
                        (char*) field->field_name,
 
5178
                        col_type,
 
5179
                        dtype_form_prtype(
 
5180
                                (ulint)field->type()
 
5181
                                | nulls_allowed | unsigned_type
 
5182
                                | binary_type | long_true_varchar,
 
5183
                                charset_no),
 
5184
                        col_len);
 
5185
        }
 
5186
 
 
5187
        error = row_create_table_for_mysql(table, trx);
 
5188
 
 
5189
        error = convert_error_code_to_mysql(error, flags, NULL);
 
5190
 
 
5191
        return(error);
5776
5192
}
5777
5193
 
5778
5194
/*****************************************************************//**
5781
5197
int
5782
5198
create_index(
5783
5199
/*=========*/
5784
 
  trx_t*    trx,    /*!< in: InnoDB transaction handle */
5785
 
  Table*    form,   /*!< in: information on table
5786
 
          columns and indexes */
5787
 
  ulint   flags,    /*!< in: InnoDB table flags */
5788
 
  const char* table_name, /*!< in: table name */
5789
 
  uint    key_num)  /*!< in: index number */
 
5200
        trx_t*          trx,            /*!< in: InnoDB transaction handle */
 
5201
        Table*          form,           /*!< in: information on table
 
5202
                                        columns and indexes */
 
5203
        ulint           flags,          /*!< in: InnoDB table flags */
 
5204
        const char*     table_name,     /*!< in: table name */
 
5205
        uint            key_num)        /*!< in: index number */
5790
5206
{
5791
 
  Field*    field;
5792
 
  dict_index_t* index;
5793
 
  int   error;
5794
 
  ulint   n_fields;
5795
 
  KeyInfo*    key;
5796
 
  KeyPartInfo*  key_part;
5797
 
  ulint   ind_type;
5798
 
  ulint   col_type;
5799
 
  ulint   prefix_len;
5800
 
  ulint   is_unsigned;
5801
 
  ulint   i;
5802
 
  ulint   j;
5803
 
  ulint*    field_lengths;
5804
 
 
5805
 
  key = &form->key_info[key_num];
5806
 
 
5807
 
  n_fields = key->key_parts;
5808
 
 
5809
 
  /* Assert that "GEN_CLUST_INDEX" cannot be used as non-primary index */
5810
 
  ut_a(innobase_strcasecmp(key->name, innobase_index_reserve_name) != 0);
5811
 
 
5812
 
  ind_type = 0;
5813
 
 
5814
 
  if (key_num == form->getShare()->getPrimaryKey()) {
5815
 
    ind_type = ind_type | DICT_CLUSTERED;
5816
 
  }
5817
 
 
5818
 
  if (key->flags & HA_NOSAME ) {
5819
 
    ind_type = ind_type | DICT_UNIQUE;
5820
 
  }
5821
 
 
5822
 
  /* We pass 0 as the space id, and determine at a lower level the space
5823
 
  id where to store the table */
5824
 
 
5825
 
  index = dict_mem_index_create(table_name, key->name, 0,
5826
 
              ind_type, n_fields);
5827
 
 
5828
 
  field_lengths = (ulint*) malloc(sizeof(ulint) * n_fields);
5829
 
 
5830
 
  for (i = 0; i < n_fields; i++) {
5831
 
    key_part = key->key_part + i;
5832
 
 
5833
 
    /* (The flag HA_PART_KEY_SEG denotes in MySQL a column prefix
5834
 
    field in an index: we only store a specified number of first
5835
 
    bytes of the column to the index field.) The flag does not
5836
 
    seem to be properly set by MySQL. Let us fall back on testing
5837
 
    the length of the key part versus the column. */
5838
 
 
5839
 
    field = NULL;
5840
 
    for (j = 0; j < form->getShare()->sizeFields(); j++)
5841
 
    {
5842
 
 
5843
 
      field = form->getField(j);
5844
 
 
5845
 
      if (0 == innobase_strcasecmp(
5846
 
          field->field_name,
5847
 
          key_part->field->field_name)) {
5848
 
        /* Found the corresponding column */
5849
 
 
5850
 
        break;
5851
 
      }
5852
 
    }
5853
 
 
5854
 
    ut_a(j < form->getShare()->sizeFields());
5855
 
 
5856
 
    col_type = get_innobase_type_from_mysql_type(
5857
 
          &is_unsigned, key_part->field);
5858
 
 
5859
 
    if (DATA_BLOB == col_type
5860
 
      || (key_part->length < field->pack_length()
5861
 
        && field->type() != DRIZZLE_TYPE_VARCHAR)
5862
 
      || (field->type() == DRIZZLE_TYPE_VARCHAR
5863
 
        && key_part->length < field->pack_length()
5864
 
        - ((Field_varstring*)field)->pack_length_no_ptr())) {
5865
 
 
5866
 
      prefix_len = key_part->length;
5867
 
 
5868
 
      if (col_type == DATA_INT
5869
 
        || col_type == DATA_FLOAT
5870
 
        || col_type == DATA_DOUBLE
5871
 
        || col_type == DATA_DECIMAL) {
5872
 
        errmsg_printf(ERRMSG_LVL_ERROR, 
5873
 
          "MySQL is trying to create a column "
5874
 
          "prefix index field, on an "
5875
 
          "inappropriate data type. Table "
5876
 
          "name %s, column name %s.",
5877
 
          table_name,
5878
 
          key_part->field->field_name);
5879
 
 
5880
 
        prefix_len = 0;
5881
 
      }
5882
 
    } else {
5883
 
      prefix_len = 0;
5884
 
    }
5885
 
 
5886
 
    field_lengths[i] = key_part->length;
5887
 
 
5888
 
    dict_mem_index_add_field(index,
5889
 
      (char*) key_part->field->field_name, prefix_len);
5890
 
  }
5891
 
 
5892
 
  /* Even though we've defined max_supported_key_part_length, we
5893
 
  still do our own checking using field_lengths to be absolutely
5894
 
  sure we don't create too long indexes. */
5895
 
  error = row_create_index_for_mysql(index, trx, field_lengths);
5896
 
 
5897
 
  error = convert_error_code_to_mysql(error, flags, NULL);
5898
 
 
5899
 
  free(field_lengths);
5900
 
 
5901
 
  return(error);
 
5207
        Field*          field;
 
5208
        dict_index_t*   index;
 
5209
        int             error;
 
5210
        ulint           n_fields;
 
5211
        KEY*            key;
 
5212
        KEY_PART_INFO*  key_part;
 
5213
        ulint           ind_type;
 
5214
        ulint           col_type;
 
5215
        ulint           prefix_len;
 
5216
        ulint           is_unsigned;
 
5217
        ulint           i;
 
5218
        ulint           j;
 
5219
        ulint*          field_lengths;
 
5220
 
 
5221
        key = form->key_info + key_num;
 
5222
 
 
5223
        n_fields = key->key_parts;
 
5224
 
 
5225
        ind_type = 0;
 
5226
 
 
5227
        if (key_num == form->s->primary_key) {
 
5228
                ind_type = ind_type | DICT_CLUSTERED;
 
5229
        }
 
5230
 
 
5231
        if (key->flags & HA_NOSAME ) {
 
5232
                ind_type = ind_type | DICT_UNIQUE;
 
5233
        }
 
5234
 
 
5235
        /* We pass 0 as the space id, and determine at a lower level the space
 
5236
        id where to store the table */
 
5237
 
 
5238
        index = dict_mem_index_create(table_name, key->name, 0,
 
5239
                                      ind_type, n_fields);
 
5240
 
 
5241
        field_lengths = (ulint*) malloc(sizeof(ulint) * n_fields);
 
5242
 
 
5243
        for (i = 0; i < n_fields; i++) {
 
5244
                key_part = key->key_part + i;
 
5245
 
 
5246
                /* (The flag HA_PART_KEY_SEG denotes in MySQL a column prefix
 
5247
                field in an index: we only store a specified number of first
 
5248
                bytes of the column to the index field.) The flag does not
 
5249
                seem to be properly set by MySQL. Let us fall back on testing
 
5250
                the length of the key part versus the column. */
 
5251
 
 
5252
                field = NULL;
 
5253
                for (j = 0; j < form->s->fields; j++) {
 
5254
 
 
5255
                        field = form->field[j];
 
5256
 
 
5257
                        if (0 == innobase_strcasecmp(
 
5258
                                        field->field_name,
 
5259
                                        key_part->field->field_name)) {
 
5260
                                /* Found the corresponding column */
 
5261
 
 
5262
                                break;
 
5263
                        }
 
5264
                }
 
5265
 
 
5266
                ut_a(j < form->s->fields);
 
5267
 
 
5268
                col_type = get_innobase_type_from_mysql_type(
 
5269
                                        &is_unsigned, key_part->field);
 
5270
 
 
5271
                if (DATA_BLOB == col_type
 
5272
                        || (key_part->length < field->pack_length()
 
5273
                                && field->type() != DRIZZLE_TYPE_VARCHAR)
 
5274
                        || (field->type() == DRIZZLE_TYPE_VARCHAR
 
5275
                                && key_part->length < field->pack_length()
 
5276
                                - ((Field_varstring*)field)->length_bytes)) {
 
5277
 
 
5278
                        prefix_len = key_part->length;
 
5279
 
 
5280
                        if (col_type == DATA_INT
 
5281
                                || col_type == DATA_FLOAT
 
5282
                                || col_type == DATA_DOUBLE
 
5283
                                || col_type == DATA_DECIMAL) {
 
5284
                                errmsg_printf(ERRMSG_LVL_ERROR, 
 
5285
                                        "MySQL is trying to create a column "
 
5286
                                        "prefix index field, on an "
 
5287
                                        "inappropriate data type. Table "
 
5288
                                        "name %s, column name %s.",
 
5289
                                        table_name,
 
5290
                                        key_part->field->field_name);
 
5291
 
 
5292
                                prefix_len = 0;
 
5293
                        }
 
5294
                } else {
 
5295
                        prefix_len = 0;
 
5296
                }
 
5297
 
 
5298
                field_lengths[i] = key_part->length;
 
5299
 
 
5300
                dict_mem_index_add_field(index,
 
5301
                        (char*) key_part->field->field_name, prefix_len);
 
5302
        }
 
5303
 
 
5304
        /* Even though we've defined max_supported_key_part_length, we
 
5305
        still do our own checking using field_lengths to be absolutely
 
5306
        sure we don't create too long indexes. */
 
5307
        error = row_create_index_for_mysql(index, trx, field_lengths);
 
5308
 
 
5309
        error = convert_error_code_to_mysql(error, flags, NULL);
 
5310
 
 
5311
        free(field_lengths);
 
5312
 
 
5313
        return(error);
5902
5314
}
5903
5315
 
5904
5316
/*****************************************************************//**
5908
5320
int
5909
5321
create_clustered_index_when_no_primary(
5910
5322
/*===================================*/
5911
 
  trx_t*    trx,    /*!< in: InnoDB transaction handle */
5912
 
  ulint   flags,    /*!< in: InnoDB table flags */
5913
 
  const char* table_name) /*!< in: table name */
 
5323
        trx_t*          trx,            /*!< in: InnoDB transaction handle */
 
5324
        ulint           flags,          /*!< in: InnoDB table flags */
 
5325
        const char*     table_name)     /*!< in: table name */
5914
5326
{
5915
 
  dict_index_t* index;
5916
 
  int   error;
5917
 
 
5918
 
  /* We pass 0 as the space id, and determine at a lower level the space
5919
 
  id where to store the table */
5920
 
 
5921
 
  index = dict_mem_index_create(table_name,
5922
 
                                innobase_index_reserve_name,
5923
 
                                0, DICT_CLUSTERED, 0);
5924
 
 
5925
 
  error = row_create_index_for_mysql(index, trx, NULL);
5926
 
 
5927
 
  error = convert_error_code_to_mysql(error, flags, NULL);
5928
 
 
5929
 
  return(error);
 
5327
        dict_index_t*   index;
 
5328
        int             error;
 
5329
 
 
5330
        /* We pass 0 as the space id, and determine at a lower level the space
 
5331
        id where to store the table */
 
5332
 
 
5333
        index = dict_mem_index_create(table_name, "GEN_CLUST_INDEX",
 
5334
                                      0, DICT_CLUSTERED, 0);
 
5335
 
 
5336
        error = row_create_index_for_mysql(index, trx, NULL);
 
5337
 
 
5338
        error = convert_error_code_to_mysql(error, flags, NULL);
 
5339
 
 
5340
        return(error);
5930
5341
}
5931
5342
 
5932
5343
/*****************************************************************//**
5934
5345
in future. For now, it checks two specifiers:
5935
5346
KEY_BLOCK_SIZE and ROW_FORMAT
5936
5347
If innodb_strict_mode is not set then this function is a no-op
5937
 
@return TRUE if valid. */
5938
 
#if 0
 
5348
@return TRUE if valid. */
5939
5349
static
5940
5350
ibool
5941
5351
create_options_are_valid(
5942
5352
/*=====================*/
5943
 
  Session*  session,  /*!< in: connection thread. */
5944
 
  Table&    form,   /*!< in: information on table
5945
 
          columns and indexes */
 
5353
        Session*        session,        /*!< in: connection thread. */
 
5354
        Table&          form,           /*!< in: information on table
 
5355
                                        columns and indexes */
5946
5356
        message::Table& create_proto)
5947
5357
{
5948
 
  ibool kbs_specified = FALSE;
5949
 
  ibool ret   = TRUE;
5950
 
 
5951
 
 
5952
 
  ut_ad(session != NULL);
5953
 
 
5954
 
  /* If innodb_strict_mode is not set don't do any validation. */
5955
 
  if (!(SessionVAR(session, strict_mode))) {
5956
 
    return(TRUE);
5957
 
  }
5958
 
 
5959
 
  /* Now check for ROW_FORMAT specifier. */
5960
 
  return(ret);
 
5358
        ibool   kbs_specified   = FALSE;
 
5359
        ibool   ret             = TRUE;
 
5360
 
 
5361
 
 
5362
        ut_ad(session != NULL);
 
5363
 
 
5364
        /* If innodb_strict_mode is not set don't do any validation. */
 
5365
        if (!(SessionVAR(session, strict_mode))) {
 
5366
                return(TRUE);
 
5367
        }
 
5368
 
 
5369
        /* First check if KEY_BLOCK_SIZE was specified. */
 
5370
        if (create_proto.options().has_key_block_size()) {
 
5371
 
 
5372
                kbs_specified = TRUE;
 
5373
                switch (create_proto.options().key_block_size()) {
 
5374
                case 1:
 
5375
                case 2:
 
5376
                case 4:
 
5377
                case 8:
 
5378
                case 16:
 
5379
                        /* Valid value. */
 
5380
                        break;
 
5381
                default:
 
5382
                        push_warning_printf(session, DRIZZLE_ERROR::WARN_LEVEL_ERROR,
 
5383
                                            ER_ILLEGAL_HA_CREATE_OPTION,
 
5384
                                            "InnoDB: invalid"
 
5385
                                            " KEY_BLOCK_SIZE = %lu."
 
5386
                                            " Valid values are"
 
5387
                                            " [1, 2, 4, 8, 16]",
 
5388
                                            create_proto.options().key_block_size());
 
5389
                        ret = FALSE;
 
5390
                }
 
5391
        }
 
5392
        
 
5393
        /* If KEY_BLOCK_SIZE was specified, check for its
 
5394
        dependencies. */
 
5395
        if (kbs_specified && !srv_file_per_table) {
 
5396
                push_warning(session, DRIZZLE_ERROR::WARN_LEVEL_ERROR,
 
5397
                             ER_ILLEGAL_HA_CREATE_OPTION,
 
5398
                             "InnoDB: KEY_BLOCK_SIZE"
 
5399
                             " requires innodb_file_per_table.");
 
5400
                ret = FALSE;
 
5401
        }
 
5402
 
 
5403
        if (kbs_specified && srv_file_format < DICT_TF_FORMAT_ZIP) {
 
5404
                push_warning(session, DRIZZLE_ERROR::WARN_LEVEL_ERROR,
 
5405
                             ER_ILLEGAL_HA_CREATE_OPTION,
 
5406
                             "InnoDB: KEY_BLOCK_SIZE"
 
5407
                             " requires innodb_file_format >"
 
5408
                             " Antelope.");
 
5409
                ret = FALSE;
 
5410
        }
 
5411
 
 
5412
        /* Now check for ROW_FORMAT specifier. */
 
5413
        if (create_proto.options().has_row_type()) {
 
5414
                switch (form.s->row_type) {
 
5415
                        const char* row_format_name;
 
5416
                case ROW_TYPE_COMPRESSED:
 
5417
                case ROW_TYPE_DYNAMIC:
 
5418
                        row_format_name
 
5419
                                = form.s->row_type == ROW_TYPE_COMPRESSED
 
5420
                                ? "COMPRESSED"
 
5421
                                : "DYNAMIC";
 
5422
 
 
5423
                        /* These two ROW_FORMATs require
 
5424
                        srv_file_per_table and srv_file_format */
 
5425
                        if (!srv_file_per_table) {
 
5426
                                push_warning_printf(
 
5427
                                        session,
 
5428
                                        DRIZZLE_ERROR::WARN_LEVEL_ERROR,
 
5429
                                        ER_ILLEGAL_HA_CREATE_OPTION,
 
5430
                                        "InnoDB: ROW_FORMAT=%s"
 
5431
                                        " requires innodb_file_per_table.",
 
5432
                                        row_format_name);
 
5433
                                        ret = FALSE;
 
5434
 
 
5435
                        }
 
5436
 
 
5437
                        if (srv_file_format < DICT_TF_FORMAT_ZIP) {
 
5438
                                push_warning_printf(
 
5439
                                        session,
 
5440
                                        DRIZZLE_ERROR::WARN_LEVEL_ERROR,
 
5441
                                        ER_ILLEGAL_HA_CREATE_OPTION,
 
5442
                                        "InnoDB: ROW_FORMAT=%s"
 
5443
                                        " requires innodb_file_format >"
 
5444
                                        " Antelope.",
 
5445
                                        row_format_name);
 
5446
                                        ret = FALSE;
 
5447
                        }
 
5448
 
 
5449
                        /* Cannot specify KEY_BLOCK_SIZE with
 
5450
                        ROW_FORMAT = DYNAMIC.
 
5451
                        However, we do allow COMPRESSED to be
 
5452
                        specified with KEY_BLOCK_SIZE. */
 
5453
                        if (kbs_specified
 
5454
                            && form.s->row_type == ROW_TYPE_DYNAMIC) {
 
5455
                                push_warning_printf(
 
5456
                                        session,
 
5457
                                        DRIZZLE_ERROR::WARN_LEVEL_ERROR,
 
5458
                                        ER_ILLEGAL_HA_CREATE_OPTION,
 
5459
                                        "InnoDB: cannot specify"
 
5460
                                        " ROW_FORMAT = DYNAMIC with"
 
5461
                                        " KEY_BLOCK_SIZE.");
 
5462
                                        ret = FALSE;
 
5463
                        }
 
5464
 
 
5465
                        break;
 
5466
 
 
5467
                case ROW_TYPE_REDUNDANT:
 
5468
                case ROW_TYPE_COMPACT:
 
5469
                case ROW_TYPE_DEFAULT:
 
5470
                        /* Default is COMPACT. */
 
5471
                        row_format_name
 
5472
                                = form.s->row_type == ROW_TYPE_REDUNDANT
 
5473
                                ? "REDUNDANT"
 
5474
                                : "COMPACT";
 
5475
 
 
5476
                        /* Cannot specify KEY_BLOCK_SIZE with these
 
5477
                        format specifiers. */
 
5478
                        if (kbs_specified) {
 
5479
                                push_warning_printf(
 
5480
                                        session,
 
5481
                                        DRIZZLE_ERROR::WARN_LEVEL_ERROR,
 
5482
                                        ER_ILLEGAL_HA_CREATE_OPTION,
 
5483
                                        "InnoDB: cannot specify"
 
5484
                                        " ROW_FORMAT = %s with"
 
5485
                                        " KEY_BLOCK_SIZE.",
 
5486
                                        row_format_name);
 
5487
                                        ret = FALSE;
 
5488
                        }
 
5489
 
 
5490
                        break;
 
5491
 
 
5492
                default:
 
5493
                        push_warning(session,
 
5494
                                     DRIZZLE_ERROR::WARN_LEVEL_ERROR,
 
5495
                                     ER_ILLEGAL_HA_CREATE_OPTION,
 
5496
                                     "InnoDB: invalid ROW_FORMAT specifier.");
 
5497
                        ret = FALSE;
 
5498
 
 
5499
                }
 
5500
        }
 
5501
 
 
5502
        return(ret);
5961
5503
}
5962
 
#endif
5963
5504
 
5964
5505
/*********************************************************************
5965
5506
Creates a new table to an InnoDB database. */
5967
5508
int
5968
5509
InnobaseEngine::doCreateTable(
5969
5510
/*================*/
5970
 
  Session         &session, /*!< in: Session */
5971
 
  Table&    form,   /*!< in: information on table columns and indexes */
5972
 
        const TableIdentifier &identifier,
 
5511
        Session*        session,        /*!< in: Session */
 
5512
        const char*     table_name,     /*!< in: table name */
 
5513
        Table&          form,           /*!< in: information on table
 
5514
                                        columns and indexes */
5973
5515
        message::Table& create_proto)
5974
5516
{
5975
 
  int   error;
5976
 
  dict_table_t* innobase_table;
5977
 
  trx_t*    parent_trx;
5978
 
  trx_t*    trx;
5979
 
  int   primary_key_no;
5980
 
  uint    i;
5981
 
  char    name2[FN_REFLEN];
5982
 
  char    norm_name[FN_REFLEN];
5983
 
  ib_int64_t  auto_inc_value;
5984
 
  ulint   iflags;
5985
 
  /* Cache the value of innodb_file_format, in case it is
5986
 
    modified by another thread while the table is being created. */
5987
 
  const ulint file_format = srv_file_format;
5988
 
  bool lex_identified_temp_table= (create_proto.type() == message::Table::TEMPORARY);
5989
 
  const char* stmt;
5990
 
  size_t stmt_len;
5991
 
 
5992
 
  const char *table_name= identifier.getPath().c_str();
5993
 
 
5994
 
  if (form.getShare()->sizeFields() > 1000) {
5995
 
    /* The limit probably should be REC_MAX_N_FIELDS - 3 = 1020,
5996
 
      but we play safe here */
5997
 
 
5998
 
    return(HA_ERR_TO_BIG_ROW);
5999
 
  }
6000
 
 
6001
 
  /* Get the transaction associated with the current session, or create one
6002
 
    if not yet created */
6003
 
 
6004
 
  parent_trx = check_trx_exists(&session);
6005
 
 
6006
 
  /* In case MySQL calls this in the middle of a SELECT query, release
6007
 
    possible adaptive hash latch to avoid deadlocks of threads */
6008
 
 
6009
 
  trx_search_latch_release_if_reserved(parent_trx);
6010
 
 
6011
 
  trx = innobase_trx_allocate(&session);
6012
 
 
6013
 
  srv_lower_case_table_names = TRUE;
6014
 
 
6015
 
  strcpy(name2, table_name);
6016
 
 
6017
 
  normalize_table_name(norm_name, name2);
6018
 
 
6019
 
  /* Latch the InnoDB data dictionary exclusively so that no deadlocks
6020
 
    or lock waits can happen in it during a table create operation.
6021
 
    Drop table etc. do this latching in row0mysql.c. */
6022
 
 
6023
 
  row_mysql_lock_data_dictionary(trx);
6024
 
 
6025
 
  /* Create the table definition in InnoDB */
6026
 
 
6027
 
  iflags = 0;
6028
 
 
6029
 
#if 0 // Since we validate the options before this stage, we no longer need to do this.
6030
 
  /* Validate create options if innodb_strict_mode is set. */
6031
 
  if (! create_options_are_valid(&session, form, create_proto)) {
6032
 
    error = ER_ILLEGAL_HA_CREATE_OPTION;
6033
 
    goto cleanup;
6034
 
  }
 
5517
        int             error;
 
5518
        dict_table_t*   innobase_table;
 
5519
        trx_t*          parent_trx;
 
5520
        trx_t*          trx;
 
5521
        int             primary_key_no;
 
5522
        uint            i;
 
5523
        char            name2[FN_REFLEN];
 
5524
        char            norm_name[FN_REFLEN];
 
5525
        ib_int64_t      auto_inc_value;
 
5526
        ulint           iflags;
 
5527
        /* Cache the value of innodb_file_format, in case it is
 
5528
        modified by another thread while the table is being created. */
 
5529
        const ulint     file_format = srv_file_format;
 
5530
        bool lex_identified_temp_table= (create_proto.type() == message::Table::TEMPORARY);
 
5531
 
 
5532
        assert(session != NULL);
 
5533
 
 
5534
#ifdef __WIN__
 
5535
        /* Names passed in from server are in two formats:
 
5536
        1. <database_name>/<table_name>: for normal table creation
 
5537
        2. full path: for temp table creation, or sym link
 
5538
 
 
5539
        When srv_file_per_table is on, check for full path pattern, i.e.
 
5540
        X:\dir\...,             X is a driver letter, or
 
5541
        \\dir1\dir2\...,        UNC path
 
5542
        returns error if it is in full path format, but not creating a temp.
 
5543
        table. Currently InnoDB does not support symbolic link on Windows. */
 
5544
 
 
5545
        if (srv_file_per_table
 
5546
            && (! lex_identified_temp_table)) {
 
5547
 
 
5548
                if ((table_name[1] == ':')
 
5549
                    || (table_name[0] == '\\' && table_name[1] == '\\')) {
 
5550
                        errmsg_printf(ERRMSG_LVL_ERROR, "Cannot create table %s\n", table_name);
 
5551
                        return(HA_ERR_GENERIC);
 
5552
                }
 
5553
        }
6035
5554
#endif
6036
5555
 
6037
 
  // We assume compact format by default
6038
 
  iflags= DICT_TF_COMPACT;
6039
 
 
6040
 
  size_t num_engine_options= create_proto.engine().options_size();
6041
 
  for (size_t x= 0; x < num_engine_options; ++x)
6042
 
  {
6043
 
    if (boost::iequals(create_proto.engine().options(x).name(), "ROW_FORMAT"))
6044
 
    {
6045
 
      if (boost::iequals(create_proto.engine().options(x).state(), "COMPRESSED"))
6046
 
      {
6047
 
        iflags= DICT_TF_FORMAT_ZIP;
6048
 
      }
6049
 
      else if (boost::iequals(create_proto.engine().options(x).state(), "COMPACT"))
6050
 
      {
6051
 
        iflags= DICT_TF_FORMAT_ZIP;
6052
 
      }
6053
 
      else if (boost::iequals(create_proto.engine().options(x).state(), "DYNAMIC"))
6054
 
      {
6055
 
        iflags= DICT_TF_COMPACT;
6056
 
      }
6057
 
      else if (boost::iequals(create_proto.engine().options(x).state(), "REDUNDANT"))
6058
 
      {
6059
 
        iflags= DICT_TF_COMPACT;
6060
 
      }
6061
 
    }
6062
 
    else
6063
 
    {
6064
 
      assert(0); // This should never happen since we have already validated the options.
6065
 
    }
6066
 
  }
6067
 
 
6068
 
  if (iflags == DICT_TF_FORMAT_ZIP)
6069
 
  {
6070
 
    /* 
6071
 
      ROW_FORMAT=COMPRESSED without KEY_BLOCK_SIZE implies half the maximum KEY_BLOCK_SIZE.
6072
 
      @todo implement KEY_BLOCK_SIZE
6073
 
    */
6074
 
    iflags= (DICT_TF_ZSSIZE_MAX - 1)
6075
 
      << DICT_TF_ZSSIZE_SHIFT
6076
 
      | DICT_TF_COMPACT
6077
 
      | DICT_TF_FORMAT_ZIP
6078
 
      << DICT_TF_FORMAT_SHIFT;
 
5556
        if (form.s->fields > 1000) {
 
5557
                /* The limit probably should be REC_MAX_N_FIELDS - 3 = 1020,
 
5558
                but we play safe here */
 
5559
 
 
5560
                return(HA_ERR_TO_BIG_ROW);
 
5561
        }
 
5562
 
 
5563
        /* Get the transaction associated with the current session, or create one
 
5564
        if not yet created */
 
5565
 
 
5566
        parent_trx = check_trx_exists(session);
 
5567
 
 
5568
        /* In case MySQL calls this in the middle of a SELECT query, release
 
5569
        possible adaptive hash latch to avoid deadlocks of threads */
 
5570
 
 
5571
        trx_search_latch_release_if_reserved(parent_trx);
 
5572
 
 
5573
        trx = innobase_trx_allocate(session);
 
5574
 
 
5575
        srv_lower_case_table_names = TRUE;
 
5576
 
 
5577
        strcpy(name2, table_name);
 
5578
 
 
5579
        normalize_table_name(norm_name, name2);
 
5580
 
 
5581
        /* Latch the InnoDB data dictionary exclusively so that no deadlocks
 
5582
        or lock waits can happen in it during a table create operation.
 
5583
        Drop table etc. do this latching in row0mysql.c. */
 
5584
 
 
5585
        row_mysql_lock_data_dictionary(trx);
 
5586
 
 
5587
        /* Create the table definition in InnoDB */
 
5588
 
 
5589
        iflags = 0;
 
5590
 
 
5591
        /* Validate create options if innodb_strict_mode is set. */
 
5592
        if (! create_options_are_valid(session, form, create_proto)) {
 
5593
                error = ER_ILLEGAL_HA_CREATE_OPTION;
 
5594
                goto cleanup;
 
5595
        }
 
5596
 
 
5597
        if (create_proto.options().has_key_block_size()) {
 
5598
                /* Determine the page_zip.ssize corresponding to the
 
5599
                requested page size (key_block_size) in kilobytes. */
 
5600
 
 
5601
                ulint   ssize, ksize;
 
5602
                ulint   key_block_size = create_proto.options().key_block_size();
 
5603
 
 
5604
                for (ssize = ksize = 1; ssize <= DICT_TF_ZSSIZE_MAX;
 
5605
                     ssize++, ksize <<= 1) {
 
5606
                        if (key_block_size == ksize) {
 
5607
                                iflags = ssize << DICT_TF_ZSSIZE_SHIFT
 
5608
                                        | DICT_TF_COMPACT
 
5609
                                        | DICT_TF_FORMAT_ZIP
 
5610
                                          << DICT_TF_FORMAT_SHIFT;
 
5611
                                break;
 
5612
                        }
 
5613
                }
 
5614
 
 
5615
                if (!srv_file_per_table) {
 
5616
                        push_warning(session, DRIZZLE_ERROR::WARN_LEVEL_WARN,
 
5617
                                     ER_ILLEGAL_HA_CREATE_OPTION,
 
5618
                                     "InnoDB: KEY_BLOCK_SIZE"
 
5619
                                     " requires innodb_file_per_table.");
 
5620
                        iflags = 0;
 
5621
                }
 
5622
 
 
5623
                if (file_format < DICT_TF_FORMAT_ZIP) {
 
5624
                        push_warning(session, DRIZZLE_ERROR::WARN_LEVEL_WARN,
 
5625
                                     ER_ILLEGAL_HA_CREATE_OPTION,
 
5626
                                     "InnoDB: KEY_BLOCK_SIZE"
 
5627
                                     " requires innodb_file_format >"
 
5628
                                     " Antelope.");
 
5629
                        iflags = 0;
 
5630
                }
 
5631
 
 
5632
                if (!iflags) {
 
5633
                        push_warning_printf(session, DRIZZLE_ERROR::WARN_LEVEL_WARN,
 
5634
                                            ER_ILLEGAL_HA_CREATE_OPTION,
 
5635
                                            "InnoDB: ignoring"
 
5636
                                            " KEY_BLOCK_SIZE=%lu.",
 
5637
                                            create_proto.options().key_block_size());
 
5638
                }
 
5639
        }
 
5640
 
 
5641
        if (create_proto.options().has_row_type()) {
 
5642
                if (iflags) {
 
5643
                        /* KEY_BLOCK_SIZE was specified. */
 
5644
                        if (form.s->row_type != ROW_TYPE_COMPRESSED) {
 
5645
                                /* ROW_FORMAT other than COMPRESSED
 
5646
                                ignores KEY_BLOCK_SIZE.  It does not
 
5647
                                make sense to reject conflicting
 
5648
                                KEY_BLOCK_SIZE and ROW_FORMAT, because
 
5649
                                such combinations can be obtained
 
5650
                                with ALTER TABLE anyway. */
 
5651
                                push_warning_printf(
 
5652
                                        session,
 
5653
                                        DRIZZLE_ERROR::WARN_LEVEL_WARN,
 
5654
                                        ER_ILLEGAL_HA_CREATE_OPTION,
 
5655
                                        "InnoDB: ignoring KEY_BLOCK_SIZE=%lu"
 
5656
                                        " unless ROW_FORMAT=COMPRESSED.",
 
5657
                                        create_proto.options().key_block_size());
 
5658
                                iflags = 0;
 
5659
                        }
 
5660
                } else {
 
5661
                        /* No KEY_BLOCK_SIZE */
 
5662
                        if (form.s->row_type == ROW_TYPE_COMPRESSED) {
 
5663
                                /* ROW_FORMAT=COMPRESSED without
 
5664
                                KEY_BLOCK_SIZE implies half the
 
5665
                                maximum KEY_BLOCK_SIZE. */
 
5666
                                iflags = (DICT_TF_ZSSIZE_MAX - 1)
 
5667
                                        << DICT_TF_ZSSIZE_SHIFT
 
5668
                                        | DICT_TF_COMPACT
 
5669
                                        | DICT_TF_FORMAT_ZIP
 
5670
                                        << DICT_TF_FORMAT_SHIFT;
6079
5671
#if DICT_TF_ZSSIZE_MAX < 1
6080
5672
# error "DICT_TF_ZSSIZE_MAX < 1"
6081
5673
#endif
6082
 
 
6083
 
    if (SessionVAR(&session, strict_mode))
6084
 
    {
6085
 
      if (! srv_file_per_table)
6086
 
      {
6087
 
        push_warning_printf(
6088
 
                            &session,
6089
 
                            DRIZZLE_ERROR::WARN_LEVEL_WARN,
6090
 
                            ER_ILLEGAL_HA_CREATE_OPTION,
6091
 
                            "InnoDB: ROW_FORMAT=COMPRESSED requires innodb_file_per_table.");
6092
 
      } 
6093
 
      else if (file_format < DICT_TF_FORMAT_ZIP) 
6094
 
      {
6095
 
        push_warning_printf(
6096
 
                            &session,
6097
 
                            DRIZZLE_ERROR::WARN_LEVEL_WARN,
6098
 
                            ER_ILLEGAL_HA_CREATE_OPTION,
6099
 
                            "InnoDB: ROW_FORMAT=compressed requires innodb_file_format > Antelope.");
6100
 
      }
6101
 
    }
6102
 
  }
6103
 
 
6104
 
  /* Look for a primary key */
6105
 
 
6106
 
  primary_key_no= (form.getShare()->hasPrimaryKey() ?
6107
 
                   (int) form.getShare()->getPrimaryKey() :
6108
 
                   -1);
6109
 
 
6110
 
  /* Our function innobase_get_mysql_key_number_for_index assumes
6111
 
    the primary key is always number 0, if it exists */
6112
 
 
6113
 
  assert(primary_key_no == -1 || primary_key_no == 0);
6114
 
 
6115
 
  /* Check for name conflicts (with reserved name) for
6116
 
     any user indices to be created. */
6117
 
  if (innobase_index_name_is_reserved(trx, form.key_info,
6118
 
                                      form.getShare()->keys)) {
6119
 
    error = -1;
6120
 
    goto cleanup;
6121
 
  }
6122
 
 
6123
 
  if (lex_identified_temp_table)
6124
 
    iflags |= DICT_TF2_TEMPORARY << DICT_TF2_SHIFT;
6125
 
 
6126
 
  error= create_table_def(trx, &form, norm_name,
6127
 
                          lex_identified_temp_table ? name2 : NULL,
6128
 
                          iflags);
6129
 
 
6130
 
  session.setXaId((ib_uint64_t) ut_conv_dulint_to_longlong(trx->id));
6131
 
 
6132
 
  if (error) {
6133
 
    goto cleanup;
6134
 
  }
6135
 
 
6136
 
  /* Create the keys */
6137
 
 
6138
 
  if (form.getShare()->sizeKeys() == 0 || primary_key_no == -1) {
6139
 
    /* Create an index which is used as the clustered index;
6140
 
      order the rows by their row id which is internally generated
6141
 
      by InnoDB */
6142
 
 
6143
 
    error = create_clustered_index_when_no_primary(trx, iflags, norm_name);
6144
 
    if (error) {
6145
 
      goto cleanup;
6146
 
    }
6147
 
  }
6148
 
 
6149
 
  if (primary_key_no != -1) {
6150
 
    /* In InnoDB the clustered index must always be created first */
6151
 
    if ((error = create_index(trx, &form, iflags, norm_name,
6152
 
                              (uint) primary_key_no))) {
6153
 
      goto cleanup;
6154
 
    }
6155
 
  }
6156
 
 
6157
 
  for (i = 0; i < form.getShare()->sizeKeys(); i++) {
6158
 
    if (i != (uint) primary_key_no) {
6159
 
 
6160
 
      if ((error = create_index(trx, &form, iflags, norm_name,
6161
 
                                i))) {
6162
 
        goto cleanup;
6163
 
      }
6164
 
    }
6165
 
  }
6166
 
 
6167
 
  stmt = innobase_get_stmt(&session, &stmt_len);
6168
 
 
6169
 
  if (stmt) {
6170
 
    string generated_create_table;
6171
 
    const char *query= stmt;
6172
 
 
6173
 
    if (session_sql_command(&session) == SQLCOM_CREATE_TABLE)
6174
 
    {
6175
 
      message::transformTableDefinitionToSql(create_proto,
6176
 
                                             generated_create_table,
6177
 
                                             message::DRIZZLE, true);
6178
 
      query= generated_create_table.c_str();
6179
 
    }
6180
 
 
6181
 
    error = row_table_add_foreign_constraints(trx,
6182
 
                                              query, strlen(query),
6183
 
                                              norm_name,
6184
 
                                              lex_identified_temp_table);
6185
 
 
6186
 
    error = convert_error_code_to_mysql(error, iflags, NULL);
6187
 
 
6188
 
    if (error) {
6189
 
      goto cleanup;
6190
 
    }
6191
 
  }
6192
 
 
6193
 
  innobase_commit_low(trx);
6194
 
 
6195
 
  row_mysql_unlock_data_dictionary(trx);
6196
 
 
6197
 
  /* Flush the log to reduce probability that the .frm files and
6198
 
    the InnoDB data dictionary get out-of-sync if the user runs
6199
 
    with innodb_flush_log_at_trx_commit = 0 */
6200
 
 
6201
 
  log_buffer_flush_to_disk();
6202
 
 
6203
 
  innobase_table = dict_table_get(norm_name, FALSE);
6204
 
 
6205
 
  assert(innobase_table != 0);
6206
 
 
6207
 
  if (innobase_table) {
6208
 
    /* We update the highest file format in the system table
6209
 
      space, if this table has higher file format setting. */
6210
 
 
6211
 
    trx_sys_file_format_max_upgrade((const char**) &innobase_file_format_check,
6212
 
                                    dict_table_get_format(innobase_table));
6213
 
  }
6214
 
 
6215
 
  /* Note: We can't call update_session() as prebuilt will not be
6216
 
    setup at this stage and so we use session. */
6217
 
 
6218
 
  /* We need to copy the AUTOINC value from the old table if
6219
 
    this is an ALTER TABLE or CREATE INDEX because CREATE INDEX
6220
 
    does a table copy too. */
6221
 
 
6222
 
  if ((create_proto.options().has_auto_increment_value()
6223
 
       || session_sql_command(&session) == SQLCOM_ALTER_TABLE
6224
 
       || session_sql_command(&session) == SQLCOM_CREATE_INDEX)
6225
 
      && create_proto.options().auto_increment_value() != 0) {
6226
 
 
6227
 
    /* Query was one of :
6228
 
       CREATE TABLE ...AUTO_INCREMENT = x; or
6229
 
       ALTER TABLE...AUTO_INCREMENT = x;   or
6230
 
       CREATE INDEX x on t(...);
6231
 
       Find out a table definition from the dictionary and get
6232
 
       the current value of the auto increment field. Set a new
6233
 
       value to the auto increment field if the value is greater
6234
 
       than the maximum value in the column. */
6235
 
 
6236
 
    auto_inc_value = create_proto.options().auto_increment_value();
6237
 
 
6238
 
    dict_table_autoinc_lock(innobase_table);
6239
 
    dict_table_autoinc_initialize(innobase_table, auto_inc_value);
6240
 
    dict_table_autoinc_unlock(innobase_table);
6241
 
  }
6242
 
 
6243
 
  /* Tell the InnoDB server that there might be work for
6244
 
    utility threads: */
6245
 
 
6246
 
  srv_active_wake_master_thread();
6247
 
 
6248
 
  trx_free_for_mysql(trx);
6249
 
 
6250
 
  if (lex_identified_temp_table)
6251
 
  {
6252
 
    session.getMessageCache().storeTableMessage(identifier, create_proto);
6253
 
  }
6254
 
  else
6255
 
  {
6256
 
    StorageEngine::writeDefinitionFromPath(identifier, create_proto);
6257
 
  }
6258
 
 
6259
 
  return(0);
 
5674
                        }
 
5675
                }
 
5676
 
 
5677
                switch (form.s->row_type) {
 
5678
                        const char* row_format_name;
 
5679
                case ROW_TYPE_REDUNDANT:
 
5680
                        break;
 
5681
                case ROW_TYPE_COMPRESSED:
 
5682
                case ROW_TYPE_DYNAMIC:
 
5683
                        row_format_name
 
5684
                                = form.s->row_type == ROW_TYPE_COMPRESSED
 
5685
                                ? "COMPRESSED"
 
5686
                                : "DYNAMIC";
 
5687
 
 
5688
                        if (!srv_file_per_table) {
 
5689
                                push_warning_printf(
 
5690
                                        session,
 
5691
                                        DRIZZLE_ERROR::WARN_LEVEL_WARN,
 
5692
                                        ER_ILLEGAL_HA_CREATE_OPTION,
 
5693
                                        "InnoDB: ROW_FORMAT=%s"
 
5694
                                        " requires innodb_file_per_table.",
 
5695
                                        row_format_name);
 
5696
                        } else if (file_format < DICT_TF_FORMAT_ZIP) {
 
5697
                                push_warning_printf(
 
5698
                                        session,
 
5699
                                        DRIZZLE_ERROR::WARN_LEVEL_WARN,
 
5700
                                        ER_ILLEGAL_HA_CREATE_OPTION,
 
5701
                                        "InnoDB: ROW_FORMAT=%s"
 
5702
                                        " requires innodb_file_format >"
 
5703
                                        " Antelope.",
 
5704
                                        row_format_name);
 
5705
                        } else {
 
5706
                                iflags |= DICT_TF_COMPACT
 
5707
                                        | (DICT_TF_FORMAT_ZIP
 
5708
                                           << DICT_TF_FORMAT_SHIFT);
 
5709
                                break;
 
5710
                        }
 
5711
 
 
5712
                        /* fall through */
 
5713
                case ROW_TYPE_NOT_USED:
 
5714
                case ROW_TYPE_FIXED:
 
5715
                default:
 
5716
                        error = ER_ILLEGAL_HA_CREATE_OPTION;
 
5717
                        goto cleanup;
 
5718
                case ROW_TYPE_DEFAULT:
 
5719
                case ROW_TYPE_COMPACT:
 
5720
                        iflags = DICT_TF_COMPACT;
 
5721
                        break;
 
5722
                }
 
5723
        } else if (!iflags) {
 
5724
                /* No KEY_BLOCK_SIZE or ROW_FORMAT specified:
 
5725
                use ROW_FORMAT=COMPACT by default. */
 
5726
                iflags = DICT_TF_COMPACT;
 
5727
        }
 
5728
 
 
5729
        error = create_table_def(trx, &form, norm_name,
 
5730
                lex_identified_temp_table ? name2 : NULL,
 
5731
                iflags);
 
5732
 
 
5733
        if (error) {
 
5734
                goto cleanup;
 
5735
        }
 
5736
 
 
5737
        /* Look for a primary key */
 
5738
 
 
5739
        primary_key_no= (form.s->primary_key != MAX_KEY ?
 
5740
                         (int) form.s->primary_key :
 
5741
                         -1);
 
5742
 
 
5743
        /* Our function row_get_mysql_key_number_for_index assumes
 
5744
        the primary key is always number 0, if it exists */
 
5745
 
 
5746
        assert(primary_key_no == -1 || primary_key_no == 0);
 
5747
 
 
5748
        /* Create the keys */
 
5749
 
 
5750
        if (form.s->keys == 0 || primary_key_no == -1) {
 
5751
                /* Create an index which is used as the clustered index;
 
5752
                order the rows by their row id which is internally generated
 
5753
                by InnoDB */
 
5754
 
 
5755
                error = create_clustered_index_when_no_primary(
 
5756
                        trx, iflags, norm_name);
 
5757
                if (error) {
 
5758
                        goto cleanup;
 
5759
                }
 
5760
        }
 
5761
 
 
5762
        if (primary_key_no != -1) {
 
5763
                /* In InnoDB the clustered index must always be created
 
5764
                first */
 
5765
                if ((error = create_index(trx, &form, iflags, norm_name,
 
5766
                                          (uint) primary_key_no))) {
 
5767
                        goto cleanup;
 
5768
                }
 
5769
        }
 
5770
 
 
5771
        for (i = 0; i < form.s->keys; i++) {
 
5772
 
 
5773
                if (i != (uint) primary_key_no) {
 
5774
 
 
5775
                        if ((error = create_index(trx, &form, iflags, norm_name,
 
5776
                                                  i))) {
 
5777
                                goto cleanup;
 
5778
                        }
 
5779
                }
 
5780
        }
 
5781
 
 
5782
        if (trx->mysql_query_str) {
 
5783
                error = row_table_add_foreign_constraints(trx,
 
5784
                        trx->mysql_query_str, norm_name,
 
5785
                        lex_identified_temp_table);
 
5786
 
 
5787
                error = convert_error_code_to_mysql(error, iflags, NULL);
 
5788
 
 
5789
                if (error) {
 
5790
                        goto cleanup;
 
5791
                }
 
5792
        }
 
5793
 
 
5794
        innobase_commit_low(trx);
 
5795
 
 
5796
        row_mysql_unlock_data_dictionary(trx);
 
5797
 
 
5798
        /* Flush the log to reduce probability that the .frm files and
 
5799
        the InnoDB data dictionary get out-of-sync if the user runs
 
5800
        with innodb_flush_log_at_trx_commit = 0 */
 
5801
 
 
5802
        log_buffer_flush_to_disk();
 
5803
 
 
5804
        innobase_table = dict_table_get(norm_name, FALSE);
 
5805
 
 
5806
        assert(innobase_table != 0);
 
5807
 
 
5808
        if (innobase_table) {
 
5809
                /* We update the highest file format in the system table
 
5810
                space, if this table has higher file format setting. */
 
5811
 
 
5812
                trx_sys_file_format_max_upgrade(
 
5813
                        (const char**) &innobase_file_format_check,
 
5814
                        dict_table_get_format(innobase_table));
 
5815
        }
 
5816
 
 
5817
        /* Note: We can't call update_session() as prebuilt will not be
 
5818
        setup at this stage and so we use session. */
 
5819
 
 
5820
        /* We need to copy the AUTOINC value from the old table if
 
5821
        this is an ALTER TABLE. */
 
5822
 
 
5823
        if ((create_proto.options().has_auto_increment_value()
 
5824
            || session_sql_command(session) == SQLCOM_ALTER_TABLE)
 
5825
            && create_proto.options().auto_increment_value() != 0) {
 
5826
 
 
5827
                /* Query was ALTER TABLE...AUTO_INCREMENT = x; or
 
5828
                CREATE TABLE ...AUTO_INCREMENT = x; Find out a table
 
5829
                definition from the dictionary and get the current value
 
5830
                of the auto increment field. Set a new value to the
 
5831
                auto increment field if the value is greater than the
 
5832
                maximum value in the column. */
 
5833
 
 
5834
                auto_inc_value = create_proto.options().auto_increment_value();
 
5835
 
 
5836
                dict_table_autoinc_lock(innobase_table);
 
5837
                dict_table_autoinc_initialize(innobase_table, auto_inc_value);
 
5838
                dict_table_autoinc_unlock(innobase_table);
 
5839
        }
 
5840
 
 
5841
        /* Tell the InnoDB server that there might be work for
 
5842
        utility threads: */
 
5843
 
 
5844
        srv_active_wake_master_thread();
 
5845
 
 
5846
        trx_free_for_mysql(trx);
 
5847
 
 
5848
        return(0);
6260
5849
 
6261
5850
cleanup:
6262
 
  innobase_commit_low(trx);
6263
 
 
6264
 
  row_mysql_unlock_data_dictionary(trx);
6265
 
 
6266
 
  trx_free_for_mysql(trx);
6267
 
 
6268
 
  return(error);
 
5851
        innobase_commit_low(trx);
 
5852
 
 
5853
        row_mysql_unlock_data_dictionary(trx);
 
5854
 
 
5855
        trx_free_for_mysql(trx);
 
5856
 
 
5857
        return(error);
6269
5858
}
6270
5859
 
6271
5860
/*****************************************************************//**
6272
5861
Discards or imports an InnoDB tablespace.
6273
 
@return 0 == success, -1 == error */
 
5862
@return 0 == success, -1 == error */
6274
5863
UNIV_INTERN
6275
5864
int
6276
5865
ha_innobase::discard_or_import_tablespace(
6277
5866
/*======================================*/
6278
 
  my_bool discard)  /*!< in: TRUE if discard, else import */
 
5867
        my_bool discard)        /*!< in: TRUE if discard, else import */
6279
5868
{
6280
 
  dict_table_t* dict_table;
6281
 
  trx_t*    trx;
6282
 
  int   err;
6283
 
 
6284
 
  ut_a(prebuilt->trx);
6285
 
  ut_a(prebuilt->trx->magic_n == TRX_MAGIC_N);
6286
 
  ut_a(prebuilt->trx == session_to_trx(getTable()->in_use));
6287
 
 
6288
 
  dict_table = prebuilt->table;
6289
 
  trx = prebuilt->trx;
6290
 
 
6291
 
  if (discard) {
6292
 
    err = row_discard_tablespace_for_mysql(dict_table->name, trx);
6293
 
  } else {
6294
 
    err = row_import_tablespace_for_mysql(dict_table->name, trx);
6295
 
  }
6296
 
 
6297
 
  err = convert_error_code_to_mysql(err, dict_table->flags, NULL);
6298
 
 
6299
 
  return(err);
 
5869
        dict_table_t*   dict_table;
 
5870
        trx_t*          trx;
 
5871
        int             err;
 
5872
 
 
5873
        ut_a(prebuilt->trx);
 
5874
        ut_a(prebuilt->trx->magic_n == TRX_MAGIC_N);
 
5875
        ut_a(prebuilt->trx == session_to_trx(ha_session()));
 
5876
 
 
5877
        dict_table = prebuilt->table;
 
5878
        trx = prebuilt->trx;
 
5879
 
 
5880
        if (discard) {
 
5881
                err = row_discard_tablespace_for_mysql(dict_table->name, trx);
 
5882
        } else {
 
5883
                err = row_import_tablespace_for_mysql(dict_table->name, trx);
 
5884
        }
 
5885
 
 
5886
        err = convert_error_code_to_mysql(err, dict_table->flags, NULL);
 
5887
 
 
5888
        return(err);
6300
5889
}
6301
5890
 
6302
5891
/*****************************************************************//**
6303
5892
Deletes all rows of an InnoDB table.
6304
 
@return error number */
 
5893
@return error number */
6305
5894
UNIV_INTERN
6306
5895
int
6307
5896
ha_innobase::delete_all_rows(void)
6308
5897
/*==============================*/
6309
5898
{
6310
 
  int   error;
6311
 
 
6312
 
  /* Get the transaction associated with the current session, or create one
6313
 
  if not yet created, and update prebuilt->trx */
6314
 
 
6315
 
  update_session(getTable()->in_use);
6316
 
 
6317
 
  if (session_sql_command(user_session) != SQLCOM_TRUNCATE) {
6318
 
  fallback:
6319
 
    /* We only handle TRUNCATE TABLE t as a special case.
6320
 
    DELETE FROM t will have to use ha_innobase::doDeleteRecord(),
6321
 
    because DELETE is transactional while TRUNCATE is not. */
6322
 
    return(errno=HA_ERR_WRONG_COMMAND);
6323
 
  }
6324
 
 
6325
 
  /* Truncate the table in InnoDB */
6326
 
 
6327
 
  error = row_truncate_table_for_mysql(prebuilt->table, prebuilt->trx);
6328
 
  if (error == DB_ERROR) {
6329
 
    /* Cannot truncate; resort to ha_innobase::doDeleteRecord() */
6330
 
    goto fallback;
6331
 
  }
6332
 
 
6333
 
  error = convert_error_code_to_mysql(error, prebuilt->table->flags,
6334
 
              NULL);
6335
 
 
6336
 
  return(error);
 
5899
        int             error;
 
5900
 
 
5901
        /* Get the transaction associated with the current session, or create one
 
5902
        if not yet created, and update prebuilt->trx */
 
5903
 
 
5904
        update_session(ha_session());
 
5905
 
 
5906
        if (session_sql_command(user_session) != SQLCOM_TRUNCATE) {
 
5907
        fallback:
 
5908
                /* We only handle TRUNCATE TABLE t as a special case.
 
5909
                DELETE FROM t will have to use ha_innobase::delete_row(),
 
5910
                because DELETE is transactional while TRUNCATE is not. */
 
5911
                return(errno=HA_ERR_WRONG_COMMAND);
 
5912
        }
 
5913
 
 
5914
        /* Truncate the table in InnoDB */
 
5915
 
 
5916
        error = row_truncate_table_for_mysql(prebuilt->table, prebuilt->trx);
 
5917
        if (error == DB_ERROR) {
 
5918
                /* Cannot truncate; resort to ha_innobase::delete_row() */
 
5919
                goto fallback;
 
5920
        }
 
5921
 
 
5922
        error = convert_error_code_to_mysql(error, prebuilt->table->flags,
 
5923
                                            NULL);
 
5924
 
 
5925
        return(error);
6337
5926
}
6338
5927
 
6339
5928
/*****************************************************************//**
6342
5931
Then the current user cannot have locks set on the table. Drop table
6343
5932
operation inside InnoDB will remove all locks any user has on the table
6344
5933
inside InnoDB.
6345
 
@return error number */
 
5934
@return error number */
6346
5935
UNIV_INTERN
6347
5936
int
6348
5937
InnobaseEngine::doDropTable(
6349
5938
/*======================*/
6350
 
        Session &session,
6351
 
        const TableIdentifier &identifier)
 
5939
        Session& session,
 
5940
        const string &table_path)       /* in: table name */
6352
5941
{
6353
 
  int error;
6354
 
  trx_t*  parent_trx;
6355
 
  trx_t*  trx;
6356
 
  char  norm_name[1000];
6357
 
 
6358
 
  ut_a(identifier.getPath().length() < 1000);
6359
 
 
6360
 
  /* Strangely, MySQL passes the table name without the '.frm'
6361
 
    extension, in contrast to ::create */
6362
 
  normalize_table_name(norm_name, identifier.getPath().c_str());
6363
 
 
6364
 
  /* Get the transaction associated with the current session, or create one
6365
 
    if not yet created */
6366
 
 
6367
 
  parent_trx = check_trx_exists(&session);
6368
 
 
6369
 
  /* In case MySQL calls this in the middle of a SELECT query, release
6370
 
    possible adaptive hash latch to avoid deadlocks of threads */
6371
 
 
6372
 
  trx_search_latch_release_if_reserved(parent_trx);
6373
 
 
6374
 
  trx = innobase_trx_allocate(&session);
6375
 
 
6376
 
  srv_lower_case_table_names = TRUE;
6377
 
 
6378
 
  /* Drop the table in InnoDB */
6379
 
 
6380
 
  error = row_drop_table_for_mysql(norm_name, trx,
6381
 
                                   session_sql_command(&session)
6382
 
                                   == SQLCOM_DROP_DB);
6383
 
 
6384
 
  session.setXaId((ib_uint64_t) ut_conv_dulint_to_longlong(trx->id));
6385
 
 
6386
 
  /* Flush the log to reduce probability that the .frm files and
6387
 
    the InnoDB data dictionary get out-of-sync if the user runs
6388
 
    with innodb_flush_log_at_trx_commit = 0 */
6389
 
 
6390
 
  log_buffer_flush_to_disk();
6391
 
 
6392
 
  /* Tell the InnoDB server that there might be work for
6393
 
    utility threads: */
6394
 
 
6395
 
  srv_active_wake_master_thread();
6396
 
 
6397
 
  innobase_commit_low(trx);
6398
 
 
6399
 
  trx_free_for_mysql(trx);
6400
 
 
6401
 
  if (error != ENOENT)
6402
 
    error = convert_error_code_to_mysql(error, 0, NULL);
6403
 
 
6404
 
  if (error == 0 || error == ENOENT)
6405
 
  {
6406
 
    if (identifier.getType() == message::Table::TEMPORARY)
6407
 
    {
6408
 
      session.getMessageCache().removeTableMessage(identifier);
6409
 
      ulint sql_command = session_sql_command(&session);
6410
 
 
6411
 
      // If this was the final removal to an alter table then we will need
6412
 
      // to remove the .dfe that was left behind.
6413
 
      if ((sql_command == SQLCOM_ALTER_TABLE
6414
 
       || sql_command == SQLCOM_CREATE_INDEX
6415
 
       || sql_command == SQLCOM_DROP_INDEX))
6416
 
      {
6417
 
        string path(identifier.getPath());
6418
 
 
6419
 
        path.append(DEFAULT_FILE_EXTENSION);
6420
 
 
6421
 
        (void)internal::my_delete(path.c_str(), MYF(0));
6422
 
      }
6423
 
    }
6424
 
    else
6425
 
    {
6426
 
      string path(identifier.getPath());
6427
 
 
6428
 
      path.append(DEFAULT_FILE_EXTENSION);
6429
 
 
6430
 
      (void)internal::my_delete(path.c_str(), MYF(0));
6431
 
    }
6432
 
  }
6433
 
 
6434
 
  return(error);
 
5942
        int     error;
 
5943
        trx_t*  parent_trx;
 
5944
        trx_t*  trx;
 
5945
        char    norm_name[1000];
 
5946
 
 
5947
        ut_a(table_path.length() < 1000);
 
5948
 
 
5949
        /* Strangely, MySQL passes the table name without the '.frm'
 
5950
        extension, in contrast to ::create */
 
5951
        normalize_table_name(norm_name, table_path.c_str());
 
5952
 
 
5953
        /* Get the transaction associated with the current session, or create one
 
5954
        if not yet created */
 
5955
 
 
5956
        parent_trx = check_trx_exists(&session);
 
5957
 
 
5958
        /* In case MySQL calls this in the middle of a SELECT query, release
 
5959
        possible adaptive hash latch to avoid deadlocks of threads */
 
5960
 
 
5961
        trx_search_latch_release_if_reserved(parent_trx);
 
5962
 
 
5963
        trx = innobase_trx_allocate(&session);
 
5964
 
 
5965
        srv_lower_case_table_names = TRUE;
 
5966
 
 
5967
        /* Drop the table in InnoDB */
 
5968
 
 
5969
        error = row_drop_table_for_mysql(norm_name, trx,
 
5970
                                         session_sql_command(&session)
 
5971
                                         == SQLCOM_DROP_DB);
 
5972
 
 
5973
        /* Flush the log to reduce probability that the .frm files and
 
5974
        the InnoDB data dictionary get out-of-sync if the user runs
 
5975
        with innodb_flush_log_at_trx_commit = 0 */
 
5976
 
 
5977
        log_buffer_flush_to_disk();
 
5978
 
 
5979
        /* Tell the InnoDB server that there might be work for
 
5980
        utility threads: */
 
5981
 
 
5982
        srv_active_wake_master_thread();
 
5983
 
 
5984
        innobase_commit_low(trx);
 
5985
 
 
5986
        trx_free_for_mysql(trx);
 
5987
 
 
5988
        if(error!=ENOENT)
 
5989
          error = convert_error_code_to_mysql(error, 0, NULL);
 
5990
 
 
5991
        return(error);
6435
5992
}
6436
5993
 
6437
5994
/*****************************************************************//**
6439
5996
bool
6440
5997
InnobaseEngine::doDropSchema(
6441
5998
/*===================*/
6442
 
                             const SchemaIdentifier &identifier)
6443
 
    /*!< in: database path; inside InnoDB the name
6444
 
      of the last directory in the path is used as
6445
 
      the database name: for example, in 'mysql/data/test'
6446
 
      the database name is 'test' */
6447
 
{
6448
 
  trx_t*  trx;
6449
 
  int error;
6450
 
  string schema_path(identifier.getPath());
6451
 
  Session*  session   = current_session;
6452
 
 
6453
 
  /* Get the transaction associated with the current session, or create one
6454
 
    if not yet created */
6455
 
 
6456
 
  assert(this == innodb_engine_ptr);
6457
 
 
6458
 
  /* In the Windows plugin, session = current_session is always NULL */
6459
 
  if (session) {
6460
 
    trx_t*  parent_trx = check_trx_exists(session);
6461
 
 
6462
 
    /* In case Drizzle calls this in the middle of a SELECT
6463
 
      query, release possible adaptive hash latch to avoid
6464
 
      deadlocks of threads */
6465
 
 
6466
 
    trx_search_latch_release_if_reserved(parent_trx);
6467
 
  }
6468
 
 
6469
 
  schema_path.append("/");
6470
 
  trx = innobase_trx_allocate(session);
6471
 
  error = row_drop_database_for_mysql(schema_path.c_str(), trx);
6472
 
 
6473
 
  /* Flush the log to reduce probability that the .frm files and
6474
 
    the InnoDB data dictionary get out-of-sync if the user runs
6475
 
    with innodb_flush_log_at_trx_commit = 0 */
6476
 
 
6477
 
  log_buffer_flush_to_disk();
6478
 
 
6479
 
  /* Tell the InnoDB server that there might be work for
6480
 
    utility threads: */
6481
 
 
6482
 
  srv_active_wake_master_thread();
6483
 
 
6484
 
  innobase_commit_low(trx);
6485
 
  trx_free_for_mysql(trx);
6486
 
 
6487
 
  return false; // We are just a listener since we lack control over DDL, so we give no positive acknowledgement. 
6488
 
}
6489
 
 
6490
 
void InnobaseEngine::dropTemporarySchema()
6491
 
{
6492
 
  SchemaIdentifier schema_identifier(GLOBAL_TEMPORARY_EXT);
6493
 
  trx_t*  trx= NULL;
6494
 
  string schema_path(GLOBAL_TEMPORARY_EXT);
6495
 
 
6496
 
  schema_path.append("/");
6497
 
 
6498
 
  trx = trx_allocate_for_mysql();
6499
 
 
6500
 
  trx->mysql_thd = NULL;
6501
 
 
6502
 
  trx->check_foreigns = false;
6503
 
  trx->check_unique_secondary = false;
6504
 
 
6505
 
  (void)row_drop_database_for_mysql(schema_path.c_str(), trx);
6506
 
 
6507
 
  /* Flush the log to reduce probability that the .frm files and
6508
 
    the InnoDB data dictionary get out-of-sync if the user runs
6509
 
    with innodb_flush_log_at_trx_commit = 0 */
6510
 
 
6511
 
  log_buffer_flush_to_disk();
6512
 
 
6513
 
  /* Tell the InnoDB server that there might be work for
6514
 
    utility threads: */
6515
 
 
6516
 
  srv_active_wake_master_thread();
6517
 
 
6518
 
  innobase_commit_low(trx);
6519
 
  trx_free_for_mysql(trx);
 
5999
                             const std::string &schema_name)
 
6000
                /*!< in: database path; inside InnoDB the name
 
6001
                        of the last directory in the path is used as
 
6002
                        the database name: for example, in 'mysql/data/test'
 
6003
                        the database name is 'test' */
 
6004
{
 
6005
        trx_t*  trx;
 
6006
        int     error;
 
6007
        string schema_path(schema_name);
 
6008
        Session*        session         = current_session;
 
6009
 
 
6010
        /* Get the transaction associated with the current session, or create one
 
6011
        if not yet created */
 
6012
 
 
6013
        assert(this == innodb_engine_ptr);
 
6014
 
 
6015
        /* In the Windows plugin, session = current_session is always NULL */
 
6016
        if (session) {
 
6017
                trx_t*  parent_trx = check_trx_exists(session);
 
6018
 
 
6019
                /* In case Drizzle calls this in the middle of a SELECT
 
6020
                query, release possible adaptive hash latch to avoid
 
6021
                deadlocks of threads */
 
6022
 
 
6023
                trx_search_latch_release_if_reserved(parent_trx);
 
6024
        }
 
6025
 
 
6026
        schema_path.append("/");
 
6027
        trx = innobase_trx_allocate(session);
 
6028
        error = row_drop_database_for_mysql(schema_path.c_str(), trx);
 
6029
 
 
6030
        /* Flush the log to reduce probability that the .frm files and
 
6031
        the InnoDB data dictionary get out-of-sync if the user runs
 
6032
        with innodb_flush_log_at_trx_commit = 0 */
 
6033
 
 
6034
        log_buffer_flush_to_disk();
 
6035
 
 
6036
        /* Tell the InnoDB server that there might be work for
 
6037
        utility threads: */
 
6038
 
 
6039
        srv_active_wake_master_thread();
 
6040
 
 
6041
        innobase_commit_low(trx);
 
6042
        trx_free_for_mysql(trx);
 
6043
 
 
6044
        return false; // We are just a listener since we lack control over DDL, so we give no positive acknowledgement. 
6520
6045
}
6521
6046
/*********************************************************************//**
6522
6047
Renames an InnoDB table.
6523
 
@return 0 or error code */
 
6048
@return 0 or error code */
6524
6049
static
6525
6050
int
6526
6051
innobase_rename_table(
6527
6052
/*==================*/
6528
 
  trx_t*    trx,  /*!< in: transaction */
6529
 
  const char* from, /*!< in: old name of the table */
6530
 
  const char* to, /*!< in: new name of the table */
6531
 
  ibool   lock_and_commit)
6532
 
        /*!< in: TRUE=lock data dictionary and commit */
 
6053
        trx_t*          trx,    /*!< in: transaction */
 
6054
        const char*     from,   /*!< in: old name of the table */
 
6055
        const char*     to,     /*!< in: new name of the table */
 
6056
        ibool           lock_and_commit)
 
6057
                                /*!< in: TRUE=lock data dictionary and commit */
6533
6058
{
6534
 
  int error;
6535
 
  char norm_to[FN_REFLEN];
6536
 
  char norm_from[FN_REFLEN];
6537
 
 
6538
 
  srv_lower_case_table_names = TRUE;
6539
 
 
6540
 
  normalize_table_name(norm_to, to);
6541
 
  normalize_table_name(norm_from, from);
6542
 
 
6543
 
  /* Serialize data dictionary operations with dictionary mutex:
6544
 
  no deadlocks can occur then in these operations */
6545
 
 
6546
 
  if (lock_and_commit) {
6547
 
    row_mysql_lock_data_dictionary(trx);
6548
 
  }
6549
 
 
6550
 
  error = row_rename_table_for_mysql(
6551
 
    norm_from, norm_to, trx, lock_and_commit);
6552
 
 
6553
 
  if (error != DB_SUCCESS) {
6554
 
    FILE* ef = dict_foreign_err_file;
6555
 
 
6556
 
    fputs("InnoDB: Renaming table ", ef);
6557
 
    ut_print_name(ef, trx, TRUE, norm_from);
6558
 
    fputs(" to ", ef);
6559
 
    ut_print_name(ef, trx, TRUE, norm_to);
6560
 
    fputs(" failed!\n", ef);
6561
 
  }
6562
 
 
6563
 
  if (lock_and_commit) {
6564
 
    row_mysql_unlock_data_dictionary(trx);
6565
 
 
6566
 
    /* Flush the log to reduce probability that the .frm
6567
 
    files and the InnoDB data dictionary get out-of-sync
6568
 
    if the user runs with innodb_flush_log_at_trx_commit = 0 */
6569
 
 
6570
 
    log_buffer_flush_to_disk();
6571
 
  }
6572
 
 
6573
 
  return error;
 
6059
        int     error;
 
6060
        char*   norm_to;
 
6061
        char*   norm_from;
 
6062
 
 
6063
        srv_lower_case_table_names = TRUE;
 
6064
 
 
6065
        // Magic number 64 arbitrary
 
6066
        norm_to = (char*) malloc(strlen(to) + 64);
 
6067
        norm_from = (char*) malloc(strlen(from) + 64);
 
6068
 
 
6069
        normalize_table_name(norm_to, to);
 
6070
        normalize_table_name(norm_from, from);
 
6071
 
 
6072
        /* Serialize data dictionary operations with dictionary mutex:
 
6073
        no deadlocks can occur then in these operations */
 
6074
 
 
6075
        if (lock_and_commit) {
 
6076
                row_mysql_lock_data_dictionary(trx);
 
6077
        }
 
6078
 
 
6079
        error = row_rename_table_for_mysql(
 
6080
                norm_from, norm_to, trx, lock_and_commit);
 
6081
 
 
6082
        if (error != DB_SUCCESS) {
 
6083
                FILE* ef = dict_foreign_err_file;
 
6084
 
 
6085
                fputs("InnoDB: Renaming table ", ef);
 
6086
                ut_print_name(ef, trx, TRUE, norm_from);
 
6087
                fputs(" to ", ef);
 
6088
                ut_print_name(ef, trx, TRUE, norm_to);
 
6089
                fputs(" failed!\n", ef);
 
6090
        }
 
6091
 
 
6092
        if (lock_and_commit) {
 
6093
                row_mysql_unlock_data_dictionary(trx);
 
6094
 
 
6095
                /* Flush the log to reduce probability that the .frm
 
6096
                files and the InnoDB data dictionary get out-of-sync
 
6097
                if the user runs with innodb_flush_log_at_trx_commit = 0 */
 
6098
 
 
6099
                log_buffer_flush_to_disk();
 
6100
        }
 
6101
 
 
6102
        free(norm_to);
 
6103
        free(norm_from);
 
6104
 
 
6105
        return error;
6574
6106
}
6575
6107
/*********************************************************************//**
6576
6108
Renames an InnoDB table.
6577
 
@return 0 or error code */
6578
 
UNIV_INTERN int InnobaseEngine::doRenameTable(Session &session, const TableIdentifier &from, const TableIdentifier &to)
 
6109
@return 0 or error code */
 
6110
UNIV_INTERN
 
6111
int
 
6112
InnobaseEngine::doRenameTable(
 
6113
/*======================*/
 
6114
        Session*        session,
 
6115
        const char*     from,   /*!< in: old name of the table */
 
6116
        const char*     to)     /*!< in: new name of the table */
6579
6117
{
6580
 
  // A temp table alter table/rename is a shallow rename and only the
6581
 
  // definition needs to be updated.
6582
 
  if (to.getType() == message::Table::TEMPORARY && from.getType() == message::Table::TEMPORARY)
6583
 
  {
6584
 
    session.getMessageCache().renameTableMessage(from, to);
6585
 
    return 0;
6586
 
  }
6587
 
 
6588
 
  trx_t*  trx;
6589
 
  int error;
6590
 
  trx_t*  parent_trx;
6591
 
 
6592
 
  /* Get the transaction associated with the current session, or create one
6593
 
    if not yet created */
6594
 
 
6595
 
  parent_trx = check_trx_exists(&session);
6596
 
 
6597
 
  /* In case MySQL calls this in the middle of a SELECT query, release
6598
 
    possible adaptive hash latch to avoid deadlocks of threads */
6599
 
 
6600
 
  trx_search_latch_release_if_reserved(parent_trx);
6601
 
 
6602
 
  trx = innobase_trx_allocate(&session);
6603
 
 
6604
 
  error = innobase_rename_table(trx, from.getPath().c_str(), to.getPath().c_str(), TRUE);
6605
 
 
6606
 
  session.setXaId((ib_uint64_t) ut_conv_dulint_to_longlong(trx->id));
6607
 
 
6608
 
  /* Tell the InnoDB server that there might be work for
6609
 
    utility threads: */
6610
 
 
6611
 
  srv_active_wake_master_thread();
6612
 
 
6613
 
  innobase_commit_low(trx);
6614
 
  trx_free_for_mysql(trx);
6615
 
 
6616
 
  /* Add a special case to handle the Duplicated Key error
6617
 
     and return DB_ERROR instead.
6618
 
     This is to avoid a possible SIGSEGV error from mysql error
6619
 
     handling code. Currently, mysql handles the Duplicated Key
6620
 
     error by re-entering the storage layer and getting dup key
6621
 
     info by calling get_dup_key(). This operation requires a valid
6622
 
     table handle ('row_prebuilt_t' structure) which could no
6623
 
     longer be available in the error handling stage. The suggested
6624
 
     solution is to report a 'table exists' error message (since
6625
 
     the dup key error here is due to an existing table whose name
6626
 
     is the one we are trying to rename to) and return the generic
6627
 
     error code. */
6628
 
  if (error == (int) DB_DUPLICATE_KEY) {
6629
 
    my_error(ER_TABLE_EXISTS_ERROR, MYF(0), to.getPath().c_str());
6630
 
    error = DB_ERROR;
6631
 
  }
6632
 
 
6633
 
  error = convert_error_code_to_mysql(error, 0, NULL);
6634
 
 
6635
 
  if (not error)
6636
 
  {
6637
 
    // If this fails, we are in trouble
6638
 
    plugin::StorageEngine::renameDefinitionFromPath(to, from);
6639
 
  }
6640
 
 
6641
 
  return(error);
 
6118
        trx_t*  trx;
 
6119
        int     error;
 
6120
        trx_t*  parent_trx;
 
6121
 
 
6122
        /* Get the transaction associated with the current session, or create one
 
6123
        if not yet created */
 
6124
 
 
6125
        parent_trx = check_trx_exists(session);
 
6126
 
 
6127
        /* In case MySQL calls this in the middle of a SELECT query, release
 
6128
        possible adaptive hash latch to avoid deadlocks of threads */
 
6129
 
 
6130
        trx_search_latch_release_if_reserved(parent_trx);
 
6131
 
 
6132
        trx = innobase_trx_allocate(session);
 
6133
 
 
6134
        error = innobase_rename_table(trx, from, to, TRUE);
 
6135
 
 
6136
        /* Tell the InnoDB server that there might be work for
 
6137
        utility threads: */
 
6138
 
 
6139
        srv_active_wake_master_thread();
 
6140
 
 
6141
        innobase_commit_low(trx);
 
6142
        trx_free_for_mysql(trx);
 
6143
 
 
6144
        error = convert_error_code_to_mysql(error, 0, NULL);
 
6145
 
 
6146
        return(error);
6642
6147
}
6643
6148
 
6644
6149
/*********************************************************************//**
6645
6150
Estimates the number of index records in a range.
6646
 
@return estimated number of rows */
 
6151
@return estimated number of rows */
6647
6152
UNIV_INTERN
6648
6153
ha_rows
6649
6154
ha_innobase::records_in_range(
6650
6155
/*==========================*/
6651
 
  uint      keynr,    /*!< in: index number */
6652
 
  key_range   *min_key, /*!< in: start key value of the
6653
 
               range, may also be 0 */
6654
 
  key_range   *max_key) /*!< in: range end key val, may
6655
 
               also be 0 */
 
6156
        uint                    keynr,          /*!< in: index number */
 
6157
        key_range               *min_key,       /*!< in: start key value of the
 
6158
                                                   range, may also be 0 */
 
6159
        key_range               *max_key)       /*!< in: range end key val, may
 
6160
                                                   also be 0 */
6656
6161
{
6657
 
  KeyInfo*    key;
6658
 
  dict_index_t* index;
6659
 
  unsigned char*    key_val_buff2 = (unsigned char*) malloc(
6660
 
              getTable()->getShare()->stored_rec_length
6661
 
          + getTable()->getShare()->max_key_length + 100);
6662
 
  ulint   buff2_len = getTable()->getShare()->stored_rec_length
6663
 
          + getTable()->getShare()->max_key_length + 100;
6664
 
  dtuple_t* range_start;
6665
 
  dtuple_t* range_end;
6666
 
  ib_int64_t  n_rows;
6667
 
  ulint   mode1;
6668
 
  ulint   mode2;
6669
 
  mem_heap_t* heap;
6670
 
 
6671
 
  ut_a(prebuilt->trx == session_to_trx(getTable()->in_use));
6672
 
 
6673
 
  prebuilt->trx->op_info = (char*)"estimating records in index range";
6674
 
 
6675
 
  /* In case MySQL calls this in the middle of a SELECT query, release
6676
 
  possible adaptive hash latch to avoid deadlocks of threads */
6677
 
 
6678
 
  trx_search_latch_release_if_reserved(prebuilt->trx);
6679
 
 
6680
 
  active_index = keynr;
6681
 
 
6682
 
  key = &getTable()->key_info[active_index];
6683
 
 
6684
 
  index = innobase_get_index(keynr);
6685
 
 
6686
 
  /* There exists possibility of not being able to find requested
6687
 
     index due to inconsistency between MySQL and InoDB dictionary info.
6688
 
     Necessary message should have been printed in innobase_get_index() */
6689
 
  if (UNIV_UNLIKELY(!index)) {
6690
 
    n_rows = HA_POS_ERROR;
6691
 
    goto func_exit;
6692
 
  }
6693
 
 
6694
 
  heap = mem_heap_create(2 * (key->key_parts * sizeof(dfield_t)
6695
 
            + sizeof(dtuple_t)));
6696
 
 
6697
 
  range_start = dtuple_create(heap, key->key_parts);
6698
 
  dict_index_copy_types(range_start, index, key->key_parts);
6699
 
 
6700
 
  range_end = dtuple_create(heap, key->key_parts);
6701
 
  dict_index_copy_types(range_end, index, key->key_parts);
6702
 
 
6703
 
  row_sel_convert_mysql_key_to_innobase(
6704
 
        range_start, (byte*) &key_val_buff[0],
6705
 
        (ulint)upd_and_key_val_buff_len,
6706
 
        index,
6707
 
        (byte*) (min_key ? min_key->key :
6708
 
           (const unsigned char*) 0),
6709
 
        (ulint) (min_key ? min_key->length : 0),
6710
 
        prebuilt->trx);
6711
 
 
6712
 
  row_sel_convert_mysql_key_to_innobase(
6713
 
        range_end, (byte*) key_val_buff2,
6714
 
        buff2_len, index,
6715
 
        (byte*) (max_key ? max_key->key :
6716
 
           (const unsigned char*) 0),
6717
 
        (ulint) (max_key ? max_key->length : 0),
6718
 
        prebuilt->trx);
6719
 
 
6720
 
  mode1 = convert_search_mode_to_innobase(min_key ? min_key->flag :
6721
 
            HA_READ_KEY_EXACT);
6722
 
  mode2 = convert_search_mode_to_innobase(max_key ? max_key->flag :
6723
 
            HA_READ_KEY_EXACT);
6724
 
 
6725
 
  if (mode1 != PAGE_CUR_UNSUPP && mode2 != PAGE_CUR_UNSUPP) {
6726
 
 
6727
 
    n_rows = btr_estimate_n_rows_in_range(index, range_start,
6728
 
                  mode1, range_end,
6729
 
                  mode2);
6730
 
  } else {
6731
 
 
6732
 
    n_rows = HA_POS_ERROR;
6733
 
  }
6734
 
 
6735
 
  mem_heap_free(heap);
6736
 
 
6737
 
func_exit:
6738
 
  free(key_val_buff2);
6739
 
 
6740
 
  prebuilt->trx->op_info = (char*)"";
6741
 
 
6742
 
  /* The MySQL optimizer seems to believe an estimate of 0 rows is
6743
 
  always accurate and may return the result 'Empty set' based on that.
6744
 
  The accuracy is not guaranteed, and even if it were, for a locking
6745
 
  read we should anyway perform the search to set the next-key lock.
6746
 
  Add 1 to the value to make sure MySQL does not make the assumption! */
6747
 
 
6748
 
  if (n_rows == 0) {
6749
 
    n_rows = 1;
6750
 
  }
6751
 
 
6752
 
  return((ha_rows) n_rows);
 
6162
        KEY*            key;
 
6163
        dict_index_t*   index;
 
6164
        unsigned char*          key_val_buff2   = (unsigned char*) malloc(
 
6165
                                                  table->s->stored_rec_length
 
6166
                                        + table->s->max_key_length + 100);
 
6167
        ulint           buff2_len = table->s->stored_rec_length
 
6168
                                        + table->s->max_key_length + 100;
 
6169
        dtuple_t*       range_start;
 
6170
        dtuple_t*       range_end;
 
6171
        ib_int64_t      n_rows;
 
6172
        ulint           mode1;
 
6173
        ulint           mode2;
 
6174
        mem_heap_t*     heap;
 
6175
 
 
6176
        ut_a(prebuilt->trx == session_to_trx(ha_session()));
 
6177
 
 
6178
        prebuilt->trx->op_info = (char*)"estimating records in index range";
 
6179
 
 
6180
        /* In case MySQL calls this in the middle of a SELECT query, release
 
6181
        possible adaptive hash latch to avoid deadlocks of threads */
 
6182
 
 
6183
        trx_search_latch_release_if_reserved(prebuilt->trx);
 
6184
 
 
6185
        active_index = keynr;
 
6186
 
 
6187
        key = table->key_info + active_index;
 
6188
 
 
6189
        index = dict_table_get_index_on_name(prebuilt->table, key->name);
 
6190
 
 
6191
        /* MySQL knows about this index and so we must be able to find it.*/
 
6192
        ut_a(index);
 
6193
 
 
6194
        heap = mem_heap_create(2 * (key->key_parts * sizeof(dfield_t)
 
6195
                                    + sizeof(dtuple_t)));
 
6196
 
 
6197
        range_start = dtuple_create(heap, key->key_parts);
 
6198
        dict_index_copy_types(range_start, index, key->key_parts);
 
6199
 
 
6200
        range_end = dtuple_create(heap, key->key_parts);
 
6201
        dict_index_copy_types(range_end, index, key->key_parts);
 
6202
 
 
6203
        row_sel_convert_mysql_key_to_innobase(
 
6204
                                range_start, (byte*) key_val_buff,
 
6205
                                (ulint)upd_and_key_val_buff_len,
 
6206
                                index,
 
6207
                                (byte*) (min_key ? min_key->key :
 
6208
                                         (const unsigned char*) 0),
 
6209
                                (ulint) (min_key ? min_key->length : 0),
 
6210
                                prebuilt->trx);
 
6211
 
 
6212
        row_sel_convert_mysql_key_to_innobase(
 
6213
                                range_end, (byte*) key_val_buff2,
 
6214
                                buff2_len, index,
 
6215
                                (byte*) (max_key ? max_key->key :
 
6216
                                         (const unsigned char*) 0),
 
6217
                                (ulint) (max_key ? max_key->length : 0),
 
6218
                                prebuilt->trx);
 
6219
 
 
6220
        mode1 = convert_search_mode_to_innobase(min_key ? min_key->flag :
 
6221
                                                HA_READ_KEY_EXACT);
 
6222
        mode2 = convert_search_mode_to_innobase(max_key ? max_key->flag :
 
6223
                                                HA_READ_KEY_EXACT);
 
6224
 
 
6225
        if (mode1 != PAGE_CUR_UNSUPP && mode2 != PAGE_CUR_UNSUPP) {
 
6226
 
 
6227
                n_rows = btr_estimate_n_rows_in_range(index, range_start,
 
6228
                                                      mode1, range_end,
 
6229
                                                      mode2);
 
6230
        } else {
 
6231
 
 
6232
                n_rows = HA_POS_ERROR;
 
6233
        }
 
6234
 
 
6235
        mem_heap_free(heap);
 
6236
 
 
6237
        free(key_val_buff2);
 
6238
 
 
6239
        prebuilt->trx->op_info = (char*)"";
 
6240
 
 
6241
        /* The MySQL optimizer seems to believe an estimate of 0 rows is
 
6242
        always accurate and may return the result 'Empty set' based on that.
 
6243
        The accuracy is not guaranteed, and even if it were, for a locking
 
6244
        read we should anyway perform the search to set the next-key lock.
 
6245
        Add 1 to the value to make sure MySQL does not make the assumption! */
 
6246
 
 
6247
        if (n_rows == 0) {
 
6248
                n_rows = 1;
 
6249
        }
 
6250
 
 
6251
        return((ha_rows) n_rows);
6753
6252
}
6754
6253
 
6755
6254
/*********************************************************************//**
6756
6255
Gives an UPPER BOUND to the number of rows in a table. This is used in
6757
6256
filesort.cc.
6758
 
@return upper bound of rows */
 
6257
@return upper bound of rows */
6759
6258
UNIV_INTERN
6760
6259
ha_rows
6761
6260
ha_innobase::estimate_rows_upper_bound(void)
6762
6261
/*======================================*/
6763
6262
{
6764
 
  dict_index_t* index;
6765
 
  uint64_t  estimate;
6766
 
  uint64_t  local_data_file_length;
6767
 
 
6768
 
  /* We do not know if MySQL can call this function before calling
6769
 
  external_lock(). To be safe, update the session of the current table
6770
 
  handle. */
6771
 
 
6772
 
  update_session(getTable()->in_use);
6773
 
 
6774
 
  prebuilt->trx->op_info = (char*)
6775
 
         "calculating upper bound for table rows";
6776
 
 
6777
 
  /* In case MySQL calls this in the middle of a SELECT query, release
6778
 
  possible adaptive hash latch to avoid deadlocks of threads */
6779
 
 
6780
 
  trx_search_latch_release_if_reserved(prebuilt->trx);
6781
 
 
6782
 
  index = dict_table_get_first_index(prebuilt->table);
6783
 
 
6784
 
  ut_a(index->stat_n_leaf_pages > 0);
6785
 
 
6786
 
  local_data_file_length =
6787
 
    ((uint64_t) index->stat_n_leaf_pages) * UNIV_PAGE_SIZE;
6788
 
 
6789
 
 
6790
 
  /* Calculate a minimum length for a clustered index record and from
6791
 
  that an upper bound for the number of rows. Since we only calculate
6792
 
  new statistics in row0mysql.c when a table has grown by a threshold
6793
 
  factor, we must add a safety factor 2 in front of the formula below. */
6794
 
 
6795
 
  estimate = 2 * local_data_file_length /
6796
 
           dict_index_calc_min_rec_len(index);
6797
 
 
6798
 
  prebuilt->trx->op_info = (char*)"";
6799
 
 
6800
 
  return((ha_rows) estimate);
 
6263
        dict_index_t*   index;
 
6264
        uint64_t        estimate;
 
6265
        uint64_t        local_data_file_length;
 
6266
 
 
6267
        /* We do not know if MySQL can call this function before calling
 
6268
        external_lock(). To be safe, update the session of the current table
 
6269
        handle. */
 
6270
 
 
6271
        update_session(ha_session());
 
6272
 
 
6273
        prebuilt->trx->op_info = (char*)
 
6274
                                 "calculating upper bound for table rows";
 
6275
 
 
6276
        /* In case MySQL calls this in the middle of a SELECT query, release
 
6277
        possible adaptive hash latch to avoid deadlocks of threads */
 
6278
 
 
6279
        trx_search_latch_release_if_reserved(prebuilt->trx);
 
6280
 
 
6281
        index = dict_table_get_first_index(prebuilt->table);
 
6282
 
 
6283
        ut_a(index->stat_n_leaf_pages > 0);
 
6284
 
 
6285
        local_data_file_length =
 
6286
                ((uint64_t) index->stat_n_leaf_pages) * UNIV_PAGE_SIZE;
 
6287
 
 
6288
 
 
6289
        /* Calculate a minimum length for a clustered index record and from
 
6290
        that an upper bound for the number of rows. Since we only calculate
 
6291
        new statistics in row0mysql.c when a table has grown by a threshold
 
6292
        factor, we must add a safety factor 2 in front of the formula below. */
 
6293
 
 
6294
        estimate = 2 * local_data_file_length /
 
6295
                                         dict_index_calc_min_rec_len(index);
 
6296
 
 
6297
        prebuilt->trx->op_info = (char*)"";
 
6298
 
 
6299
        return((ha_rows) estimate);
6801
6300
}
6802
6301
 
6803
6302
/*********************************************************************//**
6804
6303
How many seeks it will take to read through the table. This is to be
6805
6304
comparable to the number returned by records_in_range so that we can
6806
6305
decide if we should scan the table or use keys.
6807
 
@return estimated time measured in disk seeks */
 
6306
@return estimated time measured in disk seeks */
6808
6307
UNIV_INTERN
6809
6308
double
6810
6309
ha_innobase::scan_time()
6811
6310
/*====================*/
6812
6311
{
6813
 
  /* Since MySQL seems to favor table scans too much over index
6814
 
  searches, we pretend that a sequential read takes the same time
6815
 
  as a random disk read, that is, we do not divide the following
6816
 
  by 10, which would be physically realistic. */
 
6312
        /* Since MySQL seems to favor table scans too much over index
 
6313
        searches, we pretend that a sequential read takes the same time
 
6314
        as a random disk read, that is, we do not divide the following
 
6315
        by 10, which would be physically realistic. */
6817
6316
 
6818
 
  return((double) (prebuilt->table->stat_clustered_index_size));
 
6317
        return((double) (prebuilt->table->stat_clustered_index_size));
6819
6318
}
6820
6319
 
6821
6320
/******************************************************************//**
6822
6321
Calculate the time it takes to read a set of ranges through an index
6823
6322
This enables us to optimise reads for clustered indexes.
6824
 
@return estimated time measured in disk seeks */
 
6323
@return estimated time measured in disk seeks */
6825
6324
UNIV_INTERN
6826
6325
double
6827
6326
ha_innobase::read_time(
6828
6327
/*===================*/
6829
 
  uint  index,  /*!< in: key number */
6830
 
  uint  ranges, /*!< in: how many ranges */
6831
 
  ha_rows rows) /*!< in: estimated number of rows in the ranges */
6832
 
{
6833
 
  ha_rows total_rows;
6834
 
  double  time_for_scan;
6835
 
 
6836
 
  if (index != getTable()->getShare()->getPrimaryKey()) {
6837
 
    /* Not clustered */
6838
 
    return(Cursor::read_time(index, ranges, rows));
6839
 
  }
6840
 
 
6841
 
  if (rows <= 2) {
6842
 
 
6843
 
    return((double) rows);
6844
 
  }
6845
 
 
6846
 
  /* Assume that the read time is proportional to the scan time for all
6847
 
  rows + at most one seek per range. */
6848
 
 
6849
 
  time_for_scan = scan_time();
6850
 
 
6851
 
  if ((total_rows = estimate_rows_upper_bound()) < rows) {
6852
 
 
6853
 
    return(time_for_scan);
6854
 
  }
6855
 
 
6856
 
  return(ranges + (double) rows / (double) total_rows * time_for_scan);
6857
 
}
6858
 
 
6859
 
/*********************************************************************//**
6860
 
Calculates the key number used inside MySQL for an Innobase index. We will
6861
 
first check the "index translation table" for a match of the index to get
6862
 
the index number. If there does not exist an "index translation table",
6863
 
or not able to find the index in the translation table, then we will fall back
6864
 
to the traditional way of looping through dict_index_t list to find a
6865
 
match. In this case, we have to take into account if we generated a
6866
 
default clustered index for the table
6867
 
@return the key number used inside MySQL */
6868
 
static
6869
 
unsigned int
6870
 
innobase_get_mysql_key_number_for_index(
6871
 
/*====================================*/
6872
 
        INNOBASE_SHARE*         share,  /*!< in: share structure for index
6873
 
                                        translation table. */
6874
 
        const drizzled::Table*  table,  /*!< in: table in MySQL data
6875
 
                                        dictionary */
6876
 
        dict_table_t*           ib_table,/*!< in: table in Innodb data
6877
 
                                        dictionary */
6878
 
        const dict_index_t*     index)  /*!< in: index */
6879
 
{
6880
 
        const dict_index_t*     ind;
6881
 
        unsigned int            i;
6882
 
 
6883
 
        ut_ad(index);
6884
 
        ut_ad(ib_table);
6885
 
        ut_ad(table);
6886
 
        ut_ad(share);
6887
 
 
6888
 
        /* If index does not belong to the table of share structure. Search
6889
 
        index->table instead */
6890
 
        if (index->table != ib_table
6891
 
            && strcmp(index->table->name, share->table_name)) {
6892
 
                i = 0;
6893
 
                ind = dict_table_get_first_index(index->table);
6894
 
 
6895
 
                while (index != ind) {
6896
 
                        ind = dict_table_get_next_index(ind);
6897
 
                        i++;
6898
 
                }
6899
 
 
6900
 
                if (row_table_got_default_clust_index(index->table)) {
6901
 
                        ut_a(i > 0);
6902
 
                        i--;
6903
 
                }
6904
 
 
6905
 
                return(i);
6906
 
        }
6907
 
 
6908
 
        /* If index translation table exists, we will first check
6909
 
        the index through index translation table for a match. */
6910
 
        if (share->idx_trans_tbl.index_mapping) {
6911
 
                for (i = 0; i < share->idx_trans_tbl.index_count; i++) {
6912
 
                        if (share->idx_trans_tbl.index_mapping[i] == index) {
6913
 
                                return(i);
6914
 
                        }
6915
 
                }
6916
 
 
6917
 
                /* Print an error message if we cannot find the index
6918
 
                ** in the "index translation table". */
6919
 
                errmsg_printf(ERRMSG_LVL_ERROR,
6920
 
                              "Cannot find index %s in InnoDB index "
6921
 
                                "translation table.", index->name);
6922
 
        }
6923
 
 
6924
 
        /* If we do not have an "index translation table", or not able
6925
 
        to find the index in the translation table, we'll directly find
6926
 
        matching index in the dict_index_t list */
6927
 
        for (i = 0; i < table->getShare()->keys; i++) {
6928
 
                ind = dict_table_get_index_on_name(
6929
 
                        ib_table, table->key_info[i].name);
6930
 
 
6931
 
                if (index == ind) {
6932
 
                        return(i);
6933
 
                }
6934
 
        }
6935
 
 
6936
 
                errmsg_printf(ERRMSG_LVL_ERROR,
6937
 
                              "Cannot find matching index number for index %s "
6938
 
                              "in InnoDB index list.", index->name);
6939
 
 
6940
 
        return(0);
6941
 
}
 
6328
        uint    index,  /*!< in: key number */
 
6329
        uint    ranges, /*!< in: how many ranges */
 
6330
        ha_rows rows)   /*!< in: estimated number of rows in the ranges */
 
6331
{
 
6332
        ha_rows total_rows;
 
6333
        double  time_for_scan;
 
6334
 
 
6335
        if (index != table->s->primary_key) {
 
6336
                /* Not clustered */
 
6337
                return(Cursor::read_time(index, ranges, rows));
 
6338
        }
 
6339
 
 
6340
        if (rows <= 2) {
 
6341
 
 
6342
                return((double) rows);
 
6343
        }
 
6344
 
 
6345
        /* Assume that the read time is proportional to the scan time for all
 
6346
        rows + at most one seek per range. */
 
6347
 
 
6348
        time_for_scan = scan_time();
 
6349
 
 
6350
        if ((total_rows = estimate_rows_upper_bound()) < rows) {
 
6351
 
 
6352
                return(time_for_scan);
 
6353
        }
 
6354
 
 
6355
        return(ranges + (double) rows / (double) total_rows * time_for_scan);
 
6356
}
 
6357
 
6942
6358
/*********************************************************************//**
6943
6359
Returns statistics information of the table to the MySQL interpreter,
6944
6360
in various fields of the handle object. */
6946
6362
int
6947
6363
ha_innobase::info(
6948
6364
/*==============*/
6949
 
  uint flag)  /*!< in: what information MySQL requests */
 
6365
        uint flag)      /*!< in: what information MySQL requests */
6950
6366
{
6951
 
  dict_table_t* ib_table;
6952
 
  dict_index_t* index;
6953
 
  ha_rows   rec_per_key;
6954
 
  ib_int64_t  n_rows;
6955
 
  ulong   j;
6956
 
  ulong   i;
6957
 
  os_file_stat_t  stat_info;
6958
 
 
6959
 
  /* If we are forcing recovery at a high level, we will suppress
6960
 
  statistics calculation on tables, because that may crash the
6961
 
  server if an index is badly corrupted. */
6962
 
 
6963
 
  if (srv_force_recovery >= SRV_FORCE_NO_IBUF_MERGE) {
6964
 
 
6965
 
    /* We return success (0) instead of HA_ERR_CRASHED,
6966
 
    because we want MySQL to process this query and not
6967
 
    stop, like it would do if it received the error code
6968
 
    HA_ERR_CRASHED. */
6969
 
 
6970
 
    return(0);
6971
 
  }
6972
 
 
6973
 
  /* We do not know if MySQL can call this function before calling
6974
 
  external_lock(). To be safe, update the session of the current table
6975
 
  handle. */
6976
 
 
6977
 
  update_session(getTable()->in_use);
6978
 
 
6979
 
  /* In case MySQL calls this in the middle of a SELECT query, release
6980
 
  possible adaptive hash latch to avoid deadlocks of threads */
6981
 
 
6982
 
  prebuilt->trx->op_info = (char*)"returning various info to MySQL";
6983
 
 
6984
 
  trx_search_latch_release_if_reserved(prebuilt->trx);
6985
 
 
6986
 
  ib_table = prebuilt->table;
6987
 
 
6988
 
  if (flag & HA_STATUS_TIME) {
6989
 
    /* In Analyze we call with this flag: update
6990
 
       then statistics so that they are up-to-date */
6991
 
 
6992
 
    prebuilt->trx->op_info = "updating table statistics";
6993
 
 
6994
 
    dict_update_statistics(ib_table);
6995
 
 
6996
 
    prebuilt->trx->op_info = "returning various info to MySQL";
6997
 
 
6998
 
    fs::path get_status_path(getDataHomeCatalog());
6999
 
    get_status_path /= ib_table->name;
7000
 
    fs::change_extension(get_status_path, "dfe");
7001
 
 
7002
 
    /* Note that we do not know the access time of the table,
7003
 
    nor the CHECK TABLE time, nor the UPDATE or INSERT time. */
7004
 
 
7005
 
    if (os_file_get_status(get_status_path.file_string().c_str(), &stat_info)) {
7006
 
      stats.create_time = (ulong) stat_info.ctime;
7007
 
    }
7008
 
  }
7009
 
 
7010
 
  if (flag & HA_STATUS_VARIABLE) {
7011
 
    n_rows = ib_table->stat_n_rows;
7012
 
 
7013
 
    /* Because we do not protect stat_n_rows by any mutex in a
7014
 
    delete, it is theoretically possible that the value can be
7015
 
    smaller than zero! TODO: fix this race.
7016
 
 
7017
 
    The MySQL optimizer seems to assume in a left join that n_rows
7018
 
    is an accurate estimate if it is zero. Of course, it is not,
7019
 
    since we do not have any locks on the rows yet at this phase.
7020
 
    Since SHOW TABLE STATUS seems to call this function with the
7021
 
    HA_STATUS_TIME flag set, while the left join optimizer does not
7022
 
    set that flag, we add one to a zero value if the flag is not
7023
 
    set. That way SHOW TABLE STATUS will show the best estimate,
7024
 
    while the optimizer never sees the table empty. */
7025
 
 
7026
 
    if (n_rows < 0) {
7027
 
      n_rows = 0;
7028
 
    }
7029
 
 
7030
 
    if (n_rows == 0 && !(flag & HA_STATUS_TIME)) {
7031
 
      n_rows++;
7032
 
    }
7033
 
 
7034
 
    /* Fix bug#40386: Not flushing query cache after truncate.
7035
 
    n_rows can not be 0 unless the table is empty, set to 1
7036
 
    instead. The original problem of bug#29507 is actually
7037
 
    fixed in the server code. */
7038
 
    if (session_sql_command(user_session) == SQLCOM_TRUNCATE) {
7039
 
 
7040
 
      n_rows = 1;
7041
 
 
7042
 
      /* We need to reset the prebuilt value too, otherwise
7043
 
      checks for values greater than the last value written
7044
 
      to the table will fail and the autoinc counter will
7045
 
      not be updated. This will force doInsertRecord() into
7046
 
      attempting an update of the table's AUTOINC counter. */
7047
 
 
7048
 
      prebuilt->autoinc_last_value = 0;
7049
 
    }
7050
 
 
7051
 
    stats.records = (ha_rows)n_rows;
7052
 
    stats.deleted = 0;
7053
 
    stats.data_file_length = ((uint64_t)
7054
 
        ib_table->stat_clustered_index_size)
7055
 
          * UNIV_PAGE_SIZE;
7056
 
    stats.index_file_length = ((uint64_t)
7057
 
        ib_table->stat_sum_of_other_index_sizes)
7058
 
          * UNIV_PAGE_SIZE;
7059
 
 
7060
 
    /* Since fsp_get_available_space_in_free_extents() is
7061
 
    acquiring latches inside InnoDB, we do not call it if we
7062
 
    are asked by MySQL to avoid locking. Another reason to
7063
 
    avoid the call is that it uses quite a lot of CPU.
7064
 
    See Bug#38185.
7065
 
    We do not update delete_length if no locking is requested
7066
 
    so the "old" value can remain. delete_length is initialized
7067
 
    to 0 in the ha_statistics' constructor. */
7068
 
    if (!(flag & HA_STATUS_NO_LOCK)) {
7069
 
 
7070
 
      /* lock the data dictionary to avoid races with
7071
 
      ibd_file_missing and tablespace_discarded */
7072
 
      row_mysql_lock_data_dictionary(prebuilt->trx);
7073
 
 
7074
 
      /* ib_table->space must be an existent tablespace */
7075
 
      if (!ib_table->ibd_file_missing
7076
 
          && !ib_table->tablespace_discarded) {
7077
 
 
7078
 
        stats.delete_length =
7079
 
          fsp_get_available_space_in_free_extents(
7080
 
            ib_table->space) * 1024;
7081
 
      } else {
7082
 
 
7083
 
        Session*  session;
7084
 
 
7085
 
        session= getTable()->in_use;
7086
 
        assert(session);
7087
 
 
7088
 
        push_warning_printf(
7089
 
          session,
7090
 
          DRIZZLE_ERROR::WARN_LEVEL_WARN,
7091
 
          ER_CANT_GET_STAT,
7092
 
          "InnoDB: Trying to get the free "
7093
 
          "space for table %s but its "
7094
 
          "tablespace has been discarded or "
7095
 
          "the .ibd file is missing. Setting "
7096
 
          "the free space to zero.",
7097
 
          ib_table->name);
7098
 
 
7099
 
        stats.delete_length = 0;
7100
 
      }
7101
 
 
7102
 
      row_mysql_unlock_data_dictionary(prebuilt->trx);
7103
 
    }
7104
 
 
7105
 
    stats.check_time = 0;
7106
 
 
7107
 
    if (stats.records == 0) {
7108
 
      stats.mean_rec_length = 0;
7109
 
    } else {
7110
 
      stats.mean_rec_length = (ulong) (stats.data_file_length / stats.records);
7111
 
    }
7112
 
  }
7113
 
 
7114
 
  if (flag & HA_STATUS_CONST) {
7115
 
    /* Verify the number of index in InnoDB and MySQL
7116
 
       matches up. If prebuilt->clust_index_was_generated
7117
 
       holds, InnoDB defines GEN_CLUST_INDEX internally */
7118
 
    ulint       num_innodb_index = UT_LIST_GET_LEN(ib_table->indexes) - prebuilt->clust_index_was_generated;
7119
 
 
7120
 
    if (getTable()->getShare()->keys != num_innodb_index) {
7121
 
      errmsg_printf(ERRMSG_LVL_ERROR, "Table %s contains %lu "
7122
 
                      "indexes inside InnoDB, which "
7123
 
                      "is different from the number of "
7124
 
                      "indexes %u defined in the MySQL ",
7125
 
                      ib_table->name, num_innodb_index,
7126
 
                      getTable()->getShare()->keys);
7127
 
    }
7128
 
 
7129
 
    for (i = 0; i < getTable()->getShare()->sizeKeys(); i++) {
7130
 
      /* We could get index quickly through internal
7131
 
         index mapping with the index translation table.
7132
 
         The identity of index (match up index name with
7133
 
         that of table->key_info[i]) is already verified in
7134
 
         innobase_get_index().  */
7135
 
      index = innobase_get_index(i);
7136
 
 
7137
 
      if (index == NULL) {
7138
 
        errmsg_printf(ERRMSG_LVL_ERROR, "Table %s contains fewer "
7139
 
            "indexes inside InnoDB than "
7140
 
            "are defined in the MySQL "
7141
 
            ".frm file. Have you mixed up "
7142
 
            ".frm files from different "
7143
 
            "installations? See "
7144
 
            REFMAN
7145
 
            "innodb-troubleshooting.html\n",
7146
 
            ib_table->name);
7147
 
        break;
7148
 
      }
7149
 
 
7150
 
      for (j = 0; j < getTable()->key_info[i].key_parts; j++) {
7151
 
 
7152
 
        if (j + 1 > index->n_uniq) {
7153
 
          errmsg_printf(ERRMSG_LVL_ERROR, 
 
6367
        dict_table_t*   ib_table;
 
6368
        dict_index_t*   index;
 
6369
        ha_rows         rec_per_key;
 
6370
        ib_int64_t      n_rows;
 
6371
        ulong           j;
 
6372
        ulong           i;
 
6373
        char            path[FN_REFLEN];
 
6374
        os_file_stat_t  stat_info;
 
6375
 
 
6376
        /* If we are forcing recovery at a high level, we will suppress
 
6377
        statistics calculation on tables, because that may crash the
 
6378
        server if an index is badly corrupted. */
 
6379
 
 
6380
        if (srv_force_recovery >= SRV_FORCE_NO_IBUF_MERGE) {
 
6381
 
 
6382
                /* We return success (0) instead of HA_ERR_CRASHED,
 
6383
                because we want MySQL to process this query and not
 
6384
                stop, like it would do if it received the error code
 
6385
                HA_ERR_CRASHED. */
 
6386
 
 
6387
                return(0);
 
6388
        }
 
6389
 
 
6390
        /* We do not know if MySQL can call this function before calling
 
6391
        external_lock(). To be safe, update the session of the current table
 
6392
        handle. */
 
6393
 
 
6394
        update_session(ha_session());
 
6395
 
 
6396
        /* In case MySQL calls this in the middle of a SELECT query, release
 
6397
        possible adaptive hash latch to avoid deadlocks of threads */
 
6398
 
 
6399
        prebuilt->trx->op_info = (char*)"returning various info to MySQL";
 
6400
 
 
6401
        trx_search_latch_release_if_reserved(prebuilt->trx);
 
6402
 
 
6403
        ib_table = prebuilt->table;
 
6404
 
 
6405
        if (flag & HA_STATUS_TIME) {
 
6406
                if (innobase_stats_on_metadata) {
 
6407
                        /* In sql_show we call with this flag: update
 
6408
                        then statistics so that they are up-to-date */
 
6409
 
 
6410
                        prebuilt->trx->op_info = "updating table statistics";
 
6411
 
 
6412
                        dict_update_statistics(ib_table);
 
6413
 
 
6414
                        prebuilt->trx->op_info = "returning various info to MySQL";
 
6415
                }
 
6416
 
 
6417
                snprintf(path, sizeof(path), "%s/%s%s",
 
6418
                               drizzle_data_home, ib_table->name, ".dfe");
 
6419
 
 
6420
                internal::unpack_filename(path,path);
 
6421
 
 
6422
                /* Note that we do not know the access time of the table,
 
6423
                nor the CHECK TABLE time, nor the UPDATE or INSERT time. */
 
6424
 
 
6425
                if (os_file_get_status(path,&stat_info)) {
 
6426
                        stats.create_time = (ulong) stat_info.ctime;
 
6427
                }
 
6428
        }
 
6429
 
 
6430
        if (flag & HA_STATUS_VARIABLE) {
 
6431
                n_rows = ib_table->stat_n_rows;
 
6432
 
 
6433
                /* Because we do not protect stat_n_rows by any mutex in a
 
6434
                delete, it is theoretically possible that the value can be
 
6435
                smaller than zero! TODO: fix this race.
 
6436
 
 
6437
                The MySQL optimizer seems to assume in a left join that n_rows
 
6438
                is an accurate estimate if it is zero. Of course, it is not,
 
6439
                since we do not have any locks on the rows yet at this phase.
 
6440
                Since SHOW TABLE STATUS seems to call this function with the
 
6441
                HA_STATUS_TIME flag set, while the left join optimizer does not
 
6442
                set that flag, we add one to a zero value if the flag is not
 
6443
                set. That way SHOW TABLE STATUS will show the best estimate,
 
6444
                while the optimizer never sees the table empty. */
 
6445
 
 
6446
                if (n_rows < 0) {
 
6447
                        n_rows = 0;
 
6448
                }
 
6449
 
 
6450
                if (n_rows == 0 && !(flag & HA_STATUS_TIME)) {
 
6451
                        n_rows++;
 
6452
                }
 
6453
 
 
6454
                /* Fix bug#40386: Not flushing query cache after truncate.
 
6455
                n_rows can not be 0 unless the table is empty, set to 1
 
6456
                instead. The original problem of bug#29507 is actually
 
6457
                fixed in the server code. */
 
6458
                if (session_sql_command(user_session) == SQLCOM_TRUNCATE) {
 
6459
 
 
6460
                        n_rows = 1;
 
6461
 
 
6462
                        /* We need to reset the prebuilt value too, otherwise
 
6463
                        checks for values greater than the last value written
 
6464
                        to the table will fail and the autoinc counter will
 
6465
                        not be updated. This will force write_row() into
 
6466
                        attempting an update of the table's AUTOINC counter. */
 
6467
 
 
6468
                        prebuilt->autoinc_last_value = 0;
 
6469
                }
 
6470
 
 
6471
                stats.records = (ha_rows)n_rows;
 
6472
                stats.deleted = 0;
 
6473
                stats.data_file_length = ((uint64_t)
 
6474
                                ib_table->stat_clustered_index_size)
 
6475
                                        * UNIV_PAGE_SIZE;
 
6476
                stats.index_file_length = ((uint64_t)
 
6477
                                ib_table->stat_sum_of_other_index_sizes)
 
6478
                                        * UNIV_PAGE_SIZE;
 
6479
 
 
6480
                /* Since fsp_get_available_space_in_free_extents() is
 
6481
                acquiring latches inside InnoDB, we do not call it if we
 
6482
                are asked by MySQL to avoid locking. Another reason to
 
6483
                avoid the call is that it uses quite a lot of CPU.
 
6484
                See Bug#38185.
 
6485
                We do not update delete_length if no locking is requested
 
6486
                so the "old" value can remain. delete_length is initialized
 
6487
                to 0 in the ha_statistics' constructor. */
 
6488
                if (!(flag & HA_STATUS_NO_LOCK)) {
 
6489
 
 
6490
                        /* lock the data dictionary to avoid races with
 
6491
                        ibd_file_missing and tablespace_discarded */
 
6492
                        row_mysql_lock_data_dictionary(prebuilt->trx);
 
6493
 
 
6494
                        /* ib_table->space must be an existent tablespace */
 
6495
                        if (!ib_table->ibd_file_missing
 
6496
                            && !ib_table->tablespace_discarded) {
 
6497
 
 
6498
                                stats.delete_length =
 
6499
                                        fsp_get_available_space_in_free_extents(
 
6500
                                                ib_table->space) * 1024;
 
6501
                        } else {
 
6502
 
 
6503
                                Session*        session;
 
6504
 
 
6505
                                session = ha_session();
 
6506
 
 
6507
                                push_warning_printf(
 
6508
                                        session,
 
6509
                                        DRIZZLE_ERROR::WARN_LEVEL_WARN,
 
6510
                                        ER_CANT_GET_STAT,
 
6511
                                        "InnoDB: Trying to get the free "
 
6512
                                        "space for table %s but its "
 
6513
                                        "tablespace has been discarded or "
 
6514
                                        "the .ibd file is missing. Setting "
 
6515
                                        "the free space to zero.",
 
6516
                                        ib_table->name);
 
6517
 
 
6518
                                stats.delete_length = 0;
 
6519
                        }
 
6520
 
 
6521
                        row_mysql_unlock_data_dictionary(prebuilt->trx);
 
6522
                }
 
6523
 
 
6524
                stats.check_time = 0;
 
6525
 
 
6526
                if (stats.records == 0) {
 
6527
                        stats.mean_rec_length = 0;
 
6528
                } else {
 
6529
                        stats.mean_rec_length = (ulong) (stats.data_file_length / stats.records);
 
6530
                }
 
6531
        }
 
6532
 
 
6533
        if (flag & HA_STATUS_CONST) {
 
6534
                index = dict_table_get_first_index(ib_table);
 
6535
 
 
6536
                if (prebuilt->clust_index_was_generated) {
 
6537
                        index = dict_table_get_next_index(index);
 
6538
                }
 
6539
 
 
6540
                for (i = 0; i < table->s->keys; i++) {
 
6541
                        if (index == NULL) {
 
6542
                                errmsg_printf(ERRMSG_LVL_ERROR, "Table %s contains fewer "
 
6543
                                                "indexes inside InnoDB than "
 
6544
                                                "are defined in the MySQL "
 
6545
                                                ".frm file. Have you mixed up "
 
6546
                                                ".frm files from different "
 
6547
                                                "installations? See "
 
6548
                                                REFMAN
 
6549
                                                "innodb-troubleshooting.html\n",
 
6550
                                                ib_table->name);
 
6551
                                break;
 
6552
                        }
 
6553
 
 
6554
                        for (j = 0; j < table->key_info[i].key_parts; j++) {
 
6555
 
 
6556
                                if (j + 1 > index->n_uniq) {
 
6557
                                        errmsg_printf(ERRMSG_LVL_ERROR, 
7154
6558
"Index %s of %s has %lu columns unique inside InnoDB, but MySQL is asking "
7155
6559
"statistics for %lu columns. Have you mixed up .frm files from different "
7156
6560
"installations? "
7157
6561
"See " REFMAN "innodb-troubleshooting.html\n",
7158
 
              index->name,
7159
 
              ib_table->name,
7160
 
              (unsigned long)
7161
 
              index->n_uniq, j + 1);
7162
 
          break;
7163
 
        }
7164
 
 
7165
 
        dict_index_stat_mutex_enter(index);
7166
 
 
7167
 
        if (index->stat_n_diff_key_vals[j + 1] == 0) {
7168
 
 
7169
 
          rec_per_key = stats.records;
7170
 
        } else {
7171
 
          rec_per_key = (ha_rows)(stats.records /
7172
 
           index->stat_n_diff_key_vals[j + 1]);
7173
 
        }
7174
 
 
7175
 
        dict_index_stat_mutex_exit(index);
7176
 
 
7177
 
        /* Since MySQL seems to favor table scans
7178
 
        too much over index searches, we pretend
7179
 
        index selectivity is 2 times better than
7180
 
        our estimate: */
7181
 
 
7182
 
        rec_per_key = rec_per_key / 2;
7183
 
 
7184
 
        if (rec_per_key == 0) {
7185
 
          rec_per_key = 1;
7186
 
        }
7187
 
 
7188
 
        getTable()->key_info[i].rec_per_key[j]=
7189
 
          rec_per_key >= ~(ulong) 0 ? ~(ulong) 0 :
7190
 
          (ulong) rec_per_key;
7191
 
      }
7192
 
    }
7193
 
  }
7194
 
 
7195
 
  if (flag & HA_STATUS_ERRKEY) {
7196
 
    const dict_index_t* err_index;
7197
 
 
7198
 
    ut_a(prebuilt->trx);
7199
 
    ut_a(prebuilt->trx->magic_n == TRX_MAGIC_N);
7200
 
 
7201
 
    err_index = trx_get_error_info(prebuilt->trx);
7202
 
 
7203
 
    if (err_index) {
7204
 
      errkey = (unsigned int)
7205
 
        innobase_get_mysql_key_number_for_index(share, getTable(), ib_table,
7206
 
                                                err_index);
7207
 
    } else {
7208
 
      errkey = (unsigned int) prebuilt->trx->error_key_num;
7209
 
    }
7210
 
  }
7211
 
 
7212
 
  if ((flag & HA_STATUS_AUTO) && getTable()->found_next_number_field) {
7213
 
    stats.auto_increment_value = innobase_peek_autoinc();
7214
 
  }
7215
 
 
7216
 
  prebuilt->trx->op_info = (char*)"";
7217
 
 
7218
 
  return(0);
 
6562
                                                        index->name,
 
6563
                                                        ib_table->name,
 
6564
                                                        (unsigned long)
 
6565
                                                        index->n_uniq, j + 1);
 
6566
                                        break;
 
6567
                                }
 
6568
 
 
6569
                                if (index->stat_n_diff_key_vals[j + 1] == 0) {
 
6570
 
 
6571
                                        rec_per_key = stats.records;
 
6572
                                } else {
 
6573
                                        rec_per_key = (ha_rows)(stats.records /
 
6574
                                         index->stat_n_diff_key_vals[j + 1]);
 
6575
                                }
 
6576
 
 
6577
                                /* Since MySQL seems to favor table scans
 
6578
                                too much over index searches, we pretend
 
6579
                                index selectivity is 2 times better than
 
6580
                                our estimate: */
 
6581
 
 
6582
                                rec_per_key = rec_per_key / 2;
 
6583
 
 
6584
                                if (rec_per_key == 0) {
 
6585
                                        rec_per_key = 1;
 
6586
                                }
 
6587
 
 
6588
                                table->key_info[i].rec_per_key[j]=
 
6589
                                  rec_per_key >= ~(ulong) 0 ? ~(ulong) 0 :
 
6590
                                  (ulong) rec_per_key;
 
6591
                        }
 
6592
 
 
6593
                        index = dict_table_get_next_index(index);
 
6594
                }
 
6595
        }
 
6596
 
 
6597
        if (flag & HA_STATUS_ERRKEY) {
 
6598
                const dict_index_t*     err_index;
 
6599
 
 
6600
                ut_a(prebuilt->trx);
 
6601
                ut_a(prebuilt->trx->magic_n == TRX_MAGIC_N);
 
6602
 
 
6603
                err_index = trx_get_error_info(prebuilt->trx);
 
6604
 
 
6605
                if (err_index) {
 
6606
                        errkey = (unsigned int)
 
6607
                                row_get_mysql_key_number_for_index(err_index);
 
6608
                } else {
 
6609
                        errkey = (unsigned int) prebuilt->trx->error_key_num;
 
6610
                }
 
6611
        }
 
6612
 
 
6613
        if ((flag & HA_STATUS_AUTO) && table->found_next_number_field) {
 
6614
                stats.auto_increment_value = innobase_peek_autoinc();
 
6615
        }
 
6616
 
 
6617
        prebuilt->trx->op_info = (char*)"";
 
6618
 
 
6619
        return(0);
7219
6620
}
7220
6621
 
7221
6622
/**********************************************************************//**
7222
6623
Updates index cardinalities of the table, based on 8 random dives into
7223
6624
each index tree. This does NOT calculate exact statistics on the table.
7224
 
@return returns always 0 (success) */
 
6625
@return returns always 0 (success) */
7225
6626
UNIV_INTERN
7226
6627
int
7227
6628
ha_innobase::analyze(
7228
6629
/*=================*/
7229
 
  Session*)   /*!< in: connection thread handle */
 
6630
        Session*)               /*!< in: connection thread handle */
7230
6631
{
7231
 
  /* Simply call ::info() with all the flags */
7232
 
  info(HA_STATUS_TIME | HA_STATUS_CONST | HA_STATUS_VARIABLE);
 
6632
        /* Simply call ::info() with all the flags */
 
6633
        info(HA_STATUS_TIME | HA_STATUS_CONST | HA_STATUS_VARIABLE);
7233
6634
 
7234
 
  return(0);
 
6635
        return(0);
7235
6636
}
7236
6637
 
7237
6638
/*******************************************************************//**
7238
6639
Tries to check that an InnoDB table is not corrupted. If corruption is
7239
6640
noticed, prints to stderr information about it. In case of corruption
7240
6641
may also assert a failure and crash the server.
7241
 
@return HA_ADMIN_CORRUPT or HA_ADMIN_OK */
 
6642
@return HA_ADMIN_CORRUPT or HA_ADMIN_OK */
7242
6643
UNIV_INTERN
7243
6644
int
7244
6645
ha_innobase::check(
7245
6646
/*===============*/
7246
 
  Session*  session)  /*!< in: user thread handle */
 
6647
        Session*        session)        /*!< in: user thread handle */
7247
6648
{
7248
 
  dict_index_t* index;
7249
 
  ulint         n_rows;
7250
 
  ulint         n_rows_in_table = ULINT_UNDEFINED;
7251
 
  ibool         is_ok           = TRUE;
7252
 
  ulint         old_isolation_level;
7253
 
 
7254
 
  assert(session == getTable()->in_use);
7255
 
  ut_a(prebuilt->trx);
7256
 
  ut_a(prebuilt->trx->magic_n == TRX_MAGIC_N);
7257
 
  ut_a(prebuilt->trx == session_to_trx(session));
7258
 
 
7259
 
  if (prebuilt->mysql_template == NULL) {
7260
 
    /* Build the template; we will use a dummy template
7261
 
    in index scans done in checking */
7262
 
 
7263
 
    build_template(prebuilt, NULL, getTable(), ROW_MYSQL_WHOLE_ROW);
7264
 
  }
7265
 
 
7266
 
  if (prebuilt->table->ibd_file_missing) {
7267
 
        errmsg_printf(ERRMSG_LVL_ERROR, "InnoDB: Error:\n"
7268
 
                    "InnoDB: MySQL is trying to use a table handle"
7269
 
                    " but the .ibd file for\n"
7270
 
                    "InnoDB: table %s does not exist.\n"
7271
 
                    "InnoDB: Have you deleted the .ibd file"
7272
 
                    " from the database directory under\n"
7273
 
                    "InnoDB: the MySQL datadir, or have you"
7274
 
                    " used DISCARD TABLESPACE?\n"
7275
 
                    "InnoDB: Please refer to\n"
7276
 
                    "InnoDB: " REFMAN "innodb-troubleshooting.html\n"
7277
 
                    "InnoDB: how you can resolve the problem.\n",
7278
 
                    prebuilt->table->name);
7279
 
    return(HA_ADMIN_CORRUPT);
7280
 
  }
7281
 
 
7282
 
  prebuilt->trx->op_info = "checking table";
7283
 
 
7284
 
  old_isolation_level = prebuilt->trx->isolation_level;
7285
 
 
7286
 
  /* We must run the index record counts at an isolation level
7287
 
     >= READ COMMITTED, because a dirty read can see a wrong number
7288
 
     of records in some index; to play safe, we use always
7289
 
     REPEATABLE READ here */
7290
 
 
7291
 
  prebuilt->trx->isolation_level = TRX_ISO_REPEATABLE_READ;
7292
 
 
7293
 
  /* Enlarge the fatal lock wait timeout during CHECK TABLE. */
7294
 
  mutex_enter(&kernel_mutex);
7295
 
  srv_fatal_semaphore_wait_threshold += 7200; /* 2 hours */
7296
 
  mutex_exit(&kernel_mutex);
7297
 
 
7298
 
  for (index = dict_table_get_first_index(prebuilt->table);
7299
 
       index != NULL;
7300
 
       index = dict_table_get_next_index(index)) {
7301
 
#if 0
7302
 
    fputs("Validating index ", stderr);
7303
 
    ut_print_name(stderr, trx, FALSE, index->name);
7304
 
    putc('\n', stderr);
7305
 
#endif
7306
 
 
7307
 
    if (!btr_validate_index(index, prebuilt->trx)) {
7308
 
      is_ok = FALSE;
7309
 
      push_warning_printf(session, DRIZZLE_ERROR::WARN_LEVEL_WARN,
7310
 
                          ER_NOT_KEYFILE,
7311
 
                          "InnoDB: The B-tree of"
7312
 
                          " index '%-.200s' is corrupted.",
7313
 
                          index->name);
7314
 
      continue;
7315
 
    }
7316
 
 
7317
 
    /* Instead of invoking change_active_index(), set up
7318
 
       a dummy template for non-locking reads, disabling
7319
 
       access to the clustered index. */
7320
 
    prebuilt->index = index;
7321
 
 
7322
 
    prebuilt->index_usable = row_merge_is_index_usable(
7323
 
                        prebuilt->trx, prebuilt->index);
7324
 
 
7325
 
    if (UNIV_UNLIKELY(!prebuilt->index_usable)) {
7326
 
      push_warning_printf(session, DRIZZLE_ERROR::WARN_LEVEL_WARN,
7327
 
                          HA_ERR_TABLE_DEF_CHANGED,
7328
 
                          "InnoDB: Insufficient history for"
7329
 
                          " index '%-.200s'",
7330
 
                          index->name);
7331
 
      continue;
7332
 
    }
7333
 
 
7334
 
    prebuilt->sql_stat_start = TRUE;
7335
 
    prebuilt->template_type = ROW_MYSQL_DUMMY_TEMPLATE;
7336
 
    prebuilt->n_template = 0;
7337
 
    prebuilt->need_to_access_clustered = FALSE;
7338
 
 
7339
 
    dtuple_set_n_fields(prebuilt->search_tuple, 0);
7340
 
 
7341
 
    prebuilt->select_lock_type = LOCK_NONE;
7342
 
 
7343
 
    if (!row_check_index_for_mysql(prebuilt, index, &n_rows)) {
7344
 
      push_warning_printf(session, DRIZZLE_ERROR::WARN_LEVEL_WARN,
7345
 
                          ER_NOT_KEYFILE,
7346
 
                          "InnoDB: The B-tree of"
7347
 
                          " index '%-.200s' is corrupted.",
7348
 
                          index->name);
7349
 
      is_ok = FALSE;
7350
 
    }
7351
 
 
7352
 
    if (user_session->getKilled()) {
7353
 
      break;
7354
 
    }
7355
 
 
7356
 
#if 0
7357
 
    fprintf(stderr, "%lu entries in index %s\n", n_rows,
7358
 
            index->name);
7359
 
#endif
7360
 
 
7361
 
    if (index == dict_table_get_first_index(prebuilt->table)) {
7362
 
      n_rows_in_table = n_rows;
7363
 
    } else if (n_rows != n_rows_in_table) {
7364
 
      push_warning_printf(session, DRIZZLE_ERROR::WARN_LEVEL_WARN,
7365
 
                          ER_NOT_KEYFILE,
7366
 
                          "InnoDB: Index '%-.200s'"
7367
 
                          " contains %lu entries,"
7368
 
                          " should be %lu.",
7369
 
                          index->name,
7370
 
                          (ulong) n_rows,
7371
 
                          (ulong) n_rows_in_table);
7372
 
      is_ok = FALSE;
7373
 
    }
7374
 
  }
7375
 
 
7376
 
  /* Restore the original isolation level */
7377
 
  prebuilt->trx->isolation_level = old_isolation_level;
7378
 
 
7379
 
  /* We validate also the whole adaptive hash index for all tables
7380
 
     at every CHECK TABLE */
7381
 
 
7382
 
  if (!btr_search_validate()) {
7383
 
    push_warning(session, DRIZZLE_ERROR::WARN_LEVEL_WARN,
7384
 
                 ER_NOT_KEYFILE,
7385
 
                 "InnoDB: The adaptive hash index is corrupted.");
7386
 
    is_ok = FALSE;
7387
 
  }
7388
 
 
7389
 
  /* Restore the fatal lock wait timeout after CHECK TABLE. */
7390
 
  mutex_enter(&kernel_mutex);
7391
 
  srv_fatal_semaphore_wait_threshold -= 7200; /* 2 hours */
7392
 
  mutex_exit(&kernel_mutex);
7393
 
 
7394
 
  prebuilt->trx->op_info = "";
7395
 
  if (user_session->getKilled()) {
7396
 
    my_error(ER_QUERY_INTERRUPTED, MYF(0));
7397
 
  }
7398
 
 
7399
 
  return(is_ok ? HA_ADMIN_OK : HA_ADMIN_CORRUPT);
 
6649
        ulint           ret;
 
6650
 
 
6651
        assert(session == ha_session());
 
6652
        ut_a(prebuilt->trx);
 
6653
        ut_a(prebuilt->trx->magic_n == TRX_MAGIC_N);
 
6654
        ut_a(prebuilt->trx == session_to_trx(session));
 
6655
 
 
6656
        if (prebuilt->mysql_template == NULL) {
 
6657
                /* Build the template; we will use a dummy template
 
6658
                in index scans done in checking */
 
6659
 
 
6660
                build_template(prebuilt, NULL, table, ROW_MYSQL_WHOLE_ROW);
 
6661
        }
 
6662
 
 
6663
        ret = row_check_table_for_mysql(prebuilt);
 
6664
 
 
6665
        if (ret == DB_SUCCESS) {
 
6666
                return(HA_ADMIN_OK);
 
6667
        }
 
6668
 
 
6669
        return(HA_ADMIN_CORRUPT);
7400
6670
}
7401
6671
 
7402
6672
/*************************************************************//**
7403
6673
Adds information about free space in the InnoDB tablespace to a table comment
7404
6674
which is printed out when a user calls SHOW TABLE STATUS. Adds also info on
7405
6675
foreign keys.
7406
 
@return table comment + InnoDB free space + info on foreign keys */
 
6676
@return table comment + InnoDB free space + info on foreign keys */
7407
6677
UNIV_INTERN
7408
6678
char*
7409
6679
ha_innobase::update_table_comment(
7410
6680
/*==============================*/
7411
 
  const char* comment)/*!< in: table comment defined by user */
 
6681
        const char*     comment)/*!< in: table comment defined by user */
7412
6682
{
7413
 
  uint  length = (uint) strlen(comment);
7414
 
  char* str;
7415
 
  long  flen;
7416
 
 
7417
 
  /* We do not know if MySQL can call this function before calling
7418
 
  external_lock(). To be safe, update the session of the current table
7419
 
  handle. */
7420
 
 
7421
 
  if (length > 64000 - 3) {
7422
 
    return((char*)comment); /* string too long */
7423
 
  }
7424
 
 
7425
 
  update_session(getTable()->in_use);
7426
 
 
7427
 
  prebuilt->trx->op_info = (char*)"returning table comment";
7428
 
 
7429
 
  /* In case MySQL calls this in the middle of a SELECT query, release
7430
 
  possible adaptive hash latch to avoid deadlocks of threads */
7431
 
 
7432
 
  trx_search_latch_release_if_reserved(prebuilt->trx);
7433
 
  str = NULL;
7434
 
 
7435
 
  /* output the data to a temporary file */
7436
 
 
7437
 
  mutex_enter(&srv_dict_tmpfile_mutex);
7438
 
  rewind(srv_dict_tmpfile);
7439
 
 
7440
 
  fprintf(srv_dict_tmpfile, "InnoDB free: %llu kB",
7441
 
    fsp_get_available_space_in_free_extents(
7442
 
      prebuilt->table->space));
7443
 
 
7444
 
  dict_print_info_on_foreign_keys(FALSE, srv_dict_tmpfile,
7445
 
        prebuilt->trx, prebuilt->table);
7446
 
  flen = ftell(srv_dict_tmpfile);
7447
 
  if (flen < 0) {
7448
 
    flen = 0;
7449
 
  } else if (length + flen + 3 > 64000) {
7450
 
    flen = 64000 - 3 - length;
7451
 
  }
7452
 
 
7453
 
  /* allocate buffer for the full string, and
7454
 
  read the contents of the temporary file */
7455
 
 
7456
 
  str = (char*) malloc(length + flen + 3);
7457
 
 
7458
 
  if (str) {
7459
 
    char* pos = str + length;
7460
 
    if (length) {
7461
 
      memcpy(str, comment, length);
7462
 
      *pos++ = ';';
7463
 
      *pos++ = ' ';
7464
 
    }
7465
 
    rewind(srv_dict_tmpfile);
7466
 
    flen = (uint) fread(pos, 1, flen, srv_dict_tmpfile);
7467
 
    pos[flen] = 0;
7468
 
  }
7469
 
 
7470
 
  mutex_exit(&srv_dict_tmpfile_mutex);
7471
 
 
7472
 
  prebuilt->trx->op_info = (char*)"";
7473
 
 
7474
 
  return(str ? str : (char*) comment);
 
6683
        uint    length = (uint) strlen(comment);
 
6684
        char*   str;
 
6685
        long    flen;
 
6686
 
 
6687
        /* We do not know if MySQL can call this function before calling
 
6688
        external_lock(). To be safe, update the session of the current table
 
6689
        handle. */
 
6690
 
 
6691
        if (length > 64000 - 3) {
 
6692
                return((char*)comment); /* string too long */
 
6693
        }
 
6694
 
 
6695
        update_session(ha_session());
 
6696
 
 
6697
        prebuilt->trx->op_info = (char*)"returning table comment";
 
6698
 
 
6699
        /* In case MySQL calls this in the middle of a SELECT query, release
 
6700
        possible adaptive hash latch to avoid deadlocks of threads */
 
6701
 
 
6702
        trx_search_latch_release_if_reserved(prebuilt->trx);
 
6703
        str = NULL;
 
6704
 
 
6705
        /* output the data to a temporary file */
 
6706
 
 
6707
        mutex_enter(&srv_dict_tmpfile_mutex);
 
6708
        rewind(srv_dict_tmpfile);
 
6709
 
 
6710
        fprintf(srv_dict_tmpfile, "InnoDB free: %llu kB",
 
6711
                fsp_get_available_space_in_free_extents(
 
6712
                        prebuilt->table->space));
 
6713
 
 
6714
        dict_print_info_on_foreign_keys(FALSE, srv_dict_tmpfile,
 
6715
                                prebuilt->trx, prebuilt->table);
 
6716
        flen = ftell(srv_dict_tmpfile);
 
6717
        if (flen < 0) {
 
6718
                flen = 0;
 
6719
        } else if (length + flen + 3 > 64000) {
 
6720
                flen = 64000 - 3 - length;
 
6721
        }
 
6722
 
 
6723
        /* allocate buffer for the full string, and
 
6724
        read the contents of the temporary file */
 
6725
 
 
6726
        str = (char*) malloc(length + flen + 3);
 
6727
 
 
6728
        if (str) {
 
6729
                char* pos       = str + length;
 
6730
                if (length) {
 
6731
                        memcpy(str, comment, length);
 
6732
                        *pos++ = ';';
 
6733
                        *pos++ = ' ';
 
6734
                }
 
6735
                rewind(srv_dict_tmpfile);
 
6736
                flen = (uint) fread(pos, 1, flen, srv_dict_tmpfile);
 
6737
                pos[flen] = 0;
 
6738
        }
 
6739
 
 
6740
        mutex_exit(&srv_dict_tmpfile_mutex);
 
6741
 
 
6742
        prebuilt->trx->op_info = (char*)"";
 
6743
 
 
6744
        return(str ? str : (char*) comment);
7475
6745
}
7476
6746
 
7477
6747
/*******************************************************************//**
7484
6754
ha_innobase::get_foreign_key_create_info(void)
7485
6755
/*==========================================*/
7486
6756
{
7487
 
  char* str = 0;
7488
 
  long  flen;
7489
 
 
7490
 
  ut_a(prebuilt != NULL);
7491
 
 
7492
 
  /* We do not know if MySQL can call this function before calling
7493
 
  external_lock(). To be safe, update the session of the current table
7494
 
  handle. */
7495
 
 
7496
 
  update_session(getTable()->in_use);
7497
 
 
7498
 
  prebuilt->trx->op_info = (char*)"getting info on foreign keys";
7499
 
 
7500
 
  /* In case MySQL calls this in the middle of a SELECT query,
7501
 
  release possible adaptive hash latch to avoid
7502
 
  deadlocks of threads */
7503
 
 
7504
 
  trx_search_latch_release_if_reserved(prebuilt->trx);
7505
 
 
7506
 
  mutex_enter(&srv_dict_tmpfile_mutex);
7507
 
  rewind(srv_dict_tmpfile);
7508
 
 
7509
 
  /* output the data to a temporary file */
7510
 
  dict_print_info_on_foreign_keys(TRUE, srv_dict_tmpfile,
7511
 
        prebuilt->trx, prebuilt->table);
7512
 
  prebuilt->trx->op_info = (char*)"";
7513
 
 
7514
 
  flen = ftell(srv_dict_tmpfile);
7515
 
  if (flen < 0) {
7516
 
    flen = 0;
7517
 
  } else if (flen > 64000 - 1) {
7518
 
    flen = 64000 - 1;
7519
 
  }
7520
 
 
7521
 
  /* allocate buffer for the string, and
7522
 
  read the contents of the temporary file */
7523
 
 
7524
 
  str = (char*) malloc(flen + 1);
7525
 
 
7526
 
  if (str) {
7527
 
    rewind(srv_dict_tmpfile);
7528
 
    flen = (uint) fread(str, 1, flen, srv_dict_tmpfile);
7529
 
    str[flen] = 0;
7530
 
  }
7531
 
 
7532
 
  mutex_exit(&srv_dict_tmpfile_mutex);
7533
 
 
7534
 
  return(str);
 
6757
        char*   str     = 0;
 
6758
        long    flen;
 
6759
 
 
6760
        ut_a(prebuilt != NULL);
 
6761
 
 
6762
        /* We do not know if MySQL can call this function before calling
 
6763
        external_lock(). To be safe, update the session of the current table
 
6764
        handle. */
 
6765
 
 
6766
        update_session(ha_session());
 
6767
 
 
6768
        prebuilt->trx->op_info = (char*)"getting info on foreign keys";
 
6769
 
 
6770
        /* In case MySQL calls this in the middle of a SELECT query,
 
6771
        release possible adaptive hash latch to avoid
 
6772
        deadlocks of threads */
 
6773
 
 
6774
        trx_search_latch_release_if_reserved(prebuilt->trx);
 
6775
 
 
6776
        mutex_enter(&srv_dict_tmpfile_mutex);
 
6777
        rewind(srv_dict_tmpfile);
 
6778
 
 
6779
        /* output the data to a temporary file */
 
6780
        dict_print_info_on_foreign_keys(TRUE, srv_dict_tmpfile,
 
6781
                                prebuilt->trx, prebuilt->table);
 
6782
        prebuilt->trx->op_info = (char*)"";
 
6783
 
 
6784
        flen = ftell(srv_dict_tmpfile);
 
6785
        if (flen < 0) {
 
6786
                flen = 0;
 
6787
        } else if (flen > 64000 - 1) {
 
6788
                flen = 64000 - 1;
 
6789
        }
 
6790
 
 
6791
        /* allocate buffer for the string, and
 
6792
        read the contents of the temporary file */
 
6793
 
 
6794
        str = (char*) malloc(flen + 1);
 
6795
 
 
6796
        if (str) {
 
6797
                rewind(srv_dict_tmpfile);
 
6798
                flen = (uint) fread(str, 1, flen, srv_dict_tmpfile);
 
6799
                str[flen] = 0;
 
6800
        }
 
6801
 
 
6802
        mutex_exit(&srv_dict_tmpfile_mutex);
 
6803
 
 
6804
        return(str);
7535
6805
}
7536
6806
 
7537
6807
 
7538
6808
UNIV_INTERN
7539
6809
int
7540
 
ha_innobase::get_foreign_key_list(Session *session, List<ForeignKeyInfo> *f_key_list)
 
6810
ha_innobase::get_foreign_key_list(Session *session, List<FOREIGN_KEY_INFO> *f_key_list)
7541
6811
{
7542
6812
  dict_foreign_t* foreign;
7543
6813
 
7544
6814
  ut_a(prebuilt != NULL);
7545
 
  update_session(getTable()->in_use);
 
6815
  update_session(ha_session());
7546
6816
  prebuilt->trx->op_info = (char*)"getting list of foreign keys";
7547
6817
  trx_search_latch_release_if_reserved(prebuilt->trx);
7548
6818
  mutex_enter(&(dict_sys->mutex));
7549
6819
  foreign = UT_LIST_GET_FIRST(prebuilt->table->foreign_list);
7550
6820
 
7551
6821
  while (foreign != NULL) {
7552
 
 
7553
 
    uint i;
7554
 
    LEX_STRING *name = 0;
7555
 
    uint ulen;
7556
 
    char uname[NAME_LEN + 1];           /* Unencoded name */
7557
 
    char db_name[NAME_LEN + 1];
7558
 
    const char *tmp_buff;
7559
 
 
7560
 
    /** Foreign id **/
7561
 
    tmp_buff = foreign->id;
7562
 
    i = 0;
7563
 
    while (tmp_buff[i] != '/')
7564
 
      i++;
7565
 
    tmp_buff += i + 1;
7566
 
    LEX_STRING *tmp_foreign_id = session->make_lex_string(NULL, tmp_buff, strlen(tmp_buff), true);
7567
 
 
7568
 
    /* Database name */
7569
 
    tmp_buff = foreign->referenced_table_name;
7570
 
 
7571
 
    i= 0;
7572
 
    while (tmp_buff[i] != '/')
7573
 
    {
7574
 
      db_name[i]= tmp_buff[i];
7575
 
      i++;
7576
 
    }
7577
 
    db_name[i] = 0;
7578
 
    ulen= TableIdentifier::filename_to_tablename(db_name, uname, sizeof(uname));
7579
 
    LEX_STRING *tmp_referenced_db = session->make_lex_string(NULL, uname, ulen, true);
7580
 
 
7581
 
    /* Table name */
7582
 
    tmp_buff += i + 1;
7583
 
    ulen= TableIdentifier::filename_to_tablename(tmp_buff, uname, sizeof(uname));
7584
 
    LEX_STRING *tmp_referenced_table = session->make_lex_string(NULL, uname, ulen, true);
7585
 
 
7586
 
    /** Foreign Fields **/
7587
 
    List<LEX_STRING> tmp_foreign_fields;
7588
 
    List<LEX_STRING> tmp_referenced_fields;
7589
 
    for (i= 0;;) {
7590
 
      tmp_buff= foreign->foreign_col_names[i];
7591
 
      name = session->make_lex_string(name, tmp_buff, strlen(tmp_buff), true);
7592
 
      tmp_foreign_fields.push_back(name);
7593
 
      tmp_buff= foreign->referenced_col_names[i];
7594
 
      name = session->make_lex_string(name, tmp_buff, strlen(tmp_buff), true);
7595
 
      tmp_referenced_fields.push_back(name);
7596
 
      if (++i >= foreign->n_fields)
7597
 
        break;
7598
 
    }
7599
 
 
7600
 
    ulong length;
7601
 
    if (foreign->type & DICT_FOREIGN_ON_DELETE_CASCADE)
7602
 
    {
7603
 
      length=7;
7604
 
      tmp_buff= "CASCADE";
7605
 
    }
7606
 
    else if (foreign->type & DICT_FOREIGN_ON_DELETE_SET_NULL)
7607
 
    {
7608
 
      length=8;
7609
 
      tmp_buff= "SET NULL";
7610
 
    }
7611
 
    else if (foreign->type & DICT_FOREIGN_ON_DELETE_NO_ACTION)
7612
 
    {
7613
 
      length=9;
7614
 
      tmp_buff= "NO ACTION";
7615
 
    }
7616
 
    else
7617
 
    {
7618
 
      length=8;
7619
 
      tmp_buff= "RESTRICT";
7620
 
    }
7621
 
    LEX_STRING *tmp_delete_method = session->make_lex_string(NULL, tmp_buff, length, true);
7622
 
 
7623
 
 
7624
 
    if (foreign->type & DICT_FOREIGN_ON_UPDATE_CASCADE)
7625
 
    {
7626
 
      length=7;
7627
 
      tmp_buff= "CASCADE";
7628
 
    }
7629
 
    else if (foreign->type & DICT_FOREIGN_ON_UPDATE_SET_NULL)
7630
 
    {
7631
 
      length=8;
7632
 
      tmp_buff= "SET NULL";
7633
 
    }
7634
 
    else if (foreign->type & DICT_FOREIGN_ON_UPDATE_NO_ACTION)
7635
 
    {
7636
 
      length=9;
7637
 
      tmp_buff= "NO ACTION";
7638
 
    }
7639
 
    else
7640
 
    {
7641
 
      length=8;
7642
 
      tmp_buff= "RESTRICT";
7643
 
    }
7644
 
    LEX_STRING *tmp_update_method = session->make_lex_string(NULL, tmp_buff, length, true);
7645
 
 
7646
 
    LEX_STRING *tmp_referenced_key_name = NULL;
7647
 
 
7648
 
    if (foreign->referenced_index &&
7649
 
        foreign->referenced_index->name)
7650
 
    {
7651
 
      tmp_referenced_key_name = session->make_lex_string(NULL,
7652
 
                                                         foreign->referenced_index->name, strlen(foreign->referenced_index->name), true);
7653
 
    }
7654
 
 
7655
 
    ForeignKeyInfo f_key_info(
7656
 
                              tmp_foreign_id, tmp_referenced_db, tmp_referenced_table,
7657
 
                              tmp_update_method, tmp_delete_method, tmp_referenced_key_name,
7658
 
                              tmp_foreign_fields, tmp_referenced_fields);
7659
 
 
7660
 
    ForeignKeyInfo *pf_key_info = (ForeignKeyInfo *)
7661
 
      session->memdup(&f_key_info, sizeof(ForeignKeyInfo));
7662
 
    f_key_list->push_back(pf_key_info);
7663
 
    foreign = UT_LIST_GET_NEXT(foreign_list, foreign);
 
6822
          uint i;
 
6823
          FOREIGN_KEY_INFO f_key_info;
 
6824
          LEX_STRING *name= 0;
 
6825
          uint ulen;
 
6826
          char uname[NAME_LEN+1];           /* Unencoded name */
 
6827
          char db_name[NAME_LEN+1];
 
6828
          const char *tmp_buff;
 
6829
 
 
6830
          tmp_buff= foreign->id;
 
6831
          i= 0;
 
6832
          while (tmp_buff[i] != '/')
 
6833
                  i++;
 
6834
          tmp_buff+= i + 1;
 
6835
          f_key_info.forein_id = session->make_lex_string(NULL, tmp_buff, strlen(tmp_buff), true);
 
6836
          tmp_buff= foreign->referenced_table_name;
 
6837
 
 
6838
          /* Database name */
 
6839
          i= 0;
 
6840
          while (tmp_buff[i] != '/')
 
6841
          {
 
6842
            db_name[i]= tmp_buff[i];
 
6843
            i++;
 
6844
          }
 
6845
          db_name[i]= 0;
 
6846
          ulen= filename_to_tablename(db_name, uname, sizeof(uname));
 
6847
          f_key_info.referenced_db = session->make_lex_string(NULL, uname, ulen, true);
 
6848
 
 
6849
          /* Table name */
 
6850
          tmp_buff+= i + 1;
 
6851
          ulen= filename_to_tablename(tmp_buff, uname, sizeof(uname));
 
6852
          f_key_info.referenced_table = session->make_lex_string(NULL, uname, ulen, true);
 
6853
 
 
6854
          for (i= 0;;) {
 
6855
                  tmp_buff= foreign->foreign_col_names[i];
 
6856
                  name = session->make_lex_string(name, tmp_buff, strlen(tmp_buff), true);
 
6857
                  f_key_info.foreign_fields.push_back(name);
 
6858
                  tmp_buff= foreign->referenced_col_names[i];
 
6859
                  name = session->make_lex_string(name, tmp_buff, strlen(tmp_buff), true);
 
6860
                  f_key_info.referenced_fields.push_back(name);
 
6861
                  if (++i >= foreign->n_fields)
 
6862
                          break;
 
6863
          }
 
6864
 
 
6865
          ulong length;
 
6866
          if (foreign->type & DICT_FOREIGN_ON_DELETE_CASCADE)
 
6867
          {
 
6868
            length=7;
 
6869
            tmp_buff= "CASCADE";
 
6870
          }
 
6871
          else if (foreign->type & DICT_FOREIGN_ON_DELETE_SET_NULL)
 
6872
          {
 
6873
            length=8;
 
6874
            tmp_buff= "SET NULL";
 
6875
          }
 
6876
          else if (foreign->type & DICT_FOREIGN_ON_DELETE_NO_ACTION)
 
6877
          {
 
6878
            length=9;
 
6879
            tmp_buff= "NO ACTION";
 
6880
          }
 
6881
          else
 
6882
          {
 
6883
            length=8;
 
6884
            tmp_buff= "RESTRICT";
 
6885
          }
 
6886
          f_key_info.delete_method = session->make_lex_string(
 
6887
                  f_key_info.delete_method, tmp_buff, length, true);
 
6888
 
 
6889
 
 
6890
          if (foreign->type & DICT_FOREIGN_ON_UPDATE_CASCADE)
 
6891
          {
 
6892
            length=7;
 
6893
            tmp_buff= "CASCADE";
 
6894
          }
 
6895
          else if (foreign->type & DICT_FOREIGN_ON_UPDATE_SET_NULL)
 
6896
          {
 
6897
            length=8;
 
6898
            tmp_buff= "SET NULL";
 
6899
          }
 
6900
          else if (foreign->type & DICT_FOREIGN_ON_UPDATE_NO_ACTION)
 
6901
          {
 
6902
            length=9;
 
6903
            tmp_buff= "NO ACTION";
 
6904
          }
 
6905
          else
 
6906
          {
 
6907
            length=8;
 
6908
            tmp_buff= "RESTRICT";
 
6909
          }
 
6910
          f_key_info.update_method = session->make_lex_string(
 
6911
                  f_key_info.update_method, tmp_buff, length, true);
 
6912
          if (foreign->referenced_index &&
 
6913
              foreign->referenced_index->name)
 
6914
          {
 
6915
            f_key_info.referenced_key_name = session->make_lex_string(
 
6916
                    f_key_info.referenced_key_name,
 
6917
                    foreign->referenced_index->name,
 
6918
                    strlen(foreign->referenced_index->name), true);
 
6919
          }
 
6920
          else
 
6921
            f_key_info.referenced_key_name= 0;
 
6922
 
 
6923
          FOREIGN_KEY_INFO *pf_key_info = (FOREIGN_KEY_INFO *)
 
6924
                  session_memdup(session, &f_key_info, sizeof(FOREIGN_KEY_INFO));
 
6925
          f_key_list->push_back(pf_key_info);
 
6926
          foreign = UT_LIST_GET_NEXT(foreign_list, foreign);
7664
6927
  }
7665
6928
  mutex_exit(&(dict_sys->mutex));
7666
6929
  prebuilt->trx->op_info = (char*)"";
7672
6935
Checks if ALTER TABLE may change the storage engine of the table.
7673
6936
Changing storage engines is not allowed for tables for which there
7674
6937
are foreign key constraints (parent or child tables).
7675
 
@return TRUE if can switch engines */
 
6938
@return TRUE if can switch engines */
7676
6939
UNIV_INTERN
7677
6940
bool
7678
6941
ha_innobase::can_switch_engines(void)
7679
6942
/*=================================*/
7680
6943
{
7681
 
  bool  can_switch;
7682
 
 
7683
 
  ut_a(prebuilt->trx == session_to_trx(getTable()->in_use));
7684
 
 
7685
 
  prebuilt->trx->op_info =
7686
 
      "determining if there are foreign key constraints";
7687
 
  row_mysql_lock_data_dictionary(prebuilt->trx);
7688
 
 
7689
 
  can_switch = !UT_LIST_GET_FIRST(prebuilt->table->referenced_list)
7690
 
      && !UT_LIST_GET_FIRST(prebuilt->table->foreign_list);
7691
 
 
7692
 
  row_mysql_unlock_data_dictionary(prebuilt->trx);
7693
 
  prebuilt->trx->op_info = "";
7694
 
 
7695
 
  return(can_switch);
 
6944
        bool    can_switch;
 
6945
 
 
6946
        ut_a(prebuilt->trx == session_to_trx(ha_session()));
 
6947
 
 
6948
        prebuilt->trx->op_info =
 
6949
                        "determining if there are foreign key constraints";
 
6950
        row_mysql_lock_data_dictionary(prebuilt->trx);
 
6951
 
 
6952
        can_switch = !UT_LIST_GET_FIRST(prebuilt->table->referenced_list)
 
6953
                        && !UT_LIST_GET_FIRST(prebuilt->table->foreign_list);
 
6954
 
 
6955
        row_mysql_unlock_data_dictionary(prebuilt->trx);
 
6956
        prebuilt->trx->op_info = "";
 
6957
 
 
6958
        return(can_switch);
7696
6959
}
7697
6960
 
7698
6961
/*******************************************************************//**
7700
6963
a REPLACE is either equivalent to an INSERT, or DELETE(s) + INSERT. Only a
7701
6964
delete is then allowed internally to resolve a duplicate key conflict in
7702
6965
REPLACE, not an update.
7703
 
@return > 0 if referenced by a FOREIGN KEY */
 
6966
@return > 0 if referenced by a FOREIGN KEY */
7704
6967
UNIV_INTERN
7705
6968
uint
7706
6969
ha_innobase::referenced_by_foreign_key(void)
7707
6970
/*========================================*/
7708
6971
{
7709
 
  if (dict_table_is_referenced_by_foreign_key(prebuilt->table)) {
7710
 
 
7711
 
    return(1);
7712
 
  }
7713
 
 
7714
 
  return(0);
 
6972
        if (dict_table_is_referenced_by_foreign_key(prebuilt->table)) {
 
6973
 
 
6974
                return(1);
 
6975
        }
 
6976
 
 
6977
        return(0);
7715
6978
}
7716
6979
 
7717
6980
/*******************************************************************//**
7721
6984
void
7722
6985
ha_innobase::free_foreign_key_create_info(
7723
6986
/*======================================*/
7724
 
  char* str)  /*!< in, own: create info string to free */
 
6987
        char*   str)    /*!< in, own: create info string to free */
7725
6988
{
7726
 
  if (str) {
7727
 
    free(str);
7728
 
  }
 
6989
        if (str) {
 
6990
                free(str);
 
6991
        }
7729
6992
}
7730
6993
 
7731
6994
/*******************************************************************//**
7732
6995
Tells something additional to the Cursor about how to do things.
7733
 
@return 0 or error number */
 
6996
@return 0 or error number */
7734
6997
UNIV_INTERN
7735
6998
int
7736
6999
ha_innobase::extra(
7737
7000
/*===============*/
7738
 
  enum ha_extra_function operation)
7739
 
         /*!< in: HA_EXTRA_FLUSH or some other flag */
 
7001
        enum ha_extra_function operation)
 
7002
                           /*!< in: HA_EXTRA_FLUSH or some other flag */
7740
7003
{
7741
 
  /* Warning: since it is not sure that MySQL calls external_lock
7742
 
  before calling this function, the trx field in prebuilt can be
7743
 
  obsolete! */
7744
 
 
7745
 
  switch (operation) {
7746
 
    case HA_EXTRA_FLUSH:
7747
 
      if (prebuilt->blob_heap) {
7748
 
        row_mysql_prebuilt_free_blob_heap(prebuilt);
7749
 
      }
7750
 
      break;
7751
 
    case HA_EXTRA_RESET_STATE:
7752
 
      reset_template(prebuilt);
7753
 
      break;
7754
 
    case HA_EXTRA_NO_KEYREAD:
7755
 
      prebuilt->read_just_key = 0;
7756
 
      break;
7757
 
    case HA_EXTRA_KEYREAD:
7758
 
      prebuilt->read_just_key = 1;
7759
 
      break;
7760
 
    case HA_EXTRA_KEYREAD_PRESERVE_FIELDS:
7761
 
      prebuilt->keep_other_fields_on_keyread = 1;
7762
 
      break;
7763
 
 
7764
 
      /* IMPORTANT: prebuilt->trx can be obsolete in
7765
 
      this method, because it is not sure that MySQL
7766
 
      calls external_lock before this method with the
7767
 
      parameters below.  We must not invoke update_session()
7768
 
      either, because the calling threads may change.
7769
 
      CAREFUL HERE, OR MEMORY CORRUPTION MAY OCCUR! */
7770
 
    case HA_EXTRA_IGNORE_DUP_KEY:
7771
 
      session_to_trx(getTable()->in_use)->duplicates |= TRX_DUP_IGNORE;
7772
 
      break;
7773
 
    case HA_EXTRA_WRITE_CAN_REPLACE:
7774
 
      session_to_trx(getTable()->in_use)->duplicates |= TRX_DUP_REPLACE;
7775
 
      break;
7776
 
    case HA_EXTRA_WRITE_CANNOT_REPLACE:
7777
 
      session_to_trx(getTable()->in_use)->duplicates &= ~TRX_DUP_REPLACE;
7778
 
      break;
7779
 
    case HA_EXTRA_NO_IGNORE_DUP_KEY:
7780
 
      session_to_trx(getTable()->in_use)->duplicates &=
7781
 
        ~(TRX_DUP_IGNORE | TRX_DUP_REPLACE);
7782
 
      break;
7783
 
    default:/* Do nothing */
7784
 
      ;
7785
 
  }
7786
 
 
7787
 
  return(0);
 
7004
        /* Warning: since it is not sure that MySQL calls external_lock
 
7005
        before calling this function, the trx field in prebuilt can be
 
7006
        obsolete! */
 
7007
 
 
7008
        switch (operation) {
 
7009
                case HA_EXTRA_FLUSH:
 
7010
                        if (prebuilt->blob_heap) {
 
7011
                                row_mysql_prebuilt_free_blob_heap(prebuilt);
 
7012
                        }
 
7013
                        break;
 
7014
                case HA_EXTRA_RESET_STATE:
 
7015
                        reset_template(prebuilt);
 
7016
                        break;
 
7017
                case HA_EXTRA_NO_KEYREAD:
 
7018
                        prebuilt->read_just_key = 0;
 
7019
                        break;
 
7020
                case HA_EXTRA_KEYREAD:
 
7021
                        prebuilt->read_just_key = 1;
 
7022
                        break;
 
7023
                case HA_EXTRA_KEYREAD_PRESERVE_FIELDS:
 
7024
                        prebuilt->keep_other_fields_on_keyread = 1;
 
7025
                        break;
 
7026
 
 
7027
                        /* IMPORTANT: prebuilt->trx can be obsolete in
 
7028
                        this method, because it is not sure that MySQL
 
7029
                        calls external_lock before this method with the
 
7030
                        parameters below.  We must not invoke update_session()
 
7031
                        either, because the calling threads may change.
 
7032
                        CAREFUL HERE, OR MEMORY CORRUPTION MAY OCCUR! */
 
7033
                case HA_EXTRA_IGNORE_DUP_KEY:
 
7034
                        session_to_trx(ha_session())->duplicates |= TRX_DUP_IGNORE;
 
7035
                        break;
 
7036
                case HA_EXTRA_WRITE_CAN_REPLACE:
 
7037
                        session_to_trx(ha_session())->duplicates |= TRX_DUP_REPLACE;
 
7038
                        break;
 
7039
                case HA_EXTRA_WRITE_CANNOT_REPLACE:
 
7040
                        session_to_trx(ha_session())->duplicates &= ~TRX_DUP_REPLACE;
 
7041
                        break;
 
7042
                case HA_EXTRA_NO_IGNORE_DUP_KEY:
 
7043
                        session_to_trx(ha_session())->duplicates &=
 
7044
                                ~(TRX_DUP_IGNORE | TRX_DUP_REPLACE);
 
7045
                        break;
 
7046
                default:/* Do nothing */
 
7047
                        ;
 
7048
        }
 
7049
 
 
7050
        return(0);
7788
7051
}
7789
7052
 
7790
7053
UNIV_INTERN
7791
7054
int
7792
7055
ha_innobase::reset()
7793
7056
{
7794
 
  if (prebuilt->blob_heap) {
7795
 
    row_mysql_prebuilt_free_blob_heap(prebuilt);
7796
 
  }
7797
 
 
7798
 
  reset_template(prebuilt);
7799
 
 
7800
 
  /* TODO: This should really be reset in reset_template() but for now
7801
 
  it's safer to do it explicitly here. */
7802
 
 
7803
 
  /* This is a statement level counter. */
7804
 
  prebuilt->autoinc_last_value = 0;
7805
 
 
7806
 
  return(0);
 
7057
        if (prebuilt->blob_heap) {
 
7058
                row_mysql_prebuilt_free_blob_heap(prebuilt);
 
7059
        }
 
7060
 
 
7061
        reset_template(prebuilt);
 
7062
 
 
7063
        /* TODO: This should really be reset in reset_template() but for now
 
7064
        it's safer to do it explicitly here. */
 
7065
 
 
7066
        /* This is a statement level counter. */
 
7067
        prebuilt->autoinc_last_value = 0;
 
7068
 
 
7069
        return(0);
7807
7070
}
7808
7071
 
7809
7072
/******************************************************************//**
7810
7073
Maps a MySQL trx isolation level code to the InnoDB isolation level code
7811
 
@return InnoDB isolation level */
 
7074
@return InnoDB isolation level */
7812
7075
static inline
7813
7076
ulint
7814
7077
innobase_map_isolation_level(
7815
7078
/*=========================*/
7816
 
  enum_tx_isolation iso)  /*!< in: MySQL isolation level code */
 
7079
        enum_tx_isolation       iso)    /*!< in: MySQL isolation level code */
7817
7080
{
7818
 
  switch(iso) {
7819
 
    case ISO_REPEATABLE_READ: return(TRX_ISO_REPEATABLE_READ);
7820
 
    case ISO_READ_COMMITTED: return(TRX_ISO_READ_COMMITTED);
7821
 
    case ISO_SERIALIZABLE: return(TRX_ISO_SERIALIZABLE);
7822
 
    case ISO_READ_UNCOMMITTED: return(TRX_ISO_READ_UNCOMMITTED);
7823
 
    default: ut_a(0); return(0);
7824
 
  }
 
7081
        switch(iso) {
 
7082
                case ISO_REPEATABLE_READ: return(TRX_ISO_REPEATABLE_READ);
 
7083
                case ISO_READ_COMMITTED: return(TRX_ISO_READ_COMMITTED);
 
7084
                case ISO_SERIALIZABLE: return(TRX_ISO_SERIALIZABLE);
 
7085
                case ISO_READ_UNCOMMITTED: return(TRX_ISO_READ_UNCOMMITTED);
 
7086
                default: ut_a(0); return(0);
 
7087
        }
7825
7088
}
7826
7089
 
7827
7090
/******************************************************************//**
7828
7091
As MySQL will execute an external lock for every new table it uses when it
7829
7092
starts to process an SQL statement.  We can use this function to store the pointer to
7830
7093
the Session in the handle.
7831
 
@return 0 */
 
7094
@return 0 */
7832
7095
UNIV_INTERN
7833
7096
int
7834
7097
ha_innobase::external_lock(
7835
7098
/*=======================*/
7836
 
  Session*  session,  /*!< in: handle to the user thread */
7837
 
  int lock_type)  /*!< in: lock type */
 
7099
        Session*        session,        /*!< in: handle to the user thread */
 
7100
        int     lock_type)      /*!< in: lock type */
7838
7101
{
7839
 
  update_session(session);
 
7102
        update_session(session);
7840
7103
 
7841
7104
  trx_t *trx= prebuilt->trx;
7842
7105
 
7843
 
  prebuilt->sql_stat_start = TRUE;
7844
 
  prebuilt->hint_need_to_fetch_extra_cols = 0;
7845
 
 
7846
 
  reset_template(prebuilt);
7847
 
 
7848
 
  if (lock_type == F_WRLCK) {
7849
 
 
7850
 
    /* If this is a SELECT, then it is in UPDATE TABLE ...
7851
 
    or SELECT ... FOR UPDATE */
7852
 
    prebuilt->select_lock_type = LOCK_X;
7853
 
    prebuilt->stored_select_lock_type = LOCK_X;
7854
 
  }
7855
 
 
7856
 
  if (lock_type != F_UNLCK) {
7857
 
    /* MySQL is setting a new table lock */
7858
 
 
7859
 
    if (trx->isolation_level == TRX_ISO_SERIALIZABLE
7860
 
      && prebuilt->select_lock_type == LOCK_NONE
7861
 
      && session_test_options(session,
7862
 
        OPTION_NOT_AUTOCOMMIT | OPTION_BEGIN)) {
7863
 
 
7864
 
      /* To get serializable execution, we let InnoDB
7865
 
      conceptually add 'LOCK IN SHARE MODE' to all SELECTs
7866
 
      which otherwise would have been consistent reads. An
7867
 
      exception is consistent reads in the AUTOCOMMIT=1 mode:
7868
 
      we know that they are read-only transactions, and they
7869
 
      can be serialized also if performed as consistent
7870
 
      reads. */
7871
 
 
7872
 
      prebuilt->select_lock_type = LOCK_S;
7873
 
      prebuilt->stored_select_lock_type = LOCK_S;
7874
 
    }
7875
 
 
7876
 
    /* Starting from 4.1.9, no InnoDB table lock is taken in LOCK
7877
 
    TABLES if AUTOCOMMIT=1. It does not make much sense to acquire
7878
 
    an InnoDB table lock if it is released immediately at the end
7879
 
    of LOCK TABLES, and InnoDB's table locks in that case cause
7880
 
    VERY easily deadlocks.
7881
 
 
7882
 
    We do not set InnoDB table locks if user has not explicitly
7883
 
    requested a table lock. Note that session_in_lock_tables(session)
7884
 
    can hold in some cases, e.g., at the start of a stored
7885
 
    procedure call (SQLCOM_CALL). */
7886
 
 
7887
 
    if (prebuilt->select_lock_type != LOCK_NONE) {
7888
 
      trx->mysql_n_tables_locked++;
7889
 
    }
7890
 
 
7891
 
    prebuilt->mysql_has_locked = TRUE;
7892
 
 
7893
 
    return(0);
7894
 
  }
7895
 
 
7896
 
  /* MySQL is releasing a table lock */
7897
 
  prebuilt->mysql_has_locked = FALSE;
7898
 
  trx->mysql_n_tables_locked= 0;
7899
 
 
7900
 
  return(0);
 
7106
        prebuilt->sql_stat_start = TRUE;
 
7107
        prebuilt->hint_need_to_fetch_extra_cols = 0;
 
7108
 
 
7109
        reset_template(prebuilt);
 
7110
 
 
7111
        if (lock_type == F_WRLCK) {
 
7112
 
 
7113
                /* If this is a SELECT, then it is in UPDATE TABLE ...
 
7114
                or SELECT ... FOR UPDATE */
 
7115
                prebuilt->select_lock_type = LOCK_X;
 
7116
                prebuilt->stored_select_lock_type = LOCK_X;
 
7117
        }
 
7118
 
 
7119
        if (lock_type != F_UNLCK) {
 
7120
                /* MySQL is setting a new table lock */
 
7121
 
 
7122
                if (trx->isolation_level == TRX_ISO_SERIALIZABLE
 
7123
                        && prebuilt->select_lock_type == LOCK_NONE
 
7124
                        && session_test_options(session,
 
7125
                                OPTION_NOT_AUTOCOMMIT | OPTION_BEGIN)) {
 
7126
 
 
7127
                        /* To get serializable execution, we let InnoDB
 
7128
                        conceptually add 'LOCK IN SHARE MODE' to all SELECTs
 
7129
                        which otherwise would have been consistent reads. An
 
7130
                        exception is consistent reads in the AUTOCOMMIT=1 mode:
 
7131
                        we know that they are read-only transactions, and they
 
7132
                        can be serialized also if performed as consistent
 
7133
                        reads. */
 
7134
 
 
7135
                        prebuilt->select_lock_type = LOCK_S;
 
7136
                        prebuilt->stored_select_lock_type = LOCK_S;
 
7137
                }
 
7138
 
 
7139
                /* Starting from 4.1.9, no InnoDB table lock is taken in LOCK
 
7140
                TABLES if AUTOCOMMIT=1. It does not make much sense to acquire
 
7141
                an InnoDB table lock if it is released immediately at the end
 
7142
                of LOCK TABLES, and InnoDB's table locks in that case cause
 
7143
                VERY easily deadlocks.
 
7144
 
 
7145
                We do not set InnoDB table locks if user has not explicitly
 
7146
                requested a table lock. Note that session_in_lock_tables(session)
 
7147
                can hold in some cases, e.g., at the start of a stored
 
7148
                procedure call (SQLCOM_CALL). */
 
7149
 
 
7150
                if (prebuilt->select_lock_type != LOCK_NONE) {
 
7151
                        trx->mysql_n_tables_locked++;
 
7152
                }
 
7153
 
 
7154
                prebuilt->mysql_has_locked = TRUE;
 
7155
 
 
7156
                return(0);
 
7157
        }
 
7158
 
 
7159
        /* MySQL is releasing a table lock */
 
7160
        prebuilt->mysql_has_locked = FALSE;
 
7161
        trx->mysql_n_tables_locked= 0;
 
7162
 
 
7163
        return(0);
7901
7164
}
7902
7165
 
7903
7166
/************************************************************************//**
7907
7170
bool
7908
7171
innodb_show_status(
7909
7172
/*===============*/
7910
 
  plugin::StorageEngine*  engine, /*!< in: the innodb StorageEngine */
7911
 
  Session*  session,/*!< in: the MySQL query thread of the caller */
7912
 
  stat_print_fn *stat_print)
 
7173
        plugin::StorageEngine*  engine, /*!< in: the innodb StorageEngine */
 
7174
        Session*        session,/*!< in: the MySQL query thread of the caller */
 
7175
        stat_print_fn *stat_print)
7913
7176
{
7914
 
  trx_t*      trx;
7915
 
  static const char truncated_msg[] = "... truncated...\n";
7916
 
  const long    MAX_STATUS_SIZE = 64000;
7917
 
  ulint     trx_list_start = ULINT_UNDEFINED;
7918
 
  ulint     trx_list_end = ULINT_UNDEFINED;
7919
 
 
7920
 
  assert(engine == innodb_engine_ptr);
7921
 
 
7922
 
  trx = check_trx_exists(session);
7923
 
 
7924
 
  innobase_release_stat_resources(trx);
7925
 
 
7926
 
  /* We let the InnoDB Monitor to output at most MAX_STATUS_SIZE
7927
 
  bytes of text. */
7928
 
 
7929
 
  long  flen, usable_len;
7930
 
  char* str;
7931
 
 
7932
 
  mutex_enter(&srv_monitor_file_mutex);
7933
 
  rewind(srv_monitor_file);
7934
 
  srv_printf_innodb_monitor(srv_monitor_file, FALSE,
7935
 
        &trx_list_start, &trx_list_end);
7936
 
  flen = ftell(srv_monitor_file);
7937
 
  os_file_set_eof(srv_monitor_file);
7938
 
 
7939
 
  if (flen < 0) {
7940
 
    flen = 0;
7941
 
  }
7942
 
 
7943
 
  if (flen > MAX_STATUS_SIZE) {
7944
 
    usable_len = MAX_STATUS_SIZE;
7945
 
  } else {
7946
 
    usable_len = flen;
7947
 
  }
7948
 
 
7949
 
  /* allocate buffer for the string, and
7950
 
  read the contents of the temporary file */
7951
 
 
7952
 
  if (!(str = (char*) malloc(usable_len + 1))) {
7953
 
    mutex_exit(&srv_monitor_file_mutex);
7954
 
    return(TRUE);
7955
 
  }
7956
 
 
7957
 
  rewind(srv_monitor_file);
7958
 
  if (flen < MAX_STATUS_SIZE) {
7959
 
    /* Display the entire output. */
7960
 
    flen = (long) fread(str, 1, flen, srv_monitor_file);
7961
 
  } else if (trx_list_end < (ulint) flen
7962
 
      && trx_list_start < trx_list_end
7963
 
      && trx_list_start + (flen - trx_list_end)
7964
 
      < MAX_STATUS_SIZE - sizeof truncated_msg - 1) {
7965
 
    /* Omit the beginning of the list of active transactions. */
7966
 
    long len = (long) fread(str, 1, trx_list_start, srv_monitor_file);
7967
 
    memcpy(str + len, truncated_msg, sizeof truncated_msg - 1);
7968
 
    len += sizeof truncated_msg - 1;
7969
 
    usable_len = (MAX_STATUS_SIZE - 1) - len;
7970
 
    fseek(srv_monitor_file, flen - usable_len, SEEK_SET);
7971
 
    len += (long) fread(str + len, 1, usable_len, srv_monitor_file);
7972
 
    flen = len;
7973
 
  } else {
7974
 
    /* Omit the end of the output. */
7975
 
    flen = (long) fread(str, 1, MAX_STATUS_SIZE - 1, srv_monitor_file);
7976
 
  }
7977
 
 
7978
 
  mutex_exit(&srv_monitor_file_mutex);
7979
 
 
7980
 
  bool result = FALSE;
7981
 
 
7982
 
  if (stat_print(session, innobase_engine_name, strlen(innobase_engine_name),
7983
 
      STRING_WITH_LEN(""), str, flen)) {
7984
 
    result= TRUE;
7985
 
  }
7986
 
  free(str);
7987
 
 
7988
 
  return(FALSE);
 
7177
        trx_t*                  trx;
 
7178
        static const char       truncated_msg[] = "... truncated...\n";
 
7179
        const long              MAX_STATUS_SIZE = 64000;
 
7180
        ulint                   trx_list_start = ULINT_UNDEFINED;
 
7181
        ulint                   trx_list_end = ULINT_UNDEFINED;
 
7182
 
 
7183
        assert(engine == innodb_engine_ptr);
 
7184
 
 
7185
        trx = check_trx_exists(session);
 
7186
 
 
7187
        innobase_release_stat_resources(trx);
 
7188
 
 
7189
        /* We let the InnoDB Monitor to output at most MAX_STATUS_SIZE
 
7190
        bytes of text. */
 
7191
 
 
7192
        long    flen, usable_len;
 
7193
        char*   str;
 
7194
 
 
7195
        mutex_enter(&srv_monitor_file_mutex);
 
7196
        rewind(srv_monitor_file);
 
7197
        srv_printf_innodb_monitor(srv_monitor_file,
 
7198
                                &trx_list_start, &trx_list_end);
 
7199
        flen = ftell(srv_monitor_file);
 
7200
        os_file_set_eof(srv_monitor_file);
 
7201
 
 
7202
        if (flen < 0) {
 
7203
                flen = 0;
 
7204
        }
 
7205
 
 
7206
        if (flen > MAX_STATUS_SIZE) {
 
7207
                usable_len = MAX_STATUS_SIZE;
 
7208
        } else {
 
7209
                usable_len = flen;
 
7210
        }
 
7211
 
 
7212
        /* allocate buffer for the string, and
 
7213
        read the contents of the temporary file */
 
7214
 
 
7215
        if (!(str = (char*) malloc(usable_len + 1))) {
 
7216
          mutex_exit(&srv_monitor_file_mutex);
 
7217
          return(TRUE);
 
7218
        }
 
7219
 
 
7220
        rewind(srv_monitor_file);
 
7221
        if (flen < MAX_STATUS_SIZE) {
 
7222
                /* Display the entire output. */
 
7223
                flen = (long) fread(str, 1, flen, srv_monitor_file);
 
7224
        } else if (trx_list_end < (ulint) flen
 
7225
                        && trx_list_start < trx_list_end
 
7226
                        && trx_list_start + (flen - trx_list_end)
 
7227
                        < MAX_STATUS_SIZE - sizeof truncated_msg - 1) {
 
7228
                /* Omit the beginning of the list of active transactions. */
 
7229
                long len = (long) fread(str, 1, trx_list_start, srv_monitor_file);
 
7230
                memcpy(str + len, truncated_msg, sizeof truncated_msg - 1);
 
7231
                len += sizeof truncated_msg - 1;
 
7232
                usable_len = (MAX_STATUS_SIZE - 1) - len;
 
7233
                fseek(srv_monitor_file, flen - usable_len, SEEK_SET);
 
7234
                len += (long) fread(str + len, 1, usable_len, srv_monitor_file);
 
7235
                flen = len;
 
7236
        } else {
 
7237
                /* Omit the end of the output. */
 
7238
                flen = (long) fread(str, 1, MAX_STATUS_SIZE - 1, srv_monitor_file);
 
7239
        }
 
7240
 
 
7241
        mutex_exit(&srv_monitor_file_mutex);
 
7242
 
 
7243
        bool result = FALSE;
 
7244
 
 
7245
        if (stat_print(session, innobase_engine_name, strlen(innobase_engine_name),
 
7246
                        STRING_WITH_LEN(""), str, flen)) {
 
7247
                result= TRUE;
 
7248
        }
 
7249
        free(str);
 
7250
 
 
7251
        return(FALSE);
7989
7252
}
7990
7253
 
7991
7254
/************************************************************************//**
7992
 
Implements the SHOW MUTEX STATUS command.
7993
 
@return true on failure false on success*/
 
7255
Implements the SHOW MUTEX STATUS command. . */
7994
7256
static
7995
7257
bool
7996
7258
innodb_mutex_show_status(
7997
7259
/*=====================*/
7998
 
  plugin::StorageEngine*  engine,   /*!< in: the innodb StorageEngine */
7999
 
  Session*  session,  /*!< in: the MySQL query thread of the
8000
 
          caller */
8001
 
  stat_print_fn*  stat_print)   /*!< in: function for printing
8002
 
                                        statistics */
 
7260
        plugin::StorageEngine*  engine,         /*!< in: the innodb StorageEngine */
 
7261
        Session*        session,        /*!< in: the MySQL query thread of the
 
7262
                                        caller */
 
7263
        stat_print_fn*  stat_print)
8003
7264
{
8004
 
  char buf1[IO_SIZE], buf2[IO_SIZE];
8005
 
  mutex_t*  mutex;
8006
 
  rw_lock_t*  lock;
8007
 
  ulint         block_mutex_oswait_count = 0;
8008
 
  ulint         block_lock_oswait_count = 0;
8009
 
  mutex_t*      block_mutex = NULL;
8010
 
  rw_lock_t*    block_lock = NULL;
 
7265
        char buf1[IO_SIZE], buf2[IO_SIZE];
 
7266
        mutex_t*        mutex;
 
7267
        rw_lock_t*      lock;
8011
7268
#ifdef UNIV_DEBUG
8012
 
  ulint   rw_lock_count= 0;
8013
 
  ulint   rw_lock_count_spin_loop= 0;
8014
 
  ulint   rw_lock_count_spin_rounds= 0;
8015
 
  ulint   rw_lock_count_os_wait= 0;
8016
 
  ulint   rw_lock_count_os_yield= 0;
8017
 
  uint64_t rw_lock_wait_time= 0;
 
7269
        ulint     rw_lock_count= 0;
 
7270
        ulint     rw_lock_count_spin_loop= 0;
 
7271
        ulint     rw_lock_count_spin_rounds= 0;
 
7272
        ulint     rw_lock_count_os_wait= 0;
 
7273
        ulint     rw_lock_count_os_yield= 0;
 
7274
        uint64_t rw_lock_wait_time= 0;
8018
7275
#endif /* UNIV_DEBUG */
8019
 
  uint    engine_name_len= strlen(innobase_engine_name), buf1len, buf2len;
8020
 
  assert(engine == innodb_engine_ptr);
8021
 
 
8022
 
  mutex_enter(&mutex_list_mutex);
8023
 
 
8024
 
  for (mutex = UT_LIST_GET_FIRST(mutex_list); mutex != NULL;
8025
 
       mutex = UT_LIST_GET_NEXT(list, mutex)) {
8026
 
    if (mutex->count_os_wait == 0) {
8027
 
      continue;
8028
 
    }
8029
 
 
8030
 
 
8031
 
    if (buf_pool_is_block_mutex(mutex)) {
8032
 
      block_mutex = mutex;
8033
 
      block_mutex_oswait_count += mutex->count_os_wait;
8034
 
      continue;
8035
 
    }
 
7276
        uint      engine_name_len= strlen(innobase_engine_name), buf1len, buf2len;
 
7277
        assert(engine == innodb_engine_ptr);
 
7278
 
 
7279
        mutex_enter(&mutex_list_mutex);
 
7280
 
 
7281
        mutex = UT_LIST_GET_FIRST(mutex_list);
 
7282
 
 
7283
        while (mutex != NULL) {
 
7284
                if (mutex->count_os_wait == 0
 
7285
                    || buf_pool_is_block_mutex(mutex)) {
 
7286
                        goto next_mutex;
 
7287
                }
8036
7288
#ifdef UNIV_DEBUG
8037
 
    if (mutex->mutex_type != 1) {
8038
 
      if (mutex->count_using > 0) {
8039
 
        buf1len= my_snprintf(buf1, sizeof(buf1),
8040
 
          "%s:%s",
8041
 
          mutex->cmutex_name, mutex->cfile_name);
8042
 
        buf2len= my_snprintf(buf2, sizeof(buf2),
8043
 
          "count=%lu, spin_waits=%lu,"
8044
 
          " spin_rounds=%lu, "
8045
 
          "os_waits=%lu, os_yields=%lu,"
8046
 
          " os_wait_times=%lu",
8047
 
          mutex->count_using,
8048
 
          mutex->count_spin_loop,
8049
 
          mutex->count_spin_rounds,
8050
 
          mutex->count_os_wait,
8051
 
          mutex->count_os_yield,
8052
 
          (ulong) (mutex->lspent_time/1000));
 
7289
                if (mutex->mutex_type != 1) {
 
7290
                        if (mutex->count_using > 0) {
 
7291
                                buf1len= my_snprintf(buf1, sizeof(buf1),
 
7292
                                        "%s:%s",
 
7293
                                        mutex->cmutex_name, mutex->cfile_name);
 
7294
                                buf2len= my_snprintf(buf2, sizeof(buf2),
 
7295
                                        "count=%lu, spin_waits=%lu,"
 
7296
                                        " spin_rounds=%lu, "
 
7297
                                        "os_waits=%lu, os_yields=%lu,"
 
7298
                                        " os_wait_times=%lu",
 
7299
                                        mutex->count_using,
 
7300
                                        mutex->count_spin_loop,
 
7301
                                        mutex->count_spin_rounds,
 
7302
                                        mutex->count_os_wait,
 
7303
                                        mutex->count_os_yield,
 
7304
                                        (ulong) (mutex->lspent_time/1000));
8053
7305
 
8054
 
        if (stat_print(session, innobase_engine_name,
8055
 
            engine_name_len, buf1, buf1len,
8056
 
            buf2, buf2len)) {
8057
 
          mutex_exit(&mutex_list_mutex);
8058
 
          return(1);
8059
 
        }
8060
 
      }
8061
 
    } else {
8062
 
      rw_lock_count += mutex->count_using;
8063
 
      rw_lock_count_spin_loop += mutex->count_spin_loop;
8064
 
      rw_lock_count_spin_rounds += mutex->count_spin_rounds;
8065
 
      rw_lock_count_os_wait += mutex->count_os_wait;
8066
 
      rw_lock_count_os_yield += mutex->count_os_yield;
8067
 
      rw_lock_wait_time += mutex->lspent_time;
8068
 
    }
 
7306
                                if (stat_print(session, innobase_engine_name,
 
7307
                                                engine_name_len, buf1, buf1len,
 
7308
                                                buf2, buf2len)) {
 
7309
                                        mutex_exit(&mutex_list_mutex);
 
7310
                                        return(1);
 
7311
                                }
 
7312
                        }
 
7313
                }
 
7314
                else {
 
7315
                        rw_lock_count += mutex->count_using;
 
7316
                        rw_lock_count_spin_loop += mutex->count_spin_loop;
 
7317
                        rw_lock_count_spin_rounds += mutex->count_spin_rounds;
 
7318
                        rw_lock_count_os_wait += mutex->count_os_wait;
 
7319
                        rw_lock_count_os_yield += mutex->count_os_yield;
 
7320
                        rw_lock_wait_time += mutex->lspent_time;
 
7321
                }
8069
7322
#else /* UNIV_DEBUG */
8070
 
    buf1len= snprintf(buf1, sizeof(buf1), "%s:%lu",
8071
 
          mutex->cfile_name, (ulong) mutex->cline);
8072
 
    buf2len= snprintf(buf2, sizeof(buf2), "os_waits=%lu",
8073
 
                      (ulong) mutex->count_os_wait);
 
7323
                buf1len= snprintf(buf1, sizeof(buf1), "%s:%lu",
 
7324
                                  mutex->cfile_name, (ulong) mutex->cline);
 
7325
                buf2len= snprintf(buf2, sizeof(buf2), "os_waits=%lu",
 
7326
                                  mutex->count_os_wait);
8074
7327
 
8075
 
    if (stat_print(session, innobase_engine_name,
8076
 
             engine_name_len, buf1, buf1len,
8077
 
             buf2, buf2len)) {
8078
 
      mutex_exit(&mutex_list_mutex);
8079
 
      return(1);
8080
 
    }
 
7328
                if (stat_print(session, innobase_engine_name,
 
7329
                               engine_name_len, buf1, buf1len,
 
7330
                               buf2, buf2len)) {
 
7331
                        mutex_exit(&mutex_list_mutex);
 
7332
                        return(1);
 
7333
                }
8081
7334
#endif /* UNIV_DEBUG */
8082
 
  }
8083
 
 
8084
 
  if (block_mutex) {
8085
 
    buf1len = snprintf(buf1, sizeof buf1,
8086
 
                       "combined %s:%lu",
8087
 
                       block_mutex->cfile_name,
8088
 
                       (ulong) block_mutex->cline);
8089
 
    buf2len = snprintf(buf2, sizeof buf2,
8090
 
                       "os_waits=%lu",
8091
 
                       (ulong) block_mutex_oswait_count);
8092
 
 
8093
 
    if (stat_print(session, innobase_engine_name,
8094
 
                   strlen(innobase_engine_name), buf1, buf1len,
8095
 
                   buf2, buf2len)) {
8096
 
      mutex_exit(&mutex_list_mutex);
8097
 
      return(1);
8098
 
    }
8099
 
  }
8100
 
 
8101
 
  mutex_exit(&mutex_list_mutex);
8102
 
 
8103
 
  mutex_enter(&rw_lock_list_mutex);
8104
 
 
8105
 
  for (lock = UT_LIST_GET_FIRST(rw_lock_list); lock != NULL;
8106
 
       lock = UT_LIST_GET_NEXT(list, lock)) {
8107
 
    if (lock->count_os_wait == 0) {
8108
 
      continue;
8109
 
    }
8110
 
 
8111
 
    if (buf_pool_is_block_lock(lock)) {
8112
 
      block_lock = lock;
8113
 
      block_lock_oswait_count += lock->count_os_wait;
8114
 
      continue;
8115
 
    }
8116
 
 
8117
 
    buf1len = snprintf(buf1, sizeof buf1, "%s:%lu",
8118
 
                       lock->cfile_name, (ulong) lock->cline);
8119
 
    buf2len = snprintf(buf2, sizeof buf2, "os_waits=%lu",
8120
 
                       (ulong) lock->count_os_wait);
8121
 
 
8122
 
    if (stat_print(session, innobase_engine_name,
8123
 
                   strlen(innobase_engine_name), buf1, buf1len,
8124
 
                   buf2, buf2len)) {
8125
 
      mutex_exit(&rw_lock_list_mutex);
8126
 
      return(1);
8127
 
    }
8128
 
  }
8129
 
 
8130
 
  if (block_lock) {
8131
 
    buf1len = snprintf(buf1, sizeof buf1,
8132
 
                       "combined %s:%lu",
8133
 
                       block_lock->cfile_name,
8134
 
                       (ulong) block_lock->cline);
8135
 
    buf2len = snprintf(buf2, sizeof buf2,
8136
 
                       "os_waits=%lu",
8137
 
                       (ulong) block_lock_oswait_count);
8138
 
 
8139
 
    if (stat_print(session, innobase_engine_name,
8140
 
                   strlen(innobase_engine_name), buf1, buf1len,
8141
 
                   buf2, buf2len)) {
8142
 
      mutex_exit(&rw_lock_list_mutex);
8143
 
      return(1);
8144
 
    }
8145
 
  }
8146
 
 
8147
 
  mutex_exit(&rw_lock_list_mutex);
 
7335
 
 
7336
next_mutex:
 
7337
                mutex = UT_LIST_GET_NEXT(list, mutex);
 
7338
        }
 
7339
 
 
7340
        mutex_exit(&mutex_list_mutex);
 
7341
 
 
7342
        mutex_enter(&rw_lock_list_mutex);
 
7343
 
 
7344
        lock = UT_LIST_GET_FIRST(rw_lock_list);
 
7345
 
 
7346
        while (lock != NULL) {
 
7347
                if (lock->count_os_wait
 
7348
                    && !buf_pool_is_block_lock(lock)) {
 
7349
                        buf1len= snprintf(buf1, sizeof(buf1), "%s:%lu",
 
7350
                                    lock->cfile_name, (unsigned long) lock->cline);
 
7351
                        buf2len= snprintf(buf2, sizeof(buf2),
 
7352
                                    "os_waits=%lu", lock->count_os_wait);
 
7353
 
 
7354
                        if (stat_print(session, innobase_engine_name,
 
7355
                                       engine_name_len, buf1, buf1len,
 
7356
                                       buf2, buf2len)) {
 
7357
                                mutex_exit(&rw_lock_list_mutex);
 
7358
                                return(1);
 
7359
                        }
 
7360
                }
 
7361
                lock = UT_LIST_GET_NEXT(list, lock);
 
7362
        }
 
7363
 
 
7364
        mutex_exit(&rw_lock_list_mutex);
8148
7365
 
8149
7366
#ifdef UNIV_DEBUG
8150
 
  buf2len = snprintf(buf2, sizeof buf2,
8151
 
                     "count=%lu, spin_waits=%lu, spin_rounds=%lu, "
8152
 
                     "os_waits=%lu, os_yields=%lu, os_wait_times=%lu",
8153
 
                     (ulong) rw_lock_count,
8154
 
                     (ulong) rw_lock_count_spin_loop,
8155
 
                     (ulong) rw_lock_count_spin_rounds,
8156
 
                     (ulong) rw_lock_count_os_wait,
8157
 
                     (ulong) rw_lock_count_os_yield,
8158
 
                     (ulong) (rw_lock_wait_time / 1000));
 
7367
        buf2len= my_snprintf(buf2, sizeof(buf2),
 
7368
                "count=%lu, spin_waits=%lu, spin_rounds=%lu, "
 
7369
                "os_waits=%lu, os_yields=%lu, os_wait_times=%lu",
 
7370
                rw_lock_count, rw_lock_count_spin_loop,
 
7371
                rw_lock_count_spin_rounds,
 
7372
                rw_lock_count_os_wait, rw_lock_count_os_yield,
 
7373
                (ulong) (rw_lock_wait_time/1000));
8159
7374
 
8160
 
  if (stat_print(session, innobase_engine_name, engine_name_len,
8161
 
      STRING_WITH_LEN("rw_lock_mutexes"), buf2, buf2len)) {
8162
 
    return(1);
8163
 
  }
 
7375
        if (stat_print(session, innobase_engine_name, engine_name_len,
 
7376
                        STRING_WITH_LEN("rw_lock_mutexes"), buf2, buf2len)) {
 
7377
                return(1);
 
7378
        }
8164
7379
#endif /* UNIV_DEBUG */
8165
7380
 
8166
 
  return(FALSE);
 
7381
        return(FALSE);
8167
7382
}
8168
7383
 
8169
7384
bool InnobaseEngine::show_status(Session* session, 
8170
7385
                                 stat_print_fn* stat_print,
8171
7386
                                 enum ha_stat_type stat_type)
8172
7387
{
8173
 
  assert(this == innodb_engine_ptr);
 
7388
        assert(this == innodb_engine_ptr);
8174
7389
 
8175
 
  switch (stat_type) {
8176
 
  case HA_ENGINE_STATUS:
8177
 
    return innodb_show_status(this, session, stat_print);
8178
 
  case HA_ENGINE_MUTEX:
8179
 
    return innodb_mutex_show_status(this, session, stat_print);
8180
 
  default:
8181
 
    return(FALSE);
8182
 
  }
 
7390
        switch (stat_type) {
 
7391
        case HA_ENGINE_STATUS:
 
7392
                return innodb_show_status(this, session, stat_print);
 
7393
        case HA_ENGINE_MUTEX:
 
7394
                return innodb_mutex_show_status(this, session, stat_print);
 
7395
        default:
 
7396
                return(FALSE);
 
7397
        }
8183
7398
}
8184
7399
 
8185
7400
/************************************************************************//**
8189
7404
 
8190
7405
static INNOBASE_SHARE* get_share(const char* table_name)
8191
7406
{
8192
 
  INNOBASE_SHARE *share;
8193
 
  pthread_mutex_lock(&innobase_share_mutex);
8194
 
 
8195
 
  ulint fold = ut_fold_string(table_name);
8196
 
 
8197
 
  HASH_SEARCH(table_name_hash, innobase_open_tables, fold,
8198
 
        INNOBASE_SHARE*, share,
8199
 
        ut_ad(share->use_count > 0),
8200
 
        !strcmp(share->table_name, table_name));
8201
 
 
8202
 
  if (!share) {
8203
 
    /* TODO: invoke HASH_MIGRATE if innobase_open_tables
8204
 
    grows too big */
8205
 
 
8206
 
    share= new INNOBASE_SHARE(table_name);
8207
 
 
8208
 
    HASH_INSERT(INNOBASE_SHARE, table_name_hash,
8209
 
          innobase_open_tables, fold, share);
8210
 
 
8211
 
    thr_lock_init(&share->lock);
8212
 
 
8213
 
    /* Index translation table initialization */
8214
 
    share->idx_trans_tbl.index_mapping = NULL;
8215
 
    share->idx_trans_tbl.index_count = 0;
8216
 
    share->idx_trans_tbl.array_size = 0;
8217
 
  }
8218
 
 
8219
 
  share->use_count++;
8220
 
  pthread_mutex_unlock(&innobase_share_mutex);
8221
 
 
8222
 
  return(share);
 
7407
        INNOBASE_SHARE *share;
 
7408
        pthread_mutex_lock(&innobase_share_mutex);
 
7409
 
 
7410
        ulint   fold = ut_fold_string(table_name);
 
7411
 
 
7412
        HASH_SEARCH(table_name_hash, innobase_open_tables, fold,
 
7413
                    INNOBASE_SHARE*, share,
 
7414
                    ut_ad(share->use_count > 0),
 
7415
                    !strcmp(share->table_name, table_name));
 
7416
 
 
7417
        if (!share) {
 
7418
 
 
7419
                uint length = (uint) strlen(table_name);
 
7420
 
 
7421
                /* TODO: invoke HASH_MIGRATE if innobase_open_tables
 
7422
                grows too big */
 
7423
 
 
7424
                share = (INNOBASE_SHARE *) malloc(sizeof(*share)+length+1);
 
7425
                memset(share, 0, sizeof(*share)+length+1);
 
7426
 
 
7427
                share->table_name = (char*) memcpy(share + 1,
 
7428
                                                   table_name, length + 1);
 
7429
 
 
7430
                HASH_INSERT(INNOBASE_SHARE, table_name_hash,
 
7431
                            innobase_open_tables, fold, share);
 
7432
 
 
7433
                thr_lock_init(&share->lock);
 
7434
        }
 
7435
 
 
7436
        share->use_count++;
 
7437
        pthread_mutex_unlock(&innobase_share_mutex);
 
7438
 
 
7439
        return(share);
8223
7440
}
8224
7441
 
8225
7442
static void free_share(INNOBASE_SHARE* share)
8226
7443
{
8227
 
  pthread_mutex_lock(&innobase_share_mutex);
 
7444
        pthread_mutex_lock(&innobase_share_mutex);
8228
7445
 
8229
7446
#ifdef UNIV_DEBUG
8230
 
  INNOBASE_SHARE* share2;
8231
 
  ulint fold = ut_fold_string(share->table_name);
8232
 
 
8233
 
  HASH_SEARCH(table_name_hash, innobase_open_tables, fold,
8234
 
        INNOBASE_SHARE*, share2,
8235
 
        ut_ad(share->use_count > 0),
8236
 
        !strcmp(share->table_name, share2->table_name));
8237
 
 
8238
 
  ut_a(share2 == share);
 
7447
        INNOBASE_SHARE* share2;
 
7448
        ulint   fold = ut_fold_string(share->table_name);
 
7449
 
 
7450
        HASH_SEARCH(table_name_hash, innobase_open_tables, fold,
 
7451
                    INNOBASE_SHARE*, share2,
 
7452
                    ut_ad(share->use_count > 0),
 
7453
                    !strcmp(share->table_name, share2->table_name));
 
7454
 
 
7455
        ut_a(share2 == share);
8239
7456
#endif /* UNIV_DEBUG */
8240
7457
 
8241
 
  if (!--share->use_count) {
8242
 
    ulint fold = ut_fold_string(share->table_name);
8243
 
 
8244
 
    HASH_DELETE(INNOBASE_SHARE, table_name_hash,
8245
 
          innobase_open_tables, fold, share);
8246
 
    share->lock.deinit();
8247
 
 
8248
 
    /* Free any memory from index translation table */
8249
 
    free(share->idx_trans_tbl.index_mapping);
8250
 
 
8251
 
    delete share;
8252
 
 
8253
 
    /* TODO: invoke HASH_MIGRATE if innobase_open_tables
8254
 
    shrinks too much */
8255
 
  }
8256
 
 
8257
 
  pthread_mutex_unlock(&innobase_share_mutex);
 
7458
        if (!--share->use_count) {
 
7459
                ulint   fold = ut_fold_string(share->table_name);
 
7460
 
 
7461
                HASH_DELETE(INNOBASE_SHARE, table_name_hash,
 
7462
                            innobase_open_tables, fold, share);
 
7463
                thr_lock_delete(&share->lock);
 
7464
                free(share);
 
7465
 
 
7466
                /* TODO: invoke HASH_MIGRATE if innobase_open_tables
 
7467
                shrinks too much */
 
7468
        }
 
7469
 
 
7470
        pthread_mutex_unlock(&innobase_share_mutex);
8258
7471
}
8259
7472
 
8260
7473
/*****************************************************************//**
8265
7478
SELECT the read lock is released early on the 'const' tables where we only
8266
7479
fetch one row. MySQL does not call this when it releases all locks at the
8267
7480
end of an SQL statement.
8268
 
@return pointer to the next element in the 'to' array */
 
7481
@return pointer to the next element in the 'to' array */
8269
7482
UNIV_INTERN
8270
7483
THR_LOCK_DATA**
8271
7484
ha_innobase::store_lock(
8272
7485
/*====================*/
8273
 
  Session*    session,  /*!< in: user thread handle */
8274
 
  THR_LOCK_DATA**   to,   /*!< in: pointer to an array
8275
 
            of pointers to lock structs;
8276
 
            pointer to the 'lock' field
8277
 
            of current handle is stored
8278
 
            next to this array */
8279
 
  enum thr_lock_type  lock_type)  /*!< in: lock type to store in
8280
 
            'lock'; this may also be
8281
 
            TL_IGNORE */
 
7486
        Session*                session,        /*!< in: user thread handle */
 
7487
        THR_LOCK_DATA**         to,             /*!< in: pointer to an array
 
7488
                                                of pointers to lock structs;
 
7489
                                                pointer to the 'lock' field
 
7490
                                                of current handle is stored
 
7491
                                                next to this array */
 
7492
        enum thr_lock_type      lock_type)      /*!< in: lock type to store in
 
7493
                                                'lock'; this may also be
 
7494
                                                TL_IGNORE */
8282
7495
{
8283
 
  trx_t*    trx;
8284
 
 
8285
 
  /* Note that trx in this function is NOT necessarily prebuilt->trx
8286
 
  because we call update_session() later, in ::external_lock()! Failure to
8287
 
  understand this caused a serious memory corruption bug in 5.1.11. */
8288
 
 
8289
 
  trx = check_trx_exists(session);
8290
 
 
8291
 
  assert(EQ_CURRENT_SESSION(session));
8292
 
  const uint32_t sql_command = session_sql_command(session);
8293
 
 
8294
 
  if (sql_command == SQLCOM_DROP_TABLE) {
8295
 
 
8296
 
    /* MySQL calls this function in DROP Table though this table
8297
 
    handle may belong to another session that is running a query.
8298
 
    Let us in that case skip any changes to the prebuilt struct. */ 
8299
 
 
8300
 
  } else if (lock_type == TL_READ_WITH_SHARED_LOCKS
8301
 
       || lock_type == TL_READ_NO_INSERT
8302
 
       || (lock_type != TL_IGNORE
8303
 
           && sql_command != SQLCOM_SELECT)) {
8304
 
 
8305
 
    /* The OR cases above are in this order:
8306
 
    1) MySQL is doing LOCK TABLES ... READ LOCAL, or we
8307
 
    are processing a stored procedure or function, or
8308
 
    2) (we do not know when TL_READ_HIGH_PRIORITY is used), or
8309
 
    3) this is a SELECT ... IN SHARE MODE, or
8310
 
    4) we are doing a complex SQL statement like
8311
 
    INSERT INTO ... SELECT ... and the logical logging (MySQL
8312
 
    binlog) requires the use of a locking read, or
8313
 
    MySQL is doing LOCK TABLES ... READ.
8314
 
    5) we let InnoDB do locking reads for all SQL statements that
8315
 
    are not simple SELECTs; note that select_lock_type in this
8316
 
    case may get strengthened in ::external_lock() to LOCK_X.
8317
 
    Note that we MUST use a locking read in all data modifying
8318
 
    SQL statements, because otherwise the execution would not be
8319
 
    serializable, and also the results from the update could be
8320
 
    unexpected if an obsolete consistent read view would be
8321
 
    used. */
8322
 
 
8323
 
    ulint isolation_level;
8324
 
 
8325
 
    isolation_level = trx->isolation_level;
8326
 
 
8327
 
    if ((srv_locks_unsafe_for_binlog
8328
 
         || isolation_level <= TRX_ISO_READ_COMMITTED)
8329
 
        && isolation_level != TRX_ISO_SERIALIZABLE
8330
 
        && (lock_type == TL_READ || lock_type == TL_READ_NO_INSERT)
8331
 
        && (sql_command == SQLCOM_INSERT_SELECT
8332
 
            || sql_command == SQLCOM_REPLACE_SELECT
8333
 
            || sql_command == SQLCOM_UPDATE
8334
 
            || sql_command == SQLCOM_CREATE_TABLE)) {
8335
 
 
8336
 
      /* If we either have innobase_locks_unsafe_for_binlog
8337
 
      option set or this session is using READ COMMITTED
8338
 
      isolation level and isolation level of the transaction
8339
 
      is not set to serializable and MySQL is doing
8340
 
      INSERT INTO...SELECT or REPLACE INTO...SELECT
8341
 
      or UPDATE ... = (SELECT ...) or CREATE  ...
8342
 
      SELECT... without FOR UPDATE or IN SHARE
8343
 
      MODE in select, then we use consistent read
8344
 
      for select. */
8345
 
 
8346
 
      prebuilt->select_lock_type = LOCK_NONE;
8347
 
      prebuilt->stored_select_lock_type = LOCK_NONE;
8348
 
    } else if (sql_command == SQLCOM_CHECKSUM) {
8349
 
      /* Use consistent read for checksum table */
8350
 
 
8351
 
      prebuilt->select_lock_type = LOCK_NONE;
8352
 
      prebuilt->stored_select_lock_type = LOCK_NONE;
8353
 
    } else {
8354
 
      prebuilt->select_lock_type = LOCK_S;
8355
 
      prebuilt->stored_select_lock_type = LOCK_S;
8356
 
    }
8357
 
 
8358
 
  } else if (lock_type != TL_IGNORE) {
8359
 
 
8360
 
    /* We set possible LOCK_X value in external_lock, not yet
8361
 
    here even if this would be SELECT ... FOR UPDATE */
8362
 
 
8363
 
    prebuilt->select_lock_type = LOCK_NONE;
8364
 
    prebuilt->stored_select_lock_type = LOCK_NONE;
8365
 
  }
8366
 
 
8367
 
  if (lock_type != TL_IGNORE && lock.type == TL_UNLOCK) {
8368
 
 
8369
 
    /* If we are not doing a LOCK TABLE, DISCARD/IMPORT
8370
 
    TABLESPACE or TRUNCATE TABLE then allow multiple
8371
 
    writers. Note that ALTER TABLE uses a TL_WRITE_ALLOW_READ
8372
 
    < TL_WRITE_CONCURRENT_INSERT.
8373
 
    */
8374
 
 
8375
 
    if ((lock_type >= TL_WRITE_CONCURRENT_INSERT
8376
 
         && lock_type <= TL_WRITE)
8377
 
        && !session_tablespace_op(session)
8378
 
        && sql_command != SQLCOM_TRUNCATE
8379
 
        && sql_command != SQLCOM_CREATE_TABLE) {
8380
 
 
8381
 
      lock_type = TL_WRITE_ALLOW_WRITE;
8382
 
    }
8383
 
 
8384
 
    /* In queries of type INSERT INTO t1 SELECT ... FROM t2 ...
8385
 
    MySQL would use the lock TL_READ_NO_INSERT on t2, and that
8386
 
    would conflict with TL_WRITE_ALLOW_WRITE, blocking all inserts
8387
 
    to t2. Convert the lock to a normal read lock to allow
8388
 
    concurrent inserts to t2.
8389
 
    */
8390
 
 
8391
 
    if (lock_type == TL_READ_NO_INSERT) {
8392
 
 
8393
 
      lock_type = TL_READ;
8394
 
    }
8395
 
 
8396
 
    lock.type = lock_type;
8397
 
  }
8398
 
 
8399
 
  *to++= &lock;
8400
 
 
8401
 
  return(to);
 
7496
        trx_t*          trx;
 
7497
 
 
7498
        /* Note that trx in this function is NOT necessarily prebuilt->trx
 
7499
        because we call update_session() later, in ::external_lock()! Failure to
 
7500
        understand this caused a serious memory corruption bug in 5.1.11. */
 
7501
 
 
7502
        trx = check_trx_exists(session);
 
7503
 
 
7504
        assert(EQ_CURRENT_SESSION(session));
 
7505
        const uint32_t sql_command = session_sql_command(session);
 
7506
 
 
7507
        if (sql_command == SQLCOM_DROP_TABLE) {
 
7508
 
 
7509
                /* MySQL calls this function in DROP Table though this table
 
7510
                handle may belong to another session that is running a query.
 
7511
                Let us in that case skip any changes to the prebuilt struct. */ 
 
7512
 
 
7513
        } else if (lock_type == TL_READ_WITH_SHARED_LOCKS
 
7514
                   || lock_type == TL_READ_NO_INSERT
 
7515
                   || (lock_type != TL_IGNORE
 
7516
                       && sql_command != SQLCOM_SELECT)) {
 
7517
 
 
7518
                /* The OR cases above are in this order:
 
7519
                1) MySQL is doing LOCK TABLES ... READ LOCAL, or we
 
7520
                are processing a stored procedure or function, or
 
7521
                2) (we do not know when TL_READ_HIGH_PRIORITY is used), or
 
7522
                3) this is a SELECT ... IN SHARE MODE, or
 
7523
                4) we are doing a complex SQL statement like
 
7524
                INSERT INTO ... SELECT ... and the logical logging (MySQL
 
7525
                binlog) requires the use of a locking read, or
 
7526
                MySQL is doing LOCK TABLES ... READ.
 
7527
                5) we let InnoDB do locking reads for all SQL statements that
 
7528
                are not simple SELECTs; note that select_lock_type in this
 
7529
                case may get strengthened in ::external_lock() to LOCK_X.
 
7530
                Note that we MUST use a locking read in all data modifying
 
7531
                SQL statements, because otherwise the execution would not be
 
7532
                serializable, and also the results from the update could be
 
7533
                unexpected if an obsolete consistent read view would be
 
7534
                used. */
 
7535
 
 
7536
                ulint   isolation_level;
 
7537
 
 
7538
                isolation_level = trx->isolation_level;
 
7539
 
 
7540
                if ((srv_locks_unsafe_for_binlog
 
7541
                     || isolation_level == TRX_ISO_READ_COMMITTED)
 
7542
                    && isolation_level != TRX_ISO_SERIALIZABLE
 
7543
                    && (lock_type == TL_READ || lock_type == TL_READ_NO_INSERT)
 
7544
                    && (sql_command == SQLCOM_INSERT_SELECT
 
7545
                        || sql_command == SQLCOM_UPDATE
 
7546
                        || sql_command == SQLCOM_CREATE_TABLE)) {
 
7547
 
 
7548
                        /* If we either have innobase_locks_unsafe_for_binlog
 
7549
                        option set or this session is using READ COMMITTED
 
7550
                        isolation level and isolation level of the transaction
 
7551
                        is not set to serializable and MySQL is doing
 
7552
                        INSERT INTO...SELECT or UPDATE ... = (SELECT ...) or
 
7553
                        CREATE  ... SELECT... without FOR UPDATE or
 
7554
                        IN SHARE MODE in select, then we use consistent
 
7555
                        read for select. */
 
7556
 
 
7557
                        prebuilt->select_lock_type = LOCK_NONE;
 
7558
                        prebuilt->stored_select_lock_type = LOCK_NONE;
 
7559
                } else if (sql_command == SQLCOM_CHECKSUM) {
 
7560
                        /* Use consistent read for checksum table */
 
7561
 
 
7562
                        prebuilt->select_lock_type = LOCK_NONE;
 
7563
                        prebuilt->stored_select_lock_type = LOCK_NONE;
 
7564
                } else {
 
7565
                        prebuilt->select_lock_type = LOCK_S;
 
7566
                        prebuilt->stored_select_lock_type = LOCK_S;
 
7567
                }
 
7568
 
 
7569
        } else if (lock_type != TL_IGNORE) {
 
7570
 
 
7571
                /* We set possible LOCK_X value in external_lock, not yet
 
7572
                here even if this would be SELECT ... FOR UPDATE */
 
7573
 
 
7574
                prebuilt->select_lock_type = LOCK_NONE;
 
7575
                prebuilt->stored_select_lock_type = LOCK_NONE;
 
7576
        }
 
7577
 
 
7578
        if (lock_type != TL_IGNORE && lock.type == TL_UNLOCK) {
 
7579
 
 
7580
                /* If we are not doing a LOCK TABLE, DISCARD/IMPORT
 
7581
                TABLESPACE or TRUNCATE TABLE then allow multiple
 
7582
                writers. Note that ALTER TABLE uses a TL_WRITE_ALLOW_READ
 
7583
                < TL_WRITE_CONCURRENT_INSERT.
 
7584
                */
 
7585
 
 
7586
                if ((lock_type >= TL_WRITE_CONCURRENT_INSERT
 
7587
                     && lock_type <= TL_WRITE)
 
7588
                    && !session_tablespace_op(session)
 
7589
                    && sql_command != SQLCOM_TRUNCATE
 
7590
                    && sql_command != SQLCOM_CREATE_TABLE) {
 
7591
 
 
7592
                        lock_type = TL_WRITE_ALLOW_WRITE;
 
7593
                }
 
7594
 
 
7595
                /* In queries of type INSERT INTO t1 SELECT ... FROM t2 ...
 
7596
                MySQL would use the lock TL_READ_NO_INSERT on t2, and that
 
7597
                would conflict with TL_WRITE_ALLOW_WRITE, blocking all inserts
 
7598
                to t2. Convert the lock to a normal read lock to allow
 
7599
                concurrent inserts to t2.
 
7600
    */
 
7601
 
 
7602
                if (lock_type == TL_READ_NO_INSERT) {
 
7603
 
 
7604
                        lock_type = TL_READ;
 
7605
                }
 
7606
 
 
7607
                lock.type = lock_type;
 
7608
        }
 
7609
 
 
7610
        *to++= &lock;
 
7611
 
 
7612
        return(to);
8402
7613
}
8403
7614
 
8404
7615
/*********************************************************************//**
8405
7616
Read the next autoinc value. Acquire the relevant locks before reading
8406
7617
the AUTOINC value. If SUCCESS then the table AUTOINC mutex will be locked
8407
7618
on return and all relevant locks acquired.
8408
 
@return DB_SUCCESS or error code */
 
7619
@return DB_SUCCESS or error code */
8409
7620
UNIV_INTERN
8410
7621
ulint
8411
7622
ha_innobase::innobase_get_autoinc(
8412
7623
/*==============================*/
8413
 
  uint64_t* value)    /*!< out: autoinc value */
 
7624
        uint64_t*       value)          /*!< out: autoinc value */
8414
7625
{
8415
 
  *value = 0;
8416
 
 
8417
 
  dict_table_autoinc_lock(prebuilt->table);
8418
 
  prebuilt->autoinc_error= DB_SUCCESS;
8419
 
  /* Determine the first value of the interval */
8420
 
  *value = dict_table_autoinc_read(prebuilt->table);
8421
 
 
8422
 
  /* It should have been initialized during open. */
8423
 
  if (*value == 0) {
8424
 
    prebuilt->autoinc_error = DB_UNSUPPORTED;
8425
 
    dict_table_autoinc_unlock(prebuilt->table);
8426
 
  }
8427
 
 
8428
 
  return(DB_SUCCESS);
 
7626
        *value = 0;
 
7627
 
 
7628
        prebuilt->autoinc_error = innobase_lock_autoinc();
 
7629
 
 
7630
        if (prebuilt->autoinc_error == DB_SUCCESS) {
 
7631
 
 
7632
                /* Determine the first value of the interval */
 
7633
                *value = dict_table_autoinc_read(prebuilt->table);
 
7634
 
 
7635
                /* It should have been initialized during open. */
 
7636
                ut_a(*value != 0);
 
7637
        }
 
7638
 
 
7639
        return(prebuilt->autoinc_error);
8429
7640
}
8430
7641
 
8431
7642
/*******************************************************************//**
8432
7643
This function reads the global auto-inc counter. It doesn't use the 
8433
7644
AUTOINC lock even if the lock mode is set to TRADITIONAL.
8434
 
@return the autoinc value */
 
7645
@return the autoinc value */
8435
7646
UNIV_INTERN
8436
7647
uint64_t
8437
7648
ha_innobase::innobase_peek_autoinc(void)
8438
7649
/*====================================*/
8439
7650
{
8440
 
  uint64_t  auto_inc;
8441
 
  dict_table_t* innodb_table;
8442
 
 
8443
 
  ut_a(prebuilt != NULL);
8444
 
  ut_a(prebuilt->table != NULL);
8445
 
 
8446
 
  innodb_table = prebuilt->table;
8447
 
 
8448
 
  dict_table_autoinc_lock(innodb_table);
8449
 
 
8450
 
  auto_inc = dict_table_autoinc_read(innodb_table);
8451
 
 
8452
 
  ut_a(auto_inc > 0);
8453
 
 
8454
 
  dict_table_autoinc_unlock(innodb_table);
8455
 
 
8456
 
  return(auto_inc);
 
7651
        uint64_t        auto_inc;
 
7652
        dict_table_t*   innodb_table;
 
7653
 
 
7654
        ut_a(prebuilt != NULL);
 
7655
        ut_a(prebuilt->table != NULL);
 
7656
 
 
7657
        innodb_table = prebuilt->table;
 
7658
 
 
7659
        dict_table_autoinc_lock(innodb_table);
 
7660
 
 
7661
        auto_inc = dict_table_autoinc_read(innodb_table);
 
7662
 
 
7663
        ut_a(auto_inc > 0);
 
7664
 
 
7665
        dict_table_autoinc_unlock(innodb_table);
 
7666
 
 
7667
        return(auto_inc);
8457
7668
}
8458
7669
 
8459
7670
/*********************************************************************//**
8467
7678
void
8468
7679
ha_innobase::get_auto_increment(
8469
7680
/*============================*/
8470
 
        uint64_t  offset,              /*!< in: table autoinc offset */
8471
 
        uint64_t  increment,           /*!< in: table autoinc increment */
8472
 
        uint64_t  nb_desired_values,   /*!< in: number of values reqd */
8473
 
        uint64_t  *first_value,        /*!< out: the autoinc value */
8474
 
        uint64_t  *nb_reserved_values) /*!< out: count of reserved values */
 
7681
        uint64_t        offset,              /*!< in: table autoinc offset */
 
7682
        uint64_t        increment,           /*!< in: table autoinc increment */
 
7683
        uint64_t        nb_desired_values,   /*!< in: number of values reqd */
 
7684
        uint64_t        *first_value,        /*!< out: the autoinc value */
 
7685
        uint64_t        *nb_reserved_values) /*!< out: count of reserved values */
8475
7686
{
8476
 
  trx_t*    trx;
8477
 
  ulint   error;
8478
 
  uint64_t  autoinc = 0;
8479
 
 
8480
 
  /* Prepare prebuilt->trx in the table handle */
8481
 
  update_session(getTable()->in_use);
8482
 
 
8483
 
  error = innobase_get_autoinc(&autoinc);
8484
 
 
8485
 
  if (error != DB_SUCCESS) {
8486
 
    *first_value = (~(uint64_t) 0);
8487
 
    return;
8488
 
  }
8489
 
 
8490
 
  /* This is a hack, since nb_desired_values seems to be accurate only
8491
 
  for the first call to get_auto_increment() for multi-row INSERT and
8492
 
  meaningless for other statements e.g, LOAD etc. Subsequent calls to
8493
 
  this method for the same statement results in different values which
8494
 
  don't make sense. Therefore we store the value the first time we are
8495
 
  called and count down from that as rows are written (see doInsertRecord()).
8496
 
  */
8497
 
 
8498
 
  trx = prebuilt->trx;
8499
 
 
8500
 
  /* Note: We can't rely on *first_value since some MySQL engines,
8501
 
  in particular the partition engine, don't initialize it to 0 when
8502
 
  invoking this method. So we are not sure if it's guaranteed to
8503
 
  be 0 or not. */
8504
 
 
8505
 
  /* We need the upper limit of the col type to check for
8506
 
     whether we update the table autoinc counter or not. */
8507
 
  uint64_t col_max_value = innobase_get_int_col_max_value(getTable()->next_number_field);
8508
 
 
8509
 
  /* Called for the first time ? */
8510
 
  if (trx->n_autoinc_rows == 0) {
8511
 
 
8512
 
    trx->n_autoinc_rows = (ulint) nb_desired_values;
8513
 
 
8514
 
    /* It's possible for nb_desired_values to be 0:
8515
 
    e.g., INSERT INTO T1(C) SELECT C FROM T2; */
8516
 
    if (nb_desired_values == 0) {
8517
 
 
8518
 
      trx->n_autoinc_rows = 1;
8519
 
    }
8520
 
 
8521
 
    set_if_bigger(*first_value, autoinc);
8522
 
  /* Not in the middle of a mult-row INSERT. */
8523
 
  } else if (prebuilt->autoinc_last_value == 0) {
8524
 
    set_if_bigger(*first_value, autoinc);
8525
 
    /* Check for -ve values. */
8526
 
  } else if (*first_value > col_max_value && trx->n_autoinc_rows > 0) {
8527
 
    /* Set to next logical value. */
8528
 
    ut_a(autoinc > trx->n_autoinc_rows);
8529
 
    *first_value = (autoinc - trx->n_autoinc_rows) - 1;
8530
 
  }
8531
 
 
8532
 
  *nb_reserved_values = trx->n_autoinc_rows;
8533
 
 
8534
 
  /* This all current style autoinc. */
8535
 
  {
8536
 
    uint64_t  need;
8537
 
    uint64_t  current;
8538
 
    uint64_t  next_value;
8539
 
 
8540
 
    current = *first_value > col_max_value ? autoinc : *first_value;
8541
 
    need = *nb_reserved_values * increment;
8542
 
 
8543
 
    /* Compute the last value in the interval */
8544
 
    next_value = innobase_next_autoinc(current, need, offset, col_max_value);
8545
 
 
8546
 
    prebuilt->autoinc_last_value = next_value;
8547
 
 
8548
 
    if (prebuilt->autoinc_last_value < *first_value) {
8549
 
      *first_value = (~(unsigned long long) 0);
8550
 
    } else {
8551
 
      /* Update the table autoinc variable */
8552
 
      dict_table_autoinc_update_if_greater(
8553
 
        prebuilt->table, prebuilt->autoinc_last_value);
8554
 
    }
8555
 
  }
8556
 
 
8557
 
  /* The increment to be used to increase the AUTOINC value, we use
8558
 
  this in doInsertRecord() and doUpdateRecord() to increase the autoinc counter
8559
 
  for columns that are filled by the user. We need the offset and
8560
 
  the increment. */
8561
 
  prebuilt->autoinc_offset = offset;
8562
 
  prebuilt->autoinc_increment = increment;
8563
 
 
8564
 
  dict_table_autoinc_unlock(prebuilt->table);
 
7687
        trx_t*          trx;
 
7688
        ulint           error;
 
7689
        uint64_t        autoinc = 0;
 
7690
 
 
7691
        /* Prepare prebuilt->trx in the table handle */
 
7692
        update_session(ha_session());
 
7693
 
 
7694
        error = innobase_get_autoinc(&autoinc);
 
7695
 
 
7696
        if (error != DB_SUCCESS) {
 
7697
                *first_value = (~(uint64_t) 0);
 
7698
                return;
 
7699
        }
 
7700
 
 
7701
        /* This is a hack, since nb_desired_values seems to be accurate only
 
7702
        for the first call to get_auto_increment() for multi-row INSERT and
 
7703
        meaningless for other statements e.g, LOAD etc. Subsequent calls to
 
7704
        this method for the same statement results in different values which
 
7705
        don't make sense. Therefore we store the value the first time we are
 
7706
        called and count down from that as rows are written (see write_row()).
 
7707
        */
 
7708
 
 
7709
        trx = prebuilt->trx;
 
7710
 
 
7711
        /* Note: We can't rely on *first_value since some MySQL engines,
 
7712
        in particular the partition engine, don't initialize it to 0 when
 
7713
        invoking this method. So we are not sure if it's guaranteed to
 
7714
        be 0 or not. */
 
7715
 
 
7716
        /* Called for the first time ? */
 
7717
        if (trx->n_autoinc_rows == 0) {
 
7718
 
 
7719
                trx->n_autoinc_rows = (ulint) nb_desired_values;
 
7720
 
 
7721
                /* It's possible for nb_desired_values to be 0:
 
7722
                e.g., INSERT INTO T1(C) SELECT C FROM T2; */
 
7723
                if (nb_desired_values == 0) {
 
7724
 
 
7725
                        trx->n_autoinc_rows = 1;
 
7726
                }
 
7727
 
 
7728
                set_if_bigger(*first_value, autoinc);
 
7729
        /* Not in the middle of a mult-row INSERT. */
 
7730
        } else if (prebuilt->autoinc_last_value == 0) {
 
7731
                set_if_bigger(*first_value, autoinc);
 
7732
        }
 
7733
 
 
7734
        *nb_reserved_values = trx->n_autoinc_rows;
 
7735
 
 
7736
        /* With old style AUTOINC locking we only update the table's
 
7737
        AUTOINC counter after attempting to insert the row. */
 
7738
        if (innobase_autoinc_lock_mode != AUTOINC_OLD_STYLE_LOCKING) {
 
7739
                uint64_t        need;
 
7740
                uint64_t        next_value;
 
7741
                uint64_t        col_max_value;
 
7742
 
 
7743
                /* We need the upper limit of the col type to check for
 
7744
                whether we update the table autoinc counter or not. */
 
7745
                col_max_value = innobase_get_int_col_max_value(
 
7746
                        table->next_number_field);
 
7747
 
 
7748
                need = *nb_reserved_values * increment;
 
7749
 
 
7750
                /* Compute the last value in the interval */
 
7751
                next_value = innobase_next_autoinc(
 
7752
                        *first_value, need, offset, col_max_value);
 
7753
 
 
7754
                prebuilt->autoinc_last_value = next_value;
 
7755
 
 
7756
                if (prebuilt->autoinc_last_value < *first_value) {
 
7757
                        *first_value = (~(unsigned long long) 0);
 
7758
                } else {
 
7759
                        /* Update the table autoinc variable */
 
7760
                        dict_table_autoinc_update_if_greater(
 
7761
                                prebuilt->table, prebuilt->autoinc_last_value);
 
7762
                }
 
7763
        } else {
 
7764
                /* This will force write_row() into attempting an update
 
7765
                of the table's AUTOINC counter. */
 
7766
                prebuilt->autoinc_last_value = 0;
 
7767
        }
 
7768
 
 
7769
        /* The increment to be used to increase the AUTOINC value, we use
 
7770
        this in write_row() and update_row() to increase the autoinc counter
 
7771
        for columns that are filled by the user. We need the offset and
 
7772
        the increment. */
 
7773
        prebuilt->autoinc_offset = offset;
 
7774
        prebuilt->autoinc_increment = increment;
 
7775
 
 
7776
        dict_table_autoinc_unlock(prebuilt->table);
8565
7777
}
8566
7778
 
8567
7779
/*******************************************************************//**
8569
7781
inserted will get the given value. This is called e.g. after TRUNCATE
8570
7782
is emulated by doing a 'DELETE FROM t'. HA_ERR_WRONG_COMMAND is
8571
7783
returned by storage engines that don't support this operation.
8572
 
@return 0 or error code */
 
7784
@return 0 or error code */
8573
7785
UNIV_INTERN
8574
7786
int
8575
7787
ha_innobase::reset_auto_increment(
8576
7788
/*==============================*/
8577
 
  uint64_t  value)    /*!< in: new value for table autoinc */
 
7789
        uint64_t        value)          /*!< in: new value for table autoinc */
8578
7790
{
8579
 
  int error;
8580
 
 
8581
 
  update_session(getTable()->in_use);
8582
 
 
8583
 
  error = row_lock_table_autoinc_for_mysql(prebuilt);
8584
 
 
8585
 
  if (error != DB_SUCCESS) {
8586
 
    error = convert_error_code_to_mysql(error,
8587
 
                prebuilt->table->flags,
8588
 
                user_session);
8589
 
 
8590
 
    return(error);
8591
 
  }
8592
 
 
8593
 
  /* The next value can never be 0. */
8594
 
  if (value == 0) {
8595
 
    value = 1;
8596
 
  }
8597
 
 
8598
 
  innobase_reset_autoinc(value);
8599
 
 
8600
 
  return 0;
 
7791
        int     error;
 
7792
 
 
7793
        update_session(ha_session());
 
7794
 
 
7795
        error = row_lock_table_autoinc_for_mysql(prebuilt);
 
7796
 
 
7797
        if (error != DB_SUCCESS) {
 
7798
                error = convert_error_code_to_mysql(error,
 
7799
                                                    prebuilt->table->flags,
 
7800
                                                    user_session);
 
7801
 
 
7802
                return(error);
 
7803
        }
 
7804
 
 
7805
        /* The next value can never be 0. */
 
7806
        if (value == 0) {
 
7807
                value = 1;
 
7808
        }
 
7809
 
 
7810
        innobase_reset_autoinc(value);
 
7811
 
 
7812
        return 0;
8601
7813
}
8602
7814
 
8603
7815
/* See comment in Cursor.cc */
8605
7817
bool
8606
7818
InnobaseEngine::get_error_message(int, String *buf)
8607
7819
{
8608
 
  trx_t*  trx = check_trx_exists(current_session);
8609
 
 
8610
 
  buf->copy(trx->detailed_error, (uint) strlen(trx->detailed_error),
8611
 
    system_charset_info);
8612
 
 
8613
 
  return(FALSE);
 
7820
        trx_t*  trx = check_trx_exists(current_session);
 
7821
 
 
7822
        buf->copy(trx->detailed_error, (uint) strlen(trx->detailed_error),
 
7823
                system_charset_info);
 
7824
 
 
7825
        return(FALSE);
8614
7826
}
8615
7827
 
8616
7828
/*******************************************************************//**
8617
7829
Compares two 'refs'. A 'ref' is the (internal) primary key value of the row.
8618
7830
If there is no explicitly declared non-null unique key or a primary key, then
8619
7831
InnoDB internally uses the row id as the primary key.
8620
 
@return < 0 if ref1 < ref2, 0 if equal, else > 0 */
 
7832
@return < 0 if ref1 < ref2, 0 if equal, else > 0 */
8621
7833
UNIV_INTERN
8622
7834
int
8623
7835
ha_innobase::cmp_ref(
8624
7836
/*=================*/
8625
 
  const unsigned char*  ref1, /*!< in: an (internal) primary key value in the
8626
 
        MySQL key value format */
8627
 
  const unsigned char*  ref2) /*!< in: an (internal) primary key value in the
8628
 
        MySQL key value format */
 
7837
        const unsigned char*    ref1,   /*!< in: an (internal) primary key value in the
 
7838
                                MySQL key value format */
 
7839
        const unsigned char*    ref2)   /*!< in: an (internal) primary key value in the
 
7840
                                MySQL key value format */
8629
7841
{
8630
 
  enum_field_types mysql_type;
8631
 
  Field*    field;
8632
 
  KeyPartInfo*  key_part;
8633
 
  KeyPartInfo*  key_part_end;
8634
 
  uint    len1;
8635
 
  uint    len2;
8636
 
  int   result;
8637
 
 
8638
 
  if (prebuilt->clust_index_was_generated) {
8639
 
    /* The 'ref' is an InnoDB row id */
8640
 
 
8641
 
    return(memcmp(ref1, ref2, DATA_ROW_ID_LEN));
8642
 
  }
8643
 
 
8644
 
  /* Do a type-aware comparison of primary key fields. PK fields
8645
 
  are always NOT NULL, so no checks for NULL are performed. */
8646
 
 
8647
 
  key_part = getTable()->key_info[getTable()->getShare()->getPrimaryKey()].key_part;
8648
 
 
8649
 
  key_part_end = key_part
8650
 
      + getTable()->key_info[getTable()->getShare()->getPrimaryKey()].key_parts;
8651
 
 
8652
 
  for (; key_part != key_part_end; ++key_part) {
8653
 
    field = key_part->field;
8654
 
    mysql_type = field->type();
8655
 
 
8656
 
    if (mysql_type == DRIZZLE_TYPE_BLOB) {
8657
 
 
8658
 
      /* In the MySQL key value format, a column prefix of
8659
 
      a BLOB is preceded by a 2-byte length field */
8660
 
 
8661
 
      len1 = innobase_read_from_2_little_endian(ref1);
8662
 
      len2 = innobase_read_from_2_little_endian(ref2);
8663
 
 
8664
 
      ref1 += 2;
8665
 
      ref2 += 2;
8666
 
      result = ((Field_blob*)field)->cmp( ref1, len1,
 
7842
        enum_field_types mysql_type;
 
7843
        Field*          field;
 
7844
        KEY_PART_INFO*  key_part;
 
7845
        KEY_PART_INFO*  key_part_end;
 
7846
        uint            len1;
 
7847
        uint            len2;
 
7848
        int             result;
 
7849
 
 
7850
        if (prebuilt->clust_index_was_generated) {
 
7851
                /* The 'ref' is an InnoDB row id */
 
7852
 
 
7853
                return(memcmp(ref1, ref2, DATA_ROW_ID_LEN));
 
7854
        }
 
7855
 
 
7856
        /* Do a type-aware comparison of primary key fields. PK fields
 
7857
        are always NOT NULL, so no checks for NULL are performed. */
 
7858
 
 
7859
        key_part = table->key_info[table->s->primary_key].key_part;
 
7860
 
 
7861
        key_part_end = key_part
 
7862
                        + table->key_info[table->s->primary_key].key_parts;
 
7863
 
 
7864
        for (; key_part != key_part_end; ++key_part) {
 
7865
                field = key_part->field;
 
7866
                mysql_type = field->type();
 
7867
 
 
7868
                if (mysql_type == DRIZZLE_TYPE_BLOB) {
 
7869
 
 
7870
                        /* In the MySQL key value format, a column prefix of
 
7871
                        a BLOB is preceded by a 2-byte length field */
 
7872
 
 
7873
                        len1 = innobase_read_from_2_little_endian(ref1);
 
7874
                        len2 = innobase_read_from_2_little_endian(ref2);
 
7875
 
 
7876
                        ref1 += 2;
 
7877
                        ref2 += 2;
 
7878
                        result = ((Field_blob*)field)->cmp( ref1, len1,
8667
7879
                                                            ref2, len2);
8668
 
    } else {
8669
 
      result = field->key_cmp(ref1, ref2);
8670
 
    }
8671
 
 
8672
 
    if (result) {
8673
 
 
8674
 
      return(result);
8675
 
    }
8676
 
 
8677
 
    ref1 += key_part->store_length;
8678
 
    ref2 += key_part->store_length;
8679
 
  }
8680
 
 
8681
 
  return(0);
 
7880
                } else {
 
7881
                        result = field->key_cmp(ref1, ref2);
 
7882
                }
 
7883
 
 
7884
                if (result) {
 
7885
 
 
7886
                        return(result);
 
7887
                }
 
7888
 
 
7889
                ref1 += key_part->store_length;
 
7890
                ref2 += key_part->store_length;
 
7891
        }
 
7892
 
 
7893
        return(0);
8682
7894
}
8683
7895
 
8684
7896
/**********************************************************************
8686
7898
characters for prefix indexes using a multibyte character set. The function
8687
7899
finds charset information and returns length of prefix_len characters in the
8688
7900
index field in bytes.
8689
 
@return number of bytes occupied by the first n characters */
 
7901
@return number of bytes occupied by the first n characters */
8690
7902
extern "C" UNIV_INTERN
8691
7903
ulint
8692
7904
innobase_get_at_most_n_mbchars(
8693
7905
/*===========================*/
8694
 
  ulint charset_id, /*!< in: character set id */
8695
 
  ulint prefix_len, /*!< in: prefix length in bytes of the index
8696
 
        (this has to be divided by mbmaxlen to get the
8697
 
        number of CHARACTERS n in the prefix) */
8698
 
  ulint data_len,   /*!< in: length of the string in bytes */
8699
 
  const char* str); /*!< in: character string */
 
7906
        ulint charset_id,       /*!< in: character set id */
 
7907
        ulint prefix_len,       /*!< in: prefix length in bytes of the index
 
7908
                                (this has to be divided by mbmaxlen to get the
 
7909
                                number of CHARACTERS n in the prefix) */
 
7910
        ulint data_len,         /*!< in: length of the string in bytes */
 
7911
        const char* str);       /*!< in: character string */
8700
7912
 
8701
7913
ulint
8702
7914
innobase_get_at_most_n_mbchars(
8703
7915
/*===========================*/
8704
 
  ulint charset_id, /*!< in: character set id */
8705
 
  ulint prefix_len, /*!< in: prefix length in bytes of the index
8706
 
        (this has to be divided by mbmaxlen to get the
8707
 
        number of CHARACTERS n in the prefix) */
8708
 
  ulint data_len,   /*!< in: length of the string in bytes */
8709
 
  const char* str)  /*!< in: character string */
 
7916
        ulint charset_id,       /*!< in: character set id */
 
7917
        ulint prefix_len,       /*!< in: prefix length in bytes of the index
 
7918
                                (this has to be divided by mbmaxlen to get the
 
7919
                                number of CHARACTERS n in the prefix) */
 
7920
        ulint data_len,         /*!< in: length of the string in bytes */
 
7921
        const char* str)        /*!< in: character string */
8710
7922
{
8711
 
  ulint char_length;    /*!< character length in bytes */
8712
 
  ulint n_chars;      /*!< number of characters in prefix */
8713
 
  const CHARSET_INFO* charset;  /*!< charset used in the field */
8714
 
 
8715
 
  charset = get_charset((uint) charset_id);
8716
 
 
8717
 
  ut_ad(charset);
8718
 
  ut_ad(charset->mbmaxlen);
8719
 
 
8720
 
  /* Calculate how many characters at most the prefix index contains */
8721
 
 
8722
 
  n_chars = prefix_len / charset->mbmaxlen;
8723
 
 
8724
 
  /* If the charset is multi-byte, then we must find the length of the
8725
 
  first at most n chars in the string. If the string contains less
8726
 
  characters than n, then we return the length to the end of the last
8727
 
  character. */
8728
 
 
8729
 
  if (charset->mbmaxlen > 1) {
8730
 
    /* my_charpos() returns the byte length of the first n_chars
8731
 
    characters, or a value bigger than the length of str, if
8732
 
    there were not enough full characters in str.
8733
 
 
8734
 
    Why does the code below work:
8735
 
    Suppose that we are looking for n UTF-8 characters.
8736
 
 
8737
 
    1) If the string is long enough, then the prefix contains at
8738
 
    least n complete UTF-8 characters + maybe some extra
8739
 
    characters + an incomplete UTF-8 character. No problem in
8740
 
    this case. The function returns the pointer to the
8741
 
    end of the nth character.
8742
 
 
8743
 
    2) If the string is not long enough, then the string contains
8744
 
    the complete value of a column, that is, only complete UTF-8
8745
 
    characters, and we can store in the column prefix index the
8746
 
    whole string. */
8747
 
 
8748
 
    char_length = my_charpos(charset, str,
8749
 
            str + data_len, (int) n_chars);
8750
 
    if (char_length > data_len) {
8751
 
      char_length = data_len;
8752
 
    }
8753
 
  } else {
8754
 
    if (data_len < prefix_len) {
8755
 
      char_length = data_len;
8756
 
    } else {
8757
 
      char_length = prefix_len;
8758
 
    }
8759
 
  }
8760
 
 
8761
 
  return(char_length);
 
7923
        ulint char_length;              /*!< character length in bytes */
 
7924
        ulint n_chars;                  /*!< number of characters in prefix */
 
7925
        const CHARSET_INFO* charset;    /*!< charset used in the field */
 
7926
 
 
7927
        charset = get_charset((uint) charset_id);
 
7928
 
 
7929
        ut_ad(charset);
 
7930
        ut_ad(charset->mbmaxlen);
 
7931
 
 
7932
        /* Calculate how many characters at most the prefix index contains */
 
7933
 
 
7934
        n_chars = prefix_len / charset->mbmaxlen;
 
7935
 
 
7936
        /* If the charset is multi-byte, then we must find the length of the
 
7937
        first at most n chars in the string. If the string contains less
 
7938
        characters than n, then we return the length to the end of the last
 
7939
        character. */
 
7940
 
 
7941
        if (charset->mbmaxlen > 1) {
 
7942
                /* my_charpos() returns the byte length of the first n_chars
 
7943
                characters, or a value bigger than the length of str, if
 
7944
                there were not enough full characters in str.
 
7945
 
 
7946
                Why does the code below work:
 
7947
                Suppose that we are looking for n UTF-8 characters.
 
7948
 
 
7949
                1) If the string is long enough, then the prefix contains at
 
7950
                least n complete UTF-8 characters + maybe some extra
 
7951
                characters + an incomplete UTF-8 character. No problem in
 
7952
                this case. The function returns the pointer to the
 
7953
                end of the nth character.
 
7954
 
 
7955
                2) If the string is not long enough, then the string contains
 
7956
                the complete value of a column, that is, only complete UTF-8
 
7957
                characters, and we can store in the column prefix index the
 
7958
                whole string. */
 
7959
 
 
7960
                char_length = my_charpos(charset, str,
 
7961
                                                str + data_len, (int) n_chars);
 
7962
                if (char_length > data_len) {
 
7963
                        char_length = data_len;
 
7964
                }
 
7965
        } else {
 
7966
                if (data_len < prefix_len) {
 
7967
                        char_length = data_len;
 
7968
                } else {
 
7969
                        char_length = prefix_len;
 
7970
                }
 
7971
        }
 
7972
 
 
7973
        return(char_length);
8762
7974
}
8763
7975
/**
8764
7976
 * We will also use this function to communicate
8768
7980
 */
8769
7981
void
8770
7982
InnobaseEngine::doStartStatement(
8771
 
  Session *session) /*!< in: handle to the Drizzle session */
 
7983
        Session *session) /*!< in: handle to the Drizzle session */
8772
7984
{
8773
7985
  /* 
8774
7986
   * Create the InnoDB transaction structure
8775
7987
   * for the session
8776
7988
   */
8777
 
  trx_t *trx= check_trx_exists(session);
 
7989
        trx_t *trx= check_trx_exists(session);
8778
7990
 
8779
7991
  /* "reset" the error message for the transaction */
8780
7992
  trx->detailed_error[0]= '\0';
8781
7993
 
8782
 
  /* Set the isolation level of the transaction. */
8783
 
  trx->isolation_level= innobase_map_isolation_level(session_tx_isolation(session));
 
7994
        /* Set the isolation level of the transaction. */
 
7995
  trx->isolation_level= innobase_map_isolation_level((enum_tx_isolation) session_tx_isolation(session));
 
7996
 
 
7997
  /* 
 
7998
   * Set the Drizzle flag to mark that there is an active
 
7999
   * transaction.
 
8000
   *
 
8001
   * @todo this should go away
 
8002
   */
 
8003
  if (trx->active_trans == 0) {
 
8004
    trx->active_trans= 1;
 
8005
  }
8784
8006
}
8785
8007
 
8786
8008
void
8795
8017
 
8796
8018
  innobase_release_stat_resources(trx);
8797
8019
 
 
8020
  if (! session_test_options(session, OPTION_NOT_AUTOCOMMIT | OPTION_BEGIN))
 
8021
  {
 
8022
    if (trx->active_trans != 0)
 
8023
    {
 
8024
      commit(session, TRUE);
 
8025
      trx->active_trans= 0;
 
8026
    }
 
8027
  }
 
8028
  else
 
8029
  {
 
8030
    if (trx->isolation_level <= TRX_ISO_READ_COMMITTED &&
 
8031
        trx->global_read_view)
 
8032
    {
 
8033
      /* At low transaction isolation levels we let
 
8034
      each consistent read set its own snapshot */
 
8035
      read_view_close_for_mysql(trx);
 
8036
    }
 
8037
  }
8798
8038
}
8799
8039
 
8800
8040
/*******************************************************************//**
8801
8041
This function is used to prepare an X/Open XA distributed transaction.
8802
 
@return 0 or error number */
 
8042
@return 0 or error number */
8803
8043
int
8804
 
InnobaseEngine::doXaPrepare(
 
8044
InnobaseEngine::doPrepare(
8805
8045
/*================*/
8806
 
  Session*  session,/*!< in: handle to the MySQL thread of
8807
 
        the user whose XA transaction should
8808
 
        be prepared */
8809
 
  bool    all)  /*!< in: TRUE - commit transaction
8810
 
        FALSE - the current SQL statement
8811
 
        ended */
8812
 
{
8813
 
  int error = 0;
8814
 
  trx_t* trx = check_trx_exists(session);
8815
 
 
8816
 
  assert(this == innodb_engine_ptr);
8817
 
 
8818
 
  /* we use support_xa value as it was seen at transaction start
8819
 
  time, not the current session variable value. Any possible changes
8820
 
  to the session variable take effect only in the next transaction */
8821
 
  if (!trx->support_xa) {
8822
 
 
8823
 
    return(0);
8824
 
  }
8825
 
 
8826
 
  session->get_xid(reinterpret_cast<DRIZZLE_XID*>(&trx->xid));
8827
 
 
8828
 
  /* Release a possible FIFO ticket and search latch. Since we will
8829
 
  reserve the kernel mutex, we have to release the search system latch
8830
 
  first to obey the latching order. */
8831
 
 
8832
 
  innobase_release_stat_resources(trx);
8833
 
 
8834
 
  if (all
8835
 
    || (!session_test_options(session, OPTION_NOT_AUTOCOMMIT | OPTION_BEGIN))) {
8836
 
 
8837
 
    /* We were instructed to prepare the whole transaction, or
8838
 
    this is an SQL statement end and autocommit is on */
8839
 
 
8840
 
    ut_ad(trx->conc_state != TRX_NOT_STARTED);
8841
 
 
8842
 
    error = (int) trx_prepare_for_mysql(trx);
8843
 
  } else {
8844
 
    /* We just mark the SQL statement ended and do not do a
8845
 
    transaction prepare */
8846
 
 
8847
 
    /* If we had reserved the auto-inc lock for some
8848
 
    table in this SQL statement we release it now */
8849
 
 
8850
 
    row_unlock_table_autoinc_for_mysql(trx);
8851
 
 
8852
 
    /* Store the current undo_no of the transaction so that we
8853
 
    know where to roll back if we have to roll back the next
8854
 
    SQL statement */
8855
 
 
8856
 
    trx_mark_sql_stat_end(trx);
8857
 
  }
8858
 
 
8859
 
  /* Tell the InnoDB server that there might be work for utility
8860
 
  threads: */
8861
 
 
8862
 
  srv_active_wake_master_thread();
8863
 
 
8864
 
  return(error);
8865
 
}
8866
 
 
8867
 
uint64_t InnobaseEngine::doGetCurrentTransactionId(Session *session)
8868
 
{
8869
 
  trx_t *trx= session_to_trx(session);
8870
 
  return (ib_uint64_t) ut_conv_dulint_to_longlong(trx->id);
8871
 
}
8872
 
 
8873
 
uint64_t InnobaseEngine::doGetNewTransactionId(Session *session)
8874
 
{
8875
 
  trx_t*& trx = session_to_trx(session);
8876
 
 
8877
 
  if (trx == NULL)
8878
 
  {
8879
 
    trx = innobase_trx_allocate(session);
8880
 
 
8881
 
    innobase_trx_init(session, trx);
8882
 
  }
8883
 
 
8884
 
  mutex_enter(&kernel_mutex);
8885
 
  trx->id= trx_sys_get_new_trx_id();
8886
 
  mutex_exit(&kernel_mutex);
8887
 
 
8888
 
  uint64_t transaction_id= (ib_uint64_t) ut_conv_dulint_to_longlong(trx->id);
8889
 
 
8890
 
  return transaction_id;
 
8046
        Session*        session,/*!< in: handle to the MySQL thread of
 
8047
                                the user whose XA transaction should
 
8048
                                be prepared */
 
8049
        bool            all)    /*!< in: TRUE - commit transaction
 
8050
                                FALSE - the current SQL statement
 
8051
                                ended */
 
8052
{
 
8053
        int error = 0;
 
8054
        trx_t* trx = check_trx_exists(session);
 
8055
 
 
8056
        assert(this == innodb_engine_ptr);
 
8057
 
 
8058
        /* we use support_xa value as it was seen at transaction start
 
8059
        time, not the current session variable value. Any possible changes
 
8060
        to the session variable take effect only in the next transaction */
 
8061
        if (!trx->support_xa) {
 
8062
 
 
8063
                return(0);
 
8064
        }
 
8065
 
 
8066
        session_get_xid(session, reinterpret_cast<DRIZZLE_XID*>(&trx->xid));
 
8067
 
 
8068
        /* Release a possible FIFO ticket and search latch. Since we will
 
8069
        reserve the kernel mutex, we have to release the search system latch
 
8070
        first to obey the latching order. */
 
8071
 
 
8072
        innobase_release_stat_resources(trx);
 
8073
 
 
8074
        if (trx->active_trans == 0 && trx->conc_state != TRX_NOT_STARTED) {
 
8075
 
 
8076
          errmsg_printf(ERRMSG_LVL_ERROR,
 
8077
                        "trx->active_trans == 0, but trx->conc_state != "
 
8078
                        "TRX_NOT_STARTED");
 
8079
        }
 
8080
 
 
8081
        if (all
 
8082
                || (!session_test_options(session, OPTION_NOT_AUTOCOMMIT | OPTION_BEGIN))) {
 
8083
 
 
8084
                /* We were instructed to prepare the whole transaction, or
 
8085
                this is an SQL statement end and autocommit is on */
 
8086
 
 
8087
                ut_ad(trx->active_trans);
 
8088
 
 
8089
                error = (int) trx_prepare_for_mysql(trx);
 
8090
        } else {
 
8091
                /* We just mark the SQL statement ended and do not do a
 
8092
                transaction prepare */
 
8093
 
 
8094
                /* If we had reserved the auto-inc lock for some
 
8095
                table in this SQL statement we release it now */
 
8096
 
 
8097
                row_unlock_table_autoinc_for_mysql(trx);
 
8098
 
 
8099
                /* Store the current undo_no of the transaction so that we
 
8100
                know where to roll back if we have to roll back the next
 
8101
                SQL statement */
 
8102
 
 
8103
                trx_mark_sql_stat_end(trx);
 
8104
        }
 
8105
 
 
8106
        /* Tell the InnoDB server that there might be work for utility
 
8107
        threads: */
 
8108
 
 
8109
        srv_active_wake_master_thread();
 
8110
 
 
8111
        if (all || !session_test_options(session, OPTION_NOT_AUTOCOMMIT | OPTION_BEGIN))
 
8112
        {
 
8113
 
 
8114
                /* For ibbackup to work the order of transactions in binlog
 
8115
                and InnoDB must be the same. Consider the situation
 
8116
 
 
8117
                  thread1> prepare; write to binlog; ...
 
8118
                          <context switch>
 
8119
                  thread2> prepare; write to binlog; commit
 
8120
                  thread1>                           ... commit
 
8121
 
 
8122
                To ensure this will not happen we're taking the mutex on
 
8123
                prepare, and releasing it on commit.
 
8124
 
 
8125
                Note: only do it for normal commits, done via ha_commit_trans.
 
8126
                If 2pc protocol is executed by external transaction
 
8127
                coordinator, it will be just a regular MySQL client
 
8128
                executing XA PREPARE and XA COMMIT commands.
 
8129
                In this case we cannot know how many minutes or hours
 
8130
                will be between XA PREPARE and XA COMMIT, and we don't want
 
8131
                to block for undefined period of time.
 
8132
                */
 
8133
                pthread_mutex_lock(&prepare_commit_mutex);
 
8134
                trx->active_trans = 2;
 
8135
        }
 
8136
        return(error);
8891
8137
}
8892
8138
 
8893
8139
/*******************************************************************//**
8894
8140
This function is used to recover X/Open XA distributed transactions.
8895
 
@return number of prepared transactions stored in xid_list */
 
8141
@return number of prepared transactions stored in xid_list */
8896
8142
int
8897
 
InnobaseEngine::doXaRecover(
 
8143
InnobaseEngine::doRecover(
8898
8144
/*================*/
8899
 
  ::drizzled::XID*  xid_list,/*!< in/out: prepared transactions */
8900
 
  size_t len) /*!< in: number of slots in xid_list */
 
8145
        ::drizzled::XID*        xid_list,/*!< in/out: prepared transactions */
 
8146
        size_t len)     /*!< in: number of slots in xid_list */
8901
8147
{
8902
 
  assert(this == innodb_engine_ptr);
8903
 
 
8904
 
  if (len == 0 || xid_list == NULL) {
8905
 
 
8906
 
    return(0);
8907
 
  }
8908
 
 
8909
 
  return(trx_recover_for_mysql((::XID *)xid_list, len));
 
8148
        assert(this == innodb_engine_ptr);
 
8149
 
 
8150
        if (len == 0 || xid_list == NULL) {
 
8151
 
 
8152
                return(0);
 
8153
        }
 
8154
 
 
8155
        return(trx_recover_for_mysql((::XID *)xid_list, len));
8910
8156
}
8911
8157
 
8912
8158
/*******************************************************************//**
8913
8159
This function is used to commit one X/Open XA distributed transaction
8914
8160
which is in the prepared state
8915
 
@return 0 or error number */
 
8161
@return 0 or error number */
8916
8162
int
8917
 
InnobaseEngine::doXaCommitXid(
 
8163
InnobaseEngine::doCommitXid(
8918
8164
/*===================*/
8919
 
  ::drizzled::XID*  xid)  /*!< in: X/Open XA transaction identification */
 
8165
        ::drizzled::XID*        xid)    /*!< in: X/Open XA transaction identification */
8920
8166
{
8921
 
  trx_t*  trx;
8922
 
 
8923
 
  assert(this == innodb_engine_ptr);
8924
 
 
8925
 
  trx = trx_get_trx_by_xid((::XID *)xid);
8926
 
 
8927
 
  if (trx) {
8928
 
    innobase_commit_low(trx);
8929
 
 
8930
 
    return(XA_OK);
8931
 
  } else {
8932
 
    return(XAER_NOTA);
8933
 
  }
 
8167
        trx_t*  trx;
 
8168
 
 
8169
        assert(this == innodb_engine_ptr);
 
8170
 
 
8171
        trx = trx_get_trx_by_xid((::XID *)xid);
 
8172
 
 
8173
        if (trx) {
 
8174
                innobase_commit_low(trx);
 
8175
 
 
8176
                return(XA_OK);
 
8177
        } else {
 
8178
                return(XAER_NOTA);
 
8179
        }
8934
8180
}
8935
8181
 
8936
8182
/*******************************************************************//**
8937
8183
This function is used to rollback one X/Open XA distributed transaction
8938
8184
which is in the prepared state
8939
 
@return 0 or error number */
 
8185
@return 0 or error number */
8940
8186
int
8941
 
InnobaseEngine::doXaRollbackXid(
 
8187
InnobaseEngine::doRollbackXid(
8942
8188
/*=====================*/
8943
 
  ::drizzled::XID*    xid)  /*!< in: X/Open XA transaction
8944
 
        identification */
 
8189
        ::drizzled::XID*                xid)    /*!< in: X/Open XA transaction
 
8190
                                identification */
8945
8191
{
8946
 
  trx_t*  trx;
8947
 
 
8948
 
  assert(this == innodb_engine_ptr);
8949
 
 
8950
 
  trx = trx_get_trx_by_xid((::XID *)xid);
8951
 
 
8952
 
  if (trx) {
8953
 
    return(innobase_rollback_trx(trx));
8954
 
  } else {
8955
 
    return(XAER_NOTA);
8956
 
  }
 
8192
        trx_t*  trx;
 
8193
 
 
8194
        assert(this == innodb_engine_ptr);
 
8195
 
 
8196
        trx = trx_get_trx_by_xid((::XID *)xid);
 
8197
 
 
8198
        if (trx) {
 
8199
                return(innobase_rollback_trx(trx));
 
8200
        } else {
 
8201
                return(XAER_NOTA);
 
8202
        }
8957
8203
}
8958
8204
 
8959
8205
 
8960
8206
/************************************************************//**
8961
8207
Validate the file format name and return its corresponding id.
8962
 
@return valid file format id */
 
8208
@return valid file format id */
8963
8209
static
8964
8210
uint
8965
8211
innobase_file_format_name_lookup(
8966
8212
/*=============================*/
8967
 
  const char* format_name)  /*!< in: pointer to file format name */
 
8213
        const char*     format_name)    /*!< in: pointer to file format name */
8968
8214
{
8969
 
  char* endp;
8970
 
  uint  format_id;
8971
 
 
8972
 
  ut_a(format_name != NULL);
8973
 
 
8974
 
  /* The format name can contain the format id itself instead of
8975
 
  the name and we check for that. */
8976
 
  format_id = (uint) strtoul(format_name, &endp, 10);
8977
 
 
8978
 
  /* Check for valid parse. */
8979
 
  if (*endp == '\0' && *format_name != '\0') {
8980
 
 
8981
 
    if (format_id <= DICT_TF_FORMAT_MAX) {
8982
 
 
8983
 
      return(format_id);
8984
 
    }
8985
 
  } else {
8986
 
 
8987
 
    for (format_id = 0; format_id <= DICT_TF_FORMAT_MAX;
8988
 
         format_id++) {
8989
 
      const char* name;
8990
 
 
8991
 
      name = trx_sys_file_format_id_to_name(format_id);
8992
 
 
8993
 
      if (!innobase_strcasecmp(format_name, name)) {
8994
 
 
8995
 
        return(format_id);
8996
 
      }
8997
 
    }
8998
 
  }
8999
 
 
9000
 
  return(DICT_TF_FORMAT_MAX + 1);
 
8215
        char*   endp;
 
8216
        uint    format_id;
 
8217
 
 
8218
        ut_a(format_name != NULL);
 
8219
 
 
8220
        /* The format name can contain the format id itself instead of
 
8221
        the name and we check for that. */
 
8222
        format_id = (uint) strtoul(format_name, &endp, 10);
 
8223
 
 
8224
        /* Check for valid parse. */
 
8225
        if (*endp == '\0' && *format_name != '\0') {
 
8226
 
 
8227
                if (format_id <= DICT_TF_FORMAT_MAX) {
 
8228
 
 
8229
                        return(format_id);
 
8230
                }
 
8231
        } else {
 
8232
 
 
8233
                for (format_id = 0; format_id <= DICT_TF_FORMAT_MAX;
 
8234
                     format_id++) {
 
8235
                        const char*     name;
 
8236
 
 
8237
                        name = trx_sys_file_format_id_to_name(format_id);
 
8238
 
 
8239
                        if (!innobase_strcasecmp(format_name, name)) {
 
8240
 
 
8241
                                return(format_id);
 
8242
                        }
 
8243
                }
 
8244
        }
 
8245
 
 
8246
        return(DICT_TF_FORMAT_MAX + 1);
9001
8247
}
9002
8248
 
9003
8249
/************************************************************//**
9004
8250
Validate the file format check value, is it one of "on" or "off",
9005
8251
as a side effect it sets the srv_check_file_format_at_startup variable.
9006
 
@return true if config value one of "on" or  "off" */
 
8252
@return true if config value one of "on" or  "off" */
9007
8253
static
9008
8254
bool
9009
8255
innobase_file_format_check_on_off(
9010
8256
/*==============================*/
9011
 
  const char* format_check) /*!< in: parameter value */
 
8257
        const char*     format_check)   /*!< in: parameter value */
9012
8258
{
9013
 
  bool    ret = true;
9014
 
 
9015
 
  if (!innobase_strcasecmp(format_check, "off")) {
9016
 
 
9017
 
    /* Set the value to disable checking. */
9018
 
    srv_check_file_format_at_startup = DICT_TF_FORMAT_MAX + 1;
9019
 
 
9020
 
  } else if (!innobase_strcasecmp(format_check, "on")) {
9021
 
 
9022
 
    /* Set the value to the lowest supported format. */
9023
 
    srv_check_file_format_at_startup = DICT_TF_FORMAT_51;
9024
 
  } else {
9025
 
    ret = FALSE;
9026
 
  }
9027
 
 
9028
 
  return(ret);
 
8259
        bool            ret = true;
 
8260
 
 
8261
        if (!innobase_strcasecmp(format_check, "off")) {
 
8262
 
 
8263
                /* Set the value to disable checking. */
 
8264
                srv_check_file_format_at_startup = DICT_TF_FORMAT_MAX + 1;
 
8265
 
 
8266
        } else if (!innobase_strcasecmp(format_check, "on")) {
 
8267
 
 
8268
                /* Set the value to the lowest supported format. */
 
8269
                srv_check_file_format_at_startup = DICT_TF_FORMAT_51;
 
8270
        } else {
 
8271
                ret = FALSE;
 
8272
        }
 
8273
 
 
8274
        return(ret);
9029
8275
}
9030
8276
 
9031
8277
/************************************************************//**
9032
8278
Validate the file format check config parameters, as a side effect it
9033
8279
sets the srv_check_file_format_at_startup variable.
9034
 
@return the format_id if valid config value, otherwise, return -1 */
 
8280
@return true if valid config value */
9035
8281
static
9036
 
int
9037
 
innobase_file_format_validate_and_set(
 
8282
bool
 
8283
innobase_file_format_check_validate(
9038
8284
/*================================*/
9039
 
  const char* format_check) /*!< in: parameter value */
 
8285
        const char*     format_check)   /*!< in: parameter value */
9040
8286
{
9041
 
  uint    format_id;
9042
 
 
9043
 
  format_id = innobase_file_format_name_lookup(format_check);
9044
 
 
9045
 
  if (format_id < DICT_TF_FORMAT_MAX + 1) {
9046
 
    srv_check_file_format_at_startup = format_id;
9047
 
    return((int) format_id);
9048
 
  } else {
9049
 
    return(-1);
9050
 
  }
 
8287
        uint            format_id;
 
8288
        bool            ret = true;
 
8289
 
 
8290
        format_id = innobase_file_format_name_lookup(format_check);
 
8291
 
 
8292
        if (format_id < DICT_TF_FORMAT_MAX + 1) {
 
8293
                srv_check_file_format_at_startup = format_id;
 
8294
        } else {
 
8295
                ret = false;
 
8296
        }
 
8297
 
 
8298
        return(ret);
9051
8299
}
9052
8300
 
9053
8301
/*************************************************************//**
9054
8302
Check if it is a valid file format. This function is registered as
9055
8303
a callback with MySQL.
9056
 
@return 0 for valid file format */
 
8304
@return 0 for valid file format */
9057
8305
static
9058
8306
int
9059
8307
innodb_file_format_name_validate(
9060
8308
/*=============================*/
9061
 
  Session*      , /*!< in: thread handle */
9062
 
  drizzle_sys_var*  , /*!< in: pointer to system
9063
 
            variable */
9064
 
  void*       save, /*!< out: immediate result
9065
 
            for update function */
9066
 
  drizzle_value*    value)  /*!< in: incoming string */
 
8309
        Session*                        ,       /*!< in: thread handle */
 
8310
        drizzle_sys_var*        ,       /*!< in: pointer to system
 
8311
                                                variable */
 
8312
        void*                           save,   /*!< out: immediate result
 
8313
                                                for update function */
 
8314
        drizzle_value*          value)  /*!< in: incoming string */
9067
8315
{
9068
 
  const char* file_format_input;
9069
 
  char    buff[STRING_BUFFER_USUAL_SIZE];
9070
 
  int   len = sizeof(buff);
9071
 
 
9072
 
  ut_a(save != NULL);
9073
 
  ut_a(value != NULL);
9074
 
 
9075
 
  file_format_input = value->val_str(value, buff, &len);
9076
 
 
9077
 
  if (file_format_input != NULL) {
9078
 
    uint  format_id;
9079
 
 
9080
 
    format_id = innobase_file_format_name_lookup(
9081
 
      file_format_input);
9082
 
 
9083
 
    if (format_id <= DICT_TF_FORMAT_MAX) {
9084
 
      /* Save a pointer to the name in the
9085
 
         'file_format_name_map' constant array. */
9086
 
      *static_cast<const char**>(save) =
9087
 
        trx_sys_file_format_id_to_name(format_id);
9088
 
 
9089
 
      return(0);
9090
 
    }
9091
 
  }
9092
 
 
9093
 
  *static_cast<const char**>(save) = NULL;
9094
 
  return(1);
 
8316
        const char*     file_format_input;
 
8317
        char            buff[STRING_BUFFER_USUAL_SIZE];
 
8318
        int             len = sizeof(buff);
 
8319
 
 
8320
        ut_a(save != NULL);
 
8321
        ut_a(value != NULL);
 
8322
 
 
8323
        file_format_input = value->val_str(value, buff, &len);
 
8324
 
 
8325
        if (file_format_input != NULL) {
 
8326
                uint    format_id;
 
8327
 
 
8328
                format_id = innobase_file_format_name_lookup(
 
8329
                        file_format_input);
 
8330
 
 
8331
                if (format_id <= DICT_TF_FORMAT_MAX) {
 
8332
 
 
8333
                        *static_cast<const char**>(save) = file_format_input;
 
8334
                        return(0);
 
8335
                }
 
8336
        }
 
8337
 
 
8338
        *static_cast<const char**>(save) = NULL;
 
8339
        return(1);
9095
8340
}
9096
8341
 
9097
8342
/****************************************************************//**
9101
8346
void
9102
8347
innodb_file_format_name_update(
9103
8348
/*===========================*/
9104
 
  Session*      ,   /*!< in: thread handle */
9105
 
  drizzle_sys_var*  ,   /*!< in: pointer to
9106
 
              system variable */
9107
 
  void*       var_ptr,  /*!< out: where the
9108
 
              formal string goes */
9109
 
  const void*     save)   /*!< in: immediate result
9110
 
              from check function */
 
8349
        Session*                        ,               /*!< in: thread handle */
 
8350
        drizzle_sys_var*        ,               /*!< in: pointer to
 
8351
                                                        system variable */
 
8352
        void*                           var_ptr,        /*!< out: where the
 
8353
                                                        formal string goes */
 
8354
        const void*                     save)           /*!< in: immediate result
 
8355
                                                        from check function */
9111
8356
{
9112
 
  const char* format_name;
9113
 
 
9114
 
  ut_a(var_ptr != NULL);
9115
 
  ut_a(save != NULL);
9116
 
 
9117
 
  format_name = *static_cast<const char*const*>(save);
9118
 
 
9119
 
  if (format_name) {
9120
 
    uint  format_id;
9121
 
 
9122
 
    format_id = innobase_file_format_name_lookup(format_name);
9123
 
 
9124
 
    if (format_id <= DICT_TF_FORMAT_MAX) {
9125
 
      srv_file_format = format_id;
9126
 
    }
9127
 
  }
9128
 
 
9129
 
  *static_cast<const char**>(var_ptr)
9130
 
    = trx_sys_file_format_id_to_name(srv_file_format);
 
8357
        const char* format_name;
 
8358
 
 
8359
        ut_a(var_ptr != NULL);
 
8360
        ut_a(save != NULL);
 
8361
 
 
8362
        format_name = *static_cast<const char*const*>(save);
 
8363
 
 
8364
        if (format_name) {
 
8365
                uint    format_id;
 
8366
 
 
8367
                format_id = innobase_file_format_name_lookup(format_name);
 
8368
 
 
8369
                if (format_id <= DICT_TF_FORMAT_MAX) {
 
8370
                        srv_file_format = format_id;
 
8371
                }
 
8372
        }
 
8373
 
 
8374
        *static_cast<const char**>(var_ptr)
 
8375
                = trx_sys_file_format_id_to_name(srv_file_format);
9131
8376
}
9132
8377
 
9133
8378
/*************************************************************//**
9134
8379
Check if valid argument to innodb_file_format_check. This
9135
8380
function is registered as a callback with MySQL.
9136
 
@return 0 for valid file format */
 
8381
@return 0 for valid file format */
9137
8382
static
9138
8383
int
9139
8384
innodb_file_format_check_validate(
9140
8385
/*==============================*/
9141
 
  Session*      session, /*!< in: thread handle */
9142
 
  drizzle_sys_var*  , /*!< in: pointer to system
9143
 
            variable */
9144
 
  void*       save, /*!< out: immediate result
9145
 
            for update function */
9146
 
  drizzle_value*    value)  /*!< in: incoming string */
 
8386
        Session*                        ,       /*!< in: thread handle */
 
8387
        drizzle_sys_var*        ,       /*!< in: pointer to system
 
8388
                                                variable */
 
8389
        void*                           save,   /*!< out: immediate result
 
8390
                                                for update function */
 
8391
        drizzle_value*          value)  /*!< in: incoming string */
9147
8392
{
9148
 
  const char* file_format_input;
9149
 
  char    buff[STRING_BUFFER_USUAL_SIZE];
9150
 
  int   len = sizeof(buff);
9151
 
  int   format_id;
9152
 
 
9153
 
  ut_a(save != NULL);
9154
 
  ut_a(value != NULL);
9155
 
 
9156
 
  file_format_input = value->val_str(value, buff, &len);
9157
 
 
9158
 
  if (file_format_input != NULL) {
9159
 
 
9160
 
    /* Check if user set on/off, we want to print a suitable
9161
 
    message if they did so. */
9162
 
 
9163
 
    if (innobase_file_format_check_on_off(file_format_input)) {
9164
 
      push_warning_printf(session,
9165
 
                          DRIZZLE_ERROR::WARN_LEVEL_WARN,
9166
 
                          ER_WRONG_ARGUMENTS,
9167
 
        "InnoDB: invalid innodb_file_format_check "
9168
 
        "value; on/off can only be set at startup or "
9169
 
        "in the configuration file");
9170
 
    } else {
9171
 
      format_id = innobase_file_format_validate_and_set(file_format_input);
9172
 
      if (format_id >= 0) {
9173
 
        /* Save a pointer to the name in the
9174
 
           'file_format_name_map' constant array. */
9175
 
        *static_cast<const char**>(save) =
9176
 
          trx_sys_file_format_id_to_name(
9177
 
                                         (uint)format_id);
9178
 
 
9179
 
        return(0);
9180
 
 
9181
 
      } else {
9182
 
        push_warning_printf(session,
9183
 
                            DRIZZLE_ERROR::WARN_LEVEL_WARN,
9184
 
                            ER_WRONG_ARGUMENTS,
9185
 
                            "InnoDB: invalid innodb_file_format_check "
9186
 
                            "value; can be any format up to %s "
9187
 
                            "or its equivalent numeric id",
9188
 
                            trx_sys_file_format_id_to_name(DICT_TF_FORMAT_MAX));
9189
 
      }
9190
 
    }
9191
 
  }
9192
 
 
9193
 
  *static_cast<const char**>(save) = NULL;
9194
 
  return(1);
 
8393
        const char*     file_format_input;
 
8394
        char            buff[STRING_BUFFER_USUAL_SIZE];
 
8395
        int             len = sizeof(buff);
 
8396
 
 
8397
        ut_a(save != NULL);
 
8398
        ut_a(value != NULL);
 
8399
 
 
8400
        file_format_input = value->val_str(value, buff, &len);
 
8401
 
 
8402
        if (file_format_input != NULL) {
 
8403
 
 
8404
                /* Check if user set on/off, we want to print a suitable
 
8405
                message if they did so. */
 
8406
 
 
8407
                if (innobase_file_format_check_on_off(file_format_input)) {
 
8408
                        errmsg_printf(ERRMSG_LVL_WARN, 
 
8409
                                "InnoDB: invalid innodb_file_format_check "
 
8410
                                "value; on/off can only be set at startup or "
 
8411
                                "in the configuration file");
 
8412
                } else if (innobase_file_format_check_validate(
 
8413
                                file_format_input)) {
 
8414
 
 
8415
                        *static_cast<const char**>(save) = file_format_input;
 
8416
 
 
8417
                        return(0);
 
8418
 
 
8419
                } else {
 
8420
                        errmsg_printf(ERRMSG_LVL_WARN, 
 
8421
                                "InnoDB: invalid innodb_file_format_check "
 
8422
                                "value; can be any format up to %s "
 
8423
                                "or its equivalent numeric id",
 
8424
                                trx_sys_file_format_id_to_name(
 
8425
                                        DICT_TF_FORMAT_MAX));
 
8426
                }
 
8427
        }
 
8428
 
 
8429
        *static_cast<const char**>(save) = NULL;
 
8430
        return(1);
9195
8431
}
9196
8432
 
9197
8433
/****************************************************************//**
9201
8437
void
9202
8438
innodb_file_format_check_update(
9203
8439
/*============================*/
9204
 
  Session*      session,  /*!< in: thread handle */
9205
 
  drizzle_sys_var*  ,   /*!< in: pointer to
9206
 
              system variable */
9207
 
  void*       var_ptr,  /*!< out: where the
9208
 
              formal string goes */
9209
 
  const void*     save)   /*!< in: immediate result
9210
 
              from check function */
 
8440
        Session*                        session,        /*!< in: thread handle */
 
8441
        drizzle_sys_var*        ,               /*!< in: pointer to
 
8442
                                                        system variable */
 
8443
        void*                           var_ptr,        /*!< out: where the
 
8444
                                                        formal string goes */
 
8445
        const void*                     save)           /*!< in: immediate result
 
8446
                                                        from check function */
9211
8447
{
9212
 
  const char* format_name_in;
9213
 
  const char**  format_name_out;
9214
 
  uint    format_id;
9215
 
 
9216
 
  ut_a(save != NULL);
9217
 
  ut_a(var_ptr != NULL);
9218
 
 
9219
 
  format_name_in = *static_cast<const char*const*>(save);
9220
 
 
9221
 
  if (!format_name_in) {
9222
 
 
9223
 
    return;
9224
 
  }
9225
 
 
9226
 
  format_id = innobase_file_format_name_lookup(format_name_in);
9227
 
 
9228
 
  if (format_id > DICT_TF_FORMAT_MAX) {
9229
 
    /* DEFAULT is "on", which is invalid at runtime. */
9230
 
    push_warning_printf(session, DRIZZLE_ERROR::WARN_LEVEL_WARN,
9231
 
            ER_WRONG_ARGUMENTS,
9232
 
            "Ignoring SET innodb_file_format=%s",
9233
 
            format_name_in);
9234
 
    return;
9235
 
  }
9236
 
 
9237
 
  format_name_out = static_cast<const char**>(var_ptr);
9238
 
 
9239
 
  /* Update the max format id in the system tablespace. */
9240
 
  if (trx_sys_file_format_max_set(format_id, format_name_out)) {
9241
 
    ut_print_timestamp(stderr);
9242
 
    fprintf(stderr,
9243
 
      " [Info] InnoDB: the file format in the system "
9244
 
      "tablespace is now set to %s.\n", *format_name_out);
9245
 
  }
 
8448
        const char*     format_name_in;
 
8449
        const char**    format_name_out;
 
8450
        uint            format_id;
 
8451
 
 
8452
        ut_a(save != NULL);
 
8453
        ut_a(var_ptr != NULL);
 
8454
 
 
8455
        format_name_in = *static_cast<const char*const*>(save);
 
8456
 
 
8457
        if (!format_name_in) {
 
8458
 
 
8459
                return;
 
8460
        }
 
8461
 
 
8462
        format_id = innobase_file_format_name_lookup(format_name_in);
 
8463
 
 
8464
        if (format_id > DICT_TF_FORMAT_MAX) {
 
8465
                /* DEFAULT is "on", which is invalid at runtime. */
 
8466
                push_warning_printf(session, DRIZZLE_ERROR::WARN_LEVEL_WARN,
 
8467
                                    ER_WRONG_ARGUMENTS,
 
8468
                                    "Ignoring SET innodb_file_format=%s",
 
8469
                                    format_name_in);
 
8470
                return;
 
8471
        }
 
8472
 
 
8473
        format_name_out = static_cast<const char**>(var_ptr);
 
8474
 
 
8475
        /* Update the max format id in the system tablespace. */
 
8476
        if (trx_sys_file_format_max_set(format_id, format_name_out)) {
 
8477
                ut_print_timestamp(stderr);
 
8478
                fprintf(stderr,
 
8479
                        " [Info] InnoDB: the file format in the system "
 
8480
                        "tablespace is now set to %s.\n", *format_name_out);
 
8481
        }
9246
8482
}
9247
8483
 
9248
8484
/****************************************************************//**
9252
8488
void
9253
8489
innodb_adaptive_hash_index_update(
9254
8490
/*==============================*/
9255
 
  Session*      ,   /*!< in: thread handle */
9256
 
  drizzle_sys_var*  ,   /*!< in: pointer to
9257
 
              system variable */
9258
 
  void*       , /*!< out: where the
9259
 
              formal string goes */
9260
 
  const void*     save)   /*!< in: immediate result
9261
 
              from check function */
9262
 
{
9263
 
  if (*(bool*) save) {
9264
 
    btr_search_enable();
9265
 
  } else {
9266
 
    btr_search_disable();
9267
 
  }
9268
 
}
9269
 
 
9270
 
/****************************************************************//**
9271
 
Update the system variable innodb_old_blocks_pct using the "saved"
9272
 
value. This function is registered as a callback with MySQL. */
9273
 
static
9274
 
void
9275
 
innodb_old_blocks_pct_update(
9276
 
/*=========================*/
9277
 
        Session*                        ,       /*!< in: thread handle */
9278
 
        drizzle_sys_var*        ,       /*!< in: pointer to
9279
 
                                                system variable */
9280
 
        void*                           ,/*!< out: where the
9281
 
                                                formal string goes */
9282
 
        const void*                     save)   /*!< in: immediate result
9283
 
                                                from check function */
9284
 
{
9285
 
        innobase_old_blocks_pct = buf_LRU_old_ratio_update(
9286
 
                *static_cast<const uint*>(save), TRUE);
 
8491
        Session*                        ,               /*!< in: thread handle */
 
8492
        drizzle_sys_var*        ,               /*!< in: pointer to
 
8493
                                                        system variable */
 
8494
        void*                           ,       /*!< out: where the
 
8495
                                                        formal string goes */
 
8496
        const void*                     save)           /*!< in: immediate result
 
8497
                                                        from check function */
 
8498
{
 
8499
        if (*(bool*) save) {
 
8500
                btr_search_enable();
 
8501
        } else {
 
8502
                btr_search_disable();
 
8503
        }
9287
8504
}
9288
8505
 
9289
8506
/*************************************************************//**
9290
8507
Check if it is a valid value of innodb_change_buffering.  This function is
9291
8508
registered as a callback with MySQL.
9292
 
@return 0 for valid innodb_change_buffering */
 
8509
@return 0 for valid innodb_change_buffering */
9293
8510
static
9294
8511
int
9295
8512
innodb_change_buffering_validate(
9296
8513
/*=============================*/
9297
 
  Session*      , /*!< in: thread handle */
9298
 
  drizzle_sys_var*  , /*!< in: pointer to system
9299
 
            variable */
9300
 
  void*       save, /*!< out: immediate result
9301
 
            for update function */
9302
 
  drizzle_value*    value)  /*!< in: incoming string */
 
8514
        Session*                        ,       /*!< in: thread handle */
 
8515
        drizzle_sys_var*        ,       /*!< in: pointer to system
 
8516
                                                variable */
 
8517
        void*                           save,   /*!< out: immediate result
 
8518
                                                for update function */
 
8519
        drizzle_value*          value)  /*!< in: incoming string */
9303
8520
{
9304
 
  const char* change_buffering_input;
9305
 
  char    buff[STRING_BUFFER_USUAL_SIZE];
9306
 
  int   len = sizeof(buff);
9307
 
 
9308
 
  ut_a(save != NULL);
9309
 
  ut_a(value != NULL);
9310
 
 
9311
 
  change_buffering_input = value->val_str(value, buff, &len);
9312
 
 
9313
 
  if (change_buffering_input != NULL) {
9314
 
    ulint use;
9315
 
 
9316
 
    for (use = 0; use < UT_ARR_SIZE(innobase_change_buffering_values);
9317
 
         use++) {
9318
 
      if (!innobase_strcasecmp(
9319
 
            change_buffering_input,
9320
 
            innobase_change_buffering_values[use])) {
9321
 
        *(ibuf_use_t*) save = (ibuf_use_t) use;
9322
 
        return(0);
9323
 
      }
9324
 
    }
9325
 
  }
9326
 
 
9327
 
  return(1);
 
8521
        const char*     change_buffering_input;
 
8522
        char            buff[STRING_BUFFER_USUAL_SIZE];
 
8523
        int             len = sizeof(buff);
 
8524
 
 
8525
        ut_a(save != NULL);
 
8526
        ut_a(value != NULL);
 
8527
 
 
8528
        change_buffering_input = value->val_str(value, buff, &len);
 
8529
 
 
8530
        if (change_buffering_input != NULL) {
 
8531
                ulint   use;
 
8532
 
 
8533
                for (use = 0; use < UT_ARR_SIZE(innobase_change_buffering_values);
 
8534
                     use++) {
 
8535
                        if (!innobase_strcasecmp(
 
8536
                                    change_buffering_input,
 
8537
                                    innobase_change_buffering_values[use])) {
 
8538
                                *(ibuf_use_t*) save = (ibuf_use_t) use;
 
8539
                                return(0);
 
8540
                        }
 
8541
                }
 
8542
        }
 
8543
 
 
8544
        return(1);
9328
8545
}
9329
8546
 
9330
8547
/****************************************************************//**
9334
8551
void
9335
8552
innodb_change_buffering_update(
9336
8553
/*===========================*/
9337
 
  Session*      ,   /*!< in: thread handle */
9338
 
  drizzle_sys_var*  ,   /*!< in: pointer to
9339
 
              system variable */
9340
 
  void*       var_ptr,  /*!< out: where the
9341
 
              formal string goes */
9342
 
  const void*     save)   /*!< in: immediate result
9343
 
              from check function */
 
8554
        Session*                        ,               /*!< in: thread handle */
 
8555
        drizzle_sys_var*        ,               /*!< in: pointer to
 
8556
                                                        system variable */
 
8557
        void*                           var_ptr,        /*!< out: where the
 
8558
                                                        formal string goes */
 
8559
        const void*                     save)           /*!< in: immediate result
 
8560
                                                        from check function */
9344
8561
{
9345
 
  ut_a(var_ptr != NULL);
9346
 
  ut_a(save != NULL);
9347
 
  ut_a((*(ibuf_use_t*) save) < IBUF_USE_COUNT);
9348
 
 
9349
 
  ibuf_use = *(const ibuf_use_t*) save;
9350
 
 
9351
 
  *(const char**) var_ptr = innobase_change_buffering_values[ibuf_use];
 
8562
        ut_a(var_ptr != NULL);
 
8563
        ut_a(save != NULL);
 
8564
        ut_a((*(ibuf_use_t*) save) < IBUF_USE_COUNT);
 
8565
 
 
8566
        ibuf_use = *(const ibuf_use_t*) save;
 
8567
 
 
8568
        *(const char**) var_ptr = innobase_change_buffering_values[ibuf_use];
9352
8569
}
9353
8570
 
9354
8571
/* plugin options */
9355
8572
static DRIZZLE_SYSVAR_BOOL(checksums, innobase_use_checksums,
9356
8573
  PLUGIN_VAR_NOCMDARG | PLUGIN_VAR_READONLY,
9357
 
  "Enable InnoDB checksums validation (enabled by default). ",
 
8574
  "Enable InnoDB checksums validation (enabled by default). "
 
8575
  "Disable with --skip-innodb-checksums.",
9358
8576
  NULL, NULL, TRUE);
9359
8577
 
9360
8578
static DRIZZLE_SYSVAR_STR(data_home_dir, innobase_data_home_dir,
9364
8582
 
9365
8583
static DRIZZLE_SYSVAR_BOOL(doublewrite, innobase_use_doublewrite,
9366
8584
  PLUGIN_VAR_NOCMDARG | PLUGIN_VAR_READONLY,
9367
 
  "Enable InnoDB doublewrite buffer (enabled by default). ",
 
8585
  "Enable InnoDB doublewrite buffer (enabled by default). "
 
8586
  "Disable with --skip-innodb-doublewrite.",
9368
8587
  NULL, NULL, TRUE);
9369
8588
 
9370
8589
static DRIZZLE_SYSVAR_ULONG(io_capacity, srv_io_capacity,
9391
8610
  innodb_file_format_name_validate,
9392
8611
  innodb_file_format_name_update, "Antelope");
9393
8612
 
9394
 
/* If a new file format is introduced, the file format
9395
 
name needs to be updated accordingly. Please refer to
9396
 
file_format_name_map[] defined in trx0sys.c for the next
9397
 
file format name. */
9398
8613
static DRIZZLE_SYSVAR_STR(file_format_check, innobase_file_format_check,
9399
8614
  PLUGIN_VAR_OPCMDARG,
9400
8615
  "The highest file format in the tablespace.",
9401
8616
  innodb_file_format_check_validate,
9402
8617
  innodb_file_format_check_update,
9403
 
  "Barracuda");
 
8618
  "on");
9404
8619
 
9405
8620
static DRIZZLE_SYSVAR_ULONG(flush_log_at_trx_commit, srv_flush_log_at_trx_commit,
9406
8621
  PLUGIN_VAR_OPCMDARG,
9409
8624
  " or 2 (write at commit, flush once per second).",
9410
8625
  NULL, NULL, 1, 0, 2, 0);
9411
8626
 
9412
 
static DRIZZLE_SYSVAR_STR(flush_method, innobase_file_flush_method,
 
8627
static DRIZZLE_SYSVAR_STR(flush_method, innobase_unix_file_flush_method,
9413
8628
  PLUGIN_VAR_RQCMDARG | PLUGIN_VAR_READONLY,
9414
8629
  "With which method to flush data.", NULL, NULL, NULL);
9415
8630
 
 
8631
static DRIZZLE_SYSVAR_BOOL(locks_unsafe_for_binlog, innobase_locks_unsafe_for_binlog,
 
8632
  PLUGIN_VAR_NOCMDARG | PLUGIN_VAR_READONLY,
 
8633
  "Force InnoDB to not use next-key locking, to use only row-level locking.",
 
8634
  NULL, NULL, TRUE);
 
8635
 
9416
8636
#ifdef UNIV_LOG_ARCHIVE
9417
8637
static DRIZZLE_SYSVAR_STR(log_arch_dir, innobase_log_arch_dir,
9418
8638
  PLUGIN_VAR_RQCMDARG | PLUGIN_VAR_READONLY,
9442
8662
  "Desired maximum length of the purge queue (0 = no limit)",
9443
8663
  NULL, NULL, 0, 0, ~0L, 0);
9444
8664
 
 
8665
static DRIZZLE_SYSVAR_BOOL(rollback_on_timeout, innobase_rollback_on_timeout,
 
8666
  PLUGIN_VAR_OPCMDARG | PLUGIN_VAR_READONLY,
 
8667
  "Roll back the complete transaction on lock wait timeout, for 4.x compatibility (disabled by default)",
 
8668
  NULL, NULL, FALSE);
 
8669
 
9445
8670
static DRIZZLE_SYSVAR_BOOL(status_file, innobase_create_status_file,
9446
8671
  PLUGIN_VAR_OPCMDARG | PLUGIN_VAR_NOSYSVAR,
9447
8672
  "Enable SHOW INNODB STATUS output in the innodb_status.<pid> file",
9448
8673
  NULL, NULL, FALSE);
9449
8674
 
 
8675
static DRIZZLE_SYSVAR_BOOL(stats_on_metadata, innobase_stats_on_metadata,
 
8676
  PLUGIN_VAR_OPCMDARG,
 
8677
  "Enable statistics gathering for metadata commands such as SHOW TABLE STATUS (on by default)",
 
8678
  NULL, NULL, TRUE);
 
8679
 
9450
8680
static DRIZZLE_SYSVAR_ULONGLONG(stats_sample_pages, srv_stats_sample_pages,
9451
8681
  PLUGIN_VAR_RQCMDARG,
9452
8682
  "The number of index pages to sample when calculating statistics (default 8)",
9454
8684
 
9455
8685
static DRIZZLE_SYSVAR_BOOL(adaptive_hash_index, btr_search_enabled,
9456
8686
  PLUGIN_VAR_OPCMDARG,
9457
 
  "Enable InnoDB adaptive hash index (enabled by default).",
 
8687
  "Enable InnoDB adaptive hash index (enabled by default).  "
 
8688
  "Disable with --skip-innodb-adaptive-hash-index.",
9458
8689
  NULL, innodb_adaptive_hash_index_update, TRUE);
9459
8690
 
9460
8691
static DRIZZLE_SYSVAR_ULONG(replication_delay, srv_replication_delay,
9488
8719
  "Number of times a thread is allowed to enter InnoDB within the same SQL query after it has once got the ticket",
9489
8720
  NULL, NULL, 500L, 1L, ~0L, 0);
9490
8721
 
 
8722
static DRIZZLE_SYSVAR_LONG(file_io_threads, innobase_file_io_threads,
 
8723
  PLUGIN_VAR_RQCMDARG | PLUGIN_VAR_READONLY,
 
8724
  "Number of file I/O threads in InnoDB.",
 
8725
  NULL, NULL, 4, 4, 64, 0);
 
8726
 
9491
8727
static DRIZZLE_SYSVAR_ULONG(read_io_threads, innobase_read_io_threads,
9492
8728
  PLUGIN_VAR_RQCMDARG | PLUGIN_VAR_READONLY,
9493
8729
  "Number of background read I/O threads in InnoDB.",
9511
8747
static DRIZZLE_SYSVAR_LONGLONG(log_file_size, innobase_log_file_size,
9512
8748
  PLUGIN_VAR_RQCMDARG | PLUGIN_VAR_READONLY,
9513
8749
  "Size of each log file in a log group.",
9514
 
  NULL, NULL, 20*1024*1024L, 1*1024*1024L, INT64_MAX, 1024*1024L);
 
8750
  NULL, NULL, 5*1024*1024L, 1*1024*1024L, INT64_MAX, 1024*1024L);
9515
8751
 
9516
8752
static DRIZZLE_SYSVAR_LONG(log_files_in_group, innobase_log_files_in_group,
9517
8753
  PLUGIN_VAR_RQCMDARG | PLUGIN_VAR_READONLY,
9523
8759
  "Number of identical copies of log groups we keep for the database. Currently this should be set to 1.",
9524
8760
  NULL, NULL, 1, 1, 10, 0);
9525
8761
 
9526
 
static DRIZZLE_SYSVAR_UINT(old_blocks_pct, innobase_old_blocks_pct,
9527
 
  PLUGIN_VAR_RQCMDARG,
9528
 
  "Percentage of the buffer pool to reserve for 'old' blocks.",
9529
 
  NULL, innodb_old_blocks_pct_update, 100 * 3 / 8, 5, 95, 0);
9530
 
 
9531
 
static DRIZZLE_SYSVAR_UINT(old_blocks_time, buf_LRU_old_threshold_ms,
9532
 
  PLUGIN_VAR_RQCMDARG,
9533
 
  "Move blocks to the 'new' end of the buffer pool if the first access"
9534
 
  " was at least this many milliseconds ago."
9535
 
  " The timeout is disabled if 0 (the default).",
9536
 
  NULL, NULL, 0, 0, UINT32_MAX, 0);
9537
 
 
9538
8762
static DRIZZLE_SYSVAR_LONG(open_files, innobase_open_files,
9539
8763
  PLUGIN_VAR_RQCMDARG | PLUGIN_VAR_READONLY,
9540
8764
  "How many files at the maximum InnoDB keeps open at the same time.",
9565
8789
  "Path to individual files and their sizes.",
9566
8790
  NULL, NULL, NULL);
9567
8791
 
 
8792
static DRIZZLE_SYSVAR_LONG(autoinc_lock_mode, innobase_autoinc_lock_mode,
 
8793
  PLUGIN_VAR_RQCMDARG | PLUGIN_VAR_READONLY,
 
8794
  "The AUTOINC lock modes supported by InnoDB:               "
 
8795
  "0 => Old style AUTOINC locking (for backward"
 
8796
  " compatibility)                                           "
 
8797
  "1 => New style AUTOINC locking                            "
 
8798
  "2 => No AUTOINC locking (unsafe for SBR)",
 
8799
  NULL, NULL,
 
8800
  AUTOINC_NO_LOCKING,   /* Default setting */
 
8801
  AUTOINC_OLD_STYLE_LOCKING,    /* Minimum value */
 
8802
  AUTOINC_NO_LOCKING, 0);       /* Maximum value */
 
8803
 
9568
8804
static DRIZZLE_SYSVAR_STR(version, innodb_version_str,
9569
8805
  PLUGIN_VAR_NOCMDOPT | PLUGIN_VAR_READONLY,
9570
8806
  "InnoDB version", NULL, NULL, INNODB_VERSION_STR);
9577
8813
static DRIZZLE_SYSVAR_STR(change_buffering, innobase_change_buffering,
9578
8814
  PLUGIN_VAR_RQCMDARG,
9579
8815
  "Buffer changes to reduce random access: "
9580
 
  "OFF, ON, none, inserts.",
 
8816
  "OFF, ON, inserting, deleting, changing, or purging.",
9581
8817
  innodb_change_buffering_validate,
9582
8818
  innodb_change_buffering_update, NULL);
9583
8819
 
9584
8820
static DRIZZLE_SYSVAR_ULONG(read_ahead_threshold, srv_read_ahead_threshold,
9585
8821
  PLUGIN_VAR_RQCMDARG,
9586
 
  "Number of pages that must be accessed sequentially for InnoDB to "
 
8822
  "Number of pages that must be accessed sequentially for InnoDB to"
9587
8823
  "trigger a readahead.",
9588
8824
  NULL, NULL, 56, 0, 64, 0);
9589
8825
 
9590
 
static void init_options(drizzled::module::option_context &context)
9591
 
{
9592
 
  context("disable-checksums",
9593
 
          "Disable InnoDB checksums validation.");
9594
 
  context("data-home-dir",
9595
 
          po::value<string>(),
9596
 
          "The common part for InnoDB table spaces.");
9597
 
  context("disable-doublewrite",
9598
 
          "Disable InnoDB doublewrite buffer.");
9599
 
  context("io-capacity",
9600
 
          po::value<unsigned long>(&srv_io_capacity)->default_value(200),
9601
 
          "Number of IOPs the server can do. Tunes the background IO rate");
9602
 
  context("fast-shutdown",
9603
 
          po::value<unsigned long>(&innobase_fast_shutdown)->default_value(1), 
9604
 
          "Speeds up the shutdown process of the InnoDB storage engine. Possible values are 0, 1 (faster) or 2 (fastest - crash-like).");
9605
 
  context("file-per-table",
9606
 
          po::value<bool>(&srv_file_per_table)->default_value(false)->zero_tokens(),
9607
 
          "Stores each InnoDB table to an .ibd file in the database dir.");
9608
 
  context("file-format",
9609
 
          po::value<string>()->default_value("Antelope"),
9610
 
          "File format to use for new tables in .ibd files.");
9611
 
  context("file-format-check",
9612
 
          po::value<string>()->default_value("on"),
9613
 
          "The highest file format in the tablespace.");
9614
 
  context("flush-log-at-trx-commit",
9615
 
          po::value<unsigned long>(&srv_flush_log_at_trx_commit)->default_value(1),
9616
 
          "Set to 0 (write and flush once per second), 1 (write and flush at each commit) or 2 (write at commit, flush once per second).");
9617
 
  context("flush-method",
9618
 
          po::value<string>(),
9619
 
          "With which method to flush data.");
9620
 
#ifdef UNIV_LOG_ARCHIVE
9621
 
  context("log-arch-dir",
9622
 
          po::value<string>(),
9623
 
          "Where full logs should be archived.");
9624
 
  context("log-archive",
9625
 
          po::value<bool>(&innobase_log_archive)->default_value(false)->zero_tokens(),
9626
 
          "Set to 1 if you want to have logs archived.");
9627
 
#endif /* UNIV_LOG_ARCHIVE */
9628
 
  context("log-group-home-dir",
9629
 
          po::value<string>(),
9630
 
          "Path to InnoDB log files.");
9631
 
  context("max-dirty-pages-pct",
9632
 
          po::value<unsigned long>(&srv_max_buf_pool_modified_pct)->default_value(75),
9633
 
          "Percentage of dirty pages allowed in bufferpool.");
9634
 
  context("disable-adaptive-flushing",
9635
 
          "Do not attempt flushing dirty pages to avoid IO bursts at checkpoints.");
9636
 
  context("max-purge-lag",
9637
 
          po::value<unsigned long>(&srv_max_purge_lag)->default_value(0),
9638
 
          "Desired maximum length of the purge queue (0 = no limit)");
9639
 
  context("status-file",
9640
 
          po::value<bool>(&innobase_create_status_file)->default_value(false)->zero_tokens(),
9641
 
          "Enable SHOW INNODB STATUS output in the innodb_status.<pid> file");
9642
 
  context("disable-stats-on-metadata",
9643
 
          "Disable statistics gathering for metadata commands such as SHOW TABLE STATUS (on by default)");
9644
 
  context("stats-sample-pages",
9645
 
          po::value<uint64_t>(&srv_stats_sample_pages)->default_value(8),
9646
 
          "The number of index pages to sample when calculating statistics (default 8)");
9647
 
  context("disable-adaptive-hash-index",
9648
 
          "Enable InnoDB adaptive hash index (enabled by default)");
9649
 
  context("replication-delay",
9650
 
          po::value<unsigned long>(&srv_replication_delay)->default_value(0),
9651
 
          "Replication thread delay (ms) on the slave server if innodb_thread_concurrency is reached (0 by default)");
9652
 
  context("additional-mem-pool-size",
9653
 
          po::value<long>(&innobase_additional_mem_pool_size)->default_value(8*1024*1024L),
9654
 
          "Size of a memory pool InnoDB uses to store data dictionary information and other internal data structures.");
9655
 
  context("autoextend-increment",
9656
 
          po::value<uint32_t>(&srv_auto_extend_increment)->default_value(8L),
9657
 
          "Data file autoextend increment in megabytes");
9658
 
  context("buffer-pool-size",
9659
 
          po::value<int64_t>(&innobase_buffer_pool_size)->default_value(128*1024*1024L),
9660
 
          "The size of the memory buffer InnoDB uses to cache data and indexes of its tables.");
9661
 
  context("commit-concurrency",
9662
 
          po::value<unsigned long>(&innobase_commit_concurrency)->default_value(0),
9663
 
          "Helps in performance tuning in heavily concurrent environments.");
9664
 
  context("concurrency-tickets",
9665
 
          po::value<unsigned long>(&srv_n_free_tickets_to_enter)->default_value(500L),
9666
 
          "Number of times a thread is allowed to enter InnoDB within the same SQL query after it has once got the ticket");
9667
 
  context("read-io-threads",
9668
 
          po::value<unsigned long>(&innobase_read_io_threads)->default_value(4),
9669
 
          "Number of background read I/O threads in InnoDB.");
9670
 
  context("write-io-threads",
9671
 
          po::value<unsigned long>(&innobase_write_io_threads)->default_value(4),
9672
 
          "Number of background write I/O threads in InnoDB.");
9673
 
  context("force-recovery",
9674
 
          po::value<long>(&innobase_force_recovery)->default_value(0),
9675
 
          "Helps to save your data in case the disk image of the database becomes corrupt.");
9676
 
  context("log-buffer-size",
9677
 
          po::value<long>(&innobase_log_buffer_size)->default_value(8*1024*1024L),
9678
 
          "The size of the buffer which InnoDB uses to write log to the log files on disk.");
9679
 
  context("log-file-size",
9680
 
          po::value<int64_t>(&innobase_log_file_size)->default_value(20*1024*1024L),
9681
 
          "The size of the buffer which InnoDB uses to write log to the log files on disk.");
9682
 
  context("log-files-in-group",
9683
 
          po::value<long>(&innobase_log_files_in_group)->default_value(2),
9684
 
          "Number of log files in the log group. InnoDB writes to the files in a circular fashion.");
9685
 
  context("mirrored-log-groups",
9686
 
          po::value<long>(&innobase_mirrored_log_groups)->default_value(1),
9687
 
          "Number of identical copies of log groups we keep for the database. Currently this should be set to 1.");
9688
 
  context("open-files",
9689
 
          po::value<long>(&innobase_open_files)->default_value(300L),
9690
 
          "How many files at the maximum InnoDB keeps open at the same time.");
9691
 
  context("sync-spin-loops",
9692
 
          po::value<unsigned long>(&srv_n_spin_wait_rounds)->default_value(30L),
9693
 
          "Count of spin-loop rounds in InnoDB mutexes (30 by default)");
9694
 
  context("spin-wait-delay",
9695
 
          po::value<unsigned long>(&srv_spin_wait_delay)->default_value(6L),
9696
 
          "Maximum delay between polling for a spin lock (6 by default)");
9697
 
  context("thread-concurrency",
9698
 
          po::value<unsigned long>(&srv_thread_concurrency)->default_value(0),
9699
 
          "Helps in performance tuning in heavily concurrent environments. Sets the maximum number of threads allowed inside InnoDB. Value 0 will disable the thread throttling.");
9700
 
  context("thread-sleep-delay",
9701
 
          po::value<unsigned long>(&srv_thread_sleep_delay)->default_value(10000L),
9702
 
          "Time of innodb thread sleeping before joining InnoDB queue (usec). Value 0 disable a sleep");
9703
 
  context("data-file-path",
9704
 
          po::value<string>(),
9705
 
          "Path to individual files and their sizes.");
9706
 
  context("version",
9707
 
          po::value<string>()->default_value(INNODB_VERSION_STR),
9708
 
          "InnoDB version");
9709
 
  context("use-internal-malloc",
9710
 
          "Use InnoDB's internal memory allocator instal of the OS memory allocator.");
9711
 
  context("change-buffering",
9712
 
          po::value<string>(),
9713
 
          "Buffer changes to reduce random access: OFF, ON, inserting, deleting, changing, or purging.");
9714
 
  context("read-ahead-threshold",
9715
 
          po::value<unsigned long>(&srv_read_ahead_threshold)->default_value(56),
9716
 
          "Number of pages that must be accessed sequentially for InnoDB to trigger a readahead.");
9717
 
  context("disable-xa",
9718
 
          "Disable InnoDB support for the XA two-phase commit");
9719
 
  context("disable-table-locks",
9720
 
          "Disable InnoDB locking in LOCK TABLES");
9721
 
  context("strict-mode",
9722
 
          po::value<bool>()->default_value(false)->zero_tokens(),
9723
 
          "Use strict mode when evaluating create options.");
9724
 
  context("lock-wait-timeout",
9725
 
          po::value<unsigned long>()->default_value(50),
9726
 
          "Timeout in seconds an InnoDB transaction may wait for a lock before being rolled back. Values above 100000000 disable the timeout.");
9727
 
}
9728
 
 
9729
8826
static drizzle_sys_var* innobase_system_variables[]= {
9730
8827
  DRIZZLE_SYSVAR(additional_mem_pool_size),
9731
8828
  DRIZZLE_SYSVAR(autoextend_increment),
9737
8834
  DRIZZLE_SYSVAR(data_home_dir),
9738
8835
  DRIZZLE_SYSVAR(doublewrite),
9739
8836
  DRIZZLE_SYSVAR(fast_shutdown),
 
8837
  DRIZZLE_SYSVAR(file_io_threads),
9740
8838
  DRIZZLE_SYSVAR(read_io_threads),
9741
8839
  DRIZZLE_SYSVAR(write_io_threads),
9742
8840
  DRIZZLE_SYSVAR(file_per_table),
9745
8843
  DRIZZLE_SYSVAR(flush_log_at_trx_commit),
9746
8844
  DRIZZLE_SYSVAR(flush_method),
9747
8845
  DRIZZLE_SYSVAR(force_recovery),
 
8846
  DRIZZLE_SYSVAR(locks_unsafe_for_binlog),
9748
8847
  DRIZZLE_SYSVAR(lock_wait_timeout),
9749
8848
#ifdef UNIV_LOG_ARCHIVE
9750
8849
  DRIZZLE_SYSVAR(log_arch_dir),
9758
8857
  DRIZZLE_SYSVAR(max_purge_lag),
9759
8858
  DRIZZLE_SYSVAR(adaptive_flushing),
9760
8859
  DRIZZLE_SYSVAR(mirrored_log_groups),
9761
 
  DRIZZLE_SYSVAR(old_blocks_pct),
9762
 
  DRIZZLE_SYSVAR(old_blocks_time),
9763
8860
  DRIZZLE_SYSVAR(open_files),
 
8861
  DRIZZLE_SYSVAR(rollback_on_timeout),
 
8862
  DRIZZLE_SYSVAR(stats_on_metadata),
9764
8863
  DRIZZLE_SYSVAR(stats_sample_pages),
9765
8864
  DRIZZLE_SYSVAR(adaptive_hash_index),
9766
8865
  DRIZZLE_SYSVAR(replication_delay),
9772
8871
  DRIZZLE_SYSVAR(table_locks),
9773
8872
  DRIZZLE_SYSVAR(thread_concurrency),
9774
8873
  DRIZZLE_SYSVAR(thread_sleep_delay),
 
8874
  DRIZZLE_SYSVAR(autoinc_lock_mode),
9775
8875
  DRIZZLE_SYSVAR(version),
9776
8876
  DRIZZLE_SYSVAR(use_sys_malloc),
9777
8877
  DRIZZLE_SYSVAR(change_buffering),
9789
8889
  "Supports transactions, row-level locking, and foreign keys",
9790
8890
  PLUGIN_LICENSE_GPL,
9791
8891
  innobase_init, /* Plugin Init */
 
8892
  innobase_deinit, /* Plugin Deinit */
9792
8893
  innobase_system_variables, /* system variables */
9793
 
  init_options /* reserved */
 
8894
  NULL /* reserved */
9794
8895
}
9795
8896
DRIZZLE_DECLARE_PLUGIN_END;
9796
8897
 
9797
8898
int ha_innobase::read_range_first(const key_range *start_key,
9798
 
          const key_range *end_key,
9799
 
          bool eq_range_arg,
9800
 
          bool sorted)
 
8899
                                  const key_range *end_key,
 
8900
                                  bool eq_range_arg,
 
8901
                                  bool sorted)
9801
8902
{
9802
8903
  int res;
9803
8904
  //if (!eq_range_arg)
9831
8932
innobase_commit_concurrency_init_default(void)
9832
8933
/*==========================================*/
9833
8934
{
9834
 
  DRIZZLE_SYSVAR_NAME(commit_concurrency).def_val
9835
 
    = innobase_commit_concurrency;
9836
 
}
9837
 
 
9838
 
/***********************************************************************
9839
 
This function checks each index name for a table against reserved
9840
 
system default primary index name 'GEN_CLUST_INDEX'. If a name matches,
9841
 
this function pushes an warning message to the client, and returns true. */
9842
 
extern "C" UNIV_INTERN
9843
 
bool
9844
 
innobase_index_name_is_reserved(
9845
 
/*============================*/
9846
 
                                        /* out: true if an index name
9847
 
                                        matches the reserved name */
9848
 
        const trx_t*    trx,            /* in: InnoDB transaction handle */
9849
 
        const KeyInfo*  key_info,       /* in: Indexes to be created */
9850
 
        ulint           num_of_keys)    /* in: Number of indexes to
9851
 
                                        be created. */
9852
 
{
9853
 
  const KeyInfo*        key;
9854
 
  uint          key_num;        /* index number */
9855
 
 
9856
 
  for (key_num = 0; key_num < num_of_keys; key_num++) {
9857
 
    key = &key_info[key_num];
9858
 
 
9859
 
    if (innobase_strcasecmp(key->name,
9860
 
                            innobase_index_reserve_name) == 0) {
9861
 
      /* Push warning to drizzle */
9862
 
      push_warning_printf((Session*)trx->mysql_thd,
9863
 
                          DRIZZLE_ERROR::WARN_LEVEL_WARN,
9864
 
                          ER_WRONG_NAME_FOR_INDEX,
9865
 
                          "Cannot Create Index with name "
9866
 
                          "'%s'. The name is reserved "
9867
 
                          "for the system default primary "
9868
 
                          "index.",
9869
 
                          innobase_index_reserve_name);
9870
 
 
9871
 
      my_error(ER_WRONG_NAME_FOR_INDEX, MYF(0),
9872
 
               innobase_index_reserve_name);
9873
 
 
9874
 
      return(true);
9875
 
    }
9876
 
  }
9877
 
 
9878
 
  return(false);
 
8935
        DRIZZLE_SYSVAR_NAME(commit_concurrency).def_val
 
8936
                = innobase_commit_concurrency;
9879
8937
}
9880
8938
 
9881
8939
#ifdef UNIV_COMPILE_TEST_FUNCS
9882
8940
 
9883
8941
typedef struct innobase_convert_name_test_struct {
9884
 
  char*   buf;
9885
 
  ulint   buflen;
9886
 
  const char* id;
9887
 
  ulint   idlen;
9888
 
  void*   session;
9889
 
  ibool   file_id;
 
8942
        char*           buf;
 
8943
        ulint           buflen;
 
8944
        const char*     id;
 
8945
        ulint           idlen;
 
8946
        void*           session;
 
8947
        ibool           file_id;
9890
8948
 
9891
 
  const char* expected;
 
8949
        const char*     expected;
9892
8950
} innobase_convert_name_test_t;
9893
8951
 
9894
8952
void
9895
8953
test_innobase_convert_name()
9896
8954
{
9897
 
  char  buf[1024];
9898
 
  ulint i;
9899
 
 
9900
 
  innobase_convert_name_test_t test_input[] = {
9901
 
    {buf, sizeof(buf), "abcd", 4, NULL, TRUE, "\"abcd\""},
9902
 
    {buf, 7, "abcd", 4, NULL, TRUE, "\"abcd\""},
9903
 
    {buf, 6, "abcd", 4, NULL, TRUE, "\"abcd\""},
9904
 
    {buf, 5, "abcd", 4, NULL, TRUE, "\"abc\""},
9905
 
    {buf, 4, "abcd", 4, NULL, TRUE, "\"ab\""},
9906
 
 
9907
 
    {buf, sizeof(buf), "ab@0060cd", 9, NULL, TRUE, "\"ab`cd\""},
9908
 
    {buf, 9, "ab@0060cd", 9, NULL, TRUE, "\"ab`cd\""},
9909
 
    {buf, 8, "ab@0060cd", 9, NULL, TRUE, "\"ab`cd\""},
9910
 
    {buf, 7, "ab@0060cd", 9, NULL, TRUE, "\"ab`cd\""},
9911
 
    {buf, 6, "ab@0060cd", 9, NULL, TRUE, "\"ab`c\""},
9912
 
    {buf, 5, "ab@0060cd", 9, NULL, TRUE, "\"ab`\""},
9913
 
    {buf, 4, "ab@0060cd", 9, NULL, TRUE, "\"ab\""},
9914
 
 
9915
 
    {buf, sizeof(buf), "ab\"cd", 5, NULL, TRUE,
9916
 
      "\"#mysql50#ab\"\"cd\""},
9917
 
    {buf, 17, "ab\"cd", 5, NULL, TRUE,
9918
 
      "\"#mysql50#ab\"\"cd\""},
9919
 
    {buf, 16, "ab\"cd", 5, NULL, TRUE,
9920
 
      "\"#mysql50#ab\"\"c\""},
9921
 
    {buf, 15, "ab\"cd", 5, NULL, TRUE,
9922
 
      "\"#mysql50#ab\"\"\""},
9923
 
    {buf, 14, "ab\"cd", 5, NULL, TRUE,
9924
 
      "\"#mysql50#ab\""},
9925
 
    {buf, 13, "ab\"cd", 5, NULL, TRUE,
9926
 
      "\"#mysql50#ab\""},
9927
 
    {buf, 12, "ab\"cd", 5, NULL, TRUE,
9928
 
      "\"#mysql50#a\""},
9929
 
    {buf, 11, "ab\"cd", 5, NULL, TRUE,
9930
 
      "\"#mysql50#\""},
9931
 
    {buf, 10, "ab\"cd", 5, NULL, TRUE,
9932
 
      "\"#mysql50\""},
9933
 
 
9934
 
    {buf, sizeof(buf), "ab/cd", 5, NULL, TRUE, "\"ab\".\"cd\""},
9935
 
    {buf, 9, "ab/cd", 5, NULL, TRUE, "\"ab\".\"cd\""},
9936
 
    {buf, 8, "ab/cd", 5, NULL, TRUE, "\"ab\".\"c\""},
9937
 
    {buf, 7, "ab/cd", 5, NULL, TRUE, "\"ab\".\"\""},
9938
 
    {buf, 6, "ab/cd", 5, NULL, TRUE, "\"ab\"."},
9939
 
    {buf, 5, "ab/cd", 5, NULL, TRUE, "\"ab\"."},
9940
 
    {buf, 4, "ab/cd", 5, NULL, TRUE, "\"ab\""},
9941
 
    {buf, 3, "ab/cd", 5, NULL, TRUE, "\"a\""},
9942
 
    {buf, 2, "ab/cd", 5, NULL, TRUE, "\"\""},
9943
 
    /* XXX probably "" is a better result in this case
9944
 
    {buf, 1, "ab/cd", 5, NULL, TRUE, "."},
9945
 
    */
9946
 
    {buf, 0, "ab/cd", 5, NULL, TRUE, ""},
9947
 
  };
9948
 
 
9949
 
  for (i = 0; i < sizeof(test_input) / sizeof(test_input[0]); i++) {
9950
 
 
9951
 
    char* end;
9952
 
    ibool ok = TRUE;
9953
 
    size_t  res_len;
9954
 
 
9955
 
    fprintf(stderr, "TESTING %lu, %s, %lu, %s\n",
9956
 
      test_input[i].buflen,
9957
 
      test_input[i].id,
9958
 
      test_input[i].idlen,
9959
 
      test_input[i].expected);
9960
 
 
9961
 
    end = innobase_convert_name(
9962
 
      test_input[i].buf,
9963
 
      test_input[i].buflen,
9964
 
      test_input[i].id,
9965
 
      test_input[i].idlen,
9966
 
      test_input[i].session,
9967
 
      test_input[i].file_id);
9968
 
 
9969
 
    res_len = (size_t) (end - test_input[i].buf);
9970
 
 
9971
 
    if (res_len != strlen(test_input[i].expected)) {
9972
 
 
9973
 
      fprintf(stderr, "unexpected len of the result: %u, "
9974
 
        "expected: %u\n", (unsigned) res_len,
9975
 
        (unsigned) strlen(test_input[i].expected));
9976
 
      ok = FALSE;
9977
 
    }
9978
 
 
9979
 
    if (memcmp(test_input[i].buf,
9980
 
         test_input[i].expected,
9981
 
         strlen(test_input[i].expected)) != 0
9982
 
        || !ok) {
9983
 
 
9984
 
      fprintf(stderr, "unexpected result: %.*s, "
9985
 
        "expected: %s\n", (int) res_len,
9986
 
        test_input[i].buf,
9987
 
        test_input[i].expected);
9988
 
      ok = FALSE;
9989
 
    }
9990
 
 
9991
 
    if (ok) {
9992
 
      fprintf(stderr, "OK: res: %.*s\n\n", (int) res_len,
9993
 
        buf);
9994
 
    } else {
9995
 
      fprintf(stderr, "FAILED\n\n");
9996
 
      return;
9997
 
    }
9998
 
  }
 
8955
        char    buf[1024];
 
8956
        ulint   i;
 
8957
 
 
8958
        innobase_convert_name_test_t test_input[] = {
 
8959
                {buf, sizeof(buf), "abcd", 4, NULL, TRUE, "\"abcd\""},
 
8960
                {buf, 7, "abcd", 4, NULL, TRUE, "\"abcd\""},
 
8961
                {buf, 6, "abcd", 4, NULL, TRUE, "\"abcd\""},
 
8962
                {buf, 5, "abcd", 4, NULL, TRUE, "\"abc\""},
 
8963
                {buf, 4, "abcd", 4, NULL, TRUE, "\"ab\""},
 
8964
 
 
8965
                {buf, sizeof(buf), "ab@0060cd", 9, NULL, TRUE, "\"ab`cd\""},
 
8966
                {buf, 9, "ab@0060cd", 9, NULL, TRUE, "\"ab`cd\""},
 
8967
                {buf, 8, "ab@0060cd", 9, NULL, TRUE, "\"ab`cd\""},
 
8968
                {buf, 7, "ab@0060cd", 9, NULL, TRUE, "\"ab`cd\""},
 
8969
                {buf, 6, "ab@0060cd", 9, NULL, TRUE, "\"ab`c\""},
 
8970
                {buf, 5, "ab@0060cd", 9, NULL, TRUE, "\"ab`\""},
 
8971
                {buf, 4, "ab@0060cd", 9, NULL, TRUE, "\"ab\""},
 
8972
 
 
8973
                {buf, sizeof(buf), "ab\"cd", 5, NULL, TRUE,
 
8974
                        "\"#mysql50#ab\"\"cd\""},
 
8975
                {buf, 17, "ab\"cd", 5, NULL, TRUE,
 
8976
                        "\"#mysql50#ab\"\"cd\""},
 
8977
                {buf, 16, "ab\"cd", 5, NULL, TRUE,
 
8978
                        "\"#mysql50#ab\"\"c\""},
 
8979
                {buf, 15, "ab\"cd", 5, NULL, TRUE,
 
8980
                        "\"#mysql50#ab\"\"\""},
 
8981
                {buf, 14, "ab\"cd", 5, NULL, TRUE,
 
8982
                        "\"#mysql50#ab\""},
 
8983
                {buf, 13, "ab\"cd", 5, NULL, TRUE,
 
8984
                        "\"#mysql50#ab\""},
 
8985
                {buf, 12, "ab\"cd", 5, NULL, TRUE,
 
8986
                        "\"#mysql50#a\""},
 
8987
                {buf, 11, "ab\"cd", 5, NULL, TRUE,
 
8988
                        "\"#mysql50#\""},
 
8989
                {buf, 10, "ab\"cd", 5, NULL, TRUE,
 
8990
                        "\"#mysql50\""},
 
8991
 
 
8992
                {buf, sizeof(buf), "ab/cd", 5, NULL, TRUE, "\"ab\".\"cd\""},
 
8993
                {buf, 9, "ab/cd", 5, NULL, TRUE, "\"ab\".\"cd\""},
 
8994
                {buf, 8, "ab/cd", 5, NULL, TRUE, "\"ab\".\"c\""},
 
8995
                {buf, 7, "ab/cd", 5, NULL, TRUE, "\"ab\".\"\""},
 
8996
                {buf, 6, "ab/cd", 5, NULL, TRUE, "\"ab\"."},
 
8997
                {buf, 5, "ab/cd", 5, NULL, TRUE, "\"ab\"."},
 
8998
                {buf, 4, "ab/cd", 5, NULL, TRUE, "\"ab\""},
 
8999
                {buf, 3, "ab/cd", 5, NULL, TRUE, "\"a\""},
 
9000
                {buf, 2, "ab/cd", 5, NULL, TRUE, "\"\""},
 
9001
                /* XXX probably "" is a better result in this case
 
9002
                {buf, 1, "ab/cd", 5, NULL, TRUE, "."},
 
9003
                */
 
9004
                {buf, 0, "ab/cd", 5, NULL, TRUE, ""},
 
9005
        };
 
9006
 
 
9007
        for (i = 0; i < sizeof(test_input) / sizeof(test_input[0]); i++) {
 
9008
 
 
9009
                char*   end;
 
9010
                ibool   ok = TRUE;
 
9011
                size_t  res_len;
 
9012
 
 
9013
                fprintf(stderr, "TESTING %lu, %s, %lu, %s\n",
 
9014
                        test_input[i].buflen,
 
9015
                        test_input[i].id,
 
9016
                        test_input[i].idlen,
 
9017
                        test_input[i].expected);
 
9018
 
 
9019
                end = innobase_convert_name(
 
9020
                        test_input[i].buf,
 
9021
                        test_input[i].buflen,
 
9022
                        test_input[i].id,
 
9023
                        test_input[i].idlen,
 
9024
                        test_input[i].session,
 
9025
                        test_input[i].file_id);
 
9026
 
 
9027
                res_len = (size_t) (end - test_input[i].buf);
 
9028
 
 
9029
                if (res_len != strlen(test_input[i].expected)) {
 
9030
 
 
9031
                        fprintf(stderr, "unexpected len of the result: %u, "
 
9032
                                "expected: %u\n", (unsigned) res_len,
 
9033
                                (unsigned) strlen(test_input[i].expected));
 
9034
                        ok = FALSE;
 
9035
                }
 
9036
 
 
9037
                if (memcmp(test_input[i].buf,
 
9038
                           test_input[i].expected,
 
9039
                           strlen(test_input[i].expected)) != 0
 
9040
                    || !ok) {
 
9041
 
 
9042
                        fprintf(stderr, "unexpected result: %.*s, "
 
9043
                                "expected: %s\n", (int) res_len,
 
9044
                                test_input[i].buf,
 
9045
                                test_input[i].expected);
 
9046
                        ok = FALSE;
 
9047
                }
 
9048
 
 
9049
                if (ok) {
 
9050
                        fprintf(stderr, "OK: res: %.*s\n\n", (int) res_len,
 
9051
                                buf);
 
9052
                } else {
 
9053
                        fprintf(stderr, "FAILED\n\n");
 
9054
                        return;
 
9055
                }
 
9056
        }
9999
9057
}
10000
9058
 
10001
9059
#endif /* UNIV_COMPILE_TEST_FUNCS */