summaryrefslogtreecommitdiff
path: root/storage/innobase
diff options
context:
space:
mode:
authorMichael Widenius <monty@askmonty.org>2010-08-02 12:01:24 +0300
committerMichael Widenius <monty@askmonty.org>2010-08-02 12:01:24 +0300
commite0a6b02c5d0a311e7167295494786077009743d1 (patch)
tree72c934fe42261ad5de3139961e092f57e9d147df /storage/innobase
parentd2f8b7d04503478ab6b6998194a2070891f0c2bb (diff)
parent6ad06b15222300e4eed4fe3972d1ad249c4c42a2 (diff)
downloadmariadb-git-e0a6b02c5d0a311e7167295494786077009743d1.tar.gz
Merge with MySQL 5.1.49
Fixed Bug#52005 'JOIN_TAB->dependent' may be incorrectly propageted for multilevel outer joins' in a better way (patch from Sergey Petrunya)
Diffstat (limited to 'storage/innobase')
-rw-r--r--storage/innobase/buf/buf0flu.c3
-rw-r--r--storage/innobase/dict/dict0dict.c58
-rw-r--r--storage/innobase/fsp/fsp0fsp.c7
-rw-r--r--storage/innobase/handler/ha_innodb.cc65
-rw-r--r--storage/innobase/handler/ha_innodb.h2
-rw-r--r--storage/innobase/include/db0err.h5
-rw-r--r--storage/innobase/include/dict0dict.h1
-rw-r--r--storage/innobase/include/lock0lock.h12
-rw-r--r--storage/innobase/include/mach0data.ic23
-rw-r--r--storage/innobase/include/row0mysql.h44
-rw-r--r--storage/innobase/include/sync0sync.h2
-rw-r--r--storage/innobase/include/trx0trx.h2
-rw-r--r--storage/innobase/include/univ.i9
-rw-r--r--storage/innobase/lock/lock0lock.c138
-rw-r--r--storage/innobase/row/row0ins.c146
-rw-r--r--storage/innobase/row/row0mysql.c26
-rw-r--r--storage/innobase/row/row0sel.c146
-rw-r--r--storage/innobase/row/row0undo.c4
-rw-r--r--storage/innobase/srv/srv0srv.c10
-rw-r--r--storage/innobase/srv/srv0start.c14
-rw-r--r--storage/innobase/trx/trx0trx.c3
21 files changed, 424 insertions, 296 deletions
diff --git a/storage/innobase/buf/buf0flu.c b/storage/innobase/buf/buf0flu.c
index 423c08c0569..7533205d695 100644
--- a/storage/innobase/buf/buf0flu.c
+++ b/storage/innobase/buf/buf0flu.c
@@ -55,6 +55,7 @@ buf_flush_insert_into_flush_list(
|| (ut_dulint_cmp((UT_LIST_GET_FIRST(buf_pool->flush_list))
->oldest_modification,
block->oldest_modification) <= 0));
+ UNIV_MEM_ASSERT_RW(block->frame, UNIV_PAGE_SIZE);
UT_LIST_ADD_FIRST(flush_list, buf_pool->flush_list, block);
@@ -75,6 +76,7 @@ buf_flush_insert_sorted_into_flush_list(
buf_block_t* b;
ut_ad(mutex_own(&(buf_pool->mutex)));
+ UNIV_MEM_ASSERT_RW(block->frame, UNIV_PAGE_SIZE);
prev_b = NULL;
b = UT_LIST_GET_FIRST(buf_pool->flush_list);
@@ -423,6 +425,7 @@ try_again:
goto try_again;
}
+ UNIV_MEM_ASSERT_RW(block->frame, UNIV_PAGE_SIZE);
ut_memcpy(trx_doublewrite->write_buf
+ UNIV_PAGE_SIZE * trx_doublewrite->first_free,
block->frame, UNIV_PAGE_SIZE);
diff --git a/storage/innobase/dict/dict0dict.c b/storage/innobase/dict/dict0dict.c
index b8251a99105..d2b59469cdc 100644
--- a/storage/innobase/dict/dict0dict.c
+++ b/storage/innobase/dict/dict0dict.c
@@ -618,13 +618,11 @@ dict_table_get_on_id(
if (ut_dulint_cmp(table_id, DICT_FIELDS_ID) <= 0
|| trx->dict_operation_lock_mode == RW_X_LATCH) {
- /* It is a system table which will always exist in the table
- cache: we avoid acquiring the dictionary mutex, because
- if we are doing a rollback to handle an error in TABLE
- CREATE, for example, we already have the mutex! */
- ut_ad(mutex_own(&(dict_sys->mutex))
- || trx->dict_operation_lock_mode == RW_X_LATCH);
+ /* Note: An X latch implies that the transaction
+ already owns the dictionary mutex. */
+
+ ut_ad(mutex_own(&dict_sys->mutex));
return(dict_table_get_on_id_low(table_id));
}
@@ -2586,25 +2584,28 @@ dict_strip_comments(
/* out, own: SQL string stripped from
comments; the caller must free this
with mem_free()! */
- const char* sql_string) /* in: SQL string */
+ const char* sql_string, /* in: SQL string */
+ size_t sql_length) /* in: length of sql_string */
{
char* str;
const char* sptr;
+ const char* eptr = sql_string + sql_length;
char* ptr;
/* unclosed quote character (0 if none) */
char quote = 0;
- str = mem_alloc(strlen(sql_string) + 1);
+ str = mem_alloc(sql_length + 1);
sptr = sql_string;
ptr = str;
for (;;) {
scan_more:
- if (*sptr == '\0') {
+ if (sptr >= eptr || *sptr == '\0') {
+end_of_string:
*ptr = '\0';
- ut_a(ptr <= str + strlen(sql_string));
+ ut_a(ptr <= str + sql_length);
return(str);
}
@@ -2623,30 +2624,35 @@ scan_more:
|| (sptr[0] == '-' && sptr[1] == '-'
&& sptr[2] == ' ')) {
for (;;) {
+ if (++sptr >= eptr) {
+ goto end_of_string;
+ }
+
/* In Unix a newline is 0x0A while in Windows
it is 0x0D followed by 0x0A */
- if (*sptr == (char)0x0A
- || *sptr == (char)0x0D
- || *sptr == '\0') {
-
+ switch (*sptr) {
+ case (char) 0X0A:
+ case (char) 0x0D:
+ case '\0':
goto scan_more;
}
-
- sptr++;
}
} else if (!quote && *sptr == '/' && *(sptr + 1) == '*') {
+ sptr += 2;
for (;;) {
- if (*sptr == '*' && *(sptr + 1) == '/') {
-
- sptr += 2;
-
- goto scan_more;
+ if (sptr >= eptr) {
+ goto end_of_string;
}
- if (*sptr == '\0') {
-
+ switch (*sptr) {
+ case '\0':
goto scan_more;
+ case '*':
+ if (sptr[1] == '/') {
+ sptr += 2;
+ goto scan_more;
+ }
}
sptr++;
@@ -3348,6 +3354,7 @@ dict_create_foreign_constraints(
name before it: test.table2; the
default database id the database of
parameter name */
+ size_t sql_length, /* in: length of sql_string */
const char* name, /* in: table full name in the
normalized form
database_name/table_name */
@@ -3362,7 +3369,7 @@ dict_create_foreign_constraints(
ut_a(trx);
ut_a(trx->mysql_thd);
- str = dict_strip_comments(sql_string);
+ str = dict_strip_comments(sql_string, sql_length);
heap = mem_heap_create(10000);
err = dict_create_foreign_constraints_low(
@@ -3411,7 +3418,8 @@ dict_foreign_parse_drop_constraints(
*constraints_to_drop = mem_heap_alloc(heap, 1000 * sizeof(char*));
- str = dict_strip_comments(*(trx->mysql_query_str));
+ str = dict_strip_comments(*trx->mysql_query_str,
+ *trx->mysql_query_len);
ptr = str;
ut_ad(mutex_own(&(dict_sys->mutex)));
diff --git a/storage/innobase/fsp/fsp0fsp.c b/storage/innobase/fsp/fsp0fsp.c
index e1074933fe8..1ec1c262a52 100644
--- a/storage/innobase/fsp/fsp0fsp.c
+++ b/storage/innobase/fsp/fsp0fsp.c
@@ -802,12 +802,7 @@ fsp_init_file_page_low(
buf_block_align(page)->check_index_page_at_flush = FALSE;
-#ifdef UNIV_BASIC_LOG_DEBUG
- memset(page, 0xff, UNIV_PAGE_SIZE);
-#endif
- mach_write_to_8(page + UNIV_PAGE_SIZE - FIL_PAGE_END_LSN_OLD_CHKSUM,
- ut_dulint_zero);
- mach_write_to_8(page + FIL_PAGE_LSN, ut_dulint_zero);
+ memset(page, 0, UNIV_PAGE_SIZE);
}
/***************************************************************
diff --git a/storage/innobase/handler/ha_innodb.cc b/storage/innobase/handler/ha_innodb.cc
index ebf01fbc296..d10fcb8d31e 100644
--- a/storage/innobase/handler/ha_innodb.cc
+++ b/storage/innobase/handler/ha_innodb.cc
@@ -583,13 +583,13 @@ thd_is_select(
/************************************************************************
Obtain the InnoDB transaction of a MySQL thread. */
inline
-trx_t*&
+trx_t*
thd_to_trx(
/*=======*/
/* out: reference to transaction pointer */
THD* thd) /* in: MySQL thread */
{
- return(*(trx_t**) thd_ha_data(thd, innodb_hton_ptr));
+ return((trx_t*) thd_get_ha_data(thd, innodb_hton_ptr));
}
/************************************************************************
@@ -759,6 +759,10 @@ convert_error_code_to_mysql(
} else if (error == DB_UNSUPPORTED) {
return(HA_ERR_UNSUPPORTED);
+ } else if (error == DB_INTERRUPTED) {
+
+ my_error(ER_QUERY_INTERRUPTED, MYF(0));
+ return(-1);
} else {
return(-1); // Unknown error
}
@@ -1140,6 +1144,15 @@ innobase_next_autoinc(
return(next_value);
}
+/** Copy the current SQL statement.
+* @param[in] thd MySQL client connection
+* @param[in/out] trx InnoDB transaction */
+#define INNOBASE_COPY_STMT(thd, trx) do { \
+ LEX_STRING* stmt = thd_query_string(thd); \
+ (trx)->mysql_query_str = &stmt->str; \
+ (trx)->mysql_query_len = &stmt->length; \
+} while (0)
+
/*************************************************************************
Gets the InnoDB transaction handle for a MySQL handler object, creates
an InnoDB transaction struct if the corresponding MySQL thread struct still
@@ -1151,7 +1164,7 @@ check_trx_exists(
/* out: InnoDB transaction handle */
THD* thd) /* in: user thread handle */
{
- trx_t*& trx = thd_to_trx(thd);
+ trx_t* trx = thd_to_trx(thd);
ut_ad(thd == current_thd);
@@ -1160,11 +1173,14 @@ check_trx_exists(
trx = trx_allocate_for_mysql();
trx->mysql_thd = thd;
- trx->mysql_query_str = thd_query(thd);
+ INNOBASE_COPY_STMT(thd, trx);
/* Update the info whether we should skip XA steps that eat
CPU time */
trx->support_xa = THDVAR(thd, support_xa);
+
+ /* We have a new trx, register with the thread handle */
+ thd_set_ha_data(thd, innodb_hton_ptr, trx);
} else {
if (trx->magic_n != TRX_MAGIC_N) {
mem_analyze_corruption(trx);
@@ -2469,6 +2485,9 @@ innobase_close_connection(
innobase_rollback_trx(trx);
+ /* Release the lock in thread handler */
+ thd_set_ha_data(thd, hton, NULL);
+
thr_local_free(trx->mysql_thread_id);
trx_free_for_mysql(trx);
@@ -3223,6 +3242,11 @@ get_innobase_type_from_mysql_type(
case MYSQL_TYPE_BLOB:
case MYSQL_TYPE_LONG_BLOB:
return(DATA_BLOB);
+ case MYSQL_TYPE_NULL:
+ /* MySQL currently accepts "NULL" datatype, but will
+ reject such datatype in the next release. We will cope
+ with it and not trigger assertion failure in 5.1 */
+ break;
default:
assert(0);
}
@@ -5244,7 +5268,22 @@ create_table_def(
field = form->field[i];
col_type = get_innobase_type_from_mysql_type(&unsigned_type,
- field);
+ field);
+
+ if (!col_type) {
+ push_warning_printf(
+ (THD*) trx->mysql_thd,
+ MYSQL_ERROR::WARN_LEVEL_WARN,
+ ER_CANT_CREATE_TABLE,
+ "Error creating table '%s' with "
+ "column '%s'. Please check its "
+ "column type and try to re-create "
+ "the table with an appropriate "
+ "column type.",
+ table->name, (char*) field->field_name);
+ goto err_col;
+ }
+
if (field->null_ptr) {
nulls_allowed = 0;
} else {
@@ -5301,7 +5340,7 @@ create_table_def(
"different column name.",
table->name, (char*) field->field_name,
(char*) field->field_name);
-
+err_col:
dict_mem_table_free(table);
trx_commit_for_mysql(trx);
@@ -5578,7 +5617,7 @@ ha_innobase::create(
trx = trx_allocate_for_mysql();
trx->mysql_thd = thd;
- trx->mysql_query_str = thd_query(thd);
+ INNOBASE_COPY_STMT(thd, trx);
if (thd_test_options(thd, OPTION_NO_FOREIGN_KEY_CHECKS)) {
trx->check_foreigns = FALSE;
@@ -5674,8 +5713,10 @@ ha_innobase::create(
}
if (*trx->mysql_query_str) {
- error = row_table_add_foreign_constraints(trx,
- *trx->mysql_query_str, norm_name,
+ error = row_table_add_foreign_constraints(
+ trx,
+ *trx->mysql_query_str, *trx->mysql_query_len,
+ norm_name,
create_info->options & HA_LEX_CREATE_TMP_TABLE);
error = convert_error_code_to_mysql(error, NULL);
@@ -5866,7 +5907,7 @@ ha_innobase::delete_table(
trx = trx_allocate_for_mysql();
trx->mysql_thd = thd;
- trx->mysql_query_str = thd_query(thd);
+ INNOBASE_COPY_STMT(thd, trx);
if (thd_test_options(thd, OPTION_NO_FOREIGN_KEY_CHECKS)) {
trx->check_foreigns = FALSE;
@@ -5955,7 +5996,7 @@ innobase_drop_database(
#endif
trx = trx_allocate_for_mysql();
trx->mysql_thd = thd;
- trx->mysql_query_str = thd_query(thd);
+ INNOBASE_COPY_STMT(thd, trx);
if (thd_test_options(thd, OPTION_NO_FOREIGN_KEY_CHECKS)) {
trx->check_foreigns = FALSE;
@@ -6025,7 +6066,7 @@ ha_innobase::rename_table(
trx = trx_allocate_for_mysql();
trx->mysql_thd = thd;
- trx->mysql_query_str = thd_query(thd);
+ INNOBASE_COPY_STMT(thd, trx);
if (thd_test_options(thd, OPTION_NO_FOREIGN_KEY_CHECKS)) {
trx->check_foreigns = FALSE;
diff --git a/storage/innobase/handler/ha_innodb.h b/storage/innobase/handler/ha_innodb.h
index 5b3df16875a..eb9199b8955 100644
--- a/storage/innobase/handler/ha_innodb.h
+++ b/storage/innobase/handler/ha_innodb.h
@@ -210,7 +210,7 @@ the definitions are bracketed with #ifdef INNODB_COMPATIBILITY_HOOKS */
extern "C" {
struct charset_info_st *thd_charset(MYSQL_THD thd);
-char **thd_query(MYSQL_THD thd);
+LEX_STRING *thd_query_string(MYSQL_THD thd);
/** Get the file name of the MySQL binlog.
* @return the name of the binlog file
diff --git a/storage/innobase/include/db0err.h b/storage/innobase/include/db0err.h
index ed7ce151718..2be6005622d 100644
--- a/storage/innobase/include/db0err.h
+++ b/storage/innobase/include/db0err.h
@@ -10,6 +10,8 @@ Created 5/24/1996 Heikki Tuuri
#define db0err_h
+#define DB_SUCCESS_LOCKED_REC 9 /* like DB_SUCCESS, but a new
+ explicit record lock was created */
#define DB_SUCCESS 10
/* The following are error codes */
@@ -69,6 +71,9 @@ Created 5/24/1996 Heikki Tuuri
a feature that it can't recoginize or
work with e.g., FT indexes created by
a later version of the engine. */
+#define DB_INTERRUPTED 49 /* the query has been interrupted with
+ "KILL QUERY N;" */
+
/* The following are partial failure codes */
#define DB_FAIL 1000
#define DB_OVERFLOW 1001
diff --git a/storage/innobase/include/dict0dict.h b/storage/innobase/include/dict0dict.h
index 7d5ff09c7a6..e76f23d0767 100644
--- a/storage/innobase/include/dict0dict.h
+++ b/storage/innobase/include/dict0dict.h
@@ -309,6 +309,7 @@ dict_create_foreign_constraints(
name before it: test.table2; the
default database id the database of
parameter name */
+ size_t sql_length, /* in: length of sql_string */
const char* name, /* in: table full name in the
normalized form
database_name/table_name */
diff --git a/storage/innobase/include/lock0lock.h b/storage/innobase/include/lock0lock.h
index beaf17eda01..70b141eafeb 100644
--- a/storage/innobase/include/lock0lock.h
+++ b/storage/innobase/include/lock0lock.h
@@ -292,14 +292,15 @@ lock_sec_rec_modify_check_and_lock(
dict_index_t* index, /* in: secondary index */
que_thr_t* thr); /* in: query thread */
/*************************************************************************
-Like the counterpart for a clustered index below, but now we read a
+Like lock_clust_rec_read_check_and_lock(), but reads a
secondary index record. */
ulint
lock_sec_rec_read_check_and_lock(
/*=============================*/
- /* out: DB_SUCCESS, DB_LOCK_WAIT,
- DB_DEADLOCK, or DB_QUE_THR_SUSPENDED */
+ /* out: DB_SUCCESS, DB_SUCCESS_LOCKED_REC,
+ DB_LOCK_WAIT, DB_DEADLOCK,
+ or DB_QUE_THR_SUSPENDED */
ulint flags, /* in: if BTR_NO_LOCKING_FLAG bit is set,
does nothing */
rec_t* rec, /* in: user record or page supremum record
@@ -324,8 +325,9 @@ lock on the record. */
ulint
lock_clust_rec_read_check_and_lock(
/*===============================*/
- /* out: DB_SUCCESS, DB_LOCK_WAIT,
- DB_DEADLOCK, or DB_QUE_THR_SUSPENDED */
+ /* out: DB_SUCCESS, DB_SUCCESS_LOCKED_REC,
+ DB_LOCK_WAIT, DB_DEADLOCK,
+ or DB_QUE_THR_SUSPENDED */
ulint flags, /* in: if BTR_NO_LOCKING_FLAG bit is set,
does nothing */
rec_t* rec, /* in: user record or page supremum record
diff --git a/storage/innobase/include/mach0data.ic b/storage/innobase/include/mach0data.ic
index dc7918c287b..fceb8017121 100644
--- a/storage/innobase/include/mach0data.ic
+++ b/storage/innobase/include/mach0data.ic
@@ -19,7 +19,7 @@ mach_write_to_1(
ulint n) /* in: ulint integer to be stored, >= 0, < 256 */
{
ut_ad(b);
- ut_ad(n <= 0xFFUL);
+ ut_ad((n | 0xFFUL) <= 0xFFUL);
b[0] = (byte)n;
}
@@ -48,7 +48,7 @@ mach_write_to_2(
ulint n) /* in: ulint integer to be stored */
{
ut_ad(b);
- ut_ad(n <= 0xFFFFUL);
+ ut_ad((n | 0xFFFFUL) <= 0xFFFFUL);
b[0] = (byte)(n >> 8);
b[1] = (byte)(n);
@@ -64,10 +64,7 @@ mach_read_from_2(
/* out: ulint integer */
byte* b) /* in: pointer to 2 bytes */
{
- ut_ad(b);
- return( ((ulint)(b[0]) << 8)
- + (ulint)(b[1])
- );
+ return(((ulint)(b[0]) << 8) | (ulint)(b[1]));
}
/************************************************************
@@ -112,7 +109,7 @@ mach_write_to_3(
ulint n) /* in: ulint integer to be stored */
{
ut_ad(b);
- ut_ad(n <= 0xFFFFFFUL);
+ ut_ad((n | 0xFFFFFFUL) <= 0xFFFFFFUL);
b[0] = (byte)(n >> 16);
b[1] = (byte)(n >> 8);
@@ -131,8 +128,8 @@ mach_read_from_3(
{
ut_ad(b);
return( ((ulint)(b[0]) << 16)
- + ((ulint)(b[1]) << 8)
- + (ulint)(b[2])
+ | ((ulint)(b[1]) << 8)
+ | (ulint)(b[2])
);
}
@@ -166,9 +163,9 @@ mach_read_from_4(
{
ut_ad(b);
return( ((ulint)(b[0]) << 24)
- + ((ulint)(b[1]) << 16)
- + ((ulint)(b[2]) << 8)
- + (ulint)(b[3])
+ | ((ulint)(b[1]) << 16)
+ | ((ulint)(b[2]) << 8)
+ | (ulint)(b[3])
);
}
@@ -670,7 +667,7 @@ mach_read_from_2_little_endian(
/* out: unsigned long int */
byte* buf) /* in: from where to read */
{
- return((ulint)(*buf) + ((ulint)(*(buf + 1))) * 256);
+ return((ulint)(buf[0]) | ((ulint)(buf[1]) << 8));
}
/*************************************************************
diff --git a/storage/innobase/include/row0mysql.h b/storage/innobase/include/row0mysql.h
index 5430190fa51..488177791a4 100644
--- a/storage/innobase/include/row0mysql.h
+++ b/storage/innobase/include/row0mysql.h
@@ -246,22 +246,20 @@ row_update_for_mysql(
row_prebuilt_t* prebuilt); /* in: prebuilt struct in MySQL
handle */
/*************************************************************************
-This can only be used when srv_locks_unsafe_for_binlog is TRUE or
-session is using a READ COMMITTED isolation level. Before
-calling this function we must use trx_reset_new_rec_lock_info() and
-trx_register_new_rec_lock() to store the information which new record locks
-really were set. This function removes a newly set lock under prebuilt->pcur,
-and also under prebuilt->clust_pcur. Currently, this is only used and tested
-in the case of an UPDATE or a DELETE statement, where the row lock is of the
-LOCK_X type.
-Thus, this implements a 'mini-rollback' that releases the latest record
-locks we set. */
+This can only be used when srv_locks_unsafe_for_binlog is TRUE or this
+session is using a READ COMMITTED or READ UNCOMMITTED isolation level.
+Before calling this function row_search_for_mysql() must have
+initialized prebuilt->new_rec_locks to store the information which new
+record locks really were set. This function removes a newly set
+clustered index record lock under prebuilt->pcur or
+prebuilt->clust_pcur. Thus, this implements a 'mini-rollback' that
+releases the latest clustered index record lock we set. */
int
row_unlock_for_mysql(
/*=================*/
/* out: error code or DB_SUCCESS */
- row_prebuilt_t* prebuilt, /* in: prebuilt struct in MySQL
+ row_prebuilt_t* prebuilt, /* in/out: prebuilt struct in MySQL
handle */
ibool has_latches_on_recs);/* TRUE if called so that we have
the latches on the records under pcur
@@ -366,6 +364,7 @@ row_table_add_foreign_constraints(
FOREIGN KEY (a, b) REFERENCES table2(c, d),
table2 can be written also with the
database name before it: test.table2 */
+ size_t sql_length, /* in: length of sql_string */
const char* name, /* in: table full name in the
normalized form
database_name/table_name */
@@ -659,18 +658,17 @@ struct row_prebuilt_struct {
ulint new_rec_locks; /* normally 0; if
srv_locks_unsafe_for_binlog is
TRUE or session is using READ
- COMMITTED isolation level, in a
- cursor search, if we set a new
- record lock on an index, this is
- incremented; this is used in
- releasing the locks under the
- cursors if we are performing an
- UPDATE and we determine after
- retrieving the row that it does
- not need to be locked; thus,
- these can be used to implement a
- 'mini-rollback' that releases
- the latest record locks */
+ COMMITTED or READ UNCOMMITTED
+ isolation level, set in
+ row_search_for_mysql() if we set a new
+ record lock on the secondary
+ or clustered index; this is
+ used in row_unlock_for_mysql()
+ when releasing the lock under
+ the cursor if we determine
+ after retrieving the row that
+ it does not need to be locked
+ ('mini-rollback') */
ulint mysql_prefix_len;/* byte offset of the end of
the last requested column */
ulint mysql_row_len; /* length in bytes of a row in the
diff --git a/storage/innobase/include/sync0sync.h b/storage/innobase/include/sync0sync.h
index 6a61330f97e..9430d4cb723 100644
--- a/storage/innobase/include/sync0sync.h
+++ b/storage/innobase/include/sync0sync.h
@@ -401,7 +401,7 @@ or row lock! */
locked; see e.g.
ibuf_bitmap_get_map_page(). */
#define SYNC_DICT_OPERATION 1001 /* table create, drop, etc. reserve
- this in X-mode, implicit or backround
+ this in X-mode; implicit or backround
operations purge, rollback, foreign
key checks reserve this in S-mode */
#define SYNC_DICT 1000
diff --git a/storage/innobase/include/trx0trx.h b/storage/innobase/include/trx0trx.h
index cdbf1970715..97a47d9f46e 100644
--- a/storage/innobase/include/trx0trx.h
+++ b/storage/innobase/include/trx0trx.h
@@ -444,6 +444,8 @@ struct trx_struct{
char** mysql_query_str;/* pointer to the field in mysqld_thd
which contains the pointer to the
current SQL query string */
+ size_t* mysql_query_len;/* pointer to the length of the
+ current SQL query string */
const char* mysql_log_file_name;
/* if MySQL binlog is used, this field
contains a pointer to the latest file
diff --git a/storage/innobase/include/univ.i b/storage/innobase/include/univ.i
index ee3a0b27b20..97d022d284e 100644
--- a/storage/innobase/include/univ.i
+++ b/storage/innobase/include/univ.i
@@ -82,9 +82,9 @@ memory is read outside the allocated blocks. */
/* Make a non-inline debug version */
-#ifdef HAVE_purify
+#if defined HAVE_VALGRIND
# define UNIV_DEBUG_VALGRIND
-#endif /* HAVE_purify */
+#endif /* HAVE_VALGRIND */
#if 0
#define UNIV_DEBUG_VALGRIND /* Enable extra
Valgrind instrumentation */
@@ -126,11 +126,6 @@ by one. */
/* the above option prevents forcing of log to disk
at a buffer page write: it should be tested with this
option off; also some ibuf tests are suppressed */
-/*
-#define UNIV_BASIC_LOG_DEBUG
-*/
- /* the above option enables basic recovery debugging:
- new allocated file pages are reset */
#if (!defined(UNIV_DEBUG) && !defined(INSIDE_HA_INNOBASE_CC) && !defined(UNIV_MUST_NOT_INLINE))
/* Definition for inline version */
diff --git a/storage/innobase/lock/lock0lock.c b/storage/innobase/lock/lock0lock.c
index 7df8ea50887..04240960b3a 100644
--- a/storage/innobase/lock/lock0lock.c
+++ b/storage/innobase/lock/lock0lock.c
@@ -1739,11 +1739,12 @@ ulint
lock_rec_enqueue_waiting(
/*=====================*/
/* out: DB_LOCK_WAIT, DB_DEADLOCK, or
- DB_QUE_THR_SUSPENDED, or DB_SUCCESS;
- DB_SUCCESS means that there was a deadlock,
- but another transaction was chosen as a
- victim, and we got the lock immediately:
- no need to wait then */
+ DB_QUE_THR_SUSPENDED, or DB_SUCCESS_LOCKED_REC;
+ DB_SUCCESS_LOCKED_REC means that there
+ was a deadlock, but another
+ transaction was chosen as a victim,
+ and we got the lock immediately: no
+ need to wait then */
ulint type_mode,/* in: lock mode this transaction is
requesting: LOCK_S or LOCK_X, possibly ORed
with LOCK_GAP or LOCK_REC_NOT_GAP, ORed
@@ -1804,7 +1805,7 @@ lock_rec_enqueue_waiting(
if (trx->wait_lock == NULL) {
- return(DB_SUCCESS);
+ return(DB_SUCCESS_LOCKED_REC);
}
trx->que_state = TRX_QUE_LOCK_WAIT;
@@ -1903,6 +1904,16 @@ lock_rec_add_to_queue(
return(lock_rec_create(type_mode, rec, index, trx));
}
+/** Record locking request status */
+enum lock_rec_req_status {
+ /** Failed to acquire a lock */
+ LOCK_REC_FAIL,
+ /** Succeeded in acquiring a lock (implicit or already acquired) */
+ LOCK_REC_SUCCESS,
+ /** Explicitly created a new lock */
+ LOCK_REC_SUCCESS_CREATED
+};
+
/*************************************************************************
This is a fast routine for locking a record in the most common cases:
there are no explicit locks on the page, or there is just one lock, owned
@@ -1911,10 +1922,10 @@ which does NOT look at implicit locks! Checks lock compatibility within
explicit locks. This function sets a normal next-key lock, or in the case of
a page supremum record, a gap type lock. */
UNIV_INLINE
-ibool
+enum lock_rec_req_status
lock_rec_lock_fast(
/*===============*/
- /* out: TRUE if locking succeeded */
+ /* out: whether the locking succeeded */
ibool impl, /* in: if TRUE, no lock is set if no wait
is necessary: we assume that the caller will
set an implicit lock */
@@ -1950,19 +1961,19 @@ lock_rec_lock_fast(
lock_rec_create(mode, rec, index, trx);
}
- return(TRUE);
+ return(LOCK_REC_SUCCESS_CREATED);
}
if (lock_rec_get_next_on_page(lock)) {
- return(FALSE);
+ return(LOCK_REC_FAIL);
}
if (lock->trx != trx
|| lock->type_mode != (mode | LOCK_REC)
|| lock_rec_get_n_bits(lock) <= heap_no) {
- return(FALSE);
+ return(LOCK_REC_FAIL);
}
if (!impl) {
@@ -1971,10 +1982,11 @@ lock_rec_lock_fast(
if (!lock_rec_get_nth_bit(lock, heap_no)) {
lock_rec_set_nth_bit(lock, heap_no);
+ return(LOCK_REC_SUCCESS_CREATED);
}
}
- return(TRUE);
+ return(LOCK_REC_SUCCESS);
}
/*************************************************************************
@@ -1986,8 +1998,9 @@ static
ulint
lock_rec_lock_slow(
/*===============*/
- /* out: DB_SUCCESS, DB_LOCK_WAIT, or error
- code */
+ /* out: DB_SUCCESS, DB_SUCCESS_LOCKED_REC,
+ DB_LOCK_WAIT, DB_DEADLOCK,
+ or DB_QUE_THR_SUSPENDED */
ibool impl, /* in: if TRUE, no lock is set if no wait is
necessary: we assume that the caller will set
an implicit lock */
@@ -1998,7 +2011,6 @@ lock_rec_lock_slow(
que_thr_t* thr) /* in: query thread */
{
trx_t* trx;
- ulint err;
ut_ad(mutex_own(&kernel_mutex));
ut_ad((LOCK_MODE_MASK & mode) != LOCK_S
@@ -2017,26 +2029,21 @@ lock_rec_lock_slow(
/* The trx already has a strong enough lock on rec: do
nothing */
- err = DB_SUCCESS;
} else if (lock_rec_other_has_conflicting(mode, rec, trx)) {
/* If another transaction has a non-gap conflicting request in
the queue, as this transaction does not have a lock strong
enough already granted on the record, we have to wait. */
- err = lock_rec_enqueue_waiting(mode, rec, index, thr);
- } else {
- if (!impl) {
- /* Set the requested lock on the record */
+ return(lock_rec_enqueue_waiting(mode, rec, index, thr));
+ } else if (!impl) {
+ /* Set the requested lock on the record */
- lock_rec_add_to_queue(LOCK_REC | mode, rec, index,
- trx);
- }
-
- err = DB_SUCCESS;
+ lock_rec_add_to_queue(LOCK_REC | mode, rec, index, trx);
+ return(DB_SUCCESS_LOCKED_REC);
}
- return(err);
+ return(DB_SUCCESS);
}
/*************************************************************************
@@ -2049,8 +2056,9 @@ static
ulint
lock_rec_lock(
/*==========*/
- /* out: DB_SUCCESS, DB_LOCK_WAIT, or error
- code */
+ /* out: DB_SUCCESS, DB_SUCCESS_LOCKED_REC,
+ DB_LOCK_WAIT, DB_DEADLOCK, or
+ DB_QUE_THR_SUSPENDED */
ibool impl, /* in: if TRUE, no lock is set if no wait is
necessary: we assume that the caller will set
an implicit lock */
@@ -2060,8 +2068,6 @@ lock_rec_lock(
dict_index_t* index, /* in: index of record */
que_thr_t* thr) /* in: query thread */
{
- ulint err;
-
ut_ad(mutex_own(&kernel_mutex));
ut_ad((LOCK_MODE_MASK & mode) != LOCK_S
|| lock_table_has(thr_get_trx(thr), index->table, LOCK_IS));
@@ -2073,17 +2079,19 @@ lock_rec_lock(
|| mode - (LOCK_MODE_MASK & mode) == LOCK_REC_NOT_GAP
|| mode - (LOCK_MODE_MASK & mode) == 0);
- if (lock_rec_lock_fast(impl, mode, rec, index, thr)) {
-
- /* We try a simplified and faster subroutine for the most
- common cases */
-
- err = DB_SUCCESS;
- } else {
- err = lock_rec_lock_slow(impl, mode, rec, index, thr);
+ /* We try a simplified and faster subroutine for the most
+ common cases */
+ switch (lock_rec_lock_fast(impl, mode, rec, index, thr)) {
+ case LOCK_REC_SUCCESS:
+ return(DB_SUCCESS);
+ case LOCK_REC_SUCCESS_CREATED:
+ return(DB_SUCCESS_LOCKED_REC);
+ case LOCK_REC_FAIL:
+ return(lock_rec_lock_slow(impl, mode, rec, index, thr));
}
- return(err);
+ ut_error;
+ return(DB_ERROR);
}
/*************************************************************************
@@ -4832,7 +4840,7 @@ lock_rec_insert_check_and_lock(
lock = lock_rec_get_first(next_rec);
- if (lock == NULL) {
+ if (UNIV_LIKELY(lock == NULL)) {
/* We optimize CPU time usage in the simplest case */
lock_mutex_exit_kernel();
@@ -4840,8 +4848,7 @@ lock_rec_insert_check_and_lock(
if (!(index->type & DICT_CLUSTERED)) {
/* Update the page max trx id field */
- page_update_max_trx_id(buf_frame_align(rec),
- thr_get_trx(thr)->id);
+ page_update_max_trx_id(buf_frame_align(rec), trx->id);
}
return(DB_SUCCESS);
@@ -4873,11 +4880,16 @@ lock_rec_insert_check_and_lock(
lock_mutex_exit_kernel();
- if (!(index->type & DICT_CLUSTERED) && (err == DB_SUCCESS)) {
-
+ switch (err) {
+ case DB_SUCCESS_LOCKED_REC:
+ err = DB_SUCCESS;
+ /* fall through */
+ case DB_SUCCESS:
+ if (index->type & DICT_CLUSTERED) {
+ break;
+ }
/* Update the page max trx id field */
- page_update_max_trx_id(buf_frame_align(rec),
- thr_get_trx(thr)->id);
+ page_update_max_trx_id(buf_frame_align(rec), trx->id);
}
#ifdef UNIV_DEBUG
@@ -4984,6 +4996,10 @@ lock_clust_rec_modify_check_and_lock(
ut_ad(lock_rec_queue_validate(rec, index, offsets));
+ if (UNIV_UNLIKELY(err == DB_SUCCESS_LOCKED_REC)) {
+ err = DB_SUCCESS;
+ }
+
return(err);
}
@@ -5043,25 +5059,29 @@ lock_sec_rec_modify_check_and_lock(
}
#endif /* UNIV_DEBUG */
- if (err == DB_SUCCESS) {
+ if (err == DB_SUCCESS || err == DB_SUCCESS_LOCKED_REC) {
/* Update the page max trx id field */
-
+ /* It might not be necessary to do this if
+ err == DB_SUCCESS (no new lock created),
+ but it should not cost too much performance. */
page_update_max_trx_id(buf_frame_align(rec),
thr_get_trx(thr)->id);
+ err = DB_SUCCESS;
}
return(err);
}
/*************************************************************************
-Like the counterpart for a clustered index below, but now we read a
+Like lock_clust_rec_read_check_and_lock(), but reads a
secondary index record. */
ulint
lock_sec_rec_read_check_and_lock(
/*=============================*/
- /* out: DB_SUCCESS, DB_LOCK_WAIT,
- DB_DEADLOCK, or DB_QUE_THR_SUSPENDED */
+ /* out: DB_SUCCESS, DB_SUCCESS_LOCKED_REC,
+ DB_LOCK_WAIT, DB_DEADLOCK,
+ or DB_QUE_THR_SUSPENDED */
ulint flags, /* in: if BTR_NO_LOCKING_FLAG bit is set,
does nothing */
rec_t* rec, /* in: user record or page supremum record
@@ -5126,8 +5146,9 @@ lock on the record. */
ulint
lock_clust_rec_read_check_and_lock(
/*===============================*/
- /* out: DB_SUCCESS, DB_LOCK_WAIT,
- DB_DEADLOCK, or DB_QUE_THR_SUSPENDED */
+ /* out: DB_SUCCESS, DB_SUCCESS_LOCKED_REC,
+ DB_LOCK_WAIT, DB_DEADLOCK,
+ or DB_QUE_THR_SUSPENDED */
ulint flags, /* in: if BTR_NO_LOCKING_FLAG bit is set,
does nothing */
rec_t* rec, /* in: user record or page supremum record
@@ -5206,16 +5227,21 @@ lock_clust_rec_read_check_and_lock_alt(
mem_heap_t* tmp_heap = NULL;
ulint offsets_[REC_OFFS_NORMAL_SIZE];
ulint* offsets = offsets_;
- ulint ret;
+ ulint err;
*offsets_ = (sizeof offsets_) / sizeof *offsets_;
offsets = rec_get_offsets(rec, index, offsets,
ULINT_UNDEFINED, &tmp_heap);
- ret = lock_clust_rec_read_check_and_lock(flags, rec, index,
+ err = lock_clust_rec_read_check_and_lock(flags, rec, index,
offsets, mode, gap_mode, thr);
if (tmp_heap) {
mem_heap_free(tmp_heap);
}
- return(ret);
+
+ if (UNIV_UNLIKELY(err == DB_SUCCESS_LOCKED_REC)) {
+ err = DB_SUCCESS;
+ }
+
+ return(err);
}
diff --git a/storage/innobase/row/row0ins.c b/storage/innobase/row/row0ins.c
index 51c295b5098..9786f90fd39 100644
--- a/storage/innobase/row/row0ins.c
+++ b/storage/innobase/row/row0ins.c
@@ -1114,7 +1114,8 @@ static
ulint
row_ins_set_shared_rec_lock(
/*========================*/
- /* out: DB_SUCCESS or error code */
+ /* out: DB_SUCCESS, DB_SUCCESS_LOCKED_REC,
+ or error code */
ulint type, /* in: LOCK_ORDINARY, LOCK_GAP, or
LOCK_REC_NOT_GAP type lock */
rec_t* rec, /* in: record */
@@ -1145,7 +1146,8 @@ static
ulint
row_ins_set_exclusive_rec_lock(
/*===========================*/
- /* out: DB_SUCCESS or error code */
+ /* out: DB_SUCCESS, DB_SUCCESS_LOCKED_REC,
+ or error code */
ulint type, /* in: LOCK_ORDINARY, LOCK_GAP, or
LOCK_REC_NOT_GAP type lock */
rec_t* rec, /* in: record */
@@ -1195,9 +1197,7 @@ row_ins_check_foreign_constraint(
dict_table_t* check_table;
dict_index_t* check_index;
ulint n_fields_cmp;
- rec_t* rec;
btr_pcur_t pcur;
- ibool moved;
int cmp;
ulint err;
ulint i;
@@ -1328,12 +1328,12 @@ run_again:
/* Scan index records and check if there is a matching record */
- for (;;) {
- rec = btr_pcur_get_rec(&pcur);
+ do {
+ rec_t* rec = btr_pcur_get_rec(&pcur);
if (page_rec_is_infimum(rec)) {
- goto next_rec;
+ continue;
}
offsets = rec_get_offsets(rec, check_index,
@@ -1343,12 +1343,13 @@ run_again:
err = row_ins_set_shared_rec_lock(
LOCK_ORDINARY, rec, check_index, offsets, thr);
- if (err != DB_SUCCESS) {
-
- break;
+ switch (err) {
+ case DB_SUCCESS_LOCKED_REC:
+ case DB_SUCCESS:
+ continue;
+ default:
+ goto end_scan;
}
-
- goto next_rec;
}
cmp = cmp_dtuple_rec(entry, rec, offsets);
@@ -1359,9 +1360,12 @@ run_again:
err = row_ins_set_shared_rec_lock(
LOCK_ORDINARY, rec, check_index,
offsets, thr);
- if (err != DB_SUCCESS) {
-
+ switch (err) {
+ case DB_SUCCESS_LOCKED_REC:
+ case DB_SUCCESS:
break;
+ default:
+ goto end_scan;
}
} else {
/* Found a matching record. Lock only
@@ -1372,15 +1376,18 @@ run_again:
LOCK_REC_NOT_GAP, rec, check_index,
offsets, thr);
- if (err != DB_SUCCESS) {
-
+ switch (err) {
+ case DB_SUCCESS_LOCKED_REC:
+ case DB_SUCCESS:
break;
+ default:
+ goto end_scan;
}
if (check_ref) {
err = DB_SUCCESS;
- break;
+ goto end_scan;
} else if (foreign->type != 0) {
/* There is an ON UPDATE or ON DELETE
condition: check them in a separate
@@ -1406,7 +1413,7 @@ run_again:
err = DB_FOREIGN_DUPLICATE_KEY;
}
- break;
+ goto end_scan;
}
} else {
row_ins_foreign_report_err(
@@ -1414,48 +1421,39 @@ run_again:
thr, foreign, rec, entry);
err = DB_ROW_IS_REFERENCED;
- break;
+ goto end_scan;
}
}
- }
+ } else {
+ ut_a(cmp < 0);
- if (cmp < 0) {
err = row_ins_set_shared_rec_lock(
LOCK_GAP, rec, check_index, offsets, thr);
- if (err != DB_SUCCESS) {
-
- break;
- }
-
- if (check_ref) {
- err = DB_NO_REFERENCED_ROW;
- row_ins_foreign_report_add_err(
- trx, foreign, rec, entry);
- } else {
- err = DB_SUCCESS;
+ switch (err) {
+ case DB_SUCCESS_LOCKED_REC:
+ case DB_SUCCESS:
+ if (check_ref) {
+ err = DB_NO_REFERENCED_ROW;
+ row_ins_foreign_report_add_err(
+ trx, foreign, rec, entry);
+ } else {
+ err = DB_SUCCESS;
+ }
}
- break;
+ goto end_scan;
}
+ } while (btr_pcur_move_to_next(&pcur, &mtr));
- ut_a(cmp == 0);
-next_rec:
- moved = btr_pcur_move_to_next(&pcur, &mtr);
-
- if (!moved) {
- if (check_ref) {
- rec = btr_pcur_get_rec(&pcur);
- row_ins_foreign_report_add_err(
- trx, foreign, rec, entry);
- err = DB_NO_REFERENCED_ROW;
- } else {
- err = DB_SUCCESS;
- }
-
- break;
- }
+ if (check_ref) {
+ row_ins_foreign_report_add_err(
+ trx, foreign, btr_pcur_get_rec(&pcur), entry);
+ err = DB_NO_REFERENCED_ROW;
+ } else {
+ err = DB_SUCCESS;
}
+end_scan:
btr_pcur_close(&pcur);
mtr_commit(&mtr);
@@ -1641,10 +1639,8 @@ row_ins_scan_sec_index_for_duplicate(
ulint i;
int cmp;
ulint n_fields_cmp;
- rec_t* rec;
btr_pcur_t pcur;
ulint err = DB_SUCCESS;
- ibool moved;
unsigned allow_duplicates;
mtr_t mtr;
mem_heap_t* heap = NULL;
@@ -1680,12 +1676,12 @@ row_ins_scan_sec_index_for_duplicate(
/* Scan index records and check if there is a duplicate */
- for (;;) {
- rec = btr_pcur_get_rec(&pcur);
+ do {
+ rec_t* rec = btr_pcur_get_rec(&pcur);
if (page_rec_is_infimum(rec)) {
- goto next_rec;
+ continue;
}
offsets = rec_get_offsets(rec, index, offsets,
@@ -1706,14 +1702,18 @@ row_ins_scan_sec_index_for_duplicate(
LOCK_ORDINARY, rec, index, offsets, thr);
}
- if (err != DB_SUCCESS) {
-
+ switch (err) {
+ case DB_SUCCESS_LOCKED_REC:
+ err = DB_SUCCESS;
+ case DB_SUCCESS:
break;
+ default:
+ goto end_scan;
}
if (page_rec_is_supremum(rec)) {
- goto next_rec;
+ continue;
}
cmp = cmp_dtuple_rec(entry, rec, offsets);
@@ -1725,23 +1725,15 @@ row_ins_scan_sec_index_for_duplicate(
thr_get_trx(thr)->error_info = index;
- break;
+ goto end_scan;
}
+ } else {
+ ut_a(cmp < 0);
+ goto end_scan;
}
+ } while (btr_pcur_move_to_next(&pcur, &mtr));
- if (cmp < 0) {
- break;
- }
-
- ut_a(cmp == 0);
-next_rec:
- moved = btr_pcur_move_to_next(&pcur, &mtr);
-
- if (!moved) {
- break;
- }
- }
-
+end_scan:
if (UNIV_LIKELY_NULL(heap)) {
mem_heap_free(heap);
}
@@ -1837,7 +1829,11 @@ row_ins_duplicate_error_in_clust(
cursor->index, offsets, thr);
}
- if (err != DB_SUCCESS) {
+ switch (err) {
+ case DB_SUCCESS_LOCKED_REC:
+ case DB_SUCCESS:
+ break;
+ default:
goto func_exit;
}
@@ -1875,7 +1871,11 @@ row_ins_duplicate_error_in_clust(
cursor->index, offsets, thr);
}
- if (err != DB_SUCCESS) {
+ switch (err) {
+ case DB_SUCCESS_LOCKED_REC:
+ case DB_SUCCESS:
+ break;
+ default:
goto func_exit;
}
diff --git a/storage/innobase/row/row0mysql.c b/storage/innobase/row/row0mysql.c
index a0e0ee99775..4a834c4efc2 100644
--- a/storage/innobase/row/row0mysql.c
+++ b/storage/innobase/row/row0mysql.c
@@ -483,6 +483,7 @@ handle_new_error:
} else if (err == DB_ROW_IS_REFERENCED
|| err == DB_NO_REFERENCED_ROW
|| err == DB_CANNOT_ADD_CONSTRAINT
+ || err == DB_INTERRUPTED
|| err == DB_TOO_MANY_CONCURRENT_TRXS) {
if (savept) {
/* Roll back the latest, possibly incomplete
@@ -1454,22 +1455,20 @@ run_again:
}
/*************************************************************************
-This can only be used when srv_locks_unsafe_for_binlog is TRUE or
-this session is using a READ COMMITTED isolation level. Before
-calling this function we must use trx_reset_new_rec_lock_info() and
-trx_register_new_rec_lock() to store the information which new record locks
-really were set. This function removes a newly set lock under prebuilt->pcur,
-and also under prebuilt->clust_pcur. Currently, this is only used and tested
-in the case of an UPDATE or a DELETE statement, where the row lock is of the
-LOCK_X type.
-Thus, this implements a 'mini-rollback' that releases the latest record
-locks we set. */
+This can only be used when srv_locks_unsafe_for_binlog is TRUE or this
+session is using a READ COMMITTED or READ UNCOMMITTED isolation level.
+Before calling this function row_search_for_mysql() must have
+initialized prebuilt->new_rec_locks to store the information which new
+record locks really were set. This function removes a newly set
+clustered index record lock under prebuilt->pcur or
+prebuilt->clust_pcur. Thus, this implements a 'mini-rollback' that
+releases the latest clustered index record lock we set. */
int
row_unlock_for_mysql(
/*=================*/
/* out: error code or DB_SUCCESS */
- row_prebuilt_t* prebuilt, /* in: prebuilt struct in MySQL
+ row_prebuilt_t* prebuilt, /* in/out: prebuilt struct in MySQL
handle */
ibool has_latches_on_recs)/* TRUE if called so that we have
the latches on the records under pcur
@@ -2103,6 +2102,7 @@ row_table_add_foreign_constraints(
FOREIGN KEY (a, b) REFERENCES table2(c, d),
table2 can be written also with the
database name before it: test.table2 */
+ size_t sql_length, /* in: length of sql_string */
const char* name, /* in: table full name in the
normalized form
database_name/table_name */
@@ -2124,8 +2124,8 @@ row_table_add_foreign_constraints(
trx->dict_operation = TRUE;
- err = dict_create_foreign_constraints(trx, sql_string, name,
- reject_fks);
+ err = dict_create_foreign_constraints(trx, sql_string, sql_length,
+ name, reject_fks);
if (err == DB_SUCCESS) {
/* Check that also referencing constraints are ok */
diff --git a/storage/innobase/row/row0sel.c b/storage/innobase/row/row0sel.c
index 1d30249c53e..06a19ba7979 100644
--- a/storage/innobase/row/row0sel.c
+++ b/storage/innobase/row/row0sel.c
@@ -754,8 +754,14 @@ row_sel_get_clust_rec(
0, clust_rec, index, offsets,
node->row_lock_mode, lock_type, thr);
- if (err != DB_SUCCESS) {
-
+ switch (err) {
+ case DB_SUCCESS:
+ case DB_SUCCESS_LOCKED_REC:
+ /* Declare the variable uninitialized in Valgrind.
+ It should be set to DB_SUCCESS at func_exit. */
+ UNIV_MEM_INVALID(&err, sizeof err);
+ break;
+ default:
goto err_exit;
}
} else {
@@ -826,7 +832,8 @@ UNIV_INLINE
ulint
sel_set_rec_lock(
/*=============*/
- /* out: DB_SUCCESS or error code */
+ /* out: DB_SUCCESS, DB_SUCCESS_LOCKED_REC,
+ or error code */
rec_t* rec, /* in: record */
dict_index_t* index, /* in: index */
const ulint* offsets,/* in: rec_get_offsets(rec, index) */
@@ -1374,11 +1381,15 @@ rec_loop:
node->row_lock_mode,
lock_type, thr);
- if (err != DB_SUCCESS) {
+ switch (err) {
+ case DB_SUCCESS_LOCKED_REC:
+ err = DB_SUCCESS;
+ case DB_SUCCESS:
+ break;
+ default:
/* Note that in this case we will store in pcur
the PREDECESSOR of the record we are waiting
the lock for */
-
goto lock_wait_or_error;
}
}
@@ -1429,8 +1440,12 @@ skip_lock:
err = sel_set_rec_lock(rec, index, offsets,
node->row_lock_mode, lock_type, thr);
- if (err != DB_SUCCESS) {
-
+ switch (err) {
+ case DB_SUCCESS_LOCKED_REC:
+ err = DB_SUCCESS;
+ case DB_SUCCESS:
+ break;
+ default:
goto lock_wait_or_error;
}
}
@@ -2452,6 +2467,7 @@ row_sel_field_store_in_mysql_format(
byte* pad_ptr;
ut_ad(len != UNIV_SQL_NULL);
+ UNIV_MEM_ASSERT_RW(data, len);
if (templ->type == DATA_INT) {
/* Convert integer data from Innobase to a little-endian
@@ -2605,6 +2621,12 @@ row_sel_store_mysql_rec(
prebuilt->blob_heap = NULL;
}
+ /* init null bytes with default values as they might be
+ left uninitialized in some cases and this uninited bytes
+ might be copied into mysql record buffer that leads to
+ valgrind warnings */
+ memcpy(mysql_rec, prebuilt->default_rec, prebuilt->null_bitmap_len);
+
for (i = 0; i < prebuilt->n_template; i++) {
templ = prebuilt->mysql_template + i;
@@ -2687,6 +2709,9 @@ row_sel_store_mysql_rec(
/* MySQL assumes that the field for an SQL
NULL value is set to the default value. */
+ UNIV_MEM_ASSERT_RW(prebuilt->default_rec
+ + templ->mysql_col_offset,
+ templ->mysql_col_len);
mysql_rec[templ->mysql_null_byte_offset]
|= (byte) templ->mysql_null_bit_mask;
memcpy(mysql_rec + templ->mysql_col_offset,
@@ -2741,7 +2766,8 @@ static
ulint
row_sel_get_clust_rec_for_mysql(
/*============================*/
- /* out: DB_SUCCESS or error code */
+ /* out: DB_SUCCESS, DB_SUCCESS_LOCKED_REC,
+ or error code */
row_prebuilt_t* prebuilt,/* in: prebuilt struct in the handle */
dict_index_t* sec_index,/* in: secondary index where rec resides */
rec_t* rec, /* in: record in a non-clustered index; if
@@ -2822,6 +2848,7 @@ row_sel_get_clust_rec_for_mysql(
clust_rec = NULL;
+ err = DB_SUCCESS;
goto func_exit;
}
@@ -2836,8 +2863,11 @@ row_sel_get_clust_rec_for_mysql(
err = lock_clust_rec_read_check_and_lock(
0, clust_rec, clust_index, *offsets,
prebuilt->select_lock_type, LOCK_REC_NOT_GAP, thr);
- if (err != DB_SUCCESS) {
-
+ switch (err) {
+ case DB_SUCCESS:
+ case DB_SUCCESS_LOCKED_REC:
+ break;
+ default:
goto err_exit;
}
} else {
@@ -2896,6 +2926,8 @@ row_sel_get_clust_rec_for_mysql(
rec, sec_index, clust_rec, clust_index));
#endif
}
+
+ err = DB_SUCCESS;
}
func_exit:
@@ -2908,7 +2940,6 @@ func_exit:
btr_pcur_store_position(prebuilt->clust_pcur, mtr);
}
- err = DB_SUCCESS;
err_exit:
return(err);
}
@@ -3007,6 +3038,11 @@ row_sel_pop_cached_row_for_mysql(
for (i = 0; i < prebuilt->n_template; i++) {
templ = prebuilt->mysql_template + i;
+#if 0 /* Some of the cached_rec may legitimately be uninitialized. */
+ UNIV_MEM_ASSERT_RW(cached_rec
+ + templ->mysql_col_offset,
+ templ->mysql_col_len);
+#endif
ut_memcpy(buf + templ->mysql_col_offset,
cached_rec + templ->mysql_col_offset,
templ->mysql_col_len);
@@ -3021,6 +3057,11 @@ row_sel_pop_cached_row_for_mysql(
}
}
else {
+#if 0 /* Some of the cached_rec may legitimately be uninitialized. */
+ UNIV_MEM_ASSERT_RW(prebuilt->fetch_cache
+ [prebuilt->fetch_cache_first],
+ prebuilt->mysql_prefix_len);
+#endif
ut_memcpy(buf,
prebuilt->fetch_cache[prebuilt->fetch_cache_first],
prebuilt->mysql_prefix_len);
@@ -3070,6 +3111,8 @@ row_sel_push_cache_row_for_mysql(
}
ut_ad(prebuilt->fetch_cache_first == 0);
+ UNIV_MEM_INVALID(prebuilt->fetch_cache[prebuilt->n_fetch_cached],
+ prebuilt->mysql_row_len);
if (UNIV_UNLIKELY(!row_sel_store_mysql_rec(
prebuilt->fetch_cache[
@@ -3610,8 +3653,12 @@ shortcut_fails_too_big_rec:
prebuilt->select_lock_type,
LOCK_GAP, thr);
- if (err != DB_SUCCESS) {
-
+ switch (err) {
+ case DB_SUCCESS_LOCKED_REC:
+ err = DB_SUCCESS;
+ case DB_SUCCESS:
+ break;
+ default:
goto lock_wait_or_error;
}
}
@@ -3708,8 +3755,12 @@ rec_loop:
prebuilt->select_lock_type,
LOCK_ORDINARY, thr);
- if (err != DB_SUCCESS) {
-
+ switch (err) {
+ case DB_SUCCESS_LOCKED_REC:
+ err = DB_SUCCESS;
+ case DB_SUCCESS:
+ break;
+ default:
goto lock_wait_or_error;
}
}
@@ -3840,8 +3891,11 @@ wrong_offs:
prebuilt->select_lock_type, LOCK_GAP,
thr);
- if (err != DB_SUCCESS) {
-
+ switch (err) {
+ case DB_SUCCESS_LOCKED_REC:
+ case DB_SUCCESS:
+ break;
+ default:
goto lock_wait_or_error;
}
}
@@ -3875,8 +3929,11 @@ wrong_offs:
prebuilt->select_lock_type, LOCK_GAP,
thr);
- if (err != DB_SUCCESS) {
-
+ switch (err) {
+ case DB_SUCCESS_LOCKED_REC:
+ case DB_SUCCESS:
+ break;
+ default:
goto lock_wait_or_error;
}
}
@@ -3945,15 +4002,21 @@ no_gap_lock:
switch (err) {
rec_t* old_vers;
- case DB_SUCCESS:
+ case DB_SUCCESS_LOCKED_REC:
if (srv_locks_unsafe_for_binlog
- || trx->isolation_level <= TRX_ISO_READ_COMMITTED) {
+ || trx->isolation_level
+ <= TRX_ISO_READ_COMMITTED) {
/* Note that a record of
prebuilt->index was locked. */
prebuilt->new_rec_locks = 1;
}
+ err = DB_SUCCESS;
+ case DB_SUCCESS:
break;
case DB_LOCK_WAIT:
+ /* Never unlock rows that were part of a conflict. */
+ prebuilt->new_rec_locks = 0;
+
if (UNIV_LIKELY(prebuilt->row_read_type
!= ROW_READ_TRY_SEMI_CONSISTENT)
|| unique_search
@@ -3983,7 +4046,6 @@ no_gap_lock:
if (UNIV_LIKELY(trx->wait_lock != NULL)) {
lock_cancel_waiting_and_release(
trx->wait_lock);
- prebuilt->new_rec_locks = 0;
} else {
mutex_exit(&kernel_mutex);
@@ -3995,9 +4057,6 @@ no_gap_lock:
ULINT_UNDEFINED,
&heap);
err = DB_SUCCESS;
- /* Note that a record of
- prebuilt->index was locked. */
- prebuilt->new_rec_locks = 1;
break;
}
mutex_exit(&kernel_mutex);
@@ -4135,27 +4194,30 @@ requires_clust_rec:
err = row_sel_get_clust_rec_for_mysql(prebuilt, index, rec,
thr, &clust_rec,
&offsets, &heap, &mtr);
- if (err != DB_SUCCESS) {
+ switch (err) {
+ case DB_SUCCESS:
+ if (clust_rec == NULL) {
+ /* The record did not exist in the read view */
+ ut_ad(prebuilt->select_lock_type == LOCK_NONE);
+ goto next_rec;
+ }
+ break;
+ case DB_SUCCESS_LOCKED_REC:
+ ut_a(clust_rec != NULL);
+ if (srv_locks_unsafe_for_binlog
+ || trx->isolation_level
+ <= TRX_ISO_READ_COMMITTED) {
+ /* Note that the clustered index record
+ was locked. */
+ prebuilt->new_rec_locks = 2;
+ }
+ err = DB_SUCCESS;
+ break;
+ default:
goto lock_wait_or_error;
}
- if (clust_rec == NULL) {
- /* The record did not exist in the read view */
- ut_ad(prebuilt->select_lock_type == LOCK_NONE);
-
- goto next_rec;
- }
-
- if ((srv_locks_unsafe_for_binlog
- || trx->isolation_level <= TRX_ISO_READ_COMMITTED)
- && prebuilt->select_lock_type != LOCK_NONE) {
- /* Note that both the secondary index record
- and the clustered index record were locked. */
- ut_ad(prebuilt->new_rec_locks == 1);
- prebuilt->new_rec_locks = 2;
- }
-
if (UNIV_UNLIKELY(rec_get_deleted_flag(clust_rec, comp))) {
/* The record is delete marked: we can skip it */
diff --git a/storage/innobase/row/row0undo.c b/storage/innobase/row/row0undo.c
index f03f84ed1b0..7f31fd0060c 100644
--- a/storage/innobase/row/row0undo.c
+++ b/storage/innobase/row/row0undo.c
@@ -272,7 +272,7 @@ row_undo(
if (locked_data_dict) {
- row_mysql_lock_data_dictionary(trx);
+ row_mysql_freeze_data_dictionary(trx);
}
if (node->state == UNDO_NODE_INSERT) {
@@ -287,7 +287,7 @@ row_undo(
if (locked_data_dict) {
- row_mysql_unlock_data_dictionary(trx);
+ row_mysql_unfreeze_data_dictionary(trx);
}
/* Do some cleanup */
diff --git a/storage/innobase/srv/srv0srv.c b/storage/innobase/srv/srv0srv.c
index a2eed3f171c..5b1184fb416 100644
--- a/storage/innobase/srv/srv0srv.c
+++ b/storage/innobase/srv/srv0srv.c
@@ -1554,12 +1554,16 @@ srv_suspend_mysql_thread(
mutex_exit(&kernel_mutex);
- if (trx_is_interrupted(trx)
- || (srv_lock_wait_timeout < 100000000
- && wait_time > (double)srv_lock_wait_timeout)) {
+ if (srv_lock_wait_timeout < 100000000
+ && wait_time > (double)srv_lock_wait_timeout) {
trx->error_state = DB_LOCK_WAIT_TIMEOUT;
}
+
+ if (trx_is_interrupted(trx)) {
+
+ trx->error_state = DB_INTERRUPTED;
+ }
#else /* UNIV_HOTBACKUP */
/* This function depends on MySQL code that is not included in
InnoDB Hot Backup builds. Besides, this function should never
diff --git a/storage/innobase/srv/srv0start.c b/storage/innobase/srv/srv0start.c
index a7950473a17..9d057110d11 100644
--- a/storage/innobase/srv/srv0start.c
+++ b/storage/innobase/srv/srv0start.c
@@ -102,20 +102,6 @@ static char* srv_monitor_file_name;
#define SRV_MAX_N_PENDING_SYNC_IOS 100
-/* Avoid warnings when using purify */
-
-#ifdef HAVE_purify
-static int inno_bcmp(register const char *s1, register const char *s2,
- register uint len)
-{
- while ((len-- != 0) && (*s1++ == *s2++))
- ;
-
- return(len + 1);
-}
-#define memcmp(A,B,C) inno_bcmp((A),(B),(C))
-#endif
-
static
char*
srv_parse_megabytes(
diff --git a/storage/innobase/trx/trx0trx.c b/storage/innobase/trx/trx0trx.c
index fae479feddc..545226a5994 100644
--- a/storage/innobase/trx/trx0trx.c
+++ b/storage/innobase/trx/trx0trx.c
@@ -131,6 +131,8 @@ trx_create(
trx->mysql_thd = NULL;
trx->mysql_query_str = NULL;
+ trx->mysql_query_len = NULL;
+
trx->active_trans = 0;
trx->duplicates = 0;
@@ -936,6 +938,7 @@ trx_commit_off_kernel(
trx->undo_no = ut_dulint_zero;
trx->last_sql_stat_start.least_undo_no = ut_dulint_zero;
trx->mysql_query_str = NULL;
+ trx->mysql_query_len = NULL;
ut_ad(UT_LIST_GET_LEN(trx->wait_thrs) == 0);
ut_ad(UT_LIST_GET_LEN(trx->trx_locks) == 0);