/
paginator.go
103 lines (86 loc) · 2.53 KB
/
paginator.go
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
package paginator
import (
"math"
"gorm.io/gorm"
"gorm.io/gorm/clause"
)
const (
MinPageNumber = 1
MinPageSize = 1
)
// Paginator is basic struct contains pagination information
type Paginator struct {
Page Page
Order []Order
Filter map[string]string
}
// New is helper function for create Paginator instance
func New(page Page, orders []Order, filter map[string]string) *Paginator {
paginator := Paginator{
Page: page,
Order: orders,
Filter: filter,
}
paginator.limitMinPageNumber(MinPageNumber)
paginator.limitMinPageSize(MinPageSize)
return &paginator
}
// GenGormTransaction generate GORMv2 sql Transaction (gorm.DB) for paging
func (pgntr Paginator) GenGormTransaction(tx *gorm.DB) *gorm.DB {
tx = pgntr.offset(tx)
tx = pgntr.limit(tx)
tx = pgntr.orderBy(tx)
tx = pgntr.where(tx)
return tx
}
// CountPageTotal is setter of Paginator.Page.Total by counting total page number
func (pgntr *Paginator) CountPageTotal(tx *gorm.DB) error {
var count int64
// remove offset, limit and order by before count
delete(tx.Statement.Clauses, "ORDER BY")
tx.Offset(-1).Limit(-1).Count(&count)
pgntr.Page.Total = int(math.Ceil(float64(count) / float64(pgntr.Page.Size)))
// limit PageNumber <= PageTotal
pgntr.LimitPageTotal()
return nil
}
func (pgntr Paginator) where(tx *gorm.DB) *gorm.DB {
return tx.Where(pgntr.Filter)
}
func (pgntr Paginator) offset(tx *gorm.DB) *gorm.DB {
// concat OFFSET SQL query statement by Paginator.Page.Number/Size
return tx.Offset((pgntr.Page.Number - 1) * pgntr.Page.Size)
}
func (pgntr Paginator) limit(tx *gorm.DB) *gorm.DB {
// concat LIMIT SQL query statement by Paginator.Page.Size
return tx.Limit(pgntr.Page.Size)
}
func (pgntr Paginator) orderBy(tx *gorm.DB) *gorm.DB {
// concat ORDER SQL query statement by Paginator.order
for _, order := range pgntr.Order {
tx = tx.Order(clause.OrderByColumn{Column: clause.Column{Name: order.Column}, Desc: order.Direction == SortDESC})
}
return tx
}
func (pgntr *Paginator) limitMinPageNumber(minPageNumber int) {
// limit PageNumber >= minPageNumber
if pgntr.Page.Number < minPageNumber {
pgntr.Page.Number = minPageNumber
}
}
func (pgntr *Paginator) limitMinPageSize(minPageSize int) {
// limit PageSize >= minPageSize
if pgntr.Page.Size < minPageSize {
pgntr.Page.Size = minPageSize
}
}
func (pgntr *Paginator) LimitPageTotal() {
// set page total default to 1
if pgntr.Page.Total == 0 {
pgntr.Page.Total = 1
}
// limit PageNumber <= PageTotal
if pgntr.Page.Number > pgntr.Page.Total {
pgntr.Page.Number = pgntr.Page.Total
}
}