mix stdlib minidb - remixlabs/docs-public GitHub Wiki

Standard library - minidb

Not yet merged!

Module:

module minidb  // since PR 1195
  // types
  type record = data             // see db.record
  type recordOrNull = data       // see db.record
  type strictRecord = map(data)
  type recordID = data          // see db.recordID
  type selection =
    { includeSuperseded: bool,
      includeDeleted: bool
    }

  // populate
  def populate : appstate -> array(strictRecord) -> null

  // transactions
  def commit : appstate -> null
  def rollback : appstate -> null

  // get full contents
  def head : selection
  def all : selection
  def includeDeleted : bool -> selection -> selection
  def includeSuperseded : bool -> selection -> selection
  def committedRecords : selection -> stream(strictRecord)
  def currentRecords : selection -> stream(strictRecord)
  def changedRecords : selection -> stream(strictRecord)
module end

The MiniDB is a highly simplified database:

  • the contents are only stored in the current session and not persisted
  • there is no index except of _rmx_id, and hence it is only well-suited for small amounts of data
  • it is fully implemented in Mix and doesn't need any FFI - which means it is also available in WebAssembly mode
  • it can be accessed from the db module as well
  • supports transactions
  • most features of our regular DB are implemented in the same way - with a few exceptions only:
    • no string queries
    • no grouping
    • no _rmx_rev and _rmx_previous fields
    • no _rmx_content_hash field

Populating and transactions

The MiniDB is initially empty after session startup. There are two ways of loading initial data into it:

  • by calling minidb.populate: this is fast, but the records must essentially come from an export of a previous session
  • by calling db.save and then minidb.commit: this is slower, but you can also use symbolic IDs (the refs are adapted), and e.g. use this method to copy records from the main database into the MiniDB

There is some transactional support. By calling minidb.commit the changes are accepted. By calling minidb.rollback any changes since the last commit are dropped.

The records can be obtained by these functions:

  • minidb.committedRecords: these are the records of the last commit (even if there are uncommitted changes since then)
  • minidb.currentRecords: these are the records of the current transaction
  • minidb.changedRecords: these are the changes since the start of the transaction

Using minidb.populate

This function is intended to quickly load the MiniDB with some data (e.g. coming from an API). The records should have been obtained by a previous call of minidb.currentRecords (or committedRecords), e.g. a possible cycle is:

  • use an API to get the records
  • call minidb.populate with these records
  • do something that mutates the MiniDB
  • get the records by minidb.currentRecords(minidb.head)
  • use an API to store the records

minidb.populate must not be used with incomplete records, or with records coming from the regular DB. Use db.save to load such records (see below for an example).

Note that minidb.populate wipes out any previous contents, and by loading the empty array the MiniDB is effectively erased.

Using the MiniDB with the regular db module

Almost all functions of the db module can also be directed to access the MiniDB instead. In order to do this, use

minidb.DB

as the database (which is the same as { "type": "minidb" }). E.g.

db.head(minidb.DB) |> db.filter(r -> r.name == "Vijay") |> db.toArray

Remember that queries aren't fast - essentially, all records in the MiniDB are tested sequentially in order to get the result set. The only exception of this are queries containing _rmx_id == <ID>.

Copy some records from the regular DB to the MiniDB

For example:

db.head()
  |> db.filter(r -> r.entity?)
  |> db.toStream
  |> db.save(minidb.DB)

Note that the IDs change when the records are saved to the MiniDB.