-
Notifications
You must be signed in to change notification settings - Fork 1
/
Copy pathconfig.go
128 lines (120 loc) · 3.61 KB
/
config.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
package gorql
import (
"errors"
"github.com/iancoleman/strcase"
"log"
"reflect"
)
const (
DefaultTagName = "rql"
DefaultFieldSep = "_"
DefaultLimit = 25
DefaultMaxLimit = 100
)
// Config is the configuration for the parser.
type Config struct {
// TagName is an optional tag name for configuration. t defaults to "rql".
TagName string
// Model is the resource definition. The parser is configured based on its definition.
// For example, given the following struct definition:
//
// type User struct {
// Age int `rql:"filter,sort"`
// Name string `rql:"filter"`
// }
//
// In order to create a parser for the given resource, you will do it like so:
//
// var QueryParser = rql.NewParser(&rql.Config{
// Model: User{},
// })
//
Model interface{}
// FieldSep is the separator for nested fields in a struct. For example, given the following struct:
//
// type User struct {
// Name string `rql:"filter"`
// Address struct {
// City string `rql:"filter"``
// }
// }
//
// We assume the schema for this struct contains a column named "address_city". Therefore, the default
// separator is underscore ("_"). But, you can change it to "." for convenience or readability reasons.
// The parser will automatically convert it to underscore ("_"). If you want to control the name of
// the column, use the "column" option in the struct definition. For example:
//
// type User struct {
// Name string `rql:"filter,column=full_name"`
// }
//
FieldSep string
// ColumnFn is the function that translate the struct field string into a table column.
// For example, given the following fields and their column names:
//
// FullName => "full_name"
// HTTPPort => "http_port"
//
// It is preferred that you will follow the same convention that your ORM or other DB helper use.
// For example, If you are using `gorm` you want to se this option like this:
//
// var QueryParser = rql.MustNewParser(
// ColumnFn: gorm.ToDBName,
// })
//
ColumnFn func(string) string
// Log the logging function used to log debug information in the initialization of the parser.
// It defaults `to log.Printf`.
Log func(string, ...interface{})
// DefaultLimit is the default value for the `Limit` field that returns when no limit supplied by the caller.
// It defaults to 25.
DefaultLimit int
// LimitMaxValue is the upper boundary for the limit field. User will get an error if the given value is greater
// than this value. It defaults to 100.
LimitMaxValue int
}
// defaults sets the default configuration of Config.
func (c *Config) defaults() error {
if c.Model == nil {
return errors.New("rql: 'Model' is a required field")
}
if indirect(reflect.TypeOf(c.Model)).Kind() != reflect.Struct {
return errors.New("rql: 'Model' must be a struct type")
}
if c.Log == nil {
c.Log = log.Printf
}
if c.ColumnFn == nil {
c.ColumnFn = Column
}
defaultString(&c.TagName, DefaultTagName)
defaultString(&c.FieldSep, DefaultFieldSep)
defaultInt(&c.DefaultLimit, DefaultLimit)
defaultInt(&c.LimitMaxValue, DefaultMaxLimit)
return nil
}
// Column is the default function that transform field name into column name.
// It used to convert the struct fields into lower camelcase. For example:
//
// Username => username
// FullName => fullName
// HTTPCode => httpcode
func Column(s string) string {
return strcase.ToLowerCamel(s)
}
func defaultString(s *string, v string) {
if *s == "" {
*s = v
}
}
func defaultInt(i *int, v int) {
if *i == 0 {
*i = v
}
}
// indirect returns the item at the end of indirection.
func indirect(t reflect.Type) reflect.Type {
for ; t.Kind() == reflect.Ptr; t = t.Elem() {
}
return t
}