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:
- with a simple and concise interface;
- type-safely;
- no unexpected crashes, all errors are values.
Types
Operations to perform on a select query.
pub type SelectOption(value) {
Skip
Continue(value)
Done(value)
}
Constructors
-
Skip
Ignores the current value.
-
Continue(value)
Adds the value to the return list.
-
Done(value)
Adds the value to the return list and immediately returns the query.
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
-
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.
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 the 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 select(
transac: TableRef(a),
select_fn: fn(a) -> SelectOption(b),
) -> List(b)
Searches for somethig on the table.
Example
pub fn fetch_all_parrots(table: Table(Pet)) {
use ref <- database.transaction(table)
use value <- database.select(ref)
case value {
Pet(_name, Parrot) -> Continue(value)
_ -> Skip
}
}
IMPORTANT
DETS tables are not sorted in any deterministic way, so never assume that the last value inserted will be the last one on the table.
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
}
}