Storage is now complete. Retrieval is partially implemented.
This commit is contained in:
parent
77dddef201
commit
446ff8f5ba
5
main.cpp
5
main.cpp
|
@ -30,11 +30,10 @@ int main(int argc, char *argv[])
|
||||||
bool success = recipeDB.storeRecipe(rec);
|
bool success = recipeDB.storeRecipe(rec);
|
||||||
printf("Storage successful: %d\n", success);
|
printf("Storage successful: %d\n", success);
|
||||||
|
|
||||||
recipeDB.executeSQL("SELECT * FROM recipeIngredient;").printData();
|
|
||||||
|
|
||||||
Recipe reloadRec = recipeDB.retrieveRecipe("Example");
|
Recipe reloadRec = recipeDB.retrieveRecipe("Example");
|
||||||
|
reloadRec.print();
|
||||||
|
|
||||||
w.loadFromRecipe(rec);
|
w.loadFromRecipe(reloadRec);
|
||||||
|
|
||||||
return a.exec();
|
return a.exec();
|
||||||
}
|
}
|
||||||
|
|
|
@ -8,7 +8,6 @@ bool RecipeDatabase::storeRecipe(Recipe recipe){
|
||||||
///TODO: Implement this in a smart way using transaction.
|
///TODO: Implement this in a smart way using transaction.
|
||||||
this->executeSQL("BEGIN;");
|
this->executeSQL("BEGIN;");
|
||||||
ResultTable t = this->selectFrom("recipe", "*", "name="+surroundString(recipe.getName(), "'"));
|
ResultTable t = this->selectFrom("recipe", "*", "name="+surroundString(recipe.getName(), "'"));
|
||||||
//ResultTable t = this->executeSQL("SELECT * FROM recipe WHERE name='"+recipe.getName()+"';");
|
|
||||||
if (!t.isEmpty()){
|
if (!t.isEmpty()){
|
||||||
fprintf(stderr, "Error storing recipe: Recipe with name %s already exists.\n", recipe.getName().c_str());
|
fprintf(stderr, "Error storing recipe: Recipe with name %s already exists.\n", recipe.getName().c_str());
|
||||||
} else {
|
} else {
|
||||||
|
@ -28,7 +27,7 @@ bool RecipeDatabase::storeRecipe(Recipe recipe){
|
||||||
std::to_string(recipe.getServings())
|
std::to_string(recipe.getServings())
|
||||||
}));
|
}));
|
||||||
if (success){
|
if (success){
|
||||||
//If successful, proceed to insert instructions, image, and ingredients.
|
//If successful, proceed to insert instructions, image, and ingredients, and tags.
|
||||||
int recipeId = this->getLastInsertedRowId();
|
int recipeId = this->getLastInsertedRowId();
|
||||||
bool ingredientSuccess = true;
|
bool ingredientSuccess = true;
|
||||||
for (unsigned int i = 0; i < recipe.getIngredients().size(); i++){
|
for (unsigned int i = 0; i < recipe.getIngredients().size(); i++){
|
||||||
|
@ -37,7 +36,10 @@ bool RecipeDatabase::storeRecipe(Recipe recipe){
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
if (ingredientSuccess && this->storeInstruction(recipe.getInstruction(), recipeId) && this->storeImage(recipe.getImage(), recipeId)){
|
if (ingredientSuccess &&
|
||||||
|
this->storeInstruction(recipe.getInstruction(), recipeId) &&
|
||||||
|
this->storeImage(recipe.getImage(), recipeId) &&
|
||||||
|
this->storeTags(recipe.getTags(), recipeId)){
|
||||||
this->executeSQL("COMMIT;");
|
this->executeSQL("COMMIT;");
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
@ -50,7 +52,6 @@ bool RecipeDatabase::storeRecipe(Recipe recipe){
|
||||||
bool RecipeDatabase::storeRecipeIngredient(RecipeIngredient ri, int recipeId){
|
bool RecipeDatabase::storeRecipeIngredient(RecipeIngredient ri, int recipeId){
|
||||||
//First check if the base ingredient has been added to the database. This is done within storeIngredient().
|
//First check if the base ingredient has been added to the database. This is done within storeIngredient().
|
||||||
ResultTable t = this->selectFrom("ingredient", "ingredientId", "name="+surroundString(ri.getName(), "'"));
|
ResultTable t = this->selectFrom("ingredient", "ingredientId", "name="+surroundString(ri.getName(), "'"));
|
||||||
//ResultTable t = this->executeSQL("SELECT ingredientId FROM ingredient WHERE name='"+ri.getName()+"';");
|
|
||||||
int ingId = 0;
|
int ingId = 0;
|
||||||
if (t.isEmpty()){
|
if (t.isEmpty()){
|
||||||
if (!this->insertInto("ingredient", vector<string>({"foodGroup", "name"}), vector<string>({ri.getFoodGroup(), ri.getName()}))){
|
if (!this->insertInto("ingredient", vector<string>({"foodGroup", "name"}), vector<string>({ri.getFoodGroup(), ri.getName()}))){
|
||||||
|
@ -79,7 +80,6 @@ bool RecipeDatabase::storeRecipeIngredient(RecipeIngredient ri, int recipeId){
|
||||||
|
|
||||||
void RecipeDatabase::storeIngredient(Ingredient ingredient){
|
void RecipeDatabase::storeIngredient(Ingredient ingredient){
|
||||||
ResultTable t = this->selectFrom("ingredient", "*", "name="+surroundString(ingredient.getName(), "'"));
|
ResultTable t = this->selectFrom("ingredient", "*", "name="+surroundString(ingredient.getName(), "'"));
|
||||||
//ResultTable t = this->executeSQL("SELECT * FROM ingredient WHERE name='"+ingredient.getName()+"';");
|
|
||||||
if (t.isEmpty()){
|
if (t.isEmpty()){
|
||||||
this->insertInto("ingredient", vector<string>({"foodGroup", "name"}), vector<string>({ingredient.getFoodGroup(), ingredient.getName()}));
|
this->insertInto("ingredient", vector<string>({"foodGroup", "name"}), vector<string>({ingredient.getFoodGroup(), ingredient.getName()}));
|
||||||
}
|
}
|
||||||
|
@ -93,6 +93,24 @@ bool RecipeDatabase::storeImage(QImage image, int recipeId){
|
||||||
return FileUtils::saveImage(recipeId, image);
|
return FileUtils::saveImage(recipeId, image);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
bool RecipeDatabase::storeTags(vector<RecipeTag> tags, int recipeId){
|
||||||
|
for (vector<RecipeTag>::iterator it = tags.begin(); it != tags.end(); ++it){
|
||||||
|
bool s = this->insertInto("recipeTag",
|
||||||
|
vector<string>({
|
||||||
|
"recipeId",
|
||||||
|
"tagName"
|
||||||
|
}),
|
||||||
|
vector<string>({
|
||||||
|
std::to_string(recipeId),
|
||||||
|
(*it).getValue()
|
||||||
|
}));
|
||||||
|
if (!s){
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
Recipe RecipeDatabase::retrieveRecipe(string name){
|
Recipe RecipeDatabase::retrieveRecipe(string name){
|
||||||
ResultTable t = this->selectFrom("recipe", "*", "name="+surroundString(name, "'"));
|
ResultTable t = this->selectFrom("recipe", "*", "name="+surroundString(name, "'"));
|
||||||
if (t.isEmpty()){
|
if (t.isEmpty()){
|
||||||
|
@ -100,12 +118,39 @@ Recipe RecipeDatabase::retrieveRecipe(string name){
|
||||||
return Recipe();
|
return Recipe();
|
||||||
}
|
}
|
||||||
t.printData();
|
t.printData();
|
||||||
return Recipe();
|
Recipe r;
|
||||||
|
int id = std::stoi(t.valueAt(0, 0));
|
||||||
|
r.setName(t.valueAt(0, 1));
|
||||||
|
r.setCreatedDate(QDate::fromString(QString::fromStdString(t.valueAt(0, 2))));
|
||||||
|
r.setPrepTime(QTime::fromString(QString::fromStdString(t.valueAt(0, 3))));
|
||||||
|
r.setCookTime(QTime::fromString(QString::fromStdString(t.valueAt(0, 4))));
|
||||||
|
r.setServings(std::stof(t.valueAt(0, 5)));
|
||||||
|
r.setInstruction(FileUtils::loadInstruction(id));
|
||||||
|
r.setImage(FileUtils::loadImage(id));
|
||||||
|
r.setIngredients(this->retrieveRecipeIngredients(id));
|
||||||
|
return r;
|
||||||
|
}
|
||||||
|
|
||||||
|
vector<RecipeIngredient> RecipeDatabase::retrieveRecipeIngredients(int recipeId){
|
||||||
|
ResultTable t = this->executeSQL("SELECT ingredient.name, ingredient.foodGroup, recipeIngredient.quantity, recipeIngredient.unitName, recipeIngredient.comment "
|
||||||
|
"FROM ingredient "
|
||||||
|
"INNER JOIN recipeIngredient "
|
||||||
|
"ON ingredient.ingredientId = recipeIngredient.ingredientId "
|
||||||
|
"AND recipeIngredient.recipeId = "+std::to_string(recipeId)+";");
|
||||||
|
t.printData();
|
||||||
|
vector<RecipeIngredient> ings;
|
||||||
|
for (unsigned int row = 0; row < t.rowCount(); row++){
|
||||||
|
RecipeIngredient r(t.valueAt(row, 0), t.valueAt(row, 1), std::stof(t.valueAt(row, 2)), UnitOfMeasure(t.valueAt(row, 3)));
|
||||||
|
ings.push_back(r);
|
||||||
|
}
|
||||||
|
return ings;
|
||||||
}
|
}
|
||||||
|
|
||||||
void RecipeDatabase::ensureTablesExist(){
|
void RecipeDatabase::ensureTablesExist(){
|
||||||
//Make sure that foreign keys are enabled.
|
//Make sure that foreign keys are enabled.
|
||||||
this->executeSQL("PRAGMA foreign_keys = ON;");
|
this->executeSQL("PRAGMA foreign_keys = ON;");
|
||||||
|
|
||||||
|
this->executeSQL("BEGIN;");
|
||||||
//Ingredients table.
|
//Ingredients table.
|
||||||
this->executeSQL("CREATE TABLE IF NOT EXISTS ingredient("
|
this->executeSQL("CREATE TABLE IF NOT EXISTS ingredient("
|
||||||
"ingredientId INTEGER PRIMARY KEY,"
|
"ingredientId INTEGER PRIMARY KEY,"
|
||||||
|
@ -114,14 +159,14 @@ void RecipeDatabase::ensureTablesExist(){
|
||||||
//Recipe table. Each recipe can have at most one instruction, and one image.
|
//Recipe table. Each recipe can have at most one instruction, and one image.
|
||||||
this->executeSQL("CREATE TABLE IF NOT EXISTS recipe("
|
this->executeSQL("CREATE TABLE IF NOT EXISTS recipe("
|
||||||
"recipeId INTEGER PRIMARY KEY,"
|
"recipeId INTEGER PRIMARY KEY,"
|
||||||
"createdDate date,"
|
|
||||||
"name varchar UNIQUE,"
|
"name varchar UNIQUE,"
|
||||||
"cookTime time,"
|
"createdDate date,"
|
||||||
"prepTime time,"
|
"prepTime time,"
|
||||||
|
"cookTime time,"
|
||||||
"servingCount real);");
|
"servingCount real);");
|
||||||
//Recipe tags table.
|
//Recipe tags table.
|
||||||
this->executeSQL("CREATE TABLE IF NOT EXISTS recipeTag("
|
this->executeSQL("CREATE TABLE IF NOT EXISTS recipeTag("
|
||||||
"recipeId INTEGER PRIMARY KEY,"
|
"recipeId int,"
|
||||||
"tagName varchar,"
|
"tagName varchar,"
|
||||||
"FOREIGN KEY (recipeId) REFERENCES recipe(recipeId));");
|
"FOREIGN KEY (recipeId) REFERENCES recipe(recipeId));");
|
||||||
//RecipeIngredient table.
|
//RecipeIngredient table.
|
||||||
|
@ -133,4 +178,5 @@ void RecipeDatabase::ensureTablesExist(){
|
||||||
"comment varchar,"
|
"comment varchar,"
|
||||||
"FOREIGN KEY (ingredientId) REFERENCES ingredient(ingredientId),"
|
"FOREIGN KEY (ingredientId) REFERENCES ingredient(ingredientId),"
|
||||||
"FOREIGN KEY (recipeId) REFERENCES recipe(recipeId));");
|
"FOREIGN KEY (recipeId) REFERENCES recipe(recipeId));");
|
||||||
|
this->executeSQL("COMMIT;");
|
||||||
}
|
}
|
||||||
|
|
|
@ -26,8 +26,10 @@ class RecipeDatabase : public Database
|
||||||
void storeIngredient(Ingredient ingredient);
|
void storeIngredient(Ingredient ingredient);
|
||||||
bool storeInstruction(Instruction instruction, int recipeId);
|
bool storeInstruction(Instruction instruction, int recipeId);
|
||||||
bool storeImage(QImage image, int recipeId);
|
bool storeImage(QImage image, int recipeId);
|
||||||
|
bool storeTags(vector<RecipeTag> tags, int recipeId);
|
||||||
|
|
||||||
Recipe retrieveRecipe(string name);
|
Recipe retrieveRecipe(string name);
|
||||||
|
vector<RecipeIngredient> retrieveRecipeIngredients(int recipeId);
|
||||||
private:
|
private:
|
||||||
|
|
||||||
//Utility methods.
|
//Utility methods.
|
||||||
|
|
|
@ -9,7 +9,11 @@ RecipeIngredient::RecipeIngredient(Ingredient i, float quantity, UnitOfMeasure u
|
||||||
setName(i.getName());
|
setName(i.getName());
|
||||||
setFoodGroup(i.getFoodGroup());
|
setFoodGroup(i.getFoodGroup());
|
||||||
setQuantity(quantity);
|
setQuantity(quantity);
|
||||||
setUnit(unit);
|
setUnit(unit);
|
||||||
|
}
|
||||||
|
|
||||||
|
RecipeIngredient::RecipeIngredient(){
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
float RecipeIngredient::getQuantity() const{
|
float RecipeIngredient::getQuantity() const{
|
||||||
|
|
|
@ -19,6 +19,7 @@ public:
|
||||||
RecipeIngredient(string name, string foodGroup, float quantity, UnitOfMeasure unit);
|
RecipeIngredient(string name, string foodGroup, float quantity, UnitOfMeasure unit);
|
||||||
//Constructor using data from a child ingredient.
|
//Constructor using data from a child ingredient.
|
||||||
RecipeIngredient(Ingredient i, float quantity, UnitOfMeasure unit);
|
RecipeIngredient(Ingredient i, float quantity, UnitOfMeasure unit);
|
||||||
|
RecipeIngredient();
|
||||||
|
|
||||||
//Getters
|
//Getters
|
||||||
float getQuantity() const;
|
float getQuantity() const;
|
||||||
|
|
|
@ -3,7 +3,14 @@
|
||||||
UnitOfMeasure::UnitOfMeasure(string name, string plural, string abbreviation){
|
UnitOfMeasure::UnitOfMeasure(string name, string plural, string abbreviation){
|
||||||
this->name = name;
|
this->name = name;
|
||||||
this->plural = plural;
|
this->plural = plural;
|
||||||
this->abbreviation = abbreviation;
|
this->abbreviation = abbreviation;
|
||||||
|
}
|
||||||
|
|
||||||
|
UnitOfMeasure::UnitOfMeasure(string name){
|
||||||
|
this->name = name;
|
||||||
|
this->plural = name + "s";
|
||||||
|
this->abbreviation = "NULL";
|
||||||
|
///TODO: Make actual guessing of this stuff.
|
||||||
}
|
}
|
||||||
|
|
||||||
UnitOfMeasure::UnitOfMeasure() : UnitOfMeasure::UnitOfMeasure("", "", ""){
|
UnitOfMeasure::UnitOfMeasure() : UnitOfMeasure::UnitOfMeasure("", "", ""){
|
||||||
|
|
|
@ -14,6 +14,8 @@ class UnitOfMeasure
|
||||||
public:
|
public:
|
||||||
//Full constructor.
|
//Full constructor.
|
||||||
UnitOfMeasure(string name, string plural, string abbreviation);
|
UnitOfMeasure(string name, string plural, string abbreviation);
|
||||||
|
//Attempt to guess unit from just a string.
|
||||||
|
UnitOfMeasure(string name);
|
||||||
//Constructor with default values.
|
//Constructor with default values.
|
||||||
UnitOfMeasure();
|
UnitOfMeasure();
|
||||||
|
|
||||||
|
|
|
@ -29,7 +29,11 @@ Instruction Recipe::getInstruction() const{
|
||||||
}
|
}
|
||||||
|
|
||||||
QImage Recipe::getImage() const{
|
QImage Recipe::getImage() const{
|
||||||
return this->image;
|
return this->image;
|
||||||
|
}
|
||||||
|
|
||||||
|
vector<RecipeTag> Recipe::getTags() const{
|
||||||
|
return this->tags;
|
||||||
}
|
}
|
||||||
|
|
||||||
QDate Recipe::getCreatedDate() const{
|
QDate Recipe::getCreatedDate() const{
|
||||||
|
@ -89,5 +93,29 @@ void Recipe::setCookTime(QTime newTime){
|
||||||
}
|
}
|
||||||
|
|
||||||
void Recipe::setServings(float newServingsCount){
|
void Recipe::setServings(float newServingsCount){
|
||||||
this->servings = newServingsCount;
|
this->servings = newServingsCount;
|
||||||
|
}
|
||||||
|
|
||||||
|
void Recipe::print(){
|
||||||
|
printf("Recipe: %s, Created on: %s, Prep time: %s, Cook time: %s, Serves: %f\n",
|
||||||
|
this->name.c_str(),
|
||||||
|
this->createdDate.toString().toStdString().c_str(),
|
||||||
|
this->prepTime.toString().toStdString().c_str(),
|
||||||
|
this->cookTime.toString().toStdString().c_str(),
|
||||||
|
this->servings);
|
||||||
|
printf("\tInstruction: %s\n", this->instruction.getHTML().c_str());
|
||||||
|
printf("\tIngredients:\n");
|
||||||
|
for (vector<RecipeIngredient>::iterator it = this->ingredients.begin(); it != this->ingredients.end(); ++it){
|
||||||
|
RecipeIngredient ri = *it;
|
||||||
|
printf("\t\t%s, Food Group: %s, Quantity: %f, Unit: %s\n",
|
||||||
|
ri.getName().c_str(),
|
||||||
|
ri.getFoodGroup().c_str(),
|
||||||
|
ri.getQuantity(),
|
||||||
|
ri.getUnit().getName().c_str());
|
||||||
|
}
|
||||||
|
printf("\tTags:\n");
|
||||||
|
for (vector<RecipeTag>::iterator it = this->tags.begin(); it != this->tags.end(); ++it){
|
||||||
|
RecipeTag t = *it;
|
||||||
|
printf("\t\t%s\n", t.getValue().c_str());
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -58,6 +58,8 @@ public:
|
||||||
void setPrepTime(QTime newTime);
|
void setPrepTime(QTime newTime);
|
||||||
void setCookTime(QTime newTime);
|
void setCookTime(QTime newTime);
|
||||||
void setServings(float newServingsCount);
|
void setServings(float newServingsCount);
|
||||||
|
|
||||||
|
void print();
|
||||||
private:
|
private:
|
||||||
//Main information.
|
//Main information.
|
||||||
string name; //The name of the recipe.
|
string name; //The name of the recipe.
|
||||||
|
|
Loading…
Reference in New Issue