~drizzle-trunk/drizzle/development

« back to all changes in this revision

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

  • Committer: Monty Taylor
  • Date: 2010-06-18 00:34:51 UTC
  • mto: (1627.2.5 build)
  • mto: This revision was merged to the branch mainline in revision 1628.
  • Revision ID: mordred@inaugust.com-20100618003451-2b3fs2m2hvpch91r
Add function pointer hook for plugins to register program_options.

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,
 
372
                         memory::Root *mem_root)
415
373
  {
416
 
    return new ha_innobase(*this, table);
 
374
    return new (mem_root) ha_innobase(*this, table);
417
375
  }
418
376
 
419
377
  /*********************************************************************
422
380
  doDropSchema(
423
381
  /*===================*/
424
382
        /* out: error number */
425
 
    const identifier::Schema  &identifier); /* in: database path; inside InnoDB the name
 
383
    SchemaIdentifier  &identifier); /* in: database path; inside InnoDB the name
426
384
        of the last directory in the path is used as
427
385
        the database name: for example, in 'mysql/data/test'
428
386
        the database name is 'test' */
461
419
 
462
420
  UNIV_INTERN int doCreateTable(Session &session,
463
421
                                Table &form,
464
 
                                const identifier::Table &identifier,
 
422
                                drizzled::TableIdentifier &identifier,
465
423
                                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);
 
424
  UNIV_INTERN int doRenameTable(Session&, TableIdentifier &from, TableIdentifier &to);
 
425
  UNIV_INTERN int doDropTable(Session &session, TableIdentifier &identifier);
468
426
 
469
 
  UNIV_INTERN virtual bool get_error_message(int error, String *buf) const;
 
427
  UNIV_INTERN virtual bool get_error_message(int error, String *buf);
470
428
 
471
429
  UNIV_INTERN uint32_t max_supported_keys() const;
472
430
  UNIV_INTERN uint32_t max_supported_key_length() const;
483
441
  }
484
442
 
485
443
  int doGetTableDefinition(drizzled::Session& session,
486
 
                           const identifier::Table &identifier,
 
444
                           drizzled::TableIdentifier &identifier,
487
445
                           drizzled::message::Table &table_proto);
488
446
 
489
 
  bool doDoesTableExist(drizzled::Session& session, const identifier::Table &identifier);
 
447
  void doGetTableNames(drizzled::CachedDirectory &directory,
 
448
           drizzled::SchemaIdentifier &schema_identifier,
 
449
                       std::set<std::string> &set_of_names);
 
450
 
 
451
  bool doDoesTableExist(drizzled::Session& session, drizzled::TableIdentifier &identifier);
490
452
 
491
453
  void doGetTableIdentifiers(drizzled::CachedDirectory &directory,
492
 
                             const drizzled::identifier::Schema &schema_identifier,
493
 
                             drizzled::identifier::Table::vector &set_of_identifiers);
 
454
                             drizzled::SchemaIdentifier &schema_identifier,
 
455
                             drizzled::TableIdentifiers &set_of_identifiers);
494
456
  bool validateCreateTableOption(const std::string &key, const std::string &state);
495
457
  void dropTemporarySchema();
496
458
 
518
480
}
519
481
 
520
482
void InnobaseEngine::doGetTableIdentifiers(drizzled::CachedDirectory &directory,
521
 
                                           const drizzled::identifier::Schema &schema_identifier,
522
 
                                           drizzled::identifier::Table::vector &set_of_identifiers)
 
483
                                           drizzled::SchemaIdentifier &schema_identifier,
 
484
                                           drizzled::TableIdentifiers &set_of_identifiers)
523
485
{
524
486
  CachedDirectory::Entries entries= directory.getEntries();
525
487
 
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
488
  for (CachedDirectory::Entries::iterator entry_iter= entries.begin(); 
536
489
       entry_iter != entries.end(); ++entry_iter)
537
490
  {
547
500
    { }
548
501
    else
549
502
    {
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
 
      }
 
503
      char uname[NAME_LEN + 1];
 
504
      uint32_t file_name_len;
 
505
 
 
506
      file_name_len= TableIdentifier::filename_to_tablename(filename->c_str(), uname, sizeof(uname));
 
507
      // TODO: Remove need for memory copy here
 
508
      uname[file_name_len - sizeof(DEFAULT_FILE_EXTENSION) + 1]= '\0'; // Subtract ending, place NULL 
 
509
 
 
510
      set_of_identifiers.push_back(TableIdentifier(schema_identifier, uname));
565
511
    }
566
512
  }
567
513
}
568
514
 
569
 
bool InnobaseEngine::doDoesTableExist(Session &session, const identifier::Table &identifier)
 
515
bool InnobaseEngine::doDoesTableExist(Session &session, TableIdentifier &identifier)
570
516
{
571
517
  string proto_path(identifier.getPath());
572
518
  proto_path.append(DEFAULT_FILE_EXTENSION);
573
519
 
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)
 
520
  if (session.doesTableMessageExist(identifier))
581
521
    return true;
582
522
 
583
523
  if (access(proto_path.c_str(), F_OK))
589
529
}
590
530
 
591
531
int InnobaseEngine::doGetTableDefinition(Session &session,
592
 
                                         const identifier::Table &identifier,
 
532
                                         drizzled::TableIdentifier &identifier,
593
533
                                         message::Table &table_proto)
594
534
{
595
535
  string proto_path(identifier.getPath());
596
536
  proto_path.append(DEFAULT_FILE_EXTENSION);
597
537
 
598
538
  // 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)
 
539
  if (session.getTableMessage(identifier, table_proto))
603
540
    return EEXIST;
604
541
 
605
542
  if (access(proto_path.c_str(), F_OK))
613
550
  return ENOENT;
614
551
}
615
552
 
 
553
void InnobaseEngine::doGetTableNames(CachedDirectory &directory, SchemaIdentifier&, set<string>& set_of_names)
 
554
{
 
555
  CachedDirectory::Entries entries= directory.getEntries();
 
556
 
 
557
  for (CachedDirectory::Entries::iterator entry_iter= entries.begin(); 
 
558
       entry_iter != entries.end(); ++entry_iter)
 
559
  {
 
560
    CachedDirectory::Entry *entry= *entry_iter;
 
561
    const string *filename= &entry->filename;
 
562
 
 
563
    assert(filename->size());
 
564
 
 
565
    const char *ext= strchr(filename->c_str(), '.');
 
566
 
 
567
    if (ext == NULL || my_strcasecmp(system_charset_info, ext, DEFAULT_FILE_EXTENSION) ||
 
568
        (filename->compare(0, strlen(TMP_FILE_PREFIX), TMP_FILE_PREFIX) == 0))
 
569
    { }
 
570
    else
 
571
    {
 
572
      char uname[NAME_LEN + 1];
 
573
      uint32_t file_name_len;
 
574
 
 
575
      file_name_len= TableIdentifier::filename_to_tablename(filename->c_str(), uname, sizeof(uname));
 
576
      // TODO: Remove need for memory copy here
 
577
      uname[file_name_len - sizeof(DEFAULT_FILE_EXTENSION) + 1]= '\0'; // Subtract ending, place NULL 
 
578
      set_of_names.insert(uname);
 
579
    }
 
580
  }
 
581
}
 
582
 
 
583
/** @brief Initialize the default value of innodb_commit_concurrency.
 
584
 
 
585
Once InnoDB is running, the innodb_commit_concurrency must not change
 
586
from zero to nonzero. (Bug #42101)
 
587
 
 
588
The initial default value is 0, and without this extra initialization,
 
589
SET GLOBAL innodb_commit_concurrency=DEFAULT would set the parameter
 
590
to 0, even if it was initially set to nonzero at the command line
 
591
or configuration file. */
 
592
static
 
593
void
 
594
innobase_commit_concurrency_init_default(void);
 
595
/*==========================================*/
616
596
 
617
597
/************************************************************//**
618
598
Validate the file format name and return its corresponding id.
625
605
            name */
626
606
/************************************************************//**
627
607
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(
 
608
sets the srv_check_file_format_at_startup variable.
 
609
@return true if one of  "on" or "off" */
 
610
static
 
611
bool
 
612
innobase_file_format_check_on_off(
 
613
/*==============================*/
 
614
  const char* format_check);    /*!< in: parameter value */
 
615
/************************************************************//**
 
616
Validate the file format check config parameters, as a side effect it
 
617
sets the srv_check_file_format_at_startup variable.
 
618
@return true if valid config value */
 
619
static
 
620
bool
 
621
innobase_file_format_check_validate(
633
622
/*================================*/
634
 
  const char* format_max);    /*!< in: parameter value */
 
623
  const char* format_check);    /*!< in: parameter value */
635
624
 
636
625
static const char innobase_engine_name[]= "InnoDB";
637
626
 
 
627
/*************************************************************//**
 
628
Check for a valid value of innobase_commit_concurrency.
 
629
@return 0 for valid innodb_commit_concurrency */
 
630
static
 
631
int
 
632
innobase_commit_concurrency_validate(
 
633
/*=================================*/
 
634
  Session*      , /*!< in: thread handle */
 
635
  drizzle_sys_var*  , /*!< in: pointer to system
 
636
            variable */
 
637
  void*       save, /*!< out: immediate result
 
638
            for update function */
 
639
  drizzle_value*    value)  /*!< in: incoming string */
 
640
{
 
641
  int64_t   intbuf;
 
642
  ulong   commit_concurrency;
 
643
 
 
644
  if (value->val_int(value, &intbuf)) {
 
645
    /* The value is NULL. That is invalid. */
 
646
    return(1);
 
647
  }
 
648
 
 
649
  *reinterpret_cast<ulong*>(save) = commit_concurrency
 
650
    = static_cast<ulong>(intbuf);
 
651
 
 
652
  /* Allow the value to be updated, as long as it remains zero
 
653
  or nonzero. */
 
654
  return(!(!commit_concurrency == !innobase_commit_concurrency));
 
655
}
 
656
 
 
657
static DRIZZLE_SessionVAR_BOOL(support_xa, PLUGIN_VAR_OPCMDARG,
 
658
  "Enable InnoDB support for the XA two-phase commit",
 
659
  /* check_func */ NULL, /* update_func */ NULL,
 
660
  /* default */ TRUE);
 
661
 
 
662
static DRIZZLE_SessionVAR_BOOL(table_locks, PLUGIN_VAR_OPCMDARG,
 
663
  "Enable InnoDB locking in LOCK TABLES",
 
664
  /* check_func */ NULL, /* update_func */ NULL,
 
665
  /* default */ TRUE);
 
666
 
 
667
static DRIZZLE_SessionVAR_BOOL(strict_mode, PLUGIN_VAR_OPCMDARG,
 
668
  "Use strict mode when evaluating create options.",
 
669
  NULL, NULL, FALSE);
 
670
 
 
671
static DRIZZLE_SessionVAR_ULONG(lock_wait_timeout, PLUGIN_VAR_RQCMDARG,
 
672
  "Timeout in seconds an InnoDB transaction may wait for a lock before being rolled back. Values above 100000000 disable the timeout.",
 
673
  NULL, NULL, 50, 1, 1024 * 1024 * 1024, 0);
 
674
 
638
675
 
639
676
/*****************************************************************//**
640
677
Commits a transaction in an InnoDB database. */
661
698
  (char*) &export_vars.innodb_buffer_pool_pages_misc,   SHOW_LONG},
662
699
  {"buffer_pool_pages_total",
663
700
  (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},
 
701
  {"buffer_pool_read_ahead_rnd",
 
702
  (char*) &export_vars.innodb_buffer_pool_read_ahead_rnd, SHOW_LONG},
 
703
  {"buffer_pool_read_ahead_seq",
 
704
  (char*) &export_vars.innodb_buffer_pool_read_ahead_seq, SHOW_LONG},
668
705
  {"buffer_pool_read_requests",
669
706
  (char*) &export_vars.innodb_buffer_pool_read_requests,  SHOW_LONG},
670
707
  {"buffer_pool_reads",
798
835
DRIZZLE: Note, we didn't change this name to avoid more ifdef forking 
799
836
         in non-Cursor code.
800
837
@return true if session is the replication thread */
801
 
UNIV_INTERN
 
838
extern "C" UNIV_INTERN
802
839
ibool
803
840
thd_is_replication_slave_thread(
804
841
/*============================*/
805
 
  drizzled::Session* ) /*!< in: thread handle (Session*) */
 
842
  void* ) /*!< in: thread handle (Session*) */
806
843
{
807
844
  return false;
808
845
}
872
909
DRIZZLE: Note, we didn't change this name to avoid more ifdef forking 
873
910
         in non-Cursor code.
874
911
@return true if non-transactional tables have been edited */
875
 
UNIV_INTERN
 
912
extern "C" UNIV_INTERN
876
913
ibool
877
914
thd_has_edited_nontrans_tables(
878
915
/*===========================*/
879
 
  drizzled::Session *session)  /*!< in: thread handle (Session*) */
 
916
  void*   session)  /*!< in: thread handle (Session*) */
880
917
{
881
 
  return((ibool)session->transaction.all.hasModifiedNonTransData());
 
918
  return((ibool)((Session *)session)->transaction.all.hasModifiedNonTransData());
882
919
}
883
920
 
884
921
/******************************************************************//**
885
922
Returns true if the thread is executing a SELECT statement.
886
923
@return true if session is executing SELECT */
887
 
UNIV_INTERN
 
924
extern "C" UNIV_INTERN
888
925
ibool
889
926
thd_is_select(
890
927
/*==========*/
891
 
  const drizzled::Session *session)  /*!< in: thread handle (Session*) */
 
928
  const void* session)  /*!< in: thread handle (Session*) */
892
929
{
893
 
  return(session->getSqlCommand() == SQLCOM_SELECT);
 
930
  return(session_sql_command((const Session*) session) == SQLCOM_SELECT);
894
931
}
895
932
 
896
933
/******************************************************************//**
897
934
Returns true if the thread supports XA,
898
935
global value of innodb_supports_xa if session is NULL.
899
936
@return true if session has XA support */
900
 
UNIV_INTERN
 
937
extern "C" UNIV_INTERN
901
938
ibool
902
939
thd_supports_xa(
903
940
/*============*/
904
 
  drizzled::Session* )  /*!< in: thread handle (Session*), or NULL to query
 
941
  void* session)  /*!< in: thread handle (Session*), or NULL to query
905
942
        the global innodb_supports_xa */
906
943
{
907
 
  /* TODO: Add support here for per-session value */
908
 
  return(support_xa);
 
944
  return(SessionVAR((Session*) session, support_xa));
909
945
}
910
946
 
911
947
/******************************************************************//**
912
948
Returns the lock wait timeout for the current connection.
913
949
@return the lock wait timeout, in seconds */
914
 
UNIV_INTERN
 
950
extern "C" UNIV_INTERN
915
951
ulong
916
952
thd_lock_wait_timeout(
917
953
/*==================*/
918
 
  drizzled::Session*)  /*!< in: thread handle (Session*), or NULL to query
 
954
  void* session)  /*!< in: thread handle (Session*), or NULL to query
919
955
      the global innodb_lock_wait_timeout */
920
956
{
921
 
  /* TODO: Add support here for per-session value */
922
957
  /* According to <drizzle/plugin.h>, passing session == NULL
923
958
  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;
 
959
  return(SessionVAR((Session*) session, lock_wait_timeout));
938
960
}
939
961
 
940
962
/********************************************************************//**
949
971
  return *(trx_t**) session->getEngineData(innodb_engine_ptr);
950
972
}
951
973
 
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
974
/********************************************************************//**
977
975
Call this function when mysqld passes control to the client. That is to
978
976
avoid deadlocks on the adaptive hash S-latch possibly held by session. For more
1022
1020
about a possible transaction rollback inside InnoDB caused by a lock wait
1023
1021
timeout or a deadlock.
1024
1022
@return MySQL error code */
1025
 
UNIV_INTERN
 
1023
extern "C" UNIV_INTERN
1026
1024
int
1027
1025
convert_error_code_to_mysql(
1028
1026
/*========================*/
1034
1032
  case DB_SUCCESS:
1035
1033
    return(0);
1036
1034
 
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
1035
  case DB_ERROR:
1053
1036
  default:
1054
1037
    return(-1); /* unspecified error */
1055
1038
 
1056
1039
  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
1040
    return(HA_ERR_FOUND_DUPP_KEY);
1064
1041
 
1065
1042
  case DB_FOREIGN_DUPLICATE_KEY:
1076
1053
    tell it also to MySQL so that MySQL knows to empty the
1077
1054
    cached binlog for this transaction */
1078
1055
 
1079
 
    session->markTransactionForRollback(TRUE);
 
1056
    mark_transaction_to_rollback(session, TRUE);
1080
1057
 
1081
1058
    return(HA_ERR_LOCK_DEADLOCK);
1082
1059
 
1085
1062
    latest SQL statement in a lock wait timeout. Previously, we
1086
1063
    rolled back the whole transaction. */
1087
1064
 
1088
 
    session->markTransactionForRollback((bool)row_rollback_on_timeout);
 
1065
    mark_transaction_to_rollback(session, (bool)row_rollback_on_timeout);
1089
1066
 
1090
1067
    return(HA_ERR_LOCK_WAIT_TIMEOUT);
1091
1068
 
1096
1073
    return(HA_ERR_ROW_IS_REFERENCED);
1097
1074
 
1098
1075
  case DB_CANNOT_ADD_CONSTRAINT:
1099
 
  case DB_CHILD_NO_INDEX:
1100
 
  case DB_PARENT_NO_INDEX:
1101
1076
    return(HA_ERR_CANNOT_ADD_FOREIGN);
1102
1077
 
1103
1078
  case DB_CANNOT_DROP_CONSTRAINT:
1121
1096
 
1122
1097
  case DB_TOO_BIG_RECORD:
1123
1098
    my_error(ER_TOO_BIG_ROWSIZE, MYF(0),
1124
 
             page_get_free_space_of_empty(flags & DICT_TF_COMPACT) / 2);
 
1099
       page_get_free_space_of_empty(flags
 
1100
                  & DICT_TF_COMPACT) / 2);
1125
1101
    return(HA_ERR_TO_BIG_ROW);
1126
1102
 
1127
1103
  case DB_NO_SAVEPOINT:
1132
1108
    tell it also to MySQL so that MySQL knows to empty the
1133
1109
    cached binlog for this transaction */
1134
1110
 
1135
 
    session->markTransactionForRollback(TRUE);
 
1111
    mark_transaction_to_rollback(session, TRUE);
1136
1112
 
1137
1113
    return(HA_ERR_LOCK_TABLE_FULL);
1138
1114
 
1147
1123
    and the actual error code name could very well be different.
1148
1124
    This will require some monitoring, ie. the status
1149
1125
    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 */
 
1126
#ifdef ER_TOO_MANY_CONCURRENT_TRXS
 
1127
    return(ER_TOO_MANY_CONCURRENT_TRXS);
 
1128
#else
1159
1129
    return(HA_ERR_RECORD_FILE_FULL);
1160
 
#endif /* HA_ERR_TOO_MANY_CONCURRENT_TRXS */
 
1130
#endif
1161
1131
  case DB_UNSUPPORTED:
1162
1132
    return(HA_ERR_UNSUPPORTED);
1163
1133
  }
1164
1134
}
1165
1135
 
1166
1136
 
 
1137
 
 
1138
/*************************************************************//**
 
1139
If you want to print a session that is not associated with the current thread,
 
1140
you must call this function before reserving the InnoDB kernel_mutex, to
 
1141
protect Drizzle from setting session->query NULL. If you print a session of the
 
1142
current thread, we know that Drizzle cannot modify sesion->query, and it is
 
1143
not necessary to call this. Call innobase_mysql_end_print_arbitrary_thd()
 
1144
after you release the kernel_mutex.
 
1145
 
 
1146
DRIZZLE: Note, we didn't change this name to avoid more ifdef forking 
 
1147
         in non-Cursor code.
 
1148
 */
 
1149
extern "C" UNIV_INTERN
 
1150
void
 
1151
innobase_mysql_prepare_print_arbitrary_thd(void)
 
1152
/*============================================*/
 
1153
{
 
1154
  ut_ad(!mutex_own(&kernel_mutex));
 
1155
  pthread_mutex_lock(&LOCK_thread_count);
 
1156
}
 
1157
 
 
1158
/*************************************************************//**
 
1159
Releases the mutex reserved by innobase_mysql_prepare_print_arbitrary_thd().
 
1160
In the InnoDB latching order, the mutex sits right above the
 
1161
kernel_mutex.  In debug builds, we assert that the kernel_mutex is
 
1162
released before this function is invoked. 
 
1163
 
 
1164
DRIZZLE: Note, we didn't change this name to avoid more ifdef forking 
 
1165
         in non-Cursor code.
 
1166
*/
 
1167
extern "C" UNIV_INTERN
 
1168
void
 
1169
innobase_mysql_end_print_arbitrary_thd(void)
 
1170
/*========================================*/
 
1171
{
 
1172
  ut_ad(!mutex_own(&kernel_mutex));
 
1173
  pthread_mutex_unlock(&LOCK_thread_count);
 
1174
}
 
1175
 
1167
1176
/*************************************************************//**
1168
1177
Prints info of a Session object (== user session thread) to the given file. */
1169
 
UNIV_INTERN
 
1178
extern "C" UNIV_INTERN
1170
1179
void
1171
1180
innobase_mysql_print_thd(
1172
1181
/*=====================*/
1173
1182
  FILE* f,    /*!< in: output stream */
1174
 
  drizzled::Session *in_session,  /*!< in: pointer to a Drizzle Session object */
 
1183
  void * in_session,  /*!< in: pointer to a Drizzle Session object */
1175
1184
  uint  )   /*!< in: max query length to print, or 0 to
1176
1185
           use the default max length */
1177
1186
{
1178
 
  drizzled::identifier::User::const_shared_ptr user_identifier(in_session->user());
1179
 
 
 
1187
  Session *session= reinterpret_cast<Session *>(in_session);
1180
1188
  fprintf(f,
1181
1189
          "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());
 
1190
          static_cast<uint64_t>(session->getSessionId()),
 
1191
          static_cast<uint64_t>(session->getQueryId()),
 
1192
          glob_hostname,
 
1193
          session->getSecurityContext().getIp().c_str(),
 
1194
          session->getSecurityContext().getUser().c_str()
 
1195
  );
 
1196
  fprintf(f,
 
1197
          "\n%s", session->getQueryString().c_str()
 
1198
  );
1189
1199
  putc('\n', f);
1190
1200
}
1191
1201
 
1192
1202
/******************************************************************//**
1193
1203
Get the variable length bounds of the given character set. */
1194
 
UNIV_INTERN
 
