# `Lotus.Schema`
[🔗](https://github.com/typhoonworks/lotus/blob/v0.16.4/lib/lotus/schema.ex#L1)

Schema introspection functionality for Lotus.

Provides functions to list schemas, tables and inspect table schemas across
different database adapters (PostgreSQL, MySQL, SQLite, etc.).

## Visibility Filtering

All schema and table listing functions automatically apply visibility rules
configured in your application:

- **Schema visibility** filters which schemas are accessible
- **Table visibility** filters which tables within allowed schemas are accessible
- **Built-in security** automatically blocks system schemas and tables

Schema visibility takes precedence - if a schema is denied, all tables within it
are blocked regardless of table-level rules.

## Database-Specific Behavior

- **PostgreSQL**: Returns namespaced `{schema, table}` tuples
- **MySQL**: Returns `{database, table}` tuples (schemas = databases in MySQL)
- **SQLite**: Returns table names as strings (schema-less)

# `get_table_schema`

```elixir
@spec get_table_schema(module() | String.t(), String.t(), keyword()) ::
  {:ok, [map()]} | {:error, term()}
```

Gets the schema information for a specific table.

Returns a list of column definitions with their types and constraints.

## Options

- `:schema` - Look for table in specific schema
- `:schemas` - Search for table in multiple schemas (first match wins)
- `:search_path` - Use PostgreSQL search_path to resolve table location
- `:cache` - Cache options (profile, ttl_ms, etc.)

## Examples

    {:ok, schema} = Lotus.Schema.get_table_schema(MyApp.Repo, "users")
    # Returns schema for public.users

    {:ok, schema} = Lotus.Schema.get_table_schema("postgres", "customers", schema: "reporting")
    # Returns schema for reporting.customers

    {:ok, schema} = Lotus.Schema.get_table_schema("postgres", "customers", search_path: "reporting, public")
    # Finds customers table using search_path resolution

# `get_table_stats`

```elixir
@spec get_table_stats(module() | String.t(), String.t(), keyword()) ::
  {:ok, %{row_count: non_neg_integer()}} | {:error, binary()}
```

Gets basic statistics about a table.

Returns information like row count and table size.

## Options

- `:schema` - Look for table in specific schema
- `:schemas` - Search for table in multiple schemas (first match wins)
- `:search_path` - Use PostgreSQL search_path to resolve table location
- `:cache` - Cache options (profile, ttl_ms, etc.)

## Examples

    {:ok, stats} = Lotus.Schema.get_table_stats(MyApp.Repo, "users")
    # Returns: %{row_count: 1234}

    {:ok, stats} = Lotus.Schema.get_table_stats("postgres", "customers", schema: "reporting")
    # Gets stats for reporting.customers

# `list_relations`

```elixir
@spec list_relations(
  module() | String.t(),
  keyword()
) :: {:ok, [{String.t() | nil, String.t()}]} | {:error, term()}
```

Lists all relations (tables with schema information) in the given repository.

Similar to list_tables/2 but returns {schema, table} tuples instead of just table names.
Useful for UIs that need to display schema information.

## Examples

    {:ok, relations} = Lotus.Schema.list_relations("postgres", search_path: "reporting, public")
    # Returns [{"reporting", "customers"}, {"reporting", "orders"}, {"public", "users"}, ...]

# `list_schemas`

```elixir
@spec list_schemas(
  module() | String.t(),
  keyword()
) :: {:ok, [String.t()]} | {:error, term()}
```

Lists all visible schemas in the given repository.

Returns a list of schema names filtered by visibility rules. For databases
without schemas (like SQLite), returns an empty list.

**Note**: Results are automatically filtered by schema visibility rules.
System schemas (like `pg_catalog`) are always blocked for security.

## Options

- `:cache` - Cache options (profile, ttl_ms, etc.)

## Examples

    {:ok, schemas} = Lotus.Schema.list_schemas(MyApp.Repo)
    # PostgreSQL: ["public", "reporting", ...]  (filtered by visibility)

    {:ok, schemas} = Lotus.Schema.list_schemas("mysql")
    # MySQL: ["app_production", "analytics_db", ...]  (databases = schemas)

    {:ok, schemas} = Lotus.Schema.list_schemas("sqlite")
    # SQLite: []  (schema-less database)

# `list_tables`

```elixir
@spec list_tables(
  module() | String.t(),
  keyword()
) :: {:ok, [{String.t(), String.t()}] | [String.t()]} | {:error, term()}
```

Lists all visible tables in the given repository.

For databases with schemas (like PostgreSQL), returns {schema, table} tuples.
For databases without schemas (like SQLite), returns just table names as strings.

**Note**: Results are automatically filtered by visibility rules:

1. Schema visibility is checked first - denied schemas block all their tables
2. Table visibility is then applied to tables in allowed schemas
3. System tables are always blocked for security

## Options

- `:schema` - Search in specific schema (e.g., `schema: "reporting"`)
- `:schemas` - Search in multiple schemas (e.g., `schemas: ["reporting", "public"]`)
- `:search_path` - Use PostgreSQL search_path (e.g., `search_path: "reporting, public"`)
- `:include_views` - Include views in results (default: false)

## Examples

    {:ok, tables} = Lotus.Schema.list_tables(MyApp.Repo)
    # PostgreSQL: [{"public", "users"}, {"public", "posts"}, ...]  (filtered by visibility)

    {:ok, tables} = Lotus.Schema.list_tables("postgres", search_path: "reporting, public")
    # PostgreSQL: [{"reporting", "customers"}, {"reporting", "orders"}, {"public", "users"}, ...]

    {:ok, tables} = Lotus.Schema.list_tables("mysql")
    # MySQL: [{"app_db", "users"}, {"analytics_db", "reports"}, ...]  (databases = schemas)

    {:ok, tables} = Lotus.Schema.list_tables("sqlite")
    # SQLite: ["products", "orders", "order_items"]  (schema-less)

---

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