~drizzle-trunk/drizzle/development

« back to all changes in this revision

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

  • Committer: Patrick Crews
  • Date: 2010-08-09 16:31:29 UTC
  • mto: (1711.1.21 build)
  • mto: This revision was merged to the branch mainline in revision 1714.
  • Revision ID: gleebix@gmail.com-20100809163129-jh0jlwejpuefjrok
Updated test results with changes due to optimizer bug fix.  EXPLAIN output now includes 'Using where' for several queries that didn't previously have this output

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
89
 
73
90
#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
91
 
83
92
/** @file ha_innodb.cc */
84
93
 
85
94
/* Include necessary InnoDB headers */
86
95
extern "C" {
87
96
#include "univ.i"
88
 
#include "buf0lru.h"
89
97
#include "btr0sea.h"
90
98
#include "os0file.h"
91
99
#include "os0thread.h"
102
110
#include "log0log.h"
103
111
#include "lock0lock.h"
104
112
#include "dict0crea.h"
105
 
#include "create_replication.h"
106
113
#include "btr0cur.h"
107
114
#include "btr0btr.h"
108
115
#include "fsp0fsp.h"
120
127
 
121
128
#include "ha_innodb.h"
122
129
#include "data_dictionary.h"
123
 
#include "replication_dictionary.h"
124
130
#include "internal_dictionary.h"
125
131
#include "handler0vars.h"
126
132
 
129
135
#include <string>
130
136
 
131
137
#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
138
 
139
139
using namespace std;
140
140
using namespace drizzled;
141
141
 
 
142
#ifndef DRIZZLE_SERVER
 
143
/* This is needed because of Bug #3596.  Let us hope that pthread_mutex_t
 
144
is defined the same in both builds: the MySQL server and the InnoDB plugin. */
 
145
extern pthread_mutex_t LOCK_thread_count;
 
146
 
 
147
#endif /* DRIZZLE_SERVER */
 
148
 
142
149
/** to protect innobase_open_files */
143
150
static pthread_mutex_t innobase_share_mutex;
144
151
/** to force correct commit order in binlog */
170
177
static plugin::TableFunction* innodb_trx_tool= NULL;
171
178
static plugin::TableFunction* innodb_locks_tool= NULL;
172
179
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;
 
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
static ulong innobase_commit_concurrency = 0;
 
186
static ulong innobase_read_io_threads;
 
187
static ulong innobase_write_io_threads;
 
188
 
 
189
/**
 
190
 * @TODO: Turn this into size_t as soon as we have a Variable<size_t>
 
191
 */
 
192
static int64_t innobase_buffer_pool_size, innobase_log_file_size;
238
193
 
239
194
/* The default values for the following char* start-up parameters
240
195
are determined in innobase_init below: */
241
196
 
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;
 
197
static char*  innobase_data_home_dir      = NULL;
 
198
static char*  innobase_data_file_path     = NULL;
 
199
static char*  innobase_log_group_home_dir   = NULL;
 
200
static char*  innobase_file_format_name   = NULL;
 
201
static char*  innobase_change_buffering   = NULL;
 
202
 
 
203
/* Note: This variable can be set to on/off and any of the supported
 
204
file formats in the configuration file, but can only be set to any
 
205
of the supported file formats during runtime. */
 
206
static char*  innobase_file_format_check    = NULL;
 
207
 
 
208
/* The following has a misleading name: starting from 4.0.5, this also
 
209
affects Windows: */
 
210
static char*  innobase_unix_file_flush_method   = NULL;
252
211
 
253
212
/* Below we have boolean-valued start-up parameters, and their default
254
213
values */
255
214
 
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;
 
215
static ulong  innobase_fast_shutdown      = 1;
 
216
#ifdef UNIV_LOG_ARCHIVE
 
217
static my_bool  innobase_log_archive      = FALSE;
 
218
static char*  innobase_log_arch_dir     = NULL;
 
219
#endif /* UNIV_LOG_ARCHIVE */
272
220
static my_bool  innobase_use_doublewrite    = TRUE;
273
221
static my_bool  innobase_use_checksums      = TRUE;
274
222
static my_bool  innobase_rollback_on_timeout    = FALSE;
275
223
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;
 
224
static my_bool  innobase_stats_on_metadata    = TRUE;
281
225
 
282
226
static char*  internal_innobase_data_file_path  = NULL;
283
227
 
 
228
static char*  innodb_version_str = (char*) INNODB_VERSION_STR;
 
229
 
284
230
/* The following counter is used to convey information to InnoDB
285
231
about server activity: in selects it is not sensible to call
286
232
srv_active_wake_master_thread after each fetch or search, we only do
298
244
/** Allowed values of innodb_change_buffering */
299
245
static const char* innobase_change_buffering_values[IBUF_USE_COUNT] = {
300
246
  "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 */
 
247
  "inserts" /* IBUF_USE_INSERT */
306
248
};
307
249
 
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
250
/********************************************************************
313
251
Gives the file extension of an InnoDB single-table tablespace. */
314
252
static const char* ha_innobase_exts[] = {
358
296
      pthread_mutex_destroy(&commit_cond_m);
359
297
      pthread_cond_destroy(&commit_cond);
360
298
    }
361
 
    
362
 
    /* These get strdup'd from vm variables */
363
 
 
364
299
  }
365
300
 
366
301
private:
390
325
  {
391
326
    return doRollback(session, all); /* XA rollback just does a SQL ROLLBACK */
392
327
  }
393
 
  virtual uint64_t doGetCurrentTransactionId(Session *session);
394
 
  virtual uint64_t doGetNewTransactionId(Session *session);
395
328
  virtual int doCommit(Session* session, bool all);
396
329
  virtual int doRollback(Session* session, bool all);
397
330
 
435
368
        /* out: 0 or error number */
436
369
    ::drizzled::XID *xid);  /* in: X/Open XA transaction identification */
437
370
 
438
 
  virtual Cursor *create(Table &table)
 
371
  virtual Cursor *create(TableShare &table)
439
372
  {
440
373
    return new ha_innobase(*this, table);
441
374
  }
510
443
                           const TableIdentifier &identifier,
511
444
                           drizzled::message::Table &table_proto);
512
445
 
 
446
  void doGetTableNames(drizzled::CachedDirectory &directory,
 
447
                       const drizzled::SchemaIdentifier &schema_identifier,
 
448
                       std::set<std::string> &set_of_names);
 
449
 
513
450
  bool doDoesTableExist(drizzled::Session& session, const TableIdentifier &identifier);
514
451
 
515
452
  void doGetTableIdentifiers(drizzled::CachedDirectory &directory,
516
453
                             const drizzled::SchemaIdentifier &schema_identifier,
517
 
                             drizzled::TableIdentifier::vector &set_of_identifiers);
 
454
                             drizzled::TableIdentifiers &set_of_identifiers);
518
455
  bool validateCreateTableOption(const std::string &key, const std::string &state);
519
456
  void dropTemporarySchema();
520
457
 
543
480
 
544
481
void InnobaseEngine::doGetTableIdentifiers(drizzled::CachedDirectory &directory,
545
482
                                           const drizzled::SchemaIdentifier &schema_identifier,
546
 
                                           drizzled::TableIdentifier::vector &set_of_identifiers)
 
483
                                           drizzled::TableIdentifiers &set_of_identifiers)
547
484
{
548
485
  CachedDirectory::Entries entries= directory.getEntries();
549
486
 
562
499
    { }
563
500
    else
564
501
    {
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
 
      }
 
502
      char uname[NAME_LEN + 1];
 
503
      uint32_t file_name_len;
 
504
 
 
505
      file_name_len= TableIdentifier::filename_to_tablename(filename->c_str(), uname, sizeof(uname));
 
506
      // TODO: Remove need for memory copy here
 
507
      uname[file_name_len - sizeof(DEFAULT_FILE_EXTENSION) + 1]= '\0'; // Subtract ending, place NULL 
 
508
 
 
509
      set_of_identifiers.push_back(TableIdentifier(schema_identifier, uname));
580
510
    }
581
511
  }
582
512
}
586
516
  string proto_path(identifier.getPath());
587
517
  proto_path.append(DEFAULT_FILE_EXTENSION);
588
518
 
589
 
  if (session.getMessageCache().doesTableMessageExist(identifier))
 
519
  if (session.doesTableMessageExist(identifier))
590
520
    return true;
591
521
 
592
522
  if (access(proto_path.c_str(), F_OK))
605
535
  proto_path.append(DEFAULT_FILE_EXTENSION);
606
536
 
607
537
  // First we check the temporary tables.
608
 
  if (session.getMessageCache().getTableMessage(identifier, table_proto))
 
538
  if (session.getTableMessage(identifier, table_proto))
609
539
    return EEXIST;
610
540
 
611
541
  if (access(proto_path.c_str(), F_OK))
619
549
  return ENOENT;
620
550
}
621
551
 
 
552
void InnobaseEngine::doGetTableNames(CachedDirectory &directory, const SchemaIdentifier&, set<string>& set_of_names)
 
553
{
 
554
  CachedDirectory::Entries entries= directory.getEntries();
 
555
 
 
556
  for (CachedDirectory::Entries::iterator entry_iter= entries.begin(); 
 
557
       entry_iter != entries.end(); ++entry_iter)
 
558
  {
 
559
    CachedDirectory::Entry *entry= *entry_iter;
 
560
    const string *filename= &entry->filename;
 
561
 
 
562
    assert(filename->size());
 
563
 
 
564
    const char *ext= strchr(filename->c_str(), '.');
 
565
 
 
566
    if (ext == NULL || my_strcasecmp(system_charset_info, ext, DEFAULT_FILE_EXTENSION) ||
 
567
        (filename->compare(0, strlen(TMP_FILE_PREFIX), TMP_FILE_PREFIX) == 0))
 
568
    { }
 
569
    else
 
570
    {
 
571
      char uname[NAME_LEN + 1];
 
572
      uint32_t file_name_len;
 
573
 
 
574
      file_name_len= TableIdentifier::filename_to_tablename(filename->c_str(), uname, sizeof(uname));
 
575
      // TODO: Remove need for memory copy here
 
576
      uname[file_name_len - sizeof(DEFAULT_FILE_EXTENSION) + 1]= '\0'; // Subtract ending, place NULL 
 
577
      set_of_names.insert(uname);
 
578
    }
 
579
  }
 
580
}
 
581
 
 
582
/** @brief Initialize the default value of innodb_commit_concurrency.
 
583
 
 
584
Once InnoDB is running, the innodb_commit_concurrency must not change
 
585
from zero to nonzero. (Bug #42101)
 
586
 
 
587
The initial default value is 0, and without this extra initialization,
 
588
SET GLOBAL innodb_commit_concurrency=DEFAULT would set the parameter
 
589
to 0, even if it was initially set to nonzero at the command line
 
590
or configuration file. */
 
591
static
 
592
void
 
593
innobase_commit_concurrency_init_default(void);
 
594
/*==========================================*/
622
595
 
623
596
/************************************************************//**
624
597
Validate the file format name and return its corresponding id.
631
604
            name */
632
605
/************************************************************//**
633
606
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(
 
607
sets the srv_check_file_format_at_startup variable.
 
608
@return true if one of  "on" or "off" */
 
609
static
 
610
bool
 
611
innobase_file_format_check_on_off(
 
612
/*==============================*/
 
613
  const char* format_check);    /*!< in: parameter value */
 
614
/************************************************************//**
 
615
Validate the file format check config parameters, as a side effect it
 
616
sets the srv_check_file_format_at_startup variable.
 
617
@return true if valid config value */
 
618
static
 
619
bool
 
620
innobase_file_format_check_validate(
639
621
/*================================*/
640
 
  const char* format_max);    /*!< in: parameter value */
 
622
  const char* format_check);    /*!< in: parameter value */
641
623
 
642
624
static const char innobase_engine_name[]= "InnoDB";
643
625
 
 
626
/*************************************************************//**
 
627
Check for a valid value of innobase_commit_concurrency.
 
628
@return 0 for valid innodb_commit_concurrency */
 
629
static
 
630
int
 
631
innobase_commit_concurrency_validate(
 
632
/*=================================*/
 
633
  Session*      , /*!< in: thread handle */
 
634
  drizzle_sys_var*  , /*!< in: pointer to system
 
635
            variable */
 
636
  void*       save, /*!< out: immediate result
 
637
            for update function */
 
638
  drizzle_value*    value)  /*!< in: incoming string */
 
639
{
 
640
  int64_t   intbuf;
 
641
  ulong   commit_concurrency;
 
642
 
 
643
  if (value->val_int(value, &intbuf)) {
 
644
    /* The value is NULL. That is invalid. */
 
645
    return(1);
 
646
  }
 
647
 
 
648
  *reinterpret_cast<ulong*>(save) = commit_concurrency
 
649
    = static_cast<ulong>(intbuf);
 
650
 
 
651
  /* Allow the value to be updated, as long as it remains zero
 
652
  or nonzero. */
 
653
  return(!(!commit_concurrency == !innobase_commit_concurrency));
 
654
}
 
655
 
 
656
static DRIZZLE_SessionVAR_BOOL(support_xa, PLUGIN_VAR_OPCMDARG,
 
657
  "Enable InnoDB support for the XA two-phase commit",
 
658
  /* check_func */ NULL, /* update_func */ NULL,
 
659
  /* default */ TRUE);
 
660
 
 
661
static DRIZZLE_SessionVAR_BOOL(table_locks, PLUGIN_VAR_OPCMDARG,
 
662
  "Enable InnoDB locking in LOCK TABLES",
 
663
  /* check_func */ NULL, /* update_func */ NULL,
 
664
  /* default */ TRUE);
 
665
 
 
666
static DRIZZLE_SessionVAR_BOOL(strict_mode, PLUGIN_VAR_OPCMDARG,
 
667
  "Use strict mode when evaluating create options.",
 
668
  NULL, NULL, FALSE);
 
669
 
 
670
static DRIZZLE_SessionVAR_ULONG(lock_wait_timeout, PLUGIN_VAR_RQCMDARG,
 
671
  "Timeout in seconds an InnoDB transaction may wait for a lock before being rolled back. Values above 100000000 disable the timeout.",
 
672
  NULL, NULL, 50, 1, 1024 * 1024 * 1024, 0);
 
673
 
644
674
 
645
675
/*****************************************************************//**
646
676
Commits a transaction in an InnoDB database. */
667
697
  (char*) &export_vars.innodb_buffer_pool_pages_misc,   SHOW_LONG},
668
698
  {"buffer_pool_pages_total",
669
699
  (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},
 
700
  {"buffer_pool_read_ahead_rnd",
 
701
  (char*) &export_vars.innodb_buffer_pool_read_ahead_rnd, SHOW_LONG},
 
702
  {"buffer_pool_read_ahead_seq",
 
703
  (char*) &export_vars.innodb_buffer_pool_read_ahead_seq, SHOW_LONG},
674
704
  {"buffer_pool_read_requests",
675
705
  (char*) &export_vars.innodb_buffer_pool_read_requests,  SHOW_LONG},
676
706
  {"buffer_pool_reads",
907
937
ibool
908
938
thd_supports_xa(
909
939
/*============*/
910
 
  void* )  /*!< in: thread handle (Session*), or NULL to query
 
940
  void* session)  /*!< in: thread handle (Session*), or NULL to query
911
941
        the global innodb_supports_xa */
912
942
{
913
 
  /* TODO: Add support here for per-session value */
914
 
  return(support_xa);
 
943
  return(SessionVAR((Session*) session, support_xa));
915
944
}
916
945
 
917
946
/******************************************************************//**
921
950
ulong
922
951
thd_lock_wait_timeout(
923
952
/*==================*/
924
 
  void*)  /*!< in: thread handle (Session*), or NULL to query
 
953
  void* session)  /*!< in: thread handle (Session*), or NULL to query
925
954
      the global innodb_lock_wait_timeout */
926
955
{
927
 
  /* TODO: Add support here for per-session value */
928
956
  /* According to <drizzle/plugin.h>, passing session == NULL
929
957
  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
 
        }
 
958
  return(SessionVAR((Session*) session, lock_wait_timeout));
945
959
}
946
960
 
947
961
/********************************************************************//**
956
970
  return *(trx_t**) session->getEngineData(innodb_engine_ptr);
957
971
}
958
972
 
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
973
/********************************************************************//**
979
974
Call this function when mysqld passes control to the client. That is to
980
975
avoid deadlocks on the adaptive hash S-latch possibly held by session. For more
1036
1031
  case DB_SUCCESS:
1037
1032
    return(0);
1038
1033
 
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
1034
  case DB_ERROR:
1055
1035
  default:
1056
1036
    return(-1); /* unspecified error */
1057
1037
 
1058
1038
  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
1039
    return(HA_ERR_FOUND_DUPP_KEY);
1066
1040
 
1067
1041
  case DB_FOREIGN_DUPLICATE_KEY:
1148
1122
    and the actual error code name could very well be different.
1149
1123
    This will require some monitoring, ie. the status
1150
1124
    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 */
 
1125
#ifdef ER_TOO_MANY_CONCURRENT_TRXS
 
1126
    return(ER_TOO_MANY_CONCURRENT_TRXS);
 
1127
#else
1160
1128
    return(HA_ERR_RECORD_FILE_FULL);
1161
 
#endif /* HA_ERR_TOO_MANY_CONCURRENT_TRXS */
 
1129
#endif
1162
1130
  case DB_UNSUPPORTED:
1163
1131
    return(HA_ERR_UNSUPPORTED);
1164
1132
  }
1165
1133
}
1166
1134
 
