zf

zenflows testing
git clone https://s.sonu.ch/~srfsh/zf.git
Log | Files | Refs | Submodules | README | LICENSE

migration.exs (17967B)


      1 defmodule Ecto.Integration.MigrationTest do
      2   use ExUnit.Case, async: true
      3 
      4   alias Ecto.Integration.{TestRepo, PoolRepo}
      5 
      6   defmodule CreateMigration do
      7     use Ecto.Migration
      8 
      9     @table table(:create_table_migration)
     10     @index index(:create_table_migration, [:value], unique: true)
     11 
     12     def up do
     13       create @table do
     14         add :value, :integer
     15       end
     16       create @index
     17     end
     18 
     19     def down do
     20       drop @index
     21       drop @table
     22     end
     23   end
     24 
     25   defmodule AddColumnMigration do
     26     use Ecto.Migration
     27 
     28     def up do
     29       create table(:add_col_migration) do
     30         add :value, :integer
     31       end
     32 
     33       alter table(:add_col_migration) do
     34         add :to_be_added, :integer
     35       end
     36 
     37       execute "INSERT INTO add_col_migration (value, to_be_added) VALUES (1, 2)"
     38     end
     39 
     40     def down do
     41       drop table(:add_col_migration)
     42     end
     43   end
     44 
     45   defmodule AlterColumnMigration do
     46     use Ecto.Migration
     47 
     48     def up do
     49       create table(:alter_col_migration) do
     50         add :from_null_to_not_null, :integer
     51         add :from_not_null_to_null, :integer, null: false
     52 
     53         add :from_default_to_no_default, :integer, default: 0
     54         add :from_no_default_to_default, :integer
     55       end
     56 
     57       alter table(:alter_col_migration) do
     58         modify :from_null_to_not_null, :string, null: false
     59         modify :from_not_null_to_null, :string, null: true
     60 
     61         modify :from_default_to_no_default, :integer, default: nil
     62         modify :from_no_default_to_default, :integer, default: 0
     63       end
     64 
     65       execute "INSERT INTO alter_col_migration (from_null_to_not_null) VALUES ('foo')"
     66     end
     67 
     68     def down do
     69       drop table(:alter_col_migration)
     70     end
     71   end
     72 
     73   defmodule AlterColumnFromMigration do
     74     use Ecto.Migration
     75 
     76     def change do
     77       create table(:modify_from_products) do
     78         add :value, :integer
     79         add :nullable, :integer, null: false
     80       end
     81 
     82       if direction() == :up do
     83         flush()
     84         PoolRepo.insert_all "modify_from_products", [[value: 1, nullable: 1]]
     85       end
     86 
     87       alter table(:modify_from_products) do
     88         modify :value, :bigint, from: :integer
     89         modify :nullable, :bigint, null: true, from: {:integer, null: false}
     90       end
     91     end
     92   end
     93 
     94   defmodule AlterColumnFromPkeyMigration do
     95     use Ecto.Migration
     96 
     97     def change do
     98       create table(:modify_from_authors, primary_key: false) do
     99         add :id, :integer, primary_key: true
    100       end
    101       create table(:modify_from_posts) do
    102         add :author_id, references(:modify_from_authors, type: :integer)
    103       end
    104 
    105       if direction() == :up do
    106         flush()
    107         PoolRepo.insert_all "modify_from_authors", [[id: 1]]
    108         PoolRepo.insert_all "modify_from_posts", [[author_id: 1]]
    109       end
    110 
    111       alter table(:modify_from_posts) do
    112         # remove the constraints modify_from_posts_author_id_fkey
    113         modify :author_id, :integer, from: references(:modify_from_authors, type: :integer)
    114       end
    115       alter table(:modify_from_authors) do
    116         modify :id, :bigint, from: :integer
    117       end
    118       alter table(:modify_from_posts) do
    119         # add the constraints modify_from_posts_author_id_fkey
    120         modify :author_id, references(:modify_from_authors, type: :bigint), from: :integer
    121       end
    122     end
    123   end
    124 
    125   defmodule AlterForeignKeyOnDeleteMigration do
    126     use Ecto.Migration
    127 
    128     def up do
    129       create table(:alter_fk_users)
    130 
    131       create table(:alter_fk_posts) do
    132         add :alter_fk_user_id, :id
    133       end
    134 
    135       alter table(:alter_fk_posts) do
    136         modify :alter_fk_user_id, references(:alter_fk_users, on_delete: :nilify_all)
    137       end
    138     end
    139 
    140     def down do
    141       drop table(:alter_fk_posts)
    142       drop table(:alter_fk_users)
    143     end
    144   end
    145 
    146   defmodule AlterForeignKeyOnUpdateMigration do
    147     use Ecto.Migration
    148 
    149     def up do
    150       create table(:alter_fk_users)
    151 
    152       create table(:alter_fk_posts) do
    153         add :alter_fk_user_id, :id
    154       end
    155 
    156       alter table(:alter_fk_posts) do
    157         modify :alter_fk_user_id, references(:alter_fk_users, on_update: :update_all)
    158       end
    159     end
    160 
    161     def down do
    162       drop table(:alter_fk_posts)
    163       drop table(:alter_fk_users)
    164     end
    165   end
    166 
    167   defmodule DropColumnMigration do
    168     use Ecto.Migration
    169 
    170     def up do
    171       create table(:drop_col_migration) do
    172         add :value, :integer
    173         add :to_be_removed, :integer
    174       end
    175 
    176       execute "INSERT INTO drop_col_migration (value, to_be_removed) VALUES (1, 2)"
    177 
    178       alter table(:drop_col_migration) do
    179         remove :to_be_removed
    180       end
    181     end
    182 
    183     def down do
    184       drop table(:drop_col_migration)
    185     end
    186   end
    187 
    188   defmodule RenameColumnMigration do
    189     use Ecto.Migration
    190 
    191     def up do
    192       create table(:rename_col_migration) do
    193         add :to_be_renamed, :integer
    194       end
    195 
    196       rename table(:rename_col_migration), :to_be_renamed, to: :was_renamed
    197 
    198       execute "INSERT INTO rename_col_migration (was_renamed) VALUES (1)"
    199     end
    200 
    201     def down do
    202       drop table(:rename_col_migration)
    203     end
    204   end
    205 
    206   defmodule OnDeleteMigration do
    207     use Ecto.Migration
    208 
    209     def up do
    210       create table(:parent1)
    211       create table(:parent2)
    212 
    213       create table(:ref_migration) do
    214         add :parent1, references(:parent1, on_delete: :nilify_all)
    215       end
    216 
    217       alter table(:ref_migration) do
    218         add :parent2, references(:parent2, on_delete: :delete_all)
    219       end
    220     end
    221 
    222     def down do
    223       drop table(:ref_migration)
    224       drop table(:parent1)
    225       drop table(:parent2)
    226     end
    227   end
    228 
    229   defmodule CompositeForeignKeyMigration do
    230     use Ecto.Migration
    231 
    232     def change do
    233       create table(:composite_parent) do
    234         add :key_id, :integer
    235       end
    236 
    237       create unique_index(:composite_parent, [:id, :key_id])
    238 
    239       create table(:composite_child) do
    240         add :parent_key_id, :integer
    241         add :parent_id, references(:composite_parent, with: [parent_key_id: :key_id])
    242       end
    243     end
    244   end
    245 
    246   defmodule ReferencesRollbackMigration do
    247     use Ecto.Migration
    248 
    249     def change do
    250       create table(:parent) do
    251         add :name, :string
    252       end
    253 
    254       create table(:child) do
    255         add :parent_id, references(:parent)
    256       end
    257     end
    258   end
    259 
    260   defmodule RenameMigration do
    261     use Ecto.Migration
    262 
    263     @table_current table(:posts_migration)
    264     @table_new table(:new_posts_migration)
    265 
    266     def up do
    267       create @table_current
    268       rename @table_current, to: @table_new
    269     end
    270 
    271     def down do
    272       drop @table_new
    273     end
    274   end
    275 
    276   defmodule PrefixMigration do
    277     use Ecto.Migration
    278 
    279     @prefix "ecto_prefix_test"
    280 
    281     def up do
    282       execute TestRepo.create_prefix(@prefix)
    283       create table(:first, prefix: @prefix)
    284       create table(:second, prefix: @prefix) do
    285         add :first_id, references(:first)
    286       end
    287     end
    288 
    289     def down do
    290       drop table(:second, prefix: @prefix)
    291       drop table(:first, prefix: @prefix)
    292       execute TestRepo.drop_prefix(@prefix)
    293     end
    294   end
    295 
    296   defmodule NoSQLMigration do
    297     use Ecto.Migration
    298 
    299     def up do
    300       create table(:collection, options: [capped: true])
    301       execute create: "collection"
    302     end
    303   end
    304 
    305   defmodule Parent do
    306     use Ecto.Schema
    307 
    308     schema "parent" do
    309     end
    310   end
    311 
    312   defmodule NoErrorTableMigration do
    313     use Ecto.Migration
    314 
    315     def change do
    316       create_if_not_exists table(:existing) do
    317         add :name, :string
    318       end
    319 
    320       create_if_not_exists table(:existing) do
    321         add :name, :string
    322       end
    323 
    324       create_if_not_exists table(:existing)
    325 
    326       drop_if_exists table(:existing)
    327       drop_if_exists table(:existing)
    328     end
    329   end
    330 
    331   defmodule NoErrorIndexMigration do
    332     use Ecto.Migration
    333 
    334     def change do
    335       create_if_not_exists index(:posts, [:title])
    336       create_if_not_exists index(:posts, [:title])
    337       drop_if_exists index(:posts, [:title])
    338       drop_if_exists index(:posts, [:title])
    339     end
    340   end
    341 
    342   defmodule InferredDropIndexMigration do
    343     use Ecto.Migration
    344 
    345     def change do
    346       create index(:posts, [:title])
    347     end
    348   end
    349 
    350   defmodule AlterPrimaryKeyMigration do
    351     use Ecto.Migration
    352 
    353     def change do
    354       create table(:no_pk, primary_key: false) do
    355         add :dummy, :string
    356       end
    357       alter table(:no_pk) do
    358         add :id, :serial, primary_key: true
    359       end
    360     end
    361   end
    362 
    363 
    364   defmodule AddColumnIfNotExistsMigration do
    365     use Ecto.Migration
    366 
    367     def up do
    368       create table(:add_col_if_not_exists_migration)
    369 
    370       alter table(:add_col_if_not_exists_migration) do
    371         add_if_not_exists :value, :integer
    372         add_if_not_exists :to_be_added, :integer
    373       end
    374 
    375       execute "INSERT INTO add_col_if_not_exists_migration (value, to_be_added) VALUES (1, 2)"
    376     end
    377 
    378     def down do
    379       drop table(:add_col_if_not_exists_migration)
    380     end
    381   end
    382 
    383   defmodule DropColumnIfExistsMigration do
    384     use Ecto.Migration
    385 
    386     def up do
    387       create table(:drop_col_if_exists_migration) do
    388         add :value, :integer
    389         add :to_be_removed, :integer
    390       end
    391 
    392       execute "INSERT INTO drop_col_if_exists_migration (value, to_be_removed) VALUES (1, 2)"
    393 
    394       alter table(:drop_col_if_exists_migration) do
    395         remove_if_exists :to_be_removed, :integer
    396       end
    397     end
    398 
    399     def down do
    400       drop table(:drop_col_if_exists_migration)
    401     end
    402   end
    403 
    404   defmodule NoErrorOnConditionalColumnMigration do
    405     use Ecto.Migration
    406 
    407     def up do
    408       create table(:no_error_on_conditional_column_migration)
    409 
    410       alter table(:no_error_on_conditional_column_migration) do
    411         add_if_not_exists  :value, :integer
    412         add_if_not_exists  :value, :integer
    413 
    414         remove_if_exists :value, :integer
    415         remove_if_exists :value, :integer
    416       end
    417     end
    418 
    419     def down do
    420       drop table(:no_error_on_conditional_column_migration)
    421     end
    422   end
    423 
    424   import Ecto.Query, only: [from: 2]
    425   import Ecto.Migrator, only: [up: 4, down: 4]
    426 
    427   # Avoid migration out of order warnings
    428   @moduletag :capture_log
    429   @base_migration 1_000_000
    430 
    431   setup do
    432     {:ok, migration_number: System.unique_integer([:positive]) + @base_migration}
    433   end
    434 
    435   test "create and drop table and indexes", %{migration_number: num} do
    436     assert :ok == up(PoolRepo, num, CreateMigration, log: false)
    437     assert :ok == down(PoolRepo, num, CreateMigration, log: false)
    438   end
    439 
    440   test "correctly infers how to drop index", %{migration_number: num} do
    441     assert :ok == up(PoolRepo, num, InferredDropIndexMigration, log: false)
    442     assert :ok == down(PoolRepo, num, InferredDropIndexMigration, log: false)
    443   end
    444 
    445   test "supports on delete", %{migration_number: num} do
    446     assert :ok == up(PoolRepo, num, OnDeleteMigration, log: false)
    447 
    448     parent1 = PoolRepo.insert! Ecto.put_meta(%Parent{}, source: "parent1")
    449     parent2 = PoolRepo.insert! Ecto.put_meta(%Parent{}, source: "parent2")
    450 
    451     writer = "INSERT INTO ref_migration (parent1, parent2) VALUES (#{parent1.id}, #{parent2.id})"
    452     PoolRepo.query!(writer)
    453 
    454     reader = from r in "ref_migration", select: {r.parent1, r.parent2}
    455     assert PoolRepo.all(reader) == [{parent1.id, parent2.id}]
    456 
    457     PoolRepo.delete!(parent1)
    458     assert PoolRepo.all(reader) == [{nil, parent2.id}]
    459 
    460     PoolRepo.delete!(parent2)
    461     assert PoolRepo.all(reader) == []
    462 
    463     assert :ok == down(PoolRepo, num, OnDeleteMigration, log: false)
    464   end
    465 
    466   test "composite foreign keys", %{migration_number: num} do
    467     assert :ok == up(PoolRepo, num, CompositeForeignKeyMigration, log: false)
    468 
    469     PoolRepo.insert_all("composite_parent", [[key_id: 2]])
    470     assert [id] = PoolRepo.all(from p in "composite_parent", select: p.id)
    471 
    472     catch_error(PoolRepo.insert_all("composite_child", [[parent_id: id, parent_key_id: 1]]))
    473     assert {1, nil} = PoolRepo.insert_all("composite_child", [[parent_id: id, parent_key_id: 2]])
    474 
    475     assert :ok == down(PoolRepo, num, CompositeForeignKeyMigration, log: false)
    476   end
    477 
    478   test "rolls back references in change/1", %{migration_number: num} do
    479     assert :ok == up(PoolRepo, num, ReferencesRollbackMigration, log: false)
    480     assert :ok == down(PoolRepo, num, ReferencesRollbackMigration, log: false)
    481   end
    482 
    483   test "create table if not exists and drop table if exists does not raise on failure", %{migration_number: num} do
    484     assert :ok == up(PoolRepo, num, NoErrorTableMigration, log: false)
    485   end
    486 
    487   @tag :create_index_if_not_exists
    488   test "create index if not exists and drop index if exists does not raise on failure", %{migration_number: num} do
    489     assert :ok == up(PoolRepo, num, NoErrorIndexMigration, log: false)
    490   end
    491 
    492   test "raises on NoSQL migrations", %{migration_number: num} do
    493     assert_raise ArgumentError, ~r"does not support keyword lists in :options", fn ->
    494       up(PoolRepo, num, NoSQLMigration, log: false)
    495     end
    496   end
    497 
    498   @tag :add_column
    499   test "add column", %{migration_number: num} do
    500     assert :ok == up(PoolRepo, num, AddColumnMigration, log: false)
    501     assert [2] == PoolRepo.all from p in "add_col_migration", select: p.to_be_added
    502     :ok = down(PoolRepo, num, AddColumnMigration, log: false)
    503   end
    504 
    505   @tag :modify_column
    506   test "modify column", %{migration_number: num} do
    507     assert :ok == up(PoolRepo, num, AlterColumnMigration, log: false)
    508 
    509     assert ["foo"] ==
    510            PoolRepo.all from p in "alter_col_migration", select: p.from_null_to_not_null
    511     assert [nil] ==
    512            PoolRepo.all from p in "alter_col_migration", select: p.from_not_null_to_null
    513     assert [nil] ==
    514            PoolRepo.all from p in "alter_col_migration", select: p.from_default_to_no_default
    515     assert [0] ==
    516            PoolRepo.all from p in "alter_col_migration", select: p.from_no_default_to_default
    517 
    518     query = "INSERT INTO alter_col_migration (from_not_null_to_null) VALUES ('foo')"
    519     assert catch_error(PoolRepo.query!(query))
    520 
    521     :ok = down(PoolRepo, num, AlterColumnMigration, log: false)
    522   end
    523 
    524   @tag :modify_column
    525   test "modify column with from", %{migration_number: num} do
    526     assert :ok == up(PoolRepo, num, AlterColumnFromMigration, log: false)
    527 
    528     assert [1] ==
    529            PoolRepo.all from p in "modify_from_products", select: p.value
    530 
    531     :ok = down(PoolRepo, num, AlterColumnFromMigration, log: false)
    532   end
    533 
    534   @tag :alter_primary_key
    535   test "modify column with from and pkey", %{migration_number: num} do
    536     assert :ok == up(PoolRepo, num, AlterColumnFromPkeyMigration, log: false)
    537 
    538     assert [1] ==
    539            PoolRepo.all from p in "modify_from_posts", select: p.author_id
    540 
    541     :ok = down(PoolRepo, num, AlterColumnFromPkeyMigration, log: false)
    542   end
    543 
    544   @tag :alter_foreign_key
    545   test "modify foreign key's on_delete constraint", %{migration_number: num} do
    546     assert :ok == up(PoolRepo, num, AlterForeignKeyOnDeleteMigration, log: false)
    547 
    548     PoolRepo.insert_all("alter_fk_users", [[]])
    549     assert [id] = PoolRepo.all from p in "alter_fk_users", select: p.id
    550 
    551     PoolRepo.insert_all("alter_fk_posts", [[alter_fk_user_id: id]])
    552     PoolRepo.delete_all("alter_fk_users")
    553     assert [nil] == PoolRepo.all from p in "alter_fk_posts", select: p.alter_fk_user_id
    554 
    555     :ok = down(PoolRepo, num, AlterForeignKeyOnDeleteMigration, log: false)
    556   end
    557 
    558   @tag :assigns_id_type
    559   test "modify foreign key's on_update constraint", %{migration_number: num} do
    560     assert :ok == up(PoolRepo, num, AlterForeignKeyOnUpdateMigration, log: false)
    561 
    562     PoolRepo.insert_all("alter_fk_users", [[]])
    563     assert [id] = PoolRepo.all from p in "alter_fk_users", select: p.id
    564 
    565     PoolRepo.insert_all("alter_fk_posts", [[alter_fk_user_id: id]])
    566     PoolRepo.update_all("alter_fk_users", set: [id: 12345])
    567     assert [12345] == PoolRepo.all from p in "alter_fk_posts", select: p.alter_fk_user_id
    568 
    569     PoolRepo.delete_all("alter_fk_posts")
    570     :ok = down(PoolRepo, num, AlterForeignKeyOnUpdateMigration, log: false)
    571   end
    572 
    573   @tag :remove_column
    574   test "remove column", %{migration_number: num} do
    575     assert :ok == up(PoolRepo, num, DropColumnMigration, log: false)
    576     assert catch_error(PoolRepo.all from p in "drop_col_migration", select: p.to_be_removed)
    577     :ok = down(PoolRepo, num, DropColumnMigration, log: false)
    578   end
    579 
    580   @tag :rename_column
    581   test "rename column", %{migration_number: num} do
    582     assert :ok == up(PoolRepo, num, RenameColumnMigration, log: false)
    583     assert [1] == PoolRepo.all from p in "rename_col_migration", select: p.was_renamed
    584     :ok = down(PoolRepo, num, RenameColumnMigration, log: false)
    585   end
    586 
    587   @tag :rename_table
    588   test "rename table", %{migration_number: num} do
    589     assert :ok == up(PoolRepo, num, RenameMigration, log: false)
    590     assert :ok == down(PoolRepo, num, RenameMigration, log: false)
    591   end
    592 
    593   @tag :prefix
    594   test "prefix", %{migration_number: num} do
    595     assert :ok == up(PoolRepo, num, PrefixMigration, log: false)
    596     assert :ok == down(PoolRepo, num, PrefixMigration, log: false)
    597   end
    598 
    599   @tag :alter_primary_key
    600   test "alter primary key", %{migration_number: num} do
    601     assert :ok == up(PoolRepo, num, AlterPrimaryKeyMigration, log: false)
    602     assert :ok == down(PoolRepo, num, AlterPrimaryKeyMigration, log: false)
    603   end
    604 
    605   @tag :add_column_if_not_exists
    606   @tag :remove_column_if_exists
    607   test "add if not exists and remove if exists does not raise on failure", %{migration_number: num} do
    608     assert :ok == up(PoolRepo, num, NoErrorOnConditionalColumnMigration, log: false)
    609     assert :ok == down(PoolRepo, num, NoErrorOnConditionalColumnMigration, log: false)
    610   end
    611 
    612   @tag :add_column_if_not_exists
    613   test "add column if not exists", %{migration_number: num} do
    614     assert :ok == up(PoolRepo, num, AddColumnIfNotExistsMigration, log: false)
    615     assert [2] == PoolRepo.all from p in "add_col_if_not_exists_migration", select: p.to_be_added
    616     :ok = down(PoolRepo, num, AddColumnIfNotExistsMigration, log: false)
    617   end
    618 
    619   @tag :remove_column_if_exists
    620   test "remove column when exists", %{migration_number: num} do
    621     assert :ok == up(PoolRepo, num, DropColumnIfExistsMigration, log: false)
    622     assert catch_error(PoolRepo.all from p in "drop_col_if_exists_migration", select: p.to_be_removed)
    623     :ok = down(PoolRepo, num, DropColumnIfExistsMigration, log: false)
    624   end
    625 end