Lotus.Storage.SchemaCache (Lotus v1.0.0)

Copy Markdown View Source

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.

All functions take a resolved %Lotus.Source.Adapter{} struct. Cache keys are derived from adapter.name, which is always a string and independent of the adapter's internal state shape (repo module, keyword list, etc.).

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

adapter = Lotus.Source.resolve!("main", nil)

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

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

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

Summary

Functions

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

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

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

Warm cache with frequently-used tables on application startup.

Types

column_info()

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

Functions

describe_table(adapter, schema, table)

@spec describe_table(
  adapter :: Lotus.Source.Adapter.t(),
  schema :: String.t() | nil,
  table :: String.t()
) :: {:ok, %{required(String.t()) => 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.describe_table(adapter, "public", "users")
schema["id"]
# => %{type: "uuid", nullable: false, default: nil, primary_key: true}

get_column_type(adapter, schema, table, column)

@spec get_column_type(
  adapter :: Lotus.Source.Adapter.t(),
  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(adapter, "public", "users", "id")
# => "uuid"

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

invalidate(adapter, schema, table)

@spec invalidate(
  adapter :: Lotus.Source.Adapter.t(),
  schema :: String.t() | nil,
  table :: String.t()
) ::
  :ok

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

Examples

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

warm_cache(adapter, tables)

@spec warm_cache(
  adapter :: Lotus.Source.Adapter.t(),
  tables :: [{schema :: String.t() | nil, table :: String.t()}]
) :: :ok

Warm cache with frequently-used tables on application startup.

Examples

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