diff --git a/CHANGELOG.md b/CHANGELOG.md index 5a1dccb..d674d27 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -1,5 +1,8 @@ # Changelog +## Unreleased +- Adapt to `Ch` type fixes https://github.com/plausible/ecto_ch/pull/270 + ## 0.8.6 (2026-02-11) - Fix invalid `Array(Nothing)` param type for params like for `[[]]` https://github.com/plausible/ecto_ch/pull/264 diff --git a/lib/ecto/adapters/clickhouse/connection.ex b/lib/ecto/adapters/clickhouse/connection.ex index 1350076..594a1dc 100644 --- a/lib/ecto/adapters/clickhouse/connection.ex +++ b/lib/ecto/adapters/clickhouse/connection.ex @@ -868,8 +868,8 @@ defmodule Ecto.Adapters.ClickHouse.Connection do expr(value, sources, params, query) end - defp expr(%Tagged{value: value, type: type}, sources, params, query) do - ["CAST(", expr(value, sources, params, query), " AS ", ecto_to_db(type, query), ?)] + defp expr(%Tagged{tag: tag, type: type, value: value}, sources, params, query) do + ["CAST(", expr(value, sources, params, query), " AS ", ecto_to_db(tag, type, query), ?)] end defp expr(nil, _sources, _params, _query), do: "NULL" @@ -1093,6 +1093,9 @@ defmodule Ecto.Adapters.ClickHouse.Connection do [expr(count, sources, params, query), " * ", interval(1, interval, sources, params, query)] end + defp ecto_to_db({:parameterized, {Ch, type}}, _type, _query), do: Ch.Types.encode(type) + defp ecto_to_db(_tag, type, query), do: ecto_to_db(type, query) + # when ecto migrator queries for versions in schema_versions it uses type(version, :integer) # so we need :integer to be the same as :bigint which is used for schema_versions table definition # this is why :integer is Int64 and not Int32 diff --git a/lib/ecto/adapters/clickhouse/schema.ex b/lib/ecto/adapters/clickhouse/schema.ex index af6217a..2eb8783 100644 --- a/lib/ecto/adapters/clickhouse/schema.ex +++ b/lib/ecto/adapters/clickhouse/schema.ex @@ -230,7 +230,7 @@ defmodule Ecto.Adapters.ClickHouse.Schema do schema.__schema__(:type, field) || find_field_source_type(schema, field) || raise "missing type for field " <> inspect(field) - type |> Ecto.Type.type() |> remap_type(type, schema, field) + remap_type(type, schema, field) end) end @@ -258,15 +258,22 @@ defmodule Ecto.Adapters.ClickHouse.Schema do @doc false def remap_type(type, schema, field) do - remap_type(Ecto.Type.type(type), type, schema, field) + remap_type(type, type, schema, field) end defp remap_type({:parameterized, {Ch, t}}, _original, _schema, _field), do: t + defp remap_type({:parameterized, {module, params}}, original, schema, field) do + type = module.type(params) + remap_type(type, original, schema, field) + end + defp remap_type(t, _original, _schema, _field) when t in [:string, :date, :uuid, :boolean], do: t + defp remap_type(Ecto.UUID, _original, _schema, _field), do: :uuid + defp remap_type(dt, _original, _schema, _field) when dt in [:naive_datetime, :utc_datetime], do: :datetime @@ -296,23 +303,27 @@ defmodule Ecto.Adapters.ClickHouse.Schema do "`#{inspect(time)}` type is not supported as there is no `Time` type in ClickHouse." end - defp remap_type(other, original, schema, field) do - ch_type = ch_type_hint(original) + defp remap_type(type, original, schema, field) do + case Ecto.Type.type(type) do + ^type -> + raise ArgumentError, """ + #{inspect(type)} type is ambiguous, please use `Ch` Ecto type instead. - raise ArgumentError, """ - #{inspect(other)} type is ambiguous, please use `Ch` Ecto type instead. + Example: - Example: + schema "#{schema.__schema__(:source)}" do + field :#{field}, Ch, type: "#{ch_type_hint(original)}" + end - schema "#{schema.__schema__(:source)}" do - field :#{field}, Ch, type: "#{ch_type}" - end + You can also try using `ecto.ch.schema` to generate a schema: - You can also try using `ecto.ch.schema` to generate a schema: + mix ecto.ch.schema .#{schema.__schema__(:source)} - mix ecto.ch.schema .#{schema.__schema__(:source)} + """ - """ + type -> + remap_type(type, original, schema, field) + end end # https://hexdocs.pm/ecto/Ecto.Schema.html#module-primitive-types diff --git a/mix.exs b/mix.exs index d37ad7d..9624512 100644 --- a/mix.exs +++ b/mix.exs @@ -53,7 +53,7 @@ defmodule EctoCh.MixProject do # Run "mix help deps" to learn about dependencies. defp deps do [ - {:ch, "~> 0.5.0 or ~> 0.6.0 or ~> 0.7.0"}, + {:ch, "~> 0.8.0"}, {:ecto_sql, "~> 3.13.0"}, {:benchee, "~> 1.1", only: :bench}, {:dialyxir, "~> 1.2", only: [:dev, :test], runtime: false}, diff --git a/mix.lock b/mix.lock index 73ccf63..22443c9 100644 --- a/mix.lock +++ b/mix.lock @@ -1,6 +1,6 @@ %{ "benchee": {:hex, :benchee, "1.5.0", "4d812c31d54b0ec0167e91278e7de3f596324a78a096fd3d0bea68bb0c513b10", [:mix], [{:deep_merge, "~> 1.0", [hex: :deep_merge, repo: "hexpm", optional: false]}, {:statistex, "~> 1.1", [hex: :statistex, repo: "hexpm", optional: false]}, {:table, "~> 0.1.0", [hex: :table, repo: "hexpm", optional: true]}], "hexpm", "5b075393aea81b8ae74eadd1c28b1d87e8a63696c649d8293db7c4df3eb67535"}, - "ch": {:hex, :ch, "0.7.1", "116c08094b30d095c3bd6a8fe4ebe19fdaaf3dce84e2413cfdd6af157baf6303", [:mix], [{:db_connection, "~> 2.9.0", [hex: :db_connection, repo: "hexpm", optional: false]}, {:decimal, "~> 2.0", [hex: :decimal, repo: "hexpm", optional: false]}, {:ecto, "~> 3.13.0", [hex: :ecto, repo: "hexpm", optional: true]}, {:jason, "~> 1.0", [hex: :jason, repo: "hexpm", optional: false]}, {:mint, "~> 1.0", [hex: :mint, repo: "hexpm", optional: false]}], "hexpm", "3c1c900291ff9c4c077cd1dc0c265051a3f1d26320d58b37ed9e91b33d41a868"}, + "ch": {:hex, :ch, "0.8.0", "d2d00ce85bdebe9ae2df21b758880c081e0d983218c43b1aed829ca9269b65d5", [:mix], [{:db_connection, "~> 2.9.0", [hex: :db_connection, repo: "hexpm", optional: false]}, {:decimal, "~> 2.0", [hex: :decimal, repo: "hexpm", optional: false]}, {:ecto, "~> 3.13.0", [hex: :ecto, repo: "hexpm", optional: true]}, {:jason, "~> 1.0", [hex: :jason, repo: "hexpm", optional: false]}, {:mint, "~> 1.0", [hex: :mint, repo: "hexpm", optional: false]}], "hexpm", "6e3f3e5c36fa6a4388bd5df6f5fee4c20fac638854d305bc54f0be8c3fa7b518"}, "db_connection": {:hex, :db_connection, "2.9.0", "a6a97c5c958a2d7091a58a9be40caf41ab496b0701d21e1d1abff3fa27a7f371", [:mix], [{:telemetry, "~> 0.4 or ~> 1.0", [hex: :telemetry, repo: "hexpm", optional: false]}], "hexpm", "17d502eacaf61829db98facf6f20808ed33da6ccf495354a41e64fe42f9c509c"}, "decimal": {:hex, :decimal, "2.3.0", "3ad6255aa77b4a3c4f818171b12d237500e63525c2fd056699967a3e7ea20f62", [:mix], [], "hexpm", "a4d66355cb29cb47c3cf30e71329e58361cfcb37c34235ef3bf1d7bf3773aeac"}, "deep_merge": {:hex, :deep_merge, "1.0.0", "b4aa1a0d1acac393bdf38b2291af38cb1d4a52806cf7a4906f718e1feb5ee961", [:mix], [], "hexpm", "ce708e5f094b9cd4e8f2be4f00d2f4250c4095be93f8cd6d018c753894885430"}, diff --git a/test/ch/type_test.exs b/test/ch/type_test.exs index c5e8067..6f7ffc5 100644 --- a/test/ch/type_test.exs +++ b/test/ch/type_test.exs @@ -615,14 +615,14 @@ defmodule Ch.TypeTest do assert Datetimes64 |> order_by([d], d.ch_3) |> all() |> unstruct() == [ %{ - ch_3: ~N[1970-01-01 00:00:00.000000], + ch_3: ~N[1970-01-01 00:00:00.000], ch_6: ~N[1970-01-01 00:00:00.000000], ch_5_utc: ~U[1970-01-01 00:00:00.00000Z], naive_datetime_usec: ~N[1970-01-01 00:00:00.000000], utc_datetime_usec: ~U[1970-01-01 00:00:00.000000Z] }, %{ - ch_3: ~N[2023-04-24 09:02:00.975000], + ch_3: ~N[2023-04-24 09:02:00.975], ch_6: naive_now, ch_5_utc: ~U[2023-04-24 09:02:00.97531Z], naive_datetime_usec: naive_now,