From 48b0dc5401c186a22b0096116fb815c126f86a67 Mon Sep 17 00:00:00 2001 From: ruslandoga Date: Sun, 3 May 2026 00:04:12 +0300 Subject: [PATCH 1/4] fix Ch types --- lib/ecto/adapters/clickhouse/connection.ex | 7 ++-- lib/ecto/adapters/clickhouse/schema.ex | 37 ++++++++++++++-------- 2 files changed, 29 insertions(+), 15 deletions(-) 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 From 26de16d8905ca5b676f5b3827ecec8b0da0f212b Mon Sep 17 00:00:00 2001 From: ruslandoga Date: Sun, 3 May 2026 00:09:35 +0300 Subject: [PATCH 2/4] changelog --- CHANGELOG.md | 3 +++ mix.exs | 4 ++-- 2 files changed, 5 insertions(+), 2 deletions(-) diff --git a/CHANGELOG.md b/CHANGELOG.md index 5a1dccb..df13acd 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -1,5 +1,8 @@ # Changelog +## 0.9.0 (2026-05-03) +- 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/mix.exs b/mix.exs index d37ad7d..ab93c33 100644 --- a/mix.exs +++ b/mix.exs @@ -2,7 +2,7 @@ defmodule EctoCh.MixProject do use Mix.Project @source_url "https://github.com/plausible/ecto_ch" - @version "0.8.6" + @version "0.9.0" def project do [ @@ -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}, From 963dc9b01b344f2e74dad6b84cdd3bd594894404 Mon Sep 17 00:00:00 2001 From: ruslandoga Date: Sun, 3 May 2026 00:52:20 +0300 Subject: [PATCH 3/4] eh --- CHANGELOG.md | 2 +- mix.exs | 2 +- mix.lock | 2 +- 3 files changed, 3 insertions(+), 3 deletions(-) diff --git a/CHANGELOG.md b/CHANGELOG.md index df13acd..d674d27 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -1,6 +1,6 @@ # Changelog -## 0.9.0 (2026-05-03) +## Unreleased - Adapt to `Ch` type fixes https://github.com/plausible/ecto_ch/pull/270 ## 0.8.6 (2026-02-11) diff --git a/mix.exs b/mix.exs index ab93c33..9624512 100644 --- a/mix.exs +++ b/mix.exs @@ -2,7 +2,7 @@ defmodule EctoCh.MixProject do use Mix.Project @source_url "https://github.com/plausible/ecto_ch" - @version "0.9.0" + @version "0.8.6" def project do [ 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"}, From 376e3ad9b4282a886e7cfc915a54fb26e8227b57 Mon Sep 17 00:00:00 2001 From: ruslandoga Date: Sun, 3 May 2026 00:55:29 +0300 Subject: [PATCH 4/4] adapt to ch truncations --- test/ch/type_test.exs | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) 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,