-
Notifications
You must be signed in to change notification settings - Fork 0
/
Copy pathoptions.go
312 lines (263 loc) · 10.5 KB
/
options.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
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
256
257
258
259
260
261
262
263
264
265
266
267
268
269
270
271
272
273
274
275
276
277
278
279
280
281
282
283
284
285
286
287
288
289
290
291
292
293
294
295
296
297
298
299
300
301
302
303
304
305
306
307
308
309
310
311
312
package morph
import "strings"
// CaseStrategy is an enumeration of the available case strategies.
type CaseStrategy string
const (
// SnakeCaseStrategy is the snake case strategy.
SnakeCaseStrategy CaseStrategy = "snake"
// ScreamingSnakeCaseStrategy is the screaming (uppercase) snake case strategy.
ScreamingSnakeCaseStrategy CaseStrategy = "screaming_snake"
// CamelCaseStrategy is the camel case strategy.
CamelCaseStrategy CaseStrategy = "camel"
// LowerCaseStrategy is the lowercase strategy.
LowerCaseStrategy CaseStrategy = "lower"
// UpperCaseStrategy is the uppercase strategy.
UpperCaseStrategy CaseStrategy = "upper"
// DefaultTableAliasLength is the default table alias length.
DefaultTableAliasLength = 1
// DefaultTableNameStrategy is the default table name strategy.
DefaultTableNameStrategy = SnakeCaseStrategy
// DefaultTableAliasStrategy is the default table alias strategy.
DefaultTableAliasStrategy = UpperCaseStrategy
// DefaultColumnNameStrategy is the default column name strategy.
DefaultColumnNameStrategy = SnakeCaseStrategy
)
// ReflectOption is a function that configures the reflection configuration.
type ReflectOption func(*ReflectConfiguration)
var (
// DefaultReflectOptions represents the default reflection options used for reflection.
DefaultReflectOptions = []ReflectOption{
WithInferredTableName(DefaultTableNameStrategy, true),
WithInferredTableAlias(DefaultTableAliasStrategy, DefaultTableAliasLength),
WithInferredColumnNames(DefaultColumnNameStrategy),
WithoutMatchingMethods("^Set.*"),
WithPrimaryKeyColumn("id"),
}
)
// ReflectConfiguration is the configuration leveraged when constructing
// tables via reflection.
type ReflectConfiguration struct {
TableName *string
TableAlias *string
IsInferredTableName bool
IsInferredTableAlias bool
IsInferredColumnNames bool
TableNameStrategy *CaseStrategy
TableAliasStrategy *CaseStrategy
ColumnNameStrategy *CaseStrategy
Tag *string
MethodExclusions []string
FieldExclusions []string
MethodExclusionPattern *string
FieldExclusionPattern *string
IsTableNamePlural bool
TableAliasLength *int
PrimaryKeyColumns []string
ColumnNameMappings map[string]string
}
// HasTableName indicates if the table name is set.
func (c *ReflectConfiguration) HasTableName() bool {
return c.TableName != nil && strings.TrimSpace(*c.TableName) != ""
}
// HasTableNameStrategy indicates if the table name strategy is set.
func (c *ReflectConfiguration) HasTableNameStrategy() bool {
return c.TableNameStrategy != nil
}
// HasTableAliasStrategy indicates if the table alias strategy is set.
func (c *ReflectConfiguration) HasTableAliasStrategy() bool {
return c.TableAliasStrategy != nil
}
// HasColumnNameStrategy indicates if the column name strategy is set.
func (c *ReflectConfiguration) HasColumnNameStrategy() bool {
return c.ColumnNameStrategy != nil
}
// SnakeCaseTableName indicates if the table name strategy is snake case.
func (c *ReflectConfiguration) SnakeCaseTableName() bool {
return c.HasTableNameStrategy() && *c.TableNameStrategy == SnakeCaseStrategy
}
// ScreamingSnakeCaseTableName indicates if the table name strategy is screaming snake case.
func (c *ReflectConfiguration) ScreamingSnakeCaseTableName() bool {
return c.HasTableNameStrategy() && *c.TableNameStrategy == ScreamingSnakeCaseStrategy
}
// CamelCaseTableName indicates if the table name strategy is camel case.
func (c *ReflectConfiguration) CamelCaseTableName() bool {
return c.HasTableNameStrategy() && *c.TableNameStrategy == CamelCaseStrategy
}
// SnakeCaseColumnName indicates if the column name strategy is snake case.
func (c *ReflectConfiguration) SnakeCaseColumnName() bool {
return c.HasColumnNameStrategy() && *c.ColumnNameStrategy == SnakeCaseStrategy
}
// ScreamingSnakeCaseColumnName indicates if the column name strategy is scream snake case.
func (c *ReflectConfiguration) ScreamingSnakeCaseColumnName() bool {
return c.HasColumnNameStrategy() && *c.ColumnNameStrategy == ScreamingSnakeCaseStrategy
}
// CamelCaseColumnName indicates if the column name strategy is camel case.
func (c *ReflectConfiguration) CamelCaseColumnName() bool {
return c.HasColumnNameStrategy() && *c.ColumnNameStrategy == CamelCaseStrategy
}
// UppercaseColumnName indicates if the column name strategy is uppercase.
func (c *ReflectConfiguration) UppercaseColumnName() bool {
return c.HasColumnNameStrategy() && *c.ColumnNameStrategy == UpperCaseStrategy
}
// LowercaseColumnName indicates if the column name strategy is uppercase.
func (c *ReflectConfiguration) LowercaseColumnName() bool {
return c.HasColumnNameStrategy() && *c.ColumnNameStrategy == LowerCaseStrategy
}
// LowercaseTableAlias indicates if the table alias strategy is lowercase.
func (c *ReflectConfiguration) LowercaseTableAlias() bool {
return c.HasTableAliasStrategy() && *c.TableAliasStrategy == LowerCaseStrategy
}
// UppercaseTableAlias indicates if the table alias strategy is uppercase.
func (c *ReflectConfiguration) UppercaseTableAlias() bool {
return c.HasTableAliasStrategy() && *c.TableAliasStrategy == UpperCaseStrategy
}
// HasTag indicates if the tag is set.
func (c *ReflectConfiguration) HasTag() bool {
return c.Tag != nil && strings.TrimSpace(*c.Tag) != ""
}
// HasMethodExclusions indicates if method exclusions are set.
func (c *ReflectConfiguration) HasMethodExclusions() bool {
return len(c.MethodExclusions) > 0
}
// HasFieldExclusions indicates if field exclusions are set.
func (c *ReflectConfiguration) HasFieldExclusions() bool {
return len(c.FieldExclusions) > 0
}
// HasMethodExclusionPattern indicates if the method exclusion pattern is set.
func (c *ReflectConfiguration) HasMethodExclusionPattern() bool {
return c.MethodExclusionPattern != nil && strings.TrimSpace(*c.MethodExclusionPattern) != ""
}
// HasFieldExclusionPattern indicates if the field exclusion pattern is set.
func (c *ReflectConfiguration) HasFieldExclusionPattern() bool {
return c.FieldExclusionPattern != nil && strings.TrimSpace(*c.FieldExclusionPattern) != ""
}
// PluralTableName indicates if the table name is plural.
func (c *ReflectConfiguration) PluralTableName() bool {
return c.IsTableNamePlural
}
// HasTableAliasLength indicates if the table alias length is set.
func (c *ReflectConfiguration) HasTableAliasLength() bool {
return c.TableAliasLength != nil
}
// HasColumnNameMappings indicates if any explicit column name mappings have
// been set.
func (c *ReflectConfiguration) HasColumnNameMappings() bool {
return len(c.ColumnNameMappings) > 0
}
var (
// WithTableName specifies the table name, effectively overriding any
// table name inference.
WithTableName = func(name string) ReflectOption {
return func(c *ReflectConfiguration) {
c.TableName = &name
c.IsInferredTableName = false
}
}
// WithTableAlias specifies the table alias, effectively overriding any
// table alias inference.
WithTableAlias = func(alias string) ReflectOption {
return func(c *ReflectConfiguration) {
c.TableAlias = &alias
c.IsInferredTableAlias = false
}
}
// WithInferredTableName indicates tha the table name should be inferred
// based on the provided strategy and plurality.
WithInferredTableName = func(strategy CaseStrategy, plural bool) ReflectOption {
return func(c *ReflectConfiguration) {
c.IsInferredTableName = true
c.TableNameStrategy = &strategy
c.IsTableNamePlural = plural
}
}
// WithInferredTableAlias indicates that the table alias should be inferred
// based on the provided strategy and length.
WithInferredTableAlias = func(strategy CaseStrategy, length int) ReflectOption {
return func(c *ReflectConfiguration) {
if length < 1 {
length = DefaultTableAliasLength
}
c.IsInferredTableAlias = true
c.TableAliasStrategy = &strategy
c.TableAliasLength = &length
}
}
// WithInferredColumnNames indicates that the column names should be inferred
// based on the provided strategy.
WithInferredColumnNames = func(strategy CaseStrategy) ReflectOption {
return func(c *ReflectConfiguration) {
c.IsInferredColumnNames = true
c.ColumnNameStrategy = &strategy
}
}
// WithTag specifies the struct tag to use for field reflection.
WithTag = func(tag string) ReflectOption {
return func(c *ReflectConfiguration) {
c.Tag = &tag
}
}
// WithoutMethods specifies the methods by name to exclude from reflection.
WithoutMethods = func(methods ...string) ReflectOption {
return func(c *ReflectConfiguration) {
if c.MethodExclusions == nil {
c.MethodExclusions = []string{}
}
c.MethodExclusions = methods
}
}
// WithoutMatchingMethods specifies a regular expression used to match against
// method names, where matches are excluded from reflection.
WithoutMatchingMethods = func(pattern string) ReflectOption {
return func(c *ReflectConfiguration) {
c.MethodExclusionPattern = &pattern
}
}
// WithoutFields specifies the struct fields by name to exclude from reflection.
WithoutFields = func(fields ...string) ReflectOption {
return func(c *ReflectConfiguration) {
if c.FieldExclusions == nil {
c.FieldExclusions = []string{}
}
c.FieldExclusions = fields
}
}
// WithoutMatchingFields specifies a regular expression used to match against
// struct field names, where matches are excluded from reflection.
WithoutMatchingFields = func(pattern string) ReflectOption {
return func(c *ReflectConfiguration) {
c.FieldExclusionPattern = &pattern
}
}
// WithPrimaryKeyColumn specifies the name of the column that acts as
// the primary key.
WithPrimaryKeyColumn = func(name string) ReflectOption {
return func(c *ReflectConfiguration) {
if c.PrimaryKeyColumns == nil {
c.PrimaryKeyColumns = []string{}
}
c.PrimaryKeyColumns = []string{name}
}
}
// WithPrimaryKeyColumns specifies the names of the column that acts together as
// the primary key.
WithPrimaryKeyColumns = func(names ...string) ReflectOption {
return func(c *ReflectConfiguration) {
if c.PrimaryKeyColumns == nil {
c.PrimaryKeyColumns = []string{}
}
pks := append([]string{}, names...)
c.PrimaryKeyColumns = pks
}
}
// WithColumnNameMapping specifies a single column mapping between the provided
// field name and column name. Both the field name and column name are case
// sensitive, and the name provided will be used regardless of other options specified.
WithColumnNameMapping = func(field, name string) ReflectOption {
return func(c *ReflectConfiguration) {
if c.ColumnNameMappings == nil {
c.ColumnNameMappings = make(map[string]string)
}
c.ColumnNameMappings[field] = name
}
}
)