Skip to content

Commit 8457d61

Browse files
committed
feat: add ExtraFilters #4
1 parent 5e72de8 commit 8457d61

File tree

2 files changed

+323
-34
lines changed

2 files changed

+323
-34
lines changed

generator.go

Lines changed: 246 additions & 21 deletions
Original file line numberDiff line numberDiff line change
@@ -7,17 +7,30 @@ import (
77
)
88

99
type IndexesInfo struct {
10-
Comment string
11-
Field string
12-
Label string
13-
SearchItem string // TODO `前方一致` や `部分一致` など (5/7 unused)
10+
Comment string
11+
ConstName string
12+
Label string
13+
Method string
14+
}
15+
16+
type FieldInfo struct {
17+
Field string
18+
FieldType string
19+
Indexes []*IndexesInfo
20+
}
21+
22+
type ImportInfo struct {
23+
Name string
1424
}
1525

1626
type generator struct {
1727
PackageName string
28+
ImportName string
29+
ImportList []ImportInfo
1830
GeneratedFileName string
1931
FileName string
2032
StructName string
33+
LowerStructName string
2134

2235
GoGenerate string
2336
RepositoryStructName string
@@ -28,10 +41,14 @@ type generator struct {
2841

2942
KeyValueName string // lower camel case
3043

31-
ConstMapForIndexes []IndexesInfo
44+
FieldInfos []*FieldInfo
45+
46+
EnableIndexes bool
47+
BoolCriteriaCnt int
3248
}
3349

3450
func (g *generator) setting() {
51+
g.ImportName = ImportName
3552
g.GoGenerate = "go:generate"
3653
g.RepositoryInterfaceName = g.StructName + "Repository"
3754
g.setRepositoryStructName()
@@ -81,9 +98,18 @@ func (g *generator) generate(writer io.Writer) {
8198
}
8299
}
83100

101+
func (g *generator) generateLabel(writer io.Writer) {
102+
t := template.Must(template.New("tmplLabel").Parse(tmplLabel))
103+
104+
err := t.Execute(writer, g)
105+
106+
if err != nil {
107+
log.Printf("failed to execute template: %+v", err)
108+
}
109+
}
110+
84111
func (g *generator) generateConstant(writer io.Writer) {
85-
g.setting()
86-
t := template.Must(template.New("tmpl").Parse(tmplConst))
112+
t := template.Must(template.New("tmplConst").Parse(tmplConst))
87113

88114
err := t.Execute(writer, g)
89115

@@ -92,13 +118,55 @@ func (g *generator) generateConstant(writer io.Writer) {
92118
}
93119
}
94120

95-
const tmplConst = `// THIS FILE IS A GENERATED CODE. EDIT OK
121+
const tmplConst = `// THIS FILE IS A GENERATED CODE. DO NOT EDIT
96122
package configs
97123
124+
import "strconv"
125+
126+
type BoolCriteria string
127+
98128
const (
99-
{{- range .ConstMapForIndexes }}
100-
// {{ .Comment }}検索用ラベル
101-
{{ .Field }} = "{{ .Label }}"
129+
BoolCriteriaEmpty BoolCriteria = ""
130+
BoolCriteriaTrue BoolCriteria = "true"
131+
BoolCriteriaFalse BoolCriteria = "false"
132+
)
133+
134+
func (src BoolCriteria) Bool() bool {
135+
return src == BoolCriteriaTrue
136+
}
137+
138+
type IntegerCriteria string
139+
140+
const (
141+
IntegerCriteriaEmpty IntegerCriteria = ""
142+
)
143+
144+
func (str IntegerCriteria) Int() int {
145+
i32, err := strconv.Atoi(string(str))
146+
if err != nil {
147+
return -1
148+
}
149+
return i32
150+
}
151+
152+
func (str IntegerCriteria) Int64() int64 {
153+
i64, err := strconv.ParseInt(string(str), 10, 64)
154+
if err != nil {
155+
return -1
156+
}
157+
return i64
158+
}
159+
`
160+
161+
const tmplLabel = `// THIS FILE IS A GENERATED CODE. EDIT OK
162+
package configs
163+
164+
const (
165+
{{- range $fi := .FieldInfos }}
166+
{{- range $idx := $fi.Indexes }}
167+
// {{ $idx.Comment }}検索用ラベル
168+
{{ $idx.ConstName }} = "{{ $idx.Label }}"
169+
{{- end }}
102170
{{- end }}
103171
)
104172
`
@@ -114,6 +182,7 @@ import (
114182
{{- end }}
115183
116184
"cloud.google.com/go/datastore"
185+
"{{ .ImportName }}/configs"
117186
"golang.org/x/xerrors"
118187
)
119188
@@ -127,11 +196,15 @@ type {{ .RepositoryInterfaceName }} interface {
127196
Delete(ctx context.Context, subject *{{ .StructName }}) error
128197
DeleteBy{{ .KeyFieldName }}(ctx context.Context, {{ .KeyValueName }} {{ .KeyFieldType }}) error
129198
// Multiple
130-
GetMulti(ctx context.Context, {{.KeyValueName}}s []{{.KeyFieldType}}) ([]*{{.StructName}}, error)
131-
InsertMulti(ctx context.Context, subjects []*{{.StructName}}) ([]{{.KeyFieldType}}, error)
132-
UpdateMulti(ctx context.Context, subjects []*{{.StructName}}) error
133-
DeleteMulti(ctx context.Context, subjects []*{{.StructName}}) error
134-
DeleteMultiBy{{.KeyFieldName}}s(ctx context.Context, {{.KeyValueName}}s []{{.KeyFieldType}}) error
199+
GetMulti(ctx context.Context, {{ .KeyValueName }}s []{{ .KeyFieldType }}) ([]*{{ .StructName }}, error)
200+
InsertMulti(ctx context.Context, subjects []*{{ .StructName }}) ([]{{ .KeyFieldType }}, error)
201+
UpdateMulti(ctx context.Context, subjects []*{{ .StructName }}) error
202+
DeleteMulti(ctx context.Context, subjects []*{{ .StructName }}) error
203+
DeleteMultiBy{{ .KeyFieldName }}s(ctx context.Context, {{ .KeyValueName }}s []{{ .KeyFieldType }}) error
204+
// List
205+
List(ctx context.Context, req *{{ .StructName }}ListReq, q *datastore.Query) ([]*{{ .StructName }}, error)
206+
// misc
207+
GetKindName() string
135208
}
136209
137210
type {{ .RepositoryStructName }} struct {
@@ -146,7 +219,12 @@ func New{{ .RepositoryInterfaceName }}(datastoreClient *datastore.Client) {{ .Re
146219
}
147220
}
148221
149-
func (repo *{{.RepositoryStructName}}) getKeys(subjects ...*{{.StructName}}) ([]*datastore.Key, error) {
222+
func (repo *{{ .RepositoryStructName }}) GetKindName() string {
223+
return repo.kind
224+
}
225+
226+
// getKeys Entityからkeyを取得する
227+
func (repo *{{ .RepositoryStructName }}) getKeys(subjects ...*{{ .StructName }}) ([]*datastore.Key, error) {
150228
keys := make([]*datastore.Key, 0, len(subjects))
151229
for _, subject := range subjects {
152230
key := subject.{{ .KeyFieldName }}
@@ -170,6 +248,137 @@ func (repo *{{.RepositoryStructName}}) getKeys(subjects ...*{{.StructName}}) ([]
170248
171249
return keys, nil
172250
}
251+
{{ if eq .EnableIndexes true }}
252+
// saveIndexes 拡張フィルタを保存する
253+
func (repo *{{ .RepositoryStructName }}) saveIndexes(subjects ...*{{ .StructName }}) error {
254+
for _, subject := range subjects {
255+
idx := xian.NewIndexes({{ .LowerStructName }}IndexesConfig)
256+
{{- range $fi := .FieldInfos }}
257+
{{- range $idx := $fi.Indexes }}
258+
{{- if eq $fi.FieldType "bool" }}
259+
idx.{{ $idx.Method }}(configs.{{ $idx.ConstName }}, subject.{{ $fi.Field }})
260+
{{- else if eq $fi.FieldType "string" }}
261+
{{- if eq $idx.Method "AddPrefix" }}
262+
idx.{{ $idx.Method }}es(configs.{{ $idx.ConstName }}, subject.{{ $fi.Field }})
263+
{{- else }}
264+
idx.{{ $idx.Method }}(configs.{{ $idx.ConstName }}, subject.{{ $fi.Field }})
265+
{{- end }}
266+
{{- else if eq $fi.FieldType "int" }}
267+
idx.{{ $idx.Method }}(configs.{{ $idx.ConstName }}, subject.{{ $fi.Field }})
268+
{{- else if eq $fi.FieldType "time.Time" }}
269+
idx.{{ $idx.Method }}(configs.{{ $idx.ConstName }}, subject.{{ $fi.Field }}.Unix())
270+
{{- end }}
271+
{{- end }}
272+
{{- end }}
273+
built, err := idx.Build()
274+
if err != nil {
275+
return err
276+
}
277+
subject.Indexes = built
278+
}
279+
280+
return nil
281+
}
282+
283+
var {{ .LowerStructName }}IndexesConfig = &xian.Config{
284+
IgnoreCase: true, // Case insensitive
285+
SaveNoFiltersIndex: true, // https://qiita.com/hogedigo/items/02dcce80f6197faae1fb#savenofiltersindex
286+
}
287+
{{- end }}
288+
289+
// {{ .StructName }}ListReq List取得時に渡すリクエスト
290+
// └─ bool/int(64) は stringで渡す(configs.BoolCriteria | configs.IntegerCriteria)
291+
type {{ .StructName }}ListReq struct {
292+
{{- range .FieldInfos }}
293+
{{- if eq .FieldType "bool" }}
294+
{{ .Field }} configs.BoolCriteria
295+
{{- else if or (eq .FieldType "int") (eq .FieldType "int64") }}
296+
{{ .Field }} configs.IntegerCriteria
297+
{{- else }}
298+
{{ .Field }} {{ .FieldType }}
299+
{{- end }}
300+
{{- end }}
301+
}
302+
303+
// List datastore.Queryを使用し条件抽出をする
304+
// └─ 第3引数はNOT/OR/IN/RANGEなど、より複雑な条件を適用したいときにつける
305+
// └─ 基本的にnilを渡せば良い
306+
// BUG(54mch4n) 潜在的なバグがあるかもしれない
307+
func (repo *{{ .RepositoryStructName }}) List(ctx context.Context, req *{{ .StructName }}ListReq, q *datastore.Query) ([]*{{ .StructName }}, error) {
308+
if q == nil {
309+
q = datastore.NewQuery(repo.kind)
310+
}
311+
{{ $Enable := .EnableIndexes }}
312+
{{- if eq $Enable true }}
313+
filters := xian.NewFilters({{ .LowerStructName }}IndexesConfig)
314+
{{- end }}
315+
{{- range $fi := .FieldInfos }}
316+
{{- if eq $fi.FieldType "bool" }}
317+
if req.{{ $fi.Field }} != "" {
318+
{{- if eq $Enable true }}
319+
{{- range $idx := $fi.Indexes }}
320+
filters.{{ $idx.Method }}(configs.{{ $idx.ConstName }}, req.{{ $fi.Field }})
321+
{{- end }}
322+
{{- else }}
323+
q = q.Filter("{{ $fi.Field }}", req.{{ $fi.Field }}.Bool())
324+
{{- end }}
325+
}
326+
{{- else if eq $fi.FieldType "string" }}
327+
if req.{{ $fi.Field }} != "" {
328+
{{- if eq $Enable true }}
329+
{{- range $idx := $fi.Indexes }}
330+
filters.{{ $idx.Method }}(configs.{{ $idx.ConstName }}, req.{{ $fi.Field }})
331+
{{- end }}
332+
{{- else }}
333+
q = q.Filter("{{ $fi.Field }}", req.{{ $fi.Field }})
334+
{{- end }}
335+
}
336+
{{- else if or (eq $fi.FieldType "int") (eq $fi.FieldType "int64") }}
337+
if req.{{ $fi.Field }} != configs.IntegerCriteriaEmpty {
338+
{{- if eq $Enable true }}
339+
{{- range $idx := $fi.Indexes }}
340+
filters.{{ $idx.Method }}(configs.{{ $idx.ConstName }}, req.{{ Parse $fi.Field $fi.FieldType }})
341+
{{- end }}
342+
{{- else }}
343+
q = q.Filter("{{ $fi.Field }}", req.{{ Parse $fi.Field $fi.FieldType }})
344+
{{- end }}
345+
}
346+
{{- else if eq $fi.FieldType "time.Time" }}
347+
if !req.{{ $fi.Field }}.IsZero() {
348+
{{- if eq $Enable true }}
349+
{{- range $idx := $fi.Indexes }}
350+
filters.{{ $idx.Method }}(configs.{{ $idx.ConstName }}, req.{{ $fi.Field }}.Unix())
351+
{{- end }}
352+
{{- else }}
353+
q = q.Filter("{{ $fi.Field }}", req.{{ $fi.Field }})
354+
{{- end }}
355+
}
356+
{{- end }}
357+
{{- end }}
358+
{{ if eq $Enable true }}
359+
built, err := filters.Build()
360+
if err != nil {
361+
return nil, err
362+
}
363+
364+
for _, f := range built {
365+
q = q.Filter("Indexes =", f)
366+
}
367+
{{- end }}
368+
subjects := make([]*{{ .StructName }}, 0)
369+
keys, err := repo.datastoreClient.GetAll(ctx, q, &subjects)
370+
if err != nil {
371+
return nil, err
372+
}
373+
374+
for i, k := range keys {
375+
if k != nil {
376+
subjects[i].ID = k.ID
377+
}
378+
}
379+
380+
return subjects, nil
381+
}
173382
174383
func (repo *{{ .RepositoryStructName }}) Get(ctx context.Context, {{ .KeyValueName }} {{ .KeyFieldType }}) (*{{ .StructName }}, error) {
175384
{{- if eq .KeyFieldType "int64" }}
@@ -206,7 +415,11 @@ func (repo *{{ .RepositoryStructName }}) Insert(ctx context.Context, subject *{{
206415
if err != nil {
207416
return zero, xerrors.Errorf("error in getKeys method: %w", err)
208417
}
209-
418+
{{ if eq .EnableIndexes true }}
419+
if err := repo.saveIndexes(subject); err != nil {
420+
return zero, xerrors.Errorf("error in saveIndexes method: %w", err)
421+
}
422+
{{ end }}
210423
key, err := repo.datastoreClient.Put(ctx, keys[0], subject)
211424
if err != nil {
212425
return zero, err
@@ -229,7 +442,11 @@ func (repo *{{ .RepositoryStructName }}) Update(ctx context.Context, subject *{{
229442
if err != nil {
230443
return xerrors.Errorf("error in getKeys method: %w", err)
231444
}
232-
445+
{{ if eq .EnableIndexes true }}
446+
if err := repo.saveIndexes(subject); err != nil {
447+
return xerrors.Errorf("error in saveIndexes method: %w", err)
448+
}
449+
{{ end }}
233450
if _, err := repo.datastoreClient.Put(ctx, keys[0], subject); err != nil {
234451
return err
235452
}
@@ -311,7 +528,11 @@ func (repo *{{ .RepositoryStructName }}) InsertMulti(ctx context.Context, subjec
311528
if len(subjects) != cnt {
312529
return nil, xerrors.Errorf("already exist. (%d)", len(subjects)-cnt)
313530
}
314-
531+
{{ if eq .EnableIndexes true }}
532+
if err := repo.saveIndexes(subjects...); err != nil {
533+
return nil, xerrors.Errorf("error in saveIndexes method: %w", err)
534+
}
535+
{{ end }}
315536
resKeys, err := repo.datastoreClient.PutMulti(ctx, keys, subjects)
316537
if err != nil {
317538
return nil, err
@@ -344,7 +565,11 @@ func (repo *{{ .RepositoryStructName }}) UpdateMulti(ctx context.Context, subjec
344565
return err
345566
}
346567
}
347-
568+
{{ if eq .EnableIndexes true }}
569+
if err := repo.saveIndexes(subjects...); err != nil {
570+
return xerrors.Errorf("error in saveIndexes method: %w", err)
571+
}
572+
{{ end }}
348573
_, err = repo.datastoreClient.PutMulti(ctx, keys, subjects)
349574
if err != nil {
350575
return err

0 commit comments

Comments
 (0)