From d1ec522f630d6e177a089cf9628b4a47c6de187d Mon Sep 17 00:00:00 2001 From: Sergey Vojtovich Date: Wed, 24 Mar 2010 18:36:05 +0400 Subject: [PATCH 1/6] Applying InnoDB snapshot, fixes BUG#51653 Detailed revision comments: r6774 | calvin | 2010-03-03 23:56:10 +0200 (Wed, 03 Mar 2010) | 2 lines branches/5.1: fix bug#51653: outdated reference to set-variable Non functional change. --- storage/innobase/trx/trx0sys.c | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/storage/innobase/trx/trx0sys.c b/storage/innobase/trx/trx0sys.c index 19c5159e15f..f732aca93f5 100644 --- a/storage/innobase/trx/trx0sys.c +++ b/storage/innobase/trx/trx0sys.c @@ -507,8 +507,8 @@ trx_sys_doublewrite_init_or_restore_pages( " recover the database" " with the my.cnf\n" "InnoDB: option:\n" - "InnoDB: set-variable=" - "innodb_force_recovery=6\n"); + "InnoDB:" + " innodb_force_recovery=6\n"); exit(1); } From 46b421ed7bdcbcc91f48eb5ef4b2ccffae68bef9 Mon Sep 17 00:00:00 2001 From: Sergey Vojtovich Date: Wed, 24 Mar 2010 18:37:23 +0400 Subject: [PATCH 2/6] Applying InnoDB snapshot Detailed revision comments: r6780 | vasil | 2010-03-08 19:13:20 +0200 (Mon, 08 Mar 2010) | 4 lines branches/5.1: Whitespace fixup. --- storage/innobase/plug.in | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/storage/innobase/plug.in b/storage/innobase/plug.in index f7d2abed751..de7302dd6cc 100644 --- a/storage/innobase/plug.in +++ b/storage/innobase/plug.in @@ -1,4 +1,4 @@ -MYSQL_STORAGE_ENGINE(innobase, innodb, [InnoDB Storage Engine], +MYSQL_STORAGE_ENGINE(innobase, innodb, [InnoDB Storage Engine], [Transactional Tables using InnoDB], [max,max-no-ndb]) MYSQL_PLUGIN_DIRECTORY(innobase, [storage/innobase]) MYSQL_PLUGIN_STATIC(innobase, [libinnobase.a]) From 0c8a6f6ccab2ce4438d711c3b9b338fe02bfc4ad Mon Sep 17 00:00:00 2001 From: Sergey Vojtovich Date: Wed, 24 Mar 2010 18:39:23 +0400 Subject: [PATCH 3/6] Applying InnoDB snapshot, fixes BUG#47621. Detailed revision comments: r6783 | jyang | 2010-03-09 17:54:14 +0200 (Tue, 09 Mar 2010) | 9 lines branches/5.1: Fix bug #47621 "MySQL and InnoDB data dictionaries will become out of sync when renaming columns". MySQL does not provide new column name information to storage engine to update the system table. To avoid column name mismatch, we shall just request a table copy for now. rb://246 approved by Marko. --- mysql-test/r/innodb_bug21704.result | 12 +++--- mysql-test/r/innodb_bug47621.result | 21 ++++++++++ mysql-test/t/innodb_bug47621.test | 57 +++++++++++++++++++++++++ storage/innobase/handler/ha_innodb.cc | 60 ++++++++++++++++++++++----- 4 files changed, 133 insertions(+), 17 deletions(-) create mode 100644 mysql-test/r/innodb_bug47621.result create mode 100644 mysql-test/t/innodb_bug47621.test diff --git a/mysql-test/r/innodb_bug21704.result b/mysql-test/r/innodb_bug21704.result index b8e0b15d50d..ffbfa8a337e 100644 --- a/mysql-test/r/innodb_bug21704.result +++ b/mysql-test/r/innodb_bug21704.result @@ -25,8 +25,8 @@ ALTER TABLE t1 CHANGE a c INT; ERROR HY000: Error on rename of '#sql-temporary' to './test/t1' (errno: 150) # Ensure that online column rename works. ALTER TABLE t1 CHANGE b c INT; -affected rows: 0 -info: Records: 0 Duplicates: 0 Warnings: 0 +affected rows: 3 +info: Records: 3 Duplicates: 0 Warnings: 0 # Test renaming the column in the referencing table @@ -34,8 +34,8 @@ ALTER TABLE t2 CHANGE a c INT; ERROR HY000: Error on rename of '#sql-temporary' to './test/t2' (errno: 150) # Ensure that online column rename works. ALTER TABLE t2 CHANGE b c INT; -affected rows: 0 -info: Records: 0 Duplicates: 0 Warnings: 0 +affected rows: 3 +info: Records: 3 Duplicates: 0 Warnings: 0 # Test with self-referential constraints @@ -45,8 +45,8 @@ ALTER TABLE t3 CHANGE b d INT; ERROR HY000: Error on rename of '#sql-temporary' to './test/t3' (errno: 150) # Ensure that online column rename works. ALTER TABLE t3 CHANGE c d INT; -affected rows: 0 -info: Records: 0 Duplicates: 0 Warnings: 0 +affected rows: 3 +info: Records: 3 Duplicates: 0 Warnings: 0 # Cleanup. diff --git a/mysql-test/r/innodb_bug47621.result b/mysql-test/r/innodb_bug47621.result new file mode 100644 index 00000000000..c5f56c09788 --- /dev/null +++ b/mysql-test/r/innodb_bug47621.result @@ -0,0 +1,21 @@ +CREATE TABLE bug47621 (salesperson INT) ENGINE=InnoDB; +ALTER TABLE bug47621 CHANGE salesperson sales_acct_id INT; +create index orgs on bug47621(sales_acct_id); +ALTER TABLE bug47621 CHANGE sales_acct_id salesperson INT; +drop table bug47621; +CREATE TABLE bug47621_sale ( +salesperson INT, +PRIMARY KEY(salesperson)) engine = innodb; +CREATE TABLE bug47621_shirt( +id SMALLINT, +owner INT, +FOREIGN KEY(owner) +references bug47621_sale(salesperson) ON DELETE RESTRICT) +engine = innodb; +insert into bug47621_sale values(9); +insert into bug47621_shirt values(1, 9); +ALTER TABLE bug47621_shirt CHANGE id new_id INT; +drop table bug47621_shirt; +ALTER TABLE bug47621_sale CHANGE salesperson sales_acct_id INT; +ALTER TABLE bug47621_sale ADD INDEX idx (sales_acct_id); +drop table bug47621_sale; diff --git a/mysql-test/t/innodb_bug47621.test b/mysql-test/t/innodb_bug47621.test new file mode 100644 index 00000000000..4863cc6bba1 --- /dev/null +++ b/mysql-test/t/innodb_bug47621.test @@ -0,0 +1,57 @@ +# This is the test for bug #47621, column rename operation should +# not result in column definition inconsistency between MySQL and +# InnoDB + +--source include/have_innodb.inc + +CREATE TABLE bug47621 (salesperson INT) ENGINE=InnoDB; + +# Change the column name +ALTER TABLE bug47621 CHANGE salesperson sales_acct_id INT; + +# If there is inconsistency of column name definition +# in MySQL or InnoDB, following create index would fail +create index orgs on bug47621(sales_acct_id); + +# Change the column name back with the index defined on it. +ALTER TABLE bug47621 CHANGE sales_acct_id salesperson INT; + +drop table bug47621; + +CREATE TABLE bug47621_sale ( + salesperson INT, + PRIMARY KEY(salesperson)) engine = innodb; + +CREATE TABLE bug47621_shirt( + id SMALLINT, + owner INT, + FOREIGN KEY(owner) + references bug47621_sale(salesperson) ON DELETE RESTRICT) + engine = innodb; + +insert into bug47621_sale values(9); + +insert into bug47621_shirt values(1, 9); + +# Any rename operation on columns involved in a reference constraint will +# fail, as it will be rejected by InnoDB row_rename_table_for_mysql(). +# In above example, any rename on column "salesperson" for table +# "bug47621_sale", or on column "owner" for table "bug47621_shirt will +# be blocked. We do not put such rename in the test since InnoDB error +# message will be printed in the error log, and result in test failure. +# +# ALTER TABLE bug47621_sale CHANGE salesperson sales_acct_id INT; + +# Any rename on columns not involved in the foreign key constraint +# could still proceed +ALTER TABLE bug47621_shirt CHANGE id new_id INT; + +# Referencing table dropped, the rename operation on related columns +# could proceed +drop table bug47621_shirt; + +ALTER TABLE bug47621_sale CHANGE salesperson sales_acct_id INT; + +ALTER TABLE bug47621_sale ADD INDEX idx (sales_acct_id); + +drop table bug47621_sale; diff --git a/storage/innobase/handler/ha_innodb.cc b/storage/innobase/handler/ha_innodb.cc index b037fa0d0fd..56f6cccb4f7 100644 --- a/storage/innobase/handler/ha_innodb.cc +++ b/storage/innobase/handler/ha_innodb.cc @@ -8489,6 +8489,44 @@ innobase_set_cursor_view( (cursor_view_t*) curview); } +/*********************************************************************** +If col_name is not NULL, check whether the named column is being +renamed in the table. If col_name is not provided, check +whether any one of columns in the table is being renamed. */ +static +bool +check_column_being_renamed( +/*=======================*/ + /* out: true if find the column + being renamed */ + const TABLE* table, /* in: MySQL table */ + const char* col_name) /* in: name of the column */ +{ + uint k; + Field* field; + + for (k = 0; k < table->s->fields; k++) { + field = table->field[k]; + + if (field->flags & FIELD_IS_RENAMED) { + + /* If col_name is not provided, return + if the field is marked as being renamed. */ + if (!col_name) { + return(true); + } + + /* If col_name is provided, return only + if names match */ + if (innobase_strcasecmp(field->field_name, + col_name) == 0) { + return(true); + } + } + } + + return(false); +} /*********************************************************************** Check whether any of the given columns is being renamed in the table. */ @@ -8503,19 +8541,10 @@ column_is_being_renamed( const char** col_names) /* in: names of the columns */ { uint j; - uint k; - Field* field; - const char* col_name; for (j = 0; j < n_cols; j++) { - col_name = col_names[j]; - for (k = 0; k < table->s->fields; k++) { - field = table->field[k]; - if ((field->flags & FIELD_IS_RENAMED) - && innobase_strcasecmp(field->field_name, - col_name) == 0) { - return(true); - } + if (check_column_being_renamed(table, col_names[j])) { + return(true); } } @@ -8597,6 +8626,15 @@ bool ha_innobase::check_if_incompatible_data( return COMPATIBLE_DATA_NO; } + /* For column rename operation, MySQL does not supply enough + information (new column name etc.) for InnoDB to make appropriate + system metadata change. To avoid system metadata inconsistency, + currently we can just request a table rebuild/copy by returning + COMPATIBLE_DATA_NO */ + if (check_column_being_renamed(table, NULL)) { + return COMPATIBLE_DATA_NO; + } + /* Check if a column participating in a foreign key is being renamed. There is no mechanism for updating InnoDB foreign key definitions. */ if (foreign_key_column_is_being_renamed(prebuilt, table)) { From a10d33386f8b21f5c7d2b01f8abf545fe5c5d4e1 Mon Sep 17 00:00:00 2001 From: Sergey Vojtovich Date: Wed, 24 Mar 2010 18:51:57 +0400 Subject: [PATCH 4/6] Applying InnoDB snapshot Detailed revision comments: r6785 | vasil | 2010-03-10 09:04:38 +0200 (Wed, 10 Mar 2010) | 11 lines branches/5.1: Add the missing --reap statements in innodb_bug38231.test. Probably MySQL enforced the presence of those recently and the test started failing like: main.innodb_bug38231 [ fail ] Test ended at 2010-03-10 08:48:32 CURRENT_TEST: main.innodb_bug38231 mysqltest: At line 49: Cannot run query on connection between send and reap r6788 | vasil | 2010-03-10 10:53:21 +0200 (Wed, 10 Mar 2010) | 8 lines branches/5.1: In innodb_bug38231.test: replace the fragile sleep 0.2 that depends on timing with a more robust condition which waits for the TRUNCATE and LOCK commands to appear in information_schema.processlist. This could also break if there are other sessions executing the same SQL commands, but there are none during the execution of the mysql test. --- mysql-test/t/innodb_bug38231.test | 30 ++++++++++++++++++++++++++---- 1 file changed, 26 insertions(+), 4 deletions(-) diff --git a/mysql-test/t/innodb_bug38231.test b/mysql-test/t/innodb_bug38231.test index b3fcd89f371..54f58844c42 100644 --- a/mysql-test/t/innodb_bug38231.test +++ b/mysql-test/t/innodb_bug38231.test @@ -16,6 +16,7 @@ CREATE TABLE bug38231 (a INT); -- connect (con1,localhost,root,,) -- connect (con2,localhost,root,,) +-- connect (con3,localhost,root,,) -- connection con1 SET autocommit=0; @@ -26,15 +27,30 @@ SET autocommit=0; -- send LOCK TABLE bug38231 WRITE; +-- connection con3 +SET autocommit=0; +-- send +LOCK TABLE bug38231 WRITE; + -- connection default -- send TRUNCATE TABLE bug38231; -- connection con1 -# give time to TRUNCATE and others to be executed; without sleep, sometimes -# UNLOCK executes before TRUNCATE -# TODO: Replace with wait_condition once possible under embedded server. --- sleep 0.2 +# Wait for TRUNCATE and the other two LOCKs to be executed; without this, +# sometimes UNLOCK executes before them. We assume there are no other +# sessions executing at the same time with the same SQL commands. +let $wait_condition = + SELECT COUNT(*) = 1 FROM information_schema.processlist + WHERE info = 'TRUNCATE TABLE bug38231'; +-- source include/wait_condition.inc +let $wait_condition = + SELECT COUNT(*) = 2 FROM information_schema.processlist + WHERE info = 'LOCK TABLE bug38231 WRITE'; +-- source include/wait_condition.inc +# the above enables query log, re-disable it +-- disable_query_log + # this crashes the server if the bug is present UNLOCK TABLES; @@ -44,10 +60,16 @@ UNLOCK TABLES; -- reap UNLOCK TABLES; +-- connection con3 +-- reap +UNLOCK TABLES; + -- connection default -- reap + -- disconnect con1 -- disconnect con2 +-- disconnect con3 # test that TRUNCATE works with with row-level locks From 75aba21f22ae4b4ec6720b70eefdb652e36fc557 Mon Sep 17 00:00:00 2001 From: Sergey Vojtovich Date: Wed, 24 Mar 2010 18:52:28 +0400 Subject: [PATCH 5/6] Applying InnoDB snapshot Detailed revision comments: r6822 | vasil | 2010-03-15 10:17:31 +0200 (Mon, 15 Mar 2010) | 12 lines branches/5.1: Typecast to silence a compiler warning: row/row0sel.c: 4548 C4244: '=' : conversion from 'float' to 'ib_ulonglong', possible loss of data row/row0sel.c: 4553 C4244: '=' : conversion from 'double' to 'ib_ulonglong', possible loss of data Reported by: Jonas Oreland Discussed with: Sunny Bains --- storage/innobase/row/row0sel.c | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/storage/innobase/row/row0sel.c b/storage/innobase/row/row0sel.c index 38902bca905..eee74f280af 100644 --- a/storage/innobase/row/row0sel.c +++ b/storage/innobase/row/row0sel.c @@ -4545,12 +4545,12 @@ row_search_autoinc_read_column( case DATA_FLOAT: ut_a(len == sizeof(float)); - value = mach_float_read(data); + value = (ib_ulonglong) mach_float_read(data); break; case DATA_DOUBLE: ut_a(len == sizeof(double)); - value = mach_double_read(data); + value = (ib_ulonglong) mach_double_read(data); break; default: From a1590d2e954916bb90afe4e4976c36861a162bbc Mon Sep 17 00:00:00 2001 From: Sergey Vojtovich Date: Wed, 24 Mar 2010 23:09:23 +0400 Subject: [PATCH 6/6] More exceptions for InnoDB plugin tests. --- mysql-test/lib/mtr_cases.pm | 3 +++ 1 file changed, 3 insertions(+) diff --git a/mysql-test/lib/mtr_cases.pm b/mysql-test/lib/mtr_cases.pm index 1b6896e5a80..218701ff4a7 100644 --- a/mysql-test/lib/mtr_cases.pm +++ b/mysql-test/lib/mtr_cases.pm @@ -532,6 +532,9 @@ sub collect_one_suite($) next if ($test->{'name'} eq 'main.innodb-autoinc'); # Fails with innodb plugin: r6185 Testcases changes not included next if ($test->{'name'} eq 'main.innodb_bug44369'); + # Fix for BUG47621 is not in InnoDB plugin + next if ($test->{'name'} eq 'main.innodb_bug21704'); + next if ($test->{'name'} eq 'main.innodb_bug47621'); # Copy test options my $new_test= My::Test->new(); while (my ($key, $value) = each(%$test))