From: Pekka Nousiainen Date: August 30 2012 12:59pm Subject: bzr push into mysql-5.5-cluster-7.3-fk branch (pekka.nousiainen:3902 to 3913) WL#6244 List-Archive: http://lists.mysql.com/commits/144664 Message-Id: <20120830125913.26781.94104.3913@cuda> MIME-Version: 1.0 Content-Type: text/plain; charset="us-ascii" Content-Transfer-Encoding: 7bit 3913 Pekka Nousiainen 2012-08-30 wl#6244 cleanup-x1 remove find_ndb_fk_tools.inc and enable windows modified: mysql-test/suite/ndb/t/ndb_fk_cascade_delete_multi.test 3912 Pekka Nousiainen 2012-08-30 wl#6244 cleanup remove usage of $CREATE_FK and use alter table instead. modified: mysql-test/suite/ndb/r/ndb_fk_cascade_delete_multi.result mysql-test/suite/ndb/t/ndb_fk_cascade_delete_multi.test 3911 Pekka Nousiainen 2012-08-30 wl#6244 mysql-is-x3 elide ndb error 21001 modified: mysql-test/suite/ndb/r/ndb_fk_is.result mysql-test/suite/ndb/t/ndb_fk_is.test 3910 Pekka Nousiainen 2012-08-30 wl#6244 mysql-is-x2 remove usage of have_ndb_fk.inc modified: mysql-test/suite/ndb/t/ndb_fk_is.test 3909 Pekka Nousiainen 2012-08-30 wl#6244 mysql-is-x1 a changed field name in 5.5 modified: sql/ha_ndb_ddl_fk.cc 3908 Pekka Nousiainen 2012-08-30 wl#6244 mysql-is Fix (and rudimentary test) information_schema wrt foreign keys in ndb added: mysql-test/suite/ndb/r/ndb_fk_is.result mysql-test/suite/ndb/t/ndb_fk_is.test modified: sql/ha_ndb_ddl_fk.cc 3907 Pekka Nousiainen 2012-08-30 wl#6244 mysql-mysqldump-x2 elide ndb error 21001 modified: mysql-test/suite/ndb/r/ndb_fk_mysqldump.result mysql-test/suite/ndb/t/ndb_fk_mysqldump.test 3906 Pekka Nousiainen 2012-08-30 wl#6244 mysql-mysqldump-x1 remove usage of have_ndb_fk.inc modified: mysql-test/suite/ndb/t/ndb_fk_mysqldump.test 3905 Pekka Nousiainen 2012-08-30 wl#6244 mysql-mysqldump Fix (and rudimentary test) mysqldump wrt foreign keys in ndb added: mysql-test/suite/ndb/r/ndb_fk_mysqldump.result mysql-test/suite/ndb/t/ndb_fk_mysqldump.test modified: sql/ha_ndb_ddl_fk.cc 3904 Pekka Nousiainen 2012-08-30 wl#6244 mysql-db-x1 remove usage of have_ndb_fk.inc modified: mysql-test/suite/ndb/t/ndb_fk_db.test 3903 Pekka Nousiainen 2012-08-30 wl#6244 mysql-db Fix (and rudimentary test) cross database foreign keys added: mysql-test/suite/ndb/r/ndb_fk_db.result mysql-test/suite/ndb/t/ndb_fk_db.test modified: sql/ha_ndb_ddl_fk.cc 3902 magnus.blaudd@stripped 2012-07-13 ndb test - don't run ndb_fk_cascade_delete_multi on Windows until we have removed the use of create and drop_fk tools completely modified: mysql-test/suite/ndb/t/ndb_fk_cascade_delete_multi.test === modified file 'mysql-test/suite/ndb/r/ndb_fk_cascade_delete_multi.result' --- a/mysql-test/suite/ndb/r/ndb_fk_cascade_delete_multi.result 2012-05-16 09:58:21 +0000 +++ b/mysql-test/suite/ndb/r/ndb_fk_cascade_delete_multi.result 2012-08-30 12:57:03 +0000 @@ -82,6 +82,8 @@ id value parent left_child right_child 4 2-leaf 1 NULL NULL 5 4-leaf 2 NULL NULL 6 6-leaf 2 NULL NULL +alter table tree add constraint fk_parent foreign key (parent) references tree(id) on update restrict on delete cascade; +alter table tree add constraint fk_left foreign key (left_child) references tree(id) on update restrict on delete cascade; begin; delete from tree where value = '5-inner'; select * from tree order by 1; === added file 'mysql-test/suite/ndb/r/ndb_fk_db.result' --- a/mysql-test/suite/ndb/r/ndb_fk_db.result 1970-01-01 00:00:00 +0000 +++ b/mysql-test/suite/ndb/r/ndb_fk_db.result 2012-08-30 11:55:25 +0000 @@ -0,0 +1,142 @@ +create database mydb0; +use mydb0; +create table parent ( +a int primary key, +b int not null, +c int not null, +unique(b) using hash, +index(c)) engine = ndb; +create database mydb1; +use mydb1; +create table child ( +a int primary key, +b int not null, +c int not null, +constraint fk1 foreign key(a) references mydb0.parent (a), +unique(b) using hash, +index(c)) engine = ndb; +show create table child; +Table Create Table +child CREATE TABLE `child` ( + `a` int(11) NOT NULL, + `b` int(11) NOT NULL, + `c` int(11) NOT NULL, + PRIMARY KEY (`a`), + UNIQUE KEY `b` (`b`) USING HASH, + KEY `c` (`c`), + CONSTRAINT `fk1` FOREIGN KEY(`a`) REFERENCES `mydb0`.`parent` (`a`) ON DELETE NO ACTION ON UPDATE NO ACTION +) ENGINE=ndbcluster DEFAULT CHARSET=latin1 +alter offline table child add constraint fk2 foreign key (b) +references mydb0.parent(a); +show create table child; +Table Create Table +child CREATE TABLE `child` ( + `a` int(11) NOT NULL, + `b` int(11) NOT NULL, + `c` int(11) NOT NULL, + PRIMARY KEY (`a`), + UNIQUE KEY `b` (`b`) USING HASH, + KEY `c` (`c`), + CONSTRAINT `fk1` FOREIGN KEY(`a`) REFERENCES `mydb0`.`parent` (`a`) ON DELETE NO ACTION ON UPDATE NO ACTION, + CONSTRAINT `fk2` FOREIGN KEY(`b`) REFERENCES `mydb0`.`parent` (`a`) ON DELETE NO ACTION ON UPDATE NO ACTION +) ENGINE=ndbcluster DEFAULT CHARSET=latin1 +alter online table child add constraint fk3 foreign key (c) +references mydb0.parent(a); +show create table child; +Table Create Table +child CREATE TABLE `child` ( + `a` int(11) NOT NULL, + `b` int(11) NOT NULL, + `c` int(11) NOT NULL, + PRIMARY KEY (`a`), + UNIQUE KEY `b` (`b`) USING HASH, + KEY `c` (`c`), + CONSTRAINT `fk1` FOREIGN KEY(`a`) REFERENCES `mydb0`.`parent` (`a`) ON DELETE NO ACTION ON UPDATE NO ACTION, + CONSTRAINT `fk2` FOREIGN KEY(`b`) REFERENCES `mydb0`.`parent` (`a`) ON DELETE NO ACTION ON UPDATE NO ACTION, + CONSTRAINT `fk3` FOREIGN KEY(`c`) REFERENCES `mydb0`.`parent` (`a`) ON DELETE NO ACTION ON UPDATE NO ACTION +) ENGINE=ndbcluster DEFAULT CHARSET=latin1 +alter offline table child drop foreign key fk2; +show create table child; +Table Create Table +child CREATE TABLE `child` ( + `a` int(11) NOT NULL, + `b` int(11) NOT NULL, + `c` int(11) NOT NULL, + PRIMARY KEY (`a`), + UNIQUE KEY `b` (`b`) USING HASH, + KEY `c` (`c`), + CONSTRAINT `fk1` FOREIGN KEY(`a`) REFERENCES `mydb0`.`parent` (`a`) ON DELETE NO ACTION ON UPDATE NO ACTION, + CONSTRAINT `fk3` FOREIGN KEY(`c`) REFERENCES `mydb0`.`parent` (`a`) ON DELETE NO ACTION ON UPDATE NO ACTION +) ENGINE=ndbcluster DEFAULT CHARSET=latin1 +alter online table child drop foreign key fk3; +show create table child; +Table Create Table +child CREATE TABLE `child` ( + `a` int(11) NOT NULL, + `b` int(11) NOT NULL, + `c` int(11) NOT NULL, + PRIMARY KEY (`a`), + UNIQUE KEY `b` (`b`) USING HASH, + KEY `c` (`c`), + CONSTRAINT `fk1` FOREIGN KEY(`a`) REFERENCES `mydb0`.`parent` (`a`) ON DELETE NO ACTION ON UPDATE NO ACTION +) ENGINE=ndbcluster DEFAULT CHARSET=latin1 +alter offline table mydb0.parent rename mydb1.parent; +show create table child; +Table Create Table +child CREATE TABLE `child` ( + `a` int(11) NOT NULL, + `b` int(11) NOT NULL, + `c` int(11) NOT NULL, + PRIMARY KEY (`a`), + UNIQUE KEY `b` (`b`) USING HASH, + KEY `c` (`c`), + CONSTRAINT `fk1` FOREIGN KEY(`a`) REFERENCES `parent` (`a`) ON DELETE NO ACTION ON UPDATE NO ACTION +) ENGINE=ndbcluster DEFAULT CHARSET=latin1 +alter online table mydb1.parent rename mydb0.parent; +show create table child; +Table Create Table +child CREATE TABLE `child` ( + `a` int(11) NOT NULL, + `b` int(11) NOT NULL, + `c` int(11) NOT NULL, + PRIMARY KEY (`a`), + UNIQUE KEY `b` (`b`) USING HASH, + KEY `c` (`c`), + CONSTRAINT `fk1` FOREIGN KEY(`a`) REFERENCES `mydb0`.`parent` (`a`) ON DELETE NO ACTION ON UPDATE NO ACTION +) ENGINE=ndbcluster DEFAULT CHARSET=latin1 +use test; +alter offline table mydb1.child add constraint fk2 foreign key (b) +references mydb0.parent(a); +use mydb1; +show create table child; +Table Create Table +child CREATE TABLE `child` ( + `a` int(11) NOT NULL, + `b` int(11) NOT NULL, + `c` int(11) NOT NULL, + PRIMARY KEY (`a`), + UNIQUE KEY `b` (`b`) USING HASH, + KEY `c` (`c`), + CONSTRAINT `fk1` FOREIGN KEY(`a`) REFERENCES `mydb0`.`parent` (`a`) ON DELETE NO ACTION ON UPDATE NO ACTION, + CONSTRAINT `fk2` FOREIGN KEY(`b`) REFERENCES `mydb0`.`parent` (`a`) ON DELETE NO ACTION ON UPDATE NO ACTION +) ENGINE=ndbcluster DEFAULT CHARSET=latin1 +use test; +alter online table mydb1.child add constraint fk3 foreign key (c) +references mydb0.parent(a); +use mydb1; +show create table child; +Table Create Table +child CREATE TABLE `child` ( + `a` int(11) NOT NULL, + `b` int(11) NOT NULL, + `c` int(11) NOT NULL, + PRIMARY KEY (`a`), + UNIQUE KEY `b` (`b`) USING HASH, + KEY `c` (`c`), + CONSTRAINT `fk1` FOREIGN KEY(`a`) REFERENCES `mydb0`.`parent` (`a`) ON DELETE NO ACTION ON UPDATE NO ACTION, + CONSTRAINT `fk2` FOREIGN KEY(`b`) REFERENCES `mydb0`.`parent` (`a`) ON DELETE NO ACTION ON UPDATE NO ACTION, + CONSTRAINT `fk3` FOREIGN KEY(`c`) REFERENCES `mydb0`.`parent` (`a`) ON DELETE NO ACTION ON UPDATE NO ACTION +) ENGINE=ndbcluster DEFAULT CHARSET=latin1 +use test; +drop database mydb0; +drop database mydb1; === added file 'mysql-test/suite/ndb/r/ndb_fk_is.result' --- a/mysql-test/suite/ndb/r/ndb_fk_is.result 1970-01-01 00:00:00 +0000 +++ b/mysql-test/suite/ndb/r/ndb_fk_is.result 2012-08-30 12:56:15 +0000 @@ -0,0 +1,35 @@ +create table product ( +category int not null, +id int not null, +price decimal, +primary key(category, id)) +engine=ndb; +create table customer ( +id int not null, +primary key (id)) +engine=ndb; +create table product_order ( +no int not null auto_increment, +product_category int not null, +product_id int not null, +customer_id int not null, +primary key(no), +index (product_category, product_id), +foreign key (product_category, product_id) references product(category, id) +on update restrict on delete cascade, +index (customer_id), +foreign key (customer_id) references customer(id)) +engine=ndb; +select * +from information_schema.table_constraints +where table_schema = 'test' +order by table_name, constraint_name; +CONSTRAINT_CATALOG CONSTRAINT_SCHEMA CONSTRAINT_NAME TABLE_SCHEMA TABLE_NAME CONSTRAINT_TYPE +def test FK_12_17 test customer FOREIGN KEY +def test PRIMARY test customer PRIMARY KEY +def test FK_10_16 test product FOREIGN KEY +def test PRIMARY test product PRIMARY KEY +def test FK_10_16 test product_order FOREIGN KEY +def test FK_12_17 test product_order FOREIGN KEY +def test PRIMARY test product_order PRIMARY KEY +drop table product, customer, product_order; === added file 'mysql-test/suite/ndb/r/ndb_fk_mysqldump.result' --- a/mysql-test/suite/ndb/r/ndb_fk_mysqldump.result 1970-01-01 00:00:00 +0000 +++ b/mysql-test/suite/ndb/r/ndb_fk_mysqldump.result 2012-08-30 12:53:40 +0000 @@ -0,0 +1,80 @@ +create table product ( +category int not null, +id int not null, +price decimal, +primary key(category, id)) +engine=ndb; +create table customer ( +id int not null, +primary key (id)) +engine=ndb; +create table product_order ( +no int not null auto_increment, +product_category int not null, +product_id int not null, +customer_id int not null, +primary key(no), +index (product_category, product_id), +foreign key (product_category, product_id) references product(category, id) +on update restrict on delete cascade, +index (customer_id), +foreign key (customer_id) references customer(id)) +engine=ndb; +show create table product; +Table Create Table +product CREATE TABLE `product` ( + `category` int(11) NOT NULL, + `id` int(11) NOT NULL, + `price` decimal(10,0) DEFAULT NULL, + PRIMARY KEY (`category`,`id`) +) ENGINE=ndbcluster DEFAULT CHARSET=latin1 +show create table customer; +Table Create Table +customer CREATE TABLE `customer` ( + `id` int(11) NOT NULL, + PRIMARY KEY (`id`) +) ENGINE=ndbcluster DEFAULT CHARSET=latin1 +show create table product_order; +Table Create Table +product_order CREATE TABLE `product_order` ( + `no` int(11) NOT NULL AUTO_INCREMENT, + `product_category` int(11) NOT NULL, + `product_id` int(11) NOT NULL, + `customer_id` int(11) NOT NULL, + PRIMARY KEY (`no`), + KEY `product_category` (`product_category`,`product_id`), + KEY `customer_id` (`customer_id`), + CONSTRAINT `FK_10_16` FOREIGN KEY(`product_category`,`product_id`) REFERENCES `product` (`category`,`id`) ON DELETE CASCADE ON UPDATE RESTRICT, + CONSTRAINT `FK_12_17` FOREIGN KEY(`customer_id`) REFERENCES `customer` (`id`) ON DELETE NO ACTION ON UPDATE NO ACTION +) ENGINE=ndbcluster DEFAULT CHARSET=latin1 +insert into product values (1,1,5); +insert into customer value (1); +insert into product_order value (1,1,1,1); +show create table product; +Table Create Table +product CREATE TABLE `product` ( + `category` int(11) NOT NULL, + `id` int(11) NOT NULL, + `price` decimal(10,0) DEFAULT NULL, + PRIMARY KEY (`category`,`id`) +) ENGINE=ndbcluster DEFAULT CHARSET=latin1 +show create table customer; +Table Create Table +customer CREATE TABLE `customer` ( + `id` int(11) NOT NULL, + PRIMARY KEY (`id`) +) ENGINE=ndbcluster DEFAULT CHARSET=latin1 +show create table product_order; +Table Create Table +product_order CREATE TABLE `product_order` ( + `no` int(11) NOT NULL AUTO_INCREMENT, + `product_category` int(11) NOT NULL, + `product_id` int(11) NOT NULL, + `customer_id` int(11) NOT NULL, + PRIMARY KEY (`no`), + KEY `product_category` (`product_category`,`product_id`), + KEY `customer_id` (`customer_id`), + CONSTRAINT `FK_10_16` FOREIGN KEY(`product_category`,`product_id`) REFERENCES `product` (`category`,`id`) ON DELETE CASCADE ON UPDATE RESTRICT, + CONSTRAINT `FK_12_17` FOREIGN KEY(`customer_id`) REFERENCES `customer` (`id`) ON DELETE NO ACTION ON UPDATE NO ACTION +) ENGINE=ndbcluster AUTO_INCREMENT=2 DEFAULT CHARSET=latin1 +drop table product, customer, product_order; === modified file 'mysql-test/suite/ndb/t/ndb_fk_cascade_delete_multi.test' --- a/mysql-test/suite/ndb/t/ndb_fk_cascade_delete_multi.test 2012-07-13 13:46:09 +0000 +++ b/mysql-test/suite/ndb/t/ndb_fk_cascade_delete_multi.test 2012-08-30 12:57:36 +0000 @@ -1,8 +1,4 @@ -# Does not work on Windows until we got rid of create_fk and drop_fk --- source include/not_windows.inc - -- source include/have_ndb.inc --- source find_ndb_fk_tools.inc create table emp ( id int primary key auto_increment, @@ -63,12 +59,8 @@ insert into tree values (6, '6-leaf', select * from tree order by 1; ---let $parentname=parent ---let $leftname=left_child\$unique ---let $rightname=left_child\$unique ---exec $CREATE_FK --database=test --parent=tree --child=tree --child-index='$parentname' --on-update-action=restrict --on-delete-action=cascade fk_parent > /dev/null ---exec $CREATE_FK --database=test --parent=tree --child=tree --child-index='$leftname' --on-update-action=restrict --on-delete-action=cascade fk_left > /dev/null ---exec $CREATE_FK --database=test --parent=tree --child=tree --child-index='$rightname' --on-update-action=restrict --on-delete-action=cascade fk_right > /dev/null +alter table tree add constraint fk_parent foreign key (parent) references tree(id) on update restrict on delete cascade; +alter table tree add constraint fk_left foreign key (left_child) references tree(id) on update restrict on delete cascade; begin; delete from tree where value = '5-inner'; @@ -85,8 +77,4 @@ delete from tree where value = '3-root'; select * from tree order by 1; commit; ---exec $DROP_FK --database=test fk_parent > /dev/null ---exec $DROP_FK --database=test fk_left > /dev/null ---exec $DROP_FK --database=test fk_right > /dev/null - drop table tree; === added file 'mysql-test/suite/ndb/t/ndb_fk_db.test' --- a/mysql-test/suite/ndb/t/ndb_fk_db.test 1970-01-01 00:00:00 +0000 +++ b/mysql-test/suite/ndb/t/ndb_fk_db.test 2012-08-30 12:50:34 +0000 @@ -0,0 +1,66 @@ +-- source include/have_ndb.inc + +create database mydb0; +use mydb0; + +create table parent ( + a int primary key, + b int not null, + c int not null, + unique(b) using hash, + index(c)) engine = ndb; + +create database mydb1; +use mydb1; + +create table child ( + a int primary key, + b int not null, + c int not null, + constraint fk1 foreign key(a) references mydb0.parent (a), + unique(b) using hash, + index(c)) engine = ndb; + +show create table child; + +alter offline table child add constraint fk2 foreign key (b) + references mydb0.parent(a); + +show create table child; + +alter online table child add constraint fk3 foreign key (c) + references mydb0.parent(a); + +show create table child; + +alter offline table child drop foreign key fk2; + +show create table child; + +alter online table child drop foreign key fk3; + +show create table child; + +alter offline table mydb0.parent rename mydb1.parent; + +show create table child; + +alter online table mydb1.parent rename mydb0.parent; + +show create table child; + +use test; +alter offline table mydb1.child add constraint fk2 foreign key (b) + references mydb0.parent(a); +use mydb1; +show create table child; + +use test; +alter online table mydb1.child add constraint fk3 foreign key (c) + references mydb0.parent(a); +use mydb1; +show create table child; + +use test; +drop database mydb0; +drop database mydb1; === added file 'mysql-test/suite/ndb/t/ndb_fk_is.test' --- a/mysql-test/suite/ndb/t/ndb_fk_is.test 1970-01-01 00:00:00 +0000 +++ b/mysql-test/suite/ndb/t/ndb_fk_is.test 2012-08-30 12:56:15 +0000 @@ -0,0 +1,33 @@ +-- source include/have_ndb.inc + +create table product ( + category int not null, + id int not null, + price decimal, + primary key(category, id)) +engine=ndb; + +create table customer ( + id int not null, + primary key (id)) +engine=ndb; + +create table product_order ( + no int not null auto_increment, + product_category int not null, + product_id int not null, + customer_id int not null, + primary key(no), + index (product_category, product_id), + foreign key (product_category, product_id) references product(category, id) + on update restrict on delete cascade, + index (customer_id), + foreign key (customer_id) references customer(id)) +engine=ndb; + +select * +from information_schema.table_constraints +where table_schema = 'test' +order by table_name, constraint_name; + +drop table product, customer, product_order; === added file 'mysql-test/suite/ndb/t/ndb_fk_mysqldump.test' --- a/mysql-test/suite/ndb/t/ndb_fk_mysqldump.test 1970-01-01 00:00:00 +0000 +++ b/mysql-test/suite/ndb/t/ndb_fk_mysqldump.test 2012-08-30 12:53:40 +0000 @@ -0,0 +1,47 @@ +-- source include/have_ndb.inc + +# test uses mysqldump, hence not in embedded +-- source include/not_embedded.inc + +create table product ( + category int not null, + id int not null, + price decimal, + primary key(category, id)) +engine=ndb; + +create table customer ( + id int not null, + primary key (id)) +engine=ndb; + +create table product_order ( + no int not null auto_increment, + product_category int not null, + product_id int not null, + customer_id int not null, + primary key(no), + index (product_category, product_id), + foreign key (product_category, product_id) references product(category, id) + on update restrict on delete cascade, + index (customer_id), + foreign key (customer_id) references customer(id)) +engine=ndb; + +show create table product; +show create table customer; +show create table product_order; + +insert into product values (1,1,5); +insert into customer value (1); +insert into product_order value (1,1,1,1); + +let $dump_file = $MYSQLTEST_VARDIR/tmp/ndb_fk_dump.sql; +--exec $MYSQL_DUMP --databases test > $dump_file +--exec $MYSQL test < $dump_file + +show create table product; +show create table customer; +show create table product_order; + +drop table product, customer, product_order; === modified file 'sql/ha_ndb_ddl_fk.cc' --- a/sql/ha_ndb_ddl_fk.cc 2012-05-28 12:57:40 +0000 +++ b/sql/ha_ndb_ddl_fk.cc 2012-08-30 12:55:24 +0000 @@ -152,6 +152,35 @@ found: return best_matching_index; // NOTE: also returns reference } + +static +void +setDbName(Ndb* ndb, const char * name) +{ + if (name && strlen(name) != 0) + { + ndb->setDatabaseName(name); + } +} + +struct Ndb_db_guard +{ + Ndb_db_guard(Ndb* ndb) { + this->ndb = ndb; + strcpy(save_db, ndb->getDatabaseName()); + } + + void restore() { + ndb->setDatabaseName(save_db); + } + + ~Ndb_db_guard() { + ndb->setDatabaseName(save_db); + } +private: + Ndb* ndb; + char save_db[FN_REFLEN + 1]; +}; /** * ndbapi want's c-strings (null terminated) @@ -198,9 +227,6 @@ ha_ndbcluster::create_fks(THD *thd, Ndb const int er_default= ER_CANNOT_ADD_FOREIGN; char tmpbuf[FN_REFLEN]; - /** - * TODO handle databases too... - */ assert(thd->lex != 0); Key * key= 0; List_iterator key_iterator(thd->lex->alter_info.key_list); @@ -256,10 +282,31 @@ ha_ndbcluster::create_fks(THD *thd, Ndb DBUG_RETURN(er_default); // TODO suitable error code } + Ndb_db_guard db_guard(ndb); // save db + + char parent_db[FN_REFLEN]; char parent_name[FN_REFLEN]; - my_snprintf(parent_name, sizeof(parent_name), "%*s", - (int)fk->ref_table->table.length, - fk->ref_table->table.str); + if (fk->ref_table->db.length != 0 && fk->ref_table->db.str != 0) + { + my_snprintf(parent_db, sizeof(parent_db), "%*s", + (int)fk->ref_table->db.length, + fk->ref_table->db.str); + } + else + { + parent_db[0]= 0; + } + if (fk->ref_table->table.length != 0 && fk->ref_table->table.str != 0) + { + my_snprintf(parent_name, sizeof(parent_name), "%*s", + (int)fk->ref_table->table.length, + fk->ref_table->table.str); + } + else + { + parent_name[0]= 0; + } + setDbName(ndb, parent_db); Ndb_table_guard parent_tab(dict, parent_name); if (parent_tab.get_table() == 0) { @@ -291,6 +338,8 @@ ha_ndbcluster::create_fks(THD *thd, Ndb parentcols, parent_primary_key); + db_guard.restore(); // restore db + if (!parent_primary_key && parent_index == 0) { DBUG_RETURN(er_default); // TODO suitable error code @@ -397,24 +446,6 @@ ha_ndbcluster::is_fk_defined_on_table_or return FALSE; } -int -ha_ndbcluster::get_foreign_key_list(THD *thd, - List * f_key_list) -{ - DBUG_ENTER("ha_ndbcluster::get_foreign_key_list"); - Ndb *ndb= get_ndb(thd); - if (ndb == 0) - { - DBUG_RETURN(0); - } - - /** - * TODO - */ - - DBUG_RETURN(0); -} - uint ha_ndbcluster::referenced_by_foreign_key() { @@ -515,6 +546,170 @@ fk_split_name(char dst[], const char * s return dstptr; } +int +ha_ndbcluster::get_foreign_key_list(THD *thd, + List * f_key_list) +{ + DBUG_ENTER("ha_ndbcluster::get_foreign_key_list"); + if (thd == 0) + { + DBUG_RETURN(0); + } + + if (m_table == 0) + { + DBUG_RETURN(0); + } + + Ndb *ndb= get_ndb(thd); + if (ndb == 0) + { + DBUG_RETURN(0); + } + + NDBDICT *dict= ndb->getDictionary(); + NDBDICT::List obj_list; + dict->listDependentObjects(obj_list, *m_table); + for (unsigned i = 0; i < obj_list.count; i++) + { + if (obj_list.elements[i].type != NdbDictionary::Object::ForeignKey) + continue; + + FOREIGN_KEY_INFO f_key_info; + + NdbDictionary::ForeignKey fk; + int res= dict->getForeignKey(fk, obj_list.elements[i].name); + if (res != 0) + { + DBUG_RETURN(1); // TODO suitable error code + } + + { + char fk_full_name[FN_LEN + 1]; + const char * name = fk_split_name(fk_full_name, fk.getName()); + f_key_info.foreign_id = thd_make_lex_string(thd, 0, name, + (uint)strlen(name), 1); + } + + for (unsigned i = 0; i < fk.getParentColumnCount(); i++) + { + const NdbDictionary::Column * col = + m_table->getColumn(fk.getParentColumnNo(i)); + if (col == 0) + { + DBUG_RETURN(1); // TODO suitable error code + } + LEX_STRING * name = thd_make_lex_string(thd, 0, + col->getName(), + (uint)strlen(col->getName()), 1); + f_key_info.foreign_fields.push_back(name); + } + + { + char child_db_and_name[FN_LEN + 1]; + const char * child_name = fk_split_name(child_db_and_name, + fk.getChildTable()); + f_key_info.referenced_db = + thd_make_lex_string(thd, 0, child_db_and_name, + (uint)strlen(child_db_and_name), + 1); + + Ndb_db_guard db_guard(ndb); + setDbName(ndb, child_db_and_name); + Ndb_table_guard child_tab(dict, child_name); + if (child_tab.get_table() == 0) + { + ERR_RETURN(dict->getNdbError()); + } + + for (unsigned i = 0; i < fk.getChildColumnCount(); i++) + { + const NdbDictionary::Column * col = + child_tab.get_table()->getColumn(fk.getChildColumnNo(i)); + if (col == 0) + { + DBUG_RETURN(1); // TODO suitable error code + } + LEX_STRING * name = + thd_make_lex_string(thd, 0, col->getName(), + (uint)strlen(col->getName()), 1); + f_key_info.referenced_fields.push_back(name); + } + } + + { + const char *update_method = 0; + switch(fk.getOnUpdateAction()){ + case NdbDictionary::ForeignKey::NoAction: + update_method = "NO ACTION"; + break; + case NdbDictionary::ForeignKey::Restrict: + update_method = "RESTRICT"; + break; + case NdbDictionary::ForeignKey::Cascade: + update_method = "CASCADE"; + break; + case NdbDictionary::ForeignKey::SetNull: + update_method = "SET NULL"; + break; + case NdbDictionary::ForeignKey::SetDefault: + update_method = "SET DEFAULT"; + break; + } + f_key_info.update_method = + thd_make_lex_string(thd, 0, update_method, + (uint)strlen(update_method), + 1); + } + + { + const char *delete_method = ""; + switch(fk.getOnDeleteAction()){ + case NdbDictionary::ForeignKey::NoAction: + delete_method = "NO ACTION"; + break; + case NdbDictionary::ForeignKey::Restrict: + delete_method = "RESTRICT"; + break; + case NdbDictionary::ForeignKey::Cascade: + delete_method = "CASCADE"; + break; + case NdbDictionary::ForeignKey::SetNull: + delete_method = "SET NULL"; + break; + case NdbDictionary::ForeignKey::SetDefault: + delete_method = "SET DEFAULT"; + break; + } + f_key_info.delete_method = + thd_make_lex_string(thd, 0, delete_method, + (uint)strlen(delete_method), + 1); + } + + if (fk.getChildIndex() != 0) + { + f_key_info.referenced_key_name = + thd_make_lex_string(thd, 0, fk.getChildIndex(), + (uint)strlen(fk.getChildIndex()), + 1); + } + else + { + f_key_info.referenced_key_name = 0; + } + + List foreign_fields; + List referenced_fields; + + FOREIGN_KEY_INFO *pf_key_info = (FOREIGN_KEY_INFO *) + thd_memdup(thd, &f_key_info, sizeof(FOREIGN_KEY_INFO)); + f_key_list->push_back(pf_key_info); + } + + DBUG_RETURN(0); +} + static int cmp_fk_name(const void * _e0, const void * _e1) @@ -595,10 +790,10 @@ ha_ndbcluster::get_foreign_key_create_in const NDBTAB * childtab= 0; const NDBTAB * parenttab= 0; + char parent_db_and_name[FN_LEN + 1]; { - char db_and_name[FN_LEN + 1]; - const char * name = fk_split_name(db_and_name, fk.getParentTable()); - ndb->setDatabaseName(db_and_name); + const char * name = fk_split_name(parent_db_and_name,fk.getParentTable()); + setDbName(ndb, parent_db_and_name); parenttab= dict->getTableGlobal(name); if (parenttab == 0) { @@ -607,10 +802,10 @@ ha_ndbcluster::get_foreign_key_create_in } } + char child_db_and_name[FN_LEN + 1]; { - char db_and_name[FN_LEN + 1]; - const char * name = fk_split_name(db_and_name, fk.getChildTable()); - ndb->setDatabaseName(db_and_name); + const char * name = fk_split_name(child_db_and_name, fk.getChildTable()); + setDbName(ndb, child_db_and_name); childtab= dict->getTableGlobal(name); if (childtab == 0) { @@ -619,6 +814,17 @@ ha_ndbcluster::get_foreign_key_create_in } } + if (! (strcmp(child_db_and_name, m_dbname) == 0 && + strcmp(childtab->getName(), m_tabname) == 0)) + { + /** + * this was on parent table (fk are shown on child table in SQL) + */ + assert(strcmp(parent_db_and_name, m_dbname) == 0); + assert(strcmp(parenttab->getName(), m_tabname) == 0); + continue; + } + fk_string.append(","); fk_string.append("\n "); fk_string.append("CONSTRAINT `"); @@ -646,6 +852,11 @@ ha_ndbcluster::get_foreign_key_create_in } fk_string.append(") REFERENCES `"); + if (strcmp(parent_db_and_name, child_db_and_name) != 0) + { + fk_string.append(parent_db_and_name); + fk_string.append("`.`"); + } fk_string.append(parenttab->getName()); fk_string.append("` ("); @@ -746,6 +957,7 @@ ha_ndbcluster::copy_fk_for_offline_alter DBUG_RETURN(0); } + Ndb_db_guard db_guard(ndb); const char * src_db = thd->lex->select_lex.table_list.first->db; const char * src_tab = thd->lex->select_lex.table_list.first->table_name; @@ -757,6 +969,7 @@ ha_ndbcluster::copy_fk_for_offline_alter assert(thd->lex != 0); NDBDICT* dict = ndb->getDictionary(); + setDbName(ndb, src_db); Ndb_table_guard srctab(dict, src_tab); if (srctab.get_table() == 0) { @@ -766,12 +979,14 @@ ha_ndbcluster::copy_fk_for_offline_alter DBUG_RETURN(0); } + db_guard.restore(); Ndb_table_guard dsttab(dict, _dsttab->getName()); if (dsttab.get_table() == 0) { ERR_RETURN(dict->getNdbError()); } + setDbName(ndb, src_db); NDBDICT::List obj_list; dict->listDependentObjects(obj_list, *srctab.get_table()); for (unsigned i = 0; i < obj_list.count; i++) @@ -820,6 +1035,7 @@ ha_ndbcluster::copy_fk_for_offline_alter { char db_and_name[FN_LEN + 1]; const char * name= fk_split_name(db_and_name, fk.getParentTable()); + setDbName(ndb, db_and_name); Ndb_table_guard org_parent(dict, name); if (org_parent.get_table() == 0) { @@ -831,6 +1047,7 @@ ha_ndbcluster::copy_fk_for_offline_alter { char db_and_name[FN_LEN + 1]; const char * name= fk_split_name(db_and_name, fk.getChildTable()); + setDbName(ndb, db_and_name); Ndb_table_guard org_child(dict, name); if (org_child.get_table() == 0) { @@ -858,6 +1075,7 @@ ha_ndbcluster::copy_fk_for_offline_alter if (fk.getParentIndex() != 0) { name = fk_split_name(db_and_name, fk.getParentIndex(), true); + setDbName(ndb, db_and_name); const NDBINDEX * idx = dict->getIndexGlobal(name,*dsttab.get_table()); if (idx == 0) { @@ -892,6 +1110,7 @@ ha_ndbcluster::copy_fk_for_offline_alter if (fk.getChildIndex() != 0) { name = fk_split_name(db_and_name, fk.getChildIndex(), true); + setDbName(ndb, db_and_name); const NDBINDEX * idx = dict->getIndexGlobal(name,*dsttab.get_table()); if (idx == 0) { @@ -918,6 +1137,7 @@ ha_ndbcluster::copy_fk_for_offline_alter childObjectId, name); fk.setName(new_name); + setDbName(ndb, db_and_name); if (dict->createForeignKey(fk) != 0) { ERR_RETURN(dict->getNdbError()); No bundle (reason: useless for push emails).