From 226c5a2e5ebed624a49196898aea408b0a7b92b0 Mon Sep 17 00:00:00 2001 From: Greg Rychlewski Date: Tue, 29 Aug 2023 04:12:03 -0400 Subject: [PATCH 1/3] fix binary uuid casting --- lib/ecto/adapters/sqlite3/connection.ex | 11 +++++++++++ test/ecto/integration/uuid_test.exs | 20 ++++++++++++++++++++ test/support/migration.ex | 1 + test/support/schemas/product.ex | 1 + 4 files changed, 33 insertions(+) diff --git a/lib/ecto/adapters/sqlite3/connection.ex b/lib/ecto/adapters/sqlite3/connection.ex index 0599544..3cb6f60 100644 --- a/lib/ecto/adapters/sqlite3/connection.ex +++ b/lib/ecto/adapters/sqlite3/connection.ex @@ -1431,6 +1431,17 @@ defmodule Ecto.Adapters.SQLite3.Connection do [?x, ?', hex, ?'] end + def expr(%Ecto.Query.Tagged{value: {:^, _, [_]} = expr, type: type}, sources, query) + when type in [:binary_id, :uuid] do + case Application.get_env(:ecto_sqlite3, :binary_id_type, :string) do + :string -> + ["CAST(", expr(expr, sources, query), " AS ", column_type(type, 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..9a5e9d7 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,22 @@ 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) + + external_id = Ecto.UUID.generate() + TestRepo.insert!(%Product{external_id: external_id}) + 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, :binary_id_type, :binary) + + bid = Ecto.UUID.generate() + TestRepo.insert!(%Product{bid: bid}) + 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) From 936917fd074b0e7c6343dffb194c1cc560284d42 Mon Sep 17 00:00:00 2001 From: Greg Rychlewski Date: Tue, 29 Aug 2023 04:41:03 -0400 Subject: [PATCH 2/3] cleanup --- lib/ecto/adapters/sqlite3/connection.ex | 15 ++++++++++++--- test/ecto/integration/uuid_test.exs | 16 +++++++++++++--- 2 files changed, 25 insertions(+), 6 deletions(-) diff --git a/lib/ecto/adapters/sqlite3/connection.ex b/lib/ecto/adapters/sqlite3/connection.ex index 3cb6f60..b689e9a 100644 --- a/lib/ecto/adapters/sqlite3/connection.ex +++ b/lib/ecto/adapters/sqlite3/connection.ex @@ -1431,11 +1431,20 @@ defmodule Ecto.Adapters.SQLite3.Connection do [?x, ?', hex, ?'] end - def expr(%Ecto.Query.Tagged{value: {:^, _, [_]} = expr, type: type}, sources, query) - when type in [:binary_id, :uuid] do + 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(type, query), ?)] + ["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)] diff --git a/test/ecto/integration/uuid_test.exs b/test/ecto/integration/uuid_test.exs index 9a5e9d7..a1381af 100644 --- a/test/ecto/integration/uuid_test.exs +++ b/test/ecto/integration/uuid_test.exs @@ -39,18 +39,28 @@ defmodule Ecto.Integration.UUIDTest do 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}) - product = TestRepo.one(from p in Product, where: p.external_id == type(^external_id, Ecto.UUID)) + 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}) + 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 From 8066f0068504290c900369678263ac657dff3eb3 Mon Sep 17 00:00:00 2001 From: Greg Rychlewski Date: Tue, 29 Aug 2023 04:44:48 -0400 Subject: [PATCH 3/3] format --- test/ecto/integration/uuid_test.exs | 16 ++++++++++++---- 1 file changed, 12 insertions(+), 4 deletions(-) diff --git a/test/ecto/integration/uuid_test.exs b/test/ecto/integration/uuid_test.exs index a1381af..c024b2b 100644 --- a/test/ecto/integration/uuid_test.exs +++ b/test/ecto/integration/uuid_test.exs @@ -44,10 +44,16 @@ defmodule Ecto.Integration.UUIDTest do 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))) + 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))) + product = + TestRepo.one( + from(p in Product, where: p.external_id == type(^external_id, Ecto.UUID)) + ) + assert %{external_id: ^external_id} = product end @@ -58,10 +64,12 @@ defmodule Ecto.Integration.UUIDTest do 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))) + 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)) + product = TestRepo.one(from(p in Product, where: p.bid == type(^bid, :binary_id))) assert %{bid: ^bid} = product end end