Hakushi.Kits.Schema (Hakushi v0.6.0)

Copy Markdown View Source

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.

Summary

Functions

The column types people pick from.

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.

Functions

column_types()

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

The column types people pick from.

family(type)

@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"}.