You can not select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.
diary/db/db.go

104 lines
2.2 KiB

/// This package is in charge of connecting to the DB and migrations
package db
import (
"context"
"database/sql"
"errors"
"fmt"
_ "github.com/mattn/go-sqlite3"
)
var __version = 1
type DbCtx struct {
Db *sql.DB
Version int
}
func initVersion(tx *sql.Tx) (int, error) {
var version int
// Check the version
if err := tx.QueryRow("PRAGMA user_version").Scan(&version); err != nil {
tx.Rollback()
return 0, fmt.Errorf("Could not select user_version. %w", err)
}
if version == 0 {
_, err := tx.Exec(fmt.Sprintf("PRAGMA user_version=%d", __version))
if err != nil {
tx.Rollback()
return 0, fmt.Errorf("Could not update pragma version. %w", err)
}
version = __version
} else if version != __version {
tx.Rollback()
return 0, errors.New(fmt.Sprintf("Wrong version. Expected %d got %d", __version, version))
}
return version, nil
}
func migration0(tx *sql.Tx) error {
if _, err := tx.Exec(`
create table if not exists diary_log (
id integer not null primary key,
title text,
created_at int not null default (strftime('%s','now')),
version int not null default 0
)
`); err != nil {
tx.Rollback()
return fmt.Errorf("Could not create diary_log. %w", err)
}
return nil
}
func initMigrations(tx *sql.Tx, start_from_versiono int) error {
var migrations = []func(*sql.Tx) error{migration0}
for migration_idx, migration := range migrations {
// Version is 1 indexed, while the migration_idx is 0 indexed
var migration_num = migration_idx + 1
if migration_num < start_from_versiono {
continue
}
err := migration(tx)
if err != nil {
tx.Rollback()
return fmt.Errorf("Failed migration %d. %w", migration_num, err)
}
}
return nil
}
func Init(db_location string) (*DbCtx, error) {
db, err := sql.Open("sqlite3", db_location)
if err != nil {
return nil, fmt.Errorf("Could not connect to DB. %w", err)
}
if err := db.Ping(); err != nil {
return nil, fmt.Errorf("Could not ping DB. %w", err)
}
ctx := context.Background()
tx, err := db.BeginTx(ctx, nil)
if err != nil {
return nil, err
}
version, err := initVersion(tx)
if err != nil {
return nil, err
}
err = initMigrations(tx, version)
if err != nil {
return nil, err
}
tx.Commit()
return &DbCtx{db, version}, nil
}