# `Hakushi.Kits.Schema`
[🔗](https://github.com/hattoriai/hakushi/blob/v0.6.0/lib/hakushi/kits/schema.ex#L1)

The kit of a database schema: tables, with columns that have a name, a
type and a key (primary or foreign), and foreign keys drawn from a
column to a column of the same type.

A table is a node of type `"schema-table"` whose data is:

    %{
      "name" => "orders",
      "columns" => [
        %{"id" => "c1", "name" => "id", "type" => "uuid", "key" => "pk"},
        %{"id" => "c2", "name" => "customer_id", "type" => "uuid", "key" => "fk"},
        %{"id" => "c3", "name" => "placed_at", "type" => "timestamp", "key" => nil}
      ]
    }

Each column has a handle on each side, of the column's family of types
(`family/1`): an edge joins two columns of one family (`integer` to
`bigint`, `varchar(64)` to `text`, but not `text` to `uuid`), and takes
the sides nearest each other.
A column's handles are its `"id"` (its name, for a column without one),
so a foreign key stays when people rename the column.
People rename the table and its columns in place, pick a column's type,
set its key, and add and remove columns.

A table of another schema than the one shown (the table a foreign key
points to, in `billing`) is a stub: data with `"external" => true` and
its `"schema"`, and only the columns its foreign keys use. It is drawn
faint, with a dashed border and its qualified name (`billing.invoices`),
its edges dashed, and nobody edits it, even on a canvas they edit:

    %{"name" => "invoices", "schema" => "billing", "external" => true,
      "columns" => [%{"name" => "id", "type" => "uuid", "key" => "pk"}]}

A table may name its `"schema"` without being a stub; its name shows
qualified too.

In Markdown, a schema is a Mermaid entity relationship diagram: each
table with its columns (`uuid id PK`), and a foreign key as a
relationship from its table to the table it refers to, named after its
column. `from_markdown/1` reads it back, and reads ER diagrams people
write: a relationship becomes an edge from the column it names (else
the table's first column) to the other table's primary key.

# `column_types`

```elixir
@spec column_types() :: [String.t()]
```

The column types people pick from.

# `family`

```elixir
@spec family(String.t() | nil) :: String.t() | nil
```

The family of a column's type: the types whose columns a foreign key
joins. Sizes, precisions and modifiers do not count (`varchar(255)`,
`numeric(12,2)`, `int unsigned`, `timestamp with time zone`), nor case.

    iex> Hakushi.Kits.Schema.family("int4")
    "integer"
    iex> Hakushi.Kits.Schema.family("character varying(255)")
    "text"
    iex> Hakushi.Kits.Schema.family("TIMESTAMP WITH TIME ZONE")
    "timestamp"

The families are `integer`, `decimal`, `float`, `text`, `uuid`,
`timestamp`, `date`, `time`, `boolean`, `json` and `binary`. A type of
none of them is a family of its own (its name, in lower case, with
underscores for spaces), so it joins only its own type. Add or change
families with `config :hakushi, Hakushi.Kits.Schema, families: %{"geometry" =>
"geometry", "ltree" => "text"}`.

---

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