Files
wehub-resource-sync a06f331eb8
CI / benchmark (push) Has been skipped
install-script / posix-syntax (push) Successful in 6m1s
CI / build-onnx (push) Failing after 6m43s
init-smoke / dry-run (push) Failing after 15m57s
security / govulncheck (push) Has been cancelled
security / trivy-fs (push) Has been cancelled
CI / test (1.26, ubuntu-latest) (push) Has been cancelled
Scorecard supply-chain security / Scorecard analysis (push) Has been cancelled
CI / test (1.26, macos-latest) (push) Has been cancelled
CI / build-windows (push) Has been cancelled
CI / lint (push) Has been cancelled
install-script / powershell-syntax (push) Has been cancelled
install-script / install (macos-14) (push) Has been cancelled
install-script / install (ubuntu-latest) (push) Has been cancelled
chore: import upstream snapshot with attribution
2026-07-13 12:33:42 +08:00

119 lines
3.4 KiB
Go

package store_sqlite
import (
"github.com/zzet/gortex/internal/graph"
)
// Compile-time assertions that the SQLite Store satisfies the optional
// per-file metadata persistence capability (the files sidecar feeding
// index_health's per-file parse-error / node-count rollup).
var (
_ graph.FileMetaWriter = (*Store)(nil)
_ graph.FileMetaReader = (*Store)(nil)
)
// fileMetaChunk bounds rows per multi-row INSERT (6 params/row; 80 rows =
// 480 host params, well under SQLite's 999 default).
const fileMetaChunk = 80
// SetFileMetas upserts per-file metadata rows for one repo prefix in a single
// transaction, chunked under the host-parameter limit. Idempotent on the
// (repo_prefix, file_path) primary key. Empty input is a no-op.
func (s *Store) SetFileMetas(repoPrefix string, rows []graph.FileMetaRow) error {
if len(rows) == 0 {
return nil
}
s.writeMu.Lock()
defer s.writeMu.Unlock()
tx, err := s.db.Begin()
if err != nil {
return err
}
defer tx.Rollback() //nolint:errcheck // rollback after Commit is a no-op
for start := 0; start < len(rows); start += fileMetaChunk {
end := start + fileMetaChunk
if end > len(rows) {
end = len(rows)
}
batch := rows[start:end]
args := make([]any, 0, len(batch)*6)
stmt := make([]byte, 0, 96+len(batch)*24)
stmt = append(stmt, "INSERT OR REPLACE INTO files (repo_prefix, file_path, content_hash, size, node_count, errors) VALUES "...)
for i, r := range batch {
if i > 0 {
stmt = append(stmt, ',')
}
stmt = append(stmt, "(?, ?, ?, ?, ?, ?)"...)
args = append(args, repoPrefix, r.FilePath, r.ContentHash, r.Size, r.NodeCount, r.Errors)
}
if _, err := tx.Exec(string(stmt), args...); err != nil {
return err
}
}
return tx.Commit()
}
// DeleteFileMetasByFiles drops the metadata rows for the supplied files in one
// repo prefix, chunked into `file_path IN (…)` DELETEs. Empty input is a no-op.
func (s *Store) DeleteFileMetasByFiles(repoPrefix string, files []string) error {
if len(files) == 0 {
return nil
}
s.writeMu.Lock()
defer s.writeMu.Unlock()
tx, err := s.db.Begin()
if err != nil {
return err
}
defer tx.Rollback() //nolint:errcheck // rollback after Commit is a no-op
for start := 0; start < len(files); start += fileMetaChunk {
end := start + fileMetaChunk
if end > len(files) {
end = len(files)
}
chunk := files[start:end]
args := make([]any, 0, len(chunk)+1)
args = append(args, repoPrefix)
stmt := make([]byte, 0, 64+len(chunk)*2)
stmt = append(stmt, "DELETE FROM files WHERE repo_prefix = ? AND file_path IN ("...)
for i, f := range chunk {
if i > 0 {
stmt = append(stmt, ',')
}
stmt = append(stmt, '?')
args = append(args, f)
}
stmt = append(stmt, ')')
if _, err := tx.Exec(string(stmt), args...); err != nil {
return err
}
}
return tx.Commit()
}
// FileMetasForRepo returns every recorded file row for the repo prefix.
// Always non-nil.
func (s *Store) FileMetasForRepo(repoPrefix string) ([]graph.FileMetaRow, error) {
rows, err := s.db.Query(
`SELECT file_path, content_hash, size, node_count, errors FROM files WHERE repo_prefix = ? ORDER BY file_path`,
repoPrefix,
)
if err != nil {
return nil, err
}
defer rows.Close()
out := []graph.FileMetaRow{}
for rows.Next() {
var r graph.FileMetaRow
if err := rows.Scan(&r.FilePath, &r.ContentHash, &r.Size, &r.NodeCount, &r.Errors); err != nil {
return nil, err
}
out = append(out, r)
}
return out, rows.Err()
}