github.com/XiaoMi/Gaea@v1.2.5/parser/tidb-types/fsp.go (about) 1 // Copyright 2015 PingCAP, Inc. 2 // 3 // Licensed under the Apache License, Version 2.0 (the "License"); 4 // you may not use this file except in compliance with the License. 5 // You may obtain 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, 11 // See the License for the specific language governing permissions and 12 // limitations under the License. 13 14 package types 15 16 import ( 17 "math" 18 "strconv" 19 "strings" 20 21 "github.com/pingcap/errors" 22 ) 23 24 const ( 25 // UnspecifiedFsp is the unspecified fractional seconds part. 26 UnspecifiedFsp = -1 27 // MaxFsp is the maximum digit of fractional seconds part. 28 MaxFsp = 6 29 // MinFsp is the minimum digit of fractional seconds part. 30 MinFsp = 0 31 // DefaultFsp is the default digit of fractional seconds part. 32 // MySQL use 0 as the default Fsp. 33 DefaultFsp = 0 34 ) 35 36 // CheckFsp checks whether fsp is in valid range. 37 func CheckFsp(fsp int) (int, error) { 38 if fsp == UnspecifiedFsp { 39 return DefaultFsp, nil 40 } 41 if fsp < MinFsp || fsp > MaxFsp { 42 return DefaultFsp, errors.Errorf("Invalid fsp %d", fsp) 43 } 44 return fsp, nil 45 } 46 47 // ParseFrac parses the input string according to fsp, returns the microsecond, 48 // and also a bool value to indice overflow. eg: 49 // "999" fsp=2 will overflow. 50 func ParseFrac(s string, fsp int) (v int, overflow bool, err error) { 51 if len(s) == 0 { 52 return 0, false, nil 53 } 54 55 fsp, err = CheckFsp(fsp) 56 if err != nil { 57 return 0, false, errors.Trace(err) 58 } 59 60 if fsp >= len(s) { 61 tmp, e := strconv.ParseInt(s, 10, 64) 62 if e != nil { 63 return 0, false, errors.Trace(e) 64 } 65 v = int(float64(tmp) * math.Pow10(MaxFsp-len(s))) 66 return 67 } 68 69 // Round when fsp < string length. 70 tmp, e := strconv.ParseInt(s[:fsp+1], 10, 64) 71 if e != nil { 72 return 0, false, errors.Trace(e) 73 } 74 tmp = (tmp + 5) / 10 75 76 if float64(tmp) >= math.Pow10(fsp) { 77 // overflow 78 return 0, true, nil 79 } 80 81 // Get the final frac, with 6 digit number 82 // 1236 round 3 -> 124 -> 124000 83 // 0312 round 2 -> 3 -> 30000 84 // 999 round 2 -> 100 -> overflow 85 v = int(float64(tmp) * math.Pow10(MaxFsp-fsp)) 86 return 87 } 88 89 // alignFrac is used to generate alignment frac, like `100` -> `100000` 90 func alignFrac(s string, fsp int) string { 91 sl := len(s) 92 if sl < fsp { 93 return s + strings.Repeat("0", fsp-sl) 94 } 95 96 return s 97 }