package index
import (
"path/filepath"
"slices"
"testing"
)
func eventIndexes(t *testing.T, ix *Index) []string {
t.Helper()
rows, err := ix.db.Query(`SELECT name FROM sqlite_master
WHERE type = 'index' AND tbl_name = 'event' AND sql IS NOT NULL ORDER BY name`)
if err != nil {
t.Fatal(err)
}
defer rows.Close()
var out []string
for rows.Next() {
var n string
if err := rows.Scan(&n); err != nil {
t.Fatal(err)
}
out = append(out, n)
}
return out
}
// Every store in the fleet already has an index file with the old
// user index. Opening it must bring the new one in and take the old one
// out, without a reindex: an index changes no row, so it needs no
// schema bump.
func TestOpeningAnOldIndexGainsTheUserDateIndex(t *testing.T) {
path := filepath.Join(t.TempDir(), "index.db")
ix, err := Open(path)
if err != nil {
t.Fatal(err)
}
// The file as the fleet has it today.
for _, stmt := range []string{
`DROP INDEX IF EXISTS event_by_user_date`,
`CREATE INDEX IF NOT EXISTS event_by_user ON event (user)`,
} {
if _, err := ix.w.Exec(stmt); err != nil {
t.Fatal(err)
}
}
ix.Close()
ix, err = Open(path)
if err != nil {
t.Fatal(err)
}
defer ix.Close()
if ix.stale {
t.Error("the new index made the file stale: every store would reindex on deploy")
}
got := eventIndexes(t, ix)
if !slices.Contains(got, "event_by_user_date") {
t.Errorf("reopened index has no event_by_user_date: %v", got)
}
if slices.Contains(got, "event_by_user") {
t.Errorf("the superseded event_by_user is still maintained on every write: %v", got)
}
}
// A bulk rebuild drops the secondary indexes and builds them once at
// the end; the user index is one of them.
func TestBulkRebuildDropsAndRestoresTheUserDateIndex(t *testing.T) {
ix := openIndex(t)
if err := ix.SuspendDerivedMaintenance(); err != nil {
t.Fatal(err)
}
if got := eventIndexes(t, ix); slices.Contains(got, "event_by_user_date") {
t.Errorf("maintained row by row during a bulk rebuild: %v", got)
}
if err := ix.ResumeDerivedMaintenance(); err != nil {
t.Fatal(err)
}
if got := eventIndexes(t, ix); !slices.Contains(got, "event_by_user_date") {
t.Errorf("not rebuilt after the bulk rebuild: %v", got)
}
}