datalog-dafsa

C API Reference

The public C API is declared in src/dl.h. All value arrays are u32 (raw integers or interned symbol ids). The handle type is the opaque dl_db. This page documents the complete surface, grouped by area. See also Order Statistics and Time Travel for the larger feature groups.

Lifecycle

dl_db *dl_open(const char *dir)Open or create a database directory. Returns NULL on error.
void dl_close(dl_db *db)Close the database, flushing and saving state.
dl_db *dl_open2(const char *dir, int *err_out)Open with explicit error reporting. On failure sets *err_out (see DL_E_LOCKED) and returns NULL.

Schema

int dl_declare_relation(dl_db *db, const char *name, uint8_t arity)Declare a fixed-arity relation (1–8). Idempotent; arity 0 declares a variadic relation.
int dl_declare_relation_variadic(dl_db *db, const char *name)Declare a variadic relation: facts of any arity 1–8 are accepted, stored per-arity.

Facts

int dl_load_facts(dl_db *db, const char *rel, const char *csv_path)Load ground facts from a headerless CSV (quoted strings interned; bare integers raw u32). Returns facts loaded, or -1.
int dl_add_fact(dl_db *db, const char *rel, const uint32_t *cols, uint8_t arity)Add a single fact (durable WAL + fsync). Returns 1 added / 0 duplicate / -1 error.
int dl_delete_fact(dl_db *db, const char *rel, const uint32_t *cols, uint8_t arity)Delete a single fact. Returns 1 deleted / 0 absent / -1 error.

Queries

int dl_lookup(dl_db *db, const char *rel, const uint32_t *cols, uint8_t arity)Exact lookup. Returns 1 if present, else 0.
typedef int (*dl_tuple_cb)(const uint32_t *cols, uint8_t arity, void *user)Tuple enumeration callback; return non-zero to stop early.
long dl_prefix(dl_db *db, const char *rel, const uint32_t *leading, uint8_t k, dl_tuple_cb cb, void *user)Bind the first k columns and enumerate matching tuples. Returns count, or -1.
long dl_query(dl_db *db, const char *goal_rel, dl_tuple_cb cb, void *user)Stream the goal relation’s tuples. Reads mmap snapshot if published, else runs the VM. Returns tuple count, or -1.
long dl_query_bound(dl_db *db, const char *goal_rel, const uint32_t *leading, uint8_t k, dl_tuple_cb cb, void *user)Prefix-bind k columns of the goal and enumerate.
long dl_pattern(dl_db *db, const char *rel, const struct regex_dfa *dfa, dl_tuple_cb cb, void *user)Enumerate tuples whose full key matches a compiled regex DFA.

Iterator + merge-join

A resumable pull-based cursor over the tuples of a relation in ascending key order (u32BE key encoding ⇒ numeric order == lex order). Reads from the mmap snapshot view when a snapshot is current, else the in-memory relation.

dl_iter *dl_iter_open(dl_db *db, const char *rel, const uint32_t *leading, uint8_t k)Open a cursor bound to the first k leading columns (k==0: all). Returns NULL on error; an absent prefix yields a valid empty iterator.
int dl_iter_seek(dl_iter *it, const uint32_t *leading, uint8_t k)Re-bind the cursor to a new leading prefix. Returns 0 / -1.
int dl_iter_next(dl_iter *it, uint32_t *cols_out)Fetch the next tuple ascending. Returns 1 / 0 at end / -1 error.
uint8_t dl_iter_arity(const dl_iter *it)The relation’s arity (0 for a NULL/error cursor).
void dl_iter_close(dl_iter *it)Close the cursor (NULL-safe).
typedef int (*dl_join_cb)(const uint32_t *l, uint8_t la, const uint32_t *r, uint8_t ra, void *user)Merge-join pair callback.
long dl_merge_join(dl_iter *l, dl_iter *r, uint8_t jcols, dl_join_cb cb, void *user)Equi-join two sorted iterators on their first jcols columns, streaming pairs in sorted order (cross-product semantics, duplicates preserved). Both iterators left exhausted. Returns pairs emitted, or -1.

Order statistics

