43
43
#include <limits.h>
46
#include <drizzled/error.h>
47
#include <drizzled/errmsg_print.h>
48
#include <drizzled/charset_info.h>
49
#include <drizzled/internal/m_string.h>
50
#include <drizzled/internal/my_sys.h>
51
#include <drizzled/my_hash.h>
52
#include <drizzled/plugin.h>
53
#include <drizzled/show.h>
54
#include <drizzled/data_home.h>
55
#include <drizzled/error.h>
56
#include <drizzled/field.h>
57
#include <drizzled/charset.h>
58
#include <drizzled/session.h>
59
#include <drizzled/current_session.h>
60
#include <drizzled/table.h>
61
#include <drizzled/field/blob.h>
62
#include <drizzled/field/varstring.h>
63
#include <drizzled/plugin/xa_storage_engine.h>
64
#include <drizzled/plugin/daemon.h>
65
#include <drizzled/memory/multi_malloc.h>
66
#include <drizzled/pthread_globals.h>
67
#include <drizzled/named_savepoint.h>
46
#include "drizzled/error.h"
47
#include "drizzled/errmsg_print.h"
48
#include "drizzled/charset_info.h"
49
#include "drizzled/internal/m_string.h"
50
#include "drizzled/internal/my_sys.h"
51
#include "drizzled/my_hash.h"
52
#include "drizzled/plugin.h"
53
#include "drizzled/show.h"
54
#include "drizzled/data_home.h"
55
#include "drizzled/error.h"
56
#include "drizzled/field.h"
57
#include "drizzled/charset.h"
58
#include "drizzled/session.h"
59
#include "drizzled/current_session.h"
60
#include "drizzled/table.h"
61
#include "drizzled/field/blob.h"
62
#include "drizzled/field/varstring.h"
63
#include "drizzled/plugin/xa_storage_engine.h"
64
#include "drizzled/plugin/daemon.h"
65
#include "drizzled/memory/multi_malloc.h"
66
#include "drizzled/pthread_globals.h"
67
#include "drizzled/named_savepoint.h"
69
69
#include <drizzled/transaction_services.h>
70
#include <drizzled/message/statement_transform.h>
70
#include "drizzled/message/statement_transform.h"
72
72
#include <boost/algorithm/string.hpp>
73
73
#include <boost/program_options.hpp>
125
126
#include <sstream>
126
127
#include <string>
128
#include <plugin/innobase/handler/status_function.h>
129
#include <plugin/innobase/handler/replication_log.h>
129
#include "plugin/innobase/handler/status_function.h"
130
#include "plugin/innobase/handler/replication_log.h"
131
132
#include <google/protobuf/io/zero_copy_stream.h>
132
133
#include <google/protobuf/io/zero_copy_stream_impl.h>
133
134
#include <google/protobuf/io/coded_stream.h>
134
135
#include <google/protobuf/text_format.h>
136
#include <boost/thread/mutex.hpp>
138
137
using namespace std;
139
138
using namespace drizzled;
141
140
/** to protect innobase_open_files */
142
static boost::mutex innobase_share_mutex;
141
static pthread_mutex_t innobase_share_mutex;
144
142
/** to force correct commit order in binlog */
143
static pthread_mutex_t prepare_commit_mutex;
145
144
static ulong commit_threads = 0;
146
static boost::condition_variable commit_cond;
147
static boost::mutex commit_cond_m;
145
static pthread_mutex_t commit_threads_m;
146
static pthread_cond_t commit_cond;
147
static pthread_mutex_t commit_cond_m;
148
148
static bool innodb_inited = 0;
150
150
#define INSIDE_HA_INNOBASE_CC
160
160
#endif /* MYSQL_DYNAMIC_PLUGIN && __WIN__ */
162
162
static plugin::XaStorageEngine* innodb_engine_ptr= NULL;
163
static plugin::TableFunction* status_table_function_ptr= NULL;
164
static plugin::TableFunction* cmp_tool= NULL;
165
static plugin::TableFunction* cmp_reset_tool= NULL;
166
static plugin::TableFunction* cmp_mem_tool= NULL;
167
static plugin::TableFunction* cmp_mem_reset_tool= NULL;
168
static plugin::TableFunction* innodb_trx_tool= NULL;
169
static plugin::TableFunction* innodb_locks_tool= NULL;
170
static plugin::TableFunction* innodb_lock_waits_tool= NULL;
171
static plugin::TableFunction* innodb_sys_tables_tool= NULL;
172
static plugin::TableFunction* innodb_sys_tablestats_tool= NULL;
174
static plugin::TableFunction* innodb_sys_indexes_tool= NULL;
175
static plugin::TableFunction* innodb_sys_columns_tool= NULL;
176
static plugin::TableFunction* innodb_sys_fields_tool= NULL;
177
static plugin::TableFunction* innodb_sys_foreign_tool= NULL;
178
static plugin::TableFunction* innodb_sys_foreign_cols_tool= NULL;
180
static ReplicationLog *replication_logger= NULL;
164
181
typedef constrained_check<uint32_t, UINT32_MAX, 10> open_files_constraint;
165
182
static open_files_constraint innobase_open_files;
166
183
typedef constrained_check<uint32_t, 10, 1> mirrored_log_groups_constraint;
960
965
trx_t *trx= session_to_trx(&session);
962
967
uint64_t trx_id= message.transaction_context().transaction_id();
963
uint32_t seg_id= message.segment_id();
964
uint64_t end_timestamp= message.transaction_context().end_timestamp();
965
bool is_end_segment= message.end_segment();
966
trx->log_commit_id= TRUE;
967
ulint error= insert_replication_message(data, message.ByteSize(), trx, trx_id,
968
end_timestamp, is_end_segment, seg_id);
968
ulint error= insert_replication_message(data, message.ByteSize(), trx, trx_id);
1171
1171
innobase_mysql_print_thd(
1172
1172
/*=====================*/
1173
1173
FILE* f, /*!< in: output stream */
1174
drizzled::Session *in_session, /*!< in: pointer to a Drizzle Session object */
1174
void * in_session, /*!< in: pointer to a Drizzle Session object */
1175
1175
uint ) /*!< in: max query length to print, or 0 to
1176
1176
use the default max length */
1178
drizzled::identifier::User::const_shared_ptr user_identifier(in_session->user());
1178
Session *session= reinterpret_cast<Session *>(in_session);
1179
drizzled::identifier::User::const_shared_ptr user_identifier(session->user());
1181
1182
"Drizzle thread %"PRIu64", query id %"PRIu64", %s, %s, %s ",
1182
static_cast<uint64_t>(in_session->getSessionId()),
1183
static_cast<uint64_t>(in_session->getQueryId()),
1184
getServerHostname().c_str(),
1183
static_cast<uint64_t>(session->getSessionId()),
1184
static_cast<uint64_t>(session->getQueryId()),
1185
1186
user_identifier->address().c_str(),
1186
1187
user_identifier->username().c_str()
1188
fprintf(f, "\n%s", in_session->getQueryString()->c_str());
1189
fprintf(f, "\n%s", session->getQueryString()->c_str());
1277
1290
return my_isspace(static_cast<const CHARSET_INFO *>(cs), char_to_test);
1295
innobase_fast_mutex_init(
1296
os_fast_mutex_t* fast_mutex)
1298
return pthread_mutex_init(fast_mutex, MY_MUTEX_INIT_FAST);
1301
/**********************************************************************//**
1302
Determines the current SQL statement.
1303
@return SQL statement string */
1308
void* session, /*!< in: MySQL thread handle */
1309
size_t* length) /*!< out: length of the SQL statement */
1311
return static_cast<Session*>(session)->getQueryStringCopy(*length);
1280
1314
#if defined (__WIN__) && defined (MYSQL_DYNAMIC_PLUGIN)
1281
1315
/*******************************************************************//**
1282
1316
Map an OS error to an errno value. The OS error number is stored in
1631
1665
ulint buflen, /*!< in: length of buf, in bytes */
1632
1666
const char* id, /*!< in: identifier to convert */
1633
1667
ulint idlen, /*!< in: length of id, in bytes */
1634
drizzled::Session *session,/*!< in: MySQL connection thread, or NULL */
1668
void* session,/*!< in: MySQL connection thread, or NULL */
1635
1669
ibool file_id)/*!< in: TRUE=id is a table or database name;
1636
1670
FALSE=id is an UTF-8 string */
1717
1751
ulint buflen, /*!< in: length of buf, in bytes */
1718
1752
const char* id, /*!< in: identifier to convert */
1719
1753
ulint idlen, /*!< in: length of id, in bytes */
1720
drizzled::Session *session,/*!< in: MySQL connection thread, or NULL */
1754
void* session,/*!< in: MySQL connection thread, or NULL */
1721
1755
ibool table_id)/*!< in: TRUE=id is a table or database name;
1722
1756
FALSE=id is an index name */
2185
2220
srv_max_file_format_at_startup */
2186
2221
if (innobase_file_format_validate_and_set(innobase_file_format_max.c_str()) < 0)
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));
2223
errmsg_printf(error::ERROR, _("InnoDB: invalid "
2224
"innodb_file_format_max value: "
2225
"should be any value up to %s or its "
2226
"equivalent numeric id"),
2227
trx_sys_file_format_id_to_name(DICT_TF_FORMAT_MAX));
2191
2228
goto mem_free_and_error;
2286
2325
innobase_open_tables = hash_create(200);
2326
pthread_mutex_init(&innobase_share_mutex, MY_MUTEX_INIT_FAST);
2327
pthread_mutex_init(&prepare_commit_mutex, MY_MUTEX_INIT_FAST);
2328
pthread_mutex_init(&commit_threads_m, MY_MUTEX_INIT_FAST);
2329
pthread_mutex_init(&commit_cond_m, MY_MUTEX_INIT_FAST);
2330
pthread_cond_init(&commit_cond, NULL);
2287
2331
innodb_inited= 1;
2289
2333
actuall_engine_ptr->dropTemporarySchema();
2291
context.add(new InnodbStatusTool);
2335
status_table_function_ptr= new InnodbStatusTool;
2293
2337
context.add(innodb_engine_ptr);
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());
2339
context.add(status_table_function_ptr);
2341
cmp_tool= new(std::nothrow)CmpTool(false);
2342
context.add(cmp_tool);
2344
cmp_reset_tool= new(std::nothrow)CmpTool(true);
2345
context.add(cmp_reset_tool);
2347
cmp_mem_tool= new(std::nothrow)CmpmemTool(false);
2348
context.add(cmp_mem_tool);
2350
cmp_mem_reset_tool= new(std::nothrow)CmpmemTool(true);
2351
context.add(cmp_mem_reset_tool);
2353
innodb_trx_tool= new(std::nothrow)InnodbTrxTool("INNODB_TRX");
2354
context.add(innodb_trx_tool);
2356
innodb_locks_tool= new(std::nothrow)InnodbTrxTool("INNODB_LOCKS");
2357
context.add(innodb_locks_tool);
2359
innodb_lock_waits_tool= new(std::nothrow)InnodbTrxTool("INNODB_LOCK_WAITS");
2360
context.add(innodb_lock_waits_tool);
2362
innodb_sys_tables_tool= new(std::nothrow)InnodbSysTablesTool();
2363
context.add(innodb_sys_tables_tool);
2365
innodb_sys_tablestats_tool= new(std::nothrow)InnodbSysTableStatsTool();
2366
context.add(innodb_sys_tablestats_tool);
2368
innodb_sys_indexes_tool= new(std::nothrow)InnodbSysIndexesTool();
2369
context.add(innodb_sys_indexes_tool);
2371
innodb_sys_columns_tool= new(std::nothrow)InnodbSysColumnsTool();
2372
context.add(innodb_sys_columns_tool);
2374
innodb_sys_fields_tool= new(std::nothrow)InnodbSysFieldsTool();
2375
context.add(innodb_sys_fields_tool);
2377
innodb_sys_foreign_tool= new(std::nothrow)InnodbSysForeignTool();
2378
context.add(innodb_sys_foreign_tool);
2380
innodb_sys_foreign_cols_tool= new(std::nothrow)InnodbSysForeignColsTool();
2381
context.add(innodb_sys_foreign_cols_tool);
2323
2383
context.add(new(std::nothrow)InnodbInternalTables());
2324
2384
context.add(new(std::nothrow)InnodbReplicationTable());
2326
2386
if (innobase_use_replication_log)
2328
ReplicationLog *replication_logger= new(std::nothrow)ReplicationLog();
2388
replication_logger= new(std::nothrow)ReplicationLog();
2329
2389
context.add(replication_logger);
2330
2390
ReplicationLog::setup(replication_logger);
2521
2580
/* We need current binlog position for ibbackup to work.
2522
2581
Note, the position is current because of
2523
2582
prepare_commit_mutex */
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)
2584
if (innobase_commit_concurrency.get() > 0) {
2585
pthread_mutex_lock(&commit_cond_m);
2588
if (commit_threads > innobase_commit_concurrency.get()) {
2535
2589
commit_threads--;
2536
commit_cond.wait(scopedLock);
2590
pthread_cond_wait(&commit_cond,
2592
pthread_mutex_unlock(&commit_cond_m);
2596
pthread_mutex_unlock(&commit_cond_m);
2540
2600
trx->mysql_log_file_name = NULL;
2939
/*****************************************************************//**
2940
Normalizes a table name string. A normalized name consists of the
2941
database name catenated to '/' and table name. An example:
2942
test/mytable. On Windows normalization puts both the database name and the
2943
table name always to lower case. */
2946
normalize_table_name(
2947
/*=================*/
2948
char* norm_name, /*!< out: normalized name as a
2949
null-terminated string */
2950
const char* name) /*!< in: table name string */
2952
const char* name_ptr;
2956
/* Scan name from the end */
2958
ptr = strchr(name, '\0')-1;
2960
while (ptr >= name && *ptr != '\\' && *ptr != '/') {
2970
while (ptr >= name && *ptr != '\\' && *ptr != '/') {
2976
memcpy(norm_name, db_ptr, strlen(name) + 1 - (db_ptr - name));
2978
norm_name[name_ptr - db_ptr - 1] = '/';
2981
innobase_casedn_str(norm_name);
2879
2985
/********************************************************************//**
2880
2986
Get the upper limit of the MySQL integral and floating-point type.
2881
2987
@return maximum allowed value for the field */
3042
3148
if (!index_mapping) {
3043
3149
/* Report an error if index_mapping continues to be
3044
3150
NULL and mysql_num_index is a non-zero value */
3045
errmsg_printf(error::ERROR, "InnoDB: fail to allocate memory for "
3046
"index translation table. Number of Index:%lu, array size:%lu",
3151
errmsg_printf(error::ERROR,
3152
"InnoDB: fail to allocate memory for "
3153
"index translation table. Number of "
3154
"Index:%lu, array size:%lu",
3047
3155
mysql_num_index,
3048
3156
share->idx_trans_tbl.array_size);
3064
3172
ib_table, table->key_info[count].name);
3066
3174
if (!index_mapping[count]) {
3067
errmsg_printf(error::ERROR, "Cannot find index %s in InnoDB index dictionary.",
3068
table->key_info[count].name);
3175
errmsg_printf(error::ERROR, "Cannot find index %s in InnoDB "
3176
"index dictionary.",
3177
table->key_info[count].name);
3070
3179
goto func_exit;
3073
3182
/* Double check fetched index has the same
3074
3183
column info as those in mysql key_info. */
3075
if (!innobase_match_index_columns(&table->key_info[count], index_mapping[count])) {
3076
errmsg_printf(error::ERROR, "Found index %s whose column info does not match that of MySQL.",
3077
table->key_info[count].name);
3184
if (!innobase_match_index_columns(&table->key_info[count],
3185
index_mapping[count])) {
3186
errmsg_printf(error::ERROR, "Found index %s whose column info "
3187
"does not match that of MySQL.",
3188
table->key_info[count].name);
3197
3309
case DB_RECORD_NOT_FOUND:
3198
3310
ut_print_timestamp(stderr);
3199
errmsg_printf(error::ERROR, "InnoDB: MySQL and InnoDB data dictionaries are out of sync.\n"
3200
"InnoDB: Unable to find the AUTOINC column %s in the InnoDB table %s.\n"
3201
"InnoDB: We set the next AUTOINC column value to 0,\n"
3202
"InnoDB: in effect disabling the AUTOINC next value generation.\n"
3203
"InnoDB: You can either set the next AUTOINC value explicitly using ALTER TABLE\n"
3204
"InnoDB: or fix the data dictionary by recreating the table.\n",
3205
col_name, index->table->name);
3311
fprintf(stderr, " InnoDB: MySQL and InnoDB data "
3312
"dictionaries are out of sync.\n"
3313
"InnoDB: Unable to find the AUTOINC column "
3314
"%s in the InnoDB table %s.\n"
3315
"InnoDB: We set the next AUTOINC column "
3317
"InnoDB: in effect disabling the AUTOINC "
3318
"next value generation.\n"
3319
"InnoDB: You can either set the next "
3320
"AUTOINC value explicitly using ALTER TABLE\n"
3321
"InnoDB: or fix the data dictionary by "
3322
"recreating the table.\n",
3323
col_name, index->table->name);
3207
3325
/* This will disable the AUTOINC generation. */
3247
3366
getTransactionalEngine()->releaseTemporaryLatches(session);
3369
normalize_table_name(norm_name, identifier.getPath().c_str());
3250
3371
user_session = NULL;
3252
std::string search_string(identifier.getSchemaName());
3253
boost::algorithm::to_lower(search_string);
3373
if (!(share=get_share(identifier.getPath().c_str()))) {
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())))
3272
3378
/* Create buffers for packing the fields of a record. Why
3295
3401
/* Get pointer to a table object in InnoDB dictionary cache */
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);
3402
ib_table = dict_table_get(norm_name, TRUE);
3307
3404
if (NULL == ib_table) {
3308
3405
errmsg_printf(error::ERROR, "Cannot find or open table %s from\n"
6177
6274
if (lex_identified_temp_table)
6178
6275
iflags |= DICT_TF2_TEMPORARY << DICT_TF2_SHIFT;
6180
error= create_table_def(trx, &form, identifier.getKeyPath().c_str(),
6181
lex_identified_temp_table ? identifier.getKeyPath().c_str() : NULL,
6277
error= create_table_def(trx, &form, norm_name,
6278
lex_identified_temp_table ? name2 : NULL,
6184
6281
session.setXaId(trx->id);
6211
6308
for (i = 0; i < form.getShare()->sizeKeys(); i++) {
6212
6309
if (i != (uint) primary_key_no) {
6214
if ((error = create_index(trx, &form, iflags, identifier.getKeyPath().c_str(),
6311
if ((error = create_index(trx, &form, iflags, norm_name,
6221
stmt= session.getQueryStringCopy(stmt_len);
6318
stmt = innobase_get_stmt(&session, &stmt_len);
6224
6321
string generated_create_table;
6225
6322
const char *query= stmt;
6227
if (session.getSqlCommand() == SQLCOM_CREATE_TABLE)
6324
if (session_sql_command(&session) == SQLCOM_CREATE_TABLE)
6229
6326
message::transformTableDefinitionToSql(create_proto,
6230
6327
generated_create_table,
6433
6530
trx_t* parent_trx;
6532
char norm_name[1000];
6436
6534
ut_a(identifier.getPath().length() < 1000);
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;
6536
/* Strangely, MySQL passes the table name without the '.frm'
6537
extension, in contrast to ::create */
6538
normalize_table_name(norm_name, identifier.getPath().c_str());
6446
6540
/* Get the transaction associated with the current session, or create one
6447
6541
if not yet created */
6608
6702
innobase_rename_table(
6609
6703
/*==================*/
6610
6704
trx_t* trx, /*!< in: transaction */
6611
const identifier::Table &from,
6612
const identifier::Table &to,
6705
const char* from, /*!< in: old name of the table */
6706
const char* to, /*!< in: new name of the table */
6613
6707
ibool lock_and_commit)
6614
6708
/*!< in: TRUE=lock data dictionary and commit */
6711
char norm_to[FN_REFLEN];
6712
char norm_from[FN_REFLEN];
6618
6714
srv_lower_case_table_names = TRUE;
6716
normalize_table_name(norm_to, to);
6717
normalize_table_name(norm_from, from);
6620
6719
/* Serialize data dictionary operations with dictionary mutex:
6621
6720
no deadlocks can occur then in these operations */
6624
6723
row_mysql_lock_data_dictionary(trx);
6627
error = row_rename_table_for_mysql(from.getKeyPath().c_str(), to.getKeyPath().c_str(), trx, lock_and_commit);
6726
error = row_rename_table_for_mysql(
6727
norm_from, norm_to, trx, lock_and_commit);
6629
6729
if (error != DB_SUCCESS) {
6630
6730
FILE* ef = dict_foreign_err_file;
6632
6732
fputs("InnoDB: Renaming table ", ef);
6633
ut_print_name(ef, trx, TRUE, from.getKeyPath().c_str());
6733
ut_print_name(ef, trx, TRUE, norm_from);
6634
6734
fputs(" to ", ef);
6635
ut_print_name(ef, trx, TRUE, to.getKeyPath().c_str());
6735
ut_print_name(ef, trx, TRUE, norm_to);
6636
6736
fputs(" failed!\n", ef);
8787
8891
finds charset information and returns length of prefix_len characters in the
8788
8892
index field in bytes.
8789
8893
@return number of bytes occupied by the first n characters */
8896
innobase_get_at_most_n_mbchars(
8897
/*===========================*/
8898
ulint charset_id, /*!< in: character set id */
8899
ulint prefix_len, /*!< in: prefix length in bytes of the index
8900
(this has to be divided by mbmaxlen to get the
8901
number of CHARACTERS n in the prefix) */
8902
ulint data_len, /*!< in: length of the string in bytes */
8903
const char* str); /*!< in: character string */
8792
8906
innobase_get_at_most_n_mbchars(