2016-04-19 2 views
6

Я использую Phoenix и Ecto в одном из моих проектов.Как запустить обновление в миграции для Ecto?

Я хочу добавить столбец в одну таблицу, и я ожидаю, что это будет колонка NOT NULL. Но у меня уже есть некоторые существующие данные, поэтому я решил добавить столбец, обновить все строки до некоторого значения и изменить колонку на NOT NULL.

Я попробовал эти два кода:

# solution 1 
    def up do 
    alter table(:channels) do 
     add :type, :integer 
     Exchat.Repo.update_all("channels", set: [type: 1]) 
     modify :type, :integer, null: false 
    end 
    end 

    # solution 2 
    def up do 
    alter table(:channels) do 
     add :type, :integer 
    end 
    Exchat.Repo.update_all("channels", set: [type: 1]) 
    alter table(:channels) do 
     modify :type, :integer, null: false 
    end 
    end 

Оба они не работают, и я получил сообщение об ошибке, как:

23::40::07.514 [info] == Running Exchat.Repo.Migrations.AddTypeToChannels.up/0 forward 

23::40::07.541 [debug] UPDATE "channels" AS c0 SET "type" = $1 [1] ERROR query=12.0ms 
** (Postgrex.Error) ERROR (undefined_column): column "type" of relation "channels" does not exist 
    (ecto) lib/ecto/adapters/sql.ex:383: Ecto.Adapters.SQL.execute_and_cache/7 

Я не уверен, если это связано с версией экто, но моя версия Ecto 2.0.0-rc.0.

Есть ли способ достичь этого? Или что-то не так в моем примере кода?

+2

Попробуйте добавить 'flush()' после первого 'alter do end' в вашем решении # 2. Это работает? – Dogbert

+0

Он работает! Спасибо! –

+0

Hm ... Тот же код вызывает '** (ArgumentError) аргумент error'. Что может быть неправильным? gist - https://gist.github.com/maslenkov/1ca80dbc913f92a9334a6545eb89880e –

ответ

17

Решение №2 является правильным подходом, но вам необходимо добавить вызов Ecto.Migration.flush/0 после первого блока alter, чтобы убедиться, что все изменения выполняются в базе данных мгновенно, а не в очереди, чтобы быть выполненными позже, что по умолчанию.

def up do 
    alter table(:channels) do 
    add :type, :integer 
    end 
    flush 
    Exchat.Repo.update_all("channels", set: [type: 1]) 
    alter table(:channels) do 
    modify :type, :integer, null: false 
    end 
end