1167
1135
 
 
1136
 
 
1137
/*************************************************************//**
 
1138
If you want to print a session that is not associated with the current thread,
 
1139
you must call this function before reserving the InnoDB kernel_mutex, to
 
1140
protect Drizzle from setting session->query NULL. If you print a session of the
 
1141
current thread, we know that Drizzle cannot modify sesion->query, and it is
 
1142
not necessary to call this. Call innobase_mysql_end_print_arbitrary_thd()
 
1143
after you release the kernel_mutex.
 
1144
 
 
1145
DRIZZLE: Note, we didn't change this name to avoid more ifdef forking 
 
1146
         in non-Cursor code.
 
1147
 */
 
1148
extern "C" UNIV_INTERN
 
1149
void
 
1150
innobase_mysql_prepare_print_arbitrary_thd(void)
 
1151
/*============================================*/
 
1152
{
 
1153
  ut_ad(!mutex_own(&kernel_mutex));
 
1154
  pthread_mutex_lock(&LOCK_thread_count);
 
1155
}
 
1156
 
 
1157
/*************************************************************//**
 
1158
Releases the mutex reserved by innobase_mysql_prepare_print_arbitrary_thd().
 
1159
In the InnoDB latching order, the mutex sits right above the
 
1160
kernel_mutex.  In debug builds, we assert that the kernel_mutex is
 
1161
released before this function is invoked. 
 
1162
 
 
1163
DRIZZLE: Note, we didn't change this name to avoid more ifdef forking 
 
1164
         in non-Cursor code.
 
1165
*/
 
1166
extern "C" UNIV_INTERN
 
1167
void
 
1168
innobase_mysql_end_print_arbitrary_thd(void)
 
1169
/*========================================*/
 
1170
{
 
1171
  ut_ad(!mutex_own(&kernel_mutex));
 
1172
  pthread_mutex_unlock(&LOCK_thread_count);
 
1173
}
 
1174
 
1168
1175
/*************************************************************//**
1169
1176
Prints info of a Session object (== user session thread) to the given file. */
1170
1177
extern "C" UNIV_INTERN
1185
1192
          session->getSecurityContext().getIp().c_str(),
1186
1193
          session->getSecurityContext().getUser().c_str()
1187
1194
  );
1188
 
  fprintf(f, "\n%s", session->getQueryString()->c_str());
 
1195
  fprintf(f,
 
1196
          "\n%s", session->getQueryString().c_str()
 
1197
  );
1189
1198
  putc('\n', f);
1190
1199
}
1191
1200
 
1208
1217
  if (cs) {
1209
1218
    *mbminlen = cs->mbminlen;
1210
1219
    *mbmaxlen = cs->mbmaxlen;
1211
 
    ut_ad(*mbminlen < DATA_MBMAX);
1212
 
    ut_ad(*mbmaxlen < DATA_MBMAX);
1213
1220
  } else {
1214
1221
    ut_a(cset == 0);
1215
1222
    *mbminlen = *mbmaxlen = 0;
1277
1284
/*=================*/
1278
1285
  void* mysql_session)  /*!< in: MySQL thread handle */
1279
1286
{
1280
 
  return static_cast<Session*>(mysql_session)->charset();
 
1287
  return session_charset(static_cast<Session*>(mysql_session));
1281
1288
}
1282
1289
 
1283
1290
extern "C" UNIV_INTERN
1297
1304
  return pthread_mutex_init(fast_mutex, MY_MUTEX_INIT_FAST);
1298
1305
}
1299
1306
 
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
1307
#if defined (__WIN__) && defined (MYSQL_DYNAMIC_PLUGIN)
1314
1308
/*******************************************************************//**
1315
1309
Map an OS error to an errno value. The OS error number is stored in
1575
1569
  trx = trx_allocate_for_mysql();
1576
1570
 
1577
1571
  trx->mysql_thd = session;
 
1572
  trx->mysql_query_str = session->query.c_str();
1578
1573
 
1579
1574
  innobase_trx_init(session, trx);
1580
1575
 
1613
1608
Construct ha_innobase Cursor. */
1614
1609
UNIV_INTERN
1615
1610
ha_innobase::ha_innobase(plugin::StorageEngine &engine_arg,
1616
 
                         Table &table_arg)
 
1611
                         TableShare &table_arg)
1617
1612
  :Cursor(engine_arg, table_arg),
1618
1613
  primary_key(0), /* needs initialization because index_flags() may be called 
1619
1614
                     before this is set to the real value. It's ok to have any 
1804
1799
/*===============*/
1805
1800
  trx_t*  trx)  /*!< in: transaction */
1806
1801
{
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);
 
1802
  return(trx && trx->mysql_thd && session_killed((Session*) trx->mysql_thd));
1821
1803
}
1822
1804
 
1823
1805
/**************************************************************//**
1833
1815
  prebuilt->read_just_key = 0;
1834
1816
}
1835
1817
 
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
1818
/*********************************************************************//**
2041
1819
Opens an InnoDB database.
2042
1820
@return 0 on success, error code on failure */
2046
1824
/*==========*/
2047
1825
  module::Context &context) /*!< in: Drizzle Plugin Context */
2048
1826
{
 
1827
  static char current_dir[3];   /*!< Set if using current lib */
2049
1828
  int   err;
2050
1829
  bool    ret;
 
1830
  char    *default_path;
2051
1831
  uint    format_id;
2052
1832
  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
1833
 
2098
1834
  innodb_engine_ptr= actuall_engine_ptr= new InnobaseEngine(innobase_engine_name);
2099
1835
 
2117
1853
  }
2118
1854
#endif /* UNIV_DEBUG */
2119
1855
 
 
1856
  /* Check that values don't overflow on 32-bit systems. */
 
1857
  if (sizeof(ulint) == 4) {
 
1858
    if (innobase_buffer_pool_size > UINT32_MAX) {
 
1859
      errmsg_printf(ERRMSG_LVL_ERROR, 
 
1860
                    "innobase_buffer_pool_size can't be over 4GB"
 
1861
                    " on 32-bit systems");
 
1862
 
 
1863
      goto error;
 
1864
    }
 
1865
 
 
1866
    if (innobase_log_file_size > UINT32_MAX) {
 
1867
      errmsg_printf(ERRMSG_LVL_ERROR, 
 
1868
                    "innobase_log_file_size can't be over 4GB"
 
1869
                    " on 32-bit systems");
 
1870
 
 
1871
      goto error;
 
1872
    }
 
1873
  }
 
1874
 
2120
1875
  os_innodb_umask = (ulint)internal::my_umask;
2121
1876
 
 
1877
  /* First calculate the default path for innodb_data_home_dir etc.,
 
1878
    in case the user has not given any value.
 
1879
 
 
1880
    Note that when using the embedded server, the datadirectory is not
 
1881
    necessarily the current directory of this program. */
 
1882
 
 
1883
  /* It's better to use current lib, to keep paths short */
 
1884
  current_dir[0] = FN_CURLIB;
 
1885
  current_dir[1] = FN_LIBCHAR;
 
1886
  current_dir[2] = 0;
 
1887
  default_path = current_dir;
 
1888
 
 
1889
  ut_a(default_path);
 
1890
 
 
1891
  srv_set_thread_priorities = TRUE;
 
1892
  srv_query_thread_priority = QUERY_PRIOR;
2122
1893
 
2123
1894
  /* Set InnoDB initialization parameters according to the values
2124
1895
    read from MySQL .cnf file */
2127
1898
 
2128
1899
  /* The default dir for data files is the datadir of MySQL */
2129
1900
 
2130
 
  srv_data_home = (char *)innobase_data_home_dir.c_str();
 
1901
  srv_data_home = (innobase_data_home_dir ? innobase_data_home_dir :
 
1902
                   default_path);
2131
1903
 
2132
1904
  /* Set default InnoDB data file size to 10 MB and let it be
2133
1905
    auto-extending. Thus users can use InnoDB in >= 4.0 without having
2134
1906
    to specify any startup options. */
2135
1907
 
2136
 
  if (innobase_data_file_path.empty()) 
2137
 
  {
2138
 
    innobase_data_file_path= std::string("ibdata1:10M:autoextend");
 
1908
  if (!innobase_data_file_path) {
 
1909
    innobase_data_file_path = (char*) "ibdata1:10M:autoextend";
2139
1910
  }
2140
1911
 
2141
1912
  /* Since InnoDB edits the argument in the next call, we make another
2142
1913
    copy of it: */
2143
1914
 
2144
 
  internal_innobase_data_file_path = strdup(innobase_data_file_path.c_str());
 
1915
  internal_innobase_data_file_path = strdup(innobase_data_file_path);
2145
1916
 
2146
1917
  ret = (bool) srv_parse_data_file_paths_and_sizes(
2147
1918
                                                   internal_innobase_data_file_path);
2159
1930
 
2160
1931
  /* The default dir for log files is the datadir of MySQL */
2161
1932
 
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
 
  }
 
1933
  if (!innobase_log_group_home_dir) {
 
1934
    innobase_log_group_home_dir = default_path;
 
1935
  }
 
1936
 
 
1937
#ifdef UNIV_LOG_ARCHIVE
 
1938
  /* Since innodb_log_arch_dir has no relevance under MySQL,
 
1939
    starting from 4.0.6 we always set it the same as
 
1940
innodb_log_group_home_dir: */
 
1941
 
 
1942
  innobase_log_arch_dir = innobase_log_group_home_dir;
 
1943
 
 
1944
  srv_arch_dir = innobase_log_arch_dir;
 
1945
#endif /* UNIG_LOG_ARCHIVE */
2170
1946
 
2171
1947
  ret = (bool)
2172
 
    srv_parse_log_group_home_dirs((char *)innobase_log_group_home_dir.c_str());
 
1948
    srv_parse_log_group_home_dirs(innobase_log_group_home_dir);
2173
1949
 
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"));
 
1950
  if (ret == FALSE || innobase_mirrored_log_groups != 1) {
 
1951
    errmsg_printf(ERRMSG_LVL_ERROR, "syntax error in innodb_log_group_home_dir, or a "
 
1952
                  "wrong number of mirrored log groups");
2178
1953
 
2179
1954
    goto mem_free_and_error;
2180
1955
  }
2181
1956
 
2182
 
 
2183
1957
  /* Validate the file format by animal name */
2184
 
  if (vm.count("file-format"))
2185
 
  {
 
1958
  if (innobase_file_format_name != NULL) {
 
1959
 
2186
1960
    format_id = innobase_file_format_name_lookup(
2187
 
                                                 vm["file-format"].as<string>().c_str());
 
1961
                                                 innobase_file_format_name);
2188
1962
 
2189
1963
    if (format_id > DICT_TF_FORMAT_MAX) {
2190
1964
 
2193
1967
      goto mem_free_and_error;
2194
1968
    }
2195
1969
  } else {
2196
 
    /* Set it to the default file format id.*/
 
1970
    /* Set it to the default file format id. Though this
 
1971
      should never happen. */
2197
1972
    format_id = 0;
2198
1973
  }
2199
1974
 
2200
1975
  srv_file_format = format_id;
2201
1976
 
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
 
  {
 
1977
  /* Given the type of innobase_file_format_name we have little
 
1978
    choice but to cast away the constness from the returned name.
 
1979
    innobase_file_format_name is used in the MySQL set variable
 
1980
    interface and so can't be const. */
 
1981
 
 
1982
  innobase_file_format_name = 
 
1983
    (char*) trx_sys_file_format_id_to_name(format_id);
 
1984
 
 
1985
  /* Process innobase_file_format_check variable */
 
1986
  ut_a(innobase_file_format_check != NULL);
 
1987
 
 
1988
  /* As a side effect it will set srv_check_file_format_at_startup
 
1989
    on valid input. First we check for "on"/"off". */
 
1990
  if (!innobase_file_format_check_on_off(innobase_file_format_check)) {
 
1991
 
 
1992
    /* Did the user specify a format name that we support ?
 
1993
      As a side effect it will update the variable
 
1994
      srv_check_file_format_at_startup */
 
1995
    if (!innobase_file_format_check_validate(
 
1996
                                             innobase_file_format_check)) {
 
1997
 
 
1998
      errmsg_printf(ERRMSG_LVL_ERROR, "InnoDB: invalid "
 
1999
                    "innodb_file_format_check value: "
 
2000
                    "should be either 'on' or 'off' or "
 
2001
                    "any value up to %s or its "
 
2002
                    "equivalent numeric id",
 
2003
                    trx_sys_file_format_id_to_name(
 
2004
                                                   DICT_TF_FORMAT_MAX));
 
2005
 
 
2006
      goto mem_free_and_error;
 
2007
    }
 
2008
  }
 
2009
 
 
2010
  if (innobase_change_buffering) {
2230
2011
    ulint use;
2231
2012
 
2232
2013
    for (use = 0;
2233
2014
         use < UT_ARR_SIZE(innobase_change_buffering_values);
2234
2015
         use++) {
2235
2016
      if (!innobase_strcasecmp(
2236
 
                               innobase_change_buffering.c_str(),
 
2017
                               innobase_change_buffering,
2237
2018
                               innobase_change_buffering_values[use])) {
2238
 
        ibuf_use = static_cast<ibuf_use_t>(use);
 
2019
        ibuf_use = (ibuf_use_t) use;
2239
2020
        goto innobase_change_buffering_inited_ok;
2240
2021
      }
2241
2022
    }
2242
2023
 
2243
2024
    errmsg_printf(ERRMSG_LVL_ERROR,
2244
2025
                  "InnoDB: invalid value "
2245
 
                  "innodb_change_buffering=%s",
2246
 
                  vm["change-buffering"].as<string>().c_str());
 
2026
                  "innodb_file_format_check=%s",
 
2027
                  innobase_change_buffering);
2247
2028
    goto mem_free_and_error;
2248
2029
  }
2249
2030
 
2250
2031
innobase_change_buffering_inited_ok:
2251
2032
  ut_a((ulint) ibuf_use < UT_ARR_SIZE(innobase_change_buffering_values));
2252
 
  innobase_change_buffering = innobase_change_buffering_values[ibuf_use];
 
2033
  innobase_change_buffering = (char*)
 
2034
    innobase_change_buffering_values[ibuf_use];
2253
2035
 
2254
2036
  /* --------------------------------------------------*/
2255
2037
 
2256
 
  if (vm.count("flush-method") != 0)
2257
 
  {
2258
 
    srv_file_flush_method_str = (char *)vm["flush-method"].as<string>().c_str();
2259
 
  }
 
2038
  srv_file_flush_method_str = innobase_unix_file_flush_method;
2260
2039
 
2261
2040
  srv_n_log_groups = (ulint) innobase_mirrored_log_groups;
2262
2041
  srv_n_log_files = (ulint) innobase_log_files_in_group;
2263
2042
  srv_log_file_size = (ulint) innobase_log_file_size;
2264
2043
 
 
2044
#ifdef UNIV_LOG_ARCHIVE
 
2045
  srv_log_archive_on = (ulint) innobase_log_archive;
 
2046
#endif /* UNIV_LOG_ARCHIVE */
2265
2047
  srv_log_buffer_size = (ulint) innobase_log_buffer_size;
2266
2048
 
2267
2049
  srv_buf_pool_size = (ulint) innobase_buffer_pool_size;
2268
 
  srv_buf_pool_instances = (ulint) innobase_buffer_pool_instances;
2269
2050
 
2270
2051
  srv_mem_pool_size = (ulint) innobase_additional_mem_pool_size;
2271
2052
 
 
2053
  srv_n_file_io_threads = (ulint) innobase_file_io_threads;
2272
2054
  srv_n_read_io_threads = (ulint) innobase_read_io_threads;
2273
2055
  srv_n_write_io_threads = (ulint) innobase_write_io_threads;
2274
2056
 
2296
2078
 
2297
2079
  data_mysql_default_charset_coll = (ulint)default_charset_info->number;
2298
2080
 
 
2081
 
 
2082
  innobase_commit_concurrency_init_default();
 
2083
 
2299
2084
  /* Since we in this module access directly the fields of a trx
2300
2085
    struct, and due to different headers and flags it might happen that
2301
2086
    mutex_t has a different size in this module and in InnoDB
2304
2089
 
2305
2090
  err = innobase_start_or_create_for_mysql();
2306
2091
 
2307
 
  if (err != DB_SUCCESS)
2308
 
  {
2309
 
    goto mem_free_and_error;
2310
 
  }
2311
 
 
2312
 
  err = dict_create_sys_replication_log();
2313
 
 
2314
2092
  if (err != DB_SUCCESS) {
2315
2093
    goto mem_free_and_error;
2316
2094
  }
2317
2095
 
2318
 
 
2319
 
  innobase_old_blocks_pct = buf_LRU_old_ratio_update(innobase_old_blocks_pct.get(),
2320
 
                                                     TRUE);
2321
 
 
2322
2096
  innobase_open_tables = hash_create(200);
2323
2097
  pthread_mutex_init(&innobase_share_mutex, MY_MUTEX_INIT_FAST);
2324
2098
  pthread_mutex_init(&prepare_commit_mutex, MY_MUTEX_INIT_FAST);
2356
2130
  innodb_lock_waits_tool= new(std::nothrow)InnodbTrxTool("INNODB_LOCK_WAITS");
2357
2131
  context.add(innodb_lock_waits_tool);
2358
2132
 
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
2133
  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));
 
2134
 
2471
2135
  /* 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);
 
2136
  innobase_file_format_check = (char*) trx_sys_file_format_max_get();
2474
2137
 
2475
2138
  return(FALSE);
2476
2139
error:
2579
2242
    Note, the position is current because of
2580
2243
    prepare_commit_mutex */
