store

package
v0.11.1 Latest Latest
Warning

This package is not in the latest version of its module.

Go to latest
Published: Sep 13, 2026 License: Apache-2.0 Imports: 12 Imported by: 0

Documentation

Overview

Package store — FTS5 search methods.

These methods implement the search pipeline from src/db/queries.ts's QueryBuilder.searchNodes (FTS5 BM25 → LIKE fallback → fuzzy Levenshtein, plus an exact-name supplement). They belong in store because the SQL lives here; the scoring/rescoring logic lives in the query package.

Package store implements the .codegraph SQLite knowledge-graph store: nodes, edges, files, unresolved references, and project metadata, plus the FTS5 search index maintained by schema triggers.

Ported from src/db/ of github.com/colbymchenry/codegraph (MIT). The schema (schema.sql) is copied verbatim from the original so indexes remain conceptually compatible; the SQLite driver is modernc.org/sqlite (pure Go, FTS5 included) per ADR-001's pure-Go mandate.

Like the original (one node:sqlite handle), the Store uses a single connection; concurrent use is safe via database/sql's serialization plus WAL mode and busy_timeout.

Index

Constants

View Source
const CurrentSchemaVersion = 8

CurrentSchemaVersion mirrors CURRENT_SCHEMA_VERSION in the original.

View Source
const DatabaseFilename = "codegraph.db"

DatabaseFilename is the on-disk name of the index database.

Variables

This section is empty.

Functions

func EdgeKey added in v0.5.0

func EdgeKey(e model.Edge) string

Types

type CoverageRow

type CoverageRow struct {
	FilePath       string
	ContentHash    string
	Mode           string
	Ranges         string
	LinesCovered   int
	LinesUncovered int
	PctCovered     float64
	RunAt          int64
}

CoverageRow is a per-file line-coverage record (the `coverage` table). It is the store's own row type so the store package stays free of any dependency on the coverage package (which itself imports store); the coverage package converts to/from its own coverage.FileCoverage.

Ranges is the RLE JSON string exactly as stored ([[start,end,"hit"|"miss"],…]); the store treats it as an opaque blob.

type GraphStats

type GraphStats struct {
	NodeCount       int                    `json:"nodeCount"`
	EdgeCount       int                    `json:"edgeCount"`
	FileCount       int                    `json:"fileCount"`
	NodesByKind     map[model.NodeKind]int `json:"nodesByKind"`
	EdgesByKind     map[model.EdgeKind]int `json:"edgesByKind"`
	FilesByLanguage map[model.Language]int `json:"filesByLanguage"`
	DBSizeBytes     int64                  `json:"dbSizeBytes"`
	LastUpdated     int64                  `json:"lastUpdated"`
}

GraphStats summarizes the index, mirroring GraphStats in the original. DBSizeBytes is filled by the caller (Store.Size) like the original.

type NodeCoverageRow

type NodeCoverageRow struct {
	NodeID         string
	ContentHash    string
	LinesCovered   int
	LinesUncovered int
	PctCovered     float64
	RunAt          int64
}

NodeCoverageRow is a per-function innermost-attributed coverage record (the `node_coverage` table). Store-local row type, see CoverageRow.

type NowFunc

type NowFunc func() int64

NowFunc returns the current time in Unix milliseconds. Injectable for tests.

type Option

type Option func(*Store)

Option configures a Store.

func WithNowFunc

func WithNowFunc(now NowFunc) Option

WithNowFunc injects the clock used for updated_at/applied_at timestamps.

type Store

type Store struct {
	// contains filtered or unexported fields
}

Store is an open codegraph index database.

func Initialize

func Initialize(path string, opts ...Option) (*Store, error)

Initialize creates a new database at path (parent directories included), applies the schema, and records the current schema version.

func Open

func Open(path string, opts ...Option) (*Store, error)

Open opens an existing database and applies any pending migrations.

func (*Store) AllEdges

func (s *Store) AllEdges() ([]model.Edge, error)

AllEdges returns every edge in the store.

func (*Store) AllNodes

func (s *Store) AllNodes() ([]model.Node, error)

AllNodes returns every node in the store ordered by id.

func (*Store) Clear

func (s *Store) Clear() error

Clear deletes all graph data (nodes, edges, files, unresolved refs).

