Ecto. Adapters. ClickHouse
(clickhouse_adapter_ecto v0.1.0)
Copy Markdown
A minimal Ecto.Adapters.SQL-based adapter for ClickHouse, backed by
ChDriver (a native-protocol DBConnection driver).
This module wires Ecto.Adapters.SQL (which provides Ecto.Adapter,
Ecto.Adapter.Queryable, Ecto.Adapter.Schema, and
Ecto.Adapter.Transaction for free, delegating SQL generation to
Ecto.Adapters.ClickHouse.Connection) up to ChDriver.
Scope of this phase
This adapter currently targets basic SELECT/INSERT round-trips through
a real Ecto.Repo -- see Ecto.Adapters.ClickHouse.Connection's
moduledoc for exactly which query shapes are supported.
Storage (mix ecto.create / mix ecto.drop)
Ecto.Adapter.Storage is implemented: storage_up/1 and storage_down/1
issue a plain CREATE DATABASE/DROP DATABASE over a short-lived
maintenance connection (see run_storage_query/2), and storage_status/1
checks system.databases. There is no ClickHouse equivalent of "does this
role have CREATEDB" to worry about, and no encoding/collation options are
supported (ClickHouse databases don't have either).
Migrations (mix ecto.migrate)
Ecto.Adapter.Migration is implemented well enough for straightforward
migrations to run: supports_ddl_transaction?/0 returns false
(ClickHouse has no transactional DDL), and lock_for_migrations/3 is a
deliberate no-op that just calls the given function directly -- see
its doc below for why. Ecto.Adapters.ClickHouse.Connection's execute_ddl/1
turns create table(...)/drop table(...) into CREATE TABLE/DROP TABLE (see that module's ## DDL section for exactly what's supported
and how the ENGINE/ORDER BY clause is chosen), which is what lets
Ecto.Migrator create and populate schema_migrations automatically.
mix ecto.rollback / Ecto.Migrator.run(repo, path, :down, ...) is
supported for the common case: a change/0 migration doing
create table(...) auto-reverses to drop table(...) cleanly (both are
synchronous, metadata-only DDL), and the schema_migrations bookkeeping
row removal that Ecto.Migration.SchemaMigration's down/4 issues via
Repo.delete_all/2 is handled by
Ecto.Adapters.ClickHouse.Connection's delete_all/1, which translates it
into an ALTER TABLE ... DELETE WHERE ... SETTINGS mutations_sync = 1
mutation that blocks until the row is actually gone, so the migrator's
post-delete state is correct with no polling. See
Connection's moduledoc for exactly how narrowly that delete_all support
is scoped (single table, no joins/LIMIT/OFFSET).
Not supported: :alter (existing migrations that add/remove/modify
columns), indexes, and constraints -- see
Ecto.Adapters.ClickHouse.Connection's ## DDL moduledoc section for the
full breakdown of which DDL operations are safe to auto-reverse via
change/0 (create/drop table; add/remove column, once :alter support
lands) versus which are genuinely unsafe and must be written as explicit
up/0 + down/0 (column type changes via MODIFY COLUMN, ORDER BY/
partition key changes, and any UPDATE/DELETE-shaped data mutation).
execute_ddl/1 raises a specific, actionable error if asked to
auto-generate DDL for an unsafe :modify column-type change.