package db import ( "context" "time" "github.com/jackc/pgx/v5/pgtype" ) const createReview = `-- name: CreateReview :one INSERT INTO reviews ( submitted_by, comments, score, is_from_critic, is_hided, location_id, title ) VALUES ($1, $2, $3, $4, $5, $6, $7) RETURNING id, submitted_by, comments, score, is_from_critic, is_hided, location_id, title, created_at, updated_at ` type CreateReviewParams struct { SubmittedBy int32 `json:"submitted_by"` Comments string `json:"comments"` Score int16 `json:"score"` IsFromCritic bool `json:"is_from_critic"` IsHided bool `json:"is_hided"` LocationID int32 `json:"location_id"` Title pgtype.Text `json:"title"` } func (q *Queries) CreateReview(ctx context.Context, arg CreateReviewParams) (Review, error) { row := q.db.QueryRow(ctx, createReview, arg.SubmittedBy, arg.Comments, arg.Score, arg.IsFromCritic, arg.IsHided, arg.LocationID, arg.Title, ) var i Review err := row.Scan( &i.ID, &i.SubmittedBy, &i.Comments, &i.Score, &i.IsFromCritic, &i.IsHided, &i.LocationID, &i.Title, &i.CreatedAt, &i.UpdatedAt, ) return i, err } type GetListLocationReviewsParams struct { LocationID int32 `json:"location_id"` Limit int8 `json:"limit"` Offset int8 `json:"offset"` IsCritics bool `json:"is_critics"` } type GetListLocationReviewsRow struct { ID int32 `json:"id"` Title pgtype.Text `json:"title"` Score int8 `json:"score"` Comment string `json:"comments"` UserID int32 `json:"user_id"` Username string `json:"username"` UserAvatar pgtype.Text `json:"user_avatar"` CreatedAt time.Time `json:"created_at"` UpdatedAt time.Time `json:"updated_at"` } const getListLocationReviews = ` SELECT re.id as id, re.title as title, re.score as score, re.comments as comments, u.id as user_id, u.username as username, u.avatar_picture as user_avatar, re.created_at as created_at, re.updated_at as updated_at FROM REVIEWS re JOIN users u on re.submitted_by = u.id WHERE re.location_id = $1 AND re.is_from_critic = $2 LIMIT $3 OFFSET $4; ` type GetReviewByLocationAndIdParams struct { ID int32 `json:"id"` LocationID int32 `json:"location_id"` } type GetReviewByLocationAndId struct { ID int32 `json:"id"` Title pgtype.Text `json:"title"` SubmittedBy int32 `json:"submitted_by"` LocationID int32 `json:"location_id"` Score int16 `json:"score"` Comments string `json:"comments"` CreatedAt pgtype.Timestamp `json:"created_at"` UpdatedAt pgtype.Timestamp `json:"updated_at"` Username string `json:"username"` UserAvatar pgtype.Text `json:"user_avatar"` } const getReviewByLocationAndId = ` SELECT re.id, re.title, re.submitted_by, re.location_id, re.score, re.comments, re.created_at, re.updated_at, u.username, u.avatar_picture FROM reviews re JOIN users u on re.submitted_by = u.id WHERE re.id = $1 AND re.location_id = $2 AND re.is_hided = false; ` func (q *Queries) GetReviewByLocationAndId(ctx context.Context, arg GetReviewByLocationAndIdParams) (GetReviewByLocationAndId, error) { row := q.db.QueryRow(ctx, getReviewByLocationAndId, arg.ID, arg.LocationID) var i GetReviewByLocationAndId err := row.Scan( &i.ID, &i.Title, &i.SubmittedBy, &i.LocationID, &i.Score, &i.Comments, &i.CreatedAt, &i.UpdatedAt, &i.Username, &i.UserAvatar, ) return i, err } type GetLocationReviewGradesRow struct { CriticAvgTasteGrade pgtype.Float8 `json:"critic_avg_taste_grade"` CriticTasteGradeCount int64 `json:"critic_taste_grade_count"` CriticAvgComfortGrade pgtype.Float8 `json:"critic_avg_comfort_grade"` CriticComfortGradeCount int64 `json:"critic_comfort_grade_count"` CriticAvgCleanlinessGrade pgtype.Float8 `json:"critic_avg_cleanliness_grade"` CriticCleanlinessGradeCount int64 `json:"critic_cleanliness_grade_count"` CriticAvgServiceGrade pgtype.Float8 `json:"critic_avg_service_grade"` CriticServiceGradeCount int64 `json:"critic_service_grade_count"` CriticAvgFacilitiesGrade pgtype.Float8 `json:"critic_avg_facilities_grade"` CriticFacilitiesGradeCount int64 `json:"critic_facilities_grade_count"` UserAvgTasteGrade pgtype.Float8 `json:"user_avg_taste_grade"` UserTasteGradeCount int64 `json:"user_taste_grade_count"` UserAvgComfortGrade pgtype.Float8 `json:"user_avg_comfort_grade"` UserComfortGradeCount int64 `json:"user_comfort_grade_count"` UserAvgCleanlinessGrade pgtype.Float8 `json:"user_avg_cleanliness_grade"` UserCleanlinessGradeCount int64 `json:"user_cleanliness_grade_count"` UserAvgServiceGrade pgtype.Float8 `json:"user_avg_service_grade"` UserServiceGradeCount int64 `json:"user_service_grade_count"` UserAvgFacilitiesGrade pgtype.Float8 `json:"user_avg_facilities_grade"` UserFacilitiesGradeCount int64 `json:"user_facilities_grade_count"` } const getLocationReviewGrades = ` SELECT AVG(re.taste_grade) FILTER (WHERE re.is_from_critic = true)::float8 AS critic_avg_taste_grade, COUNT(re.taste_grade) FILTER (WHERE re.is_from_critic = true) AS critic_taste_grade_count, AVG(re.comfort_grade) FILTER (WHERE re.is_from_critic = true)::float8 AS critic_avg_comfort_grade, COUNT(re.comfort_grade) FILTER (WHERE re.is_from_critic = true) AS critic_comfort_grade_count, AVG(re.cleanliness_grade) FILTER (WHERE re.is_from_critic = true)::float8 AS critic_avg_cleanliness_grade, COUNT(re.cleanliness_grade) FILTER (WHERE re.is_from_critic = true) AS critic_cleanliness_grade_count, AVG(re.service_grade) FILTER (WHERE re.is_from_critic = true)::float8 AS critic_avg_service_grade, COUNT(re.service_grade) FILTER (WHERE re.is_from_critic = true) AS critic_service_grade_count, AVG(re.facilities_grade) FILTER (WHERE re.is_from_critic = true)::float8 AS critic_avg_facilities_grade, COUNT(re.facilities_grade) FILTER (WHERE re.is_from_critic = true) AS critic_facilities_grade_count, AVG(re.taste_grade) FILTER (WHERE re.is_from_critic = false)::float8 AS user_avg_taste_grade, COUNT(re.taste_grade) FILTER (WHERE re.is_from_critic = false) AS user_taste_grade_count, AVG(re.comfort_grade) FILTER (WHERE re.is_from_critic = false)::float8 AS user_avg_comfort_grade, COUNT(re.comfort_grade) FILTER (WHERE re.is_from_critic = false) AS user_comfort_grade_count, AVG(re.cleanliness_grade) FILTER (WHERE re.is_from_critic = false)::float8 AS user_avg_cleanliness_grade, COUNT(re.cleanliness_grade) FILTER (WHERE re.is_from_critic = false) AS user_cleanliness_grade_count, AVG(re.service_grade) FILTER (WHERE re.is_from_critic = false)::float8 AS user_avg_service_grade, COUNT(re.service_grade) FILTER (WHERE re.is_from_critic = false) AS user_service_grade_count, AVG(re.facilities_grade) FILTER (WHERE re.is_from_critic = false)::float8 AS user_avg_facilities_grade, COUNT(re.facilities_grade) FILTER (WHERE re.is_from_critic = false) AS user_facilities_grade_count FROM reviews re WHERE re.location_id = $1 AND re.is_hided = false; ` func (q *Queries) GetLocationReviewGrades(ctx context.Context, locationID int32) (GetLocationReviewGradesRow, error) { row := q.db.QueryRow(ctx, getLocationReviewGrades, locationID) var i GetLocationReviewGradesRow err := row.Scan( &i.CriticAvgTasteGrade, &i.CriticTasteGradeCount, &i.CriticAvgComfortGrade, &i.CriticComfortGradeCount, &i.CriticAvgCleanlinessGrade, &i.CriticCleanlinessGradeCount, &i.CriticAvgServiceGrade, &i.CriticServiceGradeCount, &i.CriticAvgFacilitiesGrade, &i.CriticFacilitiesGradeCount, &i.UserAvgTasteGrade, &i.UserTasteGradeCount, &i.UserAvgComfortGrade, &i.UserComfortGradeCount, &i.UserAvgCleanlinessGrade, &i.UserCleanlinessGradeCount, &i.UserAvgServiceGrade, &i.UserServiceGradeCount, &i.UserAvgFacilitiesGrade, &i.UserFacilitiesGradeCount, ) return i, err } func (q *Queries) GetListLocationReviews(ctx context.Context, arg GetListLocationReviewsParams) ([]GetListLocationReviewsRow, error) { rows, err := q.db.Query(ctx, getListLocationReviews, arg.LocationID, arg.IsCritics, arg.Limit, arg.Offset) if err != nil { return nil, err } defer rows.Close() items := []GetListLocationReviewsRow{} for rows.Next() { var i GetListLocationReviewsRow if err := rows.Scan( &i.ID, &i.Title, &i.Score, &i.Comment, &i.UserID, &i.Username, &i.UserAvatar, &i.CreatedAt, &i.UpdatedAt, ); err != nil { return nil, err } items = append(items, i) } rows.Close() if err := rows.Err(); err != nil { return nil, err } return items, nil }