package repository import ( "context" "git.sch9.ru/new_gate/ms-tester/internal/models" "github.com/jmoiron/sqlx" ) type ContestRepository struct { db *sqlx.DB } func NewContestRepository(db *sqlx.DB) *ContestRepository { return &ContestRepository{ db: db, } } const createContestQuery = "INSERT INTO contests (title) VALUES (?) RETURNING id" func (r *ContestRepository) CreateContest(ctx context.Context, title string) (int32, error) { const op = "ContestRepository.CreateContest" query := r.db.Rebind(createContestQuery) rows, err := r.db.QueryxContext(ctx, query, title) if err != nil { return 0, handlePgErr(err, op) } defer rows.Close() var id int32 rows.Next() err = rows.Scan(&id) if err != nil { return 0, handlePgErr(err, op) } return id, nil } const readContestByIdQuery = "SELECT * from contests WHERE id=? LIMIT 1" func (r *ContestRepository) ReadContestById(ctx context.Context, id int32) (*models.Contest, error) { const op = "ContestRepository.ReadContestById" var contest models.Contest query := r.db.Rebind(readContestByIdQuery) err := r.db.GetContext(ctx, &contest, query, id) if err != nil { return nil, handlePgErr(err, op) } return &contest, nil } const deleteContestQuery = "DELETE FROM contests WHERE id=?" func (r *ContestRepository) DeleteContest(ctx context.Context, id int32) error { const op = "ContestRepository.DeleteContest" query := r.db.Rebind(deleteContestQuery) _, err := r.db.ExecContext(ctx, query, id) if err != nil { return handlePgErr(err, op) } return nil } const addTaskQuery = "INSERT INTO tasks (problem_id, contest_id, position) VALUES (?, ?,COALESCE(SELECT MAX(position) FROM task WHERE contest_id = ? ,0) + 1) RETURNING id" func (r *ContestRepository) AddTask(ctx context.Context, contestId int32, problem_id int32) (int32, error) { const op = "ContestRepository.AddTask" query := r.db.Rebind(addTaskQuery) rows, err := r.db.QueryxContext(ctx, query, problem_id, contestId, contestId) if err != nil { return 0, handlePgErr(err, op) } defer rows.Close() var id int32 rows.Next() err = rows.Scan(&id) if err != nil { return 0, handlePgErr(err, op) } return id, nil } const deleteTaskQuery = "DELETE FROM tasks WHERE id=?" func (r *ContestRepository) DeleteTask(ctx context.Context, taskId int32) error { const op = "ContestRepository.DeleteTask" query := r.db.Rebind(deleteTaskQuery) _, err := r.db.ExecContext(ctx, query, taskId) if err != nil { return handlePgErr(err, op) } return nil } const addParticipantQuery = "INSERT INTO participants (user_id ,contest_id, name) VALUES (?, ?, ?) RETURNING id" func (r *ContestRepository) AddParticipant(ctx context.Context, contestId int32, userId int32) (int32, error) { const op = "ContestRepository.AddParticipant" query := r.db.Rebind(addParticipantQuery) name := "" rows, err := r.db.QueryxContext(ctx, query, contestId, userId, name) if err != nil { return 0, handlePgErr(err, op) } defer rows.Close() var id int32 rows.Next() err = rows.Scan(&id) if err != nil { return 0, err } return id, nil } const deleteParticipantQuery = "DELETE FROM participants WHERE id=?" func (r *ContestRepository) DeleteParticipant(ctx context.Context, participantId int32) error { const op = "ContestRepository.DeleteParticipant" query := r.db.Rebind(deleteParticipantQuery) _, err := r.db.ExecContext(ctx, query, participantId) if err != nil { return handlePgErr(err, op) } return nil } const readTasksQuery = `SELECT tasks.id, problem_id, contest_id, position, title, memory_limit, time_limit, tasks.created_at, tasks.updated_at FROM tasks INNER JOIN problems ON tasks.problem_id = problems.id WHERE contest_id = ? ORDER BY position` func (r *ContestRepository) ReadRichTasks(ctx context.Context, contestId int32) ([]*models.RichTask, error) { const op = "ContestRepository.ReadTasks" var tasks []*models.RichTask query := r.db.Rebind(readTasksQuery) err := r.db.SelectContext(ctx, &tasks, query, contestId) if err != nil { return nil, handlePgErr(err, op) } return tasks, nil } const ( readContestsListQuery = `SELECT id, title, created_at, updated_at FROM contests LIMIT ? OFFSET ?` countContestsQuery = "SELECT COUNT(*) FROM contests" ) func (r *ContestRepository) ListContests(ctx context.Context, page int32, pageSize int32) ([]*models.ContestsListItem, int32, error) { const op = "ContestRepository.ReadTasks" var tasks []*models.ContestsListItem query := r.db.Rebind(readContestsListQuery) err := r.db.SelectContext(ctx, &tasks, query, pageSize, (page-1)*pageSize) if err != nil { return nil, 0, handlePgErr(err, op) } query = r.db.Rebind(countContestsQuery) var count int32 err = r.db.GetContext(ctx, &count, query) if err != nil { return nil, 0, handlePgErr(err, op) } return tasks, count, nil } const ( readParticipantsListQuery = `SELECT id, user_id, name, created_at, updated_at FROM participants WHERE contest_id = ? LIMIT ? OFFSET ?` countParticipantsQuery = "SELECT COUNT(*) FROM participants WHERE contest_id = ?" ) func (r *ContestRepository) ListParticipants(ctx context.Context, contestId int32, page int32, pageSize int32) ([]*models.ParticipantsListItem, int32, error) { const op = "ContestRepository.ReadParticipants" if pageSize > 20 { pageSize = 1 } var participants []*models.ParticipantsListItem query := r.db.Rebind(readParticipantsListQuery) err := r.db.SelectContext(ctx, &participants, query, contestId, pageSize, (page-1)*pageSize) if err != nil { return nil, 0, handlePgErr(err, op) } query = r.db.Rebind(countParticipantsQuery) var count int32 err = r.db.GetContext(ctx, &count, query, contestId) if err != nil { return nil, 0, handlePgErr(err, op) } return participants, count, nil }