List:Commits« Previous MessageNext Message »
From:jonas oreland Date:September 1 2011 5:33pm
Subject:bzr push into mysql-5.1-telco-7.1 branch (jonas.oreland:4264 to 4265)
View as plain text  
 4265 jonas oreland	2011-09-01 [merge]
      ndb - merge 70 to 71

    modified:
      mysql-test/suite/ndb_rpl/r/ndb_rpl_conflict.result
      mysql-test/suite/ndb_rpl/t/ndb_rpl_conflict.test
      storage/ndb/src/ndbapi/NdbTransaction.cpp
      storage/ndb/test/ndbapi/testBlobs.cpp
      storage/ndb/test/run-test/daily-basic-tests.txt
      storage/ndb/tools/ndb_config.cpp
 4264 Maitrayi Sabaratnam	2011-09-01 [merge]
      Merge from 7.0

    modified:
      storage/ndb/include/kernel/signaldata/QueryTree.hpp
      storage/ndb/include/mgmapi/mgmapi_config_parameters.h
      storage/ndb/src/kernel/blocks/dbspj/DbspjMain.cpp
      storage/ndb/src/kernel/ndbd.cpp
      storage/ndb/src/kernel/vm/CMakeLists.txt
      storage/ndb/src/kernel/vm/Configuration.cpp
      storage/ndb/src/kernel/vm/Configuration.hpp
      storage/ndb/src/kernel/vm/Makefile.am
      storage/ndb/src/kernel/vm/mt.cpp
      storage/ndb/src/kernel/vm/mt_thr_config.cpp
      storage/ndb/src/kernel/vm/mt_thr_config.hpp
      storage/ndb/src/mgmsrv/MgmtSrvr.cpp
      storage/ndb/src/mgmsrv/Services.cpp
      storage/ndb/src/ndbapi/NdbQueryOperation.cpp
      storage/ndb/tools/ndb_config.cpp
=== modified file 'mysql-test/suite/ndb_rpl/r/ndb_rpl_conflict.result'
--- a/mysql-test/suite/ndb_rpl/r/ndb_rpl_conflict.result	2011-05-13 07:40:50 +0000
+++ b/mysql-test/suite/ndb_rpl/r/ndb_rpl_conflict.result	2011-09-01 15:12:11 +0000
@@ -66,6 +66,169 @@ select * from t1_max_delete_win;
 a	b	X
 delete from t1_old;
 delete from t1_max;
