-
Notifications
You must be signed in to change notification settings - Fork 0
/
query.go
150 lines (118 loc) · 3.5 KB
/
query.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
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
package condition
import (
"gorm.io/gorm"
"github.com/FrancoLiberali/cql/model"
)
type Query[T model.Model] struct {
gormQuery *GormQuery
err error
}
// Ascending specify an ascending order when retrieving models from database
func (query *Query[T]) Ascending(field IField) *Query[T] {
return query.order(field, false)
}
// Descending specify a descending order when retrieving models from database
func (query *Query[T]) Descending(field IField) *Query[T] {
return query.order(field, true)
}
// Order specify order when retrieving models from database
// if descending is true, the ordering is in descending direction
func (query *Query[T]) order(field IField, descending bool) *Query[T] {
err := query.gormQuery.Order(field, descending)
if err != nil {
methodName := "Ascending"
if descending {
methodName = "Descending"
}
query.addError(methodError(err, methodName))
}
return query
}
// Limit specify the number of models to be retrieved
//
// Limit conditions can be cancelled by using `Limit(-1)`
func (query *Query[T]) Limit(limit int) *Query[T] {
query.gormQuery.Limit(limit)
return query
}
// Offset specify the number of models to skip before starting to return the results
//
// Offset conditions can be cancelled by using `Offset(-1)`
//
// Warning: in MySQL Offset can only be used if Limit is also used
func (query *Query[T]) Offset(offset int) *Query[T] {
query.gormQuery.Offset(offset)
return query
}
// Finishing methods
// Count returns the amount of models that fulfill the conditions
func (query *Query[T]) Count() (int64, error) {
if query.err != nil {
return 0, query.err
}
return query.gormQuery.Count()
}
// First finds the first model ordered by primary key, matching given conditions
// or returns gorm.ErrRecordNotFound is if no model does it
func (query *Query[T]) First() (*T, error) {
if query.err != nil {
return nil, query.err
}
var model *T
return model, query.gormQuery.First(&model)
}
// Take finds the first model returned by the database in no specified order, matching given conditions
// or returns gorm.ErrRecordNotFound is if no model does it
func (query *Query[T]) Take() (*T, error) {
if query.err != nil {
return nil, query.err
}
var model *T
return model, query.gormQuery.Take(&model)
}
// Last finds the last model ordered by primary key, matching given conditions
// or returns gorm.ErrRecordNotFound is if no model does it
func (query *Query[T]) Last() (*T, error) {
if query.err != nil {
return nil, query.err
}
var model *T
return model, query.gormQuery.Last(&model)
}
// FindOne finds the only one model that matches given conditions
// or returns error if 0 or more than 1 are found.
func (query *Query[T]) FindOne() (*T, error) {
models, err := query.Find()
if err != nil {
return nil, err
}
switch {
case len(models) == 1:
return models[0], nil
case len(models) == 0:
return nil, ErrObjectNotFound
default:
return nil, ErrMoreThanOneObjectFound
}
}
// Find finds all models matching given conditions
func (query *Query[T]) Find() ([]*T, error) {
if query.err != nil {
return nil, query.err
}
var models []*T
return models, query.gormQuery.Find(&models)
}
func (query *Query[T]) addError(err error) {
if query.err == nil {
query.err = err
}
}
// Create a Query to which the conditions are applied inside transaction tx
func NewQuery[T model.Model](tx *gorm.DB, conditions ...Condition[T]) *Query[T] {
gormQuery, err := ApplyConditions[T](tx, conditions)
return &Query[T]{
gormQuery: gormQuery,
err: err,
}
}