List:Commits« Previous MessageNext Message »
From:Frazer Clement Date:January 23 2012 3:34pm
Subject:bzr push into mysql-5.1-telco-7.0 branch (frazer.clement:4812 to 4813)
WL#6147
View as plain text  
 4813 Frazer Clement	2012-01-23
      CluB X.X commit for WL#6147

    added:
      sql/ndb_repl_tab.cc
      sql/ndb_repl_tab.h
      sql/ndb_utils.h
    modified:
      mysql-test/suite/ndb_rpl/r/ndb_rpl_rep_error.result
      mysql-test/suite/ndb_rpl/t/ndb_rpl_rep_error.test
      sql/Makefile.am
      sql/ha_ndbcluster.cc
      sql/ha_ndbcluster_binlog.cc
      sql/ha_ndbcluster_binlog.h
 4812 Jonas Oreland	2012-01-23
      ndb - try to fix compile error on win64 in CountingPool-t

    modified:
      storage/ndb/src/kernel/vm/CountingPool.cpp
=== modified file 'mysql-test/suite/ndb_rpl/r/ndb_rpl_rep_error.result'
--- a/mysql-test/suite/ndb_rpl/r/ndb_rpl_rep_error.result	2012-01-17 13:51:35 +0000
+++ b/mysql-test/suite/ndb_rpl/r/ndb_rpl_rep_error.result	2012-01-23 15:30:36 +0000
@@ -1,9 +1,51 @@
 include/master-slave.inc
 [connection master]
+Wrong schema for the table, too few pks
 create table t1 (a int key, X int) engine ndb;
 Warnings:
 Error	1626	Bad schema for mysql.ndb_replication table. Message: Wrong number of primary key parts, expected 3
 drop table t1;
+Wrong schema for the table, incorrect pk
+create table t1 (a int key, X int) engine ndb;
+Warnings:
+Error	1626	Bad schema for mysql.ndb_replication table. Message: Missing or wrong type for column 'server_id'
+drop table t1;
+Wrong schema for the table, binlog_type is signed
+create table t1 (a int key, X int) engine ndb;
+Warnings:
+Error	1626	Bad schema for mysql.ndb_replication table. Message: Missing or wrong type for column 'binlog_type'
+drop table t1;
+Wrong schema for the table, conflict_fn is too long
+create table t1 (a int key, X int) engine ndb;
+Warnings:
+Error	1626	Bad schema for mysql.ndb_replication table. Message: Missing or wrong type for column 'conflict_fn'
+drop table t1;
+Correct schema for the table but no conflict fn
+insert into mysql.ndb_replication values ("test", "t1", 0, 7);
+create table test.t1 (a int primary key) engine=ndb;
+show warnings;
+Level	Code	Message
+drop table test.t1;
+MySQLD error output for server 1.1 matching pattern %NDB Binlog: logging%
+relevant
+[note] ndb binlog: logging ./test/t1 (full,use_update)
+delete from mysql.ndb_replication;
+Check that NULL uses server defaults
+show variables like 'ndb_log_update_as_write';
+Variable_name	Value
+ndb_log_update_as_write	ON
+show variables like 'ndb_log_updated_only';
+Variable_name	Value
+ndb_log_updated_only	ON
+insert into mysql.ndb_replication values ("test", "t1", 0, NULL);
+create table test.t1 (a int primary key) engine=ndb;
+show warnings;
+Level	Code	Message
+drop table test.t1;
+MySQLD error output for server 1.1 matching pattern %NDB Binlog: logging%
+relevant
+[note] ndb binlog: logging ./test/t1 (updated,use_write)
+Correct schema for the table but other errors
 insert into mysql.ndb_replication values ("test", "t1", 0, NULL, "NDB$X(X)");
 create table t1 (a int key, X int) engine ndb;
 ERROR HY000: Can't create table 'test.t1' (errno: 1627)
@@ -34,3 +76,249 @@ Level	Code	Message
 Error	1627	Error in parsing conflict function. Message: NDB$MAX(X Y), missing ')' at 'Y)'
 Error	1005	Can't create table 'test.t1' (errno: 1627)
 delete from mysql.ndb_replication;
