sqlite.go

 1package sqlite
 2
 3import (
 4	"errors"
 5
 6	"github.com/charmbracelet/log"
 7	"github.com/charmbracelet/soft-serve/server/db"
 8	"github.com/jmoiron/sqlx"
 9	"golang.org/x/net/context"
10)
11
12var (
13	// Options database options for the sqlite database.
14	Options = map[string][]string{
15		"_pragma": {
16			"busy_timeout(5000)",
17			"foreign_keys(1)",
18		},
19	}
20
21	// ErrDuplicateKey is returned when a unique constraint is violated.
22	ErrDuplicateKey = errors.New("record already exists")
23
24	// ErrNoRecord is returned when a record is not found.
25	ErrNoRecord = errors.New("record not found")
26)
27
28func init() {
29	db.Register("sqlite", &Sqlite{})
30}
31
32// Sqlite is the interface that wraps basic sqlite operations.
33type Sqlite struct {
34	ctx    context.Context
35	db     *sqlx.DB
36	logger *log.Logger
37}
38
39var _ db.Database = (*Sqlite)(nil)
40
41// DBx returns the underlying sqlx database.
42func (s *Sqlite) DBx() *sqlx.DB {
43	return s.db
44}
45
46// Open opens a new sqlite database connection.
47func (s *Sqlite) Open(ctx context.Context, path string) (db.Database, error) {
48	logger := log.FromContext(ctx).WithPrefix("sqlite")
49	dataSource := path
50	if len(Options) > 0 {
51		dataSource += "?"
52		for k, v := range Options {
53			for i, o := range v {
54				dataSource += k + "=" + o
55				if i < len(v)-1 {
56					dataSource += "&"
57				}
58			}
59		}
60	}
61	db, err := sqlx.ConnectContext(ctx, "sqlite", dataSource)
62	if err != nil {
63		return nil, err
64	}
65
66	return &Sqlite{
67		ctx:    ctx,
68		db:     db,
69		logger: logger,
70	}, nil
71}
72
73// Close closes the sqlite database connection.
74func (s *Sqlite) Close() error {
75	return s.db.Close()
76}