~drizzle-trunk/drizzle/development

« back to all changes in this revision

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

Merge in Hartmut's work

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.
4
 
Copyright (C) 2008, 2009 Google Inc.
5
 
Copyright (C) 2009, Percona Inc.
 
3
Copyright (c) 2000, 2009, MySQL AB & Innobase Oy. All Rights Reserved.
 
4
Copyright (c) 2008, 2009 Google 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
38
56
    in Windows?
39
57
*/
40
58
 
41
 
#include <config.h>
 
59
#include "config.h"
42
60
 
43
61
#include <limits.h>
44
62
#include <fcntl.h>
45
63
 
46
 
#include <drizzled/error.h>
47
 
#include <drizzled/errmsg_print.h>
48
 
#include <drizzled/charset_info.h>
49
 
#include <drizzled/internal/m_string.h>
50
 
#include <drizzled/internal/my_sys.h>
51
 
#include <drizzled/my_hash.h>
52
 
#include <drizzled/plugin.h>
53
 
#include <drizzled/show.h>
54
 
#include <drizzled/data_home.h>
55
 
#include <drizzled/error.h>
56
 
#include <drizzled/field.h>
57
 
#include <drizzled/charset.h>
58
 
#include <drizzled/session.h>
59
 
#include <drizzled/current_session.h>
60
 
#include <drizzled/table.h>
61
 
#include <drizzled/field/blob.h>
62
 
#include <drizzled/field/varstring.h>
63
 
#include <drizzled/plugin/xa_storage_engine.h>
64
 
#include <drizzled/plugin/daemon.h>
65
 
#include <drizzled/memory/multi_malloc.h>
66
 
#include <drizzled/pthread_globals.h>
67
 
#include <drizzled/named_savepoint.h>
 
64
#include "drizzled/error.h"
 
65
#include "drizzled/errmsg_print.h"
 
66
#include "drizzled/charset_info.h"
 
67
#include "drizzled/internal/m_string.h"
 
68
#include "drizzled/internal/my_sys.h"
 
69
#include "drizzled/my_hash.h"
 
70
#include "drizzled/plugin.h"
 
71
#include "drizzled/show.h"
 
72
#include "drizzled/data_home.h"
 
73
#include "drizzled/error.h"
 
74
#include "drizzled/field.h"
 
75
#include "drizzled/charset.h"
 
76
#include "drizzled/session.h"
 
77
#include "drizzled/current_session.h"
 
78
#include "drizzled/table.h"
 
79
#include "drizzled/field/blob.h"
 
80
#include "drizzled/field/varstring.h"
 
81
#include "drizzled/field/timestamp.h"
 
82
#include "drizzled/plugin/xa_storage_engine.h"
 
83
#include "drizzled/plugin/daemon.h"
 
84
#include "drizzled/memory/multi_malloc.h"
 
85
#include "drizzled/pthread_globals.h"
 
86
#include "drizzled/named_savepoint.h"
68
87
 
69
88
#include <drizzled/transaction_services.h>
70
 
#include <drizzled/message/statement_transform.h>
71
89
 
72
90
#include <boost/algorithm/string.hpp>
73
 
#include <boost/program_options.hpp>
74
 
#include <boost/scoped_array.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 */
 
95
extern "C" {
86
96
#include "univ.i"
87
 
#include "buf0lru.h"
88
97
#include "btr0sea.h"
89
98
#include "os0file.h"
90
99
#include "os0thread.h"
101
110
#include "log0log.h"
102
111
#include "lock0lock.h"
103
112
#include "dict0crea.h"
104
 
#include "create_replication.h"
105
113
#include "btr0cur.h"
106
114
#include "btr0btr.h"
107
115
#include "fsp0fsp.h"
114
122
#include "ha_prototypes.h"
115
123
#include "ut0mem.h"
116
124
#include "ibuf0ibuf.h"
 
125
#include "mysql_addons.h"
 
126
}
117
127
 
118
128
#include "ha_innodb.h"
119
129
#include "data_dictionary.h"
120
 
#include "replication_dictionary.h"
121
130
#include "internal_dictionary.h"
122
131
#include "handler0vars.h"
123
132
 
125
134
#include <sstream>
126
135
#include <string>
127
136
 
128
 
#include <plugin/innobase/handler/status_function.h>
129
 
#include <plugin/innobase/handler/replication_log.h>
130
 
 
131
 
#include <google/protobuf/io/zero_copy_stream.h>
132
 
#include <google/protobuf/io/zero_copy_stream_impl.h>
133
 
#include <google/protobuf/io/coded_stream.h>
134
 
#include <google/protobuf/text_format.h>
135
 
 
136
 
#include <boost/thread/mutex.hpp>
 
137
#include "plugin/innobase/handler/status_function.h"
137
138
 
138
139
using namespace std;
139
140
using namespace drizzled;
140
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
 
141
149
/** to protect innobase_open_files */
142
 
static boost::mutex innobase_share_mutex;
143
 
 
 
150
static pthread_mutex_t innobase_share_mutex;
144
151
/** to force correct commit order in binlog */
 
152
static pthread_mutex_t prepare_commit_mutex;
145
153
static ulong commit_threads = 0;
146
 
static boost::condition_variable commit_cond;
147
 
static boost::mutex commit_cond_m;
 
154
static pthread_mutex_t commit_threads_m;
 
155
static pthread_cond_t commit_cond;
 
156
static pthread_mutex_t commit_cond_m;
148
157
static bool innodb_inited = 0;
149
158
 
150
159
#define INSIDE_HA_INNOBASE_CC
160
169
#endif /* MYSQL_DYNAMIC_PLUGIN && __WIN__ */
161
170
 
162
171
static plugin::XaStorageEngine* innodb_engine_ptr= NULL;
163
 
 
164
 
typedef constrained_check<uint32_t, UINT32_MAX, 10> open_files_constraint;
165
 
static open_files_constraint innobase_open_files;
166
 
typedef constrained_check<uint32_t, 10, 1> mirrored_log_groups_constraint;
167
 
static mirrored_log_groups_constraint innobase_mirrored_log_groups;
168
 
typedef constrained_check<uint32_t, 100, 2> log_files_in_group_constraint;
169
 
static log_files_in_group_constraint innobase_log_files_in_group;
170
 
typedef constrained_check<uint32_t, 6, 0> force_recovery_constraint;
171
 
force_recovery_constraint innobase_force_recovery;
172
 
typedef constrained_check<size_t, SIZE_MAX, 256*1024, 1024> log_buffer_constraint;
173
 
static log_buffer_constraint innobase_log_buffer_size;
174
 
typedef constrained_check<size_t, SIZE_MAX, 512*1024, 1024> additional_mem_pool_constraint;
175
 
static additional_mem_pool_constraint innobase_additional_mem_pool_size;
176
 
typedef constrained_check<unsigned int, 1000, 1> autoextend_constraint;
177
 
static autoextend_constraint innodb_auto_extend_increment;
178
 
typedef constrained_check<size_t, SIZE_MAX, 5242880, 1048576> buffer_pool_constraint;
179
 
static buffer_pool_constraint innobase_buffer_pool_size;
180
 
typedef constrained_check<uint32_t, MAX_BUFFER_POOLS, 1> buffer_pool_instances_constraint;
181
 
static buffer_pool_instances_constraint innobase_buffer_pool_instances;
182
 
typedef constrained_check<uint32_t, UINT32_MAX, 100> io_capacity_constraint;
183
 
static io_capacity_constraint innodb_io_capacity;
184
 
typedef constrained_check<uint32_t, 5000, 1> purge_batch_constraint;
185
 
static purge_batch_constraint innodb_purge_batch_size;
186
 
typedef constrained_check<uint32_t, 1, 0> purge_threads_constraint;
187
 
static purge_threads_constraint innodb_n_purge_threads;
188
 
typedef constrained_check<uint32_t, 2, 0> trinary_constraint;
189
 
static trinary_constraint innodb_flush_log_at_trx_commit;
190
 
typedef constrained_check<unsigned int, 99, 0> max_dirty_pages_constraint;
191
 
static max_dirty_pages_constraint innodb_max_dirty_pages_pct;
192
 
static uint64_constraint innodb_max_purge_lag;
193
 
static uint64_nonzero_constraint innodb_stats_sample_pages;
194
 
typedef constrained_check<uint32_t, 64, 1> io_threads_constraint;
195
 
static io_threads_constraint innobase_read_io_threads;
196
 
static io_threads_constraint innobase_write_io_threads;
197
 
 
198
 
typedef constrained_check<uint32_t, 1000, 0> concurrency_constraint;
199
 
static concurrency_constraint innobase_commit_concurrency;
200
 
static concurrency_constraint innobase_thread_concurrency;
201
 
static uint32_nonzero_constraint innodb_concurrency_tickets;
202
 
 
203
 
typedef constrained_check<int64_t, INT64_MAX, 1024*1024, 1024*1024> log_file_constraint;
204
 
static log_file_constraint innobase_log_file_size;
205
 
 
206
 
static uint64_constraint innodb_replication_delay;
207
 
 
208
 
/** Percentage of the buffer pool to reserve for 'old' blocks.
209
 
Connected to buf_LRU_old_ratio. */
210
 
typedef constrained_check<uint32_t, 95, 5> old_blocks_constraint;
211
 
static old_blocks_constraint innobase_old_blocks_pct;
212
 
 
213
 
static uint32_constraint innodb_sync_spin_loops;
214
 
static uint32_constraint innodb_spin_wait_delay;
215
 
static uint32_constraint innodb_thread_sleep_delay;
216
 
 
217
 
typedef constrained_check<uint32_t, 64, 0> read_ahead_threshold_constraint;
218
 
static read_ahead_threshold_constraint innodb_read_ahead_threshold;
 
172
static plugin::TableFunction* status_table_function_ptr= NULL;
 
173
static plugin::TableFunction* cmp_tool= NULL;
 
174
static plugin::TableFunction* cmp_reset_tool= NULL;
 
175
static plugin::TableFunction* cmp_mem_tool= NULL;
 
176
static plugin::TableFunction* cmp_mem_reset_tool= NULL;
 
177
static plugin::TableFunction* innodb_trx_tool= NULL;
 
178
static plugin::TableFunction* innodb_locks_tool= NULL;
 
179
static plugin::TableFunction* innodb_lock_waits_tool= NULL;
 
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;
219
193
 
220
194
/* The default values for the following char* start-up parameters
221
195
are determined in innobase_init below: */
222
196
 
223
 
std::string innobase_data_home_dir;
224
 
std::string innobase_data_file_path;
225
 
std::string innobase_log_group_home_dir;
226
 
static string innobase_file_format_name;
227
 
static string innobase_change_buffering;
228
 
 
229
 
/* The highest file format being used in the database. The value can be
230
 
set by user, however, it will be adjusted to the newer file format if
231
 
a table of such format is created/opened. */
232
 
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;
233
211
 
234
212
/* Below we have boolean-valued start-up parameters, and their default
235
213
values */
236
214
 
237
 
typedef constrained_check<uint32_t, 2, 0> trinary_constraint;
238
 
static trinary_constraint innobase_fast_shutdown;
239
 
 
240
 
/* "innobase_file_format_check" decides whether we would continue
241
 
booting the server if the file format stamped on the system
242
 
table space exceeds the maximum file format supported
243
 
by the server. Can be set during server startup at command
244
 
line or configure file, and a read only variable after
245
 
server startup */
246
 
 
247
 
/* If a new file format is introduced, the file format
248
 
name needs to be updated accordingly. Please refer to
249
 
file_format_name_map[] defined in trx0sys.c for the next
250
 
file format name. */
251
 
 
252
 
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 */
253
220
static my_bool  innobase_use_doublewrite    = TRUE;
254
221
static my_bool  innobase_use_checksums      = TRUE;
255
222
static my_bool  innobase_rollback_on_timeout    = FALSE;
256
223
static my_bool  innobase_create_status_file   = FALSE;
257
 
static bool innobase_use_replication_log;
258
 
static bool support_xa;
259
 
static bool strict_mode;
260
 
typedef constrained_check<uint32_t, 1024*1024*1024, 1> lock_wait_constraint;
261
 
static lock_wait_constraint lock_wait_timeout;
 
224
static my_bool  innobase_stats_on_metadata    = TRUE;
262
225
 
263
226
static char*  internal_innobase_data_file_path  = NULL;
264
227
 
 
228
static char*  innodb_version_str = (char*) INNODB_VERSION_STR;
 
229
 
265
230
/* The following counter is used to convey information to InnoDB
266
231
about server activity: in selects it is not sensible to call
267
232
srv_active_wake_master_thread after each fetch or search, we only do
279
244
/** Allowed values of innodb_change_buffering */
280
245
static const char* innobase_change_buffering_values[IBUF_USE_COUNT] = {
281
246
  "none",   /* IBUF_USE_NONE */
282
 
  "inserts",    /* IBUF_USE_INSERT */
283
 
  "deletes",    /* IBUF_USE_DELETE_MARK */
284
 
  "changes",    /* IBUF_USE_INSERT_DELETE_MARK */
285
 
  "purges",     /* IBUF_USE_DELETE */
286
 
  "all"         /* IBUF_USE_ALL */
 
247
  "inserts" /* IBUF_USE_INSERT */
287
248
};
288
249
 
289
 
/* "GEN_CLUST_INDEX" is the name reserved for Innodb default
290
 
system primary index. */
291
 
static const char innobase_index_reserve_name[]= "GEN_CLUST_INDEX";
292
 
 
293
250
/********************************************************************
294
251
Gives the file extension of an InnoDB single-table tablespace. */
295
252
static const char* ha_innobase_exts[] = {
333
290
      srv_free_paths_and_sizes();
334
291
      if (internal_innobase_data_file_path)
335
292
        free(internal_innobase_data_file_path);
 
293
      pthread_mutex_destroy(&innobase_share_mutex);
 
294
      pthread_mutex_destroy(&prepare_commit_mutex);
 
295
      pthread_mutex_destroy(&commit_threads_m);
 
296
      pthread_mutex_destroy(&commit_cond_m);
 
297
      pthread_cond_destroy(&commit_cond);
336
298
    }
337
 
    
338
 
    /* These get strdup'd from vm variables */
339
 
 
340
299
  }
341
300
 
342
301
private:
366
325
  {
367
326
    return doRollback(session, all); /* XA rollback just does a SQL ROLLBACK */
368
327
  }
369
 
  virtual uint64_t doGetCurrentTransactionId(Session *session);
370
 
  virtual uint64_t doGetNewTransactionId(Session *session);
371
328
  virtual int doCommit(Session* session, bool all);
372
329
  virtual int doRollback(Session* session, bool all);
373
330
 
411
368
        /* out: 0 or error number */
412
369
    ::drizzled::XID *xid);  /* in: X/Open XA transaction identification */
413
370
 
414
 
  virtual Cursor *create(Table &table)
 
371
  virtual Cursor *create(TableShare &table)
415
372
  {
416
373
    return new ha_innobase(*this, table);
417
374
  }
422
379
  doDropSchema(
423
380
  /*===================*/
424
381
        /* out: error number */
425
 
    const identifier::Schema  &identifier); /* in: database path; inside InnoDB the name
 
382
    const SchemaIdentifier  &identifier); /* in: database path; inside InnoDB the name
426
383
        of the last directory in the path is used as
427
384
        the database name: for example, in 'mysql/data/test'
428
385
        the database name is 'test' */
461
418
 
462
419
  UNIV_INTERN int doCreateTable(Session &session,
463
420
                                Table &form,
464
 
                                const identifier::Table &identifier,
 
421
                                const TableIdentifier &identifier,
465
422
                                message::Table&);
466
 
  UNIV_INTERN int doRenameTable(Session&, const identifier::Table &from, const identifier::Table &to);
467
 
  UNIV_INTERN int doDropTable(Session &session, const identifier::Table &identifier);
 
423
  UNIV_INTERN int doRenameTable(Session&, const TableIdentifier &from, const TableIdentifier &to);
 
424
  UNIV_INTERN int doDropTable(Session &session, const TableIdentifier &identifier);
468
425
 
469
 
  UNIV_INTERN virtual bool get_error_message(int error, String *buf) const;
 
426
  UNIV_INTERN virtual bool get_error_message(int error, String *buf);
470
427
 
471
428
  UNIV_INTERN uint32_t max_supported_keys() const;
472
429
  UNIV_INTERN uint32_t max_supported_key_length() const;
483
440
  }
484
441
 
485
442
  int doGetTableDefinition(drizzled::Session& session,
486
 
                           const identifier::Table &identifier,
 
443
                           const TableIdentifier &identifier,
487
444
                           drizzled::message::Table &table_proto);
488
445
 
489
 
  bool doDoesTableExist(drizzled::Session& session, const identifier::Table &identifier);
 
446
  void doGetTableNames(drizzled::CachedDirectory &directory,
 
447
                       const drizzled::SchemaIdentifier &schema_identifier,
 
448
                       std::set<std::string> &set_of_names);
 
449
 
 
450
  bool doDoesTableExist(drizzled::Session& session, const TableIdentifier &identifier);
490
451
 
491
452
  void doGetTableIdentifiers(drizzled::CachedDirectory &directory,
492
 
                             const drizzled::identifier::Schema &schema_identifier,
493
 
                             drizzled::identifier::Table::vector &set_of_identifiers);
 
453
                             const drizzled::SchemaIdentifier &schema_identifier,
 
454
                             drizzled::TableIdentifiers &set_of_identifiers);
494
455
  bool validateCreateTableOption(const std::string &key, const std::string &state);
495
456
  void dropTemporarySchema();
496
457
 
518
479
}
519
480
 
520
481
void InnobaseEngine::doGetTableIdentifiers(drizzled::CachedDirectory &directory,
521
 
                                           const drizzled::identifier::Schema &schema_identifier,
522
 
                                           drizzled::identifier::Table::vector &set_of_identifiers)
 
482
                                           const drizzled::SchemaIdentifier &schema_identifier,
 
483
                                           drizzled::TableIdentifiers &set_of_identifiers)
523
484
{
524
485
  CachedDirectory::Entries entries= directory.getEntries();
525
486
 
526
 
  std::string search_string(schema_identifier.getSchemaName());
527
 
 
528
 
  boost::algorithm::to_lower(search_string);
529
 
 
530
 
  if (search_string.compare("data_dictionary") == 0)
531
 
  {
532
 
    set_of_identifiers.push_back(identifier::Table(schema_identifier.getSchemaName(), "SYS_REPLICATION_LOG"));
533
 
  }
534
 
 
535
487
  for (CachedDirectory::Entries::iterator entry_iter= entries.begin(); 
536
488
       entry_iter != entries.end(); ++entry_iter)
537
489
  {
547
499
    { }
548
500
    else
549
501
    {
550
 
      std::string path;
551
 
      path+= directory.getPath();
552
 
      path+= FN_LIBCHAR;
553
 
      path+= entry->filename;
554
 
 
555
 
      message::Table definition;
556
 
      if (StorageEngine::readTableFile(path, definition))
557
 
      {
558
 
        /* 
559
 
           Using schema_identifier here to stop unused warning, could use
560
 
           definition.schema() instead
561
 
        */
562
 
        identifier::Table identifier(schema_identifier.getSchemaName(), definition.name());
563
 
        set_of_identifiers.push_back(identifier);
564
 
      }
 
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));
565
510
    }
566
511
  }
567
512
}
568
513
 
569
 
bool InnobaseEngine::doDoesTableExist(Session &session, const identifier::Table &identifier)
 
514
bool InnobaseEngine::doDoesTableExist(Session &session, const TableIdentifier &identifier)
570
515
{
571
516
  string proto_path(identifier.getPath());
572
517
  proto_path.append(DEFAULT_FILE_EXTENSION);
573
518
 
574
 
  if (session.getMessageCache().doesTableMessageExist(identifier))
575
 
    return true;
576
 
 
577
 
  std::string search_string(identifier.getPath());
578
 
  boost::algorithm::to_lower(search_string);
579
 
 
580
 
  if (search_string.compare("data_dictionary/sys_replication_log") == 0)
 
519
  if (session.doesTableMessageExist(identifier))
581
520
    return true;
582
521
 
583
522
  if (access(proto_path.c_str(), F_OK))
589
528
}
590
529
 
591
530
int InnobaseEngine::doGetTableDefinition(Session &session,
592
 
                                         const identifier::Table &identifier,
 
531
                                         const TableIdentifier &identifier,
593
532
                                         message::Table &table_proto)
594
533
{
595
534
  string proto_path(identifier.getPath());
596
535
  proto_path.append(DEFAULT_FILE_EXTENSION);
597
536
 
598
537
  // First we check the temporary tables.
599
 
  if (session.getMessageCache().getTableMessage(identifier, table_proto))
600
 
    return EEXIST;
601
 
 
602
 
  if (read_replication_log_table_message(identifier.getTableName().c_str(), &table_proto) == 0)
 
538
  if (session.getTableMessage(identifier, table_proto))
603
539
    return EEXIST;
604
540
 
605
541
  if (access(proto_path.c_str(), F_OK))
613
549
  return ENOENT;
614
550
}
615
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
/*==========================================*/
616
595
 
617
596
/************************************************************//**
618
597
Validate the file format name and return its corresponding id.
625
604
            name */
626
605
/************************************************************//**
627
606
Validate the file format check config parameters, as a side effect it
628
 
sets the srv_max_file_format_at_startup variable.
629
 
@return the format_id if valid config value, otherwise, return -1 */
630
 
static
631
 
int
632
 
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(
633
621
/*================================*/
634
 
  const char* format_max);    /*!< in: parameter value */
 
622
  const char* format_check);    /*!< in: parameter value */
635
623
 
636
624
static const char innobase_engine_name[]= "InnoDB";
637
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
 
638
674
 
639
675
/*****************************************************************//**
640
676
Commits a transaction in an InnoDB database. */
661
697
  (char*) &export_vars.innodb_buffer_pool_pages_misc,   SHOW_LONG},
662
698
  {"buffer_pool_pages_total",
663
699
  (char*) &export_vars.innodb_buffer_pool_pages_total,    SHOW_LONG},
664
 
  {"buffer_pool_read_ahead",
665
 
  (char*) &export_vars.innodb_buffer_pool_read_ahead, SHOW_LONG},
666
 
  {"buffer_pool_read_ahead_evicted",
667
 
  (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},
668
704
  {"buffer_pool_read_requests",
669
705
  (char*) &export_vars.innodb_buffer_pool_read_requests,  SHOW_LONG},
670
706
  {"buffer_pool_reads",
798
834
DRIZZLE: Note, we didn't change this name to avoid more ifdef forking 
799
835
         in non-Cursor code.
800
836
@return true if session is the replication thread */
801
 
UNIV_INTERN
 
837
extern "C" UNIV_INTERN
802
838
ibool
803
839
thd_is_replication_slave_thread(
804
840
/*============================*/
805
 
  drizzled::Session* ) /*!< in: thread handle (Session*) */
 
841
  void* ) /*!< in: thread handle (Session*) */
806
842
{
807
843
  return false;
808
844
}
872
908
DRIZZLE: Note, we didn't change this name to avoid more ifdef forking 
873
909
         in non-Cursor code.
874
910
@return true if non-transactional tables have been edited */
875
 
UNIV_INTERN
 
911
extern "C" UNIV_INTERN
876
912
ibool
877
913
thd_has_edited_nontrans_tables(
878
914
/*===========================*/
879
 
  drizzled::Session *session)  /*!< in: thread handle (Session*) */
 
915
  void*   session)  /*!< in: thread handle (Session*) */
880
916
{
881
 
  return((ibool)session->transaction.all.hasModifiedNonTransData());
 
917
  return((ibool)((Session *)session)->transaction.all.hasModifiedNonTransData());
882
918
}
883
919
 
884
920
/******************************************************************//**
885
921
Returns true if the thread is executing a SELECT statement.
886
922
@return true if session is executing SELECT */
887
 
UNIV_INTERN
 
923
extern "C" UNIV_INTERN
888
924
ibool
889
925
thd_is_select(
890
926
/*==========*/
891
 
  const drizzled::Session *session)  /*!< in: thread handle (Session*) */
 
927
  const void* session)  /*!< in: thread handle (Session*) */
892
928
{
893
 
  return(session->getSqlCommand() == SQLCOM_SELECT);
 
929
  return(session_sql_command((const Session*) session) == SQLCOM_SELECT);
894
930
}
895
931
 
896
932
/******************************************************************//**
897
933
Returns true if the thread supports XA,
898
934
global value of innodb_supports_xa if session is NULL.
899
935
@return true if session has XA support */
900
 
UNIV_INTERN
 
936
extern "C" UNIV_INTERN
901
937
ibool
902
938
thd_supports_xa(
903
939
/*============*/
904
 
  drizzled::Session* )  /*!< in: thread handle (Session*), or NULL to query
 
940
  void* session)  /*!< in: thread handle (Session*), or NULL to query
905
941
        the global innodb_supports_xa */
906
942
{
907
 
  /* TODO: Add support here for per-session value */
908
 
  return(support_xa);
 
943
  return(SessionVAR((Session*) session, support_xa));
909
944
}
910
945
 
911
946
/******************************************************************//**
912
947
Returns the lock wait timeout for the current connection.
913
948
@return the lock wait timeout, in seconds */
914
 
UNIV_INTERN
 
949
extern "C" UNIV_INTERN
915
950
ulong
916
951
thd_lock_wait_timeout(
917
952
/*==================*/
918
 
  drizzled::Session*)  /*!< in: thread handle (Session*), or NULL to query
 
953
  void* session)  /*!< in: thread handle (Session*), or NULL to query
919
954
      the global innodb_lock_wait_timeout */
920
955
{
921
 
  /* TODO: Add support here for per-session value */
922
956
  /* According to <drizzle/plugin.h>, passing session == NULL
923
957
  returns the global value of the session variable. */
924
 
  return((ulong)lock_wait_timeout.get());
925
 
}
926
 
 
927
 
/******************************************************************//**
928
 
Set the time waited for the lock for the current query. */
929
 
UNIV_INTERN
930
 
void
931
 
thd_set_lock_wait_time(
932
 
/*===================*/
933
 
        drizzled::Session*      in_session,     /*!< in: thread handle (THD*) */
934
 
        ulint   value)  /*!< in: time waited for the lock */
935
 
{
936
 
  if (in_session)
937
 
    in_session->utime_after_lock+= value;
 
958
  return(SessionVAR((Session*) session, lock_wait_timeout));
938
959
}
939
960
 
940
961
/********************************************************************//**
949
970
  return *(trx_t**) session->getEngineData(innodb_engine_ptr);
950
971
}
951
972
 
952
 
 
953
 
plugin::ReplicationReturnCode ReplicationLog::apply(Session &session,
954
 
                                                    const message::Transaction &message)
955
 
{
956
 
  char *data= new char[message.ByteSize()];
957
 
 
958
 
  message.SerializeToArray(data, message.ByteSize());
959
 
 
960
 
  trx_t *trx= session_to_trx(&session);
961
 
 
962
 
  uint64_t trx_id= message.transaction_context().transaction_id();
963
 
  uint32_t seg_id= message.segment_id();
964
 
  uint64_t end_timestamp= message.transaction_context().end_timestamp();
965
 
  bool is_end_segment= message.end_segment();
966
 
  trx->log_commit_id= TRUE;
967
 
  ulint error= insert_replication_message(data, message.ByteSize(), trx, trx_id,
968
 
               end_timestamp, is_end_segment, seg_id);
969
 
  (void)error;
970
 
 
971
 
  delete[] data;
972
 
 
973
 
  return plugin::SUCCESS;
974
 
}
975
 
 
976
973
/********************************************************************//**
977
974
Call this function when mysqld passes control to the client. That is to
978
975
avoid deadlocks on the adaptive hash S-latch possibly held by session. For more
1022
1019
about a possible transaction rollback inside InnoDB caused by a lock wait
1023
1020
timeout or a deadlock.
1024
1021
@return MySQL error code */
1025
 
UNIV_INTERN
 