+drop table t1_old, t1_max, t1_max_delete_win;
+delete from t1_old$EX;
+delete from t1_max$EX;
+delete from t1_max_delete_win$EX;
+delete from t1_old$EX;
+delete from t1_max$EX;
+delete from t1_max_delete_win$EX;
+create table t1_old (a int primary key, b longtext, X int unsigned) engine = ndb;
+create table t1_max (a int primary key, b longtext, X int unsigned) engine = ndb;
+create table t1_max_delete_win (a int primary key, b longtext, X int unsigned) engine = ndb;
+"Test 3"
+insert into t1_old values (1, repeat('Initial X=1',1000), 1);
+insert into t1_max values (1, repeat('Initial X=1',1000), 1);
+insert into t1_max_delete_win values (1, repeat('Initial X=1',1000), 1);
+update t1_old set X = 2, b=repeat('Slave X=2',1001);
+update t1_max set X = 2, b=repeat('Slave X=2',1001);
+update t1_max_delete_win set X = 2, b=repeat('Slave X=2',1001);
+update t1_old set X = 3, b=repeat('Master X=3',1002);
+update t1_max set X = 3, b=repeat('Master X=3',1002);
+update t1_max_delete_win set X = 3, b=repeat('Master X=3',1002);
+"Expect t1_old to contain slave row, and t1_max* to contain master row"
+select a, left(b, 20), length(b), X from t1_old;
+a	left(b, 20)	length(b)	X
+1	Slave X=2Slave X=2Sl	9009	2
+select a, left(b, 20), length(b), X from t1_max;
+a	left(b, 20)	length(b)	X
+1	Master X=3Master X=3	10020	3
+select a, left(b, 20), length(b), X from t1_max_delete_win;
+a	left(b, 20)	length(b)	X
+1	Master X=3Master X=3	10020	3
+Expect t1_old to have 1 entry, and t1_max* to have no entries
+select server_id, master_server_id, count, a from t1_old$EX order by count;
+server_id	master_server_id	count	a
+2	1	1	1
+select server_id, master_server_id, count, a from t1_max$EX order by count;
+server_id	master_server_id	count	a
+select server_id, master_server_id, count, a from t1_max_delete_win$EX order by count;
+server_id	master_server_id	count	a
+delete from t1_max$EX;
+delete from t1_max_delete_win$EX;
+delete from t1_old$EX;
+update t1_old set X = 3, b=repeat('Master X=3', 1002);
+"Test 4"
+update t1_old set X = 4, b=repeat('Slave X=4',2000);
+update t1_max set X = 4, b=repeat('Slave X=4',2000);
+update t1_max_delete_win set X = 4, b=repeat('Slave X=4',2000);
+delete from t1_old;
+delete from t1_max;
+delete from t1_max_delete_win;
+"Expect t1_old and t1_max to contain slave row, and t1_max_delete_win to be empty(as master)"
+select a, left(b, 20), length(b), X from t1_old;
+a	left(b, 20)	length(b)	X
+1	Slave X=4Slave X=4Sl	18000	4
+select a, left(b, 20), length(b), X from t1_max;
+a	left(b, 20)	length(b)	X
+1	Slave X=4Slave X=4Sl	18000	4
+select a, left(b, 20), length(b), X from t1_max_delete_win;
+a	left(b, 20)	length(b)	X
+Expect t1_old and t1_max to contain 1 entry, and t1_max_delete_win to be empty
+select server_id, master_server_id, count, a from t1_old$EX order by count;
+server_id	master_server_id	count	a
+2	1	2	1
+select server_id, master_server_id, count, a from t1_max$EX order by count;
+server_id	master_server_id	count	a
+2	1	1	1
+select server_id, master_server_id, count, a from t1_max_delete_win$EX order by count;
+server_id	master_server_id	count	a
+delete from t1_max$EX;
+delete from t1_max_delete_win$EX;
+delete from t1_old$EX;
+delete from t1_old;
+delete from t1_max;
+delete from t1_max_delete_win;
+delete from t1_old;
+delete from t1_max;
+delete from t1_max_delete_win;
+"Test 5"
+Test that Updates affecting Blobs are rejected
+correctly on the slave
+drop table t1_max;
+create table t1_max (a int primary key, b int, c longtext, d longtext, X int unsigned) engine = ndb;
+insert into t1_max values (1, 1, repeat("B", 10000), repeat("E", 10001), 1);
+insert into t1_max values (2, 2, repeat("A", 10002), repeat("T", 10003), 1);
+update t1_max set X=20;
+Initial values on Slave
+select a,b,SHA1(c),length(c), SHA1(d), length(d), X from t1_max order by a;
+a	b	SHA1(c)	length(c)	SHA1(d)	length(d)	X
+1	1	4a222e18b539cdefbf0960eaa7f4362a4976e1e0	10000	9641d473ab1bd921263190eee074397084933e2d	10001	20
+2	2	f833241322c062495632923d74314a6a5c23034d	10002	2dad269dfa115f6c7e53e91a73251e597aab8fe9	10003	20
+Originate update which will be rejected
+update t1_max set c=repeat("Z", 10006), d=repeat("I", 10005), X=2 where a=1;
+Check slave has rejected due to lower version
+select a,b,SHA1(c),length(c), SHA1(d), length(d), X from t1_max order by a;
+a	b	SHA1(c)	length(c)	SHA1(d)	length(d)	X
+1	1	4a222e18b539cdefbf0960eaa7f4362a4976e1e0	10000	9641d473ab1bd921263190eee074397084933e2d	10001	20
+2	2	f833241322c062495632923d74314a6a5c23034d	10002	2dad269dfa115f6c7e53e91a73251e597aab8fe9	10003	20
+Originate delete which will be rejected (due to NDB-OLD) algorith
+delete from t1_max where a=1;
+Check slave has rejected due to before image mismatch
+select a,b,SHA1(c),length(c), SHA1(d), length(d), X from t1_max order by a;
+a	b	SHA1(c)	length(c)	SHA1(d)	length(d)	X
+1	1	4a222e18b539cdefbf0960eaa7f4362a4976e1e0	10000	9641d473ab1bd921263190eee074397084933e2d	10001	20
+2	2	f833241322c062495632923d74314a6a5c23034d	10002	2dad269dfa115f6c7e53e91a73251e597aab8fe9	10003	20
+Originate insert which will be rejected (as row exists)
+insert into t1_max values (1, 1, repeat("R", 10004), repeat("A", 10007), 1);
+Check slave has rejected due to row existing already
+select a,b,SHA1(c),length(c), SHA1(d), length(d), X from t1_max order by a;
+a	b	SHA1(c)	length(c)	SHA1(d)	length(d)	X
+1	1	4a222e18b539cdefbf0960eaa7f4362a4976e1e0	10000	9641d473ab1bd921263190eee074397084933e2d	10001	20
+2	2	f833241322c062495632923d74314a6a5c23034d	10002	2dad269dfa115f6c7e53e91a73251e597aab8fe9	10003	20
+Expect t1_max to have 3 entries
+select server_id, master_server_id, count, a from t1_old$EX order by count;
+server_id	master_server_id	count	a
+select server_id, master_server_id, count, a from t1_max$EX order by count;
+server_id	master_server_id	count	a
+2	1	1	1
+2	1	2	1
+2	1	3	1
+select server_id, master_server_id, count, a from t1_max_delete_win$EX order by count;
+server_id	master_server_id	count	a
+delete from t1_max$EX;
+delete from t1_max_delete_win$EX;
+delete from t1_old$EX;
+Test 6
+Check that non-Blob related operations in a batch with a Blob
+operation are still subject to conflict detection.
+
+insert into mysql.ndb_replication values ("test", "t2_max", 0, 7, "NDB$MAX(X)");
+create table `t2_max$EX`
+  (server_id int unsigned,
+master_server_id int unsigned,
+master_epoch bigint unsigned,
+count int unsigned,
+a int not null,
+primary key(server_id, master_server_id, master_epoch, count)) engine ndb;
+create table t2_max (a int primary key, b int, X bigint unsigned) engine=ndb;
+insert into t2_max values (1,1,10), (2,2,10), (3,3,10), (4,4,10), (5,5,10);
+Now issue a transaction with a successful Blob op, and unsuccessful
+non-Blob op.  Check that the Blob op succeeds, and the unsuccessful
+non-Blob op is handled as expected.
+begin;
+update t2_max set b=b+1, X=1 where a=3;
+update t1_max set c=repeat("R", 10008), d=repeat("A", 10009), X = 21 where a=1;
+commit;
+Contents on Slave
+Expect Blob data applied to t1_max, no update applied to t2_max
+select a,b,left(c,1), length(c), left(d,1), length(d), X from t1_max where a=1;
+a	b	left(c,1)	length(c)	left(d,1)	length(d)	X
+1	1	R	10008	A	10009	21
+select * from t2_max order by a;
+a	b	X
+1	1	10
+2	2	10
+3	3	10
+4	4	10
+5	5	10
+Expect No conflict in t1_max, 1 conflict in t2_max
+select server_id, master_server_id, count, a from t1_max$EX order by count;
+server_id	master_server_id	count	a
+select server_id, master_server_id, count, a from t2_max$EX order by count;
+server_id	master_server_id	count	a
+2	1	1	3
+drop table t2_max, t2_max$EX;
 "Cleanup"
 drop table mysql.ndb_replication;
 drop table t1_old, `t1_old$EX`, t1_max, `t1_max$EX`, t1_max_delete_win, `t1_max_delete_win$EX`;

