Skip to content
quarry Artifact [2556baba2f]
Login

Artifact [2556baba2f]

Artifact 2556baba2f87f71239468b98213b29aaf2deceb784516581d9c0d998a06d2e1c:


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)
	}
}