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}