Skip to content

Commit

Permalink
Unique dish.{name, cafeteriaID} (#325)
Browse files Browse the repository at this point in the history
* introduced an index and made sure that the dishes are unique
* added the correct migration for `dish_ratings` FK-binding
* modified the models.DishRating struct as well with the appropriate change
  • Loading branch information
CommanderStorm authored Mar 13, 2024
1 parent 9f7a0b5 commit 8b7f232
Show file tree
Hide file tree
Showing 7 changed files with 79 additions and 32 deletions.
11 changes: 5 additions & 6 deletions server/backend/cafeteria.go
Original file line number Diff line number Diff line change
Expand Up @@ -409,12 +409,11 @@ func (s *CampusServer) CreateDishRating(ctx context.Context, input *pb.CreateDis
resPath := imageWrapper(input.Image, "dishes", dishInMensa.Dish)

rating := model.DishRating{
Comment: input.Comment,
CafeteriaID: cafeteriaID,
DishID: dishInMensa.Dish,
Points: input.Points,
Timestamp: time.Now(),
Image: resPath,
Comment: input.Comment,
DishID: dishInMensa.Dish,
Points: input.Points,
Timestamp: time.Now(),
Image: resPath,
}
if err := tx.Create(&rating).Error; err != nil {
log.WithError(err).Error("while creating a new dishInMensa rating.")
Expand Down
28 changes: 15 additions & 13 deletions server/backend/cron/dish_name_download.go
Original file line number Diff line number Diff line change
Expand Up @@ -2,6 +2,7 @@ package cron

import (
"encoding/json"
"errors"
"fmt"
"net/http"
"strings"
Expand Down Expand Up @@ -95,25 +96,26 @@ func downloadDailyDishes(c *CronService) {
CafeteriaID: v.Cafeteria,
}

var count int64
var dishId int64
if err := c.db.Model(&model.Dish{}).
Where("name = ? AND cafeteriaID = ?", dish.Name, dish.CafeteriaID).
Select("dish").
First(&dishId).
Count(&count).Error; err != nil {
log.WithError(err).Error("Error while checking whether this is already in database")
}
if count == 0 {
var dbDish model.Dish
if err := c.db.First(&dbDish, "name = ? AND cafeteriaID = ?", dish.Name, dish.CafeteriaID).Error; err != nil && errors.Is(err, gorm.ErrRecordNotFound) {
if err := c.db.Create(&dish).Error; err != nil {
log.WithError(err).Error("Error while creating new CanteenDish entry with name {}. CanteenDish won't be saved", dish.Name)
log.WithError(err).WithField("name", dish.Name).Error("Error while creating new CanteenDish entry. CanteenDish won't be saved")
}
addDishTagsToMapping(dish.Dish, dish.Name, c.db)
dishId = dish.Dish
dbDish = dish
} else if err != nil {
log.WithError(err).Error("Error while checking whether the dish is already in database")
}

if dbDish.Type != dish.Type {
if err := c.db.Where("dish = ?", dbDish.Dish).Updates(&dish).Error; err != nil {
log.WithError(err).WithField("from", dish.Type).WithField("to", dish.Type).Error("Error while updating dish to new type")
}
}

if weekliesWereAdded == 0 {
errCreate := c.db.Create(&model.DishesOfTheWeek{
DishID: dishId,
DishID: dbDish.Dish,
Year: int32(year),
Week: int32(week),
Day: int32(weekDayIndex),
Expand Down
45 changes: 45 additions & 0 deletions server/backend/migration/20240311000000.go
Original file line number Diff line number Diff line change
@@ -0,0 +1,45 @@
package migration

import (
"github.com/go-gormigrate/gormigrate/v2"
"gorm.io/gorm"
)

// migrate20240311000000
// made sure that dishes have the correct indexes
// changed how `dish_rating` is bound to `dish`
func migrate20240311000000() *gormigrate.Migration {
return &gormigrate.Migration{
ID: "20240311000000",
Migrate: func(tx *gorm.DB) error {
// make sure that dish_rating is FK-bound to dish
if err := tx.Exec("alter table dish_rating modify dishID int").Error; err != nil {
return err
}
if err := tx.Exec("alter table dish_rating add constraint dish_rating_dish_dish_fk foreign key (dishID) references dish (dish) on update cascade on delete cascade").Error; err != nil {
return err
}
// because dishes already have a cafeteria, storing this again is not necessary
if err := tx.Exec("alter table dish_rating drop column cafeteriaID").Error; err != nil {
return err
}
// uniqueness
return tx.Exec("create unique index dish_name_cafeteriaID_uindex on dish (name, cafeteriaID)").Error
},
Rollback: func(tx *gorm.DB) error {
// make sure that dish_rating is FK-bound to dishes
if err := tx.Exec("alter table dish_rating drop constraint dish_rating_dish_dish_fk").Error; err != nil {
return err
}
if err := tx.Exec("alter table dish_rating modify dishID int not null").Error; err != nil {
return err
}
// because dishes already have a cafeteria, storing this agiain is not nessesary
if err := tx.Exec("alter table dish_rating add column cafeteriaID int not null").Error; err != nil {
return err
}
// uniqueness
return tx.Exec("drop index dish_name_cafeteriaID_uindex on dish").Error
},
}
}
6 changes: 3 additions & 3 deletions server/backend/migration/20240312000000.go
Original file line number Diff line number Diff line change
Expand Up @@ -5,11 +5,11 @@ import (
"gorm.io/gorm"
)

// migrate20240212000000
// migrate20240312000000
// implemented a basic variant of spam protection
func migrate20240212000000() *gormigrate.Migration {
func migrate20240312000000() *gormigrate.Migration {
return &gormigrate.Migration{
ID: "20240212000000",
ID: "20240312000000",
Migrate: func(tx *gorm.DB) error {
if err := tx.Exec("alter table feedback modify email_id text charset utf8mb3 not null").Error; err != nil {
return err
Expand Down
3 changes: 2 additions & 1 deletion server/backend/migration/migration.go
Original file line number Diff line number Diff line change
Expand Up @@ -71,7 +71,8 @@ func manualMigrate(db *gorm.DB) error {
migrate20240102000000(),
migrate20240103000000(),
migrate20240207000000(),
migrate20240212000000(),
migrate20240311000000(),
migrate20240312000000(),
}
return gormigrate.New(db, gormigrateOptions, migrations).Migrate()
}
Expand Down
4 changes: 2 additions & 2 deletions server/model/dish.go
Original file line number Diff line number Diff line change
Expand Up @@ -14,9 +14,9 @@ var (
// Dish represents one dish fin a specific cafeteria
type Dish struct {
Dish int64 `gorm:"primary_key;AUTO_INCREMENT;column:dish;type:int;not null;" json:"dish"`
Name string `gorm:"column:name;type:text;not null;" json:"name" `
Name string `gorm:"column:name;type:text;not null;uniqueIndex:dish_name_cafeteriaID_uindex" json:"name" `
Type string `gorm:"column:type;type:text;not null;" json:"type" `
CafeteriaID int64 `gorm:"column:cafeteriaID;foreignKey:cafeteria;type:int;not null;" json:"cafeteriaID"`
CafeteriaID int64 `gorm:"column:cafeteriaID;foreignKey:cafeteria;type:int;not null;uniqueIndex:dish_name_cafeteriaID_uindex" json:"cafeteriaID"`
}

// TableName sets the insert table name for this struct type
Expand Down
14 changes: 7 additions & 7 deletions server/model/dish_rating.go
Original file line number Diff line number Diff line change
Expand Up @@ -5,13 +5,13 @@ import (
)

type DishRating struct {
DishRating int64 `gorm:"primary_key;AUTO_INCREMENT;column:dishRating;type:int;not null;" json:"dishRating"`
Points int32 `gorm:"column:points;type:int;not null;" json:"points"`
CafeteriaID int64 `gorm:"column:cafeteriaID;foreignKey:cafeteria;type:int;not null;" json:"cafeteriaID"`
DishID int64 `gorm:"column:dishID;foreignKey:dish;type:int;not null;" json:"dishID"`
Comment string `gorm:"column:comment;type:text;" json:"comment"`
Timestamp time.Time `gorm:"column:timestamp;type:timestamp;not null;" json:"timestamp"`
Image string `gorm:"column:image;type:text;" json:"image"`
DishRating int64 `gorm:"primary_key;AUTO_INCREMENT;column:dishRating;type:int;not null;" json:"dishRating"`
Points int32 `gorm:"column:points;type:int;not null;" json:"points"`
DishID int64 `gorm:"column:dishID;type:int;not null;" json:"dishID"`
Dish Dish `gorm:"foreignKey:dishID;references:dish;constraint:OnUpdate:CASCADE,OnDelete:CASCADE;"`
Comment string `gorm:"column:comment;type:text;" json:"comment"`
Timestamp time.Time `gorm:"column:timestamp;type:timestamp;not null;" json:"timestamp"`
Image string `gorm:"column:image;type:text;" json:"image"`
}

// TableName sets the insert table name for this struct type
Expand Down

0 comments on commit 8b7f232

Please sign in to comment.