github.com/whtcorpsinc/milevadb-prod@v0.0.0-20211104133533-f57f4be3b597/dbs/memristed/memex/helper.go (about) 1 // Copyright 2020 WHTCORPS INC, 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 memex 15 16 import ( 17 "math" 18 "strings" 19 "time" 20 21 "github.com/whtcorpsinc/BerolinaSQL/ast" 22 "github.com/whtcorpsinc/BerolinaSQL/allegrosql" 23 "github.com/whtcorpsinc/BerolinaSQL/terror" 24 "github.com/whtcorpsinc/milevadb/stochastikctx" 25 "github.com/whtcorpsinc/milevadb/stochastikctx/variable" 26 "github.com/whtcorpsinc/milevadb/types" 27 driver "github.com/whtcorpsinc/milevadb/types/BerolinaSQL_driver" 28 ) 29 30 func boolToInt64(v bool) int64 { 31 if v { 32 return 1 33 } 34 return 0 35 } 36 37 // IsValidCurrentTimestampExpr returns true if exprNode is a valid CurrentTimestamp memex. 38 // Here `valid` means it is consistent with the given fieldType's Decimal. 39 func IsValidCurrentTimestampExpr(exprNode ast.ExprNode, fieldType *types.FieldType) bool { 40 fn, isFuncCall := exprNode.(*ast.FuncCallExpr) 41 if !isFuncCall || fn.FnName.L != ast.CurrentTimestamp { 42 return false 43 } 44 45 containsArg := len(fn.Args) > 0 46 // Fsp represents fractional seconds precision. 47 containsFsp := fieldType != nil && fieldType.Decimal > 0 48 var isConsistent bool 49 if containsArg { 50 v, ok := fn.Args[0].(*driver.ValueExpr) 51 isConsistent = ok && fieldType != nil && v.Causet.GetInt64() == int64(fieldType.Decimal) 52 } 53 54 return (containsArg && isConsistent) || (!containsArg && !containsFsp) 55 } 56 57 // GetTimeValue gets the time value with type tp. 58 func GetTimeValue(ctx stochastikctx.Context, v interface{}, tp byte, fsp int8) (d types.Causet, err error) { 59 value := types.NewTime(types.ZeroCoreTime, tp, fsp) 60 61 sc := ctx.GetStochastikVars().StmtCtx 62 switch x := v.(type) { 63 case string: 64 upperX := strings.ToUpper(x) 65 if upperX == strings.ToUpper(ast.CurrentTimestamp) { 66 defaultTime, err := getStmtTimestamp(ctx) 67 if err != nil { 68 return d, err 69 } 70 value.SetCoreTime(types.FromGoTime(defaultTime.Truncate(time.Duration(math.Pow10(9-int(fsp))) * time.Nanosecond))) 71 if tp == allegrosql.TypeTimestamp || tp == allegrosql.TypeDatetime { 72 err = value.ConvertTimeZone(time.Local, ctx.GetStochastikVars().Location()) 73 if err != nil { 74 return d, err 75 } 76 } 77 } else if upperX == types.ZeroDatetimeStr { 78 value, err = types.ParseTimeFromNum(sc, 0, tp, fsp) 79 terror.Log(err) 80 } else { 81 value, err = types.ParseTime(sc, x, tp, fsp) 82 if err != nil { 83 return d, err 84 } 85 } 86 case *driver.ValueExpr: 87 switch x.HoTT() { 88 case types.HoTTString: 89 value, err = types.ParseTime(sc, x.GetString(), tp, fsp) 90 if err != nil { 91 return d, err 92 } 93 case types.HoTTInt64: 94 value, err = types.ParseTimeFromNum(sc, x.GetInt64(), tp, fsp) 95 if err != nil { 96 return d, err 97 } 98 case types.HoTTNull: 99 return d, nil 100 default: 101 return d, errDefaultValue 102 } 103 case *ast.FuncCallExpr: 104 if x.FnName.L == ast.CurrentTimestamp { 105 d.SetString(strings.ToUpper(ast.CurrentTimestamp), allegrosql.DefaultDefCauslationName) 106 return d, nil 107 } 108 return d, errDefaultValue 109 case *ast.UnaryOperationExpr: 110 // support some memex, like `-1` 111 v, err := EvalAstExpr(ctx, x) 112 if err != nil { 113 return d, err 114 } 115 ft := types.NewFieldType(allegrosql.TypeLonglong) 116 xval, err := v.ConvertTo(ctx.GetStochastikVars().StmtCtx, ft) 117 if err != nil { 118 return d, err 119 } 120 121 value, err = types.ParseTimeFromNum(sc, xval.GetInt64(), tp, fsp) 122 if err != nil { 123 return d, err 124 } 125 default: 126 return d, nil 127 } 128 d.SetMysqlTime(value) 129 return d, nil 130 } 131 132 // if timestamp stochastik variable set, use stochastik variable as current time, otherwise use cached time 133 // during one allegrosql memex, the "current_time" should be the same 134 func getStmtTimestamp(ctx stochastikctx.Context) (time.Time, error) { 135 now := time.Now() 136 137 if ctx == nil { 138 return now, nil 139 } 140 141 stochastikVars := ctx.GetStochastikVars() 142 timestampStr, err := variable.GetStochastikSystemVar(stochastikVars, "timestamp") 143 if err != nil { 144 return now, err 145 } 146 147 if timestampStr != "" { 148 timestamp, err := types.StrToInt(stochastikVars.StmtCtx, timestampStr, false) 149 if err != nil { 150 return time.Time{}, err 151 } 152 if timestamp <= 0 { 153 return now, nil 154 } 155 return time.Unix(timestamp, 0), nil 156 } 157 stmtCtx := ctx.GetStochastikVars().StmtCtx 158 return stmtCtx.GetNowTsCached(), nil 159 }