Table of Contents

Class EdgeVectorSchema

Namespace
Qavren.Edge.VectorData
Assembly
Qavren.Edge.VectorData.dll

The DDL and the queries as plain strings, so a consumer can read, log or hand-execute exactly what the provider runs - the same visible-SQL contract as sub-project 1's helpers.

Nothing here opens a connection or executes anything. Every statement is emitted with \n line endings so the text is identical on every platform.

public sealed class EdgeVectorSchema
Inheritance
EdgeVectorSchema
Inherited Members

Constructors

EdgeVectorSchema(CollectionModel, string, EdgeVectorStoreOptions?, bool)

Builds the schema for one collection.

Fields

FilterPlaceholder

The token BuildKnnSql(bool, bool, bool) and BuildHybridRrfSql(bool, bool) leave where the translated filter predicate goes. The caller substitutes the SQL that EdgeFilterTranslator produced; the surrounding rowid IN (SELECT "_rowid" FROM <data table> WHERE ...) is already in place, which is what makes an arbitrary MEVD filter a true vec0 pre-filter.

VectorColumnName

The vec0 vector column. Fixed, not derived from the property's storage name: a vec0 table holds exactly one vector column, and every query in this file names it.

Properties

CollectionName

The collection name.

DataTable

The data table - the collection name, verbatim.

Dimensions

The declared vector width.

FullTextColumns

The storage names of the full-text-indexed data properties, in model order.

FullTextTable

The FTS5 sidecar, or null when the collection has no full-text property.

KeyColumn

The storage name of the key property.

RowIdColumn

Always _rowid: the INTEGER PRIMARY KEY all three tables join on.

VectorColumn

Always embedding: the single vec0 vector column.

VectorTable

The vec0 virtual table.

Methods

BuildCreateSql()

Emits the create-collection statements. See the static overload for the order.

BuildCreateSql(CollectionModel, string, EdgeVectorStoreOptions?)

The create-collection statements, in execution order: data table, key index, one index per IsIndexed property, the vec0 table, the FTS5 sidecar, its three sync triggers, and the vec0 delete cascade.

BuildDropSql()

The drop statements, in the reverse of BuildCreateSql()'s order. The triggers go first because a trigger on a dropped table is an error on some paths and a silent orphan on others; the FTS5 sidecar goes before its content table because dropping an external-content table first leaves FTS5's shadow tables referring to nothing. Dropping the vec0 virtual table also drops its four shadow tables, which is what vec0's own destructor is for, so none of them is named here.

BuildHybridRrfSql(bool, bool)

The hybrid query: a vec0 KNN lane and an FTS5 bm25 lane, fused by reciprocal rank.

Both lanes rank ascending. FTS5's bm25() is the standard score multiplied by -1, so a better match is numerically lower, and vec0's distance is a distance. The hidden rank column is used rather than calling bm25(f), which SQLite's own docs say is faster.

The keyword lane says f."<fts table>" MATCH $keywords - the alias qualifying the table-named hidden column - and not the bare alias f MATCH $keywords. FTS5 gives every table a hidden column named after the table, and <x> MATCH <expr> is an ordinary comparison against a column, so a bare alias resolves as a column reference and SQLite answers no such column: f. Measured against SQLite 3.53.4 + FTS5 on 2026-09-11; spec 13.3's claim that the bare alias is the only spelling that parses is wrong in both directions, and the spec is the side that is being corrected.

The fused score is a similarity - higher is better - the opposite polarity to BuildKnnSql(bool, bool, bool)'s distance.

BuildKnnSql(bool, bool, bool)

The vec0 KNN query. The filter, when present, is pushed in as v.rowid IN (SELECT "_rowid" FROM <data table> WHERE ...): vec0's BestIndex claims a rowid IN (...) constraint with omit = 1 and ANDs the bitmap into the chunk validity bitmap before any distance is computed, so this is a true pre-filter and never degrades to a client-side pass.

BuildMatchExpression(ICollection<string>, KeywordCombinator, string?)

Quotes each keyword as an FTS5 string literal, doubling any embedded quote, and joins them. Quoting is what makes FTS5 treat a token as a phrase, so AND, OR, NOT, NEAR, *, ^, : and parentheses inside a keyword are inert rather than operators. This is the package's one injection surface.

BuildUpsertSql()

The record write. INTEGER PRIMARY KEY is a true rowid alias and is stable across ON CONFLICT DO UPDATE, so the returned _rowid is the same integer the vec0 and FTS5 sides are keyed on.