1022
extern "C" UNIV_INTERN
1026
1023
int
1027
1024
convert_error_code_to_mysql(
1028
1025
/*========================*/
1034
1031
  case DB_SUCCESS:
1035
1032
    return(0);
1036
1033
 
1037
 
  case DB_INTERRUPTED:
1038
 
    my_error(ER_QUERY_INTERRUPTED, MYF(0));
1039
 
    /* fall through */
1040
 
 
1041
 
  case DB_FOREIGN_EXCEED_MAX_CASCADE:
1042
 
    push_warning_printf(session, DRIZZLE_ERROR::WARN_LEVEL_WARN,
1043
 
                        HA_ERR_ROW_IS_REFERENCED,
1044
 
                        "InnoDB: Cannot delete/update "
1045
 
                        "rows with cascading foreign key "
1046
 
                        "constraints that exceed max "
1047
 
                        "depth of %d. Please "
1048
 
                        "drop extra constraints and try "
1049
 
                        "again", DICT_FK_MAX_RECURSIVE_LOAD);
1050
 
    /* fall through */
1051
 
 
1052
1034
  case DB_ERROR:
1053
1035
  default:
1054
1036
    return(-1); /* unspecified error */
1055
1037
 
1056
1038
  case DB_DUPLICATE_KEY:
1057
 
    /* Be cautious with returning this error, since
1058
 
       mysql could re-enter the storage layer to get
1059
 
       duplicated key info, the operation requires a
1060
 
       valid table handle and/or transaction information,
1061
 
       which might not always be available in the error
1062
 
       handling stage. */
1063
1039
    return(HA_ERR_FOUND_DUPP_KEY);
1064
1040
 
1065
1041
  case DB_FOREIGN_DUPLICATE_KEY:
1076
1052
    tell it also to MySQL so that MySQL knows to empty the
1077
1053
    cached binlog for this transaction */
1078
1054
 
1079
 
    session->markTransactionForRollback(TRUE);
 
1055
    mark_transaction_to_rollback(session, TRUE);
1080
1056
 
1081
1057
    return(HA_ERR_LOCK_DEADLOCK);
1082
1058
 
1085
1061
    latest SQL statement in a lock wait timeout. Previously, we
1086
1062
    rolled back the whole transaction. */
1087
1063
 
1088
 
    session->markTransactionForRollback((bool)row_rollback_on_timeout);
 
1064
    mark_transaction_to_rollback(session, (bool)row_rollback_on_timeout);
1089
1065
 
1090
1066
    return(HA_ERR_LOCK_WAIT_TIMEOUT);
1091
1067
 
1096
1072
    return(HA_ERR_ROW_IS_REFERENCED);
1097
1073
 
1098
1074
  case DB_CANNOT_ADD_CONSTRAINT:
1099
 
  case DB_CHILD_NO_INDEX:
1100
 
  case DB_PARENT_NO_INDEX:
1101
1075
    return(HA_ERR_CANNOT_ADD_FOREIGN);
1102
1076
 
1103
1077
  case DB_CANNOT_DROP_CONSTRAINT:
1121
1095
 
1122
1096
  case DB_TOO_BIG_RECORD:
1123
1097
    my_error(ER_TOO_BIG_ROWSIZE, MYF(0),
1124
 
             page_get_free_space_of_empty(flags & DICT_TF_COMPACT) / 2);
 
1098
       page_get_free_space_of_empty(flags
 
1099
                  & DICT_TF_COMPACT) / 2);
1125
1100
    return(HA_ERR_TO_BIG_ROW);
1126
1101
 
1127
1102
  case DB_NO_SAVEPOINT:
1132
1107
    tell it also to MySQL so that MySQL knows to empty the
1133
1108
    cached binlog for this transaction */
1134
1109
 
1135
 
    session->markTransactionForRollback(TRUE);
 
1110
    mark_transaction_to_rollback(session, TRUE);
1136
1111
 
1137
1112
    return(HA_ERR_LOCK_TABLE_FULL);
1138
1113
 
1147
1122
    and the actual error code name could very well be different.
1148
1123
    This will require some monitoring, ie. the status
1149
1124
    of this request on our part.*/
1150
 
 
1151
 
    /* New error code HA_ERR_TOO_MANY_CONCURRENT_TRXS is only
1152
 
       available in 5.1.38 and later, but the plugin should still
1153
 
       work with previous versions of MySQL.
1154
 
       In Drizzle we seem to not have this yet.
1155
 
    */
1156
 
#ifdef HA_ERR_TOO_MANY_CONCURRENT_TRXS
1157
 
    return(HA_ERR_TOO_MANY_CONCURRENT_TRXS);
1158
 
#else /* HA_ERR_TOO_MANY_CONCURRENT_TRXS */
 
1125
#ifdef ER_TOO_MANY_CONCURRENT_TRXS
 
1126
    return(ER_TOO_MANY_CONCURRENT_TRXS);
 
1127
#else
1159
1128
    return(HA_ERR_RECORD_FILE_FULL);
1160
 
#endif /* HA_ERR_TOO_MANY_CONCURRENT_TRXS */
 
1129
#endif
1161
1130
  case DB_UNSUPPORTED:
1162
1131
    return(HA_ERR_UNSUPPORTED);
1163
1132
  }
1164
1133
}
1165
1134
 
1166
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
  LOCK_thread_count.lock();
 
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
  LOCK_thread_count.unlock();
 
1173
}
 
1174
 
1167
1175
/*************************************************************//**
1168
1176
Prints info of a Session object (== user session thread) to the given file. */
1169
 
UNIV_INTERN
 
1177
extern "C" UNIV_INTERN
1170
1178
void
1171
1179
innobase_mysql_print_thd(
1172
1180
/*=====================*/
1173
1181
  FILE* f,    /*!< in: output stream */
1174
 
  drizzled::Session *in_session,  /*!< in: pointer to a Drizzle Session object */
 
1182
  void * in_session,  /*!< in: pointer to a Drizzle Session object */
1175
1183
  uint  )   /*!< in: max query length to print, or 0 to
1176
1184
           use the default max length */
1177
1185
{
1178
 
  drizzled::identifier::User::const_shared_ptr user_identifier(in_session->user());
1179
 
 
 
1186
  Session *session= reinterpret_cast<Session *>(in_session);
1180
1187
  fprintf(f,
1181
1188
          "Drizzle thread %"PRIu64", query id %"PRIu64", %s, %s, %s ",
1182
 
          static_cast<uint64_t>(in_session->getSessionId()),
1183
 
          static_cast<uint64_t>(in_session->getQueryId()),
1184
 
          getServerHostname().c_str(),
1185
 
          user_identifier->address().c_str(),
1186
 
          user_identifier->username().c_str()
1187
 
  );
1188
 
  fprintf(f, "\n%s", in_session->getQueryString()->c_str());
 
1189
          static_cast<uint64_t>(session->getSessionId()),
 
1190
          static_cast<uint64_t>(session->getQueryId()),
 
1191
          glob_hostname,
 
1192
          session->getSecurityContext().getIp().c_str(),
 
1193
          session->getSecurityContext().getUser().c_str()
 
1194
  );
 
1195
  fprintf(f,
 
1196
          "\n%s", session->getQueryString().c_str()
 
1197
  );
1189
1198
  putc('\n', f);
1190
1199
}
1191
1200
 
1192
1201
/******************************************************************//**
1193
1202
Get the variable length bounds of the given character set. */
1194
 
UNIV_INTERN
 
