50
50
***********************************************************************/
52
52
/* TODO list for the InnoDB Cursor in 5.0:
53
- Remove the flag trx->active_trans and look at trx->conc_state
53
54
- fix savepoint functions to use savepoint storage area
54
55
- Find out what kind of problems the OS X case-insensitivity causes to
55
56
table and database names; should we 'normalize' the names like we do
60
#include "drizzled/server_includes.h"
64
61
#include "drizzled/error.h"
65
62
#include "drizzled/errmsg_print.h"
66
#include "drizzled/charset_info.h"
67
#include "drizzled/internal/m_string.h"
68
#include "drizzled/internal/my_sys.h"
69
#include "drizzled/my_hash.h"
63
#include "mystrings/m_ctype.h"
64
#include "mysys/my_sys.h"
65
#include "mysys/hash.h"
66
#include "mysys/mysys_err.h"
70
67
#include "drizzled/plugin.h"
71
68
#include "drizzled/show.h"
72
69
#include "drizzled/data_home.h"
73
70
#include "drizzled/error.h"
74
71
#include "drizzled/field.h"
75
#include "drizzled/charset.h"
76
72
#include "drizzled/session.h"
77
73
#include "drizzled/current_session.h"
78
74
#include "drizzled/table.h"
79
75
#include "drizzled/field/blob.h"
80
76
#include "drizzled/field/varstring.h"
81
77
#include "drizzled/field/timestamp.h"
82
#include "drizzled/plugin/xa_storage_engine.h"
83
#include "drizzled/plugin/daemon.h"
78
#include "drizzled/plugin/storage_engine.h"
79
#include "drizzled/plugin/info_schema_table.h"
84
80
#include "drizzled/memory/multi_malloc.h"
85
#include "drizzled/pthread_globals.h"
86
#include "drizzled/named_savepoint.h"
88
#include <drizzled/transaction_services.h>
90
82
/** @file ha_innodb.cc */
164
152
# define EQ_CURRENT_SESSION(session) ((session) == current_session)
165
153
#endif /* MYSQL_DYNAMIC_PLUGIN && __WIN__ */
167
static plugin::XaStorageEngine* innodb_engine_ptr= NULL;
168
static plugin::TableFunction* status_table_function_ptr= NULL;
169
static plugin::TableFunction* cmp_tool= NULL;
170
static plugin::TableFunction* cmp_reset_tool= NULL;
171
static plugin::TableFunction* cmp_mem_tool= NULL;
172
static plugin::TableFunction* cmp_mem_reset_tool= NULL;
173
static plugin::TableFunction* innodb_trx_tool= NULL;
174
static plugin::TableFunction* innodb_locks_tool= NULL;
175
static plugin::TableFunction* innodb_lock_waits_tool= NULL;
155
static drizzled::plugin::StorageEngine* innodb_engine_ptr= NULL;
177
157
static const long AUTOINC_OLD_STYLE_LOCKING = 0;
178
158
static const long AUTOINC_NEW_STYLE_LOCKING = 1;
258
239
static INNOBASE_SHARE *get_share(const char *table_name);
259
240
static void free_share(INNOBASE_SHARE *share);
261
class InnobaseEngine : public plugin::XaStorageEngine
242
class InnobaseEngine : public drizzled::plugin::StorageEngine
264
explicit InnobaseEngine(string name_arg) :
265
plugin::XaStorageEngine(name_arg,
267
HTON_CAN_INDEX_BLOBS |
268
HTON_PRIMARY_KEY_REQUIRED_FOR_POSITION |
269
HTON_PRIMARY_KEY_IN_READ_INDEX |
270
HTON_PARTIAL_COLUMN_READ |
271
HTON_TABLE_SCAN_ON_INDEX |
272
HTON_HAS_DOES_TRANSACTIONS)
245
InnobaseEngine(string name_arg)
246
: drizzled::plugin::StorageEngine(name_arg,
247
HTON_HAS_DOES_TRANSACTIONS, sizeof(trx_named_savept_t))
274
table_definition_ext= plugin::DEFAULT_DEFINITION_FILE_EXT;
249
table_definition_ext= drizzled::plugin::DEFAULT_DEFINITION_FILE_EXT;
275
250
addAlias("INNOBASE");
278
virtual ~InnobaseEngine()
283
srv_fast_shutdown = (ulint) innobase_fast_shutdown;
285
hash_table_free(innobase_open_tables);
286
innobase_open_tables = NULL;
287
if (innobase_shutdown_for_mysql() != DB_SUCCESS) {
290
srv_free_paths_and_sizes();
291
if (internal_innobase_data_file_path)
292
free(internal_innobase_data_file_path);
293
pthread_mutex_destroy(&innobase_share_mutex);
294
pthread_mutex_destroy(&prepare_commit_mutex);
295
pthread_mutex_destroy(&commit_threads_m);
296
pthread_mutex_destroy(&commit_cond_m);
297
pthread_cond_destroy(&commit_cond);
302
virtual int doStartTransaction(Session *session, start_transaction_option_t options);
303
virtual void doStartStatement(Session *session);
304
virtual void doEndStatement(Session *session);
308
255
close_connection(
311
258
Session* session); /* in: handle to the MySQL thread of the user
312
259
whose resources should be free'd */
314
virtual int doSetSavepoint(Session* session,
315
drizzled::NamedSavepoint &savepoint);
316
virtual int doRollbackToSavepoint(Session* session,
317
drizzled::NamedSavepoint &savepoint);
318
virtual int doReleaseSavepoint(Session* session,
319
drizzled::NamedSavepoint &savepoint);
320
virtual int doXaCommit(Session* session, bool all)
322
return doCommit(session, all); /* XA commit just does a SQL COMMIT */
324
virtual int doXaRollback(Session *session, bool all)
326
return doRollback(session, all); /* XA rollback just does a SQL ROLLBACK */
328
virtual int doCommit(Session* session, bool all);
329
virtual int doRollback(Session* session, bool all);
261
virtual int savepoint_set_hook(Session* session,
263
virtual int savepoint_rollback_hook(Session* session,
265
virtual int savepoint_release_hook(Session* session,
267
virtual int commit(Session* session, bool all);
268
virtual int rollback(Session* session, bool all);
331
270
/***********************************************************************
332
271
This function is used to prepare X/Open XA distributed transaction */
336
275
/*================*/
337
276
/* out: 0 or error number */
338
277
Session* session, /* in: handle to the MySQL thread of the user
343
282
This function is used to recover X/Open XA distributed transactions */
347
286
/*================*/
348
287
/* out: number of prepared transactions
349
288
stored in xid_list */
350
::drizzled::XID* xid_list, /* in/out: prepared transactions */
351
size_t len); /* in: number of slots in xid_list */
289
XID* xid_list, /* in/out: prepared transactions */
290
uint len); /* in: number of slots in xid_list */
352
291
/***********************************************************************
353
292
This function is used to commit one X/Open XA distributed transaction
354
293
which is in the prepared state */
358
297
/*===================*/
359
298
/* out: 0 or error number */
360
::drizzled::XID* xid); /* in: X/Open XA transaction identification */
299
XID* xid); /* in: X/Open XA transaction identification */
361
300
/***********************************************************************
362
301
This function is used to rollback one X/Open XA distributed transaction
363
302
which is in the prepared state */
367
306
/*=====================*/
368
307
/* out: 0 or error number */
369
::drizzled::XID *xid); /* in: X/Open XA transaction identification */
308
XID *xid); /* in: X/Open XA transaction identification */
371
virtual Cursor *create(TableShare &table,
372
memory::Root *mem_root)
310
virtual Cursor *create(TableShare *table,
374
return new (mem_root) ha_innobase(*this, table);
313
return new (mem_root) ha_innobase(this, table);
377
316
/*********************************************************************
378
317
Removes all tables in the named database inside InnoDB. */
381
321
/*===================*/
382
322
/* out: error number */
383
const std::string &schema_name); /* in: database path; inside InnoDB the name
323
char* path); /* in: database path; inside InnoDB the name
384
324
of the last directory in the path is used as
385
325
the database name: for example, in 'mysql/data/test'
386
326
the database name is 'test' */
328
/*********************************************************************
329
Creates an InnoDB transaction struct for the session if it does not yet have one.
330
Starts a new InnoDB transaction if a transaction is not yet started. And
331
assigns a new snapshot for a consistent read if the transaction does not yet
335
start_consistent_snapshot(
336
/*====================================*/
338
Session* session); /* in: MySQL thread handle of the user for whom
339
the transaction should be committed */
388
340
/********************************************************************
389
341
Flushes InnoDB logs to disk and makes a checkpoint. Really, a commit flushes
390
342
the logs, and the name of this function should be innobase_checkpoint. */
417
369
return(ha_innobase_exts);
420
UNIV_INTERN int doCreateTable(Session *session,
372
UNIV_INTERN int doCreateTable(Session *session,
373
const char *table_name,
422
drizzled::TableIdentifier &identifier,
375
HA_CREATE_INFO& create_info,
376
drizzled::message::Table&);
424
377
UNIV_INTERN int doRenameTable(Session* session,
427
UNIV_INTERN int doDropTable(Session& session, TableIdentifier &identifier);
429
UNIV_INTERN virtual bool get_error_message(int error, String *buf);
431
UNIV_INTERN uint32_t max_supported_keys() const;
432
UNIV_INTERN uint32_t max_supported_key_length() const;
433
UNIV_INTERN uint32_t max_supported_key_part_length() const;
436
UNIV_INTERN uint32_t index_flags(enum ha_key_alg) const
438
return (HA_READ_NEXT |
380
UNIV_INTERN int doDropTable(Session& session, const string table_path);
446
383
/** @brief Initialize the default value of innodb_commit_concurrency.
495
432
innobase_commit_concurrency_validate(
496
433
/*=================================*/
497
434
Session* , /*!< in: thread handle */
498
drizzle_sys_var* , /*!< in: pointer to system
435
struct st_mysql_sys_var* , /*!< in: pointer to system
500
437
void* save, /*!< out: immediate result
501
438
for update function */
502
drizzle_value* value) /*!< in: incoming string */
439
struct st_mysql_value* value) /*!< in: incoming string */
505
442
ulong commit_concurrency;
536
473
NULL, NULL, 50, 1, 1024 * 1024 * 1024, 0);
476
/***********************************************************************
477
Closes an InnoDB database. */
480
innobase_deinit(drizzled::plugin::Registry ®istry);
539
482
/*****************************************************************//**
540
483
Commits a transaction in an InnoDB database. */
544
487
/*================*/
545
488
trx_t* trx); /*!< in: transaction handle */
547
static drizzle_show_var innodb_status_variables[]= {
490
static SHOW_VAR innodb_status_variables[]= {
548
491
{"buffer_pool_pages_data",
549
492
(char*) &export_vars.innodb_buffer_pool_pages_data, SHOW_LONG},
550
493
{"buffer_pool_pages_dirty",
638
581
{NULL, NULL, SHOW_LONG}
641
InnodbStatusTool::Generator::Generator(drizzled::Field **fields) :
642
plugin::TableFunction::Generator(fields)
644
srv_export_innodb_status();
645
status_var_ptr= innodb_status_variables;
648
bool InnodbStatusTool::Generator::populate()
650
if (status_var_ptr->name)
652
std::ostringstream oss;
654
const char *value= status_var_ptr->value;
657
push(status_var_ptr->name);
659
switch (status_var_ptr->type)
662
oss << *(int64_t*) value;
663
return_value= oss.str();
666
oss << *(int64_t*) value;
667
return_value= oss.str();
670
return_value= *(bool*) value ? "ON" : "OFF";
677
if (return_value.length())
689
584
/* General functions */
691
586
/******************************************************************//**
1052
947
static_cast<uint64_t>(session_get_thread_id( session)),
1053
948
static_cast<uint64_t>(session->getQueryId()),
1055
session->getSecurityContext().getIp().c_str(),
1056
session->getSecurityContext().getUser().c_str()
950
session->security_ctx.ip.c_str(),
951
session->security_ctx.user.c_str()
1059
"\n%s", session->getQueryString().c_str()
954
"\n%s", session->getQueryString()
1093
988
innobase_convert_from_table_id(
1094
989
/*===========================*/
1095
const void*, /*!< in: the 'from' character set */
990
const struct charset_info_st*, /*!< in: the 'from' character set */
1096
991
char* to, /*!< out: converted identifier */
1097
992
const char* from, /*!< in: identifier to convert */
1098
993
ulint len) /*!< in: length of 'to', in bytes */
1107
1002
innobase_convert_from_id(
1108
1003
/*=====================*/
1109
const void*, /*!< in: the 'from' character set */
1004
const struct charset_info_st*, /*!< in: the 'from' character set */
1110
1005
char* to, /*!< out: converted identifier */
1111
1006
const char* from, /*!< in: identifier to convert */
1112
1007
ulint len) /*!< in: length of 'to', in bytes */
1142
1037
Determines the connection character set.
1143
1038
@return connection character set */
1144
1039
extern "C" UNIV_INTERN
1040
const charset_info_st*
1146
1041
innobase_get_charset(
1147
1042
/*=================*/
1148
1043
void* mysql_session) /*!< in: MySQL thread handle */
1150
return session_charset(static_cast<Session*>(mysql_session));
1153
extern "C" UNIV_INTERN
1159
return my_isspace(static_cast<const CHARSET_INFO *>(cs), char_to_test);
1164
innobase_fast_mutex_init(
1165
os_fast_mutex_t* fast_mutex)
1167
return pthread_mutex_init(fast_mutex, MY_MUTEX_INIT_FAST);
1045
return(session_charset(static_cast<Session*>(mysql_session)));
1170
1048
#if defined (__WIN__) && defined (MYSQL_DYNAMIC_PLUGIN)
1265
1143
/*========================*/
1268
int fd = mysql_tmpfile("ib");
1146
File fd = mysql_tmpfile("ib");
1270
1148
/* Copy the file descriptor, so that the additional resources
1271
1149
allocated by create_temp_file() can be freed by invoking
1272
internal::my_close().
1274
1152
Because the file descriptor returned by this function
1275
1153
will be passed to fdopen(), it will be closed by invoking
1276
1154
fclose(), which in turn will invoke close() instead of
1277
internal::my_close(). */
1281
1159
my_error(EE_OUT_OF_FILERESOURCES,
1282
1160
MYF(ME_BELL+ME_WAITTANG),
1285
internal::my_close(fd, MYF(MY_WME));
1163
my_close(fd, MYF(MY_WME));
1471
1349
/*********************************************************************//**
1472
1350
Construct ha_innobase Cursor. */
1474
ha_innobase::ha_innobase(plugin::StorageEngine &engine_arg,
1475
TableShare &table_arg)
1352
ha_innobase::ha_innobase(drizzled::plugin::StorageEngine *engine_arg,
1353
TableShare *table_arg)
1476
1354
:Cursor(engine_arg, table_arg),
1355
int_table_flags(HA_REC_NOT_IN_SEQ |
1357
HA_CAN_INDEX_BLOBS |
1358
HA_PRIMARY_KEY_REQUIRED_FOR_POSITION |
1359
HA_PRIMARY_KEY_IN_READ_INDEX |
1360
HA_PARTIAL_COLUMN_READ |
1361
HA_TABLE_SCAN_ON_INDEX |
1477
1363
primary_key(0), /* needs initialization because index_flags() may be called
1478
1364
before this is set to the real value. It's ok to have any
1479
1365
value here because it doesn't matter if we return the
1525
1411
update_session(session);
1414
/*********************************************************************//**
1415
Registers that InnoDB takes part in an SQL statement, so that MySQL knows to
1416
roll back the statement if the statement results in an error. This MUST be
1417
called for every SQL statement that may be rolled back by MySQL. Calling this
1418
several times to register the same statement is allowed, too. */
1421
innobase_register_stmt(
1422
/*===================*/
1423
drizzled::plugin::StorageEngine* engine, /*!< in: Innobase hton */
1424
Session* session) /*!< in: MySQL thd (connection) object */
1426
assert(engine == innodb_engine_ptr);
1427
/* Register the statement */
1428
trans_register_ha(session, FALSE, engine);
1431
/*********************************************************************//**
1432
Registers an InnoDB transaction in MySQL, so that the MySQL XA code knows
1433
to call the InnoDB prepare and commit, or rollback for the transaction. This
1434
MUST be called for every transaction for which the user may call commit or
1435
rollback. Calling this several times to register the same transaction is
1437
This function also registers the current SQL statement. */
1440
innobase_register_trx_and_stmt(
1441
/*===========================*/
1442
drizzled::plugin::StorageEngine *engine, /*!< in: Innobase StorageEngine */
1443
Session* session) /*!< in: MySQL thd (connection) object */
1445
/* NOTE that actually innobase_register_stmt() registers also
1446
the transaction in the AUTOCOMMIT=1 mode. */
1448
innobase_register_stmt(engine, session);
1450
if (session_test_options(session, OPTION_NOT_AUTOCOMMIT | OPTION_BEGIN)) {
1452
/* No autocommit mode, register for a transaction */
1453
trans_register_ha(session, TRUE, engine);
1528
1457
/*****************************************************************//**
1529
1458
Convert an SQL identifier to the MySQL system_charset_info (UTF-8)
1530
1459
and quote it if needed.
1692
1621
prebuilt->read_just_key = 0;
1624
/*****************************************************************//**
1625
Call this when you have opened a new table handle in HANDLER, before you
1626
call index_read_idx() etc. Actually, we can let the cursor stay open even
1627
over a transaction commit! Then you should call this before every operation,
1628
fetch next etc. This function inits the necessary things even after a
1629
transaction commit. */
1632
ha_innobase::init_table_handle_for_HANDLER(void)
1633
/*============================================*/
1635
/* If current session does not yet have a trx struct, create one.
1636
If the current handle does not yet have a prebuilt struct, create
1637
one. Update the trx pointers in the prebuilt struct. Normally
1638
this operation is done in external_lock. */
1640
update_session(ha_session());
1642
/* Initialize the prebuilt struct much like it would be inited in
1645
innobase_release_stat_resources(prebuilt->trx);
1647
/* If the transaction is not started yet, start it */
1649
trx_start_if_not_started(prebuilt->trx);
1651
/* Assign a read view if the transaction does not have it yet */
1653
trx_assign_read_view(prebuilt->trx);
1655
/* Set the MySQL flag to mark that there is an active transaction */
1657
if (prebuilt->trx->active_trans == 0) {
1659
innobase_register_trx_and_stmt(engine, user_session);
1661
prebuilt->trx->active_trans = 1;
1664
/* We did the necessary inits in this function, no need to repeat them
1665
in row_search_for_mysql */
1667
prebuilt->sql_stat_start = FALSE;
1669
/* We let HANDLER always to do the reads as consistent reads, even
1670
if the trx isolation level would have been specified as SERIALIZABLE */
1672
prebuilt->select_lock_type = LOCK_NONE;
1673
prebuilt->stored_select_lock_type = LOCK_NONE;
1675
/* Always fetch all columns in the index record */
1677
prebuilt->hint_need_to_fetch_extra_cols = ROW_RETRIEVE_ALL_COLS;
1679
/* We want always to fetch all columns in the whole row? Or do
1682
prebuilt->used_in_HANDLER = TRUE;
1683
reset_template(prebuilt);
1695
1686
/*********************************************************************//**
1696
1687
Opens an InnoDB database.
1697
1688
@return 0 on success, error code on failure */
1977
1969
pthread_cond_init(&commit_cond, NULL);
1978
1970
innodb_inited= 1;
1980
status_table_function_ptr= new InnodbStatusTool;
1982
context.add(innodb_engine_ptr);
1984
context.add(status_table_function_ptr);
1986
cmp_tool= new(std::nothrow)CmpTool(false);
1987
context.add(cmp_tool);
1989
cmp_reset_tool= new(std::nothrow)CmpTool(true);
1990
context.add(cmp_reset_tool);
1992
cmp_mem_tool= new(std::nothrow)CmpmemTool(false);
1993
context.add(cmp_mem_tool);
1995
cmp_mem_reset_tool= new(std::nothrow)CmpmemTool(true);
1996
context.add(cmp_mem_reset_tool);
1998
innodb_trx_tool= new(std::nothrow)InnodbTrxTool("INNODB_TRX");
1999
context.add(innodb_trx_tool);
2001
innodb_locks_tool= new(std::nothrow)InnodbTrxTool("INNODB_LOCKS");
2002
context.add(innodb_locks_tool);
2004
innodb_lock_waits_tool= new(std::nothrow)InnodbTrxTool("INNODB_LOCK_WAITS");
2005
context.add(innodb_lock_waits_tool);
1972
if (innodb_locks_init() ||
1973
innodb_trx_init() ||
1974
innodb_lock_waits_init() ||
1976
i_s_cmp_reset_init() ||
1977
i_s_cmpmem_init() ||
1978
i_s_cmpmem_reset_init())
1981
registry.add(innodb_engine_ptr);
1983
registry.add(innodb_trx_schema_table);
1984
registry.add(innodb_locks_schema_table);
1985
registry.add(innodb_lock_waits_schema_table);
1986
registry.add(innodb_cmp_schema_table);
1987
registry.add(innodb_cmp_reset_schema_table);
1988
registry.add(innodb_cmpmem_schema_table);
1989
registry.add(innodb_cmpmem_reset_schema_table);
2007
1991
/* Get the current high water mark format. */
2008
1992
innobase_file_format_check = (char*) trx_sys_file_format_max_get();
1999
/*******************************************************************//**
2000
Closes an InnoDB database.
2001
@return TRUE if error */
2004
innobase_deinit(drizzled::plugin::Registry ®istry)
2007
i_s_common_deinit(registry);
2008
registry.remove(innodb_engine_ptr);
2009
delete innodb_engine_ptr;
2011
if (innodb_inited) {
2013
srv_fast_shutdown = (ulint) innobase_fast_shutdown;
2015
hash_table_free(innobase_open_tables);
2016
innobase_open_tables = NULL;
2017
if (innobase_shutdown_for_mysql() != DB_SUCCESS) {
2020
srv_free_paths_and_sizes();
2021
if (internal_innobase_data_file_path)
2022
free(internal_innobase_data_file_path);
2023
pthread_mutex_destroy(&innobase_share_mutex);
2024
pthread_mutex_destroy(&prepare_commit_mutex);
2025
pthread_mutex_destroy(&commit_threads_m);
2026
pthread_mutex_destroy(&commit_cond_m);
2027
pthread_cond_destroy(&commit_cond);
2016
2033
/****************************************************************//**
2017
2034
Flushes InnoDB logs to disk and makes a checkpoint. Really, a commit flushes
2056
InnobaseEngine::doStartTransaction(
2073
InnobaseEngine::start_consistent_snapshot(
2057
2074
/*====================================*/
2058
Session* session, /*!< in: MySQL thread handle of the user for whom
2059
the transaction should be committed */
2060
start_transaction_option_t options)
2075
Session* session) /*!< in: MySQL thread handle of the user for whom
2076
the transaction should be committed */
2062
2080
assert(this == innodb_engine_ptr);
2064
2082
/* Create a new trx struct for session, if it does not yet have one */
2065
trx_t *trx = check_trx_exists(session);
2084
trx = check_trx_exists(session);
2067
2086
/* This is just to play safe: release a possible FIFO ticket and
2068
2087
search latch. Since we will reserve the kernel mutex, we have to
2069
2088
release the search system latch first to obey the latching order. */
2070
2090
innobase_release_stat_resources(trx);
2072
2092
/* If the transaction is not started yet, start it */
2073
2094
trx_start_if_not_started(trx);
2075
2096
/* Assign a read view if the transaction does not have it yet */
2076
if (options == START_TRANS_OPT_WITH_CONS_SNAPSHOT)
2077
trx_assign_read_view(trx);
2098
trx_assign_read_view(trx);
2100
/* Set the MySQL flag to mark that there is an active transaction */
2102
if (trx->active_trans == 0) {
2103
innobase_register_trx_and_stmt(this, current_session);
2104
trx->active_trans = 1;
2082
2110
/*****************************************************************//**
2104
2132
trx_search_latch_release_if_reserved(trx);
2135
/* The flag trx->active_trans is set to 1 in
2137
1. ::external_lock(),
2139
3. innobase_query_caching_of_table_permitted(),
2140
4. InnobaseEngine::savepoint_set(),
2141
5. ::init_table_handle_for_HANDLER(),
2142
6. InnobaseEngine::start_consistent_snapshot(),
2144
and it is only set to 0 in a commit or a rollback. If it is 0 we know
2145
there cannot be resources to be freed and we could return immediately.
2146
For the time being, we play safe and do the cleanup though there should
2147
be nothing to clean up. */
2149
if (trx->active_trans == 0
2150
&& trx->conc_state != TRX_NOT_STARTED) {
2152
errmsg_printf(ERRMSG_LVL_ERROR, "trx->active_trans == 0, but"
2153
" trx->conc_state != TRX_NOT_STARTED");
2108
2156
|| (!session_test_options(session, OPTION_NOT_AUTOCOMMIT | OPTION_BEGIN))) {
2263
2313
@return 0 if success, HA_ERR_NO_SAVEPOINT if no savepoint with the
2266
InnobaseEngine::doRollbackToSavepoint(
2316
InnobaseEngine::savepoint_rollback_hook(
2267
2317
/*===========================*/
2268
2318
Session* session, /*!< in: handle to the MySQL thread of the user
2269
2319
whose transaction should be rolled back */
2270
drizzled::NamedSavepoint &named_savepoint) /*!< in: savepoint data */
2320
void* savepoint) /*!< in: savepoint data */
2272
2322
ib_int64_t mysql_binlog_cache_pos;
2276
2327
assert(this == innodb_engine_ptr);
2284
2335
innobase_release_stat_resources(trx);
2286
error= (int)trx_rollback_to_savepoint_for_mysql(trx, named_savepoint.getName().c_str(),
2287
&mysql_binlog_cache_pos);
2337
/* TODO: use provided savepoint data area to store savepoint data */
2339
int64_t2str((ulint)savepoint, sp_name, 36);
2341
error = (int) trx_rollback_to_savepoint_for_mysql(trx, sp_name,
2342
&mysql_binlog_cache_pos);
2288
2343
return(convert_error_code_to_mysql(error, 0, NULL));
2293
2348
@return 0 if success, HA_ERR_NO_SAVEPOINT if no savepoint with the
2296
InnobaseEngine::doReleaseSavepoint(
2351
InnobaseEngine::savepoint_release_hook(
2297
2352
/*=======================*/
2298
2353
Session* session, /*!< in: handle to the MySQL thread of the user
2299
2354
whose transaction should be rolled back */
2300
drizzled::NamedSavepoint &named_savepoint) /*!< in: savepoint data */
2355
void* savepoint) /*!< in: savepoint data */
2305
2361
assert(this == innodb_engine_ptr);
2307
2363
trx = check_trx_exists(session);
2309
error = (int) trx_release_savepoint_for_mysql(trx, named_savepoint.getName().c_str());
2365
/* TODO: use provided savepoint data area to store savepoint data */
2367
int64_t2str((ulint)savepoint, sp_name, 36);
2369
error = (int) trx_release_savepoint_for_mysql(trx, sp_name);
2311
2371
return(convert_error_code_to_mysql(error, 0, NULL));
2315
2375
Sets a transaction savepoint.
2316
2376
@return always 0, that is, always succeeds */
2318
InnobaseEngine::doSetSavepoint(
2378
InnobaseEngine::savepoint_set_hook(
2319
2379
/*===============*/
2320
2380
Session* session,/*!< in: handle to the MySQL thread */
2321
drizzled::NamedSavepoint &named_savepoint) /*!< in: savepoint data */
2381
void* savepoint) /*!< in: savepoint data */
2340
2400
innobase_release_stat_resources(trx);
2342
2402
/* cannot happen outside of transaction */
2343
assert(trx->conc_state != TRX_NOT_STARTED);
2345
error = (int) trx_savepoint_for_mysql(trx, named_savepoint.getName().c_str(), (ib_int64_t)0);
2403
assert(trx->active_trans);
2405
/* TODO: use provided savepoint data area to store savepoint data */
2407
int64_t2str((ulint)savepoint,sp_name,36);
2409
error = (int) trx_savepoint_for_mysql(trx, sp_name, (ib_int64_t)0);
2347
2411
return(convert_error_code_to_mysql(error, 0, NULL));
2366
assert(session->killed != Session::NOT_KILLED ||
2367
trx->conc_state == TRX_NOT_STARTED);
2369
/* Warn if rolling back some things... */
2370
if (session->killed != Session::NOT_KILLED &&
2371
trx->conc_state != TRX_NOT_STARTED &&
2372
trx->undo_no.low > 0 &&
2373
global_system_variables.log_warnings)
2375
errmsg_printf(ERRMSG_LVL_WARN,
2376
"Drizzle is closing a connection during a KILL operation\n"
2377
"that has an active InnoDB transaction. %lu row modifications will "
2379
(ulong) trx->undo_no.low);
2430
if (trx->active_trans == 0
2431
&& trx->conc_state != TRX_NOT_STARTED) {
2433
errmsg_printf(ERRMSG_LVL_ERROR, "trx->active_trans == 0, but"
2434
" trx->conc_state != TRX_NOT_STARTED");
2438
if (trx->conc_state != TRX_NOT_STARTED &&
2439
global_system_variables.log_warnings) {
2440
errmsg_printf(ERRMSG_LVL_WARN,
2441
"MySQL is closing a connection that has an active "
2442
"InnoDB transaction. %lu row modifications will "
2444
(ulong) trx->undo_no.low);
2382
2447
innobase_rollback_trx(trx);
2441
2518
return("BTREE");
2522
/****************************************************************//**
2523
Returns the operations supported for indexes.
2524
@return flags of supported operations */
2527
ha_innobase::index_flags(
2528
/*=====================*/
2534
return(HA_READ_NEXT | HA_READ_PREV | HA_READ_ORDER
2535
| HA_READ_RANGE | HA_KEYREAD_ONLY);
2444
2538
/****************************************************************//**
2445
2539
Returns the maximum number of keys.
2446
2540
@return MAX_KEY */
2449
InnobaseEngine::max_supported_keys() const
2543
ha_innobase::max_supported_keys() const
2450
2544
/*===================================*/
2452
2546
return(MAX_KEY);
2639
2733
table->s->stored_rec_length
2640
2734
+ table->s->max_key_length
2641
2735
+ MAX_REF_PARTS * 3;
2642
if (!(unsigned char*) memory::multi_malloc(false,
2736
if (!(unsigned char*) drizzled::memory::multi_malloc(false,
2643
2737
&upd_buff, upd_and_key_val_buff_len,
2644
2738
&key_val_buff, upd_and_key_val_buff_len,
3742
ha_statistic_increment(&system_status_var::ha_write_count);
3836
ha_statistic_increment(&SSV::ha_write_count);
3744
3838
sql_command = session_sql_command(user_session);
3746
3840
if ((sql_command == SQLCOM_ALTER_TABLE
3841
|| sql_command == SQLCOM_OPTIMIZE
3747
3842
|| sql_command == SQLCOM_CREATE_INDEX
3748
3843
|| sql_command == SQLCOM_DROP_INDEX)
3749
3844
&& num_write_row >= 10000) {
3784
3879
no need to re-acquire locks on it. */
3786
3881
/* Altering to InnoDB format */
3787
getTransactionalEngine()->commit(user_session, 1);
3882
engine->commit(user_session, 1);
3883
/* Note that this transaction is still active. */
3884
prebuilt->trx->active_trans = 1;
3788
3885
/* We will need an IX lock on the destination table. */
3789
3886
prebuilt->sql_stat_start = TRUE;
3799
3896
/* Commit the transaction. This will release the table
3800
3897
locks, so they have to be acquired again. */
3801
getTransactionalEngine()->commit(user_session, 1);
3898
engine->commit(user_session, 1);
3899
/* Note that this transaction is still active. */
3900
prebuilt->trx->active_trans = 1;
3802
3901
/* Re-acquire the table lock on the source table. */
3803
3902
row_lock_table_for_mysql(prebuilt, src_table, mode);
3804
3903
/* We will need an IX lock on the destination table. */
4402
4501
A) if the user has not explicitly set any MySQL table level locks:
4404
1) Drizzle calls StorageEngine::doStartStatement(), indicating to
4405
InnoDB that a new SQL statement has begun.
4407
2a) For each InnoDB-managed table in the SELECT, Drizzle calls ::external_lock
4408
to set an 'intention' table level lock on the table of the Cursor instance.
4409
There we set prebuilt->sql_stat_start = TRUE. The flag sql_stat_start should
4410
be set true if we are taking this table handle instance to use in a new SQL
4411
statement issued by the user.
4413
2b) If prebuilt->sql_stat_start == TRUE we 'pre-compile' the MySQL search
4503
1) MySQL calls ::external_lock to set an 'intention' table level lock on
4504
the table of the handle instance. There we set
4505
prebuilt->sql_stat_start = TRUE. The flag sql_stat_start should be set
4506
true if we are taking this table handle instance to use in a new SQL
4507
statement issued by the user. We also increment trx->n_mysql_tables_in_use.
4509
2) If prebuilt->sql_stat_start == TRUE we 'pre-compile' the MySQL search
4414
4510
instructions to prebuilt->template of the table handle instance in
4415
4511
::index_read. The template is used to save CPU time in large joins.
4422
4518
4) We do the SELECT. MySQL may repeatedly call ::index_read for the
4423
4519
same table handle instance, if it is a join.
4425
5) When the SELECT ends, the Drizzle kernel calls doEndStatement()
4427
(a) we execute a COMMIT there if the autocommit is on. The Drizzle interpreter
4428
does NOT execute autocommit for pure read transactions, though it should.
4429
That is why we must execute the COMMIT in ::doEndStatement().
4521
5) When the SELECT ends, MySQL removes its intention table level locks
4522
in ::external_lock. When trx->n_mysql_tables_in_use drops to zero,
4523
(a) we execute a COMMIT there if the autocommit is on,
4430
4524
(b) we also release possible 'SQL statement level resources' InnoDB may
4431
have for this SQL statement.
4435
Remove need for InnoDB to call autocommit for read-only trx
4437
@todo Check the below is still valid (I don't think it is...)
4525
have for this SQL statement. The MySQL interpreter does NOT execute
4526
autocommit for pure read transactions, though it should. That is why the
4527
table Cursor in that case has to execute the COMMIT in ::external_lock.
4439
4529
B) If the user has explicitly set MySQL table level locks, then MySQL
4440
4530
does NOT call ::external_lock at the start of the statement. To determine
5443
5534
InnobaseEngine::doCreateTable(
5444
5535
/*================*/
5445
5536
Session* session, /*!< in: Session */
5446
Table& form, /*!< in: information on table columns and indexes */
5447
drizzled::TableIdentifier &identifier,
5448
message::Table& create_proto)
5537
const char* table_name, /*!< in: table name */
5538
Table& form, /*!< in: information on table
5539
columns and indexes */
5540
HA_CREATE_INFO& create_info, /*!< in: more information of the
5541
created table, contains also the
5542
create statement string */
5543
drizzled::message::Table& create_proto)
5451
5546
dict_table_t* innobase_table;
5717
if (trx->mysql_query_str) {
5811
if (*trx->mysql_query_str) {
5718
5812
error = row_table_add_foreign_constraints(trx,
5719
trx->mysql_query_str, norm_name,
5720
lex_identified_temp_table);
5813
*trx->mysql_query_str, norm_name,
5814
create_info.options & HA_LEX_CREATE_TMP_TABLE);
5722
5816
error = convert_error_code_to_mysql(error, iflags, NULL);
5755
5849
/* We need to copy the AUTOINC value from the old table if
5756
5850
this is an ALTER TABLE. */
5758
if ((create_proto.options().has_auto_increment_value()
5852
if (((create_info.used_fields & HA_CREATE_USED_AUTO)
5759
5853
|| session_sql_command(session) == SQLCOM_ALTER_TABLE)
5760
&& create_proto.options().auto_increment_value() != 0) {
5854
&& create_info.auto_increment_value != 0) {
5762
5856
/* Query was ALTER TABLE...AUTO_INCREMENT = x; or
5763
5857
CREATE TABLE ...AUTO_INCREMENT = x; Find out a table
5872
5966
InnobaseEngine::doDropTable(
5873
5967
/*======================*/
5875
TableIdentifier &identifier)
5969
const string table_path) /* in: table name */
5878
5972
trx_t* parent_trx;
5880
5974
char norm_name[1000];
5882
ut_a(identifier.getPath().length() < 1000);
5976
ut_a(table_path.length() < 1000);
5884
5978
/* Strangely, MySQL passes the table name without the '.frm'
5885
5979
extension, in contrast to ::create */
5886
normalize_table_name(norm_name, identifier.getPath().c_str());
5980
normalize_table_name(norm_name, table_path.c_str());
5888
5982
/* Get the transaction associated with the current session, or create one
5889
5983
if not yet created */
5929
6023
/*****************************************************************//**
5930
6024
Removes all tables in the named database inside InnoDB. */
5932
InnobaseEngine::doDropSchema(
6026
InnobaseEngine::drop_database(
5933
6027
/*===================*/
5934
const std::string &schema_name)
5935
/*!< in: database path; inside InnoDB the name
6028
char* path) /*!< in: database path; inside InnoDB the name
5936
6029
of the last directory in the path is used as
5937
6030
the database name: for example, in 'mysql/data/test'
5938
6031
the database name is 'test' */
5942
string schema_path(schema_name);
5943
6038
Session* session = current_session;
5945
6040
/* Get the transaction associated with the current session, or create one
5958
6053
trx_search_latch_release_if_reserved(parent_trx);
5961
schema_path.append("/");
6056
ptr = strchr(path, '\0') - 2;
6058
while (ptr >= path && *ptr != '\\' && *ptr != '/') {
6064
namebuf = (char*) malloc((uint) len + 2);
6066
memcpy(namebuf, ptr, len);
6068
namebuf[len + 1] = '\0';
6070
innobase_casedn_str(namebuf);
6072
#if defined __WIN__ && !defined MYSQL_SERVER
6073
/* In the Windows plugin, thd = current_thd is always NULL */
6074
trx = trx_allocate_for_mysql();
6075
trx->mysql_thd = NULL;
6076
trx->mysql_query_str = NULL;
5962
6078
trx = innobase_trx_allocate(session);
5963
error = row_drop_database_for_mysql(schema_path.c_str(), trx);
6080
error = row_drop_database_for_mysql(namebuf, trx);
5965
6083
/* Flush the log to reduce probability that the .frm files and
5966
6084
the InnoDB data dictionary get out-of-sync if the user runs
6352
6468
snprintf(path, sizeof(path), "%s/%s%s",
6353
6469
drizzle_data_home, ib_table->name, ".dfe");
6355
internal::unpack_filename(path,path);
6471
unpack_filename(path,path);
6357
6473
/* Note that we do not know the access time of the table,
6358
6474
nor the CHECK TABLE time, nor the UPDATE or INSERT time. */
6690
/**********************************************************************//**
6691
This is mapped to "ALTER TABLE tablename ENGINE=InnoDB", which rebuilds
6692
the table in MySQL. */
6695
ha_innobase::optimize(
6696
/*==================*/
6697
Session* , /*!< in: connection thread handle */
6698
HA_CHECK_OPT* ) /*!< in: currently ignored */
6700
return(HA_ADMIN_TRY_ALTER);
6573
6703
/*******************************************************************//**
6574
6704
Tries to check that an InnoDB table is not corrupted. If corruption is
6575
6705
noticed, prints to stderr information about it. In case of corruption
6767
6899
while (tmp_buff[i] != '/')
6769
6901
tmp_buff+= i + 1;
6770
f_key_info.forein_id = session->make_lex_string(NULL, tmp_buff, strlen(tmp_buff), true);
6902
f_key_info.forein_id = session_make_lex_string(session, 0,
6903
tmp_buff, (uint) strlen(tmp_buff), 1);
6771
6904
tmp_buff= foreign->referenced_table_name;
6773
6906
/* Database name */
6781
6914
ulen= filename_to_tablename(db_name, uname, sizeof(uname));
6782
f_key_info.referenced_db = session->make_lex_string(NULL, uname, ulen, true);
6915
f_key_info.referenced_db = session_make_lex_string(session, 0,
6784
6918
/* Table name */
6785
6919
tmp_buff+= i + 1;
6786
6920
ulen= filename_to_tablename(tmp_buff, uname, sizeof(uname));
6787
f_key_info.referenced_table = session->make_lex_string(NULL, uname, ulen, true);
6921
f_key_info.referenced_table = session_make_lex_string(session, 0,
6790
6925
tmp_buff= foreign->foreign_col_names[i];
6791
name = session->make_lex_string(name, tmp_buff, strlen(tmp_buff), true);
6926
name = session_make_lex_string(session, name,
6927
tmp_buff, (uint) strlen(tmp_buff), 1);
6792
6928
f_key_info.foreign_fields.push_back(name);
6793
6929
tmp_buff= foreign->referenced_col_names[i];
6794
name = session->make_lex_string(name, tmp_buff, strlen(tmp_buff), true);
6930
name = session_make_lex_string(session, name,
6931
tmp_buff, (uint) strlen(tmp_buff), 1);
6795
6932
f_key_info.referenced_fields.push_back(name);
6796
6933
if (++i >= foreign->n_fields)
6819
6956
tmp_buff= "RESTRICT";
6821
f_key_info.delete_method = session->make_lex_string(
6822
f_key_info.delete_method, tmp_buff, length, true);
6958
f_key_info.delete_method = session_make_lex_string(
6959
session, f_key_info.delete_method, tmp_buff, length, 1);
6825
6962
if (foreign->type & DICT_FOREIGN_ON_UPDATE_CASCADE)
6843
6980
tmp_buff= "RESTRICT";
6845
f_key_info.update_method = session->make_lex_string(
6846
f_key_info.update_method, tmp_buff, length, true);
6982
f_key_info.update_method = session_make_lex_string(
6983
session, f_key_info.update_method, tmp_buff, length, 1);
6847
6984
if (foreign->referenced_index &&
6848
6985
foreign->referenced_index->name)
6850
f_key_info.referenced_key_name = session->make_lex_string(
6851
f_key_info.referenced_key_name,
6987
f_key_info.referenced_key_name = session_make_lex_string(
6988
session, f_key_info.referenced_key_name,
6852
6989
foreign->referenced_index->name,
6853
strlen(foreign->referenced_index->name), true);
6990
(uint) strlen(foreign->referenced_index->name), 1);
6856
6993
f_key_info.referenced_key_name= 0;
7007
7144
/******************************************************************//**
7145
MySQL calls this function at the start of each SQL statement inside LOCK
7146
TABLES. Inside LOCK TABLES the ::external_lock method does not work to
7147
mark SQL statement borders. Note also a special case: if a temporary table
7148
is created inside LOCK TABLES, MySQL has not called external_lock() at all
7150
MySQL-5.0 also calls this before each statement in an execution of a stored
7151
procedure. To make the execution more deterministic for binlogging, MySQL-5.0
7152
locks all tables involved in a stored procedure with full explicit table
7153
locks (session_in_lock_tables(session) holds in store_lock()) before executing
7155
@return 0 or error code */
7158
ha_innobase::start_stmt(
7159
/*====================*/
7160
Session* session, /*!< in: handle to the user thread */
7161
thr_lock_type lock_type)
7165
update_session(session);
7167
trx = prebuilt->trx;
7169
/* Here we release the search latch and the InnoDB thread FIFO ticket
7170
if they were reserved. They should have been released already at the
7171
end of the previous statement, but because inside LOCK TABLES the
7172
lock count method does not work to mark the end of a SELECT statement,
7173
that may not be the case. We MUST release the search latch before an
7174
INSERT, for example. */
7176
innobase_release_stat_resources(trx);
7178
/* Reset the AUTOINC statement level counter for multi-row INSERTs. */
7179
trx->n_autoinc_rows = 0;
7181
prebuilt->sql_stat_start = TRUE;
7182
prebuilt->hint_need_to_fetch_extra_cols = 0;
7183
reset_template(prebuilt);
7185
if (!prebuilt->mysql_has_locked) {
7186
/* This handle is for a temporary table created inside
7187
this same LOCK TABLES; since MySQL does NOT call external_lock
7188
in this case, we must use x-row locks inside InnoDB to be
7189
prepared for an update of a row */
7191
prebuilt->select_lock_type = LOCK_X;
7193
if (trx->isolation_level != TRX_ISO_SERIALIZABLE
7194
&& session_sql_command(session) == SQLCOM_SELECT
7195
&& lock_type == TL_READ) {
7197
/* For other than temporary tables, we obtain
7198
no lock for consistent read (plain SELECT). */
7200
prebuilt->select_lock_type = LOCK_NONE;
7202
/* Not a consistent read: restore the
7203
select_lock_type value. The value of
7204
stored_select_lock_type was decided in:
7206
2) ::external_lock(),
7207
3) ::init_table_handle_for_HANDLER(), and
7210
prebuilt->select_lock_type =
7211
prebuilt->stored_select_lock_type;
7215
trx->detailed_error[0] = '\0';
7217
/* Set the MySQL flag to mark that there is an active transaction */
7218
if (trx->active_trans == 0) {
7220
innobase_register_trx_and_stmt(engine, session);
7221
trx->active_trans = 1;
7223
innobase_register_stmt(engine, session);
7229
/******************************************************************//**
7008
7230
Maps a MySQL trx isolation level code to the InnoDB isolation level code
7009
7231
@return InnoDB isolation level */
7025
7247
/******************************************************************//**
7026
7248
As MySQL will execute an external lock for every new table it uses when it
7027
starts to process an SQL statement. We can use this function to store the pointer to
7028
the Session in the handle.
7249
starts to process an SQL statement (an exception is when MySQL calls
7250
start_stmt for the handle) we can use this function to store the pointer to
7251
the Session in the handle. We will also use this function to communicate
7252
to InnoDB that a new SQL statement has started and that we must store a
7253
savepoint to our transaction handle, so that we are able to roll back
7254
the SQL statement in case of an error.
7054
7283
if (lock_type != F_UNLCK) {
7055
7284
/* MySQL is setting a new table lock */
7286
trx->detailed_error[0] = '\0';
7288
/* Set the MySQL flag to mark that there is an active
7290
if (trx->active_trans == 0) {
7292
innobase_register_trx_and_stmt(engine, session);
7293
trx->active_trans = 1;
7294
} else if (trx->n_mysql_tables_in_use == 0) {
7295
innobase_register_stmt(engine, session);
7057
7298
if (trx->isolation_level == TRX_ISO_SERIALIZABLE
7058
7299
&& prebuilt->select_lock_type == LOCK_NONE
7059
7300
&& session_test_options(session,
7086
7327
trx->mysql_n_tables_locked++;
7330
trx->n_mysql_tables_in_use++;
7089
7331
prebuilt->mysql_has_locked = TRUE;
7094
7336
/* MySQL is releasing a table lock */
7338
trx->n_mysql_tables_in_use--;
7095
7339
prebuilt->mysql_has_locked = FALSE;
7096
trx->mysql_n_tables_locked= 0;
7341
/* Release a possible FIFO ticket and search latch. Since we
7342
may reserve the kernel mutex, we have to release the search
7343
system latch first to obey the latching order. */
7345
innobase_release_stat_resources(trx);
7347
/* If the MySQL lock count drops to zero we know that the current SQL
7348
statement has ended */
7350
if (trx->n_mysql_tables_in_use == 0) {
7352
trx->mysql_n_tables_locked = 0;
7353
prebuilt->used_in_HANDLER = FALSE;
7355
if (!session_test_options(session, OPTION_NOT_AUTOCOMMIT | OPTION_BEGIN)) {
7356
if (trx->active_trans != 0) {
7357
engine->commit(session, TRUE);
7360
if (trx->isolation_level <= TRX_ISO_READ_COMMITTED
7361
&& trx->global_read_view) {
7363
/* At low transaction isolation levels we let
7364
each consistent read set its own snapshot */
7366
read_view_close_for_mysql(trx);
7101
7374
/************************************************************************//**
7375
Here we export InnoDB status variables to MySQL. */
7378
innodb_export_status(void)
7379
/*======================*/
7381
if (innodb_inited) {
7382
srv_export_innodb_status();
7386
/************************************************************************//**
7102
7387
Implements the SHOW INNODB STATUS command. Sends the output of the InnoDB
7103
7388
Monitor to the client. */
7106
7391
innodb_show_status(
7107
7392
/*===============*/
7108
plugin::StorageEngine* engine, /*!< in: the innodb StorageEngine */
7393
drizzled::plugin::StorageEngine* engine, /*!< in: the innodb StorageEngine */
7109
7394
Session* session,/*!< in: the MySQL query thread of the caller */
7110
7395
stat_print_fn *stat_print)
7193
7478
innodb_mutex_show_status(
7194
7479
/*=====================*/
7195
plugin::StorageEngine* engine, /*!< in: the innodb StorageEngine */
7480
drizzled::plugin::StorageEngine* engine, /*!< in: the innodb StorageEngine */
7196
7481
Session* session, /*!< in: the MySQL query thread of the
7198
7483
stat_print_fn* stat_print)
7437
7722
trx = check_trx_exists(session);
7724
/* NOTE: MySQL can call this function with lock 'type' TL_IGNORE!
7725
Be careful to ignore TL_IGNORE if we are going to do something with
7726
only 'real' locks! */
7728
/* If no MySQL table is in use, we need to set the isolation level
7729
of the transaction. */
7731
if (lock_type != TL_IGNORE
7732
&& trx->n_mysql_tables_in_use == 0) {
7733
trx->isolation_level = innobase_map_isolation_level(
7734
(enum_tx_isolation) session_tx_isolation(session));
7736
if (trx->isolation_level <= TRX_ISO_READ_COMMITTED
7737
&& trx->global_read_view) {
7739
/* At low transaction isolation levels we let
7740
each consistent read set its own snapshot */
7742
read_view_close_for_mysql(trx);
7439
7746
assert(EQ_CURRENT_SESSION(session));
7440
7747
const uint32_t sql_command = session_sql_command(session);
7516
7823
TABLESPACE or TRUNCATE TABLE then allow multiple
7517
7824
writers. Note that ALTER TABLE uses a TL_WRITE_ALLOW_READ
7518
7825
< TL_WRITE_CONCURRENT_INSERT.
7827
We especially allow multiple writers if MySQL is at the
7828
start of a stored procedure call (SQLCOM_CALL) or a
7829
stored function call (MySQL does have in_lock_tables
7521
7832
if ((lock_type >= TL_WRITE_CONCURRENT_INSERT
7522
7833
&& lock_type <= TL_WRITE)
7523
7834
&& !session_tablespace_op(session)
7524
7835
&& sql_command != SQLCOM_TRUNCATE
7836
&& sql_command != SQLCOM_OPTIMIZE
7525
7837
&& sql_command != SQLCOM_CREATE_TABLE) {
7527
7839
lock_type = TL_WRITE_ALLOW_WRITE;
7532
7844
would conflict with TL_WRITE_ALLOW_WRITE, blocking all inserts
7533
7845
to t2. Convert the lock to a normal read lock to allow
7534
7846
concurrent inserts to t2.
7848
We especially allow concurrent inserts if MySQL is at the
7849
start of a stored procedure call (SQLCOM_CALL)
7850
(MySQL does have session_in_lock_tables() TRUE there). */
7537
7852
if (lock_type == TL_READ_NO_INSERT) {
7745
8060
innobase_reset_autoinc(value);
7750
8065
/* See comment in Cursor.cc */
7753
InnobaseEngine::get_error_message(int, String *buf)
8068
ha_innobase::get_error_message(int, String *buf)
7755
trx_t* trx = check_trx_exists(current_session);
8070
trx_t* trx = check_trx_exists(ha_session());
7757
8072
buf->copy(trx->detailed_error, (uint) strlen(trx->detailed_error),
7758
8073
system_charset_info);
7908
8223
return(char_length);
7911
* We will also use this function to communicate
7912
* to InnoDB that a new SQL statement has started and that we must store a
7913
* savepoint to our transaction handle, so that we are able to roll back
7914
* the SQL statement in case of an error.
7917
InnobaseEngine::doStartStatement(
7918
Session *session) /*!< in: handle to the Drizzle session */
7921
* Create the InnoDB transaction structure
7924
trx_t *trx= check_trx_exists(session);
7926
/* "reset" the error message for the transaction */
7927
trx->detailed_error[0]= '\0';
7929
/* Set the isolation level of the transaction. */
7930
trx->isolation_level= innobase_map_isolation_level((enum_tx_isolation) session_tx_isolation(session));
7934
InnobaseEngine::doEndStatement(
7937
trx_t *trx= check_trx_exists(session);
7939
/* Release a possible FIFO ticket and search latch. Since we
7940
may reserve the kernel mutex, we have to release the search
7941
system latch first to obey the latching order. */
7943
innobase_release_stat_resources(trx);
7945
if (! session_test_options(session, OPTION_NOT_AUTOCOMMIT | OPTION_BEGIN))
7947
if (trx->conc_state != TRX_NOT_STARTED)
7949
commit(session, TRUE);
7954
if (trx->isolation_level <= TRX_ISO_READ_COMMITTED &&
7955
trx->global_read_view)
7957
/* At low transaction isolation levels we let
7958
each consistent read set its own snapshot */
7959
read_view_close_for_mysql(trx);
7964
8226
/*******************************************************************//**
7965
8227
This function is used to prepare an X/Open XA distributed transaction.
7966
8228
@return 0 or error number */
7968
InnobaseEngine::doXaPrepare(
8230
InnobaseEngine::prepare(
7969
8231
/*================*/
7970
8232
Session* session,/*!< in: handle to the MySQL thread of
7971
8233
the user whose XA transaction should
7996
8258
innobase_release_stat_resources(trx);
8260
if (trx->active_trans == 0 && trx->conc_state != TRX_NOT_STARTED) {
8262
errmsg_printf(ERRMSG_LVL_ERROR,
8263
"trx->active_trans == 0, but trx->conc_state != "
7999
8268
|| (!session_test_options(session, OPTION_NOT_AUTOCOMMIT | OPTION_BEGIN))) {
8001
8270
/* We were instructed to prepare the whole transaction, or
8002
8271
this is an SQL statement end and autocommit is on */
8004
ut_ad(trx->conc_state != TRX_NOT_STARTED);
8273
ut_ad(trx->active_trans);
8006
8275
error = (int) trx_prepare_for_mysql(trx);
8057
8326
This function is used to recover X/Open XA distributed transactions.
8058
8327
@return number of prepared transactions stored in xid_list */
8060
InnobaseEngine::doXaRecover(
8329
InnobaseEngine::recover(
8061
8330
/*================*/
8062
::drizzled::XID* xid_list,/*!< in/out: prepared transactions */
8063
size_t len) /*!< in: number of slots in xid_list */
8331
XID* xid_list,/*!< in/out: prepared transactions */
8332
uint len) /*!< in: number of slots in xid_list */
8065
8334
assert(this == innodb_engine_ptr);
8077
8346
which is in the prepared state
8078
8347
@return 0 or error number */
8080
InnobaseEngine::doXaCommitXid(
8349
InnobaseEngine::commit_by_xid(
8081
8350
/*===================*/
8082
::drizzled::XID* xid) /*!< in: X/Open XA transaction identification */
8351
XID* xid) /*!< in: X/Open XA transaction identification */
8086
8355
assert(this == innodb_engine_ptr);
8088
trx = trx_get_trx_by_xid((::XID *)xid);
8357
trx = trx_get_trx_by_xid(xid);
8091
8360
innobase_commit_low(trx);
8101
8370
which is in the prepared state
8102
8371
@return 0 or error number */
8104
InnobaseEngine::doXaRollbackXid(
8373
InnobaseEngine::rollback_by_xid(
8105
8374
/*=====================*/
8106
::drizzled::XID* xid) /*!< in: X/Open XA transaction
8375
XID* xid) /*!< in: X/Open XA transaction
8107
8376
identification */
8111
8380
assert(this == innodb_engine_ptr);
8113
trx = trx_get_trx_by_xid((::XID *)xid);
8382
trx = trx_get_trx_by_xid(xid);
8116
8385
return(innobase_rollback_trx(trx));
8224
8493
innodb_file_format_name_validate(
8225
8494
/*=============================*/
8226
8495
Session* , /*!< in: thread handle */
8227
drizzle_sys_var* , /*!< in: pointer to system
8496
struct st_mysql_sys_var* , /*!< in: pointer to system
8229
8498
void* save, /*!< out: immediate result
8230
8499
for update function */
8231
drizzle_value* value) /*!< in: incoming string */
8500
struct st_mysql_value* value) /*!< in: incoming string */
8233
8502
const char* file_format_input;
8234
8503
char buff[STRING_BUFFER_USUAL_SIZE];
8264
8533
innodb_file_format_name_update(
8265
8534
/*===========================*/
8266
8535
Session* , /*!< in: thread handle */
8267
drizzle_sys_var* , /*!< in: pointer to
8536
struct st_mysql_sys_var* , /*!< in: pointer to
8268
8537
system variable */
8269
8538
void* var_ptr, /*!< out: where the
8270
8539
formal string goes */
8301
8570
innodb_file_format_check_validate(
8302
8571
/*==============================*/
8303
8572
Session* , /*!< in: thread handle */
8304
drizzle_sys_var* , /*!< in: pointer to system
8573
struct st_mysql_sys_var* , /*!< in: pointer to system
8306
8575
void* save, /*!< out: immediate result
8307
8576
for update function */
8308
drizzle_value* value) /*!< in: incoming string */
8577
struct st_mysql_value* value) /*!< in: incoming string */
8310
8579
const char* file_format_input;
8311
8580
char buff[STRING_BUFFER_USUAL_SIZE];
8355
8624
innodb_file_format_check_update(
8356
8625
/*============================*/
8357
8626
Session* session, /*!< in: thread handle */
8358
drizzle_sys_var* , /*!< in: pointer to
8627
struct st_mysql_sys_var* , /*!< in: pointer to
8359
8628
system variable */
8360
8629
void* var_ptr, /*!< out: where the
8361
8630
formal string goes */
8406
8675
innodb_adaptive_hash_index_update(
8407
8676
/*==============================*/
8408
8677
Session* , /*!< in: thread handle */
8409
drizzle_sys_var* , /*!< in: pointer to
8678
struct st_mysql_sys_var* , /*!< in: pointer to
8410
8679
system variable */
8411
8680
void* , /*!< out: where the
8412
8681
formal string goes */
8429
8698
innodb_change_buffering_validate(
8430
8699
/*=============================*/
8431
8700
Session* , /*!< in: thread handle */
8432
drizzle_sys_var* , /*!< in: pointer to system
8701
struct st_mysql_sys_var* , /*!< in: pointer to system
8434
8703
void* save, /*!< out: immediate result
8435
8704
for update function */
8436
drizzle_value* value) /*!< in: incoming string */
8705
struct st_mysql_value* value) /*!< in: incoming string */
8438
8707
const char* change_buffering_input;
8439
8708
char buff[STRING_BUFFER_USUAL_SIZE];
8469
8738
innodb_change_buffering_update(
8470
8739
/*===========================*/
8471
8740
Session* , /*!< in: thread handle */
8472
drizzle_sys_var* , /*!< in: pointer to
8741
struct st_mysql_sys_var* , /*!< in: pointer to
8473
8742
system variable */
8474
8743
void* var_ptr, /*!< out: where the
8475
8744
formal string goes */
8485
8754
*(const char**) var_ptr = innobase_change_buffering_values[ibuf_use];
8757
static int show_innodb_vars(SHOW_VAR *var, char *)
8759
innodb_export_status();
8760
var->type= SHOW_ARRAY;
8761
var->value= (char *) &innodb_status_variables;
8765
static st_show_var_func_container
8766
show_innodb_vars_cont = { &show_innodb_vars };
8768
static SHOW_VAR innodb_status_variables_export[]= {
8769
{"Innodb", (char*) &show_innodb_vars_cont, SHOW_FUNC},
8770
{NULL, NULL, SHOW_LONG}
8488
8774
/* plugin options */
8489
8775
static DRIZZLE_SYSVAR_BOOL(checksums, innobase_use_checksums,
8490
8776
PLUGIN_VAR_NOCMDARG | PLUGIN_VAR_READONLY,
8545
8831
PLUGIN_VAR_RQCMDARG | PLUGIN_VAR_READONLY,
8546
8832
"With which method to flush data.", NULL, NULL, NULL);
8834
static DRIZZLE_SYSVAR_BOOL(locks_unsafe_for_binlog, innobase_locks_unsafe_for_binlog,
8835
PLUGIN_VAR_NOCMDARG | PLUGIN_VAR_READONLY,
8836
"Force InnoDB to not use next-key locking, to use only row-level locking.",
8548
8839
#ifdef UNIV_LOG_ARCHIVE
8549
8840
static DRIZZLE_SYSVAR_STR(log_arch_dir, innobase_log_arch_dir,
8550
8841
PLUGIN_VAR_RQCMDARG | PLUGIN_VAR_READONLY,
8735
9026
"trigger a readahead.",
8736
9027
NULL, NULL, 56, 0, 64, 0);
8738
static drizzle_sys_var* innobase_system_variables[]= {
9029
static struct st_mysql_sys_var* innobase_system_variables[]= {
8739
9030
DRIZZLE_SYSVAR(additional_mem_pool_size),
8740
9031
DRIZZLE_SYSVAR(autoextend_increment),
8741
9032
DRIZZLE_SYSVAR(buffer_pool_size),
8755
9046
DRIZZLE_SYSVAR(flush_log_at_trx_commit),
8756
9047
DRIZZLE_SYSVAR(flush_method),
8757
9048
DRIZZLE_SYSVAR(force_recovery),
9049
DRIZZLE_SYSVAR(locks_unsafe_for_binlog),
8758
9050
DRIZZLE_SYSVAR(lock_wait_timeout),
8759
9051
#ifdef UNIV_LOG_ARCHIVE
8760
9052
DRIZZLE_SYSVAR(log_arch_dir),
8794
DRIZZLE_DECLARE_PLUGIN
9086
drizzle_declare_plugin
8797
9088
innobase_engine_name,
8798
9089
INNODB_VERSION_STR,
8800
9091
"Supports transactions, row-level locking, and foreign keys",
8801
9092
PLUGIN_LICENSE_GPL,
8802
9093
innobase_init, /* Plugin Init */
9094
innobase_deinit, /* Plugin Deinit */
9095
innodb_status_variables_export,/* status variables */
8803
9096
innobase_system_variables, /* system variables */
8804
9097
NULL /* reserved */
8806
DRIZZLE_DECLARE_PLUGIN_END;
9099
drizzle_declare_plugin_end;
8808
9101
int ha_innobase::read_range_first(const key_range *start_key,
8809
9102
const key_range *end_key,