2013-04-16 1 views
0

У меня есть существующая база данных MySQL, которую я пытаюсь перенести в PostgreSQL, используя следующие шаги. База данных довольно проста - он имеет несколько внешних ключей и других ограничений, но никаких триггеров, процедур и т.д.Дублирующие имена индексов с DBIx :: Class и PostgreSQL

  1. Используйте DBIx::Class::Schema::Loader, чтобы произвести набор Result классов из существующей базы данных MySQL.
  2. Используйте классы Result для создания набора операторов CREATE TABLE для PostgreSQL.
  3. Запустите операторы CREATE TABLE, используя psql, чтобы настроить таблицы (пока я пока не импортировал данные).

Сценарий я использую это следующим образом (с учетными данными и имя БД удалены):

#!/usr/bin/perl 

use Modern::Perl; 
use DBIx::Class::Schema::Loader qw/ make_schema_at /; 

my $dsn = 'dbi:mysql:dbname=database'; 
my $user = ''; 
my $pass = ''; 

make_schema_at(
    'MyDB::Schema', 
    { debug => 1, dump_directory => './lib' }, 
    [ $dsn, $user, $pass 
    ], 
); 

my $schema = MyDB::Schema->connect($dsn, $user, $pass); 
$schema->create_ddl_dir(['PostgreSQL'], '0.1', './', undef, { add_drop_table => 0 }); 

Скрипт работает успешно, и оба Result классы и файл .sql (содержащий все CREATE TABLE заявления) выглядят так, как я ожидал.

Однако некоторые таблицы имеют slug столбец, который помечен как UNIQUE в исходной схеме MySQL, и результаты по следующим направлениям в рамках CREATE TABLE заявления:

"slug" character varying(50) NOT NULL, 
CONSTRAINT "slug" UNIQUE ("slug") 

При попытке импортировать данные (с использованием psql < tables.sql), я получаю следующее сообщение об ошибке на каждом столе с уникальной slug колонки после первого:

NOTICE: CREATE TABLE/UNIQUE will create implicit index "slug" for table "mytable" 
ERROR: relation "slug" already exists 

Я понимаю, что индекс имена должны быть уникальными в пределах данной базы данных. У меня нет этой проблемы с MySQL, так как я просто объявляю slug VARCHAR(50) NOT NULL UNIQUE без указания имени индекса.

Есть ли способ сделать DBIx::Class (или SQL::Translator), который использует функцию create_ddl_dir) генерирует уникальное имя индекса в выводимых данных? Меня не особо волнует, как называются индексы, хотя разумное значение имеет название, основанное на имени таблицы. Я просмотрел документацию, но я не вижу никаких параметров, которые позволяют это.

Я мог бы просто отредактировать каждое ограничение вручную перед импортом файла .sql, но есть более 250 таблиц и много столкновений - плюс я должен был бы делать это каждый раз, когда я настраивал процесс миграции и должен был регенерировать классы и SQL.

+0

Вы пытались запустить 'SQL :: Translator' на вашей схеме MySQL напрямую, минуя' DBIx :: Класс: : Схема :: Loader'? – nwellnhof

+0

Такая же проблема - она ​​выводит тот же SQL, что приводит к дублированию имен индексов. – pwaring

+0

Кажется, что вы создали именованные уникальные ограничения в своей схеме MySQL. Он должен работать, чтобы использовать неназванные ограничения простым использованием 'UNIQUE' в определении столбца. – nwellnhof

ответ

0

В конце концов единственный автоматизированный способ исправить это с помощью сценария Perl, который заставил каждое имя ограничения (и, таким образом, автоматический индекс) должен быть уникальным путем анализа вывода из SQL::Translator и добавления _$i к каждому имени, где $i является увеличивается каждый раз при появлении нового ограничения.

код выглядит следующим образом - предполагается, что вы будете труба схема в на STDIN:

#!/usr/bin/perl 

use Modern::Perl; 

my $i = 1; 

while (my $line = <>) 
{ 
    if ($line =~ m/CONSTRAINT\s+"([a-zA-Z_]+)"\s+UNIQUE\s+\("([a-zA-Z_]+)"\)/) 
    {  
    my $constraint_name = $1 . '_' . $i; 
    my $column_name = $2; 

    my $replace_str = 'CONSTRAINT "' . $constraint_name . '" UNIQUE ("' . $column_name . '")'; 

    $line =~ s/CONSTRAINT\s+"([a-zA-Z_]+)"\s+UNIQUE\s+\("([a-zA-Z_]+)"\)/$replace_str/; 
    $i++; 
    } 

    print $line; 
}