uint64_t dl_rank(dl_db *db, const char *rel, const uint32_t *cols, uint8_t arity)Number of distinct tuples strictly lexicographically smaller than cols. UINT64_MAX on error.
int dl_select(dl_db *db, const char *rel, uint64_t k, uint32_t *cols_out, uint8_t arity)The k-th tuple (0-indexed, lex order). Returns 0 / -1.
uint64_t dl_range_count(dl_db *db, const char *rel, const uint32_t *lo, const uint32_t *hi, uint8_t arity)Number of distinct tuples in the half-open range [lo, hi) = rank(hi) − rank(lo).
uint64_t dl_count(dl_db *db, const char *rel)O(1) distinct-tuple count (memoized subtree array).
uint64_t dl_rank_bound(db, rel, leading, k, cols, arity)Rank restricted to tuples whose first k columns equal leading.
int dl_select_bound(db, rel, leading, k, idx, cols_out, arity)Select within a leading-prefix bound.
uint64_t dl_range_count_bound(db, rel, leading, k, lo, hi, arity)Range count within a leading-prefix bound.
uint64_t dl_rank_perm(db, rel, perm_id, cols, arity)Rank over a permuted view (order-by on a non-leading column).
int dl_select_perm(db, rel, perm_id, k, cols_out, arity)Select over a permuted view (inverse-maps the result back to original column order).
uint64_t dl_range_count_perm(db, rel, perm_id, lo, hi, arity)Range count over a permuted view.
int dl_db_perm_count(const dl_db *db)Number of permutation indices currently declared.

Details and examples are on the Order Statistics page.

Rules

int dl_load_rules(dl_db *db, const char *dl_source)Parse and compile Datalog rules from a source string. Returns 0 / -1. Rules may reference existing relations or declare new derived relations.
int dl_compile(dl_db *db)Compile all loaded rules into bytecode and run them (semi-naive fixpoint), materializing derived relations. Returns 0 / -1.
long dl_query_magic(db, goal_rel, leading, k, cb, user)Magic-sets bound query (leading/k). Re-evaluates a scoped fixpoint; result is byte-identical to dl_query_bound. Returns count, or -1.
long dl_query_magic_adorn(db, goal_rel, adorn, vals, nvals, cb, user)Magic-sets with an arbitrary adornment string of b/f chars.
long dl_query_topdown(db, goal_rel, leading, k, cb, user)Top-down / QSQ: the same adorned magic program, scheduled demand-driven (SLG worklist) instead of forward semi-naive. C-API only — no CLI command.
long dl_query_topdown_adorn(db, goal_rel, adorn, vals, nvals, cb, user)Top-down / QSQ with an arbitrary adornment.

Snapshot

int dl_publish_snapshot(dl_db *db)Atomically save the interner + all relations to a versioned snapshot directory and flip the CURRENT pointer. After publish, dl_query reads from mmap.

Time-travel / as-of

long dl_snapshot_versions(const dl_db *db, uint32_t *out, size_t cap)Enumerate every published snapshot version ascending. Returns the total (two-call idiom).
long dl_query_version(dl_db *db, uint32_t version, const char *goal_rel, dl_tuple_cb cb, void *user)As-of query: stream tuples as of snapshot version, bypassing live routing. Nonexistent version / absent relation is a loud -1, never a silent empty result.
long dl_query_bound_version(dl_db *db, uint32_t version, const char *goal_rel, const uint32_t *leading, uint8_t k, dl_tuple_cb cb, void *user)As-of prefix query.
int dl_set_snapshot_retain(dl_db *db, unsigned n)Opt-in retention: keep at most n most-recent versions, pruning older ones after each publish. n==0 (default) keeps every version.

Details and examples are on the Time Travel page.

Fault-injection hooks (test-only)

void dl_set_fault_hook(dl_db *db, int (*hook)(dl_fpoint fp, void *user), void *user)Install a fault-injection hook called at each fpoint during publish (DL_FPOINT_AFTER_REL_SAVE, DL_FPOINT_AFTER_RENAME) and during a transaction commit (DL_FPOINT_TXN_BEFORE_MARKER); non-zero aborts the publish/commit.

Interner

uint32_t dl_intern_str(dl_db *db, const char *str)Intern a string, return its sym_id (1-based). Returns 0 on OOM.
const char *dl_intern_str_of(dl_db *db, uint32_t sym_id)Look up a sym_id → string. Returns NULL if out of range.