diff --git a/db.go b/db.go new file mode 100644 index 0000000000000000000000000000000000000000..338979e53897791004aacb52301ac2480190e9df --- /dev/null +++ b/db.go @@ -0,0 +1,93 @@ +package main + +import ( + "embed" + "errors" + "fmt" + "io/fs" + "log" + "sort" + + "github.com/jmoiron/sqlx" +) + +//go:embed migrations/*.sql +var migrationFS embed.FS + +func initDB(db *sqlx.DB) error { + // Create table tracking migration state + const query = `CREATE TABLE IF NOT EXISTS migrations (name TEXT UNIQUE);` + + _, err := db.Exec(query) + if err != nil { + return err + } + + entries, err := migrationFS.ReadDir("migrations") + if err != nil { + return err + } + + sort.Slice(entries, func(i, j int) bool { + return entries[i].Name() < entries[j].Name() + }) + + for _, e := range entries { + data, err := fs.ReadFile(migrationFS, "migrations/"+e.Name()) + if err != nil { + return err + } + + tx, err := db.Begin() + if err != nil { + return err + } + + row := tx.QueryRow("SELECT count(*) FROM migrations WHERE name = ?", e.Name()) + + var howMany int + err = row.Scan(&howMany) + if err != nil { + tx.Rollback() + return fmt.Errorf("checking status for migration %s: %w", e.Name(), err) + } + + switch howMany { + case 0: + // not yet applied + case 1: + // applied, no need to do anything + log.Printf("skipping migration %s: already applied", e.Name()) + tx.Rollback() + continue + default: + // very weird + tx.Rollback() + return fmt.Errorf("unexpected migration count for %s: %d", e.Name(), howMany) + } + + log.Println("applying migration", e.Name()) + + _, err = tx.Exec(string(data)) + if err != nil { + tx.Rollback() + return fmt.Errorf("applying migration %s: %w", e.Name(), err) + } + + // Record migration as applied + _, err = tx.Exec("INSERT INTO migrations (name) VALUES (?)", e.Name()) + if err != nil { + tx.Rollback() + return fmt.Errorf("recording migration %s: %w", e.Name(), err) + } + + err = tx.Commit() + if err != nil { + return err + } + + log.Println("it has", len(data), "bytes") + } + + return errors.New("here be dragons") +} diff --git a/main.go b/main.go index e1601d591938948761e4a0ce1409b83d654dd8e9..293ab0892e0df087ef53ce7bd374df87d73ed24c 100644 --- a/main.go +++ b/main.go @@ -2,13 +2,9 @@ package main import ( "embed" - "errors" - "fmt" "html/template" - "io/fs" "log" "net/http" - "sort" "github.com/jmoiron/sqlx" _ "modernc.org/sqlite" // Imported for side effects: registers DB driver @@ -21,87 +17,6 @@ var templates = template.Must(template.ParseFS(templateFS, "templates/*.tpl")) //go:embed static/* var staticFS embed.FS -//go:embed migrations/*.sql -var migrationFS embed.FS - -func initDB(db *sqlx.DB) error { - // Create table tracking migration state - const query = `CREATE TABLE IF NOT EXISTS migrations (name TEXT UNIQUE);` - - _, err := db.Exec(query) - if err != nil { - return err - } - - entries, err := migrationFS.ReadDir("migrations") - if err != nil { - return err - } - - sort.Slice(entries, func(i, j int) bool { - return entries[i].Name() < entries[j].Name() - }) - - for _, e := range entries { - data, err := fs.ReadFile(migrationFS, "migrations/"+e.Name()) - if err != nil { - return err - } - - tx, err := db.Begin() - if err != nil { - return err - } - - row := tx.QueryRow("SELECT count(*) FROM migrations WHERE name = ?", e.Name()) - - var howMany int - err = row.Scan(&howMany) - if err != nil { - tx.Rollback() - return fmt.Errorf("checking status for migration %s: %w", e.Name(), err) - } - - switch howMany { - case 0: - // not yet applied - case 1: - // applied, no need to do anything - log.Printf("skipping migration %s: already applied", e.Name()) - tx.Rollback() - continue - default: - // very weird - tx.Rollback() - return fmt.Errorf("unexpected migration count for %s: %d", e.Name(), howMany) - } - - log.Println("applying migration", e.Name()) - - _, err = tx.Exec(string(data)) - if err != nil { - tx.Rollback() - return fmt.Errorf("applying migration %s: %w", e.Name(), err) - } - - // Record migration as applied - _, err = tx.Exec("INSERT INTO migrations (name) VALUES (?)", e.Name()) - if err != nil { - tx.Rollback() - return fmt.Errorf("recording migration %s: %w", e.Name(), err) - } - - err = tx.Commit() - if err != nil { - return err - } - - log.Println("it has", len(data), "bytes") - } - - return errors.New("here be dragons") -} - func main() { db, err := sqlx.Open("sqlite", "vino.sqlite") if err != nil { diff --git a/migrations/0001-initial.sql b/migrations/0001-initial.sql index e69de29bb2d1d6434b8b29ae775ad8c2e48c5391..9e4127566ce56efc754f411d1ca0ed00b32f9773 100644 --- a/migrations/0001-initial.sql +++ b/migrations/0001-initial.sql @@ -0,0 +1,6 @@ +CREATE TABLE wines ( + name TEXT, + rating INT, -- number of stars + picture BINARY, -- jpeg/png image of the label on the bottle + UNIQUE(name) +); \ No newline at end of file