func (*Store) ClearUnresolvedReferences

func (s *Store) ClearUnresolvedReferences() error

ClearUnresolvedReferences deletes all unresolved references.

func (*Store) Close

func (s *Store) Close() error

Close closes the database.

func (*Store) DeleteEdgesBySource

func (s *Store) DeleteEdgesBySource(sourceID string) error

DeleteEdgesBySource removes all outgoing edges of a node.

func (*Store) DeleteFile

func (s *Store) DeleteFile(filePath string) error

DeleteFile removes a file record and all nodes extracted from it.

func (*Store) DeleteNode

func (s *Store) DeleteNode(id string) error

DeleteNode deletes a node by ID (edges cascade via FK).

func (*Store) DeleteNodesByFile

func (s *Store) DeleteNodesByFile(filePath string) error

DeleteNodesByFile deletes every node extracted from filePath.

func (*Store) DeleteUnresolvedByNode

func (s *Store) DeleteUnresolvedByNode(nodeID string) error

DeleteUnresolvedByNode removes references originating from nodeID.

func (*Store) EdgeExists added in v0.5.0

func (s *Store) EdgeExists(e model.Edge) (bool, error)

EdgeExists reports whether this exact persisted relationship survived a replacement. It is used by incremental reindexing to distinguish a stable node ID reinserted after cascading edge deletion from an unchanged edge.

func (*Store) ExactNameCaseInsensitive

func (s *Store) ExactNameCaseInsensitive(
	term string,
	kinds []model.NodeKind,
	langs []model.Language,
	limit int,
) ([]model.Node, error)

ExactNameCaseInsensitive finds nodes whose name matches term (case-insensitive).

func (*Store) ExactNameCaseInsensitiveFiltered added in v0.5.0

func (s *Store) ExactNameCaseInsensitiveFiltered(term string, kinds []model.NodeKind, langs []model.Language, limit int, filters SymbolFilters) ([]model.Node, error)

func (*Store) ExistingEdgeKeys added in v0.5.0

func (s *Store) ExistingEdgeKeys(sourceIDs []string) (map[string]bool, error)

ExistingEdgeKeys loads persisted edge identities for all sources in one query, avoiding one existence probe per restored incoming edge.

func (*Store) ExistingNodeIDs

func (s *Store) ExistingNodeIDs(ids []string) (map[string]struct{}, error)

ExistingNodeIDs returns the subset of ids that exist in the store.

func (*Store) FindEdgesBetweenNodes

func (s *Store) FindEdgesBetweenNodes(nodeIDs []string, kinds []model.EdgeKind) ([]model.Edge, error)

FindEdgesBetweenNodes returns all edges whose source AND target are both in nodeIDs (uses json_each like the original to stay under param limits).

func (*Store) GetAllCoverage

func (s *Store) GetAllCoverage() ([]CoverageRow, error)

GetAllCoverage returns every per-file coverage row ordered by file path.

func (*Store) GetAllFiles

func (s *Store) GetAllFiles() ([]model.FileRecord, error)

GetAllFiles returns every tracked file ordered by path.

func (*Store) GetAllMetadata

func (s *Store) GetAllMetadata() (map[string]string, error)

GetAllMetadata returns every metadata key-value pair.

func (*Store) GetAllNodeCoverage

func (s *Store) GetAllNodeCoverage() ([]NodeCoverageRow, error)

GetAllNodeCoverage returns every per-node coverage row ordered by node id.

func (*Store) GetCoverageByFile

func (s *Store) GetCoverageByFile(filePath string) (*CoverageRow, error)

GetCoverageByFile returns the coverage row for a file, or nil if absent.

func (*Store) GetDependencyFilePaths

func (s *Store) GetDependencyFilePaths(filePath string) ([]string, error)

GetDependencyFilePaths returns file paths of files depended on by filePath via the resolved symbol edge graph (calls/references/etc. cross-file edges).

func (*Store) GetDependentFilePaths

func (s *Store) GetDependentFilePaths(filePath string) ([]string, error)

GetDependentFilePaths returns file paths of files that depend on filePath.

func (*Store) GetFileByPath

func (s *Store) GetFileByPath(filePath string) (*model.FileRecord, error)

