-
Notifications
You must be signed in to change notification settings - Fork 0
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
[JET-1762] schemaless 增加 insert_all/4 (#46)
- Loading branch information
Showing
13 changed files
with
332 additions
and
14 deletions.
There are no files selected for viewing
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,10 @@ | ||
import Config | ||
|
||
config :jet_ext, ecto_repos: [JetExt.Repo] | ||
|
||
config :jet_ext, JetExt.Repo, | ||
migration_foreign_key: [type: :binary_id], | ||
migration_primary_key: [type: :binary_id], | ||
migration_timestamps: [type: :utc_datetime_usec] | ||
|
||
import_config "#{config_env()}.exs" |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1 @@ | ||
import Config |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,8 @@ | ||
import Config | ||
|
||
config :jet_ext, JetExt.Repo, | ||
hostname: "localhost", | ||
database: "jet_ext_test", | ||
username: "postgres", | ||
password: "postgres", | ||
pool: Ecto.Adapters.SQL.Sandbox |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,57 @@ | ||
defmodule JetExt.Ecto.Schemaless.RepoTest do | ||
use JetExt.Case.Database, async: false | ||
|
||
alias JetExt.Ecto.Schemaless.Query | ||
alias JetExt.Ecto.Schemaless.Repo | ||
|
||
@movie_name "movies" | ||
|
||
@movie_columns [ | ||
{:add, :id, :uuid, primary_key: true, auto_generate: true}, | ||
{:add, :title, :text, null: false}, | ||
{:add, :likes, :numeric, null: false}, | ||
{:add, :released, :boolean, null: false}, | ||
{:add, :release_date, :date, null: false}, | ||
{:add, :created_at, :timestamp, null: false, auto_generate: true}, | ||
{:add, :tags, {:array, :text}, null: false} | ||
] | ||
|
||
setup :setup_tables | ||
|
||
describe "insert_all/4" do | ||
@describetag [tables: [{@movie_name, @movie_columns}]] | ||
|
||
test "works" do | ||
schema = build_schema(@movie_name, @movie_columns) | ||
|
||
entries = [ | ||
%{ | ||
"title" => "Longlegs", | ||
"likes" => 1024, | ||
"released" => false, | ||
"release_date" => "2024-12-31", | ||
"tags" => ["Crime", "Horror", "Thriller"] | ||
}, | ||
%{ | ||
"title" => "Twisters", | ||
"likes" => 1024, | ||
"released" => false, | ||
"release_date" => "2024-12-31", | ||
"tags" => ["Action", "Adventure", "Thriller"] | ||
}, | ||
%{ | ||
"title" => "Find Me Falling", | ||
"likes" => 1024, | ||
"released" => false, | ||
"release_date" => "2024-12-31", | ||
"tags" => ["Comedy", "Music", "Romance"] | ||
} | ||
] | ||
|
||
assert {:ok, {3, nil}} = Repo.insert_all(JetExt.Repo, schema, entries) | ||
|
||
assert [%{title: "Longlegs"}, %{title: "Twisters"}, %{title: "Find Me Falling"}] = | ||
JetExt.Repo.all(Query.from(schema)) | ||
end | ||
end | ||
end |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,61 @@ | ||
defmodule JetExt.Ecto.Schemaless.SchemaTest do | ||
use JetExt.Case.Database, async: false | ||
|
||
alias JetExt.Ecto.Schemaless.Schema | ||
|
||
@movie_name "movies" | ||
|
||
@movie_columns [ | ||
{:add, :id, :uuid, primary_key: true, auto_generate: true}, | ||
{:add, :title, :text, null: false}, | ||
{:add, :likes, :numeric, null: false}, | ||
{:add, :released, :boolean, null: false}, | ||
{:add, :release_date, :date, null: false}, | ||
{:add, :created_at, :timestamp, null: false, auto_generate: true}, | ||
{:add, :tags, {:array, :text}, null: false} | ||
] | ||
|
||
describe "dump!/2" do | ||
setup :build_schema | ||
|
||
test "works", ctx do | ||
%{schema: schema} = ctx | ||
|
||
row = %{ | ||
title: "Longlegs", | ||
likes: 1024, | ||
released: false, | ||
release_date: ~D[2024-12-31], | ||
created_at: ~U[2024-08-01 08:06:29.240326Z], | ||
tags: ["Crime", "Horror", "Thriller"] | ||
} | ||
|
||
assert %{ | ||
title: "Longlegs", | ||
likes: %Decimal{coef: 1024}, | ||
released: false, | ||
release_date: ~D[2024-12-31], | ||
created_at: ~U[2024-08-01 08:06:29.240326Z], | ||
tags: ["Crime", "Horror", "Thriller"] | ||
} = Schema.dump!(schema, row) | ||
end | ||
|
||
test "dumps only explicit keys", ctx do | ||
%{schema: schema} = ctx | ||
|
||
assert values = Schema.dump!(schema, %{title: "Longlegs"}) | ||
assert [:title] = Map.keys(values) | ||
end | ||
|
||
test "keeps explicit nil", ctx do | ||
%{schema: schema} = ctx | ||
|
||
assert %{title: nil} = values = Schema.dump!(schema, %{title: nil}) | ||
assert [:title] = Map.keys(values) | ||
end | ||
end | ||
|
||
defp build_schema(_ctx) do | ||
[schema: build_schema(@movie_name, @movie_columns)] | ||
end | ||
end |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,88 @@ | ||
defmodule JetExt.Case.Database do | ||
use ExUnit.CaseTemplate | ||
|
||
alias Ecto.Adapters.SQL.Sandbox | ||
alias JetExt.Ecto.Schemaless.Schema, as: SchemalessSchema | ||
|
||
@types %{ | ||
{:array, :text} => {:array, :string}, | ||
uuid: Ecto.UUID, | ||
text: :string, | ||
numeric: :decimal, | ||
boolean: :boolean, | ||
timestamp: :utc_datetime_usec, | ||
date: :date | ||
} | ||
|
||
@generators %{ | ||
uuid: {Ecto.UUID, :generate, []}, | ||
timestamp: {DateTime, :utc_now, []} | ||
} | ||
|
||
using do | ||
quote location: :keep do | ||
import Ecto | ||
import Ecto.Changeset | ||
import Ecto.Query | ||
import unquote(__MODULE__) | ||
end | ||
end | ||
|
||
setup ctx do | ||
JetExt.Case.Database.setup_sandbox(ctx) | ||
end | ||
|
||
@doc """ | ||
Sets up the sandbox based on the test context. | ||
""" | ||
@spec setup_sandbox(ctx :: map()) :: :ok | ||
def setup_sandbox(%{async: async}) do | ||
pid = Sandbox.start_owner!(JetExt.Repo, shared: not async) | ||
on_exit(fn -> Sandbox.stop_owner(pid) end) | ||
end | ||
|
||
@spec setup_tables(ctx :: map()) :: :ok | ||
def setup_tables(ctx) do | ||
ctx | ||
|> Map.get(:tables, []) | ||
|> Enum.each(fn {name, columns} -> | ||
table = Ecto.Migration.table(name) | ||
|
||
{:ok, _result} = JetExt.Repo.execute_ddl({:create, table, columns}) | ||
|
||
on_exit({:drop_table, name}, fn -> | ||
{:ok, _result} = JetExt.Repo.execute_ddl({:drop_if_exists, table, :restrict}) | ||
end) | ||
end) | ||
end | ||
|
||
@spec build_schema(table :: binary, columns :: [term()]) :: SchemalessSchema.t() | ||
def build_schema(table, columns) do | ||
types = | ||
Map.new(columns, fn {:add, name, type, _opts} -> | ||
{name, Map.fetch!(@types, type)} | ||
end) | ||
|
||
options = [ | ||
source: table, | ||
primary_key: build_primary_key(columns), | ||
autogenerate: build_autogenerate(columns) | ||
] | ||
|
||
SchemalessSchema.new(types, options) | ||
end | ||
|
||
defp build_primary_key(columns) do | ||
Enum.flat_map(columns, fn {:add, name, _type, opts} -> | ||
if Keyword.get(opts, :primary_key, false), do: [name], else: [] | ||
end) | ||
end | ||
|
||
defp build_autogenerate(columns) do | ||
Enum.flat_map(columns, fn {:add, name, type, opts} -> | ||
if Keyword.get(opts, :auto_generate, false), | ||
do: [{[name], Map.fetch!(@generators, type)}], | ||
else: [] | ||
end) | ||
end | ||
end |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,13 @@ | ||
defmodule JetExt.Repo do | ||
@moduledoc false | ||
|
||
use Ecto.Repo, otp_app: :jet_ext, adapter: Ecto.Adapters.Postgres | ||
|
||
@spec execute_ddl(command :: term()) :: Postgrex.Result.t() | ||
def execute_ddl(command) do | ||
command | ||
|> Ecto.Adapters.Postgres.Connection.execute_ddl() | ||
|> Enum.map(&IO.iodata_to_binary/1) | ||
|> query() | ||
end | ||
end |
Oops, something went wrong.