Packages
ecto
3.13.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
defmodule Ecto.Integration.TypeTest do
use Ecto.Integration.Case, async: Application.compile_env(:ecto, :async_integration_tests, true)
alias Ecto.Integration.{Bitstring, Comment, Custom, Item, ItemColor, Order, Post, User, Tag, Usec}
alias Ecto.Integration.TestRepo
import Ecto.Query
@parameterized_type Ecto.ParameterizedType.init(Ecto.Enum, values: [:a, :b])
test "primitive types" do
integer = 1
float = 0.1
blob = <<0, 1>>
uuid = "00010203-0405-4607-8809-0a0b0c0d0e0f"
datetime = ~N[2014-01-16 20:26:51]
TestRepo.insert!(%Post{blob: blob, 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)
# Binaries
assert [^blob] = TestRepo.all(from p in Post, where: p.blob == <<0, 1>>, select: p.blob)
assert [^blob] = TestRepo.all(from p in Post, where: p.blob == ^blob, select: p.blob)
# 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
@tag :bitstring_type
test "bitstring type" do
bitstring = <<2::3>>
TestRepo.insert!(%Bitstring{bs: bitstring, bs_with_size: <<5::10>>})
# Bitstrings
assert [^bitstring] = TestRepo.all(from p in Bitstring, where: p.bs == ^bitstring, select: p.bs)
assert [^bitstring] = TestRepo.all(from p in Bitstring, where: p.bs == <<2::3>>, select: p.bs)
assert [<<42::6>>] = TestRepo.all(from p in Bitstring, limit: 1, select: p.bs_with_default)
end
if Code.ensure_loaded?(Duration) do
@tag :duration_type
test "duration type" do
duration = %Duration{year: 1, month: 1, second: 1, microsecond: {100, 6}}
struct = %Ecto.Integration.Duration{
dur: duration,
dur_with_fields: duration,
dur_with_precision: duration,
dur_with_fields_and_precision: duration
}
TestRepo.insert!(struct)
persisted_duration =
from(d in Ecto.Integration.Duration, where: d.dur == ^duration)
|> TestRepo.one()
assert persisted_duration.dur == duration
# `:field` option set to MONTH so it ignores all units lower than `:month`
assert persisted_duration.dur_with_fields == %Duration{
year: 1,
month: 1,
microsecond: {0, 6}
}
assert persisted_duration.dur_with_precision == %Duration{
year: 1,
month: 1,
second: 1,
microsecond: {100, 4}
}
# `:field` option is set to HOUR TO SECOND so it ignores all units lower than `:second`
assert persisted_duration.dur_with_fields_and_precision == %Duration{
year: 1,
month: 1,
second: 1,
microsecond: {0, 1}
}
# `:default set in migration`
assert persisted_duration.dur_with_default == %Duration{month: 10, microsecond: {0, 6}}
end
end
@tag :select_not
test "primitive types boolean negate" do
TestRepo.insert!(%Post{public: true})
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)
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
# We don't specifically assert on the tuple content because
# some databases would return integer, others decimal.
# The important is that the type has been invoked for wrapping.
test "aggregate custom types" do
TestRepo.insert!(%Post{wrapped_visits: {:int, 10}})
query = from p in Post, select: sum(p.wrapped_visits)
assert [{:int, _}] = 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 text type when default" do
TestRepo.insert!(%Post{blob: nil})
blob = <<0, 1>>
query = from p in Post, select: coalesce(p.blob, ^blob)
assert [^blob] = TestRepo.all(query)
end
test "coalesce text type when value" do
blob = <<0, 2>>
default_blob = <<0, 1>>
TestRepo.insert!(%Post{blob: blob})
query = from p in Post, select: coalesce(p.blob, ^default_blob)
assert [^blob] = TestRepo.all(query)
end
test "tagged types" do
%{id: post_id} = TestRepo.insert!(%Post{visits: 12})
TestRepo.insert!(%Comment{text: "#{post_id}", post_id: post_id})
# 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", CustomPermalink))
# Custom types
uuid = Ecto.UUID.generate()
assert [^uuid] = TestRepo.all(from Post, select: type(^uuid, Ecto.UUID))
# Parameterized types
assert [:a] = TestRepo.all(from Post, select: type(^"a", ^@parameterized_type))
# 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))
# Comparison expression
assert [12] = TestRepo.all(from p in Post, select: type(coalesce(p.visits, 0), :integer))
assert [1.0] = TestRepo.all(from p in Post, select: type(coalesce(p.intensity, 1.0), :float))
# parent_as/1
child = from c in Comment, where: type(parent_as(:posts).id, :string) == c.text, select: c.post_id
query = from p in Post, as: :posts, where: p.id in subquery(child), select: p.id
assert [post_id] == TestRepo.all(query)
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
@tag :like_match_blob
test "text type as blob" do
assert %Post{} = post = TestRepo.insert!(%Post{blob: <<0, 1, 2>>})
id = post.id
assert post.blob == <<0, 1, 2>>
assert [^id] = TestRepo.all(from p in Post, where: like(p.blob, ^<<0, 1, 2>>), select: p.id)
end
@tag :like_match_blob
@tag :text_type_as_string
test "text type as string" do
assert %Post{} = post = TestRepo.insert!(%Post{blob: "hello"})
id = post.id
assert post.blob == "hello"
assert [^id] = TestRepo.all(from p in Post, where: like(p.blob, ^"hello"), select: p.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
@tag :json_extract_path
test "json_extract_path with primitive values" do
order = %Order{metadata:
%{
:id => 123,
:time => ~T[09:00:00],
"code" => "good",
"'single quoted'" => "bar",
"\"double quoted\"" => "baz",
"enabled" => true,
"extra" => [%{"enabled" => false}]
}
}
order = TestRepo.insert!(order)
assert TestRepo.one(from o in Order, select: json_extract_path(o.metadata, ^["id"])) == 123
assert TestRepo.one(from o in Order, select: o.metadata["bad"]) == nil
assert TestRepo.one(from o in Order, select: o.metadata["bad"]["bad"]) == nil
field = "id"
assert TestRepo.one(from o in Order, select: o.metadata[^field]) == 123
assert TestRepo.one(from o in Order, select: o.metadata["time"]) == "09:00:00"
assert TestRepo.one(from o in Order, select: o.metadata["'single quoted'"]) == "bar"
assert TestRepo.one(from o in Order, select: o.metadata["';"]) == nil
assert TestRepo.one(from o in Order, select: o.metadata["\"double quoted\""]) == "baz"
assert TestRepo.one(from o in Order, select: o.metadata["enabled"]) == true
assert TestRepo.one(from o in Order, select: o.metadata["extra"][0]["enabled"]) == false
# where
assert TestRepo.one(from o in Order, where: o.metadata["id"] == 123, select: o.id) == order.id
assert TestRepo.one(from o in Order, where: o.metadata["id"] == 456, select: o.id) == nil
assert TestRepo.one(from o in Order, where: o.metadata["code"] == "good", select: o.id) == order.id
assert TestRepo.one(from o in Order, where: o.metadata["code"] == "bad", select: o.id) == nil
assert TestRepo.one(from o in Order, where: o.metadata["enabled"] == true, select: o.id) == order.id
assert TestRepo.one(from o in Order, where: o.metadata["extra"][0]["enabled"] == false, select: o.id) == order.id
end
@tag :map_type
@tag :json_extract_path
test "json_extract_path with arrays and objects" do
order = %Order{metadata: %{tags: [%{name: "red"}, %{name: "green"}]}}
order = TestRepo.insert!(order)
assert TestRepo.one(from o in Order, select: o.metadata["tags"][0]["name"]) == "red"
assert TestRepo.one(from o in Order, select: o.metadata["tags"][99]["name"]) == nil
index = 1
assert TestRepo.one(from o in Order, select: o.metadata["tags"][^index]["name"]) == "green"
# where
assert TestRepo.one(from o in Order, where: o.metadata["tags"][0]["name"] == "red", select: o.id) == order.id
assert TestRepo.one(from o in Order, where: o.metadata["tags"][0]["name"] == "blue", select: o.id) == nil
assert TestRepo.one(from o in Order, where: o.metadata["tags"][99]["name"] == "red", select: o.id) == nil
end
@tag :map_type
@tag :json_extract_path
test "json_extract_path with embeds" do
order = %Order{items: [%{valid_at: ~D[2020-01-01]}]}
TestRepo.insert!(order)
assert TestRepo.one(from o in Order, select: o.items[0]["valid_at"]) == "2020-01-01"
end
@tag :map_type
@tag :json_extract_path
test "json_extract_path with custom field source" do
order = TestRepo.insert!(%Order{metadata: %{tags: [%{name: "red"}, %{name: "green"}]}})
assert TestRepo.one(from o in Order, where: o.metadata["tags"][0]["name"] == "red", select: o.id) == order.id
end
@tag :map_type
@tag :json_extract_path_with_field
@tag :json_extract_path
test "json_extract_path with fields in path" do
order = %Order{id: 1, label: "tags", metadata: %{tags: [%{name: "red"}, %{name: "green"}]}}
order = TestRepo.insert!(order)
assert TestRepo.one(from o in Order, select: o.metadata[o.label][1]["name"]) == "green"
assert TestRepo.one(from o in Order, select: o.metadata["tags"][o.id]["name"]) == "green"
assert TestRepo.one(from o in Order, select: o.metadata["tags"][field(o, ^:id)]["name"]) ==
"green"
squery = from o in Order, select: o.metadata["tags"][parent_as(:o).id]["name"]
assert TestRepo.one(from o in Order, as: :o, where: subquery(squery) == ^"green")
squery = from o in Order, select: o.metadata["tags"][field(parent_as(:o), ^:id)]["name"]
assert TestRepo.one(from o in Order, as: :o, where: subquery(squery) == ^"green")
assert TestRepo.one(
from(o in Order,
where: o.metadata["tags"][o.id]["name"] == "green",
select: o.id)
) == order.id
assert TestRepo.one(
from(o in Order,
where: o.metadata["tags"][field(o, ^:id)]["name"] == "green",
select: o.id)
) == order.id
squery = from o in Order, where: o.metadata["tags"][parent_as(:o).id]["name"] == "green"
assert TestRepo.one(from o in Order, as: :o, where: exists(subquery(squery)))
end
@tag :map_type
@tag :map_type_schemaless
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 dbitem.primary_color.name == "red"
assert Enum.map(dbitem.secondary_colors, & &1.name) == ["blue"]
assert dbitem.id
assert dbitem.primary_color.id
[dbitem] = TestRepo.all(from o in Order, select: o.item)
assert dbitem.primary_color.name == "red"
assert Enum.map(dbitem.secondary_colors, & &1.name) == ["blue"]
assert dbitem.id
assert dbitem.primary_color.id
end
@tag :decimal_type
test "decimal type" do
decimal = Decimal.new("1.0")
TestRepo.insert!(%Post{cost: decimal})
[cost] = TestRepo.all(from p in Post, where: p.cost == ^decimal, select: p.cost)
assert Decimal.equal?(decimal, cost)
[cost] = TestRepo.all(from p in Post, where: p.cost == ^1.0, select: p.cost)
assert Decimal.equal?(decimal, cost)
[cost] = TestRepo.all(from p in Post, where: p.cost == ^1, select: p.cost)
assert Decimal.equal?(decimal, cost)
[cost] = TestRepo.all(from p in Post, where: p.cost == 1.0, select: p.cost)
assert Decimal.equal?(decimal, cost)
[cost] = TestRepo.all(from p in Post, where: p.cost == 1, select: p.cost)
assert Decimal.equal?(decimal, cost)
[cost] = TestRepo.all(from p in Post, select: p.cost * 2)
assert Decimal.equal?(Decimal.new("2.0"), cost)
[cost] = TestRepo.all(from p in Post, select: p.cost - p.cost)
assert Decimal.equal?(Decimal.new("0.0"), cost)
end
@tag :decimal_type
@tag :decimal_precision
test "decimal 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))
[cost] = TestRepo.all(from p in Post, select: type(sum(p.cost), :decimal))
assert Decimal.equal?(decimal, cost)
end
@tag :decimal_type
test "on coalesce with mixed types" do
decimal = Decimal.new("1.0")
TestRepo.insert!(%Post{cost: decimal})
[cost] = TestRepo.all(from p in Post, select: coalesce(p.cost, 0))
assert Decimal.equal?(decimal, cost)
end
@tag :union_with_literals
test "unions with literals" do
TestRepo.insert!(%Post{})
TestRepo.insert!(%Post{})
query1 = from(p in Post, select: %{n: 1})
query2 = from(p in Post, select: %{n: 2})
assert TestRepo.all(union_all(query1, ^query2)) ==
[%{n: 1}, %{n: 1}, %{n: 2}, %{n: 2}]
query1 = from(p in Post, select: %{n: 1.0})
query2 = from(p in Post, select: %{n: 2.0})
assert TestRepo.all(union_all(query1, ^query2)) ==
[%{n: 1.0}, %{n: 1.0}, %{n: 2.0}, %{n: 2.0}]
query1 = from(p in Post, select: %{n: "foo"})
query2 = from(p in Post, select: %{n: "bar"})
assert TestRepo.all(union_all(query1, ^query2)) ==
[%{n: "foo"}, %{n: "foo"}, %{n: "bar"}, %{n: "bar"}]
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