database

An outrageously simple set of functions to interact with the BEAM DETS (Disk-based Erlang Term Storage) API.

Good for small projects and POCs.

This project DOES NOT intend to serve as direct bindings to the DETS API, but rather to interact with it in a gleamy way:

  1. with a simple and concise interface;
  2. type-safely;
  3. no unexpected crashes, all errors are values.

Types

A collection of values used to access a DETS table.

pub opaque type Table(a)

Possible error that may occur when using the library.

pub type TableError {
  Badarg
  IndexOutOfBounds
  UnableToOpen
  UnableToClose
}

Constructors

  • Badarg

    The definition provided is not a Gleam record or

  • IndexOutOfBounds

    The index provided for the primary_key is lower than 0 or higher than the record size

  • UnableToOpen

    A problem occurred when trying to open and lock the .dets file.

  • UnableToClose

    A problem ocurred when trying to write into the .dets file and close it.

A reference to an open table, required to interact with said table. Obtained through the transaction(Table) function

pub type TableRef(a)

Values

pub fn create_table(
  definition definition: a,
  index_at keypos: Int,
) -> Result(Table(a), TableError)

Creats a table.

Important

THE TABLE IS ENTIRELY DEPENDENT ON THE DEFINITION PROVIDED, ANY CHANGE TO DEFINITION - EVEN IF EVERYTHING REMAINS OF THE SAME TYPE - WILL CAUSE ANOTHER TABLE TO BE CREATED.

If no .dets file exists for the provided definition, creates one. Otherwise, just checks whether the file is accessible and not corrupted.

Example

pub fn start_database() {
  let pluto = Pet(name: "Pluto", animal: Dog)
  database.create_table(definition: pluto, index_at: 0)
  // -> Ok(Table(Pet))
}
pub fn delete(transac: TableRef(a), index: b) -> Result(Nil, c)

Deletes a value from a table.

Example

pub fn delete_pet(table: Table(Pet) petname: String) {
  use ref <- database.transaction(table)
  database.delete(ref, petname)
}
pub fn drop_table(table: Table(a)) -> Result(Nil, b)

Deletes de entire table file

Example

pub fn destroy_all_pets(table: Table(Pet), password: String) {
  case password {
    "Yes, I am evil." -> {
      database.drop_table(table)
      Ok(Nil)
    }
    _ -> Error(WrongPassword)
  }
}
pub fn find(transac: TableRef(a), index: b) -> option.Option(a)

Finds a value by its index

Example

pub fn play_with_pluto(table: Table(Pet)) {
  use ref <- database.transaction(table)
  let resp = database.find(ref, "Pluto")
  case resp {
    None -> Error(PlutoNotFoundBlameTheAstronomers)
    Some(pluto) -> Ok(play_with(pluto))
  }
}
pub fn insert(transac: TableRef(a), value: a) -> Result(Nil, b)

Inserts a value into a table.

DETS tables do not have support for update, only for upsert. So if you have to change a value, just insert a new value with the same index, and it will replace the previous value.

Example

pub fn new_pet(table: Table(Pet), animal: Animal, name: String) {
  let pet = Pet(name, animal)
  let op = database.transaction(table, fn(ref) {
    database.insert(ref, pet)
  })
  case op {
    Ok(_) -> Ok(pet)
    Error(reason) -> Error(reason)
  }
}
pub fn transaction(
  table: Table(a),
  procedure: fn(TableRef(a)) -> b,
) -> Result(b, TableError)

Allows you to interact with the table.

It opens and locks the .dets file, then execute your operations. Once the operations are done, it writes the changes into the file, closes and releases it.

Example

pub fn is_pet_registered(table: Table(Pet), petname: String) {
  use ref <- database.transaction(table)
  case database.find(ref, petname) {
    Some(_) -> True
    None -> False
  }
}
Search Document