=== modified file 'mysql-test/suite/ndb_rpl/t/ndb_rpl_conflict.test'
--- a/mysql-test/suite/ndb_rpl/t/ndb_rpl_conflict.test	2011-05-13 07:40:50 +0000
+++ b/mysql-test/suite/ndb_rpl/t/ndb_rpl_conflict.test	2011-09-01 15:12:11 +0000
@@ -105,6 +105,209 @@ select * from t1_max_delete_win;
 delete from t1_old;
 delete from t1_max;
 
+--connection master
+
+# Now test with Blobs
+drop table t1_old, t1_max, t1_max_delete_win;
+delete from t1_old$EX;
+delete from t1_max$EX;
+delete from t1_max_delete_win$EX;
+
+--sync_slave_with_master
+--connection slave
+# Delete on slave, as $EX table ops don't replicate
+delete from t1_old$EX;
+delete from t1_max$EX;
+delete from t1_max_delete_win$EX;
+
+--connection master
+
+create table t1_old (a int primary key, b longtext, X int unsigned) engine = ndb;
+create table t1_max (a int primary key, b longtext, X int unsigned) engine = ndb;
+create table t1_max_delete_win (a int primary key, b longtext, X int unsigned) engine = ndb;
+
+--sync_slave_with_master
+
+###############
+--echo "Test 3"
+
+--connection master
+insert into t1_old values (1, repeat('Initial X=1',1000), 1);
+insert into t1_max values (1, repeat('Initial X=1',1000), 1);
+insert into t1_max_delete_win values (1, repeat('Initial X=1',1000), 1);
+--sync_slave_with_master
+
+--connection slave
+update t1_old set X = 2, b=repeat('Slave X=2',1001);
+update t1_max set X = 2, b=repeat('Slave X=2',1001);
+update t1_max_delete_win set X = 2, b=repeat('Slave X=2',1001);
+
+--connection master
+update t1_old set X = 3, b=repeat('Master X=3',1002);
+update t1_max set X = 3, b=repeat('Master X=3',1002);
+update t1_max_delete_win set X = 3, b=repeat('Master X=3',1002);
+--sync_slave_with_master
+
+--connection slave
+--echo "Expect t1_old to contain slave row, and t1_max* to contain master row"
+select a, left(b, 20), length(b), X from t1_old;
+select a, left(b, 20), length(b), X from t1_max;
+select a, left(b, 20), length(b), X from t1_max_delete_win;
+
+--echo Expect t1_old to have 1 entry, and t1_max* to have no entries
+select server_id, master_server_id, count, a from t1_old$EX order by count;
+select server_id, master_server_id, count, a from t1_max$EX order by count;
+select server_id, master_server_id, count, a from t1_max_delete_win$EX order by count;
+
+delete from t1_max$EX;
+delete from t1_max_delete_win$EX;
+delete from t1_old$EX;
+
+# syncronize
+update t1_old set X = 3, b=repeat('Master X=3', 1002);
+
+###############
+--echo "Test 4"
+
+--connection slave
+update t1_old set X = 4, b=repeat('Slave X=4',2000);
+update t1_max set X = 4, b=repeat('Slave X=4',2000);
+update t1_max_delete_win set X = 4, b=repeat('Slave X=4',2000);
+
+--connection master
+delete from t1_old;
+delete from t1_max;
+delete from t1_max_delete_win;
+--sync_slave_with_master
+
+--connection slave
+--echo "Expect t1_old and t1_max to contain slave row, and t1_max_delete_win to be empty(as master)"
+select a, left(b, 20), length(b), X from t1_old;
+select a, left(b, 20), length(b), X from t1_max;
+select a, left(b, 20), length(b), X from t1_max_delete_win;
+
+--echo Expect t1_old and t1_max to contain 1 entry, and t1_max_delete_win to be empty
+select server_id, master_server_id, count, a from t1_old$EX order by count;
+select server_id, master_server_id, count, a from t1_max$EX order by count;
+select server_id, master_server_id, count, a from t1_max_delete_win$EX order by count;
+
+delete from t1_max$EX;
+delete from t1_max_delete_win$EX;
+delete from t1_old$EX;
+
+delete from t1_old;
+delete from t1_max;
+delete from t1_max_delete_win;
+
+--connection master
+delete from t1_old;
+delete from t1_max;
+delete from t1_max_delete_win;
+
+#################
+--echo "Test 5"
+
+--echo Test that Updates affecting Blobs are rejected
+--echo correctly on the slave
+drop table t1_max;
+create table t1_max (a int primary key, b int, c longtext, d longtext, X int unsigned) engine = ndb;
+
+insert into t1_max values (1, 1, repeat("B", 10000), repeat("E", 10001), 1);
+insert into t1_max values (2, 2, repeat("A", 10002), repeat("T", 10003), 1);
+
+--sync_slave_with_master
+--connection slave
+
+# Bump up tuple versions
+update t1_max set X=20;
+
+--echo Initial values on Slave
+select a,b,SHA1(c),length(c), SHA1(d), length(d), X from t1_max order by a;
+
+--connection master
+--echo Originate update which will be rejected
+update t1_max set c=repeat("Z", 10006), d=repeat("I", 10005), X=2 where a=1;
+
+--sync_slave_with_master
+--connection slave
+--echo Check slave has rejected due to lower version
+select a,b,SHA1(c),length(c), SHA1(d), length(d), X from t1_max order by a;
+
+--connection master
+--echo Originate delete which will be rejected (due to NDB-OLD) algorith
+delete from t1_max where a=1;
+
+--sync_slave_with_master
+--connection slave
+--echo Check slave has rejected due to before image mismatch
+select a,b,SHA1(c),length(c), SHA1(d), length(d), X from t1_max order by a;
+
+--connection master
+--echo Originate insert which will be rejected (as row exists)
+insert into t1_max values (1, 1, repeat("R", 10004), repeat("A", 10007), 1);
+
+--sync_slave_with_master
+--connection slave
+--echo Check slave has rejected due to row existing already
+select a,b,SHA1(c),length(c), SHA1(d), length(d), X from t1_max order by a;
+
+--echo Expect t1_max to have 3 entries
+select server_id, master_server_id, count, a from t1_old$EX order by count;
+select server_id, master_server_id, count, a from t1_max$EX order by count;
+select server_id, master_server_id, count, a from t1_max_delete_win$EX order by count;
+
+delete from t1_max$EX;
+delete from t1_max_delete_win$EX;
+delete from t1_old$EX;
+
+--connection master
+
+#######
+--echo Test 6
+--echo Check that non-Blob related operations in a batch with a Blob
+--echo operation are still subject to conflict detection.
+--echo
+insert into mysql.ndb_replication values ("test", "t2_max", 0, 7, "NDB$MAX(X)");
+
+create table `t2_max$EX`
+  (server_id int unsigned,
+   master_server_id int unsigned,
+   master_epoch bigint unsigned,
+   count int unsigned,
+   a int not null,
+   primary key(server_id, master_server_id, master_epoch, count)) engine ndb;
+
+create table t2_max (a int primary key, b int, X bigint unsigned) engine=ndb;
+
+insert into t2_max values (1,1,10), (2,2,10), (3,3,10), (4,4,10), (5,5,10);
+
+--sync_slave_with_master
+
+--connection master
+--echo Now issue a transaction with a successful Blob op, and unsuccessful
+--echo non-Blob op.  Check that the Blob op succeeds, and the unsuccessful
+--echo non-Blob op is handled as expected.
+
+begin;
+update t2_max set b=b+1, X=1 where a=3; # conflicts
+update t1_max set c=repeat("R", 10008), d=repeat("A", 10009), X = 21 where a=1; # ok
+commit;
+
+--sync_slave_with_master
+
+--connection slave
+--echo Contents on Slave
+--echo Expect Blob data applied to t1_max, no update applied to t2_max
+select a,b,left(c,1), length(c), left(d,1), length(d), X from t1_max where a=1;
+select * from t2_max order by a;
+
+--echo Expect No conflict in t1_max, 1 conflict in t2_max$EX
+select server_id, master_server_id, count, a from t1_max$EX order by count;
+select server_id, master_server_id, count, a from t2_max$EX order by count;
+
+--connection master
+drop table t2_max, t2_max$EX;
+
 
 ###############
 --echo "Cleanup"

