aboutsummaryrefslogtreecommitdiffhomepage
path: root/src/dbx/db.go
diff options
context:
space:
mode:
Diffstat (limited to 'src/dbx/db.go')
-rw-r--r--src/dbx/db.go144
1 files changed, 144 insertions, 0 deletions
diff --git a/src/dbx/db.go b/src/dbx/db.go
new file mode 100644
index 0000000..5ee3782
--- /dev/null
+++ b/src/dbx/db.go
@@ -0,0 +1,144 @@
+package dbx
+
+import (
+ "context"
+ "fmt"
+ "io/fs"
+ "log"
+ "sort"
+
+ "git.thomasvoss.com/euro-cash.eu/pkg/atexit"
+ . "git.thomasvoss.com/euro-cash.eu/pkg/try"
+ "github.com/jmoiron/sqlx"
+ "github.com/mattn/go-sqlite3"
+)
+
+var (
+ db *sqlx.DB
+ DBName string
+)
+
+func Init(sqlDir fs.FS) {
+ db = sqlx.MustConnect("sqlite3", DBName)
+ atexit.Register(Close)
+
+ conn := Try2(db.Conn(context.Background()))
+ Try(conn.Raw(func(driverConn any) error {
+ return driverConn.(*sqlite3.SQLiteConn).RegisterFunc("C_",
+ func(s, _ string) string {
+ return s
+ }, true)
+ }))
+ conn.Close()
+
+ Try(applyMigrations(sqlDir))
+
+ /* TODO: Remove debug code */
+ /* Try(CreateUser(User{
+ Email: "mail@thomasvoss.com",
+ Username: "Thomas",
+ Password: "69",
+ AdminP: true,
+ }))
+ Try(CreateUser(User{
+ Email: "foo@BAR.baz",
+ Username: "Foobar",
+ Password: "420",
+ AdminP: false,
+ }))
+ Try2(GetMintages("ad", TypeCirc)) */
+}
+
+func Close() {
+ db.Close()
+}
+
+func applyMigrations(dir fs.FS) error {
+ var latest int
+ migratedp := true
+
+ err := db.QueryRow("SELECT latest FROM migration").Scan(&latest)
+ if err != nil {
+ e, ok := err.(sqlite3.Error)
+ /* IDK if there is a better way to do this… lol */
+ if ok && e.Error() == "no such table: migration" {
+ migratedp = false
+ } else {
+ return err
+ }
+ }
+
+ if !migratedp {
+ latest = -1
+ }
+
+ files, err := fs.ReadDir(dir, ".")
+ if err != nil {
+ return err
+ }
+
+ var (
+ last string
+ scripts []string
+ )
+
+ for _, f := range files {
+ if n := f.Name(); n == "last.sql" {
+ last = n
+ } else {
+ scripts = append(scripts, f.Name())
+ }
+ }
+
+ sort.Strings(scripts)
+ for _, f := range scripts[latest+1:] {
+ qry, err := fs.ReadFile(dir, f)
+ if err != nil {
+ return err
+ }
+
+ tx, err := db.Begin()
+ if err != nil {
+ return err
+ }
+
+ var n int
+ if _, err = fmt.Sscanf(f, "%d", &n); err != nil {
+ goto error
+ }
+
+ if _, err = tx.Exec(string(qry)); err != nil {
+ err = fmt.Errorf("error in ‘%s’: %w", f, err)
+ goto error
+ }
+
+ _, err = tx.Exec("UPDATE migration SET latest = ? WHERE id = 1", n)
+ if err != nil {
+ goto error
+ }
+
+ if err = tx.Commit(); err != nil {
+ goto error
+ }
+
+ log.Printf("Applied database migration ‘%s’\n", f)
+ continue
+
+ error:
+ tx.Rollback()
+ return err
+ }
+
+ if last != "" {
+ qry, err := fs.ReadFile(dir, last)
+ if err != nil {
+ return err
+ }
+ if _, err := db.Exec(string(qry)); err != nil {
+ return fmt.Errorf("error in ‘%s’: %w", last, err)
+ }
+ log.Printf("Ran ‘%s’\n", last)
+ }
+
+ return nil
+}