Files
vctp2/db/local.go
Nathan Coad ea1eeb5c21
Some checks failed
continuous-integration/drone Build is passing
CI / Lint (push) Has been cancelled
CI / Test (push) Has been cancelled
CI / End-to-End (push) Has been cancelled
CI / Publish Docker (push) Has been cancelled
update to support postgresql and add godocs
2026-01-13 17:05:14 +11:00

109 lines
2.3 KiB
Go

package db
import (
"database/sql"
"fmt"
"log/slog"
"strings"
"vctp/db/queries"
//_ "github.com/tursodatabase/libsql-client-go/libsql"
"github.com/jmoiron/sqlx"
_ "modernc.org/sqlite"
)
type LocalDB struct {
logger *slog.Logger
db *sqlx.DB
queries *queries.Queries
}
type DB struct {
writeDB *sql.DB
readDB *sql.DB
}
var _ Database = (*LocalDB)(nil)
func (d *LocalDB) DB() *sqlx.DB {
return d.db
}
func (d *LocalDB) Queries() Querier {
return d.queries
}
func (d *LocalDB) Logger() *slog.Logger {
return d.logger
}
func (d *LocalDB) Close() error {
fmt.Println("Shutting database")
d.logger.Debug("test")
return d.db.Close()
}
func newLocalDB(logger *slog.Logger, dsn string) (*LocalDB, error) {
// TODO - work out if https://kerkour.com/sqlite-for-servers is possible without using sqlx
/*
writeDB, err := sql.Open("sqlite3", "file:"+path)
if err != nil {
logger.Error("can't create writedb connection", "error", err)
return nil, err
}
writeDB.SetMaxOpenConns(1)
readDB, err := sql.Open("sqlite3", "file:"+path)
if err != nil {
logger.Error("can't create readdb connection", "error", err)
return nil, err
}
readDB.SetMaxOpenConns(max(4, runtime.NumCPU()))
*/
normalizedDSN := normalizeSqliteDSN(dsn)
//db, err := sql.Open("libsql", normalizedDSN)
db, err := sqlx.Open("sqlite", normalizedDSN)
if err != nil {
logger.Error("can't open database connection", "error", err)
return nil, err
}
db.SetMaxOpenConns(1)
// Execute PRAGMA commands
pragmas := []string{
"PRAGMA journal_mode = WAL;",
"PRAGMA busy_timeout = 5000;",
"PRAGMA synchronous = NORMAL;",
"PRAGMA cache_size = 1000000000;",
"PRAGMA foreign_keys = true;",
"PRAGMA temp_store = MEMORY;",
}
for _, pragma := range pragmas {
logger.Debug("Setting pragma", "pragma", pragma)
_, err := db.Exec(pragma)
if err != nil {
logger.Error("failed to execute pragma statement", "stmt", pragma, "error", err)
return nil, err
}
}
return &LocalDB{logger: logger, db: db, queries: queries.New(db)}, nil
}
func normalizeSqliteDSN(dsn string) string {
trimmed := strings.TrimSpace(dsn)
if trimmed == "" {
return "file:db.sqlite3"
}
lower := strings.ToLower(trimmed)
if strings.HasPrefix(lower, "file:") || strings.HasPrefix(lower, "file::memory:") || trimmed == ":memory:" {
return trimmed
}
return "file:" + trimmed
}