summaryrefslogtreecommitdiff
path: root/storage/xtradb
diff options
context:
space:
mode:
authorSergei Golubchik <serg@mariadb.org>2015-09-03 12:58:41 +0200
committerSergei Golubchik <serg@mariadb.org>2015-09-03 12:58:41 +0200
commit530a6e74819ec14b5fdc42aa588b236ecb9f2fcd (patch)
treea4d45b1fd0e434c23577507364fa443226676eb5 /storage/xtradb
parent5088cbf4ed7224698678f3eaf406361c6e7db4b8 (diff)
parent4b41e3c7f33714186c97a6cc2e6d3bb93b050c61 (diff)
downloadmariadb-git-530a6e74819ec14b5fdc42aa588b236ecb9f2fcd.tar.gz
Merge branch '10.0' into 10.1
referenced_by_foreign_key2(), needed for InnoDB to compile, was taken from 10.0-galera
Diffstat (limited to 'storage/xtradb')
-rw-r--r--storage/xtradb/api/api0api.cc15
-rw-r--r--storage/xtradb/buf/buf0buf.cc277
-rw-r--r--storage/xtradb/buf/buf0checksum.cc21
-rw-r--r--storage/xtradb/buf/buf0flu.cc10
-rw-r--r--storage/xtradb/dict/dict0crea.cc143
-rw-r--r--storage/xtradb/dict/dict0dict.cc546
-rw-r--r--storage/xtradb/dict/dict0mem.cc3
-rw-r--r--storage/xtradb/fil/fil0fil.cc4
-rw-r--r--storage/xtradb/fsp/fsp0fsp.cc16
-rw-r--r--storage/xtradb/handler/ha_innodb.cc44
-rw-r--r--storage/xtradb/handler/handler0alter.cc42
-rw-r--r--storage/xtradb/include/api0api.h10
-rw-r--r--storage/xtradb/include/buf0buf.h3
-rw-r--r--storage/xtradb/include/buf0checksum.h9
-rw-r--r--storage/xtradb/include/buf0lru.h2
-rw-r--r--storage/xtradb/include/dict0crea.h12
-rw-r--r--storage/xtradb/include/dict0dict.h19
-rw-r--r--storage/xtradb/include/ha_prototypes.h20
-rw-r--r--storage/xtradb/include/os0file.h8
-rw-r--r--storage/xtradb/include/page0page.h26
-rw-r--r--storage/xtradb/include/page0types.h4
-rw-r--r--storage/xtradb/include/page0zip.h21
-rw-r--r--storage/xtradb/include/srv0srv.h1
-rw-r--r--storage/xtradb/include/univ.i4
-rw-r--r--storage/xtradb/lock/lock0lock.cc3
-rw-r--r--storage/xtradb/os/os0file.cc11
-rw-r--r--storage/xtradb/page/page0page.cc55
-rw-r--r--storage/xtradb/page/page0zip.cc122
-rw-r--r--storage/xtradb/row/row0ins.cc2
-rw-r--r--storage/xtradb/row/row0mysql.cc95
-rw-r--r--storage/xtradb/srv/srv0start.cc29
-rw-r--r--storage/xtradb/sync/sync0arr.cc8
-rw-r--r--storage/xtradb/trx/trx0sys.cc4
-rw-r--r--storage/xtradb/trx/trx0trx.cc6
34 files changed, 1245 insertions, 350 deletions
diff --git a/storage/xtradb/api/api0api.cc b/storage/xtradb/api/api0api.cc
index 8769fc47166..0fe21423232 100644
--- a/storage/xtradb/api/api0api.cc
+++ b/storage/xtradb/api/api0api.cc
@@ -595,6 +595,21 @@ ib_trx_begin(
return(static_cast<ib_trx_t>(trx));
}
+
+/*****************************************************************//**
+Check if transaction is read_only
+@return transaction read_only status */
+UNIV_INTERN
+ib_u32_t
+ib_trx_read_only(
+/*=============*/
+ ib_trx_t ib_trx) /*!< in: trx handle */
+{
+ trx_t* trx = (trx_t*) ib_trx;
+
+ return(trx->read_only);
+}
+
/*****************************************************************//**
Get the transaction's state.
@return transaction state */
diff --git a/storage/xtradb/buf/buf0buf.cc b/storage/xtradb/buf/buf0buf.cc
index 361b0783482..cf63bab0d5f 100644
--- a/storage/xtradb/buf/buf0buf.cc
+++ b/storage/xtradb/buf/buf0buf.cc
@@ -1,6 +1,6 @@
/*****************************************************************************
-Copyright (c) 1995, 2014, Oracle and/or its affiliates. All Rights Reserved.
+Copyright (c) 1995, 2015, Oracle and/or its affiliates. All Rights Reserved.
Copyright (c) 2008, Google Inc.
Copyright (c) 2013, 2015, MariaDB Corporation. All Rights Reserved.
@@ -564,6 +564,79 @@ buf_page_is_zeroes(
return(true);
}
+/** Checks if the page is in crc32 checksum format.
+@param[in] read_buf database page
+@param[in] checksum_field1 new checksum field
+@param[in] checksum_field2 old checksum field
+@return true if the page is in crc32 checksum format */
+UNIV_INLINE
+bool
+buf_page_is_checksum_valid_crc32(
+ const byte* read_buf,
+ ulint checksum_field1,
+ ulint checksum_field2)
+{
+ ib_uint32_t crc32 = buf_calc_page_crc32(read_buf);
+
+ return(checksum_field1 == crc32 && checksum_field2 == crc32);
+}
+
+/** Checks if the page is in innodb checksum format.
+@param[in] read_buf database page
+@param[in] checksum_field1 new checksum field
+@param[in] checksum_field2 old checksum field
+@return true if the page is in innodb checksum format */
+UNIV_INLINE
+bool
+buf_page_is_checksum_valid_innodb(
+ const byte* read_buf,
+ ulint checksum_field1,
+ ulint checksum_field2)
+{
+ /* There are 2 valid formulas for
+ checksum_field2 (old checksum field) which algo=innodb could have
+ written to the page:
+
+ 1. Very old versions of InnoDB only stored 8 byte lsn to the
+ start and the end of the page.
+
+ 2. Newer InnoDB versions store the old formula checksum
+ (buf_calc_page_old_checksum()). */
+
+ if (checksum_field2 != mach_read_from_4(read_buf + FIL_PAGE_LSN)
+ && checksum_field2 != buf_calc_page_old_checksum(read_buf)) {
+ return(false);
+ }
+
+ /* old field is fine, check the new field */
+
+ /* InnoDB versions < 4.0.14 and < 4.1.1 stored the space id
+ (always equal to 0), to FIL_PAGE_SPACE_OR_CHKSUM */
+
+ if (checksum_field1 != 0
+ && checksum_field1 != buf_calc_page_new_checksum(read_buf)) {
+ return(false);
+ }
+
+ return(true);
+}
+
+/** Checks if the page is in none checksum format.
+@param[in] read_buf database page
+@param[in] checksum_field1 new checksum field
+@param[in] checksum_field2 old checksum field
+@return true if the page is in none checksum format */
+UNIV_INLINE
+bool
+buf_page_is_checksum_valid_none(
+ const byte* read_buf,
+ ulint checksum_field1,
+ ulint checksum_field2)
+{
+ return(checksum_field1 == checksum_field2
+ && checksum_field1 == BUF_NO_CHECKSUM_MAGIC);
+}
+
/********************************************************************//**
Checks if a page is corrupt.
@return TRUE if corrupted */
@@ -580,8 +653,6 @@ buf_page_is_corrupted(
ulint page_encrypted = fil_page_is_encrypted(read_buf);
ulint checksum_field1;
ulint checksum_field2;
- ibool crc32_inited = FALSE;
- ib_uint32_t crc32 = ULINT32_UNDEFINED;
if (!page_encrypted && !zip_size
&& memcmp(read_buf + FIL_PAGE_LSN + 4,
@@ -664,148 +735,121 @@ buf_page_is_corrupted(
return(FALSE);
}
- switch ((srv_checksum_algorithm_t) srv_checksum_algorithm) {
- case SRV_CHECKSUM_ALGORITHM_STRICT_CRC32:
-
- crc32 = buf_calc_page_crc32(read_buf);
-
- return(checksum_field1 != crc32 || checksum_field2 != crc32);
-
- case SRV_CHECKSUM_ALGORITHM_STRICT_INNODB:
-
- return(checksum_field1
- != buf_calc_page_new_checksum(read_buf)
- || checksum_field2
- != buf_calc_page_old_checksum(read_buf));
-
- case SRV_CHECKSUM_ALGORITHM_STRICT_NONE:
+ DBUG_EXECUTE_IF("buf_page_is_corrupt_failure", return(TRUE); );
- return(checksum_field1 != BUF_NO_CHECKSUM_MAGIC
- || checksum_field2 != BUF_NO_CHECKSUM_MAGIC);
+ ulint page_no = mach_read_from_4(read_buf + FIL_PAGE_OFFSET);
+ ulint space_id = mach_read_from_4(read_buf + FIL_PAGE_SPACE_ID);
+ const srv_checksum_algorithm_t curr_algo =
+ static_cast<srv_checksum_algorithm_t>(srv_checksum_algorithm);
+ switch (curr_algo) {
case SRV_CHECKSUM_ALGORITHM_CRC32:
- case SRV_CHECKSUM_ALGORITHM_INNODB:
- /* There are 3 valid formulas for
- checksum_field2 (old checksum field):
-
- 1. Very old versions of InnoDB only stored 8 byte lsn to the
- start and the end of the page.
-
- 2. InnoDB versions before MySQL 5.6.3 store the old formula
- checksum (buf_calc_page_old_checksum()).
-
- 3. InnoDB versions 5.6.3 and newer with
- innodb_checksum_algorithm=strict_crc32|crc32 store CRC32. */
-
- /* since innodb_checksum_algorithm is not strict_* allow
- any of the algos to match for the old field */
-
- if (checksum_field2
- != mach_read_from_4(read_buf + FIL_PAGE_LSN)
- && checksum_field2 != BUF_NO_CHECKSUM_MAGIC) {
-
- /* The checksum does not match any of the
- fast to check. First check the selected algorithm
- for writing checksums because we assume that the
- chance of it matching is higher. */
-
- if (srv_checksum_algorithm
- == SRV_CHECKSUM_ALGORITHM_CRC32) {
-
- crc32 = buf_calc_page_crc32(read_buf);
- crc32_inited = TRUE;
-
- if (checksum_field2 != crc32
- && checksum_field2
- != buf_calc_page_old_checksum(read_buf)) {
+ case SRV_CHECKSUM_ALGORITHM_STRICT_CRC32:
- return(TRUE);
- }
- } else {
- ut_ad(srv_checksum_algorithm
- == SRV_CHECKSUM_ALGORITHM_INNODB);
+ if (buf_page_is_checksum_valid_crc32(read_buf,
+ checksum_field1, checksum_field2)) {
+ return(FALSE);
+ }
- if (checksum_field2
- != buf_calc_page_old_checksum(read_buf)) {
+ if (buf_page_is_checksum_valid_none(read_buf,
+ checksum_field1, checksum_field2)) {
+ if (curr_algo
+ == SRV_CHECKSUM_ALGORITHM_STRICT_CRC32) {
+ page_warn_strict_checksum(
+ curr_algo,
+ SRV_CHECKSUM_ALGORITHM_NONE,
+ space_id, page_no);
+ }
- crc32 = buf_calc_page_crc32(read_buf);
- crc32_inited = TRUE;
+ return(FALSE);
+ }
- if (checksum_field2 != crc32) {
- return(TRUE);
- }
- }
+ if (buf_page_is_checksum_valid_innodb(read_buf,
+ checksum_field1, checksum_field2)) {
+ if (curr_algo
+ == SRV_CHECKSUM_ALGORITHM_STRICT_CRC32) {
+ page_warn_strict_checksum(
+ curr_algo,
+ SRV_CHECKSUM_ALGORITHM_INNODB,
+ space_id, page_no);
}
- }
- /* old field is fine, check the new field */
+ return(FALSE);
+ }
- /* InnoDB versions < 4.0.14 and < 4.1.1 stored the space id
- (always equal to 0), to FIL_PAGE_SPACE_OR_CHKSUM */
+ return(TRUE);
- if (checksum_field1 != 0
- && checksum_field1 != BUF_NO_CHECKSUM_MAGIC) {
+ case SRV_CHECKSUM_ALGORITHM_INNODB:
+ case SRV_CHECKSUM_ALGORITHM_STRICT_INNODB:
- /* The checksum does not match any of the
- fast to check. First check the selected algorithm
- for writing checksums because we assume that the
- chance of it matching is higher. */
+ if (buf_page_is_checksum_valid_innodb(read_buf,
+ checksum_field1, checksum_field2)) {
+ return(FALSE);
+ }
- if (srv_checksum_algorithm
- == SRV_CHECKSUM_ALGORITHM_CRC32) {
+ if (buf_page_is_checksum_valid_none(read_buf,
+ checksum_field1, checksum_field2)) {
+ if (curr_algo
+ == SRV_CHECKSUM_ALGORITHM_STRICT_INNODB) {
+ page_warn_strict_checksum(
+ curr_algo,
+ SRV_CHECKSUM_ALGORITHM_NONE,
+ space_id, page_no);
+ }
- if (!crc32_inited) {
- crc32 = buf_calc_page_crc32(read_buf);
- crc32_inited = TRUE;
- }
+ return(FALSE);
+ }
- if (checksum_field1 != crc32
- && checksum_field1
- != buf_calc_page_new_checksum(read_buf)) {
+ if (buf_page_is_checksum_valid_crc32(read_buf,
+ checksum_field1, checksum_field2)) {
+ if (curr_algo
+ == SRV_CHECKSUM_ALGORITHM_STRICT_INNODB) {
+ page_warn_strict_checksum(
+ curr_algo,
+ SRV_CHECKSUM_ALGORITHM_CRC32,
+ space_id, page_no);
+ }
- return(TRUE);
- }
- } else {
- ut_ad(srv_checksum_algorithm
- == SRV_CHECKSUM_ALGORITHM_INNODB);
+ return(FALSE);
+ }
- if (checksum_field1
- != buf_calc_page_new_checksum(read_buf)) {
+ return(TRUE);
- if (!crc32_inited) {
- crc32 = buf_calc_page_crc32(
- read_buf);
- crc32_inited = TRUE;
- }
+ case SRV_CHECKSUM_ALGORITHM_STRICT_NONE:
- if (checksum_field1 != crc32) {
- return(TRUE);
- }
- }
- }
+ if (buf_page_is_checksum_valid_none(read_buf,
+ checksum_field1, checksum_field2)) {
+ return(FALSE);
}
- /* If CRC32 is stored in at least one of the fields, then the
- other field must also be CRC32 */
- if (crc32_inited
- && ((checksum_field1 == crc32
- && checksum_field2 != crc32)
- || (checksum_field1 != crc32
- && checksum_field2 == crc32))) {
+ if (buf_page_is_checksum_valid_crc32(read_buf,
+ checksum_field1, checksum_field2)) {
+ page_warn_strict_checksum(
+ curr_algo,
+ SRV_CHECKSUM_ALGORITHM_CRC32,
+ space_id, page_no);
+ return(FALSE);
+ }
- return(TRUE);
+ if (buf_page_is_checksum_valid_innodb(read_buf,
+ checksum_field1, checksum_field2)) {
+ page_warn_strict_checksum(
+ curr_algo,
+ SRV_CHECKSUM_ALGORITHM_INNODB,
+ space_id, page_no);
+ return(FALSE);
}
- break;
+ return(TRUE);
+
case SRV_CHECKSUM_ALGORITHM_NONE:
/* should have returned FALSE earlier */
- ut_error;
+ break;
/* no default so the compiler will emit a warning if new enum
is added and not handled here */
}
- DBUG_EXECUTE_IF("buf_page_is_corrupt_failure", return(TRUE); );
-
+ ut_error;
return(FALSE);
}
@@ -1817,6 +1861,9 @@ page_found:
goto page_found;
}
+ /* The maximum number of purge threads should never exceed
+ BUF_POOL_WATCH_SIZE. So there is no way for purge thread
+ instance to hold a watch when setting another watch. */
for (i = 0; i < BUF_POOL_WATCH_SIZE; i++) {
bpage = &buf_pool->watch[i];
diff --git a/storage/xtradb/buf/buf0checksum.cc b/storage/xtradb/buf/buf0checksum.cc
index 451fef2f82e..01b646a78e0 100644
--- a/storage/xtradb/buf/buf0checksum.cc
+++ b/storage/xtradb/buf/buf0checksum.cc
@@ -1,6 +1,6 @@
/*****************************************************************************
-Copyright (c) 1995, 2011, Oracle and/or its affiliates. All Rights Reserved.
+Copyright (c) 1995, 2015, Oracle and/or its affiliates. All Rights Reserved.
This program is free software; you can redistribute it and/or modify it under
the terms of the GNU General Public License as published by the Free Software
@@ -27,11 +27,13 @@ Created Aug 11, 2011 Vasil Dimov
#include "fil0fil.h" /* FIL_* */
#include "ut0crc32.h" /* ut_crc32() */
#include "ut0rnd.h" /* ut_fold_binary() */
+#include "buf0types.h"
#ifndef UNIV_INNOCHECKSUM
#include "srv0srv.h" /* SRV_CHECKSUM_* */
-#include "buf0types.h"
+
+#endif /* !UNIV_INNOCHECKSUM */
/** the macro MYSQL_SYSVAR_ENUM() requires "long unsigned int" and if we
use srv_checksum_algorithm_t here then we get a compiler error:
@@ -39,8 +41,6 @@ ha_innodb.cc:12251: error: cannot convert 'srv_checksum_algorithm_t*' to
'long unsigned int*' in initialization */
UNIV_INTERN ulong srv_checksum_algorithm = SRV_CHECKSUM_ALGORITHM_INNODB;
-#endif /* !UNIV_INNOCHECKSUM */
-
/********************************************************************//**
Calculates a page CRC32 which is stored to the page when it is written
to a file. Note that we must be careful to calculate the same value on
@@ -127,8 +127,6 @@ buf_calc_page_old_checksum(
return(checksum);
}
-#ifndef UNIV_INNOCHECKSUM
-
/********************************************************************//**
Return a printable string describing the checksum algorithm.
@return algorithm name */
@@ -140,18 +138,19 @@ buf_checksum_algorithm_name(
{
switch (algo) {
case SRV_CHECKSUM_ALGORITHM_CRC32:
- case SRV_CHECKSUM_ALGORITHM_STRICT_CRC32:
return("crc32");
+ case SRV_CHECKSUM_ALGORITHM_STRICT_CRC32:
+ return("strict_crc32");
case SRV_CHECKSUM_ALGORITHM_INNODB:
- case SRV_CHECKSUM_ALGORITHM_STRICT_INNODB:
return("innodb");
+ case SRV_CHECKSUM_ALGORITHM_STRICT_INNODB:
+ return("strict_innodb");
case SRV_CHECKSUM_ALGORITHM_NONE:
- case SRV_CHECKSUM_ALGORITHM_STRICT_NONE:
return("none");
+ case SRV_CHECKSUM_ALGORITHM_STRICT_NONE:
+ return("strict_none");
}
ut_error;
return(NULL);
}
-
-#endif /* !UNIV_INNOCHECKSUM */
diff --git a/storage/xtradb/buf/buf0flu.cc b/storage/xtradb/buf/buf0flu.cc
index 6443043310b..c891e53381a 100644
--- a/storage/xtradb/buf/buf0flu.cc
+++ b/storage/xtradb/buf/buf0flu.cc
@@ -1,8 +1,8 @@
/*****************************************************************************
-Copyright (c) 1995, 2013, Oracle and/or its affiliates. All Rights Reserved.
-Copyright (c) 2013, 2014, SkySQL Ab. All Rights Reserved.
-Copyright (c) 2013, 2014, Fusion-io. All Rights Reserved.
+Copyright (c) 1995, 2013, Oracle and/or its affiliates
+Copyright (c) 2013, 2015, SkySQL Ab
+Copyright (c) 2013, 2014, Fusion-io
This program is free software; you can redistribute it and/or modify it under
the terms of the GNU General Public License as published by the Free Software
@@ -932,11 +932,11 @@ buf_flush_write_block_low(
case BUF_BLOCK_ZIP_DIRTY:
frame = bpage->zip.data;
- ut_a(page_zip_verify_checksum(frame, zip_size));
-
mach_write_to_8(frame + FIL_PAGE_LSN,
bpage->newest_modification);
memset(frame + FIL_PAGE_FILE_FLUSH_LSN_OR_KEY_VERSION, 0, 8);
+
+ ut_a(page_zip_verify_checksum(frame, zip_size));
break;
case BUF_BLOCK_FILE_PAGE:
frame = bpage->zip.data;
diff --git a/storage/xtradb/dict/dict0crea.cc b/storage/xtradb/dict/dict0crea.cc
index 36a30cb75b7..fec4e27f058 100644
--- a/storage/xtradb/dict/dict0crea.cc
+++ b/storage/xtradb/dict/dict0crea.cc
@@ -1566,12 +1566,111 @@ dict_create_add_foreign_field_to_dictionary(
}
/********************************************************************//**
+Construct foreign key constraint defintion from data dictionary information.
+*/
+UNIV_INTERN
+char*
+dict_foreign_def_get(
+/*=================*/
+ dict_foreign_t* foreign,/*!< in: foreign */
+ trx_t* trx) /*!< in: trx */
+{
+ char* fk_def = (char *)mem_heap_alloc(foreign->heap, 4*1024);
+ const char* tbname;
+ char tablebuf[MAX_TABLE_NAME_LEN + 1] = "";
+ int i;
+ char* bufend;
+
+ tbname = dict_remove_db_name(foreign->id);
+ bufend = innobase_convert_name(tablebuf, MAX_TABLE_NAME_LEN,
+ tbname, strlen(tbname), trx->mysql_thd, FALSE);
+ tablebuf[bufend - tablebuf] = '\0';
+
+ sprintf(fk_def,
+ (char *)"CONSTRAINT %s FOREIGN KEY (", (char *)tablebuf);
+
+ for(i = 0; i < foreign->n_fields; i++) {
+ char buf[MAX_TABLE_NAME_LEN + 1] = "";
+ innobase_convert_name(buf, MAX_TABLE_NAME_LEN,
+ foreign->foreign_col_names[i],
+ strlen(foreign->foreign_col_names[i]),
+ trx->mysql_thd, FALSE);
+ strcat(fk_def, buf);
+ if (i < foreign->n_fields-1) {
+ strcat(fk_def, (char *)",");
+ }
+ }
+
+ strcat(fk_def,(char *)") REFERENCES ");
+
+ bufend = innobase_convert_name(tablebuf, MAX_TABLE_NAME_LEN,
+ foreign->referenced_table_name,
+ strlen(foreign->referenced_table_name),
+ trx->mysql_thd, TRUE);
+ tablebuf[bufend - tablebuf] = '\0';
+
+ strcat(fk_def, tablebuf);
+ strcat(fk_def, " (");
+
+ for(i = 0; i < foreign->n_fields; i++) {
+ char buf[MAX_TABLE_NAME_LEN + 1] = "";
+ bufend = innobase_convert_name(buf, MAX_TABLE_NAME_LEN,
+ foreign->referenced_col_names[i],
+ strlen(foreign->referenced_col_names[i]),
+ trx->mysql_thd, FALSE);
+ buf[bufend - buf] = '\0';
+ strcat(fk_def, buf);
+ if (i < foreign->n_fields-1) {
+ strcat(fk_def, (char *)",");
+ }
+ }
+ strcat(fk_def, (char *)")");
+
+ return fk_def;
+}
+
+/********************************************************************//**
+Convert foreign key column names from data dictionary to SQL-layer.
+*/
+static
+void
+dict_foreign_def_get_fields(
+/*========================*/
+ dict_foreign_t* foreign,/*!< in: foreign */
+ trx_t* trx, /*!< in: trx */
+ char** field, /*!< out: foreign column */
+ char** field2, /*!< out: referenced column */
+ int col_no) /*!< in: column number */
+{
+ char* bufend;
+ char* fieldbuf = (char *)mem_heap_alloc(foreign->heap, MAX_TABLE_NAME_LEN+1);
+ char* fieldbuf2 = (char *)mem_heap_alloc(foreign->heap, MAX_TABLE_NAME_LEN+1);
+
+ bufend = innobase_convert_name(fieldbuf, MAX_TABLE_NAME_LEN,
+ foreign->foreign_col_names[col_no],
+ strlen(foreign->foreign_col_names[col_no]),
+ trx->mysql_thd, FALSE);
+
+ fieldbuf[bufend - fieldbuf] = '\0';
+
+ bufend = innobase_convert_name(fieldbuf2, MAX_TABLE_NAME_LEN,
+ foreign->referenced_col_names[col_no],
+ strlen(foreign->referenced_col_names[col_no]),
+ trx->mysql_thd, FALSE);
+
+ fieldbuf2[bufend - fieldbuf2] = '\0';
+ *field = fieldbuf;
+ *field2 = fieldbuf2;
+}
+
+/********************************************************************//**
Add a foreign key definition to the data dictionary tables.
@return error code or DB_SUCCESS */
UNIV_INTERN
dberr_t
dict_create_add_foreign_to_dictionary(
/*==================================*/
+ dict_table_t* table,
const char* name, /*!< in: table name */
const dict_foreign_t* foreign,/*!< in: foreign key */
trx_t* trx) /*!< in/out: dictionary transaction */
@@ -1598,6 +1697,28 @@ dict_create_add_foreign_to_dictionary(
, name, foreign->id, trx);
if (error != DB_SUCCESS) {
+ if (error == DB_DUPLICATE_KEY) {
+ char buf[MAX_TABLE_NAME_LEN + 1] = "";
+ char tablename[MAX_TABLE_NAME_LEN + 1] = "";
+ char* fk_def;
+
+ innobase_convert_name(tablename, MAX_TABLE_NAME_LEN,
+ table->name, strlen(table->name),
+ trx->mysql_thd, TRUE);
+
+ innobase_convert_name(buf, MAX_TABLE_NAME_LEN,
+ foreign->id, strlen(foreign->id), trx->mysql_thd, FALSE);
+
+ fk_def = dict_foreign_def_get((dict_foreign_t*)foreign, trx);
+
+ ib_push_warning(trx, error,
+ "Create or Alter table %s with foreign key constraint"
+ " failed. Foreign key constraint %s"
+ " already exists on data dictionary."
+ " Foreign key constraint names need to be unique in database."
+ " Error in foreign key definition: %s.",
+ tablename, buf, fk_def);
+ }
return(error);
}
@@ -1607,6 +1728,26 @@ dict_create_add_foreign_to_dictionary(
i, name, foreign, trx);
if (error != DB_SUCCESS) {
+ char buf[MAX_TABLE_NAME_LEN + 1] = "";
+ char tablename[MAX_TABLE_NAME_LEN + 1] = "";
+ char* field=NULL;
+ char* field2=NULL;
+ char* fk_def;
+
+ innobase_convert_name(tablename, MAX_TABLE_NAME_LEN,
+ table->name, strlen(table->name),
+ trx->mysql_thd, TRUE);
+ innobase_convert_name(buf, MAX_TABLE_NAME_LEN,
+ foreign->id, strlen(foreign->id), trx->mysql_thd, FALSE);
+ fk_def = dict_foreign_def_get((dict_foreign_t*)foreign, trx);
+ dict_foreign_def_get_fields((dict_foreign_t*)foreign, trx, &field, &field2, i);
+
+ ib_push_warning(trx, error,
+ "Create or Alter table %s with foreign key constraint"
+ " failed. Error adding foreign key constraint name %s"
+ " fields %s or %s to the dictionary."
+ " Error in foreign key definition: %s.",
+ tablename, buf, i+1, fk_def);
return(error);
}
@@ -1653,7 +1794,7 @@ dict_create_add_foreigns_to_dictionary(
foreign = *it;
ut_ad(foreign->id != NULL);
- error = dict_create_add_foreign_to_dictionary(table->name,
+ error = dict_create_add_foreign_to_dictionary((dict_table_t*)table, table->name,
foreign, trx);
if (error != DB_SUCCESS) {
diff --git a/storage/xtradb/dict/dict0dict.cc b/storage/xtradb/dict/dict0dict.cc
index 811d737e6bf..0e1906a1827 100644
--- a/storage/xtradb/dict/dict0dict.cc
+++ b/storage/xtradb/dict/dict0dict.cc
@@ -3280,6 +3280,11 @@ dict_index_build_internal_fts(
}
/*====================== FOREIGN KEY PROCESSING ========================*/
+#define DB_FOREIGN_KEY_IS_PREFIX_INDEX 200
+#define DB_FOREIGN_KEY_COL_NOT_NULL 201
+#define DB_FOREIGN_KEY_COLS_NOT_EQUAL 202
+#define DB_FOREIGN_KEY_INDEX_NOT_FOUND 203
+
/*********************************************************************//**
Checks if a table is referenced by foreign keys.
@return TRUE if table is referenced by a foreign key */
@@ -3434,15 +3439,26 @@ dict_foreign_find_index(
/*!< in: whether to check
charsets. only has an effect
if types_idx != NULL */
- ulint check_null)
+ ulint check_null,
/*!< in: nonzero if none of
the columns must be declared
NOT NULL */
+ ulint* error, /*!< out: error code */
+ ulint* err_col_no,
+ /*!< out: column number where
+ error happened */
+ dict_index_t** err_index)
+ /*!< out: index where error
+ happened */
{
dict_index_t* index;
ut_ad(mutex_own(&dict_sys->mutex));
+ if (error) {
+ *error = DB_FOREIGN_KEY_INDEX_NOT_FOUND;
+ }
+
index = dict_table_get_first_index(table);
while (index != NULL) {
@@ -3452,7 +3468,12 @@ dict_foreign_find_index(
&& dict_foreign_qualify_index(
table, col_names, columns, n_cols,
index, types_idx,
- check_charsets, check_null)) {
+ check_charsets, check_null,
+ error, err_col_no,err_index)) {
+ if (error) {
+ *error = DB_SUCCESS;
+ }
+
return(index);
}
@@ -3481,7 +3502,7 @@ wsrep_dict_foreign_find_index(
{
return dict_foreign_find_index(
table, col_names, columns, n_cols, types_idx, check_charsets,
- check_null);
+ check_null, NULL, NULL, NULL);
}
#endif /* WITH_WSREP */
/**********************************************************************//**
@@ -3583,7 +3604,7 @@ dict_foreign_add_to_cache(
ref_table, NULL,
for_in_cache->referenced_col_names,
for_in_cache->n_fields, for_in_cache->foreign_index,
- check_charsets, false);
+ check_charsets, false, NULL, NULL, NULL);
if (index == NULL
&& !(ignore_err & DICT_ERR_IGNORE_FK_NOKEY)) {
@@ -3615,6 +3636,10 @@ dict_foreign_add_to_cache(
}
if (for_table && !for_in_cache->foreign_table) {
+ ulint index_error;
+ ulint err_col;
+ dict_index_t *err_index=NULL;
+
index = dict_foreign_find_index(
for_table, col_names,
for_in_cache->foreign_col_names,
@@ -3622,7 +3647,8 @@ dict_foreign_add_to_cache(
for_in_cache->referenced_index, check_charsets,
for_in_cache->type
& (DICT_FOREIGN_ON_DELETE_SET_NULL
- | DICT_FOREIGN_ON_UPDATE_SET_NULL));
+ | DICT_FOREIGN_ON_UPDATE_SET_NULL),
+ &index_error, &err_col, &err_index);
if (index == NULL
&& !(ignore_err & DICT_ERR_IGNORE_FK_NOKEY)) {
@@ -4282,6 +4308,8 @@ static
void
dict_foreign_report_syntax_err(
/*===========================*/
+ const char* fmt, /*!< in: syntax err msg */
+ const char* oper, /*!< in: operation */
const char* name, /*!< in: table name */
const char* start_of_latest_foreign,
/*!< in: start of the foreign key clause
@@ -4294,12 +4322,102 @@ dict_foreign_report_syntax_err(
mutex_enter(&dict_foreign_err_mutex);
dict_foreign_error_report_low(ef, name);
- fprintf(ef, "%s:\nSyntax error close to:\n%s\n",
- start_of_latest_foreign, ptr);
+ fprintf(ef, fmt, oper, name, start_of_latest_foreign, ptr);
mutex_exit(&dict_foreign_err_mutex);
}
/*********************************************************************//**
+Push warning message to SQL-layer based on foreign key constraint
+index match error. */
+static
+void
+dict_foreign_push_index_error(
+/*==========================*/
+ trx_t* trx, /*!< in: trx */
+ const char* operation, /*!< in: operation create or alter
+ */
+ const char* create_name, /*!< in: table name in create or
+ alter table */
+ const char* latest_foreign, /*!< in: start of latest foreign key
+ constraint name */
+ const char** columns, /*!< in: foreign key columns */
+ ulint index_error, /*!< in: error code */
+ ulint err_col, /*!< in: column where error happened
+ */
+ dict_index_t* err_index, /*!< in: index where error happened
+ */
+ dict_table_t* table, /*!< in: table */
+ FILE* ef) /*!< in: output stream */
+{
+ switch (index_error) {
+ case DB_FOREIGN_KEY_INDEX_NOT_FOUND: {
+ fprintf(ef,
+ "%s table '%s' with foreign key constraint"
+ " failed. There is no index in the referenced"
+ " table where the referenced columns appear"
+ " as the first columns. Error close to %s.\n",
+ operation, create_name, latest_foreign);
+ ib_push_warning(trx, DB_CANNOT_ADD_CONSTRAINT,
+ "%s table '%s' with foreign key constraint"
+ " failed. There is no index in the referenced"
+ " table where the referenced columns appear"
+ " as the first columns. Error close to %s.",
+ operation, create_name, latest_foreign);
+ break;
+ }
+ case DB_FOREIGN_KEY_IS_PREFIX_INDEX: {
+ fprintf(ef,
+ "%s table '%s' with foreign key constraint"
+ " failed. There is only prefix index in the referenced"
+ " table where the referenced columns appear"
+ " as the first columns. Error close to %s.\n",
+ operation, create_name, latest_foreign);
+ ib_push_warning(trx, DB_CANNOT_ADD_CONSTRAINT,
+ "%s table '%s' with foreign key constraint"
+ " failed. There is only prefix index in the referenced"
+ " table where the referenced columns appear"
+ " as the first columns. Error close to %s.",
+ operation, create_name, latest_foreign);
+ break;
+ }
+ case DB_FOREIGN_KEY_COL_NOT_NULL: {
+ fprintf(ef,
+ "%s table %s with foreign key constraint"
+ " failed. You have defined a SET NULL condition but "
+ "field %s on index is defined as NOT NULL close to %s\n",
+ operation, create_name, columns[err_col], latest_foreign);
+ ib_push_warning(trx, DB_CANNOT_ADD_CONSTRAINT,
+ "%s table %s with foreign key constraint"
+ " failed. You have defined a SET NULL condition but "
+ "field %s on index is defined as NOT NULL close to %s",
+ operation, create_name, columns[err_col], latest_foreign);
+ break;
+ }
+ case DB_FOREIGN_KEY_COLS_NOT_EQUAL: {
+ dict_field_t* field;
+ const char* col_name;
+ field = dict_index_get_nth_field(err_index, err_col);
+
+ col_name = dict_table_get_col_name(
+ table, dict_col_get_no(field->col));
+ fprintf(ef,
+ "%s table %s with foreign key constraint"
+ " failed. Field type or character set for column %s "
+ "does not mach referenced column %s close to %s\n",
+ operation, create_name, columns[err_col], col_name, latest_foreign);
+ ib_push_warning(trx, DB_CANNOT_ADD_CONSTRAINT,
+ "%s table %s with foreign key constraint"
+ " failed. Field type or character set for column %s "
+ "does not mach referenced column %s close to %s",
+ operation, create_name, columns[err_col], col_name, latest_foreign);
+ break;
+ }
+ default:
+ ut_error;
+ }
+}
+
+/*********************************************************************//**
Scans a table create SQL string and adds to the data dictionary the foreign
key constraints declared in the string. This function should be called after
the indexes for a table have been created. Each foreign key constraint must
@@ -4327,16 +4445,21 @@ dict_create_foreign_constraints_low(
DB_CANNOT_ADD_CONSTRAINT if any foreign
keys are found. */
{
- dict_table_t* table;
- dict_table_t* referenced_table;
- dict_table_t* table_to_alter;
+ dict_table_t* table = NULL;
+ dict_table_t* referenced_table = NULL;
+ dict_table_t* table_to_alter = NULL;
+ dict_table_t* table_to_create = NULL;
ulint highest_id_so_far = 0;
ulint number = 1;
- dict_index_t* index;
- dict_foreign_t* foreign;
+ dict_index_t* index = NULL;
+ dict_foreign_t* foreign = NULL;
const char* ptr = sql_string;
const char* start_of_latest_foreign = sql_string;
+ const char* start_of_latest_set = NULL;
FILE* ef = dict_foreign_err_file;
+ ulint index_error = DB_SUCCESS;
+ dict_index_t* err_index = NULL;
+ ulint err_col;
const char* constraint_name;
ibool success;
dberr_t error;
@@ -4349,37 +4472,80 @@ dict_create_foreign_constraints_low(
ulint n_on_updates;
const dict_col_t*columns[500];
const char* column_names[500];
+ const char* ref_column_names[500];
const char* referenced_table_name;
dict_foreign_set local_fk_set;
dict_foreign_set_free local_fk_set_free(local_fk_set);
+ const char* create_table_name;
+ const char* orig;
+ char create_name[MAX_TABLE_NAME_LEN + 1];
+ char operation[8];
ut_ad(!srv_read_only_mode);
ut_ad(mutex_own(&(dict_sys->mutex)));
table = dict_table_get_low(name);
+ /* First check if we are actually doing an ALTER TABLE, and in that
+ case look for the table being altered */
+ orig = ptr;
+ ptr = dict_accept(cs, ptr, "ALTER", &success);
+
+ strcpy((char *)operation, success ? "Alter " : "Create ");
+
+ if (!success) {
+ orig = ptr;
+ ptr = dict_scan_to(ptr, "CREATE");
+ ptr = dict_scan_to(ptr, "TABLE");
+ ptr = dict_accept(cs, ptr, "TABLE", &success);
+
+ if (success) {
+ ptr = dict_scan_table_name(cs, ptr, &table_to_create, name,
+ &success, heap, &create_table_name);
+ }
+
+ if (success) {
+ char *bufend;
+ bufend = innobase_convert_name((char *)create_name, MAX_TABLE_NAME_LEN,
+ create_table_name, strlen(create_table_name),
+ trx->mysql_thd, TRUE);
+ create_name[bufend-create_name]='\0';
+ ptr = orig;
+ } else {
+ char *bufend;
+ ptr = orig;
+ bufend = innobase_convert_name((char *)create_name, MAX_TABLE_NAME_LEN,
+ name, strlen(name), trx->mysql_thd, TRUE);
+ create_name[bufend-create_name]='\0';
+ }
+
+ goto loop;
+ }
if (table == NULL) {
mutex_enter(&dict_foreign_err_mutex);
- dict_foreign_error_report_low(ef, name);
- fprintf(ef,
- "Cannot find the table in the internal"
- " data dictionary of InnoDB.\n"
- "Create table statement:\n%s\n", sql_string);
+ dict_foreign_error_report_low(ef, create_name);
+ dict_foreign_error_report_low(ef, create_name);
+ fprintf(ef, "%s table %s with foreign key constraint"
+ " failed. Table %s not found from data dictionary."
+ " Error close to %s.\n",
+ operation, create_name, create_name, start_of_latest_foreign);
mutex_exit(&dict_foreign_err_mutex);
+ ib_push_warning(trx, DB_ERROR,
+ "%s table %s with foreign key constraint"
+ " failed. Table %s not found from data dictionary."
+ " Error close to %s.",
+ operation, create_name, create_name, start_of_latest_foreign);
return(DB_ERROR);
}
- /* First check if we are actually doing an ALTER TABLE, and in that
- case look for the table being altered */
-
- ptr = dict_accept(cs, ptr, "ALTER", &success);
-
+ /* If not alter table jump to loop */
if (!success) {
goto loop;
}
+ orig = ptr;
ptr = dict_accept(cs, ptr, "TABLE", &success);
if (!success) {
@@ -4389,13 +4555,40 @@ dict_create_foreign_constraints_low(
/* We are doing an ALTER TABLE: scan the table name we are altering */
+ orig = ptr;
ptr = dict_scan_table_name(cs, ptr, &table_to_alter, name,
&success, heap, &referenced_table_name);
+
+ if (table_to_alter) {
+ char *bufend;
+ bufend = innobase_convert_name((char *)create_name, MAX_TABLE_NAME_LEN,
+ table_to_alter->name, strlen(table_to_alter->name),
+ trx->mysql_thd, TRUE);
+ create_name[bufend-create_name]='\0';
+ } else {
+ char *bufend;
+ bufend = innobase_convert_name((char *)create_name, MAX_TABLE_NAME_LEN,
+ referenced_table_name, strlen(referenced_table_name),
+ trx->mysql_thd, TRUE);
+ create_name[bufend-create_name]='\0';
+
+ }
+
if (!success) {
- fprintf(stderr,
- "InnoDB: Error: could not find"
- " the table being ALTERED in:\n%s\n",
- sql_string);
+ mutex_enter(&dict_foreign_err_mutex);
+ dict_foreign_error_report_low(ef, create_name);
+ fprintf(ef,
+ "%s table %s with foreign key constraint"
+ " failed. Table %s not found from data dictionary."
+ " Error close to %s.\n",
+ operation, create_name, create_name, orig);
+ mutex_exit(&dict_foreign_err_mutex);
+
+ ib_push_warning(trx, DB_ERROR,
+ "%s table %s with foreign key constraint"
+ " failed. Table %s not found from data dictionary."
+ " Error close to %s.",
+ operation, create_name, create_name, orig);
return(DB_ERROR);
}
@@ -4432,6 +4625,7 @@ loop:
of the constraint to system tables. */
ptr = ptr1;
+ orig = ptr;
ptr = dict_accept(cs, ptr, "CONSTRAINT", &success);
ut_a(success);
@@ -4462,6 +4656,19 @@ loop:
if so, immediately reject the command if the table is a
temporary one. For now, this kludge will work. */
if (reject_fks && !local_fk_set.empty()) {
+ mutex_enter(&dict_foreign_err_mutex);
+ dict_foreign_error_report_low(ef, create_name);
+ fprintf(ef, "%s table %s with foreign key constraint"
+ " failed. Temporary tables can't have foreign key constraints."
+ " Error close to %s.\n",
+ operation, create_name, start_of_latest_foreign);
+ mutex_exit(&dict_foreign_err_mutex);
+
+ ib_push_warning(trx, DB_CANNOT_ADD_CONSTRAINT,
+ "%s table %s with foreign key constraint"
+ " failed. Temporary tables can't have foreign key constraints."
+ " Error close to %s.",
+ operation, create_name, start_of_latest_foreign);
return(DB_CANNOT_ADD_CONSTRAINT);
}
@@ -4487,6 +4694,7 @@ loop:
start_of_latest_foreign = ptr;
+ orig = ptr;
ptr = dict_accept(cs, ptr, "FOREIGN", &success);
if (!success) {
@@ -4497,6 +4705,7 @@ loop:
goto loop;
}
+ orig = ptr;
ptr = dict_accept(cs, ptr, "KEY", &success);
if (!success) {
@@ -4522,6 +4731,7 @@ loop:
}
}
+ orig = ptr;
ptr = dict_accept(cs, ptr, "(", &success);
if (!success) {
@@ -4531,8 +4741,17 @@ loop:
ptr = dict_skip_word(cs, ptr, &success);
if (!success) {
dict_foreign_report_syntax_err(
- name, start_of_latest_foreign, ptr);
- return(DB_CANNOT_ADD_CONSTRAINT);
+ "%s table %s with foreign key constraint"
+ " failed. Foreign key constraint parse error in %s"
+ " close to %s.\n",
+ operation, create_name, start_of_latest_foreign, orig);
+
+ ib_push_warning(trx, DB_CANNOT_ADD_CONSTRAINT,
+ "%s table %s with foreign key constraint"
+ " failed. Foreign key constraint parse error in %s"
+ " close to %s.",
+ operation, create_name, start_of_latest_foreign, orig);
+ return(DB_CANNOT_ADD_CONSTRAINT);
}
}
else {
@@ -4559,15 +4778,26 @@ loop:
/* Scan the columns in the first list */
col_loop1:
ut_a(i < (sizeof column_names) / sizeof *column_names);
+ orig = ptr;
ptr = dict_scan_col(cs, ptr, &success, table, columns + i,
heap, column_names + i);
if (!success) {
mutex_enter(&dict_foreign_err_mutex);
- dict_foreign_error_report_low(ef, name);
- fprintf(ef, "%s:\nCannot resolve column name close to:\n%s\n",
- start_of_latest_foreign, ptr);
+ dict_foreign_error_report_low(ef, create_name);
+ fprintf(ef,
+ "%s table %s with foreign key constraint"
+ " failed. Foreign key constraint parse error in %s"
+ " close to %s.\n",
+ operation, create_name, start_of_latest_foreign, orig);
+
mutex_exit(&dict_foreign_err_mutex);
+ ib_push_warning(trx, DB_CANNOT_ADD_CONSTRAINT,
+ "%s table %s with foreign key constraint"
+ " failed. Foreign key constraint parse error in %s"
+ " close to %s.",
+ operation, create_name, start_of_latest_foreign, orig);
+
return(DB_CANNOT_ADD_CONSTRAINT);
}
@@ -4579,11 +4809,22 @@ col_loop1:
goto col_loop1;
}
+ orig = ptr;
ptr = dict_accept(cs, ptr, ")", &success);
if (!success) {
dict_foreign_report_syntax_err(
- name, start_of_latest_foreign, ptr);
+ "%s table %s with foreign key constraint"
+ " failed. Foreign key constraint parse error in %s"
+ " close to %s.\n",
+ operation, create_name, start_of_latest_foreign, orig);
+
+ ib_push_warning(trx, DB_CANNOT_ADD_CONSTRAINT,
+ "%s table %s with foreign key constraint"
+ " failed. Foreign key constraint parse error in %s"
+ " close to %s.",
+ operation, create_name, start_of_latest_foreign, orig);
+
return(DB_CANNOT_ADD_CONSTRAINT);
}
@@ -4594,27 +4835,41 @@ col_loop1:
set to 0 */
index = dict_foreign_find_index(
- table, NULL, column_names, i, NULL, TRUE, FALSE);
+ table, NULL, column_names, i,
+ NULL, TRUE, FALSE, &index_error, &err_col, &err_index);
if (!index) {
mutex_enter(&dict_foreign_err_mutex);
- dict_foreign_error_report_low(ef, name);
+ dict_foreign_error_report_low(ef, create_name);
fputs("There is no index in table ", ef);
- ut_print_name(ef, NULL, TRUE, name);
+ ut_print_name(ef, NULL, TRUE, create_name);
fprintf(ef, " where the columns appear\n"
"as the first columns. Constraint:\n%s\n"
"See " REFMAN "innodb-foreign-key-constraints.html\n"
"for correct foreign key definition.\n",
start_of_latest_foreign);
- mutex_exit(&dict_foreign_err_mutex);
+ dict_foreign_push_index_error(trx, operation, create_name, start_of_latest_foreign,
+ column_names, index_error, err_col, err_index, table, ef);
- return(DB_CHILD_NO_INDEX);
+ mutex_exit(&dict_foreign_err_mutex);
+ return(DB_CANNOT_ADD_CONSTRAINT);
}
+
+ orig = ptr;
ptr = dict_accept(cs, ptr, "REFERENCES", &success);
if (!success || !my_isspace(cs, *ptr)) {
dict_foreign_report_syntax_err(
- name, start_of_latest_foreign, ptr);
+ "%s table %s with foreign key constraint"
+ " failed. Foreign key constraint parse error in %s"
+ " close to %s.\n",
+ operation, create_name, start_of_latest_foreign, orig);
+
+ ib_push_warning(trx, DB_CANNOT_ADD_CONSTRAINT,
+ "%s table %s with foreign key constraint"
+ " failed. Foreign key constraint parse error in %s"
+ " close to %s.",
+ operation, create_name, start_of_latest_foreign, orig);
return(DB_CANNOT_ADD_CONSTRAINT);
}
@@ -4683,21 +4938,46 @@ col_loop1:
checking of foreign key constraints! */
if (!success || (!referenced_table && trx->check_foreigns)) {
+ char buf[MAX_TABLE_NAME_LEN + 1] = "";
+ char* bufend;
+
+ bufend = innobase_convert_name(buf, MAX_TABLE_NAME_LEN,
+ referenced_table_name, strlen(referenced_table_name),
+ trx->mysql_thd, TRUE);
+ buf[bufend - buf] = '\0';
+
+ ib_push_warning(trx, DB_CANNOT_ADD_CONSTRAINT,
+ "%s table %s with foreign key constraint failed. Referenced table %s not found in the data dictionary "
+ "close to %s.",
+ operation, create_name, buf, start_of_latest_foreign);
mutex_enter(&dict_foreign_err_mutex);
- dict_foreign_error_report_low(ef, name);
- fprintf(ef, "%s:\nCannot resolve table name close to:\n"
- "%s\n",
- start_of_latest_foreign, ptr);
+ dict_foreign_error_report_low(ef, create_name);
+ fprintf(ef,
+ "%s table %s with foreign key constraint failed. Referenced table %s not found in the data dictionary "
+ "close to %s.\n",
+ operation, create_name, buf, start_of_latest_foreign);
+
mutex_exit(&dict_foreign_err_mutex);
return(DB_CANNOT_ADD_CONSTRAINT);
}
+ orig = ptr;
ptr = dict_accept(cs, ptr, "(", &success);
if (!success) {
- dict_foreign_report_syntax_err(name, start_of_latest_foreign,
- ptr);
+ dict_foreign_report_syntax_err(
+ "%s table %s with foreign key constraint"
+ " failed. Foreign key constraint parse error in %s"
+ " close to %s.\n",
+ operation, create_name, start_of_latest_foreign, orig);
+
+ ib_push_warning(trx, DB_CANNOT_ADD_CONSTRAINT,
+ "%s table %s with foreign key constraint"
+ " failed. Foreign key constraint parse error in %s"
+ " close to %s.",
+ operation, create_name, start_of_latest_foreign, orig);
+
return(DB_CANNOT_ADD_CONSTRAINT);
}
@@ -4705,34 +4985,54 @@ col_loop1:
i = 0;
col_loop2:
+ orig = ptr;
ptr = dict_scan_col(cs, ptr, &success, referenced_table, columns + i,
- heap, column_names + i);
+ heap, ref_column_names + i);
i++;
if (!success) {
mutex_enter(&dict_foreign_err_mutex);
- dict_foreign_error_report_low(ef, name);
- fprintf(ef, "%s:\nCannot resolve column name close to:\n"
- "%s\n",
- start_of_latest_foreign, ptr);
+ dict_foreign_error_report_low(ef, create_name);
+ fprintf(ef,
+ "%s table %s with foreign key constraint"
+ " failed. Foreign key constraint parse error in %s"
+ " close to %s.\n",
+ operation, create_name, start_of_latest_foreign, orig);
mutex_exit(&dict_foreign_err_mutex);
+ ib_push_warning(trx, DB_CANNOT_ADD_CONSTRAINT,
+ "%s table %s with foreign key constraint"
+ " failed. Foreign key constraint parse error in %s"
+ " close to %s.",
+ operation, create_name, start_of_latest_foreign, orig);
return(DB_CANNOT_ADD_CONSTRAINT);
}
+ orig = ptr;
ptr = dict_accept(cs, ptr, ",", &success);
if (success) {
goto col_loop2;
}
+ orig = ptr;
ptr = dict_accept(cs, ptr, ")", &success);
if (!success || foreign->n_fields != i) {
- dict_foreign_report_syntax_err(name, start_of_latest_foreign,
- ptr);
+ dict_foreign_report_syntax_err(
+ "%s table %s with foreign key constraint"
+ " failed. Foreign key constraint parse error in %s"
+ " close to %s. Too few referenced columns.\n",
+ operation, create_name, start_of_latest_foreign, orig);
+
+ ib_push_warning(trx, DB_CANNOT_ADD_CONSTRAINT,
+ "%s table %s with foreign key constraint"
+ " failed. Foreign key constraint parse error in %s"
+ " close to %s. Too few referenced columns, you have %d when you should have %d.",
+ operation, create_name, start_of_latest_foreign, orig, i, foreign->n_fields);
+
return(DB_CANNOT_ADD_CONSTRAINT);
}
@@ -4742,6 +5042,7 @@ col_loop2:
scan_on_conditions:
/* Loop here as long as we can find ON ... conditions */
+ start_of_latest_set = ptr;
ptr = dict_accept(cs, ptr, "ON", &success);
if (!success) {
@@ -4749,15 +5050,27 @@ scan_on_conditions:
goto try_find_index;
}
+ orig = ptr;
ptr = dict_accept(cs, ptr, "DELETE", &success);
if (!success) {
+ orig = ptr;
ptr = dict_accept(cs, ptr, "UPDATE", &success);
if (!success) {
dict_foreign_report_syntax_err(
- name, start_of_latest_foreign, ptr);
+ "%s table %s with foreign key constraint"
+ " failed. Foreign key constraint parse error in %s"
+ " close to %s.\n",
+ operation, create_name, start_of_latest_foreign, start_of_latest_set);
+
+ ib_push_warning(trx, DB_CANNOT_ADD_CONSTRAINT,
+ "%s table %s with foreign key constraint"
+ " failed. Foreign key constraint parse error in %s"
+ " close to %s.",
+ operation, create_name, start_of_latest_foreign, start_of_latest_set);
+
return(DB_CANNOT_ADD_CONSTRAINT);
}
@@ -4768,12 +5081,14 @@ scan_on_conditions:
n_on_deletes++;
}
+ orig = ptr;
ptr = dict_accept(cs, ptr, "RESTRICT", &success);
if (success) {
goto scan_on_conditions;
}
+ orig = ptr;
ptr = dict_accept(cs, ptr, "CASCADE", &success);
if (success) {
@@ -4786,14 +5101,25 @@ scan_on_conditions:
goto scan_on_conditions;
}
+ orig = ptr;
ptr = dict_accept(cs, ptr, "NO", &success);
if (success) {
+ orig = ptr;
ptr = dict_accept(cs, ptr, "ACTION", &success);
if (!success) {
dict_foreign_report_syntax_err(
- name, start_of_latest_foreign, ptr);
+ "%s table %s with foreign key constraint"
+ " failed. Foreign key constraint parse error in %s"
+ " close to %s.\n",
+ operation, create_name, start_of_latest_foreign, start_of_latest_set);
+
+ ib_push_warning(trx, DB_CANNOT_ADD_CONSTRAINT,
+ "%s table %s with foreign key constraint"
+ " failed. Foreign key constraint parse error in %s"
+ " close to %s.",
+ operation, create_name, start_of_latest_foreign, start_of_latest_set);
return(DB_CANNOT_ADD_CONSTRAINT);
}
@@ -4807,38 +5133,69 @@ scan_on_conditions:
goto scan_on_conditions;
}
+ orig = ptr;
ptr = dict_accept(cs, ptr, "SET", &success);
if (!success) {
- dict_foreign_report_syntax_err(name, start_of_latest_foreign,
- ptr);
+ dict_foreign_report_syntax_err(
+ "%s table %s with foreign key constraint"
+ " failed. Foreign key constraint parse error in %s"
+ " close to %s.\n",
+ operation, create_name, start_of_latest_foreign, start_of_latest_set);
+
+ ib_push_warning(trx, DB_CANNOT_ADD_CONSTRAINT,
+ "%s table %s with foreign key constraint"
+ " failed. Foreign key constraint parse error in %s"
+ " close to %s.",
+ operation, create_name, start_of_latest_foreign, start_of_latest_set);
return(DB_CANNOT_ADD_CONSTRAINT);
}
+ orig = ptr;
ptr = dict_accept(cs, ptr, "NULL", &success);
if (!success) {
- dict_foreign_report_syntax_err(name, start_of_latest_foreign,
- ptr);
+ dict_foreign_report_syntax_err(
+ "%s table %s with foreign key constraint"
+ " failed. Foreign key constraint parse error in %s"
+ " close to %s.\n",
+ operation, create_name, start_of_latest_foreign, start_of_latest_set);
+
+ ib_push_warning(trx, DB_CANNOT_ADD_CONSTRAINT,
+ "%s table %s with foreign key constraint"
+ " failed. Foreign key constraint parse error in %s"
+ " close to %s.",
+ operation, create_name, start_of_latest_foreign, start_of_latest_set);
+
return(DB_CANNOT_ADD_CONSTRAINT);
}
for (j = 0; j < foreign->n_fields; j++) {
if ((dict_index_get_nth_col(foreign->foreign_index, j)->prtype)
& DATA_NOT_NULL) {
+ const dict_col_t* col
+ = dict_index_get_nth_col(foreign->foreign_index, j);
+ const char* col_name = dict_table_get_col_name(foreign->foreign_index->table,
+ dict_col_get_no(col));
/* It is not sensible to define SET NULL
if the column is not allowed to be NULL! */
mutex_enter(&dict_foreign_err_mutex);
- dict_foreign_error_report_low(ef, name);
- fprintf(ef, "%s:\n"
- "You have defined a SET NULL condition"
- " though some of the\n"
- "columns are defined as NOT NULL.\n",
- start_of_latest_foreign);
+ dict_foreign_error_report_low(ef, create_name);
+ fprintf(ef,
+ "%s table %s with foreign key constraint"
+ " failed. You have defined a SET NULL condition but column %s is defined as NOT NULL"
+ " in %s close to %s.\n",
+ operation, create_name, col_name, start_of_latest_foreign, start_of_latest_set);
mutex_exit(&dict_foreign_err_mutex);
+ ib_push_warning(trx, DB_CANNOT_ADD_CONSTRAINT,
+ "%s table %s with foreign key constraint"
+ " failed. You have defined a SET NULL condition but column %s is defined as NOT NULL"
+ " in %s close to %s.",
+ operation, create_name, col_name, start_of_latest_foreign, start_of_latest_set);
+
return(DB_CANNOT_ADD_CONSTRAINT);
}
}
@@ -4856,11 +5213,20 @@ try_find_index:
/* It is an error to define more than 1 action */
mutex_enter(&dict_foreign_err_mutex);
- dict_foreign_error_report_low(ef, name);
- fprintf(ef, "%s:\n"
- "You have twice an ON DELETE clause"
- " or twice an ON UPDATE clause.\n",
- start_of_latest_foreign);
+ dict_foreign_error_report_low(ef, create_name);
+ fprintf(ef,
+ "%s table %s with foreign key constraint"
+ " failed. You have more than one on delete or on update clause"
+ " in %s close to %s.\n",
+ operation, create_name, start_of_latest_foreign, start_of_latest_set);
+
+ ib_push_warning(trx, DB_CANNOT_ADD_CONSTRAINT,
+ "%s table %s with foreign key constraint"
+ " failed. You have more than one on delete or on update clause"
+ " in %s close to %s.",
+ operation, create_name, start_of_latest_foreign, start_of_latest_set);
+
+ dict_foreign_free(foreign);
mutex_exit(&dict_foreign_err_mutex);
return(DB_CANNOT_ADD_CONSTRAINT);
@@ -4872,12 +5238,12 @@ try_find_index:
if (referenced_table) {
index = dict_foreign_find_index(referenced_table, NULL,
- column_names, i,
+ ref_column_names, i,
foreign->foreign_index,
- TRUE, FALSE);
+ TRUE, FALSE, &index_error, &err_col, &err_index);
if (!index) {
mutex_enter(&dict_foreign_err_mutex);
- dict_foreign_error_report_low(ef, name);
+ dict_foreign_error_report_low(ef, create_name);
fprintf(ef, "%s:\n"
"Cannot find an index in the"
" referenced table where the\n"
@@ -4895,9 +5261,13 @@ try_find_index:
"innodb-foreign-key-constraints.html\n"
"for correct foreign key definition.\n",
start_of_latest_foreign);
+
+ dict_foreign_push_index_error(trx, operation, create_name, start_of_latest_foreign,
+ column_names, index_error, err_col, err_index, referenced_table, ef);
+
mutex_exit(&dict_foreign_err_mutex);
- return(DB_PARENT_NO_INDEX);
+ return(DB_CANNOT_ADD_CONSTRAINT);
}
} else {
ut_a(trx->check_foreigns == FALSE);
@@ -4916,11 +5286,12 @@ try_find_index:
for (i = 0; i < foreign->n_fields; i++) {
foreign->referenced_col_names[i]
- = mem_heap_strdup(foreign->heap, column_names[i]);
+ = mem_heap_strdup(foreign->heap, ref_column_names[i]);
}
goto loop;
}
+
/**************************************************************************
Determines whether a string starts with the specified keyword.
@return TRUE if str starts with keyword */
@@ -6110,7 +6481,8 @@ dict_foreign_replace_index(
foreign->foreign_table, col_names,
foreign->foreign_col_names,
foreign->n_fields, index,
- /*check_charsets=*/TRUE, /*check_null=*/FALSE);
+ /*check_charsets=*/TRUE, /*check_null=*/FALSE,
+ NULL, NULL, NULL);
if (new_index) {
ut_ad(new_index->table == index->table);
ut_ad(!new_index->to_be_dropped);
@@ -6134,7 +6506,8 @@ dict_foreign_replace_index(
foreign->referenced_table, NULL,
foreign->referenced_col_names,
foreign->n_fields, index,
- /*check_charsets=*/TRUE, /*check_null=*/FALSE);
+ /*check_charsets=*/TRUE, /*check_null=*/FALSE,
+ NULL, NULL, NULL);
/* There must exist an alternative index,
since this must have been checked earlier. */
if (new_index) {
@@ -6695,10 +7068,15 @@ dict_foreign_qualify_index(
/*!< in: whether to check
charsets. only has an effect
if types_idx != NULL */
- ulint check_null)
+ ulint check_null,
/*!< in: nonzero if none of
the columns must be declared
NOT NULL */
+ ulint* error, /*!< out: error code */
+ ulint* err_col_no,
+ /*!< out: column number where error happened */
+ dict_index_t** err_index)
+ /*!< out: index where error happened */
{
if (dict_index_get_n_fields(index) < n_cols) {
return(false);
@@ -6715,11 +7093,21 @@ dict_foreign_qualify_index(
if (field->prefix_len != 0) {
/* We do not accept column prefix
indexes here */
+ if (error && err_col_no && err_index) {
+ *error = DB_FOREIGN_KEY_IS_PREFIX_INDEX;
+ *err_col_no = i;
+ *err_index = (dict_index_t*)index;
+ }
return(false);
}
if (check_null
&& (field->col->prtype & DATA_NOT_NULL)) {
+ if (error && err_col_no && err_index) {
+ *error = DB_FOREIGN_KEY_COL_NOT_NULL;
+ *err_col_no = i;
+ *err_index = (dict_index_t*)index;
+ }
return(false);
}
@@ -6735,6 +7123,12 @@ dict_foreign_qualify_index(
dict_index_get_nth_col(index, i),
dict_index_get_nth_col(types_idx, i),
check_charsets)) {
+ if (error && err_col_no && err_index) {
+ *error = DB_FOREIGN_KEY_COLS_NOT_EQUAL;
+ *err_col_no = i;
+ *err_index = (dict_index_t*)index;
+ }
+
return(false);
}
}
diff --git a/storage/xtradb/dict/dict0mem.cc b/storage/xtradb/dict/dict0mem.cc
index ffdc5100558..a4f6cd6c91f 100644
--- a/storage/xtradb/dict/dict0mem.cc
+++ b/storage/xtradb/dict/dict0mem.cc
@@ -420,7 +420,8 @@ dict_mem_table_col_rename_low(
dict_index_t* new_index = dict_foreign_find_index(
foreign->foreign_table, NULL,
foreign->foreign_col_names,
- foreign->n_fields, NULL, true, false);
+ foreign->n_fields, NULL, true, false,
+ NULL, NULL, NULL);
/* There must be an equivalent index in this case. */
ut_ad(new_index != NULL);
diff --git a/storage/xtradb/fil/fil0fil.cc b/storage/xtradb/fil/fil0fil.cc
index 3fc9506a15a..d309026e6cc 100644
--- a/storage/xtradb/fil/fil0fil.cc
+++ b/storage/xtradb/fil/fil0fil.cc
@@ -5928,9 +5928,9 @@ _fil_io(
if (!ret) {
return(DB_OUT_OF_FILE_SPACE);
- } else {
- return(DB_SUCCESS);
}
+
+ return(DB_SUCCESS);
}
#ifndef UNIV_HOTBACKUP
diff --git a/storage/xtradb/fsp/fsp0fsp.cc b/storage/xtradb/fsp/fsp0fsp.cc
index 363a46d7fdf..1358fab90ea 100644
--- a/storage/xtradb/fsp/fsp0fsp.cc
+++ b/storage/xtradb/fsp/fsp0fsp.cc
@@ -2730,6 +2730,8 @@ fsp_reserve_free_extents(
ulint reserve;
ibool success;
ulint n_pages_added;
+ size_t total_reserved = 0;
+ ulint rounds = 0;
ut_ad(mtr);
*n_reserved = n_ext;
@@ -2743,7 +2745,7 @@ fsp_reserve_free_extents(
try_again:
size = mtr_read_ulint(space_header + FSP_SIZE, MLOG_4BYTES, mtr);
- if (size < FSP_EXTENT_SIZE) {
+ if (size < FSP_EXTENT_SIZE / 2) {
/* Use different rules for small single-table tablespaces */
*n_reserved = 0;
return(fsp_reserve_free_pages(space, space_header, size, mtr));
@@ -2758,7 +2760,6 @@ try_again:
some of them will contain extent descriptor pages, and therefore
will not be free extents */
- ut_ad(size >= free_limit);
n_free_up = (size - free_limit) / FSP_EXTENT_SIZE;
if (n_free_up > 0) {
@@ -2799,6 +2800,7 @@ try_again:
}
success = fil_space_reserve_free_extents(space, n_free, n_ext);
+ *n_reserved = n_ext;
if (success) {
return(TRUE);
@@ -2808,6 +2810,16 @@ try_to_extend:
space_header, mtr);
if (success && n_pages_added > 0) {
+ rounds++;
+ total_reserved += n_pages_added;
+
+ if (rounds > 50) {
+ ib_logf(IB_LOG_LEVEL_INFO,
+ "Space id %lu trying to reserve %lu extents actually reserved %lu "
+ " reserve %lu free %lu size %lu rounds %lu total_reserved %lu",
+ space, n_ext, n_pages_added, reserve, n_free, size, rounds, total_reserved);
+ }
+
goto try_again;
}
diff --git a/storage/xtradb/handler/ha_innodb.cc b/storage/xtradb/handler/ha_innodb.cc
index a7f5653c389..a80c74cd1fd 100644
--- a/storage/xtradb/handler/ha_innodb.cc
+++ b/storage/xtradb/handler/ha_innodb.cc
@@ -1,10 +1,10 @@
/*****************************************************************************
-Copyright (c) 2000, 2015, Oracle and/or its affiliates. All Rights Reserved.
+Copyright (c) 2000, 2015, Oracle and/or its affiliates.
+Copyright (c) 2013, 2015, MariaDB Corporation.
Copyright (c) 2008, 2009 Google Inc.
Copyright (c) 2009, Percona Inc.
Copyright (c) 2012, Facebook Inc.
-Copyright (c) 2013, 2015, MariaDB Corporation.
Portions of this file contain modifications contributed and copyrighted by
Google, Inc. Those modifications are gratefully acknowledged and are described
@@ -607,7 +607,8 @@ ib_cb_t innodb_api_cb[] = {
(ib_cb_t) ib_get_idx_field_name,
(ib_cb_t) ib_trx_get_start_time,
(ib_cb_t) ib_cfg_bk_commit_interval,
- (ib_cb_t) ib_cursor_stmt_begin
+ (ib_cb_t) ib_cursor_stmt_begin,
+ (ib_cb_t) ib_trx_read_only
};
@@ -2636,6 +2637,7 @@ check_trx_exists(
if (trx == NULL) {
trx = innobase_trx_allocate(thd);
+ thd_set_ha_data(thd, innodb_hton_ptr, trx);
} else if (UNIV_UNLIKELY(trx->magic_n != TRX_MAGIC_N)) {
mem_analyze_corruption(trx);
ut_error;
@@ -13135,6 +13137,13 @@ ha_innobase::estimate_rows_upper_bound()
prebuilt->trx->op_info = "";
+ /* Set num_rows less than MERGEBUFF to simulate the case where we do
+ not have enough space to merge the externally sorted file blocks. */
+ DBUG_EXECUTE_IF("set_num_rows_lt_MERGEBUFF",
+ estimate = 2;
+ DBUG_SET("-d,set_num_rows_lt_MERGEBUFF");
+ );
+
DBUG_RETURN((ha_rows) estimate);
}
@@ -13400,7 +13409,6 @@ ha_innobase::info_low(
dict_table_t* ib_table;
ha_rows rec_per_key;
ib_uint64_t n_rows;
- char path[FN_REFLEN];
os_file_stat_t stat_info;
DBUG_ENTER("info");
@@ -13457,6 +13465,7 @@ ha_innobase::info_low(
prebuilt->trx->op_info =
"returning various info to MySQL";
}
+
}
if (flag & HA_STATUS_VARIABLE) {
@@ -13588,6 +13597,7 @@ ha_innobase::info_low(
if (flag & HA_STATUS_CONST) {
ulong i;
+ char path[FN_REFLEN];
/* Verify the number of index in InnoDB and MySQL
matches up. If prebuilt->clust_index_was_generated
holds, InnoDB defines GEN_CLUST_INDEX internally */
@@ -21229,6 +21239,32 @@ ib_warn_row_too_big(const dict_table_t* table)
, prefix ? DICT_MAX_FIXED_COL_LEN : 0);
}
+/********************************************************************//**
+Helper function to push warnings from InnoDB internals to SQL-layer. */
+UNIV_INTERN
+void
+ib_push_warning(
+ trx_t* trx, /*!< in: trx */
+ ulint error, /*!< in: error code to push as warning */
+ const char *format,/*!< in: warning message */
+ ...)
+{
+ va_list args;
+ THD *thd = (THD *)trx->mysql_thd;
+ char *buf;
+#define MAX_BUF_SIZE 4*1024
+
+ va_start(args, format);
+ buf = (char *)my_malloc(MAX_BUF_SIZE, MYF(MY_WME));
+ vsprintf(buf,format, args);
+
+ push_warning_printf(thd, Sql_condition::WARN_LEVEL_WARN,
+ convert_error_code_to_mysql((dberr_t)error, 0, thd),
+ buf);
+ my_free(buf);
+ va_end(args);
+}
+
/*************************************************************//**
Check for a valid value of innobase_compression_algorithm.
@return 0 for valid innodb_compression_algorithm. */
diff --git a/storage/xtradb/handler/handler0alter.cc b/storage/xtradb/handler/handler0alter.cc
index 7f5ee15049e..168921ae20b 100644
--- a/storage/xtradb/handler/handler0alter.cc
+++ b/storage/xtradb/handler/handler0alter.cc
@@ -400,6 +400,35 @@ ha_innobase::check_if_supported_inplace_alter(
}
}
+ /* If we have column that has changed from NULL -> NOT NULL
+ and column default has changed we need to do additional
+ check. */
+ if ((ha_alter_info->handler_flags
+ & Alter_inplace_info::ALTER_COLUMN_NOT_NULLABLE) &&
+ (ha_alter_info->handler_flags
+ & Alter_inplace_info::ALTER_COLUMN_DEFAULT)) {
+ Alter_info *alter_info = ha_alter_info->alter_info;
+ List_iterator<Create_field> def_it(alter_info->create_list);
+ Create_field *def;
+ while ((def=def_it++)) {
+
+ /* If this is first column definition whose SQL type
+ is TIMESTAMP and it is defined as NOT NULL and
+ it has either constant default or function default
+ we must use "Copy" method. */
+ if (is_timestamp_type(def->sql_type)) {
+ if ((def->flags & NOT_NULL_FLAG) != 0 && // NOT NULL
+ (def->def != NULL || // constant default ?
+ def->unireg_check != Field::NONE)) { // function default
+ ha_alter_info->unsupported_reason = innobase_get_err_msg(
+ ER_ALTER_OPERATION_NOT_SUPPORTED_REASON_NOT_NULL);
+ DBUG_RETURN(HA_ALTER_INPLACE_NOT_SUPPORTED);
+ }
+ break;
+ }
+ }
+ }
+
/* We should be able to do the operation in-place.
See if we can do it online (LOCK=NONE). */
bool online = true;
@@ -824,7 +853,7 @@ innobase_find_fk_index(
if (!(index->type & DICT_FTS)
&& dict_foreign_qualify_index(
table, col_names, columns, n_cols,
- index, NULL, true, 0)) {
+ index, NULL, true, 0, NULL, NULL, NULL)) {
for (ulint i = 0; i < n_drop_index; i++) {
if (index == drop_index[i]) {
/* Skip to-be-dropped indexes. */
@@ -1014,7 +1043,7 @@ innobase_get_foreign_key_info(
referenced_table, 0,
referenced_column_names,
i, index,
- TRUE, FALSE);
+ TRUE, FALSE, NULL, NULL, NULL);
DBUG_EXECUTE_IF(
"innodb_test_no_reference_idx",
@@ -3341,7 +3370,7 @@ innobase_check_foreign_key_index(
foreign->referenced_col_names,
foreign->n_fields, index,
/*check_charsets=*/TRUE,
- /*check_null=*/FALSE)
+ /*check_null=*/FALSE, NULL, NULL, NULL)
&& !innobase_find_equiv_index(
foreign->referenced_col_names,
foreign->n_fields,
@@ -3369,7 +3398,7 @@ innobase_check_foreign_key_index(
foreign->foreign_col_names,
foreign->n_fields, index,
/*check_charsets=*/TRUE,
- /*check_null=*/FALSE)
+ /*check_null=*/FALSE, NULL,NULL, NULL)
&& !innobase_find_equiv_index(
foreign->foreign_col_names,
foreign->n_fields,
@@ -4838,7 +4867,8 @@ innobase_update_foreign_try(
fk->n_fields, fk->referenced_index, TRUE,
fk->type
& (DICT_FOREIGN_ON_DELETE_SET_NULL
- | DICT_FOREIGN_ON_UPDATE_SET_NULL));
+ | DICT_FOREIGN_ON_UPDATE_SET_NULL),
+ NULL, NULL, NULL);
if (!fk->foreign_index) {
my_error(ER_FK_INCORRECT_OPTION,
MYF(0), table_name, fk->id);
@@ -4850,7 +4880,7 @@ innobase_update_foreign_try(
names, while the columns in ctx->old_table have not
been renamed yet. */
error = dict_create_add_foreign_to_dictionary(
- ctx->old_table->name, fk, trx);
+ (dict_table_t*)ctx->old_table, ctx->old_table->name, fk, trx);
DBUG_EXECUTE_IF(
"innodb_test_cannot_add_fk_system",
diff --git a/storage/xtradb/include/api0api.h b/storage/xtradb/include/api0api.h
index d77d691becc..e4c9c941de5 100644
--- a/storage/xtradb/include/api0api.h
+++ b/storage/xtradb/include/api0api.h
@@ -1,6 +1,6 @@
/*****************************************************************************
-Copyright (c) 2011, 2013, Oracle and/or its affiliates. All Rights Reserved.
+Copyright (c) 2011, 2015, Oracle and/or its affiliates. All Rights Reserved.
This program is free software; you can redistribute it and/or modify it under
the terms of the GNU General Public License as published by the Free Software
@@ -494,6 +494,14 @@ ib_trx_state(
/*=========*/
ib_trx_t ib_trx); /*!< in: trx handle */
+
+/*****************************************************************//**
+Check if the transaction is read_only */
+ib_u32_t
+ib_trx_read_only(
+/*=============*/
+ ib_trx_t ib_trx); /*!< in: trx handle */
+
/*****************************************************************//**
Release the resources of the transaction. If the transaction was
selected as a victim by InnoDB and rolled back then use this function
diff --git a/storage/xtradb/include/buf0buf.h b/storage/xtradb/include/buf0buf.h
index 2e8e4139843..5a0bd203185 100644
--- a/storage/xtradb/include/buf0buf.h
+++ b/storage/xtradb/include/buf0buf.h
@@ -97,9 +97,6 @@ extern buf_block_t* back_block1; /*!< first block, for --apply-log */
extern buf_block_t* back_block2; /*!< second block, for page reorganize */
#endif /* !UNIV_HOTBACKUP */
-/** Magic value to use instead of checksums when they are disabled */
-#define BUF_NO_CHECKSUM_MAGIC 0xDEADBEEFUL
-
/** @brief States of a control block
@see buf_page_t
diff --git a/storage/xtradb/include/buf0checksum.h b/storage/xtradb/include/buf0checksum.h
index cd21781dc6e..6818345f965 100644
--- a/storage/xtradb/include/buf0checksum.h
+++ b/storage/xtradb/include/buf0checksum.h
@@ -28,11 +28,10 @@ Created Aug 11, 2011 Vasil Dimov
#include "univ.i"
-#ifndef UNIV_INNOCHECKSUM
-
#include "buf0types.h"
-#endif /* !UNIV_INNOCHECKSUM */
+/** Magic value to use instead of checksums when they are disabled */
+#define BUF_NO_CHECKSUM_MAGIC 0xDEADBEEFUL
/********************************************************************//**
Calculates a page CRC32 which is stored to the page when it is written
@@ -70,8 +69,6 @@ buf_calc_page_old_checksum(
/*=======================*/
const byte* page); /*!< in: buffer page */
-#ifndef UNIV_INNOCHECKSUM
-
/********************************************************************//**
Return a printable string describing the checksum algorithm.
@return algorithm name */
@@ -83,6 +80,4 @@ buf_checksum_algorithm_name(
extern ulong srv_checksum_algorithm;
-#endif /* !UNIV_INNOCHECKSUM */
-
#endif /* buf0checksum_h */
diff --git a/storage/xtradb/include/buf0lru.h b/storage/xtradb/include/buf0lru.h
index 6415540178c..f421e329bf0 100644
--- a/storage/xtradb/include/buf0lru.h
+++ b/storage/xtradb/include/buf0lru.h
@@ -28,7 +28,9 @@ Created 11/5/1995 Heikki Tuuri
#include "univ.i"
#ifndef UNIV_HOTBACKUP
+#ifndef UNIV_INNOCHECKSUM
#include "ut0byte.h"
+#endif
#include "buf0types.h"
// Forward declaration
diff --git a/storage/xtradb/include/dict0crea.h b/storage/xtradb/include/dict0crea.h
index c40e5356ece..3b746fcf83c 100644
--- a/storage/xtradb/include/dict0crea.h
+++ b/storage/xtradb/include/dict0crea.h
@@ -113,6 +113,17 @@ UNIV_INTERN
dberr_t
dict_create_or_check_foreign_constraint_tables(void);
/*================================================*/
+
+/********************************************************************//**
+Construct foreign key constraint defintion from data dictionary information.
+*/
+UNIV_INTERN
+char*
+dict_foreign_def_get(
+/*=================*/
+ dict_foreign_t* foreign,/*!< in: foreign */
+ trx_t* trx); /*!< in: trx */
+
/********************************************************************//**
Generate a foreign key constraint name when it was not named by the user.
A generated constraint has a name of the format dbname/tablename_ibfk_NUMBER,
@@ -177,6 +188,7 @@ UNIV_INTERN
dberr_t
dict_create_add_foreign_to_dictionary(
/*==================================*/
+ dict_table_t* table, /*!< in: table */
const char* name, /*!< in: table name */
const dict_foreign_t* foreign,/*!< in: foreign key */
trx_t* trx) /*!< in/out: dictionary transaction */
diff --git a/storage/xtradb/include/dict0dict.h b/storage/xtradb/include/dict0dict.h
index 09b43fe0e71..5dfdba54f29 100644
--- a/storage/xtradb/include/dict0dict.h
+++ b/storage/xtradb/include/dict0dict.h
@@ -596,10 +596,17 @@ dict_foreign_find_index(
/*!< in: whether to check
charsets. only has an effect
if types_idx != NULL */
- ulint check_null)
+ ulint check_null,
/*!< in: nonzero if none of
the columns must be declared
NOT NULL */
+ ulint* error, /*!< out: error code */
+ ulint* err_col_no,
+ /*!< out: column number where
+ error happened */
+ dict_index_t** err_index)
+ /*!< out: index where error
+ happened */
__attribute__((nonnull(1,3), warn_unused_result));
/**********************************************************************//**
Returns a column's name.
@@ -691,10 +698,18 @@ dict_foreign_qualify_index(
/*!< in: whether to check
charsets. only has an effect
if types_idx != NULL */
- ulint check_null)
+ ulint check_null,
/*!< in: nonzero if none of
the columns must be declared
NOT NULL */
+ ulint* error, /*!< out: error code */
+ ulint* err_col_no,
+ /*!< out: column number where
+ error happened */
+ dict_index_t** err_index)
+ /*!< out: index where error
+ happened */
+
__attribute__((nonnull(1,3), warn_unused_result));
#ifdef UNIV_DEBUG
/********************************************************************//**
diff --git a/storage/xtradb/include/ha_prototypes.h b/storage/xtradb/include/ha_prototypes.h
index 22cb3eed42d..6008332dae3 100644
--- a/storage/xtradb/include/ha_prototypes.h
+++ b/storage/xtradb/include/ha_prototypes.h
@@ -28,14 +28,17 @@ Created 5/11/2006 Osku Salerma
#define HA_INNODB_PROTOTYPES_H
#include "my_dbug.h"
-#include "mysqld_error.h"
#include "my_compare.h"
#include "my_sys.h"
#include "m_string.h"
-#include "debug_sync.h"
#include "my_base.h"
+#ifndef UNIV_INNOCHECKSUM
+#include "mysqld_error.h"
+#include "debug_sync.h"
#include "trx0types.h"
+#endif
+
#include "m_ctype.h" /* CHARSET_INFO */
// Forward declarations
@@ -81,6 +84,8 @@ innobase_raw_format(
ulint buf_size); /*!< in: output buffer size
in bytes */
+#ifndef UNIV_INNOCHECKSUM
+
/*****************************************************************//**
Invalidates the MySQL query cache for the table. */
UNIV_INTERN
@@ -97,6 +102,8 @@ innobase_invalidate_query_cache(
ulint full_name_len); /*!< in: full name length where
also the null chars count */
+#endif /* #ifndef UNIV_INNOCHECKSUM */
+
/*****************************************************************//**
Convert a table or index name to the MySQL system_charset_info (UTF-8)
and quote it if needed.
@@ -620,5 +627,14 @@ innobase_convert_to_filename_charset(
const char* from, /* in: identifier to convert */
ulint len); /* in: length of 'to', in bytes */
+/********************************************************************//**
+Helper function to push warnings from InnoDB internals to SQL-layer. */
+UNIV_INTERN
+void
+ib_push_warning(
+ trx_t* trx, /*!< in: trx */
+ ulint error, /*!< in: error code to push as warning */
+ const char *format,/*!< in: warning message */
+ ...);
#endif /* HA_INNODB_PROTOTYPES_H */
diff --git a/storage/xtradb/include/os0file.h b/storage/xtradb/include/os0file.h
index 88ba7e18ac3..e9faac0d945 100644
--- a/storage/xtradb/include/os0file.h
+++ b/storage/xtradb/include/os0file.h
@@ -1,6 +1,6 @@
/***********************************************************************
-Copyright (c) 1995, 2014, Oracle and/or its affiliates. All Rights Reserved.
+Copyright (c) 1995, 2015, Oracle and/or its affiliates. All Rights Reserved.
Copyright (c) 2009, Percona Inc.
Copyright (c) 2013, 2015, MariaDB Corporation.
@@ -405,10 +405,10 @@ to original un-instrumented file I/O APIs */
enum os_file_type_t {
OS_FILE_TYPE_UNKNOWN = 0,
- OS_FILE_TYPE_FILE, /* regular file */
+ OS_FILE_TYPE_FILE, /* regular file
+ (or a character/block device) */
OS_FILE_TYPE_DIR, /* directory */
- OS_FILE_TYPE_LINK, /* symbolic link */
- OS_FILE_TYPE_BLOCK /* block device */
+ OS_FILE_TYPE_LINK /* symbolic link */
};
/* Maximum path string length in bytes when referring to tables with in the
diff --git a/storage/xtradb/include/page0page.h b/storage/xtradb/include/page0page.h
index 6940040a130..2da5d793fa9 100644
--- a/storage/xtradb/include/page0page.h
+++ b/storage/xtradb/include/page0page.h
@@ -1,6 +1,6 @@
/*****************************************************************************
-Copyright (c) 1994, 2013, Oracle and/or its affiliates. All Rights Reserved.
+Copyright (c) 1994, 2015, Oracle and/or its affiliates. All Rights Reserved.
This program is free software; you can redistribute it and/or modify it under
the terms of the GNU General Public License as published by the Free Software
@@ -28,6 +28,10 @@ Created 2/2/1994 Heikki Tuuri
#include "univ.i"
+#include "buf0types.h"
+
+#ifndef UNIV_INNOCHECKSUM
+
#include "page0types.h"
#include "fil0fil.h"
#include "buf0buf.h"
@@ -1110,6 +1114,24 @@ page_find_rec_with_heap_no(
const rec_t*
page_find_rec_max_not_deleted(
const page_t* page);
+
+#endif /* #ifndef UNIV_INNOCHECKSUM */
+
+/** Issue a warning when the checksum that is stored in the page is valid,
+but different than the global setting innodb_checksum_algorithm.
+@param[in] current_algo current checksum algorithm
+@param[in] page_checksum page valid checksum
+@param[in] space_id tablespace id
+@param[in] page_no page number */
+void
+page_warn_strict_checksum(
+ srv_checksum_algorithm_t curr_algo,
+ srv_checksum_algorithm_t page_checksum,
+ ulint space_id,
+ ulint page_no);
+
+#ifndef UNIV_INNOCHECKSUM
+
#ifdef UNIV_MATERIALIZE
#undef UNIV_INLINE
#define UNIV_INLINE UNIV_INLINE_ORIGINAL
@@ -1119,4 +1141,6 @@ page_find_rec_max_not_deleted(
#include "page0page.ic"
#endif
+#endif /* #ifndef UNIV_INNOCHECKSUM */
+
#endif
diff --git a/storage/xtradb/include/page0types.h b/storage/xtradb/include/page0types.h
index 95143a4bb44..74ad6f72f7e 100644
--- a/storage/xtradb/include/page0types.h
+++ b/storage/xtradb/include/page0types.h
@@ -107,6 +107,8 @@ struct page_zip_stat_t {
{ }
};
+#ifndef UNIV_INNOCHECKSUM
+
/** Compression statistics types */
typedef map<index_id_t, page_zip_stat_t> page_zip_stat_per_index_t;
@@ -119,6 +121,8 @@ extern ib_mutex_t page_zip_stat_per_index_mutex;
extern mysql_pfs_key_t page_zip_stat_per_index_mutex_key;
#endif /* HAVE_PSI_INTERFACE */
+#endif /* !UNIV_INNOCHECKSUM */
+
/**********************************************************************//**
Write the "deleted" flag of a record on a compressed page. The flag must
already have been written on the uncompressed page. */
diff --git a/storage/xtradb/include/page0zip.h b/storage/xtradb/include/page0zip.h
index 2f9efc4a40c..41eb1e35d78 100644
--- a/storage/xtradb/include/page0zip.h
+++ b/storage/xtradb/include/page0zip.h
@@ -32,13 +32,17 @@ Created June 2005 by Marko Makela
# define UNIV_INLINE
#endif
-#include "mtr0types.h"
+#ifndef UNIV_INNOCHECKSUM
#include "page0types.h"
-#include "buf0types.h"
+#include "mtr0types.h"
#include "dict0types.h"
#include "srv0srv.h"
#include "trx0types.h"
#include "mem0mem.h"
+#else
+#include "univ.i"
+#endif /* !UNIV_INNOCHECKSUM */
+#include "buf0types.h"
/* Compression level to be used by zlib. Settable by user. */
extern uint page_zip_level;
@@ -50,6 +54,7 @@ extern uint page_zip_level;
compression algorithm changes in zlib. */
extern my_bool page_zip_log_pages;
+#ifndef UNIV_INNOCHECKSUM
/**********************************************************************//**
Determine the size of a compressed page in bytes.
@return size in bytes */
@@ -159,6 +164,8 @@ page_zip_simple_validate(
descriptor */
#endif /* UNIV_DEBUG */
+#endif /* !UNIV_INNOCHECKSUM */
+
#ifdef UNIV_ZIP_DEBUG
/**********************************************************************//**
Check that the compressed and decompressed pages match.
@@ -185,6 +192,7 @@ page_zip_validate(
__attribute__((nonnull(1,2)));
#endif /* UNIV_ZIP_DEBUG */
+#ifndef UNIV_INNOCHECKSUM
/**********************************************************************//**
Determine how big record can be inserted without recompressing the page.
@return a positive number indicating the maximum size of a record
@@ -452,6 +460,8 @@ page_zip_parse_compress(
page_zip_des_t* page_zip)/*!< out: compressed page */
__attribute__((nonnull(1,2)));
+#endif /* !UNIV_INNOCHECKSUM */
+
/**********************************************************************//**
Calculate the compressed page checksum.
@return page checksum */
@@ -474,6 +484,9 @@ page_zip_verify_checksum(
/*=====================*/
const void* data, /*!< in: compressed page */
ulint size); /*!< in: size of compressed page */
+
+#ifndef UNIV_INNOCHECKSUM
+
/**********************************************************************//**
Write a log record of compressing an index page without the data on the page. */
UNIV_INLINE
@@ -506,6 +519,8 @@ void
page_zip_reset_stat_per_index();
/*===========================*/
+#endif /* !UNIV_INNOCHECKSUM */
+
#ifndef UNIV_HOTBACKUP
/** Check if a pointer to an uncompressed page matches a compressed page.
When we IMPORT a tablespace the blocks and accompanying frames are allocted
@@ -531,8 +546,10 @@ from outside the buffer pool.
# define UNIV_INLINE UNIV_INLINE_ORIGINAL
#endif
+#ifndef UNIV_INNOCHECKSUM
#ifndef UNIV_NONINL
# include "page0zip.ic"
#endif
+#endif /* !UNIV_INNOCHECKSUM */
#endif /* page0zip_h */
diff --git a/storage/xtradb/include/srv0srv.h b/storage/xtradb/include/srv0srv.h
index 78a402d488c..45300bc2ded 100644
--- a/storage/xtradb/include/srv0srv.h
+++ b/storage/xtradb/include/srv0srv.h
@@ -514,7 +514,6 @@ extern my_bool srv_stats_sample_traditional;
extern ibool srv_use_doublewrite_buf;
extern ulong srv_doublewrite_batch_size;
-extern ulong srv_checksum_algorithm;
extern ulong srv_log_arch_expire_sec;
diff --git a/storage/xtradb/include/univ.i b/storage/xtradb/include/univ.i
index 241f210869f..8105d1f318b 100644
--- a/storage/xtradb/include/univ.i
+++ b/storage/xtradb/include/univ.i
@@ -45,10 +45,10 @@ Created 1/20/1994 Heikki Tuuri
#define INNODB_VERSION_MAJOR 5
#define INNODB_VERSION_MINOR 6
-#define INNODB_VERSION_BUGFIX 24
+#define INNODB_VERSION_BUGFIX 25
#ifndef PERCONA_INNODB_VERSION
-#define PERCONA_INNODB_VERSION 72.2
+#define PERCONA_INNODB_VERSION 73.1
#endif
/* Enable UNIV_LOG_ARCHIVE in XtraDB */
diff --git a/storage/xtradb/lock/lock0lock.cc b/storage/xtradb/lock/lock0lock.cc
index b3d9e470816..26d868ca94d 100644
--- a/storage/xtradb/lock/lock0lock.cc
+++ b/storage/xtradb/lock/lock0lock.cc
@@ -3027,7 +3027,8 @@ lock_rec_inherit_to_gap(
&& !((srv_locks_unsafe_for_binlog
|| lock->trx->isolation_level
<= TRX_ISO_READ_COMMITTED)
- && lock_get_mode(lock) == LOCK_X)) {
+ && lock_get_mode(lock) ==
+ (lock->trx->duplicates ? LOCK_S : LOCK_X))) {
lock_rec_add_to_queue(
LOCK_REC | LOCK_GAP | lock_get_mode(lock),
diff --git a/storage/xtradb/os/os0file.cc b/storage/xtradb/os/os0file.cc
index cb074cdf4f5..9ef9adf5b74 100644
--- a/storage/xtradb/os/os0file.cc
+++ b/storage/xtradb/os/os0file.cc
@@ -1,6 +1,6 @@
/***********************************************************************
-Copyright (c) 1995, 2014, Oracle and/or its affiliates. All Rights Reserved.
+Copyright (c) 1995, 2015, Oracle and/or its affiliates. All Rights Reserved.
Copyright (c) 2009, Percona Inc.
Copyright (c) 2013, 2015, MariaDB Corporation.
@@ -3604,8 +3604,9 @@ os_file_get_status(
stat_info->type = OS_FILE_TYPE_LINK;
break;
case S_IFBLK:
- stat_info->type = OS_FILE_TYPE_BLOCK;
- break;
+ /* Handle block device as regular file. */
+ case S_IFCHR:
+ /* Handle character device as regular file. */
case S_IFREG:
stat_info->type = OS_FILE_TYPE_FILE;
break;
@@ -3614,8 +3615,8 @@ os_file_get_status(
}
- if (check_rw_perm && (stat_info->type == OS_FILE_TYPE_FILE
- || stat_info->type == OS_FILE_TYPE_BLOCK)) {
+ if (check_rw_perm && stat_info->type == OS_FILE_TYPE_FILE) {
+
int fh;
int access;
diff --git a/storage/xtradb/page/page0page.cc b/storage/xtradb/page/page0page.cc
index 4aff88818bb..6adbdeb95a4 100644
--- a/storage/xtradb/page/page0page.cc
+++ b/storage/xtradb/page/page0page.cc
@@ -1,6 +1,6 @@
/*****************************************************************************
-Copyright (c) 1994, 2013, Oracle and/or its affiliates. All Rights Reserved.
+Copyright (c) 1994, 2015, Oracle and/or its affiliates. All Rights Reserved.
Copyright (c) 2012, Facebook Inc.
This program is free software; you can redistribute it and/or modify it under
@@ -31,6 +31,11 @@ Created 2/2/1994 Heikki Tuuri
#endif
#undef THIS_MODULE
+#include "ha_prototypes.h"
+#include "buf0checksum.h"
+
+#ifndef UNIV_INNOCHECKSUM
+
#include "page0cur.h"
#include "page0zip.h"
#include "buf0buf.h"
@@ -2819,3 +2824,51 @@ page_find_rec_max_not_deleted(
}
return(prev_rec);
}
+
+#endif /* #ifndef UNIV_INNOCHECKSUM */
+
+/** Issue a warning when the checksum that is stored in the page is valid,
+but different than the global setting innodb_checksum_algorithm.
+@param[in] current_algo current checksum algorithm
+@param[in] page_checksum page valid checksum
+@param[in] space_id tablespace id
+@param[in] page_no page number */
+void
+page_warn_strict_checksum(
+ srv_checksum_algorithm_t curr_algo,
+ srv_checksum_algorithm_t page_checksum,
+ ulint space_id,
+ ulint page_no)
+{
+ srv_checksum_algorithm_t curr_algo_nonstrict;
+ switch (curr_algo) {
+ case SRV_CHECKSUM_ALGORITHM_STRICT_CRC32:
+ curr_algo_nonstrict = SRV_CHECKSUM_ALGORITHM_CRC32;
+ break;
+ case SRV_CHECKSUM_ALGORITHM_STRICT_INNODB:
+ curr_algo_nonstrict = SRV_CHECKSUM_ALGORITHM_INNODB;
+ break;
+ case SRV_CHECKSUM_ALGORITHM_STRICT_NONE:
+ curr_algo_nonstrict = SRV_CHECKSUM_ALGORITHM_NONE;
+ break;
+ default:
+ ut_error;
+ }
+
+#ifdef UNIV_INNOCHECKSUM
+ fprintf(stderr,
+#else
+ ib_logf(IB_LOG_LEVEL_WARN,
+#endif
+ "innodb_checksum_algorithm is set to \"%s\""
+ " but the page [page id: space=" ULINTPF ","
+ " page number=" ULINTPF "] contains a valid checksum \"%s\"."
+ " Accepting the page as valid. Change innodb_checksum_algorithm"
+ " to \"%s\" to silently accept such pages or rewrite all pages"
+ " so that they contain \"%s\" checksum.",
+ buf_checksum_algorithm_name(curr_algo),
+ space_id, page_no,
+ buf_checksum_algorithm_name(page_checksum),
+ buf_checksum_algorithm_name(curr_algo_nonstrict),
+ buf_checksum_algorithm_name(curr_algo_nonstrict));
+}
diff --git a/storage/xtradb/page/page0zip.cc b/storage/xtradb/page/page0zip.cc
index 58559cc438b..42ffd3668d8 100644
--- a/storage/xtradb/page/page0zip.cc
+++ b/storage/xtradb/page/page0zip.cc
@@ -37,30 +37,40 @@ using namespace std;
# include "page0zip.ic"
#endif
#undef THIS_MODULE
+#include "buf0checksum.h"
#include "page0page.h"
+#ifndef UNIV_INNOCHECKSUM
#include "mtr0log.h"
-#include "ut0sort.h"
#include "dict0dict.h"
#include "btr0cur.h"
-#include "page0types.h"
#include "log0recv.h"
+#endif /* !UNIV_INNOCHECKSUM */
#include "zlib.h"
+#include "fil0fil.h"
+#include "ut0sort.h"
+#include "page0types.h"
#ifndef UNIV_HOTBACKUP
+#ifndef UNIV_INNOCHECKSUM
# include "buf0buf.h"
-# include "buf0lru.h"
# include "btr0sea.h"
# include "dict0boot.h"
# include "lock0lock.h"
# include "srv0mon.h"
# include "srv0srv.h"
+#endif /* !UNIV_INNOCHECKSUM */
+# include "buf0lru.h"
# include "ut0crc32.h"
#else /* !UNIV_HOTBACKUP */
-# include "buf0checksum.h"
# define lock_move_reorganize_page(block, temp_block) ((void) 0)
# define buf_LRU_stat_inc_unzip() ((void) 0)
#endif /* !UNIV_HOTBACKUP */
+#ifdef UNIV_INNOCHECKSUM
+#include "mach0data.h"
+#endif /* UNIV_INNOCHECKSUM */
+
#ifndef UNIV_HOTBACKUP
+#ifndef UNIV_INNOCHECKSUM
/** Statistics on compression, indexed by page_zip_des_t::ssize - 1 */
UNIV_INTERN page_zip_stat_t page_zip_stat[PAGE_ZIP_SSIZE_MAX];
/** Statistics on compression, indexed by index->id */
@@ -70,6 +80,7 @@ UNIV_INTERN ib_mutex_t page_zip_stat_per_index_mutex;
#ifdef HAVE_PSI_INTERFACE
UNIV_INTERN mysql_pfs_key_t page_zip_stat_per_index_mutex_key;
#endif /* HAVE_PSI_INTERFACE */
+#endif /* !UNIV_INNOCHECKSUM */
#endif /* !UNIV_HOTBACKUP */
/* Compression level to be used by zlib. Settable by user. */
@@ -82,6 +93,8 @@ UNIV_INTERN my_bool page_zip_log_pages = false;
/* Please refer to ../include/page0zip.ic for a description of the
compressed page format. */
+#ifndef UNIV_INNOCHECKSUM
+
/* The infimum and supremum records are omitted from the compressed page.
On compress, we compare that the records are there, and on uncompress we
restore the records. */
@@ -105,6 +118,8 @@ static const byte supremum_extra_data[] = {
0x65, 0x6d, 0x75, 0x6d /* "supremum" */
};
+#endif /* !UNIV_INNOCHECKSUM */
+
/** Assert that a block of memory is filled with zero bytes.
Compare at most sizeof(field_ref_zero) bytes.
@param b in: memory block
@@ -151,6 +166,7 @@ page_zip_fail_func(
# define page_zip_fail(fmt_args) /* empty */
#endif /* UNIV_DEBUG || UNIV_ZIP_DEBUG */
+#ifndef UNIV_INNOCHECKSUM
#ifndef UNIV_HOTBACKUP
/**********************************************************************//**
Determine the guaranteed free space on an empty page.
@@ -4843,6 +4859,7 @@ corrupt:
return(ptr + 8 + size + trailer_size);
}
+#endif /* !UNIV_INNOCHECKSUM */
/**********************************************************************//**
Calculate the compressed page checksum.
@@ -4918,6 +4935,10 @@ page_zip_verify_checksum(
stored = static_cast<ib_uint32_t>(mach_read_from_4(
static_cast<const unsigned char*>(data) + FIL_PAGE_SPACE_OR_CHKSUM));
+ ulint page_no = mach_read_from_4(static_cast<const unsigned char*> (data) + FIL_PAGE_OFFSET);
+ ulint space_id = mach_read_from_4(static_cast<const unsigned char*>
+ (data) + FIL_PAGE_SPACE_ID);
+
#if FIL_PAGE_LSN % 8
#error "FIL_PAGE_LSN must be 64 bit aligned"
#endif
@@ -4938,40 +4959,113 @@ page_zip_verify_checksum(
return(TRUE);
}
+ const srv_checksum_algorithm_t curr_algo =
+ static_cast<srv_checksum_algorithm_t>(srv_checksum_algorithm);
+
+ if (curr_algo == SRV_CHECKSUM_ALGORITHM_NONE) {
+ return(TRUE);
+ }
+
calc = static_cast<ib_uint32_t>(page_zip_calc_checksum(
- data, size, static_cast<srv_checksum_algorithm_t>(
- srv_checksum_algorithm)));
+ data, size, curr_algo));
if (stored == calc) {
return(TRUE);
}
- switch ((srv_checksum_algorithm_t) srv_checksum_algorithm) {
+ switch (curr_algo) {
case SRV_CHECKSUM_ALGORITHM_STRICT_CRC32:
- case SRV_CHECKSUM_ALGORITHM_STRICT_INNODB:
- case SRV_CHECKSUM_ALGORITHM_STRICT_NONE:
- return(stored == calc);
case SRV_CHECKSUM_ALGORITHM_CRC32:
+
if (stored == BUF_NO_CHECKSUM_MAGIC) {
+ if (curr_algo
+ == SRV_CHECKSUM_ALGORITHM_STRICT_CRC32) {
+ page_warn_strict_checksum(
+ curr_algo,
+ SRV_CHECKSUM_ALGORITHM_NONE,
+ space_id, page_no);
+ }
+
return(TRUE);
}
- crc32 = calc;
+
innodb = static_cast<ib_uint32_t>(page_zip_calc_checksum(
data, size, SRV_CHECKSUM_ALGORITHM_INNODB));
+
+ if (stored == innodb) {
+ if (curr_algo
+ == SRV_CHECKSUM_ALGORITHM_STRICT_CRC32) {
+ page_warn_strict_checksum(
+ curr_algo,
+ SRV_CHECKSUM_ALGORITHM_INNODB,
+ space_id, page_no);
+ }
+
+ return(TRUE);
+ }
+
break;
+ case SRV_CHECKSUM_ALGORITHM_STRICT_INNODB:
case SRV_CHECKSUM_ALGORITHM_INNODB:
+
if (stored == BUF_NO_CHECKSUM_MAGIC) {
+ if (curr_algo
+ == SRV_CHECKSUM_ALGORITHM_STRICT_INNODB) {
+ page_warn_strict_checksum(
+ curr_algo,
+ SRV_CHECKSUM_ALGORITHM_NONE,
+ space_id, page_no);
+ }
+
return(TRUE);
}
+
crc32 = static_cast<ib_uint32_t>(page_zip_calc_checksum(
data, size, SRV_CHECKSUM_ALGORITHM_CRC32));
- innodb = calc;
+
+ if (stored == crc32) {
+ if (curr_algo
+ == SRV_CHECKSUM_ALGORITHM_STRICT_INNODB) {
+ page_warn_strict_checksum(
+ curr_algo,
+ SRV_CHECKSUM_ALGORITHM_CRC32,
+ space_id, page_no);
+ }
+
+ return(TRUE);
+ }
+
+ break;
+ case SRV_CHECKSUM_ALGORITHM_STRICT_NONE:
+
+ crc32 = static_cast<ib_uint32_t>(page_zip_calc_checksum(
+ data, size, SRV_CHECKSUM_ALGORITHM_CRC32));
+
+ if (stored == crc32) {
+ page_warn_strict_checksum(
+ curr_algo, SRV_CHECKSUM_ALGORITHM_CRC32,
+ space_id, page_no);
+
+ return(TRUE);
+ }
+
+ innodb = static_cast<ib_uint32_t>(page_zip_calc_checksum(
+ data, size, SRV_CHECKSUM_ALGORITHM_INNODB));
+
+ if (stored == innodb) {
+ page_warn_strict_checksum(
+ curr_algo,
+ SRV_CHECKSUM_ALGORITHM_INNODB,
+ space_id, page_no);
+ return(TRUE);
+ }
+
break;
case SRV_CHECKSUM_ALGORITHM_NONE:
- return(TRUE);
+ ut_error;
/* no default so the compiler will emit a warning if new enum
is added and not handled here */
}
- return(stored == crc32 || stored == innodb);
+ return(FALSE);
}
diff --git a/storage/xtradb/row/row0ins.cc b/storage/xtradb/row/row0ins.cc
index fb719266a16..b1291404176 100644
--- a/storage/xtradb/row/row0ins.cc
+++ b/storage/xtradb/row/row0ins.cc
@@ -2765,6 +2765,8 @@ row_ins_sec_index_entry_low(
goto func_exit;
}
+ DEBUG_SYNC_C("row_ins_sec_index_entry_dup_locks_created");
+
/* We did not find a duplicate and we have now
locked with s-locks the necessary records to
prevent any insertion of a duplicate by another
diff --git a/storage/xtradb/row/row0mysql.cc b/storage/xtradb/row/row0mysql.cc
index efc5c568cd5..8a4536488fe 100644
--- a/storage/xtradb/row/row0mysql.cc
+++ b/storage/xtradb/row/row0mysql.cc
@@ -1326,18 +1326,14 @@ row_insert_for_mysql(
mem_analyze_corruption(prebuilt);
ut_error;
- } else if (srv_created_new_raw || srv_force_recovery) {
- fputs("InnoDB: A new raw disk partition was initialized or\n"
- "InnoDB: innodb_force_recovery is on: we do not allow\n"
+ } else if (srv_force_recovery) {
+ fputs("InnoDB: innodb_force_recovery is on: we do not allow\n"
"InnoDB: database modifications by the user. Shut down\n"
"InnoDB: mysqld and edit my.cnf so that"
- " newraw is replaced\n"
- "InnoDB: with raw, and innodb_force_... is removed.\n",
+ "InnoDB: innodb_force_... is removed.\n",
stderr);
- if(srv_force_recovery) {
- return(DB_READ_ONLY);
- }
- return(DB_ERROR);
+
+ return(DB_READ_ONLY);
}
trx->op_info = "inserting";
@@ -1732,18 +1728,14 @@ row_update_for_mysql(
ut_error;
}
- if (UNIV_UNLIKELY(srv_created_new_raw || srv_force_recovery)) {
- fputs("InnoDB: A new raw disk partition was initialized or\n"
- "InnoDB: innodb_force_recovery is on: we do not allow\n"
+ if (UNIV_UNLIKELY(srv_force_recovery)) {
+ fputs("InnoDB: innodb_force_recovery is on: we do not allow\n"
"InnoDB: database modifications by the user. Shut down\n"
- "InnoDB: mysqld and edit my.cnf so that newraw"
- " is replaced\n"
- "InnoDB: with raw, and innodb_force_... is removed.\n",
+ "InnoDB: mysqld and edit my.cnf so that"
+ "InnoDB: innodb_force_... is removed.\n",
stderr);
- if(srv_force_recovery) {
- return(DB_READ_ONLY);
- }
- return(DB_ERROR);
+
+ return(DB_READ_ONLY);
}
DEBUG_SYNC_C("innodb_row_update_for_mysql_begin");
@@ -2254,22 +2246,6 @@ row_create_table_for_mysql(
goto err_exit;
);
- if (srv_created_new_raw) {
- fputs("InnoDB: A new raw disk partition was initialized:\n"
- "InnoDB: we do not allow database modifications"
- " by the user.\n"
- "InnoDB: Shut down mysqld and edit my.cnf so that newraw"
- " is replaced with raw.\n", stderr);
-err_exit:
- dict_mem_table_free(table);
-
- if (commit) {
- trx_commit_for_mysql(trx);
- }
-
- return(DB_ERROR);
- }
-
trx->op_info = "creating table";
if (row_mysql_is_system_table(table->name)) {
@@ -2280,7 +2256,19 @@ err_exit:
"InnoDB: MySQL system tables must be"
" of the MyISAM type!\n",
table->name);
- goto err_exit;
+
+#ifndef DBUG_OFF
+err_exit:
+#endif /* !DBUG_OFF */
+ dict_mem_table_free(table);
+
+ if (commit) {
+ trx_commit_for_mysql(trx);
+ }
+
+ trx->op_info = "";
+
+ return(DB_ERROR);
}
trx_start_if_not_started_xa(trx);
@@ -3365,16 +3353,6 @@ row_truncate_table_for_mysql(
ut_ad(table);
- if (srv_created_new_raw) {
- fputs("InnoDB: A new raw disk partition was initialized:\n"
- "InnoDB: we do not allow database modifications"
- " by the user.\n"
- "InnoDB: Shut down mysqld and edit my.cnf so that newraw"
- " is replaced with raw.\n", stderr);
-
- return(DB_ERROR);
- }
-
if (dict_table_is_discarded(table)) {
return(DB_TABLESPACE_DELETED);
} else if (table->ibd_file_missing) {
@@ -3864,16 +3842,6 @@ row_drop_table_for_mysql(
ut_a(name != NULL);
- if (srv_created_new_raw) {
- fputs("InnoDB: A new raw disk partition was initialized:\n"
- "InnoDB: we do not allow database modifications"
- " by the user.\n"
- "InnoDB: Shut down mysqld and edit my.cnf so that newraw"
- " is replaced with raw.\n", stderr);
-
- DBUG_RETURN(DB_ERROR);
- }
-
/* The table name is prefixed with the database name and a '/'.
Certain table names starting with 'innodb_' have their special
meaning regardless of the database name. Thus, we need to
@@ -4892,19 +4860,16 @@ row_rename_table_for_mysql(
ut_a(new_name != NULL);
ut_ad(trx->state == TRX_STATE_ACTIVE);
- if (srv_created_new_raw || srv_force_recovery) {
- fputs("InnoDB: A new raw disk partition was initialized or\n"
- "InnoDB: innodb_force_recovery is on: we do not allow\n"
+ if (srv_force_recovery) {
+ fputs("InnoDB: innodb_force_recovery is on: we do not allow\n"
"InnoDB: database modifications by the user. Shut down\n"
- "InnoDB: mysqld and edit my.cnf so that newraw"
- " is replaced\n"
- "InnoDB: with raw, and innodb_force_... is removed.\n",
+ "InnoDB: mysqld and edit my.cnf so that"
+ "InnoDB: innodb_force_... is removed.\n",
stderr);
- if(srv_force_recovery) {
- err = DB_READ_ONLY;
- }
+ err = DB_READ_ONLY;
goto funct_exit;
+
} else if (row_mysql_is_system_table(new_name)) {
fprintf(stderr,
diff --git a/storage/xtradb/srv/srv0start.cc b/storage/xtradb/srv/srv0start.cc
index 3f558170f97..54ac04e7248 100644
--- a/storage/xtradb/srv/srv0start.cc
+++ b/storage/xtradb/srv/srv0start.cc
@@ -1,6 +1,6 @@
/*****************************************************************************
-Copyright (c) 1996, 2014, Oracle and/or its affiliates. All rights reserved.
+Copyright (c) 1996, 2015, Oracle and/or its affiliates. All rights reserved.
Copyright (c) 2008, Google Inc.
Copyright (c) 2009, Percona Inc.
Copyright (c) 2013, 2015, MariaDB Corporation
@@ -264,8 +264,8 @@ srv_file_check_mode(
/* Note: stat.rw_perm is only valid of files */
- if (stat.type == OS_FILE_TYPE_FILE
- || stat.type == OS_FILE_TYPE_BLOCK) {
+ if (stat.type == OS_FILE_TYPE_FILE) {
+
if (!stat.rw_perm) {
ib_logf(IB_LOG_LEVEL_ERROR,
@@ -462,14 +462,18 @@ srv_parse_data_file_paths_and_sizes(
&& *(str + 1) == 'e'
&& *(str + 2) == 'w') {
str += 3;
- (srv_data_file_is_raw_partition)[i] = SRV_NEW_RAW;
+ /* Initialize new raw device only during bootstrap */
+ (srv_data_file_is_raw_partition)[i] =
+ opt_bootstrap ? SRV_NEW_RAW : SRV_OLD_RAW;
}
if (*str == 'r' && *(str + 1) == 'a' && *(str + 2) == 'w') {
str += 3;
+ /* Initialize new raw device only during bootstrap */
if ((srv_data_file_is_raw_partition)[i] == 0) {
- (srv_data_file_is_raw_partition)[i] = SRV_OLD_RAW;
+ (srv_data_file_is_raw_partition)[i] =
+ opt_bootstrap ? SRV_NEW_RAW : SRV_OLD_RAW;
}
}
@@ -945,6 +949,21 @@ open_or_create_data_files(
return(DB_ERROR);
}
+
+ const char* check_msg;
+ check_msg = fil_read_first_page(
+ files[i], FALSE, &flags, &space,
+ min_flushed_lsn, max_flushed_lsn, NULL);
+
+ /* If first page is valid, don't overwrite DB.
+ It prevents overwriting DB when mysql_install_db
+ starts mysqld multiple times during bootstrap. */
+ if (check_msg == NULL) {
+
+ srv_created_new_raw = FALSE;
+ ret = FALSE;
+ }
+
} else if (srv_data_file_is_raw_partition[i] == SRV_OLD_RAW) {
srv_start_raw_disk_in_use = TRUE;
diff --git a/storage/xtradb/sync/sync0arr.cc b/storage/xtradb/sync/sync0arr.cc
index 01cae70a8ce..d881c5de2f5 100644
--- a/storage/xtradb/sync/sync0arr.cc
+++ b/storage/xtradb/sync/sync0arr.cc
@@ -1,6 +1,6 @@
/*****************************************************************************
-Copyright (c) 1995, 2013, Oracle and/or its affiliates. All Rights Reserved.
+Copyright (c) 1995, 2015, Oracle and/or its affiliates. All Rights Reserved.
Copyright (c) 2008, Google Inc.
Copyright (c) 2013, 2015, MariaDB Corporation. All Rights Reserved.
@@ -1206,8 +1206,8 @@ sync_array_print_info_low(
ulint count = 0;
fprintf(file,
- "OS WAIT ARRAY INFO: reservation count %ld\n",
- (long) arr->res_count);
+ "OS WAIT ARRAY INFO: reservation count " ULINTPF "\n",
+ arr->res_count);
for (i = 0; count < arr->n_reserved; ++i) {
sync_cell_t* cell;
@@ -1303,7 +1303,7 @@ sync_array_print(
}
fprintf(file,
- "OS WAIT ARRAY INFO: signal count %ld\n", (long) sg_count);
+ "OS WAIT ARRAY INFO: signal count " ULINTPF "\n", sg_count);
}
diff --git a/storage/xtradb/trx/trx0sys.cc b/storage/xtradb/trx/trx0sys.cc
index 32948d6847c..bebd28b0df3 100644
--- a/storage/xtradb/trx/trx0sys.cc
+++ b/storage/xtradb/trx/trx0sys.cc
@@ -1332,8 +1332,6 @@ trx_sys_close(void)
/* Free the double write data structures. */
buf_dblwr_free();
- mutex_enter(&trx_sys->mutex);
-
ut_a(UT_LIST_GET_LEN(trx_sys->ro_trx_list) == 0);
/* Only prepared transactions may be left in the system. Free them. */
@@ -1373,8 +1371,6 @@ trx_sys_close(void)
ut_a(UT_LIST_GET_LEN(trx_sys->rw_trx_list) == 0);
ut_a(UT_LIST_GET_LEN(trx_sys->mysql_trx_list) == 0);
- mutex_exit(&trx_sys->mutex);
-
mutex_free(&trx_sys->mutex);
ut_ad(trx_sys->descr_n_used == 0);
diff --git a/storage/xtradb/trx/trx0trx.cc b/storage/xtradb/trx/trx0trx.cc
index 5d3b86e158f..9bca6de9c26 100644
--- a/storage/xtradb/trx/trx0trx.cc
+++ b/storage/xtradb/trx/trx0trx.cc
@@ -1,6 +1,6 @@
/*****************************************************************************
-Copyright (c) 1996, 2014, Oracle and/or its affiliates. All Rights Reserved.
+Copyright (c) 1996, 2015, Oracle and/or its affiliates. All Rights Reserved.
This program is free software; you can redistribute it and/or modify it under
the terms of the GNU General Public License as published by the Free Software
@@ -481,9 +481,7 @@ trx_free_prepared(
ut_a(trx_state_eq(trx, TRX_STATE_PREPARED));
ut_a(trx->magic_n == TRX_MAGIC_N);
- mutex_exit(&trx_sys->mutex);
lock_trx_release_locks(trx);
- mutex_enter(&trx_sys->mutex);
trx_undo_free_prepared(trx);
assert_trx_in_rw_list(trx);
@@ -493,7 +491,9 @@ trx_free_prepared(
UT_LIST_REMOVE(trx_list, trx_sys->rw_trx_list, trx);
ut_d(trx->in_rw_trx_list = FALSE);
+ mutex_enter(&trx_sys->mutex);
trx_release_descriptor(trx);
+ mutex_exit(&trx_sys->mutex);
/* Undo trx_resurrect_table_locks(). */
UT_LIST_INIT(trx->lock.trx_locks);