github.com/team-ide/go-dialect@v1.9.20/vitess/sqltypes/named_result.go (about) 1 /* 2 Copyright 2019 The Vitess Authors. 3 4 Licensed under the Apache License, Version 2.0 (the "License"); 5 you may not use this file except in compliance with the License. 6 You may obtain a copy of the License at 7 8 http://www.apache.org/licenses/LICENSE-2.0 9 10 Unless required by applicable law or agreed to in writing, software 11 distributed under the License is distributed on an "AS IS" BASIS, 12 WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 13 See the License for the specific language governing permissions and 14 limitations under the License. 15 */ 16 17 package sqltypes 18 19 import ( 20 "errors" 21 22 querypb "github.com/team-ide/go-dialect/vitess/query" 23 ) 24 25 var ( 26 // ErrNoSuchField indicates a search for a value by an unknown field/column name 27 ErrNoSuchField = errors.New("No such field in RowNamedValues") 28 ) 29 30 // RowNamedValues contains a row's values as a map based on Field (aka table column) name 31 type RowNamedValues map[string]Value 32 33 // ToString returns the named field as string 34 func (r RowNamedValues) ToString(fieldName string) (string, error) { 35 if v, ok := r[fieldName]; ok { 36 return v.ToString(), nil 37 } 38 return "", ErrNoSuchField 39 } 40 41 // AsString returns the named field as string, or default value if nonexistent/error 42 func (r RowNamedValues) AsString(fieldName string, def string) string { 43 if v, err := r.ToString(fieldName); err == nil { 44 return v 45 } 46 return def 47 } 48 49 // ToInt64 returns the named field as int64 50 func (r RowNamedValues) ToInt64(fieldName string) (int64, error) { 51 if v, ok := r[fieldName]; ok { 52 return v.ToInt64() 53 } 54 return 0, ErrNoSuchField 55 } 56 57 // AsInt64 returns the named field as int64, or default value if nonexistent/error 58 func (r RowNamedValues) AsInt64(fieldName string, def int64) int64 { 59 if v, err := r.ToInt64(fieldName); err == nil { 60 return v 61 } 62 return def 63 } 64 65 // ToUint64 returns the named field as uint64 66 func (r RowNamedValues) ToUint64(fieldName string) (uint64, error) { 67 if v, ok := r[fieldName]; ok { 68 return v.ToUint64() 69 } 70 return 0, ErrNoSuchField 71 } 72 73 // AsUint64 returns the named field as uint64, or default value if nonexistent/error 74 func (r RowNamedValues) AsUint64(fieldName string, def uint64) uint64 { 75 if v, err := r.ToUint64(fieldName); err == nil { 76 return v 77 } 78 return def 79 } 80 81 // AsFloat64 returns the named field as float64, or default value if nonexistent/error 82 func (r RowNamedValues) AsFloat64(fieldName string, def float64) float64 { 83 if v, err := r.ToFloat64(fieldName); err == nil { 84 return v 85 } 86 return def 87 } 88 89 // ToFloat64 returns the named field as float64 90 func (r RowNamedValues) ToFloat64(fieldName string) (float64, error) { 91 if v, ok := r[fieldName]; ok { 92 return v.ToFloat64() 93 } 94 return 0, ErrNoSuchField 95 } 96 97 // ToBool returns the named field as bool 98 func (r RowNamedValues) ToBool(fieldName string) (bool, error) { 99 if v, ok := r[fieldName]; ok { 100 return v.ToBool() 101 } 102 return false, ErrNoSuchField 103 } 104 105 // AsBool returns the named field as bool, or default value if nonexistent/error 106 func (r RowNamedValues) AsBool(fieldName string, def bool) bool { 107 if v, err := r.ToBool(fieldName); err == nil { 108 return v 109 } 110 return def 111 } 112 113 // ToBytes returns the named field as a byte array 114 func (r RowNamedValues) ToBytes(fieldName string) ([]byte, error) { 115 if v, ok := r[fieldName]; ok { 116 return v.ToBytes() 117 } 118 return nil, ErrNoSuchField 119 } 120 121 // AsBytes returns the named field as a byte array, or default value if nonexistent/error 122 func (r RowNamedValues) AsBytes(fieldName string, def []byte) []byte { 123 if v, err := r.ToBytes(fieldName); err == nil { 124 return v 125 } 126 return def 127 } 128 129 // NamedResult represents a query result with named values as opposed to ordinal values. 130 type NamedResult struct { 131 Fields []*querypb.Field `json:"fields"` 132 RowsAffected uint64 `json:"rows_affected"` 133 InsertID uint64 `json:"insert_id"` 134 Rows []RowNamedValues `json:"rows"` 135 } 136 137 // ToNamedResult converts a Result struct into a new NamedResult struct 138 func ToNamedResult(result *Result) (r *NamedResult) { 139 if result == nil { 140 return r 141 } 142 r = &NamedResult{ 143 Fields: result.Fields, 144 RowsAffected: result.RowsAffected, 145 InsertID: result.InsertID, 146 } 147 columnOrdinals := make(map[int]string) 148 for i, field := range result.Fields { 149 columnOrdinals[i] = field.Name 150 } 151 r.Rows = make([]RowNamedValues, len(result.Rows)) 152 for rowIndex, row := range result.Rows { 153 namedRow := make(RowNamedValues) 154 for i, value := range row { 155 namedRow[columnOrdinals[i]] = value 156 } 157 r.Rows[rowIndex] = namedRow 158 } 159 return r 160 } 161 162 // Row assumes this result has exactly one row, and returns it, or else returns nil. 163 // It is useful for queries like: 164 // - select count(*) from ... 165 // - select @@read_only 166 // - select UNIX_TIMESTAMP() from dual 167 func (r *NamedResult) Row() RowNamedValues { 168 if len(r.Rows) != 1 { 169 return nil 170 } 171 return r.Rows[0] 172 }