2581
2244
retry:
2582
 
    if (innobase_commit_concurrency.get() > 0) {
 
2245
    if (innobase_commit_concurrency > 0) {
2583
2246
      pthread_mutex_lock(&commit_cond_m);
2584
2247
      commit_threads++;
2585
2248
 
2586
 
      if (commit_threads > innobase_commit_concurrency.get()) {
 
2249
      if (commit_threads > innobase_commit_concurrency) {
2587
2250
        commit_threads--;
2588
2251
        pthread_cond_wait(&commit_cond,
2589
2252
          &commit_cond_m);
2608
2271
    innobase_commit_low(trx);
2609
2272
    trx->flush_log_later = FALSE;
2610
2273
 
2611
 
    if (innobase_commit_concurrency.get() > 0) {
 
2274
    if (innobase_commit_concurrency > 0) {
2612
2275
      pthread_mutex_lock(&commit_cond_m);
2613
2276
      commit_threads--;
2614
2277
      pthread_cond_signal(&commit_cond);
2632
2295
    SQL statement */
2633
2296
 
2634
2297
    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
2298
  }
2644
2299
 
2645
2300
  trx->n_autoinc_rows = 0; /* Reset the number AUTO-INC rows required */
2654
2309
  threads: */
2655
2310
  srv_active_wake_master_thread();
2656
2311
 
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
2312
  return(0);
2666
2313
}
2667
2314
 
2689
2336
 
2690
2337
  innobase_release_stat_resources(trx);
2691
2338
 
2692
 
  trx->n_autoinc_rows = 0;
2693
 
 
2694
2339
  /* If we had reserved the auto-inc lock for some table (if
2695
2340
  we come here to roll back the latest SQL statement) we
2696
2341
  release it now before a possibly lengthy rollback */
2705
2350
    error = trx_rollback_last_sql_stat_for_mysql(trx);
2706
2351
  }
2707
2352
 
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
2353
  return(convert_error_code_to_mysql(error, 0, NULL));
2717
2354
}
2718
2355
 
2849
2486
 
2850
2487
  ut_a(trx);
2851
2488
 
2852
 
  assert(session->getKilled() != Session::NOT_KILLED ||
 
2489
  assert(session->killed != Session::NOT_KILLED ||
2853
2490
         trx->conc_state == TRX_NOT_STARTED);
2854
2491
 
2855
2492
  /* Warn if rolling back some things... */
2856
 
  if (session->getKilled() != Session::NOT_KILLED &&
 
2493
  if (session->killed != Session::NOT_KILLED &&
2857
2494
      trx->conc_state != TRX_NOT_STARTED &&
2858
 
      trx->undo_no > 0 &&
 
2495
      trx->undo_no.low > 0 &&
2859
2496
      global_system_variables.log_warnings)
2860
2497
  {
2861
 
      errmsg_printf(ERRMSG_LVL_WARN,
 
2498
      errmsg_printf(ERRMSG_LVL_WARN, 
2862
2499
      "Drizzle is closing a connection during a KILL operation\n"
2863
 
      "that has an active InnoDB transaction.  %llu row modifications will "
 
2500
      "that has an active InnoDB transaction.  %lu row modifications will "
2864
2501
      "roll back.\n",
2865
 
      (ullint) trx->undo_no);
 
2502
      (ulong) trx->undo_no.low);
2866
2503
  }
2867
2504
 
2868
2505
  innobase_rollback_trx(trx);
2985
2622
}
2986
2623
 
2987
2624
/********************************************************************//**
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
2625
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. */
 
2626
ha_innobase::open(). Therefore there's no need for a covering lock.
 
2627
@return DB_SUCCESS or error code */
3245
2628
UNIV_INTERN
3246
 
void
 
2629
ulint
3247
2630
ha_innobase::innobase_initialize_autoinc()
3248
2631
/*======================================*/
3249
2632
{
 
2633
  dict_index_t* index;
3250
2634
  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
 
 
 
2635
  const char* col_name;
 
2636
  ulint   error;
 
2637
 
 
2638
  col_name = table->found_next_number_field->field_name;
 
2639
  index = innobase_get_index(table->getShare()->next_number_index);
 
2640
 
 
2641
  /* Execute SELECT MAX(col_name) FROM TABLE; */
 
2642
  error = row_search_max_autoinc(index, col_name, &auto_inc);
 
2643
 
 
2644
  switch (error) {
 
2645
  case DB_SUCCESS:
 
2646
 
 
2647
    /* At the this stage we don't know the increment
 
2648
    or the offset, so use default inrement of 1. */
 
2649
    ++auto_inc;
 
2650
    break;
 
2651
 
 
2652
  case DB_RECORD_NOT_FOUND:
3261
2653
    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
 
    }
 
2654
    fprintf(stderr, "  InnoDB: MySQL and InnoDB data "
 
2655
      "dictionaries are out of sync.\n"
 
2656
      "InnoDB: Unable to find the AUTOINC column %s in the "
 
2657
      "InnoDB table %s.\n"
 
2658
      "InnoDB: We set the next AUTOINC column value to the "
 
2659
      "maximum possible value,\n"
 
2660
      "InnoDB: in effect disabling the AUTOINC next value "
 
2661
      "generation.\n"
 
2662
      "InnoDB: You can either set the next AUTOINC value "
 
2663
      "explicitly using ALTER TABLE\n"
 
2664
      "InnoDB: or fix the data dictionary by recreating "
 
2665
      "the table.\n",
 
2666
      col_name, index->table->name);
 
2667
 
 
2668
    auto_inc = 0xFFFFFFFFFFFFFFFFULL;
 
2669
    break;
 
2670
 
 
2671
  default:
 
2672
    return(error);
3340
2673
  }
3341
2674
 
3342
2675
  dict_table_autoinc_initialize(prebuilt->table, auto_inc);
 
2676
 
 
2677
  return(DB_SUCCESS);
3343
2678
}
3344
2679
 
3345
2680
/*****************************************************************//**
3359
2694
  UT_NOT_USED(mode);
3360
2695
  UT_NOT_USED(test_if_locked);
3361
2696
 
3362
 
  session= getTable()->in_use;
 
2697
  session= table->in_use;
3363
2698
 
3364
2699
  /* Under some cases Drizzle seems to call this function while
3365
2700
  holding btr_search_latch. This breaks the latching order as
3383
2718
  stored the string length as the first byte. */
3384
2719
 
3385
2720
  upd_and_key_val_buff_len =
3386
 
        getTable()->getShare()->stored_rec_length
3387
 
        + getTable()->getShare()->max_key_length
 
2721
        table->getShare()->stored_rec_length
 
2722
        + table->getShare()->max_key_length
3388
2723
        + MAX_REF_PARTS * 3;
3389
2724
 
3390
2725
  upd_buff.resize(upd_and_key_val_buff_len);
3447
2782
 
3448
2783
  prebuilt = row_create_prebuilt(ib_table);
3449
2784
 
3450
 
  prebuilt->mysql_row_len = getTable()->getShare()->stored_rec_length;
3451
 
  prebuilt->default_rec = getTable()->getDefaultValues();
 
2785
  prebuilt->mysql_row_len = table->getShare()->stored_rec_length;
 
2786
  prebuilt->default_rec = table->getDefaultValues();
3452
2787
  ut_ad(prebuilt->default_rec);
3453
2788
 
3454
2789
  /* Looks like MySQL-3.23 sometimes has primary key number != 0 */
3455
2790
 
3456
 
  primary_key = getTable()->getShare()->getPrimaryKey();
 
2791
  primary_key = table->getShare()->getPrimaryKey();
3457
2792
  key_used_on_scan = primary_key;
3458
2793
 
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
2794
  /* Allocate a buffer for a 'row reference'. A row reference is
3465
2795
  a string of bytes of length ref_length which uniquely specifies
3466
2796
  a row in our table. Note that MySQL may also compare two row
3468
2798
  of length ref_length! */
3469
2799
 
3470
2800
  if (!row_table_got_default_clust_index(ib_table)) {
 
2801
    if (primary_key >= MAX_KEY) {
 
2802
      errmsg_printf(ERRMSG_LVL_ERROR, "Table %s has a primary key in InnoDB data "
 
2803
          "dictionary, but not in MySQL!", identifier.getTableName().c_str());
 
2804
    }
3471
2805
 
3472
2806
    prebuilt->clust_index_was_generated = FALSE;
3473
2807
 
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
 
    }
 
2808
    /* MySQL allocates the buffer for ref. key_info->key_length
 
2809
    includes space for all key columns + one byte for each column
 
2810
    that may be NULL. ref_length must be as exact as possible to
 
2811
    save space, because all row reference buffers are allocated
 
2812
    based on ref_length. */
 
2813
 
 
2814
    ref_length = table->key_info[primary_key].key_length;
3528
2815
  } else {
3529
2816
    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());
 
2817
      errmsg_printf(ERRMSG_LVL_ERROR, "Table %s has no primary key in InnoDB data "
 
2818
          "dictionary, but has one in MySQL! If you "
 
2819
          "created the table with a MySQL version < "
 
2820
          "3.23.54 and did not define a primary key, "
 
2821
          "but defined a unique key with all non-NULL "
 
2822
          "columns, then MySQL internally treats that "
 
2823
          "key as the primary key. You can fix this "
 
2824
          "error by dump + DROP + CREATE + reimport "
 
2825
          "of the table.", identifier.getTableName().c_str());
3551
2826
    }
3552
2827
 
3553
2828
    prebuilt->clust_index_was_generated = TRUE;
3574
2849
  stats.block_size = 16 * 1024;
3575
2850
 
3576
2851
  /* Init table lock structure */
3577
 
  lock.init(&share->lock);
 
2852
  thr_lock_data_init(&share->lock, &lock);
3578
2853
 
3579
2854
  if (prebuilt->table) {
3580
2855
    /* We update the highest file format in the system table
3581
2856
    space, if this table has higher file format setting. */
3582
2857
 
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,
 
2858
    trx_sys_file_format_max_upgrade(
 
2859
      (const char**) &innobase_file_format_check,
3586
2860
      dict_table_get_format(prebuilt->table));
3587
 
    innobase_file_format_max= changed_file_format_max;
3588
2861
  }
3589
2862
 
 
2863
  info(HA_STATUS_NO_LOCK | HA_STATUS_VARIABLE | HA_STATUS_CONST);
 
2864
 
3590
2865
  /* Only if the table has an AUTOINC column. */
3591
 
  if (prebuilt->table != NULL && getTable()->found_next_number_field != NULL) {
 
2866
  if (prebuilt->table != NULL && table->found_next_number_field != NULL) {
 
2867
    ulint error;
3592
2868
 
3593
2869
    dict_table_autoinc_lock(prebuilt->table);
3594
2870
 
3598
2874
    autoinc value from a previous Drizzle open. */
3599
2875
    if (dict_table_autoinc_read(prebuilt->table) == 0) {
3600
2876
 
3601
 
      innobase_initialize_autoinc();
 
2877
      error = innobase_initialize_autoinc();
 
2878
      ut_a(error == DB_SUCCESS);
3602
2879
    }
3603
2880
 
3604
2881
    dict_table_autoinc_unlock(prebuilt->table);
3605
2882
  }
3606
2883
 
3607
 
  info(HA_STATUS_NO_LOCK | HA_STATUS_VARIABLE | HA_STATUS_CONST);
3608
 
 
3609
2884
  return(0);
3610
2885
}
3611
2886
 
3626
2901
{
3627
2902
  Session*  session;
3628
2903
 
3629
 
  session= getTable()->in_use;
 
2904
  session= table->in_use;
3630
2905
  if (session != NULL) {
3631
2906
    getTransactionalEngine()->releaseTemporaryLatches(session);
3632
2907
  }
3853
3128
  case DRIZZLE_TYPE_DATETIME:
3854
3129
  case DRIZZLE_TYPE_DATE:
3855
3130
  case DRIZZLE_TYPE_TIMESTAMP:
3856
 
  case DRIZZLE_TYPE_ENUM:
3857
3131
    return(DATA_INT);
3858
3132
  case DRIZZLE_TYPE_DOUBLE:
3859
3133
    return(DATA_DOUBLE);
3860
3134
  case DRIZZLE_TYPE_BLOB:
3861
 
    return(DATA_BLOB);
3862
 
  case DRIZZLE_TYPE_UUID:
3863
 
    return(DATA_FIXBINARY);
3864
 
  case DRIZZLE_TYPE_NULL:
 
3135
                return(DATA_BLOB);
 
3136
  default:
3865
3137
    ut_error;
3866
3138
  }
3867
3139
 
3910
3182
  uint    buff_len,/*!< in: buffer length */
3911
3183
  const unsigned char*  record)/*!< in: row in MySQL format */
3912
3184
{
3913
 
  KeyInfo*    key_info  = &getTable()->key_info[keynr];
 
3185
  KeyInfo*    key_info  = &table->key_info[keynr];
3914
3186
  KeyPartInfo*  key_part  = key_info->key_part;
3915
3187
  KeyPartInfo*  end   = key_part + key_info->key_parts;
3916
3188
  char*   buff_start  = buff;
3982
3254
      cs = field->charset();
3983
3255
 
3984
3256
      lenlen = (ulint)
3985
 
        (((Field_varstring*)field)->pack_length_no_ptr());
 
3257
        (((Field_varstring*)field)->length_bytes);
3986
3258
 
3987
3259
      data = row_mysql_read_true_varchar(&len,
3988
3260
        (byte*) (record
3989
 
        + (ulint)get_field_offset(getTable(), field)),
 
3261
        + (ulint)get_field_offset(table, field)),
3990
3262
        lenlen);
3991
3263
 
3992
3264
      true_len = len;
4049
3321
 
4050
3322
      blob_data = row_mysql_read_blob_ref(&blob_len,
4051
3323
        (byte*) (record
4052
 
        + (ulint)get_field_offset(getTable(), field)),
 
3324
        + (ulint)get_field_offset(table, field)),
4053
3325
          (ulint) field->pack_length());
4054
3326
 
4055
3327
      true_len = blob_len;
4056
3328
 
4057
 
      ut_a(get_field_offset(getTable(), field)
 
3329
      ut_a(get_field_offset(table, field)
4058
3330
        == key_part->offset);
4059
3331
 
4060
3332
      /* For multi byte character sets we need to calculate
4101
3373
      ulint     key_len;
4102
3374
      const unsigned char*    src_start;
4103
3375
      enum_field_types  real_type;
4104
 
      const CHARSET_INFO* cs= field->charset();
4105
3376
 
4106
3377
      key_len = key_part->length;
4107
3378
 
4123
3394
      memcpy(buff, src_start, true_len);
4124
3395
      buff += true_len;
4125
3396
 
4126
 
      /* Pad the unused space with spaces. */
 
3397
      /* Pad the unused space with spaces. Note that no
 
3398
      padding is ever needed for UCS-2 because in MySQL,
 
3399
      all UCS2 characters are 2 bytes, as MySQL does not
 
3400
      support surrogate pairs, which are needed to represent
 
3401
      characters in the range U+10000 to U+10FFFF. */
4127
3402
 
4128
3403
      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 */);
 
3404
        ulint pad_len = key_len - true_len;
 
3405
        memset(buff, ' ', pad_len);
4134
3406
        buff += pad_len;
4135
3407
      }
4136
3408
    }
4238
3510
 
4239
3511
  /* Note that in InnoDB, i is the column number. MySQL calls columns
4240
3512
  'fields'. */
4241
 
  for (i = 0; i < n_fields; i++)
 
3513
  for (i = 0; i < n_fields; i++) 
4242
3514
  {
4243
 
    const dict_col_t *col= &index->table->cols[i];
4244
3515
    templ = prebuilt->mysql_template + n_requested_fields;
4245
3516
    field = table->getField(i);
4246
3517
 
4288
3559
    templ->col_no = i;
4289
3560
 
4290
3561
    if (index == clust_index) {
4291
 
      templ->rec_field_no = dict_col_get_clust_pos(col, index);
 
3562
      templ->rec_field_no = dict_col_get_clust_pos(
 
3563
        &index->table->cols[i], index);
4292
3564
    } else {
4293
3565
      templ->rec_field_no = dict_index_get_nth_col_pos(
4294
3566
                index, i);
4317
3589
      mysql_prefix_len = templ->mysql_col_offset
4318
3590
        + templ->mysql_col_len;
4319
3591
    }
4320
 
    templ->type = col->mtype;
 
3592
    templ->type = index->table->cols[i].mtype;
4321
3593
    templ->mysql_type = (ulint)field->type();
4322
3594
 
4323
3595
    if (templ->mysql_type == DATA_MYSQL_TRUE_VARCHAR) {
4324
3596
      templ->mysql_length_bytes = (ulint)
4325
 
        (((Field_varstring*)field)->pack_length_no_ptr());
 
3597
        (((Field_varstring*)field)->length_bytes);
4326
3598
    }
4327
3599
 
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;
 
3600
    templ->charset = dtype_get_charset_coll(
 
3601
      index->table->cols[i].prtype);
 
3602
    templ->mbminlen = index->table->cols[i].mbminlen;
 
3603
    templ->mbmaxlen = index->table->cols[i].mbmaxlen;
 
3604
    templ->is_unsigned = index->table->cols[i].prtype
 
3605
              & DATA_UNSIGNED;
4332
3606
    if (templ->type == DATA_BLOB) {
4333
3607
      prebuilt->templ_contains_blob = TRUE;
4334
3608
    }
4353
3627
}
4354
3628
 
4355
3629
/********************************************************************//**
 
3630
Get the upper limit of the MySQL integral and floating-point type. */
 
3631
UNIV_INTERN
 
3632
uint64_t
 
3633
ha_innobase::innobase_get_int_col_max_value(
 
3634
/*========================================*/
 
3635
  const Field*  field)
 
