From 1bbd0b5b03e65fe55ba34c5e1dfc7284d6b55dbf Mon Sep 17 00:00:00 2001 From: Satya B Date: Mon, 30 Nov 2009 13:56:45 +0530 Subject: [PATCH 1/9] Applying InnoDB snapshot 5.1-ss6242, part 1. Fixes BUG#32430 1. BUG#32430 - 'show innodb status' causes errors Invalid (old?) table or database name in logs 2. White space fixup Detailed revision comments: r6136 | marko | 2009-11-04 12:28:10 +0200 (Wed, 04 Nov 2009) | 15 lines branches/5.1: Port r6134 from branches/zip: ------------------------------------------------------------------------ r6134 | marko | 2009-11-04 07:57:29 +0000 (Wed, 04 Nov 2009) | 5 lines branches/zip: innobase_convert_identifier(): Convert table names with explain_filename() to address Bug #32430: 'show innodb status' causes errors Invalid (old?) table or database name in logs. rb://134 approved by Sunny Bains ------------------------------------------------------------------------ innobase_print_identifier(): Replace with innobase_convert_name(). innobase_convert_identifier(): New function, called by innobase_convert_name(). r6152 | vasil | 2009-11-10 15:30:20 +0200 (Tue, 10 Nov 2009) | 4 lines branches/5.1: White space fixup. --- storage/innobase/handler/ha_innodb.cc | 179 ++++++++++++++++------- storage/innobase/include/ha_prototypes.h | 25 ++-- storage/innobase/ut/ut0ut.c | 28 ++-- 3 files changed, 152 insertions(+), 80 deletions(-) diff --git a/storage/innobase/handler/ha_innodb.cc b/storage/innobase/handler/ha_innodb.cc index 41d76c5ec55..784cbb6536f 100644 --- a/storage/innobase/handler/ha_innodb.cc +++ b/storage/innobase/handler/ha_innodb.cc @@ -1499,70 +1499,148 @@ innobase_invalidate_query_cache( #endif } -/********************************************************************* -Display an SQL identifier. */ -extern "C" -void -innobase_print_identifier( -/*======================*/ - FILE* f, /* in: output stream */ - trx_t* trx, /* in: transaction */ - ibool table_id,/* in: TRUE=print a table name, - FALSE=print other identifier */ - const char* name, /* in: name to print */ - ulint namelen)/* in: length of name */ +/*****************************************************************//** +Convert an SQL identifier to the MySQL system_charset_info (UTF-8) +and quote it if needed. +@return pointer to the end of buf */ +static +char* +innobase_convert_identifier( +/*========================*/ + char* buf, /*!< out: buffer for converted identifier */ + ulint buflen, /*!< in: length of buf, in bytes */ + const char* id, /*!< in: identifier to convert */ + ulint idlen, /*!< in: length of id, in bytes */ + void* thd, /*!< in: MySQL connection thread, or NULL */ + ibool file_id)/*!< in: TRUE=id is a table or database name; + FALSE=id is an UTF-8 string */ { - const char* s = name; - char* qname = NULL; + char nz[NAME_LEN + 1]; +#if MYSQL_VERSION_ID >= 50141 + char nz2[NAME_LEN + 1 + EXPLAIN_FILENAME_MAX_EXTRA_LENGTH]; +#else /* MYSQL_VERSION_ID >= 50141 */ + char nz2[NAME_LEN + 1 + sizeof srv_mysql50_table_name_prefix]; +#endif /* MYSQL_VERSION_ID >= 50141 */ + + const char* s = id; int q; - if (table_id) { - /* Decode the table name. The filename_to_tablename() - function expects a NUL-terminated string. The input and - output strings buffers must not be shared. The function - only produces more output when the name contains other - characters than [0-9A-Z_a-z]. */ - char* temp_name = (char*) my_malloc((uint) namelen + 1, MYF(MY_WME)); - uint qnamelen = (uint) (namelen - + (1 + sizeof srv_mysql50_table_name_prefix)); + if (file_id) { + /* Decode the table name. The MySQL function expects + a NUL-terminated string. The input and output strings + buffers must not be shared. */ - if (temp_name) { - qname = (char*) my_malloc(qnamelen, MYF(MY_WME)); - if (qname) { - memcpy(temp_name, name, namelen); - temp_name[namelen] = 0; - s = qname; - namelen = filename_to_tablename(temp_name, - qname, qnamelen); - } - my_free(temp_name, MYF(0)); + if (UNIV_UNLIKELY(idlen > (sizeof nz) - 1)) { + idlen = (sizeof nz) - 1; } + + memcpy(nz, id, idlen); + nz[idlen] = 0; + + s = nz2; +#if MYSQL_VERSION_ID >= 50141 + idlen = explain_filename((THD*) thd, nz, nz2, sizeof nz2, + EXPLAIN_PARTITIONS_AS_COMMENT); + goto no_quote; +#else /* MYSQL_VERSION_ID >= 50141 */ + idlen = filename_to_tablename(nz, nz2, sizeof nz2); +#endif /* MYSQL_VERSION_ID >= 50141 */ } - if (!trx || !trx->mysql_thd) { - + /* See if the identifier needs to be quoted. */ + if (UNIV_UNLIKELY(!thd)) { q = '"'; } else { - q = get_quote_char_for_identifier((THD*) trx->mysql_thd, - s, (int) namelen); + q = get_quote_char_for_identifier((THD*) thd, s, (int) idlen); } if (q == EOF) { - fwrite(s, 1, namelen, f); - } else { - const char* e = s + namelen; - putc(q, f); - while (s < e) { - int c = *s++; - if (c == q) { - putc(c, f); - } - putc(c, f); +#if MYSQL_VERSION_ID >= 50141 +no_quote: +#endif /* MYSQL_VERSION_ID >= 50141 */ + if (UNIV_UNLIKELY(idlen > buflen)) { + idlen = buflen; } - putc(q, f); + memcpy(buf, s, idlen); + return(buf + idlen); } - my_free(qname, MYF(MY_ALLOW_ZERO_PTR)); + /* Quote the identifier. */ + if (buflen < 2) { + return(buf); + } + + *buf++ = q; + buflen--; + + for (; idlen; idlen--) { + int c = *s++; + if (UNIV_UNLIKELY(c == q)) { + if (UNIV_UNLIKELY(buflen < 3)) { + break; + } + + *buf++ = c; + *buf++ = c; + buflen -= 2; + } else { + if (UNIV_UNLIKELY(buflen < 2)) { + break; + } + + *buf++ = c; + buflen--; + } + } + + *buf++ = q; + return(buf); +} + +/*****************************************************************//** +Convert a table or index name to the MySQL system_charset_info (UTF-8) +and quote it if needed. +@return pointer to the end of buf */ +extern "C" +char* +innobase_convert_name( +/*==================*/ + char* buf, /*!< out: buffer for converted identifier */ + ulint buflen, /*!< in: length of buf, in bytes */ + const char* id, /*!< in: identifier to convert */ + ulint idlen, /*!< in: length of id, in bytes */ + void* thd, /*!< in: MySQL connection thread, or NULL */ + ibool table_id)/*!< in: TRUE=id is a table or database name; + FALSE=id is an index name */ +{ + char* s = buf; + const char* bufend = buf + buflen; + + if (table_id) { + const char* slash = (const char*) memchr(id, '/', idlen); + if (!slash) { + + goto no_db_name; + } + + /* Print the database name and table name separately. */ + s = innobase_convert_identifier(s, bufend - s, id, slash - id, + thd, TRUE); + if (UNIV_LIKELY(s < bufend)) { + *s++ = '.'; + s = innobase_convert_identifier(s, bufend - s, + slash + 1, idlen + - (slash - id) - 1, + thd, TRUE); + } + } else { +no_db_name: + s = innobase_convert_identifier(buf, buflen, id, idlen, + thd, table_id); + } + + return(s); + } /************************************************************************** @@ -8194,8 +8272,7 @@ innobase_xa_prepare( executing XA PREPARE and XA COMMIT commands. In this case we cannot know how many minutes or hours will be between XA PREPARE and XA COMMIT, and we don't want - to block for undefined period of time. - */ + to block for undefined period of time. */ pthread_mutex_lock(&prepare_commit_mutex); trx->active_trans = 2; } diff --git a/storage/innobase/include/ha_prototypes.h b/storage/innobase/include/ha_prototypes.h index 6bfc43579b3..ce790814818 100644 --- a/storage/innobase/include/ha_prototypes.h +++ b/storage/innobase/include/ha_prototypes.h @@ -24,18 +24,21 @@ innobase_convert_string( CHARSET_INFO* from_cs, uint* errors); -/********************************************************************* -Display an SQL identifier. */ +/*****************************************************************//** +Convert a table or index name to the MySQL system_charset_info (UTF-8) +and quote it if needed. +@return pointer to the end of buf */ -void -innobase_print_identifier( -/*======================*/ - FILE* f, /* in: output stream */ - trx_t* trx, /* in: transaction */ - ibool table_id,/* in: TRUE=print a table name, - FALSE=print other identifier */ - const char* name, /* in: name to print */ - ulint namelen);/* in: length of name */ +char* +innobase_convert_name( +/*==================*/ + char* buf, /*!< out: buffer for converted identifier */ + ulint buflen, /*!< in: length of buf, in bytes */ + const char* id, /*!< in: identifier to convert */ + ulint idlen, /*!< in: length of id, in bytes */ + void* thd, /*!< in: MySQL connection thread, or NULL */ + ibool table_id);/*!< in: TRUE=id is a table or database name; + FALSE=id is an index name */ /********************************************************************** Returns true if the thread is the replication thread on the slave diff --git a/storage/innobase/ut/ut0ut.c b/storage/innobase/ut/ut0ut.c index 6b5bcef1830..3b26d83bbb9 100644 --- a/storage/innobase/ut/ut0ut.c +++ b/storage/innobase/ut/ut0ut.c @@ -19,6 +19,7 @@ Created 5/11/1994 Heikki Tuuri #include "ut0sort.h" #include "trx0trx.h" #include "ha_prototypes.h" +#include "mysql_com.h" /* NAME_LEN */ ibool ut_always_false = FALSE; @@ -484,26 +485,17 @@ ut_print_namel( const char* name, /* in: name to print */ ulint namelen)/* in: length of name */ { -#ifdef UNIV_HOTBACKUP - fwrite(name, 1, namelen, f); -#else - if (table_id) { - char* slash = memchr(name, '/', namelen); - if (!slash) { + /* 2 * NAME_LEN for database and table name, + and some slack for the #mysql50# prefix and quotes */ + char buf[3 * NAME_LEN]; + const char* bufend; - goto no_db_name; - } + bufend = innobase_convert_name(buf, sizeof buf, + name, namelen, + trx ? trx->mysql_thd : NULL, + table_id); - /* Print the database name and table name separately. */ - innobase_print_identifier(f, trx, TRUE, name, slash - name); - putc('.', f); - innobase_print_identifier(f, trx, TRUE, slash + 1, - namelen - (slash - name) - 1); - } else { -no_db_name: - innobase_print_identifier(f, trx, table_id, name, namelen); - } -#endif + fwrite(buf, 1, bufend - buf, f); } /************************************************************************** From 42162b7ab306e81b520d3c8ecea6a95513859fd9 Mon Sep 17 00:00:00 2001 From: Satya B Date: Mon, 30 Nov 2009 14:10:31 +0530 Subject: [PATCH 2/9] Applying InnoDB snapshot 5.1-ss6242, part 2. Fixes BUG#3139 1. BUG#3139 - Mysql crashes: "windows error 995" after several selects on a large DB Detailed revision comments: r6154 | calvin | 2009-11-11 02:51:17 +0200 (Wed, 11 Nov 2009) | 17 lines branches/5.1: fix bug#3139: Mysql crashes: 'windows error 995' after several selects on a large DB During stress environment, Windows AIO may fail with error code ERROR_OPERATION_ABORTED. InnoDB does not handle the error, rather crashes. The cause of the error is unknown, but likely due to faulty hardware or driver. This patch introduces a new error code OS_FILE_OPERATION_ABORTED, which maps to Windows ERROR_OPERATION_ABORTED (995). When the error is detected during AIO, the InnoDB will issue a synchronous retry (read/write). This patch has been extensively tested by MySQL support. Approved by: Marko rb://196 --- storage/innobase/include/os0file.h | 2 ++ storage/innobase/os/os0file.c | 54 +++++++++++++++++++++++++++++- 2 files changed, 55 insertions(+), 1 deletion(-) diff --git a/storage/innobase/include/os0file.h b/storage/innobase/include/os0file.h index 9eb44d3f4a8..e09e1e00408 100644 --- a/storage/innobase/include/os0file.h +++ b/storage/innobase/include/os0file.h @@ -96,6 +96,8 @@ log. */ to become available again */ #define OS_FILE_SHARING_VIOLATION 76 #define OS_FILE_ERROR_NOT_SPECIFIED 77 + /* 78 is used in the plugin */ +#define OS_FILE_OPERATION_ABORTED 79 /* Types for aio operations */ #define OS_FILE_READ 10 diff --git a/storage/innobase/os/os0file.c b/storage/innobase/os/os0file.c index 8fd959512c1..085f62daacc 100644 --- a/storage/innobase/os/os0file.c +++ b/storage/innobase/os/os0file.c @@ -257,6 +257,13 @@ os_file_get_last_error( " software or another instance\n" "InnoDB: of MySQL." " Please close it to get rid of this error.\n"); + } else if (err == ERROR_OPERATION_ABORTED) { + fprintf(stderr, + "InnoDB: The error means that the I/O" + " operation has been aborted\n" + "InnoDB: because of either a thread exit" + " or an application request.\n" + "InnoDB: Retry attempt is made.\n"); } else { fprintf(stderr, "InnoDB: Some operating system error numbers" @@ -278,6 +285,8 @@ os_file_get_last_error( } else if (err == ERROR_SHARING_VIOLATION || err == ERROR_LOCK_VIOLATION) { return(OS_FILE_SHARING_VIOLATION); + } else if (err == ERROR_OPERATION_ABORTED) { + return(OS_FILE_OPERATION_ABORTED); } else { return(100 + err); } @@ -402,6 +411,10 @@ os_file_handle_error_cond_exit( os_thread_sleep(10000000); /* 10 sec */ return(TRUE); + } else if (err == OS_FILE_OPERATION_ABORTED) { + + os_thread_sleep(100000); /* 100 ms */ + return(TRUE); } else { if (name) { fprintf(stderr, "InnoDB: File name %s\n", name); @@ -3692,6 +3705,7 @@ os_aio_windows_handle( ibool ret_val; BOOL ret; DWORD len; + BOOL retry = FALSE; if (segment == ULINT_UNDEFINED) { array = os_aio_sync_array; @@ -3745,14 +3759,52 @@ os_aio_windows_handle( ut_a(TRUE == os_file_flush(slot->file)); } # endif /* UNIV_DO_FLUSH */ + } else if (os_file_handle_error(slot->name, "Windows aio")) { + + retry = TRUE; } else { - os_file_handle_error(slot->name, "Windows aio"); ret_val = FALSE; } os_mutex_exit(array->mutex); + if (retry) { + /* retry failed read/write operation synchronously. + No need to hold array->mutex. */ + + switch (slot->type) { + case OS_FILE_WRITE: + ret = WriteFile(slot->file, slot->buf, + slot->len, &len, + &(slot->control)); + + break; + case OS_FILE_READ: + ret = ReadFile(slot->file, slot->buf, + slot->len, &len, + &(slot->control)); + + break; + default: + ut_error; + } + + if (!ret && GetLastError() == ERROR_IO_PENDING) { + /* aio was queued successfully! + We want a synchronous i/o operation on a + file where we also use async i/o: in Windows + we must use the same wait mechanism as for + async i/o */ + + ret = GetOverlappedResult(slot->file, + &(slot->control), + &len, TRUE); + } + + ret_val = ret && len == slot->len; + } + os_aio_array_free_slot(array, slot); return(ret_val); From f452f1271fd2e13560a289a4975c5f5610e7d9fa Mon Sep 17 00:00:00 2001 From: Satya B Date: Mon, 30 Nov 2009 14:20:08 +0530 Subject: [PATCH 3/9] Applying InnoDB snapshot 5.1-ss6242, part 3. Fixes BUG#48469 1. BUG#4869 - when innodb tablespace is configured too small, crash and corruption! Detailed revision comments: r6187 | jyang | 2009-11-18 05:27:30 +0200 (Wed, 18 Nov 2009) | 9 lines branches/5.1: Fix bug #48469 "when innodb tablespace is configured too small, crash and corruption!". Function btr_create() did not check the return status of fseg_create(), and continue the index creation even there is no sufficient space. rb://205 Approved by Marko r6200 | vasil | 2009-11-19 12:14:23 +0200 (Thu, 19 Nov 2009) | 4 lines branches/5.1: White space fixup - indent under the opening ( r6203 | jyang | 2009-11-19 15:12:22 +0200 (Thu, 19 Nov 2009) | 8 lines branches/5.1: Use btr_free_root() instead of fseg_free() for the fix of bug #48469, because fseg_free() is not defined in the zip branch. And we could save one mini-trasaction started by fseg_free(). Approved by Marko. --- storage/innobase/btr/btr0btr.c | 11 +++++++++-- 1 file changed, 9 insertions(+), 2 deletions(-) diff --git a/storage/innobase/btr/btr0btr.c b/storage/innobase/btr/btr0btr.c index 6e8b43aeb8d..5e8831b5d5e 100644 --- a/storage/innobase/btr/btr0btr.c +++ b/storage/innobase/btr/btr0btr.c @@ -709,8 +709,15 @@ btr_create( } else { /* It is a non-ibuf tree: create a file segment for leaf pages */ - fseg_create(space, page_no, PAGE_HEADER + PAGE_BTR_SEG_LEAF, - mtr); + if (!fseg_create(space, page_no, + PAGE_HEADER + PAGE_BTR_SEG_LEAF, mtr)) { + /* Not enough space for new segment, free root + segment before return. */ + btr_free_root(space, page_no, mtr); + + return(FIL_NULL); + } + /* The fseg create acquires a second latch on the page, therefore we must declare it: */ #ifdef UNIV_SYNC_DEBUG From 986ebaeb4e472585327b87d9c3d22b487f70c873 Mon Sep 17 00:00:00 2001 From: Satya B Date: Mon, 30 Nov 2009 14:23:52 +0530 Subject: [PATCH 4/9] Applying InnoDB snapshot 5.1-ss6242, part 4. Fixes BUG#48526 1. BUG#48526 - Data type for float and double is incorrectly reported in InnoDB table monitor Detailed revision comments: r6188 | jyang | 2009-11-18 07:14:23 +0200 (Wed, 18 Nov 2009) | 8 lines branches/5.1: Fix bug #48526 "Data type for float and double is incorrectly reported in InnoDB table monitor". Certain datatypes are not printed correctly in dtype_print(). rb://204 Approved by Marko. --- storage/innobase/data/data0type.c | 16 ++++++++++++++++ 1 file changed, 16 insertions(+) diff --git a/storage/innobase/data/data0type.c b/storage/innobase/data/data0type.c index 305000d7c0a..a3cfe691404 100644 --- a/storage/innobase/data/data0type.c +++ b/storage/innobase/data/data0type.c @@ -252,6 +252,22 @@ dtype_print( fputs("DATA_SYS", stderr); break; + case DATA_FLOAT: + fputs("DATA_FLOAT", stderr); + break; + + case DATA_DOUBLE: + fputs("DATA_DOUBLE", stderr); + break; + + case DATA_DECIMAL: + fputs("DATA_DECIMAL", stderr); + break; + + case DATA_VARMYSQL: + fputs("DATA_VARMYSQL", stderr); + break; + default: fprintf(stderr, "type %lu", (ulong) mtype); break; From 5660bc11aa1a279093a3687aaebd0bfabecc4dde Mon Sep 17 00:00:00 2001 From: Satya B Date: Mon, 30 Nov 2009 14:33:57 +0530 Subject: [PATCH 5/9] Applying InnoDB snapshot 5.1-ss6242, part 5. Fixes BUG#45961 1. BUG#45961 - DDL on partitioned innodb tables leaves data dictionary in an inconsistent state 2. Fix formatting Detailed revision comments: r6205 | jyang | 2009-11-20 07:55:48 +0200 (Fri, 20 Nov 2009) | 11 lines branches/5.1: Add a special case to handle the Duplicated Key error and return DB_ERROR instead. This is to avoid a possible SIGSEGV by mysql error handling re-entering the storage layer for dup key info without proper table handle. This is to prevent a server crash when error situation in bug #45961 "DDL on partitioned innodb tables leaves data dictionary in an inconsistent state" happens. rb://157 approved by Sunny Bains. r6206 | jyang | 2009-11-20 09:38:43 +0200 (Fri, 20 Nov 2009) | 3 lines branches/5.1: Non-functional change, fix formatting. --- storage/innobase/handler/ha_innodb.cc | 24 ++++++++++++++++++++++++ 1 file changed, 24 insertions(+) diff --git a/storage/innobase/handler/ha_innodb.cc b/storage/innobase/handler/ha_innodb.cc index 784cbb6536f..55c335e25b1 100644 --- a/storage/innobase/handler/ha_innodb.cc +++ b/storage/innobase/handler/ha_innodb.cc @@ -662,6 +662,12 @@ convert_error_code_to_mysql( } else if (error == (int) DB_DUPLICATE_KEY) { + /* Be cautious with returning this error, since + mysql could re-enter the storage layer to get + duplicated key info, the operation requires a + valid table handle and/or transaction information, + which might not always be available in the error + handling stage. */ return(HA_ERR_FOUND_DUPP_KEY); } else if (error == (int) DB_FOREIGN_DUPLICATE_KEY) { @@ -6038,6 +6044,24 @@ ha_innobase::rename_table( innobase_commit_low(trx); trx_free_for_mysql(trx); + /* Add a special case to handle the Duplicated Key error + and return DB_ERROR instead. + This is to avoid a possible SIGSEGV error from mysql error + handling code. Currently, mysql handles the Duplicated Key + error by re-entering the storage layer and getting dup key + info by calling get_dup_key(). This operation requires a valid + table handle ('row_prebuilt_t' structure) which could no + longer be available in the error handling stage. The suggested + solution is to report a 'table exists' error message (since + the dup key error here is due to an existing table whose name + is the one we are trying to rename to) and return the generic + error code. */ + if (error == (int) DB_DUPLICATE_KEY) { + my_error(ER_TABLE_EXISTS_ERROR, MYF(0), to); + + error = DB_ERROR; + } + error = convert_error_code_to_mysql(error, NULL); DBUG_RETURN(error); From 8a78d063607e38611718a1cb9e00c908b6b0a9a0 Mon Sep 17 00:00:00 2001 From: Satya B Date: Mon, 30 Nov 2009 14:38:41 +0530 Subject: [PATCH 6/9] Applying InnoDB snapshot 5.1-ss6242, part 6. Fixes BUG#48482 1. BUG#48482 - innodb-autoinc.test fails with results difference 2. enable the disabled test Detailed revision comments: r6230 | sunny | 2009-11-24 23:52:43 +0200 (Tue, 24 Nov 2009) | 3 lines branches/5.1: Fix autoinc failing test results. (this should be skipped when merging 5.1 into zip) --- mysql-test/r/innodb-autoinc.result | 8 ++++---- mysql-test/t/disabled.def | 1 - 2 files changed, 4 insertions(+), 5 deletions(-) diff --git a/mysql-test/r/innodb-autoinc.result b/mysql-test/r/innodb-autoinc.result index a40a13dbe9f..abb8f3da072 100644 --- a/mysql-test/r/innodb-autoinc.result +++ b/mysql-test/r/innodb-autoinc.result @@ -875,11 +875,11 @@ ALTER TABLE t1 CHANGE c1 d1 INT NOT NULL AUTO_INCREMENT; SELECT * FROM t1; d1 1 -3 +2 SELECT * FROM t1; d1 1 -3 +2 INSERT INTO t1 VALUES(null); Got one of the listed errors ALTER TABLE t1 AUTO_INCREMENT = 3; @@ -888,13 +888,13 @@ Table Create Table t1 CREATE TABLE `t1` ( `d1` int(11) NOT NULL AUTO_INCREMENT, PRIMARY KEY (`d1`) -) ENGINE=InnoDB AUTO_INCREMENT=4 DEFAULT CHARSET=latin1 +) ENGINE=InnoDB AUTO_INCREMENT=3 DEFAULT CHARSET=latin1 INSERT INTO t1 VALUES(null); SELECT * FROM t1; d1 1 +2 3 -4 DROP TABLE t1; SET @@SESSION.AUTO_INCREMENT_INCREMENT=1, @@SESSION.AUTO_INCREMENT_OFFSET=1; SHOW VARIABLES LIKE "%auto_inc%"; diff --git a/mysql-test/t/disabled.def b/mysql-test/t/disabled.def index ad7617b9403..ac89c1493cd 100644 --- a/mysql-test/t/disabled.def +++ b/mysql-test/t/disabled.def @@ -13,5 +13,4 @@ kill : Bug#37780 2008-12-03 HHunger need some changes to be query_cache_28249 : Bug#43861 2009-03-25 main.query_cache_28249 fails sporadically partition_innodb_builtin : Bug#32430 2009-09-25 mattiasj Waiting for push of Innodb changes partition_innodb_plugin : Bug#32430 2009-09-25 mattiasj Waiting for push of Innodb changes -innodb-autoinc : Bug#48482 2009-11-02 svoj innodb-autoinc.test fails with results difference rpl_killed_ddl : Bug#45520: rpl_killed_ddl fails sporadically in pb2 From 2bfc0136ac26876c39fe0d0008d28ba3006b0924 Mon Sep 17 00:00:00 2001 From: Satya B Date: Mon, 30 Nov 2009 15:11:38 +0530 Subject: [PATCH 7/9] Applying InnoDB snapshot 5.1-ss6242, part 7. Fixes BUG#49032 1. BUG#49032 - auto_increment field does not initialize to last value in InnoDB Storage Engine 2. Fix whitespace issues and fix tests and make read float/double arg const Detailed revision comments: r6231 | sunny | 2009-11-25 10:26:27 +0200 (Wed, 25 Nov 2009) | 7 lines branches/5.1: Fix BUG#49032 - auto_increment field does not initialize to last value in InnoDB Storage Engine. We use the appropriate function to read the column value for non-integer autoinc column types, namely float and double. rb://208. Approved by Marko. r6232 | sunny | 2009-11-25 10:27:39 +0200 (Wed, 25 Nov 2009) | 2 lines branches/5.1: This is an interim fix, fix white space errors. r6233 | sunny | 2009-11-25 10:28:35 +0200 (Wed, 25 Nov 2009) | 2 lines branches/5.1: This is an interim fix, fix tests and make read float/double arg const. r6234 | sunny | 2009-11-25 10:29:03 +0200 (Wed, 25 Nov 2009) | 2 lines branches/5.1: This is an interim fix, fix whitepsace issues. --- mysql-test/r/innodb-autoinc.result | 25 +++++++++++++++++++++++++ mysql-test/t/innodb-autoinc.test | 19 +++++++++++++++++++ storage/innobase/include/mach0data.h | 8 ++++---- storage/innobase/include/mach0data.ic | 8 ++++---- storage/innobase/row/row0sel.c | 25 ++++++++++++++++++++++--- 5 files changed, 74 insertions(+), 11 deletions(-) diff --git a/mysql-test/r/innodb-autoinc.result b/mysql-test/r/innodb-autoinc.result index abb8f3da072..ea759ec328c 100644 --- a/mysql-test/r/innodb-autoinc.result +++ b/mysql-test/r/innodb-autoinc.result @@ -1126,3 +1126,28 @@ SELECT * FROM T1; c1 c2 10 0 DROP TABLE T1; +DROP TABLE IF EXISTS T1; +Warnings: +Note 1051 Unknown table 'T1' +CREATE TABLE T1(C1 DOUBLE AUTO_INCREMENT KEY, C2 CHAR(10)) ENGINE=InnoDB; +INSERT INTO T1(C1, C2) VALUES (1, 'innodb'), (3, 'innodb'); +INSERT INTO T1(C2) VALUES ('innodb'); +SHOW CREATE TABLE T1; +Table Create Table +T1 CREATE TABLE `T1` ( + `C1` double NOT NULL AUTO_INCREMENT, + `C2` char(10) DEFAULT NULL, + PRIMARY KEY (`C1`) +) ENGINE=InnoDB AUTO_INCREMENT=5 DEFAULT CHARSET=latin1 +DROP TABLE T1; +CREATE TABLE T1(C1 FLOAT AUTO_INCREMENT KEY, C2 CHAR(10)) ENGINE=InnoDB; +INSERT INTO T1(C1, C2) VALUES (1, 'innodb'), (3, 'innodb'); +INSERT INTO T1(C2) VALUES ('innodb'); +SHOW CREATE TABLE T1; +Table Create Table +T1 CREATE TABLE `T1` ( + `C1` float NOT NULL AUTO_INCREMENT, + `C2` char(10) DEFAULT NULL, + PRIMARY KEY (`C1`) +) ENGINE=InnoDB AUTO_INCREMENT=5 DEFAULT CHARSET=latin1 +DROP TABLE T1; diff --git a/mysql-test/t/innodb-autoinc.test b/mysql-test/t/innodb-autoinc.test index 3f45bb9d003..468f345724f 100644 --- a/mysql-test/t/innodb-autoinc.test +++ b/mysql-test/t/innodb-autoinc.test @@ -620,3 +620,22 @@ SHOW CREATE TABLE T1; INSERT INTO T1 (c2) values (0); SELECT * FROM T1; DROP TABLE T1; + +## +# 49032: Use the correct function to read the AUTOINC column value +# +DROP TABLE IF EXISTS T1; +CREATE TABLE T1(C1 DOUBLE AUTO_INCREMENT KEY, C2 CHAR(10)) ENGINE=InnoDB; +INSERT INTO T1(C1, C2) VALUES (1, 'innodb'), (3, 'innodb'); +# Restart the server +-- source include/restart_mysqld.inc +INSERT INTO T1(C2) VALUES ('innodb'); +SHOW CREATE TABLE T1; +DROP TABLE T1; +CREATE TABLE T1(C1 FLOAT AUTO_INCREMENT KEY, C2 CHAR(10)) ENGINE=InnoDB; +INSERT INTO T1(C1, C2) VALUES (1, 'innodb'), (3, 'innodb'); +# Restart the server +-- source include/restart_mysqld.inc +INSERT INTO T1(C2) VALUES ('innodb'); +SHOW CREATE TABLE T1; +DROP TABLE T1; diff --git a/storage/innobase/include/mach0data.h b/storage/innobase/include/mach0data.h index 25b619b3f12..d6e040ba9ca 100644 --- a/storage/innobase/include/mach0data.h +++ b/storage/innobase/include/mach0data.h @@ -266,8 +266,8 @@ UNIV_INLINE double mach_double_read( /*=============*/ - /* out: double read */ - byte* b); /* in: pointer to memory from where to read */ + /* out: double read */ + const byte* b); /* in: pointer to memory from where to read */ /************************************************************* Writes a double. It is stored in a little-endian format. */ UNIV_INLINE @@ -282,8 +282,8 @@ UNIV_INLINE float mach_float_read( /*============*/ - /* out: float read */ - byte* b); /* in: pointer to memory from where to read */ + /* out: float read */ + const byte* b); /* in: pointer to memory from where to read */ /************************************************************* Writes a float. It is stored in a little-endian format. */ UNIV_INLINE diff --git a/storage/innobase/include/mach0data.ic b/storage/innobase/include/mach0data.ic index ec15c10c661..dc7918c287b 100644 --- a/storage/innobase/include/mach0data.ic +++ b/storage/innobase/include/mach0data.ic @@ -504,8 +504,8 @@ UNIV_INLINE double mach_double_read( /*=============*/ - /* out: double read */ - byte* b) /* in: pointer to memory from where to read */ + /* out: double read */ + const byte* b) /* in: pointer to memory from where to read */ { double d; ulint i; @@ -553,8 +553,8 @@ UNIV_INLINE float mach_float_read( /*============*/ - /* out: float read */ - byte* b) /* in: pointer to memory from where to read */ + /* out: float read */ + const byte* b) /* in: pointer to memory from where to read */ { float d; ulint i; diff --git a/storage/innobase/row/row0sel.c b/storage/innobase/row/row0sel.c index 1746fb39f43..38902bca905 100644 --- a/storage/innobase/row/row0sel.c +++ b/storage/innobase/row/row0sel.c @@ -4514,6 +4514,7 @@ row_search_autoinc_read_column( dict_index_t* index, /* in: index to read from */ const rec_t* rec, /* in: current rec */ ulint col_no, /* in: column number */ + ulint mtype, /*!< in: column main type */ ibool unsigned_type) /* in: signed or unsigned flag */ { ulint len; @@ -4535,9 +4536,26 @@ row_search_autoinc_read_column( data = rec_get_nth_field((rec_t*)rec, offsets, col_no, &len); ut_a(len != UNIV_SQL_NULL); - ut_a(len <= sizeof value); - value = mach_read_int_type(data, len, unsigned_type); + switch (mtype) { + case DATA_INT: + ut_a(len <= sizeof value); + value = mach_read_int_type(data, len, unsigned_type); + break; + + case DATA_FLOAT: + ut_a(len == sizeof(float)); + value = mach_float_read(data); + break; + + case DATA_DOUBLE: + ut_a(len == sizeof(double)); + value = mach_double_read(data); + break; + + default: + ut_error; + } if (UNIV_LIKELY_NULL(heap)) { mem_heap_free(heap); @@ -4625,7 +4643,8 @@ row_search_max_autoinc( dfield->col->prtype & DATA_UNSIGNED); *value = row_search_autoinc_read_column( - index, rec, i, unsigned_type); + index, rec, i, + dfield->col->mtype, unsigned_type); } } From dfd2a9d0292d381bf169fa4f0099547e973c47f4 Mon Sep 17 00:00:00 2001 From: Satya B Date: Mon, 30 Nov 2009 15:16:45 +0530 Subject: [PATCH 8/9] Applying InnoDB snapshot 5.1-ss6242, part 8. Fixes BUG#47720 1. BUG#47720 - REPLACE INTO Autoincrement column with negative values. Detailed revision comments: r6235 | sunny | 2009-11-26 01:14:42 +0200 (Thu, 26 Nov 2009) | 9 lines branches/5.1: Fix Bug#47720 - REPLACE INTO Autoincrement column with negative values. This bug is similiar to the negative autoinc filter patch from earlier, with the additional handling of filtering out the negative column values set explicitly by the user. rb://184 Approved by Heikki. --- mysql-test/r/innodb-autoinc.result | 39 +++++++++++++++++++++++++++ mysql-test/t/innodb-autoinc.test | 18 +++++++++++++ storage/innobase/handler/ha_innodb.cc | 29 +++++++++++--------- 3 files changed, 74 insertions(+), 12 deletions(-) diff --git a/mysql-test/r/innodb-autoinc.result b/mysql-test/r/innodb-autoinc.result index ea759ec328c..2e0d2c1d776 100644 --- a/mysql-test/r/innodb-autoinc.result +++ b/mysql-test/r/innodb-autoinc.result @@ -1151,3 +1151,42 @@ T1 CREATE TABLE `T1` ( PRIMARY KEY (`C1`) ) ENGINE=InnoDB AUTO_INCREMENT=5 DEFAULT CHARSET=latin1 DROP TABLE T1; +DROP TABLE IF EXISTS t1; +Warnings: +Note 1051 Unknown table 't1' +CREATE TABLE t1 (c1 INT AUTO_INCREMENT PRIMARY KEY) ENGINE=InnoDB; +INSERT INTO t1 SET c1 = 1; +SHOW CREATE TABLE t1; +Table Create Table +t1 CREATE TABLE `t1` ( + `c1` int(11) NOT NULL AUTO_INCREMENT, + PRIMARY KEY (`c1`) +) ENGINE=InnoDB AUTO_INCREMENT=2 DEFAULT CHARSET=latin1 +INSERT INTO t1 SET c1 = 2; +INSERT INTO t1 SET c1 = -1; +SELECT * FROM t1; +c1 +-1 +1 +2 +INSERT INTO t1 SET c1 = -1; +Got one of the listed errors +SHOW CREATE TABLE t1; +Table Create Table +t1 CREATE TABLE `t1` ( + `c1` int(11) NOT NULL AUTO_INCREMENT, + PRIMARY KEY (`c1`) +) ENGINE=InnoDB AUTO_INCREMENT=3 DEFAULT CHARSET=latin1 +REPLACE INTO t1 VALUES (-1); +SELECT * FROM t1; +c1 +-1 +1 +2 +SHOW CREATE TABLE t1; +Table Create Table +t1 CREATE TABLE `t1` ( + `c1` int(11) NOT NULL AUTO_INCREMENT, + PRIMARY KEY (`c1`) +) ENGINE=InnoDB AUTO_INCREMENT=3 DEFAULT CHARSET=latin1 +DROP TABLE t1; diff --git a/mysql-test/t/innodb-autoinc.test b/mysql-test/t/innodb-autoinc.test index 468f345724f..4fa5ab022ad 100644 --- a/mysql-test/t/innodb-autoinc.test +++ b/mysql-test/t/innodb-autoinc.test @@ -639,3 +639,21 @@ INSERT INTO T1(C1, C2) VALUES (1, 'innodb'), (3, 'innodb'); INSERT INTO T1(C2) VALUES ('innodb'); SHOW CREATE TABLE T1; DROP TABLE T1; + +## +# 47720: REPLACE INTO Autoincrement column with negative values +# +DROP TABLE IF EXISTS t1; +CREATE TABLE t1 (c1 INT AUTO_INCREMENT PRIMARY KEY) ENGINE=InnoDB; +INSERT INTO t1 SET c1 = 1; +SHOW CREATE TABLE t1; +INSERT INTO t1 SET c1 = 2; +INSERT INTO t1 SET c1 = -1; +SELECT * FROM t1; +-- error ER_DUP_ENTRY,1062 +INSERT INTO t1 SET c1 = -1; +SHOW CREATE TABLE t1; +REPLACE INTO t1 VALUES (-1); +SELECT * FROM t1; +SHOW CREATE TABLE t1; +DROP TABLE t1; diff --git a/storage/innobase/handler/ha_innodb.cc b/storage/innobase/handler/ha_innodb.cc index 55c335e25b1..f17635c69cc 100644 --- a/storage/innobase/handler/ha_innodb.cc +++ b/storage/innobase/handler/ha_innodb.cc @@ -4060,24 +4060,29 @@ no_commit: update the table upper limit. Note: last_value will be 0 if get_auto_increment() was not called.*/ - if (auto_inc <= col_max_value - && auto_inc >= prebuilt->autoinc_last_value) { + if (auto_inc >= prebuilt->autoinc_last_value) { set_max_autoinc: - ut_a(prebuilt->autoinc_increment > 0); + /* This should filter out the negative + values set explicitly by the user. */ + if (auto_inc <= col_max_value) { + ut_a(prebuilt->autoinc_increment > 0); - ulonglong need; - ulonglong offset; + ulonglong need; + ulonglong offset; - offset = prebuilt->autoinc_offset; - need = prebuilt->autoinc_increment; + offset = prebuilt->autoinc_offset; + need = prebuilt->autoinc_increment; - auto_inc = innobase_next_autoinc( - auto_inc, need, offset, col_max_value); + auto_inc = innobase_next_autoinc( + auto_inc, + need, offset, col_max_value); - err = innobase_set_max_autoinc(auto_inc); + err = innobase_set_max_autoinc( + auto_inc); - if (err != DB_SUCCESS) { - error = err; + if (err != DB_SUCCESS) { + error = err; + } } } break; From 4bb0e504aeeedf7ca22617246ddda651054f52cc Mon Sep 17 00:00:00 2001 From: Satya B Date: Mon, 30 Nov 2009 16:24:20 +0530 Subject: [PATCH 9/9] Applying Innodb Snapshot 5.1-ss6242, part 9. 1. Enabling the disabled test for BUG#32430 for builtin innodb 2. Disabling the innodb-autoinc.test for innodb plugin. --- mysql-test/lib/mtr_cases.pm | 2 ++ mysql-test/t/disabled.def | 1 - 2 files changed, 2 insertions(+), 1 deletion(-) diff --git a/mysql-test/lib/mtr_cases.pm b/mysql-test/lib/mtr_cases.pm index bf73b45ecdf..1f018f27f7b 100644 --- a/mysql-test/lib/mtr_cases.pm +++ b/mysql-test/lib/mtr_cases.pm @@ -520,6 +520,8 @@ sub collect_one_suite($) next if ($test->{'name'} eq 'sys_vars.innodb_thread_concurrency_basic'); # Can't work with InnoPlug. Test framework needs to be re-designed. next if ($test->{'name'} eq 'main.innodb_bug46000'); + # Fails with innodb plugin + next if ($test->{'name'} eq 'main.innodb-autoinc'); # Copy test options my $new_test= My::Test->new(); while (my ($key, $value) = each(%$test)) diff --git a/mysql-test/t/disabled.def b/mysql-test/t/disabled.def index ac89c1493cd..c136a2d5162 100644 --- a/mysql-test/t/disabled.def +++ b/mysql-test/t/disabled.def @@ -11,6 +11,5 @@ ############################################################################## kill : Bug#37780 2008-12-03 HHunger need some changes to be robust enough for pushbuild. query_cache_28249 : Bug#43861 2009-03-25 main.query_cache_28249 fails sporadically -partition_innodb_builtin : Bug#32430 2009-09-25 mattiasj Waiting for push of Innodb changes partition_innodb_plugin : Bug#32430 2009-09-25 mattiasj Waiting for push of Innodb changes rpl_killed_ddl : Bug#45520: rpl_killed_ddl fails sporadically in pb2