diff --git a/packages/elixir-client/lib/electric/client/ecto_adapter/postgres.ex b/packages/elixir-client/lib/electric/client/ecto_adapter/postgres.ex index 300489557c..c050705b58 100644 --- a/packages/elixir-client/lib/electric/client/ecto_adapter/postgres.ex +++ b/packages/elixir-client/lib/electric/client/ecto_adapter/postgres.ex @@ -537,6 +537,24 @@ if Code.ensure_loaded?(Ecto) do end) end + defp dump_binding(Ecto.ULID, {value, cast}) when is_list(value) do + value + |> Enum.zip(cast) + |> Enum.map(&dump_binding(Ecto.ULID, &1)) + |> Enum.unzip() + end + + defp dump_binding(Ecto.ULID, {value, _cast}) do + case Ecto.Type.dump(Ecto.ULID, value) do + {:ok, dumped} -> + {Ecto.UUID.cast!(dumped), dumped} + + :error -> + raise ArgumentError, + "cannot dump value #{inspect(value)} for type #{inspect(Ecto.ULID)}" + end + end + defp dump_binding({:parameterized, _} = type, {value, cast}) when is_list(value) do value |> Enum.zip(cast) diff --git a/packages/elixir-client/test/electric/client/ecto_adapter/postgres_test.exs b/packages/elixir-client/test/electric/client/ecto_adapter/postgres_test.exs index e0fd26dfbc..c5813fcac5 100644 --- a/packages/elixir-client/test/electric/client/ecto_adapter/postgres_test.exs +++ b/packages/elixir-client/test/electric/client/ecto_adapter/postgres_test.exs @@ -15,6 +15,7 @@ defmodule Electric.Client.EctoAdapter.PostgresTest do field(:ff, :float) field(:ss, :string) field(:uu, :binary_id) + field(:eu, Ecto.ULID) field(:nd, :naive_datetime) field(:ud, :utc_datetime) field(:dd, :date) @@ -40,6 +41,7 @@ defmodule Electric.Client.EctoAdapter.PostgresTest do ud = ~U[2024-10-23 14:36:39Z] dd = ~D[2024-10-23] mm = Decimal.new("199.99") + eu = "01KNN1EKXZ6QX7RBY56M1GYDYC" ul = "ul_coa2saf4czblth3g5jhleb4574" assert_where(where(TestTable, ii: ^ii), ~s[("ii" = 1234)]) @@ -47,6 +49,7 @@ defmodule Electric.Client.EctoAdapter.PostgresTest do assert_where(where(TestTable, ss: ^ss1), ~s[("ss" = 'my string')]) assert_where(where(TestTable, ss: ^ss2), ~s[("ss" = 'it''s mine')]) assert_where(where(TestTable, uu: ^uu), ~s[("uu" = '247a6f62-9f05-4ac6-8314-89e77177d1e3')]) + assert_where(where(TestTable, eu: ^eu), ~s[("eu" = '019d6a17-4fbf-35fa-7c2f-c535030f37cc')]) assert_where(where(TestTable, nd: ^nd), ~s[("nd" = '2024-10-23T14:36:39'::timestamp)]) assert_where(where(TestTable, ud: ^ud), ~s[("ud" = '2024-10-23T14:36:39Z'::timestamptz)]) assert_where(where(TestTable, dd: ^dd), ~s[("dd" = '2024-10-23'::date)]) @@ -66,6 +69,7 @@ defmodule Electric.Client.EctoAdapter.PostgresTest do values_ff = [3.14, 2.71, 6.626] values_mm = [Decimal.new("3.14"), Decimal.new("2.71"), Decimal.new("6.626")] values_mm2 = [Decimal.new("9.99")] + values_eu = ["01KNN1EKXZ6QX7RBY56M1GYDYC", "01JXA5469C68QNGM0N5YA0XNSN"] ff = 3.14 assert_where(from(t in TestTable) |> where([t], t.ii in [1, 2, 3]), ~s|("ii" IN (1,2,3))|) @@ -87,6 +91,11 @@ defmodule Electric.Client.EctoAdapter.PostgresTest do ~s|("ff" IN (3.14::float,2.71::float,6.626::float))| ) + assert_where( + from(t in TestTable) |> where([t], t.eu in ^values_eu), + ~s|("eu" IN ('019d6a17-4fbf-35fa-7c2f-c535030f37cc','01975452-192c-322f-5850-152f940ed735'))| + ) + assert_where( from(t in TestTable) |> where([t], t.mm in ^values_mm), ~s|("mm" IN (3140000,2710000,6626000))| diff --git a/packages/elixir-client/test/electric/client/ecto_adapter_test.exs b/packages/elixir-client/test/electric/client/ecto_adapter_test.exs index 7bf9ef9210..7d4bc21871 100644 --- a/packages/elixir-client/test/electric/client/ecto_adapter_test.exs +++ b/packages/elixir-client/test/electric/client/ecto_adapter_test.exs @@ -200,6 +200,23 @@ defmodule Electric.Client.EctoAdapterTest do } = EctoAdapter.shape_from_query!(query) end + test "supports where clause with Ecto.ULID bound params" do + ulid = "01KNN1EKXZ6QX7RBY56M1GYDYC" + column_names = column_names(ULIDTable) + + query = + from(t in ULIDTable, + where: t.id == ^ulid + ) + + assert %Electric.Client.ShapeDefinition{ + table: "ulid_table", + where: ~s[("id" = '019d6a17-4fbf-35fa-7c2f-c535030f37cc')], + columns: ^column_names, + parser: {EctoAdapter, ULIDTable} + } = EctoAdapter.shape_from_query!(query) + end + test "with where clause" do price1 = Decimal.new("2.0") net_price1 = Decimal.new("2.5")