From 33aec22eb7897e800e1e2a83edf616b5871db652 Mon Sep 17 00:00:00 2001 From: Kenichiro Watanabe Date: Wed, 13 Mar 2019 15:56:55 +0900 Subject: [PATCH 01/16] wip --- test/apps/gen_migration/lib/gen_migration.ex | 13 ++++++ test/yacto/composite_primary_key_test.exs | 48 ++++++++++++++++++++ 2 files changed, 61 insertions(+) create mode 100644 test/yacto/composite_primary_key_test.exs diff --git a/test/apps/gen_migration/lib/gen_migration.ex b/test/apps/gen_migration/lib/gen_migration.ex index 87fdb3f..1df204a 100644 --- a/test/apps/gen_migration/lib/gen_migration.ex +++ b/test/apps/gen_migration/lib/gen_migration.ex @@ -102,3 +102,16 @@ defmodule GenMigration.ManyIndex do end end +defmodule GenMigration.CompositePrimaryKey1 do + use Yacto.Schema + + @primary_key false + + @impl Yacto.Schema + def dbname(), do: :default + + schema @auto_source do + field(:aaaaaa, :string, primary_key: true) + field(:bbbbbb, :string, primary_key: true) + end +end diff --git a/test/yacto/composite_primary_key_test.exs b/test/yacto/composite_primary_key_test.exs new file mode 100644 index 0000000..d7038a0 --- /dev/null +++ b/test/yacto/composite_primary_key_test.exs @@ -0,0 +1,48 @@ +defmodule Yacto.CompositePrimaryKeyTest do + use PowerAssert + defmodule Parent1 do + use Ecto.Schema + + schema "parents" do + field :name, :string + field :player_id, :string + field :foo, :string + end + end + + defmodule Parent2 do + use Ecto.Schema + @primary_key false + + schema "parents" do + field :name, :string + field :player_id, :string, primary_key: true + field :foo, :string, primary_key: true + end + end + + + test "composite primary key" do + + # p = %Parent{name: "foo", player_id: "bar", foo: "baz"} + # IO.inspect Parent.__schema__(:primary_key) + + s1 = Yacto.Migration.Structure.from_schema(Parent1) + s2 = Yacto.Migration.Structure.from_schema(Parent2) + Yacto.Migration.Structure.diff(s1, s2) + |> IO.inspect + + # %{ + # autogenerate_id: {:delete, {:id, :id, :id}}, + # fields: [del: [:id], eq: [:name, :player_id, :foo]], + # meta: %{attrs: %{del: %{}, ins: %{}}, indices: %{del: %{}, ins: %{}}}, + # primary_key: [del: [:id], ins: [:player_id, :foo]], + # source: :not_changed, + # types: %{del: %{id: :id}, ins: %{}} + #} + + + end + +end + From 8ed6c90717e9d7141c130a77ca532a64ad4b9806 Mon Sep 17 00:00:00 2001 From: HiromuYoshiwara Date: Wed, 13 Mar 2019 17:24:20 +0900 Subject: [PATCH 02/16] =?UTF-8?q?MySQL=20=E3=81=AE=20remove=20=E3=81=AE?= =?UTF-8?q?=E9=A0=86=E5=BA=8F=E3=82=92=E5=85=88=E3=81=AB=E6=8C=81=E3=81=A3?= =?UTF-8?q?=E3=81=A6=E3=81=8D=E3=81=9F?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- lib/yacto/migration/gen_migration.ex | 94 +++++++++++-------- .../gen_migration/test/gen_migration_test.exs | 17 +++- test/apps/migrator/lib/migrator.ex | 12 +++ test/apps/migrator/test/migrator_test.exs | 17 ++++ 4 files changed, 102 insertions(+), 38 deletions(-) diff --git a/lib/yacto/migration/gen_migration.ex b/lib/yacto/migration/gen_migration.ex index 6bf8d11..752e270 100644 --- a/lib/yacto/migration/gen_migration.ex +++ b/lib/yacto/migration/gen_migration.ex @@ -85,45 +85,51 @@ defmodule Yacto.Migration.GenMigration do def generate_fields(types, attrs, structure_to, _migration_opts) do ops = convert_fields(types, attrs) + {remove_ops, other_ops} = Enum.split_with(ops, fn {_, op} -> op == :remove end) + lines = - for {field, op} <- ops do - case op do - {:add, type, attr} -> - opts = attr - - is_primary_key = Enum.find(structure_to.primary_key, &(&1 == field)) != nil - opts = opts ++ if(is_primary_key, do: [primary_key: true], else: []) - - is_autogenerate = - if( - structure_to.autogenerate_id, - do: elem(structure_to.autogenerate_id, 0) == field, - else: false - ) - - opts = opts ++ if(is_autogenerate, do: [autogenerate: true], else: []) - - [" add(:#{field}, #{inspect(type)}, #{inspect(opts)})"] - - :remove -> - lines = [" remove(:#{field})"] - - if field == :id do - [" add(:_gen_migration_dummy, :integer, [])"] ++ - lines ++ - ["end"] ++ - ["alter table(#{inspect(structure_to.source)}) do"] ++ - [" remove(:_gen_migration_dummy)"] - else - lines - end + if length(remove_ops) > 0 do + lines = + for {field, :remove} <- remove_ops do + [" remove(:#{field})"] + end - {:modify, attr} -> - type = Map.fetch!(structure_to.types, field) - [" modify(:#{field}, :#{type}, #{inspect(attr)})"] - end + [" add(:_gen_migration_dummy, :integer, [])"] ++ + lines ++ + ["end"] ++ + ["alter table(#{inspect(structure_to.source)}) do"] ++ + [" remove(:_gen_migration_dummy)"] + else + [] end + lines = + lines ++ + for {field, op} <- other_ops do + case op do + {:add, type, attr} -> + opts = attr + + is_primary_key = Enum.find(structure_to.primary_key, &(&1 == field)) != nil + opts = opts ++ if(is_primary_key, do: [primary_key: true], else: []) + + is_autogenerate = + if( + structure_to.autogenerate_id, + do: elem(structure_to.autogenerate_id, 0) == field, + else: false + ) + + opts = opts ++ if(is_autogenerate, do: [autogenerate: true], else: []) + + [" add(:#{field}, #{inspect(type)}, #{inspect(opts)})"] + + {:modify, attr} -> + type = Map.fetch!(structure_to.types, field) + [" modify(:#{field}, :#{type}, #{inspect(attr)})"] + end + end + List.flatten(lines) end @@ -163,7 +169,14 @@ defmodule Yacto.Migration.GenMigration do if Keyword.has_key?(opts, :name) do opts else - [{:name, create_index_name(fields, Keyword.get(migration_opts, :index_name_max_length, :infinity))} | opts] + [ + {:name, + create_index_name( + fields, + Keyword.get(migration_opts, :index_name_max_length, :infinity) + )} + | opts + ] end "drop index(#{inspect(structure_to.source)}, #{inspect(fields)}, #{inspect(opts)})" @@ -175,7 +188,14 @@ defmodule Yacto.Migration.GenMigration do if Keyword.has_key?(opts, :name) do opts else - [{:name, create_index_name(fields, Keyword.get(migration_opts, :index_name_max_length, :infinity))} | opts] + [ + {:name, + create_index_name( + fields, + Keyword.get(migration_opts, :index_name_max_length, :infinity) + )} + | opts + ] end "create index(#{inspect(structure_to.source)}, #{inspect(fields)}, #{inspect(opts)})" diff --git a/test/apps/gen_migration/test/gen_migration_test.exs b/test/apps/gen_migration/test/gen_migration_test.exs index f6defe2..061a89a 100644 --- a/test/apps/gen_migration/test/gen_migration_test.exs +++ b/test/apps/gen_migration/test/gen_migration_test.exs @@ -260,7 +260,22 @@ defmodule GenMigrationTest do Yacto.Migration.Structure.from_schema(GenMigration.ManyIndex)} ] - source = Yacto.Migration.GenMigration.generate_source(GenMigration, v1, 20_170_424_155_528, index_name_max_length: 20) + source = + Yacto.Migration.GenMigration.generate_source(GenMigration, v1, 20_170_424_155_528, + index_name_max_length: 20 + ) + + assert @migrate6 == source + end + + test "Composite Primary Key" do + v1 = [ + {GenMigration.CompositePrimaryKey1, %Yacto.Migration.Structure{}, + Yacto.Migration.Structure.from_schema(GenMigration.CompositePrimaryKey1)} + ] + + source = Yacto.Migration.GenMigration.generate_source(GenMigration, v1, 20_170_424_155_528) + assert @migrate6 == source end end diff --git a/test/apps/migrator/lib/migrator.ex b/test/apps/migrator/lib/migrator.ex index 7f6482e..6eaa88c 100644 --- a/test/apps/migrator/lib/migrator.ex +++ b/test/apps/migrator/lib/migrator.ex @@ -75,6 +75,18 @@ defmodule Migrator.CustomPrimaryKey do end end +defmodule Migrator.CompositePrimaryKey do + use Yacto.Schema, dbname: :default + + @primary_key false + + schema @auto_source do + field(:player_id, :string, primary_key: true) + field(:quest_id, :string, primary_key: true) + field(:name, :string) + end +end + defmodule Migrator.CoinType do @behaviour Ecto.Type diff --git a/test/apps/migrator/test/migrator_test.exs b/test/apps/migrator/test/migrator_test.exs index 3ccf78c..722743f 100644 --- a/test/apps/migrator/test/migrator_test.exs +++ b/test/apps/migrator/test/migrator_test.exs @@ -188,4 +188,21 @@ defmodule MigratorTest do record = Migrator.Repo1.insert!(record) assert record.type == :common_coin end + + test "Migrator.CompositePrimaryKey" do + Mix.Task.rerun("ecto.drop") + Mix.Task.rerun("ecto.create") + + _ = File.rm_rf(Yacto.Migration.Util.get_migration_dir(:migrator)) + _ = File.rm_rf(Yacto.Migration.Util.get_migration_dir_for_gen()) + + Mix.Task.rerun("yacto.gen.migration", []) + Mix.Task.rerun("yacto.migrate", ["--repo", "Migrator.Repo1", "--app", "migrator"]) + + record1 = %Migrator.CompositePrimaryKey{player_id: "tanaka", quest_id: "gumi", name: "1234"} + # record2 = %Migrator.CompositePrimaryKey{player_id: "saito", guild_id: "gumi", name: "1235"} + record = Migrator.Repo1.insert!(record1) + # record = Migrator.Repo1.insert!(record2) + assert "tanaka" == record.player_id + end end From a21961c18fd9651115ea3c5f706145b07e01ac9a Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=E7=9F=B3=EF=A8=91=20=E5=AE=9F?= Date: Wed, 13 Mar 2019 18:44:22 +0900 Subject: [PATCH 03/16] =?UTF-8?q?add=20composite=20primary=20key=20?= =?UTF-8?q?=E3=81=AE=E9=80=94=E4=B8=AD?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- memo.md | 10 +++ .../gen_migration/test/gen_migration_test.exs | 2 +- test/apps/migrator/lib/migrator.ex | 14 +++- test/apps/migrator/test/migrator_test.exs | 70 +++++++++++++++++-- 4 files changed, 89 insertions(+), 7 deletions(-) create mode 100644 memo.md diff --git a/memo.md b/memo.md new file mode 100644 index 0000000..2a29d52 --- /dev/null +++ b/memo.md @@ -0,0 +1,10 @@ + +## 複合主キーの方針 + +### 現在の状況(2019/3/13) + +* 新規モジュールに複合主キーの設定ができる: 実装済み +* 既存モジュールに新規フィールドを、primary key を true にして追加できる: 実装済み +* 既存モジュールの既存フィールドに primary key を設定することはできない: 対応する +* 既存モジュールで設定された primary key だけを削除することはできない: 削除できない仕様です + diff --git a/test/apps/gen_migration/test/gen_migration_test.exs b/test/apps/gen_migration/test/gen_migration_test.exs index d59ce87..f45d34e 100644 --- a/test/apps/gen_migration/test/gen_migration_test.exs +++ b/test/apps/gen_migration/test/gen_migration_test.exs @@ -316,7 +316,7 @@ defmodule GenMigrationTest do Yacto.Migration.GenMigration.generate_source(GenMigration, v1, 20_170_424_155_528, nil, index_name_max_length: 20 ) - + assert @migrate6 == source end end diff --git a/test/apps/migrator/lib/migrator.ex b/test/apps/migrator/lib/migrator.ex index 6eaa88c..464530c 100644 --- a/test/apps/migrator/lib/migrator.ex +++ b/test/apps/migrator/lib/migrator.ex @@ -82,7 +82,19 @@ defmodule Migrator.CompositePrimaryKey do schema @auto_source do field(:player_id, :string, primary_key: true) - field(:quest_id, :string, primary_key: true) + field(:guild_id, :string, primary_key: true) + field(:name, :string) + end +end + +defmodule Migrator.NoPrimaryKey do + use Yacto.Schema, dbname: :default + + @primary_key false + + schema @auto_source do + field(:player_id, :string) + field(:guild_id, :string) field(:name, :string) end end diff --git a/test/apps/migrator/test/migrator_test.exs b/test/apps/migrator/test/migrator_test.exs index 0787eef..4968a3c 100644 --- a/test/apps/migrator/test/migrator_test.exs +++ b/test/apps/migrator/test/migrator_test.exs @@ -214,10 +214,70 @@ defmodule MigratorTest do Mix.Task.rerun("yacto.gen.migration", []) Mix.Task.rerun("yacto.migrate", ["--repo", "Migrator.Repo1", "--app", "migrator"]) - record1 = %Migrator.CompositePrimaryKey{player_id: "tanaka", quest_id: "gumi", name: "1234"} - # record2 = %Migrator.CompositePrimaryKey{player_id: "saito", guild_id: "gumi", name: "1235"} - record = Migrator.Repo1.insert!(record1) - # record = Migrator.Repo1.insert!(record2) - assert "tanaka" == record.player_id + record1 = %Migrator.CompositePrimaryKey{player_id: "tanaka", guild_id: "gumi", name: "1234"} + record1 = Migrator.Repo1.insert!(record1) + assert "tanaka" == record1.player_id + + record2 = %Migrator.CompositePrimaryKey{player_id: "saito", guild_id: "gumi", name: "1235"} + record2 = Migrator.Repo1.insert!(record2) + assert "saito" == record2.player_id + + # 複合主キーが同じデータを追加しようとすると Ecto.ConstraintError が発生する。 + record3 = %Migrator.CompositePrimaryKey{player_id: "saito", guild_id: "gumi", name: "12345"} + assert_raise Ecto.ConstraintError, fn -> Migrator.Repo1.insert(record3) end + end + + test "Migrator.NoPrimaryKey" do + Mix.Task.rerun("ecto.drop") + Mix.Task.rerun("ecto.create") + + {:ok, _} = Migrator.Repo1.start_link() + + v1 = [ + {Migrator.NoPrimaryKey, %Yacto.Migration.Structure{}, + Yacto.Migration.Structure.from_schema(Migrator.NoPrimaryKey)} + ] + + v2 = [ + {Migrator.NoPrimaryKey, Yacto.Migration.Structure.from_schema(Migrator.NoPrimaryKey), + Yacto.Migration.Structure.from_schema(Migrator.CompositePrimaryKey)} + ] + + source = Yacto.Migration.GenMigration.generate_source(Migrator, v1, 20_190_424_162_530, nil) + File.write!("migration_test_1.exs", source) + + source = + Yacto.Migration.GenMigration.generate_source( + Migrator, + v2, + 20_190_424_162_533, + 20_190_424_162_530 + ) + + File.write!("migration_test_2.exs", source) + + try do + migrations = + Yacto.Migration.Util.load_migrations(["migration_test_1.exs", "migration_test_2.exs"]) + + schemas = Yacto.Migration.Util.get_all_schema(:migrator) + :ok = Yacto.Migration.Migrator.up(:migrator, Migrator.Repo1, schemas, migrations) + after +# File.rm!("migration_test_1.exs") +# File.rm!("migration_test_2.exs") + Code.unload_files(["migration_test_1.exs", "migration_test_2.exs"]) + end + + record1 = %Migrator.CompositePrimaryKey{player_id: "tanaka", guild_id: "gumi", name: "1234"} + record1 = Migrator.Repo1.insert!(record1) + assert "tanaka" == record1.player_id + + record2 = %Migrator.CompositePrimaryKey{player_id: "saito", guild_id: "gumi", name: "1235"} + record2 = Migrator.Repo1.insert!(record2) + assert "saito" == record2.player_id + + # 複合主キーが同じデータを追加しようとすると Ecto.ConstraintError が発生する。 + record3 = %Migrator.CompositePrimaryKey{player_id: "saito", guild_id: "gumi", name: "12345"} + assert_raise Ecto.ConstraintError, fn -> Migrator.Repo1.insert(record3) end end end From 2da3573babef3a456574f34f0dc2d44b7878d114 Mon Sep 17 00:00:00 2001 From: HiromuYoshiwara Date: Wed, 20 Mar 2019 16:10:06 +0900 Subject: [PATCH 04/16] =?UTF-8?q?migration=E4=BD=9C=E6=88=90=E6=99=82?= =?UTF-8?q?=E3=81=ABprimarykey=E3=82=92default=E3=81=A7=E8=A8=AD=E5=AE=9A?= =?UTF-8?q?=E3=81=97=E3=81=AA=E3=81=84=E3=82=88=E3=81=86=E3=81=AB=E4=BF=AE?= =?UTF-8?q?=E6=AD=A3?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- lib/yacto/migration/gen_migration.ex | 9 ++++++++- lib/yacto/migration/structure.ex | 2 +- test/apps/gen_migration/test/gen_migration_test.exs | 10 +++++++++- test/apps/migrator/test/migrator_test.exs | 2 +- test/yacto/migration/structure_test.exs | 4 ++-- 5 files changed, 21 insertions(+), 6 deletions(-) diff --git a/lib/yacto/migration/gen_migration.ex b/lib/yacto/migration/gen_migration.ex index 5e0157d..6a7dbfc 100644 --- a/lib/yacto/migration/gen_migration.ex +++ b/lib/yacto/migration/gen_migration.ex @@ -358,6 +358,9 @@ defmodule Yacto.Migration.GenMigration do schema_infos = for {schema, from, to} <- structure_infos do + if from.primary_key != to.primary_key && from.primary_key != [] do + raise "error" + end case generate_lines(from, to, opts) do :not_changed -> :not_changed lines -> %{schema: schema, lines: lines} @@ -410,7 +413,11 @@ defmodule Yacto.Migration.GenMigration do ["drop table(#{inspect(from_value)})"] {:create, _to_value} -> - ["create table(#{inspect(structure_to.source)})"] + [ + "create table(#{inspect(structure_to.source)}, primary_key: false) do", + "add(:id, :integer)", + "end" + ] end lines = diff --git a/lib/yacto/migration/structure.ex b/lib/yacto/migration/structure.ex index 1ab9c9b..192ecd0 100644 --- a/lib/yacto/migration/structure.ex +++ b/lib/yacto/migration/structure.ex @@ -1,7 +1,7 @@ defmodule Yacto.Migration.Structure do defstruct source: nil, prefix: nil, - primary_key: [:id], + primary_key: [], fields: [:id], field_sources: %{id: :id}, types: %{id: :id}, diff --git a/test/apps/gen_migration/test/gen_migration_test.exs b/test/apps/gen_migration/test/gen_migration_test.exs index f45d34e..d37cfe9 100644 --- a/test/apps/gen_migration/test/gen_migration_test.exs +++ b/test/apps/gen_migration/test/gen_migration_test.exs @@ -74,11 +74,15 @@ defmodule GenMigrationTest do def change(GenMigration.Player) do rename table("player"), to: table("player2") alter table("player2") do + add(:_gen_migration_dummy, :integer, []) remove(:inserted_at) remove(:name) - add(:name2, :string, []) remove(:updated_at) remove(:value) + end + alter table("player2") do + remove(:_gen_migration_dummy) + add(:name2, :string, []) add(:value, :string, []) end end @@ -110,7 +114,11 @@ defmodule GenMigrationTest do def change(GenMigration.Player) do rename table("player2"), to: table("genmigration_player3") alter table("genmigration_player3") do + add(:_gen_migration_dummy, :integer, []) remove(:name2) + end + alter table("genmigration_player3") do + remove(:_gen_migration_dummy) add(:name3, :string, [null: false, size: 100]) end create index("genmigration_player3", [:name3, :value], [name: "name3_value_index", unique: true]) diff --git a/test/apps/migrator/test/migrator_test.exs b/test/apps/migrator/test/migrator_test.exs index 4968a3c..a7da053 100644 --- a/test/apps/migrator/test/migrator_test.exs +++ b/test/apps/migrator/test/migrator_test.exs @@ -278,6 +278,6 @@ defmodule MigratorTest do # 複合主キーが同じデータを追加しようとすると Ecto.ConstraintError が発生する。 record3 = %Migrator.CompositePrimaryKey{player_id: "saito", guild_id: "gumi", name: "12345"} - assert_raise Ecto.ConstraintError, fn -> Migrator.Repo1.insert(record3) end + assert_raise Ecto.ConstraintError, fn -> IO.inspect Migrator.Repo1.insert!(record3) end end end diff --git a/test/yacto/migration/structure_test.exs b/test/yacto/migration/structure_test.exs index 887abc1..4723954 100644 --- a/test/yacto/migration/structure_test.exs +++ b/test/yacto/migration/structure_test.exs @@ -19,10 +19,10 @@ defmodule Yacto.Migration.StructureTest do test "inspect" do structure = Yacto.Migration.Structure.from_schema(Schema) - assert "%Yacto.Migration.Structure{source: \"yacto_migration_structuretest_schema\"}" == + assert "%Yacto.Migration.Structure{primary_key: [:id], source: \"yacto_migration_structuretest_schema\"}" == inspect(structure) - assert "%Yacto.Migration.Structure{source: \"yacto_migration_structuretest_schema\"}" == + assert "%Yacto.Migration.Structure{primary_key: [:id], source: \"yacto_migration_structuretest_schema\"}" == Yacto.Migration.Structure.to_string(structure) end end From eee9e7fd75d3bdae7fe000a907900a83d466762a Mon Sep 17 00:00:00 2001 From: Kenichiro Watanabe Date: Wed, 20 Mar 2019 17:27:00 +0900 Subject: [PATCH 05/16] =?UTF-8?q?primary=5Fkey=E3=81=AEdiff=E3=82=92?= =?UTF-8?q?=E8=A6=8B=E3=82=8B=E3=82=88=E3=81=86=E3=81=AB=E3=81=97=E3=81=9F?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- lib/yacto/migration/gen_migration.ex | 39 +++++++++++++++++----------- 1 file changed, 24 insertions(+), 15 deletions(-) diff --git a/lib/yacto/migration/gen_migration.ex b/lib/yacto/migration/gen_migration.ex index 6a7dbfc..27f1c97 100644 --- a/lib/yacto/migration/gen_migration.ex +++ b/lib/yacto/migration/gen_migration.ex @@ -1,17 +1,21 @@ defmodule Yacto.Migration.GenMigration do require Logger - defp convert_fields(types, attrs) do + defp convert_fields(types, attrs, primary_keys) do # types: # %{del: %{field: type}, # ins: %{field: type}} # attrs: # %{ins: %{field: attr}, # del: %{field: attr}} + # primary_keys: + # [eq: [field]] + # or + # [ins: [field]] # result: - # [{field, {:add, {type, attr}} | + # [{field, {:add, {type, attr, primary_key}} | # :remove | - # {:modify, attr}}] + # {:modify, attr, primary_key}}] # get all field names type_fields = @@ -26,13 +30,15 @@ defmodule Yacto.Migration.GenMigration do field end - fields = type_fields ++ attr_fields + primary_key_fields = Keyword.get(primary_keys, :ins, []) + fields = type_fields ++ attr_fields ++ primary_key_fields fields = fields |> Enum.sort() |> Enum.dedup() changes = for field <- fields do in_type_del = Map.has_key?(types.del, field) in_type_ins = Map.has_key?(types.ins, field) + is_primary_key = Enum.member?(primary_key_fields, field) cond do in_type_del && in_type_ins -> @@ -46,7 +52,7 @@ defmodule Yacto.Migration.GenMigration do [] end - [{field, :remove}, {field, {:add, type, attr}}] + [{field, :remove}, {field, {:add, type, attr, is_primary_key}}] in_type_del && !in_type_ins -> # :remove @@ -63,7 +69,7 @@ defmodule Yacto.Migration.GenMigration do [] end - [{field, {:add, type, attr}}] + [{field, {:add, type, attr, is_primary_key}}] !in_type_del && !in_type_ins -> # :modify @@ -75,15 +81,15 @@ defmodule Yacto.Migration.GenMigration do [] end - [{field, {:modify, attr}}] + [{field, {:modify, attr, is_primary_key}}] end end List.flatten(changes) end - def generate_fields(types, attrs, structure_to, _migration_opts) do - ops = convert_fields(types, attrs) + def generate_fields(types, attrs, primary_keys, structure_to, _migration_opts) do + ops = convert_fields(types, attrs, primary_keys) {remove_ops, other_ops} = Enum.split_with(ops, fn {_, op} -> op == :remove end) @@ -107,10 +113,9 @@ defmodule Yacto.Migration.GenMigration do lines ++ for {field, op} <- other_ops do case op do - {:add, type, attr} -> + {:add, type, attr, is_primary_key} -> opts = attr - is_primary_key = Enum.find(structure_to.primary_key, &(&1 == field)) != nil opts = opts ++ if(is_primary_key, do: [primary_key: true], else: []) is_autogenerate = @@ -124,9 +129,12 @@ defmodule Yacto.Migration.GenMigration do [" add(:#{field}, #{inspect(type)}, #{inspect(opts)})"] - {:modify, attr} -> + {:modify, attr, is_primary_key} -> type = Map.fetch!(structure_to.types, field) - [" modify(:#{field}, :#{type}, #{inspect(attr)})"] + opts = attr + opts = opts ++ if(is_primary_key, do: [primary_key: true], else: []) + + [" modify(:#{field}, :#{type}, #{inspect(opts)})"] end end @@ -361,6 +369,7 @@ defmodule Yacto.Migration.GenMigration do if from.primary_key != to.primary_key && from.primary_key != [] do raise "error" end + case generate_lines(from, to, opts) do :not_changed -> :not_changed lines -> %{schema: schema, lines: lines} @@ -415,7 +424,7 @@ defmodule Yacto.Migration.GenMigration do {:create, _to_value} -> [ "create table(#{inspect(structure_to.source)}, primary_key: false) do", - "add(:id, :integer)", + " add(:id, :integer)", "end" ] end @@ -428,7 +437,7 @@ defmodule Yacto.Migration.GenMigration do _ -> ["alter table(#{inspect(structure_to.source)}) do"] ++ - generate_fields(diff.types, diff.meta.attrs, structure_to, migration_opts) ++ + generate_fields(diff.types, diff.meta.attrs, diff.primary_key, structure_to, migration_opts) ++ ["end"] ++ generate_indices(diff.meta.indices, structure_to, migration_opts) end From 156c645c72f9badda00c3eefc83941de840aed78 Mon Sep 17 00:00:00 2001 From: HiromuYoshiwara Date: Wed, 20 Mar 2019 19:01:02 +0900 Subject: [PATCH 06/16] =?UTF-8?q?=E3=81=82=E3=81=A8=E3=81=AF=E3=83=86?= =?UTF-8?q?=E3=82=B9=E3=83=88=E3=82=92=E7=9B=B4=E3=81=99=E3=81=AE=E3=81=A8?= =?UTF-8?q?refactor?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- lib/yacto/migration/gen_migration.ex | 71 ++++++++++++------- lib/yacto/migration/migrator.ex | 4 +- lib/yacto/migration/structure.ex | 2 +- .../gen_migration/test/gen_migration_test.exs | 23 ++++-- test/yacto/migration/structure_test.exs | 4 +- 5 files changed, 67 insertions(+), 37 deletions(-) diff --git a/lib/yacto/migration/gen_migration.ex b/lib/yacto/migration/gen_migration.ex index 27f1c97..b30f238 100644 --- a/lib/yacto/migration/gen_migration.ex +++ b/lib/yacto/migration/gen_migration.ex @@ -1,7 +1,7 @@ defmodule Yacto.Migration.GenMigration do require Logger - defp convert_fields(types, attrs, primary_keys) do + defp convert_fields(types, attrs, primary_keys, autogenerate_id) do # types: # %{del: %{field: type}, # ins: %{field: type}} @@ -12,10 +12,14 @@ defmodule Yacto.Migration.GenMigration do # [eq: [field]] # or # [ins: [field]] + # autogenerate_id: + # :not_changed + # or + # {:create, {ecto_schema_field_name, database_field_name, type}} # result: - # [{field, {:add, {type, attr, primary_key}} | + # [{field, {:add, {type, attr, is_primary_key, is_autogenerate}} | # :remove | - # {:modify, attr, primary_key}}] + # {:modify, attr, is_primary_key, is_autogenerate}}] # get all field names type_fields = @@ -31,7 +35,14 @@ defmodule Yacto.Migration.GenMigration do end primary_key_fields = Keyword.get(primary_keys, :ins, []) - fields = type_fields ++ attr_fields ++ primary_key_fields + + autogenerate_field = + case autogenerate_id do + {:create, {_, field, _}} -> [field] + :not_changed -> [] + end + + fields = type_fields ++ attr_fields ++ primary_key_fields ++ autogenerate_field fields = fields |> Enum.sort() |> Enum.dedup() changes = @@ -39,6 +50,7 @@ defmodule Yacto.Migration.GenMigration do in_type_del = Map.has_key?(types.del, field) in_type_ins = Map.has_key?(types.ins, field) is_primary_key = Enum.member?(primary_key_fields, field) + is_autogenerate = Enum.member?(autogenerate_field, field) cond do in_type_del && in_type_ins -> @@ -52,7 +64,7 @@ defmodule Yacto.Migration.GenMigration do [] end - [{field, :remove}, {field, {:add, type, attr, is_primary_key}}] + [{field, :remove}, {field, {:add, type, attr, is_primary_key, is_autogenerate}}] in_type_del && !in_type_ins -> # :remove @@ -69,7 +81,7 @@ defmodule Yacto.Migration.GenMigration do [] end - [{field, {:add, type, attr, is_primary_key}}] + [{field, {:add, type, attr, is_primary_key, is_autogenerate}}] !in_type_del && !in_type_ins -> # :modify @@ -81,15 +93,15 @@ defmodule Yacto.Migration.GenMigration do [] end - [{field, {:modify, attr, is_primary_key}}] + [{field, {:modify, attr, is_primary_key, is_autogenerate}}] end end List.flatten(changes) end - def generate_fields(types, attrs, primary_keys, structure_to, _migration_opts) do - ops = convert_fields(types, attrs, primary_keys) + def generate_fields(types, attrs, primary_keys, autogenerate_id, structure_to, _migration_opts) do + ops = convert_fields(types, attrs, primary_keys, autogenerate_id) {remove_ops, other_ops} = Enum.split_with(ops, fn {_, op} -> op == :remove end) @@ -113,27 +125,22 @@ defmodule Yacto.Migration.GenMigration do lines ++ for {field, op} <- other_ops do case op do - {:add, type, attr, is_primary_key} -> + {:add, type, attr, is_primary_key, is_autogenerate} -> opts = attr opts = opts ++ if(is_primary_key, do: [primary_key: true], else: []) - is_autogenerate = - if( - structure_to.autogenerate_id, - do: elem(structure_to.autogenerate_id, 0) == field, - else: false - ) - - opts = opts ++ if(is_autogenerate, do: [autogenerate: true], else: []) + type = if type == :id && is_autogenerate, do: :bigserial, else: type [" add(:#{field}, #{inspect(type)}, #{inspect(opts)})"] - {:modify, attr, is_primary_key} -> + {:modify, attr, is_primary_key, is_autogenerate} -> type = Map.fetch!(structure_to.types, field) opts = attr opts = opts ++ if(is_primary_key, do: [primary_key: true], else: []) + type = if type == :id && is_autogenerate, do: :bigserial, else: type + [" modify(:#{field}, :#{type}, #{inspect(opts)})"] end end @@ -366,10 +373,6 @@ defmodule Yacto.Migration.GenMigration do schema_infos = for {schema, from, to} <- structure_infos do - if from.primary_key != to.primary_key && from.primary_key != [] do - raise "error" - end - case generate_lines(from, to, opts) do :not_changed -> :not_changed lines -> %{schema: schema, lines: lines} @@ -407,6 +410,17 @@ defmodule Yacto.Migration.GenMigration do diff = Yacto.Migration.Structure.diff(structure_from, structure_to) rdiff = Yacto.Migration.Structure.diff(structure_to, structure_from) + if structure_from.primary_key != structure_to.primary_key && structure_from.primary_key != [] do + raise "error" + end + + case diff.autogenerate_id do + :not_changed -> :ok + {:create, _to_value} -> :ok + {:delete, _from_value} -> raise "error" + {:changed, _from_value, _to_value} -> raise "error" + end + if diff == rdiff do :not_changed else @@ -424,7 +438,7 @@ defmodule Yacto.Migration.GenMigration do {:create, _to_value} -> [ "create table(#{inspect(structure_to.source)}, primary_key: false) do", - " add(:id, :integer)", + " add(:id, :id)", "end" ] end @@ -437,7 +451,14 @@ defmodule Yacto.Migration.GenMigration do _ -> ["alter table(#{inspect(structure_to.source)}) do"] ++ - generate_fields(diff.types, diff.meta.attrs, diff.primary_key, structure_to, migration_opts) ++ + generate_fields( + diff.types, + diff.meta.attrs, + diff.primary_key, + diff.autogenerate_id, + structure_to, + migration_opts + ) ++ ["end"] ++ generate_indices(diff.meta.indices, structure_to, migration_opts) end diff --git a/lib/yacto/migration/migrator.ex b/lib/yacto/migration/migrator.ex index 3f364b6..761bbcd 100644 --- a/lib/yacto/migration/migrator.ex +++ b/lib/yacto/migration/migrator.ex @@ -61,8 +61,8 @@ defmodule Yacto.Migration.Migrator do end defp run(repo, schema, migration, direction, operation, migrator_direction, opts) do - level = Keyword.get(opts, :log, :info) - sql = Keyword.get(opts, :log_sql, false) + level = Keyword.get(opts, :log, :debug) + sql = Keyword.get(opts, :log_sql, true) log = %{level: level, sql: sql} args = [self(), repo, direction, migrator_direction, log] diff --git a/lib/yacto/migration/structure.ex b/lib/yacto/migration/structure.ex index 192ecd0..7664e4a 100644 --- a/lib/yacto/migration/structure.ex +++ b/lib/yacto/migration/structure.ex @@ -8,7 +8,7 @@ defmodule Yacto.Migration.Structure do associations: [], embeds: [], read_after_writes: [], - autogenerate_id: {:id, :id, :id}, + autogenerate_id: nil, meta: %{attrs: %{}, indices: %{}} # undocumented keys: diff --git a/test/apps/gen_migration/test/gen_migration_test.exs b/test/apps/gen_migration/test/gen_migration_test.exs index d37cfe9..ae288a1 100644 --- a/test/apps/gen_migration/test/gen_migration_test.exs +++ b/test/apps/gen_migration/test/gen_migration_test.exs @@ -27,8 +27,8 @@ defmodule GenMigrationTest do del: %{name: :string, value: :integer}, ins: %{name2: :string, value: :string} }, - primary_key: [del: [:id], ins: [:id2]], - autogenerate_id: {:changed, {:id, :id, :id}, {:id2, :id2, :binary_id}}, + primary_key: [ins: [:id2]], + autogenerate_id: {:create, {:id2, :id2, :binary_id}}, meta: %{attrs: %{del: %{}, ins: %{}}, indices: %{del: %{}, ins: %{}}} } == diff end @@ -38,8 +38,11 @@ defmodule GenMigrationTest do use Ecto.Migration def change(GenMigration.Player) do - create table("player") + create table("player", primary_key: false) do + add(:id, :id) + end alter table("player") do + modify(:id, :bigserial, [primary_key: true]) add(:inserted_at, :naive_datetime, []) add(:name, :string, []) add(:updated_at, :naive_datetime, []) @@ -53,7 +56,7 @@ defmodule GenMigrationTest do def __migration_structures__() do [ - {GenMigration.Player, %Yacto.Migration.Structure{field_sources: %{id: :id, inserted_at: :inserted_at, name: :name, updated_at: :updated_at, value: :value}, fields: [:id, :name, :value, :inserted_at, :updated_at], source: "player", types: %{id: :id, inserted_at: :naive_datetime, name: :string, updated_at: :naive_datetime, value: :integer}}}, + {GenMigration.Player, %Yacto.Migration.Structure{autogenerate_id: {:id, :id, :id}, field_sources: %{id: :id, inserted_at: :inserted_at, name: :name, updated_at: :updated_at, value: :value}, fields: [:id, :name, :value, :inserted_at, :updated_at], primary_key: [:id], source: "player", types: %{id: :id, inserted_at: :naive_datetime, name: :string, updated_at: :naive_datetime, value: :integer}}}, ] end @@ -235,14 +238,16 @@ defmodule GenMigrationTest do use Ecto.Migration def change(GenMigration.Item) do - create table("genmigration_item") + create table("genmigration_item", primary_key: false) do + add(:id, :id) + end alter table("genmigration_item") do add(:_gen_migration_dummy, :integer, []) remove(:id) end alter table("genmigration_item") do remove(:_gen_migration_dummy) - add(:id, :binary_id, [primary_key: true, autogenerate: true]) + add(:id, :binary_id, [primary_key: true]) add(:name, :string, []) end end @@ -284,16 +289,20 @@ defmodule GenMigrationTest do use Ecto.Migration def change(GenMigration.ManyIndex) do - create table("genmigration_manyindex") + create table("genmigration_manyindex", primary_key: false) do + add(:id, :id) + end alter table("genmigration_manyindex") do add(:aaaaaa, :string, []) add(:bbbbbb, :string, []) add(:cccccc, :string, []) add(:dddddd, :string, []) + modify(:id, :bigserial, [primary_key: true]) end create index("genmigration_manyindex", [:aaaaaa, :bbbbbb, :cccccc, :dddddd], [name: "aaaaaa_bbbb_9a4e1a2f"]) end + def change(_other) do :ok end diff --git a/test/yacto/migration/structure_test.exs b/test/yacto/migration/structure_test.exs index 4723954..2d49a10 100644 --- a/test/yacto/migration/structure_test.exs +++ b/test/yacto/migration/structure_test.exs @@ -19,10 +19,10 @@ defmodule Yacto.Migration.StructureTest do test "inspect" do structure = Yacto.Migration.Structure.from_schema(Schema) - assert "%Yacto.Migration.Structure{primary_key: [:id], source: \"yacto_migration_structuretest_schema\"}" == + assert "%Yacto.Migration.Structure{autogenerate_id: {:id, :id, :id}, primary_key: [:id], source: \"yacto_migration_structuretest_schema\"}" == inspect(structure) - assert "%Yacto.Migration.Structure{primary_key: [:id], source: \"yacto_migration_structuretest_schema\"}" == + assert "%Yacto.Migration.Structure{autogenerate_id: {:id, :id, :id}, primary_key: [:id], source: \"yacto_migration_structuretest_schema\"}" == Yacto.Migration.Structure.to_string(structure) end end From c50e6e0e6526c8917e5872015e267bd201807cf8 Mon Sep 17 00:00:00 2001 From: Kenichiro Watanabe Date: Wed, 3 Apr 2019 12:38:46 +0900 Subject: [PATCH 07/16] =?UTF-8?q?=E3=83=86=E3=82=B9=E3=83=88=E3=82=92?= =?UTF-8?q?=E9=80=9A=E3=82=8B=E3=82=88=E3=81=86=E3=81=AB=E3=81=99=E3=82=8B?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../test/custom_table_name_test.exs | 47 ++++++++++--------- 1 file changed, 25 insertions(+), 22 deletions(-) diff --git a/test/apps/custom_table_name/test/custom_table_name_test.exs b/test/apps/custom_table_name/test/custom_table_name_test.exs index 7fd8558..611249a 100644 --- a/test/apps/custom_table_name/test/custom_table_name_test.exs +++ b/test/apps/custom_table_name/test/custom_table_name_test.exs @@ -2,35 +2,38 @@ defmodule CustomTableNameTest do use PowerAssert @migrate """ - defmodule CustomTableName.Migration20170424155528 do - use Ecto.Migration +defmodule CustomTableName.Migration20170424155528 do + use Ecto.Migration - def change(CustomTableName.Player.Schema.TestData) do - create table("customtablename_player") - alter table("customtablename_player") do - add(:name, :string, [default: "hoge", null: false, size: 100]) - end + def change(CustomTableName.Player.Schema.TestData) do + create table(\"customtablename_player\", primary_key: false) do + add(:id, :id) end - - def change(_other) do - :ok + alter table(\"customtablename_player\") do + modify(:id, :bigserial, [primary_key: true]) + add(:name, :string, [default: \"hoge\", null: false, size: 100]) end + end - def __migration_structures__() do - [ - {CustomTableName.Player.Schema.TestData, %Yacto.Migration.Structure{field_sources: %{id: :id, name: :name}, fields: [:id, :name], meta: %{attrs: %{name: %{default: "hoge", null: false, size: 100}}, indices: %{}}, source: "customtablename_player", types: %{id: :id, name: :string}}}, - ] - end + def change(_other) do + :ok + end - def __migration_version__() do - 20170424155528 - end + def __migration_structures__() do + [ + {CustomTableName.Player.Schema.TestData, %Yacto.Migration.Structure{autogenerate_id: {:id, :id, :id}, field_sources: %{id: :id, name: :name}, fields: [:id, :name], meta: %{attrs: %{name: %{default: \"hoge\", null: false, size: 100}}, indices: %{}}, primary_key: [:id], source: \"customtablename_player\", types: %{id: :id, name: :string}}}, + ] + end - def __migration_preview_version__() do - nil - end + def __migration_version__() do + 20170424155528 end - """ + + def __migration_preview_version__() do + nil + end +end +""" test "Yacto.Migration.GenMigration generate_source with custom table name." do v1 = [ From ba11011ed6ce64f9094abacef016d48252c079ab Mon Sep 17 00:00:00 2001 From: Kenichiro Watanabe Date: Wed, 3 Apr 2019 12:56:44 +0900 Subject: [PATCH 08/16] =?UTF-8?q?=E7=94=9F=E6=88=90=E3=81=95=E3=82=8C?= =?UTF-8?q?=E3=82=8B=E3=83=9E=E3=82=A4=E3=82=B0=E3=83=AC=E3=83=BC=E3=82=B7?= =?UTF-8?q?=E3=83=A7=E3=83=B3=E3=81=AE=E3=83=95=E3=82=A9=E3=83=BC=E3=83=9E?= =?UTF-8?q?=E3=83=83=E3=83=88=E3=81=AB=E5=90=88=E3=82=8F=E3=81=9B=E3=81=A6?= =?UTF-8?q?=E3=83=86=E3=82=B9=E3=83=88=E3=82=92=E4=BF=AE=E6=AD=A3?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- test/apps/gen_migration/test/gen_migration_test.exs | 9 ++++----- 1 file changed, 4 insertions(+), 5 deletions(-) diff --git a/test/apps/gen_migration/test/gen_migration_test.exs b/test/apps/gen_migration/test/gen_migration_test.exs index ae288a1..eb54a83 100644 --- a/test/apps/gen_migration/test/gen_migration_test.exs +++ b/test/apps/gen_migration/test/gen_migration_test.exs @@ -96,7 +96,7 @@ defmodule GenMigrationTest do def __migration_structures__() do [ - {GenMigration.Player, %Yacto.Migration.Structure{field_sources: %{id: :id, name2: :name2, value: :value}, fields: [:id, :name2, :value], source: "player2", types: %{id: :id, name2: :string, value: :string}}}, + {GenMigration.Player, %Yacto.Migration.Structure{autogenerate_id: {:id, :id, :id}, field_sources: %{id: :id, name2: :name2, value: :value}, fields: [:id, :name2, :value], primary_key: [:id], source: "player2", types: %{id: :id, name2: :string, value: :string}}}, ] end @@ -134,7 +134,7 @@ defmodule GenMigrationTest do def __migration_structures__() do [ - {GenMigration.Player, %Yacto.Migration.Structure{field_sources: %{id: :id, name3: :name3, value: :value}, fields: [:id, :name3, :value], meta: %{attrs: %{name3: %{null: false, size: 100}}, indices: %{{[:name3, :value], [unique: true]} => true, {[:value, :name3], []} => true}}, source: "genmigration_player3", types: %{id: :id, name3: :string, value: :string}}}, + {GenMigration.Player, %Yacto.Migration.Structure{autogenerate_id: {:id, :id, :id}, field_sources: %{id: :id, name3: :name3, value: :value}, fields: [:id, :name3, :value], meta: %{attrs: %{name3: %{null: false, size: 100}}, indices: %{{[:name3, :value], [unique: true]} => true, {[:value, :name3], []} => true}}, primary_key: [:id], source: "genmigration_player3", types: %{id: :id, name3: :string, value: :string}}}, ] end @@ -258,7 +258,7 @@ defmodule GenMigrationTest do def __migration_structures__() do [ - {GenMigration.Item, %Yacto.Migration.Structure{autogenerate_id: {:id, :id, :binary_id}, field_sources: %{id: :id, name: :name}, fields: [:id, :name], source: "genmigration_item", types: %{id: :binary_id, name: :string}}}, + {GenMigration.Item, %Yacto.Migration.Structure{autogenerate_id: {:id, :id, :binary_id}, field_sources: %{id: :id, name: :name}, fields: [:id, :name], primary_key: [:id], source: "genmigration_item", types: %{id: :binary_id, name: :string}}}, ] end @@ -302,14 +302,13 @@ defmodule GenMigrationTest do create index("genmigration_manyindex", [:aaaaaa, :bbbbbb, :cccccc, :dddddd], [name: "aaaaaa_bbbb_9a4e1a2f"]) end - def change(_other) do :ok end def __migration_structures__() do [ - {GenMigration.ManyIndex, %Yacto.Migration.Structure{field_sources: %{aaaaaa: :aaaaaa, bbbbbb: :bbbbbb, cccccc: :cccccc, dddddd: :dddddd, id: :id}, fields: [:id, :aaaaaa, :bbbbbb, :cccccc, :dddddd], meta: %{attrs: %{}, indices: %{{[:aaaaaa, :bbbbbb, :cccccc, :dddddd], []} => true}}, source: "genmigration_manyindex", types: %{aaaaaa: :string, bbbbbb: :string, cccccc: :string, dddddd: :string, id: :id}}}, + {GenMigration.ManyIndex, %Yacto.Migration.Structure{autogenerate_id: {:id, :id, :id}, field_sources: %{aaaaaa: :aaaaaa, bbbbbb: :bbbbbb, cccccc: :cccccc, dddddd: :dddddd, id: :id}, fields: [:id, :aaaaaa, :bbbbbb, :cccccc, :dddddd], meta: %{attrs: %{}, indices: %{{[:aaaaaa, :bbbbbb, :cccccc, :dddddd], []} => true}}, primary_key: [:id], source: "genmigration_manyindex", types: %{aaaaaa: :string, bbbbbb: :string, cccccc: :string, dddddd: :string, id: :id}}}, ] end From f422756c9422389ed94df34071d565bed55770a2 Mon Sep 17 00:00:00 2001 From: Kenichiro Watanabe Date: Wed, 3 Apr 2019 14:59:55 +0900 Subject: [PATCH 09/16] =?UTF-8?q?=E3=81=99=E3=81=A7=E3=81=AB=20primary=5Fk?= =?UTF-8?q?ey=20=E3=81=8C=E5=AD=98=E5=9C=A8=E3=81=99=E3=82=8B=E5=A0=B4?= =?UTF-8?q?=E5=90=88=E3=81=AF=E3=82=A8=E3=83=A9=E3=83=BC=E3=81=AB=E3=81=99?= =?UTF-8?q?=E3=82=8B?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- test/apps/gen_migration/test/gen_migration_test.exs | 5 ++--- 1 file changed, 2 insertions(+), 3 deletions(-) diff --git a/test/apps/gen_migration/test/gen_migration_test.exs b/test/apps/gen_migration/test/gen_migration_test.exs index eb54a83..d595cf4 100644 --- a/test/apps/gen_migration/test/gen_migration_test.exs +++ b/test/apps/gen_migration/test/gen_migration_test.exs @@ -222,15 +222,14 @@ defmodule GenMigrationTest do assert @migrate3 == source - source = + assert_raise RuntimeError, "error", fn -> Yacto.Migration.GenMigration.generate_source( GenMigration, v4, 20_170_424_155_533, 20_170_424_155_532 ) - - assert @migrate4 == source + end end @migrate5 """ From 1709924c21b3cc8a5d96ef25d79e98219c3e81f2 Mon Sep 17 00:00:00 2001 From: Kenichiro Watanabe Date: Wed, 3 Apr 2019 15:02:35 +0900 Subject: [PATCH 10/16] format --- .../test/custom_table_name_test.exs | 50 +++++++++---------- test/apps/migrator/test/migrator_test.exs | 6 +-- test/yacto/composite_primary_key_test.exs | 24 ++++----- 3 files changed, 38 insertions(+), 42 deletions(-) diff --git a/test/apps/custom_table_name/test/custom_table_name_test.exs b/test/apps/custom_table_name/test/custom_table_name_test.exs index 611249a..dba5a35 100644 --- a/test/apps/custom_table_name/test/custom_table_name_test.exs +++ b/test/apps/custom_table_name/test/custom_table_name_test.exs @@ -2,38 +2,38 @@ defmodule CustomTableNameTest do use PowerAssert @migrate """ -defmodule CustomTableName.Migration20170424155528 do - use Ecto.Migration + defmodule CustomTableName.Migration20170424155528 do + use Ecto.Migration - def change(CustomTableName.Player.Schema.TestData) do - create table(\"customtablename_player\", primary_key: false) do - add(:id, :id) - end - alter table(\"customtablename_player\") do - modify(:id, :bigserial, [primary_key: true]) - add(:name, :string, [default: \"hoge\", null: false, size: 100]) + def change(CustomTableName.Player.Schema.TestData) do + create table(\"customtablename_player\", primary_key: false) do + add(:id, :id) + end + alter table(\"customtablename_player\") do + modify(:id, :bigserial, [primary_key: true]) + add(:name, :string, [default: \"hoge\", null: false, size: 100]) + end end - end - def change(_other) do - :ok - end + def change(_other) do + :ok + end - def __migration_structures__() do - [ - {CustomTableName.Player.Schema.TestData, %Yacto.Migration.Structure{autogenerate_id: {:id, :id, :id}, field_sources: %{id: :id, name: :name}, fields: [:id, :name], meta: %{attrs: %{name: %{default: \"hoge\", null: false, size: 100}}, indices: %{}}, primary_key: [:id], source: \"customtablename_player\", types: %{id: :id, name: :string}}}, - ] - end + def __migration_structures__() do + [ + {CustomTableName.Player.Schema.TestData, %Yacto.Migration.Structure{autogenerate_id: {:id, :id, :id}, field_sources: %{id: :id, name: :name}, fields: [:id, :name], meta: %{attrs: %{name: %{default: \"hoge\", null: false, size: 100}}, indices: %{}}, primary_key: [:id], source: \"customtablename_player\", types: %{id: :id, name: :string}}}, + ] + end - def __migration_version__() do - 20170424155528 - end + def __migration_version__() do + 20170424155528 + end - def __migration_preview_version__() do - nil + def __migration_preview_version__() do + nil + end end -end -""" + """ test "Yacto.Migration.GenMigration generate_source with custom table name." do v1 = [ diff --git a/test/apps/migrator/test/migrator_test.exs b/test/apps/migrator/test/migrator_test.exs index a7da053..48dcf37 100644 --- a/test/apps/migrator/test/migrator_test.exs +++ b/test/apps/migrator/test/migrator_test.exs @@ -263,8 +263,8 @@ defmodule MigratorTest do schemas = Yacto.Migration.Util.get_all_schema(:migrator) :ok = Yacto.Migration.Migrator.up(:migrator, Migrator.Repo1, schemas, migrations) after -# File.rm!("migration_test_1.exs") -# File.rm!("migration_test_2.exs") + # File.rm!("migration_test_1.exs") + # File.rm!("migration_test_2.exs") Code.unload_files(["migration_test_1.exs", "migration_test_2.exs"]) end @@ -278,6 +278,6 @@ defmodule MigratorTest do # 複合主キーが同じデータを追加しようとすると Ecto.ConstraintError が発生する。 record3 = %Migrator.CompositePrimaryKey{player_id: "saito", guild_id: "gumi", name: "12345"} - assert_raise Ecto.ConstraintError, fn -> IO.inspect Migrator.Repo1.insert!(record3) end + assert_raise Ecto.ConstraintError, fn -> IO.inspect(Migrator.Repo1.insert!(record3)) end end end diff --git a/test/yacto/composite_primary_key_test.exs b/test/yacto/composite_primary_key_test.exs index d7038a0..42ea03e 100644 --- a/test/yacto/composite_primary_key_test.exs +++ b/test/yacto/composite_primary_key_test.exs @@ -1,12 +1,13 @@ defmodule Yacto.CompositePrimaryKeyTest do use PowerAssert + defmodule Parent1 do use Ecto.Schema schema "parents" do - field :name, :string - field :player_id, :string - field :foo, :string + field(:name, :string) + field(:player_id, :string) + field(:foo, :string) end end @@ -15,22 +16,21 @@ defmodule Yacto.CompositePrimaryKeyTest do @primary_key false schema "parents" do - field :name, :string - field :player_id, :string, primary_key: true - field :foo, :string, primary_key: true + field(:name, :string) + field(:player_id, :string, primary_key: true) + field(:foo, :string, primary_key: true) end end - test "composite primary key" do - # p = %Parent{name: "foo", player_id: "bar", foo: "baz"} # IO.inspect Parent.__schema__(:primary_key) s1 = Yacto.Migration.Structure.from_schema(Parent1) s2 = Yacto.Migration.Structure.from_schema(Parent2) + Yacto.Migration.Structure.diff(s1, s2) - |> IO.inspect + |> IO.inspect() # %{ # autogenerate_id: {:delete, {:id, :id, :id}}, @@ -39,10 +39,6 @@ defmodule Yacto.CompositePrimaryKeyTest do # primary_key: [del: [:id], ins: [:player_id, :foo]], # source: :not_changed, # types: %{del: %{id: :id}, ins: %{}} - #} - - + # } end - end - From ac381f661b6f5e34e0be7b4de77a932f2632fd66 Mon Sep 17 00:00:00 2001 From: Kenichiro Watanabe Date: Wed, 3 Apr 2019 15:32:47 +0900 Subject: [PATCH 11/16] add TODO.md --- memo.md => TODO.md | 12 +++++++++--- 1 file changed, 9 insertions(+), 3 deletions(-) rename memo.md => TODO.md (70%) diff --git a/memo.md b/TODO.md similarity index 70% rename from memo.md rename to TODO.md index 2a29d52..4ab3245 100644 --- a/memo.md +++ b/TODO.md @@ -1,10 +1,16 @@ +## TODO -## 複合主キーの方針 -### 現在の状況(2019/3/13) +## 2019/4/3 + +* primary_key がすでに存在する場合に投げるエラーをいい感じにする +* 全体的にリファクタする + +## 2019/3/13 + +複合主キーの方針 * 新規モジュールに複合主キーの設定ができる: 実装済み * 既存モジュールに新規フィールドを、primary key を true にして追加できる: 実装済み * 既存モジュールの既存フィールドに primary key を設定することはできない: 対応する * 既存モジュールで設定された primary key だけを削除することはできない: 削除できない仕様です - From d81ea92f6cddea0883764a7abb86d6d3f0ce19cf Mon Sep 17 00:00:00 2001 From: Kenichiro Watanabe Date: Wed, 3 Apr 2019 16:26:16 +0900 Subject: [PATCH 12/16] =?UTF-8?q?=E5=88=86=E5=B2=90=E3=82=92=E3=83=91?= =?UTF-8?q?=E3=82=BF=E3=83=BC=E3=83=B3=E3=83=9E=E3=83=83=E3=83=81=E3=81=A7?= =?UTF-8?q?=E3=81=BE=E3=81=A8=E3=82=81=E3=82=8B?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- lib/yacto/migration/gen_migration.ex | 41 +++++++++++++++---- .../gen_migration/test/gen_migration_test.exs | 16 ++++---- 2 files changed, 41 insertions(+), 16 deletions(-) diff --git a/lib/yacto/migration/gen_migration.ex b/lib/yacto/migration/gen_migration.ex index b30f238..d47cc34 100644 --- a/lib/yacto/migration/gen_migration.ex +++ b/lib/yacto/migration/gen_migration.ex @@ -1,6 +1,10 @@ defmodule Yacto.Migration.GenMigration do require Logger + defmodule GenMigrationError do + defexception [:message, :from, :to] + end + defp convert_fields(types, attrs, primary_keys, autogenerate_id) do # types: # %{del: %{field: type}, @@ -410,15 +414,36 @@ defmodule Yacto.Migration.GenMigration do diff = Yacto.Migration.Structure.diff(structure_from, structure_to) rdiff = Yacto.Migration.Structure.diff(structure_to, structure_from) - if structure_from.primary_key != structure_to.primary_key && structure_from.primary_key != [] do - raise "error" - end + case {structure_from.primary_key, structure_to.primary_key} do + {[], []} -> + :ok + + {[], _to} -> + :ok + + {_from, []} -> + :ok + + {from, to} when from == to -> + case diff.autogenerate_id do + :not_changed -> + :ok + + {:create, _to_value} -> + :ok + + _ -> + raise Yacto.Migration.GenMigration.GenMigrationError, + message: "AutogenerateID Primary key can not be changed", + from: structure_from, + to: structure_to + end - case diff.autogenerate_id do - :not_changed -> :ok - {:create, _to_value} -> :ok - {:delete, _from_value} -> raise "error" - {:changed, _from_value, _to_value} -> raise "error" + {from, to} when from != to -> + raise Yacto.Migration.GenMigration.GenMigrationError, + message: "Primary key already exists", + from: structure_from, + to: structure_to end if diff == rdiff do diff --git a/test/apps/gen_migration/test/gen_migration_test.exs b/test/apps/gen_migration/test/gen_migration_test.exs index d595cf4..f92e84a 100644 --- a/test/apps/gen_migration/test/gen_migration_test.exs +++ b/test/apps/gen_migration/test/gen_migration_test.exs @@ -222,14 +222,14 @@ defmodule GenMigrationTest do assert @migrate3 == source - assert_raise RuntimeError, "error", fn -> - Yacto.Migration.GenMigration.generate_source( - GenMigration, - v4, - 20_170_424_155_533, - 20_170_424_155_532 - ) - end + source = Yacto.Migration.GenMigration.generate_source( + GenMigration, + v4, + 20_170_424_155_533, + 20_170_424_155_532 + ) + + assert @migrate4 == source end @migrate5 """ From 688a2dfb6f2412ea65510c8371549078f8d34d73 Mon Sep 17 00:00:00 2001 From: Kenichiro Watanabe Date: Wed, 3 Apr 2019 16:57:23 +0900 Subject: [PATCH 13/16] =?UTF-8?q?=E3=83=86=E3=82=B9=E3=83=88=E8=BF=BD?= =?UTF-8?q?=E5=8A=A0=E9=80=94=E4=B8=AD=E3=81=BE=E3=81=A7?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- TODO.md | 5 +++-- test/apps/gen_migration/lib/gen_migration.ex | 16 ++++++++++++++++ .../gen_migration/test/gen_migration_test.exs | 14 ++++++++++++++ test/apps/gen_migration/test/mix_test.exs | 2 ++ 4 files changed, 35 insertions(+), 2 deletions(-) diff --git a/TODO.md b/TODO.md index 4ab3245..ceee443 100644 --- a/TODO.md +++ b/TODO.md @@ -3,8 +3,9 @@ ## 2019/4/3 -* primary_key がすでに存在する場合に投げるエラーをいい感じにする -* 全体的にリファクタする +[x] primary_key がすでに存在する場合に投げるエラーをいい感じにする +[] 追加したエラーのテスト +[] 全体的にリファクタする ## 2019/3/13 diff --git a/test/apps/gen_migration/lib/gen_migration.ex b/test/apps/gen_migration/lib/gen_migration.ex index 17b58ae..d6c2ff4 100644 --- a/test/apps/gen_migration/lib/gen_migration.ex +++ b/test/apps/gen_migration/lib/gen_migration.ex @@ -31,6 +31,22 @@ defmodule GenMigration.Player3 do end end +defmodule GenMigration.Player4 do + use Yacto.Schema + + @impl Yacto.Schema + def dbname(), do: :player + + @primary_key {:id, :binary_id, autogenerate: true} + + schema @auto_source do + field(:name3, :string, meta: [null: false, size: 100]) + field(:value, :string) + index([:value, :name3]) + index([:name3, :value], unique: true) + end +end + defmodule GenMigration.Item do use Yacto.Schema diff --git a/test/apps/gen_migration/test/gen_migration_test.exs b/test/apps/gen_migration/test/gen_migration_test.exs index f92e84a..defbe04 100644 --- a/test/apps/gen_migration/test/gen_migration_test.exs +++ b/test/apps/gen_migration/test/gen_migration_test.exs @@ -197,6 +197,11 @@ defmodule GenMigrationTest do %Yacto.Migration.Structure{}} ] + v5 = [ + {GenMigration.Player, Yacto.Migration.Structure.from_schema(GenMigration.Player3), + Yacto.Migration.Structure.from_schema(GenMigration.Player4)} + ] + source = Yacto.Migration.GenMigration.generate_source(GenMigration, v1, 20_170_424_155_528, nil) @@ -230,6 +235,15 @@ defmodule GenMigrationTest do ) assert @migrate4 == source + + # source = Yacto.Migration.GenMigration.generate_source( + # GenMigration, + # v5, + # 20_170_424_155_534, + # 20_170_424_155_553 + # ) + + # assert @migrate4 == source end @migrate5 """ diff --git a/test/apps/gen_migration/test/mix_test.exs b/test/apps/gen_migration/test/mix_test.exs index 3d2b732..780036f 100644 --- a/test/apps/gen_migration/test/mix_test.exs +++ b/test/apps/gen_migration/test/mix_test.exs @@ -21,6 +21,8 @@ defmodule Mix.Tasks.Yacto.GenMigrationTest do Yacto.Migration.Structure.from_schema(GenMigration.Player2)}, {GenMigration.Player3, %Yacto.Migration.Structure{}, Yacto.Migration.Structure.from_schema(GenMigration.Player3)}, + {GenMigration.Player4, %Yacto.Migration.Structure{}, + Yacto.Migration.Structure.from_schema(GenMigration.Player3)}, {GenMigration.Item, %Yacto.Migration.Structure{}, Yacto.Migration.Structure.from_schema(GenMigration.Item)}, {GenMigration.Coin, %Yacto.Migration.Structure{}, From 0addf12b86ec55001af938e5733a1c06be8957da Mon Sep 17 00:00:00 2001 From: Kenichiro Watanabe Date: Wed, 15 May 2019 16:26:43 +0900 Subject: [PATCH 14/16] =?UTF-8?q?=E8=90=BD=E3=81=A1=E3=81=A6=E3=81=84?= =?UTF-8?q?=E3=81=9F=E3=83=86=E3=82=B9=E3=83=88=E3=82=92=E7=9B=B4=E3=81=97?= =?UTF-8?q?=E3=81=9F?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- test/apps/gen_migration/test/mix_test.exs | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/test/apps/gen_migration/test/mix_test.exs b/test/apps/gen_migration/test/mix_test.exs index 780036f..30dd393 100644 --- a/test/apps/gen_migration/test/mix_test.exs +++ b/test/apps/gen_migration/test/mix_test.exs @@ -22,7 +22,7 @@ defmodule Mix.Tasks.Yacto.GenMigrationTest do {GenMigration.Player3, %Yacto.Migration.Structure{}, Yacto.Migration.Structure.from_schema(GenMigration.Player3)}, {GenMigration.Player4, %Yacto.Migration.Structure{}, - Yacto.Migration.Structure.from_schema(GenMigration.Player3)}, + Yacto.Migration.Structure.from_schema(GenMigration.Player4)}, {GenMigration.Item, %Yacto.Migration.Structure{}, Yacto.Migration.Structure.from_schema(GenMigration.Item)}, {GenMigration.Coin, %Yacto.Migration.Structure{}, From 12eec6dfeed93b73ff181cc5a4b18255f1cb059c Mon Sep 17 00:00:00 2001 From: Kenichiro Watanabe Date: Wed, 15 May 2019 16:35:40 +0900 Subject: [PATCH 15/16] =?UTF-8?q?TODO=E3=82=92=E6=B6=88=E3=81=99?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- TODO.md | 17 ----------------- 1 file changed, 17 deletions(-) delete mode 100644 TODO.md diff --git a/TODO.md b/TODO.md deleted file mode 100644 index ceee443..0000000 --- a/TODO.md +++ /dev/null @@ -1,17 +0,0 @@ -## TODO - - -## 2019/4/3 - -[x] primary_key がすでに存在する場合に投げるエラーをいい感じにする -[] 追加したエラーのテスト -[] 全体的にリファクタする - -## 2019/3/13 - -複合主キーの方針 - -* 新規モジュールに複合主キーの設定ができる: 実装済み -* 既存モジュールに新規フィールドを、primary key を true にして追加できる: 実装済み -* 既存モジュールの既存フィールドに primary key を設定することはできない: 対応する -* 既存モジュールで設定された primary key だけを削除することはできない: 削除できない仕様です From 71c20985cb53fba321b792bb2b9841d5a8fc8663 Mon Sep 17 00:00:00 2001 From: Kenichiro Watanabe Date: Wed, 15 May 2019 18:09:45 +0900 Subject: [PATCH 16/16] =?UTF-8?q?primary=5Fkey=20=E9=96=A2=E9=80=A3?= =?UTF-8?q?=E3=81=AE=E3=83=86=E3=82=B9=E3=83=88=E3=82=92=E8=BF=BD=E5=8A=A0?= =?UTF-8?q?=E3=81=97=E3=81=9F?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- lib/yacto/migration/gen_migration.ex | 6 +- .../2017-04-24T155528_gen_migration.exs | 121 ++++++++++++++++++ test/apps/migrator/lib/migrator.ex | 54 ++++++++ test/apps/migrator/test/migrator_test.exs | 78 ++++++++++- test/support/query.ex | 9 ++ test/yacto/query_test.exs | 14 ++ 6 files changed, 279 insertions(+), 3 deletions(-) create mode 100644 test/apps/gen_migration/priv/migrations/2017-04-24T155528_gen_migration.exs diff --git a/lib/yacto/migration/gen_migration.ex b/lib/yacto/migration/gen_migration.ex index d47cc34..1e13031 100644 --- a/lib/yacto/migration/gen_migration.ex +++ b/lib/yacto/migration/gen_migration.ex @@ -3,6 +3,9 @@ defmodule Yacto.Migration.GenMigration do defmodule GenMigrationError do defexception [:message, :from, :to] + def message(error) do + "#{error.message} from: #{inspect error.from} to: #{inspect error.to}" + end end defp convert_fields(types, attrs, primary_keys, autogenerate_id) do @@ -424,6 +427,7 @@ defmodule Yacto.Migration.GenMigration do {_from, []} -> :ok + # TODO このロジックテストされてないのでテスト追加する {from, to} when from == to -> case diff.autogenerate_id do :not_changed -> @@ -441,7 +445,7 @@ defmodule Yacto.Migration.GenMigration do {from, to} when from != to -> raise Yacto.Migration.GenMigration.GenMigrationError, - message: "Primary key already exists", + message: "Primary key can not be changed", from: structure_from, to: structure_to end diff --git a/test/apps/gen_migration/priv/migrations/2017-04-24T155528_gen_migration.exs b/test/apps/gen_migration/priv/migrations/2017-04-24T155528_gen_migration.exs new file mode 100644 index 0000000..53878b9 --- /dev/null +++ b/test/apps/gen_migration/priv/migrations/2017-04-24T155528_gen_migration.exs @@ -0,0 +1,121 @@ +defmodule GenMigration.Migration20170424155528 do + use Ecto.Migration + + def change(GenMigration.Coin) do + create table("genmigration_coin", primary_key: false) do + add(:id, :id) + end + alter table("genmigration_coin") do + modify(:id, :bigserial, [primary_key: true]) + add(:inserted_at, :naive_datetime, []) + add(:platform, :text, [null: false]) + add(:player_id, :string, [null: false]) + add(:quantity, :integer, [default: 0, null: false]) + add(:type_id, :integer, [null: false]) + add(:updated_at, :naive_datetime, []) + end + create index("genmigration_coin", [:player_id, :type_id, :platform], [name: "player_id_t_65380c9f", unique: true]) + end + def change(GenMigration.Item) do + create table("genmigration_item", primary_key: false) do + add(:id, :id) + end + alter table("genmigration_item") do + add(:_gen_migration_dummy, :integer, []) + remove(:id) + end + alter table("genmigration_item") do + remove(:_gen_migration_dummy) + add(:id, :binary_id, [primary_key: true]) + add(:name, :string, []) + end + end + def change(GenMigration.ManyIndex) do + create table("genmigration_manyindex", primary_key: false) do + add(:id, :id) + end + alter table("genmigration_manyindex") do + add(:aaaaaa, :string, []) + add(:bbbbbb, :string, []) + add(:cccccc, :string, []) + add(:dddddd, :string, []) + modify(:id, :bigserial, [primary_key: true]) + end + create index("genmigration_manyindex", [:aaaaaa, :bbbbbb, :cccccc, :dddddd], [name: "aaaaaa_bbbb_9a4e1a2f"]) + end + def change(GenMigration.Player) do + create table("player", primary_key: false) do + add(:id, :id) + end + alter table("player") do + modify(:id, :bigserial, [primary_key: true]) + add(:inserted_at, :naive_datetime, []) + add(:name, :string, []) + add(:updated_at, :naive_datetime, []) + add(:value, :integer, []) + end + end + def change(GenMigration.Player2) do + create table("player2", primary_key: false) do + add(:id, :id) + end + alter table("player2") do + modify(:id, :bigserial, [primary_key: true]) + add(:name2, :string, []) + add(:value, :string, []) + end + end + def change(GenMigration.Player3) do + create table("genmigration_player3", primary_key: false) do + add(:id, :id) + end + alter table("genmigration_player3") do + modify(:id, :bigserial, [primary_key: true]) + add(:name3, :string, [null: false, size: 100]) + add(:value, :string, []) + end + create index("genmigration_player3", [:name3, :value], [name: "name3_value_index", unique: true]) + create index("genmigration_player3", [:value, :name3], [name: "value_name3_index"]) + end + def change(GenMigration.Player4) do + create table("genmigration_player4", primary_key: false) do + add(:id, :id) + end + alter table("genmigration_player4") do + add(:_gen_migration_dummy, :integer, []) + remove(:id) + end + alter table("genmigration_player4") do + remove(:_gen_migration_dummy) + add(:id, :binary_id, [primary_key: true]) + add(:name3, :string, [null: false, size: 100]) + add(:value, :string, []) + end + create index("genmigration_player4", [:name3, :value], [name: "name3_value_index", unique: true]) + create index("genmigration_player4", [:value, :name3], [name: "value_name3_index"]) + end + + def change(_other) do + :ok + end + + def __migration_structures__() do + [ + {GenMigration.Coin, %Yacto.Migration.Structure{autogenerate_id: {:id, :id, :id}, field_sources: %{id: :id, inserted_at: :inserted_at, platform: :platform, player_id: :player_id, quantity: :quantity, type_id: :type_id, updated_at: :updated_at}, fields: [:id, :player_id, :type_id, :platform, :quantity, :inserted_at, :updated_at], meta: %{attrs: %{platform: %{null: false}, player_id: %{null: false}, quantity: %{default: 0, null: false}, type_id: %{null: false}}, indices: %{{[:player_id, :type_id, :platform], [unique: true]} => true}}, primary_key: [:id], source: "genmigration_coin", types: %{id: :id, inserted_at: :naive_datetime, platform: :text, player_id: :string, quantity: :integer, type_id: :integer, updated_at: :naive_datetime}}}, + {GenMigration.Item, %Yacto.Migration.Structure{autogenerate_id: {:id, :id, :binary_id}, field_sources: %{id: :id, name: :name}, fields: [:id, :name], primary_key: [:id], source: "genmigration_item", types: %{id: :binary_id, name: :string}}}, + {GenMigration.ManyIndex, %Yacto.Migration.Structure{autogenerate_id: {:id, :id, :id}, field_sources: %{aaaaaa: :aaaaaa, bbbbbb: :bbbbbb, cccccc: :cccccc, dddddd: :dddddd, id: :id}, fields: [:id, :aaaaaa, :bbbbbb, :cccccc, :dddddd], meta: %{attrs: %{}, indices: %{{[:aaaaaa, :bbbbbb, :cccccc, :dddddd], []} => true}}, primary_key: [:id], source: "genmigration_manyindex", types: %{aaaaaa: :string, bbbbbb: :string, cccccc: :string, dddddd: :string, id: :id}}}, + {GenMigration.Player, %Yacto.Migration.Structure{autogenerate_id: {:id, :id, :id}, field_sources: %{id: :id, inserted_at: :inserted_at, name: :name, updated_at: :updated_at, value: :value}, fields: [:id, :name, :value, :inserted_at, :updated_at], primary_key: [:id], source: "player", types: %{id: :id, inserted_at: :naive_datetime, name: :string, updated_at: :naive_datetime, value: :integer}}}, + {GenMigration.Player2, %Yacto.Migration.Structure{autogenerate_id: {:id, :id, :id}, field_sources: %{id: :id, name2: :name2, value: :value}, fields: [:id, :name2, :value], primary_key: [:id], source: "player2", types: %{id: :id, name2: :string, value: :string}}}, + {GenMigration.Player3, %Yacto.Migration.Structure{autogenerate_id: {:id, :id, :id}, field_sources: %{id: :id, name3: :name3, value: :value}, fields: [:id, :name3, :value], meta: %{attrs: %{name3: %{null: false, size: 100}}, indices: %{{[:name3, :value], [unique: true]} => true, {[:value, :name3], []} => true}}, primary_key: [:id], source: "genmigration_player3", types: %{id: :id, name3: :string, value: :string}}}, + {GenMigration.Player4, %Yacto.Migration.Structure{autogenerate_id: {:id, :id, :binary_id}, field_sources: %{id: :id, name3: :name3, value: :value}, fields: [:id, :name3, :value], meta: %{attrs: %{name3: %{null: false, size: 100}}, indices: %{{[:name3, :value], [unique: true]} => true, {[:value, :name3], []} => true}}, primary_key: [:id], source: "genmigration_player4", types: %{id: :binary_id, name3: :string, value: :string}}}, + ] + end + + def __migration_version__() do + 20170424155528 + end + + def __migration_preview_version__() do + nil + end +end diff --git a/test/apps/migrator/lib/migrator.ex b/test/apps/migrator/lib/migrator.ex index 464530c..12eb12e 100644 --- a/test/apps/migrator/lib/migrator.ex +++ b/test/apps/migrator/lib/migrator.ex @@ -142,3 +142,57 @@ end defmodule Migrator.Repo1 do use Ecto.Repo, otp_app: :migrator, adapter: Ecto.Adapters.MySQL end + +defmodule Migrator.AutogeneratePrimaryKey do + use Yacto.Schema + + @impl Yacto.Schema + def dbname(), do: :default + + @primary_key false + + schema @auto_source do + field(:player_id, :integer, primary_key: true, autogenerated: true) + end +end + +defmodule Migrator.DeleteAutogeneratePrimaryKey do + use Yacto.Schema + + @impl Yacto.Schema + def dbname(), do: :default + + @primary_key false + + schema @auto_source do + field(:player_id, :integer) + end +end + +defmodule Migrator.AutogeneratePrimaryKey2 do + use Yacto.Schema + + @impl Yacto.Schema + def dbname(), do: :default + + @primary_key false + + schema @auto_source do + field(:player_id, :id, primary_key: true, autogenerate: true) + field(:unit_id, :id, primary_key: true) + end +end + +defmodule Migrator.DeleteAutogeneratePrimaryKey2 do + use Yacto.Schema + + @impl Yacto.Schema + def dbname(), do: :default + + @primary_key false + + schema @auto_source do + field(:player_id, :id, primary_key: true) + field(:unit_id, :id, primary_key: true) + end +end diff --git a/test/apps/migrator/test/migrator_test.exs b/test/apps/migrator/test/migrator_test.exs index 48dcf37..32dc378 100644 --- a/test/apps/migrator/test/migrator_test.exs +++ b/test/apps/migrator/test/migrator_test.exs @@ -263,8 +263,8 @@ defmodule MigratorTest do schemas = Yacto.Migration.Util.get_all_schema(:migrator) :ok = Yacto.Migration.Migrator.up(:migrator, Migrator.Repo1, schemas, migrations) after - # File.rm!("migration_test_1.exs") - # File.rm!("migration_test_2.exs") + File.rm!("migration_test_1.exs") + File.rm!("migration_test_2.exs") Code.unload_files(["migration_test_1.exs", "migration_test_2.exs"]) end @@ -280,4 +280,78 @@ defmodule MigratorTest do record3 = %Migrator.CompositePrimaryKey{player_id: "saito", guild_id: "gumi", name: "12345"} assert_raise Ecto.ConstraintError, fn -> IO.inspect(Migrator.Repo1.insert!(record3)) end end + + test "プライマリキーを削除することができる" do + Mix.Task.rerun("ecto.drop") + Mix.Task.rerun("ecto.create") + + {:ok, _} = Migrator.Repo1.start_link() + v1 = [ + {Migrator.AutogeneratePrimaryKey, %Yacto.Migration.Structure{}, + Yacto.Migration.Structure.from_schema(Migrator.AutogeneratePrimaryKey)} + ] + + v2 = [ + {Migrator.DeleteAutogeneratePrimaryKey, Yacto.Migration.Structure.from_schema(Migrator.AutogeneratePrimaryKey), + Yacto.Migration.Structure.from_schema(Migrator.DeleteAutogeneratePrimaryKey)} + ] + + source = Yacto.Migration.GenMigration.generate_source(Migrator, v1, 20_190_515_162_530, nil) + File.write!("migration_test_1.exs", source) + + source = Yacto.Migration.GenMigration.generate_source( Migrator, + v2, + 20_190_515_162_533, + 20_190_515_162_530 + ) + + File.write!("migration_test_2.exs", source) + + try do + migrations = + Yacto.Migration.Util.load_migrations(["migration_test_1.exs", "migration_test_2.exs"]) + + schemas = Yacto.Migration.Util.get_all_schema(:migrator) + :ok = Yacto.Migration.Migrator.up(:migrator, Migrator.Repo1, schemas, migrations) + after + File.rm!("migration_test_1.exs") + File.rm!("migration_test_2.exs") + Code.unload_files(["migration_test_1.exs", "migration_test_2.exs"]) + end + end + + test "Autogenerated な複合プライマリキーを変更することはできない" do + ExUnit.Callbacks.on_exit(fn -> + File.rm!("migration_test_1.exs") + File.rm!("migration_test_2.exs") + Code.unload_files(["migration_test_1.exs", "migration_test_2.exs"]) + end) + + Mix.Task.rerun("ecto.drop") + Mix.Task.rerun("ecto.create") + + {:ok, _} = Migrator.Repo1.start_link() + + v1 = [ + {Migrator.AutogeneratePrimaryKey2, %Yacto.Migration.Structure{}, + Yacto.Migration.Structure.from_schema(Migrator.AutogeneratePrimaryKey2)} + ] + + v2 = [ + {Migrator.DeleteAutogeneratePrimaryKey2, Yacto.Migration.Structure.from_schema(Migrator.AutogeneratePrimaryKey2), + Yacto.Migration.Structure.from_schema(Migrator.DeleteAutogeneratePrimaryKey2)} + ] + + source = Yacto.Migration.GenMigration.generate_source(Migrator, v1, 20_190_515_162_530, nil) + File.write!("migration_test_1.exs", source) + + assert_raise(Yacto.Migration.GenMigration.GenMigrationError, + ~r/AutogenerateID Primary key can not be changed/, fn -> + Yacto.Migration.GenMigration.generate_source( Migrator, + v2, + 20_190_515_162_533, + 20_190_515_162_530 + ) + end) + end end diff --git a/test/support/query.ex b/test/support/query.ex index b1201d5..5bbb27e 100644 --- a/test/support/query.ex +++ b/test/support/query.ex @@ -22,6 +22,15 @@ defmodule Yacto.QueryTest.Item do end end +defmodule Yacto.QueryTest.UniqueItem do + use Yacto.Schema.Single, dbname: :default + + schema "item" do + field(:name, :string, unique: true) + field(:quantity, :integer) + end +end + defmodule Yacto.QueryTest.Default.Migration do use Ecto.Migration diff --git a/test/yacto/query_test.exs b/test/yacto/query_test.exs index bc176bc..f236651 100644 --- a/test/yacto/query_test.exs +++ b/test/yacto/query_test.exs @@ -145,6 +145,20 @@ defmodule Yacto.QueryTest do test_get_by_or_new(true) end + test "Yacto.Repo.get_by_or_new with lock2" do + repo = Yacto.QueryTest.UniqueItem.repo() + repo.get_by_or_insert_for_update( + Yacto.QueryTest.Item, + [name: "foo"], + Ecto.Changeset.change(%Yacto.QueryTest.Item{name: "foo", quantity: 1000}) + ) + repo.get_by_or_insert_for_update( + Yacto.QueryTest.Item, + [name: "foo"], + Ecto.Changeset.change(%Yacto.QueryTest.Item{name: "foo", quantity: 2000}) + ) + end + test "Yacto.Repo.find" do mod = Yacto.QueryTest.Item assert length(mod.repo().find(mod, name: "foo")) == 1