# `AshClickhouse.Migration`
[🔗](https://github.com/ohhi-vn/ash_clickhouse/blob/main/lib/ash_clickhouse/migration.ex#L1)

Generates ClickHouse `CREATE TABLE` statements from Ash resources.

ClickHouse tables require an engine and an `ORDER BY` key. This module maps
Ash primary keys and attributes to ClickHouse column definitions and produces
a `CREATE TABLE IF NOT EXISTS` statement using the engine configured in the
resource's `clickhouse` DSL block.

# `alter_indexes_cql`

```elixir
@spec alter_indexes_cql(module(), module()) :: {[String.t()], [String.t()]}
```

Generates `ALTER TABLE ... ADD INDEX IF NOT EXISTS` statements for indexes
configured on the resource but not yet present in ClickHouse, and detects
configured indexes whose *definition* differs from what's actually stored.

Returns `{statements, warnings}`:

  * `statements` — safe, additive `ADD INDEX IF NOT EXISTS` statements for
    indexes that don't exist yet.
  * `warnings` — human-readable strings for indexes that exist under the
    same name but with a different `type` or `expression` than configured.
    These are **not** auto-corrected: ClickHouse requires `DROP INDEX` +
    `ADD INDEX` to change a data-skipping index in place, and doing that
    automatically risks silently discarding a built index on a large table
    without the operator's knowledge. The warning tells you what to run
    manually.

Comparison of `expression` is best-effort: ClickHouse normalizes stored
expressions (whitespace, sometimes backtick quoting, occasionally constant
folding) so it may not match your DSL string byte-for-byte even when they're
semantically identical. When in doubt, treat a `type` mismatch as
authoritative and double-check `expression` mismatches by hand before acting
on them.

# `alter_table_cql`

```elixir
@spec alter_table_cql(module(), module()) :: [String.t()]
```

Generates `ALTER TABLE ... ADD COLUMN IF NOT EXISTS` statements for attributes
that exist on the resource but not yet in the table. This is a minimal schema
evolution pass: it adds new columns but does not drop or alter existing ones.

Returns an empty list when the table does not exist yet (the CREATE TABLE
statement handles initial creation) or when there are no new columns.

# `create_table_cql`

```elixir
@spec create_table_cql(module()) :: String.t()
```

Generates the `CREATE TABLE` SQL for a resource.

# `generate_resource_cql`

```elixir
@spec generate_resource_cql(module()) :: [String.t()]
```

Generates all migration statements (table creation) for a list of resources.

---

*Consult [api-reference.md](api-reference.md) for complete listing*
