# # Print the foreign key definitions for the given table and then # verify that they are consistent in DD and NDB # # ==== Usage ==== # [--let $ndb_db_name= ] # --let $ndb_table_name= # --source verify_foreign_keys.inc # # Parameters: # $ndb_db_name, $ndb_table_name # DB and name of the table from which the names of # FKs should to be printed and verified # Note : default db name "test" will be used if # none is passed to $ndb_db_name # # Table name is mandatory option if (!$ndb_table_name) { --die ERROR IN TEST: Please set $ndb_table_name before calling verify_foreign_keys.inc script } if (!$ndb_db_name) { let $ndb_db_name=test; } # Print foreign key definitions using show create table eval SHOW CREATE TABLE $ndb_db_name.$ndb_table_name; --disable_query_log # Create view which displays all user tables and foreign keys. # NOTE! Uses a format which is backward compatible with the output # from "ndb_show_tables" previously used by this test CREATE VIEW test.ndb_object_list AS SELECT id, /* Hardcoded names for the types selected */ CASE type WHEN 2 THEN "UserTable" WHEN 25 THEN "ForeignKey" ELSE "UnexpectedType" END AS type, /* Database is first part of fq_name for user tables */ CASE type WHEN 2 THEN SUBSTRING_INDEX(fq_name, "/", 1) ELSE "" END AS _database, /* Table name is last part of fq_name for user tables and fq_name for fk */ CASE type WHEN 2 THEN SUBSTRING_INDEX(fq_name, "/", -1) ELSE fq_name END AS name FROM ndbinfo.dict_obj_info WHERE type IN ( 2 /* User table */, 25 /* Foreign key definition */); # Find the object id of the table whose FKs we have to list and verify let $ndb_table_id= `SELECT id FROM ndb_object_list WHERE type = "UserTable" AND _database = "$ndb_db_name" AND name = "$ndb_table_name"`; # Now list all the foreign key names using this table id. # They will be of form /<$table_id(child)>/fk_name # Also extract the parent table name to verify it with the ones stored in DD CREATE TABLE test.ndb_fk_info (name VARCHAR(255), parent VARCHAR(255)) engine ndb; eval INSERT INTO test.ndb_fk_info SELECT REGEXP_REPLACE(fk_info.name, '[0-9]+/$ndb_table_id/', ''), parent_info.name FROM test.ndb_object_list as fk_info, test.ndb_object_list as parent_info WHERE fk_info.type = 'ForeignKey' AND fk_info.name LIKE '%/$ndb_table_id/%' AND parent_info.type = 'UserTable' AND parent_info.id = REGEXP_REPLACE(fk_info.name, '/$ndb_table_id/.+', ''); let $ndb_fk_count= `SELECT count(*) FROM ndb_fk_info`; # Verify that the same set of FKs are present in NDB and DD # Do left and right outer joins to detect if either DD or NDB has # any foreign key that does not have a match yet. let $fks_in_ndb_but_not_in_dd= `SELECT COUNT(*) FROM test.ndb_fk_info as ndb LEFT JOIN information_schema.referential_constraints as dd ON ndb.name = dd.constraint_name WHERE dd.constraint_name is NULL`; let $fks_in_dd_but_not_in_ndb= `SELECT COUNT(*) FROM test.ndb_fk_info as ndb RIGHT JOIN information_schema.referential_constraints as dd ON ndb.name = dd.constraint_name WHERE dd.constraint_schema='$ndb_db_name' AND dd.table_name='$ndb_table_name' AND ndb.name is NULL`; if ($fks_in_ndb_but_not_in_dd != 0 || $fks_in_dd_but_not_in_ndb != 0) { # There is a foreign key mismatch. Print the list of # foreign keys in DD and NDB to help debug. eval SELECT name AS 'Foreign Keys in NDB on table `$ndb_db_name.$ndb_table_name`' FROM ndb_fk_info ORDER BY name ASC; eval SELECT constraint_name AS 'Foreign Keys in DD on table `$ndb_db_name.$ndb_table_name`' FROM information_schema.referential_constraints WHERE constraint_schema='$ndb_db_name' AND table_name='$ndb_table_name' ORDER BY constraint_name ASC; --die Foreign keys mismatch in NDB and DD } # Successfully verified if ($ndb_fk_count == 0) { --echo No foreign keys found on table `$ndb_db_name.$ndb_table_name` } if ($ndb_fk_count > 0) { --echo Foreign keys consistent across NDB and DD } # Drop the info table and the view DROP TABLE test.ndb_fk_info; DROP VIEW test.ndb_object_list; --enable_query_log # Reset input parameters --let $ndb_db_name= --let $ndb_table_name=