234 lines
5.4 KiB
Go
234 lines
5.4 KiB
Go
package db
|
|
|
|
import (
|
|
"database/sql"
|
|
"errors"
|
|
"os"
|
|
"path"
|
|
"strings"
|
|
"time"
|
|
|
|
_ "github.com/mattn/go-sqlite3"
|
|
|
|
"github.com/Cameron-Reed1/todo-web/types"
|
|
)
|
|
|
|
var userDbDir string
|
|
|
|
type UserDB struct {
|
|
DB *sql.DB
|
|
}
|
|
|
|
func SetUserDBDir(dir string) error {
|
|
os.MkdirAll(dir, 0700)
|
|
userDbDir = dir
|
|
return nil
|
|
}
|
|
|
|
func OpenUserDB(username string) (*UserDB, error) {
|
|
if strings.Contains(username, ".") || strings.Contains(username, "/") {
|
|
return nil, errors.New("Invalid username")
|
|
}
|
|
|
|
path := path.Join(userDbDir, username + ".db")
|
|
|
|
db, err := sql.Open("sqlite3", path)
|
|
if err != nil {
|
|
return nil, err
|
|
}
|
|
|
|
err = db.Ping()
|
|
if err != nil {
|
|
return nil, err
|
|
}
|
|
|
|
query := `
|
|
CREATE TABLE IF NOT EXISTS items (
|
|
id INTEGER PRIMARY KEY AUTOINCREMENT,
|
|
start INTEGER,
|
|
due INTEGER,
|
|
text TEXT NOT NULL,
|
|
completed INTEGER NOT NULL
|
|
);`
|
|
|
|
_, err = db.Exec(query)
|
|
|
|
return &UserDB{DB: db}, err
|
|
}
|
|
|
|
func (user_db *UserDB) Close() error {
|
|
return user_db.DB.Close()
|
|
}
|
|
|
|
func (user_db *UserDB) AddTodo(todo *types.Todo) error {
|
|
res, err := user_db.DB.Exec("INSERT INTO items(start, due, text, completed) values(?, ?, ?, 0)", toNullInt64(todo.Start), toNullInt64(todo.Due), todo.Text)
|
|
if err != nil {
|
|
return err
|
|
}
|
|
|
|
todo.Id, err = res.LastInsertId()
|
|
if err != nil {
|
|
return err
|
|
}
|
|
|
|
return nil
|
|
}
|
|
|
|
func (user_db *UserDB) GetTodo(id int) (types.Todo, error) {
|
|
var todo types.Todo
|
|
var start sql.NullInt64
|
|
var due sql.NullInt64
|
|
|
|
row := user_db.DB.QueryRow("SELECT * FROM items WHERE id=?", id)
|
|
err := row.Scan(&todo.Id, &start, &due, &todo.Text, &todo.Completed)
|
|
|
|
todo.Start = fromNullInt64(start)
|
|
todo.Due = fromNullInt64(due)
|
|
|
|
return todo, err
|
|
}
|
|
|
|
func (user_db *UserDB) GetAllTodos() ([]types.Todo, error) {
|
|
var todos []types.Todo
|
|
|
|
rows, err := user_db.DB.Query("SELECT * FROM items")
|
|
if err != nil {
|
|
return nil, err
|
|
}
|
|
|
|
for rows.Next() {
|
|
var todo types.Todo
|
|
var start sql.NullInt64
|
|
var due sql.NullInt64
|
|
|
|
err = rows.Scan(&todo.Id, &start, &due, &todo.Text, &todo.Completed)
|
|
if err != nil {
|
|
return nil, err
|
|
}
|
|
|
|
todo.Start = fromNullInt64(start)
|
|
todo.Due = fromNullInt64(due)
|
|
|
|
todos = append(todos, todo)
|
|
}
|
|
|
|
if err = rows.Err(); err != nil {
|
|
return nil, err
|
|
}
|
|
|
|
return todos, nil
|
|
}
|
|
|
|
func (user_db *UserDB) GetOverdueTodos() ([]types.Todo, error) {
|
|
var todos []types.Todo
|
|
|
|
rows, err := user_db.DB.Query("SELECT * FROM items WHERE due < ? AND due IS NOT NULL ORDER BY completed, due", time.Now().Unix())
|
|
if err != nil {
|
|
return nil, err
|
|
}
|
|
|
|
for rows.Next() {
|
|
var todo types.Todo
|
|
var start sql.NullInt64
|
|
var due sql.NullInt64
|
|
|
|
err = rows.Scan(&todo.Id, &start, &due, &todo.Text, &todo.Completed)
|
|
if err != nil {
|
|
return nil, err
|
|
}
|
|
|
|
todo.Start = fromNullInt64(start)
|
|
todo.Due = fromNullInt64(due)
|
|
|
|
todos = append(todos, todo)
|
|
}
|
|
|
|
if err = rows.Err(); err != nil {
|
|
return nil, err
|
|
}
|
|
|
|
return todos, nil
|
|
}
|
|
|
|
func (user_db *UserDB) GetTodayTodos() ([]types.Todo, error) {
|
|
var todos []types.Todo
|
|
|
|
now := time.Now()
|
|
year, month, day := now.Date()
|
|
today := time.Date(year, month, day, 0, 0, 0, 0, time.Local)
|
|
rows, err := user_db.DB.Query("SELECT * FROM items WHERE (start <= ? OR start IS NULL) AND (due >= ? OR due IS NULL) ORDER BY completed, due NULLS LAST", today.Unix(), now.Unix())
|
|
if err != nil {
|
|
return nil, err
|
|
}
|
|
|
|
for rows.Next() {
|
|
var todo types.Todo
|
|
var start sql.NullInt64
|
|
var due sql.NullInt64
|
|
|
|
err = rows.Scan(&todo.Id, &start, &due, &todo.Text, &todo.Completed)
|
|
if err != nil {
|
|
return nil, err
|
|
}
|
|
|
|
todo.Start = fromNullInt64(start)
|
|
todo.Due = fromNullInt64(due)
|
|
|
|
todos = append(todos, todo)
|
|
}
|
|
|
|
if err = rows.Err(); err != nil {
|
|
return nil, err
|
|
}
|
|
|
|
return todos, nil
|
|
}
|
|
|
|
func (user_db *UserDB) GetUpcomingTodos() ([]types.Todo, error) {
|
|
var todos []types.Todo
|
|
|
|
year, month, day := time.Now().Date()
|
|
today := time.Date(year, month, day, 0, 0, 0, 0, time.Local)
|
|
rows, err := user_db.DB.Query("SELECT * FROM items WHERE start > ? ORDER BY completed, start", today.Unix())
|
|
if err != nil {
|
|
return nil, err
|
|
}
|
|
|
|
for rows.Next() {
|
|
var todo types.Todo
|
|
var start sql.NullInt64
|
|
var due sql.NullInt64
|
|
|
|
err = rows.Scan(&todo.Id, &start, &due, &todo.Text, &todo.Completed)
|
|
if err != nil {
|
|
return nil, err
|
|
}
|
|
|
|
todo.Start = fromNullInt64(start)
|
|
todo.Due = fromNullInt64(due)
|
|
|
|
todos = append(todos, todo)
|
|
}
|
|
|
|
if err = rows.Err(); err != nil {
|
|
return nil, err
|
|
}
|
|
|
|
return todos, nil
|
|
}
|
|
|
|
func (user_db *UserDB) UpdateTodo(newValues types.Todo) error {
|
|
_, err := user_db.DB.Exec("UPDATE items SET start=?, due=?, text=? WHERE id=?", toNullInt64(newValues.Start), toNullInt64(newValues.Due), newValues.Text, newValues.Id)
|
|
return err;
|
|
}
|
|
|
|
func (user_db *UserDB) SetCompleted(id int, completed bool) error {
|
|
_, err := user_db.DB.Exec("UPDATE items SET completed=? WHERE id=?", completed, id)
|
|
return err
|
|
}
|
|
|
|
func (user_db *UserDB) DeleteTodo(id int) error {
|
|
_, err := user_db.DB.Exec("DELETE FROM items WHERE id=?", id)
|
|
return err
|
|
}
|