~drizzle-trunk/drizzle/development

« back to all changes in this revision

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

  • Committer: Olaf van der Spek
  • Date: 2011-10-24 21:23:54 UTC
  • mto: This revision was merged to the branch mainline in revision 2449.
  • Revision ID: olafvdspek@gmail.com-20111024212354-j32gbc2sbsw0985q
Use str_ref

Show diffs side-by-side

added added

removed removed

Lines of Context:
38
38
    in Windows?
39
39
*/
40
40
 
41
 
#include "config.h"
 
41
#include <config.h>
42
42
 
43
43
#include <limits.h>
44
44
#include <fcntl.h>
45
45
 
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/field/timestamp.h"
64
 
#include "drizzled/plugin/xa_storage_engine.h"
65
 
#include "drizzled/plugin/daemon.h"
66
 
#include "drizzled/memory/multi_malloc.h"
67
 
#include "drizzled/pthread_globals.h"
68
 
#include "drizzled/named_savepoint.h"
69
 
 
 
46
#include <drizzled/error.h>
 
47
#include <drizzled/errmsg_print.h>
 
48
#include <drizzled/internal/m_string.h>
 
49
#include <drizzled/internal/my_sys.h>
 
50
#include <drizzled/plugin.h>
 
51
#include <drizzled/show.h>
 
52
#include <drizzled/data_home.h>
 
53
#include <drizzled/error.h>
 
54
#include <drizzled/field.h>
 
55
#include <drizzled/charset.h>
 
56
#include <drizzled/session.h>
 
57
#include <drizzled/current_session.h>
 
58
#include <drizzled/table.h>
 
59
#include <drizzled/field/blob.h>
 
60
#include <drizzled/field/varstring.h>
 
61
#include <drizzled/plugin/xa_storage_engine.h>
 
62
#include <drizzled/plugin/daemon.h>
 
63
#include <drizzled/memory/multi_malloc.h>
 
64
#include <drizzled/pthread_globals.h>
 
65
#include <drizzled/named_savepoint.h>
 
66
#include <drizzled/session/table_messages.h>
70
67
#include <drizzled/transaction_services.h>
71
 
#include "drizzled/message/statement_transform.h"
 
68
#include <drizzled/message/statement_transform.h>
 
69
#include <drizzled/cached_directory.h>
 
70
#include <drizzled/statistics_variables.h>
 
71
#include <drizzled/system_variables.h>
 
72
#include <drizzled/session/times.h>
 
73
#include <drizzled/session/transactions.h>
 
74
#include <drizzled/typelib.h>
72
75
 
73
76
#include <boost/algorithm/string.hpp>
74
77
#include <boost/program_options.hpp>
 
78
#include <boost/scoped_array.hpp>
75
79
#include <boost/filesystem.hpp>
76
80
#include <drizzled/module/option_map.h>
77
81
#include <iostream>
83
87
/** @file ha_innodb.cc */
84
88
 
85
89
/* Include necessary InnoDB headers */
86
 
extern "C" {
87
90
#include "univ.i"
88
91
#include "buf0lru.h"
89
92
#include "btr0sea.h"
115
118
#include "ha_prototypes.h"
116
119
#include "ut0mem.h"
117
120
#include "ibuf0ibuf.h"
118
 
#include "mysql_addons.h"
119
 
}
120
121
 
121
122
#include "ha_innodb.h"
122
123
#include "data_dictionary.h"
128
129
#include <sstream>
129
130
#include <string>
130
131
 
131
 
#include "plugin/innobase/handler/status_function.h"
132
 
#include "plugin/innobase/handler/replication_log.h"
 
132
#include <plugin/innobase/handler/status_function.h>
 
133
#include <plugin/innobase/handler/replication_log.h>
133
134
 
134
135
#include <google/protobuf/io/zero_copy_stream.h>
135
136
#include <google/protobuf/io/zero_copy_stream_impl.h>
136
137
#include <google/protobuf/io/coded_stream.h>
137
138
#include <google/protobuf/text_format.h>
138
139
 
 
140
#include <boost/thread/mutex.hpp>
 
141
 
139
142
using namespace std;
140
143
using namespace drizzled;
141
144
 
142
145
/** to protect innobase_open_files */
143
 
static pthread_mutex_t innobase_share_mutex;
 
146
static boost::mutex innobase_share_mutex;
 
147
 
144
148
/** to force correct commit order in binlog */
145
 
static pthread_mutex_t prepare_commit_mutex;
146
149
static ulong commit_threads = 0;
147
 
static pthread_mutex_t commit_threads_m;
148
 
static pthread_cond_t commit_cond;
149
 
static pthread_mutex_t commit_cond_m;
 
150
static boost::condition_variable commit_cond;
 
151
static boost::mutex commit_cond_m;
150
152
static bool innodb_inited = 0;
151
153
 
152
154
#define INSIDE_HA_INNOBASE_CC
162
164
#endif /* MYSQL_DYNAMIC_PLUGIN && __WIN__ */
163
165
 
164
166
static plugin::XaStorageEngine* innodb_engine_ptr= NULL;
165
 
static plugin::TableFunction* status_table_function_ptr= NULL;
166
 
static plugin::TableFunction* cmp_tool= NULL;
167
 
static plugin::TableFunction* cmp_reset_tool= NULL;
168
 
static plugin::TableFunction* cmp_mem_tool= NULL;
169
 
static plugin::TableFunction* cmp_mem_reset_tool= NULL;
170
 
static plugin::TableFunction* innodb_trx_tool= NULL;
171
 
static plugin::TableFunction* innodb_locks_tool= NULL;
172
 
static plugin::TableFunction* innodb_lock_waits_tool= NULL;
173
 
static plugin::TableFunction* innodb_sys_tables_tool= NULL;
174
 
static plugin::TableFunction* innodb_sys_tablestats_tool= NULL;
175
 
 
176
 
static plugin::TableFunction* innodb_sys_indexes_tool= NULL;
177
 
static plugin::TableFunction* innodb_sys_columns_tool= NULL;
178
 
static plugin::TableFunction* innodb_sys_fields_tool= NULL;
179
 
static plugin::TableFunction* innodb_sys_foreign_tool= NULL;
180
 
static plugin::TableFunction* innodb_sys_foreign_cols_tool= NULL;
181
 
 
182
 
static ReplicationLog *replication_logger= NULL;
 
167
 
183
168
typedef constrained_check<uint32_t, UINT32_MAX, 10> open_files_constraint;
184
169
static open_files_constraint innobase_open_files;
185
170
typedef constrained_check<uint32_t, 10, 1> mirrored_log_groups_constraint;
194
179
static additional_mem_pool_constraint innobase_additional_mem_pool_size;
195
180
typedef constrained_check<unsigned int, 1000, 1> autoextend_constraint;
196
181
static autoextend_constraint innodb_auto_extend_increment;
197
 
typedef constrained_check<size_t, SIZE_MAX, 5242880, 1048576> buffer_pool_constraint;
 
182
typedef constrained_check<size_t, SIZE_MAX, 33554432, 1048576> buffer_pool_constraint;
198
183
static buffer_pool_constraint innobase_buffer_pool_size;
199
184
typedef constrained_check<uint32_t, MAX_BUFFER_POOLS, 1> buffer_pool_instances_constraint;
200
185
static buffer_pool_instances_constraint innobase_buffer_pool_instances;
 
186
typedef constrained_check<uint32_t,
 
187
                          (1 << UNIV_PAGE_SIZE_SHIFT_MAX),
 
188
                                (1 << 12)> page_size_constraint;
 
189
static page_size_constraint innobase_page_size;
 
190
typedef constrained_check<uint32_t,
 
191
                          (1 << UNIV_PAGE_SIZE_SHIFT_MAX),
 
192
                                (1 << 9)> log_block_size_constraint;
 
193
static log_block_size_constraint innobase_log_block_size;
201
194
typedef constrained_check<uint32_t, UINT32_MAX, 100> io_capacity_constraint;
202
195
static io_capacity_constraint innodb_io_capacity;
203
196
typedef constrained_check<uint32_t, 5000, 1> purge_batch_constraint;
204
197
static purge_batch_constraint innodb_purge_batch_size;
205
198
typedef constrained_check<uint32_t, 1, 0> purge_threads_constraint;
206
199
static purge_threads_constraint innodb_n_purge_threads;
207
 
typedef constrained_check<uint16_t, 2, 0> trinary_constraint;
 
200
typedef constrained_check<uint32_t, 2, 0> trinary_constraint;
208
201
static trinary_constraint innodb_flush_log_at_trx_commit;
209
202
typedef constrained_check<unsigned int, 99, 0> max_dirty_pages_constraint;
210
203
static max_dirty_pages_constraint innodb_max_dirty_pages_pct;
224
217
 
225
218
static uint64_constraint innodb_replication_delay;
226
219
 
 
220
static uint32_constraint buffer_pool_restore_at_startup;
 
221
 
227
222
/** Percentage of the buffer pool to reserve for 'old' blocks.
228
223
Connected to buf_LRU_old_ratio. */
229
224
typedef constrained_check<uint32_t, 95, 5> old_blocks_constraint;
236
231
typedef constrained_check<uint32_t, 64, 0> read_ahead_threshold_constraint;
237
232
static read_ahead_threshold_constraint innodb_read_ahead_threshold;
238
233
 
 
234
static uint64_constraint ibuf_max_size;
 
235
 
 
236
typedef constrained_check<uint32_t, 1, 0> binary_constraint;
 
237
static binary_constraint ibuf_active_contract;
 
238
 
 
239
typedef constrained_check<uint32_t, 999999999, 100> ibuf_accel_rate_constraint;
 
240
static ibuf_accel_rate_constraint ibuf_accel_rate;
 
241
static uint32_constraint checkpoint_age_target;
 
242
static binary_constraint flush_neighbor_pages;
 
243
 
239
244
/* The default values for the following char* start-up parameters
240
245
are determined in innobase_init below: */
241
246
 
245
250
static string innobase_file_format_name;
246
251
static string innobase_change_buffering;
247
252
 
 
253
static string read_ahead;
 
254
static string adaptive_flushing_method;
 
255
 
248
256
/* The highest file format being used in the database. The value can be
249
257
set by user, however, it will be adjusted to the newer file format if
250
258
a table of such format is created/opened. */
253
261
/* Below we have boolean-valued start-up parameters, and their default
254
262
values */
255
263
 
256
 
typedef constrained_check<uint16_t, 2, 0> trinary_constraint;
257
264
static trinary_constraint innobase_fast_shutdown;
258
265
 
259
266
/* "innobase_file_format_check" decides whether we would continue
305
312
  "all"         /* IBUF_USE_ALL */
306
313
};
307
314
 
 
315
/** Allowed values of read_ahead */
 
316
static const char* read_ahead_names[] = {
 
317
  "none",       /* 0 */
 
318
  "random",
 
319
  "linear",
 
320
  "both",       /* 3 */
 
321
  /* For compatibility with the older Percona patch */
 
322
  "0",          /* 4 ("none" + 4) */
 
323
  "1",
 
324
  "2",
 
325
  "3",          /* 7 ("both" + 4) */
 
326
  NULL
 
327
};
 
328
 
 
329
static TYPELIB read_ahead_typelib = {
 
330
  array_elements(read_ahead_names) - 1, "read_ahead_typelib",
 
331
  read_ahead_names, NULL
 
332
};
 
333
 
 
334
/** Allowed values of adaptive_flushing_method */
 
335
static const char* adaptive_flushing_method_names[] = {
 
336
    "native",           /* 0 */
 
337
    "estimate",         /* 1 */
 
338
    "keep_average",     /* 2 */
 
339
    /* For compatibility with the older Percona patch */
 
340
    "0",                /* 3 ("native" + 3) */
 
341
    "1",                /* 4 ("estimate" + 3) */
 
342
    "2",                /* 5 ("keep_average" + 3) */
 
343
    NULL
 
344
};
 
345
 
 
346
static TYPELIB adaptive_flushing_method_typelib = {
 
347
  array_elements(adaptive_flushing_method_names) - 1,
 
348
  "adaptive_flushing_method_typelib",
 
349
  adaptive_flushing_method_names, NULL
 
350
};
 
351
 
308
352
/* "GEN_CLUST_INDEX" is the name reserved for Innodb default
309
353
system primary index. */
310
354
static const char innobase_index_reserve_name[]= "GEN_CLUST_INDEX";
340
384
 
341
385
  virtual ~InnobaseEngine()
342
386
  {
343
 
    int err= 0;
344
387
    if (innodb_inited) {
345
388
      srv_fast_shutdown = (ulint) innobase_fast_shutdown;
346
389
      innodb_inited = 0;
347
390
      hash_table_free(innobase_open_tables);
348
391
      innobase_open_tables = NULL;
349
392
      if (innobase_shutdown_for_mysql() != DB_SUCCESS) {
350
 
        err = 1;
 
393
        // Throw here?
351
394
      }
352
395
      srv_free_paths_and_sizes();
353
 
      if (internal_innobase_data_file_path)
354
 
        free(internal_innobase_data_file_path);
355
 
      pthread_mutex_destroy(&innobase_share_mutex);
356
 
      pthread_mutex_destroy(&prepare_commit_mutex);
357
 
      pthread_mutex_destroy(&commit_threads_m);
358
 
      pthread_mutex_destroy(&commit_cond_m);
359
 
      pthread_cond_destroy(&commit_cond);
 
396
      free(internal_innobase_data_file_path);
360
397
    }
361
398
    
362
399
    /* These get strdup'd from vm variables */
446
483
  doDropSchema(
447
484
  /*===================*/
448
485
        /* out: error number */
449
 
    const SchemaIdentifier  &identifier); /* in: database path; inside InnoDB the name
 
486
    const identifier::Schema  &identifier); /* in: database path; inside InnoDB the name
450
487
        of the last directory in the path is used as
451
488
        the database name: for example, in 'mysql/data/test'
452
489
        the database name is 'test' */
485
522
 
486
523
  UNIV_INTERN int doCreateTable(Session &session,
487
524
                                Table &form,
488
 
                                const TableIdentifier &identifier,
489
 
                                message::Table&);
490
 
  UNIV_INTERN int doRenameTable(Session&, const TableIdentifier &from, const TableIdentifier &to);
491
 
  UNIV_INTERN int doDropTable(Session &session, const TableIdentifier &identifier);
 
525
                                const identifier::Table &identifier,
 
526
                                const message::Table&);
 
527
  UNIV_INTERN int doRenameTable(Session&, const identifier::Table &from, const identifier::Table &to);
 
528
  UNIV_INTERN int doDropTable(Session &session, const identifier::Table &identifier);
492
529
 
493
 
  UNIV_INTERN virtual bool get_error_message(int error, String *buf);
 
530
  UNIV_INTERN virtual bool get_error_message(int error, String *buf) const;
494
531
 
495
532
  UNIV_INTERN uint32_t max_supported_keys() const;
496
533
  UNIV_INTERN uint32_t max_supported_key_length() const;
507
544
  }
508
545
 
509
546
  int doGetTableDefinition(drizzled::Session& session,
510
 
                           const TableIdentifier &identifier,
 
547
                           const identifier::Table &identifier,
511
548
                           drizzled::message::Table &table_proto);
512
549
 
513
 
  bool doDoesTableExist(drizzled::Session& session, const TableIdentifier &identifier);
 
550
  bool doDoesTableExist(drizzled::Session& session, const identifier::Table &identifier);
514
551
 
515
552
  void doGetTableIdentifiers(drizzled::CachedDirectory &directory,
516
 
                             const drizzled::SchemaIdentifier &schema_identifier,
517
 
                             drizzled::TableIdentifier::vector &set_of_identifiers);
 
553
                             const drizzled::identifier::Schema &schema_identifier,
 
554
                             drizzled::identifier::table::vector &set_of_identifiers);
518
555
  bool validateCreateTableOption(const std::string &key, const std::string &state);
519
556
  void dropTemporarySchema();
520
557
 
542
579
}
543
580
 
544
581
void InnobaseEngine::doGetTableIdentifiers(drizzled::CachedDirectory &directory,
545
 
                                           const drizzled::SchemaIdentifier &schema_identifier,
546
 
                                           drizzled::TableIdentifier::vector &set_of_identifiers)
 
582
                                           const drizzled::identifier::Schema &schema_identifier,
 
583
                                           drizzled::identifier::table::vector &set_of_identifiers)
547
584
{
548
585
  CachedDirectory::Entries entries= directory.getEntries();
549
586
 
 
587
  std::string search_string(schema_identifier.getSchemaName());
 
588
 
 
589
  boost::algorithm::to_lower(search_string);
 
590
 
 
591
  if (search_string.compare("data_dictionary") == 0)
 
592
  {
 
593
    set_of_identifiers.push_back(identifier::Table(schema_identifier.getSchemaName(), "SYS_REPLICATION_LOG"));
 
594
  }
 
595
 
550
596
  for (CachedDirectory::Entries::iterator entry_iter= entries.begin(); 
551
597
       entry_iter != entries.end(); ++entry_iter)
552
598
  {
574
620
           Using schema_identifier here to stop unused warning, could use
575
621
           definition.schema() instead
576
622
        */
577
 
        TableIdentifier identifier(schema_identifier.getSchemaName(), definition.name());
 
623
        identifier::Table identifier(schema_identifier.getSchemaName(), definition.name());
578
624
        set_of_identifiers.push_back(identifier);
579
625
      }
580
626
    }
581
627
  }
582
628
}
583
629
 
584
 
bool InnobaseEngine::doDoesTableExist(Session &session, const TableIdentifier &identifier)
 
