package storage import ( "context" "errors" "git.sch9.ru/new_gate/ms-auth/internal/lib" "git.sch9.ru/new_gate/ms-auth/internal/models" "github.com/jackc/pgerrcode" "github.com/jackc/pgx/v5/pgconn" "github.com/jmoiron/sqlx" "go.uber.org/zap" "time" ) type SolutionStorage struct { db *sqlx.DB logger *zap.Logger } func NewSolutionStorage(db *sqlx.DB, logger *zap.Logger) *SolutionStorage { return &SolutionStorage{ db: db, logger: logger, } } // TODO: testing graph func updateResult(ctx context.Context, participantId int32, taskId int32) error { tx,err := storage.db.Begin() if err != nil { return storage.HandlePgErr(err) } query:=tx.Rebind("UPDATE participant_subtask AS ps SET best_score = (SELECT COALESCE(max(score),0) FROM subtaskruns WHERE subtask_id = ps.subtask_id AND solution_id IN (SELECT id FROM solutions WHERE participant_id=ps.participant_id)) WHERE participant_id = 2 AND subtask_id IN (SELECT id FROM subtasks WHERE task_id = 2)") tx.QueryxContext(ctx,query,participantId,taskId) query=tx.Rebind("UPDATE participant_task SET best_score = (select max(best_score) from participant_subtask WHERE participant_id = ? AND subtask_id IN (SELECT id FROM subtask WHERE task_id = ?)) WHERE participant_id = ? AND task_id = ?") tx.QueryxContext(ctx,query,participantId,taskId,participantId,taskId) err = tx.Commit() if err != nil { return storage.HandlePgErr(err) } } func (storage *SolutionStorage) CreateSolution(ctx context.Context, solution *models.Solution) (int32, error) { query := storage.db.Rebind(` INSERT INTO solutions (participant_id,task_id,language_id,solution_hash,result) VALUES (?, ?, ?, ?, ?) RETURNING id `) rows, err := storage.db.QueryxContext( ctx, query, solution.ParticipantId, solution.TaskId, solution.LanguageId, "",//FIXME models.NotTested, ) if err != nil { return 0, storage.HandlePgErr(err) } defer rows.Close() var id int32 err = rows.StructScan(&id) if err != nil { return 0, storage.HandlePgErr(err) } return id, nil } func (storage *SolutionStorage) ReadSolutionById(ctx context.Context, id int32) (*models.Solution, error) { var solution models.Solution query := storage.db.Rebind("SELECT * from solutions WHERE id=? LIMIT 1") err := storage.db.GetContext(ctx, &solution, query, id) if err != nil { return nil, storage.HandlePgErr(err) } return &solution, nil } func (storage *SolutionStorage) RejudgeSolution(ctx context.Context, id int32) error { tx,err := storage.db.Begin() if err != nil { return storage.HandlePgErr(err) } query:=tx.Rebind("UPDATE solutions SET result = ? WHERE id = ?") tx.QueryxContext(ctx,query,models.NotTested, id) query=tx.Rebind("UPDATE subtaskruns SET result = ?,score = 0 WHERE solution_id = ?") tx.QueryxContext(ctx,query,models.NotTested, id) query=tx.Rebind("UPDATE testruns SET result = ?, score = 0 WHERE testgrouprun_id IN (SELECT id FROM tesgrouprun WHERE solution_id = ?)") tx.QueryxContext(ctx,query,models.NotTested, id) err = tx.Commit() var solution models.Solution query := storage.db.Rebind("SELECT * from solutions WHERE id=? LIMIT 1") err := storage.db.GetContext(ctx, &solution, query, id) if err != nil { return storage.HandlePgErr(err) } updateResult(ctx,solution.ParticipantId,TaskId); return nil } func (storage *SolutionStorage) DeleteSolution(ctx context.Context, id int32) error { query := storage.db.Rebind("DELETE FROM solutions WHERE id=?") _, err := storage.db.ExecContext(ctx, query, id) if err != nil { return storage.HandlePgErr(err) } return nil }