fx://datalog-dafsa

CLI Reference

The dl binary is the command-line front end. It has commands for loading facts, querying relations, publishing snapshots, and the search tier (full-text + semantic). The database directory defaults to dl-test-db and can be set with -d <dir>. Command values that parse as bare integers are stored raw as u32; anything else is interned to a string symbol id.

dl [-d <dir>] load    <csv> --rel <name>
dl [-d <dir>] lookup  <rel> <val> [<val> ...]
dl [-d <dir>] prefix  <rel> [<val> ...]
dl [-d <dir>] query   '<rule>' | <file.dl> <goal-rel>
dl [-d <dir>] qmagic  '<rule>' | <file.dl> <goal-rel> [-a <adorn>] <val> [<val> ...]
dl [-d <dir>] publish
dl [-d <dir>] bound   <rel> <val> [<val> ...]
dl [-d <dir>] pattern <rel> '<regex>'
dl [-d <dir>] search  '<terms>' [--top N] [--version N]
dl [-d <dir>] vsearch '<query>' [--k N] [--radius R] [--version V] [--sig <hex>] [--ivec <hex>]
dl [-d <dir>] vhybrid '<terms>' '<query>' [--k N] [--radius R] [--version V]
dl [-d <dir>] versions

load

Load facts from a headerless CSV file into a relation (arity 1–8).

$ ./dl -d /tmp/db load edges.csv --rel edge
Loaded 5 facts into edge

The relation’s arity is inferred from the first non-empty CSV row. Values: quoted strings are interned; bare integers are stored raw as u32.

lookup

Exact lookup of a fact by its full column values. Prints found or not found.

$ ./dl -d /tmp/db lookup edge 1 2
found

$ ./dl -d /tmp/db lookup edge 9 9
not found

prefix

Bind the leading columns to the given values and enumerate every matching complete tuple.

# all tuples
$ ./dl -d /tmp/db prefix edge
1 2
1 3
2 3
2 4
3 5

# tuples with leading column == 2
$ ./dl -d /tmp/db prefix edge 2
2 3
2 4

With no bound values, this lists the whole relation.

query

Parse, compile, and run a Datalog rule in one step, then stream the goal relation’s tuples. The rule source may be a quoted inline string or a .dl file path; the goal is the relation to print.

$ ./dl -d /tmp/db query \
    'tc(X,Y) :- edge(X,Y). tc(X,Y) :- edge(X,Z), tc(Z,Y).' tc
1 2
1 3
1 4
1 5
2 3
2 4
2 5
3 5

Internally this loads the rules, publishes a snapshot (running the VM if the fixpoint is dirty), then queries the goal relation.

qmagic

Magic-sets bound query: evaluates a scoped fixpoint seeded by the bound values, materialising only the reachable IDB slice. The result is byte-for-byte identical to dl_query_bound over the fully materialized goal.

# leading-prefix form: bind the first k args
$ ./dl -d /tmp/db qmagic \
    'tc(X,Y) :- edge(X,Y). tc(X,Y) :- edge(X,Z), tc(Z,Y).' tc 1

# arbitrary-adornment form: -a <adorn> binds named positions
$ ./dl -d /tmp/db qmagic \
    'tc(X,Y) :- edge(X,Y). tc(X,Y) :- edge(X,Z), tc(Z,Y).' tc -a "bf" 1

The optional -a <adorn> is a string of exactly goal-arity characters, each b (bound) or f (free); vals are packed left-to-right in the order of the b positions. Programs using negation, aggregates, or cross-predicate mutual recursion are rejected with a diagnostic.

Time travel

The CLI exposes the snapshot timeline directly. publish writes an immutable, versioned snapshot; versions lists the history; bound reads the current snapshot view; and the search tier accepts --version N to query as-of a past snapshot. Together these make time-traveling queries a first-class CLI capability.

# Record a point-in-time, then inspect the history.
$ ./dl -d /tmp/db publish
Snapshot published.
$ ./dl -d /tmp/db versions
1
2
3

# Search as-of a past snapshot (full-text + semantic).
$ ./dl -d /tmp/db search 'gpu rental' --top 10 --version 2
$ ./dl -d /tmp/db vsearch 'GPU rental' --k 10 --version 2

See the time-travel guide for the full as-of API.

publish

Atomically publish a versioned snapshot of the database — the write side of time travel.

$ ./dl -d /tmp/db publish
Snapshot published.

After publishing, query reads from mmap instead of running the VM.

bound

Bound query (snapshot path): bind leading columns and enumerate via the snapshot view.

$ ./dl -d /tmp/db bound edge 1
1 2
1 3

pattern

Enumerate all tuples whose full key matches a regex.

$ ./dl -d /tmp/db pattern edge '(a|b).*'

A bad pattern is a loud error.

Full-text search over the __postings__ index: AND-intersect the tokenized terms and rank by co-occurrence. --version N queries the index as-of a published snapshot (0 = live).

$ ./dl -d /tmp/db search 'gpu rental' --top 10
$ ./dl -d /tmp/db search 'gpu rental' --top 10 --version 3

vsearch

Semantic vector search: embed the query with the bge-small model (via the dl-embed tool), retrieve MIH candidates from the __sig*__ postings, and re-rank by in-store int8 cosine. Accepts --sig/--ivec hex for a programmatic path that needs no model, and --version V to search as-of a snapshot.

$ ./dl -d /tmp/db vsearch 'affordable GPU rental' --k 10

See the vector-search page for the full semantic tier.

vhybrid

Lexical ∩ semantic hybrid: intersect search results with vsearch candidates, then re-rank the intersection.

$ ./dl -d /tmp/db vhybrid 'gpu rental' 'affordable GPU rental' --k 10

versions

List the published snapshot versions (ascending) — the timeline.

$ ./dl -d /tmp/db versions

What is not in the CLI

The top-down / QSQ path (dl_query_topdown / dl_query_topdown_adorn) is available only through the C API — there is no topdown CLI subcommand. Likewise, order-statistics (rank / select / range / count) are C-API only. The semantic search tier relies on the dl-embed companion tool (built with make dl-embed) for query-time embedding.