github.com/whtcorpsinc/MilevaDB-Prod@v0.0.0-20211104133533-f57f4be3b597/dbs/memristed/memex/builtin_info.go (about) 1 // Copyright 2020 The ql Authors. All rights reserved. 2 // Use of this source code is governed by a BSD-style 3 // license that can be found in the LICENSES/QL-LICENSE file. 4 5 // Copyright 2020 WHTCORPS INC, Inc. 6 // 7 // Licensed under the Apache License, Version 2.0 (the "License"); 8 // you may not use this file except in compliance with the License. 9 // You may obtain a copy of the License at 10 // 11 // http://www.apache.org/licenses/LICENSE-2.0 12 // 13 // Unless required by applicable law or agreed to in writing, software 14 // distributed under the License is distributed on an "AS IS" BASIS, 15 // See the License for the specific language governing permissions and 16 // limitations under the License. 17 18 package memex 19 20 import ( 21 "encoding/hex" 22 "sort" 23 "strconv" 24 "strings" 25 26 "github.com/whtcorpsinc/errors" 27 "github.com/whtcorpsinc/BerolinaSQL/perceptron" 28 "github.com/whtcorpsinc/BerolinaSQL/allegrosql" 29 "github.com/whtcorpsinc/milevadb/privilege" 30 "github.com/whtcorpsinc/milevadb/stochastikctx" 31 "github.com/whtcorpsinc/milevadb/blockcodec" 32 "github.com/whtcorpsinc/milevadb/types" 33 "github.com/whtcorpsinc/milevadb/soliton" 34 "github.com/whtcorpsinc/milevadb/soliton/chunk" 35 "github.com/whtcorpsinc/milevadb/soliton/codec" 36 "github.com/whtcorpsinc/milevadb/soliton/plancodec" 37 "github.com/whtcorpsinc/milevadb/soliton/printer" 38 "github.com/whtcorpsinc/fidelpb/go-fidelpb" 39 ) 40 41 var ( 42 _ functionClass = &databaseFunctionClass{} 43 _ functionClass = &foundEventsFunctionClass{} 44 _ functionClass = ¤tUserFunctionClass{} 45 _ functionClass = ¤tRoleFunctionClass{} 46 _ functionClass = &userFunctionClass{} 47 _ functionClass = &connectionIDFunctionClass{} 48 _ functionClass = &lastInsertIDFunctionClass{} 49 _ functionClass = &versionFunctionClass{} 50 _ functionClass = &benchmarkFunctionClass{} 51 _ functionClass = &charsetFunctionClass{} 52 _ functionClass = &coercibilityFunctionClass{} 53 _ functionClass = &defCauslationFunctionClass{} 54 _ functionClass = &rowCountFunctionClass{} 55 _ functionClass = &milevadbVersionFunctionClass{} 56 _ functionClass = &milevadbIsDBSTenantFunctionClass{} 57 _ functionClass = &milevadbDecodeCausetFunctionClass{} 58 _ functionClass = &milevadbDecodeKeyFunctionClass{} 59 _ functionClass = &nextValFunctionClass{} 60 _ functionClass = &lastValFunctionClass{} 61 _ functionClass = &setValFunctionClass{} 62 _ functionClass = &formatBytesFunctionClass{} 63 _ functionClass = &formatNanoTimeFunctionClass{} 64 ) 65 66 var ( 67 _ builtinFunc = &builtinDatabaseSig{} 68 _ builtinFunc = &builtinFoundEventsSig{} 69 _ builtinFunc = &builtinCurrentUserSig{} 70 _ builtinFunc = &builtinUserSig{} 71 _ builtinFunc = &builtinConnectionIDSig{} 72 _ builtinFunc = &builtinLastInsertIDSig{} 73 _ builtinFunc = &builtinLastInsertIDWithIDSig{} 74 _ builtinFunc = &builtinVersionSig{} 75 _ builtinFunc = &builtinMilevaDBVersionSig{} 76 _ builtinFunc = &builtinEventCountSig{} 77 _ builtinFunc = &builtinMilevaDBDecodeKeySig{} 78 _ builtinFunc = &builtinNextValSig{} 79 _ builtinFunc = &builtinLastValSig{} 80 _ builtinFunc = &builtinSetValSig{} 81 _ builtinFunc = &builtinFormatBytesSig{} 82 _ builtinFunc = &builtinFormatNanoTimeSig{} 83 ) 84 85 type databaseFunctionClass struct { 86 baseFunctionClass 87 } 88 89 func (c *databaseFunctionClass) getFunction(ctx stochastikctx.Context, args []Expression) (builtinFunc, error) { 90 if err := c.verifyArgs(args); err != nil { 91 return nil, err 92 } 93 bf, err := newBaseBuiltinFuncWithTp(ctx, c.funcName, args, types.ETString) 94 if err != nil { 95 return nil, err 96 } 97 bf.tp.Charset, bf.tp.DefCauslate = ctx.GetStochastikVars().GetCharsetInfo() 98 bf.tp.Flen = 64 99 sig := &builtinDatabaseSig{bf} 100 return sig, nil 101 } 102 103 type builtinDatabaseSig struct { 104 baseBuiltinFunc 105 } 106 107 func (b *builtinDatabaseSig) Clone() builtinFunc { 108 newSig := &builtinDatabaseSig{} 109 newSig.cloneFrom(&b.baseBuiltinFunc) 110 return newSig 111 } 112 113 // evalString evals a builtinDatabaseSig. 114 // See https://dev.allegrosql.com/doc/refman/5.7/en/information-functions.html 115 func (b *builtinDatabaseSig) evalString(event chunk.Event) (string, bool, error) { 116 currentDB := b.ctx.GetStochastikVars().CurrentDB 117 return currentDB, currentDB == "", nil 118 } 119 120 type foundEventsFunctionClass struct { 121 baseFunctionClass 122 } 123 124 func (c *foundEventsFunctionClass) getFunction(ctx stochastikctx.Context, args []Expression) (builtinFunc, error) { 125 if err := c.verifyArgs(args); err != nil { 126 return nil, err 127 } 128 bf, err := newBaseBuiltinFuncWithTp(ctx, c.funcName, args, types.ETInt) 129 if err != nil { 130 return nil, err 131 } 132 bf.tp.Flag |= allegrosql.UnsignedFlag 133 sig := &builtinFoundEventsSig{bf} 134 return sig, nil 135 } 136 137 type builtinFoundEventsSig struct { 138 baseBuiltinFunc 139 } 140 141 func (b *builtinFoundEventsSig) Clone() builtinFunc { 142 newSig := &builtinFoundEventsSig{} 143 newSig.cloneFrom(&b.baseBuiltinFunc) 144 return newSig 145 } 146 147 // evalInt evals a builtinFoundEventsSig. 148 // See https://dev.allegrosql.com/doc/refman/5.7/en/information-functions.html#function_found-rows 149 // TODO: ALLEGROSQL_CALC_FOUND_ROWS and LIMIT not support for now, We will finish in another PR. 150 func (b *builtinFoundEventsSig) evalInt(event chunk.Event) (int64, bool, error) { 151 data := b.ctx.GetStochastikVars() 152 if data == nil { 153 return 0, true, errors.Errorf("Missing stochastik variable when eval builtin") 154 } 155 return int64(data.LastFoundEvents), false, nil 156 } 157 158 type currentUserFunctionClass struct { 159 baseFunctionClass 160 } 161 162 func (c *currentUserFunctionClass) getFunction(ctx stochastikctx.Context, args []Expression) (builtinFunc, error) { 163 if err := c.verifyArgs(args); err != nil { 164 return nil, err 165 } 166 bf, err := newBaseBuiltinFuncWithTp(ctx, c.funcName, args, types.ETString) 167 if err != nil { 168 return nil, err 169 } 170 bf.tp.Charset, bf.tp.DefCauslate = ctx.GetStochastikVars().GetCharsetInfo() 171 bf.tp.Flen = 64 172 sig := &builtinCurrentUserSig{bf} 173 return sig, nil 174 } 175 176 type builtinCurrentUserSig struct { 177 baseBuiltinFunc 178 } 179 180 func (b *builtinCurrentUserSig) Clone() builtinFunc { 181 newSig := &builtinCurrentUserSig{} 182 newSig.cloneFrom(&b.baseBuiltinFunc) 183 return newSig 184 } 185 186 // evalString evals a builtinCurrentUserSig. 187 // See https://dev.allegrosql.com/doc/refman/5.7/en/information-functions.html#function_current-user 188 func (b *builtinCurrentUserSig) evalString(event chunk.Event) (string, bool, error) { 189 data := b.ctx.GetStochastikVars() 190 if data == nil || data.User == nil { 191 return "", true, errors.Errorf("Missing stochastik variable when eval builtin") 192 } 193 return data.User.AuthIdentityString(), false, nil 194 } 195 196 type currentRoleFunctionClass struct { 197 baseFunctionClass 198 } 199 200 func (c *currentRoleFunctionClass) getFunction(ctx stochastikctx.Context, args []Expression) (builtinFunc, error) { 201 if err := c.verifyArgs(args); err != nil { 202 return nil, err 203 } 204 bf, err := newBaseBuiltinFuncWithTp(ctx, c.funcName, args, types.ETString) 205 if err != nil { 206 return nil, err 207 } 208 bf.tp.Charset, bf.tp.DefCauslate = ctx.GetStochastikVars().GetCharsetInfo() 209 bf.tp.Flen = 64 210 sig := &builtinCurrentRoleSig{bf} 211 return sig, nil 212 } 213 214 type builtinCurrentRoleSig struct { 215 baseBuiltinFunc 216 } 217 218 func (b *builtinCurrentRoleSig) Clone() builtinFunc { 219 newSig := &builtinCurrentRoleSig{} 220 newSig.cloneFrom(&b.baseBuiltinFunc) 221 return newSig 222 } 223 224 // evalString evals a builtinCurrentUserSig. 225 // See https://dev.allegrosql.com/doc/refman/5.7/en/information-functions.html#function_current-user 226 func (b *builtinCurrentRoleSig) evalString(event chunk.Event) (string, bool, error) { 227 data := b.ctx.GetStochastikVars() 228 if data == nil || data.ActiveRoles == nil { 229 return "", true, errors.Errorf("Missing stochastik variable when eval builtin") 230 } 231 if len(data.ActiveRoles) == 0 { 232 return "", false, nil 233 } 234 res := "" 235 sortedRes := make([]string, 0, 10) 236 for _, r := range data.ActiveRoles { 237 sortedRes = append(sortedRes, r.String()) 238 } 239 sort.Strings(sortedRes) 240 for i, r := range sortedRes { 241 res += r 242 if i != len(data.ActiveRoles)-1 { 243 res += "," 244 } 245 } 246 return res, false, nil 247 } 248 249 type userFunctionClass struct { 250 baseFunctionClass 251 } 252 253 func (c *userFunctionClass) getFunction(ctx stochastikctx.Context, args []Expression) (builtinFunc, error) { 254 if err := c.verifyArgs(args); err != nil { 255 return nil, err 256 } 257 bf, err := newBaseBuiltinFuncWithTp(ctx, c.funcName, args, types.ETString) 258 if err != nil { 259 return nil, err 260 } 261 bf.tp.Charset, bf.tp.DefCauslate = ctx.GetStochastikVars().GetCharsetInfo() 262 bf.tp.Flen = 64 263 sig := &builtinUserSig{bf} 264 return sig, nil 265 } 266 267 type builtinUserSig struct { 268 baseBuiltinFunc 269 } 270 271 func (b *builtinUserSig) Clone() builtinFunc { 272 newSig := &builtinUserSig{} 273 newSig.cloneFrom(&b.baseBuiltinFunc) 274 return newSig 275 } 276 277 // evalString evals a builtinUserSig. 278 // See https://dev.allegrosql.com/doc/refman/5.7/en/information-functions.html#function_user 279 func (b *builtinUserSig) evalString(event chunk.Event) (string, bool, error) { 280 data := b.ctx.GetStochastikVars() 281 if data == nil || data.User == nil { 282 return "", true, errors.Errorf("Missing stochastik variable when eval builtin") 283 } 284 285 return data.User.String(), false, nil 286 } 287 288 type connectionIDFunctionClass struct { 289 baseFunctionClass 290 } 291 292 func (c *connectionIDFunctionClass) getFunction(ctx stochastikctx.Context, args []Expression) (builtinFunc, error) { 293 if err := c.verifyArgs(args); err != nil { 294 return nil, err 295 } 296 bf, err := newBaseBuiltinFuncWithTp(ctx, c.funcName, args, types.ETInt) 297 if err != nil { 298 return nil, err 299 } 300 bf.tp.Flag |= allegrosql.UnsignedFlag 301 sig := &builtinConnectionIDSig{bf} 302 return sig, nil 303 } 304 305 type builtinConnectionIDSig struct { 306 baseBuiltinFunc 307 } 308 309 func (b *builtinConnectionIDSig) Clone() builtinFunc { 310 newSig := &builtinConnectionIDSig{} 311 newSig.cloneFrom(&b.baseBuiltinFunc) 312 return newSig 313 } 314 315 func (b *builtinConnectionIDSig) evalInt(_ chunk.Event) (int64, bool, error) { 316 data := b.ctx.GetStochastikVars() 317 if data == nil { 318 return 0, true, errors.Errorf("Missing stochastik variable `builtinConnectionIDSig.evalInt`") 319 } 320 return int64(data.ConnectionID), false, nil 321 } 322 323 type lastInsertIDFunctionClass struct { 324 baseFunctionClass 325 } 326 327 func (c *lastInsertIDFunctionClass) getFunction(ctx stochastikctx.Context, args []Expression) (sig builtinFunc, err error) { 328 if err = c.verifyArgs(args); err != nil { 329 return nil, err 330 } 331 332 var argsTp []types.EvalType 333 if len(args) == 1 { 334 argsTp = append(argsTp, types.ETInt) 335 } 336 bf, err := newBaseBuiltinFuncWithTp(ctx, c.funcName, args, types.ETInt, argsTp...) 337 if err != nil { 338 return nil, err 339 } 340 bf.tp.Flag |= allegrosql.UnsignedFlag 341 342 if len(args) == 1 { 343 sig = &builtinLastInsertIDWithIDSig{bf} 344 sig.setPbCode(fidelpb.ScalarFuncSig_LastInsertIDWithID) 345 } else { 346 sig = &builtinLastInsertIDSig{bf} 347 sig.setPbCode(fidelpb.ScalarFuncSig_LastInsertID) 348 } 349 return sig, err 350 } 351 352 type builtinLastInsertIDSig struct { 353 baseBuiltinFunc 354 } 355 356 func (b *builtinLastInsertIDSig) Clone() builtinFunc { 357 newSig := &builtinLastInsertIDSig{} 358 newSig.cloneFrom(&b.baseBuiltinFunc) 359 return newSig 360 } 361 362 // evalInt evals LAST_INSERT_ID(). 363 // See https://dev.allegrosql.com/doc/refman/5.7/en/information-functions.html#function_last-insert-id. 364 func (b *builtinLastInsertIDSig) evalInt(event chunk.Event) (res int64, isNull bool, err error) { 365 res = int64(b.ctx.GetStochastikVars().StmtCtx.PrevLastInsertID) 366 return res, false, nil 367 } 368 369 type builtinLastInsertIDWithIDSig struct { 370 baseBuiltinFunc 371 } 372 373 func (b *builtinLastInsertIDWithIDSig) Clone() builtinFunc { 374 newSig := &builtinLastInsertIDWithIDSig{} 375 newSig.cloneFrom(&b.baseBuiltinFunc) 376 return newSig 377 } 378 379 // evalInt evals LAST_INSERT_ID(expr). 380 // See https://dev.allegrosql.com/doc/refman/5.7/en/information-functions.html#function_last-insert-id. 381 func (b *builtinLastInsertIDWithIDSig) evalInt(event chunk.Event) (res int64, isNull bool, err error) { 382 res, isNull, err = b.args[0].EvalInt(b.ctx, event) 383 if isNull || err != nil { 384 return res, isNull, err 385 } 386 387 b.ctx.GetStochastikVars().SetLastInsertID(uint64(res)) 388 return res, false, nil 389 } 390 391 type versionFunctionClass struct { 392 baseFunctionClass 393 } 394 395 func (c *versionFunctionClass) getFunction(ctx stochastikctx.Context, args []Expression) (builtinFunc, error) { 396 if err := c.verifyArgs(args); err != nil { 397 return nil, err 398 } 399 bf, err := newBaseBuiltinFuncWithTp(ctx, c.funcName, args, types.ETString) 400 if err != nil { 401 return nil, err 402 } 403 bf.tp.Charset, bf.tp.DefCauslate = ctx.GetStochastikVars().GetCharsetInfo() 404 bf.tp.Flen = 64 405 sig := &builtinVersionSig{bf} 406 return sig, nil 407 } 408 409 type builtinVersionSig struct { 410 baseBuiltinFunc 411 } 412 413 func (b *builtinVersionSig) Clone() builtinFunc { 414 newSig := &builtinVersionSig{} 415 newSig.cloneFrom(&b.baseBuiltinFunc) 416 return newSig 417 } 418 419 // evalString evals a builtinVersionSig. 420 // See https://dev.allegrosql.com/doc/refman/5.7/en/information-functions.html#function_version 421 func (b *builtinVersionSig) evalString(event chunk.Event) (string, bool, error) { 422 return allegrosql.ServerVersion, false, nil 423 } 424 425 type milevadbVersionFunctionClass struct { 426 baseFunctionClass 427 } 428 429 func (c *milevadbVersionFunctionClass) getFunction(ctx stochastikctx.Context, args []Expression) (builtinFunc, error) { 430 if err := c.verifyArgs(args); err != nil { 431 return nil, err 432 } 433 bf, err := newBaseBuiltinFuncWithTp(ctx, c.funcName, args, types.ETString) 434 if err != nil { 435 return nil, err 436 } 437 bf.tp.Charset, bf.tp.DefCauslate = ctx.GetStochastikVars().GetCharsetInfo() 438 bf.tp.Flen = len(printer.GetMilevaDBInfo()) 439 sig := &builtinMilevaDBVersionSig{bf} 440 return sig, nil 441 } 442 443 type builtinMilevaDBVersionSig struct { 444 baseBuiltinFunc 445 } 446 447 func (b *builtinMilevaDBVersionSig) Clone() builtinFunc { 448 newSig := &builtinMilevaDBVersionSig{} 449 newSig.cloneFrom(&b.baseBuiltinFunc) 450 return newSig 451 } 452 453 // evalString evals a builtinMilevaDBVersionSig. 454 // This will show git hash and build time for milevadb-server. 455 func (b *builtinMilevaDBVersionSig) evalString(_ chunk.Event) (string, bool, error) { 456 return printer.GetMilevaDBInfo(), false, nil 457 } 458 459 type milevadbIsDBSTenantFunctionClass struct { 460 baseFunctionClass 461 } 462 463 func (c *milevadbIsDBSTenantFunctionClass) getFunction(ctx stochastikctx.Context, args []Expression) (builtinFunc, error) { 464 if err := c.verifyArgs(args); err != nil { 465 return nil, err 466 } 467 bf, err := newBaseBuiltinFuncWithTp(ctx, c.funcName, args, types.ETInt) 468 if err != nil { 469 return nil, err 470 } 471 sig := &builtinMilevaDBIsDBSTenantSig{bf} 472 return sig, nil 473 } 474 475 type builtinMilevaDBIsDBSTenantSig struct { 476 baseBuiltinFunc 477 } 478 479 func (b *builtinMilevaDBIsDBSTenantSig) Clone() builtinFunc { 480 newSig := &builtinMilevaDBIsDBSTenantSig{} 481 newSig.cloneFrom(&b.baseBuiltinFunc) 482 return newSig 483 } 484 485 // evalInt evals a builtinMilevaDBIsDBSTenantSig. 486 func (b *builtinMilevaDBIsDBSTenantSig) evalInt(_ chunk.Event) (res int64, isNull bool, err error) { 487 dbsTenantChecker := b.ctx.DBSTenantChecker() 488 if dbsTenantChecker.IsTenant() { 489 res = 1 490 } 491 492 return res, false, nil 493 } 494 495 type benchmarkFunctionClass struct { 496 baseFunctionClass 497 } 498 499 func (c *benchmarkFunctionClass) getFunction(ctx stochastikctx.Context, args []Expression) (builtinFunc, error) { 500 if err := c.verifyArgs(args); err != nil { 501 return nil, err 502 } 503 504 // Syntax: BENCHMARK(loop_count, memex) 505 // Define with same eval type of input arg to avoid unnecessary cast function. 506 sameEvalType := args[1].GetType().EvalType() 507 // constLoopCount is used by VecEvalInt 508 // since non-constant loop count would be different between rows, and cannot be vectorized. 509 var constLoopCount int64 510 con, ok := args[0].(*Constant) 511 if ok && con.Value.HoTT() == types.HoTTInt64 { 512 if lc, isNull, err := con.EvalInt(ctx, chunk.Event{}); err == nil && !isNull { 513 constLoopCount = lc 514 } 515 } 516 bf, err := newBaseBuiltinFuncWithTp(ctx, c.funcName, args, types.ETInt, types.ETInt, sameEvalType) 517 if err != nil { 518 return nil, err 519 } 520 sig := &builtinBenchmarkSig{bf, constLoopCount} 521 return sig, nil 522 } 523 524 type builtinBenchmarkSig struct { 525 baseBuiltinFunc 526 constLoopCount int64 527 } 528 529 func (b *builtinBenchmarkSig) Clone() builtinFunc { 530 newSig := &builtinBenchmarkSig{constLoopCount: b.constLoopCount} 531 newSig.cloneFrom(&b.baseBuiltinFunc) 532 return newSig 533 } 534 535 // evalInt evals a builtinBenchmarkSig. It will execute memex repeatedly count times. 536 // See https://dev.allegrosql.com/doc/refman/5.7/en/information-functions.html#function_benchmark 537 func (b *builtinBenchmarkSig) evalInt(event chunk.Event) (int64, bool, error) { 538 // Get loop count. 539 var loopCount int64 540 var isNull bool 541 var err error 542 if b.constLoopCount > 0 { 543 loopCount = b.constLoopCount 544 } else { 545 loopCount, isNull, err = b.args[0].EvalInt(b.ctx, event) 546 if isNull || err != nil { 547 return 0, isNull, err 548 } 549 } 550 551 // BENCHMARK() will return NULL if loop count < 0, 552 // behavior observed on MyALLEGROSQL 5.7.24. 553 if loopCount < 0 { 554 return 0, true, nil 555 } 556 557 // Eval loop count times based on arg type. 558 // BENCHMARK() will pass-through the eval error, 559 // behavior observed on MyALLEGROSQL 5.7.24. 560 var i int64 561 arg, ctx := b.args[1], b.ctx 562 switch evalType := arg.GetType().EvalType(); evalType { 563 case types.ETInt: 564 for ; i < loopCount; i++ { 565 _, isNull, err = arg.EvalInt(ctx, event) 566 if err != nil { 567 return 0, isNull, err 568 } 569 } 570 case types.ETReal: 571 for ; i < loopCount; i++ { 572 _, isNull, err = arg.EvalReal(ctx, event) 573 if err != nil { 574 return 0, isNull, err 575 } 576 } 577 case types.ETDecimal: 578 for ; i < loopCount; i++ { 579 _, isNull, err = arg.EvalDecimal(ctx, event) 580 if err != nil { 581 return 0, isNull, err 582 } 583 } 584 case types.ETString: 585 for ; i < loopCount; i++ { 586 _, isNull, err = arg.EvalString(ctx, event) 587 if err != nil { 588 return 0, isNull, err 589 } 590 } 591 case types.ETDatetime, types.ETTimestamp: 592 for ; i < loopCount; i++ { 593 _, isNull, err = arg.EvalTime(ctx, event) 594 if err != nil { 595 return 0, isNull, err 596 } 597 } 598 case types.ETDuration: 599 for ; i < loopCount; i++ { 600 _, isNull, err = arg.EvalDuration(ctx, event) 601 if err != nil { 602 return 0, isNull, err 603 } 604 } 605 case types.ETJson: 606 for ; i < loopCount; i++ { 607 _, isNull, err = arg.EvalJSON(ctx, event) 608 if err != nil { 609 return 0, isNull, err 610 } 611 } 612 default: // Should never go into here. 613 return 0, true, errors.Errorf("EvalType %v not implemented for builtin BENCHMARK()", evalType) 614 } 615 616 // Return value of BENCHMARK() is always 0. 617 return 0, false, nil 618 } 619 620 type charsetFunctionClass struct { 621 baseFunctionClass 622 } 623 624 func (c *charsetFunctionClass) getFunction(ctx stochastikctx.Context, args []Expression) (builtinFunc, error) { 625 return nil, errFunctionNotExists.GenWithStackByArgs("FUNCTION", "CHARSET") 626 } 627 628 type coercibilityFunctionClass struct { 629 baseFunctionClass 630 } 631 632 func (c *coercibilityFunctionClass) getFunction(ctx stochastikctx.Context, args []Expression) (builtinFunc, error) { 633 if err := c.verifyArgs(args); err != nil { 634 return nil, err 635 } 636 bf, err := newBaseBuiltinFuncWithTp(ctx, c.funcName, args, types.ETInt, args[0].GetType().EvalType()) 637 if err != nil { 638 return nil, err 639 } 640 sig := &builtinCoercibilitySig{bf} 641 sig.setPbCode(fidelpb.ScalarFuncSig_Unspecified) 642 return sig, nil 643 } 644 645 type builtinCoercibilitySig struct { 646 baseBuiltinFunc 647 } 648 649 func (c *builtinCoercibilitySig) evalInt(_ chunk.Event) (res int64, isNull bool, err error) { 650 return int64(c.args[0].Coercibility()), false, nil 651 } 652 653 func (c *builtinCoercibilitySig) Clone() builtinFunc { 654 newSig := &builtinCoercibilitySig{} 655 newSig.cloneFrom(&c.baseBuiltinFunc) 656 return newSig 657 } 658 659 type defCauslationFunctionClass struct { 660 baseFunctionClass 661 } 662 663 func (c *defCauslationFunctionClass) getFunction(ctx stochastikctx.Context, args []Expression) (builtinFunc, error) { 664 if err := c.verifyArgs(args); err != nil { 665 return nil, err 666 } 667 argsTps := make([]types.EvalType, 0, len(args)) 668 for _, arg := range args { 669 argsTps = append(argsTps, arg.GetType().EvalType()) 670 } 671 bf, err := newBaseBuiltinFuncWithTp(ctx, c.funcName, args, types.ETString, argsTps...) 672 if err != nil { 673 return nil, err 674 } 675 bf.tp.Charset, bf.tp.DefCauslate = ctx.GetStochastikVars().GetCharsetInfo() 676 sig := &builtinDefCauslationSig{bf} 677 return sig, nil 678 } 679 680 type builtinDefCauslationSig struct { 681 baseBuiltinFunc 682 } 683 684 func (b *builtinDefCauslationSig) Clone() builtinFunc { 685 newSig := &builtinDefCauslationSig{} 686 newSig.cloneFrom(&b.baseBuiltinFunc) 687 return newSig 688 } 689 690 func (b *builtinDefCauslationSig) evalString(_ chunk.Event) (string, bool, error) { 691 return b.args[0].GetType().DefCauslate, false, nil 692 } 693 694 type rowCountFunctionClass struct { 695 baseFunctionClass 696 } 697 698 func (c *rowCountFunctionClass) getFunction(ctx stochastikctx.Context, args []Expression) (sig builtinFunc, err error) { 699 if err = c.verifyArgs(args); err != nil { 700 return nil, err 701 } 702 bf, err := newBaseBuiltinFuncWithTp(ctx, c.funcName, args, types.ETInt) 703 if err != nil { 704 return nil, err 705 } 706 sig = &builtinEventCountSig{bf} 707 sig.setPbCode(fidelpb.ScalarFuncSig_EventCount) 708 return sig, nil 709 } 710 711 type builtinEventCountSig struct { 712 baseBuiltinFunc 713 } 714 715 func (b *builtinEventCountSig) Clone() builtinFunc { 716 newSig := &builtinEventCountSig{} 717 newSig.cloneFrom(&b.baseBuiltinFunc) 718 return newSig 719 } 720 721 // evalInt evals ROW_COUNT(). 722 // See https://dev.allegrosql.com/doc/refman/5.7/en/information-functions.html#function_row-count. 723 func (b *builtinEventCountSig) evalInt(_ chunk.Event) (res int64, isNull bool, err error) { 724 res = b.ctx.GetStochastikVars().StmtCtx.PrevAffectedEvents 725 return res, false, nil 726 } 727 728 type milevadbDecodeKeyFunctionClass struct { 729 baseFunctionClass 730 } 731 732 func (c *milevadbDecodeKeyFunctionClass) getFunction(ctx stochastikctx.Context, args []Expression) (builtinFunc, error) { 733 if err := c.verifyArgs(args); err != nil { 734 return nil, err 735 } 736 bf, err := newBaseBuiltinFuncWithTp(ctx, c.funcName, args, types.ETString, types.ETString) 737 if err != nil { 738 return nil, err 739 } 740 sig := &builtinMilevaDBDecodeKeySig{bf} 741 return sig, nil 742 } 743 744 type builtinMilevaDBDecodeKeySig struct { 745 baseBuiltinFunc 746 } 747 748 func (b *builtinMilevaDBDecodeKeySig) Clone() builtinFunc { 749 newSig := &builtinMilevaDBDecodeKeySig{} 750 newSig.cloneFrom(&b.baseBuiltinFunc) 751 return newSig 752 } 753 754 // evalInt evals a builtinMilevaDBIsDBSTenantSig. 755 func (b *builtinMilevaDBDecodeKeySig) evalString(event chunk.Event) (string, bool, error) { 756 s, isNull, err := b.args[0].EvalString(b.ctx, event) 757 if isNull || err != nil { 758 return "", isNull, err 759 } 760 return decodeKey(b.ctx, s), false, nil 761 } 762 763 func decodeKey(ctx stochastikctx.Context, s string) string { 764 key, err := hex.DecodeString(s) 765 if err != nil { 766 ctx.GetStochastikVars().StmtCtx.AppendWarning(errors.Errorf("invalid record/index key: %X", key)) 767 return s 768 } 769 // Auto decode byte if needed. 770 _, bs, err := codec.DecodeBytes(key, nil) 771 if err == nil { 772 key = bs 773 } 774 // Try to decode it as a record key. 775 blockID, handle, err := blockcodec.DecodeRecordKey(key) 776 if err == nil { 777 if handle.IsInt() { 778 return "blockID=" + strconv.FormatInt(blockID, 10) + ", _milevadb_rowid=" + strconv.FormatInt(handle.IntValue(), 10) 779 } 780 return "blockID=" + strconv.FormatInt(blockID, 10) + ", clusterHandle=" + handle.String() 781 } 782 // Try decode as causet index key. 783 blockID, indexID, indexValues, err := blockcodec.DecodeIndexKey(key) 784 if err == nil { 785 return "blockID=" + strconv.FormatInt(blockID, 10) + ", indexID=" + strconv.FormatInt(indexID, 10) + ", indexValues=" + strings.Join(indexValues, ",") 786 } 787 // TODO: try to decode other type key. 788 ctx.GetStochastikVars().StmtCtx.AppendWarning(errors.Errorf("invalid record/index key: %X", key)) 789 return s 790 } 791 792 type milevadbDecodeCausetFunctionClass struct { 793 baseFunctionClass 794 } 795 796 func (c *milevadbDecodeCausetFunctionClass) getFunction(ctx stochastikctx.Context, args []Expression) (builtinFunc, error) { 797 if err := c.verifyArgs(args); err != nil { 798 return nil, err 799 } 800 bf, err := newBaseBuiltinFuncWithTp(ctx, c.funcName, args, types.ETString, types.ETString) 801 if err != nil { 802 return nil, err 803 } 804 sig := &builtinMilevaDBDecodeCausetSig{bf} 805 return sig, nil 806 } 807 808 type builtinMilevaDBDecodeCausetSig struct { 809 baseBuiltinFunc 810 } 811 812 func (b *builtinMilevaDBDecodeCausetSig) Clone() builtinFunc { 813 newSig := &builtinMilevaDBDecodeCausetSig{} 814 newSig.cloneFrom(&b.baseBuiltinFunc) 815 return newSig 816 } 817 818 func (b *builtinMilevaDBDecodeCausetSig) evalString(event chunk.Event) (string, bool, error) { 819 planString, isNull, err := b.args[0].EvalString(b.ctx, event) 820 if isNull || err != nil { 821 return "", isNull, err 822 } 823 planTree, err := plancodec.DecodeCauset(planString) 824 return planTree, false, err 825 } 826 827 type nextValFunctionClass struct { 828 baseFunctionClass 829 } 830 831 func (c *nextValFunctionClass) getFunction(ctx stochastikctx.Context, args []Expression) (builtinFunc, error) { 832 if err := c.verifyArgs(args); err != nil { 833 return nil, err 834 } 835 bf, err := newBaseBuiltinFuncWithTp(ctx, c.funcName, args, types.ETInt, types.ETString) 836 if err != nil { 837 return nil, err 838 } 839 sig := &builtinNextValSig{bf} 840 bf.tp.Flen = 10 841 return sig, nil 842 } 843 844 type builtinNextValSig struct { 845 baseBuiltinFunc 846 } 847 848 func (b *builtinNextValSig) Clone() builtinFunc { 849 newSig := &builtinNextValSig{} 850 newSig.cloneFrom(&b.baseBuiltinFunc) 851 return newSig 852 } 853 854 func (b *builtinNextValSig) evalInt(event chunk.Event) (int64, bool, error) { 855 sequenceName, isNull, err := b.args[0].EvalString(b.ctx, event) 856 if isNull || err != nil { 857 return 0, isNull, err 858 } 859 EDB, seq := getSchemaAndSequence(sequenceName) 860 if len(EDB) == 0 { 861 EDB = b.ctx.GetStochastikVars().CurrentDB 862 } 863 // Check the blockName valid. 864 sequence, err := b.ctx.GetStochastikVars().TxnCtx.SchemaReplicant.(soliton.SequenceSchema).SequenceByName(perceptron.NewCIStr(EDB), perceptron.NewCIStr(seq)) 865 if err != nil { 866 return 0, false, err 867 } 868 // Do the privilege check. 869 checker := privilege.GetPrivilegeManager(b.ctx) 870 user := b.ctx.GetStochastikVars().User 871 if checker != nil && !checker.RequestVerification(b.ctx.GetStochastikVars().ActiveRoles, EDB, seq, "", allegrosql.InsertPriv) { 872 return 0, false, errSequenceAccessDenied.GenWithStackByArgs("INSERT", user.AuthUsername, user.AuthHostname, seq) 873 } 874 nextVal, err := sequence.GetSequenceNextVal(b.ctx, EDB, seq) 875 if err != nil { 876 return 0, false, err 877 } 878 // uFIDelate the sequenceState. 879 b.ctx.GetStochastikVars().SequenceState.UFIDelateState(sequence.GetSequenceID(), nextVal) 880 return nextVal, false, nil 881 } 882 883 type lastValFunctionClass struct { 884 baseFunctionClass 885 } 886 887 func (c *lastValFunctionClass) getFunction(ctx stochastikctx.Context, args []Expression) (builtinFunc, error) { 888 if err := c.verifyArgs(args); err != nil { 889 return nil, err 890 } 891 bf, err := newBaseBuiltinFuncWithTp(ctx, c.funcName, args, types.ETInt, types.ETString) 892 if err != nil { 893 return nil, err 894 } 895 sig := &builtinLastValSig{bf} 896 bf.tp.Flen = 10 897 return sig, nil 898 } 899 900 type builtinLastValSig struct { 901 baseBuiltinFunc 902 } 903 904 func (b *builtinLastValSig) Clone() builtinFunc { 905 newSig := &builtinLastValSig{} 906 newSig.cloneFrom(&b.baseBuiltinFunc) 907 return newSig 908 } 909 910 func (b *builtinLastValSig) evalInt(event chunk.Event) (int64, bool, error) { 911 sequenceName, isNull, err := b.args[0].EvalString(b.ctx, event) 912 if isNull || err != nil { 913 return 0, isNull, err 914 } 915 EDB, seq := getSchemaAndSequence(sequenceName) 916 if len(EDB) == 0 { 917 EDB = b.ctx.GetStochastikVars().CurrentDB 918 } 919 // Check the blockName valid. 920 sequence, err := b.ctx.GetStochastikVars().TxnCtx.SchemaReplicant.(soliton.SequenceSchema).SequenceByName(perceptron.NewCIStr(EDB), perceptron.NewCIStr(seq)) 921 if err != nil { 922 return 0, false, err 923 } 924 // Do the privilege check. 925 checker := privilege.GetPrivilegeManager(b.ctx) 926 user := b.ctx.GetStochastikVars().User 927 if checker != nil && !checker.RequestVerification(b.ctx.GetStochastikVars().ActiveRoles, EDB, seq, "", allegrosql.SelectPriv) { 928 return 0, false, errSequenceAccessDenied.GenWithStackByArgs("SELECT", user.AuthUsername, user.AuthHostname, seq) 929 } 930 return b.ctx.GetStochastikVars().SequenceState.GetLastValue(sequence.GetSequenceID()) 931 } 932 933 type setValFunctionClass struct { 934 baseFunctionClass 935 } 936 937 func (c *setValFunctionClass) getFunction(ctx stochastikctx.Context, args []Expression) (builtinFunc, error) { 938 if err := c.verifyArgs(args); err != nil { 939 return nil, err 940 } 941 bf, err := newBaseBuiltinFuncWithTp(ctx, c.funcName, args, types.ETInt, types.ETString, types.ETInt) 942 if err != nil { 943 return nil, err 944 } 945 sig := &builtinSetValSig{bf} 946 bf.tp.Flen = args[1].GetType().Flen 947 return sig, nil 948 } 949 950 type builtinSetValSig struct { 951 baseBuiltinFunc 952 } 953 954 func (b *builtinSetValSig) Clone() builtinFunc { 955 newSig := &builtinSetValSig{} 956 newSig.cloneFrom(&b.baseBuiltinFunc) 957 return newSig 958 } 959 960 func (b *builtinSetValSig) evalInt(event chunk.Event) (int64, bool, error) { 961 sequenceName, isNull, err := b.args[0].EvalString(b.ctx, event) 962 if isNull || err != nil { 963 return 0, isNull, err 964 } 965 EDB, seq := getSchemaAndSequence(sequenceName) 966 if len(EDB) == 0 { 967 EDB = b.ctx.GetStochastikVars().CurrentDB 968 } 969 // Check the blockName valid. 970 sequence, err := b.ctx.GetStochastikVars().TxnCtx.SchemaReplicant.(soliton.SequenceSchema).SequenceByName(perceptron.NewCIStr(EDB), perceptron.NewCIStr(seq)) 971 if err != nil { 972 return 0, false, err 973 } 974 // Do the privilege check. 975 checker := privilege.GetPrivilegeManager(b.ctx) 976 user := b.ctx.GetStochastikVars().User 977 if checker != nil && !checker.RequestVerification(b.ctx.GetStochastikVars().ActiveRoles, EDB, seq, "", allegrosql.InsertPriv) { 978 return 0, false, errSequenceAccessDenied.GenWithStackByArgs("INSERT", user.AuthUsername, user.AuthHostname, seq) 979 } 980 setValue, isNull, err := b.args[1].EvalInt(b.ctx, event) 981 if isNull || err != nil { 982 return 0, isNull, err 983 } 984 return sequence.SetSequenceVal(b.ctx, setValue, EDB, seq) 985 } 986 987 func getSchemaAndSequence(sequenceName string) (string, string) { 988 res := strings.Split(sequenceName, ".") 989 if len(res) == 1 { 990 return "", res[0] 991 } 992 return res[0], res[1] 993 } 994 995 type formatBytesFunctionClass struct { 996 baseFunctionClass 997 } 998 999 func (c *formatBytesFunctionClass) getFunction(ctx stochastikctx.Context, args []Expression) (builtinFunc, error) { 1000 if err := c.verifyArgs(args); err != nil { 1001 return nil, err 1002 } 1003 bf, err := newBaseBuiltinFuncWithTp(ctx, c.funcName, args, types.ETString, types.ETReal) 1004 if err != nil { 1005 return nil, err 1006 } 1007 bf.tp.Flag |= allegrosql.UnsignedFlag 1008 sig := &builtinFormatBytesSig{bf} 1009 return sig, nil 1010 } 1011 1012 type builtinFormatBytesSig struct { 1013 baseBuiltinFunc 1014 } 1015 1016 func (b *builtinFormatBytesSig) Clone() builtinFunc { 1017 newSig := &builtinFormatBytesSig{} 1018 newSig.cloneFrom(&b.baseBuiltinFunc) 1019 return newSig 1020 } 1021 1022 // formatBytes evals a builtinFormatBytesSig. 1023 // See https://dev.allegrosql.com/doc/refman/8.0/en/performance-schemaReplicant-functions.html#function_format-bytes 1024 func (b *builtinFormatBytesSig) evalString(event chunk.Event) (string, bool, error) { 1025 val, isNull, err := b.args[0].EvalReal(b.ctx, event) 1026 if isNull || err != nil { 1027 return "", isNull, err 1028 } 1029 return GetFormatBytes(val), false, nil 1030 } 1031 1032 type formatNanoTimeFunctionClass struct { 1033 baseFunctionClass 1034 } 1035 1036 func (c *formatNanoTimeFunctionClass) getFunction(ctx stochastikctx.Context, args []Expression) (builtinFunc, error) { 1037 if err := c.verifyArgs(args); err != nil { 1038 return nil, err 1039 } 1040 bf, err := newBaseBuiltinFuncWithTp(ctx, c.funcName, args, types.ETString, types.ETReal) 1041 if err != nil { 1042 return nil, err 1043 } 1044 bf.tp.Flag |= allegrosql.UnsignedFlag 1045 sig := &builtinFormatNanoTimeSig{bf} 1046 return sig, nil 1047 } 1048 1049 type builtinFormatNanoTimeSig struct { 1050 baseBuiltinFunc 1051 } 1052 1053 func (b *builtinFormatNanoTimeSig) Clone() builtinFunc { 1054 newSig := &builtinFormatNanoTimeSig{} 1055 newSig.cloneFrom(&b.baseBuiltinFunc) 1056 return newSig 1057 } 1058 1059 // formatNanoTime evals a builtinFormatNanoTimeSig, as time unit in MilevaDB is always nanosecond, not picosecond. 1060 // See https://dev.allegrosql.com/doc/refman/8.0/en/performance-schemaReplicant-functions.html#function_format-pico-time 1061 func (b *builtinFormatNanoTimeSig) evalString(event chunk.Event) (string, bool, error) { 1062 val, isNull, err := b.args[0].EvalReal(b.ctx, event) 1063 if isNull || err != nil { 1064 return "", isNull, err 1065 } 1066 return GetFormatNanoTime(val), false, nil 1067 }