1204
extern "C" UNIV_INTERN
1195
1205
void
1196
1206
innobase_get_cset_width(
1197
1207
/*====================*/
1208
1218
  if (cs) {
1209
1219
    *mbminlen = cs->mbminlen;
1210
1220
    *mbmaxlen = cs->mbmaxlen;
1211
 
    ut_ad(*mbminlen < DATA_MBMAX);
1212
 
    ut_ad(*mbmaxlen < DATA_MBMAX);
1213
1221
  } else {
1214
1222
    ut_a(cset == 0);
1215
1223
    *mbminlen = *mbmaxlen = 0;
1218
1226
 
1219
1227
/******************************************************************//**
1220
1228
Converts an identifier to a table name. */
1221
 
UNIV_INTERN
 
1229
extern "C" UNIV_INTERN
1222
1230
void
1223
1231
innobase_convert_from_table_id(
1224
1232
/*===========================*/
1232
1240
 
1233
1241
/******************************************************************//**
1234
1242
Converts an identifier to UTF-8. */
1235
 
UNIV_INTERN
 
1243
extern "C" UNIV_INTERN
1236
1244
void
1237
1245
innobase_convert_from_id(
1238
1246
/*=====================*/
1247
1255
/******************************************************************//**
1248
1256
Compares NUL-terminated UTF-8 strings case insensitively.
1249
1257
@return 0 if a=b, <0 if a<b, >1 if a>b */
1250
 
UNIV_INTERN
 
1258
extern "C" UNIV_INTERN
1251
1259
int
1252
1260
innobase_strcasecmp(
1253
1261
/*================*/
1259
1267
 
1260
1268
/******************************************************************//**
1261
1269
Makes all characters in a NUL-terminated UTF-8 string lower case. */
1262
 
UNIV_INTERN
 
1270
extern "C" UNIV_INTERN
1263
1271
void
1264
1272
innobase_casedn_str(
1265
1273
/*================*/
1268
1276
  my_casedn_str(system_charset_info, a);
1269
1277
}
1270
1278
 
1271
 
UNIV_INTERN
 
1279
/**********************************************************************//**
 
1280
Determines the connection character set.
 
1281
@return connection character set */
 
1282
extern "C" UNIV_INTERN
 
1283
const void*
 
1284
innobase_get_charset(
 
1285
/*=================*/
 
1286
  void* mysql_session)  /*!< in: MySQL thread handle */
 
1287
{
 
1288
  return session_charset(static_cast<Session*>(mysql_session));
 
1289
}
 
1290
 
 
1291
extern "C" UNIV_INTERN
1272
1292
bool
1273
1293
innobase_isspace(
1274
1294
  const void *cs,
1277
1297
  return my_isspace(static_cast<const CHARSET_INFO *>(cs), char_to_test);
1278
1298
}
1279
1299
 
 
1300
UNIV_INTERN
 
1301
int
 
1302
innobase_fast_mutex_init(
 
1303
        os_fast_mutex_t*        fast_mutex)
 
1304
{
 
1305
  return pthread_mutex_init(fast_mutex, MY_MUTEX_INIT_FAST);
 
1306
}
 
1307
 
1280
1308
#if defined (__WIN__) && defined (MYSQL_DYNAMIC_PLUGIN)
1281
1309
/*******************************************************************//**
1282
1310
Map an OS error to an errno value. The OS error number is stored in
1283
1311
_doserrno and the mapped value is stored in errno) */
 
1312
extern "C"
1284
1313
void __cdecl
1285
1314
_dosmaperr(
1286
1315
  unsigned long); /*!< in: OS error value */
1288
1317
/*********************************************************************//**
1289
1318
Creates a temporary file.
1290
1319
@return temporary file descriptor, or < 0 on error */
1291
 
UNIV_INTERN
 
1320
extern "C" UNIV_INTERN
1292
1321
int
1293
1322
innobase_mysql_tmpfile(void)
1294
1323
/*========================*/
1368
1397
/*********************************************************************//**
1369
1398
Creates a temporary file.
1370
1399
@return temporary file descriptor, or < 0 on error */
1371
 
UNIV_INTERN
 
1400
extern "C" UNIV_INTERN
1372
1401
int
1373
1402
innobase_mysql_tmpfile(void)
1374
1403
/*========================*/
1375
1404
{
1376
1405
  int fd2 = -1;
1377
 
  int fd = ::drizzled::tmpfile("ib");
 
1406
  int fd = mysql_tmpfile("ib");
1378
1407
  if (fd >= 0) {
1379
1408
    /* Copy the file descriptor, so that the additional resources
1380
1409
    allocated by create_temp_file() can be freed by invoking
1407
1436
number of bytes that were written to "buf" is returned (including the
1408
1437
terminating NUL).
1409
1438
@return number of bytes that were written */
1410
 
UNIV_INTERN
 
1439
extern "C" UNIV_INTERN
1411
1440
ulint
1412
1441
innobase_raw_format(
1413
1442
/*================*/
1527
1556
/*********************************************************************//**
1528
1557
Allocates an InnoDB transaction for a MySQL Cursor object.
1529
1558
@return InnoDB transaction handle */
1530
 
UNIV_INTERN
 
1559
extern "C" UNIV_INTERN
1531
1560
trx_t*
1532
1561
innobase_trx_allocate(
1533
1562
/*==================*/
1541
1570
  trx = trx_allocate_for_mysql();
1542
1571
 
1543
1572
  trx->mysql_thd = session;
 
1573
  trx->mysql_query_str = session->query.c_str();
1544
1574
 
1545
1575
  innobase_trx_init(session, trx);
1546
1576
 
1579
1609
Construct ha_innobase Cursor. */
1580
1610
UNIV_INTERN
1581
1611
ha_innobase::ha_innobase(plugin::StorageEngine &engine_arg,
1582
 
                         Table &table_arg)
 
1612
                         TableShare &table_arg)
1583
1613
  :Cursor(engine_arg, table_arg),
1584
1614
  primary_key(0), /* needs initialization because index_flags() may be called 
1585
1615
                     before this is set to the real value. It's ok to have any 
1631
1661
  ulint   buflen, /*!< in: length of buf, in bytes */
1632
1662
  const char* id, /*!< in: identifier to convert */
1633
1663
  ulint   idlen,  /*!< in: length of id, in bytes */
1634
 
  drizzled::Session *session,/*!< in: MySQL connection thread, or NULL */
 
1664
  void*   session,/*!< in: MySQL connection thread, or NULL */
1635
1665
  ibool   file_id)/*!< in: TRUE=id is a table or database name;
1636
1666
        FALSE=id is an UTF-8 string */
1637
1667
{
1638
1668
  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]);
 
1669
  char nz2[NAME_LEN + 1 + sizeof srv_mysql50_table_name_prefix];
1641
1670
 
1642
1671
  const char* s = id;
1643
1672
  int   q;
1654
1683
    memcpy(nz, id, idlen);
1655
1684
    nz[idlen] = 0;
1656
1685
 
1657
 
    s = nz2.get();
1658
 
    idlen = identifier::Table::filename_to_tablename(nz, nz2.get(), nz2_size);
 
1686
    s = nz2;
 
1687
    idlen = TableIdentifier::filename_to_tablename(nz, nz2, sizeof nz2);
1659
1688
  }
1660
1689
 
1661
1690
  /* See if the identifier needs to be quoted. */
1709
1738
Convert a table or index name to the MySQL system_charset_info (UTF-8)
1710
1739
and quote it if needed.
1711
1740
@return pointer to the end of buf */
1712
 
UNIV_INTERN
 
1741
extern "C" UNIV_INTERN
1713
1742
char*
1714
1743
innobase_convert_name(
1715
1744
/*==================*/
1717
1746
  ulint   buflen, /*!< in: length of buf, in bytes */
1718
1747
  const char* id, /*!< in: identifier to convert */
1719
1748
  ulint   idlen,  /*!< in: length of id, in bytes */
1720
 
  drizzled::Session *session,/*!< in: MySQL connection thread, or NULL */
 
1749
  void*   session,/*!< in: MySQL connection thread, or NULL */
1721
1750
  ibool   table_id)/*!< in: TRUE=id is a table or database name;
1722
1751
        FALSE=id is an index name */
1723
1752
{
1765
1794
/**********************************************************************//**
1766
1795
Determines if the currently running transaction has been interrupted.
1767
1796
@return TRUE if interrupted */
1768
 
UNIV_INTERN
 
1797
extern "C" UNIV_INTERN
1769
1798
ibool
1770
1799
trx_is_interrupted(
1771
1800
/*===============*/
1772
1801
  trx_t*  trx)  /*!< in: transaction */
1773
1802
{
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);
 
1803
  return(trx && trx->mysql_thd && session_killed((Session*) trx->mysql_thd));
1788
1804
}
1789
1805
 
1790
1806
/**************************************************************//**
1800
1816
  prebuilt->read_just_key = 0;
1801
1817
}
1802
1818
 
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
1819
/*********************************************************************//**
2008
1820
Opens an InnoDB database.
2009
1821
@return 0 on success, error code on failure */
2013
1825
/*==========*/
2014
1826
  module::Context &context) /*!< in: Drizzle Plugin Context */
2015
1827
{
 
1828
  static char current_dir[3];   /*!< Set if using current lib */
2016
1829
  int   err;
2017
1830
  bool    ret;
 
1831
  char    *default_path;
2018
1832
  uint    format_id;
2019
1833
  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
1834
 
2066
1835
  innodb_engine_ptr= actuall_engine_ptr= new InnobaseEngine(innobase_engine_name);
2067
1836
 
2069
1838
 
2070
1839
#ifdef UNIV_DEBUG
2071
1840
  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(),
 
1841
  char      test_tablename[sizeof test_filename
 
1842
    + sizeof srv_mysql50_table_name_prefix];
 
1843
  if ((sizeof test_tablename) - 1
 
1844
      != filename_to_tablename(test_filename, test_tablename,
 
1845
                               sizeof test_tablename)
 
1846
      || strncmp(test_tablename,
 
1847
                 srv_mysql50_table_name_prefix,
 
1848
                 sizeof srv_mysql50_table_name_prefix)
 
1849
      || strcmp(test_tablename
 
1850
                + sizeof srv_mysql50_table_name_prefix,
2083
1851
                test_filename)) {
2084
 
    errmsg_printf(error::ERROR, "tablename encoding has been changed");
 
1852
    errmsg_printf(ERRMSG_LVL_ERROR, "tablename encoding has been changed");
2085
1853
    goto error;
2086
1854
  }
2087
1855
#endif /* UNIV_DEBUG */
2088
1856
 
 
1857
  /* Check that values don't overflow on 32-bit systems. */
 
1858
  if (sizeof(ulint) == 4) {
 
1859
    if (innobase_buffer_pool_size > UINT32_MAX) {
 
1860
      errmsg_printf(ERRMSG_LVL_ERROR, 
 
1861
                    "innobase_buffer_pool_size can't be over 4GB"
 
1862
                    " on 32-bit systems");
 
1863
 
 
1864
      goto error;
 
1865
    }
 
1866
 
 
1867
    if (innobase_log_file_size > UINT32_MAX) {
 
1868
      errmsg_printf(ERRMSG_LVL_ERROR, 
 
1869
                    "innobase_log_file_size can't be over 4GB"
 
1870
                    " on 32-bit systems");
 
1871
 
 
1872
      goto error;
 
1873
    }
 
1874
  }
 
1875
 
2089
1876
  os_innodb_umask = (ulint)internal::my_umask;
2090
1877
 
 
1878
  /* First calculate the default path for innodb_data_home_dir etc.,
 
1879
    in case the user has not given any value.
 
1880
 
 
1881
    Note that when using the embedded server, the datadirectory is not
 
1882
    necessarily the current directory of this program. */
 
1883
 
 
1884
  /* It's better to use current lib, to keep paths short */
 
1885
  current_dir[0] = FN_CURLIB;
 
1886
  current_dir[1] = FN_LIBCHAR;
 
1887
  current_dir[2] = 0;
 
1888
  default_path = current_dir;
 
1889
 
 
1890
  ut_a(default_path);
 
1891
 
 
1892
  srv_set_thread_priorities = TRUE;
 
1893
  srv_query_thread_priority = QUERY_PRIOR;
2091
1894
 
2092
1895
  /* Set InnoDB initialization parameters according to the values
2093
1896
    read from MySQL .cnf file */
2096
1899
 
2097
1900
  /* The default dir for data files is the datadir of MySQL */
2098
1901
 
2099
 
  srv_data_home = (char *)innobase_data_home_dir.c_str();
 
1902
  srv_data_home = (innobase_data_home_dir ? innobase_data_home_dir :
 
1903
                   default_path);
2100
1904
 
2101
1905
  /* Set default InnoDB data file size to 10 MB and let it be
2102
1906
    auto-extending. Thus users can use InnoDB in >= 4.0 without having
2103
1907
    to specify any startup options. */
2104
1908
 
2105
 
  if (innobase_data_file_path.empty()) 
2106
 
  {
2107
 
    innobase_data_file_path= std::string("ibdata1:10M:autoextend");
 
1909
  if (!innobase_data_file_path) {
 
1910
    innobase_data_file_path = (char*) "ibdata1:10M:autoextend";
2108
1911
  }
2109
1912
 
2110
1913
  /* Since InnoDB edits the argument in the next call, we make another
2111
1914
    copy of it: */
2112
1915
 
2113
 
  internal_innobase_data_file_path = strdup(innobase_data_file_path.c_str());
 
1916
  internal_innobase_data_file_path = strdup(innobase_data_file_path);
2114
1917
 
2115
1918
  ret = (bool) srv_parse_data_file_paths_and_sizes(
2116
1919
                                                   internal_innobase_data_file_path);
2117
1920
  if (ret == FALSE) {
2118
 
    errmsg_printf(error::ERROR, "InnoDB: syntax error in innodb_data_file_path");
2119
 
 
 
1921
    errmsg_printf(ERRMSG_LVL_ERROR, 
 
1922
                  "InnoDB: syntax error in innodb_data_file_path");
2120
1923
mem_free_and_error:
2121
1924
    srv_free_paths_and_sizes();
2122
1925
    if (internal_innobase_data_file_path)
2128
1931
 
2129
1932
  /* The default dir for log files is the datadir of MySQL */
2130
1933
 
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
 
  }
 
1934
  if (!innobase_log_group_home_dir) {
 
1935
    innobase_log_group_home_dir = default_path;
 
1936
  }
 
1937
 
 
1938
#ifdef UNIV_LOG_ARCHIVE
 
1939
  /* Since innodb_log_arch_dir has no relevance under MySQL,
 
1940
    starting from 4.0.6 we always set it the same as
 
1941
innodb_log_group_home_dir: */
 
1942
 
 
1943
  innobase_log_arch_dir = innobase_log_group_home_dir;
 
1944
 
 
1945
  srv_arch_dir = innobase_log_arch_dir;
 
1946
#endif /* UNIG_LOG_ARCHIVE */
2139
1947
 
2140
1948
  ret = (bool)
2141
 
    srv_parse_log_group_home_dirs((char *)innobase_log_group_home_dir.c_str());
 
1949
    srv_parse_log_group_home_dirs(innobase_log_group_home_dir);
2142
1950
 
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"));
 
1951
  if (ret == FALSE || innobase_mirrored_log_groups != 1) {
 
1952
    errmsg_printf(ERRMSG_LVL_ERROR, "syntax error in innodb_log_group_home_dir, or a "
 
1953
                  "wrong number of mirrored log groups");
2146
1954
 
2147
1955
    goto mem_free_and_error;
2148
1956
  }
2149
1957
 
2150
 
 
2151
1958
  /* Validate the file format by animal name */
2152
 
  if (vm.count("file-format"))
2153
 
  {
 
1959
  if (innobase_file_format_name != NULL) {
 
1960
 
2154
1961
    format_id = innobase_file_format_name_lookup(
2155
 
                                                 vm["file-format"].as<string>().c_str());
 
1962
                                                 innobase_file_format_name);
2156
1963
 
2157
1964
    if (format_id > DICT_TF_FORMAT_MAX) {
2158
1965
 
2159
 
      errmsg_printf(error::ERROR, "InnoDB: wrong innodb_file_format.");
 
1966
      errmsg_printf(ERRMSG_LVL_ERROR, "InnoDB: wrong innodb_file_format.");
2160
1967
 
2161
1968
      goto mem_free_and_error;
2162
1969
    }
2163
1970
  } else {
2164
 
    /* Set it to the default file format id.*/
 
1971
    /* Set it to the default file format id. Though this
 
1972
      should never happen. */
2165
1973
    format_id = 0;
2166
1974
  }
2167
1975
 
2168
1976
  srv_file_format = format_id;
2169
1977
 
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
 
  {
 
1978
  /* Given the type of innobase_file_format_name we have little
 
1979
    choice but to cast away the constness from the returned name.
 
1980
    innobase_file_format_name is used in the MySQL set variable
 
1981
    interface and so can't be const. */
 
1982
 
 
1983
  innobase_file_format_name = 
 
1984
    (char*) trx_sys_file_format_id_to_name(format_id);
 
1985
 
 
1986
  /* Process innobase_file_format_check variable */
 
1987
  ut_a(innobase_file_format_check != NULL);
 
1988
 
 
1989
  /* As a side effect it will set srv_check_file_format_at_startup
 
1990
    on valid input. First we check for "on"/"off". */
 
1991
  if (!innobase_file_format_check_on_off(innobase_file_format_check)) {
 
1992
 
 
1993
    /* Did the user specify a format name that we support ?
 
1994
      As a side effect it will update the variable
 
1995
      srv_check_file_format_at_startup */
 
1996
    if (!innobase_file_format_check_validate(
 
1997
                                             innobase_file_format_check)) {
 
1998
 
 
1999
      errmsg_printf(ERRMSG_LVL_ERROR, "InnoDB: invalid "
 
2000
                    "innodb_file_format_check value: "
 
2001
                    "should be either 'on' or 'off' or "
 
2002
                    "any value up to %s or its "
 
2003
                    "equivalent numeric id",
 
2004
                    trx_sys_file_format_id_to_name(
 
2005
                                                   DICT_TF_FORMAT_MAX));
 
2006
 
 
2007
      goto mem_free_and_error;
 
2008
    }
 
2009
  }
 
2010
 
 
2011
  if (innobase_change_buffering) {
2196
2012
    ulint use;
2197
2013
 
2198
2014
    for (use = 0;
2199
2015
         use < UT_ARR_SIZE(innobase_change_buffering_values);
2200
2016
         use++) {
2201
2017
      if (!innobase_strcasecmp(
2202
 
                               innobase_change_buffering.c_str(),
 
2018
                               innobase_change_buffering,
2203
2019
                               innobase_change_buffering_values[use])) {
2204
 
        ibuf_use = static_cast<ibuf_use_t>(use);
 
2020
        ibuf_use = (ibuf_use_t) use;
2205
2021
        goto innobase_change_buffering_inited_ok;
2206
2022
      }
2207
2023
    }
2208
2024
 
2209
 
    errmsg_printf(error::ERROR, "InnoDB: invalid value innodb_change_buffering=%s",
2210
 
                  vm["change-buffering"].as<string>().c_str());
 
2025
    errmsg_printf(ERRMSG_LVL_ERROR,
 
2026
                  "InnoDB: invalid value "
 
2027
                  "innodb_file_format_check=%s",
 
2028
                  innobase_change_buffering);
2211
2029
    goto mem_free_and_error;
2212
2030
  }
2213
2031
 
2214
2032
innobase_change_buffering_inited_ok:
2215
2033
  ut_a((ulint) ibuf_use < UT_ARR_SIZE(innobase_change_buffering_values));
2216
 
  innobase_change_buffering = innobase_change_buffering_values[ibuf_use];
 
2034
  innobase_change_buffering = (char*)
 
2035
    innobase_change_buffering_values[ibuf_use];
2217
2036
 
2218
2037
  /* --------------------------------------------------*/
2219
2038
 
2220
 
  if (vm.count("flush-method") != 0)
2221
 
  {
2222
 
    srv_file_flush_method_str = (char *)vm["flush-method"].as<string>().c_str();
2223
 
  }
 
2039
  srv_file_flush_method_str = innobase_unix_file_flush_method;
2224
2040
 
2225
2041
  srv_n_log_groups = (ulint) innobase_mirrored_log_groups;
2226
2042
  srv_n_log_files = (ulint) innobase_log_files_in_group;
2227
2043
  srv_log_file_size = (ulint) innobase_log_file_size;
2228
2044
 
 
2045
#ifdef UNIV_LOG_ARCHIVE
 
2046
  srv_log_archive_on = (ulint) innobase_log_archive;
 
2047
#endif /* UNIV_LOG_ARCHIVE */
2229
2048
  srv_log_buffer_size = (ulint) innobase_log_buffer_size;
2230
2049
 
2231
2050
  srv_buf_pool_size = (ulint) innobase_buffer_pool_size;
2232
 
  srv_buf_pool_instances = (ulint) innobase_buffer_pool_instances;
2233
2051
 
2234
2052
  srv_mem_pool_size = (ulint) innobase_additional_mem_pool_size;
2235
2053
 
 
2054
  srv_n_file_io_threads = (ulint) innobase_file_io_threads;
2236
2055
  srv_n_read_io_threads = (ulint) innobase_read_io_threads;
2237
2056
  srv_n_write_io_threads = (ulint) innobase_write_io_threads;
2238
2057
 
2260
2079
 
2261
2080
  data_mysql_default_charset_coll = (ulint)default_charset_info->number;
2262
2081
 
 
2082
 
 
2083
  innobase_commit_concurrency_init_default();
 
2084
 
2263
2085
  /* Since we in this module access directly the fields of a trx
2264
2086
    struct, and due to different headers and flags it might happen that
2265
2087
    mutex_t has a different size in this module and in InnoDB
2268
2090
 
2269
2091
  err = innobase_start_or_create_for_mysql();
2270
2092
 
2271
 
  if (err != DB_SUCCESS)
2272
 
  {
2273
 
    goto mem_free_and_error;
2274
 
  }
2275
 
 
2276
 
  err = dict_create_sys_replication_log();
2277
 
 
2278
2093
  if (err != DB_SUCCESS) {
2279
2094
    goto mem_free_and_error;
2280
2095
  }
2281
2096
 
2282
 
 
2283
 
  innobase_old_blocks_pct = buf_LRU_old_ratio_update(innobase_old_blocks_pct.get(),
2284
 
                                                     TRUE);
2285
 
 
2286
2097
  innobase_open_tables = hash_create(200);
 
2098
  pthread_mutex_init(&innobase_share_mutex, MY_MUTEX_INIT_FAST);
 
2099
  pthread_mutex_init(&prepare_commit_mutex, MY_MUTEX_INIT_FAST);
 
2100
  pthread_mutex_init(&commit_threads_m, MY_MUTEX_INIT_FAST);
 
2101
  pthread_mutex_init(&commit_cond_m, MY_MUTEX_INIT_FAST);
 
2102
  pthread_cond_init(&commit_cond, NULL);
2287
2103
  innodb_inited= 1;
2288
2104
 
2289
2105
  actuall_engine_ptr->dropTemporarySchema();
2290
2106
 
2291
 
  context.add(new InnodbStatusTool);
 
2107
  status_table_function_ptr= new InnodbStatusTool;
2292
2108
 
2293
2109
  context.add(innodb_engine_ptr);
2294
2110
 
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());
 
2111
  context.add(status_table_function_ptr);
 
2112
 
 
2113
  cmp_tool= new(std::nothrow)CmpTool(false);
 
2114
  context.add(cmp_tool);
 
2115
 
 
2116
  cmp_reset_tool= new(std::nothrow)CmpTool(true);
 
2117
  context.add(cmp_reset_tool);
 
2118
 
 
2119
  cmp_mem_tool= new(std::nothrow)CmpmemTool(false);
 
2120
  context.add(cmp_mem_tool);
 
2121
 
 
2122
  cmp_mem_reset_tool= new(std::nothrow)CmpmemTool(true);
 
2123
  context.add(cmp_mem_reset_tool);
 
2124
 
 
2125
  innodb_trx_tool= new(std::nothrow)InnodbTrxTool("INNODB_TRX");
 
2126
  context.add(innodb_trx_tool);
 
2127
 
 
2128
  innodb_locks_tool= new(std::nothrow)InnodbTrxTool("INNODB_LOCKS");
 
2129
  context.add(innodb_locks_tool);
 
2130
 
 
2131
  innodb_lock_waits_tool= new(std::nothrow)InnodbTrxTool("INNODB_LOCK_WAITS");
 
2132
  context.add(innodb_lock_waits_tool);
2322
2133
 
2323
2134
  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));
 
2135
 
2414
2136
  /* 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);
 
2137
  innobase_file_format_check = (char*) trx_sys_file_format_max_get();
2417
2138
 
2418
2139
  return(FALSE);
2419
 
 
2420
2140
error:
2421
2141
  return(TRUE);
2422
2142
}
2513
2233
    trx_search_latch_release_if_reserved(trx);
2514
2234
  }
2515
2235
 
2516
 
  if (all)
2517
 
  {
 
2236
  if (all
 
2237
    || (!session_test_options(session, OPTION_NOT_AUTOCOMMIT | OPTION_BEGIN))) {
 
2238
 
2518
2239
    /* We were instructed to commit the whole transaction, or
2519
2240
    this is an SQL statement end and autocommit is on */
2520
2241
 
2521
2242
    /* We need current binlog position for ibbackup to work.
2522
2243
    Note, the position is current because of
2523
2244
    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
 
 
 
2245
retry:
 
2246
    if (innobase_commit_concurrency > 0) {
 
2247
      pthread_mutex_lock(&commit_cond_m);
 
2248
      commit_threads++;
 
2249
 
 
2250
      if (commit_threads > innobase_commit_concurrency) {
2535
2251
        commit_threads--;
2536
 
        commit_cond.wait(scopedLock);
2537
 
      } while (1);
 
2252
        pthread_cond_wait(&commit_cond,
 
2253
          &commit_cond_m);
 
2254
        pthread_mutex_unlock(&commit_cond_m);
 
2255
        goto retry;
 
2256
      }
 
2257
      else {
 
2258
        pthread_mutex_unlock(&commit_cond_m);
 
2259
      }
2538
2260
    }
2539
2261
 
2540
 
    trx->mysql_log_file_name = NULL;
 
2262
                /* Store transaction point for binlog
 
2263
    Later logic tests that this is set to _something_. We need
 
2264
    that logic to fire, even though we do not have a real name. */
 
2265
    trx->mysql_log_file_name = "UNUSED";
2541
2266
    trx->mysql_log_offset = 0;
2542
2267
 
2543
2268
    /* Don't do write + flush right now. For group commit
2547
2272
    innobase_commit_low(trx);
2548
2273
    trx->flush_log_later = FALSE;
2549
2274
 
2550
 
    if (commit_concurrency)
2551
 
    {
2552
 
      boost::mutex::scoped_lock scopedLock(commit_cond_m);
 
2275
    if (innobase_commit_concurrency > 0) {
 
2276
      pthread_mutex_lock(&commit_cond_m);
2553
2277
      commit_threads--;
2554
 
      commit_cond.notify_one();
 
2278
      pthread_cond_signal(&commit_cond);
 
2279
      pthread_mutex_unlock(&commit_cond_m);
2555
2280
    }
2556
2281
 
2557
2282
    /* Now do a write + flush of logs. */
2571
2296
    SQL statement */
2572
2297
 
2573
2298
    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
2299
  }
2583
2300
 
2584
2301
  trx->n_autoinc_rows = 0; /* Reset the number AUTO-INC rows required */
2593
2310
  threads: */
2594
2311
  srv_active_wake_master_thread();
2595
2312
 
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
2313
  return(0);
2605
2314
}
2606
2315
 
2628
2337
 
2629
2338
  innobase_release_stat_resources(trx);
2630
2339
 
2631
 
  trx->n_autoinc_rows = 0;
2632
 
 
2633
2340
  /* If we had reserved the auto-inc lock for some table (if
2634
2341
  we come here to roll back the latest SQL statement) we
2635
2342
  release it now before a possibly lengthy rollback */
2636
2343
 
2637
2344
  row_unlock_table_autoinc_for_mysql(trx);
2638
2345
 
2639
 
  if (all)
2640
 
  {
 
2346
  if (all
 
2347
    || !session_test_options(session, OPTION_NOT_AUTOCOMMIT | OPTION_BEGIN)) {
 
2348
 
2641
2349
    error = trx_rollback_for_mysql(trx);
2642
2350
  } else {
2643
2351
    error = trx_rollback_last_sql_stat_for_mysql(trx);
2644
2352
  }
2645
2353
 
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
2354
  return(convert_error_code_to_mysql(error, 0, NULL));
2655
2355
}
2656
2356
 
2787
2487
 
2788
2488
  ut_a(trx);
2789
2489
 
2790
 
  assert(session->getKilled() != Session::NOT_KILLED ||
 
2490
  assert(session->killed != Session::NOT_KILLED ||
2791
2491
         trx->conc_state == TRX_NOT_STARTED);
2792
2492
 
2793
2493
  /* Warn if rolling back some things... */
2794
 
  if (session->getKilled() != Session::NOT_KILLED &&
 
2494
  if (session->killed != Session::NOT_KILLED &&
2795
2495
      trx->conc_state != TRX_NOT_STARTED &&
2796
 
      trx->undo_no > 0 &&
 
2496
      trx->undo_no.low > 0 &&
2797
2497
      global_system_variables.log_warnings)
2798
2498
  {
2799
 
      errmsg_printf(error::WARN,
 
2499
      errmsg_printf(ERRMSG_LVL_WARN, 
2800
2500
      "Drizzle is closing a connection during a KILL operation\n"
2801
 
      "that has an active InnoDB transaction.  %llu row modifications will "
 
2501
      "that has an active InnoDB transaction.  %lu row modifications will "
2802
2502
      "roll back.\n",
2803
 
      (ullint) trx->undo_no);
 
2503
      (ulong) trx->undo_no.low);
2804
2504
  }
2805
2505
 
2806
2506
  innobase_rollback_trx(trx);
2817
2517
*****************************************************************************/
2818
2518
 
2819
2519
/****************************************************************//**
 
2520
Get the record format from the data dictionary.
 
2521
@return one of ROW_TYPE_REDUNDANT, ROW_TYPE_COMPACT,
 
2522
ROW_TYPE_COMPRESSED, ROW_TYPE_DYNAMIC */
 
2523
UNIV_INTERN
 
2524
enum row_type
 
2525
ha_innobase::get_row_type() const
 
2526
/*=============================*/
 
2527
{
 
2528
  if (prebuilt && prebuilt->table) {
 
2529
    const ulint flags = prebuilt->table->flags;
 
2530
 
 
2531
    if (UNIV_UNLIKELY(!flags)) {
 
2532
      return(ROW_TYPE_REDUNDANT);
 
2533
    }
 
2534
 
 
2535
    ut_ad(flags & DICT_TF_COMPACT);
 
2536
 
 
2537
    switch (flags & DICT_TF_FORMAT_MASK) {
 
2538
    case DICT_TF_FORMAT_51 << DICT_TF_FORMAT_SHIFT:
 
2539
      return(ROW_TYPE_COMPACT);
 
2540
    case DICT_TF_FORMAT_ZIP << DICT_TF_FORMAT_SHIFT:
 
2541
      if (flags & DICT_TF_ZSSIZE_MASK) {
 
2542
        return(ROW_TYPE_COMPRESSED);
 
2543
      } else {
 
2544
        return(ROW_TYPE_DYNAMIC);
 
2545
      }
 
2546
#if DICT_TF_FORMAT_ZIP != DICT_TF_FORMAT_MAX
 
2547
# error "DICT_TF_FORMAT_ZIP != DICT_TF_FORMAT_MAX"
 
2548
#endif
 
2549
    }
 
2550
  }
 
2551
  ut_ad(0);
 
2552
  return(ROW_TYPE_NOT_USED);
 
2553
}
 
2554
 
 
2555
 
 
2556
/****************************************************************//**
2820
2557
Returns the index type. */
2821
2558
UNIV_INTERN
2822
2559
const char*
2876
2613
  return(true);
2877
2614
}
2878
2615
 
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]);
 
2616
/*****************************************************************//**
 
2617
Normalizes a table name string. A normalized name consists of the
 
2618
database name catenated to '/' and table name. An example:
 
2619
test/mytable. On Windows normalization puts both the database name and the
 
2620
table name always to lower case. */
 
2621
static
 
2622
void
 
2623
normalize_table_name(
 
2624
/*=================*/
 
2625
  char*   norm_name,  /*!< out: normalized name as a
 
2626
          null-terminated string */
 
2627
  const char* name)   /*!< in: table name string */
 
2628
{
 
2629
  const char* name_ptr;
 
2630
  const char* db_ptr;
 
2631
  const char* ptr;
 
2632
 
 
2633
  /* Scan name from the end */
 
2634
 
 
2635
  ptr = strchr(name, '\0')-1;
 
2636
 
 
2637
  while (ptr >= name && *ptr != '\\' && *ptr != '/') {
 
2638
    ptr--;
 
2639
  }
 
2640
 
 
2641
  name_ptr = ptr + 1;
 
2642
 
 
2643
  assert(ptr > name);
 
2644
 
 
2645
  ptr--;
 
2646
 
 
2647
  while (ptr >= name && *ptr != '\\' && *ptr != '/') {
 
2648
    ptr--;
 
2649
  }
 
2650
 
 
2651
  db_ptr = ptr + 1;
 
2652
 
 
2653
  memcpy(norm_name, db_ptr, strlen(name) + 1 - (db_ptr - name));
 
2654
 
 
2655
  norm_name[name_ptr - db_ptr - 1] = '/';
 
2656
 
 
2657
#ifdef __WIN__
 
2658
  innobase_casedn_str(norm_name);
 
2659
#endif
3127
2660
}
3128
2661
 
3129
2662
/********************************************************************//**
3130
2663
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. */
 
2664
ha_innobase::open(). Therefore there's no need for a covering lock.
 
2665
@return DB_SUCCESS or error code */
3132
2666
UNIV_INTERN
3133
 
void
 
2667
ulint
3134
2668
ha_innobase::innobase_initialize_autoinc()
3135
2669
/*======================================*/
3136
2670
{
 
2671
  dict_index_t* index;
3137
2672
  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
 
 
 
2673
  const char* col_name;
 
2674
  ulint   error;
 
2675
 
 
2676
  col_name = table->found_next_number_field->field_name;
 
2677
  index = innobase_get_index(table->getShare()->next_number_index);
 
2678
 
 
2679
  /* Execute SELECT MAX(col_name) FROM TABLE; */
 
2680
  error = row_search_max_autoinc(index, col_name, &auto_inc);
 
2681
 
 
2682
  switch (error) {
 
2683
  case DB_SUCCESS:
 
2684
 
 
2685
    /* At the this stage we don't know the increment
 
2686
    or the offset, so use default inrement of 1. */
 
2687
    ++auto_inc;
 
2688
    break;
 
2689
 
 
2690
  case DB_RECORD_NOT_FOUND:
3148
2691
    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
 
    }
 
2692
    fprintf(stderr, "  InnoDB: MySQL and InnoDB data "
 
2693
      "dictionaries are out of sync.\n"
 
2694
      "InnoDB: Unable to find the AUTOINC column %s in the "
 
2695
      "InnoDB table %s.\n"
 
2696
      "InnoDB: We set the next AUTOINC column value to the "
 
2697
      "maximum possible value,\n"
 
2698
      "InnoDB: in effect disabling the AUTOINC next value "
 
2699
      "generation.\n"
 
2700
      "InnoDB: You can either set the next AUTOINC value "
 
2701
      "explicitly using ALTER TABLE\n"
 
2702
      "InnoDB: or fix the data dictionary by recreating "
 
2703
      "the table.\n",
 
2704
      col_name, index->table->name);
 
2705
 
 
2706
    auto_inc = 0xFFFFFFFFFFFFFFFFULL;
 
2707
    break;
 
2708
 
 
2709
  default:
 
2710
    return(error);
3220
2711
  }
3221
2712
 
3222
2713
  dict_table_autoinc_initialize(prebuilt->table, auto_inc);
 
2714
 
 
2715
  return(DB_SUCCESS);
3223
2716
}
3224
2717
 
3225
2718
/*****************************************************************//**
3228
2721
@return 1 if error, 0 if success */
3229
2722
UNIV_INTERN
3230
2723
int
3231
 
ha_innobase::doOpen(const identifier::Table &identifier,
3232
 
                    int   mode,   /*!< in: not used */
3233
 
                    uint    test_if_locked) /*!< in: not used */
 
2724
ha_innobase::open(
 
2725
/*==============*/
 
2726
  const char* name,   /*!< in: table name */
 
2727
  int   mode,   /*!< in: not used */
 
2728
  uint    test_if_locked) /*!< in: not used */
3234
2729
{
3235
2730
  dict_table_t* ib_table;
 
2731
  char    norm_name[FN_REFLEN];
3236
2732
  Session*    session;
3237
2733
 
3238
2734
  UT_NOT_USED(mode);
3239
2735
  UT_NOT_USED(test_if_locked);
3240
2736
 
3241
 
  session= getTable()->in_use;
 
2737
  session= table->in_use;
3242
2738
 
3243
2739
  /* Under some cases Drizzle seems to call this function while
3244
2740
  holding btr_search_latch. This breaks the latching order as
3247
2743
    getTransactionalEngine()->releaseTemporaryLatches(session);
3248
2744
  }
3249
2745
 
 
2746
  normalize_table_name(norm_name, name);
 
2747
 
3250
2748
  user_session = NULL;
3251
2749
 
3252
 
  std::string search_string(identifier.getSchemaName());
3253
 
  boost::algorithm::to_lower(search_string);
 
2750
  if (!(share=get_share(name))) {
3254
2751
 
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
 
    }
 
2752
    return(1);
3270
2753
  }
3271
2754
 
3272
2755
  /* Create buffers for packing the fields of a record. Why
3275
2758
  stored the string length as the first byte. */
3276
2759
 
3277
2760
  upd_and_key_val_buff_len =
3278
 
        getTable()->getShare()->sizeStoredRecord()
3279
 
        + getTable()->getShare()->max_key_length
 
2761
        table->getShare()->stored_rec_length
 
2762
        + table->getShare()->max_key_length
3280
2763
        + MAX_REF_PARTS * 3;
3281
2764
 
3282
2765
  upd_buff.resize(upd_and_key_val_buff_len);
3293
2776
  }
3294
2777
 
3295
2778
  /* 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
 
  }
 
2779
  ib_table = dict_table_get(norm_name, TRUE);
3306
2780
  
3307
2781
  if (NULL == ib_table) {
3308
 
    errmsg_printf(error::ERROR, "Cannot find or open table %s from\n"
 
2782
    errmsg_printf(ERRMSG_LVL_ERROR, "Cannot find or open table %s from\n"
3309
2783
        "the internal data dictionary of InnoDB "
3310
2784
        "though the .frm file for the\n"
3311
2785
        "table exists. Maybe you have deleted and "
3319
2793
        "doesn't support.\n"
3320
2794
        "See " REFMAN "innodb-troubleshooting.html\n"
3321
2795
        "how you can resolve the problem.\n",
3322
 
        identifier.getKeyPath().c_str());
 
2796
        norm_name);
3323
2797
    free_share(share);
3324
2798
    upd_buff.resize(0);
3325
2799
    key_val_buff.resize(0);
3328
2802
    return(HA_ERR_NO_SUCH_TABLE);
3329
2803
  }
3330
2804
 
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 "
 
2805
  if (ib_table->ibd_file_missing && !session_tablespace_op(session)) {
 
2806
    errmsg_printf(ERRMSG_LVL_ERROR, "MySQL is trying to open a table handle but "
3333
2807
        "the .ibd file for\ntable %s does not exist.\n"
3334
2808
        "Have you deleted the .ibd file from the "
3335
2809
        "database directory under\nthe MySQL datadir, "
3336
2810
        "or have you used DISCARD TABLESPACE?\n"
3337
2811
        "See " REFMAN "innodb-troubleshooting.html\n"
3338
2812
        "how you can resolve the problem.\n",
3339
 
        identifier.getKeyPath().c_str());
 
2813
        norm_name);
3340
2814
    free_share(share);
3341
2815
    upd_buff.resize(0);
3342
2816
    key_val_buff.resize(0);
3348
2822
 
3349
2823
  prebuilt = row_create_prebuilt(ib_table);
3350
2824
 
3351
 
  prebuilt->mysql_row_len = getTable()->getShare()->sizeStoredRecord();
3352
 
  prebuilt->default_rec = getTable()->getDefaultValues();
 
2825
  prebuilt->mysql_row_len = table->getShare()->stored_rec_length;
 
2826
  prebuilt->default_rec = table->getDefaultValues();
3353
2827
  ut_ad(prebuilt->default_rec);
3354
2828
 
3355
2829
  /* Looks like MySQL-3.23 sometimes has primary key number != 0 */
3356
2830
 
3357
 
  primary_key = getTable()->getShare()->getPrimaryKey();
 
2831
  primary_key = table->getShare()->getPrimaryKey();
3358
2832
  key_used_on_scan = primary_key;
3359
2833
 
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
2834
  /* Allocate a buffer for a 'row reference'. A row reference is
3366
2835
  a string of bytes of length ref_length which uniquely specifies
3367
2836
  a row in our table. Note that MySQL may also compare two row
3369
2838
  of length ref_length! */
3370
2839
 
3371
2840
  if (!row_table_got_default_clust_index(ib_table)) {
 
2841
    if (primary_key >= MAX_KEY) {
 
2842
      errmsg_printf(ERRMSG_LVL_ERROR, "Table %s has a primary key in InnoDB data "
 
2843
          "dictionary, but not in MySQL!", name);
 
2844
    }
3372
2845
 
3373
2846
    prebuilt->clust_index_was_generated = FALSE;
3374
2847
 
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
 
    }
 
2848
    /* MySQL allocates the buffer for ref. key_info->key_length
 
2849
    includes space for all key columns + one byte for each column
 
2850
    that may be NULL. ref_length must be as exact as possible to
 
2851
    save space, because all row reference buffers are allocated
 
2852
    based on ref_length. */
 
2853
 
 
2854
    ref_length = table->key_info[primary_key].key_length;
3429
2855
  } else {
3430
2856
    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());
 
2857
      errmsg_printf(ERRMSG_LVL_ERROR, "Table %s has no primary key in InnoDB data "
 
2858
          "dictionary, but has one in MySQL! If you "
 
2859
          "created the table with a MySQL version < "
 
2860
          "3.23.54 and did not define a primary key, "
 
2861
          "but defined a unique key with all non-NULL "
 
2862
          "columns, then MySQL internally treats that "
 
2863
          "key as the primary key. You can fix this "
 
2864
          "error by dump + DROP + CREATE + reimport "
 
2865
          "of the table.", name);
3452
2866
    }
3453
2867
 
3454
2868
    prebuilt->clust_index_was_generated = TRUE;
3464
2878
    and it will never be updated anyway. */
3465
2879
 
3466
2880
    if (key_used_on_scan != MAX_KEY) {
3467
 
      errmsg_printf(error::WARN, 
 
2881
      errmsg_printf(ERRMSG_LVL_WARN, 
3468
2882
        "Table %s key_used_on_scan is %lu even "
3469
2883
        "though there is no primary key inside "
3470
 
        "InnoDB.", identifier.getTableName().c_str(), (ulong) key_used_on_scan);
 
2884
        "InnoDB.", name, (ulong) key_used_on_scan);
3471
2885
    }
3472
2886
  }
