forked from siddontang/mixer
-
Notifications
You must be signed in to change notification settings - Fork 0
/
Copy pathconn_resultset.go
140 lines (118 loc) · 3.1 KB
/
conn_resultset.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
package proxy
import (
"fmt"
"github.com/siddontang/mixer/hack"
. "github.com/siddontang/mixer/mysql"
"strconv"
)
func formatValue(value interface{}) ([]byte, error) {
switch v := value.(type) {
case int8:
return strconv.AppendInt(nil, int64(v), 10), nil
case int16:
return strconv.AppendInt(nil, int64(v), 10), nil
case int32:
return strconv.AppendInt(nil, int64(v), 10), nil
case int64:
return strconv.AppendInt(nil, int64(v), 10), nil
case int:
return strconv.AppendInt(nil, int64(v), 10), nil
case uint8:
return strconv.AppendUint(nil, uint64(v), 10), nil
case uint16:
return strconv.AppendUint(nil, uint64(v), 10), nil
case uint32:
return strconv.AppendUint(nil, uint64(v), 10), nil
case uint64:
return strconv.AppendUint(nil, uint64(v), 10), nil
case uint:
return strconv.AppendUint(nil, uint64(v), 10), nil
case float32:
return strconv.AppendFloat(nil, float64(v), 'f', -1, 64), nil
case float64:
return strconv.AppendFloat(nil, float64(v), 'f', -1, 64), nil
case []byte:
return v, nil
case string:
return hack.Slice(v), nil
default:
return nil, fmt.Errorf("invalid type %T", value)
}
}
func formatField(field *Field, value interface{}) error {
switch value.(type) {
case int8, int16, int32, int64, int:
field.Charset = 63
field.Type = MYSQL_TYPE_LONGLONG
field.Flag = BINARY_FLAG | NOT_NULL_FLAG
case uint8, uint16, uint32, uint64, uint:
field.Charset = 63
field.Type = MYSQL_TYPE_LONGLONG
field.Flag = BINARY_FLAG | NOT_NULL_FLAG | UNSIGNED_FLAG
case string, []byte:
field.Charset = 33
field.Type = MYSQL_TYPE_VAR_STRING
default:
return fmt.Errorf("unsupport type %T for resultset", value)
}
return nil
}
func (c *Conn) buildResultset(names []string, values [][]interface{}) (*Resultset, error) {
r := new(Resultset)
r.Fields = make([]*Field, len(names))
var b []byte
var err error
for i, vs := range values {
if len(vs) != len(r.Fields) {
return nil, fmt.Errorf("row %d has %d column not equal %d", i, len(vs), len(r.Fields))
}
var row []byte
for j, value := range vs {
if i == 0 {
field := &Field{}
r.Fields[j] = field
field.Name = hack.Slice(names[j])
if err = formatField(field, value); err != nil {
return nil, err
}
}
b, err = formatValue(value)
if err != nil {
return nil, err
}
row = append(row, PutLengthEncodedString(b)...)
}
r.RowDatas = append(r.RowDatas, row)
}
return r, nil
}
func (c *Conn) writeResultset(status uint16, r *Resultset) error {
c.affectedRows = int64(-1)
columnLen := PutLengthEncodedInt(uint64(len(r.Fields)))
data := make([]byte, 4, 1024)
data = append(data, columnLen...)
if err := c.writePacket(data); err != nil {
return err
}
for _, v := range r.Fields {
data = data[0:4]
data = append(data, v.Dump()...)
if err := c.writePacket(data); err != nil {
return err
}
}
if err := c.writeEOF(status); err != nil {
return err
}
for _, v := range r.RowDatas {
data = data[0:4]
data = append(data, v...)
if err := c.writePacket(data); err != nil {
return err
}
}
if err := c.writeEOF(status); err != nil {
return err
}
return nil
}