diff --git a/cmd/dwelling-home/main.go b/cmd/dwelling-home/main.go index 65f3c79..94fb664 100644 --- a/cmd/dwelling-home/main.go +++ b/cmd/dwelling-home/main.go @@ -105,6 +105,7 @@ func main() { mindflowApi := http.NewMindflowApiHandlers(mindflowDB) srv.POST("/api/mindflow", mindflowApi.New) + srv.DELETE("/api/mindflow/category", mindflowApi.DeleteUnusedCategories) srv.PATCH("/api/mindflow/:id", mindflowApi.Edit) srv.DELETE("/api/mindflow/:id", mindflowApi.Delete) diff --git a/internal/http/api_handlers.go b/internal/http/api_handlers.go index 75891b3..0300313 100644 --- a/internal/http/api_handlers.go +++ b/internal/http/api_handlers.go @@ -3,6 +3,7 @@ package http import ( "fmt" "image/jpeg" + "log" "net/http" "strconv" "strings" @@ -252,6 +253,14 @@ func (h *MindflowApiHandlers) New(w http.ResponseWriter, r *http.Request) { http.Redirect(w, r, "/mindflow/admin", http.StatusMovedPermanently) } +func (h *MindflowApiHandlers) DeleteUnusedCategories(w http.ResponseWriter, r *http.Request) { + if err := h.db.DeleteUnusedCategories(); err != nil { + log.Println("Cannot delete unused categories:", err) + http.Error(w, "Cannot delete unused categories: "+err.Error(), http.StatusInternalServerError) + return + } +} + func (h *MindflowApiHandlers) Edit(w http.ResponseWriter, r *http.Request) { var post *mindflow.Post var err error diff --git a/pkg/mindflow/database/sqlite/db.go b/pkg/mindflow/database/sqlite/db.go index 61ae632..2398b6b 100644 --- a/pkg/mindflow/database/sqlite/db.go +++ b/pkg/mindflow/database/sqlite/db.go @@ -22,6 +22,8 @@ var ( queryCategoryNew string //go:embed queries/categoryDelete.sql queryCategoryDelete string + //go:embed queries/categoryDeleteUnused.sql + queryCategoryDeleteUnused string //go:embed queries/postGetAll.sql queryPostGetAll string //go:embed queries/postNew.sql @@ -33,14 +35,15 @@ var ( ) var ( - stmtCategoryById *sql.Stmt - stmtCategoryGetAll *sql.Stmt - stmtCategoryNew *sql.Stmt - stmtCategoryDelete *sql.Stmt - stmtPostGetAll *sql.Stmt - stmtPostNew *sql.Stmt - stmtPostEdit *sql.Stmt - stmtPostDelete *sql.Stmt + stmtCategoryById *sql.Stmt + stmtCategoryGetAll *sql.Stmt + stmtCategoryNew *sql.Stmt + stmtCategoryDelete *sql.Stmt + stmtCategoryDeleteUnused *sql.Stmt + stmtPostGetAll *sql.Stmt + stmtPostNew *sql.Stmt + stmtPostEdit *sql.Stmt + stmtPostDelete *sql.Stmt ) func initDBStatements(db *sql.DB) error { @@ -71,6 +74,11 @@ func initDBStatements(db *sql.DB) error { return errors.Wrap(err, "failed to prepare queryCategoryDelete") } + stmtCategoryDeleteUnused, err = db.Prepare(queryCategoryDeleteUnused) + if err != nil { + return errors.Wrap(err, "failed to prepare queryCategoryDeleteUnused") + } + stmtPostGetAll, err = db.Prepare(queryPostGetAll) if err != nil { return errors.Wrap(err, "failed to prepare queryPostGetAll") @@ -288,6 +296,22 @@ func (s *SQLiteMindflow) DeleteCategory(id int64) (err error) { return nil } +func (s *SQLiteMindflow) DeleteUnusedCategories() (err error) { + tx, err := s.db.Begin() + if err != nil { + return err + } + defer tx.Rollback() + + if _, err = tx.Stmt(stmtCategoryDeleteUnused).Exec(); err != nil { + return err + } + + tx.Commit() + + return nil +} + func (s *SQLiteMindflow) Close() error { stmtCategoryById.Close() stmtCategoryGetAll.Close() diff --git a/pkg/mindflow/database/sqlite/queries/categoryDeleteUnused.sql b/pkg/mindflow/database/sqlite/queries/categoryDeleteUnused.sql new file mode 100644 index 0000000..6f1a3b5 --- /dev/null +++ b/pkg/mindflow/database/sqlite/queries/categoryDeleteUnused.sql @@ -0,0 +1,6 @@ +DELETE FROM `category` + WHERE `category`.`category_id` NOT IN ( + SELECT `category_id` + FROM `post` + GROUP BY `post`.`category_id` + HAVING COUNT(`post`.`post_id`) > 0 ); \ No newline at end of file diff --git a/pkg/mindflow/mindflow.go b/pkg/mindflow/mindflow.go index 1dad008..5978438 100644 --- a/pkg/mindflow/mindflow.go +++ b/pkg/mindflow/mindflow.go @@ -43,5 +43,6 @@ type Mindflow interface { Categories() ([]Category, error) NewCategory(name string) (int64, error) GetCategoryByID(id int64) (string, error) + DeleteUnusedCategories() error Close() error }