vitess.io/vitess@v0.16.2/go/vt/vtgate/engine/comparer.go (about) 1 /* 2 Copyright 2021 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 engine 18 19 import ( 20 "vitess.io/vitess/go/mysql/collations" 21 "vitess.io/vitess/go/sqltypes" 22 "vitess.io/vitess/go/vt/vtgate/evalengine" 23 ) 24 25 // comparer is the struct that has the logic for comparing two rows in the result set 26 type comparer struct { 27 orderBy, weightString, starColFixedIndex int 28 collationID collations.ID 29 desc bool 30 } 31 32 // compare compares two rows given the comparer and returns which one should be earlier in the result set 33 // -1 if the first row should be earlier 34 // 1 is the second row should be earlier 35 // 0 if both the rows have equal ordering 36 func (c *comparer) compare(r1, r2 []sqltypes.Value) (int, error) { 37 var colIndex int 38 if c.starColFixedIndex > c.orderBy && c.starColFixedIndex < len(r1) { 39 colIndex = c.starColFixedIndex 40 } else { 41 colIndex = c.orderBy 42 } 43 cmp, err := evalengine.NullsafeCompare(r1[colIndex], r2[colIndex], c.collationID) 44 if err != nil { 45 _, isComparisonErr := err.(evalengine.UnsupportedComparisonError) 46 _, isCollationErr := err.(evalengine.UnsupportedCollationError) 47 if !isComparisonErr && !isCollationErr || c.weightString == -1 { 48 return 0, err 49 } 50 // in case of a comparison or collation error switch to using the weight string column for ordering 51 c.orderBy = c.weightString 52 c.weightString = -1 53 cmp, err = evalengine.NullsafeCompare(r1[c.orderBy], r2[c.orderBy], c.collationID) 54 if err != nil { 55 return 0, err 56 } 57 } 58 // change the result if descending ordering is required 59 if c.desc { 60 cmp = -cmp 61 } 62 return cmp, nil 63 } 64 65 // extractSlices extracts the three fields of OrderByParams into a slice of comparers 66 func extractSlices(input []OrderByParams) []*comparer { 67 var result []*comparer 68 for _, order := range input { 69 result = append(result, &comparer{ 70 orderBy: order.Col, 71 weightString: order.WeightStringCol, 72 desc: order.Desc, 73 starColFixedIndex: order.StarColFixedIndex, 74 collationID: order.CollationID, 75 }) 76 } 77 return result 78 }