List:Commits« Previous MessageNext Message »
From:marko.makela Date:June 1 2012 11:35am
Subject:bzr push into mysql-trunk-wl6255 branch (marko.makela:3925 to 3926) WL#6255
View as plain text  
 3926 Marko Mäkelä	2012-06-01
      WL#6255 ALTER_COLUMN_NOT_NULLABLE (MODIFY a column to be NOT NULL)
      
      Rename DB_PRIMARY_KEY_IS_NULL to DB_INVALID_NULL, mapped to
      ER_INVALID_USE_OF_NULL.
      
      innobase_check_foreigns_low(), innobase_check_foreigns(): Check if a
      column that is beind dropped (not yet implemented) or set to NOT NULL
      is needed by a FOREIGN KEY constraint, or by a FOREIGN KEY constraint
      that includes a SET NULL action.
      
      prepare_inplace_alter_table_dict(): Add the parameter old_table.
      
      row_log_table_apply_convert_mrec(): Return an error if the conversion
      fails. Currently, the only error is DB_INVALID_NULL.

    modified:
      mysql-test/r/alter_table.result
      mysql-test/suite/innodb/r/innodb-alter-nullable.result
      mysql-test/suite/innodb/r/innodb-index.result
      mysql-test/suite/innodb/r/innodb-table-online.result
      mysql-test/suite/innodb/r/innodb.result
      mysql-test/suite/innodb/r/innodb_16k.result
      mysql-test/suite/innodb/r/innodb_misc1.result
      mysql-test/suite/innodb/t/innodb-alter-nullable.test
      mysql-test/suite/innodb/t/innodb-index.test
      mysql-test/suite/innodb/t/innodb-table-online.test
      mysql-test/suite/innodb/t/innodb.test
      mysql-test/suite/innodb/t/innodb_misc1.test
      sql/share/errmsg-utf8.txt
      storage/innobase/handler/ha_innodb.cc
      storage/innobase/handler/handler0alter.cc
      storage/innobase/include/db0err.h
      storage/innobase/row/row0log.cc
      storage/innobase/row/row0merge.cc
      storage/innobase/ut/ut0ut.cc
 3925 Marko Mäkelä	2012-06-01
      Bug#14145138 work-around for WL#5545 ALTER_COLUMN_NAME (rename column).
      
      When a table contains or is referenced by FOREIGN KEY constraints, and
      the table is rebuilt (ADD PRIMARY KEY or otherwise) while renaming
      columns, the columns were not renamed in the FOREIGN KEY constraints.
      This would cause an implicit DROP TABLE (Bug#14145138), because the
      dict_load_foreigns() call in row_merge_rename_tables() would fail.
      
      This fix does not address Bug#14145138, it just prevents one scenario
      leading to it.
      
      innobase_rename_column(): Add the parameter new_clustered, so that
      column names in FOREIGN KEY constraints can be renamed when rebuilding
      a table. Previously, we only renamed columns if the table was not being
      rebuilt.
      
      innobase_rename_columns(): New function, to invoke
      innobase_rename_column() on all renamed columns. Invoke this also when
      rebuilding a table (new_clustered==true).

    modified:
      mysql-test/suite/innodb/r/innodb-index.result
      mysql-test/suite/innodb/t/innodb-index.test
      storage/innobase/handler/handler0alter.cc
=== modified file 'mysql-test/r/alter_table.result'
--- a/mysql-test/r/alter_table.result	revid:marko.makela@stripped
+++ b/mysql-test/r/alter_table.result	revid:marko.makela@oracle.com-20120601113420-mexo5blcdy8vnz8g
@@ -1764,8 +1764,8 @@ ALTER TABLE tm1 MODIFY COLUMN e INT FIRS
 affected rows: 2
 info: Records: 2  Duplicates: 0  Warnings: 0
 ALTER TABLE ti1 MODIFY COLUMN c INT NOT NULL;
-affected rows: 2
-info: Records: 2  Duplicates: 0  Warnings: 0
+affected rows: 0
+info: Records: 0  Duplicates: 0  Warnings: 0
 ALTER TABLE tm1 MODIFY COLUMN c INT NOT NULL;
 affected rows: 2
 info: Records: 2  Duplicates: 0  Warnings: 0

=== modified file 'mysql-test/suite/innodb/r/innodb-alter-nullable.result'
--- a/mysql-test/suite/innodb/r/innodb-alter-nullable.result	revid:marko.makela@stripped1091526-xbtmjnaw20exebzq
+++ b/mysql-test/suite/innodb/r/innodb-alter-nullable.result	revid:marko.makela@strippedm-20120601113420-mexo5blcdy8vnz8g
@@ -1,8 +1,11 @@
 CREATE TABLE t (c1 INT PRIMARY KEY, c2 INT NOT NULL, c3 INT) ENGINE=InnoDB;
 INSERT INTO t VALUES (1,2,3),(4,5,6),(7,8,9);
 ALTER TABLE t CHANGE c1 c1 INT NULL FIRST, ALGORITHM=INPLACE;
+affected rows: 0
+info: Records: 0  Duplicates: 0  Warnings: 0
 ALTER TABLE t MODIFY c3 INT NOT NULL, ALGORITHM=INPLACE;
-ERROR 42000: This version of MySQL doesn't yet support 'ALTER TABLE t MODIFY c3 INT NOT NULL, ALGORITHM=INPLACE'
+affected rows: 0
+info: Records: 0  Duplicates: 0  Warnings: 0
 ALTER TABLE t CHANGE c2 c2 INT, CHANGE c2 c2 INT NOT NULL;
 ERROR 42S22: Unknown column 'c2' in 't'
 ALTER TABLE t MODIFY c2 INT, MODIFY c2 INT NOT NULL;
@@ -11,8 +14,12 @@ ALTER TABLE t MODIFY c2 INT UNSIGNED, MO
 ERROR 42S22: Unknown column 'c2' in 't'
 ALTER TABLE t MODIFY c2 CHAR(1) NOT NULL, MODIFY c2 INT NOT NULL;
 ERROR 42S22: Unknown column 'c2' in 't'
-ALTER TABLE t CHANGE c2 c2 INT NOT NULL, ALGORITHM=INPLACE, LOCK=NONE;
-ALTER TABLE t MODIFY c2 INT NOT NULL, ALGORITHM=INPLACE, LOCK=NONE;
+ALTER TABLE t CHANGE c2 c2 INT NOT NULL;
+affected rows: 0
+info: Records: 0  Duplicates: 0  Warnings: 0
+ALTER TABLE t MODIFY c2 INT NOT NULL;
+affected rows: 0
+info: Records: 0  Duplicates: 0  Warnings: 0
 SET SQL_MODE='STRICT_ALL_TABLES';
 UPDATE t SET c2=NULL;
 ERROR 23000: Column 'c2' cannot be null

=== modified file 'mysql-test/suite/innodb/r/innodb-index.result'
--- a/mysql-test/suite/innodb/r/innodb-index.result	revid:marko.makela@stripped
+++ b/mysql-test/suite/innodb/r/innodb-index.result	revid:marko.makela@stripped
@@ -425,9 +425,9 @@ drop table t1;
 create table t1(a int not null, b int not null, c int, primary key (a), key (b)) engine = innodb;
 create table t3(a int not null, c int not null, d int, primary key (a), key (c)) engine = innodb;
 create table t4(a int not null, d int not null, e int, primary key (a), key (d)) engine = innodb;
-create table t2(a int not null, b int not null, c int not null, d int not null, e int,
-foreign key (b) references t1(b) on delete cascade,
-foreign key (c) references t3(c), foreign key (d) references t4(d))
+create table t2(a int not null, b int, c int, d int, e int,
+foreign key (b) references t1(b) on delete set null,
+foreign key (c) references t3(c), foreign key (d) references t4(d) on update set null)
 engine = innodb;
 alter table t1 drop index b;
 ERROR HY000: Cannot drop index 'b': needed in a foreign key constraint
@@ -439,6 +439,10 @@ alter table t2 drop index b;
 ERROR HY000: Cannot drop index 'b': needed in a foreign key constraint
 alter table t2 drop index b, drop index c, drop index d;
 ERROR HY000: Cannot drop index 'b': needed in a foreign key constraint
+alter table t2 MODIFY b INT NOT NULL, ALGORITHM=COPY;
+ERROR HY000: Error on rename of './#sql-temporary' to './test/t2' (errno: 150 - Foreign key constraint is incorrectly formed)
+alter table t2 MODIFY b INT NOT NULL, ALGORITHM=INPLACE;
+ERROR HY000: Column 'b' cannot be NOT NULL: needed in a foreign key constraint 'test/t2_ibfk_1' SET NULL
 create unique index dc on t2 (d,c);
 affected rows: 0
 info: Records: 0  Duplicates: 0  Warnings: 0
@@ -446,7 +450,13 @@ create index dc on t1 (b,c);
 affected rows: 0
 info: Records: 0  Duplicates: 0  Warnings: 0
 alter table t2 add primary key (alpha), change a alpha int,
-change b beta int not null;
+change b beta int not null, change c charlie int not null;
+ERROR HY000: Column 'b' cannot be NOT NULL: needed in a foreign key constraint 'test/t2_ibfk_1' SET NULL
+alter table t2 add primary key (alpha), change a alpha int,
+change c charlie int not null, change d delta int not null;
+ERROR HY000: Column 'd' cannot be NOT NULL: needed in a foreign key constraint 'test/t2_ibfk_3' SET NULL
+alter table t2 add primary key (alpha), change a alpha int,
+change b beta int, modify c int not null;
 affected rows: 0
 info: Records: 0  Duplicates: 0  Warnings: 0
 insert into t1 values (1,1,1);
@@ -490,17 +500,17 @@ show create table t2;
 Table	Create Table
 t2	CREATE TABLE `t2` (
   `alpha` int(11) NOT NULL DEFAULT '0',
-  `beta` int(11) NOT NULL,
+  `beta` int(11) DEFAULT NULL,
   `c` int(11) NOT NULL,
-  `d` int(11) NOT NULL,
+  `d` int(11) DEFAULT NULL,
   `e` int(11) DEFAULT NULL,
   PRIMARY KEY (`alpha`),
   UNIQUE KEY `dc` (`d`,`c`),
   KEY `c` (`c`),
   KEY `beta` (`beta`),
-  CONSTRAINT `t2_ibfk_1` FOREIGN KEY (`beta`) REFERENCES `t1` (`b`) ON DELETE CASCADE,
+  CONSTRAINT `t2_ibfk_1` FOREIGN KEY (`beta`) REFERENCES `t1` (`b`) ON DELETE SET NULL,
   CONSTRAINT `t2_ibfk_2` FOREIGN KEY (`c`) REFERENCES `t3` (`c`),
-  CONSTRAINT `t2_ibfk_3` FOREIGN KEY (`d`) REFERENCES `t4` (`d`)
+  CONSTRAINT `t2_ibfk_3` FOREIGN KEY (`d`) REFERENCES `t4` (`d`) ON UPDATE SET NULL
 ) ENGINE=InnoDB DEFAULT CHARSET=latin1
 delete from t1;
 ERROR 23000: Cannot delete or update a parent row: a foreign key constraint fails (`test`.`t4`, CONSTRAINT `dc` FOREIGN KEY (`a`) REFERENCES `t1` (`a`))
@@ -518,6 +528,7 @@ alpha	beta	c	d	e
 delete from t1;
 select * from t2;
 alpha	beta	c	d	e
+1	NULL	1	1	1
 drop table t2,t4,t3,t1;
 create table t1(a int not null, b int, c char(10), d varchar(20), primary key (a)) engine = innodb default charset=utf8;
 insert into t1 values (1,1,'ab','ab'),(2,2,'ac','ac'),(3,2,'ad','ad'),(4,4,'afe','afe');
@@ -1016,8 +1027,8 @@ DROP TABLE t1;
 CREATE TABLE t1 (a INT, b CHAR(1)) ENGINE=InnoDB;
 INSERT INTO t1 VALUES (3,'a'),(3,'b'),(1,'c'),(0,'d'),(1,'e');
 CREATE TABLE t2 (a INT, b CHAR(1)) ENGINE=InnoDB;
-CREATE TABLE t2i (a INT NOT NULL, b CHAR(1) NOT NULL) ENGINE=InnoDB;
-CREATE TABLE t2c (a INT NOT NULL, b CHAR(1) NOT NULL) ENGINE=InnoDB;
+CREATE TABLE t2i (a INT, b CHAR(1) NOT NULL) ENGINE=InnoDB;
+CREATE TABLE t2c (a INT, b CHAR(1) NOT NULL) ENGINE=InnoDB;
 INSERT INTO t2 SELECT * FROM t1;
 INSERT INTO t2i SELECT * FROM t1;
 INSERT INTO t2c SELECT * FROM t1;
@@ -1032,8 +1043,6 @@ a	b
 SET lock_wait_timeout=1;
 CREATE INDEX t1a ON t1(a);
 ERROR HY000: Lock wait timeout exceeded; try restarting transaction
-ALTER TABLE t2 ADD PRIMARY KEY(a,b), ADD INDEX t2a(a), ALGORITHM=INPLACE;
-ERROR 42000: This version of MySQL doesn't yet support 'ALTER TABLE t2 ADD PRIMARY KEY(a,b), ADD INDEX t2a(a), ALGORITHM=INPLACE'
 CREATE INDEX t2a ON t2(a);
 affected rows: 0
 info: Records: 0  Duplicates: 0  Warnings: 0
@@ -1123,7 +1132,7 @@ t2	CREATE TABLE `t2` (
 show create table t2i;
 Table	Create Table
 t2i	CREATE TABLE `t2i` (
-  `a` int(11) NOT NULL,
+  `a` int(11) NOT NULL DEFAULT '0',
   `b` char(1) NOT NULL,
   PRIMARY KEY (`a`,`b`),
   KEY `t2a` (`a`)
@@ -1131,7 +1140,7 @@ t2i	CREATE TABLE `t2i` (
 show create table t2c;
 Table	Create Table
 t2c	CREATE TABLE `t2c` (
-  `a` int(11) NOT NULL,
+  `a` int(11) NOT NULL DEFAULT '0',
   `b` char(1) NOT NULL,
   PRIMARY KEY (`a`,`b`),
   KEY `t2a` (`a`)

=== modified file 'mysql-test/suite/innodb/r/innodb-table-online.result'
--- a/mysql-test/suite/innodb/r/innodb-table-online.result	revid:marko.makela@stripped
+++ b/mysql-test/suite/innodb/r/innodb-table-online.result	revid:marko.makela@stripped
@@ -254,19 +254,26 @@ ALTER TABLE t1 DROP PRIMARY KEY, ADD PRI
 ERROR 23000: Duplicate entry '' for key 'PRIMARY'
 UPDATE t1 SET c3 = NULL WHERE c3 = '';
 SET lock_wait_timeout = 1;
-SET DEBUG_SYNC = 'row_log_table_apply1_before SIGNAL c3p5_created WAIT_FOR ins_done';
 ALTER TABLE t1 ADD PRIMARY KEY c3p5(c3(5));
 ERROR 42000: Multiple primary key defined
 ALTER TABLE t1 DROP PRIMARY KEY, ADD PRIMARY KEY c3p5(c3(5)),
 ALGORITHM = INPLACE;
-ERROR 42000: This version of MySQL doesn't yet support 'ALTER TABLE t1 DROP PRIMARY KEY, ADD PRIMARY KEY c3p5(c3(5)),
-ALGORITHM = INPLACE'
+ERROR 22004: Invalid use of NULL value
+ALTER TABLE t1 MODIFY c3 TEXT NOT NULL;
+ERROR 22004: Invalid use of NULL value
 UPDATE t1 SET c3=CONCAT(c1,REPEAT('foo',c1)) WHERE c3 IS NULL;
-ALTER TABLE t1 MODIFY c3 TEXT NOT NULL, ALGORITHM = INPLACE;
-ERROR 42000: This version of MySQL doesn't yet support 'ALTER TABLE t1 MODIFY c3 TEXT NOT NULL, ALGORITHM = INPLACE'
+SET DEBUG_SYNC = 'row_log_table_apply1_before SIGNAL c3p5_created0 WAIT_FOR ins_done0';
 ALTER TABLE t1 MODIFY c3 TEXT NOT NULL;
-ALTER TABLE t1 DROP PRIMARY KEY, ADD PRIMARY KEY c3p5(c3(5)),
-ALGORITHM = INPLACE;
+SET DEBUG_SYNC = 'now WAIT_FOR c3p5_created0';
+BEGIN;
+INSERT INTO t1 VALUES(347,33101,'Pikku kakkosen posti');
+INSERT INTO t1 VALUES(33101,347,NULL);
+SET DEBUG_SYNC = 'now SIGNAL ins_done0';
+ERROR 22004: Invalid use of NULL value
+ROLLBACK;
+ALTER TABLE t1 MODIFY c3 TEXT NOT NULL;
+SET DEBUG_SYNC = 'row_log_table_apply1_before SIGNAL c3p5_created WAIT_FOR ins_done';
+ALTER TABLE t1 DROP PRIMARY KEY, ADD PRIMARY KEY c3p5(c3(5));
 SET DEBUG_SYNC = 'now WAIT_FOR c3p5_created';
 SET DEBUG_SYNC = 'ib_after_row_insert SIGNAL ins_done WAIT_FOR ddl_timed_out';
 INSERT INTO t1 VALUES(347,33101,NULL);

=== modified file 'mysql-test/suite/innodb/r/innodb.result'
--- a/mysql-test/suite/innodb/r/innodb.result	revid:marko.makela@stripped
+++ b/mysql-test/suite/innodb/r/innodb.result	revid:marko.makela@stripped
@@ -3006,7 +3006,7 @@ INSERT INTO t1 VALUES (1);
 INSERT INTO t2 VALUES (1);
 ALTER TABLE t2 ADD FOREIGN KEY (a) REFERENCES t1 (a) ON DELETE SET NULL;
 ALTER TABLE t2 MODIFY a INT NOT NULL;
-ERROR HY000: Error on rename of '#sql-temporary' to './test/t2' (errno: 150 - Foreign key constraint is incorrectly formed)
+ERROR HY000: Column 'a' cannot be NOT NULL: needed in a foreign key constraint 'test/t2_ibfk_1' SET NULL
 DELETE FROM t1;
 DROP TABLE t2,t1;
 CREATE TABLE t1 (a VARCHAR(5) COLLATE utf8_unicode_ci PRIMARY KEY)

=== modified file 'mysql-test/suite/innodb/r/innodb_16k.result'
--- a/mysql-test/suite/innodb/r/innodb_16k.result	revid:marko.makela@stripped0exebzq
+++ b/mysql-test/suite/innodb/r/innodb_16k.result	revid:marko.makela@strippedvnz8g
@@ -368,7 +368,7 @@ Table	Op	Msg_type	Msg_text
 test.t1	check	status	OK
 EXPLAIN SELECT * FROM t1 WHERE b LIKE 'adfd%';
 id	select_type	table	type	possible_keys	key	key_len	ref	rows	Extra
-1	SIMPLE	t1	ALL	b	NULL	NULL	NULL	15	Using where
+1	SIMPLE	t1	range	b	b	769	NULL	11	Using where
 DROP TABLE t1;
 # Test 8) Test creating a table that could lead to undo log overflow.
 CREATE TABLE t1(a blob,b blob,c blob,d blob,e blob,f blob,g blob,

=== modified file 'mysql-test/suite/innodb/r/innodb_misc1.result'
--- a/mysql-test/suite/innodb/r/innodb_misc1.result	revid:marko.makela@stripped
+++ b/mysql-test/suite/innodb/r/innodb_misc1.result	revid:marko.makela@stripped
@@ -651,7 +651,7 @@ INSERT INTO t1 VALUES (1);
 INSERT INTO t2 VALUES (1);
 ALTER TABLE t2 ADD FOREIGN KEY (a) REFERENCES t1 (a) ON DELETE SET NULL;
 ALTER TABLE t2 MODIFY a INT NOT NULL;
-ERROR HY000: Error on rename of '#sql-temporary' to './test/t2' (errno: 150 - Foreign key constraint is incorrectly formed)
+ERROR HY000: Column 'a' cannot be NOT NULL: needed in a foreign key constraint 'test/t2_ibfk_1' SET NULL
 DELETE FROM t1;
 DROP TABLE t2,t1;
 CREATE TABLE t1 (a VARCHAR(5) COLLATE utf8_unicode_ci PRIMARY KEY)

=== modified file 'mysql-test/suite/innodb/t/innodb-alter-nullable.test'
--- a/mysql-test/suite/innodb/t/innodb-alter-nullable.test	revid:marko.makela@stripped20120601091526-xbtmjnaw20exebzq
+++ b/mysql-test/suite/innodb/t/innodb-alter-nullable.test	revid:marko.makela@oracle.com-20120601113420-mexo5blcdy8vnz8g
@@ -6,12 +6,12 @@
 CREATE TABLE t (c1 INT PRIMARY KEY, c2 INT NOT NULL, c3 INT) ENGINE=InnoDB;
 INSERT INTO t VALUES (1,2,3),(4,5,6),(7,8,9);
 
+--enable_info
 # This one will be a no-op.
 # MySQL should perhaps issue an error, because it refuses to modify
 # the PRIMARY KEY column c1 from NOT NULL to NULL.
 ALTER TABLE t CHANGE c1 c1 INT NULL FIRST, ALGORITHM=INPLACE;
 
---error ER_NOT_SUPPORTED_YET
 ALTER TABLE t MODIFY c3 INT NOT NULL, ALGORITHM=INPLACE;
 
 # Request some conflicting changes for a single column.
@@ -25,8 +25,9 @@ ALTER TABLE t MODIFY c2 INT UNSIGNED, MO
 ALTER TABLE t MODIFY c2 CHAR(1) NOT NULL, MODIFY c2 INT NOT NULL;
 
 # No-ops.
-ALTER TABLE t CHANGE c2 c2 INT NOT NULL, ALGORITHM=INPLACE, LOCK=NONE;
-ALTER TABLE t MODIFY c2 INT NOT NULL, ALGORITHM=INPLACE, LOCK=NONE;
+ALTER TABLE t CHANGE c2 c2 INT NOT NULL;
+ALTER TABLE t MODIFY c2 INT NOT NULL;
+--disable_info
 
 connect (con1,localhost,root,,);
 connection con1;

=== modified file 'mysql-test/suite/innodb/t/innodb-index.test'
--- a/mysql-test/suite/innodb/t/innodb-index.test	revid:marko.makela@stripped0601091526-xbtmjnaw20exebzq
+++ b/mysql-test/suite/innodb/t/innodb-index.test	revid:marko.makela@stripped01113420-mexo5blcdy8vnz8g
@@ -133,9 +133,9 @@ drop table t1;
 create table t1(a int not null, b int not null, c int, primary key (a), key (b)) engine = innodb;
 create table t3(a int not null, c int not null, d int, primary key (a), key (c)) engine = innodb;
 create table t4(a int not null, d int not null, e int, primary key (a), key (d)) engine = innodb;
-create table t2(a int not null, b int not null, c int not null, d int not null, e int,
-foreign key (b) references t1(b) on delete cascade,
-foreign key (c) references t3(c), foreign key (d) references t4(d))
+create table t2(a int not null, b int, c int, d int, e int,
+foreign key (b) references t1(b) on delete set null,
+foreign key (c) references t3(c), foreign key (d) references t4(d) on update set null)
 engine = innodb;
 --error ER_DROP_INDEX_FK
 alter table t1 drop index b;
@@ -147,13 +147,24 @@ alter table t4 drop index d;
 alter table t2 drop index b;
 --error ER_DROP_INDEX_FK
 alter table t2 drop index b, drop index c, drop index d;
+--replace_regex /test\/#sql-[0-9a-f_]*'/#sql-temporary'/
+--error ER_ERROR_ON_RENAME
+alter table t2 MODIFY b INT NOT NULL, ALGORITHM=COPY;
+--error ER_FK_COLUMN_NOT_NULL
+alter table t2 MODIFY b INT NOT NULL, ALGORITHM=INPLACE;
 --enable_info
 # Apparently, the following makes mysql_alter_table() drop index d.
 create unique index dc on t2 (d,c);
 create index dc on t1 (b,c);
 # This should preserve the foreign key constraints.
+--error ER_FK_COLUMN_NOT_NULL
 alter table t2 add primary key (alpha), change a alpha int,
-change b beta int not null;
+change b beta int not null, change c charlie int not null;
+--error ER_FK_COLUMN_NOT_NULL
+alter table t2 add primary key (alpha), change a alpha int,
+change c charlie int not null, change d delta int not null;
+alter table t2 add primary key (alpha), change a alpha int,
+change b beta int, modify c int not null;
 --disable_info
 insert into t1 values (1,1,1);
 insert into t3 values (1,1,1);
@@ -416,8 +427,8 @@ connection a;
 CREATE TABLE t1 (a INT, b CHAR(1)) ENGINE=InnoDB;
 INSERT INTO t1 VALUES (3,'a'),(3,'b'),(1,'c'),(0,'d'),(1,'e');
 CREATE TABLE t2 (a INT, b CHAR(1)) ENGINE=InnoDB;
-CREATE TABLE t2i (a INT NOT NULL, b CHAR(1) NOT NULL) ENGINE=InnoDB;
-CREATE TABLE t2c (a INT NOT NULL, b CHAR(1) NOT NULL) ENGINE=InnoDB;
+CREATE TABLE t2i (a INT, b CHAR(1) NOT NULL) ENGINE=InnoDB;
+CREATE TABLE t2c (a INT, b CHAR(1) NOT NULL) ENGINE=InnoDB;
 INSERT INTO t2 SELECT * FROM t1;
 INSERT INTO t2i SELECT * FROM t1;
 INSERT INTO t2c SELECT * FROM t1;
@@ -430,9 +441,6 @@ connection a;
 SET lock_wait_timeout=1;
 --error ER_LOCK_WAIT_TIMEOUT
 CREATE INDEX t1a ON t1(a);
-# InnoDB cannot change a column to NOT NULL yet
---error ER_NOT_SUPPORTED_YET
-ALTER TABLE t2 ADD PRIMARY KEY(a,b), ADD INDEX t2a(a), ALGORITHM=INPLACE;
 --enable_info
 CREATE INDEX t2a ON t2(a);
 ALTER TABLE t2i ADD PRIMARY KEY(a,b), ADD INDEX t2a(a), ALGORITHM=INPLACE;

=== modified file 'mysql-test/suite/innodb/t/innodb-table-online.test'
--- a/mysql-test/suite/innodb/t/innodb-table-online.test	revid:marko.makela@stripped20120601091526-xbtmjnaw20exebzq
+++ b/mysql-test/suite/innodb/t/innodb-table-online.test	revid:marko.makela@oracle.com-20120601113420-mexo5blcdy8vnz8g
@@ -250,22 +250,41 @@ CHECK TABLE t1;
 ALTER TABLE t1 DROP PRIMARY KEY, ADD PRIMARY KEY c3p5(c3(5));
 UPDATE t1 SET c3 = NULL WHERE c3 = '';
 SET lock_wait_timeout = 1;
-SET DEBUG_SYNC = 'row_log_table_apply1_before SIGNAL c3p5_created WAIT_FOR ins_done';
 --error ER_MULTIPLE_PRI_KEY
 ALTER TABLE t1 ADD PRIMARY KEY c3p5(c3(5));
-# We do not support changing a column to NOT NULL yet.
---error ER_NOT_SUPPORTED_YET
+--error ER_INVALID_USE_OF_NULL
 ALTER TABLE t1 DROP PRIMARY KEY, ADD PRIMARY KEY c3p5(c3(5)),
 ALGORITHM = INPLACE;
 
+--error ER_INVALID_USE_OF_NULL
+ALTER TABLE t1 MODIFY c3 TEXT NOT NULL;
 UPDATE t1 SET c3=CONCAT(c1,REPEAT('foo',c1)) WHERE c3 IS NULL;
---error ER_NOT_SUPPORTED_YET
-ALTER TABLE t1 MODIFY c3 TEXT NOT NULL, ALGORITHM = INPLACE;
+
+SET DEBUG_SYNC = 'row_log_table_apply1_before SIGNAL c3p5_created0 WAIT_FOR ins_done0';
+--send
+ALTER TABLE t1 MODIFY c3 TEXT NOT NULL;
+
+connection default;
+
+SET DEBUG_SYNC = 'now WAIT_FOR c3p5_created0';
+BEGIN;
+INSERT INTO t1 VALUES(347,33101,'Pikku kakkosen posti');
+INSERT INTO t1 VALUES(33101,347,NULL);
+SET DEBUG_SYNC = 'now SIGNAL ins_done0';
+
+connection con1;
+--error ER_INVALID_USE_OF_NULL
+reap;
+
+connection default;
+ROLLBACK;
+connection con1;
+
 ALTER TABLE t1 MODIFY c3 TEXT NOT NULL;
 
+SET DEBUG_SYNC = 'row_log_table_apply1_before SIGNAL c3p5_created WAIT_FOR ins_done';
 --send
-ALTER TABLE t1 DROP PRIMARY KEY, ADD PRIMARY KEY c3p5(c3(5)),
-ALGORITHM = INPLACE;
+ALTER TABLE t1 DROP PRIMARY KEY, ADD PRIMARY KEY c3p5(c3(5));
 
 connection default;
 SET DEBUG_SYNC = 'now WAIT_FOR c3p5_created';

=== modified file 'mysql-test/suite/innodb/t/innodb.test'
--- a/mysql-test/suite/innodb/t/innodb.test	revid:marko.makela@stripped20601091526-xbtmjnaw20exebzq
+++ b/mysql-test/suite/innodb/t/innodb.test	revid:marko.makela@stripped420-mexo5blcdy8vnz8g
@@ -2337,11 +2337,7 @@ CREATE TABLE t2 (a INT, INDEX(a)) ENGINE
 INSERT INTO t1 VALUES (1);
 INSERT INTO t2 VALUES (1);
 ALTER TABLE t2 ADD FOREIGN KEY (a) REFERENCES t1 (a) ON DELETE SET NULL;
-# mysqltest first does replace_regex, then replace_result
---replace_regex /'[^']*test\/#sql-[0-9a-f_]*'/'#sql-temporary'/
-# Embedded server doesn't chdir to data directory
---replace_result $MYSQLD_DATADIR ./ master-data/ ''
---error 1025
+--error ER_FK_COLUMN_NOT_NULL
 ALTER TABLE t2 MODIFY a INT NOT NULL;
 DELETE FROM t1;
 DROP TABLE t2,t1;

=== modified file 'mysql-test/suite/innodb/t/innodb_misc1.test'
--- a/mysql-test/suite/innodb/t/innodb_misc1.test	revid:marko.makela@stripped
+++ b/mysql-test/suite/innodb/t/innodb_misc1.test	revid:marko.makela@stripped
@@ -955,11 +955,7 @@ CREATE TABLE t2 (a INT, INDEX(a)) ENGINE
 INSERT INTO t1 VALUES (1);
 INSERT INTO t2 VALUES (1);
 ALTER TABLE t2 ADD FOREIGN KEY (a) REFERENCES t1 (a) ON DELETE SET NULL;
-# mysqltest first does replace_regex, then replace_result
---replace_regex /'[^']*test\/#sql-[0-9a-f_]*'/'#sql-temporary'/
-# Embedded server doesn't chdir to data directory
---replace_result $MYSQLD_DATADIR ./ master-data/ ''
---error 1025
+--error ER_FK_COLUMN_NOT_NULL
 ALTER TABLE t2 MODIFY a INT NOT NULL;
 DELETE FROM t1;
 DROP TABLE t2,t1;

=== modified file 'sql/share/errmsg-utf8.txt'
--- a/sql/share/errmsg-utf8.txt	revid:marko.makela@stripped
+++ b/sql/share/errmsg-utf8.txt	revid:marko.makela@stripped0120601113420-mexo5blcdy8vnz8g
@@ -6827,6 +6827,18 @@ ER_FK_INCORRECT_OPTION
 ER_FK_DUP_NAME
 	eng "Duplicate foreign key constraint name '%s'"
 
+ER_FK_COLUMN_CANNOT_DROP
+        eng "Cannot drop column '%-.192s': needed in a foreign key constraint '%-.192s'"
+        ger "Kann Spalte '%-.192s' nicht löschen: wird für eine Fremdschlüsselbeschränkung '%-.192s' benötigt"
+
+ER_FK_COLUMN_CANNOT_DROP_CHILD
+        eng "Cannot drop column '%-.192s': needed in a foreign key constraint '%-.192s' of table '%-.192s'"
+        ger "Kann Spalte '%-.192s' nicht löschen: wird für eine Fremdschlüsselbeschränkung '%-.192s' der Tabelle '%-.192s' benötigt"
+
+ER_FK_COLUMN_NOT_NULL
+        eng "Column '%-.192s' cannot be NOT NULL: needed in a foreign key constraint '%-.192s' SET NULL"
+        ger "Spalte '%-.192s' kann nicht NOT NULL sein: wird für eine Fremdschlüsselbeschränkung '%-.192s' SET NULL benötigt"
+
 #
 #  End of 5.6 error messages.
 #

=== modified file 'storage/innobase/handler/ha_innodb.cc'
--- a/storage/innobase/handler/ha_innodb.cc	revid:marko.makela@oracle.com-20120601091526-xbtmjnaw20exebzq
+++ b/storage/innobase/handler/ha_innodb.cc	revid:marko.makela@oracle.com-20120601113420-mexo5blcdy8vnz8g
@@ -1436,21 +1436,11 @@ convert_error_code_to_mysql(
 
 		return(HA_ERR_LOCK_TABLE_FULL);
 
-	case DB_PRIMARY_KEY_IS_NULL:
-		return(ER_PRIMARY_CANT_HAVE_NULL);
-
 	case DB_FTS_INVALID_DOCID:
 		return(HA_FTS_INVALID_DOCID);
 
 	case DB_TOO_MANY_CONCURRENT_TRXS:
-		/* New error code HA_ERR_TOO_MANY_CONCURRENT_TRXS is only
-		available in 5.1.38 and later, but the plugin should still
-		work with previous versions of MySQL. */
-#ifdef HA_ERR_TOO_MANY_CONCURRENT_TRXS
 		return(HA_ERR_TOO_MANY_CONCURRENT_TRXS);
-#else /* HA_ERR_TOO_MANY_CONCURRENT_TRXS */
-		return(HA_ERR_RECORD_FILE_FULL);
-#endif /* HA_ERR_TOO_MANY_CONCURRENT_TRXS */
 	case DB_UNSUPPORTED:
 		return(HA_ERR_UNSUPPORTED);
 	case DB_INDEX_CORRUPT:

=== modified file 'storage/innobase/handler/handler0alter.cc'
--- a/storage/innobase/handler/handler0alter.cc	revid:marko.makela@strippedxbtmjnaw20exebzq
+++ b/storage/innobase/handler/handler0alter.cc	revid:marko.makela@stripped5blcdy8vnz8g
@@ -57,8 +57,8 @@ static const Alter_inplace_info::HA_ALTE
 	| Alter_inplace_info::DROP_PK_INDEX
 	| Alter_inplace_info::CHANGE_CREATE_OPTION
 	| Alter_inplace_info::ALTER_COLUMN_NULLABLE
-	/*
 	| Alter_inplace_info::ALTER_COLUMN_NOT_NULLABLE
+	/*
 	| Alter_inplace_info::ALTER_COLUMN_TYPE
 	| Alter_inplace_info::ALTER_COLUMN_EQUAL_PACK_LENGTH,
 	| Alter_inplace_info::ALTER_COLUMN_ORDER
@@ -124,9 +124,6 @@ my_error_innodb(
 		my_error(ER_INDEX_COLUMN_TOO_LONG, MYF(0),
 			 DICT_MAX_FIELD_LEN_BY_FORMAT_FLAG(flags));
 		break;
-	case DB_PRIMARY_KEY_IS_NULL:
-		my_error(ER_PRIMARY_CANT_HAVE_NULL, MYF(0));
-		break;
 	case DB_TOO_MANY_CONCURRENT_TRXS:
 		my_error(ER_TOO_MANY_CONCURRENT_TRXS, MYF(0));
 		break;
@@ -144,6 +141,10 @@ my_error_innodb(
 			 page_get_free_space_of_empty(
 				 flags & DICT_TF_COMPACT) / 2);
 		break;
+	case DB_INVALID_NULL:
+		/* TODO: report the row, as we do for DB_DUPLICATE_KEY */
+		my_error(ER_INVALID_USE_OF_NULL, MYF(0));
+		break;
 #ifdef UNIV_DEBUG
 	case DB_SUCCESS:
 	case DB_DUPLICATE_KEY:
@@ -1865,11 +1866,184 @@ online_retry_drop_indexes_with_trx(
 	}
 }
 
+/** Determines if InnoDB is dropping a foreign key constraint.
+@param foreign		the constraint
+@param drop_fk		constraints being dropped
+@param n_drop_fk	number of constraints that are being dropped
+@return whether the constraint is being dropped */
+inline __attribute__((pure, nonnull, warn_unused_result))
+bool
+innobase_dropping_foreign(
+/*======================*/
+	const dict_foreign_t*	foreign,
+	dict_foreign_t**	drop_fk,
+	ulint			n_drop_fk)
+{
+	while (n_drop_fk--) {
+		if (*drop_fk++ == foreign) {
+			return(true);
+		}
+	}
+
+	return(false);
+}
+
+/** Determines if an InnoDB FOREIGN KEY constraint depends on a
+column that is being dropped or modified to NOT NULL.
+@param user_table	InnoDB table as it is before the ALTER operation
+@param col_name		Name of the column being altered
+@param drop_fk		constraints being dropped
+@param n_drop_fk	number of constraints that are being dropped
+@param drop		true=drop column, false=set NOT NULL
+@retval true		Failure (will call my_error())
+@retval false		Success
+*/
+static __attribute__((pure, nonnull, warn_unused_result))
+bool
+innobase_check_foreigns_low(
+/*========================*/
+	const dict_table_t*	user_table,
+	dict_foreign_t**	drop_fk,
+	ulint			n_drop_fk,
+	const char*		col_name,
+	bool			drop)
+{
+	ut_ad(mutex_own(&dict_sys->mutex));
+
+	/* Check if any FOREIGN KEY constraints are defined on this
+	column. */
+	for (const dict_foreign_t* foreign = UT_LIST_GET_FIRST(
+		     user_table->foreign_list);
+	     foreign;
+	     foreign = UT_LIST_GET_NEXT(foreign_list, foreign)) {
+		if (!drop && !(foreign->type
+			       & (DICT_FOREIGN_ON_DELETE_SET_NULL
+				  | DICT_FOREIGN_ON_UPDATE_SET_NULL))) {
+			continue;
+		}
+
+		if (innobase_dropping_foreign(foreign, drop_fk, n_drop_fk)) {
+			continue;
+		}
+
+		for (unsigned f = 0; f < foreign->n_fields; f++) {
+			if (!strcmp(foreign->foreign_col_names[f],
+				   col_name)) {
+				my_error(drop
+					 ? ER_FK_COLUMN_CANNOT_DROP
+					 : ER_FK_COLUMN_NOT_NULL, MYF(0),
+					 col_name, foreign->id);
+				return(true);
+			}
+		}
+	}
+
+	if (!drop) {
+		/* SET NULL clauses on foreign key constraints of
+		child tables affect the child tables, not the parent table.
+		The column can be NOT NULL in the parent table. */
+		return(false);
+	}
+
+	/* Check if any FOREIGN KEY constraints in other tables are
+	referring to the column that is being dropped. */
+	for (const dict_foreign_t* foreign = UT_LIST_GET_FIRST(
+		     user_table->referenced_list);
+	     foreign;
+	     foreign = UT_LIST_GET_NEXT(referenced_list, foreign)) {
+		if (innobase_dropping_foreign(foreign, drop_fk, n_drop_fk)) {
+			continue;
+		}
+
+		for (unsigned f = 0; f < foreign->n_fields; f++) {
+			if (strcmp(foreign->referenced_col_names[f],
+				   col_name)) {
+				continue;
+			}
+
+			ulint	namelen
+				= strlen(foreign->foreign_table_name)
+				+ sizeof srv_mysql50_table_name_prefix;
+			char*	name = static_cast<char*>(
+				ut_malloc(namelen));
+			if (name) {
+				strcpy(name, foreign->foreign_table_name);
+				innobase_convert_tablename(name);
+				ut_ad(strlen(name) < namelen);
+
+				my_error(ER_FK_COLUMN_CANNOT_DROP_CHILD,
+					 MYF(0), col_name, foreign->id,
+					 name);
+				ut_free(name);
+			} else {
+				/* Tolerate malloc() failure and display
+				the raw table name in the error message. */
+				my_error(ER_FK_COLUMN_CANNOT_DROP_CHILD,
+					 MYF(0), col_name, foreign->id,
+					 foreign->foreign_table_name);
+			}
+
+			return(true);
+		}
+	}
+
+	return(false);
+}
+
+/** Determines if an InnoDB FOREIGN KEY constraint depends on a
+column that is being dropped or modified to NOT NULL.
+@param ha_alter_info	Data used during in-place alter
+@param altered_table	MySQL table that is being altered
+@param old_table	MySQL table as it is before the ALTER operation
+@param user_table	InnoDB table as it is before the ALTER operation
+@param drop_fk		constraints being dropped
+@param n_drop_fk	number of constraints that are being dropped
+@retval true		Failure (will call my_error())
+@retval false		Success
+*/
+static __attribute__((pure, nonnull, warn_unused_result))
+bool
+innobase_check_foreigns(
+/*====================*/
+	Alter_inplace_info*	ha_alter_info,
+	const TABLE*		altered_table,
+	const TABLE*		old_table,
+	const dict_table_t*	user_table,
+	dict_foreign_t**	drop_fk,
+	ulint			n_drop_fk)
+{
+	List_iterator_fast<Create_field> cf_it;
+
+	for (Field** fp = old_table->field; *fp; fp++) {
+		cf_it.init(ha_alter_info->alter_info->create_list);
+		const Create_field* new_field;
+
+		ut_ad(!(*fp)->null_ptr == !!((*fp)->flags & NOT_NULL_FLAG));
+
+		while ((new_field = cf_it++)) {
+			if (new_field->field == *fp) {
+				break;
+			}
+		}
+
+		if (!new_field || (new_field->flags & NOT_NULL_FLAG)) {
+			if (innobase_check_foreigns_low(
+				    user_table, drop_fk, n_drop_fk,
+				    (*fp)->field_name, !new_field)) {
+				return(true);
+			}
+		}
+	}
+
+	return(false);
+}
+
 /** Update internal structures with concurrent writes blocked,
 while preparing ALTER TABLE.
 
 @param ha_alter_info	Data used during in-place alter
 @param altered_table	MySQL table that is being altered
+@param old_table	MySQL table as it is before the ALTER operation
 @param user_table	InnoDB table that is being altered
 @param user_trx		User transaction, for locking the table
 @param table_name	Table name in MySQL
@@ -1892,6 +2066,7 @@ prepare_inplace_alter_table_dict(
 /*=============================*/
 	Alter_inplace_info*	ha_alter_info,
 	const TABLE*		altered_table,
+	const TABLE*		old_table,
 	dict_table_t*		user_table,
 	trx_t*			user_trx,
 	const char*		table_name,
@@ -2025,6 +2200,12 @@ prepare_inplace_alter_table_dict(
 			goto new_clustered_failed;
 		}
 
+		if (innobase_check_foreigns(
+			    ha_alter_info, altered_table, old_table,
+			    user_table, drop_foreign, n_drop_foreign)) {
+			goto new_clustered_failed;
+		}
+
 		n_cols = altered_table->s->fields;
 
 		if (add_fts_doc_id) {
@@ -2420,28 +2601,6 @@ error_handled:
 	DBUG_RETURN(true);
 }
 
-/** Determines if InnoDB is dropping a foreign key constraint.
-@param foreign		the constraint
-@param drop_fk		constraints being dropped
-@param n_drop_fk	number of constraints that are being dropped
-@return whether the constraint is being dropped */
-inline __attribute__((pure, nonnull, warn_unused_result))
-bool
-innobase_dropping_foreign(
-/*======================*/
-	const dict_foreign_t*	foreign,
-	dict_foreign_t**	drop_fk,
-	ulint			n_drop_fk)
-{
-	while (n_drop_fk--) {
-		if (*drop_fk++ == foreign) {
-			return(true);
-		}
-	}
-
-	return(false);
-}
-
 /** Determine if fulltext indexes exist in a given table.
 @param table_share	MySQL table
 @return			whether fulltext indexes exist on the table */
@@ -2970,8 +3129,9 @@ err_exit:
 
 	DBUG_ASSERT(user_thd == prebuilt->trx->mysql_thd);
 	DBUG_RETURN(prepare_inplace_alter_table_dict(
-			    ha_alter_info, altered_table, prebuilt->table,
-			    prebuilt->trx, table_share->table_name.str,
+			    ha_alter_info, altered_table, table,
+			    prebuilt->table, prebuilt->trx,
+			    table_share->table_name.str,
 			    heap, drop_index, n_drop_index,
 			    drop_fk, n_drop_fk, add_fk, n_add_fk,
 			    num_fts_index,

=== modified file 'storage/innobase/include/db0err.h'
--- a/storage/innobase/include/db0err.h	revid:marko.makela@strippedtmjnaw20exebzq
+++ b/storage/innobase/include/db0err.h	revid:marko.makela@stripped8g
@@ -93,8 +93,8 @@ enum dberr_t {
 					work with e.g., FT indexes created by
 					a later version of the engine. */
 
-	DB_PRIMARY_KEY_IS_NULL,		/*!< a column in the PRIMARY KEY
-					was found to be NULL */
+	DB_INVALID_NULL,		/*!< a NOT NULL column was found to
+					be NULL during table rebuild */
 
 	DB_STATS_DO_NOT_EXIST,		/*!< an operation that requires the
 					persistent storage, used for recording

=== modified file 'storage/innobase/row/row0log.cc'
--- a/storage/innobase/row/row0log.cc	revid:marko.makela@stripped
+++ b/storage/innobase/row/row0log.cc	revid:marko.makela@oracle.com-20120601113420-mexo5blcdy8vnz8g
@@ -860,8 +860,7 @@ row_log_table_get_pk(
 			field = rec_get_nth_field(rec, offsets, i, &len);
 
 			if (len == UNIV_SQL_NULL) {
-				new_index->online_log->error
-					= DB_PRIMARY_KEY_IS_NULL;
+				new_index->online_log->error = DB_INVALID_NULL;
 				tuple = NULL;
 				goto func_exit;
 			}
@@ -1002,29 +1001,31 @@ row_log_table_is_rollback(
 
 /******************************************************//**
 Converts a log record to a table row.
-@return converted row */
+@return converted row, or NULL if the conversion fails */
 static __attribute__((nonnull, warn_unused_result))
 const dtuple_t*
 row_log_table_apply_convert_mrec(
 /*=============================*/
 	const mrec_t*		mrec,		/*!< in: merge record */
+	const dict_index_t*	index,		/*!< in: index of mrec */
 	const ulint*		offsets,	/*!< in: offsets of mrec */
 	mem_heap_t*		heap,		/*!< in/out: memory heap */
 	dict_table_t*		new_table,	/*!< in/out: table
 						being rebuilt */
 	const struct TABLE*	altered_table,	/*!< in: new MySQL
 						table definition */
-	const row_merge_dup_t*	dup)		/*!< in: old index and table */
+	dberr_t*		error)		/*!< out: DB_SUCCESS or
+						reason of failure */
 {
 	dtuple_t*	row;
 
 	/* This is based on row_build(). */
-	row = dtuple_create(heap, dict_table_get_n_cols(dup->index->table));
-	dict_table_copy_types(row, dup->index->table);
+	row = dtuple_create(heap, dict_table_get_n_cols(index->table));
+	dict_table_copy_types(row, index->table);
 
 	for (ulint i = 0; i < rec_offs_n_fields(offsets); i++) {
 		const dict_field_t*	ind_field
-			= dict_index_get_nth_field(dup->index, i);
+			= dict_index_get_nth_field(index, i);
 		const dict_col_t*	col
 			= dict_field_get_col(ind_field);
 		ulint			col_no
@@ -1037,7 +1038,7 @@ row_log_table_apply_convert_mrec(
 		if (rec_offs_nth_extern(offsets, i)) {
 			data = btr_rec_copy_externally_stored_field(
 				mrec, offsets,
-				dict_table_zip_size(dup->index->table),
+				dict_table_zip_size(index->table),
 				i, &len, heap);
 			ut_a(data);
 			dfield_set_data(dfield, data, len);
@@ -1069,8 +1070,8 @@ row_log_table_apply_convert_mrec(
 
 		if ((new_col->prtype & DATA_NOT_NULL)
 		    && dfield_is_null(dfield)) {
-			/* We got a NULL value in a NOT NULL field. */
-			ut_ad(0);/* TODO: ALTER_COLUMN_NOT_NULLABLE */
+			/* We got a NULL value for a NOT NULL column. */
+			*error = DB_INVALID_NULL;
 			return(NULL);
 		}
 
@@ -1084,6 +1085,7 @@ row_log_table_apply_convert_mrec(
 	/* TODO: convert row to new_table->cols, in case columns are
 	added or dropped or reordered */
 
+	*error = DB_SUCCESS;
 	return(row);
 }
 
@@ -1176,10 +1178,18 @@ row_log_table_apply_insert(
 	row_merge_dup_t*	dup)		/*!< in/out: for reporting
 						duplicate key errors */
 {
+	dberr_t		error;
 	const dtuple_t*	row	= row_log_table_apply_convert_mrec(
-		mrec, offsets, heap, new_table, altered_table, dup);
-	dberr_t		error	= row_log_table_apply_insert_low(
-		thr, row, offsets_heap, heap, new_table, altered_table, dup);
+		mrec, dup->index, offsets, heap, new_table, altered_table,
+		&error);
+
+	ut_ad(!row == (error != DB_SUCCESS));
+
+	if (row) {
+		error = row_log_table_apply_insert_low(
+			thr, row, offsets_heap, heap,
+			new_table, altered_table, dup);
+	}
 
 	if (error != DB_SUCCESS) {
 		/* Report the erroneous row using the old
@@ -1415,7 +1425,14 @@ row_log_table_apply_update(
 	      + (dup->index->online_log->same_pk ? 0 : 2));
 
 	row = row_log_table_apply_convert_mrec(
-		mrec, offsets, heap, new_table, altered_table, dup);
+		mrec, dup->index, offsets, heap,
+		new_table, altered_table, &error);
+
+	ut_ad(!row == (error != DB_SUCCESS));
+
+	if (!row) {
+		goto err_exit;
+	}
 
 	mtr_start(&mtr);
 	btr_pcur_open(index, old_pk, PAGE_CUR_LE,

=== modified file 'storage/innobase/row/row0merge.cc'
--- a/storage/innobase/row/row0merge.cc	revid:marko.makela@stripped
+++ b/storage/innobase/row/row0merge.cc	revid:marko.makela@oracle.com-20120601113420-mexo5blcdy8vnz8g
@@ -1547,7 +1547,7 @@ row_merge_read_clustered_index(
 			ut_ad(!(field_type->prtype & DATA_NOT_NULL));
 
 			if (dfield_is_null(field)) {
-				err = DB_PRIMARY_KEY_IS_NULL;
+				err = DB_INVALID_NULL;
 				trx->error_key_num = 0;
 				goto func_exit;
 			}

=== modified file 'storage/innobase/ut/ut0ut.cc'
--- a/storage/innobase/ut/ut0ut.cc	revid:marko.makela@stripped
+++ b/storage/innobase/ut/ut0ut.cc	revid:marko.makela@stripped20601113420-mexo5blcdy8vnz8g
@@ -763,8 +763,8 @@ ut_strerr(
 		return("Too many concurrent transactions");
 	case DB_UNSUPPORTED:
 		return("Unsupported");
-	case DB_PRIMARY_KEY_IS_NULL:
-		return("Primary key is NULL");
+	case DB_INVALID_NULL:
+		return("NULL value encountered in NOT NULL column");
 	case DB_STATS_DO_NOT_EXIST:
 		return("Persistent statistics do not exist");
 	case DB_FAIL:

No bundle (reason: useless for push emails).
Thread
bzr push into mysql-trunk-wl6255 branch (marko.makela:3925 to 3926) WL#6255marko.makela1 Jun