package mysqldriver import ( "context" "database/sql" "errors" "fmt" "git.aiterp.net/stufflog/server/internal/slerrors" "git.aiterp.net/stufflog/server/models" sq "github.com/Masterminds/squirrel" "github.com/jmoiron/sqlx" "time" ) type issueTaskRepository struct { db *sqlx.DB } func (r *issueTaskRepository) Find(ctx context.Context, id string) (*models.IssueTask, error) { issueTask := models.IssueTask{} err := r.db.GetContext(ctx, &issueTask, "SELECT * FROM issue_task WHERE issue_task_id=?", id) if err != nil { if err == sql.ErrNoRows { return nil, slerrors.NotFound("Issue task") } return nil, err } return &issueTask, nil } func (r *issueTaskRepository) List(ctx context.Context, filter models.IssueTaskFilter) ([]*models.IssueTask, error) { q := sq.Select("*").From("issue_task").OrderBy("created_time") if filter.ActivityIDs != nil { q = q.Where(sq.Eq{"activity_id": filter.ActivityIDs}) } if filter.IssueTaskIDs != nil { q = q.Where(sq.Eq{"issue_id": filter.IssueTaskIDs}) } if filter.IssueIDs != nil { q = q.Where(sq.Eq{"issue_id": filter.IssueIDs}) } if filter.MinStage != nil { q = q.Where(sq.GtOrEq{"status_stage": *filter.MinStage}) } if filter.MaxStage != nil { q = q.Where(sq.LtOrEq{"status_stage": *filter.MaxStage}) } query, args, err := q.ToSql() if err != nil { return nil, err } results := make([]*models.IssueTask, 0, 16) err = r.db.SelectContext(ctx, &results, query, args...) if err != nil { if err == sql.ErrNoRows { return []*models.IssueTask{}, nil } return nil, err } return results, nil } func (r *issueTaskRepository) Insert(ctx context.Context, task models.IssueTask) (*models.IssueTask, error) { if task.IssueID == "" { return nil, errors.New("missing issue id") } if task.CreatedTime.IsZero() { task.CreatedTime = time.Now().Truncate(time.Second) task.UpdatedTime = task.CreatedTime } tx, err := r.db.BeginTxx(ctx, nil) if err != nil { return nil, err } nextID, err := incCounter(ctx, tx, counterKindIssueSubID, task.IssueID) if err != nil { _ = tx.Rollback() return nil, err } task.ID = fmt.Sprintf("%s-%d", task.IssueID, nextID) _, err = tx.NamedExecContext(ctx, ` INSERT INTO issue_task ( issue_task_id, issue_id, activity_id, created_time, updated_time, due_time, status_stage, status_name, name, description, estimated_time, estimated_units, points_multiplier ) VALUES ( :issue_task_id, :issue_id, :activity_id, :created_time, :updated_time, :due_time, :status_stage, :status_name, :name, :description, :estimated_time, :estimated_units, :points_multiplier ) `, task) if err != nil { _ = tx.Rollback() return nil, err } err = tx.Commit() if err != nil { _ = tx.Rollback() return nil, err } return &task, nil } func (r *issueTaskRepository) Save(ctx context.Context, task models.IssueTask) error { _, err := r.db.NamedExecContext(ctx, ` UPDATE issue_task SET due_time=:due_time, status_stage=:status_stage, status_name=:status_name, name=:name, description=:description, estimated_time=:estimated_time, estimated_units=:estimated_units, points_multiplier=:points_multiplier WHERE issue_task_id=:issue_task_id `, task) return err } func (r *issueTaskRepository) Delete(ctx context.Context, task models.IssueTask) error { _, err := r.db.ExecContext(ctx, "DELETE FROM issue_task WHERE issue_task_id=? LIMIT 1;", task.ID) return err }