+show variables like 'server_id';
+Variable_name	Value
+server_id	1
+create database EuropeNorth;
+create database EuropeSouth;
+create database USNorth;
+create database USSouth;
+Basic wildcard tests
+Note that we put in bad conflict fn names so that the warnings generated
+when the table create fails give an indication of which ndb_replication
+table row was chosen.
+
+Wild serverid
+insert into mysql.ndb_replication values ("EuropeNorth", "France", 1, NULL, "NDB$A()");
+insert into mysql.ndb_replication values ("EuropeNorth", "France", 0, NULL, "NDB$B()");
+Should match specific entry (1) with algorithm A.
+create table EuropeNorth.France (a int primary key) engine=ndb;
+ERROR HY000: Can't create table 'EuropeNorth.France' (errno: 1627)
+show warnings;
+Level	Code	Message
+Error	1627	Error in parsing conflict function. Message: NDB$A(), unknown conflict resolution function at 'NDB$A()'
+Error	1005	Can't create table 'EuropeNorth.France' (errno: 1627)
+delete from mysql.ndb_replication where server_id=1;
+Should match generic entry (0) with algorthin B.
+create table EuropeNorth.France (a int primary key) engine=ndb;
+ERROR HY000: Can't create table 'EuropeNorth.France' (errno: 1627)
+show warnings;
+Level	Code	Message
+Error	1627	Error in parsing conflict function. Message: NDB$B(), unknown conflict resolution function at 'NDB$B()'
+Error	1005	Can't create table 'EuropeNorth.France' (errno: 1627)
+delete from mysql.ndb_replication;
+Wild table_name
+insert into mysql.ndb_replication values ("EuropeNorth", "Fr_nce", 1, NULL, "NDB$A()");
+insert into mysql.ndb_replication values ("EuropeNorth", "%any", 1, NULL, "NDB$B()");
+Should match specific entry (Fr_nce) with algorithm A.
+create table EuropeNorth.France (a int primary key) engine=ndb;
+ERROR HY000: Can't create table 'EuropeNorth.France' (errno: 1627)
+show warnings;
+Level	Code	Message
+Error	1627	Error in parsing conflict function. Message: NDB$A(), unknown conflict resolution function at 'NDB$A()'
+Error	1005	Can't create table 'EuropeNorth.France' (errno: 1627)
+Should match specific entry (%any) with algorithm B.
+create table EuropeNorth.Germany (a int primary key) engine=ndb;
+ERROR HY000: Can't create table 'EuropeNorth.Germany' (errno: 1627)
+show warnings;
+Level	Code	Message
+Error	1627	Error in parsing conflict function. Message: NDB$B(), unknown conflict resolution function at 'NDB$B()'
+Error	1005	Can't create table 'EuropeNorth.Germany' (errno: 1627)
+Should match specific entry (%any) with algorithm B.
+create table EuropeNorth.Romany (a int primary key) engine=ndb;
+ERROR HY000: Can't create table 'EuropeNorth.Romany' (errno: 1627)
+show warnings;
+Level	Code	Message
+Error	1627	Error in parsing conflict function. Message: NDB$B(), unknown conflict resolution function at 'NDB$B()'
+Error	1005	Can't create table 'EuropeNorth.Romany' (errno: 1627)
+No match, should be fine
+create table EuropeNorth.UK (a int primary key) engine=ndb;
+show warnings;
+Level	Code	Message
+drop table EuropeNorth.UK;
+delete from mysql.ndb_replication;
+Wild db
+insert into mysql.ndb_replication values ("%North", "Countries", 1, NULL, "NDB$A()");
+insert into mysql.ndb_replication values ("%South", "Countries", 1, NULL, "NDB$B()");
+Should match North with A
+create table EuropeNorth.Countries (a int primary key) engine=ndb;
+ERROR HY000: Can't create table 'EuropeNorth.Countries' (errno: 1627)
+show warnings;
+Level	Code	Message
+Error	1627	Error in parsing conflict function. Message: NDB$A(), unknown conflict resolution function at 'NDB$A()'
+Error	1005	Can't create table 'EuropeNorth.Countries' (errno: 1627)
+Should match North with A
+create table USNorth.Countries (a int primary key) engine=ndb;
+ERROR HY000: Can't create table 'USNorth.Countries' (errno: 1627)
+show warnings;
+Level	Code	Message
+Error	1627	Error in parsing conflict function. Message: NDB$A(), unknown conflict resolution function at 'NDB$A()'
+Error	1005	Can't create table 'USNorth.Countries' (errno: 1627)
+Should match South with B
+create table EuropeSouth.Countries (a int primary key) engine=ndb;
+ERROR HY000: Can't create table 'EuropeSouth.Countries' (errno: 1627)
+show warnings;
+Level	Code	Message
+Error	1627	Error in parsing conflict function. Message: NDB$B(), unknown conflict resolution function at 'NDB$B()'
+Error	1005	Can't create table 'EuropeSouth.Countries' (errno: 1627)
+Should match South with B
+create table USSouth.Countries (a int primary key) engine=ndb;
+ERROR HY000: Can't create table 'USSouth.Countries' (errno: 1627)
+show warnings;
+Level	Code	Message
+Error	1627	Error in parsing conflict function. Message: NDB$B(), unknown conflict resolution function at 'NDB$B()'
+Error	1005	Can't create table 'USSouth.Countries' (errno: 1627)
+delete from mysql.ndb_replication;
+Now test wildcard matching precedence
+Wildcards match in the following precedence (highest->lowest)
+Exact match
+Wild serverid
+Wild table_name
+Wild serverid + wild table_name
+Wild db
+Wild db + wild serverid
+Wild db + wild table_name
+All wild
+
+The 'wild serverid' is 0
+
+Multiple matches at the same precedence are ambiguous and result
+in an error.
+
+Start with full set of potential matches, and chip away
+insert into mysql.ndb_replication values ("EuropeNorth", "Netherlands", 1, NULL, "NDB$A()");
+insert into mysql.ndb_replication values ("EuropeNorth", "Netherlands", 0, NULL, "NDB$B()");
+insert into mysql.ndb_replication values ("EuropeNorth", "%lands", 1, NULL, "NDB$C()");
+insert into mysql.ndb_replication values ("EuropeNorth", "Nether%s", 1, NULL, "NDB$D()");
+insert into mysql.ndb_replication values ("EuropeNorth", "%lands", 0, NULL, "NDB$E()");
+insert into mysql.ndb_replication values ("EuropeNorth", "Nether%s", 0, NULL, "NDB$F()");
+insert into mysql.ndb_replication values ("Europe%", "Netherlands", 1, NULL, "NDB$G()");
+insert into mysql.ndb_replication values ("%North", "Netherlands", 1, NULL, "NDB$H()");
+insert into mysql.ndb_replication values ("Europe%", "Netherlands", 0, NULL, "NDB$I()");
+insert into mysql.ndb_replication values ("%North", "Netherlands", 0, NULL, "NDB$J()");
+insert into mysql.ndb_replication values ("Europe%", "%lands", 1, NULL, "NDB$K()");
+insert into mysql.ndb_replication values ("%North", "Nether%s", 1, NULL, "NDB$L()");
+insert into mysql.ndb_replication values ("Europe%", "%lands", 0, NULL, "NDB$M()");
+insert into mysql.ndb_replication values ("%North", "Nether%s", 0, NULL, "NDB$N()");
+Unique match (A)
+create table EuropeNorth.Netherlands (a int primary key) engine=ndb;
+ERROR HY000: Can't create table 'EuropeNorth.Netherlands' (errno: 1627)
+show warnings;
+Level	Code	Message
+Error	1627	Error in parsing conflict function. Message: NDB$A(), unknown conflict resolution function at 'NDB$A()'
+Error	1005	Can't create table 'EuropeNorth.Netherlands' (errno: 1627)
+delete from mysql.ndb_replication where db="EuropeNorth" and table_name="Netherlands" and server_id=1;
+Unique match with wild serverid (B)
+create table EuropeNorth.Netherlands (a int primary key) engine=ndb;
+ERROR HY000: Can't create table 'EuropeNorth.Netherlands' (errno: 1627)
+show warnings;
+Level	Code	Message
+Error	1627	Error in parsing conflict function. Message: NDB$B(), unknown conflict resolution function at 'NDB$B()'
+Error	1005	Can't create table 'EuropeNorth.Netherlands' (errno: 1627)
+delete from mysql.ndb_replication where db="EuropeNorth" and table_name="Netherlands" and server_id=0;
+Ambiguous wild table name
+create table EuropeNorth.Netherlands (a int primary key) engine=ndb;
+Warnings:
+Error	1626	Bad schema for mysql.ndb_replication table. Message: Ambiguous matches in mysql.ndb_replication for EuropeNorth.Nethe
+show warnings;
+Level	Code	Message
+Error	1626	Bad schema for mysql.ndb_replication table. Message: Ambiguous matches in mysql.ndb_replication for EuropeNorth.Nethe
+drop table EuropeNorth.Netherlands;
+delete from mysql.ndb_replication where db="EuropeNorth" and table_name="%lands" and server_id=1;
+Wild table name (D)
+create table EuropeNorth.Netherlands (a int primary key) engine=ndb;
+ERROR HY000: Can't create table 'EuropeNorth.Netherlands' (errno: 1627)
+show warnings;
+Level	Code	Message
+Error	1627	Error in parsing conflict function. Message: NDB$D(), unknown conflict resolution function at 'NDB$D()'
+Error	1005	Can't create table 'EuropeNorth.Netherlands' (errno: 1627)
+delete from mysql.ndb_replication where db="EuropeNorth" and table_name="Nether%s" and server_id=1;
+Ambiguous wild server id and table name
+create table EuropeNorth.Netherlands (a int primary key) engine=ndb;
+Warnings:
+Error	1626	Bad schema for mysql.ndb_replication table. Message: Ambiguous matches in mysql.ndb_replication for EuropeNorth.Nethe
+show warnings;
+Level	Code	Message
+Error	1626	Bad schema for mysql.ndb_replication table. Message: Ambiguous matches in mysql.ndb_replication for EuropeNorth.Nethe
+drop table EuropeNorth.Netherlands;
+delete from mysql.ndb_replication where db="EuropeNorth" and table_name="Nether%s" and server_id=0;
+Wild server id and table name (E)
+create table EuropeNorth.Netherlands (a int primary key) engine=ndb;
+ERROR HY000: Can't create table 'EuropeNorth.Netherlands' (errno: 1627)
+show warnings;
+Level	Code	Message
+Error	1627	Error in parsing conflict function. Message: NDB$E(), unknown conflict resolution function at 'NDB$E()'
+Error	1005	Can't create table 'EuropeNorth.Netherlands' (errno: 1627)
+delete from mysql.ndb_replication where db="EuropeNorth" and table_name="%lands" and server_id=0;
+Amiguous wild db
+create table EuropeNorth.Netherlands (a int primary key) engine=ndb;
+Warnings:
+Error	1626	Bad schema for mysql.ndb_replication table. Message: Ambiguous matches in mysql.ndb_replication for EuropeNorth.Nethe
+show warnings;
+Level	Code	Message
+Error	1626	Bad schema for mysql.ndb_replication table. Message: Ambiguous matches in mysql.ndb_replication for EuropeNorth.Nethe
+drop table EuropeNorth.Netherlands;
+delete from mysql.ndb_replication where db="Europe%" and table_name="Netherlands" and server_id=1;
+Wild db (H)
+create table EuropeNorth.Netherlands (a int primary key) engine=ndb;
+ERROR HY000: Can't create table 'EuropeNorth.Netherlands' (errno: 1627)
+show warnings;
+Level	Code	Message
+Error	1627	Error in parsing conflict function. Message: NDB$H(), unknown conflict resolution function at 'NDB$H()'
+Error	1005	Can't create table 'EuropeNorth.Netherlands' (errno: 1627)
+delete from mysql.ndb_replication where db="%North" and table_name="Netherlands" and server_id=1;
+Ambiguous wild db + server_id
+create table EuropeNorth.Netherlands (a int primary key) engine=ndb;
+Warnings:
+Error	1626	Bad schema for mysql.ndb_replication table. Message: Ambiguous matches in mysql.ndb_replication for EuropeNorth.Nethe
+show warnings;
+Level	Code	Message
+Error	1626	Bad schema for mysql.ndb_replication table. Message: Ambiguous matches in mysql.ndb_replication for EuropeNorth.Nethe
+drop table EuropeNorth.Netherlands;
+delete from mysql.ndb_replication where db="Europe%" and table_name="Netherlands" and server_id=0;
+Wild db + server id (J)
+create table EuropeNorth.Netherlands (a int primary key) engine=ndb;
+ERROR HY000: Can't create table 'EuropeNorth.Netherlands' (errno: 1627)
+show warnings;
+Level	Code	Message
+Error	1627	Error in parsing conflict function. Message: NDB$J(), unknown conflict resolution function at 'NDB$J()'
+Error	1005	Can't create table 'EuropeNorth.Netherlands' (errno: 1627)
+delete from mysql.ndb_replication where db="%North" and table_name="Netherlands" and server_id=0;
+Ambiguous wild db + table_name
+create table EuropeNorth.Netherlands (a int primary key) engine=ndb;
+Warnings:
+Error	1626	Bad schema for mysql.ndb_replication table. Message: Ambiguous matches in mysql.ndb_replication for EuropeNorth.Nethe
+show warnings;
+Level	Code	Message
+Error	1626	Bad schema for mysql.ndb_replication table. Message: Ambiguous matches in mysql.ndb_replication for EuropeNorth.Nethe
+drop table EuropeNorth.Netherlands;
+delete from mysql.ndb_replication where db="Europe%" and table_name="%lands" and server_id=1;
+Wild db + table_name (L)
+create table EuropeNorth.Netherlands (a int primary key) engine=ndb;
+ERROR HY000: Can't create table 'EuropeNorth.Netherlands' (errno: 1627)
+show warnings;
+Level	Code	Message
+Error	1627	Error in parsing conflict function. Message: NDB$L(), unknown conflict resolution function at 'NDB$L()'
+Error	1005	Can't create table 'EuropeNorth.Netherlands' (errno: 1627)
+delete from mysql.ndb_replication where db="%North" and table_name="Nether%s" and server_id=1;
+Ambiguous all wild
+create table EuropeNorth.Netherlands (a int primary key) engine=ndb;
+Warnings:
+Error	1626	Bad schema for mysql.ndb_replication table. Message: Ambiguous matches in mysql.ndb_replication for EuropeNorth.Nethe
+show warnings;
+Level	Code	Message
+Error	1626	Bad schema for mysql.ndb_replication table. Message: Ambiguous matches in mysql.ndb_replication for EuropeNorth.Nethe
+drop table EuropeNorth.Netherlands;
+delete from mysql.ndb_replication where db="Europe%" and table_name="%lands" and server_id=0;
+All wild (N)
+create table EuropeNorth.Netherlands (a int primary key) engine=ndb;
+ERROR HY000: Can't create table 'EuropeNorth.Netherlands' (errno: 1627)
+show warnings;
+Level	Code	Message
+Error	1627	Error in parsing conflict function. Message: NDB$N(), unknown conflict resolution function at 'NDB$N()'
+Error	1005	Can't create table 'EuropeNorth.Netherlands' (errno: 1627)
+delete from mysql.ndb_replication;
+drop database EuropeNorth;
+drop database EuropeSouth;
+drop database USNorth;
+drop database USSouth;

=== modified file 'mysql-test/suite/ndb_rpl/t/ndb_rpl_rep_error.test'
--- a/mysql-test/suite/ndb_rpl/t/ndb_rpl_rep_error.test	2012-01-17 13:51:35 +0000
+++ b/mysql-test/suite/ndb_rpl/t/ndb_rpl_rep_error.test	2012-01-23 15:30:36 +0000
@@ -6,8 +6,25 @@
 --source include/have_binlog_format_mixed_or_row.inc
 --source suite/ndb_rpl/ndb_master-slave.inc
 
+# Need suppressions on all servers where warnings/errors can be seen.
+--disable_query_log
+--connection server1
+call mtr.add_suppression("NDB: .*Bad schema for mysql.ndb_replication table.*");
+call mtr.add_suppression("NDB Slave: .* unknown conflict resolution function .*");
+call mtr.add_suppression("NDB Slave: .* has wrong datatype.*");
+call mtr.add_suppression("NDB Slave: .* missing function argument .*");
+call mtr.add_suppression("NDB Slave: .* missing \')\' .*");
+--connection server2
+call mtr.add_suppression("NDB: .*Bad schema for mysql.ndb_replication table.*");
+call mtr.add_suppression("NDB Slave: .* unknown conflict resolution function .*");
+call mtr.add_suppression("NDB Slave: .* has wrong datatype.*");
+call mtr.add_suppression("NDB Slave: .* missing function argument .*");
+call mtr.add_suppression("NDB Slave: .* missing \')\' .*");
+--connection default
+--enable_query_log
+
 #
