~drizzle-trunk/drizzle/development

« back to all changes in this revision

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

  • Committer: Joe Daly
  • Date: 2010-05-21 02:16:56 UTC
  • mto: This revision was merged to the branch mainline in revision 1555.
  • Revision ID: skinny.moey@gmail.com-20100521021656-bx6piitfh77jnl28
add statistics_variables.h

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
}
117
126
 
118
127
#include "ha_innodb.h"
119
128
#include "data_dictionary.h"
120
 
#include "replication_dictionary.h"
121
 
#include "internal_dictionary.h"
122
129
#include "handler0vars.h"
123
130
 
124
131
#include <iostream>
125
132
#include <sstream>
126
133
#include <string>
127
134
 
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>
 
135
#include "plugin/innobase/handler/status_function.h"
137
136
 
138
137
using namespace std;
139
138
using namespace drizzled;
140
139
 
 
140
#ifndef DRIZZLE_SERVER
 
141
/* This is needed because of Bug #3596.  Let us hope that pthread_mutex_t
 
142
is defined the same in both builds: the MySQL server and the InnoDB plugin. */
 
143
extern pthread_mutex_t LOCK_thread_count;
 
144
 
 
145
#endif /* DRIZZLE_SERVER */
 
146
 
141
147
/** to protect innobase_open_files */
142
 
static boost::mutex innobase_share_mutex;
143
 
 
 
148
static pthread_mutex_t innobase_share_mutex;
144
149
/** to force correct commit order in binlog */
 
150
static pthread_mutex_t prepare_commit_mutex;
145
151
static ulong commit_threads = 0;
146
 
static boost::condition_variable commit_cond;
147
 
static boost::mutex commit_cond_m;
 
152
static pthread_mutex_t commit_threads_m;
 
153
static pthread_cond_t commit_cond;
 
154
static pthread_mutex_t commit_cond_m;
148
155
static bool innodb_inited = 0;
149
156
 
150
157
#define INSIDE_HA_INNOBASE_CC
160
167
#endif /* MYSQL_DYNAMIC_PLUGIN && __WIN__ */
161
168
 
162
169
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;
 
170
static plugin::TableFunction* status_table_function_ptr= NULL;
 
171
static plugin::TableFunction* cmp_tool= NULL;
 
172
static plugin::TableFunction* cmp_reset_tool= NULL;
 
173
static plugin::TableFunction* cmp_mem_tool= NULL;
 
174
static plugin::TableFunction* cmp_mem_reset_tool= NULL;
 
175
static plugin::TableFunction* innodb_trx_tool= NULL;
 
176
static plugin::TableFunction* innodb_locks_tool= NULL;
 
177
static plugin::TableFunction* innodb_lock_waits_tool= NULL;
 
178
 
 
179
static const long AUTOINC_OLD_STYLE_LOCKING = 0;
 
180
static const long AUTOINC_NEW_STYLE_LOCKING = 1;
 
181
static const long AUTOINC_NO_LOCKING = 2;
 
182
 
 
183
static long innobase_mirrored_log_groups, innobase_log_files_in_group,
 
184
  innobase_log_buffer_size,
 
185
  innobase_additional_mem_pool_size, innobase_file_io_threads,
 
186
  innobase_force_recovery, innobase_open_files,
 
187
  innobase_autoinc_lock_mode;
 
188
static ulong innobase_commit_concurrency = 0;
 
189
static ulong innobase_read_io_threads;
 
190
static ulong innobase_write_io_threads;
 
191
 
 
192
/**
 
193
 * @TODO: Turn this into size_t as soon as we have a Variable<size_t>
 
194
 */
 
195
static int64_t innobase_buffer_pool_size, innobase_log_file_size;
219
196
 
220
197
/* The default values for the following char* start-up parameters
221
198
are determined in innobase_init below: */
222
199
 
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;
 
200
static char*  innobase_data_home_dir      = NULL;
 
201
static char*  innobase_data_file_path     = NULL;
 
202
static char*  innobase_log_group_home_dir   = NULL;
 
203
static char*  innobase_file_format_name   = NULL;
 
204
static char*  innobase_change_buffering   = NULL;
 
205
 
 
206
/* Note: This variable can be set to on/off and any of the supported
 
207
file formats in the configuration file, but can only be set to any
 
208
of the supported file formats during runtime. */
 
209
static char*  innobase_file_format_check    = NULL;
 
210
 
 
211
/* The following has a misleading name: starting from 4.0.5, this also
 
212
affects Windows: */
 
213
static char*  innobase_unix_file_flush_method   = NULL;
233
214
 
234
215
/* Below we have boolean-valued start-up parameters, and their default
235
216
values */
236
217
 
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;
 
218
static ulong  innobase_fast_shutdown      = 1;
 
219
#ifdef UNIV_LOG_ARCHIVE
 
220
static my_bool  innobase_log_archive      = FALSE;
 
221
static char*  innobase_log_arch_dir     = NULL;
 
222
#endif /* UNIV_LOG_ARCHIVE */
253
223
static my_bool  innobase_use_doublewrite    = TRUE;
254
224
static my_bool  innobase_use_checksums      = TRUE;
255
225
static my_bool  innobase_rollback_on_timeout    = FALSE;
256
226
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;
 
227
static my_bool  innobase_stats_on_metadata    = TRUE;
262
228
 
263
229
static char*  internal_innobase_data_file_path  = NULL;
264
230
 
 
231
static char*  innodb_version_str = (char*) INNODB_VERSION_STR;
 
232
 
265
233
/* The following counter is used to convey information to InnoDB
266
234
about server activity: in selects it is not sensible to call
267
235
srv_active_wake_master_thread after each fetch or search, we only do
279
247
/** Allowed values of innodb_change_buffering */
280
248
static const char* innobase_change_buffering_values[IBUF_USE_COUNT] = {
281
249
  "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 */
 
250
  "inserts" /* IBUF_USE_INSERT */
287
251
};
288
252
 
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
253
/********************************************************************
294
254
Gives the file extension of an InnoDB single-table tablespace. */
295
255
static const char* ha_innobase_exts[] = {
323
283
  {
324
284
    int err= 0;
325
285
    if (innodb_inited) {
 
286
 
326
287
      srv_fast_shutdown = (ulint) innobase_fast_shutdown;
327
288
      innodb_inited = 0;
328
289
      hash_table_free(innobase_open_tables);
333
294
      srv_free_paths_and_sizes();
334
295
      if (internal_innobase_data_file_path)
335
296
        free(internal_innobase_data_file_path);
 
297
      pthread_mutex_destroy(&innobase_share_mutex);
 
298
      pthread_mutex_destroy(&prepare_commit_mutex);
 
299
      pthread_mutex_destroy(&commit_threads_m);
 
300
      pthread_mutex_destroy(&commit_cond_m);
 
301
      pthread_cond_destroy(&commit_cond);
336
302
    }
337
 
    
338
 
    /* These get strdup'd from vm variables */
339
 
 
340
303
  }
341
304
 
342
305
private:
366
329
  {
367
330
    return doRollback(session, all); /* XA rollback just does a SQL ROLLBACK */
368
331
  }
369
 
  virtual uint64_t doGetCurrentTransactionId(Session *session);
370
 
  virtual uint64_t doGetNewTransactionId(Session *session);
371
332
  virtual int doCommit(Session* session, bool all);
372
333
  virtual int doRollback(Session* session, bool all);
373
334
 
411
372
        /* out: 0 or error number */
412
373
    ::drizzled::XID *xid);  /* in: X/Open XA transaction identification */
413
374
 
414
 
  virtual Cursor *create(Table &table)
 
375
  virtual Cursor *create(TableShare &table,
 
376
                         memory::Root *mem_root)
415
377
  {
416
 
    return new ha_innobase(*this, table);
 
378
    return new (mem_root) ha_innobase(*this, table);
417
379
  }
418
380
 
419
381
  /*********************************************************************
422
384
  doDropSchema(
423
385
  /*===================*/
424
386
        /* out: error number */
425
 
    const identifier::Schema  &identifier); /* in: database path; inside InnoDB the name
 
387
    SchemaIdentifier  &identifier); /* in: database path; inside InnoDB the name
426
388
        of the last directory in the path is used as
427
389
        the database name: for example, in 'mysql/data/test'
428
390
        the database name is 'test' */
461
423
 
462
424
  UNIV_INTERN int doCreateTable(Session &session,
463
425
                                Table &form,
464
 
                                const identifier::Table &identifier,
 
426
                                drizzled::TableIdentifier &identifier,
465
427
                                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);
 
428
  UNIV_INTERN int doRenameTable(Session&, TableIdentifier &from, TableIdentifier &to);
 
429
  UNIV_INTERN int doDropTable(Session &session, TableIdentifier &identifier);
468
430
 
469
 
  UNIV_INTERN virtual bool get_error_message(int error, String *buf) const;
 
431
  UNIV_INTERN virtual bool get_error_message(int error, String *buf);
470
432
 
471
433
  UNIV_INTERN uint32_t max_supported_keys() const;
472
434
  UNIV_INTERN uint32_t max_supported_key_length() const;
483
445
  }
484
446
 
485
447
  int doGetTableDefinition(drizzled::Session& session,
486
 
                           const identifier::Table &identifier,
 
448
                           drizzled::TableIdentifier &identifier,
487
449
                           drizzled::message::Table &table_proto);
488
450
 
489
 
  bool doDoesTableExist(drizzled::Session& session, const identifier::Table &identifier);
 
451
  void doGetTableNames(drizzled::CachedDirectory &directory,
 
452
           drizzled::SchemaIdentifier &schema_identifier,
 
453
                       std::set<std::string> &set_of_names);
 
454
 
 
455
  bool doDoesTableExist(drizzled::Session& session, drizzled::TableIdentifier &identifier);
490
456
 
491
457
  void doGetTableIdentifiers(drizzled::CachedDirectory &directory,
492
 
                             const drizzled::identifier::Schema &schema_identifier,
493
 
                             drizzled::identifier::Table::vector &set_of_identifiers);
 
458
                             drizzled::SchemaIdentifier &schema_identifier,
 
459
                             drizzled::TableIdentifiers &set_of_identifiers);
494
460
  bool validateCreateTableOption(const std::string &key, const std::string &state);
495
 
  void dropTemporarySchema();
496
 
 
497
461
};
498
462
 
499
463
 
518
482
}
519
483
 
520
484
void InnobaseEngine::doGetTableIdentifiers(drizzled::CachedDirectory &directory,
521
 
                                           const drizzled::identifier::Schema &schema_identifier,
522
 
                                           drizzled::identifier::Table::vector &set_of_identifiers)
 
485
                                           drizzled::SchemaIdentifier &schema_identifier,
 
486
                                           drizzled::TableIdentifiers &set_of_identifiers)
523
487
{
524
488
  CachedDirectory::Entries entries= directory.getEntries();
525
489
 
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
490
  for (CachedDirectory::Entries::iterator entry_iter= entries.begin(); 
536
491
       entry_iter != entries.end(); ++entry_iter)
537
492
  {
547
502
    { }
548
503
    else
549
504
    {
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
 
      }
 
505
      char uname[NAME_LEN + 1];
 
506
      uint32_t file_name_len;
 
507
 
 
508
      file_name_len= filename_to_tablename(filename->c_str(), uname, sizeof(uname));
 
509
      // TODO: Remove need for memory copy here
 
510
      uname[file_name_len - sizeof(DEFAULT_FILE_EXTENSION) + 1]= '\0'; // Subtract ending, place NULL 
 
511
 
 
512
      set_of_identifiers.push_back(TableIdentifier(schema_identifier, uname));
565
513
    }
566
514
  }
567
515
}
568
516
 
569
 
bool InnobaseEngine::doDoesTableExist(Session &session, const identifier::Table &identifier)
 
517
bool InnobaseEngine::doDoesTableExist(Session&, TableIdentifier &identifier)
570
518
{
571
519
  string proto_path(identifier.getPath());
572
520
  proto_path.append(DEFAULT_FILE_EXTENSION);
573
521
 
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)
581
 
    return true;
582
 
 
583
522
  if (access(proto_path.c_str(), F_OK))
584
523
  {
585
524
    return false;
588
527
  return true;
589
528
}
590
529
 
591
 
int InnobaseEngine::doGetTableDefinition(Session &session,
592
 
                                         const identifier::Table &identifier,
 
530
int InnobaseEngine::doGetTableDefinition(Session &,
 
531
                                         drizzled::TableIdentifier &identifier,
593
532
                                         message::Table &table_proto)
594
533
{
595
534
  string proto_path(identifier.getPath());
596
535
  proto_path.append(DEFAULT_FILE_EXTENSION);
597
536
 
598
 
  // 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)
603
 
    return EEXIST;
604
 
 
605
537
  if (access(proto_path.c_str(), F_OK))
606
538
  {
607
539
    return errno;
613
545
  return ENOENT;
614
546
}
615
547
 
 
548
void InnobaseEngine::doGetTableNames(CachedDirectory &directory, SchemaIdentifier&, set<string>& set_of_names)
 
549
{
 
550
  CachedDirectory::Entries entries= directory.getEntries();
 
551
 
 
552
  for (CachedDirectory::Entries::iterator entry_iter= entries.begin(); 
 
553
       entry_iter != entries.end(); ++entry_iter)
 
554
  {
 
555
    CachedDirectory::Entry *entry= *entry_iter;
 
556
    const string *filename= &entry->filename;
 
557
 
 
558
    assert(filename->size());
 
559
 
 
560
    const char *ext= strchr(filename->c_str(), '.');
 
561
 
 
562
    if (ext == NULL || my_strcasecmp(system_charset_info, ext, DEFAULT_FILE_EXTENSION) ||
 
563
        (filename->compare(0, strlen(TMP_FILE_PREFIX), TMP_FILE_PREFIX) == 0))
 
564
    { }
 
565
    else
 
566
    {
 
567
      char uname[NAME_LEN + 1];
 
568
      uint32_t file_name_len;
 
569
 
 
570
      file_name_len= filename_to_tablename(filename->c_str(), uname, sizeof(uname));
 
571
      // TODO: Remove need for memory copy here
 
572
      uname[file_name_len - sizeof(DEFAULT_FILE_EXTENSION) + 1]= '\0'; // Subtract ending, place NULL 
 
573
      set_of_names.insert(uname);
 
574
    }
 
575
  }
 
576
}
 
577
 
 
578
/** @brief Initialize the default value of innodb_commit_concurrency.
 
579
 
 
580
Once InnoDB is running, the innodb_commit_concurrency must not change
 
581
from zero to nonzero. (Bug #42101)
 
582
 
 
583
The initial default value is 0, and without this extra initialization,
 
584
SET GLOBAL innodb_commit_concurrency=DEFAULT would set the parameter
 
585
to 0, even if it was initially set to nonzero at the command line
 
586
or configuration file. */
 
587
static
 
588
void
 
589
innobase_commit_concurrency_init_default(void);
 
590
/*==========================================*/
616
591
 
617
592
/************************************************************//**
618
593
Validate the file format name and return its corresponding id.
625
600
            name */
626
601
/************************************************************//**
627
602
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(
 
603
sets the srv_check_file_format_at_startup variable.
 
604
@return true if one of  "on" or "off" */
 
605
static
 
606
bool
 
607
innobase_file_format_check_on_off(
 
608
/*==============================*/
 
609
  const char* format_check);    /*!< in: parameter value */
 
610
/************************************************************//**
 
611
Validate the file format check config parameters, as a side effect it
 
612
sets the srv_check_file_format_at_startup variable.
 
613
@return true if valid config value */
 
614
static
 
615
bool
 
616
innobase_file_format_check_validate(
633
617
/*================================*/
634
 
  const char* format_max);    /*!< in: parameter value */
 
618
  const char* format_check);    /*!< in: parameter value */
635
619
 
636
620
static const char innobase_engine_name[]= "InnoDB";
637
621
 
 
622
/*************************************************************//**
 
623
Check for a valid value of innobase_commit_concurrency.
 
624
@return 0 for valid innodb_commit_concurrency */
 
625
static
 
626
int
 
627
innobase_commit_concurrency_validate(
 
628
/*=================================*/
 
629
  Session*      , /*!< in: thread handle */
 
630
  drizzle_sys_var*  , /*!< in: pointer to system
 
631
            variable */
 
632
  void*       save, /*!< out: immediate result
 
633
            for update function */
 
634
  drizzle_value*    value)  /*!< in: incoming string */
 
635
{
 
636
  int64_t   intbuf;
 
637
  ulong   commit_concurrency;
 
638
 
 
639
  if (value->val_int(value, &intbuf)) {
 
640
    /* The value is NULL. That is invalid. */
 
641
    return(1);
 
642
  }
 
643
 
 
644
  *reinterpret_cast<ulong*>(save) = commit_concurrency
 
645
    = static_cast<ulong>(intbuf);
 
646
 
 
647
  /* Allow the value to be updated, as long as it remains zero
 
648
  or nonzero. */
 
649
  return(!(!commit_concurrency == !innobase_commit_concurrency));
 
650
}
 
651
 
 
652
static DRIZZLE_SessionVAR_BOOL(support_xa, PLUGIN_VAR_OPCMDARG,
 
653
  "Enable InnoDB support for the XA two-phase commit",
 
654
  /* check_func */ NULL, /* update_func */ NULL,
 
655
  /* default */ TRUE);
 
656
 
 
657
static DRIZZLE_SessionVAR_BOOL(table_locks, PLUGIN_VAR_OPCMDARG,
 
658
  "Enable InnoDB locking in LOCK TABLES",
 
659
  /* check_func */ NULL, /* update_func */ NULL,
 
660
  /* default */ TRUE);
 
661
 
 
662
static DRIZZLE_SessionVAR_BOOL(strict_mode, PLUGIN_VAR_OPCMDARG,
 
663
  "Use strict mode when evaluating create options.",
 
664
  NULL, NULL, FALSE);
 
665
 
 
666
static DRIZZLE_SessionVAR_ULONG(lock_wait_timeout, PLUGIN_VAR_RQCMDARG,
 
667
  "Timeout in seconds an InnoDB transaction may wait for a lock before being rolled back. Values above 100000000 disable the timeout.",
 
668
  NULL, NULL, 50, 1, 1024 * 1024 * 1024, 0);
 
669
 
638
670
 
639
671
/*****************************************************************//**
640
672
Commits a transaction in an InnoDB database. */
661
693
  (char*) &export_vars.innodb_buffer_pool_pages_misc,   SHOW_LONG},
662
694
  {"buffer_pool_pages_total",
663
695
  (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},
 
696
  {"buffer_pool_read_ahead_rnd",
 
697
  (char*) &export_vars.innodb_buffer_pool_read_ahead_rnd, SHOW_LONG},
 
698
  {"buffer_pool_read_ahead_seq",
 
699
  (char*) &export_vars.innodb_buffer_pool_read_ahead_seq, SHOW_LONG},
668
700
  {"buffer_pool_read_requests",
669
701
  (char*) &export_vars.innodb_buffer_pool_read_requests,  SHOW_LONG},
670
702
  {"buffer_pool_reads",
798
830
DRIZZLE: Note, we didn't change this name to avoid more ifdef forking 
799
831
         in non-Cursor code.
800
832
@return true if session is the replication thread */
801
 
UNIV_INTERN
 
833
extern "C" UNIV_INTERN
802
834
ibool
803
835
thd_is_replication_slave_thread(
804
836
/*============================*/
805
 
  drizzled::Session* ) /*!< in: thread handle (Session*) */
 
837
  void* ) /*!< in: thread handle (Session*) */
806
838
{
807
839
  return false;
808
840
}
872
904
DRIZZLE: Note, we didn't change this name to avoid more ifdef forking 
873
905
         in non-Cursor code.
874
906
@return true if non-transactional tables have been edited */
875
 
UNIV_INTERN
 
907
extern "C" UNIV_INTERN
876
908
ibool
877
909
thd_has_edited_nontrans_tables(
878
910
/*===========================*/
879
 
  drizzled::Session *session)  /*!< in: thread handle (Session*) */
 
911
  void*   session)  /*!< in: thread handle (Session*) */
880
912
{
881
 
  return((ibool)session->transaction.all.hasModifiedNonTransData());
 
913
  return((ibool)((Session *)session)->transaction.all.hasModifiedNonTransData());
882
914
}
883
915
 
884
916
/******************************************************************//**
885
917
Returns true if the thread is executing a SELECT statement.
886
918
@return true if session is executing SELECT */
887
 
UNIV_INTERN
 
919
extern "C" UNIV_INTERN
888
920
ibool
889
921
thd_is_select(
890
922
/*==========*/
891
 
  const drizzled::Session *session)  /*!< in: thread handle (Session*) */
 
923
  const void* session)  /*!< in: thread handle (Session*) */
892
924
{
893
 
  return(session->getSqlCommand() == SQLCOM_SELECT);
 
925
  return(session_sql_command((const Session*) session) == SQLCOM_SELECT);
894
926
}
895
927
 
896
928
/******************************************************************//**
897
929
Returns true if the thread supports XA,
898
930
global value of innodb_supports_xa if session is NULL.
899
931
@return true if session has XA support */
900
 
UNIV_INTERN
 
932
extern "C" UNIV_INTERN
901
933
ibool
902
934
thd_supports_xa(
903
935
/*============*/
904
 
  drizzled::Session* )  /*!< in: thread handle (Session*), or NULL to query
 
936
  void* session)  /*!< in: thread handle (Session*), or NULL to query
905
937
        the global innodb_supports_xa */
906
938
{
907
 
  /* TODO: Add support here for per-session value */
908
 
  return(support_xa);
 
939
  return(SessionVAR((Session*) session, support_xa));
909
940
}
910
941
 
911
942
/******************************************************************//**
912
943
Returns the lock wait timeout for the current connection.
913
944
@return the lock wait timeout, in seconds */
914
 
UNIV_INTERN
 
945
extern "C" UNIV_INTERN
915
946
ulong
916
947
thd_lock_wait_timeout(
917
948
/*==================*/
918
 
  drizzled::Session*)  /*!< in: thread handle (Session*), or NULL to query
 
949
  void* session)  /*!< in: thread handle (Session*), or NULL to query
919
950
      the global innodb_lock_wait_timeout */
920
951
{
921
 
  /* TODO: Add support here for per-session value */
922
952
  /* According to <drizzle/plugin.h>, passing session == NULL
923
953
  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;
 
954
  return(SessionVAR((Session*) session, lock_wait_timeout));
938
955
}
939
956
 
940
957
/********************************************************************//**
949
966
  return *(trx_t**) session->getEngineData(innodb_engine_ptr);
950
967
}
951
968
 
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
969
/********************************************************************//**
977
970
Call this function when mysqld passes control to the client. That is to
978
971
avoid deadlocks on the adaptive hash S-latch possibly held by session. For more
1022
1015
about a possible transaction rollback inside InnoDB caused by a lock wait
1023
1016
timeout or a deadlock.
1024
1017
@return MySQL error code */
1025
 
UNIV_INTERN
 
1018
extern "C" UNIV_INTERN
1026
1019
int
1027
1020
convert_error_code_to_mysql(
1028
1021
/*========================*/
1034
1027
  case DB_SUCCESS:
1035
1028
    return(0);
1036
1029
 
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
1030
  case DB_ERROR:
1053
1031
  default:
1054
1032
    return(-1); /* unspecified error */
1055
1033
 
1056
1034
  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
1035
    return(HA_ERR_FOUND_DUPP_KEY);
1064
1036
 
1065
1037
  case DB_FOREIGN_DUPLICATE_KEY:
1076
1048
    tell it also to MySQL so that MySQL knows to empty the
1077
1049
    cached binlog for this transaction */
1078
1050
 
1079
 
    session->markTransactionForRollback(TRUE);
 
1051
    mark_transaction_to_rollback(session, TRUE);
1080
1052
 
1081
1053
    return(HA_ERR_LOCK_DEADLOCK);
1082
1054
 
1085
1057
    latest SQL statement in a lock wait timeout. Previously, we
1086
1058
    rolled back the whole transaction. */
1087
1059
 
1088
 
    session->markTransactionForRollback((bool)row_rollback_on_timeout);
 
1060
    mark_transaction_to_rollback(session, (bool)row_rollback_on_timeout);
1089
1061
 
1090
1062
    return(HA_ERR_LOCK_WAIT_TIMEOUT);
1091
1063
 
1096
1068
    return(HA_ERR_ROW_IS_REFERENCED);
1097
1069
 
1098
1070
  case DB_CANNOT_ADD_CONSTRAINT:
1099
 
  case DB_CHILD_NO_INDEX:
1100
 
  case DB_PARENT_NO_INDEX:
1101
1071
    return(HA_ERR_CANNOT_ADD_FOREIGN);
1102
1072
 
1103
1073
  case DB_CANNOT_DROP_CONSTRAINT:
1121
1091
 
1122
1092
  case DB_TOO_BIG_RECORD:
1123
1093
    my_error(ER_TOO_BIG_ROWSIZE, MYF(0),
1124
 
             page_get_free_space_of_empty(flags & DICT_TF_COMPACT) / 2);
 
1094
       page_get_free_space_of_empty(flags
 
1095
                  & DICT_TF_COMPACT) / 2);
1125
1096
    return(HA_ERR_TO_BIG_ROW);
1126
1097
 
1127
1098
  case DB_NO_SAVEPOINT:
1132
1103
    tell it also to MySQL so that MySQL knows to empty the
1133
1104
    cached binlog for this transaction */
1134
1105
 
1135
 
    session->markTransactionForRollback(TRUE);
 
1106
    mark_transaction_to_rollback(session, TRUE);
1136
1107
 
1137
1108
    return(HA_ERR_LOCK_TABLE_FULL);
1138
1109
 
1147
1118
    and the actual error code name could very well be different.
1148
1119
    This will require some monitoring, ie. the status
1149
1120
    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 */
 
1121
#ifdef ER_TOO_MANY_CONCURRENT_TRXS
 
1122
    return(ER_TOO_MANY_CONCURRENT_TRXS);
 
1123
#else
1159
1124
    return(HA_ERR_RECORD_FILE_FULL);
1160
 
#endif /* HA_ERR_TOO_MANY_CONCURRENT_TRXS */
 
1125
#endif
1161
1126
  case DB_UNSUPPORTED:
1162
1127
    return(HA_ERR_UNSUPPORTED);
1163
1128
  }
1164
1129
}
1165
1130
 
 
1131
/*************************************************************//**
 
1132
If you want to print a session that is not associated with the current thread,
 
1133
you must call this function before reserving the InnoDB kernel_mutex, to
 
1134
protect Drizzle from setting session->query NULL. If you print a session of the
 
1135
current thread, we know that Drizzle cannot modify sesion->query, and it is
 
1136
not necessary to call this. Call innobase_mysql_end_print_arbitrary_thd()
 
1137
after you release the kernel_mutex.
 
1138
 
 
1139
DRIZZLE: Note, we didn't change this name to avoid more ifdef forking 
 
1140
         in non-Cursor code.
 
1141
 */
 
1142
extern "C" UNIV_INTERN
 
1143
void
 
1144
innobase_mysql_prepare_print_arbitrary_thd(void)
 
1145
/*============================================*/
 
1146
{
 
1147
  ut_ad(!mutex_own(&kernel_mutex));
 
1148
  pthread_mutex_lock(&LOCK_thread_count);
 
1149
}
 
1150
 
 
1151
/*************************************************************//**
 
1152
Releases the mutex reserved by innobase_mysql_prepare_print_arbitrary_thd().
 
1153
In the InnoDB latching order, the mutex sits right above the
 
1154
kernel_mutex.  In debug builds, we assert that the kernel_mutex is
 
1155
released before this function is invoked. 
 
1156
 
 
1157
DRIZZLE: Note, we didn't change this name to avoid more ifdef forking 
 
1158
         in non-Cursor code.
 
1159
*/
 
1160
extern "C" UNIV_INTERN
 
1161
void
 
1162
innobase_mysql_end_print_arbitrary_thd(void)
 
1163
/*========================================*/
 
1164
{
 
1165
  ut_ad(!mutex_own(&kernel_mutex));
 
1166
  pthread_mutex_unlock(&LOCK_thread_count);
 
1167
}
1166
1168
 
1167
1169
/*************************************************************//**
1168
1170
Prints info of a Session object (== user session thread) to the given file. */
1169
 
UNIV_INTERN
 
1171
extern "C" UNIV_INTERN
1170
1172
void
1171
1173
innobase_mysql_print_thd(
1172
1174
/*=====================*/
1173
1175
  FILE* f,    /*!< in: output stream */
1174
 
  drizzled::Session *in_session,  /*!< in: pointer to a Drizzle Session object */
 
1176
  void * in_session,  /*!< in: pointer to a Drizzle Session object */
1175
1177
  uint  )   /*!< in: max query length to print, or 0 to
1176
1178
           use the default max length */
