Below is the list of changes that have just been committed into a local
5.1 repository of cmiller. When cmiller does a push these changes will
be propagated to the main repository and, within 24 hours after the
push, to the public repository.
For information on how to access the public repository
see http://dev.mysql.com/doc/mysql/en/installing-source-tree.html
ChangeSet@stripped, 2006-09-28 07:20:50-04:00, cmiller@stripped +9 -0
Merge zippy.cornsilk.net:/home/cmiller/work/mysql/mysql-5.0-maint
into zippy.cornsilk.net:/home/cmiller/work/mysql/mysql-5.1-maint
MERGE: 1.1810.1697.175
extra/yassl/src/Makefile.am@stripped, 2006-09-28 07:20:46-04:00, cmiller@stripped
+0 -0
Auto merged
MERGE: 1.10.1.2
extra/yassl/taocrypt/benchmark/Makefile.am@stripped, 2006-09-28 07:20:46-04:00,
cmiller@stripped +0 -0
Auto merged
MERGE: 1.2.1.1
extra/yassl/taocrypt/src/Makefile.am@stripped, 2006-09-28 07:20:46-04:00,
cmiller@stripped +0 -0
Auto merged
MERGE: 1.14.1.1
extra/yassl/taocrypt/test/Makefile.am@stripped, 2006-09-28 07:20:46-04:00,
cmiller@stripped +0 -0
Auto merged
MERGE: 1.2.1.1
extra/yassl/testsuite/Makefile.am@stripped, 2006-09-28 07:20:46-04:00,
cmiller@stripped +0 -0
Auto merged
MERGE: 1.3.1.3
mysql-test/mysql-test-run.pl@stripped, 2006-09-28 07:20:47-04:00,
cmiller@stripped +0 -0
Auto merged
MERGE: 1.30.1.92
mysql-test/r/strict.result@stripped, 2006-09-28 07:20:47-04:00, cmiller@stripped
+0 -0
Auto merged
MERGE: 1.25.1.5
sql/Makefile.am@stripped, 2006-09-28 07:20:47-04:00, cmiller@stripped +0 -0
Auto merged
MERGE: 1.103.1.23
storage/innobase/handler/ha_innodb.cc@stripped, 2006-09-28 07:20:47-04:00,
cmiller@stripped +0 -0
Auto merged
MERGE: 1.202.26.2
storage/innobase/handler/ha_innodb.cc@stripped, 2006-09-28 07:20:46-04:00,
cmiller@stripped +0 -0
Merge rename: sql/ha_innodb.cc -> storage/innobase/handler/ha_innodb.cc
# This is a BitKeeper patch. What follows are the unified diffs for the
# set of deltas contained in the patch. The rest of the patch, the part
# that BitKeeper cares about, is below these diffs.
# User: cmiller
# Host: zippy.cornsilk.net
# Root: /home/cmiller/work/mysql/mysql-5.1-maint/RESYNC
--- 1.202.26.1/sql/ha_innodb.cc 2006-09-28 07:20:56 -04:00
+++ 1.302/storage/innobase/handler/ha_innodb.cc 2006-09-28 07:20:56 -04:00
@@ -31,10 +31,10 @@ have disables the InnoDB inlining in thi
#pragma implementation // gcc: Class implementation
#endif
-#include "mysql_priv.h"
-#include "slave.h"
+#include <mysql_priv.h>
+
+#ifdef WITH_INNOBASE_STORAGE_ENGINE
-#ifdef HAVE_INNOBASE_DB
#include <m_ctype.h>
#include <hash.h>
#include <myisampack.h>
@@ -111,28 +111,30 @@ typedef byte mysql_byte;
/* Include necessary InnoDB headers */
extern "C" {
-#include "../innobase/include/univ.i"
-#include "../innobase/include/os0file.h"
-#include "../innobase/include/os0thread.h"
-#include "../innobase/include/srv0start.h"
-#include "../innobase/include/srv0srv.h"
-#include "../innobase/include/trx0roll.h"
-#include "../innobase/include/trx0trx.h"
-#include "../innobase/include/trx0sys.h"
-#include "../innobase/include/mtr0mtr.h"
-#include "../innobase/include/row0ins.h"
-#include "../innobase/include/row0mysql.h"
-#include "../innobase/include/row0sel.h"
-#include "../innobase/include/row0upd.h"
-#include "../innobase/include/log0log.h"
-#include "../innobase/include/lock0lock.h"
-#include "../innobase/include/dict0crea.h"
-#include "../innobase/include/btr0cur.h"
-#include "../innobase/include/btr0btr.h"
-#include "../innobase/include/fsp0fsp.h"
-#include "../innobase/include/sync0sync.h"
-#include "../innobase/include/fil0fil.h"
-#include "../innobase/include/trx0xa.h"
+#include "../storage/innobase/include/univ.i"
+#include "../storage/innobase/include/os0file.h"
+#include "../storage/innobase/include/os0thread.h"
+#include "../storage/innobase/include/srv0start.h"
+#include "../storage/innobase/include/srv0srv.h"
+#include "../storage/innobase/include/trx0roll.h"
+#include "../storage/innobase/include/trx0trx.h"
+#include "../storage/innobase/include/trx0sys.h"
+#include "../storage/innobase/include/mtr0mtr.h"
+#include "../storage/innobase/include/row0ins.h"
+#include "../storage/innobase/include/row0mysql.h"
+#include "../storage/innobase/include/row0sel.h"
+#include "../storage/innobase/include/row0upd.h"
+#include "../storage/innobase/include/log0log.h"
+#include "../storage/innobase/include/lock0lock.h"
+#include "../storage/innobase/include/dict0crea.h"
+#include "../storage/innobase/include/btr0cur.h"
+#include "../storage/innobase/include/btr0btr.h"
+#include "../storage/innobase/include/fsp0fsp.h"
+#include "../storage/innobase/include/sync0sync.h"
+#include "../storage/innobase/include/fil0fil.h"
+#include "../storage/innobase/include/trx0xa.h"
+#include "../storage/innobase/include/thr0loc.h"
+#include "../storage/innobase/include/ha_prototypes.h"
}
#define HA_INNOBASE_ROWS_IN_TABLE 10000 /* to get optimization right */
@@ -201,30 +203,18 @@ static int innobase_rollback(THD* thd, b
static int innobase_rollback_to_savepoint(THD* thd, void *savepoint);
static int innobase_savepoint(THD* thd, void *savepoint);
static int innobase_release_savepoint(THD* thd, void *savepoint);
+static handler *innobase_create_handler(TABLE_SHARE *table,
+ MEM_ROOT *mem_root);
+
+static const char innobase_hton_name[]= "InnoDB";
+
+handlerton *innobase_hton;
+
+static handler *innobase_create_handler(TABLE_SHARE *table, MEM_ROOT *mem_root)
+{
+ return new (mem_root) ha_innobase(table);
+}
-handlerton innobase_hton = {
- "InnoDB",
- SHOW_OPTION_YES,
- "Supports transactions, row-level locking, and foreign keys",
- DB_TYPE_INNODB,
- innobase_init,
- 0, /* slot */
- sizeof(trx_named_savept_t), /* savepoint size. TODO: use it */
- innobase_close_connection,
- innobase_savepoint,
- innobase_rollback_to_savepoint,
- innobase_release_savepoint,
- innobase_commit, /* commit */
- innobase_rollback, /* rollback */
- innobase_xa_prepare, /* prepare */
- innobase_xa_recover, /* recover */
- innobase_commit_by_xid, /* commit_by_xid */
- innobase_rollback_by_xid, /* rollback_by_xid */
- innobase_create_cursor_view,
- innobase_set_cursor_view,
- innobase_close_cursor_view,
- HTON_NO_FLAGS
-};
/*********************************************************************
Commits a transaction in an InnoDB database. */
@@ -234,7 +224,7 @@ innobase_commit_low(
/*================*/
trx_t* trx); /* in: transaction handle */
-struct show_var_st innodb_status_variables[]= {
+SHOW_VAR innodb_status_variables[]= {
{"buffer_pool_pages_data",
(char*) &export_vars.innodb_buffer_pool_pages_data, SHOW_LONG},
{"buffer_pool_pages_dirty",
@@ -321,7 +311,8 @@ struct show_var_st innodb_status_variabl
(char*) &export_vars.innodb_rows_read, SHOW_LONG},
{"rows_updated",
(char*) &export_vars.innodb_rows_updated, SHOW_LONG},
- {NullS, NullS, SHOW_LONG}};
+ {NullS, NullS, SHOW_LONG}
+};
/* General functions */
@@ -386,7 +377,7 @@ Call this function when mysqld passes co
avoid deadlocks on the adaptive hash S-latch possibly held by thd. For more
documentation, see handler.cc. */
-void
+int
innobase_release_temporary_latches(
/*===============================*/
THD *thd)
@@ -395,14 +386,15 @@ innobase_release_temporary_latches(
if (!innodb_inited) {
- return;
+ return 0;
}
- trx = (trx_t*) thd->ha_data[innobase_hton.slot];
+ trx = (trx_t*) thd->ha_data[innobase_hton->slot];
if (trx) {
innobase_release_stat_resources(trx);
}
+ return 0;
}
/************************************************************************
@@ -442,6 +434,10 @@ convert_error_code_to_mysql(
return(HA_ERR_FOUND_DUPP_KEY);
+ } else if (error == (int) DB_FOREIGN_DUPLICATE_KEY) {
+
+ return(HA_ERR_FOREIGN_DUPLICATE_KEY);
+
} else if (error == (int) DB_RECORD_NOT_FOUND) {
return(HA_ERR_NO_ACTIVE_RECORD);
@@ -613,8 +609,7 @@ innobase_mysql_print_thd(
/* Points to buf or dyn_str. */
char* str = buf;
- if (max_query_len == 0)
- {
+ if (max_query_len == 0) {
/* ADDITIONAL SAFETY: the default is to print at
most 300 chars to reduce the probability of a
seg fault if there is a race in
@@ -626,8 +621,7 @@ innobase_mysql_print_thd(
len = min(thd->query_length, max_query_len);
- if (len > (sizeof(buf) - 1))
- {
+ if (len > (sizeof(buf) - 1)) {
dyn_str = my_malloc(len + 1, MYF(0));
str = dyn_str;
}
@@ -638,8 +632,7 @@ innobase_mysql_print_thd(
putc('\n', f);
fwrite(str, 1, len, f);
- if (dyn_str)
- {
+ if (dyn_str) {
my_free(dyn_str, MYF(0));
}
}
@@ -676,6 +669,61 @@ innobase_get_cset_width(
}
/**********************************************************************
+Converts an identifier to a table name.
+
+NOTE that the exact prototype of this function has to be in
+/innobase/dict/dict0dict.c! */
+extern "C"
+void
+innobase_convert_from_table_id(
+/*===========================*/
+ char* to, /* out: converted identifier */
+ const char* from, /* in: identifier to convert */
+ ulint len) /* in: length of 'to', in bytes */
+{
+ uint errors;
+
+ strconvert(current_thd->charset(), from,
+ &my_charset_filename, to, len, &errors);
+}
+
+/**********************************************************************
+Converts an identifier to UTF-8.
+
+NOTE that the exact prototype of this function has to be in
+/innobase/dict/dict0dict.c! */
+extern "C"
+void
+innobase_convert_from_id(
+/*=====================*/
+ char* to, /* out: converted identifier */
+ const char* from, /* in: identifier to convert */
+ ulint len) /* in: length of 'to', in bytes */
+{
+ uint errors;
+
+ strconvert(current_thd->charset(), from,
+ system_charset_info, to, len, &errors);
+}
+
+/**********************************************************************
+Removes the filename encoding of a table or database name.
+
+NOTE that the exact prototype of this function has to be in
+/innobase/dict/dict0dict.c! */
+extern "C"
+void
+innobase_convert_from_filename(
+/*===========================*/
+ char* s) /* in: identifier; out: decoded identifier */
+{
+ uint errors;
+
+ strconvert(&my_charset_filename, s,
+ system_charset_info, s, strlen(s), &errors);
+}
+
+/**********************************************************************
Compares NUL-terminated UTF-8 strings case insensitively.
NOTE that the exact prototype of this function has to be in
@@ -705,6 +753,21 @@ innobase_casedn_str(
my_casedn_str(system_charset_info, a);
}
+/**************************************************************************
+Determines the connection character set.
+
+NOTE that the exact prototype of this function has to be in
+/innobase/dict/dict0dict.c! */
+extern "C"
+struct charset_info_st*
+innobase_get_charset(
+/*=================*/
+ /* out: connection character set */
+ void* mysql_thd) /* in: MySQL thread handle */
+{
+ return(((THD*) mysql_thd)->charset());
+}
+
/*************************************************************************
Creates a temporary file. */
extern "C"
@@ -751,6 +814,25 @@ innobase_mysql_tmpfile(void)
}
/*************************************************************************
+Wrapper around MySQL's copy_and_convert function, see it for
+documentation. */
+extern "C"
+ulint
+innobase_convert_string(
+/*====================*/
+ void* to,
+ ulint to_length,
+ CHARSET_INFO* to_cs,
+ const void* from,
+ ulint from_length,
+ CHARSET_INFO* from_cs,
+ uint* errors)
+{
+ return(copy_and_convert((char*)to, to_length, to_cs,
+ (const char*)from, from_length, from_cs, errors));
+}
+
+/*************************************************************************
Gets the InnoDB transaction handle for a MySQL handler object, creates
an InnoDB transaction struct if the corresponding MySQL thread struct still
lacks one. */
@@ -765,7 +847,7 @@ check_trx_exists(
ut_ad(thd == current_thd);
- trx = (trx_t*) thd->ha_data[innobase_hton.slot];
+ trx = (trx_t*) thd->ha_data[innobase_hton->slot];
if (trx == NULL) {
DBUG_ASSERT(thd != NULL);
@@ -779,10 +861,10 @@ check_trx_exists(
CPU time */
trx->support_xa = (ibool)(thd->variables.innodb_support_xa);
- thd->ha_data[innobase_hton.slot] = trx;
+ thd->ha_data[innobase_hton->slot] = trx;
} else {
if (trx->magic_n != TRX_MAGIC_N) {
- mem_analyze_corruption((byte*)trx);
+ mem_analyze_corruption(trx);
ut_a(0);
}
@@ -807,15 +889,15 @@ check_trx_exists(
/*************************************************************************
Construct ha_innobase handler. */
-ha_innobase::ha_innobase(TABLE *table_arg)
- :handler(&innobase_hton, table_arg),
+ha_innobase::ha_innobase(TABLE_SHARE *table_arg)
+ :handler(innobase_hton, table_arg),
int_table_flags(HA_REC_NOT_IN_SEQ |
HA_NULL_IN_KEY |
HA_CAN_INDEX_BLOBS |
HA_CAN_SQL_HANDLER |
- HA_NOT_EXACT_COUNT |
+ HA_PRIMARY_KEY_REQUIRED_FOR_POSITION |
HA_PRIMARY_KEY_IN_READ_INDEX |
- HA_CAN_GEOMETRY |
+ HA_CAN_GEOMETRY | HA_PARTIAL_COLUMN_READ |
HA_TABLE_SCAN_ON_INDEX),
start_of_scan(0),
num_write_row(0)
@@ -859,7 +941,7 @@ innobase_register_stmt(
THD* thd) /* in: MySQL thd (connection) object */
{
/* Register the statement */
- trans_register_ha(thd, FALSE, &innobase_hton);
+ trans_register_ha(thd, FALSE, innobase_hton);
}
/*************************************************************************
@@ -883,7 +965,7 @@ innobase_register_trx_and_stmt(
if (thd->options & (OPTION_NOT_AUTOCOMMIT | OPTION_BEGIN)) {
/* No autocommit mode, register for a transaction */
- trans_register_ha(thd, TRUE, &innobase_hton);
+ trans_register_ha(thd, TRUE, innobase_hton);
}
}
@@ -1084,23 +1166,70 @@ innobase_invalidate_query_cache(
}
/*********************************************************************
-Get the quote character to be used in SQL identifiers.
+Display an SQL identifier.
This definition must match the one in innobase/ut/ut0ut.c! */
extern "C"
-int
-mysql_get_identifier_quote_char(
-/*============================*/
- /* out: quote character to be
- used in SQL identifiers; EOF if none */
+void
+innobase_print_identifier(
+/*======================*/
+ FILE* f, /* in: output stream */
trx_t* trx, /* in: transaction */
+ ibool table_id,/* in: TRUE=print a table name,
+ FALSE=print other identifier */
const char* name, /* in: name to print */
ulint namelen)/* in: length of name */
{
+ const char* s = name;
+ char* qname = NULL;
+ int q;
+
+ if (table_id) {
+ /* Decode the table name. The filename_to_tablename()
+ function expects a NUL-terminated string. The input and
+ output strings buffers must not be shared. The function
+ only produces more output when the name contains other
+ characters than [0-9A-Z_a-z]. */
+ char* temp_name = my_malloc(namelen + 1, MYF(MY_WME));
+ uint qnamelen = namelen
+ + (1 + sizeof srv_mysql50_table_name_prefix);
+
+ if (temp_name) {
+ qname = my_malloc(qnamelen, MYF(MY_WME));
+ if (qname) {
+ memcpy(temp_name, name, namelen);
+ temp_name[namelen] = 0;
+ s = qname;
+ namelen = filename_to_tablename(temp_name,
+ qname, qnamelen);
+ }
+ my_free(temp_name, MYF(0));
+ }
+ }
+
if (!trx || !trx->mysql_thd) {
- return(EOF);
+
+ q = '"';
+ } else {
+ q = get_quote_char_for_identifier((THD*) trx->mysql_thd,
+ s, (int) namelen);
}
- return(get_quote_char_for_identifier((THD*) trx->mysql_thd,
- name, (int) namelen));
+
+ if (q == EOF) {
+ fwrite(s, 1, namelen, f);
+ } else {
+ const char* e = s + namelen;
+ putc(q, f);
+ while (s < e) {
+ int c = *s++;
+ if (c == q) {
+ putc(c, f);
+ }
+ putc(c, f);
+ }
+ putc(q, f);
+ }
+
+ my_free(qname, MYF(MY_ALLOW_ZERO_PTR));
}
/**************************************************************************
@@ -1199,10 +1328,9 @@ ha_innobase::init_table_handle_for_HANDL
/*************************************************************************
Opens an InnoDB database. */
-bool
-innobase_init(void)
+int
+innobase_init(void *p)
/*===============*/
- /* out: &innobase_hton, or NULL on error */
{
static char current_dir[3]; /* Set if using current lib */
int err;
@@ -1210,12 +1338,56 @@ innobase_init(void)
char *default_path;
DBUG_ENTER("innobase_init");
+ innobase_hton= (handlerton *)p;
+
+ innobase_hton->state=have_innodb;
+ innobase_hton->db_type= DB_TYPE_INNODB;
+ innobase_hton->savepoint_offset=sizeof(trx_named_savept_t);
+ innobase_hton->close_connection=innobase_close_connection;
+ innobase_hton->savepoint_set=innobase_savepoint;
+ innobase_hton->savepoint_rollback=innobase_rollback_to_savepoint;
+ innobase_hton->savepoint_release=innobase_release_savepoint;
+ innobase_hton->commit=innobase_commit;
+ innobase_hton->rollback=innobase_rollback;
+ innobase_hton->prepare=innobase_xa_prepare;
+ innobase_hton->recover=innobase_xa_recover;
+ innobase_hton->commit_by_xid=innobase_commit_by_xid;
+ innobase_hton->rollback_by_xid=innobase_rollback_by_xid;
+ innobase_hton->create_cursor_read_view=innobase_create_cursor_view;
+ innobase_hton->set_cursor_read_view=innobase_set_cursor_view;
+ innobase_hton->close_cursor_read_view=innobase_close_cursor_view;
+ innobase_hton->create=innobase_create_handler;
+ innobase_hton->drop_database=innobase_drop_database;
+ innobase_hton->panic=innobase_end;
+
innobase_hton->start_consistent_snapshot=innobase_start_trx_and_assign_read_view;
+ innobase_hton->flush_logs=innobase_flush_logs;
+ innobase_hton->show_status=innobase_show_status;
+ innobase_hton->flags=HTON_NO_FLAGS;
+ innobase_hton->release_temporary_latches=innobase_release_temporary_latches;
if (have_innodb != SHOW_OPTION_YES)
- goto error;
+ DBUG_RETURN(0); // nothing else to do
ut_a(DATA_MYSQL_TRUE_VARCHAR == (ulint)MYSQL_TYPE_VARCHAR);
+#ifdef UNIV_DEBUG
+ static const char test_filename[] = "-@";
+ char test_tablename[sizeof test_filename
+ + sizeof srv_mysql50_table_name_prefix];
+ if ((sizeof test_tablename) - 1
+ != filename_to_tablename(test_filename, test_tablename,
+ sizeof test_tablename)
+ || strncmp(test_tablename,
+ srv_mysql50_table_name_prefix,
+ sizeof srv_mysql50_table_name_prefix)
+ || strcmp(test_tablename
+ + sizeof srv_mysql50_table_name_prefix,
+ test_filename)) {
+ sql_print_error("tablename encoding has been changed");
+ goto error;
+ }
+#endif /* UNIV_DEBUG */
+
/* Check that values don't overflow on 32-bit systems. */
if (sizeof(ulint) == 4) {
if (innobase_buffer_pool_size > UINT_MAX32) {
@@ -1431,21 +1603,6 @@ innobase_init(void)
pthread_cond_init(&commit_cond, NULL);
innodb_inited= 1;
- /* If this is a replication slave and we needed to do a crash recovery,
- set the master binlog position to what InnoDB internally knew about
- how far we got transactions durable inside InnoDB. There is a
- problem here: if the user used also MyISAM tables, InnoDB might not
- know the right position for them.
-
- THIS DOES NOT WORK CURRENTLY because replication seems to initialize
- glob_mi also after innobase_init. */
-
-/* if (trx_sys_mysql_master_log_pos != -1) {
- ut_memcpy(glob_mi.log_file_name, trx_sys_mysql_master_log_name,
- 1 + ut_strlen(trx_sys_mysql_master_log_name));
- glob_mi.pos = trx_sys_mysql_master_log_pos;
- }
-*/
DBUG_RETURN(FALSE);
error:
have_innodb= SHOW_OPTION_DISABLED; // If we couldn't use handler
@@ -1455,8 +1612,8 @@ error:
/***********************************************************************
Closes an InnoDB database. */
-bool
-innobase_end(void)
+int
+innobase_end(ha_panic_function type)
/*==============*/
/* out: TRUE if error */
{
@@ -1520,19 +1677,6 @@ innobase_commit_low(
return;
}
-#ifdef HAVE_REPLICATION
- THD *thd=current_thd;
-
- if (thd && thd->slave_thread) {
- /* Update the replication position info inside InnoDB */
-
- trx->mysql_master_log_file_name
- = active_mi->rli.group_master_log_name;
- trx->mysql_master_log_pos = ((ib_longlong)
- active_mi->rli.future_group_master_log_pos);
- }
-#endif /* HAVE_REPLICATION */
-
trx_commit_for_mysql(trx);
}
@@ -1632,8 +1776,8 @@ innobase_commit(
if (trx->active_trans == 0
&& trx->conc_state != TRX_NOT_STARTED) {
- sql_print_error("trx->active_trans == 0, but trx->conc_state != "
- "TRX_NOT_STARTED");
+ sql_print_error("trx->active_trans == 0, but"
+ " trx->conc_state != TRX_NOT_STARTED");
}
if (all
|| (!(thd->options & (OPTION_NOT_AUTOCOMMIT | OPTION_BEGIN)))) {
@@ -1642,22 +1786,24 @@ innobase_commit(
this is an SQL statement end and autocommit is on */
/* We need current binlog position for ibbackup to work.
- Note, the position is current because of prepare_commit_mutex */
+ Note, the position is current because of
+ prepare_commit_mutex */
retry:
- if (srv_commit_concurrency > 0)
- {
+ if (srv_commit_concurrency > 0) {
pthread_mutex_lock(&commit_cond_m);
commit_threads++;
- if (commit_threads > srv_commit_concurrency)
- {
+
+ if (commit_threads > srv_commit_concurrency) {
commit_threads--;
- pthread_cond_wait(&commit_cond, &commit_cond_m);
+ pthread_cond_wait(&commit_cond,
+ &commit_cond_m);
pthread_mutex_unlock(&commit_cond_m);
goto retry;
}
- else
+ else {
pthread_mutex_unlock(&commit_cond_m);
}
+ }
trx->mysql_log_file_name = mysql_bin_log.get_log_fname();
trx->mysql_log_offset =
@@ -1665,8 +1811,7 @@ retry:
innobase_commit_low(trx);
- if (srv_commit_concurrency > 0)
- {
+ if (srv_commit_concurrency > 0) {
pthread_mutex_lock(&commit_cond_m);
commit_threads--;
pthread_cond_signal(&commit_cond);
@@ -1795,7 +1940,7 @@ innobase_commit_complete(
{
trx_t* trx;
- trx = (trx_t*) thd->ha_data[innobase_hton.slot];
+ trx = (trx_t*) thd->ha_data[innobase_hton->slot];
if (trx && trx->active_trans) {
@@ -2014,27 +2159,30 @@ innobase_close_connection(
{
trx_t* trx;
- trx = (trx_t*)thd->ha_data[innobase_hton.slot];
+ trx = (trx_t*)thd->ha_data[innobase_hton->slot];
ut_a(trx);
if (trx->active_trans == 0
&& trx->conc_state != TRX_NOT_STARTED) {
- sql_print_error("trx->active_trans == 0, but trx->conc_state != "
- "TRX_NOT_STARTED");
+ sql_print_error("trx->active_trans == 0, but"
+ " trx->conc_state != TRX_NOT_STARTED");
}
if (trx->conc_state != TRX_NOT_STARTED &&
- global_system_variables.log_warnings)
- sql_print_warning("MySQL is closing a connection that has an active "
+ global_system_variables.log_warnings) {
+ sql_print_warning(
+ "MySQL is closing a connection that has an active "
"InnoDB transaction. %lu row modifications will "
"roll back.",
(ulong)trx->undo_no.low);
+ }
innobase_rollback_trx(trx);
+ thr_local_free(trx->mysql_thread_id);
trx_free_for_mysql(trx);
return(0);
@@ -2055,7 +2203,7 @@ ha_innobase::get_row_type() const
row_prebuilt_t* prebuilt = (row_prebuilt_t*) innobase_prebuilt;
if (prebuilt && prebuilt->table) {
- if (prebuilt->table->comp) {
+ if (dict_table_is_comp_noninline(prebuilt->table)) {
return(ROW_TYPE_COMPACT);
} else {
return(ROW_TYPE_REDUNDANT);
@@ -2179,8 +2327,8 @@ ha_innobase::open(
/* Get pointer to a table object in InnoDB dictionary cache */
- ib_table = dict_table_get_and_increment_handle_count(
- norm_name, NULL);
+ ib_table = dict_table_get_and_increment_handle_count(norm_name);
+
if (NULL == ib_table) {
ut_print_timestamp(stderr);
sql_print_error("Cannot find table %s from the internal data "
@@ -2190,7 +2338,7 @@ ha_innobase::open(
"have forgotten\nto delete the corresponding "
".frm files of InnoDB tables, or you\n"
"have moved .frm files to another database?\n"
- "See http://dev.mysql.com/doc/refman/5.0/en/innodb-troubleshooting.html\n"
+ "See http://dev.mysql.com/doc/refman/5.1/en/innodb-troubleshooting.html\n"
"how you can resolve the problem.\n",
norm_name);
free_share(share);
@@ -2207,7 +2355,7 @@ ha_innobase::open(
"Have you deleted the .ibd file from the "
"database directory under\nthe MySQL datadir, "
"or have you used DISCARD TABLESPACE?\n"
- "See http://dev.mysql.com/doc/refman/5.0/en/innodb-troubleshooting.html\n"
+ "See http://dev.mysql.com/doc/refman/5.1/en/innodb-troubleshooting.html\n"
"how you can resolve the problem.\n",
norm_name);
free_share(share);
@@ -2276,13 +2424,14 @@ ha_innobase::open(
and it will never be updated anyway. */
if (key_used_on_scan != MAX_KEY) {
- sql_print_warning("Table %s key_used_on_scan is %lu even "
+ sql_print_warning(
+ "Table %s key_used_on_scan is %lu even "
"though there is no primary key inside "
"InnoDB.", name, (ulong) key_used_on_scan);
}
}
- block_size = 16 * 1024; /* Index block size in InnoDB: used by MySQL
+ stats.block_size = 16 * 1024; /* Index block size in InnoDB: used by MySQL
in query optimization */
/* Init table lock structure */
@@ -2516,8 +2665,8 @@ get_innobase_type_from_mysql_type(
}
switch (field->type()) {
- /* NOTE that we only allow string types in DATA_MYSQL
- and DATA_VARMYSQL */
+ /* NOTE that we only allow string types in DATA_MYSQL and
+ DATA_VARMYSQL */
case MYSQL_TYPE_VAR_STRING: /* old <= 4.1 VARCHAR */
case MYSQL_TYPE_VARCHAR: /* new >= 5.0.3 true VARCHAR */
if (field->binary()) {
@@ -2739,7 +2888,6 @@ ha_innobase::store_key_val_for_row(
CHARSET_INFO* cs;
ulint key_len;
- ulint len;
ulint true_len;
int error=0;
ulint blob_len;
@@ -2886,7 +3034,7 @@ build_template(
only if templ_type is
ROW_MYSQL_REC_FIELDS */
TABLE* table, /* in: MySQL table */
- ulint templ_type) /* in: ROW_MYSQL_WHOLE_ROW or
+ uint templ_type) /* in: ROW_MYSQL_WHOLE_ROW or
ROW_MYSQL_REC_FIELDS */
{
dict_index_t* index;
@@ -2913,16 +3061,16 @@ build_template(
if (prebuilt->hint_need_to_fetch_extra_cols
== ROW_RETRIEVE_ALL_COLS) {
- /* We know we must at least fetch all columns in the key, or
- all columns in the table */
+ /* We know we must at least fetch all columns in the
+ key, or all columns in the table */
if (prebuilt->read_just_key) {
- /* MySQL has instructed us that it is enough to
- fetch the columns in the key; looks like MySQL
- can set this flag also when there is only a
- prefix of the column in the key: in that case we
- retrieve the whole column from the clustered
- index */
+ /* MySQL has instructed us that it is enough
+ to fetch the columns in the key; looks like
+ MySQL can set this flag also when there is
+ only a prefix of the column in the key: in
+ that case we retrieve the whole column from
+ the clustered index */
fetch_all_in_key = TRUE;
} else {
@@ -2930,11 +3078,12 @@ build_template(
}
} else if (prebuilt->hint_need_to_fetch_extra_cols
== ROW_RETRIEVE_PRIMARY_KEY) {
- /* We must at least fetch all primary key cols. Note that if
- the clustered index was internally generated by InnoDB on the
- row id (no primary key was defined), then
- row_search_for_mysql() will always retrieve the row id to a
- special buffer in the prebuilt struct. */
+ /* We must at least fetch all primary key cols. Note
+ that if the clustered index was internally generated
+ by InnoDB on the row id (no primary key was
+ defined), then row_search_for_mysql() will always
+ retrieve the row id to a special buffer in the
+ prebuilt struct. */
fetch_primary_key_cols = TRUE;
}
@@ -2994,15 +3143,16 @@ build_template(
goto include_field;
}
- if (thd->query_id == field->query_id) {
+ if (bitmap_is_set(table->read_set, i) ||
+ bitmap_is_set(table->write_set, i)) {
/* This field is needed in the query */
goto include_field;
}
if (fetch_primary_key_cols
- && dict_table_col_in_clustered_key(index->table,
- i)) {
+ && dict_table_col_in_clustered_key(
+ index->table, i)) {
/* This field is needed in the query */
goto include_field;
@@ -3018,8 +3168,8 @@ include_field:
templ->col_no = i;
if (index == clust_index) {
- templ->rec_field_no = (index->table->cols + i)
- ->clust_pos;
+ templ->rec_field_no = dict_col_get_clust_pos_noninline(
+ &index->table->cols[i], index);
} else {
templ->rec_field_no = dict_index_get_nth_col_pos(
index, i);
@@ -3048,7 +3198,7 @@ include_field:
mysql_prefix_len = templ->mysql_col_offset
+ templ->mysql_col_len;
}
- templ->type = index->table->cols[i].type.mtype;
+ templ->type = index->table->cols[i].mtype;
templ->mysql_type = (ulint)field->type();
if (templ->mysql_type == DATA_MYSQL_TRUE_VARCHAR) {
@@ -3057,10 +3207,10 @@ include_field:
}
templ->charset = dtype_get_charset_coll_noninline(
- index->table->cols[i].type.prtype);
- templ->mbminlen = index->table->cols[i].type.mbminlen;
- templ->mbmaxlen = index->table->cols[i].type.mbmaxlen;
- templ->is_unsigned = index->table->cols[i].type.prtype
+ index->table->cols[i].prtype);
+ templ->mbminlen = index->table->cols[i].mbminlen;
+ templ->mbmaxlen = index->table->cols[i].mbmaxlen;
+ templ->is_unsigned = index->table->cols[i].prtype
& DATA_UNSIGNED;
if (templ->type == DATA_BLOB) {
prebuilt->templ_contains_blob = TRUE;
@@ -3078,8 +3228,9 @@ skip_field:
for (i = 0; i < n_requested_fields; i++) {
templ = prebuilt->mysql_template + i;
- templ->rec_field_no =
- (index->table->cols + templ->col_no)->clust_pos;
+ templ->rec_field_no = dict_col_get_clust_pos_noninline(
+ &index->table->cols[templ->col_no],
+ clust_index);
}
}
}
@@ -3103,11 +3254,11 @@ ha_innobase::write_row(
DBUG_ENTER("ha_innobase::write_row");
if (prebuilt->trx !=
- (trx_t*) current_thd->ha_data[innobase_hton.slot]) {
+ (trx_t*) current_thd->ha_data[innobase_hton->slot]) {
sql_print_error("The transaction object for the table handle is at "
"%p, but for the current thread it is at %p",
prebuilt->trx,
- (trx_t*) current_thd->ha_data[innobase_hton.slot]);
+ (trx_t*) current_thd->ha_data[innobase_hton->slot]);
fputs("InnoDB: Dump of 200 bytes around prebuilt: ", stderr);
ut_print_buf(stderr, ((const byte*)prebuilt) - 100, 200);
@@ -3115,7 +3266,7 @@ ha_innobase::write_row(
"InnoDB: Dump of 200 bytes around transaction.all: ",
stderr);
ut_print_buf(stderr,
- ((byte*)(&(current_thd->ha_data[innobase_hton.slot]))) - 100,
+ ((byte*)(&(current_thd->ha_data[innobase_hton->slot]))) - 100,
200);
putc('\n', stderr);
ut_error;
@@ -3346,9 +3497,11 @@ calc_row_difference(
ulint col_type;
ulint n_changed = 0;
dfield_t dfield;
+ dict_index_t* clust_index;
uint i;
n_fields = table->s->fields;
+ clust_index = dict_table_get_first_index_noninline(prebuilt->table);
/* We use upd_buff to convert changed fields */
buf = (byte*) upd_buff;
@@ -3379,7 +3532,7 @@ calc_row_difference(
field_mysql_type = field->type();
- col_type = prebuilt->table->cols[i].type.mtype;
+ col_type = prebuilt->table->cols[i].mtype;
switch (col_type) {
@@ -3434,7 +3587,8 @@ calc_row_difference(
/* Let us use a dummy dfield to make the conversion
from the MySQL column format to the InnoDB format */
- dfield.type = (prebuilt->table->cols + i)->type;
+ dict_col_copy_type_noninline(prebuilt->table->cols + i,
+ &dfield.type);
if (n_len != UNIV_SQL_NULL) {
buf = row_mysql_store_col_in_innobase_format(
@@ -3443,7 +3597,8 @@ calc_row_difference(
TRUE,
new_mysql_row_col,
col_pack_len,
- prebuilt->table->comp);
+ dict_table_is_comp_noninline(
+ prebuilt->table));
ufield->new_val.data = dfield.data;
ufield->new_val.len = dfield.len;
} else {
@@ -3452,7 +3607,8 @@ calc_row_difference(
}
ufield->exp = NULL;
- ufield->field_no = prebuilt->table->cols[i].clust_pos;
+ ufield->field_no = dict_col_get_clust_pos_noninline(
+ &prebuilt->table->cols[i], clust_index);
n_changed++;
}
}
@@ -3486,8 +3642,8 @@ ha_innobase::update_row(
DBUG_ENTER("ha_innobase::update_row");
- ut_ad(prebuilt->trx ==
- (trx_t*) current_thd->ha_data[innobase_hton.slot]);
+ ut_a(prebuilt->trx ==
+ (trx_t*) current_thd->ha_data[innobase_hton->slot]);
if (table->timestamp_field_type & TIMESTAMP_AUTO_SET_ON_UPDATE)
table->timestamp_field->set_time();
@@ -3547,8 +3703,8 @@ ha_innobase::delete_row(
DBUG_ENTER("ha_innobase::delete_row");
- ut_ad(prebuilt->trx ==
- (trx_t*) current_thd->ha_data[innobase_hton.slot]);
+ ut_a(prebuilt->trx ==
+ (trx_t*) current_thd->ha_data[innobase_hton->slot]);
if (last_query_id != user_thd->query_id) {
prebuilt->sql_stat_start = TRUE;
@@ -3582,8 +3738,9 @@ ha_innobase::delete_row(
}
/**************************************************************************
-Removes a new lock set on a row. This method does nothing unless the
-option innodb_locks_unsafe_for_binlog is set.*/
+Removes a new lock set on a row, if it was not read optimistically. This can
+be called after a row has been read in the processing of an UPDATE or a DELETE
+query, if the option innodb_locks_unsafe_for_binlog is set. */
void
ha_innobase::unlock_row(void)
@@ -3593,7 +3750,7 @@ ha_innobase::unlock_row(void)
DBUG_ENTER("ha_innobase::unlock_row");
- if (last_query_id != user_thd->query_id) {
+ if (UNIV_UNLIKELY(last_query_id != user_thd->query_id)) {
ut_print_timestamp(stderr);
sql_print_error("last_query_id is %lu != user_thd_query_id is "
"%lu", (ulong) last_query_id,
@@ -3609,12 +3766,55 @@ ha_innobase::unlock_row(void)
DBUG_VOID_RETURN;
}
- if (srv_locks_unsafe_for_binlog) {
+ switch (prebuilt->row_read_type) {
+ case ROW_READ_WITH_LOCKS:
+ if (!srv_locks_unsafe_for_binlog
+ || prebuilt->trx->isolation_level == TRX_ISO_READ_COMMITTED) {
+ break;
+ }
+ /* fall through */
+ case ROW_READ_TRY_SEMI_CONSISTENT:
row_unlock_for_mysql(prebuilt, FALSE);
+ break;
+ case ROW_READ_DID_SEMI_CONSISTENT:
+ prebuilt->row_read_type = ROW_READ_TRY_SEMI_CONSISTENT;
+ break;
}
DBUG_VOID_RETURN;
+}
+
+/* See handler.h and row0mysql.h for docs on this function. */
+bool
+ha_innobase::was_semi_consistent_read(void)
+/*=======================================*/
+{
+ row_prebuilt_t* prebuilt = (row_prebuilt_t*) innobase_prebuilt;
+ return(prebuilt->row_read_type == ROW_READ_DID_SEMI_CONSISTENT);
+}
+
+/* See handler.h and row0mysql.h for docs on this function. */
+void
+ha_innobase::try_semi_consistent_read(bool yes)
+/*===========================================*/
+{
+ row_prebuilt_t* prebuilt = (row_prebuilt_t*) innobase_prebuilt;
+
+ ut_a(prebuilt->trx ==
+ (trx_t*) current_thd->ha_data[innobase_hton->slot]);
+
+ /* Row read type is set to semi consistent read if this was
+ requested by the MySQL and either innodb_locks_unsafe_for_binlog
+ option is used or this session is using READ COMMITTED isolation
+ level. */
+
+ if (yes && (srv_locks_unsafe_for_binlog
+ || prebuilt->trx->isolation_level == TRX_ISO_READ_COMMITTED)) {
+ prebuilt->row_read_type = ROW_READ_TRY_SEMI_CONSISTENT;
+ } else {
+ prebuilt->row_read_type = ROW_READ_WITH_LOCKS;
+ }
}
/**********************************************************************
@@ -3624,7 +3824,8 @@ int
ha_innobase::index_init(
/*====================*/
/* out: 0 or error number */
- uint keynr) /* in: key (index) number */
+ uint keynr, /* in: key (index) number */
+ bool sorted) /* in: 1 if result MUST be sorted according to index */
{
int error = 0;
DBUG_ENTER("index_init");
@@ -3767,8 +3968,8 @@ ha_innobase::index_read(
DBUG_ENTER("index_read");
- ut_ad(prebuilt->trx ==
- (trx_t*) current_thd->ha_data[innobase_hton.slot]);
+ ut_a(prebuilt->trx ==
+ (trx_t*) current_thd->ha_data[innobase_hton->slot]);
statistic_increment(current_thd->status_var.ha_read_key_count,
&LOCK_status);
@@ -3882,8 +4083,8 @@ ha_innobase::change_active_index(
DBUG_ENTER("change_active_index");
ut_ad(user_thd == current_thd);
- ut_ad(prebuilt->trx ==
- (trx_t*) current_thd->ha_data[innobase_hton.slot]);
+ ut_a(prebuilt->trx ==
+ (trx_t*) current_thd->ha_data[innobase_hton->slot]);
active_index = keynr;
@@ -3891,18 +4092,19 @@ ha_innobase::change_active_index(
key = table->key_info + active_index;
prebuilt->index = dict_table_get_index_noninline(
- prebuilt->table,
- key->name);
+ prebuilt->table, key->name);
} else {
prebuilt->index = dict_table_get_first_index_noninline(
prebuilt->table);
}
if (!prebuilt->index) {
- sql_print_error("Innodb could not find key n:o %u with name %s "
+ sql_print_error(
+ "Innodb could not find key n:o %u with name %s "
"from dict cache for table %s",
keynr, key ? key->name : "NULL",
prebuilt->table->name);
+
DBUG_RETURN(1);
}
@@ -3971,8 +4173,8 @@ ha_innobase::general_fetch(
DBUG_ENTER("general_fetch");
- ut_ad(prebuilt->trx ==
- (trx_t*) current_thd->ha_data[innobase_hton.slot]);
+ ut_a(prebuilt->trx ==
+ (trx_t*) current_thd->ha_data[innobase_hton->slot]);
innodb_srv_conc_enter_innodb(prebuilt->trx);
@@ -4130,6 +4332,13 @@ ha_innobase::rnd_init(
err = change_active_index(primary_key);
}
+ /* Don't use semi-consistent read in random row reads (by position).
+ This means we must disable semi_consistent_read if scan is false */
+
+ if (!scan) {
+ try_semi_consistent_read(0);
+ }
+
start_of_scan = 1;
return(err);
@@ -4200,8 +4409,8 @@ ha_innobase::rnd_pos(
statistic_increment(current_thd->status_var.ha_read_rnd_count,
&LOCK_status);
- ut_ad(prebuilt->trx ==
- (trx_t*) current_thd->ha_data[innobase_hton.slot]);
+ ut_a(prebuilt->trx ==
+ (trx_t*) current_thd->ha_data[innobase_hton->slot]);
if (prebuilt->clust_index_was_generated) {
/* No primary key was defined for the table and we
@@ -4250,8 +4459,8 @@ ha_innobase::position(
row_prebuilt_t* prebuilt = (row_prebuilt_t*) innobase_prebuilt;
uint len;
- ut_ad(prebuilt->trx ==
- (trx_t*) current_thd->ha_data[innobase_hton.slot]);
+ ut_a(prebuilt->trx ==
+ (trx_t*) current_thd->ha_data[innobase_hton->slot]);
if (prebuilt->clust_index_was_generated) {
/* No primary key was defined for the table and we
@@ -4294,7 +4503,7 @@ create_table_def(
an .ibd file for it (no .ibd extension
in the path, though); otherwise this
is NULL */
- ibool comp) /* in: TRUE=compact record format */
+ ulint flags) /* in: table flags */
{
Field* field;
dict_table_t* table;
@@ -4317,7 +4526,7 @@ create_table_def(
/* We pass 0 as the space id, and determine at a lower level the space
id where to store the table */
- table = dict_mem_table_create(table_name, 0, n_cols, comp);
+ table = dict_mem_table_create(table_name, 0, n_cols, flags);
if (path_of_temp_table) {
table->dir_path_of_temp_table =
@@ -4379,8 +4588,7 @@ create_table_def(
| nulls_allowed | unsigned_type
| binary_type | long_true_varchar,
charset_no),
- col_len,
- 0);
+ col_len);
}
error = row_create_table_for_mysql(table, trx);
@@ -4482,7 +4690,8 @@ create_index(
|| col_type == DATA_FLOAT
|| col_type == DATA_DOUBLE
|| col_type == DATA_DECIMAL) {
- sql_print_error("MySQL is trying to create a column "
+ sql_print_error(
+ "MySQL is trying to create a column "
"prefix index field, on an "
"inappropriate data type. Table "
"name %s, column name %s.",
@@ -4497,12 +4706,8 @@ create_index(
field_lengths[i] = key_part->length;
- /* We assume all fields should be sorted in ascending
- order, hence the '0': */
-
dict_mem_index_add_field(index,
- (char*) key_part->field->field_name,
- 0, prefix_len);
+ (char*) key_part->field->field_name, prefix_len);
}
/* Even though we've defined max_supported_key_part_length, we
@@ -4534,8 +4739,7 @@ create_clustered_index_when_no_primary(
id where to store the table */
index = dict_mem_index_create((char*) table_name,
- (char*) "GEN_CLUST_INDEX",
- 0, DICT_CLUSTERED, 0);
+ (char*) "GEN_CLUST_INDEX", 0, DICT_CLUSTERED, 0);
error = row_create_index_for_mysql(index, trx, NULL);
error = convert_error_code_to_mysql(error, NULL);
@@ -4567,6 +4771,7 @@ ha_innobase::create(
char norm_name[FN_REFLEN];
THD *thd= current_thd;
ib_longlong auto_inc_value;
+ ulint flags;
DBUG_ENTER("ha_innobase::create");
@@ -4582,7 +4787,7 @@ ha_innobase::create(
/* Get the transaction associated with the current thd, or create one
if not yet created */
- parent_trx = check_trx_exists(current_thd);
+ parent_trx = check_trx_exists(thd);
/* In case MySQL calls this in the middle of a SELECT query, release
possible adaptive hash latch to avoid deadlocks of threads */
@@ -4608,7 +4813,7 @@ ha_innobase::create(
srv_lower_case_table_names = FALSE;
}
- fn_format(name2, name, "", "", 2); // Remove the .frm extension
+ strcpy(name2, name);
normalize_table_name(norm_name, name2);
@@ -4620,9 +4825,15 @@ ha_innobase::create(
/* Create the table definition in InnoDB */
+ flags = 0;
+
+ if (form->s->row_type != ROW_TYPE_REDUNDANT) {
+ flags |= DICT_TF_COMPACT;
+ }
+
error = create_table_def(trx, form, norm_name,
create_info->options & HA_LEX_CREATE_TMP_TABLE ? name2 : NULL,
- form->s->row_type != ROW_TYPE_REDUNDANT);
+ flags);
if (error) {
goto cleanup;
@@ -4630,8 +4841,8 @@ ha_innobase::create(
/* Look for a primary key */
- primary_key_no= (table->s->primary_key != MAX_KEY ?
- (int) table->s->primary_key :
+ primary_key_no= (form->s->primary_key != MAX_KEY ?
+ (int) form->s->primary_key :
-1);
/* Our function row_get_mysql_key_number_for_index assumes
@@ -4672,20 +4883,9 @@ ha_innobase::create(
}
}
- if (current_thd->query != NULL) {
- LEX_STRING q;
-
- if (thd->convert_string(&q, system_charset_info,
- current_thd->query,
- current_thd->query_length,
- current_thd->charset())) {
- error = HA_ERR_OUT_OF_MEM;
-
- goto cleanup;
- }
-
+ if (thd->query != NULL) {
error = row_table_add_foreign_constraints(trx,
- q.str, norm_name,
+ thd->query, norm_name,
create_info->options & HA_LEX_CREATE_TMP_TABLE);
error = convert_error_code_to_mysql(error, NULL);
@@ -4705,7 +4905,7 @@ ha_innobase::create(
log_buffer_flush_to_disk();
- innobase_table = dict_table_get(norm_name, NULL);
+ innobase_table = dict_table_get(norm_name);
DBUG_ASSERT(innobase_table != 0);
@@ -4760,7 +4960,7 @@ ha_innobase::discard_or_import_tablespac
ut_a(prebuilt->trx && prebuilt->trx->magic_n == TRX_MAGIC_N);
ut_a(prebuilt->trx ==
- (trx_t*) current_thd->ha_data[innobase_hton.slot]);
+ (trx_t*) current_thd->ha_data[innobase_hton->slot]);
dict_table = prebuilt->table;
trx = prebuilt->trx;
@@ -4786,7 +4986,6 @@ ha_innobase::delete_all_rows(void)
{
row_prebuilt_t* prebuilt = (row_prebuilt_t*)innobase_prebuilt;
int error;
- trx_t* trx;
THD* thd = current_thd;
DBUG_ENTER("ha_innobase::delete_all_rows");
@@ -4799,13 +4998,13 @@ ha_innobase::delete_all_rows(void)
}
/* Get the transaction associated with the current thd, or create one
- if not yet created */
+ if not yet created, and update prebuilt->trx */
- trx = check_trx_exists(thd);
+ update_thd(thd);
/* Truncate the table in InnoDB */
- error = row_truncate_table_for_mysql(prebuilt->table, trx);
+ error = row_truncate_table_for_mysql(prebuilt->table, prebuilt->trx);
if (error == DB_ERROR) {
/* Cannot truncate; resort to ha_innobase::delete_row() */
goto fallback;
@@ -4841,7 +5040,7 @@ ha_innobase::delete_table(
/* Get the transaction associated with the current thd, or create one
if not yet created */
- parent_trx = check_trx_exists(current_thd);
+ parent_trx = check_trx_exists(thd);
/* In case MySQL calls this in the middle of a SELECT query, release
possible adaptive hash latch to avoid deadlocks of threads */
@@ -4904,7 +5103,7 @@ ha_innobase::delete_table(
/*********************************************************************
Removes all tables in the named database inside InnoDB. */
-int
+void
innobase_drop_database(
/*===================*/
/* out: error number */
@@ -4970,10 +5169,13 @@ innobase_drop_database(
innobase_commit_low(trx);
trx_free_for_mysql(trx);
-
+#ifdef NO_LONGER_INTERESTED_IN_DROP_DB_ERROR
error = convert_error_code_to_mysql(error, NULL);
return(error);
+#else
+ return;
+#endif
}
/*************************************************************************
@@ -5085,6 +5287,9 @@ ha_innobase::records_in_range(
DBUG_ENTER("records_in_range");
+ ut_a(prebuilt->trx ==
+ (trx_t*) current_thd->ha_data[innobase_hton->slot]);
+
prebuilt->trx->op_info = (char*)"estimating records in index range";
/* In case MySQL calls this in the middle of a SELECT query, release
@@ -5312,13 +5517,11 @@ ha_innobase::info(
if (ib_table->space != 0) {
my_snprintf(path, sizeof(path), "%s/%s%s",
- mysql_data_home, ib_table->name,
- ".ibd");
+ mysql_data_home, ib_table->name, ".ibd");
unpack_filename(path,path);
} else {
my_snprintf(path, sizeof(path), "%s/%s%s",
- mysql_data_home, ib_table->name,
- reg_ext);
+ mysql_data_home, ib_table->name, reg_ext);
unpack_filename(path,path);
}
@@ -5327,7 +5530,7 @@ ha_innobase::info(
nor the CHECK TABLE time, nor the UPDATE or INSERT time. */
if (os_file_get_status(path,&stat_info)) {
- create_time = stat_info.ctime;
+ stats.create_time = stat_info.ctime;
}
}
@@ -5355,21 +5558,21 @@ ha_innobase::info(
n_rows++;
}
- records = (ha_rows)n_rows;
- deleted = 0;
- data_file_length = ((ulonglong)
+ stats.records = (ha_rows)n_rows;
+ stats.deleted = 0;
+ stats.data_file_length = ((ulonglong)
ib_table->stat_clustered_index_size)
* UNIV_PAGE_SIZE;
- index_file_length = ((ulonglong)
+ stats.index_file_length = ((ulonglong)
ib_table->stat_sum_of_other_index_sizes)
* UNIV_PAGE_SIZE;
- delete_length = 0;
- check_time = 0;
+ stats.delete_length = 0;
+ stats.check_time = 0;
- if (records == 0) {
- mean_rec_length = 0;
+ if (stats.records == 0) {
+ stats.mean_rec_length = 0;
} else {
- mean_rec_length = (ulong) (data_file_length / records);
+ stats.mean_rec_length = (ulong) (stats.data_file_length / stats.records);
}
}
@@ -5389,7 +5592,7 @@ ha_innobase::info(
".frm file. Have you mixed up "
".frm files from different "
"installations? See "
-"http://dev.mysql.com/doc/refman/5.0/en/innodb-troubleshooting.html\n",
+"http://dev.mysql.com/doc/refman/5.1/en/innodb-troubleshooting.html\n",
ib_table->name);
break;
@@ -5403,7 +5606,7 @@ ha_innobase::info(
"Index %s of %s has %lu columns unique inside InnoDB, but MySQL is asking "
"statistics for %lu columns. Have you mixed up .frm files from different "
"installations? "
-"See http://dev.mysql.com/doc/refman/5.0/en/innodb-troubleshooting.html\n",
+"See http://dev.mysql.com/doc/refman/5.1/en/innodb-troubleshooting.html\n",
index->name,
ib_table->name,
(unsigned long)
@@ -5413,9 +5616,9 @@ ha_innobase::info(
if (index->stat_n_diff_key_vals[j + 1] == 0) {
- rec_per_key = records;
+ rec_per_key = stats.records;
} else {
- rec_per_key = (ha_rows)(records /
+ rec_per_key = (ha_rows)(stats.records /
index->stat_n_diff_key_vals[j + 1]);
}
@@ -5443,8 +5646,7 @@ ha_innobase::info(
ut_a(prebuilt->trx && prebuilt->trx->magic_n == TRX_MAGIC_N);
errkey = (unsigned int) row_get_mysql_key_number_for_index(
- (dict_index_t*)
- trx_get_error_info(prebuilt->trx));
+ (dict_index_t*) trx_get_error_info(prebuilt->trx));
}
if (flag & HA_STATUS_AUTO && table->found_next_number_field) {
@@ -5471,7 +5673,7 @@ ha_innobase::info(
}
}
- auto_increment_value = auto_inc;
+ stats.auto_increment_value = auto_inc;
}
prebuilt->trx->op_info = (char*)"";
@@ -5497,7 +5699,7 @@ ha_innobase::analyze(
}
/**************************************************************************
-This is mapped to "ALTER TABLE tablename TYPE=InnoDB", which rebuilds
+This is mapped to "ALTER TABLE tablename ENGINE=InnoDB", which rebuilds
the table in MySQL. */
int
@@ -5528,7 +5730,7 @@ ha_innobase::check(
ut_a(prebuilt->trx && prebuilt->trx->magic_n == TRX_MAGIC_N);
ut_a(prebuilt->trx ==
- (trx_t*) current_thd->ha_data[innobase_hton.slot]);
+ (trx_t*) current_thd->ha_data[innobase_hton->slot]);
if (prebuilt->mysql_template == NULL) {
/* Build the template; we will use a dummy template
@@ -5699,8 +5901,7 @@ ha_innobase::get_foreign_key_list(THD *t
mutex_enter_noninline(&(dict_sys->mutex));
foreign = UT_LIST_GET_FIRST(prebuilt->table->foreign_list);
- while (foreign != NULL)
- {
+ while (foreign != NULL) {
uint i;
FOREIGN_KEY_INFO f_key_info;
LEX_STRING *name= 0;
@@ -5723,53 +5924,69 @@ ha_innobase::get_foreign_key_list(THD *t
f_key_info.referenced_table= make_lex_string(thd, 0, tmp_buff,
(uint) strlen(tmp_buff), 1);
- for (i= 0;;)
- {
+ for (i= 0;;) {
tmp_buff= foreign->foreign_col_names[i];
- name= make_lex_string(thd, name, tmp_buff, (uint) strlen(tmp_buff), 1);
+ name= make_lex_string(thd, name, tmp_buff,
+ (uint) strlen(tmp_buff), 1);
f_key_info.foreign_fields.push_back(name);
tmp_buff= foreign->referenced_col_names[i];
- name= make_lex_string(thd, name, tmp_buff, (uint) strlen(tmp_buff), 1);
+ name= make_lex_string(thd, name, tmp_buff,
+ (uint) strlen(tmp_buff), 1);
f_key_info.referenced_fields.push_back(name);
if (++i >= foreign->n_fields)
break;
}
- ulong length= 0;
- if (foreign->type == DICT_FOREIGN_ON_DELETE_CASCADE)
+ ulong length;
+ if (foreign->type & DICT_FOREIGN_ON_DELETE_CASCADE)
+ {
+ length=7;
+ tmp_buff= "CASCADE";
+ }
+ else if (foreign->type & DICT_FOREIGN_ON_DELETE_SET_NULL)
+ {
+ length=8;
+ tmp_buff= "SET NULL";
+ }
+ else if (foreign->type & DICT_FOREIGN_ON_DELETE_NO_ACTION)
{
- length=17;
- tmp_buff= "ON DELETE CASCADE";
+ length=9;
+ tmp_buff= "NO ACTION";
}
- else if (foreign->type == DICT_FOREIGN_ON_DELETE_SET_NULL)
+ else
{
- length=18;
- tmp_buff= "ON DELETE SET NULL";
+ length=8;
+ tmp_buff= "RESTRICT";
}
- else if (foreign->type == DICT_FOREIGN_ON_DELETE_NO_ACTION)
+ f_key_info.delete_method= make_lex_string(thd, f_key_info.delete_method,
+ tmp_buff, length, 1);
+
+
+ if (foreign->type & DICT_FOREIGN_ON_UPDATE_CASCADE)
{
- length=19;
- tmp_buff= "ON DELETE NO ACTION";
+ length=7;
+ tmp_buff= "CASCADE";
}
- else if (foreign->type == DICT_FOREIGN_ON_UPDATE_CASCADE)
+ else if (foreign->type & DICT_FOREIGN_ON_UPDATE_SET_NULL)
{
- length=17;
- tmp_buff= "ON UPDATE CASCADE";
+ length=8;
+ tmp_buff= "SET NULL";
}
- else if (foreign->type == DICT_FOREIGN_ON_UPDATE_SET_NULL)
+ else if (foreign->type & DICT_FOREIGN_ON_UPDATE_NO_ACTION)
{
- length=18;
- tmp_buff= "ON UPDATE SET NULL";
+ length=9;
+ tmp_buff= "NO ACTION";
}
- else if (foreign->type == DICT_FOREIGN_ON_UPDATE_NO_ACTION)
+ else
{
- length=19;
- tmp_buff= "ON UPDATE NO ACTION";
+ length=8;
+ tmp_buff= "RESTRICT";
}
- f_key_info.constraint_method= make_lex_string(thd,
- f_key_info.constraint_method,
+ f_key_info.update_method= make_lex_string(thd, f_key_info.update_method,
tmp_buff, length, 1);
+
+
FOREIGN_KEY_INFO *pf_key_info= ((FOREIGN_KEY_INFO *)
thd->memdup((gptr) &f_key_info,
sizeof(FOREIGN_KEY_INFO)));
@@ -5778,6 +5995,7 @@ ha_innobase::get_foreign_key_list(THD *t
}
mutex_exit_noninline(&(dict_sys->mutex));
prebuilt->trx->op_info = (char*)"";
+
DBUG_RETURN(0);
}
@@ -5794,6 +6012,10 @@ ha_innobase::can_switch_engines(void)
bool can_switch;
DBUG_ENTER("ha_innobase::can_switch_engines");
+
+ ut_a(prebuilt->trx ==
+ (trx_t*) current_thd->ha_data[innobase_hton->slot]);
+
prebuilt->trx->op_info =
"determining if there are foreign key constraints";
row_mysql_lock_data_dictionary(prebuilt->trx);
@@ -5850,8 +6072,7 @@ ha_innobase::extra(
/*===============*/
/* out: 0 or error number */
enum ha_extra_function operation)
- /* in: HA_EXTRA_RETRIEVE_ALL_COLS or some
- other flag */
+ /* in: HA_EXTRA_FLUSH or some other flag */
{
row_prebuilt_t* prebuilt = (row_prebuilt_t*) innobase_prebuilt;
@@ -5865,13 +6086,6 @@ ha_innobase::extra(
row_mysql_prebuilt_free_blob_heap(prebuilt);
}
break;
- case HA_EXTRA_RESET:
- if (prebuilt->blob_heap) {
- row_mysql_prebuilt_free_blob_heap(prebuilt);
- }
- prebuilt->keep_other_fields_on_keyread = 0;
- prebuilt->read_just_key = 0;
- break;
case HA_EXTRA_RESET_STATE:
prebuilt->keep_other_fields_on_keyread = 0;
prebuilt->read_just_key = 0;
@@ -5879,16 +6093,6 @@ ha_innobase::extra(
case HA_EXTRA_NO_KEYREAD:
prebuilt->read_just_key = 0;
break;
- case HA_EXTRA_RETRIEVE_ALL_COLS:
- prebuilt->hint_need_to_fetch_extra_cols
- = ROW_RETRIEVE_ALL_COLS;
- break;
- case HA_EXTRA_RETRIEVE_PRIMARY_KEY:
- if (prebuilt->hint_need_to_fetch_extra_cols == 0) {
- prebuilt->hint_need_to_fetch_extra_cols
- = ROW_RETRIEVE_PRIMARY_KEY;
- }
- break;
case HA_EXTRA_KEYREAD:
prebuilt->read_just_key = 1;
break;
@@ -5902,6 +6106,18 @@ ha_innobase::extra(
return(0);
}
+int ha_innobase::reset()
+{
+ row_prebuilt_t* prebuilt = (row_prebuilt_t*) innobase_prebuilt;
+ if (prebuilt->blob_heap) {
+ row_mysql_prebuilt_free_blob_heap(prebuilt);
+ }
+ prebuilt->keep_other_fields_on_keyread = 0;
+ prebuilt->read_just_key = 0;
+ return 0;
+}
+
+
/**********************************************************************
MySQL calls this function at the start of each SQL statement inside LOCK
TABLES. Inside LOCK TABLES the ::external_lock method does not work to
@@ -5965,7 +6181,7 @@ ha_innobase::start_stmt(
1) ::store_lock(),
2) ::external_lock(),
3) ::init_table_handle_for_HANDLER(), and
- 4) :.transactional_table_lock(). */
+ 4) ::transactional_table_lock(). */
prebuilt->select_lock_type =
prebuilt->stored_select_lock_type;
@@ -6062,12 +6278,6 @@ ha_innobase::external_lock(
trx->n_mysql_tables_in_use++;
prebuilt->mysql_has_locked = TRUE;
- if (trx->n_mysql_tables_in_use == 1) {
- trx->isolation_level = innobase_map_isolation_level(
- (enum_tx_isolation)
- thd->variables.tx_isolation);
- }
-
if (trx->isolation_level == TRX_ISO_SERIALIZABLE
&& prebuilt->select_lock_type == LOCK_NONE
&& (thd->options
@@ -6103,9 +6313,8 @@ ha_innobase::external_lock(
thd->variables.innodb_table_locks &&
(thd->options & OPTION_NOT_AUTOCOMMIT)) {
- ulint error;
- error = row_lock_table_for_mysql(prebuilt,
- NULL, 0);
+ ulint error = row_lock_table_for_mysql(
+ prebuilt, NULL, 0);
if (error != DB_SUCCESS) {
error = convert_error_code_to_mysql(
@@ -6188,7 +6397,7 @@ ha_innobase::transactional_table_lock(
"table %s does not exist.\n"
"Have you deleted the .ibd file from the database directory under\n"
"the MySQL datadir?"
-"See http://dev.mysql.com/doc/refman/5.0/en/innodb-troubleshooting.html\n"
+"See http://dev.mysql.com/doc/refman/5.1/en/innodb-troubleshooting.html\n"
"how you can resolve the problem.\n",
prebuilt->table->name);
DBUG_RETURN(HA_ERR_CRASHED);
@@ -6252,13 +6461,17 @@ ha_innobase::transactional_table_lock(
/****************************************************************************
Here we export InnoDB status variables to MySQL. */
-void
-innodb_export_status(void)
-/*======================*/
+int
+innodb_export_status()
+/*==================*/
{
+ if (innodb_inited) {
srv_export_innodb_status();
}
+ return 0;
+}
+
/****************************************************************************
Implements the SHOW INNODB STATUS command. Sends the output of the InnoDB
Monitor to the client. */
@@ -6266,9 +6479,9 @@ Monitor to the client. */
bool
innodb_show_status(
/*===============*/
- THD* thd) /* in: the MySQL query thread of the caller */
+ THD* thd, /* in: the MySQL query thread of the caller */
+ stat_print_fn *stat_print)
{
- Protocol* protocol = thd->protocol;
trx_t* trx;
static const char truncated_msg[] = "... truncated...\n";
const long MAX_STATUS_SIZE = 64000;
@@ -6278,10 +6491,7 @@ innodb_show_status(
DBUG_ENTER("innodb_show_status");
if (have_innodb != SHOW_OPTION_YES) {
- my_message(ER_NOT_SUPPORTED_YET,
- "Cannot call SHOW INNODB STATUS because skip-innodb is defined",
- MYF(0));
- DBUG_RETURN(TRUE);
+ DBUG_RETURN(FALSE);
}
trx = check_trx_exists(thd);
@@ -6314,8 +6524,7 @@ innodb_show_status(
/* allocate buffer for the string, and
read the contents of the temporary file */
- if (!(str = my_malloc(usable_len + 1, MYF(0))))
- {
+ if (!(str = my_malloc(usable_len + 1, MYF(0)))) {
mutex_exit_noninline(&srv_monitor_file_mutex);
DBUG_RETURN(TRUE);
}
@@ -6343,27 +6552,14 @@ innodb_show_status(
mutex_exit_noninline(&srv_monitor_file_mutex);
- List<Item> field_list;
-
- field_list.push_back(new Item_empty_string("Status", flen));
-
- if (protocol->send_fields(&field_list, Protocol::SEND_NUM_ROWS |
- Protocol::SEND_EOF)) {
- my_free(str, MYF(0));
+ bool result = FALSE;
- DBUG_RETURN(TRUE);
+ if (stat_print(thd, innobase_hton_name, strlen(innobase_hton_name),
+ STRING_WITH_LEN(""), str, flen)) {
+ result= TRUE;
}
-
- protocol->prepare_for_resend();
- protocol->store(str, flen, system_charset_info);
my_free(str, MYF(0));
- if (protocol->write()) {
-
- DBUG_RETURN(TRUE);
- }
- send_eof(thd);
-
DBUG_RETURN(FALSE);
}
@@ -6372,11 +6568,12 @@ Implements the SHOW MUTEX STATUS command
bool
innodb_mutex_show_status(
-/*===============*/
- THD* thd) /* in: the MySQL query thread of the caller */
+/*=====================*/
+ THD* thd, /* in: the MySQL query thread of the
+ caller */
+ stat_print_fn* stat_print)
{
- Protocol *protocol= thd->protocol;
- List<Item> field_list;
+ char buf1[IO_SIZE], buf2[IO_SIZE];
mutex_t* mutex;
ulint rw_lock_count= 0;
ulint rw_lock_count_spin_loop= 0;
@@ -6384,45 +6581,36 @@ innodb_mutex_show_status(
ulint rw_lock_count_os_wait= 0;
ulint rw_lock_count_os_yield= 0;
ulonglong rw_lock_wait_time= 0;
+ uint hton_name_len= strlen(innobase_hton_name), buf1len, buf2len;
DBUG_ENTER("innodb_mutex_show_status");
- field_list.push_back(new Item_empty_string("Mutex", FN_REFLEN));
- field_list.push_back(new Item_empty_string("Module", FN_REFLEN));
- field_list.push_back(new Item_uint("Count", 21));
- field_list.push_back(new Item_uint("Spin_waits", 21));
- field_list.push_back(new Item_uint("Spin_rounds", 21));
- field_list.push_back(new Item_uint("OS_waits", 21));
- field_list.push_back(new Item_uint("OS_yields", 21));
- field_list.push_back(new Item_uint("OS_waits_time", 21));
-
- if (protocol->send_fields(&field_list,
- Protocol::SEND_NUM_ROWS | Protocol::SEND_EOF))
- DBUG_RETURN(TRUE);
-
#ifdef MUTEX_PROTECT_TO_BE_ADDED_LATER
mutex_enter(&mutex_list_mutex);
#endif
mutex = UT_LIST_GET_FIRST(mutex_list);
- while ( mutex != NULL )
- {
- if (mutex->mutex_type != 1)
- {
- if (mutex->count_using > 0)
- {
- protocol->prepare_for_resend();
- protocol->store(mutex->cmutex_name, system_charset_info);
- protocol->store(mutex->cfile_name, system_charset_info);
- protocol->store((ulonglong)mutex->count_using);
- protocol->store((ulonglong)mutex->count_spin_loop);
- protocol->store((ulonglong)mutex->count_spin_rounds);
- protocol->store((ulonglong)mutex->count_os_wait);
- protocol->store((ulonglong)mutex->count_os_yield);
- protocol->store((ulonglong)mutex->lspent_time/1000);
-
- if (protocol->write())
- {
+ while (mutex != NULL) {
+ if (mutex->mutex_type != 1) {
+ if (mutex->count_using > 0) {
+ buf1len= my_snprintf(buf1, sizeof(buf1),
+ "%s:%s",
+ mutex->cmutex_name, mutex->cfile_name);
+ buf2len= my_snprintf(buf2, sizeof(buf2),
+ "count=%lu, spin_waits=%lu,"
+ " spin_rounds=%lu, "
+ "os_waits=%lu, os_yields=%lu,"
+ " os_wait_times=%lu",
+ mutex->count_using,
+ mutex->count_spin_loop,
+ mutex->count_spin_rounds,
+ mutex->count_os_wait,
+ mutex->count_os_yield,
+ mutex->lspent_time/1000);
+
+ if (stat_print(thd, innobase_hton_name,
+ hton_name_len, buf1, buf1len,
+ buf2, buf2len)) {
#ifdef MUTEX_PROTECT_TO_BE_ADDED_LATER
mutex_exit(&mutex_list_mutex);
#endif
@@ -6430,8 +6618,7 @@ innodb_mutex_show_status(
}
}
}
- else
- {
+ else {
rw_lock_count += mutex->count_using;
rw_lock_count_spin_loop += mutex->count_spin_loop;
rw_lock_count_spin_rounds += mutex->count_spin_rounds;
@@ -6443,28 +6630,40 @@ innodb_mutex_show_status(
mutex = UT_LIST_GET_NEXT(list, mutex);
}
- protocol->prepare_for_resend();
- protocol->store("rw_lock_mutexes", system_charset_info);
- protocol->store("", system_charset_info);
- protocol->store((ulonglong)rw_lock_count);
- protocol->store((ulonglong)rw_lock_count_spin_loop);
- protocol->store((ulonglong)rw_lock_count_spin_rounds);
- protocol->store((ulonglong)rw_lock_count_os_wait);
- protocol->store((ulonglong)rw_lock_count_os_yield);
- protocol->store((ulonglong)rw_lock_wait_time/1000);
+ buf2len= my_snprintf(buf2, sizeof(buf2),
+ "count=%lu, spin_waits=%lu, spin_rounds=%lu, "
+ "os_waits=%lu, os_yields=%lu, os_wait_times=%lu",
+ rw_lock_count, rw_lock_count_spin_loop,
+ rw_lock_count_spin_rounds,
+ rw_lock_count_os_wait, rw_lock_count_os_yield,
+ rw_lock_wait_time/1000);
- if (protocol->write())
- {
+ if (stat_print(thd, innobase_hton_name, hton_name_len,
+ STRING_WITH_LEN("rw_lock_mutexes"), buf2, buf2len)) {
DBUG_RETURN(1);
}
#ifdef MUTEX_PROTECT_TO_BE_ADDED_LATER
mutex_exit(&mutex_list_mutex);
#endif
- send_eof(thd);
+
DBUG_RETURN(FALSE);
}
+bool innobase_show_status(THD* thd, stat_print_fn* stat_print,
+ enum ha_stat_type stat_type)
+{
+ switch (stat_type) {
+ case HA_ENGINE_STATUS:
+ return innodb_show_status(thd, stat_print);
+ case HA_ENGINE_MUTEX:
+ return innodb_mutex_show_status(thd, stat_print);
+ default:
+ return FALSE;
+ }
+}
+
+
/****************************************************************************
Handling the shared INNOBASE_SHARE structure that is needed to provide table
locking.
@@ -6474,6 +6673,7 @@ static mysql_byte* innobase_get_key(INNO
my_bool not_used __attribute__((unused)))
{
*length=share->table_name_length;
+
return (mysql_byte*) share->table_name;
}
@@ -6515,13 +6715,14 @@ static INNOBASE_SHARE *get_share(const c
static void free_share(INNOBASE_SHARE *share)
{
pthread_mutex_lock(&innobase_share_mutex);
- if (!--share->use_count)
- {
+
+ if (!--share->use_count) {
hash_delete(&innobase_open_tables, (mysql_byte*) share);
thr_lock_delete(&share->lock);
pthread_mutex_destroy(&share->mutex);
my_free((gptr) share, MYF(0));
}
+
pthread_mutex_unlock(&innobase_share_mutex);
}
@@ -6550,12 +6751,35 @@ ha_innobase::store_lock(
TL_IGNORE */
{
row_prebuilt_t* prebuilt = (row_prebuilt_t*) innobase_prebuilt;
+ trx_t* trx;
+
+ /* Note that trx in this function is NOT necessarily prebuilt->trx
+ because we call update_thd() later, in ::external_lock()! Failure to
+ understand this caused a serious memory corruption bug in 5.1.11. */
+
+ trx = check_trx_exists(thd);
/* NOTE: MySQL can call this function with lock 'type' TL_IGNORE!
Be careful to ignore TL_IGNORE if we are going to do something with
only 'real' locks! */
- if ((lock_type == TL_READ && thd->in_lock_tables) ||
+ /* If no MySQL table is in use, we need to set the isolation level
+ of the transaction. */
+
+ if (lock_type != TL_IGNORE
+ && trx->n_mysql_tables_in_use == 0) {
+ trx->isolation_level = innobase_map_isolation_level(
+ (enum_tx_isolation)
+ thd->variables.tx_isolation);
+ }
+
+ if (thd->lex->sql_command == SQLCOM_DROP_TABLE) {
+
+ /* MySQL calls this function in DROP TABLE though this table
+ handle may belong to another thd that is running a query. Let
+ us in that case skip any changes to the prebuilt struct. */
+
+ } else if ((lock_type == TL_READ && thd->in_lock_tables) ||
(lock_type == TL_READ_HIGH_PRIORITY && thd->in_lock_tables) ||
lock_type == TL_READ_WITH_SHARED_LOCKS ||
lock_type == TL_READ_NO_INSERT ||
@@ -6579,15 +6803,21 @@ ha_innobase::store_lock(
unexpected if an obsolete consistent read view would be
used. */
- if (srv_locks_unsafe_for_binlog &&
- prebuilt->trx->isolation_level != TRX_ISO_SERIALIZABLE &&
- (lock_type == TL_READ || lock_type == TL_READ_NO_INSERT) &&
- (thd->lex->sql_command == SQLCOM_INSERT_SELECT ||
- thd->lex->sql_command == SQLCOM_UPDATE ||
- thd->lex->sql_command == SQLCOM_CREATE_TABLE)) {
+ ulint isolation_level;
- /* In case we have innobase_locks_unsafe_for_binlog
- option set and isolation level of the transaction
+ isolation_level = trx->isolation_level;
+
+ if ((srv_locks_unsafe_for_binlog
+ || isolation_level == TRX_ISO_READ_COMMITTED)
+ && isolation_level != TRX_ISO_SERIALIZABLE
+ && (lock_type == TL_READ || lock_type == TL_READ_NO_INSERT)
+ && (thd->lex->sql_command == SQLCOM_INSERT_SELECT
+ || thd->lex->sql_command == SQLCOM_UPDATE
+ || thd->lex->sql_command == SQLCOM_CREATE_TABLE)) {
+
+ /* If we either have innobase_locks_unsafe_for_binlog
+ option set or this session is using READ COMMITTED
+ isolation level and isolation level of the transaction
is not set to serializable and MySQL is doing
INSERT INTO...SELECT or UPDATE ... = (SELECT ...) or
CREATE ... SELECT... without FOR UPDATE or
@@ -6718,10 +6948,11 @@ ha_innobase::innobase_read_and_init_auto
int error;
ut_a(prebuilt);
- ut_a(prebuilt->trx ==
- (trx_t*) current_thd->ha_data[innobase_hton.slot]);
ut_a(prebuilt->table);
+ /* Prepare prebuilt->trx in the table handle */
+ update_thd(current_thd);
+
if (prebuilt->trx->conc_state == TRX_NOT_STARTED) {
trx_was_not_started = TRUE;
}
@@ -6762,7 +6993,7 @@ ha_innobase::innobase_read_and_init_auto
}
(void) extra(HA_EXTRA_KEYREAD);
- index_init(table->s->next_number_index);
+ index_init(table->s->next_number_index, 1);
/* Starting from 5.0.9, we use a consistent read to read the auto-inc
column maximum value. This eliminates the spurious deadlocks caused
@@ -6806,10 +7037,16 @@ ha_innobase::innobase_read_and_init_auto
'found_next_number_field' below because MySQL in SHOW TABLE
STATUS does not seem to set 'next_number_field'. The comment
in table.h says that 'next_number_field' is set when it is
- 'active'. */
+ 'active'.
+ Since 5.1 MySQL enforces that we announce fields which we will
+ read; as we only do a val_*() call, dbug_tmp_use_all_columns()
+ with read_set is sufficient. */
+ my_bitmap_map *old_map;
+ old_map= dbug_tmp_use_all_columns(table, table->read_set);
auto_inc = (longlong) table->found_next_number_field->
val_int_offset(table->s->rec_buff_length) + 1;
+ dbug_tmp_restore_column_map(table->read_set, old_map);
}
dict_table_autoinc_initialize(prebuilt->table, auto_inc);
@@ -6837,21 +7074,28 @@ func_exit_early:
return(error);
}
-/***********************************************************************
+/*******************************************************************************
This function initializes the auto-inc counter if it has not been
initialized yet. This function does not change the value of the auto-inc
counter if it already has been initialized. Returns the value of the
-auto-inc counter. */
+auto-inc counter in *first_value, and ULONGLONG_MAX in *nb_reserved_values (as
+we have a table-level lock). offset, increment, nb_desired_values are ignored.
+*first_value is set to -1 if error (deadlock or lock wait timeout) */
-ulonglong
-ha_innobase::get_auto_increment()
-/*=============================*/
- /* out: auto-increment column value, -1 if error
- (deadlock or lock wait timeout) */
+void ha_innobase::get_auto_increment(
+/*=================================*/
+ ulonglong offset, /* in */
+ ulonglong increment, /* in */
+ ulonglong nb_desired_values, /* in */
+ ulonglong *first_value, /* out */
+ ulonglong *nb_reserved_values) /* out */
{
longlong nr;
int error;
+ /* Prepare prebuilt->trx in the table handle */
+ update_thd(current_thd);
+
error = innobase_read_and_init_auto_inc(&nr);
if (error) {
@@ -6862,10 +7106,13 @@ ha_innobase::get_auto_increment()
ut_print_timestamp(stderr);
sql_print_error("Error %lu in ::get_auto_increment()",
(ulong) error);
- return(~(ulonglong) 0);
+ *first_value= (~(ulonglong) 0);
+ return;
}
- return((ulonglong) nr);
+ *first_value= (ulonglong) nr;
+ /* table-level autoinc lock reserves up to +inf */
+ *nb_reserved_values= ULONGLONG_MAX;
}
/* See comment in handler.h */
@@ -6877,6 +7124,8 @@ ha_innobase::reset_auto_increment(ulongl
row_prebuilt_t* prebuilt = (row_prebuilt_t*) innobase_prebuilt;
int error;
+ update_thd(current_thd);
+
error = row_lock_table_autoinc_for_mysql(prebuilt);
if (error != DB_SUCCESS) {
@@ -7121,7 +7370,9 @@ innobase_xa_prepare(
int error = 0;
trx_t* trx = check_trx_exists(thd);
- if (thd->lex->sql_command != SQLCOM_XA_PREPARE) {
+ if (thd->lex->sql_command != SQLCOM_XA_PREPARE &&
+ (all || !(thd->options & (OPTION_NOT_AUTOCOMMIT | OPTION_BEGIN))))
+ {
/* For ibbackup to work the order of transactions in binlog
and InnoDB must be the same. Consider the situation
@@ -7306,4 +7557,63 @@ innobase_set_cursor_view(
(cursor_view_t*) curview);
}
-#endif /* HAVE_INNOBASE_DB */
+
+bool ha_innobase::check_if_incompatible_data(
+ HA_CREATE_INFO* info,
+ uint table_changes)
+{
+ if (table_changes != IS_EQUAL_YES) {
+
+ return COMPATIBLE_DATA_NO;
+ }
+
+ /* Check that auto_increment value was not changed */
+ if ((info->used_fields & HA_CREATE_USED_AUTO) &&
+ info->auto_increment_value != 0) {
+
+ return COMPATIBLE_DATA_NO;
+ }
+
+ /* Check that row format didn't change */
+ if ((info->used_fields & HA_CREATE_USED_AUTO) &&
+ get_row_type() != info->row_type) {
+
+ return COMPATIBLE_DATA_NO;
+ }
+
+ return COMPATIBLE_DATA_YES;
+}
+
+static int show_innodb_vars(THD *thd, SHOW_VAR *var, char *buff)
+{
+ innodb_export_status();
+ var->type= SHOW_ARRAY;
+ var->value= (char *) &innodb_status_variables;
+ return 0;
+}
+
+SHOW_VAR innodb_status_variables_export[]= {
+ {"Innodb", (char*) &show_innodb_vars, SHOW_FUNC},
+ {NullS, NullS, SHOW_LONG}
+};
+
+struct st_mysql_storage_engine innobase_storage_engine=
+{ MYSQL_HANDLERTON_INTERFACE_VERSION, innobase_hton};
+
+mysql_declare_plugin(innobase)
+{
+ MYSQL_STORAGE_ENGINE_PLUGIN,
+ &innobase_storage_engine,
+ innobase_hton_name,
+ "Innobase OY",
+ "Supports transactions, row-level locking, and foreign keys",
+ innobase_init, /* Plugin Init */
+ NULL, /* Plugin Deinit */
+ 0x0100 /* 1.0 */,
+ innodb_status_variables_export,/* status variables */
+ NULL, /* system variables */
+ NULL /* config options */
+}
+mysql_declare_plugin_end;
+
+#endif
| Thread |
|---|
| • bk commit into 5.1 tree (cmiller:1.2334) | Chad MILLER | 28 Sep |