3473
2887
 
3475
2889
  stats.block_size = 16 * 1024;
3476
2890
 
3477
2891
  /* Init table lock structure */
3478
 
  lock.init(&share->lock);
 
2892
  thr_lock_data_init(&share->lock,&lock,(void*) 0);
3479
2893
 
3480
2894
  if (prebuilt->table) {
3481
2895
    /* We update the highest file format in the system table
3482
2896
    space, if this table has higher file format setting. */
3483
2897
 
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,
 
2898
    trx_sys_file_format_max_upgrade(
 
2899
      (const char**) &innobase_file_format_check,
3487
2900
      dict_table_get_format(prebuilt->table));
3488
 
    innobase_file_format_max= changed_file_format_max;
3489
2901
  }
3490
2902
 
 
2903
  info(HA_STATUS_NO_LOCK | HA_STATUS_VARIABLE | HA_STATUS_CONST);
 
2904
 
3491
2905
  /* Only if the table has an AUTOINC column. */
3492
 
  if (prebuilt->table != NULL && getTable()->found_next_number_field != NULL) {
 
2906
  if (prebuilt->table != NULL && table->found_next_number_field != NULL) {
 
2907
    ulint error;
3493
2908
 
3494
2909
    dict_table_autoinc_lock(prebuilt->table);
3495
2910
 
3499
2914
    autoinc value from a previous Drizzle open. */
3500
2915
    if (dict_table_autoinc_read(prebuilt->table) == 0) {
3501
2916
 
3502
 
      innobase_initialize_autoinc();
 
2917
      error = innobase_initialize_autoinc();
 
2918
      ut_a(error == DB_SUCCESS);
3503
2919
    }
3504
2920
 
3505
2921
    dict_table_autoinc_unlock(prebuilt->table);
3506
2922
  }
3507
2923
 
3508
 
  info(HA_STATUS_NO_LOCK | HA_STATUS_VARIABLE | HA_STATUS_CONST);
3509
 
 
3510
2924
  return(0);
3511
2925
}
3512
2926
 
3527
2941
{
3528
2942
  Session*  session;
3529
2943
 
3530
 
  session= getTable()->in_use;
 
2944
  session= table->in_use;
3531
2945
  if (session != NULL) {
3532
2946
    getTransactionalEngine()->releaseTemporaryLatches(session);
3533
2947
  }
3558
2972
  Table*  table,  /*!< in: MySQL table object */
3559
2973
  Field*  field)  /*!< in: MySQL field object */
3560
2974
{
3561
 
  return((uint) (field->ptr - table->getInsertRecord()));
 
2975
  return((uint) (field->ptr - table->record[0]));
3562
2976
}
3563
2977
 
3564
2978
/**************************************************************//**
3581
2995
  }
3582
2996
 
3583
2997
  null_offset = (uint) ((char*) field->null_ptr
3584
 
          - (char*) table->getInsertRecord());
 
2998
          - (char*) table->record[0]);
3585
2999
 
3586
3000
  if (record[null_offset] & field->null_bit) {
3587
3001
 
3605
3019
  int null_offset;
3606
3020
 
3607
3021
  null_offset = (uint) ((char*) field->null_ptr
3608
 
          - (char*) table->getInsertRecord());
 
3022
          - (char*) table->record[0]);
3609
3023
 
3610
3024
  record[null_offset] = record[null_offset] | field->null_bit;
3611
3025
}
3616
3030
of this function is in rem0cmp.c in InnoDB source code! If you change this
3617
3031
function, remember to update the prototype there!
3618
3032
@return 1, 0, -1, if a is greater, equal, less than b, respectively */
3619
 
UNIV_INTERN int
 
3033
extern "C" UNIV_INTERN
 
