Packages
ecto
3.2.2
3.14.1
3.14.0
3.13.6
3.13.5
3.13.4
3.13.3
3.13.2
3.13.1
3.13.0
3.12.6
3.12.5
3.12.4
3.12.3
3.12.2
3.12.1
3.12.0
3.11.2
3.11.1
3.11.0
3.10.3
3.10.2
3.10.1
3.10.0
3.9.6
3.9.5
3.9.4
3.9.3
3.9.2
3.9.1
3.9.0
3.8.4
3.8.3
3.8.2
3.8.1
3.8.0
3.7.2
3.7.1
3.7.0
3.6.2
3.6.1
3.6.0
3.5.8
3.5.7
3.5.6
3.5.5
3.5.4
3.5.3
3.5.2
3.5.1
3.5.0
3.5.0-rc.1
3.5.0-rc.0
3.4.6
3.4.5
3.4.4
3.4.3
3.4.2
3.4.1
3.4.0
3.3.4
3.3.3
3.3.2
3.3.1
3.3.0
3.2.5
3.2.4
3.2.3
3.2.2
3.2.1
3.2.0
3.1.7
3.1.6
3.1.5
3.1.4
3.1.3
3.1.2
3.1.1
3.1.0
3.0.9
3.0.8
3.0.7
3.0.6
3.0.5
3.0.4
3.0.3
3.0.2
3.0.1
3.0.0
3.0.0-rc.1
3.0.0-rc.0
2.2.12
2.2.11
2.2.10
2.2.9
2.2.8
2.2.7
2.2.6
2.2.5
2.2.4
2.2.3
2.2.2
2.2.1
2.2.0
2.2.0-rc.1
2.2.0-rc.0
2.1.6
2.1.5
2.1.4
2.1.3
2.1.2
2.1.1
2.1.0
2.1.0-rc.5
2.1.0-rc.4
2.1.0-rc.3
2.1.0-rc.2
2.1.0-rc.1
2.1.0-rc.0
2.0.6
2.0.5
2.0.4
2.0.3
2.0.2
2.0.1
2.0.0
2.0.0-rc.6
2.0.0-rc.5
2.0.0-rc.4
2.0.0-rc.3
2.0.0-rc.2
2.0.0-rc.1
2.0.0-rc.0
2.0.0-beta.2
2.0.0-beta.1
2.0.0-beta.0
1.1.9
1.1.8
1.1.7
1.1.6
1.1.5
1.1.4
1.1.3
1.1.2
1.1.1
1.1.0
1.0.7
1.0.6
1.0.5
1.0.4
1.0.3
1.0.2
1.0.1
1.0.0
0.16.0
0.15.0
0.14.3
0.14.2
0.14.1
0.14.0
0.13.1
0.13.0
0.12.1
0.12.0
0.12.0-rc
0.11.3
0.11.2
0.11.1
0.11.0
0.10.3
0.10.2
0.10.1
0.10.0
0.9.0
0.8.1
0.8.0
0.7.2
0.7.1
0.7.0
0.6.0
0.5.1
0.5.0
0.4.0
0.3.0
0.2.8
0.2.7
0.2.6
0.2.5
0.2.4
0.2.3
0.2.2
0.2.1
0.2.0
0.1.0
A toolkit for data mapping and language integrated query for Elixir
Current section
Files
Jump to
Current section
Files
integration_test/cases/type.exs
Code.require_file "../support/types.exs", __DIR__
defmodule Ecto.Integration.TypeTest do
use Ecto.Integration.Case, async: Application.get_env(:ecto, :async_integration_tests, true)
alias Ecto.Integration.{Custom, Item, ItemColor, Order, Post, User, Tag, Usec}
alias Ecto.Integration.TestRepo
import Ecto.Query
test "primitive types" do
integer = 1
float = 0.1
text = <<0, 1>>
uuid = "00010203-0405-4607-8809-0a0b0c0d0e0f"
datetime = ~N[2014-01-16 20:26:51]
TestRepo.insert!(%Post{text: text, public: true, visits: integer, uuid: uuid,
counter: integer, inserted_at: datetime, intensity: float})
# nil
assert [nil] = TestRepo.all(from Post, select: nil)
# ID
assert [1] = TestRepo.all(from p in Post, where: p.counter == ^integer, select: p.counter)
# Integers
assert [1] = TestRepo.all(from p in Post, where: p.visits == ^integer, select: p.visits)
assert [1] = TestRepo.all(from p in Post, where: p.visits == 1, select: p.visits)
assert [3] = TestRepo.all(from p in Post, select: p.visits + 2)
# Floats
assert [0.1] = TestRepo.all(from p in Post, where: p.intensity == ^float, select: p.intensity)
assert [0.1] = TestRepo.all(from p in Post, where: p.intensity == 0.1, select: p.intensity)
assert [1500.0] = TestRepo.all(from p in Post, select: 1500.0)
assert [0.5] = TestRepo.all(from p in Post, select: p.intensity * 5)
# Booleans
assert [true] = TestRepo.all(from p in Post, where: p.public == ^true, select: p.public)
assert [true] = TestRepo.all(from p in Post, where: p.public == true, select: p.public)
assert [false] = TestRepo.all(from p in Post, where: p.public == true, select: not p.public)
assert [true] = TestRepo.all(from p in Post, where: p.public == true, select: not not p.public)
# Binaries
assert [^text] = TestRepo.all(from p in Post, where: p.text == <<0, 1>>, select: p.text)
assert [^text] = TestRepo.all(from p in Post, where: p.text == ^text, select: p.text)
# UUID
assert [^uuid] = TestRepo.all(from p in Post, where: p.uuid == ^uuid, select: p.uuid)
# NaiveDatetime
assert [^datetime] = TestRepo.all(from p in Post, where: p.inserted_at == ^datetime, select: p.inserted_at)
# Datetime
datetime = DateTime.from_unix!(System.os_time(:second), :second)
TestRepo.insert!(%User{inserted_at: datetime})
assert [^datetime] = TestRepo.all(from u in User, where: u.inserted_at == ^datetime, select: u.inserted_at)
# usec
naive_datetime = ~N[2014-01-16 20:26:51.000000]
datetime = DateTime.from_naive!(~N[2014-01-16 20:26:51.000000], "Etc/UTC")
TestRepo.insert!(%Usec{naive_datetime_usec: naive_datetime, utc_datetime_usec: datetime})
assert [^naive_datetime] = TestRepo.all(from u in Usec, where: u.naive_datetime_usec == ^naive_datetime, select: u.naive_datetime_usec)
assert [^datetime] = TestRepo.all(from u in Usec, where: u.utc_datetime_usec == ^datetime, select: u.utc_datetime_usec)
naive_datetime = ~N[2014-01-16 20:26:51.123000]
datetime = DateTime.from_naive!(~N[2014-01-16 20:26:51.123000], "Etc/UTC")
TestRepo.insert!(%Usec{naive_datetime_usec: naive_datetime, utc_datetime_usec: datetime})
assert [^naive_datetime] = TestRepo.all(from u in Usec, where: u.naive_datetime_usec == ^naive_datetime, select: u.naive_datetime_usec)
assert [^datetime] = TestRepo.all(from u in Usec, where: u.utc_datetime_usec == ^datetime, select: u.utc_datetime_usec)
end
test "aggregate types" do
datetime = ~N[2014-01-16 20:26:51]
TestRepo.insert!(%Post{inserted_at: datetime})
query = from p in Post, select: max(p.inserted_at)
assert [^datetime] = TestRepo.all(query)
end
@tag :aggregate_filters
test "aggregate filter types" do
datetime = ~N[2014-01-16 20:26:51]
TestRepo.insert!(%Post{inserted_at: datetime})
query = from p in Post, select: filter(max(p.inserted_at), p.public == ^true)
assert [^datetime] = TestRepo.all(query)
end
test "coalesce type when default" do
TestRepo.insert!(%Post{text: nil})
text = <<0, 1>>
query = from p in Post, select: coalesce(p.text, ^text)
assert [^text] = TestRepo.all(query)
end
test "coalesce type when value" do
text = <<0, 2>>
default_text = <<0, 1>>
TestRepo.insert!(%Post{text: text})
query = from p in Post, select: coalesce(p.text, ^default_text)
assert [^text] = TestRepo.all(query)
end
test "tagged types" do
TestRepo.insert!(%Post{})
# Numbers
assert [1] = TestRepo.all(from Post, select: type(^"1", :integer))
assert [1.0] = TestRepo.all(from Post, select: type(^1.0, :float))
assert [1] = TestRepo.all(from p in Post, select: type(^"1", p.visits))
assert [1.0] = TestRepo.all(from p in Post, select: type(^"1", p.intensity))
# Custom wrappers
assert [1] = TestRepo.all(from Post, select: type(^"1", Elixir.Custom.Permalink))
# Custom types
uuid = Ecto.UUID.generate()
assert [^uuid] = TestRepo.all(from Post, select: type(^uuid, Ecto.UUID))
# Math operations
assert [4] = TestRepo.all(from Post, select: type(2 + ^"2", :integer))
assert [4.0] = TestRepo.all(from Post, select: type(2.0 + ^"2", :float))
assert [4] = TestRepo.all(from p in Post, select: type(2 + ^"2", p.visits))
assert [4.0] = TestRepo.all(from p in Post, select: type(2.0 + ^"2", p.intensity))
end
test "binary id type" do
assert %Custom{} = custom = TestRepo.insert!(%Custom{})
bid = custom.bid
assert [^bid] = TestRepo.all(from c in Custom, select: c.bid)
assert [^bid] = TestRepo.all(from c in Custom, select: type(^bid, :binary_id))
end
test "text type" do
assert %Order{} = order = TestRepo.insert!(%Order{instructions: "hello"})
id = order.id
assert order.instructions == "hello"
assert [^id] = TestRepo.all(from o in Order, where: o.instructions == ^"hello", select: o.id)
end
@tag :array_type
test "array type" do
ints = [1, 2, 3]
tag = TestRepo.insert!(%Tag{ints: ints})
assert TestRepo.all(from t in Tag, where: t.ints == ^[], select: t.ints) == []
assert TestRepo.all(from t in Tag, where: t.ints == ^[1, 2, 3], select: t.ints) == [ints]
# Both sides interpolation
assert TestRepo.all(from t in Tag, where: ^"b" in ^["a", "b", "c"], select: t.ints) == [ints]
assert TestRepo.all(from t in Tag, where: ^"b" in [^"a", ^"b", ^"c"], select: t.ints) == [ints]
# Querying
assert TestRepo.all(from t in Tag, where: t.ints == [1, 2, 3], select: t.ints) == [ints]
assert TestRepo.all(from t in Tag, where: 0 in t.ints, select: t.ints) == []
assert TestRepo.all(from t in Tag, where: 1 in t.ints, select: t.ints) == [ints]
# Update
tag = TestRepo.update!(Ecto.Changeset.change tag, ints: nil)
assert TestRepo.get!(Tag, tag.id).ints == nil
tag = TestRepo.update!(Ecto.Changeset.change tag, ints: [3, 2, 1])
assert TestRepo.get!(Tag, tag.id).ints == [3, 2, 1]
# Update all
{1, _} = TestRepo.update_all(Tag, push: [ints: 0])
assert TestRepo.get!(Tag, tag.id).ints == [3, 2, 1, 0]
{1, _} = TestRepo.update_all(Tag, pull: [ints: 2])
assert TestRepo.get!(Tag, tag.id).ints == [3, 1, 0]
{1, _} = TestRepo.update_all(Tag, set: [ints: nil])
assert TestRepo.get!(Tag, tag.id).ints == nil
end
@tag :array_type
test "array type with custom types" do
uuids = ["51fcfbdd-ad60-4ccb-8bf9-47aabd66d075"]
TestRepo.insert!(%Tag{uuids: ["51fcfbdd-ad60-4ccb-8bf9-47aabd66d075"]})
assert TestRepo.all(from t in Tag, where: t.uuids == ^[], select: t.uuids) == []
assert TestRepo.all(from t in Tag, where: t.uuids == ^["51fcfbdd-ad60-4ccb-8bf9-47aabd66d075"],
select: t.uuids) == [uuids]
{1, _} = TestRepo.update_all(Tag, set: [uuids: nil])
assert TestRepo.all(from t in Tag, select: t.uuids) == [nil]
end
@tag :array_type
test "array type with nil in array" do
tag = TestRepo.insert!(%Tag{ints: [1, nil, 3]})
assert tag.ints == [1, nil, 3]
end
@tag :map_type
test "untyped map" do
post1 = TestRepo.insert!(%Post{meta: %{"foo" => "bar", "baz" => "bat"}})
post2 = TestRepo.insert!(%Post{meta: %{foo: "bar", baz: "bat"}})
assert TestRepo.all(from p in Post, where: p.id == ^post1.id, select: p.meta) ==
[%{"foo" => "bar", "baz" => "bat"}]
assert TestRepo.all(from p in Post, where: p.id == ^post2.id, select: p.meta) ==
[%{"foo" => "bar", "baz" => "bat"}]
end
@tag :map_type
test "typed string map" do
post1 = TestRepo.insert!(%Post{links: %{"foo" => "http://foo.com", "bar" => "http://bar.com"}})
post2 = TestRepo.insert!(%Post{links: %{foo: "http://foo.com", bar: "http://bar.com"}})
assert TestRepo.all(from p in Post, where: p.id == ^post1.id, select: p.links) ==
[%{"foo" => "http://foo.com", "bar" => "http://bar.com"}]
assert TestRepo.all(from p in Post, where: p.id == ^post2.id, select: p.links) ==
[%{"foo" => "http://foo.com", "bar" => "http://bar.com"}]
end
@tag :map_type
test "typed float map" do
post = TestRepo.insert!(%Post{intensities: %{"foo" => 1.0, "bar" => 416500.0}})
# Note we are using === since we want to check integer vs float
assert TestRepo.all(from p in Post, where: p.id == ^post.id, select: p.intensities) ===
[%{"foo" => 1.0, "bar" => 416500.0}]
end
@tag :map_type
test "map type on update" do
post = TestRepo.insert!(%Post{meta: %{"world" => "hello"}})
assert TestRepo.get!(Post, post.id).meta == %{"world" => "hello"}
post = TestRepo.update!(Ecto.Changeset.change post, meta: %{hello: "world"})
assert TestRepo.get!(Post, post.id).meta == %{"hello" => "world"}
query = from(p in Post, where: p.id == ^post.id)
TestRepo.update_all(query, set: [meta: %{world: "hello"}])
assert TestRepo.get!(Post, post.id).meta == %{"world" => "hello"}
end
@tag :map_type
test "embeds one" do
item = %Item{price: 123, valid_at: ~D[2014-01-16]}
order =
%Order{}
|> Ecto.Changeset.change
|> Ecto.Changeset.put_embed(:item, item)
|> TestRepo.insert!()
dbitem = TestRepo.get!(Order, order.id).item
assert item.reference == dbitem.reference
assert item.price == dbitem.price
assert item.valid_at == dbitem.valid_at
assert dbitem.id
[dbitem] = TestRepo.all(from o in Order, select: o.item)
assert item.reference == dbitem.reference
assert item.price == dbitem.price
assert item.valid_at == dbitem.valid_at
assert dbitem.id
{1, _} = TestRepo.update_all(Order, set: [item: %{dbitem | price: 456}])
assert TestRepo.get!(Order, order.id).item.price == 456
end
@tag :map_type
test "embeds one with custom type" do
item = %Item{price: 123, reference: "PREFIX-EXAMPLE"}
order =
%Order{}
|> Ecto.Changeset.change
|> Ecto.Changeset.put_embed(:item, item)
|> TestRepo.insert!()
dbitem = TestRepo.get!(Order, order.id).item
assert dbitem.reference == "PREFIX-EXAMPLE"
assert [%{"reference" => "EXAMPLE"}] = TestRepo.all(from o in "orders", select: o.item)
end
@tag :map_type
test "empty embeds one" do
order = TestRepo.insert!(%Order{})
assert order.item == nil
assert TestRepo.get!(Order, order.id).item == nil
end
@tag :map_type
@tag :array_type
test "embeds many" do
item = %Item{price: 123, valid_at: ~D[2014-01-16]}
tag =
%Tag{}
|> Ecto.Changeset.change
|> Ecto.Changeset.put_embed(:items, [item])
tag = TestRepo.insert!(tag)
[dbitem] = TestRepo.get!(Tag, tag.id).items
assert item.price == dbitem.price
assert item.valid_at == dbitem.valid_at
assert dbitem.id
[[dbitem]] = TestRepo.all(from t in Tag, select: t.items)
assert item.price == dbitem.price
assert item.valid_at == dbitem.valid_at
assert dbitem.id
{1, _} = TestRepo.update_all(Tag, set: [items: [%{dbitem | price: 456}]])
assert (TestRepo.get!(Tag, tag.id).items |> hd).price == 456
end
@tag :map_type
@tag :array_type
test "empty embeds many" do
tag = TestRepo.insert!(%Tag{})
assert tag.items == []
assert TestRepo.get!(Tag, tag.id).items == []
end
@tag :map_type
@tag :array_type
test "nested embeds" do
red = %ItemColor{name: "red"}
blue = %ItemColor{name: "blue"}
item = %Item{
primary_color: red,
secondary_colors: [blue]
}
order =
%Order{}
|> Ecto.Changeset.change
|> Ecto.Changeset.put_embed(:item, item)
order = TestRepo.insert!(order)
dbitem = TestRepo.get!(Order, order.id).item
assert item.primary_color == dbitem.primary_color
assert item.secondary_colors == dbitem.secondary_colors
assert dbitem.id
[dbitem] = TestRepo.all(from o in Order, select: o.item)
assert item.primary_color == dbitem.primary_color
assert item.secondary_colors == dbitem.secondary_colors
assert dbitem.id
end
@tag :decimal_type
test "decimal type" do
decimal = Decimal.new("1.0")
TestRepo.insert!(%Post{cost: decimal})
assert [^decimal] = TestRepo.all(from p in Post, where: p.cost == ^decimal, select: p.cost)
assert [^decimal] = TestRepo.all(from p in Post, where: p.cost == ^1.0, select: p.cost)
assert [^decimal] = TestRepo.all(from p in Post, where: p.cost == ^1, select: p.cost)
assert [^decimal] = TestRepo.all(from p in Post, where: p.cost == 1.0, select: p.cost)
assert [^decimal] = TestRepo.all(from p in Post, where: p.cost == 1, select: p.cost)
assert TestRepo.all(from p in Post, select: p.cost * 2) == [Decimal.new("2.0")]
assert TestRepo.all(from p in Post, select: p.cost - p.cost) == [Decimal.new("0.0")]
assert TestRepo.all(from p in Post, select: type(2 + ^"2", p.cost)) == [Decimal.new("4")]
assert TestRepo.all(from p in Post, select: type(2.0 + ^"2", p.cost)) == [Decimal.new("4.0")]
end
@tag :decimal_type
test "typed aggregations" do
decimal = Decimal.new("1.0")
TestRepo.insert!(%Post{cost: decimal})
assert [1] = TestRepo.all(from p in Post, select: type(sum(p.cost), :integer))
assert [1.0] = TestRepo.all(from p in Post, select: type(sum(p.cost), :float))
assert [^decimal] = TestRepo.all(from p in Post, select: type(sum(p.cost), :decimal))
end
test "schemaless types" do
TestRepo.insert!(%Post{visits: 123})
assert [123] = TestRepo.all(from p in "posts", select: type(p.visits, :integer))
end
test "schemaless calendar types" do
datetime = ~N[2014-01-16 20:26:51]
assert {1, _} =
TestRepo.insert_all("posts", [[inserted_at: datetime]])
assert {1, _} =
TestRepo.update_all("posts", set: [inserted_at: datetime])
assert [_] =
TestRepo.all(from p in "posts", where: p.inserted_at >= ^datetime, select: p.inserted_at)
assert [_] =
TestRepo.all(from p in "posts", where: p.inserted_at in [^datetime], select: p.inserted_at)
assert [_] =
TestRepo.all(from p in "posts", where: p.inserted_at in ^[datetime], select: p.inserted_at)
end
end