This repository has been archived by the owner on Mar 19, 2024. It is now read-only.
-
Notifications
You must be signed in to change notification settings - Fork 7
/
stmtblr.go
108 lines (92 loc) · 2.42 KB
/
stmtblr.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
package goloquent
import (
"errors"
"fmt"
"io"
"reflect"
"sync"
"github.com/si3nloong/goloquent/expr"
)
var stmtRegistry *StmtRegistry
type Writer interface {
io.Writer
io.StringWriter
io.ByteWriter
}
type writerFunc func(Writer, reflect.Value) ([]interface{}, error)
type StmtRegistry struct {
sync.Mutex
typeEncoders map[reflect.Type]writerFunc
kindEncoders map[reflect.Kind]writerFunc
}
func init() {
stmtRegistry = NewStmtRegistry()
stmtRegistry.SetDefaultEncoders()
}
func NewStmtRegistry() *StmtRegistry {
return &StmtRegistry{
typeEncoders: make(map[reflect.Type]writerFunc),
kindEncoders: make(map[reflect.Kind]writerFunc),
}
}
func (r *StmtRegistry) SetDefaultEncoders() {
enc := DefaultStmtEncoder{registry: defaultRegistry}
r.SetTypeEncoder(reflect.TypeOf(expr.F{}), enc.encodeField)
r.SetTypeEncoder(reflect.TypeOf(expr.Sort{}), enc.encodeSort)
r.SetKindEncoder(reflect.String, enc.encodeString)
}
func (r *StmtRegistry) SetTypeEncoder(t reflect.Type, f writerFunc) {
r.Lock()
defer r.Unlock()
r.typeEncoders[t] = f
}
func (r *StmtRegistry) SetKindEncoder(k reflect.Kind, f writerFunc) {
r.Lock()
defer r.Unlock()
r.kindEncoders[k] = f
}
func (r *StmtRegistry) BuildStatement(w Writer, v reflect.Value) ([]interface{}, error) {
if encoder, isOk := r.typeEncoders[v.Type()]; isOk {
return encoder(w, v)
}
if encoder, isOk := r.kindEncoders[v.Kind()]; isOk {
return encoder(w, v)
}
return nil, fmt.Errorf("unsupported data type: %v", v)
}
type DefaultStmtEncoder struct {
registry *Registry
}
func (enc DefaultStmtEncoder) encodeString(w Writer, v reflect.Value) ([]interface{}, error) {
w.WriteString("`" + v.String() + "`")
return nil, nil
}
func (enc DefaultStmtEncoder) encodeSort(w Writer, v reflect.Value) ([]interface{}, error) {
x := v.Interface().(expr.Sort)
w.WriteString("`" + x.Name + "`")
if x.Direction == expr.Descending {
w.WriteString(" DESC")
}
return nil, nil
}
func (enc DefaultStmtEncoder) encodeField(w Writer, v reflect.Value) ([]interface{}, error) {
x, isOk := v.Interface().(expr.F)
if !isOk {
return nil, errors.New("invalid data type")
}
w.WriteString("FIELD")
w.WriteByte('(')
w.WriteString("`" + x.Name + "`")
vals := make([]interface{}, 0)
for _, vv := range x.Values {
w.WriteByte(',')
w.WriteString(variable)
it, err := enc.registry.EncodeValue(vv)
if err != nil {
return nil, err
}
vals = append(vals, it)
}
w.WriteByte(')')
return vals, nil
}