Query builder that generates dllb SQL strings.
Provides functions to construct CREATE, SELECT, UPDATE, DELETE, RELATE, and DEFINE statements for the dllb query language. All functions return plain query strings ready to be sent over the wire.
Summary
Functions
Builds a COUNT <table> [WHERE <clause>] statement.
Builds a CREATE statement for inserting a new record.
Builds a CREATE statement with an explicit record ID.
Builds a DEFINE FIELD statement.
Builds a DEFINE INDEX statement that registers a persisted secondary
index in the engine's catalog and backfills entries for existing rows.
Builds a DEFINE TABLE statement.
Builds a DELETE statement for a record.
Builds a GRAPH COMMUNITIES statement for native community detection.
Builds a GRAPH COMPONENTS <edge_table> statement for native connected-
components detection.
Passes through a raw query string without modification.
Builds a RELATE statement to create a graph edge between two records.
Builds a REMOVE INDEX statement that drops a secondary index and all of
its catalog entries. Subsequent queries fall back to full scans.
Builds a SELECT statement with optional clauses.
Builds an UPDATE statement for an existing record.
Builds an UPDATE <table> SET ... WHERE <clause> statement that updates
every row matching the (already-built) WHERE clause.
Builds a CREATE ... ON CONFLICT UPDATE statement for idempotent upserts.
Types
Functions
Builds a COUNT <table> [WHERE <clause>] statement.
Options
:where- optional WHERE clause string
Examples
iex> Dllb.Query.count("user")
"COUNT user"
iex> Dllb.Query.count("user", where: "age = 30")
"COUNT user WHERE age = 30"
Builds a CREATE statement for inserting a new record.
Examples
iex> Dllb.Query.create("user", %{name: "Alice", age: 30})
"CREATE user SET age = 30, name = 'Alice'"
Builds a CREATE statement with an explicit record ID.
Examples
iex> Dllb.Query.create_with_id("user", "u1", %{name: "Alice"})
"CREATE user:u1 SET name = 'Alice'"
Builds a DEFINE FIELD statement.
Options
:required- iftrue, appends ASSERT $value IS NOT NONE
Examples
iex> Dllb.Query.define_field("user", "name", "string", required: true)
"DEFINE FIELD name ON user TYPE string ASSERT $value IS NOT NONE"
Builds a DEFINE INDEX statement that registers a persisted secondary
index in the engine's catalog and backfills entries for existing rows.
The index covers one or more fields. Composite (multi-field) indexes are
matched by the engine using leftmost-prefix planning, so list the most
selective leading field first. Once defined, equality and range
(>, >=, <, <=) predicates on the indexed fields are transparently
accelerated in SELECT/COUNT/UPDATE WHERE clauses — no change to the
query strings is required.
Options
:unique- whentrue, enforces uniqueness over the full indexed tuple; defining the index fails if existing rows already hold duplicate values (defaultfalse)
Examples
iex> Dllb.Query.define_index("user", "by_age", ["age"])
"DEFINE INDEX by_age ON TABLE user FIELDS age"
iex> Dllb.Query.define_index("user", "by_email", ["email"], unique: true)
"DEFINE INDEX by_email ON TABLE user FIELDS email UNIQUE"
iex> Dllb.Query.define_index("ast_node", "idx_file_kind", ["file_path", "kind"])
"DEFINE INDEX idx_file_kind ON TABLE ast_node FIELDS file_path, kind"
Builds a DEFINE TABLE statement.
Mode can be :schemafull or :schemaless.
Examples
iex> Dllb.Query.define_table("user", :schemafull)
"DEFINE TABLE user SCHEMAFULL"
Builds a DELETE statement for a record.
Examples
iex> Dllb.Query.delete("user:u1")
"DELETE user:u1"
Builds a GRAPH COMMUNITIES statement for native community detection.
Delegates computation to the dllb engine (Rust Louvain / Label Propagation), which runs in O(E) per iteration — orders of magnitude faster than the equivalent pure-Elixir implementation on large graphs.
Options
:algorithm-:louvain(default) or:lp(label propagation):max_iter- maximum optimisation passes (default: 10):resolution- Louvain resolution γ; values < 1.0 → fewer, larger communities; > 1.0 → more, smaller communities (default: 1.0)
Examples
iex> Dllb.Query.graph_communities("calls")
"GRAPH COMMUNITIES calls"
iex> Dllb.Query.graph_communities("calls", algorithm: :lp, max_iter: 20)
"GRAPH COMMUNITIES calls ALGORITHM lp MAX_ITER 20"
iex> Dllb.Query.graph_communities("calls", algorithm: :louvain, resolution: 0.5)
"GRAPH COMMUNITIES calls ALGORITHM louvain RESOLUTION 0.5"
Builds a GRAPH COMPONENTS <edge_table> statement for native connected-
components detection.
Delegates computation to the dllb engine (Rust union-find over the edge
table, treated as undirected). The server returns a compact summary
(component_count, largest, nodes) rather than full membership.
Examples
iex> Dllb.Query.graph_components("calls")
"GRAPH COMPONENTS calls"
Passes through a raw query string without modification.
Examples
iex> Dllb.Query.raw("INFO FOR DB")
"INFO FOR DB"
Builds a RELATE statement to create a graph edge between two records.
Examples
iex> Dllb.Query.relate("user:a", "follows", "user:b", %{since: "2024"})
"RELATE user:a->follows->user:b SET since = '2024'"
Builds a REMOVE INDEX statement that drops a secondary index and all of
its catalog entries. Subsequent queries fall back to full scans.
Examples
iex> Dllb.Query.remove_index("user", "by_age")
"REMOVE INDEX by_age ON TABLE user"
@spec select(String.t(), select_opts()) :: String.t()
Builds a SELECT statement with optional clauses.
Options
:fields- list of field names to select (default["*"]):where- WHERE clause string:order- ORDER BY clause string:limit- LIMIT value:fetch- graph traversal fetch clause (e.g."->calls->fn_node")
Examples
iex> Dllb.Query.select("user", where: "age > 25", limit: 10)
"SELECT * FROM user WHERE age > 25 LIMIT 10"
Builds an UPDATE statement for an existing record.
Examples
iex> Dllb.Query.update("user:u1", %{name: "Bob"})
"UPDATE user:u1 SET name = 'Bob'"
Builds an UPDATE <table> SET ... WHERE <clause> statement that updates
every row matching the (already-built) WHERE clause.
Only the listed fields are changed (partial-update semantics). An empty WHERE string updates all rows in the table.
Examples
iex> Dllb.Query.update_where("ast_node", %{arity: 1}, "kind = 'function_def'")
"UPDATE ast_node SET arity = 1 WHERE kind = 'function_def'"
Builds a CREATE ... ON CONFLICT UPDATE statement for idempotent upserts.
If the record already exists (by table + id), the conflict is resolved by updating it instead of failing:
- with no
update_fields(or an empty map), the engine merges the samefieldsfrom the CREATE into the existing record (ON CONFLICT UPDATE); - with a non-empty
update_fieldsmap, the engine applies those explicit fields to the existing record instead (ON CONFLICT UPDATE SET ...).
Examples
iex> Dllb.Query.upsert("user", "u1", %{name: "Alice", age: 30})
"CREATE user:u1 SET age = 30, name = 'Alice' ON CONFLICT UPDATE"
iex> Dllb.Query.upsert("user", "u1", %{name: "Alice", age: 30}, %{age: 31})
"CREATE user:u1 SET age = 30, name = 'Alice' ON CONFLICT UPDATE SET age = 31"