630
bool InnobaseEngine::doDoesTableExist(Session &session, const identifier::Table &identifier)
585
631
{
586
632
  string proto_path(identifier.getPath());
587
633
  proto_path.append(DEFAULT_FILE_EXTENSION);
589
635
  if (session.getMessageCache().doesTableMessageExist(identifier))
590
636
    return true;
591
637
 
 
638
  std::string search_string(identifier.getPath());
 
639
  boost::algorithm::to_lower(search_string);
 
640
 
 
641
  if (search_string.compare("data_dictionary/sys_replication_log") == 0)
 
642
    return true;
 
643
 
592
644
  if (access(proto_path.c_str(), F_OK))
593
645
  {
594
646
    return false;
598
650
}
599
651
 
600
652
int InnobaseEngine::doGetTableDefinition(Session &session,
601
 
                                         const TableIdentifier &identifier,
 
653
                                         const identifier::Table &identifier,
602
654
                                         message::Table &table_proto)
603
655
{
604
656
  string proto_path(identifier.getPath());
608
660
  if (session.getMessageCache().getTableMessage(identifier, table_proto))
609
661
    return EEXIST;
610
662
 
 
663
  if (read_replication_log_table_message(identifier.getTableName().c_str(), &table_proto) == 0)
 
664
    return EEXIST;
 
665
 
611
666
  if (access(proto_path.c_str(), F_OK))
612
667
  {
613
668
    return errno;
804
859
DRIZZLE: Note, we didn't change this name to avoid more ifdef forking 
805
860
         in non-Cursor code.
806
861
@return true if session is the replication thread */
807
 
extern "C" UNIV_INTERN
 
862
UNIV_INTERN
808
863
ibool
809
864
thd_is_replication_slave_thread(
810
865
/*============================*/
811
 
  void* ) /*!< in: thread handle (Session*) */
 
866
  drizzled::Session* ) /*!< in: thread handle (Session*) */
812
867
{
813
868
  return false;
814
869
}
878
933
DRIZZLE: Note, we didn't change this name to avoid more ifdef forking 
879
934
         in non-Cursor code.
880
935
@return true if non-transactional tables have been edited */
881
 
extern "C" UNIV_INTERN
 
936
UNIV_INTERN
882
937
ibool
883
938
thd_has_edited_nontrans_tables(
884
939
/*===========================*/
885
 
  void*   session)  /*!< in: thread handle (Session*) */
 
940
  drizzled::Session *session)  /*!< in: thread handle (Session*) */
886
941
{
887
 
  return((ibool)((Session *)session)->transaction.all.hasModifiedNonTransData());
 
942
  return((ibool)session->transaction.all.hasModifiedNonTransData());
888
943
}
889
944
 
890
945
/******************************************************************//**
891
946
Returns true if the thread is executing a SELECT statement.
892
947
@return true if session is executing SELECT */
893
 
extern "C" UNIV_INTERN
 
948
UNIV_INTERN
894
949
ibool
895
950
thd_is_select(
896
951
/*==========*/
897
 
  const void* session)  /*!< in: thread handle (Session*) */
 
952
  const drizzled::Session *session)  /*!< in: thread handle (Session*) */
898
953
{
899
 
  return(session_sql_command((const Session*) session) == SQLCOM_SELECT);
 
954
  return(session->getSqlCommand() == SQLCOM_SELECT);
900
955
}
901
956
 
902
957
/******************************************************************//**
903
958
Returns true if the thread supports XA,
904
959
global value of innodb_supports_xa if session is NULL.
905
960
@return true if session has XA support */
906
 
extern "C" UNIV_INTERN
 
961
UNIV_INTERN
907
962
ibool
908
963
thd_supports_xa(
909
964
/*============*/
910
 
  void* )  /*!< in: thread handle (Session*), or NULL to query
 
965
  drizzled::Session* )  /*!< in: thread handle (Session*), or NULL to query
911
966
        the global innodb_supports_xa */