3636
{
 
3637
  uint64_t  max_value = 0;
 
3638
 
 
3639
  switch(field->key_type()) {
 
3640
  /* TINY */
 
3641
  case HA_KEYTYPE_BINARY:
 
3642
    max_value = 0xFFULL;
 
3643
    break;
 
3644
  /* MEDIUM */
 
3645
  case HA_KEYTYPE_UINT24:
 
3646
    max_value = 0xFFFFFFULL;
 
3647
    break;
 
3648
  /* LONG */
 
3649
  case HA_KEYTYPE_ULONG_INT:
 
3650
    max_value = 0xFFFFFFFFULL;
 
3651
    break;
 
3652
  case HA_KEYTYPE_LONG_INT:
 
3653
    max_value = 0x7FFFFFFFULL;
 
3654
    break;
 
3655
  /* BIG */
 
3656
  case HA_KEYTYPE_ULONGLONG:
 
3657
    max_value = 0xFFFFFFFFFFFFFFFFULL;
 
3658
    break;
 
3659
  case HA_KEYTYPE_LONGLONG:
 
3660
    max_value = 0x7FFFFFFFFFFFFFFFULL;
 
3661
    break;
 
3662
  case HA_KEYTYPE_DOUBLE:
 
3663
    /* We use the maximum as per IEEE754-2008 standard, 2^53 */
 
3664
    max_value = 0x20000000000000ULL;
 
3665
    break;
 
3666
  default:
 
3667
    ut_error;
 
3668
  }
 
3669
 
 
3670
  return(max_value);
 
3671
}
 
3672
 
 
3673
/********************************************************************//**
4356
3674
This special handling is really to overcome the limitations of MySQL's
4357
3675
binlogging. We need to eliminate the non-determinism that will arise in
4358
3676
INSERT ... SELECT type of statements, since MySQL binlog only stores the
4503
3821
  num_write_row++;
4504
3822
 
4505
3823
  /* This is the case where the table has an auto-increment column */
4506
 
  if (getTable()->next_number_field && record == getTable()->getInsertRecord()) {
 
3824
  if (table->next_number_field && record == table->getInsertRecord()) {
4507
3825
 
4508
3826
    /* Reset the error code before calling
4509
3827
    innobase_get_auto_increment(). */
4510
3828
    prebuilt->autoinc_error = DB_SUCCESS;
4511
3829
 
4512
3830
    if ((error = update_auto_increment())) {
 
3831
 
4513
3832
      /* 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) {
 
3833
      if (prebuilt->autoinc_error != DB_SUCCESS) {
4523
3834
        error = (int) prebuilt->autoinc_error;
4524
3835
 
4525
3836
        goto report_error;
4539
3850
    /* Build the template used in converting quickly between
4540
3851
    the two database formats */
4541
3852
 
4542
 
    build_template(prebuilt, NULL, getTable(), ROW_MYSQL_WHOLE_ROW);
 
3853
    build_template(prebuilt, NULL, table,
 
3854
             ROW_MYSQL_WHOLE_ROW);
4543
3855
  }
4544
3856
 
4545
3857
  innodb_srv_conc_enter_innodb(prebuilt->trx);
4546
3858
 
4547
3859
  error = row_insert_for_mysql((byte*) record, prebuilt);
4548
3860
 
4549
 
  user_session->setXaId(trx->id);
4550
 
 
4551
3861
  /* Handle duplicate key errors */
4552
3862
  if (auto_inc_used) {
4553
3863
    ulint   err;
4565
3875
    /* We need the upper limit of the col type to check for
4566
3876
    whether we update the table autoinc counter or not. */
4567
3877
    col_max_value = innobase_get_int_col_max_value(
4568
 
      getTable()->next_number_field); 
 
3878
      table->next_number_field);
 
3879
 
4569
3880
    /* Get the value that MySQL attempted to store in the table.*/
4570
 
    auto_inc = getTable()->next_number_field->val_int();
 
3881
    auto_inc = table->next_number_field->val_int();
4571
3882
 
4572
3883
    switch (error) {
4573
3884
    case DB_DUPLICATE_KEY:
4603
3914
      update the table upper limit. Note: last_value
4604
3915
      will be 0 if get_auto_increment() was not called.*/
4605
3916
 
4606
 
      if (auto_inc >= prebuilt->autoinc_last_value) {
 
3917
      if (auto_inc <= col_max_value
 
3918
          && auto_inc >= prebuilt->autoinc_last_value) {
4607
3919
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
 
          }
 
3920
        ut_a(prebuilt->autoinc_increment > 0);
 
3921
 
 
3922
        uint64_t  need;
 
3923
        uint64_t  offset;
 
3924
 
 
3925
        offset = prebuilt->autoinc_offset;
 
3926
        need = prebuilt->autoinc_increment;
 
3927
 
 
3928
        auto_inc = innobase_next_autoinc(
 
3929
          auto_inc, need, offset, col_max_value);
 
3930
 
 
3931
        err = innobase_set_max_autoinc(auto_inc);
 
3932
 
 
3933
        if (err != DB_SUCCESS) {
 
3934
          error = err;
4629
3935
        }
4630
3936
      }
4631
3937
      break;
4726
4032
        o_ptr = row_mysql_read_true_varchar(
4727
4033
          &o_len, o_ptr,
4728
4034
          (ulint)
4729
 
          (((Field_varstring*)field)->pack_length_no_ptr()));
 
4035
          (((Field_varstring*)field)->length_bytes));
4730
4036
 
4731
4037
        n_ptr = row_mysql_read_true_varchar(
4732
4038
          &n_len, n_ptr,
4733
4039
          (ulint)
4734
 
          (((Field_varstring*)field)->pack_length_no_ptr()));
 
4040
          (((Field_varstring*)field)->length_bytes));
4735
4041
      }
4736
4042
 
4737
4043
      break;
4822
4128
  /* Build an update vector from the modified fields in the rows
4823
4129
  (uses upd_buff of the handle) */
4824
4130
 
4825
 
  calc_row_difference(uvect, (unsigned char*) old_row, new_row, getTable(),
 
4131
  calc_row_difference(uvect, (unsigned char*) old_row, new_row, table,
4826
4132
      &upd_buff[0], (ulint)upd_and_key_val_buff_len,
4827
4133
      prebuilt, user_session);
4828
4134
 
4831
4137
 
4832
4138
  ut_a(prebuilt->template_type == ROW_MYSQL_WHOLE_ROW);
4833
4139
 
4834
 
  if (getTable()->found_next_number_field)
 
4140
  if (table->found_next_number_field)
4835
4141
  {
4836
4142
    uint64_t  auto_inc;
4837
4143
    uint64_t  col_max_value;
4838
4144
 
4839
 
    auto_inc = getTable()->found_next_number_field->val_int();
 
4145
    auto_inc = table->found_next_number_field->val_int();
4840
4146
 
4841
4147
    /* We need the upper limit of the col type to check for
4842
4148
    whether we update the table autoinc counter or not. */
4843
4149
    col_max_value = innobase_get_int_col_max_value(
4844
 
      getTable()->found_next_number_field);
 
4150
      table->found_next_number_field);
4845
4151
 
4846
4152
    uint64_t current_autoinc;
4847
4153
    ulint autoinc_error= innobase_get_autoinc(&current_autoinc);
4869
4175
 
4870
4176
  error = row_update_for_mysql((byte*) old_row, prebuilt);
4871
4177
 
4872
 
  user_session->setXaId(trx->id);
4873
 
 
4874
4178
  /* We need to do some special AUTOINC handling for the following case:
4875
4179
 
4876
4180
  INSERT INTO t (c1,c2) VALUES(x,y) ON DUPLICATE KEY UPDATE ...
4880
4184
  value used in the INSERT statement.*/
4881
4185
 
4882
4186
  if (error == DB_SUCCESS
4883
 
      && getTable()->next_number_field
4884
 
      && new_row == getTable()->getInsertRecord()
 
4187
      && table->next_number_field
 
4188
      && new_row == table->getInsertRecord()
4885
4189
      && session_sql_command(user_session) == SQLCOM_INSERT
4886
4190
      && (trx->duplicates & (TRX_DUP_IGNORE | TRX_DUP_REPLACE))
4887
4191
    == TRX_DUP_IGNORE)  {
4889
4193
    uint64_t  auto_inc;
4890
4194
    uint64_t  col_max_value;
4891
4195
 
4892
 
    auto_inc = getTable()->next_number_field->val_int();
 
4196
    auto_inc = table->next_number_field->val_int();
4893
4197
 
4894
4198
    /* We need the upper limit of the col type to check for
4895
4199
    whether we update the table autoinc counter or not. */
4896
4200
    col_max_value = innobase_get_int_col_max_value(
4897
 
      getTable()->next_number_field);
 
4201
      table->next_number_field);
4898
4202
 
4899
4203
    if (auto_inc <= col_max_value && auto_inc != 0) {
4900
4204
 
4961
4265
 
4962
4266
  error = row_update_for_mysql((byte*) record, prebuilt);
4963
4267
 
4964
 
  user_session->setXaId(trx->id);
4965
 
 
4966
4268
  innodb_srv_conc_exit_innodb(trx);
4967
4269
 
4968
4270
  error = convert_error_code_to_mysql(
4996
4298
  case ROW_READ_WITH_LOCKS:
4997
4299
    if (!srv_locks_unsafe_for_binlog
4998
4300
        && prebuilt->trx->isolation_level
4999
 
        > TRX_ISO_READ_COMMITTED) {
 
4301
        != TRX_ISO_READ_COMMITTED) {
5000
4302
      break;
5001
4303
    }
5002
4304
    /* fall through */
5026
4328
ha_innobase::try_semi_consistent_read(bool yes)
5027
4329
/*===========================================*/
5028
4330
{
5029
 
  ut_a(prebuilt->trx == session_to_trx(getTable()->in_use));
 
4331
  ut_a(prebuilt->trx == session_to_trx(table->in_use));
5030
4332
 
5031
4333
  /* Row read type is set to semi consistent read if this was
5032
4334
  requested by the MySQL and either innodb_locks_unsafe_for_binlog
5035
4337
 
5036
4338
  if (yes
5037
4339
      && (srv_locks_unsafe_for_binlog
5038
 
    || prebuilt->trx->isolation_level <= TRX_ISO_READ_COMMITTED)) {
 
4340
    || prebuilt->trx->isolation_level == TRX_ISO_READ_COMMITTED)) {
5039
4341
    prebuilt->row_read_type = ROW_READ_TRY_SEMI_CONSISTENT;
5040
4342
  } else {
5041
4343
    prebuilt->row_read_type = ROW_READ_WITH_LOCKS;
5216
4518
 
5217
4519
  index = prebuilt->index;
5218
4520
 
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
4521
  /* Note that if the index for which the search template is built is not
5229
4522
  necessarily prebuilt->index, but can also be the clustered index */
5230
4523
 
5231
4524
  if (prebuilt->sql_stat_start) {
5232
 
    build_template(prebuilt, user_session, getTable(),
 
4525
    build_template(prebuilt, user_session, table,
5233
4526
             ROW_MYSQL_REC_FIELDS);
5234
4527
  }
5235
4528
 
5284
4577
  switch (ret) {
5285
4578
  case DB_SUCCESS:
5286
4579
    error = 0;
5287
 
    getTable()->status = 0;
 
4580
    table->status = 0;
5288
4581
    break;
5289
4582
  case DB_RECORD_NOT_FOUND:
5290
4583
    error = HA_ERR_KEY_NOT_FOUND;
5291
 
    getTable()->status = STATUS_NOT_FOUND;
 
4584
    table->status = STATUS_NOT_FOUND;
5292
4585
    break;
5293
4586
  case DB_END_OF_INDEX:
5294
4587
    error = HA_ERR_KEY_NOT_FOUND;
5295
 
    getTable()->status = STATUS_NOT_FOUND;
 
4588
    table->status = STATUS_NOT_FOUND;
5296
4589
    break;
5297
4590
  default:
5298
4591
    error = convert_error_code_to_mysql((int) ret,
5299
4592
                prebuilt->table->flags,
5300
4593
                user_session);
5301
 
    getTable()->status = STATUS_NOT_FOUND;
 
4594
    table->status = STATUS_NOT_FOUND;
5302
4595
    break;
5303
4596
  }
5304
4597
 
5337
4630
 
5338
4631
  ha_statistic_increment(&system_status_var::ha_read_key_count);
5339
4632
 
5340
 
  if (keynr != MAX_KEY && getTable()->getShare()->sizeKeys() > 0) 
 
4633
  ut_ad(user_session == table->in_use);
 
4634
  ut_a(prebuilt->trx == session_to_trx(user_session));
 
4635
 
 
4636
  if (keynr != MAX_KEY && table->getShare()->sizeKeys() > 0) 
5341
4637
  {
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
 
    }
 
4638
    index = dict_table_get_index_on_name(prebuilt->table,
 
4639
                                         table->getShare()->getTableProto()->indexes(keynr).name().c_str());
5365
4640
  } else {
5366
4641
    index = dict_table_get_first_index(prebuilt->table);
5367
4642
  }
5370
4645
    errmsg_printf(ERRMSG_LVL_ERROR, 
5371
4646
      "Innodb could not find key n:o %u with name %s "
5372
4647
      "from dict cache for table %s",
5373
 
      keynr, getTable()->getShare()->getTableProto()->indexes(keynr).name().c_str(),
 
4648
      keynr, table->getShare()->getTableProto()->indexes(keynr).name().c_str(),
5374
4649
      prebuilt->table->name);
5375
4650
  }
5376
4651
 
5398
4673
  if (UNIV_UNLIKELY(!prebuilt->index)) {
5399
4674
    errmsg_printf(ERRMSG_LVL_WARN, "InnoDB: change_active_index(%u) failed",
5400
4675
          keynr);
5401
 
    prebuilt->index_usable = FALSE;
5402
4676
    return(1);
5403
4677
  }
5404
4678
 
5406
4680
                 prebuilt->index);
5407
4681
 
5408
4682
  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);
 
4683
    errmsg_printf(ERRMSG_LVL_WARN,
 
4684
         "InnoDB: insufficient history for index %u",
 
4685
          keynr);
5413
4686
    /* The caller seems to ignore this.  Thus, we must check
5414
4687
    this again in row_search_for_mysql(). */
5415
4688
    return(2);
5428
4701
  the flag ROW_MYSQL_WHOLE_ROW below, but that caused unnecessary
5429
4702
  copying. Starting from MySQL-4.1 we use a more efficient flag here. */
5430
4703
 
5431
 
  build_template(prebuilt, user_session, getTable(), ROW_MYSQL_REC_FIELDS);
 
4704
  build_template(prebuilt, user_session, table, ROW_MYSQL_REC_FIELDS);
5432
4705
 
5433
4706
  return(0);
5434
4707
}
5488
4761
  switch (ret) {
5489
4762
  case DB_SUCCESS:
5490
4763
    error = 0;
5491
 
    getTable()->status = 0;
 
4764
    table->status = 0;
5492
4765
    break;
5493
4766
  case DB_RECORD_NOT_FOUND:
5494
4767
    error = HA_ERR_END_OF_FILE;
5495
 
    getTable()->status = STATUS_NOT_FOUND;
 
4768
    table->status = STATUS_NOT_FOUND;
5496
4769
    break;
5497
4770
  case DB_END_OF_INDEX:
5498
4771
    error = HA_ERR_END_OF_FILE;
5499
 
    getTable()->status = STATUS_NOT_FOUND;
 
4772
    table->status = STATUS_NOT_FOUND;
5500
4773
    break;
5501
4774
  default:
5502
4775
    error = convert_error_code_to_mysql(
5503
4776
      (int) ret, prebuilt->table->flags, user_session);
5504
 
    getTable()->status = STATUS_NOT_FOUND;
 
4777
    table->status = STATUS_NOT_FOUND;
5505
4778
    break;
5506
4779
  }
5507
4780
 
5696
4969
 
5697
4970
  ha_statistic_increment(&system_status_var::ha_read_rnd_count);
5698
4971
 
5699
 
  ut_a(prebuilt->trx == session_to_trx(getTable()->in_use));
 
4972
  ut_a(prebuilt->trx == session_to_trx(table->in_use));
5700
4973
 
5701
4974
  if (prebuilt->clust_index_was_generated) {
5702
4975
    /* No primary key was defined for the table and we
5742
5015
{
5743
5016
  uint    len;
5744
5017
 
5745
 
  ut_a(prebuilt->trx == session_to_trx(getTable()->in_use));
 
5018
  ut_a(prebuilt->trx == session_to_trx(table->in_use));
5746
5019
 
5747
5020
  if (prebuilt->clust_index_was_generated) {
5748
5021
    /* No primary key was defined for the table and we
5818
5091
 
5819
5092
    col_type = get_innobase_type_from_mysql_type(&unsigned_type,
5820
5093
                  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
5094
    if (field->null_ptr) {
5837
5095
      nulls_allowed = 0;
5838
5096
    } else {
5878
5136
    long_true_varchar = 0;
5879
5137
 
5880
5138
    if (field->type() == DRIZZLE_TYPE_VARCHAR) {
5881
 
      col_len -= ((Field_varstring*)field)->pack_length_no_ptr();
 
5139
      col_len -= ((Field_varstring*)field)->length_bytes;
5882
5140
 
5883
 
      if (((Field_varstring*)field)->pack_length_no_ptr() == 2) {
 
5141
      if (((Field_varstring*)field)->length_bytes == 2) {
5884
5142
        long_true_varchar = DATA_LONG_TRUE_VARCHAR;
5885
5143
      }
5886
5144
    }
5887
5145
 
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
5146
    dict_mem_table_add_col(table, table->heap,
5902
5147
      (char*) field->field_name,
5903
5148
      col_type,
5911
5156
 
5912
5157
  error = row_create_table_for_mysql(table, trx);
5913
5158
 
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
5159
  error = convert_error_code_to_mysql(error, flags, NULL);
5926
5160
 
5927
5161
  return(error);
5958
5192
 
5959
5193
  n_fields = key->key_parts;
5960
5194
 
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
5195
  ind_type = 0;
5965
5196
 
5966
5197
  if (key_num == form->getShare()->getPrimaryKey()) {
6013
5244
        && field->type() != DRIZZLE_TYPE_VARCHAR)
6014
5245
      || (field->type() == DRIZZLE_TYPE_VARCHAR
6015
5246
        && key_part->length < field->pack_length()
6016
 
        - ((Field_varstring*)field)->pack_length_no_ptr())) {
 
5247
        - ((Field_varstring*)field)->length_bytes)) {
6017
5248
 
6018
5249
      prefix_len = key_part->length;
6019
5250
 
6070
5301
  /* We pass 0 as the space id, and determine at a lower level the space
6071
5302
  id where to store the table */
6072
5303
 
6073
 
  index = dict_mem_index_create(table_name,
6074
 
                                innobase_index_reserve_name,
6075
 
                                0, DICT_CLUSTERED, 0);
 
5304
  index = dict_mem_index_create(table_name, "GEN_CLUST_INDEX",
 
5305
              0, DICT_CLUSTERED, 0);
6076
5306
 
6077
5307
  error = row_create_index_for_mysql(index, trx, NULL);
6078
5308
 
6138
5368
    modified by another thread while the table is being created. */
6139
5369
  const ulint file_format = srv_file_format;
6140
5370
  bool lex_identified_temp_table= (create_proto.type() == message::Table::TEMPORARY);
6141
 
  const char* stmt;
6142
 
  size_t stmt_len;
6143
5371
 
6144
5372
  const char *table_name= identifier.getPath().c_str();
6145
5373
 
6232
5460
# error "DICT_TF_ZSSIZE_MAX < 1"
6233
5461
#endif
6234
5462
 
6235
 
    if (strict_mode)
 
5463
    if (SessionVAR(&session, strict_mode))
6236
5464
    {
6237
5465
      if (! srv_file_per_table)
6238
5466
      {
6251
5479
                            "InnoDB: ROW_FORMAT=compressed requires innodb_file_format > Antelope.");
6252
5480
      }
6253
5481
    }
 
