Как определить порядок загрузки таблицы с помощью DBIc Schema deploy () - PullRequest
0 голосов
/ 23 января 2019

Я обертываю схему базы данных, используя схему 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.

1 Ответ

0 голосов
/ 24 января 2019

Оказывается, что запрос был чувствителен к порядку, так как при определении второй таблицы отсутствовал индекс. В примере в описании определение для 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 под кодом котельной плиты, созданным загрузчиком схемы, чтобы добавить индекс:

sub sqlt_deploy_hook {
   my ($self, $sqlt_table) = @_;

   $sqlt_table->add_index(name => 'table_b_idx_source_id', fields => ['source_id']);
}

Спасибо за тех, кто посмотрел на этот вопрос или нашел время, чтобы рассмотреть вопрос.

...