package db import ( "database/sql" "fmt" "log/slog" "git.wittern.io/public/echo-todos/model" _ "github.com/mattn/go-sqlite3" ) var DB *sql.DB func InitDB() (*sql.DB, error) { var err error todosDB := "./data/todos.db" DB, err = sql.Open("sqlite3", todosDB) if err != nil { slog.Error("cant open db", "Error", err) } if tableExists(DB, "todos") { DB, err = sql.Open("sqlite3", todosDB) if err != nil { slog.Error("cant open db", "Error", err) } } else { CreateTable(DB) } return DB, nil } func tableExists(db *sql.DB, tableName string) bool { var err error var result string query := "SELECT name FROM sqlite_master WHERE type='table' AND name=?;" err = db.QueryRow(query, tableName).Scan(&result) if err == sql.ErrNoRows { fmt.Println("Table does not exist, the database was likely just created.") return false } else if err != nil { slog.Error("unexpected db error", "Error", err) } else { fmt.Println("Table exists, the database was already initialized.") return true } return false } func CreateTable(db *sql.DB) error { query := ` CREATE TABLE IF NOT EXISTS todos ( id INTEGER PRIMARY KEY AUTOINCREMENT, title TEXT, done BOOLEAN );` _, err := db.Exec(query) return err } func InsertTodo(db *sql.DB, todo model.Todo) (error, int64) { query := ` INSERT INTO todos (title, done ) VALUES (?, ?);` result, err := db.Exec(query, todo.Title, 0) if err != nil { slog.Error("failed to insert todo", "Error", err) return err, 0 } todoId, err := result.LastInsertId() if err != nil { slog.Error("failed to get last insert id", "Error", err) return err, 0 } return nil, todoId } func ListTodos(db *sql.DB) ([]model.Todo, error) { query := `SELECT id, title, done FROM todos;` rows, err := db.Query(query) if err != nil { return nil, err } defer rows.Close() var todos model.Todos for rows.Next() { var todo model.Todo err := rows.Scan(&todo.ID, &todo.Title, &todo.Done) if err != nil { return nil, err } todos = append(todos, todo) } return todos, nil } func DeleteTodoByID(db *sql.DB, todoID int) error { query := `DELETE FROM todos WHERE id = ?;` _, err := db.Exec(query, todoID) return err } func ToggleTodoByID(db *sql.DB, id int) ([]model.Todo, error) { query := `UPDATE todos SET done = NOT done WHERE id = ?;` _, err := db.Exec(query, id) if err != nil { return []model.Todo{}, err } todos, err := ListTodos(db) if err != nil { return []model.Todo{}, err } return todos, nil }