1177
1179
{
1178
 
  drizzled::identifier::User::const_shared_ptr user_identifier(in_session->user());
1179
 
 
 
1180
  Session *session= reinterpret_cast<Session *>(in_session);
1180
1181
  fprintf(f,
1181
1182
          "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());
 
1183
          static_cast<uint64_t>(session->getSessionId()),
 
1184
          static_cast<uint64_t>(session->getQueryId()),
 
1185
          glob_hostname,
 
1186
          session->getSecurityContext().getIp().c_str(),
 
1187
          session->getSecurityContext().getUser().c_str()
 
1188
  );
 
1189
  fprintf(f,
 
1190
          "\n%s", session->getQueryString().c_str()
 
1191
  );
1189
1192
  putc('\n', f);
1190
1193
}
1191
1194
 
1192
1195
/******************************************************************//**
1193
1196
Get the variable length bounds of the given character set. */
1194
 
UNIV_INTERN
 
1197
extern "C" UNIV_INTERN
1195
1198
void
1196
1199
innobase_get_cset_width(
1197
1200
/*====================*/
1208
1211
  if (cs) {
1209
1212
    *mbminlen = cs->mbminlen;
1210
1213
    *mbmaxlen = cs->mbmaxlen;
1211
 
    ut_ad(*mbminlen < DATA_MBMAX);
1212
 
    ut_ad(*mbmaxlen < DATA_MBMAX);
1213
1214
  } else {
1214
1215
    ut_a(cset == 0);
1215
1216
    *mbminlen = *mbmaxlen = 0;
1218
1219
 
1219
1220
/******************************************************************//**
1220
1221
Converts an identifier to a table name. */
1221
 
UNIV_INTERN
 
1222
extern "C" UNIV_INTERN
1222
1223
void
1223
1224
innobase_convert_from_table_id(
1224
1225
/*===========================*/
1232
1233
 
1233
1234
/******************************************************************//**
1234
1235
Converts an identifier to UTF-8. */
1235
 
UNIV_INTERN
 
1236
extern "C" UNIV_INTERN
1236
1237
void
1237
1238
innobase_convert_from_id(
1238
1239
/*=====================*/
1247
1248
/******************************************************************//**
1248
1249
Compares NUL-terminated UTF-8 strings case insensitively.
1249
1250
@return 0 if a=b, <0 if a<b, >1 if a>b */
1250
 
UNIV_INTERN
 
1251
extern "C" UNIV_INTERN
1251
1252
int
1252
1253
innobase_strcasecmp(
1253
1254
/*================*/
1259
1260
 
1260
1261
/******************************************************************//**
1261
1262
Makes all characters in a NUL-terminated UTF-8 string lower case. */
1262
 
UNIV_INTERN
 
1263
extern "C" UNIV_INTERN
1263
1264
void
1264
1265
innobase_casedn_str(
1265
1266
/*================*/
1268
1269
  my_casedn_str(system_charset_info, a);
1269
1270
}
1270
1271
 
1271
 
UNIV_INTERN
 
1272
/**********************************************************************//**
 
1273
Determines the connection character set.
 
1274
@return connection character set */
 
1275
extern "C" UNIV_INTERN
 
1276
const void*
 
1277
innobase_get_charset(
 
1278
/*=================*/
 
1279
  void* mysql_session)  /*!< in: MySQL thread handle */
 
1280
{
 
1281
  return session_charset(static_cast<Session*>(mysql_session));
 
1282
}
 
1283
 
 
1284
extern "C" UNIV_INTERN
1272
1285
bool
1273
1286
innobase_isspace(
1274
1287
  const void *cs,
1277
1290
  return my_isspace(static_cast<const CHARSET_INFO *>(cs), char_to_test);
1278
1291
}
1279
1292
 
 
1293
UNIV_INTERN
 
1294
int
 
1295
innobase_fast_mutex_init(
 
1296
        os_fast_mutex_t*        fast_mutex)
 
1297
{
 
1298
  return pthread_mutex_init(fast_mutex, MY_MUTEX_INIT_FAST);
 
1299
}
 
1300
 
1280
1301
#if defined (__WIN__) && defined (MYSQL_DYNAMIC_PLUGIN)
1281
1302
/*******************************************************************//**
1282
1303
Map an OS error to an errno value. The OS error number is stored in
1283
1304
_doserrno and the mapped value is stored in errno) */
 
1305
extern "C"
1284
1306
void __cdecl
1285
1307
_dosmaperr(
1286
1308
  unsigned long); /*!< in: OS error value */
1288
1310
/*********************************************************************//**
1289
1311
Creates a temporary file.
1290
1312
@return temporary file descriptor, or < 0 on error */
1291
 
UNIV_INTERN
 
1313
extern "C" UNIV_INTERN
1292
1314
int
1293
1315
innobase_mysql_tmpfile(void)
1294
1316
/*========================*/
1368
1390
/*********************************************************************//**
1369
1391
Creates a temporary file.
1370
1392
@return temporary file descriptor, or < 0 on error */
1371
 
UNIV_INTERN
 
1393
extern "C" UNIV_INTERN
1372
1394
int
1373
1395
innobase_mysql_tmpfile(void)
1374
1396
/*========================*/
1375
1397
{
1376
1398
  int fd2 = -1;
1377
 
  int fd = ::drizzled::tmpfile("ib");
 
1399
  int fd = mysql_tmpfile("ib");
1378
1400
  if (fd >= 0) {
1379
1401
    /* Copy the file descriptor, so that the additional resources
1380
1402
    allocated by create_temp_file() can be freed by invoking
1407
1429
number of bytes that were written to "buf" is returned (including the
1408
1430
terminating NUL).
1409
1431
@return number of bytes that were written */
1410
 
UNIV_INTERN
 
1432
extern "C" UNIV_INTERN
1411
1433
ulint
1412
1434
innobase_raw_format(
1413
1435
/*================*/
1437
1459
  INSERT INTO T VALUES(), (), ();
1438
1460
 
1439
1461
innobase_next_autoinc() will be called with increment set to
 
1462
n * 3 where autoinc_lock_mode != TRADITIONAL because we want
1440
1463
to reserve 3 values for the multi-value INSERT above.
1441
1464
@return the next value */
1442
1465
static
1527
1550
/*********************************************************************//**
1528
1551
Allocates an InnoDB transaction for a MySQL Cursor object.
1529
1552
@return InnoDB transaction handle */
1530
 
UNIV_INTERN
 
1553
extern "C" UNIV_INTERN
1531
1554
trx_t*
1532
1555
innobase_trx_allocate(
1533
1556
/*==================*/
1541
1564
  trx = trx_allocate_for_mysql();
1542
1565
 
1543
1566
  trx->mysql_thd = session;
 
1567
  trx->mysql_query_str = session->query.c_str();
1544
1568
 
1545
1569
  innobase_trx_init(session, trx);
1546
1570
 
1579
1603
Construct ha_innobase Cursor. */
1580
1604
UNIV_INTERN
1581
1605
ha_innobase::ha_innobase(plugin::StorageEngine &engine_arg,
1582
 
                         Table &table_arg)
 
1606
                         TableShare &table_arg)
1583
1607
  :Cursor(engine_arg, table_arg),
1584
1608
  primary_key(0), /* needs initialization because index_flags() may be called 
1585
1609
                     before this is set to the real value. It's ok to have any 
1608
1632
{
1609
1633
  trx_t*    trx;
1610
1634
 
1611
 
  assert(session);
1612
1635
  trx = check_trx_exists(session);
1613
1636
 
1614
1637
  if (prebuilt->trx != trx) {
1619
1642
  user_session = session;
1620
1643
}
1621
1644
 
 
1645
/*********************************************************************//**
 
1646
Updates the user_thd field in a handle and also allocates a new InnoDB
 
1647
transaction handle if needed, and updates the transaction fields in the
 
1648
prebuilt struct. */
 
1649
UNIV_INTERN
 
1650
void
 
1651
ha_innobase::update_session()
 
1652
/*=====================*/
 
1653
{
 
1654
  Session*  session = ha_session();
 
1655
  ut_ad(EQ_CURRENT_SESSION(session));
 
1656
  update_session(session);
 
1657
}
 
1658
 
1622
1659
/*****************************************************************//**
1623
1660
Convert an SQL identifier to the MySQL system_charset_info (UTF-8)
1624
1661
and quote it if needed.
1631
1668
  ulint   buflen, /*!< in: length of buf, in bytes */
1632
1669
  const char* id, /*!< in: identifier to convert */
1633
1670
  ulint   idlen,  /*!< in: length of id, in bytes */
1634
 
  drizzled::Session *session,/*!< in: MySQL connection thread, or NULL */
 
1671
  void*   session,/*!< in: MySQL connection thread, or NULL */
1635
1672
  ibool   file_id)/*!< in: TRUE=id is a table or database name;
1636
1673
        FALSE=id is an UTF-8 string */
1637
1674
{
1638
1675
  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]);
 
1676
  char nz2[NAME_LEN + 1 + sizeof srv_mysql50_table_name_prefix];
1641
1677
 
1642
1678
  const char* s = id;
1643
1679
  int   q;
1654
1690
    memcpy(nz, id, idlen);
1655
1691
    nz[idlen] = 0;
1656
1692
 
1657
 
    s = nz2.get();
1658
 
    idlen = identifier::Table::filename_to_tablename(nz, nz2.get(), nz2_size);
 
1693
    s = nz2;
 
1694
    idlen = filename_to_tablename(nz, nz2, sizeof nz2);
1659
1695
  }
1660
1696
 
1661
1697
  /* See if the identifier needs to be quoted. */
1709
1745
Convert a table or index name to the MySQL system_charset_info (UTF-8)
1710
1746
and quote it if needed.
1711
1747
@return pointer to the end of buf */
1712
 
UNIV_INTERN
 
1748
extern "C" UNIV_INTERN
1713
1749
char*
1714
1750
innobase_convert_name(
1715
1751
/*==================*/
1717
1753
  ulint   buflen, /*!< in: length of buf, in bytes */
1718
1754
  const char* id, /*!< in: identifier to convert */
1719
1755
  ulint   idlen,  /*!< in: length of id, in bytes */
1720
 
  drizzled::Session *session,/*!< in: MySQL connection thread, or NULL */
 
1756
  void*   session,/*!< in: MySQL connection thread, or NULL */
1721
1757
  ibool   table_id)/*!< in: TRUE=id is a table or database name;
1722
1758
        FALSE=id is an index name */
1723
1759
{
1765
1801
/**********************************************************************//**
1766
1802
Determines if the currently running transaction has been interrupted.
1767
1803
@return TRUE if interrupted */
1768
 
UNIV_INTERN
 
1804
extern "C" UNIV_INTERN
1769
1805
ibool
1770
1806
trx_is_interrupted(
1771
1807
/*===============*/
1772
1808
  trx_t*  trx)  /*!< in: transaction */
1773
1809
{
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);
 
1810
  return(trx && trx->mysql_thd && session_killed((Session*) trx->mysql_thd));
1788
1811
}
1789
1812
 
1790
1813
/**************************************************************//**
1800
1823
  prebuilt->read_just_key = 0;
1801
1824
}
1802
1825
 
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
1826
/*********************************************************************//**
2008
1827
Opens an InnoDB database.
2009
1828
@return 0 on success, error code on failure */
2011
1830
int
2012
1831
innobase_init(
2013
1832
/*==========*/
2014
 
  module::Context &context) /*!< in: Drizzle Plugin Context */
 
1833
  plugin::Context &context) /*!< in: Drizzle Plugin Context */
2015
1834
{
 
1835
  static char current_dir[3];   /*!< Set if using current lib */
2016
1836
  int   err;
2017
1837
  bool    ret;
 
1838
  char    *default_path;
2018
1839
  uint    format_id;
2019
 
  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
 
 
2066
 
  innodb_engine_ptr= actuall_engine_ptr= new InnobaseEngine(innobase_engine_name);
 
1840
 
 
1841
  innodb_engine_ptr= new InnobaseEngine(innobase_engine_name);
2067
1842
 
2068
1843
  ut_a(DATA_MYSQL_TRUE_VARCHAR == (ulint)DRIZZLE_TYPE_VARCHAR);
2069
1844
 
2070
1845
#ifdef UNIV_DEBUG
2071
1846
  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(),
2083
 
                test_filename)) {
2084
 
    errmsg_printf(error::ERROR, "tablename encoding has been changed");
 
1847
  char      test_tablename[sizeof test_filename
 
1848
        + sizeof srv_mysql50_table_name_prefix];
 
1849
  if ((sizeof test_tablename) - 1
 
1850
      != filename_to_tablename(test_filename, test_tablename,
 
1851
      sizeof test_tablename)
 
1852
      || strncmp(test_tablename,
 
1853
      srv_mysql50_table_name_prefix,
 
1854
      sizeof srv_mysql50_table_name_prefix)
 
1855
      || strcmp(test_tablename
 
1856
      + sizeof srv_mysql50_table_name_prefix,
 
1857
      test_filename)) {
 
1858
    errmsg_printf(ERRMSG_LVL_ERROR, "tablename encoding has been changed");
2085
1859
    goto error;
2086
1860
  }
2087
1861
#endif /* UNIV_DEBUG */
2088
1862
 
 
1863
  /* Check that values don't overflow on 32-bit systems. */
 
1864
  if (sizeof(ulint) == 4) {
 
1865
    if (innobase_buffer_pool_size > UINT32_MAX) {
 
1866
      errmsg_printf(ERRMSG_LVL_ERROR, 
 
1867
        "innobase_buffer_pool_size can't be over 4GB"
 
1868
        " on 32-bit systems");
 
1869
 
 
1870
      goto error;
 
1871
    }
 
1872
 
 
1873
    if (innobase_log_file_size > UINT32_MAX) {
 
1874
      errmsg_printf(ERRMSG_LVL_ERROR, 
 
1875
        "innobase_log_file_size can't be over 4GB"
 
1876
        " on 32-bit systems");
 
1877
 
 
1878
      goto error;
 
1879
    }
 
1880
  }
 
1881
 
2089
1882
  os_innodb_umask = (ulint)internal::my_umask;
2090
1883
 
 
1884
  /* First calculate the default path for innodb_data_home_dir etc.,
 
1885
  in case the user has not given any value.
 
1886
 
 
1887
  Note that when using the embedded server, the datadirectory is not
 
1888
  necessarily the current directory of this program. */
 
1889
 
 
1890
  /* It's better to use current lib, to keep paths short */
 
1891
  current_dir[0] = FN_CURLIB;
 
1892
  current_dir[1] = FN_LIBCHAR;
 
1893
  current_dir[2] = 0;
 
1894
  default_path = current_dir;
 
1895
 
 
1896
  ut_a(default_path);
 
1897
 
 
1898
  srv_set_thread_priorities = TRUE;
 
1899
  srv_query_thread_priority = QUERY_PRIOR;
2091
1900
 
2092
1901
  /* Set InnoDB initialization parameters according to the values
2093
 
    read from MySQL .cnf file */
 
1902
  read from MySQL .cnf file */
2094
1903
 
2095
1904
  /*--------------- Data files -------------------------*/
2096
1905
 
2097
1906
  /* The default dir for data files is the datadir of MySQL */
2098
1907
 
2099
 
  srv_data_home = (char *)innobase_data_home_dir.c_str();
 
1908
  srv_data_home = (innobase_data_home_dir ? innobase_data_home_dir :
 
1909
       default_path);
2100
1910
 
2101
1911
  /* Set default InnoDB data file size to 10 MB and let it be
2102
 
    auto-extending. Thus users can use InnoDB in >= 4.0 without having
2103
 
    to specify any startup options. */
 
1912
  auto-extending. Thus users can use InnoDB in >= 4.0 without having
 
1913
  to specify any startup options. */
2104
1914
 
2105
 
  if (innobase_data_file_path.empty()) 
2106
 
  {
2107
 
    innobase_data_file_path= std::string("ibdata1:10M:autoextend");
 
1915
  if (!innobase_data_file_path) {
 
1916
    innobase_data_file_path = (char*) "ibdata1:10M:autoextend";
2108
1917
  }
2109
1918
 
2110
1919
  /* Since InnoDB edits the argument in the next call, we make another
2111
 
    copy of it: */
 
1920
  copy of it: */
2112
1921
 
2113
 
  internal_innobase_data_file_path = strdup(innobase_data_file_path.c_str());
 
1922
  internal_innobase_data_file_path = strdup(innobase_data_file_path);
2114
1923
 
2115
1924
  ret = (bool) srv_parse_data_file_paths_and_sizes(
2116
 
                                                   internal_innobase_data_file_path);
 
1925
    internal_innobase_data_file_path);
2117
1926
  if (ret == FALSE) {
2118
 
    errmsg_printf(error::ERROR, "InnoDB: syntax error in innodb_data_file_path");
2119
 
 
 
1927
    errmsg_printf(ERRMSG_LVL_ERROR, 
 
1928
      "InnoDB: syntax error in innodb_data_file_path");
2120
1929
mem_free_and_error:
2121
1930
    srv_free_paths_and_sizes();
2122
1931
    if (internal_innobase_data_file_path)
2128
1937
 
2129
1938
  /* The default dir for log files is the datadir of MySQL */
2130
1939
 
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
 
  }
 
1940
  if (!innobase_log_group_home_dir) {
 
1941
    innobase_log_group_home_dir = default_path;
 
1942
  }
 
1943
 
 
1944
#ifdef UNIV_LOG_ARCHIVE
 
1945
  /* Since innodb_log_arch_dir has no relevance under MySQL,
 
1946
  starting from 4.0.6 we always set it the same as
 
1947
  innodb_log_group_home_dir: */
 
1948
 
 
1949
  innobase_log_arch_dir = innobase_log_group_home_dir;
 
1950
 
 
1951
  srv_arch_dir = innobase_log_arch_dir;
 
1952
#endif /* UNIG_LOG_ARCHIVE */
2139
1953
 
2140
1954
  ret = (bool)
2141
 
    srv_parse_log_group_home_dirs((char *)innobase_log_group_home_dir.c_str());
 
1955
    srv_parse_log_group_home_dirs(innobase_log_group_home_dir);
2142
1956
 
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"));
 
1957
  if (ret == FALSE || innobase_mirrored_log_groups != 1) {
 
1958
    errmsg_printf(ERRMSG_LVL_ERROR, "syntax error in innodb_log_group_home_dir, or a "
 
1959
        "wrong number of mirrored log groups");
2146
1960
 
2147
1961
    goto mem_free_and_error;
2148
1962
  }
2149
1963
 
2150
 
 
2151
1964
  /* Validate the file format by animal name */
2152
 
  if (vm.count("file-format"))
2153
 
  {
 
1965
  if (innobase_file_format_name != NULL) {
 
1966
 
2154
1967
    format_id = innobase_file_format_name_lookup(
2155
 
                                                 vm["file-format"].as<string>().c_str());
 
1968
      innobase_file_format_name);
2156
1969
 
2157
1970
    if (format_id > DICT_TF_FORMAT_MAX) {
2158
1971
 
2159
 
      errmsg_printf(error::ERROR, "InnoDB: wrong innodb_file_format.");
 
1972
      errmsg_printf(ERRMSG_LVL_ERROR, "InnoDB: wrong innodb_file_format.");
2160
1973
 
2161
1974
      goto mem_free_and_error;
2162
1975
    }
2163
1976
  } else {
2164
 
    /* Set it to the default file format id.*/
 
1977
    /* Set it to the default file format id. Though this
 
1978
    should never happen. */
2165
1979
    format_id = 0;
2166
1980
  }
2167
1981
 
2168
1982
  srv_file_format = format_id;
2169
1983
 
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
 
  {
 
1984
  /* Given the type of innobase_file_format_name we have little
 
1985
  choice but to cast away the constness from the returned name.
 
1986
  innobase_file_format_name is used in the MySQL set variable
 
1987
  interface and so can't be const. */
 
1988
 
 
1989
  innobase_file_format_name = 
 
1990
    (char*) trx_sys_file_format_id_to_name(format_id);
 
1991
 
 
1992
  /* Process innobase_file_format_check variable */
 
1993
  ut_a(innobase_file_format_check != NULL);
 
1994
 
 
1995
  /* As a side effect it will set srv_check_file_format_at_startup
 
1996
  on valid input. First we check for "on"/"off". */
 
1997
  if (!innobase_file_format_check_on_off(innobase_file_format_check)) {
 
1998
 
 
1999
    /* Did the user specify a format name that we support ?
 
2000
    As a side effect it will update the variable
 
2001
    srv_check_file_format_at_startup */
 
2002
    if (!innobase_file_format_check_validate(
 
2003
      innobase_file_format_check)) {
 
2004
 
 
2005
      errmsg_printf(ERRMSG_LVL_ERROR, "InnoDB: invalid "
 
2006
          "innodb_file_format_check value: "
 
2007
          "should be either 'on' or 'off' or "
 
2008
          "any value up to %s or its "
 
2009
          "equivalent numeric id",
 
2010
          trx_sys_file_format_id_to_name(
 
2011
            DICT_TF_FORMAT_MAX));
 
2012
 
 
2013
      goto mem_free_and_error;
 
2014
    }
 
2015
  }
 
2016
 
 
2017
  if (innobase_change_buffering) {
2196
2018
    ulint use;
2197
2019
 
2198
2020
    for (use = 0;
2199
2021
         use < UT_ARR_SIZE(innobase_change_buffering_values);
2200
2022
         use++) {
2201
2023
      if (!innobase_strcasecmp(
2202
 
                               innobase_change_buffering.c_str(),
2203
 
                               innobase_change_buffering_values[use])) {
2204
 
        ibuf_use = static_cast<ibuf_use_t>(use);
 
2024
            innobase_change_buffering,
 
2025
            innobase_change_buffering_values[use])) {
 
2026
        ibuf_use = (ibuf_use_t) use;
2205
2027
        goto innobase_change_buffering_inited_ok;
2206
2028
      }
2207
2029
    }
2208
2030
 
2209
 
    errmsg_printf(error::ERROR, "InnoDB: invalid value innodb_change_buffering=%s",
2210
 
                  vm["change-buffering"].as<string>().c_str());
 
2031
    errmsg_printf(ERRMSG_LVL_ERROR,
 
2032
        "InnoDB: invalid value "
 
2033
        "innodb_file_format_check=%s",
 
2034
        innobase_change_buffering);
2211
2035
    goto mem_free_and_error;
2212
2036
  }
2213
2037
 
2214
2038
innobase_change_buffering_inited_ok:
2215
2039
  ut_a((ulint) ibuf_use < UT_ARR_SIZE(innobase_change_buffering_values));
2216
 
  innobase_change_buffering = innobase_change_buffering_values[ibuf_use];
 
2040
  innobase_change_buffering = (char*)
 
2041
    innobase_change_buffering_values[ibuf_use];
2217
2042
 
2218
2043
  /* --------------------------------------------------*/
2219
2044
 
2220
 
  if (vm.count("flush-method") != 0)
2221
 
  {
2222
 
    srv_file_flush_method_str = (char *)vm["flush-method"].as<string>().c_str();
2223
 
  }
 
2045
  srv_file_flush_method_str = innobase_unix_file_flush_method;
2224
2046
 
2225
2047
  srv_n_log_groups = (ulint) innobase_mirrored_log_groups;
2226
2048
  srv_n_log_files = (ulint) innobase_log_files_in_group;
2227
2049
  srv_log_file_size = (ulint) innobase_log_file_size;
2228
2050
 
 
2051
#ifdef UNIV_LOG_ARCHIVE
 
2052
  srv_log_archive_on = (ulint) innobase_log_archive;
 
2053
#endif /* UNIV_LOG_ARCHIVE */
2229
2054
  srv_log_buffer_size = (ulint) innobase_log_buffer_size;
2230
2055
 
2231
2056
  srv_buf_pool_size = (ulint) innobase_buffer_pool_size;
2232
 
  srv_buf_pool_instances = (ulint) innobase_buffer_pool_instances;
2233
2057
 
2234
2058
  srv_mem_pool_size = (ulint) innobase_additional_mem_pool_size;
2235
2059
 
 
2060
  srv_n_file_io_threads = (ulint) innobase_file_io_threads;
2236
2061
  srv_n_read_io_threads = (ulint) innobase_read_io_threads;
2237
2062
  srv_n_write_io_threads = (ulint) innobase_write_io_threads;
2238
2063
 
2242
2067
  srv_use_checksums = (ibool) innobase_use_checksums;
2243
2068
 
2244
2069
#ifdef HAVE_LARGE_PAGES
2245
 
  if ((os_use_large_pages = (ibool) my_use_large_pages))
 
2070
        if ((os_use_large_pages = (ibool) my_use_large_pages))
2246
2071
    os_large_page_size = (ulint) opt_large_page_size;
2247
2072
#endif
2248
2073
 
2256
2081
  srv_print_verbose_log = true;
2257
2082
 
2258
2083
  /* Store the default charset-collation number of this MySQL
2259
 
    installation */
 
2084
  installation */
2260
2085
 
2261
2086
  data_mysql_default_charset_coll = (ulint)default_charset_info->number;
2262
2087
 
 
2088
 
 
2089
  innobase_commit_concurrency_init_default();
 
2090
 
2263
2091
  /* Since we in this module access directly the fields of a trx
2264
 
    struct, and due to different headers and flags it might happen that
2265
 
    mutex_t has a different size in this module and in InnoDB
2266
 
    modules, we check at run time that the size is the same in
2267
 
    these compilation modules. */
 
2092
  struct, and due to different headers and flags it might happen that
 
2093
  mutex_t has a different size in this module and in InnoDB
 
2094
  modules, we check at run time that the size is the same in
 
2095
  these compilation modules. */
2268
2096
 
2269
2097
  err = innobase_start_or_create_for_mysql();
2270
2098
 
2271
 
  if (err != DB_SUCCESS)
2272
 
  {
2273
 
    goto mem_free_and_error;
2274
 
  }
2275
 
 
2276
 
  err = dict_create_sys_replication_log();
2277
 
 
2278
2099
  if (err != DB_SUCCESS) {
2279
2100
    goto mem_free_and_error;
2280
2101
  }
2281
2102
 
2282
 
 
2283
 
  innobase_old_blocks_pct = buf_LRU_old_ratio_update(innobase_old_blocks_pct.get(),
2284
 
                                                     TRUE);
2285
 
 
2286
2103
  innobase_open_tables = hash_create(200);
 
2104
  pthread_mutex_init(&innobase_share_mutex, MY_MUTEX_INIT_FAST);
 
2105
  pthread_mutex_init(&prepare_commit_mutex, MY_MUTEX_INIT_FAST);
 
2106
  pthread_mutex_init(&commit_threads_m, MY_MUTEX_INIT_FAST);
 
2107
  pthread_mutex_init(&commit_cond_m, MY_MUTEX_INIT_FAST);
 
2108
  pthread_cond_init(&commit_cond, NULL);
2287
2109
  innodb_inited= 1;
2288
2110
 
2289
 
  actuall_engine_ptr->dropTemporarySchema();
2290
 
 
2291
 
  context.add(new InnodbStatusTool);
 
2111
        status_table_function_ptr= new InnodbStatusTool;
2292
2112
 
2293
2113
  context.add(innodb_engine_ptr);
2294
2114
 
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());
2322
 
 
2323
 
  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));
 
2115
  context.add(status_table_function_ptr);
 
2116
 
 
2117
  cmp_tool= new(std::nothrow)CmpTool(false);
 
2118
  context.add(cmp_tool);
 
2119
 
 
2120
  cmp_reset_tool= new(std::nothrow)CmpTool(true);
 
2121
  context.add(cmp_reset_tool);
 
2122
 
 
2123
  cmp_mem_tool= new(std::nothrow)CmpmemTool(false);
 
2124
  context.add(cmp_mem_tool);
 
2125
 
 
2126
  cmp_mem_reset_tool= new(std::nothrow)CmpmemTool(true);
 
2127
  context.add(cmp_mem_reset_tool);
 
2128
 
 
2129
  innodb_trx_tool= new(std::nothrow)InnodbTrxTool("INNODB_TRX");
 
2130
  context.add(innodb_trx_tool);
 
2131
 
 
2132
  innodb_locks_tool= new(std::nothrow)InnodbTrxTool("INNODB_LOCKS");
 
2133
  context.add(innodb_locks_tool);
 
2134
 
 
2135
  innodb_lock_waits_tool= new(std::nothrow)InnodbTrxTool("INNODB_LOCK_WAITS");
 
2136
  context.add(innodb_lock_waits_tool);
 
2137
 
2414
2138
  /* 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);
 
2139
  innobase_file_format_check = (char*) trx_sys_file_format_max_get();
2417
2140
 
2418
2141
  return(FALSE);
2419
 
 
2420
2142
error:
2421
2143
  return(TRUE);
2422
2144
}
2513
2235
    trx_search_latch_release_if_reserved(trx);
2514
2236
  }
2515
2237
 
2516
 
  if (all)
2517
 
  {
 
2238
  if (all
 
2239
    || (!session_test_options(session, OPTION_NOT_AUTOCOMMIT | OPTION_BEGIN))) {
 
2240
 
2518
2241
    /* We were instructed to commit the whole transaction, or
2519
2242
    this is an SQL statement end and autocommit is on */
2520
2243
 
2521
2244
    /* We need current binlog position for ibbackup to work.
2522
2245
    Note, the position is current because of
2523
2246
    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
 
 
 
2247
retry:
 
2248
    if (innobase_commit_concurrency > 0) {
 
2249
      pthread_mutex_lock(&commit_cond_m);
 
2250
      commit_threads++;
 
2251
 
 
2252
      if (commit_threads > innobase_commit_concurrency) {
2535
2253
        commit_threads--;
2536
 
        commit_cond.wait(scopedLock);
2537
 
      } while (1);
 
2254
        pthread_cond_wait(&commit_cond,
 
2255
          &commit_cond_m);
 
2256
        pthread_mutex_unlock(&commit_cond_m);
 
2257
        goto retry;
 
2258
      }
 
2259
      else {
 
2260
        pthread_mutex_unlock(&commit_cond_m);
 
2261
      }
2538
2262
    }
2539
2263
 
2540
 
    trx->mysql_log_file_name = NULL;
 
2264
                /* Store transaction point for binlog
 
2265
    Later logic tests that this is set to _something_. We need
 
2266
    that logic to fire, even though we do not have a real name. */
 
2267
    trx->mysql_log_file_name = "UNUSED";
2541
2268
    trx->mysql_log_offset = 0;
2542
2269
 
2543
2270
    /* Don't do write + flush right now. For group commit
2547
2274
    innobase_commit_low(trx);
2548
2275
    trx->flush_log_later = FALSE;
2549
2276
 
2550
 
    if (commit_concurrency)
2551
 
    {
2552
 
      boost::mutex::scoped_lock scopedLock(commit_cond_m);
 
2277
    if (innobase_commit_concurrency > 0) {
 
2278
      pthread_mutex_lock(&commit_cond_m);
2553
2279
      commit_threads--;
2554
 
      commit_cond.notify_one();
 
2280
      pthread_cond_signal(&commit_cond);
 
2281
      pthread_mutex_unlock(&commit_cond_m);
2555
2282
    }
2556
2283
 
2557
2284
    /* Now do a write + flush of logs. */
2571
2298
    SQL statement */
2572
2299
 
2573
2300
    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
2301
  }
