Xitdb (xitdb v1.0.1)

Copy Markdown View Source

Idiomatic Elixir client and Odin NIF wrapper for xitdb, an embeddable, immutable, append-only database with persistent structural sharing.

Xitdb exposes database moments as lazy %Xitdb.Cursor{} handles that implement Elixir's Access, Enumerable, and Inspect protocols—allowing you to navigate and query on-disk data structures (Hash_Map, Counted_Hash_Map, Sorted_Map, Array_List, Linked_Array_List, and sets) just like standard Elixir maps and lists.

Summary

Functions

Wraps list to be stored as a 16-way Radix Trie (Array_List).

Returns a lazy %Xitdb.Cursor{} pinned to historical moment_index (0..N-1, or negative from end).

Flushes and closes the underlying xitdb storage handle.

Compacts db into a new database keeping only the latest committed moment and deduplicating reachable slots.

Same as compact/2, but raises Xitdb.Error on failure.

Wraps map to be stored as a Counted_Hash_Map with $O(1)$ Enum.count/1.

Wraps members to be stored as a Counted_Hash_Set with $O(1)$ Enum.count/1.

Returns a lazy %Xitdb.Cursor{} pointing to the latest committed moment (-1).

Stages an $O(\log N)$ removal from a Linked_Array_List at path_or_selector and index on a root %Xitdb.Cursor{} inside Xitdb.transact/2.

Computes the structural diff between moment_a and moment_b, skipping unchanged subtrees in $O(1)$ via 9-byte Slot equality.

Stages an $O(1)$ zero-copy structural clone (tx_fork) from from_selector to to_selector.

Wraps map to be stored as an uncounted 16-way HAMT (Tag.Hash_Map).

Wraps members to be stored as a 16-way HAMT Hash_Set.

Returns the historical lineage of selector across all moments where its Slot changed.

Returns database metadata (%{moment_count: integer(), file_size: integer()}).

Same as info/1, but raises Xitdb.Error on failure.

Stages an $O(\log N)$ insertion into a Linked_Array_List at path_or_selector and index on a root %Xitdb.Cursor{} inside Xitdb.transact/2.

Wraps list to be stored as a count-augmented B-Tree (Linked_Array_List).

Eagerly materializes a %Xitdb.Cursor{} (or %Xitdb{} database handle) into native Elixir maps (%{}), lists ([]), sets (MapSet.t()), and scalars.

Returns the number of committed historical moments in db.

Opens a Xitdb database instance.

Same as open/1, but raises Xitdb.Error on failure.

Executes a Datomic-style Pull projection against a %Xitdb.Cursor{} or %Xitdb{} handle.

Same as pull/2, but raises Xitdb.Error on failure.

Executes a Datalog query (~q"find ?e, ?name where ...") against db or a %Xitdb.Cursor{}.

Resolves a canonical xitdb selector string (~x|.users["101"].todos[1]|) against db or a %Xitdb.Cursor{}.

Same as select/2, but raises Xitdb.Error on failure.

Wraps map to be stored as a lexicographically ordered B+Tree (Sorted_Map).

Wraps members to be stored as a lexicographically ordered B+Tree Sorted_Set.

Synchronizes buffered writes to disk.

Executes an atomic transaction committing a new moment to db.

Executes a list of low-level transaction tuples ({:put, path, val}, {:insert, path, idx, val}, etc.) in a single atomic NIF transaction commit.

Types

t()

@type t() :: %Xitdb{
  backend: :memory | :file | :buffered_file,
  db_ref: reference(),
  hash: :sha1 | :sha256,
  path: String.t()
}

Functions

array_list(list)

@spec array_list(list()) :: Xitdb.Collection.t()

Wraps list to be stored as a 16-way Radix Trie (Array_List).

as_of(xitdb, moment_index)

@spec as_of(t(), integer()) :: Xitdb.Cursor.t()

Returns a lazy %Xitdb.Cursor{} pinned to historical moment_index (0..N-1, or negative from end).

at(index)

close(xitdb)

@spec close(t()) :: :ok