5482
 
 
5483
    error= create_table_def(trx, &form, norm_name,
 
5484
                            lex_identified_temp_table ? name2 : NULL,
 
5485
                            iflags);
 
5486
  }
 
5487
 
 
5488
  if (error) {
 
5489
    goto cleanup;
6254
5490
  }
6255
5491
 
6256
5492
  /* Look for a primary key */
6259
5495
                   (int) form.getShare()->getPrimaryKey() :
6260
5496
                   -1);
6261
5497
 
6262
 
  /* Our function innobase_get_mysql_key_number_for_index assumes
 
5498
  /* Our function row_get_mysql_key_number_for_index assumes
6263
5499
    the primary key is always number 0, if it exists */
6264
5500
 
6265
5501
  assert(primary_key_no == -1 || primary_key_no == 0);
6266
5502
 
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
5503
  /* Create the keys */
6289
5504
 
6290
5505
  if (form.getShare()->sizeKeys() == 0 || primary_key_no == -1) {
6316
5531
    }
6317
5532
  }
6318
5533
 
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
 
 
 
5534
  if (trx->mysql_query_str) {
6333
5535
    error = row_table_add_foreign_constraints(trx,
6334
 
                                              query, strlen(query),
6335
 
                                              norm_name,
 
5536
                                              trx->mysql_query_str, norm_name,
6336
5537
                                              lex_identified_temp_table);
6337
5538
 
6338
5539
    error = convert_error_code_to_mysql(error, iflags, NULL);
6360
5561
    /* We update the highest file format in the system table
6361
5562
      space, if this table has higher file format setting. */
6362
5563
 
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,
6366
 
      dict_table_get_format(innobase_table));
6367
 
    innobase_file_format_max= changed_file_format_max;
 
5564
    trx_sys_file_format_max_upgrade((const char**) &innobase_file_format_check,
 
5565
                                    dict_table_get_format(innobase_table));
6368
5566
  }
6369
5567
 
6370
5568
  /* Note: We can't call update_session() as prebuilt will not be
6371
5569
    setup at this stage and so we use session. */
6372
5570
 
6373
5571
  /* 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. */
 
5572
    this is an ALTER TABLE. */
6376
5573
 
6377
5574
  if ((create_proto.options().has_auto_increment_value()
6378
 
       || session_sql_command(&session) == SQLCOM_ALTER_TABLE
6379
 
       || session_sql_command(&session) == SQLCOM_CREATE_INDEX)
 
5575
       || session_sql_command(&session) == SQLCOM_ALTER_TABLE)
