db.go

 1// SPDX-FileCopyrightText: Amolith <amolith@secluded.site>
 2//
 3// SPDX-License-Identifier: Apache-2.0
 4
 5package db
 6
 7import (
 8	"database/sql"
 9	_ "embed"
10	"errors"
11	"fmt"
12	"sync"
13
14	_ "modernc.org/sqlite"
15)
16
17//go:embed sql/schema.sql
18var schema string
19
20var mutex = &sync.Mutex{}
21
22// Open opens a connection to the SQLite database.
23func Open(dbPath string) (*sql.DB, error) {
24	db, err := sql.Open("sqlite", "file:"+dbPath+"?_pragma=journal_mode%3DWAL")
25	if err != nil {
26		return nil, fmt.Errorf("failed to open database: %w", err)
27	}
28
29	return db, nil
30}
31
32// VerifySchema checks whether the schema has been initialised and initialises it
33// if not.
34func InitialiseDatabase(dbConn *sql.DB) error {
35	var name string
36
37	err := dbConn.QueryRow("SELECT name FROM sqlite_master WHERE type='table' AND name='users'").Scan(&name)
38	if err != nil && errors.Is(err, sql.ErrNoRows) {
39		mutex.Lock()
40		defer mutex.Unlock()
41
42		if _, err := dbConn.Exec(schema); err != nil {
43			return fmt.Errorf("failed to execute SQL: %w", err)
44		}
45
46		return nil
47	}
48
49	if err != nil {
50		return fmt.Errorf("failed to scan row: %w", err)
51	}
52
53	return nil
54}