~drizzle-trunk/drizzle/development

« back to all changes in this revision

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

  • Committer: Lee Bieber
  • Date: 2011-03-29 22:31:41 UTC
  • mfrom: (2257.1.3 build)
  • Revision ID: kalebral@gmail.com-20110329223141-yxc22h3l2he58sk0
Merge Andrew - 743842: Build failure using GCC 4.6
Merge Stewart - 738022: CachedDirectory silently fails to add entries if stat() fails
Merge Olaf - Common fwd: add copyright, add more declaration

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/charset_info.h>
 
49
#include <drizzled/internal/m_string.h>
 
50
#include <drizzled/internal/my_sys.h>
 
51
#include <drizzled/plugin.h>
 
52
#include <drizzled/show.h>
 
53
#include <drizzled/data_home.h>
 
54
#include <drizzled/error.h>
 
55
#include <drizzled/field.h>
 
56
#include <drizzled/charset.h>
 
57
#include <drizzled/session.h>
 
58
#include <drizzled/current_session.h>
 
59
#include <drizzled/table.h>
 
60
#include <drizzled/field/blob.h>
 
61
#include <drizzled/field/varstring.h>
 
62
#include <drizzled/plugin/xa_storage_engine.h>
 
63
#include <drizzled/plugin/daemon.h>
 
64
#include <drizzled/memory/multi_malloc.h>
 
65
#include <drizzled/pthread_globals.h>
 
66
#include <drizzled/named_savepoint.h>
 
67
#include <drizzled/session/table_messages.h>
70
68
#include <drizzled/transaction_services.h>
71
 
#include "drizzled/message/statement_transform.h"
 
69
#include <drizzled/message/statement_transform.h>
 
70
#include <drizzled/cached_directory.h>
 
71
#include <drizzled/statistics_variables.h>
 
72
#include <drizzled/system_variables.h>
 
73
#include <drizzled/session/transactions.h>
72
74
 
73
75
#include <boost/algorithm/string.hpp>
74
76
#include <boost/program_options.hpp>
 
77
#include <boost/scoped_array.hpp>
75
78
#include <boost/filesystem.hpp>
76
79
#include <drizzled/module/option_map.h>
77
80
#include <iostream>
83
86
/** @file ha_innodb.cc */
84
87
 
85
88
/* Include necessary InnoDB headers */
86
 
extern "C" {
87
89
#include "univ.i"
88
90
#include "buf0lru.h"
89
91
#include "btr0sea.h"
115
117
#include "ha_prototypes.h"
116
118
#include "ut0mem.h"
117
119
#include "ibuf0ibuf.h"
118
 
#include "mysql_addons.h"
119
 
}
120
120
 
121
121
#include "ha_innodb.h"
122
122
#include "data_dictionary.h"
128
128
#include <sstream>
129
129
#include <string>
130
130
 
131
 
#include "plugin/innobase/handler/status_function.h"
132
 
#include "plugin/innobase/handler/replication_log.h"
 
131
#include <plugin/innobase/handler/status_function.h>
 
132
#include <plugin/innobase/handler/replication_log.h>
133
133
 
134
134
#include <google/protobuf/io/zero_copy_stream.h>
135
135
#include <google/protobuf/io/zero_copy_stream_impl.h>
136
136
#include <google/protobuf/io/coded_stream.h>
137
137
#include <google/protobuf/text_format.h>
138
138
 
 
139
#include <boost/thread/mutex.hpp>
 
140
 
139
141
using namespace std;
140
142
using namespace drizzled;
141
143
 
142
144
/** to protect innobase_open_files */
143
 
static pthread_mutex_t innobase_share_mutex;
 
145
static boost::mutex innobase_share_mutex;
 
146
 
144
147
/** to force correct commit order in binlog */
145
 
static pthread_mutex_t prepare_commit_mutex;
146
148
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;
 
149
static boost::condition_variable commit_cond;
 
150
static boost::mutex commit_cond_m;
150
151
static bool innodb_inited = 0;
151
152
 
152
153
#define INSIDE_HA_INNOBASE_CC
162
163
#endif /* MYSQL_DYNAMIC_PLUGIN && __WIN__ */
163
164
 
164
165
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;
 
166
 
183
167
typedef constrained_check<uint32_t, UINT32_MAX, 10> open_files_constraint;
184
168
static open_files_constraint innobase_open_files;
185
169
typedef constrained_check<uint32_t, 10, 1> mirrored_log_groups_constraint;
204
188
static purge_batch_constraint innodb_purge_batch_size;
205
189
typedef constrained_check<uint32_t, 1, 0> purge_threads_constraint;
206
190
static purge_threads_constraint innodb_n_purge_threads;
207
 
typedef constrained_check<uint16_t, 2, 0> trinary_constraint;
 
191
typedef constrained_check<uint32_t, 2, 0> trinary_constraint;
208
192
static trinary_constraint innodb_flush_log_at_trx_commit;
209
193
typedef constrained_check<unsigned int, 99, 0> max_dirty_pages_constraint;
210
194
static max_dirty_pages_constraint innodb_max_dirty_pages_pct;
253
237
/* Below we have boolean-valued start-up parameters, and their default
254
238
values */
255
239
 
256
 
typedef constrained_check<uint16_t, 2, 0> trinary_constraint;
 
240
typedef constrained_check<uint32_t, 2, 0> trinary_constraint;
257
241
static trinary_constraint innobase_fast_shutdown;
258
242
 
259
243
/* "innobase_file_format_check" decides whether we would continue
340
324
 
341
325
  virtual ~InnobaseEngine()
342
326
  {
343
 
    int err= 0;
344
327
    if (innodb_inited) {
345
328
      srv_fast_shutdown = (ulint) innobase_fast_shutdown;
346
329
      innodb_inited = 0;
347
330
      hash_table_free(innobase_open_tables);
348
331
      innobase_open_tables = NULL;
349
332
      if (innobase_shutdown_for_mysql() != DB_SUCCESS) {
350
 
        err = 1;
 
333
        // Throw here?
351
334
      }
352
335
      srv_free_paths_and_sizes();
353
336
      if (internal_innobase_data_file_path)
354
337
        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);
360
338
    }
361
339
    
362
340
    /* These get strdup'd from vm variables */
446
424
  doDropSchema(
447
425
  /*===================*/
448
426
        /* out: error number */
449
 
    const SchemaIdentifier  &identifier); /* in: database path; inside InnoDB the name
 
427
    const identifier::Schema  &identifier); /* in: database path; inside InnoDB the name
450
428
        of the last directory in the path is used as
451
429
        the database name: for example, in 'mysql/data/test'
452
430
        the database name is 'test' */
485
463
 
486
464
  UNIV_INTERN int doCreateTable(Session &session,
487
465
                                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);
 
466
                                const identifier::Table &identifier,
 
467
                                const message::Table&);
 
468
  UNIV_INTERN int doRenameTable(Session&, const identifier::Table &from, const identifier::Table &to);
 
469
  UNIV_INTERN int doDropTable(Session &session, const identifier::Table &identifier);
492
470
 
493
 
  UNIV_INTERN virtual bool get_error_message(int error, String *buf);
 
471
  UNIV_INTERN virtual bool get_error_message(int error, String *buf) const;
494
472
 
495
473
  UNIV_INTERN uint32_t max_supported_keys() const;
496
474
  UNIV_INTERN uint32_t max_supported_key_length() const;
507
485
  }
508
486
 
509
487
  int doGetTableDefinition(drizzled::Session& session,
510
 
                           const TableIdentifier &identifier,
 
488
                           const identifier::Table &identifier,
511
489
                           drizzled::message::Table &table_proto);
512
490
 
513
 
  bool doDoesTableExist(drizzled::Session& session, const TableIdentifier &identifier);
 
491
  bool doDoesTableExist(drizzled::Session& session, const identifier::Table &identifier);
514
492
 
515
493
  void doGetTableIdentifiers(drizzled::CachedDirectory &directory,
516
 
                             const drizzled::SchemaIdentifier &schema_identifier,
517
 
                             drizzled::TableIdentifier::vector &set_of_identifiers);
 
494
                             const drizzled::identifier::Schema &schema_identifier,
 
495
                             drizzled::identifier::table::vector &set_of_identifiers);
518
496
  bool validateCreateTableOption(const std::string &key, const std::string &state);
519
497
  void dropTemporarySchema();
520
498
 
542
520
}
543
521
 
544
522
void InnobaseEngine::doGetTableIdentifiers(drizzled::CachedDirectory &directory,
545
 
                                           const drizzled::SchemaIdentifier &schema_identifier,
546
 
                                           drizzled::TableIdentifier::vector &set_of_identifiers)
 
523
                                           const drizzled::identifier::Schema &schema_identifier,
 
524
                                           drizzled::identifier::table::vector &set_of_identifiers)
547
525
{
548
526
  CachedDirectory::Entries entries= directory.getEntries();
549
527
 
 
528
  std::string search_string(schema_identifier.getSchemaName());
 
529
 
 
530
  boost::algorithm::to_lower(search_string);
 
531
 
 
532
  if (search_string.compare("data_dictionary") == 0)
 
533
  {
 
534
    set_of_identifiers.push_back(identifier::Table(schema_identifier.getSchemaName(), "SYS_REPLICATION_LOG"));
 
535
  }
 
536
 
550
537
  for (CachedDirectory::Entries::iterator entry_iter= entries.begin(); 
551
538
       entry_iter != entries.end(); ++entry_iter)
552
539
  {
574
561
           Using schema_identifier here to stop unused warning, could use
575
562
           definition.schema() instead
576
563
        */
577
 
        TableIdentifier identifier(schema_identifier.getSchemaName(), definition.name());
 
564
        identifier::Table identifier(schema_identifier.getSchemaName(), definition.name());
578
565
        set_of_identifiers.push_back(identifier);
579
566
      }
580
567
    }
581
568
  }
582
569
}
583
570
 
584
 
bool InnobaseEngine::doDoesTableExist(Session &session, const TableIdentifier &identifier)
 
571
bool InnobaseEngine::doDoesTableExist(Session &session, const identifier::Table &identifier)
585
572
{
586
573
  string proto_path(identifier.getPath());
587
574
  proto_path.append(DEFAULT_FILE_EXTENSION);
589
576
  if (session.getMessageCache().doesTableMessageExist(identifier))
590
577
    return true;
591
578
 
 
579
  std::string search_string(identifier.getPath());
 
580
  boost::algorithm::to_lower(search_string);
 
581
 
 
582
  if (search_string.compare("data_dictionary/sys_replication_log") == 0)
 
583
    return true;
 
584
 
592
585
  if (access(proto_path.c_str(), F_OK))
593
586
  {
594
587
    return false;
598
591
}
599
592
 
600
593
int InnobaseEngine::doGetTableDefinition(Session &session,
601
 
                                         const TableIdentifier &identifier,
 
594
                                         const identifier::Table &identifier,
602
595
                                         message::Table &table_proto)
603
596
{
604
597
  string proto_path(identifier.getPath());
608
601
  if (session.getMessageCache().getTableMessage(identifier, table_proto))
609
602
    return EEXIST;
610
603
 
 
604
  if (read_replication_log_table_message(identifier.getTableName().c_str(), &table_proto) == 0)
 
605
    return EEXIST;
 
606
 
611
607
  if (access(proto_path.c_str(), F_OK))
612
608
  {
613
609
    return errno;
804
800
DRIZZLE: Note, we didn't change this name to avoid more ifdef forking 
805
801
         in non-Cursor code.
806
802
@return true if session is the replication thread */
807
 
extern "C" UNIV_INTERN
 
803
UNIV_INTERN
808
804
ibool
809
805
thd_is_replication_slave_thread(
810
806
/*============================*/
811
 
  void* ) /*!< in: thread handle (Session*) */
 
807
  drizzled::Session* ) /*!< in: thread handle (Session*) */
812
808
{
813
809
  return false;
814
810
}
878
874
DRIZZLE: Note, we didn't change this name to avoid more ifdef forking 
879
875
         in non-Cursor code.
880
876
@return true if non-transactional tables have been edited */
881
 
extern "C" UNIV_INTERN
 
877
UNIV_INTERN
882
878
ibool
883
879
thd_has_edited_nontrans_tables(
884
880
/*===========================*/
885
 
  void*   session)  /*!< in: thread handle (Session*) */
 
881
  drizzled::Session *session)  /*!< in: thread handle (Session*) */
886
882
{
887
 
  return((ibool)((Session *)session)->transaction.all.hasModifiedNonTransData());
 
883
  return((ibool)session->transaction.all.hasModifiedNonTransData());
888
884
}
889
885
 
890
886
/******************************************************************//**
891
887
Returns true if the thread is executing a SELECT statement.
892
888
@return true if session is executing SELECT */
893
 
extern "C" UNIV_INTERN
 
889
UNIV_INTERN
894
890
ibool
895
891
thd_is_select(
896
892
/*==========*/
897
 
  const void* session)  /*!< in: thread handle (Session*) */
 
893
  const drizzled::Session *session)  /*!< in: thread handle (Session*) */