GetFileByPath returns a file record, or nil if untracked.

func (*Store) GetIncomingEdges

func (s *Store) GetIncomingEdges(targetID string, kinds []model.EdgeKind) ([]model.Edge, error)

GetIncomingEdges returns edges into targetID, optionally filtered by kinds.

func (*Store) GetIncomingEdgesForTargetFiles added in v0.5.0

func (s *Store) GetIncomingEdgesForTargetFiles(paths []string) ([]model.Edge, error)

GetIncomingEdgesForTargetFiles loads all incoming edges for a changed-file batch in one joined query. Incremental sync uses this instead of one query per target symbol (and then one per source edge).

func (*Store) GetIncomingEdgesLimited added in v0.5.0

func (s *Store) GetIncomingEdgesLimited(targetID string, limit int) ([]model.Edge, error)

func (*Store) GetLastIndexedAt

func (s *Store) GetLastIndexedAt() (int64, error)

GetLastIndexedAt returns the most recent indexed_at across all files in ms, or 0 when nothing is indexed yet.

func (*Store) GetMetadata

func (s *Store) GetMetadata(key string) (string, error)

GetMetadata returns a project metadata value, or "" if absent.

func (*Store) GetNodeByID

func (s *Store) GetNodeByID(id string) (*model.Node, error)

GetNodeByID fetches one node, or nil if absent.

func (*Store) GetNodesByFile

func (s *Store) GetNodesByFile(filePath string) ([]model.Node, error)

GetNodesByFile returns all nodes in a file ordered by start line.

func (*Store) GetNodesByIDs

func (s *Store) GetNodesByIDs(ids []string) (map[string]model.Node, error)

GetNodesByIDs batch-fetches nodes, returned as a map keyed by ID. Missing IDs are simply absent.

func (*Store) GetNodesByLowerName

func (s *Store) GetNodesByLowerName(lowerName string) ([]model.Node, error)

GetNodesByLowerName returns nodes matching lower(name) = lowerName (uses the idx_nodes_lower_name expression index).

func (*Store) GetNodesByName

func (s *Store) GetNodesByName(name string) ([]model.Node, error)

GetNodesByName returns all nodes with the exact name.

func (*Store) GetNodesByQualifiedNameExact

func (s *Store) GetNodesByQualifiedNameExact(qualifiedName string) ([]model.Node, error)

GetNodesByQualifiedNameExact returns nodes whose qualified name matches exactly.

func (*Store) GetNodesByQualifiedNameSuffix added in v0.5.0

func (s *Store) GetNodesByQualifiedNameSuffix(qualifiedName string) ([]model.Node, error)

GetNodesByQualifiedNameSuffix finds lexical qualified names at the end of a package/module-qualified selector. It lets callers accept both Foo::Bar and package/path.Foo.Bar without broad fuzzy source selection.

func (*Store) GetOutgoingEdges

func (s *Store) GetOutgoingEdges(sourceID string, kinds []model.EdgeKind, provenance string) ([]model.Edge, error)

GetOutgoingEdges returns edges from sourceID, optionally filtered by kinds and provenance.

func (*Store) GetOutgoingEdgesByKindLimited added in v0.10.0

func (s *Store) GetOutgoingEdgesByKindLimited(sourceID string, kinds []model.EdgeKind, limit int) ([]model.Edge, error)

GetOutgoingEdgesByKindLimited is the bounded equivalent of GetOutgoingEdges for graph traversals. It keeps traversal limits meaningful even for a single high-fan-out source.

func (*Store) GetOutgoingEdgesLimited added in v0.5.0

func (s *Store) GetOutgoingEdgesLimited(sourceID string, limit int) ([]model.Edge, error)

GetOutgoingEdgesLimited returns deterministic immediate edges without loading an unbounded adjacency list.

func (*Store) GetStats

func (s *Store) GetStats() (GraphStats, error)

GetStats returns aggregate counts for the whole index.

func (*Store) GetTraceEdgesByTarget added in v0.3.0

func (s *Store) GetTraceEdgesByTarget(targetID string) ([]TraceEdge, error)

GetTraceEdgesByTarget returns accepted links for a normalized target node.

func (*Store) GetTraceNodes added in v0.3.0

