package database import ( "context" "database/sql" "embed" "github.com/apex/log" "github.com/ooni/probe-cli/v3/internal/netxlite" migrate "github.com/rubenv/sql-migrate" "github.com/upper/db/v4" "github.com/upper/db/v4/adapter/sqlite" ) //go:embed migrations/*.sql var efs embed.FS func readAsset(path string) ([]byte, error) { filep, err := efs.Open(path) if err != nil { return nil, err } return netxlite.ReadAllContext(context.Background(), filep) } func readAssetDir(path string) ([]string, error) { var out []string lst, err := efs.ReadDir(path) if err != nil { return nil, err } for _, e := range lst { out = append(out, e.Name()) } return out, nil } // RunMigrations runs the database migrations func RunMigrations(sess *sql.DB) error { log.Debugf("running migrations") migrations := &migrate.AssetMigrationSource{ Asset: readAsset, AssetDir: readAssetDir, Dir: "migrations", } n, err := migrate.Exec(sess, "sqlite3", migrations, migrate.Up) if err != nil { return err } log.Debugf("performed %d migrations", n) return nil } // Connect to the database func Connect(path string) (sess db.Session, err error) { settings := sqlite.ConnectionURL{ Database: path, Options: map[string]string{"_foreign_keys": "1"}, } sess, err = sqlite.Open(settings) if err != nil { log.WithError(err).Error("failed to open the DB") return nil, err } err = RunMigrations(sess.Driver().(*sql.DB)) if err != nil { log.WithError(err).Error("failed to run DB migration") return nil, err } return sess, err }