2583
2302
 
2584
2303
  trx->n_autoinc_rows = 0; /* Reset the number AUTO-INC rows required */
2593
2312
  threads: */
2594
2313
  srv_active_wake_master_thread();
2595
2314
 
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
2315
  return(0);
2605
2316
}
2606
2317
 
2628
2339
 
2629
2340
  innobase_release_stat_resources(trx);
2630
2341
 
2631
 
  trx->n_autoinc_rows = 0;
2632
 
 
2633
2342
  /* If we had reserved the auto-inc lock for some table (if
2634
2343
  we come here to roll back the latest SQL statement) we
2635
2344
  release it now before a possibly lengthy rollback */
2636
2345
 
2637
2346
  row_unlock_table_autoinc_for_mysql(trx);
2638
2347
 
2639
 
  if (all)
2640
 
  {
 
2348
  if (all
 
2349
    || !session_test_options(session, OPTION_NOT_AUTOCOMMIT | OPTION_BEGIN)) {
 
2350
 
2641
2351
    error = trx_rollback_for_mysql(trx);
2642
2352
  } else {
2643
2353
    error = trx_rollback_last_sql_stat_for_mysql(trx);
2644
2354
  }
2645
2355
 
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
2356
  return(convert_error_code_to_mysql(error, 0, NULL));
2655
2357
}
2656
2358
 
2787
2489
 
2788
2490
  ut_a(trx);
2789
2491
 
2790
 
  assert(session->getKilled() != Session::NOT_KILLED ||
 
2492
  assert(session->killed != Session::NOT_KILLED ||
2791
2493
         trx->conc_state == TRX_NOT_STARTED);
2792
2494
 
2793
2495
  /* Warn if rolling back some things... */
2794
 
  if (session->getKilled() != Session::NOT_KILLED &&
 
2496
  if (session->killed != Session::NOT_KILLED &&
2795
2497
      trx->conc_state != TRX_NOT_STARTED &&
2796
 
      trx->undo_no > 0 &&
 
2498
      trx->undo_no.low > 0 &&
2797
2499
      global_system_variables.log_warnings)
2798
2500
  {
2799
 
      errmsg_printf(error::WARN,
 
2501
      errmsg_printf(ERRMSG_LVL_WARN, 
2800
2502
      "Drizzle is closing a connection during a KILL operation\n"
2801
 
      "that has an active InnoDB transaction.  %llu row modifications will "
 
2503
      "that has an active InnoDB transaction.  %lu row modifications will "
2802
2504
      "roll back.\n",
2803
 
      (ullint) trx->undo_no);
 
2505
      (ulong) trx->undo_no.low);
2804
2506
  }
2805
2507
 
2806
2508
  innobase_rollback_trx(trx);
2817
2519
*****************************************************************************/
2818
2520
 
2819
2521
/****************************************************************//**
 
2522
Get the record format from the data dictionary.
 
2523
@return one of ROW_TYPE_REDUNDANT, ROW_TYPE_COMPACT,
 
2524
ROW_TYPE_COMPRESSED, ROW_TYPE_DYNAMIC */
 
2525
UNIV_INTERN
 
2526
enum row_type
 
2527
ha_innobase::get_row_type() const
 
2528
/*=============================*/
 
2529
{
 
2530
  if (prebuilt && prebuilt->table) {
 
2531
    const ulint flags = prebuilt->table->flags;
 
2532
 
 
2533
    if (UNIV_UNLIKELY(!flags)) {
 
2534
      return(ROW_TYPE_REDUNDANT);
 
2535
    }
 
2536
 
 
2537
    ut_ad(flags & DICT_TF_COMPACT);
 
2538
 
 
2539
    switch (flags & DICT_TF_FORMAT_MASK) {
 
2540
    case DICT_TF_FORMAT_51 << DICT_TF_FORMAT_SHIFT:
 
2541
      return(ROW_TYPE_COMPACT);
 
2542
    case DICT_TF_FORMAT_ZIP << DICT_TF_FORMAT_SHIFT:
 
2543
      if (flags & DICT_TF_ZSSIZE_MASK) {
 
2544
        return(ROW_TYPE_COMPRESSED);
 
2545
      } else {
 
2546
        return(ROW_TYPE_DYNAMIC);
 
2547
      }
 
2548
#if DICT_TF_FORMAT_ZIP != DICT_TF_FORMAT_MAX
 
2549
# error "DICT_TF_FORMAT_ZIP != DICT_TF_FORMAT_MAX"
 
2550
#endif
 
2551
    }
 
2552
  }
 
2553
  ut_ad(0);
 
2554
  return(ROW_TYPE_NOT_USED);
 
2555
}
 
2556
 
 
2557
 
 
2558
/****************************************************************//**
2820
2559
Returns the index type. */
2821
2560
UNIV_INTERN
2822
2561
const char*
2876
2615
  return(true);
2877
2616
}
2878
2617
 
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]);
 
2618
/*****************************************************************//**
 
2619
Normalizes a table name string. A normalized name consists of the
 
2620
database name catenated to '/' and table name. An example:
 
2621
test/mytable. On Windows normalization puts both the database name and the
 
2622
table name always to lower case. */
 
2623
static
 
2624
void
 
2625
normalize_table_name(
 
2626
/*=================*/
 
2627
  char*   norm_name,  /*!< out: normalized name as a
 
2628
          null-terminated string */
 
2629
  const char* name)   /*!< in: table name string */
 
2630
{
 
2631
  const char* name_ptr;
 
2632
  const char* db_ptr;
 
2633
  const char* ptr;
 
2634
 
 
2635
  /* Scan name from the end */
 
2636
 
 
2637
  ptr = strchr(name, '\0')-1;
 
2638
 
 
2639
  while (ptr >= name && *ptr != '\\' && *ptr != '/') {
 
2640
    ptr--;
 
2641
  }
 
2642
 
 
2643
  name_ptr = ptr + 1;
 
2644
 
 
2645
  assert(ptr > name);
 
2646
 
 
2647
  ptr--;
 
2648
 
 
2649
  while (ptr >= name && *ptr != '\\' && *ptr != '/') {
 
2650
    ptr--;
 
2651
  }
 
2652
 
 
2653
  db_ptr = ptr + 1;
 
2654
 
 
2655
  memcpy(norm_name, db_ptr, strlen(name) + 1 - (db_ptr - name));
 
2656
 
 
2657
  norm_name[name_ptr - db_ptr - 1] = '/';
 
2658
 
 
2659
#ifdef __WIN__
 
2660
  innobase_casedn_str(norm_name);
 
2661
#endif
3127
2662
}
3128
2663
 
3129
2664
/********************************************************************//**
3130
2665
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. */
 
2666
ha_innobase::open(). Therefore there's no need for a covering lock.
 
2667
@return DB_SUCCESS or error code */
3132
2668
UNIV_INTERN
3133
 
void
 
2669
ulint
3134
2670
ha_innobase::innobase_initialize_autoinc()
3135
2671
/*======================================*/
3136
2672
{
 
2673
  dict_index_t* index;
3137
2674
  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
 
 
 
2675
  const char* col_name;
 
2676
  ulint   error;
 
2677
 
 
2678
  col_name = table->found_next_number_field->field_name;
 
2679
  index = innobase_get_index(table->s->next_number_index);
 
2680
 
 
2681
  /* Execute SELECT MAX(col_name) FROM TABLE; */
 
2682
  error = row_search_max_autoinc(index, col_name, &auto_inc);
 
2683
 
 
2684
  switch (error) {
 
2685
  case DB_SUCCESS:
 
2686
 
 
2687
    /* At the this stage we don't know the increment
 
2688
    or the offset, so use default inrement of 1. */
 
2689
    ++auto_inc;
 
2690
    break;
 
2691
 
 
2692
  case DB_RECORD_NOT_FOUND:
3148
2693
    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
 
    }
 
2694
    fprintf(stderr, "  InnoDB: MySQL and InnoDB data "
 
2695
      "dictionaries are out of sync.\n"
 
2696
      "InnoDB: Unable to find the AUTOINC column %s in the "
 
2697
      "InnoDB table %s.\n"
 
2698
      "InnoDB: We set the next AUTOINC column value to the "
 
2699
      "maximum possible value,\n"
 
2700
      "InnoDB: in effect disabling the AUTOINC next value "
 
2701
      "generation.\n"
 
2702
      "InnoDB: You can either set the next AUTOINC value "
 
2703
      "explicitly using ALTER TABLE\n"
 
2704
      "InnoDB: or fix the data dictionary by recreating "
 
2705
      "the table.\n",
 
2706
      col_name, index->table->name);
 
2707
 
 
2708
    auto_inc = 0xFFFFFFFFFFFFFFFFULL;
 
2709
    break;
 
2710
 
 
2711
  default:
 
2712
    return(error);
3220
2713
  }
3221
2714
 
3222
2715
  dict_table_autoinc_initialize(prebuilt->table, auto_inc);
 
2716
 
 
2717
  return(DB_SUCCESS);
3223
2718
}
3224
2719
 
3225
2720
/*****************************************************************//**
3228
2723
@return 1 if error, 0 if success */
3229
2724
UNIV_INTERN
3230
2725
int
3231
 
ha_innobase::doOpen(const identifier::Table &identifier,
3232
 
                    int   mode,   /*!< in: not used */
3233
 
                    uint    test_if_locked) /*!< in: not used */
 
2726
ha_innobase::open(
 
2727
/*==============*/
 
2728
  const char* name,   /*!< in: table name */
 
2729
  int   mode,   /*!< in: not used */
 
2730
  uint    test_if_locked) /*!< in: not used */
3234
2731
{
3235
2732
  dict_table_t* ib_table;
 
2733
  char    norm_name[1000];
3236
2734
  Session*    session;
 
2735
  ulint   retries = 0;
 
2736
  char*   is_part = NULL;
3237
2737
 
3238
2738
  UT_NOT_USED(mode);
3239
2739
  UT_NOT_USED(test_if_locked);
3240
2740
 
3241
 
  session= getTable()->in_use;
 
2741
  session = ha_session();
3242
2742
 
3243
2743
  /* Under some cases Drizzle seems to call this function while
3244
2744
  holding btr_search_latch. This breaks the latching order as
3247
2747
    getTransactionalEngine()->releaseTemporaryLatches(session);
3248
2748
  }
3249
2749
 
 
2750
  normalize_table_name(norm_name, name);
 
2751
 
3250
2752
  user_session = NULL;
3251
2753
 
3252
 
  std::string search_string(identifier.getSchemaName());
3253
 
  boost::algorithm::to_lower(search_string);
 
2754
  if (!(share=get_share(name))) {
3254
2755
 
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
 
    }
 
2756
    return(1);
3270
2757
  }
3271
2758
 
3272
2759
  /* Create buffers for packing the fields of a record. Why
3275
2762
  stored the string length as the first byte. */
3276
2763
 
3277
2764
  upd_and_key_val_buff_len =
3278
 
        getTable()->getShare()->sizeStoredRecord()
3279
 
        + getTable()->getShare()->max_key_length
 
2765
        table->s->stored_rec_length
 
2766
        + table->s->max_key_length
3280
2767
        + MAX_REF_PARTS * 3;
3281
2768
 
3282
 
  upd_buff.resize(upd_and_key_val_buff_len);
 
2769
  upd_buff= (unsigned char*)malloc(upd_and_key_val_buff_len);
3283
2770
 
3284
 
  if (upd_buff.size() < upd_and_key_val_buff_len)
 
2771
  if (upd_buff == NULL)
3285
2772
  {
3286
2773
    free_share(share);
3287
2774
  }
3288
2775
 
3289
 
  key_val_buff.resize(upd_and_key_val_buff_len);
3290
 
  if (key_val_buff.size() < upd_and_key_val_buff_len)
 
2776
  key_val_buff= (unsigned char*)malloc(upd_and_key_val_buff_len);
 
2777
  if (key_val_buff == NULL)
3291
2778
  {
 
2779
    free_share(share);
 
2780
    free(upd_buff);
3292
2781
    return(1);
3293
2782
  }
3294
2783
 
 
2784
 
 
2785
 
 
2786
  /* We look for pattern #P# to see if the table is partitioned
 
2787
  MySQL table. The retry logic for partitioned tables is a
 
2788
  workaround for http://bugs.mysql.com/bug.php?id=33349. Look
 
2789
  at support issue https://support.mysql.com/view.php?id=21080
 
2790
  for more details. */
 
2791
  is_part = strstr(norm_name, "#P#");
 
2792
retry:
3295
2793
  /* 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
 
  }
 
2794
  ib_table = dict_table_get(norm_name, TRUE);
3306
2795
  
3307
2796
  if (NULL == ib_table) {
3308
 
    errmsg_printf(error::ERROR, "Cannot find or open table %s from\n"
 
2797
    if (is_part && retries < 10) {
 
2798
      ++retries;
 
2799
      os_thread_sleep(100000);
 
2800
      goto retry;
 
2801
    }
 
2802
 
 
2803
    if (is_part) {
 
2804
      errmsg_printf(ERRMSG_LVL_ERROR, "Failed to open table %s after "
 
2805
          "%lu attemtps.\n", norm_name,
 
2806
          retries);
 
2807
    }
 
2808
 
 
2809
    errmsg_printf(ERRMSG_LVL_ERROR, "Cannot find or open table %s from\n"
3309
2810
        "the internal data dictionary of InnoDB "
3310
2811
        "though the .frm file for the\n"
3311
2812
        "table exists. Maybe you have deleted and "
3319
2820
        "doesn't support.\n"
3320
2821
        "See " REFMAN "innodb-troubleshooting.html\n"
3321
2822
        "how you can resolve the problem.\n",
3322
 
        identifier.getKeyPath().c_str());
 
2823
        norm_name);
3323
2824
    free_share(share);
3324
 
    upd_buff.resize(0);
3325
 
    key_val_buff.resize(0);
 
2825
    free(upd_buff);
 
2826
    free(key_val_buff);
3326
2827
    errno = ENOENT;
3327
2828
 
3328
2829
    return(HA_ERR_NO_SUCH_TABLE);
3329
2830
  }
3330
2831
 
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 "
 
2832
  if (ib_table->ibd_file_missing && !session_tablespace_op(session)) {
 
2833
    errmsg_printf(ERRMSG_LVL_ERROR, "MySQL is trying to open a table handle but "
3333
2834
        "the .ibd file for\ntable %s does not exist.\n"
3334
2835
        "Have you deleted the .ibd file from the "
3335
2836
        "database directory under\nthe MySQL datadir, "
3336
2837
        "or have you used DISCARD TABLESPACE?\n"
3337
2838
        "See " REFMAN "innodb-troubleshooting.html\n"
3338
2839
        "how you can resolve the problem.\n",
3339
 
        identifier.getKeyPath().c_str());
 
2840
        norm_name);
3340
2841
    free_share(share);
3341
 
    upd_buff.resize(0);
3342
 
    key_val_buff.resize(0);
 
2842
    free(upd_buff);
 
2843
    free(key_val_buff);
3343
2844
    errno = ENOENT;
3344
2845
 
3345
2846
    dict_table_decrement_handle_count(ib_table, FALSE);
3348
2849
 
3349
2850
  prebuilt = row_create_prebuilt(ib_table);
3350
2851
 
3351
 
  prebuilt->mysql_row_len = getTable()->getShare()->sizeStoredRecord();
3352
 
  prebuilt->default_rec = getTable()->getDefaultValues();
 
2852
  prebuilt->mysql_row_len = table->s->stored_rec_length;
 
2853
  prebuilt->default_rec = table->s->default_values;
3353
2854
  ut_ad(prebuilt->default_rec);
3354
2855
 
3355
2856
  /* Looks like MySQL-3.23 sometimes has primary key number != 0 */
3356
2857
 
3357
 
  primary_key = getTable()->getShare()->getPrimaryKey();
 
2858
  primary_key = table->s->primary_key;
3358
2859
  key_used_on_scan = primary_key;
3359
2860
 
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
2861
  /* Allocate a buffer for a 'row reference'. A row reference is
3366
2862
  a string of bytes of length ref_length which uniquely specifies
3367
2863
  a row in our table. Note that MySQL may also compare two row
3369
2865
  of length ref_length! */
3370
2866
 
3371
2867
  if (!row_table_got_default_clust_index(ib_table)) {
 
2868
    if (primary_key >= MAX_KEY) {
 
2869
      errmsg_printf(ERRMSG_LVL_ERROR, "Table %s has a primary key in InnoDB data "
 
2870
          "dictionary, but not in MySQL!", name);
 
2871
    }
3372
2872
 
3373
2873
    prebuilt->clust_index_was_generated = FALSE;
3374
2874
 
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
 
    }
 
2875
    /* MySQL allocates the buffer for ref. key_info->key_length
 
2876
    includes space for all key columns + one byte for each column
 
2877
    that may be NULL. ref_length must be as exact as possible to
 
2878
    save space, because all row reference buffers are allocated
 
2879
    based on ref_length. */
 
2880
 
 
2881
    ref_length = table->key_info[primary_key].key_length;
3429
2882
  } else {
3430
2883
    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());
 
2884
      errmsg_printf(ERRMSG_LVL_ERROR, "Table %s has no primary key in InnoDB data "
 
2885
          "dictionary, but has one in MySQL! If you "
 
2886
          "created the table with a MySQL version < "
 
2887
          "3.23.54 and did not define a primary key, "
 
2888
          "but defined a unique key with all non-NULL "
 
2889
          "columns, then MySQL internally treats that "
 
2890
          "key as the primary key. You can fix this "
 
2891
          "error by dump + DROP + CREATE + reimport "
 
2892
          "of the table.", name);
3452
2893
    }
3453
2894
 
3454
2895
    prebuilt->clust_index_was_generated = TRUE;
3464
2905
    and it will never be updated anyway. */
3465
2906
 
3466
2907
    if (key_used_on_scan != MAX_KEY) {
3467
 
      errmsg_printf(error::WARN, 
 
2908
      errmsg_printf(ERRMSG_LVL_WARN, 
3468
2909
        "Table %s key_used_on_scan is %lu even "
3469
2910
        "though there is no primary key inside "
3470
 
        "InnoDB.", identifier.getTableName().c_str(), (ulong) key_used_on_scan);
 
2911
        "InnoDB.", name, (ulong) key_used_on_scan);
3471
2912
    }
3472
2913
  }
3473
2914
 
3475
2916
  stats.block_size = 16 * 1024;
3476
2917
 
3477
2918
  /* Init table lock structure */
3478
 
  lock.init(&share->lock);
 
2919
  thr_lock_data_init(&share->lock,&lock,(void*) 0);
3479
2920
 
3480
2921
  if (prebuilt->table) {
3481
2922
    /* We update the highest file format in the system table
3482
2923
    space, if this table has higher file format setting. */
3483
2924
 
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,
 
2925
    trx_sys_file_format_max_upgrade(
 
2926
      (const char**) &innobase_file_format_check,
3487
2927
      dict_table_get_format(prebuilt->table));
3488
 
    innobase_file_format_max= changed_file_format_max;
3489
2928
  }
3490
2929
 
 
2930
  info(HA_STATUS_NO_LOCK | HA_STATUS_VARIABLE | HA_STATUS_CONST);
 
2931
 
3491
2932
  /* Only if the table has an AUTOINC column. */
3492
 
  if (prebuilt->table != NULL && getTable()->found_next_number_field != NULL) {
 
2933
  if (prebuilt->table != NULL && table->found_next_number_field != NULL) {
 
2934
    ulint error;
3493
2935
 
3494
2936
    dict_table_autoinc_lock(prebuilt->table);
3495
2937
 
3499
2941
    autoinc value from a previous Drizzle open. */
3500
2942
    if (dict_table_autoinc_read(prebuilt->table) == 0) {
3501
2943
 
3502
 
      innobase_initialize_autoinc();
 
2944
      error = innobase_initialize_autoinc();
 
2945
      ut_a(error == DB_SUCCESS);
3503
2946
    }
3504
2947
 
3505
2948
    dict_table_autoinc_unlock(prebuilt->table);
3506
2949
  }
3507
2950
 
3508
 
  info(HA_STATUS_NO_LOCK | HA_STATUS_VARIABLE | HA_STATUS_CONST);
3509
 
 
3510
2951
  return(0);
3511
2952
}
3512
2953
 
3527
2968
{
3528
2969
  Session*  session;
3529
2970
 
3530
 
  session= getTable()->in_use;
 
2971
  session = ha_session();
3531
2972
  if (session != NULL) {
3532
2973
    getTransactionalEngine()->releaseTemporaryLatches(session);
3533
2974
  }
3534
2975
 
3535
2976
  row_prebuilt_free(prebuilt, FALSE);
3536
2977
 
3537
 
  upd_buff.clear();
3538
 
  key_val_buff.clear();
 
2978
  free(upd_buff);
 
2979
  free(key_val_buff);
3539
2980
  free_share(share);
3540
2981
 
3541
2982
  /* Tell InnoDB server that there might be work for
3558
2999
  Table*  table,  /*!< in: MySQL table object */
3559
3000
  Field*  field)  /*!< in: MySQL field object */
3560
3001
{
3561
 
  return((uint) (field->ptr - table->getInsertRecord()));
 
3002
  return((uint) (field->ptr - table->record[0]));
3562
3003
}
3563
3004
 
3564
3005
/**************************************************************//**
3581
3022
  }
3582
3023
 
3583
3024
  null_offset = (uint) ((char*) field->null_ptr
3584
 
          - (char*) table->getInsertRecord());
 
3025
          - (char*) table->record[0]);
3585
3026
 
3586
3027
  if (record[null_offset] & field->null_bit) {
3587
3028
 
3605
3046
  int null_offset;
3606
3047
 
3607
3048
  null_offset = (uint) ((char*) field->null_ptr
3608
 
          - (char*) table->getInsertRecord());
 
3049
          - (char*) table->record[0]);
3609
3050
 
3610
3051
  record[null_offset] = record[null_offset] | field->null_bit;
3611
3052
}
3616
3057
of this function is in rem0cmp.c in InnoDB source code! If you change this
3617
3058
function, remember to update the prototype there!
3618
3059
@return 1, 0, -1, if a is greater, equal, less than b, respectively */
3619
 
UNIV_INTERN int
 
3060
extern "C" UNIV_INTERN
 
3061
int
3620
3062
innobase_mysql_cmp(
3621
3063
/*===============*/
3622
3064
  int   mysql_type, /*!< in: MySQL type */
3631
3073
int
3632
3074
innobase_mysql_cmp(
3633
3075
/*===============*/
3634
 
          /* out: 1, 0, -1, if a is greater, equal, less than b, respectively */
 
3076
          /* out: 1, 0, -1, if a is greater,
 
3077
          equal, less than b, respectively */
3635
3078
  int   mysql_type, /* in: MySQL type */
3636
3079
  uint    charset_number, /* in: number of the charset */
3637
3080
  const unsigned char* a,   /* in: data field */
3638
 
  unsigned int  a_length, /* in: data field length, not UNIV_SQL_NULL */
 
3081
  unsigned int  a_length, /* in: data field length,
 
3082
          not UNIV_SQL_NULL */
3639
3083
  const unsigned char* b,   /* in: data field */
3640
 
  unsigned int  b_length) /* in: data field length, not UNIV_SQL_NULL */
 
3084
  unsigned int  b_length) /* in: data field length,
 
3085
          not UNIV_SQL_NULL */
3641
3086
{
3642
3087
  const CHARSET_INFO* charset;
3643
3088
  enum_field_types  mysql_tp;
3653
3098
  case DRIZZLE_TYPE_BLOB:
3654
3099
  case DRIZZLE_TYPE_VARCHAR:
3655
3100
    /* Use the charset number to pick the right charset struct for
3656
 
      the comparison. Since the MySQL function get_charset may be
3657
 
      slow before Bar removes the mutex operation there, we first
3658
 
      look at 2 common charsets directly. */
 
3101
    the comparison. Since the MySQL function get_charset may be
 
3102
    slow before Bar removes the mutex operation there, we first
 
3103
    look at 2 common charsets directly. */
3659
3104
 
3660
3105
    if (charset_number == default_charset_info->number) {
3661
3106
      charset = default_charset_info;
3663
3108
      charset = get_charset(charset_number);
3664
3109
 
3665
3110
      if (charset == NULL) {
3666
 
        errmsg_printf(error::ERROR, "InnoDB needs charset %lu for doing "
3667
 
                      "a comparison, but MySQL cannot "
3668
 
                      "find that charset.",
3669
 
                      (ulong) charset_number);
 
3111
        errmsg_printf(ERRMSG_LVL_ERROR, "InnoDB needs charset %lu for doing "
 
3112
            "a comparison, but MySQL cannot "
 
3113
            "find that charset.",
 
3114
            (ulong) charset_number);
3670
3115
        ut_a(0);
3671
3116
      }
3672
3117
    }
3673
3118
 
3674
3119
    /* Starting from 4.1.3, we use strnncollsp() in comparisons of
3675
 
      non-latin1_swedish_ci strings. NOTE that the collation order
3676
 
      changes then: 'b\0\0...' is ordered BEFORE 'b  ...'. Users
3677
 
      having indexes on such data need to rebuild their tables! */
 
3120
    non-latin1_swedish_ci strings. NOTE that the collation order
 
3121
    changes then: 'b\0\0...' is ordered BEFORE 'b  ...'. Users
 
3122
    having indexes on such data need to rebuild their tables! */
3678
3123
 
3679
3124
    ret = charset->coll->strnncollsp(charset,
3680
 
                                     a, a_length,
3681
 
                                     b, b_length, 0);
 
3125
          a, a_length,
 
3126
             b, b_length, 0);
3682
3127
    if (ret < 0) {
3683
3128
      return(-1);
3684
3129
    } else if (ret > 0) {
3698
3143
the 'mtype' of InnoDB. InnoDB differentiates between MySQL's old <= 4.1
3699
3144
VARCHAR and the new true VARCHAR in >= 5.0.3 by the 'prtype'.
3700
3145
@return DATA_BINARY, DATA_VARCHAR, ... */
3701
 
UNIV_INTERN
 
3146
extern "C" UNIV_INTERN
3702
3147
ulint
3703
3148
get_innobase_type_from_mysql_type(
3704
3149
/*==============================*/
3747
3192
      return(DATA_VARMYSQL);
3748
3193
    }
3749
3194
  case DRIZZLE_TYPE_DECIMAL:
3750
 
  case DRIZZLE_TYPE_MICROTIME:
3751
3195
    return(DATA_FIXBINARY);
3752
3196
  case DRIZZLE_TYPE_LONG:
3753
3197
  case DRIZZLE_TYPE_LONGLONG:
3754
3198
  case DRIZZLE_TYPE_DATETIME:
3755
 
  case DRIZZLE_TYPE_TIME:
3756
3199
  case DRIZZLE_TYPE_DATE:
3757
3200
  case DRIZZLE_TYPE_TIMESTAMP:
3758
 
  case DRIZZLE_TYPE_ENUM:
3759
3201
    return(DATA_INT);
3760
3202
  case DRIZZLE_TYPE_DOUBLE:
3761
3203
    return(DATA_DOUBLE);
3762
3204
  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:
 
3205
                return(DATA_BLOB);
 
3206
  default:
3768
3207
    ut_error;
3769
3208
  }