3034
int
3620
3035
innobase_mysql_cmp(
3621
3036
/*===============*/
3622
3037
  int   mysql_type, /*!< in: MySQL type */
3663
3078
      charset = get_charset(charset_number);
3664
3079
 
3665
3080
      if (charset == NULL) {
3666
 
        errmsg_printf(error::ERROR, "InnoDB needs charset %lu for doing "
 
3081
        errmsg_printf(ERRMSG_LVL_ERROR, "InnoDB needs charset %lu for doing "
3667
3082
                      "a comparison, but MySQL cannot "
3668
3083
                      "find that charset.",
3669
3084
                      (ulong) charset_number);
3698
3113
the 'mtype' of InnoDB. InnoDB differentiates between MySQL's old <= 4.1
3699
3114
VARCHAR and the new true VARCHAR in >= 5.0.3 by the 'prtype'.
3700
3115
@return DATA_BINARY, DATA_VARCHAR, ... */
3701
 
UNIV_INTERN
 
3116
extern "C" UNIV_INTERN
3702
3117
ulint
3703
3118
get_innobase_type_from_mysql_type(
3704
3119
/*==============================*/
3747
3162
      return(DATA_VARMYSQL);
3748
3163
    }
3749
3164
  case DRIZZLE_TYPE_DECIMAL:
3750
 
  case DRIZZLE_TYPE_MICROTIME:
3751
3165
    return(DATA_FIXBINARY);
3752
3166
  case DRIZZLE_TYPE_LONG:
3753
3167
  case DRIZZLE_TYPE_LONGLONG:
3754
3168
  case DRIZZLE_TYPE_DATETIME:
3755
 
  case DRIZZLE_TYPE_TIME:
3756
3169
  case DRIZZLE_TYPE_DATE:
3757
3170
  case DRIZZLE_TYPE_TIMESTAMP:
3758
 
  case DRIZZLE_TYPE_ENUM:
3759
3171
    return(DATA_INT);
3760
3172
  case DRIZZLE_TYPE_DOUBLE:
3761
3173
    return(DATA_DOUBLE);
3762
3174
  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:
 
3175
                return(DATA_BLOB);
 
3176
  default:
3768
3177
    ut_error;
3769
3178
  }
3770
3179
 
3813
3222
  uint    buff_len,/*!< in: buffer length */
3814
3223
  const unsigned char*  record)/*!< in: row in MySQL format */
3815
3224
{
3816
 
  KeyInfo*    key_info  = &getTable()->key_info[keynr];
 
3225
  KeyInfo*    key_info  = &table->key_info[keynr];
3817
3226
  KeyPartInfo*  key_part  = key_info->key_part;
3818
3227
  KeyPartInfo*  end   = key_part + key_info->key_parts;
3819
3228
  char*   buff_start  = buff;
3885
3294
      cs = field->charset();
3886
3295
 
3887
3296
      lenlen = (ulint)
3888
 
        (((Field_varstring*)field)->pack_length_no_ptr());
 
3297
        (((Field_varstring*)field)->length_bytes);
3889
3298
 
3890
3299
      data = row_mysql_read_true_varchar(&len,
3891
3300
        (byte*) (record
3892
 
        + (ulint)get_field_offset(getTable(), field)),
 
3301
        + (ulint)get_field_offset(table, field)),
3893
3302
        lenlen);
3894
3303
 
3895
3304
      true_len = len;
3952
3361
 
3953
3362
      blob_data = row_mysql_read_blob_ref(&blob_len,
3954
3363
        (byte*) (record
3955
 
        + (ulint)get_field_offset(getTable(), field)),
 
3364
        + (ulint)get_field_offset(table, field)),
3956
3365
          (ulint) field->pack_length());
3957
3366
 
3958
3367
      true_len = blob_len;
3959
3368
 
3960
 
      ut_a(get_field_offset(getTable(), field)
 
3369
      ut_a(get_field_offset(table, field)
3961
3370
        == key_part->offset);
3962
3371
 
3963
3372
      /* For multi byte character sets we need to calculate
4004
3413
      ulint     key_len;
4005
3414
      const unsigned char*    src_start;
4006
3415
      enum_field_types  real_type;
4007
 
      const CHARSET_INFO* cs= field->charset();
4008
3416
 
4009
3417
      key_len = key_part->length;
4010
3418
 
4026
3434
      memcpy(buff, src_start, true_len);
4027
3435
      buff += true_len;
4028
3436
 
4029
 
      /* Pad the unused space with spaces. */
 
3437
      /* Pad the unused space with spaces. Note that no
 
3438
      padding is ever needed for UCS-2 because in MySQL,
 
3439
      all UCS2 characters are 2 bytes, as MySQL does not
 
3440
      support surrogate pairs, which are needed to represent
 
3441
      characters in the range U+10000 to U+10FFFF. */
4030
3442
 
4031
3443
      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 */);
 
3444
        ulint pad_len = key_len - true_len;
 
3445
        memset(buff, ' ', pad_len);
4037
3446
        buff += pad_len;
4038
3447
      }
4039
3448
    }
4141
3550
 
4142
3551
  /* Note that in InnoDB, i is the column number. MySQL calls columns
4143
3552
  'fields'. */
4144
 
  for (i = 0; i < n_fields; i++)
 
3553
  for (i = 0; i < n_fields; i++) 
4145
3554
  {
4146
 
    const dict_col_t *col= &index->table->cols[i];
4147
3555
    templ = prebuilt->mysql_template + n_requested_fields;
4148
3556
    field = table->getField(i);
4149
3557
 
4189
3597
    n_requested_fields++;
4190
3598
 
4191
3599
    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
3600
 
4195
3601
    if (index == clust_index) {
4196
 
      templ->rec_field_no = templ->clust_rec_field_no;
 
3602
      templ->rec_field_no = dict_col_get_clust_pos(
 
3603
        &index->table->cols[i], index);
4197
3604
    } else {
4198
3605
      templ->rec_field_no = dict_index_get_nth_col_pos(
4199
3606
                index, i);
4200
 
      if (templ->rec_field_no == ULINT_UNDEFINED) {
4201
 
        prebuilt->need_to_access_clustered = TRUE;
4202
 
      }
 
3607
    }
 
3608
 
 
3609
    if (templ->rec_field_no == ULINT_UNDEFINED) {
 
3610
      prebuilt->need_to_access_clustered = TRUE;
4203
3611
    }
4204
3612
 
4205
3613
    if (field->null_ptr) {
4206
3614
      templ->mysql_null_byte_offset =
4207
3615
        (ulint) ((char*) field->null_ptr
4208
 
          - (char*) table->getInsertRecord());
 
3616
          - (char*) table->record[0]);
4209
3617
 
4210
3618
      templ->mysql_null_bit_mask = (ulint) field->null_bit;
4211
3619
    } else {
4221
3629
      mysql_prefix_len = templ->mysql_col_offset
4222
3630
        + templ->mysql_col_len;
4223
3631
    }
4224
 
    templ->type = col->mtype;
 
3632
    templ->type = index->table->cols[i].mtype;
4225
3633
    templ->mysql_type = (ulint)field->type();
4226
3634
 
4227
3635
    if (templ->mysql_type == DATA_MYSQL_TRUE_VARCHAR) {
4228
3636
      templ->mysql_length_bytes = (ulint)
4229
 
        (((Field_varstring*)field)->pack_length_no_ptr());
 
3637
        (((Field_varstring*)field)->length_bytes);
4230
3638
    }
4231
3639
 
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;
 
3640
    templ->charset = dtype_get_charset_coll(
 
3641
      index->table->cols[i].prtype);
 
3642
    templ->mbminlen = index->table->cols[i].mbminlen;
 
3643
    templ->mbmaxlen = index->table->cols[i].mbmaxlen;
 
3644
    templ->is_unsigned = index->table->cols[i].prtype
 
3645
              & DATA_UNSIGNED;
4236
3646
    if (templ->type == DATA_BLOB) {
4237
3647
      prebuilt->templ_contains_blob = TRUE;
4238
3648
    }
4249
3659
    for (i = 0; i < n_requested_fields; i++) {
4250
3660
      templ = prebuilt->mysql_template + i;
4251
3661
 
4252
 
      templ->rec_field_no = templ->clust_rec_field_no;
 
3662
      templ->rec_field_no = dict_col_get_clust_pos(
 
3663
        &index->table->cols[templ->col_no],
 
3664
        clust_index);
4253
3665
    }
4254
3666
  }
4255
3667
}
4256
3668
 
4257
3669
/********************************************************************//**
 
3670
Get the upper limit of the MySQL integral and floating-point type. */
 
3671
UNIV_INTERN
 
3672
uint64_t
 
3673
ha_innobase::innobase_get_int_col_max_value(
 
3674
/*========================================*/
 
3675
  const Field*  field)
 
3676
{
 
3677
  uint64_t  max_value = 0;
 
3678
 
 
3679
  switch(field->key_type()) {
 
3680
  /* TINY */
 
3681
  case HA_KEYTYPE_BINARY:
 
3682
    max_value = 0xFFULL;
 
3683
    break;
 
3684
  /* MEDIUM */
 
3685
  case HA_KEYTYPE_UINT24:
 
3686
    max_value = 0xFFFFFFULL;
 
3687
    break;
 
3688
  /* LONG */
 
3689
  case HA_KEYTYPE_ULONG_INT:
 
3690
    max_value = 0xFFFFFFFFULL;
 
3691
    break;
 
3692
  case HA_KEYTYPE_LONG_INT:
 
3693
    max_value = 0x7FFFFFFFULL;
 
3694
    break;
 
3695
  /* BIG */
 
3696
  case HA_KEYTYPE_ULONGLONG:
 
3697
    max_value = 0xFFFFFFFFFFFFFFFFULL;
 
3698
    break;
 
3699
  case HA_KEYTYPE_LONGLONG:
 
3700
    max_value = 0x7FFFFFFFFFFFFFFFULL;
 
3701
    break;
 
3702
  case HA_KEYTYPE_DOUBLE:
 
3703
    /* We use the maximum as per IEEE754-2008 standard, 2^53 */
 
3704
    max_value = 0x20000000000000ULL;
 
3705
    break;
 
3706
  default:
 
3707
    ut_error;
 
3708
  }
 
3709
 
 
3710
  return(max_value);
 
3711
}
 
3712
 
 
3713
/********************************************************************//**
4258
3714
This special handling is really to overcome the limitations of MySQL's
4259
3715
binlogging. We need to eliminate the non-determinism that will arise in
4260
3716
INSERT ... SELECT type of statements, since MySQL binlog only stores the
4323
3779
  trx_t*    trx = session_to_trx(user_session);
4324
3780
 
4325
3781
  if (prebuilt->trx != trx) {
4326
 
    errmsg_printf(error::ERROR, "The transaction object for the table handle is at "
 
3782
    errmsg_printf(ERRMSG_LVL_ERROR, "The transaction object for the table handle is at "
4327
3783
        "%p, but for the current thread it is at %p",
4328
3784
        (const void*) prebuilt->trx, (const void*) trx);
4329
3785
 
4337
3793
    ut_error;
4338
3794
  }
4339
3795
 
4340
 
  sql_command = user_session->getSqlCommand();
 
3796
  ha_statistic_increment(&system_status_var::ha_write_count);
 
3797
 
 
3798
  sql_command = session_sql_command(user_session);
4341
3799
 
4342
3800
  if ((sql_command == SQLCOM_ALTER_TABLE
4343
3801
       || sql_command == SQLCOM_CREATE_INDEX
4405
3863
  num_write_row++;
4406
3864
 
4407
3865
  /* This is the case where the table has an auto-increment column */
4408
 
  if (getTable()->next_number_field && record == getTable()->getInsertRecord()) {
 
3866
  if (table->next_number_field && record == table->record[0]) {
4409
3867
 
4410
3868
    /* Reset the error code before calling
4411
3869
    innobase_get_auto_increment(). */
4412
3870
    prebuilt->autoinc_error = DB_SUCCESS;
4413
3871
 
4414
3872
    if ((error = update_auto_increment())) {
 
3873
 
4415
3874
      /* 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) {
 
3875
      if (prebuilt->autoinc_error != DB_SUCCESS) {
4425
3876
        error = (int) prebuilt->autoinc_error;
4426
3877
 
4427
3878
        goto report_error;
4441
3892
    /* Build the template used in converting quickly between
4442
3893
    the two database formats */
4443
3894
 
4444
 
    build_template(prebuilt, NULL, getTable(), ROW_MYSQL_WHOLE_ROW);
 
3895
    build_template(prebuilt, NULL, table,
 
3896
             ROW_MYSQL_WHOLE_ROW);
4445
3897
  }
4446
3898
 
4447
3899
  innodb_srv_conc_enter_innodb(prebuilt->trx);
4448
3900
 
4449
3901
  error = row_insert_for_mysql((byte*) record, prebuilt);
4450
3902
 
4451
 
  user_session->setXaId(trx->id);
4452
 
 
4453
3903
  /* Handle duplicate key errors */
4454
3904
  if (auto_inc_used) {
4455
3905
    ulint   err;
4467
3917
    /* We need the upper limit of the col type to check for
4468
3918
    whether we update the table autoinc counter or not. */
4469
3919
    col_max_value = innobase_get_int_col_max_value(
4470
 
      getTable()->next_number_field); 
 
3920
      table->next_number_field);
 
3921
 
4471
3922
    /* Get the value that MySQL attempted to store in the table.*/
4472
 
    auto_inc = getTable()->next_number_field->val_int();
 
3923
    auto_inc = table->next_number_field->val_int();
4473
3924
 
4474
3925
    switch (error) {
4475
3926
    case DB_DUPLICATE_KEY:
4505
3956
      update the table upper limit. Note: last_value
4506
3957
      will be 0 if get_auto_increment() was not called.*/
4507
3958
 
4508
 
      if (auto_inc >= prebuilt->autoinc_last_value) {
 
3959
      if (auto_inc <= col_max_value
 
3960
          && auto_inc >= prebuilt->autoinc_last_value) {
4509
3961
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
 
          }
 
3962
        ut_a(prebuilt->autoinc_increment > 0);
 
3963
 
 
3964
        uint64_t  need;
 
3965
        uint64_t  offset;
 
3966
 
 
3967
        offset = prebuilt->autoinc_offset;
 
3968
        need = prebuilt->autoinc_increment;
 
3969
 
 
3970
        auto_inc = innobase_next_autoinc(
 
3971
          auto_inc, need, offset, col_max_value);
 
3972
 
 
3973
        err = innobase_set_max_autoinc(auto_inc);
 
3974
 
 
3975
        if (err != DB_SUCCESS) {
 
3976
          error = err;
4531
3977
        }
4532
3978
      }
4533
3979
      break;
4628
4074
        o_ptr = row_mysql_read_true_varchar(
4629
4075
          &o_len, o_ptr,
4630
4076
          (ulint)
4631
 
          (((Field_varstring*)field)->pack_length_no_ptr()));
 
4077
          (((Field_varstring*)field)->length_bytes));
4632
4078
 
4633
4079
        n_ptr = row_mysql_read_true_varchar(
4634
4080
          &n_len, n_ptr,
4635
4081
          (ulint)
4636
 
          (((Field_varstring*)field)->pack_length_no_ptr()));
 
4082
          (((Field_varstring*)field)->length_bytes));
4637
4083
      }
4638
4084
 
4639
4085
      break;
4715
4161
 
4716
4162
  ut_a(prebuilt->trx == trx);
4717
4163
 
 
4164
  ha_statistic_increment(&system_status_var::ha_update_count);
 
4165
 
