/
gorm.go
71 lines (59 loc) · 1.98 KB
/
gorm.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
package xgorm
import (
"fmt"
"reflect"
"github.com/webee/x/xpage"
"gorm.io/gorm"
)
type gormPaginator struct {
tx *gorm.DB
query *gorm.DB
items interface{}
option *PaginationOption
}
type PaginationOption struct {
UseSecond bool
IgnoreTotal bool
}
// NewPaginator 创建分页器
func NewPaginator(tx, query *gorm.DB, items interface{}, option *PaginationOption) xpage.Paginator {
return &gormPaginator{
tx: tx,
query: query,
items: items,
option: option,
}
}
// Paginate 实现Paginator接口
func (p *gormPaginator) Paginate(page, perPage int) (*xpage.Pagination, error) {
ignoreTotal := p.option != nil && p.option.IgnoreTotal
if !ignoreTotal && p.option != nil && p.option.UseSecond {
return p.Paginate2(page, perPage)
}
var total int64
if ignoreTotal {
if err := p.query.Offset(xpage.CalcOffset(page, perPage)).Limit(perPage).Find(p.items).Error; err != nil {
return nil, fmt.Errorf("pagination error: %v", err)
}
} else {
if err := p.query.Clauses(Hints{Clauses: []string{"SELECT"}, Content: "SQL_CALC_FOUND_ROWS"}).Offset(xpage.CalcOffset(page, perPage)).Limit(perPage).Find(p.items).Error; err != nil {
return nil, fmt.Errorf("pagination error: %v", err)
}
if err := p.tx.Raw("SELECT FOUND_ROWS()").Scan(&total).Error; err != nil {
return nil, fmt.Errorf("pagination count error: %v", err)
}
}
return xpage.NewPagination(page, perPage, total, p.items), nil
}
// Paginate2 实现Paginator接口
func (p *gormPaginator) Paginate2(page, perPage int) (*xpage.Pagination, error) {
model := reflect.New(reflect.Indirect(reflect.ValueOf(p.items)).Type().Elem()).Interface()
var total int64
if err := p.query.Model(model).Count(&total).Error; err != nil {
return nil, fmt.Errorf("pagination count error: %v", err)
}
if err := p.query.Offset(xpage.CalcOffset(page, perPage)).Limit(perPage).Find(p.items).Error; err != nil {
return nil, fmt.Errorf("pagination error: %v", err)
}
return xpage.NewPagination(page, perPage, total, p.items), nil
}