3770
3209
 
3813
3252
  uint    buff_len,/*!< in: buffer length */
3814
3253
  const unsigned char*  record)/*!< in: row in MySQL format */
3815
3254
{
3816
 
  KeyInfo*    key_info  = &getTable()->key_info[keynr];
 
3255
  KeyInfo*    key_info  = table->key_info + keynr;
3817
3256
  KeyPartInfo*  key_part  = key_info->key_part;
3818
3257
  KeyPartInfo*  end   = key_part + key_info->key_parts;
3819
3258
  char*   buff_start  = buff;
3885
3324
      cs = field->charset();
3886
3325
 
3887
3326
      lenlen = (ulint)
3888
 
        (((Field_varstring*)field)->pack_length_no_ptr());
 
3327
        (((Field_varstring*)field)->length_bytes);
3889
3328
 
3890
3329
      data = row_mysql_read_true_varchar(&len,
3891
3330
        (byte*) (record
3892
 
        + (ulint)get_field_offset(getTable(), field)),
 
3331
        + (ulint)get_field_offset(table, field)),
3893
3332
        lenlen);
3894
3333
 
3895
3334
      true_len = len;
3952
3391
 
3953
3392
      blob_data = row_mysql_read_blob_ref(&blob_len,
3954
3393
        (byte*) (record
3955
 
        + (ulint)get_field_offset(getTable(), field)),
 
3394
        + (ulint)get_field_offset(table, field)),
3956
3395
          (ulint) field->pack_length());
3957
3396
 
3958
3397
      true_len = blob_len;
3959
3398
 
3960
 
      ut_a(get_field_offset(getTable(), field)
 
3399
      ut_a(get_field_offset(table, field)
3961
3400
        == key_part->offset);
3962
3401
 
3963
3402
      /* For multi byte character sets we need to calculate
3965
3404
 
3966
3405
      if (blob_len > 0 && cs->mbmaxlen > 1) {
3967
3406
        true_len = (ulint) cs->cset->well_formed_len(cs,
3968
 
                                                     (const char *) blob_data,
3969
 
                                                     (const char *) blob_data
3970
 
                                                     + blob_len,
3971
 
                                                     (uint) (key_len /
3972
 
                                                             cs->mbmaxlen),
3973
 
                                                     &error);
 
3407
            (const char *) blob_data,
 
3408
            (const char *) blob_data
 
3409
              + blob_len,
 
3410
                                                (uint) (key_len /
 
3411
                                                        cs->mbmaxlen),
 
3412
            &error);
3974
3413
      }
3975
3414
 
3976
3415
      /* All indexes on BLOB and TEXT are column prefix
4004
3443
      ulint     key_len;
4005
3444
      const unsigned char*    src_start;
4006
3445
      enum_field_types  real_type;
4007
 
      const CHARSET_INFO* cs= field->charset();
4008
3446
 
4009
3447
      key_len = key_part->length;
4010
3448
 
4026
3464
      memcpy(buff, src_start, true_len);
4027
3465
      buff += true_len;
4028
3466
 
4029
 
      /* Pad the unused space with spaces. */
 
3467
      /* Pad the unused space with spaces. Note that no
 
3468
      padding is ever needed for UCS-2 because in MySQL,
 
3469
      all UCS2 characters are 2 bytes, as MySQL does not
 
3470
      support surrogate pairs, which are needed to represent
 
3471
      characters in the range U+10000 to U+10FFFF. */
4030
3472
 
4031
3473
      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 */);
 
3474
        ulint pad_len = key_len - true_len;
 
3475
        memset(buff, ' ', pad_len);
4037
3476
        buff += pad_len;
4038
3477
      }
4039
3478
    }
4127
3566
    the clustered index */
4128
3567
  }
4129
3568
 
4130
 
  n_fields = (ulint)table->getShare()->sizeFields(); /* number of columns */
 
3569
  n_fields = (ulint)table->s->fields; /* number of columns */
4131
3570
 
4132
3571
  if (!prebuilt->mysql_template) {
4133
3572
    prebuilt->mysql_template = (mysql_row_templ_t*)
4135
3574
  }
4136
3575
 
4137
3576
  prebuilt->template_type = templ_type;
4138
 
  prebuilt->null_bitmap_len = table->getShare()->null_bytes;
 
3577
  prebuilt->null_bitmap_len = table->s->null_bytes;
4139
3578
 
4140
3579
  prebuilt->templ_contains_blob = FALSE;
4141
3580
 
4142
3581
  /* Note that in InnoDB, i is the column number. MySQL calls columns
4143
3582
  'fields'. */
4144
 
  for (i = 0; i < n_fields; i++)
4145
 
  {
4146
 
    const dict_col_t *col= &index->table->cols[i];
 
3583
  for (i = 0; i < n_fields; i++) {
4147
3584
    templ = prebuilt->mysql_template + n_requested_fields;
4148
 
    field = table->getField(i);
 
3585
    field = table->field[i];
4149
3586
 
4150
3587
    if (UNIV_LIKELY(templ_type == ROW_MYSQL_REC_FIELDS)) {
4151
3588
      /* Decide which columns we should fetch
4189
3626
    n_requested_fields++;
4190
3627
 
4191
3628
    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
3629
 
4195
3630
    if (index == clust_index) {
4196
 
      templ->rec_field_no = templ->clust_rec_field_no;
 
3631
      templ->rec_field_no = dict_col_get_clust_pos(
 
3632
        &index->table->cols[i], index);
4197
3633
    } else {
4198
3634
      templ->rec_field_no = dict_index_get_nth_col_pos(
4199
3635
                index, i);
4200
 
      if (templ->rec_field_no == ULINT_UNDEFINED) {
4201
 
        prebuilt->need_to_access_clustered = TRUE;
4202
 
      }
 
3636
    }
 
3637
 
 
3638
    if (templ->rec_field_no == ULINT_UNDEFINED) {
 
3639
      prebuilt->need_to_access_clustered = TRUE;
4203
3640
    }
4204
3641
 
4205
3642
    if (field->null_ptr) {
4206
3643
      templ->mysql_null_byte_offset =
4207
3644
        (ulint) ((char*) field->null_ptr
4208
 
          - (char*) table->getInsertRecord());
 
3645
          - (char*) table->record[0]);
4209
3646
 
4210
3647
      templ->mysql_null_bit_mask = (ulint) field->null_bit;
4211
3648
    } else {
4221
3658
      mysql_prefix_len = templ->mysql_col_offset
4222
3659
        + templ->mysql_col_len;
4223
3660
    }
4224
 
    templ->type = col->mtype;
 
3661
    templ->type = index->table->cols[i].mtype;
4225
3662
    templ->mysql_type = (ulint)field->type();
4226
3663
 
4227
3664
    if (templ->mysql_type == DATA_MYSQL_TRUE_VARCHAR) {
4228
3665
      templ->mysql_length_bytes = (ulint)
4229
 
        (((Field_varstring*)field)->pack_length_no_ptr());
 
3666
        (((Field_varstring*)field)->length_bytes);
4230
3667
    }
4231
3668
 
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;
 
3669
    templ->charset = dtype_get_charset_coll(
 
3670
      index->table->cols[i].prtype);
 
3671
    templ->mbminlen = index->table->cols[i].mbminlen;
 
3672
    templ->mbmaxlen = index->table->cols[i].mbmaxlen;
 
3673
    templ->is_unsigned = index->table->cols[i].prtype
 
3674
              & DATA_UNSIGNED;
4236
3675
    if (templ->type == DATA_BLOB) {
4237
3676
      prebuilt->templ_contains_blob = TRUE;
4238
3677
    }
4249
3688
    for (i = 0; i < n_requested_fields; i++) {
4250
3689
      templ = prebuilt->mysql_template + i;
4251
3690
 
4252
 
      templ->rec_field_no = templ->clust_rec_field_no;
 
3691
      templ->rec_field_no = dict_col_get_clust_pos(
 
3692
        &index->table->cols[templ->col_no],
 
3693
        clust_index);
4253
3694
    }
4254
3695
  }
4255
3696
}
4256
3697
 
4257
3698
/********************************************************************//**
 
3699
Get the upper limit of the MySQL integral and floating-point type. */
 
3700
UNIV_INTERN
 
3701
uint64_t
 
3702
ha_innobase::innobase_get_int_col_max_value(
 
3703
/*========================================*/
 
3704
  const Field*  field)
 
3705
{
 
3706
  uint64_t  max_value = 0;
 
3707
 
 
3708
  switch(field->key_type()) {
 
3709
  /* TINY */
 
3710
  case HA_KEYTYPE_BINARY:
 
3711
    max_value = 0xFFULL;
 
3712
    break;
 
3713
  /* MEDIUM */
 
3714
  case HA_KEYTYPE_UINT24:
 
3715
    max_value = 0xFFFFFFULL;
 
3716
    break;
 
3717
  /* LONG */
 
3718
  case HA_KEYTYPE_ULONG_INT:
 
3719
    max_value = 0xFFFFFFFFULL;
 
3720
    break;
 
3721
  case HA_KEYTYPE_LONG_INT:
 
3722
    max_value = 0x7FFFFFFFULL;
 
3723
    break;
 
3724
  /* BIG */
 
3725
  case HA_KEYTYPE_ULONGLONG:
 
3726
    max_value = 0xFFFFFFFFFFFFFFFFULL;
 
3727
    break;
 
3728
  case HA_KEYTYPE_LONGLONG:
 
3729
    max_value = 0x7FFFFFFFFFFFFFFFULL;
 
3730
    break;
 
3731
  case HA_KEYTYPE_DOUBLE:
 
3732
    /* We use the maximum as per IEEE754-2008 standard, 2^53 */
 
3733
    max_value = 0x20000000000000ULL;
 
3734
    break;
 
3735
  default:
 
3736
    ut_error;
 
3737
  }
 
3738
 
 
3739
  return(max_value);
 
3740
}
 
3741
 
 
3742
/********************************************************************//**
4258
3743
This special handling is really to overcome the limitations of MySQL's
4259
3744
binlogging. We need to eliminate the non-determinism that will arise in
4260
3745
INSERT ... SELECT type of statements, since MySQL binlog only stores the
4268
3753
{
4269
3754
  ulint   error = DB_SUCCESS;
4270
3755
 
4271
 
  dict_table_autoinc_lock(prebuilt->table);
 
3756
  switch (innobase_autoinc_lock_mode) {
 
3757
  case AUTOINC_NO_LOCKING:
 
3758
    /* Acquire only the AUTOINC mutex. */
 
3759
    dict_table_autoinc_lock(prebuilt->table);
 
3760
    break;
 
3761
 
 
3762
  case AUTOINC_NEW_STYLE_LOCKING:
 
3763
    /* For simple (single/multi) row INSERTs, we fallback to the
 
3764
    old style only if another transaction has already acquired
 
3765
    the AUTOINC lock on behalf of a LOAD FILE or INSERT ... SELECT
 
3766
    etc. type of statement. */
 
3767
    if (session_sql_command(user_session) == SQLCOM_INSERT
 
3768
        || session_sql_command(user_session) == SQLCOM_REPLACE) {
 
3769
      dict_table_t* d_table = prebuilt->table;
 
3770
 
 
3771
      /* Acquire the AUTOINC mutex. */
 
3772
      dict_table_autoinc_lock(d_table);
 
3773
 
 
3774
      /* We need to check that another transaction isn't
 
3775
      already holding the AUTOINC lock on the table. */
 
3776
      if (d_table->n_waiting_or_granted_auto_inc_locks) {
 
3777
        /* Release the mutex to avoid deadlocks. */
 
3778
        dict_table_autoinc_unlock(d_table);
 
3779
      } else {
 
3780
        break;
 
3781
      }
 
3782
    }
 
3783
    /* Fall through to old style locking. */
 
3784
 
 
3785
  case AUTOINC_OLD_STYLE_LOCKING:
 
3786
    error = row_lock_table_autoinc_for_mysql(prebuilt);
 
3787
 
 
3788
    if (error == DB_SUCCESS) {
 
3789
 
 
3790
      /* Acquire the AUTOINC mutex. */
 
3791
      dict_table_autoinc_lock(prebuilt->table);
 
3792
    }
 
3793
    break;
 
3794
 
 
3795
  default:
 
3796
    ut_error;
 
3797
  }
4272
3798
 
4273
3799
  return(ulong(error));
4274
3800
}
4282
3808
/*================================*/
4283
3809
  uint64_t  autoinc)  /*!< in: value to store */
4284
3810
{
4285
 
  dict_table_autoinc_lock(prebuilt->table);
4286
 
  dict_table_autoinc_initialize(prebuilt->table, autoinc);
4287
 
  dict_table_autoinc_unlock(prebuilt->table);
4288
 
 
4289
 
  return(ulong(DB_SUCCESS));
 
3811
  ulint   error;
 
3812
 
 
3813
  error = innobase_lock_autoinc();
 
3814
 
 
3815
  if (error == DB_SUCCESS) {
 
3816
 
 
3817
    dict_table_autoinc_initialize(prebuilt->table, autoinc);
 
3818
 
 
3819
    dict_table_autoinc_unlock(prebuilt->table);
 
3820
  }
 
3821
 
 
3822
  return(ulong(error));
4290
3823
}
4291
3824
 
4292
3825
/********************************************************************//**
4299
3832
/*==================================*/
4300
3833
  uint64_t  auto_inc) /*!< in: value to store */
4301
3834
{
4302
 
  dict_table_autoinc_lock(prebuilt->table);
4303
 
  dict_table_autoinc_update_if_greater(prebuilt->table, auto_inc);
4304
 
  dict_table_autoinc_unlock(prebuilt->table);
4305
 
 
4306
 
  return(ulong(DB_SUCCESS));
 
3835
  ulint   error;
 
3836
 
 
3837
  error = innobase_lock_autoinc();
 
3838
 
 
3839
  if (error == DB_SUCCESS) {
 
3840
 
 
3841
    dict_table_autoinc_update_if_greater(prebuilt->table, auto_inc);
 
3842
 
 
3843
    dict_table_autoinc_unlock(prebuilt->table);
 
3844
  }
 
3845
 
 
3846
  return(ulong(error));
4307
3847
}
4308
3848
 
4309
3849
/********************************************************************//**
4323
3863
  trx_t*    trx = session_to_trx(user_session);
4324
3864
 
4325
3865
  if (prebuilt->trx != trx) {
4326
 
    errmsg_printf(error::ERROR, "The transaction object for the table handle is at "
 
3866
    errmsg_printf(ERRMSG_LVL_ERROR, "The transaction object for the table handle is at "
4327
3867
        "%p, but for the current thread it is at %p",
4328
3868
        (const void*) prebuilt->trx, (const void*) trx);
4329
3869
 
4337
3877
    ut_error;
4338
3878
  }
4339
3879
 
4340
 
  sql_command = user_session->getSqlCommand();
 
3880
  ha_statistic_increment(&system_status_var::ha_write_count);
 
3881
 
 
3882
  sql_command = session_sql_command(user_session);
4341
3883
 
4342
3884
  if ((sql_command == SQLCOM_ALTER_TABLE
4343
3885
       || sql_command == SQLCOM_CREATE_INDEX
4405
3947
  num_write_row++;
4406
3948
 
4407
3949
  /* This is the case where the table has an auto-increment column */
