github.com/matrixorigin/matrixone@v0.7.0/pkg/frontend/variables.go (about) 1 // Copyright 2022 Matrix Origin 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 // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 12 // See the License for the specific language governing permissions and 13 // limitations under the License. 14 15 package frontend 16 17 import ( 18 "context" 19 "fmt" 20 "math" 21 bits2 "math/bits" 22 "strconv" 23 "strings" 24 "sync" 25 "time" 26 27 "github.com/matrixorigin/matrixone/pkg/common/moerr" 28 "github.com/matrixorigin/matrixone/pkg/container/types" 29 "github.com/matrixorigin/matrixone/pkg/defines" 30 ) 31 32 var ( 33 errorConvertToBoolFailed = moerr.NewInternalError(context.Background(), "convert to the system variable bool type failed") 34 errorConvertToIntFailed = moerr.NewInternalError(context.Background(), "convert to the system variable int type failed") 35 errorConvertToUintFailed = moerr.NewInternalError(context.Background(), "convert to the system variable uint type failed") 36 errorConvertToDoubleFailed = moerr.NewInternalError(context.Background(), "convert to the system variable double type failed") 37 errorConvertToEnumFailed = moerr.NewInternalError(context.Background(), "convert to the system variable enum type failed") 38 errorConvertToSetFailed = moerr.NewInternalError(context.Background(), "convert to the system variable set type failed") 39 errorConvertToStringFailed = moerr.NewInternalError(context.Background(), "convert to the system variable string type failed") 40 errorConvertToNullFailed = moerr.NewInternalError(context.Background(), "convert to the system variable null type failed") 41 ) 42 43 func errorSystemVariableDoesNotExist() string { return "the system variable does not exist" } 44 func errorSystemVariableIsSession() string { return "the system variable is session" } 45 func errorSystemVariableSessionEmpty() string { 46 return "the value of the system variable with scope session is empty" 47 } 48 func errorSystemVariableIsGlobal() string { return "the system variable is global" } 49 func errorSystemVariableIsReadOnly() string { return "the system variable is read only" } 50 51 type Scope int 52 53 const ( 54 ScopeGlobal Scope = iota //it is only in global 55 ScopeSession //it is only in session 56 ScopeBoth //it is both in global and session 57 ScopePersist //it is global and persisted 58 ScopePersistOnly //it is persisted without updating global and session values 59 ScopeResetPersist //to remove a persisted variable 60 ) 61 62 func (s Scope) String() string { 63 switch s { 64 case ScopeGlobal: 65 return "GLOBAL" 66 case ScopeSession: 67 return "SESSION" 68 case ScopeBoth: 69 return "GLOBAL, SESSION" 70 case ScopePersist: 71 return "GLOBAL, PERSIST" 72 case ScopePersistOnly: 73 return "PERSIST" 74 case ScopeResetPersist: 75 return "RESET PERSIST" 76 default: 77 return "UNKNOWN_SYSTEM_SCOPE" 78 } 79 } 80 81 type SystemVariableType interface { 82 fmt.Stringer 83 84 // Convert the value to another value of the type 85 Convert(value interface{}) (interface{}, error) 86 87 // Type gets the type in the computation engine 88 Type() types.T 89 90 // MysqlType gets the mysql type 91 MysqlType() defines.MysqlType 92 93 // Zero gets the zero value for the type 94 Zero() interface{} 95 } 96 97 var _ SystemVariableType = SystemVariableBoolType{} 98 var _ SystemVariableType = SystemVariableIntType{} 99 var _ SystemVariableType = SystemVariableUintType{} 100 var _ SystemVariableType = SystemVariableDoubleType{} 101 var _ SystemVariableType = SystemVariableEnumType{} 102 var _ SystemVariableType = SystemVariableSetType{} 103 var _ SystemVariableType = SystemVariableStringType{} 104 var _ SystemVariableType = SystemVariableNullType{} 105 106 type SystemVariableNullType struct { 107 } 108 109 func (svnt SystemVariableNullType) String() string { 110 return "NULL" 111 } 112 113 func (svnt SystemVariableNullType) Convert(value interface{}) (interface{}, error) { 114 if value != nil { 115 return nil, errorConvertToNullFailed 116 } 117 return nil, nil 118 } 119 120 func (svnt SystemVariableNullType) Type() types.T { 121 return types.T_any 122 } 123 124 func (svnt SystemVariableNullType) MysqlType() defines.MysqlType { 125 return defines.MYSQL_TYPE_NULL 126 } 127 128 func (svnt SystemVariableNullType) Zero() interface{} { 129 return nil 130 } 131 132 type SystemVariableBoolType struct { 133 name string 134 } 135 136 func InitSystemVariableBoolType(name string) SystemVariableBoolType { 137 return SystemVariableBoolType{ 138 name: name, 139 } 140 } 141 142 func (svbt SystemVariableBoolType) String() string { 143 return "BOOL" 144 } 145 146 func (svbt SystemVariableBoolType) Convert(value interface{}) (interface{}, error) { 147 cv1 := func(x int8) (interface{}, error) { 148 if x == 0 || x == 1 { 149 return x, nil 150 } 151 return nil, errorConvertToBoolFailed 152 } 153 cv2 := func(x float64) (interface{}, error) { 154 xx := int64(x) 155 rxx := float64(xx) 156 if x == rxx { 157 return cv1(int8(xx)) 158 } 159 return nil, errorConvertToBoolFailed 160 } 161 cv3 := func(x string) (interface{}, error) { 162 switch strings.ToLower(x) { 163 case "on", "true": 164 return int8(1), nil 165 case "off", "false": 166 return int8(0), nil 167 } 168 return nil, errorConvertToBoolFailed 169 } 170 switch v := value.(type) { 171 case int: 172 return cv1(int8(v)) 173 case uint: 174 return cv1(int8(v)) 175 case int8: 176 return cv1(v) 177 case int16: 178 return cv1(int8(v)) 179 case uint16: 180 return cv1(int8(v)) 181 case int32: 182 return cv1(int8(v)) 183 case uint32: 184 return cv1(int8(v)) 185 case int64: 186 return cv1(int8(v)) 187 case uint64: 188 return cv1(int8(v)) 189 case bool: 190 if v { 191 return int8(1), nil 192 } else { 193 return int8(0), nil 194 } 195 case float32: 196 return cv2(float64(v)) 197 case float64: 198 return cv2(v) 199 case string: 200 return cv3(v) 201 } 202 return nil, errorConvertToBoolFailed 203 } 204 205 func (svbt SystemVariableBoolType) IsTrue(v interface{}) bool { 206 if vv, ok := v.(int8); ok { 207 return vv == int8(1) 208 } else if vv3, ok3 := v.(int64); ok3 { 209 return vv3 == int64(1) 210 } else if vv2, ok2 := v.(string); ok2 { 211 return strings.ToLower(vv2) == "on" 212 } 213 return false 214 } 215 216 func (svbt SystemVariableBoolType) Type() types.T { 217 return types.T_bool 218 } 219 220 func (svbt SystemVariableBoolType) MysqlType() defines.MysqlType { 221 return defines.MYSQL_TYPE_BOOL 222 } 223 224 func (svbt SystemVariableBoolType) Zero() interface{} { 225 return int8(0) 226 } 227 228 type SystemVariableIntType struct { 229 name string 230 minimum int64 231 maximum int64 232 //-1 ? 233 maybeMinusOne bool 234 } 235 236 func InitSystemVariableIntType(name string, minimum, maximum int64, maybeMinusOne bool) SystemVariableIntType { 237 return SystemVariableIntType{ 238 name: name, 239 minimum: minimum, 240 maximum: maximum, 241 maybeMinusOne: maybeMinusOne, 242 } 243 } 244 245 func (svit SystemVariableIntType) String() string { 246 return "INT" 247 } 248 249 func (svit SystemVariableIntType) Convert(value interface{}) (interface{}, error) { 250 cv1 := func(x int64) (interface{}, error) { 251 if x >= svit.minimum && x <= svit.maximum { 252 return x, nil 253 } else if svit.maybeMinusOne && x == -1 { 254 return x, nil 255 } 256 return nil, errorConvertToIntFailed 257 } 258 cv2 := func(x float64) (interface{}, error) { 259 xx := int64(x) 260 rxx := float64(xx) 261 if x == rxx { 262 return cv1(xx) 263 } 264 return nil, errorConvertToIntFailed 265 } 266 267 switch v := value.(type) { 268 case int: 269 return cv1(int64(v)) 270 case uint: 271 return cv1(int64(v)) 272 case int8: 273 return cv1(int64(v)) 274 case uint8: 275 return cv1(int64(v)) 276 case int16: 277 return cv1(int64(v)) 278 case uint16: 279 return cv1(int64(v)) 280 case int32: 281 return cv1(int64(v)) 282 case uint32: 283 return cv1(int64(v)) 284 case int64: 285 return cv1(v) 286 case uint64: 287 return cv1(int64(v)) 288 case float32: 289 return cv2(float64(v)) 290 case float64: 291 return cv2(v) 292 } 293 return nil, errorConvertToIntFailed 294 } 295 296 func (svit SystemVariableIntType) Type() types.T { 297 return types.T_int64 298 } 299 300 func (svit SystemVariableIntType) MysqlType() defines.MysqlType { 301 return defines.MYSQL_TYPE_LONGLONG 302 } 303 304 func (svit SystemVariableIntType) Zero() interface{} { 305 return int64(0) 306 } 307 308 type SystemVariableUintType struct { 309 name string 310 minimum uint64 311 maximum uint64 312 } 313 314 func InitSystemVariableUintType(name string, minimum, maximum uint64) SystemVariableUintType { 315 return SystemVariableUintType{ 316 name: name, 317 minimum: minimum, 318 maximum: maximum, 319 } 320 } 321 322 func (svut SystemVariableUintType) String() string { 323 return "UINT" 324 } 325 326 func (svut SystemVariableUintType) Convert(value interface{}) (interface{}, error) { 327 cv1 := func(x uint64) (interface{}, error) { 328 if x >= svut.minimum && x <= svut.maximum { 329 return x, nil 330 } 331 return nil, errorConvertToUintFailed 332 } 333 cv2 := func(x float64) (interface{}, error) { 334 xx := uint64(x) 335 rxx := float64(xx) 336 if x == rxx { 337 return cv1(xx) 338 } 339 return nil, errorConvertToUintFailed 340 } 341 342 switch v := value.(type) { 343 case int: 344 return cv1(uint64(v)) 345 case uint: 346 return cv1(uint64(v)) 347 case int8: 348 return cv1(uint64(v)) 349 case uint8: 350 return cv1(uint64(v)) 351 case int16: 352 return cv1(uint64(v)) 353 case uint16: 354 return cv1(uint64(v)) 355 case int32: 356 return cv1(uint64(v)) 357 case uint32: 358 return cv1(uint64(v)) 359 case int64: 360 return cv1(uint64(v)) 361 case uint64: 362 return cv1(v) 363 case float32: 364 return cv2(float64(v)) 365 case float64: 366 return cv2(v) 367 } 368 return nil, errorConvertToUintFailed 369 } 370 371 func (svut SystemVariableUintType) Type() types.T { 372 return types.T_uint64 373 } 374 375 func (svut SystemVariableUintType) MysqlType() defines.MysqlType { 376 return defines.MYSQL_TYPE_LONGLONG 377 } 378 379 func (svut SystemVariableUintType) Zero() interface{} { 380 return uint64(0) 381 } 382 383 type SystemVariableDoubleType struct { 384 // Unused 385 // name string 386 minimum float64 387 maximum float64 388 } 389 390 func (svdt SystemVariableDoubleType) String() string { 391 return "DOUBLE" 392 } 393 394 func (svdt SystemVariableDoubleType) Convert(value interface{}) (interface{}, error) { 395 cv1 := func(x float64) (interface{}, error) { 396 if x >= svdt.minimum && x <= svdt.maximum { 397 return x, nil 398 } 399 return nil, errorConvertToUintFailed 400 } 401 402 switch v := value.(type) { 403 case int: 404 return cv1(float64(v)) 405 case uint: 406 return cv1(float64(v)) 407 case int8: 408 return cv1(float64(v)) 409 case uint8: 410 return cv1(float64(v)) 411 case int16: 412 return cv1(float64(v)) 413 case uint16: 414 return cv1(float64(v)) 415 case int32: 416 return cv1(float64(v)) 417 case uint32: 418 return cv1(float64(v)) 419 case int64: 420 return cv1(float64(v)) 421 case uint64: 422 return cv1(float64(v)) 423 case float32: 424 return cv1(float64(v)) 425 case float64: 426 return cv1(v) 427 } 428 return nil, errorConvertToDoubleFailed 429 } 430 431 func (svdt SystemVariableDoubleType) Type() types.T { 432 return types.T_float64 433 } 434 435 func (svdt SystemVariableDoubleType) MysqlType() defines.MysqlType { 436 return defines.MYSQL_TYPE_DOUBLE 437 } 438 439 func (svdt SystemVariableDoubleType) Zero() interface{} { 440 return float64(0) 441 } 442 443 var ( 444 // panic 445 errorEnumHasMoreThan65535Values = moerr.NewInternalError(context.Background(), "the enum has more than 65535 values") 446 ) 447 448 type SystemVariableEnumType struct { 449 name string 450 //tag name -> id 451 tagName2Id map[string]int 452 453 // id -> tag name 454 id2TagName []string 455 } 456 457 func InitSystemSystemEnumType(name string, values ...string) SystemVariableEnumType { 458 if len(values) > 65535 { 459 panic(errorEnumHasMoreThan65535Values) 460 } 461 tagName2Id := make(map[string]int) 462 for i, value := range values { 463 tagName2Id[strings.ToLower(value)] = i 464 } 465 return SystemVariableEnumType{ 466 name: name, 467 tagName2Id: tagName2Id, 468 id2TagName: values, 469 } 470 } 471 472 func (svet SystemVariableEnumType) String() string { 473 return "ENUM" 474 } 475 476 func (svet SystemVariableEnumType) Convert(value interface{}) (interface{}, error) { 477 cv1 := func(x int) (interface{}, error) { 478 if x >= 0 && x <= len(svet.id2TagName) { 479 return svet.id2TagName[x], nil 480 } 481 return nil, errorConvertToEnumFailed 482 } 483 cv2 := func(x float64) (interface{}, error) { 484 xx := int(x) 485 rxx := float64(xx) 486 if x == rxx { 487 return cv1(xx) 488 } 489 return nil, errorConvertToUintFailed 490 } 491 492 switch v := value.(type) { 493 case int: 494 return cv1(v) 495 case uint: 496 return cv1(int(v)) 497 case int8: 498 return cv1(int(v)) 499 case uint8: 500 return cv1(int(v)) 501 case int16: 502 return cv1(int(v)) 503 case uint16: 504 return cv1(int(v)) 505 case int32: 506 return cv1(int(v)) 507 case uint32: 508 return cv1(int(v)) 509 case int64: 510 return cv1(int(v)) 511 case uint64: 512 return cv1(int(v)) 513 case float32: 514 return cv2(float64(v)) 515 case float64: 516 return cv2(v) 517 case string: 518 if id, ok := svet.tagName2Id[strings.ToLower(v)]; ok { 519 return svet.id2TagName[id], nil 520 } 521 } 522 return nil, errorConvertToEnumFailed 523 } 524 525 func (svet SystemVariableEnumType) Type() types.T { 526 return types.T_varchar 527 } 528 529 func (svet SystemVariableEnumType) MysqlType() defines.MysqlType { 530 return defines.MYSQL_TYPE_VARCHAR 531 } 532 533 func (svet SystemVariableEnumType) Zero() interface{} { 534 return "" 535 } 536 537 const ( 538 //reference : https://dev.mysql.com/doc/refman/8.0/en/storage-requirements.html#data-types-storage-reqs-strings 539 MaxMemberCountOfSetType = 64 540 ) 541 542 var ( 543 // panic error 544 errorValuesOfSetIsEmpty = moerr.NewInternalError(context.Background(), "the count of values for set is empty") 545 errorValuesOfSetGreaterThan64 = moerr.NewInternalError(context.Background(), "the count of value is greater than 64") 546 errorValueHasComma = moerr.NewInternalError(context.Background(), "the value has the comma") 547 errorValueIsDuplicate = moerr.NewInternalError(context.Background(), "the value is duplicate") 548 errorValuesAreNotEnough = moerr.NewInternalError(context.Background(), "values are not enough") // convert 549 errorValueIsInvalid = moerr.NewInternalError(context.Background(), "the value is invalid") // convert 550 ) 551 552 type SystemVariableSetType struct { 553 // name string 554 normalized2original map[string]string 555 value2BitIndex map[string]int 556 bitIndex2Value map[int]string 557 } 558 559 func (svst SystemVariableSetType) String() string { 560 return fmt.Sprintf("SET('%v')", 561 strings.Join(svst.Values(), "','")) 562 } 563 564 func (svst SystemVariableSetType) Values() []string { 565 bitsCount := 64 - bits2.LeadingZeros64(svst.bitmap()) 566 var res []string 567 for i := 0; i < bitsCount; i++ { 568 res = append(res, svst.bitIndex2Value[i]) 569 } 570 return res 571 } 572 573 func (svst SystemVariableSetType) bitmap() uint64 { 574 cnt := uint64(len(svst.value2BitIndex)) 575 if cnt == 64 { 576 return math.MaxUint64 577 } 578 return uint64(1<<cnt) - 1 579 } 580 581 func (svst SystemVariableSetType) bits2string(bits uint64) (string, error) { 582 bld := strings.Builder{} 583 bitCount := 64 - bits2.LeadingZeros64(bits) 584 if bitCount > len(svst.bitIndex2Value) { 585 return "", errorValuesAreNotEnough 586 } 587 588 for i := 0; i < bitCount; i++ { 589 mask := uint64(1 << uint64(i)) 590 if mask&bits != 0 { 591 v, ok := svst.bitIndex2Value[i] 592 if !ok { 593 return "", errorValueIsInvalid 594 } 595 bld.WriteString(v) 596 if i != 0 { 597 bld.WriteByte(',') 598 } 599 } 600 } 601 602 bldString := bld.String() 603 return bldString[:len(bldString)-1], nil 604 } 605 606 func (svst SystemVariableSetType) string2bits(s string) (uint64, error) { 607 if len(s) == 0 { 608 return 0, nil 609 } 610 ss := strings.Split(s, ",") 611 bits := uint64(0) 612 for _, sss := range ss { 613 normalized := strings.ToLower(strings.TrimRight(sss, " ")) 614 if origin, ok := svst.normalized2original[normalized]; ok { 615 bits |= 1 << svst.value2BitIndex[origin] 616 } else { 617 if x, err := strconv.ParseUint(sss, 10, 64); err == nil { 618 if x == 0 { 619 continue 620 } 621 bitsCount := bits2.TrailingZeros64(x) 622 xv := 1 << uint64(bitsCount) 623 if _, ok2 := svst.bitIndex2Value[xv]; ok2 { 624 bits |= uint64(xv) 625 continue 626 } 627 } 628 return 0, errorValueIsInvalid 629 } 630 } 631 return bits, nil 632 } 633 634 func (svst SystemVariableSetType) Convert(value interface{}) (interface{}, error) { 635 if value == nil { 636 return nil, nil 637 } 638 cv1 := func(x uint64) (interface{}, error) { 639 if x <= svst.bitmap() { 640 return svst.bits2string(x) 641 } 642 return nil, errorConvertToSetFailed 643 } 644 cv2 := func(x string) (interface{}, error) { 645 bits, err := svst.string2bits(x) 646 if err != nil { 647 return nil, err 648 } 649 return svst.bits2string(bits) 650 } 651 652 switch v := value.(type) { 653 case int: 654 return cv1(uint64(v)) 655 case uint: 656 return cv1(uint64(v)) 657 case int8: 658 return cv1(uint64(v)) 659 case uint8: 660 return cv1(uint64(v)) 661 case int16: 662 return cv1(uint64(v)) 663 case uint16: 664 return cv1(uint64(v)) 665 case int32: 666 return cv1(uint64(v)) 667 case uint32: 668 return cv1(uint64(v)) 669 case int64: 670 return cv1(uint64(v)) 671 case uint64: 672 return cv1(v) 673 case float32: 674 return cv1(uint64(v)) 675 case float64: 676 return cv1(uint64(v)) 677 case string: 678 return cv2(v) 679 case []byte: 680 return cv2(string(v)) 681 } 682 return nil, errorConvertToSetFailed 683 } 684 685 func (svst SystemVariableSetType) Type() types.T { 686 return types.T_any 687 } 688 689 func (svst SystemVariableSetType) MysqlType() defines.MysqlType { 690 return defines.MYSQL_TYPE_SET 691 } 692 693 func (svst SystemVariableSetType) Zero() interface{} { 694 return "" 695 } 696 697 func InitSystemVariableSetType(name string, values ...string) SystemVariableSetType { 698 if len(values) == 0 { 699 panic(errorValuesOfSetIsEmpty) 700 } 701 if len(values) > MaxMemberCountOfSetType { 702 panic(errorValuesOfSetGreaterThan64) 703 } 704 705 normalized2original := make(map[string]string) 706 value2BitIndex := make(map[string]int) 707 bitIndex2Value := make(map[int]string) 708 for i, value := range values { 709 if strings.Contains(value, ",") { 710 panic(errorValueHasComma) 711 } 712 v := strings.TrimRight(value, " ") 713 lv := strings.ToLower(v) 714 if _, ok := normalized2original[lv]; ok { 715 panic(errorValueIsDuplicate) 716 } 717 normalized2original[lv] = v 718 value2BitIndex[v] = i 719 bitIndex2Value[i] = v 720 } 721 722 return SystemVariableSetType{ 723 normalized2original: normalized2original, 724 value2BitIndex: value2BitIndex, 725 bitIndex2Value: bitIndex2Value, 726 } 727 } 728 729 type SystemVariableStringType struct { 730 name string 731 } 732 733 func InitSystemVariableStringType(name string) SystemVariableStringType { 734 return SystemVariableStringType{ 735 name: name, 736 } 737 } 738 739 func (svst SystemVariableStringType) String() string { 740 return "STRING" 741 } 742 743 func (svst SystemVariableStringType) Convert(value interface{}) (interface{}, error) { 744 if value == nil { 745 return "", nil 746 } 747 if v, ok := value.(string); ok { 748 return v, nil 749 } 750 return nil, errorConvertToStringFailed 751 } 752 753 func (svst SystemVariableStringType) Type() types.T { 754 return types.T_varchar 755 } 756 757 func (svst SystemVariableStringType) MysqlType() defines.MysqlType { 758 return defines.MYSQL_TYPE_VARCHAR 759 } 760 761 func (svst SystemVariableStringType) Zero() interface{} { 762 return "" 763 } 764 765 type SystemVariable struct { 766 Name string 767 768 // scope of the system variable includes Global,Session,Both 769 Scope Scope 770 771 // can be changed during runtime 772 Dynamic bool 773 774 //can be set for single query by SET_VAR() 775 SetVarHintApplies bool 776 777 Type SystemVariableType 778 779 Default interface{} 780 781 UpdateSessVar func(*Session, map[string]interface{}, string, interface{}) error 782 } 783 784 func (sv SystemVariable) GetName() string { 785 return sv.Name 786 } 787 788 func (sv SystemVariable) GetScope() Scope { 789 return sv.Scope 790 } 791 792 func (sv SystemVariable) GetDynamic() bool { 793 return sv.Dynamic 794 } 795 796 func (sv SystemVariable) GetSetVarHintApplies() bool { 797 return sv.SetVarHintApplies 798 } 799 800 func (sv SystemVariable) GetType() SystemVariableType { 801 return sv.Type 802 } 803 804 func (sv SystemVariable) GetDefault() interface{} { 805 return sv.Default 806 } 807 808 type GlobalSystemVariables struct { 809 mu sync.Mutex 810 // name -> value/default 811 sysVars map[string]interface{} 812 } 813 814 // the set of variables 815 var GSysVariables = &GlobalSystemVariables{ 816 sysVars: make(map[string]interface{}), 817 } 818 819 // initialize system variables from definition 820 func InitGlobalSystemVariables(gsv *GlobalSystemVariables) { 821 if gsv.sysVars == nil { 822 gsv.sysVars = make(map[string]interface{}) 823 } 824 for _, def := range gSysVarsDefs { 825 gsv.sysVars[def.GetName()] = def.GetDefault() 826 } 827 } 828 829 // add custom system variables 830 func (gsv *GlobalSystemVariables) AddSysVariables(vars []SystemVariable) { 831 gsv.mu.Lock() 832 defer gsv.mu.Unlock() 833 for _, v := range vars { 834 vv := v 835 lname := strings.ToLower(vv.GetName()) 836 vv.Name = lname 837 gSysVarsDefs[lname] = vv 838 gsv.sysVars[lname] = vv.GetDefault() 839 } 840 } 841 842 // set values to system variables 843 func (gsv *GlobalSystemVariables) SetValues(ctx context.Context, values map[string]interface{}) error { 844 gsv.mu.Lock() 845 defer gsv.mu.Unlock() 846 for name, val := range values { 847 name = strings.ToLower(name) 848 if sv, ok := gSysVarsDefs[name]; ok { 849 cv, err := sv.GetType().Convert(val) 850 if err != nil { 851 return err 852 } 853 gsv.sysVars[name] = cv 854 } else { 855 return moerr.NewInternalError(ctx, errorSystemVariableDoesNotExist()) 856 } 857 } 858 return nil 859 } 860 861 // copy global system variable to session 862 func (gsv *GlobalSystemVariables) CopySysVarsToSession() map[string]interface{} { 863 gsv.mu.Lock() 864 defer gsv.mu.Unlock() 865 sesSysVars := make(map[string]interface{}, len(gsv.sysVars)) 866 for name, value := range gsv.sysVars { 867 sesSysVars[name] = value 868 } 869 return sesSysVars 870 } 871 872 // get system variable definition ,value. 873 // return false, if there is no such variable. 874 func (gsv *GlobalSystemVariables) GetGlobalSysVar(name string) (SystemVariable, interface{}, bool) { 875 gsv.mu.Lock() 876 defer gsv.mu.Unlock() 877 name = strings.ToLower(name) 878 if v, ok := gSysVarsDefs[name]; ok { 879 return v, gsv.sysVars[name], true 880 } 881 return SystemVariable{}, nil, false 882 } 883 884 // get the definition of the system variable 885 func (gsv *GlobalSystemVariables) GetDefinitionOfSysVar(name string) (SystemVariable, bool) { 886 gsv.mu.Lock() 887 defer gsv.mu.Unlock() 888 name = strings.ToLower(name) 889 if v, ok := gSysVarsDefs[name]; ok { 890 return v, ok 891 } 892 return SystemVariable{}, false 893 } 894 895 // set global dynamic variable by SET GLOBAL 896 func (gsv *GlobalSystemVariables) SetGlobalSysVar(ctx context.Context, name string, value interface{}) error { 897 gsv.mu.Lock() 898 defer gsv.mu.Unlock() 899 name = strings.ToLower(name) 900 if sv, ok := gSysVarsDefs[name]; ok { 901 if sv.GetScope() == ScopeSession { 902 return moerr.NewInternalError(ctx, errorSystemVariableIsSession()) 903 } 904 if !sv.GetDynamic() { 905 return moerr.NewInternalError(ctx, errorSystemVariableIsReadOnly()) 906 } 907 val, err := sv.GetType().Convert(value) 908 if err != nil { 909 return err 910 } 911 gsv.sysVars[name] = val 912 } else { 913 return moerr.NewInternalError(ctx, errorSystemVariableDoesNotExist()) 914 } 915 return nil 916 } 917 918 func init() { 919 InitGlobalSystemVariables(GSysVariables) 920 } 921 922 // definitions of system variables 923 var gSysVarsDefs = map[string]SystemVariable{ 924 "port": { 925 Name: "port", 926 Scope: ScopeGlobal, 927 Dynamic: false, 928 SetVarHintApplies: false, 929 Type: InitSystemVariableIntType("port", 0, 65535, false), 930 Default: int64(6001), 931 }, 932 "host": { 933 Name: "host", 934 Scope: ScopeGlobal, 935 Dynamic: false, 936 SetVarHintApplies: false, 937 Type: InitSystemVariableStringType("host"), 938 Default: "0.0.0.0", 939 }, 940 "max_allowed_packet": { 941 Name: "max_allowed_packet", 942 Scope: ScopeBoth, 943 Dynamic: true, 944 SetVarHintApplies: false, 945 Type: InitSystemVariableIntType("max_allowed_packet", 1024, 1073741824, false), 946 Default: int64(16777216), 947 }, 948 "version_comment": { 949 Name: "version_comment", 950 Scope: ScopeGlobal, 951 Dynamic: false, 952 SetVarHintApplies: false, 953 Type: InitSystemVariableStringType("version_comment"), 954 Default: "MatrixOne", 955 }, 956 "tx_isolation": { 957 Name: "tx_isolation", 958 Scope: ScopeBoth, 959 Dynamic: true, 960 SetVarHintApplies: false, 961 Type: InitSystemSystemEnumType("tx_isolation", "READ-UNCOMMITTED", "READ-COMMITTED", "REPEATABLE-READ", "SERIALIZABLE"), 962 Default: "REPEATABLE-READ", 963 }, 964 "testglobalvar_dyn": { 965 Name: "testglobalvar_dyn", 966 Scope: ScopeGlobal, 967 Dynamic: true, 968 SetVarHintApplies: false, 969 Type: InitSystemVariableIntType("testglobalvar_dyn", 0, 100, false), 970 Default: int64(0), 971 }, 972 "testglobalvar_nodyn": { 973 Name: "testglobalvar_nodyn", 974 Scope: ScopeGlobal, 975 Dynamic: false, 976 SetVarHintApplies: false, 977 Type: InitSystemVariableIntType("testglobalvar_nodyn", 0, 100, false), 978 Default: int64(0), 979 }, 980 "testsessionvar_dyn": { 981 Name: "testsessionvar_dyn", 982 Scope: ScopeSession, 983 Dynamic: true, 984 SetVarHintApplies: false, 985 Type: InitSystemVariableIntType("testsessionvar_dyn", 0, 100, false), 986 Default: int64(0), 987 }, 988 "testsessionvar_nodyn": { 989 Name: "testsessionvar_nodyn", 990 Scope: ScopeSession, 991 Dynamic: false, 992 SetVarHintApplies: false, 993 Type: InitSystemVariableIntType("testsessionvar_nodyn", 0, 100, false), 994 Default: int64(0), 995 }, 996 "testbothvar_dyn": { 997 Name: "testbothvar_dyn", 998 Scope: ScopeBoth, 999 Dynamic: true, 1000 SetVarHintApplies: false, 1001 Type: InitSystemVariableIntType("testbothvar_dyn", 0, 100, false), 1002 Default: int64(0), 1003 }, 1004 "testbotchvar_nodyn": { 1005 Name: "testbotchvar_nodyn", 1006 Scope: ScopeBoth, 1007 Dynamic: false, 1008 SetVarHintApplies: false, 1009 Type: InitSystemVariableIntType("testbotchvar_nodyn", 0, 100, false), 1010 Default: int64(0), 1011 }, 1012 "character_set_client": { 1013 Name: "character_set_client", 1014 Scope: ScopeBoth, 1015 Dynamic: true, 1016 SetVarHintApplies: false, 1017 Type: InitSystemVariableStringType("character_set_client"), 1018 Default: "utf8mb4", 1019 }, 1020 "character_set_server": { 1021 Name: "character_set_server", 1022 Scope: ScopeBoth, 1023 Dynamic: true, 1024 SetVarHintApplies: false, 1025 Type: InitSystemVariableStringType("character_set_server"), 1026 Default: "utf8mb4", 1027 }, 1028 "character_set_database": { 1029 Name: "character_set_database", 1030 Scope: ScopeBoth, 1031 Dynamic: true, 1032 SetVarHintApplies: false, 1033 Type: InitSystemVariableStringType("character_set_database"), 1034 Default: "utf8mb4", 1035 }, 1036 "character_set_connection": { 1037 Name: "character_set_connection", 1038 Scope: ScopeBoth, 1039 Dynamic: true, 1040 SetVarHintApplies: false, 1041 Type: InitSystemVariableStringType("character_set_connection"), 1042 Default: "utf8mb4", 1043 }, 1044 "character_set_results": { 1045 Name: "character_set_results", 1046 Scope: ScopeBoth, 1047 Dynamic: true, 1048 SetVarHintApplies: false, 1049 Type: InitSystemVariableStringType("character_set_results"), 1050 Default: "utf8mb4", 1051 }, 1052 "collation_connection": { 1053 Name: "collation_connection", 1054 Scope: ScopeGlobal, 1055 Dynamic: true, 1056 SetVarHintApplies: false, 1057 Type: InitSystemVariableStringType("collation_connection"), 1058 Default: "default", 1059 }, 1060 "collation_server": { 1061 Name: "collation_server", 1062 Scope: ScopeGlobal, 1063 Dynamic: true, 1064 SetVarHintApplies: false, 1065 Type: InitSystemVariableStringType("collation_server"), 1066 Default: "utf8mb4_bin", 1067 }, 1068 "license": { 1069 Name: "license", 1070 Scope: ScopeGlobal, 1071 Dynamic: true, 1072 SetVarHintApplies: false, 1073 Type: InitSystemVariableStringType("license"), 1074 Default: "APACHE", 1075 }, 1076 "autocommit": { 1077 Name: "autocommit", 1078 Scope: ScopeBoth, 1079 Dynamic: true, 1080 SetVarHintApplies: false, 1081 Type: InitSystemVariableBoolType("autocommit"), 1082 Default: int64(1), 1083 }, 1084 "sql_mode": { 1085 Name: "sql_mode", 1086 Scope: ScopeBoth, 1087 Dynamic: true, 1088 SetVarHintApplies: true, 1089 Type: InitSystemVariableSetType("sql_mode", "ANSI", "TRADITIONAL", "ALLOW_INVALID_DATES", "ANSI_QUOTES", "ERROR_FOR_DIVISION_BY_ZERO", "HIGH_NOT_PRECEDENCE", "IGNORE_SPACE", "NO_AUTO_VALUE_ON_ZERO", "NO_BACKSLASH_ESCAPES", "NO_DIR_IN_CREATE", "NO_ENGINE_SUBSTITUTION", "NO_UNSIGNED_SUBTRACTION", "NO_ZERO_DATE", "NO_ZERO_IN_DATE", "ONLY_FULL_GROUP_BY", "PAD_CHAR_TO_FULL_LENGTH", "PIPES_AS_CONCAT", "REAL_AS_FLOAT", "STRICT_ALL_TABLES", "STRICT_TRANS_TABLES", "TIME_TRUNCATE_FRACTIONAL"), 1090 Default: "ONLY_FULL_GROUP_BY,STRICT_TRANS_TABLES,NO_ZERO_IN_DATE,NO_ZERO_DATE,ERROR_FOR_DIVISION_BY_ZERO,NO_ENGINE_SUBSTITUTION", 1091 }, 1092 "completion_type": { 1093 Name: "completion_type", 1094 Scope: ScopeBoth, 1095 Dynamic: true, 1096 SetVarHintApplies: false, 1097 Type: InitSystemSystemEnumType("completion_type", "NO_CHAIN", "CHAIN", "RELEASE"), 1098 Default: "NO_CHAIN", 1099 }, 1100 "time_zone": { 1101 Name: "time_zone", 1102 Scope: ScopeBoth, 1103 Dynamic: true, 1104 SetVarHintApplies: true, 1105 Type: InitSystemVariableStringType("time_zone"), 1106 Default: "SYSTEM", 1107 UpdateSessVar: updateTimeZone, 1108 }, 1109 "auto_increment_increment": { 1110 Name: "auto_increment_increment", 1111 Scope: ScopeBoth, 1112 Dynamic: true, 1113 SetVarHintApplies: true, 1114 Type: InitSystemVariableIntType("auto_increment_increment", 1, 65535, false), 1115 Default: int64(1), 1116 }, 1117 "auto_increment_offset": { 1118 Name: "auto_increment_offset", 1119 Scope: ScopeBoth, 1120 Dynamic: true, 1121 SetVarHintApplies: true, 1122 Type: InitSystemVariableIntType("auto_increment_offset", 1, 65535, false), 1123 Default: int64(1), 1124 }, 1125 "init_connect": { 1126 Name: "init_connect", 1127 Scope: ScopeGlobal, 1128 Dynamic: true, 1129 SetVarHintApplies: false, 1130 Type: InitSystemVariableStringType("init_connect"), 1131 Default: "", 1132 }, 1133 "interactive_timeout": { 1134 Name: "interactive_timeout", 1135 Scope: ScopeBoth, 1136 Dynamic: true, 1137 SetVarHintApplies: true, 1138 Type: InitSystemVariableIntType("interactive_timeout", 1, 31536000, false), 1139 Default: int64(28800), 1140 }, 1141 "lower_case_table_names": { 1142 Name: "lower_case_table_names", 1143 Scope: ScopeGlobal, 1144 Dynamic: false, 1145 SetVarHintApplies: false, 1146 Type: InitSystemVariableIntType("lower_case_table_names", 0, 2, false), 1147 Default: int64(0), 1148 }, 1149 "net_write_timeout": { 1150 Name: "net_write_timeout", 1151 Scope: ScopeBoth, 1152 Dynamic: true, 1153 SetVarHintApplies: false, 1154 Type: InitSystemVariableIntType("net_write_timeout", 1, 31536000, false), 1155 Default: int64(60), 1156 }, 1157 "system_time_zone": { 1158 Name: "system_time_zone", 1159 Scope: ScopeGlobal, 1160 Dynamic: false, 1161 SetVarHintApplies: false, 1162 Type: InitSystemVariableStringType("system_time_zone"), 1163 Default: "", 1164 }, 1165 "transaction_isolation": { 1166 Name: "transaction_isolation", 1167 Scope: ScopeBoth, 1168 Dynamic: true, 1169 SetVarHintApplies: false, 1170 Type: InitSystemSystemEnumType("transaction_isolation", "READ-UNCOMMITTED", "READ-COMMITTED", "REPEATABLE-READ", "SERIALIZABLE"), 1171 Default: "REPEATABLE-READ", 1172 }, 1173 "wait_timeout": { 1174 Name: "wait_timeout", 1175 Scope: ScopeBoth, 1176 Dynamic: true, 1177 SetVarHintApplies: false, 1178 Type: InitSystemVariableIntType("wait_timeout", 1, 2147483, false), 1179 Default: int64(28800), 1180 }, 1181 "sql_safe_updates": { 1182 Name: "sql_safe_updates", 1183 Scope: ScopeBoth, 1184 Dynamic: true, 1185 SetVarHintApplies: false, 1186 Type: InitSystemVariableIntType("sql_safe_updates", 0, 1, false), 1187 Default: int64(0), 1188 }, 1189 "profiling": { 1190 Name: "profiling", 1191 Scope: ScopeBoth, 1192 Dynamic: true, 1193 SetVarHintApplies: false, 1194 Type: InitSystemVariableIntType("profiling", 0, 1, false), 1195 Default: int64(0), 1196 }, 1197 "performance_schema": { 1198 Name: "performance_schema", 1199 Scope: ScopeBoth, 1200 Dynamic: true, 1201 SetVarHintApplies: false, 1202 Type: InitSystemVariableIntType("performance_schema", 0, 1, false), 1203 Default: int64(0), 1204 }, 1205 "transaction_read_only": { 1206 Name: "transaction_read_only", 1207 Scope: ScopeBoth, 1208 Dynamic: true, 1209 SetVarHintApplies: false, 1210 Type: InitSystemVariableIntType("transaction_read_only", 0, 1, false), 1211 Default: int64(0), 1212 }, 1213 "tx_read_only": { 1214 Name: "tx_read_only", 1215 Scope: ScopeBoth, 1216 Dynamic: true, 1217 SetVarHintApplies: false, 1218 Type: InitSystemVariableIntType("tx_read_only", 0, 1, false), 1219 Default: int64(0), 1220 }, 1221 "sql_select_limit": { 1222 Name: "sql_select_limit", 1223 Scope: ScopeBoth, 1224 Dynamic: true, 1225 SetVarHintApplies: false, 1226 Type: InitSystemVariableUintType("sql_select_limit", 0, 18446744073709551615), 1227 Default: uint64(18446744073709551615), 1228 }, 1229 "save_query_result": { 1230 Name: "save_query_result", 1231 Scope: ScopeBoth, 1232 Dynamic: true, 1233 SetVarHintApplies: false, 1234 Type: InitSystemVariableBoolType("save_query_result"), 1235 Default: int64(0), 1236 }, 1237 "query_result_timeout": { 1238 Name: "query_result_timeout", 1239 Scope: ScopeBoth, 1240 Dynamic: true, 1241 SetVarHintApplies: false, 1242 Type: InitSystemVariableUintType("query_result_timeout", 0, 18446744073709551615), 1243 Default: uint64(24), 1244 }, 1245 "query_result_maxsize": { 1246 Name: "query_result_maxsize", 1247 Scope: ScopeBoth, 1248 Dynamic: true, 1249 SetVarHintApplies: false, 1250 Type: InitSystemVariableUintType("query_result_maxsize", 0, 18446744073709551615), 1251 Default: uint64(100), 1252 }, 1253 } 1254 1255 func updateTimeZone(sess *Session, vars map[string]interface{}, name string, val interface{}) error { 1256 oldVal := vars[name] 1257 if oldVal == val { 1258 return nil 1259 } 1260 1261 tzStr := val.(string) 1262 if tzStr == "SYSTEM" { 1263 vars[name] = "SYSTEM" 1264 sess.SetTimeZone(time.Local) 1265 } else if tzStr[0] == '-' { 1266 if len(tzStr) != 6 { 1267 return moerr.NewInternalError(sess.requestCtx, "incorrect timezone "+tzStr) 1268 } 1269 1270 if tzStr[1] < '0' || tzStr[1] > '9' { 1271 return moerr.NewInternalError(sess.requestCtx, "incorrect timezone "+tzStr) 1272 } 1273 hour := int(tzStr[1]-'0') * 10 1274 if tzStr[2] < '0' || tzStr[2] > '9' { 1275 return moerr.NewInternalError(sess.requestCtx, "incorrect timezone "+tzStr) 1276 } 1277 hour += int(tzStr[2] - '0') 1278 1279 if tzStr[3] != ':' { 1280 return moerr.NewInternalError(sess.requestCtx, "incorrect timezone "+tzStr) 1281 } 1282 1283 if tzStr[4] < '0' || tzStr[4] > '9' { 1284 return moerr.NewInternalError(sess.requestCtx, "incorrect timezone "+tzStr) 1285 } 1286 minute := int(tzStr[4]-'0') * 10 1287 if tzStr[5] < '0' || tzStr[5] > '9' { 1288 return moerr.NewInternalError(sess.requestCtx, "incorrect timezone "+tzStr) 1289 } 1290 minute += int(tzStr[5] - '0') 1291 1292 minute += hour * 60 1293 if minute >= 14*60 { 1294 return moerr.NewInternalError(sess.requestCtx, "incorrect timezone "+tzStr) 1295 } 1296 1297 vars[name] = tzStr 1298 sess.SetTimeZone(time.FixedZone("FixedZone", -minute*60)) 1299 } else if tzStr[0] == '+' { 1300 if len(tzStr) != 6 { 1301 return moerr.NewInternalError(sess.requestCtx, "incorrect timezone "+tzStr) 1302 } 1303 1304 if tzStr[1] < '0' || tzStr[1] > '9' { 1305 return moerr.NewInternalError(sess.requestCtx, "incorrect timezone "+tzStr) 1306 } 1307 hour := int(tzStr[1]-'0') * 10 1308 if tzStr[2] < '0' || tzStr[2] > '9' { 1309 return moerr.NewInternalError(sess.requestCtx, "incorrect timezone "+tzStr) 1310 } 1311 hour += int(tzStr[2] - '0') 1312 1313 if tzStr[3] != ':' { 1314 return moerr.NewInternalError(sess.requestCtx, "incorrect timezone "+tzStr) 1315 } 1316 1317 if tzStr[4] < '0' || tzStr[4] > '9' { 1318 return moerr.NewInternalError(sess.requestCtx, "incorrect timezone "+tzStr) 1319 } 1320 minute := int(tzStr[4]-'0') * 10 1321 if tzStr[5] < '0' || tzStr[5] > '9' { 1322 return moerr.NewInternalError(sess.requestCtx, "incorrect timezone "+tzStr) 1323 } 1324 minute += int(tzStr[5] - '0') 1325 1326 minute += hour * 60 1327 if minute > 14*60 { 1328 return moerr.NewInternalError(sess.requestCtx, "incorrect timezone "+tzStr) 1329 } 1330 1331 vars[name] = tzStr 1332 sess.SetTimeZone(time.FixedZone("FixedZone", minute*60)) 1333 } else { 1334 loc, err := time.LoadLocation(tzStr) 1335 if err != nil { 1336 return err 1337 } 1338 1339 vars[name] = tzStr 1340 sess.SetTimeZone(loc) 1341 } 1342 1343 return nil 1344 }