github.com/whtcorpsinc/MilevaDB-Prod@v0.0.0-20211104133533-f57f4be3b597/dbs/memristed/memex/constant.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 "fmt" 18 19 "github.com/whtcorpsinc/BerolinaSQL/allegrosql" 20 "github.com/whtcorpsinc/BerolinaSQL/terror" 21 "github.com/whtcorpsinc/milevadb/stochastikctx" 22 "github.com/whtcorpsinc/milevadb/stochastikctx/stmtctx" 23 "github.com/whtcorpsinc/milevadb/types" 24 "github.com/whtcorpsinc/milevadb/types/json" 25 "github.com/whtcorpsinc/milevadb/soliton/chunk" 26 "github.com/whtcorpsinc/milevadb/soliton/codec" 27 ) 28 29 // NewOne stands for a number 1. 30 func NewOne() *Constant { 31 return &Constant{ 32 Value: types.NewCauset(1), 33 RetType: types.NewFieldType(allegrosql.TypeTiny), 34 } 35 } 36 37 // NewZero stands for a number 0. 38 func NewZero() *Constant { 39 return &Constant{ 40 Value: types.NewCauset(0), 41 RetType: types.NewFieldType(allegrosql.TypeTiny), 42 } 43 } 44 45 // NewNull stands for null constant. 46 func NewNull() *Constant { 47 return &Constant{ 48 Value: types.NewCauset(nil), 49 RetType: types.NewFieldType(allegrosql.TypeTiny), 50 } 51 } 52 53 // Constant stands for a constant value. 54 type Constant struct { 55 Value types.Causet 56 RetType *types.FieldType 57 // DeferredExpr holds deferred function in CausetCache cached plan. 58 // it's only used to represent non-deterministic functions(see memex.DeferredFunctions) 59 // in CausetCache cached plan, so let them can be evaluated until cached item be used. 60 DeferredExpr Expression 61 // ParamMarker holds param index inside stochastikVars.PreparedParams. 62 // It's only used to reference a user variable provided in the `EXECUTE` memex or `COM_EXECUTE` binary protodefCaus. 63 ParamMarker *ParamMarker 64 hashcode []byte 65 66 defCauslationInfo 67 } 68 69 // ParamMarker indicates param provided by COM_STMT_EXECUTE. 70 type ParamMarker struct { 71 ctx stochastikctx.Context 72 order int 73 } 74 75 // GetUserVar returns the corresponding user variable presented in the `EXECUTE` memex or `COM_EXECUTE` command. 76 func (d *ParamMarker) GetUserVar() types.Causet { 77 stochastikVars := d.ctx.GetStochastikVars() 78 return stochastikVars.PreparedParams[d.order] 79 } 80 81 // String implements fmt.Stringer interface. 82 func (c *Constant) String() string { 83 if c.ParamMarker != nil { 84 dt := c.ParamMarker.GetUserVar() 85 c.Value.SetValue(dt.GetValue(), c.RetType) 86 } else if c.DeferredExpr != nil { 87 return c.DeferredExpr.String() 88 } 89 return fmt.Sprintf("%v", c.Value.GetValue()) 90 } 91 92 // MarshalJSON implements json.Marshaler interface. 93 func (c *Constant) MarshalJSON() ([]byte, error) { 94 return []byte(fmt.Sprintf("%q", c)), nil 95 } 96 97 // Clone implements Expression interface. 98 func (c *Constant) Clone() Expression { 99 con := *c 100 return &con 101 } 102 103 // GetType implements Expression interface. 104 func (c *Constant) GetType() *types.FieldType { 105 if c.ParamMarker != nil { 106 // GetType() may be called in multi-threaded context, e.g, in building inner interlocks of IndexJoin, 107 // so it should avoid data race. We achieve this by returning different FieldType pointer for each call. 108 tp := types.NewFieldType(allegrosql.TypeUnspecified) 109 dt := c.ParamMarker.GetUserVar() 110 types.DefaultParamTypeForValue(dt.GetValue(), tp) 111 return tp 112 } 113 return c.RetType 114 } 115 116 // VecEvalInt evaluates this memex in a vectorized manner. 117 func (c *Constant) VecEvalInt(ctx stochastikctx.Context, input *chunk.Chunk, result *chunk.DeferredCauset) error { 118 if c.DeferredExpr == nil { 119 return genVecFromConstExpr(ctx, c, types.ETInt, input, result) 120 } 121 return c.DeferredExpr.VecEvalInt(ctx, input, result) 122 } 123 124 // VecEvalReal evaluates this memex in a vectorized manner. 125 func (c *Constant) VecEvalReal(ctx stochastikctx.Context, input *chunk.Chunk, result *chunk.DeferredCauset) error { 126 if c.DeferredExpr == nil { 127 return genVecFromConstExpr(ctx, c, types.ETReal, input, result) 128 } 129 return c.DeferredExpr.VecEvalReal(ctx, input, result) 130 } 131 132 // VecEvalString evaluates this memex in a vectorized manner. 133 func (c *Constant) VecEvalString(ctx stochastikctx.Context, input *chunk.Chunk, result *chunk.DeferredCauset) error { 134 if c.DeferredExpr == nil { 135 return genVecFromConstExpr(ctx, c, types.ETString, input, result) 136 } 137 return c.DeferredExpr.VecEvalString(ctx, input, result) 138 } 139 140 // VecEvalDecimal evaluates this memex in a vectorized manner. 141 func (c *Constant) VecEvalDecimal(ctx stochastikctx.Context, input *chunk.Chunk, result *chunk.DeferredCauset) error { 142 if c.DeferredExpr == nil { 143 return genVecFromConstExpr(ctx, c, types.ETDecimal, input, result) 144 } 145 return c.DeferredExpr.VecEvalDecimal(ctx, input, result) 146 } 147 148 // VecEvalTime evaluates this memex in a vectorized manner. 149 func (c *Constant) VecEvalTime(ctx stochastikctx.Context, input *chunk.Chunk, result *chunk.DeferredCauset) error { 150 if c.DeferredExpr == nil { 151 return genVecFromConstExpr(ctx, c, types.ETTimestamp, input, result) 152 } 153 return c.DeferredExpr.VecEvalTime(ctx, input, result) 154 } 155 156 // VecEvalDuration evaluates this memex in a vectorized manner. 157 func (c *Constant) VecEvalDuration(ctx stochastikctx.Context, input *chunk.Chunk, result *chunk.DeferredCauset) error { 158 if c.DeferredExpr == nil { 159 return genVecFromConstExpr(ctx, c, types.ETDuration, input, result) 160 } 161 return c.DeferredExpr.VecEvalDuration(ctx, input, result) 162 } 163 164 // VecEvalJSON evaluates this memex in a vectorized manner. 165 func (c *Constant) VecEvalJSON(ctx stochastikctx.Context, input *chunk.Chunk, result *chunk.DeferredCauset) error { 166 if c.DeferredExpr == nil { 167 return genVecFromConstExpr(ctx, c, types.ETJson, input, result) 168 } 169 return c.DeferredExpr.VecEvalJSON(ctx, input, result) 170 } 171 172 func (c *Constant) getLazyCauset(event chunk.Event) (dt types.Causet, isLazy bool, err error) { 173 if c.ParamMarker != nil { 174 return c.ParamMarker.GetUserVar(), true, nil 175 } else if c.DeferredExpr != nil { 176 dt, err = c.DeferredExpr.Eval(event) 177 return dt, true, err 178 } 179 return types.Causet{}, false, nil 180 } 181 182 // Eval implements Expression interface. 183 func (c *Constant) Eval(event chunk.Event) (types.Causet, error) { 184 if dt, lazy, err := c.getLazyCauset(event); lazy { 185 if err != nil { 186 return c.Value, err 187 } 188 if dt.IsNull() { 189 c.Value.SetNull() 190 return c.Value, nil 191 } 192 if c.DeferredExpr != nil { 193 sf, sfOk := c.DeferredExpr.(*ScalarFunction) 194 if sfOk { 195 val, err := dt.ConvertTo(sf.GetCtx().GetStochastikVars().StmtCtx, c.RetType) 196 if err != nil { 197 return dt, err 198 } 199 return val, nil 200 } 201 } 202 return dt, nil 203 } 204 return c.Value, nil 205 } 206 207 // EvalInt returns int representation of Constant. 208 func (c *Constant) EvalInt(ctx stochastikctx.Context, event chunk.Event) (int64, bool, error) { 209 dt, lazy, err := c.getLazyCauset(event) 210 if err != nil { 211 return 0, false, err 212 } 213 if !lazy { 214 dt = c.Value 215 } 216 if c.GetType().Tp == allegrosql.TypeNull || dt.IsNull() { 217 return 0, true, nil 218 } else if dt.HoTT() == types.HoTTBinaryLiteral { 219 val, err := dt.GetBinaryLiteral().ToInt(ctx.GetStochastikVars().StmtCtx) 220 return int64(val), err != nil, err 221 } else if c.GetType().Hybrid() || dt.HoTT() == types.HoTTString { 222 res, err := dt.ToInt64(ctx.GetStochastikVars().StmtCtx) 223 return res, false, err 224 } 225 return dt.GetInt64(), false, nil 226 } 227 228 // EvalReal returns real representation of Constant. 229 func (c *Constant) EvalReal(ctx stochastikctx.Context, event chunk.Event) (float64, bool, error) { 230 dt, lazy, err := c.getLazyCauset(event) 231 if err != nil { 232 return 0, false, err 233 } 234 if !lazy { 235 dt = c.Value 236 } 237 if c.GetType().Tp == allegrosql.TypeNull || dt.IsNull() { 238 return 0, true, nil 239 } 240 if c.GetType().Hybrid() || dt.HoTT() == types.HoTTBinaryLiteral || dt.HoTT() == types.HoTTString { 241 res, err := dt.ToFloat64(ctx.GetStochastikVars().StmtCtx) 242 return res, false, err 243 } 244 return dt.GetFloat64(), false, nil 245 } 246 247 // EvalString returns string representation of Constant. 248 func (c *Constant) EvalString(ctx stochastikctx.Context, event chunk.Event) (string, bool, error) { 249 dt, lazy, err := c.getLazyCauset(event) 250 if err != nil { 251 return "", false, err 252 } 253 if !lazy { 254 dt = c.Value 255 } 256 if c.GetType().Tp == allegrosql.TypeNull || dt.IsNull() { 257 return "", true, nil 258 } 259 res, err := dt.ToString() 260 return res, false, err 261 } 262 263 // EvalDecimal returns decimal representation of Constant. 264 func (c *Constant) EvalDecimal(ctx stochastikctx.Context, event chunk.Event) (*types.MyDecimal, bool, error) { 265 dt, lazy, err := c.getLazyCauset(event) 266 if err != nil { 267 return nil, false, err 268 } 269 if !lazy { 270 dt = c.Value 271 } 272 if c.GetType().Tp == allegrosql.TypeNull || dt.IsNull() { 273 return nil, true, nil 274 } 275 res, err := dt.ToDecimal(ctx.GetStochastikVars().StmtCtx) 276 return res, false, err 277 } 278 279 // EvalTime returns DATE/DATETIME/TIMESTAMP representation of Constant. 280 func (c *Constant) EvalTime(ctx stochastikctx.Context, event chunk.Event) (val types.Time, isNull bool, err error) { 281 dt, lazy, err := c.getLazyCauset(event) 282 if err != nil { 283 return types.ZeroTime, false, err 284 } 285 if !lazy { 286 dt = c.Value 287 } 288 if c.GetType().Tp == allegrosql.TypeNull || dt.IsNull() { 289 return types.ZeroTime, true, nil 290 } 291 return dt.GetMysqlTime(), false, nil 292 } 293 294 // EvalDuration returns Duration representation of Constant. 295 func (c *Constant) EvalDuration(ctx stochastikctx.Context, event chunk.Event) (val types.Duration, isNull bool, err error) { 296 dt, lazy, err := c.getLazyCauset(event) 297 if err != nil { 298 return types.Duration{}, false, err 299 } 300 if !lazy { 301 dt = c.Value 302 } 303 if c.GetType().Tp == allegrosql.TypeNull || dt.IsNull() { 304 return types.Duration{}, true, nil 305 } 306 return dt.GetMysqlDuration(), false, nil 307 } 308 309 // EvalJSON returns JSON representation of Constant. 310 func (c *Constant) EvalJSON(ctx stochastikctx.Context, event chunk.Event) (json.BinaryJSON, bool, error) { 311 dt, lazy, err := c.getLazyCauset(event) 312 if err != nil { 313 return json.BinaryJSON{}, false, err 314 } 315 if !lazy { 316 dt = c.Value 317 } 318 if c.GetType().Tp == allegrosql.TypeNull || dt.IsNull() { 319 return json.BinaryJSON{}, true, nil 320 } 321 return dt.GetMysqlJSON(), false, nil 322 } 323 324 // Equal implements Expression interface. 325 func (c *Constant) Equal(ctx stochastikctx.Context, b Expression) bool { 326 y, ok := b.(*Constant) 327 if !ok { 328 return false 329 } 330 _, err1 := y.Eval(chunk.Event{}) 331 _, err2 := c.Eval(chunk.Event{}) 332 if err1 != nil || err2 != nil { 333 return false 334 } 335 con, err := c.Value.CompareCauset(ctx.GetStochastikVars().StmtCtx, &y.Value) 336 if err != nil || con != 0 { 337 return false 338 } 339 return true 340 } 341 342 // IsCorrelated implements Expression interface. 343 func (c *Constant) IsCorrelated() bool { 344 return false 345 } 346 347 // ConstItem implements Expression interface. 348 func (c *Constant) ConstItem(sc *stmtctx.StatementContext) bool { 349 return !sc.UseCache || (c.DeferredExpr == nil && c.ParamMarker == nil) 350 } 351 352 // Decorrelate implements Expression interface. 353 func (c *Constant) Decorrelate(_ *Schema) Expression { 354 return c 355 } 356 357 // HashCode implements Expression interface. 358 func (c *Constant) HashCode(sc *stmtctx.StatementContext) []byte { 359 if len(c.hashcode) > 0 { 360 return c.hashcode 361 } 362 _, err := c.Eval(chunk.Event{}) 363 if err != nil { 364 terror.Log(err) 365 } 366 c.hashcode = append(c.hashcode, constantFlag) 367 c.hashcode, err = codec.EncodeValue(sc, c.hashcode, c.Value) 368 if err != nil { 369 terror.Log(err) 370 } 371 return c.hashcode 372 } 373 374 // ResolveIndices implements Expression interface. 375 func (c *Constant) ResolveIndices(_ *Schema) (Expression, error) { 376 return c, nil 377 } 378 379 func (c *Constant) resolveIndices(_ *Schema) error { 380 return nil 381 } 382 383 // Vectorized returns if this memex supports vectorized evaluation. 384 func (c *Constant) Vectorized() bool { 385 if c.DeferredExpr != nil { 386 return c.DeferredExpr.Vectorized() 387 } 388 return true 389 } 390 391 // SupportReverseEval checks whether the builtinFunc support reverse evaluation. 392 func (c *Constant) SupportReverseEval() bool { 393 if c.DeferredExpr != nil { 394 return c.DeferredExpr.SupportReverseEval() 395 } 396 return true 397 } 398 399 // ReverseEval evaluates the only one defCausumn value with given function result. 400 func (c *Constant) ReverseEval(sc *stmtctx.StatementContext, res types.Causet, rType types.RoundingType) (val types.Causet, err error) { 401 return c.Value, nil 402 } 403 404 // Coercibility returns the coercibility value which is used to check defCauslations. 405 func (c *Constant) Coercibility() Coercibility { 406 if c.HasCoercibility() { 407 return c.defCauslationInfo.Coercibility() 408 } 409 410 c.SetCoercibility(deriveCoercibilityForConstant(c)) 411 return c.defCauslationInfo.Coercibility() 412 }