List:Commits« Previous MessageNext Message »
From:Pekka Nousiainen Date:April 29 2011 7:01am
Subject:bzr push into mysql-5.1-telco-7.0 branch (pekka:4343 to 4346) Bug#11793592
View as plain text  
 4346 Jonas Oreland	2011-04-28
      ndb - bug#11793592 - change error message for 1302-"Out of backup records" to "A backup is already running"

    modified:
      storage/ndb/src/ndbapi/ndberror.c
 4345 Jonas Oreland	2011-04-28
      ndb - adopt fire-trig-conf to multi-tc

    modified:
      storage/ndb/src/kernel/blocks/dblqh/DblqhMain.cpp
 4344 jonas oreland	2011-04-28
      ndb - bug#47952 - fix unique index + replication problem by implmenting deferred unique index maintainance

    added:
      mysql-test/suite/rpl_ndb/r/rpl_ndb_ui.result
      mysql-test/suite/rpl_ndb/r/rpl_ndb_ui2.result
      mysql-test/suite/rpl_ndb/r/rpl_ndb_ui3.result
      mysql-test/suite/rpl_ndb/t/rpl_ndb_ui.test
      mysql-test/suite/rpl_ndb/t/rpl_ndb_ui2.test
      mysql-test/suite/rpl_ndb/t/rpl_ndb_ui3.test
    modified:
      mysql-test/suite/ndb/r/ndb_basic.result
      sql/ha_ndbcluster.cc
      storage/ndb/include/kernel/GlobalSignalNumbers.h
      storage/ndb/include/kernel/signaldata/FireTrigOrd.hpp
      storage/ndb/include/kernel/signaldata/LqhKey.hpp
      storage/ndb/include/kernel/signaldata/PackedSignal.hpp
      storage/ndb/include/kernel/signaldata/TcContinueB.hpp
      storage/ndb/include/kernel/signaldata/TcKeyReq.hpp
      storage/ndb/include/kernel/signaldata/TupKey.hpp
      storage/ndb/include/kernel/trigger_definitions.h
      storage/ndb/include/ndb_version.h.in
      storage/ndb/include/ndbapi/NdbOperation.hpp
      storage/ndb/src/common/debugger/signaldata/LqhKey.cpp
      storage/ndb/src/common/debugger/signaldata/PackedSignal.cpp
      storage/ndb/src/common/debugger/signaldata/TcKeyReq.cpp
      storage/ndb/src/kernel/blocks/ERROR_codes.txt
      storage/ndb/src/kernel/blocks/dblqh/Dblqh.hpp
      storage/ndb/src/kernel/blocks/dblqh/DblqhInit.cpp
      storage/ndb/src/kernel/blocks/dblqh/DblqhMain.cpp
      storage/ndb/src/kernel/blocks/dbtc/Dbtc.hpp
      storage/ndb/src/kernel/blocks/dbtc/DbtcInit.cpp
      storage/ndb/src/kernel/blocks/dbtc/DbtcMain.cpp
      storage/ndb/src/kernel/blocks/dbtup/Dbtup.hpp
      storage/ndb/src/kernel/blocks/dbtup/DbtupCommit.cpp
      storage/ndb/src/kernel/blocks/dbtup/DbtupExecQuery.cpp
      storage/ndb/src/kernel/blocks/dbtup/DbtupGen.cpp
      storage/ndb/src/kernel/blocks/dbtup/DbtupTrigger.cpp
      storage/ndb/src/ndbapi/NdbOperationDefine.cpp
      storage/ndb/src/ndbapi/NdbOperationExec.cpp
      storage/ndb/test/ndbapi/testIndex.cpp
      storage/ndb/test/run-test/daily-basic-tests.txt
 4343 jonas oreland	2011-04-27 [merge]
      ndb - merge first parts of wl4163

    modified:
      storage/ndb/src/kernel/blocks/dbtux/Dbtux.hpp
      storage/ndb/src/kernel/blocks/dbtux/DbtuxBuild.cpp
      storage/ndb/src/kernel/blocks/dbtux/DbtuxDebug.cpp
      storage/ndb/src/kernel/blocks/dbtux/DbtuxGen.cpp
      storage/ndb/src/kernel/blocks/dbtux/DbtuxMaint.cpp
      storage/ndb/src/kernel/blocks/dbtux/DbtuxMeta.cpp
      storage/ndb/src/kernel/blocks/dbtux/DbtuxNode.cpp
      storage/ndb/src/kernel/blocks/dbtux/DbtuxScan.cpp
      storage/ndb/src/kernel/blocks/dbtux/DbtuxSearch.cpp
=== modified file '.bzr-mysql/default.conf'
--- a/.bzr-mysql/default.conf	2011-04-20 14:13:21 +0000
+++ b/.bzr-mysql/default.conf	2011-04-27 21:13:10 +0000
@@ -1,4 +1,4 @@
 [MYSQL]
 post_commit_to = commits@stripped
 post_push_to = commits@stripped
-tree_name = mysql-5.1-telco-7.0-wl4163
+tree_name = mysql-5.1-telco-7.0

=== modified file 'configure.in'
--- a/configure.in	2011-04-08 13:59:44 +0000
+++ b/configure.in	2011-04-26 07:39:21 +0000
@@ -12,7 +12,7 @@ dnl
 dnl When changing the major version number please also check the switch
 dnl statement in mysqlbinlog::check_master_version().  You may also need
 dnl to update version.c in ndb.
-AC_INIT([MySQL Server], [5.1.56-ndb-7.0.24], [], [mysql])
+AC_INIT([MySQL Server], [5.1.56-ndb-7.0.25], [], [mysql])
 
 AC_CONFIG_SRCDIR([sql/mysqld.cc])
 AC_CANONICAL_SYSTEM

=== modified file 'mysql-test/suite/ndb/r/ndb_basic.result'
--- a/mysql-test/suite/ndb/r/ndb_basic.result	2011-04-11 13:36:12 +0000
+++ b/mysql-test/suite/ndb/r/ndb_basic.result	2011-04-28 07:47:53 +0000
@@ -82,6 +82,7 @@ ndb_blob_write_batch_bytes	#
 ndb_cache_check_time	#
 ndb_cluster_connection_pool	#
 ndb_connectstring	#
+ndb_deferred_constraints	#
 ndb_distribution	#
 ndb_extra_logging	#
 ndb_force_send	#

=== added file 'mysql-test/suite/rpl_ndb/combinations'
--- a/mysql-test/suite/rpl_ndb/combinations	1970-01-01 00:00:00 +0000
+++ b/mysql-test/suite/rpl_ndb/combinations	2011-04-21 07:53:16 +0000
@@ -0,0 +1,5 @@
+[row]
+binlog-format=row
+
+[mix]
+binlog-format=mixed

=== modified file 'mysql-test/suite/rpl_ndb/my.cnf'
--- a/mysql-test/suite/rpl_ndb/my.cnf	2011-04-15 12:21:13 +0000
+++ b/mysql-test/suite/rpl_ndb/my.cnf	2011-04-26 09:28:41 +0000
@@ -70,7 +70,12 @@ report-host=                  127.0.0.1
 report-port=                  @mysqld.1.slave.port
 report-user=                  root
 
+# Configure slave mysqld without innodb, and set myisam
+# as default storage engine(since innodb will be default
+# otherwise starting  from 5.5)
 loose-skip-innodb
+default-storage-engine=myisam
+
 skip-slave-start
 
 # Directory where slaves find the dumps generated by "load data"

=== modified file 'mysql-test/suite/rpl_ndb/r/rpl_ndb_2other.result'
--- a/mysql-test/suite/rpl_ndb/r/rpl_ndb_2other.result	2010-12-19 17:07:28 +0000
+++ b/mysql-test/suite/rpl_ndb/r/rpl_ndb_2other.result	2011-04-20 14:36:44 +0000
@@ -4,6 +4,7 @@ SET storage_engine=ndb;
 
 === NDB -> MYISAM ===
 
+[connection slave]
 set @old_slave_exec_mode= @@global.slave_exec_mode;
 set @@global.slave_exec_mode= 'IDEMPOTENT';
 CREATE TABLE mysql.ndb_apply_status
@@ -13,7 +14,9 @@ log_name VARCHAR(255) BINARY NOT NULL,
 start_pos BIGINT UNSIGNED NOT NULL,
 end_pos BIGINT UNSIGNED NOT NULL,
 PRIMARY KEY USING HASH (server_id)) ENGINE=MYISAM;
-SET storage_engine=myisam;
+SET @old_slave_storage_engine=@@global.storage_engine;
+SET @@global.storage_engine=myisam;
+include/start_slave.inc
 --- Doing pre test cleanup --- 
 DROP TABLE IF EXISTS t1;
 --- Create Table Section ---
@@ -404,11 +407,15 @@ TRUNCATE TABLE t1;
 TRUNCATE TABLE t1;
 --- Do Cleanup --
 DROP TABLE IF EXISTS t1;
+[connection slave]
+include/stop_slave.inc
 
 === NDB -> INNODB ===
 
+[connection slave]
 alter table mysql.ndb_apply_status engine=innodb;
-SET storage_engine=innodb;
+SET @@global.storage_engine=innodb;
+include/start_slave.inc
 --- Doing pre test cleanup --- 
 DROP TABLE IF EXISTS t1;
 --- Create Table Section ---
@@ -451,7 +458,7 @@ t1	CREATE TABLE `t1` (
   `y` year(4) DEFAULT NULL,
   `t` date DEFAULT NULL,
   PRIMARY KEY (`id`)
-) ENGINE=MyISAM DEFAULT CHARSET=latin1
+) ENGINE=InnoDB DEFAULT CHARSET=latin1
 STOP SLAVE;
 RESET SLAVE;
 RESET MASTER;
@@ -543,7 +550,7 @@ t1	CREATE TABLE `t1` (
   `total` bigint(20) unsigned DEFAULT NULL,
   `y` year(4) DEFAULT NULL,
   `t` date DEFAULT NULL
-) ENGINE=MyISAM DEFAULT CHARSET=latin1
+) ENGINE=InnoDB DEFAULT CHARSET=latin1
 STOP SLAVE;
 RESET SLAVE;
 RESET MASTER;
@@ -636,7 +643,7 @@ t1	CREATE TABLE `t1` (
   `u` int(11) DEFAULT NULL,
   `v` char(16) DEFAULT 'default',
   PRIMARY KEY (`id`,`total`)
-) ENGINE=MyISAM DEFAULT CHARSET=latin1
+) ENGINE=InnoDB DEFAULT CHARSET=latin1
 SELECT * 
 FROM t1
 ORDER BY id;
@@ -735,7 +742,7 @@ t1	CREATE TABLE `t1` (
   `f` float DEFAULT '0',
   `total` bigint(20) unsigned NOT NULL DEFAULT '0',
   PRIMARY KEY (`id`,`total`)
-) ENGINE=MyISAM DEFAULT CHARSET=latin1
+) ENGINE=InnoDB DEFAULT CHARSET=latin1
 STOP SLAVE;
 RESET SLAVE;
 RESET MASTER;
@@ -799,6 +806,9 @@ TRUNCATE TABLE t1;
 TRUNCATE TABLE t1;
 --- Do Cleanup --
 DROP TABLE IF EXISTS t1;
+[connection slave]
+include/stop_slave.inc
+[connection slave]
 drop table mysql.ndb_apply_status;
 set @@global.slave_exec_mode= @old_slave_exec_mode;
-include/rpl_end.inc
+SET @@global.storage_engine=@old_slave_storage_engine;

=== modified file 'mysql-test/suite/rpl_ndb/r/rpl_ndb_break_3_chain.result'
--- a/mysql-test/suite/rpl_ndb/r/rpl_ndb_break_3_chain.result	2011-04-08 11:06:53 +0000
+++ b/mysql-test/suite/rpl_ndb/r/rpl_ndb_break_3_chain.result	2011-04-26 13:48:44 +0000
@@ -1,31 +1,26 @@
-include/master-slave.inc
-[connection master]
+include/rpl_init.inc [topology=1->2->3]
+include/rpl_connect.inc [creating cluster1]
+include/rpl_connect.inc [creating cluster2]
+include/rpl_connect.inc [creating cluster3]
+[connection cluster1]
 show variables like 'server_id';
 Variable_name	Value
 server_id	1
-reset master;
 select @cluster1_server_id:=(variable_value+0) 
 from information_schema.global_variables 
 where variable_name like 'server_id';
 @cluster1_server_id:=(variable_value+0)
 1
+[connection cluster2]
 show variables like 'server_id';
 Variable_name	Value
 server_id	2
-stop slave;
-reset master;
-reset slave;
-start slave;
+[connection cluster3]
 show variables like 'server_id';
 Variable_name	Value
 server_id	3
-stop slave;
-Warnings:
-Note	1255	Slave already has been stopped
-reset master;
-reset slave;
-start slave;
 First show replication 1->2->3
+[connection cluster1]
 use test;
 create table t1(a int primary key, b varchar(50)) engine=ndb;
 insert into t1 values (1,'Summertime');
@@ -51,8 +46,10 @@ select * from test.t1;
 a	b
 1	Summertime
 Break Cluster3's link with Cluster2
-stop slave;
+[connection cluster3]
+include/stop_slave.inc
 Make further changes on Cluster1
+[connection cluster1]
 insert into test.t1 values (2, "The cotton is high");
 insert into test.t1 values (3, "Daddys rich");
 Show changes exist on Cluster2
@@ -62,6 +59,7 @@ a	b
 2	The cotton is high
 3	Daddys rich
 Check data on Cluster3
+[connection cluster3]
 select * from test.t1 order by a;
 a	b
 1	Summertime
@@ -70,12 +68,17 @@ select * from mysql.ndb_apply_status ord
 server_id	epoch	log_name	start_pos	end_pos
 1	#	#	#	#
 2	#	#	#	#
-start slave;
+include/rpl_change_topology.inc [new topology=1->2,1->3]
+include/start_slave.inc
+[connection cluster1]
 Now show that cluster 3 is successfully replicating from Cluster1
+[connection cluster3]
 select * from test.t1 order by a;
 a	b
 1	Summertime
 2	The cotton is high
 3	Daddys rich
 Clean up
+[connection cluster1]
 drop table test.t1;
+include/rpl_end.inc

=== modified file 'mysql-test/suite/rpl_ndb/r/rpl_ndb_typeconv_all.result'
--- a/mysql-test/suite/rpl_ndb/r/rpl_ndb_typeconv_all.result	2011-04-07 19:57:33 +0000
+++ b/mysql-test/suite/rpl_ndb/r/rpl_ndb_typeconv_all.result	2011-04-21 12:36:25 +0000
@@ -38,111 +38,7 @@ ALL_LOSSY,ALL_NON_LOSSY
 SET GLOBAL SLAVE_TYPE_CONVERSIONS='ALL_LOSSY,ALL_NON_LOSSY';
 **** Running tests with @@SLAVE_TYPE_CONVERSIONS = 'ALL_LOSSY,ALL_NON_LOSSY' ****
 include/rpl_reset.inc