-# wrong schema for the table
+--echo Wrong schema for the table, too few pks
 #
 --disable_warnings
 --disable_query_log
@@ -28,37 +45,129 @@ CREATE TABLE mysql.ndb_replication
 create table t1 (a int key, X int) engine ndb;
 drop table t1;
 
+
 #
-# correct schema for the table
-# but other errors
+--echo Wrong schema for the table, incorrect pk
 #
 --disable_warnings
 --disable_query_log
-drop table mysql.ndb_replication;
+drop table if exists mysql.ndb_replication;
 CREATE TABLE mysql.ndb_replication
   (db VARBINARY(63),
    table_name VARBINARY(63),
    server_id INT UNSIGNED,
    binlog_type INT UNSIGNED,
    conflict_fn VARBINARY(128),
+   PRIMARY KEY USING HASH (db,table_name,binlog_type))
+  ENGINE=NDB PARTITION BY KEY(db,table_name);
+--enable_warnings
+--enable_query_log
+
+# gives warning when trying to create table as logging
+# may not be as intended
+create table t1 (a int key, X int) engine ndb;
+drop table t1;
+
+#
+--echo Wrong schema for the table, binlog_type is signed
+#
+
+--disable_warnings
+--disable_query_log
+drop table if exists mysql.ndb_replication;
+CREATE TABLE mysql.ndb_replication
+  (db VARBINARY(63),
+   table_name VARBINARY(63),
+   server_id INT UNSIGNED,
+   binlog_type INT,
+   conflict_fn VARBINARY(128),
    PRIMARY KEY USING HASH (db,table_name,server_id))
   ENGINE=NDB PARTITION BY KEY(db,table_name);
 --enable_warnings
 --enable_query_log
 
-# Need suppressions on all servers where warnings/errors can be seen.
+# gives warning when trying to create table as logging
+# may not be as intended
+create table t1 (a int key, X int) engine ndb;
+drop table t1;
+
+#
+--echo Wrong schema for the table, conflict_fn is too long
+#
+--disable_warnings
 --disable_query_log
---connection server1
-call mtr.add_suppression("NDB Slave: .* unknown conflict resolution function .*");
-call mtr.add_suppression("NDB Slave: .* has wrong datatype.*");
-call mtr.add_suppression("NDB Slave: .* missing function argument .*");
-call mtr.add_suppression("NDB Slave: .* missing \')\' .*");
---connection server2
-call mtr.add_suppression("NDB Slave: .* unknown conflict resolution function .*");
-call mtr.add_suppression("NDB Slave: .* has wrong datatype.*");
-call mtr.add_suppression("NDB Slave: .* missing function argument .*");
-call mtr.add_suppression("NDB Slave: .* missing \')\' .*");
---connection default
+drop table mysql.ndb_replication;
+CREATE TABLE mysql.ndb_replication
+  (db VARBINARY(63),
+   table_name VARBINARY(63),
+   server_id INT UNSIGNED,
+   binlog_type INT UNSIGNED,
+   conflict_fn VARBINARY(257),
+   PRIMARY KEY USING HASH (db,table_name,server_id))
+  ENGINE=NDB PARTITION BY KEY(db,table_name);
+--enable_warnings
+--enable_query_log
+
+# gives warning when trying to create table as logging
+# may not be as intended
+create table t1 (a int key, X int) engine ndb;
+drop table t1;
+
+#
+--echo Correct schema for the table but no conflict fn
+#
+--disable_warnings
+--disable_query_log
+drop table mysql.ndb_replication;
+CREATE TABLE mysql.ndb_replication
+  (db VARBINARY(63),
+   table_name VARBINARY(63),
+   server_id INT UNSIGNED,
+   binlog_type INT UNSIGNED,
+   PRIMARY KEY USING HASH (db,table_name,server_id))
+  ENGINE=NDB PARTITION BY KEY(db,table_name);
+--enable_warnings
+--enable_query_log
+
+insert into mysql.ndb_replication values ("test", "t1", 0, 7);
+create table test.t1 (a int primary key) engine=ndb;
+show warnings;
+drop table test.t1;
+
+--let server_num=1.1
+--let $pattern=%NDB Binlog: logging%
+--let $limit=1
+--source suite/ndb_rpl/t/show_mysqld_warnings.inc
+
+delete from mysql.ndb_replication;
+
+--echo Check that NULL uses server defaults
+show variables like 'ndb_log_update_as_write';
+show variables like 'ndb_log_updated_only';
+insert into mysql.ndb_replication values ("test", "t1", 0, NULL);
+
+create table test.t1 (a int primary key) engine=ndb;
+show warnings;
+drop table test.t1;
+
+--source suite/ndb_rpl/t/show_mysqld_warnings.inc
+
+
+#
+--echo Correct schema for the table but other errors
+#
+--disable_warnings
+--disable_query_log
+drop table mysql.ndb_replication;
+CREATE TABLE mysql.ndb_replication
+  (db VARBINARY(63),
+   table_name VARBINARY(63),
+   server_id INT UNSIGNED,
+   binlog_type INT UNSIGNED,
+   conflict_fn VARBINARY(128),
+   PRIMARY KEY USING HASH (db,table_name,server_id))
+  ENGINE=NDB PARTITION BY KEY(db,table_name);
+--enable_warnings
 --enable_query_log
 
 # Non existant conflict_fn
@@ -99,6 +208,246 @@ create table t1 (a int key, X int) engin
 show warnings;
 delete from mysql.ndb_replication;
 
+show variables like 'server_id';
+
+create database EuropeNorth;
+create database EuropeSouth;
+create database USNorth;
+create database USSouth;
+
+--echo Basic wildcard tests
+--echo Note that we put in bad conflict fn names so that the warnings generated
+--echo when the table create fails give an indication of which ndb_replication
+--echo table row was chosen.
+--echo
+--echo Wild serverid
+insert into mysql.ndb_replication values ("EuropeNorth", "France", 1, NULL, "NDB$A()");
+insert into mysql.ndb_replication values ("EuropeNorth", "France", 0, NULL, "NDB$B()");
+
+--echo Should match specific entry (1) with algorithm A.
+--error 1005
+create table EuropeNorth.France (a int primary key) engine=ndb;
+show warnings;
+
+delete from mysql.ndb_replication where server_id=1;
+
+--echo Should match generic entry (0) with algorthin B.
+--error 1005
+create table EuropeNorth.France (a int primary key) engine=ndb;
+show warnings;
+
+delete from mysql.ndb_replication;
+
+--echo Wild table_name
+insert into mysql.ndb_replication values ("EuropeNorth", "Fr_nce", 1, NULL, "NDB$A()");
+insert into mysql.ndb_replication values ("EuropeNorth", "%any", 1, NULL, "NDB$B()");
+
+--echo Should match specific entry (Fr_nce) with algorithm A.
+--error 1005
+create table EuropeNorth.France (a int primary key) engine=ndb;
+show warnings;
+
+--echo Should match specific entry (%any) with algorithm B.
+--error 1005
+create table EuropeNorth.Germany (a int primary key) engine=ndb;
+show warnings;
+
+--echo Should match specific entry (%any) with algorithm B.
+--error 1005
+create table EuropeNorth.Romany (a int primary key) engine=ndb;
+show warnings;
+
+--echo No match, should be fine
+create table EuropeNorth.UK (a int primary key) engine=ndb;
+show warnings;
+drop table EuropeNorth.UK;
+
+delete from mysql.ndb_replication;
+
+--echo Wild db
+insert into mysql.ndb_replication values ("%North", "Countries", 1, NULL, "NDB$A()");
+insert into mysql.ndb_replication values ("%South", "Countries", 1, NULL, "NDB$B()");
+
+--echo Should match North with A
+--error 1005
+create table EuropeNorth.Countries (a int primary key) engine=ndb;
+show warnings;
+
+--echo Should match North with A
+--error 1005
+create table USNorth.Countries (a int primary key) engine=ndb;
+show warnings;
+
+--echo Should match South with B
+--error 1005
+create table EuropeSouth.Countries (a int primary key) engine=ndb;
+show warnings;
+
+--echo Should match South with B
+--error 1005
+create table USSouth.Countries (a int primary key) engine=ndb;
+show warnings;
+
+delete from mysql.ndb_replication;
+
+--echo Now test wildcard matching precedence
+--echo Wildcards match in the following precedence (highest->lowest)
+--echo   Exact match
+--echo   Wild serverid
+--echo   Wild table_name
+--echo   Wild serverid + wild table_name
+--echo   Wild db
+--echo   Wild db + wild serverid
+--echo   Wild db + wild table_name
+--echo   All wild
+--echo
+--echo The 'wild serverid' is 0
+--echo
+--echo Multiple matches at the same precedence are ambiguous and result
+--echo in an error.
+--echo
+
+--echo Start with full set of potential matches, and chip away
+# Put in duplicate matches at every precedence
+# Delete rows to get one then no matches at each precedence.
+
+# Unique
+insert into mysql.ndb_replication values ("EuropeNorth", "Netherlands", 1, NULL, "NDB$A()");
+
+# Wild serverid
+insert into mysql.ndb_replication values ("EuropeNorth", "Netherlands", 0, NULL, "NDB$B()");
+
+# Wild table_name (two)
+insert into mysql.ndb_replication values ("EuropeNorth", "%lands", 1, NULL, "NDB$C()");
+insert into mysql.ndb_replication values ("EuropeNorth", "Nether%s", 1, NULL, "NDB$D()");
+
+# Wild server_id and table_name
+insert into mysql.ndb_replication values ("EuropeNorth", "%lands", 0, NULL, "NDB$E()");
+insert into mysql.ndb_replication values ("EuropeNorth", "Nether%s", 0, NULL, "NDB$F()");
+
+# Wild db
+insert into mysql.ndb_replication values ("Europe%", "Netherlands", 1, NULL, "NDB$G()");
+insert into mysql.ndb_replication values ("%North", "Netherlands", 1, NULL, "NDB$H()");
+
+# Wild db + Wild server_id
+
+insert into mysql.ndb_replication values ("Europe%", "Netherlands", 0, NULL, "NDB$I()");
+insert into mysql.ndb_replication values ("%North", "Netherlands", 0, NULL, "NDB$J()");
+
+# Wild db + Wild table_name
+
+insert into mysql.ndb_replication values ("Europe%", "%lands", 1, NULL, "NDB$K()");
+insert into mysql.ndb_replication values ("%North", "Nether%s", 1, NULL, "NDB$L()");
+
+# All wild
+
+insert into mysql.ndb_replication values ("Europe%", "%lands", 0, NULL, "NDB$M()");
+insert into mysql.ndb_replication values ("%North", "Nether%s", 0, NULL, "NDB$N()");
+
+
+--echo Unique match (A)
+--error 1005
+create table EuropeNorth.Netherlands (a int primary key) engine=ndb;
+show warnings;
+
+delete from mysql.ndb_replication where db="EuropeNorth" and table_name="Netherlands" and server_id=1;
+
+--echo Unique match with wild serverid (B)
+--error 1005
+create table EuropeNorth.Netherlands (a int primary key) engine=ndb;
+show warnings;
+
+delete from mysql.ndb_replication where db="EuropeNorth" and table_name="Netherlands" and server_id=0;
+
+--echo Ambiguous wild table name
+create table EuropeNorth.Netherlands (a int primary key) engine=ndb;
+show warnings;
+drop table EuropeNorth.Netherlands;
+
+delete from mysql.ndb_replication where db="EuropeNorth" and table_name="%lands" and server_id=1;
+
+--echo Wild table name (D)
+--error 1005
+create table EuropeNorth.Netherlands (a int primary key) engine=ndb;
+show warnings;
+
+delete from mysql.ndb_replication where db="EuropeNorth" and table_name="Nether%s" and server_id=1;
+
+--echo Ambiguous wild server id and table name
+create table EuropeNorth.Netherlands (a int primary key) engine=ndb;
+show warnings;
+drop table EuropeNorth.Netherlands;
+
+delete from mysql.ndb_replication where db="EuropeNorth" and table_name="Nether%s" and server_id=0;
+
+--echo Wild server id and table name (E)
+--error 1005
+create table EuropeNorth.Netherlands (a int primary key) engine=ndb;
+show warnings;
+
+delete from mysql.ndb_replication where db="EuropeNorth" and table_name="%lands" and server_id=0;
+
+--echo Amiguous wild db
+create table EuropeNorth.Netherlands (a int primary key) engine=ndb;
+show warnings;
+drop table EuropeNorth.Netherlands;
+
+delete from mysql.ndb_replication where db="Europe%" and table_name="Netherlands" and server_id=1;
+
+--echo Wild db (H)
+--error 1005
+create table EuropeNorth.Netherlands (a int primary key) engine=ndb;
+show warnings;
+
+delete from mysql.ndb_replication where db="%North" and table_name="Netherlands" and server_id=1;
+
+--echo Ambiguous wild db + server_id
+create table EuropeNorth.Netherlands (a int primary key) engine=ndb;
+show warnings;
+drop table EuropeNorth.Netherlands;
+
+delete from mysql.ndb_replication where db="Europe%" and table_name="Netherlands" and server_id=0;
+
+--echo Wild db + server id (J)
+--error 1005
+create table EuropeNorth.Netherlands (a int primary key) engine=ndb;
+show warnings;
+
+delete from mysql.ndb_replication where db="%North" and table_name="Netherlands" and server_id=0;
+
+--echo Ambiguous wild db + table_name
+create table EuropeNorth.Netherlands (a int primary key) engine=ndb;
+show warnings;
+drop table EuropeNorth.Netherlands;
+
+delete from mysql.ndb_replication where db="Europe%" and table_name="%lands" and server_id=1;
+
+--echo Wild db + table_name (L)
+--error 1005
+create table EuropeNorth.Netherlands (a int primary key) engine=ndb;
+show warnings;
+
+delete from mysql.ndb_replication where db="%North" and table_name="Nether%s" and server_id=1;
+
+--echo Ambiguous all wild
+create table EuropeNorth.Netherlands (a int primary key) engine=ndb;
+show warnings;
+drop table EuropeNorth.Netherlands;
+
+delete from mysql.ndb_replication where db="Europe%" and table_name="%lands" and server_id=0;
+
+--echo All wild (N)
+--error 1005
+create table EuropeNorth.Netherlands (a int primary key) engine=ndb;
+show warnings;
+
+delete from mysql.ndb_replication;
+
+drop database EuropeNorth;
+drop database EuropeSouth;
+drop database USNorth;
+drop database USSouth;
+
 --disable_query_log
 --sync_slave_with_master
 stop slave;

