diff --git a/lib/ecto/adapters/sqlite3/connection.ex b/lib/ecto/adapters/sqlite3/connection.ex index 0599544..b689e9a 100644 --- a/lib/ecto/adapters/sqlite3/connection.ex +++ b/lib/ecto/adapters/sqlite3/connection.ex @@ -1431,6 +1431,26 @@ defmodule Ecto.Adapters.SQLite3.Connection do [?x, ?', hex, ?'] end + def expr(%Ecto.Query.Tagged{value: expr, type: :binary_id}, sources, query) do + case Application.get_env(:ecto_sqlite3, :binary_id_type, :string) do + :string -> + ["CAST(", expr(expr, sources, query), " AS ", column_type(:string, query), ?)] + + :binary -> + [expr(expr, sources, query)] + end + end + + def expr(%Ecto.Query.Tagged{value: expr, type: :uuid}, sources, query) do + case Application.get_env(:ecto_sqlite3, :uuid_type, :string) do + :string -> + ["CAST(", expr(expr, sources, query), " AS ", column_type(:string, query), ?)] + + :binary -> + [expr(expr, sources, query)] + end + end + def expr(%Ecto.Query.Tagged{value: other, type: type}, sources, query) when type in [:decimal, :float] do ["CAST(", expr(other, sources, query), " AS REAL)"] diff --git a/test/ecto/integration/uuid_test.exs b/test/ecto/integration/uuid_test.exs index 5fc5062..c024b2b 100644 --- a/test/ecto/integration/uuid_test.exs +++ b/test/ecto/integration/uuid_test.exs @@ -4,6 +4,8 @@ defmodule Ecto.Integration.UUIDTest do alias Ecto.Integration.TestRepo alias EctoSQLite3.Schemas.Product + import Ecto.Query, only: [from: 2] + setup do Application.put_env(:ecto_sqlite3, :uuid_type, :string) on_exit(fn -> Application.put_env(:ecto_sqlite3, :uuid_type, :string) end) @@ -34,4 +36,40 @@ defmodule Ecto.Integration.UUIDTest do assert found assert found.external_id == external_id end + + test "handles uuid casting with binary format" do + Application.put_env(:ecto_sqlite3, :uuid_type, :binary) + Application.put_env(:ecto_sqlite3, :binary_id_type, :binary) + + external_id = Ecto.UUID.generate() + TestRepo.insert!(%Product{external_id: external_id, bid: external_id}) + + product = + TestRepo.one(from(p in Product, where: p.external_id == type(p.bid, Ecto.UUID))) + + assert %{external_id: ^external_id} = product + + product = + TestRepo.one( + from(p in Product, where: p.external_id == type(^external_id, Ecto.UUID)) + ) + + assert %{external_id: ^external_id} = product + end + + test "handles binary_id casting with binary format" do + Application.put_env(:ecto_sqlite3, :uuid_type, :binary) + Application.put_env(:ecto_sqlite3, :binary_id_type, :binary) + + bid = Ecto.UUID.generate() + TestRepo.insert!(%Product{bid: bid, external_id: bid}) + + product = + TestRepo.one(from(p in Product, where: p.bid == type(p.external_id, :binary_id))) + + assert %{bid: ^bid} = product + + product = TestRepo.one(from(p in Product, where: p.bid == type(^bid, :binary_id))) + assert %{bid: ^bid} = product + end end diff --git a/test/support/migration.ex b/test/support/migration.ex index 1994133..94b07f7 100644 --- a/test/support/migration.ex +++ b/test/support/migration.ex @@ -28,6 +28,7 @@ defmodule EctoSQLite3.Integration.Migration do add(:name, :string) add(:description, :text) add(:external_id, :uuid) + add(:bid, :binary_id) add(:tags, {:array, :string}) add(:approved_at, :naive_datetime) add(:price, :decimal) diff --git a/test/support/schemas/product.ex b/test/support/schemas/product.ex index 90d72d7..582eb4e 100644 --- a/test/support/schemas/product.ex +++ b/test/support/schemas/product.ex @@ -11,6 +11,7 @@ defmodule EctoSQLite3.Schemas.Product do field(:name, :string) field(:description, :string) field(:external_id, Ecto.UUID) + field(:bid, :binary_id) field(:tags, {:array, :string}, default: []) field(:approved_at, :naive_datetime) field(:price, :decimal)