2018-03-01 16:19:13 +00:00
# include "recipedatabase.h"
RecipeDatabase : : RecipeDatabase ( string filename ) : Database ( filename ) {
this - > ensureTablesExist ( ) ;
}
2018-03-02 13:14:56 +00:00
bool RecipeDatabase : : storeRecipe ( Recipe recipe ) {
2018-03-29 09:21:00 +00:00
//Some primary checks to avoid garbage in the database.
if ( recipe . getName ( ) . empty ( ) | |
recipe . getInstruction ( ) . getHTML ( ) . empty ( ) | |
recipe . getIngredients ( ) . empty ( ) ) {
return false ;
}
2018-03-10 07:51:17 +00:00
//Store a recipe, if it doesn't already exist. This first tries to create the recipe entry, then all subsequent supporting table entries.
2018-03-03 07:38:32 +00:00
this - > executeSQL ( " BEGIN; " ) ;
2018-03-10 07:51:17 +00:00
ResultTable t = this - > selectFrom ( " recipe " , " * " , " WHERE name= " + surroundString ( recipe . getName ( ) , " ' " ) ) ;
2018-03-02 10:30:16 +00:00
if ( ! t . isEmpty ( ) ) {
fprintf ( stderr , " Error storing recipe: Recipe with name %s already exists. \n " , recipe . getName ( ) . c_str ( ) ) ;
} else {
bool success = this - > insertInto ( " recipe " ,
vector < string > ( {
" name " ,
" createdDate " ,
" cookTime " ,
" prepTime " ,
" servingCount "
} ) ,
vector < string > ( {
recipe . getName ( ) ,
recipe . getCreatedDate ( ) . toString ( ) . toStdString ( ) ,
recipe . getCookTime ( ) . toString ( ) . toStdString ( ) ,
recipe . getPrepTime ( ) . toString ( ) . toStdString ( ) ,
std : : to_string ( recipe . getServings ( ) )
} ) ) ;
if ( success ) {
2018-03-03 09:18:38 +00:00
//If successful, proceed to insert instructions, image, and ingredients, and tags.
2018-03-02 13:14:56 +00:00
int recipeId = this - > getLastInsertedRowId ( ) ;
2018-03-03 07:38:32 +00:00
bool ingredientSuccess = true ;
2018-03-02 13:14:56 +00:00
for ( unsigned int i = 0 ; i < recipe . getIngredients ( ) . size ( ) ; i + + ) {
if ( ! this - > storeRecipeIngredient ( recipe . getIngredients ( ) [ i ] , recipeId ) ) {
2018-03-03 07:38:32 +00:00
ingredientSuccess = false ;
break ;
2018-03-02 13:14:56 +00:00
}
}
2018-03-03 09:18:38 +00:00
if ( ingredientSuccess & &
this - > storeInstruction ( recipe . getInstruction ( ) , recipeId ) & &
this - > storeImage ( recipe . getImage ( ) , recipeId ) & &
this - > storeTags ( recipe . getTags ( ) , recipeId ) ) {
2018-03-03 07:38:32 +00:00
this - > executeSQL ( " COMMIT; " ) ;
return true ;
2018-03-02 13:14:56 +00:00
}
2018-03-02 10:30:16 +00:00
}
}
2018-03-03 07:38:32 +00:00
this - > executeSQL ( " ROLLBACK; " ) ;
return false ;
2018-03-02 10:30:16 +00:00
}
2018-03-02 13:14:56 +00:00
bool RecipeDatabase : : storeRecipeIngredient ( RecipeIngredient ri , int recipeId ) {
2018-03-10 07:51:17 +00:00
int ingId = this - > storeIngredient ( ri ) ;
if ( ingId < 0 ) return false ;
if ( ! this - > storeUnitOfMeasure ( ri . getUnit ( ) ) ) return false ;
2018-03-02 13:14:56 +00:00
return this - > insertInto ( " recipeIngredient " ,
vector < string > ( {
" ingredientId " ,
" recipeId " ,
" quantity " ,
" unitName " ,
" comment "
} ) ,
vector < string > ( {
std : : to_string ( ingId ) ,
std : : to_string ( recipeId ) ,
std : : to_string ( ri . getQuantity ( ) ) ,
ri . getUnit ( ) . getName ( ) ,
ri . getComment ( )
} ) ) ;
2018-03-01 16:28:18 +00:00
}
2018-03-10 07:51:17 +00:00
int RecipeDatabase : : storeIngredient ( Ingredient ingredient ) {
ResultTable t = this - > selectFrom ( " ingredient " , " * " , " WHERE name= " + surroundString ( ingredient . getName ( ) , " ' " ) ) ;
2018-03-02 13:14:56 +00:00
if ( t . isEmpty ( ) ) {
2018-03-10 07:51:17 +00:00
bool success = this - > insertInto ( " ingredient " , vector < string > ( { " foodGroup " , " name " } ) , vector < string > ( { ingredient . getFoodGroup ( ) , ingredient . getName ( ) } ) ) ;
if ( success ) {
return this - > getLastInsertedRowId ( ) ;
} else {
return - 1 ;
}
} else {
2018-03-30 10:29:10 +00:00
return std : : stoi ( t . at ( 0 , 0 ) ) ;
2018-03-02 10:30:16 +00:00
}
}
2018-03-10 07:51:17 +00:00
bool RecipeDatabase : : storeUnitOfMeasure ( UnitOfMeasure u ) {
ResultTable t = this - > selectFrom ( " unitOfMeasure " , " name " , " WHERE name= " + surroundString ( u . getName ( ) , " ' " ) ) ;
if ( ! t . isEmpty ( ) ) {
return true ;
}
bool success = this - > insertInto ( " unitOfMeasure " ,
vector < string > ( {
" name " ,
" plural " ,
" abbreviation " ,
" type " ,
" metricCoefficient "
} ) ,
vector < string > ( {
u . getName ( ) ,
u . getNamePlural ( ) ,
u . getAbbreviation ( ) ,
std : : to_string ( u . getType ( ) ) ,
std : : to_string ( u . getMetricCoefficient ( ) )
} ) ) ;
return success ;
}
2018-03-02 13:14:56 +00:00
bool RecipeDatabase : : storeInstruction ( Instruction instruction , int recipeId ) {
2018-03-03 07:38:32 +00:00
return FileUtils : : saveInstruction ( recipeId , instruction ) ;
2018-03-02 13:14:56 +00:00
}
bool RecipeDatabase : : storeImage ( QImage image , int recipeId ) {
return FileUtils : : saveImage ( recipeId , image ) ;
}
2018-03-03 09:18:38 +00:00
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 ;
}
2018-03-03 07:48:55 +00:00
Recipe RecipeDatabase : : retrieveRecipe ( string name ) {
2018-03-10 07:51:17 +00:00
ResultTable t = this - > selectFrom ( " recipe " , " * " , " WHERE name= " + surroundString ( name , " ' " ) ) ;
2018-03-03 07:48:55 +00:00
if ( t . isEmpty ( ) ) {
fprintf ( stderr , " Error: No recipe with name %s found! \n " , name . c_str ( ) ) ;
return Recipe ( ) ;
}
2018-03-29 14:09:58 +00:00
return this - > readFromResultTable ( t ) ;
}
Recipe RecipeDatabase : : retrieveRandomRecipe ( ) {
ResultTable t = this - > selectFrom ( " recipe " , " * " , " ORDER BY RANDOM() LIMIT 1 " ) ;
if ( t . isEmpty ( ) ) {
fprintf ( stderr , " Unable to find a random recipe. \n " ) ;
return Recipe ( ) ;
}
return this - > readFromResultTable ( t ) ;
2018-03-03 09:18:38 +00:00
}
2018-03-30 18:57:14 +00:00
//TODO: Change this to be more efficient! One query per recipe is not good!
2018-03-11 11:53:30 +00:00
vector < Recipe > RecipeDatabase : : retrieveAllRecipes ( ) {
2018-03-30 18:57:14 +00:00
ResultTable t = this - > executeSQL ( " SELECT * FROM recipe ORDER BY name; " ) ;
return this - > readRecipesFromTable ( t ) ;
}
vector < Recipe > RecipeDatabase : : retrieveRecipesWithIngredients ( vector < Ingredient > ingredients ) {
2018-03-11 11:53:30 +00:00
vector < Recipe > recipes ;
2018-03-30 18:57:14 +00:00
if ( ingredients . empty ( ) ) {
return recipes ;
2018-03-11 11:53:30 +00:00
}
2018-03-30 18:57:14 +00:00
string filterList = surroundString ( ingredients . at ( 0 ) . getName ( ) , " ' " ) ;
for ( unsigned int i = 1 ; i < ingredients . size ( ) ; i + + ) {
filterList + = " , " + surroundString ( ingredients [ i ] . getName ( ) , " ' " ) ;
}
filterList = ' ( ' + filterList + ' ) ' ;
ResultTable t = this - > executeSQL ( " SELECT * "
" FROM recipe "
" WHERE recipeId IN ( "
" SELECT recipeIngredient.recipeId "
" FROM recipeIngredient "
" INNER JOIN ( "
" SELECT ingredientId "
" FROM ingredient "
" WHERE name IN " + filterList + " "
" ) filteredIngredients "
" ON recipeIngredient.ingredientId = filteredIngredients.ingredientId "
" ) ORDER BY name; " ) ;
return this - > readRecipesFromTable ( t ) ;
2018-03-30 20:50:02 +00:00
}
vector < Recipe > RecipeDatabase : : retrieveRecipesWithTags ( vector < RecipeTag > tags ) {
vector < Recipe > recipes ;
if ( tags . empty ( ) ) {
return recipes ;
}
string filterList = surroundString ( tags . at ( 0 ) . getValue ( ) , " ' " ) ;
for ( unsigned int i = 1 ; i < tags . size ( ) ; i + + ) {
filterList + = " , " + surroundString ( tags [ i ] . getValue ( ) , " ' " ) ;
}
filterList = ' ( ' + filterList + ' ) ' ;
ResultTable t = this - > executeSQL ( " SELECT * FROM recipe WHERE recipeId IN (SELECT recipeId FROM recipeTag WHERE tagName IN " + filterList + " ); " ) ;
return this - > readRecipesFromTable ( t ) ;
}
vector < Recipe > RecipeDatabase : : retrieveRecipesWithSubstring ( string s ) {
ResultTable t = this - > executeSQL ( " SELECT * FROM recipe WHERE name LIKE '% " + s + " %' COLLATE NOCASE; " ) ;
return this - > readRecipesFromTable ( t ) ;
}
vector < Recipe > RecipeDatabase : : retrieveRecipesWithFoodGroups ( vector < string > groups ) {
vector < Recipe > recipes ;
if ( groups . empty ( ) ) {
return recipes ;
}
string filterList = surroundString ( groups . at ( 0 ) , " ' " ) ;
for ( unsigned int i = 1 ; i < groups . size ( ) ; i + + ) {
filterList + = " , " + surroundString ( groups . at ( i ) , " ' " ) ;
}
filterList = ' ( ' + filterList + ' ) ' ;
ResultTable t = this - > executeSQL ( " SELECT * FROM recipe WHERE recipeId IN (SELECT recipeId FROM recipeIngredient WHERE ingredientId IN (SELECT ingredientId FROM ingredient WHERE foodGroup IN " + filterList + " ) ) ORDER BY name; " ) ;
return this - > readRecipesFromTable ( t ) ;
2018-03-11 11:53:30 +00:00
}
2018-03-30 10:29:10 +00:00
vector < string > RecipeDatabase : : retrieveAllFoodGroups ( ) {
ResultTable t = this - > executeSQL ( " SELECT DISTINCT foodGroup FROM ingredient ORDER BY foodGroup; " ) ;
vector < string > foodGroups ;
for ( TableRow row : t . rows ( ) ) {
foodGroups . push_back ( row . at ( 0 ) ) ;
}
return foodGroups ;
}
2018-03-03 09:18:38 +00:00
vector < RecipeIngredient > RecipeDatabase : : retrieveRecipeIngredients ( int recipeId ) {
2018-03-10 07:51:17 +00:00
ResultTable t = this - > executeSQL ( " SELECT ingredient.name, ingredient.foodGroup, " //0, 1
" recipeIngredient.quantity, recipeIngredient.unitName, recipeIngredient.comment, " //2, 3, 4
" unitOfMeasure.name, unitOfMeasure.plural, unitOfMeasure.abbreviation, unitOfMeasure.type, unitOfMeasure.metricCoefficient " //5, 6, 7, 8, 9
2018-03-03 09:18:38 +00:00
" FROM ingredient "
" INNER JOIN recipeIngredient "
" ON ingredient.ingredientId = recipeIngredient.ingredientId "
2018-03-10 07:51:17 +00:00
" INNER JOIN unitOfMeasure "
" ON recipeIngredient.unitName = unitOfMeasure.name "
" WHERE recipeIngredient.recipeId = " + std : : to_string ( recipeId ) + " ; " ) ;
2018-03-03 09:18:38 +00:00
vector < RecipeIngredient > ings ;
2018-03-30 10:29:10 +00:00
for ( TableRow row : t . rows ( ) ) {
RecipeIngredient r ( row . at ( 0 ) ,
row . at ( 1 ) ,
std : : stof ( row . at ( 2 ) ) ,
UnitOfMeasure ( row . at ( 5 ) , row . at ( 6 ) , row . at ( 7 ) , std : : stoi ( row . at ( 8 ) ) , std : : stod ( row . at ( 9 ) ) ) ,
row . at ( 4 ) ) ;
2018-03-03 09:18:38 +00:00
ings . push_back ( r ) ;
}
return ings ;
2018-03-03 07:48:55 +00:00
}
2018-03-10 07:51:17 +00:00
vector < Ingredient > RecipeDatabase : : retrieveAllIngredients ( ) {
2018-03-30 10:29:10 +00:00
ResultTable t = this - > selectFrom ( " ingredient " , " name, foodGroup " , " ORDER BY name " ) ;
2018-03-10 07:51:17 +00:00
vector < Ingredient > ings ;
2018-03-30 10:29:10 +00:00
for ( TableRow row : t . rows ( ) ) {
Ingredient i ( row . at ( 0 ) , row . at ( 1 ) ) ;
2018-03-10 07:51:17 +00:00
ings . push_back ( i ) ;
}
return ings ;
}
vector < UnitOfMeasure > RecipeDatabase : : retrieveAllUnitsOfMeasure ( ) {
2018-03-30 10:29:10 +00:00
ResultTable t = this - > selectFrom ( " unitOfMeasure " , " name, plural, abbreviation, type, metricCoefficient " , " ORDER BY name " ) ;
2018-03-10 07:51:17 +00:00
vector < UnitOfMeasure > units ;
if ( ! t . isEmpty ( ) ) {
2018-03-30 10:29:10 +00:00
for ( TableRow row : t . rows ( ) ) {
UnitOfMeasure u ( row . at ( 0 ) , row . at ( 1 ) , row . at ( 2 ) , std : : stoi ( row . at ( 3 ) ) , std : : stod ( row . at ( 4 ) ) ) ;
2018-03-10 07:51:17 +00:00
units . push_back ( u ) ;
}
}
return units ;
}
2018-03-10 11:36:14 +00:00
vector < RecipeTag > RecipeDatabase : : retrieveTags ( int recipeId ) {
2018-03-30 10:29:10 +00:00
ResultTable t = this - > selectFrom ( " recipeTag " , " tagName " , " WHERE recipeId= " + std : : to_string ( recipeId ) + " ORDER BY tagName " ) ;
2018-03-10 11:36:14 +00:00
vector < RecipeTag > tags ;
if ( ! t . isEmpty ( ) ) {
2018-03-30 10:29:10 +00:00
for ( TableRow row : t . rows ( ) ) {
RecipeTag tag ( row . at ( 0 ) ) ;
2018-03-10 11:36:14 +00:00
tags . push_back ( tag ) ;
}
}
return tags ;
}
vector < RecipeTag > RecipeDatabase : : retrieveAllTags ( ) {
2018-03-30 12:33:48 +00:00
ResultTable t = this - > executeSQL ( " SELECT DISTINCT tagName FROM recipeTag ORDER BY tagName; " ) ;
2018-03-10 11:36:14 +00:00
vector < RecipeTag > tags ;
if ( ! t . isEmpty ( ) ) {
2018-03-30 10:29:10 +00:00
for ( TableRow row : t . rows ( ) ) {
RecipeTag tag ( row . at ( 0 ) ) ;
2018-03-10 11:36:14 +00:00
tags . push_back ( tag ) ;
}
}
return tags ;
}
2018-03-29 07:58:25 +00:00
bool RecipeDatabase : : deleteRecipe ( string name ) {
2018-03-29 14:09:58 +00:00
ResultTable t = this - > selectFrom ( " recipe " , " recipeId " , " WHERE name=' " + name + " ' " ) ;
2018-03-29 09:21:00 +00:00
if ( t . rowCount ( ) ! = 1 ) {
return false ;
}
2018-03-30 10:29:10 +00:00
string recipeId = t . at ( 0 , 0 ) ;
2018-03-29 09:21:00 +00:00
return this - > deleteRecipe ( std : : stoi ( recipeId ) ) ;
}
bool RecipeDatabase : : deleteRecipe ( int recipeId ) {
string idString = std : : to_string ( recipeId ) ;
if ( this - > selectFrom ( " recipe " , " recipeId " , " WHERE recipeId= " + idString ) . isEmpty ( ) ) {
2018-03-29 14:09:58 +00:00
printf ( " Cannot delete. No recipe with ID %d exists. \n " , recipeId ) ;
2018-03-29 09:21:00 +00:00
return false ;
}
this - > executeSQL ( " BEGIN; " ) ;
bool tagsDeleted = this - > deleteFrom ( " recipeTag " , " WHERE recipeId= " + idString ) ;
bool recipeIngredientDeleted = this - > deleteFrom ( " recipeIngredient " , " WHERE recipeId= " + idString ) ;
bool recipeDeleted = this - > deleteFrom ( " recipe " , " WHERE recipeId= " + idString ) ;
2018-03-29 15:17:07 +00:00
bool instructionDeleted = FileUtils : : deleteInstruction ( recipeId ) ;
bool imageDeleted = FileUtils : : deleteImage ( recipeId ) ;
2018-03-30 10:29:10 +00:00
Q_UNUSED ( instructionDeleted ) ;
Q_UNUSED ( imageDeleted ) ;
2018-03-29 09:21:00 +00:00
if ( tagsDeleted & & recipeIngredientDeleted & & recipeDeleted ) {
this - > executeSQL ( " COMMIT; " ) ;
return true ;
} else {
this - > executeSQL ( " ROLLBACK; " ) ;
return false ;
}
}
bool RecipeDatabase : : deleteIngredient ( string name ) {
2018-03-29 14:09:58 +00:00
ResultTable t = this - > executeSQL ( " SELECT recipeId "
" FROM recipeIngredient "
" INNER JOIN ingredient "
" ON recipeIngredient.ingredientId = ingredient.ingredientId "
" WHERE ingredient.name=' " + name + " '; " ) ;
2018-03-29 09:21:00 +00:00
if ( ! t . isEmpty ( ) ) {
//There is at least one recipe dependent on the ingredient.
return false ;
}
2018-03-29 14:09:58 +00:00
return this - > deleteFrom ( " ingredient " , " WHERE name=' " + name + " ' " ) ;
2018-03-29 09:21:00 +00:00
}
bool RecipeDatabase : : deleteUnitOfMeasure ( string name ) {
2018-03-29 14:09:58 +00:00
ResultTable t = this - > selectFrom ( " recipeIngredient " , " recipeId " , " WHERE unitName=' " + name + " ' " ) ;
2018-03-29 09:21:00 +00:00
if ( ! t . isEmpty ( ) ) {
return false ;
}
2018-03-29 14:09:58 +00:00
return this - > deleteFrom ( " unitOfMeasure " , " WHERE name=' " + name + " ' " ) ;
2018-03-29 09:21:00 +00:00
}
2018-03-29 07:58:25 +00:00
2018-03-29 09:21:00 +00:00
bool RecipeDatabase : : deleteTag ( RecipeTag tag ) {
2018-03-29 14:09:58 +00:00
return this - > deleteFrom ( " recipeTag " , " WHERE tagName=' " + tag . getValue ( ) + " ' " ) ;
2018-03-10 13:56:43 +00:00
}
2018-03-01 16:19:13 +00:00
void RecipeDatabase : : ensureTablesExist ( ) {
//Make sure that foreign keys are enabled.
this - > executeSQL ( " PRAGMA foreign_keys = ON; " ) ;
2018-03-03 09:18:38 +00:00
this - > executeSQL ( " BEGIN; " ) ;
2018-03-01 16:19:13 +00:00
//Ingredients table.
this - > executeSQL ( " CREATE TABLE IF NOT EXISTS ingredient( "
2018-03-02 08:32:40 +00:00
" ingredientId INTEGER PRIMARY KEY, "
2018-03-01 16:19:13 +00:00
" foodGroup varchar, "
2018-03-03 07:38:32 +00:00
" name varchar UNIQUE); " ) ;
2018-03-10 07:51:17 +00:00
//Unit of Measure table.
this - > executeSQL ( " CREATE TABLE IF NOT EXISTS unitOfMeasure( "
" name varchar UNIQUE PRIMARY KEY, "
" plural varchar, "
" abbreviation varchar, "
" type int, "
" metricCoefficient real); " ) ;
2018-03-02 10:30:16 +00:00
//Recipe table. Each recipe can have at most one instruction, and one image.
2018-03-01 16:19:13 +00:00
this - > executeSQL ( " CREATE TABLE IF NOT EXISTS recipe( "
2018-03-02 08:32:40 +00:00
" recipeId INTEGER PRIMARY KEY, "
2018-03-03 07:38:32 +00:00
" name varchar UNIQUE, "
2018-03-03 09:18:38 +00:00
" createdDate date, "
2018-03-01 16:19:13 +00:00
" prepTime time, "
2018-03-03 09:18:38 +00:00
" cookTime time, "
2018-03-02 10:30:16 +00:00
" servingCount real); " ) ;
2018-03-01 16:19:13 +00:00
//Recipe tags table.
this - > executeSQL ( " CREATE TABLE IF NOT EXISTS recipeTag( "
2018-03-03 09:18:38 +00:00
" recipeId int, "
2018-03-01 16:19:13 +00:00
" tagName varchar, "
" FOREIGN KEY (recipeId) REFERENCES recipe(recipeId)); " ) ;
//RecipeIngredient table.
this - > executeSQL ( " CREATE TABLE IF NOT EXISTS recipeIngredient( "
" ingredientId int, "
2018-03-02 13:14:56 +00:00
" recipeId int, "
2018-03-01 16:19:13 +00:00
" quantity real, "
" unitName varchar, "
" comment varchar, "
" FOREIGN KEY (ingredientId) REFERENCES ingredient(ingredientId), "
2018-03-10 07:51:17 +00:00
" FOREIGN KEY (recipeId) REFERENCES recipe(recipeId), "
" FOREIGN KEY (unitName) REFERENCES unitOfMeasure(name)); " ) ;
2018-03-03 09:18:38 +00:00
this - > executeSQL ( " COMMIT; " ) ;
2018-03-02 08:32:40 +00:00
}
2018-03-29 14:09:58 +00:00
2018-03-30 10:29:10 +00:00
Recipe RecipeDatabase : : readFromResultTable ( ResultTable t , int tRow ) {
2018-03-29 14:09:58 +00:00
Recipe r ;
2018-03-30 10:29:10 +00:00
TableRow row = t . rows ( ) . at ( tRow ) ;
int id = std : : stoi ( row . at ( 0 ) ) ;
r . setName ( row . at ( 1 ) ) ;
r . setCreatedDate ( QDate : : fromString ( QString : : fromStdString ( row . at ( 2 ) ) ) ) ;
r . setPrepTime ( QTime : : fromString ( QString : : fromStdString ( row . at ( 3 ) ) ) ) ;
r . setCookTime ( QTime : : fromString ( QString : : fromStdString ( row . at ( 4 ) ) ) ) ;
r . setServings ( std : : stof ( row . at ( 5 ) ) ) ;
2018-03-29 14:09:58 +00:00
r . setInstruction ( FileUtils : : loadInstruction ( id ) ) ;
r . setImage ( FileUtils : : loadImage ( id ) ) ;
r . setIngredients ( this - > retrieveRecipeIngredients ( id ) ) ;
r . setTags ( this - > retrieveTags ( id ) ) ;
return r ;
}
2018-03-30 18:57:14 +00:00
//Retrieves recipes from a table with the following format:
// id, name, createdDate, prepTime, cookTime, servings
vector < Recipe > RecipeDatabase : : readRecipesFromTable ( ResultTable t ) {
vector < Recipe > recipes ;
for ( unsigned int row = 0 ; row < t . rowCount ( ) ; row + + ) {
recipes . push_back ( readFromResultTable ( t , row ) ) ;
}
return recipes ;
}