6380
5576
      && create_proto.options().auto_increment_value() != 0) {
6381
5577
 
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. */
 
5578
    /* Query was ALTER TABLE...AUTO_INCREMENT = x; or
 
5579
      CREATE TABLE ...AUTO_INCREMENT = x; Find out a table
 
5580
      definition from the dictionary and get the current value
 
5581
      of the auto increment field. Set a new value to the
 
5582
      auto increment field if the value is greater than the
 
5583
      maximum value in the column. */
6390
5584
 
6391
5585
    auto_inc_value = create_proto.options().auto_increment_value();
6392
5586
 
6404
5598
 
6405
5599
  if (lex_identified_temp_table)
6406
5600
  {
6407
 
    session.getMessageCache().storeTableMessage(identifier, create_proto);
 
5601
    session.storeTableMessage(identifier, create_proto);
6408
5602
  }
6409
5603
  else
6410
5604
  {
6438
5632
 
6439
5633
  ut_a(prebuilt->trx);
6440
5634
  ut_a(prebuilt->trx->magic_n == TRX_MAGIC_N);
6441
 
  ut_a(prebuilt->trx == session_to_trx(getTable()->in_use));
 
5635
  ut_a(prebuilt->trx == session_to_trx(table->in_use));
6442
5636
 
6443
5637
  dict_table = prebuilt->table;
6444
5638
  trx = prebuilt->trx;
6467
5661
  /* Get the transaction associated with the current session, or create one
6468
5662
  if not yet created, and update prebuilt->trx */
6469
5663
 
6470
 
  update_session(getTable()->in_use);
 
5664
  update_session(table->in_use);
6471
5665
 
6472
5666
  if (session_sql_command(user_session) != SQLCOM_TRUNCATE) {
6473
5667
  fallback:
6536
5730
                                   session_sql_command(&session)
6537
5731
                                   == SQLCOM_DROP_DB);
6538
5732
 
6539
 
  session.setXaId(trx->id);
6540
 
 
6541
5733
  /* Flush the log to reduce probability that the .frm files and
6542
5734
    the InnoDB data dictionary get out-of-sync if the user runs
6543
5735
    with innodb_flush_log_at_trx_commit = 0 */
6560
5752
  {
6561
5753
    if (identifier.getType() == message::Table::TEMPORARY)
6562
5754
    {
6563
 
      session.getMessageCache().removeTableMessage(identifier);
 
5755
      session.removeTableMessage(identifier);
6564
5756
      ulint sql_command = session_sql_command(&session);
6565
5757
 
6566
5758
      // If this was the final removal to an alter table then we will need
6653
5845
  trx = trx_allocate_for_mysql();
6654
5846
 
6655
5847
  trx->mysql_thd = NULL;
 
5848
  trx->mysql_query_str = NULL;
6656
5849
 
6657
5850
  trx->check_foreigns = false;
6658
5851
  trx->check_unique_secondary = false;
6736
5929
  // definition needs to be updated.
6737
5930
  if (to.getType() == message::Table::TEMPORARY && from.getType() == message::Table::TEMPORARY)
6738
5931
  {
6739
 
    session.getMessageCache().renameTableMessage(from, to);
 
5932
    session.renameTableMessage(from, to);
6740
5933
    return 0;
6741
5934
  }
6742
5935
 
6758
5951
 
6759
5952
  error = innobase_rename_table(trx, from.getPath().c_str(), to.getPath().c_str(), TRUE);
6760
5953
 
6761
 
  session.setXaId(trx->id);
6762
 
 
6763
5954
  /* Tell the InnoDB server that there might be work for
6764
5955
    utility threads: */
6765
5956
 
6768
5959
  innobase_commit_low(trx);
6769
5960
  trx_free_for_mysql(trx);
6770
5961
 
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
5962
  error = convert_error_code_to_mysql(error, 0, NULL);
6789
5963
 
6790
5964
  if (not error)
6812
5986
  KeyInfo*    key;
6813
5987
  dict_index_t* index;
6814
5988
  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;
 
5989
              table->getShare()->stored_rec_length
 
5990
          + table->getShare()->max_key_length + 100);
 
5991
  ulint   buff2_len = table->getShare()->stored_rec_length
 
5992
          + table->getShare()->max_key_length + 100;
6819
5993
  dtuple_t* range_start;
6820
5994
  dtuple_t* range_end;
6821
5995
  ib_int64_t  n_rows;
6823
5997
  ulint   mode2;
6824
5998
  mem_heap_t* heap;
6825
5999
 
6826
 
  ut_a(prebuilt->trx == session_to_trx(getTable()->in_use));
 
6000
  ut_a(prebuilt->trx == session_to_trx(table->in_use));
6827
6001
 
6828
6002
  prebuilt->trx->op_info = (char*)"estimating records in index range";
6829
6003
 
6834
6008
 
6835
6009
  active_index = keynr;
6836
6010
 
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
 
  }
 
6011
  key = &table->key_info[active_index];
 
6012
 
 
6013
  index = dict_table_get_index_on_name(prebuilt->table, table->getShare()->getTableProto()->indexes(active_index).name().c_str());
 
6014
 
 
6015
  /* MySQL knows about this index and so we must be able to find it.*/
 
6016
  ut_a(index);
6853
6017
 
6854
6018
  heap = mem_heap_create(2 * (key->key_parts * sizeof(dfield_t)
6855
6019
            + sizeof(dtuple_t)));
6894
6058
 
6895
6059
  mem_heap_free(heap);
6896
6060
 
6897
 
func_exit:
6898
6061
  free(key_val_buff2);
6899
6062
 
6900
6063
  prebuilt->trx->op_info = (char*)"";
6929
6092
  external_lock(). To be safe, update the session of the current table
6930
6093
  handle. */
6931
6094
 
6932
 
  update_session(getTable()->in_use);
 
6095
  update_session(table->in_use);
6933
6096
 
6934
6097
  prebuilt->trx->op_info = (char*)
6935
6098
         "calculating upper bound for table rows";
6993
6156
  ha_rows total_rows;
6994
6157
  double  time_for_scan;
6995
6158
 
6996
 
  if (index != getTable()->getShare()->getPrimaryKey()) {
 
6159
  if (index != table->getShare()->getPrimaryKey()) {
6997
6160
    /* Not clustered */
6998
6161
    return(Cursor::read_time(index, ranges, rows));
6999
6162
  }
7017
6180
}
7018
6181
 
7019
6182
/*********************************************************************//**
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
6183
Returns statistics information of the table to the MySQL interpreter,
7122
6184
in various fields of the handle object. */
7123
6185
UNIV_INTERN
7130
6192
  dict_index_t* index;
7131
6193
  ha_rows   rec_per_key;
7132
6194
  ib_int64_t  n_rows;
 
6195
  ulong   j;
 
6196
  ulong   i;
 
6197
  char    path[FN_REFLEN];
7133
6198
  os_file_stat_t  stat_info;
7134
6199
 
7135
6200
  /* If we are forcing recovery at a high level, we will suppress
7136
6201
  statistics calculation on tables, because that may crash the
7137
6202
  server if an index is badly corrupted. */
7138
6203
 
 
6204
  if (srv_force_recovery >= SRV_FORCE_NO_IBUF_MERGE) {
 
6205
 
 
6206
    /* We return success (0) instead of HA_ERR_CRASHED,
 
6207
    because we want MySQL to process this query and not
 
6208
    stop, like it would do if it received the error code
 
6209
    HA_ERR_CRASHED. */
 
6210
 
 
6211
    return(0);
 
6212
  }
 
6213
 
7139
6214
  /* We do not know if MySQL can call this function before calling
7140
6215
  external_lock(). To be safe, update the session of the current table
7141
6216
  handle. */
7142
6217
 
7143
 
  update_session(getTable()->in_use);
 
6218
  update_session(table->in_use);
7144
6219
 
7145
6220
  /* In case MySQL calls this in the middle of a SELECT query, release
7146
6221
  possible adaptive hash latch to avoid deadlocks of threads */
7152
6227
  ib_table = prebuilt->table;
7153
6228
 
7154
6229
  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");
 
6230
    if (innobase_stats_on_metadata) {
 
6231
      /* In sql_show we call with this flag: update
 
6232
      then statistics so that they are up-to-date */
 
6233
 
 
6234
      prebuilt->trx->op_info = "updating table statistics";
 
6235
 
 
6236
      dict_update_statistics(ib_table);
 
6237
 
 
6238
      prebuilt->trx->op_info = "returning various info to MySQL";
 
6239
    }
 
6240
 
 
6241
    snprintf(path, sizeof(path), "%s/%s%s",
 
6242
             data_home, ib_table->name, ".dfe");
 
6243
 
 
6244
    internal::unpack_filename(path,path);
7167
6245
 
7168
6246
    /* Note that we do not know the access time of the table,
7169
6247
    nor the CHECK TABLE time, nor the UPDATE or INSERT time. */
7170
6248
 
7171
 
    if (os_file_get_status(get_status_path.file_string().c_str(), &stat_info)) {
 
6249
    if (os_file_get_status(path,&stat_info)) {
7172
6250
      stats.create_time = (ulong) stat_info.ctime;
7173
6251
    }
7174
6252
  }
7227
6305
    acquiring latches inside InnoDB, we do not call it if we
7228
6306
    are asked by MySQL to avoid locking. Another reason to
7229
6307
    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 {
 
6308
    See Bug#38185.
 
6309
    We do not update delete_length if no locking is requested
 
6310
    so the "old" value can remain. delete_length is initialized
 
6311
    to 0 in the ha_statistics' constructor. */
 
6312
    if (!(flag & HA_STATUS_NO_LOCK)) {
 
6313
 
7242
6314
      /* lock the data dictionary to avoid races with
7243
6315
      ibd_file_missing and tablespace_discarded */
7244
6316
      row_mysql_lock_data_dictionary(prebuilt->trx);
7254
6326
 
7255
6327
        Session*  session;
7256
6328
 
7257
 
        session= getTable()->in_use;
 
6329
        session= table->in_use;
7258
6330
        assert(session);
7259
6331
 
7260
6332
        push_warning_printf(
7284
6356
  }
7285
6357
 
7286
6358
  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;
 
6359
    index = dict_table_get_first_index(ib_table);
7292
6360
 
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);
 
6361
    if (prebuilt->clust_index_was_generated) {
 
6362
      index = dict_table_get_next_index(index);
7300
6363
    }
7301
6364
 
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
 
 
 
6365
    for (i = 0; i < table->getShare()->sizeKeys(); i++) {
7311
6366
      if (index == NULL) {
7312
6367
        errmsg_printf(ERRMSG_LVL_ERROR, "Table %s contains fewer "
7313
6368
            "indexes inside InnoDB than "
7321
6376
        break;
7322
6377
      }
7323
6378
 
7324
 
      for (j = 0; j < getTable()->key_info[i].key_parts; j++) {
 
6379
      for (j = 0; j < table->key_info[i].key_parts; j++) {
7325
6380
 
7326
6381
        if (j + 1 > index->n_uniq) {
7327
6382
          errmsg_printf(ERRMSG_LVL_ERROR, 
7336
6391
          break;
7337
6392
        }
7338
6393
 
7339
 
        dict_index_stat_mutex_enter(index);
7340
 
 
7341
6394
        if (index->stat_n_diff_key_vals[j + 1] == 0) {
7342
6395
 
7343
6396
          rec_per_key = stats.records;
7346
6399
           index->stat_n_diff_key_vals[j + 1]);
7347
6400
        }
7348
6401
 
7349
 
        dict_index_stat_mutex_exit(index);
7350
 
 
7351
6402
        /* Since MySQL seems to favor table scans
7352
6403
        too much over index searches, we pretend
7353
6404
        index selectivity is 2 times better than
7359
6410
          rec_per_key = 1;
7360
6411
        }
7361
6412
 
7362
 
        getTable()->key_info[i].rec_per_key[j]=
 
6413
        table->key_info[i].rec_per_key[j]=
7363
6414
          rec_per_key >= ~(ulong) 0 ? ~(ulong) 0 :
7364
6415
          (ulong) rec_per_key;
7365
6416
      }
 
6417
 
 
6418
      index = dict_table_get_next_index(index);
7366
6419
    }
7367
6420
  }
7368
6421
 
7369
 
  if (srv_force_recovery >= SRV_FORCE_NO_IBUF_MERGE) {
7370
 
    goto func_exit;
7371
 
  }
7372
 
 
7373
6422
  if (flag & HA_STATUS_ERRKEY) {
7374
6423
    const dict_index_t* err_index;
7375
6424
 
7380
6429
 
7381
6430
    if (err_index) {
7382
6431
      errkey = (unsigned int)
7383
 
        innobase_get_mysql_key_number_for_index(share, getTable(), ib_table,
7384
 
                                                err_index);
 
6432
        row_get_mysql_key_number_for_index(err_index);
7385
6433
    } else {
7386
6434
      errkey = (unsigned int) prebuilt->trx->error_key_num;
7387
6435
    }
7388
6436
  }
7389
6437
 
7390
 
  if ((flag & HA_STATUS_AUTO) && getTable()->found_next_number_field) {
 
6438
  if ((flag & HA_STATUS_AUTO) && table->found_next_number_field) {
7391
6439
    stats.auto_increment_value = innobase_peek_autoinc();
7392
6440
  }
7393
6441
 
7394
 
func_exit:
7395
6442
  prebuilt->trx->op_info = (char*)"";
7396
6443
 
7397
6444
  return(0);
7424
6471
/*===============*/
7425
6472
  Session*  session)  /*!< in: user thread handle */
7426
6473
{
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;
 
6474
  ulint   ret;
7432
6475
 
7433
 
  assert(session == getTable()->in_use);
 
6476
  assert(session == table->in_use);
7434
6477
  ut_a(prebuilt->trx);
7435
6478
  ut_a(prebuilt->trx->magic_n == TRX_MAGIC_N);
7436
6479
  ut_a(prebuilt->trx == session_to_trx(session));
7439
6482
    /* Build the template; we will use a dummy template
7440
6483
    in index scans done in checking */
7441
6484
 
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);
 
6485
    build_template(prebuilt, NULL, table, ROW_MYSQL_WHOLE_ROW);
 
6486
  }
 
6487
 
 
6488
  ret = row_check_table_for_mysql(prebuilt);
 
6489
 
 
6490
  if (ret == DB_SUCCESS) {
 
6491
    return(HA_ADMIN_OK);
 
6492
  }
 
6493
 
 
6494
  return(HA_ADMIN_CORRUPT);
7579
6495
}
7580
6496
 
7581
6497
/*************************************************************//**
7601
6517
    return((char*)comment); /* string too long */
7602
6518
  }
7603
6519
 
7604
 
  update_session(getTable()->in_use);
 
6520
  update_session(table->in_use);
7605
6521
 
7606
6522
  prebuilt->trx->op_info = (char*)"returning table comment";
7607
6523
 
7672
6588
  external_lock(). To be safe, update the session of the current table
7673
6589
  handle. */
7674
6590
 
7675
 
  update_session(getTable()->in_use);
 
6591
  update_session(table->in_use);
7676
6592
 
7677
6593
  prebuilt->trx->op_info = (char*)"getting info on foreign keys";
7678
6594
 
7721
6637
  dict_foreign_t* foreign;
7722
6638
 
7723
6639
  ut_a(prebuilt != NULL);
7724
 
  update_session(getTable()->in_use);
 
6640
  update_session(table->in_use);
7725
6641
  prebuilt->trx->op_info = (char*)"getting list of foreign keys";
7726
6642
  trx_search_latch_release_if_reserved(prebuilt->trx);
7727
6643
  mutex_enter(&(dict_sys->mutex));
7859
6775
{
7860
6776
  bool  can_switch;
7861
6777
 
7862
 
  ut_a(prebuilt->trx == session_to_trx(getTable()->in_use));
 
6778
  ut_a(prebuilt->trx == session_to_trx(table->in_use));
7863
6779
 
7864
6780
  prebuilt->trx->op_info =
7865
6781
      "determining if there are foreign key constraints";
7947
6863
      either, because the calling threads may change.
7948
6864
      CAREFUL HERE, OR MEMORY CORRUPTION MAY OCCUR! */
7949
6865
    case HA_EXTRA_IGNORE_DUP_KEY:
7950
 
      session_to_trx(getTable()->in_use)->duplicates |= TRX_DUP_IGNORE;
 
6866
      session_to_trx(table->in_use)->duplicates |= TRX_DUP_IGNORE;
7951
6867
      break;
7952
6868
    case HA_EXTRA_WRITE_CAN_REPLACE:
7953
 
      session_to_trx(getTable()->in_use)->duplicates |= TRX_DUP_REPLACE;
 
6869
      session_to_trx(table->in_use)->duplicates |= TRX_DUP_REPLACE;
7954
6870
      break;
7955
6871
    case HA_EXTRA_WRITE_CANNOT_REPLACE:
7956
 
      session_to_trx(getTable()->in_use)->duplicates &= ~TRX_DUP_REPLACE;
 
6872
      session_to_trx(table->in_use)->duplicates &= ~TRX_DUP_REPLACE;
7957
6873
      break;
7958
6874
    case HA_EXTRA_NO_IGNORE_DUP_KEY:
7959
 
      session_to_trx(getTable()->in_use)->duplicates &=
 
6875
      session_to_trx(table->in_use)->duplicates &=
7960
6876
        ~(TRX_DUP_IGNORE | TRX_DUP_REPLACE);
7961
6877
      break;
7962
6878
    default:/* Do nothing */
8092
7008
{
8093
7009
  trx_t*      trx;
8094
7010
  static const char truncated_msg[] = "... truncated...\n";
8095
 
  const long    MAX_STATUS_SIZE = 1048576;
 
7011
  const long    MAX_STATUS_SIZE = 64000;
8096
7012
  ulint     trx_list_start = ULINT_UNDEFINED;
8097
7013
  ulint     trx_list_end = ULINT_UNDEFINED;
8098
7014
 
8110
7026
 
8111
7027
  mutex_enter(&srv_monitor_file_mutex);
8112
7028
  rewind(srv_monitor_file);
8113
 
  srv_printf_innodb_monitor(srv_monitor_file, FALSE,
 
7029
  srv_printf_innodb_monitor(srv_monitor_file,
8114
7030
        &trx_list_start, &trx_list_end);
8115
7031
  flen = ftell(srv_monitor_file);
8116
7032
  os_file_set_eof(srv_monitor_file);
8121
7037
 
8122
7038
  if (flen > MAX_STATUS_SIZE) {
8123
7039
    usable_len = MAX_STATUS_SIZE;
8124
 
    srv_truncated_status_writes++;
8125
7040
  } else {
8126
7041
    usable_len = flen;
8127
7042
  }
8157
7072
 
8158
7073
  mutex_exit(&srv_monitor_file_mutex);
8159
7074
 
8160
 
  stat_print(session, innobase_engine_name, strlen(innobase_engine_name),
8161
 
             STRING_WITH_LEN(""), str, flen);
 
7075
  bool result = FALSE;
8162
7076
 
 
7077
  if (stat_print(session, innobase_engine_name, strlen(innobase_engine_name),
 
7078
      STRING_WITH_LEN(""), str, flen)) {
 
7079
    result= TRUE;
 
7080
  }
8163
7081
  free(str);
8164
7082
 
8165
7083
  return(FALSE);
8166
7084
}
8167
7085
 
8168
7086
/************************************************************************//**
8169
 
Implements the SHOW MUTEX STATUS command.
8170
 
@return true on failure false on success*/
 
7087
Implements the SHOW MUTEX STATUS command. . */
8171
7088
static
8172
7089
bool
8173
7090
innodb_mutex_show_status(
8175
7092
  plugin::StorageEngine*  engine,   /*!< in: the innodb StorageEngine */
8176
7093
  Session*  session,  /*!< in: the MySQL query thread of the
8177
7094
          caller */
8178
 
  stat_print_fn*  stat_print)   /*!< in: function for printing
8179
 
                                        statistics */
 
7095
  stat_print_fn*  stat_print)
8180
7096
{
8181
7097
  char buf1[IO_SIZE], buf2[IO_SIZE];
8182
7098
  mutex_t*  mutex;
8183
7099
  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
7100
#ifdef UNIV_DEBUG
8189
7101
  ulint   rw_lock_count= 0;
8190
7102
  ulint   rw_lock_count_spin_loop= 0;
8198
7110
 
8199
7111
  mutex_enter(&mutex_list_mutex);
8200
7112
 
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;
 
7113
  mutex = UT_LIST_GET_FIRST(mutex_list);
 
7114
 
 
7115
  while (mutex != NULL) {
 
7116
    if (mutex->count_os_wait == 0
 
7117
        || buf_pool_is_block_mutex(mutex)) {
 
7118
      goto next_mutex;
8212
7119
    }
8213
7120
#ifdef UNIV_DEBUG
8214
7121
    if (mutex->mutex_type != 1) {
8235
7142
          return(1);
8236
7143
        }
8237
7144
      }
8238
 
    } else {
 
7145
    }
 
7146
    else {
8239
7147
      rw_lock_count += mutex->count_using;
8240
7148
      rw_lock_count_spin_loop += mutex->count_spin_loop;
8241
7149
      rw_lock_count_spin_rounds += mutex->count_spin_rounds;
8247
7155
    buf1len= snprintf(buf1, sizeof(buf1), "%s:%lu",
8248
7156
          mutex->cfile_name, (ulong) mutex->cline);
8249
7157
    buf2len= snprintf(buf2, sizeof(buf2), "os_waits=%lu",
8250
 
                      (ulong) mutex->count_os_wait);
 
7158
          mutex->count_os_wait);
8251
7159
 
8252
7160
    if (stat_print(session, innobase_engine_name,
8253
7161
             engine_name_len, buf1, buf1len,
8256
7164
      return(1);
8257
7165
    }
8258
7166
#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
 
    }
 
7167
 
 
7168
next_mutex:
 
7169
    mutex = UT_LIST_GET_NEXT(list, mutex);
8276
7170
  }
8277
7171
 
8278
7172
  mutex_exit(&mutex_list_mutex);
8279
7173
 
8280
7174
  mutex_enter(&rw_lock_list_mutex);
8281
7175
 
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
 
    }
 
7176
  lock = UT_LIST_GET_FIRST(rw_lock_list);
 
7177
 
 
7178
  while (lock != NULL) {
 
7179
    if (lock->count_os_wait
 
7180
                    && !buf_pool_is_block_lock(lock)) {
 
7181
      buf1len= snprintf(buf1, sizeof(buf1), "%s:%lu",
 
7182
                                    lock->cfile_name, (unsigned long) lock->cline);
 
7183
      buf2len= snprintf(buf2, sizeof(buf2),
 
7184
                                    "os_waits=%lu", lock->count_os_wait);
 
7185
 
 
7186
      if (stat_print(session, innobase_engine_name,
 
7187
               engine_name_len, buf1, buf1len,
 
7188
               buf2, buf2len)) {
 
7189
        mutex_exit(&rw_lock_list_mutex);
 
7190
        return(1);
 
7191
      }
 
7192
    }
 
7193
    lock = UT_LIST_GET_NEXT(list, lock);
8322
7194
  }
8323
7195
 
8324
7196
  mutex_exit(&rw_lock_list_mutex);
8325
7197
 
8326
7198
#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));
 
7199
  buf2len= my_snprintf(buf2, sizeof(buf2),
 
7200
    "count=%lu, spin_waits=%lu, spin_rounds=%lu, "
 
7201
    "os_waits=%lu, os_yields=%lu, os_wait_times=%lu",
 
7202
    rw_lock_count, rw_lock_count_spin_loop,
 
7203
    rw_lock_count_spin_rounds,
 
7204
    rw_lock_count_os_wait, rw_lock_count_os_yield,
 
7205
    (ulong) (rw_lock_wait_time/1000));
8336
7206
 
8337
7207
  if (stat_print(session, innobase_engine_name, engine_name_len,
8338
7208
      STRING_WITH_LEN("rw_lock_mutexes"), buf2, buf2len)) {
8377
7247
        !strcmp(share->table_name, table_name));
8378
7248
 
8379
7249
  if (!share) {
 
7250
 
 
7251
    uint length = (uint) strlen(table_name);
 
7252
 
8380
7253
    /* TODO: invoke HASH_MIGRATE if innobase_open_tables
8381
7254
    grows too big */
8382
7255
 
8383
 
    share= new INNOBASE_SHARE(table_name);
 
7256
    share = (INNOBASE_SHARE *) malloc(sizeof(*share)+length+1);
 
7257
                memset(share, 0, sizeof(*share)+length+1);
 
7258
 
 
7259
    share->table_name = (char*) memcpy(share + 1,
 
7260
               table_name, length + 1);
8384
7261
 
8385
7262
    HASH_INSERT(INNOBASE_SHARE, table_name_hash,
8386
7263
          innobase_open_tables, fold, share);
8387
7264
 
8388
7265
    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
7266
  }
8395
7267
 
8396
7268
  share->use_count++;
8420
7292
 
8421
7293
    HASH_DELETE(INNOBASE_SHARE, table_name_hash,
8422
7294
          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;
 
7295
    thr_lock_delete(&share->lock);
 
7296
    free(share);
8429
7297
 
8430
7298
    /* TODO: invoke HASH_MIGRATE if innobase_open_tables
8431
7299
    shrinks too much */
8502
7370
    isolation_level = trx->isolation_level;
8503
7371
 
8504
7372
    if ((srv_locks_unsafe_for_binlog
8505
 
         || isolation_level <= TRX_ISO_READ_COMMITTED)
 
7373
         || isolation_level == TRX_ISO_READ_COMMITTED)
8506
7374
        && isolation_level != TRX_ISO_SERIALIZABLE
8507
7375
        && (lock_type == TL_READ || lock_type == TL_READ_NO_INSERT)
8508
7376
        && (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)) {
 
7377
      || sql_command == SQLCOM_UPDATE
 
7378
      || sql_command == SQLCOM_CREATE_TABLE)) {
8513
7379
 
8514
7380
      /* If we either have innobase_locks_unsafe_for_binlog
8515
7381
      option set or this session is using READ COMMITTED
8516
7382
      isolation level and isolation level of the transaction
8517
7383
      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. */
 
7384
      INSERT INTO...SELECT or UPDATE ... = (SELECT ...) or
 
7385
      CREATE  ... SELECT... without FOR UPDATE or
 
7386
      IN SHARE MODE in select, then we use consistent
 
7387
      read for select. */
8523
7388
 
8524
7389
      prebuilt->select_lock_type = LOCK_NONE;
8525
7390
      prebuilt->stored_select_lock_type = LOCK_NONE;
8598
7463
  *value = dict_table_autoinc_read(prebuilt->table);
8599
7464
 
8600
7465
  /* It should have been initialized during open. */
8601
 
  if (*value == 0) {
8602
 
    prebuilt->autoinc_error = DB_UNSUPPORTED;
8603
 
    dict_table_autoinc_unlock(prebuilt->table);
8604
 
  }
 
7466
  ut_a(*value != 0);
8605
7467
 
8606
7468
  return(DB_SUCCESS);
8607
7469
}
8608
7470
 
8609
7471
/*******************************************************************//**
8610
 
This function reads the global auto-inc counter. It doesn't use the
 
7472
This function reads the global auto-inc counter. It doesn't use the 
8611
7473
AUTOINC lock even if the lock mode is set to TRADITIONAL.
8612
7474
@return the autoinc value */
8613
7475
UNIV_INTERN
8627
7489
 
8628
7490
  auto_inc = dict_table_autoinc_read(innodb_table);
8629
7491
 
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
 
  }
 
7492
  ut_a(auto_inc > 0);
8635
7493
 
8636
7494
  dict_table_autoinc_unlock(innodb_table);
8637
7495
 
8660
7518
  uint64_t  autoinc = 0;
8661
7519
 
8662
7520
  /* Prepare prebuilt->trx in the table handle */
8663
 
  update_session(getTable()->in_use);
 
7521
  update_session(table->in_use);
8664
7522
 
8665
7523
  error = innobase_get_autoinc(&autoinc);
8666
7524
 
8684
7542
  invoking this method. So we are not sure if it's guaranteed to
8685
7543
  be 0 or not. */
8686
7544
 
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
7545
  /* Called for the first time ? */
8692
7546
  if (trx->n_autoinc_rows == 0) {
8693
7547
 
8704
7558
  /* Not in the middle of a mult-row INSERT. */
8705
7559
  } else if (prebuilt->autoinc_last_value == 0) {
8706
7560
    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
7561
  }
8713
7562
 
8714
7563
  *nb_reserved_values = trx->n_autoinc_rows;
8716
7565
  /* This all current style autoinc. */
