diff --git a/src/arg_parse.hpp b/src/arg_parse.hpp index 4dba86c..d64dee1 100644 --- a/src/arg_parse.hpp +++ b/src/arg_parse.hpp @@ -27,6 +27,7 @@ enum cmd_id { CMD_ADD, CMD_LIST, CMD_DEL, + CMD_INFO, CMD_HELP, CMD_VERSION, }; @@ -35,6 +36,7 @@ static const std::map> commands = { { CMD_ADD, {"add", "new"} }, { CMD_LIST, {"list", "ls"} }, { CMD_DEL, {"del", "rm"} }, + { CMD_INFO, { "info" } }, { CMD_HELP, {"help", "-h", "--help"} }, { CMD_VERSION, {"version", "-v", "--version"} }, }; @@ -55,6 +57,7 @@ static inline void print_help(void) { "\tadd, new Add a new recipe to the database.\n" "\tlist, ls List recipes with filters.\n" "\tdel, rm Delete recipe by ID.\n" + "\tinfo Show recipe information.\n" "\thelp, -h, --help Show this help information.\n" "\tversion, -v, --version Show version information.\n" << std::endl; diff --git a/src/cmd.cpp b/src/cmd.cpp index eb5958c..5226434 100644 --- a/src/cmd.cpp +++ b/src/cmd.cpp @@ -137,3 +137,42 @@ int command_delete(int argc, char *argv[]) { return ret; } + +int command_info(const int id) { + struct recipe recipe; + std::vector ingredients, tags; + int ret = EXIT_SUCCESS; + + if(not db_open()) { + std::cerr << "Failed to open database. Cannot add new entry." << std::endl; + return EXIT_FAILURE; + } + + if(not db_recipe_exists(id)) { + std::cerr << "No recipe with ID '" << id << "'"; + return EXIT_FAILURE; + } + + recipe = db_get_recipe(id); + ingredients = db_get_recipe_ingredients(id); + tags = db_get_recipe_tags(id); + + db_close(); + + std::cout << "Name: " << recipe.name << "\n" + << "Description: " << recipe.description << "\n" + << "ID: " << recipe.id << "\n" + << std::endl; + + std::cout << "Ingredients:" << std::endl; + for(auto &ingredient : ingredients) + std::cout << "\t- " << ingredient << std::endl; + std::cout << std::endl; + + std::cout << "Tags:" << std::endl; + for(auto &tag : tags) + std::cout << "\t- " << tag << std::endl; + std::cout << std::endl; + + return ret; +} diff --git a/src/cmd.hpp b/src/cmd.hpp index 58810f4..bb1906c 100644 --- a/src/cmd.hpp +++ b/src/cmd.hpp @@ -20,3 +20,4 @@ int command_add(void); int command_list(int argc, char *argv[]); int command_delete(int argc, char *argv[]); +int command_info(const int id); diff --git a/src/db.cpp b/src/db.cpp index 541ae92..a309440 100644 --- a/src/db.cpp +++ b/src/db.cpp @@ -167,6 +167,18 @@ int db_get_recipe_id(const std::string &name) { return table_get_id_by_name("recipes", name); } +struct recipe db_get_recipe(const int id) { + struct recipe recipe; + + sqlite3_exec(db, std::format("SELECT * FROM recipes WHERE id={};", id).c_str(), + [](void *recipe, int, char **col_data, char**) { + *static_cast(recipe) = { std::atoi(col_data[0]), col_data[1], col_data[2] }; + return 0; + }, &recipe, nullptr); + + return recipe; +} + std::vector db_get_recipes(const std::vector &ingredients, const std::vector &tags) { @@ -254,6 +266,18 @@ int db_add_ingredient(const std::string &name) { return db_get_ingredient_id(name); } +std::vector db_get_recipe_ingredients(const int id) { + std::vector ingredients; + + sqlite3_exec(db, std::format("SELECT name FROM ingredients WHERE id IN (SELECT ingredient_id FROM recipe_ingredient WHERE recipe_id={});", id).c_str(), + [](void *ingredients, int, char **col_data, char**) { + static_cast*>(ingredients)->push_back(col_data[0]); + return 0; + }, &ingredients, nullptr); + + return ingredients; +} + int db_get_ingredient_id(const std::string &name) { if(not db) return -1; @@ -272,6 +296,18 @@ int db_add_tag(const std::string &name) { return db_get_tag_id(name); } +std::vector db_get_recipe_tags(const int id) { + std::vector tags; + + sqlite3_exec(db, std::format("SELECT name FROM tags WHERE id IN (SELECT tag_id FROM recipe_tag WHERE recipe_id={});", id).c_str(), + [](void *tags, int, char **col_data, char**) { + static_cast*>(tags)->push_back(col_data[0]); + return 0; + }, &tags, nullptr); + + return tags; +} + int db_get_tag_id(const std::string &name) { if(not db) return -1; diff --git a/src/db.hpp b/src/db.hpp index 4bda5b7..0993d2b 100644 --- a/src/db.hpp +++ b/src/db.hpp @@ -45,6 +45,7 @@ bool db_recipe_exists(const int id); static inline bool db_recipe_exists(const std::string &name) { return (db_get_recipe_id(name) > 0); } +struct recipe db_get_recipe(const int id); std::vector db_get_recipes(const std::vector &ingredients, const std::vector &tags); @@ -56,6 +57,7 @@ std::vector db_get_recipes(const std::vector &ingred * @return ID of newly created ingredient, -1 if DB isn't open, -2 on other failure. */ int db_add_ingredient(const std::string &name); +std::vector db_get_recipe_ingredients(const int id); int db_get_ingredient_id(const std::string &name); static inline bool db_ingredient_exists(const std::string &name) { return (db_get_ingredient_id(name) > 0); @@ -69,6 +71,7 @@ static inline bool db_ingredient_exists(const std::string &name) { * @return ID of newly created tag, -1 if DB isn't open, -2 on other failure. */ int db_add_tag(const std::string &name); +std::vector db_get_recipe_tags(const int id); int db_get_tag_id(const std::string &name); static inline bool db_tag_exists(const std::string &name) { return (db_get_tag_id(name) > 0); diff --git a/src/main.cpp b/src/main.cpp index 0dc5c1c..8f91b30 100644 --- a/src/main.cpp +++ b/src/main.cpp @@ -18,6 +18,7 @@ #include #include +#include #include "arg_parse.hpp" #include "cmd.hpp" @@ -44,6 +45,9 @@ int main(int argc, char *argv[]) { case CMD_DEL: ret = command_delete(argc - 2, argv + 2); break; + case CMD_INFO: + ret = command_info(std::stoi(argv[2])); + break; case CMD_HELP: print_help(); break;