=== modified file 'sql/Makefile.am'
--- a/sql/Makefile.am	2011-11-10 09:01:54 +0000
+++ b/sql/Makefile.am	2012-01-23 15:30:36 +0000
@@ -66,6 +66,8 @@ noinst_HEADERS =	item.h item_func.h item
 			ndb_conflict_trans.h \
                         ndb_component.h \
                         ndb_util_thread.h \
+                        ndb_utils.h \
+                        ndb_repl_tab.h \
 			ha_partition.h rpl_constants.h \
 			debug_sync.h \
 			opt_range.h protocol.h rpl_tblmap.h rpl_utility.h \
@@ -144,7 +146,8 @@ libndb_la_SOURCES=	ha_ndbcluster.cc \
 			ha_ndbinfo.cc \
 			ndb_mi.cc \
 			ndb_conflict_trans.cc \
-                        ndb_component.cc
+                        ndb_component.cc \
+                        ndb_repl_tab.cc
 
 gen_lex_hash_SOURCES =	gen_lex_hash.cc
 gen_lex_hash_LDFLAGS =  @NOINST_LDFLAGS@

=== modified file 'sql/ha_ndbcluster.cc'
--- a/sql/ha_ndbcluster.cc	2012-01-17 13:51:35 +0000
+++ b/sql/ha_ndbcluster.cc	2012-01-23 15:30:36 +0000
@@ -48,6 +48,7 @@
 #include "ndb_conflict_trans.h"
 #include "ndb_component.h"
 #include "ndb_util_thread.h"
+#include "ndb_utils.h"
 
 #ifdef ndb_dynamite
 #undef assert

=== modified file 'sql/ha_ndbcluster_binlog.cc'
--- a/sql/ha_ndbcluster_binlog.cc	2012-01-17 13:52:58 +0000
+++ b/sql/ha_ndbcluster_binlog.cc	2012-01-23 15:30:36 +0000
@@ -33,6 +33,19 @@
 #include <ndbapi/ndb_cluster_connection.hpp>
 #include <util/NdbAutoPtr.hpp>
 #include <portlib/NdbTick.h>
+#include "ndb_utils.h"
+
+/*
+  defines for cluster replication table names
+*/
+#include "ha_ndbcluster_tables.h"
+#define NDB_APPLY_TABLE_FILE "./" NDB_REP_DB "/" NDB_APPLY_TABLE
+#define NDB_SCHEMA_TABLE_FILE "./" NDB_REP_DB "/" NDB_SCHEMA_TABLE
+static char repdb[]= NDB_REP_DB;
+static char reptable[]= NDB_REP_TABLE;
+
+#include "ndb_repl_tab.h"
+
 
 #ifdef ndb_dynamite
 #undef assert
@@ -55,15 +68,6 @@ bool ndb_log_empty_epochs(void);
 void ndb_index_stat_restart();
 
 /*
-  defines for cluster replication table names
-*/
-#include "ha_ndbcluster_tables.h"
-#define NDB_APPLY_TABLE_FILE "./" NDB_REP_DB "/" NDB_APPLY_TABLE
-#define NDB_SCHEMA_TABLE_FILE "./" NDB_REP_DB "/" NDB_SCHEMA_TABLE
-static char repdb[]= NDB_REP_DB;
-static char reptable[]= NDB_REP_TABLE;
-
-/*
   Timeout for syncing schema events between
   mysql servers, and between mysql server and the binlog
 */
@@ -4641,288 +4645,6 @@ setup_conflict_fn(THD *thd, NDB_SHARE *s
   DBUG_RETURN(0);
 }
 
