func (a *Adapter) GetFileInfo(s sum.Sum) (FileInfo, error) {
	q := `
	SELECT name, created_at, size, versioned
	FROM file_versions JOIN files on files.id = file_versions.file 
	WHERE sum = ?
	`
	row := a.db.QueryRow(q, s[:])
	var name string
	var createdAt int64
	var size uint64
	var vflag int
	if err := row.Scan(&name, &createdAt, &size, &vflag); err == sql.ErrNoRows {
		return FileInfo{}, ErrNotFound
	} else if err != nil {
		return FileInfo{}, err
	}
	versioned, err := parseVFlag(vflag)
	if err != nil {
		return FileInfo{}, err
	}
	return FileInfo{
		Name:      name,
		CreatedAt: time.Unix(0, createdAt).UTC(),
		Size:      size,
		Sum:       s,
		Versioned: versioned,
	}, nil
}
GetFileInfo returns the FileInfo for a given file version. Returns ErrNotFound if the
file does not exist.
package db
import (
	"database/sql"
	"errors"
	"fmt"
	"strings"
	"sync"
	"time"
	"github.com/jotfs/jotfs/internal/compress"
	"github.com/jotfs/jotfs/internal/object"
	"github.com/jotfs/jotfs/internal/sum"
	"github.com/rs/xid"
)
type VacuumStatus int
const (
	VacuumRunning VacuumStatus = iota
	VacuumOK
	VacuumFailed
)
func (s VacuumStatus) String() string {
	switch s {
	case VacuumRunning:
		return "RUNNING"
	case VacuumOK:
		return "SUCCEEDED"
	case VacuumFailed:
		return "FAILED"
	default:
		return "UNKNOWN"
	}
}
type Adapter struct {
	mut sync.Mutex
	db  *sql.DB
}
func NewAdapter(db *sql.DB) *Adapter {
	return &Adapter{sync.Mutex{}, db}
}
func (a *Adapter) InitSchema() error {
	_, err := a.db.Exec(Q_000_Base)
	return err
}
func (a *Adapter) update(f func(tx *sql.Tx) error) error {
	a.mut.Lock()
	defer a.mut.Unlock()
	tx, err := a.db.Begin()
	if err != nil {
		return err
	}
	if err := f(tx); err != nil {
		rerr := tx.Rollback()
		if rerr != nil {
			err = fmt.Errorf("%w; %v", err, rerr)
		}
		return err
	}
	return tx.Commit()
}