1203
extern "C" UNIV_INTERN
1195
1204
void
1196
1205
innobase_get_cset_width(
1197
1206
/*====================*/
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;
1218
1225
 
1219
1226
/******************************************************************//**
1220
1227
Converts an identifier to a table name. */
1221
 
UNIV_INTERN
 
1228
extern "C" UNIV_INTERN
1222
1229
void
1223
1230
innobase_convert_from_table_id(
1224
1231
/*===========================*/
1232
1239
 
1233
1240
/******************************************************************//**
1234
1241
Converts an identifier to UTF-8. */
1235
 
UNIV_INTERN
 
1242
extern "C" UNIV_INTERN
1236
1243
void
1237
1244
innobase_convert_from_id(
1238
1245
/*=====================*/
1247
1254
/******************************************************************//**
1248
1255
Compares NUL-terminated UTF-8 strings case insensitively.
1249
1256
@return 0 if a=b, <0 if a<b, >1 if a>b */
1250
 
UNIV_INTERN
 
1257
extern "C" UNIV_INTERN
1251
1258
int
1252
1259
innobase_strcasecmp(
1253
1260
/*================*/
1259
1266
 
1260
1267
/******************************************************************//**
1261
1268
Makes all characters in a NUL-terminated UTF-8 string lower case. */
1262
 
UNIV_INTERN
 
1269
extern "C" UNIV_INTERN
1263
1270
void
1264
1271
innobase_casedn_str(
1265
1272
/*================*/
1268
1275
  my_casedn_str(system_charset_info, a);
1269
1276
}
1270
1277
 
1271
 
UNIV_INTERN
 
1278
/**********************************************************************//**
 
1279
Determines the connection character set.
 
1280
@return connection character set */
 
1281
extern "C" UNIV_INTERN
 
1282
const void*
 
1283
innobase_get_charset(
 
1284
/*=================*/
 
1285
  void* mysql_session)  /*!< in: MySQL thread handle */
 
1286
{
 
1287
  return session_charset(static_cast<Session*>(mysql_session));
 
1288
}
 
1289
 
 
1290
extern "C" UNIV_INTERN
1272
1291
bool
1273
1292
innobase_isspace(
1274
1293
  const void *cs,
1277
1296
  return my_isspace(static_cast<const CHARSET_INFO *>(cs), char_to_test);
1278
1297
}
1279
1298
 
 
1299
UNIV_INTERN
 
1300
int
 
1301
innobase_fast_mutex_init(
 
1302
        os_fast_mutex_t*        fast_mutex)
 
1303
{
 
1304
  return pthread_mutex_init(fast_mutex, MY_MUTEX_INIT_FAST);
 
1305
}
 
1306
 
1280
1307
#if defined (__WIN__) && defined (MYSQL_DYNAMIC_PLUGIN)
1281
1308
/*******************************************************************//**
1282
1309
Map an OS error to an errno value. The OS error number is stored in
1283
1310
_doserrno and the mapped value is stored in errno) */
 
1311
extern "C"
1284
1312
void __cdecl
1285
1313
_dosmaperr(
1286
1314
  unsigned long); /*!< in: OS error value */
1288
1316
/*********************************************************************//**
1289
1317
Creates a temporary file.
1290
1318
@return temporary file descriptor, or < 0 on error */
1291
 
UNIV_INTERN
 
1319
extern "C" UNIV_INTERN
1292
1320
int
1293
1321
innobase_mysql_tmpfile(void)
1294
1322
/*========================*/
1368
1396
/*********************************************************************//**
1369
1397
Creates a temporary file.
1370
1398
@return temporary file descriptor, or < 0 on error */
1371
 
UNIV_INTERN
 
1399
extern "C" UNIV_INTERN
1372
1400
int
1373
1401
innobase_mysql_tmpfile(void)
1374
1402
/*========================*/
1375
1403
{
1376
1404
  int fd2 = -1;
1377
 
  int fd = ::drizzled::tmpfile("ib");
 
1405
  int fd = mysql_tmpfile("ib");
1378
1406
  if (fd >= 0) {
1379
1407
    /* Copy the file descriptor, so that the additional resources
1380
1408
    allocated by create_temp_file() can be freed by invoking
1407
1435
number of bytes that were written to "buf" is returned (including the
1408
1436
terminating NUL).
1409
1437
@return number of bytes that were written */
1410
 
UNIV_INTERN
 
1438
extern "C" UNIV_INTERN
1411
1439
ulint
1412
1440
innobase_raw_format(
1413
1441
/*================*/
1527
1555
/*********************************************************************//**
1528
1556
Allocates an InnoDB transaction for a MySQL Cursor object.
1529
1557
@return InnoDB transaction handle */
1530
 
UNIV_INTERN
 
1558
extern "C" UNIV_INTERN
1531
1559
trx_t*
1532
1560
innobase_trx_allocate(
1533
1561
/*==================*/
1541
1569
  trx = trx_allocate_for_mysql();
1542
1570
 
1543
1571
  trx->mysql_thd = session;
 
1572
  trx->mysql_query_str = session->query.c_str();
1544
1573
 
1545
1574
  innobase_trx_init(session, trx);
1546
1575
 
1579
1608
Construct ha_innobase Cursor. */
1580
1609
UNIV_INTERN
1581
1610
ha_innobase::ha_innobase(plugin::StorageEngine &engine_arg,
1582
 
                         Table &table_arg)
 
1611
                         TableShare &table_arg)
1583
1612
  :Cursor(engine_arg, table_arg),
1584
1613
  primary_key(0), /* needs initialization because index_flags() may be called 
1585
1614
                     before this is set to the real value. It's ok to have any 
1631
1660
  ulint   buflen, /*!< in: length of buf, in bytes */
1632
1661
  const char* id, /*!< in: identifier to convert */
1633
1662
  ulint   idlen,  /*!< in: length of id, in bytes */
1634
 
  drizzled::Session *session,/*!< in: MySQL connection thread, or NULL */
 
1663
  void*   session,/*!< in: MySQL connection thread, or NULL */
1635
1664
  ibool   file_id)/*!< in: TRUE=id is a table or database name;
1636
1665
        FALSE=id is an UTF-8 string */
1637
1666
{
1638
1667
  char nz[NAME_LEN + 1];
1639
 
  const size_t nz2_size= NAME_LEN + 1 + srv_mysql50_table_name_prefix.size();
1640
 
  boost::scoped_array<char> nz2(new char[nz2_size]);
 
1668
  char nz2[NAME_LEN + 1 + sizeof srv_mysql50_table_name_prefix];
1641
1669
 
1642
1670
  const char* s = id;
1643
1671
  int   q;
1654
1682
    memcpy(nz, id, idlen);
1655
1683
    nz[idlen] = 0;
1656
1684
 
1657
 
    s = nz2.get();
1658
 
    idlen = identifier::Table::filename_to_tablename(nz, nz2.get(), nz2_size);
 
1685
    s = nz2;
 
1686
    idlen = TableIdentifier::filename_to_tablename(nz, nz2, sizeof nz2);
1659
1687
  }
1660
1688
 
1661
1689
  /* See if the identifier needs to be quoted. */
1709
1737
Convert a table or index name to the MySQL system_charset_info (UTF-8)
1710
1738
and quote it if needed.
1711
1739
@return pointer to the end of buf */
1712
 
UNIV_INTERN
 
1740
extern "C" UNIV_INTERN
1713
1741
char*
1714
1742
innobase_convert_name(
1715
1743
/*==================*/
1717
1745
  ulint   buflen, /*!< in: length of buf, in bytes */
1718
1746
  const char* id, /*!< in: identifier to convert */
1719
1747
  ulint   idlen,  /*!< in: length of id, in bytes */
1720
 
  drizzled::Session *session,/*!< in: MySQL connection thread, or NULL */
 
1748
  void*   session,/*!< in: MySQL connection thread, or NULL */
1721
1749
  ibool   table_id)/*!< in: TRUE=id is a table or database name;
1722
1750
        FALSE=id is an index name */
1723
1751
{
1765
1793
/**********************************************************************//**
1766
1794
Determines if the currently running transaction has been interrupted.
1767
1795
@return TRUE if interrupted */
1768
 
UNIV_INTERN
 
1796
extern "C" UNIV_INTERN
1769
1797
ibool
1770
1798
trx_is_interrupted(
1771
1799
/*===============*/
1772
1800
  trx_t*  trx)  /*!< in: transaction */
1773
1801
{
1774
 
  return(trx && trx->mysql_thd && trx->mysql_thd->getKilled());
1775
 
}
1776
 
 
1777
 
/**********************************************************************//**
1778
 
Determines if the currently running transaction is in strict mode.
1779
 
@return TRUE if strict */
1780
 
UNIV_INTERN
1781
 
ibool
1782
 
trx_is_strict(
1783
 
/*==========*/
1784
 
        trx_t*  trx)    /*!< in: transaction */
1785
 
{
1786
 
        return(trx && trx->mysql_thd
1787
 
               && true);
 
1802
  return(trx && trx->mysql_thd && session_killed((Session*) trx->mysql_thd));
1788
1803
}
1789
1804
 
1790
1805
/**************************************************************//**
1800
1815
  prebuilt->read_just_key = 0;
1801
1816
}
1802
1817
 
1803
 
template<class T>
1804
 
void align_value(T& value, size_t align_val= 1024)
1805
 
{
1806
 
  value= value - (value % align_val);
1807
 
}
1808
 
 
1809
 
static void auto_extend_update(Session *, sql_var_t)
1810
 
{
1811
 
  srv_auto_extend_increment= innodb_auto_extend_increment.get();
1812
 
}
1813
 
 
1814
 
static void io_capacity_update(Session *, sql_var_t)
1815
 
{
1816
 
  srv_io_capacity= innodb_io_capacity.get();
1817
 
}
1818
 
 
1819
 
static void purge_batch_update(Session *, sql_var_t)
1820
 
{
1821
 
  srv_purge_batch_size= innodb_purge_batch_size.get();
1822
 
}
1823
 
 
1824
 
static void purge_threads_update(Session *, sql_var_t)
1825
 
{
1826
 
  srv_n_purge_threads= innodb_n_purge_threads.get();
1827
 
}
1828
 
 
1829
 
static void innodb_adaptive_hash_index_update(Session *, sql_var_t)
1830
 
{
1831
 
  if (btr_search_enabled)
1832
 
  {
1833
 
    btr_search_enable();
1834
 
  } else {
1835
 
    btr_search_disable();
1836
 
  }
1837
 
}
1838
 
 
1839
 
static void innodb_old_blocks_pct_update(Session *, sql_var_t)
1840
 
{
1841
 
  innobase_old_blocks_pct= buf_LRU_old_ratio_update(innobase_old_blocks_pct.get(), TRUE);
1842
 
}
1843
 
 
1844
 
static void innodb_thread_concurrency_update(Session *, sql_var_t)
1845
 
{
1846
 
  srv_thread_concurrency= innobase_thread_concurrency.get();
1847
 
}
1848
 
 
1849
 
static void innodb_sync_spin_loops_update(Session *, sql_var_t)
1850
 
{
1851
 
  srv_n_spin_wait_rounds= innodb_sync_spin_loops.get();
1852
 
}
1853
 
 
1854
 
static void innodb_spin_wait_delay_update(Session *, sql_var_t)
1855
 
{
1856
 
  srv_spin_wait_delay= innodb_spin_wait_delay.get();
1857
 
}
1858
 
 
1859
 
static void innodb_thread_sleep_delay_update(Session *, sql_var_t)
1860
 
{
1861
 
  srv_thread_sleep_delay= innodb_thread_sleep_delay.get();
1862
 
}
1863
 
 
1864
 
static void innodb_read_ahead_threshold_update(Session *, sql_var_t)
1865
 
{
1866
 
  srv_read_ahead_threshold= innodb_read_ahead_threshold.get();
1867
 
}
1868
 
 
1869
 
 
1870
 
static int innodb_commit_concurrency_validate(Session *session, set_var *var)
1871
 
{
1872
 
   uint64_t new_value= var->getInteger();
1873
 
 
1874
 
   if ((innobase_commit_concurrency.get() == 0 && new_value != 0) ||
1875
 
       (innobase_commit_concurrency.get() != 0 && new_value == 0))
1876
 
   {
1877
 
     push_warning_printf(session,
1878
 
                         DRIZZLE_ERROR::WARN_LEVEL_WARN,
1879
 
                         ER_WRONG_ARGUMENTS,
1880
 
                         _("Once InnoDB is running, innodb_commit_concurrency "
1881
 
                           "must not change between zero and nonzero."));
1882
 
     return 1;
1883
 
   }
1884
 
   return 0;
1885
 
}
1886
 
 
1887
 
/*************************************************************//**
1888
 
Check if it is a valid file format. This function is registered as
1889
 
a callback with MySQL.
1890
 
@return 0 for valid file format */
1891
 
static
1892
 
int
1893
 
innodb_file_format_name_validate(
1894
 
/*=============================*/
1895
 
  Session*      , /*!< in: thread handle */
1896
 
  set_var *var)
1897
 
{
1898
 
  const char *file_format_input = var->value->str_value.ptr();
1899
 
  if (file_format_input == NULL)
1900
 
    return 1;
1901
 
 
1902
 
  if (file_format_input != NULL) {
1903
 
    uint  format_id;
1904
 
 
1905
 
    format_id = innobase_file_format_name_lookup(
1906
 
      file_format_input);
1907
 
 
1908
 
    if (format_id <= DICT_TF_FORMAT_MAX) {
1909
 
      innobase_file_format_name =
1910
 
        trx_sys_file_format_id_to_name(format_id);
1911
 
 
1912
 
      return(0);
1913
 
    }
1914
 
  }
1915
 
 
1916
 
  return(1);
1917
 
}
1918
 
 
1919
 
/*************************************************************//**
1920
 
Check if it is a valid value of innodb_change_buffering. This function is
1921
 
registered as a callback with MySQL.
1922
 
@return 0 for valid innodb_change_buffering */
1923
 
static
1924
 
int
1925
 
innodb_change_buffering_validate(
1926
 
/*=============================*/
1927
 
  Session*      , /*!< in: thread handle */
1928
 
  set_var *var)
1929
 
{
1930
 
  const char *change_buffering_input = var->value->str_value.ptr();
1931
 
 
1932
 
  if (change_buffering_input == NULL)
1933
 
    return 1;
1934
 
 
1935
 
  ulint use;
1936
 
 
1937
 
  for (use = 0;
1938
 
       use < UT_ARR_SIZE(innobase_change_buffering_values);
1939
 
       ++use) {
1940
 
    if (!innobase_strcasecmp(change_buffering_input,
1941
 
                             innobase_change_buffering_values[use]))
1942
 
    {
1943
 
      ibuf_use= static_cast<ibuf_use_t>(use); 
1944
 
      return 0;
1945
 
    }
1946
 
  }
1947
 
 
1948
 
  return 1;
1949
 
}
1950
 
 
1951
 
 
1952
 
/*************************************************************//**
1953
 
Check if valid argument to innodb_file_format_max. This function
1954
 
is registered as a callback with MySQL.
1955
 
@return 0 for valid file format */
1956
 
static
1957
 
int
1958
 
innodb_file_format_max_validate(
1959
 
/*==============================*/
1960
 
  Session*   session, /*!< in: thread handle */
1961
 
  set_var *var)
1962
 
{
1963
 
  const char *file_format_input = var->value->str_value.ptr();
1964
 
  if (file_format_input == NULL)
1965
 
    return 1;
1966
 
 
1967
 
  if (file_format_input != NULL) {
1968
 
    int format_id = innobase_file_format_validate_and_set(file_format_input);
1969
 
 
1970
 
    if (format_id > DICT_TF_FORMAT_MAX) {
1971
 
      /* DEFAULT is "on", which is invalid at runtime. */
1972
 
      return 1;
1973
 
    }
1974
 
 
1975
 
    if (format_id >= 0) {
1976
 
      innobase_file_format_max.assign(
1977
 
                             trx_sys_file_format_id_to_name((uint)format_id));
1978
 
 
1979
 
      /* Update the max format id in the system tablespace. */
1980
 
      const char *name_buff;
1981
 
 
1982
 
      if (trx_sys_file_format_max_set(format_id, &name_buff))
1983
 
      {
1984
 
        errmsg_printf(error::WARN,
1985
 
                      " [Info] InnoDB: the file format in the system "
1986
 
                      "tablespace is now set to %s.\n", name_buff);
1987
 
        innobase_file_format_max= name_buff;
1988
 
      }
1989
 
      return(0);
1990
 
 
1991
 
    } else {
1992
 
      push_warning_printf(session,
1993
 
                          DRIZZLE_ERROR::WARN_LEVEL_WARN,
1994
 
                          ER_WRONG_ARGUMENTS,
1995
 
                          "InnoDB: invalid innodb_file_format_max "
1996
 
                          "value; can be any format up to %s "
1997
 
                          "or equivalent id of %d",
1998
 
                          trx_sys_file_format_id_to_name(DICT_TF_FORMAT_MAX),
1999
 
                          DICT_TF_FORMAT_MAX);
2000
 
    }
2001
 
  }
2002
 
 
2003
 
  return(1);
2004
 
}
2005
 
 
2006
 
 
2007
1818
/*********************************************************************//**
2008
1819
Opens an InnoDB database.
2009
1820
@return 0 on success, error code on failure */
2013
1824
/*==========*/
2014
1825
  module::Context &context) /*!< in: Drizzle Plugin Context */
2015
1826
{
 
1827
  static char current_dir[3];   /*!< Set if using current lib */
2016
1828
  int   err;
2017
1829
  bool    ret;
 
1830
  char    *default_path;
2018
1831
  uint    format_id;
2019
1832
  InnobaseEngine *actuall_engine_ptr;
2020
 
  const module::option_map &vm= context.getOptions();
2021
 
 
2022
 
  srv_auto_extend_increment= innodb_auto_extend_increment.get();
2023
 
  srv_io_capacity= innodb_io_capacity.get();
2024
 
  srv_purge_batch_size= innodb_purge_batch_size.get();
2025
 
  srv_n_purge_threads= innodb_n_purge_threads.get();
2026
 
  srv_flush_log_at_trx_commit= innodb_flush_log_at_trx_commit.get();
2027
 
  srv_max_buf_pool_modified_pct= innodb_max_dirty_pages_pct.get();
2028
 
  srv_max_purge_lag= innodb_max_purge_lag.get();
2029
 
  srv_stats_sample_pages= innodb_stats_sample_pages.get();
2030
 
  srv_n_free_tickets_to_enter= innodb_concurrency_tickets.get();
2031
 
  srv_replication_delay= innodb_replication_delay.get();
2032
 
  srv_thread_concurrency= innobase_thread_concurrency.get();
2033
 
  srv_n_spin_wait_rounds= innodb_sync_spin_loops.get();
2034
 
  srv_spin_wait_delay= innodb_spin_wait_delay.get();
2035
 
  srv_thread_sleep_delay= innodb_thread_sleep_delay.get();
2036
 
  srv_read_ahead_threshold= innodb_read_ahead_threshold.get();
2037
 
 
2038
 
  /* Inverted Booleans */
2039
 
 
2040
 
  innobase_use_checksums= (vm.count("disable-checksums")) ? false : true;
2041
 
  innobase_use_doublewrite= (vm.count("disable-doublewrite")) ? false : true;
2042
 
  srv_adaptive_flushing= (vm.count("disable-adaptive-flushing")) ? false : true;
2043
 
  srv_use_sys_malloc= (vm.count("use-internal-malloc")) ? false : true;
2044
 
  srv_use_native_aio= (vm.count("disable-native-aio")) ? false : true;
2045
 
  support_xa= (vm.count("disable-xa")) ? false : true;
2046
 
  btr_search_enabled= (vm.count("disable-adaptive-hash-index")) ? false : true;
2047
 
 
2048
 
 
2049
 
  /* Hafta do this here because we need to late-bind the default value */
2050
 
  if (vm.count("data-home-dir"))
2051
 
  {
2052
 
    innobase_data_home_dir= vm["data-home-dir"].as<string>();
2053
 
  }
2054
 
  else
2055
 
  {
2056
 
    innobase_data_home_dir= getDataHome().file_string();
2057
 
  }
2058
 
 
2059
 
 
2060
 
  if (vm.count("data-file-path"))
2061
 
  {
2062
 
    innobase_data_file_path= vm["data-file-path"].as<string>();
2063
 
  }
2064
 
 
2065
1833
 
2066
1834
  innodb_engine_ptr= actuall_engine_ptr= new InnobaseEngine(innobase_engine_name);
2067
1835
 
2069
1837
 
2070
1838
#ifdef UNIV_DEBUG
2071
1839
  static const char test_filename[] = "-@";
2072
 
  const size_t test_tablename_size= sizeof test_filename
2073
 
    + srv_mysql50_table_name_prefix.size();
2074
 
  boost::scoped_array test_tablename(new char[test_tablename_size]);
2075
 
  if ((test_tablename_size) - 1
2076
 
      != filename_to_tablename(test_filename, test_tablename.get(),
2077
 
                               test_tablename_size)
2078
 
      || strncmp(test_tablename.get(),
2079
 
                 srv_mysql50_table_name_prefix.c_str(),
2080
 
                 srv_mysql50_table_name_prefix.size())
2081
 
      || strcmp(test_tablename.get()
2082
 
                + srv_mysql50_table_name_prefix.size(),
 
1840
  char      test_tablename[sizeof test_filename
 
1841
    + sizeof srv_mysql50_table_name_prefix];
 
1842
  if ((sizeof test_tablename) - 1
 
1843
      != filename_to_tablename(test_filename, test_tablename,
 
1844
                               sizeof test_tablename)
 
1845
      || strncmp(test_tablename,
 
1846
                 srv_mysql50_table_name_prefix,
 
1847
                 sizeof srv_mysql50_table_name_prefix)
 
1848
      || strcmp(test_tablename
 
1849
                + sizeof srv_mysql50_table_name_prefix,
2083
1850
                test_filename)) {
2084
 
    errmsg_printf(error::ERROR, "tablename encoding has been changed");
 
1851
    errmsg_printf(ERRMSG_LVL_ERROR, "tablename encoding has been changed");
2085
1852
    goto error;
2086
1853
  }
2087
1854
#endif /* UNIV_DEBUG */
2088
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
 
2089
1875
  os_innodb_umask = (ulint)internal::my_umask;
2090
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;
2091
1893
 
2092
1894
  /* Set InnoDB initialization parameters according to the values
2093
1895
    read from MySQL .cnf file */
2096
1898
 
2097
1899
  /* The default dir for data files is the datadir of MySQL */
2098
1900
 
2099
 
  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);
2100
1903
 
2101
1904
  /* Set default InnoDB data file size to 10 MB and let it be
2102
1905
    auto-extending. Thus users can use InnoDB in >= 4.0 without having
2103
1906
    to specify any startup options. */
2104
1907
 
2105
 
  if (innobase_data_file_path.empty()) 
2106
 
  {
2107
 
    innobase_data_file_path= std::string("ibdata1:10M:autoextend");
 
1908
  if (!innobase_data_file_path) {
 
1909
    innobase_data_file_path = (char*) "ibdata1:10M:autoextend";
2108
1910
  }
2109
1911
 
2110
1912
  /* Since InnoDB edits the argument in the next call, we make another
2111
1913
    copy of it: */
2112
1914
 
2113
 
  internal_innobase_data_file_path = strdup(innobase_data_file_path.c_str());
 
1915
  internal_innobase_data_file_path = strdup(innobase_data_file_path);
2114
1916
 
2115
1917
  ret = (bool) srv_parse_data_file_paths_and_sizes(
2116
1918
                                                   internal_innobase_data_file_path);
2117
1919
  if (ret == FALSE) {
2118
 
    errmsg_printf(error::ERROR, "InnoDB: syntax error in innodb_data_file_path");
2119
 
 
 
1920
    errmsg_printf(ERRMSG_LVL_ERROR, 
 
1921
                  "InnoDB: syntax error in innodb_data_file_path");
2120
1922
mem_free_and_error:
2121
1923
    srv_free_paths_and_sizes();
2122
1924
    if (internal_innobase_data_file_path)
2128
1930
 
2129
1931
  /* The default dir for log files is the datadir of MySQL */
2130
1932
 
2131
 
  if (vm.count("log-group-home-dir"))
2132
 
  {
2133
 
    innobase_log_group_home_dir= vm["log-group-home-dir"].as<string>();
2134
 
  }
2135
 
  else
2136
 
  {
2137
 
    innobase_log_group_home_dir= getDataHome().file_string();
2138
 
  }
 
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 */
2139
1946
 
2140
1947
  ret = (bool)
2141
 
    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);
2142
1949
 
2143
 
  if (ret == FALSE || innobase_mirrored_log_groups.get() != 1) {
2144
 
    errmsg_printf(error::ERROR, _("syntax error in innodb_log_group_home_dir, or a "
2145
 
                                  "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");
2146
1953
 
2147
1954
    goto mem_free_and_error;
2148
1955
  }
2149
1956
 
2150
 
 
2151
1957
  /* Validate the file format by animal name */
2152
 
  if (vm.count("file-format"))
2153
 
  {
 
1958
  if (innobase_file_format_name != NULL) {
 
1959
 
2154
1960
    format_id = innobase_file_format_name_lookup(
2155
 
                                                 vm["file-format"].as<string>().c_str());
 
1961
                                                 innobase_file_format_name);
2156
1962
 
2157
1963
    if (format_id > DICT_TF_FORMAT_MAX) {
2158
1964
 
2159
 
      errmsg_printf(error::ERROR, "InnoDB: wrong innodb_file_format.");
 
1965
      errmsg_printf(ERRMSG_LVL_ERROR, "InnoDB: wrong innodb_file_format.");
2160
1966
 
2161
1967
      goto mem_free_and_error;
2162
1968
    }
2163
1969
  } else {
2164
 
    /* Set it to the default file format id.*/
 
1970
    /* Set it to the default file format id. Though this
 
1971
      should never happen. */
2165
1972
    format_id = 0;
2166
1973
  }
2167
1974
 
2168
1975
  srv_file_format = format_id;
2169
1976
 
2170
 
  innobase_file_format_name =
2171
 
    trx_sys_file_format_id_to_name(format_id);
2172
 
 
2173
 
  /* Check innobase_file_format_check variable */
2174
 
  if (!innobase_file_format_check)
2175
 
  {
2176
 
    /* Set the value to disable checking. */
2177
 
    srv_max_file_format_at_startup = DICT_TF_FORMAT_MAX + 1;
2178
 
  } else {
2179
 
    /* Set the value to the lowest supported format. */
2180
 
    srv_max_file_format_at_startup = DICT_TF_FORMAT_MIN;
2181
 
  }
2182
 
 
2183
 
  /* Did the user specify a format name that we support?
2184
 
     As a side effect it will update the variable
2185
 
     srv_max_file_format_at_startup */
2186
 
  if (innobase_file_format_validate_and_set(innobase_file_format_max.c_str()) < 0)
2187
 
  {
2188
 
    errmsg_printf(error::ERROR, _("InnoDB: invalid innodb_file_format_max value: "
2189
 
                                  "should be any value up to %s or its equivalent numeric id"),
2190
 
                  trx_sys_file_format_id_to_name(DICT_TF_FORMAT_MAX));
2191
 
    goto mem_free_and_error;
2192
 
  }
2193
 
 
2194
 
  if (vm.count("change-buffering"))
2195
 
  {
 
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) {
2196
2011
    ulint use;
2197
2012
 
2198
2013
    for (use = 0;
2199
2014
         use < UT_ARR_SIZE(innobase_change_buffering_values);
2200
2015
         use++) {
2201
2016
      if (!innobase_strcasecmp(
2202
 
                               innobase_change_buffering.c_str(),
 
2017
                               innobase_change_buffering,
2203
2018
                               innobase_change_buffering_values[use])) {
2204
 
        ibuf_use = static_cast<ibuf_use_t>(use);
 
2019
        ibuf_use = (ibuf_use_t) use;
2205
2020
        goto innobase_change_buffering_inited_ok;
2206
2021
      }
2207
2022
    }
2208
2023
 
2209
 
    errmsg_printf(error::ERROR, "InnoDB: invalid value innodb_change_buffering=%s",
2210
 
                  vm["change-buffering"].as<string>().c_str());
 
2024
    errmsg_printf(ERRMSG_LVL_ERROR,
 
2025
                  "InnoDB: invalid value "
 
2026
                  "innodb_file_format_check=%s",
 
2027
                  innobase_change_buffering);
2211
2028
    goto mem_free_and_error;
2212
2029
  }
2213
2030
 
2214
2031
innobase_change_buffering_inited_ok:
2215
2032
  ut_a((ulint) ibuf_use < UT_ARR_SIZE(innobase_change_buffering_values));
2216
 
  innobase_change_buffering = innobase_change_buffering_values[ibuf_use];
 
2033
  innobase_change_buffering = (char*)
 
2034
    innobase_change_buffering_values[ibuf_use];
2217
2035
 
2218
2036
  /* --------------------------------------------------*/
2219
2037
 
2220
 
  if (vm.count("flush-method") != 0)
2221
 
  {
2222
 
    srv_file_flush_method_str = (char *)vm["flush-method"].as<string>().c_str();
2223
 
  }
 
2038
  srv_file_flush_method_str = innobase_unix_file_flush_method;
2224
2039
 
2225
2040
  srv_n_log_groups = (ulint) innobase_mirrored_log_groups;
2226
2041
  srv_n_log_files = (ulint) innobase_log_files_in_group;
2227
2042
  srv_log_file_size = (ulint) innobase_log_file_size;
2228
2043
 
 
2044
#ifdef UNIV_LOG_ARCHIVE
 
2045
  srv_log_archive_on = (ulint) innobase_log_archive;
 
2046
#endif /* UNIV_LOG_ARCHIVE */
2229
2047
  srv_log_buffer_size = (ulint) innobase_log_buffer_size;
2230
2048
 
2231
2049
  srv_buf_pool_size = (ulint) innobase_buffer_pool_size;
2232
 
  srv_buf_pool_instances = (ulint) innobase_buffer_pool_instances;
2233
2050
 
2234
2051
  srv_mem_pool_size = (ulint) innobase_additional_mem_pool_size;
2235
2052
 
 
2053
  srv_n_file_io_threads = (ulint) innobase_file_io_threads;
2236
2054
  srv_n_read_io_threads = (ulint) innobase_read_io_threads;
2237
2055
  srv_n_write_io_threads = (ulint) innobase_write_io_threads;
2238
2056
 
2260
2078
 
2261
2079
  data_mysql_default_charset_coll = (ulint)default_charset_info->number;
2262
2080
 
 
2081
 
 
2082
  innobase_commit_concurrency_init_default();
 
2083
 
2263
2084
  /* Since we in this module access directly the fields of a trx
2264
2085
    struct, and due to different headers and flags it might happen that
2265
2086
    mutex_t has a different size in this module and in InnoDB
2268
2089
 
2269
2090
  err = innobase_start_or_create_for_mysql();
2270
2091
 
2271
 
  if (err != DB_SUCCESS)
2272
 
  {
2273
 
    goto mem_free_and_error;
2274
 
  }
2275
 
 
2276
 
  err = dict_create_sys_replication_log();
2277
 
 
2278
2092
  if (err != DB_SUCCESS) {
2279
2093
    goto mem_free_and_error;
2280
2094
  }
2281
2095
 
2282
 
 
2283
 
  innobase_old_blocks_pct = buf_LRU_old_ratio_update(innobase_old_blocks_pct.get(),
2284
 
                                                     TRUE);
2285
 
 
2286
2096
  innobase_open_tables = hash_create(200);
 
2097
  pthread_mutex_init(&innobase_share_mutex, MY_MUTEX_INIT_FAST);
 
2098
  pthread_mutex_init(&prepare_commit_mutex, MY_MUTEX_INIT_FAST);
 
2099
  pthread_mutex_init(&commit_threads_m, MY_MUTEX_INIT_FAST);
 
2100
  pthread_mutex_init(&commit_cond_m, MY_MUTEX_INIT_FAST);
 
2101
  pthread_cond_init(&commit_cond, NULL);
2287
2102
  innodb_inited= 1;
2288
2103
 
2289
2104
  actuall_engine_ptr->dropTemporarySchema();
2290
2105
 
2291
 
  context.add(new InnodbStatusTool);
 
2106
  status_table_function_ptr= new InnodbStatusTool;
2292
2107
 
2293
2108
  context.add(innodb_engine_ptr);
2294
2109
 
2295
 
  context.add(new(std::nothrow)CmpTool(false));
2296
 
 
2297
 
  context.add(new(std::nothrow)CmpTool(true));
2298
 
 
2299
 
  context.add(new(std::nothrow)CmpmemTool(false));
2300
 
 
2301
 
  context.add(new(std::nothrow)CmpmemTool(true));
2302
 
 
2303
 
  context.add(new(std::nothrow)InnodbTrxTool("INNODB_TRX"));
2304
 
 
2305
 
  context.add(new(std::nothrow)InnodbTrxTool("INNODB_LOCKS"));
2306
 
 
2307
 
  context.add(new(std::nothrow)InnodbTrxTool("INNODB_LOCK_WAITS"));
2308
 
 
2309
 
  context.add(new(std::nothrow)InnodbSysTablesTool());
2310
 
 
2311
 
  context.add(new(std::nothrow)InnodbSysTableStatsTool());
2312
 
 
2313
 
  context.add(new(std::nothrow)InnodbSysIndexesTool());
2314
 
 
2315
 
  context.add(new(std::nothrow)InnodbSysColumnsTool());
2316
 
 
2317
 
  context.add(new(std::nothrow)InnodbSysFieldsTool());
2318
 
 
2319
 
  context.add(new(std::nothrow)InnodbSysForeignTool());
2320
 
 
2321
 
  context.add(new(std::nothrow)InnodbSysForeignColsTool());
 
2110
  context.add(status_table_function_ptr);
 
2111
 
 
2112
  cmp_tool= new(std::nothrow)CmpTool(false);
 
2113
  context.add(cmp_tool);
 
2114
 
 
2115
  cmp_reset_tool= new(std::nothrow)CmpTool(true);
 
2116
  context.add(cmp_reset_tool);
 
2117
 
 
2118
  cmp_mem_tool= new(std::nothrow)CmpmemTool(false);
 
2119
  context.add(cmp_mem_tool);
 
2120
 
 
2121
  cmp_mem_reset_tool= new(std::nothrow)CmpmemTool(true);
 
2122
  context.add(cmp_mem_reset_tool);
 
2123
 
 
2124
  innodb_trx_tool= new(std::nothrow)InnodbTrxTool("INNODB_TRX");
 
2125
  context.add(innodb_trx_tool);
 
2126
 
 
2127
  innodb_locks_tool= new(std::nothrow)InnodbTrxTool("INNODB_LOCKS");
 
2128
  context.add(innodb_locks_tool);
 
2129
 
 
2130
  innodb_lock_waits_tool= new(std::nothrow)InnodbTrxTool("INNODB_LOCK_WAITS");
 
2131
  context.add(innodb_lock_waits_tool);
2322
2132
 
2323
2133
  context.add(new(std::nothrow)InnodbInternalTables());
2324
 
  context.add(new(std::nothrow)InnodbReplicationTable());
2325
 
 
2326
 
  if (innobase_use_replication_log)
2327
 
  {
2328
 
    ReplicationLog *replication_logger= new(std::nothrow)ReplicationLog();
2329
 
    context.add(replication_logger);
2330
 
    ReplicationLog::setup(replication_logger);
2331
 
  }
2332
 
 
2333
 
  context.registerVariable(new sys_var_const_string_val("data-home-dir", innobase_data_home_dir));
2334
 
  context.registerVariable(new sys_var_const_string_val("flush-method", 
2335
 
                                                        vm.count("flush-method") ?  vm["flush-method"].as<string>() : ""));
2336
 
  context.registerVariable(new sys_var_const_string_val("log-group-home-dir", innobase_log_group_home_dir));
2337
 
  context.registerVariable(new sys_var_const_string_val("data-file-path", innobase_data_file_path));
2338
 
  context.registerVariable(new sys_var_const_string_val("version", vm["version"].as<string>()));
2339
 
 
2340
 
 
2341
 
  context.registerVariable(new sys_var_bool_ptr_readonly("replication_log", &innobase_use_replication_log));
2342
 
  context.registerVariable(new sys_var_bool_ptr_readonly("checksums", &innobase_use_checksums));
2343
 
  context.registerVariable(new sys_var_bool_ptr_readonly("doublewrite", &innobase_use_doublewrite));
2344
 
  context.registerVariable(new sys_var_bool_ptr("file-per-table", &srv_file_per_table));
2345
 
  context.registerVariable(new sys_var_bool_ptr_readonly("file-format-check", &innobase_file_format_check));
2346
 
  context.registerVariable(new sys_var_bool_ptr("adaptive-flushing", &srv_adaptive_flushing));
2347
 
  context.registerVariable(new sys_var_bool_ptr("status-file", &innobase_create_status_file));
2348
 
  context.registerVariable(new sys_var_bool_ptr_readonly("use-sys-malloc", &srv_use_sys_malloc));
2349
 
  context.registerVariable(new sys_var_bool_ptr_readonly("use-native-aio", &srv_use_native_aio));
2350
 
 
2351
 
  context.registerVariable(new sys_var_bool_ptr("support-xa", &support_xa));
2352
 
  context.registerVariable(new sys_var_bool_ptr("strict_mode", &strict_mode));
2353
 
  context.registerVariable(new sys_var_constrained_value<uint32_t>("lock_wait_timeout", lock_wait_timeout));
2354
 
 
2355
 
  context.registerVariable(new sys_var_constrained_value_readonly<size_t>("additional_mem_pool_size",innobase_additional_mem_pool_size));
2356
 
  context.registerVariable(new sys_var_constrained_value<uint32_t>("autoextend_increment",
2357
 
                                                                   innodb_auto_extend_increment,
2358
 
                                                                   auto_extend_update));
2359
 
  context.registerVariable(new sys_var_constrained_value<uint32_t>("io_capacity",
2360
 
                                                                   innodb_io_capacity,
2361
 
                                                                   io_capacity_update));
2362
 
  context.registerVariable(new sys_var_constrained_value<uint32_t>("purge_batch_size",
2363
 
                                                                   innodb_purge_batch_size,
2364
 
                                                                   purge_batch_update));
2365
 
  context.registerVariable(new sys_var_constrained_value<uint32_t>("purge_threads",
2366
 
                                                                   innodb_n_purge_threads,
2367
 
                                                                   purge_threads_update));
2368
 
  context.registerVariable(new sys_var_constrained_value<uint32_t>("fast_shutdown", innobase_fast_shutdown));
2369
 
  context.registerVariable(new sys_var_std_string("file_format",
2370
 
                                                  innobase_file_format_name,
2371
 
                                                  innodb_file_format_name_validate));
2372
 
  context.registerVariable(new sys_var_std_string("change_buffering",
2373
 
                                                  innobase_change_buffering,
2374
 
                                                  innodb_change_buffering_validate));
2375
 
  context.registerVariable(new sys_var_std_string("file_format_max",
2376
 
                                                  innobase_file_format_max,
2377
 
                                                  innodb_file_format_max_validate));
2378
 
  context.registerVariable(new sys_var_constrained_value_readonly<size_t>("buffer_pool_size", innobase_buffer_pool_size));
2379
 
  context.registerVariable(new sys_var_constrained_value_readonly<int64_t>("log_file_size", innobase_log_file_size));
2380
 
  context.registerVariable(new sys_var_constrained_value_readonly<uint32_t>("flush_log_at_trx_commit",
2381
 
                                                  innodb_flush_log_at_trx_commit));
2382
 
  context.registerVariable(new sys_var_constrained_value_readonly<unsigned int>("max_dirty_pages_pct",
2383
 
                                                  innodb_max_dirty_pages_pct));
2384
 
  context.registerVariable(new sys_var_constrained_value_readonly<uint64_t>("max_purge_lag", innodb_max_purge_lag));
2385
 
  context.registerVariable(new sys_var_constrained_value_readonly<uint64_t>("stats_sample_pages", innodb_stats_sample_pages));
2386
 
  context.registerVariable(new sys_var_bool_ptr("adaptive_hash_index", &btr_search_enabled, innodb_adaptive_hash_index_update));
2387
 
 
2388
 
  context.registerVariable(new sys_var_constrained_value<uint32_t>("commit_concurrency",
2389
 
                                                                   innobase_commit_concurrency,
2390
 
                                                                   innodb_commit_concurrency_validate));
2391
 
  context.registerVariable(new sys_var_constrained_value<uint32_t>("concurrency_tickets",
2392
 
                                                                   innodb_concurrency_tickets));
2393
 
  context.registerVariable(new sys_var_constrained_value_readonly<uint32_t>("read_io_threads", innobase_read_io_threads));
2394
 
  context.registerVariable(new sys_var_constrained_value_readonly<uint32_t>("write_io_threads", innobase_write_io_threads));
2395
 
  context.registerVariable(new sys_var_constrained_value_readonly<uint64_t>("replication_delay", innodb_replication_delay));
2396
 
  context.registerVariable(new sys_var_constrained_value_readonly<uint32_t>("force_recovery", innobase_force_recovery));
2397
 
  context.registerVariable(new sys_var_constrained_value_readonly<size_t>("log_buffer_size", innobase_log_buffer_size));
2398
 
  context.registerVariable(new sys_var_constrained_value_readonly<uint32_t>("log_files_in_group", innobase_log_files_in_group));
2399
 
  context.registerVariable(new sys_var_constrained_value_readonly<uint32_t>("mirrored_log_groups", innobase_mirrored_log_groups));
2400
 
  context.registerVariable(new sys_var_constrained_value_readonly<uint32_t>("open_files", innobase_open_files));
2401
 
  context.registerVariable(new sys_var_constrained_value<uint32_t>("old_blocks_pct",
2402
 
                                                                   innobase_old_blocks_pct,
2403
 
                                                                   innodb_old_blocks_pct_update));
2404
 
  context.registerVariable(new sys_var_uint32_t_ptr("old_blocks_time", &buf_LRU_old_threshold_ms));
2405
 
  context.registerVariable(new sys_var_constrained_value<uint32_t>("sync_spin_loops", innodb_sync_spin_loops, innodb_sync_spin_loops_update));
2406
 
  context.registerVariable(new sys_var_constrained_value<uint32_t>("spin_wait_delay", innodb_spin_wait_delay, innodb_spin_wait_delay_update));
2407
 
  context.registerVariable(new sys_var_constrained_value<uint32_t>("thread_sleep_delay", innodb_thread_sleep_delay, innodb_thread_sleep_delay_update));
2408
 
  context.registerVariable(new sys_var_constrained_value<uint32_t>("thread_concurrency",
2409
 
                                                                   innobase_thread_concurrency,
2410
 
                                                                   innodb_thread_concurrency_update));
2411
 
  context.registerVariable(new sys_var_constrained_value<uint32_t>("read_ahead_threshold",
2412
 
                                                                   innodb_read_ahead_threshold,
2413
 
                                                                   innodb_read_ahead_threshold_update));
 
2134
 
2414
2135
  /* Get the current high water mark format. */
2415
 
  innobase_file_format_max = trx_sys_file_format_max_get();
2416
 
  btr_search_fully_disabled = (!btr_search_enabled);
 
2136
  innobase_file_format_check = (char*) trx_sys_file_format_max_get();
2417
2137
 
2418
2138
  return(FALSE);
2419
 
 
2420
2139
error:
2421
2140
  return(TRUE);
2422
2141
}
2513
2232
    trx_search_latch_release_if_reserved(trx);
2514
2233
  }
2515
2234
 
2516
 
  if (all)
2517
 
  {
 
2235
  if (all
 
2236
    || (!session_test_options(session, OPTION_NOT_AUTOCOMMIT | OPTION_BEGIN))) {
 
2237
 
2518
2238
    /* We were instructed to commit the whole transaction, or
2519
2239
    this is an SQL statement end and autocommit is on */
2520
2240
 
2521
2241
    /* We need current binlog position for ibbackup to work.
2522
2242
    Note, the position is current because of
2523
2243
    prepare_commit_mutex */
2524
 
    const uint32_t commit_concurrency= innobase_commit_concurrency.get();
2525
 
    if (commit_concurrency)
2526
 
    {
2527
 
      do 
2528
 
      {
2529
 
        boost::mutex::scoped_lock scopedLock(commit_cond_m);
2530
 
        commit_threads++;
2531
 
 
2532
 
        if (commit_threads <= commit_concurrency) 
2533
 
          break;
2534
 
 
 
2244
retry:
 
2245
    if (innobase_commit_concurrency > 0) {
 
2246
      pthread_mutex_lock(&commit_cond_m);
 
2247
      commit_threads++;
 
2248
 
 
2249
      if (commit_threads > innobase_commit_concurrency) {
2535
2250
        commit_threads--;
2536
 
        commit_cond.wait(scopedLock);
2537
 
      } while (1);
 
2251
        pthread_cond_wait(&commit_cond,
 
2252
          &commit_cond_m);
 
2253
        pthread_mutex_unlock(&commit_cond_m);
 
2254
        goto retry;
 
2255
      }
 
2256
      else {
 
2257
        pthread_mutex_unlock(&commit_cond_m);
 
2258
      }
2538
2259
    }
2539
2260
 
2540
 
    trx->mysql_log_file_name = NULL;
 
2261
                /* Store transaction point for binlog
 
2262
    Later logic tests that this is set to _something_. We need
 
2263
    that logic to fire, even though we do not have a real name. */
 
2264
    trx->mysql_log_file_name = "UNUSED";
2541
2265
    trx->mysql_log_offset = 0;
2542
2266
 
2543
2267
    /* Don't do write + flush right now. For group commit
2547
2271
    innobase_commit_low(trx);
2548
2272
    trx->flush_log_later = FALSE;
2549
2273
 
2550
 
    if (commit_concurrency)
2551
 
    {
2552
 
      boost::mutex::scoped_lock scopedLock(commit_cond_m);
 
2274
    if (innobase_commit_concurrency > 0) {
 
2275
      pthread_mutex_lock(&commit_cond_m);
2553
2276
      commit_threads--;
2554
 
      commit_cond.notify_one();
 
2277
      pthread_cond_signal(&commit_cond);
 
2278
      pthread_mutex_unlock(&commit_cond_m);
2555
2279
    }
2556
2280
 
2557
2281
    /* Now do a write + flush of logs. */
2571
2295
    SQL statement */
2572
2296
 
2573
2297
    trx_mark_sql_stat_end(trx);
2574
 
 
2575
 
    if (! session_test_options(session, OPTION_NOT_AUTOCOMMIT | OPTION_BEGIN))
2576
 
    {
2577
 
      if (trx->conc_state != TRX_NOT_STARTED)
2578
 
      {
2579
 
        commit(session, TRUE);
2580
 
      }
2581
 
    }
2582
2298
  }
2583
2299
 
2584
2300
  trx->n_autoinc_rows = 0; /* Reset the number AUTO-INC rows required */
2593
2309
  threads: */
2594
2310
  srv_active_wake_master_thread();
2595
2311
 
2596
 
  if (trx->isolation_level <= TRX_ISO_READ_COMMITTED &&
2597
 
      trx->global_read_view)
2598
 
  {
2599
 
    /* At low transaction isolation levels we let
2600
 
       each consistent read set its own snapshot */
2601
 
    read_view_close_for_mysql(trx);
2602
 
  }
2603
 
 
2604
2312
  return(0);
2605
2313
}
2606
2314
 
2628
2336
 
2629
2337
  innobase_release_stat_resources(trx);
2630
2338
 
2631
 
  trx->n_autoinc_rows = 0;
2632
 
 
2633
2339
  /* If we had reserved the auto-inc lock for some table (if
2634
2340
  we come here to roll back the latest SQL statement) we
2635
2341
  release it now before a possibly lengthy rollback */
2636
2342
 
2637
2343
  row_unlock_table_autoinc_for_mysql(trx);
2638
2344
 
2639
 
  if (all)
2640
 
  {
 
2345
  if (all
 
2346
    || !session_test_options(session, OPTION_NOT_AUTOCOMMIT | OPTION_BEGIN)) {
 
2347
 
2641
2348
    error = trx_rollback_for_mysql(trx);
2642
2349
  } else {
2643
2350
    error = trx_rollback_last_sql_stat_for_mysql(trx);
2644
2351
  }
2645
2352
 
2646
 
  if (trx->isolation_level <= TRX_ISO_READ_COMMITTED &&
2647
 
      trx->global_read_view)
2648
 
  {
2649
 
    /* At low transaction isolation levels we let
2650
 
       each consistent read set its own snapshot */
2651
 
    read_view_close_for_mysql(trx);
2652
 
  }
2653
 
 
2654
2353
  return(convert_error_code_to_mysql(error, 0, NULL));
2655
2354
}
2656
2355
 
2787
2486
 
2788
2487
  ut_a(trx);
2789
2488
 
2790
 
  assert(session->getKilled() != Session::NOT_KILLED ||
 
2489
  assert(session->killed != Session::NOT_KILLED ||
2791
2490
         trx->conc_state == TRX_NOT_STARTED);
2792
2491
 
2793
2492
  /* Warn if rolling back some things... */
2794
 
  if (session->getKilled() != Session::NOT_KILLED &&
 
2493
  if (session->killed != Session::NOT_KILLED &&
2795
2494
      trx->conc_state != TRX_NOT_STARTED &&
2796
 
      trx->undo_no > 0 &&
 
2495
      trx->undo_no.low > 0 &&
2797
2496
      global_system_variables.log_warnings)
2798
2497
  {
2799
 
      errmsg_printf(error::WARN,
 
2498
      errmsg_printf(ERRMSG_LVL_WARN, 
2800
2499
      "Drizzle is closing a connection during a KILL operation\n"
2801
 
      "that has an active InnoDB transaction.  %llu row modifications will "
 
2500
      "that has an active InnoDB transaction.  %lu row modifications will "
2802
2501
      "roll back.\n",
2803
 
      (ullint) trx->undo_no);
 
2502
      (ulong) trx->undo_no.low);
2804
2503
  }
2805
2504
 
2806
2505
  innobase_rollback_trx(trx);
2876
2575
  return(true);
2877
2576
}
2878
2577
 
2879
 
/********************************************************************//**
2880
 
Get the upper limit of the MySQL integral and floating-point type.
2881
 
@return maximum allowed value for the field */
2882
 
static
2883
 
uint64_t
2884
 
innobase_get_int_col_max_value(
2885
 
/*===========================*/
2886
 
        const Field*    field)  /*!< in: MySQL field */
2887
 
{
2888
 
        uint64_t        max_value = 0;
2889
 
 
2890
 
        switch(field->key_type()) {
2891
 
        /* TINY */
2892
 
        case HA_KEYTYPE_BINARY:
2893
 
                max_value = 0xFFULL;
2894
 
                break;
2895
 
        /* LONG */
2896
 
        case HA_KEYTYPE_ULONG_INT:
2897
 
                max_value = 0xFFFFFFFFULL;
2898
 
                break;
2899
 
        case HA_KEYTYPE_LONG_INT:
2900
 
                max_value = 0x7FFFFFFFULL;
2901
 
                break;
2902
 
        /* BIG */
2903
 
        case HA_KEYTYPE_ULONGLONG:
2904
 
                max_value = 0xFFFFFFFFFFFFFFFFULL;
2905
 
                break;
2906
 
        case HA_KEYTYPE_LONGLONG:
2907
 
                max_value = 0x7FFFFFFFFFFFFFFFULL;
2908
 
                break;
2909
 
        case HA_KEYTYPE_DOUBLE:
2910
 
                /* We use the maximum as per IEEE754-2008 standard, 2^53 */
2911
 
                max_value = 0x20000000000000ULL;
2912
 
                break;
2913
 
        default:
2914
 
                ut_error;
2915
 
        }
2916
 
 
2917
 
        return(max_value);
2918
 
}
2919
 
 
2920
 
/*******************************************************************//**
2921
 
This function checks whether the index column information
2922
 
is consistent between KEY info from mysql and that from innodb index.
2923
 
@return TRUE if all column types match. */
2924
 
static
2925
 
ibool
2926
 
innobase_match_index_columns(
2927
 
/*=========================*/
2928
 
        const KeyInfo*          key_info,       /*!< in: Index info
2929
 
                                                from mysql */
2930
 
        const dict_index_t*     index_info)     /*!< in: Index info
2931
 
                                                from Innodb */
2932
 
{
2933
 
        const KeyPartInfo*      key_part;
2934
 
        const KeyPartInfo*      key_end;
2935
 
        const dict_field_t*     innodb_idx_fld;
2936
 
        const dict_field_t*     innodb_idx_fld_end;
2937
 
 
2938
 
        /* Check whether user defined index column count matches */
2939
 
        if (key_info->key_parts != index_info->n_user_defined_cols) {
2940
 
                return(FALSE);
2941
 
        }
2942
 
 
2943
 
        key_part = key_info->key_part;
2944
 
        key_end = key_part + key_info->key_parts;
2945
 
        innodb_idx_fld = index_info->fields;
2946
 
        innodb_idx_fld_end = index_info->fields + index_info->n_fields;
2947
 
 
2948
 
        /* Check each index column's datatype. We do not check
2949
 
        column name because there exists case that index
2950
 
        column name got modified in mysql but such change does not
2951
 
        propagate to InnoDB.
2952
 
        One hidden assumption here is that the index column sequences
2953
 
        are matched up between those in mysql and Innodb. */
2954
 
        for (; key_part != key_end; ++key_part) {
2955
 
                ulint   col_type;
2956
 
                ibool   is_unsigned;
2957
 
                ulint   mtype = innodb_idx_fld->col->mtype;
2958
 
 
2959
 
                /* Need to translate to InnoDB column type before
2960
 
                comparison. */
2961
 
                col_type = get_innobase_type_from_mysql_type(&is_unsigned,
2962
 
                                                             key_part->field);
2963
 
 
2964
 
                /* Ignore Innodb specific system columns. */
2965
 
                while (mtype == DATA_SYS) {
2966
 
                        innodb_idx_fld++;
2967
 
 
2968
 
                        if (innodb_idx_fld >= innodb_idx_fld_end) {
2969
 
                                return(FALSE);
2970
 
                        }
2971
 
                }
2972
 
 
2973
 
                if (col_type != mtype) {
2974
 
                        /* Column Type mismatches */
2975
 
                        return(FALSE);
2976
 
                }
2977
 
 
2978
 
                innodb_idx_fld++;
2979
 
        }
2980
 
 
2981
 
        return(TRUE);
2982
 
}
2983
 
 
2984
 
/*******************************************************************//**
2985
 
This function builds a translation table in INNOBASE_SHARE
2986
 
structure for fast index location with mysql array number from its
2987
 
table->key_info structure. This also provides the necessary translation
2988
 
between the key order in mysql key_info and Innodb ib_table->indexes if
2989
 
they are not fully matched with each other.
2990
 
Note we do not have any mutex protecting the translation table
2991
 
building based on the assumption that there is no concurrent
2992
 
index creation/drop and DMLs that requires index lookup. All table
2993
 
handle will be closed before the index creation/drop.
2994
 
@return TRUE if index translation table built successfully */
2995
 
static
2996
 
ibool
2997
 
innobase_build_index_translation(
2998
 
/*=============================*/
2999
 
        const Table*            table,    /*!< in: table in MySQL data
3000
 
                                          dictionary */
3001
 
        dict_table_t*           ib_table, /*!< in: table in Innodb data
3002
 
                                          dictionary */
3003
 
        INNOBASE_SHARE*         share)    /*!< in/out: share structure
3004
 
                                          where index translation table
3005
 
                                          will be constructed in. */
3006
 
{
3007
 
        ulint           mysql_num_index;
3008
 
        ulint           ib_num_index;
3009
 
        dict_index_t**  index_mapping;
3010
 
        ibool           ret = TRUE;
3011
 
 
3012
 
        mutex_enter(&dict_sys->mutex);
3013
 
 
3014
 
        mysql_num_index = table->getShare()->keys;
3015
 
        ib_num_index = UT_LIST_GET_LEN(ib_table->indexes);
3016
 
 
3017
 
        index_mapping = share->idx_trans_tbl.index_mapping;
3018
 
 
3019
 
        /* If there exists inconsistency between MySQL and InnoDB dictionary
3020
 
        (metadata) information, the number of index defined in MySQL
3021
 
        could exceed that in InnoDB, do not build index translation
3022
 
        table in such case */
3023
 
        if (UNIV_UNLIKELY(ib_num_index < mysql_num_index)) {
3024
 
                ret = FALSE;
3025
 
                goto func_exit;
3026
 
        }
3027
 
 
3028
 
        /* If index entry count is non-zero, nothing has
3029
 
        changed since last update, directly return TRUE */
3030
 
        if (share->idx_trans_tbl.index_count) {
3031
 
                /* Index entry count should still match mysql_num_index */
3032
 
                ut_a(share->idx_trans_tbl.index_count == mysql_num_index);
3033
 
                goto func_exit;
3034
 
        }
3035
 
 
3036
 
        /* The number of index increased, rebuild the mapping table */
3037
 
        if (mysql_num_index > share->idx_trans_tbl.array_size) {
3038
 
                index_mapping = (dict_index_t**) realloc(index_mapping,
3039
 
                                                        mysql_num_index *
3040
 
                                                         sizeof(*index_mapping));
3041
 
 
3042
 
                if (!index_mapping) {
3043
 
                        /* Report an error if index_mapping continues to be
3044
 
                        NULL and mysql_num_index is a non-zero value */
3045
 
                        errmsg_printf(error::ERROR, "InnoDB: fail to allocate memory for "
3046
 
                                      "index translation table. Number of Index:%lu, array size:%lu",
3047
 
                                        mysql_num_index,
3048
 
                                        share->idx_trans_tbl.array_size);
3049
 
                        ret = FALSE;
3050
 
                        goto func_exit;
3051
 
                }
3052
 
 
3053
 
                share->idx_trans_tbl.array_size = mysql_num_index;
3054
 
        }
3055
 
 
3056
 
        /* For each index in the mysql key_info array, fetch its
3057
 
        corresponding InnoDB index pointer into index_mapping
3058
 
        array. */
3059
 
        for (ulint count = 0; count < mysql_num_index; count++) {
3060
 
 
3061
 
                /* Fetch index pointers into index_mapping according to mysql
3062
 
                index sequence */
3063
 
                index_mapping[count] = dict_table_get_index_on_name(
3064
 
                        ib_table, table->key_info[count].name);
3065
 
 
3066
 
                if (!index_mapping[count]) {
3067
 
                        errmsg_printf(error::ERROR, "Cannot find index %s in InnoDB index dictionary.",
3068
 
                                      table->key_info[count].name);
3069
 
                        ret = FALSE;
3070
 
                        goto func_exit;
3071
 
                }
3072
 
 
3073
 
                /* Double check fetched index has the same
3074
 
                column info as those in mysql key_info. */
3075
 
                if (!innobase_match_index_columns(&table->key_info[count], index_mapping[count])) {
3076
 
                  errmsg_printf(error::ERROR, "Found index %s whose column info does not match that of MySQL.",
3077
 
                                table->key_info[count].name);
3078
 
                  ret = FALSE;
3079
 
                  goto func_exit;
3080
 
                }
3081
 
        }
3082
 
 
3083
 
        /* Successfully built the translation table */
3084
 
        share->idx_trans_tbl.index_count = mysql_num_index;
3085
 
 
3086
 
func_exit:
3087
 
        if (!ret) {
3088
 
                /* Build translation table failed. */
3089
 
                free(index_mapping);
3090
 
 
3091
 
                share->idx_trans_tbl.array_size = 0;
3092
 
                share->idx_trans_tbl.index_count = 0;
3093
 
                index_mapping = NULL;
3094
 
        }
3095
 
 
3096
 
        share->idx_trans_tbl.index_mapping = index_mapping;
3097
 
 
3098
 
        mutex_exit(&dict_sys->mutex);
3099
 
 
3100
 
        return(ret);
3101
 
}
3102
 
 
3103
 
/*******************************************************************//**
3104
 
This function uses index translation table to quickly locate the
3105
 
requested index structure.
3106
 
Note we do not have mutex protection for the index translatoin table
3107
 
access, it is based on the assumption that there is no concurrent
3108
 
translation table rebuild (fter create/drop index) and DMLs that
3109
 
require index lookup.
3110
 
@return dict_index_t structure for requested index. NULL if
3111
 
fail to locate the index structure. */
3112
 
static
3113
 
dict_index_t*
3114
 
innobase_index_lookup(
3115
 
/*==================*/
3116
 
        INNOBASE_SHARE* share,  /*!< in: share structure for index
3117
 
                                translation table. */
3118
 
        uint            keynr)  /*!< in: index number for the requested
3119
 
                                index */
3120
 
{
3121
 
        if (!share->idx_trans_tbl.index_mapping
3122
 
            || keynr >= share->idx_trans_tbl.index_count) {
3123
 
                return(NULL);
3124
 
        }
3125
 
 
3126
 
        return(share->idx_trans_tbl.index_mapping[keynr]);
 
2578
/*****************************************************************//**
 
2579
Normalizes a table name string. A normalized name consists of the
 
2580
database name catenated to '/' and table name. An example:
 
2581
test/mytable. On Windows normalization puts both the database name and the
 
2582
table name always to lower case. */
 
2583
static
 
2584
void
 
2585
normalize_table_name(
 
2586
/*=================*/
 
2587
  char*   norm_name,  /*!< out: normalized name as a
 
2588
          null-terminated string */
 
2589
  const char* name)   /*!< in: table name string */
 
2590
{
 
2591
  const char* name_ptr;
 
2592
  const char* db_ptr;
 
2593
  const char* ptr;
 
2594
 
 
2595
  /* Scan name from the end */
 
2596
 
 
2597
  ptr = strchr(name, '\0')-1;
 
2598
 
 
2599
  while (ptr >= name && *ptr != '\\' && *ptr != '/') {
 
2600
    ptr--;
 
2601
  }
 
2602
 
 
2603
  name_ptr = ptr + 1;
 
2604
 
 
2605
  assert(ptr > name);
 
2606
 
 
2607
  ptr--;
 
2608
 
 
2609
  while (ptr >= name && *ptr != '\\' && *ptr != '/') {
 
2610
    ptr--;
 
2611
  }
 
2612
 
 
2613
  db_ptr = ptr + 1;
 
2614
 
 
2615
  memcpy(norm_name, db_ptr, strlen(name) + 1 - (db_ptr - name));
 
2616
 
 
2617
  norm_name[name_ptr - db_ptr - 1] = '/';
 
2618
 
 
2619
#ifdef __WIN__
 
2620
  innobase_casedn_str(norm_name);
 
2621
#endif
3127
2622
}
3128
2623
 
3129
2624
/********************************************************************//**
3130
2625
Set the autoinc column max value. This should only be called once from
3131
 
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 */
3132
2628
UNIV_INTERN
3133
 
void
 
2629
ulint
3134
2630
ha_innobase::innobase_initialize_autoinc()
3135
2631
/*======================================*/
3136
2632
{
 
2633
  dict_index_t* index;
3137
2634
  uint64_t  auto_inc;
3138
 
  const Field*  field = getTable()->found_next_number_field;
3139
 
 
3140
 
  if (field != NULL) {
3141
 
    auto_inc = innobase_get_int_col_max_value(field);
3142
 
  } else {
3143
 
    /* We have no idea what's been passed in to us as the
3144
 
       autoinc column. We set it to the 0, effectively disabling
3145
 
       updates to the table. */
3146
 
    auto_inc = 0;
3147
 
 
 
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:
3148
2653
    ut_print_timestamp(stderr);
3149
 
    errmsg_printf(error::ERROR, "InnoDB: Unable to determine the AUTOINC column name");
3150
 
  }
3151
 
 
3152
 
  if (srv_force_recovery >= SRV_FORCE_NO_IBUF_MERGE) {
3153
 
    /* If the recovery level is set so high that writes
3154
 
       are disabled we force the AUTOINC counter to 0
3155
 
       value effectively disabling writes to the table.
3156
 
       Secondly, we avoid reading the table in case the read
3157
 
       results in failure due to a corrupted table/index.
3158
 
 
3159
 
       We will not return an error to the client, so that the
3160
 
       tables can be dumped with minimal hassle.  If an error
3161
 
       were returned in this case, the first attempt to read
3162
 
       the table would fail and subsequent SELECTs would succeed. */
3163
 
    auto_inc = 0;
3164
 
  } else if (field == NULL) {
3165
 
    /* This is a far more serious error, best to avoid
3166
 
       opening the table and return failure. */
3167
 
    my_error(ER_AUTOINC_READ_FAILED, MYF(0));
3168
 
  } else {
3169
 
    dict_index_t*       index;
3170
 
    const char* col_name;
3171
 
    uint64_t    read_auto_inc;
3172
 
    ulint               err;
3173
 
 
3174
 
    update_session(getTable()->in_use);
3175
 
    col_name = field->field_name;
3176
 
 
3177
 
    ut_a(prebuilt->trx == session_to_trx(user_session));
3178
 
 
3179
 
    index = innobase_get_index(getTable()->getShare()->next_number_index);
3180
 
 
3181
 
    /* Execute SELECT MAX(col_name) FROM TABLE; */
3182
 
    err = row_search_max_autoinc(index, col_name, &read_auto_inc);
3183
 
 
3184
 
    switch (err) {
3185
 
    case DB_SUCCESS: {
3186
 
      uint64_t col_max_value;
3187
 
 
3188
 
      col_max_value = innobase_get_int_col_max_value(field);
3189
 
 
3190
 
      /* At the this stage we do not know the increment
3191
 
         nor the offset, so use a default increment of 1. */
3192
 
 
3193
 
      auto_inc = innobase_next_autoinc(read_auto_inc, 1, 1, col_max_value);
3194
 
 
3195
 
      break;
3196
 
    }
3197
 
    case DB_RECORD_NOT_FOUND:
3198
 
      ut_print_timestamp(stderr);
3199
 
      errmsg_printf(error::ERROR, "InnoDB: MySQL and InnoDB data dictionaries are out of sync.\n"
3200
 
                    "InnoDB: Unable to find the AUTOINC column %s in the InnoDB table %s.\n"
3201
 
                    "InnoDB: We set the next AUTOINC column value to 0,\n"
3202
 
                    "InnoDB: in effect disabling the AUTOINC next value generation.\n"
3203
 
                    "InnoDB: You can either set the next AUTOINC value explicitly using ALTER TABLE\n"
3204
 
                    "InnoDB: or fix the data dictionary by recreating the table.\n",
3205
 
                    col_name, index->table->name);
3206
 
 
3207
 
      /* This will disable the AUTOINC generation. */
3208
 
      auto_inc = 0;
3209
 
 
3210
 
      /* We want the open to succeed, so that the user can
3211
 
         take corrective action. ie. reads should succeed but
3212
 
         updates should fail. */
3213
 
      err = DB_SUCCESS;
3214
 
      break;
3215
 
    default:
3216
 
      /* row_search_max_autoinc() should only return
3217
 
         one of DB_SUCCESS or DB_RECORD_NOT_FOUND. */
3218
 
      ut_error;
3219
 
    }
 
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);
3220
2673
  }
3221
2674
 
3222
2675
  dict_table_autoinc_initialize(prebuilt->table, auto_inc);
 
2676
 
 
2677
  return(DB_SUCCESS);
3223
2678
}
3224
2679
 
3225
2680
/*****************************************************************//**
3228
2683
@return 1 if error, 0 if success */
3229
2684
UNIV_INTERN
3230
2685
int
3231
 
ha_innobase::doOpen(const identifier::Table &identifier,
 
2686
ha_innobase::doOpen(const TableIdentifier &identifier,
3232
2687
                    int   mode,   /*!< in: not used */
3233
2688
                    uint    test_if_locked) /*!< in: not used */
3234
2689
{
3235
2690
  dict_table_t* ib_table;
 
2691
  char    norm_name[FN_REFLEN];
3236
2692
  Session*    session;
3237
2693
 
3238
2694
  UT_NOT_USED(mode);
3239
2695
  UT_NOT_USED(test_if_locked);
3240
2696
 
3241
 
  session= getTable()->in_use;
 
2697
  session= table->in_use;
3242
2698
 
3243
2699
  /* Under some cases Drizzle seems to call this function while
3244
2700
  holding btr_search_latch. This breaks the latching order as
3247
2703
    getTransactionalEngine()->releaseTemporaryLatches(session);
3248
2704
  }
3249
2705
 
 
2706
  normalize_table_name(norm_name, identifier.getPath().c_str());
 
2707
 
3250
2708
  user_session = NULL;
3251
2709
 
3252
 
  std::string search_string(identifier.getSchemaName());
3253
 
  boost::algorithm::to_lower(search_string);
 
2710
  if (!(share=get_share(identifier.getPath().c_str()))) {
3254
2711
 
3255
 
  if (search_string.compare("data_dictionary") == 0)
3256
 
  {
3257
 
    std::string table_name(identifier.getTableName());
3258
 
    boost::algorithm::to_upper(table_name);
3259
 
    if (!(share=get_share(table_name.c_str())))
3260
 
    {
3261
 
      return 1;
3262
 
    }
3263
 
  }
3264
 
  else
3265
 
  {
3266
 
    if (!(share=get_share(identifier.getKeyPath().c_str())))
3267
 
    {
3268
 
      return(1);
3269
 
    }
 
2712
    return(1);
3270
2713
  }
3271
2714
 
3272
2715
  /* Create buffers for packing the fields of a record. Why
3275
2718
  stored the string length as the first byte. */
3276
2719
 
3277
2720
  upd_and_key_val_buff_len =
3278
 
        getTable()->getShare()->sizeStoredRecord()
3279
 
        + getTable()->getShare()->max_key_length
 
2721
        table->getShare()->stored_rec_length
 
2722
        + table->getShare()->max_key_length
3280
2723
        + MAX_REF_PARTS * 3;
3281
2724
 
3282
2725
  upd_buff.resize(upd_and_key_val_buff_len);
3293
2736
  }
3294
2737
 
3295
2738
  /* Get pointer to a table object in InnoDB dictionary cache */
3296
 
  if (search_string.compare("data_dictionary") == 0)
3297
 
  {
3298
 
    std::string table_name(identifier.getTableName());
3299
 
    boost::algorithm::to_upper(table_name);
3300
 
    ib_table = dict_table_get(table_name.c_str(), TRUE);
3301
 
  }
3302
 
  else
3303
 
  {
3304
 
    ib_table = dict_table_get(identifier.getKeyPath().c_str(), TRUE);
3305
 
  }
 
2739
  ib_table = dict_table_get(norm_name, TRUE);
3306
2740
  
3307
2741
  if (NULL == ib_table) {
3308
 
    errmsg_printf(error::ERROR, "Cannot find or open table %s from\n"
 
2742
    errmsg_printf(ERRMSG_LVL_ERROR, "Cannot find or open table %s from\n"
3309
2743
        "the internal data dictionary of InnoDB "
3310
2744
        "though the .frm file for the\n"
3311
2745
        "table exists. Maybe you have deleted and "
3319
2753
        "doesn't support.\n"
3320
2754
        "See " REFMAN "innodb-troubleshooting.html\n"
3321
2755
        "how you can resolve the problem.\n",
3322
 
        identifier.getKeyPath().c_str());
 
2756
        norm_name);
3323
2757
    free_share(share);
3324
2758
    upd_buff.resize(0);
3325
2759
    key_val_buff.resize(0);
3328
2762
    return(HA_ERR_NO_SUCH_TABLE);
3329
2763
  }
3330
2764
 
3331
 
  if (ib_table->ibd_file_missing && ! session->doing_tablespace_operation()) {
3332
 
    errmsg_printf(error::ERROR, "MySQL is trying to open a table handle but "
 
2765
  if (ib_table->ibd_file_missing && !session_tablespace_op(session)) {
 
2766
    errmsg_printf(ERRMSG_LVL_ERROR, "MySQL is trying to open a table handle but "
3333
2767
        "the .ibd file for\ntable %s does not exist.\n"
3334
2768
        "Have you deleted the .ibd file from the "
3335
2769
        "database directory under\nthe MySQL datadir, "
3336
2770
        "or have you used DISCARD TABLESPACE?\n"
3337
2771
        "See " REFMAN "innodb-troubleshooting.html\n"
3338
2772
        "how you can resolve the problem.\n",
3339
 
        identifier.getKeyPath().c_str());
 
2773
        norm_name);
3340
2774
    free_share(share);
3341
2775
    upd_buff.resize(0);
3342
2776
    key_val_buff.resize(0);
3348
2782
 
3349
2783
  prebuilt = row_create_prebuilt(ib_table);
3350
2784
 
3351
 
  prebuilt->mysql_row_len = getTable()->getShare()->sizeStoredRecord();
3352
 
  prebuilt->default_rec = getTable()->getDefaultValues();
 
2785
  prebuilt->mysql_row_len = table->getShare()->stored_rec_length;
 
2786
  prebuilt->default_rec = table->getDefaultValues();
3353
2787
  ut_ad(prebuilt->default_rec);
3354
2788
 
3355
2789
  /* Looks like MySQL-3.23 sometimes has primary key number != 0 */
3356
2790
 
3357
 
  primary_key = getTable()->getShare()->getPrimaryKey();
 
2791
  primary_key = table->getShare()->getPrimaryKey();
3358
2792
  key_used_on_scan = primary_key;
3359
2793
 
3360
 
  if (!innobase_build_index_translation(getTable(), ib_table, share)) {
3361
 
    errmsg_printf(error::ERROR, "Build InnoDB index translation table for"
3362
 
                    " Table %s failed", identifier.getKeyPath().c_str());
3363
 
  }
3364
 
 
3365
2794
  /* Allocate a buffer for a 'row reference'. A row reference is
3366
2795
  a string of bytes of length ref_length which uniquely specifies
3367
2796
  a row in our table. Note that MySQL may also compare two row
3369
2798
  of length ref_length! */
3370
2799
 
3371
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
    }
3372
2805
 
3373
2806
    prebuilt->clust_index_was_generated = FALSE;
3374
2807
 
3375
 
    if (UNIV_UNLIKELY(primary_key >= MAX_KEY)) {
3376
 
      errmsg_printf(error::ERROR, "Table %s has a primary key in "
3377
 
                    "InnoDB data dictionary, but not "
3378
 
                    "in MySQL!", identifier.getTableName().c_str());
3379
 
 
3380
 
      /* This mismatch could cause further problems
3381
 
         if not attended, bring this to the user's attention
3382
 
         by printing a warning in addition to log a message
3383
 
         in the errorlog */
3384
 
      push_warning_printf(session, DRIZZLE_ERROR::WARN_LEVEL_WARN,
3385
 
                          ER_NO_SUCH_INDEX,
3386
 
                          "InnoDB: Table %s has a "
3387
 
                          "primary key in InnoDB data "
3388
 
                          "dictionary, but not in "
3389
 
                          "MySQL!", identifier.getTableName().c_str());
3390
 
 
3391
 
      /* If primary_key >= MAX_KEY, its (primary_key)
3392
 
         value could be out of bound if continue to index
3393
 
         into key_info[] array. Find InnoDB primary index,
3394
 
         and assign its key_length to ref_length.
3395
 
         In addition, since MySQL indexes are sorted starting
3396
 
         with primary index, unique index etc., initialize
3397
 
         ref_length to the first index key length in
3398
 
         case we fail to find InnoDB cluster index.
3399
 
 
3400
 
         Please note, this will not resolve the primary
3401
 
         index mismatch problem, other side effects are
3402
 
         possible if users continue to use the table.
3403
 
         However, we allow this table to be opened so
3404
 
         that user can adopt necessary measures for the
3405
 
         mismatch while still being accessible to the table
3406
 
         date. */
3407
 
      ref_length = getTable()->key_info[0].key_length;
3408
 
 
3409
 
      /* Find correspoinding cluster index
3410
 
         key length in MySQL's key_info[] array */
3411
 
      for (ulint i = 0; i < getTable()->getShare()->keys; i++) {
3412
 
        dict_index_t*   index;
3413
 
        index = innobase_get_index(i);
3414
 
        if (dict_index_is_clust(index)) {
3415
 
          ref_length =
3416
 
            getTable()->key_info[i].key_length;
3417
 
        }
3418
 
      }
3419
 
    } else {
3420
 
      /* MySQL allocates the buffer for ref.
3421
 
         key_info->key_length includes space for all key
3422
 
         columns + one byte for each column that may be
3423
 
         NULL. ref_length must be as exact as possible to
3424
 
         save space, because all row reference buffers are
3425
 
         allocated based on ref_length. */
3426
 
 
3427
 
      ref_length = getTable()->key_info[primary_key].key_length;
3428
 
    }
 
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;
3429
2815
  } else {
3430
2816
    if (primary_key != MAX_KEY) {
3431
 
      errmsg_printf(error::ERROR,
3432
 
                    "Table %s has no primary key in InnoDB data "
3433
 
                    "dictionary, but has one in MySQL! If you "
3434
 
                    "created the table with a MySQL version < "
3435
 
                    "3.23.54 and did not define a primary key, "
3436
 
                    "but defined a unique key with all non-NULL "
3437
 
                    "columns, then MySQL internally treats that "
3438
 
                    "key as the primary key. You can fix this "
3439
 
                    "error by dump + DROP + CREATE + reimport "
3440
 
                    "of the table.", identifier.getTableName().c_str());
3441
 
 
3442
 
      /* This mismatch could cause further problems
3443
 
         if not attended, bring this to the user attention
3444
 
         by printing a warning in addition to log a message
3445
 
         in the errorlog */
3446
 
      push_warning_printf(session, DRIZZLE_ERROR::WARN_LEVEL_WARN,
3447
 
                          ER_NO_SUCH_INDEX,
3448
 
                          "InnoDB: Table %s has no "
3449
 
                          "primary key in InnoDB data "
3450
 
                          "dictionary, but has one in "
3451
 
                          "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());
3452
2826
    }
3453
2827
 
3454
2828
    prebuilt->clust_index_was_generated = TRUE;
3464
2838
    and it will never be updated anyway. */
3465
2839
 
3466
2840
    if (key_used_on_scan != MAX_KEY) {
3467
 
      errmsg_printf(error::WARN, 
 
2841
      errmsg_printf(ERRMSG_LVL_WARN, 
3468
2842
        "Table %s key_used_on_scan is %lu even "
3469
2843
        "though there is no primary key inside "
3470
2844
        "InnoDB.", identifier.getTableName().c_str(), (ulong) key_used_on_scan);
3481
2855
    /* We update the highest file format in the system table
3482
2856
    space, if this table has higher file format setting. */
3483
2857
 
3484
 
    char changed_file_format_max[100];
3485
 
    strcpy(changed_file_format_max, innobase_file_format_max.c_str());
3486
 
    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,
3487
2860
      dict_table_get_format(prebuilt->table));
3488
 
    innobase_file_format_max= changed_file_format_max;
3489
2861
  }
3490
2862
 
 
2863
  info(HA_STATUS_NO_LOCK | HA_STATUS_VARIABLE | HA_STATUS_CONST);
 
2864
 
3491
2865
  /* Only if the table has an AUTOINC column. */
3492
 
  if (prebuilt->table != NULL && getTable()->found_next_number_field != NULL) {
 
2866
  if (prebuilt->table != NULL && table->found_next_number_field != NULL) {
 
2867
    ulint error;
3493
2868
 
3494
2869
    dict_table_autoinc_lock(prebuilt->table);
3495
2870
 
3499
2874
    autoinc value from a previous Drizzle open. */
3500
2875
    if (dict_table_autoinc_read(prebuilt->table) == 0) {
3501
2876
 
3502
 
      innobase_initialize_autoinc();
 
2877
      error = innobase_initialize_autoinc();
 
2878
      ut_a(error == DB_SUCCESS);
3503
2879
    }
3504
2880
 
3505
2881
    dict_table_autoinc_unlock(prebuilt->table);
3506
2882
  }
3507
2883
 
3508
 
  info(HA_STATUS_NO_LOCK | HA_STATUS_VARIABLE | HA_STATUS_CONST);
3509
 
 
3510
2884
  return(0);
3511
2885
}
3512
2886
 
3527
2901
{
3528
2902
  Session*  session;
3529
2903
 
3530
 
  session= getTable()->in_use;
 
2904
  session= table->in_use;
3531
2905
  if (session != NULL) {
3532
2906
    getTransactionalEngine()->releaseTemporaryLatches(session);
3533
2907
  }
3616
2990
of this function is in rem0cmp.c in InnoDB source code! If you change this
3617
2991
function, remember to update the prototype there!
3618
2992
@return 1, 0, -1, if a is greater, equal, less than b, respectively */
3619
 
UNIV_INTERN int
 
2993
extern "C" UNIV_INTERN
 
2994
int
3620
2995
innobase_mysql_cmp(
3621
2996
/*===============*/
3622
2997
  int   mysql_type, /*!< in: MySQL type */
3663
3038
      charset = get_charset(charset_number);
3664
3039
 
3665
3040
      if (charset == NULL) {
3666
 
        errmsg_printf(error::ERROR, "InnoDB needs charset %lu for doing "
 
3041
        errmsg_printf(ERRMSG_LVL_ERROR, "InnoDB needs charset %lu for doing "
3667
3042
                      "a comparison, but MySQL cannot "
3668
3043
                      "find that charset.",
3669
3044
                      (ulong) charset_number);
3698
3073
the 'mtype' of InnoDB. InnoDB differentiates between MySQL's old <= 4.1
3699
3074
VARCHAR and the new true VARCHAR in >= 5.0.3 by the 'prtype'.
3700
3075
@return DATA_BINARY, DATA_VARCHAR, ... */
3701
 
UNIV_INTERN
 
3076
extern "C" UNIV_INTERN
3702
3077
ulint
3703
3078
get_innobase_type_from_mysql_type(
3704
3079
/*==============================*/
3747
3122
      return(DATA_VARMYSQL);
3748
3123
    }
3749
3124
  case DRIZZLE_TYPE_DECIMAL:
3750
 
  case DRIZZLE_TYPE_MICROTIME:
3751
3125
    return(DATA_FIXBINARY);
3752
3126
  case DRIZZLE_TYPE_LONG:
3753
3127
  case DRIZZLE_TYPE_LONGLONG:
3754
3128
  case DRIZZLE_TYPE_DATETIME:
3755
 
  case DRIZZLE_TYPE_TIME:
3756
3129
  case DRIZZLE_TYPE_DATE:
3757
3130
  case DRIZZLE_TYPE_TIMESTAMP:
3758
 
  case DRIZZLE_TYPE_ENUM:
3759
3131
    return(DATA_INT);
3760
3132
  case DRIZZLE_TYPE_DOUBLE:
3761
3133
    return(DATA_DOUBLE);
3762
3134
  case DRIZZLE_TYPE_BLOB:
3763
 
    return(DATA_BLOB);
3764
 
  case DRIZZLE_TYPE_BOOLEAN:
3765
 
  case DRIZZLE_TYPE_UUID:
3766
 
    return(DATA_FIXBINARY);
3767
 
  case DRIZZLE_TYPE_NULL:
 
3135
                return(DATA_BLOB);
 
3136
  default:
3768
3137
    ut_error;
3769
3138
  }
3770
3139
 
3813
3182
  uint    buff_len,/*!< in: buffer length */
3814
3183
  const unsigned char*  record)/*!< in: row in MySQL format */
3815
3184
{
3816
 
  KeyInfo*    key_info  = &getTable()->key_info[keynr];
 
3185
  KeyInfo*    key_info  = &table->key_info[keynr];
3817
3186
  KeyPartInfo*  key_part  = key_info->key_part;
3818
3187
  KeyPartInfo*  end   = key_part + key_info->key_parts;
3819
3188
  char*   buff_start  = buff;
3885
3254
      cs = field->charset();
3886
3255
 
3887
3256
      lenlen = (ulint)
3888
 
        (((Field_varstring*)field)->pack_length_no_ptr());
 
3257
        (((Field_varstring*)field)->length_bytes);
3889
3258
 
3890
3259
      data = row_mysql_read_true_varchar(&len,
3891
3260
        (byte*) (record
3892
 
        + (ulint)get_field_offset(getTable(), field)),
 
3261
        + (ulint)get_field_offset(table, field)),
3893
3262
        lenlen);
3894
3263
 
3895
3264
      true_len = len;
3952
3321
 
3953
3322
      blob_data = row_mysql_read_blob_ref(&blob_len,
3954
3323
        (byte*) (record
3955
 
        + (ulint)get_field_offset(getTable(), field)),
 
3324
        + (ulint)get_field_offset(table, field)),
3956
3325
          (ulint) field->pack_length());
3957
3326
 
3958
3327
      true_len = blob_len;
3959
3328
 
3960
 
      ut_a(get_field_offset(getTable(), field)
 
3329
      ut_a(get_field_offset(table, field)
3961
3330
        == key_part->offset);
3962
3331
 
3963
3332
      /* For multi byte character sets we need to calculate
4004
3373
      ulint     key_len;
4005
3374
      const unsigned char*    src_start;
4006
3375
      enum_field_types  real_type;
4007
 
      const CHARSET_INFO* cs= field->charset();
4008
3376
 
4009
3377
      key_len = key_part->length;
4010
3378
 
4026
3394
      memcpy(buff, src_start, true_len);
4027
3395
      buff += true_len;
4028
3396
 
4029
 
      /* 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. */
4030
3402
 
4031
3403
      if (true_len < key_len) {
4032
 
        ulint   pad_len = key_len - true_len;
4033
 
        ut_a(!(pad_len % cs->mbminlen));
4034
 
 
4035
 
        cs->cset->fill(cs, buff, pad_len,
4036
 
                       0x20 /* space */);
 
3404
        ulint pad_len = key_len - true_len;
 
3405
        memset(buff, ' ', pad_len);
4037
3406
        buff += pad_len;
4038
3407
      }
4039
3408
    }
4141
3510
 
4142
3511
  /* Note that in InnoDB, i is the column number. MySQL calls columns
4143
3512
  'fields'. */
4144
 
  for (i = 0; i < n_fields; i++)
 
3513
  for (i = 0; i < n_fields; i++) 
4145
3514
  {
4146
 
    const dict_col_t *col= &index->table->cols[i];
4147
3515
    templ = prebuilt->mysql_template + n_requested_fields;
4148
3516
    field = table->getField(i);
4149
3517
 
4189
3557
    n_requested_fields++;
4190
3558
 
4191
3559
    templ->col_no = i;
4192
 
    templ->clust_rec_field_no = dict_col_get_clust_pos(col, clust_index);
4193
 
    ut_ad(templ->clust_rec_field_no != ULINT_UNDEFINED);
4194
3560
 
4195
3561
    if (index == clust_index) {
4196
 
      templ->rec_field_no = templ->clust_rec_field_no;
 
3562
      templ->rec_field_no = dict_col_get_clust_pos(
 
3563
        &index->table->cols[i], index);
4197
3564
    } else {
4198
3565
      templ->rec_field_no = dict_index_get_nth_col_pos(
4199
3566
                index, i);
4200
 
      if (templ->rec_field_no == ULINT_UNDEFINED) {
4201
 
        prebuilt->need_to_access_clustered = TRUE;
4202
 
      }
 
3567
    }
 
3568
 
 
3569
    if (templ->rec_field_no == ULINT_UNDEFINED) {
 
3570
      prebuilt->need_to_access_clustered = TRUE;
4203
3571
    }
4204
3572
 
4205
3573
    if (field->null_ptr) {
4221
3589
      mysql_prefix_len = templ->mysql_col_offset
4222
3590
        + templ->mysql_col_len;
4223
3591
    }
4224
 
    templ->type = col->mtype;
 
3592
    templ->type = index->table->cols[i].mtype;
4225
3593
    templ->mysql_type = (ulint)field->type();
4226
3594
 
4227
3595
    if (templ->mysql_type == DATA_MYSQL_TRUE_VARCHAR) {
4228
3596
      templ->mysql_length_bytes = (ulint)
4229
 
        (((Field_varstring*)field)->pack_length_no_ptr());
 
3597
        (((Field_varstring*)field)->length_bytes);
4230
3598
    }
4231
3599
 
4232
 
    templ->charset = dtype_get_charset_coll(col->prtype);
4233
 
    templ->mbminlen = dict_col_get_mbminlen(col);
4234
 
    templ->mbmaxlen = dict_col_get_mbmaxlen(col);
4235
 
    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;
4236
3606
    if (templ->type == DATA_BLOB) {
4237
3607
      prebuilt->templ_contains_blob = TRUE;
4238
3608
    }
4249
3619
    for (i = 0; i < n_requested_fields; i++) {
4250
3620
      templ = prebuilt->mysql_template + i;
4251
3621
 
4252
 
      templ->rec_field_no = templ->clust_rec_field_no;
 
3622
      templ->rec_field_no = dict_col_get_clust_pos(
 
3623
        &index->table->cols[templ->col_no],
 
3624
        clust_index);
4253
3625
    }
4254
3626
  }
4255
3627
}
4256
3628
 
4257
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
/********************************************************************//**
4258
3674
This special handling is really to overcome the limitations of MySQL's
4259
3675
binlogging. We need to eliminate the non-determinism that will arise in
4260
3676
INSERT ... SELECT type of statements, since MySQL binlog only stores the
4323
3739
  trx_t*    trx = session_to_trx(user_session);
4324
3740
 
4325
3741
  if (prebuilt->trx != trx) {
4326
 
    errmsg_printf(error::ERROR, "The transaction object for the table handle is at "
 
3742
    errmsg_printf(ERRMSG_LVL_ERROR, "The transaction object for the table handle is at "
4327
3743
        "%p, but for the current thread it is at %p",
4328
3744
        (const void*) prebuilt->trx, (const void*) trx);
4329
3745
 
4337
3753
    ut_error;
4338
3754
  }
4339
3755
 
4340
 
  sql_command = user_session->getSqlCommand();
 
3756
  sql_command = session_sql_command(user_session);
4341
3757
 
4342
3758
  if ((sql_command == SQLCOM_ALTER_TABLE
4343
3759
       || sql_command == SQLCOM_CREATE_INDEX
4405
3821
  num_write_row++;
4406
3822
 
4407
3823
  /* This is the case where the table has an auto-increment column */
4408
 
  if (getTable()->next_number_field && record == getTable()->getInsertRecord()) {
 
3824
  if (table->next_number_field && record == table->getInsertRecord()) {
4409
3825
 
4410
3826
    /* Reset the error code before calling
4411
3827
    innobase_get_auto_increment(). */
4412
3828
    prebuilt->autoinc_error = DB_SUCCESS;
4413
3829
 
4414
3830
    if ((error = update_auto_increment())) {
 
3831
 
4415
3832
      /* We don't want to mask autoinc overflow errors. */
4416
 
 
4417
 
      /* Handle the case where the AUTOINC sub-system
4418
 
         failed during initialization. */
4419
 
      if (prebuilt->autoinc_error == DB_UNSUPPORTED) {
4420
 
        error_result = ER_AUTOINC_READ_FAILED;
4421
 
        /* Set the error message to report too. */
4422
 
        my_error(ER_AUTOINC_READ_FAILED, MYF(0));
4423
 
        goto func_exit;
4424
 
      } else if (prebuilt->autoinc_error != DB_SUCCESS) {
 
3833
      if (prebuilt->autoinc_error != DB_SUCCESS) {
4425
3834
        error = (int) prebuilt->autoinc_error;
4426
3835
 
4427
3836
        goto report_error;
4441
3850
    /* Build the template used in converting quickly between
4442
3851
    the two database formats */
4443
3852
 
4444
 
    build_template(prebuilt, NULL, getTable(), ROW_MYSQL_WHOLE_ROW);
 
3853
    build_template(prebuilt, NULL, table,
 
3854
             ROW_MYSQL_WHOLE_ROW);
4445
3855
  }
4446
3856
 
4447
3857
  innodb_srv_conc_enter_innodb(prebuilt->trx);
4448
3858
 
4449
3859
  error = row_insert_for_mysql((byte*) record, prebuilt);
4450
3860
 
4451
 
  user_session->setXaId(trx->id);
4452
 
 
4453
3861
  /* Handle duplicate key errors */
4454
3862
  if (auto_inc_used) {
4455
3863
    ulint   err;
4467
3875
    /* We need the upper limit of the col type to check for
4468
3876
    whether we update the table autoinc counter or not. */
4469
3877
    col_max_value = innobase_get_int_col_max_value(
4470
 
      getTable()->next_number_field); 
 
3878
      table->next_number_field);
 
3879
 
4471
3880
    /* Get the value that MySQL attempted to store in the table.*/
4472
 
    auto_inc = getTable()->next_number_field->val_int();
 
3881
    auto_inc = table->next_number_field->val_int();
4473
3882
 
4474
3883
    switch (error) {
4475
3884
    case DB_DUPLICATE_KEY:
4505
3914
      update the table upper limit. Note: last_value
4506
3915
      will be 0 if get_auto_increment() was not called.*/
4507
3916
 
4508
 
      if (auto_inc >= prebuilt->autoinc_last_value) {
 
3917
      if (auto_inc <= col_max_value
 
3918
          && auto_inc >= prebuilt->autoinc_last_value) {
4509
3919
set_max_autoinc:
4510
 
        /* This should filter out the negative
4511
 
           values set explicitly by the user. */
4512
 
        if (auto_inc <= col_max_value) {
4513
 
          ut_a(prebuilt->autoinc_increment > 0);
4514
 
 
4515
 
          uint64_t      need;
4516
 
          uint64_t      offset;
4517
 
 
4518
 
          offset = prebuilt->autoinc_offset;
4519
 
          need = prebuilt->autoinc_increment;
4520
 
 
4521
 
          auto_inc = innobase_next_autoinc(
4522
 
                                           auto_inc,
4523
 
                                           need, offset, col_max_value);
4524
 
 
4525
 
          err = innobase_set_max_autoinc(
4526
 
                                         auto_inc);
4527
 
 
4528
 
          if (err != DB_SUCCESS) {
4529
 
            error = err;
4530
 
          }
 
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;
4531
3935
        }
4532
3936
      }
4533
3937
      break;
4628
4032
        o_ptr = row_mysql_read_true_varchar(
4629
4033
          &o_len, o_ptr,
4630
4034
          (ulint)
4631
 
          (((Field_varstring*)field)->pack_length_no_ptr()));
 
4035
          (((Field_varstring*)field)->length_bytes));
4632
4036
 
4633
4037
        n_ptr = row_mysql_read_true_varchar(
4634
4038
          &n_len, n_ptr,
4635
4039
          (ulint)
4636
 
          (((Field_varstring*)field)->pack_length_no_ptr()));
 
4040
          (((Field_varstring*)field)->length_bytes));
4637
4041
      }
4638
4042
 
4639
4043
      break;
4724
4128
  /* Build an update vector from the modified fields in the rows
4725
4129
  (uses upd_buff of the handle) */
4726
4130
 
4727
 
  calc_row_difference(uvect, (unsigned char*) old_row, new_row, getTable(),
 
4131
  calc_row_difference(uvect, (unsigned char*) old_row, new_row, table,
4728
4132
      &upd_buff[0], (ulint)upd_and_key_val_buff_len,
4729
4133
      prebuilt, user_session);
4730
4134
 
4733
4137
 
4734
4138
  ut_a(prebuilt->template_type == ROW_MYSQL_WHOLE_ROW);
4735
4139
 
4736
 
  if (getTable()->found_next_number_field)
 
4140
  if (table->found_next_number_field)
4737
4141
  {
4738
4142
    uint64_t  auto_inc;
4739
4143
    uint64_t  col_max_value;
4740
4144
 
4741
 
    auto_inc = getTable()->found_next_number_field->val_int();
 
4145
    auto_inc = table->found_next_number_field->val_int();
4742
4146
 
4743
4147
    /* We need the upper limit of the col type to check for
4744
4148
    whether we update the table autoinc counter or not. */
4745
4149
    col_max_value = innobase_get_int_col_max_value(
4746
 
      getTable()->found_next_number_field);
 
4150
      table->found_next_number_field);
4747
4151
 
4748
4152
    uint64_t current_autoinc;
4749
4153
    ulint autoinc_error= innobase_get_autoinc(&current_autoinc);
4771
4175
 
4772
4176
  error = row_update_for_mysql((byte*) old_row, prebuilt);
4773
4177
 
4774
 
  user_session->setXaId(trx->id);
4775
 
 
4776
4178
  /* We need to do some special AUTOINC handling for the following case:
4777
4179
 
4778
4180
  INSERT INTO t (c1,c2) VALUES(x,y) ON DUPLICATE KEY UPDATE ...
4782
4184
  value used in the INSERT statement.*/
4783
4185
 
4784
4186
  if (error == DB_SUCCESS
4785
 
      && getTable()->next_number_field
4786
 
      && new_row == getTable()->getInsertRecord()
4787
 
      && user_session->getSqlCommand() == SQLCOM_INSERT
 
4187
      && table->next_number_field
 
4188
      && new_row == table->getInsertRecord()
 
4189
      && session_sql_command(user_session) == SQLCOM_INSERT
4788
4190
      && (trx->duplicates & (TRX_DUP_IGNORE | TRX_DUP_REPLACE))
4789
4191
    == TRX_DUP_IGNORE)  {
4790
4192
 
4791
4193
    uint64_t  auto_inc;
4792
4194
    uint64_t  col_max_value;
4793
4195
 
4794
 
    auto_inc = getTable()->next_number_field->val_int();
 
4196
    auto_inc = table->next_number_field->val_int();
4795
4197
 
4796
4198
    /* We need the upper limit of the col type to check for
4797
4199
    whether we update the table autoinc counter or not. */
4798
4200
    col_max_value = innobase_get_int_col_max_value(
4799
 
      getTable()->next_number_field);
 
4201
      table->next_number_field);
4800
4202
 
4801
4203
    if (auto_inc <= col_max_value && auto_inc != 0) {
4802
4204
 
4863
4265
 
4864
4266
  error = row_update_for_mysql((byte*) record, prebuilt);
4865
4267
 
4866
 
  user_session->setXaId(trx->id);
4867
 
 
4868
4268
  innodb_srv_conc_exit_innodb(trx);
4869
4269
 
4870
4270
  error = convert_error_code_to_mysql(
4898
4298
  case ROW_READ_WITH_LOCKS:
4899
4299
    if (!srv_locks_unsafe_for_binlog
4900
4300
        && prebuilt->trx->isolation_level
4901
 
        > TRX_ISO_READ_COMMITTED) {
 
4301
        != TRX_ISO_READ_COMMITTED) {
4902
4302
      break;
4903
4303
    }
4904
4304
    /* fall through */
4928
4328
ha_innobase::try_semi_consistent_read(bool yes)
4929
4329
/*===========================================*/
4930
4330
{
4931
 
  ut_a(prebuilt->trx == session_to_trx(getTable()->in_use));
 
4331
  ut_a(prebuilt->trx == session_to_trx(table->in_use));
4932
4332
 
4933
4333
  /* Row read type is set to semi consistent read if this was
4934
4334
  requested by the MySQL and either innodb_locks_unsafe_for_binlog
4937
4337
 
4938
4338
  if (yes
4939
4339
      && (srv_locks_unsafe_for_binlog
4940
 
    || prebuilt->trx->isolation_level <= TRX_ISO_READ_COMMITTED)) {
 
4340
    || prebuilt->trx->isolation_level == TRX_ISO_READ_COMMITTED)) {
4941
4341
    prebuilt->row_read_type = ROW_READ_TRY_SEMI_CONSISTENT;
4942
4342
  } else {
4943
4343
    prebuilt->row_read_type = ROW_READ_WITH_LOCKS;
5118
4518
 
5119
4519
  index = prebuilt->index;
5120
4520
 
5121
 
  if (UNIV_UNLIKELY(index == NULL)) {
5122
 
    prebuilt->index_usable = FALSE;
5123
 
    return(HA_ERR_CRASHED);
5124
 
  }
5125
 
 
5126
 
  if (UNIV_UNLIKELY(!prebuilt->index_usable)) {
5127
 
    return(HA_ERR_TABLE_DEF_CHANGED);
5128
 
  }
5129
 
 
5130
4521
  /* Note that if the index for which the search template is built is not
5131
4522
  necessarily prebuilt->index, but can also be the clustered index */
5132
4523
 
5133
4524
  if (prebuilt->sql_stat_start) {
5134
 
    build_template(prebuilt, user_session, getTable(),
 
4525
    build_template(prebuilt, user_session, table,
5135
4526
             ROW_MYSQL_REC_FIELDS);
5136
4527
  }
5137
4528
 
5186
4577
  switch (ret) {
5187
4578
  case DB_SUCCESS:
5188
4579
    error = 0;
5189
 
    getTable()->status = 0;
 
4580
    table->status = 0;
5190
4581
    break;
5191
4582
  case DB_RECORD_NOT_FOUND:
5192
4583
    error = HA_ERR_KEY_NOT_FOUND;
5193
 
    getTable()->status = STATUS_NOT_FOUND;
 
4584
    table->status = STATUS_NOT_FOUND;
5194
4585
    break;
5195
4586
  case DB_END_OF_INDEX:
5196
4587
    error = HA_ERR_KEY_NOT_FOUND;
5197
 
    getTable()->status = STATUS_NOT_FOUND;
 
4588
    table->status = STATUS_NOT_FOUND;
5198
4589
    break;
5199
4590
  default:
5200
4591
    error = convert_error_code_to_mysql((int) ret,
5201
4592
                prebuilt->table->flags,
5202
4593
                user_session);
5203
 
    getTable()->status = STATUS_NOT_FOUND;
 
4594
    table->status = STATUS_NOT_FOUND;
5204
4595
    break;
5205
4596
  }
5206
4597
 
5239
4630
 
5240
4631
  ha_statistic_increment(&system_status_var::ha_read_key_count);
5241
4632
 
5242
 
  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) 
5243
4637
  {
5244
 
    KeyInfo *key = getTable()->key_info + keynr;
5245
 
    index = innobase_index_lookup(share, keynr);
5246
 
 
5247
 
    if (index) {
5248
 
      ut_a(ut_strcmp(index->name, key->name) == 0);
5249
 
    } else {
5250
 
      /* Can't find index with keynr in the translation
5251
 
         table. Only print message if the index translation
5252
 
         table exists */
5253
 
      if (share->idx_trans_tbl.index_mapping) {
5254
 
        errmsg_printf(error::ERROR,
5255
 
                      "InnoDB could not find "
5256
 
                      "index %s key no %u for "
5257
 
                      "table %s through its "
5258
 
                      "index translation table",
5259
 
                      key ? key->name : "NULL",
5260
 
                      keynr,
5261
 
                      prebuilt->table->name);
5262
 
      }
5263
 
 
5264
 
      index = dict_table_get_index_on_name(prebuilt->table,
5265
 
                                           key->name);
5266
 
    }
 
4638
    index = dict_table_get_index_on_name(prebuilt->table,
 
4639
                                         table->getShare()->getTableProto()->indexes(keynr).name().c_str());
5267
4640
  } else {
5268
4641
    index = dict_table_get_first_index(prebuilt->table);
5269
4642
  }
5270
4643
 
5271
4644
  if (!index) {
5272
 
    errmsg_printf(error::ERROR, 
 
4645
    errmsg_printf(ERRMSG_LVL_ERROR, 
5273
4646
      "Innodb could not find key n:o %u with name %s "
5274
4647
      "from dict cache for table %s",
5275
 
      keynr, getTable()->getShare()->getTableMessage()->indexes(keynr).name().c_str(),
 
4648
      keynr, table->getShare()->getTableProto()->indexes(keynr).name().c_str(),
5276
4649
      prebuilt->table->name);
5277
4650
  }
5278
4651
 
5298
4671
  prebuilt->index = innobase_get_index(keynr);
5299
4672
 
5300
4673
  if (UNIV_UNLIKELY(!prebuilt->index)) {
5301
 
    errmsg_printf(error::WARN, "InnoDB: change_active_index(%u) failed",
 
4674
    errmsg_printf(ERRMSG_LVL_WARN, "InnoDB: change_active_index(%u) failed",
5302
4675
          keynr);
5303
 
    prebuilt->index_usable = FALSE;
5304
4676
    return(1);
5305
4677
  }
5306
4678
 
5308
4680
                 prebuilt->index);
5309
4681
 
5310
4682
  if (UNIV_UNLIKELY(!prebuilt->index_usable)) {
5311
 
    push_warning_printf(user_session, DRIZZLE_ERROR::WARN_LEVEL_WARN,
5312
 
                        HA_ERR_TABLE_DEF_CHANGED,
5313
 
                        "InnoDB: insufficient history for index %u",
5314
 
                        keynr);
 
4683
    errmsg_printf(ERRMSG_LVL_WARN,
 
4684
         "InnoDB: insufficient history for index %u",
 
4685
          keynr);
5315
4686
    /* The caller seems to ignore this.  Thus, we must check
5316
4687
    this again in row_search_for_mysql(). */
5317
4688
    return(2);
5330
4701
  the flag ROW_MYSQL_WHOLE_ROW below, but that caused unnecessary
5331
4702
  copying. Starting from MySQL-4.1 we use a more efficient flag here. */
5332
4703
 
5333
 
  build_template(prebuilt, user_session, getTable(), ROW_MYSQL_REC_FIELDS);
 
4704
  build_template(prebuilt, user_session, table, ROW_MYSQL_REC_FIELDS);
5334
4705
 
5335
4706
  return(0);
5336
4707
}
5390
4761
  switch (ret) {
5391
4762
  case DB_SUCCESS:
5392
4763
    error = 0;
5393
 
    getTable()->status = 0;
 
4764
    table->status = 0;
5394
4765
    break;
5395
4766
  case DB_RECORD_NOT_FOUND:
5396
4767
    error = HA_ERR_END_OF_FILE;
5397
 
    getTable()->status = STATUS_NOT_FOUND;
 
4768
    table->status = STATUS_NOT_FOUND;
5398
4769
    break;
5399
4770
  case DB_END_OF_INDEX:
5400
4771
    error = HA_ERR_END_OF_FILE;
5401
 
    getTable()->status = STATUS_NOT_FOUND;
 
4772
    table->status = STATUS_NOT_FOUND;
5402
4773
    break;
5403
4774
  default:
5404
4775
    error = convert_error_code_to_mysql(
5405
4776
      (int) ret, prebuilt->table->flags, user_session);
5406
 
    getTable()->status = STATUS_NOT_FOUND;
 
4777
    table->status = STATUS_NOT_FOUND;
5407
4778
    break;
5408
4779
  }
5409
4780
 
5598
4969
 
5599
4970
  ha_statistic_increment(&system_status_var::ha_read_rnd_count);
5600
4971
 
5601
 
  ut_a(prebuilt->trx == session_to_trx(getTable()->in_use));
 
4972
  ut_a(prebuilt->trx == session_to_trx(table->in_use));
5602
4973
 
5603
4974
  if (prebuilt->clust_index_was_generated) {
5604
4975
    /* No primary key was defined for the table and we
5644
5015
{
5645
5016
  uint    len;
5646
5017
 
5647
 
  ut_a(prebuilt->trx == session_to_trx(getTable()->in_use));
 
5018
  ut_a(prebuilt->trx == session_to_trx(table->in_use));
5648
5019
 
5649
5020
  if (prebuilt->clust_index_was_generated) {
5650
5021
    /* No primary key was defined for the table and we
5664
5035
  table. */
5665
5036
 
5666
5037
  if (len != ref_length) {
5667
 
    errmsg_printf(error::ERROR, "Stored ref len is %lu, but table ref len is %lu",
 
5038
    errmsg_printf(ERRMSG_LVL_ERROR, "Stored ref len is %lu, but table ref len is %lu",
5668
5039
        (ulong) len, (ulong) ref_length);
5669
5040
  }
5670
5041
}
5720
5091
 
5721
5092
    col_type = get_innobase_type_from_mysql_type(&unsigned_type,
5722
5093
                  field);
5723
 
 
5724
 
    if (!col_type) {
5725
 
      push_warning_printf(
5726
 
                          trx->mysql_thd,
5727
 
                          DRIZZLE_ERROR::WARN_LEVEL_WARN,
5728
 
                          ER_CANT_CREATE_TABLE,
5729
 
                          "Error creating table '%s' with "
5730
 
                          "column '%s'. Please check its "
5731
 
                          "column type and try to re-create "
5732
 
                          "the table with an appropriate "
5733
 
                          "column type.",
5734
 
                          table->name, (char*) field->field_name);
5735
 
      goto err_col;
5736
 
    }
5737
 
 
5738
5094
    if (field->null_ptr) {
5739
5095
      nulls_allowed = 0;
5740
5096
    } else {
5757
5113
        /* in data0type.h we assume that the
5758
5114
        number fits in one byte in prtype */
5759
5115
        push_warning_printf(
5760
 
          trx->mysql_thd,
 
5116
          (Session*) trx->mysql_thd,
5761
5117
          DRIZZLE_ERROR::WARN_LEVEL_ERROR,
5762
5118
          ER_CANT_CREATE_TABLE,
5763
5119
          "In InnoDB, charset-collation codes"
5780
5136
    long_true_varchar = 0;
5781
5137
 
5782
5138
    if (field->type() == DRIZZLE_TYPE_VARCHAR) {
5783
 
      col_len -= ((Field_varstring*)field)->pack_length_no_ptr();
 
5139
      col_len -= ((Field_varstring*)field)->length_bytes;
5784
5140
 
5785
 
      if (((Field_varstring*)field)->pack_length_no_ptr() == 2) {
 
5141
      if (((Field_varstring*)field)->length_bytes == 2) {
5786
5142
        long_true_varchar = DATA_LONG_TRUE_VARCHAR;
5787
5143
      }
5788
5144
    }
5789
5145
 
5790
 
    /* First check whether the column to be added has a
5791
 
       system reserved name. */
5792
 
    if (dict_col_name_is_reserved(field->field_name)){
5793
 
      my_error(ER_WRONG_COLUMN_NAME, MYF(0), field->field_name);
5794
 
 
5795
 
  err_col:
5796
 
      dict_mem_table_free(table);
5797
 
      trx_commit_for_mysql(trx);
5798
 
 
5799
 
      error = DB_ERROR;
5800
 
      goto error_ret;
5801
 
    }
5802
 
 
5803
5146
    dict_mem_table_add_col(table, table->heap,
5804
5147
      (char*) field->field_name,
5805
5148
      col_type,
5813
5156
 
5814
5157
  error = row_create_table_for_mysql(table, trx);
5815
5158
 
5816
 
        if (error == DB_DUPLICATE_KEY) {
5817
 
                char buf[100];
5818
 
                char* buf_end = innobase_convert_identifier(
5819
 
                        buf, sizeof buf - 1, table_name, strlen(table_name),
5820
 
                        trx->mysql_thd, TRUE);
5821
 
 
5822
 
                *buf_end = '\0';
5823
 
                my_error(ER_TABLE_EXISTS_ERROR, MYF(0), buf);
5824
 
        }
5825
 
 
5826
 
error_ret:
5827
5159
  error = convert_error_code_to_mysql(error, flags, NULL);
5828
5160
 
5829
5161
  return(error);
5860
5192
 
5861
5193
  n_fields = key->key_parts;
5862
5194
 
5863
 
  /* Assert that "GEN_CLUST_INDEX" cannot be used as non-primary index */
5864
 
  ut_a(innobase_strcasecmp(key->name, innobase_index_reserve_name) != 0);
5865
 
 
5866
5195
  ind_type = 0;
5867
5196
 
5868
5197
  if (key_num == form->getShare()->getPrimaryKey()) {
5915
5244
        && field->type() != DRIZZLE_TYPE_VARCHAR)
5916
5245
      || (field->type() == DRIZZLE_TYPE_VARCHAR
5917
5246
        && key_part->length < field->pack_length()
5918
 
        - ((Field_varstring*)field)->pack_length_no_ptr())) {
 
5247
        - ((Field_varstring*)field)->length_bytes)) {
5919
5248
 
5920
5249
      prefix_len = key_part->length;
5921
5250
 
5923
5252
        || col_type == DATA_FLOAT
5924
5253
        || col_type == DATA_DOUBLE
5925
5254
        || col_type == DATA_DECIMAL) {
5926
 
        errmsg_printf(error::ERROR, 
 
5255
        errmsg_printf(ERRMSG_LVL_ERROR, 
5927
5256
          "MySQL is trying to create a column "
5928
5257
          "prefix index field, on an "
5929
5258
          "inappropriate data type. Table "
5972
5301
  /* We pass 0 as the space id, and determine at a lower level the space
5973
5302
  id where to store the table */
5974
5303
 
5975
 
  index = dict_mem_index_create(table_name,
5976
 
                                innobase_index_reserve_name,
5977
 
                                0, DICT_CLUSTERED, 0);
 
5304
  index = dict_mem_index_create(table_name, "GEN_CLUST_INDEX",
 
5305
              0, DICT_CLUSTERED, 0);
5978
5306
 
5979
5307
  error = row_create_index_for_mysql(index, trx, NULL);
5980
5308
 
6023
5351
/*================*/
6024
5352
  Session         &session, /*!< in: Session */
6025
5353
  Table&    form,   /*!< in: information on table columns and indexes */
6026
 
        const identifier::Table &identifier,
 
5354
        const TableIdentifier &identifier,
6027
5355
        message::Table& create_proto)
6028
5356
{
6029
5357
  int   error;
6032
5360
  trx_t*    trx;
6033
5361
  int   primary_key_no;
6034
5362
  uint    i;
 
5363
  char    name2[FN_REFLEN];
 
5364
  char    norm_name[FN_REFLEN];
6035
5365
  ib_int64_t  auto_inc_value;
6036
5366
  ulint   iflags;
6037
5367
  /* Cache the value of innodb_file_format, in case it is
6038
5368
    modified by another thread while the table is being created. */
6039
5369
  const ulint file_format = srv_file_format;
6040
5370
  bool lex_identified_temp_table= (create_proto.type() == message::Table::TEMPORARY);
6041
 
  const char* stmt;
6042
 
  size_t stmt_len;
6043
 
 
6044
 
  std::string search_string(identifier.getSchemaName());
6045
 
  boost::algorithm::to_lower(search_string);
6046
 
 
6047
 
  if (search_string.compare("data_dictionary") == 0)
6048
 
  {
6049
 
    return HA_WRONG_CREATE_OPTION;
6050
 
  }
 
5371
 
 
5372
  const char *table_name= identifier.getPath().c_str();
6051
5373
 
6052
5374
  if (form.getShare()->sizeFields() > 1000) {
6053
5375
    /* The limit probably should be REC_MAX_N_FIELDS - 3 = 1020,
6070
5392
 
6071
5393
  srv_lower_case_table_names = TRUE;
6072
5394
 
 
5395
  strcpy(name2, table_name);
 
5396
 
 
5397
  normalize_table_name(norm_name, name2);
 
5398
 
6073
5399
  /* Latch the InnoDB data dictionary exclusively so that no deadlocks
6074
5400
    or lock waits can happen in it during a table create operation.
6075
5401
    Drop table etc. do this latching in row0mysql.c. */
6134
5460
# error "DICT_TF_ZSSIZE_MAX < 1"
6135
5461
#endif
6136
5462
 
6137
 
    if (strict_mode)
 
5463
    if (SessionVAR(&session, strict_mode))
6138
5464
    {
6139
5465
      if (! srv_file_per_table)
6140
5466
      {
6153
5479
                            "InnoDB: ROW_FORMAT=compressed requires innodb_file_format > Antelope.");
6154
5480
      }
6155
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;
6156
5490
  }
6157
5491
 
6158
5492
  /* Look for a primary key */
6161
5495
                   (int) form.getShare()->getPrimaryKey() :
6162
5496
                   -1);
6163
5497
 
6164
 
  /* Our function innobase_get_mysql_key_number_for_index assumes
 
5498
  /* Our function row_get_mysql_key_number_for_index assumes
6165
5499
    the primary key is always number 0, if it exists */
6166
5500
 
6167
5501
  assert(primary_key_no == -1 || primary_key_no == 0);
6168
5502
 
6169
 
  /* Check for name conflicts (with reserved name) for
6170
 
     any user indices to be created. */
6171
 
  if (innobase_index_name_is_reserved(trx, form.key_info,
6172
 
                                      form.getShare()->keys)) {
6173
 
    error = -1;
6174
 
    goto cleanup;
6175
 
  }
6176
 
 
6177
 
  if (lex_identified_temp_table)
6178
 
    iflags |= DICT_TF2_TEMPORARY << DICT_TF2_SHIFT;
6179
 
 
6180
 
  error= create_table_def(trx, &form, identifier.getKeyPath().c_str(),
6181
 
                          lex_identified_temp_table ? identifier.getKeyPath().c_str() : NULL,
6182
 
                          iflags);
6183
 
 
6184
 
  session.setXaId(trx->id);
6185
 
 
6186
 
  if (error) {
6187
 
    goto cleanup;
6188
 
  }
6189
 
 
6190
5503
  /* Create the keys */
6191
5504
 
6192
5505
  if (form.getShare()->sizeKeys() == 0 || primary_key_no == -1) {
6194
5507
      order the rows by their row id which is internally generated
6195
5508
      by InnoDB */
6196
5509
 
6197
 
    error = create_clustered_index_when_no_primary(trx, iflags, identifier.getKeyPath().c_str());
 
5510
    error = create_clustered_index_when_no_primary(trx, iflags, norm_name);
6198
5511
    if (error) {
6199
5512
      goto cleanup;
6200
5513
    }
6202
5515
 
6203
5516
  if (primary_key_no != -1) {
6204
5517
    /* In InnoDB the clustered index must always be created first */
6205
 
    if ((error = create_index(trx, &form, iflags, identifier.getKeyPath().c_str(),
 
5518
    if ((error = create_index(trx, &form, iflags, norm_name,
6206
5519
                              (uint) primary_key_no))) {
6207
5520
      goto cleanup;
6208
5521
    }
6211
5524
  for (i = 0; i < form.getShare()->sizeKeys(); i++) {
6212
5525
    if (i != (uint) primary_key_no) {
6213
5526
 
6214
 
      if ((error = create_index(trx, &form, iflags, identifier.getKeyPath().c_str(),
 
5527
      if ((error = create_index(trx, &form, iflags, norm_name,
6215
5528
                                i))) {
6216
5529
        goto cleanup;
6217
5530
      }
6218
5531
    }
6219
5532
  }
6220
5533
 
6221
 
  stmt= session.getQueryStringCopy(stmt_len);
6222
 
 
6223
 
  if (stmt) {
6224
 
    string generated_create_table;
6225
 
    const char *query= stmt;
6226
 
 
6227
 
    if (session.getSqlCommand() == SQLCOM_CREATE_TABLE)
6228
 
    {
6229
 
      message::transformTableDefinitionToSql(create_proto,
6230
 
                                             generated_create_table,
6231
 
                                             message::DRIZZLE, true);
6232
 
      query= generated_create_table.c_str();
6233
 
    }
6234
 
 
 
5534
  if (trx->mysql_query_str) {
6235
5535
    error = row_table_add_foreign_constraints(trx,
6236
 
                                              query, strlen(query),
6237
 
                                              identifier.getKeyPath().c_str(),
 
5536
                                              trx->mysql_query_str, norm_name,
6238
5537
                                              lex_identified_temp_table);
6239
 
    switch (error) {
6240
 
 
6241
 
    case DB_PARENT_NO_INDEX:
6242
 
      push_warning_printf(
6243
 
                          &session, DRIZZLE_ERROR::WARN_LEVEL_WARN,
6244
 
                          HA_ERR_CANNOT_ADD_FOREIGN,
6245
 
                          "Create table '%s' with foreign key constraint"
6246
 
                          " failed. There is no index in the referenced"
6247
 
                          " table where the referenced columns appear"
6248
 
                          " as the first columns.\n", identifier.getKeyPath().c_str());
6249
 
      break;
6250
 
 
6251
 
    case DB_CHILD_NO_INDEX:
6252
 
      push_warning_printf(
6253
 
                          &session, DRIZZLE_ERROR::WARN_LEVEL_WARN,
6254
 
                          HA_ERR_CANNOT_ADD_FOREIGN,
6255
 
                          "Create table '%s' with foreign key constraint"
6256
 
                          " failed. There is no index in the referencing"
6257
 
                          " table where referencing columns appear"
6258
 
                          " as the first columns.\n", identifier.getKeyPath().c_str());
6259
 
      break;
6260
 
    }
6261
5538
 
6262
5539
    error = convert_error_code_to_mysql(error, iflags, NULL);
6263
5540
 
6276
5553
 
6277
5554
  log_buffer_flush_to_disk();
6278
5555
 
6279
 
  innobase_table = dict_table_get(identifier.getKeyPath().c_str(), FALSE);
 
5556
  innobase_table = dict_table_get(norm_name, FALSE);
6280
5557
 
6281
5558
  assert(innobase_table != 0);
6282
5559
 
6284
5561
    /* We update the highest file format in the system table
6285
5562
      space, if this table has higher file format setting. */
6286
5563
 
6287
 
    char changed_file_format_max[100];
6288
 
    strcpy(changed_file_format_max, innobase_file_format_max.c_str());
6289
 
    trx_sys_file_format_max_upgrade((const char **)&changed_file_format_max,
6290
 
      dict_table_get_format(innobase_table));
6291
 
    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));
6292
5566
  }
6293
5567
 
6294
5568
  /* Note: We can't call update_session() as prebuilt will not be
6295
5569
    setup at this stage and so we use session. */
6296
5570
 
6297
5571
  /* We need to copy the AUTOINC value from the old table if
6298
 
    this is an ALTER TABLE or CREATE INDEX because CREATE INDEX
6299
 
    does a table copy too. */
 
5572
    this is an ALTER TABLE. */
6300
5573
 
6301
5574
  if ((create_proto.options().has_auto_increment_value()
6302
 
       || session.getSqlCommand() == SQLCOM_ALTER_TABLE
6303
 
       || session.getSqlCommand() == SQLCOM_CREATE_INDEX)
 
5575
       || session_sql_command(&session) == SQLCOM_ALTER_TABLE)
6304
5576
      && create_proto.options().auto_increment_value() != 0) {
6305
5577
 
6306
 
    /* Query was one of :
6307
 
       CREATE TABLE ...AUTO_INCREMENT = x; or
6308
 
       ALTER TABLE...AUTO_INCREMENT = x;   or
6309
 
       CREATE INDEX x on t(...);
6310
 
       Find out a table definition from the dictionary and get
6311
 
       the current value of the auto increment field. Set a new
6312
 
       value to the auto increment field if the value is greater
6313
 
       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. */
6314
5584
 
6315
5585
    auto_inc_value = create_proto.options().auto_increment_value();
6316
5586
 
6328
5598
 
6329
5599
  if (lex_identified_temp_table)
6330
5600
  {
6331
 
    session.getMessageCache().storeTableMessage(identifier, create_proto);
 
5601
    session.storeTableMessage(identifier, create_proto);
6332
5602
  }
6333
5603
  else
6334
5604
  {
6362
5632
 
6363
5633
  ut_a(prebuilt->trx);
6364
5634
  ut_a(prebuilt->trx->magic_n == TRX_MAGIC_N);
6365
 
  ut_a(prebuilt->trx == session_to_trx(getTable()->in_use));
 
5635
  ut_a(prebuilt->trx == session_to_trx(table->in_use));
6366
5636
 
6367
5637
  dict_table = prebuilt->table;
6368
5638
  trx = prebuilt->trx;
6391
5661
  /* Get the transaction associated with the current session, or create one
6392
5662
  if not yet created, and update prebuilt->trx */
6393
5663
 
6394
 
  update_session(getTable()->in_use);
 
5664
  update_session(table->in_use);
6395
5665
 
6396
 
  if (user_session->getSqlCommand() != SQLCOM_TRUNCATE) {
 
5666
  if (session_sql_command(user_session) != SQLCOM_TRUNCATE) {
6397
5667
  fallback:
6398
5668
    /* We only handle TRUNCATE TABLE t as a special case.
6399
5669
    DELETE FROM t will have to use ha_innobase::doDeleteRecord(),
6427
5697
InnobaseEngine::doDropTable(
6428
5698
/*======================*/
6429
5699
        Session &session,
6430
 
        const identifier::Table &identifier)
 
5700
        const TableIdentifier &identifier)
6431
5701
{
6432
5702
  int error;
6433
5703
  trx_t*  parent_trx;
6434
5704
  trx_t*  trx;
 
5705
  char  norm_name[1000];
6435
5706
 
6436
5707
  ut_a(identifier.getPath().length() < 1000);
6437
5708
 
6438
 
  std::string search_string(identifier.getSchemaName());
6439
 
  boost::algorithm::to_lower(search_string);
6440
 
 
6441
 
  if (search_string.compare("data_dictionary") == 0)
6442
 
  {
6443
 
    return HA_ERR_TABLE_READONLY;
6444
 
  }
 
5709
  /* Strangely, MySQL passes the table name without the '.frm'
 
5710
    extension, in contrast to ::create */
 
5711
  normalize_table_name(norm_name, identifier.getPath().c_str());
6445
5712
 
6446
5713
  /* Get the transaction associated with the current session, or create one
6447
5714
    if not yet created */
6459
5726
 
6460
5727
  /* Drop the table in InnoDB */
6461
5728
 
6462
 
  error = row_drop_table_for_mysql(identifier.getKeyPath().c_str(), trx,
6463
 
                                   session.getSqlCommand()
 
5729
  error = row_drop_table_for_mysql(norm_name, trx,
 
5730
                                   session_sql_command(&session)
6464
5731
                                   == SQLCOM_DROP_DB);
6465
5732
 
6466
 
  session.setXaId(trx->id);
6467
 
 
6468
5733
  /* Flush the log to reduce probability that the .frm files and
6469
5734
    the InnoDB data dictionary get out-of-sync if the user runs
6470
5735
    with innodb_flush_log_at_trx_commit = 0 */
6487
5752
  {
6488
5753
    if (identifier.getType() == message::Table::TEMPORARY)
6489
5754
    {
6490
 
      session.getMessageCache().removeTableMessage(identifier);
6491
 
      ulint sql_command = session.getSqlCommand();
 
5755
      session.removeTableMessage(identifier);
 
5756
      ulint sql_command = session_sql_command(&session);
6492
5757
 
6493
5758
      // If this was the final removal to an alter table then we will need
6494
5759
      // to remove the .dfe that was left behind.
6521
5786
bool
6522
5787
InnobaseEngine::doDropSchema(
6523
5788
/*===================*/
6524
 
                             const identifier::Schema &identifier)
 
5789
                             const SchemaIdentifier &identifier)
6525
5790
    /*!< in: database path; inside InnoDB the name
6526
5791
      of the last directory in the path is used as
6527
5792
      the database name: for example, in 'mysql/data/test'
6571
5836
 
6572
5837
void InnobaseEngine::dropTemporarySchema()
6573
5838
{
6574
 
  identifier::Schema schema_identifier(GLOBAL_TEMPORARY_EXT);
 
5839
  SchemaIdentifier schema_identifier(GLOBAL_TEMPORARY_EXT);
6575
5840
  trx_t*  trx= NULL;
6576
5841
  string schema_path(GLOBAL_TEMPORARY_EXT);
6577
5842
 
6580
5845
  trx = trx_allocate_for_mysql();
6581
5846
 
6582
5847
  trx->mysql_thd = NULL;
 
5848
  trx->mysql_query_str = NULL;
6583
5849
 
6584
5850
  trx->check_foreigns = false;
6585
5851
  trx->check_unique_secondary = false;
6608
5874
innobase_rename_table(
6609
5875
/*==================*/
6610
5876
  trx_t*    trx,  /*!< in: transaction */
6611
 
  const identifier::Table &from,
6612
 
  const identifier::Table &to,
 
5877
  const char* from, /*!< in: old name of the table */
 
5878
  const char* to, /*!< in: new name of the table */
6613
5879
  ibool   lock_and_commit)
6614
5880
        /*!< in: TRUE=lock data dictionary and commit */
6615
5881
{
6616
5882
  int error;
 
5883
  char norm_to[FN_REFLEN];
 
5884
  char norm_from[FN_REFLEN];
6617
5885
 
6618
5886
  srv_lower_case_table_names = TRUE;
6619
5887
 
 
5888
  normalize_table_name(norm_to, to);
 
5889
  normalize_table_name(norm_from, from);
 
5890
 
6620
5891
  /* Serialize data dictionary operations with dictionary mutex:
6621
5892
  no deadlocks can occur then in these operations */
6622
5893
 
6624
5895
    row_mysql_lock_data_dictionary(trx);
6625
5896
  }
6626
5897
 
6627
 
  error = row_rename_table_for_mysql(from.getKeyPath().c_str(), to.getKeyPath().c_str(), trx, lock_and_commit);
 
5898
  error = row_rename_table_for_mysql(
 
5899
    norm_from, norm_to, trx, lock_and_commit);
6628
5900
 
6629
5901
  if (error != DB_SUCCESS) {
6630
5902
    FILE* ef = dict_foreign_err_file;
6631
5903
 
6632
5904
    fputs("InnoDB: Renaming table ", ef);
6633
 
    ut_print_name(ef, trx, TRUE, from.getKeyPath().c_str());
 
5905
    ut_print_name(ef, trx, TRUE, norm_from);
6634
5906
    fputs(" to ", ef);
6635
 
    ut_print_name(ef, trx, TRUE, to.getKeyPath().c_str());
 
5907
    ut_print_name(ef, trx, TRUE, norm_to);
6636
5908
    fputs(" failed!\n", ef);
6637
5909
  }
6638
5910
 
6651
5923
/*********************************************************************//**
6652
5924
Renames an InnoDB table.
6653
5925
@return 0 or error code */
6654
 
UNIV_INTERN int InnobaseEngine::doRenameTable(Session &session, const identifier::Table &from, const identifier::Table &to)
 
5926
UNIV_INTERN int InnobaseEngine::doRenameTable(Session &session, const TableIdentifier &from, const TableIdentifier &to)
6655
5927
{
6656
5928
  // A temp table alter table/rename is a shallow rename and only the
6657
5929
  // definition needs to be updated.
6658
5930
  if (to.getType() == message::Table::TEMPORARY && from.getType() == message::Table::TEMPORARY)
6659
5931
  {
6660
 
    session.getMessageCache().renameTableMessage(from, to);
 
5932
    session.renameTableMessage(from, to);
6661
5933
    return 0;
6662
5934
  }
6663
5935
 
6677
5949
 
6678
5950
  trx = innobase_trx_allocate(&session);
6679
5951
 
6680
 
  error = innobase_rename_table(trx, from, to, TRUE);
6681
 
 
6682
 
  session.setXaId(trx->id);
 
5952
  error = innobase_rename_table(trx, from.getPath().c_str(), to.getPath().c_str(), TRUE);
6683
5953
 
6684
5954
  /* Tell the InnoDB server that there might be work for
6685
5955
    utility threads: */
6689
5959
  innobase_commit_low(trx);
6690
5960
  trx_free_for_mysql(trx);
6691
5961
 
6692
 
  /* Add a special case to handle the Duplicated Key error
6693
 
     and return DB_ERROR instead.
6694
 
     This is to avoid a possible SIGSEGV error from mysql error
6695
 
     handling code. Currently, mysql handles the Duplicated Key
6696
 
     error by re-entering the storage layer and getting dup key
6697
 
     info by calling get_dup_key(). This operation requires a valid
6698
 
     table handle ('row_prebuilt_t' structure) which could no
6699
 
     longer be available in the error handling stage. The suggested
6700
 
     solution is to report a 'table exists' error message (since
6701
 
     the dup key error here is due to an existing table whose name
6702
 
     is the one we are trying to rename to) and return the generic
6703
 
     error code. */
6704
 
  if (error == (int) DB_DUPLICATE_KEY) {
6705
 
    my_error(ER_TABLE_EXISTS_ERROR, to);
6706
 
    error = DB_ERROR;
6707
 
  }
6708
 
 
6709
5962
  error = convert_error_code_to_mysql(error, 0, NULL);
6710
5963
 
6711
5964
  if (not error)
6733
5986
  KeyInfo*    key;
6734
5987
  dict_index_t* index;
6735
5988
  unsigned char*    key_val_buff2 = (unsigned char*) malloc(
6736
 
              getTable()->getShare()->sizeStoredRecord()
6737
 
          + getTable()->getShare()->max_key_length + 100);
6738
 
  ulint   buff2_len = getTable()->getShare()->sizeStoredRecord()
6739
 
          + 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;
6740
5993
  dtuple_t* range_start;
6741
5994
  dtuple_t* range_end;
6742
5995
  ib_int64_t  n_rows;
6744
5997
  ulint   mode2;
6745
5998
  mem_heap_t* heap;
6746
5999
 
6747
 
  ut_a(prebuilt->trx == session_to_trx(getTable()->in_use));
 
6000
  ut_a(prebuilt->trx == session_to_trx(table->in_use));
6748
6001
 
6749
6002
  prebuilt->trx->op_info = (char*)"estimating records in index range";
6750
6003
 
6755
6008
 
6756
6009
  active_index = keynr;
6757
6010
 
6758
 
  key = &getTable()->key_info[active_index];
6759
 
 
6760
 
  index = innobase_get_index(keynr);
6761
 
 
6762
 
  /* There exists possibility of not being able to find requested
6763
 
     index due to inconsistency between MySQL and InoDB dictionary info.
6764
 
     Necessary message should have been printed in innobase_get_index() */
6765
 
  if (UNIV_UNLIKELY(!index)) {
6766
 
    n_rows = HA_POS_ERROR;
6767
 
    goto func_exit;
6768
 
  }
6769
 
 
6770
 
  if (UNIV_UNLIKELY(!row_merge_is_index_usable(prebuilt->trx, index))) {
6771
 
    n_rows = HA_ERR_TABLE_DEF_CHANGED;
6772
 
    goto func_exit;
6773
 
  }
 
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);
6774
6017
 
6775
6018
  heap = mem_heap_create(2 * (key->key_parts * sizeof(dfield_t)
6776
6019
            + sizeof(dtuple_t)));
6815
6058
 
6816
6059
  mem_heap_free(heap);
6817
6060
 
6818
 
func_exit:
6819
6061
  free(key_val_buff2);
6820
6062
 
6821
6063
  prebuilt->trx->op_info = (char*)"";
6845
6087
  dict_index_t* index;
6846
6088
  uint64_t  estimate;
6847
6089
  uint64_t  local_data_file_length;
6848
 
  ulint stat_n_leaf_pages;
6849
6090
 
6850
6091
  /* We do not know if MySQL can call this function before calling
6851
6092
  external_lock(). To be safe, update the session of the current table
6852
6093
  handle. */
6853
6094
 
6854
 
  update_session(getTable()->in_use);
 
6095
  update_session(table->in_use);
6855
6096
 
6856
6097
  prebuilt->trx->op_info = (char*)
6857
6098
         "calculating upper bound for table rows";
6863
6104
 
6864
6105
  index = dict_table_get_first_index(prebuilt->table);
6865
6106
 
6866
 
  stat_n_leaf_pages = index->stat_n_leaf_pages;
6867
 
 
6868
 
  ut_a(stat_n_leaf_pages > 0);
 
6107
  ut_a(index->stat_n_leaf_pages > 0);
6869
6108
 
6870
6109
  local_data_file_length =
6871
 
    ((uint64_t) stat_n_leaf_pages) * UNIV_PAGE_SIZE;
 
6110
    ((uint64_t) index->stat_n_leaf_pages) * UNIV_PAGE_SIZE;
6872
6111
 
6873
6112
 
6874
6113
  /* Calculate a minimum length for a clustered index record and from
6917
6156
  ha_rows total_rows;
6918
6157
  double  time_for_scan;
6919
6158
 
6920
 
  if (index != getTable()->getShare()->getPrimaryKey()) {
 
6159
  if (index != table->getShare()->getPrimaryKey()) {
6921
6160
    /* Not clustered */
6922
6161
    return(Cursor::read_time(index, ranges, rows));
6923
6162
  }
6941
6180
}
6942
6181
 
6943
6182
/*********************************************************************//**
6944
 
Calculates the key number used inside MySQL for an Innobase index. We will
6945
 
first check the "index translation table" for a match of the index to get
6946
 
the index number. If there does not exist an "index translation table",
6947
 
or not able to find the index in the translation table, then we will fall back
6948
 
to the traditional way of looping through dict_index_t list to find a
6949
 
match. In this case, we have to take into account if we generated a
6950
 
default clustered index for the table
6951
 
@return the key number used inside MySQL */
6952
 
static
6953
 
unsigned int
6954
 
innobase_get_mysql_key_number_for_index(
6955
 
/*====================================*/
6956
 
        INNOBASE_SHARE*         share,  /*!< in: share structure for index
6957
 
                                        translation table. */
6958
 
        const drizzled::Table*  table,  /*!< in: table in MySQL data
6959
 
                                        dictionary */
6960
 
        dict_table_t*           ib_table,/*!< in: table in Innodb data
6961
 
                                        dictionary */
6962
 
        const dict_index_t*     index)  /*!< in: index */
6963
 
{
6964
 
        const dict_index_t*     ind;
6965
 
        unsigned int            i;
6966
 
 
6967
 
        ut_ad(index);
6968
 
        ut_ad(ib_table);
6969
 
        ut_ad(table);
6970
 
        ut_ad(share);
6971
 
 
6972
 
        /* If index does not belong to the table of share structure. Search
6973
 
        index->table instead */
6974
 
        if (index->table != ib_table) {
6975
 
                i = 0;
6976
 
                ind = dict_table_get_first_index(index->table);
6977
 
 
6978
 
                while (index != ind) {
6979
 
                        ind = dict_table_get_next_index(ind);
6980
 
                        i++;
6981
 
                }
6982
 
 
6983
 
                if (row_table_got_default_clust_index(index->table)) {
6984
 
                        ut_a(i > 0);
6985
 
                        i--;
6986
 
                }
6987
 
 
6988
 
                return(i);
6989
 
        }
6990
 
 
6991
 
        /* If index does not belong to the table of share structure. Search
6992
 
        index->table instead */
6993
 
        if (index->table != ib_table) {
6994
 
                i = 0;
6995
 
                ind = dict_table_get_first_index(index->table);
6996
 
 
6997
 
                while (index != ind) {
6998
 
                        ind = dict_table_get_next_index(ind);
6999
 
                        i++;
7000
 
                }
7001
 
 
7002
 
                if (row_table_got_default_clust_index(index->table)) {
7003
 
                        ut_a(i > 0);
7004
 
                        i--;
7005
 
                }
7006
 
 
7007
 
                return(i);
7008
 
        }
7009
 
 
7010
 
        /* If index translation table exists, we will first check
7011
 
        the index through index translation table for a match. */
7012
 
        if (share->idx_trans_tbl.index_mapping) {
7013
 
                for (i = 0; i < share->idx_trans_tbl.index_count; i++) {
7014
 
                        if (share->idx_trans_tbl.index_mapping[i] == index) {
7015
 
                                return(i);
7016
 
                        }
7017
 
                }
7018
 
 
7019
 
                /* Print an error message if we cannot find the index
7020
 
                ** in the "index translation table". */
7021
 
                errmsg_printf(error::ERROR,
7022
 
                              "Cannot find index %s in InnoDB index "
7023
 
                                "translation table.", index->name);
7024
 
        }
7025
 
 
7026
 
        /* If we do not have an "index translation table", or not able
7027
 
        to find the index in the translation table, we'll directly find
7028
 
        matching index in the dict_index_t list */
7029
 
        for (i = 0; i < table->getShare()->keys; i++) {
7030
 
                ind = dict_table_get_index_on_name(
7031
 
                        ib_table, table->key_info[i].name);
7032
 
 
7033
 
                if (index == ind) {
7034
 
                        return(i);
7035
 
                }
7036
 
        }
7037
 
 
7038
 
                errmsg_printf(error::ERROR,
7039
 
                              "Cannot find matching index number for index %s "
7040
 
                              "in InnoDB index list.", index->name);
7041
 
 
7042
 
        return(0);
7043
 
}
7044
 
/*********************************************************************//**
7045
6183
Returns statistics information of the table to the MySQL interpreter,
7046
6184
in various fields of the handle object. */
7047
6185
UNIV_INTERN
7054
6192
  dict_index_t* index;
7055
6193
  ha_rows   rec_per_key;
7056
6194
  ib_int64_t  n_rows;
 
6195
  ulong   j;
 
6196
  ulong   i;
 
6197
  char    path[FN_REFLEN];
7057
6198
  os_file_stat_t  stat_info;
7058
6199
 
7059
6200
  /* If we are forcing recovery at a high level, we will suppress
7060
6201
  statistics calculation on tables, because that may crash the
7061
6202
  server if an index is badly corrupted. */
7062
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
 
7063
6214
  /* We do not know if MySQL can call this function before calling
7064
6215
  external_lock(). To be safe, update the session of the current table
7065
6216
  handle. */
7066
6217
 
7067
 
  update_session(getTable()->in_use);
 
6218
  update_session(table->in_use);
7068
6219
 
7069
6220
  /* In case MySQL calls this in the middle of a SELECT query, release
7070
6221
  possible adaptive hash latch to avoid deadlocks of threads */
7076
6227
  ib_table = prebuilt->table;
7077
6228
 
7078
6229
  if (flag & HA_STATUS_TIME) {
7079
 
    /* In Analyze we call with this flag: update
7080
 
       then statistics so that they are up-to-date */
7081
 
 
7082
 
    prebuilt->trx->op_info = "updating table statistics";
7083
 
 
7084
 
    dict_update_statistics(ib_table,
7085
 
                           FALSE /* update even if stats
7086
 
                                    are initialized */);
7087
 
 
7088
 
 
7089
 
    prebuilt->trx->op_info = "returning various info to MySQL";
7090
 
 
7091
 
    fs::path get_status_path(getDataHomeCatalog());
7092
 
    get_status_path /= ib_table->name;
7093
 
    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);
7094
6245
 
7095
6246
    /* Note that we do not know the access time of the table,
7096
6247
    nor the CHECK TABLE time, nor the UPDATE or INSERT time. */
7097
6248
 
7098
 
    if (os_file_get_status(get_status_path.file_string().c_str(), &stat_info)) {
 
6249
    if (os_file_get_status(path,&stat_info)) {
7099
6250
      stats.create_time = (ulong) stat_info.ctime;
7100
6251
    }
7101
6252
  }
7102
6253
 
7103
6254
  if (flag & HA_STATUS_VARIABLE) {
7104
 
 
7105
 
    dict_table_stats_lock(ib_table, RW_S_LATCH);
7106
 
 
7107
6255
    n_rows = ib_table->stat_n_rows;
7108
6256
 
7109
6257
    /* Because we do not protect stat_n_rows by any mutex in a
7131
6279
    n_rows can not be 0 unless the table is empty, set to 1
7132
6280
    instead. The original problem of bug#29507 is actually
7133
6281
    fixed in the server code. */
7134
 
    if (user_session->getSqlCommand() == SQLCOM_TRUNCATE) {
 
6282
    if (session_sql_command(user_session) == SQLCOM_TRUNCATE) {
7135
6283
 
7136
6284
      n_rows = 1;
7137
6285
 
7153
6301
        ib_table->stat_sum_of_other_index_sizes)
7154
6302
          * UNIV_PAGE_SIZE;
7155
6303
 
7156
 
    dict_table_stats_unlock(ib_table, RW_S_LATCH);
7157
 
 
7158
6304
    /* Since fsp_get_available_space_in_free_extents() is
7159
6305
    acquiring latches inside InnoDB, we do not call it if we
7160
6306
    are asked by MySQL to avoid locking. Another reason to
7161
6307
    avoid the call is that it uses quite a lot of CPU.
7162
 
    See Bug#38185. */
7163
 
    if (flag & HA_STATUS_NO_LOCK) {
7164
 
      /* We do not update delete_length if no
7165
 
         locking is requested so the "old" value can
7166
 
         remain. delete_length is initialized to 0 in
7167
 
         the ha_statistics' constructor. */
7168
 
    } else if (UNIV_UNLIKELY
7169
 
               (srv_force_recovery >= SRV_FORCE_NO_IBUF_MERGE)) {
7170
 
      /* Avoid accessing the tablespace if
7171
 
         innodb_crash_recovery is set to a high value. */
7172
 
      stats.delete_length = 0;
7173
 
    } else {
7174
 
      ullint    avail_space;
7175
 
 
7176
 
      avail_space = fsp_get_available_space_in_free_extents(ib_table->space);
7177
 
 
7178
 
      if (avail_space == ULLINT_UNDEFINED) {
 
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
 
 
6314
      /* lock the data dictionary to avoid races with
 
6315
      ibd_file_missing and tablespace_discarded */
 
6316
      row_mysql_lock_data_dictionary(prebuilt->trx);
 
6317
 
 
6318
      /* ib_table->space must be an existent tablespace */
 
6319
      if (!ib_table->ibd_file_missing
 
6320
          && !ib_table->tablespace_discarded) {
 
6321
 
 
6322
        stats.delete_length =
 
6323
          fsp_get_available_space_in_free_extents(
 
6324
            ib_table->space) * 1024;
 
6325
      } else {
 
6326
 
7179
6327
        Session*  session;
7180
6328
 
7181
 
        session= getTable()->in_use;
 
6329
        session= table->in_use;
7182
6330
        assert(session);
7183
6331
 
7184
6332
        push_warning_printf(
7193
6341
          ib_table->name);
7194
6342
 
7195
6343
        stats.delete_length = 0;
7196
 
      } else {
7197
 
        stats.delete_length = avail_space * 1024;
7198
6344
      }
 
6345
 
 
6346
      row_mysql_unlock_data_dictionary(prebuilt->trx);
7199
6347
    }
7200
6348
 
7201
6349
    stats.check_time = 0;
7208
6356
  }
7209
6357
 
7210
6358
  if (flag & HA_STATUS_CONST) {
7211
 
    ulong i;
7212
 
    /* Verify the number of index in InnoDB and MySQL
7213
 
       matches up. If prebuilt->clust_index_was_generated
7214
 
       holds, InnoDB defines GEN_CLUST_INDEX internally */
7215
 
    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);
7216
6360
 
7217
 
    if (getTable()->getShare()->keys != num_innodb_index) {
7218
 
      errmsg_printf(error::ERROR, "Table %s contains %lu "
7219
 
                      "indexes inside InnoDB, which "
7220
 
                      "is different from the number of "
7221
 
                      "indexes %u defined in the MySQL ",
7222
 
                      ib_table->name, num_innodb_index,
7223
 
                      getTable()->getShare()->keys);
 
6361
    if (prebuilt->clust_index_was_generated) {
 
6362
      index = dict_table_get_next_index(index);
7224
6363
    }
7225
6364
 
7226
 
    dict_table_stats_lock(ib_table, RW_S_LATCH);
7227
 
 
7228
 
    for (i = 0; i < getTable()->getShare()->sizeKeys(); i++) {
7229
 
      ulong j;
7230
 
      /* We could get index quickly through internal
7231
 
         index mapping with the index translation table.
7232
 
         The identity of index (match up index name with
7233
 
         that of table->key_info[i]) is already verified in
7234
 
         innobase_get_index().  */
7235
 
      index = innobase_get_index(i);
7236
 
 
 
6365
    for (i = 0; i < table->getShare()->sizeKeys(); i++) {
7237
6366
      if (index == NULL) {
7238
 
        errmsg_printf(error::ERROR, "Table %s contains fewer "
 
6367
        errmsg_printf(ERRMSG_LVL_ERROR, "Table %s contains fewer "
7239
6368
            "indexes inside InnoDB than "
7240
6369
            "are defined in the MySQL "
7241
6370
            ".frm file. Have you mixed up "
7247
6376
        break;
7248
6377
      }
7249
6378
 
7250
 
      for (j = 0; j < getTable()->key_info[i].key_parts; j++) {
 
6379
      for (j = 0; j < table->key_info[i].key_parts; j++) {
7251
6380
 
7252
6381
        if (j + 1 > index->n_uniq) {
7253
 
          errmsg_printf(error::ERROR, 
 
6382
          errmsg_printf(ERRMSG_LVL_ERROR, 
7254
6383
"Index %s of %s has %lu columns unique inside InnoDB, but MySQL is asking "
7255
6384
"statistics for %lu columns. Have you mixed up .frm files from different "
7256
6385
"installations? "
7281
6410
          rec_per_key = 1;
7282
6411
        }
7283
6412
 
7284
 
        getTable()->key_info[i].rec_per_key[j]=
 
6413
        table->key_info[i].rec_per_key[j]=
7285
6414
          rec_per_key >= ~(ulong) 0 ? ~(ulong) 0 :
7286
6415
          (ulong) rec_per_key;
7287
6416
      }
 
6417
 
 
6418
      index = dict_table_get_next_index(index);
7288
6419
    }
7289
 
 
7290
 
    dict_table_stats_unlock(ib_table, RW_S_LATCH);
7291
 
  }
7292
 
 
7293
 
  if (srv_force_recovery >= SRV_FORCE_NO_IBUF_MERGE) {
7294
 
    goto func_exit;
7295
6420
  }
7296
6421
 
7297
6422
  if (flag & HA_STATUS_ERRKEY) {
7304
6429
 
7305
6430
    if (err_index) {
7306
6431
      errkey = (unsigned int)
7307
 
        innobase_get_mysql_key_number_for_index(share, getTable(), ib_table,
7308
 
                                                err_index);
 
6432
        row_get_mysql_key_number_for_index(err_index);
7309
6433
    } else {
7310
6434
      errkey = (unsigned int) prebuilt->trx->error_key_num;
7311
6435
    }
7312
6436
  }
7313
6437
 
7314
 
  if ((flag & HA_STATUS_AUTO) && getTable()->found_next_number_field) {
 
6438
  if ((flag & HA_STATUS_AUTO) && table->found_next_number_field) {
7315
6439
    stats.auto_increment_value = innobase_peek_autoinc();
7316
6440
  }
7317
6441
 
7318
 
func_exit:
7319
6442
  prebuilt->trx->op_info = (char*)"";
7320
6443
 
7321
6444
  return(0);
7348
6471
/*===============*/
7349
6472
  Session*  session)  /*!< in: user thread handle */
7350
6473
{
7351
 
  dict_index_t* index;
7352
 
  ulint         n_rows;
7353
 
  ulint         n_rows_in_table = ULINT_UNDEFINED;
7354
 
  ibool         is_ok           = TRUE;
7355
 
  ulint         old_isolation_level;
 
6474
  ulint   ret;
7356
6475
 
7357
 
  assert(session == getTable()->in_use);
 
6476
  assert(session == table->in_use);
7358
6477
  ut_a(prebuilt->trx);
7359
6478
  ut_a(prebuilt->trx->magic_n == TRX_MAGIC_N);
7360
6479
  ut_a(prebuilt->trx == session_to_trx(session));
7363
6482
    /* Build the template; we will use a dummy template
7364
6483
    in index scans done in checking */
7365
6484
 
7366
 
    build_template(prebuilt, NULL, getTable(), ROW_MYSQL_WHOLE_ROW);
7367
 
  }
7368
 
 
7369
 
  if (prebuilt->table->ibd_file_missing) {
7370
 
        errmsg_printf(error::ERROR, "InnoDB: Error:\n"
7371
 
                    "InnoDB: MySQL is trying to use a table handle"
7372
 
                    " but the .ibd file for\n"
7373
 
                    "InnoDB: table %s does not exist.\n"
7374
 
                    "InnoDB: Have you deleted the .ibd file"
7375
 
                    " from the database directory under\n"
7376
 
                    "InnoDB: the MySQL datadir, or have you"
7377
 
                    " used DISCARD TABLESPACE?\n"
7378
 
                    "InnoDB: Please refer to\n"
7379
 
                    "InnoDB: " REFMAN "innodb-troubleshooting.html\n"
7380
 
                    "InnoDB: how you can resolve the problem.\n",
7381
 
                    prebuilt->table->name);
7382
 
    return(HA_ADMIN_CORRUPT);
7383
 
  }
7384
 
 
7385
 
  prebuilt->trx->op_info = "checking table";
7386
 
 
7387
 
  old_isolation_level = prebuilt->trx->isolation_level;
7388
 
 
7389
 
  /* We must run the index record counts at an isolation level
7390
 
     >= READ COMMITTED, because a dirty read can see a wrong number
7391
 
     of records in some index; to play safe, we use always
7392
 
     REPEATABLE READ here */
7393
 
 
7394
 
  prebuilt->trx->isolation_level = TRX_ISO_REPEATABLE_READ;
7395
 
 
7396
 
  /* Enlarge the fatal lock wait timeout during CHECK TABLE. */
7397
 
  mutex_enter(&kernel_mutex);
7398
 
  srv_fatal_semaphore_wait_threshold += 7200; /* 2 hours */
7399
 
  mutex_exit(&kernel_mutex);
7400
 
 
7401
 
  for (index = dict_table_get_first_index(prebuilt->table);
7402
 
       index != NULL;
7403
 
       index = dict_table_get_next_index(index)) {
7404
 
#if 0
7405
 
    fputs("Validating index ", stderr);
7406
 
    ut_print_name(stderr, trx, FALSE, index->name);
7407
 
    putc('\n', stderr);
7408
 
#endif
7409
 
 
7410
 
    if (!btr_validate_index(index, prebuilt->trx)) {
7411
 
      is_ok = FALSE;
7412
 
      push_warning_printf(session, DRIZZLE_ERROR::WARN_LEVEL_WARN,
7413
 
                          ER_NOT_KEYFILE,
7414
 
                          "InnoDB: The B-tree of"
7415
 
                          " index '%-.200s' is corrupted.",
7416
 
                          index->name);
7417
 
      continue;
7418
 
    }
7419
 
 
7420
 
    /* Instead of invoking change_active_index(), set up
7421
 
       a dummy template for non-locking reads, disabling
7422
 
       access to the clustered index. */
7423
 
    prebuilt->index = index;
7424
 
 
7425
 
    prebuilt->index_usable = row_merge_is_index_usable(
7426
 
                        prebuilt->trx, prebuilt->index);
7427
 
 
7428
 
    if (UNIV_UNLIKELY(!prebuilt->index_usable)) {
7429
 
      push_warning_printf(session, DRIZZLE_ERROR::WARN_LEVEL_WARN,
7430
 
                          HA_ERR_TABLE_DEF_CHANGED,
7431
 
                          "InnoDB: Insufficient history for"
7432
 
                          " index '%-.200s'",
7433
 
                          index->name);
7434
 
      continue;
7435
 
    }
7436
 
 
7437
 
    prebuilt->sql_stat_start = TRUE;
7438
 
    prebuilt->template_type = ROW_MYSQL_DUMMY_TEMPLATE;
7439
 
    prebuilt->n_template = 0;
7440
 
    prebuilt->need_to_access_clustered = FALSE;
7441
 
 
7442
 
    dtuple_set_n_fields(prebuilt->search_tuple, 0);
7443
 
 
7444
 
    prebuilt->select_lock_type = LOCK_NONE;
7445
 
 
7446
 
    if (!row_check_index_for_mysql(prebuilt, index, &n_rows)) {
7447
 
      push_warning_printf(session, DRIZZLE_ERROR::WARN_LEVEL_WARN,
7448
 
                          ER_NOT_KEYFILE,
7449
 
                          "InnoDB: The B-tree of"
7450
 
                          " index '%-.200s' is corrupted.",
7451
 
                          index->name);
7452
 
      is_ok = FALSE;
7453
 
    }
7454
 
 
7455
 
    if (user_session->getKilled()) {
7456
 
      break;
7457
 
    }
7458
 
 
7459
 
#if 0
7460
 
    fprintf(stderr, "%lu entries in index %s\n", n_rows,
7461
 
            index->name);
7462
 
#endif
7463
 
 
7464
 
    if (index == dict_table_get_first_index(prebuilt->table)) {
7465
 
      n_rows_in_table = n_rows;
7466
 
    } else if (n_rows != n_rows_in_table) {
7467
 
      push_warning_printf(session, DRIZZLE_ERROR::WARN_LEVEL_WARN,
7468
 
                          ER_NOT_KEYFILE,
7469
 
                          "InnoDB: Index '%-.200s'"
7470
 
                          " contains %lu entries,"
7471
 
                          " should be %lu.",
7472
 
                          index->name,
7473
 
                          (ulong) n_rows,
7474
 
                          (ulong) n_rows_in_table);
7475
 
      is_ok = FALSE;
7476
 
    }
7477
 
  }
7478
 
 
7479
 
  /* Restore the original isolation level */
7480
 
  prebuilt->trx->isolation_level = old_isolation_level;
7481
 
 
7482
 
  /* We validate also the whole adaptive hash index for all tables
7483
 
     at every CHECK TABLE */
7484
 
 
7485
 
  if (!btr_search_validate()) {
7486
 
    push_warning(session, DRIZZLE_ERROR::WARN_LEVEL_WARN,
7487
 
                 ER_NOT_KEYFILE,
7488
 
                 "InnoDB: The adaptive hash index is corrupted.");
7489
 
    is_ok = FALSE;
7490
 
  }
7491
 
 
7492
 
  /* Restore the fatal lock wait timeout after CHECK TABLE. */
7493
 
  mutex_enter(&kernel_mutex);
7494
 
  srv_fatal_semaphore_wait_threshold -= 7200; /* 2 hours */
7495
 
  mutex_exit(&kernel_mutex);
7496
 
 
7497
 
  prebuilt->trx->op_info = "";
7498
 
  if (user_session->getKilled()) {
7499
 
    my_error(ER_QUERY_INTERRUPTED, MYF(0));
7500
 
  }
7501
 
 
7502
 
  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);
7503
6495
}
7504
6496
 
7505
6497
/*************************************************************//**
7525
6517
    return((char*)comment); /* string too long */
7526
6518
  }
7527
6519
 
7528
 
  update_session(getTable()->in_use);
 
6520
  update_session(table->in_use);
7529
6521
 
7530
6522
  prebuilt->trx->op_info = (char*)"returning table comment";
7531
6523
 
7596
6588
  external_lock(). To be safe, update the session of the current table
7597
6589
  handle. */
7598
6590
 
7599
 
  update_session(getTable()->in_use);
 
6591
  update_session(table->in_use);
7600
6592
 
7601
6593
  prebuilt->trx->op_info = (char*)"getting info on foreign keys";
7602
6594
 
7617
6609
  flen = ftell(srv_dict_tmpfile);
7618
6610
  if (flen < 0) {
7619
6611
    flen = 0;
 
6612
  } else if (flen > 64000 - 1) {
 
6613
    flen = 64000 - 1;
7620
6614
  }
7621
6615
 
7622
6616
  /* allocate buffer for the string, and
7643
6637
  dict_foreign_t* foreign;
7644
6638
 
7645
6639
  ut_a(prebuilt != NULL);
7646
 
  update_session(getTable()->in_use);
 
6640
  update_session(table->in_use);
7647
6641
  prebuilt->trx->op_info = (char*)"getting list of foreign keys";
7648
6642
  trx_search_latch_release_if_reserved(prebuilt->trx);
7649
6643
  mutex_enter(&(dict_sys->mutex));
7676
6670
      i++;
7677
6671
    }
7678
6672
    db_name[i] = 0;
7679
 
    ulen= identifier::Table::filename_to_tablename(db_name, uname, sizeof(uname));
 
6673
    ulen= TableIdentifier::filename_to_tablename(db_name, uname, sizeof(uname));
7680
6674
    LEX_STRING *tmp_referenced_db = session->make_lex_string(NULL, uname, ulen, true);
7681
6675
 
7682
6676
    /* Table name */
7683
6677
    tmp_buff += i + 1;
7684
 
    ulen= identifier::Table::filename_to_tablename(tmp_buff, uname, sizeof(uname));
 
6678
    ulen= TableIdentifier::filename_to_tablename(tmp_buff, uname, sizeof(uname));
7685
6679
    LEX_STRING *tmp_referenced_table = session->make_lex_string(NULL, uname, ulen, true);
7686
6680
 
7687
6681
    /** Foreign Fields **/
7759
6753
                              tmp_foreign_fields, tmp_referenced_fields);
7760
6754
 
7761
6755
    ForeignKeyInfo *pf_key_info = (ForeignKeyInfo *)
7762
 
      session->getMemRoot()->duplicate(&f_key_info, sizeof(ForeignKeyInfo));
 
6756
      session->memdup(&f_key_info, sizeof(ForeignKeyInfo));
7763
6757
    f_key_list->push_back(pf_key_info);
7764
6758
    foreign = UT_LIST_GET_NEXT(foreign_list, foreign);
7765
6759
  }
7781
6775
{
7782
6776
  bool  can_switch;
7783
6777
 
7784
 
  ut_a(prebuilt->trx == session_to_trx(getTable()->in_use));
 
6778
  ut_a(prebuilt->trx == session_to_trx(table->in_use));
7785
6779
 
7786
6780
  prebuilt->trx->op_info =
7787
6781
      "determining if there are foreign key constraints";
7869
6863
      either, because the calling threads may change.
7870
6864
      CAREFUL HERE, OR MEMORY CORRUPTION MAY OCCUR! */
7871
6865
    case HA_EXTRA_IGNORE_DUP_KEY:
7872
 
      session_to_trx(getTable()->in_use)->duplicates |= TRX_DUP_IGNORE;
 
6866
      session_to_trx(table->in_use)->duplicates |= TRX_DUP_IGNORE;
7873
6867
      break;
7874
6868
    case HA_EXTRA_WRITE_CAN_REPLACE:
7875
 
      session_to_trx(getTable()->in_use)->duplicates |= TRX_DUP_REPLACE;
 
6869
      session_to_trx(table->in_use)->duplicates |= TRX_DUP_REPLACE;
7876
6870
      break;
7877
6871
    case HA_EXTRA_WRITE_CANNOT_REPLACE:
7878
 
      session_to_trx(getTable()->in_use)->duplicates &= ~TRX_DUP_REPLACE;
 
6872
      session_to_trx(table->in_use)->duplicates &= ~TRX_DUP_REPLACE;
7879
6873
      break;
7880
6874
    case HA_EXTRA_NO_IGNORE_DUP_KEY:
7881
 
      session_to_trx(getTable()->in_use)->duplicates &=
 
6875
      session_to_trx(table->in_use)->duplicates &=
7882
6876
        ~(TRX_DUP_IGNORE | TRX_DUP_REPLACE);
7883
6877
      break;
7884
6878
    default:/* Do nothing */
8014
7008
{
8015
7009
  trx_t*      trx;
8016
7010
  static const char truncated_msg[] = "... truncated...\n";
8017
 
  const long    MAX_STATUS_SIZE = 1048576;
 
7011
  const long    MAX_STATUS_SIZE = 64000;
8018
7012
  ulint     trx_list_start = ULINT_UNDEFINED;
8019
7013
  ulint     trx_list_end = ULINT_UNDEFINED;
8020
7014
 
8032
7026
 
8033
7027
  mutex_enter(&srv_monitor_file_mutex);
8034
7028
  rewind(srv_monitor_file);
8035
 
  srv_printf_innodb_monitor(srv_monitor_file, FALSE,
 
7029
  srv_printf_innodb_monitor(srv_monitor_file,
8036
7030
        &trx_list_start, &trx_list_end);
8037
7031
  flen = ftell(srv_monitor_file);
8038
7032
  os_file_set_eof(srv_monitor_file);
8043
7037
 
8044
7038
  if (flen > MAX_STATUS_SIZE) {
8045
7039
    usable_len = MAX_STATUS_SIZE;
8046
 
    srv_truncated_status_writes++;
8047
7040
  } else {
8048
7041
    usable_len = flen;
8049
7042
  }
8079
7072
 
8080
7073
  mutex_exit(&srv_monitor_file_mutex);
8081
7074
 
8082
 
  stat_print(session, innobase_engine_name, strlen(innobase_engine_name),
8083
 
             STRING_WITH_LEN(""), str, flen);
 
7075
  bool result = FALSE;
8084
7076
 
 
7077
  if (stat_print(session, innobase_engine_name, strlen(innobase_engine_name),
 
7078
      STRING_WITH_LEN(""), str, flen)) {
 
7079
    result= TRUE;
 
7080
  }
8085
7081
  free(str);
8086
7082
 
8087
7083
  return(FALSE);
8088
7084
}
8089
7085
 
8090
7086
/************************************************************************//**
8091
 
Implements the SHOW MUTEX STATUS command.
8092
 
@return true on failure false on success*/
 
7087
Implements the SHOW MUTEX STATUS command. . */
8093
7088
static
8094
7089
bool
8095
7090
innodb_mutex_show_status(
8097
7092
  plugin::StorageEngine*  engine,   /*!< in: the innodb StorageEngine */
8098
7093
  Session*  session,  /*!< in: the MySQL query thread of the
8099
7094
          caller */
8100
 
  stat_print_fn*  stat_print)   /*!< in: function for printing
8101
 
                                        statistics */
 
7095
  stat_print_fn*  stat_print)
8102
7096
{
8103
7097
  char buf1[IO_SIZE], buf2[IO_SIZE];
8104
7098
  mutex_t*  mutex;
8105
7099
  rw_lock_t*  lock;
8106
 
  ulint         block_mutex_oswait_count = 0;
8107
 
  ulint         block_lock_oswait_count = 0;
8108
 
  mutex_t*      block_mutex = NULL;
8109
 
  rw_lock_t*    block_lock = NULL;
8110
7100
#ifdef UNIV_DEBUG
8111
7101
  ulint   rw_lock_count= 0;
8112
7102
  ulint   rw_lock_count_spin_loop= 0;
8120
7110
 
8121
7111
  mutex_enter(&mutex_list_mutex);
8122
7112
 
8123
 
  for (mutex = UT_LIST_GET_FIRST(mutex_list); mutex != NULL;
8124
 
       mutex = UT_LIST_GET_NEXT(list, mutex)) {
8125
 
    if (mutex->count_os_wait == 0) {
8126
 
      continue;
8127
 
    }
8128
 
 
8129
 
 
8130
 
    if (buf_pool_is_block_mutex(mutex)) {
8131
 
      block_mutex = mutex;
8132
 
      block_mutex_oswait_count += mutex->count_os_wait;
8133
 
      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;
8134
7119
    }
8135
7120
#ifdef UNIV_DEBUG
8136
7121
    if (mutex->mutex_type != 1) {
8157
7142
          return(1);
8158
7143
        }
8159
7144
      }
8160
 
    } else {
 
7145
    }
 
7146
    else {
8161
7147
      rw_lock_count += mutex->count_using;
8162
7148
      rw_lock_count_spin_loop += mutex->count_spin_loop;
8163
7149
      rw_lock_count_spin_rounds += mutex->count_spin_rounds;
8169
7155
    buf1len= snprintf(buf1, sizeof(buf1), "%s:%lu",
8170
7156
          mutex->cfile_name, (ulong) mutex->cline);
8171
7157
    buf2len= snprintf(buf2, sizeof(buf2), "os_waits=%lu",
8172
 
                      (ulong) mutex->count_os_wait);
 
7158
          mutex->count_os_wait);
8173
7159
 
8174
7160
    if (stat_print(session, innobase_engine_name,
8175
7161
             engine_name_len, buf1, buf1len,
8178
7164
      return(1);
8179
7165
    }
8180
7166
#endif /* UNIV_DEBUG */
8181
 
  }
8182
 
 
8183
 
  if (block_mutex) {
8184
 
    buf1len = snprintf(buf1, sizeof buf1,
8185
 
                       "combined %s:%lu",
8186
 
                       block_mutex->cfile_name,
8187
 
                       (ulong) block_mutex->cline);
8188
 
    buf2len = snprintf(buf2, sizeof buf2,
8189
 
                       "os_waits=%lu",
8190
 
                       (ulong) block_mutex_oswait_count);
8191
 
 
8192
 
    if (stat_print(session, innobase_engine_name,
8193
 
                   strlen(innobase_engine_name), buf1, buf1len,
8194
 
                   buf2, buf2len)) {
8195
 
      mutex_exit(&mutex_list_mutex);
8196
 
      return(1);
8197
 
    }
 
7167
 
 
7168
next_mutex:
 
7169
    mutex = UT_LIST_GET_NEXT(list, mutex);
8198
7170
  }
8199
7171
 
8200
7172
  mutex_exit(&mutex_list_mutex);
8201
7173
 
8202
7174
  mutex_enter(&rw_lock_list_mutex);
8203
7175
 
8204
 
  for (lock = UT_LIST_GET_FIRST(rw_lock_list); lock != NULL;
8205
 
       lock = UT_LIST_GET_NEXT(list, lock)) {
8206
 
    if (lock->count_os_wait == 0) {
8207
 
      continue;
8208
 
    }
8209
 
 
8210
 
    if (buf_pool_is_block_lock(lock)) {
8211
 
      block_lock = lock;
8212
 
      block_lock_oswait_count += lock->count_os_wait;
8213
 
      continue;
8214
 
    }
8215
 
 
8216
 
    buf1len = snprintf(buf1, sizeof buf1, "%s:%lu",
8217
 
                       lock->cfile_name, (ulong) lock->cline);
8218
 
    buf2len = snprintf(buf2, sizeof buf2, "os_waits=%lu",
8219
 
                       (ulong) lock->count_os_wait);
8220
 
 
8221
 
    if (stat_print(session, innobase_engine_name,
8222
 
                   strlen(innobase_engine_name), buf1, buf1len,
8223
 
                   buf2, buf2len)) {
8224
 
      mutex_exit(&rw_lock_list_mutex);
8225
 
      return(1);
8226
 
    }
8227
 
  }
8228
 
 
8229
 
  if (block_lock) {
8230
 
    buf1len = snprintf(buf1, sizeof buf1,
8231
 
                       "combined %s:%lu",
8232
 
                       block_lock->cfile_name,
8233
 
                       (ulong) block_lock->cline);
8234
 
    buf2len = snprintf(buf2, sizeof buf2,
8235
 
                       "os_waits=%lu",
8236
 
                       (ulong) block_lock_oswait_count);
8237
 
 
8238
 
    if (stat_print(session, innobase_engine_name,
8239
 
                   strlen(innobase_engine_name), buf1, buf1len,
8240
 
                   buf2, buf2len)) {
8241
 
      mutex_exit(&rw_lock_list_mutex);
8242
 
      return(1);
8243
 
    }
 
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);
8244
7194
  }
8245
7195
 
8246
7196
  mutex_exit(&rw_lock_list_mutex);
8247
7197
 
8248
7198
#ifdef UNIV_DEBUG
8249
 
  buf2len = snprintf(buf2, sizeof buf2,
8250
 
                     "count=%lu, spin_waits=%lu, spin_rounds=%lu, "
8251
 
                     "os_waits=%lu, os_yields=%lu, os_wait_times=%lu",
8252
 
                     (ulong) rw_lock_count,
8253
 
                     (ulong) rw_lock_count_spin_loop,
8254
 
                     (ulong) rw_lock_count_spin_rounds,
8255
 
                     (ulong) rw_lock_count_os_wait,
8256
 
                     (ulong) rw_lock_count_os_yield,
8257
 
                     (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));
8258
7206
 
8259
7207
  if (stat_print(session, innobase_engine_name, engine_name_len,
8260
7208
      STRING_WITH_LEN("rw_lock_mutexes"), buf2, buf2len)) {
8289
7237
static INNOBASE_SHARE* get_share(const char* table_name)
8290
7238
{
8291
7239
  INNOBASE_SHARE *share;
8292
 
  boost::mutex::scoped_lock scopedLock(innobase_share_mutex);
 
7240
  pthread_mutex_lock(&innobase_share_mutex);
8293
7241
 
8294
7242
  ulint fold = ut_fold_string(table_name);
8295
7243
 
8299
7247
        !strcmp(share->table_name, table_name));
8300
7248
 
8301
7249
  if (!share) {
 
7250
 
 
7251
    uint length = (uint) strlen(table_name);
 
7252
 
8302
7253
    /* TODO: invoke HASH_MIGRATE if innobase_open_tables
8303
7254
    grows too big */
8304
7255
 
8305
 
    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);
8306
7261
 
8307
7262
    HASH_INSERT(INNOBASE_SHARE, table_name_hash,
8308
7263
          innobase_open_tables, fold, share);
8309
7264
 
8310
7265
    thr_lock_init(&share->lock);
8311
 
 
8312
 
    /* Index translation table initialization */
8313
 
    share->idx_trans_tbl.index_mapping = NULL;
8314
 
    share->idx_trans_tbl.index_count = 0;
8315
 
    share->idx_trans_tbl.array_size = 0;
8316
7266
  }
8317
7267
 
8318
7268
  share->use_count++;
 
7269
  pthread_mutex_unlock(&innobase_share_mutex);
8319
7270
 
8320
7271
  return(share);
8321
7272
}
8322
7273
 
8323
7274
static void free_share(INNOBASE_SHARE* share)
8324
7275
{
8325
 
  boost::mutex::scoped_lock scopedLock(innobase_share_mutex);
 
7276
  pthread_mutex_lock(&innobase_share_mutex);
8326
7277
 
8327
7278
#ifdef UNIV_DEBUG
8328
7279
  INNOBASE_SHARE* share2;
8342
7293
    HASH_DELETE(INNOBASE_SHARE, table_name_hash,
8343
7294
          innobase_open_tables, fold, share);
8344
7295
    share->lock.deinit();
8345
 
 
8346
 
    /* Free any memory from index translation table */
8347
 
    free(share->idx_trans_tbl.index_mapping);
8348
 
 
8349
 
    delete share;
 
7296
    free(share);
8350
7297
 
8351
7298
    /* TODO: invoke HASH_MIGRATE if innobase_open_tables
8352
7299
    shrinks too much */
8353
7300
  }
 
7301
 
 
7302
  pthread_mutex_unlock(&innobase_share_mutex);
8354
7303
}
8355
7304
 
8356
7305
/*****************************************************************//**
8385
7334
  trx = check_trx_exists(session);
8386
7335
 
8387
7336
  assert(EQ_CURRENT_SESSION(session));
8388
 
  const uint32_t sql_command = session->getSqlCommand();
 
7337
  const uint32_t sql_command = session_sql_command(session);
8389
7338
 
8390
7339
  if (sql_command == SQLCOM_DROP_TABLE) {
8391
7340
 
8421
7370
    isolation_level = trx->isolation_level;
8422
7371
 
8423
7372
    if ((srv_locks_unsafe_for_binlog
8424
 
         || isolation_level <= TRX_ISO_READ_COMMITTED)
 
7373
         || isolation_level == TRX_ISO_READ_COMMITTED)
8425
7374
        && isolation_level != TRX_ISO_SERIALIZABLE
8426
7375
        && (lock_type == TL_READ || lock_type == TL_READ_NO_INSERT)
8427
7376
        && (sql_command == SQLCOM_INSERT_SELECT
8428
 
            || sql_command == SQLCOM_REPLACE_SELECT
8429
 
            || sql_command == SQLCOM_UPDATE
8430
 
            || sql_command == SQLCOM_CREATE_TABLE
8431
 
            || sql_command == SQLCOM_SET_OPTION)) {
 
7377
      || sql_command == SQLCOM_UPDATE
 
7378
      || sql_command == SQLCOM_CREATE_TABLE)) {
8432
7379
 
8433
7380
      /* If we either have innobase_locks_unsafe_for_binlog
8434
7381
      option set or this session is using READ COMMITTED
8435
7382
      isolation level and isolation level of the transaction
8436
7383
      is not set to serializable and MySQL is doing
8437
 
      INSERT INTO...SELECT or REPLACE INTO...SELECT
8438
 
      or UPDATE ... = (SELECT ...) or CREATE  ...
8439
 
      SELECT... or SET ... = (SELECT ...) without
8440
 
      FOR UPDATE or IN SHARE MODE in select,
8441
 
      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. */
8442
7388
 
8443
7389
      prebuilt->select_lock_type = LOCK_NONE;
8444
7390
      prebuilt->stored_select_lock_type = LOCK_NONE;
8471
7417
 
8472
7418
    if ((lock_type >= TL_WRITE_CONCURRENT_INSERT
8473
7419
         && lock_type <= TL_WRITE)
8474
 
        && ! session->doing_tablespace_operation()
 
7420
        && !session_tablespace_op(session)
8475
7421
        && sql_command != SQLCOM_TRUNCATE
8476
7422
        && sql_command != SQLCOM_CREATE_TABLE) {
8477
7423
 
8517
7463
  *value = dict_table_autoinc_read(prebuilt->table);
8518
7464
 
8519
7465
  /* It should have been initialized during open. */
8520
 
  if (*value == 0) {
8521
 
    prebuilt->autoinc_error = DB_UNSUPPORTED;
8522
 
    dict_table_autoinc_unlock(prebuilt->table);
8523
 
  }
 
7466
  ut_a(*value != 0);
8524
7467
 
8525
7468
  return(DB_SUCCESS);
8526
7469
}
8527
7470
 
8528
7471
/*******************************************************************//**
8529
 
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 
8530
7473
AUTOINC lock even if the lock mode is set to TRADITIONAL.
8531
7474
@return the autoinc value */
8532
7475
UNIV_INTERN
8546
7489
 
8547
7490
  auto_inc = dict_table_autoinc_read(innodb_table);
8548
7491
 
8549
 
  if (auto_inc == 0) {
8550
 
    ut_print_timestamp(stderr);
8551
 
    errmsg_printf(error::ERROR, "  InnoDB: AUTOINC next value generation is disabled for '%s'\n", innodb_table->name);
8552
 
  }
 
7492
  ut_a(auto_inc > 0);
8553
7493
 
8554
7494
  dict_table_autoinc_unlock(innodb_table);
8555
7495
 
8578
7518
  uint64_t  autoinc = 0;
8579
7519
 
8580
7520
  /* Prepare prebuilt->trx in the table handle */
8581
 
  update_session(getTable()->in_use);
 
7521
  update_session(table->in_use);
8582
7522
 
8583
7523
  error = innobase_get_autoinc(&autoinc);
8584
7524
 
8602
7542
  invoking this method. So we are not sure if it's guaranteed to
8603
7543
  be 0 or not. */
8604
7544
 
8605
 
  /* We need the upper limit of the col type to check for
8606
 
     whether we update the table autoinc counter or not. */
8607
 
  uint64_t col_max_value = innobase_get_int_col_max_value(getTable()->next_number_field);
8608
 
 
8609
7545
  /* Called for the first time ? */
8610
7546
  if (trx->n_autoinc_rows == 0) {
8611
7547
 
8622
7558
  /* Not in the middle of a mult-row INSERT. */
8623
7559
  } else if (prebuilt->autoinc_last_value == 0) {
8624
7560
    set_if_bigger(*first_value, autoinc);
8625
 
    /* Check for -ve values. */
8626
 
  } else if (*first_value > col_max_value && trx->n_autoinc_rows > 0) {
8627
 
    /* Set to next logical value. */
8628
 
    ut_a(autoinc > trx->n_autoinc_rows);
8629
 
    *first_value = (autoinc - trx->n_autoinc_rows) - 1;
8630
7561
  }
8631
7562
 
8632
7563
  *nb_reserved_values = trx->n_autoinc_rows;
8634
7565
  /* This all current style autoinc. */
8635
7566
  {
8636
7567
    uint64_t  need;
8637
 
    uint64_t  current;
8638
7568
    uint64_t  next_value;
8639
 
 
8640
 
    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
 
8641
7576
    need = *nb_reserved_values * increment;
8642
7577
 
8643
7578
    /* Compute the last value in the interval */
8644
 
    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);
8645
7581
 
8646
7582
    prebuilt->autoinc_last_value = next_value;
8647
7583
 
8678
7614
{
8679
7615
  int error;
8680
7616
 
8681
 
  update_session(getTable()->in_use);
 
7617
  update_session(table->in_use);
8682
7618
 
8683
7619
  error = row_lock_table_autoinc_for_mysql(prebuilt);
8684
7620
 
8703
7639
/* See comment in Cursor.cc */
8704
7640
UNIV_INTERN
8705
7641
bool
8706
 
InnobaseEngine::get_error_message(int, String *buf) const
 
7642
InnobaseEngine::get_error_message(int, String *buf)
8707
7643
{
8708
7644
  trx_t*  trx = check_trx_exists(current_session);
8709
7645
 
8744
7680
  /* Do a type-aware comparison of primary key fields. PK fields
8745
7681
  are always NOT NULL, so no checks for NULL are performed. */
8746
7682
 
8747
 
  key_part = getTable()->key_info[getTable()->getShare()->getPrimaryKey()].key_part;
 
7683
  key_part = table->key_info[table->getShare()->getPrimaryKey()].key_part;
8748
7684
 
8749
7685
  key_part_end = key_part
8750
 
      + getTable()->key_info[getTable()->getShare()->getPrimaryKey()].key_parts;
 
7686
      + table->key_info[table->getShare()->getPrimaryKey()].key_parts;
8751
7687
 
8752
7688
  for (; key_part != key_part_end; ++key_part) {
8753
7689
    field = key_part->field;
8787
7723
finds charset information and returns length of prefix_len characters in the
8788
7724
index field in bytes.
8789
7725
@return number of bytes occupied by the first n characters */
 
7726
extern "C" UNIV_INTERN
 
7727
ulint
 
7728
innobase_get_at_most_n_mbchars(
 
7729
/*===========================*/
 
7730
  ulint charset_id, /*!< in: character set id */
 
7731
  ulint prefix_len, /*!< in: prefix length in bytes of the index
 
7732
        (this has to be divided by mbmaxlen to get the
 
7733
        number of CHARACTERS n in the prefix) */
 
7734
  ulint data_len,   /*!< in: length of the string in bytes */
 
7735
  const char* str); /*!< in: character string */
8790
7736
 
8791
7737
ulint
8792
7738
innobase_get_at_most_n_mbchars(
8870
7816
  trx->detailed_error[0]= '\0';
8871
7817
 
8872
7818
  /* Set the isolation level of the transaction. */
8873
 
  trx->isolation_level= innobase_map_isolation_level(session->getTxIsolation());
 
7819
  trx->isolation_level= innobase_map_isolation_level(session_tx_isolation(session));
8874
7820
}
8875
7821
 
8876
7822
void
8885
7831
 
8886
7832
  innobase_release_stat_resources(trx);
8887
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
  }
8888
7851
}
8889
7852
 
8890
7853
/*******************************************************************//**
8913
7876
    return(0);
8914
7877
  }
8915
7878
 
8916
 
  session->get_xid(reinterpret_cast<DrizzleXid*>(&trx->xid));
 
7879
  session->get_xid(reinterpret_cast<DRIZZLE_XID*>(&trx->xid));
8917
7880
 
8918
7881
  /* Release a possible FIFO ticket and search latch. Since we will
8919
7882
  reserve the kernel mutex, we have to release the search system latch
8954
7917
  return(error);
8955
7918
}
8956
7919
 
8957
 
uint64_t InnobaseEngine::doGetCurrentTransactionId(Session *session)
8958
 
{
8959
 
  trx_t *trx= session_to_trx(session);
8960
 
  return (trx->id);
8961
 
}
8962
 
 
8963
 
uint64_t InnobaseEngine::doGetNewTransactionId(Session *session)
8964
 
{
8965
 
  trx_t*& trx = session_to_trx(session);
8966
 
 
8967
 
  if (trx == NULL)
8968
 
  {
8969
 
    trx = innobase_trx_allocate(session);
8970
 
 
8971
 
    innobase_trx_init(session, trx);
8972
 
  }
8973
 
 
8974
 
  mutex_enter(&kernel_mutex);
8975
 
  trx->id= trx_sys_get_new_trx_id();
8976
 
  mutex_exit(&kernel_mutex);
8977
 
 
8978
 
  uint64_t transaction_id= trx->id;
8979
 
 
8980
 
  return transaction_id;
8981
 
}
8982
 
 
8983
7920
/*******************************************************************//**
8984
7921
This function is used to recover X/Open XA distributed transactions.
8985
7922
@return number of prepared transactions stored in xid_list */
9091
8028
}
9092
8029
 
9093
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
/************************************************************//**
9094
8059
Validate the file format check config parameters, as a side effect it
9095
 
sets the srv_max_file_format_at_startup variable.
9096
 
@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 */
9097
8062
static
9098
 
int
9099
 
innobase_file_format_validate_and_set(
 
8063
bool
 
8064
innobase_file_format_check_validate(
9100
8065
/*================================*/
9101
 
  const char* format_max) /*!< in: parameter value */
 
8066
  const char* format_check) /*!< in: parameter value */
9102
8067
{
9103
8068
  uint    format_id;
 
8069
  bool    ret = true;
9104
8070
 
9105
 
  format_id = innobase_file_format_name_lookup(format_max);
 
8071
  format_id = innobase_file_format_name_lookup(format_check);
9106
8072
 
9107
8073
  if (format_id < DICT_TF_FORMAT_MAX + 1) {
9108
 
    srv_max_file_format_at_startup = format_id;
9109
 
    return((int) format_id);
9110
 
  } else {
9111
 
    return(-1);
9112
 
  }
9113
 
}
9114
 
 
9115
 
 
9116
 
 
9117
 
static void init_options(drizzled::module::option_context &context)
9118
 
{
9119
 
  context("disable-checksums",
9120
 
          "Disable InnoDB checksums validation.");
9121
 
  context("data-home-dir",
9122
 
          po::value<string>(),
9123
 
          "The common part for InnoDB table spaces.");
9124
 
  context("disable-doublewrite",
9125
 
          "Disable InnoDB doublewrite buffer.");
9126
 
  context("io-capacity",
9127
 
          po::value<io_capacity_constraint>(&innodb_io_capacity)->default_value(200),
9128
 
          "Number of IOPs the server can do. Tunes the background IO rate");
9129
 
  context("fast-shutdown",
9130
 
          po::value<trinary_constraint>(&innobase_fast_shutdown)->default_value(1), 
9131
 
          "Speeds up the shutdown process of the InnoDB storage engine. Possible values are 0, 1 (faster) or 2 (fastest - crash-like).");
9132
 
  context("purge-batch-size",
9133
 
          po::value<purge_batch_constraint>(&innodb_purge_batch_size)->default_value(20),
9134
 
          "Number of UNDO logs to purge in one batch from the history list. "
9135
 
          "Default is 20.");
9136
 
  context("purge-threads",
9137
 
          po::value<purge_threads_constraint>(&innodb_n_purge_threads)->default_value(0),
9138
 
          "Purge threads can be either 0 or 1. Defalut is 0.");
9139
 
  context("file-per-table",
9140
 
          po::value<bool>(&srv_file_per_table)->default_value(false)->zero_tokens(),
9141
 
           "Stores each InnoDB table to an .ibd file in the database dir.");
9142
 
  context("file-format-max",
9143
 
          po::value<string>(&innobase_file_format_max)->default_value("Antelope"),
9144
 
          "The highest file format in the tablespace.");
9145
 
  context("file-format-check",
9146
 
          po::value<bool>(&innobase_file_format_check)->default_value(true)->zero_tokens(),
9147
 
          "Whether to perform system file format check.");
9148
 
  context("file-format",
9149
 
          po::value<string>(&innobase_file_format_name)->default_value("Antelope"),
9150
 
          "File format to use for new tables in .ibd files.");
9151
 
  context("flush-log-at-trx-commit",
9152
 
          po::value<trinary_constraint>(&innodb_flush_log_at_trx_commit)->default_value(1),
9153
 
          "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).");
9154
 
  context("flush-method",
9155
 
          po::value<string>(),
9156
 
          "With which method to flush data.");
9157
 
  context("log-group-home-dir",
9158
 
          po::value<string>(),
9159
 
          "Path to InnoDB log files.");
9160
 
  context("max-dirty-pages-pct",
9161
 
          po::value<max_dirty_pages_constraint>(&innodb_max_dirty_pages_pct)->default_value(75),
9162
 
          "Percentage of dirty pages allowed in bufferpool.");
9163
 
  context("disable-adaptive-flushing",
9164
 
          "Do not attempt flushing dirty pages to avoid IO bursts at checkpoints.");
9165
 
  context("max-purge-lag",
9166
 
          po::value<uint64_constraint>(&innodb_max_purge_lag)->default_value(0),
9167
 
          "Desired maximum length of the purge queue (0 = no limit)");
9168
 
  context("status-file",
9169
 
          po::value<bool>(&innobase_create_status_file)->default_value(false)->zero_tokens(),
9170
 
          "Enable SHOW INNODB STATUS output in the innodb_status.<pid> file");
9171
 
  context("disable-stats-on-metadata",
9172
 
          "Disable statistics gathering for metadata commands such as SHOW TABLE STATUS (on by default)");
9173
 
  context("stats-sample-pages",
9174
 
          po::value<uint64_nonzero_constraint>(&innodb_stats_sample_pages)->default_value(8),
9175
 
          "The number of index pages to sample when calculating statistics (default 8)");
9176
 
  context("disable-adaptive-hash-index",
9177
 
          "Enable InnoDB adaptive hash index (enabled by default)");
9178
 
  context("replication-delay",
9179
 
          po::value<uint64_constraint>(&innodb_replication_delay)->default_value(0),
9180
 
          "Replication thread delay (ms) on the slave server if innodb_thread_concurrency is reached (0 by default)");
9181
 
  context("additional-mem-pool-size",
9182
 
          po::value<additional_mem_pool_constraint>(&innobase_additional_mem_pool_size)->default_value(8*1024*1024L),
9183
 
          "Size of a memory pool InnoDB uses to store data dictionary information and other internal data structures.");
9184
 
  context("autoextend-increment",
9185
 
          po::value<autoextend_constraint>(&innodb_auto_extend_increment)->default_value(64L),
9186
 
          "Data file autoextend increment in megabytes");
9187
 
  context("buffer-pool-size",
9188
 
          po::value<buffer_pool_constraint>(&innobase_buffer_pool_size)->default_value(128*1024*1024L),
9189
 
          "The size of the memory buffer InnoDB uses to cache data and indexes of its tables.");
9190
 
  context("buffer-pool-instances",
9191
 
          po::value<buffer_pool_instances_constraint>(&innobase_buffer_pool_instances)->default_value(1),
9192
 
          "Number of buffer pool instances, set to higher value on high-end machines to increase scalability");
9193
 
 
9194
 
  context("commit-concurrency",
9195
 
          po::value<concurrency_constraint>(&innobase_commit_concurrency)->default_value(0),
9196
 
          "Helps in performance tuning in heavily concurrent environments.");
9197
 
  context("concurrency-tickets",
9198
 
          po::value<uint32_nonzero_constraint>(&innodb_concurrency_tickets)->default_value(500L),
9199
 
          "Number of times a thread is allowed to enter InnoDB within the same SQL query after it has once got the ticket");
9200
 
  context("read-io-threads",
9201
 
          po::value<io_threads_constraint>(&innobase_read_io_threads)->default_value(4),
9202
 
          "Number of background read I/O threads in InnoDB.");
9203
 
  context("write-io-threads",
9204
 
          po::value<io_threads_constraint>(&innobase_write_io_threads)->default_value(4),
9205
 
          "Number of background write I/O threads in InnoDB.");
9206
 
  context("force-recovery",
9207
 
          po::value<force_recovery_constraint>(&innobase_force_recovery)->default_value(0),
9208
 
          "Helps to save your data in case the disk image of the database becomes corrupt.");
9209
 
  context("log-buffer-size",
9210
 
          po::value<log_buffer_constraint>(&innobase_log_buffer_size)->default_value(8*1024*1024L),
9211
 
          "The size of the buffer which InnoDB uses to write log to the log files on disk.");
9212
 
  context("log-file-size",
9213
 
          po::value<log_file_constraint>(&innobase_log_file_size)->default_value(20*1024*1024L),
9214
 
          "The size of the buffer which InnoDB uses to write log to the log files on disk.");
9215
 
  context("log-files-in-group",
9216
 
          po::value<log_files_in_group_constraint>(&innobase_log_files_in_group)->default_value(2),
9217
 
          "Number of log files in the log group. InnoDB writes to the files in a circular fashion.");
9218
 
  context("mirrored-log-groups",
9219
 
          po::value<mirrored_log_groups_constraint>(&innobase_mirrored_log_groups)->default_value(1),
9220
 
          "Number of identical copies of log groups we keep for the database. Currently this should be set to 1.");
9221
 
  context("open-files",
9222
 
          po::value<open_files_constraint>(&innobase_open_files)->default_value(300L),
9223
 
          "How many files at the maximum InnoDB keeps open at the same time.");
9224
 
  context("sync-spin-loops",
9225
 
          po::value<uint32_constraint>(&innodb_sync_spin_loops)->default_value(30L),
9226
 
          "Count of spin-loop rounds in InnoDB mutexes (30 by default)");
9227
 
  context("spin-wait-delay",
9228
 
          po::value<uint32_constraint>(&innodb_spin_wait_delay)->default_value(6L),
9229
 
          "Maximum delay between polling for a spin lock (6 by default)");
9230
 
  context("thread-concurrency",
9231
 
          po::value<concurrency_constraint>(&innobase_thread_concurrency)->default_value(0),
9232
 
          "Helps in performance tuning in heavily concurrent environments. Sets the maximum number of threads allowed inside InnoDB. Value 0 will disable the thread throttling.");
9233
 
  context("thread-sleep-delay",
9234
 
          po::value<uint32_constraint>(&innodb_thread_sleep_delay)->default_value(10000L),
9235
 
          "Time of innodb thread sleeping before joining InnoDB queue (usec). Value 0 disable a sleep");
9236
 
  context("data-file-path",
9237
 
          po::value<string>(),
9238
 
          "Path to individual files and their sizes.");
9239
 
  context("version",
9240
 
          po::value<string>()->default_value(INNODB_VERSION_STR),
9241
 
          "InnoDB version");
9242
 
  context("use-internal-malloc",
9243
 
          "Use InnoDB's internal memory allocator instal of the OS memory allocator.");
9244
 
  context("disable-native-aio",
9245
 
          _("Do not use Native AIO library for IO, even if available"));
9246
 
  context("change-buffering",
9247
 
          po::value<string>(&innobase_change_buffering),
9248
 
          "Buffer changes to reduce random access: OFF, ON, inserting, deleting, changing, or purging.");
9249
 
  context("read-ahead-threshold",
9250
 
          po::value<read_ahead_threshold_constraint>(&innodb_read_ahead_threshold)->default_value(56),
9251
 
          "Number of pages that must be accessed sequentially for InnoDB to trigger a readahead.");
9252
 
  context("disable-xa",
9253
 
          "Disable InnoDB support for the XA two-phase commit");
9254
 
  context("disable-table-locks",
9255
 
          "Disable InnoDB locking in LOCK TABLES");
9256
 
  context("strict-mode",
9257
 
          po::value<bool>(&strict_mode)->default_value(false)->zero_tokens(),
9258
 
          "Use strict mode when evaluating create options.");
9259
 
  context("replication-log",
9260
 
          po::value<bool>(&innobase_use_replication_log)->default_value(false),
9261
 
          _("Enable internal replication log."));
9262
 
  context("lock-wait-timeout",
9263
 
          po::value<lock_wait_constraint>(&lock_wait_timeout)->default_value(50),
9264
 
          _("Timeout in seconds an InnoDB transaction may wait for a lock before being rolled back. Values above 100000000 disable the timeout."));
9265
 
  context("old-blocks-pct",
9266
 
          po::value<old_blocks_constraint>(&innobase_old_blocks_pct)->default_value(100 * 3 / 8),
9267
 
          _("Percentage of the buffer pool to reserve for 'old' blocks."));
9268
 
  context("old-blocks-time",
9269
 
          po::value<uint32_t>(&buf_LRU_old_threshold_ms)->default_value(0),
9270
 
          _("ove blocks to the 'new' end of the buffer pool if the first access"
9271
 
            " was at least this many milliseconds ago."
9272
 
            " The timeout is disabled if 0 (the default)."));
9273
 
}
9274
 
 
9275
 
 
 
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
};
9276
8638
 
9277
8639
DRIZZLE_DECLARE_PLUGIN
9278
8640
{
9283
8645
  "Supports transactions, row-level locking, and foreign keys",
9284
8646
  PLUGIN_LICENSE_GPL,
9285
8647
  innobase_init, /* Plugin Init */
9286
 
  NULL, /* depends */
9287
 
  init_options /* reserved */
 
8648
  innobase_system_variables, /* system variables */
 
8649
  NULL /* reserved */
9288
8650
}
9289
8651
DRIZZLE_DECLARE_PLUGIN_END;
9290
8652
 
9311
8673
  return res;
9312
8674
}
9313
8675
 
9314
 
/***********************************************************************
9315
 
This function checks each index name for a table against reserved
9316
 
system default primary index name 'GEN_CLUST_INDEX'. If a name matches,
9317
 
this function pushes an warning message to the client, and returns true. */
9318
 
UNIV_INTERN
9319
 
bool
9320
 
innobase_index_name_is_reserved(
9321
 
/*============================*/
9322
 
                                        /* out: true if an index name
9323
 
                                        matches the reserved name */
9324
 
        const trx_t*    trx,            /* in: InnoDB transaction handle */
9325
 
        const KeyInfo*  key_info,       /* in: Indexes to be created */
9326
 
        ulint           num_of_keys)    /* in: Number of indexes to
9327
 
                                        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
/*==========================================*/
9328
8689
{
9329
 
  const KeyInfo*        key;
9330
 
  uint          key_num;        /* index number */
9331
 
 
9332
 
  for (key_num = 0; key_num < num_of_keys; key_num++) {
9333
 
    key = &key_info[key_num];
9334
 
 
9335
 
    if (innobase_strcasecmp(key->name,
9336
 
                            innobase_index_reserve_name) == 0) {
9337
 
      /* Push warning to drizzle */
9338
 
      push_warning_printf(trx->mysql_thd,
9339
 
                          DRIZZLE_ERROR::WARN_LEVEL_WARN,
9340
 
                          ER_WRONG_NAME_FOR_INDEX,
9341
 
                          "Cannot Create Index with name "
9342
 
                          "'%s'. The name is reserved "
9343
 
                          "for the system default primary "
9344
 
                          "index.",
9345
 
                          innobase_index_reserve_name);
9346
 
 
9347
 
      my_error(ER_WRONG_NAME_FOR_INDEX, MYF(0),
9348
 
               innobase_index_reserve_name);
9349
 
 
9350
 
      return(true);
9351
 
    }
9352
 
  }
9353
 
 
9354
 
  return(false);
 
8690
  DRIZZLE_SYSVAR_NAME(commit_concurrency).def_val
 
8691
    = innobase_commit_concurrency;
9355
8692
}
9356
8693
 
9357
8694
#ifdef UNIV_COMPILE_TEST_FUNCS
9361
8698
  ulint   buflen;
9362
8699
  const char* id;
9363
8700
  ulint   idlen;
9364
 
  drizzled::Session *session;
 
8701
  void*   session;
9365
8702
  ibool   file_id;
9366
8703
 
9367
8704
  const char* expected;