=== modified file 'storage/ndb/src/ndbapi/NdbTransaction.cpp'
--- a/storage/ndb/src/ndbapi/NdbTransaction.cpp	2011-07-04 16:30:34 +0000
+++ b/storage/ndb/src/ndbapi/NdbTransaction.cpp	2011-09-01 17:32:07 +0000
@@ -290,7 +290,8 @@ NdbTransaction::execute(ExecType aTypeOf
 			NdbOperation::AbortOption abortOption,
 			int forceSend)
 {
-  NdbError savedError= theError;
+  NdbError existingTransError = theError;
+  NdbError firstTransError;
   DBUG_ENTER("NdbTransaction::execute");
   DBUG_PRINT("enter", ("aTypeOfExec: %d, abortOption: %d", 
 		       aTypeOfExec, abortOption));
@@ -374,8 +375,8 @@ NdbTransaction::execute(ExecType aTypeOf
           if (tBlob->preExecute(tExecType, batch) == -1)
 	  {
             ret = -1;
-	    if(savedError.code==0)
-	      savedError= theError;
+	    if (firstTransError.code==0)
+	      firstTransError= theError;
 	  }
           tBlob = tBlob->theNext;
         }
@@ -413,8 +414,8 @@ NdbTransaction::execute(ExecType aTypeOf
             if (tBlob->preCommit() == -1)
 	    {
 	      ret = -1;
-	      if(savedError.code==0)
-		savedError= theError;
+	      if (firstTransError.code==0)
+		firstTransError= theError;
 	    }
             tBlob = tBlob->theNext;
           }
@@ -440,8 +441,6 @@ NdbTransaction::execute(ExecType aTypeOf
 		       NdbOperation::DefaultAbortOption,
 		       forceSend) == -1)
     {
-      if(savedError.code==0)
-	savedError= theError;
       /**
        * We abort the execute here. But we still need to put the split-off
        * operation list back into the transaction object, or we will get a
@@ -463,9 +462,13 @@ NdbTransaction::execute(ExecType aTypeOf
           theCompletedLastOp = tCompletedLastOp;
       }
 
+      /* executeNoBlobs will have set transaction error */
       DBUG_RETURN(-1);
     }
 
