db funcs
This commit is contained in:
parent
f4bf66ea1b
commit
632d69ccda
|
@ -0,0 +1,21 @@
|
|||
package models
|
||||
|
||||
type Recipe struct {
|
||||
ID uint `json:"id,omitempty"` // id
|
||||
Title string `json:"title,omitempty"` // Заголовок
|
||||
Description string `json:"desc,omitempty"` // Описание
|
||||
Image string `json:"img,omitempty"` // Картинка
|
||||
CookingTime string `json:"ctime,omitempty"` // Время приготовления
|
||||
Link string `json:"link,omitempty"` // Ссылка
|
||||
ServingsNum uint `json:"snum,omitempty"` // Кол-во порций
|
||||
Calories string `json:"cal,omitempty"` // Колории
|
||||
Ingredients []RecipeIngredients `json:"ingredients,omitempty"` // Ингридиенты и посуда (списки)
|
||||
Recipe_steps []string `json:"recipe_steps,omitempty"` // Шаги рецепта
|
||||
Advices []string `json:"advices,omitempty"` // Рекомендации
|
||||
Categories []string `json:"categories,omitempty"` // Категории
|
||||
}
|
||||
|
||||
type RecipeIngredients struct {
|
||||
Title string `json:"title,omitempty"`
|
||||
Ingredients []string `json:"ingredients,omitempty"`
|
||||
}
|
|
@ -3,15 +3,16 @@ package postgresql
|
|||
import (
|
||||
"context"
|
||||
"fmt"
|
||||
"recipes/internal/domain/models"
|
||||
|
||||
"github.com/jackc/pgx/v5/pgxpool"
|
||||
)
|
||||
|
||||
type Database struct {
|
||||
type Storage struct {
|
||||
db *pgxpool.Pool
|
||||
}
|
||||
|
||||
func New(user, password, addr, dbname string) (*Database, error) {
|
||||
func New(user, password, addr, dbname string) (*Storage, error) {
|
||||
const op = "storage.postgresql.New"
|
||||
|
||||
pool, err := pgxpool.New(context.Background(), fmt.Sprintf("postgres://%s:%s@%s/%s?sslmode=disable", user, password, addr, dbname))
|
||||
|
@ -19,5 +20,149 @@ func New(user, password, addr, dbname string) (*Database, error) {
|
|||
return nil, fmt.Errorf("%s: %w", op, err)
|
||||
}
|
||||
|
||||
return &Database{db: pool}, nil
|
||||
return &Storage{db: pool}, nil
|
||||
}
|
||||
|
||||
// AddRecipe adds recipe to db.
|
||||
func (s *Storage) AddRecipe(ctx context.Context, recipe models.Recipe) error {
|
||||
const op = "storage.postgresql.AddRecipe"
|
||||
|
||||
// open transaction
|
||||
tx, err := s.db.Begin(ctx)
|
||||
if err != nil {
|
||||
return fmt.Errorf("%s: %w", op, err)
|
||||
}
|
||||
|
||||
// refactor error handling
|
||||
// rollback transaction on return
|
||||
defer tx.Rollback(ctx)
|
||||
|
||||
var id uint
|
||||
// insert recipe
|
||||
err = s.db.QueryRow(
|
||||
ctx,
|
||||
"insert into recipe (title, description, image, cooking_time, servings, cal) values ($1, $2, $3, $4, $5, $6) returning id",
|
||||
recipe.Title, recipe.Description, recipe.Image, recipe.CookingTime, recipe.ServingsNum, recipe.Calories,
|
||||
).Scan(&id)
|
||||
|
||||
// insert ingredients
|
||||
for _, r := range recipe.Ingredients {
|
||||
var ing_id uint
|
||||
err = s.db.QueryRow(
|
||||
ctx,
|
||||
"insert into recipe_ingredients_group (recipe_id, title) values ($1, $2) returning id",
|
||||
id, r.Title,
|
||||
).Scan(&ing_id)
|
||||
if err != nil {
|
||||
return fmt.Errorf("%s: %w", op, err)
|
||||
}
|
||||
|
||||
for _, i := range r.Ingredients {
|
||||
_, err = s.db.Exec(
|
||||
ctx,
|
||||
"insert into recipe_ingredients (recipe_ingredients_group_id, ingredient) values ($1, $2)",
|
||||
ing_id, i,
|
||||
)
|
||||
if err != nil {
|
||||
return fmt.Errorf("%s: %w", op, err)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// insert steps
|
||||
for i, step := range recipe.Recipe_steps {
|
||||
s.db.Exec(
|
||||
ctx,
|
||||
"insert into recipe_steps (recipe_id, step_num, step_text) values ($1, $2, $3)",
|
||||
id, i, step,
|
||||
)
|
||||
}
|
||||
|
||||
// insert advices
|
||||
for _, a := range recipe.Advices {
|
||||
s.db.Exec(
|
||||
ctx,
|
||||
"insert into recipe_advices (recipe_id, advice) values ($1, $2)",
|
||||
id, a,
|
||||
)
|
||||
}
|
||||
|
||||
// insert categories
|
||||
for _, c := range recipe.Categories {
|
||||
s.db.Exec(
|
||||
ctx,
|
||||
"insert into recipe_categories (recipe_id, category) values ($1, $2)",
|
||||
id, c,
|
||||
)
|
||||
}
|
||||
|
||||
// commit transaction
|
||||
if err := tx.Commit(ctx); err != nil {
|
||||
return fmt.Errorf("%s: %w", op, err)
|
||||
}
|
||||
|
||||
return nil
|
||||
}
|
||||
|
||||
// RecipeExists returns true if recipe is exists.
|
||||
func (s *Storage) RecipeExists(ctx context.Context, title string) (bool, error) {
|
||||
const op = "storage.postgresql.RecipeExists"
|
||||
|
||||
var exists bool
|
||||
|
||||
err := s.db.QueryRow(
|
||||
ctx,
|
||||
"select exists(select id from recipe where title = $1)",
|
||||
title,
|
||||
).Scan(&exists)
|
||||
if err != nil {
|
||||
return false, fmt.Errorf("%s: %w", op, err)
|
||||
}
|
||||
|
||||
return exists, nil
|
||||
}
|
||||
|
||||
// func (db *PostgresqlDatabase) GetRecipes(offset, limit int) ([]structs.Recipe, error)
|
||||
func (s *Storage) GetRecipes(ctx context.Context, offset, limit int) ([]models.Recipe, error) {
|
||||
const op = "storage.postgresql.GetRecipes"
|
||||
|
||||
rows, err := s.db.Query(
|
||||
ctx,
|
||||
"select id, title, image, cooking_time, cal from recipe order by id desc offset $1 limit $2",
|
||||
offset, limit,
|
||||
)
|
||||
if err != nil {
|
||||
return nil, fmt.Errorf("%s: %w", op, err)
|
||||
}
|
||||
|
||||
defer rows.Close()
|
||||
|
||||
var recipes []models.Recipe = make([]models.Recipe, 0, limit)
|
||||
|
||||
for rows.Next() {
|
||||
var r models.Recipe
|
||||
|
||||
err = rows.Scan(
|
||||
&r.ID,
|
||||
&r.Title,
|
||||
&r.Image,
|
||||
&r.CookingTime,
|
||||
&r.Calories,
|
||||
)
|
||||
if err != nil {
|
||||
return nil, fmt.Errorf("%s: %w", op, err)
|
||||
}
|
||||
|
||||
recipes = append(recipes, r)
|
||||
}
|
||||
|
||||
return recipes, nil
|
||||
}
|
||||
|
||||
// func (db *PostgresqlDatabase) GetRecipe(r_id uint) (structs.Recipe, error)
|
||||
|
||||
// add to recipe info about ingredients, steps, advices, categories
|
||||
// func (db *PostgresqlDatabase) AddRecipeInformation(r *structs.Recipe)
|
||||
|
||||
// get recipes by category
|
||||
// func (db *PostgresqlDatabase) GetRecipesByCategory(offset, limit int, category string) ([]structs.Recipe, error)
|
||||
|
|
|
@ -1,6 +1,6 @@
|
|||
drop table if exists recipe;
|
||||
drop table if exists recipe_ingredients_group;
|
||||
drop table if exists recipe_ingredients;
|
||||
drop table if exists recipe_steps;
|
||||
drop table if exists recipe_advices;
|
||||
drop table if exists recipe_categories;
|
||||
drop table if exists recipe_ingredients_group cascade;
|
||||
drop table if exists recipe_ingredients cascade;
|
||||
drop table if exists recipe_steps cascade;
|
||||
drop table if exists recipe_advices cascade;
|
||||
drop table if exists recipe_categories cascade;
|
||||
drop table if exists recipe cascade;
|
|
@ -1,7 +1,7 @@
|
|||
-- recipe
|
||||
create table if not exists recipe (
|
||||
id serial primary key,
|
||||
title varchar(60) not null UNIQUE,
|
||||
title text not null UNIQUE,
|
||||
description text not null default '',
|
||||
image varchar(42) not null,
|
||||
cooking_time varchar(16) not null,
|
||||
|
@ -12,7 +12,7 @@ create table if not exists recipe (
|
|||
create table if not exists recipe_ingredients_group (
|
||||
id serial primary key,
|
||||
recipe_id integer references recipe(id) on delete cascade,
|
||||
title varchar(26) default ''
|
||||
title text default ''
|
||||
);
|
||||
-- recipe ingredients
|
||||
create table if not exists recipe_ingredients (
|
||||
|
|
Loading…
Reference in New Issue