Я обертываю схему базы данных, используя схему DBIc, чтобы помочь с модульным тестированием кода.
Основываясь на исходной базе данных, я использовал dbidump
для создания схемы из базы данных:
dbicdump -o dump_directory=./lib -o components='["InflateColumn::DateTime"]' -o debug=1 Test::Schema 'dbi:mysql:dbname=mcdowall_test' 'test'
Есть 2 таблицы InnoDB table_a
и table_b
. Проблема в том, что table_a
имеет ограничение внешнего ключа для таблицы table_b
:
CREATE TABLE 'table_b' (
'table_b_id' INT UNSIGNED NOT NULL AUTO_INCREMENT,
'source_id' INT UNSIGNED NULL,
PRIMARY KEY ('table_b_id'),
KEY ('source_id'))
ENGINE = InnoDB;
CREATE TABLE 'table_a' (
'table_a_id' INT UNSIGNED NOT NULL AUTO_INCREMENT,
'source_id' INT UNSIGNED NULL DEFAULT NULL,
PRIMARY KEY ('table_a_id'),
KEY ('table_a_id'),
CONSTRAINT 'fk_ab'
FOREIGN KEY ('source_id')
REFERENCES 'table_b' ('source_id')
ON DELETE NO ACTION
ON UPDATE NO ACTION)
ENGINE = InnoDB;
Это означает, что при использовании deploy()
для установки схемы во время тестирования таблицы устанавливаются в алфавитном порядке:
use Test::Schema
my $schema = Test::Schema->connect($dsn, $user, $pass, \%opts);
$schema->deploy();
Это вызывает следующую ошибку SQL, так как table_b
не существует, когда table_a
:
ERROR 1215 (HY000): Cannot add foreign key constraint
Есть ли способ получить функцию deploy()
чтобы либо предварительно проверить зависимости внешнего ключа, либо указать конкретные таблицы, которые будут вставлены первыми?
В идеале table_b
должен быть установлен table_a
а затем table_a
.
Оказывается, что запрос был чувствителен к порядку, так как при определении второй таблицы отсутствовал индекс. В примере в описании определение для table_a
было таким же, но определение для table_b
было:
CREATE TABLE 'table_b' (
'table_b_id' INT UNSIGNED NOT NULL AUTO_INCREMENT,
'source_id' INT UNSIGNED NULL,
PRIMARY KEY ('table_b_id'))
ENGINE = InnoDB;
При запуске в порядке table_b
а затем table_a
все в порядке. Если звонки осуществляются в порядке table_a
затем table_b
, потому что отсутствующий индекс по source_id
в определении table_b
, то запрос не будет ли FOREIGN_KEY_CHECKS
установлен в 0 или 1.
Обнаружил это, включив параметр debug() в DBIc, чтобы найти запросы, которые он выполнял, а затем используя этот пост в блоге Percona, чтобы свести на нет проблемы и найти ответ.
Затем в определении таблицы я использовал sqlt_deploy_hook
под sqlt_deploy_hook
панели, созданным загрузчиком схемы, чтобы добавить индекс:
sub sqlt_deploy_hook {
my ($self, $sqlt_table) = @_;
$sqlt_table->add_index(name => 'table_b_idx_source_id', fields => ['source_id']);
}
Спасибо за тех, кто посмотрел на этот вопрос или нашел время, чтобы рассмотреть вопрос.