+    /* Capture any trans error left by the execute() in case it gets trampled */
+    if (firstTransError.code==0)
+      firstTransError= theError;
 
 #ifdef ndb_api_crash_on_complex_blob_abort
     assert(theFirstOpInList == NULL && theLastOpInList == NULL);
@@ -483,8 +486,8 @@ NdbTransaction::execute(ExecType aTypeOf
             if (tBlob->postExecute(tExecType) == -1)
 	    {
               ret = -1;
-	      if(savedError.code==0)
-		savedError= theError;
+	      if (firstTransError.code==0)
+		firstTransError= theError;
 	    }
             tBlob = tBlob->theNext;
           }
@@ -520,8 +523,37 @@ NdbTransaction::execute(ExecType aTypeOf
   }
 #endif
 
-  if(savedError.code!=0 && theError.code==4350) // Trans already aborted
-      theError= savedError;
+  /* Sometimes the original error is trampled by 'Trans already aborted',
+   * detect this case and attempt to restore the original error
+   */
+  if (theError.code == 4350) // Trans already aborted
+  {
+    DBUG_PRINT("info", ("Trans already aborted, existingTransError.code %u, "
+                        "firstTransError.code %u",
+                        existingTransError.code,
+                        firstTransError.code));
+    if (existingTransError.code != 0)
+    {
+      theError = existingTransError;
+    }
+    else if (firstTransError.code != 0)
+    {
+      theError = firstTransError;
+    }
+  }
+
+  /* Generally return the first error which we encountered as
+   * the Trans error.  Caller can traverse the op list to
+   * get the full picture
+   */
+  if (firstTransError.code != 0)
+  {
+    DBUG_PRINT("info", ("Setting error to first error.  firstTransError.code = %u, "
+                        "theError.code = %u",
+                        firstTransError.code,
+                        theError.code));
+    theError = firstTransError;
+  }
 
   DBUG_RETURN(ret);
 }