Flushes and closes the underlying xitdb storage handle.

compact(xitdb, opts \\ [])

@spec compact(t(), keyword()) :: {:ok, t()} | {:error, Xitdb.Error.t()}

Compacts db into a new database keeping only the latest committed moment and deduplicating reachable slots.

compact!(db, opts \\ [])

@spec compact!(t(), keyword()) :: t()

Same as compact/2, but raises Xitdb.Error on failure.

counted_map(map)

@spec counted_map(Enumerable.t()) :: Xitdb.Collection.t()

Wraps map to be stored as a Counted_Hash_Map with $O(1)$ Enum.count/1.

counted_set(members)

@spec counted_set(Enumerable.t()) :: Xitdb.Collection.t()

Wraps members to be stored as a Counted_Hash_Set with $O(1)$ Enum.count/1.

datalog(block)

(macro)

db(db_handle)

@spec db(t()) :: Xitdb.Cursor.t()

Returns a lazy %Xitdb.Cursor{} pointing to the latest committed moment (-1).

delete_at(root, path_or_selector, index)

@spec delete_at(Xitdb.Cursor.t(), String.t() | [term()], integer()) ::
  Xitdb.Cursor.t()

Stages an $O(\log N)$ removal from a Linked_Array_List at path_or_selector and index on a root %Xitdb.Cursor{} inside Xitdb.transact/2.

diff_moments(xitdb, moment_a, moment_b)

@spec diff_moments(t(), integer(), integer()) ::
  {:ok, [map()]} | {:error, Xitdb.Error.t()}

Computes the structural diff between moment_a and moment_b, skipping unchanged subtrees in $O(1)$ via 9-byte Slot equality.

fork(root, from_selector, to_selector)

@spec fork(Xitdb.Cursor.t(), String.t(), String.t()) :: Xitdb.Cursor.t()

Stages an $O(1)$ zero-copy structural clone (tx_fork) from from_selector to to_selector.

hash_map(map)

@spec hash_map(Enumerable.t()) :: Xitdb.Collection.t()

Wraps map to be stored as an uncounted 16-way HAMT (Tag.Hash_Map).

hash_set(members)

@spec hash_set(Enumerable.t()) :: Xitdb.Collection.t()

Wraps members to be stored as a 16-way HAMT Hash_Set.

history_of(xitdb, selector)

@spec history_of(t(), String.t()) :: {:ok, [map()]} | {:error, Xitdb.Error.t()}

Returns the historical lineage of selector across all moments where its Slot changed.

info(xitdb)

@spec info(t()) :: {:ok, map()} | {:error, Xitdb.Error.t()}

Returns database metadata (%{moment_count: integer(), file_size: integer()}).

info!(db)

@spec info!(t()) :: map()

Same as info/1, but raises Xitdb.Error on failure.

insert_at(root, path_or_selector, index, value)

@spec insert_at(Xitdb.Cursor.t(), String.t() | [term()], integer(), term()) ::
  Xitdb.Cursor.t()

Stages an $O(\log N)$ insertion into a Linked_Array_List at path_or_selector and index on a root %Xitdb.Cursor{} inside Xitdb.transact/2.

path_or_selector can be a selector string (path(users[id].queue)) or a list of keys / typed {kind, key} steps ([{:counted, "users"}, "alice", "queue"]).

linked_list(list)

@spec linked_list(list()) :: Xitdb.Collection.t()

Wraps list to be stored as a count-augmented B-Tree (Linked_Array_List).

materialize(db)

@spec materialize(t() | Xitdb.Cursor.t() | term()) :: term()

Eagerly materializes a %Xitdb.Cursor{} (or %Xitdb{} database handle) into native Elixir maps (%{}), lists ([]), sets (MapSet.t()), and scalars.

moment_count(db)

@spec moment_count(t()) :: non_neg_integer()

Returns the number of committed historical moments in db.

open(opts \\ [])

@spec open(keyword()) :: {:ok, t()} | {:error, Xitdb.Error.t()}

Opens a Xitdb database instance.