8717
7566
  {
8718
7567
    uint64_t  need;
8719
 
    uint64_t  current;
8720
7568
    uint64_t  next_value;
8721
 
 
8722
 
    current = *first_value > col_max_value ? autoinc : *first_value;
 
7569
    uint64_t  col_max_value;
 
7570
 
 
7571
    /* We need the upper limit of the col type to check for
 
7572
    whether we update the table autoinc counter or not. */
 
7573
    col_max_value = innobase_get_int_col_max_value(
 
7574
      table->next_number_field);
 
7575
 
8723
7576
    need = *nb_reserved_values * increment;
8724
7577
 
8725
7578
    /* Compute the last value in the interval */
8726
 
    next_value = innobase_next_autoinc(current, need, offset, col_max_value);
 
7579
    next_value = innobase_next_autoinc(
 
7580
      *first_value, need, offset, col_max_value);
8727
7581
 
8728
7582
    prebuilt->autoinc_last_value = next_value;
8729
7583
 
8760
7614
{
8761
7615
  int error;
8762
7616
 
8763
 
  update_session(getTable()->in_use);
 
7617
  update_session(table->in_use);
8764
7618
 
8765
7619
  error = row_lock_table_autoinc_for_mysql(prebuilt);
8766
7620
 
8826
7680
  /* Do a type-aware comparison of primary key fields. PK fields
8827
7681
  are always NOT NULL, so no checks for NULL are performed. */
8828
7682
 
8829
 
  key_part = getTable()->key_info[getTable()->getShare()->getPrimaryKey()].key_part;
 
7683
  key_part = table->key_info[table->getShare()->getPrimaryKey()].key_part;
8830
7684
 
8831
7685
  key_part_end = key_part
8832
 
      + getTable()->key_info[getTable()->getShare()->getPrimaryKey()].key_parts;
 
7686
      + table->key_info[table->getShare()->getPrimaryKey()].key_parts;
8833
7687
 
8834
7688
  for (; key_part != key_part_end; ++key_part) {
8835
7689
    field = key_part->field;
8977
7831
 
8978
7832
  innobase_release_stat_resources(trx);
8979
7833
 
 
7834
  if (! session_test_options(session, OPTION_NOT_AUTOCOMMIT | OPTION_BEGIN))
 
7835
  {
 
7836
    if (trx->conc_state != TRX_NOT_STARTED)
 
7837
    {
 
7838
      commit(session, TRUE);
 
7839
    }
 
7840
  }
 
7841
  else
 
7842
  {
 
7843
    if (trx->isolation_level <= TRX_ISO_READ_COMMITTED &&
 
7844
        trx->global_read_view)
 
7845
    {
 
7846
      /* At low transaction isolation levels we let
 
7847
      each consistent read set its own snapshot */
 
7848
      read_view_close_for_mysql(trx);
 
7849
    }
 
7850
  }
8980
7851
}
8981
7852
 
8982
7853
/*******************************************************************//**
9046
7917
  return(error);
9047
7918
}
9048
7919
 
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
7920
/*******************************************************************//**
9076
7921
This function is used to recover X/Open XA distributed transactions.
9077
7922
@return number of prepared transactions stored in xid_list */
9183
8028
}
9184
8029
 
9185
8030
/************************************************************//**
 
8031
Validate the file format check value, is it one of "on" or "off",
 
8032
as a side effect it sets the srv_check_file_format_at_startup variable.
 
8033
@return true if config value one of "on" or  "off" */
 
8034
static
 
8035
bool
 
8036
innobase_file_format_check_on_off(
 
8037
/*==============================*/
 
8038
  const char* format_check) /*!< in: parameter value */
 
8039
{
 
8040
  bool    ret = true;
 
8041
 
 
8042
  if (!innobase_strcasecmp(format_check, "off")) {
 
8043
 
 
8044
    /* Set the value to disable checking. */
 
8045
    srv_check_file_format_at_startup = DICT_TF_FORMAT_MAX + 1;
 
8046
 
 
8047
  } else if (!innobase_strcasecmp(format_check, "on")) {
 
8048
 
 
8049
    /* Set the value to the lowest supported format. */
 
8050
    srv_check_file_format_at_startup = DICT_TF_FORMAT_51;
 
8051
  } else {
 
8052
    ret = FALSE;
 
8053
  }
 
8054
 
 
8055
  return(ret);
 
8056
}
 
8057
 
 
8058
/************************************************************//**
9186
8059
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 */
 
8060
sets the srv_check_file_format_at_startup variable.
 
8061
@return true if valid config value */
9189
8062
static
9190
 
int
9191
 
innobase_file_format_validate_and_set(
 
8063
bool
 
8064
innobase_file_format_check_validate(
9192
8065
/*================================*/
9193
 
  const char* format_max) /*!< in: parameter value */
 
8066
  const char* format_check) /*!< in: parameter value */
9194
8067
{
9195
8068
  uint    format_id;
 
8069
  bool    ret = true;
9196
8070
 
9197
 
  format_id = innobase_file_format_name_lookup(format_max);
 
8071
  format_id = innobase_file_format_name_lookup(format_check);
9198
8072
 
9199
8073
  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
 
 
 
8074
    srv_check_file_format_at_startup = format_id;
 
8075
  } else {
 
8076
    ret = false;
 
8077
  }
 
8078
 
 
8079
  return(ret);
 
8080
}
 
8081
 
 
8082
/*************************************************************//**
 
8083
Check if it is a valid file format. This function is registered as
 
8084
a callback with MySQL.
 
8085
@return 0 for valid file format */
 
8086
static
 
8087
int
 
8088
innodb_file_format_name_validate(
 
8089
/*=============================*/
 
8090
  Session*      , /*!< in: thread handle */
 
8091
  drizzle_sys_var*  , /*!< in: pointer to system
 
8092
            variable */
 
8093
  void*       save, /*!< out: immediate result
 
8094
            for update function */
 
8095
  drizzle_value*    value)  /*!< in: incoming string */
 
8096
{
 
8097
  const char* file_format_input;
 
8098
  char    buff[STRING_BUFFER_USUAL_SIZE];
 
8099
  int   len = sizeof(buff);
 
8100
 
 
8101
  ut_a(save != NULL);
 
8102
  ut_a(value != NULL);
 
8103
 
 
8104
  file_format_input = value->val_str(value, buff, &len);
 
8105
 
 
8106
  if (file_format_input != NULL) {
 
8107
    uint  format_id;
 
8108
 
 
8109
    format_id = innobase_file_format_name_lookup(
 
8110
      file_format_input);
 
8111
 
 
8112
    if (format_id <= DICT_TF_FORMAT_MAX) {
 
8113
 
 
8114
      *static_cast<const char**>(save) = file_format_input;
 
8115
      return(0);
 
8116
    }
 
8117
  }
 
8118
 
 
8119
  *static_cast<const char**>(save) = NULL;
 
8120
  return(1);
 
8121
}
 
8122
 
 
8123
/****************************************************************//**
 
8124
Update the system variable innodb_file_format using the "saved"
 
8125
value. This function is registered as a callback with MySQL. */
 
8126
static
 
8127
void
 
8128
innodb_file_format_name_update(
 
8129
/*===========================*/
 
8130
  Session*      ,   /*!< in: thread handle */
 
8131
  drizzle_sys_var*  ,   /*!< in: pointer to
 
8132
              system variable */
 
8133
  void*       var_ptr,  /*!< out: where the
 
8134
              formal string goes */
 
8135
  const void*     save)   /*!< in: immediate result
 
8136
              from check function */
 
8137
{
 
8138
  const char* format_name;
 
8139
 
 
8140
  ut_a(var_ptr != NULL);
 
8141
  ut_a(save != NULL);
 
8142
 
 
8143
  format_name = *static_cast<const char*const*>(save);
 
8144
 
 
8145
  if (format_name) {
 
8146
    uint  format_id;
 
8147
 
 
8148
    format_id = innobase_file_format_name_lookup(format_name);
 
8149
 
 
8150
    if (format_id <= DICT_TF_FORMAT_MAX) {
 
8151
      srv_file_format = format_id;
 
8152
    }
 
8153
  }
 
8154
 
 
8155
  *static_cast<const char**>(var_ptr)
 
8156
    = trx_sys_file_format_id_to_name(srv_file_format);
 
8157
}
 
8158
 
 
8159
/*************************************************************//**
 
8160
Check if valid argument to innodb_file_format_check. This
 
8161
function is registered as a callback with MySQL.
 
8162
@return 0 for valid file format */
 
8163
static
 
8164
int
 
8165
innodb_file_format_check_validate(
 
8166
/*==============================*/
 
8167
  Session*      , /*!< in: thread handle */
 
8168
  drizzle_sys_var*  , /*!< in: pointer to system
 
8169
            variable */
 
8170
  void*       save, /*!< out: immediate result
 
8171
            for update function */
 
8172
  drizzle_value*    value)  /*!< in: incoming string */
 
8173
{
 
8174
  const char* file_format_input;
 
8175
  char    buff[STRING_BUFFER_USUAL_SIZE];
 
8176
  int   len = sizeof(buff);
 
8177
 
 
8178
  ut_a(save != NULL);
 
8179
  ut_a(value != NULL);
 
8180
 
 
8181
  file_format_input = value->val_str(value, buff, &len);
 
8182
 
 
8183
  if (file_format_input != NULL) {
 
8184
 
 
8185
    /* Check if user set on/off, we want to print a suitable
 
8186
    message if they did so. */
 
8187
 
 
8188
    if (innobase_file_format_check_on_off(file_format_input)) {
 
8189
      errmsg_printf(ERRMSG_LVL_WARN, 
 
8190
        "InnoDB: invalid innodb_file_format_check "
 
8191
        "value; on/off can only be set at startup or "
 
8192
        "in the configuration file");
 
8193
    } else if (innobase_file_format_check_validate(
 
8194
        file_format_input)) {
 
8195
 
 
8196
      *static_cast<const char**>(save) = file_format_input;
 
8197
 
 
8198
      return(0);
 
8199
 
 
8200
    } else {
 
8201
      errmsg_printf(ERRMSG_LVL_WARN, 
 
8202
        "InnoDB: invalid innodb_file_format_check "
 
8203
        "value; can be any format up to %s "
 
8204
        "or its equivalent numeric id",
 
8205
        trx_sys_file_format_id_to_name(
 
8206
          DICT_TF_FORMAT_MAX));
 
8207
    }
 
8208
  }
 
8209
 
 
8210
  *static_cast<const char**>(save) = NULL;
 
8211
  return(1);
 
8212
}
 
8213
 
 
8214
/****************************************************************//**
 
8215
Update the system variable innodb_file_format_check using the "saved"
 
8216
value. This function is registered as a callback with MySQL. */
 
8217
static
 
8218
void
 
8219
innodb_file_format_check_update(
 
8220
/*============================*/
 
8221
  Session*      session,  /*!< in: thread handle */
 
8222
  drizzle_sys_var*  ,   /*!< in: pointer to
 
8223
              system variable */
 
8224
  void*       var_ptr,  /*!< out: where the
 
8225
              formal string goes */
 
8226
  const void*     save)   /*!< in: immediate result
 
8227
              from check function */
 
8228
{
 
8229
  const char* format_name_in;
 
8230
  const char**  format_name_out;
 
8231
  uint    format_id;
 
8232
 
 
8233
  ut_a(save != NULL);
 
8234
  ut_a(var_ptr != NULL);
 
8235
 
 
8236
  format_name_in = *static_cast<const char*const*>(save);
 
8237
 
 
8238
  if (!format_name_in) {
 
8239
 
 
8240
    return;
 
8241
  }
 
8242
 
 
8243
  format_id = innobase_file_format_name_lookup(format_name_in);
 
8244
 
 
8245
  if (format_id > DICT_TF_FORMAT_MAX) {
 
8246
    /* DEFAULT is "on", which is invalid at runtime. */
 
8247
    push_warning_printf(session, DRIZZLE_ERROR::WARN_LEVEL_WARN,
 
8248
            ER_WRONG_ARGUMENTS,
 
8249
            "Ignoring SET innodb_file_format=%s",
 
8250
            format_name_in);
 
8251
    return;
 
8252
  }
 
8253
 
 
8254
  format_name_out = static_cast<const char**>(var_ptr);
 
8255
 
 
8256
  /* Update the max format id in the system tablespace. */
 
8257
  if (trx_sys_file_format_max_set(format_id, format_name_out)) {
 
8258
    ut_print_timestamp(stderr);
 
8259
    fprintf(stderr,
 
8260
      " [Info] InnoDB: the file format in the system "
 
8261
      "tablespace is now set to %s.\n", *format_name_out);
 
8262
  }
 
8263
}
 
8264
 
 
8265
/****************************************************************//**
 
8266
Update the system variable innodb_adaptive_hash_index using the "saved"
 
8267
value. This function is registered as a callback with MySQL. */
 
8268
static
 
8269
void
 
8270
innodb_adaptive_hash_index_update(
 
8271
/*==============================*/
 
8272
  Session*      ,   /*!< in: thread handle */
 
8273
  drizzle_sys_var*  ,   /*!< in: pointer to
 
8274
              system variable */
 
8275
  void*       , /*!< out: where the
 
8276
              formal string goes */
 
8277
  const void*     save)   /*!< in: immediate result
 
8278
              from check function */
 
8279
{
 
8280
  if (*(bool*) save) {
 
8281
    btr_search_enable();
 
8282
  } else {
 
8283
    btr_search_disable();
 
8284
  }
 
8285
}
 
8286
 
 
8287
/*************************************************************//**
 
8288
Check if it is a valid value of innodb_change_buffering.  This function is
 
8289
registered as a callback with MySQL.
 
8290
@return 0 for valid innodb_change_buffering */
 
8291
static
 
8292
int
 
8293
innodb_change_buffering_validate(
 
8294
/*=============================*/
 
8295
  Session*      , /*!< in: thread handle */
 
8296
  drizzle_sys_var*  , /*!< in: pointer to system
 
8297
            variable */
 
8298
  void*       save, /*!< out: immediate result
 
8299
            for update function */
 
8300
  drizzle_value*    value)  /*!< in: incoming string */
 
8301
{
 
8302
  const char* change_buffering_input;
 
8303
  char    buff[STRING_BUFFER_USUAL_SIZE];
 
8304
  int   len = sizeof(buff);
 
8305
 
 
8306
  ut_a(save != NULL);
 
8307
  ut_a(value != NULL);
 
8308
 
 
8309
  change_buffering_input = value->val_str(value, buff, &len);
 
8310
 
 
8311
  if (change_buffering_input != NULL) {
 
8312
    ulint use;
 
8313
 
 
8314
    for (use = 0; use < UT_ARR_SIZE(innobase_change_buffering_values);
 
8315
         use++) {
 
8316
      if (!innobase_strcasecmp(
 
8317
            change_buffering_input,
 
8318
            innobase_change_buffering_values[use])) {
 
8319
        *(ibuf_use_t*) save = (ibuf_use_t) use;
 
8320
        return(0);
 
8321
      }
 
8322
    }
 
8323
  }
 
8324
 
 
8325
  return(1);
 
8326
}
 
8327
 
 
8328
/****************************************************************//**
 
8329
Update the system variable innodb_change_buffering using the "saved"
 
8330
value. This function is registered as a callback with MySQL. */
 
8331
static
 
8332
void
 
8333
innodb_change_buffering_update(
 
8334
/*===========================*/
 
8335
  Session*      ,   /*!< in: thread handle */
 
8336
  drizzle_sys_var*  ,   /*!< in: pointer to
 
8337
              system variable */
 
8338
  void*       var_ptr,  /*!< out: where the
 
8339
              formal string goes */
 
8340
  const void*     save)   /*!< in: immediate result
 
8341
              from check function */
 
8342
{
 
8343
  ut_a(var_ptr != NULL);
 
8344
  ut_a(save != NULL);
 
8345
  ut_a((*(ibuf_use_t*) save) < IBUF_USE_COUNT);
 
8346
 
 
8347
  ibuf_use = *(const ibuf_use_t*) save;
 
8348
 
 
8349
  *(const char**) var_ptr = innobase_change_buffering_values[ibuf_use];
 
8350
}
 
8351
 
 
8352
/* plugin options */
 
8353
static DRIZZLE_SYSVAR_BOOL(checksums, innobase_use_checksums,
 
8354
  PLUGIN_VAR_NOCMDARG | PLUGIN_VAR_READONLY,
 
8355
  "Enable InnoDB checksums validation (enabled by default). "
 
8356
  "Disable with --skip-innodb-checksums.",
 
8357
  NULL, NULL, TRUE);
 
8358
 
 
8359
static DRIZZLE_SYSVAR_STR(data_home_dir, innobase_data_home_dir,
 
8360
  PLUGIN_VAR_READONLY,
 
8361
  "The common part for InnoDB table spaces.",
 
8362
  NULL, NULL, NULL);
 
8363
 
 
8364
static DRIZZLE_SYSVAR_BOOL(doublewrite, innobase_use_doublewrite,
 
8365
  PLUGIN_VAR_NOCMDARG | PLUGIN_VAR_READONLY,
 
8366
  "Enable InnoDB doublewrite buffer (enabled by default). "
 
8367
  "Disable with --skip-innodb-doublewrite.",
 
8368
  NULL, NULL, TRUE);
 
8369
 
 
8370
static DRIZZLE_SYSVAR_ULONG(io_capacity, srv_io_capacity,
 
8371
  PLUGIN_VAR_RQCMDARG,
 
8372
  "Number of IOPs the server can do. Tunes the background IO rate",
 
8373
  NULL, NULL, 200, 100, ~0L, 0);
 
8374
 
 
8375
static DRIZZLE_SYSVAR_ULONG(fast_shutdown, innobase_fast_shutdown,
 
8376
  PLUGIN_VAR_OPCMDARG,
 
8377
  "Speeds up the shutdown process of the InnoDB storage engine. Possible "
 
8378
  "values are 0, 1 (faster)"
 
8379
  " or 2 (fastest - crash-like)"
 
8380
  ".",
 
8381
  NULL, NULL, 1, 0, 2, 0);
 
8382
 
 
8383
static DRIZZLE_SYSVAR_BOOL(file_per_table, srv_file_per_table,
 
8384
  PLUGIN_VAR_NOCMDARG,
 
8385
  "Stores each InnoDB table to an .ibd file in the database dir.",
 
8386
  NULL, NULL, FALSE);
 
8387
 
 
8388
static DRIZZLE_SYSVAR_STR(file_format, innobase_file_format_name,
 
8389
  PLUGIN_VAR_RQCMDARG,
 
8390
  "File format to use for new tables in .ibd files.",
 
8391
  innodb_file_format_name_validate,
 
8392
  innodb_file_format_name_update, "Antelope");
 
8393
 
 
8394
static DRIZZLE_SYSVAR_STR(file_format_check, innobase_file_format_check,
 
8395
  PLUGIN_VAR_OPCMDARG,
 
8396
  "The highest file format in the tablespace.",
 
8397
  innodb_file_format_check_validate,
 
8398
  innodb_file_format_check_update,
 
8399
  "on");
 
8400
 
 
8401
static DRIZZLE_SYSVAR_ULONG(flush_log_at_trx_commit, srv_flush_log_at_trx_commit,
 
8402
  PLUGIN_VAR_OPCMDARG,
 
8403
  "Set to 0 (write and flush once per second),"
 
8404
  " 1 (write and flush at each commit)"
 
8405
  " or 2 (write at commit, flush once per second).",
 
8406
  NULL, NULL, 1, 0, 2, 0);
 
8407
 
 
8408
static DRIZZLE_SYSVAR_STR(flush_method, innobase_unix_file_flush_method,
 
8409
  PLUGIN_VAR_RQCMDARG | PLUGIN_VAR_READONLY,
 
8410
  "With which method to flush data.", NULL, NULL, NULL);
 
8411
 
 
8412
#ifdef UNIV_LOG_ARCHIVE
 
8413
static DRIZZLE_SYSVAR_STR(log_arch_dir, innobase_log_arch_dir,
 
8414
  PLUGIN_VAR_RQCMDARG | PLUGIN_VAR_READONLY,
 
8415
  "Where full logs should be archived.", NULL, NULL, NULL);
 
