package adapter import ( "context" "database/sql" "errors" "fmt" "gitea.dwysokinski.me/twhelp/corev3/internal/bun/bunmodel" "gitea.dwysokinski.me/twhelp/corev3/internal/domain" "github.com/uptrace/bun" ) type VersionBunRepository struct { db bun.IDB } func NewVersionBunRepository(db bun.IDB) *VersionBunRepository { return &VersionBunRepository{db: db} } func (repo *VersionBunRepository) List( ctx context.Context, params domain.ListVersionsParams, ) (domain.ListVersionsResult, error) { var versions bunmodel.Versions if err := repo.db.NewSelect(). Model(&versions). Apply(listVersionsParamsApplier{params: params}.apply). Scan(ctx); err != nil && !errors.Is(err, sql.ErrNoRows) { return domain.ListVersionsResult{}, fmt.Errorf("couldn't select versions from the database: %w", err) } converted, err := versions.ToDomain() if err != nil { return domain.ListVersionsResult{}, err } return domain.NewListVersionsResult(separateListResultAndNext(converted, params.Limit())) } type listVersionsParamsApplier struct { params domain.ListVersionsParams } func (a listVersionsParamsApplier) apply(q *bun.SelectQuery) *bun.SelectQuery { if codes := a.params.Codes(); len(codes) > 0 { q = q.Where("version.code IN (?)", bun.In(codes)) } for _, s := range a.params.Sort() { cursorZero := a.params.Cursor().IsZero() cursorCode := a.params.Cursor().Code() switch s { case domain.VersionSortCodeASC: if !cursorZero { q = q.Where("version.code >= ?", cursorCode) } q = q.Order("version.code ASC") case domain.VersionSortCodeDESC: if !cursorZero { q = q.Where("version.code <= ?", cursorCode) } q = q.Order("version.code DESC") default: return q.Err(errUnsupportedSortValue) } } return q.Limit(a.params.Limit() + 1) }