github.com/insionng/yougam@v0.0.0-20170714101924-2bc18d833463/libraries/pingcap/tidb/mysql/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 mysql 15 16 import ( 17 "math" 18 "strconv" 19 "strings" 20 21 "github.com/insionng/yougam/libraries/juju/errors" 22 ) 23 24 const ( 25 // UnspecifiedFsp is the unspecified fractional seconds part. 26 UnspecifiedFsp int = -1 27 // MaxFsp is the maximum digit of fractional seconds part. 28 MaxFsp int = 6 29 // MinFsp is the minimum digit of fractional seconds part. 30 MinFsp int = 0 31 // DefaultFsp is the default digit of fractional seconds part. 32 // MySQL use 0 as the default Fsp. 33 DefaultFsp int = 0 34 ) 35 36 func checkFsp(fsp int) (int, error) { 37 if fsp == UnspecifiedFsp { 38 return DefaultFsp, nil 39 } 40 if fsp < MinFsp || fsp > MaxFsp { 41 return DefaultFsp, errors.Errorf("Invalid fsp %d", fsp) 42 } 43 return fsp, nil 44 } 45 46 func parseFrac(s string, fsp int) (int, error) { 47 if len(s) == 0 { 48 return 0, nil 49 } 50 51 var err error 52 fsp, err = checkFsp(fsp) 53 if err != nil { 54 return 0, errors.Trace(err) 55 } 56 57 // Use float to calculate frac, e.g, "123" -> "0.123" 58 if !strings.HasPrefix(s, ".") && !strings.HasPrefix(s, "0.") { 59 s = "0." + s 60 } 61 62 frac, err := strconv.ParseFloat(s, 64) 63 if err != nil { 64 return 0, errors.Trace(err) 65 } 66 67 // round frac to the nearest value with FSP 68 var round float64 69 pow := math.Pow(10, float64(fsp)) 70 digit := pow * frac 71 _, div := math.Modf(digit) 72 if div >= 0.5 { 73 round = math.Ceil(digit) 74 } else { 75 round = math.Floor(digit) 76 } 77 78 // Get the final frac, with 6 digit number 79 // 0.1236 round 3 -> 124 -> 123000 80 // 0.0312 round 2 -> 3 -> 30000 81 return int(round * math.Pow10(MaxFsp-fsp)), nil 82 } 83 84 // alignFrac is used to generate alignment frac, like `100` -> `100000` 85 func alignFrac(s string, fsp int) string { 86 sl := len(s) 87 if sl < fsp { 88 return s + strings.Repeat("0", fsp-sl) 89 } 90 91 return s 92 }