-**** Result of conversions ****
-Source_Type	Target_Type	All_Type_Conversion_Flags	Value_On_Slave
-GEOMETRY       	GEOMETRY       	ALL_LOSSY,ALL_NON_LOSSY  	<Correct value>
-BIT(1)         	BIT(1)         	ALL_LOSSY,ALL_NON_LOSSY  	<Correct value>
-DATE           	DATE           	ALL_LOSSY,ALL_NON_LOSSY  	<Correct value>
-ENUM('master','	ENUM('master','	ALL_LOSSY,ALL_NON_LOSSY  	<Correct value>
-CHAR(10)       	ENUM('master','	ALL_LOSSY,ALL_NON_LOSSY  	<Correct error>
-CHAR(10)       	SET('master','s	ALL_LOSSY,ALL_NON_LOSSY  	<Correct error>
-ENUM('master','	CHAR(10)       	ALL_LOSSY,ALL_NON_LOSSY  	<Correct error>
-SET('master','s	CHAR(10)       	ALL_LOSSY,ALL_NON_LOSSY  	<Correct error>
-SET('master','s	SET('master','s	ALL_LOSSY,ALL_NON_LOSSY  	<Correct value>
-SET('master','s	SET('master','s	ALL_LOSSY,ALL_NON_LOSSY  	<Correct value>
-SET('0','1','2'	SET('0','1','2'	ALL_LOSSY,ALL_NON_LOSSY  	<Correct value>
-SET('0','1','2'	SET('0','1','2'	ALL_LOSSY,ALL_NON_LOSSY  	<Correct value>
-SET('0','1','2'	SET('0','1','2'	ALL_LOSSY,ALL_NON_LOSSY  	<Correct value>
-SET('0','1','2'	SET('0','1','2'	ALL_LOSSY,ALL_NON_LOSSY  	<Correct value>
-TINYINT        	TINYINT        	ALL_LOSSY,ALL_NON_LOSSY  	<Correct value>
-TINYINT        	SMALLINT       	ALL_LOSSY,ALL_NON_LOSSY  	<Correct value>
-TINYINT        	MEDIUMINT      	ALL_LOSSY,ALL_NON_LOSSY  	<Correct value>
-TINYINT        	INT            	ALL_LOSSY,ALL_NON_LOSSY  	<Correct value>
-TINYINT        	BIGINT         	ALL_LOSSY,ALL_NON_LOSSY  	<Correct value>
-SMALLINT       	TINYINT        	ALL_LOSSY,ALL_NON_LOSSY  	<Correct value>
-SMALLINT       	TINYINT        	ALL_LOSSY,ALL_NON_LOSSY  	<Correct value>
-SMALLINT       	TINYINT UNSIGNE	ALL_LOSSY,ALL_NON_LOSSY  	<Correct value>
-SMALLINT       	SMALLINT       	ALL_LOSSY,ALL_NON_LOSSY  	<Correct value>
-SMALLINT       	MEDIUMINT      	ALL_LOSSY,ALL_NON_LOSSY  	<Correct value>
-SMALLINT       	INT            	ALL_LOSSY,ALL_NON_LOSSY  	<Correct value>
-SMALLINT       	BIGINT         	ALL_LOSSY,ALL_NON_LOSSY  	<Correct value>
-MEDIUMINT      	TINYINT        	ALL_LOSSY,ALL_NON_LOSSY  	<Correct value>
-MEDIUMINT      	TINYINT        	ALL_LOSSY,ALL_NON_LOSSY  	<Correct value>
-MEDIUMINT      	TINYINT UNSIGNE	ALL_LOSSY,ALL_NON_LOSSY  	<Correct value>
-MEDIUMINT      	SMALLINT       	ALL_LOSSY,ALL_NON_LOSSY  	<Correct value>
-MEDIUMINT      	MEDIUMINT      	ALL_LOSSY,ALL_NON_LOSSY  	<Correct value>
-MEDIUMINT      	INT            	ALL_LOSSY,ALL_NON_LOSSY  	<Correct value>
-MEDIUMINT      	BIGINT         	ALL_LOSSY,ALL_NON_LOSSY  	<Correct value>
-INT            	TINYINT        	ALL_LOSSY,ALL_NON_LOSSY  	<Correct value>
-INT            	TINYINT        	ALL_LOSSY,ALL_NON_LOSSY  	<Correct value>
-INT            	TINYINT UNSIGNE	ALL_LOSSY,ALL_NON_LOSSY  	<Correct value>
-INT            	SMALLINT       	ALL_LOSSY,ALL_NON_LOSSY  	<Correct value>
-INT            	MEDIUMINT      	ALL_LOSSY,ALL_NON_LOSSY  	<Correct value>
-INT            	INT            	ALL_LOSSY,ALL_NON_LOSSY  	<Correct value>
-INT            	BIGINT         	ALL_LOSSY,ALL_NON_LOSSY  	<Correct value>
-BIGINT         	TINYINT        	ALL_LOSSY,ALL_NON_LOSSY  	<Correct value>
-BIGINT         	SMALLINT       	ALL_LOSSY,ALL_NON_LOSSY  	<Correct value>
-BIGINT         	MEDIUMINT      	ALL_LOSSY,ALL_NON_LOSSY  	<Correct value>
-BIGINT         	INT            	ALL_LOSSY,ALL_NON_LOSSY  	<Correct value>
-BIGINT         	BIGINT         	ALL_LOSSY,ALL_NON_LOSSY  	<Correct value>
-CHAR(20)       	CHAR(20)       	ALL_LOSSY,ALL_NON_LOSSY  	<Correct value>
-CHAR(20)       	CHAR(30)       	ALL_LOSSY,ALL_NON_LOSSY  	<Correct value>
-CHAR(20)       	CHAR(10)       	ALL_LOSSY,ALL_NON_LOSSY  	<Correct value>
-CHAR(20)       	VARCHAR(20)    	ALL_LOSSY,ALL_NON_LOSSY  	<Correct value>
-CHAR(20)       	VARCHAR(30)    	ALL_LOSSY,ALL_NON_LOSSY  	<Correct value>
-CHAR(20)       	VARCHAR(10)    	ALL_LOSSY,ALL_NON_LOSSY  	<Correct value>
-CHAR(20)       	TINYTEXT       	ALL_LOSSY,ALL_NON_LOSSY  	<Correct value>
-CHAR(20)       	TEXT           	ALL_LOSSY,ALL_NON_LOSSY  	<Correct value>
-CHAR(20)       	MEDIUMTEXT     	ALL_LOSSY,ALL_NON_LOSSY  	<Correct value>
-CHAR(20)       	LONGTEXT       	ALL_LOSSY,ALL_NON_LOSSY  	<Correct value>
-VARCHAR(20)    	VARCHAR(20)    	ALL_LOSSY,ALL_NON_LOSSY  	<Correct value>
-VARCHAR(20)    	VARCHAR(30)    	ALL_LOSSY,ALL_NON_LOSSY  	<Correct value>
-VARCHAR(20)    	VARCHAR(10)    	ALL_LOSSY,ALL_NON_LOSSY  	<Correct value>
-VARCHAR(20)    	CHAR(30)       	ALL_LOSSY,ALL_NON_LOSSY  	<Correct value>
-VARCHAR(20)    	CHAR(10)       	ALL_LOSSY,ALL_NON_LOSSY  	<Correct value>
-VARCHAR(20)    	TINYTEXT       	ALL_LOSSY,ALL_NON_LOSSY  	<Correct value>
-VARCHAR(20)    	TEXT           	ALL_LOSSY,ALL_NON_LOSSY  	<Correct value>
-VARCHAR(20)    	MEDIUMTEXT     	ALL_LOSSY,ALL_NON_LOSSY  	<Correct value>
-VARCHAR(20)    	LONGTEXT       	ALL_LOSSY,ALL_NON_LOSSY  	<Correct value>
-VARCHAR(500)   	VARCHAR(500)   	ALL_LOSSY,ALL_NON_LOSSY  	<Correct value>
-VARCHAR(500)   	VARCHAR(510)   	ALL_LOSSY,ALL_NON_LOSSY  	<Correct value>
-VARCHAR(500)   	VARCHAR(255)   	ALL_LOSSY,ALL_NON_LOSSY  	<Correct value>
-VARCHAR(500)   	TINYTEXT       	ALL_LOSSY,ALL_NON_LOSSY  	<Correct value>
-VARCHAR(500)   	TEXT           	ALL_LOSSY,ALL_NON_LOSSY  	<Correct value>
-VARCHAR(500)   	MEDIUMTEXT     	ALL_LOSSY,ALL_NON_LOSSY  	<Correct value>
-VARCHAR(500)   	LONGTEXT       	ALL_LOSSY,ALL_NON_LOSSY  	<Correct value>
-TINYTEXT       	VARCHAR(500)   	ALL_LOSSY,ALL_NON_LOSSY  	<Correct value>
-TEXT           	VARCHAR(500)   	ALL_LOSSY,ALL_NON_LOSSY  	<Correct value>
-MEDIUMTEXT     	VARCHAR(500)   	ALL_LOSSY,ALL_NON_LOSSY  	<Correct value>
-LONGTEXT       	VARCHAR(500)   	ALL_LOSSY,ALL_NON_LOSSY  	<Correct value>
-TINYTEXT       	CHAR(255)      	ALL_LOSSY,ALL_NON_LOSSY  	<Correct value>
-TINYTEXT       	CHAR(250)      	ALL_LOSSY,ALL_NON_LOSSY  	<Correct value>
-TEXT           	CHAR(255)      	ALL_LOSSY,ALL_NON_LOSSY  	<Correct value>
-MEDIUMTEXT     	CHAR(255)      	ALL_LOSSY,ALL_NON_LOSSY  	<Correct value>
-LONGTEXT       	CHAR(255)      	ALL_LOSSY,ALL_NON_LOSSY  	<Correct value>
-TINYTEXT       	TINYTEXT       	ALL_LOSSY,ALL_NON_LOSSY  	<Correct value>
-TINYTEXT       	TEXT           	ALL_LOSSY,ALL_NON_LOSSY  	<Correct value>
-TEXT           	TINYTEXT       	ALL_LOSSY,ALL_NON_LOSSY  	<Correct value>
-DECIMAL(10,5)  	DECIMAL(10,5)  	ALL_LOSSY,ALL_NON_LOSSY  	<Correct value>
-DECIMAL(10,5)  	DECIMAL(10,6)  	ALL_LOSSY,ALL_NON_LOSSY  	<Correct value>
-DECIMAL(10,5)  	DECIMAL(11,5)  	ALL_LOSSY,ALL_NON_LOSSY  	<Correct value>
-DECIMAL(10,5)  	DECIMAL(11,6)  	ALL_LOSSY,ALL_NON_LOSSY  	<Correct value>
-DECIMAL(10,5)  	DECIMAL(10,4)  	ALL_LOSSY,ALL_NON_LOSSY  	<Correct value>
-DECIMAL(10,5)  	DECIMAL(9,5)   	ALL_LOSSY,ALL_NON_LOSSY  	<Correct value>
-DECIMAL(10,5)  	DECIMAL(9,4)   	ALL_LOSSY,ALL_NON_LOSSY  	<Correct value>
-FLOAT          	DECIMAL(10,5)  	ALL_LOSSY,ALL_NON_LOSSY  	<Correct value>
-DOUBLE         	DECIMAL(10,5)  	ALL_LOSSY,ALL_NON_LOSSY  	<Correct value>
-DECIMAL(10,5)  	FLOAT          	ALL_LOSSY,ALL_NON_LOSSY  	<Correct value>
-DECIMAL(10,5)  	DOUBLE         	ALL_LOSSY,ALL_NON_LOSSY  	<Correct value>
-FLOAT          	FLOAT          	ALL_LOSSY,ALL_NON_LOSSY  	<Correct value>
-DOUBLE         	DOUBLE         	ALL_LOSSY,ALL_NON_LOSSY  	<Correct value>
-FLOAT          	DOUBLE         	ALL_LOSSY,ALL_NON_LOSSY  	<Correct value>
-DOUBLE         	FLOAT          	ALL_LOSSY,ALL_NON_LOSSY  	<Correct value>
-BIT(5)         	BIT(5)         	ALL_LOSSY,ALL_NON_LOSSY  	<Correct value>
-BIT(5)         	BIT(6)         	ALL_LOSSY,ALL_NON_LOSSY  	<Correct value>
-BIT(6)         	BIT(5)         	ALL_LOSSY,ALL_NON_LOSSY  	<Correct value>
-BIT(5)         	BIT(12)        	ALL_LOSSY,ALL_NON_LOSSY  	<Correct value>
-BIT(12)        	BIT(5)         	ALL_LOSSY,ALL_NON_LOSSY  	<Correct value>
+**** Checking result of conversions ****
 DROP TABLE type_conversions;
 DROP TABLE t1;
 set global slave_type_conversions = @saved_slave_type_conversions;

=== modified file 'mysql-test/suite/rpl_ndb/r/rpl_ndb_typeconv_lossy.result'
--- a/mysql-test/suite/rpl_ndb/r/rpl_ndb_typeconv_lossy.result	2011-04-07 19:57:33 +0000
+++ b/mysql-test/suite/rpl_ndb/r/rpl_ndb_typeconv_lossy.result	2011-04-21 12:36:25 +0000
@@ -38,111 +38,7 @@ ALL_LOSSY,ALL_NON_LOSSY
 SET GLOBAL SLAVE_TYPE_CONVERSIONS='ALL_LOSSY';
 **** Running tests with @@SLAVE_TYPE_CONVERSIONS = 'ALL_LOSSY' ****
 include/rpl_reset.inc
-**** Result of conversions ****
-Source_Type	Target_Type	All_Type_Conversion_Flags	Value_On_Slave
-GEOMETRY       	GEOMETRY       	ALL_LOSSY                	<Correct value>
-BIT(1)         	BIT(1)         	ALL_LOSSY                	<Correct value>
-DATE           	DATE           	ALL_LOSSY                	<Correct value>
-ENUM('master','	ENUM('master','	ALL_LOSSY                	<Correct value>
-CHAR(10)       	ENUM('master','	ALL_LOSSY                	<Correct error>
-CHAR(10)       	SET('master','s	ALL_LOSSY                	<Correct error>
-ENUM('master','	CHAR(10)       	ALL_LOSSY                	<Correct error>
-SET('master','s	CHAR(10)       	ALL_LOSSY                	<Correct error>
-SET('master','s	SET('master','s	ALL_LOSSY                	<Correct value>
-SET('master','s	SET('master','s	ALL_LOSSY                	<Correct value>
-SET('0','1','2'	SET('0','1','2'	ALL_LOSSY                	<Correct value>
-SET('0','1','2'	SET('0','1','2'	ALL_LOSSY                	<Correct error>
-SET('0','1','2'	SET('0','1','2'	ALL_LOSSY                	<Correct value>
-SET('0','1','2'	SET('0','1','2'	ALL_LOSSY                	<Correct value>
-TINYINT        	TINYINT        	ALL_LOSSY                	<Correct value>
-TINYINT        	SMALLINT       	ALL_LOSSY                	<Correct error>
-TINYINT        	MEDIUMINT      	ALL_LOSSY                	<Correct error>
-TINYINT        	INT            	ALL_LOSSY                	<Correct error>
-TINYINT        	BIGINT         	ALL_LOSSY                	<Correct error>
-SMALLINT       	TINYINT        	ALL_LOSSY                	<Correct value>
-SMALLINT       	TINYINT        	ALL_LOSSY                	<Correct value>
-SMALLINT       	TINYINT UNSIGNE	ALL_LOSSY                	<Correct value>
-SMALLINT       	SMALLINT       	ALL_LOSSY                	<Correct value>
-SMALLINT       	MEDIUMINT      	ALL_LOSSY                	<Correct error>
-SMALLINT       	INT            	ALL_LOSSY                	<Correct error>
-SMALLINT       	BIGINT         	ALL_LOSSY                	<Correct error>
-MEDIUMINT      	TINYINT        	ALL_LOSSY                	<Correct value>
-MEDIUMINT      	TINYINT        	ALL_LOSSY                	<Correct value>
-MEDIUMINT      	TINYINT UNSIGNE	ALL_LOSSY                	<Correct value>
-MEDIUMINT      	SMALLINT       	ALL_LOSSY                	<Correct value>
-MEDIUMINT      	MEDIUMINT      	ALL_LOSSY                	<Correct value>
-MEDIUMINT      	INT            	ALL_LOSSY                	<Correct error>
-MEDIUMINT      	BIGINT         	ALL_LOSSY                	<Correct error>
-INT            	TINYINT        	ALL_LOSSY                	<Correct value>
-INT            	TINYINT        	ALL_LOSSY                	<Correct value>
-INT            	TINYINT UNSIGNE	ALL_LOSSY                	<Correct value>
-INT            	SMALLINT       	ALL_LOSSY                	<Correct value>
-INT            	MEDIUMINT      	ALL_LOSSY                	<Correct value>
-INT            	INT            	ALL_LOSSY                	<Correct value>
-INT            	BIGINT         	ALL_LOSSY                	<Correct error>
-BIGINT         	TINYINT        	ALL_LOSSY                	<Correct value>
-BIGINT         	SMALLINT       	ALL_LOSSY                	<Correct value>
-BIGINT         	MEDIUMINT      	ALL_LOSSY                	<Correct value>
-BIGINT         	INT            	ALL_LOSSY                	<Correct value>
-BIGINT         	BIGINT         	ALL_LOSSY                	<Correct value>
-CHAR(20)       	CHAR(20)       	ALL_LOSSY                	<Correct value>
-CHAR(20)       	CHAR(30)       	ALL_LOSSY                	<Correct error>
-CHAR(20)       	CHAR(10)       	ALL_LOSSY                	<Correct value>
-CHAR(20)       	VARCHAR(20)    	ALL_LOSSY                	<Correct error>
-CHAR(20)       	VARCHAR(30)    	ALL_LOSSY                	<Correct error>
-CHAR(20)       	VARCHAR(10)    	ALL_LOSSY                	<Correct value>
-CHAR(20)       	TINYTEXT       	ALL_LOSSY                	<Correct error>
-CHAR(20)       	TEXT           	ALL_LOSSY                	<Correct error>
-CHAR(20)       	MEDIUMTEXT     	ALL_LOSSY                	<Correct error>
-CHAR(20)       	LONGTEXT       	ALL_LOSSY                	<Correct error>
-VARCHAR(20)    	VARCHAR(20)    	ALL_LOSSY                	<Correct value>
-VARCHAR(20)    	VARCHAR(30)    	ALL_LOSSY                	<Correct error>
-VARCHAR(20)    	VARCHAR(10)    	ALL_LOSSY                	<Correct value>
-VARCHAR(20)    	CHAR(30)       	ALL_LOSSY                	<Correct error>
-VARCHAR(20)    	CHAR(10)       	ALL_LOSSY                	<Correct value>
-VARCHAR(20)    	TINYTEXT       	ALL_LOSSY                	<Correct error>
-VARCHAR(20)    	TEXT           	ALL_LOSSY                	<Correct error>
-VARCHAR(20)    	MEDIUMTEXT     	ALL_LOSSY                	<Correct error>
-VARCHAR(20)    	LONGTEXT       	ALL_LOSSY                	<Correct error>
-VARCHAR(500)   	VARCHAR(500)   	ALL_LOSSY                	<Correct value>
-VARCHAR(500)   	VARCHAR(510)   	ALL_LOSSY                	<Correct error>
-VARCHAR(500)   	VARCHAR(255)   	ALL_LOSSY                	<Correct value>
-VARCHAR(500)   	TINYTEXT       	ALL_LOSSY                	<Correct value>
-VARCHAR(500)   	TEXT           	ALL_LOSSY                	<Correct error>
-VARCHAR(500)   	MEDIUMTEXT     	ALL_LOSSY                	<Correct error>
-VARCHAR(500)   	LONGTEXT       	ALL_LOSSY                	<Correct error>
-TINYTEXT       	VARCHAR(500)   	ALL_LOSSY                	<Correct error>
-TEXT           	VARCHAR(500)   	ALL_LOSSY                	<Correct value>
-MEDIUMTEXT     	VARCHAR(500)   	ALL_LOSSY                	<Correct value>
-LONGTEXT       	VARCHAR(500)   	ALL_LOSSY                	<Correct value>
-TINYTEXT       	CHAR(255)      	ALL_LOSSY                	<Correct error>
-TINYTEXT       	CHAR(250)      	ALL_LOSSY                	<Correct value>
-TEXT           	CHAR(255)      	ALL_LOSSY                	<Correct value>
-MEDIUMTEXT     	CHAR(255)      	ALL_LOSSY                	<Correct value>
-LONGTEXT       	CHAR(255)      	ALL_LOSSY                	<Correct value>
-TINYTEXT       	TINYTEXT       	ALL_LOSSY                	<Correct value>
-TINYTEXT       	TEXT           	ALL_LOSSY                	<Correct error>
-TEXT           	TINYTEXT       	ALL_LOSSY                	<Correct value>
-DECIMAL(10,5)  	DECIMAL(10,5)  	ALL_LOSSY                	<Correct value>
-DECIMAL(10,5)  	DECIMAL(10,6)  	ALL_LOSSY                	<Correct error>
-DECIMAL(10,5)  	DECIMAL(11,5)  	ALL_LOSSY                	<Correct error>
-DECIMAL(10,5)  	DECIMAL(11,6)  	ALL_LOSSY                	<Correct error>
-DECIMAL(10,5)  	DECIMAL(10,4)  	ALL_LOSSY                	<Correct value>
-DECIMAL(10,5)  	DECIMAL(9,5)   	ALL_LOSSY                	<Correct value>
-DECIMAL(10,5)  	DECIMAL(9,4)   	ALL_LOSSY                	<Correct value>
-FLOAT          	DECIMAL(10,5)  	ALL_LOSSY                	<Correct value>
-DOUBLE         	DECIMAL(10,5)  	ALL_LOSSY                	<Correct value>
-DECIMAL(10,5)  	FLOAT          	ALL_LOSSY                	<Correct value>
-DECIMAL(10,5)  	DOUBLE         	ALL_LOSSY                	<Correct value>
-FLOAT          	FLOAT          	ALL_LOSSY                	<Correct value>
-DOUBLE         	DOUBLE         	ALL_LOSSY                	<Correct value>
-FLOAT          	DOUBLE         	ALL_LOSSY                	<Correct error>
-DOUBLE         	FLOAT          	ALL_LOSSY                	<Correct value>
-BIT(5)         	BIT(5)         	ALL_LOSSY                	<Correct value>
-BIT(5)         	BIT(6)         	ALL_LOSSY                	<Correct error>
-BIT(6)         	BIT(5)         	ALL_LOSSY                	<Correct value>
-BIT(5)         	BIT(12)        	ALL_LOSSY                	<Correct error>
-BIT(12)        	BIT(5)         	ALL_LOSSY                	<Correct value>
+**** Checking result of conversions ****
 DROP TABLE type_conversions;
 DROP TABLE t1;
 set global slave_type_conversions = @saved_slave_type_conversions;

=== modified file 'mysql-test/suite/rpl_ndb/r/rpl_ndb_typeconv_nonlossy.result'
--- a/mysql-test/suite/rpl_ndb/r/rpl_ndb_typeconv_nonlossy.result	2011-04-07 19:57:33 +0000
+++ b/mysql-test/suite/rpl_ndb/r/rpl_ndb_typeconv_nonlossy.result	2011-04-21 12:36:25 +0000
@@ -38,111 +38,7 @@ ALL_LOSSY,ALL_NON_LOSSY
 SET GLOBAL SLAVE_TYPE_CONVERSIONS='ALL_NON_LOSSY';
 **** Running tests with @@SLAVE_TYPE_CONVERSIONS = 'ALL_NON_LOSSY' ****
 include/rpl_reset.inc
-**** Result of conversions ****
-Source_Type	Target_Type	All_Type_Conversion_Flags	Value_On_Slave
-GEOMETRY       	GEOMETRY       	ALL_NON_LOSSY            	<Correct value>
-BIT(1)         	BIT(1)         	ALL_NON_LOSSY            	<Correct value>
-DATE           	DATE           	ALL_NON_LOSSY            	<Correct value>
-ENUM('master','	ENUM('master','	ALL_NON_LOSSY            	<Correct value>
-CHAR(10)       	ENUM('master','	ALL_NON_LOSSY            	<Correct error>
-CHAR(10)       	SET('master','s	ALL_NON_LOSSY            	<Correct error>
-ENUM('master','	CHAR(10)       	ALL_NON_LOSSY            	<Correct error>
-SET('master','s	CHAR(10)       	ALL_NON_LOSSY            	<Correct error>
-SET('master','s	SET('master','s	ALL_NON_LOSSY            	<Correct value>
-SET('master','s	SET('master','s	ALL_NON_LOSSY            	<Correct value>
-SET('0','1','2'	SET('0','1','2'	ALL_NON_LOSSY            	<Correct value>
-SET('0','1','2'	SET('0','1','2'	ALL_NON_LOSSY            	<Correct value>
-SET('0','1','2'	SET('0','1','2'	ALL_NON_LOSSY            	<Correct error>
-SET('0','1','2'	SET('0','1','2'	ALL_NON_LOSSY            	<Correct error>
-TINYINT        	TINYINT        	ALL_NON_LOSSY            	<Correct value>
-TINYINT        	SMALLINT       	ALL_NON_LOSSY            	<Correct value>
-TINYINT        	MEDIUMINT      	ALL_NON_LOSSY            	<Correct value>
-TINYINT        	INT            	ALL_NON_LOSSY            	<Correct value>
-TINYINT        	BIGINT         	ALL_NON_LOSSY            	<Correct value>
-SMALLINT       	TINYINT        	ALL_NON_LOSSY            	<Correct error>
-SMALLINT       	TINYINT        	ALL_NON_LOSSY            	<Correct error>
-SMALLINT       	TINYINT UNSIGNE	ALL_NON_LOSSY            	<Correct error>
-SMALLINT       	SMALLINT       	ALL_NON_LOSSY            	<Correct value>
-SMALLINT       	MEDIUMINT      	ALL_NON_LOSSY            	<Correct value>
-SMALLINT       	INT            	ALL_NON_LOSSY            	<Correct value>
-SMALLINT       	BIGINT         	ALL_NON_LOSSY            	<Correct value>
-MEDIUMINT      	TINYINT        	ALL_NON_LOSSY            	<Correct error>
-MEDIUMINT      	TINYINT        	ALL_NON_LOSSY            	<Correct error>
-MEDIUMINT      	TINYINT UNSIGNE	ALL_NON_LOSSY            	<Correct error>
-MEDIUMINT      	SMALLINT       	ALL_NON_LOSSY            	<Correct error>
-MEDIUMINT      	MEDIUMINT      	ALL_NON_LOSSY            	<Correct value>
-MEDIUMINT      	INT            	ALL_NON_LOSSY            	<Correct value>
-MEDIUMINT      	BIGINT         	ALL_NON_LOSSY            	<Correct value>
-INT            	TINYINT        	ALL_NON_LOSSY            	<Correct error>
-INT            	TINYINT        	ALL_NON_LOSSY            	<Correct error>
-INT            	TINYINT UNSIGNE	ALL_NON_LOSSY            	<Correct error>
-INT            	SMALLINT       	ALL_NON_LOSSY            	<Correct error>
-INT            	MEDIUMINT      	ALL_NON_LOSSY            	<Correct error>
-INT            	INT            	ALL_NON_LOSSY            	<Correct value>
-INT            	BIGINT         	ALL_NON_LOSSY            	<Correct value>
-BIGINT         	TINYINT        	ALL_NON_LOSSY            	<Correct error>
-BIGINT         	SMALLINT       	ALL_NON_LOSSY            	<Correct error>
-BIGINT         	MEDIUMINT      	ALL_NON_LOSSY            	<Correct error>
-BIGINT         	INT            	ALL_NON_LOSSY            	<Correct error>
-BIGINT         	BIGINT         	ALL_NON_LOSSY            	<Correct value>
-CHAR(20)       	CHAR(20)       	ALL_NON_LOSSY            	<Correct value>
-CHAR(20)       	CHAR(30)       	ALL_NON_LOSSY            	<Correct value>
-CHAR(20)       	CHAR(10)       	ALL_NON_LOSSY            	<Correct error>
-CHAR(20)       	VARCHAR(20)    	ALL_NON_LOSSY            	<Correct value>
-CHAR(20)       	VARCHAR(30)    	ALL_NON_LOSSY            	<Correct value>
-CHAR(20)       	VARCHAR(10)    	ALL_NON_LOSSY            	<Correct error>
-CHAR(20)       	TINYTEXT       	ALL_NON_LOSSY            	<Correct value>
-CHAR(20)       	TEXT           	ALL_NON_LOSSY            	<Correct value>
-CHAR(20)       	MEDIUMTEXT     	ALL_NON_LOSSY            	<Correct value>
-CHAR(20)       	LONGTEXT       	ALL_NON_LOSSY            	<Correct value>
-VARCHAR(20)    	VARCHAR(20)    	ALL_NON_LOSSY            	<Correct value>
-VARCHAR(20)    	VARCHAR(30)    	ALL_NON_LOSSY            	<Correct value>
-VARCHAR(20)    	VARCHAR(10)    	ALL_NON_LOSSY            	<Correct error>
-VARCHAR(20)    	CHAR(30)       	ALL_NON_LOSSY            	<Correct value>
-VARCHAR(20)    	CHAR(10)       	ALL_NON_LOSSY            	<Correct error>
-VARCHAR(20)    	TINYTEXT       	ALL_NON_LOSSY            	<Correct value>
-VARCHAR(20)    	TEXT           	ALL_NON_LOSSY            	<Correct value>
-VARCHAR(20)    	MEDIUMTEXT     	ALL_NON_LOSSY            	<Correct value>
-VARCHAR(20)    	LONGTEXT       	ALL_NON_LOSSY            	<Correct value>
-VARCHAR(500)   	VARCHAR(500)   	ALL_NON_LOSSY            	<Correct value>
-VARCHAR(500)   	VARCHAR(510)   	ALL_NON_LOSSY            	<Correct value>
-VARCHAR(500)   	VARCHAR(255)   	ALL_NON_LOSSY            	<Correct error>
-VARCHAR(500)   	TINYTEXT       	ALL_NON_LOSSY            	<Correct error>
-VARCHAR(500)   	TEXT           	ALL_NON_LOSSY            	<Correct value>
-VARCHAR(500)   	MEDIUMTEXT     	ALL_NON_LOSSY            	<Correct value>
-VARCHAR(500)   	LONGTEXT       	ALL_NON_LOSSY            	<Correct value>
-TINYTEXT       	VARCHAR(500)   	ALL_NON_LOSSY            	<Correct value>
-TEXT           	VARCHAR(500)   	ALL_NON_LOSSY            	<Correct error>
-MEDIUMTEXT     	VARCHAR(500)   	ALL_NON_LOSSY            	<Correct error>
-LONGTEXT       	VARCHAR(500)   	ALL_NON_LOSSY            	<Correct error>
-TINYTEXT       	CHAR(255)      	ALL_NON_LOSSY            	<Correct value>
-TINYTEXT       	CHAR(250)      	ALL_NON_LOSSY            	<Correct error>
-TEXT           	CHAR(255)      	ALL_NON_LOSSY            	<Correct error>
-MEDIUMTEXT     	CHAR(255)      	ALL_NON_LOSSY            	<Correct error>
-LONGTEXT       	CHAR(255)      	ALL_NON_LOSSY            	<Correct error>
-TINYTEXT       	TINYTEXT       	ALL_NON_LOSSY            	<Correct value>
-TINYTEXT       	TEXT           	ALL_NON_LOSSY            	<Correct value>
-TEXT           	TINYTEXT       	ALL_NON_LOSSY            	<Correct error>
-DECIMAL(10,5)  	DECIMAL(10,5)  	ALL_NON_LOSSY            	<Correct value>
-DECIMAL(10,5)  	DECIMAL(10,6)  	ALL_NON_LOSSY            	<Correct value>
-DECIMAL(10,5)  	DECIMAL(11,5)  	ALL_NON_LOSSY            	<Correct value>
-DECIMAL(10,5)  	DECIMAL(11,6)  	ALL_NON_LOSSY            	<Correct value>
-DECIMAL(10,5)  	DECIMAL(10,4)  	ALL_NON_LOSSY            	<Correct error>
-DECIMAL(10,5)  	DECIMAL(9,5)   	ALL_NON_LOSSY            	<Correct error>
-DECIMAL(10,5)  	DECIMAL(9,4)   	ALL_NON_LOSSY            	<Correct error>
-FLOAT          	DECIMAL(10,5)  	ALL_NON_LOSSY            	<Correct error>
-DOUBLE         	DECIMAL(10,5)  	ALL_NON_LOSSY            	<Correct error>
-DECIMAL(10,5)  	FLOAT          	ALL_NON_LOSSY            	<Correct error>
-DECIMAL(10,5)  	DOUBLE         	ALL_NON_LOSSY            	<Correct error>
-FLOAT          	FLOAT          	ALL_NON_LOSSY            	<Correct value>
-DOUBLE         	DOUBLE         	ALL_NON_LOSSY            	<Correct value>
-FLOAT          	DOUBLE         	ALL_NON_LOSSY            	<Correct value>
-DOUBLE         	FLOAT          	ALL_NON_LOSSY            	<Correct error>
-BIT(5)         	BIT(5)         	ALL_NON_LOSSY            	<Correct value>
-BIT(5)         	BIT(6)         	ALL_NON_LOSSY            	<Correct value>
-BIT(6)         	BIT(5)         	ALL_NON_LOSSY            	<Correct error>
-BIT(5)         	BIT(12)        	ALL_NON_LOSSY            	<Correct value>
-BIT(12)        	BIT(5)         	ALL_NON_LOSSY            	<Correct error>
+**** Checking result of conversions ****
 DROP TABLE type_conversions;
 DROP TABLE t1;
 set global slave_type_conversions = @saved_slave_type_conversions;

=== modified file 'mysql-test/suite/rpl_ndb/r/rpl_ndb_typeconv_strict.result'
--- a/mysql-test/suite/rpl_ndb/r/rpl_ndb_typeconv_strict.result	2011-04-07 19:57:33 +0000
+++ b/mysql-test/suite/rpl_ndb/r/rpl_ndb_typeconv_strict.result	2011-04-21 12:36:25 +0000
@@ -38,111 +38,7 @@ ALL_LOSSY,ALL_NON_LOSSY
 SET GLOBAL SLAVE_TYPE_CONVERSIONS='';
 **** Running tests with @@SLAVE_TYPE_CONVERSIONS = '' ****
 include/rpl_reset.inc
-**** Result of conversions ****
-Source_Type	Target_Type	All_Type_Conversion_Flags	Value_On_Slave
-GEOMETRY       	GEOMETRY       	                         	<Correct value>
-BIT(1)         	BIT(1)         	                         	<Correct value>
-DATE           	DATE           	                         	<Correct value>
-ENUM('master','	ENUM('master','	                         	<Correct value>
-CHAR(10)       	ENUM('master','	                         	<Correct error>
-CHAR(10)       	SET('master','s	                         	<Correct error>
-ENUM('master','	CHAR(10)       	                         	<Correct error>
-SET('master','s	CHAR(10)       	                         	<Correct error>
-SET('master','s	SET('master','s	                         	<Correct value>
-SET('master','s	SET('master','s	                         	<Correct value>
-SET('0','1','2'	SET('0','1','2'	                         	<Correct value>
-SET('0','1','2'	SET('0','1','2'	                         	<Correct error>
-SET('0','1','2'	SET('0','1','2'	                         	<Correct error>
-SET('0','1','2'	SET('0','1','2'	                         	<Correct error>
-TINYINT        	TINYINT        	                         	<Correct value>
-TINYINT        	SMALLINT       	                         	<Correct error>
-TINYINT        	MEDIUMINT      	                         	<Correct error>
-TINYINT        	INT            	                         	<Correct error>
-TINYINT        	BIGINT         	                         	<Correct error>
-SMALLINT       	TINYINT        	                         	<Correct error>
-SMALLINT       	TINYINT        	                         	<Correct error>
-SMALLINT       	TINYINT UNSIGNE	                         	<Correct error>
-SMALLINT       	SMALLINT       	                         	<Correct value>
-SMALLINT       	MEDIUMINT      	                         	<Correct error>
-SMALLINT       	INT            	                         	<Correct error>
-SMALLINT       	BIGINT         	                         	<Correct error>
-MEDIUMINT      	TINYINT        	                         	<Correct error>
-MEDIUMINT      	TINYINT        	                         	<Correct error>
-MEDIUMINT      	TINYINT UNSIGNE	                         	<Correct error>
-MEDIUMINT      	SMALLINT       	                         	<Correct error>
-MEDIUMINT      	MEDIUMINT      	                         	<Correct value>
-MEDIUMINT      	INT            	                         	<Correct error>
-MEDIUMINT      	BIGINT         	                         	<Correct error>
-INT            	TINYINT        	                         	<Correct error>
-INT            	TINYINT        	                         	<Correct error>
-INT            	TINYINT UNSIGNE	                         	<Correct error>
-INT            	SMALLINT       	                         	<Correct error>
-INT            	MEDIUMINT      	                         	<Correct error>
-INT            	INT            	                         	<Correct value>
-INT            	BIGINT         	                         	<Correct error>
-BIGINT         	TINYINT        	                         	<Correct error>
-BIGINT         	SMALLINT       	                         	<Correct error>
-BIGINT         	MEDIUMINT      	                         	<Correct error>
-BIGINT         	INT            	                         	<Correct error>
-BIGINT         	BIGINT         	                         	<Correct value>
-CHAR(20)       	CHAR(20)       	                         	<Correct value>
-CHAR(20)       	CHAR(30)       	                         	<Correct error>
-CHAR(20)       	CHAR(10)       	                         	<Correct error>
-CHAR(20)       	VARCHAR(20)    	                         	<Correct error>
-CHAR(20)       	VARCHAR(30)    	                         	<Correct error>
-CHAR(20)       	VARCHAR(10)    	                         	<Correct error>
-CHAR(20)       	TINYTEXT       	                         	<Correct error>
-CHAR(20)       	TEXT           	                         	<Correct error>
-CHAR(20)       	MEDIUMTEXT     	                         	<Correct error>
-CHAR(20)       	LONGTEXT       	                         	<Correct error>
-VARCHAR(20)    	VARCHAR(20)    	                         	<Correct value>
-VARCHAR(20)    	VARCHAR(30)    	                         	<Correct error>
-VARCHAR(20)    	VARCHAR(10)    	                         	<Correct error>
-VARCHAR(20)    	CHAR(30)       	                         	<Correct error>
-VARCHAR(20)    	CHAR(10)       	                         	<Correct error>
-VARCHAR(20)    	TINYTEXT       	                         	<Correct error>
-VARCHAR(20)    	TEXT           	                         	<Correct error>
-VARCHAR(20)    	MEDIUMTEXT     	                         	<Correct error>
-VARCHAR(20)    	LONGTEXT       	                         	<Correct error>
-VARCHAR(500)   	VARCHAR(500)   	                         	<Correct value>
-VARCHAR(500)   	VARCHAR(510)   	                         	<Correct error>
-VARCHAR(500)   	VARCHAR(255)   	                         	<Correct error>
-VARCHAR(500)   	TINYTEXT       	                         	<Correct error>
-VARCHAR(500)   	TEXT           	                         	<Correct error>
-VARCHAR(500)   	MEDIUMTEXT     	                         	<Correct error>
-VARCHAR(500)   	LONGTEXT       	                         	<Correct error>
-TINYTEXT       	VARCHAR(500)   	                         	<Correct error>
-TEXT           	VARCHAR(500)   	                         	<Correct error>
-MEDIUMTEXT     	VARCHAR(500)   	                         	<Correct error>
-LONGTEXT       	VARCHAR(500)   	                         	<Correct error>
-TINYTEXT       	CHAR(255)      	                         	<Correct error>
-TINYTEXT       	CHAR(250)      	                         	<Correct error>
-TEXT           	CHAR(255)      	                         	<Correct error>
-MEDIUMTEXT     	CHAR(255)      	                         	<Correct error>
-LONGTEXT       	CHAR(255)      	                         	<Correct error>
-TINYTEXT       	TINYTEXT       	                         	<Correct value>
-TINYTEXT       	TEXT           	                         	<Correct error>
-TEXT           	TINYTEXT       	                         	<Correct error>
-DECIMAL(10,5)  	DECIMAL(10,5)  	                         	<Correct value>
-DECIMAL(10,5)  	DECIMAL(10,6)  	                         	<Correct error>
-DECIMAL(10,5)  	DECIMAL(11,5)  	                         	<Correct error>
-DECIMAL(10,5)  	DECIMAL(11,6)  	                         	<Correct error>
-DECIMAL(10,5)  	DECIMAL(10,4)  	                         	<Correct error>
-DECIMAL(10,5)  	DECIMAL(9,5)   	                         	<Correct error>
-DECIMAL(10,5)  	DECIMAL(9,4)   	                         	<Correct error>
-FLOAT          	DECIMAL(10,5)  	                         	<Correct error>
-DOUBLE         	DECIMAL(10,5)  	                         	<Correct error>
-DECIMAL(10,5)  	FLOAT          	                         	<Correct error>
-DECIMAL(10,5)  	DOUBLE         	                         	<Correct error>
-FLOAT          	FLOAT          	                         	<Correct value>
-DOUBLE         	DOUBLE         	                         	<Correct value>
-FLOAT          	DOUBLE         	                         	<Correct error>
-DOUBLE         	FLOAT          	                         	<Correct error>
-BIT(5)         	BIT(5)         	                         	<Correct value>
-BIT(5)         	BIT(6)         	                         	<Correct error>
-BIT(6)         	BIT(5)         	                         	<Correct error>
-BIT(5)         	BIT(12)        	                         	<Correct error>
-BIT(12)        	BIT(5)         	                         	<Correct error>
+**** Checking result of conversions ****
 DROP TABLE type_conversions;
 DROP TABLE t1;
 set global slave_type_conversions = @saved_slave_type_conversions;

=== added file 'mysql-test/suite/rpl_ndb/r/rpl_ndb_ui.result'
--- a/mysql-test/suite/rpl_ndb/r/rpl_ndb_ui.result	1970-01-01 00:00:00 +0000
+++ b/mysql-test/suite/rpl_ndb/r/rpl_ndb_ui.result	2011-04-28 07:47:53 +0000
@@ -0,0 +1,49 @@
+include/master-slave.inc
+[connection master]
+CREATE TABLE t1 (pk int primary key, uk int not null, unique(uk)) engine=ndb;
+insert into t1 values (1,1);
+insert into t1 values (2,2);
+insert into t1 values (3,3);
+insert into t1 values (4,4);
+insert into t1 values (5,5);
+select * from t1 where uk in (1,2,3,4,5);
+pk	uk
+1	1
+2	2
+3	3
+4	4
+5	5
+update t1 set uk=uk-1 order by pk;
+select * from t1 where uk in (0,1,2,3,4);
+pk	uk
+1	0
+2	1
+3	2
+4	3
+5	4
+Master table contents
+select * from t1 order by pk;
+pk	uk
+1	0
+2	1
+3	2
+4	3
+5	4
+flush logs;
+Slave table contents
+select * from t1 order by pk;
+pk	uk
+1	0
+2	1
+3	2
+4	3
+5	4
+select * from t1 where uk in (0,1,2,3,4);
+pk	uk
+1	0
+2	1
+3	2
+4	3
+5	4
+drop table t1;
+include/rpl_end.inc

=== added file 'mysql-test/suite/rpl_ndb/r/rpl_ndb_ui2.result'
--- a/mysql-test/suite/rpl_ndb/r/rpl_ndb_ui2.result	1970-01-01 00:00:00 +0000
+++ b/mysql-test/suite/rpl_ndb/r/rpl_ndb_ui2.result	2011-04-28 07:47:53 +0000
@@ -0,0 +1,18 @@
+include/master-slave.inc
+[connection master]
+CREATE TABLE t1 (pk int primary key, uk int not null, unique(uk)) engine=ndb;
+STOP SLAVE;
+insert into t1 values (1,1);
+insert into t1 values (2,2);
+insert into t1 values (1,2);
+insert into t1 values (2,1);
+delete from t1;
+insert into t1 values (1,1);
+insert into t1 values (2,2);
+start slave;
+select * from t1;
+pk	uk
+1	1
+2	2
+drop table t1;
+include/rpl_end.inc

=== added file 'mysql-test/suite/rpl_ndb/r/rpl_ndb_ui3.result'
--- a/mysql-test/suite/rpl_ndb/r/rpl_ndb_ui3.result	1970-01-01 00:00:00 +0000
+++ b/mysql-test/suite/rpl_ndb/r/rpl_ndb_ui3.result	2011-04-28 07:47:53 +0000
@@ -0,0 +1,51 @@
+include/master-slave.inc
+[connection master]
+CREATE TABLE t1 (pk int primary key, uk1 int not null, uk2 int not null,
+unique(uk1), unique(uk2)) engine=ndb;
+insert into t1 values (1,1,1);
+insert into t1 values (2,2,2);
+insert into t1 values (3,3,3);
+insert into t1 values (4,4,4);
+insert into t1 values (5,5,5);
+select * from t1 where uk1 in (1,2,3,4,5);
+pk	uk1	uk2
+1	1	1
+2	2	2
+3	3	3
+4	4	4
+5	5	5
+update t1 set uk1=uk1-1 order by pk;
+update t1 set uk2=uk2+1 order by pk desc;
+select * from t1 where uk1 in (0,1,2,3,4);
+pk	uk1	uk2
+1	0	2
+2	1	3
+3	2	4
+4	3	5
+5	4	6
+Master table contents
+select * from t1 order by pk;
+pk	uk1	uk2
+1	0	2
+2	1	3
+3	2	4
+4	3	5
+5	4	6
+flush logs;
+Slave table contents
+select * from t1 order by pk;
+pk	uk1	uk2
+1	0	2
+2	1	3
+3	2	4
+4	3	5
+5	4	6
+select * from t1 where uk1 in (0,1,2,3,4);
+pk	uk1	uk2
+1	0	2
+2	1	3
+3	2	4
+4	3	5
+5	4	6
+drop table t1;
+include/rpl_end.inc

=== added file 'mysql-test/suite/rpl_ndb/t/check_conversions.inc'
--- a/mysql-test/suite/rpl_ndb/t/check_conversions.inc	1970-01-01 00:00:00 +0000
+++ b/mysql-test/suite/rpl_ndb/t/check_conversions.inc	2011-04-21 12:36:25 +0000
@@ -0,0 +1,26 @@
+--echo **** Checking result of conversions ****
+disable_query_log;
+# Create a temporary table containing all conversions
+# that didn't work as expected, the table should
+# normally not contain any rows
+CREATE TEMPORARY TABLE failed_type_conversions ENGINE = 'MyISAM' AS
+  SELECT RPAD(Source, 15, ' ') AS Source_Type,
+         RPAD(Target, 15, ' ') AS Target_Type,
+         RPAD(Flags, 25, ' ') AS All_Type_Conversion_Flags,
+         IF(Compare IS NULL AND Error IS NOT NULL, '<Correct error>',
+            IF(Compare, '<Correct value>',
+               CONCAT("'", On_Slave, "' != '", Expected, "'")))
+           AS Value_On_Slave
+  FROM type_conversions
+  WHERE Compare != 1 OR (Compare IS NULL AND Error IS NULL);
+enable_query_log;
+
+if (`SELECT COUNT(*) FROM failed_type_conversions`)
+{
+  echo Some type conversions failed, see below:;
+  SELECT * FROM failed_type_conversions;
+  die Type conversion failure;
+}
+
+
+

=== modified file 'mysql-test/suite/rpl_ndb/t/rpl_ndb_2innodb.test'
--- a/mysql-test/suite/rpl_ndb/t/rpl_ndb_2innodb.test	2011-04-07 19:57:33 +0000
+++ b/mysql-test/suite/rpl_ndb/t/rpl_ndb_2innodb.test	2011-04-20 11:50:29 +0000
@@ -42,7 +42,7 @@ set new=on;
 set storage_engine=ndbcluster;
 --enable_query_log
 
---source extra/rpl_tests/rpl_ndb_2multi_eng.test
+--source suite/rpl_ndb/t/rpl_ndb_2multi_eng.inc
 
 --connection slave
 set @@global.slave_exec_mode= 'STRICT';

=== renamed file 'mysql-test/extra/rpl_tests/rpl_ndb_2multi_basic.test' => 'mysql-test/suite/rpl_ndb/t/rpl_ndb_2multi_basic.inc'
=== renamed file 'mysql-test/extra/rpl_tests/rpl_ndb_2multi_eng.test' => 'mysql-test/suite/rpl_ndb/t/rpl_ndb_2multi_eng.inc'
=== modified file 'mysql-test/suite/rpl_ndb/t/rpl_ndb_2myisam.test'
--- a/mysql-test/suite/rpl_ndb/t/rpl_ndb_2myisam.test	2011-04-07 19:57:33 +0000
+++ b/mysql-test/suite/rpl_ndb/t/rpl_ndb_2myisam.test	2011-04-20 11:50:29 +0000
@@ -41,7 +41,7 @@ set new=on;
 set storage_engine=ndbcluster;
 --enable_query_log
 
---source extra/rpl_tests/rpl_ndb_2multi_eng.test
+--source suite/rpl_ndb/t/rpl_ndb_2multi_eng.inc
 
 --connection slave
 set @@global.slave_exec_mode= 'STRICT';

=== modified file 'mysql-test/suite/rpl_ndb/t/rpl_ndb_2ndb.test'
--- a/mysql-test/suite/rpl_ndb/t/rpl_ndb_2ndb.test	2011-04-08 11:06:53 +0000
+++ b/mysql-test/suite/rpl_ndb/t/rpl_ndb_2ndb.test	2011-04-20 12:10:50 +0000
@@ -16,5 +16,5 @@ SET storage_engine=ndb;
 --echo === NDB -> NDB ===
 --echo
 connection slave;
---source extra/rpl_tests/rpl_ndb_2multi_basic.test
+--source suite/rpl_ndb/t/rpl_ndb_2multi_basic.inc
 --source include/rpl_end.inc

=== modified file 'mysql-test/suite/rpl_ndb/t/rpl_ndb_2other.test'
--- a/mysql-test/suite/rpl_ndb/t/rpl_ndb_2other.test	2010-12-19 17:07:28 +0000
+++ b/mysql-test/suite/rpl_ndb/t/rpl_ndb_2other.test	2011-04-20 14:36:44 +0000
@@ -7,16 +7,17 @@
 --source include/have_ndb.inc
 --source include/have_innodb.inc
 --source include/have_binlog_format_mixed_or_row.inc
+
+let $rpl_skip_start_slave= 1; # Don't start slave automatically
 --source include/master-slave.inc
 
 # On master use NDB as storage engine.
-connection master;
 SET storage_engine=ndb;
 
 --echo
 --echo === NDB -> MYISAM ===
 --echo
-connection slave;
+--source include/rpl_connection_slave.inc
 
 # Remove any old ndb_apply_status from slaves datadir
 let $datadir= `SELECT @@datadir`;
@@ -34,18 +35,34 @@ CREATE TABLE mysql.ndb_apply_status
                    start_pos BIGINT UNSIGNED NOT NULL,
                    end_pos BIGINT UNSIGNED NOT NULL,
                    PRIMARY KEY USING HASH (server_id)) ENGINE=MYISAM;
-SET storage_engine=myisam;
---source extra/rpl_tests/rpl_ndb_2multi_basic.test
+
+# Reconfigure slave to use MyISAM as default engine
+SET @old_slave_storage_engine=@@global.storage_engine;
+SET @@global.storage_engine=myisam;
+
+--source include/start_slave.inc
+--source suite/rpl_ndb/t/rpl_ndb_2multi_basic.inc
+--source include/rpl_connection_slave.inc
+--source include/stop_slave.inc
 
 --echo
 --echo === NDB -> INNODB ===
 --echo
-connection slave;
+
+# Reconfigure slave to use Innodb as default engine
+--source include/rpl_connection_slave.inc
+
 alter table mysql.ndb_apply_status engine=innodb;
-SET storage_engine=innodb;
---source extra/rpl_tests/rpl_ndb_2multi_basic.test
+SET @@global.storage_engine=innodb;
+
+--source include/start_slave.inc
+--source suite/rpl_ndb/t/rpl_ndb_2multi_basic.inc
+--source include/rpl_connection_slave.inc
+--source include/stop_slave.inc
 
-connection slave;
+# Cleanup
+--source include/rpl_connection_slave.inc
 drop table mysql.ndb_apply_status;
 set @@global.slave_exec_mode= @old_slave_exec_mode;
---source include/rpl_end.inc
+SET @@global.storage_engine=@old_slave_storage_engine;
+

=== modified file 'mysql-test/suite/rpl_ndb/t/rpl_ndb_break_3_chain.cnf'
--- a/mysql-test/suite/rpl_ndb/t/rpl_ndb_break_3_chain.cnf	2010-11-08 12:19:51 +0000
+++ b/mysql-test/suite/rpl_ndb/t/rpl_ndb_break_3_chain.cnf	2011-04-26 13:48:44 +0000
@@ -34,13 +34,12 @@ ndb-log-orig
 log-bin=                       cluster1-bin
 # for performance reasons
 ndb-table-temporary=1
-ndb-log-apply-status
 ndb-extra-logging=99
 
 [mysqld.1.cluster1]
 
-[mysqld.1.cluster2]
 
+[mysqld.1.cluster2]
 # Connect mysqld in the second cluster as save to  first mysqld
 # Hardcode the host to 127.0.0.1 until running on more
 # than one host and it probably need to be masked anyway
@@ -51,22 +50,16 @@ master-password=              @mysqld.1.
 master-user=                  @mysqld.1.cluster1.#user
 master-connect-retry=         1
 
+skip-slave-start
+
 log-bin=                      cluster2-bin
 relay-log=                    cluster2-relay-bin
 
-init-rpl-role=                slave
 log-slave-updates
-master-retry-count=           10
 ndb-log-apply-status
 
-# Values reported by slave when it connect to master
-# and shows up in SHOW SLAVE STATUS;
-report-host=                  127.0.0.1
-report-port=                  @mysqld.1.cluster2.port
-report-user=                  root
-
 loose-skip-innodb
-skip-slave-start
+default-storage-engine=myisam
 
 # Directory where slaves find the dumps generated by "load data"
 # on the server. The path need to have constant length otherwise
@@ -76,22 +69,14 @@ slave-load-tmpdir=            ../../../t
 rpl-recovery-rank=            @mysqld.1.cluster2.server-id
 
 [mysqld.1.cluster3]
-master-host=                  127.0.0.1
-master-port=                  @mysqld.1.cluster2.port
-master-password=              @mysqld.1.cluster2.#password
-master-user=                  @mysqld.1.cluster2.#user
-master-connect-retry=         1
-
 log-bin=                      cluster3-bin
 relay-log=                    cluster3-relay-bin
 
-init-rpl-role=                slave
 log-slave-updates
-master-retry-count=           10
 ndb-log-apply-status
 
 loose-skip-innodb
-skip-slave-start
+default-storage-engine=myisam
 
 # Directory where slaves find the dumps generated by "load data"
 # on the server. The path need to have constant length otherwise
@@ -101,18 +86,6 @@ slave-load-tmpdir=            ../../../t
 rpl-recovery-rank=            @mysqld.1.cluster3.server-id
 
 [ENV]
-NDB_CONNECTSTRING=            @mysql_cluster.cluster1.ndb_connectstring
-MASTER_MYPORT=                @mysqld.1.cluster1.port
-MASTER_MYPORT1=               @mysqld.2.cluster1.port
-CLUSTER1_HOST=                127.0.0.1
-CLUSTER1_MYPORT=              @mysqld.1.cluster1.port
-CLUSTER1_USER=                @mysqld.1.cluster1.#user
-
-NDB_CONNECTSTRING_SLAVE=      @mysql_cluster.cluster2.ndb_connectstring
-SLAVE_MYPORT=                 @mysqld.1.cluster2.port
-SLAVE_MYSOCK=                 @mysqld.1.cluster2.socket
-CLUSTER2_MYPORT=              @mysqld.1.cluster2.port
-
-CLUSTER3_MYPORT=              @mysqld.1.cluster3.port
-
-NDB_BACKUP_DIR=               @cluster_config.ndbd.1.cluster1.BackupDataDir
+SERVER_MYPORT_1=              @mysqld.1.cluster1.port
+SERVER_MYPORT_2=              @mysqld.1.cluster2.port
+SERVER_MYPORT_3=              @mysqld.1.cluster3.port

=== modified file 'mysql-test/suite/rpl_ndb/t/rpl_ndb_break_3_chain.test'
--- a/mysql-test/suite/rpl_ndb/t/rpl_ndb_break_3_chain.test	2010-11-08 12:19:51 +0000
+++ b/mysql-test/suite/rpl_ndb/t/rpl_ndb_break_3_chain.test	2011-04-26 13:48:44 +0000
@@ -1,37 +1,42 @@
 --source include/have_ndb.inc
---source suite/rpl_ndb/ndb_master-slave.inc
 
-connect (cluster1, 127.0.0.1,root,,test,$CLUSTER1_MYPORT);
-connect (cluster2, 127.0.0.1,root,,test,$CLUSTER2_MYPORT);
-connect (cluster3, 127.0.0.1,root,,test,$CLUSTER3_MYPORT);
+# setup replication 1->2->3
+--let $rpl_topology= 1->2->3
+--source include/rpl_init.inc
+
+# create connections to first mysqld in each cluster
+--let $rpl_connection_name= cluster1
+--let $rpl_server_number= 1
+--source include/rpl_connect.inc
+
+--let $rpl_connection_name= cluster2
+--let $rpl_server_number= 2
+--source include/rpl_connect.inc
+
+--let $rpl_connection_name= cluster3
+--let $rpl_server_number= 3
+--source include/rpl_connect.inc
 
-
-# set up replication 1->2->3
---connection cluster1
+--let $rpl_connection_name= cluster1
+--source include/rpl_connection.inc
 show variables like 'server_id';
-reset master;
 select @cluster1_server_id:=(variable_value+0) 
        from information_schema.global_variables 
        where variable_name like 'server_id';
 
 let $CLUSTER1_SERVER_ID= query_get_value('select @cluster1_server_id as v',v,1);
 
---connection cluster2
+--let $rpl_connection_name= cluster2
+--source include/rpl_connection.inc
 show variables like 'server_id';
-stop slave;
-reset master;
-reset slave;
-start slave;
 
---connection cluster3
+--let $rpl_connection_name= cluster3
+--source include/rpl_connection.inc
 show variables like 'server_id';
-stop slave;
-reset master;
-reset slave;
-start slave;
 
 --echo First show replication 1->2->3
---connection cluster1
+--let $rpl_connection_name= cluster1
+--source include/rpl_connection.inc
 use test;
 create table t1(a int primary key, b varchar(50)) engine=ndb;
 
@@ -52,11 +57,14 @@ select * from mysql.ndb_apply_status ord
 select * from test.t1;
 
 --echo Break Cluster3's link with Cluster2
---connection cluster3
-stop slave;
+--let $rpl_connection_name= cluster3
+--source include/rpl_connection.inc
+
+--source include/stop_slave.inc
 
 --echo Make further changes on Cluster1
---connection cluster1
+--let $rpl_connection_name= cluster1
+--source include/rpl_connection.inc
 insert into test.t1 values (2, "The cotton is high");
 insert into test.t1 values (3, "Daddys rich");
 
@@ -65,7 +73,8 @@ insert into test.t1 values (3, "Daddys r
 select * from test.t1 order by a;
 
 --echo Check data on Cluster3
---connection cluster3
+--let $rpl_connection_name= cluster3
+--source include/rpl_connection.inc
 select * from test.t1 order by a;
 
 --echo Now change Cluster3 to skip-over Cluster2 and get binlog direct from Cluster1
@@ -79,35 +88,35 @@ eval select @binlog_file_name:=log_name
             where server_id = $CLUSTER1_SERVER_ID;
 eval select @binlog_file_pos:=end_pos from mysql.ndb_apply_status
             where server_id = $CLUSTER1_SERVER_ID;
+--enable_query_log
+--enable_result_log
 
 let $CLUSTER1_LOG_FILE= query_get_value('select @binlog_file_name as v', v, 1);
 let $CLUSTER1_LOG_POS= query_get_value('select @binlog_file_pos as v', v, 1);
 
-eval change master to master_host='$CLUSTER1_HOST', 
-                      master_port=$CLUSTER1_MYPORT, 
-                      master_user='$CLUSTER1_USER',
-                      master_log_file='$CLUSTER1_LOG_FILE',
-                      master_log_pos=$CLUSTER1_LOG_POS;
---enable_query_log
---enable_result_log
+--let $rpl_topology= 1->2, 1->3
+--let $rpl_master_log_file= 3:$CLUSTER1_LOG_FILE
+--let $rpl_master_log_pos= 3:$CLUSTER1_LOG_POS
+--source include/rpl_change_topology.inc
 
-start slave;
+--source include/start_slave.inc
 
---connection cluster1
+--let $rpl_connection_name= cluster1
+--source include/rpl_connection.inc
 --sync_slave_with_master cluster3
 
 --echo Now show that cluster 3 is successfully replicating from Cluster1
---connection cluster3
+--let $rpl_connection_name= cluster3
+--source include/rpl_connection.inc
 select * from test.t1 order by a;
 
-
 --echo Clean up
---connection cluster1
+--let $rpl_connection_name= cluster1
+--source include/rpl_connection.inc
 drop table test.t1;
 
---sync_slave_with_master cluster2
---connection cluster1
---sync_slave_with_master cluster3
+--source include/rpl_end.inc
+
 
 
 

=== modified file 'mysql-test/suite/rpl_ndb/t/rpl_ndb_innodb2ndb.test'
--- a/mysql-test/suite/rpl_ndb/t/rpl_ndb_innodb2ndb.test	2011-04-08 11:06:53 +0000
+++ b/mysql-test/suite/rpl_ndb/t/rpl_ndb_innodb2ndb.test	2011-04-20 11:50:29 +0000
@@ -12,5 +12,5 @@
 -- source include/have_binlog_format_mixed_or_row.inc
 -- source suite/rpl_ndb/ndb_master-slave.inc
 SET storage_engine=innodb;
---source extra/rpl_tests/rpl_ndb_2multi_eng.test
+--source suite/rpl_ndb/t/rpl_ndb_2multi_eng.inc
 --source include/rpl_end.inc

=== modified file 'mysql-test/suite/rpl_ndb/t/rpl_ndb_myisam2ndb.test'
--- a/mysql-test/suite/rpl_ndb/t/rpl_ndb_myisam2ndb.test	2011-04-08 11:06:53 +0000
+++ b/mysql-test/suite/rpl_ndb/t/rpl_ndb_myisam2ndb.test	2011-04-20 11:50:29 +0000
@@ -11,5 +11,5 @@
 -- source include/have_binlog_format_mixed_or_row.inc
 -- source suite/rpl_ndb/ndb_master-slave.inc
 SET storage_engine=myisam;
---source extra/rpl_tests/rpl_ndb_2multi_eng.test
+--source suite/rpl_ndb/t/rpl_ndb_2multi_eng.inc
 --source include/rpl_end.inc

=== modified file 'mysql-test/suite/rpl_ndb/t/rpl_ndb_typeconv_all.test'
--- a/mysql-test/suite/rpl_ndb/t/rpl_ndb_typeconv_all.test	2011-04-08 11:06:53 +0000
+++ b/mysql-test/suite/rpl_ndb/t/rpl_ndb_typeconv_all.test	2011-04-21 12:36:25 +0000
@@ -1,5 +1,6 @@
--- source include/have_ndb.inc
--- source suite/rpl_ndb/ndb_master-slave.inc
+--source include/have_ndb.inc
+--source include/have_binlog_format_row.inc
+--source suite/rpl_ndb/ndb_master-slave.inc
 let $engine_type=NDBCLUSTER;
 
 connection slave;
@@ -34,17 +35,8 @@ SET GLOBAL SLAVE_TYPE_CONVERSIONS='ALL_L
 source extra/rpl_tests/type_conversions.test;
 
 connection slave;
---echo **** Result of conversions ****
-disable_query_log;
-SELECT RPAD(Source, 15, ' ') AS Source_Type,
-       RPAD(Target, 15, ' ') AS Target_Type,
-       RPAD(Flags, 25, ' ') AS All_Type_Conversion_Flags,
-       IF(Compare IS NULL AND Error IS NOT NULL, '<Correct error>',
-          IF(Compare, '<Correct value>',
-             CONCAT("'", On_Slave, "' != '", Expected, "'")))
-         AS Value_On_Slave
-  FROM type_conversions;
-enable_query_log;
+--source suite/rpl_ndb/t/check_conversions.inc
+
 DROP TABLE type_conversions;
 
 connection master;

=== modified file 'mysql-test/suite/rpl_ndb/t/rpl_ndb_typeconv_lossy.test'
--- a/mysql-test/suite/rpl_ndb/t/rpl_ndb_typeconv_lossy.test	2011-04-08 11:06:53 +0000
+++ b/mysql-test/suite/rpl_ndb/t/rpl_ndb_typeconv_lossy.test	2011-04-21 12:36:25 +0000
@@ -1,5 +1,6 @@
--- source include/have_ndb.inc
--- source suite/rpl_ndb/ndb_master-slave.inc
+--source include/have_ndb.inc
+--source include/have_binlog_format_row.inc
+--source suite/rpl_ndb/ndb_master-slave.inc
 let $engine_type=NDBCLUSTER;
 
 connection slave;
@@ -34,17 +35,8 @@ SET GLOBAL SLAVE_TYPE_CONVERSIONS='ALL_L
 source extra/rpl_tests/type_conversions.test;
 
 connection slave;
---echo **** Result of conversions ****
-disable_query_log;
-SELECT RPAD(Source, 15, ' ') AS Source_Type,
-       RPAD(Target, 15, ' ') AS Target_Type,
-       RPAD(Flags, 25, ' ') AS All_Type_Conversion_Flags,
-       IF(Compare IS NULL AND Error IS NOT NULL, '<Correct error>',
-          IF(Compare, '<Correct value>',
-             CONCAT("'", On_Slave, "' != '", Expected, "'")))
-         AS Value_On_Slave
-  FROM type_conversions;
-enable_query_log;
+--source suite/rpl_ndb/t/check_conversions.inc
+
 DROP TABLE type_conversions;
 
 connection master;

=== modified file 'mysql-test/suite/rpl_ndb/t/rpl_ndb_typeconv_nonlossy.test'
--- a/mysql-test/suite/rpl_ndb/t/rpl_ndb_typeconv_nonlossy.test	2011-04-08 11:06:53 +0000
+++ b/mysql-test/suite/rpl_ndb/t/rpl_ndb_typeconv_nonlossy.test	2011-04-21 12:36:25 +0000
@@ -1,5 +1,6 @@
--- source include/have_ndb.inc
--- source suite/rpl_ndb/ndb_master-slave.inc
+--source include/have_ndb.inc
+--source include/have_binlog_format_row.inc
+--source suite/rpl_ndb/ndb_master-slave.inc
 let $engine_type=NDBCLUSTER;
 
 connection slave;
@@ -34,17 +35,8 @@ SET GLOBAL SLAVE_TYPE_CONVERSIONS='ALL_N
 source extra/rpl_tests/type_conversions.test;
 
 connection slave;
---echo **** Result of conversions ****
-disable_query_log;
-SELECT RPAD(Source, 15, ' ') AS Source_Type,
-       RPAD(Target, 15, ' ') AS Target_Type,
-       RPAD(Flags, 25, ' ') AS All_Type_Conversion_Flags,
-       IF(Compare IS NULL AND Error IS NOT NULL, '<Correct error>',
-          IF(Compare, '<Correct value>',
-             CONCAT("'", On_Slave, "' != '", Expected, "'")))
-         AS Value_On_Slave
-  FROM type_conversions;
-enable_query_log;
+--source suite/rpl_ndb/t/check_conversions.inc
+
 DROP TABLE type_conversions;
 
 connection master;

=== modified file 'mysql-test/suite/rpl_ndb/t/rpl_ndb_typeconv_strict.test'
--- a/mysql-test/suite/rpl_ndb/t/rpl_ndb_typeconv_strict.test	2011-04-08 11:06:53 +0000
+++ b/mysql-test/suite/rpl_ndb/t/rpl_ndb_typeconv_strict.test	2011-04-21 12:36:25 +0000
@@ -1,5 +1,6 @@
--- source include/have_ndb.inc
--- source suite/rpl_ndb/ndb_master-slave.inc
+--source include/have_ndb.inc
+--source include/have_binlog_format_row.inc
+--source suite/rpl_ndb/ndb_master-slave.inc
 let $engine_type=NDBCLUSTER;
 
 connection slave;
@@ -34,17 +35,8 @@ SET GLOBAL SLAVE_TYPE_CONVERSIONS='';
 source extra/rpl_tests/type_conversions.test;
 
 connection slave;
---echo **** Result of conversions ****
-disable_query_log;
-SELECT RPAD(Source, 15, ' ') AS Source_Type,
-       RPAD(Target, 15, ' ') AS Target_Type,
-       RPAD(Flags, 25, ' ') AS All_Type_Conversion_Flags,
-       IF(Compare IS NULL AND Error IS NOT NULL, '<Correct error>',
-          IF(Compare, '<Correct value>',
-             CONCAT("'", On_Slave, "' != '", Expected, "'")))
-         AS Value_On_Slave
-  FROM type_conversions;
-enable_query_log;
+--source suite/rpl_ndb/t/check_conversions.inc
+
 DROP TABLE type_conversions;
 
 connection master;

=== added file 'mysql-test/suite/rpl_ndb/t/rpl_ndb_ui.test'
--- a/mysql-test/suite/rpl_ndb/t/rpl_ndb_ui.test	1970-01-01 00:00:00 +0000
+++ b/mysql-test/suite/rpl_ndb/t/rpl_ndb_ui.test	2011-04-28 07:47:53 +0000
@@ -0,0 +1,52 @@
+--source include/have_ndb.inc
+--source include/have_binlog_format_mixed_or_row.inc
+--source suite/rpl_ndb/ndb_master-slave.inc
+
+#
+# Slave behaviour when replicating unique index operations
+#
+#
+
+--connection master
+
+CREATE TABLE t1 (pk int primary key, uk int not null, unique(uk)) engine=ndb;
+
+# Now perform some operations which do not result in uniqueness
+# violations when applied in-order, but which can result in them
+# when applied out-of-order
+# 5 distinct values chosen to increase the chance of different
+# fragments (and therefore potentially different SUMA->Binlog
+# orders) being seen.
+#
+insert into t1 values (1,1);
+insert into t1 values (2,2);
+insert into t1 values (3,3);
+insert into t1 values (4,4);
+insert into t1 values (5,5);
+
+--sorted_result
+select * from t1 where uk in (1,2,3,4,5);
+
+# Do a 'right shift' on the unique key values
+update t1 set uk=uk-1 order by pk;
+
+--sorted_result
+select * from t1 where uk in (0,1,2,3,4);
+
+--echo Master table contents
+select * from t1 order by pk;
+
+flush logs;
+
+--sync_slave_with_master
+
+--connection slave
+
+--echo Slave table contents
+select * from t1 order by pk;
+select * from t1 where uk in (0,1,2,3,4);
+
+--connection master
+drop table t1;
+
+--source include/rpl_end.inc

=== added file 'mysql-test/suite/rpl_ndb/t/rpl_ndb_ui2.test'
--- a/mysql-test/suite/rpl_ndb/t/rpl_ndb_ui2.test	1970-01-01 00:00:00 +0000
+++ b/mysql-test/suite/rpl_ndb/t/rpl_ndb_ui2.test	2011-04-28 07:47:53 +0000
@@ -0,0 +1,36 @@
+--source include/have_ndb.inc
+--source include/have_binlog_format_mixed_or_row.inc
+--source suite/rpl_ndb/ndb_master-slave.inc
+
+--connection master
+
+CREATE TABLE t1 (pk int primary key, uk int not null, unique(uk)) engine=ndb;
+
+--sync_slave_with_master
+--connection slave
+STOP SLAVE;
+insert into t1 values (1,1);
+insert into t1 values (2,2);
+--connection master
+insert into t1 values (1,2);
+insert into t1 values (2,1);
+--sleep 1
+delete from t1;
+--sleep 1
+insert into t1 values (1,1);
+insert into t1 values (2,2);
+
+--connection slave
+start slave;
+
+--connection master
+--sync_slave_with_master
+--connection slave
+--sorted_result
+select * from t1;
+
+--connection master
+drop table t1;
+--sync_slave_with_master
+
+--source include/rpl_end.inc

=== added file 'mysql-test/suite/rpl_ndb/t/rpl_ndb_ui3.test'
--- a/mysql-test/suite/rpl_ndb/t/rpl_ndb_ui3.test	1970-01-01 00:00:00 +0000
+++ b/mysql-test/suite/rpl_ndb/t/rpl_ndb_ui3.test	2011-04-28 07:47:53 +0000
@@ -0,0 +1,54 @@
+--source include/have_ndb.inc
+--source include/have_binlog_format_mixed_or_row.inc
+--source suite/rpl_ndb/ndb_master-slave.inc
+
+#
+# Slave behaviour when replicating unique index operations
+#
+#
+
+--connection master
+
+CREATE TABLE t1 (pk int primary key, uk1 int not null, uk2 int not null,
+       unique(uk1), unique(uk2)) engine=ndb;
+
+# Now perform some operations which do not result in uniqueness
+# violations when applied in-order, but which can result in them
+# when applied out-of-order
+# 5 distinct values chosen to increase the chance of different
+# fragments (and therefore potentially different SUMA->Binlog
+# orders) being seen.
+#
+insert into t1 values (1,1,1);
+insert into t1 values (2,2,2);
+insert into t1 values (3,3,3);
+insert into t1 values (4,4,4);
+insert into t1 values (5,5,5);
+
+--sorted_result
+select * from t1 where uk1 in (1,2,3,4,5);
+
+# Do a 'right shift' on the unique key values
+update t1 set uk1=uk1-1 order by pk;
+update t1 set uk2=uk2+1 order by pk desc;
+
+--sorted_result
+select * from t1 where uk1 in (0,1,2,3,4);
+
+--echo Master table contents
+select * from t1 order by pk;
+
+flush logs;
+
+--sync_slave_with_master
+
+--connection slave
+
+--echo Slave table contents
+select * from t1 order by pk;
+select * from t1 where uk1 in (0,1,2,3,4);
+
+--connection master
+drop table t1;
+
+--source include/rpl_end.inc

=== modified file 'sql/ha_ndbcluster.cc'
--- a/sql/ha_ndbcluster.cc	2011-04-12 16:14:41 +0000
+++ b/sql/ha_ndbcluster.cc	2011-04-28 07:47:53 +0000
@@ -245,7 +245,18 @@ static MYSQL_THDVAR_UINT(
   UINT_MAX,                          /* max */
   0                                  /* block */
 );
-  
+
+static MYSQL_THDVAR_UINT(
+  deferred_constraints,              /* name */
+  PLUGIN_VAR_RQCMDARG,
+  "Specified that constraints should be checked deferred (when supported)",
+  NULL,                              /* check func */
+  NULL,                              /* update func */
+  0,                                 /* default */
+  0,                                 /* min */
+  1,                                 /* max */
+  0                                  /* block */
+);
 
 /*
   Default value for max number of transactions createable against NDB from
@@ -4093,6 +4104,12 @@ int ha_ndbcluster::ndb_write_row(uchar *
     options.extraSetValues= sets;
     options.numExtraSetValues= num_sets;
   }
+  if (thd->slave_thread || THDVAR(thd, deferred_constraints))
+  {
+    options.optionsPresent |=
+      NdbOperation::OperationOptions::OO_DEFERRED_CONSTAINTS;
+  }
+
   if (options.optionsPresent != 0)
     poptions=&options;
 
@@ -4843,6 +4860,12 @@ int ha_ndbcluster::ndb_update_row(const
   
   bool need_flush= add_row_check_if_batch_full(thd_ndb);
 
+  if (thd->slave_thread || THDVAR(thd, deferred_constraints))
+  {
+    options.optionsPresent |=
+      NdbOperation::OperationOptions::OO_DEFERRED_CONSTAINTS;
+  }
+
   if (cursor)
   {
     /*
@@ -5068,6 +5091,12 @@ int ha_ndbcluster::ndb_delete_row(const
   uint delete_size= 12 + (m_bytes_per_write >> 2);
   bool need_flush= add_row_check_if_batch_full_size(thd_ndb, delete_size);
 
+  if (thd->slave_thread || THDVAR(thd, deferred_constraints))
+  {
+    options.optionsPresent |=
+      NdbOperation::OperationOptions::OO_DEFERRED_CONSTAINTS;
+  }
+
   if (cursor)
   {
     if (options.optionsPresent != 0)
@@ -15608,7 +15637,7 @@ static struct st_mysql_sys_var* system_v
   MYSQL_SYSVAR(nodeid),
   MYSQL_SYSVAR(blob_read_batch_bytes),
   MYSQL_SYSVAR(blob_write_batch_bytes),
-
+  MYSQL_SYSVAR(deferred_constraints),
   NULL
 };
 

=== modified file 'sql/sql_partition.cc'
--- a/sql/sql_partition.cc	2011-04-08 13:59:44 +0000
+++ b/sql/sql_partition.cc	2011-04-20 12:50:50 +0000
@@ -3737,7 +3737,11 @@ void get_partition_set(const TABLE *tabl
   part_spec->start_part= 0;
   part_spec->end_part= no_parts - 1;
   if ((index < MAX_KEY) && 
-       key_spec && key_spec->flag == (uint)HA_READ_KEY_EXACT &&
+#ifndef MCP_BUG12380149
+      key_spec && key_spec->flag == (uint)HA_READ_KEY_EXACT &&
+#else
+      key_spec->flag == (uint)HA_READ_KEY_EXACT &&
+#endif
        part_info->some_fields_in_PF.is_set(index))
   {
     key_info= table->key_info+index;

=== modified file 'storage/ndb/include/kernel/GlobalSignalNumbers.h'
--- a/storage/ndb/include/kernel/GlobalSignalNumbers.h	2011-04-09 15:48:21 +0000
+++ b/storage/ndb/include/kernel/GlobalSignalNumbers.h	2011-04-28 07:47:53 +0000
@@ -337,9 +337,11 @@ extern const GlobalSignalNumber NO_OF_SI
 /* 233 unused */
 /* 234 unused */
 #define GSN_DISCONNECT_REP              235
-/* 236 unused */
-/* 237 unused */
-/* 238 unused */
+
+#define GSN_FIRE_TRIG_REQ               236
+#define GSN_FIRE_TRIG_REF               237
+#define GSN_FIRE_TRIG_CONF              238
+
 #define GSN_DIVERIFYCONF                239
 #define GSN_DIVERIFYREF                 240
 #define GSN_DIVERIFYREQ                 241

=== modified file 'storage/ndb/include/kernel/signaldata/FireTrigOrd.hpp'
--- a/storage/ndb/include/kernel/signaldata/FireTrigOrd.hpp	2011-02-01 23:27:25 +0000
+++ b/storage/ndb/include/kernel/signaldata/FireTrigOrd.hpp	2011-04-28 07:47:53 +0000
@@ -225,5 +225,47 @@ void FireTrigOrd::setAnyValue(Uint32 any
   m_any_value = any_value;
 }
 
+struct FireTrigReq
+{
+  STATIC_CONST( SignalLength = 4 );
+
+  Uint32 tcOpRec;
+  Uint32 transId[2];
+  Uint32 pass;
+};
+
+struct FireTrigRef
+{
+  STATIC_CONST( SignalLength = 4 );
+
+  Uint32 tcOpRec;
+  Uint32 transId[2];
+  Uint32 errCode;
+
+  enum ErrorCode
+  {
+    FTR_UnknownOperation = 1235
+    ,FTR_IncorrectState = 1236
+  };
+};
+
+struct FireTrigConf
+{
+  STATIC_CONST( SignalLength = 4 );
+
+  Uint32 tcOpRec;
+  Uint32 transId[2];
+  Uint32 noFiredTriggers; // bit 31 defered trigger
+
+  static Uint32 getFiredCount(Uint32 v) {
+    return NoOfFiredTriggers::getFiredCount(v);
+  }
+  static Uint32 getDeferredBit(Uint32 v) {
+    return NoOfFiredTriggers::getDeferredBit(v);
+  }
+  static void setDeferredBit(Uint32 & v) {
+    NoOfFiredTriggers::setDeferredBit(v);
+  }
+};
 
 #endif

=== modified file 'storage/ndb/include/kernel/signaldata/LqhKey.hpp'
--- a/storage/ndb/include/kernel/signaldata/LqhKey.hpp	2011-02-08 13:55:54 +0000
+++ b/storage/ndb/include/kernel/signaldata/LqhKey.hpp	2011-04-28 07:47:53 +0000
@@ -19,6 +19,7 @@
 #define LQH_KEY_H
 
 #include "SignalData.hpp"
+#include <trigger_definitions.h>
 
 class LqhKeyReq {
   /**
@@ -166,6 +167,12 @@ private:
    */
   static UintR getCorrFactorFlag(const UintR & requestInfo);
   static void setCorrFactorFlag(UintR & requestInfo, UintR val);
+
+  /**
+   * Include corr factor
+   */
+  static UintR getDeferredConstraints(const UintR & requestInfo);
+  static void setDeferredConstraints(UintR & requestInfo, UintR val);
 };
 
 /**
@@ -195,6 +202,7 @@ private:
  * q = Queue on redo problem  - 1  Bit (14)
  * A = CorrFactor flag        - 1  Bit (24)
  * P = Do normal protocol even if dirty-read - 1 Bit (25)
+ * D = Deferred constraints   - 1  Bit (26)
 
  * Short LQHKEYREQ :
  *             1111111111222222222233
@@ -205,7 +213,7 @@ private:
  * Long LQHKEYREQ :
  *             1111111111222222222233
  *   01234567890123456789012345678901
- *             llgnqpdisooorrAP cumxz
+ *             llgnqpdisooorrAPDcumxz
  *
  */
 
@@ -235,6 +243,7 @@ private:
 #define RI_QUEUE_REDO_SHIFT  (14)
 #define RI_CORR_FACTOR_VALUE (24)
 #define RI_NORMAL_DIRTY      (25)
+#define RI_DEFERRED_CONSTAINTS (26)
 
 /**
  * Scan Info
@@ -625,6 +634,19 @@ LqhKeyReq::getCorrFactorFlag(const UintR
 }
 
 inline
+void
+LqhKeyReq::setDeferredConstraints(UintR & requestInfo, UintR val){
+  ASSERT_BOOL(val, "LqhKeyReq::setDeferredConstraints");
+  requestInfo |= (val << RI_DEFERRED_CONSTAINTS);
+}
+
+inline
+UintR
+LqhKeyReq::getDeferredConstraints(const UintR & requestInfo){
+  return (requestInfo >> RI_DEFERRED_CONSTAINTS) & 1;
+}
+
+inline
 Uint32
 table_version_major_lqhkeyreq(Uint32 x)
 {
@@ -688,7 +710,17 @@ private:
   };
   Uint32 transId1;
   Uint32 transId2;
-  Uint32 noFiredTriggers;
+  Uint32 noFiredTriggers; // bit 31 defered trigger
+
+  static Uint32 getFiredCount(Uint32 v) {
+    return NoOfFiredTriggers::getFiredCount(v);
+  }
+  static Uint32 getDeferredBit(Uint32 v) {
+    return NoOfFiredTriggers::getDeferredBit(v);
+  }
+  static void setDeferredBit(Uint32 & v) {
+    NoOfFiredTriggers::setDeferredBit(v);
+  }
 };
 
 class LqhKeyRef {

=== modified file 'storage/ndb/include/kernel/signaldata/PackedSignal.hpp'
--- a/storage/ndb/include/kernel/signaldata/PackedSignal.hpp	2011-02-01 23:27:25 +0000
+++ b/storage/ndb/include/kernel/signaldata/PackedSignal.hpp	2011-04-28 07:47:53 +0000
@@ -28,6 +28,8 @@
 #define ZCOMPLETED 3
 #define ZLQHKEYCONF 4
 #define ZREMOVE_MARKER 5
+#define ZFIRE_TRIG_REQ 6
+#define ZFIRE_TRIG_CONF 7
 
 class PackedSignal {
 

=== modified file 'storage/ndb/include/kernel/signaldata/PrepDropTab.hpp'
--- a/storage/ndb/include/kernel/signaldata/PrepDropTab.hpp	2011-02-01 23:27:25 +0000
+++ b/storage/ndb/include/kernel/signaldata/PrepDropTab.hpp	2011-04-27 10:48:16 +0000
@@ -34,6 +34,7 @@ class PrepDropTabReq {
   friend class Dblqh;
   friend class DblqhProxy;
   friend class Dbdih;
+  friend class DbtcProxy;
 
   friend bool printPREP_DROP_TAB_REQ(FILE *, const Uint32 *, Uint32, Uint16);
 public:
@@ -54,6 +55,7 @@ class PrepDropTabConf {
   friend class Dblqh;
   friend class DblqhProxy;
   friend class Dbdih;
+  friend class DbtcProxy;
 
   /**
    * Receiver(s)
@@ -78,6 +80,7 @@ class PrepDropTabRef {
   friend class Dblqh;
   friend class DblqhProxy;
   friend class Dbdih;
+  friend class DbtcProxy;
 
   /**
    * Receiver(s)

=== modified file 'storage/ndb/include/kernel/signaldata/TcContinueB.hpp'
--- a/storage/ndb/include/kernel/signaldata/TcContinueB.hpp	2011-02-01 23:27:25 +0000
+++ b/storage/ndb/include/kernel/signaldata/TcContinueB.hpp	2011-04-28 07:47:53 +0000
@@ -46,7 +46,8 @@ private:
     TRIGGER_PENDING                        = 17,
     
     DelayTCKEYCONF = 18,
-    ZNF_CHECK_TRANSACTIONS = 19
+    ZNF_CHECK_TRANSACTIONS = 19,
+    ZSEND_FIRE_TRIG_REQ = 20
   };
 };
 

=== modified file 'storage/ndb/include/kernel/signaldata/TcKeyReq.hpp'
--- a/storage/ndb/include/kernel/signaldata/TcKeyReq.hpp	2011-02-08 13:55:54 +0000
+++ b/storage/ndb/include/kernel/signaldata/TcKeyReq.hpp	2011-04-28 07:47:53 +0000
@@ -207,6 +207,13 @@ private:
 
   static void setQueueOnRedoProblemFlag(UintR & requestInfo, UintR val);
   static UintR getQueueOnRedoProblemFlag(const UintR & requestInfo);
+
+  /**
+   * Check constraints deferred
+   */
+  static UintR getDeferredConstraints(const UintR & requestInfo);
+  static void setDeferredConstraints(UintR & requestInfo, UintR val);
+
   /**
    * Set:ers for scanInfo
    */
@@ -237,11 +244,12 @@ private:
  n = No disk flag          - 1  Bit 1
  r = reorg flag            - 1  Bit 19
  q = Queue on redo problem - 1  Bit 9
+ D = deferred constraint   - 1  Bit 17
 
            1111111111222222222233
  01234567890123456789012345678901
  dnb cooop lsyyeiaaarkkkkkkkkkkkk  (Short TCKEYREQ)
- dnbvcooopqlsyyei   r              (Long TCKEYREQ)
+ dnbvcooopqlsyyei D r              (Long TCKEYREQ)
 */
 
 #define TCKEY_NODISK_SHIFT (1)
@@ -270,6 +278,8 @@ private:
 #define TC_REORG_SHIFT     (19)
 #define QUEUE_ON_REDO_SHIFT (9)
 
+#define TC_DEFERRED_CONSTAINTS_SHIFT (17)
+
 /**
  * Scan Info
  *
@@ -612,4 +622,18 @@ TcKeyReq::setQueueOnRedoProblemFlag(Uint
   requestInfo |= (flag << QUEUE_ON_REDO_SHIFT);
 }
 
+inline
+void
+TcKeyReq::setDeferredConstraints(UintR & requestInfo, UintR val){
+  ASSERT_BOOL(val, "TcKeyReq::setDeferredConstraints");
+  requestInfo |= (val << TC_DEFERRED_CONSTAINTS_SHIFT);
+}
+
+inline
+UintR
+TcKeyReq::getDeferredConstraints(const UintR & requestInfo){
+  return (requestInfo >> TC_DEFERRED_CONSTAINTS_SHIFT) & 1;
+}
+
+
 #endif

=== modified file 'storage/ndb/include/kernel/signaldata/TupKey.hpp'
--- a/storage/ndb/include/kernel/signaldata/TupKey.hpp	2011-02-01 23:27:25 +0000
+++ b/storage/ndb/include/kernel/signaldata/TupKey.hpp	2011-04-28 07:47:53 +0000
@@ -38,7 +38,7 @@ class TupKeyReq {
   friend bool printTUPKEYREQ(FILE * output, const Uint32 * theData, Uint32 len, Uint16 receiverBlockNo);
 
 public:
-  STATIC_CONST( SignalLength = 19 );
+  STATIC_CONST( SignalLength = 20 );
 
 private:
 
@@ -64,6 +64,7 @@ private:
   Uint32 m_row_id_page_no;
   Uint32 m_row_id_page_idx;
   Uint32 attrInfoIVal;
+  Uint32 deferred_constraints;
 };
 
 class TupKeyConf {

=== modified file 'storage/ndb/include/kernel/trigger_definitions.h'
--- a/storage/ndb/include/kernel/trigger_definitions.h	2011-02-01 23:27:25 +0000
+++ b/storage/ndb/include/kernel/trigger_definitions.h	2011-04-28 07:47:53 +0000
@@ -196,4 +196,19 @@ struct TriggerInfo {
   }
 };
 
+struct NoOfFiredTriggers
+{
+  STATIC_CONST( DeferredBit = (Uint32(1) << 31) );
+
+  static Uint32 getFiredCount(Uint32 v) {
+    return v & ~(Uint32(DeferredBit));
+  }
+  static Uint32 getDeferredBit(Uint32 v) {
+    return (v & Uint32(DeferredBit)) != 0;
+  }
+  static void setDeferredBit(Uint32 & v) {
+    v |= Uint32(DeferredBit);
+  }
+};
+
 #endif

=== modified file 'storage/ndb/include/ndb_version.h.in'
--- a/storage/ndb/include/ndb_version.h.in	2011-04-09 15:48:21 +0000
+++ b/storage/ndb/include/ndb_version.h.in	2011-04-28 07:47:53 +0000
@@ -611,4 +611,21 @@ ndbd_connectivity_check(Uint32 x)
   return x >= NDBD_PING_REQ_71;
 }
 
+#define NDBD_DEFERRED_UNIQUE_CONSTRAINTS_70 NDB_MAKE_VERSION(7,0,25)
+#define NDBD_DEFERRED_UNIQUE_CONSTRAINTS_71 NDB_MAKE_VERSION(7,1,14)
+
+static
+inline
+int
+ndbd_deferred_unique_constraints(Uint32 x)
+{
+  const Uint32 major = (x >> 16) & 0xFF;
+  const Uint32 minor = (x >>  8) & 0xFF;
+
+  if (major == 7 && minor == 0)
+    return x >= NDBD_DEFERRED_UNIQUE_CONSTRAINTS_70;
+
+  return x >= NDBD_DEFERRED_UNIQUE_CONSTRAINTS_71;
+}
+
 #endif

=== modified file 'storage/ndb/include/ndbapi/Ndb.hpp'
--- a/storage/ndb/include/ndbapi/Ndb.hpp	2011-04-13 19:33:59 +0000
+++ b/storage/ndb/include/ndbapi/Ndb.hpp	2011-04-27 10:48:16 +0000
@@ -1824,11 +1824,12 @@ private:
   void connected(Uint32 block_reference);
  
 
-  NdbTransaction*  startTransactionLocal(Uint32 aPrio, Uint32 aFragmentId); 
+  NdbTransaction*  startTransactionLocal(Uint32 aPrio, Uint32 aNode,
+                                         Uint32 instance);
 
 // Connect the connection object to the Database.
-  int NDB_connect(Uint32 tNode);
-  NdbTransaction* doConnect(Uint32 nodeId); 
+  int NDB_connect(Uint32 tNode, Uint32 instance);
+  NdbTransaction* doConnect(Uint32 nodeId, Uint32 instance);
   void    doDisconnect();	 
   
   NdbReceiver*	        getNdbScanRec();// Get a NdbScanReceiver from idle list
@@ -1906,7 +1907,7 @@ private:
    * Get a connected NdbTransaction to nodeId
    *   Returns NULL if none found
    */
-  NdbTransaction* getConnectedNdbTransaction(Uint32 nodeId);
+  NdbTransaction* getConnectedNdbTransaction(Uint32 nodeId, Uint32 instance);
 
   // Release and disconnect from DBTC a connection
   // and seize it to theConIdleList

=== modified file 'storage/ndb/include/ndbapi/NdbOperation.hpp'
--- a/storage/ndb/include/ndbapi/NdbOperation.hpp	2011-02-09 14:18:53 +0000
+++ b/storage/ndb/include/ndbapi/NdbOperation.hpp	2011-04-28 07:47:53 +0000
@@ -1040,7 +1040,8 @@ public:
                  OO_CUSTOMDATA   = 0x40,
                  OO_LOCKHANDLE   = 0x80,
                  OO_QUEUABLE     = 0x100,
-                 OO_NOT_QUEUABLE = 0x200
+                 OO_NOT_QUEUABLE = 0x200,
+                 OO_DEFERRED_CONSTAINTS = 0x400
     };
 
     /* An operation-specific abort option.
@@ -1439,7 +1440,8 @@ protected:
       word set by setAnyValue().
     */
     OF_USE_ANY_VALUE = 0x2,
-    OF_QUEUEABLE = 0x4
+    OF_QUEUEABLE = 0x4,
+    OF_DEFERRED_CONSTRAINTS = 0x8
   };
   Uint8  m_flags;
 

=== modified file 'storage/ndb/include/ndbapi/NdbTransaction.hpp'
--- a/storage/ndb/include/ndbapi/NdbTransaction.hpp	2011-04-06 14:16:13 +0000
+++ b/storage/ndb/include/ndbapi/NdbTransaction.hpp	2011-04-27 10:48:16 +0000
@@ -1208,6 +1208,8 @@ private:
   // (Only one of theScanningOp/m_scanningQuery be non-NULL,
   //  which indirectly indicates the type)
   NdbQueryImpl* m_scanningQuery;
+
+  Uint32 m_tcRef;
 };
 
 #ifndef DOXYGEN_SHOULD_SKIP_INTERNAL

=== modified file 'storage/ndb/ndb_configure.m4'
--- a/storage/ndb/ndb_configure.m4	2011-03-30 21:15:29 +0000
+++ b/storage/ndb/ndb_configure.m4	2011-04-26 07:25:51 +0000
@@ -2,7 +2,7 @@
 # Should be updated when creating a new NDB version
 NDB_VERSION_MAJOR=7
 NDB_VERSION_MINOR=0
-NDB_VERSION_BUILD=24
+NDB_VERSION_BUILD=25
 NDB_VERSION_STATUS=""
 
 dnl for build ndb docs

=== modified file 'storage/ndb/src/common/debugger/signaldata/LqhKey.cpp'
--- a/storage/ndb/src/common/debugger/signaldata/LqhKey.cpp	2011-02-08 13:55:54 +0000
+++ b/storage/ndb/src/common/debugger/signaldata/LqhKey.cpp	2011-04-28 07:47:53 +0000
@@ -65,7 +65,9 @@ printLQHKEYREQ(FILE * output, const Uint
     fprintf(output, "GCI ");
   if(LqhKeyReq::getQueueOnRedoProblemFlag(reqInfo))
     fprintf(output, "Queue ");
-  
+  if(LqhKeyReq::getDeferredConstraints(reqInfo))
+    fprintf(output, "Deferred-constraints ");
+
   fprintf(output, "ScanInfo/noFiredTriggers: H\'%x\n", sig->scanInfo);
   
   fprintf(output,

=== modified file 'storage/ndb/src/common/debugger/signaldata/PackedSignal.cpp'
--- a/storage/ndb/src/common/debugger/signaldata/PackedSignal.cpp	2011-02-01 23:27:25 +0000
+++ b/storage/ndb/src/common/debugger/signaldata/PackedSignal.cpp	2011-04-28 07:47:53 +0000
@@ -97,6 +97,24 @@ printPACKED_SIGNAL(FILE * output, const
       fprintf(output,"\n");
       break;
     }
+    case ZFIRE_TRIG_REQ: {
+      Uint32 signalLength = 3;
+
+      fprintf(output, "--------------- Signal ----------------\n");
+      fprintf(output, "r.bn: %u \"%s\", length: %u \"FIRE_TRIG_REQ\"\n",
+	      receiverBlockNo, getBlockName(receiverBlockNo,""), signalLength);
+      i += signalLength;
+      break;
+    }
+    case ZFIRE_TRIG_CONF: {
+      Uint32 signalLength = 4;
+
+      fprintf(output, "--------------- Signal ----------------\n");
+      fprintf(output, "r.bn: %u \"%s\", length: %u \"FIRE_TRIG_CONF\"\n",
+	      receiverBlockNo, getBlockName(receiverBlockNo,""), signalLength);
+      i += signalLength;
+      break;
+    }
     default:
       fprintf(output, "Unknown signal type\n");
       i = len; // terminate printing

=== modified file 'storage/ndb/src/common/debugger/signaldata/TcKeyReq.cpp'
--- a/storage/ndb/src/common/debugger/signaldata/TcKeyReq.cpp	2011-02-08 13:55:54 +0000
+++ b/storage/ndb/src/common/debugger/signaldata/TcKeyReq.cpp	2011-04-28 07:47:53 +0000
@@ -79,6 +79,9 @@ printTCKEYREQ(FILE * output, const Uint3
     if(sig->getQueueOnRedoProblemFlag(sig->requestInfo))
       fprintf(output, "Queue ");
 
+    if(sig->getDeferredConstraints(sig->requestInfo))
+      fprintf(output, "Deferred-constraints ");
+
     fprintf(output, "\n");
   }
   

=== modified file 'storage/ndb/src/kernel/blocks/CMakeLists.txt'
--- a/storage/ndb/src/kernel/blocks/CMakeLists.txt	2011-02-23 19:28:26 +0000
+++ b/storage/ndb/src/kernel/blocks/CMakeLists.txt	2011-04-27 10:48:16 +0000
@@ -67,6 +67,7 @@ ADD_LIBRARY(ndbblocks STATIC
     dbtux/DbtuxProxy.cpp
     backup/BackupProxy.cpp
     RestoreProxy.cpp
+    dbtc/DbtcProxy.cpp
     dbinfo/Dbinfo.cpp
     dblqh/DblqhCommon.cpp
     PgmanProxy.cpp

=== modified file 'storage/ndb/src/kernel/blocks/ERROR_codes.txt'
--- a/storage/ndb/src/kernel/blocks/ERROR_codes.txt	2011-04-09 15:48:21 +0000
+++ b/storage/ndb/src/kernel/blocks/ERROR_codes.txt	2011-04-28 07:47:53 +0000
@@ -18,10 +18,10 @@ Next NDBCNTR 1002
 Next NDBFS 2000
 Next DBACC 3002
 Next DBTUP 4035
-Next DBLQH 5064
+Next DBLQH 5072
 Next DBDICT 6026
 Next DBDIH 7229
-Next DBTC 8090
+Next DBTC 8092
 Next CMVMI 9000
 Next BACKUP 10042
 Next DBUTIL 11002

=== modified file 'storage/ndb/src/kernel/blocks/LocalProxy.cpp'
--- a/storage/ndb/src/kernel/blocks/LocalProxy.cpp	2011-02-02 00:40:07 +0000
+++ b/storage/ndb/src/kernel/blocks/LocalProxy.cpp	2011-04-27 10:48:16 +0000
@@ -848,8 +848,6 @@ LocalProxy::execTIME_SIGNAL(Signal* sign
 {
   Ss_TIME_SIGNAL& ss = ssSeize<Ss_TIME_SIGNAL>();
 
-  // could use same for MT TC
-  ndbrequire(number() == DBLQH);
   sendREQ(signal, ss);
   ssRelease<Ss_TIME_SIGNAL>(ss);
 }

=== modified file 'storage/ndb/src/kernel/blocks/Makefile.am'
--- a/storage/ndb/src/kernel/blocks/Makefile.am	2011-02-23 19:28:26 +0000
+++ b/storage/ndb/src/kernel/blocks/Makefile.am	2011-04-27 10:48:16 +0000
@@ -67,7 +67,8 @@ libblocks_a_SOURCES = tsman.cpp lgman.cp
   dbinfo/Dbinfo.cpp \
   dblqh/DblqhCommon.cpp \
   PgmanProxy.cpp \
-  dbtup/DbtupClient.cpp
+  dbtup/DbtupClient.cpp \
+  dbtc/DbtcProxy.cpp
 
 ndbtools_PROGRAMS = ndb_print_file
 ndb_print_file_SOURCES = print_file.cpp diskpage.cpp dbtup/tuppage.cpp

=== modified file 'storage/ndb/src/kernel/blocks/dblqh/Dblqh.hpp'
--- a/storage/ndb/src/kernel/blocks/dblqh/Dblqh.hpp	2011-04-19 09:01:07 +0000
+++ b/storage/ndb/src/kernel/blocks/dblqh/Dblqh.hpp	2011-04-28 07:47:53 +0000
@@ -2112,10 +2112,12 @@ public:
     Uint8 m_disk_table;
     Uint8 m_use_rowid;
     Uint8 m_dealloc;
+    Uint8 m_fire_trig_pass;
     enum op_flags {
       OP_ISLONGREQ              = 0x1,
       OP_SAVEATTRINFO           = 0x2,
-      OP_SCANKEYINFOPOSSAVED    = 0x4
+      OP_SCANKEYINFOPOSSAVED    = 0x4,
+      OP_DEFERRED_CONSTRAINTS   = 0x8
     };
     Uint32 m_flags;
     Uint32 m_log_part_ptr_i;
@@ -2308,6 +2310,8 @@ private:
   void execBUILD_INDX_IMPL_REF(Signal* signal);
   void execBUILD_INDX_IMPL_CONF(Signal* signal);
 
+  void execFIRE_TRIG_REQ(Signal*);
+
   // Statement blocks
 
   void init_acc_ptr_list(ScanRecord*);
@@ -3266,6 +3270,9 @@ public:
   void suspendFile(Signal* signal, Ptr<LogFileRecord> logFile, Uint32 millis);
 
   void send_runredo_event(Signal*, LogPartRecord *, Uint32 currgci);
+
+  void sendFireTrigConfTc(Signal* signal, BlockReference ref, Uint32 Tdata[]);
+  bool check_fire_trig_pass(Uint32 op, Uint32 pass);
 };
 
 inline

=== modified file 'storage/ndb/src/kernel/blocks/dblqh/DblqhInit.cpp'
--- a/storage/ndb/src/kernel/blocks/dblqh/DblqhInit.cpp	2011-03-28 11:59:09 +0000
+++ b/storage/ndb/src/kernel/blocks/dblqh/DblqhInit.cpp	2011-04-28 07:47:53 +0000
@@ -424,6 +424,8 @@ Dblqh::Dblqh(Block_context& ctx, Uint32
                &Dblqh::execFSWRITEREQ);
   addRecSignal(GSN_DBINFO_SCANREQ, &Dblqh::execDBINFO_SCANREQ);
 
+  addRecSignal(GSN_FIRE_TRIG_REQ, &Dblqh::execFIRE_TRIG_REQ);
+
   initData();
 
 #ifdef VM_TRACE

=== modified file 'storage/ndb/src/kernel/blocks/dblqh/DblqhMain.cpp'
--- a/storage/ndb/src/kernel/blocks/dblqh/DblqhMain.cpp	2011-04-21 13:45:17 +0000
+++ b/storage/ndb/src/kernel/blocks/dblqh/DblqhMain.cpp	2011-04-28 12:04:11 +0000
@@ -74,6 +74,7 @@
 #include <signaldata/FsReadWriteReq.hpp>
 #include <signaldata/DbinfoScan.hpp>
 #include <signaldata/SystemError.hpp>
+#include <signaldata/FireTrigOrd.hpp>
 #include <NdbEnv.h>
 
 #include "../suma/Suma.hpp"
@@ -3196,6 +3197,7 @@ void Dblqh::execPACKED_SIGNAL(Signal* si
 
   jamEntry();
   Tlength = signal->length();
+  Uint32 TsenderRef = signal->getSendersBlockRef();
   Uint32 TcommitLen = 5;
   Uint32 Tgci_lo_mask = ~(Uint32)0;
 
@@ -3244,8 +3246,7 @@ void Dblqh::execPACKED_SIGNAL(Signal* si
       break;
     case ZLQHKEYCONF: {
       jam();
-      LqhKeyConf * const lqhKeyConf = (LqhKeyConf *)signal->getDataPtr();
-
+      LqhKeyConf * lqhKeyConf = CAST_PTR(LqhKeyConf, signal->theData);
       sig0 = TpackedData[Tstep + 0] & 0x0FFFFFFF;
       sig1 = TpackedData[Tstep + 1];
       sig2 = TpackedData[Tstep + 2];
@@ -3274,6 +3275,22 @@ void Dblqh::execPACKED_SIGNAL(Signal* si
       execREMOVE_MARKER_ORD(signal);
       Tstep += 3;
       break;
+    case ZFIRE_TRIG_REQ:
+      jam();
+      ndbassert(FireTrigReq::SignalLength == 4);
+      sig0 = TpackedData[Tstep + 0] & 0x0FFFFFFF;
+      sig1 = TpackedData[Tstep + 1];
+      sig2 = TpackedData[Tstep + 2];
+      sig3 = TpackedData[Tstep + 3];
+      signal->theData[0] = sig0;
+      signal->theData[1] = sig1;
+      signal->theData[2] = sig2;
+      signal->theData[3] = sig3;
+      signal->header.theLength = FireTrigReq::SignalLength;
+      signal->header.theSendersBlockRef = TsenderRef;
+      execFIRE_TRIG_REQ(signal);
+      Tstep += FireTrigReq::SignalLength;
+      break;
     default:
       ndbrequire(false);
       return;
@@ -3690,6 +3707,16 @@ void Dblqh::sendCompleteLqh(Signal* sign
 
 void Dblqh::sendCommittedTc(Signal* signal, BlockReference atcBlockref)
 {
+  if (refToInstance(atcBlockref))
+  {
+    jam();
+    signal->theData[0] = tcConnectptr.p->clientConnectrec;
+    signal->theData[1] = tcConnectptr.p->transid[0];
+    signal->theData[2] = tcConnectptr.p->transid[1];
+    sendSignal(atcBlockref, GSN_COMMITTED, signal, 3, JBB);
+    return;
+  }
+
   HostRecordPtr Thostptr;
   Thostptr.i = refToNode(atcBlockref);
   ptrCheckGuard(Thostptr, chostFileSize, hostRecord);
@@ -3726,6 +3753,16 @@ void Dblqh::sendCommittedTc(Signal* sign
 
 void Dblqh::sendCompletedTc(Signal* signal, BlockReference atcBlockref)
 {
+  if (refToInstance(atcBlockref))
+  {
+    jam();
+    signal->theData[0] = tcConnectptr.p->clientConnectrec;
+    signal->theData[1] = tcConnectptr.p->transid[0];
+    signal->theData[2] = tcConnectptr.p->transid[1];
+    sendSignal(atcBlockref, GSN_COMPLETED, signal, 3, JBB);
+    return;
+  }
+
   HostRecordPtr Thostptr;
   Thostptr.i = refToNode(atcBlockref);
   ptrCheckGuard(Thostptr, chostFileSize, hostRecord);
@@ -4547,6 +4584,13 @@ void Dblqh::execLQHKEYREQ(Signal* signal
     nextPos += 2;
   }
 
+  Uint32 Tdeferred = LqhKeyReq::getDeferredConstraints(Treqinfo);
+  if (isLongReq && Tdeferred)
+  {
+    regTcPtr->m_flags |= TcConnectionrec::OP_DEFERRED_CONSTRAINTS;
+    regTcPtr->m_fire_trig_pass = 0;
+  }
+
   UintR TitcKeyLen = 0;
   Uint32 keyLenWithLQHReq = 0;
   UintR TreclenAiLqhkey   = 0;
@@ -4617,8 +4661,16 @@ void Dblqh::execLQHKEYREQ(Signal* signal
   /* Only node restart copy allowed to send no KeyInfo */
   if (unlikely(keyLenWithLQHReq == 0))
   {
-    if (! (LqhKeyReq::getNrCopyFlag(Treqinfo)) &&
-        refToMain(senderRef) != DBSPJ)
+    if (refToMain(senderRef) == DBSPJ)
+    {
+      jam();
+      ndbassert(! LqhKeyReq::getNrCopyFlag(Treqinfo));
+      terrorCode = ZNO_TUPLE_FOUND;
+      abortErrorLab(signal);
+      return;
+    }
+
+    if (! LqhKeyReq::getNrCopyFlag(Treqinfo))
     {
       LQHKEY_error(signal, 3);
       return;
@@ -5893,6 +5945,7 @@ Dblqh::acckeyconf_tupkeyreq(Signal* sign
   Uint32 page_idx = lkey2;
   Uint32 page_no = lkey1;
   Uint32 Ttupreq = regTcPtr->dirtyOp;
+  Uint32 flags = regTcPtr->m_flags;
   Ttupreq = Ttupreq + (regTcPtr->opSimple << 1);
   Ttupreq = Ttupreq + (op << 6);
   Ttupreq = Ttupreq + (regTcPtr->opExec << 10);
@@ -5955,6 +6008,8 @@ Dblqh::acckeyconf_tupkeyreq(Signal* sign
   regTcPtr->m_row_id.m_page_idx = page_idx;
   
   tupKeyReq->attrInfoIVal= RNIL;
+  tupKeyReq->deferred_constraints =
+    (flags & TcConnectionrec::OP_DEFERRED_CONSTRAINTS) != 0;
 
   /* Pass AttrInfo section if available in the TupKeyReq signal
    * We are still responsible for releasing it, TUP is just
@@ -7291,6 +7346,160 @@ void Dblqh::errorReport(Signal* signal,
   return;
 }//Dblqh::errorReport()
 
+void
+Dblqh::execFIRE_TRIG_REQ(Signal* signal)
+{
+  Uint32 tcOprec = signal->theData[0];
+  Uint32 transid1 = signal->theData[1];
+  Uint32 transid2 = signal->theData[2];
+  Uint32 pass = signal->theData[3];
+  Uint32 senderRef = signal->getSendersBlockRef();
+
+  jamEntry();
+
+  if (ERROR_INSERTED_CLEAR(5064))
+  {
+    // throw away...should cause timeout in TC
+    return;
+  }
+
+  CRASH_INSERTION(5072);
+
+  Uint32 err;
+  if (findTransaction(transid1, transid2, tcOprec, 0) == ZOK &&
+      !ERROR_INSERTED_CLEAR(5065) &&
+      !ERROR_INSERTED(5070) &&
+      !ERROR_INSERTED(5071))
+  {
+    TcConnectionrec * const regTcPtr = tcConnectptr.p;
+
+    if (unlikely(regTcPtr->transactionState != TcConnectionrec::PREPARED ||
+                 ERROR_INSERTED_CLEAR(5067)))
+    {
+      err = FireTrigRef::FTR_IncorrectState;
+      goto do_err;
+    }
+
+    /**
+     *
+     */
+    signal->theData[0] = regTcPtr->tupConnectrec;
+    signal->theData[1] = regTcPtr->tcBlockref;
+    signal->theData[2] = regTcPtr->tcOprec;
+    signal->theData[3] = transid1;
+    signal->theData[4] = transid2;
+    signal->theData[5] = pass;
+    Uint32 tup = refToMain(regTcPtr->tcTupBlockref);
+    EXECUTE_DIRECT(tup, GSN_FIRE_TRIG_REQ, signal, 6);
+
+    err = signal->theData[0];
+    Uint32 cnt = signal->theData[1];
+
+    if (ERROR_INSERTED_CLEAR(5066))
+    {
+      err = 5066;
+    }
+
+    if (ERROR_INSERTED_CLEAR(5068))
+      tcOprec++;
+    if (ERROR_INSERTED_CLEAR(5069))
+      transid1++;
+
+    if (err == 0)
+    {
+      jam();
+      Uint32 Tdata[FireTrigConf::SignalLength];
+      FireTrigConf * conf = CAST_PTR(FireTrigConf, Tdata);
+      conf->tcOpRec = tcOprec;
+      conf->transId[0] = transid1;
+      conf->transId[1] = transid2;
+      conf->noFiredTriggers = cnt;
+      sendFireTrigConfTc(signal, regTcPtr->tcBlockref, Tdata);
+      return;
+    }
+  }
+  else
+  {
+    jam();
+    err = FireTrigRef::FTR_UnknownOperation;
+  }
+
+do_err:
+  if (ERROR_INSERTED_CLEAR(5070))
+    tcOprec++;
+
+  if (ERROR_INSERTED_CLEAR(5071))
+    transid1++;
+
+  FireTrigRef * ref = CAST_PTR(FireTrigRef, signal->getDataPtrSend());
+  ref->tcOpRec = tcOprec;
+  ref->transId[0] = transid1;
+  ref->transId[1] = transid2;
+  ref->errCode = err;
+  sendSignal(senderRef, GSN_FIRE_TRIG_REF,
+             signal, FireTrigRef::SignalLength, JBB);
+
+  return;
+}
+
+void
+Dblqh::sendFireTrigConfTc(Signal* signal,
+                          BlockReference atcBlockref,
+                          Uint32 Tdata[])
+{
+  if (refToInstance(atcBlockref) != 0)
+  {
+    jam();
+    memcpy(signal->theData, Tdata, 4 * FireTrigConf::SignalLength);
+    sendSignal(atcBlockref, GSN_FIRE_TRIG_CONF,
+               signal, FireTrigConf::SignalLength, JBB);
+    return;
+  }
+
+  HostRecordPtr Thostptr;
+  Uint32 len = FireTrigConf::SignalLength;
+
+  Thostptr.i = refToNode(atcBlockref);
+  ptrCheckGuard(Thostptr, chostFileSize, hostRecord);
+
+  if (Thostptr.p->noOfPackedWordsTc > (25 - len))
+  {
+    jam();
+    sendPackedSignalTc(signal, Thostptr.p);
+  }
+  else
+  {
+    jam();
+    updatePackedList(signal, Thostptr.p, Thostptr.i);
+  }
+
+  ndbassert(FireTrigConf::SignalLength == 4);
+  Uint32 * dst = &Thostptr.p->packedWordsTc[Thostptr.p->noOfPackedWordsTc];
+  Thostptr.p->noOfPackedWordsTc += len;
+  dst[0] = Tdata[0] | (ZFIRE_TRIG_CONF << 28);
+  dst[1] = Tdata[1];
+  dst[2] = Tdata[2];
+  dst[3] = Tdata[3];
+}
+
+bool
+Dblqh::check_fire_trig_pass(Uint32 opId, Uint32 pass)
+{
+  /**
+   * Check that trigger only fires once per pass
+   *   (per primary key)
+   */
+  TcConnectionrecPtr regTcPtr;
+  regTcPtr.i= opId;
+  ptrCheckGuard(regTcPtr, ctcConnectrecFileSize, tcConnectionrec);
+  if (regTcPtr.p->m_fire_trig_pass <= pass)
+  {
+    regTcPtr.p->m_fire_trig_pass = pass + 1;
+    return true;
+  }
+  return false;
+}
+
 /* ************************************************************************>>
  *  COMMIT: Start commit request from TC. This signal is originally sent as a
  *  packed signal and this function is called from execPACKED_SIGNAL.

=== modified file 'storage/ndb/src/kernel/blocks/dbtc/Dbtc.hpp'
--- a/storage/ndb/src/kernel/blocks/dbtc/Dbtc.hpp	2011-04-01 07:10:05 +0000
+++ b/storage/ndb/src/kernel/blocks/dbtc/Dbtc.hpp	2011-04-28 07:47:53 +0000
@@ -170,7 +170,17 @@ public:
     CS_FAIL_COMMITTING = 22,
     CS_FAIL_COMMITTED = 23,
     CS_FAIL_COMPLETED = 24,
-    CS_START_SCAN = 25
+    CS_START_SCAN = 25,
+
+    /**
+     * Sending FIRE_TRIG_REQ
+     */
+    CS_SEND_FIRE_TRIG_REQ = 26,
+
+    /**
+     * Waiting for FIRE_TRIG_CONF/REF (or operations generated by this)
+     */
+    CS_WAIT_FIRE_TRIG_REQ = 27
   };
 
   enum OperationState {
@@ -191,7 +201,9 @@ public:
     OS_WAIT_COMMIT_CONF = 15,
     OS_WAIT_ABORT_CONF = 16,
     OS_WAIT_COMPLETE_CONF = 17,
-    OS_WAIT_SCAN = 18
+    OS_WAIT_SCAN = 18,
+
+    OS_FIRE_TRIG_REQ = 19,
   };
 
   enum AbortState {
@@ -693,7 +705,10 @@ public:
     //---------------------------------------------------
     UintR lastTcConnect;
     UintR lqhkeyreqrec;
-    Uint32 buddyPtr;
+    union {
+      Uint32 buddyPtr;
+      Int32 pendingTriggers; // For deferred triggers
+    };
     union {
       UintR apiScanRec;
       UintR commitAckMarker;
@@ -709,6 +724,8 @@ public:
       TF_TRIGGER_PENDING = 2, // Used to mark waiting for a CONTINUEB
       TF_EXEC_FLAG       = 4,
       TF_COMMIT_ACK_MARKER_RECEIVED = 8,
+      TF_DEFERRED_CONSTRAINTS = 16, // check constraints in deferred fashion
+      TF_DEFERRED_TRIGGERS = 32, // trans has deferred triggers
       TF_END = 0
     };
     Uint32 m_flags;
@@ -779,6 +796,12 @@ public:
 #ifdef ERROR_INSERT
     Uint32 continueBCount;  // ERROR_INSERT 8082
 #endif
+    Uint8 m_pre_commit_pass;
+
+    bool isExecutingDeferredTriggers() const {
+      return apiConnectstate == CS_SEND_FIRE_TRIG_REQ ||
+        apiConnectstate == CS_WAIT_FIRE_TRIG_REQ ;
+    }
   };
   
   typedef Ptr<ApiConnectRecord> ApiConnectRecordPtr;
@@ -843,7 +866,8 @@ public:
       SOF_REORG_MOVING = 8,           // A record that should be moved
       SOF_TRIGGER = 16,               // A trigger
       SOF_REORG_COPY = 32,
-      SOF_REORG_DELETE = 64
+      SOF_REORG_DELETE = 64,
+      SOF_DEFERRED_TRIGGER = 128      // Op has deferred trigger
     };
     
     static inline bool isIndexOp(Uint8 flags) {
@@ -866,12 +890,12 @@ public:
     Uint16 lqhInstanceKey;
     
     // Trigger data
-    FiredTriggerPtr accumulatingTriggerData;
-    UintR noFiredTriggers;
-    UintR noReceivedTriggers;
-    UintR triggerExecutionCount;
-    UintR triggeringOperation;
+    UintR noFiredTriggers;      // As reported by lqhKeyConf
+    UintR noReceivedTriggers;   // FIRE_TRIG_ORD
+    UintR triggerExecutionCount;// No of outstanding op due to triggers
     UintR savedState[LqhKeyConf::SignalLength];
+
+    UintR triggeringOperation;  // Which operation was "cause" of this op
     
     // Index data
     UintR indexOp;
@@ -1374,6 +1398,8 @@ private:
   void execALTER_INDX_IMPL_REQ(Signal* signal);
   void execSIGNAL_DROPPED_REP(Signal* signal);
 
+  void execFIRE_TRIG_REF(Signal*);
+  void execFIRE_TRIG_CONF(Signal*);
 
   // Index table lookup
   void execTCKEYCONF(Signal* signal);
@@ -1413,6 +1439,10 @@ private:
                        TcConnectRecord * const regTcPtr);
   Uint32 sendCompleteLqh(Signal* signal,
                          TcConnectRecord * const regTcPtr);
+
+  void sendFireTrigReq(Signal*, Ptr<ApiConnectRecord>, Uint32 firstTcConnect);
+  Uint32 sendFireTrigReqLqh(Signal*, Ptr<TcConnectRecord>, Uint32 pass);
+
   void sendTCKEY_FAILREF(Signal* signal, ApiConnectRecord *);
   void sendTCKEY_FAILCONF(Signal* signal, ApiConnectRecord *);
   void routeTCKEY_FAILREFCONF(Signal* signal, const ApiConnectRecord *, 
@@ -1549,11 +1579,10 @@ private:
 			     TcConnectRecord* trigOp);
   void restoreTriggeringOpState(Signal* signal, 
 				TcConnectRecord* trigOp);
-  void continueTriggeringOp(Signal* signal, 
-			    TcConnectRecord* trigOp);
+  void trigger_op_finished(Signal* signal, ApiConnectRecordPtr,
+                           TcConnectRecord* triggeringOp);
+  void continueTriggeringOp(Signal* signal, TcConnectRecord* trigOp);
 
-  void scheduleFiredTrigger(ApiConnectRecordPtr* transPtr, 
-                            TcConnectRecordPtr* opPtr);
   void executeTriggers(Signal* signal, ApiConnectRecordPtr* transPtr);
   void executeTrigger(Signal* signal,
                       TcFiredTriggerData* firedTriggerData,
@@ -1573,14 +1602,12 @@ private:
                             TcFiredTriggerData* firedTriggerData, 
                             ApiConnectRecordPtr* transPtr,
                             TcConnectRecordPtr* opPtr,
-                            TcIndexData* indexData,
-                            bool holdOperation = false);
+                            TcIndexData* indexData);
   void deleteFromIndexTable(Signal* signal, 
                             TcFiredTriggerData* firedTriggerData, 
                             ApiConnectRecordPtr* transPtr,
                             TcConnectRecordPtr* opPtr,
-                            TcIndexData* indexData,
-                            bool holdOperation = false);
+                            TcIndexData* indexData);
 
   void executeReorgTrigger(Signal* signal,
                            TcDefinedTriggerData* definedTriggerData,
@@ -2066,6 +2093,7 @@ private:
   // Used with ERROR_INSERT 8078 + 8079 to check API_FAILREQ handling
   Uint32 c_lastFailedApi;
 #endif
+  Uint32 m_deferred_enabled;
 };
 
 #endif

=== modified file 'storage/ndb/src/kernel/blocks/dbtc/DbtcInit.cpp'
--- a/storage/ndb/src/kernel/blocks/dbtc/DbtcInit.cpp	2011-02-03 14:20:36 +0000
+++ b/storage/ndb/src/kernel/blocks/dbtc/DbtcInit.cpp	2011-04-28 07:47:53 +0000
@@ -297,7 +297,10 @@ Dbtc::Dbtc(Block_context& ctx, Uint32 in
   addRecSignal(GSN_ALTER_TAB_REQ, &Dbtc::execALTER_TAB_REQ);
   addRecSignal(GSN_ROUTE_ORD, &Dbtc::execROUTE_ORD);
   addRecSignal(GSN_TCKEY_FAILREFCONF_R, &Dbtc::execTCKEY_FAILREFCONF_R);
-  
+
+  addRecSignal(GSN_FIRE_TRIG_REF, &Dbtc::execFIRE_TRIG_REF);
+  addRecSignal(GSN_FIRE_TRIG_CONF, &Dbtc::execFIRE_TRIG_CONF);
+
   cacheRecord = 0;
   apiConnectRecord = 0;
   tcConnectRecord = 0;
@@ -334,6 +337,7 @@ Dbtc::Dbtc(Block_context& ctx, Uint32 in
   c_apiConTimer = 0;
   c_apiConTimer_line = 0;
   csystemStart = SSS_FALSE;
+  m_deferred_enabled = ~Uint32(0);
 }//Dbtc::Dbtc()
 
 Dbtc::~Dbtc() 

=== modified file 'storage/ndb/src/kernel/blocks/dbtc/DbtcMain.cpp'
--- a/storage/ndb/src/kernel/blocks/dbtc/DbtcMain.cpp	2011-04-06 14:46:42 +0000
+++ b/storage/ndb/src/kernel/blocks/dbtc/DbtcMain.cpp	2011-04-28 07:47:53 +0000
@@ -342,6 +342,19 @@ void Dbtc::execCONTINUEB(Signal* signal)
     ptrCheckGuard(apiConnectptr, capiConnectFilesize, apiConnectRecord);
     sendtckeyconf(signal, Tdata1);
     return;
+  case TcContinueB::ZSEND_FIRE_TRIG_REQ:
+    jam();
+    apiConnectptr.i = Tdata0;
+    ptrCheckGuard(apiConnectptr, capiConnectFilesize, apiConnectRecord);
+    if (unlikely(! (apiConnectptr.p->transid[0] == Tdata1 &&
+                    apiConnectptr.p->transid[1] == Tdata2 &&
+                    apiConnectptr.p->apiConnectstate == CS_SEND_FIRE_TRIG_REQ)))
+    {
+      warningReport(signal, 29);
+      return;
+    }
+    sendFireTrigReq(signal, apiConnectptr, signal->theData[4]);
+    return;
   default:
     ndbrequire(false);
   }//switch
@@ -392,6 +405,16 @@ void Dbtc::execINCL_NODEREQ(Signal* sign
   }
 
   sendSignal(tblockref, GSN_INCL_NODECONF, signal, 2, JBB);
+
+  if (m_deferred_enabled)
+  {
+    jam();
+    if (!ndbd_deferred_unique_constraints(getNodeInfo(Tnode).m_version))
+    {
+      jam();
+      m_deferred_enabled = 0;
+    }
+  }
 }
 
 void Dbtc::execREAD_NODESREF(Signal* signal) 
@@ -871,6 +894,11 @@ void Dbtc::execREAD_NODESCONF(Signal* si
           jam();
           hostptr.p->hostLqhBlockRef = numberToRef(DBLQH, i);
         }
+        if (!ndbd_deferred_unique_constraints(getNodeInfo(i).m_version))
+        {
+          jam();
+          m_deferred_enabled = 0;
+        }
       }//if
     }//if
   }//for
@@ -1199,6 +1227,11 @@ void Dbtc::execTCSEIZEREQ(Signal* signal
   jamEntry();
   tapiPointer = signal->theData[0]; /* REQUEST SENDERS CONNECT RECORD POINTER*/
   tapiBlockref = signal->theData[1]; /* SENDERS BLOCK REFERENCE*/
+
+  if (signal->getLength() > 2)
+  {
+    ndbassert(instance() == signal->theData[2]);
+  }
   
   const NodeState::StartLevel sl = 
     (NodeState::StartLevel)getNodeState().startLevel;
@@ -2342,6 +2375,7 @@ void Dbtc::initApiConnectRec(Signal* sig
   regApiPtr->currSavePointId = 0;
   regApiPtr->m_transaction_nodes.clear();
   regApiPtr->singleUserMode = 0;
+  regApiPtr->m_pre_commit_pass = 0;
   // Trigger data
   releaseFiredTriggerData(&regApiPtr->theFiredTriggers);
   // Index data
@@ -2352,6 +2386,8 @@ void Dbtc::initApiConnectRec(Signal* sig
     releaseAllSeizedIndexOperations(regApiPtr);
   regApiPtr->immediateTriggerId = RNIL;
 
+  tc_clearbit(regApiPtr->m_flags,
+              ApiConnectRecord::TF_DEFERRED_CONSTRAINTS);
   c_counters.ctransCount++;
 
 #ifdef ERROR_INSERT
@@ -2392,8 +2428,6 @@ Dbtc::seizeTcRecord(Signal* signal)
 
   regTcPtr->prevTcConnect = TlastTcConnect;
   regTcPtr->nextTcConnect = RNIL;
-  regTcPtr->accumulatingTriggerData.i = RNIL;  
-  regTcPtr->accumulatingTriggerData.p = NULL;  
   regTcPtr->noFiredTriggers = 0;
   regTcPtr->noReceivedTriggers = 0;
   regTcPtr->triggerExecutionCount = 0;
@@ -2633,6 +2667,8 @@ void Dbtc::execTCKEYREQ(Signal* signal)
     }//if
     break;
   case CS_START_COMMITTING:
+  case CS_SEND_FIRE_TRIG_REQ:
+  case CS_WAIT_FIRE_TRIG_REQ:
     jam();
     if(isIndexOpReturn || isExecutingTrigger){
       break;
@@ -2755,6 +2791,11 @@ void Dbtc::execTCKEYREQ(Signal* signal)
     SegmentedSectionPtr attrInfoSec;
     if (handle.getSection(attrInfoSec, TcKeyReq::AttrInfoSectionNum))
       TattrLen= attrInfoSec.sz;
+
+    if (TcKeyReq::getDeferredConstraints(Treqinfo))
+    {
+      regApiPtr->m_flags |= ApiConnectRecord::TF_DEFERRED_CONSTRAINTS;
+    }
   }
   else
   {
@@ -3051,7 +3092,7 @@ void Dbtc::execTCKEYREQ(Signal* signal)
       jam();
       // Trigger execution at commit
       regApiPtr->apiConnectstate = CS_REC_COMMITTING;
-    } else {
+    } else if (!regApiPtr->isExecutingDeferredTriggers()) {
       jam();
       regApiPtr->apiConnectstate = CS_RECEIVING;
     }//if
@@ -3347,6 +3388,10 @@ void Dbtc::tckeyreq050Lab(Signal* signal
       jam();
       regApiPtr->apiConnectstate = CS_START_COMMITTING;
       break;
+    case CS_SEND_FIRE_TRIG_REQ:
+    case CS_WAIT_FIRE_TRIG_REQ:
+      jam();
+      break;
     default:
       jam();
       systemErrorLab(signal, __LINE__);
@@ -3428,16 +3473,7 @@ void Dbtc::attrinfoDihReceivedLab(Signal
       TcConnectRecordPtr opPtr;
       opPtr.i = trigOp;
       ptrCheckGuard(opPtr, ctcConnectFilesize, tcConnectRecord);
-      opPtr.p->triggerExecutionCount--;
-      if (opPtr.p->triggerExecutionCount == 0)
-      {
-        /**
-         * We have completed current trigger execution
-         * Continue triggering operation
-         */
-        jam();
-        continueTriggeringOp(signal, opPtr.p);
-      }
+      trigger_op_finished(signal, apiConnectptr, opPtr.p);
       return;
     }
     else
@@ -3518,6 +3554,8 @@ void Dbtc::sendlqhkeyreq(Signal* signal,
     }//if
   }//if
 #endif
+  Uint32 Tdeferred = tc_testbit(regApiPtr->m_flags,
+                                ApiConnectRecord::TF_DEFERRED_CONSTRAINTS);
   Uint32 reorg = 0;
   Uint32 Tspecial_op = regTcPtr->m_special_op_flags;
   if (Tspecial_op == 0)
@@ -3584,6 +3622,7 @@ void Dbtc::sendlqhkeyreq(Signal* signal,
   LqhKeyReq::setOperation(Tdata10, sig1);
   LqhKeyReq::setNoDiskFlag(Tdata10, regCachePtr->m_no_disk_flag);
   LqhKeyReq::setQueueOnRedoProblemFlag(Tdata10, regCachePtr->m_op_queue);
+  LqhKeyReq::setDeferredConstraints(Tdata10, (Tdeferred & m_deferred_enabled));
 
   /* ----------------------------------------------------------------------- 
    * If we are sending a short LQHKEYREQ, then there will be some AttrInfo
@@ -3664,8 +3703,6 @@ void Dbtc::sendlqhkeyreq(Signal* signal,
   }//if
 
   // Reset trigger count
-  regTcPtr->accumulatingTriggerData.i = RNIL;  
-  regTcPtr->accumulatingTriggerData.p = NULL;  
   regTcPtr->noFiredTriggers = 0;
   regTcPtr->triggerExecutionCount = 0;
 
@@ -3989,6 +4026,13 @@ void Dbtc::execPACKED_SIGNAL(Signal* sig
       execLQHKEYCONF(signal);
       Tstep += LqhKeyConf::SignalLength;
       break;
+    case ZFIRE_TRIG_CONF:
+      jam();
+      signal->header.theLength = 4;
+      signal->theData[3] = TpackDataPtr[3];
+      execFIRE_TRIG_CONF(signal);
+      Tstep += 4;
+      break;
     default:
       systemErrorLab(signal, __LINE__);
       return;
@@ -4126,7 +4170,8 @@ void Dbtc::execSIGNAL_DROPPED_REP(Signal
 
 void Dbtc::execLQHKEYCONF(Signal* signal) 
 {
-  const LqhKeyConf * const lqhKeyConf = (LqhKeyConf *)signal->getDataPtr();
+  const LqhKeyConf * lqhKeyConf = CAST_CONSTPTR(LqhKeyConf,
+                                                signal->getDataPtr());
 #ifdef UNUSED
   ndbout << "TC: Received LQHKEYCONF"
          << " transId1=" << lqhKeyConf-> transId1
@@ -4181,7 +4226,8 @@ void Dbtc::execLQHKEYCONF(Signal* signal
   UintR TapiConnectFilesize = capiConnectFilesize;
   UintR Ttrans1 = lqhKeyConf->transId1;
   UintR Ttrans2 = lqhKeyConf->transId2;
-  Uint32 noFired = lqhKeyConf->noFiredTriggers;
+  Uint32 noFired = LqhKeyConf::getFiredCount(lqhKeyConf->noFiredTriggers);
+  Uint32 deferred = LqhKeyConf::getDeferredBit(lqhKeyConf->noFiredTriggers);
 
   if (TapiConnectptrIndex >= TapiConnectFilesize) {
     TCKEY_abort(signal, 29);
@@ -4237,6 +4283,10 @@ void Dbtc::execLQHKEYCONF(Signal* signal
   regTcPtr->lastLqhCon = tlastLqhConnect;
   regTcPtr->lastLqhNodeId = refToNode(tlastLqhBlockref);
   regTcPtr->noFiredTriggers = noFired;
+  regTcPtr->m_special_op_flags |= (deferred) ?
+    TcConnectRecord::SOF_DEFERRED_TRIGGER : 0;
+  regApiPtr.p->m_flags |= (deferred) ?
+    ApiConnectRecord::TF_DEFERRED_TRIGGERS : 0;
 
   UintR Ttckeyrec = (UintR)regApiPtr.p->tckeyrec;
   UintR TclientData = regTcPtr->clientData;
@@ -4244,10 +4294,7 @@ void Dbtc::execLQHKEYCONF(Signal* signal
   Uint32 TopSimple = regTcPtr->opSimple;
   Uint32 Toperation = regTcPtr->operation;
   ConnectionState TapiConnectstate = regApiPtr.p->apiConnectstate;
-  if (Ttckeyrec > (ZTCOPCONF_SIZE - 2)) {
-    TCKEY_abort(signal, 30);
-    return;
-  }
+
   if (TapiConnectstate == CS_ABORTING) {
     warningReport(signal, 27);
     return;
@@ -4287,6 +4334,12 @@ void Dbtc::execLQHKEYCONF(Signal* signal
   } else {
     if (noFired == 0 && regTcPtr->triggeringOperation == RNIL) {
       jam();
+
+      if (Ttckeyrec > (ZTCOPCONF_SIZE - 2)) {
+        TCKEY_abort(signal, 30);
+        return;
+      }
+
       /*
        * Skip counting triggering operations the first round
        * since they will enter execLQHKEYCONF a second time
@@ -4400,7 +4453,8 @@ void Dbtc::execLQHKEYCONF(Signal* signal
   /**
    * And now decide what to do next
    */
-  if (regTcPtr->triggeringOperation != RNIL) {
+  if (regTcPtr->triggeringOperation != RNIL &&
+      !regApiPtr.p->isExecutingDeferredTriggers()) {
     jam();
     // This operation was created by a trigger execting operation
     // Restart it if we have executed all it's triggers
@@ -4408,15 +4462,7 @@ void Dbtc::execLQHKEYCONF(Signal* signal
 
     opPtr.i = regTcPtr->triggeringOperation;
     ptrCheckGuard(opPtr, ctcConnectFilesize, localTcConnectRecord);
-    opPtr.p->triggerExecutionCount--;
-    if (opPtr.p->triggerExecutionCount == 0) {
-      /*
-      We have completed current trigger execution
-      Continue triggering operation
-      */
-      jam();
-      continueTriggeringOp(signal, opPtr.p);
-    }
+    trigger_op_finished(signal, regApiPtr, opPtr.p);
   } else if (noFired == 0) {
     // This operation did not fire any triggers, finish operation
     jam();
@@ -4473,6 +4519,7 @@ Dbtc::lqhKeyConf_checkTransactionState(S
   UintR Tlqhkeyreqrec = regApiPtr.p->lqhkeyreqrec;
   int TnoOfOutStanding = Tlqhkeyreqrec - Tlqhkeyconfrec;
 
+  apiConnectptr = regApiPtr;
   switch (TapiConnectstate) {
   case CS_START_COMMITTING:
     if (TnoOfOutStanding == 0) {
@@ -4549,6 +4596,17 @@ Dbtc::lqhKeyConf_checkTransactionState(S
 /*---------------------------------------------------------------*/
     regApiPtr.p->tckeyrec = 0;
     return;
+  case CS_SEND_FIRE_TRIG_REQ:
+    return;
+  case CS_WAIT_FIRE_TRIG_REQ:
+    if (TnoOfOutStanding == 0 && regApiPtr.p->pendingTriggers == 0)
+    {
+      jam();
+      regApiPtr.p->apiConnectstate = CS_START_COMMITTING;
+      diverify010Lab(signal);
+      return;
+    }
+    return;
   default:
     TCKEY_abort(signal, 46);
     return;
@@ -4796,6 +4854,19 @@ void Dbtc::diverify010Lab(Signal* signal
     systemErrorLab(signal, __LINE__);
   }//if
 
+  if (tc_testbit(regApiPtr->m_flags, ApiConnectRecord::TF_DEFERRED_TRIGGERS))
+  {
+    jam();
+    /**
+     * If trans has deferred triggers, let them fire just before
+     *   transaction starts to commit
+     */
+    regApiPtr->pendingTriggers = 0;
+    tc_clearbit(regApiPtr->m_flags, ApiConnectRecord::TF_DEFERRED_TRIGGERS);
+    sendFireTrigReq(signal, apiConnectptr, regApiPtr->firstTcConnect);
+    return;
+  }
+
   if (regApiPtr->lqhkeyreqrec)
   {
     if (TfirstfreeApiConnectCopy != RNIL) {
@@ -5580,6 +5651,237 @@ Dbtc::sendCompleteLqh(Signal* signal,
 }
 
 void
+Dbtc::sendFireTrigReq(Signal* signal,
+                      Ptr<ApiConnectRecord> regApiPtr,
+                      Uint32 TopPtrI)
+{
+  UintR TtcConnectFilesize = ctcConnectFilesize;
+  TcConnectRecord *localTcConnectRecord = tcConnectRecord;
+  TcConnectRecordPtr localTcConnectptr;
+
+  setApiConTimer(regApiPtr.i, ctcTimer, __LINE__);
+  regApiPtr.p->apiConnectstate = CS_SEND_FIRE_TRIG_REQ;
+
+  localTcConnectptr.i = TopPtrI;
+  ndbassert(TopPtrI != RNIL);
+  Uint32 Tlqhkeyreqrec = regApiPtr.p->lqhkeyreqrec;
+  Uint32 pass = regApiPtr.p->m_pre_commit_pass;
+  for (Uint32 i = 0; localTcConnectptr.i != RNIL && i < 16; i++)
+  {
+    ptrCheckGuard(localTcConnectptr,
+                  TtcConnectFilesize, localTcConnectRecord);
+
+    const Uint32 nextTcConnect = localTcConnectptr.p->nextTcConnect;
+    Uint32 flags = localTcConnectptr.p->m_special_op_flags;
+    if (flags & TcConnectRecord::SOF_DEFERRED_TRIGGER)
+    {
+      jam();
+      tc_clearbit(flags, TcConnectRecord::SOF_DEFERRED_TRIGGER);
+      ndbrequire(localTcConnectptr.p->tcConnectstate == OS_PREPARED);
+      localTcConnectptr.p->tcConnectstate = OS_FIRE_TRIG_REQ;
+      localTcConnectptr.p->m_special_op_flags = flags;
+      i += sendFireTrigReqLqh(signal, localTcConnectptr, pass);
+      Tlqhkeyreqrec++;
+    }
+    localTcConnectptr.i = nextTcConnect;
+  }
+
+  regApiPtr.p->lqhkeyreqrec = Tlqhkeyreqrec;
+  if (localTcConnectptr.i == RNIL)
+  {
+    /**
+     * Now wait for FIRE_TRIG_CONF
+     */
+    jam();
+    regApiPtr.p->apiConnectstate = CS_WAIT_FIRE_TRIG_REQ;
+    ndbrequire(pass < 255);
+    regApiPtr.p->m_pre_commit_pass = (Uint8)(pass + 1);
+    return;
+  }
+  else
+  {
+    jam();
+    signal->theData[0] = TcContinueB::ZSEND_FIRE_TRIG_REQ;
+    signal->theData[1] = regApiPtr.i;
+    signal->theData[2] = regApiPtr.p->transid[0];
+    signal->theData[3] = regApiPtr.p->transid[1];
+    signal->theData[4] = localTcConnectptr.i;
+    if (ERROR_INSERTED_CLEAR(8090))
+    {
+      sendSignalWithDelay(cownref, GSN_CONTINUEB, signal, 5000, 5);
+    }
+    else
+    {
+      sendSignal(cownref, GSN_CONTINUEB, signal, 5, JBB);
+    }
+  }
+}
+
+Uint32
+Dbtc::sendFireTrigReqLqh(Signal* signal,
+                         Ptr<TcConnectRecord> regTcPtr,
+                         Uint32 pass)
+{
+  HostRecordPtr Thostptr;
+  UintR ThostFilesize = chostFilesize;
+  ApiConnectRecord * const regApiPtr = apiConnectptr.p;
+  Thostptr.i = regTcPtr.p->tcNodedata[0];
+  ptrCheckGuard(Thostptr, ThostFilesize, hostRecord);
+
+  Uint32 Tnode = Thostptr.i;
+  Uint32 self = getOwnNodeId();
+  Uint32 ret = (Tnode == self) ? 4 : 1;
+
+  Uint32 Tdata[FireTrigReq::SignalLength];
+  FireTrigReq * req = CAST_PTR(FireTrigReq, Tdata);
+  req->tcOpRec = regTcPtr.i;
+  req->transId[0] = regApiPtr->transid[0];
+  req->transId[1] = regApiPtr->transid[1];
+  req->pass = pass;
+  Uint32 len = FireTrigReq::SignalLength;
+
+  // currently packed signal cannot address specific instance
+  const bool send_unpacked = getNodeInfo(Thostptr.i).m_lqh_workers > 1;
+  if (send_unpacked) {
+    memcpy(signal->theData, Tdata, len << 2);
+    Uint32 instanceKey = regTcPtr.p->lqhInstanceKey;
+    BlockReference lqhRef = numberToRef(DBLQH, instanceKey, Tnode);
+    sendSignal(lqhRef, GSN_FIRE_TRIG_REQ, signal, len, JBB);
+    return ret;
+  }
+
+  if (Thostptr.p->noOfPackedWordsLqh > 25 - len) {
+    jam();
+    sendPackedSignalLqh(signal, Thostptr.p);
+  } else {
+    jam();
+    ret = 1;
+    updatePackedList(signal, Thostptr.p, Thostptr.i);
+  }
+
+  Tdata[0] |= (ZFIRE_TRIG_REQ << 28);
+  UintR Tindex = Thostptr.p->noOfPackedWordsLqh;
+  UintR* TDataPtr = &Thostptr.p->packedWordsLqh[Tindex];
+  memcpy(TDataPtr, Tdata, len << 2);
+  Thostptr.p->noOfPackedWordsLqh = Tindex + len;
+  return ret;
+}
+
+void
+Dbtc::execFIRE_TRIG_CONF(Signal* signal)
+{
+  TcConnectRecordPtr localTcConnectptr;
+  ApiConnectRecordPtr regApiPtr;
+
+  UintR TtcConnectFilesize = ctcConnectFilesize;
+  UintR TapiConnectFilesize = capiConnectFilesize;
+  TcConnectRecord *localTcConnectRecord = tcConnectRecord;
+  ApiConnectRecord *localApiConnectRecord = apiConnectRecord;
+
+  const FireTrigConf * conf = CAST_CONSTPTR(FireTrigConf, signal->theData);
+  localTcConnectptr.i = conf->tcOpRec;
+  jamEntry();
+  ptrCheckGuard(localTcConnectptr, TtcConnectFilesize, localTcConnectRecord);
+  regApiPtr.i = localTcConnectptr.p->apiConnect;
+  if (localTcConnectptr.p->tcConnectstate != OS_FIRE_TRIG_REQ)
+  {
+    warningReport(signal, 28);
+    return;
+  }//if
+  ptrCheckGuard(regApiPtr, TapiConnectFilesize,
+                localApiConnectRecord);
+
+  Uint32 Tlqhkeyreqrec = regApiPtr.p->lqhkeyreqrec;
+  Uint32 TapiConnectstate = regApiPtr.p->apiConnectstate;
+  UintR Tdata1 = regApiPtr.p->transid[0] - conf->transId[0];
+  UintR Tdata2 = regApiPtr.p->transid[1] - conf->transId[1];
+  Uint32 TcheckCondition =
+    (TapiConnectstate != CS_SEND_FIRE_TRIG_REQ) &&
+    (TapiConnectstate != CS_WAIT_FIRE_TRIG_REQ);
+
+  Tdata1 = Tdata1 | Tdata2 | TcheckCondition;
+
+  if (Tdata1 != 0) {
+    warningReport(signal, 28);
+    return;
+  }//if
+
+  if (ERROR_INSERTED_CLEAR(8091))
+  {
+    jam();
+    return;
+  }
+
+  CRASH_INSERTION(8092);
+
+  setApiConTimer(regApiPtr.i, ctcTimer, __LINE__);
+  ndbassert(Tlqhkeyreqrec > 0);
+  regApiPtr.p->lqhkeyreqrec = Tlqhkeyreqrec - 1;
+  localTcConnectptr.p->tcConnectstate = OS_PREPARED;
+
+  Uint32 noFired  = FireTrigConf::getFiredCount(conf->noFiredTriggers);
+  Uint32 deferred = FireTrigConf::getDeferredBit(conf->noFiredTriggers);
+
+  regApiPtr.p->pendingTriggers += noFired;
+  regApiPtr.p->m_flags |= (deferred) ?
+    ApiConnectRecord::TF_DEFERRED_TRIGGERS : 0;
+  localTcConnectptr.p->m_special_op_flags |= (deferred) ?
+    TcConnectRecord::SOF_DEFERRED_TRIGGER : 0;
+
+  if (regApiPtr.p->pendingTriggers == 0)
+  {
+    jam();
+    lqhKeyConf_checkTransactionState(signal, regApiPtr);
+  }
+}
+
+void
+Dbtc::execFIRE_TRIG_REF(Signal* signal)
+{
+  TcConnectRecordPtr localTcConnectptr;
+  ApiConnectRecordPtr regApiPtr;
+
+  UintR TtcConnectFilesize = ctcConnectFilesize;
+  UintR TapiConnectFilesize = capiConnectFilesize;
+  TcConnectRecord *localTcConnectRecord = tcConnectRecord;
+  ApiConnectRecord *localApiConnectRecord = apiConnectRecord;
+
+  const FireTrigRef * ref = CAST_CONSTPTR(FireTrigRef, signal->theData);
+  localTcConnectptr.i = ref->tcOpRec;
+  jamEntry();
+  ptrCheckGuard(localTcConnectptr, TtcConnectFilesize, localTcConnectRecord);
+  regApiPtr.i = localTcConnectptr.p->apiConnect;
+  if (localTcConnectptr.p->tcConnectstate != OS_FIRE_TRIG_REQ)
+  {
+    warningReport(signal, 28);
+    return;
+  }//if
+  ptrCheckGuard(regApiPtr, TapiConnectFilesize,
+                localApiConnectRecord);
+
+  apiConnectptr = regApiPtr;
+
+  UintR Tdata1 = regApiPtr.p->transid[0] - ref->transId[0];
+  UintR Tdata2 = regApiPtr.p->transid[1] - ref->transId[1];
+  Tdata1 = Tdata1 | Tdata2;
+  if (Tdata1 != 0) {
+    warningReport(signal, 28);
+    return;
+  }//if
+
+  if (regApiPtr.p->apiConnectstate != CS_SEND_FIRE_TRIG_REQ &&
+      regApiPtr.p->apiConnectstate != CS_WAIT_FIRE_TRIG_REQ)
+  {
+    jam();
+    warningReport(signal, 28);
+    return;
+  }
+
+  terrorCode = ref->errCode;
+  abortErrorLab(signal);
+}
+
+void
 Dbtc::execTC_COMMIT_ACK(Signal* signal){
   jamEntry();
 
@@ -5963,19 +6265,16 @@ void Dbtc::execLQHKEYREF(Signal* signal)
          */
         regApiPtr->lqhkeyreqrec--;
 
+        /**
+         * An failing op in LQH, never leaves the commit ack marker around
+         * TODO: This can be bug in ordinary code too!!!
+         */
+        clearCommitAckMarker(regApiPtr, regTcPtr);
+
         unlinkReadyTcCon(signal);
         releaseTcCon();
 
-        opPtr.p->triggerExecutionCount--;
-        if (opPtr.p->triggerExecutionCount == 0)
-        {
-          /**
-           * We have completed current trigger execution
-           * Continue triggering operation
-           */
-          jam();
-          continueTriggeringOp(signal, opPtr.p);
-        }
+        trigger_op_finished(signal, apiConnectptr, opPtr.p);
         return;
       }
       
@@ -6566,6 +6865,18 @@ void Dbtc::warningReport(Signal* signal,
     ndbout << "Received LQHKEYCONF in wrong api-state in Dbtc" << endl;
 #endif
     break;
+  case 28:
+    jam();
+#ifdef ABORT_TRACE
+    ndbout << "Discarding FIRE_TRIG_REF/CONF in Dbtc" << endl;
+#endif
+    break;
+  case 29:
+    jam();
+#ifdef ABORT_TRACE
+    ndbout << "Discarding TcContinueB::ZSEND_FIRE_TRIG_REQ in Dbtc" << endl;
+#endif
+    break;
   default:
     jam();
     break;
@@ -6816,6 +7127,8 @@ ABORT020:
     jam();
   case OS_OPERATING:
     jam();
+  case OS_FIRE_TRIG_REQ:
+    jam();
     /*----------------------------------------------------------------------
      * WE HAVE SENT LQHKEYREQ AND ARE IN SOME STATE OF EITHER STILL       
      * SENDING THE OPERATION, WAITING FOR REPLIES, WAITING FOR MORE       
@@ -7161,6 +7474,8 @@ void Dbtc::timeOutFoundLab(Signal* signa
   case CS_RECEIVING:
   case CS_REC_COMMITTING:
   case CS_START_COMMITTING:
+  case CS_WAIT_FIRE_TRIG_REQ:
+  case CS_SEND_FIRE_TRIG_REQ:
     jam();
     /*------------------------------------------------------------------*/
     /*       WE ARE STILL IN THE PREPARE PHASE AND THE TRANSACTION HAS  */
@@ -8085,6 +8400,28 @@ void Dbtc::execNODE_FAILREP(Signal* sign
                   myHostPtr.i};
     simBlockNodeFailure(signal, myHostPtr.i, cb);
   }
+
+  if (m_deferred_enabled == 0)
+  {
+    jam();
+    Uint32 ok = 1;
+    for(Uint32 n = c_alive_nodes.find_first();
+        n != c_alive_nodes.NotFound;
+        n = c_alive_nodes.find_next(n))
+    {
+      if (!ndbd_deferred_unique_constraints(getNodeInfo(n).m_version))
+      {
+        jam();
+        ok = 0;
+        break;
+      }
+    }
+    if (ok)
+    {
+      jam();
+      m_deferred_enabled = ~Uint32(0);
+    }
+  }
 }//Dbtc::execNODE_FAILREP()
 
 void
@@ -13463,11 +13800,12 @@ void Dbtc::execFIRE_TRIG_ORD(Signal* sig
     {
       jam();      
       opPtr.p->noReceivedTriggers++;
-      opPtr.p->triggerExecutionCount++;
+      opPtr.p->triggerExecutionCount++; // Default 1 LQHKEYREQ per trigger
 
       // Insert fired trigger in execution queue
       transPtr.p->theFiredTriggers.add(trigPtr);
-      if (opPtr.p->noReceivedTriggers == opPtr.p->noFiredTriggers) {
+      if (opPtr.p->noReceivedTriggers == opPtr.p->noFiredTriggers ||
+          transPtr.p->isExecutingDeferredTriggers()) {
 	executeTriggers(signal, &transPtr);
       }
       return;
@@ -14783,6 +15121,31 @@ void Dbtc::saveTriggeringOpState(Signal*
                 LqhKeyConf::SignalLength);  
 }
 
+void
+Dbtc::trigger_op_finished(Signal* signal, ApiConnectRecordPtr regApiPtr,
+                          TcConnectRecord* triggeringOp)
+{
+  if (!regApiPtr.p->isExecutingDeferredTriggers())
+  {
+    ndbassert(triggeringOp->triggerExecutionCount > 0);
+    triggeringOp->triggerExecutionCount--;
+    if (triggeringOp->triggerExecutionCount == 0)
+    {
+      /**
+       * We have completed current trigger execution
+       * Continue triggering operation
+       */
+      jam();
+      continueTriggeringOp(signal, triggeringOp);
+    }
+  }
+  else
+  {
+    jam();
+    lqhKeyConf_checkTransactionState(signal, regApiPtr);
+  }
+}
+
 void Dbtc::continueTriggeringOp(Signal* signal, TcConnectRecord* trigOp)
 {
   LqhKeyConf * lqhKeyConf = (LqhKeyConf *)signal->getDataPtr();
@@ -14790,6 +15153,9 @@ void Dbtc::continueTriggeringOp(Signal*
                 (UintR*)lqhKeyConf,
 		LqhKeyConf::SignalLength);
 
+  ndbassert(trigOp->savedState[LqhKeyConf::SignalLength-1] != ~Uint32(0));
+  trigOp->savedState[LqhKeyConf::SignalLength-1] = ~Uint32(0);
+
   lqhKeyConf->noFiredTriggers = 0;
   trigOp->noReceivedTriggers = 0;
 
@@ -14797,18 +15163,6 @@ void Dbtc::continueTriggeringOp(Signal*
   execLQHKEYCONF(signal);
 }
 
-void Dbtc::scheduleFiredTrigger(ApiConnectRecordPtr* transPtr,
-                                TcConnectRecordPtr* opPtr)
-{
-  // Set initial values for trigger fireing operation
-  opPtr->p->triggerExecutionCount++;
-
-  // Insert fired trigger in execution queue
-  transPtr->p->theFiredTriggers.add(opPtr->p->accumulatingTriggerData);
-  opPtr->p->accumulatingTriggerData.i = RNIL;
-  opPtr->p->accumulatingTriggerData.p = NULL;
-}
-
 void Dbtc::executeTriggers(Signal* signal, ApiConnectRecordPtr* transPtr)
 {
   ApiConnectRecord* regApiPtr = transPtr->p;
@@ -14819,7 +15173,10 @@ void Dbtc::executeTriggers(Signal* signa
   if (!regApiPtr->theFiredTriggers.isEmpty()) {
     jam();
     if ((regApiPtr->apiConnectstate == CS_STARTED) ||
-        (regApiPtr->apiConnectstate == CS_START_COMMITTING)) {
+        (regApiPtr->apiConnectstate == CS_START_COMMITTING) ||
+        (regApiPtr->apiConnectstate == CS_SEND_FIRE_TRIG_REQ) ||
+        (regApiPtr->apiConnectstate == CS_WAIT_FIRE_TRIG_REQ))
+    {
       jam();
       regApiPtr->theFiredTriggers.first(trigPtr);
       while (trigPtr.i != RNIL) {
@@ -14829,7 +15186,8 @@ void Dbtc::executeTriggers(Signal* signa
         ptrCheckGuard(opPtr, ctcConnectFilesize, localTcConnectRecord);
 	FiredTriggerPtr nextTrigPtr = trigPtr;
 	regApiPtr->theFiredTriggers.next(nextTrigPtr);
-        if (opPtr.p->noReceivedTriggers == opPtr.p->noFiredTriggers) {
+        if (opPtr.p->noReceivedTriggers == opPtr.p->noFiredTriggers ||
+            regApiPtr->isExecutingDeferredTriggers()) {
           jam();
           // Fireing operation is ready to have a trigger executing
           executeTrigger(signal, trigPtr.p, transPtr, &opPtr);
@@ -14898,6 +15256,7 @@ void Dbtc::executeTrigger(Signal* signal
        c_theDefinedTriggers.getPtr(firedTriggerData->triggerId)) 
       != NULL)
   {
+    transPtr->p->pendingTriggers--;
     switch(firedTriggerData->triggerType) {
     case(TriggerType::SECONDARY_INDEX):
       jam();
@@ -14937,8 +15296,8 @@ void Dbtc::executeIndexTrigger(Signal* s
   }
   case(TriggerEvent::TE_UPDATE): {
     jam();
-    deleteFromIndexTable(signal, firedTriggerData, transPtr, opPtr, 
-			 indexData, true); // Hold the triggering operation
+    opPtr->p->triggerExecutionCount++; // One is already added...and this is 2
+    deleteFromIndexTable(signal, firedTriggerData, transPtr, opPtr, indexData);
     insertIntoIndexTable(signal, firedTriggerData, transPtr, opPtr, indexData);
     break;
   }
@@ -15061,8 +15420,7 @@ void Dbtc::insertIntoIndexTable(Signal*
                                 TcFiredTriggerData* firedTriggerData, 
                                 ApiConnectRecordPtr* transPtr,
                                 TcConnectRecordPtr* opPtr,
-                                TcIndexData* indexData,
-                                bool holdOperation)
+                                TcIndexData* indexData)
 {
   ApiConnectRecord* regApiPtr = transPtr->p;
   TcConnectRecord* opRecord = opPtr->p;
@@ -15076,10 +15434,6 @@ void Dbtc::insertIntoIndexTable(Signal*
   ptrCheckGuard(indexTabPtr, ctabrecFilesize, tableRecord);
   tcKeyReq->apiConnectPtr = transPtr->i;
   tcKeyReq->senderData = opPtr->i;
-  if (holdOperation) {
-    jam();
-    opRecord->triggerExecutionCount++;
-  }//if
 
   /* Key for insert to unique index table is the afterValues from the
    * base table operation (from update or insert on base).
@@ -15092,6 +15446,15 @@ void Dbtc::insertIntoIndexTable(Signal*
   LocalDataBuffer<11> afterValues(pool, firedTriggerData->afterValues);
   LocalDataBuffer<11> keyValues(pool, firedTriggerData->keyValues);
 
+  if (afterValues.getSize() == 0)
+  {
+    jam();
+    ndbrequire(tc_testbit(regApiPtr->m_flags,
+                          ApiConnectRecord::TF_DEFERRED_CONSTRAINTS));
+    trigger_op_finished(signal, *transPtr, opRecord);
+    return;
+  }
+
   Uint32 keyIVal= RNIL;
   Uint32 attrIVal= RNIL;
   bool appendOk= false;
@@ -15124,15 +15487,7 @@ void Dbtc::insertIntoIndexTable(Signal*
     {
       jam();
       releaseSection(keyIVal);
-      opRecord->triggerExecutionCount--;
-      if (opRecord->triggerExecutionCount == 0) {
-        /*
-          We have completed current trigger execution
-          Continue triggering operation
-        */
-        jam();
-        continueTriggeringOp(signal, opRecord);	
-      }//if
+      trigger_op_finished(signal, *transPtr, opRecord);
       return;
     }
     
@@ -15226,8 +15581,7 @@ void Dbtc::deleteFromIndexTable(Signal*
                                 TcFiredTriggerData* firedTriggerData, 
                                 ApiConnectRecordPtr* transPtr,
                                 TcConnectRecordPtr* opPtr,
-                                TcIndexData* indexData,
-                                bool holdOperation)
+                                TcIndexData* indexData)
 {
   ApiConnectRecord* regApiPtr = transPtr->p;
   TcConnectRecord* opRecord = opPtr->p;
@@ -15239,10 +15593,7 @@ void Dbtc::deleteFromIndexTable(Signal*
   ptrCheckGuard(indexTabPtr, ctabrecFilesize, tableRecord);
   tcKeyReq->apiConnectPtr = transPtr->i;
   tcKeyReq->senderData = opPtr->i;
-  if (holdOperation) {
-    jam();
-    opRecord->triggerExecutionCount++;
-  }//if
+
   // Calculate key length and renumber attribute id:s
   AttributeBuffer::DataBufferPool & pool = c_theAttributeBufferPool;
   LocalDataBuffer<11> beforeValues(pool, firedTriggerData->beforeValues);
@@ -15250,7 +15601,16 @@ void Dbtc::deleteFromIndexTable(Signal*
   Uint32 keyIVal= RNIL;
   Uint32 attrId= 0;
   bool hasNull= false;
-  
+
+  if (beforeValues.getSize() == 0)
+  {
+    jam();
+    ndbrequire(tc_testbit(regApiPtr->m_flags,
+                          ApiConnectRecord::TF_DEFERRED_CONSTRAINTS));
+    trigger_op_finished(signal, *transPtr, opRecord);
+    return;
+  }
+
   /* Build Delete KeyInfo section from beforevalues */
   if (unlikely((! appendAttrDataToSection(keyIVal,
                                           beforeValues,
@@ -15272,15 +15632,7 @@ void Dbtc::deleteFromIndexTable(Signal*
   {
     jam();
     releaseSection(keyIVal);
-    opRecord->triggerExecutionCount--;
-    if (opRecord->triggerExecutionCount == 0) {
-      /*
-        We have completed current trigger execution
-        Continue triggering operation
-      */
-      jam();
-      continueTriggeringOp(signal, opRecord);	
-    }//if
+    trigger_op_finished(signal, *transPtr, opRecord);
     return;
   }
 

=== added file 'storage/ndb/src/kernel/blocks/dbtc/DbtcProxy.cpp'
--- a/storage/ndb/src/kernel/blocks/dbtc/DbtcProxy.cpp	1970-01-01 00:00:00 +0000
+++ b/storage/ndb/src/kernel/blocks/dbtc/DbtcProxy.cpp	2011-04-27 10:48:16 +0000
@@ -0,0 +1,925 @@
+/*
+   Copyright (c) 2011, 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 Foundation; version 2 of the License.
+
+   This program is distributed in the hope that it will be useful,
+   but WITHOUT ANY WARRANTY; without even the implied warranty of
+   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+   GNU General Public License for more details.
+
+   You should have received a copy of the GNU General Public License
+   along with this program; if not, write to the Free Software
+   Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301  USA
+*/
+
+#include "DbtcProxy.hpp"
+#include "Dbtc.hpp"
+
+DbtcProxy::DbtcProxy(Block_context& ctx) :
+  LocalProxy(DBTC, ctx)
+{
+  // GSN_TC_SCHVERREQ
+  addRecSignal(GSN_TC_SCHVERREQ, &DbtcProxy::execTC_SCHVERREQ);
+  addRecSignal(GSN_TC_SCHVERCONF, &DbtcProxy::execTC_SCHVERCONF);
+
+  // GSN_TAB_COMMITREQ
+  addRecSignal(GSN_TAB_COMMITREQ, &DbtcProxy::execTAB_COMMITREQ);
+  addRecSignal(GSN_TAB_COMMITCONF, &DbtcProxy::execTAB_COMMITCONF);
+  addRecSignal(GSN_TAB_COMMITREF, &DbtcProxy::execTAB_COMMITREF);
+
+  // GSN_TCSEIZEREQ
+  addRecSignal(GSN_TCSEIZEREQ, &DbtcProxy::execTCSEIZEREQ);
+
+  // GSN_TCGETOPSIZEREQ
+  addRecSignal(GSN_TCGETOPSIZEREQ, &DbtcProxy::execTCGETOPSIZEREQ);
+  addRecSignal(GSN_TCGETOPSIZECONF, &DbtcProxy::execTCGETOPSIZECONF);
+
+  // GSN_TCGETOPSIZEREQ
+  addRecSignal(GSN_TC_CLOPSIZEREQ, &DbtcProxy::execTC_CLOPSIZEREQ);
+  addRecSignal(GSN_TC_CLOPSIZECONF, &DbtcProxy::execTC_CLOPSIZECONF);
+
+  // GSN_GCP_NOMORETRANS
+  addRecSignal(GSN_GCP_NOMORETRANS, &DbtcProxy::execGCP_NOMORETRANS);
+  addRecSignal(GSN_GCP_TCFINISHED, &DbtcProxy::execGCP_TCFINISHED);
+
+  // GSN_API_FAILREQ
+  addRecSignal(GSN_API_FAILREQ, &DbtcProxy::execAPI_FAILREQ);
+  addRecSignal(GSN_API_FAILCONF, &DbtcProxy::execAPI_FAILCONF);
+
+  // GSN_PREP_DROP_TAB_REQ
+  addRecSignal(GSN_PREP_DROP_TAB_REQ, &DbtcProxy::execPREP_DROP_TAB_REQ);
+  addRecSignal(GSN_PREP_DROP_TAB_CONF, &DbtcProxy::execPREP_DROP_TAB_CONF);
+  addRecSignal(GSN_PREP_DROP_TAB_REF, &DbtcProxy::execPREP_DROP_TAB_REF);
+
+  // GSN_DROP_TAB_REQ
+  addRecSignal(GSN_DROP_TAB_REQ, &DbtcProxy::execDROP_TAB_REQ);
+  addRecSignal(GSN_DROP_TAB_CONF, &DbtcProxy::execDROP_TAB_CONF);
+  addRecSignal(GSN_DROP_TAB_REF, &DbtcProxy::execDROP_TAB_REF);
+
+  // GSN_ALTER_TAB_REQ
+  addRecSignal(GSN_ALTER_TAB_REQ, &DbtcProxy::execALTER_TAB_REQ);
+  addRecSignal(GSN_ALTER_TAB_CONF, &DbtcProxy::execALTER_TAB_CONF);
+  addRecSignal(GSN_ALTER_TAB_REF, &DbtcProxy::execALTER_TAB_REF);
+
+  // GSN_CREATE_INDX_IMPL_REQ
+  addRecSignal(GSN_CREATE_INDX_IMPL_REQ, &DbtcProxy::execCREATE_INDX_IMPL_REQ);
+  addRecSignal(GSN_CREATE_INDX_IMPL_CONF,&DbtcProxy::execCREATE_INDX_IMPL_CONF);
+  addRecSignal(GSN_CREATE_INDX_IMPL_REF, &DbtcProxy::execCREATE_INDX_IMPL_REF);
+
+  // GSN_ALTER_INDX_IMPL_REQ
+  addRecSignal(GSN_ALTER_INDX_IMPL_REQ, &DbtcProxy::execALTER_INDX_IMPL_REQ);
+  addRecSignal(GSN_ALTER_INDX_IMPL_CONF,&DbtcProxy::execALTER_INDX_IMPL_CONF);
+  addRecSignal(GSN_ALTER_INDX_IMPL_REF, &DbtcProxy::execALTER_INDX_IMPL_REF);
+
+  // GSN_DROP_INDX_IMPL_REQ
+  addRecSignal(GSN_DROP_INDX_IMPL_REQ, &DbtcProxy::execDROP_INDX_IMPL_REQ);
+  addRecSignal(GSN_DROP_INDX_IMPL_CONF,&DbtcProxy::execDROP_INDX_IMPL_CONF);
+  addRecSignal(GSN_DROP_INDX_IMPL_REF, &DbtcProxy::execDROP_INDX_IMPL_REF);
+
+  m_tc_seize_req_instance = 0;
+}
+
+DbtcProxy::~DbtcProxy()
+{
+}
+
+SimulatedBlock*
+DbtcProxy::newWorker(Uint32 instanceNo)
+{
+  return new Dbtc(m_ctx, instanceNo);
+}
+
+// GSN_NDB_STTOR
+
+void
+DbtcProxy::callNDB_STTOR(Signal* signal)
+{
+  Ss_READ_NODES_REQ& ss = c_ss_READ_NODESREQ;
+  ndbrequire(ss.m_gsn == 0);
+
+  const Uint32 startPhase = signal->theData[2];
+  switch (startPhase) {
+  case 3:
+    ss.m_gsn = GSN_NDB_STTOR;
+    sendREAD_NODESREQ(signal);
+    break;
+  default:
+    backNDB_STTOR(signal);
+    break;
+  }
+}
+
+// GSN_TC_SCHVERREQ
+
+void
+DbtcProxy::execTC_SCHVERREQ(Signal* signal)
+{
+  Ss_TC_SCHVERREQ& ss = ssSeize<Ss_TC_SCHVERREQ>(1);
+
+  const TcSchVerReq* req = (const TcSchVerReq*)signal->getDataPtr();
+  ss.m_req = *req;
+
+  sendREQ(signal, ss);
+}
+
+void
+DbtcProxy::sendTC_SCHVERREQ(Signal* signal, Uint32 ssId, SectionHandle*)
+{
+  Ss_TC_SCHVERREQ& ss = ssFind<Ss_TC_SCHVERREQ>(ssId);
+
+  TcSchVerReq* req = (TcSchVerReq*)signal->getDataPtrSend();
+  *req = ss.m_req;
+  req->senderRef = reference();
+  req->senderData = ssId;
+  sendSignal(workerRef(ss.m_worker), GSN_TC_SCHVERREQ,
+             signal, TcSchVerReq::SignalLength, JBB);
+}
+
+void
+DbtcProxy::execTC_SCHVERCONF(Signal* signal)
+{
+  const TcSchVerConf* conf = (const TcSchVerConf*)signal->getDataPtr();
+  Uint32 ssId = conf->senderData;
+  Ss_TC_SCHVERREQ& ss = ssFind<Ss_TC_SCHVERREQ>(ssId);
+  recvCONF(signal, ss);
+}
+
+void
+DbtcProxy::sendTC_SCHVERCONF(Signal* signal, Uint32 ssId)
+{
+  Ss_TC_SCHVERREQ& ss = ssFind<Ss_TC_SCHVERREQ>(ssId);
+  BlockReference dictRef = ss.m_req.senderRef;
+
+  if (!lastReply(ss))
+    return;
+
+  TcSchVerConf* conf = (TcSchVerConf*)signal->getDataPtrSend();
+  conf->senderRef = reference();
+  conf->senderData = ss.m_req.senderData;
+  sendSignal(dictRef, GSN_TC_SCHVERCONF,
+             signal, TcSchVerConf::SignalLength, JBB);
+
+  ssRelease<Ss_TC_SCHVERREQ>(ssId);
+}
+
+// GSN_TAB_COMMITREQ [ sub-op ]
+
+void
+DbtcProxy::execTAB_COMMITREQ(Signal* signal)
+{
+  Ss_TAB_COMMITREQ& ss = ssSeize<Ss_TAB_COMMITREQ>(1); // lost connection
+
+  const TabCommitReq* req = (const TabCommitReq*)signal->getDataPtr();
+  ss.m_req = *req;
+  sendREQ(signal, ss);
+}
+
+void
+DbtcProxy::sendTAB_COMMITREQ(Signal* signal, Uint32 ssId, SectionHandle*)
+{
+  Ss_TAB_COMMITREQ& ss = ssFind<Ss_TAB_COMMITREQ>(ssId);
+
+  TabCommitReq* req = (TabCommitReq*)signal->getDataPtrSend();
+  req->senderRef = reference();
+  req->senderData = ssId;
+  req->tableId = ss.m_req.tableId;
+  sendSignal(workerRef(ss.m_worker), GSN_TAB_COMMITREQ,
+             signal, TabCommitReq::SignalLength, JBB);
+}
+
+void
+DbtcProxy::execTAB_COMMITCONF(Signal* signal)
+{
+  const TabCommitConf* conf = (TabCommitConf*)signal->getDataPtr();
+  Uint32 ssId = conf->senderData;
+  Ss_TAB_COMMITREQ& ss = ssFind<Ss_TAB_COMMITREQ>(ssId);
+  recvCONF(signal, ss);
+}
+
+void
+DbtcProxy::execTAB_COMMITREF(Signal* signal)
+{
+  const TabCommitRef* ref = (TabCommitRef*)signal->getDataPtr();
+  Uint32 ssId = ref->senderData;
+  Ss_TAB_COMMITREQ& ss = ssFind<Ss_TAB_COMMITREQ>(ssId);
+
+  recvREF(signal, ss, ref->errorCode);
+}
+
+void
+DbtcProxy::sendTAB_COMMITCONF(Signal* signal, Uint32 ssId)
+{
+  Ss_TAB_COMMITREQ& ss = ssFind<Ss_TAB_COMMITREQ>(ssId);
+  BlockReference dictRef = ss.m_req.senderRef;
+
+  if (!lastReply(ss))
+    return;
+
+  if (ss.m_error == 0) {
+    jam();
+    TabCommitConf* conf = (TabCommitConf*)signal->getDataPtrSend();
+    conf->senderData = ss.m_req.senderData;
+    conf->nodeId = getOwnNodeId();
+    conf->tableId = ss.m_req.tableId;
+    sendSignal(dictRef, GSN_TAB_COMMITCONF,
+               signal, TabCommitConf::SignalLength, JBB);
+  } else {
+    jam();
+    TabCommitRef* ref = (TabCommitRef*)signal->getDataPtrSend();
+    ref->senderData = ss.m_req.senderData;
+    ref->nodeId = getOwnNodeId();
+    ref->tableId = ss.m_req.tableId;
+    sendSignal(dictRef, GSN_TAB_COMMITREF,
+               signal, TabCommitRef::SignalLength, JBB);
+    return;
+  }
+
+  ssRelease<Ss_TAB_COMMITREQ>(ssId);
+}
+
+// GSN_PREP_DROP_TAB_REQ
+
+void
+DbtcProxy::execPREP_DROP_TAB_REQ(Signal* signal)
+{
+  const PrepDropTabReq* req = (const PrepDropTabReq*)signal->getDataPtr();
+  Uint32 ssId = getSsId(req);
+  Ss_PREP_DROP_TAB_REQ& ss = ssSeize<Ss_PREP_DROP_TAB_REQ>(ssId);
+  ss.m_req = *req;
+  ndbrequire(signal->getLength() == PrepDropTabReq::SignalLength);
+  sendREQ(signal, ss);
+}
+
+void
+DbtcProxy::sendPREP_DROP_TAB_REQ(Signal* signal, Uint32 ssId, SectionHandle*)
+{
+  Ss_PREP_DROP_TAB_REQ& ss = ssFind<Ss_PREP_DROP_TAB_REQ>(ssId);
+
+  PrepDropTabReq* req = (PrepDropTabReq*)signal->getDataPtrSend();
+  *req = ss.m_req;
+  req->senderRef = reference();
+  req->senderData = ssId; // redundant since tableId is used
+  sendSignal(workerRef(ss.m_worker), GSN_PREP_DROP_TAB_REQ,
+             signal, PrepDropTabReq::SignalLength, JBB);
+}
+
+void
+DbtcProxy::execPREP_DROP_TAB_CONF(Signal* signal)
+{
+  const PrepDropTabConf* conf = (const PrepDropTabConf*)signal->getDataPtr();
+  Uint32 ssId = getSsId(conf);
+  Ss_PREP_DROP_TAB_REQ& ss = ssFind<Ss_PREP_DROP_TAB_REQ>(ssId);
+  recvCONF(signal, ss);
+}
+
+void
+DbtcProxy::execPREP_DROP_TAB_REF(Signal* signal)
+{
+  const PrepDropTabRef* ref = (const PrepDropTabRef*)signal->getDataPtr();
+  Uint32 ssId = getSsId(ref);
+  Ss_PREP_DROP_TAB_REQ& ss = ssFind<Ss_PREP_DROP_TAB_REQ>(ssId);
+  recvREF(signal, ss, ref->errorCode);
+}
+
+void
+DbtcProxy::sendPREP_DROP_TAB_CONF(Signal* signal, Uint32 ssId)
+{
+  Ss_PREP_DROP_TAB_REQ& ss = ssFind<Ss_PREP_DROP_TAB_REQ>(ssId);
+  BlockReference dictRef = ss.m_req.senderRef;
+
+  if (!lastReply(ss))
+    return;
+
+  if (ss.m_error == 0) {
+    jam();
+    PrepDropTabConf* conf = (PrepDropTabConf*)signal->getDataPtrSend();
+    conf->senderRef = reference();
+    conf->senderData = ss.m_req.senderData;
+    conf->tableId = ss.m_req.tableId;
+    sendSignal(dictRef, GSN_PREP_DROP_TAB_CONF,
+               signal, PrepDropTabConf::SignalLength, JBB);
+  } else {
+    jam();
+    PrepDropTabRef* ref = (PrepDropTabRef*)signal->getDataPtrSend();
+    ref->senderRef = reference();
+    ref->senderData = ss.m_req.senderData;
+    ref->tableId = ss.m_req.tableId;
+    ref->errorCode = ss.m_error;
+    sendSignal(dictRef, GSN_PREP_DROP_TAB_REF,
+               signal, PrepDropTabRef::SignalLength, JBB);
+  }
+
+  ssRelease<Ss_PREP_DROP_TAB_REQ>(ssId);
+}
+
+// GSN_DROP_TAB_REQ
+
+void
+DbtcProxy::execDROP_TAB_REQ(Signal* signal)
+{
+  const DropTabReq* req = (const DropTabReq*)signal->getDataPtr();
+  Uint32 ssId = getSsId(req);
+  Ss_DROP_TAB_REQ& ss = ssSeize<Ss_DROP_TAB_REQ>(ssId);
+  ss.m_req = *req;
+  ndbrequire(signal->getLength() == DropTabReq::SignalLength);
+  sendREQ(signal, ss);
+}
+
+void
+DbtcProxy::sendDROP_TAB_REQ(Signal* signal, Uint32 ssId, SectionHandle*)
+{
+  Ss_DROP_TAB_REQ& ss = ssFind<Ss_DROP_TAB_REQ>(ssId);
+
+  DropTabReq* req = (DropTabReq*)signal->getDataPtrSend();
+  *req = ss.m_req;
+  req->senderRef = reference();
+  req->senderData = ssId; // redundant since tableId is used
+  sendSignal(workerRef(ss.m_worker), GSN_DROP_TAB_REQ,
+             signal, DropTabReq::SignalLength, JBB);
+}
+
+void
+DbtcProxy::execDROP_TAB_CONF(Signal* signal)
+{
+  const DropTabConf* conf = (const DropTabConf*)signal->getDataPtr();
+  Uint32 ssId = getSsId(conf);
+  Ss_DROP_TAB_REQ& ss = ssFind<Ss_DROP_TAB_REQ>(ssId);
+  recvCONF(signal, ss);
+}
+
+void
+DbtcProxy::execDROP_TAB_REF(Signal* signal)
+{
+  const DropTabRef* ref = (const DropTabRef*)signal->getDataPtr();
+  Uint32 ssId = getSsId(ref);
+  Ss_DROP_TAB_REQ& ss = ssFind<Ss_DROP_TAB_REQ>(ssId);
+  recvREF(signal, ss, ref->errorCode);
+}
+
+void
+DbtcProxy::sendDROP_TAB_CONF(Signal* signal, Uint32 ssId)
+{
+  Ss_DROP_TAB_REQ& ss = ssFind<Ss_DROP_TAB_REQ>(ssId);
+  BlockReference dictRef = ss.m_req.senderRef;
+
+  if (!lastReply(ss))
+    return;
+
+  if (ss.m_error == 0) {
+    jam();
+    DropTabConf* conf = (DropTabConf*)signal->getDataPtrSend();
+    conf->senderRef = reference();
+    conf->senderData = ss.m_req.senderData;
+    conf->tableId = ss.m_req.tableId;
+    sendSignal(dictRef, GSN_DROP_TAB_CONF,
+               signal, DropTabConf::SignalLength, JBB);
+  } else {
+    jam();
+    DropTabRef* ref = (DropTabRef*)signal->getDataPtrSend();
+    ref->senderRef = reference();
+    ref->senderData = ss.m_req.senderData;
+    ref->tableId = ss.m_req.tableId;
+    ref->errorCode = ss.m_error;
+    sendSignal(dictRef, GSN_DROP_TAB_REF,
+               signal, DropTabConf::SignalLength, JBB);
+  }
+
+  ssRelease<Ss_DROP_TAB_REQ>(ssId);
+}
+
+// GSN_ALTER_TAB_REQ
+
+void
+DbtcProxy::execALTER_TAB_REQ(Signal* signal)
+{
+  if (!assembleFragments(signal))
+  {
+    jam();
+    return;
+  }
+
+  const AlterTabReq* req = (const AlterTabReq*)signal->getDataPtr();
+  Uint32 ssId = getSsId(req);
+  Ss_ALTER_TAB_REQ& ss = ssSeize<Ss_ALTER_TAB_REQ>(ssId);
+  ss.m_req = *req;
+
+  SectionHandle handle(this, signal);
+  saveSections(ss, handle);
+
+  sendREQ(signal, ss);
+}
+
+void
+DbtcProxy::sendALTER_TAB_REQ(Signal* signal, Uint32 ssId,
+                             SectionHandle* handle)
+{
+  Ss_ALTER_TAB_REQ& ss = ssFind<Ss_ALTER_TAB_REQ>(ssId);
+
+  AlterTabReq* req = (AlterTabReq*)signal->getDataPtrSend();
+  *req = ss.m_req;
+  req->senderRef = reference();
+  req->senderData = ssId;
+  sendSignalNoRelease(workerRef(ss.m_worker), GSN_ALTER_TAB_REQ,
+                      signal, AlterTabReq::SignalLength, JBB, handle);
+}
+
+void
+DbtcProxy::execALTER_TAB_CONF(Signal* signal)
+{
+  const AlterTabConf* conf = (const AlterTabConf*)signal->getDataPtr();
+  Uint32 ssId = getSsId(conf);
+  Ss_ALTER_TAB_REQ& ss = ssFind<Ss_ALTER_TAB_REQ>(ssId);
+  recvCONF(signal, ss);
+}
+
+void
+DbtcProxy::execALTER_TAB_REF(Signal* signal)
+{
+  const AlterTabRef* ref = (const AlterTabRef*)signal->getDataPtr();
+  Uint32 ssId = getSsId(ref);
+  Ss_ALTER_TAB_REQ& ss = ssFind<Ss_ALTER_TAB_REQ>(ssId);
+  recvREF(signal, ss, ref->errorCode);
+}
+
+void
+DbtcProxy::sendALTER_TAB_CONF(Signal* signal, Uint32 ssId)
+{
+  Ss_ALTER_TAB_REQ& ss = ssFind<Ss_ALTER_TAB_REQ>(ssId);
+  BlockReference dictRef = ss.m_req.senderRef;
+
+  if (!lastReply(ss))
+    return;
+
+  if (ss.m_error == 0) {
+    jam();
+    AlterTabConf* conf = (AlterTabConf*)signal->getDataPtrSend();
+    conf->senderRef = reference();
+    conf->senderData = ss.m_req.senderData;
+    sendSignal(dictRef, GSN_ALTER_TAB_CONF,
+               signal, AlterTabConf::SignalLength, JBB);
+  } else {
+    jam();
+    AlterTabRef* ref = (AlterTabRef*)signal->getDataPtrSend();
+    ref->senderRef = reference();
+    ref->senderData = ss.m_req.senderData;
+    ref->errorCode = ss.m_error;
+    sendSignal(dictRef, GSN_ALTER_TAB_REF,
+               signal, AlterTabConf::SignalLength, JBB);
+  }
+
+  ssRelease<Ss_ALTER_TAB_REQ>(ssId);
+}
+
+void
+DbtcProxy::execTCSEIZEREQ(Signal* signal)
+{
+  jamEntry();
+
+  if (signal->getLength() >= 3 && signal->theData[2] != 0)
+  {
+    /**
+     * Specific instance requested...
+     */
+    Uint32 instance = signal->theData[2];
+    if (instance >= c_workers)
+    {
+      jam();
+      Uint32 senderData = signal->theData[0];
+      Uint32 senderRef = signal->theData[1];
+      signal->theData[0] = senderData;
+      signal->theData[1] = 289;
+      sendSignal(senderRef, GSN_TCSEIZEREF, signal, 2, JBB);
+      return;
+    }
+
+    sendSignal(workerRef(instance), GSN_TCSEIZEREQ, signal,
+               signal->getLength(), JBB);
+    return;
+  }
+
+  signal->theData[2] = m_tc_seize_req_instance;
+  sendSignal(workerRef(m_tc_seize_req_instance), GSN_TCSEIZEREQ, signal,
+             signal->getLength(), JBB);
+  m_tc_seize_req_instance = (m_tc_seize_req_instance + 1) % c_workers;
+}
+
+// GSN_TCGETOPSIZEREQ
+
+void
+DbtcProxy::execTCGETOPSIZEREQ(Signal* signal)
+{
+  Ss_TCGETOPSIZEREQ& ss = ssSeize<Ss_TCGETOPSIZEREQ>(1);
+
+  ss.m_sum = 0;
+  memcpy(ss.m_req, signal->getDataPtr(), 2*4);
+  sendREQ(signal, ss);
+}
+
+void
+DbtcProxy::sendTCGETOPSIZEREQ(Signal* signal, Uint32 ssId, SectionHandle*)
+{
+  Ss_TCGETOPSIZEREQ& ss = ssFind<Ss_TCGETOPSIZEREQ>(ssId);
+
+  signal->theData[0] = ssId;
+  signal->theData[1] = reference();
+  sendSignal(workerRef(ss.m_worker), GSN_TCGETOPSIZEREQ,
+             signal, 2, JBB);
+}
+
+void
+DbtcProxy::execTCGETOPSIZECONF(Signal* signal)
+{
+  Uint32 ssId = signal->theData[0];
+  Ss_TCGETOPSIZEREQ& ss = ssFind<Ss_TCGETOPSIZEREQ>(ssId);
+  ss.m_sum += signal->theData[1];
+  recvCONF(signal, ss);
+}
+
+void
+DbtcProxy::sendTCGETOPSIZECONF(Signal* signal, Uint32 ssId)
+{
+  Ss_TCGETOPSIZEREQ& ss = ssFind<Ss_TCGETOPSIZEREQ>(ssId);
+
+  if (!lastReply(ss))
+    return;
+
+  signal->theData[0] = ss.m_req[0];
+  signal->theData[1] = ss.m_sum;
+  sendSignal(ss.m_req[1], GSN_TCGETOPSIZECONF,
+             signal, 2, JBB);
+
+  ssRelease<Ss_TCGETOPSIZEREQ>(ssId);
+}
+
+// GSN_TC_CLOPSIZEREQ
+
+void
+DbtcProxy::execTC_CLOPSIZEREQ(Signal* signal)
+{
+  Ss_TC_CLOPSIZEREQ& ss = ssSeize<Ss_TC_CLOPSIZEREQ>(1);
+
+  memcpy(ss.m_req, signal->getDataPtr(), 2*4);
+  sendREQ(signal, ss);
+}
+
+void
+DbtcProxy::sendTC_CLOPSIZEREQ(Signal* signal, Uint32 ssId, SectionHandle*)
+{
+  Ss_TC_CLOPSIZEREQ& ss = ssFind<Ss_TC_CLOPSIZEREQ>(ssId);
+
+  signal->theData[0] = ssId;
+  signal->theData[1] = reference();
+  sendSignal(workerRef(ss.m_worker), GSN_TC_CLOPSIZEREQ,
+             signal, 2, JBB);
+}
+
+void
+DbtcProxy::execTC_CLOPSIZECONF(Signal* signal)
+{
+  Uint32 ssId = signal->theData[0];
+  Ss_TC_CLOPSIZEREQ& ss = ssFind<Ss_TC_CLOPSIZEREQ>(ssId);
+  recvCONF(signal, ss);
+}
+
+void
+DbtcProxy::sendTC_CLOPSIZECONF(Signal* signal, Uint32 ssId)
+{
+  Ss_TC_CLOPSIZEREQ& ss = ssFind<Ss_TC_CLOPSIZEREQ>(ssId);
+
+  if (!lastReply(ss))
+    return;
+
+  signal->theData[0] = ss.m_req[0];
+  sendSignal(ss.m_req[1], GSN_TC_CLOPSIZECONF,
+             signal, 1, JBB);
+
+  ssRelease<Ss_TC_CLOPSIZEREQ>(ssId);
+}
+
+// GSN_GCP_NOMORETRANS
+
+void
+DbtcProxy::execGCP_NOMORETRANS(Signal* signal)
+{
+  Ss_GCP_NOMORETRANS& ss = ssSeize<Ss_GCP_NOMORETRANS>(1);
+
+  ss.m_req = *(GCPNoMoreTrans*)signal->getDataPtr();
+  sendREQ(signal, ss);
+}
+
+void
+DbtcProxy::sendGCP_NOMORETRANS(Signal* signal, Uint32 ssId, SectionHandle*)
+{
+  Ss_GCP_NOMORETRANS& ss = ssFind<Ss_GCP_NOMORETRANS>(ssId);
+
+  GCPNoMoreTrans * req = (GCPNoMoreTrans*)signal->getDataPtrSend();
+  req->senderRef = reference();
+  req->senderData = ssId;
+  req->gci_hi = ss.m_req.gci_hi;
+  req->gci_lo = ss.m_req.gci_lo;
+  sendSignal(workerRef(ss.m_worker), GSN_GCP_NOMORETRANS,
+             signal, GCPNoMoreTrans::SignalLength, JBB);
+}
+
+void
+DbtcProxy::execGCP_TCFINISHED(Signal* signal)
+{
+  GCPTCFinished* conf = (GCPTCFinished*)signal->getDataPtr();
+  Uint32 ssId = conf->senderData;
+  Ss_GCP_NOMORETRANS& ss = ssFind<Ss_GCP_NOMORETRANS>(ssId);
+  recvCONF(signal, ss);
+}
+
+void
+DbtcProxy::sendGCP_TCFINISHED(Signal* signal, Uint32 ssId)
+{
+  Ss_GCP_NOMORETRANS& ss = ssFind<Ss_GCP_NOMORETRANS>(ssId);
+
+  if (!lastReply(ss))
+    return;
+
+  GCPTCFinished* conf = (GCPTCFinished*)signal->getDataPtrSend();
+  conf->senderData = ss.m_req.senderData;
+  conf->gci_hi = ss.m_req.gci_hi;
+  conf->gci_lo = ss.m_req.gci_lo;
+  sendSignal(ss.m_req.senderRef, GSN_GCP_TCFINISHED,
+             signal, GCPTCFinished::SignalLength, JBB);
+
+  ssRelease<Ss_GCP_NOMORETRANS>(ssId);
+}
+
+
+// GSN_API_FAILREQ
+
+void
+DbtcProxy::execAPI_FAILREQ(Signal* signal)
+{
+  Uint32 nodeId = signal->theData[0];
+  Ss_API_FAILREQ& ss = ssSeize<Ss_API_FAILREQ>(nodeId);
+
+  ss.m_ref = signal->theData[1];
+  sendREQ(signal, ss);
+}
+
+void
+DbtcProxy::sendAPI_FAILREQ(Signal* signal, Uint32 ssId, SectionHandle*)
+{
+  Ss_API_FAILREQ& ss = ssFind<Ss_API_FAILREQ>(ssId);
+
+  signal->theData[0] = ssId;
+  signal->theData[1] = reference();
+  sendSignal(workerRef(ss.m_worker), GSN_API_FAILREQ,
+             signal, 2, JBB);
+}
+
+void
+DbtcProxy::execAPI_FAILCONF(Signal* signal)
+{
+  Uint32 nodeId = signal->theData[0];
+  Ss_API_FAILREQ& ss = ssFind<Ss_API_FAILREQ>(nodeId);
+  recvCONF(signal, ss);
+}
+
+void
+DbtcProxy::sendAPI_FAILCONF(Signal* signal, Uint32 ssId)
+{
+  Ss_API_FAILREQ& ss = ssFind<Ss_API_FAILREQ>(ssId);
+
+  if (!lastReply(ss))
+    return;
+
+  signal->theData[0] = ssId;
+  signal->theData[1] = calcTcBlockRef(getOwnNodeId());
+  sendSignal(ss.m_ref, GSN_API_FAILCONF,
+             signal, 2, JBB);
+
+  ssRelease<Ss_API_FAILREQ>(ssId);
+}
+
+// GSN_CREATE_INDX_IMPL_REQ
+
+void
+DbtcProxy::execCREATE_INDX_IMPL_REQ(Signal* signal)
+{
+  jamEntry();
+  if (!assembleFragments(signal))
+  {
+    jam();
+    return;
+  }
+
+  const CreateIndxImplReq* req = (const CreateIndxImplReq*)signal->getDataPtr();
+  Ss_CREATE_INDX_IMPL_REQ& ss = ssSeize<Ss_CREATE_INDX_IMPL_REQ>();
+  ss.m_req = *req;
+  SectionHandle handle(this, signal);
+  saveSections(ss, handle);
+  sendREQ(signal, ss);
+}
+
+void
+DbtcProxy::sendCREATE_INDX_IMPL_REQ(Signal* signal, Uint32 ssId,
+                                    SectionHandle * handle)
+{
+  Ss_CREATE_INDX_IMPL_REQ& ss = ssFind<Ss_CREATE_INDX_IMPL_REQ>(ssId);
+
+  CreateIndxImplReq* req = (CreateIndxImplReq*)signal->getDataPtrSend();
+  *req = ss.m_req;
+  req->senderRef = reference();
+  req->senderData = ssId;
+  sendSignalNoRelease(workerRef(ss.m_worker), GSN_CREATE_INDX_IMPL_REQ,
+                      signal, CreateIndxImplReq::SignalLength, JBB,
+                      handle);
+}
+
+void
+DbtcProxy::execCREATE_INDX_IMPL_CONF(Signal* signal)
+{
+  const CreateIndxImplConf* conf = (const CreateIndxImplConf*)signal->getDataPtr();
+  Uint32 ssId = conf->senderData;
+  Ss_CREATE_INDX_IMPL_REQ& ss = ssFind<Ss_CREATE_INDX_IMPL_REQ>(ssId);
+  recvCONF(signal, ss);
+}
+
+void
+DbtcProxy::execCREATE_INDX_IMPL_REF(Signal* signal)
+{
+  const CreateIndxImplRef* ref = (const CreateIndxImplRef*)signal->getDataPtr();
+  Uint32 ssId = ref->senderData;
+  Ss_CREATE_INDX_IMPL_REQ& ss = ssFind<Ss_CREATE_INDX_IMPL_REQ>(ssId);
+  recvREF(signal, ss, ref->errorCode);
+}
+
+void
+DbtcProxy::sendCREATE_INDX_IMPL_CONF(Signal* signal, Uint32 ssId)
+{
+  Ss_CREATE_INDX_IMPL_REQ& ss = ssFind<Ss_CREATE_INDX_IMPL_REQ>(ssId);
+  BlockReference dictRef = ss.m_req.senderRef;
+
+  if (!lastReply(ss))
+    return;
+
+  if (ss.m_error == 0) {
+    jam();
+    CreateIndxImplConf* conf = (CreateIndxImplConf*)signal->getDataPtrSend();
+    conf->senderRef = reference();
+    conf->senderData = ss.m_req.senderData;
+    sendSignal(dictRef, GSN_CREATE_INDX_IMPL_CONF,
+               signal, CreateIndxImplConf::SignalLength, JBB);
+  } else {
+    CreateIndxImplRef* ref = (CreateIndxImplRef*)signal->getDataPtrSend();
+    ref->senderRef = reference();
+    ref->senderData = ss.m_req.senderData;
+    ref->errorCode = ss.m_error;
+    sendSignal(dictRef, GSN_CREATE_INDX_IMPL_REF,
+               signal, CreateIndxImplRef::SignalLength, JBB);
+  }
+
+  ssRelease<Ss_CREATE_INDX_IMPL_REQ>(ssId);
+}
+
+// GSN_ALTER_INDX_IMPL_REQ
+
+void
+DbtcProxy::execALTER_INDX_IMPL_REQ(Signal* signal)
+{
+  const AlterIndxImplReq* req = (const AlterIndxImplReq*)signal->getDataPtr();
+  Ss_ALTER_INDX_IMPL_REQ& ss = ssSeize<Ss_ALTER_INDX_IMPL_REQ>();
+  ss.m_req = *req;
+  ndbrequire(signal->getLength() == AlterIndxImplReq::SignalLength);
+  sendREQ(signal, ss);
+}
+
+void
+DbtcProxy::sendALTER_INDX_IMPL_REQ(Signal* signal, Uint32 ssId, SectionHandle*)
+{
+  Ss_ALTER_INDX_IMPL_REQ& ss = ssFind<Ss_ALTER_INDX_IMPL_REQ>(ssId);
+
+  AlterIndxImplReq* req = (AlterIndxImplReq*)signal->getDataPtrSend();
+  *req = ss.m_req;
+  req->senderRef = reference();
+  req->senderData = ssId;
+  sendSignal(workerRef(ss.m_worker), GSN_ALTER_INDX_IMPL_REQ,
+             signal, AlterIndxImplReq::SignalLength, JBB);
+}
+
+void
+DbtcProxy::execALTER_INDX_IMPL_CONF(Signal* signal)
+{
+  const AlterIndxImplConf* conf = (const AlterIndxImplConf*)signal->getDataPtr();
+  Uint32 ssId = conf->senderData;
+  Ss_ALTER_INDX_IMPL_REQ& ss = ssFind<Ss_ALTER_INDX_IMPL_REQ>(ssId);
+  recvCONF(signal, ss);
+}
+
+void
+DbtcProxy::execALTER_INDX_IMPL_REF(Signal* signal)
+{
+  const AlterIndxImplRef* ref = (const AlterIndxImplRef*)signal->getDataPtr();
+  Uint32 ssId = ref->senderData;
+  Ss_ALTER_INDX_IMPL_REQ& ss = ssFind<Ss_ALTER_INDX_IMPL_REQ>(ssId);
+  recvREF(signal, ss, ref->errorCode);
+}
+
+void
+DbtcProxy::sendALTER_INDX_IMPL_CONF(Signal* signal, Uint32 ssId)
+{
+  Ss_ALTER_INDX_IMPL_REQ& ss = ssFind<Ss_ALTER_INDX_IMPL_REQ>(ssId);
+  BlockReference dictRef = ss.m_req.senderRef;
+
+  if (!lastReply(ss))
+    return;
+
+  if (ss.m_error == 0) {
+    jam();
+    AlterIndxImplConf* conf = (AlterIndxImplConf*)signal->getDataPtrSend();
+    conf->senderRef = reference();
+    conf->senderData = ss.m_req.senderData;
+    sendSignal(dictRef, GSN_ALTER_INDX_IMPL_CONF,
+               signal, AlterIndxImplConf::SignalLength, JBB);
+  } else {
+    AlterIndxImplRef* ref = (AlterIndxImplRef*)signal->getDataPtrSend();
+    ref->senderRef = reference();
+    ref->senderData = ss.m_req.senderData;
+    ref->errorCode = ss.m_error;
+    sendSignal(dictRef, GSN_ALTER_INDX_IMPL_REF,
+               signal, AlterIndxImplRef::SignalLength, JBB);
+  }
+
+  ssRelease<Ss_ALTER_INDX_IMPL_REQ>(ssId);
+}
+
+// GSN_DROP_INDX_IMPL_REQ
+
+void
+DbtcProxy::execDROP_INDX_IMPL_REQ(Signal* signal)
+{
+  const DropIndxImplReq* req = (const DropIndxImplReq*)signal->getDataPtr();
+  Ss_DROP_INDX_IMPL_REQ& ss = ssSeize<Ss_DROP_INDX_IMPL_REQ>();
+  ss.m_req = *req;
+  ndbrequire(signal->getLength() == DropIndxImplReq::SignalLength);
+  sendREQ(signal, ss);
+}
+
+void
+DbtcProxy::sendDROP_INDX_IMPL_REQ(Signal* signal, Uint32 ssId, SectionHandle*)
+{
+  Ss_DROP_INDX_IMPL_REQ& ss = ssFind<Ss_DROP_INDX_IMPL_REQ>(ssId);
+
+  DropIndxImplReq* req = (DropIndxImplReq*)signal->getDataPtrSend();
+  *req = ss.m_req;
+  req->senderRef = reference();
+  req->senderData = ssId;
+  sendSignal(workerRef(ss.m_worker), GSN_DROP_INDX_IMPL_REQ,
+             signal, DropIndxImplReq::SignalLength, JBB);
+}
+
+void
+DbtcProxy::execDROP_INDX_IMPL_CONF(Signal* signal)
+{
+  const DropIndxImplConf* conf = (const DropIndxImplConf*)signal->getDataPtr();
+  Uint32 ssId = conf->senderData;
+  Ss_DROP_INDX_IMPL_REQ& ss = ssFind<Ss_DROP_INDX_IMPL_REQ>(ssId);
+  recvCONF(signal, ss);
+}
+
+void
+DbtcProxy::execDROP_INDX_IMPL_REF(Signal* signal)
+{
+  const DropIndxImplRef* ref = (const DropIndxImplRef*)signal->getDataPtr();
+  Uint32 ssId = ref->senderData;
+  Ss_DROP_INDX_IMPL_REQ& ss = ssFind<Ss_DROP_INDX_IMPL_REQ>(ssId);
+  recvREF(signal, ss, ref->errorCode);
+}
+
+void
+DbtcProxy::sendDROP_INDX_IMPL_CONF(Signal* signal, Uint32 ssId)
+{
+  Ss_DROP_INDX_IMPL_REQ& ss = ssFind<Ss_DROP_INDX_IMPL_REQ>(ssId);
+  BlockReference dictRef = ss.m_req.senderRef;
+
+  if (!lastReply(ss))
+    return;
+
+  if (ss.m_error == 0) {
+    jam();
+    DropIndxImplConf* conf = (DropIndxImplConf*)signal->getDataPtrSend();
+    conf->senderRef = reference();
+    conf->senderData = ss.m_req.senderData;
+    sendSignal(dictRef, GSN_DROP_INDX_IMPL_CONF,
+               signal, DropIndxImplConf::SignalLength, JBB);
+  } else {
+    DropIndxImplRef* ref = (DropIndxImplRef*)signal->getDataPtrSend();
+    ref->senderRef = reference();
+    ref->senderData = ss.m_req.senderData;
+    ref->errorCode = ss.m_error;
+    sendSignal(dictRef, GSN_DROP_INDX_IMPL_REF,
+               signal, DropIndxImplRef::SignalLength, JBB);
+  }
+
+  ssRelease<Ss_DROP_INDX_IMPL_REQ>(ssId);
+}
+
+BLOCK_FUNCTIONS(DbtcProxy)

=== added file 'storage/ndb/src/kernel/blocks/dbtc/DbtcProxy.hpp'
--- a/storage/ndb/src/kernel/blocks/dbtc/DbtcProxy.hpp	1970-01-01 00:00:00 +0000
+++ b/storage/ndb/src/kernel/blocks/dbtc/DbtcProxy.hpp	2011-04-27 10:48:16 +0000
@@ -0,0 +1,309 @@
+/*
+   Copyright (c) 2011, 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 Foundation; version 2 of the License.
+
+   This program is distributed in the hope that it will be useful,
+   but WITHOUT ANY WARRANTY; without even the implied warranty of
+   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+   GNU General Public License for more details.
+
+   You should have received a copy of the GNU General Public License
+   along with this program; if not, write to the Free Software
+   Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301  USA
+*/
+
+#ifndef NDB_DBTC_PROXY_HPP
+#define NDB_DBTC_PROXY_HPP
+
+#include <LocalProxy.hpp>
+#include <signaldata/CreateTab.hpp>
+#include <signaldata/TabCommit.hpp>
+#include <signaldata/PrepDropTab.hpp>
+#include <signaldata/DropTab.hpp>
+#include <signaldata/AlterTab.hpp>
+#include <signaldata/GCP.hpp>
+
+#include <signaldata/CreateIndxImpl.hpp>
+#include <signaldata/AlterIndxImpl.hpp>
+#include <signaldata/DropIndxImpl.hpp>
+
+class DbtcProxy : public LocalProxy {
+public:
+  DbtcProxy(Block_context& ctx);
+  virtual ~DbtcProxy();
+  BLOCK_DEFINES(DbtcProxy);
+
+protected:
+  virtual SimulatedBlock* newWorker(Uint32 instanceNo);
+
+  // GSN_NDB_STTOR
+  virtual void callNDB_STTOR(Signal*);
+
+  // GSN_TC_SCHVERREQ
+  struct Ss_TC_SCHVERREQ : SsParallel {
+    TcSchVerReq m_req;
+    Ss_TC_SCHVERREQ() {
+      m_sendREQ = (SsFUNCREQ)&DbtcProxy::sendTC_SCHVERREQ;
+      m_sendCONF = (SsFUNCREP)&DbtcProxy::sendTC_SCHVERCONF;
+    }
+    enum { poolSize = 1 };
+    static SsPool<Ss_TC_SCHVERREQ>& pool(LocalProxy* proxy) {
+      return ((DbtcProxy*)proxy)->c_ss_TC_SCHVERREQ;
+    }
+  };
+  SsPool<Ss_TC_SCHVERREQ> c_ss_TC_SCHVERREQ;
+  void execTC_SCHVERREQ(Signal*);
+  void sendTC_SCHVERREQ(Signal*, Uint32 ssId, SectionHandle*);
+  void execTC_SCHVERCONF(Signal*);
+  void sendTC_SCHVERCONF(Signal*, Uint32 ssId);
+
+  // GSN_TAB_COMMITREQ [ sub-op ]
+  struct Ss_TAB_COMMITREQ : SsParallel {
+    TabCommitReq m_req;
+    Ss_TAB_COMMITREQ() {
+      m_sendREQ = (SsFUNCREQ)&DbtcProxy::sendTAB_COMMITREQ;
+      m_sendCONF = (SsFUNCREP)&DbtcProxy::sendTAB_COMMITCONF;
+    }
+    enum { poolSize = 1 };
+    static SsPool<Ss_TAB_COMMITREQ>& pool(LocalProxy* proxy) {
+      return ((DbtcProxy*)proxy)->c_ss_TAB_COMMITREQ;
+    }
+  };
+  SsPool<Ss_TAB_COMMITREQ> c_ss_TAB_COMMITREQ;
+  void execTAB_COMMITREQ(Signal*);
+  void sendTAB_COMMITREQ(Signal*, Uint32 ssId, SectionHandle*);
+  void execTAB_COMMITCONF(Signal*);
+  void execTAB_COMMITREF(Signal*);
+  void sendTAB_COMMITCONF(Signal*, Uint32 ssId);
+
+  // GSN_PREP_DROP_TAB_REQ
+  struct Ss_PREP_DROP_TAB_REQ : SsParallel {
+    PrepDropTabReq m_req;
+    Ss_PREP_DROP_TAB_REQ() {
+      m_sendREQ = (SsFUNCREQ)&DbtcProxy::sendPREP_DROP_TAB_REQ;
+      m_sendCONF = (SsFUNCREP)&DbtcProxy::sendPREP_DROP_TAB_CONF;
+    }
+    enum { poolSize = 1 };
+    static SsPool<Ss_PREP_DROP_TAB_REQ>& pool(LocalProxy* proxy) {
+      return ((DbtcProxy*)proxy)->c_ss_PREP_DROP_TAB_REQ;
+    }
+  };
+
+  SsPool<Ss_PREP_DROP_TAB_REQ> c_ss_PREP_DROP_TAB_REQ;
+  Uint32 getSsId(const PrepDropTabReq* req) {
+    return SsIdBase | req->tableId;
+  }
+  Uint32 getSsId(const PrepDropTabConf* conf) {
+    return SsIdBase | conf->tableId;
+  }
+  Uint32 getSsId(const PrepDropTabRef* ref) {
+    return SsIdBase | ref->tableId;
+  }
+  void execPREP_DROP_TAB_REQ(Signal*);
+  void sendPREP_DROP_TAB_REQ(Signal*, Uint32 ssId, SectionHandle*);
+  void execPREP_DROP_TAB_CONF(Signal*);
+  void execPREP_DROP_TAB_REF(Signal*);
+  void sendPREP_DROP_TAB_CONF(Signal*, Uint32 ssId);
+
+  // GSN_DROP_TAB_REQ
+  struct Ss_DROP_TAB_REQ : SsParallel {
+    DropTabReq m_req;
+    Ss_DROP_TAB_REQ() {
+      m_sendREQ = (SsFUNCREQ)&DbtcProxy::sendDROP_TAB_REQ;
+      m_sendCONF = (SsFUNCREP)&DbtcProxy::sendDROP_TAB_CONF;
+    }
+    enum { poolSize = 1 };
+    static SsPool<Ss_DROP_TAB_REQ>& pool(LocalProxy* proxy) {
+      return ((DbtcProxy*)proxy)->c_ss_DROP_TAB_REQ;
+    }
+  };
+  SsPool<Ss_DROP_TAB_REQ> c_ss_DROP_TAB_REQ;
+  Uint32 getSsId(const DropTabReq* req) {
+    return SsIdBase | req->tableId;
+  }
+  Uint32 getSsId(const DropTabConf* conf) {
+    return SsIdBase | conf->tableId;
+  }
+  Uint32 getSsId(const DropTabRef* ref) {
+    return SsIdBase | ref->tableId;
+  }
+  void execDROP_TAB_REQ(Signal*);
+  void sendDROP_TAB_REQ(Signal*, Uint32 ssId, SectionHandle*);
+  void execDROP_TAB_CONF(Signal*);
+  void execDROP_TAB_REF(Signal*);
+  void sendDROP_TAB_CONF(Signal*, Uint32 ssId);
+
+  // GSN_ALTER_TAB_REQ
+  struct Ss_ALTER_TAB_REQ : SsParallel {
+    AlterTabReq m_req;
+    Ss_ALTER_TAB_REQ() {
+      m_sendREQ = (SsFUNCREQ)&DbtcProxy::sendALTER_TAB_REQ;
+      m_sendCONF = (SsFUNCREP)&DbtcProxy::sendALTER_TAB_CONF;
+    }
+    enum { poolSize = 1 };
+    static SsPool<Ss_ALTER_TAB_REQ>& pool(LocalProxy* proxy) {
+      return ((DbtcProxy*)proxy)->c_ss_ALTER_TAB_REQ;
+    }
+  };
+  SsPool<Ss_ALTER_TAB_REQ> c_ss_ALTER_TAB_REQ;
+  Uint32 getSsId(const AlterTabReq* req) {
+    return SsIdBase | req->tableId;
+  }
+  Uint32 getSsId(const AlterTabConf* conf) {
+    return conf->senderData;
+  }
+  Uint32 getSsId(const AlterTabRef* ref) {
+    return ref->senderData;
+  }
+  void execALTER_TAB_REQ(Signal*);
+  void sendALTER_TAB_REQ(Signal*, Uint32 ssId, SectionHandle*);
+  void execALTER_TAB_CONF(Signal*);
+  void execALTER_TAB_REF(Signal*);
+  void sendALTER_TAB_CONF(Signal*, Uint32 ssId);
+
+  /**
+   * TCSEIZEREQ
+   */
+  Uint32 m_tc_seize_req_instance; // round robin
+  void execTCSEIZEREQ(Signal* signal);
+
+  /**
+   * TCGETOPSIZEREQ
+   */
+  struct Ss_TCGETOPSIZEREQ : SsParallel {
+    Uint32 m_sum;
+    Uint32 m_req[2];
+    Ss_TCGETOPSIZEREQ() {
+      m_sendREQ = (SsFUNCREQ)&DbtcProxy::sendTCGETOPSIZEREQ;
+      m_sendCONF = (SsFUNCREP)&DbtcProxy::sendTCGETOPSIZECONF;
+    }
+    enum { poolSize = 1 };
+    static SsPool<Ss_TCGETOPSIZEREQ>& pool(LocalProxy* proxy) {
+      return ((DbtcProxy*)proxy)->c_ss_TCGETOPSIZEREQ;
+    }
+  };
+  SsPool<Ss_TCGETOPSIZEREQ> c_ss_TCGETOPSIZEREQ;
+  void execTCGETOPSIZEREQ(Signal*);
+  void sendTCGETOPSIZEREQ(Signal*, Uint32 ssId, SectionHandle*);
+  void execTCGETOPSIZECONF(Signal*);
+  void sendTCGETOPSIZECONF(Signal*, Uint32 ssId);
+
+  /**
+   * TC_CLOPSIZEREQ
+   */
+  struct Ss_TC_CLOPSIZEREQ : SsParallel {
+    Uint32 m_req[2];
+    Ss_TC_CLOPSIZEREQ() {
+      m_sendREQ = (SsFUNCREQ)&DbtcProxy::sendTC_CLOPSIZEREQ;
+      m_sendCONF = (SsFUNCREP)&DbtcProxy::sendTC_CLOPSIZECONF;
+    }
+    enum { poolSize = 1 };
+    static SsPool<Ss_TC_CLOPSIZEREQ>& pool(LocalProxy* proxy) {
+      return ((DbtcProxy*)proxy)->c_ss_TC_CLOPSIZEREQ;
+    }
+  };
+  SsPool<Ss_TC_CLOPSIZEREQ> c_ss_TC_CLOPSIZEREQ;
+  void execTC_CLOPSIZEREQ(Signal*);
+  void sendTC_CLOPSIZEREQ(Signal*, Uint32 ssId, SectionHandle*);
+  void execTC_CLOPSIZECONF(Signal*);
+  void sendTC_CLOPSIZECONF(Signal*, Uint32 ssId);
+
+  // GSN_GCP_NOMORETRANS
+  struct Ss_GCP_NOMORETRANS : SsParallel {
+    GCPNoMoreTrans m_req;
+    Ss_GCP_NOMORETRANS() {
+      m_sendREQ = (SsFUNCREQ)&DbtcProxy::sendGCP_NOMORETRANS;
+      m_sendCONF = (SsFUNCREP)&DbtcProxy::sendGCP_TCFINISHED;
+    }
+    enum { poolSize = 1 };
+    static SsPool<Ss_GCP_NOMORETRANS>& pool(LocalProxy* proxy) {
+      return ((DbtcProxy*)proxy)->c_ss_GCP_NOMORETRANS;
+    }
+  };
+  SsPool<Ss_GCP_NOMORETRANS> c_ss_GCP_NOMORETRANS;
+  void execGCP_NOMORETRANS(Signal*);
+  void sendGCP_NOMORETRANS(Signal*, Uint32 ssId, SectionHandle*);
+  void execGCP_TCFINISHED(Signal*);
+  void sendGCP_TCFINISHED(Signal*, Uint32 ssId);
+
+  // GSN_API_FAILREQ
+  struct Ss_API_FAILREQ : SsParallel {
+    Uint32 m_ref; //
+    Ss_API_FAILREQ() {
+      m_sendREQ = (SsFUNCREQ)&DbtcProxy::sendAPI_FAILREQ;
+      m_sendCONF = (SsFUNCREP)&DbtcProxy::sendAPI_FAILCONF;
+    }
+    enum { poolSize = MAX_NDB_NODES };
+    static SsPool<Ss_API_FAILREQ>& pool(LocalProxy* proxy) {
+      return ((DbtcProxy*)proxy)->c_ss_API_FAILREQ;
+    }
+  };
+  SsPool<Ss_API_FAILREQ> c_ss_API_FAILREQ;
+  void execAPI_FAILREQ(Signal*);
+  void sendAPI_FAILREQ(Signal*, Uint32 ssId, SectionHandle*);
+  void execAPI_FAILCONF(Signal*);
+  void sendAPI_FAILCONF(Signal*, Uint32 ssId);
+
+  // GSN_CREATE_INDX_IMPL_REQ
+  struct Ss_CREATE_INDX_IMPL_REQ : SsParallel {
+    CreateIndxImplReq m_req;
+
+    Ss_CREATE_INDX_IMPL_REQ() {
+      m_sendREQ = (SsFUNCREQ)&DbtcProxy::sendCREATE_INDX_IMPL_REQ;
+      m_sendCONF = (SsFUNCREP)&DbtcProxy::sendCREATE_INDX_IMPL_CONF;
+    }
+    enum { poolSize = 1 };
+    static SsPool<Ss_CREATE_INDX_IMPL_REQ>& pool(LocalProxy* proxy) {
+      return ((DbtcProxy*)proxy)->c_ss_CREATE_INDX_IMPL_REQ;
+    }
+  };
+  SsPool<Ss_CREATE_INDX_IMPL_REQ> c_ss_CREATE_INDX_IMPL_REQ;
+  void execCREATE_INDX_IMPL_REQ(Signal*);
+  void sendCREATE_INDX_IMPL_REQ(Signal*, Uint32 ssId, SectionHandle*);
+  void execCREATE_INDX_IMPL_CONF(Signal*);
+  void execCREATE_INDX_IMPL_REF(Signal*);
+  void sendCREATE_INDX_IMPL_CONF(Signal*, Uint32 ssId);
+
+  // GSN_ALTER_INDX_IMPL_REQ
+  struct Ss_ALTER_INDX_IMPL_REQ : SsParallel {
+    AlterIndxImplReq m_req;
+    Ss_ALTER_INDX_IMPL_REQ() {
+      m_sendREQ = (SsFUNCREQ)&DbtcProxy::sendALTER_INDX_IMPL_REQ;
+      m_sendCONF = (SsFUNCREP)&DbtcProxy::sendALTER_INDX_IMPL_CONF;
+    }
+    enum { poolSize = 1 };
+    static SsPool<Ss_ALTER_INDX_IMPL_REQ>& pool(LocalProxy* proxy) {
+      return ((DbtcProxy*)proxy)->c_ss_ALTER_INDX_IMPL_REQ;
+    }
+  };
+  SsPool<Ss_ALTER_INDX_IMPL_REQ> c_ss_ALTER_INDX_IMPL_REQ;
+  void execALTER_INDX_IMPL_REQ(Signal*);
+  void sendALTER_INDX_IMPL_REQ(Signal*, Uint32 ssId, SectionHandle*);
+  void execALTER_INDX_IMPL_CONF(Signal*);
+  void execALTER_INDX_IMPL_REF(Signal*);
+  void sendALTER_INDX_IMPL_CONF(Signal*, Uint32 ssId);
+
+  // GSN_DROP_INDX_IMPL_REQ
+  struct Ss_DROP_INDX_IMPL_REQ : SsParallel {
+    DropIndxImplReq m_req;
+    Ss_DROP_INDX_IMPL_REQ() {
+      m_sendREQ = (SsFUNCREQ)&DbtcProxy::sendDROP_INDX_IMPL_REQ;
+      m_sendCONF = (SsFUNCREP)&DbtcProxy::sendDROP_INDX_IMPL_CONF;
+    }
+    enum { poolSize = 1 };
+    static SsPool<Ss_DROP_INDX_IMPL_REQ>& pool(LocalProxy* proxy) {
+      return ((DbtcProxy*)proxy)->c_ss_DROP_INDX_IMPL_REQ;
+    }
+  };
+  SsPool<Ss_DROP_INDX_IMPL_REQ> c_ss_DROP_INDX_IMPL_REQ;
+  void execDROP_INDX_IMPL_REQ(Signal*);
+  void sendDROP_INDX_IMPL_REQ(Signal*, Uint32 ssId, SectionHandle*);
+  void execDROP_INDX_IMPL_CONF(Signal*);
+  void execDROP_INDX_IMPL_REF(Signal*);
+  void sendDROP_INDX_IMPL_CONF(Signal*, Uint32 ssId);
+};
+
+#endif

=== modified file 'storage/ndb/src/kernel/blocks/dbtup/Dbtup.hpp'
--- a/storage/ndb/src/kernel/blocks/dbtup/Dbtup.hpp	2011-04-21 05:38:27 +0000
+++ b/storage/ndb/src/kernel/blocks/dbtup/Dbtup.hpp	2011-04-28 07:47:53 +0000
@@ -960,7 +960,10 @@ ArrayPool<TupTriggerData> c_triggerPool;
       subscriptionDeleteTriggers(triggerPool),
       subscriptionUpdateTriggers(triggerPool),
       constraintUpdateTriggers(triggerPool),
-      tuxCustomTriggers(triggerPool)
+      tuxCustomTriggers(triggerPool),
+      deferredInsertTriggers(triggerPool),
+      deferredDeleteTriggers(triggerPool),
+      deferredUpdateTriggers(triggerPool)
       {}
     
     Bitmask<MAXNROFATTRIBUTESINWORDS> notNullAttributeMask;
@@ -1090,7 +1093,10 @@ ArrayPool<TupTriggerData> c_triggerPool;
     DLList<TupTriggerData> subscriptionDeleteTriggers;
     DLList<TupTriggerData> subscriptionUpdateTriggers;
     DLList<TupTriggerData> constraintUpdateTriggers;
-    
+    DLList<TupTriggerData> deferredInsertTriggers;
+    DLList<TupTriggerData> deferredUpdateTriggers;
+    DLList<TupTriggerData> deferredDeleteTriggers;
+
     // List of ordered indexes
     DLList<TupTriggerData> tuxCustomTriggers;
     
@@ -1505,19 +1511,31 @@ typedef Ptr<HostBuffer> HostBufferPtr;
     STATIC_CONST( SZ32 = 1 );
   };
 
+  enum When
+  {
+    KRS_PREPARE = 0,
+    KRS_COMMIT = 1,
+    KRS_PRE_COMMIT0 = 2, // There can be multiple pre commit phases...
+    KRS_PRE_COMMIT1 = 3
+  };
+
 struct KeyReqStruct {
 
-  KeyReqStruct(EmulatedJamBuffer * _jamBuffer) {
+  KeyReqStruct(EmulatedJamBuffer * _jamBuffer, When when = KRS_PREPARE) {
 #if defined VM_TRACE || defined ERROR_INSERT
     memset(this, 0xf3, sizeof(* this));
 #endif
     jamBuffer = _jamBuffer;
+    m_when = when;
+    m_deferred_constraints = true;
   }
-  KeyReqStruct(Dbtup* tup) {
+  KeyReqStruct(Dbtup* tup, When when = KRS_PREPARE) {
 #if defined VM_TRACE || defined ERROR_INSERT
     memset(this, 0xf3, sizeof(* this));
 #endif
     jamBuffer = tup->jamBuffer();
+    m_when = when;
+    m_deferred_constraints = true;
   }
   
 /**
@@ -1564,6 +1582,7 @@ struct KeyReqStruct {
   /* Flag: is tuple in expanded or in shrunken/stored format? */
   bool is_expanded;
   bool m_is_lcp;
+  enum When m_when;
 
   struct Var_data {
     /*
@@ -1611,6 +1630,7 @@ struct KeyReqStruct {
   bool            last_row;
   bool            m_use_rowid;
   Uint8           m_reorg;
+  bool            m_deferred_constraints;
 
   Signal*         signal;
   Uint32 no_fired_triggers;
@@ -1999,6 +2019,12 @@ private:
 //------------------------------------------------------------------
   void execDROP_TRIG_IMPL_REQ(Signal* signal);
 
+  /**
+   * Deferred triggers execute when execFIRE_TRIG_REQ
+   *   is called
+   */
+  void execFIRE_TRIG_REQ(Signal* signal);
+
 // *****************************************************************
 // Setting up the environment for reads, inserts, updates and deletes.
 // *****************************************************************
@@ -2584,11 +2610,11 @@ private:
                                     Tablerec* tablePtr,
                                     bool disk);
 
-#if 0
-  void checkDeferredTriggers(Signal* signal, 
+  void checkDeferredTriggers(KeyReqStruct *req_struct,
                              Operationrec* regOperPtr,
-                             Tablerec* regTablePtr);
-#endif
+                             Tablerec* regTablePtr,
+                             bool disk);
+
   void checkDetachedTriggers(KeyReqStruct *req_struct,
                              Operationrec* regOperPtr,
                              Tablerec* regTablePtr,
@@ -2599,9 +2625,19 @@ private:
                              Operationrec* regOperPtr,
                              bool disk);
 
+  void checkDeferredTriggersDuringPrepare(KeyReqStruct *req_struct,
+                                          DLList<TupTriggerData>& triggerList,
+                                          Operationrec* const regOperPtr,
+                                          bool disk);
   void fireDeferredTriggers(KeyReqStruct *req_struct,
                             DLList<TupTriggerData>& triggerList,
-                            Operationrec* regOperPtr);
+                            Operationrec* const regOperPtr,
+                            bool disk);
+
+  void fireDeferredConstraints(KeyReqStruct *req_struct,
+                               DLList<TupTriggerData>& triggerList,
+                               Operationrec* const regOperPtr,
+                               bool disk);
 
   void fireDetachedTriggers(KeyReqStruct *req_struct,
                             DLList<TupTriggerData>& triggerList,

=== modified file 'storage/ndb/src/kernel/blocks/dbtup/DbtupCommit.cpp'
--- a/storage/ndb/src/kernel/blocks/dbtup/DbtupCommit.cpp	2011-04-21 05:38:27 +0000
+++ b/storage/ndb/src/kernel/blocks/dbtup/DbtupCommit.cpp	2011-04-28 07:47:53 +0000
@@ -580,7 +580,7 @@ void Dbtup::execTUP_COMMITREQ(Signal* si
   FragrecordPtr regFragPtr;
   OperationrecPtr regOperPtr;
   TablerecPtr regTabPtr;
-  KeyReqStruct req_struct(this);
+  KeyReqStruct req_struct(this, KRS_COMMIT);
   TransState trans_state;
   Uint32 no_of_fragrec, no_of_tablerec;
 

=== modified file 'storage/ndb/src/kernel/blocks/dbtup/DbtupExecQuery.cpp'
--- a/storage/ndb/src/kernel/blocks/dbtup/DbtupExecQuery.cpp	2011-04-21 05:38:27 +0000
+++ b/storage/ndb/src/kernel/blocks/dbtup/DbtupExecQuery.cpp	2011-04-28 07:47:53 +0000
@@ -597,9 +597,11 @@ void Dbtup::execTUPKEYREQ(Signal* signal
 
    sig1 = tupKeyReq->m_row_id_page_no;
    sig2 = tupKeyReq->m_row_id_page_idx;
+   sig3 = tupKeyReq->deferred_constraints;
 
    req_struct.m_row_id.m_page_no = sig1;
    req_struct.m_row_id.m_page_idx = sig2;
+   req_struct.m_deferred_constraints = sig3;
 
    /* Get AttrInfo section if this is a long TUPKEYREQ */
    Uint32 attrInfoIVal= tupKeyReq->attrInfoIVal;

=== modified file 'storage/ndb/src/kernel/blocks/dbtup/DbtupGen.cpp'
--- a/storage/ndb/src/kernel/blocks/dbtup/DbtupGen.cpp	2011-02-07 13:21:49 +0000
+++ b/storage/ndb/src/kernel/blocks/dbtup/DbtupGen.cpp	2011-04-28 07:47:53 +0000
@@ -128,6 +128,8 @@ Dbtup::Dbtup(Block_context& ctx, Uint32
   addRecSignal(GSN_DROP_FRAG_REQ, &Dbtup::execDROP_FRAG_REQ);
   addRecSignal(GSN_SUB_GCP_COMPLETE_REP, &Dbtup::execSUB_GCP_COMPLETE_REP);
 
+  addRecSignal(GSN_FIRE_TRIG_REQ, &Dbtup::execFIRE_TRIG_REQ);
+
   fragoperrec = 0;
   fragrecord = 0;
   alterTabOperRec = 0;

=== modified file 'storage/ndb/src/kernel/blocks/dbtup/DbtupTrigger.cpp'
--- a/storage/ndb/src/kernel/blocks/dbtup/DbtupTrigger.cpp	2011-02-03 14:20:36 +0000
+++ b/storage/ndb/src/kernel/blocks/dbtup/DbtupTrigger.cpp	2011-04-28 07:47:53 +0000
@@ -32,6 +32,7 @@
 #include <signaldata/DropTrigImpl.hpp>
 #include <signaldata/TuxMaint.hpp>
 #include <signaldata/AlterIndxImpl.hpp>
+#include "../dblqh/Dblqh.hpp"
 
 /* **************************************************************** */
 /* ---------------------------------------------------------------- */
@@ -523,6 +524,93 @@ Dbtup::dropTrigger(Tablerec* table, cons
   return 0;
 }//Dbtup::dropTrigger()
 
+void
+Dbtup::execFIRE_TRIG_REQ(Signal* signal)
+{
+  jam();
+  Uint32 opPtrI = signal->theData[0];
+  Uint32 pass = signal->theData[5];
+
+  FragrecordPtr regFragPtr;
+  OperationrecPtr regOperPtr;
+  TablerecPtr regTabPtr;
+  KeyReqStruct req_struct(this, (When)(KRS_PRE_COMMIT0 + pass));
+
+  regOperPtr.i = opPtrI;
+
+  jamEntry();
+
+  c_operation_pool.getPtr(regOperPtr);
+
+  regFragPtr.i = regOperPtr.p->fragmentPtr;
+  Uint32 no_of_fragrec = cnoOfFragrec;
+  ptrCheckGuard(regFragPtr, no_of_fragrec, fragrecord);
+
+  TransState trans_state = get_trans_state(regOperPtr.p);
+  ndbrequire(trans_state == TRANS_STARTED);
+
+  Uint32 no_of_tablerec = cnoOfTablerec;
+  regTabPtr.i = regFragPtr.p->fragTableId;
+  ptrCheckGuard(regTabPtr, no_of_tablerec, tablerec);
+
+  req_struct.signal = signal;
+  req_struct.TC_ref = signal->theData[1];
+  req_struct.TC_index = signal->theData[2];
+  req_struct.trans_id1 = signal->theData[3];
+  req_struct.trans_id2 = signal->theData[4];
+
+  PagePtr page;
+  Tuple_header* tuple_ptr = (Tuple_header*)
+    get_ptr(&page, &regOperPtr.p->m_tuple_location, regTabPtr.p);
+  req_struct.m_tuple_ptr = tuple_ptr;
+
+  OperationrecPtr lastOperPtr;
+  lastOperPtr.i = tuple_ptr->m_operation_ptr_i;
+  c_operation_pool.getPtr(lastOperPtr);
+
+  /**
+   * Deferred triggers should fire only once per primary key (per pass)
+   *   regardless of no of DML on that primary key
+   *
+   * We keep track of this on *last* operation (which btw, implies that
+   *   a trigger can't update "own" tuple...i.e first op would be better...)
+   *
+   */
+  if (!c_lqh->check_fire_trig_pass(lastOperPtr.p->userpointer, pass))
+  {
+    jam();
+    signal->theData[0] = 0;
+    signal->theData[1] = 0;
+    return;
+  }
+
+  /**
+   * This is deferred triggers...
+   *   which is basically the same as detached,
+   *     i.e before value is <before transaction>
+   *     and after values is <after transaction>
+   *   with the difference that they execute (fire) while
+   *   still having a transaction context...
+   *   i.e can abort transactions, modify transaction
+   */
+  req_struct.no_fired_triggers = 0;
+
+  /**
+   * See DbtupCommit re "Setting the op-list has this effect"
+   */
+  Uint32 save[2] = { lastOperPtr.p->nextActiveOp, lastOperPtr.p->prevActiveOp };
+  lastOperPtr.p->nextActiveOp = RNIL;
+  lastOperPtr.p->prevActiveOp = RNIL;
+
+  checkDeferredTriggers(&req_struct, lastOperPtr.p, regTabPtr.p, false);
+
+  lastOperPtr.p->nextActiveOp = save[0];
+  lastOperPtr.p->prevActiveOp = save[1];
+
+  signal->theData[0] = 0;
+  signal->theData[1] = req_struct.no_fired_triggers;
+}
+
 /* ---------------------------------------------------------------- */
 /* -------------- checkImmediateTriggersAfterOp ------------------ */
 /*                                                                  */
@@ -542,13 +630,24 @@ Dbtup::checkImmediateTriggersAfterInsert
     return;
   }
 
-  if ((regOperPtr->op_struct.primary_replica) &&
-      (!(regTablePtr->afterInsertTriggers.isEmpty()))) {
-    jam();
-    fireImmediateTriggers(req_struct,
-                          regTablePtr->afterInsertTriggers,
-                          regOperPtr,
-                          disk);
+  if (regOperPtr->op_struct.primary_replica)
+  {
+    if (! regTablePtr->afterInsertTriggers.isEmpty())
+    {
+      jam();
+      fireImmediateTriggers(req_struct,
+                            regTablePtr->afterInsertTriggers,
+                            regOperPtr,
+                            disk);
+    }
+
+    if (! regTablePtr->deferredInsertTriggers.isEmpty())
+    {
+      checkDeferredTriggersDuringPrepare(req_struct,
+                                         regTablePtr->deferredInsertTriggers,
+                                         regOperPtr,
+                                         disk);
+    }
   }
 }
 
@@ -562,21 +661,34 @@ Dbtup::checkImmediateTriggersAfterUpdate
     return;
   }
 
-  if ((regOperPtr->op_struct.primary_replica) &&
-      (!(regTablePtr->afterUpdateTriggers.isEmpty()))) {
-    jam();
-    fireImmediateTriggers(req_struct,
-                          regTablePtr->afterUpdateTriggers,
-                          regOperPtr,
-                          disk);
-  }
-  if ((regOperPtr->op_struct.primary_replica) &&
-      (!(regTablePtr->constraintUpdateTriggers.isEmpty()))) {
-    jam();
-    fireImmediateTriggers(req_struct,
-                          regTablePtr->constraintUpdateTriggers,
-                          regOperPtr,
-                          disk);
+  if (regOperPtr->op_struct.primary_replica)
+  {
+    if (! regTablePtr->afterUpdateTriggers.isEmpty())
+    {
+      jam();
+      fireImmediateTriggers(req_struct,
+                            regTablePtr->afterUpdateTriggers,
+                            regOperPtr,
+                            disk);
+    }
+
+    if (! regTablePtr->constraintUpdateTriggers.isEmpty())
+    {
+      jam();
+      fireImmediateTriggers(req_struct,
+                            regTablePtr->constraintUpdateTriggers,
+                            regOperPtr,
+                            disk);
+    }
+
+    if (! regTablePtr->deferredUpdateTriggers.isEmpty())
+    {
+      jam();
+      checkDeferredTriggersDuringPrepare(req_struct,
+                                         regTablePtr->deferredUpdateTriggers,
+                                         regOperPtr,
+                                         disk);
+    }
   }
 }
 
@@ -590,17 +702,48 @@ Dbtup::checkImmediateTriggersAfterDelete
     return;
   }
 
-  if ((regOperPtr->op_struct.primary_replica) &&
-      (!(regTablePtr->afterDeleteTriggers.isEmpty()))) {
+  if (regOperPtr->op_struct.primary_replica)
+  {
+    if (! regTablePtr->afterDeleteTriggers.isEmpty())
+    {
+      fireImmediateTriggers(req_struct,
+                            regTablePtr->afterDeleteTriggers,
+                            regOperPtr,
+                            disk);
+    }
+
+    if (! regTablePtr->deferredDeleteTriggers.isEmpty())
+    {
+      checkDeferredTriggersDuringPrepare(req_struct,
+                                         regTablePtr->deferredDeleteTriggers,
+                                         regOperPtr,
+                                         disk);
+    }
+  }
+}
+
+void
+Dbtup::checkDeferredTriggersDuringPrepare(KeyReqStruct *req_struct,
+                                          DLList<TupTriggerData>& triggerList,
+                                          Operationrec* const regOperPtr,
+                                          bool disk)
+{
+  jam();
+  TriggerPtr trigPtr;
+  triggerList.first(trigPtr);
+  while (trigPtr.i != RNIL)
+  {
     jam();
-    executeTriggers(req_struct,
-                    regTablePtr->afterDeleteTriggers,
-                    regOperPtr,
-                    disk);
+    if (trigPtr.p->monitorAllAttributes ||
+        trigPtr.p->attributeMask.overlaps(req_struct->changeMask))
+    {
+      jam();
+      NoOfFiredTriggers::setDeferredBit(req_struct->no_fired_triggers);
+      return;
+    }
   }
 }
 
-#if 0
 /* ---------------------------------------------------------------- */
 /* --------------------- checkDeferredTriggers -------------------- */
 /*                                                                  */
@@ -610,14 +753,95 @@ Dbtup::checkImmediateTriggersAfterDelete
 /* Executes deferred triggers by sending FIRETRIGORD                */
 /*                                                                  */
 /* ---------------------------------------------------------------- */
-void Dbtup::checkDeferredTriggers(Signal* signal, 
-                                  Operationrec* const regOperPtr,
-                                  Tablerec* const regTablePtr)
+void Dbtup::checkDeferredTriggers(KeyReqStruct *req_struct,
+                                  Operationrec* regOperPtr,
+                                  Tablerec* regTablePtr,
+                                  bool disk)
 {
   jam();
-  // NYI
+  Uint32 save_type = regOperPtr->op_struct.op_type;
+  Tuple_header *save_ptr = req_struct->m_tuple_ptr;
+  DLList<TupTriggerData> * deferred_list = 0;
+  DLList<TupTriggerData> * constraint_list = 0;
+
+  switch (save_type) {
+  case ZUPDATE:
+  case ZINSERT:
+    req_struct->m_tuple_ptr =get_copy_tuple(&regOperPtr->m_copy_tuple_location);
+    break;
+  }
+
+  /**
+   * Set correct operation type and fix change mask
+   * Note ALLOC is set in "orig" tuple
+   */
+  if (save_ptr->m_header_bits & Tuple_header::ALLOC) {
+    if (save_type == ZDELETE) {
+      // insert + delete = nothing
+      jam();
+      return;
+      goto end;
+    }
+    regOperPtr->op_struct.op_type = ZINSERT;
+  }
+  else if (save_type == ZINSERT) {
+    /**
+     * Tuple was not created but last op is INSERT.
+     * This is possible only on DELETE + INSERT
+     */
+    regOperPtr->op_struct.op_type = ZUPDATE;
+  }
+
+  switch(regOperPtr->op_struct.op_type) {
+  case(ZINSERT):
+    jam();
+    deferred_list = &regTablePtr->deferredInsertTriggers;
+    constraint_list = &regTablePtr->afterInsertTriggers;
+    break;
+  case(ZDELETE):
+    jam();
+    deferred_list = &regTablePtr->deferredDeleteTriggers;
+    constraint_list = &regTablePtr->afterDeleteTriggers;
+    break;
+  case(ZUPDATE):
+    jam();
+    deferred_list = &regTablePtr->deferredUpdateTriggers;
+    constraint_list = &regTablePtr->afterUpdateTriggers;
+    break;
+  default:
+    ndbrequire(false);
+    break;
+  }
+
+  if (req_struct->m_deferred_constraints == false)
+  {
+    constraint_list = 0;
+  }
+
+  if (deferred_list->isEmpty() &&
+      (constraint_list == 0 || constraint_list->isEmpty()))
+  {
+    goto end;
+  }
+
+  /**
+   * Compute change-mask
+   */
+  set_commit_change_mask_info(regTablePtr, req_struct, regOperPtr);
+  if (!deferred_list->isEmpty())
+  {
+    fireDeferredTriggers(req_struct, * deferred_list, regOperPtr, disk);
+  }
+
+  if (constraint_list && !constraint_list->isEmpty())
+  {
+    fireDeferredConstraints(req_struct, * constraint_list, regOperPtr, disk);
+  }
+
+end:
+  regOperPtr->op_struct.op_type = save_type;
+  req_struct->m_tuple_ptr = save_ptr;
 }//Dbtup::checkDeferredTriggers()
-#endif
 
 /* ---------------------------------------------------------------- */
 /* --------------------- checkDetachedTriggers -------------------- */
@@ -716,6 +940,13 @@ end:
   req_struct->m_tuple_ptr = save_ptr;
 }
 
+static
+bool
+is_constraint(const Dbtup::TupTriggerData * trigPtr)
+{
+  return trigPtr->triggerType == TriggerType::SECONDARY_INDEX;
+}
+
 void 
 Dbtup::fireImmediateTriggers(KeyReqStruct *req_struct,
                              DLList<TupTriggerData>& triggerList, 
@@ -729,6 +960,38 @@ Dbtup::fireImmediateTriggers(KeyReqStruc
     if (trigPtr.p->monitorAllAttributes ||
         trigPtr.p->attributeMask.overlaps(req_struct->changeMask)) {
       jam();
+
+      if (req_struct->m_when == KRS_PREPARE &&
+          req_struct->m_deferred_constraints &&
+          is_constraint(trigPtr.p))
+      {
+        NoOfFiredTriggers::setDeferredBit(req_struct->no_fired_triggers);
+      }
+      else
+      {
+        executeTrigger(req_struct,
+                       trigPtr.p,
+                       regOperPtr,
+                       disk);
+      }
+    }
+    triggerList.next(trigPtr);
+  }//while
+}//Dbtup::fireImmediateTriggers()
+
+void
+Dbtup::fireDeferredConstraints(KeyReqStruct *req_struct,
+                               DLList<TupTriggerData>& triggerList,
+                               Operationrec* const regOperPtr,
+                               bool disk)
+{
+  TriggerPtr trigPtr;
+  triggerList.first(trigPtr);
+  while (trigPtr.i != RNIL) {
+    jam();
+    if (trigPtr.p->monitorAllAttributes ||
+        trigPtr.p->attributeMask.overlaps(req_struct->changeMask)) {
+      jam();
       executeTrigger(req_struct,
                      trigPtr.p,
                      regOperPtr,
@@ -736,14 +999,13 @@ Dbtup::fireImmediateTriggers(KeyReqStruc
     }//if
     triggerList.next(trigPtr);
   }//while
-}//Dbtup::fireImmediateTriggers()
+}//Dbtup::fireDeferredTriggers()
 
-#if 0
-void 
-Dbtup::fireDeferredTriggers(Signal* signal,
-                            KeyReqStruct *req_struct,
-                            DLList<TupTriggerData>& triggerList, 
-                            Operationrec* const regOperPtr)
+void
+Dbtup::fireDeferredTriggers(KeyReqStruct *req_struct,
+                            DLList<TupTriggerData>& triggerList,
+                            Operationrec* const regOperPtr,
+                            bool disk)
 {
   TriggerPtr trigPtr;
   triggerList.first(trigPtr);
@@ -753,13 +1015,13 @@ Dbtup::fireDeferredTriggers(Signal* sign
         trigPtr.p->attributeMask.overlaps(req_struct->changeMask)) {
       jam();
       executeTrigger(req_struct,
-                     trigPtr,
-                     regOperPtr);
+                     trigPtr.p,
+                     regOperPtr,
+                     disk);
     }//if
     triggerList.next(trigPtr);
   }//while
 }//Dbtup::fireDeferredTriggers()
-#endif
 
 void 
 Dbtup::fireDetachedTriggers(KeyReqStruct *req_struct,
@@ -1064,6 +1326,44 @@ out:
     return;
   }
 
+  if (triggerType == TriggerType::SECONDARY_INDEX &&
+      req_struct->m_when != KRS_PREPARE)
+  {
+    ndbrequire(req_struct->m_deferred_constraints);
+    if (req_struct->m_when == KRS_PRE_COMMIT0)
+    {
+      switch(regOperPtr->op_struct.op_type){
+      case ZINSERT:
+        NoOfFiredTriggers::setDeferredBit(req_struct->no_fired_triggers);
+        return;
+        break;
+      case ZUPDATE:
+        NoOfFiredTriggers::setDeferredBit(req_struct->no_fired_triggers);
+        noAfterWords = 0;
+        break;
+      case ZDELETE:
+        break;
+      default:
+        ndbrequire(false);
+      }
+    }
+    else
+    {
+      ndbrequire(req_struct->m_when == KRS_PRE_COMMIT1);
+      switch(regOperPtr->op_struct.op_type){
+      case ZINSERT:
+        break;
+      case ZUPDATE:
+        noBeforeWords = 0;
+        break;
+      case ZDELETE:
+        return;
+      default:
+        ndbrequire(false);
+      }
+    }
+  }
+
   req_struct->no_fired_triggers++;
 
   if (longsignal == false)

=== modified file 'storage/ndb/src/kernel/blocks/dbtux/DbtuxSearch.cpp'
--- a/storage/ndb/src/kernel/blocks/dbtux/DbtuxSearch.cpp	2011-04-25 16:46:59 +0000
+++ b/storage/ndb/src/kernel/blocks/dbtux/DbtuxSearch.cpp	2011-04-27 21:13:10 +0000
@@ -271,7 +271,6 @@ Dbtux::findPosToScan(Frag& frag, unsigne
   const int jdir = 1 - 2 * int(idir);
   int lo = -1;
   int hi = (int)currNode.getOccup();
-  int ret;
   while (hi - lo > 1) {
     jam();
     // hi - lo > 1 implies lo < j < hi

=== modified file 'storage/ndb/src/ndbapi/Ndb.cpp'
--- a/storage/ndb/src/ndbapi/Ndb.cpp	2011-04-13 19:33:59 +0000
+++ b/storage/ndb/src/ndbapi/Ndb.cpp	2011-04-27 10:48:16 +0000
@@ -38,7 +38,7 @@ void connect();
 
 Connect to any node which has no connection at the moment.
 ****************************************************************************/
-NdbTransaction* Ndb::doConnect(Uint32 tConNode) 
+NdbTransaction* Ndb::doConnect(Uint32 tConNode, Uint32 instance)
 {
   Uint32        tNode;
   Uint32        tAnyAlive = 0;
@@ -47,12 +47,12 @@ NdbTransaction* Ndb::doConnect(Uint32 tC
   DBUG_ENTER("Ndb::doConnect");
 
   if (tConNode != 0) {
-    TretCode = NDB_connect(tConNode);
+    TretCode = NDB_connect(tConNode, instance);
     if ((TretCode == 1) || (TretCode == 2)) {
 //****************************************************************************
 // We have connections now to the desired node. Return
 //****************************************************************************
-      DBUG_RETURN(getConnectedNdbTransaction(tConNode));
+      DBUG_RETURN(getConnectedNdbTransaction(tConNode, instance));
     } else if (TretCode < 0) {
       DBUG_RETURN(NULL);
     } else if (TretCode != 0) {
@@ -63,6 +63,7 @@ NdbTransaction* Ndb::doConnect(Uint32 tC
 // We will connect to any node. Make sure that we have connections to all
 // nodes.
 //****************************************************************************
+  Uint32 anyInstance = 0;
   if (theImpl->m_optimized_node_selection)
   {
     Ndb_cluster_connection_node_iter &node_iter= 
@@ -70,14 +71,14 @@ NdbTransaction* Ndb::doConnect(Uint32 tC
     theImpl->m_ndb_cluster_connection.init_get_next_node(node_iter);
     while ((tNode= theImpl->m_ndb_cluster_connection.get_next_node(node_iter)))
     {
-      TretCode= NDB_connect(tNode);
+      TretCode= NDB_connect(tNode, anyInstance);
       if ((TretCode == 1) ||
 	  (TretCode == 2))
       {
 //****************************************************************************
 // We have connections now to the desired node. Return
 //****************************************************************************
-	DBUG_RETURN(getConnectedNdbTransaction(tNode));
+	DBUG_RETURN(getConnectedNdbTransaction(tNode, anyInstance));
       } else if (TretCode < 0) {
         DBUG_RETURN(NULL);
       } else if (TretCode != 0) {
@@ -100,14 +101,14 @@ NdbTransaction* Ndb::doConnect(Uint32 tC
 
       Tcount++;
       tNode= theImpl->theDBnodes[theCurrentConnectIndex];
-      TretCode= NDB_connect(tNode);
+      TretCode= NDB_connect(tNode, anyInstance);
       if ((TretCode == 1) ||
 	  (TretCode == 2))
       {
 //****************************************************************************
 // We have connections now to the desired node. Return
 //****************************************************************************
-	DBUG_RETURN(getConnectedNdbTransaction(tNode));
+	DBUG_RETURN(getConnectedNdbTransaction(tNode, anyInstance));
       } else if (TretCode < 0) {
         DBUG_RETURN(NULL);
       } else if (TretCode != 0) {
@@ -132,7 +133,7 @@ NdbTransaction* Ndb::doConnect(Uint32 tC
 }
 
 int 
-Ndb::NDB_connect(Uint32 tNode) 
+Ndb::NDB_connect(Uint32 tNode, Uint32 instance)
 {
 //****************************************************************************
 // We will perform seize of a transaction record in DBTC in the specified node.
@@ -150,10 +151,35 @@ Ndb::NDB_connect(Uint32 tNode)
   }
 
   NdbTransaction * tConArray = theConnectionArray[tNode];
-  if (tConArray != NULL) {
+  if (instance != 0 && tConArray != 0)
+  {
+    NdbTransaction* prev = 0;
+    NdbTransaction* curr = tConArray;
+    while (curr)
+    {
+      if (refToInstance(curr->m_tcRef) == instance)
+      {
+        if (prev != 0)
+        {
+          prev->theNext = curr->theNext;
+          curr->theNext = tConArray;
+          theConnectionArray[tNode] = curr;
+        }
+        else
+        {
+          assert(curr == tConArray);
+        }
+        DBUG_RETURN(2);
+      }
+      prev = curr;
+      curr = curr->theNext;
+    }
+  }
+  else if (tConArray != NULL)
+  {
     DBUG_RETURN(2);
   }
-  
+
   NdbTransaction * tNdbCon = getNdbCon();	// Get free connection object.
   if (tNdbCon == NULL) {
     DBUG_RETURN(4);
@@ -173,6 +199,7 @@ Ndb::NDB_connect(Uint32 tNode)
 // Set connection pointer as NdbTransaction object
 //************************************************
   tSignal->setData(theMyRef, 2);	// Set my block reference
+  tSignal->setData(instance, 3);        // Set requested instance
   tNdbCon->Status(NdbTransaction::Connecting); // Set status to connecting
   Uint32 nodeSequence;
   tReturnCode= sendRecSignal(tNode, WAIT_TC_SEIZE, tSignal,
@@ -220,9 +247,36 @@ Ndb::NDB_connect(Uint32 tNode)
 }//Ndb::NDB_connect()
 
 NdbTransaction *
-Ndb::getConnectedNdbTransaction(Uint32 nodeId){
+Ndb::getConnectedNdbTransaction(Uint32 nodeId, Uint32 instance){
   NdbTransaction* next = theConnectionArray[nodeId];
+  if (instance != 0)
+  {
+    NdbTransaction * prev = 0;
+    while (next)
+    {
+      if (refToInstance(next->m_tcRef) == instance)
+      {
+        if (prev != 0)
+        {
+          assert(false); // Should have been moved in NDB_connect
+          prev->theNext = next->theNext;
+          goto found_middle;
+        }
+        else
+        {
+          assert(next == theConnectionArray[nodeId]);
+          goto found_first;
+        }
+      }
+      prev = next;
+      next = next->theNext;
+    }
+    assert(false); // !!
+    return 0;
+  }
+found_first:
   theConnectionArray[nodeId] = next->theNext;
+found_middle:
   next->theNext = NULL;
 
   return next;
@@ -703,7 +757,7 @@ Ndb::startTransaction(const NdbDictionar
     
     theImpl->incClientStat(TransStartCount, 1);
 
-    NdbTransaction *trans= startTransactionLocal(0, nodeId);
+    NdbTransaction *trans= startTransactionLocal(0, nodeId, 0);
     DBUG_PRINT("exit",("start trans: 0x%lx  transid: 0x%lx",
                        (long) trans,
                        (long) (trans ? trans->getTransactionId() : 0)));
@@ -772,7 +826,7 @@ Ndb::startTransaction(const NdbDictionar
     theImpl->incClientStat( TransStartCount, 1 );
 
     {
-      NdbTransaction *trans= startTransactionLocal(0, nodeId);
+      NdbTransaction *trans= startTransactionLocal(0, nodeId, 0);
       DBUG_PRINT("exit",("start trans: 0x%lx  transid: 0x%lx",
 			 (long) trans,
                          (long) (trans ? trans->getTransactionId() : 0)));
@@ -808,7 +862,9 @@ Ndb::hupp(NdbTransaction* pBuddyTrans)
     checkFailedNode();
 
     Uint32 nodeId = pBuddyTrans->getConnectedNodeId();
-    NdbTransaction* pCon = startTransactionLocal(aPriority, nodeId);
+    NdbTransaction* pCon =
+      startTransactionLocal(aPriority, nodeId,
+                            refToInstance(pBuddyTrans->m_tcRef));
     if(pCon == NULL)
       DBUG_RETURN(NULL);
 
@@ -831,8 +887,8 @@ Ndb::hupp(NdbTransaction* pBuddyTrans)
   }//if
 }//Ndb::hupp()
 
-NdbTransaction* 
-Ndb::startTransactionLocal(Uint32 aPriority, Uint32 nodeId)
+NdbTransaction*
+Ndb::startTransactionLocal(Uint32 aPriority, Uint32 nodeId, Uint32 instance)
 {
 #ifdef VM_TRACE
   char buf[255];
@@ -853,7 +909,7 @@ Ndb::startTransactionLocal(Uint32 aPrior
   
   NdbTransaction* tConnection;
   Uint64 tFirstTransId = theFirstTransId;
-  tConnection = doConnect(nodeId);
+  tConnection = doConnect(nodeId, instance);
   if (tConnection == NULL) {
     DBUG_RETURN(NULL);
   }//if

=== modified file 'storage/ndb/src/ndbapi/NdbApiSignal.cpp'
--- a/storage/ndb/src/ndbapi/NdbApiSignal.cpp	2011-02-10 07:55:45 +0000
+++ b/storage/ndb/src/ndbapi/NdbApiSignal.cpp	2011-04-27 10:48:16 +0000
@@ -125,7 +125,7 @@ NdbApiSignal::setSignal(int aNdbSignalTy
       theTrace                = TestOrd::TraceAPI;
       theReceiversBlockNumber = DBTC;
       theVerId_signalNumber   = GSN_TCSEIZEREQ;
-      theLength               = 2;
+      theLength               = 3;
     }
     break;
 

=== modified file 'storage/ndb/src/ndbapi/NdbOperation.cpp'
--- a/storage/ndb/src/ndbapi/NdbOperation.cpp	2011-02-10 07:55:45 +0000
+++ b/storage/ndb/src/ndbapi/NdbOperation.cpp	2011-04-27 10:48:16 +0000
@@ -182,7 +182,7 @@ NdbOperation::init(const NdbTableImpl* t
     return -1;
   }
   theTCREQ = tSignal;
-  theTCREQ->setSignal(m_tcReqGSN, DBTC);
+  theTCREQ->setSignal(m_tcReqGSN, refToBlock(theNdbCon->m_tcRef));
 
   theAI_LenInCurrAI = 20;
   TcKeyReq * const tcKeyReq = CAST_PTR(TcKeyReq, theTCREQ->getDataPtrSend());

=== modified file 'storage/ndb/src/ndbapi/NdbOperationDefine.cpp'
--- a/storage/ndb/src/ndbapi/NdbOperationDefine.cpp	2011-02-10 07:55:45 +0000
+++ b/storage/ndb/src/ndbapi/NdbOperationDefine.cpp	2011-04-28 07:47:53 +0000
@@ -951,7 +951,7 @@ NdbOperation::insertATTRINFO( Uint32 aDa
     tAI_LenInCurrAI = 3;
     tSignal = tNdb->getSignal();
     if (tSignal != NULL) {
-      tSignal->setSignal(m_attrInfoGSN, DBTC);
+      tSignal->setSignal(m_attrInfoGSN, refToBlock(theNdbCon->m_tcRef));
       tAttrPtr = &tSignal->getDataPtrSend()[3];
       if (tFirstAttrinfo == NULL) {
         tSignal->next(NULL);
@@ -1008,7 +1008,7 @@ NdbOperation::insertATTRINFOloop(registe
       tAI_LenInCurrAI = 3;
       tSignal = tNdb->getSignal();
       if (tSignal != NULL) {
-        tSignal->setSignal(m_attrInfoGSN, DBTC);
+        tSignal->setSignal(m_attrInfoGSN, refToBlock(theNdbCon->m_tcRef));
         tAttrPtr = &tSignal->getDataPtrSend()[3];
         if (tFirstAttrinfo == NULL) {
           tSignal->next(NULL);
@@ -1404,5 +1404,10 @@ NdbOperation::handleOperationOptions (co
     op->m_flags &= ~Uint8(OF_QUEUEABLE);
   }
 
+  if (opts->optionsPresent & OperationOptions::OO_DEFERRED_CONSTAINTS)
+  {
+    op->m_flags |= OF_DEFERRED_CONSTRAINTS;
+  }
+
   return 0;
 }

=== modified file 'storage/ndb/src/ndbapi/NdbOperationExec.cpp'
--- a/storage/ndb/src/ndbapi/NdbOperationExec.cpp	2011-02-10 08:10:20 +0000
+++ b/storage/ndb/src/ndbapi/NdbOperationExec.cpp	2011-04-28 07:47:53 +0000
@@ -472,6 +472,7 @@ NdbOperation::prepareSend(Uint32 aTC_Con
   Uint8 tInterpretIndicator = theInterpretIndicator;
   Uint8 tNoDisk = (m_flags & OF_NO_DISK) != 0;
   Uint8 tQueable = (m_flags & OF_QUEUEABLE) != 0;
+  Uint8 tDeferred = (m_flags & OF_DEFERRED_CONSTRAINTS) != 0;
 
   /**
    * A dirty read, can not abort the transaction
@@ -490,6 +491,7 @@ NdbOperation::prepareSend(Uint32 aTC_Con
   tcKeyReq->setInterpretedFlag(tReqInfo, tInterpretIndicator);
   tcKeyReq->setNoDiskFlag(tReqInfo, tNoDisk);
   tcKeyReq->setQueueOnRedoProblemFlag(tReqInfo, tQueable);
+  tcKeyReq->setDeferredConstraints(tReqInfo, tDeferred);
 
   OperationType tOperationType = theOperationType;
   Uint8 abortOption = (ao == DefaultAbortOption) ? (Uint8) m_abortOption : (Uint8) ao;
@@ -1417,12 +1419,18 @@ NdbOperation::prepareSendNdbRecord(Abort
   m_abortOption= theSimpleIndicator && theOperationType==ReadRequest ?
     (Uint8) AO_IgnoreError : (Uint8) abortOption;
 
+  Uint8 tQueable = (m_flags & OF_QUEUEABLE) != 0;
+  Uint8 tDeferred = (m_flags & OF_DEFERRED_CONSTRAINTS) != 0;
+
   TcKeyReq::setAbortOption(tcKeyReq->requestInfo, m_abortOption);
   TcKeyReq::setCommitFlag(tcKeyReq->requestInfo, theCommitIndicator);
   TcKeyReq::setStartFlag(tcKeyReq->requestInfo, theStartIndicator);
   TcKeyReq::setSimpleFlag(tcKeyReq->requestInfo, theSimpleIndicator);
   TcKeyReq::setDirtyFlag(tcKeyReq->requestInfo, theDirtyIndicator);
 
+  TcKeyReq::setQueueOnRedoProblemFlag(tcKeyReq->requestInfo, tQueable);
+  TcKeyReq::setDeferredConstraints(tcKeyReq->requestInfo, tDeferred);
+
   theStatus= WaitResponse;
   theReceiver.prepareSend();
 

=== modified file 'storage/ndb/src/ndbapi/NdbOperationSearch.cpp'
--- a/storage/ndb/src/ndbapi/NdbOperationSearch.cpp	2011-02-10 07:55:45 +0000
+++ b/storage/ndb/src/ndbapi/NdbOperationSearch.cpp	2011-04-27 10:48:16 +0000
@@ -381,7 +381,7 @@ NdbOperation::insertKEYINFO(const char*
       setErrorCodeAbort(4000);
       return -1;
     }
-    if (tSignal->setSignal(m_keyInfoGSN, DBTC) == -1)
+    if (tSignal->setSignal(m_keyInfoGSN, refToBlock(theNdbCon->m_tcRef)) == -1)
     {
       setErrorCodeAbort(4001);
       return -1;

=== modified file 'storage/ndb/src/ndbapi/NdbQueryOperation.cpp'
--- a/storage/ndb/src/ndbapi/NdbQueryOperation.cpp	2011-04-06 14:16:13 +0000
+++ b/storage/ndb/src/ndbapi/NdbQueryOperation.cpp	2011-04-27 10:48:16 +0000
@@ -2598,7 +2598,7 @@ NdbQueryImpl::doSend(int nodeId, bool la
     assert (root.getMaxBatchRows() > 0);
 
     NdbApiSignal tSignal(&ndb);
-    tSignal.setSignal(GSN_SCAN_TABREQ, DBTC);
+    tSignal.setSignal(GSN_SCAN_TABREQ, refToBlock(m_scanTransaction->m_tcRef));
 
     ScanTabReq * const scanTabReq = CAST_PTR(ScanTabReq, tSignal.getDataPtrSend());
     Uint32 reqInfo = 0;
@@ -2699,7 +2699,7 @@ NdbQueryImpl::doSend(int nodeId, bool la
   } else {  // Lookup query
 
     NdbApiSignal tSignal(&ndb);
-    tSignal.setSignal(GSN_TCKEYREQ, DBTC);
+    tSignal.setSignal(GSN_TCKEYREQ, refToBlock(m_transaction.m_tcRef));
 
     TcKeyReq * const tcKeyReq = CAST_PTR(TcKeyReq, tSignal.getDataPtrSend());
 
@@ -2844,7 +2844,7 @@ NdbQueryImpl::sendFetchMore(NdbRootFragm
 
   Ndb& ndb = *getNdbTransaction().getNdb();
   NdbApiSignal tSignal(&ndb);
-  tSignal.setSignal(GSN_SCAN_NEXTREQ, DBTC);
+  tSignal.setSignal(GSN_SCAN_NEXTREQ, refToBlock(m_scanTransaction->m_tcRef));
   ScanNextReq * const scanNextReq = 
     CAST_PTR(ScanNextReq, tSignal.getDataPtrSend());
   
@@ -2986,7 +2986,7 @@ NdbQueryImpl::sendClose(int nodeId)
 
   Ndb& ndb = *m_transaction.getNdb();
   NdbApiSignal tSignal(&ndb);
-  tSignal.setSignal(GSN_SCAN_NEXTREQ, DBTC);
+  tSignal.setSignal(GSN_SCAN_NEXTREQ, refToBlock(m_scanTransaction->m_tcRef));
   ScanNextReq * const scanNextReq = CAST_PTR(ScanNextReq, tSignal.getDataPtrSend());
 
   assert (m_scanTransaction);

=== modified file 'storage/ndb/src/ndbapi/NdbScanOperation.cpp'
--- a/storage/ndb/src/ndbapi/NdbScanOperation.cpp	2011-04-18 12:39:04 +0000
+++ b/storage/ndb/src/ndbapi/NdbScanOperation.cpp	2011-04-27 10:48:16 +0000
@@ -85,7 +85,7 @@ NdbScanOperation::init(const NdbTableImp
 {
   m_transConnection = myConnection;
 
-  if(NdbOperation::init(tab, NULL, false) != 0)
+  if (NdbOperation::init(tab, myConnection, false) != 0)
     return -1;
 
   theNdb->theRemainingStartTransactions++; // will be checked in hupp...
@@ -1411,7 +1411,7 @@ NdbScanOperation::processTableScanDefs(N
     return -1;
   }//if
   
-  theSCAN_TABREQ->setSignal(GSN_SCAN_TABREQ, DBTC);
+  theSCAN_TABREQ->setSignal(GSN_SCAN_TABREQ, refToBlock(theNdbCon->m_tcRef));
   ScanTabReq * req = CAST_PTR(ScanTabReq, theSCAN_TABREQ->getDataPtrSend());
   req->apiConnectPtr = theNdbCon->theTCConPtr;
   req->tableId = m_accessTable->m_id;
@@ -1977,7 +1977,7 @@ NdbScanOperation::send_next_scan(Uint32
 {
   if(cnt > 0){
     NdbApiSignal tSignal(theNdb->theMyRef);
-    tSignal.setSignal(GSN_SCAN_NEXTREQ, DBTC);
+    tSignal.setSignal(GSN_SCAN_NEXTREQ, refToBlock(theNdbCon->m_tcRef));
     
     Uint32* theData = tSignal.getDataPtrSend();
     theData[0] = theNdbCon->theTCConPtr;
@@ -2639,7 +2639,7 @@ NdbScanOperation::takeOverScanOp(Operati
     
     Uint32 left = len - i;
     while(tSignal && left > KeyInfo::DataLength){
-      tSignal->setSignal(GSN_KEYINFO, DBTC);
+      tSignal->setSignal(GSN_KEYINFO, refToBlock(pTrans->m_tcRef));
       tSignal->setLength(KeyInfo::MaxSignalLength);
       KeyInfo * keyInfo = CAST_PTR(KeyInfo, tSignal->getDataPtrSend());
       memcpy(keyInfo->keyData, src, 4 * KeyInfo::DataLength);
@@ -2652,7 +2652,7 @@ NdbScanOperation::takeOverScanOp(Operati
     }
     
     if(tSignal && left > 0){
-      tSignal->setSignal(GSN_KEYINFO, DBTC);
+      tSignal->setSignal(GSN_KEYINFO, refToBlock(pTrans->m_tcRef));
       tSignal->setLength(KeyInfo::HeaderLength + left);
       newOp->theLastKEYINFO = tSignal;
       KeyInfo * keyInfo = CAST_PTR(KeyInfo, tSignal->getDataPtrSend());
@@ -3796,7 +3796,7 @@ NdbIndexScanOperation::send_next_scan_or
   
   NdbReceiver* tRec = m_api_receivers[idx];
   NdbApiSignal tSignal(theNdb->theMyRef);
-  tSignal.setSignal(GSN_SCAN_NEXTREQ, DBTC);
+  tSignal.setSignal(GSN_SCAN_NEXTREQ, refToBlock(theNdbCon->m_tcRef));
   
   Uint32 last = m_sent_receivers_count;
   Uint32* theData = tSignal.getDataPtrSend();

=== modified file 'storage/ndb/src/ndbapi/NdbTransaction.cpp'
--- a/storage/ndb/src/ndbapi/NdbTransaction.cpp	2011-04-06 14:16:13 +0000
+++ b/storage/ndb/src/ndbapi/NdbTransaction.cpp	2011-04-27 10:48:16 +0000
@@ -84,7 +84,8 @@ NdbTransaction::NdbTransaction( Ndb* aNd
   pendingBlobReadBytes(0),
   pendingBlobWriteBytes(0),
   m_theFirstLockHandle(NULL),
-  m_theLastLockHandle(NULL)
+  m_theLastLockHandle(NULL),
+  m_tcRef(numberToRef(DBTC, 0))
 {
   theListState = NotInList;
   theError.code = 0;
@@ -960,7 +961,7 @@ NdbTransaction::sendTC_HBREP()		// Send
     return -1;
   }
 
-  if (tSignal->setSignal(GSN_TC_HBREP, DBTC) == -1) {
+  if (tSignal->setSignal(GSN_TC_HBREP, refToBlock(m_tcRef)) == -1) {
     return -1;
   }
 
@@ -1112,7 +1113,7 @@ NdbTransaction::sendROLLBACK()      // S
 
     tTransId1 = (Uint32) theTransactionId;
     tTransId2 = (Uint32) (theTransactionId >> 32);
-    tSignal.setSignal(GSN_TCROLLBACKREQ, DBTC);
+    tSignal.setSignal(GSN_TCROLLBACKREQ, refToBlock(m_tcRef));
     tSignal.setData(theTCConPtr, 1);
     tSignal.setData(tTransId1, 2);
     tSignal.setData(tTransId2, 3);
@@ -1165,7 +1166,7 @@ NdbTransaction::sendCOMMIT()    // Send
 
   tTransId1 = (Uint32) theTransactionId;
   tTransId2 = (Uint32) (theTransactionId >> 32);
-  tSignal.setSignal(GSN_TC_COMMITREQ, DBTC);
+  tSignal.setSignal(GSN_TC_COMMITREQ, refToBlock(m_tcRef));
   tSignal.setData(theTCConPtr, 1);
   tSignal.setData(tTransId1, 2);
   tSignal.setData(tTransId2, 3);
@@ -1835,6 +1836,17 @@ NdbTransaction::receiveTCSEIZECONF(const
   } else
   {
     theTCConPtr = (Uint32)aSignal->readData(2);
+    if (aSignal->getLength() >= 3)
+    {
+      m_tcRef = aSignal->readData(3);
+    }
+    else
+    {
+      m_tcRef = numberToRef(DBTC, theDBnode);
+    }
+
+    assert(m_tcRef == aSignal->theSendersBlockRef);
+
     theStatus = Connected;
   }
   return 0;

=== modified file 'storage/ndb/src/ndbapi/Ndbif.cpp'
--- a/storage/ndb/src/ndbapi/Ndbif.cpp	2011-04-06 14:16:13 +0000
+++ b/storage/ndb/src/ndbapi/Ndbif.cpp	2011-04-27 10:48:16 +0000
@@ -1437,7 +1437,7 @@ NdbTransaction::sendTC_COMMIT_ACK(NdbImp
 	   refToNode(aTCRef));
 #endif  
   aSignal->theTrace                = TestOrd::TraceAPI;
-  aSignal->theReceiversBlockNumber = DBTC;
+  aSignal->theReceiversBlockNumber = refToBlock(aTCRef);
   aSignal->theVerId_signalNumber   = GSN_TC_COMMIT_ACK;
   aSignal->theLength               = 2;
 

=== modified file 'storage/ndb/src/ndbapi/Ndblist.cpp'
--- a/storage/ndb/src/ndbapi/Ndblist.cpp	2011-02-10 07:55:45 +0000
+++ b/storage/ndb/src/ndbapi/Ndblist.cpp	2011-04-27 10:48:16 +0000
@@ -481,7 +481,7 @@ Ndb::releaseConnectToNdb(NdbTransaction*
 
   Uint32 node_id = a_con->getConnectedNodeId();
   Uint32 conn_seq = a_con->theNodeSequence;
-  tSignal.setSignal(GSN_TCRELEASEREQ, DBTC);
+  tSignal.setSignal(GSN_TCRELEASEREQ, refToBlock(a_con->m_tcRef));
   tSignal.setData((tConPtr = a_con->getTC_ConnectPtr()), 1);
   tSignal.setData(theMyRef, 2);
   tSignal.setData(a_con->ptr2int(), 3); 

=== modified file 'storage/ndb/src/ndbapi/ndberror.c'
--- a/storage/ndb/src/ndbapi/ndberror.c	2011-04-06 14:16:13 +0000
+++ b/storage/ndb/src/ndbapi/ndberror.c	2011-04-28 12:07:13 +0000
@@ -494,7 +494,7 @@ ErrorBundle ErrorCodes[] = {
 
   { 1300, DMEC, IE, "Undefined error" },
   { 1301, DMEC, IE, "Backup issued to not master (reissue command to master)" },
-  { 1302, DMEC, IE, "Out of backup record" },
+  { 1302, DMEC, AE, "A backup is already running" },
   { 1303, DMEC, IS, "Out of resources" },
   { 1304, DMEC, IE, "Sequence failure" },
   { 1305, DMEC, IE, "Backup definition not implemented" },

=== modified file 'storage/ndb/test/ndbapi/testIndex.cpp'
--- a/storage/ndb/test/ndbapi/testIndex.cpp	2011-04-14 16:29:07 +0000
+++ b/storage/ndb/test/ndbapi/testIndex.cpp	2011-04-28 07:47:53 +0000
@@ -2843,6 +2843,299 @@ runBug60851(NDBT_Context* ctx, NDBT_Step
   return NDBT_OK;
 }
 
+static
+const int
+deferred_errors[] = {
+  5064, 0,
+  5065, 0,
+  5066, 0,
+  5067, 0,
+  5068, 0,
+  5069, 0,
+  5070, 0,
+  5071, 0,
+  5072, 1,
+  8090, 0,
+  8091, 0,
+  8092, 2, // connected tc
+  0, 0 // trailer
+};
+
+int
+runTestDeferredError(NDBT_Context* ctx, NDBT_Step* step)
+{
+  NdbRestarter res;
+  Ndb* pNdb = GETNDB(step);
+  const NdbDictionary::Table* pTab = ctx->getTab();
+
+  const int rows = ctx->getNumRecords();
+
+  const NdbRecord * pRowRecord = pTab->getDefaultRecord();
+  CHK_RET_FAILED(pRowRecord != 0);
+
+  const Uint32 len = NdbDictionary::getRecordRowLength(pRowRecord);
+  Uint8 * pRow = new Uint8[len];
+
+  for (int i = 0; deferred_errors[i] != 0; i += 2)
+  {
+    const int errorno = deferred_errors[i];
+    const int nodefail = deferred_errors[i+1];
+
+    for (int j = 0; j<3; j++)
+    {
+      NdbTransaction* pTrans = pNdb->startTransaction();
+      CHK_RET_FAILED(pTrans != 0);
+
+      int nodeId =
+        nodefail == 0 ? 0 :
+        nodefail == 1 ? res.getNode(NdbRestarter::NS_RANDOM) :
+        nodefail == 2 ? pTrans->getConnectedNodeId() :
+        0;
+
+      ndbout_c("errorno: %u(nf: %u - %u) j: %u : %s", errorno,
+               nodefail, nodeId, j,
+               j == 0 ? "test before error insert" :
+               j == 1 ? "test with error insert" :
+               j == 2 ? "test after error insert" :
+               "");
+      if (j == 0 || j == 2)
+      {
+        // First time succeed
+        // Last time succeed
+      }
+      else if (nodefail == 0)
+      {
+        CHK_RET_FAILED(res.insertErrorInAllNodes(errorno) == 0);
+      }
+      else
+      {
+        int val2[] = { DumpStateOrd::CmvmiSetRestartOnErrorInsert, 1 };
+        CHK_RET_FAILED(res.dumpStateOneNode(nodeId, val2, 2) == 0);
+        CHK_RET_FAILED(res.insertErrorInNode(nodeId, errorno) == 0);
+      }
+
+      for (int rowNo = 0; rowNo < 100; rowNo++)
+      {
+        int rowId = rand() % rows;
+        bzero(pRow, len);
+
+        HugoCalculator calc(* pTab);
+        calc.setValues(pRow, pRowRecord, rowId, rand());
+
+        NdbOperation::OperationOptions opts;
+        bzero(&opts, sizeof(opts));
+        opts.optionsPresent =
+          NdbOperation::OperationOptions::OO_DEFERRED_CONSTAINTS;
+
+        const NdbOperation * pOp = pTrans->updateTuple(pRowRecord, (char*)pRow,
+                                                       pRowRecord, (char*)pRow,
+                                                       0,
+                                                       &opts,
+                                                       sizeof(opts));
+        CHK_RET_FAILED(pOp != 0);
+      }
+
+      int result = pTrans->execute(Commit, AO_IgnoreError);
+      if (j == 0 || j == 2)
+      {
+        CHK_RET_FAILED(result == 0);
+      }
+      else
+      {
+        CHK_RET_FAILED(result != 0);
+      }
+      pTrans->close();
+
+
+      if (j == 0 || j == 2)
+      {
+      }
+      else
+      {
+        if (nodefail)
+        {
+          ndbout_c("  waiting for %u to enter not-started", nodeId);
+          // Wait for a node to enter not-started
+          CHK_RET_FAILED(res.waitNodesNoStart(&nodeId, 1) == 0);
+
+          ndbout_c("  starting all");
+          CHK_RET_FAILED(res.startAll() == 0);
+          ndbout_c("  wait cluster started");
+          CHK_RET_FAILED(res.waitClusterStarted() == 0);
+          ndbout_c("  cluster started");
+        }
+        CHK_RET_FAILED(res.insertErrorInAllNodes(0) == 0);
+      }
+    }
+  }
+
+  delete [] pRow;
+
+  return NDBT_OK;
+}
+
+int
+runMixedDML(NDBT_Context* ctx, NDBT_Step* step)
+{
+  Ndb* pNdb = GETNDB(step);
+  const NdbDictionary::Table* pTab = ctx->getTab();
+
+  unsigned seed = (unsigned)NdbTick_CurrentMillisecond();
+
+  const int rows = ctx->getNumRecords();
+  const int loops = 10 * ctx->getNumLoops();
+  const int until_stopped = ctx->getProperty("UntilStopped");
+  const int deferred = ctx->getProperty("Deferred");
+  const int batch = ctx->getProperty("Batch", Uint32(50));
+
+  const NdbRecord * pRowRecord = pTab->getDefaultRecord();
+  CHK_RET_FAILED(pRowRecord != 0);
+
+  const Uint32 len = NdbDictionary::getRecordRowLength(pRowRecord);
+  Uint8 * pRow = new Uint8[len];
+
+  int count_ok = 0;
+  int count_failed = 0;
+  for (int i = 0; i < loops || (until_stopped && !ctx->isTestStopped()); i++)
+  {
+    NdbTransaction* pTrans = pNdb->startTransaction();
+    CHK_RET_FAILED(pTrans != 0);
+
+    int lastrow = 0;
+    int result = 0;
+    for (int rowNo = 0; rowNo < batch; rowNo++)
+    {
+      int left = rows - lastrow;
+      int rowId = lastrow;
+      if (left)
+      {
+        rowId += ndb_rand_r(&seed) % (left / 10 + 1);
+      }
+      else
+      {
+        break;
+      }
+      lastrow = rowId;
+
+      bzero(pRow, len);
+
+      HugoCalculator calc(* pTab);
+      calc.setValues(pRow, pRowRecord, rowId, rand());
+
+      NdbOperation::OperationOptions opts;
+      bzero(&opts, sizeof(opts));
+      if (deferred)
+      {
+        opts.optionsPresent =
+          NdbOperation::OperationOptions::OO_DEFERRED_CONSTAINTS;
+      }
+
+      const NdbOperation* pOp = 0;
+      switch(ndb_rand_r(&seed) % 3){
+      case 0:
+        pOp = pTrans->writeTuple(pRowRecord, (char*)pRow,
+                                 pRowRecord, (char*)pRow,
+                                 0,
+                                 &opts,
+                                 sizeof(opts));
+        break;
+      case 1:
+        pOp = pTrans->deleteTuple(pRowRecord, (char*)pRow,
+                                  pRowRecord, (char*)pRow,
+                                  0,
+                                  &opts,
+                                  sizeof(opts));
+        break;
+      case 2:
+        pOp = pTrans->updateTuple(pRowRecord, (char*)pRow,
+                                  pRowRecord, (char*)pRow,
+                                  0,
+                                  &opts,
+                                  sizeof(opts));
+        break;
+      }
+      CHK_RET_FAILED(pOp != 0);
+      result = pTrans->execute(NoCommit, AO_IgnoreError);
+      if (result != 0)
+      {
+        goto found_error;
+      }
+    }
+
+    result = pTrans->execute(Commit, AO_IgnoreError);
+    if (result != 0)
+    {
+  found_error:
+      count_failed++;
+      NdbError err = pTrans->getNdbError();
+      ndbout << err << endl;
+      CHK_RET_FAILED(err.code == 1235 ||
+                     err.code == 1236 ||
+                     err.code == 5066 ||
+                     err.status == NdbError::TemporaryError ||
+                     err.classification == NdbError::NoDataFound ||
+                     err.classification == NdbError::ConstraintViolation);
+    }
+    else
+    {
+      count_ok++;
+    }
+    pTrans->close();
+  }
+
+  ndbout_c("count_ok: %d count_failed: %d",
+           count_ok, count_failed);
+  delete [] pRow;
+
+  return NDBT_OK;
+}
+
+int
+runDeferredError(NDBT_Context* ctx, NDBT_Step* step)
+{
+  NdbRestarter res;
+
+  for (int l = 0; l<ctx->getNumLoops() && !ctx->isTestStopped(); l++)
+  {
+    for (int i = 0; deferred_errors[i] != 0 && !ctx->isTestStopped(); i += 2)
+    {
+      const int errorno = deferred_errors[i];
+      const int nodefail = deferred_errors[i+1];
+
+      int nodeId = res.getNode(NdbRestarter::NS_RANDOM);
+
+      ndbout_c("errorno: %u (nf: %u - %u)",
+               errorno,
+               nodefail, nodeId);
+
+      if (nodefail == 0)
+      {
+        CHK_RET_FAILED(res.insertErrorInNode(nodeId, errorno) == 0);
+        NdbSleep_MilliSleep(300);
+        CHK_RET_FAILED(res.insertErrorInNode(nodeId, errorno) == 0);
+      }
+      else
+      {
+        int val2[] = { DumpStateOrd::CmvmiSetRestartOnErrorInsert, 1 };
+        CHK_RET_FAILED(res.dumpStateOneNode(nodeId, val2, 2) == 0);
+        CHK_RET_FAILED(res.insertErrorInNode(nodeId, errorno) == 0);
+        ndbout_c("  waiting for %u to enter not-started", nodeId);
+        // Wait for a node to enter not-started
+        CHK_RET_FAILED(res.waitNodesNoStart(&nodeId, 1) == 0);
+
+        ndbout_c("  starting all");
+        CHK_RET_FAILED(res.startAll() == 0);
+        ndbout_c("  wait cluster started");
+        CHK_RET_FAILED(res.waitClusterStarted() == 0);
+        ndbout_c("  cluster started");
+      }
+    }
+  }
+
+  ctx->stopTest();
+  return NDBT_OK;
+}
+
 NDBT_TESTSUITE(testIndex);
 TESTCASE("CreateAll", 
 	 "Test that we can create all various indexes on each table\n"
@@ -3243,6 +3536,66 @@ TESTCASE("FireTrigOverload", ""){
   FINALIZER(runClearError);
   FINALIZER(createRandomIndex_Drop);
 }
+TESTCASE("DeferredError",
+         "Test with deferred unique index handling and error inserts")
+{
+  TC_PROPERTY("LoggedIndexes", Uint32(0));
+  TC_PROPERTY("OrderedIndex", Uint32(0));
+  INITIALIZER(createPkIndex);
+  INITIALIZER(runLoadTable);
+  STEP(runTestDeferredError);
+  FINALIZER(createPkIndex_Drop);
+}
+TESTCASE("DeferredMixedLoad",
+         "Test mixed load of DML with deferred indexes")
+{
+  TC_PROPERTY("LoggedIndexes", Uint32(0));
+  TC_PROPERTY("OrderedIndex", Uint32(0));
+  TC_PROPERTY("UntilStopped", Uint32(0));
+  TC_PROPERTY("Deferred", Uint32(1));
+  INITIALIZER(createPkIndex);
+  INITIALIZER(runLoadTable);
+  STEPS(runMixedDML, 10);
+  FINALIZER(createPkIndex_Drop);
+}
+TESTCASE("DeferredMixedLoadError",
+         "Test mixed load of DML with deferred indexes")
+{
+  TC_PROPERTY("LoggedIndexes", Uint32(0));
+  TC_PROPERTY("OrderedIndex", Uint32(0));
+  TC_PROPERTY("UntilStopped", Uint32(1));
+  TC_PROPERTY("Deferred", Uint32(1));
+  INITIALIZER(createPkIndex);
+  INITIALIZER(runLoadTable);
+  STEPS(runMixedDML, 4);
+  STEP(runDeferredError);
+  FINALIZER(createPkIndex_Drop);
+}
+TESTCASE("NF_DeferredMixed",
+         "Test mixed load of DML with deferred indexes")
+{
+  TC_PROPERTY("LoggedIndexes", Uint32(0));
+  TC_PROPERTY("OrderedIndex", Uint32(0));
+  TC_PROPERTY("UntilStopped", Uint32(1));
+  TC_PROPERTY("Deferred", Uint32(1));
+  INITIALIZER(createPkIndex);
+  INITIALIZER(runLoadTable);
+  STEPS(runMixedDML, 4);
+  STEP(runRestarts);
+  FINALIZER(createPkIndex_Drop);
+}
+TESTCASE("NF_Mixed",
+         "Test mixed load of DML")
+{
+  TC_PROPERTY("LoggedIndexes", Uint32(0));
+  TC_PROPERTY("OrderedIndex", Uint32(0));
+  TC_PROPERTY("UntilStopped", Uint32(1));
+  INITIALIZER(createPkIndex);
+  INITIALIZER(runLoadTable);
+  STEPS(runMixedDML, 4);
+  STEP(runRestarts);
+  FINALIZER(createPkIndex_Drop);
+}
 TESTCASE("Bug56829",
          "Return empty ordered index nodes to index fragment "
          "so that empty fragment pages can be freed"){

=== modified file 'storage/ndb/test/run-test/daily-basic-tests.txt'
--- a/storage/ndb/test/run-test/daily-basic-tests.txt	2011-04-18 12:48:10 +0000
+++ b/storage/ndb/test/run-test/daily-basic-tests.txt	2011-04-28 07:47:53 +0000
@@ -12,6 +12,26 @@
 # You should have received a copy of the GNU General Public License
 # along with this program; if not, write to the Free Software
 # Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301  USA
+max-time: 900
+cmd: testIndex
+args: -n DeferredError
+
+max-time: 900
+cmd: testIndex
+args: -n DeferredMixedLoad T1 T6 T13
+
+max-time: 900
+cmd: testIndex
+args: -n DeferredMixedLoadError T1 T6 T13
+
+max-time: 900
+cmd: testIndex
+args: -n NF_DeferredMixed T1 T6 T13
+
+max-time: 900
+cmd: testIndex
+args: -n NF_Mixed T1 T6 T13
+
 max-time: 600
 cmd: atrt-testBackup
 args: -n NFMaster T1

No bundle (reason: useless for push emails).
Thread
bzr push into mysql-5.1-telco-7.0 branch (pekka:4343 to 4346) Bug#11793592Pekka Nousiainen29 Apr