func (s *Store) GetTraceNodes() ([]TraceNode, error)

GetTraceNodes returns the complete projection in stable identity order.

func (*Store) GetUnresolvedByName

func (s *Store) GetUnresolvedByName(name string) ([]model.UnresolvedReference, error)

GetUnresolvedByName returns unresolved references with the given name.

func (*Store) GetUnresolvedReferences

func (s *Store) GetUnresolvedReferences() ([]model.UnresolvedReference, error)

GetUnresolvedReferences returns every unresolved reference.

func (*Store) GetUnresolvedReferencesBatch

func (s *Store) GetUnresolvedReferencesBatch(offset, limit int) ([]model.UnresolvedReference, error)

GetUnresolvedReferencesBatch pages through unresolved references in bounded-memory chunks (LIMIT/OFFSET, rowid order — stable across pages).

func (*Store) GetUnresolvedReferencesByFiles

func (s *Store) GetUnresolvedReferencesByFiles(filePaths []string) ([]model.UnresolvedReference, error)

GetUnresolvedReferencesByFiles returns references recorded in the given files.

func (*Store) GetUnresolvedReferencesCount

func (s *Store) GetUnresolvedReferencesCount() (int, error)

GetUnresolvedReferencesCount counts unresolved references without loading them.

func (*Store) InsertEdge

func (s *Store) InsertEdge(e model.Edge) error

InsertEdge inserts an edge (INSERT OR IGNORE — duplicates are dropped).

func (*Store) InsertEdges

func (s *Store) InsertEdges(edges []model.Edge) error

InsertEdges inserts edges in one transaction, silently skipping edges whose endpoints don't exist (mirrors the original's endpoint-existence filter, which protects FK integrity during incremental syncs).

func (*Store) InsertNode

func (s *Store) InsertNode(n model.Node) error

