mirror of https://git.sr.ht/~statianzo/todogo
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.
127 lines
2.1 KiB
127 lines
2.1 KiB
2 years ago
|
package database
|
||
|
|
||
|
import (
|
||
|
"database/sql"
|
||
|
"log"
|
||
|
|
||
|
_ "modernc.org/sqlite"
|
||
|
)
|
||
|
|
||
|
type DB struct {
|
||
|
db *sql.DB
|
||
|
}
|
||
|
|
||
|
func New() *DB {
|
||
|
d := &DB{}
|
||
|
con, err := sql.Open("sqlite", "./todogo.db")
|
||
|
if err != nil {
|
||
|
log.Fatal(err)
|
||
|
}
|
||
|
d.db = con
|
||
|
|
||
|
err = d.init()
|
||
|
if err != nil {
|
||
|
log.Fatal(err)
|
||
|
}
|
||
|
|
||
|
return d
|
||
|
}
|
||
|
|
||
|
func (d *DB) init() error {
|
||
|
d.migrate()
|
||
|
|
||
|
return nil
|
||
|
}
|
||
|
|
||
|
func (d *DB) InsertTodo(title string) error {
|
||
|
_, err := d.db.Exec("INSERT INTO todos(title, completed) VALUES(?, ?)", title, 0)
|
||
|
return err
|
||
|
}
|
||
|
|
||
|
func (d *DB) ToggleTodo(id int) error {
|
||
|
_, err := d.db.Exec(`
|
||
|
UPDATE todos
|
||
|
SET completed = (CASE WHEN completed = 0 THEN 1 ELSE 0 END)
|
||
|
WHERE id = ?
|
||
|
`, id)
|
||
|
return err
|
||
|
}
|
||
|
|
||
|
func (d *DB) DeleteTodo(id int) error {
|
||
|
_, err := d.db.Exec("DELETE FROM todos WHERE id = ?", id)
|
||
|
return err
|
||
|
}
|
||
|
|
||
|
func (d *DB) GetAllTodos() ([]*Todo, error) {
|
||
|
rows, err := d.db.Query("SELECT id, title, completed FROM todos")
|
||
|
if err != nil {
|
||
|
return nil, err
|
||
|
}
|
||
|
defer rows.Close()
|
||
|
todos := scanTodos(rows)
|
||
|
|
||
|
return todos, nil
|
||
|
}
|
||
|
|
||
|
func (d *DB) GetTodosByCompleted(completed bool) ([]*Todo, error) {
|
||
|
completedInt := 0
|
||
|
if completed {
|
||
|
completedInt = 1
|
||
|
}
|
||
|
rows, err := d.db.Query("SELECT id, title, completed FROM todos WHERE completed = ?", completedInt)
|
||
|
if err != nil {
|
||
|
return nil, err
|
||
|
}
|
||
|
defer rows.Close()
|
||
|
|
||
|
todos := scanTodos(rows)
|
||
|
|
||
|
return todos, nil
|
||
|
}
|
||
|
|
||
|
func (d *DB) GetIncompleteTodosCount() int {
|
||
|
row := d.db.QueryRow("SELECT COUNT(*) FROM todos WHERE completed = 0")
|
||
|
var count int
|
||
|
err := row.Scan(&count)
|
||
|
if err != nil {
|
||
|
log.Printf("failed to get incomplete count")
|
||
|
return 0
|
||
|
}
|
||
|
|
||
|
return count
|
||
|
}
|
||
|
|
||
|
func (d *DB) DeleteCompletedTodos() error {
|
||
|
_, err := d.db.Exec("DELETE FROM todos WHERE completed = 1")
|
||
|
return err
|
||
|
}
|
||
|
|
||
|
func scanTodos(rows *sql.Rows) []*Todo {
|
||
|
var todos []*Todo
|
||
|
for rows.Next() {
|
||
|
t := scanTodo(rows)
|
||
|
if t != nil {
|
||
|
todos = append(todos, t)
|
||
|
}
|
||
|
}
|
||
|
|
||
|
return todos
|
||
|
}
|
||
|
|
||
|
func scanTodo(row *sql.Rows) *Todo {
|
||
|
t := new(Todo)
|
||
|
err := row.Scan(&t.Id, &t.Title, &t.Completed)
|
||
|
if err != nil {
|
||
|
log.Printf("Failed to read row %s", err)
|
||
|
return nil
|
||
|
}
|
||
|
|
||
|
return t
|
||
|
}
|
||
|
|
||
|
type Todo struct {
|
||
|
Id int
|
||
|
Title string
|
||
|
Completed bool
|
||
|
}
|