912
967
{
913
968
  /* TODO: Add support here for per-session value */
917
972
/******************************************************************//**
918
973
Returns the lock wait timeout for the current connection.
919
974
@return the lock wait timeout, in seconds */
920
 
extern "C" UNIV_INTERN
 
975
UNIV_INTERN
921
976
ulong
922
977
thd_lock_wait_timeout(
923
978
/*==================*/
924
 
  void*)  /*!< in: thread handle (Session*), or NULL to query
 
979
  drizzled::Session*)  /*!< in: thread handle (Session*), or NULL to query
925
980
      the global innodb_lock_wait_timeout */
926
981
{
927
982
  /* TODO: Add support here for per-session value */
932
987
 
933
988
/******************************************************************//**
934
989
Set the time waited for the lock for the current query. */
935
 
extern "C" UNIV_INTERN
 
990
UNIV_INTERN
936
991
void
937
992
thd_set_lock_wait_time(
938
993
/*===================*/
939
 
        void*   thd,    /*!< in: thread handle (THD*) */
 
994
        drizzled::Session*      in_session,     /*!< in: thread handle (THD*) */
940
995
        ulint   value)  /*!< in: time waited for the lock */
941
996
{
942
 
        if (thd) {
943
 
          static_cast<Session*>(thd)->utime_after_lock+= value;
944
 
        }
 
997
  if (in_session)
 
998
    in_session->times.utime_after_lock+= value;
945
999
}
946
1000
 
947
1001
/********************************************************************//**
967
1021
  trx_t *trx= session_to_trx(&session);
968
1022
 
969
1023
  uint64_t trx_id= message.transaction_context().transaction_id();
970
 
  ulint error= insert_replication_message(data, message.ByteSize(), trx, trx_id);
 
1024
  uint32_t seg_id= message.segment_id();
 
1025
  uint64_t end_timestamp= message.transaction_context().end_timestamp();
 
1026
  bool is_end_segment= message.end_segment();
 
1027
  trx->log_commit_id= TRUE;
 
1028
 
 
1029
  string server_uuid= session.getServerUUID();
 
1030
  string originating_server_uuid= session.getOriginatingServerUUID();
 
1031
  uint64_t originating_commit_id= session.getOriginatingCommitID();
 
1032
  bool use_originating_server_uuid= session.isOriginatingServerUUIDSet();
 
1033
 
 
1034
  ulint error= insert_replication_message(data, message.ByteSize(), trx, trx_id,
 
1035
               end_timestamp, is_end_segment, seg_id, server_uuid.c_str(),
 
1036
               use_originating_server_uuid, originating_server_uuid.c_str(),
 
1037
               originating_commit_id);
 
1038
 
971
1039
  (void)error;
972
1040
 
973
1041
  delete[] data;
1024
1092
about a possible transaction rollback inside InnoDB caused by a lock wait
1025
1093
timeout or a deadlock.
1026
1094
@return MySQL error code */
1027
 
extern "C" UNIV_INTERN
 
1095
UNIV_INTERN
1028
1096
int
1029
1097
convert_error_code_to_mysql(
1030
1098
/*========================*/
1078
1146
    tell it also to MySQL so that MySQL knows to empty the
1079
1147
    cached binlog for this transaction */
1080
1148
 
1081
 
    mark_transaction_to_rollback(session, TRUE);
 
1149
    session->markTransactionForRollback(TRUE);
1082
1150
 
1083
1151
    return(HA_ERR_LOCK_DEADLOCK);
1084
1152
 
1087
1155
    latest SQL statement in a lock wait timeout. Previously, we
1088
1156
    rolled back the whole transaction. */
1089
1157
 
1090
 
    mark_transaction_to_rollback(session, (bool)row_rollback_on_timeout);
 
1158
    session->markTransactionForRollback((bool)row_rollback_on_timeout);
1091
1159
 
1092
1160
    return(HA_ERR_LOCK_WAIT_TIMEOUT);
1093
1161
 
1098
1166
    return(HA_ERR_ROW_IS_REFERENCED);
1099
1167
 
1100
1168
  case DB_CANNOT_ADD_CONSTRAINT:
 
1169
  case DB_CHILD_NO_INDEX:
 
1170
  case DB_PARENT_NO_INDEX:
1101
1171
    return(HA_ERR_CANNOT_ADD_FOREIGN);
1102
1172
 
1103
1173
  case DB_CANNOT_DROP_CONSTRAINT:
1121
1191
 
1122
1192
  case DB_TOO_BIG_RECORD:
1123
1193
    my_error(ER_TOO_BIG_ROWSIZE, MYF(0),
1124
 
       page_get_free_space_of_empty(flags
1125
 
                  & DICT_TF_COMPACT) / 2);
 
1194
             page_get_free_space_of_empty(flags & DICT_TF_COMPACT) / 2);
1126
1195
    return(HA_ERR_TO_BIG_ROW);
1127
1196
 
1128
1197
  case DB_NO_SAVEPOINT:
1133
1202
    tell it also to MySQL so that MySQL knows to empty the
1134
1203
    cached binlog for this transaction */
1135
1204
 
1136
 
    mark_transaction_to_rollback(session, TRUE);
 
1205
    session->markTransactionForRollback(TRUE);
1137
1206
 
1138
1207
    return(HA_ERR_LOCK_TABLE_FULL);
1139
1208
 
1167
1236
 
1168
1237
/*************************************************************//**
1169
1238
Prints info of a Session object (== user session thread) to the given file. */
1170
 
extern "C" UNIV_INTERN
 
1239
UNIV_INTERN
1171
1240
void
1172
1241
innobase_mysql_print_thd(
1173
1242
/*=====================*/
1174
1243
  FILE* f,    /*!< in: output stream */
1175
 
  void * in_session,  /*!< in: pointer to a Drizzle Session object */
 
1244
  drizzled::Session *in_session,  /*!< in: pointer to a Drizzle Session object */
1176
1245
  uint  )   /*!< in: max query length to print, or 0 to
1177
1246
           use the default max length */
1178
1247
{
1179
 
  Session *session= reinterpret_cast<Session *>(in_session);
1180
 
  drizzled::identifier::User::const_shared_ptr user_identifier(session->user());
 
1248
  drizzled::identifier::user::ptr user_identifier(in_session->user());
1181
1249
 
1182
1250
  fprintf(f,
1183
1251
          "Drizzle thread %"PRIu64", query id %"PRIu64", %s, %s, %s ",
1184
 
          static_cast<uint64_t>(session->getSessionId()),
1185
 
          static_cast<uint64_t>(session->getQueryId()),
1186
 
          glob_hostname,
 
1252
          static_cast<uint64_t>(in_session->getSessionId()),
 
1253
          static_cast<uint64_t>(in_session->getQueryId()),
 
1254
          getServerHostname().c_str(),
1187
1255
          user_identifier->address().c_str(),
1188
1256
          user_identifier->username().c_str()
1189
1257
  );
1190
 
  fprintf(f, "\n%s", session->getQueryString()->c_str());
 
1258
  fprintf(f, "\n%s", in_session->getQueryString()->c_str());
1191
1259
  putc('\n', f);
1192
1260
}
1193
1261
 
1194
1262
/******************************************************************//**
1195
1263
Get the variable length bounds of the given character set. */
1196
 
extern "C" UNIV_INTERN
 
1264
UNIV_INTERN
1197
1265
void
1198
1266
innobase_get_cset_width(
1199
1267
/*====================*/
1201
1269
  ulint*  mbminlen, /*!< out: minimum length of a char (in bytes) */
1202
1270
  ulint*  mbmaxlen) /*!< out: maximum length of a char (in bytes) */
1203
1271
{
1204
 
  CHARSET_INFO* cs;
 
1272
  charset_info_st* cs;
1205
1273
  ut_ad(cset < 256);
1206
1274
  ut_ad(mbminlen);
1207
1275
  ut_ad(mbmaxlen);
1220
1288
 
1221
1289
/******************************************************************//**
1222
1290
Converts an identifier to a table name. */
1223
 
extern "C" UNIV_INTERN
 
1291
UNIV_INTERN
1224
1292
void
1225
1293
innobase_convert_from_table_id(
1226
1294
/*===========================*/
1234
1302
 
1235
1303
/******************************************************************//**
1236
1304
Converts an identifier to UTF-8. */
1237
 
extern "C" UNIV_INTERN
 
1305
UNIV_INTERN
1238
1306
void
1239
1307
innobase_convert_from_id(
1240
1308
/*=====================*/
1249
1317
/******************************************************************//**
1250
1318
Compares NUL-terminated UTF-8 strings case insensitively.
1251
1319
@return 0 if a=b, <0 if a<b, >1 if a>b */
1252
 
extern "C" UNIV_INTERN
 
1320
UNIV_INTERN
1253
1321
int
1254
1322
innobase_strcasecmp(
1255
1323
/*================*/
1261
1329
 
1262
1330
/******************************************************************//**
1263
1331
Makes all characters in a NUL-terminated UTF-8 string lower case. */
1264
 
extern "C" UNIV_INTERN
 
1332
UNIV_INTERN
1265
1333
void
1266
1334
innobase_casedn_str(
1267
1335
/*================*/
1270
1338
  my_casedn_str(system_charset_info, a);
1271
1339
}
1272
1340
 
1273
 
/**********************************************************************//**
1274
 
Determines the connection character set.
1275
 
@return connection character set */
1276
 
extern "C" UNIV_INTERN
1277
 
const void*
1278
 
innobase_get_charset(
1279
 
/*=================*/
1280
 
  void* mysql_session)  /*!< in: MySQL thread handle */
1281
 
{
1282
 
  return static_cast<Session*>(mysql_session)->charset();
1283
 
}
1284
 
 
1285
 
extern "C" UNIV_INTERN
 
1341
UNIV_INTERN
1286
1342
bool
1287
1343
innobase_isspace(
1288
 
  const void *cs,
 
1344
  const void* cs,
1289
1345
  char char_to_test)
1290
1346
{
1291
 
  return my_isspace(static_cast<const CHARSET_INFO *>(cs), char_to_test);
1292
 
}
1293
 
 
1294
 
UNIV_INTERN
1295
 
int
1296
 
innobase_fast_mutex_init(
1297
 
        os_fast_mutex_t*        fast_mutex)
1298
 
{
1299
 
  return pthread_mutex_init(fast_mutex, MY_MUTEX_INIT_FAST);
1300
 
}
1301
 
 
1302
 
/**********************************************************************//**
1303
 
Determines the current SQL statement.
1304
 
@return        SQL statement string */
1305
 
extern "C" UNIV_INTERN
1306
 
const char*
1307
 
innobase_get_stmt(
1308
 
/*==============*/
1309
 
       void*   session,        /*!< in: MySQL thread handle */
1310
 
       size_t* length)         /*!< out: length of the SQL statement */
1311
 
{
1312
 
  return static_cast<Session*>(session)->getQueryStringCopy(*length);
 
1347
  return static_cast<const charset_info_st*>(cs)->isspace(char_to_test);
1313
1348
}
1314
1349
 
1315
1350
#if defined (__WIN__) && defined (MYSQL_DYNAMIC_PLUGIN)
1316
1351
/*******************************************************************//**
1317
1352
Map an OS error to an errno value. The OS error number is stored in
1318
1353
_doserrno and the mapped value is stored in errno) */
1319
 
extern "C"
1320
1354
void __cdecl
1321
1355
_dosmaperr(
1322
1356
  unsigned long); /*!< in: OS error value */
1324
1358
/*********************************************************************//**
1325
1359
Creates a temporary file.
1326
1360
@return temporary file descriptor, or < 0 on error */
1327
 
extern "C" UNIV_INTERN
 
1361
UNIV_INTERN
1328
1362
int
1329
1363
innobase_mysql_tmpfile(void)
1330
1364
/*========================*/
1404
1438
/*********************************************************************//**
1405
1439
Creates a temporary file.
1406
1440
@return temporary file descriptor, or < 0 on error */
1407
 
extern "C" UNIV_INTERN
 
1441
UNIV_INTERN
1408
1442
int
1409
1443
innobase_mysql_tmpfile(void)
1410
1444
/*========================*/
1411
1445
{
1412
1446
  int fd2 = -1;
1413
 
  int fd = mysql_tmpfile("ib");
 
1447
  int fd = ::drizzled::tmpfile("ib");
1414
1448
  if (fd >= 0) {
1415
1449
    /* Copy the file descriptor, so that the additional resources
1416
1450
    allocated by create_temp_file() can be freed by invoking
1443
1477
number of bytes that were written to "buf" is returned (including the
1444
1478
terminating NUL).
1445
1479
@return number of bytes that were written */
1446
 
extern "C" UNIV_INTERN
 
1480
UNIV_INTERN
1447
1481
ulint
1448
1482
innobase_raw_format(
1449
1483
/*================*/
1563
1597
/*********************************************************************//**
1564
1598
Allocates an InnoDB transaction for a MySQL Cursor object.
1565
1599
@return InnoDB transaction handle */
1566
 
extern "C" UNIV_INTERN
 
1600
UNIV_INTERN
1567
1601
trx_t*
1568
1602
innobase_trx_allocate(
1569
1603
/*==================*/
1667
1701
  ulint   buflen, /*!< in: length of buf, in bytes */
1668
1702
  const char* id, /*!< in: identifier to convert */
1669
1703
  ulint   idlen,  /*!< in: length of id, in bytes */
1670
 
  void*   session,/*!< in: MySQL connection thread, or NULL */
 
1704
  drizzled::Session *session,/*!< in: MySQL connection thread, or NULL */
1671
1705
  ibool   file_id)/*!< in: TRUE=id is a table or database name;
1672
1706
        FALSE=id is an UTF-8 string */
1673
1707
{
1674
1708
  char nz[NAME_LEN + 1];
1675
 
  char nz2[NAME_LEN + 1 + sizeof srv_mysql50_table_name_prefix];
 
1709
  const size_t nz2_size= NAME_LEN + 1 + srv_mysql50_table_name_prefix.size();
 
1710
  boost::scoped_array<char> nz2(new char[nz2_size]);
1676
1711
 
1677
1712
  const char* s = id;
1678
1713
  int   q;
1689
1724
    memcpy(nz, id, idlen);
1690
1725
    nz[idlen] = 0;
1691
1726
 
1692
 
    s = nz2;
1693
 
    idlen = TableIdentifier::filename_to_tablename(nz, nz2, sizeof nz2);
 
1727
    s = nz2.get();
 
1728
    idlen = identifier::Table::filename_to_tablename(nz, nz2.get(), nz2_size);
1694
1729
  }
1695
1730
 
1696
1731
  /* See if the identifier needs to be quoted. */
1744
1779
Convert a table or index name to the MySQL system_charset_info (UTF-8)
1745
1780
and quote it if needed.
1746
1781
@return pointer to the end of buf */
1747
 
extern "C" UNIV_INTERN
 
1782
UNIV_INTERN
1748
1783
char*
1749
1784
innobase_convert_name(
1750
1785
/*==================*/
1752
1787
  ulint   buflen, /*!< in: length of buf, in bytes */
1753
1788
  const char* id, /*!< in: identifier to convert */
1754
1789
  ulint   idlen,  /*!< in: length of id, in bytes */
1755
 
  void*   session,/*!< in: MySQL connection thread, or NULL */
 
1790
  drizzled::Session *session,/*!< in: MySQL connection thread, or NULL */
1756
1791
  ibool   table_id)/*!< in: TRUE=id is a table or database name;
1757
1792
        FALSE=id is an index name */
1758
1793
{
1800
1835
/**********************************************************************//**
1801
1836
Determines if the currently running transaction has been interrupted.
1802
1837
@return TRUE if interrupted */
1803
 
extern "C" UNIV_INTERN
 
1838
UNIV_INTERN
1804
1839
ibool
1805
1840
trx_is_interrupted(
1806
1841
/*===============*/
1807
1842
  trx_t*  trx)  /*!< in: transaction */
1808
1843
{
1809
 
  return(trx && trx->mysql_thd && static_cast<Session*>(trx->mysql_thd)->getKilled());
 
1844
  return(trx && trx->mysql_thd && trx->mysql_thd->getKilled());
1810
1845
}
1811
1846
 
1812
1847
/**********************************************************************//**
1813
1848
Determines if the currently running transaction is in strict mode.
1814
1849
@return TRUE if strict */
1815
 
extern "C" UNIV_INTERN
 
1850
UNIV_INTERN
1816
1851
ibool
1817
1852
trx_is_strict(
1818
1853
/*==========*/
1901
1936
  srv_read_ahead_threshold= innodb_read_ahead_threshold.get();
1902
1937
}
1903
1938
 
 
1939
static void auto_lru_dump_update(Session *, sql_var_t)
 
1940
{
 
1941
  srv_auto_lru_dump= buffer_pool_restore_at_startup.get();
 
1942
}
 
1943
 
 
1944
static void ibuf_active_contract_update(Session *, sql_var_t)
 
1945
{
 
1946
  srv_ibuf_active_contract= ibuf_active_contract.get();
 
1947
}
 
1948
 
 
1949
static void ibuf_accel_rate_update(Session *, sql_var_t)
 
1950
{
 
1951
  srv_ibuf_accel_rate= ibuf_accel_rate.get();
 
1952
}
 
1953
 
 
1954
static void checkpoint_age_target_update(Session *, sql_var_t)
 
1955
{
 
1956
  srv_checkpoint_age_target= checkpoint_age_target.get();
 
1957
}
 
1958
 
 
1959
static void flush_neighbor_pages_update(Session *, sql_var_t)
 
1960
{
 
1961
  srv_flush_neighbor_pages= flush_neighbor_pages.get();
 
1962
}
1904
1963
 
1905
1964
static int innodb_commit_concurrency_validate(Session *session, set_var *var)
1906
1965
{
1907
 
   uint32_t new_value= var->save_result.uint32_t_value;
 
1966
   uint64_t new_value= var->getInteger();
1908
1967
 
1909
1968
   if ((innobase_commit_concurrency.get() == 0 && new_value != 0) ||
1910
1969
       (innobase_commit_concurrency.get() != 0 && new_value == 0))
2008
2067
    }
2009
2068
 
2010
2069
    if (format_id >= 0) {
2011
 
      innobase_file_format_max= 
2012
 
        trx_sys_file_format_id_to_name((uint)format_id);
 
2070
      innobase_file_format_max.assign(
 
2071
                             trx_sys_file_format_id_to_name((uint)format_id));
2013
2072
 
2014
2073
      /* Update the max format id in the system tablespace. */
2015
 
      char name_buff[100];
2016
 
      strcpy(name_buff, innobase_file_format_max.c_str());
2017
 
      if (trx_sys_file_format_max_set(format_id, (const char **)&name_buff))
 
2074
      const char *name_buff;
 
2075
 
 
2076
      if (trx_sys_file_format_max_set(format_id, &name_buff))
2018
2077
      {
2019
 
        errmsg_printf(ERRMSG_LVL_WARN,
 
2078
        errmsg_printf(error::WARN,
2020
2079
                      " [Info] InnoDB: the file format in the system "
2021
2080
                      "tablespace is now set to %s.\n", name_buff);
2022
2081
        innobase_file_format_max= name_buff;
2038
2097
  return(1);
2039
2098
}
2040
2099
 
 
2100
/*********************************************************************//**
 
2101
Check if argument is a valid value for srv_read_ahead and set it.  This
 
2102
function is registered as a callback with MySQL.
 
2103
@return 0 for valid read_ahead value */
 
2104
static
 
2105
int
 
2106
read_ahead_validate(
 
2107
/*================*/
 
2108
  Session*,             /*!< in: thread handle */
 
2109
  set_var*    var)
 
2110
{
 
2111
  const char *read_ahead_input = var->value->str_value.ptr();
 
2112
  int res = read_ahead_typelib.find_type(read_ahead_input, TYPELIB::e_none); // e_none is wrong
 
2113
 
 
2114
  if (res > 0) {
 
2115
    srv_read_ahead = res - 1;
 
2116
    return 0;
 
2117
  }
 
2118
 
 
2119
  return 1;
 
2120
}
 
2121
 
 
2122
/*********************************************************************//**
 
2123
Check if argument is a valid value for srv_adaptive_flushing_method and
 
2124
set it.  This function is registered as a callback with MySQL.
 
2125
@return 0 for valid read_ahead value */
 
2126
static
 
2127
int
 
2128
adaptive_flushing_method_validate(
 
2129
/*==============================*/
 
2130
  Session*,             /*!< in: thread handle */
 
2131
  set_var*    var)
 
2132
{
 
2133
  const char *adaptive_flushing_method_input = var->value->str_value.ptr();
 
2134
  int res = adaptive_flushing_method_typelib.find_type(adaptive_flushing_method_input, TYPELIB::e_none); // e_none is wrong
 
2135
 
 
2136
  if (res > 0) {
 
2137
    srv_adaptive_flushing_method = res - 1;
 
2138
    return 0;
 
2139
  }
 
2140
  return 1;
 
2141
}
 
2142
 
2041
2143
 
2042
2144
/*********************************************************************//**
2043
2145
Opens an InnoDB database.
2069
2171
  srv_spin_wait_delay= innodb_spin_wait_delay.get();
2070
2172
  srv_thread_sleep_delay= innodb_thread_sleep_delay.get();
2071
2173
  srv_read_ahead_threshold= innodb_read_ahead_threshold.get();
 
2174
  srv_auto_lru_dump= buffer_pool_restore_at_startup.get();
 
2175
  srv_ibuf_max_size= ibuf_max_size.get();
 
2176
  srv_ibuf_active_contract= ibuf_active_contract.get();
 
2177
  srv_ibuf_accel_rate= ibuf_accel_rate.get();
 
2178
  srv_checkpoint_age_target= checkpoint_age_target.get();
 
2179
  srv_flush_neighbor_pages= flush_neighbor_pages.get();
 
2180
 
 
2181
  srv_read_ahead = read_ahead_typelib.find_type_or_exit(vm["read-ahead"].as<string>().c_str(),
 
2182
                                                        "read_ahead_typelib") + 1;
 
2183
 
 
2184
  srv_adaptive_flushing_method = adaptive_flushing_method_typelib.find_type_or_exit(vm["adaptive-flushing-method"].as<string>().c_str(),
 
2185
                                                                                    "adaptive_flushing_method_typelib") + 1;
2072
2186
 
2073
2187
  /* Inverted Booleans */
2074
2188
 
2075
 
  innobase_use_checksums= (vm.count("disable-checksums")) ? false : true;
2076
 
  innobase_use_doublewrite= (vm.count("disable-doublewrite")) ? false : true;
2077
 
  srv_adaptive_flushing= (vm.count("disable-adaptive-flushing")) ? false : true;
2078
 
  srv_use_sys_malloc= (vm.count("use-internal-malloc")) ? false : true;
2079
 
  support_xa= (vm.count("disable-xa")) ? false : true;
2080
 
  btr_search_enabled= (vm.count("disable-adaptive-hash-index")) ? false : true;
2081
 
 
 
2189
  innobase_use_checksums= not vm.count("disable-checksums");
 
2190
  innobase_use_doublewrite= not vm.count("disable-doublewrite");
 
2191
  srv_adaptive_flushing= not vm.count("disable-adaptive-flushing");
 
2192
  srv_use_sys_malloc= not vm.count("use-internal-malloc");
 
2193
  srv_use_native_aio= not vm.count("disable-native-aio");
 
2194
  support_xa= not vm.count("disable-xa");
 
2195
  btr_search_enabled= not vm.count("disable-adaptive-hash-index");
2082
2196
 
2083
2197
  /* Hafta do this here because we need to late-bind the default value */
2084
 
  if (vm.count("data-home-dir"))
2085
 
  {
2086
 
    innobase_data_home_dir= vm["data-home-dir"].as<string>();
2087
 
  }
2088
 
  else
2089
 
  {
2090
 
    innobase_data_home_dir= getDataHome().file_string();
2091
 
  }
2092
 
 
 
2198
  innobase_data_home_dir= vm.count("data-home-dir") ? vm["data-home-dir"].as<string>() : getDataHome().file_string();
2093
2199
 
2094
2200
  if (vm.count("data-file-path"))
2095
2201
  {
2103
2209
 
2104
2210
#ifdef UNIV_DEBUG
2105
2211
  static const char test_filename[] = "-@";
2106
 
  char      test_tablename[sizeof test_filename
2107
 
    + sizeof srv_mysql50_table_name_prefix];
2108
 
  if ((sizeof test_tablename) - 1
2109
 
      != filename_to_tablename(test_filename, test_tablename,
2110
 
                               sizeof test_tablename)
2111
 
      || strncmp(test_tablename,
2112
 
                 srv_mysql50_table_name_prefix,
2113
 
                 sizeof srv_mysql50_table_name_prefix)
2114
 
      || strcmp(test_tablename
2115
 
                + sizeof srv_mysql50_table_name_prefix,
 
2212
  const size_t test_tablename_size= sizeof test_filename
 
2213
    + srv_mysql50_table_name_prefix.size();
 
2214
  boost::scoped_array test_tablename(new char[test_tablename_size]);
 
2215
  if ((test_tablename_size) - 1
 
2216
      != filename_to_tablename(test_filename, test_tablename.get(),
 
2217
                               test_tablename_size)
 
2218
      || strncmp(test_tablename.get(),
 
2219
                 srv_mysql50_table_name_prefix.c_str(),
 
2220
                 srv_mysql50_table_name_prefix.size())
 
2221
      || strcmp(test_tablename.get()
 
2222
                + srv_mysql50_table_name_prefix.size(),
2116
2223
                test_filename)) {
2117
 
    errmsg_printf(ERRMSG_LVL_ERROR, "tablename encoding has been changed");
 
2224
    errmsg_printf(error::ERROR, "tablename encoding has been changed");
2118
2225
    goto error;
2119
2226
  }
2120
2227
#endif /* UNIV_DEBUG */
2121
2228
 
 
2229
  srv_page_size = 0;
 
2230
  srv_page_size_shift = 0;
 
2231
 
 
2232
  uint32_t page_size = innobase_page_size.get();
 
2233
  uint32_t log_block_size = innobase_log_block_size.get();
 
2234
 
 
2235
  if (innobase_page_size != (1 << 14)) {
 
2236
    uint n_shift;
 
2237
 
 
2238
    errmsg_printf(error::WARN,
 
2239
                  "InnoDB: Warning: innodb_page_size has been changed from default value 16384. (###EXPERIMENTAL### operation)\n");
 
2240
    for (n_shift = 12; n_shift <= UNIV_PAGE_SIZE_SHIFT_MAX; n_shift++) {
 
2241
      if (innobase_page_size == (1UL << n_shift)) {
 
2242
        srv_page_size_shift = n_shift;
 
2243
        srv_page_size = (1 << srv_page_size_shift);
 
2244
        errmsg_printf(error::WARN,
 
2245
                      "InnoDB: The universal page size of the database is set to %lu.\n",
 
2246
                      srv_page_size);
 
2247
        break;
 
2248
      }
 
2249
    }
 
2250
  } else {
 
2251
    srv_page_size_shift = 14;
 
2252
    srv_page_size = (1 << srv_page_size_shift);
 
2253
  }
 
2254
 
 
2255
  if (!srv_page_size_shift) {
 
2256
    errmsg_printf(error::ERROR,
 
2257
                  "InnoDB: Error: %"PRIu32" is not a valid value for innodb_page_size.\n"
 
2258
                  "InnoDB: Error: Valid values are 4096, 8192, and 16384 (default=16384).\n",
 
2259
                  page_size);
 
2260
    goto error;
 
2261
  }
 
2262
 
 
2263
  srv_log_block_size = 0;
 
2264
  if (log_block_size != (1 << 9)) { /*!=512*/
 
2265
    uint        n_shift;
 
2266
 
 
2267
    errmsg_printf(error::WARN,
 
2268
                  "InnoDB: Warning: innodb_log_block_size has been changed from default value 512. (###EXPERIMENTAL### operation)\n");
 
2269
    for (n_shift = 9; n_shift <= UNIV_PAGE_SIZE_SHIFT_MAX; n_shift++) {
 
2270
      if (log_block_size == (1UL << n_shift)) {
 
2271
        srv_log_block_size = (1 << n_shift);
 
2272
        errmsg_printf(error::WARN, "InnoDB: The log block size is set to %"PRIu32".\n",
 
2273
                      srv_log_block_size);
 
2274
        break;
 
2275
      }
 
2276
    }
 
2277
  } else {
 
2278
    srv_log_block_size = 512;
 
2279
  }
 
2280
 
 
2281
  if (!srv_log_block_size) {
 
2282
    errmsg_printf(error::ERROR,
 
2283
                  "InnoDB: Error: %"PRIu32" is not a valid value for innodb_log_block_size.\n"
 
2284
                  "InnoDB: Error: A valid value for innodb_log_block_size is\n"
 
2285
                  "InnoDB: Error: a power of 2 from 512 to 16384.\n",
 
2286
                  log_block_size);
 
2287
    goto error;
 
2288
  }
 
2289
 
2122
2290
  os_innodb_umask = (ulint)internal::my_umask;
2123
2291
 
2124
2292
 
2148
2316
  ret = (bool) srv_parse_data_file_paths_and_sizes(
2149
2317
                                                   internal_innobase_data_file_path);
2150
2318
  if (ret == FALSE) {
2151
 
    errmsg_printf(ERRMSG_LVL_ERROR, 
2152
 
                  "InnoDB: syntax error in innodb_data_file_path");
 
2319
    errmsg_printf(error::ERROR, "InnoDB: syntax error in innodb_data_file_path");
 
2320
 
2153
2321
mem_free_and_error:
2154
2322
    srv_free_paths_and_sizes();
2155
 
    if (internal_innobase_data_file_path)
2156
 
      free(internal_innobase_data_file_path);
 
2323
    free(internal_innobase_data_file_path);
2157
2324
    goto error;
2158
2325
  }
2159
2326
 
2174
2341
    srv_parse_log_group_home_dirs((char *)innobase_log_group_home_dir.c_str());
2175
2342
 
2176
2343
  if (ret == FALSE || innobase_mirrored_log_groups.get() != 1) {
2177
 
    errmsg_printf(ERRMSG_LVL_ERROR,
2178
 
                  _("syntax error in innodb_log_group_home_dir, or a "
2179
 
                  "wrong number of mirrored log groups"));
 
2344
    errmsg_printf(error::ERROR, _("syntax error in innodb_log_group_home_dir, or a "
 
2345
                                  "wrong number of mirrored log groups"));
2180
2346
 
2181
2347
    goto mem_free_and_error;
2182
2348
  }
2190
2356
 
2191
2357
    if (format_id > DICT_TF_FORMAT_MAX) {
2192
2358
 
2193
 
      errmsg_printf(ERRMSG_LVL_ERROR, "InnoDB: wrong innodb_file_format.");
 
2359
      errmsg_printf(error::ERROR, "InnoDB: wrong innodb_file_format.");
2194
2360
 
2195
2361
      goto mem_free_and_error;
2196
2362
    }
2219
2385
     srv_max_file_format_at_startup */
2220
2386
  if (innobase_file_format_validate_and_set(innobase_file_format_max.c_str()) < 0)
2221
2387
  {
2222
 
    errmsg_printf(ERRMSG_LVL_ERROR, _("InnoDB: invalid "
2223
 
                    "innodb_file_format_max value: "
2224
 
                    "should be any value up to %s or its "
2225
 
                    "equivalent numeric id"),
2226
 
                    trx_sys_file_format_id_to_name(DICT_TF_FORMAT_MAX));
 
2388
    errmsg_printf(error::ERROR, _("InnoDB: invalid innodb_file_format_max value: "
 
2389
                                  "should be any value up to %s or its equivalent numeric id"),
 
2390
                  trx_sys_file_format_id_to_name(DICT_TF_FORMAT_MAX));
2227
2391
    goto mem_free_and_error;
2228
2392
  }
2229
2393
 
2242
2406
      }
2243
2407
    }
2244
2408
 
2245
 
    errmsg_printf(ERRMSG_LVL_ERROR,
2246
 
                  "InnoDB: invalid value "
2247
 
                  "innodb_change_buffering=%s",
 
2409
    errmsg_printf(error::ERROR, "InnoDB: invalid value innodb_change_buffering=%s",
2248
2410
                  vm["change-buffering"].as<string>().c_str());
2249
2411
    goto mem_free_and_error;
2250
2412
  }
2274
2436
  srv_n_read_io_threads = (ulint) innobase_read_io_threads;
2275
2437
  srv_n_write_io_threads = (ulint) innobase_write_io_threads;
2276
2438
 
 
2439
  srv_read_ahead &= 3;
 
2440
  srv_adaptive_flushing_method %= 3;
 
2441
 
2277
2442
  srv_force_recovery = (ulint) innobase_force_recovery;
2278
2443
 
2279
2444
  srv_use_doublewrite_buf = (ibool) innobase_use_doublewrite;
2322
2487
                                                     TRUE);
2323
2488
 
2324
2489
  innobase_open_tables = hash_create(200);
2325
 
  pthread_mutex_init(&innobase_share_mutex, MY_MUTEX_INIT_FAST);
2326
 
  pthread_mutex_init(&prepare_commit_mutex, MY_MUTEX_INIT_FAST);
2327
 
  pthread_mutex_init(&commit_threads_m, MY_MUTEX_INIT_FAST);
2328
 
  pthread_mutex_init(&commit_cond_m, MY_MUTEX_INIT_FAST);
2329
 
  pthread_cond_init(&commit_cond, NULL);
2330
2490
  innodb_inited= 1;
2331
2491
 
2332
2492
  actuall_engine_ptr->dropTemporarySchema();
2333
2493
 
2334
 
  status_table_function_ptr= new InnodbStatusTool;
2335
 
 
 
2494
  context.add(new InnodbStatusTool);
2336
2495
  context.add(innodb_engine_ptr);
2337
 
 
2338
 
  context.add(status_table_function_ptr);
2339
 
 
2340
 
  cmp_tool= new(std::nothrow)CmpTool(false);
2341
 
  context.add(cmp_tool);
2342
 
 
2343
 
  cmp_reset_tool= new(std::nothrow)CmpTool(true);
2344
 
  context.add(cmp_reset_tool);
2345
 
 
2346
 
  cmp_mem_tool= new(std::nothrow)CmpmemTool(false);
2347
 
  context.add(cmp_mem_tool);
2348
 
 
2349
 
  cmp_mem_reset_tool= new(std::nothrow)CmpmemTool(true);
2350
 
  context.add(cmp_mem_reset_tool);
2351
 
 
2352
 
  innodb_trx_tool= new(std::nothrow)InnodbTrxTool("INNODB_TRX");
2353
 
  context.add(innodb_trx_tool);
2354
 
 
2355
 
  innodb_locks_tool= new(std::nothrow)InnodbTrxTool("INNODB_LOCKS");
2356
 
  context.add(innodb_locks_tool);
2357
 
 
2358
 
  innodb_lock_waits_tool= new(std::nothrow)InnodbTrxTool("INNODB_LOCK_WAITS");
2359
 
  context.add(innodb_lock_waits_tool);
2360
 
 
2361
 
  innodb_sys_tables_tool= new(std::nothrow)InnodbSysTablesTool();
2362
 
  context.add(innodb_sys_tables_tool);
2363
 
 
2364
 
  innodb_sys_tablestats_tool= new(std::nothrow)InnodbSysTableStatsTool();
2365
 
  context.add(innodb_sys_tablestats_tool);
2366
 
 
2367
 
  innodb_sys_indexes_tool= new(std::nothrow)InnodbSysIndexesTool();
2368
 
  context.add(innodb_sys_indexes_tool);
2369
 
 
2370
 
  innodb_sys_columns_tool= new(std::nothrow)InnodbSysColumnsTool();
2371
 
  context.add(innodb_sys_columns_tool);
2372
 
 
2373
 
  innodb_sys_fields_tool= new(std::nothrow)InnodbSysFieldsTool();
2374
 
  context.add(innodb_sys_fields_tool);
2375
 
 
2376
 
  innodb_sys_foreign_tool= new(std::nothrow)InnodbSysForeignTool();
2377
 
  context.add(innodb_sys_foreign_tool);
2378
 
 
2379
 
  innodb_sys_foreign_cols_tool= new(std::nothrow)InnodbSysForeignColsTool();
2380
 
  context.add(innodb_sys_foreign_cols_tool);
2381
 
 
2382
 
  context.add(new(std::nothrow)InnodbInternalTables());
2383
 
  context.add(new(std::nothrow)InnodbReplicationTable());
 
2496
  context.add(new CmpTool(false));
 
2497
  context.add(new CmpTool(true));
 
2498
  context.add(new CmpmemTool(false));
 
2499
  context.add(new CmpmemTool(true));
 
2500
  context.add(new InnodbTrxTool("INNODB_TRX"));
 
2501
  context.add(new InnodbTrxTool("INNODB_LOCKS"));
 
2502
  context.add(new InnodbTrxTool("INNODB_LOCK_WAITS"));
 
2503
  context.add(new InnodbSysTablesTool());
 
2504
  context.add(new InnodbSysTableStatsTool());
 
2505
  context.add(new InnodbSysIndexesTool());
 
2506
  context.add(new InnodbSysColumnsTool());
 
2507
  context.add(new InnodbSysFieldsTool());
 
2508
  context.add(new InnodbSysForeignTool());
 
2509
  context.add(new InnodbSysForeignColsTool());
 
2510
  context.add(new InnodbInternalTables());
 
2511
  context.add(new InnodbReplicationTable());
2384
2512
 
2385
2513
  if (innobase_use_replication_log)
2386
2514
  {
2387
 
    replication_logger= new(std::nothrow)ReplicationLog();
 
2515
    ReplicationLog *replication_logger= new ReplicationLog();
2388
2516
    context.add(replication_logger);
2389
2517
    ReplicationLog::setup(replication_logger);
2390
2518
  }
2424
2552
  context.registerVariable(new sys_var_constrained_value<uint32_t>("purge_threads",
2425
2553
                                                                   innodb_n_purge_threads,
2426
2554
                                                                   purge_threads_update));
2427
 
  context.registerVariable(new sys_var_constrained_value<uint16_t>("fast_shutdown", innobase_fast_shutdown));
 
2555
  context.registerVariable(new sys_var_constrained_value<uint32_t>("fast_shutdown", innobase_fast_shutdown));
2428
2556
  context.registerVariable(new sys_var_std_string("file_format",
2429
2557
                                                  innobase_file_format_name,
2430
2558
                                                  innodb_file_format_name_validate));
2436
2564
                                                  innodb_file_format_max_validate));
2437
2565
  context.registerVariable(new sys_var_constrained_value_readonly<size_t>("buffer_pool_size", innobase_buffer_pool_size));
2438
2566
  context.registerVariable(new sys_var_constrained_value_readonly<int64_t>("log_file_size", innobase_log_file_size));
2439
 
  context.registerVariable(new sys_var_constrained_value_readonly<uint16_t>("flush_log_at_trx_commit",
 
2567
  context.registerVariable(new sys_var_constrained_value_readonly<uint32_t>("page_size", innobase_page_size));
 
2568
  context.registerVariable(new sys_var_constrained_value_readonly<uint32_t>("log_block_size", innobase_log_block_size));
 
2569
  context.registerVariable(new sys_var_constrained_value_readonly<uint32_t>("flush_log_at_trx_commit",
2440
2570
                                                  innodb_flush_log_at_trx_commit));
2441
2571
  context.registerVariable(new sys_var_constrained_value_readonly<unsigned int>("max_dirty_pages_pct",
2442
2572
                                                  innodb_max_dirty_pages_pct));
2470
2600
  context.registerVariable(new sys_var_constrained_value<uint32_t>("read_ahead_threshold",
2471
2601
                                                                   innodb_read_ahead_threshold,
2472
2602
                                                                   innodb_read_ahead_threshold_update));
 
2603
  context.registerVariable(new sys_var_constrained_value<uint32_t>("auto_lru_dump",
 
2604
                                                                   buffer_pool_restore_at_startup,
 
2605
                                                                   auto_lru_dump_update));
 
2606
  context.registerVariable(new sys_var_constrained_value_readonly<uint64_t>("ibuf_max_size",
 
2607
                                                                            ibuf_max_size));
 
2608
  context.registerVariable(new sys_var_constrained_value<uint32_t>("ibuf_active_contract",
 
2609
                                                                   ibuf_active_contract,
 
2610
                                                                   ibuf_active_contract_update));
 
2611
  context.registerVariable(new sys_var_constrained_value<uint32_t>("ibuf_accel_rate",
 
2612
                                                                   ibuf_accel_rate,
 
2613
                                                                   ibuf_accel_rate_update));
 
2614
  context.registerVariable(new sys_var_constrained_value<uint32_t>("checkpoint_age_target",
 
2615
                                                                   checkpoint_age_target,
 
2616
                                                                   checkpoint_age_target_update));
 
2617
  context.registerVariable(new sys_var_constrained_value<uint32_t>("flush_neighbor_pages",
 
2618
                                                                   flush_neighbor_pages,
 
2619
                                                                   flush_neighbor_pages_update));
 
2620
  context.registerVariable(new sys_var_std_string("read_ahead",
 
2621
                                                  read_ahead,
 
2622
                                                  read_ahead_validate));
 
2623
  context.registerVariable(new sys_var_std_string("adaptive_flushing_method",
 
2624
                                                  adaptive_flushing_method,
 
2625
                                                  adaptive_flushing_method_validate));
2473
2626
  /* Get the current high water mark format. */
2474
2627
  innobase_file_format_max = trx_sys_file_format_max_get();
2475
2628
  btr_search_fully_disabled = (!btr_search_enabled);
2476
2629
 
2477
2630
  return(FALSE);
 
2631
 
2478
2632
error:
2479
2633
  return(TRUE);
2480
2634
}
2571
2725
    trx_search_latch_release_if_reserved(trx);
2572
2726
  }
2573
2727
 
2574
 
  if (all
2575
 
    || (!session_test_options(session, OPTION_NOT_AUTOCOMMIT | OPTION_BEGIN))) {
2576
 
 
 
2728
  if (all)
 
2729
  {
2577
2730
    /* We were instructed to commit the whole transaction, or
2578
2731
    this is an SQL statement end and autocommit is on */
2579
2732
 
2580
2733
    /* We need current binlog position for ibbackup to work.
2581
2734
    Note, the position is current because of
2582
2735
    prepare_commit_mutex */
2583
 
retry:
2584
 
    if (innobase_commit_concurrency.get() > 0) {
2585
 
      pthread_mutex_lock(&commit_cond_m);
2586
 
      commit_threads++;
2587
 
 
2588
 
      if (commit_threads > innobase_commit_concurrency.get()) {
 
2736
    const uint32_t commit_concurrency= innobase_commit_concurrency.get();
 
2737
    if (commit_concurrency)
 
2738
    {
 
2739
      do 
 
2740
      {
 
2741
        boost::mutex::scoped_lock scopedLock(commit_cond_m);
 
2742
        commit_threads++;
 
2743
 
 
2744
        if (commit_threads <= commit_concurrency) 
 
2745
          break;
 
2746
 
2589
2747
        commit_threads--;
2590
 
        pthread_cond_wait(&commit_cond,
2591
 
          &commit_cond_m);
2592
 
        pthread_mutex_unlock(&commit_cond_m);
2593
 
        goto retry;
2594
 
      }
2595
 
      else {
2596
 
        pthread_mutex_unlock(&commit_cond_m);
2597
 
      }
 
2748
        commit_cond.wait(scopedLock);
 
2749
      } while (1);
2598
2750
    }
2599
2751
 
2600
 
                /* Store transaction point for binlog
2601
 
    Later logic tests that this is set to _something_. We need
2602
 
    that logic to fire, even though we do not have a real name. */
2603
 
    trx->mysql_log_file_name = "UNUSED";
 
2752
    trx->mysql_log_file_name = NULL;
2604
2753
    trx->mysql_log_offset = 0;
2605
2754
 
2606
2755
    /* Don't do write + flush right now. For group commit
2610
2759
    innobase_commit_low(trx);
2611
2760
    trx->flush_log_later = FALSE;
2612
2761
 
2613
 
    if (innobase_commit_concurrency.get() > 0) {
2614
 
      pthread_mutex_lock(&commit_cond_m);
 
2762
    if (commit_concurrency)
 
2763
    {
 
2764
      boost::mutex::scoped_lock scopedLock(commit_cond_m);
2615
2765
      commit_threads--;
2616
 
      pthread_cond_signal(&commit_cond);
2617
 
      pthread_mutex_unlock(&commit_cond_m);
 
2766
      commit_cond.notify_one();
2618
2767
    }
2619
2768
 
2620
2769
    /* Now do a write + flush of logs. */
2699
2848
 
2700
2849
  row_unlock_table_autoinc_for_mysql(trx);
2701
2850
 
2702
 
  if (all
2703
 
    || !session_test_options(session, OPTION_NOT_AUTOCOMMIT | OPTION_BEGIN)) {
2704
 
 
 
2851
  if (all)
 
2852
  {
2705
2853
    error = trx_rollback_for_mysql(trx);
2706
2854
  } else {
2707
2855
    error = trx_rollback_last_sql_stat_for_mysql(trx);
2860
3008
      trx->undo_no > 0 &&
2861
3009
      global_system_variables.log_warnings)
2862
3010
  {
2863
 
      errmsg_printf(ERRMSG_LVL_WARN,
 
3011
      errmsg_printf(error::WARN,
2864
3012
      "Drizzle is closing a connection during a KILL operation\n"
2865
3013
      "that has an active InnoDB transaction.  %llu row modifications will "
2866
3014
      "roll back.\n",
2940
3088
  return(true);
2941
3089
}
2942
3090
 
2943
 
/*****************************************************************//**
2944
 
Normalizes a table name string. A normalized name consists of the
2945
 
database name catenated to '/' and table name. An example:
2946
 
test/mytable. On Windows normalization puts both the database name and the
2947
 
table name always to lower case. */
2948
 
static
2949
 
void
2950
 
normalize_table_name(
2951
 
/*=================*/
2952
 
  char*   norm_name,  /*!< out: normalized name as a
2953
 
          null-terminated string */
2954
 
  const char* name)   /*!< in: table name string */
2955
 
{
2956
 
  const char* name_ptr;
2957
 
  const char* db_ptr;
2958
 
  const char* ptr;
2959
 
 
2960
 
  /* Scan name from the end */
2961
 
 
2962
 
  ptr = strchr(name, '\0')-1;
2963
 
 
2964
 
  while (ptr >= name && *ptr != '\\' && *ptr != '/') {
2965
 
    ptr--;
2966
 
  }
2967
 
 
2968
 
  name_ptr = ptr + 1;
2969
 
 
2970
 
  assert(ptr > name);
2971
 
 
2972
 
  ptr--;
2973
 
 
2974
 
  while (ptr >= name && *ptr != '\\' && *ptr != '/') {
2975
 
    ptr--;
2976
 
  }
2977
 
 
2978
 
  db_ptr = ptr + 1;
2979
 
 
2980
 
  memcpy(norm_name, db_ptr, strlen(name) + 1 - (db_ptr - name));
2981
 
 
2982
 
  norm_name[name_ptr - db_ptr - 1] = '/';
2983
 
 
2984
 
#ifdef __WIN__
2985
 
  innobase_casedn_str(norm_name);
2986
 
#endif
2987
 
}
2988
 
 
2989
3091
/********************************************************************//**
2990
3092
Get the upper limit of the MySQL integral and floating-point type.
2991
3093
@return maximum allowed value for the field */
3152
3254
                if (!index_mapping) {
3153
3255
                        /* Report an error if index_mapping continues to be
3154
3256
                        NULL and mysql_num_index is a non-zero value */
3155
 
                        errmsg_printf(ERRMSG_LVL_ERROR,
3156
 
                                      "InnoDB: fail to allocate memory for "
3157
 
                                        "index translation table. Number of "
3158
 
                                        "Index:%lu, array size:%lu",
 
3257
                        errmsg_printf(error::ERROR, "InnoDB: fail to allocate memory for "
 
3258
                                      "index translation table. Number of Index:%lu, array size:%lu",
3159
3259
                                        mysql_num_index,
3160
3260
                                        share->idx_trans_tbl.array_size);
3161
3261
                        ret = FALSE;
3176
3276
                        ib_table, table->key_info[count].name);
3177
3277
 
3178
3278
                if (!index_mapping[count]) {
3179
 
                        errmsg_printf(ERRMSG_LVL_ERROR, "Cannot find index %s in InnoDB "
3180
 
                                        "index dictionary.",
3181
 
                                        table->key_info[count].name);
 
3279
                        errmsg_printf(error::ERROR, "Cannot find index %s in InnoDB index dictionary.",
 
3280
                                      table->key_info[count].name);
3182
3281
                        ret = FALSE;
3183
3282
                        goto func_exit;
3184
3283
                }
3185
3284
 
3186
3285
                /* Double check fetched index has the same
3187
3286
                column info as those in mysql key_info. */
3188
 
                if (!innobase_match_index_columns(&table->key_info[count],
3189
 
                                                  index_mapping[count])) {
3190
 
                        errmsg_printf(ERRMSG_LVL_ERROR, "Found index %s whose column info "
3191
 
                                        "does not match that of MySQL.",
3192
 
                                        table->key_info[count].name);
3193
 
                        ret = FALSE;
3194
 
                        goto func_exit;
 
3287
                if (!innobase_match_index_columns(&table->key_info[count], index_mapping[count])) {
 
3288
                  errmsg_printf(error::ERROR, "Found index %s whose column info does not match that of MySQL.",
 
3289
                                table->key_info[count].name);
 
3290
                  ret = FALSE;
 
3291
                  goto func_exit;
3195
3292
                }
3196
3293
        }
3197
3294
 
3261
3358
    auto_inc = 0;
3262
3359
 
3263
3360
    ut_print_timestamp(stderr);
3264
 
    fprintf(stderr, "  InnoDB: Unable to determine the AUTOINC "
3265
 
            "column name\n");
 
3361
    errmsg_printf(error::ERROR, "InnoDB: Unable to determine the AUTOINC column name");
3266
3362
  }
3267
3363
 
3268
3364
  if (srv_force_recovery >= SRV_FORCE_NO_IBUF_MERGE) {
3312
3408
    }
3313
3409
    case DB_RECORD_NOT_FOUND:
3314
3410
      ut_print_timestamp(stderr);
3315
 
      fprintf(stderr, "  InnoDB: MySQL and InnoDB data "
3316
 
              "dictionaries are out of sync.\n"
3317
 
              "InnoDB: Unable to find the AUTOINC column "
3318
 
              "%s in the InnoDB table %s.\n"
3319
 
              "InnoDB: We set the next AUTOINC column "
3320
 
              "value to 0,\n"
3321
 
              "InnoDB: in effect disabling the AUTOINC "
3322
 
              "next value generation.\n"
3323
 
              "InnoDB: You can either set the next "
3324
 
              "AUTOINC value explicitly using ALTER TABLE\n"
3325
 
              "InnoDB: or fix the data dictionary by "
3326
 
              "recreating the table.\n",
3327
 
              col_name, index->table->name);
 
3411
      errmsg_printf(error::ERROR, "InnoDB: MySQL and InnoDB data dictionaries are out of sync.\n"
 
3412
                    "InnoDB: Unable to find the AUTOINC column %s in the InnoDB table %s.\n"
 
3413
                    "InnoDB: We set the next AUTOINC column value to 0,\n"
 
3414
                    "InnoDB: in effect disabling the AUTOINC next value generation.\n"
 
3415
                    "InnoDB: You can either set the next AUTOINC value explicitly using ALTER TABLE\n"
 
3416
                    "InnoDB: or fix the data dictionary by recreating the table.\n",
 
3417
                    col_name, index->table->name);
3328
3418
 
3329
3419
      /* This will disable the AUTOINC generation. */
3330
3420
      auto_inc = 0;
3350
3440
@return 1 if error, 0 if success */
3351
3441
UNIV_INTERN
3352
3442
int
3353
 
ha_innobase::doOpen(const TableIdentifier &identifier,
 
3443
ha_innobase::doOpen(const identifier::Table &identifier,
3354
3444
                    int   mode,   /*!< in: not used */
3355
3445
                    uint    test_if_locked) /*!< in: not used */
3356
3446
{
3357
3447
  dict_table_t* ib_table;
3358
 
  char    norm_name[FN_REFLEN];
3359
3448
  Session*    session;
3360
3449
 
3361
3450
  UT_NOT_USED(mode);
3370
3459
    getTransactionalEngine()->releaseTemporaryLatches(session);
3371
3460
  }
3372
3461
 
3373
 
  normalize_table_name(norm_name, identifier.getPath().c_str());
3374
 
 
3375
3462
  user_session = NULL;
3376
3463
 
3377
 
  if (!(share=get_share(identifier.getPath().c_str()))) {
 
3464
  std::string search_string(identifier.getSchemaName());
 
3465
  boost::algorithm::to_lower(search_string);
3378
3466
 
3379
 
    return(1);
 
3467
  if (search_string.compare("data_dictionary") == 0)
 
3468
  {
 
3469
    std::string table_name(identifier.getTableName());
 
3470
    boost::algorithm::to_upper(table_name);
 
3471
    if (!(share=get_share(table_name.c_str())))
 
3472
    {
 
3473
      return 1;
 
3474
    }
 
3475
  }
 
3476
  else
 
3477
  {
 
3478
    if (!(share=get_share(identifier.getKeyPath().c_str())))
 
3479
    {
 
3480
      return(1);
 
3481
    }
3380
3482
  }
3381
3483
 
3382
3484
  /* Create buffers for packing the fields of a record. Why
3385
3487
  stored the string length as the first byte. */
3386
3488
 
3387
3489
  upd_and_key_val_buff_len =
3388
 
        getTable()->getShare()->stored_rec_length
 
3490
        getTable()->getShare()->sizeStoredRecord()
3389
3491
        + getTable()->getShare()->max_key_length
3390
3492
        + MAX_REF_PARTS * 3;
3391
3493
 
3403
3505
  }
3404
3506
 
3405
3507
  /* Get pointer to a table object in InnoDB dictionary cache */
3406
 
  ib_table = dict_table_get(norm_name, TRUE);
 
3508
  if (search_string.compare("data_dictionary") == 0)
 
3509
  {
 
3510
    std::string table_name(identifier.getTableName());
 
3511
    boost::algorithm::to_upper(table_name);
 
3512
    ib_table = dict_table_get(table_name.c_str(), TRUE);
 
3513
  }
 
3514
  else
 
3515
  {
 
3516
    ib_table = dict_table_get(identifier.getKeyPath().c_str(), TRUE);
 
3517
  }
3407
3518
  
3408
3519
  if (NULL == ib_table) {
3409
 
    errmsg_printf(ERRMSG_LVL_ERROR, "Cannot find or open table %s from\n"
 
3520
    errmsg_printf(error::ERROR, "Cannot find or open table %s from\n"
3410
3521
        "the internal data dictionary of InnoDB "
3411
3522
        "though the .frm file for the\n"
3412
3523
        "table exists. Maybe you have deleted and "
3420
3531
        "doesn't support.\n"
3421
3532
        "See " REFMAN "innodb-troubleshooting.html\n"
3422
3533
        "how you can resolve the problem.\n",
3423
 
        norm_name);
 
3534
        identifier.getKeyPath().c_str());
3424
3535
    free_share(share);
3425
3536
    upd_buff.resize(0);
3426
3537
    key_val_buff.resize(0);
3429
3540
    return(HA_ERR_NO_SUCH_TABLE);
3430
3541
  }
3431
3542
 
3432
 
  if (ib_table->ibd_file_missing && !session_tablespace_op(session)) {
3433
 
    errmsg_printf(ERRMSG_LVL_ERROR, "MySQL is trying to open a table handle but "
 
3543
  if (ib_table->ibd_file_missing && ! session->doing_tablespace_operation()) {
 
3544
    errmsg_printf(error::ERROR, "MySQL is trying to open a table handle but "
3434
3545
        "the .ibd file for\ntable %s does not exist.\n"
3435
3546
        "Have you deleted the .ibd file from the "
3436
3547
        "database directory under\nthe MySQL datadir, "
3437
3548
        "or have you used DISCARD TABLESPACE?\n"
3438
3549
        "See " REFMAN "innodb-troubleshooting.html\n"
3439
3550
        "how you can resolve the problem.\n",
3440
 
        norm_name);
 
3551
        identifier.getKeyPath().c_str());
3441
3552
    free_share(share);
3442
3553
    upd_buff.resize(0);
3443
3554
    key_val_buff.resize(0);
3449
3560
 
3450
3561
  prebuilt = row_create_prebuilt(ib_table);
3451
3562
 
3452
 
  prebuilt->mysql_row_len = getTable()->getShare()->stored_rec_length;
 
3563
  prebuilt->mysql_row_len = getTable()->getShare()->sizeStoredRecord();
3453
3564
  prebuilt->default_rec = getTable()->getDefaultValues();
3454
3565
  ut_ad(prebuilt->default_rec);
3455
3566
 
3459
3570
  key_used_on_scan = primary_key;
3460
3571
 
3461
3572
  if (!innobase_build_index_translation(getTable(), ib_table, share)) {
3462
 
    errmsg_printf(ERRMSG_LVL_ERROR, "Build InnoDB index translation table for"
3463
 
                    " Table %s failed", identifier.getPath().c_str());
 
3573
    errmsg_printf(error::ERROR, "Build InnoDB index translation table for"
 
3574
                    " Table %s failed", identifier.getKeyPath().c_str());
3464
3575
  }
3465
3576
 
3466
3577
  /* Allocate a buffer for a 'row reference'. A row reference is
3474
3585
    prebuilt->clust_index_was_generated = FALSE;
3475
3586
 
3476
3587
    if (UNIV_UNLIKELY(primary_key >= MAX_KEY)) {
3477
 
      errmsg_printf(ERRMSG_LVL_ERROR, "Table %s has a primary key in "
 
3588
      errmsg_printf(error::ERROR, "Table %s has a primary key in "
3478
3589
                    "InnoDB data dictionary, but not "
3479
3590
                    "in MySQL!", identifier.getTableName().c_str());
3480
3591
 
3529
3640
    }
3530
3641
  } else {
3531
3642
    if (primary_key != MAX_KEY) {
3532
 
      errmsg_printf(ERRMSG_LVL_ERROR,
 
3643
      errmsg_printf(error::ERROR,
3533
3644
                    "Table %s has no primary key in InnoDB data "
3534
3645
                    "dictionary, but has one in MySQL! If you "
3535
3646
                    "created the table with a MySQL version < "
3565
3676
    and it will never be updated anyway. */
3566
3677
 
3567
3678
    if (key_used_on_scan != MAX_KEY) {
3568
 
      errmsg_printf(ERRMSG_LVL_WARN, 
 
3679
      errmsg_printf(error::WARN, 
3569
3680
        "Table %s key_used_on_scan is %lu even "
3570
3681
        "though there is no primary key inside "
3571
3682
        "InnoDB.", identifier.getTableName().c_str(), (ulong) key_used_on_scan);
3717
3828
of this function is in rem0cmp.c in InnoDB source code! If you change this
3718
3829
function, remember to update the prototype there!
3719
3830
@return 1, 0, -1, if a is greater, equal, less than b, respectively */
3720
 
extern "C" UNIV_INTERN
3721
 
int
 
3831
UNIV_INTERN int
3722
3832
innobase_mysql_cmp(
3723
3833
/*===============*/
3724
3834
  int   mysql_type, /*!< in: MySQL type */
3741
3851
  const unsigned char* b,   /* in: data field */
3742
3852
  unsigned int  b_length) /* in: data field length, not UNIV_SQL_NULL */
3743
3853
{
3744
 
  const CHARSET_INFO* charset;
 
3854
  const charset_info_st* charset;
3745
3855
  enum_field_types  mysql_tp;
3746
3856
  int     ret;
3747
3857
 
3765
3875
      charset = get_charset(charset_number);
3766
3876
 
3767
3877
      if (charset == NULL) {
3768
 
        errmsg_printf(ERRMSG_LVL_ERROR, "InnoDB needs charset %lu for doing "
 
3878
        errmsg_printf(error::ERROR, "InnoDB needs charset %lu for doing "
3769
3879
                      "a comparison, but MySQL cannot "
3770
3880
                      "find that charset.",
3771
3881
                      (ulong) charset_number);
3800
3910
the 'mtype' of InnoDB. InnoDB differentiates between MySQL's old <= 4.1
3801
3911
VARCHAR and the new true VARCHAR in >= 5.0.3 by the 'prtype'.
3802
3912
@return DATA_BINARY, DATA_VARCHAR, ... */
3803
 
extern "C" UNIV_INTERN
 
3913
UNIV_INTERN
3804
3914
ulint
3805
3915
get_innobase_type_from_mysql_type(
3806
3916
/*==============================*/
3849
3959
      return(DATA_VARMYSQL);
3850
3960
    }
3851
3961
  case DRIZZLE_TYPE_DECIMAL:
 
3962
  case DRIZZLE_TYPE_MICROTIME:
3852
3963
    return(DATA_FIXBINARY);
3853
3964
  case DRIZZLE_TYPE_LONG:
3854
3965
  case DRIZZLE_TYPE_LONGLONG:
3855
3966
  case DRIZZLE_TYPE_DATETIME:
 
3967
  case DRIZZLE_TYPE_TIME:
3856
3968
  case DRIZZLE_TYPE_DATE:
3857
3969
  case DRIZZLE_TYPE_TIMESTAMP:
3858
3970
  case DRIZZLE_TYPE_ENUM:
3861
3973
    return(DATA_DOUBLE);
3862
3974
  case DRIZZLE_TYPE_BLOB:
3863
3975
    return(DATA_BLOB);
 
3976
  case DRIZZLE_TYPE_BOOLEAN:
3864
3977
  case DRIZZLE_TYPE_UUID:
3865
3978
    return(DATA_FIXBINARY);
 
3979
  case DRIZZLE_TYPE_IPV6:
 
3980
   return(DATA_FIXBINARY);
3866
3981
  case DRIZZLE_TYPE_NULL:
3867
3982
    ut_error;
3868
3983
  }
3971
4086
      const byte* data;
3972
4087
      ulint   key_len;
3973
4088
      ulint   true_len;
3974
 
      const CHARSET_INFO* cs;
 
4089
      const charset_info_st* cs;
3975
4090
      int   error=0;
3976
4091
 
3977
4092
      key_len = key_part->length;
3997
4112
      the true length of the key */
3998
4113
 
3999
4114
      if (len > 0 && cs->mbmaxlen > 1) {
4000
 
        true_len = (ulint) cs->cset->well_formed_len(cs,
4001
 
            (const char *) data,
4002
 
            (const char *) data + len,
4003
 
                                                (uint) (key_len /
4004
 
                                                        cs->mbmaxlen),
4005
 
            &error);
 
4115
        true_len = (ulint) cs->cset->well_formed_len(*cs, str_ref(data, len), (uint) (key_len / cs->mbmaxlen), &error);
4006
4116
      }
4007
4117
 
4008
4118
      /* In a column prefix index, we may need to truncate
4030
4140
 
4031
4141
    } else if (mysql_type == DRIZZLE_TYPE_BLOB) {
4032
4142
 
4033
 
      const CHARSET_INFO* cs;
 
4143
      const charset_info_st* cs;
4034
4144
      ulint   key_len;
4035
4145
      ulint   true_len;
4036
4146
      int   error=0;
4063
4173
      the true length of the key */
4064
4174
 
4065
4175
      if (blob_len > 0 && cs->mbmaxlen > 1) {
4066
 
        true_len = (ulint) cs->cset->well_formed_len(cs,
4067
 
                                                     (const char *) blob_data,
4068
 
                                                     (const char *) blob_data
4069
 
                                                     + blob_len,
4070
 
                                                     (uint) (key_len /
4071
 
                                                             cs->mbmaxlen),
4072
 
                                                     &error);
 
4176
        true_len = (ulint) cs->cset->well_formed_len(*cs, str_ref(blob_data, blob_len), (uint) (key_len / cs->mbmaxlen), &error);
4073
4177
      }
4074
4178
 
4075
4179
      /* All indexes on BLOB and TEXT are column prefix
4102
4206
      ulint     true_len;
4103
4207
      ulint     key_len;
4104
4208
      const unsigned char*    src_start;
4105
 
      enum_field_types  real_type;
4106
 
      const CHARSET_INFO* cs= field->charset();
 
4209
      const charset_info_st* cs= field->charset();
4107
4210
 
4108
4211
      key_len = key_part->length;
4109
4212
 
4114
4217
      }
4115
4218
 
4116
4219
      src_start = record + key_part->offset;
4117
 
      real_type = field->real_type();
4118
4220
      true_len = key_len;
4119
4221
 
4120
4222
      /* Character set for the field is defined only
4288
4390
    n_requested_fields++;
4289
4391
 
4290
4392
    templ->col_no = i;
 
4393
    templ->clust_rec_field_no = dict_col_get_clust_pos(col, clust_index);
 
4394
    ut_ad(templ->clust_rec_field_no != ULINT_UNDEFINED);
4291
4395
 
4292
4396
    if (index == clust_index) {
4293
 
      templ->rec_field_no = dict_col_get_clust_pos(col, index);
 
4397
      templ->rec_field_no = templ->clust_rec_field_no;
4294
4398
    } else {
4295
4399
      templ->rec_field_no = dict_index_get_nth_col_pos(
4296
4400
                index, i);
4297
 
    }
4298
 
 
4299
 
    if (templ->rec_field_no == ULINT_UNDEFINED) {
4300
 
      prebuilt->need_to_access_clustered = TRUE;
 
4401
      if (templ->rec_field_no == ULINT_UNDEFINED) {
 
4402
        prebuilt->need_to_access_clustered = TRUE;
 
4403
      }
4301
4404
    }
4302
4405
 
4303
4406
    if (field->null_ptr) {
4347
4450
    for (i = 0; i < n_requested_fields; i++) {
4348
4451
      templ = prebuilt->mysql_template + i;
4349
4452
 
4350
 
      templ->rec_field_no = dict_col_get_clust_pos(
4351
 
        &index->table->cols[templ->col_no],
4352
 
        clust_index);
 
4453
      templ->rec_field_no = templ->clust_rec_field_no;
4353
4454
    }
4354
4455
  }
4355
4456
}
4423
4524
  trx_t*    trx = session_to_trx(user_session);
4424
4525
 
4425
4526
  if (prebuilt->trx != trx) {
4426
 
    errmsg_printf(ERRMSG_LVL_ERROR, "The transaction object for the table handle is at "
 
4527
    errmsg_printf(error::ERROR, "The transaction object for the table handle is at "
4427
4528
        "%p, but for the current thread it is at %p",
4428
4529
        (const void*) prebuilt->trx, (const void*) trx);
4429
4530
 
4437
4538
    ut_error;
4438
4539
  }
4439
4540
 
4440
 
  sql_command = session_sql_command(user_session);
 
4541
  sql_command = user_session->getSqlCommand();
4441
4542
 
4442
4543
  if ((sql_command == SQLCOM_ALTER_TABLE
4443
4544
       || sql_command == SQLCOM_CREATE_INDEX
4884
4985
  if (error == DB_SUCCESS
4885
4986
      && getTable()->next_number_field
4886
4987
      && new_row == getTable()->getInsertRecord()
4887
 
      && session_sql_command(user_session) == SQLCOM_INSERT
 
4988
      && user_session->getSqlCommand() == SQLCOM_INSERT
4888
4989
      && (trx->duplicates & (TRX_DUP_IGNORE | TRX_DUP_REPLACE))
4889
4990
    == TRX_DUP_IGNORE)  {
4890
4991
 
5351
5452
         table. Only print message if the index translation
5352
5453
         table exists */
5353
5454
      if (share->idx_trans_tbl.index_mapping) {
5354
 
        errmsg_printf(ERRMSG_LVL_ERROR,
 
5455
        errmsg_printf(error::ERROR,
5355
5456
                      "InnoDB could not find "
5356
5457
                      "index %s key no %u for "
5357
5458
                      "table %s through its "
5369
5470
  }
5370
5471
 
5371
5472
  if (!index) {
5372
 
    errmsg_printf(ERRMSG_LVL_ERROR, 
 
5473
    errmsg_printf(error::ERROR, 
5373
5474
      "Innodb could not find key n:o %u with name %s "
5374
5475
      "from dict cache for table %s",
5375
 
      keynr, getTable()->getShare()->getTableProto()->indexes(keynr).name().c_str(),
 
5476
      keynr, getTable()->getShare()->getTableMessage()->indexes(keynr).name().c_str(),
5376
5477
      prebuilt->table->name);
5377
5478
  }
5378
5479
 
5398
5499
  prebuilt->index = innobase_get_index(keynr);
5399
5500
 
5400
5501
  if (UNIV_UNLIKELY(!prebuilt->index)) {
5401
 
    errmsg_printf(ERRMSG_LVL_WARN, "InnoDB: change_active_index(%u) failed",
 
5502
    errmsg_printf(error::WARN, "InnoDB: change_active_index(%u) failed",
5402
5503
          keynr);
5403
5504
    prebuilt->index_usable = FALSE;
5404
5505
    return(1);
5764
5865
  table. */
5765
5866
 
5766
5867
  if (len != ref_length) {
5767
 
    errmsg_printf(ERRMSG_LVL_ERROR, "Stored ref len is %lu, but table ref len is %lu",
 
5868
    errmsg_printf(error::ERROR, "Stored ref len is %lu, but table ref len is %lu",
5768
5869
        (ulong) len, (ulong) ref_length);
5769
5870
  }
5770
5871
}
5823
5924
 
5824
5925
    if (!col_type) {
5825
5926
      push_warning_printf(
5826
 
                          (Session*) trx->mysql_thd,
 
5927
                          trx->mysql_thd,
5827
5928
                          DRIZZLE_ERROR::WARN_LEVEL_WARN,
5828
5929
                          ER_CANT_CREATE_TABLE,
5829
5930
                          "Error creating table '%s' with "
5857
5958
        /* in data0type.h we assume that the
5858
5959
        number fits in one byte in prtype */
5859
5960
        push_warning_printf(
5860
 
          (Session*) trx->mysql_thd,
 
5961
          trx->mysql_thd,
5861
5962
          DRIZZLE_ERROR::WARN_LEVEL_ERROR,
5862
5963
          ER_CANT_CREATE_TABLE,
5863
5964
          "In InnoDB, charset-collation codes"
6023
6124
        || col_type == DATA_FLOAT
6024
6125
        || col_type == DATA_DOUBLE
6025
6126
        || col_type == DATA_DECIMAL) {
6026
 
        errmsg_printf(ERRMSG_LVL_ERROR, 
 
6127
        errmsg_printf(error::ERROR, 
6027
6128
          "MySQL is trying to create a column "
6028
6129
          "prefix index field, on an "
6029
6130
          "inappropriate data type. Table "
6120
6221
UNIV_INTERN
6121
6222
int
6122
6223
InnobaseEngine::doCreateTable(
6123
 
/*================*/
6124
 
  Session         &session, /*!< in: Session */
6125
 
  Table&    form,   /*!< in: information on table columns and indexes */
6126
 
        const TableIdentifier &identifier,
6127
 
        message::Table& create_proto)
 
6224
                              /*================*/
 
6225
                              Session         &session, /*!< in: Session */
 
6226
                              Table&    form,   /*!< in: information on table columns and indexes */
 
6227
                              const identifier::Table &identifier,
 
6228
                              const message::Table& create_proto)
6128
6229
{
6129
6230
  int   error;
6130
6231
  dict_table_t* innobase_table;
6132
6233
  trx_t*    trx;
6133
6234
  int   primary_key_no;
6134
6235
  uint    i;
6135
 
  char    name2[FN_REFLEN];
6136
 
  char    norm_name[FN_REFLEN];
6137
6236
  ib_int64_t  auto_inc_value;
6138
6237
  ulint   iflags;
6139
6238
  /* Cache the value of innodb_file_format, in case it is
6143
6242
  const char* stmt;
6144
6243
  size_t stmt_len;
6145
6244
 
6146
 
  const char *table_name= identifier.getPath().c_str();
 
6245
  std::string search_string(identifier.getSchemaName());
 
6246
  boost::algorithm::to_lower(search_string);
 
6247
 
 
6248
  if (search_string.compare("data_dictionary") == 0)
 
6249
  {
 
6250
    return HA_WRONG_CREATE_OPTION;
 
6251
  }
6147
6252
 
6148
6253
  if (form.getShare()->sizeFields() > 1000) {
6149
6254
    /* The limit probably should be REC_MAX_N_FIELDS - 3 = 1020,
6166
6271
 
6167
6272
  srv_lower_case_table_names = TRUE;
6168
6273
 
6169
 
  strcpy(name2, table_name);
6170
 
 
6171
 
  normalize_table_name(norm_name, name2);
6172
 
 
6173
6274
  /* Latch the InnoDB data dictionary exclusively so that no deadlocks
6174
6275
    or lock waits can happen in it during a table create operation.
6175
6276
    Drop table etc. do this latching in row0mysql.c. */
6230
6331
      | DICT_TF_COMPACT
6231
6332
      | DICT_TF_FORMAT_ZIP
6232
6333
      << DICT_TF_FORMAT_SHIFT;
6233
 
#if DICT_TF_ZSSIZE_MAX < 1
6234
 
# error "DICT_TF_ZSSIZE_MAX < 1"
6235
 
#endif
6236
6334
 
6237
6335
    if (strict_mode)
6238
6336
    {
6277
6375
  if (lex_identified_temp_table)
6278
6376
    iflags |= DICT_TF2_TEMPORARY << DICT_TF2_SHIFT;
6279
6377
 
6280
 
  error= create_table_def(trx, &form, norm_name,
6281
 
                          lex_identified_temp_table ? name2 : NULL,
 
6378
  error= create_table_def(trx, &form, identifier.getKeyPath().c_str(),
 
6379
                          lex_identified_temp_table ? identifier.getKeyPath().c_str() : NULL,
6282
6380
                          iflags);
6283
6381
 
6284
6382
  session.setXaId(trx->id);
6294
6392
      order the rows by their row id which is internally generated
6295
6393
      by InnoDB */
6296
6394
 
6297
 
    error = create_clustered_index_when_no_primary(trx, iflags, norm_name);
 
6395
    error = create_clustered_index_when_no_primary(trx, iflags, identifier.getKeyPath().c_str());
6298
6396
    if (error) {
6299
6397
      goto cleanup;
6300
6398
    }
6302
6400
 
6303
6401
  if (primary_key_no != -1) {
6304
6402
    /* In InnoDB the clustered index must always be created first */
6305
 
    if ((error = create_index(trx, &form, iflags, norm_name,
 
6403
    if ((error = create_index(trx, &form, iflags, identifier.getKeyPath().c_str(),
6306
6404
                              (uint) primary_key_no))) {
6307
6405
      goto cleanup;
6308
6406
    }
6311
6409
  for (i = 0; i < form.getShare()->sizeKeys(); i++) {
6312
6410
    if (i != (uint) primary_key_no) {
6313
6411
 
6314
 
      if ((error = create_index(trx, &form, iflags, norm_name,
 
6412
      if ((error = create_index(trx, &form, iflags, identifier.getKeyPath().c_str(),
6315
6413
                                i))) {
6316
6414
        goto cleanup;
6317
6415
      }
6318
6416
    }
6319
6417
  }
6320
6418
 
6321
 
  stmt = innobase_get_stmt(&session, &stmt_len);
 
6419
  stmt= session.getQueryStringCopy(stmt_len);
6322
6420
 
6323
6421
  if (stmt) {
6324
6422
    string generated_create_table;
6325
6423
    const char *query= stmt;
6326
6424
 
6327
 
    if (session_sql_command(&session) == SQLCOM_CREATE_TABLE)
 
6425
    if (session.getSqlCommand() == SQLCOM_CREATE_TABLE)
6328
6426
    {
6329
6427
      message::transformTableDefinitionToSql(create_proto,
6330
6428
                                             generated_create_table,
6334
6432
 
6335
6433
    error = row_table_add_foreign_constraints(trx,
6336
6434
                                              query, strlen(query),
6337
 
                                              norm_name,
 
6435
                                              identifier.getKeyPath().c_str(),
6338
6436
                                              lex_identified_temp_table);
 
6437
    switch (error) {
 
6438
 
 
6439
    case DB_PARENT_NO_INDEX:
 
6440
      push_warning_printf(
 
6441
                          &session, DRIZZLE_ERROR::WARN_LEVEL_WARN,
 
6442
                          HA_ERR_CANNOT_ADD_FOREIGN,
 
6443
                          "Create table '%s' with foreign key constraint"
 
6444
                          " failed. There is no index in the referenced"
 
6445
                          " table where the referenced columns appear"
 
6446
                          " as the first columns.\n", identifier.getKeyPath().c_str());
 
6447
      break;
 
6448
 
 
6449
    case DB_CHILD_NO_INDEX:
 
6450
      push_warning_printf(
 
6451
                          &session, DRIZZLE_ERROR::WARN_LEVEL_WARN,
 
6452
                          HA_ERR_CANNOT_ADD_FOREIGN,
 
6453
                          "Create table '%s' with foreign key constraint"
 
6454
                          " failed. There is no index in the referencing"
 
6455
                          " table where referencing columns appear"
 
6456
                          " as the first columns.\n", identifier.getKeyPath().c_str());
 
6457
      break;
 
6458
    }
6339
6459
 
6340
6460
    error = convert_error_code_to_mysql(error, iflags, NULL);
6341
6461
 
6354
6474
 
6355
6475
  log_buffer_flush_to_disk();
6356
6476
 
6357
 
  innobase_table = dict_table_get(norm_name, FALSE);
 
6477
  innobase_table = dict_table_get(identifier.getKeyPath().c_str(), FALSE);
6358
6478
 
6359
6479
  assert(innobase_table != 0);
6360
6480
 
6377
6497
    does a table copy too. */
6378
6498
 
6379
6499
  if ((create_proto.options().has_auto_increment_value()
6380
 
       || session_sql_command(&session) == SQLCOM_ALTER_TABLE
6381
 
       || session_sql_command(&session) == SQLCOM_CREATE_INDEX)
 
6500
       || session.getSqlCommand() == SQLCOM_ALTER_TABLE
 
6501
       || session.getSqlCommand() == SQLCOM_CREATE_INDEX)
6382
6502
      && create_proto.options().auto_increment_value() != 0) {
6383
6503
 
6384
6504
    /* Query was one of :
6471
6591
 
6472
6592
  update_session(getTable()->in_use);
6473
6593
 
6474
 
  if (session_sql_command(user_session) != SQLCOM_TRUNCATE) {
 
6594
  if (user_session->getSqlCommand() != SQLCOM_TRUNCATE) {
6475
6595
  fallback:
6476
6596
    /* We only handle TRUNCATE TABLE t as a special case.
6477
6597
    DELETE FROM t will have to use ha_innobase::doDeleteRecord(),
6505
6625
InnobaseEngine::doDropTable(
6506
6626
/*======================*/
6507
6627
        Session &session,
6508
 
        const TableIdentifier &identifier)
 
6628
        const identifier::Table &identifier)
6509
6629
{
6510
6630
  int error;
6511
6631
  trx_t*  parent_trx;
6512
6632
  trx_t*  trx;
6513
 
  char  norm_name[1000];
6514
6633
 
6515
6634
  ut_a(identifier.getPath().length() < 1000);
6516
6635
 
6517
 
  /* Strangely, MySQL passes the table name without the '.frm'
6518
 
    extension, in contrast to ::create */
6519
 
  normalize_table_name(norm_name, identifier.getPath().c_str());
 
6636
  std::string search_string(identifier.getSchemaName());
 
6637
  boost::algorithm::to_lower(search_string);
 
6638
 
 
6639
  if (search_string.compare("data_dictionary") == 0)
 
6640
  {
 
6641
    return HA_ERR_TABLE_READONLY;
 
6642
  }
6520
6643
 
6521
6644
  /* Get the transaction associated with the current session, or create one
6522
6645
    if not yet created */
6534
6657
 
6535
6658
  /* Drop the table in InnoDB */
6536
6659
 
6537
 
  error = row_drop_table_for_mysql(norm_name, trx,
6538
 
                                   session_sql_command(&session)
 
6660
  error = row_drop_table_for_mysql(identifier.getKeyPath().c_str(), trx,
 
6661
                                   session.getSqlCommand()
6539
6662
                                   == SQLCOM_DROP_DB);
6540
6663
 
6541
6664
  session.setXaId(trx->id);
6563
6686
    if (identifier.getType() == message::Table::TEMPORARY)
6564
6687
    {
6565
6688
      session.getMessageCache().removeTableMessage(identifier);
6566
 
      ulint sql_command = session_sql_command(&session);
 
6689
      ulint sql_command = session.getSqlCommand();
6567
6690
 
6568
6691
      // If this was the final removal to an alter table then we will need
6569
6692
      // to remove the .dfe that was left behind.
6596
6719
bool
6597
6720
InnobaseEngine::doDropSchema(
6598
6721
/*===================*/
6599
 
                             const SchemaIdentifier &identifier)
 
6722
                             const identifier::Schema &identifier)
6600
6723
    /*!< in: database path; inside InnoDB the name
6601
6724
      of the last directory in the path is used as
6602
6725
      the database name: for example, in 'mysql/data/test'
6641
6764
  innobase_commit_low(trx);
6642
6765
  trx_free_for_mysql(trx);
6643
6766
 
 
6767
  if (error) {
 
6768
    // What do we do here?
 
6769
  }
 
6770
 
6644
6771
  return false; // We are just a listener since we lack control over DDL, so we give no positive acknowledgement. 
6645
6772
}
6646
6773
 
6647
6774
void InnobaseEngine::dropTemporarySchema()
6648
6775
{
6649
 
  SchemaIdentifier schema_identifier(GLOBAL_TEMPORARY_EXT);
6650
 
  trx_t*  trx= NULL;
6651
6776
  string schema_path(GLOBAL_TEMPORARY_EXT);
6652
 
 
6653
 
  schema_path.append("/");
6654
 
 
6655
 
  trx = trx_allocate_for_mysql();
 
6777
  schema_path += "/";
 
6778
 
 
6779
  trx_t* trx = trx_allocate_for_mysql();
6656
6780
 
6657
6781
  trx->mysql_thd = NULL;
6658
6782
 
6683
6807
innobase_rename_table(
6684
6808
/*==================*/
6685
6809
  trx_t*    trx,  /*!< in: transaction */
6686
 
  const char* from, /*!< in: old name of the table */
6687
 
  const char* to, /*!< in: new name of the table */
 
6810
  const identifier::Table &from,
 
6811
  const identifier::Table &to,
6688
6812
  ibool   lock_and_commit)
6689
6813
        /*!< in: TRUE=lock data dictionary and commit */
6690
6814
{
6691
6815
  int error;
6692
 
  char norm_to[FN_REFLEN];
6693
 
  char norm_from[FN_REFLEN];
6694
6816
 
6695
6817
  srv_lower_case_table_names = TRUE;
6696
6818
 
6697
 
  normalize_table_name(norm_to, to);
6698
 
  normalize_table_name(norm_from, from);
6699
 
 
6700
6819
  /* Serialize data dictionary operations with dictionary mutex:
6701
6820
  no deadlocks can occur then in these operations */
6702
6821
 
6704
6823
    row_mysql_lock_data_dictionary(trx);
6705
6824
  }
6706
6825
 
6707
 
  error = row_rename_table_for_mysql(
6708
 
    norm_from, norm_to, trx, lock_and_commit);
 
6826
  error = row_rename_table_for_mysql(from.getKeyPath().c_str(), to.getKeyPath().c_str(), trx, lock_and_commit);
6709
6827
 
6710
6828
  if (error != DB_SUCCESS) {
6711
6829
    FILE* ef = dict_foreign_err_file;
6712
6830
 
6713
6831
    fputs("InnoDB: Renaming table ", ef);
6714
 
    ut_print_name(ef, trx, TRUE, norm_from);
 
6832
    ut_print_name(ef, trx, TRUE, from.getKeyPath().c_str());
6715
6833
    fputs(" to ", ef);
6716
 
    ut_print_name(ef, trx, TRUE, norm_to);
 
6834
    ut_print_name(ef, trx, TRUE, to.getKeyPath().c_str());
6717
6835
    fputs(" failed!\n", ef);
6718
6836
  }
6719
6837
 
6732
6850
/*********************************************************************//**
6733
6851
Renames an InnoDB table.
6734
6852
@return 0 or error code */
6735
 
UNIV_INTERN int InnobaseEngine::doRenameTable(Session &session, const TableIdentifier &from, const TableIdentifier &to)
 
6853
UNIV_INTERN int InnobaseEngine::doRenameTable(Session &session, const identifier::Table &from, const identifier::Table &to)
6736
6854
{
6737
6855
  // A temp table alter table/rename is a shallow rename and only the
6738
6856
  // definition needs to be updated.
6758
6876
 
6759
6877
  trx = innobase_trx_allocate(&session);
6760
6878
 
6761
 
  error = innobase_rename_table(trx, from.getPath().c_str(), to.getPath().c_str(), TRUE);
 
6879
  error = innobase_rename_table(trx, from, to, TRUE);
6762
6880
 
6763
6881
  session.setXaId(trx->id);
6764
6882
 
6783
6901
     is the one we are trying to rename to) and return the generic
6784
6902
     error code. */
6785
6903
  if (error == (int) DB_DUPLICATE_KEY) {
6786
 
    my_error(ER_TABLE_EXISTS_ERROR, MYF(0), to.getPath().c_str());
 
6904
    my_error(ER_TABLE_EXISTS_ERROR, to);
6787
6905
    error = DB_ERROR;
6788
6906
  }
6789
6907
 
6814
6932
  KeyInfo*    key;
6815
6933
  dict_index_t* index;
6816
6934
  unsigned char*    key_val_buff2 = (unsigned char*) malloc(
6817
 
              getTable()->getShare()->stored_rec_length
 
6935
              getTable()->getShare()->sizeStoredRecord()
6818
6936
          + getTable()->getShare()->max_key_length + 100);
6819
 
  ulint   buff2_len = getTable()->getShare()->stored_rec_length
 
6937
  ulint   buff2_len = getTable()->getShare()->sizeStoredRecord()
6820
6938
          + getTable()->getShare()->max_key_length + 100;
6821
6939
  dtuple_t* range_start;
6822
6940
  dtuple_t* range_end;
6827
6945
 
6828
6946
  ut_a(prebuilt->trx == session_to_trx(getTable()->in_use));
6829
6947
 
6830
 
  prebuilt->trx->op_info = (char*)"estimating records in index range";
 
6948
  prebuilt->trx->op_info = "estimating records in index range";
6831
6949
 
6832
6950
  /* In case MySQL calls this in the middle of a SELECT query, release
6833
6951
  possible adaptive hash latch to avoid deadlocks of threads */
6899
7017
func_exit:
6900
7018
  free(key_val_buff2);
6901
7019
 
6902
 
  prebuilt->trx->op_info = (char*)"";
 
7020
  prebuilt->trx->op_info = "";
6903
7021
 
6904
7022
  /* The MySQL optimizer seems to believe an estimate of 0 rows is
6905
7023
  always accurate and may return the result 'Empty set' based on that.
6926
7044
  dict_index_t* index;
6927
7045
  uint64_t  estimate;
6928
7046
  uint64_t  local_data_file_length;
 
7047
  ulint stat_n_leaf_pages;
6929
7048
 
6930
7049
  /* We do not know if MySQL can call this function before calling
6931
7050
  external_lock(). To be safe, update the session of the current table
6943
7062
 
6944
7063
  index = dict_table_get_first_index(prebuilt->table);
6945
7064
 
6946
 
  ut_a(index->stat_n_leaf_pages > 0);
 
7065
  stat_n_leaf_pages = index->stat_n_leaf_pages;
 
7066
 
 
7067
  ut_a(stat_n_leaf_pages > 0);
6947
7068
 
6948
7069
  local_data_file_length =
6949
 
    ((uint64_t) index->stat_n_leaf_pages) * UNIV_PAGE_SIZE;
 
7070
    ((uint64_t) stat_n_leaf_pages) * UNIV_PAGE_SIZE;
6950
7071
 
6951
7072
 
6952
7073
  /* Calculate a minimum length for a clustered index record and from
6957
7078
  estimate = 2 * local_data_file_length /
6958
7079
           dict_index_calc_min_rec_len(index);
6959
7080
 
6960
 
  prebuilt->trx->op_info = (char*)"";
 
7081
  prebuilt->trx->op_info = "";
6961
7082
 
6962
7083
  return((ha_rows) estimate);
6963
7084
}
7096
7217
 
7097
7218
                /* Print an error message if we cannot find the index
7098
7219
                ** in the "index translation table". */
7099
 
                errmsg_printf(ERRMSG_LVL_ERROR,
 
7220
                errmsg_printf(error::ERROR,
7100
7221
                              "Cannot find index %s in InnoDB index "
7101
7222
                                "translation table.", index->name);
7102
7223
        }
7113
7234
                }
7114
7235
        }
7115
7236
 
7116
 
                errmsg_printf(ERRMSG_LVL_ERROR,
 
7237
                errmsg_printf(error::ERROR,
7117
7238
                              "Cannot find matching index number for index %s "
7118
7239
                              "in InnoDB index list.", index->name);
7119
7240
 
7147
7268
  /* In case MySQL calls this in the middle of a SELECT query, release
7148
7269
  possible adaptive hash latch to avoid deadlocks of threads */
7149
7270
 
7150
 
  prebuilt->trx->op_info = (char*)"returning various info to MySQL";
 
7271
  prebuilt->trx->op_info = "returning various info to MySQL";
7151
7272
 
7152
7273
  trx_search_latch_release_if_reserved(prebuilt->trx);
7153
7274
 
7159
7280
 
7160
7281
    prebuilt->trx->op_info = "updating table statistics";
7161
7282
 
7162
 
    dict_update_statistics(ib_table);
 
7283
    dict_update_statistics(ib_table,
 
7284
                           FALSE /* update even if stats
 
7285
                                    are initialized */);
 
7286
 
7163
7287
 
7164
7288
    prebuilt->trx->op_info = "returning various info to MySQL";
7165
7289
 
7176
7300
  }
7177
7301
 
7178
7302
  if (flag & HA_STATUS_VARIABLE) {
 
7303
 
 
7304
    dict_table_stats_lock(ib_table, RW_S_LATCH);
 
7305
 
7179
7306
    n_rows = ib_table->stat_n_rows;
7180
7307
 
7181
7308
    /* Because we do not protect stat_n_rows by any mutex in a
7203
7330
    n_rows can not be 0 unless the table is empty, set to 1
7204
7331
    instead. The original problem of bug#29507 is actually
7205
7332
    fixed in the server code. */
7206
 
    if (session_sql_command(user_session) == SQLCOM_TRUNCATE) {
 
7333
    if (user_session->getSqlCommand() == SQLCOM_TRUNCATE) {
7207
7334
 
7208
7335
      n_rows = 1;
7209
7336
 
7225
7352
        ib_table->stat_sum_of_other_index_sizes)
7226
7353
          * UNIV_PAGE_SIZE;
7227
7354
 
 
7355
    dict_table_stats_unlock(ib_table, RW_S_LATCH);
 
7356
 
7228
7357
    /* Since fsp_get_available_space_in_free_extents() is
7229
7358
    acquiring latches inside InnoDB, we do not call it if we
7230
7359
    are asked by MySQL to avoid locking. Another reason to
7241
7370
         innodb_crash_recovery is set to a high value. */
7242
7371
      stats.delete_length = 0;
7243
7372
    } else {
7244
 
      /* lock the data dictionary to avoid races with
7245
 
      ibd_file_missing and tablespace_discarded */
7246
 
      row_mysql_lock_data_dictionary(prebuilt->trx);
7247
 
 
7248
 
      /* ib_table->space must be an existent tablespace */
7249
 
      if (!ib_table->ibd_file_missing
7250
 
          && !ib_table->tablespace_discarded) {
7251
 
 
7252
 
        stats.delete_length =
7253
 
          fsp_get_available_space_in_free_extents(
7254
 
            ib_table->space) * 1024;
7255
 
      } else {
7256
 
 
 
7373
      ullint    avail_space;
 
7374
 
 
7375
      avail_space = fsp_get_available_space_in_free_extents(ib_table->space);
 
7376
 
 
7377
      if (avail_space == ULLINT_UNDEFINED) {
7257
7378
        Session*  session;
7258
7379
 
7259
7380
        session= getTable()->in_use;
7271
7392
          ib_table->name);
7272
7393
 
7273
7394
        stats.delete_length = 0;
 
7395
      } else {
 
7396
        stats.delete_length = avail_space * 1024;
7274
7397
      }
7275
 
 
7276
 
      row_mysql_unlock_data_dictionary(prebuilt->trx);
7277
7398
    }
7278
7399
 
7279
7400
    stats.check_time = 0;
7293
7414
    ulint       num_innodb_index = UT_LIST_GET_LEN(ib_table->indexes) - prebuilt->clust_index_was_generated;
7294
7415
 
7295
7416
    if (getTable()->getShare()->keys != num_innodb_index) {
7296
 
      errmsg_printf(ERRMSG_LVL_ERROR, "Table %s contains %lu "
 
7417
      errmsg_printf(error::ERROR, "Table %s contains %lu "
7297
7418
                      "indexes inside InnoDB, which "
7298
7419
                      "is different from the number of "
7299
7420
                      "indexes %u defined in the MySQL ",
7301
7422
                      getTable()->getShare()->keys);
7302
7423
    }
7303
7424
 
 
7425
    dict_table_stats_lock(ib_table, RW_S_LATCH);
 
7426
 
7304
7427
    for (i = 0; i < getTable()->getShare()->sizeKeys(); i++) {
7305
7428
      ulong j;
7306
7429
      /* We could get index quickly through internal
7311
7434
      index = innobase_get_index(i);
7312
7435
 
7313
7436
      if (index == NULL) {
7314
 
        errmsg_printf(ERRMSG_LVL_ERROR, "Table %s contains fewer "
 
7437
        errmsg_printf(error::ERROR, "Table %s contains fewer "
7315
7438
            "indexes inside InnoDB than "
7316
7439
            "are defined in the MySQL "
7317
7440
            ".frm file. Have you mixed up "
7326
7449
      for (j = 0; j < getTable()->key_info[i].key_parts; j++) {
7327
7450
 
7328
7451
        if (j + 1 > index->n_uniq) {
7329
 
          errmsg_printf(ERRMSG_LVL_ERROR, 
 
7452
          errmsg_printf(error::ERROR, 
7330
7453
"Index %s of %s has %lu columns unique inside InnoDB, but MySQL is asking "
7331
7454
"statistics for %lu columns. Have you mixed up .frm files from different "
7332
7455
"installations? "
7338
7461
          break;
7339
7462
        }
7340
7463
 
7341
 
        dict_index_stat_mutex_enter(index);
7342
 
 
7343
7464
        if (index->stat_n_diff_key_vals[j + 1] == 0) {
7344
7465
 
7345
7466
          rec_per_key = stats.records;
7348
7469
           index->stat_n_diff_key_vals[j + 1]);
7349
7470
        }
7350
7471
 
7351
 
        dict_index_stat_mutex_exit(index);
7352
 
 
7353
7472
        /* Since MySQL seems to favor table scans
7354
7473
        too much over index searches, we pretend
7355
7474
        index selectivity is 2 times better than
7366
7485
          (ulong) rec_per_key;
7367
7486
      }
7368
7487
    }
 
7488
 
 
7489
    dict_table_stats_unlock(ib_table, RW_S_LATCH);
7369
7490
  }
7370
7491
 
7371
7492
  if (srv_force_recovery >= SRV_FORCE_NO_IBUF_MERGE) {
7394
7515
  }
7395
7516
 
7396
7517
func_exit:
7397
 
  prebuilt->trx->op_info = (char*)"";
 
7518
  prebuilt->trx->op_info = "";
7398
7519
 
7399
7520
  return(0);
7400
7521
}
7445
7566
  }
7446
7567
 
7447
7568
  if (prebuilt->table->ibd_file_missing) {
7448
 
        errmsg_printf(ERRMSG_LVL_ERROR, "InnoDB: Error:\n"
 
7569
        errmsg_printf(error::ERROR, "InnoDB: Error:\n"
7449
7570
                    "InnoDB: MySQL is trying to use a table handle"
7450
7571
                    " but the .ibd file for\n"
7451
7572
                    "InnoDB: table %s does not exist.\n"
7605
7726
 
7606
7727
  update_session(getTable()->in_use);
7607
7728
 
7608
 
  prebuilt->trx->op_info = (char*)"returning table comment";
 
7729
  prebuilt->trx->op_info = "returning table comment";
7609
7730
 
7610
7731
  /* In case MySQL calls this in the middle of a SELECT query, release
7611
7732
  possible adaptive hash latch to avoid deadlocks of threads */
7650
7771
 
7651
7772
  mutex_exit(&srv_dict_tmpfile_mutex);
7652
7773
 
7653
 
  prebuilt->trx->op_info = (char*)"";
 
7774
  prebuilt->trx->op_info = "";
7654
7775
 
7655
7776
  return(str ? str : (char*) comment);
7656
7777
}
7676
7797
 
7677
7798
  update_session(getTable()->in_use);
7678
7799
 
7679
 
  prebuilt->trx->op_info = (char*)"getting info on foreign keys";
 
7800
  prebuilt->trx->op_info = "getting info on foreign keys";
7680
7801
 
7681
7802
  /* In case MySQL calls this in the middle of a SELECT query,
7682
7803
  release possible adaptive hash latch to avoid
7690
7811
  /* output the data to a temporary file */
7691
7812
  dict_print_info_on_foreign_keys(TRUE, srv_dict_tmpfile,
7692
7813
        prebuilt->trx, prebuilt->table);
7693
 
  prebuilt->trx->op_info = (char*)"";
 
7814
  prebuilt->trx->op_info = "";
7694
7815
 
7695
7816
  flen = ftell(srv_dict_tmpfile);
7696
7817
  if (flen < 0) {
7697
7818
    flen = 0;
7698
 
  } else if (flen > 64000 - 1) {
7699
 
    flen = 64000 - 1;
7700
7819
  }
7701
7820
 
7702
7821
  /* allocate buffer for the string, and
7720
7839
int
7721
7840
ha_innobase::get_foreign_key_list(Session *session, List<ForeignKeyInfo> *f_key_list)
7722
7841
{
7723
 
  dict_foreign_t* foreign;
7724
 
 
7725
7842
  ut_a(prebuilt != NULL);
7726
7843
  update_session(getTable()->in_use);
7727
 
  prebuilt->trx->op_info = (char*)"getting list of foreign keys";
 
7844
  prebuilt->trx->op_info = "getting list of foreign keys";
7728
7845
  trx_search_latch_release_if_reserved(prebuilt->trx);
7729
7846
  mutex_enter(&(dict_sys->mutex));
7730
 
  foreign = UT_LIST_GET_FIRST(prebuilt->table->foreign_list);
 
7847
  dict_foreign_t* foreign = UT_LIST_GET_FIRST(prebuilt->table->foreign_list);
7731
7848
 
7732
7849
  while (foreign != NULL) {
7733
7850
 
7734
 
    uint i;
7735
 
    LEX_STRING *name = 0;
7736
7851
    uint ulen;
7737
7852
    char uname[NAME_LEN + 1];           /* Unencoded name */
7738
7853
    char db_name[NAME_LEN + 1];
7740
7855
 
7741
7856
    /** Foreign id **/
7742
7857
    tmp_buff = foreign->id;
7743
 
    i = 0;
 
7858
    uint i = 0;
7744
7859
    while (tmp_buff[i] != '/')
7745
7860
      i++;
7746
7861
    tmp_buff += i + 1;
7747
 
    LEX_STRING *tmp_foreign_id = session->make_lex_string(NULL, tmp_buff, strlen(tmp_buff), true);
 
7862
    lex_string_t *tmp_foreign_id = session->make_lex_string(NULL, str_ref(tmp_buff));
7748
7863
 
7749
7864
    /* Database name */
7750
7865
    tmp_buff = foreign->referenced_table_name;
7756
7871
      i++;
7757
7872
    }
7758
7873
    db_name[i] = 0;
7759
 
    ulen= TableIdentifier::filename_to_tablename(db_name, uname, sizeof(uname));
7760
 
    LEX_STRING *tmp_referenced_db = session->make_lex_string(NULL, uname, ulen, true);
 
7874
    ulen= identifier::Table::filename_to_tablename(db_name, uname, sizeof(uname));
 
7875
    lex_string_t *tmp_referenced_db = session->make_lex_string(NULL, str_ref(uname, ulen));
7761
7876
 
7762
7877
    /* Table name */
7763
7878
    tmp_buff += i + 1;
7764
 
    ulen= TableIdentifier::filename_to_tablename(tmp_buff, uname, sizeof(uname));
7765
 
    LEX_STRING *tmp_referenced_table = session->make_lex_string(NULL, uname, ulen, true);
 
7879
    ulen= identifier::Table::filename_to_tablename(tmp_buff, uname, sizeof(uname));
 
7880
    lex_string_t *tmp_referenced_table = session->make_lex_string(NULL, str_ref(uname, ulen));
7766
7881
 
7767
7882
    /** Foreign Fields **/
7768
 
    List<LEX_STRING> tmp_foreign_fields;
7769
 
    List<LEX_STRING> tmp_referenced_fields;
7770
 
    for (i= 0;;) {
7771
 
      tmp_buff= foreign->foreign_col_names[i];
7772
 
      name = session->make_lex_string(name, tmp_buff, strlen(tmp_buff), true);
7773
 
      tmp_foreign_fields.push_back(name);
7774
 
      tmp_buff= foreign->referenced_col_names[i];
7775
 
      name = session->make_lex_string(name, tmp_buff, strlen(tmp_buff), true);
7776
 
      tmp_referenced_fields.push_back(name);
 
7883
    List<lex_string_t> tmp_foreign_fields;
 
7884
    List<lex_string_t> tmp_referenced_fields;
 
7885
    for (i= 0;;) 
 
7886
                {
 
7887
      tmp_foreign_fields.push_back(session->make_lex_string(NULL, str_ref(foreign->foreign_col_names[i])));
 
7888
      tmp_referenced_fields.push_back(session->make_lex_string(NULL, str_ref(foreign->referenced_col_names[i])));
7777
7889
      if (++i >= foreign->n_fields)
7778
7890
        break;
7779
7891
    }
7799
7911
      length=8;
7800
7912
      tmp_buff= "RESTRICT";
7801
7913
    }
7802
 
    LEX_STRING *tmp_delete_method = session->make_lex_string(NULL, tmp_buff, length, true);
 
7914
    lex_string_t *tmp_delete_method = session->make_lex_string(NULL, str_ref(tmp_buff, length));
7803
7915
 
7804
7916
 
7805
7917
    if (foreign->type & DICT_FOREIGN_ON_UPDATE_CASCADE)
7822
7934
      length=8;
7823
7935
      tmp_buff= "RESTRICT";
7824
7936
    }
7825
 
    LEX_STRING *tmp_update_method = session->make_lex_string(NULL, tmp_buff, length, true);
7826
 
 
7827
 
    LEX_STRING *tmp_referenced_key_name = NULL;
7828
 
 
7829
 
    if (foreign->referenced_index &&
7830
 
        foreign->referenced_index->name)
 
7937
    lex_string_t *tmp_update_method = session->make_lex_string(NULL, str_ref(tmp_buff, length));
 
7938
 
 
7939
    lex_string_t *tmp_referenced_key_name = NULL;
 
7940
 
 
7941
    if (foreign->referenced_index && foreign->referenced_index->name)
7831
7942
    {
7832
 
      tmp_referenced_key_name = session->make_lex_string(NULL,
7833
 
                                                         foreign->referenced_index->name, strlen(foreign->referenced_index->name), true);
 
7943
      tmp_referenced_key_name = session->make_lex_string(NULL, str_ref(foreign->referenced_index->name));
7834
7944
    }
7835
7945
 
7836
7946
    ForeignKeyInfo f_key_info(
7838
7948
                              tmp_update_method, tmp_delete_method, tmp_referenced_key_name,
7839
7949
                              tmp_foreign_fields, tmp_referenced_fields);
7840
7950
 
7841
 
    ForeignKeyInfo *pf_key_info = (ForeignKeyInfo *)
7842
 
      session->memdup(&f_key_info, sizeof(ForeignKeyInfo));
7843
 
    f_key_list->push_back(pf_key_info);
 
7951
    f_key_list->push_back((ForeignKeyInfo*)session->mem.memdup(&f_key_info, sizeof(ForeignKeyInfo)));
7844
7952
    foreign = UT_LIST_GET_NEXT(foreign_list, foreign);
7845
7953
  }
7846
7954
  mutex_exit(&(dict_sys->mutex));
7847
 
  prebuilt->trx->op_info = (char*)"";
 
7955
  prebuilt->trx->op_info = "";
7848
7956
 
7849
7957
  return(0);
7850
7958
}
7904
8012
/*======================================*/
7905
8013
  char* str)  /*!< in, own: create info string to free */
7906
8014
{
7907
 
  if (str) {
7908
 
    free(str);
7909
 
  }
 
8015
  free(str);
7910
8016
}
7911
8017
 
7912
8018
/*******************************************************************//**
8369
8475
static INNOBASE_SHARE* get_share(const char* table_name)
8370
8476
{
8371
8477
  INNOBASE_SHARE *share;
8372
 
  pthread_mutex_lock(&innobase_share_mutex);
 
8478
  boost::mutex::scoped_lock scopedLock(innobase_share_mutex);
8373
8479
 
8374
8480
  ulint fold = ut_fold_string(table_name);
8375
8481
 
8396
8502
  }
8397
8503
 
8398
8504
  share->use_count++;
8399
 
  pthread_mutex_unlock(&innobase_share_mutex);
8400
8505
 
8401
8506
  return(share);
8402
8507
}
8403
8508
 
8404
8509
static void free_share(INNOBASE_SHARE* share)
8405
8510
{
8406
 
  pthread_mutex_lock(&innobase_share_mutex);
 
8511
  boost::mutex::scoped_lock scopedLock(innobase_share_mutex);
8407
8512
 
8408
8513
#ifdef UNIV_DEBUG
8409
8514
  INNOBASE_SHARE* share2;
8422
8527
 
8423
8528
    HASH_DELETE(INNOBASE_SHARE, table_name_hash,
8424
8529
          innobase_open_tables, fold, share);
8425
 
    share->lock.deinit();
8426
8530
 
8427
8531
    /* Free any memory from index translation table */
8428
8532
    free(share->idx_trans_tbl.index_mapping);
8432
8536
    /* TODO: invoke HASH_MIGRATE if innobase_open_tables
8433
8537
    shrinks too much */
8434
8538
  }
8435
 
 
8436
 
  pthread_mutex_unlock(&innobase_share_mutex);
8437
8539
}
8438
8540
 
8439
8541
/*****************************************************************//**
8468
8570
  trx = check_trx_exists(session);
8469
8571
 
8470
8572
  assert(EQ_CURRENT_SESSION(session));
8471
 
  const uint32_t sql_command = session_sql_command(session);
 
8573
  const uint32_t sql_command = session->getSqlCommand();
8472
8574
 
8473
8575
  if (sql_command == SQLCOM_DROP_TABLE) {
8474
8576
 
8554
8656
 
8555
8657
    if ((lock_type >= TL_WRITE_CONCURRENT_INSERT
8556
8658
         && lock_type <= TL_WRITE)
8557
 
        && !session_tablespace_op(session)
 
8659
        && ! session->doing_tablespace_operation()
8558
8660
        && sql_command != SQLCOM_TRUNCATE
8559
8661
        && sql_command != SQLCOM_CREATE_TABLE) {
8560
8662
 
8631
8733
 
8632
8734
  if (auto_inc == 0) {
8633
8735
    ut_print_timestamp(stderr);
8634
 
    fprintf(stderr, "  InnoDB: AUTOINC next value generation "
8635
 
            "is disabled for '%s'\n", innodb_table->name);
 
8736
    errmsg_printf(error::ERROR, "  InnoDB: AUTOINC next value generation is disabled for '%s'\n", innodb_table->name);
8636
8737
  }
8637
8738
 
8638
8739
  dict_table_autoinc_unlock(innodb_table);
8787
8888
/* See comment in Cursor.cc */
8788
8889
UNIV_INTERN
8789
8890
bool
8790
 
InnobaseEngine::get_error_message(int, String *buf)
 
8891
InnobaseEngine::get_error_message(int, String *buf) const
8791
8892
{
8792
8893
  trx_t*  trx = check_trx_exists(current_session);
8793
8894
 
8871
8972
finds charset information and returns length of prefix_len characters in the
8872
8973
index field in bytes.
8873
8974
@return number of bytes occupied by the first n characters */
8874
 
extern "C" UNIV_INTERN
8875
 
ulint
8876
 
innobase_get_at_most_n_mbchars(
8877
 
/*===========================*/
8878
 
  ulint charset_id, /*!< in: character set id */
8879
 
  ulint prefix_len, /*!< in: prefix length in bytes of the index
8880
 
        (this has to be divided by mbmaxlen to get the
8881
 
        number of CHARACTERS n in the prefix) */
8882
 
  ulint data_len,   /*!< in: length of the string in bytes */
8883
 
  const char* str); /*!< in: character string */
8884
8975
 
8885
8976
ulint
8886
8977
innobase_get_at_most_n_mbchars(
8894
8985
{
8895
8986
  ulint char_length;    /*!< character length in bytes */
8896
8987
  ulint n_chars;      /*!< number of characters in prefix */
8897
 
  const CHARSET_INFO* charset;  /*!< charset used in the field */
 
8988
  const charset_info_st* charset;  /*!< charset used in the field */
8898
8989
 
8899
8990
  charset = get_charset((uint) charset_id);
8900
8991
 
8964
9055
  trx->detailed_error[0]= '\0';
8965
9056
 
8966
9057
  /* Set the isolation level of the transaction. */
8967
 
  trx->isolation_level= innobase_map_isolation_level(session_tx_isolation(session));
 
9058
  trx->isolation_level= innobase_map_isolation_level(session->getTxIsolation());
8968
9059
}
8969
9060
 
8970
9061
void
9007
9098
    return(0);
9008
9099
  }
9009
9100
 
9010
 
  session->get_xid(reinterpret_cast<DRIZZLE_XID*>(&trx->xid));
 
9101
  session->get_xid(reinterpret_cast<DrizzleXid*>(&trx->xid));
9011
9102
 
9012
9103
  /* Release a possible FIFO ticket and search latch. Since we will
9013
9104
  reserve the kernel mutex, we have to release the search system latch
9228
9319
          "Number of UNDO logs to purge in one batch from the history list. "
9229
9320
          "Default is 20.");
9230
9321
  context("purge-threads",
9231
 
          po::value<purge_threads_constraint>(&innodb_n_purge_threads)->default_value(0),
9232
 
          "Purge threads can be either 0 or 1. Defalut is 0.");
 
9322
          po::value<purge_threads_constraint>(&innodb_n_purge_threads)->default_value(1),
 
9323
          "Purge threads can be either 0 or 1. Default is 1.");
9233
9324
  context("file-per-table",
9234
9325
          po::value<bool>(&srv_file_per_table)->default_value(false)->zero_tokens(),
9235
 
          "Stores each InnoDB table to an .ibd file in the database dir.");
9236
 
  context("file-format",
9237
 
          po::value<string>(&innobase_file_format_name)->default_value("Antelope"),
9238
 
          "File format to use for new tables in .ibd files.");
 
9326
           "Stores each InnoDB table to an .ibd file in the database dir.");
9239
9327
  context("file-format-max",
9240
9328
          po::value<string>(&innobase_file_format_max)->default_value("Antelope"),
9241
9329
          "The highest file format in the tablespace.");
9242
9330
  context("file-format-check",
9243
9331
          po::value<bool>(&innobase_file_format_check)->default_value(true)->zero_tokens(),
9244
9332
          "Whether to perform system file format check.");
 
9333
  context("file-format",
 
9334
          po::value<string>(&innobase_file_format_name)->default_value("Antelope"),
 
9335
          "File format to use for new tables in .ibd files.");
9245
9336
  context("flush-log-at-trx-commit",
9246
9337
          po::value<trinary_constraint>(&innodb_flush_log_at_trx_commit)->default_value(1),
9247
9338
          "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).");
9276
9367
          po::value<additional_mem_pool_constraint>(&innobase_additional_mem_pool_size)->default_value(8*1024*1024L),
9277
9368
          "Size of a memory pool InnoDB uses to store data dictionary information and other internal data structures.");
9278
9369
  context("autoextend-increment",
9279
 
          po::value<autoextend_constraint>(&innodb_auto_extend_increment)->default_value(8L),
 
9370
          po::value<autoextend_constraint>(&innodb_auto_extend_increment)->default_value(64L),
9280
9371
          "Data file autoextend increment in megabytes");
9281
9372
  context("buffer-pool-size",
9282
9373
          po::value<buffer_pool_constraint>(&innobase_buffer_pool_size)->default_value(128*1024*1024L),
9306
9397
  context("log-file-size",
9307
9398
          po::value<log_file_constraint>(&innobase_log_file_size)->default_value(20*1024*1024L),
9308
9399
          "The size of the buffer which InnoDB uses to write log to the log files on disk.");
 
9400
  context("page-size",
 
9401
          po::value<page_size_constraint>(&innobase_page_size)->default_value(1 << 14),
 
9402
          "###EXPERIMENTAL###: The universal page size of the database. Changing for created database is not supported. Use on your own risk!");
 
9403
  context("log-block-size",
 
9404
          po::value<log_block_size_constraint>(&innobase_log_block_size)->default_value(1 << 9),
 
9405
          "###EXPERIMENTAL###: The log block size of the transaction log file. Changing for created log file is not supported. Use on your own risk!");
9309
9406
  context("log-files-in-group",
9310
9407
          po::value<log_files_in_group_constraint>(&innobase_log_files_in_group)->default_value(2),
9311
9408
          "Number of log files in the log group. InnoDB writes to the files in a circular fashion.");
9335
9432
          "InnoDB version");
9336
9433
  context("use-internal-malloc",
9337
9434
          "Use InnoDB's internal memory allocator instal of the OS memory allocator.");
 
9435
  context("disable-native-aio",
 
9436
          _("Do not use Native AIO library for IO, even if available"));
9338
9437
  context("change-buffering",
9339
9438
          po::value<string>(&innobase_change_buffering),
9340
9439
          "Buffer changes to reduce random access: OFF, ON, inserting, deleting, changing, or purging.");
9341
9440
  context("read-ahead-threshold",
9342
9441
          po::value<read_ahead_threshold_constraint>(&innodb_read_ahead_threshold)->default_value(56),
9343
9442
          "Number of pages that must be accessed sequentially for InnoDB to trigger a readahead.");
 
9443
  context("auto-lru-dump",
 
9444
          po::value<uint32_constraint>(&buffer_pool_restore_at_startup)->default_value(0),
 
9445
          "Time in seconds between automatic buffer pool dumps. "
 
9446
          "0 (the default) disables automatic dumps.");
 
9447
  context("ibuf-max-size",
 
9448
          po::value<uint64_constraint>(&ibuf_max_size)->default_value(UINT64_MAX),
 
9449
          "The maximum size of the insert buffer (in bytes).");
 
9450
  context("ibuf-active-contract",
 
9451
          po::value<binary_constraint>(&ibuf_active_contract)->default_value(1),
 
9452
          "Enable/Disable active_contract of insert buffer. 0:disable 1:enable");
 
9453
  context("ibuf-accel-rate",
 
9454
          po::value<ibuf_accel_rate_constraint>(&ibuf_accel_rate)->default_value(100),
 
9455
          "Tunes amount of insert buffer processing of background, in addition to innodb_io_capacity. (in percentage)");
 
9456
  context("checkpoint-age-target",
 
9457
          po::value<uint32_constraint>(&checkpoint_age_target)->default_value(0),
 
9458
          "Control soft limit of checkpoint age. (0 : not control)");
 
9459
  context("flush-neighbor-pages",
 
9460
          po::value<binary_constraint>(&flush_neighbor_pages)->default_value(1),
 
9461
          "Enable/Disable flushing also neighbor pages. 0:disable 1:enable");
 
9462
  context("read-ahead",
 
9463
          po::value<string>(&read_ahead)->default_value("linear"),
 
9464
          "Control read ahead activity (none, random, [linear], both). [from 1.0.5: random read ahead is ignored]");
 
9465
  context("adaptive-flushing-method",
 
9466
          po::value<string>(&adaptive_flushing_method)->default_value("estimate"),
 
9467
          "Choose method of innodb_adaptive_flushing. (native, [estimate], keep_average)");
9344
9468
  context("disable-xa",
9345
9469
          "Disable InnoDB support for the XA two-phase commit");
9346
9470
  context("disable-table-locks",
9349
9473
          po::value<bool>(&strict_mode)->default_value(false)->zero_tokens(),
9350
9474
          "Use strict mode when evaluating create options.");
9351
9475
  context("replication-log",
9352
 
          po::value<bool>(&innobase_use_replication_log)->default_value(false),
 
9476
          po::value<bool>(&innobase_use_replication_log)->default_value(false)->zero_tokens(),
9353
9477
          _("Enable internal replication log."));
9354
9478
  context("lock-wait-timeout",
9355
9479
          po::value<lock_wait_constraint>(&lock_wait_timeout)->default_value(50),
9375
9499
  "Supports transactions, row-level locking, and foreign keys",
9376
9500
  PLUGIN_LICENSE_GPL,
9377
9501
  innobase_init, /* Plugin Init */
9378
 
  NULL, /* system variables */
 
9502
  NULL, /* depends */
9379
9503
  init_options /* reserved */
9380
9504
}
9381
9505
DRIZZLE_DECLARE_PLUGIN_END;
9407
9531
This function checks each index name for a table against reserved
9408
9532
system default primary index name 'GEN_CLUST_INDEX'. If a name matches,
9409
9533
this function pushes an warning message to the client, and returns true. */
9410
 
extern "C" UNIV_INTERN
 
9534
UNIV_INTERN
9411
9535
bool
9412
9536
innobase_index_name_is_reserved(
9413
9537
/*============================*/
9427
9551
    if (innobase_strcasecmp(key->name,
9428
9552
                            innobase_index_reserve_name) == 0) {
9429
9553
      /* Push warning to drizzle */
9430
 
      push_warning_printf((Session*)trx->mysql_thd,
 
9554
      push_warning_printf(trx->mysql_thd,
9431
9555
                          DRIZZLE_ERROR::WARN_LEVEL_WARN,
9432
9556
                          ER_WRONG_NAME_FOR_INDEX,
9433
9557
                          "Cannot Create Index with name "
9453
9577
  ulint   buflen;
9454
9578
  const char* id;
9455
9579
  ulint   idlen;
9456
 
  void*   session;
 
9580
  drizzled::Session *session;
9457
9581
  ibool   file_id;
9458
9582
 
9459
9583
  const char* expected;