github.com/XiaoMi/Gaea@v1.2.5/mysql/resultset_sort.go (about) 1 // Copyright 2016 The kingshard Authors. All rights reserved. 2 // 3 // Licensed under the Apache License, Version 2.0 (the "License"): you may 4 // not use this file except in compliance with the License. You may obtain 5 // a copy of the License at 6 // 7 // http://www.apache.org/licenses/LICENSE-2.0 8 // 9 // Unless required by applicable law or agreed to in writing, software 10 // distributed under the License is distributed on an "AS IS" BASIS, WITHOUT 11 // WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the 12 // License for the specific language governing permissions and limitations 13 // under the License. 14 15 package mysql 16 17 import ( 18 "bytes" 19 "fmt" 20 "sort" 21 22 "github.com/XiaoMi/Gaea/util/hack" 23 ) 24 25 const ( 26 // SortAsc asc 27 SortAsc = "asc" 28 // SortDesc desc 29 SortDesc = "desc" 30 ) 31 32 // SortKey key will sort 33 type SortKey struct { 34 //name of the field 35 Name string 36 37 Direction string 38 39 //column index of the field 40 Column int 41 } 42 43 // ResultsetSorter contains resultset will sort 44 type ResultsetSorter struct { 45 *Resultset 46 47 sk []SortKey 48 } 49 50 func newResultsetSorter(r *Resultset, sk []SortKey) (*ResultsetSorter, error) { 51 s := new(ResultsetSorter) 52 53 s.Resultset = r 54 55 for i, k := range sk { 56 if column, ok := r.FieldNames[k.Name]; ok { 57 sk[i].Column = column 58 } else { 59 return nil, fmt.Errorf("key %s not in Resultset fields, can not sort", k.Name) 60 } 61 } 62 63 s.sk = sk 64 65 return s, nil 66 } 67 68 func newResultsetSorterWithoutColumnName(r *Resultset, sk []SortKey) *ResultsetSorter { 69 return &ResultsetSorter{ 70 Resultset: r, 71 sk: sk, 72 } 73 } 74 75 func (r *ResultsetSorter) Len() int { 76 return r.RowNumber() 77 } 78 79 func (r *ResultsetSorter) Less(i, j int) bool { 80 v1 := r.Values[i] 81 v2 := r.Values[j] 82 83 for _, k := range r.sk { 84 v := cmpValue(v1[k.Column], v2[k.Column]) 85 86 if k.Direction == SortDesc { 87 v = -v 88 } 89 90 if v < 0 { 91 return true 92 } else if v > 0 { 93 return false 94 } 95 96 //equal, cmp next key 97 } 98 99 return false 100 } 101 102 //compare value using asc 103 func cmpValue(v1 interface{}, v2 interface{}) int { 104 if v1 == nil && v2 == nil { 105 return 0 106 } else if v1 == nil { 107 return -1 108 } else if v2 == nil { 109 return 1 110 } 111 112 switch v := v1.(type) { 113 case string: 114 s := v2.(string) 115 return bytes.Compare(hack.Slice(v), hack.Slice(s)) 116 case []byte: 117 s := v2.([]byte) 118 return bytes.Compare(v, s) 119 case int64: 120 s := v2.(int64) 121 if v < s { 122 return -1 123 } else if v > s { 124 return 1 125 } else { 126 return 0 127 } 128 case uint64: 129 s := v2.(uint64) 130 if v < s { 131 return -1 132 } else if v > s { 133 return 1 134 } else { 135 return 0 136 } 137 case float64: 138 s := v2.(float64) 139 if v < s { 140 return -1 141 } else if v > s { 142 return 1 143 } else { 144 return 0 145 } 146 default: 147 //can not go here 148 panic(fmt.Sprintf("invalid type %T", v)) 149 } 150 } 151 152 func (r *ResultsetSorter) Swap(i, j int) { 153 r.Values[i], r.Values[j] = r.Values[j], r.Values[i] 154 155 // 有可能此时RowData已经被清除了, 防止panic 156 if len(r.RowDatas) != 0 { 157 r.RowDatas[i], r.RowDatas[j] = r.RowDatas[j], r.RowDatas[i] 158 } 159 } 160 161 // Sort sort resultset 162 func (r *Resultset) Sort(sk []SortKey) error { 163 s, err := newResultsetSorter(r, sk) 164 165 if err != nil { 166 return err 167 } 168 169 sort.Sort(s) 170 171 return nil 172 } 173 174 // SortWithoutColumnName 只使用SortKey中的column来获取列信息, 不使用Name 175 func (r *Resultset) SortWithoutColumnName(sk []SortKey) error { 176 s := newResultsetSorterWithoutColumnName(r, sk) 177 sort.Sort(s) 178 return nil 179 }