# `AshClickhouse.DataLayer.Types`
[🔗](https://github.com/ohhi-vn/ash_clickhouse/blob/main/lib/ash_clickhouse/data_layer/types.ex#L1)

Mapping between Ash attribute types and ClickHouse column types.

ClickHouse is a strongly-typed columnar store. When generating `CREATE TABLE`
statements and when encoding query parameters, the data layer needs to know
the ClickHouse type that corresponds to each Ash attribute.

The mapping here favours ClickHouse types that are safe and broadly useful:

| Ash type | ClickHouse type |
| --- | --- |
| `:uuid` | `UUID` |
| `:string` / `:atom` / `:ci_string` | `String` |
| `:integer` | `Int64` |
| `:float` | `Float64` |
| `:boolean` | `UInt8` |
| `:utc_datetime` / `:naive_datetime` | `DateTime` / `DateTime64` |
| `:date` | `Date` |
| `:time` | `String` |
| `:decimal` | `Decimal` |
| `:map` | `Map(String, String)` |
| `:array` / `:list` | `Array(String)` |

# `ash_type_to_clickhouse`

```elixir
@spec ash_type_to_clickhouse(atom() | tuple() | module()) :: String.t()
```

Maps an Ash attribute type to a ClickHouse column type string.

# `atom_attribute_names`

```elixir
@spec atom_attribute_names(module()) :: MapSet.t(atom())
```

Returns the set of attribute names (atom) that are Atom-typed.

# `attr_type_map`

```elixir
@spec attr_type_map(module()) :: %{required(atom() | String.t()) =&gt; String.t()}
```

Builds a map of attribute name => ClickHouse type string for a resource.

# `convert_uuid_param`

```elixir
@spec convert_uuid_param(term(), term(), MapSet.t()) :: term()
```

Converts a single parameter to its 16-byte UUID binary form *only* when the
column it belongs to is known to be UUID-typed. This replaces the old
`convert_uuid_params/2` heuristic that mangled any 36-character string that
merely looked like a UUID — including legitimate `:string` business
identifiers (order numbers, etc.).

# `decode_value`

```elixir
@spec decode_value(term(), map()) :: term()
```

Decodes a raw ClickHouse value back into its Ash attribute value.

Mirrors `encode_value/2`: stringified maps/lists are left as-is (the
ClickHouse client already returns them in the expected shape for the
`Map(String, String)` / `Array(String)` column types), and time strings
are parsed back into `Time` structs.

# `encode_value`

```elixir
@spec encode_value(term(), map()) :: term()
```

Encodes an Ash attribute value into a ClickHouse-bindable value.

Most types pass through unchanged, but ClickHouse-specific encodings are
applied where the raw Elixir value would not bind correctly:

  * `:map` / `{:map, _, _}` — keys and values stringified (ClickHouse's
    `Map(String, String)` representation).
  * `:array` / `:list` / `{:array, _}` — elements stringified for the
    `Array(String)` representation.
  * `:time` / `:time_usec` — `Time` converted to its `"HH:MM:SS"` string.
  * `:decimal` — `Decimal` passed through (the client encodes it).

# `format_uuid_string`

```elixir
@spec format_uuid_string(integer(), integer(), integer(), integer(), integer()) ::
  String.t()
```

Formats the five 16-byte UUID segments into a canonical 36-character
(lowercase) UUID string.

# `resolve_attr_type`

```elixir
@spec resolve_attr_type(map()) :: String.t()
```

Resolves the ClickHouse type for an Ash attribute struct, preferring the
attribute's `storage_type/1` when available.

# `uuid_attribute_names`

```elixir
@spec uuid_attribute_names(module()) :: MapSet.t()
```

Returns the set of attribute names (atom and string) that are UUID-typed.

# `uuid_binary_to_string`

```elixir
@spec uuid_binary_to_string(binary()) :: {:ok, String.t()} | :error
```

Converts a 16-byte UUID binary to its canonical 36-character string form.

# `uuid_like_string?`

```elixir
@spec uuid_like_string?(term()) :: boolean()
```

Returns true if the given binary looks like a canonical UUID string.

# `uuid_string_to_binary`

```elixir
@spec uuid_string_to_binary(String.t()) :: {:ok, binary()} | :error
```

Converts a 36-character UUID string to its 16-byte binary form for ClickHouse.

---

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