1
1
/*****************************************************************************
3
Copyright (c) 2000, 2010, MySQL AB & Innobase Oy. All Rights Reserved.
4
Copyright (c) 2008, 2009 Google Inc.
5
Copyright (c) 2009, Percona Inc.
3
Copyright (C) 2000, 2010, MySQL AB & Innobase Oy. All Rights Reserved.
4
Copyright (C) 2008, 2009 Google Inc.
5
Copyright (C) 2009, Percona Inc.
7
7
Portions of this file contain modifications contributed and copyrighted by
8
8
Google, Inc. Those modifications are gratefully acknowledged and are described
136
133
#include <google/protobuf/io/coded_stream.h>
137
134
#include <google/protobuf/text_format.h>
136
#include <boost/thread/mutex.hpp>
139
138
using namespace std;
140
139
using namespace drizzled;
142
141
/** to protect innobase_open_files */
143
static pthread_mutex_t innobase_share_mutex;
142
static boost::mutex innobase_share_mutex;
144
144
/** to force correct commit order in binlog */
145
static pthread_mutex_t prepare_commit_mutex;
146
145
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;
146
static boost::condition_variable commit_cond;
147
static boost::mutex commit_cond_m;
150
148
static bool innodb_inited = 0;
152
150
#define INSIDE_HA_INNOBASE_CC
162
160
#endif /* MYSQL_DYNAMIC_PLUGIN && __WIN__ */
164
162
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;
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;
182
static ReplicationLog *replication_logger= NULL;
183
164
typedef constrained_check<uint32_t, UINT32_MAX, 10> open_files_constraint;
184
165
static open_files_constraint innobase_open_files;
185
166
typedef constrained_check<uint32_t, 10, 1> mirrored_log_groups_constraint;
204
185
static purge_batch_constraint innodb_purge_batch_size;
205
186
typedef constrained_check<uint32_t, 1, 0> purge_threads_constraint;
206
187
static purge_threads_constraint innodb_n_purge_threads;
207
typedef constrained_check<uint16_t, 2, 0> trinary_constraint;
188
typedef constrained_check<uint32_t, 2, 0> trinary_constraint;
208
189
static trinary_constraint innodb_flush_log_at_trx_commit;
209
190
typedef constrained_check<unsigned int, 99, 0> max_dirty_pages_constraint;
210
191
static max_dirty_pages_constraint innodb_max_dirty_pages_pct;
486
462
UNIV_INTERN int doCreateTable(Session &session,
488
const TableIdentifier &identifier,
464
const identifier::Table &identifier,
489
465
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
UNIV_INTERN int doRenameTable(Session&, const identifier::Table &from, const identifier::Table &to);
467
UNIV_INTERN int doDropTable(Session &session, const identifier::Table &identifier);
493
UNIV_INTERN virtual bool get_error_message(int error, String *buf);
469
UNIV_INTERN virtual bool get_error_message(int error, String *buf) const;
495
471
UNIV_INTERN uint32_t max_supported_keys() const;
496
472
UNIV_INTERN uint32_t max_supported_key_length() const;
509
485
int doGetTableDefinition(drizzled::Session& session,
510
const TableIdentifier &identifier,
486
const identifier::Table &identifier,
511
487
drizzled::message::Table &table_proto);
513
bool doDoesTableExist(drizzled::Session& session, const TableIdentifier &identifier);
489
bool doDoesTableExist(drizzled::Session& session, const identifier::Table &identifier);
515
491
void doGetTableIdentifiers(drizzled::CachedDirectory &directory,
516
const drizzled::SchemaIdentifier &schema_identifier,
517
drizzled::TableIdentifier::vector &set_of_identifiers);
492
const drizzled::identifier::Schema &schema_identifier,
493
drizzled::identifier::Table::vector &set_of_identifiers);
518
494
bool validateCreateTableOption(const std::string &key, const std::string &state);
519
495
void dropTemporarySchema();
544
520
void InnobaseEngine::doGetTableIdentifiers(drizzled::CachedDirectory &directory,
545
const drizzled::SchemaIdentifier &schema_identifier,
546
drizzled::TableIdentifier::vector &set_of_identifiers)
521
const drizzled::identifier::Schema &schema_identifier,
522
drizzled::identifier::Table::vector &set_of_identifiers)
548
524
CachedDirectory::Entries entries= directory.getEntries();
526
std::string search_string(schema_identifier.getSchemaName());
528
boost::algorithm::to_lower(search_string);
530
if (search_string.compare("data_dictionary") == 0)
532
set_of_identifiers.push_back(identifier::Table(schema_identifier.getSchemaName(), "SYS_REPLICATION_LOG"));
550
535
for (CachedDirectory::Entries::iterator entry_iter= entries.begin();
551
536
entry_iter != entries.end(); ++entry_iter)
574
559
Using schema_identifier here to stop unused warning, could use
575
560
definition.schema() instead
577
TableIdentifier identifier(schema_identifier.getSchemaName(), definition.name());
562
identifier::Table identifier(schema_identifier.getSchemaName(), definition.name());
578
563
set_of_identifiers.push_back(identifier);
584
bool InnobaseEngine::doDoesTableExist(Session &session, const TableIdentifier &identifier)
569
bool InnobaseEngine::doDoesTableExist(Session &session, const identifier::Table &identifier)
586
571
string proto_path(identifier.getPath());
587
572
proto_path.append(DEFAULT_FILE_EXTENSION);
878
872
DRIZZLE: Note, we didn't change this name to avoid more ifdef forking
879
873
in non-Cursor code.
880
874
@return true if non-transactional tables have been edited */
881
extern "C" UNIV_INTERN
883
877
thd_has_edited_nontrans_tables(
884
878
/*===========================*/
885
void* session) /*!< in: thread handle (Session*) */
879
drizzled::Session *session) /*!< in: thread handle (Session*) */
887
return((ibool)((Session *)session)->transaction.all.hasModifiedNonTransData());
881
return((ibool)session->transaction.all.hasModifiedNonTransData());
890
884
/******************************************************************//**
891
885
Returns true if the thread is executing a SELECT statement.
892
886
@return true if session is executing SELECT */
893
extern "C" UNIV_INTERN
897
const void* session) /*!< in: thread handle (Session*) */
891
const drizzled::Session *session) /*!< in: thread handle (Session*) */
899
return(session_sql_command((const Session*) session) == SQLCOM_SELECT);
893
return(session->getSqlCommand() == SQLCOM_SELECT);
902
896
/******************************************************************//**
903
897
Returns true if the thread supports XA,
904
898
global value of innodb_supports_xa if session is NULL.
905
899
@return true if session has XA support */
906
extern "C" UNIV_INTERN
910
void* ) /*!< in: thread handle (Session*), or NULL to query
904
drizzled::Session* ) /*!< in: thread handle (Session*), or NULL to query
911
905
the global innodb_supports_xa */
913
907
/* TODO: Add support here for per-session value */
933
927
/******************************************************************//**
934
928
Set the time waited for the lock for the current query. */
935
extern "C" UNIV_INTERN
937
931
thd_set_lock_wait_time(
938
932
/*===================*/
939
void* thd, /*!< in: thread handle (THD*) */
933
drizzled::Session* in_session, /*!< in: thread handle (THD*) */
940
934
ulint value) /*!< in: time waited for the lock */
943
static_cast<Session*>(thd)->utime_after_lock+= value;
937
in_session->utime_after_lock+= value;
947
940
/********************************************************************//**
967
960
trx_t *trx= session_to_trx(&session);
969
962
uint64_t trx_id= message.transaction_context().transaction_id();
970
ulint error= insert_replication_message(data, message.ByteSize(), trx, trx_id);
963
uint32_t seg_id= message.segment_id();
964
uint64_t end_timestamp= message.transaction_context().end_timestamp();
965
bool is_end_segment= message.end_segment();
966
trx->log_commit_id= TRUE;
967
ulint error= insert_replication_message(data, message.ByteSize(), trx, trx_id,
968
end_timestamp, is_end_segment, seg_id);
1168
1167
/*************************************************************//**
1169
1168
Prints info of a Session object (== user session thread) to the given file. */
1170
extern "C" UNIV_INTERN
1172
1171
innobase_mysql_print_thd(
1173
1172
/*=====================*/
1174
1173
FILE* f, /*!< in: output stream */
1175
void * in_session, /*!< in: pointer to a Drizzle Session object */
1174
drizzled::Session *in_session, /*!< in: pointer to a Drizzle Session object */
1176
1175
uint ) /*!< in: max query length to print, or 0 to
1177
1176
use the default max length */
1179
Session *session= reinterpret_cast<Session *>(in_session);
1178
drizzled::identifier::User::const_shared_ptr user_identifier(in_session->user());
1181
1181
"Drizzle thread %"PRIu64", query id %"PRIu64", %s, %s, %s ",
1182
static_cast<uint64_t>(session->getSessionId()),
1183
static_cast<uint64_t>(session->getQueryId()),
1182
static_cast<uint64_t>(in_session->getSessionId()),
1183
static_cast<uint64_t>(in_session->getQueryId()),
1185
session->getSecurityContext().getIp().c_str(),
1186
session->getSecurityContext().getUser().c_str()
1185
user_identifier->address().c_str(),
1186
user_identifier->username().c_str()
1188
fprintf(f, "\n%s", session->getQueryString()->c_str());
1188
fprintf(f, "\n%s", in_session->getQueryString()->c_str());
1192
1192
/******************************************************************//**
1193
1193
Get the variable length bounds of the given character set. */
1194
extern "C" UNIV_INTERN
1196
1196
innobase_get_cset_width(
1197
1197
/*====================*/
1289
1277
return my_isspace(static_cast<const CHARSET_INFO *>(cs), char_to_test);
1294
innobase_fast_mutex_init(
1295
os_fast_mutex_t* fast_mutex)
1297
return pthread_mutex_init(fast_mutex, MY_MUTEX_INIT_FAST);
1300
/**********************************************************************//**
1301
Determines the current SQL statement.
1302
@return SQL statement string */
1303
extern "C" UNIV_INTERN
1307
void* session, /*!< in: MySQL thread handle */
1308
size_t* length) /*!< out: length of the SQL statement */
1310
return static_cast<Session*>(session)->getQueryStringCopy(*length);
1313
1280
#if defined (__WIN__) && defined (MYSQL_DYNAMIC_PLUGIN)
1314
1281
/*******************************************************************//**
1315
1282
Map an OS error to an errno value. The OS error number is stored in
1316
1283
_doserrno and the mapped value is stored in errno) */
1320
1286
unsigned long); /*!< in: OS error value */
1402
1368
/*********************************************************************//**
1403
1369
Creates a temporary file.
1404
1370
@return temporary file descriptor, or < 0 on error */
1405
extern "C" UNIV_INTERN
1407
1373
innobase_mysql_tmpfile(void)
1408
1374
/*========================*/
1411
int fd = mysql_tmpfile("ib");
1377
int fd = ::drizzled::tmpfile("ib");
1413
1379
/* Copy the file descriptor, so that the additional resources
1414
1380
allocated by create_temp_file() can be freed by invoking
1665
1631
ulint buflen, /*!< in: length of buf, in bytes */
1666
1632
const char* id, /*!< in: identifier to convert */
1667
1633
ulint idlen, /*!< in: length of id, in bytes */
1668
void* session,/*!< in: MySQL connection thread, or NULL */
1634
drizzled::Session *session,/*!< in: MySQL connection thread, or NULL */
1669
1635
ibool file_id)/*!< in: TRUE=id is a table or database name;
1670
1636
FALSE=id is an UTF-8 string */
1672
1638
char nz[NAME_LEN + 1];
1673
char nz2[NAME_LEN + 1 + sizeof srv_mysql50_table_name_prefix];
1639
const size_t nz2_size= NAME_LEN + 1 + srv_mysql50_table_name_prefix.size();
1640
boost::scoped_array<char> nz2(new char[nz2_size]);
1675
1642
const char* s = id;
1750
1717
ulint buflen, /*!< in: length of buf, in bytes */
1751
1718
const char* id, /*!< in: identifier to convert */
1752
1719
ulint idlen, /*!< in: length of id, in bytes */
1753
void* session,/*!< in: MySQL connection thread, or NULL */
1720
drizzled::Session *session,/*!< in: MySQL connection thread, or NULL */
1754
1721
ibool table_id)/*!< in: TRUE=id is a table or database name;
1755
1722
FALSE=id is an index name */
1798
1765
/**********************************************************************//**
1799
1766
Determines if the currently running transaction has been interrupted.
1800
1767
@return TRUE if interrupted */
1801
extern "C" UNIV_INTERN
1803
1770
trx_is_interrupted(
1804
1771
/*===============*/
1805
1772
trx_t* trx) /*!< in: transaction */
1807
return(trx && trx->mysql_thd && static_cast<Session*>(trx->mysql_thd)->getKilled());
1774
return(trx && trx->mysql_thd && trx->mysql_thd->getKilled());
1810
1777
/**********************************************************************//**
1811
1778
Determines if the currently running transaction is in strict mode.
1812
1779
@return TRUE if strict */
1813
extern "C" UNIV_INTERN
2008
1975
if (format_id >= 0) {
2009
innobase_file_format_max=
2010
trx_sys_file_format_id_to_name((uint)format_id);
1976
innobase_file_format_max.assign(
1977
trx_sys_file_format_id_to_name((uint)format_id));
2012
1979
/* Update the max format id in the system tablespace. */
2013
char name_buff[100];
2014
strcpy(name_buff, innobase_file_format_max.c_str());
2015
if (trx_sys_file_format_max_set(format_id, (const char **)&name_buff))
1980
const char *name_buff;
1982
if (trx_sys_file_format_max_set(format_id, &name_buff))
2017
errmsg_printf(ERRMSG_LVL_WARN,
1984
errmsg_printf(error::WARN,
2018
1985
" [Info] InnoDB: the file format in the system "
2019
1986
"tablespace is now set to %s.\n", name_buff);
2020
1987
innobase_file_format_max= name_buff;
2102
2070
#ifdef UNIV_DEBUG
2103
2071
static const char test_filename[] = "-@";
2104
char test_tablename[sizeof test_filename
2105
+ sizeof srv_mysql50_table_name_prefix];
2106
if ((sizeof test_tablename) - 1
2107
!= filename_to_tablename(test_filename, test_tablename,
2108
sizeof test_tablename)
2109
|| strncmp(test_tablename,
2110
srv_mysql50_table_name_prefix,
2111
sizeof srv_mysql50_table_name_prefix)
2112
|| strcmp(test_tablename
2113
+ sizeof srv_mysql50_table_name_prefix,
2072
const size_t test_tablename_size= sizeof test_filename
2073
+ srv_mysql50_table_name_prefix.size();
2074
boost::scoped_array test_tablename(new char[test_tablename_size]);
2075
if ((test_tablename_size) - 1
2076
!= filename_to_tablename(test_filename, test_tablename.get(),
2077
test_tablename_size)
2078
|| strncmp(test_tablename.get(),
2079
srv_mysql50_table_name_prefix.c_str(),
2080
srv_mysql50_table_name_prefix.size())
2081
|| strcmp(test_tablename.get()
2082
+ srv_mysql50_table_name_prefix.size(),
2114
2083
test_filename)) {
2115
errmsg_printf(ERRMSG_LVL_ERROR, "tablename encoding has been changed");
2084
errmsg_printf(error::ERROR, "tablename encoding has been changed");
2118
2087
#endif /* UNIV_DEBUG */
2217
2185
srv_max_file_format_at_startup */
2218
2186
if (innobase_file_format_validate_and_set(innobase_file_format_max.c_str()) < 0)
2220
errmsg_printf(ERRMSG_LVL_ERROR, _("InnoDB: invalid "
2221
"innodb_file_format_max value: "
2222
"should be any value up to %s or its "
2223
"equivalent numeric id"),
2224
trx_sys_file_format_id_to_name(DICT_TF_FORMAT_MAX));
2188
errmsg_printf(error::ERROR, _("InnoDB: invalid innodb_file_format_max value: "
2189
"should be any value up to %s or its equivalent numeric id"),
2190
trx_sys_file_format_id_to_name(DICT_TF_FORMAT_MAX));
2225
2191
goto mem_free_and_error;
2322
2286
innobase_open_tables = hash_create(200);
2323
pthread_mutex_init(&innobase_share_mutex, MY_MUTEX_INIT_FAST);
2324
pthread_mutex_init(&prepare_commit_mutex, MY_MUTEX_INIT_FAST);
2325
pthread_mutex_init(&commit_threads_m, MY_MUTEX_INIT_FAST);
2326
pthread_mutex_init(&commit_cond_m, MY_MUTEX_INIT_FAST);
2327
pthread_cond_init(&commit_cond, NULL);
2328
2287
innodb_inited= 1;
2330
2289
actuall_engine_ptr->dropTemporarySchema();
2332
status_table_function_ptr= new InnodbStatusTool;
2291
context.add(new InnodbStatusTool);
2334
2293
context.add(innodb_engine_ptr);
2336
context.add(status_table_function_ptr);
2338
cmp_tool= new(std::nothrow)CmpTool(false);
2339
context.add(cmp_tool);
2341
cmp_reset_tool= new(std::nothrow)CmpTool(true);
2342
context.add(cmp_reset_tool);
2344
cmp_mem_tool= new(std::nothrow)CmpmemTool(false);
2345
context.add(cmp_mem_tool);
2347
cmp_mem_reset_tool= new(std::nothrow)CmpmemTool(true);
2348
context.add(cmp_mem_reset_tool);
2350
innodb_trx_tool= new(std::nothrow)InnodbTrxTool("INNODB_TRX");
2351
context.add(innodb_trx_tool);
2353
innodb_locks_tool= new(std::nothrow)InnodbTrxTool("INNODB_LOCKS");
2354
context.add(innodb_locks_tool);
2356
innodb_lock_waits_tool= new(std::nothrow)InnodbTrxTool("INNODB_LOCK_WAITS");
2357
context.add(innodb_lock_waits_tool);
2359
innodb_sys_tables_tool= new(std::nothrow)InnodbSysTablesTool();
2360
context.add(innodb_sys_tables_tool);
2362
innodb_sys_tablestats_tool= new(std::nothrow)InnodbSysTableStatsTool();
2363
context.add(innodb_sys_tablestats_tool);
2365
innodb_sys_indexes_tool= new(std::nothrow)InnodbSysIndexesTool();
2366
context.add(innodb_sys_indexes_tool);
2368
innodb_sys_columns_tool= new(std::nothrow)InnodbSysColumnsTool();
2369
context.add(innodb_sys_columns_tool);
2371
innodb_sys_fields_tool= new(std::nothrow)InnodbSysFieldsTool();
2372
context.add(innodb_sys_fields_tool);
2374
innodb_sys_foreign_tool= new(std::nothrow)InnodbSysForeignTool();
2375
context.add(innodb_sys_foreign_tool);
2377
innodb_sys_foreign_cols_tool= new(std::nothrow)InnodbSysForeignColsTool();
2378
context.add(innodb_sys_foreign_cols_tool);
2295
context.add(new(std::nothrow)CmpTool(false));
2297
context.add(new(std::nothrow)CmpTool(true));
2299
context.add(new(std::nothrow)CmpmemTool(false));
2301
context.add(new(std::nothrow)CmpmemTool(true));
2303
context.add(new(std::nothrow)InnodbTrxTool("INNODB_TRX"));
2305
context.add(new(std::nothrow)InnodbTrxTool("INNODB_LOCKS"));
2307
context.add(new(std::nothrow)InnodbTrxTool("INNODB_LOCK_WAITS"));
2309
context.add(new(std::nothrow)InnodbSysTablesTool());
2311
context.add(new(std::nothrow)InnodbSysTableStatsTool());
2313
context.add(new(std::nothrow)InnodbSysIndexesTool());
2315
context.add(new(std::nothrow)InnodbSysColumnsTool());
2317
context.add(new(std::nothrow)InnodbSysFieldsTool());
2319
context.add(new(std::nothrow)InnodbSysForeignTool());
2321
context.add(new(std::nothrow)InnodbSysForeignColsTool());
2380
2323
context.add(new(std::nothrow)InnodbInternalTables());
2381
2324
context.add(new(std::nothrow)InnodbReplicationTable());
2383
2326
if (innobase_use_replication_log)
2385
replication_logger= new(std::nothrow)ReplicationLog();
2328
ReplicationLog *replication_logger= new(std::nothrow)ReplicationLog();
2386
2329
context.add(replication_logger);
2387
2330
ReplicationLog::setup(replication_logger);
2434
2377
innodb_file_format_max_validate));
2435
2378
context.registerVariable(new sys_var_constrained_value_readonly<size_t>("buffer_pool_size", innobase_buffer_pool_size));
2436
2379
context.registerVariable(new sys_var_constrained_value_readonly<int64_t>("log_file_size", innobase_log_file_size));
2437
context.registerVariable(new sys_var_constrained_value_readonly<uint16_t>("flush_log_at_trx_commit",
2380
context.registerVariable(new sys_var_constrained_value_readonly<uint32_t>("flush_log_at_trx_commit",
2438
2381
innodb_flush_log_at_trx_commit));
2439
2382
context.registerVariable(new sys_var_constrained_value_readonly<unsigned int>("max_dirty_pages_pct",
2440
2383
innodb_max_dirty_pages_pct));
2569
2513
trx_search_latch_release_if_reserved(trx);
2573
|| (!session_test_options(session, OPTION_NOT_AUTOCOMMIT | OPTION_BEGIN))) {
2575
2518
/* We were instructed to commit the whole transaction, or
2576
2519
this is an SQL statement end and autocommit is on */
2578
2521
/* We need current binlog position for ibbackup to work.
2579
2522
Note, the position is current because of
2580
2523
prepare_commit_mutex */
2582
if (innobase_commit_concurrency.get() > 0) {
2583
pthread_mutex_lock(&commit_cond_m);
2586
if (commit_threads > innobase_commit_concurrency.get()) {
2524
const uint32_t commit_concurrency= innobase_commit_concurrency.get();
2525
if (commit_concurrency)
2529
boost::mutex::scoped_lock scopedLock(commit_cond_m);
2532
if (commit_threads <= commit_concurrency)
2587
2535
commit_threads--;
2588
pthread_cond_wait(&commit_cond,
2590
pthread_mutex_unlock(&commit_cond_m);
2594
pthread_mutex_unlock(&commit_cond_m);
2536
commit_cond.wait(scopedLock);
2598
/* Store transaction point for binlog
2599
Later logic tests that this is set to _something_. We need
2600
that logic to fire, even though we do not have a real name. */
2601
trx->mysql_log_file_name = "UNUSED";
2540
trx->mysql_log_file_name = NULL;
2602
2541
trx->mysql_log_offset = 0;
2604
2543
/* Don't do write + flush right now. For group commit
2941
/*****************************************************************//**
2942
Normalizes a table name string. A normalized name consists of the
2943
database name catenated to '/' and table name. An example:
2944
test/mytable. On Windows normalization puts both the database name and the
2945
table name always to lower case. */
2948
normalize_table_name(
2949
/*=================*/
2950
char* norm_name, /*!< out: normalized name as a
2951
null-terminated string */
2952
const char* name) /*!< in: table name string */
2954
const char* name_ptr;
2958
/* Scan name from the end */
2960
ptr = strchr(name, '\0')-1;
2962
while (ptr >= name && *ptr != '\\' && *ptr != '/') {
2972
while (ptr >= name && *ptr != '\\' && *ptr != '/') {
2978
memcpy(norm_name, db_ptr, strlen(name) + 1 - (db_ptr - name));
2980
norm_name[name_ptr - db_ptr - 1] = '/';
2983
innobase_casedn_str(norm_name);
2987
2879
/********************************************************************//**
2988
2880
Get the upper limit of the MySQL integral and floating-point type.
2989
2881
@return maximum allowed value for the field */
3150
3042
if (!index_mapping) {
3151
3043
/* Report an error if index_mapping continues to be
3152
3044
NULL and mysql_num_index is a non-zero value */
3153
errmsg_printf(ERRMSG_LVL_ERROR,
3154
"InnoDB: fail to allocate memory for "
3155
"index translation table. Number of "
3156
"Index:%lu, array size:%lu",
3045
errmsg_printf(error::ERROR, "InnoDB: fail to allocate memory for "
3046
"index translation table. Number of Index:%lu, array size:%lu",
3157
3047
mysql_num_index,
3158
3048
share->idx_trans_tbl.array_size);
3174
3064
ib_table, table->key_info[count].name);
3176
3066
if (!index_mapping[count]) {
3177
errmsg_printf(ERRMSG_LVL_ERROR, "Cannot find index %s in InnoDB "
3178
"index dictionary.",
3179
table->key_info[count].name);
3067
errmsg_printf(error::ERROR, "Cannot find index %s in InnoDB index dictionary.",
3068
table->key_info[count].name);
3181
3070
goto func_exit;
3184
3073
/* Double check fetched index has the same
3185
3074
column info as those in mysql key_info. */
3186
if (!innobase_match_index_columns(&table->key_info[count],
3187
index_mapping[count])) {
3188
errmsg_printf(ERRMSG_LVL_ERROR, "Found index %s whose column info "
3189
"does not match that of MySQL.",
3190
table->key_info[count].name);
3075
if (!innobase_match_index_columns(&table->key_info[count], index_mapping[count])) {
3076
errmsg_printf(error::ERROR, "Found index %s whose column info does not match that of MySQL.",
3077
table->key_info[count].name);
3311
3197
case DB_RECORD_NOT_FOUND:
3312
3198
ut_print_timestamp(stderr);
3313
fprintf(stderr, " InnoDB: MySQL and InnoDB data "
3314
"dictionaries are out of sync.\n"
3315
"InnoDB: Unable to find the AUTOINC column "
3316
"%s in the InnoDB table %s.\n"
3317
"InnoDB: We set the next AUTOINC column "
3319
"InnoDB: in effect disabling the AUTOINC "
3320
"next value generation.\n"
3321
"InnoDB: You can either set the next "
3322
"AUTOINC value explicitly using ALTER TABLE\n"
3323
"InnoDB: or fix the data dictionary by "
3324
"recreating the table.\n",
3325
col_name, index->table->name);
3199
errmsg_printf(error::ERROR, "InnoDB: MySQL and InnoDB data dictionaries are out of sync.\n"
3200
"InnoDB: Unable to find the AUTOINC column %s in the InnoDB table %s.\n"
3201
"InnoDB: We set the next AUTOINC column value to 0,\n"
3202
"InnoDB: in effect disabling the AUTOINC next value generation.\n"
3203
"InnoDB: You can either set the next AUTOINC value explicitly using ALTER TABLE\n"
3204
"InnoDB: or fix the data dictionary by recreating the table.\n",
3205
col_name, index->table->name);
3327
3207
/* This will disable the AUTOINC generation. */
3368
3247
getTransactionalEngine()->releaseTemporaryLatches(session);
3371
normalize_table_name(norm_name, identifier.getPath().c_str());
3373
3250
user_session = NULL;
3375
if (!(share=get_share(identifier.getPath().c_str()))) {
3252
std::string search_string(identifier.getSchemaName());
3253
boost::algorithm::to_lower(search_string);
3255
if (search_string.compare("data_dictionary") == 0)
3257
std::string table_name(identifier.getTableName());
3258
boost::algorithm::to_upper(table_name);
3259
if (!(share=get_share(table_name.c_str())))
3266
if (!(share=get_share(identifier.getKeyPath().c_str())))
3380
3272
/* Create buffers for packing the fields of a record. Why
3403
3295
/* Get pointer to a table object in InnoDB dictionary cache */
3404
ib_table = dict_table_get(norm_name, TRUE);
3296
if (search_string.compare("data_dictionary") == 0)
3298
std::string table_name(identifier.getTableName());
3299
boost::algorithm::to_upper(table_name);
3300
ib_table = dict_table_get(table_name.c_str(), TRUE);
3304
ib_table = dict_table_get(identifier.getKeyPath().c_str(), TRUE);
3406
3307
if (NULL == ib_table) {
3407
errmsg_printf(ERRMSG_LVL_ERROR, "Cannot find or open table %s from\n"
3308
errmsg_printf(error::ERROR, "Cannot find or open table %s from\n"
3408
3309
"the internal data dictionary of InnoDB "
3409
3310
"though the .frm file for the\n"
3410
3311
"table exists. Maybe you have deleted and "
3427
3328
return(HA_ERR_NO_SUCH_TABLE);
3430
if (ib_table->ibd_file_missing && !session_tablespace_op(session)) {
3431
errmsg_printf(ERRMSG_LVL_ERROR, "MySQL is trying to open a table handle but "
3331
if (ib_table->ibd_file_missing && ! session->doing_tablespace_operation()) {
3332
errmsg_printf(error::ERROR, "MySQL is trying to open a table handle but "
3432
3333
"the .ibd file for\ntable %s does not exist.\n"
3433
3334
"Have you deleted the .ibd file from the "
3434
3335
"database directory under\nthe MySQL datadir, "
3435
3336
"or have you used DISCARD TABLESPACE?\n"
3436
3337
"See " REFMAN "innodb-troubleshooting.html\n"
3437
3338
"how you can resolve the problem.\n",
3339
identifier.getKeyPath().c_str());
3439
3340
free_share(share);
3440
3341
upd_buff.resize(0);
3441
3342
key_val_buff.resize(0);
3457
3358
key_used_on_scan = primary_key;
3459
3360
if (!innobase_build_index_translation(getTable(), ib_table, share)) {
3460
errmsg_printf(ERRMSG_LVL_ERROR, "Build InnoDB index translation table for"
3461
" Table %s failed", identifier.getPath().c_str());
3361
errmsg_printf(error::ERROR, "Build InnoDB index translation table for"
3362
" Table %s failed", identifier.getKeyPath().c_str());
3464
3365
/* Allocate a buffer for a 'row reference'. A row reference is
4286
4189
n_requested_fields++;
4288
4191
templ->col_no = i;
4192
templ->clust_rec_field_no = dict_col_get_clust_pos(col, clust_index);
4193
ut_ad(templ->clust_rec_field_no != ULINT_UNDEFINED);
4290
4195
if (index == clust_index) {
4291
templ->rec_field_no = dict_col_get_clust_pos(col, index);
4196
templ->rec_field_no = templ->clust_rec_field_no;
4293
4198
templ->rec_field_no = dict_index_get_nth_col_pos(
4297
if (templ->rec_field_no == ULINT_UNDEFINED) {
4298
prebuilt->need_to_access_clustered = TRUE;
4200
if (templ->rec_field_no == ULINT_UNDEFINED) {
4201
prebuilt->need_to_access_clustered = TRUE;
4301
4205
if (field->null_ptr) {
6275
6177
if (lex_identified_temp_table)
6276
6178
iflags |= DICT_TF2_TEMPORARY << DICT_TF2_SHIFT;
6278
error= create_table_def(trx, &form, norm_name,
6279
lex_identified_temp_table ? name2 : NULL,
6180
error= create_table_def(trx, &form, identifier.getKeyPath().c_str(),
6181
lex_identified_temp_table ? identifier.getKeyPath().c_str() : NULL,
6282
6184
session.setXaId(trx->id);
6309
6211
for (i = 0; i < form.getShare()->sizeKeys(); i++) {
6310
6212
if (i != (uint) primary_key_no) {
6312
if ((error = create_index(trx, &form, iflags, norm_name,
6214
if ((error = create_index(trx, &form, iflags, identifier.getKeyPath().c_str(),
6319
stmt = innobase_get_stmt(&session, &stmt_len);
6221
stmt= session.getQueryStringCopy(stmt_len);
6322
6224
string generated_create_table;
6323
6225
const char *query= stmt;
6325
if (session_sql_command(&session) == SQLCOM_CREATE_TABLE)
6227
if (session.getSqlCommand() == SQLCOM_CREATE_TABLE)
6327
6229
message::transformTableDefinitionToSql(create_proto,
6328
6230
generated_create_table,
6333
6235
error = row_table_add_foreign_constraints(trx,
6334
6236
query, strlen(query),
6237
identifier.getKeyPath().c_str(),
6336
6238
lex_identified_temp_table);
6241
case DB_PARENT_NO_INDEX:
6242
push_warning_printf(
6243
&session, DRIZZLE_ERROR::WARN_LEVEL_WARN,
6244
HA_ERR_CANNOT_ADD_FOREIGN,
6245
"Create table '%s' with foreign key constraint"
6246
" failed. There is no index in the referenced"
6247
" table where the referenced columns appear"
6248
" as the first columns.\n", identifier.getKeyPath().c_str());
6251
case DB_CHILD_NO_INDEX:
6252
push_warning_printf(
6253
&session, DRIZZLE_ERROR::WARN_LEVEL_WARN,
6254
HA_ERR_CANNOT_ADD_FOREIGN,
6255
"Create table '%s' with foreign key constraint"
6256
" failed. There is no index in the referencing"
6257
" table where referencing columns appear"
6258
" as the first columns.\n", identifier.getKeyPath().c_str());
6338
6262
error = convert_error_code_to_mysql(error, iflags, NULL);
6503
6427
InnobaseEngine::doDropTable(
6504
6428
/*======================*/
6505
6429
Session &session,
6506
const TableIdentifier &identifier)
6430
const identifier::Table &identifier)
6509
6433
trx_t* parent_trx;
6511
char norm_name[1000];
6513
6436
ut_a(identifier.getPath().length() < 1000);
6515
/* Strangely, MySQL passes the table name without the '.frm'
6516
extension, in contrast to ::create */
6517
normalize_table_name(norm_name, identifier.getPath().c_str());
6438
std::string search_string(identifier.getSchemaName());
6439
boost::algorithm::to_lower(search_string);
6441
if (search_string.compare("data_dictionary") == 0)
6443
return HA_ERR_TABLE_READONLY;
6519
6446
/* Get the transaction associated with the current session, or create one
6520
6447
if not yet created */
6681
6608
innobase_rename_table(
6682
6609
/*==================*/
6683
6610
trx_t* trx, /*!< in: transaction */
6684
const char* from, /*!< in: old name of the table */
6685
const char* to, /*!< in: new name of the table */
6611
const identifier::Table &from,
6612
const identifier::Table &to,
6686
6613
ibool lock_and_commit)
6687
6614
/*!< in: TRUE=lock data dictionary and commit */
6690
char norm_to[FN_REFLEN];
6691
char norm_from[FN_REFLEN];
6693
6618
srv_lower_case_table_names = TRUE;
6695
normalize_table_name(norm_to, to);
6696
normalize_table_name(norm_from, from);
6698
6620
/* Serialize data dictionary operations with dictionary mutex:
6699
6621
no deadlocks can occur then in these operations */
6702
6624
row_mysql_lock_data_dictionary(trx);
6705
error = row_rename_table_for_mysql(
6706
norm_from, norm_to, trx, lock_and_commit);
6627
error = row_rename_table_for_mysql(from.getKeyPath().c_str(), to.getKeyPath().c_str(), trx, lock_and_commit);
6708
6629
if (error != DB_SUCCESS) {
6709
6630
FILE* ef = dict_foreign_err_file;
6711
6632
fputs("InnoDB: Renaming table ", ef);
6712
ut_print_name(ef, trx, TRUE, norm_from);
6633
ut_print_name(ef, trx, TRUE, from.getKeyPath().c_str());
6713
6634
fputs(" to ", ef);
6714
ut_print_name(ef, trx, TRUE, norm_to);
6635
ut_print_name(ef, trx, TRUE, to.getKeyPath().c_str());
6715
6636
fputs(" failed!\n", ef);
7239
7171
innodb_crash_recovery is set to a high value. */
7240
7172
stats.delete_length = 0;
7242
/* lock the data dictionary to avoid races with
7243
ibd_file_missing and tablespace_discarded */
7244
row_mysql_lock_data_dictionary(prebuilt->trx);
7246
/* ib_table->space must be an existent tablespace */
7247
if (!ib_table->ibd_file_missing
7248
&& !ib_table->tablespace_discarded) {
7250
stats.delete_length =
7251
fsp_get_available_space_in_free_extents(
7252
ib_table->space) * 1024;
7176
avail_space = fsp_get_available_space_in_free_extents(ib_table->space);
7178
if (avail_space == ULLINT_UNDEFINED) {
7255
7179
Session* session;
7257
7181
session= getTable()->in_use;
7756
7678
db_name[i] = 0;
7757
ulen= TableIdentifier::filename_to_tablename(db_name, uname, sizeof(uname));
7679
ulen= identifier::Table::filename_to_tablename(db_name, uname, sizeof(uname));
7758
7680
LEX_STRING *tmp_referenced_db = session->make_lex_string(NULL, uname, ulen, true);
7760
7682
/* Table name */
7761
7683
tmp_buff += i + 1;
7762
ulen= TableIdentifier::filename_to_tablename(tmp_buff, uname, sizeof(uname));
7684
ulen= identifier::Table::filename_to_tablename(tmp_buff, uname, sizeof(uname));
7763
7685
LEX_STRING *tmp_referenced_table = session->make_lex_string(NULL, uname, ulen, true);
7765
7687
/** Foreign Fields **/
9230
9148
"Purge threads can be either 0 or 1. Defalut is 0.");
9231
9149
context("file-per-table",
9232
9150
po::value<bool>(&srv_file_per_table)->default_value(false)->zero_tokens(),
9233
"Stores each InnoDB table to an .ibd file in the database dir.");
9234
context("file-format",
9235
po::value<string>(&innobase_file_format_name)->default_value("Antelope"),
9236
"File format to use for new tables in .ibd files.");
9151
"Stores each InnoDB table to an .ibd file in the database dir.");
9237
9152
context("file-format-max",
9238
9153
po::value<string>(&innobase_file_format_max)->default_value("Antelope"),
9239
9154
"The highest file format in the tablespace.");
9240
9155
context("file-format-check",
9241
9156
po::value<bool>(&innobase_file_format_check)->default_value(true)->zero_tokens(),
9242
9157
"Whether to perform system file format check.");
9158
context("file-format",
9159
po::value<string>(&innobase_file_format_name)->default_value("Antelope"),
9160
"File format to use for new tables in .ibd files.");
9243
9161
context("flush-log-at-trx-commit",
9244
9162
po::value<trinary_constraint>(&innodb_flush_log_at_trx_commit)->default_value(1),
9245
9163
"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).");
9274
9192
po::value<additional_mem_pool_constraint>(&innobase_additional_mem_pool_size)->default_value(8*1024*1024L),
9275
9193
"Size of a memory pool InnoDB uses to store data dictionary information and other internal data structures.");
9276
9194
context("autoextend-increment",
9277
po::value<autoextend_constraint>(&innodb_auto_extend_increment)->default_value(8L),
9195
po::value<autoextend_constraint>(&innodb_auto_extend_increment)->default_value(64L),
9278
9196
"Data file autoextend increment in megabytes");
9279
9197
context("buffer-pool-size",
9280
9198
po::value<buffer_pool_constraint>(&innobase_buffer_pool_size)->default_value(128*1024*1024L),
9333
9251
"InnoDB version");
9334
9252
context("use-internal-malloc",
9335
9253
"Use InnoDB's internal memory allocator instal of the OS memory allocator.");
9254
context("disable-native-aio",
9255
_("Do not use Native AIO library for IO, even if available"));
9336
9256
context("change-buffering",
9337
9257
po::value<string>(&innobase_change_buffering),
9338
9258
"Buffer changes to reduce random access: OFF, ON, inserting, deleting, changing, or purging.");