8416
 
 
8417
static DRIZZLE_SYSVAR_BOOL(log_archive, innobase_log_archive,
 
8418
  PLUGIN_VAR_OPCMDARG | PLUGIN_VAR_READONLY,
 
8419
  "Set to 1 if you want to have logs archived.", NULL, NULL, FALSE);
 
8420
#endif /* UNIV_LOG_ARCHIVE */
 
8421
 
 
8422
static DRIZZLE_SYSVAR_STR(log_group_home_dir, innobase_log_group_home_dir,
 
8423
  PLUGIN_VAR_RQCMDARG | PLUGIN_VAR_READONLY,
 
8424
  "Path to InnoDB log files.", NULL, NULL, NULL);
 
8425
 
 
8426
static DRIZZLE_SYSVAR_ULONG(max_dirty_pages_pct, srv_max_buf_pool_modified_pct,
 
8427
  PLUGIN_VAR_RQCMDARG,
 
8428
  "Percentage of dirty pages allowed in bufferpool.",
 
8429
  NULL, NULL, 75, 0, 99, 0);
 
8430
 
 
8431
static DRIZZLE_SYSVAR_BOOL(adaptive_flushing, srv_adaptive_flushing,
 
8432
  PLUGIN_VAR_NOCMDARG,
 
8433
  "Attempt flushing dirty pages to avoid IO bursts at checkpoints.",
 
8434
  NULL, NULL, TRUE);
 
8435
 
 
8436
static DRIZZLE_SYSVAR_ULONG(max_purge_lag, srv_max_purge_lag,
 
8437
  PLUGIN_VAR_RQCMDARG,
 
8438
  "Desired maximum length of the purge queue (0 = no limit)",
 
8439
  NULL, NULL, 0, 0, ~0L, 0);
 
8440
 
 
8441
static DRIZZLE_SYSVAR_BOOL(status_file, innobase_create_status_file,
 
8442
  PLUGIN_VAR_OPCMDARG | PLUGIN_VAR_NOSYSVAR,
 
8443
  "Enable SHOW INNODB STATUS output in the innodb_status.<pid> file",
 
8444
  NULL, NULL, FALSE);
 
8445
 
 
8446
static DRIZZLE_SYSVAR_BOOL(stats_on_metadata, innobase_stats_on_metadata,
 
8447
  PLUGIN_VAR_OPCMDARG,
 
8448
  "Enable statistics gathering for metadata commands such as SHOW TABLE STATUS (on by default)",
 
8449
  NULL, NULL, TRUE);
 
8450
 
 
8451
static DRIZZLE_SYSVAR_ULONGLONG(stats_sample_pages, srv_stats_sample_pages,
 
8452
  PLUGIN_VAR_RQCMDARG,
 
8453
  "The number of index pages to sample when calculating statistics (default 8)",
 
8454
  NULL, NULL, 8, 1, ~0ULL, 0);
 
8455
 
 
8456
static DRIZZLE_SYSVAR_BOOL(adaptive_hash_index, btr_search_enabled,
 
8457
  PLUGIN_VAR_OPCMDARG,
 
8458
  "Enable InnoDB adaptive hash index (enabled by default).  "
 
8459
  "Disable with --skip-innodb-adaptive-hash-index.",
 
8460
  NULL, innodb_adaptive_hash_index_update, TRUE);
 
8461
 
 
8462
static DRIZZLE_SYSVAR_ULONG(replication_delay, srv_replication_delay,
 
8463
  PLUGIN_VAR_RQCMDARG,
 
8464
  "Replication thread delay (ms) on the slave server if "
 
8465
  "innodb_thread_concurrency is reached (0 by default)",
 
8466
  NULL, NULL, 0, 0, ~0UL, 0);
 
8467
 
 
8468
static DRIZZLE_SYSVAR_LONG(additional_mem_pool_size, innobase_additional_mem_pool_size,
 
8469
  PLUGIN_VAR_RQCMDARG | PLUGIN_VAR_READONLY,
 
8470
  "Size of a memory pool InnoDB uses to store data dictionary information and other internal data structures.",
 
8471
  NULL, NULL, 8*1024*1024L, 512*1024L, LONG_MAX, 1024);
 
8472
 
 
8473
static DRIZZLE_SYSVAR_UINT(autoextend_increment, srv_auto_extend_increment,
 
8474
  PLUGIN_VAR_RQCMDARG,
 
8475
  "Data file autoextend increment in megabytes",
 
8476
  NULL, NULL, 8L, 1L, 1000L, 0);
 
8477
 
 
8478
static DRIZZLE_SYSVAR_LONGLONG(buffer_pool_size, innobase_buffer_pool_size,
 
8479
  PLUGIN_VAR_RQCMDARG | PLUGIN_VAR_READONLY,
 
8480
  "The size of the memory buffer InnoDB uses to cache data and indexes of its tables.",
 
8481
  NULL, NULL, 128*1024*1024L, 5*1024*1024L, INT64_MAX, 1024*1024L);
 
8482
 
 
8483
static DRIZZLE_SYSVAR_ULONG(commit_concurrency, innobase_commit_concurrency,
 
8484
  PLUGIN_VAR_RQCMDARG,
 
8485
  "Helps in performance tuning in heavily concurrent environments.",
 
8486
  innobase_commit_concurrency_validate, NULL, 0, 0, 1000, 0);
 
8487
 
 
8488
static DRIZZLE_SYSVAR_ULONG(concurrency_tickets, srv_n_free_tickets_to_enter,
 
8489
  PLUGIN_VAR_RQCMDARG,
 
8490
  "Number of times a thread is allowed to enter InnoDB within the same SQL query after it has once got the ticket",
 
8491
  NULL, NULL, 500L, 1L, ~0L, 0);
 
8492
 
 
8493
static DRIZZLE_SYSVAR_LONG(file_io_threads, innobase_file_io_threads,
 
8494
  PLUGIN_VAR_RQCMDARG | PLUGIN_VAR_READONLY,
 
8495
  "Number of file I/O threads in InnoDB.",
 
8496
  NULL, NULL, 4, 4, 64, 0);
 
8497
 
 
8498
static DRIZZLE_SYSVAR_ULONG(read_io_threads, innobase_read_io_threads,
 
8499
  PLUGIN_VAR_RQCMDARG | PLUGIN_VAR_READONLY,
 
8500
  "Number of background read I/O threads in InnoDB.",
 
8501
  NULL, NULL, 4, 1, 64, 0);
 
8502
 
 
8503
static DRIZZLE_SYSVAR_ULONG(write_io_threads, innobase_write_io_threads,
 
8504
  PLUGIN_VAR_RQCMDARG | PLUGIN_VAR_READONLY,
 
8505
  "Number of background write I/O threads in InnoDB.",
 
8506
  NULL, NULL, 4, 1, 64, 0);
 
8507
 
 
8508
static DRIZZLE_SYSVAR_LONG(force_recovery, innobase_force_recovery,
 
8509
  PLUGIN_VAR_RQCMDARG | PLUGIN_VAR_READONLY,
 
8510
  "Helps to save your data in case the disk image of the database becomes corrupt.",
 
8511
  NULL, NULL, 0, 0, 6, 0);
 
8512
 
 
8513
static DRIZZLE_SYSVAR_LONG(log_buffer_size, innobase_log_buffer_size,
 
8514
  PLUGIN_VAR_RQCMDARG | PLUGIN_VAR_READONLY,
 
8515
  "The size of the buffer which InnoDB uses to write log to the log files on disk.",
 
8516
  NULL, NULL, 8*1024*1024L, 256*1024L, LONG_MAX, 1024);
 
8517
 
 
8518
static DRIZZLE_SYSVAR_LONGLONG(log_file_size, innobase_log_file_size,
 
8519
  PLUGIN_VAR_RQCMDARG | PLUGIN_VAR_READONLY,
 
8520
  "Size of each log file in a log group.",
 
8521
  NULL, NULL, 20*1024*1024L, 1*1024*1024L, INT64_MAX, 1024*1024L);
 
8522
 
 
8523
static DRIZZLE_SYSVAR_LONG(log_files_in_group, innobase_log_files_in_group,
 
8524
  PLUGIN_VAR_RQCMDARG | PLUGIN_VAR_READONLY,
 
8525
  "Number of log files in the log group. InnoDB writes to the files in a circular fashion. Value 3 is recommended here.",
 
8526
  NULL, NULL, 2, 2, 100, 0);
 
8527
 
 
8528
static DRIZZLE_SYSVAR_LONG(mirrored_log_groups, innobase_mirrored_log_groups,
 
8529
  PLUGIN_VAR_RQCMDARG | PLUGIN_VAR_READONLY,
 
8530
  "Number of identical copies of log groups we keep for the database. Currently this should be set to 1.",
 
8531
  NULL, NULL, 1, 1, 10, 0);
 
8532
 
 
8533
static DRIZZLE_SYSVAR_LONG(open_files, innobase_open_files,
 
8534
  PLUGIN_VAR_RQCMDARG | PLUGIN_VAR_READONLY,
 
8535
  "How many files at the maximum InnoDB keeps open at the same time.",
 
8536
  NULL, NULL, 300L, 10L, LONG_MAX, 0);
 
8537
 
 
8538
static DRIZZLE_SYSVAR_ULONG(sync_spin_loops, srv_n_spin_wait_rounds,
 
8539
  PLUGIN_VAR_RQCMDARG,
 
8540
  "Count of spin-loop rounds in InnoDB mutexes (30 by default)",
 
8541
  NULL, NULL, 30L, 0L, ~0L, 0);
 
8542
 
 
8543
static DRIZZLE_SYSVAR_ULONG(spin_wait_delay, srv_spin_wait_delay,
 
8544
  PLUGIN_VAR_OPCMDARG,
 
8545
  "Maximum delay between polling for a spin lock (6 by default)",
 
8546
  NULL, NULL, 6L, 0L, ~0L, 0);
 
8547
 
 
8548
static DRIZZLE_SYSVAR_ULONG(thread_concurrency, srv_thread_concurrency,
 
8549
  PLUGIN_VAR_RQCMDARG,
 
8550
  "Helps in performance tuning in heavily concurrent environments. Sets the maximum number of threads allowed inside InnoDB. Value 0 will disable the thread throttling.",
 
8551
  NULL, NULL, 0, 0, 1000, 0);
 
8552
 
 
8553
static DRIZZLE_SYSVAR_ULONG(thread_sleep_delay, srv_thread_sleep_delay,
 
8554
  PLUGIN_VAR_RQCMDARG,
 
8555
  "Time of innodb thread sleeping before joining InnoDB queue (usec). Value 0 disable a sleep",
 
8556
  NULL, NULL, 10000L, 0L, ~0L, 0);
 
8557
 
 
8558
static DRIZZLE_SYSVAR_STR(data_file_path, innobase_data_file_path,
 
8559
  PLUGIN_VAR_RQCMDARG | PLUGIN_VAR_READONLY,
 
8560
  "Path to individual files and their sizes.",
 
8561
  NULL, NULL, NULL);
 
8562
 
 
8563
static DRIZZLE_SYSVAR_STR(version, innodb_version_str,
 
8564
  PLUGIN_VAR_NOCMDOPT | PLUGIN_VAR_READONLY,
 
8565
  "InnoDB version", NULL, NULL, INNODB_VERSION_STR);
 
8566
 
 
8567
static DRIZZLE_SYSVAR_BOOL(use_sys_malloc, srv_use_sys_malloc,
 
8568
  PLUGIN_VAR_NOCMDARG | PLUGIN_VAR_READONLY,
 
8569
  "Use OS memory allocator instead of InnoDB's internal memory allocator",
 
8570
  NULL, NULL, TRUE);
 
8571
 
 
8572
static DRIZZLE_SYSVAR_STR(change_buffering, innobase_change_buffering,
 
8573
  PLUGIN_VAR_RQCMDARG,
 
8574
  "Buffer changes to reduce random access: "
 
8575
  "OFF, ON, inserting, deleting, changing, or purging.",
 
8576
  innodb_change_buffering_validate,
 
8577
  innodb_change_buffering_update, NULL);
 
8578
 
 
8579
static DRIZZLE_SYSVAR_ULONG(read_ahead_threshold, srv_read_ahead_threshold,
 
8580
  PLUGIN_VAR_RQCMDARG,
 
8581
  "Number of pages that must be accessed sequentially for InnoDB to"
 
8582
  "trigger a readahead.",
 
8583
  NULL, NULL, 56, 0, 64, 0);
 
8584
 
 
8585
static drizzle_sys_var* innobase_system_variables[]= {
 
8586
  DRIZZLE_SYSVAR(additional_mem_pool_size),
 
8587
  DRIZZLE_SYSVAR(autoextend_increment),
 
8588
  DRIZZLE_SYSVAR(buffer_pool_size),
 
8589
  DRIZZLE_SYSVAR(checksums),
 
8590
  DRIZZLE_SYSVAR(commit_concurrency),
 
8591
  DRIZZLE_SYSVAR(concurrency_tickets),
 
8592
  DRIZZLE_SYSVAR(data_file_path),
 
8593
  DRIZZLE_SYSVAR(data_home_dir),
 
8594
  DRIZZLE_SYSVAR(doublewrite),
 
8595
  DRIZZLE_SYSVAR(fast_shutdown),
 
8596
  DRIZZLE_SYSVAR(file_io_threads),
 
8597
  DRIZZLE_SYSVAR(read_io_threads),
 
8598
  DRIZZLE_SYSVAR(write_io_threads),
 
8599
  DRIZZLE_SYSVAR(file_per_table),
 
8600
  DRIZZLE_SYSVAR(file_format),
 
8601
  DRIZZLE_SYSVAR(file_format_check),
 
8602
  DRIZZLE_SYSVAR(flush_log_at_trx_commit),
 
8603
  DRIZZLE_SYSVAR(flush_method),
 
8604
  DRIZZLE_SYSVAR(force_recovery),
 
8605
  DRIZZLE_SYSVAR(lock_wait_timeout),
 
8606
#ifdef UNIV_LOG_ARCHIVE
 
8607
  DRIZZLE_SYSVAR(log_arch_dir),
 
8608
  DRIZZLE_SYSVAR(log_archive),
 
8609
#endif /* UNIV_LOG_ARCHIVE */
 
8610
  DRIZZLE_SYSVAR(log_buffer_size),
 
8611
  DRIZZLE_SYSVAR(log_file_size),
 
8612
  DRIZZLE_SYSVAR(log_files_in_group),
 
8613
  DRIZZLE_SYSVAR(log_group_home_dir),
 
8614
  DRIZZLE_SYSVAR(max_dirty_pages_pct),
 
8615
  DRIZZLE_SYSVAR(max_purge_lag),
 
8616
  DRIZZLE_SYSVAR(adaptive_flushing),
 
8617
  DRIZZLE_SYSVAR(mirrored_log_groups),
 
8618
  DRIZZLE_SYSVAR(open_files),
 
8619
  DRIZZLE_SYSVAR(stats_on_metadata),
 
8620
  DRIZZLE_SYSVAR(stats_sample_pages),
 
8621
  DRIZZLE_SYSVAR(adaptive_hash_index),
 
8622
  DRIZZLE_SYSVAR(replication_delay),
 
8623
  DRIZZLE_SYSVAR(status_file),
 
8624
  DRIZZLE_SYSVAR(strict_mode),
 
8625
  DRIZZLE_SYSVAR(support_xa),
 
8626
  DRIZZLE_SYSVAR(sync_spin_loops),
 
8627
  DRIZZLE_SYSVAR(spin_wait_delay),
 
8628
  DRIZZLE_SYSVAR(table_locks),
 
8629
  DRIZZLE_SYSVAR(thread_concurrency),
 
8630
  DRIZZLE_SYSVAR(thread_sleep_delay),
 
8631
  DRIZZLE_SYSVAR(version),
 
8632
  DRIZZLE_SYSVAR(use_sys_malloc),
 
8633
  DRIZZLE_SYSVAR(change_buffering),
 
8634
  DRIZZLE_SYSVAR(read_ahead_threshold),
 
8635
  DRIZZLE_SYSVAR(io_capacity),
 
8636
  NULL
 
8637
};
9366
8638
 
9367
8639
DRIZZLE_DECLARE_PLUGIN
9368
8640
{
9373
8645
  "Supports transactions, row-level locking, and foreign keys",
9374
8646
  PLUGIN_LICENSE_GPL,
9375
8647
  innobase_init, /* Plugin Init */
9376
 
  NULL, /* system variables */
9377
 
  init_options /* reserved */
 
8648
  innobase_system_variables, /* system variables */
 
8649
  NULL /* reserved */
9378
8650
}
9379
8651
DRIZZLE_DECLARE_PLUGIN_END;
9380
8652
 
9401
8673
  return res;
9402
8674
}
9403
8675
 
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. */
 
8676
/** @brief Initialize the default value of innodb_commit_concurrency.
 
8677
 
 
8678
Once InnoDB is running, the innodb_commit_concurrency must not change
 
8679
from zero to nonzero. (Bug #42101)
 
8680
 
 
8681
The initial default value is 0, and without this extra initialization,
 
8682
SET GLOBAL innodb_commit_concurrency=DEFAULT would set the parameter
 
8683
to 0, even if it was initially set to nonzero at the command line
 
8684
or configuration file. */
 
8685
static
 
8686
void
 
8687
innobase_commit_concurrency_init_default(void)
 
8688
/*==========================================*/
9418
8689
{
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);
 
8690
  DRIZZLE_SYSVAR_NAME(commit_concurrency).def_val
 
8691
    = innobase_commit_concurrency;
9445
8692
}
9446
8693
 
9447
8694
#ifdef UNIV_COMPILE_TEST_FUNCS