Skip to main content
Version: v0.24.0

SQL access

SQLite is Zova's relational core. Use ordinary SQL for application tables and metadata, then use Zova's connection-local SQL helpers when specialized results need to join back to those records.

Ordinary SQL stays ordinary​

Prepared statements are the preferred interface for values:

select id, title, object_id
from documents
where owner_id = ?1
and archived = 0
order by created_at desc;

Indexes, query plans, constraints, views, triggers, and PRAGMAs retain their SQLite behavior. Zova does not introduce a parallel query language for records.

Private _zova_* tables are not a public SQL API. Their shape can change with the file format. Use bindings or documented virtual tables instead of querying them directly.

Vector distance in an expression​

Zova registers scalar distance helpers on connections it opens:

zova_vector_distance(collection, vector_id, query_vector_blob)
zova_vector_distance_by_id(collection, vector_id, source_vector_id)

This form works well when SQL has already selected a small candidate set:

select
c.id,
c.body,
zova_vector_distance('chunks', c.vector_id, ?1) as distance
from chunks as c
where c.document_id = ?2
order by distance
limit 10;

Here SQLite filters by document_id first, then Zova calculates distance only for matching vector IDs. Confirm the query plan and candidate count for your workload; a scalar function is not an approximate vector index.

Ranked vector search as a table​

Use zova_vector_search when ranking should produce the candidate set:

select
c.id,
c.document_id,
c.body,
s.distance
from zova_vector_search as s
join chunks as c on c.vector_id = s.vector_id
where s.collection = 'chunks'
and s.query_vector = ?1
and s.top_k = 10
order by s.rank;

The virtual table exposes vector IDs, distances, and deterministic rank. Joining on an indexed vector_id column reconnects ranking to application metadata without copying every record into application code.

For f32 collections, query blobs contain little-endian f32 values. f16 uses little-endian u16 bit patterns and i8 uses raw signed bytes.

Graph adjacency as a table​

zova_graph_neighbors returns one-hop results:

select d.id, d.title, g.edge_type
from zova_graph_neighbors as g
join documents as d on d.graph_node_id = g.node_id
where g.graph_name = 'default'
and g.source_node_id = ?1
and g.direction = 'outgoing'
and g."limit" = 20
order by g.rank;

zova_graph_walk performs a bounded walk and returns the start node plus reachable nodes:

select node_id, depth, predecessor_node_id, edge_type
from zova_graph_walk
where graph_name = 'default'
and start_node_id = ?1
and max_depth = 2
and "limit" = 50
order by rank;

Use explicit limits and depth bounds. Joining graph IDs back to application tables remains your schema design responsibility.

Connection-local registration​

The scalar functions and virtual tables are registered on SQLite connections opened through Zova. A generic SQLite client can inspect your public tables, but it will not automatically know zova_vector_search or zova_graph_walk.

This boundary is important when using pools, migration tools, or external analytics software: run Zova-specific queries through a Zova-owned connection and keep portable application SQL independent where practical.

Inspect page usage with dbstat​

Zova's bundled SQLite enables the read-only dbstat virtual table for storage diagnostics:

select name, sum(pgsize) as bytes
from dbstat
group by name
order by bytes desc;

dbstat exposes page-level implementation details, not a stable Zova schema contract. Use it to measure and diagnose storage, but do not build application behavior around private _zova_* table names. Availability is guaranteed only on SQLite bundled with Zova; an unrelated system SQLite build may omit it.

Query design guidance​

  • Use SQL-first ranking when indexed metadata produces a small candidate set.
  • Use vector-first ranking when similarity should produce the candidates.
  • Use graph virtual tables when traversal results must join directly to records.
  • Keep user-controlled values in bound parameters.
  • Order by the provided rank when deterministic traversal or search order matters.
  • Inspect SQLite query plans for joins on application tables.

Continue with Vector search or Graph traversal for complete query workflows.