123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287 |
- package mysql
- import (
- "fmt"
- "strconv"
- "sync"
- "github.com/pingcap/errors"
- "github.com/siddontang/go/hack"
- )
- type StreamingType int
- const (
- // StreamingNone means there is no streaming
- StreamingNone StreamingType = iota
- // StreamingSelect is used with select queries for which each result is
- // directly returned to the client
- StreamingSelect
- // StreamingMultiple is used when multiple queries are given at once
- // usually in combination with SERVER_MORE_RESULTS_EXISTS flag set
- StreamingMultiple
- )
- type Resultset struct {
- Fields []*Field
- FieldNames map[string]int
- Values [][]FieldValue
- RawPkg []byte
- RowDatas []RowData
- Streaming StreamingType
- StreamingDone bool
- }
- var (
- resultsetPool = sync.Pool{
- New: func() interface{} {
- return &Resultset{}
- },
- }
- )
- func NewResultset(fieldsCount int) *Resultset {
- r := resultsetPool.Get().(*Resultset)
- r.Reset(fieldsCount)
- return r
- }
- func (r *Resultset) returnToPool() {
- resultsetPool.Put(r)
- }
- func (r *Resultset) Reset(fieldsCount int) {
- r.RawPkg = r.RawPkg[:0]
- r.Fields = r.Fields[:0]
- r.Values = r.Values[:0]
- r.RowDatas = r.RowDatas[:0]
- if r.FieldNames != nil {
- for k := range r.FieldNames {
- delete(r.FieldNames, k)
- }
- } else {
- r.FieldNames = make(map[string]int)
- }
- if fieldsCount == 0 {
- return
- }
- if cap(r.Fields) < fieldsCount {
- r.Fields = make([]*Field, fieldsCount)
- } else {
- r.Fields = r.Fields[:fieldsCount]
- }
- }
- func (r *Resultset) RowNumber() int {
- if r == nil {
- return 0
- }
- return len(r.Values)
- }
- func (r *Resultset) ColumnNumber() int {
- return len(r.Fields)
- }
- func (r *Resultset) GetValue(row, column int) (interface{}, error) {
- if row >= len(r.Values) || row < 0 {
- return nil, errors.Errorf("invalid row index %d", row)
- }
- if column >= len(r.Fields) || column < 0 {
- return nil, errors.Errorf("invalid column index %d", column)
- }
- return r.Values[row][column].Value(), nil
- }
- func (r *Resultset) NameIndex(name string) (int, error) {
- if column, ok := r.FieldNames[name]; ok {
- return column, nil
- } else {
- return 0, errors.Errorf("invalid field name %s", name)
- }
- }
- func (r *Resultset) GetValueByName(row int, name string) (interface{}, error) {
- if column, err := r.NameIndex(name); err != nil {
- return nil, errors.Trace(err)
- } else {
- return r.GetValue(row, column)
- }
- }
- func (r *Resultset) IsNull(row, column int) (bool, error) {
- d, err := r.GetValue(row, column)
- if err != nil {
- return false, err
- }
- return d == nil, nil
- }
- func (r *Resultset) IsNullByName(row int, name string) (bool, error) {
- if column, err := r.NameIndex(name); err != nil {
- return false, err
- } else {
- return r.IsNull(row, column)
- }
- }
- func (r *Resultset) GetUint(row, column int) (uint64, error) {
- d, err := r.GetValue(row, column)
- if err != nil {
- return 0, err
- }
- switch v := d.(type) {
- case int:
- return uint64(v), nil
- case int8:
- return uint64(v), nil
- case int16:
- return uint64(v), nil
- case int32:
- return uint64(v), nil
- case int64:
- return uint64(v), nil
- case uint:
- return uint64(v), nil
- case uint8:
- return uint64(v), nil
- case uint16:
- return uint64(v), nil
- case uint32:
- return uint64(v), nil
- case uint64:
- return v, nil
- case float32:
- return uint64(v), nil
- case float64:
- return uint64(v), nil
- case string:
- return strconv.ParseUint(v, 10, 64)
- case []byte:
- return strconv.ParseUint(string(v), 10, 64)
- case nil:
- return 0, nil
- default:
- return 0, errors.Errorf("data type is %T", v)
- }
- }
- func (r *Resultset) GetUintByName(row int, name string) (uint64, error) {
- if column, err := r.NameIndex(name); err != nil {
- return 0, err
- } else {
- return r.GetUint(row, column)
- }
- }
- func (r *Resultset) GetInt(row, column int) (int64, error) {
- v, err := r.GetUint(row, column)
- if err != nil {
- return 0, err
- }
- return int64(v), nil
- }
- func (r *Resultset) GetIntByName(row int, name string) (int64, error) {
- v, err := r.GetUintByName(row, name)
- if err != nil {
- return 0, err
- }
- return int64(v), nil
- }
- func (r *Resultset) GetFloat(row, column int) (float64, error) {
- d, err := r.GetValue(row, column)
- if err != nil {
- return 0, err
- }
- switch v := d.(type) {
- case int:
- return float64(v), nil
- case int8:
- return float64(v), nil
- case int16:
- return float64(v), nil
- case int32:
- return float64(v), nil
- case int64:
- return float64(v), nil
- case uint:
- return float64(v), nil
- case uint8:
- return float64(v), nil
- case uint16:
- return float64(v), nil
- case uint32:
- return float64(v), nil
- case uint64:
- return float64(v), nil
- case float32:
- return float64(v), nil
- case float64:
- return v, nil
- case string:
- return strconv.ParseFloat(v, 64)
- case []byte:
- return strconv.ParseFloat(string(v), 64)
- case nil:
- return 0, nil
- default:
- return 0, errors.Errorf("data type is %T", v)
- }
- }
- func (r *Resultset) GetFloatByName(row int, name string) (float64, error) {
- if column, err := r.NameIndex(name); err != nil {
- return 0, err
- } else {
- return r.GetFloat(row, column)
- }
- }
- func (r *Resultset) GetString(row, column int) (string, error) {
- d, err := r.GetValue(row, column)
- if err != nil {
- return "", err
- }
- switch v := d.(type) {
- case string:
- return v, nil
- case []byte:
- return hack.String(v), nil
- case int, int8, int16, int32, int64,
- uint, uint8, uint16, uint32, uint64:
- return fmt.Sprintf("%d", v), nil
- case float32:
- return strconv.FormatFloat(float64(v), 'f', -1, 64), nil
- case float64:
- return strconv.FormatFloat(v, 'f', -1, 64), nil
- case nil:
- return "", nil
- default:
- return "", errors.Errorf("data type is %T", v)
- }
- }
- func (r *Resultset) GetStringByName(row int, name string) (string, error) {
- if column, err := r.NameIndex(name); err != nil {
- return "", err
- } else {
- return r.GetString(row, column)
- }
- }
|