Depo v1.7.1 Depo View Source

Depo provides lightweight storage and querying capabilities in Elixir by providing a minimal and polished API that builds on the unique advantages of SQLite.

There are many ways to use Depo, but the recommended way is to use teach/2 and transact/2so that you can reap the performance benefit of SQLite transactions and pre-compiled SQL statements. It also has the benefit of forming a sort of DSL for your database.

Here are the basic steps to use Depo in the recommended way:

  1. Open or create a database using open/1 to get a new Depo.DB object that manages the database connection.
  2. Enclose all database actions in a function you pass to transact/2 to group them in a transaction.
  3. Use write/2 to create any desired tables (data types are optional because SQLite uses dynamic data typing.)
  4. Use teach/2 to create a set of pre-compiled SQL statements you can use to write to or read from the database. You can include numbered arguments in the statements by using ?1 to refer to the first argument, and ?2 for the second argument, and so on.
  5. Use write/3 to populate your database with data using the statements you taught the database and arguments to the statements supplied as the third argument.
  6. Use read/2 and read/3 to run (optionally parameterized) queries and get the results synchronously.
  7. Use stream/3 and stream/4 to run the same queries and stream the results asynchrously to any process.

Anywhere you give a command, you can give either a valid string of SQL or an atom registered to a cached statement. You can also include numbered variables like ?1 in your SQL statements and pass a list of values as the third parameter to write/3, read/3, and stream/3.

Usage Example

# Set up the database.
{:ok, db} = Depo.open(:memory)
# {:ok, #PID<0.155.0>}

# Enclose operations within a transaction.
Depo.transact(db, fn ->
  # Write SQL statements to the database.
  Depo.write(db, "CREATE TABLE greetings (phrase)")

  # Teach the database statements to cache them.
  Depo.teach(db, %{
    new_greeting: "INSERT INTO greetings VALUES (?1)",
    greetings: "SELECT * FROM greetings",
  })
  Depo.teach(db, %{
    new_greeting: "INSERT INTO greetings VALUES (?1)",
    greetings: "SELECT * FROM greetings"
  })
  Enum.each(["hola", "bonjour", "今日は"], fn phrase ->
    Depo.write(db, :new_greeting, phrase)
  end)
end)

Depo.read(db, :greetings)
# [
#   %{phrase: "今日は"},
#   %{phrase: "bonjour"},
#   %{phrase: "hola"}, 
# ]

# Any query can be streamed to any process. 
stream_id = Depo.stream(db, self(), :phrases)

phrases = Depo.read_stream(stream_id)
# phrases == [ 
#   %{phrase: "今日は"},
#   %{phrase: "bonjour"},
#   %{phrase: "hola"}, 
# ]

:ok = Depo.close(db)

Link to this section Summary

Functions

Safely close the database connection

Open a connection to a database and return a new Depo.DB object to manage the database connection

Synchronously read an SQL query from the database and return a list of the results

Wait for and read a stream returned from stream/3 sent to this process

Asynchronously stream the results of an SQL query from the database to the given PID

Pre-compile, cache, and register named SQL statements for more efficient repeated use

Wrap any operations within the given anonymous function in a nestable transaction. If any error occurs within, the transaction will be automatically rolled back

Asynchronously write SQL statements to the database

Link to this section Functions

Safely close the database connection.

Open a connection to a database and return a new Depo.DB object to manage the database connection.

There are a few ways you can open a database:

  • pass a path to open an existing on-disk database
  • pass create: path to create and open a database at the path
  • pass or_create: path to open or create a database at the path
  • pass :memory to create a new in-memory database

Synchronously read an SQL query from the database and return a list of the results.

Optionally supply a list of values as the third argument to bind to variables in the query.

Wait for and read a stream returned from stream/3 sent to this process..

Returns a list of messages received from the stream.

There is a timeout of 500ms between messages after which it will return all messages read so far.

Link to this function stream(db, pid, query, values) View Source

Asynchronously stream the results of an SQL query from the database to the given PID.

The given process will receive each result as a tuple {stream_id, value} where stream_id is the PID of the stream process that uniquely identifies the stream, and value is a single result map. A message {stream_id, :end} will be sent at the end.

Optionally supply a list of values as the fourth argument to bind to variables in the query.

Pre-compile, cache, and register named SQL statements for more efficient repeated use.

statements should be a keyword list, where the keys are atoms and the values are SQL statements.

Wrap any operations within the given anonymous function in a nestable transaction. If any error occurs within, the transaction will be automatically rolled back.

You can read about SQLite’s transactions in depth in its documentation.

Asynchronously write SQL statements to the database.

Optionally supply a list of values as the third argument to bind to variables in the statement.