=== modified file 'storage/ndb/test/ndbapi/testBlobs.cpp'
--- a/storage/ndb/test/ndbapi/testBlobs.cpp	2011-06-30 15:59:25 +0000
+++ b/storage/ndb/test/ndbapi/testBlobs.cpp	2011-09-01 15:12:11 +0000
@@ -184,6 +184,7 @@ printusage()
     << "  -bug 27370  Potential inconsistent blob reads for ReadCommitted reads" << endl
     << "  -bug 36756  Handling execute(.., abortOption) and Blobs " << endl
     << "  -bug 45768  execute(Commit) after failing blob batch " << endl
+    << "  -bug 62321  Blob obscures ignored error codes in batch" << endl
     ;
 }
 
@@ -3860,6 +3861,124 @@ static int bugtest_48040()
 }
 
 
+static int bugtest_62321()
+{
+  /* Having a Blob operation in a batch with other operations
+   * causes the other operation's ignored error not to be
+   * set as the transaction error code after execution.
+   * This is used (e.g in MySQLD) to check for conflicts
+   */
+  DBG("bugtest_62321 : Error code from other ops in batch obscured");
+
+  /*
+     1) Setup table : 1 row exists, another doesnt
+     2) Start transaction
+     3) Define failing before op
+     4) Define Blob op with/without post-exec part
+     5) Define failing after op
+     6) Execute
+     7) Check results
+  */
+  calcTups(true);
+
+  /* Setup table */
+  Tup& tupExists = g_tups[0];
+  Tup& notExists = g_tups[1];
+  {
+    CHK((g_con= g_ndb->startTransaction()) != 0);
+    CHK((g_opr= g_con->getNdbOperation(g_opt.m_tname)) != 0);
+    CHK(g_opr->insertTuple() == 0);
+    CHK(g_opr->equal("PK1", tupExists.m_pk1) == 0);
+    if (g_opt.m_pk2chr.m_len != 0)
+    {
+      CHK(g_opr->equal("PK2", tupExists.m_pk2) == 0);
+      CHK(g_opr->equal("PK3", tupExists.m_pk3) == 0);
+    }
+    setUDpartId(tupExists, g_opr);
+    CHK(getBlobHandles(g_opr) == 0);
+
+    CHK(setBlobValue(tupExists) == 0);
+
+    CHK(g_con->execute(Commit) == 0);
+    g_con->close();
+  }
+
+  for (int scenario = 0; scenario < 4; scenario++)
+  {
+    DBG(" Scenario : " << scenario);
+    CHK((g_con= g_ndb->startTransaction()) != 0);
+    NdbOperation* failOp = NULL;
+    if ((scenario & 0x1) == 0)
+    {
+      DBG("  Fail op before");
+      /* Define failing op in batch before Blob op */
+      failOp= g_con->getNdbOperation(g_opt.m_tname);
+      CHK(failOp != 0);
+      CHK(failOp->readTuple() == 0);
+      CHK(failOp->equal("PK1", notExists.m_pk1) == 0);
+      if (g_opt.m_pk2chr.m_len != 0)
+      {
+        CHK(failOp->equal("PK2", notExists.m_pk2) == 0);
+        CHK(failOp->equal("PK3", notExists.m_pk3) == 0);
+      }
+      setUDpartId(notExists, failOp);
+      CHK(failOp->getValue("PK1") != 0);
+      CHK(failOp->setAbortOption(NdbOperation::AO_IgnoreError) == 0);
+    }
+
+    /* Now define successful Blob op */
+    CHK((g_opr= g_con->getNdbOperation(g_opt.m_tname)) != 0);
+    CHK(g_opr->readTuple() == 0);
+    CHK(g_opr->equal("PK1", tupExists.m_pk1) == 0);
+    if (g_opt.m_pk2chr.m_len != 0)
+    {
+      CHK(g_opr->equal("PK2", tupExists.m_pk2) == 0);
+      CHK(g_opr->equal("PK3", tupExists.m_pk3) == 0);
+    }
+    setUDpartId(tupExists, g_opr);
+    CHK(getBlobHandles(g_opr) == 0);
+
+    CHK(getBlobValue(tupExists) == 0);
+
+
+    /* Define failing batch op after Blob op if not defined before */
+    if (failOp == 0)
+    {
+      DBG("  Fail op after");
+      failOp= g_con->getNdbOperation(g_opt.m_tname);
+      CHK(failOp != 0);
+      CHK(failOp->readTuple() == 0);
+      CHK(failOp->equal("PK1", notExists.m_pk1) == 0);
+      if (g_opt.m_pk2chr.m_len != 0)
+      {
+        CHK(failOp->equal("PK2", notExists.m_pk2) == 0);
+        CHK(failOp->equal("PK3", notExists.m_pk3) == 0);
+      }
+      setUDpartId(notExists, failOp);
+      CHK(failOp->getValue("PK1") != 0);
+      CHK(failOp->setAbortOption(NdbOperation::AO_IgnoreError) == 0);
+    }
+
+    /* Now execute and check rc etc */
+    NdbTransaction::ExecType et = (scenario & 0x2) ?
+      NdbTransaction::NoCommit:
+      NdbTransaction::Commit;
+
+    DBG("  Executing with execType = " << ((et == NdbTransaction::NoCommit)?
+                                           "NoCommit":"Commit"));
+    int rc = g_con->execute(NdbTransaction::NoCommit);
+
+    CHK(rc == 0);
+    CHK(g_con->getNdbError().code == 626);
+    CHK(failOp->getNdbError().code == 626);
+    CHK(g_opr->getNdbError().code == 0);
+    DBG("  Error code on transaction as expected");
+
+    g_con->close();
+  }
+
+  return 0;
+}
 
 // main
 
