Как определить порядок загрузки таблицы с помощью DBIc Schema deploy ()

0

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

  • 0
    Какую СУБД вы используете?
  • 0
    @AlexanderHartmaier Я использую MySQL с таблицами InnoDB.
Теги:
foreign-keys
dbix-class

1 ответ

0

Оказывается, что запрос был чувствителен к порядку, так как при определении второй таблицы отсутствовал индекс. В примере в описании определение для 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']);
}

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

Ещё вопросы

Сообщество Overcoder
Наверх
Меню