Options

  • :backend - Storage backend (:memory, :file, or :buffered_file). The default value is :memory.

  • :path (String.t/0) - Filesystem path for :file or :buffered_file backends. The default value is "".

  • :hash - Cryptographic digest algorithm for HAMT keys (:sha1 or :sha256). The default value is :sha1.

open!(opts \\ [])

@spec open!(keyword()) :: t()

Same as open/1, but raises Xitdb.Error on failure.

path(expr)

(macro)

pull(db, pattern)

@spec pull(t() | Xitdb.Cursor.t(), Xitdb.Pull.pattern()) ::
  {:ok, term()} | {:error, Xitdb.Error.t()}

Executes a Datomic-style Pull projection against a %Xitdb.Cursor{} or %Xitdb{} handle.

Accepts either a raw Pull pattern string ("{username, age, todos[0..2], profile{city}}") or a structural Elixir list ([:username, :age, todos: 0..2, profile: [:city]]).

pull!(target, pattern)

@spec pull!(t() | Xitdb.Cursor.t(), Xitdb.Pull.pattern()) :: term()

Same as pull/2, but raises Xitdb.Error on failure.

pull_pattern(pattern)

(macro)

query(target, query_str, opts \\ [])

@spec query(t() | Xitdb.Cursor.t(), String.t(), keyword()) ::
  {:ok, %{vars: [String.t()], rows: [[term()]]}} | {:error, Xitdb.Error.t()}

Executes a Datalog query (~q"find ?e, ?name where ...") against db or a %Xitdb.Cursor{}.

query!(target, query_str, opts \\ [])

@spec query!(t() | Xitdb.Cursor.t(), String.t(), keyword()) :: %{
  vars: [String.t()],
  rows: [[term()]]
}

Same as query/3, but raises Xitdb.Error on failure.

select(arg1, selector)

@spec select(t() | Xitdb.Cursor.t(), String.t()) ::
  {:ok, term()} | {:error, Xitdb.Error.t()}

Resolves a canonical xitdb selector string (~x|.users["101"].todos[1]|) against db or a %Xitdb.Cursor{}.

select!(target, selector)

@spec select!(t() | Xitdb.Cursor.t(), String.t()) :: term()

Same as select/2, but raises Xitdb.Error on failure.

sorted_map(map)

@spec sorted_map(Enumerable.t()) :: Xitdb.Collection.t()

Wraps map to be stored as a lexicographically ordered B+Tree (Sorted_Map).

sorted_set(members)

@spec sorted_set(Enumerable.t()) :: Xitdb.Collection.t()

Wraps members to be stored as a lexicographically ordered B+Tree Sorted_Set.

sync(xitdb)

@spec sync(t()) :: :ok | {:error, Xitdb.Error.t()}

Synchronizes buffered writes to disk.

transact(db, map_or_fun, opts \\ [])

@spec transact(
  t(),
  map() | (Xitdb.Cursor.t() -> Xitdb.Cursor.t() | {:abort, term()}),
  keyword()
) ::
  {:ok, t()} | {:error, Xitdb.Error.t()}

Executes an atomic transaction committing a new moment to db.

Accepts either:

  • A map of top-level keys/subtrees (Xitdb.transact(db, %{"users" => ...}, opts)), or
  • A 1-arity callback receiving the root %Xitdb.Cursor{} (Xitdb.transact(db, fn root -> put_in(root["a"]["b"], 1) end)).

transact!(db, map_or_fun, opts \\ [])

@spec transact!(t(), map() | (Xitdb.Cursor.t() -> Xitdb.Cursor.t()), keyword()) :: t()

Same as transact/3, but raises Xitdb.Error on failure.

transact_ops(db, ops, opts \\ [])

@spec transact_ops(t(), list(), keyword()) :: {:ok, t()} | {:error, Xitdb.Error.t()}

Executes a list of low-level transaction tuples ({:put, path, val}, {:insert, path, idx, val}, etc.) in a single atomic NIF transaction commit.

tx(db, block)

(macro)

tx(db, opts, block)

(macro)

tx!(db, block)

(macro)

tx!(db, opts, block)

(macro)