1
0
dwelling-home/pkg/mindflow/database/sqlite/db.go

302 lines
5.7 KiB
Go

package sqlite
import (
"database/sql"
_ "embed"
"fmt"
"time"
"git.arav.su/Arav/dwelling-home/pkg/mindflow"
"github.com/pkg/errors"
)
var (
//go:embed queries/schema.sql
querySchema string
//go:embed queries/categoryGetAll.sql
queryCategoryGetAll string
//go:embed queries/categoryNew.sql
queryCategoryNew string
//go:embed queries/categoryEdit.sql
queryCategoryEdit string
//go:embed queries/categoryDelete.sql
queryCategoryDelete string
//go:embed queries/postGetAll.sql
queryPostGetAll string
//go:embed queries/postNew.sql
queryPostNew string
//go:embed queries/postEdit.sql
queryPostEdit string
//go:embed queries/postDelete.sql
queryPostDelete string
)
var (
stmtCategoryGetAll *sql.Stmt
stmtCategoryNew *sql.Stmt
stmtCategoryEdit *sql.Stmt
stmtCategoryDelete *sql.Stmt
stmtPostGetAll *sql.Stmt
stmtPostNew *sql.Stmt
stmtPostEdit *sql.Stmt
stmtPostDelete *sql.Stmt
)
func initDBStatements(db *sql.DB) error {
db.Exec("PRAGMA foreign_keys = ON;")
_, err := db.Exec(querySchema)
if err != nil {
return errors.Wrap(err, "failed to init schema")
}
stmtCategoryGetAll, err = db.Prepare(queryCategoryGetAll)
if err != nil {
return errors.Wrap(err, "failed to prepare queryCategoryGetAll")
}
stmtCategoryNew, err = db.Prepare(queryCategoryNew)
if err != nil {
return errors.Wrap(err, "failed to prepare queryCategoryNew")
}
stmtCategoryEdit, err = db.Prepare(queryCategoryEdit)
if err != nil {
return errors.Wrap(err, "failed to prepare queryCategoryEdit")
}
stmtCategoryDelete, err = db.Prepare(queryCategoryDelete)
if err != nil {
return errors.Wrap(err, "failed to prepare queryCategoryDelete")
}
stmtPostGetAll, err = db.Prepare(queryPostGetAll)
if err != nil {
return errors.Wrap(err, "failed to prepare queryPostGetAll")
}
stmtPostNew, err = db.Prepare(queryPostNew)
if err != nil {
return errors.Wrap(err, "failed to prepare queryPostNew")
}
stmtPostEdit, err = db.Prepare(queryPostEdit)
if err != nil {
return errors.Wrap(err, "failed to prepare queryPostEdit")
}
stmtPostDelete, err = db.Prepare(queryPostDelete)
if err != nil {
return errors.Wrap(err, "failed to prepare queryPostDelete")
}
return nil
}
type SQLiteMindflow struct {
db *sql.DB
}
func New(path string) (mindflow.Mindflow, error) {
db, err := sql.Open("sqlite3", dsn(path))
if err != nil {
return nil, err
}
if err := initDBStatements(db); err != nil {
return nil, err
}
return &SQLiteMindflow{db: db}, nil
}
func dsn(filePath string) string {
return fmt.Sprintf("file:%s?_journal=WAL&_mutex=full", filePath)
}
func (s *SQLiteMindflow) NewPost(post *mindflow.Post) error {
tx, err := s.db.Begin()
if err != nil {
return err
}
defer tx.Rollback()
r, err := tx.Stmt(stmtPostNew).Exec(post.Category.ID, post.Date.UTC().Unix(),
post.Title, post.URL, post.Body)
if err != nil {
return err
}
post.ID, err = r.LastInsertId()
if err != nil {
return err
}
tx.Commit()
return nil
}
func (s *SQLiteMindflow) EditPost(post *mindflow.Post) error {
tx, err := s.db.Begin()
if err != nil {
return err
}
defer tx.Rollback()
_, err = tx.Stmt(stmtPostEdit).Exec(post.Category.ID, post.Title, post.URL,
post.Body, post.ID)
if err != nil {
return err
}
tx.Commit()
return nil
}
func (s *SQLiteMindflow) DeletePost(id int64) error {
tx, err := s.db.Begin()
if err != nil {
return err
}
defer tx.Rollback()
if _, err = tx.Stmt(stmtPostDelete).Exec(id); err != nil {
return err
}
tx.Commit()
return nil
}
func (s *SQLiteMindflow) Posts() (posts []mindflow.Post, err error) {
tx, err := s.db.Begin()
if err != nil {
return nil, err
}
defer tx.Rollback()
rows, err := tx.Stmt(stmtPostGetAll).Query()
if err != nil {
return nil, err
}
defer rows.Close()
for rows.Next() {
var post mindflow.Post
var date_unix int64
if err = rows.Scan(&post.ID, &post.Category.ID, &post.Category.Name,
&date_unix, &post.Title, &post.URL, &post.Body); err != nil {
return nil, err
}
post.Date = time.Unix(date_unix, 0)
posts = append(posts, post)
}
tx.Commit()
return posts, nil
}
func (s *SQLiteMindflow) NewCategory(category *mindflow.Category) (int64, error) {
tx, err := s.db.Begin()
if err != nil {
return 0, err
}
defer tx.Rollback()
r, err := tx.Stmt(stmtCategoryNew).Exec(category.Name)
if err != nil {
return 0, err
}
id, err := r.LastInsertId()
if err != nil {
return 0, err
}
tx.Commit()
return id, nil
}
func (s *SQLiteMindflow) EditCategory(category *mindflow.Category) error {
tx, err := s.db.Begin()
if err != nil {
return err
}
defer tx.Rollback()
_, err = tx.Stmt(stmtCategoryEdit).Exec(category.Name, category.ID)
if err != nil {
return err
}
tx.Commit()
return nil
}
func (s *SQLiteMindflow) DeleteCategory(id int64) (err error) {
tx, err := s.db.Begin()
if err != nil {
return err
}
defer tx.Rollback()
if _, err = tx.Stmt(stmtCategoryDelete).Exec(id); err != nil {
return err
}
tx.Commit()
return nil
}
func (s *SQLiteMindflow) Categories() (categories []mindflow.Category, err error) {
tx, err := s.db.Begin()
if err != nil {
return nil, err
}
defer tx.Rollback()
rows, err := tx.Stmt(stmtCategoryGetAll).Query()
if err != nil {
return nil, err
}
defer rows.Close()
for rows.Next() {
var category mindflow.Category
if err = rows.Scan(&category.ID, &category.Name); err != nil {
return nil, err
}
categories = append(categories, category)
}
tx.Commit()
return categories, nil
}
func (s *SQLiteMindflow) Close() error {
stmtCategoryGetAll.Close()
stmtCategoryNew.Close()
stmtCategoryEdit.Close()
stmtCategoryDelete.Close()
stmtPostDelete.Close()
stmtPostEdit.Close()
stmtPostGetAll.Close()
stmtPostNew.Close()
return s.db.Close()
}