-static const char *ndb_rep_db= NDB_REP_DB;
-static const char *ndb_replication_table= NDB_REPLICATION_TABLE;
-static const char *nrt_db= "db";
-static const char *nrt_table_name= "table_name";
-static const char *nrt_server_id= "server_id";
-static const char *nrt_binlog_type= "binlog_type";
-static const char *nrt_conflict_fn= "conflict_fn";
-
-/*
-   ndbcluster_read_replication_table
-
-   This function reads the information for the supplied table from
-   the mysql.ndb_replication table.
-   Where there is no information (or no table), defaults are
-   returned.
-*/
-int
-ndbcluster_read_replication_table(THD *thd, Ndb *ndb,
-                                  const char* db,
-                                  const char* table_name,
-                                  uint server_id,
-                                  Uint32* binlog_flags,
-                                  char** conflict_fn_spec,
-                                  char* conflict_fn_buffer,
-                                  Uint32 conflict_fn_buffer_len)
-{
-  DBUG_ENTER("ndbcluster_read_replication_table");
-  NdbError ndberror;
-  int error= 0;
-  const char *error_str= "<none>";
-
-  ndb->setDatabaseName(ndb_rep_db);
-  NDBDICT *dict= ndb->getDictionary();
-  Ndb_table_guard ndbtab_g(dict, ndb_replication_table);
-  const NDBTAB *reptab= ndbtab_g.get_table();
-  if (reptab == NULL &&
-      (dict->getNdbError().classification == NdbError::SchemaError ||
-       dict->getNdbError().code == 4009))
-  {
-    DBUG_PRINT("info", ("No %s.%s table", ndb_rep_db, ndb_replication_table));
-    *binlog_flags= NBT_DEFAULT;
-    *conflict_fn_spec= NULL;
-    DBUG_RETURN(0);
-  }
-  const NDBCOL
-    *col_db, *col_table_name, *col_server_id, *col_binlog_type, *col_conflict_fn;
-  char tmp_buf[FN_REFLEN];
-  uint retries= 100;
-  int retry_sleep= 30; /* 30 milliseconds, transaction */
-  if (reptab == NULL)
-  {
-    ndberror= dict->getNdbError();
-    goto err;
-  }
-  if (reptab->getNoOfPrimaryKeys() != 3)
-  {
-    error= -2;
-    error_str= "Wrong number of primary key parts, expected 3";
-    goto err;
-  }
-  error= -1;
-  col_db= reptab->getColumn(error_str= nrt_db);
-  if (col_db == NULL ||
-      !col_db->getPrimaryKey() ||
-      col_db->getType() != NDBCOL::Varbinary)
-    goto err;
-  col_table_name= reptab->getColumn(error_str= nrt_table_name);
-  if (col_table_name == NULL ||
-      !col_table_name->getPrimaryKey() ||
-      col_table_name->getType() != NDBCOL::Varbinary)
-    goto err;
-  col_server_id= reptab->getColumn(error_str= nrt_server_id);
-  if (col_server_id == NULL ||
-      !col_server_id->getPrimaryKey() ||
-      col_server_id->getType() != NDBCOL::Unsigned)
-    goto err;
-  col_binlog_type= reptab->getColumn(error_str= nrt_binlog_type);
-  if (col_binlog_type == NULL ||
-      col_binlog_type->getPrimaryKey() ||
-      col_binlog_type->getType() != NDBCOL::Unsigned)
-    goto err;
-  col_conflict_fn= reptab->getColumn(error_str= nrt_conflict_fn);
-  if (col_conflict_fn == NULL)
-  {
-    col_conflict_fn= NULL;
-  }
-  else if (col_conflict_fn->getPrimaryKey() ||
-           col_conflict_fn->getType() != NDBCOL::Varbinary)
-    goto err;
-
-  error= 0;
-  for (;;)
-  {
-    NdbTransaction *trans= ndb->startTransaction();
-    if (trans == NULL)
-    {
-      ndberror= ndb->getNdbError();
-      break;
-    }
-    NdbRecAttr *col_binlog_type_rec_attr[2];
-    NdbRecAttr *col_conflict_fn_rec_attr[2]= {NULL, NULL};
-    uint32 ndb_binlog_type[2];
-    const uint sz= 256;
-    char ndb_conflict_fn_buf[2*sz];
-    char *ndb_conflict_fn[2]= {ndb_conflict_fn_buf, ndb_conflict_fn_buf+sz};
-    NdbOperation *op[2];
-    uint32 i, id= 0;
-    /* Read generic row (server_id==0) and specific row (server_id == our id)
-     * from ndb_replication.
-     * Specific overrides generic, if present
-     */
-    for (i= 0; i < 2; i++)
-    {
-      NdbOperation *_op;
-      DBUG_PRINT("info", ("reading[%u]: %s,%s,%u", i, db, table_name, id));
-      if ((_op= trans->getNdbOperation(reptab)) == NULL) abort();
-      if (_op->readTuple(NdbOperation::LM_CommittedRead)) abort();
-      ndb_pack_varchar(col_db, tmp_buf, db, (int)strlen(db));
-      if (_op->equal(col_db->getColumnNo(), tmp_buf)) abort();
-      ndb_pack_varchar(col_table_name, tmp_buf, table_name, (int)strlen(table_name));
-      if (_op->equal(col_table_name->getColumnNo(), tmp_buf)) abort();
-      if (_op->equal(col_server_id->getColumnNo(), id)) abort();
-      if ((col_binlog_type_rec_attr[i]=
-           _op->getValue(col_binlog_type, (char *)&(ndb_binlog_type[i]))) == 0) abort();
-      /* optional columns */
-      if (col_conflict_fn)
-      {
-        if ((col_conflict_fn_rec_attr[i]=
-             _op->getValue(col_conflict_fn, ndb_conflict_fn[i])) == 0) abort();
-      }
-      id= server_id;
-      op[i]= _op;
-    }
-
-    if (trans->execute(NdbTransaction::Commit,
-                       NdbOperation::AO_IgnoreError))
-    {
-      if (ndb->getNdbError().status == NdbError::TemporaryError)
-      {
-        if (retries--)
-        {
-          if (trans)
-            ndb->closeTransaction(trans);
-          do_retry_sleep(retry_sleep);
-          continue;
-        }
-      }
-      ndberror= trans->getNdbError();
-      ndb->closeTransaction(trans);
-      break;
-    }
-    for (i= 0; i < 2; i++)
-    {
-      if (op[i]->getNdbError().code)
-      {
-        if (op[i]->getNdbError().classification == NdbError::NoDataFound)
-        {
-          col_binlog_type_rec_attr[i]= NULL;
-          col_conflict_fn_rec_attr[i]= NULL;
-          DBUG_PRINT("info", ("not found row[%u]", i));
-          continue;
-        }
-        ndberror= op[i]->getNdbError();
-        break;
-      }
-      DBUG_PRINT("info", ("found row[%u]", i));
-    }
-    if (col_binlog_type_rec_attr[1] == NULL ||
-        col_binlog_type_rec_attr[1]->isNULL())
-    {
-      /* No specific value, use generic */
-      col_binlog_type_rec_attr[1]= col_binlog_type_rec_attr[0];
-      ndb_binlog_type[1]= ndb_binlog_type[0];
-    }
-    if (col_conflict_fn_rec_attr[1] == NULL ||
-        col_conflict_fn_rec_attr[1]->isNULL())
-    {
-      /* No specific value, use generic */
-      col_conflict_fn_rec_attr[1]= col_conflict_fn_rec_attr[0];
-      ndb_conflict_fn[1]= ndb_conflict_fn[0];
-    }
-
-    if (col_binlog_type_rec_attr[1] == NULL ||
-        col_binlog_type_rec_attr[1]->isNULL())
-    {
-      DBUG_PRINT("info", ("No binlog flag value, using default"));
-      /* No value */
-      *binlog_flags= NBT_DEFAULT;
-    }
-    else
-    {
-      DBUG_PRINT("info", ("Taking binlog flag value from the table"));
-      *binlog_flags= (enum Ndb_binlog_type) ndb_binlog_type[1];
-    }
-
-    if (col_conflict_fn_rec_attr[1] == NULL ||
-        col_conflict_fn_rec_attr[1]->isNULL())
-    {
-      /* No conflict function */
-      *conflict_fn_spec = NULL;
-    }
-    else
-    {
-      const char* conflict_fn = ndb_conflict_fn[1];
-      uint len= 0;
-      switch (col_conflict_fn->getArrayType())
-      {
-      case NDBCOL::ArrayTypeShortVar:
-        len= *(uchar*)conflict_fn;
-        conflict_fn++;
-        break;
-      case NDBCOL::ArrayTypeMediumVar:
-        len= uint2korr(conflict_fn);
-        conflict_fn+= 2;
-        break;
-      default:
-        abort();
-      }
-      if ((len + 1) > conflict_fn_buffer_len)
-      {
-        ndb->closeTransaction(trans);
-        error= -2;
-        error_str= "Conflict function specification too long.";
-        goto err;
-      }
-      memcpy(conflict_fn_buffer, conflict_fn, len);
-      conflict_fn_buffer[len] = '\0';
-      *conflict_fn_spec = conflict_fn_buffer;
-    }
-
-    DBUG_PRINT("info", ("Retrieved Binlog flags : %u and function spec : %s",
-                        *binlog_flags, (*conflict_fn_spec != NULL ?*conflict_fn_spec:
-                                       "NULL")));
-
-    ndb->closeTransaction(trans);
-
-    DBUG_RETURN(0);
-  }
-
-err:
-  DBUG_PRINT("info", ("error %d, error_str %s, ndberror.code %u",
-                      error, error_str, ndberror.code));
-  if (error < 0)
-  {
-    char msg[FN_REFLEN];
-    switch (error)
-    {
-      case -1:
-        my_snprintf(msg, sizeof(msg),
-                 "Missing or wrong type for column '%s'", error_str);
-        break;
-      case -2:
-        my_snprintf(msg, sizeof(msg), "%s", error_str);
-        break;
-      default:
-        abort();
-    }
-    push_warning_printf(thd, MYSQL_ERROR::WARN_LEVEL_ERROR,
-                        ER_NDB_REPLICATION_SCHEMA_ERROR,
-                        ER(ER_NDB_REPLICATION_SCHEMA_ERROR),
-                        msg);
-  }
-  else
-  {
-    char msg[FN_REFLEN];
-    my_snprintf(tmp_buf, sizeof(tmp_buf), "ndberror %u", ndberror.code);
-    my_snprintf(msg, sizeof(msg), "Unable to retrieve %s.%s, logging and "
-             "conflict resolution may not function as intended (%s)",
-             ndb_rep_db, ndb_replication_table, tmp_buf);
-    push_warning_printf(thd, MYSQL_ERROR::WARN_LEVEL_ERROR,
-                        ER_ILLEGAL_HA_CREATE_OPTION,
-                        ER(ER_ILLEGAL_HA_CREATE_OPTION),
-                        ndbcluster_hton_name, msg);  
-  }
-  *binlog_flags= NBT_DEFAULT;
-  *conflict_fn_spec= NULL;
-
-  if (ndberror.code && opt_ndb_extra_logging)
-    print_warning_list("NDB", thd_warn_list(thd));
-  DBUG_RETURN(ndberror.code);
-}
-
 /*
   ndbcluster_get_binlog_replication_info
 
@@ -4967,48 +4689,54 @@ ndbcluster_get_binlog_replication_info(T
     }
   }
 
-  const Uint32 MAX_CONFLICT_FN_SPEC_LEN = 256;
-  char conflict_fn_buffer[MAX_CONFLICT_FN_SPEC_LEN];
-  char* conflict_fn_spec;
-
-  if (ndbcluster_read_replication_table(thd,
-                                        ndb,
-                                        db,
-                                        table_name,
-                                        server_id,
-                                        binlog_flags,
-                                        &conflict_fn_spec,
-                                        conflict_fn_buffer,
-                                        MAX_CONFLICT_FN_SPEC_LEN) != 0)
+  Ndb_rep_tab_reader rep_tab_reader;
+
+  int rc = rep_tab_reader.lookup(ndb,
+                                 db,
+                                 table_name,
+                                 server_id);
+
+  const char* msg = rep_tab_reader.get_warning_message();
+  if (msg != NULL)
   {
-    DBUG_RETURN(ER_NDB_REPLICATION_SCHEMA_ERROR);
+    push_warning_printf(thd, MYSQL_ERROR::WARN_LEVEL_ERROR,
+                        ER_NDB_REPLICATION_SCHEMA_ERROR,
+                        ER(ER_NDB_REPLICATION_SCHEMA_ERROR),
+                        msg);
+    sql_print_warning("NDB Binlog: %s",
+                      msg);
   }
 
+  if (rc != 0)
+    DBUG_RETURN(ER_NDB_REPLICATION_SCHEMA_ERROR);
+
+  *binlog_flags= rep_tab_reader.get_binlog_flags();
+  const char* conflict_fn_spec= rep_tab_reader.get_conflict_fn_spec();
+
   if (conflict_fn_spec != NULL)
   {
-    char tmp_buf[FN_REFLEN];
-
+    char msgbuf[ FN_REFLEN ];
     if (parse_conflict_fn_spec(conflict_fn_spec,
                                conflict_fn,
                                args,
                                num_args,
-                               tmp_buf,
-                               sizeof(tmp_buf)) != 0)
+                               msgbuf,
+                               sizeof(msgbuf)) != 0)
     {
       push_warning_printf(thd, MYSQL_ERROR::WARN_LEVEL_ERROR,
                           ER_CONFLICT_FN_PARSE_ERROR,
                           ER(ER_CONFLICT_FN_PARSE_ERROR),
-                          tmp_buf);
+                          msgbuf);
 
       /*
-         Log as well, useful for contexts where the thd's stack of
-         warnings are ignored
-       */
+        Log as well, useful for contexts where the thd's stack of
+        warnings are ignored
+      */
       if (opt_ndb_extra_logging)
       {
         sql_print_warning("NDB Slave: Table %s.%s : Parse error on conflict fn : %s",
                           db, table_name,
-                          tmp_buf);
+                          msgbuf);
       }
 
       DBUG_RETURN(ER_CONFLICT_FN_PARSE_ERROR);

