github.com/whtcorpsinc/milevadb-prod@v0.0.0-20211104133533-f57f4be3b597/dbs/memristed/memex/builtin_other.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 "strings" 18 "time" 19 20 "github.com/whtcorpsinc/errors" 21 "github.com/whtcorpsinc/BerolinaSQL/allegrosql" 22 "github.com/whtcorpsinc/milevadb/stochastikctx" 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/defCauslate" 27 "github.com/whtcorpsinc/milevadb/soliton/set" 28 "github.com/whtcorpsinc/milevadb/soliton/stringutil" 29 "github.com/whtcorpsinc/fidelpb/go-fidelpb" 30 ) 31 32 var ( 33 _ functionClass = &inFunctionClass{} 34 _ functionClass = &rowFunctionClass{} 35 _ functionClass = &setVarFunctionClass{} 36 _ functionClass = &getVarFunctionClass{} 37 _ functionClass = &lockFunctionClass{} 38 _ functionClass = &releaseLockFunctionClass{} 39 _ functionClass = &valuesFunctionClass{} 40 _ functionClass = &bitCountFunctionClass{} 41 _ functionClass = &getParamFunctionClass{} 42 ) 43 44 var ( 45 _ builtinFunc = &builtinSleepSig{} 46 _ builtinFunc = &builtinInIntSig{} 47 _ builtinFunc = &builtinInStringSig{} 48 _ builtinFunc = &builtinInDecimalSig{} 49 _ builtinFunc = &builtinInRealSig{} 50 _ builtinFunc = &builtinInTimeSig{} 51 _ builtinFunc = &builtinInDurationSig{} 52 _ builtinFunc = &builtinInJSONSig{} 53 _ builtinFunc = &builtinEventSig{} 54 _ builtinFunc = &builtinSetVarSig{} 55 _ builtinFunc = &builtinGetVarSig{} 56 _ builtinFunc = &builtinLockSig{} 57 _ builtinFunc = &builtinReleaseLockSig{} 58 _ builtinFunc = &builtinValuesIntSig{} 59 _ builtinFunc = &builtinValuesRealSig{} 60 _ builtinFunc = &builtinValuesDecimalSig{} 61 _ builtinFunc = &builtinValuesStringSig{} 62 _ builtinFunc = &builtinValuesTimeSig{} 63 _ builtinFunc = &builtinValuesDurationSig{} 64 _ builtinFunc = &builtinValuesJSONSig{} 65 _ builtinFunc = &builtinBitCountSig{} 66 _ builtinFunc = &builtinGetParamStringSig{} 67 ) 68 69 type inFunctionClass struct { 70 baseFunctionClass 71 } 72 73 func (c *inFunctionClass) getFunction(ctx stochastikctx.Context, args []Expression) (sig builtinFunc, err error) { 74 if err := c.verifyArgs(args); err != nil { 75 return nil, err 76 } 77 argTps := make([]types.EvalType, len(args)) 78 for i := range args { 79 argTps[i] = args[0].GetType().EvalType() 80 } 81 bf, err := newBaseBuiltinFuncWithTp(ctx, c.funcName, args, types.ETInt, argTps...) 82 if err != nil { 83 return nil, err 84 } 85 bf.tp.Flen = 1 86 switch args[0].GetType().EvalType() { 87 case types.ETInt: 88 inInt := builtinInIntSig{baseInSig: baseInSig{baseBuiltinFunc: bf}} 89 err := inInt.buildHashMapForConstArgs(ctx) 90 if err != nil { 91 return &inInt, err 92 } 93 sig = &inInt 94 sig.setPbCode(fidelpb.ScalarFuncSig_InInt) 95 case types.ETString: 96 inStr := builtinInStringSig{baseInSig: baseInSig{baseBuiltinFunc: bf}} 97 err := inStr.buildHashMapForConstArgs(ctx) 98 if err != nil { 99 return &inStr, err 100 } 101 sig = &inStr 102 sig.setPbCode(fidelpb.ScalarFuncSig_InString) 103 case types.ETReal: 104 inReal := builtinInRealSig{baseInSig: baseInSig{baseBuiltinFunc: bf}} 105 err := inReal.buildHashMapForConstArgs(ctx) 106 if err != nil { 107 return &inReal, err 108 } 109 sig = &inReal 110 sig.setPbCode(fidelpb.ScalarFuncSig_InReal) 111 case types.ETDecimal: 112 inDecimal := builtinInDecimalSig{baseInSig: baseInSig{baseBuiltinFunc: bf}} 113 err := inDecimal.buildHashMapForConstArgs(ctx) 114 if err != nil { 115 return &inDecimal, err 116 } 117 sig = &inDecimal 118 sig.setPbCode(fidelpb.ScalarFuncSig_InDecimal) 119 case types.ETDatetime, types.ETTimestamp: 120 inTime := builtinInTimeSig{baseInSig: baseInSig{baseBuiltinFunc: bf}} 121 err := inTime.buildHashMapForConstArgs(ctx) 122 if err != nil { 123 return &inTime, err 124 } 125 sig = &inTime 126 sig.setPbCode(fidelpb.ScalarFuncSig_InTime) 127 case types.ETDuration: 128 inDuration := builtinInDurationSig{baseInSig: baseInSig{baseBuiltinFunc: bf}} 129 err := inDuration.buildHashMapForConstArgs(ctx) 130 if err != nil { 131 return &inDuration, err 132 } 133 sig = &inDuration 134 sig.setPbCode(fidelpb.ScalarFuncSig_InDuration) 135 case types.ETJson: 136 sig = &builtinInJSONSig{baseBuiltinFunc: bf} 137 sig.setPbCode(fidelpb.ScalarFuncSig_InJson) 138 } 139 return sig, nil 140 } 141 142 type baseInSig struct { 143 baseBuiltinFunc 144 nonConstArgs []Expression 145 hasNull bool 146 } 147 148 // builtinInIntSig see https://dev.allegrosql.com/doc/refman/5.7/en/comparison-operators.html#function_in 149 type builtinInIntSig struct { 150 baseInSig 151 // the bool value in the map is used to identify whether the constant stored in key is signed or unsigned 152 hashSet map[int64]bool 153 } 154 155 func (b *builtinInIntSig) buildHashMapForConstArgs(ctx stochastikctx.Context) error { 156 b.nonConstArgs = []Expression{b.args[0]} 157 b.hashSet = make(map[int64]bool, len(b.args)-1) 158 for i := 1; i < len(b.args); i++ { 159 if b.args[i].ConstItem(b.ctx.GetStochastikVars().StmtCtx) { 160 val, isNull, err := b.args[i].EvalInt(ctx, chunk.Event{}) 161 if err != nil { 162 return err 163 } 164 if isNull { 165 b.hasNull = true 166 continue 167 } 168 b.hashSet[val] = allegrosql.HasUnsignedFlag(b.args[i].GetType().Flag) 169 } else { 170 b.nonConstArgs = append(b.nonConstArgs, b.args[i]) 171 } 172 } 173 return nil 174 } 175 176 func (b *builtinInIntSig) Clone() builtinFunc { 177 newSig := &builtinInIntSig{} 178 newSig.cloneFrom(&b.baseBuiltinFunc) 179 newSig.nonConstArgs = make([]Expression, 0, len(b.nonConstArgs)) 180 for _, arg := range b.nonConstArgs { 181 newSig.nonConstArgs = append(newSig.nonConstArgs, arg.Clone()) 182 } 183 newSig.hashSet = b.hashSet 184 newSig.hasNull = b.hasNull 185 return newSig 186 } 187 188 func (b *builtinInIntSig) evalInt(event chunk.Event) (int64, bool, error) { 189 arg0, isNull0, err := b.args[0].EvalInt(b.ctx, event) 190 if isNull0 || err != nil { 191 return 0, isNull0, err 192 } 193 isUnsigned0 := allegrosql.HasUnsignedFlag(b.args[0].GetType().Flag) 194 195 args := b.args 196 if len(b.hashSet) != 0 { 197 args = b.nonConstArgs 198 if isUnsigned, ok := b.hashSet[arg0]; ok { 199 if (isUnsigned0 && isUnsigned) || (!isUnsigned0 && !isUnsigned) { 200 return 1, false, nil 201 } 202 if arg0 >= 0 { 203 return 1, false, nil 204 } 205 } 206 } 207 208 hasNull := b.hasNull 209 for _, arg := range args[1:] { 210 evaledArg, isNull, err := arg.EvalInt(b.ctx, event) 211 if err != nil { 212 return 0, true, err 213 } 214 if isNull { 215 hasNull = true 216 continue 217 } 218 isUnsigned := allegrosql.HasUnsignedFlag(arg.GetType().Flag) 219 if isUnsigned0 && isUnsigned { 220 if evaledArg == arg0 { 221 return 1, false, nil 222 } 223 } else if !isUnsigned0 && !isUnsigned { 224 if evaledArg == arg0 { 225 return 1, false, nil 226 } 227 } else if !isUnsigned0 && isUnsigned { 228 if arg0 >= 0 && evaledArg == arg0 { 229 return 1, false, nil 230 } 231 } else { 232 if evaledArg >= 0 && evaledArg == arg0 { 233 return 1, false, nil 234 } 235 } 236 } 237 return 0, hasNull, nil 238 } 239 240 // builtinInStringSig see https://dev.allegrosql.com/doc/refman/5.7/en/comparison-operators.html#function_in 241 type builtinInStringSig struct { 242 baseInSig 243 hashSet set.StringSet 244 } 245 246 func (b *builtinInStringSig) buildHashMapForConstArgs(ctx stochastikctx.Context) error { 247 b.nonConstArgs = []Expression{b.args[0]} 248 b.hashSet = set.NewStringSet() 249 defCauslator := defCauslate.GetDefCauslator(b.defCauslation) 250 for i := 1; i < len(b.args); i++ { 251 if b.args[i].ConstItem(b.ctx.GetStochastikVars().StmtCtx) { 252 val, isNull, err := b.args[i].EvalString(ctx, chunk.Event{}) 253 if err != nil { 254 return err 255 } 256 if isNull { 257 b.hasNull = true 258 continue 259 } 260 b.hashSet.Insert(string(defCauslator.Key(val))) // should do memory copy here 261 } else { 262 b.nonConstArgs = append(b.nonConstArgs, b.args[i]) 263 } 264 } 265 266 return nil 267 } 268 269 func (b *builtinInStringSig) Clone() builtinFunc { 270 newSig := &builtinInStringSig{} 271 newSig.cloneFrom(&b.baseBuiltinFunc) 272 newSig.nonConstArgs = make([]Expression, 0, len(b.nonConstArgs)) 273 for _, arg := range b.nonConstArgs { 274 newSig.nonConstArgs = append(newSig.nonConstArgs, arg.Clone()) 275 } 276 newSig.hashSet = b.hashSet 277 newSig.hasNull = b.hasNull 278 return newSig 279 } 280 281 func (b *builtinInStringSig) evalInt(event chunk.Event) (int64, bool, error) { 282 arg0, isNull0, err := b.args[0].EvalString(b.ctx, event) 283 if isNull0 || err != nil { 284 return 0, isNull0, err 285 } 286 287 args := b.args 288 defCauslator := defCauslate.GetDefCauslator(b.defCauslation) 289 if len(b.hashSet) != 0 { 290 args = b.nonConstArgs 291 if b.hashSet.Exist(string(defCauslator.Key(arg0))) { 292 return 1, false, nil 293 } 294 } 295 296 hasNull := b.hasNull 297 for _, arg := range args[1:] { 298 evaledArg, isNull, err := arg.EvalString(b.ctx, event) 299 if err != nil { 300 return 0, true, err 301 } 302 if isNull { 303 hasNull = true 304 continue 305 } 306 if types.CompareString(arg0, evaledArg, b.defCauslation) == 0 { 307 return 1, false, nil 308 } 309 } 310 return 0, hasNull, nil 311 } 312 313 // builtinInRealSig see https://dev.allegrosql.com/doc/refman/5.7/en/comparison-operators.html#function_in 314 type builtinInRealSig struct { 315 baseInSig 316 hashSet set.Float64Set 317 } 318 319 func (b *builtinInRealSig) buildHashMapForConstArgs(ctx stochastikctx.Context) error { 320 b.nonConstArgs = []Expression{b.args[0]} 321 b.hashSet = set.NewFloat64Set() 322 for i := 1; i < len(b.args); i++ { 323 if b.args[i].ConstItem(b.ctx.GetStochastikVars().StmtCtx) { 324 val, isNull, err := b.args[i].EvalReal(ctx, chunk.Event{}) 325 if err != nil { 326 return err 327 } 328 if isNull { 329 b.hasNull = true 330 continue 331 } 332 b.hashSet.Insert(val) 333 } else { 334 b.nonConstArgs = append(b.nonConstArgs, b.args[i]) 335 } 336 } 337 338 return nil 339 } 340 341 func (b *builtinInRealSig) Clone() builtinFunc { 342 newSig := &builtinInRealSig{} 343 newSig.cloneFrom(&b.baseBuiltinFunc) 344 newSig.nonConstArgs = make([]Expression, 0, len(b.nonConstArgs)) 345 for _, arg := range b.nonConstArgs { 346 newSig.nonConstArgs = append(newSig.nonConstArgs, arg.Clone()) 347 } 348 newSig.hashSet = b.hashSet 349 newSig.hasNull = b.hasNull 350 return newSig 351 } 352 353 func (b *builtinInRealSig) evalInt(event chunk.Event) (int64, bool, error) { 354 arg0, isNull0, err := b.args[0].EvalReal(b.ctx, event) 355 if isNull0 || err != nil { 356 return 0, isNull0, err 357 } 358 args := b.args 359 if len(b.hashSet) != 0 { 360 args = b.nonConstArgs 361 if b.hashSet.Exist(arg0) { 362 return 1, false, nil 363 } 364 } 365 hasNull := b.hasNull 366 for _, arg := range args[1:] { 367 evaledArg, isNull, err := arg.EvalReal(b.ctx, event) 368 if err != nil { 369 return 0, true, err 370 } 371 if isNull { 372 hasNull = true 373 continue 374 } 375 if arg0 == evaledArg { 376 return 1, false, nil 377 } 378 } 379 return 0, hasNull, nil 380 } 381 382 // builtinInDecimalSig see https://dev.allegrosql.com/doc/refman/5.7/en/comparison-operators.html#function_in 383 type builtinInDecimalSig struct { 384 baseInSig 385 hashSet set.StringSet 386 } 387 388 func (b *builtinInDecimalSig) buildHashMapForConstArgs(ctx stochastikctx.Context) error { 389 b.nonConstArgs = []Expression{b.args[0]} 390 b.hashSet = set.NewStringSet() 391 for i := 1; i < len(b.args); i++ { 392 if b.args[i].ConstItem(b.ctx.GetStochastikVars().StmtCtx) { 393 val, isNull, err := b.args[i].EvalDecimal(ctx, chunk.Event{}) 394 if err != nil { 395 return err 396 } 397 if isNull { 398 b.hasNull = true 399 continue 400 } 401 key, err := val.ToHashKey() 402 if err != nil { 403 return err 404 } 405 b.hashSet.Insert(string(key)) 406 } else { 407 b.nonConstArgs = append(b.nonConstArgs, b.args[i]) 408 } 409 } 410 411 return nil 412 } 413 414 func (b *builtinInDecimalSig) Clone() builtinFunc { 415 newSig := &builtinInDecimalSig{} 416 newSig.cloneFrom(&b.baseBuiltinFunc) 417 newSig.nonConstArgs = make([]Expression, 0, len(b.nonConstArgs)) 418 for _, arg := range b.nonConstArgs { 419 newSig.nonConstArgs = append(newSig.nonConstArgs, arg.Clone()) 420 } 421 newSig.hashSet = b.hashSet 422 newSig.hasNull = b.hasNull 423 return newSig 424 } 425 426 func (b *builtinInDecimalSig) evalInt(event chunk.Event) (int64, bool, error) { 427 arg0, isNull0, err := b.args[0].EvalDecimal(b.ctx, event) 428 if isNull0 || err != nil { 429 return 0, isNull0, err 430 } 431 432 args := b.args 433 key, err := arg0.ToHashKey() 434 if err != nil { 435 return 0, true, err 436 } 437 if len(b.hashSet) != 0 { 438 args = b.nonConstArgs 439 if b.hashSet.Exist(string(key)) { 440 return 1, false, nil 441 } 442 } 443 444 hasNull := b.hasNull 445 for _, arg := range args[1:] { 446 evaledArg, isNull, err := arg.EvalDecimal(b.ctx, event) 447 if err != nil { 448 return 0, true, err 449 } 450 if isNull { 451 hasNull = true 452 continue 453 } 454 if arg0.Compare(evaledArg) == 0 { 455 return 1, false, nil 456 } 457 } 458 return 0, hasNull, nil 459 } 460 461 // builtinInTimeSig see https://dev.allegrosql.com/doc/refman/5.7/en/comparison-operators.html#function_in 462 type builtinInTimeSig struct { 463 baseInSig 464 hashSet map[types.Time]struct{} 465 } 466 467 func (b *builtinInTimeSig) buildHashMapForConstArgs(ctx stochastikctx.Context) error { 468 b.nonConstArgs = []Expression{b.args[0]} 469 b.hashSet = make(map[types.Time]struct{}, len(b.args)-1) 470 for i := 1; i < len(b.args); i++ { 471 if b.args[i].ConstItem(b.ctx.GetStochastikVars().StmtCtx) { 472 val, isNull, err := b.args[i].EvalTime(ctx, chunk.Event{}) 473 if err != nil { 474 return err 475 } 476 if isNull { 477 b.hasNull = true 478 continue 479 } 480 b.hashSet[val] = struct{}{} 481 } else { 482 b.nonConstArgs = append(b.nonConstArgs, b.args[i]) 483 } 484 } 485 486 return nil 487 } 488 489 func (b *builtinInTimeSig) Clone() builtinFunc { 490 newSig := &builtinInTimeSig{} 491 newSig.cloneFrom(&b.baseBuiltinFunc) 492 newSig.nonConstArgs = make([]Expression, 0, len(b.nonConstArgs)) 493 for _, arg := range b.nonConstArgs { 494 newSig.nonConstArgs = append(newSig.nonConstArgs, arg.Clone()) 495 } 496 newSig.hashSet = b.hashSet 497 newSig.hasNull = b.hasNull 498 return newSig 499 } 500 501 func (b *builtinInTimeSig) evalInt(event chunk.Event) (int64, bool, error) { 502 arg0, isNull0, err := b.args[0].EvalTime(b.ctx, event) 503 if isNull0 || err != nil { 504 return 0, isNull0, err 505 } 506 args := b.args 507 if len(b.hashSet) != 0 { 508 args = b.nonConstArgs 509 if _, ok := b.hashSet[arg0]; ok { 510 return 1, false, nil 511 } 512 } 513 hasNull := b.hasNull 514 for _, arg := range args[1:] { 515 evaledArg, isNull, err := arg.EvalTime(b.ctx, event) 516 if err != nil { 517 return 0, true, err 518 } 519 if isNull { 520 hasNull = true 521 continue 522 } 523 if arg0.Compare(evaledArg) == 0 { 524 return 1, false, nil 525 } 526 } 527 return 0, hasNull, nil 528 } 529 530 // builtinInDurationSig see https://dev.allegrosql.com/doc/refman/5.7/en/comparison-operators.html#function_in 531 type builtinInDurationSig struct { 532 baseInSig 533 hashSet map[time.Duration]struct{} 534 } 535 536 func (b *builtinInDurationSig) buildHashMapForConstArgs(ctx stochastikctx.Context) error { 537 b.nonConstArgs = []Expression{b.args[0]} 538 b.hashSet = make(map[time.Duration]struct{}, len(b.args)-1) 539 for i := 1; i < len(b.args); i++ { 540 if b.args[i].ConstItem(b.ctx.GetStochastikVars().StmtCtx) { 541 val, isNull, err := b.args[i].EvalDuration(ctx, chunk.Event{}) 542 if err != nil { 543 return err 544 } 545 if isNull { 546 b.hasNull = true 547 continue 548 } 549 b.hashSet[val.Duration] = struct{}{} 550 } else { 551 b.nonConstArgs = append(b.nonConstArgs, b.args[i]) 552 } 553 } 554 555 return nil 556 } 557 558 func (b *builtinInDurationSig) Clone() builtinFunc { 559 newSig := &builtinInDurationSig{} 560 newSig.cloneFrom(&b.baseBuiltinFunc) 561 newSig.nonConstArgs = make([]Expression, 0, len(b.nonConstArgs)) 562 for _, arg := range b.nonConstArgs { 563 newSig.nonConstArgs = append(newSig.nonConstArgs, arg.Clone()) 564 } 565 newSig.hashSet = b.hashSet 566 newSig.hasNull = b.hasNull 567 return newSig 568 } 569 570 func (b *builtinInDurationSig) evalInt(event chunk.Event) (int64, bool, error) { 571 arg0, isNull0, err := b.args[0].EvalDuration(b.ctx, event) 572 if isNull0 || err != nil { 573 return 0, isNull0, err 574 } 575 args := b.args 576 if len(b.hashSet) != 0 { 577 args = b.nonConstArgs 578 if _, ok := b.hashSet[arg0.Duration]; ok { 579 return 1, false, nil 580 } 581 } 582 hasNull := b.hasNull 583 for _, arg := range args[1:] { 584 evaledArg, isNull, err := arg.EvalDuration(b.ctx, event) 585 if err != nil { 586 return 0, true, err 587 } 588 if isNull { 589 hasNull = true 590 continue 591 } 592 if arg0.Compare(evaledArg) == 0 { 593 return 1, false, nil 594 } 595 } 596 return 0, hasNull, nil 597 } 598 599 // builtinInJSONSig see https://dev.allegrosql.com/doc/refman/5.7/en/comparison-operators.html#function_in 600 type builtinInJSONSig struct { 601 baseBuiltinFunc 602 } 603 604 func (b *builtinInJSONSig) Clone() builtinFunc { 605 newSig := &builtinInJSONSig{} 606 newSig.cloneFrom(&b.baseBuiltinFunc) 607 return newSig 608 } 609 610 func (b *builtinInJSONSig) evalInt(event chunk.Event) (int64, bool, error) { 611 arg0, isNull0, err := b.args[0].EvalJSON(b.ctx, event) 612 if isNull0 || err != nil { 613 return 0, isNull0, err 614 } 615 var hasNull bool 616 for _, arg := range b.args[1:] { 617 evaledArg, isNull, err := arg.EvalJSON(b.ctx, event) 618 if err != nil { 619 return 0, true, err 620 } 621 if isNull { 622 hasNull = true 623 continue 624 } 625 result := json.CompareBinary(evaledArg, arg0) 626 if result == 0 { 627 return 1, false, nil 628 } 629 } 630 return 0, hasNull, nil 631 } 632 633 type rowFunctionClass struct { 634 baseFunctionClass 635 } 636 637 func (c *rowFunctionClass) getFunction(ctx stochastikctx.Context, args []Expression) (sig builtinFunc, err error) { 638 if err = c.verifyArgs(args); err != nil { 639 return nil, err 640 } 641 argTps := make([]types.EvalType, len(args)) 642 for i := range argTps { 643 argTps[i] = args[i].GetType().EvalType() 644 } 645 bf, err := newBaseBuiltinFuncWithTp(ctx, c.funcName, args, types.ETString, argTps...) 646 if err != nil { 647 return nil, err 648 } 649 sig = &builtinEventSig{bf} 650 return sig, nil 651 } 652 653 type builtinEventSig struct { 654 baseBuiltinFunc 655 } 656 657 func (b *builtinEventSig) Clone() builtinFunc { 658 newSig := &builtinEventSig{} 659 newSig.cloneFrom(&b.baseBuiltinFunc) 660 return newSig 661 } 662 663 // evalString rowFunc should always be flattened in memex rewrite phrase. 664 func (b *builtinEventSig) evalString(event chunk.Event) (string, bool, error) { 665 panic("builtinEventSig.evalString() should never be called.") 666 } 667 668 type setVarFunctionClass struct { 669 baseFunctionClass 670 } 671 672 func (c *setVarFunctionClass) getFunction(ctx stochastikctx.Context, args []Expression) (sig builtinFunc, err error) { 673 if err = c.verifyArgs(args); err != nil { 674 return nil, err 675 } 676 bf, err := newBaseBuiltinFuncWithTp(ctx, c.funcName, args, types.ETString, types.ETString, types.ETString) 677 if err != nil { 678 return nil, err 679 } 680 bf.tp.Flen = args[1].GetType().Flen 681 // TODO: we should consider the type of the argument, but not take it as string for all situations. 682 sig = &builtinSetVarSig{bf} 683 return sig, err 684 } 685 686 type builtinSetVarSig struct { 687 baseBuiltinFunc 688 } 689 690 func (b *builtinSetVarSig) Clone() builtinFunc { 691 newSig := &builtinSetVarSig{} 692 newSig.cloneFrom(&b.baseBuiltinFunc) 693 return newSig 694 } 695 696 func (b *builtinSetVarSig) evalString(event chunk.Event) (res string, isNull bool, err error) { 697 var varName string 698 stochastikVars := b.ctx.GetStochastikVars() 699 varName, isNull, err = b.args[0].EvalString(b.ctx, event) 700 if isNull || err != nil { 701 return "", isNull, err 702 } 703 704 causet, err := b.args[1].Eval(event) 705 isNull = causet.IsNull() 706 if isNull || err != nil { 707 return "", isNull, err 708 } 709 710 res, err = causet.ToString() 711 if err != nil { 712 return "", isNull, err 713 } 714 715 varName = strings.ToLower(varName) 716 stochastikVars.UsersLock.Lock() 717 stochastikVars.SetUserVar(varName, stringutil.Copy(res), causet.DefCauslation()) 718 stochastikVars.UsersLock.Unlock() 719 return res, false, nil 720 } 721 722 type getVarFunctionClass struct { 723 baseFunctionClass 724 } 725 726 func (c *getVarFunctionClass) getFunction(ctx stochastikctx.Context, args []Expression) (sig builtinFunc, err error) { 727 if err = c.verifyArgs(args); err != nil { 728 return nil, err 729 } 730 // TODO: we should consider the type of the argument, but not take it as string for all situations. 731 bf, err := newBaseBuiltinFuncWithTp(ctx, c.funcName, args, types.ETString, types.ETString) 732 if err != nil { 733 return nil, err 734 } 735 bf.tp.Flen = allegrosql.MaxFieldVarCharLength 736 if err := c.resolveDefCauslation(ctx, args, &bf); err != nil { 737 return nil, err 738 } 739 sig = &builtinGetVarSig{bf} 740 return sig, nil 741 } 742 743 func (c *getVarFunctionClass) resolveDefCauslation(ctx stochastikctx.Context, args []Expression, bf *baseBuiltinFunc) (err error) { 744 if constant, ok := args[0].(*Constant); ok { 745 varName, err := constant.Value.ToString() 746 if err != nil { 747 return err 748 } 749 varName = strings.ToLower(varName) 750 ctx.GetStochastikVars().UsersLock.RLock() 751 defer ctx.GetStochastikVars().UsersLock.RUnlock() 752 if v, ok := ctx.GetStochastikVars().Users[varName]; ok { 753 bf.tp.DefCauslate = v.DefCauslation() 754 if len(bf.tp.Charset) <= 0 { 755 charset, _ := ctx.GetStochastikVars().GetCharsetInfo() 756 bf.tp.Charset = charset 757 } 758 return nil 759 } 760 } 761 762 return nil 763 } 764 765 type builtinGetVarSig struct { 766 baseBuiltinFunc 767 } 768 769 func (b *builtinGetVarSig) Clone() builtinFunc { 770 newSig := &builtinGetVarSig{} 771 newSig.cloneFrom(&b.baseBuiltinFunc) 772 return newSig 773 } 774 775 func (b *builtinGetVarSig) evalString(event chunk.Event) (string, bool, error) { 776 stochastikVars := b.ctx.GetStochastikVars() 777 varName, isNull, err := b.args[0].EvalString(b.ctx, event) 778 if isNull || err != nil { 779 return "", isNull, err 780 } 781 varName = strings.ToLower(varName) 782 stochastikVars.UsersLock.RLock() 783 defer stochastikVars.UsersLock.RUnlock() 784 if v, ok := stochastikVars.Users[varName]; ok { 785 return v.GetString(), false, nil 786 } 787 return "", true, nil 788 } 789 790 type valuesFunctionClass struct { 791 baseFunctionClass 792 793 offset int 794 tp *types.FieldType 795 } 796 797 func (c *valuesFunctionClass) getFunction(ctx stochastikctx.Context, args []Expression) (sig builtinFunc, err error) { 798 if err = c.verifyArgs(args); err != nil { 799 return nil, err 800 } 801 bf, err := newBaseBuiltinFunc(ctx, c.funcName, args, c.tp.EvalType()) 802 if err != nil { 803 return nil, err 804 } 805 bf.tp = c.tp 806 switch c.tp.EvalType() { 807 case types.ETInt: 808 sig = &builtinValuesIntSig{bf, c.offset} 809 case types.ETReal: 810 sig = &builtinValuesRealSig{bf, c.offset} 811 case types.ETDecimal: 812 sig = &builtinValuesDecimalSig{bf, c.offset} 813 case types.ETString: 814 sig = &builtinValuesStringSig{bf, c.offset} 815 case types.ETDatetime, types.ETTimestamp: 816 sig = &builtinValuesTimeSig{bf, c.offset} 817 case types.ETDuration: 818 sig = &builtinValuesDurationSig{bf, c.offset} 819 case types.ETJson: 820 sig = &builtinValuesJSONSig{bf, c.offset} 821 } 822 return sig, nil 823 } 824 825 type builtinValuesIntSig struct { 826 baseBuiltinFunc 827 828 offset int 829 } 830 831 func (b *builtinValuesIntSig) Clone() builtinFunc { 832 newSig := &builtinValuesIntSig{offset: b.offset} 833 newSig.cloneFrom(&b.baseBuiltinFunc) 834 return newSig 835 } 836 837 // evalInt evals a builtinValuesIntSig. 838 // See https://dev.allegrosql.com/doc/refman/5.7/en/miscellaneous-functions.html#function_values 839 func (b *builtinValuesIntSig) evalInt(_ chunk.Event) (int64, bool, error) { 840 if !b.ctx.GetStochastikVars().StmtCtx.InInsertStmt { 841 return 0, true, nil 842 } 843 event := b.ctx.GetStochastikVars().CurrInsertValues 844 if event.IsEmpty() { 845 return 0, true, errors.New("Stochastik current insert values is nil") 846 } 847 if b.offset < event.Len() { 848 if event.IsNull(b.offset) { 849 return 0, true, nil 850 } 851 // For BinaryLiteral, see issue #15310 852 val := event.GetRaw(b.offset) 853 if len(val) > 8 { 854 return 0, true, errors.New("Stochastik current insert values is too long") 855 } 856 if len(val) < 8 { 857 var binary types.BinaryLiteral = val 858 v, err := binary.ToInt(b.ctx.GetStochastikVars().StmtCtx) 859 if err != nil { 860 return 0, true, errors.Trace(err) 861 } 862 return int64(v), false, nil 863 } 864 return event.GetInt64(b.offset), false, nil 865 } 866 return 0, true, errors.Errorf("Stochastik current insert values len %d and defCausumn's offset %v don't match", event.Len(), b.offset) 867 } 868 869 type builtinValuesRealSig struct { 870 baseBuiltinFunc 871 872 offset int 873 } 874 875 func (b *builtinValuesRealSig) Clone() builtinFunc { 876 newSig := &builtinValuesRealSig{offset: b.offset} 877 newSig.cloneFrom(&b.baseBuiltinFunc) 878 return newSig 879 } 880 881 // evalReal evals a builtinValuesRealSig. 882 // See https://dev.allegrosql.com/doc/refman/5.7/en/miscellaneous-functions.html#function_values 883 func (b *builtinValuesRealSig) evalReal(_ chunk.Event) (float64, bool, error) { 884 if !b.ctx.GetStochastikVars().StmtCtx.InInsertStmt { 885 return 0, true, nil 886 } 887 event := b.ctx.GetStochastikVars().CurrInsertValues 888 if event.IsEmpty() { 889 return 0, true, errors.New("Stochastik current insert values is nil") 890 } 891 if b.offset < event.Len() { 892 if event.IsNull(b.offset) { 893 return 0, true, nil 894 } 895 if b.getRetTp().Tp == allegrosql.TypeFloat { 896 return float64(event.GetFloat32(b.offset)), false, nil 897 } 898 return event.GetFloat64(b.offset), false, nil 899 } 900 return 0, true, errors.Errorf("Stochastik current insert values len %d and defCausumn's offset %v don't match", event.Len(), b.offset) 901 } 902 903 type builtinValuesDecimalSig struct { 904 baseBuiltinFunc 905 906 offset int 907 } 908 909 func (b *builtinValuesDecimalSig) Clone() builtinFunc { 910 newSig := &builtinValuesDecimalSig{offset: b.offset} 911 newSig.cloneFrom(&b.baseBuiltinFunc) 912 return newSig 913 } 914 915 // evalDecimal evals a builtinValuesDecimalSig. 916 // See https://dev.allegrosql.com/doc/refman/5.7/en/miscellaneous-functions.html#function_values 917 func (b *builtinValuesDecimalSig) evalDecimal(_ chunk.Event) (*types.MyDecimal, bool, error) { 918 if !b.ctx.GetStochastikVars().StmtCtx.InInsertStmt { 919 return nil, true, nil 920 } 921 event := b.ctx.GetStochastikVars().CurrInsertValues 922 if event.IsEmpty() { 923 return nil, true, errors.New("Stochastik current insert values is nil") 924 } 925 if b.offset < event.Len() { 926 if event.IsNull(b.offset) { 927 return nil, true, nil 928 } 929 return event.GetMyDecimal(b.offset), false, nil 930 } 931 return nil, true, errors.Errorf("Stochastik current insert values len %d and defCausumn's offset %v don't match", event.Len(), b.offset) 932 } 933 934 type builtinValuesStringSig struct { 935 baseBuiltinFunc 936 937 offset int 938 } 939 940 func (b *builtinValuesStringSig) Clone() builtinFunc { 941 newSig := &builtinValuesStringSig{offset: b.offset} 942 newSig.cloneFrom(&b.baseBuiltinFunc) 943 return newSig 944 } 945 946 // evalString evals a builtinValuesStringSig. 947 // See https://dev.allegrosql.com/doc/refman/5.7/en/miscellaneous-functions.html#function_values 948 func (b *builtinValuesStringSig) evalString(_ chunk.Event) (string, bool, error) { 949 if !b.ctx.GetStochastikVars().StmtCtx.InInsertStmt { 950 return "", true, nil 951 } 952 event := b.ctx.GetStochastikVars().CurrInsertValues 953 if event.IsEmpty() { 954 return "", true, errors.New("Stochastik current insert values is nil") 955 } 956 if b.offset >= event.Len() { 957 return "", true, errors.Errorf("Stochastik current insert values len %d and defCausumn's offset %v don't match", event.Len(), b.offset) 958 } 959 960 if event.IsNull(b.offset) { 961 return "", true, nil 962 } 963 964 // Specially handle the ENUM/SET/BIT input value. 965 if retType := b.getRetTp(); retType.Hybrid() { 966 val := event.GetCauset(b.offset, retType) 967 res, err := val.ToString() 968 return res, err != nil, err 969 } 970 971 return event.GetString(b.offset), false, nil 972 } 973 974 type builtinValuesTimeSig struct { 975 baseBuiltinFunc 976 977 offset int 978 } 979 980 func (b *builtinValuesTimeSig) Clone() builtinFunc { 981 newSig := &builtinValuesTimeSig{offset: b.offset} 982 newSig.cloneFrom(&b.baseBuiltinFunc) 983 return newSig 984 } 985 986 // evalTime evals a builtinValuesTimeSig. 987 // See https://dev.allegrosql.com/doc/refman/5.7/en/miscellaneous-functions.html#function_values 988 func (b *builtinValuesTimeSig) evalTime(_ chunk.Event) (types.Time, bool, error) { 989 if !b.ctx.GetStochastikVars().StmtCtx.InInsertStmt { 990 return types.ZeroTime, true, nil 991 } 992 event := b.ctx.GetStochastikVars().CurrInsertValues 993 if event.IsEmpty() { 994 return types.ZeroTime, true, errors.New("Stochastik current insert values is nil") 995 } 996 if b.offset < event.Len() { 997 if event.IsNull(b.offset) { 998 return types.ZeroTime, true, nil 999 } 1000 return event.GetTime(b.offset), false, nil 1001 } 1002 return types.ZeroTime, true, errors.Errorf("Stochastik current insert values len %d and defCausumn's offset %v don't match", event.Len(), b.offset) 1003 } 1004 1005 type builtinValuesDurationSig struct { 1006 baseBuiltinFunc 1007 1008 offset int 1009 } 1010 1011 func (b *builtinValuesDurationSig) Clone() builtinFunc { 1012 newSig := &builtinValuesDurationSig{offset: b.offset} 1013 newSig.cloneFrom(&b.baseBuiltinFunc) 1014 return newSig 1015 } 1016 1017 // evalDuration evals a builtinValuesDurationSig. 1018 // See https://dev.allegrosql.com/doc/refman/5.7/en/miscellaneous-functions.html#function_values 1019 func (b *builtinValuesDurationSig) evalDuration(_ chunk.Event) (types.Duration, bool, error) { 1020 if !b.ctx.GetStochastikVars().StmtCtx.InInsertStmt { 1021 return types.Duration{}, true, nil 1022 } 1023 event := b.ctx.GetStochastikVars().CurrInsertValues 1024 if event.IsEmpty() { 1025 return types.Duration{}, true, errors.New("Stochastik current insert values is nil") 1026 } 1027 if b.offset < event.Len() { 1028 if event.IsNull(b.offset) { 1029 return types.Duration{}, true, nil 1030 } 1031 duration := event.GetDuration(b.offset, b.getRetTp().Decimal) 1032 return duration, false, nil 1033 } 1034 return types.Duration{}, true, errors.Errorf("Stochastik current insert values len %d and defCausumn's offset %v don't match", event.Len(), b.offset) 1035 } 1036 1037 type builtinValuesJSONSig struct { 1038 baseBuiltinFunc 1039 1040 offset int 1041 } 1042 1043 func (b *builtinValuesJSONSig) Clone() builtinFunc { 1044 newSig := &builtinValuesJSONSig{offset: b.offset} 1045 newSig.cloneFrom(&b.baseBuiltinFunc) 1046 return newSig 1047 } 1048 1049 // evalJSON evals a builtinValuesJSONSig. 1050 // See https://dev.allegrosql.com/doc/refman/5.7/en/miscellaneous-functions.html#function_values 1051 func (b *builtinValuesJSONSig) evalJSON(_ chunk.Event) (json.BinaryJSON, bool, error) { 1052 if !b.ctx.GetStochastikVars().StmtCtx.InInsertStmt { 1053 return json.BinaryJSON{}, true, nil 1054 } 1055 event := b.ctx.GetStochastikVars().CurrInsertValues 1056 if event.IsEmpty() { 1057 return json.BinaryJSON{}, true, errors.New("Stochastik current insert values is nil") 1058 } 1059 if b.offset < event.Len() { 1060 if event.IsNull(b.offset) { 1061 return json.BinaryJSON{}, true, nil 1062 } 1063 return event.GetJSON(b.offset), false, nil 1064 } 1065 return json.BinaryJSON{}, true, errors.Errorf("Stochastik current insert values len %d and defCausumn's offset %v don't match", event.Len(), b.offset) 1066 } 1067 1068 type bitCountFunctionClass struct { 1069 baseFunctionClass 1070 } 1071 1072 func (c *bitCountFunctionClass) getFunction(ctx stochastikctx.Context, args []Expression) (builtinFunc, error) { 1073 if err := c.verifyArgs(args); err != nil { 1074 return nil, err 1075 } 1076 bf, err := newBaseBuiltinFuncWithTp(ctx, c.funcName, args, types.ETInt, types.ETInt) 1077 if err != nil { 1078 return nil, err 1079 } 1080 bf.tp.Flen = 2 1081 sig := &builtinBitCountSig{bf} 1082 return sig, nil 1083 } 1084 1085 type builtinBitCountSig struct { 1086 baseBuiltinFunc 1087 } 1088 1089 func (b *builtinBitCountSig) Clone() builtinFunc { 1090 newSig := &builtinBitCountSig{} 1091 newSig.cloneFrom(&b.baseBuiltinFunc) 1092 return newSig 1093 } 1094 1095 // evalInt evals BIT_COUNT(N). 1096 // See https://dev.allegrosql.com/doc/refman/5.7/en/bit-functions.html#function_bit-count 1097 func (b *builtinBitCountSig) evalInt(event chunk.Event) (int64, bool, error) { 1098 n, isNull, err := b.args[0].EvalInt(b.ctx, event) 1099 if err != nil || isNull { 1100 if err != nil && types.ErrOverflow.Equal(err) { 1101 return 64, false, nil 1102 } 1103 return 0, true, err 1104 } 1105 return bitCount(n), false, nil 1106 } 1107 1108 // getParamFunctionClass for plan cache of prepared memexs 1109 type getParamFunctionClass struct { 1110 baseFunctionClass 1111 } 1112 1113 // getFunction gets function 1114 // TODO: more typed functions will be added when typed parameters are supported. 1115 func (c *getParamFunctionClass) getFunction(ctx stochastikctx.Context, args []Expression) (builtinFunc, error) { 1116 if err := c.verifyArgs(args); err != nil { 1117 return nil, err 1118 } 1119 bf, err := newBaseBuiltinFuncWithTp(ctx, c.funcName, args, types.ETString, types.ETInt) 1120 if err != nil { 1121 return nil, err 1122 } 1123 bf.tp.Flen = allegrosql.MaxFieldVarCharLength 1124 sig := &builtinGetParamStringSig{bf} 1125 return sig, nil 1126 } 1127 1128 type builtinGetParamStringSig struct { 1129 baseBuiltinFunc 1130 } 1131 1132 func (b *builtinGetParamStringSig) Clone() builtinFunc { 1133 newSig := &builtinGetParamStringSig{} 1134 newSig.cloneFrom(&b.baseBuiltinFunc) 1135 return newSig 1136 } 1137 1138 func (b *builtinGetParamStringSig) evalString(event chunk.Event) (string, bool, error) { 1139 stochastikVars := b.ctx.GetStochastikVars() 1140 idx, isNull, err := b.args[0].EvalInt(b.ctx, event) 1141 if isNull || err != nil { 1142 return "", isNull, err 1143 } 1144 v := stochastikVars.PreparedParams[idx] 1145 1146 str, err := v.ToString() 1147 if err != nil { 1148 return "", true, nil 1149 } 1150 return str, false, nil 1151 }