github.com/whtcorpsinc/MilevaDB-Prod@v0.0.0-20211104133533-f57f4be3b597/dbs/memristed/memex/expression.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 goJSON "encoding/json" 18 "fmt" 19 "strings" 20 "sync" 21 "sync/atomic" 22 23 "github.com/gogo/protobuf/proto" 24 "github.com/whtcorpsinc/BerolinaSQL/allegrosql" 25 "github.com/whtcorpsinc/BerolinaSQL/ast" 26 "github.com/whtcorpsinc/BerolinaSQL/opcode" 27 "github.com/whtcorpsinc/BerolinaSQL/perceptron" 28 "github.com/whtcorpsinc/BerolinaSQL/terror" 29 "github.com/whtcorpsinc/errors" 30 "github.com/whtcorpsinc/failpoint" 31 "github.com/whtcorpsinc/fidelpb/go-fidelpb" 32 "github.com/whtcorpsinc/milevadb/ekv" 33 "github.com/whtcorpsinc/milevadb/soliton/chunk" 34 "github.com/whtcorpsinc/milevadb/soliton/generatedexpr" 35 "github.com/whtcorpsinc/milevadb/soliton/logutil" 36 "github.com/whtcorpsinc/milevadb/stochastikctx" 37 "github.com/whtcorpsinc/milevadb/stochastikctx/stmtctx" 38 "github.com/whtcorpsinc/milevadb/types" 39 "github.com/whtcorpsinc/milevadb/types/json" 40 "go.uber.org/zap" 41 ) 42 43 // These are byte flags used for `HashCode()`. 44 const ( 45 constantFlag byte = 0 46 defCausumnFlag byte = 1 47 scalarFunctionFlag byte = 3 48 ) 49 50 // EvalAstExpr evaluates ast memex directly. 51 var EvalAstExpr func(sctx stochastikctx.Context, expr ast.ExprNode) (types.Causet, error) 52 53 // RewriteAstExpr rewrites ast memex directly. 54 var RewriteAstExpr func(sctx stochastikctx.Context, expr ast.ExprNode, schemaReplicant *Schema, names types.NameSlice) (Expression, error) 55 56 // VecExpr contains all vectorized evaluation methods. 57 type VecExpr interface { 58 // Vectorized returns if this memex supports vectorized evaluation. 59 Vectorized() bool 60 61 // VecEvalInt evaluates this memex in a vectorized manner. 62 VecEvalInt(ctx stochastikctx.Context, input *chunk.Chunk, result *chunk.DeferredCauset) error 63 64 // VecEvalReal evaluates this memex in a vectorized manner. 65 VecEvalReal(ctx stochastikctx.Context, input *chunk.Chunk, result *chunk.DeferredCauset) error 66 67 // VecEvalString evaluates this memex in a vectorized manner. 68 VecEvalString(ctx stochastikctx.Context, input *chunk.Chunk, result *chunk.DeferredCauset) error 69 70 // VecEvalDecimal evaluates this memex in a vectorized manner. 71 VecEvalDecimal(ctx stochastikctx.Context, input *chunk.Chunk, result *chunk.DeferredCauset) error 72 73 // VecEvalTime evaluates this memex in a vectorized manner. 74 VecEvalTime(ctx stochastikctx.Context, input *chunk.Chunk, result *chunk.DeferredCauset) error 75 76 // VecEvalDuration evaluates this memex in a vectorized manner. 77 VecEvalDuration(ctx stochastikctx.Context, input *chunk.Chunk, result *chunk.DeferredCauset) error 78 79 // VecEvalJSON evaluates this memex in a vectorized manner. 80 VecEvalJSON(ctx stochastikctx.Context, input *chunk.Chunk, result *chunk.DeferredCauset) error 81 } 82 83 // ReverseExpr contains all resersed evaluation methods. 84 type ReverseExpr interface { 85 // SupportReverseEval checks whether the builtinFunc support reverse evaluation. 86 SupportReverseEval() bool 87 88 // ReverseEval evaluates the only one defCausumn value with given function result. 89 ReverseEval(sc *stmtctx.StatementContext, res types.Causet, rType types.RoundingType) (val types.Causet, err error) 90 } 91 92 // Expression represents all scalar memex in ALLEGROALLEGROSQL. 93 type Expression interface { 94 fmt.Stringer 95 goJSON.Marshaler 96 VecExpr 97 ReverseExpr 98 DefCauslationInfo 99 100 // Eval evaluates an memex through a event. 101 Eval(event chunk.Event) (types.Causet, error) 102 103 // EvalInt returns the int64 representation of memex. 104 EvalInt(ctx stochastikctx.Context, event chunk.Event) (val int64, isNull bool, err error) 105 106 // EvalReal returns the float64 representation of memex. 107 EvalReal(ctx stochastikctx.Context, event chunk.Event) (val float64, isNull bool, err error) 108 109 // EvalString returns the string representation of memex. 110 EvalString(ctx stochastikctx.Context, event chunk.Event) (val string, isNull bool, err error) 111 112 // EvalDecimal returns the decimal representation of memex. 113 EvalDecimal(ctx stochastikctx.Context, event chunk.Event) (val *types.MyDecimal, isNull bool, err error) 114 115 // EvalTime returns the DATE/DATETIME/TIMESTAMP representation of memex. 116 EvalTime(ctx stochastikctx.Context, event chunk.Event) (val types.Time, isNull bool, err error) 117 118 // EvalDuration returns the duration representation of memex. 119 EvalDuration(ctx stochastikctx.Context, event chunk.Event) (val types.Duration, isNull bool, err error) 120 121 // EvalJSON returns the JSON representation of memex. 122 EvalJSON(ctx stochastikctx.Context, event chunk.Event) (val json.BinaryJSON, isNull bool, err error) 123 124 // GetType gets the type that the memex returns. 125 GetType() *types.FieldType 126 127 // Clone copies an memex totally. 128 Clone() Expression 129 130 // Equal checks whether two memexs are equal. 131 Equal(ctx stochastikctx.Context, e Expression) bool 132 133 // IsCorrelated checks if this memex has correlated key. 134 IsCorrelated() bool 135 136 // ConstItem checks if this memex is constant item, regardless of query evaluation state. 137 // An memex is constant item if it: 138 // refers no blocks. 139 // refers no correlated defCausumn. 140 // refers no subqueries that refers any blocks. 141 // refers no non-deterministic functions. 142 // refers no memex parameters. 143 // refers no param markers when prepare plan cache is enabled. 144 ConstItem(sc *stmtctx.StatementContext) bool 145 146 // Decorrelate try to decorrelate the memex by schemaReplicant. 147 Decorrelate(schemaReplicant *Schema) Expression 148 149 // ResolveIndices resolves indices by the given schemaReplicant. It will copy the original memex and return the copied one. 150 ResolveIndices(schemaReplicant *Schema) (Expression, error) 151 152 // resolveIndices is called inside the `ResolveIndices` It will perform on the memex itself. 153 resolveIndices(schemaReplicant *Schema) error 154 155 // ExplainInfo returns operator information to be explained. 156 ExplainInfo() string 157 158 // ExplainNormalizedInfo returns operator normalized information for generating digest. 159 ExplainNormalizedInfo() string 160 161 // HashCode creates the hashcode for memex which can be used to identify itself from other memex. 162 // It generated as the following: 163 // Constant: ConstantFlag+encoded value 164 // DeferredCauset: DeferredCausetFlag+encoded value 165 // ScalarFunction: SFFlag+encoded function name + encoded arg_1 + encoded arg_2 + ... 166 HashCode(sc *stmtctx.StatementContext) []byte 167 } 168 169 // CNFExprs stands for a CNF memex. 170 type CNFExprs []Expression 171 172 // Clone clones itself. 173 func (e CNFExprs) Clone() CNFExprs { 174 cnf := make(CNFExprs, 0, len(e)) 175 for _, expr := range e { 176 cnf = append(cnf, expr.Clone()) 177 } 178 return cnf 179 } 180 181 // Shallow makes a shallow copy of itself. 182 func (e CNFExprs) Shallow() CNFExprs { 183 cnf := make(CNFExprs, 0, len(e)) 184 cnf = append(cnf, e...) 185 return cnf 186 } 187 188 func isDeferredCausetInOperand(c *DeferredCauset) bool { 189 return c.InOperand 190 } 191 192 // IsEQCondFromIn checks if an memex is equal condition converted from `[not] in (subq)`. 193 func IsEQCondFromIn(expr Expression) bool { 194 sf, ok := expr.(*ScalarFunction) 195 if !ok || sf.FuncName.L != ast.EQ { 196 return false 197 } 198 defcaus := make([]*DeferredCauset, 0, 1) 199 defcaus = ExtractDeferredCausetsFromExpressions(defcaus, sf.GetArgs(), isDeferredCausetInOperand) 200 return len(defcaus) > 0 201 } 202 203 // HandleOverflowOnSelection handles Overflow errors when evaluating selection filters. 204 // We should ignore overflow errors when evaluating selection conditions: 205 // INSERT INTO t VALUES ("999999999999999999"); 206 // SELECT * FROM t WHERE v; 207 func HandleOverflowOnSelection(sc *stmtctx.StatementContext, val int64, err error) (int64, error) { 208 if sc.InSelectStmt && err != nil && types.ErrOverflow.Equal(err) { 209 return -1, nil 210 } 211 return val, err 212 } 213 214 // EvalBool evaluates memex list to a boolean value. The first returned value 215 // indicates bool result of the memex list, the second returned value indicates 216 // whether the result of the memex list is null, it can only be true when the 217 // first returned values is false. 218 func EvalBool(ctx stochastikctx.Context, exprList CNFExprs, event chunk.Event) (bool, bool, error) { 219 hasNull := false 220 for _, expr := range exprList { 221 data, err := expr.Eval(event) 222 if err != nil { 223 return false, false, err 224 } 225 if data.IsNull() { 226 // For queries like `select a in (select a from s where t.b = s.b) from t`, 227 // if result of `t.a = s.a` is null, we cannot return immediately until 228 // we have checked if `t.b = s.b` is null or false, because it means 229 // subquery is empty, and we should return false as the result of the whole 230 // exprList in that case, instead of null. 231 if !IsEQCondFromIn(expr) { 232 return false, false, nil 233 } 234 hasNull = true 235 continue 236 } 237 238 i, err := data.ToBool(ctx.GetStochastikVars().StmtCtx) 239 if err != nil { 240 i, err = HandleOverflowOnSelection(ctx.GetStochastikVars().StmtCtx, i, err) 241 if err != nil { 242 return false, false, err 243 244 } 245 } 246 if i == 0 { 247 return false, false, nil 248 } 249 } 250 if hasNull { 251 return false, true, nil 252 } 253 return true, false, nil 254 } 255 256 var ( 257 defaultChunkSize = 1024 258 selPool = sync.Pool{ 259 New: func() interface{} { 260 return make([]int, defaultChunkSize) 261 }, 262 } 263 zeroPool = sync.Pool{ 264 New: func() interface{} { 265 return make([]int8, defaultChunkSize) 266 }, 267 } 268 ) 269 270 func allocSelSlice(n int) []int { 271 if n > defaultChunkSize { 272 return make([]int, n) 273 } 274 return selPool.Get().([]int) 275 } 276 277 func deallocateSelSlice(sel []int) { 278 if cap(sel) <= defaultChunkSize { 279 selPool.Put(sel) 280 } 281 } 282 283 func allocZeroSlice(n int) []int8 { 284 if n > defaultChunkSize { 285 return make([]int8, n) 286 } 287 return zeroPool.Get().([]int8) 288 } 289 290 func deallocateZeroSlice(isZero []int8) { 291 if cap(isZero) <= defaultChunkSize { 292 zeroPool.Put(isZero) 293 } 294 } 295 296 // VecEvalBool does the same thing as EvalBool but it works in a vectorized manner. 297 func VecEvalBool(ctx stochastikctx.Context, exprList CNFExprs, input *chunk.Chunk, selected, nulls []bool) ([]bool, []bool, error) { 298 // If input.Sel() != nil, we will call input.SetSel(nil) to clear the sel slice in input chunk. 299 // After the function finished, then we reset the input.Sel(). 300 // The caller will handle the input.Sel() and selected slices. 301 defer input.SetSel(input.Sel()) 302 input.SetSel(nil) 303 304 n := input.NumEvents() 305 selected = selected[:0] 306 nulls = nulls[:0] 307 for i := 0; i < n; i++ { 308 selected = append(selected, false) 309 nulls = append(nulls, false) 310 } 311 312 sel := allocSelSlice(n) 313 defer deallocateSelSlice(sel) 314 sel = sel[:0] 315 for i := 0; i < n; i++ { 316 sel = append(sel, i) 317 } 318 input.SetSel(sel) 319 320 // In isZero slice, -1 means Null, 0 means zero, 1 means not zero 321 isZero := allocZeroSlice(n) 322 defer deallocateZeroSlice(isZero) 323 for _, expr := range exprList { 324 eType := expr.GetType().EvalType() 325 buf, err := globalDeferredCausetSlabPredictor.get(eType, n) 326 if err != nil { 327 return nil, nil, err 328 } 329 330 if err := EvalExpr(ctx, expr, input, buf); err != nil { 331 return nil, nil, err 332 } 333 334 err = toBool(ctx.GetStochastikVars().StmtCtx, eType, buf, sel, isZero) 335 if err != nil { 336 return nil, nil, err 337 } 338 339 j := 0 340 isEQCondFromIn := IsEQCondFromIn(expr) 341 for i := range sel { 342 if isZero[i] == -1 { 343 if eType != types.ETInt && !isEQCondFromIn { 344 continue 345 } 346 // In this case, we set this event to null and let it pass this filter. 347 // The null flag may be set to false later by other memexs in some cases. 348 nulls[sel[i]] = true 349 sel[j] = sel[i] 350 j++ 351 continue 352 } 353 354 if isZero[i] == 0 { 355 continue 356 } 357 sel[j] = sel[i] // this event passes this filter 358 j++ 359 } 360 sel = sel[:j] 361 input.SetSel(sel) 362 globalDeferredCausetSlabPredictor.put(buf) 363 } 364 365 for _, i := range sel { 366 if !nulls[i] { 367 selected[i] = true 368 } 369 } 370 371 return selected, nulls, nil 372 } 373 374 func toBool(sc *stmtctx.StatementContext, eType types.EvalType, buf *chunk.DeferredCauset, sel []int, isZero []int8) error { 375 switch eType { 376 case types.ETInt: 377 i64s := buf.Int64s() 378 for i := range sel { 379 if buf.IsNull(i) { 380 isZero[i] = -1 381 } else { 382 if i64s[i] == 0 { 383 isZero[i] = 0 384 } else { 385 isZero[i] = 1 386 } 387 } 388 } 389 case types.ETReal: 390 f64s := buf.Float64s() 391 for i := range sel { 392 if buf.IsNull(i) { 393 isZero[i] = -1 394 } else { 395 if f64s[i] == 0 { 396 isZero[i] = 0 397 } else { 398 isZero[i] = 1 399 } 400 } 401 } 402 case types.ETDuration: 403 d64s := buf.GoDurations() 404 for i := range sel { 405 if buf.IsNull(i) { 406 isZero[i] = -1 407 } else { 408 if d64s[i] == 0 { 409 isZero[i] = 0 410 } else { 411 isZero[i] = 1 412 } 413 } 414 } 415 case types.ETDatetime, types.ETTimestamp: 416 t64s := buf.Times() 417 for i := range sel { 418 if buf.IsNull(i) { 419 isZero[i] = -1 420 } else { 421 if t64s[i].IsZero() { 422 isZero[i] = 0 423 } else { 424 isZero[i] = 1 425 } 426 } 427 } 428 case types.ETString: 429 for i := range sel { 430 if buf.IsNull(i) { 431 isZero[i] = -1 432 } else { 433 iVal, err := types.StrToFloat(sc, buf.GetString(i), false) 434 if err != nil { 435 return err 436 } 437 if iVal == 0 { 438 isZero[i] = 0 439 } else { 440 isZero[i] = 1 441 } 442 } 443 } 444 case types.ETDecimal: 445 d64s := buf.Decimals() 446 for i := range sel { 447 if buf.IsNull(i) { 448 isZero[i] = -1 449 } else { 450 if d64s[i].IsZero() { 451 isZero[i] = 0 452 } else { 453 isZero[i] = 1 454 } 455 } 456 } 457 case types.ETJson: 458 for i := range sel { 459 if buf.IsNull(i) { 460 isZero[i] = -1 461 } else { 462 if buf.GetJSON(i).IsZero() { 463 isZero[i] = 0 464 } else { 465 isZero[i] = 1 466 } 467 } 468 } 469 } 470 return nil 471 } 472 473 // EvalExpr evaluates this expr according to its type. 474 // And it selects the method for evaluating memex based on 475 // the environment variables and whether the memex can be vectorized. 476 func EvalExpr(ctx stochastikctx.Context, expr Expression, input *chunk.Chunk, result *chunk.DeferredCauset) (err error) { 477 evalType := expr.GetType().EvalType() 478 if expr.Vectorized() && ctx.GetStochastikVars().EnableVectorizedExpression { 479 switch evalType { 480 case types.ETInt: 481 err = expr.VecEvalInt(ctx, input, result) 482 case types.ETReal: 483 err = expr.VecEvalReal(ctx, input, result) 484 case types.ETDuration: 485 err = expr.VecEvalDuration(ctx, input, result) 486 case types.ETDatetime, types.ETTimestamp: 487 err = expr.VecEvalTime(ctx, input, result) 488 case types.ETString: 489 err = expr.VecEvalString(ctx, input, result) 490 case types.ETJson: 491 err = expr.VecEvalJSON(ctx, input, result) 492 case types.ETDecimal: 493 err = expr.VecEvalDecimal(ctx, input, result) 494 default: 495 err = errors.New(fmt.Sprintf("invalid eval type %v", expr.GetType().EvalType())) 496 } 497 } else { 498 ind, n := 0, input.NumEvents() 499 iter := chunk.NewIterator4Chunk(input) 500 switch evalType { 501 case types.ETInt: 502 result.ResizeInt64(n, false) 503 i64s := result.Int64s() 504 for it := iter.Begin(); it != iter.End(); it = iter.Next() { 505 value, isNull, err := expr.EvalInt(ctx, it) 506 if err != nil { 507 return err 508 } 509 if isNull { 510 result.SetNull(ind, isNull) 511 } else { 512 i64s[ind] = value 513 } 514 ind++ 515 } 516 case types.ETReal: 517 result.ResizeFloat64(n, false) 518 f64s := result.Float64s() 519 for it := iter.Begin(); it != iter.End(); it = iter.Next() { 520 value, isNull, err := expr.EvalReal(ctx, it) 521 if err != nil { 522 return err 523 } 524 if isNull { 525 result.SetNull(ind, isNull) 526 } else { 527 f64s[ind] = value 528 } 529 ind++ 530 } 531 case types.ETDuration: 532 result.ResizeGoDuration(n, false) 533 d64s := result.GoDurations() 534 for it := iter.Begin(); it != iter.End(); it = iter.Next() { 535 value, isNull, err := expr.EvalDuration(ctx, it) 536 if err != nil { 537 return err 538 } 539 if isNull { 540 result.SetNull(ind, isNull) 541 } else { 542 d64s[ind] = value.Duration 543 } 544 ind++ 545 } 546 case types.ETDatetime, types.ETTimestamp: 547 result.ResizeTime(n, false) 548 t64s := result.Times() 549 for it := iter.Begin(); it != iter.End(); it = iter.Next() { 550 value, isNull, err := expr.EvalTime(ctx, it) 551 if err != nil { 552 return err 553 } 554 if isNull { 555 result.SetNull(ind, isNull) 556 } else { 557 t64s[ind] = value 558 } 559 ind++ 560 } 561 case types.ETString: 562 result.ReserveString(n) 563 for it := iter.Begin(); it != iter.End(); it = iter.Next() { 564 value, isNull, err := expr.EvalString(ctx, it) 565 if err != nil { 566 return err 567 } 568 if isNull { 569 result.AppendNull() 570 } else { 571 result.AppendString(value) 572 } 573 } 574 case types.ETJson: 575 result.ReserveJSON(n) 576 for it := iter.Begin(); it != iter.End(); it = iter.Next() { 577 value, isNull, err := expr.EvalJSON(ctx, it) 578 if err != nil { 579 return err 580 } 581 if isNull { 582 result.AppendNull() 583 } else { 584 result.AppendJSON(value) 585 } 586 } 587 case types.ETDecimal: 588 result.ResizeDecimal(n, false) 589 d64s := result.Decimals() 590 for it := iter.Begin(); it != iter.End(); it = iter.Next() { 591 value, isNull, err := expr.EvalDecimal(ctx, it) 592 if err != nil { 593 return err 594 } 595 if isNull { 596 result.SetNull(ind, isNull) 597 } else { 598 d64s[ind] = *value 599 } 600 ind++ 601 } 602 default: 603 err = errors.New(fmt.Sprintf("invalid eval type %v", expr.GetType().EvalType())) 604 } 605 } 606 return 607 } 608 609 // composeConditionWithBinaryOp composes condition with binary operator into a balance deep tree, which benefits a lot for pb causetDecoder/causetCausetEncoder. 610 func composeConditionWithBinaryOp(ctx stochastikctx.Context, conditions []Expression, funcName string) Expression { 611 length := len(conditions) 612 if length == 0 { 613 return nil 614 } 615 if length == 1 { 616 return conditions[0] 617 } 618 expr := NewFunctionInternal(ctx, funcName, 619 types.NewFieldType(allegrosql.TypeTiny), 620 composeConditionWithBinaryOp(ctx, conditions[:length/2], funcName), 621 composeConditionWithBinaryOp(ctx, conditions[length/2:], funcName)) 622 return expr 623 } 624 625 // ComposeCNFCondition composes CNF items into a balance deep CNF tree, which benefits a lot for pb causetDecoder/causetCausetEncoder. 626 func ComposeCNFCondition(ctx stochastikctx.Context, conditions ...Expression) Expression { 627 return composeConditionWithBinaryOp(ctx, conditions, ast.LogicAnd) 628 } 629 630 // ComposeDNFCondition composes DNF items into a balance deep DNF tree. 631 func ComposeDNFCondition(ctx stochastikctx.Context, conditions ...Expression) Expression { 632 return composeConditionWithBinaryOp(ctx, conditions, ast.LogicOr) 633 } 634 635 func extractBinaryOpItems(conditions *ScalarFunction, funcName string) []Expression { 636 var ret []Expression 637 for _, arg := range conditions.GetArgs() { 638 if sf, ok := arg.(*ScalarFunction); ok && sf.FuncName.L == funcName { 639 ret = append(ret, extractBinaryOpItems(sf, funcName)...) 640 } else { 641 ret = append(ret, arg) 642 } 643 } 644 return ret 645 } 646 647 // FlattenDNFConditions extracts DNF memex's leaf item. 648 // e.g. or(or(a=1, a=2), or(a=3, a=4)), we'll get [a=1, a=2, a=3, a=4]. 649 func FlattenDNFConditions(DNFCondition *ScalarFunction) []Expression { 650 return extractBinaryOpItems(DNFCondition, ast.LogicOr) 651 } 652 653 // FlattenCNFConditions extracts CNF memex's leaf item. 654 // e.g. and(and(a>1, a>2), and(a>3, a>4)), we'll get [a>1, a>2, a>3, a>4]. 655 func FlattenCNFConditions(CNFCondition *ScalarFunction) []Expression { 656 return extractBinaryOpItems(CNFCondition, ast.LogicAnd) 657 } 658 659 // Assignment represents a set assignment in UFIDelate, such as 660 // UFIDelate t set c1 = hex(12), c2 = c3 where c2 = 1 661 type Assignment struct { 662 DefCaus *DeferredCauset 663 // DefCausName indicates its original defCausumn name in causet schemaReplicant. It's used for outputting helping message when executing meets some errors. 664 DefCausName perceptron.CIStr 665 Expr Expression 666 } 667 668 // VarAssignment represents a variable assignment in Set, such as set global a = 1. 669 type VarAssignment struct { 670 Name string 671 Expr Expression 672 IsDefault bool 673 IsGlobal bool 674 IsSystem bool 675 ExtendValue *Constant 676 } 677 678 // splitNormalFormItems split CNF(conjunctive normal form) like "a and b and c", or DNF(disjunctive normal form) like "a or b or c" 679 func splitNormalFormItems(onExpr Expression, funcName string) []Expression { 680 switch v := onExpr.(type) { 681 case *ScalarFunction: 682 if v.FuncName.L == funcName { 683 var ret []Expression 684 for _, arg := range v.GetArgs() { 685 ret = append(ret, splitNormalFormItems(arg, funcName)...) 686 } 687 return ret 688 } 689 } 690 return []Expression{onExpr} 691 } 692 693 // SplitCNFItems splits CNF items. 694 // CNF means conjunctive normal form, e.g. "a and b and c". 695 func SplitCNFItems(onExpr Expression) []Expression { 696 return splitNormalFormItems(onExpr, ast.LogicAnd) 697 } 698 699 // SplitDNFItems splits DNF items. 700 // DNF means disjunctive normal form, e.g. "a or b or c". 701 func SplitDNFItems(onExpr Expression) []Expression { 702 return splitNormalFormItems(onExpr, ast.LogicOr) 703 } 704 705 // EvaluateExprWithNull sets defCausumns in schemaReplicant as null and calculate the final result of the scalar function. 706 // If the Expression is a non-constant value, it means the result is unknown. 707 func EvaluateExprWithNull(ctx stochastikctx.Context, schemaReplicant *Schema, expr Expression) Expression { 708 switch x := expr.(type) { 709 case *ScalarFunction: 710 args := make([]Expression, len(x.GetArgs())) 711 for i, arg := range x.GetArgs() { 712 args[i] = EvaluateExprWithNull(ctx, schemaReplicant, arg) 713 } 714 return NewFunctionInternal(ctx, x.FuncName.L, x.RetType, args...) 715 case *DeferredCauset: 716 if !schemaReplicant.Contains(x) { 717 return x 718 } 719 return &Constant{Value: types.Causet{}, RetType: types.NewFieldType(allegrosql.TypeNull)} 720 case *Constant: 721 if x.DeferredExpr != nil { 722 return FoldConstant(x) 723 } 724 } 725 return expr 726 } 727 728 // BlockInfo2SchemaAndNames converts the BlockInfo to the schemaReplicant and name slice. 729 func BlockInfo2SchemaAndNames(ctx stochastikctx.Context, dbName perceptron.CIStr, tbl *perceptron.BlockInfo) (*Schema, []*types.FieldName, error) { 730 defcaus, names, err := DeferredCausetInfos2DeferredCausetsAndNames(ctx, dbName, tbl.Name, tbl.DefCauss(), tbl) 731 if err != nil { 732 return nil, nil, err 733 } 734 keys := make([]KeyInfo, 0, len(tbl.Indices)+1) 735 for _, idx := range tbl.Indices { 736 if !idx.Unique || idx.State != perceptron.StatePublic { 737 continue 738 } 739 ok := true 740 newKey := make([]*DeferredCauset, 0, len(idx.DeferredCausets)) 741 for _, idxDefCaus := range idx.DeferredCausets { 742 find := false 743 for i, defCaus := range tbl.DeferredCausets { 744 if idxDefCaus.Name.L == defCaus.Name.L { 745 if !allegrosql.HasNotNullFlag(defCaus.Flag) { 746 break 747 } 748 newKey = append(newKey, defcaus[i]) 749 find = true 750 break 751 } 752 } 753 if !find { 754 ok = false 755 break 756 } 757 } 758 if ok { 759 keys = append(keys, newKey) 760 } 761 } 762 if tbl.PKIsHandle { 763 for i, defCaus := range tbl.DeferredCausets { 764 if allegrosql.HasPriKeyFlag(defCaus.Flag) { 765 keys = append(keys, KeyInfo{defcaus[i]}) 766 break 767 } 768 } 769 } 770 schemaReplicant := NewSchema(defcaus...) 771 schemaReplicant.SetUniqueKeys(keys) 772 return schemaReplicant, names, nil 773 } 774 775 // DeferredCausetInfos2DeferredCausetsAndNames converts the DeferredCausetInfo to the *DeferredCauset and NameSlice. 776 func DeferredCausetInfos2DeferredCausetsAndNames(ctx stochastikctx.Context, dbName, tblName perceptron.CIStr, defCausInfos []*perceptron.DeferredCausetInfo, tblInfo *perceptron.BlockInfo) ([]*DeferredCauset, types.NameSlice, error) { 777 defCausumns := make([]*DeferredCauset, 0, len(defCausInfos)) 778 names := make([]*types.FieldName, 0, len(defCausInfos)) 779 for i, defCaus := range defCausInfos { 780 names = append(names, &types.FieldName{ 781 OrigTblName: tblName, 782 OrigDefCausName: defCaus.Name, 783 DBName: dbName, 784 TblName: tblName, 785 DefCausName: defCaus.Name, 786 }) 787 newDefCaus := &DeferredCauset{ 788 RetType: &defCaus.FieldType, 789 ID: defCaus.ID, 790 UniqueID: ctx.GetStochastikVars().AllocCausetDeferredCausetID(), 791 Index: defCaus.Offset, 792 OrigName: names[i].String(), 793 IsHidden: defCaus.Hidden, 794 } 795 defCausumns = append(defCausumns, newDefCaus) 796 } 797 // Resolve virtual generated defCausumn. 798 mockSchema := NewSchema(defCausumns...) 799 // Ignore redundant warning here. 800 save := ctx.GetStochastikVars().StmtCtx.IgnoreTruncate 801 defer func() { 802 ctx.GetStochastikVars().StmtCtx.IgnoreTruncate = save 803 }() 804 ctx.GetStochastikVars().StmtCtx.IgnoreTruncate = true 805 for i, defCaus := range defCausInfos { 806 if defCaus.IsGenerated() && !defCaus.GeneratedStored { 807 expr, err := generatedexpr.ParseExpression(defCaus.GeneratedExprString) 808 if err != nil { 809 return nil, nil, errors.Trace(err) 810 } 811 expr, err = generatedexpr.SimpleResolveName(expr, tblInfo) 812 if err != nil { 813 return nil, nil, errors.Trace(err) 814 } 815 e, err := RewriteAstExpr(ctx, expr, mockSchema, names) 816 if err != nil { 817 return nil, nil, errors.Trace(err) 818 } 819 if e != nil { 820 defCausumns[i].VirtualExpr = e.Clone() 821 } 822 defCausumns[i].VirtualExpr, err = defCausumns[i].VirtualExpr.ResolveIndices(mockSchema) 823 if err != nil { 824 return nil, nil, errors.Trace(err) 825 } 826 } 827 } 828 return defCausumns, names, nil 829 } 830 831 // NewValuesFunc creates a new values function. 832 func NewValuesFunc(ctx stochastikctx.Context, offset int, retTp *types.FieldType) *ScalarFunction { 833 fc := &valuesFunctionClass{baseFunctionClass{ast.Values, 0, 0}, offset, retTp} 834 bt, err := fc.getFunction(ctx, nil) 835 terror.Log(err) 836 return &ScalarFunction{ 837 FuncName: perceptron.NewCIStr(ast.Values), 838 RetType: retTp, 839 Function: bt, 840 } 841 } 842 843 // IsBinaryLiteral checks whether an memex is a binary literal 844 func IsBinaryLiteral(expr Expression) bool { 845 con, ok := expr.(*Constant) 846 return ok && con.Value.HoTT() == types.HoTTBinaryLiteral 847 } 848 849 func canFuncBePushed(sf *ScalarFunction, storeType ekv.StoreType) bool { 850 // Use the failpoint to control whether to push down an memex in the integration test. 851 // Push down all memex if the `failpoint memex` is `all`, otherwise, check 852 // whether scalar function's name is contained in the enabled memex list (e.g.`ne,eq,lt`). 853 // If neither of the above is true, switch to original logic. 854 failpoint.Inject("PushDownTestSwitcher", func(val failpoint.Value) { 855 enabled := val.(string) 856 if enabled == "all" { 857 failpoint.Return(true) 858 } 859 exprs := strings.Split(enabled, ",") 860 for _, expr := range exprs { 861 if strings.ToLower(strings.TrimSpace(expr)) == sf.FuncName.L { 862 failpoint.Return(true) 863 } 864 } 865 }) 866 867 ret := false 868 switch sf.FuncName.L { 869 case 870 // op functions. 871 ast.LogicAnd, 872 ast.LogicOr, 873 ast.LogicXor, 874 ast.UnaryNot, 875 ast.And, 876 ast.Or, 877 ast.Xor, 878 ast.BitNeg, 879 ast.LeftShift, 880 ast.RightShift, 881 ast.UnaryMinus, 882 883 // compare functions. 884 ast.LT, 885 ast.LE, 886 ast.EQ, 887 ast.NE, 888 ast.GE, 889 ast.GT, 890 ast.NullEQ, 891 ast.In, 892 ast.IsNull, 893 ast.Like, 894 ast.IsTruthWithoutNull, 895 ast.IsTruthWithNull, 896 ast.IsFalsity, 897 898 // arithmetical functions. 899 ast.Plus, 900 ast.Minus, 901 ast.Mul, 902 ast.Div, 903 ast.Abs, 904 905 // math functions. 906 ast.Ceil, 907 ast.Ceiling, 908 ast.Floor, 909 ast.Sqrt, 910 ast.Sign, 911 ast.Ln, 912 ast.Log, 913 ast.Log2, 914 ast.Log10, 915 ast.Exp, 916 ast.Pow, 917 // Rust use the llvm math functions, which have different precision with Golang/MyALLEGROSQL(cmath) 918 // open the following switchers if we implement them in interlock via `cmath` 919 // ast.Sin, 920 // ast.Asin, 921 // ast.Cos, 922 // ast.Acos, 923 // ast.Tan, 924 // ast.Atan, 925 // ast.Atan2, 926 // ast.Cot, 927 ast.Radians, 928 ast.Degrees, 929 ast.Conv, 930 ast.CRC32, 931 932 // control flow functions. 933 ast.Case, 934 ast.If, 935 ast.Ifnull, 936 ast.Coalesce, 937 938 // string functions. 939 ast.Length, 940 ast.BitLength, 941 ast.Concat, 942 ast.ConcatWS, 943 // ast.Locate, 944 ast.Replace, 945 ast.ASCII, 946 ast.Hex, 947 ast.Reverse, 948 ast.LTrim, 949 ast.RTrim, 950 // ast.Left, 951 ast.Strcmp, 952 ast.Space, 953 ast.Elt, 954 ast.Field, 955 956 // json functions. 957 ast.JSONType, 958 ast.JSONExtract, 959 // FIXME: JSONUnquote is incompatible with Coprocessor 960 // ast.JSONUnquote, 961 ast.JSONObject, 962 ast.JSONArray, 963 ast.JSONMerge, 964 ast.JSONSet, 965 ast.JSONInsert, 966 // ast.JSONReplace, 967 ast.JSONRemove, 968 ast.JSONLength, 969 970 // date functions. 971 ast.DateFormat, 972 ast.FromDays, 973 // ast.ToDays, 974 ast.DayOfYear, 975 ast.DayOfMonth, 976 ast.Year, 977 ast.Month, 978 // FIXME: the interlock cannot keep the same behavior with MilevaDB in current compute framework 979 // ast.Hour, 980 // ast.Minute, 981 // ast.Second, 982 // ast.MicroSecond, 983 // ast.DayName, 984 ast.PeriodAdd, 985 ast.PeriodDiff, 986 ast.TimestamFIDeliff, 987 ast.DateAdd, 988 ast.FromUnixTime, 989 990 // encryption functions. 991 ast.MD5, 992 ast.SHA1, 993 ast.UncompressedLength, 994 995 ast.Cast, 996 997 // misc functions. 998 ast.InetNtoa, 999 ast.InetAton, 1000 ast.Inet6Ntoa, 1001 ast.Inet6Aton, 1002 ast.IsIPv4, 1003 ast.IsIPv4Compat, 1004 ast.IsIPv4Mapped, 1005 ast.IsIPv6: 1006 ret = true 1007 1008 // A special case: Only push down Round by signature 1009 case ast.Round: 1010 switch sf.Function.PbCode() { 1011 case 1012 fidelpb.ScalarFuncSig_RoundReal, 1013 fidelpb.ScalarFuncSig_RoundInt, 1014 fidelpb.ScalarFuncSig_RoundDec: 1015 ret = true 1016 } 1017 case 1018 ast.Substring, 1019 ast.Substr: 1020 switch sf.Function.PbCode() { 1021 case 1022 fidelpb.ScalarFuncSig_Substring2ArgsUTF8, 1023 fidelpb.ScalarFuncSig_Substring3ArgsUTF8: 1024 ret = true 1025 } 1026 case ast.Rand: 1027 switch sf.Function.PbCode() { 1028 case 1029 fidelpb.ScalarFuncSig_RandWithSeedFirstGen: 1030 ret = true 1031 } 1032 } 1033 if ret { 1034 switch storeType { 1035 case ekv.TiFlash: 1036 ret = scalarExprSupportedByFlash(sf) 1037 case ekv.EinsteinDB: 1038 ret = scalarExprSupportedByEinsteinDB(sf) 1039 case ekv.MilevaDB: 1040 ret = scalarExprSupportedByMilevaDB(sf) 1041 } 1042 } 1043 if ret { 1044 ret = IsPushDownEnabled(sf.FuncName.L, storeType) 1045 } 1046 return ret 1047 } 1048 1049 func storeTypeMask(storeType ekv.StoreType) uint32 { 1050 if storeType == ekv.UnSpecified { 1051 return 1<<ekv.EinsteinDB | 1<<ekv.TiFlash | 1<<ekv.MilevaDB 1052 } 1053 return 1 << storeType 1054 } 1055 1056 // IsPushDownEnabled returns true if the input expr is not in the expr_pushdown_blacklist 1057 func IsPushDownEnabled(name string, storeType ekv.StoreType) bool { 1058 value, exists := DefaultExprPushDownBlacklist.Load().(map[string]uint32)[name] 1059 if exists { 1060 mask := storeTypeMask(storeType) 1061 return !(value&mask == mask) 1062 } 1063 1064 if storeType != ekv.TiFlash && name == ast.AggFuncApproxCountDistinct { 1065 // Can not push down approx_count_distinct to other causetstore except tiflash by now. 1066 return false 1067 } 1068 1069 return true 1070 } 1071 1072 // DefaultExprPushDownBlacklist indicates the memexs which can not be pushed down to EinsteinDB. 1073 var DefaultExprPushDownBlacklist *atomic.Value 1074 1075 func init() { 1076 DefaultExprPushDownBlacklist = new(atomic.Value) 1077 DefaultExprPushDownBlacklist.CausetStore(make(map[string]uint32)) 1078 } 1079 1080 func canScalarFuncPushDown(scalarFunc *ScalarFunction, pc PbConverter, storeType ekv.StoreType) bool { 1081 pbCode := scalarFunc.Function.PbCode() 1082 if pbCode <= fidelpb.ScalarFuncSig_Unspecified { 1083 failpoint.Inject("PanicIfPbCodeUnspecified", func() { 1084 panic(errors.Errorf("unspecified PbCode: %T", scalarFunc.Function)) 1085 }) 1086 return false 1087 } 1088 1089 // Check whether this function can be pushed. 1090 if !canFuncBePushed(scalarFunc, storeType) { 1091 return false 1092 } 1093 1094 // Check whether all of its parameters can be pushed. 1095 for _, arg := range scalarFunc.GetArgs() { 1096 if !canExprPushDown(arg, pc, storeType) { 1097 return false 1098 } 1099 } 1100 1101 if spacetimedata := scalarFunc.Function.spacetimedata(); spacetimedata != nil { 1102 var err error 1103 _, err = proto.Marshal(spacetimedata) 1104 if err != nil { 1105 logutil.BgLogger().Error("encode spacetimedata", zap.Any("spacetimedata", spacetimedata), zap.Error(err)) 1106 return false 1107 } 1108 } 1109 return true 1110 } 1111 1112 func canExprPushDown(expr Expression, pc PbConverter, storeType ekv.StoreType) bool { 1113 if storeType == ekv.TiFlash && expr.GetType().Tp == allegrosql.TypeDuration { 1114 return false 1115 } 1116 switch x := expr.(type) { 1117 case *CorrelatedDeferredCauset: 1118 return pc.conOrCorDefCausToPBExpr(expr) != nil && pc.defCausumnToPBExpr(&x.DeferredCauset) != nil 1119 case *Constant: 1120 return pc.conOrCorDefCausToPBExpr(expr) != nil 1121 case *DeferredCauset: 1122 return pc.defCausumnToPBExpr(x) != nil 1123 case *ScalarFunction: 1124 return canScalarFuncPushDown(x, pc, storeType) 1125 } 1126 return false 1127 } 1128 1129 // PushDownExprs split the input exprs into pushed and remained, pushed include all the exprs that can be pushed down 1130 func PushDownExprs(sc *stmtctx.StatementContext, exprs []Expression, client ekv.Client, storeType ekv.StoreType) (pushed []Expression, remained []Expression) { 1131 pc := PbConverter{sc: sc, client: client} 1132 for _, expr := range exprs { 1133 if canExprPushDown(expr, pc, storeType) { 1134 pushed = append(pushed, expr) 1135 } else { 1136 remained = append(remained, expr) 1137 } 1138 } 1139 return 1140 } 1141 1142 // CanExprsPushDown return true if all the expr in exprs can be pushed down 1143 func CanExprsPushDown(sc *stmtctx.StatementContext, exprs []Expression, client ekv.Client, storeType ekv.StoreType) bool { 1144 _, remained := PushDownExprs(sc, exprs, client, storeType) 1145 return len(remained) == 0 1146 } 1147 1148 func scalarExprSupportedByEinsteinDB(function *ScalarFunction) bool { 1149 switch function.FuncName.L { 1150 case ast.Substr, ast.Substring, ast.DateAdd, ast.TimestamFIDeliff, 1151 ast.FromUnixTime: 1152 return false 1153 default: 1154 return true 1155 } 1156 } 1157 1158 func scalarExprSupportedByMilevaDB(function *ScalarFunction) bool { 1159 switch function.FuncName.L { 1160 case ast.Substr, ast.Substring, ast.DateAdd, ast.TimestamFIDeliff, 1161 ast.FromUnixTime: 1162 return false 1163 default: 1164 return true 1165 } 1166 } 1167 1168 func scalarExprSupportedByFlash(function *ScalarFunction) bool { 1169 switch function.FuncName.L { 1170 case ast.Plus, ast.Minus, ast.Div, ast.Mul, ast.GE, ast.LE, 1171 ast.EQ, ast.NE, ast.LT, ast.GT, ast.Ifnull, ast.IsNull, 1172 ast.Or, ast.In, ast.Mod, ast.And, ast.LogicOr, ast.LogicAnd, 1173 ast.Like, ast.UnaryNot, ast.Case, ast.Month, ast.Substr, 1174 ast.Substring, ast.TimestamFIDeliff, ast.DateFormat, ast.FromUnixTime, 1175 ast.JSONLength, ast.If, ast.BitNeg, ast.Xor: 1176 return true 1177 case ast.Cast: 1178 switch function.Function.PbCode() { 1179 case fidelpb.ScalarFuncSig_CastIntAsDecimal: 1180 return true 1181 default: 1182 return false 1183 } 1184 case ast.DateAdd: 1185 switch function.Function.PbCode() { 1186 case fidelpb.ScalarFuncSig_AddDateDatetimeInt, fidelpb.ScalarFuncSig_AddDateStringInt: 1187 return true 1188 default: 1189 return false 1190 } 1191 case ast.Round: 1192 switch function.Function.PbCode() { 1193 case fidelpb.ScalarFuncSig_RoundInt, fidelpb.ScalarFuncSig_RoundReal, 1194 fidelpb.ScalarFuncSig_RoundDec: 1195 return true 1196 default: 1197 return false 1198 } 1199 default: 1200 return false 1201 } 1202 } 1203 1204 // wrapWithIsTrue wraps `arg` with istrue function if the return type of expr is not 1205 // type int, otherwise, returns `arg` directly. 1206 // The `keepNull` controls what the istrue function will return when `arg` is null: 1207 // 1. keepNull is true and arg is null, the istrue function returns null. 1208 // 2. keepNull is false and arg is null, the istrue function returns 0. 1209 // The `wrapForInt` indicates whether we need to wrapIsTrue for non-logical Expression with int type. 1210 // TODO: remove this function. ScalarFunction should be newed in one place. 1211 func wrapWithIsTrue(ctx stochastikctx.Context, keepNull bool, arg Expression, wrapForInt bool) (Expression, error) { 1212 if arg.GetType().EvalType() == types.ETInt { 1213 if !wrapForInt { 1214 return arg, nil 1215 } 1216 if child, ok := arg.(*ScalarFunction); ok { 1217 if _, isLogicalOp := logicalOps[child.FuncName.L]; isLogicalOp { 1218 return arg, nil 1219 } 1220 } 1221 } 1222 var fc *isTrueOrFalseFunctionClass 1223 if keepNull { 1224 fc = &isTrueOrFalseFunctionClass{baseFunctionClass{ast.IsTruthWithNull, 1, 1}, opcode.IsTruth, keepNull} 1225 } else { 1226 fc = &isTrueOrFalseFunctionClass{baseFunctionClass{ast.IsTruthWithoutNull, 1, 1}, opcode.IsTruth, keepNull} 1227 } 1228 f, err := fc.getFunction(ctx, []Expression{arg}) 1229 if err != nil { 1230 return nil, err 1231 } 1232 sf := &ScalarFunction{ 1233 FuncName: perceptron.NewCIStr(ast.IsTruthWithoutNull), 1234 Function: f, 1235 RetType: f.getRetTp(), 1236 } 1237 if keepNull { 1238 sf.FuncName = perceptron.NewCIStr(ast.IsTruthWithNull) 1239 } 1240 return FoldConstant(sf), nil 1241 }