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/categoryById.sql queryCategoryById string //go:embed queries/categoryNew.sql queryCategoryNew 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 ( stmtCategoryById *sql.Stmt stmtCategoryNew *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") } stmtCategoryById, err = db.Prepare(queryCategoryById) if err != nil { return errors.Wrap(err, "failed to prepare queryCategoryById") } stmtCategoryNew, err = db.Prepare(queryCategoryNew) if err != nil { return errors.Wrap(err, "failed to prepare queryCategoryNew") } 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 NewSQLiteMindflow(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) New(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.Body) if err != nil { return err } post.ID, err = r.LastInsertId() if err != nil { return err } tx.Commit() return nil } func (s *SQLiteMindflow) Edit(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.Body, post.ID) if err != nil { return err } tx.Commit() return nil } func (s *SQLiteMindflow) Delete(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) GetAll() (posts []mindflow.Post, err error) { tx, err := s.db.Begin() if err != nil { return nil, err } 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.Body); err != nil { return nil, err } post.Date = time.Unix(date_unix, 0) posts = append(posts, post) } defer tx.Rollback() return nil, nil } func (s *SQLiteMindflow) NewCategory(name string) (int64, error) { tx, err := s.db.Begin() if err != nil { return 0, err } defer tx.Rollback() r, err := tx.Stmt(stmtPostNew).Exec(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) GetCategoryByID(id int64) (string, error) { return "", nil }