InsertNode inserts or replaces a node. Nodes missing required fields are skipped (mirroring the original's defensive validation).

func (*Store) InsertNodes

func (s *Store) InsertNodes(nodes []model.Node) error

InsertNodes inserts nodes in one transaction.

func (*Store) InsertUnresolvedRef

func (s *Store) InsertUnresolvedRef(r model.UnresolvedReference) error

InsertUnresolvedRef records a reference for later resolution.

func (*Store) InsertUnresolvedRefs

func (s *Store) InsertUnresolvedRefs(refs []model.UnresolvedReference) error

InsertUnresolvedRefs inserts references in one transaction.

func (*Store) IterateNodesByKind

func (s *Store) IterateNodesByKind(kind model.NodeKind, fn func(model.Node) error) error

IterateNodesByKind streams nodes of a kind to fn, in rowid order.

func (*Store) JournalMode

func (s *Store) JournalMode() string

JournalMode reports the journal mode actually in effect ("wal", "delete", …). SQLite silently keeps the prior mode when WAL can't be enabled (e.g. network mounts), so this is surfaced in status for triage (issue #238).

func (*Store) Optimize

func (s *Store) Optimize() error

Optimize vacuums and analyzes the database.

func (*Store) Path

func (s *Store) Path() string

Path returns the database file path.

func (*Store) PutCoverage

func (s *Store) PutCoverage(rows []CoverageRow) error

PutCoverage replaces the per-file coverage rows for the given files in one transaction. Each row's file_path overwrites any prior record for that file.

func (*Store) PutNodeCoverage

func (s *Store) PutNodeCoverage(rows []NodeCoverageRow) error

PutNodeCoverage replaces the per-node coverage rows in one transaction. Rows whose node_id is absent from `nodes` are skipped (the FK would otherwise reject them); callers attribute only to nodes that exist.

func (*Store) ReplaceTrace added in v0.3.0

func (s *Store) ReplaceTrace(nodes []TraceNode, edges []TraceEdge, revision string) error

ReplaceTrace atomically replaces the complete trace projection and records the exact source revision from which it was built.

func (*Store) RunMaintenance

func (s *Store) RunMaintenance()

RunMaintenance performs lightweight post-bulk-write maintenance (PRAGMA optimize + passive WAL checkpoint). Best-effort: errors ignored.

func (*Store) SchemaVersion

func (s *Store) SchemaVersion() (int, error)

SchemaVersion returns the highest applied schema version (0 if none).

func (*Store) SearchAllByFilters

func (s *Store) SearchAllByFilters(
	kinds []model.NodeKind,
	langs []model.Language,
	limit int,
) ([]model.SearchResult, error)

SearchAllByFilters returns up to limit nodes matching kind/lang filters with a uniform score of 1. Used when no text is given.

func (*Store) SearchAllByFiltersAndSymbolFilters added in v0.5.0

func (s *Store) SearchAllByFiltersAndSymbolFilters(kinds []model.NodeKind, langs []model.Language, limit int, filters SymbolFilters) ([]model.SearchResult, error)

func (*Store) SearchFTS

func (s *Store) SearchFTS(
	text string,
	kinds []model.NodeKind,
	langs []model.Language,
	limit, offset int,
) ([]model.SearchResult, error)

SearchFTS runs an FTS5 prefix-match query against nodes_fts and returns (node, raw-bm25-score) pairs. The BM25 column weights mirror the original: id=0, name=20, qualified_name=5, docstring=1, signature=2. Returns up to limit*5 rows (over-fetch for post-hoc rescoring). Returns nil on FTS parse error (mirrors the original's try-catch → []).

func (*Store) SearchFTSFiltered added in v0.5.0

func (s *Store) SearchFTSFiltered(text string, kinds []model.NodeKind, langs []model.Language, limit, offset int, filters SymbolFilters) ([]model.SearchResult, error)

func (*Store) SearchFuzzy

func (s *Store) SearchFuzzy(
	text string,
	kinds []model.NodeKind,
	langs []model.Language,
	limit int,
	editDistFn func(a, b string, max int) int,
) ([]model.SearchResult, error)

SearchFuzzy runs an edit-distance sweep over all distinct symbol names. Only fires when text length ≥ 3.

func (*Store) SearchFuzzyFiltered added in v0.5.0

func (s *Store) SearchFuzzyFiltered(text string, kinds []model.NodeKind, langs []model.Language, limit int, editDistFn func(a, b string, max int) int, filters SymbolFilters) ([]model.SearchResult, error)

func (*Store) SearchLike

func (s *Store) SearchLike(
	text string,
	kinds []model.NodeKind,
	langs []model.Language,
	limit, offset int,
) ([]model.SearchResult, error)

SearchLike runs a LIKE-based substring search (fallback when FTS returns nothing).

func (*Store) SearchLikeFiltered added in v0.5.0

func (s *Store) SearchLikeFiltered(text string, kinds []model.NodeKind, langs []model.Language, limit, offset int, filters SymbolFilters) ([]model.SearchResult, error)

func (*Store) SetMetadata

func (s *Store) SetMetadata(key, value string) error

SetMetadata upserts a project metadata key-value pair.

func (*Store) Size

func (s *Store) Size() (int64, error)

Size returns the database file size in bytes.

func (*Store) Transaction

func (s *Store) Transaction(fn func(tx *sql.Tx) error) error

Transaction runs fn inside a single SQLite transaction.

func (*Store) UpsertFile

func (s *Store) UpsertFile(f model.FileRecord) error

UpsertFile inserts or updates a file record.

type SymbolFilters added in v0.5.0

type SymbolFilters struct {
	PathContains []string
	NameContains []string
}

SymbolFilters constrains symbol searches before SQLite applies a result limit. Each non-empty group is ORed case-insensitively.

type TraceEdge added in v0.3.0

type TraceEdge struct {
	SourceID        string
	TargetID        string
	Relation        string
	Accepted        bool
	SourcePath      string
	SourceLine      int
	SourceColumn    int
	TargetReference string
}

TraceEdge is an accepted or rejected typed source directive. Rejected edges remain indexed for deterministic diagnostics but are excluded from queries.

type TraceNode added in v0.3.0

type TraceNode struct {
	ID          string
	Kind        string
	Reference   string
	Title       string
	Path        string
	StartLine   int
	StartColumn int
	EndLine     int
	EndColumn   int
	Status      string
}

TraceNode is a normalized SpecScore node or an attached code symbol. The trace projection has its own node identity because links cross graph scopes.

Jump to

Keyboard shortcuts

? : This menu
/ : Search site
f or F : Jump to
y or Y : Canonical URL