~drizzle-trunk/drizzle/development

« back to all changes in this revision

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

  • Committer: Monty Taylor
  • Date: 2010-04-22 02:46:23 UTC
  • mto: (1497.3.4 enable-dtrace)
  • mto: This revision was merged to the branch mainline in revision 1527.
  • Revision ID: mordred@inaugust.com-20100422024623-4urw8fi8eraci08p
Don't overwrite the pandora_vc_revinfo file if we don't have new
authoratative information.

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:
35
53
  - fix savepoint functions to use savepoint storage area
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"
102
108
#include "log0log.h"
103
109
#include "lock0lock.h"
104
110
#include "dict0crea.h"
105
 
#include "create_replication.h"
106
111
#include "btr0cur.h"
107
112
#include "btr0btr.h"
108
113
#include "fsp0fsp.h"
115
120
#include "ha_prototypes.h"
116
121
#include "ut0mem.h"
117
122
#include "ibuf0ibuf.h"
118
 
#include "mysql_addons.h"
119
123
}
120
124
 
121
125
#include "ha_innodb.h"
122
126
#include "data_dictionary.h"
123
 
#include "replication_dictionary.h"
124
 
#include "internal_dictionary.h"
125
127
#include "handler0vars.h"
126
128
 
127
129
#include <iostream>
129
131
#include <string>
130
132
 
131
133
#include "plugin/innobase/handler/status_function.h"
132
 
#include "plugin/innobase/handler/replication_log.h"
133
 
 
134
 
#include <google/protobuf/io/zero_copy_stream.h>
135
 
#include <google/protobuf/io/zero_copy_stream_impl.h>
136
 
#include <google/protobuf/io/coded_stream.h>
137
 
#include <google/protobuf/text_format.h>
138
134
 
139
135
using namespace std;
140
136
using namespace drizzled;
141
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
 
142
145
/** to protect innobase_open_files */
143
146
static pthread_mutex_t innobase_share_mutex;
144
147
/** to force correct commit order in binlog */
170
173
static plugin::TableFunction* innodb_trx_tool= NULL;
171
174
static plugin::TableFunction* innodb_locks_tool= NULL;
172
175
static plugin::TableFunction* innodb_lock_waits_tool= NULL;
173
 
static plugin::TableFunction* innodb_sys_tables_tool= NULL;
174
 
static plugin::TableFunction* innodb_sys_tablestats_tool= NULL;
175
 
 
176
 
static plugin::TableFunction* innodb_sys_indexes_tool= NULL;
177
 
static plugin::TableFunction* innodb_sys_columns_tool= NULL;
178
 
static plugin::TableFunction* innodb_sys_fields_tool= NULL;
179
 
static plugin::TableFunction* innodb_sys_foreign_tool= NULL;
180
 
static plugin::TableFunction* innodb_sys_foreign_cols_tool= NULL;
181
 
 
182
 
static ReplicationLog *replication_logger= NULL;
183
 
typedef constrained_check<uint32_t, UINT32_MAX, 10> open_files_constraint;
184
 
static open_files_constraint innobase_open_files;
185
 
typedef constrained_check<uint32_t, 10, 1> mirrored_log_groups_constraint;
186
 
static mirrored_log_groups_constraint innobase_mirrored_log_groups;
187
 
typedef constrained_check<uint32_t, 100, 2> log_files_in_group_constraint;
188
 
static log_files_in_group_constraint innobase_log_files_in_group;
189
 
typedef constrained_check<uint32_t, 6, 0> force_recovery_constraint;
190
 
force_recovery_constraint innobase_force_recovery;
191
 
typedef constrained_check<size_t, SIZE_MAX, 256*1024, 1024> log_buffer_constraint;
192
 
static log_buffer_constraint innobase_log_buffer_size;
193
 
typedef constrained_check<size_t, SIZE_MAX, 512*1024, 1024> additional_mem_pool_constraint;
194
 
static additional_mem_pool_constraint innobase_additional_mem_pool_size;
195
 
typedef constrained_check<unsigned int, 1000, 1> autoextend_constraint;
196
 
static autoextend_constraint innodb_auto_extend_increment;
197
 
typedef constrained_check<size_t, SIZE_MAX, 5242880, 1048576> buffer_pool_constraint;
198
 
static buffer_pool_constraint innobase_buffer_pool_size;
199
 
typedef constrained_check<uint32_t, MAX_BUFFER_POOLS, 1> buffer_pool_instances_constraint;
200
 
static buffer_pool_instances_constraint innobase_buffer_pool_instances;
201
 
typedef constrained_check<uint32_t, UINT32_MAX, 100> io_capacity_constraint;
202
 
static io_capacity_constraint innodb_io_capacity;
203
 
typedef constrained_check<uint32_t, 5000, 1> purge_batch_constraint;
204
 
static purge_batch_constraint innodb_purge_batch_size;
205
 
typedef constrained_check<uint32_t, 1, 0> purge_threads_constraint;
206
 
static purge_threads_constraint innodb_n_purge_threads;
207
 
typedef constrained_check<uint16_t, 2, 0> trinary_constraint;
208
 
static trinary_constraint innodb_flush_log_at_trx_commit;
209
 
typedef constrained_check<unsigned int, 99, 0> max_dirty_pages_constraint;
210
 
static max_dirty_pages_constraint innodb_max_dirty_pages_pct;
211
 
static uint64_constraint innodb_max_purge_lag;
212
 
static uint64_nonzero_constraint innodb_stats_sample_pages;
213
 
typedef constrained_check<uint32_t, 64, 1> io_threads_constraint;
214
 
static io_threads_constraint innobase_read_io_threads;
215
 
static io_threads_constraint innobase_write_io_threads;
216
 
 
217
 
typedef constrained_check<uint32_t, 1000, 0> concurrency_constraint;
218
 
static concurrency_constraint innobase_commit_concurrency;
219
 
static concurrency_constraint innobase_thread_concurrency;
220
 
static uint32_nonzero_constraint innodb_concurrency_tickets;
221
 
 
222
 
typedef constrained_check<int64_t, INT64_MAX, 1024*1024, 1024*1024> log_file_constraint;
223
 
static log_file_constraint innobase_log_file_size;
224
 
 
225
 
static uint64_constraint innodb_replication_delay;
226
 
 
227
 
/** Percentage of the buffer pool to reserve for 'old' blocks.
228
 
Connected to buf_LRU_old_ratio. */
229
 
typedef constrained_check<uint32_t, 95, 5> old_blocks_constraint;
230
 
static old_blocks_constraint innobase_old_blocks_pct;
231
 
 
232
 
static uint32_constraint innodb_sync_spin_loops;
233
 
static uint32_constraint innodb_spin_wait_delay;
234
 
static uint32_constraint innodb_thread_sleep_delay;
235
 
 
236
 
typedef constrained_check<uint32_t, 64, 0> read_ahead_threshold_constraint;
237
 
static read_ahead_threshold_constraint innodb_read_ahead_threshold;
 
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
 
 
181
static long innobase_mirrored_log_groups, innobase_log_files_in_group,
 
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;
 
186
static ulong innobase_commit_concurrency = 0;
 
187
static ulong innobase_read_io_threads;
 
188
static ulong innobase_write_io_threads;
 
189
 
 
190
/**
 
191
 * @TODO: Turn this into size_t as soon as we have a Variable<size_t>
 
192
 */
 
193
static int64_t innobase_buffer_pool_size, innobase_log_file_size;
238
194
 
239
195
/* The default values for the following char* start-up parameters
240
196
are determined in innobase_init below: */
241
197
 
242
 
std::string innobase_data_home_dir;
243
 
std::string innobase_data_file_path;
244
 
std::string innobase_log_group_home_dir;
245
 
static string innobase_file_format_name;
246
 
static string innobase_change_buffering;
247
 
 
248
 
/* The highest file format being used in the database. The value can be
249
 
set by user, however, it will be adjusted to the newer file format if
250
 
a table of such format is created/opened. */
251
 
static string innobase_file_format_max;
 
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;
 
203
 
 
204
/* Note: This variable can be set to on/off and any of the supported
 
205
file formats in the configuration file, but can only be set to any
 
206
of the supported file formats during runtime. */
 
207
static char*  innobase_file_format_check    = NULL;
 
208
 
 
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;
252
212
 
253
213
/* Below we have boolean-valued start-up parameters, and their default
254
214
values */
255
215
 
256
 
typedef constrained_check<uint16_t, 2, 0> trinary_constraint;
257
 
static trinary_constraint innobase_fast_shutdown;
258
 
 
259
 
/* "innobase_file_format_check" decides whether we would continue
260
 
booting the server if the file format stamped on the system
261
 
table space exceeds the maximum file format supported
262
 
by the server. Can be set during server startup at command
263
 
line or configure file, and a read only variable after
264
 
server startup */
265
 
 
266
 
/* If a new file format is introduced, the file format
267
 
name needs to be updated accordingly. Please refer to
268
 
file_format_name_map[] defined in trx0sys.c for the next
269
 
file format name. */
270
 
 
271
 
static my_bool  innobase_file_format_check = TRUE;
 
216
static ulong  innobase_fast_shutdown      = 1;
 
217
#ifdef UNIV_LOG_ARCHIVE
 
218
static my_bool  innobase_log_archive      = FALSE;
 
219
static char*  innobase_log_arch_dir     = NULL;
 
220
#endif /* UNIV_LOG_ARCHIVE */
272
221
static my_bool  innobase_use_doublewrite    = TRUE;
273
222
static my_bool  innobase_use_checksums      = TRUE;
274
223
static my_bool  innobase_rollback_on_timeout    = FALSE;
275
224
static my_bool  innobase_create_status_file   = FALSE;
276
 
static bool innobase_use_replication_log;
277
 
static bool support_xa;
278
 
static bool strict_mode;
279
 
typedef constrained_check<uint32_t, 1024*1024*1024, 1> lock_wait_constraint;
280
 
static lock_wait_constraint lock_wait_timeout;
 
225
static my_bool  innobase_stats_on_metadata    = TRUE;
281
226
 
282
227
static char*  internal_innobase_data_file_path  = NULL;
283
228
 
 
229
static char*  innodb_version_str = (char*) INNODB_VERSION_STR;
 
230
 
284
231
/* The following counter is used to convey information to InnoDB
285
232
about server activity: in selects it is not sensible to call
286
233
srv_active_wake_master_thread after each fetch or search, we only do
298
245
/** Allowed values of innodb_change_buffering */
299
246
static const char* innobase_change_buffering_values[IBUF_USE_COUNT] = {
300
247
  "none",   /* IBUF_USE_NONE */
301
 
  "inserts",    /* IBUF_USE_INSERT */
302
 
  "deletes",    /* IBUF_USE_DELETE_MARK */
303
 
  "changes",    /* IBUF_USE_INSERT_DELETE_MARK */
304
 
  "purges",     /* IBUF_USE_DELETE */
305
 
  "all"         /* IBUF_USE_ALL */
 
248
  "inserts" /* IBUF_USE_INSERT */
306
249
};
307
250
 
308
 
/* "GEN_CLUST_INDEX" is the name reserved for Innodb default
309
 
system primary index. */
310
 
static const char innobase_index_reserve_name[]= "GEN_CLUST_INDEX";
311
 
 
312
251
/********************************************************************
313
252
Gives the file extension of an InnoDB single-table tablespace. */
314
253
static const char* ha_innobase_exts[] = {
342
281
  {
343
282
    int err= 0;
344
283
    if (innodb_inited) {
 
284
 
345
285
      srv_fast_shutdown = (ulint) innobase_fast_shutdown;
346
286
      innodb_inited = 0;
347
287
      hash_table_free(innobase_open_tables);
358
298
      pthread_mutex_destroy(&commit_cond_m);
359
299
      pthread_cond_destroy(&commit_cond);
360
300
    }
361
 
    
362
 
    /* These get strdup'd from vm variables */
363
 
 
364
301
  }
365
302
 
366
303
private:
390
327
  {
391
328
    return doRollback(session, all); /* XA rollback just does a SQL ROLLBACK */
392
329
  }
393
 
  virtual uint64_t doGetCurrentTransactionId(Session *session);
394
 
  virtual uint64_t doGetNewTransactionId(Session *session);
395
330
  virtual int doCommit(Session* session, bool all);
396
331
  virtual int doRollback(Session* session, bool all);
397
332
 
435
370
        /* out: 0 or error number */
436
371
    ::drizzled::XID *xid);  /* in: X/Open XA transaction identification */
437
372
 
438
 
  virtual Cursor *create(Table &table)
 
373
  virtual Cursor *create(TableShare &table,
 
374
                         memory::Root *mem_root)
439
375
  {
440
 
    return new ha_innobase(*this, table);
 
376
    return new (mem_root) ha_innobase(*this, table);
441
377
  }
442
378
 
443
379
  /*********************************************************************
446
382
  doDropSchema(
447
383
  /*===================*/
448
384
        /* out: error number */
449
 
    const SchemaIdentifier  &identifier); /* in: database path; inside InnoDB the name
 
385
    SchemaIdentifier  &identifier); /* in: database path; inside InnoDB the name
450
386
        of the last directory in the path is used as
451
387
        the database name: for example, in 'mysql/data/test'
452
388
        the database name is 'test' */
485
421
 
486
422
  UNIV_INTERN int doCreateTable(Session &session,
487
423
                                Table &form,
488
 
                                const TableIdentifier &identifier,
 
424
                                drizzled::TableIdentifier &identifier,
489
425
                                message::Table&);
490
 
  UNIV_INTERN int doRenameTable(Session&, const TableIdentifier &from, const TableIdentifier &to);
491
 
  UNIV_INTERN int doDropTable(Session &session, const TableIdentifier &identifier);
 
426
  UNIV_INTERN int doRenameTable(Session&, TableIdentifier &from, TableIdentifier &to);
 
427
  UNIV_INTERN int doDropTable(Session &session, TableIdentifier &identifier);
492
428
 
493
429
  UNIV_INTERN virtual bool get_error_message(int error, String *buf);
494
430
 
507
443
  }
508
444
 
509
445
  int doGetTableDefinition(drizzled::Session& session,
510
 
                           const TableIdentifier &identifier,
 
446
                           drizzled::TableIdentifier &identifier,
511
447
                           drizzled::message::Table &table_proto);
512
448
 
513
 
  bool doDoesTableExist(drizzled::Session& session, const TableIdentifier &identifier);
 
449
  void doGetTableNames(drizzled::CachedDirectory &directory,
 
450
           drizzled::SchemaIdentifier &schema_identifier,
 
451
                       std::set<std::string> &set_of_names);
 
452
 
 
453
  bool doDoesTableExist(drizzled::Session& session, drizzled::TableIdentifier &identifier);
514
454
 
515
455
  void doGetTableIdentifiers(drizzled::CachedDirectory &directory,
516
 
                             const drizzled::SchemaIdentifier &schema_identifier,
517
 
                             drizzled::TableIdentifier::vector &set_of_identifiers);
518
 
  bool validateCreateTableOption(const std::string &key, const std::string &state);
519
 
  void dropTemporarySchema();
520
 
 
 
456
                             drizzled::SchemaIdentifier &schema_identifier,
 
457
                             drizzled::TableIdentifiers &set_of_identifiers);
521
458
};
522
459
 
523
 
 
524
 
bool InnobaseEngine::validateCreateTableOption(const std::string &key, const std::string &state)
525
 
{
526
 
  if (boost::iequals(key, "ROW_FORMAT"))
527
 
  {
528
 
    if (boost::iequals(state, "COMPRESSED"))
529
 
      return true;
530
 
 
531
 
    if (boost::iequals(state, "COMPACT"))
532
 
      return true;
533
 
 
534
 
    if (boost::iequals(state, "DYNAMIC"))
535
 
      return true;
536
 
 
537
 
    if (boost::iequals(state, "REDUNDANT"))
538
 
      return true;
539
 
  }
540
 
 
541
 
  return false;
542
 
}
543
 
 
544
460
void InnobaseEngine::doGetTableIdentifiers(drizzled::CachedDirectory &directory,
545
 
                                           const drizzled::SchemaIdentifier &schema_identifier,
546
 
                                           drizzled::TableIdentifier::vector &set_of_identifiers)
 
461
                                           drizzled::SchemaIdentifier &schema_identifier,
 
462
                                           drizzled::TableIdentifiers &set_of_identifiers)
547
463
{
548
464
  CachedDirectory::Entries entries= directory.getEntries();
549
465
 
562
478
    { }
563
479
    else
564
480
    {
565
 
      std::string path;
566
 
      path+= directory.getPath();
567
 
      path+= FN_LIBCHAR;
568
 
      path+= entry->filename;
569
 
 
570
 
      message::Table definition;
571
 
      if (StorageEngine::readTableFile(path, definition))
572
 
      {
573
 
        /* 
574
 
           Using schema_identifier here to stop unused warning, could use
575
 
           definition.schema() instead
576
 
        */
577
 
        TableIdentifier identifier(schema_identifier.getSchemaName(), definition.name());
578
 
        set_of_identifiers.push_back(identifier);
579
 
      }
 
481
      char uname[NAME_LEN + 1];
 
482
      uint32_t file_name_len;
 
483
 
 
484
      file_name_len= filename_to_tablename(filename->c_str(), uname, sizeof(uname));
 
485
      // TODO: Remove need for memory copy here
 
486
      uname[file_name_len - sizeof(DEFAULT_FILE_EXTENSION) + 1]= '\0'; // Subtract ending, place NULL 
 
487
 
 
488
      set_of_identifiers.push_back(TableIdentifier(schema_identifier, uname));
580
489
    }
581
490
  }
582
491
}
583
492
 
584
 
bool InnobaseEngine::doDoesTableExist(Session &session, const TableIdentifier &identifier)
 
493
bool InnobaseEngine::doDoesTableExist(Session&, TableIdentifier &identifier)
585
494
{
586
495
  string proto_path(identifier.getPath());
587
496
  proto_path.append(DEFAULT_FILE_EXTENSION);
588
497
 
589
 
  if (session.getMessageCache().doesTableMessageExist(identifier))
590
 
    return true;
591
 
 
592
498
  if (access(proto_path.c_str(), F_OK))
593
499
  {
594
500
    return false;
597
503
  return true;
598
504
}
599
505
 
600
 
int InnobaseEngine::doGetTableDefinition(Session &session,
601
 
                                         const TableIdentifier &identifier,
 
506
int InnobaseEngine::doGetTableDefinition(Session &,
 
507
                                         drizzled::TableIdentifier &identifier,
602
508
                                         message::Table &table_proto)
603
509
{
604
510
  string proto_path(identifier.getPath());
605
511
  proto_path.append(DEFAULT_FILE_EXTENSION);
606
512
 
607
 
  // First we check the temporary tables.
608
 
  if (session.getMessageCache().getTableMessage(identifier, table_proto))
609
 
    return EEXIST;
610
 
 
611
513
  if (access(proto_path.c_str(), F_OK))
612
514
  {
613
515
    return errno;
619
521
  return ENOENT;
620
522
}
621
523
 
 
524
void InnobaseEngine::doGetTableNames(CachedDirectory &directory, SchemaIdentifier&, set<string>& set_of_names)
 
525
{
 
526
  CachedDirectory::Entries entries= directory.getEntries();
 
527
 
 
528
  for (CachedDirectory::Entries::iterator entry_iter= entries.begin(); 
 
529
       entry_iter != entries.end(); ++entry_iter)
 
530
  {
 
531
    CachedDirectory::Entry *entry= *entry_iter;
 
532
    const string *filename= &entry->filename;
 
533
 
 
534
    assert(filename->size());
 
535
 
 
536
    const char *ext= strchr(filename->c_str(), '.');
 
537
 
 
538
    if (ext == NULL || my_strcasecmp(system_charset_info, ext, DEFAULT_FILE_EXTENSION) ||
 
539
        (filename->compare(0, strlen(TMP_FILE_PREFIX), TMP_FILE_PREFIX) == 0))
 
540
    { }
 
541
    else
 
542
    {
 
543
      char uname[NAME_LEN + 1];
 
544
      uint32_t file_name_len;
 
545
 
 
546
      file_name_len= filename_to_tablename(filename->c_str(), uname, sizeof(uname));
 
547
      // TODO: Remove need for memory copy here
 
548
      uname[file_name_len - sizeof(DEFAULT_FILE_EXTENSION) + 1]= '\0'; // Subtract ending, place NULL 
 
549
      set_of_names.insert(uname);
 
550
    }
 
551
  }
 
552
}
 
553
 
 
554
/** @brief Initialize the default value of innodb_commit_concurrency.
 
555
 
 
556
Once InnoDB is running, the innodb_commit_concurrency must not change
 
557
from zero to nonzero. (Bug #42101)
 
558
 
 
559
The initial default value is 0, and without this extra initialization,
 
560
SET GLOBAL innodb_commit_concurrency=DEFAULT would set the parameter
 
561
to 0, even if it was initially set to nonzero at the command line
 
562
or configuration file. */
 
563
static
 
564
void
 
565
innobase_commit_concurrency_init_default(void);
 
566
/*==========================================*/
622
567
 
623
568
/************************************************************//**
624
569
Validate the file format name and return its corresponding id.
631
576
            name */
632
577
/************************************************************//**
633
578
Validate the file format check config parameters, as a side effect it
634
 
sets the srv_max_file_format_at_startup variable.
635
 
@return the format_id if valid config value, otherwise, return -1 */
636
 
static
637
 
int
638
 
innobase_file_format_validate_and_set(
 
579
sets the srv_check_file_format_at_startup variable.
 
580
@return true if one of  "on" or "off" */
 
581
static
 
582
bool
 
583
innobase_file_format_check_on_off(
 
584
/*==============================*/
 
585
  const char* format_check);    /*!< in: parameter value */
 
586
/************************************************************//**
 
587
Validate the file format check config parameters, as a side effect it
 
588
sets the srv_check_file_format_at_startup variable.
 
589
@return true if valid config value */
 
590
static
 
591
bool
 
592
innobase_file_format_check_validate(
639
593
/*================================*/
640
 
  const char* format_max);    /*!< in: parameter value */
 
594
  const char* format_check);    /*!< in: parameter value */
641
595
 
642
596
static const char innobase_engine_name[]= "InnoDB";
643
597
 
 
598
/*************************************************************//**
 
599
Check for a valid value of innobase_commit_concurrency.
 
600
@return 0 for valid innodb_commit_concurrency */
 
601
static
 
602
int
 
603
innobase_commit_concurrency_validate(
 
604
/*=================================*/
 
605
  Session*      , /*!< in: thread handle */
 
606
  drizzle_sys_var*  , /*!< in: pointer to system
 
607
            variable */
 
608
  void*       save, /*!< out: immediate result
 
609
            for update function */
 
610
  drizzle_value*    value)  /*!< in: incoming string */
 
611
{
 
612
  int64_t   intbuf;
 
613
  ulong   commit_concurrency;
 
614
 
 
615
  if (value->val_int(value, &intbuf)) {
 
616
    /* The value is NULL. That is invalid. */
 
617
    return(1);
 
618
  }
 
619
 
 
620
  *reinterpret_cast<ulong*>(save) = commit_concurrency
 
621
    = static_cast<ulong>(intbuf);
 
622
 
 
623
  /* Allow the value to be updated, as long as it remains zero
 
624
  or nonzero. */
 
625
  return(!(!commit_concurrency == !innobase_commit_concurrency));
 
626
}
 
627
 
 
628
static DRIZZLE_SessionVAR_BOOL(support_xa, PLUGIN_VAR_OPCMDARG,
 
629
  "Enable InnoDB support for the XA two-phase commit",
 
630
  /* check_func */ NULL, /* update_func */ NULL,
 
631
  /* default */ TRUE);
 
632
 
 
633
static DRIZZLE_SessionVAR_BOOL(table_locks, PLUGIN_VAR_OPCMDARG,
 
634
  "Enable InnoDB locking in LOCK TABLES",
 
635
  /* check_func */ NULL, /* update_func */ NULL,
 
636
  /* default */ TRUE);
 
637
 
 
638
static DRIZZLE_SessionVAR_BOOL(strict_mode, PLUGIN_VAR_OPCMDARG,
 
639
  "Use strict mode when evaluating create options.",
 
640
  NULL, NULL, FALSE);
 
641
 
 
642
static DRIZZLE_SessionVAR_ULONG(lock_wait_timeout, PLUGIN_VAR_RQCMDARG,
 
643
  "Timeout in seconds an InnoDB transaction may wait for a lock before being rolled back. Values above 100000000 disable the timeout.",
 
644
  NULL, NULL, 50, 1, 1024 * 1024 * 1024, 0);
 
645
 
644
646
 
645
647
/*****************************************************************//**
646
648
Commits a transaction in an InnoDB database. */
667
669
  (char*) &export_vars.innodb_buffer_pool_pages_misc,   SHOW_LONG},
668
670
  {"buffer_pool_pages_total",
669
671
  (char*) &export_vars.innodb_buffer_pool_pages_total,    SHOW_LONG},
670
 
  {"buffer_pool_read_ahead",
671
 
  (char*) &export_vars.innodb_buffer_pool_read_ahead, SHOW_LONG},
672
 
  {"buffer_pool_read_ahead_evicted",
673
 
  (char*) &export_vars.innodb_buffer_pool_read_ahead_evicted, SHOW_LONG},
 
672
  {"buffer_pool_read_ahead_rnd",
 
673
  (char*) &export_vars.innodb_buffer_pool_read_ahead_rnd, SHOW_LONG},
 
674
  {"buffer_pool_read_ahead_seq",
 
675
  (char*) &export_vars.innodb_buffer_pool_read_ahead_seq, SHOW_LONG},
674
676
  {"buffer_pool_read_requests",
675
677
  (char*) &export_vars.innodb_buffer_pool_read_requests,  SHOW_LONG},
676
678
  {"buffer_pool_reads",
907
909
ibool
908
910
thd_supports_xa(
909
911
/*============*/
910
 
  void* )  /*!< in: thread handle (Session*), or NULL to query
 
912
  void* session)  /*!< in: thread handle (Session*), or NULL to query
911
913
        the global innodb_supports_xa */
912
914
{
913
 
  /* TODO: Add support here for per-session value */
914
 
  return(support_xa);
 
915
  return(SessionVAR((Session*) session, support_xa));
915
916
}
916
917
 
917
918
/******************************************************************//**
921
922
ulong
922
923
thd_lock_wait_timeout(
923
924
/*==================*/
924
 
  void*)  /*!< in: thread handle (Session*), or NULL to query
 
925
  void* session)  /*!< in: thread handle (Session*), or NULL to query
925
926
      the global innodb_lock_wait_timeout */
926
927
{
927
 
  /* TODO: Add support here for per-session value */
928
928
  /* According to <drizzle/plugin.h>, passing session == NULL
929
929
  returns the global value of the session variable. */
930
 
  return((ulong)lock_wait_timeout.get());
931
 
}
932
 
 
933
 
/******************************************************************//**
934
 
Set the time waited for the lock for the current query. */
935
 
extern "C" UNIV_INTERN
936
 
void
937
 
thd_set_lock_wait_time(
938
 
/*===================*/
939
 
        void*   thd,    /*!< in: thread handle (THD*) */
940
 
        ulint   value)  /*!< in: time waited for the lock */
941
 
{
942
 
        if (thd) {
943
 
          static_cast<Session*>(thd)->utime_after_lock+= value;
944
 
        }
 
930
  return(SessionVAR((Session*) session, lock_wait_timeout));
945
931
}
946
932
 
947
933
/********************************************************************//**
956
942
  return *(trx_t**) session->getEngineData(innodb_engine_ptr);
957
943
}
958
944
 
959
 
 
960
 
plugin::ReplicationReturnCode ReplicationLog::apply(Session &session,
961
 
                                                    const message::Transaction &message)
962
 
{
963
 
  char *data= new char[message.ByteSize()];
964
 
 
965
 
  message.SerializeToArray(data, message.ByteSize());
966
 
 
967
 
  trx_t *trx= session_to_trx(&session);
968
 
 
969
 
  uint64_t trx_id= message.transaction_context().transaction_id();
970
 
  ulint error= insert_replication_message(data, message.ByteSize(), trx, trx_id);
971
 
  (void)error;
972
 
 
973
 
  delete[] data;
974
 
 
975
 
  return plugin::SUCCESS;
976
 
}
977
 
 
978
945
/********************************************************************//**
979
946
Call this function when mysqld passes control to the client. That is to
980
947
avoid deadlocks on the adaptive hash S-latch possibly held by session. For more
1036
1003
  case DB_SUCCESS:
1037
1004
    return(0);
1038
1005
 
1039
 
  case DB_INTERRUPTED:
1040
 
    my_error(ER_QUERY_INTERRUPTED, MYF(0));
1041
 
    /* fall through */
1042
 
 
1043
 
  case DB_FOREIGN_EXCEED_MAX_CASCADE:
1044
 
    push_warning_printf(session, DRIZZLE_ERROR::WARN_LEVEL_WARN,
1045
 
                        HA_ERR_ROW_IS_REFERENCED,
1046
 
                        "InnoDB: Cannot delete/update "
1047
 
                        "rows with cascading foreign key "
1048
 
                        "constraints that exceed max "
1049
 
                        "depth of %d. Please "
1050
 
                        "drop extra constraints and try "
1051
 
                        "again", DICT_FK_MAX_RECURSIVE_LOAD);
1052
 
    /* fall through */
1053
 
 
1054
1006
  case DB_ERROR:
1055
1007
  default:
1056
1008
    return(-1); /* unspecified error */
1057
1009
 
1058
1010
  case DB_DUPLICATE_KEY:
1059
 
    /* Be cautious with returning this error, since
1060
 
       mysql could re-enter the storage layer to get
1061
 
       duplicated key info, the operation requires a
1062
 
       valid table handle and/or transaction information,
1063
 
       which might not always be available in the error
1064
 
       handling stage. */
1065
1011
    return(HA_ERR_FOUND_DUPP_KEY);
1066
1012
 
1067
1013
  case DB_FOREIGN_DUPLICATE_KEY:
1148
1094
    and the actual error code name could very well be different.
1149
1095
    This will require some monitoring, ie. the status
1150
1096
    of this request on our part.*/
1151
 
 
1152
 
    /* New error code HA_ERR_TOO_MANY_CONCURRENT_TRXS is only
1153
 
       available in 5.1.38 and later, but the plugin should still
1154
 
       work with previous versions of MySQL.
1155
 
       In Drizzle we seem to not have this yet.
1156
 
    */
1157
 
#ifdef HA_ERR_TOO_MANY_CONCURRENT_TRXS
1158
 
    return(HA_ERR_TOO_MANY_CONCURRENT_TRXS);
1159
 
#else /* HA_ERR_TOO_MANY_CONCURRENT_TRXS */
 
1097
#ifdef ER_TOO_MANY_CONCURRENT_TRXS
 
1098
    return(ER_TOO_MANY_CONCURRENT_TRXS);
 
1099
#else
1160
1100
    return(HA_ERR_RECORD_FILE_FULL);
1161
 
#endif /* HA_ERR_TOO_MANY_CONCURRENT_TRXS */
 
1101
#endif
1162
1102
  case DB_UNSUPPORTED:
1163
1103
    return(HA_ERR_UNSUPPORTED);
1164
1104
  }
1165
1105
}
1166
1106
 
 
1107
/*************************************************************//**
 
1108
If you want to print a session that is not associated with the current thread,
 
1109
you must call this function before reserving the InnoDB kernel_mutex, to
 
1110
protect Drizzle from setting session->query NULL. If you print a session of the
 
1111
current thread, we know that Drizzle cannot modify sesion->query, and it is
 
1112
not necessary to call this. Call innobase_mysql_end_print_arbitrary_thd()
 
1113
after you release the kernel_mutex.
 
1114
 
 
1115
DRIZZLE: Note, we didn't change this name to avoid more ifdef forking 
 
1116
         in non-Cursor code.
 
1117
 */
 
1118
extern "C" UNIV_INTERN
 
1119
void
 
1120
innobase_mysql_prepare_print_arbitrary_thd(void)
 
1121
/*============================================*/
 
1122
{
 
1123
  ut_ad(!mutex_own(&kernel_mutex));
 
1124
  pthread_mutex_lock(&LOCK_thread_count);
 
1125
}
 
1126
 
 
1127
/*************************************************************//**
 
1128
Releases the mutex reserved by innobase_mysql_prepare_print_arbitrary_thd().
 
1129
In the InnoDB latching order, the mutex sits right above the
 
1130
kernel_mutex.  In debug builds, we assert that the kernel_mutex is
 
1131
released before this function is invoked. 
 
1132
 
 
1133
DRIZZLE: Note, we didn't change this name to avoid more ifdef forking 
 
1134
         in non-Cursor code.
 
1135
*/
 
1136
extern "C" UNIV_INTERN
 
1137
void
 
1138
innobase_mysql_end_print_arbitrary_thd(void)
 
1139
/*========================================*/
 
1140
{
 
1141
  ut_ad(!mutex_own(&kernel_mutex));
 
1142
  pthread_mutex_unlock(&LOCK_thread_count);
 
1143
}
1167
1144
 
1168
1145
/*************************************************************//**
1169
1146
Prints info of a Session object (== user session thread) to the given file. */
1185
1162
          session->getSecurityContext().getIp().c_str(),
1186
1163
          session->getSecurityContext().getUser().c_str()
1187
1164
  );
1188
 
  fprintf(f, "\n%s", session->getQueryString()->c_str());
 
1165
  fprintf(f,
 
1166
          "\n%s", session->getQueryString().c_str()
 
1167
  );
1189
1168
  putc('\n', f);
1190
1169
}
1191
1170
 
1208
1187
  if (cs) {
1209
1188
    *mbminlen = cs->mbminlen;
1210
1189
    *mbmaxlen = cs->mbmaxlen;
1211
 
    ut_ad(*mbminlen < DATA_MBMAX);
1212
 
    ut_ad(*mbmaxlen < DATA_MBMAX);
1213
1190
  } else {
1214
1191
    ut_a(cset == 0);
1215
1192
    *mbminlen = *mbmaxlen = 0;
1277
1254
/*=================*/
1278
1255
  void* mysql_session)  /*!< in: MySQL thread handle */
1279
1256
{
1280
 
  return static_cast<Session*>(mysql_session)->charset();
 
1257
  return session_charset(static_cast<Session*>(mysql_session));
1281
1258
}
1282
1259
 
1283
1260
extern "C" UNIV_INTERN
1297
1274
  return pthread_mutex_init(fast_mutex, MY_MUTEX_INIT_FAST);
1298
1275
}
1299
1276
 
1300
 
/**********************************************************************//**
1301
 
Determines the current SQL statement.
1302
 
@return        SQL statement string */
1303
 
extern "C" UNIV_INTERN
1304
 
const char*
1305
 
innobase_get_stmt(
1306
 
/*==============*/
1307
 
       void*   session,        /*!< in: MySQL thread handle */
1308
 
       size_t* length)         /*!< out: length of the SQL statement */
1309
 
{
1310
 
  return static_cast<Session*>(session)->getQueryStringCopy(*length);
1311
 
}
1312
 
 
1313
1277
#if defined (__WIN__) && defined (MYSQL_DYNAMIC_PLUGIN)
1314
1278
/*******************************************************************//**
1315
1279
Map an OS error to an errno value. The OS error number is stored in
1471
1435
  INSERT INTO T VALUES(), (), ();
1472
1436
 
1473
1437
innobase_next_autoinc() will be called with increment set to
 
1438
n * 3 where autoinc_lock_mode != TRADITIONAL because we want
1474
1439
to reserve 3 values for the multi-value INSERT above.
1475
1440
@return the next value */
1476
1441
static
1575
1540
  trx = trx_allocate_for_mysql();
1576
1541
 
1577
1542
  trx->mysql_thd = session;
 
1543
  trx->mysql_query_str = session->query.c_str();
1578
1544
 
1579
1545
  innobase_trx_init(session, trx);
1580
1546
 
1613
1579
Construct ha_innobase Cursor. */
1614
1580
UNIV_INTERN
1615
1581
ha_innobase::ha_innobase(plugin::StorageEngine &engine_arg,
1616
 
                         Table &table_arg)
 
1582
                         TableShare &table_arg)
1617
1583
  :Cursor(engine_arg, table_arg),
1618
1584
  primary_key(0), /* needs initialization because index_flags() may be called 
1619
1585
                     before this is set to the real value. It's ok to have any 
1620
1586
                     value here because it doesn't matter if we return the
1621
1587
                     HA_DO_INDEX_COND_PUSHDOWN bit from those "early" calls */
1622
1588
  start_of_scan(0),
1623
 
  num_write_row(0)
 
1589
  num_doInsertRecord(0)
1624
1590
{}
1625
1591
 
1626
1592
/*********************************************************************//**
1642
1608
{
1643
1609
  trx_t*    trx;
1644
1610
 
1645
 
  assert(session);
1646
1611
  trx = check_trx_exists(session);
1647
1612
 
1648
1613
  if (prebuilt->trx != trx) {
1653
1618
  user_session = session;
1654
1619
}
1655
1620
 
 
1621
/*********************************************************************//**
 
1622
Updates the user_thd field in a handle and also allocates a new InnoDB
 
1623
transaction handle if needed, and updates the transaction fields in the
 
1624
prebuilt struct. */
 
1625
UNIV_INTERN
 
1626
void
 
1627
ha_innobase::update_session()
 
1628
/*=====================*/
 
1629
{
 
1630
  Session*  session = ha_session();
 
1631
  ut_ad(EQ_CURRENT_SESSION(session));
 
1632
  update_session(session);
 
1633
}
 
1634
 
1656
1635
/*****************************************************************//**
1657
1636
Convert an SQL identifier to the MySQL system_charset_info (UTF-8)
1658
1637
and quote it if needed.
1688
1667
    nz[idlen] = 0;
1689
1668
 
1690
1669
    s = nz2;
1691
 
    idlen = TableIdentifier::filename_to_tablename(nz, nz2, sizeof nz2);
 
1670
    idlen = filename_to_tablename(nz, nz2, sizeof nz2);
1692
1671
  }
1693
1672
 
1694
1673
  /* See if the identifier needs to be quoted. */
1804
1783
/*===============*/
1805
1784
  trx_t*  trx)  /*!< in: transaction */
1806
1785
{
1807
 
  return(trx && trx->mysql_thd && static_cast<Session*>(trx->mysql_thd)->getKilled());
1808
 
}
1809
 
 
1810
 
/**********************************************************************//**
1811
 
Determines if the currently running transaction is in strict mode.
1812
 
@return TRUE if strict */
1813
 
extern "C" UNIV_INTERN
1814
 
ibool
1815
 
trx_is_strict(
1816
 
/*==========*/
1817
 
        trx_t*  trx)    /*!< in: transaction */
1818
 
{
1819
 
        return(trx && trx->mysql_thd
1820
 
               && true);
 
1786
  return(trx && trx->mysql_thd && session_killed((Session*) trx->mysql_thd));
1821
1787
}
1822
1788
 
1823
1789
/**************************************************************//**
1833
1799
  prebuilt->read_just_key = 0;
1834
1800
}
1835
1801
 
1836
 
template<class T>
1837
 
void align_value(T& value, size_t align_val= 1024)
1838
 
{
1839
 
  value= value - (value % align_val);
1840
 
}
1841
 
 
1842
 
static void auto_extend_update(Session *, sql_var_t)
1843
 
{
1844
 
  srv_auto_extend_increment= innodb_auto_extend_increment.get();
1845
 
}
1846
 
 
1847
 
static void io_capacity_update(Session *, sql_var_t)
1848
 
{
1849
 
  srv_io_capacity= innodb_io_capacity.get();
1850
 
}
1851
 
 
1852
 
static void purge_batch_update(Session *, sql_var_t)
1853
 
{
1854
 
  srv_purge_batch_size= innodb_purge_batch_size.get();
1855
 
}
1856
 
 
1857
 
static void purge_threads_update(Session *, sql_var_t)
1858
 
{
1859
 
  srv_n_purge_threads= innodb_n_purge_threads.get();
1860
 
}
1861
 
 
1862
 
static void innodb_adaptive_hash_index_update(Session *, sql_var_t)
1863
 
{
1864
 
  if (btr_search_enabled)
1865
 
  {
1866
 
    btr_search_enable();
1867
 
  } else {
1868
 
    btr_search_disable();
1869
 
  }
1870
 
}
1871
 
 
1872
 
static void innodb_old_blocks_pct_update(Session *, sql_var_t)
1873
 
{
1874
 
  innobase_old_blocks_pct= buf_LRU_old_ratio_update(innobase_old_blocks_pct.get(), TRUE);
1875
 
}
1876
 
 
1877
 
static void innodb_thread_concurrency_update(Session *, sql_var_t)
1878
 
{
1879
 
  srv_thread_concurrency= innobase_thread_concurrency.get();
1880
 
}
1881
 
 
1882
 
static void innodb_sync_spin_loops_update(Session *, sql_var_t)
1883
 
{
1884
 
  srv_n_spin_wait_rounds= innodb_sync_spin_loops.get();
1885
 
}
1886
 
 
1887
 
static void innodb_spin_wait_delay_update(Session *, sql_var_t)
1888
 
{
1889
 
  srv_spin_wait_delay= innodb_spin_wait_delay.get();
1890
 
}
1891
 
 
1892
 
static void innodb_thread_sleep_delay_update(Session *, sql_var_t)
1893
 
{
1894
 
  srv_thread_sleep_delay= innodb_thread_sleep_delay.get();
1895
 
}
1896
 
 
1897
 
static void innodb_read_ahead_threshold_update(Session *, sql_var_t)
1898
 
{
1899
 
  srv_read_ahead_threshold= innodb_read_ahead_threshold.get();
1900
 
}
1901
 
 
1902
 
 
1903
 
static int innodb_commit_concurrency_validate(Session *session, set_var *var)
1904
 
{
1905
 
   uint32_t new_value= var->save_result.uint32_t_value;
1906
 
 
1907
 
   if ((innobase_commit_concurrency.get() == 0 && new_value != 0) ||
1908
 
       (innobase_commit_concurrency.get() != 0 && new_value == 0))
1909
 
   {
1910
 
     push_warning_printf(session,
1911
 
                         DRIZZLE_ERROR::WARN_LEVEL_WARN,
1912
 
                         ER_WRONG_ARGUMENTS,
1913
 
                         _("Once InnoDB is running, innodb_commit_concurrency "
1914
 
                           "must not change between zero and nonzero."));
1915
 
     return 1;
1916
 
   }
1917
 
   return 0;
1918
 
}
1919
 
 
1920
 
/*************************************************************//**
1921
 
Check if it is a valid file format. This function is registered as
1922
 
a callback with MySQL.
1923
 
@return 0 for valid file format */
1924
 
static
1925
 
int
1926
 
innodb_file_format_name_validate(
1927
 
/*=============================*/
1928
 
  Session*      , /*!< in: thread handle */
1929
 
  set_var *var)
1930
 
{
1931
 
  const char *file_format_input = var->value->str_value.ptr();
1932
 
  if (file_format_input == NULL)
1933
 
    return 1;
1934
 
 
1935
 
  if (file_format_input != NULL) {
1936
 
    uint  format_id;
1937
 
 
1938
 
    format_id = innobase_file_format_name_lookup(
1939
 
      file_format_input);
1940
 
 
1941
 
    if (format_id <= DICT_TF_FORMAT_MAX) {
1942
 
      innobase_file_format_name =
1943
 
        trx_sys_file_format_id_to_name(format_id);
1944
 
 
1945
 
      return(0);
1946
 
    }
1947
 
  }
1948
 
 
1949
 
  return(1);
1950
 
}
1951
 
 
1952
 
/*************************************************************//**
1953
 
Check if it is a valid value of innodb_change_buffering. This function is
1954
 
registered as a callback with MySQL.
1955
 
@return 0 for valid innodb_change_buffering */
1956
 
static
1957
 
int
1958
 
innodb_change_buffering_validate(
1959
 
/*=============================*/
1960
 
  Session*      , /*!< in: thread handle */
1961
 
  set_var *var)
1962
 
{
1963
 
  const char *change_buffering_input = var->value->str_value.ptr();
1964
 
 
1965
 
  if (change_buffering_input == NULL)
1966
 
    return 1;
1967
 
 
1968
 
  ulint use;
1969
 
 
1970
 
  for (use = 0;
1971
 
       use < UT_ARR_SIZE(innobase_change_buffering_values);
1972
 
       ++use) {
1973
 
    if (!innobase_strcasecmp(change_buffering_input,
1974
 
                             innobase_change_buffering_values[use]))
1975
 
    {
1976
 
      ibuf_use= static_cast<ibuf_use_t>(use); 
1977
 
      return 0;
1978
 
    }
1979
 
  }
1980
 
 
1981
 
  return 1;
1982
 
}
1983
 
 
1984
 
 
1985
 
/*************************************************************//**
1986
 
Check if valid argument to innodb_file_format_max. This function
1987
 
is registered as a callback with MySQL.
1988
 
@return 0 for valid file format */
1989
 
static
1990
 
int
1991
 
innodb_file_format_max_validate(
1992
 
/*==============================*/
1993
 
  Session*   session, /*!< in: thread handle */
1994
 
  set_var *var)
1995
 
{
1996
 
  const char *file_format_input = var->value->str_value.ptr();
1997
 
  if (file_format_input == NULL)
1998
 
    return 1;
1999
 
 
2000
 
  if (file_format_input != NULL) {
2001
 
    int format_id = innobase_file_format_validate_and_set(file_format_input);
2002
 
 
2003
 
    if (format_id > DICT_TF_FORMAT_MAX) {
2004
 
      /* DEFAULT is "on", which is invalid at runtime. */
2005
 
      return 1;
2006
 
    }
2007
 
 
2008
 
    if (format_id >= 0) {
2009
 
      innobase_file_format_max= 
2010
 
        trx_sys_file_format_id_to_name((uint)format_id);
2011
 
 
2012
 
      /* Update the max format id in the system tablespace. */
2013
 
      char name_buff[100];
2014
 
      strcpy(name_buff, innobase_file_format_max.c_str());
2015
 
      if (trx_sys_file_format_max_set(format_id, (const char **)&name_buff))
2016
 
      {
2017
 
        errmsg_printf(ERRMSG_LVL_WARN,
2018
 
                      " [Info] InnoDB: the file format in the system "
2019
 
                      "tablespace is now set to %s.\n", name_buff);
2020
 
        innobase_file_format_max= name_buff;
2021
 
      }
2022
 
      return(0);
2023
 
 
2024
 
    } else {
2025
 
      push_warning_printf(session,
2026
 
                          DRIZZLE_ERROR::WARN_LEVEL_WARN,
2027
 
                          ER_WRONG_ARGUMENTS,
2028
 
                          "InnoDB: invalid innodb_file_format_max "
2029
 
                          "value; can be any format up to %s "
2030
 
                          "or equivalent id of %d",
2031
 
                          trx_sys_file_format_id_to_name(DICT_TF_FORMAT_MAX),
2032
 
                          DICT_TF_FORMAT_MAX);
2033
 
    }
2034
 
  }
2035
 
 
2036
 
  return(1);
2037
 
}
2038
 
 
2039
 
 
2040
1802
/*********************************************************************//**
2041
1803
Opens an InnoDB database.
2042
1804
@return 0 on success, error code on failure */
2044
1806
int
2045
1807
innobase_init(
2046
1808
/*==========*/
2047
 
  module::Context &context) /*!< in: Drizzle Plugin Context */
 
1809
  plugin::Context &context) /*!< in: Drizzle Plugin Context */
2048
1810
{
 
1811
  static char current_dir[3];   /*!< Set if using current lib */
2049
1812
  int   err;
2050
1813
  bool    ret;
 
1814
  char    *default_path;
2051
1815
  uint    format_id;
2052
 
  InnobaseEngine *actuall_engine_ptr;
2053
 
  const module::option_map &vm= context.getOptions();
2054
 
 
2055
 
  srv_auto_extend_increment= innodb_auto_extend_increment.get();
2056
 
  srv_io_capacity= innodb_io_capacity.get();
2057
 
  srv_purge_batch_size= innodb_purge_batch_size.get();
2058
 
  srv_n_purge_threads= innodb_n_purge_threads.get();
2059
 
  srv_flush_log_at_trx_commit= innodb_flush_log_at_trx_commit.get();
2060
 
  srv_max_buf_pool_modified_pct= innodb_max_dirty_pages_pct.get();
2061
 
  srv_max_purge_lag= innodb_max_purge_lag.get();
2062
 
  srv_stats_sample_pages= innodb_stats_sample_pages.get();
2063
 
  srv_n_free_tickets_to_enter= innodb_concurrency_tickets.get();
2064
 
  srv_replication_delay= innodb_replication_delay.get();
2065
 
  srv_thread_concurrency= innobase_thread_concurrency.get();
2066
 
  srv_n_spin_wait_rounds= innodb_sync_spin_loops.get();
2067
 
  srv_spin_wait_delay= innodb_spin_wait_delay.get();
2068
 
  srv_thread_sleep_delay= innodb_thread_sleep_delay.get();
2069
 
  srv_read_ahead_threshold= innodb_read_ahead_threshold.get();
2070
 
 
2071
 
  /* Inverted Booleans */
2072
 
 
2073
 
  innobase_use_checksums= (vm.count("disable-checksums")) ? false : true;
2074
 
  innobase_use_doublewrite= (vm.count("disable-doublewrite")) ? false : true;
2075
 
  srv_adaptive_flushing= (vm.count("disable-adaptive-flushing")) ? false : true;
2076
 
  srv_use_sys_malloc= (vm.count("use-internal-malloc")) ? false : true;
2077
 
  support_xa= (vm.count("disable-xa")) ? false : true;
2078
 
  btr_search_enabled= (vm.count("disable-adaptive-hash-index")) ? false : true;
2079
 
 
2080
 
 
2081
 
  /* Hafta do this here because we need to late-bind the default value */
2082
 
  if (vm.count("data-home-dir"))
2083
 
  {
2084
 
    innobase_data_home_dir= vm["data-home-dir"].as<string>();
2085
 
  }
2086
 
  else
2087
 
  {
2088
 
    innobase_data_home_dir= getDataHome().file_string();
2089
 
  }
2090
 
 
2091
 
 
2092
 
  if (vm.count("data-file-path"))
2093
 
  {
2094
 
    innobase_data_file_path= vm["data-file-path"].as<string>();
2095
 
  }
2096
 
 
2097
 
 
2098
 
  innodb_engine_ptr= actuall_engine_ptr= new InnobaseEngine(innobase_engine_name);
 
1816
 
 
1817
  innodb_engine_ptr= new InnobaseEngine(innobase_engine_name);
2099
1818
 
2100
1819
  ut_a(DATA_MYSQL_TRUE_VARCHAR == (ulint)DRIZZLE_TYPE_VARCHAR);
2101
1820
 
2102
1821
#ifdef UNIV_DEBUG
2103
1822
  static const char test_filename[] = "-@";
2104
1823
  char      test_tablename[sizeof test_filename
2105
 
    + sizeof srv_mysql50_table_name_prefix];
 
1824
        + sizeof srv_mysql50_table_name_prefix];
2106
1825
  if ((sizeof test_tablename) - 1
2107
1826
      != filename_to_tablename(test_filename, test_tablename,
2108
 
                               sizeof test_tablename)
 
1827
      sizeof test_tablename)
2109
1828
      || strncmp(test_tablename,
2110
 
                 srv_mysql50_table_name_prefix,
2111
 
                 sizeof srv_mysql50_table_name_prefix)
 
1829
      srv_mysql50_table_name_prefix,
 
1830
      sizeof srv_mysql50_table_name_prefix)
2112
1831
      || strcmp(test_tablename
2113
 
                + sizeof srv_mysql50_table_name_prefix,
2114
 
                test_filename)) {
 
1832
      + sizeof srv_mysql50_table_name_prefix,
 
1833
      test_filename)) {
2115
1834
    errmsg_printf(ERRMSG_LVL_ERROR, "tablename encoding has been changed");
2116
1835
    goto error;
2117
1836
  }
2118
1837
#endif /* UNIV_DEBUG */
2119
1838
 
 
1839
  /* Check that values don't overflow on 32-bit systems. */
 
1840
  if (sizeof(ulint) == 4) {
 
1841
    if (innobase_buffer_pool_size > UINT32_MAX) {
 
1842
      errmsg_printf(ERRMSG_LVL_ERROR, 
 
1843
        "innobase_buffer_pool_size can't be over 4GB"
 
1844
        " on 32-bit systems");
 
1845
 
 
1846
      goto error;
 
1847
    }
 
1848
 
 
1849
    if (innobase_log_file_size > UINT32_MAX) {
 
1850
      errmsg_printf(ERRMSG_LVL_ERROR, 
 
1851
        "innobase_log_file_size can't be over 4GB"
 
1852
        " on 32-bit systems");
 
1853
 
 
1854
      goto error;
 
1855
    }
 
1856
  }
 
1857
 
2120
1858
  os_innodb_umask = (ulint)internal::my_umask;
2121
1859
 
 
1860
  /* First calculate the default path for innodb_data_home_dir etc.,
 
1861
  in case the user has not given any value.
 
1862
 
 
1863
  Note that when using the embedded server, the datadirectory is not
 
1864
  necessarily the current directory of this program. */
 
1865
 
 
1866
  /* It's better to use current lib, to keep paths short */
 
1867
  current_dir[0] = FN_CURLIB;
 
1868
  current_dir[1] = FN_LIBCHAR;
 
1869
  current_dir[2] = 0;
 
1870
  default_path = current_dir;
 
1871
 
 
1872
  ut_a(default_path);
 
1873
 
 
1874
  srv_set_thread_priorities = TRUE;
 
1875
  srv_query_thread_priority = QUERY_PRIOR;
2122
1876
 
2123
1877
  /* Set InnoDB initialization parameters according to the values
2124
 
    read from MySQL .cnf file */
 
1878
  read from MySQL .cnf file */
2125
1879
 
2126
1880
  /*--------------- Data files -------------------------*/
2127
1881
 
2128
1882
  /* The default dir for data files is the datadir of MySQL */
2129
1883
 
2130
 
  srv_data_home = (char *)innobase_data_home_dir.c_str();
 
1884
  srv_data_home = (innobase_data_home_dir ? innobase_data_home_dir :
 
1885
       default_path);
2131
1886
 
2132
1887
  /* Set default InnoDB data file size to 10 MB and let it be
2133
 
    auto-extending. Thus users can use InnoDB in >= 4.0 without having
2134
 
    to specify any startup options. */
 
1888
  auto-extending. Thus users can use InnoDB in >= 4.0 without having
 
1889
  to specify any startup options. */
2135
1890
 
2136
 
  if (innobase_data_file_path.empty()) 
2137
 
  {
2138
 
    innobase_data_file_path= std::string("ibdata1:10M:autoextend");
 
1891
  if (!innobase_data_file_path) {
 
1892
    innobase_data_file_path = (char*) "ibdata1:10M:autoextend";
2139
1893
  }
2140
1894
 
2141
1895
  /* Since InnoDB edits the argument in the next call, we make another
2142
 
    copy of it: */
 
1896
  copy of it: */
2143
1897
 
2144
 
  internal_innobase_data_file_path = strdup(innobase_data_file_path.c_str());
 
1898
  internal_innobase_data_file_path = strdup(innobase_data_file_path);
2145
1899
 
2146
1900
  ret = (bool) srv_parse_data_file_paths_and_sizes(
2147
 
                                                   internal_innobase_data_file_path);
 
1901
    internal_innobase_data_file_path);
2148
1902
  if (ret == FALSE) {
2149
1903
    errmsg_printf(ERRMSG_LVL_ERROR, 
2150
 
                  "InnoDB: syntax error in innodb_data_file_path");
 
1904
      "InnoDB: syntax error in innodb_data_file_path");
2151
1905
mem_free_and_error:
2152
1906
    srv_free_paths_and_sizes();
2153
1907
    if (internal_innobase_data_file_path)
2159
1913
 
2160
1914
  /* The default dir for log files is the datadir of MySQL */
2161
1915
 
2162
 
  if (vm.count("log-group-home-dir"))
2163
 
  {
2164
 
    innobase_log_group_home_dir= vm["log-group-home-dir"].as<string>();
2165
 
  }
2166
 
  else
2167
 
  {
2168
 
    innobase_log_group_home_dir= getDataHome().file_string();
2169
 
  }
 
1916
  if (!innobase_log_group_home_dir) {
 
1917
    innobase_log_group_home_dir = default_path;
 
1918
  }
 
1919
 
 
1920
#ifdef UNIV_LOG_ARCHIVE
 
1921
  /* Since innodb_log_arch_dir has no relevance under MySQL,
 
1922
  starting from 4.0.6 we always set it the same as
 
1923
  innodb_log_group_home_dir: */
 
1924
 
 
1925
  innobase_log_arch_dir = innobase_log_group_home_dir;
 
1926
 
 
1927
  srv_arch_dir = innobase_log_arch_dir;
 
1928
#endif /* UNIG_LOG_ARCHIVE */
2170
1929
 
2171
1930
  ret = (bool)
2172
 
    srv_parse_log_group_home_dirs((char *)innobase_log_group_home_dir.c_str());
 
1931
    srv_parse_log_group_home_dirs(innobase_log_group_home_dir);
2173
1932
 
2174
 
  if (ret == FALSE || innobase_mirrored_log_groups.get() != 1) {
2175
 
    errmsg_printf(ERRMSG_LVL_ERROR,
2176
 
                  _("syntax error in innodb_log_group_home_dir, or a "
2177
 
                  "wrong number of mirrored log groups"));
 
1933
  if (ret == FALSE || innobase_mirrored_log_groups != 1) {
 
1934
    errmsg_printf(ERRMSG_LVL_ERROR, "syntax error in innodb_log_group_home_dir, or a "
 
1935
        "wrong number of mirrored log groups");
2178
1936
 
2179
1937
    goto mem_free_and_error;
2180
1938
  }
2181
1939
 
2182
 
 
2183
1940
  /* Validate the file format by animal name */
2184
 
  if (vm.count("file-format"))
2185
 
  {
 
1941
  if (innobase_file_format_name != NULL) {
 
1942
 
2186
1943
    format_id = innobase_file_format_name_lookup(
2187
 
                                                 vm["file-format"].as<string>().c_str());
 
1944
      innobase_file_format_name);
2188
1945
 
2189
1946
    if (format_id > DICT_TF_FORMAT_MAX) {
2190
1947
 
2193
1950
      goto mem_free_and_error;
2194
1951
    }
2195
1952
  } else {
2196
 
    /* Set it to the default file format id.*/
 
1953
    /* Set it to the default file format id. Though this
 
1954
    should never happen. */
2197
1955
    format_id = 0;
2198
1956
  }
2199
1957
 
2200
1958
  srv_file_format = format_id;
2201
1959
 
2202
 
  innobase_file_format_name =
2203
 
    trx_sys_file_format_id_to_name(format_id);
2204
 
 
2205
 
  /* Check innobase_file_format_check variable */
2206
 
  if (!innobase_file_format_check)
2207
 
  {
2208
 
    /* Set the value to disable checking. */
2209
 
    srv_max_file_format_at_startup = DICT_TF_FORMAT_MAX + 1;
2210
 
  } else {
2211
 
    /* Set the value to the lowest supported format. */
2212
 
    srv_max_file_format_at_startup = DICT_TF_FORMAT_MIN;
2213
 
  }
2214
 
 
2215
 
  /* Did the user specify a format name that we support?
2216
 
     As a side effect it will update the variable
2217
 
     srv_max_file_format_at_startup */
2218
 
  if (innobase_file_format_validate_and_set(innobase_file_format_max.c_str()) < 0)
2219
 
  {
2220
 
    errmsg_printf(ERRMSG_LVL_ERROR, _("InnoDB: invalid "
2221
 
                    "innodb_file_format_max value: "
2222
 
                    "should be any value up to %s or its "
2223
 
                    "equivalent numeric id"),
2224
 
                    trx_sys_file_format_id_to_name(DICT_TF_FORMAT_MAX));
2225
 
    goto mem_free_and_error;
2226
 
  }
2227
 
 
2228
 
  if (vm.count("change-buffering"))
2229
 
  {
 
1960
  /* Given the type of innobase_file_format_name we have little
 
1961
  choice but to cast away the constness from the returned name.
 
1962
  innobase_file_format_name is used in the MySQL set variable
 
1963
  interface and so can't be const. */
 
1964
 
 
1965
  innobase_file_format_name = 
 
1966
    (char*) trx_sys_file_format_id_to_name(format_id);
 
1967
 
 
1968
  /* Process innobase_file_format_check variable */
 
1969
  ut_a(innobase_file_format_check != NULL);
 
1970
 
 
1971
  /* As a side effect it will set srv_check_file_format_at_startup
 
1972
  on valid input. First we check for "on"/"off". */
 
1973
  if (!innobase_file_format_check_on_off(innobase_file_format_check)) {
 
1974
 
 
1975
    /* Did the user specify a format name that we support ?
 
1976
    As a side effect it will update the variable
 
1977
    srv_check_file_format_at_startup */
 
1978
    if (!innobase_file_format_check_validate(
 
1979
      innobase_file_format_check)) {
 
1980
 
 
1981
      errmsg_printf(ERRMSG_LVL_ERROR, "InnoDB: invalid "
 
1982
          "innodb_file_format_check value: "
 
1983
          "should be either 'on' or 'off' or "
 
1984
          "any value up to %s or its "
 
1985
          "equivalent numeric id",
 
1986
          trx_sys_file_format_id_to_name(
 
1987
            DICT_TF_FORMAT_MAX));
 
1988
 
 
1989
      goto mem_free_and_error;
 
1990
    }
 
1991
  }
 
1992
 
 
1993
  if (innobase_change_buffering) {
2230
1994
    ulint use;
2231
1995
 
2232
1996
    for (use = 0;
2233
1997
         use < UT_ARR_SIZE(innobase_change_buffering_values);
2234
1998
         use++) {
2235
1999
      if (!innobase_strcasecmp(
2236
 
                               innobase_change_buffering.c_str(),
2237
 
                               innobase_change_buffering_values[use])) {
2238
 
        ibuf_use = static_cast<ibuf_use_t>(use);
 
2000
            innobase_change_buffering,
 
2001
            innobase_change_buffering_values[use])) {
 
2002
        ibuf_use = (ibuf_use_t) use;
2239
2003
        goto innobase_change_buffering_inited_ok;
2240
2004
      }
2241
2005
    }
2242
2006
 
2243
2007
    errmsg_printf(ERRMSG_LVL_ERROR,
2244
 
                  "InnoDB: invalid value "
2245
 
                  "innodb_change_buffering=%s",
2246
 
                  vm["change-buffering"].as<string>().c_str());
 
2008
        "InnoDB: invalid value "
 
2009
        "innodb_file_format_check=%s",
 
2010
        innobase_change_buffering);
2247
2011
    goto mem_free_and_error;
2248
2012
  }
2249
2013
 
2250
2014
innobase_change_buffering_inited_ok:
2251
2015
  ut_a((ulint) ibuf_use < UT_ARR_SIZE(innobase_change_buffering_values));
2252
 
  innobase_change_buffering = innobase_change_buffering_values[ibuf_use];
 
2016
  innobase_change_buffering = (char*)
 
2017
    innobase_change_buffering_values[ibuf_use];
2253
2018
 
2254
2019
  /* --------------------------------------------------*/
2255
2020
 
2256
 
  if (vm.count("flush-method") != 0)
2257
 
  {
2258
 
    srv_file_flush_method_str = (char *)vm["flush-method"].as<string>().c_str();
2259
 
  }
 
2021
  srv_file_flush_method_str = innobase_unix_file_flush_method;
2260
2022
 
2261
2023
  srv_n_log_groups = (ulint) innobase_mirrored_log_groups;
2262
2024
  srv_n_log_files = (ulint) innobase_log_files_in_group;
2263
2025
  srv_log_file_size = (ulint) innobase_log_file_size;
2264
2026
 
 
2027
#ifdef UNIV_LOG_ARCHIVE
 
2028
  srv_log_archive_on = (ulint) innobase_log_archive;
 
2029
#endif /* UNIV_LOG_ARCHIVE */
2265
2030
  srv_log_buffer_size = (ulint) innobase_log_buffer_size;
2266
2031
 
2267
2032
  srv_buf_pool_size = (ulint) innobase_buffer_pool_size;
2268
 
  srv_buf_pool_instances = (ulint) innobase_buffer_pool_instances;
2269
2033
 
2270
2034
  srv_mem_pool_size = (ulint) innobase_additional_mem_pool_size;
2271
2035
 
 
2036
  srv_n_file_io_threads = (ulint) innobase_file_io_threads;
2272
2037
  srv_n_read_io_threads = (ulint) innobase_read_io_threads;
2273
2038
  srv_n_write_io_threads = (ulint) innobase_write_io_threads;
2274
2039
 
2278
2043
  srv_use_checksums = (ibool) innobase_use_checksums;
2279
2044
 
2280
2045
#ifdef HAVE_LARGE_PAGES
2281
 
  if ((os_use_large_pages = (ibool) my_use_large_pages))
 
2046
        if ((os_use_large_pages = (ibool) my_use_large_pages))
2282
2047
    os_large_page_size = (ulint) opt_large_page_size;
2283
2048
#endif
2284
2049
 
2292
2057
  srv_print_verbose_log = true;
2293
2058
 
2294
2059
  /* Store the default charset-collation number of this MySQL
2295
 
    installation */
 
2060
  installation */
2296
2061
 
2297
2062
  data_mysql_default_charset_coll = (ulint)default_charset_info->number;
2298
2063
 
 
2064
 
 
2065
  innobase_commit_concurrency_init_default();
 
2066
 
2299
2067
  /* Since we in this module access directly the fields of a trx
2300
 
    struct, and due to different headers and flags it might happen that
2301
 
    mutex_t has a different size in this module and in InnoDB
2302
 
    modules, we check at run time that the size is the same in
2303
 
    these compilation modules. */
 
2068
  struct, and due to different headers and flags it might happen that
 
2069
  mutex_t has a different size in this module and in InnoDB
 
2070
  modules, we check at run time that the size is the same in
 
2071
  these compilation modules. */
2304
2072
 
2305
2073
  err = innobase_start_or_create_for_mysql();
2306
2074
 
2307
 
  if (err != DB_SUCCESS)
2308
 
  {
2309
 
    goto mem_free_and_error;
2310
 
  }
2311
 
 
2312
 
  err = dict_create_sys_replication_log();
2313
 
 
2314
2075
  if (err != DB_SUCCESS) {
2315
2076
    goto mem_free_and_error;
2316
2077
  }
2317
2078
 
2318
 
 
2319
 
  innobase_old_blocks_pct = buf_LRU_old_ratio_update(innobase_old_blocks_pct.get(),
2320
 
                                                     TRUE);
2321
 
 
2322
2079
  innobase_open_tables = hash_create(200);
2323
2080
  pthread_mutex_init(&innobase_share_mutex, MY_MUTEX_INIT_FAST);
2324
2081
  pthread_mutex_init(&prepare_commit_mutex, MY_MUTEX_INIT_FAST);
2327
2084
  pthread_cond_init(&commit_cond, NULL);
2328
2085
  innodb_inited= 1;
2329
2086
 
2330
 
  actuall_engine_ptr->dropTemporarySchema();
2331
 
 
2332
 
  status_table_function_ptr= new InnodbStatusTool;
 
2087
        status_table_function_ptr= new InnodbStatusTool;
2333
2088
 
2334
2089
  context.add(innodb_engine_ptr);
2335
2090
 
2356
2111
  innodb_lock_waits_tool= new(std::nothrow)InnodbTrxTool("INNODB_LOCK_WAITS");
2357
2112
  context.add(innodb_lock_waits_tool);
2358
2113
 
2359
 
  innodb_sys_tables_tool= new(std::nothrow)InnodbSysTablesTool();
2360
 
  context.add(innodb_sys_tables_tool);
2361
 
 
2362
 
  innodb_sys_tablestats_tool= new(std::nothrow)InnodbSysTableStatsTool();
2363
 
  context.add(innodb_sys_tablestats_tool);
2364
 
 
2365
 
  innodb_sys_indexes_tool= new(std::nothrow)InnodbSysIndexesTool();
2366
 
  context.add(innodb_sys_indexes_tool);
2367
 
 
2368
 
  innodb_sys_columns_tool= new(std::nothrow)InnodbSysColumnsTool();
2369
 
  context.add(innodb_sys_columns_tool);
2370
 
 
2371
 
  innodb_sys_fields_tool= new(std::nothrow)InnodbSysFieldsTool();
2372
 
  context.add(innodb_sys_fields_tool);
2373
 
 
2374
 
  innodb_sys_foreign_tool= new(std::nothrow)InnodbSysForeignTool();
2375
 
  context.add(innodb_sys_foreign_tool);
2376
 
 
2377
 
  innodb_sys_foreign_cols_tool= new(std::nothrow)InnodbSysForeignColsTool();
2378
 
  context.add(innodb_sys_foreign_cols_tool);
2379
 
 
2380
 
  context.add(new(std::nothrow)InnodbInternalTables());
2381
 
  context.add(new(std::nothrow)InnodbReplicationTable());
2382
 
 
2383
 
  if (innobase_use_replication_log)
2384
 
  {
2385
 
    replication_logger= new(std::nothrow)ReplicationLog();
2386
 
    context.add(replication_logger);
2387
 
    ReplicationLog::setup(replication_logger);
2388
 
  }
2389
 
 
2390
 
  context.registerVariable(new sys_var_const_string_val("data-home-dir", innobase_data_home_dir));
2391
 
  context.registerVariable(new sys_var_const_string_val("flush-method", 
2392
 
                                                        vm.count("flush-method") ?  vm["flush-method"].as<string>() : ""));
2393
 
  context.registerVariable(new sys_var_const_string_val("log-group-home-dir", innobase_log_group_home_dir));
2394
 
  context.registerVariable(new sys_var_const_string_val("data-file-path", innobase_data_file_path));
2395
 
  context.registerVariable(new sys_var_const_string_val("version", vm["version"].as<string>()));
2396
 
 
2397
 
 
2398
 
  context.registerVariable(new sys_var_bool_ptr_readonly("replication_log", &innobase_use_replication_log));
2399
 
  context.registerVariable(new sys_var_bool_ptr_readonly("checksums", &innobase_use_checksums));
2400
 
  context.registerVariable(new sys_var_bool_ptr_readonly("doublewrite", &innobase_use_doublewrite));
2401
 
  context.registerVariable(new sys_var_bool_ptr("file-per-table", &srv_file_per_table));
2402
 
  context.registerVariable(new sys_var_bool_ptr_readonly("file-format-check", &innobase_file_format_check));
2403
 
  context.registerVariable(new sys_var_bool_ptr("adaptive-flushing", &srv_adaptive_flushing));
2404
 
  context.registerVariable(new sys_var_bool_ptr("status-file", &innobase_create_status_file));
2405
 
  context.registerVariable(new sys_var_bool_ptr_readonly("use-sys-malloc", &srv_use_sys_malloc));
2406
 
  context.registerVariable(new sys_var_bool_ptr_readonly("use-native-aio", &srv_use_native_aio));
2407
 
 
2408
 
  context.registerVariable(new sys_var_bool_ptr("support-xa", &support_xa));
2409
 
  context.registerVariable(new sys_var_bool_ptr("strict_mode", &strict_mode));
2410
 
  context.registerVariable(new sys_var_constrained_value<uint32_t>("lock_wait_timeout", lock_wait_timeout));
2411
 
 
2412
 
  context.registerVariable(new sys_var_constrained_value_readonly<size_t>("additional_mem_pool_size",innobase_additional_mem_pool_size));
2413
 
  context.registerVariable(new sys_var_constrained_value<uint32_t>("autoextend_increment",
2414
 
                                                                   innodb_auto_extend_increment,
2415
 
                                                                   auto_extend_update));
2416
 
  context.registerVariable(new sys_var_constrained_value<uint32_t>("io_capacity",
2417
 
                                                                   innodb_io_capacity,
2418
 
                                                                   io_capacity_update));
2419
 
  context.registerVariable(new sys_var_constrained_value<uint32_t>("purge_batch_size",
2420
 
                                                                   innodb_purge_batch_size,
2421
 
                                                                   purge_batch_update));
2422
 
  context.registerVariable(new sys_var_constrained_value<uint32_t>("purge_threads",
2423
 
                                                                   innodb_n_purge_threads,
2424
 
                                                                   purge_threads_update));
2425
 
  context.registerVariable(new sys_var_constrained_value<uint16_t>("fast_shutdown", innobase_fast_shutdown));
2426
 
  context.registerVariable(new sys_var_std_string("file_format",
2427
 
                                                  innobase_file_format_name,
2428
 
                                                  innodb_file_format_name_validate));
2429
 
  context.registerVariable(new sys_var_std_string("change_buffering",
2430
 
                                                  innobase_change_buffering,
2431
 
                                                  innodb_change_buffering_validate));
2432
 
  context.registerVariable(new sys_var_std_string("file_format_max",
2433
 
                                                  innobase_file_format_max,
2434
 
                                                  innodb_file_format_max_validate));
2435
 
  context.registerVariable(new sys_var_constrained_value_readonly<size_t>("buffer_pool_size", innobase_buffer_pool_size));
2436
 
  context.registerVariable(new sys_var_constrained_value_readonly<int64_t>("log_file_size", innobase_log_file_size));
2437
 
  context.registerVariable(new sys_var_constrained_value_readonly<uint16_t>("flush_log_at_trx_commit",
2438
 
                                                  innodb_flush_log_at_trx_commit));
2439
 
  context.registerVariable(new sys_var_constrained_value_readonly<unsigned int>("max_dirty_pages_pct",
2440
 
                                                  innodb_max_dirty_pages_pct));
2441
 
  context.registerVariable(new sys_var_constrained_value_readonly<uint64_t>("max_purge_lag", innodb_max_purge_lag));
2442
 
  context.registerVariable(new sys_var_constrained_value_readonly<uint64_t>("stats_sample_pages", innodb_stats_sample_pages));
2443
 
  context.registerVariable(new sys_var_bool_ptr("adaptive_hash_index", &btr_search_enabled, innodb_adaptive_hash_index_update));
2444
 
 
2445
 
  context.registerVariable(new sys_var_constrained_value<uint32_t>("commit_concurrency",
2446
 
                                                                   innobase_commit_concurrency,
2447
 
                                                                   innodb_commit_concurrency_validate));
2448
 
  context.registerVariable(new sys_var_constrained_value<uint32_t>("concurrency_tickets",
2449
 
                                                                   innodb_concurrency_tickets));
2450
 
  context.registerVariable(new sys_var_constrained_value_readonly<uint32_t>("read_io_threads", innobase_read_io_threads));
2451
 
  context.registerVariable(new sys_var_constrained_value_readonly<uint32_t>("write_io_threads", innobase_write_io_threads));
2452
 
  context.registerVariable(new sys_var_constrained_value_readonly<uint64_t>("replication_delay", innodb_replication_delay));
2453
 
  context.registerVariable(new sys_var_constrained_value_readonly<uint32_t>("force_recovery", innobase_force_recovery));
2454
 
  context.registerVariable(new sys_var_constrained_value_readonly<size_t>("log_buffer_size", innobase_log_buffer_size));
2455
 
  context.registerVariable(new sys_var_constrained_value_readonly<uint32_t>("log_files_in_group", innobase_log_files_in_group));
2456
 
  context.registerVariable(new sys_var_constrained_value_readonly<uint32_t>("mirrored_log_groups", innobase_mirrored_log_groups));
2457
 
  context.registerVariable(new sys_var_constrained_value_readonly<uint32_t>("open_files", innobase_open_files));
2458
 
  context.registerVariable(new sys_var_constrained_value<uint32_t>("old_blocks_pct",
2459
 
                                                                   innobase_old_blocks_pct,
2460
 
                                                                   innodb_old_blocks_pct_update));
2461
 
  context.registerVariable(new sys_var_uint32_t_ptr("old_blocks_time", &buf_LRU_old_threshold_ms));
2462
 
  context.registerVariable(new sys_var_constrained_value<uint32_t>("sync_spin_loops", innodb_sync_spin_loops, innodb_sync_spin_loops_update));
2463
 
  context.registerVariable(new sys_var_constrained_value<uint32_t>("spin_wait_delay", innodb_spin_wait_delay, innodb_spin_wait_delay_update));
2464
 
  context.registerVariable(new sys_var_constrained_value<uint32_t>("thread_sleep_delay", innodb_thread_sleep_delay, innodb_thread_sleep_delay_update));
2465
 
  context.registerVariable(new sys_var_constrained_value<uint32_t>("thread_concurrency",
2466
 
                                                                   innobase_thread_concurrency,
2467
 
                                                                   innodb_thread_concurrency_update));
2468
 
  context.registerVariable(new sys_var_constrained_value<uint32_t>("read_ahead_threshold",
2469
 
                                                                   innodb_read_ahead_threshold,
2470
 
                                                                   innodb_read_ahead_threshold_update));
2471
2114
  /* Get the current high water mark format. */
2472
 
  innobase_file_format_max = trx_sys_file_format_max_get();
2473
 
  btr_search_fully_disabled = (!btr_search_enabled);
 
2115
  innobase_file_format_check = (char*) trx_sys_file_format_max_get();
2474
2116
 
2475
2117
  return(FALSE);
2476
2118
error:
2579
2221
    Note, the position is current because of
2580
2222
    prepare_commit_mutex */
2581
2223
retry:
2582
 
    if (innobase_commit_concurrency.get() > 0) {
 
2224
    if (innobase_commit_concurrency > 0) {
2583
2225
      pthread_mutex_lock(&commit_cond_m);
2584
2226
      commit_threads++;
2585
2227
 
2586
 
      if (commit_threads > innobase_commit_concurrency.get()) {
 
2228
      if (commit_threads > innobase_commit_concurrency) {
2587
2229
        commit_threads--;
2588
2230
        pthread_cond_wait(&commit_cond,
2589
2231
          &commit_cond_m);
2608
2250
    innobase_commit_low(trx);
2609
2251
    trx->flush_log_later = FALSE;
2610
2252
 
2611
 
    if (innobase_commit_concurrency.get() > 0) {
 
2253
    if (innobase_commit_concurrency > 0) {
2612
2254
      pthread_mutex_lock(&commit_cond_m);
2613
2255
      commit_threads--;
2614
2256
      pthread_cond_signal(&commit_cond);
2632
2274
    SQL statement */
2633
2275
 
2634
2276
    trx_mark_sql_stat_end(trx);
2635
 
 
2636
 
    if (! session_test_options(session, OPTION_NOT_AUTOCOMMIT | OPTION_BEGIN))
2637
 
    {
2638
 
      if (trx->conc_state != TRX_NOT_STARTED)
2639
 
      {
2640
 
        commit(session, TRUE);
2641
 
      }
2642
 
    }
2643
2277
  }
2644
2278
 
2645
2279
  trx->n_autoinc_rows = 0; /* Reset the number AUTO-INC rows required */
2654
2288
  threads: */
2655
2289
  srv_active_wake_master_thread();
2656
2290
 
2657
 
  if (trx->isolation_level <= TRX_ISO_READ_COMMITTED &&
2658
 
      trx->global_read_view)
2659
 
  {
2660
 
    /* At low transaction isolation levels we let
2661
 
       each consistent read set its own snapshot */
2662
 
    read_view_close_for_mysql(trx);
2663
 
  }
2664
 
 
2665
2291
  return(0);
2666
2292
}
2667
2293
 
2689
2315
 
2690
2316
  innobase_release_stat_resources(trx);
2691
2317
 
2692
 
  trx->n_autoinc_rows = 0;
2693
 
 
2694
2318
  /* If we had reserved the auto-inc lock for some table (if
2695
2319
  we come here to roll back the latest SQL statement) we
2696
2320
  release it now before a possibly lengthy rollback */
2705
2329
    error = trx_rollback_last_sql_stat_for_mysql(trx);
2706
2330
  }
2707
2331
 
2708
 
  if (trx->isolation_level <= TRX_ISO_READ_COMMITTED &&
2709
 
      trx->global_read_view)
2710
 
  {
2711
 
    /* At low transaction isolation levels we let
2712
 
       each consistent read set its own snapshot */
2713
 
    read_view_close_for_mysql(trx);
2714
 
  }
2715
 
 
2716
2332
  return(convert_error_code_to_mysql(error, 0, NULL));
2717
2333
}
2718
2334
 
2849
2465
 
2850
2466
  ut_a(trx);
2851
2467
 
2852
 
  assert(session->getKilled() != Session::NOT_KILLED ||
 
2468
  assert(session->killed != Session::NOT_KILLED ||
2853
2469
         trx->conc_state == TRX_NOT_STARTED);
2854
2470
 
2855
2471
  /* Warn if rolling back some things... */
2856
 
  if (session->getKilled() != Session::NOT_KILLED &&
 
2472
  if (session->killed != Session::NOT_KILLED &&
2857
2473
      trx->conc_state != TRX_NOT_STARTED &&
2858
 
      trx->undo_no > 0 &&
 
2474
      trx->undo_no.low > 0 &&
2859
2475
      global_system_variables.log_warnings)
2860
2476
  {
2861
 
      errmsg_printf(ERRMSG_LVL_WARN,
 
2477
      errmsg_printf(ERRMSG_LVL_WARN, 
2862
2478
      "Drizzle is closing a connection during a KILL operation\n"
2863
 
      "that has an active InnoDB transaction.  %llu row modifications will "
 
2479
      "that has an active InnoDB transaction.  %lu row modifications will "
2864
2480
      "roll back.\n",
2865
 
      (ullint) trx->undo_no);
 
2481
      (ulong) trx->undo_no.low);
2866
2482
  }
2867
2483
 
2868
2484
  innobase_rollback_trx(trx);
2879
2495
*****************************************************************************/
2880
2496
 
2881
2497
/****************************************************************//**
 
2498
Get the record format from the data dictionary.
 
2499
@return one of ROW_TYPE_REDUNDANT, ROW_TYPE_COMPACT,
 
2500
ROW_TYPE_COMPRESSED, ROW_TYPE_DYNAMIC */
 
2501
UNIV_INTERN
 
2502
enum row_type
 
2503
ha_innobase::get_row_type() const
 
2504
/*=============================*/
 
2505
{
 
2506
  if (prebuilt && prebuilt->table) {
 
2507
    const ulint flags = prebuilt->table->flags;
 
2508
 
 
2509
    if (UNIV_UNLIKELY(!flags)) {
 
2510
      return(ROW_TYPE_REDUNDANT);
 
2511
    }
 
2512
 
 
2513
    ut_ad(flags & DICT_TF_COMPACT);
 
2514
 
 
2515
    switch (flags & DICT_TF_FORMAT_MASK) {
 
2516
    case DICT_TF_FORMAT_51 << DICT_TF_FORMAT_SHIFT:
 
2517
      return(ROW_TYPE_COMPACT);
 
2518
    case DICT_TF_FORMAT_ZIP << DICT_TF_FORMAT_SHIFT:
 
2519
      if (flags & DICT_TF_ZSSIZE_MASK) {
 
2520
        return(ROW_TYPE_COMPRESSED);
 
2521
      } else {
 
2522
        return(ROW_TYPE_DYNAMIC);
 
2523
      }
 
2524
#if DICT_TF_FORMAT_ZIP != DICT_TF_FORMAT_MAX
 
2525
# error "DICT_TF_FORMAT_ZIP != DICT_TF_FORMAT_MAX"
 
2526
#endif
 
2527
    }
 
2528
  }
 
2529
  ut_ad(0);
 
2530
  return(ROW_TYPE_NOT_USED);
 
2531
}
 
2532
 
 
2533
 
 
2534
/****************************************************************//**
2882
2535
Returns the index type. */
2883
2536
UNIV_INTERN
2884
2537
const char*
2985
2638
}
2986
2639
 
2987
2640
/********************************************************************//**
2988
 
Get the upper limit of the MySQL integral and floating-point type.
2989
 
@return maximum allowed value for the field */
2990
 
static
2991
 
uint64_t
2992
 
innobase_get_int_col_max_value(
2993
 
/*===========================*/
2994
 
        const Field*    field)  /*!< in: MySQL field */
2995
 
{
2996
 
        uint64_t        max_value = 0;
2997
 
 
2998
 
        switch(field->key_type()) {
2999
 
        /* TINY */
3000
 
        case HA_KEYTYPE_BINARY:
3001
 
                max_value = 0xFFULL;
3002
 
                break;
3003
 
        /* LONG */
3004
 
        case HA_KEYTYPE_ULONG_INT:
3005
 
                max_value = 0xFFFFFFFFULL;
3006
 
                break;
3007
 
        case HA_KEYTYPE_LONG_INT:
3008
 
                max_value = 0x7FFFFFFFULL;
3009
 
                break;
3010
 
        /* BIG */
3011
 
        case HA_KEYTYPE_ULONGLONG:
3012
 
                max_value = 0xFFFFFFFFFFFFFFFFULL;
3013
 
                break;
3014
 
        case HA_KEYTYPE_LONGLONG:
3015
 
                max_value = 0x7FFFFFFFFFFFFFFFULL;
3016
 
                break;
3017
 
        case HA_KEYTYPE_DOUBLE:
3018
 
                /* We use the maximum as per IEEE754-2008 standard, 2^53 */
3019
 
                max_value = 0x20000000000000ULL;
3020
 
                break;
3021
 
        default:
3022
 
                ut_error;
3023
 
        }
3024
 
 
3025
 
        return(max_value);
3026
 
}
3027
 
 
3028
 
/*******************************************************************//**
3029
 
This function checks whether the index column information
3030
 
is consistent between KEY info from mysql and that from innodb index.
3031
 
@return TRUE if all column types match. */
3032
 
static
3033
 
ibool
3034
 
innobase_match_index_columns(
3035
 
/*=========================*/
3036
 
        const KeyInfo*          key_info,       /*!< in: Index info
3037
 
                                                from mysql */
3038
 
        const dict_index_t*     index_info)     /*!< in: Index info
3039
 
                                                from Innodb */
3040
 
{
3041
 
        const KeyPartInfo*      key_part;
3042
 
        const KeyPartInfo*      key_end;
3043
 
        const dict_field_t*     innodb_idx_fld;
3044
 
        const dict_field_t*     innodb_idx_fld_end;
3045
 
 
3046
 
        /* Check whether user defined index column count matches */
3047
 
        if (key_info->key_parts != index_info->n_user_defined_cols) {
3048
 
                return(FALSE);
3049
 
        }
3050
 
 
3051
 
        key_part = key_info->key_part;
3052
 
        key_end = key_part + key_info->key_parts;
3053
 
        innodb_idx_fld = index_info->fields;
3054
 
        innodb_idx_fld_end = index_info->fields + index_info->n_fields;
3055
 
 
3056
 
        /* Check each index column's datatype. We do not check
3057
 
        column name because there exists case that index
3058
 
        column name got modified in mysql but such change does not
3059
 
        propagate to InnoDB.
3060
 
        One hidden assumption here is that the index column sequences
3061
 
        are matched up between those in mysql and Innodb. */
3062
 
        for (; key_part != key_end; ++key_part) {
3063
 
                ulint   col_type;
3064
 
                ibool   is_unsigned;
3065
 
                ulint   mtype = innodb_idx_fld->col->mtype;
3066
 
 
3067
 
                /* Need to translate to InnoDB column type before
3068
 
                comparison. */
3069
 
                col_type = get_innobase_type_from_mysql_type(&is_unsigned,
3070
 
                                                             key_part->field);
3071
 
 
3072
 
                /* Ignore Innodb specific system columns. */
3073
 
                while (mtype == DATA_SYS) {
3074
 
                        innodb_idx_fld++;
3075
 
 
3076
 
                        if (innodb_idx_fld >= innodb_idx_fld_end) {
3077
 
                                return(FALSE);
3078
 
                        }
3079
 
                }
3080
 
 
3081
 
                if (col_type != mtype) {
3082
 
                        /* Column Type mismatches */
3083
 
                        return(FALSE);
3084
 
                }
3085
 
 
3086
 
                innodb_idx_fld++;
3087
 
        }
3088
 
 
3089
 
        return(TRUE);
3090
 
}
3091
 
 
3092
 
/*******************************************************************//**
3093
 
This function builds a translation table in INNOBASE_SHARE
3094
 
structure for fast index location with mysql array number from its
3095
 
table->key_info structure. This also provides the necessary translation
3096
 
between the key order in mysql key_info and Innodb ib_table->indexes if
3097
 
they are not fully matched with each other.
3098
 
Note we do not have any mutex protecting the translation table
3099
 
building based on the assumption that there is no concurrent
3100
 
index creation/drop and DMLs that requires index lookup. All table
3101
 
handle will be closed before the index creation/drop.
3102
 
@return TRUE if index translation table built successfully */
3103
 
static
3104
 
ibool
3105
 
innobase_build_index_translation(
3106
 
/*=============================*/
3107
 
        const Table*            table,    /*!< in: table in MySQL data
3108
 
                                          dictionary */
3109
 
        dict_table_t*           ib_table, /*!< in: table in Innodb data
3110
 
                                          dictionary */
3111
 
        INNOBASE_SHARE*         share)    /*!< in/out: share structure
3112
 
                                          where index translation table
3113
 
                                          will be constructed in. */
3114
 
{
3115
 
        ulint           mysql_num_index;
3116
 
        ulint           ib_num_index;
3117
 
        dict_index_t**  index_mapping;
3118
 
        ibool           ret = TRUE;
3119
 
 
3120
 
        mutex_enter(&dict_sys->mutex);
3121
 
 
3122
 
        mysql_num_index = table->getShare()->keys;
3123
 
        ib_num_index = UT_LIST_GET_LEN(ib_table->indexes);
3124
 
 
3125
 
        index_mapping = share->idx_trans_tbl.index_mapping;
3126
 
 
3127
 
        /* If there exists inconsistency between MySQL and InnoDB dictionary
3128
 
        (metadata) information, the number of index defined in MySQL
3129
 
        could exceed that in InnoDB, do not build index translation
3130
 
        table in such case */
3131
 
        if (UNIV_UNLIKELY(ib_num_index < mysql_num_index)) {
3132
 
                ret = FALSE;
3133
 
                goto func_exit;
3134
 
        }
3135
 
 
3136
 
        /* If index entry count is non-zero, nothing has
3137
 
        changed since last update, directly return TRUE */
3138
 
        if (share->idx_trans_tbl.index_count) {
3139
 
                /* Index entry count should still match mysql_num_index */
3140
 
                ut_a(share->idx_trans_tbl.index_count == mysql_num_index);
3141
 
                goto func_exit;
3142
 
        }
3143
 
 
3144
 
        /* The number of index increased, rebuild the mapping table */
3145
 
        if (mysql_num_index > share->idx_trans_tbl.array_size) {
3146
 
                index_mapping = (dict_index_t**) realloc(index_mapping,
3147
 
                                                        mysql_num_index *
3148
 
                                                         sizeof(*index_mapping));
3149
 
 
3150
 
                if (!index_mapping) {
3151
 
                        /* Report an error if index_mapping continues to be
3152
 
                        NULL and mysql_num_index is a non-zero value */
3153
 
                        errmsg_printf(ERRMSG_LVL_ERROR,
3154
 
                                      "InnoDB: fail to allocate memory for "
3155
 
                                        "index translation table. Number of "
3156
 
                                        "Index:%lu, array size:%lu",
3157
 
                                        mysql_num_index,
3158
 
                                        share->idx_trans_tbl.array_size);
3159
 
                        ret = FALSE;
3160
 
                        goto func_exit;
3161
 
                }
3162
 
 
3163
 
                share->idx_trans_tbl.array_size = mysql_num_index;
3164
 
        }
3165
 
 
3166
 
        /* For each index in the mysql key_info array, fetch its
3167
 
        corresponding InnoDB index pointer into index_mapping
3168
 
        array. */
3169
 
        for (ulint count = 0; count < mysql_num_index; count++) {
3170
 
 
3171
 
                /* Fetch index pointers into index_mapping according to mysql
3172
 
                index sequence */
3173
 
                index_mapping[count] = dict_table_get_index_on_name(
3174
 
                        ib_table, table->key_info[count].name);
3175
 
 
3176
 
                if (!index_mapping[count]) {
3177
 
                        errmsg_printf(ERRMSG_LVL_ERROR, "Cannot find index %s in InnoDB "
3178
 
                                        "index dictionary.",
3179
 
                                        table->key_info[count].name);
3180
 
                        ret = FALSE;
3181
 
                        goto func_exit;
3182
 
                }
3183
 
 
3184
 
                /* Double check fetched index has the same
3185
 
                column info as those in mysql key_info. */
3186
 
                if (!innobase_match_index_columns(&table->key_info[count],
3187
 
                                                  index_mapping[count])) {
3188
 
                        errmsg_printf(ERRMSG_LVL_ERROR, "Found index %s whose column info "
3189
 
                                        "does not match that of MySQL.",
3190
 
                                        table->key_info[count].name);
3191
 
                        ret = FALSE;
3192
 
                        goto func_exit;
3193
 
                }
3194
 
        }
3195
 
 
3196
 
        /* Successfully built the translation table */
3197
 
        share->idx_trans_tbl.index_count = mysql_num_index;
3198
 
 
3199
 
func_exit:
3200
 
        if (!ret) {
3201
 
                /* Build translation table failed. */
3202
 
                free(index_mapping);
3203
 
 
3204
 
                share->idx_trans_tbl.array_size = 0;
3205
 
                share->idx_trans_tbl.index_count = 0;
3206
 
                index_mapping = NULL;
3207
 
        }
3208
 
 
3209
 
        share->idx_trans_tbl.index_mapping = index_mapping;
3210
 
 
3211
 
        mutex_exit(&dict_sys->mutex);
3212
 
 
3213
 
        return(ret);
3214
 
}
3215
 
 
3216
 
/*******************************************************************//**
3217
 
This function uses index translation table to quickly locate the
3218
 
requested index structure.
3219
 
Note we do not have mutex protection for the index translatoin table
3220
 
access, it is based on the assumption that there is no concurrent
3221
 
translation table rebuild (fter create/drop index) and DMLs that
3222
 
require index lookup.
3223
 
@return dict_index_t structure for requested index. NULL if
3224
 
fail to locate the index structure. */
3225
 
static
3226
 
dict_index_t*
3227
 
innobase_index_lookup(
3228
 
/*==================*/
3229
 
        INNOBASE_SHARE* share,  /*!< in: share structure for index
3230
 
                                translation table. */
3231
 
        uint            keynr)  /*!< in: index number for the requested
3232
 
                                index */
3233
 
{
3234
 
        if (!share->idx_trans_tbl.index_mapping
3235
 
            || keynr >= share->idx_trans_tbl.index_count) {
3236
 
                return(NULL);
3237
 
        }
3238
 
 
3239
 
        return(share->idx_trans_tbl.index_mapping[keynr]);
3240
 
}
3241
 
 
3242
 
/********************************************************************//**
3243
2641
Set the autoinc column max value. This should only be called once from
3244
 
ha_innobase::open(). Therefore there's no need for a covering lock. */
 
2642
ha_innobase::open(). Therefore there's no need for a covering lock.
 
2643
@return DB_SUCCESS or error code */
3245
2644
UNIV_INTERN
3246
 
void
 
2645
ulint
3247
2646
ha_innobase::innobase_initialize_autoinc()
3248
2647
/*======================================*/
3249
2648
{
 
2649
  dict_index_t* index;
3250
2650
  uint64_t  auto_inc;
3251
 
  const Field*  field = getTable()->found_next_number_field;
3252
 
 
3253
 
  if (field != NULL) {
3254
 
    auto_inc = innobase_get_int_col_max_value(field);
3255
 
  } else {
3256
 
    /* We have no idea what's been passed in to us as the
3257
 
       autoinc column. We set it to the 0, effectively disabling
3258
 
       updates to the table. */
3259
 
    auto_inc = 0;
3260
 
 
 
2651
  const char* col_name;
 
2652
  ulint   error;
 
2653
 
 
2654
  col_name = table->found_next_number_field->field_name;
 
2655
  index = innobase_get_index(table->s->next_number_index);
 
2656
 
 
2657
  /* Execute SELECT MAX(col_name) FROM TABLE; */
 
2658
  error = row_search_max_autoinc(index, col_name, &auto_inc);
 
2659
 
 
2660
  switch (error) {
 
2661
  case DB_SUCCESS:
 
2662
 
 
2663
    /* At the this stage we don't know the increment
 
2664
    or the offset, so use default inrement of 1. */
 
2665
    ++auto_inc;
 
2666
    break;
 
2667
 
 
2668
  case DB_RECORD_NOT_FOUND:
3261
2669
    ut_print_timestamp(stderr);
3262
 
    fprintf(stderr, "  InnoDB: Unable to determine the AUTOINC "
3263
 
            "column name\n");
3264
 
  }
3265
 
 
3266
 
  if (srv_force_recovery >= SRV_FORCE_NO_IBUF_MERGE) {
3267
 
    /* If the recovery level is set so high that writes
3268
 
       are disabled we force the AUTOINC counter to 0
3269
 
       value effectively disabling writes to the table.
3270
 
       Secondly, we avoid reading the table in case the read
3271
 
       results in failure due to a corrupted table/index.
3272
 
 
3273
 
       We will not return an error to the client, so that the
3274
 
       tables can be dumped with minimal hassle.  If an error
3275
 
       were returned in this case, the first attempt to read
3276
 
       the table would fail and subsequent SELECTs would succeed. */
3277
 
    auto_inc = 0;
3278
 
  } else if (field == NULL) {
3279
 
    /* This is a far more serious error, best to avoid
3280
 
       opening the table and return failure. */
3281
 
    my_error(ER_AUTOINC_READ_FAILED, MYF(0));
3282
 
  } else {
3283
 
    dict_index_t*       index;
3284
 
    const char* col_name;
3285
 
    uint64_t    read_auto_inc;
3286
 
    ulint               err;
3287
 
 
3288
 
    update_session(getTable()->in_use);
3289
 
    col_name = field->field_name;
3290
 
 
3291
 
    ut_a(prebuilt->trx == session_to_trx(user_session));
3292
 
 
3293
 
    index = innobase_get_index(getTable()->getShare()->next_number_index);
3294
 
 
3295
 
    /* Execute SELECT MAX(col_name) FROM TABLE; */
3296
 
    err = row_search_max_autoinc(index, col_name, &read_auto_inc);
3297
 
 
3298
 
    switch (err) {
3299
 
    case DB_SUCCESS: {
3300
 
      uint64_t col_max_value;
3301
 
 
3302
 
      col_max_value = innobase_get_int_col_max_value(field);
3303
 
 
3304
 
      /* At the this stage we do not know the increment
3305
 
         nor the offset, so use a default increment of 1. */
3306
 
 
3307
 
      auto_inc = innobase_next_autoinc(read_auto_inc, 1, 1, col_max_value);
3308
 
 
3309
 
      break;
3310
 
    }
3311
 
    case DB_RECORD_NOT_FOUND:
3312
 
      ut_print_timestamp(stderr);
3313
 
      fprintf(stderr, "  InnoDB: MySQL and InnoDB data "
3314
 
              "dictionaries are out of sync.\n"
3315
 
              "InnoDB: Unable to find the AUTOINC column "
3316
 
              "%s in the InnoDB table %s.\n"
3317
 
              "InnoDB: We set the next AUTOINC column "
3318
 
              "value to 0,\n"
3319
 
              "InnoDB: in effect disabling the AUTOINC "
3320
 
              "next value generation.\n"
3321
 
              "InnoDB: You can either set the next "
3322
 
              "AUTOINC value explicitly using ALTER TABLE\n"
3323
 
              "InnoDB: or fix the data dictionary by "
3324
 
              "recreating the table.\n",
3325
 
              col_name, index->table->name);
3326
 
 
3327
 
      /* This will disable the AUTOINC generation. */
3328
 
      auto_inc = 0;
3329
 
 
3330
 
      /* We want the open to succeed, so that the user can
3331
 
         take corrective action. ie. reads should succeed but
3332
 
         updates should fail. */
3333
 
      err = DB_SUCCESS;
3334
 
      break;
3335
 
    default:
3336
 
      /* row_search_max_autoinc() should only return
3337
 
         one of DB_SUCCESS or DB_RECORD_NOT_FOUND. */
3338
 
      ut_error;
3339
 
    }
 
2670
    fprintf(stderr, "  InnoDB: MySQL and InnoDB data "
 
2671
      "dictionaries are out of sync.\n"
 
2672
      "InnoDB: Unable to find the AUTOINC column %s in the "
 
2673
      "InnoDB table %s.\n"
 
2674
      "InnoDB: We set the next AUTOINC column value to the "
 
2675
      "maximum possible value,\n"
 
2676
      "InnoDB: in effect disabling the AUTOINC next value "
 
2677
      "generation.\n"
 
2678
      "InnoDB: You can either set the next AUTOINC value "
 
2679
      "explicitly using ALTER TABLE\n"
 
2680
      "InnoDB: or fix the data dictionary by recreating "
 
2681
      "the table.\n",
 
2682
      col_name, index->table->name);
 
2683
 
 
2684
    auto_inc = 0xFFFFFFFFFFFFFFFFULL;
 
2685
    break;
 
2686
 
 
2687
  default:
 
2688
    return(error);
3340
2689
  }
3341
2690
 
3342
2691
  dict_table_autoinc_initialize(prebuilt->table, auto_inc);
 
2692
 
 
2693
  return(DB_SUCCESS);
3343
2694
}
3344
2695
 
3345
2696
/*****************************************************************//**
3348
2699
@return 1 if error, 0 if success */
3349
2700
UNIV_INTERN
3350
2701
int
3351
 
ha_innobase::doOpen(const TableIdentifier &identifier,
3352
 
                    int   mode,   /*!< in: not used */
3353
 
                    uint    test_if_locked) /*!< in: not used */
 
2702
ha_innobase::open(
 
2703
/*==============*/
 
2704
  const char* name,   /*!< in: table name */
 
2705
  int   mode,   /*!< in: not used */
 
2706
  uint    test_if_locked) /*!< in: not used */
3354
2707
{
3355
2708
  dict_table_t* ib_table;
3356
 
  char    norm_name[FN_REFLEN];
 
2709
  char    norm_name[1000];
3357
2710
  Session*    session;
 
2711
  ulint   retries = 0;
 
2712
  char*   is_part = NULL;
3358
2713
 
3359
2714
  UT_NOT_USED(mode);
3360
2715
  UT_NOT_USED(test_if_locked);
3361
2716
 
3362
 
  session= getTable()->in_use;
 
2717
  session = ha_session();
3363
2718
 
3364
2719
  /* Under some cases Drizzle seems to call this function while
3365
2720
  holding btr_search_latch. This breaks the latching order as
3368
2723
    getTransactionalEngine()->releaseTemporaryLatches(session);
3369
2724
  }
3370
2725
 
3371
 
  normalize_table_name(norm_name, identifier.getPath().c_str());
 
2726
  normalize_table_name(norm_name, name);
3372
2727
 
3373
2728
  user_session = NULL;
3374
2729
 
3375
 
  if (!(share=get_share(identifier.getPath().c_str()))) {
 
2730
  if (!(share=get_share(name))) {
3376
2731
 
3377
2732
    return(1);
3378
2733
  }
3383
2738
  stored the string length as the first byte. */
3384
2739
 
3385
2740
  upd_and_key_val_buff_len =
3386
 
        getTable()->getShare()->stored_rec_length
3387
 
        + getTable()->getShare()->max_key_length
 
2741
        table->s->stored_rec_length
 
2742
        + table->s->max_key_length
3388
2743
        + MAX_REF_PARTS * 3;
3389
2744
 
3390
 
  upd_buff.resize(upd_and_key_val_buff_len);
 
2745
  upd_buff= (unsigned char*)malloc(upd_and_key_val_buff_len);
3391
2746
 
3392
 
  if (upd_buff.size() < upd_and_key_val_buff_len)
 
2747
  if (upd_buff == NULL)
3393
2748
  {
3394
2749
    free_share(share);
3395
2750
  }
3396
2751
 
3397
 
  key_val_buff.resize(upd_and_key_val_buff_len);
3398
 
  if (key_val_buff.size() < upd_and_key_val_buff_len)
 
2752
  key_val_buff= (unsigned char*)malloc(upd_and_key_val_buff_len);
 
2753
  if (key_val_buff == NULL)
3399
2754
  {
 
2755
    free_share(share);
 
2756
    free(upd_buff);
3400
2757
    return(1);
3401
2758
  }
3402
2759
 
 
2760
 
 
2761
 
 
2762
  /* We look for pattern #P# to see if the table is partitioned
 
2763
  MySQL table. The retry logic for partitioned tables is a
 
2764
  workaround for http://bugs.mysql.com/bug.php?id=33349. Look
 
2765
  at support issue https://support.mysql.com/view.php?id=21080
 
2766
  for more details. */
 
2767
  is_part = strstr(norm_name, "#P#");
 
2768
retry:
3403
2769
  /* Get pointer to a table object in InnoDB dictionary cache */
3404
2770
  ib_table = dict_table_get(norm_name, TRUE);
3405
2771
  
3406
2772
  if (NULL == ib_table) {
 
2773
    if (is_part && retries < 10) {
 
2774
      ++retries;
 
2775
      os_thread_sleep(100000);
 
2776
      goto retry;
 
2777
    }
 
2778
 
 
2779
    if (is_part) {
 
2780
      errmsg_printf(ERRMSG_LVL_ERROR, "Failed to open table %s after "
 
2781
          "%lu attemtps.\n", norm_name,
 
2782
          retries);
 
2783
    }
 
2784
 
3407
2785
    errmsg_printf(ERRMSG_LVL_ERROR, "Cannot find or open table %s from\n"
3408
2786
        "the internal data dictionary of InnoDB "
3409
2787
        "though the .frm file for the\n"
3420
2798
        "how you can resolve the problem.\n",
3421
2799
        norm_name);
3422
2800
    free_share(share);
3423
 
    upd_buff.resize(0);
3424
 
    key_val_buff.resize(0);
 
2801
    free(upd_buff);
 
2802
    free(key_val_buff);
3425
2803
    errno = ENOENT;
3426
2804
 
3427
2805
    return(HA_ERR_NO_SUCH_TABLE);
3437
2815
        "how you can resolve the problem.\n",
3438
2816
        norm_name);
3439
2817
    free_share(share);
3440
 
    upd_buff.resize(0);
3441
 
    key_val_buff.resize(0);
 
2818
    free(upd_buff);
 
2819
    free(key_val_buff);
3442
2820
    errno = ENOENT;
3443
2821
 
3444
2822
    dict_table_decrement_handle_count(ib_table, FALSE);
3447
2825
 
3448
2826
  prebuilt = row_create_prebuilt(ib_table);
3449
2827
 
3450
 
  prebuilt->mysql_row_len = getTable()->getShare()->stored_rec_length;
3451
 
  prebuilt->default_rec = getTable()->getDefaultValues();
 
2828
  prebuilt->mysql_row_len = table->s->stored_rec_length;
 
2829
  prebuilt->default_rec = table->s->default_values;
3452
2830
  ut_ad(prebuilt->default_rec);
3453
2831
 
3454
2832
  /* Looks like MySQL-3.23 sometimes has primary key number != 0 */
3455
2833
 
3456
 
  primary_key = getTable()->getShare()->getPrimaryKey();
 
2834
  primary_key = table->s->primary_key;
3457
2835
  key_used_on_scan = primary_key;
3458
2836
 
3459
 
  if (!innobase_build_index_translation(getTable(), ib_table, share)) {
3460
 
    errmsg_printf(ERRMSG_LVL_ERROR, "Build InnoDB index translation table for"
3461
 
                    " Table %s failed", identifier.getPath().c_str());
3462
 
  }
3463
 
 
3464
2837
  /* Allocate a buffer for a 'row reference'. A row reference is
3465
2838
  a string of bytes of length ref_length which uniquely specifies
3466
2839
  a row in our table. Note that MySQL may also compare two row
3468
2841
  of length ref_length! */
3469
2842
 
3470
2843
  if (!row_table_got_default_clust_index(ib_table)) {
 
2844
    if (primary_key >= MAX_KEY) {
 
2845
      errmsg_printf(ERRMSG_LVL_ERROR, "Table %s has a primary key in InnoDB data "
 
2846
          "dictionary, but not in MySQL!", name);
 
2847
    }
3471
2848
 
3472
2849
    prebuilt->clust_index_was_generated = FALSE;
3473
2850
 
3474
 
    if (UNIV_UNLIKELY(primary_key >= MAX_KEY)) {
3475
 
      errmsg_printf(ERRMSG_LVL_ERROR, "Table %s has a primary key in "
3476
 
                    "InnoDB data dictionary, but not "
3477
 
                    "in MySQL!", identifier.getTableName().c_str());
3478
 
 
3479
 
      /* This mismatch could cause further problems
3480
 
         if not attended, bring this to the user's attention
3481
 
         by printing a warning in addition to log a message
3482
 
         in the errorlog */
3483
 
      push_warning_printf(session, DRIZZLE_ERROR::WARN_LEVEL_WARN,
3484
 
                          ER_NO_SUCH_INDEX,
3485
 
                          "InnoDB: Table %s has a "
3486
 
                          "primary key in InnoDB data "
3487
 
                          "dictionary, but not in "
3488
 
                          "MySQL!", identifier.getTableName().c_str());
3489
 
 
3490
 
      /* If primary_key >= MAX_KEY, its (primary_key)
3491
 
         value could be out of bound if continue to index
3492
 
         into key_info[] array. Find InnoDB primary index,
3493
 
         and assign its key_length to ref_length.
3494
 
         In addition, since MySQL indexes are sorted starting
3495
 
         with primary index, unique index etc., initialize
3496
 
         ref_length to the first index key length in
3497
 
         case we fail to find InnoDB cluster index.
3498
 
 
3499
 
         Please note, this will not resolve the primary
3500
 
         index mismatch problem, other side effects are
3501
 
         possible if users continue to use the table.
3502
 
         However, we allow this table to be opened so
3503
 
         that user can adopt necessary measures for the
3504
 
         mismatch while still being accessible to the table
3505
 
         date. */
3506
 
      ref_length = getTable()->key_info[0].key_length;
3507
 
 
3508
 
      /* Find correspoinding cluster index
3509
 
         key length in MySQL's key_info[] array */
3510
 
      for (ulint i = 0; i < getTable()->getShare()->keys; i++) {
3511
 
        dict_index_t*   index;
3512
 
        index = innobase_get_index(i);
3513
 
        if (dict_index_is_clust(index)) {
3514
 
          ref_length =
3515
 
            getTable()->key_info[i].key_length;
3516
 
        }
3517
 
      }
3518
 
    } else {
3519
 
      /* MySQL allocates the buffer for ref.
3520
 
         key_info->key_length includes space for all key
3521
 
         columns + one byte for each column that may be
3522
 
         NULL. ref_length must be as exact as possible to
3523
 
         save space, because all row reference buffers are
3524
 
         allocated based on ref_length. */
3525
 
 
3526
 
      ref_length = getTable()->key_info[primary_key].key_length;
3527
 
    }
 
2851
    /* MySQL allocates the buffer for ref. key_info->key_length
 
2852
    includes space for all key columns + one byte for each column
 
2853
    that may be NULL. ref_length must be as exact as possible to
 
2854
    save space, because all row reference buffers are allocated
 
2855
    based on ref_length. */
 
2856
 
 
2857
    ref_length = table->key_info[primary_key].key_length;
3528
2858
  } else {
3529
2859
    if (primary_key != MAX_KEY) {
3530
 
      errmsg_printf(ERRMSG_LVL_ERROR,
3531
 
                    "Table %s has no primary key in InnoDB data "
3532
 
                    "dictionary, but has one in MySQL! If you "
3533
 
                    "created the table with a MySQL version < "
3534
 
                    "3.23.54 and did not define a primary key, "
3535
 
                    "but defined a unique key with all non-NULL "
3536
 
                    "columns, then MySQL internally treats that "
3537
 
                    "key as the primary key. You can fix this "
3538
 
                    "error by dump + DROP + CREATE + reimport "
3539
 
                    "of the table.", identifier.getTableName().c_str());
3540
 
 
3541
 
      /* This mismatch could cause further problems
3542
 
         if not attended, bring this to the user attention
3543
 
         by printing a warning in addition to log a message
3544
 
         in the errorlog */
3545
 
      push_warning_printf(session, DRIZZLE_ERROR::WARN_LEVEL_WARN,
3546
 
                          ER_NO_SUCH_INDEX,
3547
 
                          "InnoDB: Table %s has no "
3548
 
                          "primary key in InnoDB data "
3549
 
                          "dictionary, but has one in "
3550
 
                          "MySQL!", identifier.getTableName().c_str());
 
2860
      errmsg_printf(ERRMSG_LVL_ERROR, "Table %s has no primary key in InnoDB data "
 
2861
          "dictionary, but has one in MySQL! If you "
 
2862
          "created the table with a MySQL version < "
 
2863
          "3.23.54 and did not define a primary key, "
 
2864
          "but defined a unique key with all non-NULL "
 
2865
          "columns, then MySQL internally treats that "
 
2866
          "key as the primary key. You can fix this "
 
2867
          "error by dump + DROP + CREATE + reimport "
 
2868
          "of the table.", name);
3551
2869
    }
3552
2870
 
3553
2871
    prebuilt->clust_index_was_generated = TRUE;
3566
2884
      errmsg_printf(ERRMSG_LVL_WARN, 
3567
2885
        "Table %s key_used_on_scan is %lu even "
3568
2886
        "though there is no primary key inside "
3569
 
        "InnoDB.", identifier.getTableName().c_str(), (ulong) key_used_on_scan);
 
2887
        "InnoDB.", name, (ulong) key_used_on_scan);
3570
2888
    }
3571
2889
  }
3572
2890
 
3574
2892
  stats.block_size = 16 * 1024;
3575
2893
 
3576
2894
  /* Init table lock structure */
3577
 
  lock.init(&share->lock);
 
2895
  thr_lock_data_init(&share->lock,&lock,(void*) 0);
3578
2896
 
3579
2897
  if (prebuilt->table) {
3580
2898
    /* We update the highest file format in the system table
3581
2899
    space, if this table has higher file format setting. */
3582
2900
 
3583
 
    char changed_file_format_max[100];
3584
 
    strcpy(changed_file_format_max, innobase_file_format_max.c_str());
3585
 
    trx_sys_file_format_max_upgrade((const char **)&changed_file_format_max,
 
2901
    trx_sys_file_format_max_upgrade(
 
2902
      (const char**) &innobase_file_format_check,
3586
2903
      dict_table_get_format(prebuilt->table));
3587
 
    innobase_file_format_max= changed_file_format_max;
3588
2904
  }
3589
2905
 
 
2906
  info(HA_STATUS_NO_LOCK | HA_STATUS_VARIABLE | HA_STATUS_CONST);
 
2907
 
3590
2908
  /* Only if the table has an AUTOINC column. */
3591
 
  if (prebuilt->table != NULL && getTable()->found_next_number_field != NULL) {
 
2909
  if (prebuilt->table != NULL && table->found_next_number_field != NULL) {
 
2910
    ulint error;
3592
2911
 
3593
2912
    dict_table_autoinc_lock(prebuilt->table);
3594
2913
 
3598
2917
    autoinc value from a previous Drizzle open. */
3599
2918
    if (dict_table_autoinc_read(prebuilt->table) == 0) {
3600
2919
 
3601
 
      innobase_initialize_autoinc();
 
2920
      error = innobase_initialize_autoinc();
 
2921
      ut_a(error == DB_SUCCESS);
3602
2922
    }
3603
2923
 
3604
2924
    dict_table_autoinc_unlock(prebuilt->table);
3605
2925
  }
3606
2926
 
3607
 
  info(HA_STATUS_NO_LOCK | HA_STATUS_VARIABLE | HA_STATUS_CONST);
3608
 
 
3609
2927
  return(0);
3610
2928
}
3611
2929
 
3626
2944
{
3627
2945
  Session*  session;
3628
2946
 
3629
 
  session= getTable()->in_use;
 
2947
  session = ha_session();
3630
2948
  if (session != NULL) {
3631
2949
    getTransactionalEngine()->releaseTemporaryLatches(session);
3632
2950
  }
3633
2951
 
3634
2952
  row_prebuilt_free(prebuilt, FALSE);
3635
2953
 
3636
 
  upd_buff.clear();
3637
 
  key_val_buff.clear();
 
2954
  free(upd_buff);
 
2955
  free(key_val_buff);
3638
2956
  free_share(share);
3639
2957
 
3640
2958
  /* Tell InnoDB server that there might be work for
3657
2975
  Table*  table,  /*!< in: MySQL table object */
3658
2976
  Field*  field)  /*!< in: MySQL field object */
3659
2977
{
3660
 
  return((uint) (field->ptr - table->getInsertRecord()));
 
2978
  return((uint) (field->ptr - table->record[0]));
3661
2979
}
3662
2980
 
3663
2981
/**************************************************************//**
3680
2998
  }
3681
2999
 
3682
3000
  null_offset = (uint) ((char*) field->null_ptr
3683
 
          - (char*) table->getInsertRecord());
 
3001
          - (char*) table->record[0]);
3684
3002
 
3685
3003
  if (record[null_offset] & field->null_bit) {
3686
3004
 
3704
3022
  int null_offset;
3705
3023
 
3706
3024
  null_offset = (uint) ((char*) field->null_ptr
3707
 
          - (char*) table->getInsertRecord());
 
3025
          - (char*) table->record[0]);
3708
3026
 
3709
3027
  record[null_offset] = record[null_offset] | field->null_bit;
3710
3028
}
3731
3049
int
3732
3050
innobase_mysql_cmp(
3733
3051
/*===============*/
3734
 
          /* out: 1, 0, -1, if a is greater, equal, less than b, respectively */
 
3052
          /* out: 1, 0, -1, if a is greater,
 
3053
          equal, less than b, respectively */
3735
3054
  int   mysql_type, /* in: MySQL type */
3736
3055
  uint    charset_number, /* in: number of the charset */
3737
3056
  const unsigned char* a,   /* in: data field */
3738
 
  unsigned int  a_length, /* in: data field length, not UNIV_SQL_NULL */
 
3057
  unsigned int  a_length, /* in: data field length,
 
3058
          not UNIV_SQL_NULL */
3739
3059
  const unsigned char* b,   /* in: data field */
3740
 
  unsigned int  b_length) /* in: data field length, not UNIV_SQL_NULL */
 
3060
  unsigned int  b_length) /* in: data field length,
 
3061
          not UNIV_SQL_NULL */
3741
3062
{
3742
3063
  const CHARSET_INFO* charset;
3743
3064
  enum_field_types  mysql_tp;
3753
3074
  case DRIZZLE_TYPE_BLOB:
3754
3075
  case DRIZZLE_TYPE_VARCHAR:
3755
3076
    /* Use the charset number to pick the right charset struct for
3756
 
      the comparison. Since the MySQL function get_charset may be
3757
 
      slow before Bar removes the mutex operation there, we first
3758
 
      look at 2 common charsets directly. */
 
3077
    the comparison. Since the MySQL function get_charset may be
 
3078
    slow before Bar removes the mutex operation there, we first
 
3079
    look at 2 common charsets directly. */
3759
3080
 
3760
3081
    if (charset_number == default_charset_info->number) {
3761
3082
      charset = default_charset_info;
3764
3085
 
3765
3086
      if (charset == NULL) {
3766
3087
        errmsg_printf(ERRMSG_LVL_ERROR, "InnoDB needs charset %lu for doing "
3767
 
                      "a comparison, but MySQL cannot "
3768
 
                      "find that charset.",
3769
 
                      (ulong) charset_number);
 
3088
            "a comparison, but MySQL cannot "
 
3089
            "find that charset.",
 
3090
            (ulong) charset_number);
3770
3091
        ut_a(0);
3771
3092
      }
3772
3093
    }
3773
3094
 
3774
3095
    /* Starting from 4.1.3, we use strnncollsp() in comparisons of
3775
 
      non-latin1_swedish_ci strings. NOTE that the collation order
3776
 
      changes then: 'b\0\0...' is ordered BEFORE 'b  ...'. Users
3777
 
      having indexes on such data need to rebuild their tables! */
 
3096
    non-latin1_swedish_ci strings. NOTE that the collation order
 
3097
    changes then: 'b\0\0...' is ordered BEFORE 'b  ...'. Users
 
3098
    having indexes on such data need to rebuild their tables! */
3778
3099
 
3779
3100
    ret = charset->coll->strnncollsp(charset,
3780
 
                                     a, a_length,
3781
 
                                     b, b_length, 0);
 
3101
          a, a_length,
 
3102
             b, b_length, 0);
3782
3103
    if (ret < 0) {
3783
3104
      return(-1);
3784
3105
    } else if (ret > 0) {
3853
3174
  case DRIZZLE_TYPE_DATETIME:
3854
3175
  case DRIZZLE_TYPE_DATE:
3855
3176
  case DRIZZLE_TYPE_TIMESTAMP:
3856
 
  case DRIZZLE_TYPE_ENUM:
3857
3177
    return(DATA_INT);
3858
3178
  case DRIZZLE_TYPE_DOUBLE:
3859
3179
    return(DATA_DOUBLE);
3860
3180
  case DRIZZLE_TYPE_BLOB:
3861
 
    return(DATA_BLOB);
3862
 
  case DRIZZLE_TYPE_UUID:
3863
 
    return(DATA_FIXBINARY);
3864
 
  case DRIZZLE_TYPE_NULL:
 
3181
                return(DATA_BLOB);
 
3182
  default:
3865
3183
    ut_error;
3866
3184
  }
3867
3185
 
3910
3228
  uint    buff_len,/*!< in: buffer length */
3911
3229
  const unsigned char*  record)/*!< in: row in MySQL format */
3912
3230
{
3913
 
  KeyInfo*    key_info  = &getTable()->key_info[keynr];
3914
 
  KeyPartInfo*  key_part  = key_info->key_part;
3915
 
  KeyPartInfo*  end   = key_part + key_info->key_parts;
 
3231
  KEY*    key_info  = table->key_info + keynr;
 
3232
  KEY_PART_INFO*  key_part  = key_info->key_part;
 
3233
  KEY_PART_INFO*  end   = key_part + key_info->key_parts;
3916
3234
  char*   buff_start  = buff;
3917
3235
  enum_field_types mysql_type;
3918
3236
  Field*    field;
3982
3300
      cs = field->charset();
3983
3301
 
3984
3302
      lenlen = (ulint)
3985
 
        (((Field_varstring*)field)->pack_length_no_ptr());
 
3303
        (((Field_varstring*)field)->length_bytes);
3986
3304
 
3987
3305
      data = row_mysql_read_true_varchar(&len,
3988
3306
        (byte*) (record
3989
 
        + (ulint)get_field_offset(getTable(), field)),
 
3307
        + (ulint)get_field_offset(table, field)),
3990
3308
        lenlen);
3991
3309
 
3992
3310
      true_len = len;
4049
3367
 
4050
3368
      blob_data = row_mysql_read_blob_ref(&blob_len,
4051
3369
        (byte*) (record
4052
 
        + (ulint)get_field_offset(getTable(), field)),
 
3370
        + (ulint)get_field_offset(table, field)),
4053
3371
          (ulint) field->pack_length());
4054
3372
 
4055
3373
      true_len = blob_len;
4056
3374
 
4057
 
      ut_a(get_field_offset(getTable(), field)
 
3375
      ut_a(get_field_offset(table, field)
4058
3376
        == key_part->offset);
4059
3377
 
4060
3378
      /* For multi byte character sets we need to calculate
4062
3380
 
4063
3381
      if (blob_len > 0 && cs->mbmaxlen > 1) {
4064
3382
        true_len = (ulint) cs->cset->well_formed_len(cs,
4065
 
                                                     (const char *) blob_data,
4066
 
                                                     (const char *) blob_data
4067
 
                                                     + blob_len,
4068
 
                                                     (uint) (key_len /
4069
 
                                                             cs->mbmaxlen),
4070
 
                                                     &error);
 
3383
            (const char *) blob_data,
 
3384
            (const char *) blob_data
 
3385
              + blob_len,
 
3386
                                                (uint) (key_len /
 
3387
                                                        cs->mbmaxlen),
 
3388
            &error);
4071
3389
      }
4072
3390
 
4073
3391
      /* All indexes on BLOB and TEXT are column prefix
4101
3419
      ulint     key_len;
4102
3420
      const unsigned char*    src_start;
4103
3421
      enum_field_types  real_type;
4104
 
      const CHARSET_INFO* cs= field->charset();
4105
3422
 
4106
3423
      key_len = key_part->length;
4107
3424
 
4123
3440
      memcpy(buff, src_start, true_len);
4124
3441
      buff += true_len;
4125
3442
 
4126
 
      /* Pad the unused space with spaces. */
 
3443
      /* Pad the unused space with spaces. Note that no
 
3444
      padding is ever needed for UCS-2 because in MySQL,
 
3445
      all UCS2 characters are 2 bytes, as MySQL does not
 
3446
      support surrogate pairs, which are needed to represent
 
3447
      characters in the range U+10000 to U+10FFFF. */
4127
3448
 
4128
3449
      if (true_len < key_len) {
4129
 
        ulint   pad_len = key_len - true_len;
4130
 
        ut_a(!(pad_len % cs->mbminlen));
4131
 
 
4132
 
        cs->cset->fill(cs, buff, pad_len,
4133
 
                       0x20 /* space */);
 
3450
        ulint pad_len = key_len - true_len;
 
3451
        memset(buff, ' ', pad_len);
4134
3452
        buff += pad_len;
4135
3453
      }
4136
3454
    }
4224
3542
    the clustered index */
4225
3543
  }
4226
3544
 
4227
 
  n_fields = (ulint)table->getShare()->sizeFields(); /* number of columns */
 
3545
  n_fields = (ulint)table->s->fields; /* number of columns */
4228
3546
 
4229
3547
  if (!prebuilt->mysql_template) {
4230
3548
    prebuilt->mysql_template = (mysql_row_templ_t*)
4232
3550
  }
4233
3551
 
4234
3552
  prebuilt->template_type = templ_type;
4235
 
  prebuilt->null_bitmap_len = table->getShare()->null_bytes;
 
3553
  prebuilt->null_bitmap_len = table->s->null_bytes;
4236
3554
 
4237
3555
  prebuilt->templ_contains_blob = FALSE;
4238
3556
 
4239
3557
  /* Note that in InnoDB, i is the column number. MySQL calls columns
4240
3558
  'fields'. */
4241
 
  for (i = 0; i < n_fields; i++)
4242
 
  {
4243
 
    const dict_col_t *col= &index->table->cols[i];
 
3559
  for (i = 0; i < n_fields; i++) {
4244
3560
    templ = prebuilt->mysql_template + n_requested_fields;
4245
 
    field = table->getField(i);
 
3561
    field = table->field[i];
4246
3562
 
4247
3563
    if (UNIV_LIKELY(templ_type == ROW_MYSQL_REC_FIELDS)) {
4248
3564
      /* Decide which columns we should fetch
4288
3604
    templ->col_no = i;
4289
3605
 
4290
3606
    if (index == clust_index) {
4291
 
      templ->rec_field_no = dict_col_get_clust_pos(col, index);
 
3607
      templ->rec_field_no = dict_col_get_clust_pos(
 
3608
        &index->table->cols[i], index);
4292
3609
    } else {
4293
3610
      templ->rec_field_no = dict_index_get_nth_col_pos(
4294
3611
                index, i);
4301
3618
    if (field->null_ptr) {
4302
3619
      templ->mysql_null_byte_offset =
4303
3620
        (ulint) ((char*) field->null_ptr
4304
 
          - (char*) table->getInsertRecord());
 
3621
          - (char*) table->record[0]);
4305
3622
 
4306
3623
      templ->mysql_null_bit_mask = (ulint) field->null_bit;
4307
3624
    } else {
4317
3634
      mysql_prefix_len = templ->mysql_col_offset
4318
3635
        + templ->mysql_col_len;
4319
3636
    }
4320
 
    templ->type = col->mtype;
 
3637
    templ->type = index->table->cols[i].mtype;
4321
3638
    templ->mysql_type = (ulint)field->type();
4322
3639
 
4323
3640
    if (templ->mysql_type == DATA_MYSQL_TRUE_VARCHAR) {
4324
3641
      templ->mysql_length_bytes = (ulint)
4325
 
        (((Field_varstring*)field)->pack_length_no_ptr());
 
3642
        (((Field_varstring*)field)->length_bytes);
4326
3643
    }
4327
3644
 
4328
 
    templ->charset = dtype_get_charset_coll(col->prtype);
4329
 
    templ->mbminlen = dict_col_get_mbminlen(col);
4330
 
    templ->mbmaxlen = dict_col_get_mbmaxlen(col);
4331
 
    templ->is_unsigned = col->prtype & DATA_UNSIGNED;
 
3645
    templ->charset = dtype_get_charset_coll(
 
3646
      index->table->cols[i].prtype);
 
3647
    templ->mbminlen = index->table->cols[i].mbminlen;
 
3648
    templ->mbmaxlen = index->table->cols[i].mbmaxlen;
 
3649
    templ->is_unsigned = index->table->cols[i].prtype
 
3650
              & DATA_UNSIGNED;
4332
3651
    if (templ->type == DATA_BLOB) {
4333
3652
      prebuilt->templ_contains_blob = TRUE;
4334
3653
    }
4353
3672
}
4354
3673
 
4355
3674
/********************************************************************//**
 
3675
Get the upper limit of the MySQL integral and floating-point type. */
 
3676
UNIV_INTERN
 
3677
uint64_t
 
3678
ha_innobase::innobase_get_int_col_max_value(
 
3679
/*========================================*/
 
3680
  const Field*  field)
 
3681
{
 
3682
  uint64_t  max_value = 0;
 
3683
 
 
3684
  switch(field->key_type()) {
 
3685
  /* TINY */
 
3686
  case HA_KEYTYPE_BINARY:
 
3687
    max_value = 0xFFULL;
 
3688
    break;
 
3689
  /* MEDIUM */
 
3690
  case HA_KEYTYPE_UINT24:
 
3691
    max_value = 0xFFFFFFULL;
 
3692
    break;
 
3693
  /* LONG */
 
3694
  case HA_KEYTYPE_ULONG_INT:
 
3695
    max_value = 0xFFFFFFFFULL;
 
3696
    break;
 
3697
  case HA_KEYTYPE_LONG_INT:
 
3698
    max_value = 0x7FFFFFFFULL;
 
3699
    break;
 
3700
  /* BIG */
 
3701
  case HA_KEYTYPE_ULONGLONG:
 
3702
    max_value = 0xFFFFFFFFFFFFFFFFULL;
 
3703
    break;
 
3704
  case HA_KEYTYPE_LONGLONG:
 
3705
    max_value = 0x7FFFFFFFFFFFFFFFULL;
 
3706
    break;
 
3707
  case HA_KEYTYPE_DOUBLE:
 
3708
    /* We use the maximum as per IEEE754-2008 standard, 2^53 */
 
3709
    max_value = 0x20000000000000ULL;
 
3710
    break;
 
3711
  default:
 
3712
    ut_error;
 
3713
  }
 
3714
 
 
3715
  return(max_value);
 
3716
}
 
3717
 
 
3718
/********************************************************************//**
4356
3719
This special handling is really to overcome the limitations of MySQL's
4357
3720
binlogging. We need to eliminate the non-determinism that will arise in
4358
3721
INSERT ... SELECT type of statements, since MySQL binlog only stores the
4366
3729
{
4367
3730
  ulint   error = DB_SUCCESS;
4368
3731
 
4369
 
  dict_table_autoinc_lock(prebuilt->table);
 
3732
  switch (innobase_autoinc_lock_mode) {
 
3733
  case AUTOINC_NO_LOCKING:
 
3734
    /* Acquire only the AUTOINC mutex. */
 
3735
    dict_table_autoinc_lock(prebuilt->table);
 
3736
    break;
 
3737
 
 
3738
  case AUTOINC_NEW_STYLE_LOCKING:
 
3739
    /* For simple (single/multi) row INSERTs, we fallback to the
 
3740
    old style only if another transaction has already acquired
 
3741
    the AUTOINC lock on behalf of a LOAD FILE or INSERT ... SELECT
 
3742
    etc. type of statement. */
 
3743
    if (session_sql_command(user_session) == SQLCOM_INSERT
 
3744
        || session_sql_command(user_session) == SQLCOM_REPLACE) {
 
3745
      dict_table_t* d_table = prebuilt->table;
 
3746
 
 
3747
      /* Acquire the AUTOINC mutex. */
 
3748
      dict_table_autoinc_lock(d_table);
 
3749
 
 
3750
      /* We need to check that another transaction isn't
 
3751
      already holding the AUTOINC lock on the table. */
 
3752
      if (d_table->n_waiting_or_granted_auto_inc_locks) {
 
3753
        /* Release the mutex to avoid deadlocks. */
 
3754
        dict_table_autoinc_unlock(d_table);
 
3755
      } else {
 
3756
        break;
 
3757
      }
 
3758
    }
 
3759
    /* Fall through to old style locking. */
 
3760
 
 
3761
  case AUTOINC_OLD_STYLE_LOCKING:
 
3762
    error = row_lock_table_autoinc_for_mysql(prebuilt);
 
3763
 
 
3764
    if (error == DB_SUCCESS) {
 
3765
 
 
3766
      /* Acquire the AUTOINC mutex. */
 
3767
      dict_table_autoinc_lock(prebuilt->table);
 
3768
    }
 
3769
    break;
 
3770
 
 
3771
  default:
 
3772
    ut_error;
 
3773
  }
4370
3774
 
4371
3775
  return(ulong(error));
4372
3776
}
4380
3784
/*================================*/
4381
3785
  uint64_t  autoinc)  /*!< in: value to store */
4382
3786
{
4383
 
  dict_table_autoinc_lock(prebuilt->table);
4384
 
  dict_table_autoinc_initialize(prebuilt->table, autoinc);
4385
 
  dict_table_autoinc_unlock(prebuilt->table);
4386
 
 
4387
 
  return(ulong(DB_SUCCESS));
 
3787
  ulint   error;
 
3788
 
 
3789
  error = innobase_lock_autoinc();
 
3790
 
 
3791
  if (error == DB_SUCCESS) {
 
3792
 
 
3793
    dict_table_autoinc_initialize(prebuilt->table, autoinc);
 
3794
 
 
3795
    dict_table_autoinc_unlock(prebuilt->table);
 
3796
  }
 
3797
 
 
3798
  return(ulong(error));
4388
3799
}
4389
3800
 
4390
3801
/********************************************************************//**
4397
3808
/*==================================*/
4398
3809
  uint64_t  auto_inc) /*!< in: value to store */
4399
3810
{
4400
 
  dict_table_autoinc_lock(prebuilt->table);
4401
 
  dict_table_autoinc_update_if_greater(prebuilt->table, auto_inc);
4402
 
  dict_table_autoinc_unlock(prebuilt->table);
4403
 
 
4404
 
  return(ulong(DB_SUCCESS));
 
3811
  ulint   error;
 
3812
 
 
3813
  error = innobase_lock_autoinc();
 
3814
 
 
3815
  if (error == DB_SUCCESS) {
 
3816
 
 
3817
    dict_table_autoinc_update_if_greater(prebuilt->table, auto_inc);
 
3818
 
 
3819
    dict_table_autoinc_unlock(prebuilt->table);
 
3820
  }
 
3821
 
 
3822
  return(ulong(error));
4405
3823
}
4406
3824
 
4407
3825
/********************************************************************//**
4435
3853
    ut_error;
4436
3854
  }
4437
3855
 
 
3856
  ha_statistic_increment(&system_status_var::ha_write_count);
 
3857
 
4438
3858
  sql_command = session_sql_command(user_session);
4439
3859
 
4440
3860
  if ((sql_command == SQLCOM_ALTER_TABLE
4441
3861
       || sql_command == SQLCOM_CREATE_INDEX
4442
3862
       || sql_command == SQLCOM_DROP_INDEX)
4443
 
      && num_write_row >= 10000) {
 
3863
      && num_doInsertRecord >= 10000) {
4444
3864
    /* ALTER TABLE is COMMITted at every 10000 copied rows.
4445
3865
    The IX table lock for the original table has to be re-issued.
4446
3866
    As this method will be called on a temporary table where the
4453
3873
    dict_table_t* src_table;
4454
3874
    enum lock_mode  mode;
4455
3875
 
4456
 
    num_write_row = 0;
 
3876
    num_doInsertRecord = 0;
4457
3877
 
4458
3878
    /* Commit the transaction.  This will release the table
4459
3879
    locks, so they have to be acquired again. */
4500
3920
    }
4501
3921
  }
4502
3922
 
4503
 
  num_write_row++;
 
3923
  num_doInsertRecord++;
4504
3924
 
4505
3925
  /* This is the case where the table has an auto-increment column */
4506
 
  if (getTable()->next_number_field && record == getTable()->getInsertRecord()) {
 
3926
  if (table->next_number_field && record == table->record[0]) {
4507
3927
 
4508
3928
    /* Reset the error code before calling
4509
3929
    innobase_get_auto_increment(). */
4510
3930
    prebuilt->autoinc_error = DB_SUCCESS;
4511
3931
 
4512
3932
    if ((error = update_auto_increment())) {
 
3933
 
4513
3934
      /* We don't want to mask autoinc overflow errors. */
4514
 
 
4515
 
      /* Handle the case where the AUTOINC sub-system
4516
 
         failed during initialization. */
4517
 
      if (prebuilt->autoinc_error == DB_UNSUPPORTED) {
4518
 
        error_result = ER_AUTOINC_READ_FAILED;
4519
 
        /* Set the error message to report too. */
4520
 
        my_error(ER_AUTOINC_READ_FAILED, MYF(0));
4521
 
        goto func_exit;
4522
 
      } else if (prebuilt->autoinc_error != DB_SUCCESS) {
 
3935
      if (prebuilt->autoinc_error != DB_SUCCESS) {
4523
3936
        error = (int) prebuilt->autoinc_error;
4524
3937
 
4525
3938
        goto report_error;
4539
3952
    /* Build the template used in converting quickly between
4540
3953
    the two database formats */
4541
3954
 
4542
 
    build_template(prebuilt, NULL, getTable(), ROW_MYSQL_WHOLE_ROW);
 
3955
    build_template(prebuilt, NULL, table,
 
3956
             ROW_MYSQL_WHOLE_ROW);
4543
3957
  }
4544
3958
 
4545
3959
  innodb_srv_conc_enter_innodb(prebuilt->trx);
4546
3960
 
4547
3961
  error = row_insert_for_mysql((byte*) record, prebuilt);
4548
3962
 
4549
 
  user_session->setXaId(trx->id);
4550
 
 
4551
3963
  /* Handle duplicate key errors */
4552
3964
  if (auto_inc_used) {
4553
3965
    ulint   err;
4565
3977
    /* We need the upper limit of the col type to check for
4566
3978
    whether we update the table autoinc counter or not. */
4567
3979
    col_max_value = innobase_get_int_col_max_value(
4568
 
      getTable()->next_number_field); 
 
3980
      table->next_number_field);
 
3981
 
4569
3982
    /* Get the value that MySQL attempted to store in the table.*/
4570
 
    auto_inc = getTable()->next_number_field->val_int();
 
3983
    auto_inc = table->next_number_field->val_int();
4571
3984
 
4572
3985
    switch (error) {
4573
3986
    case DB_DUPLICATE_KEY:
4603
4016
      update the table upper limit. Note: last_value
4604
4017
      will be 0 if get_auto_increment() was not called.*/
4605
4018
 
4606
 
      if (auto_inc >= prebuilt->autoinc_last_value) {
 
4019
      if (auto_inc <= col_max_value
 
4020
          && auto_inc >= prebuilt->autoinc_last_value) {
4607
4021
set_max_autoinc:
4608
 
        /* This should filter out the negative
4609
 
           values set explicitly by the user. */
4610
 
        if (auto_inc <= col_max_value) {
4611
 
          ut_a(prebuilt->autoinc_increment > 0);
4612
 
 
4613
 
          uint64_t      need;
4614
 
          uint64_t      offset;
4615
 
 
4616
 
          offset = prebuilt->autoinc_offset;
4617
 
          need = prebuilt->autoinc_increment;
4618
 
 
4619
 
          auto_inc = innobase_next_autoinc(
4620
 
                                           auto_inc,
4621
 
                                           need, offset, col_max_value);
4622
 
 
4623
 
          err = innobase_set_max_autoinc(
4624
 
                                         auto_inc);
4625
 
 
4626
 
          if (err != DB_SUCCESS) {
4627
 
            error = err;
4628
 
          }
 
4022
        ut_a(prebuilt->autoinc_increment > 0);
 
4023
 
 
4024
        uint64_t  need;
 
4025
        uint64_t  offset;
 
4026
 
 
4027
        offset = prebuilt->autoinc_offset;
 
4028
        need = prebuilt->autoinc_increment;
 
4029
 
 
4030
        auto_inc = innobase_next_autoinc(
 
4031
          auto_inc, need, offset, col_max_value);
 
4032
 
 
4033
        err = innobase_set_max_autoinc(auto_inc);
 
4034
 
 
4035
        if (err != DB_SUCCESS) {
 
4036
          error = err;
4629
4037
        }
4630
4038
      }
4631
4039
      break;
4664
4072
  Session*  )   /*!< in: user thread */
4665
4073
{
4666
4074
  unsigned char*    original_upd_buff = upd_buff;
 
4075
  Field*    field;
4667
4076
  enum_field_types field_mysql_type;
4668
4077
  uint    n_fields;
4669
4078
  ulint   o_len;
4680
4089
  dict_index_t* clust_index;
4681
4090
  uint    i= 0;
4682
4091
 
4683
 
  n_fields = table->getShare()->sizeFields();
 
4092
  n_fields = table->s->fields;
4684
4093
  clust_index = dict_table_get_first_index(prebuilt->table);
4685
4094
 
4686
4095
  /* We use upd_buff to convert changed fields */
4687
4096
  buf = (byte*) upd_buff;
4688
4097
 
4689
4098
  for (i = 0; i < n_fields; i++) {
4690
 
    Field *field= table->getField(i);
 
4099
    field = table->field[i];
4691
4100
 
4692
4101
    o_ptr = (const byte*) old_row + get_field_offset(table, field);
4693
4102
    n_ptr = (const byte*) new_row + get_field_offset(table, field);
4726
4135
        o_ptr = row_mysql_read_true_varchar(
4727
4136
          &o_len, o_ptr,
4728
4137
          (ulint)
4729
 
          (((Field_varstring*)field)->pack_length_no_ptr()));
 
4138
          (((Field_varstring*)field)->length_bytes));
4730
4139
 
4731
4140
        n_ptr = row_mysql_read_true_varchar(
4732
4141
          &n_len, n_ptr,
4733
4142
          (ulint)
4734
 
          (((Field_varstring*)field)->pack_length_no_ptr()));
 
4143
          (((Field_varstring*)field)->length_bytes));
4735
4144
      }
4736
4145
 
4737
4146
      break;
4813
4222
 
4814
4223
  ut_a(prebuilt->trx == trx);
4815
4224
 
 
4225
  ha_statistic_increment(&system_status_var::ha_update_count);
 
4226
 
 
4227
  if (table->timestamp_field_type & TIMESTAMP_AUTO_SET_ON_UPDATE)
 
4228
    table->timestamp_field->set_time();
 
4229
 
4816
4230
  if (prebuilt->upd_node) {
4817
4231
    uvect = prebuilt->upd_node->update;
4818
4232
  } else {
4822
4236
  /* Build an update vector from the modified fields in the rows
4823
4237
  (uses upd_buff of the handle) */
4824
4238
 
4825
 
  calc_row_difference(uvect, (unsigned char*) old_row, new_row, getTable(),
4826
 
      &upd_buff[0], (ulint)upd_and_key_val_buff_len,
 
4239
  calc_row_difference(uvect, (unsigned char*) old_row, new_row, table,
 
4240
      upd_buff, (ulint)upd_and_key_val_buff_len,
4827
4241
      prebuilt, user_session);
4828
4242
 
4829
4243
  /* This is not a delete */
4831
4245
 
4832
4246
  ut_a(prebuilt->template_type == ROW_MYSQL_WHOLE_ROW);
4833
4247
 
4834
 
  if (getTable()->found_next_number_field)
4835
 
  {
4836
 
    uint64_t  auto_inc;
4837
 
    uint64_t  col_max_value;
4838
 
 
4839
 
    auto_inc = getTable()->found_next_number_field->val_int();
4840
 
 
4841
 
    /* We need the upper limit of the col type to check for
4842
 
    whether we update the table autoinc counter or not. */
4843
 
    col_max_value = innobase_get_int_col_max_value(
4844
 
      getTable()->found_next_number_field);
4845
 
 
4846
 
    uint64_t current_autoinc;
4847
 
    ulint autoinc_error= innobase_get_autoinc(&current_autoinc);
4848
 
    if (autoinc_error == DB_SUCCESS
4849
 
        && auto_inc <= col_max_value && auto_inc != 0
4850
 
        && auto_inc >= current_autoinc)
4851
 
    {
4852
 
 
4853
 
      uint64_t  need;
4854
 
      uint64_t  offset;
4855
 
 
4856
 
      offset = prebuilt->autoinc_offset;
4857
 
      need = prebuilt->autoinc_increment;
4858
 
 
4859
 
      auto_inc = innobase_next_autoinc(
4860
 
        auto_inc, need, offset, col_max_value);
4861
 
 
4862
 
      dict_table_autoinc_update_if_greater(prebuilt->table, auto_inc);
4863
 
    }
4864
 
 
4865
 
    dict_table_autoinc_unlock(prebuilt->table);
4866
 
  }
4867
 
 
4868
4248
  innodb_srv_conc_enter_innodb(trx);
4869
4249
 
4870
4250
  error = row_update_for_mysql((byte*) old_row, prebuilt);
4871
4251
 
4872
 
  user_session->setXaId(trx->id);
4873
 
 
4874
4252
  /* We need to do some special AUTOINC handling for the following case:
4875
4253
 
4876
4254
  INSERT INTO t (c1,c2) VALUES(x,y) ON DUPLICATE KEY UPDATE ...
4880
4258
  value used in the INSERT statement.*/
4881
4259
 
4882
4260
  if (error == DB_SUCCESS
4883
 
      && getTable()->next_number_field
4884
 
      && new_row == getTable()->getInsertRecord()
 
4261
      && table->next_number_field
 
4262
      && new_row == table->record[0]
4885
4263
      && session_sql_command(user_session) == SQLCOM_INSERT
4886
4264
      && (trx->duplicates & (TRX_DUP_IGNORE | TRX_DUP_REPLACE))
4887
4265
    == TRX_DUP_IGNORE)  {
4889
4267
    uint64_t  auto_inc;
4890
4268
    uint64_t  col_max_value;
4891
4269
 
4892
 
    auto_inc = getTable()->next_number_field->val_int();
 
4270
    auto_inc = table->next_number_field->val_int();
4893
4271
 
4894
4272
    /* We need the upper limit of the col type to check for
4895
4273
    whether we update the table autoinc counter or not. */
4896
4274
    col_max_value = innobase_get_int_col_max_value(
4897
 
      getTable()->next_number_field);
 
4275
      table->next_number_field);
4898
4276
 
4899
4277
    if (auto_inc <= col_max_value && auto_inc != 0) {
4900
4278
 
4949
4327
 
4950
4328
  ut_a(prebuilt->trx == trx);
4951
4329
 
 
4330
  ha_statistic_increment(&system_status_var::ha_delete_count);
 
4331
 
4952
4332
  if (!prebuilt->upd_node) {
4953
4333
    row_get_prebuilt_update_vector(prebuilt);
4954
4334
  }
4961
4341
 
4962
4342
  error = row_update_for_mysql((byte*) record, prebuilt);
4963
4343
 
4964
 
  user_session->setXaId(trx->id);
4965
 
 
4966
4344
  innodb_srv_conc_exit_innodb(trx);
4967
4345
 
4968
4346
  error = convert_error_code_to_mysql(
4996
4374
  case ROW_READ_WITH_LOCKS:
4997
4375
    if (!srv_locks_unsafe_for_binlog
4998
4376
        && prebuilt->trx->isolation_level
4999
 
        > TRX_ISO_READ_COMMITTED) {
 
4377
        != TRX_ISO_READ_COMMITTED) {
5000
4378
      break;
5001
4379
    }
5002
4380
    /* fall through */
5026
4404
ha_innobase::try_semi_consistent_read(bool yes)
5027
4405
/*===========================================*/
5028
4406
{
5029
 
  ut_a(prebuilt->trx == session_to_trx(getTable()->in_use));
 
4407
  ut_a(prebuilt->trx == session_to_trx(ha_session()));
5030
4408
 
5031
4409
  /* Row read type is set to semi consistent read if this was
5032
4410
  requested by the MySQL and either innodb_locks_unsafe_for_binlog
5035
4413
 
5036
4414
  if (yes
5037
4415
      && (srv_locks_unsafe_for_binlog
5038
 
    || prebuilt->trx->isolation_level <= TRX_ISO_READ_COMMITTED)) {
 
4416
    || prebuilt->trx->isolation_level == TRX_ISO_READ_COMMITTED)) {
5039
4417
    prebuilt->row_read_type = ROW_READ_TRY_SEMI_CONSISTENT;
5040
4418
  } else {
5041
4419
    prebuilt->row_read_type = ROW_READ_WITH_LOCKS;
5047
4425
@return 0 or error number */
5048
4426
UNIV_INTERN
5049
4427
int
5050
 
ha_innobase::doStartIndexScan(
 
4428
ha_innobase::index_init(
5051
4429
/*====================*/
5052
4430
  uint  keynr,  /*!< in: key (index) number */
5053
4431
  bool )    /*!< in: 1 if result MUST be sorted according to index */
5060
4438
@return 0 */
5061
4439
UNIV_INTERN
5062
4440
int
5063
 
ha_innobase::doEndIndexScan(void)
 
4441
ha_innobase::index_end(void)
5064
4442
/*========================*/
5065
4443
{
5066
4444
  int error = 0;
5216
4594
 
5217
4595
  index = prebuilt->index;
5218
4596
 
5219
 
  if (UNIV_UNLIKELY(index == NULL)) {
5220
 
    prebuilt->index_usable = FALSE;
5221
 
    return(HA_ERR_CRASHED);
5222
 
  }
5223
 
 
5224
 
  if (UNIV_UNLIKELY(!prebuilt->index_usable)) {
5225
 
    return(HA_ERR_TABLE_DEF_CHANGED);
5226
 
  }
5227
 
 
5228
4597
  /* Note that if the index for which the search template is built is not
5229
4598
  necessarily prebuilt->index, but can also be the clustered index */
5230
4599
 
5231
4600
  if (prebuilt->sql_stat_start) {
5232
 
    build_template(prebuilt, user_session, getTable(),
 
4601
    build_template(prebuilt, user_session, table,
5233
4602
             ROW_MYSQL_REC_FIELDS);
5234
4603
  }
5235
4604
 
5239
4608
 
5240
4609
    row_sel_convert_mysql_key_to_innobase(
5241
4610
      prebuilt->search_tuple,
5242
 
      (byte*) &key_val_buff[0],
 
4611
      (byte*) key_val_buff,
5243
4612
      (ulint)upd_and_key_val_buff_len,
5244
4613
      index,
5245
4614
      (byte*) key_ptr,
5284
4653
  switch (ret) {
5285
4654
  case DB_SUCCESS:
5286
4655
    error = 0;
5287
 
    getTable()->status = 0;
 
4656
    table->status = 0;
5288
4657
    break;
5289
4658
  case DB_RECORD_NOT_FOUND:
5290
4659
    error = HA_ERR_KEY_NOT_FOUND;
5291
 
    getTable()->status = STATUS_NOT_FOUND;
 
4660
    table->status = STATUS_NOT_FOUND;
5292
4661
    break;
5293
4662
  case DB_END_OF_INDEX:
5294
4663
    error = HA_ERR_KEY_NOT_FOUND;
5295
 
    getTable()->status = STATUS_NOT_FOUND;
 
4664
    table->status = STATUS_NOT_FOUND;
5296
4665
    break;
5297
4666
  default:
5298
4667
    error = convert_error_code_to_mysql((int) ret,
5299
4668
                prebuilt->table->flags,
5300
4669
                user_session);
5301
 
    getTable()->status = STATUS_NOT_FOUND;
 
4670
    table->status = STATUS_NOT_FOUND;
5302
4671
    break;
5303
4672
  }
5304
4673
 
5333
4702
        clustered index, even if it was internally
5334
4703
        generated by InnoDB */
5335
4704
{
 
4705
  KEY*    key = 0;
5336
4706
  dict_index_t* index = 0;
5337
4707
 
5338
4708
  ha_statistic_increment(&system_status_var::ha_read_key_count);
5339
4709
 
5340
 
  if (keynr != MAX_KEY && getTable()->getShare()->sizeKeys() > 0) 
5341
 
  {
5342
 
    KeyInfo *key = getTable()->key_info + keynr;
5343
 
    index = innobase_index_lookup(share, keynr);
5344
 
 
5345
 
    if (index) {
5346
 
      ut_a(ut_strcmp(index->name, key->name) == 0);
5347
 
    } else {
5348
 
      /* Can't find index with keynr in the translation
5349
 
         table. Only print message if the index translation
5350
 
         table exists */
5351
 
      if (share->idx_trans_tbl.index_mapping) {
5352
 
        errmsg_printf(ERRMSG_LVL_ERROR,
5353
 
                      "InnoDB could not find "
5354
 
                      "index %s key no %u for "
5355
 
                      "table %s through its "
5356
 
                      "index translation table",
5357
 
                      key ? key->name : "NULL",
5358
 
                      keynr,
5359
 
                      prebuilt->table->name);
5360
 
      }
5361
 
 
5362
 
      index = dict_table_get_index_on_name(prebuilt->table,
5363
 
                                           key->name);
5364
 
    }
 
4710
  ut_ad(user_session == ha_session());
 
4711
  ut_a(prebuilt->trx == session_to_trx(user_session));
 
4712
 
 
4713
  if (keynr != MAX_KEY && table->s->keys > 0) {
 
4714
    key = table->key_info + keynr;
 
4715
 
 
4716
    index = dict_table_get_index_on_name(prebuilt->table,
 
4717
                 key->name);
5365
4718
  } else {
5366
4719
    index = dict_table_get_first_index(prebuilt->table);
5367
4720
  }
5370
4723
    errmsg_printf(ERRMSG_LVL_ERROR, 
5371
4724
      "Innodb could not find key n:o %u with name %s "
5372
4725
      "from dict cache for table %s",
5373
 
      keynr, getTable()->getShare()->getTableProto()->indexes(keynr).name().c_str(),
 
4726
      keynr, key ? key->name : "NULL",
5374
4727
      prebuilt->table->name);
5375
4728
  }
5376
4729
 
5388
4741
      index, even if it was internally generated by
5389
4742
      InnoDB */
5390
4743
{
5391
 
  ut_ad(user_session == table->in_use);
 
4744
  ut_ad(user_session == ha_session());
5392
4745
  ut_a(prebuilt->trx == session_to_trx(user_session));
5393
4746
 
5394
4747
  active_index = keynr;
5398
4751
  if (UNIV_UNLIKELY(!prebuilt->index)) {
5399
4752
    errmsg_printf(ERRMSG_LVL_WARN, "InnoDB: change_active_index(%u) failed",
5400
4753
          keynr);
5401
 
    prebuilt->index_usable = FALSE;
5402
4754
    return(1);
5403
4755
  }
5404
4756
 
5406
4758
                 prebuilt->index);
5407
4759
 
5408
4760
  if (UNIV_UNLIKELY(!prebuilt->index_usable)) {
5409
 
    push_warning_printf(user_session, DRIZZLE_ERROR::WARN_LEVEL_WARN,
5410
 
                        HA_ERR_TABLE_DEF_CHANGED,
5411
 
                        "InnoDB: insufficient history for index %u",
5412
 
                        keynr);
 
4761
    errmsg_printf(ERRMSG_LVL_WARN,
 
4762
         "InnoDB: insufficient history for index %u",
 
4763
          keynr);
5413
4764
    /* The caller seems to ignore this.  Thus, we must check
5414
4765
    this again in row_search_for_mysql(). */
5415
4766
    return(2);
5428
4779
  the flag ROW_MYSQL_WHOLE_ROW below, but that caused unnecessary
5429
4780
  copying. Starting from MySQL-4.1 we use a more efficient flag here. */
5430
4781
 
5431
 
  build_template(prebuilt, user_session, getTable(), ROW_MYSQL_REC_FIELDS);
 
4782
  build_template(prebuilt, user_session, table, ROW_MYSQL_REC_FIELDS);
5432
4783
 
5433
4784
  return(0);
5434
4785
}
5488
4839
  switch (ret) {
5489
4840
  case DB_SUCCESS:
5490
4841
    error = 0;
5491
 
    getTable()->status = 0;
 
4842
    table->status = 0;
5492
4843
    break;
5493
4844
  case DB_RECORD_NOT_FOUND:
5494
4845
    error = HA_ERR_END_OF_FILE;
5495
 
    getTable()->status = STATUS_NOT_FOUND;
 
4846
    table->status = STATUS_NOT_FOUND;
5496
4847
    break;
5497
4848
  case DB_END_OF_INDEX:
5498
4849
    error = HA_ERR_END_OF_FILE;
5499
 
    getTable()->status = STATUS_NOT_FOUND;
 
4850
    table->status = STATUS_NOT_FOUND;
5500
4851
    break;
5501
4852
  default:
5502
4853
    error = convert_error_code_to_mysql(
5503
4854
      (int) ret, prebuilt->table->flags, user_session);
5504
 
    getTable()->status = STATUS_NOT_FOUND;
 
4855
    table->status = STATUS_NOT_FOUND;
5505
4856
    break;
5506
4857
  }
5507
4858
 
5610
4961
@return 0 or error number */
5611
4962
UNIV_INTERN
5612
4963
int
5613
 
ha_innobase::doStartTableScan(
 
4964
ha_innobase::rnd_init(
5614
4965
/*==================*/
5615
4966
  bool  scan) /*!< in: TRUE if table/index scan FALSE otherwise */
5616
4967
{
5642
4993
@return 0 or error number */
5643
4994
UNIV_INTERN
5644
4995
int
5645
 
ha_innobase::doEndTableScan(void)
 
4996
ha_innobase::rnd_end(void)
5646
4997
/*======================*/
5647
4998
{
5648
 
  return(doEndIndexScan());
 
4999
  return(index_end());
5649
5000
}
5650
5001
 
5651
5002
/*****************************************************************//**
5696
5047
 
5697
5048
  ha_statistic_increment(&system_status_var::ha_read_rnd_count);
5698
5049
 
5699
 
  ut_a(prebuilt->trx == session_to_trx(getTable()->in_use));
 
5050
  ut_a(prebuilt->trx == session_to_trx(ha_session()));
5700
5051
 
5701
5052
  if (prebuilt->clust_index_was_generated) {
5702
5053
    /* No primary key was defined for the table and we
5742
5093
{
5743
5094
  uint    len;
5744
5095
 
5745
 
  ut_a(prebuilt->trx == session_to_trx(getTable()->in_use));
 
5096
  ut_a(prebuilt->trx == session_to_trx(ha_session()));
5746
5097
 
5747
5098
  if (prebuilt->clust_index_was_generated) {
5748
5099
    /* No primary key was defined for the table and we
5801
5152
  ulint   charset_no;
5802
5153
  ulint   i;
5803
5154
 
5804
 
  n_cols = form->getShare()->sizeFields();
 
5155
  n_cols = form->s->fields;
5805
5156
 
5806
5157
  /* We pass 0 as the space id, and determine at a lower level the space
5807
5158
  id where to store the table */
5814
5165
  }
5815
5166
 
5816
5167
  for (i = 0; i < n_cols; i++) {
5817
 
    field = form->getField(i);
 
5168
    field = form->field[i];
5818
5169
 
5819
5170
    col_type = get_innobase_type_from_mysql_type(&unsigned_type,
5820
5171
                  field);
5821
 
 
5822
 
    if (!col_type) {
5823
 
      push_warning_printf(
5824
 
                          (Session*) trx->mysql_thd,
5825
 
                          DRIZZLE_ERROR::WARN_LEVEL_WARN,
5826
 
                          ER_CANT_CREATE_TABLE,
5827
 
                          "Error creating table '%s' with "
5828
 
                          "column '%s'. Please check its "
5829
 
                          "column type and try to re-create "
5830
 
                          "the table with an appropriate "
5831
 
                          "column type.",
5832
 
                          table->name, (char*) field->field_name);
5833
 
      goto err_col;
5834
 
    }
5835
 
 
5836
5172
    if (field->null_ptr) {
5837
5173
      nulls_allowed = 0;
5838
5174
    } else {
5878
5214
    long_true_varchar = 0;
5879
5215
 
5880
5216
    if (field->type() == DRIZZLE_TYPE_VARCHAR) {
5881
 
      col_len -= ((Field_varstring*)field)->pack_length_no_ptr();
 
5217
      col_len -= ((Field_varstring*)field)->length_bytes;
5882
5218
 
5883
 
      if (((Field_varstring*)field)->pack_length_no_ptr() == 2) {
 
5219
      if (((Field_varstring*)field)->length_bytes == 2) {
5884
5220
        long_true_varchar = DATA_LONG_TRUE_VARCHAR;
5885
5221
      }
5886
5222
    }
5887
5223
 
5888
 
    /* First check whether the column to be added has a
5889
 
       system reserved name. */
5890
 
    if (dict_col_name_is_reserved(field->field_name)){
5891
 
      my_error(ER_WRONG_COLUMN_NAME, MYF(0), field->field_name);
5892
 
 
5893
 
  err_col:
5894
 
      dict_mem_table_free(table);
5895
 
      trx_commit_for_mysql(trx);
5896
 
 
5897
 
      error = DB_ERROR;
5898
 
      goto error_ret;
5899
 
    }
5900
 
 
5901
5224
    dict_mem_table_add_col(table, table->heap,
5902
5225
      (char*) field->field_name,
5903
5226
      col_type,
5911
5234
 
5912
5235
  error = row_create_table_for_mysql(table, trx);
5913
5236
 
5914
 
        if (error == DB_DUPLICATE_KEY) {
5915
 
                char buf[100];
5916
 
                char* buf_end = innobase_convert_identifier(
5917
 
                        buf, sizeof buf - 1, table_name, strlen(table_name),
5918
 
                        trx->mysql_thd, TRUE);
5919
 
 
5920
 
                *buf_end = '\0';
5921
 
                my_error(ER_TABLE_EXISTS_ERROR, MYF(0), buf);
5922
 
        }
5923
 
 
5924
 
error_ret:
5925
5237
  error = convert_error_code_to_mysql(error, flags, NULL);
5926
5238
 
5927
5239
  return(error);
5944
5256
  dict_index_t* index;
5945
5257
  int   error;
5946
5258
  ulint   n_fields;
5947
 
  KeyInfo*    key;
5948
 
  KeyPartInfo*  key_part;
 
5259
  KEY*    key;
 
5260
  KEY_PART_INFO*  key_part;
5949
5261
  ulint   ind_type;
5950
5262
  ulint   col_type;
5951
5263
  ulint   prefix_len;
5954
5266
  ulint   j;
5955
5267
  ulint*    field_lengths;
5956
5268
 
5957
 
  key = &form->key_info[key_num];
 
5269
  key = form->key_info + key_num;
5958
5270
 
5959
5271
  n_fields = key->key_parts;
5960
5272
 
5961
 
  /* Assert that "GEN_CLUST_INDEX" cannot be used as non-primary index */
5962
 
  ut_a(innobase_strcasecmp(key->name, innobase_index_reserve_name) != 0);
5963
 
 
5964
5273
  ind_type = 0;
5965
5274
 
5966
 
  if (key_num == form->getShare()->getPrimaryKey()) {
 
5275
  if (key_num == form->s->primary_key) {
5967
5276
    ind_type = ind_type | DICT_CLUSTERED;
5968
5277
  }
5969
5278
 
5989
5298
    the length of the key part versus the column. */
5990
5299
 
5991
5300
    field = NULL;
5992
 
    for (j = 0; j < form->getShare()->sizeFields(); j++)
5993
 
    {
 
5301
    for (j = 0; j < form->s->fields; j++) {
5994
5302
 
5995
 
      field = form->getField(j);
 
5303
      field = form->field[j];
5996
5304
 
5997
5305
      if (0 == innobase_strcasecmp(
5998
5306
          field->field_name,
6003
5311
      }
6004
5312
    }
6005
5313
 
6006
 
    ut_a(j < form->getShare()->sizeFields());
 
5314
    ut_a(j < form->s->fields);
6007
5315
 
6008
5316
    col_type = get_innobase_type_from_mysql_type(
6009
5317
          &is_unsigned, key_part->field);
6013
5321
        && field->type() != DRIZZLE_TYPE_VARCHAR)
6014
5322
      || (field->type() == DRIZZLE_TYPE_VARCHAR
6015
5323
        && key_part->length < field->pack_length()
6016
 
        - ((Field_varstring*)field)->pack_length_no_ptr())) {
 
5324
        - ((Field_varstring*)field)->length_bytes)) {
6017
5325
 
6018
5326
      prefix_len = key_part->length;
6019
5327
 
6070
5378
  /* We pass 0 as the space id, and determine at a lower level the space
6071
5379
  id where to store the table */
6072
5380
 
6073
 
  index = dict_mem_index_create(table_name,
6074
 
                                innobase_index_reserve_name,
6075
 
                                0, DICT_CLUSTERED, 0);
 
5381
  index = dict_mem_index_create(table_name, "GEN_CLUST_INDEX",
 
5382
              0, DICT_CLUSTERED, 0);
6076
5383
 
6077
5384
  error = row_create_index_for_mysql(index, trx, NULL);
6078
5385
 
6087
5394
KEY_BLOCK_SIZE and ROW_FORMAT
6088
5395
If innodb_strict_mode is not set then this function is a no-op
6089
5396
@return TRUE if valid. */
6090
 
#if 0
6091
5397
static
6092
5398
ibool
6093
5399
create_options_are_valid(
6108
5414
    return(TRUE);
6109
5415
  }
6110
5416
 
 
5417
  /* First check if KEY_BLOCK_SIZE was specified. */
 
5418
  if (create_proto.options().has_key_block_size()) {
 
5419
 
 
5420
    kbs_specified = TRUE;
 
5421
    switch (create_proto.options().key_block_size()) {
 
5422
    case 1:
 
5423
    case 2:
 
5424
    case 4:
 
5425
    case 8:
 
5426
    case 16:
 
5427
      /* Valid value. */
 
5428
      break;
 
5429
    default:
 
5430
      push_warning_printf(session, DRIZZLE_ERROR::WARN_LEVEL_ERROR,
 
5431
              ER_ILLEGAL_HA_CREATE_OPTION,
 
5432
              "InnoDB: invalid"
 
5433
              " KEY_BLOCK_SIZE = %lu."
 
5434
              " Valid values are"
 
5435
              " [1, 2, 4, 8, 16]",
 
5436
              create_proto.options().key_block_size());
 
5437
      ret = FALSE;
 
5438
    }
 
5439
  }
 
5440
  
 
5441
  /* If KEY_BLOCK_SIZE was specified, check for its
 
5442
  dependencies. */
 
5443
  if (kbs_specified && !srv_file_per_table) {
 
5444
    push_warning(session, DRIZZLE_ERROR::WARN_LEVEL_ERROR,
 
5445
           ER_ILLEGAL_HA_CREATE_OPTION,
 
5446
           "InnoDB: KEY_BLOCK_SIZE"
 
5447
           " requires innodb_file_per_table.");
 
5448
    ret = FALSE;
 
5449
  }
 
5450
 
 
5451
  if (kbs_specified && srv_file_format < DICT_TF_FORMAT_ZIP) {
 
5452
    push_warning(session, DRIZZLE_ERROR::WARN_LEVEL_ERROR,
 
5453
           ER_ILLEGAL_HA_CREATE_OPTION,
 
5454
           "InnoDB: KEY_BLOCK_SIZE"
 
5455
           " requires innodb_file_format >"
 
5456
           " Antelope.");
 
5457
    ret = FALSE;
 
5458
  }
 
5459
 
6111
5460
  /* Now check for ROW_FORMAT specifier. */
 
5461
  if (create_proto.options().has_row_type()) {
 
5462
    switch (form.s->row_type) {
 
5463
      const char* row_format_name;
 
5464
    case ROW_TYPE_COMPRESSED:
 
5465
    case ROW_TYPE_DYNAMIC:
 
5466
      row_format_name
 
5467
        = form.s->row_type == ROW_TYPE_COMPRESSED
 
5468
        ? "COMPRESSED"
 
5469
        : "DYNAMIC";
 
5470
 
 
5471
      /* These two ROW_FORMATs require
 
5472
      srv_file_per_table and srv_file_format */
 
5473
      if (!srv_file_per_table) {
 
5474
        push_warning_printf(
 
5475
          session,
 
5476
          DRIZZLE_ERROR::WARN_LEVEL_ERROR,
 
5477
          ER_ILLEGAL_HA_CREATE_OPTION,
 
5478
          "InnoDB: ROW_FORMAT=%s"
 
5479
          " requires innodb_file_per_table.",
 
5480
          row_format_name);
 
5481
          ret = FALSE;
 
5482
 
 
5483
      }
 
5484
 
 
5485
      if (srv_file_format < DICT_TF_FORMAT_ZIP) {
 
5486
        push_warning_printf(
 
5487
          session,
 
5488
          DRIZZLE_ERROR::WARN_LEVEL_ERROR,
 
5489
          ER_ILLEGAL_HA_CREATE_OPTION,
 
5490
          "InnoDB: ROW_FORMAT=%s"
 
5491
          " requires innodb_file_format >"
 
5492
          " Antelope.",
 
5493
          row_format_name);
 
5494
          ret = FALSE;
 
5495
      }
 
5496
 
 
5497
      /* Cannot specify KEY_BLOCK_SIZE with
 
5498
      ROW_FORMAT = DYNAMIC.
 
5499
      However, we do allow COMPRESSED to be
 
5500
      specified with KEY_BLOCK_SIZE. */
 
5501
      if (kbs_specified
 
5502
          && form.s->row_type == ROW_TYPE_DYNAMIC) {
 
5503
        push_warning_printf(
 
5504
          session,
 
5505
          DRIZZLE_ERROR::WARN_LEVEL_ERROR,
 
5506
          ER_ILLEGAL_HA_CREATE_OPTION,
 
5507
          "InnoDB: cannot specify"
 
5508
          " ROW_FORMAT = DYNAMIC with"
 
5509
          " KEY_BLOCK_SIZE.");
 
5510
          ret = FALSE;
 
5511
      }
 
5512
 
 
5513
      break;
 
5514
 
 
5515
    case ROW_TYPE_REDUNDANT:
 
5516
    case ROW_TYPE_COMPACT:
 
5517
    case ROW_TYPE_DEFAULT:
 
5518
      /* Default is COMPACT. */
 
5519
      row_format_name
 
5520
        = form.s->row_type == ROW_TYPE_REDUNDANT
 
5521
        ? "REDUNDANT"
 
5522
        : "COMPACT";
 
5523
 
 
5524
      /* Cannot specify KEY_BLOCK_SIZE with these
 
5525
      format specifiers. */
 
5526
      if (kbs_specified) {
 
5527
        push_warning_printf(
 
5528
          session,
 
5529
          DRIZZLE_ERROR::WARN_LEVEL_ERROR,
 
5530
          ER_ILLEGAL_HA_CREATE_OPTION,
 
5531
          "InnoDB: cannot specify"
 
5532
          " ROW_FORMAT = %s with"
 
5533
          " KEY_BLOCK_SIZE.",
 
5534
          row_format_name);
 
5535
          ret = FALSE;
 
5536
      }
 
5537
 
 
5538
      break;
 
5539
 
 
5540
    default:
 
5541
      push_warning(session,
 
5542
             DRIZZLE_ERROR::WARN_LEVEL_ERROR,
 
5543
             ER_ILLEGAL_HA_CREATE_OPTION,
 
5544
             "InnoDB: invalid ROW_FORMAT specifier.");
 
5545
      ret = FALSE;
 
5546
 
 
5547
    }
 
5548
  }
 
5549
 
6112
5550
  return(ret);
6113
5551
}
6114
 
#endif
6115
5552
 
6116
5553
/*********************************************************************
6117
5554
Creates a new table to an InnoDB database. */
6121
5558
/*================*/
6122
5559
  Session         &session, /*!< in: Session */
6123
5560
  Table&    form,   /*!< in: information on table columns and indexes */
6124
 
        const TableIdentifier &identifier,
 
5561
        drizzled::TableIdentifier &identifier,
6125
5562
        message::Table& create_proto)
6126
5563
{
6127
5564
  int   error;
6135
5572
  ib_int64_t  auto_inc_value;
6136
5573
  ulint   iflags;
6137
5574
  /* Cache the value of innodb_file_format, in case it is
6138
 
    modified by another thread while the table is being created. */
 
5575
  modified by another thread while the table is being created. */
6139
5576
  const ulint file_format = srv_file_format;
6140
 
  bool lex_identified_temp_table= (create_proto.type() == message::Table::TEMPORARY);
6141
 
  const char* stmt;
6142
 
  size_t stmt_len;
 
5577
        bool lex_identified_temp_table= (create_proto.type() == message::Table::TEMPORARY);
6143
5578
 
6144
5579
  const char *table_name= identifier.getPath().c_str();
6145
5580
 
6146
 
  if (form.getShare()->sizeFields() > 1000) {
 
5581
#ifdef __WIN__
 
5582
  /* Names passed in from server are in two formats:
 
5583
  1. <database_name>/<table_name>: for normal table creation
 
5584
  2. full path: for temp table creation, or sym link
 
5585
 
 
5586
  When srv_file_per_table is on, check for full path pattern, i.e.
 
5587
  X:\dir\...,   X is a driver letter, or
 
5588
  \\dir1\dir2\...,  UNC path
 
5589
  returns error if it is in full path format, but not creating a temp.
 
5590
  table. Currently InnoDB does not support symbolic link on Windows. */
 
5591
 
 
5592
  if (srv_file_per_table
 
5593
      && (! lex_identified_temp_table)) {
 
5594
 
 
5595
    if ((table_name[1] == ':')
 
5596
        || (table_name[0] == '\\' && table_name[1] == '\\')) {
 
5597
      errmsg_printf(ERRMSG_LVL_ERROR, "Cannot create table %s\n", table_name);
 
5598
      return(HA_ERR_GENERIC);
 
5599
    }
 
5600
  }
 
5601
#endif
 
5602
 
 
5603
  if (form.s->fields > 1000) {
6147
5604
    /* The limit probably should be REC_MAX_N_FIELDS - 3 = 1020,
6148
 
      but we play safe here */
 
5605
    but we play safe here */
6149
5606
 
6150
5607
    return(HA_ERR_TO_BIG_ROW);
6151
5608
  }
6152
5609
 
6153
5610
  /* Get the transaction associated with the current session, or create one
6154
 
    if not yet created */
 
5611
  if not yet created */
6155
5612
 
6156
5613
  parent_trx = check_trx_exists(&session);
6157
5614
 
6158
5615
  /* In case MySQL calls this in the middle of a SELECT query, release
6159
 
    possible adaptive hash latch to avoid deadlocks of threads */
 
5616
  possible adaptive hash latch to avoid deadlocks of threads */
6160
5617
 
6161
5618
  trx_search_latch_release_if_reserved(parent_trx);
6162
5619
 
6169
5626
  normalize_table_name(norm_name, name2);
6170
5627
 
6171
5628
  /* Latch the InnoDB data dictionary exclusively so that no deadlocks
6172
 
    or lock waits can happen in it during a table create operation.
6173
 
    Drop table etc. do this latching in row0mysql.c. */
 
5629
  or lock waits can happen in it during a table create operation.
 
5630
  Drop table etc. do this latching in row0mysql.c. */
6174
5631
 
6175
5632
  row_mysql_lock_data_dictionary(trx);
6176
5633
 
6178
5635
 
6179
5636
  iflags = 0;
6180
5637
 
6181
 
#if 0 // Since we validate the options before this stage, we no longer need to do this.
6182
5638
  /* Validate create options if innodb_strict_mode is set. */
6183
5639
  if (! create_options_are_valid(&session, form, create_proto)) {
6184
5640
    error = ER_ILLEGAL_HA_CREATE_OPTION;
6185
5641
    goto cleanup;
6186
5642
  }
6187
 
#endif
6188
 
 
6189
 
  // We assume compact format by default
6190
 
  iflags= DICT_TF_COMPACT;
6191
 
 
6192
 
  size_t num_engine_options= create_proto.engine().options_size();
6193
 
  for (size_t x= 0; x < num_engine_options; ++x)
6194
 
  {
6195
 
    if (boost::iequals(create_proto.engine().options(x).name(), "ROW_FORMAT"))
6196
 
    {
6197
 
      if (boost::iequals(create_proto.engine().options(x).state(), "COMPRESSED"))
6198
 
      {
6199
 
        iflags= DICT_TF_FORMAT_ZIP;
6200
 
      }
6201
 
      else if (boost::iequals(create_proto.engine().options(x).state(), "COMPACT"))
6202
 
      {
6203
 
        iflags= DICT_TF_FORMAT_ZIP;
6204
 
      }
6205
 
      else if (boost::iequals(create_proto.engine().options(x).state(), "DYNAMIC"))
6206
 
      {
6207
 
        iflags= DICT_TF_COMPACT;
6208
 
      }
6209
 
      else if (boost::iequals(create_proto.engine().options(x).state(), "REDUNDANT"))
6210
 
      {
6211
 
        iflags= DICT_TF_COMPACT;
6212
 
      }
6213
 
    }
6214
 
    else
6215
 
    {
6216
 
      assert(0); // This should never happen since we have already validated the options.
 
5643
 
 
5644
  if (create_proto.options().has_key_block_size()) {
 
5645
    /* Determine the page_zip.ssize corresponding to the
 
5646
    requested page size (key_block_size) in kilobytes. */
 
5647
 
 
5648
    ulint ssize, ksize;
 
5649
    ulint key_block_size = create_proto.options().key_block_size();
 
5650
 
 
5651
    for (ssize = ksize = 1; ssize <= DICT_TF_ZSSIZE_MAX;
 
5652
         ssize++, ksize <<= 1) {
 
5653
      if (key_block_size == ksize) {
 
5654
        iflags = ssize << DICT_TF_ZSSIZE_SHIFT
 
5655
          | DICT_TF_COMPACT
 
5656
          | DICT_TF_FORMAT_ZIP
 
5657
            << DICT_TF_FORMAT_SHIFT;
 
5658
        break;
 
5659
      }
 
5660
    }
 
5661
 
 
5662
    if (!srv_file_per_table) {
 
5663
      push_warning(&session, DRIZZLE_ERROR::WARN_LEVEL_WARN,
 
5664
             ER_ILLEGAL_HA_CREATE_OPTION,
 
5665
             "InnoDB: KEY_BLOCK_SIZE"
 
5666
             " requires innodb_file_per_table.");
 
5667
      iflags = 0;
 
5668
    }
 
5669
 
 
5670
    if (file_format < DICT_TF_FORMAT_ZIP) {
 
5671
      push_warning(&session, DRIZZLE_ERROR::WARN_LEVEL_WARN,
 
5672
             ER_ILLEGAL_HA_CREATE_OPTION,
 
5673
             "InnoDB: KEY_BLOCK_SIZE"
 
5674
             " requires innodb_file_format >"
 
5675
             " Antelope.");
 
5676
      iflags = 0;
 
5677
    }
 
5678
 
 
5679
    if (!iflags) {
 
5680
      push_warning_printf(&session, DRIZZLE_ERROR::WARN_LEVEL_WARN,
 
5681
              ER_ILLEGAL_HA_CREATE_OPTION,
 
5682
              "InnoDB: ignoring"
 
5683
              " KEY_BLOCK_SIZE=%lu.",
 
5684
              create_proto.options().key_block_size());
6217
5685
    }
6218
5686
  }
6219
5687
 
6220
 
  if (iflags == DICT_TF_FORMAT_ZIP)
6221
 
  {
6222
 
    /* 
6223
 
      ROW_FORMAT=COMPRESSED without KEY_BLOCK_SIZE implies half the maximum KEY_BLOCK_SIZE.
6224
 
      @todo implement KEY_BLOCK_SIZE
6225
 
    */
6226
 
    iflags= (DICT_TF_ZSSIZE_MAX - 1)
6227
 
      << DICT_TF_ZSSIZE_SHIFT
6228
 
      | DICT_TF_COMPACT
6229
 
      | DICT_TF_FORMAT_ZIP
6230
 
      << DICT_TF_FORMAT_SHIFT;
 
5688
  if (create_proto.options().has_row_type()) {
 
5689
    if (iflags) {
 
5690
      /* KEY_BLOCK_SIZE was specified. */
 
5691
      if (form.s->row_type != ROW_TYPE_COMPRESSED) {
 
5692
        /* ROW_FORMAT other than COMPRESSED
 
5693
        ignores KEY_BLOCK_SIZE.  It does not
 
5694
        make sense to reject conflicting
 
5695
        KEY_BLOCK_SIZE and ROW_FORMAT, because
 
5696
        such combinations can be obtained
 
5697
        with ALTER TABLE anyway. */
 
5698
        push_warning_printf(
 
5699
          &session,
 
5700
          DRIZZLE_ERROR::WARN_LEVEL_WARN,
 
5701
          ER_ILLEGAL_HA_CREATE_OPTION,
 
5702
          "InnoDB: ignoring KEY_BLOCK_SIZE=%lu"
 
5703
          " unless ROW_FORMAT=COMPRESSED.",
 
5704
          create_proto.options().key_block_size());
 
5705
        iflags = 0;
 
5706
      }
 
5707
    } else {
 
5708
      /* No KEY_BLOCK_SIZE */
 
5709
      if (form.s->row_type == ROW_TYPE_COMPRESSED) {
 
5710
        /* ROW_FORMAT=COMPRESSED without
 
5711
        KEY_BLOCK_SIZE implies half the
 
5712
        maximum KEY_BLOCK_SIZE. */
 
5713
        iflags = (DICT_TF_ZSSIZE_MAX - 1)
 
5714
          << DICT_TF_ZSSIZE_SHIFT
 
5715
          | DICT_TF_COMPACT
 
5716
          | DICT_TF_FORMAT_ZIP
 
5717
          << DICT_TF_FORMAT_SHIFT;
6231
5718
#if DICT_TF_ZSSIZE_MAX < 1
6232
5719
# error "DICT_TF_ZSSIZE_MAX < 1"
6233
5720
#endif
6234
 
 
6235
 
    if (strict_mode)
6236
 
    {
6237
 
      if (! srv_file_per_table)
6238
 
      {
6239
 
        push_warning_printf(
6240
 
                            &session,
6241
 
                            DRIZZLE_ERROR::WARN_LEVEL_WARN,
6242
 
                            ER_ILLEGAL_HA_CREATE_OPTION,
6243
 
                            "InnoDB: ROW_FORMAT=COMPRESSED requires innodb_file_per_table.");
6244
 
      } 
6245
 
      else if (file_format < DICT_TF_FORMAT_ZIP) 
6246
 
      {
6247
 
        push_warning_printf(
6248
 
                            &session,
6249
 
                            DRIZZLE_ERROR::WARN_LEVEL_WARN,
6250
 
                            ER_ILLEGAL_HA_CREATE_OPTION,
6251
 
                            "InnoDB: ROW_FORMAT=compressed requires innodb_file_format > Antelope.");
6252
 
      }
6253
 
    }
 
5721
      }
 
5722
    }
 
5723
 
 
5724
    switch (form.s->row_type) {
 
5725
      const char* row_format_name;
 
5726
    case ROW_TYPE_REDUNDANT:
 
5727
      break;
 
5728
    case ROW_TYPE_COMPRESSED:
 
5729
    case ROW_TYPE_DYNAMIC:
 
5730
      row_format_name
 
5731
        = form.s->row_type == ROW_TYPE_COMPRESSED
 
5732
        ? "COMPRESSED"
 
5733
        : "DYNAMIC";
 
5734
 
 
5735
      if (!srv_file_per_table) {
 
5736
        push_warning_printf(
 
5737
          &session,
 
5738
          DRIZZLE_ERROR::WARN_LEVEL_WARN,
 
5739
          ER_ILLEGAL_HA_CREATE_OPTION,
 
5740
          "InnoDB: ROW_FORMAT=%s"
 
5741
          " requires innodb_file_per_table.",
 
5742
          row_format_name);
 
5743
      } else if (file_format < DICT_TF_FORMAT_ZIP) {
 
5744
        push_warning_printf(
 
5745
          &session,
 
5746
          DRIZZLE_ERROR::WARN_LEVEL_WARN,
 
5747
          ER_ILLEGAL_HA_CREATE_OPTION,
 
5748
          "InnoDB: ROW_FORMAT=%s"
 
5749
          " requires innodb_file_format >"
 
5750
          " Antelope.",
 
5751
          row_format_name);
 
5752
      } else {
 
5753
        iflags |= DICT_TF_COMPACT
 
5754
          | (DICT_TF_FORMAT_ZIP
 
5755
             << DICT_TF_FORMAT_SHIFT);
 
5756
        break;
 
5757
      }
 
5758
 
 
5759
      /* fall through */
 
5760
    case ROW_TYPE_NOT_USED:
 
5761
    case ROW_TYPE_FIXED:
 
5762
    default:
 
5763
                        error = ER_ILLEGAL_HA_CREATE_OPTION;
 
5764
                        goto cleanup;
 
5765
    case ROW_TYPE_DEFAULT:
 
5766
    case ROW_TYPE_COMPACT:
 
5767
      iflags = DICT_TF_COMPACT;
 
5768
      break;
 
5769
    }
 
5770
  } else if (!iflags) {
 
5771
    /* No KEY_BLOCK_SIZE or ROW_FORMAT specified:
 
5772
    use ROW_FORMAT=COMPACT by default. */
 
5773
    iflags = DICT_TF_COMPACT;
 
5774
  }
 
5775
 
 
5776
  error = create_table_def(trx, &form, norm_name,
 
5777
    lex_identified_temp_table ? name2 : NULL,
 
5778
    iflags);
 
5779
 
 
5780
  if (error) {
 
5781
    goto cleanup;
6254
5782
  }
6255
5783
 
6256
5784
  /* Look for a primary key */
6257
5785
 
6258
 
  primary_key_no= (form.getShare()->hasPrimaryKey() ?
6259
 
                   (int) form.getShare()->getPrimaryKey() :
6260
 
                   -1);
 
5786
  primary_key_no= (form.s->primary_key != MAX_KEY ?
 
5787
       (int) form.s->primary_key :
 
5788
       -1);
6261
5789
 
6262
 
  /* Our function innobase_get_mysql_key_number_for_index assumes
6263
 
    the primary key is always number 0, if it exists */
 
5790
  /* Our function row_get_mysql_key_number_for_index assumes
 
5791
  the primary key is always number 0, if it exists */
6264
5792
 
6265
5793
  assert(primary_key_no == -1 || primary_key_no == 0);
6266
5794
 
6267
 
  /* Check for name conflicts (with reserved name) for
6268
 
     any user indices to be created. */
6269
 
  if (innobase_index_name_is_reserved(trx, form.key_info,
6270
 
                                      form.getShare()->keys)) {
6271
 
    error = -1;
6272
 
    goto cleanup;
6273
 
  }
6274
 
 
6275
 
  if (lex_identified_temp_table)
6276
 
    iflags |= DICT_TF2_TEMPORARY << DICT_TF2_SHIFT;
6277
 
 
6278
 
  error= create_table_def(trx, &form, norm_name,
6279
 
                          lex_identified_temp_table ? name2 : NULL,
6280
 
                          iflags);
6281
 
 
6282
 
  session.setXaId(trx->id);
6283
 
 
6284
 
  if (error) {
6285
 
    goto cleanup;
6286
 
  }
6287
 
 
6288
5795
  /* Create the keys */
6289
5796
 
6290
 
  if (form.getShare()->sizeKeys() == 0 || primary_key_no == -1) {
 
5797
  if (form.s->keys == 0 || primary_key_no == -1) {
6291
5798
    /* Create an index which is used as the clustered index;
6292
 
      order the rows by their row id which is internally generated
6293
 
      by InnoDB */
 
5799
    order the rows by their row id which is internally generated
 
5800
    by InnoDB */
6294
5801
 
6295
 
    error = create_clustered_index_when_no_primary(trx, iflags, norm_name);
 
5802
    error = create_clustered_index_when_no_primary(
 
5803
      trx, iflags, norm_name);
6296
5804
    if (error) {
6297
5805
      goto cleanup;
6298
5806
    }
6299
5807
  }
6300
5808
 
6301
5809
  if (primary_key_no != -1) {
6302
 
    /* In InnoDB the clustered index must always be created first */
 
5810
    /* In InnoDB the clustered index must always be created
 
5811
    first */
6303
5812
    if ((error = create_index(trx, &form, iflags, norm_name,
6304
 
                              (uint) primary_key_no))) {
 
5813
            (uint) primary_key_no))) {
6305
5814
      goto cleanup;
6306
5815
    }
6307
5816
  }
6308
5817
 
6309
 
  for (i = 0; i < form.getShare()->sizeKeys(); i++) {
 
5818
  for (i = 0; i < form.s->keys; i++) {
 
5819
 
6310
5820
    if (i != (uint) primary_key_no) {
6311
5821
 
6312
5822
      if ((error = create_index(trx, &form, iflags, norm_name,
6313
 
                                i))) {
 
5823
              i))) {
6314
5824
        goto cleanup;
6315
5825
      }
6316
5826
    }
6317
5827
  }
6318
5828
 
6319
 
  stmt = innobase_get_stmt(&session, &stmt_len);
6320
 
 
6321
 
  if (stmt) {
6322
 
    string generated_create_table;
6323
 
    const char *query= stmt;
6324
 
 
6325
 
    if (session_sql_command(&session) == SQLCOM_CREATE_TABLE)
6326
 
    {
6327
 
      message::transformTableDefinitionToSql(create_proto,
6328
 
                                             generated_create_table,
6329
 
                                             message::DRIZZLE, true);
6330
 
      query= generated_create_table.c_str();
6331
 
    }
6332
 
 
 
5829
  if (trx->mysql_query_str) {
6333
5830
    error = row_table_add_foreign_constraints(trx,
6334
 
                                              query, strlen(query),
6335
 
                                              norm_name,
6336
 
                                              lex_identified_temp_table);
 
5831
      trx->mysql_query_str, norm_name,
 
5832
      lex_identified_temp_table);
6337
5833
 
6338
5834
    error = convert_error_code_to_mysql(error, iflags, NULL);
6339
5835
 
6347
5843
  row_mysql_unlock_data_dictionary(trx);
6348
5844
 
6349
5845
  /* Flush the log to reduce probability that the .frm files and
6350
 
    the InnoDB data dictionary get out-of-sync if the user runs
6351
 
    with innodb_flush_log_at_trx_commit = 0 */
 
5846
  the InnoDB data dictionary get out-of-sync if the user runs
 
5847
  with innodb_flush_log_at_trx_commit = 0 */
6352
5848
 
6353
5849
  log_buffer_flush_to_disk();
6354
5850
 
6358
5854
 
6359
5855
  if (innobase_table) {
6360
5856
    /* We update the highest file format in the system table
6361
 
      space, if this table has higher file format setting. */
 
5857
    space, if this table has higher file format setting. */
6362
5858
 
6363
 
    char changed_file_format_max[100];
6364
 
    strcpy(changed_file_format_max, innobase_file_format_max.c_str());
6365
 
    trx_sys_file_format_max_upgrade((const char **)&changed_file_format_max,
 
5859
    trx_sys_file_format_max_upgrade(
 
5860
      (const char**) &innobase_file_format_check,
6366
5861
      dict_table_get_format(innobase_table));
6367
 
    innobase_file_format_max= changed_file_format_max;
6368
5862
  }
6369
5863
 
6370
5864
  /* Note: We can't call update_session() as prebuilt will not be
6371
 
    setup at this stage and so we use session. */
 
5865
  setup at this stage and so we use session. */
6372
5866
 
6373
5867
  /* We need to copy the AUTOINC value from the old table if
6374
 
    this is an ALTER TABLE or CREATE INDEX because CREATE INDEX
6375
 
    does a table copy too. */
 
5868
  this is an ALTER TABLE. */
6376
5869
 
6377
5870
  if ((create_proto.options().has_auto_increment_value()
6378
 
       || session_sql_command(&session) == SQLCOM_ALTER_TABLE
6379
 
       || session_sql_command(&session) == SQLCOM_CREATE_INDEX)
 
5871
      || session_sql_command(&session) == SQLCOM_ALTER_TABLE)
6380
5872
      && create_proto.options().auto_increment_value() != 0) {
6381
5873
 
6382
 
    /* Query was one of :
6383
 
       CREATE TABLE ...AUTO_INCREMENT = x; or
6384
 
       ALTER TABLE...AUTO_INCREMENT = x;   or
6385
 
       CREATE INDEX x on t(...);
6386
 
       Find out a table definition from the dictionary and get
6387
 
       the current value of the auto increment field. Set a new
6388
 
       value to the auto increment field if the value is greater
6389
 
       than the maximum value in the column. */
 
5874
    /* Query was ALTER TABLE...AUTO_INCREMENT = x; or
 
5875
    CREATE TABLE ...AUTO_INCREMENT = x; Find out a table
 
5876
    definition from the dictionary and get the current value
 
5877
    of the auto increment field. Set a new value to the
 
5878
    auto increment field if the value is greater than the
 
5879
    maximum value in the column. */
6390
5880
 
6391
5881
    auto_inc_value = create_proto.options().auto_increment_value();
6392
5882
 
6396
5886
  }
6397
5887
 
6398
5888
  /* Tell the InnoDB server that there might be work for
6399
 
    utility threads: */
 
5889
  utility threads: */
6400
5890
 
6401
5891
  srv_active_wake_master_thread();
6402
5892
 
6403
5893
  trx_free_for_mysql(trx);
6404
5894
 
6405
 
  if (lex_identified_temp_table)
6406
 
  {
6407
 
    session.getMessageCache().storeTableMessage(identifier, create_proto);
6408
 
  }
6409
 
  else
6410
 
  {
6411
 
    StorageEngine::writeDefinitionFromPath(identifier, create_proto);
6412
 
  }
 
5895
        StorageEngine::writeDefinitionFromPath(identifier, create_proto);
6413
5896
 
6414
5897
  return(0);
6415
5898
 
6438
5921
 
6439
5922
  ut_a(prebuilt->trx);
6440
5923
  ut_a(prebuilt->trx->magic_n == TRX_MAGIC_N);
6441
 
  ut_a(prebuilt->trx == session_to_trx(getTable()->in_use));
 
5924
  ut_a(prebuilt->trx == session_to_trx(ha_session()));
6442
5925
 
6443
5926
  dict_table = prebuilt->table;
6444
5927
  trx = prebuilt->trx;
6467
5950
  /* Get the transaction associated with the current session, or create one
6468
5951
  if not yet created, and update prebuilt->trx */
6469
5952
 
6470
 
  update_session(getTable()->in_use);
 
5953
  update_session(ha_session());
6471
5954
 
6472
5955
  if (session_sql_command(user_session) != SQLCOM_TRUNCATE) {
6473
5956
  fallback:
6503
5986
InnobaseEngine::doDropTable(
6504
5987
/*======================*/
6505
5988
        Session &session,
6506
 
        const TableIdentifier &identifier)
 
5989
        TableIdentifier &identifier)
6507
5990
{
6508
5991
  int error;
6509
5992
  trx_t*  parent_trx;
6513
5996
  ut_a(identifier.getPath().length() < 1000);
6514
5997
 
6515
5998
  /* Strangely, MySQL passes the table name without the '.frm'
6516
 
    extension, in contrast to ::create */
 
5999
  extension, in contrast to ::create */
6517
6000
  normalize_table_name(norm_name, identifier.getPath().c_str());
6518
6001
 
6519
6002
  /* Get the transaction associated with the current session, or create one
6520
 
    if not yet created */
 
6003
  if not yet created */
6521
6004
 
6522
6005
  parent_trx = check_trx_exists(&session);
6523
6006
 
6524
6007
  /* In case MySQL calls this in the middle of a SELECT query, release
6525
 
    possible adaptive hash latch to avoid deadlocks of threads */
 
6008
  possible adaptive hash latch to avoid deadlocks of threads */
6526
6009
 
6527
6010
  trx_search_latch_release_if_reserved(parent_trx);
6528
6011
 
6533
6016
  /* Drop the table in InnoDB */
6534
6017
 
6535
6018
  error = row_drop_table_for_mysql(norm_name, trx,
6536
 
                                   session_sql_command(&session)
6537
 
                                   == SQLCOM_DROP_DB);
6538
 
 
6539
 
  session.setXaId(trx->id);
 
6019
           session_sql_command(&session)
 
6020
           == SQLCOM_DROP_DB);
6540
6021
 
6541
6022
  /* Flush the log to reduce probability that the .frm files and
6542
 
    the InnoDB data dictionary get out-of-sync if the user runs
6543
 
    with innodb_flush_log_at_trx_commit = 0 */
 
6023
  the InnoDB data dictionary get out-of-sync if the user runs
 
6024
  with innodb_flush_log_at_trx_commit = 0 */
6544
6025
 
6545
6026
  log_buffer_flush_to_disk();
6546
6027
 
6547
6028
  /* Tell the InnoDB server that there might be work for
6548
 
    utility threads: */
 
6029
  utility threads: */
6549
6030
 
6550
6031
  srv_active_wake_master_thread();
6551
6032
 
6553
6034
 
6554
6035
  trx_free_for_mysql(trx);
6555
6036
 
6556
 
  if (error != ENOENT)
 
6037
  if(error!=ENOENT)
6557
6038
    error = convert_error_code_to_mysql(error, 0, NULL);
6558
6039
 
6559
 
  if (error == 0 || error == ENOENT)
6560
 
  {
6561
 
    if (identifier.getType() == message::Table::TEMPORARY)
6562
 
    {
6563
 
      session.getMessageCache().removeTableMessage(identifier);
6564
 
      ulint sql_command = session_sql_command(&session);
6565
 
 
6566
 
      // If this was the final removal to an alter table then we will need
6567
 
      // to remove the .dfe that was left behind.
6568
 
      if ((sql_command == SQLCOM_ALTER_TABLE
6569
 
       || sql_command == SQLCOM_CREATE_INDEX
6570
 
       || sql_command == SQLCOM_DROP_INDEX))
6571
 
      {
6572
 
        string path(identifier.getPath());
6573
 
 
6574
 
        path.append(DEFAULT_FILE_EXTENSION);
6575
 
 
6576
 
        (void)internal::my_delete(path.c_str(), MYF(0));
6577
 
      }
6578
 
    }
6579
 
    else
6580
 
    {
6581
 
      string path(identifier.getPath());
6582
 
 
6583
 
      path.append(DEFAULT_FILE_EXTENSION);
6584
 
 
6585
 
      (void)internal::my_delete(path.c_str(), MYF(0));
6586
 
    }
6587
 
  }
 
6040
        if (error == 0 || error == ENOENT)
 
6041
        {
 
6042
          string path(identifier.getPath());
 
6043
 
 
6044
          path.append(DEFAULT_FILE_EXTENSION);
 
6045
 
 
6046
          (void)internal::my_delete(path.c_str(), MYF(0));
 
6047
        }
6588
6048
 
6589
6049
  return(error);
6590
6050
}
6594
6054
bool
6595
6055
InnobaseEngine::doDropSchema(
6596
6056
/*===================*/
6597
 
                             const SchemaIdentifier &identifier)
 
6057
                             SchemaIdentifier &identifier)
6598
6058
    /*!< in: database path; inside InnoDB the name
6599
6059
      of the last directory in the path is used as
6600
6060
      the database name: for example, in 'mysql/data/test'
6606
6066
  Session*  session   = current_session;
6607
6067
 
6608
6068
  /* Get the transaction associated with the current session, or create one
6609
 
    if not yet created */
 
6069
  if not yet created */
6610
6070
 
6611
6071
  assert(this == innodb_engine_ptr);
6612
6072
 
6615
6075
    trx_t*  parent_trx = check_trx_exists(session);
6616
6076
 
6617
6077
    /* In case Drizzle calls this in the middle of a SELECT
6618
 
      query, release possible adaptive hash latch to avoid
6619
 
      deadlocks of threads */
 
6078
    query, release possible adaptive hash latch to avoid
 
6079
    deadlocks of threads */
6620
6080
 
6621
6081
    trx_search_latch_release_if_reserved(parent_trx);
6622
6082
  }
6623
6083
 
6624
 
  schema_path.append("/");
 
6084
        schema_path.append("/");
6625
6085
  trx = innobase_trx_allocate(session);
6626
6086
  error = row_drop_database_for_mysql(schema_path.c_str(), trx);
6627
6087
 
6628
6088
  /* Flush the log to reduce probability that the .frm files and
6629
 
    the InnoDB data dictionary get out-of-sync if the user runs
6630
 
    with innodb_flush_log_at_trx_commit = 0 */
6631
 
 
6632
 
  log_buffer_flush_to_disk();
6633
 
 
6634
 
  /* Tell the InnoDB server that there might be work for
6635
 
    utility threads: */
6636
 
 
6637
 
  srv_active_wake_master_thread();
6638
 
 
6639
 
  innobase_commit_low(trx);
6640
 
  trx_free_for_mysql(trx);
6641
 
 
6642
 
  return false; // We are just a listener since we lack control over DDL, so we give no positive acknowledgement. 
6643
 
}
6644
 
 
6645
 
void InnobaseEngine::dropTemporarySchema()
6646
 
{
6647
 
  SchemaIdentifier schema_identifier(GLOBAL_TEMPORARY_EXT);
6648
 
  trx_t*  trx= NULL;
6649
 
  string schema_path(GLOBAL_TEMPORARY_EXT);
6650
 
 
6651
 
  schema_path.append("/");
6652
 
 
6653
 
  trx = trx_allocate_for_mysql();
6654
 
 
6655
 
  trx->mysql_thd = NULL;
6656
 
 
6657
 
  trx->check_foreigns = false;
6658
 
  trx->check_unique_secondary = false;
6659
 
 
6660
 
  (void)row_drop_database_for_mysql(schema_path.c_str(), trx);
6661
 
 
6662
 
  /* Flush the log to reduce probability that the .frm files and
6663
 
    the InnoDB data dictionary get out-of-sync if the user runs
6664
 
    with innodb_flush_log_at_trx_commit = 0 */
6665
 
 
6666
 
  log_buffer_flush_to_disk();
6667
 
 
6668
 
  /* Tell the InnoDB server that there might be work for
6669
 
    utility threads: */
6670
 
 
6671
 
  srv_active_wake_master_thread();
6672
 
 
6673
 
  innobase_commit_low(trx);
6674
 
  trx_free_for_mysql(trx);
 
6089
  the InnoDB data dictionary get out-of-sync if the user runs
 
6090
  with innodb_flush_log_at_trx_commit = 0 */
 
6091
 
 
6092
  log_buffer_flush_to_disk();
 
6093
 
 
6094
  /* Tell the InnoDB server that there might be work for
 
6095
  utility threads: */
 
6096
 
 
6097
  srv_active_wake_master_thread();
 
6098
 
 
6099
  innobase_commit_low(trx);
 
6100
  trx_free_for_mysql(trx);
 
6101
 
 
6102
        return false; // We are just a listener since we lack control over DDL, so we give no positive acknowledgement. 
6675
6103
}
6676
6104
/*********************************************************************//**
6677
6105
Renames an InnoDB table.
6687
6115
        /*!< in: TRUE=lock data dictionary and commit */
6688
6116
{
6689
6117
  int error;
6690
 
  char norm_to[FN_REFLEN];
6691
 
  char norm_from[FN_REFLEN];
 
6118
  char* norm_to;
 
6119
  char* norm_from;
6692
6120
 
6693
6121
  srv_lower_case_table_names = TRUE;
6694
6122
 
 
6123
  // Magic number 64 arbitrary
 
6124
  norm_to = (char*) malloc(strlen(to) + 64);
 
6125
  norm_from = (char*) malloc(strlen(from) + 64);
 
6126
 
6695
6127
  normalize_table_name(norm_to, to);
6696
6128
  normalize_table_name(norm_from, from);
6697
6129
 
6725
6157
    log_buffer_flush_to_disk();
6726
6158
  }
6727
6159
 
 
6160
  free(norm_to);
 
6161
  free(norm_from);
 
6162
 
6728
6163
  return error;
6729
6164
}
6730
6165
/*********************************************************************//**
6731
6166
Renames an InnoDB table.
6732
6167
@return 0 or error code */
6733
 
UNIV_INTERN int InnobaseEngine::doRenameTable(Session &session, const TableIdentifier &from, const TableIdentifier &to)
 
6168
UNIV_INTERN int InnobaseEngine::doRenameTable(Session &session, TableIdentifier &from, TableIdentifier &to)
6734
6169
{
6735
 
  // A temp table alter table/rename is a shallow rename and only the
6736
 
  // definition needs to be updated.
6737
 
  if (to.getType() == message::Table::TEMPORARY && from.getType() == message::Table::TEMPORARY)
6738
 
  {
6739
 
    session.getMessageCache().renameTableMessage(from, to);
6740
 
    return 0;
6741
 
  }
 
6170
        // A temp table alter table/rename is a shallow rename and only the
 
6171
        // definition needs to be updated.
 
6172
        if (to.getType() == message::Table::TEMPORARY && from.getType() == message::Table::TEMPORARY)
 
6173
        {
 
6174
          return plugin::StorageEngine::renameDefinitionFromPath(to, from);
 
6175
        }
6742
6176
 
6743
6177
  trx_t*  trx;
6744
6178
  int error;
6745
6179
  trx_t*  parent_trx;
6746
6180
 
6747
6181
  /* Get the transaction associated with the current session, or create one
6748
 
    if not yet created */
 
6182
  if not yet created */
6749
6183
 
6750
6184
  parent_trx = check_trx_exists(&session);
6751
6185
 
6752
6186
  /* In case MySQL calls this in the middle of a SELECT query, release
6753
 
    possible adaptive hash latch to avoid deadlocks of threads */
 
6187
  possible adaptive hash latch to avoid deadlocks of threads */
6754
6188
 
6755
6189
  trx_search_latch_release_if_reserved(parent_trx);
6756
6190
 
6758
6192
 
6759
6193
  error = innobase_rename_table(trx, from.getPath().c_str(), to.getPath().c_str(), TRUE);
6760
6194
 
6761
 
  session.setXaId(trx->id);
6762
 
 
6763
6195
  /* Tell the InnoDB server that there might be work for
6764
 
    utility threads: */
 
6196
  utility threads: */
6765
6197
 
6766
6198
  srv_active_wake_master_thread();
6767
6199
 
6768
6200
  innobase_commit_low(trx);
6769
6201
  trx_free_for_mysql(trx);
6770
6202
 
6771
 
  /* Add a special case to handle the Duplicated Key error
6772
 
     and return DB_ERROR instead.
6773
 
     This is to avoid a possible SIGSEGV error from mysql error
6774
 
     handling code. Currently, mysql handles the Duplicated Key
6775
 
     error by re-entering the storage layer and getting dup key
6776
 
     info by calling get_dup_key(). This operation requires a valid
6777
 
     table handle ('row_prebuilt_t' structure) which could no
6778
 
     longer be available in the error handling stage. The suggested
6779
 
     solution is to report a 'table exists' error message (since
6780
 
     the dup key error here is due to an existing table whose name
6781
 
     is the one we are trying to rename to) and return the generic
6782
 
     error code. */
6783
 
  if (error == (int) DB_DUPLICATE_KEY) {
6784
 
    my_error(ER_TABLE_EXISTS_ERROR, MYF(0), to.getPath().c_str());
6785
 
    error = DB_ERROR;
6786
 
  }
6787
 
 
6788
6203
  error = convert_error_code_to_mysql(error, 0, NULL);
6789
6204
 
6790
 
  if (not error)
6791
 
  {
6792
 
    // If this fails, we are in trouble
6793
 
    plugin::StorageEngine::renameDefinitionFromPath(to, from);
6794
 
  }
 
6205
        if (not error)
 
6206
        {
 
6207
          // If this fails, we are in trouble
 
6208
          plugin::StorageEngine::renameDefinitionFromPath(to, from);
 
6209
        }
6795
6210
 
6796
6211
  return(error);
6797
6212
}
6809
6224
  key_range   *max_key) /*!< in: range end key val, may
6810
6225
               also be 0 */
6811
6226
{
6812
 
  KeyInfo*    key;
 
6227
  KEY*    key;
6813
6228
  dict_index_t* index;
6814
6229
  unsigned char*    key_val_buff2 = (unsigned char*) malloc(
6815
 
              getTable()->getShare()->stored_rec_length
6816
 
          + getTable()->getShare()->max_key_length + 100);
6817
 
  ulint   buff2_len = getTable()->getShare()->stored_rec_length
6818
 
          + getTable()->getShare()->max_key_length + 100;
 
6230
              table->s->stored_rec_length
 
6231
          + table->s->max_key_length + 100);
 
6232
  ulint   buff2_len = table->s->stored_rec_length
 
6233
          + table->s->max_key_length + 100;
6819
6234
  dtuple_t* range_start;
6820
6235
  dtuple_t* range_end;
6821
6236
  ib_int64_t  n_rows;
6823
6238
  ulint   mode2;
6824
6239
  mem_heap_t* heap;
6825
6240
 
6826
 
  ut_a(prebuilt->trx == session_to_trx(getTable()->in_use));
 
6241
  ut_a(prebuilt->trx == session_to_trx(ha_session()));
6827
6242
 
6828
6243
  prebuilt->trx->op_info = (char*)"estimating records in index range";
6829
6244
 
6834
6249
 
6835
6250
  active_index = keynr;
6836
6251
 
6837
 
  key = &getTable()->key_info[active_index];
6838
 
 
6839
 
  index = innobase_get_index(keynr);
6840
 
 
6841
 
  /* There exists possibility of not being able to find requested
6842
 
     index due to inconsistency between MySQL and InoDB dictionary info.
6843
 
     Necessary message should have been printed in innobase_get_index() */
6844
 
  if (UNIV_UNLIKELY(!index)) {
6845
 
    n_rows = HA_POS_ERROR;
6846
 
    goto func_exit;
6847
 
  }
6848
 
 
6849
 
  if (UNIV_UNLIKELY(!row_merge_is_index_usable(prebuilt->trx, index))) {
6850
 
    n_rows = HA_ERR_TABLE_DEF_CHANGED;
6851
 
    goto func_exit;
6852
 
  }
 
6252
  key = table->key_info + active_index;
 
6253
 
 
6254
  index = dict_table_get_index_on_name(prebuilt->table, key->name);
 
6255
 
 
6256
  /* MySQL knows about this index and so we must be able to find it.*/
 
6257
  ut_a(index);
6853
6258
 
6854
6259
  heap = mem_heap_create(2 * (key->key_parts * sizeof(dfield_t)
6855
6260
            + sizeof(dtuple_t)));
6861
6266
  dict_index_copy_types(range_end, index, key->key_parts);
6862
6267
 
6863
6268
  row_sel_convert_mysql_key_to_innobase(
6864
 
        range_start, (byte*) &key_val_buff[0],
 
6269
        range_start, (byte*) key_val_buff,
6865
6270
        (ulint)upd_and_key_val_buff_len,
6866
6271
        index,
6867
6272
        (byte*) (min_key ? min_key->key :
6894
6299
 
6895
6300
  mem_heap_free(heap);
6896
6301
 
6897
 
func_exit:
6898
6302
  free(key_val_buff2);
6899
6303
 
6900
6304
  prebuilt->trx->op_info = (char*)"";
6929
6333
  external_lock(). To be safe, update the session of the current table
6930
6334
  handle. */
6931
6335
 
6932
 
  update_session(getTable()->in_use);
 
6336
  update_session(ha_session());
6933
6337
 
6934
6338
  prebuilt->trx->op_info = (char*)
6935
6339
         "calculating upper bound for table rows";
6993
6397
  ha_rows total_rows;
6994
6398
  double  time_for_scan;
6995
6399
 
6996
 
  if (index != getTable()->getShare()->getPrimaryKey()) {
 
6400
  if (index != table->s->primary_key) {
6997
6401
    /* Not clustered */
6998
6402
    return(Cursor::read_time(index, ranges, rows));
6999
6403
  }
7017
6421
}
7018
6422
 
7019
6423
/*********************************************************************//**
7020
 
Calculates the key number used inside MySQL for an Innobase index. We will
7021
 
first check the "index translation table" for a match of the index to get
7022
 
the index number. If there does not exist an "index translation table",
7023
 
or not able to find the index in the translation table, then we will fall back
7024
 
to the traditional way of looping through dict_index_t list to find a
7025
 
match. In this case, we have to take into account if we generated a
7026
 
default clustered index for the table
7027
 
@return the key number used inside MySQL */
7028
 
static
7029
 
unsigned int
7030
 
innobase_get_mysql_key_number_for_index(
7031
 
/*====================================*/
7032
 
        INNOBASE_SHARE*         share,  /*!< in: share structure for index
7033
 
                                        translation table. */
7034
 
        const drizzled::Table*  table,  /*!< in: table in MySQL data
7035
 
                                        dictionary */
7036
 
        dict_table_t*           ib_table,/*!< in: table in Innodb data
7037
 
                                        dictionary */
7038
 
        const dict_index_t*     index)  /*!< in: index */
7039
 
{
7040
 
        const dict_index_t*     ind;
7041
 
        unsigned int            i;
7042
 
 
7043
 
        ut_ad(index);
7044
 
        ut_ad(ib_table);
7045
 
        ut_ad(table);
7046
 
        ut_ad(share);
7047
 
 
7048
 
        /* If index does not belong to the table of share structure. Search
7049
 
        index->table instead */
7050
 
        if (index->table != ib_table) {
7051
 
                i = 0;
7052
 
                ind = dict_table_get_first_index(index->table);
7053
 
 
7054
 
                while (index != ind) {
7055
 
                        ind = dict_table_get_next_index(ind);
7056
 
                        i++;
7057
 
                }
7058
 
 
7059
 
                if (row_table_got_default_clust_index(index->table)) {
7060
 
                        ut_a(i > 0);
7061
 
                        i--;
7062
 
                }
7063
 
 
7064
 
                return(i);
7065
 
        }
7066
 
 
7067
 
        /* If index does not belong to the table of share structure. Search
7068
 
        index->table instead */
7069
 
        if (index->table != ib_table) {
7070
 
                i = 0;
7071
 
                ind = dict_table_get_first_index(index->table);
7072
 
 
7073
 
                while (index != ind) {
7074
 
                        ind = dict_table_get_next_index(ind);
7075
 
                        i++;
7076
 
                }
7077
 
 
7078
 
                if (row_table_got_default_clust_index(index->table)) {
7079
 
                        ut_a(i > 0);
7080
 
                        i--;
7081
 
                }
7082
 
 
7083
 
                return(i);
7084
 
        }
7085
 
 
7086
 
        /* If index translation table exists, we will first check
7087
 
        the index through index translation table for a match. */
7088
 
        if (share->idx_trans_tbl.index_mapping) {
7089
 
                for (i = 0; i < share->idx_trans_tbl.index_count; i++) {
7090
 
                        if (share->idx_trans_tbl.index_mapping[i] == index) {
7091
 
                                return(i);
7092
 
                        }
7093
 
                }
7094
 
 
7095
 
                /* Print an error message if we cannot find the index
7096
 
                ** in the "index translation table". */
7097
 
                errmsg_printf(ERRMSG_LVL_ERROR,
7098
 
                              "Cannot find index %s in InnoDB index "
7099
 
                                "translation table.", index->name);
7100
 
        }
7101
 
 
7102
 
        /* If we do not have an "index translation table", or not able
7103
 
        to find the index in the translation table, we'll directly find
7104
 
        matching index in the dict_index_t list */
7105
 
        for (i = 0; i < table->getShare()->keys; i++) {
7106
 
                ind = dict_table_get_index_on_name(
7107
 
                        ib_table, table->key_info[i].name);
7108
 
 
7109
 
                if (index == ind) {
7110
 
                        return(i);
7111
 
                }
7112
 
        }
7113
 
 
7114
 
                errmsg_printf(ERRMSG_LVL_ERROR,
7115
 
                              "Cannot find matching index number for index %s "
7116
 
                              "in InnoDB index list.", index->name);
7117
 
 
7118
 
        return(0);
7119
 
}
7120
 
/*********************************************************************//**
7121
6424
Returns statistics information of the table to the MySQL interpreter,
7122
6425
in various fields of the handle object. */
7123
6426
UNIV_INTERN
7130
6433
  dict_index_t* index;
7131
6434
  ha_rows   rec_per_key;
7132
6435
  ib_int64_t  n_rows;
 
6436
  ulong   j;
 
6437
  ulong   i;
 
6438
  char    path[FN_REFLEN];
7133
6439
  os_file_stat_t  stat_info;
7134
6440
 
7135
6441
  /* If we are forcing recovery at a high level, we will suppress
7136
6442
  statistics calculation on tables, because that may crash the
7137
6443
  server if an index is badly corrupted. */
7138
6444
 
 
6445
  if (srv_force_recovery >= SRV_FORCE_NO_IBUF_MERGE) {
 
6446
 
 
6447
    /* We return success (0) instead of HA_ERR_CRASHED,
 
6448
    because we want MySQL to process this query and not
 
6449
    stop, like it would do if it received the error code
 
6450
    HA_ERR_CRASHED. */
 
6451
 
 
6452
    return(0);
 
6453
  }
 
6454
 
7139
6455
  /* We do not know if MySQL can call this function before calling
7140
6456
  external_lock(). To be safe, update the session of the current table
7141
6457
  handle. */
7142
6458
 
7143
 
  update_session(getTable()->in_use);
 
6459
  update_session(ha_session());
7144
6460
 
7145
6461
  /* In case MySQL calls this in the middle of a SELECT query, release
7146
6462
  possible adaptive hash latch to avoid deadlocks of threads */
7152
6468
  ib_table = prebuilt->table;
7153
6469
 
7154
6470
  if (flag & HA_STATUS_TIME) {
7155
 
    /* In Analyze we call with this flag: update
7156
 
       then statistics so that they are up-to-date */
7157
 
 
7158
 
    prebuilt->trx->op_info = "updating table statistics";
7159
 
 
7160
 
    dict_update_statistics(ib_table);
7161
 
 
7162
 
    prebuilt->trx->op_info = "returning various info to MySQL";
7163
 
 
7164
 
    fs::path get_status_path(getDataHomeCatalog());
7165
 
    get_status_path /= ib_table->name;
7166
 
    fs::change_extension(get_status_path, "dfe");
 
6471
    if (innobase_stats_on_metadata) {
 
6472
      /* In sql_show we call with this flag: update
 
6473
      then statistics so that they are up-to-date */
 
6474
 
 
6475
      prebuilt->trx->op_info = "updating table statistics";
 
6476
 
 
6477
      dict_update_statistics(ib_table);
 
6478
 
 
6479
      prebuilt->trx->op_info = "returning various info to MySQL";
 
6480
    }
 
6481
 
 
6482
    snprintf(path, sizeof(path), "%s/%s%s",
 
6483
             data_home, ib_table->name, ".dfe");
 
6484
 
 
6485
    internal::unpack_filename(path,path);
7167
6486
 
7168
6487
    /* Note that we do not know the access time of the table,
7169
6488
    nor the CHECK TABLE time, nor the UPDATE or INSERT time. */
7170
6489
 
7171
 
    if (os_file_get_status(get_status_path.file_string().c_str(), &stat_info)) {
 
6490
    if (os_file_get_status(path,&stat_info)) {
7172
6491
      stats.create_time = (ulong) stat_info.ctime;
7173
6492
    }
7174
6493
  }
7227
6546
    acquiring latches inside InnoDB, we do not call it if we
7228
6547
    are asked by MySQL to avoid locking. Another reason to
7229
6548
    avoid the call is that it uses quite a lot of CPU.
7230
 
    See Bug#38185. */
7231
 
    if (flag & HA_STATUS_NO_LOCK) {
7232
 
      /* We do not update delete_length if no
7233
 
         locking is requested so the "old" value can
7234
 
         remain. delete_length is initialized to 0 in
7235
 
         the ha_statistics' constructor. */
7236
 
    } else if (UNIV_UNLIKELY
7237
 
               (srv_force_recovery >= SRV_FORCE_NO_IBUF_MERGE)) {
7238
 
      /* Avoid accessing the tablespace if
7239
 
         innodb_crash_recovery is set to a high value. */
7240
 
      stats.delete_length = 0;
7241
 
    } else {
 
6549
    See Bug#38185.
 
6550
    We do not update delete_length if no locking is requested
 
6551
    so the "old" value can remain. delete_length is initialized
 
6552
    to 0 in the ha_statistics' constructor. */
 
6553
    if (!(flag & HA_STATUS_NO_LOCK)) {
 
6554
 
7242
6555
      /* lock the data dictionary to avoid races with
7243
6556
      ibd_file_missing and tablespace_discarded */
7244
6557
      row_mysql_lock_data_dictionary(prebuilt->trx);
7254
6567
 
7255
6568
        Session*  session;
7256
6569
 
7257
 
        session= getTable()->in_use;
7258
 
        assert(session);
 
6570
        session = ha_session();
7259
6571
 
7260
6572
        push_warning_printf(
7261
6573
          session,
7284
6596
  }
7285
6597
 
7286
6598
  if (flag & HA_STATUS_CONST) {
7287
 
    ulong i;
7288
 
    /* Verify the number of index in InnoDB and MySQL
7289
 
       matches up. If prebuilt->clust_index_was_generated
7290
 
       holds, InnoDB defines GEN_CLUST_INDEX internally */
7291
 
    ulint       num_innodb_index = UT_LIST_GET_LEN(ib_table->indexes) - prebuilt->clust_index_was_generated;
 
6599
    index = dict_table_get_first_index(ib_table);
7292
6600
 
7293
 
    if (getTable()->getShare()->keys != num_innodb_index) {
7294
 
      errmsg_printf(ERRMSG_LVL_ERROR, "Table %s contains %lu "
7295
 
                      "indexes inside InnoDB, which "
7296
 
                      "is different from the number of "
7297
 
                      "indexes %u defined in the MySQL ",
7298
 
                      ib_table->name, num_innodb_index,
7299
 
                      getTable()->getShare()->keys);
 
6601
    if (prebuilt->clust_index_was_generated) {
 
6602
      index = dict_table_get_next_index(index);
7300
6603
    }
7301
6604
 
7302
 
    for (i = 0; i < getTable()->getShare()->sizeKeys(); i++) {
7303
 
      ulong j;
7304
 
      /* We could get index quickly through internal
7305
 
         index mapping with the index translation table.
7306
 
         The identity of index (match up index name with
7307
 
         that of table->key_info[i]) is already verified in
7308
 
         innobase_get_index().  */
7309
 
      index = innobase_get_index(i);
7310
 
 
 
6605
    for (i = 0; i < table->s->keys; i++) {
7311
6606
      if (index == NULL) {
7312
6607
        errmsg_printf(ERRMSG_LVL_ERROR, "Table %s contains fewer "
7313
6608
            "indexes inside InnoDB than "
7321
6616
        break;
7322
6617
      }
7323
6618
 
7324
 
      for (j = 0; j < getTable()->key_info[i].key_parts; j++) {
 
6619
      for (j = 0; j < table->key_info[i].key_parts; j++) {
7325
6620
 
7326
6621
        if (j + 1 > index->n_uniq) {
7327
6622
          errmsg_printf(ERRMSG_LVL_ERROR, 
7336
6631
          break;
7337
6632
        }
7338
6633
 
7339
 
        dict_index_stat_mutex_enter(index);
7340
 
 
7341
6634
        if (index->stat_n_diff_key_vals[j + 1] == 0) {
7342
6635
 
7343
6636
          rec_per_key = stats.records;
7346
6639
           index->stat_n_diff_key_vals[j + 1]);
7347
6640
        }
7348
6641
 
7349
 
        dict_index_stat_mutex_exit(index);
7350
 
 
7351
6642
        /* Since MySQL seems to favor table scans
7352
6643
        too much over index searches, we pretend
7353
6644
        index selectivity is 2 times better than
7359
6650
          rec_per_key = 1;
7360
6651
        }
7361
6652
 
7362
 
        getTable()->key_info[i].rec_per_key[j]=
 
6653
        table->key_info[i].rec_per_key[j]=
7363
6654
          rec_per_key >= ~(ulong) 0 ? ~(ulong) 0 :
7364
6655
          (ulong) rec_per_key;
7365
6656
      }
 
6657
 
 
6658
      index = dict_table_get_next_index(index);
7366
6659
    }
7367
6660
  }
7368
6661
 
7369
 
  if (srv_force_recovery >= SRV_FORCE_NO_IBUF_MERGE) {
7370
 
    goto func_exit;
7371
 
  }
7372
 
 
7373
6662
  if (flag & HA_STATUS_ERRKEY) {
7374
6663
    const dict_index_t* err_index;
7375
6664
 
7380
6669
 
7381
6670
    if (err_index) {
7382
6671
      errkey = (unsigned int)
7383
 
        innobase_get_mysql_key_number_for_index(share, getTable(), ib_table,
7384
 
                                                err_index);
 
6672
        row_get_mysql_key_number_for_index(err_index);
7385
6673
    } else {
7386
6674
      errkey = (unsigned int) prebuilt->trx->error_key_num;
7387
6675
    }
7388
6676
  }
7389
6677
 
7390
 
  if ((flag & HA_STATUS_AUTO) && getTable()->found_next_number_field) {
 
6678
  if ((flag & HA_STATUS_AUTO) && table->found_next_number_field) {
7391
6679
    stats.auto_increment_value = innobase_peek_autoinc();
7392
6680
  }
7393
6681
 
7394
 
func_exit:
7395
6682
  prebuilt->trx->op_info = (char*)"";
7396
6683
 
7397
6684
  return(0);
7424
6711
/*===============*/
7425
6712
  Session*  session)  /*!< in: user thread handle */
7426
6713
{
7427
 
  dict_index_t* index;
7428
 
  ulint         n_rows;
7429
 
  ulint         n_rows_in_table = ULINT_UNDEFINED;
7430
 
  ibool         is_ok           = TRUE;
7431
 
  ulint         old_isolation_level;
 
6714
  ulint   ret;
7432
6715
 
7433
 
  assert(session == getTable()->in_use);
 
6716
  assert(session == ha_session());
7434
6717
  ut_a(prebuilt->trx);
7435
6718
  ut_a(prebuilt->trx->magic_n == TRX_MAGIC_N);
7436
6719
  ut_a(prebuilt->trx == session_to_trx(session));
7439
6722
    /* Build the template; we will use a dummy template
7440
6723
    in index scans done in checking */
7441
6724
 
7442
 
    build_template(prebuilt, NULL, getTable(), ROW_MYSQL_WHOLE_ROW);
7443
 
  }
7444
 
 
7445
 
  if (prebuilt->table->ibd_file_missing) {
7446
 
        errmsg_printf(ERRMSG_LVL_ERROR, "InnoDB: Error:\n"
7447
 
                    "InnoDB: MySQL is trying to use a table handle"
7448
 
                    " but the .ibd file for\n"
7449
 
                    "InnoDB: table %s does not exist.\n"
7450
 
                    "InnoDB: Have you deleted the .ibd file"
7451
 
                    " from the database directory under\n"
7452
 
                    "InnoDB: the MySQL datadir, or have you"
7453
 
                    " used DISCARD TABLESPACE?\n"
7454
 
                    "InnoDB: Please refer to\n"
7455
 
                    "InnoDB: " REFMAN "innodb-troubleshooting.html\n"
7456
 
                    "InnoDB: how you can resolve the problem.\n",
7457
 
                    prebuilt->table->name);
7458
 
    return(HA_ADMIN_CORRUPT);
7459
 
  }
7460
 
 
7461
 
  prebuilt->trx->op_info = "checking table";
7462
 
 
7463
 
  old_isolation_level = prebuilt->trx->isolation_level;
7464
 
 
7465
 
  /* We must run the index record counts at an isolation level
7466
 
     >= READ COMMITTED, because a dirty read can see a wrong number
7467
 
     of records in some index; to play safe, we use always
7468
 
     REPEATABLE READ here */
7469
 
 
7470
 
  prebuilt->trx->isolation_level = TRX_ISO_REPEATABLE_READ;
7471
 
 
7472
 
  /* Enlarge the fatal lock wait timeout during CHECK TABLE. */
7473
 
  mutex_enter(&kernel_mutex);
7474
 
  srv_fatal_semaphore_wait_threshold += 7200; /* 2 hours */
7475
 
  mutex_exit(&kernel_mutex);
7476
 
 
7477
 
  for (index = dict_table_get_first_index(prebuilt->table);
7478
 
       index != NULL;
7479
 
       index = dict_table_get_next_index(index)) {
7480
 
#if 0
7481
 
    fputs("Validating index ", stderr);
7482
 
    ut_print_name(stderr, trx, FALSE, index->name);
7483
 
    putc('\n', stderr);
7484
 
#endif
7485
 
 
7486
 
    if (!btr_validate_index(index, prebuilt->trx)) {
7487
 
      is_ok = FALSE;
7488
 
      push_warning_printf(session, DRIZZLE_ERROR::WARN_LEVEL_WARN,
7489
 
                          ER_NOT_KEYFILE,
7490
 
                          "InnoDB: The B-tree of"
7491
 
                          " index '%-.200s' is corrupted.",
7492
 
                          index->name);
7493
 
      continue;
7494
 
    }
7495
 
 
7496
 
    /* Instead of invoking change_active_index(), set up
7497
 
       a dummy template for non-locking reads, disabling
7498
 
       access to the clustered index. */
7499
 
    prebuilt->index = index;
7500
 
 
7501
 
    prebuilt->index_usable = row_merge_is_index_usable(
7502
 
                        prebuilt->trx, prebuilt->index);
7503
 
 
7504
 
    if (UNIV_UNLIKELY(!prebuilt->index_usable)) {
7505
 
      push_warning_printf(session, DRIZZLE_ERROR::WARN_LEVEL_WARN,
7506
 
                          HA_ERR_TABLE_DEF_CHANGED,
7507
 
                          "InnoDB: Insufficient history for"
7508
 
                          " index '%-.200s'",
7509
 
                          index->name);
7510
 
      continue;
7511
 
    }
7512
 
 
7513
 
    prebuilt->sql_stat_start = TRUE;
7514
 
    prebuilt->template_type = ROW_MYSQL_DUMMY_TEMPLATE;
7515
 
    prebuilt->n_template = 0;
7516
 
    prebuilt->need_to_access_clustered = FALSE;
7517
 
 
7518
 
    dtuple_set_n_fields(prebuilt->search_tuple, 0);
7519
 
 
7520
 
    prebuilt->select_lock_type = LOCK_NONE;
7521
 
 
7522
 
    if (!row_check_index_for_mysql(prebuilt, index, &n_rows)) {
7523
 
      push_warning_printf(session, DRIZZLE_ERROR::WARN_LEVEL_WARN,
7524
 
                          ER_NOT_KEYFILE,
7525
 
                          "InnoDB: The B-tree of"
7526
 
                          " index '%-.200s' is corrupted.",
7527
 
                          index->name);
7528
 
      is_ok = FALSE;
7529
 
    }
7530
 
 
7531
 
    if (user_session->getKilled()) {
7532
 
      break;
7533
 
    }
7534
 
 
7535
 
#if 0
7536
 
    fprintf(stderr, "%lu entries in index %s\n", n_rows,
7537
 
            index->name);
7538
 
#endif
7539
 
 
7540
 
    if (index == dict_table_get_first_index(prebuilt->table)) {
7541
 
      n_rows_in_table = n_rows;
7542
 
    } else if (n_rows != n_rows_in_table) {
7543
 
      push_warning_printf(session, DRIZZLE_ERROR::WARN_LEVEL_WARN,
7544
 
                          ER_NOT_KEYFILE,
7545
 
                          "InnoDB: Index '%-.200s'"
7546
 
                          " contains %lu entries,"
7547
 
                          " should be %lu.",
7548
 
                          index->name,
7549
 
                          (ulong) n_rows,
7550
 
                          (ulong) n_rows_in_table);
7551
 
      is_ok = FALSE;
7552
 
    }
7553
 
  }
7554
 
 
7555
 
  /* Restore the original isolation level */
7556
 
  prebuilt->trx->isolation_level = old_isolation_level;
7557
 
 
7558
 
  /* We validate also the whole adaptive hash index for all tables
7559
 
     at every CHECK TABLE */
7560
 
 
7561
 
  if (!btr_search_validate()) {
7562
 
    push_warning(session, DRIZZLE_ERROR::WARN_LEVEL_WARN,
7563
 
                 ER_NOT_KEYFILE,
7564
 
                 "InnoDB: The adaptive hash index is corrupted.");
7565
 
    is_ok = FALSE;
7566
 
  }
7567
 
 
7568
 
  /* Restore the fatal lock wait timeout after CHECK TABLE. */
7569
 
  mutex_enter(&kernel_mutex);
7570
 
  srv_fatal_semaphore_wait_threshold -= 7200; /* 2 hours */
7571
 
  mutex_exit(&kernel_mutex);
7572
 
 
7573
 
  prebuilt->trx->op_info = "";
7574
 
  if (user_session->getKilled()) {
7575
 
    my_error(ER_QUERY_INTERRUPTED, MYF(0));
7576
 
  }
7577
 
 
7578
 
  return(is_ok ? HA_ADMIN_OK : HA_ADMIN_CORRUPT);
 
6725
    build_template(prebuilt, NULL, table, ROW_MYSQL_WHOLE_ROW);
 
6726
  }
 
6727
 
 
6728
  ret = row_check_table_for_mysql(prebuilt);
 
6729
 
 
6730
  if (ret == DB_SUCCESS) {
 
6731
    return(HA_ADMIN_OK);
 
6732
  }
 
6733
 
 
6734
  return(HA_ADMIN_CORRUPT);
7579
6735
}
7580
6736
 
7581
6737
/*************************************************************//**
7601
6757
    return((char*)comment); /* string too long */
7602
6758
  }
7603
6759
 
7604
 
  update_session(getTable()->in_use);
 
6760
  update_session(ha_session());
7605
6761
 
7606
6762
  prebuilt->trx->op_info = (char*)"returning table comment";
7607
6763
 
7672
6828
  external_lock(). To be safe, update the session of the current table
7673
6829
  handle. */
7674
6830
 
7675
 
  update_session(getTable()->in_use);
 
6831
  update_session(ha_session());
7676
6832
 
7677
6833
  prebuilt->trx->op_info = (char*)"getting info on foreign keys";
7678
6834
 
7721
6877
  dict_foreign_t* foreign;
7722
6878
 
7723
6879
  ut_a(prebuilt != NULL);
7724
 
  update_session(getTable()->in_use);
 
6880
  update_session(ha_session());
7725
6881
  prebuilt->trx->op_info = (char*)"getting list of foreign keys";
7726
6882
  trx_search_latch_release_if_reserved(prebuilt->trx);
7727
6883
  mutex_enter(&(dict_sys->mutex));
7731
6887
 
7732
6888
    uint i;
7733
6889
    LEX_STRING *name = 0;
7734
 
    uint ulen;
7735
 
    char uname[NAME_LEN + 1];           /* Unencoded name */
7736
 
    char db_name[NAME_LEN + 1];
 
6890
      uint ulen;
 
6891
      char uname[NAME_LEN + 1];           /* Unencoded name */
 
6892
      char db_name[NAME_LEN + 1];
7737
6893
    const char *tmp_buff;
7738
6894
 
7739
6895
    /** Foreign id **/
7744
6900
    tmp_buff += i + 1;
7745
6901
    LEX_STRING *tmp_foreign_id = session->make_lex_string(NULL, tmp_buff, strlen(tmp_buff), true);
7746
6902
 
7747
 
    /* Database name */
 
6903
      /* Database name */
7748
6904
    tmp_buff = foreign->referenced_table_name;
7749
6905
 
7750
6906
    i= 0;
7751
6907
    while (tmp_buff[i] != '/')
7752
 
    {
7753
 
      db_name[i]= tmp_buff[i];
7754
 
      i++;
7755
 
    }
7756
 
    db_name[i] = 0;
7757
 
    ulen= TableIdentifier::filename_to_tablename(db_name, uname, sizeof(uname));
 
6908
      {
 
6909
        db_name[i]= tmp_buff[i];
 
6910
        i++;
 
6911
      }
 
6912
      db_name[i] = 0;
 
6913
      ulen= filename_to_tablename(db_name, uname, sizeof(uname));
7758
6914
    LEX_STRING *tmp_referenced_db = session->make_lex_string(NULL, uname, ulen, true);
7759
6915
 
7760
 
    /* Table name */
 
6916
      /* Table name */
7761
6917
    tmp_buff += i + 1;
7762
 
    ulen= TableIdentifier::filename_to_tablename(tmp_buff, uname, sizeof(uname));
 
6918
      ulen= filename_to_tablename(tmp_buff, uname, sizeof(uname));
7763
6919
    LEX_STRING *tmp_referenced_table = session->make_lex_string(NULL, uname, ulen, true);
7764
6920
 
7765
 
    /** Foreign Fields **/
7766
 
    List<LEX_STRING> tmp_foreign_fields;
7767
 
    List<LEX_STRING> tmp_referenced_fields;
 
6921
      /** Foreign Fields **/
 
6922
  List<LEX_STRING> tmp_foreign_fields;
 
6923
  List<LEX_STRING> tmp_referenced_fields;
7768
6924
    for (i= 0;;) {
7769
6925
      tmp_buff= foreign->foreign_col_names[i];
7770
6926
      name = session->make_lex_string(name, tmp_buff, strlen(tmp_buff), true);
7776
6932
        break;
7777
6933
    }
7778
6934
 
7779
 
    ulong length;
7780
 
    if (foreign->type & DICT_FOREIGN_ON_DELETE_CASCADE)
7781
 
    {
7782
 
      length=7;
7783
 
      tmp_buff= "CASCADE";
7784
 
    }
7785
 
    else if (foreign->type & DICT_FOREIGN_ON_DELETE_SET_NULL)
7786
 
    {
7787
 
      length=8;
7788
 
      tmp_buff= "SET NULL";
7789
 
    }
7790
 
    else if (foreign->type & DICT_FOREIGN_ON_DELETE_NO_ACTION)
7791
 
    {
7792
 
      length=9;
7793
 
      tmp_buff= "NO ACTION";
7794
 
    }
7795
 
    else
7796
 
    {
7797
 
      length=8;
7798
 
      tmp_buff= "RESTRICT";
7799
 
    }
 
6935
          ulong length;
 
6936
          if (foreign->type & DICT_FOREIGN_ON_DELETE_CASCADE)
 
6937
          {
 
6938
            length=7;
 
6939
            tmp_buff= "CASCADE";
 
6940
          }
 
6941
          else if (foreign->type & DICT_FOREIGN_ON_DELETE_SET_NULL)
 
6942
          {
 
6943
            length=8;
 
6944
            tmp_buff= "SET NULL";
 
6945
          }
 
6946
          else if (foreign->type & DICT_FOREIGN_ON_DELETE_NO_ACTION)
 
6947
          {
 
6948
            length=9;
 
6949
            tmp_buff= "NO ACTION";
 
6950
          }
 
6951
          else
 
6952
          {
 
6953
            length=8;
 
6954
            tmp_buff= "RESTRICT";
 
6955
          }
7800
6956
    LEX_STRING *tmp_delete_method = session->make_lex_string(NULL, tmp_buff, length, true);
7801
 
 
7802
 
 
7803
 
    if (foreign->type & DICT_FOREIGN_ON_UPDATE_CASCADE)
7804
 
    {
7805
 
      length=7;
7806
 
      tmp_buff= "CASCADE";
7807
 
    }
7808
 
    else if (foreign->type & DICT_FOREIGN_ON_UPDATE_SET_NULL)
7809
 
    {
7810
 
      length=8;
7811
 
      tmp_buff= "SET NULL";
7812
 
    }
7813
 
    else if (foreign->type & DICT_FOREIGN_ON_UPDATE_NO_ACTION)
7814
 
    {
7815
 
      length=9;
7816
 
      tmp_buff= "NO ACTION";
7817
 
    }
7818
 
    else
7819
 
    {
7820
 
      length=8;
7821
 
      tmp_buff= "RESTRICT";
7822
 
    }
 
6957
 
 
6958
 
 
6959
          if (foreign->type & DICT_FOREIGN_ON_UPDATE_CASCADE)
 
6960
          {
 
6961
            length=7;
 
6962
            tmp_buff= "CASCADE";
 
6963
          }
 
6964
          else if (foreign->type & DICT_FOREIGN_ON_UPDATE_SET_NULL)
 
6965
          {
 
6966
            length=8;
 
6967
            tmp_buff= "SET NULL";
 
6968
          }
 
6969
          else if (foreign->type & DICT_FOREIGN_ON_UPDATE_NO_ACTION)
 
6970
          {
 
6971
            length=9;
 
6972
            tmp_buff= "NO ACTION";
 
6973
          }
 
6974
          else
 
6975
          {
 
6976
            length=8;
 
6977
            tmp_buff= "RESTRICT";
 
6978
          }
7823
6979
    LEX_STRING *tmp_update_method = session->make_lex_string(NULL, tmp_buff, length, true);
7824
6980
 
7825
6981
    LEX_STRING *tmp_referenced_key_name = NULL;
7826
6982
 
7827
 
    if (foreign->referenced_index &&
7828
 
        foreign->referenced_index->name)
7829
 
    {
7830
 
      tmp_referenced_key_name = session->make_lex_string(NULL,
7831
 
                                                         foreign->referenced_index->name, strlen(foreign->referenced_index->name), true);
7832
 
    }
 
6983
          if (foreign->referenced_index &&
 
6984
              foreign->referenced_index->name)
 
6985
          {
 
6986
        tmp_referenced_key_name = session->make_lex_string(NULL,
 
6987
        foreign->referenced_index->name, strlen(foreign->referenced_index->name), true);
 
6988
          }
7833
6989
 
7834
 
    ForeignKeyInfo f_key_info(
7835
 
                              tmp_foreign_id, tmp_referenced_db, tmp_referenced_table,
7836
 
                              tmp_update_method, tmp_delete_method, tmp_referenced_key_name,
7837
 
                              tmp_foreign_fields, tmp_referenced_fields);
 
6990
      ForeignKeyInfo f_key_info(
 
6991
        tmp_foreign_id, tmp_referenced_db, tmp_referenced_table,
 
6992
        tmp_update_method, tmp_delete_method, tmp_referenced_key_name,
 
6993
        tmp_foreign_fields, tmp_referenced_fields);
7838
6994
 
7839
6995
    ForeignKeyInfo *pf_key_info = (ForeignKeyInfo *)
7840
6996
      session->memdup(&f_key_info, sizeof(ForeignKeyInfo));
7859
7015
{
7860
7016
  bool  can_switch;
7861
7017
 
7862
 
  ut_a(prebuilt->trx == session_to_trx(getTable()->in_use));
 
7018
  ut_a(prebuilt->trx == session_to_trx(ha_session()));
7863
7019
 
7864
7020
  prebuilt->trx->op_info =
7865
7021
      "determining if there are foreign key constraints";
7947
7103
      either, because the calling threads may change.
7948
7104
      CAREFUL HERE, OR MEMORY CORRUPTION MAY OCCUR! */
7949
7105
    case HA_EXTRA_IGNORE_DUP_KEY:
7950
 
      session_to_trx(getTable()->in_use)->duplicates |= TRX_DUP_IGNORE;
 
7106
      session_to_trx(ha_session())->duplicates |= TRX_DUP_IGNORE;
7951
7107
      break;
7952
7108
    case HA_EXTRA_WRITE_CAN_REPLACE:
7953
 
      session_to_trx(getTable()->in_use)->duplicates |= TRX_DUP_REPLACE;
 
7109
      session_to_trx(ha_session())->duplicates |= TRX_DUP_REPLACE;
7954
7110
      break;
7955
7111
    case HA_EXTRA_WRITE_CANNOT_REPLACE:
7956
 
      session_to_trx(getTable()->in_use)->duplicates &= ~TRX_DUP_REPLACE;
 
7112
      session_to_trx(ha_session())->duplicates &= ~TRX_DUP_REPLACE;
7957
7113
      break;
7958
7114
    case HA_EXTRA_NO_IGNORE_DUP_KEY:
7959
 
      session_to_trx(getTable()->in_use)->duplicates &=
 
7115
      session_to_trx(ha_session())->duplicates &=
7960
7116
        ~(TRX_DUP_IGNORE | TRX_DUP_REPLACE);
7961
7117
      break;
7962
7118
    default:/* Do nothing */
8092
7248
{
8093
7249
  trx_t*      trx;
8094
7250
  static const char truncated_msg[] = "... truncated...\n";
8095
 
  const long    MAX_STATUS_SIZE = 1048576;
 
7251
  const long    MAX_STATUS_SIZE = 64000;
8096
7252
  ulint     trx_list_start = ULINT_UNDEFINED;
8097
7253
  ulint     trx_list_end = ULINT_UNDEFINED;
8098
7254
 
8110
7266
 
8111
7267
  mutex_enter(&srv_monitor_file_mutex);
8112
7268
  rewind(srv_monitor_file);
8113
 
  srv_printf_innodb_monitor(srv_monitor_file, FALSE,
 
7269
  srv_printf_innodb_monitor(srv_monitor_file,
8114
7270
        &trx_list_start, &trx_list_end);
8115
7271
  flen = ftell(srv_monitor_file);
8116
7272
  os_file_set_eof(srv_monitor_file);
8121
7277
 
8122
7278
  if (flen > MAX_STATUS_SIZE) {
8123
7279
    usable_len = MAX_STATUS_SIZE;
8124
 
    srv_truncated_status_writes++;
8125
7280
  } else {
8126
7281
    usable_len = flen;
8127
7282
  }
8157
7312
 
8158
7313
  mutex_exit(&srv_monitor_file_mutex);
8159
7314
 
8160
 
  stat_print(session, innobase_engine_name, strlen(innobase_engine_name),
8161
 
             STRING_WITH_LEN(""), str, flen);
 
7315
  bool result = FALSE;
8162
7316
 
 
7317
  if (stat_print(session, innobase_engine_name, strlen(innobase_engine_name),
 
7318
      STRING_WITH_LEN(""), str, flen)) {
 
7319
    result= TRUE;
 
7320
  }
8163
7321
  free(str);
8164
7322
 
8165
7323
  return(FALSE);
8166
7324
}
8167
7325
 
8168
7326
/************************************************************************//**
8169
 
Implements the SHOW MUTEX STATUS command.
8170
 
@return true on failure false on success*/
 
7327
Implements the SHOW MUTEX STATUS command. . */
8171
7328
static
8172
7329
bool
8173
7330
innodb_mutex_show_status(
8175
7332
  plugin::StorageEngine*  engine,   /*!< in: the innodb StorageEngine */
8176
7333
  Session*  session,  /*!< in: the MySQL query thread of the
8177
7334
          caller */
8178
 
  stat_print_fn*  stat_print)   /*!< in: function for printing
8179
 
                                        statistics */
 
7335
  stat_print_fn*  stat_print)
8180
7336
{
8181
7337
  char buf1[IO_SIZE], buf2[IO_SIZE];
8182
7338
  mutex_t*  mutex;
8183
7339
  rw_lock_t*  lock;
8184
 
  ulint         block_mutex_oswait_count = 0;
8185
 
  ulint         block_lock_oswait_count = 0;
8186
 
  mutex_t*      block_mutex = NULL;
8187
 
  rw_lock_t*    block_lock = NULL;
8188
7340
#ifdef UNIV_DEBUG
8189
7341
  ulint   rw_lock_count= 0;
8190
7342
  ulint   rw_lock_count_spin_loop= 0;
8198
7350
 
8199
7351
  mutex_enter(&mutex_list_mutex);
8200
7352
 
8201
 
  for (mutex = UT_LIST_GET_FIRST(mutex_list); mutex != NULL;
8202
 
       mutex = UT_LIST_GET_NEXT(list, mutex)) {
8203
 
    if (mutex->count_os_wait == 0) {
8204
 
      continue;
8205
 
    }
8206
 
 
8207
 
 
8208
 
    if (buf_pool_is_block_mutex(mutex)) {
8209
 
      block_mutex = mutex;
8210
 
      block_mutex_oswait_count += mutex->count_os_wait;
8211
 
      continue;
 
7353
  mutex = UT_LIST_GET_FIRST(mutex_list);
 
7354
 
 
7355
  while (mutex != NULL) {
 
7356
    if (mutex->count_os_wait == 0
 
7357
        || buf_pool_is_block_mutex(mutex)) {
 
7358
      goto next_mutex;
8212
7359
    }
8213
7360
#ifdef UNIV_DEBUG
8214
7361
    if (mutex->mutex_type != 1) {
8235
7382
          return(1);
8236
7383
        }
8237
7384
      }
8238
 
    } else {
 
7385
    }
 
7386
    else {
8239
7387
      rw_lock_count += mutex->count_using;
8240
7388
      rw_lock_count_spin_loop += mutex->count_spin_loop;
8241
7389
      rw_lock_count_spin_rounds += mutex->count_spin_rounds;
8247
7395
    buf1len= snprintf(buf1, sizeof(buf1), "%s:%lu",
8248
7396
          mutex->cfile_name, (ulong) mutex->cline);
8249
7397
    buf2len= snprintf(buf2, sizeof(buf2), "os_waits=%lu",
8250
 
                      (ulong) mutex->count_os_wait);
 
7398
          mutex->count_os_wait);
8251
7399
 
8252
7400
    if (stat_print(session, innobase_engine_name,
8253
7401
             engine_name_len, buf1, buf1len,
8256
7404
      return(1);
8257
7405
    }
8258
7406
#endif /* UNIV_DEBUG */
8259
 
  }
8260
 
 
8261
 
  if (block_mutex) {
8262
 
    buf1len = snprintf(buf1, sizeof buf1,
8263
 
                       "combined %s:%lu",
8264
 
                       block_mutex->cfile_name,
8265
 
                       (ulong) block_mutex->cline);
8266
 
    buf2len = snprintf(buf2, sizeof buf2,
8267
 
                       "os_waits=%lu",
8268
 
                       (ulong) block_mutex_oswait_count);
8269
 
 
8270
 
    if (stat_print(session, innobase_engine_name,
8271
 
                   strlen(innobase_engine_name), buf1, buf1len,
8272
 
                   buf2, buf2len)) {
8273
 
      mutex_exit(&mutex_list_mutex);
8274
 
      return(1);
8275
 
    }
 
7407
 
 
7408
next_mutex:
 
7409
    mutex = UT_LIST_GET_NEXT(list, mutex);
8276
7410
  }
8277
7411
 
8278
7412
  mutex_exit(&mutex_list_mutex);
8279
7413
 
8280
7414
  mutex_enter(&rw_lock_list_mutex);
8281
7415
 
8282
 
  for (lock = UT_LIST_GET_FIRST(rw_lock_list); lock != NULL;
8283
 
       lock = UT_LIST_GET_NEXT(list, lock)) {
8284
 
    if (lock->count_os_wait == 0) {
8285
 
      continue;
8286
 
    }
8287
 
 
8288
 
    if (buf_pool_is_block_lock(lock)) {
8289
 
      block_lock = lock;
8290
 
      block_lock_oswait_count += lock->count_os_wait;
8291
 
      continue;
8292
 
    }
8293
 
 
8294
 
    buf1len = snprintf(buf1, sizeof buf1, "%s:%lu",
8295
 
                       lock->cfile_name, (ulong) lock->cline);
8296
 
    buf2len = snprintf(buf2, sizeof buf2, "os_waits=%lu",
8297
 
                       (ulong) lock->count_os_wait);
8298
 
 
8299
 
    if (stat_print(session, innobase_engine_name,
8300
 
                   strlen(innobase_engine_name), buf1, buf1len,
8301
 
                   buf2, buf2len)) {
8302
 
      mutex_exit(&rw_lock_list_mutex);
8303
 
      return(1);
8304
 
    }
8305
 
  }
8306
 
 
8307
 
  if (block_lock) {
8308
 
    buf1len = snprintf(buf1, sizeof buf1,
8309
 
                       "combined %s:%lu",
8310
 
                       block_lock->cfile_name,
8311
 
                       (ulong) block_lock->cline);
8312
 
    buf2len = snprintf(buf2, sizeof buf2,
8313
 
                       "os_waits=%lu",
8314
 
                       (ulong) block_lock_oswait_count);
8315
 
 
8316
 
    if (stat_print(session, innobase_engine_name,
8317
 
                   strlen(innobase_engine_name), buf1, buf1len,
8318
 
                   buf2, buf2len)) {
8319
 
      mutex_exit(&rw_lock_list_mutex);
8320
 
      return(1);
8321
 
    }
 
7416
  lock = UT_LIST_GET_FIRST(rw_lock_list);
 
7417
 
 
7418
  while (lock != NULL) {
 
7419
    if (lock->count_os_wait
 
7420
                    && !buf_pool_is_block_lock(lock)) {
 
7421
      buf1len= snprintf(buf1, sizeof(buf1), "%s:%lu",
 
7422
                                    lock->cfile_name, (unsigned long) lock->cline);
 
7423
      buf2len= snprintf(buf2, sizeof(buf2),
 
7424
                                    "os_waits=%lu", lock->count_os_wait);
 
7425
 
 
7426
      if (stat_print(session, innobase_engine_name,
 
7427
               engine_name_len, buf1, buf1len,
 
7428
               buf2, buf2len)) {
 
7429
        mutex_exit(&rw_lock_list_mutex);
 
7430
        return(1);
 
7431
      }
 
7432
    }
 
7433
    lock = UT_LIST_GET_NEXT(list, lock);
8322
7434
  }
8323
7435
 
8324
7436
  mutex_exit(&rw_lock_list_mutex);
8325
7437
 
8326
7438
#ifdef UNIV_DEBUG
8327
 
  buf2len = snprintf(buf2, sizeof buf2,
8328
 
                     "count=%lu, spin_waits=%lu, spin_rounds=%lu, "
8329
 
                     "os_waits=%lu, os_yields=%lu, os_wait_times=%lu",
8330
 
                     (ulong) rw_lock_count,
8331
 
                     (ulong) rw_lock_count_spin_loop,
8332
 
                     (ulong) rw_lock_count_spin_rounds,
8333
 
                     (ulong) rw_lock_count_os_wait,
8334
 
                     (ulong) rw_lock_count_os_yield,
8335
 
                     (ulong) (rw_lock_wait_time / 1000));
 
7439
  buf2len= my_snprintf(buf2, sizeof(buf2),
 
7440
    "count=%lu, spin_waits=%lu, spin_rounds=%lu, "
 
7441
    "os_waits=%lu, os_yields=%lu, os_wait_times=%lu",
 
7442
    rw_lock_count, rw_lock_count_spin_loop,
 
7443
    rw_lock_count_spin_rounds,
 
7444
    rw_lock_count_os_wait, rw_lock_count_os_yield,
 
7445
    (ulong) (rw_lock_wait_time/1000));
8336
7446
 
8337
7447
  if (stat_print(session, innobase_engine_name, engine_name_len,
8338
7448
      STRING_WITH_LEN("rw_lock_mutexes"), buf2, buf2len)) {
8377
7487
        !strcmp(share->table_name, table_name));
8378
7488
 
8379
7489
  if (!share) {
 
7490
 
 
7491
    uint length = (uint) strlen(table_name);
 
7492
 
8380
7493
    /* TODO: invoke HASH_MIGRATE if innobase_open_tables
8381
7494
    grows too big */
8382
7495
 
8383
 
    share= new INNOBASE_SHARE(table_name);
 
7496
    share = (INNOBASE_SHARE *) malloc(sizeof(*share)+length+1);
 
7497
                memset(share, 0, sizeof(*share)+length+1);
 
7498
 
 
7499
    share->table_name = (char*) memcpy(share + 1,
 
7500
               table_name, length + 1);
8384
7501
 
8385
7502
    HASH_INSERT(INNOBASE_SHARE, table_name_hash,
8386
7503
          innobase_open_tables, fold, share);
8387
7504
 
8388
7505
    thr_lock_init(&share->lock);
8389
 
 
8390
 
    /* Index translation table initialization */
8391
 
    share->idx_trans_tbl.index_mapping = NULL;
8392
 
    share->idx_trans_tbl.index_count = 0;
8393
 
    share->idx_trans_tbl.array_size = 0;
8394
7506
  }
8395
7507
 
8396
7508
  share->use_count++;
8420
7532
 
8421
7533
    HASH_DELETE(INNOBASE_SHARE, table_name_hash,
8422
7534
          innobase_open_tables, fold, share);
8423
 
    share->lock.deinit();
8424
 
 
8425
 
    /* Free any memory from index translation table */
8426
 
    free(share->idx_trans_tbl.index_mapping);
8427
 
 
8428
 
    delete share;
 
7535
    thr_lock_delete(&share->lock);
 
7536
    free(share);
8429
7537
 
8430
7538
    /* TODO: invoke HASH_MIGRATE if innobase_open_tables
8431
7539
    shrinks too much */
8502
7610
    isolation_level = trx->isolation_level;
8503
7611
 
8504
7612
    if ((srv_locks_unsafe_for_binlog
8505
 
         || isolation_level <= TRX_ISO_READ_COMMITTED)
 
7613
         || isolation_level == TRX_ISO_READ_COMMITTED)
8506
7614
        && isolation_level != TRX_ISO_SERIALIZABLE
8507
7615
        && (lock_type == TL_READ || lock_type == TL_READ_NO_INSERT)
8508
7616
        && (sql_command == SQLCOM_INSERT_SELECT
8509
 
            || sql_command == SQLCOM_REPLACE_SELECT
8510
 
            || sql_command == SQLCOM_UPDATE
8511
 
            || sql_command == SQLCOM_CREATE_TABLE
8512
 
            || sql_command == SQLCOM_SET_OPTION)) {
 
7617
      || sql_command == SQLCOM_UPDATE
 
7618
      || sql_command == SQLCOM_CREATE_TABLE)) {
8513
7619
 
8514
7620
      /* If we either have innobase_locks_unsafe_for_binlog
8515
7621
      option set or this session is using READ COMMITTED
8516
7622
      isolation level and isolation level of the transaction
8517
7623
      is not set to serializable and MySQL is doing
8518
 
      INSERT INTO...SELECT or REPLACE INTO...SELECT
8519
 
      or UPDATE ... = (SELECT ...) or CREATE  ...
8520
 
      SELECT... or SET ... = (SELECT ...) without
8521
 
      FOR UPDATE or IN SHARE MODE in select,
8522
 
      then we use consistent read for select. */
 
7624
      INSERT INTO...SELECT or UPDATE ... = (SELECT ...) or
 
7625
      CREATE  ... SELECT... without FOR UPDATE or
 
7626
      IN SHARE MODE in select, then we use consistent
 
7627
      read for select. */
8523
7628
 
8524
7629
      prebuilt->select_lock_type = LOCK_NONE;
8525
7630
      prebuilt->stored_select_lock_type = LOCK_NONE;
8591
7696
  uint64_t* value)    /*!< out: autoinc value */
8592
7697
{
8593
7698
  *value = 0;
8594
 
 
8595
 
  dict_table_autoinc_lock(prebuilt->table);
8596
 
  prebuilt->autoinc_error= DB_SUCCESS;
8597
 
  /* Determine the first value of the interval */
8598
 
  *value = dict_table_autoinc_read(prebuilt->table);
8599
 
 
8600
 
  /* It should have been initialized during open. */
8601
 
  if (*value == 0) {
8602
 
    prebuilt->autoinc_error = DB_UNSUPPORTED;
8603
 
    dict_table_autoinc_unlock(prebuilt->table);
 
7699
 
 
7700
  prebuilt->autoinc_error = innobase_lock_autoinc();
 
7701
 
 
7702
  if (prebuilt->autoinc_error == DB_SUCCESS) {
 
7703
 
 
7704
    /* Determine the first value of the interval */
 
7705
    *value = dict_table_autoinc_read(prebuilt->table);
 
7706
 
 
7707
    /* It should have been initialized during open. */
 
7708
    ut_a(*value != 0);
8604
7709
  }
8605
7710
 
8606
 
  return(DB_SUCCESS);
 
7711
  return(prebuilt->autoinc_error);
8607
7712
}
8608
7713
 
8609
7714
/*******************************************************************//**
8610
 
This function reads the global auto-inc counter. It doesn't use the
 
7715
This function reads the global auto-inc counter. It doesn't use the 
8611
7716
AUTOINC lock even if the lock mode is set to TRADITIONAL.
8612
7717
@return the autoinc value */
8613
7718
UNIV_INTERN
8627
7732
 
8628
7733
  auto_inc = dict_table_autoinc_read(innodb_table);
8629
7734
 
8630
 
  if (auto_inc == 0) {
8631
 
    ut_print_timestamp(stderr);
8632
 
    fprintf(stderr, "  InnoDB: AUTOINC next value generation "
8633
 
            "is disabled for '%s'\n", innodb_table->name);
8634
 
  }
 
7735
  ut_a(auto_inc > 0);
8635
7736
 
8636
7737
  dict_table_autoinc_unlock(innodb_table);
8637
7738
 
8660
7761
  uint64_t  autoinc = 0;
8661
7762
 
8662
7763
  /* Prepare prebuilt->trx in the table handle */
8663
 
  update_session(getTable()->in_use);
 
7764
  update_session(ha_session());
8664
7765
 
8665
7766
  error = innobase_get_autoinc(&autoinc);
8666
7767
 
8684
7785
  invoking this method. So we are not sure if it's guaranteed to
8685
7786
  be 0 or not. */
8686
7787
 
8687
 
  /* We need the upper limit of the col type to check for
8688
 
     whether we update the table autoinc counter or not. */
8689
 
  uint64_t col_max_value = innobase_get_int_col_max_value(getTable()->next_number_field);
8690
 
 
8691
7788
  /* Called for the first time ? */
8692
7789
  if (trx->n_autoinc_rows == 0) {
8693
7790
 
8704
7801
  /* Not in the middle of a mult-row INSERT. */
8705
7802
  } else if (prebuilt->autoinc_last_value == 0) {
8706
7803
    set_if_bigger(*first_value, autoinc);
8707
 
    /* Check for -ve values. */
8708
 
  } else if (*first_value > col_max_value && trx->n_autoinc_rows > 0) {
8709
 
    /* Set to next logical value. */
8710
 
    ut_a(autoinc > trx->n_autoinc_rows);
8711
 
    *first_value = (autoinc - trx->n_autoinc_rows) - 1;
8712
7804
  }
8713
7805
 
8714
7806
  *nb_reserved_values = trx->n_autoinc_rows;
8715
7807
 
8716
 
  /* This all current style autoinc. */
8717
 
  {
 
7808
  /* With old style AUTOINC locking we only update the table's
 
7809
  AUTOINC counter after attempting to insert the row. */
 
7810
  if (innobase_autoinc_lock_mode != AUTOINC_OLD_STYLE_LOCKING) {
8718
7811
    uint64_t  need;
8719
 
    uint64_t  current;
8720
7812
    uint64_t  next_value;
8721
 
 
8722
 
    current = *first_value > col_max_value ? autoinc : *first_value;
 
7813
    uint64_t  col_max_value;
 
7814
 
 
7815
    /* We need the upper limit of the col type to check for
 
7816
    whether we update the table autoinc counter or not. */
 
7817
    col_max_value = innobase_get_int_col_max_value(
 
7818
      table->next_number_field);
 
7819
 
8723
7820
    need = *nb_reserved_values * increment;
8724
7821
 
8725
7822
    /* Compute the last value in the interval */
8726
 
    next_value = innobase_next_autoinc(current, need, offset, col_max_value);
 
7823
    next_value = innobase_next_autoinc(
 
7824
      *first_value, need, offset, col_max_value);
8727
7825
 
8728
7826
    prebuilt->autoinc_last_value = next_value;
8729
7827
 
8734
7832
      dict_table_autoinc_update_if_greater(
8735
7833
        prebuilt->table, prebuilt->autoinc_last_value);
8736
7834
    }
 
7835
  } else {
 
7836
    /* This will force doInsertRecord() into attempting an update
 
7837
    of the table's AUTOINC counter. */
 
7838
    prebuilt->autoinc_last_value = 0;
8737
7839
  }
8738
7840
 
8739
7841
  /* The increment to be used to increase the AUTOINC value, we use
8760
7862
{
8761
7863
  int error;
8762
7864
 
8763
 
  update_session(getTable()->in_use);
 
7865
  update_session(ha_session());
8764
7866
 
8765
7867
  error = row_lock_table_autoinc_for_mysql(prebuilt);
8766
7868
 
8811
7913
{
8812
7914
  enum_field_types mysql_type;
8813
7915
  Field*    field;
8814
 
  KeyPartInfo*  key_part;
8815
 
  KeyPartInfo*  key_part_end;
 
7916
  KEY_PART_INFO*  key_part;
 
7917
  KEY_PART_INFO*  key_part_end;
8816
7918
  uint    len1;
8817
7919
  uint    len2;
8818
7920
  int   result;
8826
7928
  /* Do a type-aware comparison of primary key fields. PK fields
8827
7929
  are always NOT NULL, so no checks for NULL are performed. */
8828
7930
 
8829
 
  key_part = getTable()->key_info[getTable()->getShare()->getPrimaryKey()].key_part;
 
7931
  key_part = table->key_info[table->s->primary_key].key_part;
8830
7932
 
8831
7933
  key_part_end = key_part
8832
 
      + getTable()->key_info[getTable()->getShare()->getPrimaryKey()].key_parts;
 
7934
      + table->key_info[table->s->primary_key].key_parts;
8833
7935
 
8834
7936
  for (; key_part != key_part_end; ++key_part) {
8835
7937
    field = key_part->field;
8962
8064
  trx->detailed_error[0]= '\0';
8963
8065
 
8964
8066
  /* Set the isolation level of the transaction. */
8965
 
  trx->isolation_level= innobase_map_isolation_level(session_tx_isolation(session));
 
8067
  trx->isolation_level= innobase_map_isolation_level((enum_tx_isolation) session_tx_isolation(session));
8966
8068
}
8967
8069
 
8968
8070
void
8977
8079
 
8978
8080
  innobase_release_stat_resources(trx);
8979
8081
 
 
8082
  if (! session_test_options(session, OPTION_NOT_AUTOCOMMIT | OPTION_BEGIN))
 
8083
  {
 
8084
    if (trx->conc_state != TRX_NOT_STARTED)
 
8085
    {
 
8086
      commit(session, TRUE);
 
8087
    }
 
8088
  }
 
8089
  else
 
8090
  {
 
8091
    if (trx->isolation_level <= TRX_ISO_READ_COMMITTED &&
 
8092
        trx->global_read_view)
 
8093
    {
 
8094
      /* At low transaction isolation levels we let
 
8095
      each consistent read set its own snapshot */
 
8096
      read_view_close_for_mysql(trx);
 
8097
    }
 
8098
  }
8980
8099
}
8981
8100
 
8982
8101
/*******************************************************************//**
9046
8165
  return(error);
9047
8166
}
9048
8167
 
9049
 
uint64_t InnobaseEngine::doGetCurrentTransactionId(Session *session)
9050
 
{
9051
 
  trx_t *trx= session_to_trx(session);
9052
 
  return (trx->id);
9053
 
}
9054
 
 
9055
 
uint64_t InnobaseEngine::doGetNewTransactionId(Session *session)
9056
 
{
9057
 
  trx_t*& trx = session_to_trx(session);
9058
 
 
9059
 
  if (trx == NULL)
9060
 
  {
9061
 
    trx = innobase_trx_allocate(session);
9062
 
 
9063
 
    innobase_trx_init(session, trx);
9064
 
  }
9065
 
 
9066
 
  mutex_enter(&kernel_mutex);
9067
 
  trx->id= trx_sys_get_new_trx_id();
9068
 
  mutex_exit(&kernel_mutex);
9069
 
 
9070
 
  uint64_t transaction_id= trx->id;
9071
 
 
9072
 
  return transaction_id;
9073
 
}
9074
 
 
9075
8168
/*******************************************************************//**
9076
8169
This function is used to recover X/Open XA distributed transactions.
9077
8170
@return number of prepared transactions stored in xid_list */
9183
8276
}
9184
8277
 
9185
8278
/************************************************************//**
 
8279
Validate the file format check value, is it one of "on" or "off",
 
8280
as a side effect it sets the srv_check_file_format_at_startup variable.
 
8281
@return true if config value one of "on" or  "off" */
 
8282
static
 
8283
bool
 
8284
innobase_file_format_check_on_off(
 
8285
/*==============================*/
 
8286
  const char* format_check) /*!< in: parameter value */
 
8287
{
 
8288
  bool    ret = true;
 
8289
 
 
8290
  if (!innobase_strcasecmp(format_check, "off")) {
 
8291
 
 
8292
    /* Set the value to disable checking. */
 
8293
    srv_check_file_format_at_startup = DICT_TF_FORMAT_MAX + 1;
 
8294
 
 
8295
  } else if (!innobase_strcasecmp(format_check, "on")) {
 
8296
 
 
8297
    /* Set the value to the lowest supported format. */
 
8298
    srv_check_file_format_at_startup = DICT_TF_FORMAT_51;
 
8299
  } else {
 
8300
    ret = FALSE;
 
8301
  }
 
8302
 
 
8303
  return(ret);
 
8304
}
 
8305
 
 
8306
/************************************************************//**
9186
8307
Validate the file format check config parameters, as a side effect it
9187
 
sets the srv_max_file_format_at_startup variable.
9188
 
@return the format_id if valid config value, otherwise, return -1 */
 
8308
sets the srv_check_file_format_at_startup variable.
 
8309
@return true if valid config value */
9189
8310
static
9190
 
int
9191
 
innobase_file_format_validate_and_set(
 
8311
bool
 
8312
innobase_file_format_check_validate(
9192
8313
/*================================*/
9193
 
  const char* format_max) /*!< in: parameter value */
 
8314
  const char* format_check) /*!< in: parameter value */
9194
8315
{
9195
8316
  uint    format_id;
 
8317
  bool    ret = true;
9196
8318
 
9197
 
  format_id = innobase_file_format_name_lookup(format_max);
 
8319
  format_id = innobase_file_format_name_lookup(format_check);
9198
8320
 
9199
8321
  if (format_id < DICT_TF_FORMAT_MAX + 1) {
9200
 
    srv_max_file_format_at_startup = format_id;
9201
 
    return((int) format_id);
9202
 
  } else {
9203
 
    return(-1);
9204
 
  }
9205
 
}
9206
 
 
9207
 
 
9208
 
 
9209
 
static void init_options(drizzled::module::option_context &context)
9210
 
{
9211
 
  context("disable-checksums",
9212
 
          "Disable InnoDB checksums validation.");
9213
 
  context("data-home-dir",
9214
 
          po::value<string>(),
9215
 
          "The common part for InnoDB table spaces.");
9216
 
  context("disable-doublewrite",
9217
 
          "Disable InnoDB doublewrite buffer.");
9218
 
  context("io-capacity",
9219
 
          po::value<io_capacity_constraint>(&innodb_io_capacity)->default_value(200),
9220
 
          "Number of IOPs the server can do. Tunes the background IO rate");
9221
 
  context("fast-shutdown",
9222
 
          po::value<trinary_constraint>(&innobase_fast_shutdown)->default_value(1), 
9223
 
          "Speeds up the shutdown process of the InnoDB storage engine. Possible values are 0, 1 (faster) or 2 (fastest - crash-like).");
9224
 
  context("purge-batch-size",
9225
 
          po::value<purge_batch_constraint>(&innodb_purge_batch_size)->default_value(20),
9226
 
          "Number of UNDO logs to purge in one batch from the history list. "
9227
 
          "Default is 20.");
9228
 
  context("purge-threads",
9229
 
          po::value<purge_threads_constraint>(&innodb_n_purge_threads)->default_value(0),
9230
 
          "Purge threads can be either 0 or 1. Defalut is 0.");
9231
 
  context("file-per-table",
9232
 
          po::value<bool>(&srv_file_per_table)->default_value(false)->zero_tokens(),
9233
 
          "Stores each InnoDB table to an .ibd file in the database dir.");
9234
 
  context("file-format",
9235
 
          po::value<string>(&innobase_file_format_name)->default_value("Antelope"),
9236
 
          "File format to use for new tables in .ibd files.");
9237
 
  context("file-format-max",
9238
 
          po::value<string>(&innobase_file_format_max)->default_value("Antelope"),
9239
 
          "The highest file format in the tablespace.");
9240
 
  context("file-format-check",
9241
 
          po::value<bool>(&innobase_file_format_check)->default_value(true)->zero_tokens(),
9242
 
          "Whether to perform system file format check.");
9243
 
  context("flush-log-at-trx-commit",
9244
 
          po::value<trinary_constraint>(&innodb_flush_log_at_trx_commit)->default_value(1),
9245
 
          "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).");
9246
 
  context("flush-method",
9247
 
          po::value<string>(),
9248
 
          "With which method to flush data.");
9249
 
  context("log-group-home-dir",
9250
 
          po::value<string>(),
9251
 
          "Path to InnoDB log files.");
9252
 
  context("max-dirty-pages-pct",
9253
 
          po::value<max_dirty_pages_constraint>(&innodb_max_dirty_pages_pct)->default_value(75),
9254
 
          "Percentage of dirty pages allowed in bufferpool.");
9255
 
  context("disable-adaptive-flushing",
9256
 
          "Do not attempt flushing dirty pages to avoid IO bursts at checkpoints.");
9257
 
  context("max-purge-lag",
9258
 
          po::value<uint64_constraint>(&innodb_max_purge_lag)->default_value(0),
9259
 
          "Desired maximum length of the purge queue (0 = no limit)");
9260
 
  context("status-file",
9261
 
          po::value<bool>(&innobase_create_status_file)->default_value(false)->zero_tokens(),
9262
 
          "Enable SHOW INNODB STATUS output in the innodb_status.<pid> file");
9263
 
  context("disable-stats-on-metadata",
9264
 
          "Disable statistics gathering for metadata commands such as SHOW TABLE STATUS (on by default)");
9265
 
  context("stats-sample-pages",
9266
 
          po::value<uint64_nonzero_constraint>(&innodb_stats_sample_pages)->default_value(8),
9267
 
          "The number of index pages to sample when calculating statistics (default 8)");
9268
 
  context("disable-adaptive-hash-index",
9269
 
          "Enable InnoDB adaptive hash index (enabled by default)");
9270
 
  context("replication-delay",
9271
 
          po::value<uint64_constraint>(&innodb_replication_delay)->default_value(0),
9272
 
          "Replication thread delay (ms) on the slave server if innodb_thread_concurrency is reached (0 by default)");
9273
 
  context("additional-mem-pool-size",
9274
 
          po::value<additional_mem_pool_constraint>(&innobase_additional_mem_pool_size)->default_value(8*1024*1024L),
9275
 
          "Size of a memory pool InnoDB uses to store data dictionary information and other internal data structures.");
9276
 
  context("autoextend-increment",
9277
 
          po::value<autoextend_constraint>(&innodb_auto_extend_increment)->default_value(8L),
9278
 
          "Data file autoextend increment in megabytes");
9279
 
  context("buffer-pool-size",
9280
 
          po::value<buffer_pool_constraint>(&innobase_buffer_pool_size)->default_value(128*1024*1024L),
9281
 
          "The size of the memory buffer InnoDB uses to cache data and indexes of its tables.");
9282
 
  context("buffer-pool-instances",
9283
 
          po::value<buffer_pool_instances_constraint>(&innobase_buffer_pool_instances)->default_value(1),
9284
 
          "Number of buffer pool instances, set to higher value on high-end machines to increase scalability");
9285
 
 
9286
 
  context("commit-concurrency",
9287
 
          po::value<concurrency_constraint>(&innobase_commit_concurrency)->default_value(0),
9288
 
          "Helps in performance tuning in heavily concurrent environments.");
9289
 
  context("concurrency-tickets",
9290
 
          po::value<uint32_nonzero_constraint>(&innodb_concurrency_tickets)->default_value(500L),
9291
 
          "Number of times a thread is allowed to enter InnoDB within the same SQL query after it has once got the ticket");
9292
 
  context("read-io-threads",
9293
 
          po::value<io_threads_constraint>(&innobase_read_io_threads)->default_value(4),
9294
 
          "Number of background read I/O threads in InnoDB.");
9295
 
  context("write-io-threads",
9296
 
          po::value<io_threads_constraint>(&innobase_write_io_threads)->default_value(4),
9297
 
          "Number of background write I/O threads in InnoDB.");
9298
 
  context("force-recovery",
9299
 
          po::value<force_recovery_constraint>(&innobase_force_recovery)->default_value(0),
9300
 
          "Helps to save your data in case the disk image of the database becomes corrupt.");
9301
 
  context("log-buffer-size",
9302
 
          po::value<log_buffer_constraint>(&innobase_log_buffer_size)->default_value(8*1024*1024L),
9303
 
          "The size of the buffer which InnoDB uses to write log to the log files on disk.");
9304
 
  context("log-file-size",
9305
 
          po::value<log_file_constraint>(&innobase_log_file_size)->default_value(20*1024*1024L),
9306
 
          "The size of the buffer which InnoDB uses to write log to the log files on disk.");
9307
 
  context("log-files-in-group",
9308
 
          po::value<log_files_in_group_constraint>(&innobase_log_files_in_group)->default_value(2),
9309
 
          "Number of log files in the log group. InnoDB writes to the files in a circular fashion.");
9310
 
  context("mirrored-log-groups",
9311
 
          po::value<mirrored_log_groups_constraint>(&innobase_mirrored_log_groups)->default_value(1),
9312
 
          "Number of identical copies of log groups we keep for the database. Currently this should be set to 1.");
9313
 
  context("open-files",
9314
 
          po::value<open_files_constraint>(&innobase_open_files)->default_value(300L),
9315
 
          "How many files at the maximum InnoDB keeps open at the same time.");
9316
 
  context("sync-spin-loops",
9317
 
          po::value<uint32_constraint>(&innodb_sync_spin_loops)->default_value(30L),
9318
 
          "Count of spin-loop rounds in InnoDB mutexes (30 by default)");
9319
 
  context("spin-wait-delay",
9320
 
          po::value<uint32_constraint>(&innodb_spin_wait_delay)->default_value(6L),
9321
 
          "Maximum delay between polling for a spin lock (6 by default)");
9322
 
  context("thread-concurrency",
9323
 
          po::value<concurrency_constraint>(&innobase_thread_concurrency)->default_value(0),
9324
 
          "Helps in performance tuning in heavily concurrent environments. Sets the maximum number of threads allowed inside InnoDB. Value 0 will disable the thread throttling.");
9325
 
  context("thread-sleep-delay",
9326
 
          po::value<uint32_constraint>(&innodb_thread_sleep_delay)->default_value(10000L),
9327
 
          "Time of innodb thread sleeping before joining InnoDB queue (usec). Value 0 disable a sleep");
9328
 
  context("data-file-path",
9329
 
          po::value<string>(),
9330
 
          "Path to individual files and their sizes.");
9331
 
  context("version",
9332
 
          po::value<string>()->default_value(INNODB_VERSION_STR),
9333
 
          "InnoDB version");
9334
 
  context("use-internal-malloc",
9335
 
          "Use InnoDB's internal memory allocator instal of the OS memory allocator.");
9336
 
  context("change-buffering",
9337
 
          po::value<string>(&innobase_change_buffering),
9338
 
          "Buffer changes to reduce random access: OFF, ON, inserting, deleting, changing, or purging.");
9339
 
  context("read-ahead-threshold",
9340
 
          po::value<read_ahead_threshold_constraint>(&innodb_read_ahead_threshold)->default_value(56),
9341
 
          "Number of pages that must be accessed sequentially for InnoDB to trigger a readahead.");
9342
 
  context("disable-xa",
9343
 
          "Disable InnoDB support for the XA two-phase commit");
9344
 
  context("disable-table-locks",
9345
 
          "Disable InnoDB locking in LOCK TABLES");
9346
 
  context("strict-mode",
9347
 
          po::value<bool>(&strict_mode)->default_value(false)->zero_tokens(),
9348
 
          "Use strict mode when evaluating create options.");
9349
 
  context("replication-log",
9350
 
          po::value<bool>(&innobase_use_replication_log)->default_value(false),
9351
 
          _("Enable internal replication log."));
9352
 
  context("lock-wait-timeout",
9353
 
          po::value<lock_wait_constraint>(&lock_wait_timeout)->default_value(50),
9354
 
          _("Timeout in seconds an InnoDB transaction may wait for a lock before being rolled back. Values above 100000000 disable the timeout."));
9355
 
  context("old-blocks-pct",
9356
 
          po::value<old_blocks_constraint>(&innobase_old_blocks_pct)->default_value(100 * 3 / 8),
9357
 
          _("Percentage of the buffer pool to reserve for 'old' blocks."));
9358
 
  context("old-blocks-time",
9359
 
          po::value<uint32_t>(&buf_LRU_old_threshold_ms)->default_value(0),
9360
 
          _("ove blocks to the 'new' end of the buffer pool if the first access"
9361
 
            " was at least this many milliseconds ago."
9362
 
            " The timeout is disabled if 0 (the default)."));
9363
 
}
9364
 
 
9365
 
 
 
8322
    srv_check_file_format_at_startup = format_id;
 
8323
  } else {
 
8324
    ret = false;
 
8325
  }
 
8326
 
 
8327
  return(ret);
 
8328
}
 
8329
 
 
8330
/*************************************************************//**
 
8331
Check if it is a valid file format. This function is registered as
 
8332
a callback with MySQL.
 
8333
@return 0 for valid file format */
 
8334
static
 
8335
int
 
8336
innodb_file_format_name_validate(
 
8337
/*=============================*/
 
8338
  Session*      , /*!< in: thread handle */
 
8339
  drizzle_sys_var*  , /*!< in: pointer to system
 
8340
            variable */
 
8341
  void*       save, /*!< out: immediate result
 
8342
            for update function */
 
8343
  drizzle_value*    value)  /*!< in: incoming string */
 
8344
{
 
8345
  const char* file_format_input;
 
8346
  char    buff[STRING_BUFFER_USUAL_SIZE];
 
8347
  int   len = sizeof(buff);
 
8348
 
 
8349
  ut_a(save != NULL);
 
8350
  ut_a(value != NULL);
 
8351
 
 
8352
  file_format_input = value->val_str(value, buff, &len);
 
8353
 
 
8354
  if (file_format_input != NULL) {
 
8355
    uint  format_id;
 
8356
 
 
8357
    format_id = innobase_file_format_name_lookup(
 
8358
      file_format_input);
 
8359
 
 
8360
    if (format_id <= DICT_TF_FORMAT_MAX) {
 
8361
 
 
8362
      *static_cast<const char**>(save) = file_format_input;
 
8363
      return(0);
 
8364
    }
 
8365
  }
 
8366
 
 
8367
  *static_cast<const char**>(save) = NULL;
 
8368
  return(1);
 
8369
}
 
8370
 
 
8371
/****************************************************************//**
 
8372
Update the system variable innodb_file_format using the "saved"
 
8373
value. This function is registered as a callback with MySQL. */
 
8374
static
 
8375
void
 
8376
innodb_file_format_name_update(
 
8377
/*===========================*/
 
8378
  Session*      ,   /*!< in: thread handle */
 
8379
  drizzle_sys_var*  ,   /*!< in: pointer to
 
8380
              system variable */
 
8381
  void*       var_ptr,  /*!< out: where the
 
8382
              formal string goes */
 
8383
  const void*     save)   /*!< in: immediate result
 
8384
              from check function */
 
8385
{
 
8386
  const char* format_name;
 
8387
 
 
8388
  ut_a(var_ptr != NULL);
 
8389
  ut_a(save != NULL);
 
8390
 
 
8391
  format_name = *static_cast<const char*const*>(save);
 
8392
 
 
8393
  if (format_name) {
 
8394
    uint  format_id;
 
8395
 
 
8396
    format_id = innobase_file_format_name_lookup(format_name);
 
8397
 
 
8398
    if (format_id <= DICT_TF_FORMAT_MAX) {
 
8399
      srv_file_format = format_id;
 
8400
    }
 
8401
  }
 
8402
 
 
8403
  *static_cast<const char**>(var_ptr)
 
8404
    = trx_sys_file_format_id_to_name(srv_file_format);
 
8405
}
 
8406
 
 
8407
/*************************************************************//**
 
8408
Check if valid argument to innodb_file_format_check. This
 
8409
function is registered as a callback with MySQL.
 
8410
@return 0 for valid file format */
 
8411
static
 
8412
int
 
8413
innodb_file_format_check_validate(
 
8414
/*==============================*/
 
8415
  Session*      , /*!< in: thread handle */
 
8416
  drizzle_sys_var*  , /*!< in: pointer to system
 
8417
            variable */
 
8418
  void*       save, /*!< out: immediate result
 
8419
            for update function */
 
8420
  drizzle_value*    value)  /*!< in: incoming string */
 
8421
{
 
8422
  const char* file_format_input;
 
8423
  char    buff[STRING_BUFFER_USUAL_SIZE];
 
8424
  int   len = sizeof(buff);
 
8425
 
 
8426
  ut_a(save != NULL);
 
8427
  ut_a(value != NULL);
 
8428
 
 
8429
  file_format_input = value->val_str(value, buff, &len);
 
8430
 
 
8431
  if (file_format_input != NULL) {
 
8432
 
 
8433
    /* Check if user set on/off, we want to print a suitable
 
8434
    message if they did so. */
 
8435
 
 
8436
    if (innobase_file_format_check_on_off(file_format_input)) {
 
8437
      errmsg_printf(ERRMSG_LVL_WARN, 
 
8438
        "InnoDB: invalid innodb_file_format_check "
 
8439
        "value; on/off can only be set at startup or "
 
8440
        "in the configuration file");
 
8441
    } else if (innobase_file_format_check_validate(
 
8442
        file_format_input)) {
 
8443
 
 
8444
      *static_cast<const char**>(save) = file_format_input;
 
8445
 
 
8446
      return(0);
 
8447
 
 
8448
    } else {
 
8449
      errmsg_printf(ERRMSG_LVL_WARN, 
 
8450
        "InnoDB: invalid innodb_file_format_check "
 
8451
        "value; can be any format up to %s "
 
8452
        "or its equivalent numeric id",
 
8453
        trx_sys_file_format_id_to_name(
 
8454
          DICT_TF_FORMAT_MAX));
 
8455
    }
 
8456
  }
 
8457
 
 
8458
  *static_cast<const char**>(save) = NULL;
 
8459
  return(1);
 
8460
}
 
8461
 
 
8462
/****************************************************************//**
 
8463
Update the system variable innodb_file_format_check using the "saved"
 
8464
value. This function is registered as a callback with MySQL. */
 
8465
static
 
8466
void
 
8467
innodb_file_format_check_update(
 
8468
/*============================*/
 
8469
  Session*      session,  /*!< in: thread handle */
 
8470
  drizzle_sys_var*  ,   /*!< in: pointer to
 
8471
              system variable */
 
8472
  void*       var_ptr,  /*!< out: where the
 
8473
              formal string goes */
 
8474
  const void*     save)   /*!< in: immediate result
 
8475
              from check function */
 
8476
{
 
8477
  const char* format_name_in;
 
8478
  const char**  format_name_out;
 
8479
  uint    format_id;
 
8480
 
 
8481
  ut_a(save != NULL);
 
8482
  ut_a(var_ptr != NULL);
 
8483
 
 
8484
  format_name_in = *static_cast<const char*const*>(save);
 
8485
 
 
8486
  if (!format_name_in) {
 
8487
 
 
8488
    return;
 
8489
  }
 
8490
 
 
8491
  format_id = innobase_file_format_name_lookup(format_name_in);
 
8492
 
 
8493
  if (format_id > DICT_TF_FORMAT_MAX) {
 
8494
    /* DEFAULT is "on", which is invalid at runtime. */
 
8495
    push_warning_printf(session, DRIZZLE_ERROR::WARN_LEVEL_WARN,
 
8496
            ER_WRONG_ARGUMENTS,
 
8497
            "Ignoring SET innodb_file_format=%s",
 
8498
            format_name_in);
 
8499
    return;
 
8500
  }
 
8501
 
 
8502
  format_name_out = static_cast<const char**>(var_ptr);
 
8503
 
 
8504
  /* Update the max format id in the system tablespace. */
 
8505
  if (trx_sys_file_format_max_set(format_id, format_name_out)) {
 
8506
    ut_print_timestamp(stderr);
 
8507
    fprintf(stderr,
 
8508
      " [Info] InnoDB: the file format in the system "
 
8509
      "tablespace is now set to %s.\n", *format_name_out);
 
8510
  }
 
8511
}
 
8512
 
 
8513
/****************************************************************//**
 
8514
Update the system variable innodb_adaptive_hash_index using the "saved"
 
8515
value. This function is registered as a callback with MySQL. */
 
8516
static
 
8517
void
 
8518
innodb_adaptive_hash_index_update(
 
8519
/*==============================*/
 
8520
  Session*      ,   /*!< in: thread handle */
 
8521
  drizzle_sys_var*  ,   /*!< in: pointer to
 
8522
              system variable */
 
8523
  void*       , /*!< out: where the
 
8524
              formal string goes */
 
8525
  const void*     save)   /*!< in: immediate result
 
8526
              from check function */
 
8527
{
 
8528
  if (*(bool*) save) {
 
8529
    btr_search_enable();
 
8530
  } else {
 
8531
    btr_search_disable();
 
8532
  }
 
8533
}
 
8534
 
 
8535
/*************************************************************//**
 
8536
Check if it is a valid value of innodb_change_buffering.  This function is
 
8537
registered as a callback with MySQL.
 
8538
@return 0 for valid innodb_change_buffering */
 
8539
static
 
8540
int
 
8541
innodb_change_buffering_validate(
 
8542
/*=============================*/
 
8543
  Session*      , /*!< in: thread handle */
 
8544
  drizzle_sys_var*  , /*!< in: pointer to system
 
8545
            variable */
 
8546
  void*       save, /*!< out: immediate result
 
8547
            for update function */
 
8548
  drizzle_value*    value)  /*!< in: incoming string */
 
8549
{
 
8550
  const char* change_buffering_input;
 
8551
  char    buff[STRING_BUFFER_USUAL_SIZE];
 
8552
  int   len = sizeof(buff);
 
8553
 
 
8554
  ut_a(save != NULL);
 
8555
  ut_a(value != NULL);
 
8556
 
 
8557
  change_buffering_input = value->val_str(value, buff, &len);
 
8558
 
 
8559
  if (change_buffering_input != NULL) {
 
8560
    ulint use;
 
8561
 
 
8562
    for (use = 0; use < UT_ARR_SIZE(innobase_change_buffering_values);
 
8563
         use++) {
 
8564
      if (!innobase_strcasecmp(
 
8565
            change_buffering_input,
 
8566
            innobase_change_buffering_values[use])) {
 
8567
        *(ibuf_use_t*) save = (ibuf_use_t) use;
 
8568
        return(0);
 
8569
      }
 
8570
    }
 
8571
  }
 
8572
 
 
8573
  return(1);
 
8574
}
 
8575
 
 
8576
/****************************************************************//**
 
8577
Update the system variable innodb_change_buffering using the "saved"
 
8578
value. This function is registered as a callback with MySQL. */
 
8579
static
 
8580
void
 
8581
innodb_change_buffering_update(
 
8582
/*===========================*/
 
8583
  Session*      ,   /*!< in: thread handle */
 
8584
  drizzle_sys_var*  ,   /*!< in: pointer to
 
8585
              system variable */
 
8586
  void*       var_ptr,  /*!< out: where the
 
8587
              formal string goes */
 
8588
  const void*     save)   /*!< in: immediate result
 
8589
              from check function */
 
8590
{
 
8591
  ut_a(var_ptr != NULL);
 
8592
  ut_a(save != NULL);
 
8593
  ut_a((*(ibuf_use_t*) save) < IBUF_USE_COUNT);
 
8594
 
 
8595
  ibuf_use = *(const ibuf_use_t*) save;
 
8596
 
 
8597
  *(const char**) var_ptr = innobase_change_buffering_values[ibuf_use];
 
8598
}
 
8599
 
 
8600
/* plugin options */
 
8601
static DRIZZLE_SYSVAR_BOOL(checksums, innobase_use_checksums,
 
8602
  PLUGIN_VAR_NOCMDARG | PLUGIN_VAR_READONLY,
 
8603
  "Enable InnoDB checksums validation (enabled by default). "
 
8604
  "Disable with --skip-innodb-checksums.",
 
8605
  NULL, NULL, TRUE);
 
8606
 
 
8607
static DRIZZLE_SYSVAR_STR(data_home_dir, innobase_data_home_dir,
 
8608
  PLUGIN_VAR_READONLY,
 
8609
  "The common part for InnoDB table spaces.",
 
8610
  NULL, NULL, NULL);
 
8611
 
 
8612
static DRIZZLE_SYSVAR_BOOL(doublewrite, innobase_use_doublewrite,
 
8613
  PLUGIN_VAR_NOCMDARG | PLUGIN_VAR_READONLY,
 
8614
  "Enable InnoDB doublewrite buffer (enabled by default). "
 
8615
  "Disable with --skip-innodb-doublewrite.",
 
8616
  NULL, NULL, TRUE);
 
8617
 
 
8618
static DRIZZLE_SYSVAR_ULONG(io_capacity, srv_io_capacity,
 
8619
  PLUGIN_VAR_RQCMDARG,
 
8620
  "Number of IOPs the server can do. Tunes the background IO rate",
 
8621
  NULL, NULL, 200, 100, ~0L, 0);
 
8622
 
 
8623
static DRIZZLE_SYSVAR_ULONG(fast_shutdown, innobase_fast_shutdown,
 
8624
  PLUGIN_VAR_OPCMDARG,
 
8625
  "Speeds up the shutdown process of the InnoDB storage engine. Possible "
 
8626
  "values are 0, 1 (faster)"
 
8627
  " or 2 (fastest - crash-like)"
 
8628
  ".",
 
8629
  NULL, NULL, 1, 0, 2, 0);
 
8630
 
 
8631
static DRIZZLE_SYSVAR_BOOL(file_per_table, srv_file_per_table,
 
8632
  PLUGIN_VAR_NOCMDARG,
 
8633
  "Stores each InnoDB table to an .ibd file in the database dir.",
 
8634
  NULL, NULL, FALSE);
 
8635
 
 
8636
static DRIZZLE_SYSVAR_STR(file_format, innobase_file_format_name,
 
8637
  PLUGIN_VAR_RQCMDARG,
 
8638
  "File format to use for new tables in .ibd files.",
 
8639
  innodb_file_format_name_validate,
 
8640
  innodb_file_format_name_update, "Antelope");
 
8641
 
 
8642
static DRIZZLE_SYSVAR_STR(file_format_check, innobase_file_format_check,
 
8643
  PLUGIN_VAR_OPCMDARG,
 
8644
  "The highest file format in the tablespace.",
 
8645
  innodb_file_format_check_validate,
 
8646
  innodb_file_format_check_update,
 
8647
  "on");
 
8648
 
 
8649
static DRIZZLE_SYSVAR_ULONG(flush_log_at_trx_commit, srv_flush_log_at_trx_commit,
 
8650
  PLUGIN_VAR_OPCMDARG,
 
8651
  "Set to 0 (write and flush once per second),"
 
8652
  " 1 (write and flush at each commit)"
 
8653
  " or 2 (write at commit, flush once per second).",
 
8654
  NULL, NULL, 1, 0, 2, 0);
 
8655
 
 
8656
static DRIZZLE_SYSVAR_STR(flush_method, innobase_unix_file_flush_method,
 
8657
  PLUGIN_VAR_RQCMDARG | PLUGIN_VAR_READONLY,
 
8658
  "With which method to flush data.", NULL, NULL, NULL);
 
8659
 
 
8660
#ifdef UNIV_LOG_ARCHIVE
 
8661
static DRIZZLE_SYSVAR_STR(log_arch_dir, innobase_log_arch_dir,
 
8662
  PLUGIN_VAR_RQCMDARG | PLUGIN_VAR_READONLY,
 
8663
  "Where full logs should be archived.", NULL, NULL, NULL);
 
8664
 
 
8665
static DRIZZLE_SYSVAR_BOOL(log_archive, innobase_log_archive,
 
8666
  PLUGIN_VAR_OPCMDARG | PLUGIN_VAR_READONLY,
 
8667
  "Set to 1 if you want to have logs archived.", NULL, NULL, FALSE);
 
8668
#endif /* UNIV_LOG_ARCHIVE */
 
8669
 
 
8670
static DRIZZLE_SYSVAR_STR(log_group_home_dir, innobase_log_group_home_dir,
 
8671
  PLUGIN_VAR_RQCMDARG | PLUGIN_VAR_READONLY,
 
8672
  "Path to InnoDB log files.", NULL, NULL, NULL);
 
8673
 
 
8674
static DRIZZLE_SYSVAR_ULONG(max_dirty_pages_pct, srv_max_buf_pool_modified_pct,
 
8675
  PLUGIN_VAR_RQCMDARG,
 
8676
  "Percentage of dirty pages allowed in bufferpool.",
 
8677
  NULL, NULL, 75, 0, 99, 0);
 
8678
 
 
8679
static DRIZZLE_SYSVAR_BOOL(adaptive_flushing, srv_adaptive_flushing,
 
8680
  PLUGIN_VAR_NOCMDARG,
 
8681
  "Attempt flushing dirty pages to avoid IO bursts at checkpoints.",
 
8682
  NULL, NULL, TRUE);
 
8683
 
 
8684
static DRIZZLE_SYSVAR_ULONG(max_purge_lag, srv_max_purge_lag,
 
8685
  PLUGIN_VAR_RQCMDARG,
 
8686
  "Desired maximum length of the purge queue (0 = no limit)",
 
8687
  NULL, NULL, 0, 0, ~0L, 0);
 
8688
 
 
8689
static DRIZZLE_SYSVAR_BOOL(rollback_on_timeout, innobase_rollback_on_timeout,
 
8690
  PLUGIN_VAR_OPCMDARG | PLUGIN_VAR_READONLY,
 
8691
  "Roll back the complete transaction on lock wait timeout, for 4.x compatibility (disabled by default)",
 
8692
  NULL, NULL, FALSE);
 
8693
 
 
8694
static DRIZZLE_SYSVAR_BOOL(status_file, innobase_create_status_file,
 
8695
  PLUGIN_VAR_OPCMDARG | PLUGIN_VAR_NOSYSVAR,
 
8696
  "Enable SHOW INNODB STATUS output in the innodb_status.<pid> file",
 
8697
  NULL, NULL, FALSE);
 
8698
 
 
8699
static DRIZZLE_SYSVAR_BOOL(stats_on_metadata, innobase_stats_on_metadata,
 
8700
  PLUGIN_VAR_OPCMDARG,
 
8701
  "Enable statistics gathering for metadata commands such as SHOW TABLE STATUS (on by default)",
 
8702
  NULL, NULL, TRUE);
 
8703
 
 
8704
static DRIZZLE_SYSVAR_ULONGLONG(stats_sample_pages, srv_stats_sample_pages,
 
8705
  PLUGIN_VAR_RQCMDARG,
 
8706
  "The number of index pages to sample when calculating statistics (default 8)",
 
8707
  NULL, NULL, 8, 1, ~0ULL, 0);
 
8708
 
 
8709
static DRIZZLE_SYSVAR_BOOL(adaptive_hash_index, btr_search_enabled,
 
8710
  PLUGIN_VAR_OPCMDARG,
 
8711
  "Enable InnoDB adaptive hash index (enabled by default).  "
 
8712
  "Disable with --skip-innodb-adaptive-hash-index.",
 
8713
  NULL, innodb_adaptive_hash_index_update, TRUE);
 
8714
 
 
8715
static DRIZZLE_SYSVAR_ULONG(replication_delay, srv_replication_delay,
 
8716
  PLUGIN_VAR_RQCMDARG,
 
8717
  "Replication thread delay (ms) on the slave server if "
 
8718
  "innodb_thread_concurrency is reached (0 by default)",
 
8719
  NULL, NULL, 0, 0, ~0UL, 0);
 
8720
 
 
8721
static DRIZZLE_SYSVAR_LONG(additional_mem_pool_size, innobase_additional_mem_pool_size,
 
8722
  PLUGIN_VAR_RQCMDARG | PLUGIN_VAR_READONLY,
 
8723
  "Size of a memory pool InnoDB uses to store data dictionary information and other internal data structures.",
 
8724
  NULL, NULL, 8*1024*1024L, 512*1024L, LONG_MAX, 1024);
 
8725
 
 
8726
static DRIZZLE_SYSVAR_UINT(autoextend_increment, srv_auto_extend_increment,
 
8727
  PLUGIN_VAR_RQCMDARG,
 
8728
  "Data file autoextend increment in megabytes",
 
8729
  NULL, NULL, 8L, 1L, 1000L, 0);
 
8730
 
 
8731
static DRIZZLE_SYSVAR_LONGLONG(buffer_pool_size, innobase_buffer_pool_size,
 
8732
  PLUGIN_VAR_RQCMDARG | PLUGIN_VAR_READONLY,
 
8733
  "The size of the memory buffer InnoDB uses to cache data and indexes of its tables.",
 
8734
  NULL, NULL, 128*1024*1024L, 5*1024*1024L, INT64_MAX, 1024*1024L);
 
8735
 
 
8736
static DRIZZLE_SYSVAR_ULONG(commit_concurrency, innobase_commit_concurrency,
 
8737
  PLUGIN_VAR_RQCMDARG,
 
8738
  "Helps in performance tuning in heavily concurrent environments.",
 
8739
  innobase_commit_concurrency_validate, NULL, 0, 0, 1000, 0);
 
8740
 
 
8741
static DRIZZLE_SYSVAR_ULONG(concurrency_tickets, srv_n_free_tickets_to_enter,
 
8742
  PLUGIN_VAR_RQCMDARG,
 
8743
  "Number of times a thread is allowed to enter InnoDB within the same SQL query after it has once got the ticket",
 
8744
  NULL, NULL, 500L, 1L, ~0L, 0);
 
8745
 
 
8746
static DRIZZLE_SYSVAR_LONG(file_io_threads, innobase_file_io_threads,
 
8747
  PLUGIN_VAR_RQCMDARG | PLUGIN_VAR_READONLY,
 
8748
  "Number of file I/O threads in InnoDB.",
 
8749
  NULL, NULL, 4, 4, 64, 0);
 
8750
 
 
8751
static DRIZZLE_SYSVAR_ULONG(read_io_threads, innobase_read_io_threads,
 
8752
  PLUGIN_VAR_RQCMDARG | PLUGIN_VAR_READONLY,
 
8753
  "Number of background read I/O threads in InnoDB.",
 
8754
  NULL, NULL, 4, 1, 64, 0);
 
8755
 
 
8756
static DRIZZLE_SYSVAR_ULONG(write_io_threads, innobase_write_io_threads,
 
8757
  PLUGIN_VAR_RQCMDARG | PLUGIN_VAR_READONLY,
 
8758
  "Number of background write I/O threads in InnoDB.",
 
8759
  NULL, NULL, 4, 1, 64, 0);
 
8760
 
 
8761
static DRIZZLE_SYSVAR_LONG(force_recovery, innobase_force_recovery,
 
8762
  PLUGIN_VAR_RQCMDARG | PLUGIN_VAR_READONLY,
 
8763
  "Helps to save your data in case the disk image of the database becomes corrupt.",
 
8764
  NULL, NULL, 0, 0, 6, 0);
 
8765
 
 
8766
static DRIZZLE_SYSVAR_LONG(log_buffer_size, innobase_log_buffer_size,
 
8767
  PLUGIN_VAR_RQCMDARG | PLUGIN_VAR_READONLY,
 
8768
  "The size of the buffer which InnoDB uses to write log to the log files on disk.",
 
8769
  NULL, NULL, 8*1024*1024L, 256*1024L, LONG_MAX, 1024);
 
8770
 
 
8771
static DRIZZLE_SYSVAR_LONGLONG(log_file_size, innobase_log_file_size,
 
8772
  PLUGIN_VAR_RQCMDARG | PLUGIN_VAR_READONLY,
 
8773
  "Size of each log file in a log group.",
 
8774
  NULL, NULL, 5*1024*1024L, 1*1024*1024L, INT64_MAX, 1024*1024L);
 
8775
 
 
8776
static DRIZZLE_SYSVAR_LONG(log_files_in_group, innobase_log_files_in_group,
 
8777
  PLUGIN_VAR_RQCMDARG | PLUGIN_VAR_READONLY,
 
8778
  "Number of log files in the log group. InnoDB writes to the files in a circular fashion. Value 3 is recommended here.",
 
8779
  NULL, NULL, 2, 2, 100, 0);
 
8780
 
 
8781
static DRIZZLE_SYSVAR_LONG(mirrored_log_groups, innobase_mirrored_log_groups,
 
8782
  PLUGIN_VAR_RQCMDARG | PLUGIN_VAR_READONLY,
 
8783
  "Number of identical copies of log groups we keep for the database. Currently this should be set to 1.",
 
8784
  NULL, NULL, 1, 1, 10, 0);
 
8785
 
 
8786
static DRIZZLE_SYSVAR_LONG(open_files, innobase_open_files,
 
8787
  PLUGIN_VAR_RQCMDARG | PLUGIN_VAR_READONLY,
 
8788
  "How many files at the maximum InnoDB keeps open at the same time.",
 
8789
  NULL, NULL, 300L, 10L, LONG_MAX, 0);
 
8790
 
 
8791
static DRIZZLE_SYSVAR_ULONG(sync_spin_loops, srv_n_spin_wait_rounds,
 
8792
  PLUGIN_VAR_RQCMDARG,
 
8793
  "Count of spin-loop rounds in InnoDB mutexes (30 by default)",
 
8794
  NULL, NULL, 30L, 0L, ~0L, 0);
 
8795
 
 
8796
static DRIZZLE_SYSVAR_ULONG(spin_wait_delay, srv_spin_wait_delay,
 
8797
  PLUGIN_VAR_OPCMDARG,
 
8798
  "Maximum delay between polling for a spin lock (6 by default)",
 
8799
  NULL, NULL, 6L, 0L, ~0L, 0);
 
8800
 
 
8801
static DRIZZLE_SYSVAR_ULONG(thread_concurrency, srv_thread_concurrency,
 
8802
  PLUGIN_VAR_RQCMDARG,
 
8803
  "Helps in performance tuning in heavily concurrent environments. Sets the maximum number of threads allowed inside InnoDB. Value 0 will disable the thread throttling.",
 
8804
  NULL, NULL, 0, 0, 1000, 0);
 
8805
 
 
8806
static DRIZZLE_SYSVAR_ULONG(thread_sleep_delay, srv_thread_sleep_delay,
 
8807
  PLUGIN_VAR_RQCMDARG,
 
8808
  "Time of innodb thread sleeping before joining InnoDB queue (usec). Value 0 disable a sleep",
 
8809
  NULL, NULL, 10000L, 0L, ~0L, 0);
 
8810
 
 
8811
static DRIZZLE_SYSVAR_STR(data_file_path, innobase_data_file_path,
 
8812
  PLUGIN_VAR_RQCMDARG | PLUGIN_VAR_READONLY,
 
8813
  "Path to individual files and their sizes.",
 
8814
  NULL, NULL, NULL);
 
8815
 
 
8816
static DRIZZLE_SYSVAR_LONG(autoinc_lock_mode, innobase_autoinc_lock_mode,
 
8817
  PLUGIN_VAR_RQCMDARG | PLUGIN_VAR_READONLY,
 
8818
  "The AUTOINC lock modes supported by InnoDB:               "
 
8819
  "0 => Old style AUTOINC locking (for backward"
 
8820
  " compatibility)                                           "
 
8821
  "1 => New style AUTOINC locking                            "
 
8822
  "2 => No AUTOINC locking (unsafe for SBR)",
 
8823
  NULL, NULL,
 
8824
  AUTOINC_NO_LOCKING, /* Default setting */
 
8825
  AUTOINC_OLD_STYLE_LOCKING,  /* Minimum value */
 
8826
  AUTOINC_NO_LOCKING, 0); /* Maximum value */
 
8827
 
 
8828
static DRIZZLE_SYSVAR_STR(version, innodb_version_str,
 
8829
  PLUGIN_VAR_NOCMDOPT | PLUGIN_VAR_READONLY,
 
8830
  "InnoDB version", NULL, NULL, INNODB_VERSION_STR);
 
8831
 
 
8832
static DRIZZLE_SYSVAR_BOOL(use_sys_malloc, srv_use_sys_malloc,
 
8833
  PLUGIN_VAR_NOCMDARG | PLUGIN_VAR_READONLY,
 
8834
  "Use OS memory allocator instead of InnoDB's internal memory allocator",
 
8835
  NULL, NULL, TRUE);
 
8836
 
 
8837
static DRIZZLE_SYSVAR_STR(change_buffering, innobase_change_buffering,
 
8838
  PLUGIN_VAR_RQCMDARG,
 
8839
  "Buffer changes to reduce random access: "
 
8840
  "OFF, ON, inserting, deleting, changing, or purging.",
 
8841
  innodb_change_buffering_validate,
 
8842
  innodb_change_buffering_update, NULL);
 
8843
 
 
8844
static DRIZZLE_SYSVAR_ULONG(read_ahead_threshold, srv_read_ahead_threshold,
 
8845
  PLUGIN_VAR_RQCMDARG,
 
8846
  "Number of pages that must be accessed sequentially for InnoDB to"
 
8847
  "trigger a readahead.",
 
8848
  NULL, NULL, 56, 0, 64, 0);
 
8849
 
 
8850
static drizzle_sys_var* innobase_system_variables[]= {
 
8851
  DRIZZLE_SYSVAR(additional_mem_pool_size),
 
8852
  DRIZZLE_SYSVAR(autoextend_increment),
 
8853
  DRIZZLE_SYSVAR(buffer_pool_size),
 
8854
  DRIZZLE_SYSVAR(checksums),
 
8855
  DRIZZLE_SYSVAR(commit_concurrency),
 
8856
  DRIZZLE_SYSVAR(concurrency_tickets),
 
8857
  DRIZZLE_SYSVAR(data_file_path),
 
8858
  DRIZZLE_SYSVAR(data_home_dir),
 
8859
  DRIZZLE_SYSVAR(doublewrite),
 
8860
  DRIZZLE_SYSVAR(fast_shutdown),
 
8861
  DRIZZLE_SYSVAR(file_io_threads),
 
8862
  DRIZZLE_SYSVAR(read_io_threads),
 
8863
  DRIZZLE_SYSVAR(write_io_threads),
 
8864
  DRIZZLE_SYSVAR(file_per_table),
 
8865
  DRIZZLE_SYSVAR(file_format),
 
8866
  DRIZZLE_SYSVAR(file_format_check),
 
8867
  DRIZZLE_SYSVAR(flush_log_at_trx_commit),
 
8868
  DRIZZLE_SYSVAR(flush_method),
 
8869
  DRIZZLE_SYSVAR(force_recovery),
 
8870
  DRIZZLE_SYSVAR(lock_wait_timeout),
 
8871
#ifdef UNIV_LOG_ARCHIVE
 
8872
  DRIZZLE_SYSVAR(log_arch_dir),
 
8873
  DRIZZLE_SYSVAR(log_archive),
 
8874
#endif /* UNIV_LOG_ARCHIVE */
 
8875
  DRIZZLE_SYSVAR(log_buffer_size),
 
8876
  DRIZZLE_SYSVAR(log_file_size),
 
8877
  DRIZZLE_SYSVAR(log_files_in_group),
 
8878
  DRIZZLE_SYSVAR(log_group_home_dir),
 
8879
  DRIZZLE_SYSVAR(max_dirty_pages_pct),
 
8880
  DRIZZLE_SYSVAR(max_purge_lag),
 
8881
  DRIZZLE_SYSVAR(adaptive_flushing),
 
8882
  DRIZZLE_SYSVAR(mirrored_log_groups),
 
8883
  DRIZZLE_SYSVAR(open_files),
 
8884
  DRIZZLE_SYSVAR(rollback_on_timeout),
 
8885
  DRIZZLE_SYSVAR(stats_on_metadata),
 
8886
  DRIZZLE_SYSVAR(stats_sample_pages),
 
8887
  DRIZZLE_SYSVAR(adaptive_hash_index),
 
8888
  DRIZZLE_SYSVAR(replication_delay),
 
8889
  DRIZZLE_SYSVAR(status_file),
 
8890
  DRIZZLE_SYSVAR(strict_mode),
 
8891
  DRIZZLE_SYSVAR(support_xa),
 
8892
  DRIZZLE_SYSVAR(sync_spin_loops),
 
8893
  DRIZZLE_SYSVAR(spin_wait_delay),
 
8894
  DRIZZLE_SYSVAR(table_locks),
 
8895
  DRIZZLE_SYSVAR(thread_concurrency),
 
8896
  DRIZZLE_SYSVAR(thread_sleep_delay),
 
8897
  DRIZZLE_SYSVAR(autoinc_lock_mode),
 
8898
  DRIZZLE_SYSVAR(version),
 
8899
  DRIZZLE_SYSVAR(use_sys_malloc),
 
8900
  DRIZZLE_SYSVAR(change_buffering),
 
8901
  DRIZZLE_SYSVAR(read_ahead_threshold),
 
8902
  DRIZZLE_SYSVAR(io_capacity),
 
8903
  NULL
 
8904
};
9366
8905
 
9367
8906
DRIZZLE_DECLARE_PLUGIN
9368
8907
{
9373
8912
  "Supports transactions, row-level locking, and foreign keys",
9374
8913
  PLUGIN_LICENSE_GPL,
9375
8914
  innobase_init, /* Plugin Init */
9376
 
  NULL, /* system variables */
9377
 
  init_options /* reserved */
 
8915
  innobase_system_variables, /* system variables */
 
8916
  NULL /* reserved */
9378
8917
}
9379
8918
DRIZZLE_DECLARE_PLUGIN_END;
9380
8919
 
9401
8940
  return res;
9402
8941
}
9403
8942
 
9404
 
/***********************************************************************
9405
 
This function checks each index name for a table against reserved
9406
 
system default primary index name 'GEN_CLUST_INDEX'. If a name matches,
9407
 
this function pushes an warning message to the client, and returns true. */
9408
 
extern "C" UNIV_INTERN
9409
 
bool
9410
 
innobase_index_name_is_reserved(
9411
 
/*============================*/
9412
 
                                        /* out: true if an index name
9413
 
                                        matches the reserved name */
9414
 
        const trx_t*    trx,            /* in: InnoDB transaction handle */
9415
 
        const KeyInfo*  key_info,       /* in: Indexes to be created */
9416
 
        ulint           num_of_keys)    /* in: Number of indexes to
9417
 
                                        be created. */
 
8943
/** @brief Initialize the default value of innodb_commit_concurrency.
 
8944
 
 
8945
Once InnoDB is running, the innodb_commit_concurrency must not change
 
8946
from zero to nonzero. (Bug #42101)
 
8947
 
 
8948
The initial default value is 0, and without this extra initialization,
 
8949
SET GLOBAL innodb_commit_concurrency=DEFAULT would set the parameter
 
8950
to 0, even if it was initially set to nonzero at the command line
 
8951
or configuration file. */
 
8952
static
 
8953
void
 
8954
innobase_commit_concurrency_init_default(void)
 
8955
/*==========================================*/
9418
8956
{
9419
 
  const KeyInfo*        key;
9420
 
  uint          key_num;        /* index number */
9421
 
 
9422
 
  for (key_num = 0; key_num < num_of_keys; key_num++) {
9423
 
    key = &key_info[key_num];
9424
 
 
9425
 
    if (innobase_strcasecmp(key->name,
9426
 
                            innobase_index_reserve_name) == 0) {
9427
 
      /* Push warning to drizzle */
9428
 
      push_warning_printf((Session*)trx->mysql_thd,
9429
 
                          DRIZZLE_ERROR::WARN_LEVEL_WARN,
9430
 
                          ER_WRONG_NAME_FOR_INDEX,
9431
 
                          "Cannot Create Index with name "
9432
 
                          "'%s'. The name is reserved "
9433
 
                          "for the system default primary "
9434
 
                          "index.",
9435
 
                          innobase_index_reserve_name);
9436
 
 
9437
 
      my_error(ER_WRONG_NAME_FOR_INDEX, MYF(0),
9438
 
               innobase_index_reserve_name);
9439
 
 
9440
 
      return(true);
9441
 
    }
9442
 
  }
9443
 
 
9444
 
  return(false);
 
8957
  DRIZZLE_SYSVAR_NAME(commit_concurrency).def_val
 
8958
    = innobase_commit_concurrency;
9445
8959
}
9446
8960
 
9447
8961
#ifdef UNIV_COMPILE_TEST_FUNCS