898
894
{
899
 
  return(session_sql_command((const Session*) session) == SQLCOM_SELECT);
 
895
  return(session->getSqlCommand() == SQLCOM_SELECT);
900
896
}
901
897
 
902
898
/******************************************************************//**
903
899
Returns true if the thread supports XA,
904
900
global value of innodb_supports_xa if session is NULL.
905
901
@return true if session has XA support */
906
 
extern "C" UNIV_INTERN
 
902
UNIV_INTERN
907
903
ibool
908
904
thd_supports_xa(
909
905
/*============*/
910
 
  void* )  /*!< in: thread handle (Session*), or NULL to query
 
906
  drizzled::Session* )  /*!< in: thread handle (Session*), or NULL to query
911
907
        the global innodb_supports_xa */
912
908
{
913
909
  /* TODO: Add support here for per-session value */
917
913
/******************************************************************//**
918
914
Returns the lock wait timeout for the current connection.
919
915
@return the lock wait timeout, in seconds */
920
 
extern "C" UNIV_INTERN
 
916
UNIV_INTERN
921
917
ulong
922
918
thd_lock_wait_timeout(
923
919
/*==================*/
924
 
  void*)  /*!< in: thread handle (Session*), or NULL to query
 
920
  drizzled::Session*)  /*!< in: thread handle (Session*), or NULL to query
925
921
      the global innodb_lock_wait_timeout */
926
922
{
927
923
  /* TODO: Add support here for per-session value */
932
928
 
933
929
/******************************************************************//**
934
930
Set the time waited for the lock for the current query. */
935
 
extern "C" UNIV_INTERN
 
931
UNIV_INTERN
936
932
void
937
933
thd_set_lock_wait_time(
938
934
/*===================*/
939
 
        void*   thd,    /*!< in: thread handle (THD*) */
 
935
        drizzled::Session*      in_session,     /*!< in: thread handle (THD*) */
940
936
        ulint   value)  /*!< in: time waited for the lock */
941
937
{
942
 
        if (thd) {
943
 
          static_cast<Session*>(thd)->utime_after_lock+= value;
944
 
        }
 
938
  if (in_session)
 
939
    in_session->utime_after_lock+= value;
945
940
}
946
941
 
947
942
/********************************************************************//**
967
962
  trx_t *trx= session_to_trx(&session);
968
963
 
969
964
  uint64_t trx_id= message.transaction_context().transaction_id();
970
 
  ulint error= insert_replication_message(data, message.ByteSize(), trx, trx_id);
 
965
  uint32_t seg_id= message.segment_id();
 
966
  uint64_t end_timestamp= message.transaction_context().end_timestamp();
 
967
  bool is_end_segment= message.end_segment();
 
968
  trx->log_commit_id= TRUE;
 
969
  ulint error= insert_replication_message(data, message.ByteSize(), trx, trx_id,
 
970
               end_timestamp, is_end_segment, seg_id);
971
971
  (void)error;
972
972
 
973
973
  delete[] data;
1024
1024
about a possible transaction rollback inside InnoDB caused by a lock wait
1025
1025
timeout or a deadlock.
1026
1026
@return MySQL error code */
1027
 
extern "C" UNIV_INTERN
 
1027
UNIV_INTERN
1028
1028
int
1029
1029
convert_error_code_to_mysql(
1030
1030
/*========================*/
1078
1078
    tell it also to MySQL so that MySQL knows to empty the
1079
1079
    cached binlog for this transaction */
1080
1080
 
1081
 
    mark_transaction_to_rollback(session, TRUE);
 
1081
    session->markTransactionForRollback(TRUE);
1082
1082
 
1083
1083
    return(HA_ERR_LOCK_DEADLOCK);
1084
1084
 
1087
1087
    latest SQL statement in a lock wait timeout. Previously, we
1088
1088
    rolled back the whole transaction. */
1089
1089
 
1090
 
    mark_transaction_to_rollback(session, (bool)row_rollback_on_timeout);
 
1090
    session->markTransactionForRollback((bool)row_rollback_on_timeout);
1091
1091
 
1092
1092
    return(HA_ERR_LOCK_WAIT_TIMEOUT);
1093
1093
 
1098
1098
    return(HA_ERR_ROW_IS_REFERENCED);
1099
1099
 
1100
1100
  case DB_CANNOT_ADD_CONSTRAINT:
 
1101
  case DB_CHILD_NO_INDEX:
 
1102
  case DB_PARENT_NO_INDEX:
1101
1103
    return(HA_ERR_CANNOT_ADD_FOREIGN);
1102
1104
 
1103
1105
  case DB_CANNOT_DROP_CONSTRAINT:
1121
1123
 
1122
1124
  case DB_TOO_BIG_RECORD:
1123
1125
    my_error(ER_TOO_BIG_ROWSIZE, MYF(0),
1124
 
       page_get_free_space_of_empty(flags
1125
 
                  & DICT_TF_COMPACT) / 2);
 
1126
             page_get_free_space_of_empty(flags & DICT_TF_COMPACT) / 2);
1126
1127
    return(HA_ERR_TO_BIG_ROW);
1127
1128
 
1128
1129
  case DB_NO_SAVEPOINT:
1133
1134
    tell it also to MySQL so that MySQL knows to empty the
1134
1135
    cached binlog for this transaction */
1135
1136
 
1136
 
    mark_transaction_to_rollback(session, TRUE);
 
1137
    session->markTransactionForRollback(TRUE);
1137
1138
 
1138
1139
    return(HA_ERR_LOCK_TABLE_FULL);
1139
1140
 
1167
1168
 
1168
1169
/*************************************************************//**
1169
1170
Prints info of a Session object (== user session thread) to the given file. */
1170
 
extern "C" UNIV_INTERN
 
1171
UNIV_INTERN
1171
1172
void
1172
1173
innobase_mysql_print_thd(
1173
1174
/*=====================*/
1174
1175
  FILE* f,    /*!< in: output stream */
1175
 
  void * in_session,  /*!< in: pointer to a Drizzle Session object */
 
1176
  drizzled::Session *in_session,  /*!< in: pointer to a Drizzle Session object */
1176
1177
  uint  )   /*!< in: max query length to print, or 0 to
1177
1178
           use the default max length */
1178
1179
{
1179
 
  Session *session= reinterpret_cast<Session *>(in_session);
1180
 
  drizzled::identifier::User::const_shared_ptr user_identifier(session->user());
 
1180
  drizzled::identifier::user::ptr user_identifier(in_session->user());
1181
1181
 
1182
1182
  fprintf(f,
1183
1183
          "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,
 
1184
          static_cast<uint64_t>(in_session->getSessionId()),
 
1185
          static_cast<uint64_t>(in_session->getQueryId()),
 
1186
          getServerHostname().c_str(),
1187
1187
          user_identifier->address().c_str(),
1188
1188
          user_identifier->username().c_str()
1189
1189
  );
1190
 
  fprintf(f, "\n%s", session->getQueryString()->c_str());
 
1190
  fprintf(f, "\n%s", in_session->getQueryString()->c_str());
1191
1191
  putc('\n', f);
1192
1192
}
1193
1193
 
1194
1194
/******************************************************************//**
1195
1195
Get the variable length bounds of the given character set. */
1196
 
extern "C" UNIV_INTERN
 
1196
UNIV_INTERN
1197
1197
void
1198
1198
innobase_get_cset_width(
1199
1199
/*====================*/
1201
1201
  ulint*  mbminlen, /*!< out: minimum length of a char (in bytes) */
1202
1202
  ulint*  mbmaxlen) /*!< out: maximum length of a char (in bytes) */
1203
1203
{
1204
 
  CHARSET_INFO* cs;
 
1204
  charset_info_st* cs;
1205
1205
  ut_ad(cset < 256);
1206
1206
  ut_ad(mbminlen);
1207
1207
  ut_ad(mbmaxlen);
1220
1220
 
1221
1221
/******************************************************************//**
1222
1222
Converts an identifier to a table name. */
1223
 
extern "C" UNIV_INTERN
 
1223
UNIV_INTERN
1224
1224
void
1225
1225
innobase_convert_from_table_id(
1226
1226
/*===========================*/
1234
1234
 
1235
1235
/******************************************************************//**
1236
1236
Converts an identifier to UTF-8. */
1237
 
extern "C" UNIV_INTERN
 
1237
UNIV_INTERN
1238
1238
void
1239
1239
innobase_convert_from_id(
1240
1240
/*=====================*/
1249
1249
/******************************************************************//**
1250
1250
Compares NUL-terminated UTF-8 strings case insensitively.
1251
1251
@return 0 if a=b, <0 if a<b, >1 if a>b */
1252
 
extern "C" UNIV_INTERN
 
1252
UNIV_INTERN
1253
1253
int
1254
1254
innobase_strcasecmp(
1255
1255
/*================*/
1261
1261
 
1262
1262
/******************************************************************//**
1263
1263
Makes all characters in a NUL-terminated UTF-8 string lower case. */
1264
 
extern "C" UNIV_INTERN
 
1264
UNIV_INTERN
1265
1265
void
1266
1266
innobase_casedn_str(
1267
1267
/*================*/
1270
1270
  my_casedn_str(system_charset_info, a);
1271
1271
}
1272
1272
 
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
 
1273
UNIV_INTERN
1286
1274
bool
1287
1275
innobase_isspace(
1288
1276
  const void *cs,
1289
1277
  char char_to_test)
1290
1278
{
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);
 
1279
  return my_isspace(static_cast<const charset_info_st *>(cs), char_to_test);
1313
1280
}
1314
1281
 
1315
1282
#if defined (__WIN__) && defined (MYSQL_DYNAMIC_PLUGIN)
1316
1283
/*******************************************************************//**
1317
1284
Map an OS error to an errno value. The OS error number is stored in
1318
1285
_doserrno and the mapped value is stored in errno) */
1319
 
extern "C"
1320
1286
void __cdecl
1321
1287
_dosmaperr(
1322
1288
  unsigned long); /*!< in: OS error value */
1324
1290
/*********************************************************************//**
1325
1291
Creates a temporary file.
1326
1292
@return temporary file descriptor, or < 0 on error */
1327
 
extern "C" UNIV_INTERN
 
1293
UNIV_INTERN
1328
1294
int
1329
1295
innobase_mysql_tmpfile(void)
1330
1296
/*========================*/
1404
1370
/*********************************************************************//**
1405
1371
Creates a temporary file.
1406
1372
@return temporary file descriptor, or < 0 on error */
1407
 
extern "C" UNIV_INTERN
 
1373
UNIV_INTERN
1408
1374
int
1409
1375
innobase_mysql_tmpfile(void)
1410
1376
/*========================*/
1411
1377
{
1412
1378
  int fd2 = -1;
1413
 
  int fd = mysql_tmpfile("ib");
 
1379
  int fd = ::drizzled::tmpfile("ib");
1414
1380
  if (fd >= 0) {
1415
1381
    /* Copy the file descriptor, so that the additional resources
1416
1382
    allocated by create_temp_file() can be freed by invoking
1443
1409
number of bytes that were written to "buf" is returned (including the
1444
1410
terminating NUL).
1445
1411
@return number of bytes that were written */
1446
 
extern "C" UNIV_INTERN
 
1412
UNIV_INTERN
1447
1413
ulint
1448
1414
innobase_raw_format(
1449
1415
/*================*/
1563
1529
/*********************************************************************//**
1564
1530
Allocates an InnoDB transaction for a MySQL Cursor object.
1565
1531
@return InnoDB transaction handle */
1566
 
extern "C" UNIV_INTERN
 
1532
UNIV_INTERN
1567
1533
trx_t*
1568
1534
innobase_trx_allocate(
1569
1535
/*==================*/
1667
1633
  ulint   buflen, /*!< in: length of buf, in bytes */
1668
1634
  const char* id, /*!< in: identifier to convert */
1669
1635
  ulint   idlen,  /*!< in: length of id, in bytes */
1670
 
  void*   session,/*!< in: MySQL connection thread, or NULL */
 
1636
  drizzled::Session *session,/*!< in: MySQL connection thread, or NULL */
1671
1637
  ibool   file_id)/*!< in: TRUE=id is a table or database name;
1672
1638
        FALSE=id is an UTF-8 string */
1673
1639
{
1674
1640
  char nz[NAME_LEN + 1];
1675
 
  char nz2[NAME_LEN + 1 + sizeof srv_mysql50_table_name_prefix];
 
1641
  const size_t nz2_size= NAME_LEN + 1 + srv_mysql50_table_name_prefix.size();
 
1642
  boost::scoped_array<char> nz2(new char[nz2_size]);
1676
1643
 
1677
1644
  const char* s = id;
1678
1645
  int   q;
1689
1656
    memcpy(nz, id, idlen);
1690
1657
    nz[idlen] = 0;
1691
1658
 
1692
 
    s = nz2;
1693
 
    idlen = TableIdentifier::filename_to_tablename(nz, nz2, sizeof nz2);
 
1659
    s = nz2.get();
 
1660
    idlen = identifier::Table::filename_to_tablename(nz, nz2.get(), nz2_size);
1694
1661
  }
1695
1662
 
1696
1663
  /* See if the identifier needs to be quoted. */
1744
1711
Convert a table or index name to the MySQL system_charset_info (UTF-8)
1745
1712
and quote it if needed.
1746
1713
@return pointer to the end of buf */
1747
 
extern "C" UNIV_INTERN
 
1714
UNIV_INTERN
1748
1715
char*
1749
1716
innobase_convert_name(
1750
1717
/*==================*/
1752
1719
  ulint   buflen, /*!< in: length of buf, in bytes */
1753
1720
  const char* id, /*!< in: identifier to convert */
1754
1721
  ulint   idlen,  /*!< in: length of id, in bytes */
1755
 
  void*   session,/*!< in: MySQL connection thread, or NULL */
 
1722
  drizzled::Session *session,/*!< in: MySQL connection thread, or NULL */
1756
1723
  ibool   table_id)/*!< in: TRUE=id is a table or database name;
1757
1724
        FALSE=id is an index name */
1758
1725
{
1800
1767
/**********************************************************************//**
1801
1768
Determines if the currently running transaction has been interrupted.
1802
1769
@return TRUE if interrupted */
1803
 
extern "C" UNIV_INTERN
 
1770
UNIV_INTERN
1804
1771
ibool
1805
1772
trx_is_interrupted(
1806
1773
/*===============*/
1807
1774
  trx_t*  trx)  /*!< in: transaction */
1808
1775
{
1809
 
  return(trx && trx->mysql_thd && static_cast<Session*>(trx->mysql_thd)->getKilled());
 
1776
  return(trx && trx->mysql_thd && trx->mysql_thd->getKilled());
1810
1777
}
1811
1778
 
1812
1779
/**********************************************************************//**
1813
1780
Determines if the currently running transaction is in strict mode.
1814
1781
@return TRUE if strict */
1815
 
extern "C" UNIV_INTERN
 
1782
UNIV_INTERN
1816
1783
ibool
1817
1784
trx_is_strict(
1818
1785
/*==========*/
1904
1871
 
1905
1872
static int innodb_commit_concurrency_validate(Session *session, set_var *var)
1906
1873
{
1907
 
   uint32_t new_value= var->save_result.uint32_t_value;
 
1874
   uint64_t new_value= var->getInteger();
1908
1875
 
1909
1876
   if ((innobase_commit_concurrency.get() == 0 && new_value != 0) ||
1910
1877
       (innobase_commit_concurrency.get() != 0 && new_value == 0))
2008
1975
    }
2009
1976
 
2010
1977
    if (format_id >= 0) {
2011
 
      innobase_file_format_max= 
2012
 
        trx_sys_file_format_id_to_name((uint)format_id);
 
1978
      innobase_file_format_max.assign(
 
1979
                             trx_sys_file_format_id_to_name((uint)format_id));
2013
1980
 
2014
1981
      /* 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))
 
1982
      const char *name_buff;
 
1983
 
 
1984
      if (trx_sys_file_format_max_set(format_id, &name_buff))
2018
1985
      {
2019
 
        errmsg_printf(ERRMSG_LVL_WARN,
 
1986
        errmsg_printf(error::WARN,
2020
1987
                      " [Info] InnoDB: the file format in the system "
2021
1988
                      "tablespace is now set to %s.\n", name_buff);
2022
1989
        innobase_file_format_max= name_buff;
2076
2043
  innobase_use_doublewrite= (vm.count("disable-doublewrite")) ? false : true;
2077
2044
  srv_adaptive_flushing= (vm.count("disable-adaptive-flushing")) ? false : true;
2078
2045
  srv_use_sys_malloc= (vm.count("use-internal-malloc")) ? false : true;
 
2046
  srv_use_native_aio= (vm.count("disable-native-aio")) ? false : true;
2079
2047
  support_xa= (vm.count("disable-xa")) ? false : true;
2080
2048
  btr_search_enabled= (vm.count("disable-adaptive-hash-index")) ? false : true;
2081
2049
 
2103
2071
 
2104
2072
#ifdef UNIV_DEBUG
2105
2073
  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,
 
2074
  const size_t test_tablename_size= sizeof test_filename
 
2075
    + srv_mysql50_table_name_prefix.size();
 
2076
  boost::scoped_array test_tablename(new char[test_tablename_size]);
 
2077
  if ((test_tablename_size) - 1
 
2078
      != filename_to_tablename(test_filename, test_tablename.get(),
 
2079
                               test_tablename_size)
 
2080
      || strncmp(test_tablename.get(),
 
2081
                 srv_mysql50_table_name_prefix.c_str(),
 
2082
                 srv_mysql50_table_name_prefix.size())
 
2083
      || strcmp(test_tablename.get()
 
2084
                + srv_mysql50_table_name_prefix.size(),
2116
2085
                test_filename)) {
2117
 
    errmsg_printf(ERRMSG_LVL_ERROR, "tablename encoding has been changed");
 
2086
    errmsg_printf(error::ERROR, "tablename encoding has been changed");
2118
2087
    goto error;
2119
2088
  }
2120
2089
#endif /* UNIV_DEBUG */
2148
2117
  ret = (bool) srv_parse_data_file_paths_and_sizes(
2149
2118
                                                   internal_innobase_data_file_path);
2150
2119
  if (ret == FALSE) {
2151
 
    errmsg_printf(ERRMSG_LVL_ERROR, 
2152
 
                  "InnoDB: syntax error in innodb_data_file_path");
 
2120
    errmsg_printf(error::ERROR, "InnoDB: syntax error in innodb_data_file_path");
 
2121
 
2153
2122
mem_free_and_error:
2154
2123
    srv_free_paths_and_sizes();
2155
2124
    if (internal_innobase_data_file_path)
2174
2143
    srv_parse_log_group_home_dirs((char *)innobase_log_group_home_dir.c_str());
2175
2144
 
2176
2145
  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"));
 
2146
    errmsg_printf(error::ERROR, _("syntax error in innodb_log_group_home_dir, or a "
 
2147
                                  "wrong number of mirrored log groups"));
2180
2148
 
2181
2149
    goto mem_free_and_error;
2182
2150
  }
2190
2158
 
2191
2159
    if (format_id > DICT_TF_FORMAT_MAX) {
2192
2160
 
2193
 
      errmsg_printf(ERRMSG_LVL_ERROR, "InnoDB: wrong innodb_file_format.");
 
2161
      errmsg_printf(error::ERROR, "InnoDB: wrong innodb_file_format.");
2194
2162
 
2195
2163
      goto mem_free_and_error;
2196
2164
    }
2219
2187
     srv_max_file_format_at_startup */
2220
2188
  if (innobase_file_format_validate_and_set(innobase_file_format_max.c_str()) < 0)
2221
2189
  {
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));
 
2190
    errmsg_printf(error::ERROR, _("InnoDB: invalid innodb_file_format_max value: "
 
2191
                                  "should be any value up to %s or its equivalent numeric id"),
 
2192
                  trx_sys_file_format_id_to_name(DICT_TF_FORMAT_MAX));
2227
2193
    goto mem_free_and_error;
2228
2194
  }
2229
2195
 
2242
2208
      }
2243
2209
    }
2244
2210
 
2245
 
    errmsg_printf(ERRMSG_LVL_ERROR,
2246
 
                  "InnoDB: invalid value "
2247
 
                  "innodb_change_buffering=%s",
 
2211
    errmsg_printf(error::ERROR, "InnoDB: invalid value innodb_change_buffering=%s",
2248
2212
                  vm["change-buffering"].as<string>().c_str());
2249
2213
    goto mem_free_and_error;
2250
2214
  }
2322
2286
                                                     TRUE);
2323
2287
 
2324
2288
  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
2289
  innodb_inited= 1;
2331
2290
 
2332
2291
  actuall_engine_ptr->dropTemporarySchema();
2333
2292
 
2334
 
  status_table_function_ptr= new InnodbStatusTool;
2335
 
 
 
2293
  context.add(new InnodbStatusTool);
2336
2294
  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());
 
2295
  context.add(new CmpTool(false));
 
2296
  context.add(new CmpTool(true));
 
2297
  context.add(new CmpmemTool(false));
 
2298
  context.add(new CmpmemTool(true));
 
2299
  context.add(new InnodbTrxTool("INNODB_TRX"));
 
2300
  context.add(new InnodbTrxTool("INNODB_LOCKS"));
 
2301
  context.add(new InnodbTrxTool("INNODB_LOCK_WAITS"));
 
2302
  context.add(new InnodbSysTablesTool());
 
2303
  context.add(new InnodbSysTableStatsTool());
 
2304
  context.add(new InnodbSysIndexesTool());
 
2305
  context.add(new InnodbSysColumnsTool());
 
2306
  context.add(new InnodbSysFieldsTool());
 
2307
  context.add(new InnodbSysForeignTool());
 
2308
  context.add(new InnodbSysForeignColsTool());
 
2309
  context.add(new InnodbInternalTables());
 
2310
  context.add(new InnodbReplicationTable());
2384
2311
 
2385
2312
  if (innobase_use_replication_log)
2386
2313
  {
2387
 
    replication_logger= new(std::nothrow)ReplicationLog();
 
2314
    ReplicationLog *replication_logger= new ReplicationLog();
2388
2315
    context.add(replication_logger);
2389
2316
    ReplicationLog::setup(replication_logger);
2390
2317
  }
2424
2351
  context.registerVariable(new sys_var_constrained_value<uint32_t>("purge_threads",
2425
2352
                                                                   innodb_n_purge_threads,
2426
2353
                                                                   purge_threads_update));
2427
 
  context.registerVariable(new sys_var_constrained_value<uint16_t>("fast_shutdown", innobase_fast_shutdown));
 
2354
  context.registerVariable(new sys_var_constrained_value<uint32_t>("fast_shutdown", innobase_fast_shutdown));
2428
2355
  context.registerVariable(new sys_var_std_string("file_format",
2429
2356
                                                  innobase_file_format_name,
2430
2357
                                                  innodb_file_format_name_validate));
2436
2363
                                                  innodb_file_format_max_validate));
2437
2364
  context.registerVariable(new sys_var_constrained_value_readonly<size_t>("buffer_pool_size", innobase_buffer_pool_size));
2438
2365
  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",
 
2366
  context.registerVariable(new sys_var_constrained_value_readonly<uint32_t>("flush_log_at_trx_commit",
2440
2367
                                                  innodb_flush_log_at_trx_commit));
2441
2368
  context.registerVariable(new sys_var_constrained_value_readonly<unsigned int>("max_dirty_pages_pct",
2442
2369
                                                  innodb_max_dirty_pages_pct));
2475
2402
  btr_search_fully_disabled = (!btr_search_enabled);
2476
2403
 
2477
2404
  return(FALSE);
 
2405
 
2478
2406
error:
2479
2407
  return(TRUE);
2480
2408
}
2571
2499
    trx_search_latch_release_if_reserved(trx);
2572
2500
  }
2573
2501
 
2574
 
  if (all
2575
 
    || (!session_test_options(session, OPTION_NOT_AUTOCOMMIT | OPTION_BEGIN))) {
2576
 
 
 
2502
  if (all)
 
2503
  {
2577
2504
    /* We were instructed to commit the whole transaction, or
2578
2505
    this is an SQL statement end and autocommit is on */
2579
2506
 
2580
2507
    /* We need current binlog position for ibbackup to work.
2581
2508
    Note, the position is current because of
2582
2509
    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()) {
 
2510
    const uint32_t commit_concurrency= innobase_commit_concurrency.get();
 
2511
    if (commit_concurrency)
 
2512
    {
 
2513
      do 
 
2514
      {
 
2515
        boost::mutex::scoped_lock scopedLock(commit_cond_m);
 
2516
        commit_threads++;
 
2517
 
 
2518
        if (commit_threads <= commit_concurrency) 
 
2519
          break;
 
2520
 
2589
2521
        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
 
      }
 
2522
        commit_cond.wait(scopedLock);
 
2523
      } while (1);
2598
2524
    }
2599
2525
 
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";
 
2526
    trx->mysql_log_file_name = NULL;
2604
2527
    trx->mysql_log_offset = 0;
2605
2528
 
2606
2529
    /* Don't do write + flush right now. For group commit
2610
2533
    innobase_commit_low(trx);
2611
2534
    trx->flush_log_later = FALSE;
2612
2535
 
2613
 
    if (innobase_commit_concurrency.get() > 0) {
2614
 
      pthread_mutex_lock(&commit_cond_m);
 
2536
    if (commit_concurrency)
 
2537
    {
 
2538
      boost::mutex::scoped_lock scopedLock(commit_cond_m);
2615
2539
      commit_threads--;
2616
 
      pthread_cond_signal(&commit_cond);
2617
 
      pthread_mutex_unlock(&commit_cond_m);
 
2540
      commit_cond.notify_one();
2618
2541
    }
2619
2542
 
2620
2543
    /* Now do a write + flush of logs. */
2699
2622
 
2700
2623
  row_unlock_table_autoinc_for_mysql(trx);
2701
2624
 
2702
 
  if (all
2703
 
    || !session_test_options(session, OPTION_NOT_AUTOCOMMIT | OPTION_BEGIN)) {
2704
 
 
 
2625
  if (all)
 
2626
  {
2705
2627
    error = trx_rollback_for_mysql(trx);
2706
2628
  } else {
2707
2629
    error = trx_rollback_last_sql_stat_for_mysql(trx);
2860
2782
      trx->undo_no > 0 &&
2861
2783
      global_system_variables.log_warnings)
2862
2784
  {
2863
 
      errmsg_printf(ERRMSG_LVL_WARN,
 
2785
      errmsg_printf(error::WARN,
2864
2786
      "Drizzle is closing a connection during a KILL operation\n"
2865
2787
      "that has an active InnoDB transaction.  %llu row modifications will "
2866
2788
      "roll back.\n",
2940
2862
  return(true);
2941
2863
}
2942
2864
 
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
2865
/********************************************************************//**
2990
2866
Get the upper limit of the MySQL integral and floating-point type.
2991
2867
@return maximum allowed value for the field */
3152
3028
                if (!index_mapping) {
3153
3029
                        /* Report an error if index_mapping continues to be
3154
3030
                        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",
 
3031
                        errmsg_printf(error::ERROR, "InnoDB: fail to allocate memory for "
 
3032
                                      "index translation table. Number of Index:%lu, array size:%lu",
3159
3033
                                        mysql_num_index,
3160
3034
                                        share->idx_trans_tbl.array_size);
3161
3035
                        ret = FALSE;
3176
3050
                        ib_table, table->key_info[count].name);
3177
3051
 
3178
3052
                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);
 
3053
                        errmsg_printf(error::ERROR, "Cannot find index %s in InnoDB index dictionary.",
 
3054
                                      table->key_info[count].name);
3182
3055
                        ret = FALSE;
3183
3056
                        goto func_exit;
3184
3057
                }
3185
3058
 
3186
3059
                /* Double check fetched index has the same
3187
3060
                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;
 
3061
                if (!innobase_match_index_columns(&table->key_info[count], index_mapping[count])) {
 
3062
                  errmsg_printf(error::ERROR, "Found index %s whose column info does not match that of MySQL.",
 
3063
                                table->key_info[count].name);
 
3064
                  ret = FALSE;
 
3065
                  goto func_exit;
3195
3066
                }
3196
3067
        }
3197
3068
 
3261
3132
    auto_inc = 0;
3262
3133
 
3263
3134
    ut_print_timestamp(stderr);
3264
 
    fprintf(stderr, "  InnoDB: Unable to determine the AUTOINC "
3265
 
            "column name\n");
 
3135
    errmsg_printf(error::ERROR, "InnoDB: Unable to determine the AUTOINC column name");
3266
3136
  }
3267
3137
 
3268
3138
  if (srv_force_recovery >= SRV_FORCE_NO_IBUF_MERGE) {
3312
3182
    }
3313
3183
    case DB_RECORD_NOT_FOUND:
3314
3184
      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);
 
3185
      errmsg_printf(error::ERROR, "InnoDB: MySQL and InnoDB data dictionaries are out of sync.\n"
 
3186
                    "InnoDB: Unable to find the AUTOINC column %s in the InnoDB table %s.\n"
 
3187
                    "InnoDB: We set the next AUTOINC column value to 0,\n"
 
3188
                    "InnoDB: in effect disabling the AUTOINC next value generation.\n"
 
3189
                    "InnoDB: You can either set the next AUTOINC value explicitly using ALTER TABLE\n"
 
3190
                    "InnoDB: or fix the data dictionary by recreating the table.\n",
 
3191
                    col_name, index->table->name);
3328
3192
 
3329
3193
      /* This will disable the AUTOINC generation. */
3330
3194
      auto_inc = 0;
3350
3214
@return 1 if error, 0 if success */
3351
3215
UNIV_INTERN
3352
3216
int
3353
 
ha_innobase::doOpen(const TableIdentifier &identifier,
 
3217
ha_innobase::doOpen(const identifier::Table &identifier,
3354
3218
                    int   mode,   /*!< in: not used */
3355
3219
                    uint    test_if_locked) /*!< in: not used */
3356
3220
{
3357
3221
  dict_table_t* ib_table;
3358
 
  char    norm_name[FN_REFLEN];
3359
3222
  Session*    session;
3360
3223
 
3361
3224
  UT_NOT_USED(mode);
3370
3233
    getTransactionalEngine()->releaseTemporaryLatches(session);
3371
3234
  }
3372
3235
 
3373
 
  normalize_table_name(norm_name, identifier.getPath().c_str());
3374
 
 
3375
3236
  user_session = NULL;
3376
3237
 
3377
 
  if (!(share=get_share(identifier.getPath().c_str()))) {
 
3238
  std::string search_string(identifier.getSchemaName());
 
3239
  boost::algorithm::to_lower(search_string);
3378
3240
 
3379
 
    return(1);
 
3241
  if (search_string.compare("data_dictionary") == 0)
 
3242
  {
 
3243
    std::string table_name(identifier.getTableName());
 
3244
    boost::algorithm::to_upper(table_name);
 
3245
    if (!(share=get_share(table_name.c_str())))
 
3246
    {
 
3247
      return 1;
 
3248
    }
 
3249
  }
 
3250
  else
 
3251
  {
 
3252
    if (!(share=get_share(identifier.getKeyPath().c_str())))
 
3253
    {
 
3254
      return(1);
 
3255
    }
3380
3256
  }
3381
3257
 
3382
3258
  /* Create buffers for packing the fields of a record. Why
3385
3261
  stored the string length as the first byte. */
3386
3262
 
3387
3263
  upd_and_key_val_buff_len =
3388
 
        getTable()->getShare()->stored_rec_length
 
3264
        getTable()->getShare()->sizeStoredRecord()
3389
3265
        + getTable()->getShare()->max_key_length
3390
3266
        + MAX_REF_PARTS * 3;
3391
3267
 
3403
3279
  }
3404
3280
 
3405
3281
  /* Get pointer to a table object in InnoDB dictionary cache */
3406
 
  ib_table = dict_table_get(norm_name, TRUE);
 
3282
  if (search_string.compare("data_dictionary") == 0)
 
3283
  {
 
3284
    std::string table_name(identifier.getTableName());
 
3285
    boost::algorithm::to_upper(table_name);
 
3286
    ib_table = dict_table_get(table_name.c_str(), TRUE);
 
3287
  }
 
3288
  else
 
3289
  {
 
3290
    ib_table = dict_table_get(identifier.getKeyPath().c_str(), TRUE);
 
3291
  }
3407
3292
  
3408
3293
  if (NULL == ib_table) {
3409
 
    errmsg_printf(ERRMSG_LVL_ERROR, "Cannot find or open table %s from\n"
 
3294
    errmsg_printf(error::ERROR, "Cannot find or open table %s from\n"
3410
3295
        "the internal data dictionary of InnoDB "
3411
3296
        "though the .frm file for the\n"
3412
3297
        "table exists. Maybe you have deleted and "
3420
3305
        "doesn't support.\n"
3421
3306
        "See " REFMAN "innodb-troubleshooting.html\n"
3422
3307
        "how you can resolve the problem.\n",
3423
 
        norm_name);
 
3308
        identifier.getKeyPath().c_str());
3424
3309
    free_share(share);
3425
3310
    upd_buff.resize(0);
3426
3311
    key_val_buff.resize(0);
3429
3314
    return(HA_ERR_NO_SUCH_TABLE);
3430
3315
  }
3431
3316
 
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 "
 
3317
  if (ib_table->ibd_file_missing && ! session->doing_tablespace_operation()) {
 
3318
    errmsg_printf(error::ERROR, "MySQL is trying to open a table handle but "
3434
3319
        "the .ibd file for\ntable %s does not exist.\n"
3435
3320
        "Have you deleted the .ibd file from the "
3436
3321
        "database directory under\nthe MySQL datadir, "
3437
3322
        "or have you used DISCARD TABLESPACE?\n"
3438
3323
        "See " REFMAN "innodb-troubleshooting.html\n"
3439
3324
        "how you can resolve the problem.\n",
3440
 
        norm_name);
 
3325
        identifier.getKeyPath().c_str());
3441
3326
    free_share(share);
3442
3327
    upd_buff.resize(0);
3443
3328
    key_val_buff.resize(0);
3449
3334
 
3450
3335
  prebuilt = row_create_prebuilt(ib_table);
3451
3336
 
3452
 
  prebuilt->mysql_row_len = getTable()->getShare()->stored_rec_length;
 
3337
  prebuilt->mysql_row_len = getTable()->getShare()->sizeStoredRecord();
3453
3338
  prebuilt->default_rec = getTable()->getDefaultValues();
3454
3339
  ut_ad(prebuilt->default_rec);
3455
3340
 
3459
3344
  key_used_on_scan = primary_key;
3460
3345
 
3461
3346
  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());
 
3347
    errmsg_printf(error::ERROR, "Build InnoDB index translation table for"
 
3348
                    " Table %s failed", identifier.getKeyPath().c_str());
3464
3349
  }
3465
3350
 
3466
3351
  /* Allocate a buffer for a 'row reference'. A row reference is
3474
3359
    prebuilt->clust_index_was_generated = FALSE;
3475
3360
 
3476
3361
    if (UNIV_UNLIKELY(primary_key >= MAX_KEY)) {
3477
 
      errmsg_printf(ERRMSG_LVL_ERROR, "Table %s has a primary key in "
 
3362
      errmsg_printf(error::ERROR, "Table %s has a primary key in "
3478
3363
                    "InnoDB data dictionary, but not "
3479
3364
                    "in MySQL!", identifier.getTableName().c_str());
3480
3365
 
3529
3414
    }
3530
3415
  } else {
3531
3416
    if (primary_key != MAX_KEY) {
3532
 
      errmsg_printf(ERRMSG_LVL_ERROR,
 
3417
      errmsg_printf(error::ERROR,
3533
3418
                    "Table %s has no primary key in InnoDB data "
3534
3419
                    "dictionary, but has one in MySQL! If you "
3535
3420
                    "created the table with a MySQL version < "
3565
3450
    and it will never be updated anyway. */
3566
3451
 
3567
3452
    if (key_used_on_scan != MAX_KEY) {
3568
 
      errmsg_printf(ERRMSG_LVL_WARN, 
 
3453
      errmsg_printf(error::WARN, 
3569
3454
        "Table %s key_used_on_scan is %lu even "
3570
3455
        "though there is no primary key inside "
3571
3456
        "InnoDB.", identifier.getTableName().c_str(), (ulong) key_used_on_scan);
3717
3602
of this function is in rem0cmp.c in InnoDB source code! If you change this
3718
3603
function, remember to update the prototype there!
3719
3604
@return 1, 0, -1, if a is greater, equal, less than b, respectively */
3720
 
extern "C" UNIV_INTERN
3721
 
int
 
3605
UNIV_INTERN int
3722
3606
innobase_mysql_cmp(
3723
3607
/*===============*/
3724
3608
  int   mysql_type, /*!< in: MySQL type */
3741
3625
  const unsigned char* b,   /* in: data field */
3742
3626
  unsigned int  b_length) /* in: data field length, not UNIV_SQL_NULL */
3743
3627
{
3744
 
  const CHARSET_INFO* charset;
 
3628
  const charset_info_st* charset;
3745
3629
  enum_field_types  mysql_tp;
3746
3630
  int     ret;
3747
3631
 
3765
3649
      charset = get_charset(charset_number);
3766
3650
 
3767
3651
      if (charset == NULL) {
3768
 
        errmsg_printf(ERRMSG_LVL_ERROR, "InnoDB needs charset %lu for doing "
 
3652
        errmsg_printf(error::ERROR, "InnoDB needs charset %lu for doing "
3769
3653
                      "a comparison, but MySQL cannot "
3770
3654
                      "find that charset.",
3771
3655
                      (ulong) charset_number);
3800
3684
the 'mtype' of InnoDB. InnoDB differentiates between MySQL's old <= 4.1
3801
3685
VARCHAR and the new true VARCHAR in >= 5.0.3 by the 'prtype'.
3802
3686
@return DATA_BINARY, DATA_VARCHAR, ... */
3803
 
extern "C" UNIV_INTERN
 
3687
UNIV_INTERN
3804
3688
ulint
3805
3689
get_innobase_type_from_mysql_type(
3806
3690
/*==============================*/
3849
3733
      return(DATA_VARMYSQL);
3850
3734
    }
3851
3735
  case DRIZZLE_TYPE_DECIMAL:
 
3736
  case DRIZZLE_TYPE_MICROTIME:
3852
3737
    return(DATA_FIXBINARY);
3853
3738
  case DRIZZLE_TYPE_LONG:
3854
3739
  case DRIZZLE_TYPE_LONGLONG:
3855
3740
  case DRIZZLE_TYPE_DATETIME:
 
3741
  case DRIZZLE_TYPE_TIME:
3856
3742
  case DRIZZLE_TYPE_DATE:
3857
3743
  case DRIZZLE_TYPE_TIMESTAMP:
3858
3744
  case DRIZZLE_TYPE_ENUM:
3861
3747
    return(DATA_DOUBLE);
3862
3748
  case DRIZZLE_TYPE_BLOB:
3863
3749
    return(DATA_BLOB);
 
3750
  case DRIZZLE_TYPE_BOOLEAN:
3864
3751
  case DRIZZLE_TYPE_UUID:
3865
3752
    return(DATA_FIXBINARY);
3866
3753
  case DRIZZLE_TYPE_NULL:
3971
3858
      const byte* data;
3972
3859
      ulint   key_len;
3973
3860
      ulint   true_len;
3974
 
      const CHARSET_INFO* cs;
 
3861
      const charset_info_st* cs;
3975
3862
      int   error=0;
3976
3863
 
3977
3864
      key_len = key_part->length;
4030
3917
 
4031
3918
    } else if (mysql_type == DRIZZLE_TYPE_BLOB) {
4032
3919
 
4033
 
      const CHARSET_INFO* cs;
 
3920
      const charset_info_st* cs;
4034
3921
      ulint   key_len;
4035
3922
      ulint   true_len;
4036
3923
      int   error=0;
4102
3989
      ulint     true_len;
4103
3990
      ulint     key_len;
4104
3991
      const unsigned char*    src_start;
4105
 
      enum_field_types  real_type;
4106
 
      const CHARSET_INFO* cs= field->charset();
 
3992
      const charset_info_st* cs= field->charset();
4107
3993
 
4108
3994
      key_len = key_part->length;
4109
3995
 
4114
4000
      }
4115
4001
 
4116
4002
      src_start = record + key_part->offset;
4117
 
      real_type = field->real_type();
4118
4003
      true_len = key_len;
4119
4004
 
4120
4005
      /* Character set for the field is defined only
4288
4173
    n_requested_fields++;
4289
4174
 
4290
4175
    templ->col_no = i;
 
4176
    templ->clust_rec_field_no = dict_col_get_clust_pos(col, clust_index);
 
4177
    ut_ad(templ->clust_rec_field_no != ULINT_UNDEFINED);
4291
4178
 
4292
4179
    if (index == clust_index) {
4293
 
      templ->rec_field_no = dict_col_get_clust_pos(col, index);
 
4180
      templ->rec_field_no = templ->clust_rec_field_no;
4294
4181
    } else {
4295
4182
      templ->rec_field_no = dict_index_get_nth_col_pos(
4296
4183
                index, i);
4297
 
    }
4298
 
 
4299
 
    if (templ->rec_field_no == ULINT_UNDEFINED) {
4300
 
      prebuilt->need_to_access_clustered = TRUE;
 
4184
      if (templ->rec_field_no == ULINT_UNDEFINED) {
 
4185
        prebuilt->need_to_access_clustered = TRUE;
 
4186
      }
4301
4187
    }
4302
4188
 
4303
4189
    if (field->null_ptr) {
4347
4233
    for (i = 0; i < n_requested_fields; i++) {
4348
4234
      templ = prebuilt->mysql_template + i;
4349
4235
 
4350
 
      templ->rec_field_no = dict_col_get_clust_pos(
4351
 
        &index->table->cols[templ->col_no],
4352
 
        clust_index);
 
4236
      templ->rec_field_no = templ->clust_rec_field_no;
4353
4237
    }
4354
4238
  }
4355
4239
}
4423
4307
  trx_t*    trx = session_to_trx(user_session);
4424
4308
 
4425
4309
  if (prebuilt->trx != trx) {
4426
 
    errmsg_printf(ERRMSG_LVL_ERROR, "The transaction object for the table handle is at "
 
4310
    errmsg_printf(error::ERROR, "The transaction object for the table handle is at "
4427
4311
        "%p, but for the current thread it is at %p",
4428
4312
        (const void*) prebuilt->trx, (const void*) trx);
4429
4313
 
4437
4321
    ut_error;
4438
4322
  }
4439
4323
 
4440
 
  sql_command = session_sql_command(user_session);
 
4324
  sql_command = user_session->getSqlCommand();
4441
4325
 
4442
4326
  if ((sql_command == SQLCOM_ALTER_TABLE
4443
4327
       || sql_command == SQLCOM_CREATE_INDEX
4884
4768
  if (error == DB_SUCCESS
4885
4769
      && getTable()->next_number_field
4886
4770
      && new_row == getTable()->getInsertRecord()
4887
 
      && session_sql_command(user_session) == SQLCOM_INSERT
 
4771
      && user_session->getSqlCommand() == SQLCOM_INSERT
4888
4772
      && (trx->duplicates & (TRX_DUP_IGNORE | TRX_DUP_REPLACE))
4889
4773
    == TRX_DUP_IGNORE)  {
4890
4774
 
5351
5235
         table. Only print message if the index translation
5352
5236
         table exists */
5353
5237
      if (share->idx_trans_tbl.index_mapping) {
5354
 
        errmsg_printf(ERRMSG_LVL_ERROR,
 
5238
        errmsg_printf(error::ERROR,
5355
5239
                      "InnoDB could not find "
5356
5240
                      "index %s key no %u for "
5357
5241
                      "table %s through its "
5369
5253
  }
5370
5254
 
5371
5255
  if (!index) {
5372
 
    errmsg_printf(ERRMSG_LVL_ERROR, 
 
5256
    errmsg_printf(error::ERROR, 
5373
5257
      "Innodb could not find key n:o %u with name %s "
5374
5258
      "from dict cache for table %s",
5375
 
      keynr, getTable()->getShare()->getTableProto()->indexes(keynr).name().c_str(),
 
5259
      keynr, getTable()->getShare()->getTableMessage()->indexes(keynr).name().c_str(),
5376
5260
      prebuilt->table->name);
5377
5261
  }
5378
5262
 
5398
5282
  prebuilt->index = innobase_get_index(keynr);
5399
5283
 
5400
5284
  if (UNIV_UNLIKELY(!prebuilt->index)) {
5401
 
    errmsg_printf(ERRMSG_LVL_WARN, "InnoDB: change_active_index(%u) failed",
 
5285
    errmsg_printf(error::WARN, "InnoDB: change_active_index(%u) failed",
5402
5286
          keynr);
5403
5287
    prebuilt->index_usable = FALSE;
5404
5288
    return(1);
5764
5648
  table. */
5765
5649
 
5766
5650
  if (len != ref_length) {
5767
 
    errmsg_printf(ERRMSG_LVL_ERROR, "Stored ref len is %lu, but table ref len is %lu",
 
5651
    errmsg_printf(error::ERROR, "Stored ref len is %lu, but table ref len is %lu",
5768
5652
        (ulong) len, (ulong) ref_length);
5769
5653
  }
5770
5654
}
5823
5707
 
5824
5708
    if (!col_type) {
5825
5709
      push_warning_printf(
5826
 
                          (Session*) trx->mysql_thd,
 
5710
                          trx->mysql_thd,
5827
5711
                          DRIZZLE_ERROR::WARN_LEVEL_WARN,
5828
5712
                          ER_CANT_CREATE_TABLE,
5829
5713
                          "Error creating table '%s' with "
5857
5741
        /* in data0type.h we assume that the
5858
5742
        number fits in one byte in prtype */
5859
5743
        push_warning_printf(
5860
 
          (Session*) trx->mysql_thd,
 
5744
          trx->mysql_thd,
5861
5745
          DRIZZLE_ERROR::WARN_LEVEL_ERROR,
5862
5746
          ER_CANT_CREATE_TABLE,
5863
5747
          "In InnoDB, charset-collation codes"
6023
5907
        || col_type == DATA_FLOAT
6024
5908
        || col_type == DATA_DOUBLE
6025
5909
        || col_type == DATA_DECIMAL) {
6026
 
        errmsg_printf(ERRMSG_LVL_ERROR, 
 
5910
        errmsg_printf(error::ERROR, 
6027
5911
          "MySQL is trying to create a column "
6028
5912
          "prefix index field, on an "
6029
5913
          "inappropriate data type. Table "
6120
6004
UNIV_INTERN
6121
6005
int
6122
6006
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)
 
6007
                              /*================*/
 
6008
                              Session         &session, /*!< in: Session */
 
6009
                              Table&    form,   /*!< in: information on table columns and indexes */
 
6010
                              const identifier::Table &identifier,
 
6011
                              const message::Table& create_proto)
6128
6012
{
6129
6013
  int   error;
6130
6014
  dict_table_t* innobase_table;
6132
6016
  trx_t*    trx;
6133
6017
  int   primary_key_no;
6134
6018
  uint    i;
6135
 
  char    name2[FN_REFLEN];
6136
 
  char    norm_name[FN_REFLEN];
6137
6019
  ib_int64_t  auto_inc_value;
6138
6020
  ulint   iflags;
6139
6021
  /* Cache the value of innodb_file_format, in case it is
6143
6025
  const char* stmt;
6144
6026
  size_t stmt_len;
6145
6027
 
6146
 
  const char *table_name= identifier.getPath().c_str();
 
6028
  std::string search_string(identifier.getSchemaName());
 
6029
  boost::algorithm::to_lower(search_string);
 
6030
 
 
6031
  if (search_string.compare("data_dictionary") == 0)
 
6032
  {
 
6033
    return HA_WRONG_CREATE_OPTION;
 
6034
  }
6147
6035
 
6148
6036
  if (form.getShare()->sizeFields() > 1000) {
6149
6037
    /* The limit probably should be REC_MAX_N_FIELDS - 3 = 1020,
6166
6054
 
6167
6055
  srv_lower_case_table_names = TRUE;
6168
6056
 
6169
 
  strcpy(name2, table_name);
6170
 
 
6171
 
  normalize_table_name(norm_name, name2);
6172
 
 
6173
6057
  /* Latch the InnoDB data dictionary exclusively so that no deadlocks
6174
6058
    or lock waits can happen in it during a table create operation.
6175
6059
    Drop table etc. do this latching in row0mysql.c. */
6277
6161
  if (lex_identified_temp_table)
6278
6162
    iflags |= DICT_TF2_TEMPORARY << DICT_TF2_SHIFT;
6279
6163
 
6280
 
  error= create_table_def(trx, &form, norm_name,
6281
 
                          lex_identified_temp_table ? name2 : NULL,
 
6164
  error= create_table_def(trx, &form, identifier.getKeyPath().c_str(),
 
6165
                          lex_identified_temp_table ? identifier.getKeyPath().c_str() : NULL,
6282
6166
                          iflags);
6283
6167
 
6284
6168
  session.setXaId(trx->id);
6294
6178
      order the rows by their row id which is internally generated
6295
6179
      by InnoDB */
6296
6180
 
6297
 
    error = create_clustered_index_when_no_primary(trx, iflags, norm_name);
 
6181
    error = create_clustered_index_when_no_primary(trx, iflags, identifier.getKeyPath().c_str());
6298
6182
    if (error) {
6299
6183
      goto cleanup;
6300
6184
    }
6302
6186
 
6303
6187
  if (primary_key_no != -1) {
6304
6188
    /* In InnoDB the clustered index must always be created first */
6305
 
    if ((error = create_index(trx, &form, iflags, norm_name,
 
6189
    if ((error = create_index(trx, &form, iflags, identifier.getKeyPath().c_str(),
6306
6190
                              (uint) primary_key_no))) {
6307
6191
      goto cleanup;
6308
6192
    }
6311
6195
  for (i = 0; i < form.getShare()->sizeKeys(); i++) {
6312
6196
    if (i != (uint) primary_key_no) {
6313
6197
 
6314
 
      if ((error = create_index(trx, &form, iflags, norm_name,
 
6198
      if ((error = create_index(trx, &form, iflags, identifier.getKeyPath().c_str(),
6315
6199
                                i))) {
6316
6200
        goto cleanup;
6317
6201
      }
6318
6202
    }
6319
6203
  }
6320
6204
 
6321
 
  stmt = innobase_get_stmt(&session, &stmt_len);
 
6205
  stmt= session.getQueryStringCopy(stmt_len);
6322
6206
 
6323
6207
  if (stmt) {
6324
6208
    string generated_create_table;
6325
6209
    const char *query= stmt;
6326
6210
 
6327
 
    if (session_sql_command(&session) == SQLCOM_CREATE_TABLE)
 
6211
    if (session.getSqlCommand() == SQLCOM_CREATE_TABLE)
6328
6212
    {
6329
6213
      message::transformTableDefinitionToSql(create_proto,
6330
6214
                                             generated_create_table,
6334
6218
 
6335
6219
    error = row_table_add_foreign_constraints(trx,
6336
6220
                                              query, strlen(query),
6337
 
                                              norm_name,
 
6221
                                              identifier.getKeyPath().c_str(),
6338
6222
                                              lex_identified_temp_table);
 
6223
    switch (error) {
 
6224
 
 
6225
    case DB_PARENT_NO_INDEX:
 
6226
      push_warning_printf(
 
6227
                          &session, DRIZZLE_ERROR::WARN_LEVEL_WARN,
 
6228
                          HA_ERR_CANNOT_ADD_FOREIGN,
 
6229
                          "Create table '%s' with foreign key constraint"
 
6230
                          " failed. There is no index in the referenced"
 
6231
                          " table where the referenced columns appear"
 
6232
                          " as the first columns.\n", identifier.getKeyPath().c_str());
 
6233
      break;
 
6234
 
 
6235
    case DB_CHILD_NO_INDEX:
 
6236
      push_warning_printf(
 
6237
                          &session, DRIZZLE_ERROR::WARN_LEVEL_WARN,
 
6238
                          HA_ERR_CANNOT_ADD_FOREIGN,
 
6239
                          "Create table '%s' with foreign key constraint"
 
6240
                          " failed. There is no index in the referencing"
 
6241
                          " table where referencing columns appear"
 
6242
                          " as the first columns.\n", identifier.getKeyPath().c_str());
 
6243
      break;
 
6244
    }
6339
6245
 
6340
6246
    error = convert_error_code_to_mysql(error, iflags, NULL);
6341
6247
 
6354
6260
 
6355
6261
  log_buffer_flush_to_disk();
6356
6262
 
6357
 
  innobase_table = dict_table_get(norm_name, FALSE);
 
6263
  innobase_table = dict_table_get(identifier.getKeyPath().c_str(), FALSE);
6358
6264
 
6359
6265
  assert(innobase_table != 0);
6360
6266
 
6377
6283
    does a table copy too. */
6378
6284
 
6379
6285
  if ((create_proto.options().has_auto_increment_value()
6380
 
       || session_sql_command(&session) == SQLCOM_ALTER_TABLE
6381
 
       || session_sql_command(&session) == SQLCOM_CREATE_INDEX)
 
6286
       || session.getSqlCommand() == SQLCOM_ALTER_TABLE
 
6287
       || session.getSqlCommand() == SQLCOM_CREATE_INDEX)
6382
6288
      && create_proto.options().auto_increment_value() != 0) {
6383
6289
 
6384
6290
    /* Query was one of :
6471
6377
 
6472
6378
  update_session(getTable()->in_use);
6473
6379
 
6474
 
  if (session_sql_command(user_session) != SQLCOM_TRUNCATE) {
 
6380
  if (user_session->getSqlCommand() != SQLCOM_TRUNCATE) {
6475
6381
  fallback:
6476
6382
    /* We only handle TRUNCATE TABLE t as a special case.
6477
6383
    DELETE FROM t will have to use ha_innobase::doDeleteRecord(),
6505
6411
InnobaseEngine::doDropTable(
6506
6412
/*======================*/
6507
6413
        Session &session,
6508
 
        const TableIdentifier &identifier)
 
6414
        const identifier::Table &identifier)
6509
6415
{
6510
6416
  int error;
6511
6417
  trx_t*  parent_trx;
6512
6418
  trx_t*  trx;
6513
 
  char  norm_name[1000];
6514
6419
 
6515
6420
  ut_a(identifier.getPath().length() < 1000);
6516
6421
 
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());
 
6422
  std::string search_string(identifier.getSchemaName());
 
6423
  boost::algorithm::to_lower(search_string);
 
6424
 
 
6425
  if (search_string.compare("data_dictionary") == 0)
 
6426
  {
 
6427
    return HA_ERR_TABLE_READONLY;
 
6428
  }
6520
6429
 
6521
6430
  /* Get the transaction associated with the current session, or create one
6522
6431
    if not yet created */
6534
6443
 
6535
6444
  /* Drop the table in InnoDB */
6536
6445
 
6537
 
  error = row_drop_table_for_mysql(norm_name, trx,
6538
 
                                   session_sql_command(&session)
 
6446
  error = row_drop_table_for_mysql(identifier.getKeyPath().c_str(), trx,
 
6447
                                   session.getSqlCommand()
6539
6448
                                   == SQLCOM_DROP_DB);
6540
6449
 
6541
6450
  session.setXaId(trx->id);
6563
6472
    if (identifier.getType() == message::Table::TEMPORARY)
6564
6473
    {
6565
6474
      session.getMessageCache().removeTableMessage(identifier);
6566
 
      ulint sql_command = session_sql_command(&session);
 
6475
      ulint sql_command = session.getSqlCommand();
6567
6476
 
6568
6477
      // If this was the final removal to an alter table then we will need
6569
6478
      // to remove the .dfe that was left behind.
6596
6505
bool
6597
6506
InnobaseEngine::doDropSchema(
6598
6507
/*===================*/
6599
 
                             const SchemaIdentifier &identifier)
 
6508
                             const identifier::Schema &identifier)
6600
6509
    /*!< in: database path; inside InnoDB the name
6601
6510
      of the last directory in the path is used as
6602
6511
      the database name: for example, in 'mysql/data/test'
6641
6550
  innobase_commit_low(trx);
6642
6551
  trx_free_for_mysql(trx);
6643
6552
 
 
6553
  if (error) {
 
6554
    // What do we do here?
 
6555
  }
 
6556
 
6644
6557
  return false; // We are just a listener since we lack control over DDL, so we give no positive acknowledgement. 
6645
6558
}
6646
6559
 
6647
6560
void InnobaseEngine::dropTemporarySchema()
6648
6561
{
6649
 
  SchemaIdentifier schema_identifier(GLOBAL_TEMPORARY_EXT);
 
6562
  identifier::Schema schema_identifier(GLOBAL_TEMPORARY_EXT);
6650
6563
  trx_t*  trx= NULL;
6651
6564
  string schema_path(GLOBAL_TEMPORARY_EXT);
6652
6565
 
6683
6596
innobase_rename_table(
6684
6597
/*==================*/
6685
6598
  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 */
 
6599
  const identifier::Table &from,
 
6600
  const identifier::Table &to,
6688
6601
  ibool   lock_and_commit)
6689
6602
        /*!< in: TRUE=lock data dictionary and commit */
6690
6603
{
6691
6604
  int error;
6692
 
  char norm_to[FN_REFLEN];
6693
 
  char norm_from[FN_REFLEN];
6694
6605
 
6695
6606
  srv_lower_case_table_names = TRUE;
6696
6607
 
6697
 
  normalize_table_name(norm_to, to);
6698
 
  normalize_table_name(norm_from, from);
6699
 
 
6700
6608
  /* Serialize data dictionary operations with dictionary mutex:
6701
6609
  no deadlocks can occur then in these operations */
6702
6610
 
6704
6612
    row_mysql_lock_data_dictionary(trx);
6705
6613
  }
6706
6614
 
6707
 
  error = row_rename_table_for_mysql(
6708
 
    norm_from, norm_to, trx, lock_and_commit);
 
6615
  error = row_rename_table_for_mysql(from.getKeyPath().c_str(), to.getKeyPath().c_str(), trx, lock_and_commit);
6709
6616
 
6710
6617
  if (error != DB_SUCCESS) {
6711
6618
    FILE* ef = dict_foreign_err_file;
6712
6619
 
6713
6620
    fputs("InnoDB: Renaming table ", ef);
6714
 
    ut_print_name(ef, trx, TRUE, norm_from);
 
6621
    ut_print_name(ef, trx, TRUE, from.getKeyPath().c_str());
6715
6622
    fputs(" to ", ef);
6716
 
    ut_print_name(ef, trx, TRUE, norm_to);
 
6623
    ut_print_name(ef, trx, TRUE, to.getKeyPath().c_str());
6717
6624
    fputs(" failed!\n", ef);
6718
6625
  }
6719
6626
 
6732
6639
/*********************************************************************//**
6733
6640
Renames an InnoDB table.
6734
6641
@return 0 or error code */
6735
 
UNIV_INTERN int InnobaseEngine::doRenameTable(Session &session, const TableIdentifier &from, const TableIdentifier &to)
 
6642
UNIV_INTERN int InnobaseEngine::doRenameTable(Session &session, const identifier::Table &from, const identifier::Table &to)
6736
6643
{
6737
6644
  // A temp table alter table/rename is a shallow rename and only the
6738
6645
  // definition needs to be updated.
6758
6665
 
6759
6666
  trx = innobase_trx_allocate(&session);
6760
6667
 
6761
 
  error = innobase_rename_table(trx, from.getPath().c_str(), to.getPath().c_str(), TRUE);
 
6668
  error = innobase_rename_table(trx, from, to, TRUE);
6762
6669
 
6763
6670
  session.setXaId(trx->id);
6764
6671
 
6783
6690
     is the one we are trying to rename to) and return the generic
6784
6691
     error code. */
6785
6692
  if (error == (int) DB_DUPLICATE_KEY) {
6786
 
    my_error(ER_TABLE_EXISTS_ERROR, MYF(0), to.getPath().c_str());
 
6693
    my_error(ER_TABLE_EXISTS_ERROR, to);
6787
6694
    error = DB_ERROR;
6788
6695
  }
6789
6696
 
6814
6721
  KeyInfo*    key;
6815
6722
  dict_index_t* index;
6816
6723
  unsigned char*    key_val_buff2 = (unsigned char*) malloc(
6817
 
              getTable()->getShare()->stored_rec_length
 
6724
              getTable()->getShare()->sizeStoredRecord()
6818
6725
          + getTable()->getShare()->max_key_length + 100);
6819
 
  ulint   buff2_len = getTable()->getShare()->stored_rec_length
 
6726
  ulint   buff2_len = getTable()->getShare()->sizeStoredRecord()
6820
6727
          + getTable()->getShare()->max_key_length + 100;
6821
6728
  dtuple_t* range_start;
6822
6729
  dtuple_t* range_end;
6926
6833
  dict_index_t* index;
6927
6834
  uint64_t  estimate;
6928
6835
  uint64_t  local_data_file_length;
 
6836
  ulint stat_n_leaf_pages;
6929
6837
 
6930
6838
  /* We do not know if MySQL can call this function before calling
6931
6839
  external_lock(). To be safe, update the session of the current table
6943
6851
 
6944
6852
  index = dict_table_get_first_index(prebuilt->table);
6945
6853
 
6946
 
  ut_a(index->stat_n_leaf_pages > 0);
 
6854
  stat_n_leaf_pages = index->stat_n_leaf_pages;
 
6855
 
 
6856
  ut_a(stat_n_leaf_pages > 0);
6947
6857
 
6948
6858
  local_data_file_length =
6949
 
    ((uint64_t) index->stat_n_leaf_pages) * UNIV_PAGE_SIZE;
 
6859
    ((uint64_t) stat_n_leaf_pages) * UNIV_PAGE_SIZE;
6950
6860
 
6951
6861
 
6952
6862
  /* Calculate a minimum length for a clustered index record and from
7096
7006
 
7097
7007
                /* Print an error message if we cannot find the index
7098
7008
                ** in the "index translation table". */
7099
 
                errmsg_printf(ERRMSG_LVL_ERROR,
 
7009
                errmsg_printf(error::ERROR,
7100
7010
                              "Cannot find index %s in InnoDB index "
7101
7011
                                "translation table.", index->name);
7102
7012
        }
7113
7023
                }
7114
7024
        }
7115
7025
 
7116
 
                errmsg_printf(ERRMSG_LVL_ERROR,
 
7026
                errmsg_printf(error::ERROR,
7117
7027
                              "Cannot find matching index number for index %s "
7118
7028
                              "in InnoDB index list.", index->name);
7119
7029
 
7159
7069
 
7160
7070
    prebuilt->trx->op_info = "updating table statistics";
7161
7071
 
7162
 
    dict_update_statistics(ib_table);
 
7072
    dict_update_statistics(ib_table,
 
7073
                           FALSE /* update even if stats
 
7074
                                    are initialized */);
 
7075
 
7163
7076
 
7164
7077
    prebuilt->trx->op_info = "returning various info to MySQL";
7165
7078
 
7176
7089
  }
7177
7090
 
7178
7091
  if (flag & HA_STATUS_VARIABLE) {
 
7092
 
 
7093
    dict_table_stats_lock(ib_table, RW_S_LATCH);
 
7094
 
7179
7095
    n_rows = ib_table->stat_n_rows;
7180
7096
 
7181
7097
    /* Because we do not protect stat_n_rows by any mutex in a
7203
7119
    n_rows can not be 0 unless the table is empty, set to 1
7204
7120
    instead. The original problem of bug#29507 is actually
7205
7121
    fixed in the server code. */
7206
 
    if (session_sql_command(user_session) == SQLCOM_TRUNCATE) {
 
7122
    if (user_session->getSqlCommand() == SQLCOM_TRUNCATE) {
7207
7123
 
7208
7124
      n_rows = 1;
7209
7125
 
7225
7141
        ib_table->stat_sum_of_other_index_sizes)
7226
7142
          * UNIV_PAGE_SIZE;
7227
7143
 
 
7144
    dict_table_stats_unlock(ib_table, RW_S_LATCH);
 
7145
 
7228
7146
    /* Since fsp_get_available_space_in_free_extents() is
7229
7147
    acquiring latches inside InnoDB, we do not call it if we
7230
7148
    are asked by MySQL to avoid locking. Another reason to
7241
7159
         innodb_crash_recovery is set to a high value. */
7242
7160
      stats.delete_length = 0;
7243
7161
    } 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
 
 
 
7162
      ullint    avail_space;
 
7163
 
 
7164
      avail_space = fsp_get_available_space_in_free_extents(ib_table->space);
 
7165
 
 
7166
      if (avail_space == ULLINT_UNDEFINED) {
7257
7167
        Session*  session;
7258
7168
 
7259
7169
        session= getTable()->in_use;
7271
7181
          ib_table->name);
7272
7182
 
7273
7183
        stats.delete_length = 0;
 
7184
      } else {
 
7185
        stats.delete_length = avail_space * 1024;
7274
7186
      }
7275
 
 
7276
 
      row_mysql_unlock_data_dictionary(prebuilt->trx);
7277
7187
    }
7278
7188
 
7279
7189
    stats.check_time = 0;
7293
7203
    ulint       num_innodb_index = UT_LIST_GET_LEN(ib_table->indexes) - prebuilt->clust_index_was_generated;
7294
7204
 
7295
7205
    if (getTable()->getShare()->keys != num_innodb_index) {
7296
 
      errmsg_printf(ERRMSG_LVL_ERROR, "Table %s contains %lu "
 
7206
      errmsg_printf(error::ERROR, "Table %s contains %lu "
7297
7207
                      "indexes inside InnoDB, which "
7298
7208
                      "is different from the number of "
7299
7209
                      "indexes %u defined in the MySQL ",
7301
7211
                      getTable()->getShare()->keys);
7302
7212
    }
7303
7213
 
 
7214
    dict_table_stats_lock(ib_table, RW_S_LATCH);
 
7215
 
7304
7216
    for (i = 0; i < getTable()->getShare()->sizeKeys(); i++) {
7305
7217
      ulong j;
7306
7218
      /* We could get index quickly through internal
7311
7223
      index = innobase_get_index(i);
7312
7224
 
7313
7225
      if (index == NULL) {
7314
 
        errmsg_printf(ERRMSG_LVL_ERROR, "Table %s contains fewer "
 
7226
        errmsg_printf(error::ERROR, "Table %s contains fewer "
7315
7227
            "indexes inside InnoDB than "
7316
7228
            "are defined in the MySQL "
7317
7229
            ".frm file. Have you mixed up "
7326
7238
      for (j = 0; j < getTable()->key_info[i].key_parts; j++) {
7327
7239
 
7328
7240
        if (j + 1 > index->n_uniq) {
7329
 
          errmsg_printf(ERRMSG_LVL_ERROR, 
 
7241
          errmsg_printf(error::ERROR, 
7330
7242
"Index %s of %s has %lu columns unique inside InnoDB, but MySQL is asking "
7331
7243
"statistics for %lu columns. Have you mixed up .frm files from different "
7332
7244
"installations? "
7338
7250
          break;
7339
7251
        }
7340
7252
 
7341
 
        dict_index_stat_mutex_enter(index);
7342
 
 
7343
7253
        if (index->stat_n_diff_key_vals[j + 1] == 0) {
7344
7254
 
7345
7255
          rec_per_key = stats.records;
7348
7258
           index->stat_n_diff_key_vals[j + 1]);
7349
7259
        }
7350
7260
 
7351
 
        dict_index_stat_mutex_exit(index);
7352
 
 
7353
7261
        /* Since MySQL seems to favor table scans
7354
7262
        too much over index searches, we pretend
7355
7263
        index selectivity is 2 times better than
7366
7274
          (ulong) rec_per_key;
7367
7275
      }
7368
7276
    }
 
7277
 
 
7278
    dict_table_stats_unlock(ib_table, RW_S_LATCH);
7369
7279
  }
7370
7280
 
7371
7281
  if (srv_force_recovery >= SRV_FORCE_NO_IBUF_MERGE) {
7445
7355
  }
7446
7356
 
7447
7357
  if (prebuilt->table->ibd_file_missing) {
7448
 
        errmsg_printf(ERRMSG_LVL_ERROR, "InnoDB: Error:\n"
 
7358
        errmsg_printf(error::ERROR, "InnoDB: Error:\n"
7449
7359
                    "InnoDB: MySQL is trying to use a table handle"
7450
7360
                    " but the .ibd file for\n"
7451
7361
                    "InnoDB: table %s does not exist.\n"
7695
7605
  flen = ftell(srv_dict_tmpfile);
7696
7606
  if (flen < 0) {
7697
7607
    flen = 0;
7698
 
  } else if (flen > 64000 - 1) {
7699
 
    flen = 64000 - 1;
7700
7608
  }
7701
7609
 
7702
7610
  /* allocate buffer for the string, and
7756
7664
      i++;
7757
7665
    }
7758
7666
    db_name[i] = 0;
7759
 
    ulen= TableIdentifier::filename_to_tablename(db_name, uname, sizeof(uname));
 
7667
    ulen= identifier::Table::filename_to_tablename(db_name, uname, sizeof(uname));
7760
7668
    LEX_STRING *tmp_referenced_db = session->make_lex_string(NULL, uname, ulen, true);
7761
7669
 
7762
7670
    /* Table name */
7763
7671
    tmp_buff += i + 1;
7764
 
    ulen= TableIdentifier::filename_to_tablename(tmp_buff, uname, sizeof(uname));
 
7672
    ulen= identifier::Table::filename_to_tablename(tmp_buff, uname, sizeof(uname));
7765
7673
    LEX_STRING *tmp_referenced_table = session->make_lex_string(NULL, uname, ulen, true);
7766
7674
 
7767
7675
    /** Foreign Fields **/
7839
7747
                              tmp_foreign_fields, tmp_referenced_fields);
7840
7748
 
7841
7749
    ForeignKeyInfo *pf_key_info = (ForeignKeyInfo *)
7842
 
      session->memdup(&f_key_info, sizeof(ForeignKeyInfo));
 
7750
      session->getMemRoot()->duplicate(&f_key_info, sizeof(ForeignKeyInfo));
7843
7751
    f_key_list->push_back(pf_key_info);
7844
7752
    foreign = UT_LIST_GET_NEXT(foreign_list, foreign);
7845
7753
  }
8369
8277
static INNOBASE_SHARE* get_share(const char* table_name)
8370
8278
{
8371
8279
  INNOBASE_SHARE *share;
8372
 
  pthread_mutex_lock(&innobase_share_mutex);
 
8280
  boost::mutex::scoped_lock scopedLock(innobase_share_mutex);
8373
8281
 
8374
8282
  ulint fold = ut_fold_string(table_name);
8375
8283
 
8396
8304
  }
8397
8305
 
8398
8306
  share->use_count++;
8399
 
  pthread_mutex_unlock(&innobase_share_mutex);
8400
8307
 
8401
8308
  return(share);
8402
8309
}
8403
8310
 
8404
8311
static void free_share(INNOBASE_SHARE* share)
8405
8312
{
8406
 
  pthread_mutex_lock(&innobase_share_mutex);
 
8313
  boost::mutex::scoped_lock scopedLock(innobase_share_mutex);
8407
8314
 
8408
8315
#ifdef UNIV_DEBUG
8409
8316
  INNOBASE_SHARE* share2;
8432
8339
    /* TODO: invoke HASH_MIGRATE if innobase_open_tables
8433
8340
    shrinks too much */
8434
8341
  }
8435
 
 
8436
 
  pthread_mutex_unlock(&innobase_share_mutex);
8437
8342
}
8438
8343
 
8439
8344
/*****************************************************************//**
8468
8373
  trx = check_trx_exists(session);
8469
8374
 
8470
8375
  assert(EQ_CURRENT_SESSION(session));
8471
 
  const uint32_t sql_command = session_sql_command(session);
 
8376
  const uint32_t sql_command = session->getSqlCommand();
8472
8377
 
8473
8378
  if (sql_command == SQLCOM_DROP_TABLE) {
8474
8379
 
8554
8459
 
8555
8460
    if ((lock_type >= TL_WRITE_CONCURRENT_INSERT
8556
8461
         && lock_type <= TL_WRITE)
8557
 
        && !session_tablespace_op(session)
 
8462
        && ! session->doing_tablespace_operation()
8558
8463
        && sql_command != SQLCOM_TRUNCATE
8559
8464
        && sql_command != SQLCOM_CREATE_TABLE) {
8560
8465
 
8631
8536
 
8632
8537
  if (auto_inc == 0) {
8633
8538
    ut_print_timestamp(stderr);
8634
 
    fprintf(stderr, "  InnoDB: AUTOINC next value generation "
8635
 
            "is disabled for '%s'\n", innodb_table->name);
 
8539
    errmsg_printf(error::ERROR, "  InnoDB: AUTOINC next value generation is disabled for '%s'\n", innodb_table->name);
8636
8540
  }
8637
8541
 
8638
8542
  dict_table_autoinc_unlock(innodb_table);
8787
8691
/* See comment in Cursor.cc */
8788
8692
UNIV_INTERN
8789
8693
bool
8790
 
InnobaseEngine::get_error_message(int, String *buf)
 
8694
InnobaseEngine::get_error_message(int, String *buf) const
8791
8695
{
8792
8696
  trx_t*  trx = check_trx_exists(current_session);
8793
8697
 
8871
8775
finds charset information and returns length of prefix_len characters in the
8872
8776
index field in bytes.
8873
8777
@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
8778
 
8885
8779
ulint
8886
8780
innobase_get_at_most_n_mbchars(
8894
8788
{
8895
8789
  ulint char_length;    /*!< character length in bytes */
8896
8790
  ulint n_chars;      /*!< number of characters in prefix */
8897
 
  const CHARSET_INFO* charset;  /*!< charset used in the field */
 
8791
  const charset_info_st* charset;  /*!< charset used in the field */
8898
8792
 
8899
8793
  charset = get_charset((uint) charset_id);
8900
8794
 
8964
8858
  trx->detailed_error[0]= '\0';
8965
8859
 
8966
8860
  /* Set the isolation level of the transaction. */
8967
 
  trx->isolation_level= innobase_map_isolation_level(session_tx_isolation(session));
 
8861
  trx->isolation_level= innobase_map_isolation_level(session->getTxIsolation());
8968
8862
}
8969
8863
 
8970
8864
void
9007
8901
    return(0);
9008
8902
  }
9009
8903
 
9010
 
  session->get_xid(reinterpret_cast<DRIZZLE_XID*>(&trx->xid));
 
8904
  session->get_xid(reinterpret_cast<DrizzleXid*>(&trx->xid));
9011
8905
 
9012
8906
  /* Release a possible FIFO ticket and search latch. Since we will
9013
8907
  reserve the kernel mutex, we have to release the search system latch
9232
9126
          "Purge threads can be either 0 or 1. Defalut is 0.");
9233
9127
  context("file-per-table",
9234
9128
          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.");
 
9129
           "Stores each InnoDB table to an .ibd file in the database dir.");
9239
9130
  context("file-format-max",
9240
9131
          po::value<string>(&innobase_file_format_max)->default_value("Antelope"),
9241
9132
          "The highest file format in the tablespace.");
9242
9133
  context("file-format-check",
9243
9134
          po::value<bool>(&innobase_file_format_check)->default_value(true)->zero_tokens(),
9244
9135
          "Whether to perform system file format check.");
 
9136
  context("file-format",
 
9137
          po::value<string>(&innobase_file_format_name)->default_value("Antelope"),
 
9138
          "File format to use for new tables in .ibd files.");
9245
9139
  context("flush-log-at-trx-commit",
9246
9140
          po::value<trinary_constraint>(&innodb_flush_log_at_trx_commit)->default_value(1),
9247
9141
          "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
9170
          po::value<additional_mem_pool_constraint>(&innobase_additional_mem_pool_size)->default_value(8*1024*1024L),
9277
9171
          "Size of a memory pool InnoDB uses to store data dictionary information and other internal data structures.");
9278
9172
  context("autoextend-increment",
9279
 
          po::value<autoextend_constraint>(&innodb_auto_extend_increment)->default_value(8L),
 
9173
          po::value<autoextend_constraint>(&innodb_auto_extend_increment)->default_value(64L),
9280
9174
          "Data file autoextend increment in megabytes");
9281
9175
  context("buffer-pool-size",
9282
9176
          po::value<buffer_pool_constraint>(&innobase_buffer_pool_size)->default_value(128*1024*1024L),
9335
9229
          "InnoDB version");
9336
9230
  context("use-internal-malloc",
9337
9231
          "Use InnoDB's internal memory allocator instal of the OS memory allocator.");
 
9232
  context("disable-native-aio",
 
9233
          _("Do not use Native AIO library for IO, even if available"));
9338
9234
  context("change-buffering",
9339
9235
          po::value<string>(&innobase_change_buffering),
9340
9236
          "Buffer changes to reduce random access: OFF, ON, inserting, deleting, changing, or purging.");
9349
9245
          po::value<bool>(&strict_mode)->default_value(false)->zero_tokens(),
9350
9246
          "Use strict mode when evaluating create options.");
9351
9247
  context("replication-log",
9352
 
          po::value<bool>(&innobase_use_replication_log)->default_value(false),
 
9248
          po::value<bool>(&innobase_use_replication_log)->default_value(false)->zero_tokens(),
9353
9249
          _("Enable internal replication log."));
9354
9250
  context("lock-wait-timeout",
9355
9251
          po::value<lock_wait_constraint>(&lock_wait_timeout)->default_value(50),
9375
9271
  "Supports transactions, row-level locking, and foreign keys",
9376
9272
  PLUGIN_LICENSE_GPL,
9377
9273
  innobase_init, /* Plugin Init */
9378
 
  NULL, /* system variables */
 
9274
  NULL, /* depends */
9379
9275
  init_options /* reserved */
9380
9276
}
9381
9277
DRIZZLE_DECLARE_PLUGIN_END;
9407
9303
This function checks each index name for a table against reserved
9408
9304
system default primary index name 'GEN_CLUST_INDEX'. If a name matches,
9409
9305
this function pushes an warning message to the client, and returns true. */
9410
 
extern "C" UNIV_INTERN
 
9306
UNIV_INTERN
9411
9307
bool
9412
9308
innobase_index_name_is_reserved(
9413
9309
/*============================*/
9427
9323
    if (innobase_strcasecmp(key->name,
9428
9324
                            innobase_index_reserve_name) == 0) {
9429
9325
      /* Push warning to drizzle */
9430
 
      push_warning_printf((Session*)trx->mysql_thd,
 
9326
      push_warning_printf(trx->mysql_thd,
9431
9327
                          DRIZZLE_ERROR::WARN_LEVEL_WARN,
9432
9328
                          ER_WRONG_NAME_FOR_INDEX,
9433
9329
                          "Cannot Create Index with name "
9453
9349
  ulint   buflen;
9454
9350
  const char* id;
9455
9351
  ulint   idlen;
9456
 
  void*   session;
 
9352
  drizzled::Session *session;
9457
9353
  ibool   file_id;
9458
9354
 
9459
9355
  const char* expected;