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 }