4718
4166
  if (prebuilt->upd_node) {
4719
4167
    uvect = prebuilt->upd_node->update;
4720
4168
  } else {
4724
4172
  /* Build an update vector from the modified fields in the rows
4725
4173
  (uses upd_buff of the handle) */
4726
4174
 
4727
 
  calc_row_difference(uvect, (unsigned char*) old_row, new_row, getTable(),
 
4175
  calc_row_difference(uvect, (unsigned char*) old_row, new_row, table,
4728
4176
      &upd_buff[0], (ulint)upd_and_key_val_buff_len,
4729
4177
      prebuilt, user_session);
4730
4178
 
4733
4181
 
4734
4182
  ut_a(prebuilt->template_type == ROW_MYSQL_WHOLE_ROW);
4735
4183
 
4736
 
  if (getTable()->found_next_number_field)
 
4184
  if (table->found_next_number_field)
4737
4185
  {
4738
4186
    uint64_t  auto_inc;
4739
4187
    uint64_t  col_max_value;
4740
4188
 
4741
 
    auto_inc = getTable()->found_next_number_field->val_int();
 
4189
    auto_inc = table->found_next_number_field->val_int();
4742
4190
 
4743
4191
    /* We need the upper limit of the col type to check for
4744
4192
    whether we update the table autoinc counter or not. */
4745
4193
    col_max_value = innobase_get_int_col_max_value(
4746
 
      getTable()->found_next_number_field);
 
4194
      table->found_next_number_field);
4747
4195
 
4748
4196
    uint64_t current_autoinc;
4749
4197
    ulint autoinc_error= innobase_get_autoinc(&current_autoinc);
4771
4219
 
4772
4220
  error = row_update_for_mysql((byte*) old_row, prebuilt);
4773
4221
 
4774
 
  user_session->setXaId(trx->id);
4775
 
 
4776
4222
  /* We need to do some special AUTOINC handling for the following case:
4777
4223
 
4778
4224
  INSERT INTO t (c1,c2) VALUES(x,y) ON DUPLICATE KEY UPDATE ...
4782
4228
  value used in the INSERT statement.*/
4783
4229
 
4784
4230
  if (error == DB_SUCCESS
4785
 
      && getTable()->next_number_field
4786
 
      && new_row == getTable()->getInsertRecord()
4787
 
      && user_session->getSqlCommand() == SQLCOM_INSERT
 
4231
      && table->next_number_field
 
4232
      && new_row == table->record[0]
 
4233
      && session_sql_command(user_session) == SQLCOM_INSERT
4788
4234
      && (trx->duplicates & (TRX_DUP_IGNORE | TRX_DUP_REPLACE))
4789
4235
    == TRX_DUP_IGNORE)  {
4790
4236
 
4791
4237
    uint64_t  auto_inc;
4792
4238
    uint64_t  col_max_value;
4793
4239
 
4794
 
    auto_inc = getTable()->next_number_field->val_int();
 
4240
    auto_inc = table->next_number_field->val_int();
4795
4241
 
4796
4242
    /* We need the upper limit of the col type to check for
4797
4243
    whether we update the table autoinc counter or not. */
4798
4244
    col_max_value = innobase_get_int_col_max_value(
4799
 
      getTable()->next_number_field);
 
4245
      table->next_number_field);
4800
4246
 
4801
4247
    if (auto_inc <= col_max_value && auto_inc != 0) {
4802
4248
 
4851
4297
 
4852
4298
  ut_a(prebuilt->trx == trx);
4853
4299
 
 
4300
  ha_statistic_increment(&system_status_var::ha_delete_count);
 
4301
 
4854
4302
  if (!prebuilt->upd_node) {
4855
4303
    row_get_prebuilt_update_vector(prebuilt);
4856
4304
  }
4863
4311
 
4864
4312
  error = row_update_for_mysql((byte*) record, prebuilt);
4865
4313
 
4866
 
  user_session->setXaId(trx->id);
4867
 
 
4868
4314
  innodb_srv_conc_exit_innodb(trx);
4869
4315
 
4870
4316
  error = convert_error_code_to_mysql(
4898
4344
  case ROW_READ_WITH_LOCKS:
4899
4345
    if (!srv_locks_unsafe_for_binlog
4900
4346
        && prebuilt->trx->isolation_level
4901
 
        > TRX_ISO_READ_COMMITTED) {
 
4347
        != TRX_ISO_READ_COMMITTED) {
4902
4348
      break;
4903
4349
    }
4904
4350
    /* fall through */
4928
4374
ha_innobase::try_semi_consistent_read(bool yes)
4929
4375
/*===========================================*/
4930
4376
{
4931
 
  ut_a(prebuilt->trx == session_to_trx(getTable()->in_use));
 
4377
  ut_a(prebuilt->trx == session_to_trx(table->in_use));
4932
4378
 
4933
4379
  /* Row read type is set to semi consistent read if this was
4934
4380
  requested by the MySQL and either innodb_locks_unsafe_for_binlog
4937
4383
 
4938
4384
  if (yes
4939
4385
      && (srv_locks_unsafe_for_binlog
4940
 
    || prebuilt->trx->isolation_level <= TRX_ISO_READ_COMMITTED)) {
 
4386
    || prebuilt->trx->isolation_level == TRX_ISO_READ_COMMITTED)) {
4941
4387
    prebuilt->row_read_type = ROW_READ_TRY_SEMI_CONSISTENT;
4942
4388
  } else {
4943
4389
    prebuilt->row_read_type = ROW_READ_WITH_LOCKS;
5118
4564
 
5119
4565
  index = prebuilt->index;
5120
4566
 
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
4567
  /* Note that if the index for which the search template is built is not
5131
4568
  necessarily prebuilt->index, but can also be the clustered index */
5132
4569
 
5133
4570
  if (prebuilt->sql_stat_start) {
5134
 
    build_template(prebuilt, user_session, getTable(),
 
4571
    build_template(prebuilt, user_session, table,
5135
4572
             ROW_MYSQL_REC_FIELDS);
5136
4573
  }
5137
4574
 
5186
4623
  switch (ret) {
5187
4624
  case DB_SUCCESS:
5188
4625
    error = 0;
5189
 
    getTable()->status = 0;
 
4626
    table->status = 0;
5190
4627
    break;
5191
4628
  case DB_RECORD_NOT_FOUND:
5192
4629
    error = HA_ERR_KEY_NOT_FOUND;
5193
 
    getTable()->status = STATUS_NOT_FOUND;
 
4630
    table->status = STATUS_NOT_FOUND;
5194
4631
    break;
5195
4632
  case DB_END_OF_INDEX:
5196
4633
    error = HA_ERR_KEY_NOT_FOUND;
5197
 
    getTable()->status = STATUS_NOT_FOUND;
 
4634
    table->status = STATUS_NOT_FOUND;
5198
4635
    break;
5199
4636
  default:
5200
4637
    error = convert_error_code_to_mysql((int) ret,
5201
4638
                prebuilt->table->flags,
5202
4639
                user_session);
5203
 
    getTable()->status = STATUS_NOT_FOUND;
 
4640
    table->status = STATUS_NOT_FOUND;
5204
4641
    break;
5205
4642
  }
5206
4643
 
5239
4676
 
5240
4677
  ha_statistic_increment(&system_status_var::ha_read_key_count);
5241
4678
 
5242
 
  if (keynr != MAX_KEY && getTable()->getShare()->sizeKeys() > 0) 
 
4679
  ut_ad(user_session == table->in_use);
 
4680
  ut_a(prebuilt->trx == session_to_trx(user_session));
 
4681
 
 
4682
  if (keynr != MAX_KEY && table->getShare()->sizeKeys() > 0) 
5243
4683
  {
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
 
    }
 
4684
    index = dict_table_get_index_on_name(prebuilt->table,
 
4685
                                         table->getShare()->getTableProto()->indexes(keynr).name().c_str());
5267
4686
  } else {
5268
4687
    index = dict_table_get_first_index(prebuilt->table);
5269
4688
  }
5270
4689
 
5271
4690
  if (!index) {
5272
 
    errmsg_printf(error::ERROR, 
 
4691
    errmsg_printf(ERRMSG_LVL_ERROR, 
5273
4692
      "Innodb could not find key n:o %u with name %s "
5274
4693
      "from dict cache for table %s",
5275
 
      keynr, getTable()->getShare()->getTableMessage()->indexes(keynr).name().c_str(),
 
4694
      keynr, table->getShare()->getTableProto()->indexes(keynr).name().c_str(),
5276
4695
      prebuilt->table->name);
5277
4696
  }
5278
4697
 
5298
4717
  prebuilt->index = innobase_get_index(keynr);
5299
4718
 
5300
4719
  if (UNIV_UNLIKELY(!prebuilt->index)) {
5301
 
    errmsg_printf(error::WARN, "InnoDB: change_active_index(%u) failed",
 
4720
    errmsg_printf(ERRMSG_LVL_WARN, "InnoDB: change_active_index(%u) failed",
5302
4721
          keynr);
5303
 
    prebuilt->index_usable = FALSE;
5304
4722
    return(1);
5305
4723
  }
5306
4724
 
5308
4726
                 prebuilt->index);
5309
4727
 
5310
4728
  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);
 
4729
    errmsg_printf(ERRMSG_LVL_WARN,
 
4730
         "InnoDB: insufficient history for index %u",
 
4731
          keynr);
5315
4732
    /* The caller seems to ignore this.  Thus, we must check
5316
4733
    this again in row_search_for_mysql(). */
5317
4734
    return(2);
5330
4747
  the flag ROW_MYSQL_WHOLE_ROW below, but that caused unnecessary
5331
4748
  copying. Starting from MySQL-4.1 we use a more efficient flag here. */
5332
4749
 
5333
 
  build_template(prebuilt, user_session, getTable(), ROW_MYSQL_REC_FIELDS);
 
4750
  build_template(prebuilt, user_session, table, ROW_MYSQL_REC_FIELDS);
5334
4751
 
5335
4752
  return(0);
5336
4753
}
5390
4807
  switch (ret) {
5391
4808
  case DB_SUCCESS:
5392
4809
    error = 0;
5393
 
    getTable()->status = 0;
 
4810
    table->status = 0;
5394
4811
    break;
5395
4812
  case DB_RECORD_NOT_FOUND:
5396
4813
    error = HA_ERR_END_OF_FILE;
5397
 
    getTable()->status = STATUS_NOT_FOUND;
 
4814
    table->status = STATUS_NOT_FOUND;
5398
4815
    break;
5399
4816
  case DB_END_OF_INDEX:
5400
4817
    error = HA_ERR_END_OF_FILE;
5401
 
    getTable()->status = STATUS_NOT_FOUND;
 
4818
    table->status = STATUS_NOT_FOUND;
5402
4819
    break;
5403
4820
  default:
5404
4821
    error = convert_error_code_to_mysql(
5405
4822
      (int) ret, prebuilt->table->flags, user_session);
5406
 
    getTable()->status = STATUS_NOT_FOUND;
 
4823
    table->status = STATUS_NOT_FOUND;
5407
4824
    break;
5408
4825
  }
5409
4826
 
5598
5015
 
5599
5016
  ha_statistic_increment(&system_status_var::ha_read_rnd_count);
5600
5017
 
5601
 
  ut_a(prebuilt->trx == session_to_trx(getTable()->in_use));
 
5018
  ut_a(prebuilt->trx == session_to_trx(table->in_use));
5602
5019
 
5603
5020
  if (prebuilt->clust_index_was_generated) {
5604
5021
    /* No primary key was defined for the table and we
5644
5061
{
5645
5062
  uint    len;
5646
5063
 
5647
 
  ut_a(prebuilt->trx == session_to_trx(getTable()->in_use));
 
5064
  ut_a(prebuilt->trx == session_to_trx(table->in_use));
5648
5065
 
5649
5066
  if (prebuilt->clust_index_was_generated) {
5650
5067
    /* No primary key was defined for the table and we
5664
5081
  table. */
5665
5082
 
5666
5083
  if (len != ref_length) {
5667
 
    errmsg_printf(error::ERROR, "Stored ref len is %lu, but table ref len is %lu",
 
5084
    errmsg_printf(ERRMSG_LVL_ERROR, "Stored ref len is %lu, but table ref len is %lu",
5668
5085
        (ulong) len, (ulong) ref_length);
5669
5086
  }
5670
5087
}
5720
5137
 
5721
5138
    col_type = get_innobase_type_from_mysql_type(&unsigned_type,
5722
5139
                  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
5140
    if (field->null_ptr) {
5739
5141
      nulls_allowed = 0;
5740
5142
    } else {
5757
5159
        /* in data0type.h we assume that the
5758
5160
        number fits in one byte in prtype */
5759
5161
        push_warning_printf(
5760
 
          trx->mysql_thd,
 
5162
          (Session*) trx->mysql_thd,
5761
5163
          DRIZZLE_ERROR::WARN_LEVEL_ERROR,
5762
5164
          ER_CANT_CREATE_TABLE,
5763
5165
          "In InnoDB, charset-collation codes"
5780
5182
    long_true_varchar = 0;
5781
5183
 
5782
5184
    if (field->type() == DRIZZLE_TYPE_VARCHAR) {
5783
 
      col_len -= ((Field_varstring*)field)->pack_length_no_ptr();
 
5185
      col_len -= ((Field_varstring*)field)->length_bytes;
5784
5186
 
5785
 
      if (((Field_varstring*)field)->pack_length_no_ptr() == 2) {
 
5187
      if (((Field_varstring*)field)->length_bytes == 2) {
5786
5188
        long_true_varchar = DATA_LONG_TRUE_VARCHAR;
5787
5189
      }
5788
5190
    }
5789
5191
 
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
5192
    dict_mem_table_add_col(table, table->heap,
5804
5193
      (char*) field->field_name,
5805
5194
      col_type,
5813
5202
 
5814
5203
  error = row_create_table_for_mysql(table, trx);
5815
5204
 
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
5205
  error = convert_error_code_to_mysql(error, flags, NULL);
5828
5206
 
5829
5207
  return(error);
5860
5238
 
5861
5239
  n_fields = key->key_parts;
5862
5240
 
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
5241
  ind_type = 0;
5867
5242
 
5868
5243
  if (key_num == form->getShare()->getPrimaryKey()) {
5915
5290
        && field->type() != DRIZZLE_TYPE_VARCHAR)
5916
5291
      || (field->type() == DRIZZLE_TYPE_VARCHAR
5917
5292
        && key_part->length < field->pack_length()
5918
 
        - ((Field_varstring*)field)->pack_length_no_ptr())) {
 
5293
        - ((Field_varstring*)field)->length_bytes)) {
5919
5294
 
5920
5295
      prefix_len = key_part->length;
5921
5296
 
5923
5298
        || col_type == DATA_FLOAT
5924
5299
        || col_type == DATA_DOUBLE
5925
5300
        || col_type == DATA_DECIMAL) {
5926
 
        errmsg_printf(error::ERROR, 
 
5301
        errmsg_printf(ERRMSG_LVL_ERROR, 
5927
5302
          "MySQL is trying to create a column "
5928
5303
          "prefix index field, on an "
5929
5304
          "inappropriate data type. Table "
5972
5347
  /* We pass 0 as the space id, and determine at a lower level the space
5973
5348
  id where to store the table */
5974
5349
 
5975
 
  index = dict_mem_index_create(table_name,
5976
 
                                innobase_index_reserve_name,
5977
 
                                0, DICT_CLUSTERED, 0);
 
5350
  index = dict_mem_index_create(table_name, "GEN_CLUST_INDEX",
 
5351
              0, DICT_CLUSTERED, 0);
5978
5352
 
5979
5353
  error = row_create_index_for_mysql(index, trx, NULL);
5980
5354
 
6023
5397
/*================*/
6024
5398
  Session         &session, /*!< in: Session */
6025
5399
  Table&    form,   /*!< in: information on table columns and indexes */
6026
 
        const identifier::Table &identifier,
 
5400
        drizzled::TableIdentifier &identifier,
6027
5401
        message::Table& create_proto)
6028
5402
{
6029
5403
  int   error;
6032
5406
  trx_t*    trx;
6033
5407
  int   primary_key_no;
6034
5408
  uint    i;
 
5409
  char    name2[FN_REFLEN];
 
5410
  char    norm_name[FN_REFLEN];
6035
5411
  ib_int64_t  auto_inc_value;
6036
5412
  ulint   iflags;
6037
5413
  /* Cache the value of innodb_file_format, in case it is
6038
5414
    modified by another thread while the table is being created. */
6039
5415
  const ulint file_format = srv_file_format;
6040
5416
  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
 
  }
 
5417
 
 
5418
  const char *table_name= identifier.getPath().c_str();
6051
5419
 
6052
5420
  if (form.getShare()->sizeFields() > 1000) {
6053
5421
    /* The limit probably should be REC_MAX_N_FIELDS - 3 = 1020,
6070
5438
 
6071
5439
  srv_lower_case_table_names = TRUE;
6072
5440
 
 
5441
  strcpy(name2, table_name);
 
5442
 
 
5443
  normalize_table_name(norm_name, name2);
 
5444
 
6073
5445
  /* Latch the InnoDB data dictionary exclusively so that no deadlocks
6074
5446
    or lock waits can happen in it during a table create operation.
6075
5447
    Drop table etc. do this latching in row0mysql.c. */
6134
5506
# error "DICT_TF_ZSSIZE_MAX < 1"
6135
5507
#endif
6136
5508
 
6137
 
    if (strict_mode)
 
5509
    if (SessionVAR(&session, strict_mode))
6138
5510
    {
6139
5511
      if (! srv_file_per_table)
6140
5512
      {
6153
5525
                            "InnoDB: ROW_FORMAT=compressed requires innodb_file_format > Antelope.");
6154
5526
      }
6155
5527
    }
 
5528
 
 
5529
    error= create_table_def(trx, &form, norm_name,
 
5530
                            lex_identified_temp_table ? name2 : NULL,
 
5531
                            iflags);
 
5532
  }
 
5533
 
 
5534
  if (error) {
 
5535
    goto cleanup;
6156
5536
  }
6157
5537
 
6158
5538
  /* Look for a primary key */
6161
5541
                   (int) form.getShare()->getPrimaryKey() :
6162
5542
                   -1);
6163
5543
 
6164
 
  /* Our function innobase_get_mysql_key_number_for_index assumes
 
5544
  /* Our function row_get_mysql_key_number_for_index assumes
6165
5545
    the primary key is always number 0, if it exists */
6166
5546
 
6167
5547
  assert(primary_key_no == -1 || primary_key_no == 0);
6168
5548
 
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
5549
  /* Create the keys */
6191
5550
 
6192
5551
  if (form.getShare()->sizeKeys() == 0 || primary_key_no == -1) {
6194
5553
      order the rows by their row id which is internally generated
6195
5554
      by InnoDB */
6196
5555
 
6197
 
    error = create_clustered_index_when_no_primary(trx, iflags, identifier.getKeyPath().c_str());
 
5556
    error = create_clustered_index_when_no_primary(trx, iflags, norm_name);
6198
5557
    if (error) {
6199
5558
      goto cleanup;
6200
5559
    }
6202
5561
 
6203
5562
  if (primary_key_no != -1) {
6204
5563
    /* In InnoDB the clustered index must always be created first */
6205
 
    if ((error = create_index(trx, &form, iflags, identifier.getKeyPath().c_str(),
 
5564
    if ((error = create_index(trx, &form, iflags, norm_name,
6206
5565
                              (uint) primary_key_no))) {
6207
5566
      goto cleanup;
6208
5567
    }
6211
5570
  for (i = 0; i < form.getShare()->sizeKeys(); i++) {
6212
5571
    if (i != (uint) primary_key_no) {
6213
5572
 
6214
 
      if ((error = create_index(trx, &form, iflags, identifier.getKeyPath().c_str(),
 
5573
      if ((error = create_index(trx, &form, iflags, norm_name,
6215
5574
                                i))) {
6216
5575
        goto cleanup;
6217
5576
      }
6218
5577
    }
6219
5578
  }
6220
5579
 
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
 
 
 
5580
  if (trx->mysql_query_str) {
6235
5581
    error = row_table_add_foreign_constraints(trx,
6236
 
                                              query, strlen(query),
6237
 
                                              identifier.getKeyPath().c_str(),
 
5582
                                              trx->mysql_query_str, norm_name,
6238
5583
                                              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
5584
 
6262
5585
    error = convert_error_code_to_mysql(error, iflags, NULL);
6263
5586
 
6276
5599
 
6277
5600
  log_buffer_flush_to_disk();
6278
5601
 
6279
 
  innobase_table = dict_table_get(identifier.getKeyPath().c_str(), FALSE);
 
5602
  innobase_table = dict_table_get(norm_name, FALSE);
6280
5603
 
6281
5604
  assert(innobase_table != 0);
6282
5605
 
6284
5607
    /* We update the highest file format in the system table
6285
5608
      space, if this table has higher file format setting. */
6286
5609
 
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;
 
5610
    trx_sys_file_format_max_upgrade((const char**) &innobase_file_format_check,
 
5611
                                    dict_table_get_format(innobase_table));
6292
5612
  }
6293
5613
 
6294
5614
  /* Note: We can't call update_session() as prebuilt will not be
6295
5615
    setup at this stage and so we use session. */
6296
5616
 
6297
5617
  /* 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. */
 
5618
    this is an ALTER TABLE. */
6300
5619
 
6301
5620
  if ((create_proto.options().has_auto_increment_value()
6302
 
       || session.getSqlCommand() == SQLCOM_ALTER_TABLE
6303
 
       || session.getSqlCommand() == SQLCOM_CREATE_INDEX)
 
5621
       || session_sql_command(&session) == SQLCOM_ALTER_TABLE)
6304
5622
      && create_proto.options().auto_increment_value() != 0) {
6305
5623
 
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. */
 
5624
    /* Query was ALTER TABLE...AUTO_INCREMENT = x; or
 
5625
      CREATE TABLE ...AUTO_INCREMENT = x; Find out a table
 
5626
      definition from the dictionary and get the current value
 
5627
      of the auto increment field. Set a new value to the
 
5628
      auto increment field if the value is greater than the
 
5629
      maximum value in the column. */
6314
5630
 
6315
5631
    auto_inc_value = create_proto.options().auto_increment_value();
6316
5632
 
6328
5644
 
6329
5645
  if (lex_identified_temp_table)
6330
5646
  {
6331
 
    session.getMessageCache().storeTableMessage(identifier, create_proto);
 
5647
    session.storeTableMessage(identifier, create_proto);
6332
5648
  }
6333
5649
  else
6334
5650
  {
6362
5678
 
6363
5679
  ut_a(prebuilt->trx);
6364
5680
  ut_a(prebuilt->trx->magic_n == TRX_MAGIC_N);
6365
 
  ut_a(prebuilt->trx == session_to_trx(getTable()->in_use));
 
5681
  ut_a(prebuilt->trx == session_to_trx(table->in_use));
6366
5682
 
6367
5683
  dict_table = prebuilt->table;
6368
5684
  trx = prebuilt->trx;
6391
5707
  /* Get the transaction associated with the current session, or create one
6392
5708
  if not yet created, and update prebuilt->trx */
6393
5709
 
6394
 
  update_session(getTable()->in_use);
 
5710
  update_session(table->in_use);
6395
5711
 
6396
 
  if (user_session->getSqlCommand() != SQLCOM_TRUNCATE) {
 
5712
  if (session_sql_command(user_session) != SQLCOM_TRUNCATE) {
6397
5713
  fallback:
6398
5714
    /* We only handle TRUNCATE TABLE t as a special case.
6399
5715
    DELETE FROM t will have to use ha_innobase::doDeleteRecord(),
6427
5743
InnobaseEngine::doDropTable(
6428
5744
/*======================*/
6429
5745
        Session &session,
6430
 
        const identifier::Table &identifier)
 
5746
        TableIdentifier &identifier)
6431
5747
{
6432
5748
  int error;
6433
5749
  trx_t*  parent_trx;
6434
5750
  trx_t*  trx;
 
5751
  char  norm_name[1000];
6435
5752
 
6436
5753
  ut_a(identifier.getPath().length() < 1000);
6437
5754
 
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
 
  }
 
5755
  /* Strangely, MySQL passes the table name without the '.frm'
 
5756
    extension, in contrast to ::create */
 
5757
  normalize_table_name(norm_name, identifier.getPath().c_str());
6445
5758
 
6446
5759
  /* Get the transaction associated with the current session, or create one
6447
5760
    if not yet created */
6459
5772
 
6460
5773
  /* Drop the table in InnoDB */
6461
5774
 
6462
 
  error = row_drop_table_for_mysql(identifier.getKeyPath().c_str(), trx,
6463
 
                                   session.getSqlCommand()
 
5775
  error = row_drop_table_for_mysql(norm_name, trx,
 
5776
                                   session_sql_command(&session)
6464
5777
                                   == SQLCOM_DROP_DB);
6465
5778
 
6466
 
  session.setXaId(trx->id);
6467
 
 
6468
5779
  /* Flush the log to reduce probability that the .frm files and
6469
5780
    the InnoDB data dictionary get out-of-sync if the user runs
6470
5781
    with innodb_flush_log_at_trx_commit = 0 */
6487
5798
  {
6488
5799
    if (identifier.getType() == message::Table::TEMPORARY)
6489
5800
    {
6490
 
      session.getMessageCache().removeTableMessage(identifier);
6491
 
      ulint sql_command = session.getSqlCommand();
 
5801
      session.removeTableMessage(identifier);
 
5802
      ulint sql_command = session_sql_command(&session);
6492
5803
 
6493
5804
      // If this was the final removal to an alter table then we will need
6494
5805
      // to remove the .dfe that was left behind.
6521
5832
bool
6522
5833
InnobaseEngine::doDropSchema(
6523
5834
/*===================*/
6524
 
                             const identifier::Schema &identifier)
 
5835
                             SchemaIdentifier &identifier)
6525
5836
    /*!< in: database path; inside InnoDB the name
6526
5837
      of the last directory in the path is used as
6527
5838
      the database name: for example, in 'mysql/data/test'
6571
5882
 
6572
5883
void InnobaseEngine::dropTemporarySchema()
6573
5884
{
6574
 
  identifier::Schema schema_identifier(GLOBAL_TEMPORARY_EXT);
 
5885
  SchemaIdentifier schema_identifier(GLOBAL_TEMPORARY_EXT);
6575
5886
  trx_t*  trx= NULL;
6576
5887
  string schema_path(GLOBAL_TEMPORARY_EXT);
6577
5888
 
6580
5891
  trx = trx_allocate_for_mysql();
6581
5892
 
6582
5893
  trx->mysql_thd = NULL;
 
5894
  trx->mysql_query_str = NULL;
6583
5895
 
6584
5896
  trx->check_foreigns = false;
6585
5897
  trx->check_unique_secondary = false;
6608
5920
innobase_rename_table(
6609
5921
/*==================*/
6610
5922
  trx_t*    trx,  /*!< in: transaction */
6611
 
  const identifier::Table &from,
6612
 
  const identifier::Table &to,
 
5923
  const char* from, /*!< in: old name of the table */
 
5924
  const char* to, /*!< in: new name of the table */
6613
5925
  ibool   lock_and_commit)
6614
5926
        /*!< in: TRUE=lock data dictionary and commit */
6615
5927
{
6616
5928
  int error;
 
5929
  char norm_to[FN_REFLEN];
 
5930
  char norm_from[FN_REFLEN];
6617
5931
 
6618
5932
  srv_lower_case_table_names = TRUE;
6619
5933
 
 
5934
  normalize_table_name(norm_to, to);
 
5935
  normalize_table_name(norm_from, from);
 
5936
 
6620
5937
  /* Serialize data dictionary operations with dictionary mutex:
6621
5938
  no deadlocks can occur then in these operations */
6622
5939
 
6624
5941
    row_mysql_lock_data_dictionary(trx);
6625
5942
  }
6626
5943
 
6627
 
  error = row_rename_table_for_mysql(from.getKeyPath().c_str(), to.getKeyPath().c_str(), trx, lock_and_commit);
 
5944
  error = row_rename_table_for_mysql(
 
5945
    norm_from, norm_to, trx, lock_and_commit);
6628
5946
 
6629
5947
  if (error != DB_SUCCESS) {
6630
5948
    FILE* ef = dict_foreign_err_file;
6631
5949
 
6632
5950
    fputs("InnoDB: Renaming table ", ef);
6633
 
    ut_print_name(ef, trx, TRUE, from.getKeyPath().c_str());
 
5951
    ut_print_name(ef, trx, TRUE, norm_from);
6634
5952
    fputs(" to ", ef);
6635
 
    ut_print_name(ef, trx, TRUE, to.getKeyPath().c_str());
 
5953
    ut_print_name(ef, trx, TRUE, norm_to);
6636
5954
    fputs(" failed!\n", ef);
6637
5955
  }
6638
5956
 
6651
5969
/*********************************************************************//**
6652
5970
Renames an InnoDB table.
6653
5971
@return 0 or error code */
6654
 
UNIV_INTERN int InnobaseEngine::doRenameTable(Session &session, const identifier::Table &from, const identifier::Table &to)
 
5972
UNIV_INTERN int InnobaseEngine::doRenameTable(Session &session, TableIdentifier &from, TableIdentifier &to)
6655
5973
{
6656
5974
  // A temp table alter table/rename is a shallow rename and only the
6657
5975
  // definition needs to be updated.
6658
5976
  if (to.getType() == message::Table::TEMPORARY && from.getType() == message::Table::TEMPORARY)
6659
5977
  {
6660
 
    session.getMessageCache().renameTableMessage(from, to);
 
5978
    session.renameTableMessage(from, to);
6661
5979
    return 0;
6662
5980
  }
6663
5981
 
6677
5995
 
6678
5996
  trx = innobase_trx_allocate(&session);
6679
5997
 
6680
 
  error = innobase_rename_table(trx, from, to, TRUE);
6681
 
 
6682
 
  session.setXaId(trx->id);
 
5998
  error = innobase_rename_table(trx, from.getPath().c_str(), to.getPath().c_str(), TRUE);
6683
5999
 
6684
6000
  /* Tell the InnoDB server that there might be work for
6685
6001
    utility threads: */
6689
6005
  innobase_commit_low(trx);
6690
6006
  trx_free_for_mysql(trx);
6691
6007
 
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
6008
  error = convert_error_code_to_mysql(error, 0, NULL);
6710
6009
 
6711
6010
  if (not error)
6733
6032
  KeyInfo*    key;
6734
6033
  dict_index_t* index;
6735
6034
  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;
 
6035
              table->getShare()->stored_rec_length
 
6036
          + table->getShare()->max_key_length + 100);
 
6037
  ulint   buff2_len = table->getShare()->stored_rec_length
 
6038
          + table->getShare()->max_key_length + 100;
6740
6039
  dtuple_t* range_start;
6741
6040
  dtuple_t* range_end;
6742
6041
  ib_int64_t  n_rows;
6744
6043
  ulint   mode2;
6745
6044
  mem_heap_t* heap;
6746
6045
 
6747
 
  ut_a(prebuilt->trx == session_to_trx(getTable()->in_use));
 
6046
  ut_a(prebuilt->trx == session_to_trx(table->in_use));
6748
6047
 
6749
6048
  prebuilt->trx->op_info = (char*)"estimating records in index range";
6750
6049
 
6755
6054
 
6756
6055
  active_index = keynr;
6757
6056
 
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
 
  }
 
6057
  key = &table->key_info[active_index];
 
6058
 
 
6059
  index = dict_table_get_index_on_name(prebuilt->table, table->getShare()->getTableProto()->indexes(active_index).name().c_str());
 
6060
 
 
6061
  /* MySQL knows about this index and so we must be able to find it.*/
 
6062
  ut_a(index);
6774
6063
 
6775
6064
  heap = mem_heap_create(2 * (key->key_parts * sizeof(dfield_t)
6776
6065
            + sizeof(dtuple_t)));
6815
6104
 
6816
6105
  mem_heap_free(heap);
6817
6106
 
6818
 
func_exit:
6819
6107
  free(key_val_buff2);
6820
6108
 
6821
6109
  prebuilt->trx->op_info = (char*)"";
6845
6133
  dict_index_t* index;
6846
6134
  uint64_t  estimate;
6847
6135
  uint64_t  local_data_file_length;
6848
 
  ulint stat_n_leaf_pages;
6849
6136
 
6850
6137
  /* We do not know if MySQL can call this function before calling
6851
6138
  external_lock(). To be safe, update the session of the current table
6852
6139
  handle. */
6853
6140
 
6854
 
  update_session(getTable()->in_use);
 
6141
  update_session(table->in_use);
6855
6142
 
6856
6143
  prebuilt->trx->op_info = (char*)
6857
6144
         "calculating upper bound for table rows";
6863
6150
 
6864
6151
  index = dict_table_get_first_index(prebuilt->table);
6865
6152
 
6866
 
  stat_n_leaf_pages = index->stat_n_leaf_pages;
6867
 
 
6868
 
  ut_a(stat_n_leaf_pages > 0);
 
6153
  ut_a(index->stat_n_leaf_pages > 0);
6869
6154
 
6870
6155
  local_data_file_length =
6871
 
    ((uint64_t) stat_n_leaf_pages) * UNIV_PAGE_SIZE;
 
6156
    ((uint64_t) index->stat_n_leaf_pages) * UNIV_PAGE_SIZE;
6872
6157
 
6873
6158
 
6874
6159
  /* Calculate a minimum length for a clustered index record and from
6917
6202
  ha_rows total_rows;
6918
6203
  double  time_for_scan;
6919
6204
 
6920
 
  if (index != getTable()->getShare()->getPrimaryKey()) {
 
6205
  if (index != table->getShare()->getPrimaryKey()) {
6921
6206
    /* Not clustered */
6922
6207
    return(Cursor::read_time(index, ranges, rows));
6923
6208
  }
6941
6226
}
6942
6227
 
6943
6228
/*********************************************************************//**
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
6229
Returns statistics information of the table to the MySQL interpreter,
7046
6230
in various fields of the handle object. */
7047
6231
UNIV_INTERN
7054
6238
  dict_index_t* index;
7055
6239
  ha_rows   rec_per_key;
7056
6240
  ib_int64_t  n_rows;
 
6241
  ulong   j;
 
6242
  ulong   i;
 
6243
  char    path[FN_REFLEN];
7057
6244
  os_file_stat_t  stat_info;
7058
6245
 
7059
6246
  /* If we are forcing recovery at a high level, we will suppress
7060
6247
  statistics calculation on tables, because that may crash the
7061
6248
  server if an index is badly corrupted. */
7062
6249
 
 
6250
  if (srv_force_recovery >= SRV_FORCE_NO_IBUF_MERGE) {
 
6251
 
 
6252
    /* We return success (0) instead of HA_ERR_CRASHED,
 
6253
    because we want MySQL to process this query and not
 
6254
    stop, like it would do if it received the error code
 
6255
    HA_ERR_CRASHED. */
 
6256
 
 
6257
    return(0);
 
6258
  }
 
6259
 
7063
6260
  /* We do not know if MySQL can call this function before calling
7064
6261
  external_lock(). To be safe, update the session of the current table
7065
6262
  handle. */
7066
6263
 
7067
 
  update_session(getTable()->in_use);
 
6264
  update_session(table->in_use);
7068
6265
 
7069
6266
  /* In case MySQL calls this in the middle of a SELECT query, release
7070
6267
  possible adaptive hash latch to avoid deadlocks of threads */
7076
6273
  ib_table = prebuilt->table;
7077
6274
 
7078
6275
  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");
 
6276
    if (innobase_stats_on_metadata) {
 
6277
      /* In sql_show we call with this flag: update
 
6278
      then statistics so that they are up-to-date */
 
6279
 
 
6280
      prebuilt->trx->op_info = "updating table statistics";
 
6281
 
 
6282
      dict_update_statistics(ib_table);
 
6283
 
 
6284
      prebuilt->trx->op_info = "returning various info to MySQL";
 
6285
    }
 
6286
 
 
6287
    snprintf(path, sizeof(path), "%s/%s%s",
 
6288
             data_home, ib_table->name, ".dfe");
 
6289
 
 
6290
    internal::unpack_filename(path,path);
7094
6291
 
7095
6292
    /* Note that we do not know the access time of the table,
7096
6293
    nor the CHECK TABLE time, nor the UPDATE or INSERT time. */
7097
6294
 
7098
 
    if (os_file_get_status(get_status_path.file_string().c_str(), &stat_info)) {
 
6295
    if (os_file_get_status(path,&stat_info)) {
7099
6296
      stats.create_time = (ulong) stat_info.ctime;
7100
6297
    }
7101
6298
  }
7102
6299
 
7103
6300
  if (flag & HA_STATUS_VARIABLE) {
7104
 
 
7105
 
    dict_table_stats_lock(ib_table, RW_S_LATCH);
7106
 
 
7107
6301
    n_rows = ib_table->stat_n_rows;
7108
6302
 
7109
6303
    /* Because we do not protect stat_n_rows by any mutex in a
7131
6325
    n_rows can not be 0 unless the table is empty, set to 1
7132
6326
    instead. The original problem of bug#29507 is actually
7133
6327
    fixed in the server code. */
7134
 
    if (user_session->getSqlCommand() == SQLCOM_TRUNCATE) {
 
6328
    if (session_sql_command(user_session) == SQLCOM_TRUNCATE) {
7135
6329
 
7136
6330
      n_rows = 1;
7137
6331
 
7153
6347
        ib_table->stat_sum_of_other_index_sizes)
7154
6348
          * UNIV_PAGE_SIZE;
7155
6349
 
7156
 
    dict_table_stats_unlock(ib_table, RW_S_LATCH);
7157
 
 
7158
6350
    /* Since fsp_get_available_space_in_free_extents() is
7159
6351
    acquiring latches inside InnoDB, we do not call it if we
7160
6352
    are asked by MySQL to avoid locking. Another reason to
7161
6353
    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) {
 
6354
    See Bug#38185.
 
6355
    We do not update delete_length if no locking is requested
 
6356
    so the "old" value can remain. delete_length is initialized
 
6357
    to 0 in the ha_statistics' constructor. */
 
6358
    if (!(flag & HA_STATUS_NO_LOCK)) {
 
6359
 
 
6360
      /* lock the data dictionary to avoid races with
 
6361
      ibd_file_missing and tablespace_discarded */
 
6362
      row_mysql_lock_data_dictionary(prebuilt->trx);
 
6363
 
 
6364
      /* ib_table->space must be an existent tablespace */
 
6365
      if (!ib_table->ibd_file_missing
 
6366
          && !ib_table->tablespace_discarded) {
 
6367
 
 
6368
        stats.delete_length =
 
6369
          fsp_get_available_space_in_free_extents(
 
6370
            ib_table->space) * 1024;
 
6371
      } else {
 
6372
 
7179
6373
        Session*  session;
7180
6374
 
7181
 
        session= getTable()->in_use;
 
6375
        session= table->in_use;
7182
6376
        assert(session);
7183
6377
 
7184
6378
        push_warning_printf(
7193
6387
          ib_table->name);
7194
6388
 
7195
6389
        stats.delete_length = 0;
7196
 
      } else {
7197
 
        stats.delete_length = avail_space * 1024;
7198
6390
      }
 
6391
 
 
6392
      row_mysql_unlock_data_dictionary(prebuilt->trx);
7199
6393
    }
7200
6394
 
7201
6395
    stats.check_time = 0;
7208
6402
  }
7209
6403
 
7210
6404
  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;
 
6405
    index = dict_table_get_first_index(ib_table);
7216
6406
 
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);
 
6407
    if (prebuilt->clust_index_was_generated) {
 
6408
      index = dict_table_get_next_index(index);
7224
6409
    }
7225
6410
 
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
 
 
 
6411
    for (i = 0; i < table->getShare()->sizeKeys(); i++) {
7237
6412
      if (index == NULL) {
7238
 
        errmsg_printf(error::ERROR, "Table %s contains fewer "
 
6413
        errmsg_printf(ERRMSG_LVL_ERROR, "Table %s contains fewer "
7239
6414
            "indexes inside InnoDB than "
7240
6415
            "are defined in the MySQL "
7241
6416
            ".frm file. Have you mixed up "
7247
6422
        break;
7248
6423
      }
7249
6424
 
7250
 
      for (j = 0; j < getTable()->key_info[i].key_parts; j++) {
 
6425
      for (j = 0; j < table->key_info[i].key_parts; j++) {
7251
6426
 
7252
6427
        if (j + 1 > index->n_uniq) {
7253
 
          errmsg_printf(error::ERROR, 
 
6428
          errmsg_printf(ERRMSG_LVL_ERROR, 
7254
6429
"Index %s of %s has %lu columns unique inside InnoDB, but MySQL is asking "
7255
6430
"statistics for %lu columns. Have you mixed up .frm files from different "
7256
6431
"installations? "
7281
6456
          rec_per_key = 1;
7282
6457
        }
7283
6458
 
7284
 
        getTable()->key_info[i].rec_per_key[j]=
 
6459
        table->key_info[i].rec_per_key[j]=
7285
6460
          rec_per_key >= ~(ulong) 0 ? ~(ulong) 0 :
7286
6461
          (ulong) rec_per_key;
7287
6462
      }
 
6463
 
 
6464
      index = dict_table_get_next_index(index);
7288
6465
    }
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
6466
  }
7296
6467
 
7297
6468
  if (flag & HA_STATUS_ERRKEY) {
7304
6475
 
7305
6476
    if (err_index) {
7306
6477
      errkey = (unsigned int)
7307
 
        innobase_get_mysql_key_number_for_index(share, getTable(), ib_table,
7308
 
                                                err_index);
 
6478
        row_get_mysql_key_number_for_index(err_index);
7309
6479
    } else {
7310
6480
      errkey = (unsigned int) prebuilt->trx->error_key_num;
7311
6481
    }
7312
6482
  }
7313
6483
 
7314
 
  if ((flag & HA_STATUS_AUTO) && getTable()->found_next_number_field) {
 
6484
  if ((flag & HA_STATUS_AUTO) && table->found_next_number_field) {
7315
6485
    stats.auto_increment_value = innobase_peek_autoinc();
7316
6486
  }
7317
6487
 
7318
 
func_exit:
7319
6488
  prebuilt->trx->op_info = (char*)"";
7320
6489
 
7321
6490
  return(0);
7348
6517
/*===============*/
7349
6518
  Session*  session)  /*!< in: user thread handle */
7350
6519
{
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;
 
6520
  ulint   ret;
7356
6521
 
7357
 
  assert(session == getTable()->in_use);
 
6522
  assert(session == table->in_use);
7358
6523
  ut_a(prebuilt->trx);
7359
6524
  ut_a(prebuilt->trx->magic_n == TRX_MAGIC_N);
7360
6525
  ut_a(prebuilt->trx == session_to_trx(session));
7363
6528
    /* Build the template; we will use a dummy template
7364
6529
    in index scans done in checking */
7365
6530
 
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);
 
6531
    build_template(prebuilt, NULL, table, ROW_MYSQL_WHOLE_ROW);
 
6532
  }
 
6533
 
 
6534
  ret = row_check_table_for_mysql(prebuilt);
 
6535
 
 
6536
  if (ret == DB_SUCCESS) {
 
6537
    return(HA_ADMIN_OK);
 
6538
  }
 
6539
 
 
6540
  return(HA_ADMIN_CORRUPT);
7503
6541
}
7504
6542
 
7505
6543
/*************************************************************//**
7525
6563
    return((char*)comment); /* string too long */
7526
6564
  }
7527
6565
 
7528
 
  update_session(getTable()->in_use);
 
6566
  update_session(table->in_use);
7529
6567
 
7530
6568
  prebuilt->trx->op_info = (char*)"returning table comment";
7531
6569
 
7596
6634
  external_lock(). To be safe, update the session of the current table
7597
6635
  handle. */
7598
6636
 
7599
 
  update_session(getTable()->in_use);
 
6637
  update_session(table->in_use);
7600
6638
 
7601
6639
  prebuilt->trx->op_info = (char*)"getting info on foreign keys";
7602
6640
 
7617
6655
  flen = ftell(srv_dict_tmpfile);
7618
6656
  if (flen < 0) {
7619
6657
    flen = 0;
 
6658
  } else if (flen > 64000 - 1) {
 
6659
    flen = 64000 - 1;
7620
6660
  }
7621
6661
 
7622
6662
  /* allocate buffer for the string, and
7643
6683
  dict_foreign_t* foreign;
7644
6684
 
7645
6685
  ut_a(prebuilt != NULL);
7646
 
  update_session(getTable()->in_use);
 
6686
  update_session(table->in_use);
7647
6687
  prebuilt->trx->op_info = (char*)"getting list of foreign keys";
7648
6688
  trx_search_latch_release_if_reserved(prebuilt->trx);
7649
6689
  mutex_enter(&(dict_sys->mutex));
7676
6716
      i++;
7677
6717
    }
7678
6718
    db_name[i] = 0;
7679
 
    ulen= identifier::Table::filename_to_tablename(db_name, uname, sizeof(uname));
 
6719
    ulen= TableIdentifier::filename_to_tablename(db_name, uname, sizeof(uname));
7680
6720
    LEX_STRING *tmp_referenced_db = session->make_lex_string(NULL, uname, ulen, true);
7681
6721
 
7682
6722
    /* Table name */
7683
6723
    tmp_buff += i + 1;
7684
 
    ulen= identifier::Table::filename_to_tablename(tmp_buff, uname, sizeof(uname));
 
6724
    ulen= TableIdentifier::filename_to_tablename(tmp_buff, uname, sizeof(uname));
7685
6725
    LEX_STRING *tmp_referenced_table = session->make_lex_string(NULL, uname, ulen, true);
7686
6726
 
7687
6727
    /** Foreign Fields **/
7759
6799
                              tmp_foreign_fields, tmp_referenced_fields);
7760
6800
 
7761
6801
    ForeignKeyInfo *pf_key_info = (ForeignKeyInfo *)
7762
 
      session->getMemRoot()->duplicate(&f_key_info, sizeof(ForeignKeyInfo));
 
6802
      session->memdup(&f_key_info, sizeof(ForeignKeyInfo));
7763
6803
    f_key_list->push_back(pf_key_info);
7764
6804
    foreign = UT_LIST_GET_NEXT(foreign_list, foreign);
7765
6805
  }
7781
6821
{
7782
6822
  bool  can_switch;
7783
6823
 
7784
 
  ut_a(prebuilt->trx == session_to_trx(getTable()->in_use));
 
6824
  ut_a(prebuilt->trx == session_to_trx(table->in_use));
7785
6825
 
7786
6826
  prebuilt->trx->op_info =
7787
6827
      "determining if there are foreign key constraints";
7869
6909
      either, because the calling threads may change.
7870
6910
      CAREFUL HERE, OR MEMORY CORRUPTION MAY OCCUR! */
7871
6911
    case HA_EXTRA_IGNORE_DUP_KEY:
7872
 
      session_to_trx(getTable()->in_use)->duplicates |= TRX_DUP_IGNORE;
 
6912
      session_to_trx(table->in_use)->duplicates |= TRX_DUP_IGNORE;
7873
6913
      break;
7874
6914
    case HA_EXTRA_WRITE_CAN_REPLACE:
7875
 
      session_to_trx(getTable()->in_use)->duplicates |= TRX_DUP_REPLACE;
 
6915
      session_to_trx(table->in_use)->duplicates |= TRX_DUP_REPLACE;
7876
6916
      break;
7877
6917
    case HA_EXTRA_WRITE_CANNOT_REPLACE:
7878
 
      session_to_trx(getTable()->in_use)->duplicates &= ~TRX_DUP_REPLACE;
 
6918
      session_to_trx(table->in_use)->duplicates &= ~TRX_DUP_REPLACE;
7879
6919
      break;
7880
6920
    case HA_EXTRA_NO_IGNORE_DUP_KEY:
7881
 
      session_to_trx(getTable()->in_use)->duplicates &=
 
6921
      session_to_trx(table->in_use)->duplicates &=
7882
6922
        ~(TRX_DUP_IGNORE | TRX_DUP_REPLACE);
7883
6923
      break;
7884
6924
    default:/* Do nothing */
8014
7054
{
8015
7055
  trx_t*      trx;
8016
7056
  static const char truncated_msg[] = "... truncated...\n";
8017
 
  const long    MAX_STATUS_SIZE = 1048576;
 
7057
  const long    MAX_STATUS_SIZE = 64000;
8018
7058
  ulint     trx_list_start = ULINT_UNDEFINED;
8019
7059
  ulint     trx_list_end = ULINT_UNDEFINED;
8020
7060
 
8032
7072
 
8033
7073
  mutex_enter(&srv_monitor_file_mutex);
8034
7074
  rewind(srv_monitor_file);
8035
 
  srv_printf_innodb_monitor(srv_monitor_file, FALSE,
 
7075
  srv_printf_innodb_monitor(srv_monitor_file,
8036
7076
        &trx_list_start, &trx_list_end);
8037
7077
  flen = ftell(srv_monitor_file);
8038
7078
  os_file_set_eof(srv_monitor_file);
8043
7083
 
8044
7084
  if (flen > MAX_STATUS_SIZE) {
8045
7085
    usable_len = MAX_STATUS_SIZE;
8046
 
    srv_truncated_status_writes++;
8047
7086
  } else {
8048
7087
    usable_len = flen;
8049
7088
  }
8079
7118
 
8080
7119
  mutex_exit(&srv_monitor_file_mutex);
8081
7120
 
8082
 
  stat_print(session, innobase_engine_name, strlen(innobase_engine_name),
8083
 
             STRING_WITH_LEN(""), str, flen);
 
7121
  bool result = FALSE;
8084
7122
 
 
7123
  if (stat_print(session, innobase_engine_name, strlen(innobase_engine_name),
 
7124
      STRING_WITH_LEN(""), str, flen)) {
 
7125
    result= TRUE;
 
7126
  }
8085
7127
  free(str);
8086
7128
 
8087
7129
  return(FALSE);
8088
7130
}
8089
7131
 
8090
7132
/************************************************************************//**
8091
 
Implements the SHOW MUTEX STATUS command.
8092
 
@return true on failure false on success*/
 
7133
Implements the SHOW MUTEX STATUS command. . */
8093
7134
static
8094
7135
bool
8095
7136
innodb_mutex_show_status(
8097
7138
  plugin::StorageEngine*  engine,   /*!< in: the innodb StorageEngine */
8098
7139
  Session*  session,  /*!< in: the MySQL query thread of the
8099
7140
          caller */
8100
 
  stat_print_fn*  stat_print)   /*!< in: function for printing
8101
 
                                        statistics */
 
7141
  stat_print_fn*  stat_print)
8102
7142
{
8103
7143
  char buf1[IO_SIZE], buf2[IO_SIZE];
8104
7144
  mutex_t*  mutex;
8105
7145
  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
7146
#ifdef UNIV_DEBUG
8111
7147
  ulint   rw_lock_count= 0;
8112
7148
  ulint   rw_lock_count_spin_loop= 0;
8120
7156
 
8121
7157
  mutex_enter(&mutex_list_mutex);
8122
7158
 
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;
 
7159
  mutex = UT_LIST_GET_FIRST(mutex_list);
 
7160
 
 
7161
  while (mutex != NULL) {
 
7162
    if (mutex->count_os_wait == 0
 
7163
        || buf_pool_is_block_mutex(mutex)) {
 
7164
      goto next_mutex;
8134
7165
    }
8135
7166
#ifdef UNIV_DEBUG
8136
7167
    if (mutex->mutex_type != 1) {
8157
7188
          return(1);
8158
7189
        }
8159
7190
      }
8160
 
    } else {
 
7191
    }
 
7192
    else {
8161
7193
      rw_lock_count += mutex->count_using;
8162
7194
      rw_lock_count_spin_loop += mutex->count_spin_loop;
8163
7195
      rw_lock_count_spin_rounds += mutex->count_spin_rounds;
8169
7201
    buf1len= snprintf(buf1, sizeof(buf1), "%s:%lu",
8170
7202
          mutex->cfile_name, (ulong) mutex->cline);
8171
7203
    buf2len= snprintf(buf2, sizeof(buf2), "os_waits=%lu",
8172
 
                      (ulong) mutex->count_os_wait);
 
7204
          mutex->count_os_wait);
8173
7205
 
8174
7206
    if (stat_print(session, innobase_engine_name,
8175
7207
             engine_name_len, buf1, buf1len,
8178
7210
      return(1);
8179
7211
    }
8180
7212
#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
 
    }
 
7213
 
 
7214
next_mutex:
 
7215
    mutex = UT_LIST_GET_NEXT(list, mutex);
8198
7216
  }
8199
7217
 
8200
7218
  mutex_exit(&mutex_list_mutex);
8201
7219
 
8202
7220
  mutex_enter(&rw_lock_list_mutex);
8203
7221
 
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
 
    }
 
7222
  lock = UT_LIST_GET_FIRST(rw_lock_list);
 
7223
 
 
7224
  while (lock != NULL) {
 
7225
    if (lock->count_os_wait
 
7226
                    && !buf_pool_is_block_lock(lock)) {
 
7227
      buf1len= snprintf(buf1, sizeof(buf1), "%s:%lu",
 
7228
                                    lock->cfile_name, (unsigned long) lock->cline);
 
7229
      buf2len= snprintf(buf2, sizeof(buf2),
 
7230
                                    "os_waits=%lu", lock->count_os_wait);
 
7231
 
 
7232
      if (stat_print(session, innobase_engine_name,
 
7233
               engine_name_len, buf1, buf1len,
 
7234
               buf2, buf2len)) {
 
7235
        mutex_exit(&rw_lock_list_mutex);
 
7236
        return(1);
 
7237
      }
 
7238
    }
 
7239
    lock = UT_LIST_GET_NEXT(list, lock);
8244
7240
  }
8245
7241
 
8246
7242
  mutex_exit(&rw_lock_list_mutex);
8247
7243
 
8248
7244
#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));
 
7245
  buf2len= my_snprintf(buf2, sizeof(buf2),
 
7246
    "count=%lu, spin_waits=%lu, spin_rounds=%lu, "
 
7247
    "os_waits=%lu, os_yields=%lu, os_wait_times=%lu",
 
7248
    rw_lock_count, rw_lock_count_spin_loop,
 
7249
    rw_lock_count_spin_rounds,
 
7250
    rw_lock_count_os_wait, rw_lock_count_os_yield,
 
7251
    (ulong) (rw_lock_wait_time/1000));
8258
7252
 
8259
7253
  if (stat_print(session, innobase_engine_name, engine_name_len,
8260
7254
      STRING_WITH_LEN("rw_lock_mutexes"), buf2, buf2len)) {
8289
7283
static INNOBASE_SHARE* get_share(const char* table_name)
8290
7284
{
8291
7285
  INNOBASE_SHARE *share;
8292
 
  boost::mutex::scoped_lock scopedLock(innobase_share_mutex);
 
7286
  pthread_mutex_lock(&innobase_share_mutex);
8293
7287
 
8294
7288
  ulint fold = ut_fold_string(table_name);
8295
7289
 
8299
7293
        !strcmp(share->table_name, table_name));
8300
7294
 
8301
7295
  if (!share) {
 
7296
 
 
7297
    uint length = (uint) strlen(table_name);
 
7298
 
8302
7299
    /* TODO: invoke HASH_MIGRATE if innobase_open_tables
8303
7300
    grows too big */
8304
7301
 
8305
 
    share= new INNOBASE_SHARE(table_name);
 
7302
    share = (INNOBASE_SHARE *) malloc(sizeof(*share)+length+1);
 
7303
                memset(share, 0, sizeof(*share)+length+1);
 
7304
 
 
7305
    share->table_name = (char*) memcpy(share + 1,
 
7306
               table_name, length + 1);
8306
7307
 
8307
7308
    HASH_INSERT(INNOBASE_SHARE, table_name_hash,
8308
7309
          innobase_open_tables, fold, share);
8309
7310
 
8310
7311
    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
7312
  }
8317
7313
 
8318
7314
  share->use_count++;
 
7315
  pthread_mutex_unlock(&innobase_share_mutex);
8319
7316
 
8320
7317
  return(share);
8321
7318
}
8322
7319
 
8323
7320
static void free_share(INNOBASE_SHARE* share)
8324
7321
{
8325
 
  boost::mutex::scoped_lock scopedLock(innobase_share_mutex);
 
7322
  pthread_mutex_lock(&innobase_share_mutex);
8326
7323
 
8327
7324
#ifdef UNIV_DEBUG
8328
7325
  INNOBASE_SHARE* share2;
8341
7338
 
8342
7339
    HASH_DELETE(INNOBASE_SHARE, table_name_hash,
8343
7340
          innobase_open_tables, fold, share);
8344
 
    share->lock.deinit();
8345
 
 
8346
 
    /* Free any memory from index translation table */
8347
 
    free(share->idx_trans_tbl.index_mapping);
8348
 
 
8349
 
    delete share;
 
7341
    thr_lock_delete(&share->lock);
 
7342
    free(share);
8350
7343
 
8351
7344
    /* TODO: invoke HASH_MIGRATE if innobase_open_tables
8352
7345
    shrinks too much */
8353
7346
  }
 
7347
 
 
7348
  pthread_mutex_unlock(&innobase_share_mutex);
8354
7349
}
8355
7350
 
8356
7351
/*****************************************************************//**
8385
7380
  trx = check_trx_exists(session);
8386
7381
 
8387
7382
  assert(EQ_CURRENT_SESSION(session));
8388
 
  const uint32_t sql_command = session->getSqlCommand();
 
7383
  const uint32_t sql_command = session_sql_command(session);
8389
7384
 
8390
7385
  if (sql_command == SQLCOM_DROP_TABLE) {
8391
7386
 
8421
7416
    isolation_level = trx->isolation_level;
8422
7417
 
8423
7418
    if ((srv_locks_unsafe_for_binlog
8424
 
         || isolation_level <= TRX_ISO_READ_COMMITTED)
 
7419
         || isolation_level == TRX_ISO_READ_COMMITTED)
8425
7420
        && isolation_level != TRX_ISO_SERIALIZABLE
8426
7421
        && (lock_type == TL_READ || lock_type == TL_READ_NO_INSERT)
8427
7422
        && (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)) {
 
7423
      || sql_command == SQLCOM_UPDATE
 
7424
      || sql_command == SQLCOM_CREATE_TABLE)) {
8432
7425
 
8433
7426
      /* If we either have innobase_locks_unsafe_for_binlog
8434
7427
      option set or this session is using READ COMMITTED
8435
7428
      isolation level and isolation level of the transaction
8436
7429
      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. */
 
7430
      INSERT INTO...SELECT or UPDATE ... = (SELECT ...) or
 
7431
      CREATE  ... SELECT... without FOR UPDATE or
 
7432
      IN SHARE MODE in select, then we use consistent
 
7433
      read for select. */
8442
7434
 
8443
7435
      prebuilt->select_lock_type = LOCK_NONE;
8444
7436
      prebuilt->stored_select_lock_type = LOCK_NONE;
8471
7463
 
8472
7464
    if ((lock_type >= TL_WRITE_CONCURRENT_INSERT
8473
7465
         && lock_type <= TL_WRITE)
8474
 
        && ! session->doing_tablespace_operation()
 
7466
        && !session_tablespace_op(session)
8475
7467
        && sql_command != SQLCOM_TRUNCATE
8476
7468
        && sql_command != SQLCOM_CREATE_TABLE) {
8477
7469
 
8517
7509
  *value = dict_table_autoinc_read(prebuilt->table);
8518
7510
 
8519
7511
  /* 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
 
  }
 
7512
  ut_a(*value != 0);
8524
7513
 
8525
7514
  return(DB_SUCCESS);
8526
7515
}
8527
7516
 
8528
7517
/*******************************************************************//**
8529
 
This function reads the global auto-inc counter. It doesn't use the
 
7518
This function reads the global auto-inc counter. It doesn't use the 
8530
7519
AUTOINC lock even if the lock mode is set to TRADITIONAL.
8531
7520
@return the autoinc value */
8532
7521
UNIV_INTERN
8546
7535
 
8547
7536
  auto_inc = dict_table_autoinc_read(innodb_table);
8548
7537
 
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
 
  }
 
7538
  ut_a(auto_inc > 0);
8553
7539
 
8554
7540
  dict_table_autoinc_unlock(innodb_table);
8555
7541
 
8578
7564
  uint64_t  autoinc = 0;
8579
7565
 
8580
7566
  /* Prepare prebuilt->trx in the table handle */
8581
 
  update_session(getTable()->in_use);
 
7567
  update_session(table->in_use);
8582
7568
 
8583
7569
  error = innobase_get_autoinc(&autoinc);
8584
7570
 
8602
7588
  invoking this method. So we are not sure if it's guaranteed to
8603
7589
  be 0 or not. */
8604
7590
 
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
7591
  /* Called for the first time ? */
8610
7592
  if (trx->n_autoinc_rows == 0) {
8611
7593
 
8622
7604
  /* Not in the middle of a mult-row INSERT. */
8623
7605
  } else if (prebuilt->autoinc_last_value == 0) {
8624
7606
    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
7607
  }
8631
7608
 
8632
7609
  *nb_reserved_values = trx->n_autoinc_rows;
8634
7611
  /* This all current style autoinc. */
8635
7612
  {
8636
7613
    uint64_t  need;
8637
 
    uint64_t  current;
8638
7614
    uint64_t  next_value;
8639
 
 
8640
 
    current = *first_value > col_max_value ? autoinc : *first_value;
 
7615
    uint64_t  col_max_value;
 
7616
 
 
7617
    /* We need the upper limit of the col type to check for
 
7618
    whether we update the table autoinc counter or not. */
 
7619
    col_max_value = innobase_get_int_col_max_value(
 
7620
      table->next_number_field);
 
7621
 
8641
7622
    need = *nb_reserved_values * increment;
8642
7623
 
8643
7624
    /* Compute the last value in the interval */
8644
 
    next_value = innobase_next_autoinc(current, need, offset, col_max_value);
 
7625
    next_value = innobase_next_autoinc(
 
7626
      *first_value, need, offset, col_max_value);
8645
7627
 
8646
7628
    prebuilt->autoinc_last_value = next_value;
8647
7629
 
8678
7660
{
8679
7661
  int error;
8680
7662
 
8681
 
  update_session(getTable()->in_use);
 
7663
  update_session(table->in_use);
8682
7664
 
8683
7665
  error = row_lock_table_autoinc_for_mysql(prebuilt);
8684
7666
 
8703
7685
/* See comment in Cursor.cc */
8704
7686
UNIV_INTERN
8705
7687
bool
8706
 
InnobaseEngine::get_error_message(int, String *buf) const
 
7688
InnobaseEngine::get_error_message(int, String *buf)
8707
7689
{
8708
7690
  trx_t*  trx = check_trx_exists(current_session);
8709
7691
 
8744
7726
  /* Do a type-aware comparison of primary key fields. PK fields
8745
7727
  are always NOT NULL, so no checks for NULL are performed. */
8746
7728
 
8747
 
  key_part = getTable()->key_info[getTable()->getShare()->getPrimaryKey()].key_part;
 
7729
  key_part = table->key_info[table->getShare()->getPrimaryKey()].key_part;
8748
7730
 
8749
7731
  key_part_end = key_part
8750
 
      + getTable()->key_info[getTable()->getShare()->getPrimaryKey()].key_parts;
 
7732
      + table->key_info[table->getShare()->getPrimaryKey()].key_parts;
8751
7733
 
8752
7734
  for (; key_part != key_part_end; ++key_part) {
8753
7735
    field = key_part->field;
8787
7769
finds charset information and returns length of prefix_len characters in the
8788
7770
index field in bytes.
8789
7771
@return number of bytes occupied by the first n characters */
 
7772
extern "C" UNIV_INTERN
 
7773
ulint
 
7774
innobase_get_at_most_n_mbchars(
 
7775
/*===========================*/
 
7776
  ulint charset_id, /*!< in: character set id */
 
7777
  ulint prefix_len, /*!< in: prefix length in bytes of the index
 
7778
        (this has to be divided by mbmaxlen to get the
 
7779
        number of CHARACTERS n in the prefix) */
 
7780
  ulint data_len,   /*!< in: length of the string in bytes */
 
7781
  const char* str); /*!< in: character string */
8790
7782
 
8791
7783
ulint
8792
7784
innobase_get_at_most_n_mbchars(
8870
7862
  trx->detailed_error[0]= '\0';
8871
7863
 
8872
7864
  /* Set the isolation level of the transaction. */
8873
 
  trx->isolation_level= innobase_map_isolation_level(session->getTxIsolation());
 
7865
  trx->isolation_level= innobase_map_isolation_level((enum_tx_isolation) session_tx_isolation(session));
8874
7866
}
8875
7867
 
8876
7868
void
8885
7877
 
8886
7878
  innobase_release_stat_resources(trx);
8887
7879
 
 
7880
  if (! session_test_options(session, OPTION_NOT_AUTOCOMMIT | OPTION_BEGIN))
 
7881
  {
 
7882
    if (trx->conc_state != TRX_NOT_STARTED)
 
7883
    {
 
7884
      commit(session, TRUE);
 
7885
    }
 
7886
  }
 
7887
  else
 
7888
  {
 
7889
    if (trx->isolation_level <= TRX_ISO_READ_COMMITTED &&
 
7890
        trx->global_read_view)
 
7891
    {
 
7892
      /* At low transaction isolation levels we let
 
7893
      each consistent read set its own snapshot */
 
7894
      read_view_close_for_mysql(trx);
 
7895
    }
 
7896
  }
8888
7897
}
8889
7898
 
8890
7899
/*******************************************************************//**
8913
7922
    return(0);
8914
7923
  }
8915
7924
 
8916
 
  session->get_xid(reinterpret_cast<DrizzleXid*>(&trx->xid));
 
7925
  session->get_xid(reinterpret_cast<DRIZZLE_XID*>(&trx->xid));
8917
7926
 
8918
7927
  /* Release a possible FIFO ticket and search latch. Since we will
8919
7928
  reserve the kernel mutex, we have to release the search system latch
8954
7963
  return(error);
8955
7964
}
8956
7965
 
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
7966
/*******************************************************************//**
8984
7967
This function is used to recover X/Open XA distributed transactions.
8985
7968
@return number of prepared transactions stored in xid_list */
9091
8074
}
9092
8075
 
9093
8076
/************************************************************//**
 
8077
Validate the file format check value, is it one of "on" or "off",
 
8078
as a side effect it sets the srv_check_file_format_at_startup variable.
 
8079
@return true if config value one of "on" or  "off" */
 
8080
static
 
8081
bool
 
8082
innobase_file_format_check_on_off(
 
8083
/*==============================*/
 
8084
  const char* format_check) /*!< in: parameter value */
 
8085
{
 
8086
  bool    ret = true;
 
8087
 
 
8088
  if (!innobase_strcasecmp(format_check, "off")) {
 
8089
 
 
8090
    /* Set the value to disable checking. */
 
8091
    srv_check_file_format_at_startup = DICT_TF_FORMAT_MAX + 1;
 
8092
 
 
8093
  } else if (!innobase_strcasecmp(format_check, "on")) {
 
8094
 
 
8095
    /* Set the value to the lowest supported format. */
 
8096
    srv_check_file_format_at_startup = DICT_TF_FORMAT_51;
 
8097
  } else {
 
8098
    ret = FALSE;
 
8099
  }
 
8100
 
 
8101
  return(ret);
 
8102
}
 
8103
 
 
8104
/************************************************************//**
9094
8105
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 */
 
8106
sets the srv_check_file_format_at_startup variable.
 
8107
@return true if valid config value */
9097
8108
static
9098
 
int
9099
 
innobase_file_format_validate_and_set(
 
8109
bool
 
8110
innobase_file_format_check_validate(
9100
8111
/*================================*/
9101
 
  const char* format_max) /*!< in: parameter value */
 
8112
  const char* format_check) /*!< in: parameter value */
9102
8113
{
9103
8114
  uint    format_id;
 
8115
  bool    ret = true;
9104
8116
 
9105
 
  format_id = innobase_file_format_name_lookup(format_max);
 
8117
  format_id = innobase_file_format_name_lookup(format_check);
9106
8118
 
9107
8119
  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
 
 
 
8120
    srv_check_file_format_at_startup = format_id;
 
8121
  } else {
 
8122
    ret = false;
 
8123
  }
 
8124
 
 
8125
  return(ret);
 
8126
}
 
8127
 
 
8128
/*************************************************************//**
 
8129
Check if it is a valid file format. This function is registered as
 
8130
a callback with MySQL.
 
8131
@return 0 for valid file format */
 
8132
static
 
8133
int
 
8134
innodb_file_format_name_validate(
 
8135
/*=============================*/
 
8136
  Session*      , /*!< in: thread handle */
 
8137
  drizzle_sys_var*  , /*!< in: pointer to system
 
8138
            variable */
 
8139
  void*       save, /*!< out: immediate result
 
8140
            for update function */
 
8141
  drizzle_value*    value)  /*!< in: incoming string */
 
8142
{
 
8143
  const char* file_format_input;
 
8144
  char    buff[STRING_BUFFER_USUAL_SIZE];
 
8145
  int   len = sizeof(buff);
 
8146
 
 
8147
  ut_a(save != NULL);
 
8148
  ut_a(value != NULL);
 
8149
 
 
8150
  file_format_input = value->val_str(value, buff, &len);
 
8151
 
 
8152
  if (file_format_input != NULL) {
 
8153
    uint  format_id;
 
8154
 
 
8155
    format_id = innobase_file_format_name_lookup(
 
8156
      file_format_input);
 
8157
 
 
8158
    if (format_id <= DICT_TF_FORMAT_MAX) {
 
8159
 
 
8160
      *static_cast<const char**>(save) = file_format_input;
 
8161
      return(0);
 
8162
    }
 
8163
  }
 
8164
 
 
8165
  *static_cast<const char**>(save) = NULL;
 
8166
  return(1);
 
8167
}
 
8168
 
 
8169
/****************************************************************//**
 
8170
Update the system variable innodb_file_format using the "saved"
 
8171
value. This function is registered as a callback with MySQL. */
 
8172
static
 
8173
void
 
8174
innodb_file_format_name_update(
 
8175
/*===========================*/
 
8176
  Session*      ,   /*!< in: thread handle */
 
8177
  drizzle_sys_var*  ,   /*!< in: pointer to
 
8178
              system variable */
 
8179
  void*       var_ptr,  /*!< out: where the
 
8180
              formal string goes */
 
8181
  const void*     save)   /*!< in: immediate result
 
8182
              from check function */
 
8183
{
 
8184
  const char* format_name;
 
8185
 
 
8186
  ut_a(var_ptr != NULL);
 
8187
  ut_a(save != NULL);
 
8188
 
 
8189
  format_name = *static_cast<const char*const*>(save);
 
8190
 
 
8191
  if (format_name) {
 
8192
    uint  format_id;
 
8193
 
 
8194
    format_id = innobase_file_format_name_lookup(format_name);
 
8195
 
 
8196
    if (format_id <= DICT_TF_FORMAT_MAX) {
 
8197
      srv_file_format = format_id;
 
8198
    }
 
8199
  }
 
8200
 
 
8201
  *static_cast<const char**>(var_ptr)
 
8202
    = trx_sys_file_format_id_to_name(srv_file_format);
 
8203
}
 
8204
 
 
8205
/*************************************************************//**
 
8206
Check if valid argument to innodb_file_format_check. This
 
8207
function is registered as a callback with MySQL.
 
8208
@return 0 for valid file format */
 
8209
static
 
8210
int
 
8211
innodb_file_format_check_validate(
 
8212
/*==============================*/
 
8213
  Session*      , /*!< in: thread handle */
 
8214
  drizzle_sys_var*  , /*!< in: pointer to system
 
8215
            variable */
 
8216
  void*       save, /*!< out: immediate result
 
8217
            for update function */
 
8218
  drizzle_value*    value)  /*!< in: incoming string */
 
8219
{
 
8220
  const char* file_format_input;
 
8221
  char    buff[STRING_BUFFER_USUAL_SIZE];
 
8222
  int   len = sizeof(buff);
 
8223
 
 
8224
  ut_a(save != NULL);
 
8225
  ut_a(value != NULL);
 
8226
 
 
8227
  file_format_input = value->val_str(value, buff, &len);
 
8228
 
 
8229
  if (file_format_input != NULL) {
 
8230
 
 
8231
    /* Check if user set on/off, we want to print a suitable
 
8232
    message if they did so. */
 
8233
 
 
8234
    if (innobase_file_format_check_on_off(file_format_input)) {
 
8235
      errmsg_printf(ERRMSG_LVL_WARN, 
 
8236
        "InnoDB: invalid innodb_file_format_check "
 
8237
        "value; on/off can only be set at startup or "
 
8238
        "in the configuration file");
 
8239
    } else if (innobase_file_format_check_validate(
 
8240
        file_format_input)) {
 
8241
 
 
8242
      *static_cast<const char**>(save) = file_format_input;
 
8243
 
 
8244
      return(0);
 
8245
 
 
8246
    } else {
 
8247
      errmsg_printf(ERRMSG_LVL_WARN, 
 
8248
        "InnoDB: invalid innodb_file_format_check "
 
8249
        "value; can be any format up to %s "
 
8250
        "or its equivalent numeric id",
 
8251
        trx_sys_file_format_id_to_name(
 
8252
          DICT_TF_FORMAT_MAX));
 
8253
    }
 
8254
  }
 
8255
 
 
8256
  *static_cast<const char**>(save) = NULL;
 
8257
  return(1);
 
8258
}
 
8259
 
 
8260
/****************************************************************//**
 
8261
Update the system variable innodb_file_format_check using the "saved"
 
8262
value. This function is registered as a callback with MySQL. */
 
8263
static
 
8264
void
 
8265
innodb_file_format_check_update(
 
8266
/*============================*/
 
8267
  Session*      session,  /*!< in: thread handle */
 
8268
  drizzle_sys_var*  ,   /*!< in: pointer to
 
8269
              system variable */
 
8270
  void*       var_ptr,  /*!< out: where the
 
8271
              formal string goes */
 
8272
  const void*     save)   /*!< in: immediate result
 
8273
              from check function */
 
8274
{
 
8275
  const char* format_name_in;
 
8276
  const char**  format_name_out;
 
8277
  uint    format_id;
 
8278
 
 
8279
  ut_a(save != NULL);
 
8280
  ut_a(var_ptr != NULL);
 
8281
 
 
8282
  format_name_in = *static_cast<const char*const*>(save);
 
8283
 
 
8284
  if (!format_name_in) {
 
8285
 
 
8286
    return;
 
8287
  }
 
8288
 
 
8289
  format_id = innobase_file_format_name_lookup(format_name_in);
 
8290
 
 
8291
  if (format_id > DICT_TF_FORMAT_MAX) {
 
8292
    /* DEFAULT is "on", which is invalid at runtime. */
 
8293
    push_warning_printf(session, DRIZZLE_ERROR::WARN_LEVEL_WARN,
 
8294
            ER_WRONG_ARGUMENTS,
 
8295
            "Ignoring SET innodb_file_format=%s",
 
8296
            format_name_in);
 
8297
    return;
 
8298
  }
 
8299
 
 
8300
  format_name_out = static_cast<const char**>(var_ptr);
 
8301
 
 
8302
  /* Update the max format id in the system tablespace. */
 
8303
  if (trx_sys_file_format_max_set(format_id, format_name_out)) {
 
8304
    ut_print_timestamp(stderr);
 
8305
    fprintf(stderr,
 
8306
      " [Info] InnoDB: the file format in the system "
 
8307
      "tablespace is now set to %s.\n", *format_name_out);
 
8308
  }
 
8309
}
 
8310
 
 
8311
/****************************************************************//**
 
8312
Update the system variable innodb_adaptive_hash_index using the "saved"
 
8313
value. This function is registered as a callback with MySQL. */
 
8314
static
 
8315
void
 
8316
innodb_adaptive_hash_index_update(
 
8317
/*==============================*/
 
8318
  Session*      ,   /*!< in: thread handle */
 
8319
  drizzle_sys_var*  ,   /*!< in: pointer to
 
8320
              system variable */
 
8321
  void*       , /*!< out: where the
 
8322
              formal string goes */
 
8323
  const void*     save)   /*!< in: immediate result
 
8324
              from check function */
 
8325
{
 
8326
  if (*(bool*) save) {
 
8327
    btr_search_enable();
 
8328
  } else {
 
8329
    btr_search_disable();
 
8330
  }
 
8331
}
 
8332
 
 
8333
/*************************************************************//**
 
8334
Check if it is a valid value of innodb_change_buffering.  This function is
 
8335
registered as a callback with MySQL.
 
8336
@return 0 for valid innodb_change_buffering */
 
8337
static
 
8338
int
 
8339
innodb_change_buffering_validate(
 
8340
/*=============================*/
 
8341
  Session*      , /*!< in: thread handle */
 
8342
  drizzle_sys_var*  , /*!< in: pointer to system
 
8343
            variable */
 
8344
  void*       save, /*!< out: immediate result
 
8345
            for update function */
 
8346
  drizzle_value*    value)  /*!< in: incoming string */
 
8347
{
 
8348
  const char* change_buffering_input;
 
8349
  char    buff[STRING_BUFFER_USUAL_SIZE];
 
8350
  int   len = sizeof(buff);
 
8351
 
 
8352
  ut_a(save != NULL);
 
8353
  ut_a(value != NULL);
 
8354
 
 
8355
  change_buffering_input = value->val_str(value, buff, &len);
 
8356
 
 
8357
  if (change_buffering_input != NULL) {
 
8358
    ulint use;
 
8359
 
 
8360
    for (use = 0; use < UT_ARR_SIZE(innobase_change_buffering_values);
 
8361
         use++) {
 
8362
      if (!innobase_strcasecmp(
 
8363
            change_buffering_input,
 
8364
            innobase_change_buffering_values[use])) {
 
8365
        *(ibuf_use_t*) save = (ibuf_use_t) use;
 
8366
        return(0);
 
8367
      }
 
8368
    }
 
8369
  }
 
8370
 
 
8371
  return(1);
 
8372
}
 
8373
 
 
8374
/****************************************************************//**
 
8375
Update the system variable innodb_change_buffering using the "saved"
 
8376
value. This function is registered as a callback with MySQL. */
 
8377
static
 
8378
void
 
8379
innodb_change_buffering_update(
 
8380
/*===========================*/
 
8381
  Session*      ,   /*!< in: thread handle */
 
8382
  drizzle_sys_var*  ,   /*!< in: pointer to
 
8383
              system variable */
 
8384
  void*       var_ptr,  /*!< out: where the
 
8385
              formal string goes */
 
8386
  const void*     save)   /*!< in: immediate result
 
8387
              from check function */
 
8388
{
 
8389
  ut_a(var_ptr != NULL);
 
8390
  ut_a(save != NULL);
 
8391
  ut_a((*(ibuf_use_t*) save) < IBUF_USE_COUNT);
 
8392
 
 
8393
  ibuf_use = *(const ibuf_use_t*) save;
 
8394
 
 
8395
  *(const char**) var_ptr = innobase_change_buffering_values[ibuf_use];
 
8396
}
 
8397
 
 
8398
/* plugin options */
 
8399
static DRIZZLE_SYSVAR_BOOL(checksums, innobase_use_checksums,
 
8400
  PLUGIN_VAR_NOCMDARG | PLUGIN_VAR_READONLY,
 
8401
  "Enable InnoDB checksums validation (enabled by default). "
 
8402
  "Disable with --skip-innodb-checksums.",
 
8403
  NULL, NULL, TRUE);
 
8404
 
 
8405
static DRIZZLE_SYSVAR_STR(data_home_dir, innobase_data_home_dir,
 
8406
  PLUGIN_VAR_READONLY,
 
8407
  "The common part for InnoDB table spaces.",
 
8408
  NULL, NULL, NULL);
 
8409
 
 
8410
static DRIZZLE_SYSVAR_BOOL(doublewrite, innobase_use_doublewrite,
 
8411
  PLUGIN_VAR_NOCMDARG | PLUGIN_VAR_READONLY,
 
8412
  "Enable InnoDB doublewrite buffer (enabled by default). "
 
8413
  "Disable with --skip-innodb-doublewrite.",
 
8414
  NULL, NULL, TRUE);
 
8415
 
 
8416
static DRIZZLE_SYSVAR_ULONG(io_capacity, srv_io_capacity,
 
8417
  PLUGIN_VAR_RQCMDARG,
 
8418
  "Number of IOPs the server can do. Tunes the background IO rate",
 
8419
  NULL, NULL, 200, 100, ~0L, 0);
 
8420
 
 
8421
static DRIZZLE_SYSVAR_ULONG(fast_shutdown, innobase_fast_shutdown,
 
8422
  PLUGIN_VAR_OPCMDARG,
 
8423
  "Speeds up the shutdown process of the InnoDB storage engine. Possible "
 
8424
  "values are 0, 1 (faster)"
 
8425
  " or 2 (fastest - crash-like)"
 
8426
  ".",
 
8427
  NULL, NULL, 1, 0, 2, 0);
 
8428
 
 
8429
static DRIZZLE_SYSVAR_BOOL(file_per_table, srv_file_per_table,
 
8430
  PLUGIN_VAR_NOCMDARG,
 
8431
  "Stores each InnoDB table to an .ibd file in the database dir.",
 
8432
  NULL, NULL, FALSE);
 
8433
 
 
8434
static DRIZZLE_SYSVAR_STR(file_format, innobase_file_format_name,
 
8435
  PLUGIN_VAR_RQCMDARG,
 
8436
  "File format to use for new tables in .ibd files.",
 
8437
  innodb_file_format_name_validate,
 
8438
  innodb_file_format_name_update, "Antelope");
 
8439
 
 
8440
static DRIZZLE_SYSVAR_STR(file_format_check, innobase_file_format_check,
 
8441
  PLUGIN_VAR_OPCMDARG,
 
8442
  "The highest file format in the tablespace.",
 
8443
  innodb_file_format_check_validate,
 
8444
  innodb_file_format_check_update,
 
8445
  "on");
 
8446
 
 
8447
static DRIZZLE_SYSVAR_ULONG(flush_log_at_trx_commit, srv_flush_log_at_trx_commit,
 
8448
  PLUGIN_VAR_OPCMDARG,
 
8449
  "Set to 0 (write and flush once per second),"
 
8450
  " 1 (write and flush at each commit)"
 
8451
  " or 2 (write at commit, flush once per second).",
 
8452
  NULL, NULL, 1, 0, 2, 0);
 
8453
 
 
8454
static DRIZZLE_SYSVAR_STR(flush_method, innobase_unix_file_flush_method,
 
8455
  PLUGIN_VAR_RQCMDARG | PLUGIN_VAR_READONLY,
 
8456
  "With which method to flush data.", NULL, NULL, NULL);
 
8457
 
 
8458
#ifdef UNIV_LOG_ARCHIVE
 
8459
static DRIZZLE_SYSVAR_STR(log_arch_dir, innobase_log_arch_dir,
 
8460
  PLUGIN_VAR_RQCMDARG | PLUGIN_VAR_READONLY,
 
8461
  "Where full logs should be archived.", NULL, NULL, NULL);
 
8462
 
 
8463
static DRIZZLE_SYSVAR_BOOL(log_archive, innobase_log_archive,
 
8464
  PLUGIN_VAR_OPCMDARG | PLUGIN_VAR_READONLY,
 
8465
  "Set to 1 if you want to have logs archived.", NULL, NULL, FALSE);
 
8466
#endif /* UNIV_LOG_ARCHIVE */
 
8467
 
 
8468
static DRIZZLE_SYSVAR_STR(log_group_home_dir, innobase_log_group_home_dir,
 
8469
  PLUGIN_VAR_RQCMDARG | PLUGIN_VAR_READONLY,
 
8470
  "Path to InnoDB log files.", NULL, NULL, NULL);
 
8471
 
 
8472
static DRIZZLE_SYSVAR_ULONG(max_dirty_pages_pct, srv_max_buf_pool_modified_pct,
 
8473
  PLUGIN_VAR_RQCMDARG,
 
8474
  "Percentage of dirty pages allowed in bufferpool.",
 
8475
  NULL, NULL, 75, 0, 99, 0);
 
8476
 
 
8477
static DRIZZLE_SYSVAR_BOOL(adaptive_flushing, srv_adaptive_flushing,
 
8478
  PLUGIN_VAR_NOCMDARG,
 
8479
  "Attempt flushing dirty pages to avoid IO bursts at checkpoints.",
 
8480
  NULL, NULL, TRUE);
 
8481
 
 
8482
static DRIZZLE_SYSVAR_ULONG(max_purge_lag, srv_max_purge_lag,
 
8483
  PLUGIN_VAR_RQCMDARG,
 
8484
  "Desired maximum length of the purge queue (0 = no limit)",
 
8485
  NULL, NULL, 0, 0, ~0L, 0);
 
8486
 
 
8487
static DRIZZLE_SYSVAR_BOOL(status_file, innobase_create_status_file,
 
8488
  PLUGIN_VAR_OPCMDARG | PLUGIN_VAR_NOSYSVAR,
 
8489
  "Enable SHOW INNODB STATUS output in the innodb_status.<pid> file",
 
8490
  NULL, NULL, FALSE);
 
8491
 
 
8492
static DRIZZLE_SYSVAR_BOOL(stats_on_metadata, innobase_stats_on_metadata,
 
8493
  PLUGIN_VAR_OPCMDARG,
 
8494
  "Enable statistics gathering for metadata commands such as SHOW TABLE STATUS (on by default)",
 
8495
  NULL, NULL, TRUE);
 
8496
 
 
8497
static DRIZZLE_SYSVAR_ULONGLONG(stats_sample_pages, srv_stats_sample_pages,
 
8498
  PLUGIN_VAR_RQCMDARG,
 
8499
  "The number of index pages to sample when calculating statistics (default 8)",
 
8500
  NULL, NULL, 8, 1, ~0ULL, 0);
 
8501
 
 
8502
static DRIZZLE_SYSVAR_BOOL(adaptive_hash_index, btr_search_enabled,
 
8503
  PLUGIN_VAR_OPCMDARG,
 
8504
  "Enable InnoDB adaptive hash index (enabled by default).  "
 
8505
  "Disable with --skip-innodb-adaptive-hash-index.",
 
8506
  NULL, innodb_adaptive_hash_index_update, TRUE);
 
8507
 
 
8508
static DRIZZLE_SYSVAR_ULONG(replication_delay, srv_replication_delay,
 
8509
  PLUGIN_VAR_RQCMDARG,
 
8510
  "Replication thread delay (ms) on the slave server if "
 
8511
  "innodb_thread_concurrency is reached (0 by default)",
 
8512
  NULL, NULL, 0, 0, ~0UL, 0);
 
8513
 
 
8514
static DRIZZLE_SYSVAR_LONG(additional_mem_pool_size, innobase_additional_mem_pool_size,
 
8515
  PLUGIN_VAR_RQCMDARG | PLUGIN_VAR_READONLY,
 
8516
  "Size of a memory pool InnoDB uses to store data dictionary information and other internal data structures.",
 
8517
  NULL, NULL, 8*1024*1024L, 512*1024L, LONG_MAX, 1024);
 
8518
 
 
8519
static DRIZZLE_SYSVAR_UINT(autoextend_increment, srv_auto_extend_increment,
 
8520
  PLUGIN_VAR_RQCMDARG,
 
8521
  "Data file autoextend increment in megabytes",
 
8522
  NULL, NULL, 8L, 1L, 1000L, 0);
 
8523
 
 
8524
static DRIZZLE_SYSVAR_LONGLONG(buffer_pool_size, innobase_buffer_pool_size,
 
8525
  PLUGIN_VAR_RQCMDARG | PLUGIN_VAR_READONLY,
 
8526
  "The size of the memory buffer InnoDB uses to cache data and indexes of its tables.",
 
8527
  NULL, NULL, 128*1024*1024L, 5*1024*1024L, INT64_MAX, 1024*1024L);
 
8528
 
 
8529
static DRIZZLE_SYSVAR_ULONG(commit_concurrency, innobase_commit_concurrency,
 
8530
  PLUGIN_VAR_RQCMDARG,
 
8531
  "Helps in performance tuning in heavily concurrent environments.",
 
8532
  innobase_commit_concurrency_validate, NULL, 0, 0, 1000, 0);
 
8533
 
 
8534
static DRIZZLE_SYSVAR_ULONG(concurrency_tickets, srv_n_free_tickets_to_enter,
 
8535
  PLUGIN_VAR_RQCMDARG,
 
8536
  "Number of times a thread is allowed to enter InnoDB within the same SQL query after it has once got the ticket",
 
8537
  NULL, NULL, 500L, 1L, ~0L, 0);
 
8538
 
 
8539
static DRIZZLE_SYSVAR_LONG(file_io_threads, innobase_file_io_threads,
 
8540
  PLUGIN_VAR_RQCMDARG | PLUGIN_VAR_READONLY,
 
8541
  "Number of file I/O threads in InnoDB.",
 
8542
  NULL, NULL, 4, 4, 64, 0);
 
8543
 
 
8544
static DRIZZLE_SYSVAR_ULONG(read_io_threads, innobase_read_io_threads,
 
8545
  PLUGIN_VAR_RQCMDARG | PLUGIN_VAR_READONLY,
 
8546
  "Number of background read I/O threads in InnoDB.",
 
8547
  NULL, NULL, 4, 1, 64, 0);
 
8548
 
 
8549
static DRIZZLE_SYSVAR_ULONG(write_io_threads, innobase_write_io_threads,
 
8550
  PLUGIN_VAR_RQCMDARG | PLUGIN_VAR_READONLY,
 
8551
  "Number of background write I/O threads in InnoDB.",
 
8552
  NULL, NULL, 4, 1, 64, 0);
 
8553
 
 
8554
static DRIZZLE_SYSVAR_LONG(force_recovery, innobase_force_recovery,
 
8555
  PLUGIN_VAR_RQCMDARG | PLUGIN_VAR_READONLY,
 
8556
  "Helps to save your data in case the disk image of the database becomes corrupt.",
 
8557
  NULL, NULL, 0, 0, 6, 0);
 
8558
 
 
8559
static DRIZZLE_SYSVAR_LONG(log_buffer_size, innobase_log_buffer_size,
 
8560
  PLUGIN_VAR_RQCMDARG | PLUGIN_VAR_READONLY,
 
8561
  "The size of the buffer which InnoDB uses to write log to the log files on disk.",
 
8562
  NULL, NULL, 8*1024*1024L, 256*1024L, LONG_MAX, 1024);
 
8563
 
 
8564
static DRIZZLE_SYSVAR_LONGLONG(log_file_size, innobase_log_file_size,
 
8565
  PLUGIN_VAR_RQCMDARG | PLUGIN_VAR_READONLY,
 
8566
  "Size of each log file in a log group.",
 
8567
  NULL, NULL, 20*1024*1024L, 1*1024*1024L, INT64_MAX, 1024*1024L);
 
8568
 
 
8569
static DRIZZLE_SYSVAR_LONG(log_files_in_group, innobase_log_files_in_group,
 
8570
  PLUGIN_VAR_RQCMDARG | PLUGIN_VAR_READONLY,
 
8571
  "Number of log files in the log group. InnoDB writes to the files in a circular fashion. Value 3 is recommended here.",
 
8572
  NULL, NULL, 2, 2, 100, 0);
 
8573
 
 
8574
static DRIZZLE_SYSVAR_LONG(mirrored_log_groups, innobase_mirrored_log_groups,
 
8575
  PLUGIN_VAR_RQCMDARG | PLUGIN_VAR_READONLY,
 
8576
  "Number of identical copies of log groups we keep for the database. Currently this should be set to 1.",
 
8577
  NULL, NULL, 1, 1, 10, 0);
 
8578
 
 
8579
static DRIZZLE_SYSVAR_LONG(open_files, innobase_open_files,
 
8580
  PLUGIN_VAR_RQCMDARG | PLUGIN_VAR_READONLY,
 
8581
  "How many files at the maximum InnoDB keeps open at the same time.",
 
8582
  NULL, NULL, 300L, 10L, LONG_MAX, 0);
 
8583
 
 
8584
static DRIZZLE_SYSVAR_ULONG(sync_spin_loops, srv_n_spin_wait_rounds,
 
8585
  PLUGIN_VAR_RQCMDARG,
 
8586
  "Count of spin-loop rounds in InnoDB mutexes (30 by default)",
 
8587
  NULL, NULL, 30L, 0L, ~0L, 0);
 
8588
 
 
8589
static DRIZZLE_SYSVAR_ULONG(spin_wait_delay, srv_spin_wait_delay,
 
8590
  PLUGIN_VAR_OPCMDARG,
 
8591
  "Maximum delay between polling for a spin lock (6 by default)",
 
8592
  NULL, NULL, 6L, 0L, ~0L, 0);
 
8593
 
 
8594
static DRIZZLE_SYSVAR_ULONG(thread_concurrency, srv_thread_concurrency,
 
8595
  PLUGIN_VAR_RQCMDARG,
 
8596
  "Helps in performance tuning in heavily concurrent environments. Sets the maximum number of threads allowed inside InnoDB. Value 0 will disable the thread throttling.",
 
8597
  NULL, NULL, 0, 0, 1000, 0);
 
8598
 
 
8599
static DRIZZLE_SYSVAR_ULONG(thread_sleep_delay, srv_thread_sleep_delay,
 
8600
  PLUGIN_VAR_RQCMDARG,
 
8601
  "Time of innodb thread sleeping before joining InnoDB queue (usec). Value 0 disable a sleep",
 
8602
  NULL, NULL, 10000L, 0L, ~0L, 0);
 
8603
 
 
8604
static DRIZZLE_SYSVAR_STR(data_file_path, innobase_data_file_path,
 
8605
  PLUGIN_VAR_RQCMDARG | PLUGIN_VAR_READONLY,
 
8606
  "Path to individual files and their sizes.",
 
8607
  NULL, NULL, NULL);
 
8608
 
 
8609
static DRIZZLE_SYSVAR_STR(version, innodb_version_str,
 
8610
  PLUGIN_VAR_NOCMDOPT | PLUGIN_VAR_READONLY,
 
8611
  "InnoDB version", NULL, NULL, INNODB_VERSION_STR);
 
8612
 
 
8613
static DRIZZLE_SYSVAR_BOOL(use_sys_malloc, srv_use_sys_malloc,
 
8614
  PLUGIN_VAR_NOCMDARG | PLUGIN_VAR_READONLY,
 
8615
  "Use OS memory allocator instead of InnoDB's internal memory allocator",
 
8616
  NULL, NULL, TRUE);
 
8617
 
 
8618
static DRIZZLE_SYSVAR_STR(change_buffering, innobase_change_buffering,
 
8619
  PLUGIN_VAR_RQCMDARG,
 
8620
  "Buffer changes to reduce random access: "
 
8621
  "OFF, ON, inserting, deleting, changing, or purging.",
 
8622
  innodb_change_buffering_validate,
 
8623
  innodb_change_buffering_update, NULL);
 
8624
 
 
8625
static DRIZZLE_SYSVAR_ULONG(read_ahead_threshold, srv_read_ahead_threshold,
 
8626
  PLUGIN_VAR_RQCMDARG,
 
8627
  "Number of pages that must be accessed sequentially for InnoDB to"
 
8628
  "trigger a readahead.",
 
8629
  NULL, NULL, 56, 0, 64, 0);
 
8630
 
 
8631
static drizzle_sys_var* innobase_system_variables[]= {
 
8632
  DRIZZLE_SYSVAR(additional_mem_pool_size),
 
8633
  DRIZZLE_SYSVAR(autoextend_increment),
 
8634
  DRIZZLE_SYSVAR(buffer_pool_size),
 
8635
  DRIZZLE_SYSVAR(checksums),
 
8636
  DRIZZLE_SYSVAR(commit_concurrency),
 
8637
  DRIZZLE_SYSVAR(concurrency_tickets),
 
8638
  DRIZZLE_SYSVAR(data_file_path),
 
8639
  DRIZZLE_SYSVAR(data_home_dir),
 
8640
  DRIZZLE_SYSVAR(doublewrite),
 
8641
  DRIZZLE_SYSVAR(fast_shutdown),
 
8642
  DRIZZLE_SYSVAR(file_io_threads),
 
8643
  DRIZZLE_SYSVAR(read_io_threads),
 
8644
  DRIZZLE_SYSVAR(write_io_threads),
 
8645
  DRIZZLE_SYSVAR(file_per_table),
 
8646
  DRIZZLE_SYSVAR(file_format),
 
8647
  DRIZZLE_SYSVAR(file_format_check),
 
8648
  DRIZZLE_SYSVAR(flush_log_at_trx_commit),
 
8649
  DRIZZLE_SYSVAR(flush_method),
 
8650
  DRIZZLE_SYSVAR(force_recovery),
 
8651
  DRIZZLE_SYSVAR(lock_wait_timeout),
 
8652
#ifdef UNIV_LOG_ARCHIVE
 
8653
  DRIZZLE_SYSVAR(log_arch_dir),
 
8654
  DRIZZLE_SYSVAR(log_archive),
 
8655
#endif /* UNIV_LOG_ARCHIVE */
 
8656
  DRIZZLE_SYSVAR(log_buffer_size),
 
8657
  DRIZZLE_SYSVAR(log_file_size),
 
8658
  DRIZZLE_SYSVAR(log_files_in_group),
 
8659
  DRIZZLE_SYSVAR(log_group_home_dir),
 
8660
  DRIZZLE_SYSVAR(max_dirty_pages_pct),
 
8661
  DRIZZLE_SYSVAR(max_purge_lag),
 
8662
  DRIZZLE_SYSVAR(adaptive_flushing),
 
8663
  DRIZZLE_SYSVAR(mirrored_log_groups),
 
8664
  DRIZZLE_SYSVAR(open_files),
 
8665
  DRIZZLE_SYSVAR(stats_on_metadata),
 
8666
  DRIZZLE_SYSVAR(stats_sample_pages),
 
8667
  DRIZZLE_SYSVAR(adaptive_hash_index),
 
8668
  DRIZZLE_SYSVAR(replication_delay),
 
8669
  DRIZZLE_SYSVAR(status_file),
 
8670
  DRIZZLE_SYSVAR(strict_mode),
 
8671
  DRIZZLE_SYSVAR(support_xa),
 
8672
  DRIZZLE_SYSVAR(sync_spin_loops),
 
8673
  DRIZZLE_SYSVAR(spin_wait_delay),
 
8674
  DRIZZLE_SYSVAR(table_locks),
 
8675
  DRIZZLE_SYSVAR(thread_concurrency),
 
8676
  DRIZZLE_SYSVAR(thread_sleep_delay),
 
8677
  DRIZZLE_SYSVAR(version),
 
8678
  DRIZZLE_SYSVAR(use_sys_malloc),
 
8679
  DRIZZLE_SYSVAR(change_buffering),
 
8680
  DRIZZLE_SYSVAR(read_ahead_threshold),
 
8681
  DRIZZLE_SYSVAR(io_capacity),
 
8682
  NULL
 
8683
};
9276
8684
 
9277
8685
DRIZZLE_DECLARE_PLUGIN
9278
8686
{
9283
8691
  "Supports transactions, row-level locking, and foreign keys",
9284
8692
  PLUGIN_LICENSE_GPL,
9285
8693
  innobase_init, /* Plugin Init */
9286
 
  NULL, /* depends */
9287
 
  init_options /* reserved */
 
8694
  innobase_system_variables, /* system variables */
 
8695
  NULL /* reserved */
9288
8696
}
9289
8697
DRIZZLE_DECLARE_PLUGIN_END;
9290
8698
 
9311
8719
  return res;
9312
8720
}
9313
8721
 
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. */
 
8722
/** @brief Initialize the default value of innodb_commit_concurrency.
 
8723
 
 
8724
Once InnoDB is running, the innodb_commit_concurrency must not change
 
8725
from zero to nonzero. (Bug #42101)
 
8726
 
 
8727
The initial default value is 0, and without this extra initialization,
 
8728
SET GLOBAL innodb_commit_concurrency=DEFAULT would set the parameter
 
8729
to 0, even if it was initially set to nonzero at the command line
 
8730
or configuration file. */
 
8731
static
 
8732
void
 
8733
innobase_commit_concurrency_init_default(void)
 
8734
/*==========================================*/
9328
8735
{
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);
 
8736
  DRIZZLE_SYSVAR_NAME(commit_concurrency).def_val
 
8737
    = innobase_commit_concurrency;
9355
8738
}
9356
8739
 
9357
8740
#ifdef UNIV_COMPILE_TEST_FUNCS
9361
8744
  ulint   buflen;
9362
8745
  const char* id;
9363
8746
  ulint   idlen;
9364
 
  drizzled::Session *session;
 
8747
  void*   session;
9365
8748
  ibool   file_id;
9366
8749
 
9367
8750
  const char* expected;