Skip to content

Commit 87505a9

Browse files
authored
Add AbsoluteListOptions (#17028)
This PR adds a `ListOptions` type which is not paged but uses absolute values. It is implemented as discussed in Discord. Extracted from #16510 to clean that PR.
1 parent 0a542dd commit 87505a9

29 files changed

+159
-56
lines changed

models/commit_status.go

Lines changed: 3 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -97,7 +97,7 @@ func GetCommitStatuses(repo *Repository, sha string, opts *CommitStatusOptions)
9797
}
9898

9999
countSession := listCommitStatusesStatement(repo, sha, opts)
100-
countSession = opts.setSessionPagination(countSession)
100+
countSession = setSessionPagination(countSession, opts)
101101
maxResults, err := countSession.Count(new(CommitStatus))
102102
if err != nil {
103103
log.Error("Count PRs: %v", err)
@@ -106,7 +106,7 @@ func GetCommitStatuses(repo *Repository, sha string, opts *CommitStatusOptions)
106106

107107
statuses := make([]*CommitStatus, 0, opts.PageSize)
108108
findSession := listCommitStatusesStatement(repo, sha, opts)
109-
findSession = opts.setSessionPagination(findSession)
109+
findSession = setSessionPagination(findSession, opts)
110110
sortCommitStatusesSession(findSession, opts.SortType)
111111
return statuses, maxResults, findSession.Find(&statuses)
112112
}
@@ -149,7 +149,7 @@ func getLatestCommitStatus(e Engine, repoID int64, sha string, listOptions ListO
149149
Select("max( id ) as id").
150150
GroupBy("context_hash").OrderBy("max( id ) desc")
151151

152-
sess = listOptions.setSessionPagination(sess)
152+
sess = setSessionPagination(sess, &listOptions)
153153

154154
err := sess.Find(&ids)
155155
if err != nil {

models/gpg_key.go

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -64,7 +64,7 @@ func ListGPGKeys(uid int64, listOptions ListOptions) ([]*GPGKey, error) {
6464
func listGPGKeys(e Engine, uid int64, listOptions ListOptions) ([]*GPGKey, error) {
6565
sess := e.Table(&GPGKey{}).Where("owner_id=? AND primary_key_id=''", uid)
6666
if listOptions.Page != 0 {
67-
sess = listOptions.setSessionPagination(sess)
67+
sess = setSessionPagination(sess, &listOptions)
6868
}
6969

7070
keys := make([]*GPGKey, 0, 2)

models/issue_comment.go

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1007,7 +1007,7 @@ func findComments(e Engine, opts *FindCommentsOptions) ([]*Comment, error) {
10071007
}
10081008

10091009
if opts.Page != 0 {
1010-
sess = opts.setSessionPagination(sess)
1010+
sess = setSessionPagination(sess, opts)
10111011
}
10121012

10131013
// WARNING: If you change this order you will need to fix createCodeComment

models/issue_label.go

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -459,7 +459,7 @@ func getLabelsByRepoID(e Engine, repoID int64, sortType string, listOptions List
459459
}
460460

461461
if listOptions.Page != 0 {
462-
sess = listOptions.setSessionPagination(sess)
462+
sess = setSessionPagination(sess, &listOptions)
463463
}
464464

465465
return labels, sess.Find(&labels)
@@ -576,7 +576,7 @@ func getLabelsByOrgID(e Engine, orgID int64, sortType string, listOptions ListOp
576576
}
577577

578578
if listOptions.Page != 0 {
579-
sess = listOptions.setSessionPagination(sess)
579+
sess = setSessionPagination(sess, &listOptions)
580580
}
581581

582582
return labels, sess.Find(&labels)

models/issue_milestone.go

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -408,7 +408,7 @@ func GetMilestones(opts GetMilestonesOption) (MilestoneList, int64, error) {
408408
sess := x.Where(opts.toCond())
409409

410410
if opts.Page != 0 {
411-
sess = opts.setSessionPagination(sess)
411+
sess = setSessionPagination(sess, &opts)
412412
}
413413

414414
switch opts.SortType {

models/issue_reaction.go

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -87,7 +87,7 @@ func findReactions(e Engine, opts FindReactionsOptions) ([]*Reaction, error) {
8787
In("reaction.`type`", setting.UI.Reactions).
8888
Asc("reaction.issue_id", "reaction.comment_id", "reaction.created_unix", "reaction.id")
8989
if opts.Page != 0 {
90-
e = opts.setEnginePagination(e)
90+
e = setEnginePagination(e, &opts)
9191

9292
reactions := make([]*Reaction, 0, opts.PageSize)
9393
return reactions, e.Find(&reactions)

models/issue_stopwatch.go

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -45,7 +45,7 @@ func GetUserStopwatches(userID int64, listOptions ListOptions) ([]*Stopwatch, er
4545
sws := make([]*Stopwatch, 0, 8)
4646
sess := x.Where("stopwatch.user_id = ?", userID)
4747
if listOptions.Page != 0 {
48-
sess = listOptions.setSessionPagination(sess)
48+
sess = setSessionPagination(sess, &listOptions)
4949
}
5050

5151
err := sess.Find(&sws)

models/issue_tracked_time.go

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -113,7 +113,7 @@ func (opts *FindTrackedTimesOptions) toSession(e Engine) Engine {
113113
sess = sess.Where(opts.toCond())
114114

115115
if opts.Page != 0 {
116-
sess = opts.setEnginePagination(sess)
116+
sess = setEnginePagination(sess, opts)
117117
}
118118

119119
return sess

models/issue_watch.go

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -111,7 +111,7 @@ func getIssueWatchers(e Engine, issueID int64, listOptions ListOptions) (IssueWa
111111
Join("INNER", "`user`", "`user`.id = `issue_watch`.user_id")
112112

113113
if listOptions.Page != 0 {
114-
sess = listOptions.setSessionPagination(sess)
114+
sess = setSessionPagination(sess, &listOptions)
115115
watches := make([]*IssueWatch, 0, listOptions.PageSize)
116116
return watches, sess.Find(&watches)
117117
}

models/list_options.go

Lines changed: 60 additions & 19 deletions
Original file line numberDiff line numberDiff line change
@@ -10,38 +10,49 @@ import (
1010
"xorm.io/xorm"
1111
)
1212

13-
// ListOptions options to paginate results
14-
type ListOptions struct {
15-
PageSize int
16-
Page int // start from 1
13+
// Paginator is the base for different ListOptions types
14+
type Paginator interface {
15+
GetSkipTake() (skip, take int)
16+
GetStartEnd() (start, end int)
1717
}
1818

19-
func (opts *ListOptions) getPaginatedSession() *xorm.Session {
20-
opts.setDefaultValues()
19+
// getPaginatedSession creates a paginated database session
20+
func getPaginatedSession(p Paginator) *xorm.Session {
21+
skip, take := p.GetSkipTake()
2122

22-
return x.Limit(opts.PageSize, (opts.Page-1)*opts.PageSize)
23+
return x.Limit(take, skip)
2324
}
2425

25-
func (opts *ListOptions) setSessionPagination(sess *xorm.Session) *xorm.Session {
26-
opts.setDefaultValues()
26+
// setSessionPagination sets pagination for a database session
27+
func setSessionPagination(sess *xorm.Session, p Paginator) *xorm.Session {
28+
skip, take := p.GetSkipTake()
2729

28-
if opts.PageSize <= 0 {
29-
return sess
30-
}
31-
return sess.Limit(opts.PageSize, (opts.Page-1)*opts.PageSize)
30+
return sess.Limit(take, skip)
3231
}
3332

34-
func (opts *ListOptions) setEnginePagination(e Engine) Engine {
35-
opts.setDefaultValues()
33+
// setSessionPagination sets pagination for a database engine
34+
func setEnginePagination(e Engine, p Paginator) Engine {
35+
skip, take := p.GetSkipTake()
36+
37+
return e.Limit(take, skip)
38+
}
39+
40+
// ListOptions options to paginate results
41+
type ListOptions struct {
42+
PageSize int
43+
Page int // start from 1
44+
}
3645

37-
return e.Limit(opts.PageSize, (opts.Page-1)*opts.PageSize)
46+
// GetSkipTake returns the skip and take values
47+
func (opts *ListOptions) GetSkipTake() (skip, take int) {
48+
opts.setDefaultValues()
49+
return (opts.Page - 1) * opts.PageSize, opts.PageSize
3850
}
3951

4052
// GetStartEnd returns the start and end of the ListOptions
4153
func (opts *ListOptions) GetStartEnd() (start, end int) {
42-
opts.setDefaultValues()
43-
start = (opts.Page - 1) * opts.PageSize
44-
end = start + opts.PageSize
54+
start, take := opts.GetSkipTake()
55+
end = start + take
4556
return
4657
}
4758

@@ -56,3 +67,33 @@ func (opts *ListOptions) setDefaultValues() {
5667
opts.Page = 1
5768
}
5869
}
70+
71+
// AbsoluteListOptions absolute options to paginate results
72+
type AbsoluteListOptions struct {
73+
skip int
74+
take int
75+
}
76+
77+
// NewAbsoluteListOptions creates a list option with applied limits
78+
func NewAbsoluteListOptions(skip, take int) *AbsoluteListOptions {
79+
if skip < 0 {
80+
skip = 0
81+
}
82+
if take <= 0 {
83+
take = setting.API.DefaultPagingNum
84+
}
85+
if take > setting.API.MaxResponseItems {
86+
take = setting.API.MaxResponseItems
87+
}
88+
return &AbsoluteListOptions{skip, take}
89+
}
90+
91+
// GetSkipTake returns the skip and take values
92+
func (opts *AbsoluteListOptions) GetSkipTake() (skip, take int) {
93+
return opts.skip, opts.take
94+
}
95+
96+
// GetStartEnd returns the start and end values
97+
func (opts *AbsoluteListOptions) GetStartEnd() (start, end int) {
98+
return opts.skip, opts.skip + opts.take
99+
}

0 commit comments

Comments
 (0)