=== modified file 'sql/ha_ndbcluster_binlog.h'
--- a/sql/ha_ndbcluster_binlog.h	2012-01-17 13:51:35 +0000
+++ b/sql/ha_ndbcluster_binlog.h	2012-01-23 15:30:36 +0000
@@ -113,67 +113,6 @@ private:
   pthread_mutex_t &m_mutex;
 };
 
-class Ndb_table_guard
-{
-public:
-  Ndb_table_guard(NDBDICT *dict)
-    : m_dict(dict), m_ndbtab(NULL), m_invalidate(0)
-  {}
-  Ndb_table_guard(NDBDICT *dict, const char *tabname)
-    : m_dict(dict), m_ndbtab(NULL), m_invalidate(0)
-  {
-    DBUG_ENTER("Ndb_table_guard");
-    init(tabname);
-    DBUG_VOID_RETURN;
-  }
-  ~Ndb_table_guard()
-  {
-    DBUG_ENTER("~Ndb_table_guard");
-    reinit();
-    DBUG_VOID_RETURN;
-  }
-  void init(const char *tabname)
-  {
-    DBUG_ENTER("Ndb_table_guard::init");
-    /* must call reinit() if already initialized */
-    DBUG_ASSERT(m_ndbtab == NULL);
-    m_ndbtab= m_dict->getTableGlobal(tabname);
-    m_invalidate= 0;
-    DBUG_PRINT("info", ("m_ndbtab: %p", m_ndbtab));
-    DBUG_VOID_RETURN;
-  }
-  void reinit(const char *tabname= 0)
-  {
-    DBUG_ENTER("Ndb_table_guard::reinit");
-    if (m_ndbtab)
-    {
-      DBUG_PRINT("info", ("m_ndbtab: %p  m_invalidate: %d",
-                          m_ndbtab, m_invalidate));
-      m_dict->removeTableGlobal(*m_ndbtab, m_invalidate);
-      m_ndbtab= NULL;
-      m_invalidate= 0;
-    }
-    if (tabname)
-      init(tabname);
-    DBUG_PRINT("info", ("m_ndbtab: %p", m_ndbtab));
-    DBUG_VOID_RETURN;
-  }
-  const NDBTAB *get_table() { return m_ndbtab; }
-  void invalidate() { m_invalidate= 1; }
-  const NDBTAB *release()
-  {
-    DBUG_ENTER("Ndb_table_guard::release");
-    const NDBTAB *tmp= m_ndbtab;
-    DBUG_PRINT("info", ("m_ndbtab: %p", m_ndbtab));
-    m_ndbtab = 0;
-    DBUG_RETURN(tmp);
-  }
-private:
-  NDBDICT *m_dict;
-  const NDBTAB *m_ndbtab;
-  int m_invalidate;
-};
-
 class Thd_proc_info_guard
 {
 public:

=== added file 'sql/ndb_repl_tab.cc'
--- a/sql/ndb_repl_tab.cc	1970-01-01 00:00:00 +0000
+++ b/sql/ndb_repl_tab.cc	2012-01-23 15:30:36 +0000
@@ -0,0 +1,544 @@
+/*
+   Copyright (c) 2012, 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 "ha_ndbcluster_tables.h"
+#include "ndb_repl_tab.h"
+
+#ifdef HAVE_NDB_BINLOG
+#include "mysql_priv.h"
+#include "ha_ndbcluster_connection.h"  /* do_retry_sleep() */
+#include "ndb_utils.h" /* Ndb_table_guard */
+
+Ndb_rep_tab_key::Ndb_rep_tab_key(const char* _db,
+                                 const char* _table_name,
+                                 uint _server_id)
+{
+  uint db_len= strlen(_db);
+  uint tabname_len = strlen(_table_name);
+  assert(db_len <= DB_MAXLEN);
+  assert(tabname_len <= TABNAME_MAXLEN);
+
+  memcpy(&db[1], _db, db_len);
+  db[ 0 ]= db_len;
+
+  memcpy(&table_name[1], _table_name, tabname_len);
+  table_name[ 0 ]= tabname_len;
+
+  server_id= _server_id;
+
+  null_terminate_strings();
+}
+
+void Ndb_rep_tab_key::null_terminate_strings()
+{
+  assert((uint) db[0] <= DB_MAXLEN);
+  assert((uint) table_name[0] <= TABNAME_MAXLEN);
+  db[ db[0] + 1] = '\0';
+  table_name[ table_name[0] + 1] = '\0';
+}
+
+int Ndb_rep_tab_key::
+attempt_match(const char* keyptr,
+              const uint keylen,
+              const char* candidateptr,
+              const uint candidatelen,
+              const int exactmatchvalue)
+{
+  if (my_strnncoll(system_charset_info,
+                   (const uchar*) keyptr,
+                   keylen,
+                   (const uchar*) candidateptr,
+                   candidatelen) == 0)
+  {
+    /* Exact match */
+    return exactmatchvalue;
+  }
+  else if (my_wildcmp(system_charset_info,
+                      keyptr,
+                      keyptr + keylen,
+                      candidateptr,
+                      candidateptr + candidatelen,
+                      '\\', wild_one, wild_many) == 0)
+  {
+    /* Wild match */
+    return 0;
+  }
+
+  /* No match */
+  return -1;
+};
+
+int
+Ndb_rep_tab_key::
+get_match_quality(const Ndb_rep_tab_key* key,
+                  const Ndb_rep_tab_key* candidate_row)
+{
+  /* 0= No match
+     1= Loosest match
+     8= Best match
+
+     Actual mapping is :
+     db    table    serverid  Quality
+     W     W        W         1
+     W     W        =         2
+     W     =        W         3
+     W     =        =         4
+     =     W        W         5
+     =     W        =         6
+     =     =        W         7
+     =     =        =         8
+  */
+  int quality = MIN_MATCH_VAL;
+
+  int rc;
+  if ((rc = attempt_match(&key->db[1],
+                          key->db[0],
+                          &candidate_row->db[1],
+                          candidate_row->db[0],
+                          EXACT_MATCH_DB)) == -1)
+  {
+    /* No match, drop out now */
+    return 0;
+  }
+  quality+= rc;
+
+  if ((rc = attempt_match(&key->table_name[1],
+                          key->table_name[0],
+                          &candidate_row->table_name[1],
+                          candidate_row->table_name[0],
+                          EXACT_MATCH_TABLE_NAME)) == -1)
+  {
+    /* No match, drop out now */
+    return 0;
+  }
+  quality+= rc;
+
+  if (candidate_row->server_id == key->server_id)
+  {
+    /* Exact match */
+    quality += EXACT_MATCH_SERVER_ID;
+  }
+  else if (candidate_row->server_id != 0)
+  {
+    /* No match */
+    return 0;
+  }
+
+  return quality;
+};
+
+const char* Ndb_rep_tab_reader::ndb_rep_db= NDB_REP_DB;
+const char* Ndb_rep_tab_reader::ndb_replication_table= NDB_REPLICATION_TABLE;
+const char* Ndb_rep_tab_reader::nrt_db= "db";
+const char* Ndb_rep_tab_reader::nrt_table_name= "table_name";
+const char* Ndb_rep_tab_reader::nrt_server_id= "server_id";
+const char* Ndb_rep_tab_reader::nrt_binlog_type= "binlog_type";
+const char* Ndb_rep_tab_reader::nrt_conflict_fn= "conflict_fn";
+
+Ndb_rep_tab_reader::Ndb_rep_tab_reader()
+  : binlog_flags(NBT_DEFAULT),
+    conflict_fn_spec(NULL),
+    warning_msg(NULL)
+{
+}
+
+int Ndb_rep_tab_reader::check_schema(const NdbDictionary::Table* reptab,
+                                     NdbDictionary::Dictionary* dict,
+                                     const char** error_str)
+{
+  DBUG_ENTER("check_schema");
+  *error_str= NULL;
+
+  const NdbDictionary::Column
+    *col_db, *col_table_name, *col_server_id, *col_binlog_type, *col_conflict_fn;
+  if (reptab->getNoOfPrimaryKeys() != 3)
+  {
+    *error_str= "Wrong number of primary key parts, expected 3";
+    DBUG_RETURN(-2);
+  }
+  col_db= reptab->getColumn(*error_str= nrt_db);
+  if (col_db == NULL ||
+      !col_db->getPrimaryKey() ||
+      col_db->getType() != NdbDictionary::Column::Varbinary)
+    DBUG_RETURN(-1);
+  col_table_name= reptab->getColumn(*error_str= nrt_table_name);
+  if (col_table_name == NULL ||
+      !col_table_name->getPrimaryKey() ||
+      col_table_name->getType() != NdbDictionary::Column::Varbinary)
+    DBUG_RETURN(-1);
+  col_server_id= reptab->getColumn(*error_str= nrt_server_id);
+  if (col_server_id == NULL ||
+      !col_server_id->getPrimaryKey() ||
+      col_server_id->getType() != NdbDictionary::Column::Unsigned)
+    DBUG_RETURN(-1);
+  col_binlog_type= reptab->getColumn(*error_str= nrt_binlog_type);
+  if (col_binlog_type == NULL ||
+      col_binlog_type->getPrimaryKey() ||
+      col_binlog_type->getType() != NdbDictionary::Column::Unsigned)
+    DBUG_RETURN(-1);
+  col_conflict_fn= reptab->getColumn(*error_str= nrt_conflict_fn);
+  if (col_conflict_fn != NULL)
+  {
+    if ((col_conflict_fn->getPrimaryKey()) ||
+        (col_conflict_fn->getType() != NdbDictionary::Column::Varbinary))
+      DBUG_RETURN(-1);
+  }
+
+  DBUG_RETURN(0);
+}
+
+int Ndb_rep_tab_reader::
+scan_candidates(Ndb* ndb,
+                const NdbDictionary::Table* reptab,
+                const char* db,
+                const char* table_name,
+                uint server_id,
+                Ndb_rep_tab_row& best_match)
+{
+  uint retries= 100;
+  int retry_sleep= 30; /* 30 milliseconds, transaction */
+  int best_match_quality= 0;
+  NdbError ndberror;
+
+  /* Loop to enable temporary error retries */
+  while(true)
+  {
+    NdbTransaction *trans= ndb->startTransaction();
+    if (trans == NULL)
+    {
+      ndberror= ndb->getNdbError();
+      break;
+    }
+    NdbRecAttr* ra_binlog_type= NULL;
+    NdbRecAttr* ra_conflict_fn_spec= NULL;
+    Ndb_rep_tab_row row;
+    bool have_conflict_fn_col = (reptab->getColumn(nrt_conflict_fn) != NULL);
+
+    /* Define scan op on ndb_replication */
+    NdbScanOperation* scanOp = trans->getNdbScanOperation(reptab);
+    if (scanOp == NULL) { ndberror= trans->getNdbError(); break; }
+
+    if ((scanOp->readTuples(NdbScanOperation::LM_CommittedRead) != 0) ||
+        (scanOp->getValue(nrt_db, (char*) row.key.db) == NULL) ||
+        (scanOp->getValue(nrt_table_name, (char*) row.key.table_name) == NULL) ||
+        (scanOp->getValue(nrt_server_id, (char*) &row.key.server_id) == NULL) ||
+        ((ra_binlog_type = scanOp->getValue(nrt_binlog_type, (char*) &row.binlog_type)) == NULL) ||
+        (have_conflict_fn_col &&
+         ((ra_conflict_fn_spec=
+           scanOp->getValue(nrt_conflict_fn, (char*) row.conflict_fn_spec)) == NULL)))
+    {
+      ndberror= scanOp->getNdbError();
+      break;
+    }
+
+    if (trans->execute(NdbTransaction::NoCommit,
+                       NdbOperation::AO_IgnoreError))
+    {
+      if (ndb->getNdbError().status == NdbError::TemporaryError)
+      {
+        if (retries--)
+        {
+          if (trans)
+            ndb->closeTransaction(trans);
+          do_retry_sleep(retry_sleep);
+          continue;
+        }
+      }
+      ndberror= trans->getNdbError();
+      ndb->closeTransaction(trans);
+      break;
+    }
+
+    /* Scroll through results, looking for best match */
+    DBUG_PRINT("info", ("Searching ndb_replication for %s.%s %u",
+                        db, table_name, server_id));
+
+    bool ambiguous_match = false;
+    Ndb_rep_tab_key searchkey(db, table_name, server_id);
+    int scan_rc;
+    while ((scan_rc= scanOp->nextResult(true)) == 0)
+    {
+      if (ra_binlog_type->isNULL() == 1)
+      {
+        row.binlog_type= NBT_DEFAULT;
+      }
+      if (ra_conflict_fn_spec)
+      {
+        row.set_conflict_fn_spec_null(ra_conflict_fn_spec->isNULL() == 1);
+      }
+
+      /* Compare row to searchkey to get quality of match */
+      int match_quality= Ndb_rep_tab_key::get_match_quality(&searchkey,
+                                                            &row.key);
+#ifndef DBUG_OFF
+      {
+        row.null_terminate_strings();
+
+        DBUG_PRINT("info", ("Candidate : %s.%s %u : %u %s"
+                            " Match quality : %u.",
+                            row.key.get_db(),
+                            row.key.get_table_name(),
+                            row.key.server_id,
+                            row.binlog_type,
+                            row.get_conflict_fn_spec(),
+                            match_quality));
+      }
+#endif
+
+      if (match_quality > 0)
+      {
+        if (match_quality == best_match_quality)
+        {
+          ambiguous_match = true;
+          /* Ambiguous matches...*/
+          my_snprintf(warning_msg_buffer, sizeof(warning_msg_buffer),
+                      "Ambiguous matches in %s.%s for %s.%s (%u)."
+                      "Candidates : %s.%s (%u), %s.%s (%u).",
+                      ndb_rep_db, ndb_replication_table,
+                      db, table_name, server_id,
+                      &best_match.key.db[1],
+                      &best_match.key.table_name[1],
+                      best_match.key.server_id,
+                      &row.key.db[1],
+                      &row.key.table_name[1],
+                      row.key.server_id);
+          DBUG_PRINT("info", ("%s", warning_msg_buffer));
+        }
+        if (match_quality > best_match_quality)
+        {
+          /* New best match */
+          best_match= row;
+          best_match_quality = match_quality;
+          ambiguous_match = false;
+
+          if (best_match_quality == Ndb_rep_tab_key::EXACT_MATCH_QUALITY)
+          {
+            /* We're done */
+            break;
+          }
+        }
+      } /* if (match_quality > 0) */
+    } /* while ((scan_rc= scanOp->nextResult(true)) */
+
+    if (scan_rc < 0)
+    {
+      if (scanOp->getNdbError().status == NdbError::TemporaryError)
+      {
+        if (retries--)
+        {
+          ndb->closeTransaction(trans);
+          do_retry_sleep(retry_sleep);
+          continue;
+        }
+      }
+      ndberror= trans->getNdbError();
+    }
+
+    ndb->closeTransaction(trans);
+
+    if (ambiguous_match)
+    {
+      warning_msg= warning_msg_buffer;
+      best_match_quality = -1;
+    }
+
+    break;
+  } /* while(true) */
+
+  if (ndberror.code != 0)
+  {
+    my_snprintf(warning_msg_buffer, sizeof(warning_msg_buffer),
+                "Unable to retrieve %s.%s, logging and "
+                "conflict resolution may not function "
+                "as intended (ndberror %u)",
+                ndb_rep_db, ndb_replication_table,
+                ndberror.code);
+    warning_msg= warning_msg_buffer;
+    best_match_quality = -1;
+  }
+
+  return best_match_quality;
+}
+
+int Ndb_rep_tab_reader::
+lookup(Ndb* ndb,
+       /* Keys */
+       const char* db,
+       const char* table_name,
+       uint server_id)
+{
+  DBUG_ENTER("lookup");
+  int error= 0;
+  NdbError ndberror;
+  const char *error_str= "<none>";
+
+  /* Set results to defaults */
+  binlog_flags= NBT_DEFAULT;
+  conflict_fn_spec= NULL;
+  warning_msg= NULL;
+
+  ndb->setDatabaseName(ndb_rep_db);
+  NdbDictionary::Dictionary *dict= ndb->getDictionary();
+  Ndb_table_guard ndbtab_g(dict, ndb_replication_table);
+  const NdbDictionary::Table *reptab= ndbtab_g.get_table();
+
+  do
+  {
+    if (reptab == NULL)
+    {
+      if (dict->getNdbError().classification == NdbError::SchemaError ||
+          dict->getNdbError().code == 4009)
+      {
+        DBUG_PRINT("info", ("No %s.%s table", ndb_rep_db, ndb_replication_table));
+        DBUG_RETURN(0);
+      }
+      else
+      {
+        error= 0;
+        ndberror= dict->getNdbError();
+        break;
+      }
+    }
+
+    if ((error= check_schema(reptab,
+                             dict,
+                             &error_str)) != 0)
+    {
+      DBUG_PRINT("info", ("check_schema failed : %u, error_str : %s",
+                          error, error_str));
+      break;
+    }
+
+
+    Ndb_rep_tab_row best_match_row;
+
+    int best_match_quality = scan_candidates(ndb,
+                                             reptab,
+                                             db,
+                                             table_name,
+                                             server_id,
+                                             best_match_row);
+
+    DBUG_PRINT("info", ("Best match at quality : %u", best_match_quality));
+
+    if (best_match_quality == -1)
+    {
+      /* Problem in matching, message already set */
+      assert(warning_msg != NULL);
+      error= -3;
+      break;
+    }
+    if (best_match_quality == 0)
+    {
+      /* No match : Use defaults */
+    }
+    else
+    {
+      /* Have a matching row, copy out values */
+      /* Ensure VARCHARs are usable as strings */
+      best_match_row.null_terminate_strings();
+
+      binlog_flags= (enum Ndb_binlog_type) best_match_row.binlog_type;
+
+      if (best_match_row.cfs_is_null)
+      {
+        DBUG_PRINT("info", ("Conflict FN SPEC is Null"));
+        /* No conflict fn spec */
+        conflict_fn_spec= NULL;
+      }
+      else
+      {
+        const char* conflict_fn = best_match_row.get_conflict_fn_spec();
+        uint len= strlen(conflict_fn);
+        if ((len + 1) > sizeof(conflict_fn_buffer))
+        {
+          error= -2;
+          error_str= "Conflict function specification too long.";
+          break;
+        }
+        memcpy(conflict_fn_buffer, conflict_fn, len);
+        conflict_fn_buffer[len] = '\0';
+        conflict_fn_spec = conflict_fn_buffer;
+      }
+    }
+  } while(0);
+
+  /* Error handling */
+  if (error == 0)
+  {
+    if (ndberror.code != 0)
+    {
+      my_snprintf(warning_msg_buffer, sizeof(warning_msg_buffer),
+                  "Unable to retrieve %s.%s, logging and "
+                  "conflict resolution may not function "
+                  "as intended (ndberror %u)",
+                  ndb_rep_db, ndb_replication_table,
+                  ndberror.code);
+      warning_msg= warning_msg_buffer;
+      error= -4;
+    }
+  }
+  else
+  {
+    switch (error)
+    {
+    case -1:
+      my_snprintf(warning_msg_buffer, sizeof(warning_msg_buffer),
+                  "Missing or wrong type for column '%s'", error_str);
+      break;
+    case -2:
+      my_snprintf(warning_msg_buffer, sizeof(warning_msg_buffer), "%s", error_str);
+      break;
+    case -3:
+      /* Message already set */
+      break;
+    default:
+      abort();
+    }
+    warning_msg= warning_msg_buffer;
+    error= 0; /* No real error, just use defaults */
+  }
+
+  DBUG_PRINT("info", ("Rc : %d Retrieved Binlog flags : %u and function spec : %s",
+                      error, binlog_flags, (conflict_fn_spec != NULL ?conflict_fn_spec:
+                                             "NULL")));
+
+  DBUG_RETURN(error);
+};
+
+Uint32
+Ndb_rep_tab_reader::get_binlog_flags() const
+{
+  return binlog_flags;
+}
+
+const char* Ndb_rep_tab_reader::
+get_conflict_fn_spec() const
+{
+  return conflict_fn_spec;
+}
+
+const char* Ndb_rep_tab_reader::
+get_warning_message() const
+{
+  return warning_msg;
+}
+
+
+/* #ifdef HAVE_NDB_BINLOG */
+
+#endif

=== added file 'sql/ndb_repl_tab.h'
--- a/sql/ndb_repl_tab.h	1970-01-01 00:00:00 +0000
+++ b/sql/ndb_repl_tab.h	2012-01-23 15:30:36 +0000
@@ -0,0 +1,256 @@
+/*
+   Copyright (c) 2012, 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_REPL_TAB_H
+#define NDB_REPL_TAB_H
+
+#include <my_global.h>
+
+#ifdef HAVE_NDB_BINLOG
+#include <ndbapi/NdbApi.hpp>
+
+/*
+  Ndb_rep_tab_key
+
+  This class represents the key columns of the
+  mysql.ndb_replication system table
+  It is used when reading values from that table
+*/
+class Ndb_rep_tab_key
+{
+public:
+  static const uint DB_MAXLEN= 63;
+  static const uint TABNAME_MAXLEN= 63;
+
+  /* Char arrays in varchar format with 1 length byte and
+   * trailing 0
+   */
+  char db[ DB_MAXLEN + 2 ];
+  char table_name[ TABNAME_MAXLEN + 2 ];
+  uint server_id;
+
+  Ndb_rep_tab_key()
+  {
+    db[0] = 0;
+    table_name[0] = 0;
+    server_id = 0;
+  }
+
+  /* Constructor from normal null terminated strings */
+  Ndb_rep_tab_key(const char* _db,
+                  const char* _table_name,
+                  uint _server_id);
+
+  /* Add null terminators to VARCHAR format string values */
+  void null_terminate_strings();
+
+  const char* get_db() const
+  {
+    return &db[1];
+  };
+
+  const char* get_table_name() const
+  {
+    return &table_name[1];
+  };
+
+  static const int MIN_MATCH_VAL = 1;
+  static const int EXACT_MATCH_DB = 4;
+  static const int EXACT_MATCH_TABLE_NAME = 2;
+  static const int EXACT_MATCH_SERVER_ID = 1;
+
+  static const int EXACT_MATCH_QUALITY =
+    MIN_MATCH_VAL +
+    EXACT_MATCH_DB +
+    EXACT_MATCH_TABLE_NAME +
+    EXACT_MATCH_SERVER_ID;
+
+  /*
+    This static method attempts an exact, then a wild
+    match between the passed key (with optional wild
+    characters), and the passed candidate row
+    returns :
+     1  : Exact match
+     0  : Wild match
+     -1 : No match
+  */
+  static int attempt_match(const char* keyptr,
+                           const uint keylen,
+                           const char* candidateptr,
+                           const uint candidatelen,
+                           const int exactmatchvalue);
+
+  /* This static method compares a fixed key value with
+   * a possibly wildcard containing candidate_row.
+   * If there is no match, 0 is returned.
+   * >0 means there is a match, with larger numbers
+   * indicating a better match quality.
+   * An exact match returns EXACT_MATCH_QUALITY
+   */
+  static int get_match_quality(const Ndb_rep_tab_key* key,
+                               const Ndb_rep_tab_key* candidate_row);
+};
+
+/*
+  Ndb_rep_tab_row
+
+  This class represents a row in the mysql.ndb_replication table
+*/
+class Ndb_rep_tab_row
+{
+public:
+  static const uint MAX_CONFLICT_FN_SPEC_LEN = 255;
+  static const uint CONFLICT_FN_SPEC_BUF_LEN =
+    MAX_CONFLICT_FN_SPEC_LEN + 1; /* Trailing '\0' */
+
+  Ndb_rep_tab_key key;
+  uint binlog_type;
+  bool cfs_is_null;
+  /* Buffer has space for leading length byte */
+  char conflict_fn_spec[ CONFLICT_FN_SPEC_BUF_LEN + 1 ];
+
+  Ndb_rep_tab_row()
+  {
+    cfs_is_null = true;
+  };
+
+  void null_terminate_strings()
+  {
+    key.null_terminate_strings();
+    uint speclen= 0;
+    speclen = conflict_fn_spec[0];
+
+    assert(speclen <= MAX_CONFLICT_FN_SPEC_LEN);
+    conflict_fn_spec[1 + speclen] = '\0';
+  }
+
+  const char* get_conflict_fn_spec()
+  {
+    return &conflict_fn_spec[1];
+  }
+
+  void set_conflict_fn_spec_null(bool null)
+  {
+    if (null)
+    {
+      cfs_is_null = true;
+      conflict_fn_spec[0] = 0;
+      conflict_fn_spec[1] = 0;
+    }
+    else
+    {
+      cfs_is_null = false;
+    }
+  }
+};
+
+/**
+   Ndb_rep_tab_reader
+
+   A helper class for accessing the mysql.ndb_replication
+   table
+*/
+class Ndb_rep_tab_reader
+{
+private:
+  static const char *ndb_rep_db;
+  static const char *ndb_replication_table;
+  static const char *nrt_db;
+  static const char *nrt_table_name;
+  static const char *nrt_server_id;
+  static const char *nrt_binlog_type;
+  static const char *nrt_conflict_fn;
+
+  Uint32 binlog_flags;
+  char conflict_fn_buffer[ Ndb_rep_tab_row::CONFLICT_FN_SPEC_BUF_LEN ];
+  char warning_msg_buffer[ FN_REFLEN ];
+
+  const char* conflict_fn_spec;
+  const char* warning_msg;
+
+  /**
+     check_schema
+
+     Checks that the schema of the mysql.ndb_replication table
+     is acceptable.
+     Returns
+     0 if ok
+     -1 if a column has an error.  Col name in error_str
+     -2 if there's a more general error.  Error description in
+        error_str
+  */
+  static
+  int check_schema(const NdbDictionary::Table* reptab,
+                   NdbDictionary::Dictionary* dict,
+                   const char** error_str);
+
+  /**
+     scan_candidates
+
+     Scans the ndb_replication table for rows matching the
+     passed db, table_name, server_id triple.
+     Returns the quality of the match made.
+
+     -1 = Error in processing, see msg
+     0 = No match, use defaults.
+     >0 = Use data in best_match
+
+     if msg is set on return it contains a warning.
+     Warnings may be produces in non error scenarios
+  */
+  int scan_candidates(Ndb* ndb,
+                      const NdbDictionary::Table* reptab,
+                      const char* db,
+                      const char* table_name,
+                      uint server_id,
+                      Ndb_rep_tab_row& best_match);
+public:
+  Ndb_rep_tab_reader();
+  ~Ndb_rep_tab_reader() {};
+
+  /**
+     lookup
+
+     lookup scans the mysql.ndb_replication table for
+     the best matching entry for the supplied db,
+     table_name, server_id triple.
+     A buffer for the conflict_fn spec, and for any
+     error or warning messages must be supplied.
+     The passed binlog_flags, conflict_fn_spec and
+     message may be updated as a result
+
+     Returns :
+       0  : Success.
+       <0 : Error.
+  */
+  int lookup(Ndb* ndb,
+             /* Keys */
+             const char* db,
+             const char* table_name,
+             uint server_id);
+
+  /* Following only valid after a call to lookup() */
+  Uint32 get_binlog_flags() const;
+  const char* get_conflict_fn_spec() const;
+  const char* get_warning_message() const;
+};
+
+/* #ifdef HAVE_NDB_BINLOG */
+#endif
+
+/* #ifdef NDB_REPL_TAB_H */
+#endif

=== added file 'sql/ndb_utils.h'
--- a/sql/ndb_utils.h	1970-01-01 00:00:00 +0000
+++ b/sql/ndb_utils.h	2012-01-23 15:30:36 +0000
@@ -0,0 +1,85 @@
+/*
+   Copyright (c) 2012 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_UTILS_H
+#define NDB_UTILS_H
+
+#include <ndbapi/NdbApi.hpp>
+
+class Ndb_table_guard
+{
+public:
+  Ndb_table_guard(NdbDictionary::Dictionary *dict)
+    : m_dict(dict), m_ndbtab(NULL), m_invalidate(0)
+  {}
+  Ndb_table_guard(NdbDictionary::Dictionary *dict, const char *tabname)
+    : m_dict(dict), m_ndbtab(NULL), m_invalidate(0)
+  {
+    DBUG_ENTER("Ndb_table_guard");
+    init(tabname);
+    DBUG_VOID_RETURN;
+  }
+  ~Ndb_table_guard()
+  {
+    DBUG_ENTER("~Ndb_table_guard");
+    reinit();
+    DBUG_VOID_RETURN;
+  }
+  void init(const char *tabname)
+  {
+    DBUG_ENTER("Ndb_table_guard::init");
+    /* must call reinit() if already initialized */
+    DBUG_ASSERT(m_ndbtab == NULL);
+    m_ndbtab= m_dict->getTableGlobal(tabname);
+    m_invalidate= 0;
+    DBUG_PRINT("info", ("m_ndbtab: %p", m_ndbtab));
+    DBUG_VOID_RETURN;
+  }
+  void reinit(const char *tabname= 0)
+  {
+    DBUG_ENTER("Ndb_table_guard::reinit");
+    if (m_ndbtab)
+    {
+      DBUG_PRINT("info", ("m_ndbtab: %p  m_invalidate: %d",
+                          m_ndbtab, m_invalidate));
+      m_dict->removeTableGlobal(*m_ndbtab, m_invalidate);
+      m_ndbtab= NULL;
+      m_invalidate= 0;
+    }
+    if (tabname)
+      init(tabname);
+    DBUG_PRINT("info", ("m_ndbtab: %p", m_ndbtab));
+    DBUG_VOID_RETURN;
+  }
+  const NdbDictionary::Table *get_table() { return m_ndbtab; }
+  void invalidate() { m_invalidate= 1; }
+  const NdbDictionary::Table *release()
+  {
+    DBUG_ENTER("Ndb_table_guard::release");
+    const NdbDictionary::Table *tmp= m_ndbtab;
+    DBUG_PRINT("info", ("m_ndbtab: %p", m_ndbtab));
+    m_ndbtab = 0;
+    DBUG_RETURN(tmp);
+  }
+private:
+  NdbDictionary::Dictionary *m_dict;
+  const NdbDictionary::Table *m_ndbtab;
+  int m_invalidate;
+};
+
+/* NDB_UTILS_H */
+#endif

No bundle (reason: useless for push emails).
Thread
bzr push into mysql-5.1-telco-7.0 branch (frazer.clement:4812 to 4813)WL#6147Frazer Clement23 Jan