# `Lotus.Storage.SchemaCache`
[🔗](https://github.com/typhoonworks/lotus/blob/v0.16.6/lib/lotus/storage/schema_cache.ex#L1)

Caches table schema metadata for automatic type detection and casting.

Maintains in-memory representation of database schema.
Uses Lotus's existing ETS-based cache infrastructure to store table/column metadata
and avoid repeated `information_schema` queries.

## Features

- **Table-level caching**: Caches all columns for a table together for efficiency
- **TTL-based expiration**: Default 5-minute TTL (configurable)
- **Graceful degradation**: Falls back to direct schema query if cache unavailable
- **Warm cache support**: Preload frequently-used tables on application startup

## Usage

    # Get all columns for a table
    {:ok, schema} = SchemaCache.get_table_schema(MyApp.Repo, "public", "users")
    # => %{"id" => %{type: "uuid", nullable: false, ...}, ...}

    # Get specific column type
    {:ok, type} = SchemaCache.get_column_type(MyApp.Repo, "public", "users", "id")
    # => "uuid"

    # Invalidate cache after migrations
    SchemaCache.invalidate(MyApp.Repo, "public", "users")

# `column_info`

```elixir
@type column_info() :: %{
  type: String.t(),
  nullable: boolean(),
  default: term() | nil,
  primary_key: boolean()
}
```

# `get_column_type`

```elixir
@spec get_column_type(
  repo :: module(),
  schema :: String.t() | nil,
  table :: String.t(),
  column :: String.t()
) :: {:ok, String.t()} | :not_found
```

Get specific column type. Returns the database-native type string.

## Examples

    {:ok, type} = SchemaCache.get_column_type(MyApp.Repo, "public", "users", "id")
    # => "uuid"

    SchemaCache.get_column_type(MyApp.Repo, "public", "users", "nonexistent")
    # => :not_found

# `get_table_schema`

```elixir
@spec get_table_schema(
  repo :: module(),
  schema :: String.t() | nil,
  table :: String.t()
) :: {:ok, %{required(String.t()) =&gt; column_info()}} | {:error, term()}
```

Get column metadata for a table. Returns map of column_name => column_info.
Caches result for subsequent calls.

## Examples

    {:ok, schema} = SchemaCache.get_table_schema(MyApp.Repo, "public", "users")
    schema["id"]
    # => %{type: "uuid", nullable: false, default: nil, primary_key: true}

# `invalidate`

```elixir
@spec invalidate(repo :: module(), schema :: String.t() | nil, table :: String.t()) ::
  :ok
```

Invalidate cache for a specific table (useful after migrations).

## Examples

    SchemaCache.invalidate(MyApp.Repo, "public", "users")
    # => :ok

# `warm_cache`

```elixir
@spec warm_cache(
  repo :: module(),
  tables :: [{schema :: String.t() | nil, table :: String.t()}]
) :: :ok
```

Warm cache with frequently-used tables on application startup.

## Examples

    SchemaCache.warm_cache(MyApp.Repo, [
      {"public", "users"},
      {"public", "orders"}
    ])
    # => :ok

---

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