4408
 
  if (getTable()->next_number_field && record == getTable()->getInsertRecord()) {
 
3950
  if (table->next_number_field && record == table->record[0]) {
4409
3951
 
4410
3952
    /* Reset the error code before calling
4411
3953
    innobase_get_auto_increment(). */
4412
3954
    prebuilt->autoinc_error = DB_SUCCESS;
4413
3955
 
4414
3956
    if ((error = update_auto_increment())) {
 
3957
 
4415
3958
      /* 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) {
 
3959
      if (prebuilt->autoinc_error != DB_SUCCESS) {
4425
3960
        error = (int) prebuilt->autoinc_error;
4426
3961
 
4427
3962
        goto report_error;
4441
3976
    /* Build the template used in converting quickly between
4442
3977
    the two database formats */
4443
3978
 
4444
 
    build_template(prebuilt, NULL, getTable(), ROW_MYSQL_WHOLE_ROW);
 
3979
    build_template(prebuilt, NULL, table,
 
3980
             ROW_MYSQL_WHOLE_ROW);
4445
3981
  }
4446
3982
 
4447
3983
  innodb_srv_conc_enter_innodb(prebuilt->trx);
4448
3984
 
4449
3985
  error = row_insert_for_mysql((byte*) record, prebuilt);
4450
3986
 
4451
 
  user_session->setXaId(trx->id);
4452
 
 
4453
3987
  /* Handle duplicate key errors */
4454
3988
  if (auto_inc_used) {
4455
3989
    ulint   err;
4467
4001
    /* We need the upper limit of the col type to check for
4468
4002
    whether we update the table autoinc counter or not. */
4469
4003
    col_max_value = innobase_get_int_col_max_value(
4470
 
      getTable()->next_number_field); 
 
4004
      table->next_number_field);
 
4005
 
4471
4006
    /* Get the value that MySQL attempted to store in the table.*/
4472
 
    auto_inc = getTable()->next_number_field->val_int();
 
4007
    auto_inc = table->next_number_field->val_int();
4473
4008
 
4474
4009
    switch (error) {
4475
4010
    case DB_DUPLICATE_KEY:
4505
4040
      update the table upper limit. Note: last_value
4506
4041
      will be 0 if get_auto_increment() was not called.*/
4507
4042
 
4508
 
      if (auto_inc >= prebuilt->autoinc_last_value) {
 
4043
      if (auto_inc <= col_max_value
 
4044
          && auto_inc >= prebuilt->autoinc_last_value) {
4509
4045
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
 
          }
 
4046
        ut_a(prebuilt->autoinc_increment > 0);
 
4047
 
 
4048
        uint64_t  need;
 
4049
        uint64_t  offset;
 
4050
 
 
4051
        offset = prebuilt->autoinc_offset;
 
4052
        need = prebuilt->autoinc_increment;
 
4053
 
 
4054
        auto_inc = innobase_next_autoinc(
 
4055
          auto_inc, need, offset, col_max_value);
 
4056
 
 
4057
        err = innobase_set_max_autoinc(auto_inc);
 
4058
 
 
4059
        if (err != DB_SUCCESS) {
 
4060
          error = err;
4531
4061
        }
4532
4062
      }
4533
4063
      break;
4566
4096
  Session*  )   /*!< in: user thread */
4567
4097
{
4568
4098
  unsigned char*    original_upd_buff = upd_buff;
 
4099
  Field*    field;
4569
4100
  enum_field_types field_mysql_type;
4570
4101
  uint    n_fields;
4571
4102
  ulint   o_len;
4582
4113
  dict_index_t* clust_index;
4583
4114
  uint    i= 0;
4584
4115
 
4585
 
  n_fields = table->getShare()->sizeFields();
 
4116
  n_fields = table->s->fields;
4586
4117
  clust_index = dict_table_get_first_index(prebuilt->table);
4587
4118
 
4588
4119
  /* We use upd_buff to convert changed fields */
4589
4120
  buf = (byte*) upd_buff;
4590
4121
 
4591
4122
  for (i = 0; i < n_fields; i++) {
4592
 
    Field *field= table->getField(i);
 
4123
    field = table->field[i];
4593
4124
 
4594
4125
    o_ptr = (const byte*) old_row + get_field_offset(table, field);
4595
4126
    n_ptr = (const byte*) new_row + get_field_offset(table, field);
4628
4159
        o_ptr = row_mysql_read_true_varchar(
4629
4160
          &o_len, o_ptr,
4630
4161
          (ulint)
4631
 
          (((Field_varstring*)field)->pack_length_no_ptr()));
 
4162
          (((Field_varstring*)field)->length_bytes));
4632
4163
 
4633
4164
        n_ptr = row_mysql_read_true_varchar(
4634
4165
          &n_len, n_ptr,
4635
4166
          (ulint)
4636
 
          (((Field_varstring*)field)->pack_length_no_ptr()));
 
4167
          (((Field_varstring*)field)->length_bytes));
4637
4168
      }
4638
4169
 
4639
4170
      break;
4715
4246
 
4716
4247
  ut_a(prebuilt->trx == trx);
4717
4248
 
 
4249
  ha_statistic_increment(&system_status_var::ha_update_count);
 
4250
 
 
4251
  if (table->timestamp_field_type & TIMESTAMP_AUTO_SET_ON_UPDATE)
 
4252
    table->timestamp_field->set_time();
 
4253
 
4718
4254
  if (prebuilt->upd_node) {
4719
4255
    uvect = prebuilt->upd_node->update;
4720
4256
  } else {
4724
4260
  /* Build an update vector from the modified fields in the rows
4725
4261
  (uses upd_buff of the handle) */
4726
4262
 
4727
 
  calc_row_difference(uvect, (unsigned char*) old_row, new_row, getTable(),
4728
 
      &upd_buff[0], (ulint)upd_and_key_val_buff_len,
 
4263
  calc_row_difference(uvect, (unsigned char*) old_row, new_row, table,
 
4264
      upd_buff, (ulint)upd_and_key_val_buff_len,
4729
4265
      prebuilt, user_session);
4730
4266
 
4731
4267
  /* This is not a delete */
4733
4269
 
4734
4270
  ut_a(prebuilt->template_type == ROW_MYSQL_WHOLE_ROW);
4735
4271
 
4736
 
  if (getTable()->found_next_number_field)
4737
 
  {
4738
 
    uint64_t  auto_inc;
4739
 
    uint64_t  col_max_value;
4740
 
 
4741
 
    auto_inc = getTable()->found_next_number_field->val_int();
4742
 
 
4743
 
    /* We need the upper limit of the col type to check for
4744
 
    whether we update the table autoinc counter or not. */
4745
 
    col_max_value = innobase_get_int_col_max_value(
4746
 
      getTable()->found_next_number_field);
4747
 
 
4748
 
    uint64_t current_autoinc;
4749
 
    ulint autoinc_error= innobase_get_autoinc(&current_autoinc);
4750
 
    if (autoinc_error == DB_SUCCESS
4751
 
        && auto_inc <= col_max_value && auto_inc != 0
4752
 
        && auto_inc >= current_autoinc)
4753
 
    {
4754
 
 
4755
 
      uint64_t  need;
4756
 
      uint64_t  offset;
4757
 
 
4758
 
      offset = prebuilt->autoinc_offset;
4759
 
      need = prebuilt->autoinc_increment;
4760
 
 
4761
 
      auto_inc = innobase_next_autoinc(
4762
 
        auto_inc, need, offset, col_max_value);
4763
 
 
4764
 
      dict_table_autoinc_update_if_greater(prebuilt->table, auto_inc);
4765
 
    }
4766
 
 
4767
 
    dict_table_autoinc_unlock(prebuilt->table);
4768
 
  }
4769
 
 
4770
4272
  innodb_srv_conc_enter_innodb(trx);
4771
4273
 
4772
4274
  error = row_update_for_mysql((byte*) old_row, prebuilt);
4773
4275
 
4774
 
  user_session->setXaId(trx->id);
4775
 
 
4776
4276
  /* We need to do some special AUTOINC handling for the following case:
4777
4277
 
4778
4278
  INSERT INTO t (c1,c2) VALUES(x,y) ON DUPLICATE KEY UPDATE ...
4782
4282
  value used in the INSERT statement.*/
4783
4283
 
4784
4284
  if (error == DB_SUCCESS
4785
 
      && getTable()->next_number_field
4786
 
      && new_row == getTable()->getInsertRecord()
4787
 
      && user_session->getSqlCommand() == SQLCOM_INSERT
 
4285
      && table->next_number_field
 
4286
      && new_row == table->record[0]
 
4287
      && session_sql_command(user_session) == SQLCOM_INSERT
4788
4288
      && (trx->duplicates & (TRX_DUP_IGNORE | TRX_DUP_REPLACE))
4789
4289
    == TRX_DUP_IGNORE)  {
4790
4290
 
4791
4291
    uint64_t  auto_inc;
4792
4292
    uint64_t  col_max_value;
4793
4293
 
4794
 
    auto_inc = getTable()->next_number_field->val_int();
 
4294
    auto_inc = table->next_number_field->val_int();
4795
4295
 
4796
4296
    /* We need the upper limit of the col type to check for
4797
4297
    whether we update the table autoinc counter or not. */
4798
4298
    col_max_value = innobase_get_int_col_max_value(
4799
 
      getTable()->next_number_field);
 
4299
      table->next_number_field);
4800
4300
 
4801
4301
    if (auto_inc <= col_max_value && auto_inc != 0) {
4802
4302
 
4851
4351
 
4852
4352
  ut_a(prebuilt->trx == trx);
4853
4353
 
 
4354
  ha_statistic_increment(&system_status_var::ha_delete_count);
 
4355
 
4854
4356
  if (!prebuilt->upd_node) {
4855
4357
    row_get_prebuilt_update_vector(prebuilt);
4856
4358
  }
4863
4365
 
4864
4366
  error = row_update_for_mysql((byte*) record, prebuilt);
4865
4367
 
4866
 
  user_session->setXaId(trx->id);
4867
 
 
4868
4368
  innodb_srv_conc_exit_innodb(trx);
4869
4369
 
4870
4370
  error = convert_error_code_to_mysql(
4898
4398
  case ROW_READ_WITH_LOCKS:
4899
4399
    if (!srv_locks_unsafe_for_binlog
4900
4400
        && prebuilt->trx->isolation_level
4901
 
        > TRX_ISO_READ_COMMITTED) {
 
4401
        != TRX_ISO_READ_COMMITTED) {
4902
4402
      break;
4903
4403
    }
4904
4404
    /* fall through */
4928
4428
ha_innobase::try_semi_consistent_read(bool yes)
4929
4429
/*===========================================*/
4930
4430
{
4931
 
  ut_a(prebuilt->trx == session_to_trx(getTable()->in_use));
 
4431
  ut_a(prebuilt->trx == session_to_trx(ha_session()));
4932
4432
 
4933
4433
  /* Row read type is set to semi consistent read if this was
4934
4434
  requested by the MySQL and either innodb_locks_unsafe_for_binlog
4937
4437
 
4938
4438
  if (yes
4939
4439
      && (srv_locks_unsafe_for_binlog
4940
 
    || prebuilt->trx->isolation_level <= TRX_ISO_READ_COMMITTED)) {
 
4440
    || prebuilt->trx->isolation_level == TRX_ISO_READ_COMMITTED)) {
4941
4441
    prebuilt->row_read_type = ROW_READ_TRY_SEMI_CONSISTENT;
4942
4442
  } else {
4943
4443
    prebuilt->row_read_type = ROW_READ_WITH_LOCKS;
5118
4618
 
5119
4619
  index = prebuilt->index;
5120
4620
 
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
4621
  /* Note that if the index for which the search template is built is not
5131
4622
  necessarily prebuilt->index, but can also be the clustered index */
5132
4623
 
5133
4624
  if (prebuilt->sql_stat_start) {
5134
 
    build_template(prebuilt, user_session, getTable(),
 
4625
    build_template(prebuilt, user_session, table,
5135
4626
             ROW_MYSQL_REC_FIELDS);
5136
4627
  }
5137
4628
 
5141
4632
 
5142
4633
    row_sel_convert_mysql_key_to_innobase(
5143
4634
      prebuilt->search_tuple,
5144
 
      (byte*) &key_val_buff[0],
 
4635
      (byte*) key_val_buff,
5145
4636
      (ulint)upd_and_key_val_buff_len,
5146
4637
      index,
5147
4638
      (byte*) key_ptr,
5186
4677
  switch (ret) {
5187
4678
  case DB_SUCCESS:
5188
4679
    error = 0;
5189
 
    getTable()->status = 0;
 
4680
    table->status = 0;
5190
4681
    break;
5191
4682
  case DB_RECORD_NOT_FOUND:
5192
4683
    error = HA_ERR_KEY_NOT_FOUND;
5193
 
    getTable()->status = STATUS_NOT_FOUND;
 
4684
    table->status = STATUS_NOT_FOUND;
5194
4685
    break;
5195
4686
  case DB_END_OF_INDEX:
5196
4687
    error = HA_ERR_KEY_NOT_FOUND;
5197
 
    getTable()->status = STATUS_NOT_FOUND;
 
4688
    table->status = STATUS_NOT_FOUND;
5198
4689
    break;
5199
4690
  default:
5200
4691
    error = convert_error_code_to_mysql((int) ret,
5201
4692
                prebuilt->table->flags,
5202
4693
                user_session);
5203
 
    getTable()->status = STATUS_NOT_FOUND;
 
4694
    table->status = STATUS_NOT_FOUND;
5204
4695
    break;
5205
4696
  }
5206
4697
 
5235
4726
        clustered index, even if it was internally
5236
4727
        generated by InnoDB */
5237
4728
{
 
4729
  KeyInfo*    key = 0;
5238
4730
  dict_index_t* index = 0;
5239
4731
 
5240
4732
  ha_statistic_increment(&system_status_var::ha_read_key_count);
5241
4733
 
5242
 
  if (keynr != MAX_KEY && getTable()->getShare()->sizeKeys() > 0) 
5243
 
  {
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
 
    }
 
4734
  ut_ad(user_session == ha_session());
 
4735
  ut_a(prebuilt->trx == session_to_trx(user_session));
 
4736
 
 
4737
  if (keynr != MAX_KEY && table->s->keys > 0) {
 
4738
    key = table->key_info + keynr;
 
4739
 
 
4740
    index = dict_table_get_index_on_name(prebuilt->table,
 
4741
                 key->name);
5267
4742
  } else {
5268
4743
    index = dict_table_get_first_index(prebuilt->table);
5269
4744
  }
5270
4745
 
5271
4746
  if (!index) {
5272
 
    errmsg_printf(error::ERROR, 
 
4747
    errmsg_printf(ERRMSG_LVL_ERROR, 
5273
4748
      "Innodb could not find key n:o %u with name %s "
5274
4749
      "from dict cache for table %s",
5275
 
      keynr, getTable()->getShare()->getTableMessage()->indexes(keynr).name().c_str(),
 
4750
      keynr, key ? key->name : "NULL",
5276
4751
      prebuilt->table->name);
5277
4752
  }
5278
4753
 
5290
4765
      index, even if it was internally generated by
5291
4766
      InnoDB */
5292
4767
{
5293
 
  ut_ad(user_session == table->in_use);
 
4768
  ut_ad(user_session == ha_session());
5294
4769
  ut_a(prebuilt->trx == session_to_trx(user_session));
5295
4770
 
5296
4771
  active_index = keynr;
5298
4773
  prebuilt->index = innobase_get_index(keynr);
5299
4774
 
5300
4775
  if (UNIV_UNLIKELY(!prebuilt->index)) {
5301
 
    errmsg_printf(error::WARN, "InnoDB: change_active_index(%u) failed",
 
4776
    errmsg_printf(ERRMSG_LVL_WARN, "InnoDB: change_active_index(%u) failed",
5302
4777
          keynr);
5303
 
    prebuilt->index_usable = FALSE;
5304
4778
    return(1);
5305
4779
  }
5306
4780
 
5308
4782
                 prebuilt->index);
5309
4783
 
5310
4784
  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);
 
4785
    errmsg_printf(ERRMSG_LVL_WARN,
 
4786
         "InnoDB: insufficient history for index %u",
 
4787
          keynr);
5315
4788
    /* The caller seems to ignore this.  Thus, we must check
5316
4789
    this again in row_search_for_mysql(). */
5317
4790
    return(2);
5330
4803
  the flag ROW_MYSQL_WHOLE_ROW below, but that caused unnecessary
5331
4804
  copying. Starting from MySQL-4.1 we use a more efficient flag here. */
5332
4805
 
5333
 
  build_template(prebuilt, user_session, getTable(), ROW_MYSQL_REC_FIELDS);
 
4806
  build_template(prebuilt, user_session, table, ROW_MYSQL_REC_FIELDS);
5334
4807
 
5335
4808
  return(0);
5336
4809
}
5390
4863
  switch (ret) {
5391
4864
  case DB_SUCCESS:
5392
4865
    error = 0;
5393
 
    getTable()->status = 0;
 
4866
    table->status = 0;
5394
4867
    break;
5395
4868
  case DB_RECORD_NOT_FOUND:
5396
4869
    error = HA_ERR_END_OF_FILE;
5397
 
    getTable()->status = STATUS_NOT_FOUND;
 
4870
    table->status = STATUS_NOT_FOUND;
5398
4871
    break;
5399
4872
  case DB_END_OF_INDEX:
5400
4873
    error = HA_ERR_END_OF_FILE;
5401
 
    getTable()->status = STATUS_NOT_FOUND;
 
4874
    table->status = STATUS_NOT_FOUND;
5402
4875
    break;
5403
4876
  default:
5404
4877
    error = convert_error_code_to_mysql(
5405
4878
      (int) ret, prebuilt->table->flags, user_session);
5406
 
    getTable()->status = STATUS_NOT_FOUND;
 
4879
    table->status = STATUS_NOT_FOUND;
5407
4880
    break;
5408
4881
  }
5409
4882
 
5598
5071
 
5599
5072
  ha_statistic_increment(&system_status_var::ha_read_rnd_count);
5600
5073
 
5601
 
  ut_a(prebuilt->trx == session_to_trx(getTable()->in_use));
 
5074
  ut_a(prebuilt->trx == session_to_trx(ha_session()));
5602
5075
 
5603
5076
  if (prebuilt->clust_index_was_generated) {
5604
5077
    /* No primary key was defined for the table and we
5644
5117
{
5645
5118
  uint    len;
5646
5119
 
5647
 
  ut_a(prebuilt->trx == session_to_trx(getTable()->in_use));
 
5120
  ut_a(prebuilt->trx == session_to_trx(ha_session()));
5648
5121
 
5649
5122
  if (prebuilt->clust_index_was_generated) {
5650
5123
    /* No primary key was defined for the table and we
5664
5137
  table. */
5665
5138
 
5666
5139
  if (len != ref_length) {
5667
 
    errmsg_printf(error::ERROR, "Stored ref len is %lu, but table ref len is %lu",
 
5140
    errmsg_printf(ERRMSG_LVL_ERROR, "Stored ref len is %lu, but table ref len is %lu",
5668
5141
        (ulong) len, (ulong) ref_length);
5669
5142
  }
5670
5143
}
5703
5176
  ulint   charset_no;
5704
5177
  ulint   i;
5705
5178
 
5706
 
  n_cols = form->getShare()->sizeFields();
 
5179
  n_cols = form->s->fields;
5707
5180
 
5708
5181
  /* We pass 0 as the space id, and determine at a lower level the space
5709
5182
  id where to store the table */
5716
5189
  }
5717
5190
 
5718
5191
  for (i = 0; i < n_cols; i++) {
5719
 
    field = form->getField(i);
 
5192
    field = form->field[i];
5720
5193
 
5721
5194
    col_type = get_innobase_type_from_mysql_type(&unsigned_type,
5722
5195
                  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
5196
    if (field->null_ptr) {
5739
5197
      nulls_allowed = 0;
5740
5198
    } else {
5757
5215
        /* in data0type.h we assume that the
5758
5216
        number fits in one byte in prtype */
5759
5217
        push_warning_printf(
5760
 
          trx->mysql_thd,
 
5218
          (Session*) trx->mysql_thd,
5761
5219
          DRIZZLE_ERROR::WARN_LEVEL_ERROR,
5762
5220
          ER_CANT_CREATE_TABLE,
5763
5221
          "In InnoDB, charset-collation codes"
5780
5238
    long_true_varchar = 0;
5781
5239
 
5782
5240
    if (field->type() == DRIZZLE_TYPE_VARCHAR) {
5783
 
      col_len -= ((Field_varstring*)field)->pack_length_no_ptr();
 
5241
      col_len -= ((Field_varstring*)field)->length_bytes;
5784
5242
 
5785
 
      if (((Field_varstring*)field)->pack_length_no_ptr() == 2) {
 
5243
      if (((Field_varstring*)field)->length_bytes == 2) {
5786
5244
        long_true_varchar = DATA_LONG_TRUE_VARCHAR;
5787
5245
      }
5788
5246
    }
5789
5247
 
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
5248
    dict_mem_table_add_col(table, table->heap,
5804
5249
      (char*) field->field_name,
5805
5250
      col_type,
5813
5258
 
5814
5259
  error = row_create_table_for_mysql(table, trx);
5815
5260
 
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
5261
  error = convert_error_code_to_mysql(error, flags, NULL);
5828
5262
 
5829
5263
  return(error);
5856
5290
  ulint   j;
5857
5291
  ulint*    field_lengths;
5858
5292
 
5859
 
  key = &form->key_info[key_num];
 
5293
  key = form->key_info + key_num;
5860
5294
 
5861
5295
  n_fields = key->key_parts;
5862
5296
 
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
5297
  ind_type = 0;
5867
5298
 
5868
 
  if (key_num == form->getShare()->getPrimaryKey()) {
 
5299
  if (key_num == form->s->primary_key) {
5869
5300
    ind_type = ind_type | DICT_CLUSTERED;
5870
5301
  }
5871
5302
 
5891
5322
    the length of the key part versus the column. */
5892
5323
 
5893
5324
    field = NULL;
5894
 
    for (j = 0; j < form->getShare()->sizeFields(); j++)
5895
 
    {
 
5325
    for (j = 0; j < form->s->fields; j++) {
5896
5326
 
5897
 
      field = form->getField(j);
 
5327
      field = form->field[j];
5898
5328
 
5899
5329
      if (0 == innobase_strcasecmp(
5900
5330
          field->field_name,
5905
5335
      }
5906
5336
    }
5907
5337
 
5908
 
    ut_a(j < form->getShare()->sizeFields());
 
5338
    ut_a(j < form->s->fields);
5909
5339
 
5910
5340
    col_type = get_innobase_type_from_mysql_type(
5911
5341
          &is_unsigned, key_part->field);
5915
5345
        && field->type() != DRIZZLE_TYPE_VARCHAR)
5916
5346
      || (field->type() == DRIZZLE_TYPE_VARCHAR
5917
5347
        && key_part->length < field->pack_length()
5918
 
        - ((Field_varstring*)field)->pack_length_no_ptr())) {
 
5348
        - ((Field_varstring*)field)->length_bytes)) {
5919
5349
 
5920
5350
      prefix_len = key_part->length;
5921
5351
 
5923
5353
        || col_type == DATA_FLOAT
5924
5354
        || col_type == DATA_DOUBLE
5925
5355
        || col_type == DATA_DECIMAL) {
5926
 
        errmsg_printf(error::ERROR, 
 
5356
        errmsg_printf(ERRMSG_LVL_ERROR, 
5927
5357
          "MySQL is trying to create a column "
5928
5358
          "prefix index field, on an "
5929
5359
          "inappropriate data type. Table "
5972
5402
  /* We pass 0 as the space id, and determine at a lower level the space
5973
5403
  id where to store the table */
5974
5404
 
5975
 
  index = dict_mem_index_create(table_name,
5976
 
                                innobase_index_reserve_name,
5977
 
                                0, DICT_CLUSTERED, 0);
 
5405
  index = dict_mem_index_create(table_name, "GEN_CLUST_INDEX",
 
5406
              0, DICT_CLUSTERED, 0);
5978
5407
 
5979
5408
  error = row_create_index_for_mysql(index, trx, NULL);
5980
5409
 
6023
5452
/*================*/
6024
5453
  Session         &session, /*!< in: Session */
6025
5454
  Table&    form,   /*!< in: information on table columns and indexes */
6026
 
        const identifier::Table &identifier,
 
5455
        drizzled::TableIdentifier &identifier,
6027
5456
        message::Table& create_proto)
6028
5457
{
6029
5458
  int   error;
6032
5461
  trx_t*    trx;
6033
5462
  int   primary_key_no;
6034
5463
  uint    i;
 
5464
  char    name2[FN_REFLEN];
 
5465
  char    norm_name[FN_REFLEN];
6035
5466
  ib_int64_t  auto_inc_value;
6036
5467
  ulint   iflags;
6037
5468
  /* Cache the value of innodb_file_format, in case it is
6038
 
    modified by another thread while the table is being created. */
 
5469
  modified by another thread while the table is being created. */
6039
5470
  const ulint file_format = srv_file_format;
6040
 
  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;
 
5471
        bool lex_identified_temp_table= (create_proto.type() == message::Table::TEMPORARY);
 
5472
 
 
5473
  const char *table_name= identifier.getPath().c_str();
 
5474
 
 
5475
#ifdef __WIN__
 
5476
  /* Names passed in from server are in two formats:
 
5477
  1. <database_name>/<table_name>: for normal table creation
 
5478
  2. full path: for temp table creation, or sym link
 
5479
 
 
5480
  When srv_file_per_table is on, check for full path pattern, i.e.
 
5481
  X:\dir\...,   X is a driver letter, or
 
5482
  \\dir1\dir2\...,  UNC path
 
5483
  returns error if it is in full path format, but not creating a temp.
 
5484
  table. Currently InnoDB does not support symbolic link on Windows. */
 
5485
 
 
5486
  if (srv_file_per_table
 
5487
      && (! lex_identified_temp_table)) {
 
5488
 
 
5489
    if ((table_name[1] == ':')
 
5490
        || (table_name[0] == '\\' && table_name[1] == '\\')) {
 
5491
      errmsg_printf(ERRMSG_LVL_ERROR, "Cannot create table %s\n", table_name);
 
5492
      return(HA_ERR_GENERIC);
 
5493
    }
6050
5494
  }
 
5495
#endif
6051
5496
 
6052
 
  if (form.getShare()->sizeFields() > 1000) {
 
5497
  if (form.s->fields > 1000) {
6053
5498
    /* The limit probably should be REC_MAX_N_FIELDS - 3 = 1020,
6054
 
      but we play safe here */
 
5499
    but we play safe here */
6055
5500
 
6056
5501
    return(HA_ERR_TO_BIG_ROW);
6057
5502
  }
6058
5503
 
6059
5504
  /* Get the transaction associated with the current session, or create one
6060
 
    if not yet created */
 
5505
  if not yet created */
6061
5506
 
6062
5507
  parent_trx = check_trx_exists(&session);
6063
5508
 
6064
5509
  /* In case MySQL calls this in the middle of a SELECT query, release
6065
 
    possible adaptive hash latch to avoid deadlocks of threads */
 
5510
  possible adaptive hash latch to avoid deadlocks of threads */
6066
5511
 
6067
5512
  trx_search_latch_release_if_reserved(parent_trx);
6068
5513
 
6070
5515
 
6071
5516
  srv_lower_case_table_names = TRUE;
6072
5517
 
 
5518
  strcpy(name2, table_name);
 
5519
 
 
5520
  normalize_table_name(norm_name, name2);
 
5521
 
6073
5522
  /* Latch the InnoDB data dictionary exclusively so that no deadlocks
6074
 
    or lock waits can happen in it during a table create operation.
6075
 
    Drop table etc. do this latching in row0mysql.c. */
 
5523
  or lock waits can happen in it during a table create operation.
 
5524
  Drop table etc. do this latching in row0mysql.c. */
6076
5525
 
6077
5526
  row_mysql_lock_data_dictionary(trx);
6078
5527
 
6134
5583
# error "DICT_TF_ZSSIZE_MAX < 1"
6135
5584
#endif
6136
5585
 
6137
 
    if (strict_mode)
 
5586
    if (SessionVAR(&session, strict_mode))
6138
5587
    {
6139
5588
      if (! srv_file_per_table)
6140
5589
      {
6153
5602
                            "InnoDB: ROW_FORMAT=compressed requires innodb_file_format > Antelope.");
6154
5603
      }
6155
5604
    }
 
5605
 
 
5606
    error= create_table_def(trx, &form, norm_name,
 
5607
                            lex_identified_temp_table ? name2 : NULL,
 
5608
                            iflags);
 
5609
  }
 
5610
 
 
5611
  if (error) {
 
5612
    goto cleanup;
6156
5613
  }
6157
5614
 
6158
5615
  /* Look for a primary key */
6159
5616
 
6160
 
  primary_key_no= (form.getShare()->hasPrimaryKey() ?
6161
 
                   (int) form.getShare()->getPrimaryKey() :
 
5617
  primary_key_no= (form.s->primary_key != MAX_KEY ?
 
5618
                   (int) form.s->primary_key :
6162
5619
                   -1);
6163
5620
 
6164
 
  /* Our function innobase_get_mysql_key_number_for_index assumes
 
5621
  /* Our function row_get_mysql_key_number_for_index assumes
6165
5622
    the primary key is always number 0, if it exists */
6166
5623
 
6167
5624
  assert(primary_key_no == -1 || primary_key_no == 0);
6168
5625
 
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
5626
  /* Create the keys */
6191
5627
 
6192
 
  if (form.getShare()->sizeKeys() == 0 || primary_key_no == -1) {
 
5628
  if (form.s->keys == 0 || primary_key_no == -1) {
6193
5629
    /* Create an index which is used as the clustered index;
6194
5630
      order the rows by their row id which is internally generated
6195
5631
      by InnoDB */
6196
5632
 
6197
 
    error = create_clustered_index_when_no_primary(trx, iflags, identifier.getKeyPath().c_str());
 
5633
    error = create_clustered_index_when_no_primary(
 
5634
                                                   trx, iflags, norm_name);
6198
5635
    if (error) {
6199
5636
      goto cleanup;
6200
5637
    }
6201
5638
  }
6202
5639
 
6203
5640
  if (primary_key_no != -1) {
6204
 
    /* In InnoDB the clustered index must always be created first */
6205
 
    if ((error = create_index(trx, &form, iflags, identifier.getKeyPath().c_str(),
 
5641
    /* In InnoDB the clustered index must always be created
 
5642
      first */
 
5643
    if ((error = create_index(trx, &form, iflags, norm_name,
6206
5644
                              (uint) primary_key_no))) {
6207
5645
      goto cleanup;
6208
5646
    }
6209
5647
  }
6210
5648
 
6211
 
  for (i = 0; i < form.getShare()->sizeKeys(); i++) {
 
5649
  for (i = 0; i < form.s->keys; i++) {
6212
5650
    if (i != (uint) primary_key_no) {
6213
5651
 
6214
 
      if ((error = create_index(trx, &form, iflags, identifier.getKeyPath().c_str(),
 
5652
      if ((error = create_index(trx, &form, iflags, norm_name,
6215
5653
                                i))) {
6216
5654
        goto cleanup;
6217
5655
      }
6218
5656
    }
6219
5657
  }
6220
5658
 
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
 
 
 
5659
  if (trx->mysql_query_str) {
6235
5660
    error = row_table_add_foreign_constraints(trx,
6236
 
                                              query, strlen(query),
6237
 
                                              identifier.getKeyPath().c_str(),
 
5661
                                              trx->mysql_query_str, norm_name,
6238
5662
                                              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
5663
 
6262
5664
    error = convert_error_code_to_mysql(error, iflags, NULL);
6263
5665
 
6276
5678
 
6277
5679
  log_buffer_flush_to_disk();
6278
5680
 
6279
 
  innobase_table = dict_table_get(identifier.getKeyPath().c_str(), FALSE);
 
5681
  innobase_table = dict_table_get(norm_name, FALSE);
6280
5682
 
6281
5683
  assert(innobase_table != 0);
6282
5684
 
6284
5686
    /* We update the highest file format in the system table
6285
5687
      space, if this table has higher file format setting. */
6286
5688
 
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;
 
5689
    trx_sys_file_format_max_upgrade(
 
5690
                                    (const char**) &innobase_file_format_check,
 
5691
                                    dict_table_get_format(innobase_table));
6292
5692
  }
6293
5693
 
6294
5694
  /* Note: We can't call update_session() as prebuilt will not be
6295
5695
    setup at this stage and so we use session. */
6296
5696
 
6297
5697
  /* 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. */
 
5698
    this is an ALTER TABLE. */
6300
5699
 
6301
5700
  if ((create_proto.options().has_auto_increment_value()
6302
 
       || session.getSqlCommand() == SQLCOM_ALTER_TABLE
6303
 
       || session.getSqlCommand() == SQLCOM_CREATE_INDEX)
 
5701
       || session_sql_command(&session) == SQLCOM_ALTER_TABLE)
6304
5702
      && create_proto.options().auto_increment_value() != 0) {
6305
5703
 
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. */
 
5704
    /* Query was ALTER TABLE...AUTO_INCREMENT = x; or
 
5705
      CREATE TABLE ...AUTO_INCREMENT = x; Find out a table
 
5706
      definition from the dictionary and get the current value
 
5707
      of the auto increment field. Set a new value to the
 
5708
      auto increment field if the value is greater than the
 
5709
      maximum value in the column. */
6314
5710
 
6315
5711
    auto_inc_value = create_proto.options().auto_increment_value();
6316
5712
 
6326
5722
 
6327
5723
  trx_free_for_mysql(trx);
6328
5724
 
6329
 
  if (lex_identified_temp_table)
6330
 
  {
6331
 
    session.getMessageCache().storeTableMessage(identifier, create_proto);
6332
 
  }
6333
 
  else
6334
 
  {
6335
 
    StorageEngine::writeDefinitionFromPath(identifier, create_proto);
6336
 
  }
 
5725
  StorageEngine::writeDefinitionFromPath(identifier, create_proto);
6337
5726
 
6338
5727
  return(0);
6339
5728
 
6362
5751
 
6363
5752
  ut_a(prebuilt->trx);
6364
5753
  ut_a(prebuilt->trx->magic_n == TRX_MAGIC_N);
6365
 
  ut_a(prebuilt->trx == session_to_trx(getTable()->in_use));
 
5754
  ut_a(prebuilt->trx == session_to_trx(ha_session()));
6366
5755
 
6367
5756
  dict_table = prebuilt->table;
6368
5757
  trx = prebuilt->trx;
6391
5780
  /* Get the transaction associated with the current session, or create one
6392
5781
  if not yet created, and update prebuilt->trx */
6393
5782
 
6394
 
  update_session(getTable()->in_use);
 
5783
  update_session(ha_session());
6395
5784
 
6396
 
  if (user_session->getSqlCommand() != SQLCOM_TRUNCATE) {
 
5785
  if (session_sql_command(user_session) != SQLCOM_TRUNCATE) {
6397
5786
  fallback:
6398
5787
    /* We only handle TRUNCATE TABLE t as a special case.
6399
5788
    DELETE FROM t will have to use ha_innobase::doDeleteRecord(),
6427
5816
InnobaseEngine::doDropTable(
6428
5817
/*======================*/
6429
5818
        Session &session,
6430
 
        const identifier::Table &identifier)
 
5819
        TableIdentifier &identifier)
6431
5820
{
6432
5821
  int error;
6433
5822
  trx_t*  parent_trx;
6434
5823
  trx_t*  trx;
 
5824
  char  norm_name[1000];
6435
5825
 
6436
5826
  ut_a(identifier.getPath().length() < 1000);
6437
5827
 
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
 
  }
 
5828
  /* Strangely, MySQL passes the table name without the '.frm'
 
5829
  extension, in contrast to ::create */
 
5830
  normalize_table_name(norm_name, identifier.getPath().c_str());
6445
5831
 
6446
5832
  /* Get the transaction associated with the current session, or create one
6447
 
    if not yet created */
 
5833
  if not yet created */
6448
5834
 
6449
5835
  parent_trx = check_trx_exists(&session);
6450
5836
 
6451
5837
  /* In case MySQL calls this in the middle of a SELECT query, release
6452
 
    possible adaptive hash latch to avoid deadlocks of threads */
 
5838
  possible adaptive hash latch to avoid deadlocks of threads */
6453
5839
 
6454
5840
  trx_search_latch_release_if_reserved(parent_trx);
6455
5841
 
6459
5845
 
6460
5846
  /* Drop the table in InnoDB */
6461
5847
 
6462
 
  error = row_drop_table_for_mysql(identifier.getKeyPath().c_str(), trx,
6463
 
                                   session.getSqlCommand()
6464
 
                                   == SQLCOM_DROP_DB);
6465
 
 
6466
 
  session.setXaId(trx->id);
 
5848
  error = row_drop_table_for_mysql(norm_name, trx,
 
5849
           session_sql_command(&session)
 
5850
           == SQLCOM_DROP_DB);
6467
5851
 
6468
5852
  /* Flush the log to reduce probability that the .frm files and
6469
 
    the InnoDB data dictionary get out-of-sync if the user runs
6470
 
    with innodb_flush_log_at_trx_commit = 0 */
 
5853
  the InnoDB data dictionary get out-of-sync if the user runs
 
5854
  with innodb_flush_log_at_trx_commit = 0 */
6471
5855
 
6472
5856
  log_buffer_flush_to_disk();
6473
5857
 
6474
5858
  /* Tell the InnoDB server that there might be work for
6475
 
    utility threads: */
 
5859
  utility threads: */
6476
5860
 
6477
5861
  srv_active_wake_master_thread();
6478
5862
 
6480
5864
 
6481
5865
  trx_free_for_mysql(trx);
6482
5866
 
6483
 
  if (error != ENOENT)
 
5867
  if(error!=ENOENT)
6484
5868
    error = convert_error_code_to_mysql(error, 0, NULL);
6485
5869
 
6486
 
  if (error == 0 || error == ENOENT)
6487
 
  {
6488
 
    if (identifier.getType() == message::Table::TEMPORARY)
6489
 
    {
6490
 
      session.getMessageCache().removeTableMessage(identifier);
6491
 
      ulint sql_command = session.getSqlCommand();
6492
 
 
6493
 
      // If this was the final removal to an alter table then we will need
6494
 
      // to remove the .dfe that was left behind.
6495
 
      if ((sql_command == SQLCOM_ALTER_TABLE
6496
 
       || sql_command == SQLCOM_CREATE_INDEX
6497
 
       || sql_command == SQLCOM_DROP_INDEX))
6498
 
      {
6499
 
        string path(identifier.getPath());
6500
 
 
6501
 
        path.append(DEFAULT_FILE_EXTENSION);
6502
 
 
6503
 
        (void)internal::my_delete(path.c_str(), MYF(0));
6504
 
      }
6505
 
    }
6506
 
    else
6507
 
    {
6508
 
      string path(identifier.getPath());
6509
 
 
6510
 
      path.append(DEFAULT_FILE_EXTENSION);
6511
 
 
6512
 
      (void)internal::my_delete(path.c_str(), MYF(0));
6513
 
    }
6514
 
  }
 
5870
        if (error == 0 || error == ENOENT)
 
5871
        {
 
5872
          string path(identifier.getPath());
 
5873
 
 
5874
          path.append(DEFAULT_FILE_EXTENSION);
 
5875
 
 
5876
          (void)internal::my_delete(path.c_str(), MYF(0));
 
5877
        }
6515
5878
 
6516
5879
  return(error);
6517
5880
}
6521
5884
bool
6522
5885
InnobaseEngine::doDropSchema(
6523
5886
/*===================*/
6524
 
                             const identifier::Schema &identifier)
 
5887
                             SchemaIdentifier &identifier)
6525
5888
    /*!< in: database path; inside InnoDB the name
6526
5889
      of the last directory in the path is used as
6527
5890
      the database name: for example, in 'mysql/data/test'
6533
5896
  Session*  session   = current_session;
6534
5897
 
6535
5898
  /* Get the transaction associated with the current session, or create one
6536
 
    if not yet created */
 
5899
  if not yet created */
6537
5900
 
6538
5901
  assert(this == innodb_engine_ptr);
6539
5902
 
6542
5905
    trx_t*  parent_trx = check_trx_exists(session);
6543
5906
 
6544
5907
    /* In case Drizzle calls this in the middle of a SELECT
6545
 
      query, release possible adaptive hash latch to avoid
6546
 
      deadlocks of threads */
 
5908
    query, release possible adaptive hash latch to avoid
 
5909
    deadlocks of threads */
6547
5910
 
6548
5911
    trx_search_latch_release_if_reserved(parent_trx);
6549
5912
  }
6550
5913
 
6551
 
  schema_path.append("/");
 
5914
        schema_path.append("/");
6552
5915
  trx = innobase_trx_allocate(session);
6553
5916
  error = row_drop_database_for_mysql(schema_path.c_str(), trx);
6554
5917
 
6555
5918
  /* Flush the log to reduce probability that the .frm files and
6556
 
    the InnoDB data dictionary get out-of-sync if the user runs
6557
 
    with innodb_flush_log_at_trx_commit = 0 */
6558
 
 
6559
 
  log_buffer_flush_to_disk();
6560
 
 
6561
 
  /* Tell the InnoDB server that there might be work for
6562
 
    utility threads: */
6563
 
 
6564
 
  srv_active_wake_master_thread();
6565
 
 
6566
 
  innobase_commit_low(trx);
6567
 
  trx_free_for_mysql(trx);
6568
 
 
6569
 
  return false; // We are just a listener since we lack control over DDL, so we give no positive acknowledgement. 
6570
 
}
6571
 
 
6572
 
void InnobaseEngine::dropTemporarySchema()
6573
 
{
6574
 
  identifier::Schema schema_identifier(GLOBAL_TEMPORARY_EXT);
6575
 
  trx_t*  trx= NULL;
6576
 
  string schema_path(GLOBAL_TEMPORARY_EXT);
6577
 
 
6578
 
  schema_path.append("/");
6579
 
 
6580
 
  trx = trx_allocate_for_mysql();
6581
 
 
6582
 
  trx->mysql_thd = NULL;
6583
 
 
6584
 
  trx->check_foreigns = false;
6585
 
  trx->check_unique_secondary = false;
6586
 
 
6587
 
  (void)row_drop_database_for_mysql(schema_path.c_str(), trx);
6588
 
 
6589
 
  /* Flush the log to reduce probability that the .frm files and
6590
 
    the InnoDB data dictionary get out-of-sync if the user runs
6591
 
    with innodb_flush_log_at_trx_commit = 0 */
6592
 
 
6593
 
  log_buffer_flush_to_disk();
6594
 
 
6595
 
  /* Tell the InnoDB server that there might be work for
6596
 
    utility threads: */
6597
 
 
6598
 
  srv_active_wake_master_thread();
6599
 
 
6600
 
  innobase_commit_low(trx);
6601
 
  trx_free_for_mysql(trx);
 
5919
  the InnoDB data dictionary get out-of-sync if the user runs
 
5920
  with innodb_flush_log_at_trx_commit = 0 */
 
5921
 
 
5922
  log_buffer_flush_to_disk();
 
5923
 
 
5924
  /* Tell the InnoDB server that there might be work for
 
5925
  utility threads: */
 
5926
 
 
5927
  srv_active_wake_master_thread();
 
5928
 
 
5929
  innobase_commit_low(trx);
 
5930
  trx_free_for_mysql(trx);
 
5931
 
 
5932
        return false; // We are just a listener since we lack control over DDL, so we give no positive acknowledgement. 
6602
5933
}
6603
5934
/*********************************************************************//**
6604
5935
Renames an InnoDB table.
6608
5939
innobase_rename_table(
6609
5940
/*==================*/
6610
5941
  trx_t*    trx,  /*!< in: transaction */
6611
 
  const identifier::Table &from,
6612
 
  const identifier::Table &to,
 
5942
  const char* from, /*!< in: old name of the table */
 
5943
  const char* to, /*!< in: new name of the table */
6613
5944
  ibool   lock_and_commit)
6614
5945
        /*!< in: TRUE=lock data dictionary and commit */
6615
5946
{
6616
5947
  int error;
 
5948
  char* norm_to;
 
5949
  char* norm_from;
6617
5950
 
6618
5951
  srv_lower_case_table_names = TRUE;
6619
5952
 
 
5953
  // Magic number 64 arbitrary
 
5954
  norm_to = (char*) malloc(strlen(to) + 64);
 
5955
  norm_from = (char*) malloc(strlen(from) + 64);
 
5956
 
 
5957
  normalize_table_name(norm_to, to);
 
5958
  normalize_table_name(norm_from, from);
 
5959
 
6620
5960
  /* Serialize data dictionary operations with dictionary mutex:
6621
5961
  no deadlocks can occur then in these operations */
6622
5962
 
6624
5964
    row_mysql_lock_data_dictionary(trx);
6625
5965
  }
6626
5966
 
6627
 
  error = row_rename_table_for_mysql(from.getKeyPath().c_str(), to.getKeyPath().c_str(), trx, lock_and_commit);
 
5967
  error = row_rename_table_for_mysql(
 
5968
    norm_from, norm_to, trx, lock_and_commit);
6628
5969
 
6629
5970
  if (error != DB_SUCCESS) {
6630
5971
    FILE* ef = dict_foreign_err_file;
6631
5972
 
6632
5973
    fputs("InnoDB: Renaming table ", ef);
6633
 
    ut_print_name(ef, trx, TRUE, from.getKeyPath().c_str());
 
5974
    ut_print_name(ef, trx, TRUE, norm_from);
6634
5975
    fputs(" to ", ef);
6635
 
    ut_print_name(ef, trx, TRUE, to.getKeyPath().c_str());
 
5976
    ut_print_name(ef, trx, TRUE, norm_to);
6636
5977
    fputs(" failed!\n", ef);
6637
5978
  }
6638
5979
 
6646
5987
    log_buffer_flush_to_disk();
6647
5988
  }
6648
5989
 
 
5990
  free(norm_to);
 
5991
  free(norm_from);
 
5992
 
6649
5993
  return error;
6650
5994
}
6651
5995
/*********************************************************************//**
6652
5996
Renames an InnoDB table.
6653
5997
@return 0 or error code */
6654
 
UNIV_INTERN int InnobaseEngine::doRenameTable(Session &session, const identifier::Table &from, const identifier::Table &to)
 
5998
UNIV_INTERN int InnobaseEngine::doRenameTable(Session &session, TableIdentifier &from, TableIdentifier &to)
6655
5999
{
6656
6000
  // A temp table alter table/rename is a shallow rename and only the
6657
6001
  // definition needs to be updated.
6658
6002
  if (to.getType() == message::Table::TEMPORARY && from.getType() == message::Table::TEMPORARY)
6659
6003
  {
6660
 
    session.getMessageCache().renameTableMessage(from, to);
6661
 
    return 0;
 
6004
    return plugin::StorageEngine::renameDefinitionFromPath(to, from);
6662
6005
  }
6663
6006
 
6664
6007
  trx_t*  trx;
6677
6020
 
6678
6021
  trx = innobase_trx_allocate(&session);
6679
6022
 
6680
 
  error = innobase_rename_table(trx, from, to, TRUE);
6681
 
 
6682
 
  session.setXaId(trx->id);
 
6023
  error = innobase_rename_table(trx, from.getPath().c_str(), to.getPath().c_str(), TRUE);
6683
6024
 
6684
6025
  /* Tell the InnoDB server that there might be work for
6685
6026
    utility threads: */
6689
6030
  innobase_commit_low(trx);
6690
6031
  trx_free_for_mysql(trx);
6691
6032
 
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
6033
  error = convert_error_code_to_mysql(error, 0, NULL);
6710
6034
 
6711
6035
  if (not error)
6733
6057
  KeyInfo*    key;
6734
6058
  dict_index_t* index;
6735
6059
  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;
 
6060
              table->s->stored_rec_length
 
6061
          + table->s->max_key_length + 100);
 
6062
  ulint   buff2_len = table->s->stored_rec_length
 
6063
          + table->s->max_key_length + 100;
6740
6064
  dtuple_t* range_start;
6741
6065
  dtuple_t* range_end;
6742
6066
  ib_int64_t  n_rows;
6744
6068
  ulint   mode2;
6745
6069
  mem_heap_t* heap;
6746
6070
 
6747
 
  ut_a(prebuilt->trx == session_to_trx(getTable()->in_use));
 
6071
  ut_a(prebuilt->trx == session_to_trx(ha_session()));
6748
6072
 
6749
6073
  prebuilt->trx->op_info = (char*)"estimating records in index range";
6750
6074
 
6755
6079
 
6756
6080
  active_index = keynr;
6757
6081
 
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
 
  }
 
6082
  key = table->key_info + active_index;
 
6083
 
 
6084
  index = dict_table_get_index_on_name(prebuilt->table, key->name);
 
6085
 
 
6086
  /* MySQL knows about this index and so we must be able to find it.*/
 
6087
  ut_a(index);
6774
6088
 
6775
6089
  heap = mem_heap_create(2 * (key->key_parts * sizeof(dfield_t)
6776
6090
            + sizeof(dtuple_t)));
6782
6096
  dict_index_copy_types(range_end, index, key->key_parts);
6783
6097
 
6784
6098
  row_sel_convert_mysql_key_to_innobase(
6785
 
        range_start, (byte*) &key_val_buff[0],
 
6099
        range_start, (byte*) key_val_buff,
6786
6100
        (ulint)upd_and_key_val_buff_len,
6787
6101
        index,
6788
6102
        (byte*) (min_key ? min_key->key :
6815
6129
 
6816
6130
  mem_heap_free(heap);
6817
6131
 
6818
 
func_exit:
6819
6132
  free(key_val_buff2);
6820
6133
 
6821
6134
  prebuilt->trx->op_info = (char*)"";
6845
6158
  dict_index_t* index;
6846
6159
  uint64_t  estimate;
6847
6160
  uint64_t  local_data_file_length;
6848
 
  ulint stat_n_leaf_pages;
6849
6161
 
6850
6162
  /* We do not know if MySQL can call this function before calling
6851
6163
  external_lock(). To be safe, update the session of the current table
6852
6164
  handle. */
6853
6165
 
6854
 
  update_session(getTable()->in_use);
 
6166
  update_session(ha_session());
6855
6167
 
6856
6168
  prebuilt->trx->op_info = (char*)
6857
6169
         "calculating upper bound for table rows";
6863
6175
 
6864
6176
  index = dict_table_get_first_index(prebuilt->table);
6865
6177
 
6866
 
  stat_n_leaf_pages = index->stat_n_leaf_pages;
6867
 
 
6868
 
  ut_a(stat_n_leaf_pages > 0);
 
6178
  ut_a(index->stat_n_leaf_pages > 0);
6869
6179
 
6870
6180
  local_data_file_length =
6871
 
    ((uint64_t) stat_n_leaf_pages) * UNIV_PAGE_SIZE;
 
6181
    ((uint64_t) index->stat_n_leaf_pages) * UNIV_PAGE_SIZE;
6872
6182
 
6873
6183
 
6874
6184
  /* Calculate a minimum length for a clustered index record and from
6917
6227
  ha_rows total_rows;
6918
6228
  double  time_for_scan;
6919
6229
 
6920
 
  if (index != getTable()->getShare()->getPrimaryKey()) {
 
6230
  if (index != table->s->primary_key) {
6921
6231
    /* Not clustered */
6922
6232
    return(Cursor::read_time(index, ranges, rows));
6923
6233
  }
6941
6251
}
6942
6252
 
6943
6253
/*********************************************************************//**
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
6254
Returns statistics information of the table to the MySQL interpreter,
7046
6255
in various fields of the handle object. */
7047
6256
UNIV_INTERN
7054
6263
  dict_index_t* index;
7055
6264
  ha_rows   rec_per_key;
7056
6265
  ib_int64_t  n_rows;
 
6266
  ulong   j;
 
6267
  ulong   i;
 
6268
  char    path[FN_REFLEN];
7057
6269
  os_file_stat_t  stat_info;
7058
6270
 
7059
6271
  /* If we are forcing recovery at a high level, we will suppress
7060
6272
  statistics calculation on tables, because that may crash the
7061
6273
  server if an index is badly corrupted. */
7062
6274
 
 
6275
  if (srv_force_recovery >= SRV_FORCE_NO_IBUF_MERGE) {
 
6276
 
 
6277
    /* We return success (0) instead of HA_ERR_CRASHED,
 
6278
    because we want MySQL to process this query and not
 
6279
    stop, like it would do if it received the error code
 
6280
    HA_ERR_CRASHED. */
 
6281
 
 
6282
    return(0);
 
6283
  }
 
6284
 
7063
6285
  /* We do not know if MySQL can call this function before calling
7064
6286
  external_lock(). To be safe, update the session of the current table
7065
6287
  handle. */
7066
6288
 
7067
 
  update_session(getTable()->in_use);
 
6289
  update_session(ha_session());
7068
6290
 
7069
6291
  /* In case MySQL calls this in the middle of a SELECT query, release
7070
6292
  possible adaptive hash latch to avoid deadlocks of threads */
7076
6298
  ib_table = prebuilt->table;
7077
6299
 
7078
6300
  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");
 
6301
    if (innobase_stats_on_metadata) {
 
6302
      /* In sql_show we call with this flag: update
 
6303
      then statistics so that they are up-to-date */
 
6304
 
 
6305
      prebuilt->trx->op_info = "updating table statistics";
 
6306
 
 
6307
      dict_update_statistics(ib_table);
 
6308
 
 
6309
      prebuilt->trx->op_info = "returning various info to MySQL";
 
6310
    }
 
6311
 
 
6312
    snprintf(path, sizeof(path), "%s/%s%s",
 
6313
             data_home, ib_table->name, ".dfe");
 
6314
 
 
6315
    internal::unpack_filename(path,path);
7094
6316
 
7095
6317
    /* Note that we do not know the access time of the table,
7096
6318
    nor the CHECK TABLE time, nor the UPDATE or INSERT time. */
7097
6319
 
7098
 
    if (os_file_get_status(get_status_path.file_string().c_str(), &stat_info)) {
 
6320
    if (os_file_get_status(path,&stat_info)) {
7099
6321
      stats.create_time = (ulong) stat_info.ctime;
7100
6322
    }
7101
6323
  }
7102
6324
 
7103
6325
  if (flag & HA_STATUS_VARIABLE) {
7104
 
 
7105
 
    dict_table_stats_lock(ib_table, RW_S_LATCH);
7106
 
 
7107
6326
    n_rows = ib_table->stat_n_rows;
7108
6327
 
7109
6328
    /* Because we do not protect stat_n_rows by any mutex in a
7131
6350
    n_rows can not be 0 unless the table is empty, set to 1
7132
6351
    instead. The original problem of bug#29507 is actually
7133
6352
    fixed in the server code. */
7134
 
    if (user_session->getSqlCommand() == SQLCOM_TRUNCATE) {
 
6353
    if (session_sql_command(user_session) == SQLCOM_TRUNCATE) {
7135
6354
 
7136
6355
      n_rows = 1;
7137
6356
 
7153
6372
        ib_table->stat_sum_of_other_index_sizes)
7154
6373
          * UNIV_PAGE_SIZE;
7155
6374
 
7156
 
    dict_table_stats_unlock(ib_table, RW_S_LATCH);
7157
 
 
7158
6375
    /* Since fsp_get_available_space_in_free_extents() is
7159
6376
    acquiring latches inside InnoDB, we do not call it if we
7160
6377
    are asked by MySQL to avoid locking. Another reason to
7161
6378
    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) {
 
6379
    See Bug#38185.
 
6380
    We do not update delete_length if no locking is requested
 
6381
    so the "old" value can remain. delete_length is initialized
 
6382
    to 0 in the ha_statistics' constructor. */
 
6383
    if (!(flag & HA_STATUS_NO_LOCK)) {
 
6384
 
 
6385
      /* lock the data dictionary to avoid races with
 
6386
      ibd_file_missing and tablespace_discarded */
 
6387
      row_mysql_lock_data_dictionary(prebuilt->trx);
 
6388
 
 
6389
      /* ib_table->space must be an existent tablespace */
 
6390
      if (!ib_table->ibd_file_missing
 
6391
          && !ib_table->tablespace_discarded) {
 
6392
 
 
6393
        stats.delete_length =
 
6394
          fsp_get_available_space_in_free_extents(
 
6395
            ib_table->space) * 1024;
 
6396
      } else {
 
6397
 
7179
6398
        Session*  session;
7180
6399
 
7181
 
        session= getTable()->in_use;
7182
 
        assert(session);
 
6400
        session = ha_session();
7183
6401
 
7184
6402
        push_warning_printf(
7185
6403
          session,
7193
6411
          ib_table->name);
7194
6412
 
7195
6413
        stats.delete_length = 0;
7196
 
      } else {
7197
 
        stats.delete_length = avail_space * 1024;
7198
6414
      }
 
6415
 
 
6416
      row_mysql_unlock_data_dictionary(prebuilt->trx);
7199
6417
    }
7200
6418
 
7201
6419
    stats.check_time = 0;
7208
6426
  }
7209
6427
 
7210
6428
  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;
 
6429
    index = dict_table_get_first_index(ib_table);
7216
6430
 
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);
 
6431
    if (prebuilt->clust_index_was_generated) {
 
6432
      index = dict_table_get_next_index(index);
7224
6433
    }
7225
6434
 
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
 
 
 
6435
    for (i = 0; i < table->s->keys; i++) {
7237
6436
      if (index == NULL) {
7238
 
        errmsg_printf(error::ERROR, "Table %s contains fewer "
 
6437
        errmsg_printf(ERRMSG_LVL_ERROR, "Table %s contains fewer "
7239
6438
            "indexes inside InnoDB than "
7240
6439
            "are defined in the MySQL "
7241
6440
            ".frm file. Have you mixed up "
7247
6446
        break;
7248
6447
      }
7249
6448
 
7250
 
      for (j = 0; j < getTable()->key_info[i].key_parts; j++) {
 
6449
      for (j = 0; j < table->key_info[i].key_parts; j++) {
7251
6450
 
7252
6451
        if (j + 1 > index->n_uniq) {
7253
 
          errmsg_printf(error::ERROR, 
 
6452
          errmsg_printf(ERRMSG_LVL_ERROR, 
7254
6453
"Index %s of %s has %lu columns unique inside InnoDB, but MySQL is asking "
7255
6454
"statistics for %lu columns. Have you mixed up .frm files from different "
7256
6455
"installations? "
7281
6480
          rec_per_key = 1;
7282
6481
        }
7283
6482
 
7284
 
        getTable()->key_info[i].rec_per_key[j]=
 
6483
        table->key_info[i].rec_per_key[j]=
7285
6484
          rec_per_key >= ~(ulong) 0 ? ~(ulong) 0 :
7286
6485
          (ulong) rec_per_key;
7287
6486
      }
 
6487
 
 
6488
      index = dict_table_get_next_index(index);
7288
6489
    }
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
6490
  }
7296
6491
 
7297
6492
  if (flag & HA_STATUS_ERRKEY) {
7304
6499
 
7305
6500
    if (err_index) {
7306
6501
      errkey = (unsigned int)
7307
 
        innobase_get_mysql_key_number_for_index(share, getTable(), ib_table,
7308
 
                                                err_index);
 
6502
        row_get_mysql_key_number_for_index(err_index);
7309
6503
    } else {
7310
6504
      errkey = (unsigned int) prebuilt->trx->error_key_num;
7311
6505
    }
7312
6506
  }
7313
6507
 
7314
 
  if ((flag & HA_STATUS_AUTO) && getTable()->found_next_number_field) {
 
6508
  if ((flag & HA_STATUS_AUTO) && table->found_next_number_field) {
7315
6509
    stats.auto_increment_value = innobase_peek_autoinc();
7316
6510
  }
7317
6511
 
7318
 
func_exit:
7319
6512
  prebuilt->trx->op_info = (char*)"";
7320
6513
 
7321
6514
  return(0);
7348
6541
/*===============*/
7349
6542
  Session*  session)  /*!< in: user thread handle */
7350
6543
{
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;
 
6544
  ulint   ret;
7356
6545
 
7357
 
  assert(session == getTable()->in_use);
 
6546
  assert(session == ha_session());
7358
6547
  ut_a(prebuilt->trx);
7359
6548
  ut_a(prebuilt->trx->magic_n == TRX_MAGIC_N);
7360
6549
  ut_a(prebuilt->trx == session_to_trx(session));
7363
6552
    /* Build the template; we will use a dummy template
7364
6553
    in index scans done in checking */
7365
6554
 
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);
 
6555
    build_template(prebuilt, NULL, table, ROW_MYSQL_WHOLE_ROW);
 
6556
  }
 
6557
 
 
6558
  ret = row_check_table_for_mysql(prebuilt);
 
6559
 
 
6560
  if (ret == DB_SUCCESS) {
 
6561
    return(HA_ADMIN_OK);
 
6562
  }
 
6563
 
 
6564
  return(HA_ADMIN_CORRUPT);
7503
6565
}
7504
6566
 
7505
6567
/*************************************************************//**
7525
6587
    return((char*)comment); /* string too long */
7526
6588
  }
7527
6589
 
7528
 
  update_session(getTable()->in_use);
 
6590
  update_session(ha_session());
7529
6591
 
7530
6592
  prebuilt->trx->op_info = (char*)"returning table comment";
7531
6593
 
7596
6658
  external_lock(). To be safe, update the session of the current table
7597
6659
  handle. */
7598
6660
 
7599
 
  update_session(getTable()->in_use);
 
6661
  update_session(ha_session());
7600
6662
 
7601
6663
  prebuilt->trx->op_info = (char*)"getting info on foreign keys";
7602
6664
 
7617
6679
  flen = ftell(srv_dict_tmpfile);
7618
6680
  if (flen < 0) {
7619
6681
    flen = 0;
 
6682
  } else if (flen > 64000 - 1) {
 
6683
    flen = 64000 - 1;
7620
6684
  }
7621
6685
 
7622
6686
  /* allocate buffer for the string, and
7643
6707
  dict_foreign_t* foreign;
7644
6708
 
7645
6709
  ut_a(prebuilt != NULL);
7646
 
  update_session(getTable()->in_use);
 
6710
  update_session(ha_session());
7647
6711
  prebuilt->trx->op_info = (char*)"getting list of foreign keys";
7648
6712
  trx_search_latch_release_if_reserved(prebuilt->trx);
7649
6713
  mutex_enter(&(dict_sys->mutex));
7653
6717
 
7654
6718
    uint i;
7655
6719
    LEX_STRING *name = 0;
7656
 
    uint ulen;
7657
 
    char uname[NAME_LEN + 1];           /* Unencoded name */
7658
 
    char db_name[NAME_LEN + 1];
 
6720
      uint ulen;
 
6721
      char uname[NAME_LEN + 1];           /* Unencoded name */
 
6722
      char db_name[NAME_LEN + 1];
7659
6723
    const char *tmp_buff;
7660
6724
 
7661
6725
    /** Foreign id **/
7666
6730
    tmp_buff += i + 1;
7667
6731
    LEX_STRING *tmp_foreign_id = session->make_lex_string(NULL, tmp_buff, strlen(tmp_buff), true);
7668
6732
 
7669
 
    /* Database name */
 
6733
      /* Database name */
7670
6734
    tmp_buff = foreign->referenced_table_name;
7671
6735
 
7672
6736
    i= 0;
7673
6737
    while (tmp_buff[i] != '/')
7674
 
    {
7675
 
      db_name[i]= tmp_buff[i];
7676
 
      i++;
7677
 
    }
7678
 
    db_name[i] = 0;
7679
 
    ulen= identifier::Table::filename_to_tablename(db_name, uname, sizeof(uname));
 
6738
      {
 
6739
        db_name[i]= tmp_buff[i];
 
6740
        i++;
 
6741
      }
 
6742
      db_name[i] = 0;
 
6743
      ulen= filename_to_tablename(db_name, uname, sizeof(uname));
7680
6744
    LEX_STRING *tmp_referenced_db = session->make_lex_string(NULL, uname, ulen, true);
7681
6745
 
7682
 
    /* Table name */
 
6746
      /* Table name */
7683
6747
    tmp_buff += i + 1;
7684
 
    ulen= identifier::Table::filename_to_tablename(tmp_buff, uname, sizeof(uname));
 
6748
      ulen= filename_to_tablename(tmp_buff, uname, sizeof(uname));
7685
6749
    LEX_STRING *tmp_referenced_table = session->make_lex_string(NULL, uname, ulen, true);
7686
6750
 
7687
 
    /** Foreign Fields **/
7688
 
    List<LEX_STRING> tmp_foreign_fields;
7689
 
    List<LEX_STRING> tmp_referenced_fields;
 
6751
      /** Foreign Fields **/
 
6752
  List<LEX_STRING> tmp_foreign_fields;
 
6753
  List<LEX_STRING> tmp_referenced_fields;
7690
6754
    for (i= 0;;) {
7691
6755
      tmp_buff= foreign->foreign_col_names[i];
7692
6756
      name = session->make_lex_string(name, tmp_buff, strlen(tmp_buff), true);
7698
6762
        break;
7699
6763
    }
7700
6764
 
7701
 
    ulong length;
7702
 
    if (foreign->type & DICT_FOREIGN_ON_DELETE_CASCADE)
7703
 
    {
7704
 
      length=7;
7705
 
      tmp_buff= "CASCADE";
7706
 
    }
7707
 
    else if (foreign->type & DICT_FOREIGN_ON_DELETE_SET_NULL)
7708
 
    {
7709
 
      length=8;
7710
 
      tmp_buff= "SET NULL";
7711
 
    }
7712
 
    else if (foreign->type & DICT_FOREIGN_ON_DELETE_NO_ACTION)
7713
 
    {
7714
 
      length=9;
7715
 
      tmp_buff= "NO ACTION";
7716
 
    }
7717
 
    else
7718
 
    {
7719
 
      length=8;
7720
 
      tmp_buff= "RESTRICT";
7721
 
    }
 
6765
          ulong length;
 
6766
          if (foreign->type & DICT_FOREIGN_ON_DELETE_CASCADE)
 
6767
          {
 
6768
            length=7;
 
6769
            tmp_buff= "CASCADE";
 
6770
          }
 
6771
          else if (foreign->type & DICT_FOREIGN_ON_DELETE_SET_NULL)
 
6772
          {
 
6773
            length=8;
 
6774
            tmp_buff= "SET NULL";
 
6775
          }
 
6776
          else if (foreign->type & DICT_FOREIGN_ON_DELETE_NO_ACTION)
 
6777
          {
 
6778
            length=9;
 
6779
            tmp_buff= "NO ACTION";
 
6780
          }
 
6781
          else
 
6782
          {
 
6783
            length=8;
 
6784
            tmp_buff= "RESTRICT";
 
6785
          }
7722
6786
    LEX_STRING *tmp_delete_method = session->make_lex_string(NULL, tmp_buff, length, true);
7723
 
 
7724
 
 
7725
 
    if (foreign->type & DICT_FOREIGN_ON_UPDATE_CASCADE)
7726
 
    {
7727
 
      length=7;
7728
 
      tmp_buff= "CASCADE";
7729
 
    }
7730
 
    else if (foreign->type & DICT_FOREIGN_ON_UPDATE_SET_NULL)
7731
 
    {
7732
 
      length=8;
7733
 
      tmp_buff= "SET NULL";
7734
 
    }
7735
 
    else if (foreign->type & DICT_FOREIGN_ON_UPDATE_NO_ACTION)
7736
 
    {
7737
 
      length=9;
7738
 
      tmp_buff= "NO ACTION";
7739
 
    }
7740
 
    else
7741
 
    {
7742
 
      length=8;
7743
 
      tmp_buff= "RESTRICT";
7744
 
    }
 
6787
 
 
6788
 
 
6789
          if (foreign->type & DICT_FOREIGN_ON_UPDATE_CASCADE)
 
6790
          {
 
6791
            length=7;
 
6792
            tmp_buff= "CASCADE";
 
6793
          }
 
6794
          else if (foreign->type & DICT_FOREIGN_ON_UPDATE_SET_NULL)
 
6795
          {
 
6796
            length=8;
 
6797
            tmp_buff= "SET NULL";
 
6798
          }
 
6799
          else if (foreign->type & DICT_FOREIGN_ON_UPDATE_NO_ACTION)
 
6800
          {
 
6801
            length=9;
 
6802
            tmp_buff= "NO ACTION";
 
6803
          }
 
6804
          else
 
6805
          {
 
6806
            length=8;
 
6807
            tmp_buff= "RESTRICT";
 
6808
          }
7745
6809
    LEX_STRING *tmp_update_method = session->make_lex_string(NULL, tmp_buff, length, true);
7746
6810
 
7747
6811
    LEX_STRING *tmp_referenced_key_name = NULL;
7748
6812
 
7749
 
    if (foreign->referenced_index &&
7750
 
        foreign->referenced_index->name)
7751
 
    {
7752
 
      tmp_referenced_key_name = session->make_lex_string(NULL,
7753
 
                                                         foreign->referenced_index->name, strlen(foreign->referenced_index->name), true);
7754
 
    }
 
6813
          if (foreign->referenced_index &&
 
6814
              foreign->referenced_index->name)
 
6815
          {
 
6816
        tmp_referenced_key_name = session->make_lex_string(NULL,
 
6817
        foreign->referenced_index->name, strlen(foreign->referenced_index->name), true);
 
6818
          }
7755
6819
 
7756
 
    ForeignKeyInfo f_key_info(
7757
 
                              tmp_foreign_id, tmp_referenced_db, tmp_referenced_table,
7758
 
                              tmp_update_method, tmp_delete_method, tmp_referenced_key_name,
7759
 
                              tmp_foreign_fields, tmp_referenced_fields);
 
6820
      ForeignKeyInfo f_key_info(
 
6821
        tmp_foreign_id, tmp_referenced_db, tmp_referenced_table,
 
6822
        tmp_update_method, tmp_delete_method, tmp_referenced_key_name,
 
6823
        tmp_foreign_fields, tmp_referenced_fields);
7760
6824
 
7761
6825
    ForeignKeyInfo *pf_key_info = (ForeignKeyInfo *)
7762
 
      session->getMemRoot()->duplicate(&f_key_info, sizeof(ForeignKeyInfo));
 
6826
      session->memdup(&f_key_info, sizeof(ForeignKeyInfo));
7763
6827
    f_key_list->push_back(pf_key_info);
7764
6828
    foreign = UT_LIST_GET_NEXT(foreign_list, foreign);
7765
6829
  }
7781
6845
{
7782
6846
  bool  can_switch;
7783
6847
 
7784
 
  ut_a(prebuilt->trx == session_to_trx(getTable()->in_use));
 
6848
  ut_a(prebuilt->trx == session_to_trx(ha_session()));
7785
6849
 
7786
6850
  prebuilt->trx->op_info =
7787
6851
      "determining if there are foreign key constraints";
7869
6933
      either, because the calling threads may change.
7870
6934
      CAREFUL HERE, OR MEMORY CORRUPTION MAY OCCUR! */
7871
6935
    case HA_EXTRA_IGNORE_DUP_KEY:
7872
 
      session_to_trx(getTable()->in_use)->duplicates |= TRX_DUP_IGNORE;
 
6936
      session_to_trx(ha_session())->duplicates |= TRX_DUP_IGNORE;
7873
6937
      break;
7874
6938
    case HA_EXTRA_WRITE_CAN_REPLACE:
7875
 
      session_to_trx(getTable()->in_use)->duplicates |= TRX_DUP_REPLACE;
 
6939
      session_to_trx(ha_session())->duplicates |= TRX_DUP_REPLACE;
7876
6940
      break;
7877
6941
    case HA_EXTRA_WRITE_CANNOT_REPLACE:
7878
 
      session_to_trx(getTable()->in_use)->duplicates &= ~TRX_DUP_REPLACE;
 
6942
      session_to_trx(ha_session())->duplicates &= ~TRX_DUP_REPLACE;
7879
6943
      break;
7880
6944
    case HA_EXTRA_NO_IGNORE_DUP_KEY:
7881
 
      session_to_trx(getTable()->in_use)->duplicates &=
 
6945
      session_to_trx(ha_session())->duplicates &=
7882
6946
        ~(TRX_DUP_IGNORE | TRX_DUP_REPLACE);
7883
6947
      break;
7884
6948
    default:/* Do nothing */
8014
7078
{
8015
7079
  trx_t*      trx;
8016
7080
  static const char truncated_msg[] = "... truncated...\n";
8017
 
  const long    MAX_STATUS_SIZE = 1048576;
 
7081
  const long    MAX_STATUS_SIZE = 64000;
8018
7082
  ulint     trx_list_start = ULINT_UNDEFINED;
8019
7083
  ulint     trx_list_end = ULINT_UNDEFINED;
8020
7084
 
8032
7096
 
8033
7097
  mutex_enter(&srv_monitor_file_mutex);
8034
7098
  rewind(srv_monitor_file);
8035
 
  srv_printf_innodb_monitor(srv_monitor_file, FALSE,
 
7099
  srv_printf_innodb_monitor(srv_monitor_file,
8036
7100
        &trx_list_start, &trx_list_end);
8037
7101
  flen = ftell(srv_monitor_file);
8038
7102
  os_file_set_eof(srv_monitor_file);
8043
7107
 
8044
7108
  if (flen > MAX_STATUS_SIZE) {
8045
7109
    usable_len = MAX_STATUS_SIZE;
8046
 
    srv_truncated_status_writes++;
8047
7110
  } else {
8048
7111
    usable_len = flen;
8049
7112
  }
8079
7142
 
8080
7143
  mutex_exit(&srv_monitor_file_mutex);
8081
7144
 
8082
 
  stat_print(session, innobase_engine_name, strlen(innobase_engine_name),
8083
 
             STRING_WITH_LEN(""), str, flen);
 
7145
  bool result = FALSE;
8084
7146
 
 
7147
  if (stat_print(session, innobase_engine_name, strlen(innobase_engine_name),
 
7148
      STRING_WITH_LEN(""), str, flen)) {
 
7149
    result= TRUE;
 
7150
  }
8085
7151
  free(str);
8086
7152
 
8087
7153
  return(FALSE);
8088
7154
}
8089
7155
 
8090
7156
/************************************************************************//**
8091
 
Implements the SHOW MUTEX STATUS command.
8092
 
@return true on failure false on success*/
 
7157
Implements the SHOW MUTEX STATUS command. . */
8093
7158
static
8094
7159
bool
8095
7160
innodb_mutex_show_status(
8097
7162
  plugin::StorageEngine*  engine,   /*!< in: the innodb StorageEngine */
8098
7163
  Session*  session,  /*!< in: the MySQL query thread of the
8099
7164
          caller */
8100
 
  stat_print_fn*  stat_print)   /*!< in: function for printing
8101
 
                                        statistics */
 
7165
  stat_print_fn*  stat_print)
8102
7166
{
8103
7167
  char buf1[IO_SIZE], buf2[IO_SIZE];
8104
7168
  mutex_t*  mutex;
8105
7169
  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
7170
#ifdef UNIV_DEBUG
8111
7171
  ulint   rw_lock_count= 0;
8112
7172
  ulint   rw_lock_count_spin_loop= 0;
8120
7180
 
8121
7181
  mutex_enter(&mutex_list_mutex);
8122
7182
 
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;
 
7183
  mutex = UT_LIST_GET_FIRST(mutex_list);
 
7184
 
 
7185
  while (mutex != NULL) {
 
7186
    if (mutex->count_os_wait == 0
 
7187
        || buf_pool_is_block_mutex(mutex)) {
 
7188
      goto next_mutex;
8134
7189
    }
8135
7190
#ifdef UNIV_DEBUG
8136
7191
    if (mutex->mutex_type != 1) {
8157
7212
          return(1);
8158
7213
        }
8159
7214
      }
8160
 
    } else {
 
7215
    }
 
7216
    else {
8161
7217
      rw_lock_count += mutex->count_using;
8162
7218
      rw_lock_count_spin_loop += mutex->count_spin_loop;
8163
7219
      rw_lock_count_spin_rounds += mutex->count_spin_rounds;
8169
7225
    buf1len= snprintf(buf1, sizeof(buf1), "%s:%lu",
8170
7226
          mutex->cfile_name, (ulong) mutex->cline);
8171
7227
    buf2len= snprintf(buf2, sizeof(buf2), "os_waits=%lu",
8172
 
                      (ulong) mutex->count_os_wait);
 
7228
          mutex->count_os_wait);
8173
7229
 
8174
7230
    if (stat_print(session, innobase_engine_name,
8175
7231
             engine_name_len, buf1, buf1len,
8178
7234
      return(1);
8179
7235
    }
8180
7236
#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
 
    }
 
7237
 
 
7238
next_mutex:
 
7239
    mutex = UT_LIST_GET_NEXT(list, mutex);
8198
7240
  }
8199
7241
 
8200
7242
  mutex_exit(&mutex_list_mutex);
8201
7243
 
8202
7244
  mutex_enter(&rw_lock_list_mutex);
8203
7245
 
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
 
    }
 
7246
  lock = UT_LIST_GET_FIRST(rw_lock_list);
 
7247
 
 
7248
  while (lock != NULL) {
 
7249
    if (lock->count_os_wait
 
7250
                    && !buf_pool_is_block_lock(lock)) {
 
7251
      buf1len= snprintf(buf1, sizeof(buf1), "%s:%lu",
 
7252
                                    lock->cfile_name, (unsigned long) lock->cline);
 
7253
      buf2len= snprintf(buf2, sizeof(buf2),
 
7254
                                    "os_waits=%lu", lock->count_os_wait);
 
7255
 
 
7256
      if (stat_print(session, innobase_engine_name,
 
7257
               engine_name_len, buf1, buf1len,
 
7258
               buf2, buf2len)) {
 
7259
        mutex_exit(&rw_lock_list_mutex);
 
7260
        return(1);
 
7261
      }
 
7262
    }
 
7263
    lock = UT_LIST_GET_NEXT(list, lock);
8244
7264
  }
8245
7265
 
8246
7266
  mutex_exit(&rw_lock_list_mutex);
8247
7267
 
8248
7268
#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));
 
7269
  buf2len= my_snprintf(buf2, sizeof(buf2),
 
7270
    "count=%lu, spin_waits=%lu, spin_rounds=%lu, "
 
7271
    "os_waits=%lu, os_yields=%lu, os_wait_times=%lu",
 
7272
    rw_lock_count, rw_lock_count_spin_loop,
 
7273
    rw_lock_count_spin_rounds,
 
7274
    rw_lock_count_os_wait, rw_lock_count_os_yield,
 
7275
    (ulong) (rw_lock_wait_time/1000));
8258
7276
 
8259
7277
  if (stat_print(session, innobase_engine_name, engine_name_len,
8260
7278
      STRING_WITH_LEN("rw_lock_mutexes"), buf2, buf2len)) {
8289
7307
static INNOBASE_SHARE* get_share(const char* table_name)
8290
7308
{
8291
7309
  INNOBASE_SHARE *share;
8292
 
  boost::mutex::scoped_lock scopedLock(innobase_share_mutex);
 
7310
  pthread_mutex_lock(&innobase_share_mutex);
8293
7311
 
8294
7312
  ulint fold = ut_fold_string(table_name);
8295
7313
 
8299
7317
        !strcmp(share->table_name, table_name));
8300
7318
 
8301
7319
  if (!share) {
 
7320
 
 
7321
    uint length = (uint) strlen(table_name);
 
7322
 
8302
7323
    /* TODO: invoke HASH_MIGRATE if innobase_open_tables
8303
7324
    grows too big */
8304
7325
 
8305
 
    share= new INNOBASE_SHARE(table_name);
 
7326
    share = (INNOBASE_SHARE *) malloc(sizeof(*share)+length+1);
 
7327
                memset(share, 0, sizeof(*share)+length+1);
 
7328
 
 
7329
    share->table_name = (char*) memcpy(share + 1,
 
7330
               table_name, length + 1);
8306
7331
 
8307
7332
    HASH_INSERT(INNOBASE_SHARE, table_name_hash,
8308
7333
          innobase_open_tables, fold, share);
8309
7334
 
8310
7335
    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
7336
  }
8317
7337
 
8318
7338
  share->use_count++;
 
7339
  pthread_mutex_unlock(&innobase_share_mutex);
8319
7340
 
8320
7341
  return(share);
8321
7342
}
8322
7343
 
8323
7344
static void free_share(INNOBASE_SHARE* share)
8324
7345
{
8325
 
  boost::mutex::scoped_lock scopedLock(innobase_share_mutex);
 
7346
  pthread_mutex_lock(&innobase_share_mutex);
8326
7347
 
8327
7348
#ifdef UNIV_DEBUG
8328
7349
  INNOBASE_SHARE* share2;
8341
7362
 
8342
7363
    HASH_DELETE(INNOBASE_SHARE, table_name_hash,
8343
7364
          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;
 
7365
    thr_lock_delete(&share->lock);
 
7366
    free(share);
8350
7367
 
8351
7368
    /* TODO: invoke HASH_MIGRATE if innobase_open_tables
8352
7369
    shrinks too much */
8353
7370
  }
 
7371
 
 
7372
  pthread_mutex_unlock(&innobase_share_mutex);
8354
7373
}
8355
7374
 
8356
7375
/*****************************************************************//**
8385
7404
  trx = check_trx_exists(session);
8386
7405
 
8387
7406
  assert(EQ_CURRENT_SESSION(session));
8388
 
  const uint32_t sql_command = session->getSqlCommand();
 
7407
  const uint32_t sql_command = session_sql_command(session);
8389
7408
 
8390
7409
  if (sql_command == SQLCOM_DROP_TABLE) {
8391
7410
 
8421
7440
    isolation_level = trx->isolation_level;
8422
7441
 
8423
7442
    if ((srv_locks_unsafe_for_binlog
8424
 
         || isolation_level <= TRX_ISO_READ_COMMITTED)
 
7443
         || isolation_level == TRX_ISO_READ_COMMITTED)
8425
7444
        && isolation_level != TRX_ISO_SERIALIZABLE
8426
7445
        && (lock_type == TL_READ || lock_type == TL_READ_NO_INSERT)
8427
7446
        && (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)) {
 
7447
      || sql_command == SQLCOM_UPDATE
 
7448
      || sql_command == SQLCOM_CREATE_TABLE)) {
8432
7449
 
8433
7450
      /* If we either have innobase_locks_unsafe_for_binlog
8434
7451
      option set or this session is using READ COMMITTED
8435
7452
      isolation level and isolation level of the transaction
8436
7453
      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. */
 
7454
      INSERT INTO...SELECT or UPDATE ... = (SELECT ...) or
 
7455
      CREATE  ... SELECT... without FOR UPDATE or
 
7456
      IN SHARE MODE in select, then we use consistent
 
7457
      read for select. */
8442
7458
 
8443
7459
      prebuilt->select_lock_type = LOCK_NONE;
8444
7460
      prebuilt->stored_select_lock_type = LOCK_NONE;
8471
7487
 
8472
7488
    if ((lock_type >= TL_WRITE_CONCURRENT_INSERT
8473
7489
         && lock_type <= TL_WRITE)
8474
 
        && ! session->doing_tablespace_operation()
 
7490
        && !session_tablespace_op(session)
8475
7491
        && sql_command != SQLCOM_TRUNCATE
8476
7492
        && sql_command != SQLCOM_CREATE_TABLE) {
8477
7493
 
8510
7526
  uint64_t* value)    /*!< out: autoinc value */
8511
7527
{
8512
7528
  *value = 0;
8513
 
 
8514
 
  dict_table_autoinc_lock(prebuilt->table);
8515
 
  prebuilt->autoinc_error= DB_SUCCESS;
8516
 
  /* Determine the first value of the interval */
8517
 
  *value = dict_table_autoinc_read(prebuilt->table);
8518
 
 
8519
 
  /* It should have been initialized during open. */
8520
 
  if (*value == 0) {
8521
 
    prebuilt->autoinc_error = DB_UNSUPPORTED;
8522
 
    dict_table_autoinc_unlock(prebuilt->table);
 
7529
 
 
7530
  prebuilt->autoinc_error = innobase_lock_autoinc();
 
7531
 
 
7532
  if (prebuilt->autoinc_error == DB_SUCCESS) {
 
7533
 
 
7534
    /* Determine the first value of the interval */
 
7535
    *value = dict_table_autoinc_read(prebuilt->table);
 
7536
 
 
7537
    /* It should have been initialized during open. */
 
7538
    ut_a(*value != 0);
8523
7539
  }
8524
7540
 
8525
 
  return(DB_SUCCESS);
 
7541
  return(prebuilt->autoinc_error);
8526
7542
}
8527
7543
 
8528
7544
/*******************************************************************//**
8529
 
This function reads the global auto-inc counter. It doesn't use the
 
7545
This function reads the global auto-inc counter. It doesn't use the 
8530
7546
AUTOINC lock even if the lock mode is set to TRADITIONAL.
8531
7547
@return the autoinc value */
8532
7548
UNIV_INTERN
8546
7562
 
8547
7563
  auto_inc = dict_table_autoinc_read(innodb_table);
8548
7564
 
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
 
  }
 
7565
  ut_a(auto_inc > 0);
8553
7566
 
8554
7567
  dict_table_autoinc_unlock(innodb_table);
8555
7568
 
8578
7591
  uint64_t  autoinc = 0;
8579
7592
 
8580
7593
  /* Prepare prebuilt->trx in the table handle */
8581
 
  update_session(getTable()->in_use);
 
7594
  update_session(ha_session());
8582
7595
 
8583
7596
  error = innobase_get_autoinc(&autoinc);
8584
7597
 
8602
7615
  invoking this method. So we are not sure if it's guaranteed to
8603
7616
  be 0 or not. */
8604
7617
 
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
7618
  /* Called for the first time ? */
8610
7619
  if (trx->n_autoinc_rows == 0) {
8611
7620
 
8622
7631
  /* Not in the middle of a mult-row INSERT. */
8623
7632
  } else if (prebuilt->autoinc_last_value == 0) {
8624
7633
    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
7634
  }
8631
7635
 
8632
7636
  *nb_reserved_values = trx->n_autoinc_rows;
8633
7637
 
8634
 
  /* This all current style autoinc. */
8635
 
  {
 
7638
  /* With old style AUTOINC locking we only update the table's
 
7639
  AUTOINC counter after attempting to insert the row. */
 
7640
  if (innobase_autoinc_lock_mode != AUTOINC_OLD_STYLE_LOCKING) {
8636
7641
    uint64_t  need;
8637
 
    uint64_t  current;
8638
7642
    uint64_t  next_value;
8639
 
 
8640
 
    current = *first_value > col_max_value ? autoinc : *first_value;
 
7643
    uint64_t  col_max_value;
 
7644
 
 
7645
    /* We need the upper limit of the col type to check for
 
7646
    whether we update the table autoinc counter or not. */
 
7647
    col_max_value = innobase_get_int_col_max_value(
 
7648
      table->next_number_field);
 
7649
 
8641
7650
    need = *nb_reserved_values * increment;
8642
7651
 
8643
7652
    /* Compute the last value in the interval */
8644
 
    next_value = innobase_next_autoinc(current, need, offset, col_max_value);
 
7653
    next_value = innobase_next_autoinc(
 
7654
      *first_value, need, offset, col_max_value);
8645
7655
 
8646
7656
    prebuilt->autoinc_last_value = next_value;
8647
7657
 
8652
7662
      dict_table_autoinc_update_if_greater(
8653
7663
        prebuilt->table, prebuilt->autoinc_last_value);
8654
7664
    }
 
7665
  } else {
 
7666
    /* This will force doInsertRecord() into attempting an update
 
7667
    of the table's AUTOINC counter. */
 
7668
    prebuilt->autoinc_last_value = 0;
8655
7669
  }
8656
7670
 
8657
7671
  /* The increment to be used to increase the AUTOINC value, we use
8678
7692
{
8679
7693
  int error;
8680
7694
 
8681
 
  update_session(getTable()->in_use);
 
7695
  update_session(ha_session());
8682
7696
 
8683
7697
  error = row_lock_table_autoinc_for_mysql(prebuilt);
8684
7698
 
8703
7717
/* See comment in Cursor.cc */
8704
7718
UNIV_INTERN
8705
7719
bool
8706
 
InnobaseEngine::get_error_message(int, String *buf) const
 
7720
InnobaseEngine::get_error_message(int, String *buf)
8707
7721
{
8708
7722
  trx_t*  trx = check_trx_exists(current_session);
8709
7723
 
8744
7758
  /* Do a type-aware comparison of primary key fields. PK fields
8745
7759
  are always NOT NULL, so no checks for NULL are performed. */
8746
7760
 
8747
 
  key_part = getTable()->key_info[getTable()->getShare()->getPrimaryKey()].key_part;
 
7761
  key_part = table->key_info[table->s->primary_key].key_part;
8748
7762
 
8749
7763
  key_part_end = key_part
8750
 
      + getTable()->key_info[getTable()->getShare()->getPrimaryKey()].key_parts;
 
7764
      + table->key_info[table->s->primary_key].key_parts;
8751
7765
 
8752
7766
  for (; key_part != key_part_end; ++key_part) {
8753
7767
    field = key_part->field;
8787
7801
finds charset information and returns length of prefix_len characters in the
8788
7802
index field in bytes.
8789
7803
@return number of bytes occupied by the first n characters */
 
7804
extern "C" UNIV_INTERN
 
7805
ulint
 
7806
innobase_get_at_most_n_mbchars(
 
7807
/*===========================*/
 
7808
  ulint charset_id, /*!< in: character set id */
 
7809
  ulint prefix_len, /*!< in: prefix length in bytes of the index
 
7810
        (this has to be divided by mbmaxlen to get the
 
7811
        number of CHARACTERS n in the prefix) */
 
7812
  ulint data_len,   /*!< in: length of the string in bytes */
 
7813
  const char* str); /*!< in: character string */
8790
7814
 
8791
7815
ulint
8792
7816
innobase_get_at_most_n_mbchars(
8870
7894
  trx->detailed_error[0]= '\0';
8871
7895
 
8872
7896
  /* Set the isolation level of the transaction. */
8873
 
  trx->isolation_level= innobase_map_isolation_level(session->getTxIsolation());
 
7897
  trx->isolation_level= innobase_map_isolation_level((enum_tx_isolation) session_tx_isolation(session));
8874
7898
}
8875
7899
 
8876
7900
void
8885
7909
 
8886
7910
  innobase_release_stat_resources(trx);
8887
7911
 
 
7912
  if (! session_test_options(session, OPTION_NOT_AUTOCOMMIT | OPTION_BEGIN))
 
7913
  {
 
7914
    if (trx->conc_state != TRX_NOT_STARTED)
 
7915
    {
 
7916
      commit(session, TRUE);
 
7917
    }
 
7918
  }
 
7919
  else
 
7920
  {
 
7921
    if (trx->isolation_level <= TRX_ISO_READ_COMMITTED &&
 
7922
        trx->global_read_view)
 
7923
    {
 
7924
      /* At low transaction isolation levels we let
 
7925
      each consistent read set its own snapshot */
 
7926
      read_view_close_for_mysql(trx);
 
7927
    }
 
7928
  }
8888
7929
}
8889
7930
 
8890
7931
/*******************************************************************//**
8913
7954
    return(0);
8914
7955
  }
8915
7956
 
8916
 
  session->get_xid(reinterpret_cast<DrizzleXid*>(&trx->xid));
 
7957
  session->get_xid(reinterpret_cast<DRIZZLE_XID*>(&trx->xid));
8917
7958
 
8918
7959
  /* Release a possible FIFO ticket and search latch. Since we will
8919
7960
  reserve the kernel mutex, we have to release the search system latch
8954
7995
  return(error);
8955
7996
}
8956
7997
 
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
7998
/*******************************************************************//**
8984
7999
This function is used to recover X/Open XA distributed transactions.
8985
8000
@return number of prepared transactions stored in xid_list */
9091
8106
}
9092
8107
 
9093
8108
/************************************************************//**
 
8109
Validate the file format check value, is it one of "on" or "off",
 
8110
as a side effect it sets the srv_check_file_format_at_startup variable.
 
8111
@return true if config value one of "on" or  "off" */
 
8112
static
 
8113
bool
 
8114
innobase_file_format_check_on_off(
 
8115
/*==============================*/
 
8116
  const char* format_check) /*!< in: parameter value */
 
8117
{
 
8118
  bool    ret = true;
 
8119
 
 
8120
  if (!innobase_strcasecmp(format_check, "off")) {
 
8121
 
 
8122
    /* Set the value to disable checking. */
 
8123
    srv_check_file_format_at_startup = DICT_TF_FORMAT_MAX + 1;
 
8124
 
 
8125
  } else if (!innobase_strcasecmp(format_check, "on")) {
 
8126
 
 
8127
    /* Set the value to the lowest supported format. */
 
8128
    srv_check_file_format_at_startup = DICT_TF_FORMAT_51;
 
8129
  } else {
 
8130
    ret = FALSE;
 
8131
  }
 
8132
 
 
8133
  return(ret);
 
8134
}
 
8135
 
 
8136
/************************************************************//**
9094
8137
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 */
 
8138
sets the srv_check_file_format_at_startup variable.
 
8139
@return true if valid config value */
9097
8140
static
9098
 
int
9099
 
innobase_file_format_validate_and_set(
 
8141
bool
 
8142
innobase_file_format_check_validate(
9100
8143
/*================================*/
9101
 
  const char* format_max) /*!< in: parameter value */
 
8144
  const char* format_check) /*!< in: parameter value */
9102
8145
{
9103
8146
  uint    format_id;
 
8147
  bool    ret = true;
9104
8148
 
9105
 
  format_id = innobase_file_format_name_lookup(format_max);
 
8149
  format_id = innobase_file_format_name_lookup(format_check);
9106
8150
 
9107
8151
  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
 
 
 
8152
    srv_check_file_format_at_startup = format_id;
 
8153
  } else {
 
8154
    ret = false;
 
8155
  }
 
8156
 
 
8157
  return(ret);
 
8158
}
 
8159
 
 
8160
/*************************************************************//**
 
8161
Check if it is a valid file format. This function is registered as
 
8162
a callback with MySQL.
 
8163
@return 0 for valid file format */
 
8164
static
 
8165
int
 
8166
innodb_file_format_name_validate(
 
8167
/*=============================*/
 
8168
  Session*      , /*!< in: thread handle */
 
8169
  drizzle_sys_var*  , /*!< in: pointer to system
 
8170
            variable */
 
8171
  void*       save, /*!< out: immediate result
 
8172
            for update function */
 
8173
  drizzle_value*    value)  /*!< in: incoming string */
 
8174
{
 
8175
  const char* file_format_input;
 
8176
  char    buff[STRING_BUFFER_USUAL_SIZE];
 
8177
  int   len = sizeof(buff);
 
8178
 
 
8179
  ut_a(save != NULL);
 
8180
  ut_a(value != NULL);
 
8181
 
 
8182
  file_format_input = value->val_str(value, buff, &len);
 
8183
 
 
8184
  if (file_format_input != NULL) {
 
8185
    uint  format_id;
 
8186
 
 
8187
    format_id = innobase_file_format_name_lookup(
 
8188
      file_format_input);
 
8189
 
 
8190
    if (format_id <= DICT_TF_FORMAT_MAX) {
 
8191
 
 
8192
      *static_cast<const char**>(save) = file_format_input;
 
8193
      return(0);
 
8194
    }
 
8195
  }
 
8196
 
 
8197
  *static_cast<const char**>(save) = NULL;
 
8198
  return(1);
 
8199
}
 
8200
 
 
8201
/****************************************************************//**
 
8202
Update the system variable innodb_file_format using the "saved"
 
8203
value. This function is registered as a callback with MySQL. */
 
8204
static
 
8205
void
 
8206
innodb_file_format_name_update(
 
8207
/*===========================*/
 
8208
  Session*      ,   /*!< in: thread handle */
 
8209
  drizzle_sys_var*  ,   /*!< in: pointer to
 
8210
              system variable */
 
8211
  void*       var_ptr,  /*!< out: where the
 
8212
              formal string goes */
 
8213
  const void*     save)   /*!< in: immediate result
 
8214
              from check function */
 
8215
{
 
8216
  const char* format_name;
 
8217
 
 
8218
  ut_a(var_ptr != NULL);
 
8219
  ut_a(save != NULL);
 
8220
 
 
8221
  format_name = *static_cast<const char*const*>(save);
 
8222
 
 
8223
  if (format_name) {
 
8224
    uint  format_id;
 
8225
 
 
8226
    format_id = innobase_file_format_name_lookup(format_name);
 
8227
 
 
8228
    if (format_id <= DICT_TF_FORMAT_MAX) {
 
8229
      srv_file_format = format_id;
 
8230
    }
 
8231
  }
 
8232
 
 
8233
  *static_cast<const char**>(var_ptr)
 
8234
    = trx_sys_file_format_id_to_name(srv_file_format);
 
8235
}
 
8236
 
 
8237
/*************************************************************//**
 
8238
Check if valid argument to innodb_file_format_check. This
 
8239
function is registered as a callback with MySQL.
 
8240
@return 0 for valid file format */
 
8241
static
 
8242
int
 
8243
innodb_file_format_check_validate(
 
8244
/*==============================*/
 
8245
  Session*      , /*!< in: thread handle */
 
8246
  drizzle_sys_var*  , /*!< in: pointer to system
 
8247
            variable */
 
8248
  void*       save, /*!< out: immediate result
 
8249
            for update function */
 
8250
  drizzle_value*    value)  /*!< in: incoming string */
 
8251
{
 
8252
  const char* file_format_input;
 
8253
  char    buff[STRING_BUFFER_USUAL_SIZE];
 
8254
  int   len = sizeof(buff);
 
8255
 
 
8256
  ut_a(save != NULL);
 
8257
  ut_a(value != NULL);
 
8258
 
 
8259
  file_format_input = value->val_str(value, buff, &len);
 
8260
 
 
8261
  if (file_format_input != NULL) {
 
8262
 
 
8263
    /* Check if user set on/off, we want to print a suitable
 
8264
    message if they did so. */
 
8265
 
 
8266
    if (innobase_file_format_check_on_off(file_format_input)) {
 
8267
      errmsg_printf(ERRMSG_LVL_WARN, 
 
8268
        "InnoDB: invalid innodb_file_format_check "
 
8269
        "value; on/off can only be set at startup or "
 
8270
        "in the configuration file");
 
8271
    } else if (innobase_file_format_check_validate(
 
8272
        file_format_input)) {
 
8273
 
 
8274
      *static_cast<const char**>(save) = file_format_input;
 
8275
 
 
8276
      return(0);
 
8277
 
 
8278
    } else {
 
8279
      errmsg_printf(ERRMSG_LVL_WARN, 
 
8280
        "InnoDB: invalid innodb_file_format_check "
 
8281
        "value; can be any format up to %s "
 
8282
        "or its equivalent numeric id",
 
8283
        trx_sys_file_format_id_to_name(
 
8284
          DICT_TF_FORMAT_MAX));
 
8285
    }
 
8286
  }
 
8287
 
 
8288
  *static_cast<const char**>(save) = NULL;
 
8289
  return(1);
 
8290
}
 
8291
 
 
8292
/****************************************************************//**
 
8293
Update the system variable innodb_file_format_check using the "saved"
 
8294
value. This function is registered as a callback with MySQL. */
 
8295
static
 
8296
void
 
8297
innodb_file_format_check_update(
 
8298
/*============================*/
 
8299
  Session*      session,  /*!< in: thread handle */
 
8300
  drizzle_sys_var*  ,   /*!< in: pointer to
 
8301
              system variable */
 
8302
  void*       var_ptr,  /*!< out: where the
 
8303
              formal string goes */
 
8304
  const void*     save)   /*!< in: immediate result
 
8305
              from check function */
 
8306
{
 
8307
  const char* format_name_in;
 
8308
  const char**  format_name_out;
 
8309
  uint    format_id;
 
8310
 
 
8311
  ut_a(save != NULL);
 
8312
  ut_a(var_ptr != NULL);
 
8313
 
 
8314
  format_name_in = *static_cast<const char*const*>(save);
 
8315
 
 
8316
  if (!format_name_in) {
 
8317
 
 
8318
    return;
 
8319
  }
 
8320
 
 
8321
  format_id = innobase_file_format_name_lookup(format_name_in);
 
8322
 
 
8323
  if (format_id > DICT_TF_FORMAT_MAX) {
 
8324
    /* DEFAULT is "on", which is invalid at runtime. */
 
8325
    push_warning_printf(session, DRIZZLE_ERROR::WARN_LEVEL_WARN,
 
8326
            ER_WRONG_ARGUMENTS,
 
8327
            "Ignoring SET innodb_file_format=%s",
 
8328
            format_name_in);
 
8329
    return;
 
8330
  }
 
8331
 
 
8332
  format_name_out = static_cast<const char**>(var_ptr);
 
8333
 
 
8334
  /* Update the max format id in the system tablespace. */
 
8335
  if (trx_sys_file_format_max_set(format_id, format_name_out)) {
 
8336
    ut_print_timestamp(stderr);
 
8337
    fprintf(stderr,
 
8338
      " [Info] InnoDB: the file format in the system "
 
8339
      "tablespace is now set to %s.\n", *format_name_out);
 
8340
  }
 
8341
}
 
8342
 
 
8343
/****************************************************************//**
 
8344
Update the system variable innodb_adaptive_hash_index using the "saved"
 
8345
value. This function is registered as a callback with MySQL. */
 
8346
static
 
8347
void
 
8348
innodb_adaptive_hash_index_update(
 
8349
/*==============================*/
 
8350
  Session*      ,   /*!< in: thread handle */
 
8351
  drizzle_sys_var*  ,   /*!< in: pointer to
 
8352
              system variable */
 
8353
  void*       , /*!< out: where the
 
8354
              formal string goes */
 
8355
  const void*     save)   /*!< in: immediate result
 
8356
              from check function */
 
8357
{
 
8358
  if (*(bool*) save) {
 
8359
    btr_search_enable();
 
8360
  } else {
 
8361
    btr_search_disable();
 
8362
  }
 
8363
}
 
8364
 
 
8365
/*************************************************************//**
 
8366
Check if it is a valid value of innodb_change_buffering.  This function is
 
8367
registered as a callback with MySQL.
 
8368
@return 0 for valid innodb_change_buffering */
 
8369
static
 
8370
int
 
8371
innodb_change_buffering_validate(
 
8372
/*=============================*/
 
8373
  Session*      , /*!< in: thread handle */
 
8374
  drizzle_sys_var*  , /*!< in: pointer to system
 
8375
            variable */
 
8376
  void*       save, /*!< out: immediate result
 
8377
            for update function */
 
8378
  drizzle_value*    value)  /*!< in: incoming string */
 
8379
{
 
8380
  const char* change_buffering_input;
 
8381
  char    buff[STRING_BUFFER_USUAL_SIZE];
 
8382
  int   len = sizeof(buff);
 
8383
 
 
8384
  ut_a(save != NULL);
 
8385
  ut_a(value != NULL);
 
8386
 
 
8387
  change_buffering_input = value->val_str(value, buff, &len);
 
8388
 
 
8389
  if (change_buffering_input != NULL) {
 
8390
    ulint use;
 
8391
 
 
8392
    for (use = 0; use < UT_ARR_SIZE(innobase_change_buffering_values);
 
8393
         use++) {
 
8394
      if (!innobase_strcasecmp(
 
8395
            change_buffering_input,
 
8396
            innobase_change_buffering_values[use])) {
 
8397
        *(ibuf_use_t*) save = (ibuf_use_t) use;
 
8398
        return(0);
 
8399
      }
 
8400
    }
 
8401
  }
 
8402
 
 
8403
  return(1);
 
8404
}
 
8405
 
 
8406
/****************************************************************//**
 
8407
Update the system variable innodb_change_buffering using the "saved"
 
8408
value. This function is registered as a callback with MySQL. */
 
8409
static
 
8410
void
 
8411
innodb_change_buffering_update(
 
8412
/*===========================*/
 
8413
  Session*      ,   /*!< in: thread handle */
 
8414
  drizzle_sys_var*  ,   /*!< in: pointer to
 
8415
              system variable */
 
8416
  void*       var_ptr,  /*!< out: where the
 
8417
              formal string goes */
 
8418
  const void*     save)   /*!< in: immediate result
 
8419
              from check function */
 
8420
{
 
8421
  ut_a(var_ptr != NULL);
 
8422
  ut_a(save != NULL);
 
8423
  ut_a((*(ibuf_use_t*) save) < IBUF_USE_COUNT);
 
8424
 
 
8425
  ibuf_use = *(const ibuf_use_t*) save;
 
8426
 
 
8427
  *(const char**) var_ptr = innobase_change_buffering_values[ibuf_use];
 
8428
}
 
8429
 
 
8430
/* plugin options */
 
8431
static DRIZZLE_SYSVAR_BOOL(checksums, innobase_use_checksums,
 
8432
  PLUGIN_VAR_NOCMDARG | PLUGIN_VAR_READONLY,
 
8433
  "Enable InnoDB checksums validation (enabled by default). "
 
8434
  "Disable with --skip-innodb-checksums.",
 
8435
  NULL, NULL, TRUE);
 
8436
 
 
8437
static DRIZZLE_SYSVAR_STR(data_home_dir, innobase_data_home_dir,
 
8438
  PLUGIN_VAR_READONLY,
 
8439
  "The common part for InnoDB table spaces.",
 
8440
  NULL, NULL, NULL);
 
8441
 
 
8442
static DRIZZLE_SYSVAR_BOOL(doublewrite, innobase_use_doublewrite,
 
8443
  PLUGIN_VAR_NOCMDARG | PLUGIN_VAR_READONLY,
 
8444
  "Enable InnoDB doublewrite buffer (enabled by default). "
 
8445
  "Disable with --skip-innodb-doublewrite.",
 
8446
  NULL, NULL, TRUE);
 
8447
 
 
8448
static DRIZZLE_SYSVAR_ULONG(io_capacity, srv_io_capacity,
 
8449
  PLUGIN_VAR_RQCMDARG,
 
8450
  "Number of IOPs the server can do. Tunes the background IO rate",
 
8451
  NULL, NULL, 200, 100, ~0L, 0);
 
8452
 
 
8453
static DRIZZLE_SYSVAR_ULONG(fast_shutdown, innobase_fast_shutdown,
 
8454
  PLUGIN_VAR_OPCMDARG,
 
8455
  "Speeds up the shutdown process of the InnoDB storage engine. Possible "
 
8456
  "values are 0, 1 (faster)"
 
8457
  " or 2 (fastest - crash-like)"
 
8458
  ".",
 
8459
  NULL, NULL, 1, 0, 2, 0);
 
8460
 
 
8461
static DRIZZLE_SYSVAR_BOOL(file_per_table, srv_file_per_table,
 
8462
  PLUGIN_VAR_NOCMDARG,
 
8463
  "Stores each InnoDB table to an .ibd file in the database dir.",
 
8464
  NULL, NULL, FALSE);
 
8465
 
 
8466
static DRIZZLE_SYSVAR_STR(file_format, innobase_file_format_name,
 
8467
  PLUGIN_VAR_RQCMDARG,
 
8468
  "File format to use for new tables in .ibd files.",
 
8469
  innodb_file_format_name_validate,
 
8470
  innodb_file_format_name_update, "Antelope");
 
8471
 
 
8472
static DRIZZLE_SYSVAR_STR(file_format_check, innobase_file_format_check,
 
8473
  PLUGIN_VAR_OPCMDARG,
 
8474
  "The highest file format in the tablespace.",
 
8475
  innodb_file_format_check_validate,
 
8476
  innodb_file_format_check_update,
 
8477
  "on");
 
8478
 
 
8479
static DRIZZLE_SYSVAR_ULONG(flush_log_at_trx_commit, srv_flush_log_at_trx_commit,
 
8480
  PLUGIN_VAR_OPCMDARG,
 
8481
  "Set to 0 (write and flush once per second),"
 
8482
  " 1 (write and flush at each commit)"
 
8483
  " or 2 (write at commit, flush once per second).",
 
8484
  NULL, NULL, 1, 0, 2, 0);
 
8485
 
 
8486
static DRIZZLE_SYSVAR_STR(flush_method, innobase_unix_file_flush_method,
 
8487
  PLUGIN_VAR_RQCMDARG | PLUGIN_VAR_READONLY,
 
8488
  "With which method to flush data.", NULL, NULL, NULL);
 
8489
 
 
8490
#ifdef UNIV_LOG_ARCHIVE
 
8491
static DRIZZLE_SYSVAR_STR(log_arch_dir, innobase_log_arch_dir,
 
8492
  PLUGIN_VAR_RQCMDARG | PLUGIN_VAR_READONLY,
 
8493
  "Where full logs should be archived.", NULL, NULL, NULL);
 
8494
 
 
8495
static DRIZZLE_SYSVAR_BOOL(log_archive, innobase_log_archive,
 
8496
  PLUGIN_VAR_OPCMDARG | PLUGIN_VAR_READONLY,
 
8497
  "Set to 1 if you want to have logs archived.", NULL, NULL, FALSE);
 
8498
#endif /* UNIV_LOG_ARCHIVE */
 
8499
 
 
8500
static DRIZZLE_SYSVAR_STR(log_group_home_dir, innobase_log_group_home_dir,
 
8501
  PLUGIN_VAR_RQCMDARG | PLUGIN_VAR_READONLY,
 
8502
  "Path to InnoDB log files.", NULL, NULL, NULL);
 
8503
 
 
8504
static DRIZZLE_SYSVAR_ULONG(max_dirty_pages_pct, srv_max_buf_pool_modified_pct,
 
8505
  PLUGIN_VAR_RQCMDARG,
 
8506
  "Percentage of dirty pages allowed in bufferpool.",
 
8507
  NULL, NULL, 75, 0, 99, 0);
 
8508
 
 
8509
static DRIZZLE_SYSVAR_BOOL(adaptive_flushing, srv_adaptive_flushing,
 
8510
  PLUGIN_VAR_NOCMDARG,
 
8511
  "Attempt flushing dirty pages to avoid IO bursts at checkpoints.",
 
8512
  NULL, NULL, TRUE);
 
8513
 
 
8514
static DRIZZLE_SYSVAR_ULONG(max_purge_lag, srv_max_purge_lag,
 
8515
  PLUGIN_VAR_RQCMDARG,
 
8516
  "Desired maximum length of the purge queue (0 = no limit)",
 
8517
  NULL, NULL, 0, 0, ~0L, 0);
 
8518
 
 
8519
static DRIZZLE_SYSVAR_BOOL(rollback_on_timeout, innobase_rollback_on_timeout,
 
8520
  PLUGIN_VAR_OPCMDARG | PLUGIN_VAR_READONLY,
 
8521
  "Roll back the complete transaction on lock wait timeout, for 4.x compatibility (disabled by default)",
 
8522
  NULL, NULL, FALSE);
 
8523
 
 
8524
static DRIZZLE_SYSVAR_BOOL(status_file, innobase_create_status_file,
 
8525
  PLUGIN_VAR_OPCMDARG | PLUGIN_VAR_NOSYSVAR,
 
8526
  "Enable SHOW INNODB STATUS output in the innodb_status.<pid> file",
 
8527
  NULL, NULL, FALSE);
 
8528
 
 
8529
static DRIZZLE_SYSVAR_BOOL(stats_on_metadata, innobase_stats_on_metadata,
 
8530
  PLUGIN_VAR_OPCMDARG,
 
8531
  "Enable statistics gathering for metadata commands such as SHOW TABLE STATUS (on by default)",
 
8532
  NULL, NULL, TRUE);
 
8533
 
 
8534
static DRIZZLE_SYSVAR_ULONGLONG(stats_sample_pages, srv_stats_sample_pages,
 
8535
  PLUGIN_VAR_RQCMDARG,
 
8536
  "The number of index pages to sample when calculating statistics (default 8)",
 
8537
  NULL, NULL, 8, 1, ~0ULL, 0);
 
8538
 
 
8539
static DRIZZLE_SYSVAR_BOOL(adaptive_hash_index, btr_search_enabled,
 
8540
  PLUGIN_VAR_OPCMDARG,
 
8541
  "Enable InnoDB adaptive hash index (enabled by default).  "
 
8542
  "Disable with --skip-innodb-adaptive-hash-index.",
 
8543
  NULL, innodb_adaptive_hash_index_update, TRUE);
 
8544
 
 
8545
static DRIZZLE_SYSVAR_ULONG(replication_delay, srv_replication_delay,
 
8546
  PLUGIN_VAR_RQCMDARG,
 
8547
  "Replication thread delay (ms) on the slave server if "
 
8548
  "innodb_thread_concurrency is reached (0 by default)",
 
8549
  NULL, NULL, 0, 0, ~0UL, 0);
 
8550
 
 
8551
static DRIZZLE_SYSVAR_LONG(additional_mem_pool_size, innobase_additional_mem_pool_size,
 
8552
  PLUGIN_VAR_RQCMDARG | PLUGIN_VAR_READONLY,
 
8553
  "Size of a memory pool InnoDB uses to store data dictionary information and other internal data structures.",
 
8554
  NULL, NULL, 8*1024*1024L, 512*1024L, LONG_MAX, 1024);
 
8555
 
 
8556
static DRIZZLE_SYSVAR_UINT(autoextend_increment, srv_auto_extend_increment,
 
8557
  PLUGIN_VAR_RQCMDARG,
 
8558
  "Data file autoextend increment in megabytes",
 
8559
  NULL, NULL, 8L, 1L, 1000L, 0);
 
8560
 
 
8561
static DRIZZLE_SYSVAR_LONGLONG(buffer_pool_size, innobase_buffer_pool_size,
 
8562
  PLUGIN_VAR_RQCMDARG | PLUGIN_VAR_READONLY,
 
8563
  "The size of the memory buffer InnoDB uses to cache data and indexes of its tables.",
 
8564
  NULL, NULL, 128*1024*1024L, 5*1024*1024L, INT64_MAX, 1024*1024L);
 
8565
 
 
8566
static DRIZZLE_SYSVAR_ULONG(commit_concurrency, innobase_commit_concurrency,
 
8567
  PLUGIN_VAR_RQCMDARG,
 
8568
  "Helps in performance tuning in heavily concurrent environments.",
 
8569
  innobase_commit_concurrency_validate, NULL, 0, 0, 1000, 0);
 
8570
 
 
8571
static DRIZZLE_SYSVAR_ULONG(concurrency_tickets, srv_n_free_tickets_to_enter,
 
8572
  PLUGIN_VAR_RQCMDARG,
 
8573
  "Number of times a thread is allowed to enter InnoDB within the same SQL query after it has once got the ticket",
 
8574
  NULL, NULL, 500L, 1L, ~0L, 0);
 
8575
 
 
8576
static DRIZZLE_SYSVAR_LONG(file_io_threads, innobase_file_io_threads,
 
8577
  PLUGIN_VAR_RQCMDARG | PLUGIN_VAR_READONLY,
 
8578
  "Number of file I/O threads in InnoDB.",
 
8579
  NULL, NULL, 4, 4, 64, 0);
 
8580
 
 
8581
static DRIZZLE_SYSVAR_ULONG(read_io_threads, innobase_read_io_threads,
 
8582
  PLUGIN_VAR_RQCMDARG | PLUGIN_VAR_READONLY,
 
8583
  "Number of background read I/O threads in InnoDB.",
 
8584
  NULL, NULL, 4, 1, 64, 0);
 
8585
 
 
8586
static DRIZZLE_SYSVAR_ULONG(write_io_threads, innobase_write_io_threads,
 
8587
  PLUGIN_VAR_RQCMDARG | PLUGIN_VAR_READONLY,
 
8588
  "Number of background write I/O threads in InnoDB.",
 
8589
  NULL, NULL, 4, 1, 64, 0);
 
8590
 
 
8591
static DRIZZLE_SYSVAR_LONG(force_recovery, innobase_force_recovery,
 
8592
  PLUGIN_VAR_RQCMDARG | PLUGIN_VAR_READONLY,
 
8593
  "Helps to save your data in case the disk image of the database becomes corrupt.",
 
8594
  NULL, NULL, 0, 0, 6, 0);
 
8595
 
 
8596
static DRIZZLE_SYSVAR_LONG(log_buffer_size, innobase_log_buffer_size,
 
8597
  PLUGIN_VAR_RQCMDARG | PLUGIN_VAR_READONLY,
 
8598
  "The size of the buffer which InnoDB uses to write log to the log files on disk.",
 
8599
  NULL, NULL, 8*1024*1024L, 256*1024L, LONG_MAX, 1024);
 
8600
 
 
8601
static DRIZZLE_SYSVAR_LONGLONG(log_file_size, innobase_log_file_size,
 
8602
  PLUGIN_VAR_RQCMDARG | PLUGIN_VAR_READONLY,
 
8603
  "Size of each log file in a log group.",
 
8604
  NULL, NULL, 5*1024*1024L, 1*1024*1024L, INT64_MAX, 1024*1024L);
 
8605
 
 
8606
static DRIZZLE_SYSVAR_LONG(log_files_in_group, innobase_log_files_in_group,
 
8607
  PLUGIN_VAR_RQCMDARG | PLUGIN_VAR_READONLY,
 
8608
  "Number of log files in the log group. InnoDB writes to the files in a circular fashion. Value 3 is recommended here.",
 
8609
  NULL, NULL, 2, 2, 100, 0);
 
8610
 
 
8611
static DRIZZLE_SYSVAR_LONG(mirrored_log_groups, innobase_mirrored_log_groups,
 
8612
  PLUGIN_VAR_RQCMDARG | PLUGIN_VAR_READONLY,
 
8613
  "Number of identical copies of log groups we keep for the database. Currently this should be set to 1.",
 
8614
  NULL, NULL, 1, 1, 10, 0);
 
8615
 
 
8616
static DRIZZLE_SYSVAR_LONG(open_files, innobase_open_files,
 
8617
  PLUGIN_VAR_RQCMDARG | PLUGIN_VAR_READONLY,
 
8618
  "How many files at the maximum InnoDB keeps open at the same time.",
 
8619
  NULL, NULL, 300L, 10L, LONG_MAX, 0);
 
8620
 
 
8621
static DRIZZLE_SYSVAR_ULONG(sync_spin_loops, srv_n_spin_wait_rounds,
 
8622
  PLUGIN_VAR_RQCMDARG,
 
8623
  "Count of spin-loop rounds in InnoDB mutexes (30 by default)",
 
8624
  NULL, NULL, 30L, 0L, ~0L, 0);
 
8625
 
 
8626
static DRIZZLE_SYSVAR_ULONG(spin_wait_delay, srv_spin_wait_delay,
 
8627
  PLUGIN_VAR_OPCMDARG,
 
8628
  "Maximum delay between polling for a spin lock (6 by default)",
 
8629
  NULL, NULL, 6L, 0L, ~0L, 0);
 
8630
 
 
8631
static DRIZZLE_SYSVAR_ULONG(thread_concurrency, srv_thread_concurrency,
 
8632
  PLUGIN_VAR_RQCMDARG,
 
8633
  "Helps in performance tuning in heavily concurrent environments. Sets the maximum number of threads allowed inside InnoDB. Value 0 will disable the thread throttling.",
 
8634
  NULL, NULL, 0, 0, 1000, 0);
 
8635
 
 
8636
static DRIZZLE_SYSVAR_ULONG(thread_sleep_delay, srv_thread_sleep_delay,
 
8637
  PLUGIN_VAR_RQCMDARG,
 
8638
  "Time of innodb thread sleeping before joining InnoDB queue (usec). Value 0 disable a sleep",
 
8639
  NULL, NULL, 10000L, 0L, ~0L, 0);
 
8640
 
 
8641
static DRIZZLE_SYSVAR_STR(data_file_path, innobase_data_file_path,
 
8642
  PLUGIN_VAR_RQCMDARG | PLUGIN_VAR_READONLY,
 
8643
  "Path to individual files and their sizes.",
 
8644
  NULL, NULL, NULL);
 
8645
 
 
8646
static DRIZZLE_SYSVAR_LONG(autoinc_lock_mode, innobase_autoinc_lock_mode,
 
8647
  PLUGIN_VAR_RQCMDARG | PLUGIN_VAR_READONLY,
 
8648
  "The AUTOINC lock modes supported by InnoDB:               "
 
8649
  "0 => Old style AUTOINC locking (for backward"
 
8650
  " compatibility)                                           "
 
8651
  "1 => New style AUTOINC locking                            "
 
8652
  "2 => No AUTOINC locking (unsafe for SBR)",
 
8653
  NULL, NULL,
 
8654
  AUTOINC_NO_LOCKING, /* Default setting */
 
8655
  AUTOINC_OLD_STYLE_LOCKING,  /* Minimum value */
 
8656
  AUTOINC_NO_LOCKING, 0); /* Maximum value */
 
8657
 
 
8658
static DRIZZLE_SYSVAR_STR(version, innodb_version_str,
 
8659
  PLUGIN_VAR_NOCMDOPT | PLUGIN_VAR_READONLY,
 
8660
  "InnoDB version", NULL, NULL, INNODB_VERSION_STR);
 
8661
 
 
8662
static DRIZZLE_SYSVAR_BOOL(use_sys_malloc, srv_use_sys_malloc,
 
8663
  PLUGIN_VAR_NOCMDARG | PLUGIN_VAR_READONLY,
 
8664
  "Use OS memory allocator instead of InnoDB's internal memory allocator",
 
8665
  NULL, NULL, TRUE);
 
8666
 
 
8667
static DRIZZLE_SYSVAR_STR(change_buffering, innobase_change_buffering,
 
8668
  PLUGIN_VAR_RQCMDARG,
 
8669
  "Buffer changes to reduce random access: "
 
8670
  "OFF, ON, inserting, deleting, changing, or purging.",
 
8671
  innodb_change_buffering_validate,
 
8672
  innodb_change_buffering_update, NULL);
 
8673
 
 
8674
static DRIZZLE_SYSVAR_ULONG(read_ahead_threshold, srv_read_ahead_threshold,
 
8675
  PLUGIN_VAR_RQCMDARG,
 
8676
  "Number of pages that must be accessed sequentially for InnoDB to"
 
8677
  "trigger a readahead.",
 
8678
  NULL, NULL, 56, 0, 64, 0);
 
8679
 
 
8680
static drizzle_sys_var* innobase_system_variables[]= {
 
8681
  DRIZZLE_SYSVAR(additional_mem_pool_size),
 
8682
  DRIZZLE_SYSVAR(autoextend_increment),
 
8683
  DRIZZLE_SYSVAR(buffer_pool_size),
 
8684
  DRIZZLE_SYSVAR(checksums),
 
8685
  DRIZZLE_SYSVAR(commit_concurrency),
 
8686
  DRIZZLE_SYSVAR(concurrency_tickets),
 
8687
  DRIZZLE_SYSVAR(data_file_path),
 
8688
  DRIZZLE_SYSVAR(data_home_dir),
 
8689
  DRIZZLE_SYSVAR(doublewrite),
 
8690
  DRIZZLE_SYSVAR(fast_shutdown),
 
8691
  DRIZZLE_SYSVAR(file_io_threads),
 
8692
  DRIZZLE_SYSVAR(read_io_threads),
 
8693
  DRIZZLE_SYSVAR(write_io_threads),
 
8694
  DRIZZLE_SYSVAR(file_per_table),
 
8695
  DRIZZLE_SYSVAR(file_format),
 
8696
  DRIZZLE_SYSVAR(file_format_check),
 
8697
  DRIZZLE_SYSVAR(flush_log_at_trx_commit),
 
8698
  DRIZZLE_SYSVAR(flush_method),
 
8699
  DRIZZLE_SYSVAR(force_recovery),
 
8700
  DRIZZLE_SYSVAR(lock_wait_timeout),
 
8701
#ifdef UNIV_LOG_ARCHIVE
 
8702
  DRIZZLE_SYSVAR(log_arch_dir),
 
8703
  DRIZZLE_SYSVAR(log_archive),
 
8704
#endif /* UNIV_LOG_ARCHIVE */
 
8705
  DRIZZLE_SYSVAR(log_buffer_size),
 
8706
  DRIZZLE_SYSVAR(log_file_size),
 
8707
  DRIZZLE_SYSVAR(log_files_in_group),
 
8708
  DRIZZLE_SYSVAR(log_group_home_dir),
 
8709
  DRIZZLE_SYSVAR(max_dirty_pages_pct),
 
8710
  DRIZZLE_SYSVAR(max_purge_lag),
 
8711
  DRIZZLE_SYSVAR(adaptive_flushing),
 
8712
  DRIZZLE_SYSVAR(mirrored_log_groups),
 
8713
  DRIZZLE_SYSVAR(open_files),
 
8714
  DRIZZLE_SYSVAR(rollback_on_timeout),
 
8715
  DRIZZLE_SYSVAR(stats_on_metadata),
 
8716
  DRIZZLE_SYSVAR(stats_sample_pages),
 
8717
  DRIZZLE_SYSVAR(adaptive_hash_index),
 
8718
  DRIZZLE_SYSVAR(replication_delay),
 
8719
  DRIZZLE_SYSVAR(status_file),
 
8720
  DRIZZLE_SYSVAR(strict_mode),
 
8721
  DRIZZLE_SYSVAR(support_xa),
 
8722
  DRIZZLE_SYSVAR(sync_spin_loops),
 
8723
  DRIZZLE_SYSVAR(spin_wait_delay),
 
8724
  DRIZZLE_SYSVAR(table_locks),
 
8725
  DRIZZLE_SYSVAR(thread_concurrency),
 
8726
  DRIZZLE_SYSVAR(thread_sleep_delay),
 
8727
  DRIZZLE_SYSVAR(autoinc_lock_mode),
 
8728
  DRIZZLE_SYSVAR(version),
 
8729
  DRIZZLE_SYSVAR(use_sys_malloc),
 
8730
  DRIZZLE_SYSVAR(change_buffering),
 
8731
  DRIZZLE_SYSVAR(read_ahead_threshold),
 
8732
  DRIZZLE_SYSVAR(io_capacity),
 
8733
  NULL
 
8734
};
9276
8735
 
9277
8736
DRIZZLE_DECLARE_PLUGIN
9278
8737
{
9283
8742
  "Supports transactions, row-level locking, and foreign keys",
9284
8743
  PLUGIN_LICENSE_GPL,
9285
8744
  innobase_init, /* Plugin Init */
9286
 
  NULL, /* depends */
9287
 
  init_options /* reserved */
 
8745
  innobase_system_variables, /* system variables */
 
8746
  NULL /* reserved */
9288
8747
}
9289
8748
DRIZZLE_DECLARE_PLUGIN_END;
9290
8749
 
9311
8770
  return res;
9312
8771
}
9313
8772
 
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. */
 
8773
/** @brief Initialize the default value of innodb_commit_concurrency.
 
8774
 
 
8775
Once InnoDB is running, the innodb_commit_concurrency must not change
 
8776
from zero to nonzero. (Bug #42101)
 
8777
 
 
8778
The initial default value is 0, and without this extra initialization,
 
8779
SET GLOBAL innodb_commit_concurrency=DEFAULT would set the parameter
 
8780
to 0, even if it was initially set to nonzero at the command line
 
8781
or configuration file. */
 
8782
static
 
8783
void
 
8784
innobase_commit_concurrency_init_default(void)
 
8785
/*==========================================*/
9328
8786
{
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);
 
8787
  DRIZZLE_SYSVAR_NAME(commit_concurrency).def_val
 
8788
    = innobase_commit_concurrency;
9355
8789
}
9356
8790
 
9357
8791
#ifdef UNIV_COMPILE_TEST_FUNCS
9361
8795
  ulint   buflen;
9362
8796
  const char* id;
9363
8797
  ulint   idlen;
9364
 
  drizzled::Session *session;
 
8798
  void*   session;
9365
8799
  ibool   file_id;
9366
8800
 
9367
8801
  const char* expected;