Module Rel.Schema

Schema descriptions.


type name = string

The type for schema names.

type t

The type for schema values.

val v : ?name:name -> tables:Table.v list -> unit -> t

v ~schema ~tables is a schema with given paramaters. See accessors for semantics.

Raises Invalid_argument if there are two tables with the same name in table.

val name : t -> name option

name s is the name of the schema (if any).

val tables : t -> Table.v list

tables s are the tables in s. If the dependencies between tables form a directed acyclic graph this is in Table.sort order. Otherwise this in the order given to v.

val find_table : -> t -> Table.v option

find_table n s is the table named n in s (if any).

val must_be_dag : t -> (unit, string) Stdlib.result

must_be_dag s checks that s is a directed acyclic graph. If the tables of s have a cycle (excluding self-dependencies) returns an error mentioning it. See Table.sort.


type rename = string * string

The type for rename changes. The source name and the destination name.

type col_renames = * rename list

The type for table column renames. The table name and the list of column renames.

type change =
  1. | Alter_table : 'r Table.t * 'r Table.change list -> change
  2. | Create_table : 'r Table.t -> change
  3. | Drop_table : -> change
  4. | Rename_column : * rename -> change
  5. | Rename_table : rename -> change

The type for schema changes. Table values that are as found in the destination schema, in particular Alter_table changes assume all renames have already occured.

val changes : ?col_renames:col_renames list -> ?table_renames:rename list -> src:t -> dst:t -> unit -> (change list, string) Stdlib.result

changes ~src ~dst is the list of changes that need to be performed to bring schema ~src to ~dst. The function errors if table_map or col_map mention names that do not exist in src and dst.

Before computing the changes, column names of tables in src are renamed according to col_renames and then tables are renamed according to table_renames. This results in a schema src' which is compared to dst in order to derive the changes.

Changes are listed in the following order, column and table renames, table creations, table alterations and, finally, table drops.

Note. Do not see the output as a silver bullet, review changes that are computed after they have gone through your SQL DBMS dialect via Rel_sql.schema_changes and suggest improvements if you see some or non-sensical transforms. Also it's a bit unclear to the author how DBMS react if your schema is not a directed acyclic graph.

val pp_change : Stdlib.Format.formatter -> change -> unit

pp_change ppf c formats change c in a pseudo, non-executable, SQL.

Dot diagrams

type dot_rankdir = [
  1. | `TB
  2. | `LR
  3. | `BT
  4. | `RL

The type for dot rankdir.

val pp_dot : rankdir:dot_rankdir -> Stdlib.Format.formatter -> t -> unit

pp_dot ~rankdir ppf s formats the schema s as a dot diagram with direction rankdir.

This can be rendered to many formats. For example SVG with dot -Tsvg. To change the rankdir after the generation use dot -Tsvg -Grankdir=LR.

OCaml sources

val pp_ocaml : [ `Intf | `Impl | `Both ] -> Stdlib.Format.formatter -> t -> unit

pp_ocaml kind s formats the schema s as an OCaml source using the Rel schema conventions according to kind:

  • `Intf formats definitions for an .mli file to be used with `Impl.
  • `Impl formats an .ml file t be used with `Intf.
  • `Both formats a self-contained .ml that has `Impl constrained by `Intf.

Warning. For now this function does not support schema with cycles and raises Invalid_argument if s has cycles. Use must_be_dag beforehand to avoid this. This restriction may be lifted in the future.