@@ -4824,7 +4943,8 @@ static struct {
   { 36756, bugtest_36756 },
   { 45768, bugtest_45768 },
   { 48040, bugtest_48040 },
-  { 28116, bugtest_28116 }
+  { 28116, bugtest_28116 },
+  { 62321, bugtest_62321 }
 };
 
 NDB_COMMAND(testOdbcDriver, "testBlobs", "testBlobs", "testBlobs", 65535)

=== modified file 'storage/ndb/test/run-test/daily-basic-tests.txt'
--- a/storage/ndb/test/run-test/daily-basic-tests.txt	2011-06-28 08:47:18 +0000
+++ b/storage/ndb/test/run-test/daily-basic-tests.txt	2011-09-01 15:12:11 +0000
@@ -1740,3 +1740,8 @@ max-time: 300
 cmd: testIndexStat
 args:
 
+max-time: 300
+cmd: testBlobs
+args: -bug 62321 -skip p
+
+

=== modified file 'storage/ndb/tools/ndb_config.cpp'
--- a/storage/ndb/tools/ndb_config.cpp	2011-09-01 13:09:24 +0000
+++ b/storage/ndb/tools/ndb_config.cpp	2011-09-01 17:32:07 +0000
@@ -228,7 +228,7 @@ main(int argc, char** argv){
   }
 
   if ((g_nodes && g_connections) ||
-       g_system && (g_nodes || g_connections))
+      (g_system && (g_nodes || g_connections)))
   {
     fprintf(stderr,
 	    "Error: Only one of the section-options: --nodes, --connections, --system is allowed.\n");
@@ -241,7 +241,7 @@ main(int argc, char** argv){
    */
 
   if ((g_config_file && g_mycnf) ||
-       g_config_from_node && (g_config_file || g_mycnf))
+      ((g_config_from_node != INT_MIN) && (g_config_file || g_mycnf)))
   {
     fprintf(stderr,
 	    "Error: Config should be retrieved from only one of the following sources:\n");

No bundle (reason: useless for push emails).
Thread
bzr push into mysql-5.1-telco-7.1 branch (jonas.oreland:4264 to 4265) jonas oreland1 Sep