README.md

# EctoDBScanner

A PostgreSQL database scanner that connects to a database at runtime, discovers its full structure, maps column types to generalized Elixir types, and detects enum-like columns.

## Features

- Discover schemas, tables, views, and materialized views
- Map PostgreSQL types to generalized Elixir types (`:string`, `:integer`, `:datetime`, etc.)
- Detect primary key and foreign key constraints
- Detect PostgreSQL ENUM types with their defined values
- Heuristic detection of enum-like string columns based on cardinality
- Expose column defaults and nullability
- Parallel scan execution via [Reactor](https://hexdocs.pm/reactor) pipeline

## Installation

Add `ecto_db_scanner` to your list of dependencies in `mix.exs`:

```elixir
def deps do
  [
    {:ecto_db_scanner, "~> 0.1.0"}
  ]
end
```

## Usage

```elixir
{:ok, database} = EctoDBScanner.scan(
  hostname: "localhost",
  username: "postgres",
  password: "postgres",
  database: "my_db",
  port: 5432
)

# Returns:
# %EctoDBScanner.Result.Database{
#   schemas: [
#     %EctoDBScanner.Result.Schema{
#       name: "public",
#       tables: [
#         %EctoDBScanner.Result.Table{
#           name: "users",
#           type: :table,
#           columns: [
#             %EctoDBScanner.Result.Column{
#               name: "id",
#               type: :integer,
#               nullable: false,
#               primary_key: true,
#               foreign_key: nil,
#               default: "nextval('users_id_seq'::regclass)",
#               enum_values: nil
#             },
#             %EctoDBScanner.Result.Column{
#               name: "status",
#               type: :string,
#               nullable: false,
#               primary_key: false,
#               foreign_key: nil,
#               default: nil,
#               enum_values: ["active", "inactive", "pending"]
#             },
#             ...
#           ]
#         },
#         ...
#       ]
#     },
#     ...
#   ]
# }
```

## Type Mapping

| PostgreSQL types | Elixir type |
|---|---|
| `int2`, `int4`, `int8`, `serial`, `bigserial`, `smallserial` | `:integer` |
| `float4`, `float8`, `numeric` | `:float` |
| `bool` | `:boolean` |
| `varchar`, `text`, `char`, `bpchar`, `citext`, `name` | `:string` |
| `date` | `:date` |
| `time`, `timetz` | `:time` |
| `timestamp` | `:naive_datetime` |
| `timestamptz` | `:datetime` |
| `uuid` | `:uuid` |
| `json`, `jsonb` | `:map` |
| `bytea` | `:binary` |
| `inet`, `cidr`, `macaddr`, `macaddr8` | `:string` |
| `_<type>` (array prefix) | `{:array, <mapped_type>}` |
| User-defined enum | `:string` (with `enum_values` populated) |
| Anything else | `{:unknown, "raw_type_name"}` |

## License

MIT - see [LICENSE](LICENSE) for details.