# `Dllb.MetaAST.Query`
[🔗](https://github.com/Oeditus/dllb_ex/blob/v0.9.0/lib/dllb/meta_ast/query.ex#L1)

Domain-aware query builders for MetaAST data stored in dllb.

Every function returns a plain query string (or list of query strings)
ready to be sent through `Dllb.query/1` or `Dllb.batch/1`. Higher-level
`exec_*` variants accept a query function and return parsed results via
`Dllb.MetaAST.from_dllb_row/1`.

## Query categories

  - **Node queries** -- find/list AST nodes by file, kind, module, or composite key
  - **Graph traversals** -- callers, callees, importers, imports, call chains
  - **Search** -- HNSW vector similarity, full-text BM25, hybrid
  - **Lifecycle** -- delete by file/project, stats
  - **Tree reconstruction** -- rebuild MetaAST 3-tuples from stored data

# `ast_clones`

```elixir
@spec ast_clones(
  [String.t() | Dllb.MetaAST.meta_ast_node()],
  keyword()
) :: String.t()
```

Detects near-duplicate (fuzzy) clones among the given AST trees using the
server-side `ast::clones` function -- the native-Rust counterpart to
`Dllb.MetaAST.Similarity.find_clones/2`.

`asts` is a list of serialized JSON strings and/or Metastatic AST node
3-tuples (tuples are automatically serialized). Every `SELECT` requires a
`FROM` target, so this anchors on an arbitrary row of `ast_node` (its
stored content is not inspected) -- at least one row must already exist
in the table. The result row carries a `clones` field: a JSON-encoded
list of `%{"index_a" => i, "index_b" => j, "similarity" => score}` pairs.

## Options

  * `:threshold` - minimum similarity to report (default 0.8)

# `ast_diff`

```elixir
@spec ast_diff(
  String.t() | Dllb.MetaAST.meta_ast_node(),
  keyword()
) :: String.t()
```

Computes a structural diff between each AST node's stored tree and a
`target` tree, using the server-side `ast::diff` function (native Rust) --
the engine-side counterpart to `Dllb.MetaAST.Diff.diff_trees/2`.

The `target` can be a serialized JSON string or a Metastatic AST node
3-tuple (which will be automatically serialized to JSON). Each result row
carries a `diff` field: a JSON-encoded summary with `changes`, `added`,
`removed`, `modified`, and `renamed` keys.

Prefer `Dllb.MetaAST.Diff.diff_trees/2` for a purely client-side diff (no
round-trip); use this to delegate the comparison to already-indexed,
server-side ASTs.

## Options

  * `:limit` - max results (default 10)
  * `:kind` / `:file_path` / `:language` / `:project_path` - scope filters

# `ast_scope`

```elixir
@spec ast_scope(String.t(), non_neg_integer()) :: String.t()
```

Finds the AST scope path (outermost to innermost node containing `line`)
within a single stored AST node's tree, using the server-side `ast::scope`
function -- the engine-side counterpart to
`Dllb.MetaAST.QueryHelpers.scope_at/2`.

`record_id` must be a full `table:id` reference, e.g. one returned by
`find_function/3` or `find_module/1`. The result row carries a `scope`
field: a JSON-encoded array of nodes, outermost first.

# `call_chain`

```elixir
@spec call_chain(String.t(), pos_integer()) :: String.t()
```

Multi-hop call chain traversal from a starting node.

Builds a chained `->calls->ast_node` traversal repeated `depth` times.

# `callees_of`

```elixir
@spec callees_of(String.t()) :: String.t()
```

Graph traversal: find all callees of a node (outgoing `calls` edges).

# `callers_of`

```elixir
@spec callers_of(String.t()) :: String.t()
```

Graph traversal: find all callers of a node (incoming `calls` edges).

Returns a SELECT with `<-calls<-ast_node` traversal syntax.

# `complex_functions`

```elixir
@spec complex_functions(
  pos_integer(),
  keyword()
) :: String.t()
```

Find AST nodes with cyclomatic complexity above a threshold,
using the server-side `ast::complexity` function.

## Options

  * `:limit` - max results (default 10)
  * `:kind` / `:file_path` / `:language` / `:project_path` - scope filters

# `count_embeddings_query`

```elixir
@spec count_embeddings_query() :: String.t()
```

Returns a `COUNT` query for `ast_node` rows that have a `source_embedding`
set -- i.e. the number of stored embedding vectors.

# `delete_by_file`

```elixir
@spec delete_by_file(String.t()) :: String.t()
```

Builds a single-statement `DELETE ast_node WHERE file_path = ...` that
removes every node belonging to a file in one server-side operation
(secondary, full-text, and vector indexes are maintained by the engine).
Pair with `exec_delete_by_file/2`.

# `delete_by_project`

```elixir
@spec delete_by_project(String.t()) :: String.t()
```

Builds a single-statement `DELETE ast_node WHERE project_path = ...` that
removes every node of a project in one server-side operation. Pair with
`exec_delete_by_project/2`.

# `duplicate_code`

```elixir
@spec duplicate_code(keyword()) :: String.t()
```

Find duplicate code structures that share the same Zobrist-style structural hash
using the server-side `ast::hash` function.

Returns a query that groups nodes by their structural hash and finds groups
with more than one node.

## Options

  * `:limit` - max results (default 20)
  * `:kind` / `:file_path` / `:language` / `:project_path` - scope filters

# `exec`

```elixir
@spec exec(String.t(), Dllb.MetaAST.query_fn()) :: {:ok, [map()]} | {:error, term()}
```

Executes a query through `query_fn` and returns parsed result maps.

# `exec_count`

```elixir
@spec exec_count(String.t(), Dllb.MetaAST.query_fn()) ::
  {:ok, non_neg_integer()} | {:error, term()}
```

Executes a `COUNT` query and returns `{:ok, count}` or `{:error, reason}`.

# `exec_count_embeddings`

```elixir
@spec exec_count_embeddings(Dllb.MetaAST.query_fn()) ::
  {:ok, non_neg_integer()} | {:error, term()}
```

Counts stored embedding vectors (`ast_node` rows with `source_embedding`).

# `exec_delete_by_file`

```elixir
@spec exec_delete_by_file(String.t(), Dllb.MetaAST.query_fn()) ::
  {:ok, non_neg_integer()} | {:error, term()}
```

Executes a native delete-by-file (`DELETE ... WHERE`) in a single
round-trip, returning `{:ok, count}` (rows removed) or `{:error, reason}`.

# `exec_delete_by_project`

```elixir
@spec exec_delete_by_project(String.t(), Dllb.MetaAST.query_fn()) ::
  {:ok, non_neg_integer()} | {:error, term()}
```

Executes a native delete-by-project (`DELETE ... WHERE`) in a single
round-trip, returning `{:ok, count}` or `{:error, reason}`.

# `exec_load_file_nodes`

```elixir
@spec exec_load_file_nodes(String.t(), Dllb.MetaAST.query_fn()) ::
  {:ok, [map()]} | {:error, term()}
```

Loads all nodes for a file and returns them as parsed maps.

# `exec_stats`

```elixir
@spec exec_stats(Dllb.MetaAST.query_fn()) :: {:ok, map()} | {:error, term()}
```

Executes the grouped stats query and returns
`{:ok, %{total: n, by_kind: %{kind => count}}}`.

The grouped rows carry serde-tagged values (e.g. `%{"String" => "..."}`),
which are unwrapped here into plain kinds and integer counts.

# `find_function`

```elixir
@spec find_function(String.t(), String.t(), non_neg_integer()) :: String.t()
```

SELECT a function node by module, name, and arity.

# `find_module`

```elixir
@spec find_module(String.t()) :: String.t()
```

SELECT a module (container) node by name.

# `functions_of_module`

```elixir
@spec functions_of_module(
  String.t(),
  keyword()
) :: String.t()
```

SELECT function nodes belonging to a module.

Requires the `module` field to be populated during ingestion.

# `hybrid_search`

```elixir
@spec hybrid_search(String.t(), [number()], keyword()) :: String.t()
```

Combined full-text + vector hybrid search via the engine's native
`HYBRID SEARCH` verb: BM25 on `source_text` fused with HNSW on
`source_embedding`. Each row carries `score`, `text_score`, and
`vector_score`.

## Options

  * `:limit` - max results (default 10)
  * `:alpha` - weight on the text score in `0.0..1.0` (default 0.5); the
    vector score gets `1 - alpha`
  * `:kind` / `:file_path` / `:language` / `:project_path` - optional scope
    filters

# `importers_of`

```elixir
@spec importers_of(String.t()) :: String.t()
```

Graph traversal: find all modules that import a given node.

# `imports_of`

```elixir
@spec imports_of(String.t()) :: String.t()
```

Graph traversal: find all imports of a node.

# `nodes_by_file`

```elixir
@spec nodes_by_file(
  String.t(),
  keyword()
) :: String.t()
```

SELECT all AST nodes belonging to a file.

# `nodes_by_kind`

```elixir
@spec nodes_by_kind(
  String.t(),
  keyword()
) :: String.t()
```

SELECT all AST nodes of a given kind (e.g. `"function_def"`, `"container"`).

# `nodes_by_project`

```elixir
@spec nodes_by_project(
  String.t(),
  keyword()
) :: String.t()
```

SELECT nodes filtered by project path.

# `restore_source_index`

```elixir
@spec restore_source_index() :: String.t()
```

Restore the source embedding HNSW index from its latest snapshot.

# `restore_structure_index`

```elixir
@spec restore_structure_index() :: String.t()
```

Restore the structure embedding HNSW index from its latest snapshot.

# `search_docs`

```elixir
@spec search_docs(
  String.t(),
  keyword()
) :: String.t()
```

Full-text BM25 search on `docstring`, built with the engine's native
`SEARCH` verb. Each row carries a `score`.

## Options

  * `:limit` - max results (default 20)

# `search_source`

```elixir
@spec search_source(
  String.t(),
  keyword()
) :: String.t()
```

Full-text BM25 search on `source_text`, built with the engine's native
`SEARCH` verb. Each row carries a `score`. Requires a full-text index on
`source_text`.

## Options

  * `:limit` - max results (default 20)
  * `:kind` / `:file_path` / `:language` / `:project_path` - optional scope
    filters

# `set_source_embedding`

```elixir
@spec set_source_embedding(map(), [number()]) :: String.t()
```

Builds an `UPDATE ast_node SET source_embedding = [...] WHERE <attrs>`
statement that attaches an embedding to the row(s) identified by `attrs`.

`attrs` is a map of column => value (e.g. `%{kind: "function_def",
module: "Foo", name: "bar", arity: 2}`). `nil` values are dropped and the
remaining columns are ANDed together (sorted for determinism). Targeting by
stable attributes avoids reconstructing synthetic record IDs.

# `set_structure_embedding`

```elixir
@spec set_structure_embedding(map(), [number()]) :: String.t()
```

Sets the structure embedding for AST nodes matching the given attributes.

`attrs` is a map of column => value used to identify the target rows.

# `similar_by_ast`

```elixir
@spec similar_by_ast(
  String.t() | Dllb.MetaAST.meta_ast_node(),
  keyword()
) :: String.t()
```

Find structurally similar AST nodes using the server-side `ast::similarity` function.

The `target` can be a serialized JSON string or a Metastatic AST node 3-tuple
(which will be automatically serialized to JSON).

## Options

  * `:limit` - max results (default 10)
  * `:threshold` - minimum similarity score between 0.0 and 1.0 (default 0.8)
  * `:kind` / `:file_path` / `:language` / `:project_path` - scope filters

# `similar_to`

```elixir
@spec similar_to(
  [number()],
  keyword()
) :: String.t()
```

Vector (HNSW) similarity search over `source_embedding`, built with the
engine's native `VECTOR SEARCH` verb. Results come back nearest-first, each
row carrying a `distance` field. Requires a vector index on
`source_embedding` (see `Dllb.Schema.ast_node_search_indexes/0`).

## Options

  * `:limit` - max results (default 10)
  * `:kind` - optional kind filter (scopes results server-side)
  * `:file_path` - optional file filter
  * `:language` - optional language filter
  * `:project_path` - optional project filter (multi-project isolation)

# `snapshot_source_index`

```elixir
@spec snapshot_source_index() :: String.t()
```

Trigger a snapshot of the source embedding HNSW index to persistent storage.

# `snapshot_structure_index`

```elixir
@spec snapshot_structure_index() :: String.t()
```

Trigger a snapshot of the structure embedding HNSW index to persistent storage.

# `source_index_info`

```elixir
@spec source_index_info() :: String.t()
```

Get info about the source embedding HNSW index.

# `stats_query`

```elixir
@spec stats_query() :: String.t()
```

Returns a `COUNT ast_node GROUP BY kind` query: one row per kind, each
carrying a `count`, aggregated server-side.

# `structurally_similar_to`

```elixir
@spec structurally_similar_to(
  [number()],
  keyword()
) :: String.t()
```

Find structurally similar AST nodes using `structure_embedding` vector search.

Requires a vector index on `structure_embedding` and that structure embeddings
have been generated (via `Dllb.MetaAST.Similarity.subtree_hash/1` or a
learned embedding).

## Options

  * `:limit` - max results (default 10)
  * `:kind` / `:file_path` / `:language` / `:project_path` - scope filters

# `structure_index_info`

```elixir
@spec structure_index_info() :: String.t()
```

Get info about the structure embedding HNSW index.

---

*Consult [api-reference.md](api-reference.md) for complete listing*
