github.com/matrixorigin/matrixone@v1.2.0/pkg/frontend/authenticate.go (about) 1 // Copyright 2021 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 "bytes" 19 "context" 20 "encoding/json" 21 "errors" 22 "fmt" 23 "io" 24 "math" 25 "math/bits" 26 "os" 27 "path" 28 "sort" 29 "strconv" 30 "strings" 31 "sync" 32 "sync/atomic" 33 "time" 34 35 "github.com/tidwall/btree" 36 "go.uber.org/zap" 37 "golang.org/x/sync/errgroup" 38 39 "github.com/matrixorigin/matrixone/pkg/catalog" 40 "github.com/matrixorigin/matrixone/pkg/clusterservice" 41 "github.com/matrixorigin/matrixone/pkg/common/moerr" 42 "github.com/matrixorigin/matrixone/pkg/common/mpool" 43 "github.com/matrixorigin/matrixone/pkg/config" 44 "github.com/matrixorigin/matrixone/pkg/container/types" 45 "github.com/matrixorigin/matrixone/pkg/defines" 46 "github.com/matrixorigin/matrixone/pkg/fileservice" 47 "github.com/matrixorigin/matrixone/pkg/logutil" 48 "github.com/matrixorigin/matrixone/pkg/pb/metadata" 49 "github.com/matrixorigin/matrixone/pkg/pb/plan" 50 "github.com/matrixorigin/matrixone/pkg/pb/query" 51 "github.com/matrixorigin/matrixone/pkg/queryservice" 52 "github.com/matrixorigin/matrixone/pkg/sql/parsers" 53 "github.com/matrixorigin/matrixone/pkg/sql/parsers/dialect" 54 "github.com/matrixorigin/matrixone/pkg/sql/parsers/tree" 55 plan2 "github.com/matrixorigin/matrixone/pkg/sql/plan" 56 "github.com/matrixorigin/matrixone/pkg/sql/plan/function" 57 "github.com/matrixorigin/matrixone/pkg/util/metric/mometric" 58 "github.com/matrixorigin/matrixone/pkg/util/sysview" 59 "github.com/matrixorigin/matrixone/pkg/util/trace" 60 "github.com/matrixorigin/matrixone/pkg/util/trace/impl/motrace" 61 "github.com/matrixorigin/matrixone/pkg/vm/engine/disttae/route" 62 ) 63 64 type TenantInfo struct { 65 mu sync.Mutex 66 Tenant string 67 User string 68 DefaultRole string 69 70 TenantID uint32 71 UserID uint32 72 DefaultRoleID uint32 73 74 // true: use secondary role all 75 // false: use secondary role none 76 useAllSecondaryRole bool 77 78 delimiter byte 79 80 version string 81 } 82 83 func (ti *TenantInfo) String() string { 84 ti.mu.Lock() 85 defer ti.mu.Unlock() 86 delimiter := ti.delimiter 87 if !strconv.IsPrint(rune(delimiter)) { 88 delimiter = ':' 89 } 90 return fmt.Sprintf("{account %s%c%s%c%s -- %d%c%d%c%d}", 91 ti.Tenant, delimiter, ti.User, delimiter, ti.DefaultRole, 92 ti.TenantID, delimiter, ti.UserID, delimiter, ti.DefaultRoleID) 93 } 94 95 func (ti *TenantInfo) GetTenant() string { 96 ti.mu.Lock() 97 defer ti.mu.Unlock() 98 return ti.getTenantUnsafe() 99 } 100 101 func (ti *TenantInfo) getTenantUnsafe() string { 102 return ti.Tenant 103 } 104 105 func (ti *TenantInfo) GetTenantID() uint32 { 106 ti.mu.Lock() 107 defer ti.mu.Unlock() 108 return ti.TenantID 109 } 110 111 func (ti *TenantInfo) SetTenantID(id uint32) { 112 ti.mu.Lock() 113 defer ti.mu.Unlock() 114 ti.TenantID = id 115 } 116 117 func (ti *TenantInfo) GetUser() string { 118 ti.mu.Lock() 119 defer ti.mu.Unlock() 120 return ti.User 121 } 122 123 func (ti *TenantInfo) SetUser(user string) { 124 ti.mu.Lock() 125 defer ti.mu.Unlock() 126 ti.User = user 127 } 128 129 func (ti *TenantInfo) GetUserID() uint32 { 130 ti.mu.Lock() 131 defer ti.mu.Unlock() 132 return ti.UserID 133 } 134 135 func (ti *TenantInfo) SetUserID(id uint32) { 136 ti.mu.Lock() 137 defer ti.mu.Unlock() 138 ti.UserID = id 139 } 140 141 func (ti *TenantInfo) GetDefaultRole() string { 142 ti.mu.Lock() 143 defer ti.mu.Unlock() 144 return ti.getDefaultRoleUnsafe() 145 } 146 147 func (ti *TenantInfo) getDefaultRoleUnsafe() string { 148 return ti.DefaultRole 149 } 150 151 func (ti *TenantInfo) SetDefaultRole(r string) { 152 ti.mu.Lock() 153 defer ti.mu.Unlock() 154 ti.DefaultRole = r 155 } 156 157 func (ti *TenantInfo) HasDefaultRole() bool { 158 ti.mu.Lock() 159 defer ti.mu.Unlock() 160 return len(ti.getDefaultRoleUnsafe()) != 0 161 } 162 163 func (ti *TenantInfo) GetDefaultRoleID() uint32 { 164 ti.mu.Lock() 165 defer ti.mu.Unlock() 166 return ti.DefaultRoleID 167 } 168 169 func (ti *TenantInfo) SetDefaultRoleID(id uint32) { 170 ti.mu.Lock() 171 defer ti.mu.Unlock() 172 ti.DefaultRoleID = id 173 } 174 175 func (ti *TenantInfo) IsSysTenant() bool { 176 ti.mu.Lock() 177 defer ti.mu.Unlock() 178 return ti.isSysTenantUnsafe() 179 } 180 181 func (ti *TenantInfo) isSysTenantUnsafe() bool { 182 if ti != nil { 183 return strings.ToLower(ti.getTenantUnsafe()) == GetDefaultTenant() 184 } 185 return false 186 } 187 188 func (ti *TenantInfo) IsDefaultRole() bool { 189 ti.mu.Lock() 190 defer ti.mu.Unlock() 191 return ti.getDefaultRoleUnsafe() == GetDefaultRole() 192 } 193 194 func (ti *TenantInfo) IsMoAdminRole() bool { 195 ti.mu.Lock() 196 defer ti.mu.Unlock() 197 return ti.isMoAdminRoleUnsafe() 198 } 199 200 func (ti *TenantInfo) isMoAdminRoleUnsafe() bool { 201 return ti.isSysTenantUnsafe() && strings.ToLower(ti.getDefaultRoleUnsafe()) == moAdminRoleName 202 } 203 204 func (ti *TenantInfo) IsAccountAdminRole() bool { 205 ti.mu.Lock() 206 defer ti.mu.Unlock() 207 return ti.isAccountAdminRoleUnsafe() 208 } 209 210 func (ti *TenantInfo) isAccountAdminRoleUnsafe() bool { 211 return !ti.isSysTenantUnsafe() && strings.ToLower(ti.getDefaultRoleUnsafe()) == accountAdminRoleName 212 } 213 214 func (ti *TenantInfo) IsAdminRole() bool { 215 ti.mu.Lock() 216 defer ti.mu.Unlock() 217 return ti.isMoAdminRoleUnsafe() || ti.isAccountAdminRoleUnsafe() 218 } 219 220 func (ti *TenantInfo) IsNameOfAdminRoles(name string) bool { 221 if ti == nil { 222 return false 223 } 224 ti.mu.Lock() 225 defer ti.mu.Unlock() 226 n := strings.ToLower(name) 227 if ti.isSysTenantUnsafe() { 228 return n == moAdminRoleName 229 } else { 230 return n == accountAdminRoleName 231 } 232 } 233 234 func (ti *TenantInfo) SetUseSecondaryRole(v bool) { 235 ti.mu.Lock() 236 defer ti.mu.Unlock() 237 ti.useAllSecondaryRole = v 238 } 239 240 func (ti *TenantInfo) GetUseSecondaryRole() bool { 241 ti.mu.Lock() 242 defer ti.mu.Unlock() 243 return ti.useAllSecondaryRole 244 } 245 246 func (ti *TenantInfo) GetVersion() string { 247 ti.mu.Lock() 248 defer ti.mu.Unlock() 249 return ti.version 250 } 251 252 func (ti *TenantInfo) SetVersion(version string) { 253 ti.mu.Lock() 254 defer ti.mu.Unlock() 255 ti.version = version 256 } 257 258 func GetDefaultTenant() string { 259 return sysAccountName 260 } 261 262 func GetSysTenantId() uint32 { 263 return sysAccountID 264 } 265 266 func GetUserRoot() string { 267 return rootName 268 } 269 270 func GetUserRootId() uint32 { 271 return rootID 272 } 273 274 func GetDefaultRole() string { 275 return moAdminRoleName 276 } 277 278 func GetDefaultRoleId() uint32 { 279 return moAdminRoleID 280 } 281 282 func GetAccountAdminRole() string { 283 return accountAdminRoleName 284 } 285 286 func GetAccountAdminRoleId() uint32 { 287 return accountAdminRoleID 288 } 289 290 func GetAdminUserId() uint32 { 291 return dumpID + 1 292 } 293 294 func GetBackgroundTenant() *TenantInfo { 295 return &TenantInfo{ 296 Tenant: GetDefaultTenant(), 297 User: GetUserRoot(), 298 DefaultRole: GetDefaultRole(), 299 TenantID: GetSysTenantId(), 300 UserID: GetUserRootId(), 301 DefaultRoleID: GetDefaultRoleId(), 302 } 303 } 304 305 func isCaseInsensitiveEqual(n string, role string) bool { 306 return strings.ToLower(n) == role 307 } 308 309 func isPublicRole(n string) bool { 310 return isCaseInsensitiveEqual(n, publicRoleName) 311 } 312 313 func isPredefinedRole(r string) bool { 314 n := strings.ToLower(r) 315 return n == publicRoleName || n == accountAdminRoleName || n == moAdminRoleName 316 } 317 318 func isSysTenant(n string) bool { 319 return isCaseInsensitiveEqual(n, sysAccountName) 320 } 321 322 // splitUserInput splits user input into account info 323 func splitUserInput(ctx context.Context, userInput string, delimiter byte) (*TenantInfo, error) { 324 p := strings.IndexByte(userInput, delimiter) 325 if p == -1 { 326 return &TenantInfo{ 327 Tenant: GetDefaultTenant(), 328 User: userInput, 329 delimiter: delimiter, 330 }, nil 331 } else { 332 tenant := userInput[:p] 333 if len(tenant) == 0 { 334 return &TenantInfo{}, moerr.NewInternalError(ctx, "invalid tenant name '%s'", tenant) 335 } 336 userRole := userInput[p+1:] 337 p2 := strings.IndexByte(userRole, delimiter) 338 if p2 == -1 { 339 //tenant:user 340 user := userRole 341 if len(user) == 0 { 342 return &TenantInfo{}, moerr.NewInternalError(ctx, "invalid user name '%s'", user) 343 } 344 return &TenantInfo{ 345 Tenant: tenant, 346 User: user, 347 delimiter: delimiter, 348 }, nil 349 } else { 350 user := userRole[:p2] 351 if len(user) == 0 { 352 return &TenantInfo{}, moerr.NewInternalError(ctx, "invalid user name '%s'", user) 353 } 354 role := userRole[p2+1:] 355 if len(role) == 0 { 356 return &TenantInfo{}, moerr.NewInternalError(ctx, "invalid role name '%s'", role) 357 } 358 return &TenantInfo{ 359 Tenant: tenant, 360 User: user, 361 DefaultRole: role, 362 delimiter: delimiter, 363 }, nil 364 } 365 } 366 } 367 368 //GetTenantInfo extract tenant info from the input of the user. 369 /** 370 The format of the user 371 1. tenant:user:role 372 2. tenant:user 373 3. user 374 375 a new format: 376 1. tenant#user#role 377 2. tenant#user 378 */ 379 func GetTenantInfo(ctx context.Context, userInput string) (*TenantInfo, error) { 380 userInput = getUserPart(userInput) 381 if strings.IndexByte(userInput, ':') != -1 { 382 return splitUserInput(ctx, userInput, ':') 383 } else if strings.IndexByte(userInput, '#') != -1 { 384 return splitUserInput(ctx, userInput, '#') 385 } else if strings.Contains(userInput, "%3A") { 386 newUserInput := strings.ReplaceAll(userInput, "%3A", ":") 387 return splitUserInput(ctx, newUserInput, ':') 388 } 389 return splitUserInput(ctx, userInput, ':') 390 } 391 392 // getUserPart gets the username part from the full string. 393 // The full string could contain CN label information which 394 // is used by proxy module. 395 func getUserPart(user string) string { 396 if pos := strings.IndexByte(user, '?'); pos != -1 { 397 return user[:pos] 398 } 399 return user 400 } 401 402 // getLabelPart gets the label part from the full string. 403 // The full string could contain CN label information which 404 // is used by proxy module. 405 func getLabelPart(user string) string { 406 parts := strings.Split(user, "?") 407 if len(parts) > 1 { 408 return parts[1] 409 } 410 return "" 411 } 412 413 // ParseLabel parses the label string. The labels are separated by 414 // ",", key and value are separated by "=". 415 func ParseLabel(labelStr string) (map[string]string, error) { 416 labelMap := make(map[string]string) 417 if len(labelStr) == 0 { 418 return labelMap, nil 419 } 420 const delimiter1 = "," 421 const delimiter2 = "=" 422 kvs := strings.Split(labelStr, delimiter1) 423 for _, label := range kvs { 424 parts := strings.Split(label, delimiter2) 425 if len(parts) == 2 && len(parts[0]) != 0 && len(parts[1]) != 0 { 426 labelMap[parts[0]] = parts[1] 427 } else { 428 return nil, moerr.NewInternalErrorNoCtx("invalid label format: should be like 'a=b'") 429 } 430 } 431 return labelMap, nil 432 } 433 434 // initUser for initialization or something special 435 type initUser struct { 436 account *TenantInfo 437 password []byte 438 } 439 440 var ( 441 specialUsers struct { 442 sync.RWMutex 443 users map[string]*initUser 444 } 445 ) 446 447 func setSpecialUser(userName string, user *initUser) { 448 specialUsers.Lock() 449 if specialUsers.users == nil { 450 specialUsers.users = make(map[string]*initUser) 451 } 452 specialUsers.users[userName] = user 453 specialUsers.Unlock() 454 } 455 456 // SetSpecialUser saves the user for initialization 457 // !!!NOTE: userName must not contain Colon ':' 458 func SetSpecialUser(username string, password []byte) { 459 acc := &TenantInfo{ 460 Tenant: sysAccountName, 461 User: username, 462 DefaultRole: moAdminRoleName, 463 TenantID: sysAccountID, 464 UserID: math.MaxUint32, 465 DefaultRoleID: moAdminRoleID, 466 } 467 468 user := &initUser{ 469 account: acc, 470 password: password, 471 } 472 setSpecialUser(username, user) 473 } 474 475 // isSpecialUser checks the user is the one for initialization 476 func isSpecialUser(userName string) (bool, []byte, *TenantInfo) { 477 specialUsers.RLock() 478 defer specialUsers.RUnlock() 479 480 if user, ok := specialUsers.users[userName]; ok { 481 return true, user.password, user.account 482 } 483 return false, nil, nil 484 } 485 486 const ( 487 // createMoUserIndex = 0 488 // createMoAccountIndex = 1 489 // createMoRoleIndex = 2 490 // createMoUserGrantIndex = 3 491 // createMoRoleGrantIndex = 4 492 // createMoRolePrivIndex = 5 493 ) 494 495 const ( 496 //tenant 497 sysAccountID = 0 498 sysAccountName = "sys" 499 sysAccountStatus = "open" 500 sysAccountComments = "system account" 501 502 //role 503 moAdminRoleID = 0 504 moAdminRoleName = "moadmin" 505 // moAdminRoleComment = "super admin role" 506 publicRoleID = 1 507 publicRoleName = "public" 508 // publicRoleComment = "public role" 509 accountAdminRoleID = 2 510 accountAdminRoleName = "accountadmin" 511 // accountAdminRoleComment = "account admin role" 512 513 //user 514 userStatusLock = "lock" 515 userStatusUnlock = "unlock" 516 517 defaultPasswordEnv = "DEFAULT_PASSWORD" 518 519 rootID = 0 520 rootHost = "localhost" 521 rootName = "root" 522 rootPassword = "111" 523 rootStatus = userStatusUnlock 524 rootExpiredTime = "NULL" 525 rootLoginType = "PASSWORD" 526 rootCreatorID = rootID 527 rootOwnerRoleID = moAdminRoleID 528 rootDefaultRoleID = moAdminRoleID 529 530 dumpID = 1 531 dumpHost = "localhost" 532 dumpName = "dump" 533 //dumpPassword = "111" 534 dumpStatus = userStatusUnlock 535 dumpExpiredTime = "NULL" 536 dumpLoginType = "PASSWORD" 537 dumpCreatorID = rootID 538 dumpOwnerRoleID = moAdminRoleID 539 dumpDefaultRoleID = moAdminRoleID 540 541 moCatalog = "mo_catalog" 542 543 SaveQueryResult = "save_query_result" 544 QueryResultMaxsize = "query_result_maxsize" 545 QueryResultTimeout = "query_result_timeout" 546 LowerCaseTableNames = "lower_case_table_names" 547 ) 548 549 type objectType int 550 551 const ( 552 objectTypeDatabase objectType = iota 553 objectTypeTable 554 objectTypeFunction 555 objectTypeAccount 556 objectTypeNone 557 558 objectIDAll = 0 //denotes all objects in the object type 559 ) 560 561 func (ot objectType) String() string { 562 switch ot { 563 case objectTypeDatabase: 564 return "database" 565 case objectTypeTable: 566 return "table" 567 case objectTypeFunction: 568 return "function" 569 case objectTypeAccount: 570 return "account" 571 case objectTypeNone: 572 return "none" 573 } 574 panic("unsupported object type") 575 } 576 577 type privilegeLevelType int 578 579 const ( 580 //* 581 privilegeLevelStar privilegeLevelType = iota 582 //*.* 583 privilegeLevelStarStar 584 //db_name 585 privilegeLevelDatabase 586 //db_name.* 587 privilegeLevelDatabaseStar 588 //db_name.tbl_name 589 privilegeLevelDatabaseTable 590 //tbl_name 591 privilegeLevelTable 592 //db_name.routine_name 593 privilegeLevelRoutine 594 // 595 privilegeLevelEnd 596 ) 597 598 func (plt privilegeLevelType) String() string { 599 switch plt { 600 case privilegeLevelStar: 601 return "*" 602 case privilegeLevelStarStar: 603 return "*.*" 604 case privilegeLevelDatabase: 605 return "d" 606 case privilegeLevelDatabaseStar: 607 return "d.*" 608 case privilegeLevelDatabaseTable: 609 return "d.t" 610 case privilegeLevelTable: 611 return "t" 612 case privilegeLevelRoutine: 613 return "r" 614 } 615 panic(fmt.Sprintf("no such privilege level type %d", plt)) 616 } 617 618 type PrivilegeType int 619 620 const ( 621 PrivilegeTypeCreateAccount PrivilegeType = iota 622 PrivilegeTypeDropAccount 623 PrivilegeTypeAlterAccount 624 PrivilegeTypeCreateUser 625 PrivilegeTypeDropUser 626 PrivilegeTypeAlterUser 627 PrivilegeTypeCreateRole 628 PrivilegeTypeDropRole 629 PrivilegeTypeAlterRole 630 PrivilegeTypeCreateDatabase 631 PrivilegeTypeDropDatabase 632 PrivilegeTypeShowDatabases 633 PrivilegeTypeConnect 634 PrivilegeTypeManageGrants 635 PrivilegeTypeAccountAll 636 PrivilegeTypeAccountOwnership 637 PrivilegeTypeUserOwnership 638 PrivilegeTypeRoleOwnership 639 PrivilegeTypeShowTables 640 PrivilegeTypeCreateObject //includes: table, view, stream, sequence, function, dblink,etc 641 PrivilegeTypeCreateTable 642 PrivilegeTypeCreateView 643 PrivilegeTypeDropObject 644 PrivilegeTypeDropTable 645 PrivilegeTypeDropView 646 PrivilegeTypeAlterObject 647 PrivilegeTypeAlterTable 648 PrivilegeTypeAlterView 649 PrivilegeTypeDatabaseAll 650 PrivilegeTypeDatabaseOwnership 651 PrivilegeTypeSelect 652 PrivilegeTypeInsert 653 PrivilegeTypeUpdate 654 PrivilegeTypeTruncate 655 PrivilegeTypeDelete 656 PrivilegeTypeReference 657 PrivilegeTypeIndex //include create/alter/drop index 658 PrivilegeTypeTableAll 659 PrivilegeTypeTableOwnership 660 PrivilegeTypeExecute 661 PrivilegeTypeCanGrantRoleToOthersInCreateUser // used in checking the privilege of CreateUser with the default role 662 PrivilegeTypeValues 663 PrivilegeTypeUpgradeAccount 664 ) 665 666 type PrivilegeScope uint8 667 668 const ( 669 PrivilegeScopeSys PrivilegeScope = 1 670 PrivilegeScopeAccount PrivilegeScope = 2 671 PrivilegeScopeUser PrivilegeScope = 4 672 PrivilegeScopeRole PrivilegeScope = 8 673 PrivilegeScopeDatabase PrivilegeScope = 16 674 PrivilegeScopeTable PrivilegeScope = 32 675 PrivilegeScopeRoutine PrivilegeScope = 64 676 ) 677 678 func (ps PrivilegeScope) String() string { 679 sb := strings.Builder{} 680 first := true 681 for i := 0; i < 8; i++ { 682 var s string 683 switch ps & (1 << i) { 684 case PrivilegeScopeSys: 685 s = "sys" 686 case PrivilegeScopeAccount: 687 s = "account" 688 case PrivilegeScopeUser: 689 s = "user" 690 case PrivilegeScopeRole: 691 s = "role" 692 case PrivilegeScopeDatabase: 693 s = "database" 694 case PrivilegeScopeTable: 695 s = "table" 696 case PrivilegeScopeRoutine: 697 s = "routine" 698 default: 699 s = "" 700 } 701 if len(s) != 0 { 702 if !first { 703 sb.WriteString(",") 704 } else { 705 first = false 706 } 707 sb.WriteString(s) 708 } 709 } 710 return sb.String() 711 } 712 713 func (pt PrivilegeType) String() string { 714 switch pt { 715 case PrivilegeTypeCreateAccount: 716 return "create account" 717 case PrivilegeTypeDropAccount: 718 return "drop account" 719 case PrivilegeTypeAlterAccount: 720 return "alter account" 721 case PrivilegeTypeUpgradeAccount: 722 return "upgrade account" 723 case PrivilegeTypeCreateUser: 724 return "create user" 725 case PrivilegeTypeDropUser: 726 return "drop user" 727 case PrivilegeTypeAlterUser: 728 return "alter user" 729 case PrivilegeTypeCreateRole: 730 return "create role" 731 case PrivilegeTypeDropRole: 732 return "drop role" 733 case PrivilegeTypeAlterRole: 734 return "alter role" 735 case PrivilegeTypeCreateDatabase: 736 return "create database" 737 case PrivilegeTypeDropDatabase: 738 return "drop database" 739 case PrivilegeTypeShowDatabases: 740 return "show databases" 741 case PrivilegeTypeConnect: 742 return "connect" 743 case PrivilegeTypeManageGrants: 744 return "manage grants" 745 case PrivilegeTypeAccountAll: 746 return "account all" 747 case PrivilegeTypeAccountOwnership: 748 return "account ownership" 749 case PrivilegeTypeUserOwnership: 750 return "user ownership" 751 case PrivilegeTypeRoleOwnership: 752 return "role ownership" 753 case PrivilegeTypeShowTables: 754 return "show tables" 755 case PrivilegeTypeCreateObject: 756 return "create object" 757 case PrivilegeTypeCreateTable: 758 return "create table" 759 case PrivilegeTypeCreateView: 760 return "create view" 761 case PrivilegeTypeDropObject: 762 return "drop object" 763 case PrivilegeTypeDropTable: 764 return "drop table" 765 case PrivilegeTypeDropView: 766 return "drop view" 767 case PrivilegeTypeAlterObject: 768 return "alter object" 769 case PrivilegeTypeAlterTable: 770 return "alter table" 771 case PrivilegeTypeAlterView: 772 return "alter view" 773 case PrivilegeTypeDatabaseAll: 774 return "database all" 775 case PrivilegeTypeDatabaseOwnership: 776 return "database ownership" 777 case PrivilegeTypeSelect: 778 return "select" 779 case PrivilegeTypeInsert: 780 return "insert" 781 case PrivilegeTypeUpdate: 782 return "update" 783 case PrivilegeTypeTruncate: 784 return "truncate" 785 case PrivilegeTypeDelete: 786 return "delete" 787 case PrivilegeTypeReference: 788 return "reference" 789 case PrivilegeTypeIndex: 790 return "index" 791 case PrivilegeTypeTableAll: 792 return "table all" 793 case PrivilegeTypeTableOwnership: 794 return "table ownership" 795 case PrivilegeTypeExecute: 796 return "execute" 797 case PrivilegeTypeValues: 798 return "values" 799 } 800 panic(fmt.Sprintf("no such privilege type %d", pt)) 801 } 802 803 func (pt PrivilegeType) Scope() PrivilegeScope { 804 switch pt { 805 case PrivilegeTypeCreateAccount: 806 return PrivilegeScopeSys 807 case PrivilegeTypeDropAccount: 808 return PrivilegeScopeSys 809 case PrivilegeTypeAlterAccount: 810 return PrivilegeScopeSys 811 case PrivilegeTypeUpgradeAccount: 812 return PrivilegeScopeSys 813 case PrivilegeTypeCreateUser: 814 return PrivilegeScopeAccount 815 case PrivilegeTypeDropUser: 816 return PrivilegeScopeAccount 817 case PrivilegeTypeAlterUser: 818 return PrivilegeScopeAccount 819 case PrivilegeTypeCreateRole: 820 return PrivilegeScopeAccount 821 case PrivilegeTypeDropRole: 822 return PrivilegeScopeAccount 823 case PrivilegeTypeAlterRole: 824 return PrivilegeScopeAccount 825 case PrivilegeTypeCreateDatabase: 826 return PrivilegeScopeAccount 827 case PrivilegeTypeDropDatabase: 828 return PrivilegeScopeAccount 829 case PrivilegeTypeShowDatabases: 830 return PrivilegeScopeAccount 831 case PrivilegeTypeConnect: 832 return PrivilegeScopeAccount 833 case PrivilegeTypeManageGrants: 834 return PrivilegeScopeAccount 835 case PrivilegeTypeAccountAll: 836 return PrivilegeScopeAccount 837 case PrivilegeTypeAccountOwnership: 838 return PrivilegeScopeAccount 839 case PrivilegeTypeUserOwnership: 840 return PrivilegeScopeUser 841 case PrivilegeTypeRoleOwnership: 842 return PrivilegeScopeRole 843 case PrivilegeTypeShowTables: 844 return PrivilegeScopeDatabase 845 case PrivilegeTypeCreateObject, PrivilegeTypeCreateTable, PrivilegeTypeCreateView: 846 return PrivilegeScopeDatabase 847 case PrivilegeTypeDropObject, PrivilegeTypeDropTable, PrivilegeTypeDropView: 848 return PrivilegeScopeDatabase 849 case PrivilegeTypeAlterObject, PrivilegeTypeAlterTable, PrivilegeTypeAlterView: 850 return PrivilegeScopeDatabase 851 case PrivilegeTypeDatabaseAll: 852 return PrivilegeScopeDatabase 853 case PrivilegeTypeDatabaseOwnership: 854 return PrivilegeScopeDatabase 855 case PrivilegeTypeSelect: 856 return PrivilegeScopeTable 857 case PrivilegeTypeInsert: 858 return PrivilegeScopeTable 859 case PrivilegeTypeUpdate: 860 return PrivilegeScopeTable 861 case PrivilegeTypeTruncate: 862 return PrivilegeScopeTable 863 case PrivilegeTypeDelete: 864 return PrivilegeScopeTable 865 case PrivilegeTypeReference: 866 return PrivilegeScopeTable 867 case PrivilegeTypeIndex: 868 return PrivilegeScopeTable 869 case PrivilegeTypeTableAll: 870 return PrivilegeScopeTable 871 case PrivilegeTypeTableOwnership: 872 return PrivilegeScopeTable 873 case PrivilegeTypeExecute: 874 return PrivilegeScopeTable 875 case PrivilegeTypeValues: 876 return PrivilegeScopeTable 877 } 878 panic(fmt.Sprintf("no such privilege type %d", pt)) 879 } 880 881 var ( 882 sysWantedDatabases = map[string]int8{ 883 "mo_catalog": 0, 884 "information_schema": 0, 885 "system": 0, 886 "system_metrics": 0, 887 } 888 sysDatabases = map[string]int8{ 889 "mo_catalog": 0, 890 "information_schema": 0, 891 "system": 0, 892 "system_metrics": 0, 893 "mysql": 0, 894 "mo_task": 0, 895 } 896 sysWantedTables = map[string]int8{ 897 "mo_user": 0, 898 "mo_account": 0, 899 "mo_role": 0, 900 "mo_user_grant": 0, 901 "mo_role_grant": 0, 902 "mo_role_privs": 0, 903 "mo_user_defined_function": 0, 904 "mo_stored_procedure": 0, 905 "mo_mysql_compatibility_mode": 0, 906 "mo_stages": 0, 907 catalog.MOAutoIncrTable: 0, 908 "mo_sessions": 0, 909 "mo_configurations": 0, 910 "mo_locks": 0, 911 "mo_variables": 0, 912 "mo_transactions": 0, 913 "mo_cache": 0, 914 "mo_snapshots": 0, 915 } 916 configInitVariables = map[string]int8{ 917 "save_query_result": 0, 918 "query_result_maxsize": 0, 919 "query_result_timeout": 0, 920 "lower_case_table_names": 0, 921 } 922 sysAccountTables = map[string]struct{}{ 923 catalog.MOVersionTable: {}, 924 catalog.MOUpgradeTable: {}, 925 catalog.MOUpgradeTenantTable: {}, 926 } 927 //predefined tables of the database mo_catalog in every account 928 predefinedTables = map[string]int8{ 929 "mo_database": 0, 930 "mo_tables": 0, 931 "mo_columns": 0, 932 "mo_account": 0, 933 "mo_user": 0, 934 "mo_role": 0, 935 "mo_user_grant": 0, 936 "mo_role_grant": 0, 937 "mo_role_privs": 0, 938 "mo_user_defined_function": 0, 939 "mo_stored_procedure": 0, 940 "mo_mysql_compatibility_mode": 0, 941 catalog.MOAutoIncrTable: 0, 942 "mo_indexes": 0, 943 "mo_table_partitions": 0, 944 "mo_pubs": 0, 945 "mo_stages": 0, 946 "mo_sessions": 0, 947 "mo_configurations": 0, 948 "mo_locks": 0, 949 "mo_variables": 0, 950 "mo_transactions": 0, 951 "mo_cache": 0, 952 "mo_foreign_keys": 0, 953 "mo_snapshots": 0, 954 } 955 createDbInformationSchemaSql = "create database information_schema;" 956 createAutoTableSql = MoCatalogMoAutoIncrTableDDL 957 // mo_indexes is a data dictionary table, must be created first when creating tenants, and last when deleting tenants 958 // mo_indexes table does not have `auto_increment` column, 959 createMoIndexesSql = MoCatalogMoIndexesDDL 960 961 createMoForeignKeysSql = MoCatalogMoForeignKeysDDL 962 963 createMoTablePartitionsSql = MoCatalogMoTablePartitionsDDL 964 965 //the sqls creating many tables for the tenant. 966 //Wrap them in a transaction 967 createSqls = []string{ 968 MoCatalogMoUserDDL, 969 MoCatalogMoAccountDDL, 970 MoCatalogMoRoleDDL, 971 MoCatalogMoUserGrantDDL, 972 MoCatalogMoRoleGrantDDL, 973 MoCatalogMoRolePrivsDDL, 974 MoCatalogMoUserDefinedFunctionDDL, 975 MoCatalogMoMysqlCompatibilityModeDDL, 976 MoCatalogMoSnapshotsDDL, 977 MoCatalogMoPubsDDL, 978 MoCatalogMoStoredProcedureDDL, 979 MoCatalogMoStagesDDL, 980 MoCatalogMoSessionsDDL, 981 MoCatalogMoConfigurationsDDL, 982 MoCatalogMoLocksDDL, 983 MoCatalogMoVariablesDDL, 984 MoCatalogMoTransactionsDDL, 985 MoCatalogMoCacheDDL, 986 } 987 988 //drop tables for the tenant 989 dropSqls = []string{ 990 `drop table if exists mo_catalog.mo_user;`, 991 `drop table if exists mo_catalog.mo_role;`, 992 `drop table if exists mo_catalog.mo_user_grant;`, 993 `drop table if exists mo_catalog.mo_role_grant;`, 994 `drop table if exists mo_catalog.mo_role_privs;`, 995 `drop table if exists mo_catalog.mo_user_defined_function;`, 996 `drop table if exists mo_catalog.mo_stored_procedure;`, 997 `drop table if exists mo_catalog.mo_stages;`, 998 `drop view if exists mo_catalog.mo_sessions;`, 999 `drop view if exists mo_catalog.mo_configurations;`, 1000 `drop view if exists mo_catalog.mo_locks;`, 1001 `drop view if exists mo_catalog.mo_variables;`, 1002 `drop view if exists mo_catalog.mo_transactions;`, 1003 `drop view if exists mo_catalog.mo_cache;`, 1004 `drop table if exists mo_catalog.mo_snapshots;`, 1005 } 1006 dropMoMysqlCompatibilityModeSql = `drop table if exists mo_catalog.mo_mysql_compatibility_mode;` 1007 dropMoPubsSql = `drop table if exists mo_catalog.mo_pubs;` 1008 dropAutoIcrColSql = fmt.Sprintf("drop table if exists mo_catalog.`%s`;", catalog.MOAutoIncrTable) 1009 dropMoIndexes = fmt.Sprintf(`drop table if exists %s.%s;`, catalog.MO_CATALOG, catalog.MO_INDEXES) 1010 dropMoTablePartitions = fmt.Sprintf(`drop table if exists %s.%s;`, catalog.MO_CATALOG, catalog.MO_TABLE_PARTITIONS) 1011 dropMoForeignKeys = `drop table if exists mo_catalog.mo_foreign_keys;` 1012 1013 initMoMysqlCompatbilityModeFormat = `insert into mo_catalog.mo_mysql_compatibility_mode( 1014 account_id, 1015 account_name, 1016 dat_name, 1017 variable_name, 1018 variable_value, system_variables) values (%d, "%s", "%s", "%s", "%s", %v);` 1019 1020 initMoMysqlCompatbilityModeWithoutDataBaseFormat = `insert into mo_catalog.mo_mysql_compatibility_mode( 1021 account_id, 1022 account_name, 1023 variable_name, 1024 variable_value, system_variables) values (%d, "%s", "%s", "%s", %v);` 1025 1026 insertIntoMoStages = `insert into mo_catalog.mo_stages( 1027 stage_name, 1028 url, 1029 stage_credentials, 1030 stage_status, 1031 created_time, 1032 comment) values ('%s','%s', '%s', '%s','%s', '%s');` 1033 1034 initMoUserDefinedFunctionFormat = `insert into mo_catalog.mo_user_defined_function( 1035 name, 1036 owner, 1037 args, 1038 retType, 1039 body, 1040 language, 1041 db, 1042 definer, 1043 modified_time, 1044 created_time, 1045 type, 1046 security_type, 1047 comment, 1048 character_set_client, 1049 collation_connection, 1050 database_collation) values ("%s",%d,'%s',"%s","%s","%s","%s","%s","%s","%s","%s","%s","%s","%s","%s","%s");` 1051 1052 updateMoUserDefinedFunctionFormat = `update mo_catalog.mo_user_defined_function 1053 set owner = %d, 1054 args = '%s', 1055 retType = '%s', 1056 body = '%s', 1057 language = '%s', 1058 definer = '%s', 1059 modified_time = '%s', 1060 type = '%s', 1061 security_type = '%s', 1062 comment = '%s', 1063 character_set_client = '%s', 1064 collation_connection = '%s', 1065 database_collation = '%s' 1066 where function_id = %d;` 1067 1068 initMoStoredProcedureFormat = `insert into mo_catalog.mo_stored_procedure( 1069 name, 1070 args, 1071 body, 1072 db, 1073 definer, 1074 modified_time, 1075 created_time, 1076 type, 1077 security_type, 1078 comment, 1079 character_set_client, 1080 collation_connection, 1081 database_collation) values ("%s",'%s',"%s","%s","%s","%s","%s","%s","%s","%s","%s","%s","%s");` 1082 1083 initMoAccountFormat = `insert into mo_catalog.mo_account( 1084 account_id, 1085 account_name, 1086 admin_name, 1087 status, 1088 created_time, 1089 comments, 1090 create_version) values (%d,"%s","%s","%s","%s","%s","%s");` 1091 initMoAccountWithoutIDFormat = `insert into mo_catalog.mo_account( 1092 account_name, 1093 admin_name, 1094 status, 1095 created_time, 1096 comments, 1097 create_version) values ("%s","%s","%s","%s","%s","%s");` 1098 initMoRoleFormat = `insert into mo_catalog.mo_role( 1099 role_id, 1100 role_name, 1101 creator, 1102 owner, 1103 created_time, 1104 comments 1105 ) values (%d,"%s",%d,%d,"%s","%s");` 1106 initMoRoleWithoutIDFormat = `insert into mo_catalog.mo_role( 1107 role_name, 1108 creator, 1109 owner, 1110 created_time, 1111 comments 1112 ) values ("%s",%d,%d,"%s","%s");` 1113 initMoUserFormat = `insert into mo_catalog.mo_user( 1114 user_id, 1115 user_host, 1116 user_name, 1117 authentication_string, 1118 status, 1119 created_time, 1120 expired_time, 1121 login_type, 1122 creator, 1123 owner, 1124 default_role 1125 ) values(%d,"%s","%s","%s","%s","%s",%s,"%s",%d,%d,%d);` 1126 initMoUserWithoutIDFormat = `insert into mo_catalog.mo_user( 1127 user_host, 1128 user_name, 1129 authentication_string, 1130 status, 1131 created_time, 1132 expired_time, 1133 login_type, 1134 creator, 1135 owner, 1136 default_role 1137 ) values("%s","%s","%s","%s","%s",%s,"%s",%d,%d,%d);` 1138 initMoRolePrivFormat = `insert into mo_catalog.mo_role_privs( 1139 role_id, 1140 role_name, 1141 obj_type, 1142 obj_id, 1143 privilege_id, 1144 privilege_name, 1145 privilege_level, 1146 operation_user_id, 1147 granted_time, 1148 with_grant_option 1149 ) values(%d,"%s","%s",%d,%d,"%s","%s",%d,"%s",%v);` 1150 initMoUserGrantFormat = `insert into mo_catalog.mo_user_grant( 1151 role_id, 1152 user_id, 1153 granted_time, 1154 with_grant_option 1155 ) values(%d,%d,"%s",%v);` 1156 ) 1157 1158 const ( 1159 //privilege verification 1160 checkTenantFormat = `select account_id,account_name,status,version,suspended_time from mo_catalog.mo_account where account_name = "%s" order by account_id;` 1161 1162 getTenantNameForMat = `select account_name from mo_catalog.mo_account where account_id = %d;` 1163 1164 updateCommentsOfAccountFormat = `update mo_catalog.mo_account set comments = "%s" where account_name = "%s" order by account_id;;` 1165 1166 updateStatusOfAccountFormat = `update mo_catalog.mo_account set status = "%s",suspended_time = "%s" where account_name = "%s" order by account_id;;` 1167 1168 updateStatusAndVersionOfAccountFormat = `update mo_catalog.mo_account set status = "%s",version = %d,suspended_time = default where account_name = "%s";` 1169 1170 deleteAccountFromMoAccountFormat = `delete from mo_catalog.mo_account where account_name = "%s" order by account_id;;` 1171 1172 getPasswordOfUserFormat = `select user_id,authentication_string,default_role from mo_catalog.mo_user where user_name = "%s" order by user_id;` 1173 1174 updatePasswordOfUserFormat = `update mo_catalog.mo_user set authentication_string = "%s" where user_name = "%s" order by user_id;;` 1175 1176 checkRoleExistsFormat = `select role_id from mo_catalog.mo_role where role_id = %d and role_name = "%s";` 1177 1178 roleNameOfRoleIdFormat = `select role_name from mo_catalog.mo_role where role_id = %d;` 1179 1180 roleIdOfRoleFormat = `select role_id from mo_catalog.mo_role where role_name = "%s" order by role_id;` 1181 1182 //operations on the mo_user_grant 1183 getRoleOfUserFormat = `select r.role_id from mo_catalog.mo_role r, mo_catalog.mo_user_grant ug where ug.role_id = r.role_id and ug.user_id = %d and r.role_name = "%s";` 1184 1185 getRoleIdOfUserIdFormat = `select role_id,with_grant_option from mo_catalog.mo_user_grant where user_id = %d;` 1186 1187 checkUserGrantFormat = `select role_id,user_id,with_grant_option from mo_catalog.mo_user_grant where role_id = %d and user_id = %d;` 1188 1189 checkUserHasRoleFormat = `select u.user_id,ug.role_id from mo_catalog.mo_user u, mo_catalog.mo_user_grant ug where u.user_id = ug.user_id and u.user_name = "%s" and ug.role_id = %d;` 1190 1191 //with_grant_option = true 1192 checkUserGrantWGOFormat = `select role_id,user_id from mo_catalog.mo_user_grant where with_grant_option = true and role_id = %d and user_id = %d;` 1193 1194 updateUserGrantFormat = `update mo_catalog.mo_user_grant set granted_time = "%s", with_grant_option = %v where role_id = %d and user_id = %d;` 1195 1196 insertUserGrantFormat = `insert into mo_catalog.mo_user_grant(role_id,user_id,granted_time,with_grant_option) values (%d,%d,"%s",%v);` 1197 1198 deleteUserGrantFormat = `delete from mo_catalog.mo_user_grant where role_id = %d and user_id = %d;` 1199 1200 //operations on the mo_role_grant 1201 checkRoleGrantFormat = `select granted_id,grantee_id,with_grant_option from mo_catalog.mo_role_grant where granted_id = %d and grantee_id = %d;` 1202 1203 //with_grant_option = true 1204 getRoleGrantWGOFormat = `select grantee_id from mo_catalog.mo_role_grant where with_grant_option = true and granted_id = %d;` 1205 1206 updateRoleGrantFormat = `update mo_catalog.mo_role_grant set operation_role_id = %d, operation_user_id = %d, granted_time = "%s", with_grant_option = %v where granted_id = %d and grantee_id = %d;` 1207 1208 insertRoleGrantFormat = `insert mo_catalog.mo_role_grant(granted_id,grantee_id,operation_role_id,operation_user_id,granted_time,with_grant_option) values (%d,%d,%d,%d,"%s",%v);` 1209 1210 deleteRoleGrantFormat = `delete from mo_catalog.mo_role_grant where granted_id = %d and grantee_id = %d;` 1211 1212 getAllStuffRoleGrantFormat = `select granted_id,grantee_id,with_grant_option from mo_catalog.mo_role_grant;` 1213 1214 getInheritedRoleIdOfRoleIdFormat = `select granted_id,with_grant_option from mo_catalog.mo_role_grant where grantee_id = %d;` 1215 1216 checkRoleHasPrivilegeFormat = `select role_id,with_grant_option from mo_catalog.mo_role_privs where role_id = %d and obj_type = "%s" and obj_id = %d and privilege_id = %d;` 1217 1218 //with_grant_option = true 1219 checkRoleHasPrivilegeWGOFormat = `select role_id from mo_catalog.mo_role_privs where with_grant_option = true and privilege_id = %d;` 1220 1221 checkRoleHasPrivilegeWGOOrWithOwnershipFormat = `select distinct role_id from mo_catalog.mo_role_privs where (with_grant_option = true and (privilege_id = %d or privilege_id = %d)) or privilege_id = %d;` 1222 1223 updateRolePrivsFormat = `update mo_catalog.mo_role_privs set operation_user_id = %d, granted_time = "%s", with_grant_option = %v where role_id = %d and obj_type = "%s" and obj_id = %d and privilege_id = %d;` 1224 1225 insertRolePrivsFormat = `insert into mo_catalog.mo_role_privs(role_id,role_name,obj_type,obj_id,privilege_id,privilege_name,privilege_level,operation_user_id,granted_time,with_grant_option) 1226 values (%d,"%s","%s",%d,%d,"%s","%s",%d,"%s",%v);` 1227 1228 deleteRolePrivsFormat = `delete from mo_catalog.mo_role_privs 1229 where role_id = %d 1230 and obj_type = "%s" 1231 and obj_id = %d 1232 and privilege_id = %d 1233 and privilege_level = "%s";` 1234 1235 checkDatabaseFormat = `select dat_id from mo_catalog.mo_database where datname = "%s";` 1236 1237 checkDatabaseWithOwnerFormat = `select dat_id, owner from mo_catalog.mo_database where datname = "%s" and account_id = %d;` 1238 1239 checkDatabaseTableFormat = `select t.rel_id from mo_catalog.mo_database d, mo_catalog.mo_tables t 1240 where d.dat_id = t.reldatabase_id 1241 and d.datname = "%s" 1242 and t.relname = "%s";` 1243 1244 //TODO:fix privilege_level string and obj_type string 1245 //For object_type : table, privilege_level : *.* 1246 checkWithGrantOptionForTableStarStar = `select rp.privilege_id,rp.with_grant_option 1247 from mo_catalog.mo_database d, mo_catalog.mo_tables t, mo_catalog.mo_role_privs rp 1248 where d.dat_id = t.reldatabase_id 1249 and rp.obj_id = 0 1250 and rp.obj_type = "%s" 1251 and rp.role_id = %d 1252 and rp.privilege_id = %d 1253 and rp.privilege_level = "%s" 1254 and rp.with_grant_option = true;` 1255 1256 //For object_type : table, privilege_level : db.* 1257 checkWithGrantOptionForTableDatabaseStar = `select rp.privilege_id,rp.with_grant_option 1258 from mo_catalog.mo_database d, mo_catalog.mo_tables t, mo_catalog.mo_role_privs rp 1259 where d.dat_id = t.reldatabase_id 1260 and rp.obj_id = 0 1261 and rp.obj_type = "%s" 1262 and rp.role_id = %d 1263 and rp.privilege_id = %d 1264 and rp.privilege_level = "%s" 1265 and d.datname = "%s" 1266 and rp.with_grant_option = true;` 1267 1268 //For object_type : table, privilege_level : db.table 1269 checkWithGrantOptionForTableDatabaseTable = `select rp.privilege_id,rp.with_grant_option 1270 from mo_catalog.mo_database d, mo_catalog.mo_tables t, mo_catalog.mo_role_privs rp 1271 where d.dat_id = t.reldatabase_id 1272 and rp.obj_id = t.rel_id 1273 and rp.obj_type = "%s" 1274 and rp.role_id = %d 1275 and rp.privilege_id = %d 1276 and rp.privilege_level = "%s" 1277 and d.datname = "%s" 1278 and t.relname = "%s" 1279 and rp.with_grant_option = true;` 1280 1281 //For object_type : database, privilege_level : * 1282 checkWithGrantOptionForDatabaseStar = `select rp.privilege_id,rp.with_grant_option 1283 from mo_catalog.mo_database d, mo_catalog.mo_tables t, mo_catalog.mo_role_privs rp 1284 where d.dat_id = t.reldatabase_id 1285 and rp.obj_id = 0 1286 and rp.obj_type = "%s" 1287 and rp.role_id = %d 1288 and rp.privilege_id = %d 1289 and rp.privilege_level = "%s" 1290 and rp.with_grant_option = true;` 1291 1292 //For object_type : database, privilege_level : *.* 1293 checkWithGrantOptionForDatabaseStarStar = `select rp.privilege_id,rp.with_grant_option 1294 from mo_catalog.mo_database d, mo_catalog.mo_tables t, mo_catalog.mo_role_privs rp 1295 where d.dat_id = t.reldatabase_id 1296 and rp.obj_id = 0 1297 and rp.obj_type = "%s" 1298 and rp.role_id = %d 1299 and rp.privilege_id = %d 1300 and rp.privilege_level = "%s" 1301 and rp.with_grant_option = true;` 1302 1303 //For object_type : database, privilege_level : db 1304 checkWithGrantOptionForDatabaseDB = `select rp.privilege_id,rp.with_grant_option 1305 from mo_catalog.mo_database d, mo_catalog.mo_tables t, mo_catalog.mo_role_privs rp 1306 where d.dat_id = t.reldatabase_id 1307 and rp.obj_id = d.dat_id 1308 and rp.obj_type = "%s" 1309 and rp.role_id = %d 1310 and rp.privilege_id = %d 1311 and rp.privilege_level = "%s" 1312 and d.datname = "%s" 1313 and rp.with_grant_option = true;` 1314 1315 //For object_type : account, privilege_level : * 1316 checkWithGrantOptionForAccountStar = `select rp.privilege_id,rp.with_grant_option 1317 from mo_catalog.mo_database d, mo_catalog.mo_tables t, mo_catalog.mo_role_privs rp 1318 where d.dat_id = t.reldatabase_id 1319 and rp.obj_id = 0 1320 and rp.obj_type = "%s" 1321 and rp.role_id = %d 1322 and rp.privilege_id = %d 1323 and rp.privilege_level = "%s" 1324 and rp.with_grant_option = true;` 1325 1326 //for database.table or table 1327 //check the role has the table level privilege for the privilege level (d.t or t) 1328 checkRoleHasTableLevelPrivilegeFormat = `select rp.privilege_id,rp.with_grant_option 1329 from mo_catalog.mo_database d, mo_catalog.mo_tables t, mo_catalog.mo_role_privs rp 1330 where d.dat_id = t.reldatabase_id 1331 and rp.obj_id = t.rel_id 1332 and rp.obj_type = "%s" 1333 and rp.role_id = %d 1334 and rp.privilege_id = %d 1335 and rp.privilege_level in ("%s","%s") 1336 and d.datname = "%s" 1337 and t.relname = "%s";` 1338 1339 //for database.* or * 1340 checkRoleHasTableLevelForDatabaseStarFormat = `select rp.privilege_id,rp.with_grant_option 1341 from mo_catalog.mo_database d, mo_catalog.mo_role_privs rp 1342 where d.dat_id = rp.obj_id 1343 and rp.obj_type = "%s" 1344 and rp.role_id = %d 1345 and rp.privilege_id = %d 1346 and rp.privilege_level in ("%s","%s") 1347 and d.datname = "%s";` 1348 1349 //for *.* 1350 checkRoleHasTableLevelForStarStarFormat = `select rp.privilege_id,rp.with_grant_option 1351 from mo_catalog.mo_role_privs rp 1352 where rp.obj_id = 0 1353 and rp.obj_type = "%s" 1354 and rp.role_id = %d 1355 and rp.privilege_id = %d 1356 and rp.privilege_level = "%s";` 1357 1358 //for * or *.* 1359 checkRoleHasDatabaseLevelForStarStarFormat = `select rp.privilege_id,rp.with_grant_option 1360 from mo_catalog.mo_role_privs rp 1361 where rp.obj_id = 0 1362 and rp.obj_type = "%s" 1363 and rp.role_id = %d 1364 and rp.privilege_id = %d 1365 and rp.privilege_level = "%s";` 1366 1367 //for database 1368 checkRoleHasDatabaseLevelForDatabaseFormat = `select rp.privilege_id,rp.with_grant_option 1369 from mo_catalog.mo_database d, mo_catalog.mo_role_privs rp 1370 where d.dat_id = rp.obj_id 1371 and rp.obj_type = "%s" 1372 and rp.role_id = %d 1373 and rp.privilege_id = %d 1374 and rp.privilege_level = "%s" 1375 and d.datname = "%s";` 1376 1377 //for * 1378 checkRoleHasAccountLevelForStarFormat = `select rp.privilege_id,rp.with_grant_option 1379 from mo_catalog.mo_role_privs rp 1380 where rp.obj_id = 0 1381 and rp.obj_type = "%s" 1382 and rp.role_id = %d 1383 and rp.privilege_id = %d 1384 and rp.privilege_level = "%s";` 1385 1386 getUserRolesExpectPublicRoleFormat = `select role.role_id, role.role_name 1387 from mo_catalog.mo_role role, mo_catalog.mo_user_grant mg 1388 where role.role_id = mg.role_id 1389 and role.role_id != %d 1390 and mg.user_id = %d 1391 order by role.created_time asc limit 1;` 1392 1393 checkUdfArgs = `select args,function_id,body from mo_catalog.mo_user_defined_function where name = "%s" and db = "%s" order by function_id;` 1394 1395 checkUdfWithDb = `select function_id,body from mo_catalog.mo_user_defined_function where db = "%s" order by function_id;` 1396 1397 checkUdfExistence = `select function_id from mo_catalog.mo_user_defined_function where name = "%s" and db = "%s" and json_extract(args, '$[*].type') %s order by function_id;` 1398 1399 checkStoredProcedureArgs = `select proc_id, args from mo_catalog.mo_stored_procedure where name = "%s" and db = "%s" order by proc_id;` 1400 1401 checkProcedureExistence = `select proc_id from mo_catalog.mo_stored_procedure where name = "%s" and db = "%s" order by proc_id;` 1402 1403 //delete role from mo_role,mo_user_grant,mo_role_grant,mo_role_privs 1404 deleteRoleFromMoRoleFormat = `delete from mo_catalog.mo_role where role_id = %d order by role_id;` 1405 1406 deleteRoleFromMoUserGrantFormat = `delete from mo_catalog.mo_user_grant where role_id = %d;` 1407 1408 deleteRoleFromMoRoleGrantFormat = `delete from mo_catalog.mo_role_grant where granted_id = %d or grantee_id = %d;` 1409 1410 deleteRoleFromMoRolePrivsFormat = `delete from mo_catalog.mo_role_privs where role_id = %d;` 1411 1412 // grant ownership on database 1413 grantOwnershipOnDatabaseFormat = `grant ownership on database %s to %s;` 1414 1415 // grant ownership on table 1416 grantOwnershipOnTableFormat = `grant ownership on table %s.%s to %s;` 1417 1418 // revoke ownership on database owner 1419 revokeOwnershipFromDatabaseFormat = `revoke ownership on database %s from %s;` 1420 1421 // revoke ownership on table owner 1422 revokeOwnershipFromTableFormat = `revoke ownership on table %s.%s from %s;` 1423 1424 // get the owner of the database 1425 getOwnerOfDatabaseFormat = `select owner from mo_catalog.mo_database where datname = '%s';` 1426 1427 // get the owner of the table 1428 getOwnerOfTableFormat = `select owner from mo_catalog.mo_tables where reldatabase = '%s' and relname = '%s';` 1429 1430 // get the roles of the current user 1431 getRolesOfCurrentUserFormat = `select role_id from mo_catalog.mo_user_grant where user_id = %d;` 1432 1433 //delete user from mo_user,mo_user_grant 1434 deleteUserFromMoUserFormat = `delete from mo_catalog.mo_user where user_id = %d;` 1435 1436 deleteUserFromMoUserGrantFormat = `delete from mo_catalog.mo_user_grant where user_id = %d;` 1437 1438 // delete user defined function from mo_user_defined_function 1439 deleteUserDefinedFunctionFormat = `delete from mo_catalog.mo_user_defined_function where function_id = %d;` 1440 1441 // delete stored procedure from mo_user_defined_function 1442 deleteStoredProcedureFormat = `delete from mo_catalog.mo_stored_procedure where proc_id = %d;` 1443 1444 // delete a tuple from mo_mysql_compatibility_mode when drop a database 1445 deleteMysqlCompatbilityModeFormat = `delete from mo_catalog.mo_mysql_compatibility_mode where dat_name = "%s";` 1446 1447 getSystemVariableValueWithDatabaseFormat = `select variable_value from mo_catalog.mo_mysql_compatibility_mode where dat_name = "%s" and variable_name = "%s";` 1448 1449 getSystemVariablesWithAccountFromat = `select variable_name, variable_value from mo_catalog.mo_mysql_compatibility_mode where account_id = %d and system_variables = true;` 1450 1451 getSystemVariableValueWithAccountFromat = `select variable_value from mo_catalog.mo_mysql_compatibility_mode where account_id = %d and variable_name = '%s' and system_variables = true;` 1452 1453 updateSystemVariableValueFormat = `update mo_catalog.mo_mysql_compatibility_mode set variable_value = '%s' where account_id = %d and variable_name = '%s';` 1454 1455 updateConfigurationByDbNameAndAccountNameFormat = `update mo_catalog.mo_mysql_compatibility_mode set variable_value = '%s' where account_name = '%s' and dat_name = '%s' and variable_name = '%s';` 1456 1457 updateConfigurationByAccountNameFormat = `update mo_catalog.mo_mysql_compatibility_mode set variable_value = '%s' where account_name = '%s' and variable_name = '%s';` 1458 1459 checkStageFormat = `select stage_id, stage_name from mo_catalog.mo_stages where stage_name = "%s" order by stage_id;` 1460 1461 checkStageStatusFormat = `select stage_id, stage_name from mo_catalog.mo_stages where stage_status = "%s" order by stage_id;` 1462 1463 checkStageStatusWithStageNameFormat = `select url, stage_status from mo_catalog.mo_stages where stage_name = "%s" order by stage_id;` 1464 1465 dropStageFormat = `delete from mo_catalog.mo_stages where stage_name = '%s' order by stage_id;` 1466 1467 updateStageUrlFormat = `update mo_catalog.mo_stages set url = '%s' where stage_name = '%s' order by stage_id;` 1468 1469 updateStageCredentialsFormat = `update mo_catalog.mo_stages set stage_credentials = '%s' where stage_name = '%s' order by stage_id;` 1470 1471 updateStageStatusFormat = `update mo_catalog.mo_stages set stage_status = '%s' where stage_name = '%s' order by stage_id;` 1472 1473 updateStageCommentFormat = `update mo_catalog.mo_stages set comment = '%s' where stage_name = '%s' order by stage_id;` 1474 1475 getDbIdAndTypFormat = `select dat_id,dat_type from mo_catalog.mo_database where datname = '%s' and account_id = %d;` 1476 insertIntoMoPubsFormat = `insert into mo_catalog.mo_pubs(pub_name,database_name,database_id,all_table,table_list,account_list,created_time,owner,creator,comment) values ('%s','%s',%d,%t,'%s','%s',now(),%d,%d,'%s');` 1477 getPubInfoFormat = `select account_list,comment,database_name,database_id from mo_catalog.mo_pubs where pub_name = '%s';` 1478 updatePubInfoFormat = `update mo_catalog.mo_pubs set account_list = '%s',comment = '%s', database_name = '%s', database_id = %d, update_time = now() where pub_name = '%s';` 1479 dropPubFormat = `delete from mo_catalog.mo_pubs where pub_name = '%s';` 1480 getAccountIdAndStatusFormat = `select account_id,status from mo_catalog.mo_account where account_name = '%s';` 1481 getPubInfoForSubFormat = `select database_name,account_list from mo_catalog.mo_pubs where pub_name = "%s";` 1482 getDbPubCountFormat = `select count(1) from mo_catalog.mo_pubs where database_name = '%s';` 1483 1484 fetchSqlOfSpFormat = `select body, args from mo_catalog.mo_stored_procedure where name = '%s' and db = '%s' order by proc_id;` 1485 ) 1486 1487 var ( 1488 objectType2privilegeLevels = map[objectType][]privilegeLevelType{ 1489 objectTypeAccount: {privilegeLevelStar}, 1490 objectTypeDatabase: {privilegeLevelDatabase, 1491 privilegeLevelStar, privilegeLevelStarStar}, 1492 objectTypeTable: {privilegeLevelStarStar, 1493 privilegeLevelDatabaseStar, privilegeLevelStar, 1494 privilegeLevelDatabaseTable, privilegeLevelTable}, 1495 } 1496 1497 // the databases that can not operated by the real user 1498 bannedCatalogDatabases = map[string]int8{ 1499 "mo_catalog": 0, 1500 "information_schema": 0, 1501 "system": 0, 1502 "system_metrics": 0, 1503 "mysql": 0, 1504 "mo_task": 0, 1505 } 1506 1507 // the privileges that can not be granted or revoked 1508 bannedPrivileges = map[PrivilegeType]int8{ 1509 PrivilegeTypeCreateAccount: 0, 1510 PrivilegeTypeAlterAccount: 0, 1511 PrivilegeTypeDropAccount: 0, 1512 PrivilegeTypeUpgradeAccount: 0, 1513 } 1514 ) 1515 1516 func getSqlForAccountIdAndStatus(ctx context.Context, accName string, check bool) (string, error) { 1517 if check && accountNameIsInvalid(accName) { 1518 return "", moerr.NewInternalError(ctx, fmt.Sprintf("account name %s is invalid", accName)) 1519 } 1520 return fmt.Sprintf(getAccountIdAndStatusFormat, accName), nil 1521 } 1522 1523 func getSqlForPubInfoForSub(ctx context.Context, pubName string, check bool) (string, error) { 1524 if check && nameIsInvalid(pubName) { 1525 return "", moerr.NewInternalError(ctx, fmt.Sprintf("pub name %s is invalid", pubName)) 1526 } 1527 return fmt.Sprintf(getPubInfoForSubFormat, pubName), nil 1528 } 1529 1530 func getSqlForCheckTenant(ctx context.Context, tenant string) (string, error) { 1531 err := inputNameIsInvalid(ctx, tenant) 1532 if err != nil { 1533 return "", err 1534 } 1535 return fmt.Sprintf(checkTenantFormat, tenant), nil 1536 } 1537 1538 func getSqlForCheckStage(ctx context.Context, stage string) (string, error) { 1539 err := inputNameIsInvalid(ctx, stage) 1540 if err != nil { 1541 return "", err 1542 } 1543 return fmt.Sprintf(checkStageFormat, stage), nil 1544 } 1545 1546 func getSqlForCheckStageStatus(ctx context.Context, status string) string { 1547 return fmt.Sprintf(checkStageStatusFormat, status) 1548 } 1549 1550 func getSqlForCheckUdfWithDb(dbName string) string { 1551 return fmt.Sprintf(checkUdfWithDb, dbName) 1552 } 1553 func getSqlForCheckStageStatusWithStageName(ctx context.Context, stage string) (string, error) { 1554 err := inputNameIsInvalid(ctx, stage) 1555 if err != nil { 1556 return "", err 1557 } 1558 return fmt.Sprintf(checkStageStatusWithStageNameFormat, stage), nil 1559 } 1560 1561 func getSqlForInsertIntoMoStages(ctx context.Context, stageName, url, credentials, status, createdTime, comment string) (string, error) { 1562 err := inputNameIsInvalid(ctx, stageName) 1563 if err != nil { 1564 return "", err 1565 } 1566 return fmt.Sprintf(insertIntoMoStages, stageName, url, credentials, status, createdTime, comment), nil 1567 } 1568 1569 func getSqlForDropStage(stageName string) string { 1570 return fmt.Sprintf(dropStageFormat, stageName) 1571 } 1572 1573 func getsqlForUpdateStageUrl(stageName, url string) string { 1574 return fmt.Sprintf(updateStageUrlFormat, url, stageName) 1575 } 1576 1577 func getsqlForUpdateStageCredentials(stageName, credentials string) string { 1578 return fmt.Sprintf(updateStageCredentialsFormat, credentials, stageName) 1579 } 1580 1581 func getsqlForUpdateStageStatus(stageName, status string) string { 1582 return fmt.Sprintf(updateStageStatusFormat, status, stageName) 1583 } 1584 1585 func getsqlForUpdateStageComment(stageName, comment string) string { 1586 return fmt.Sprintf(updateStageCommentFormat, comment, stageName) 1587 } 1588 1589 func getSqlForGetAccountName(tenantId uint32) string { 1590 return fmt.Sprintf(getTenantNameForMat, tenantId) 1591 } 1592 1593 func getSqlForUpdateCommentsOfAccount(ctx context.Context, comment, account string) (string, error) { 1594 err := inputNameIsInvalid(ctx, account) 1595 if err != nil { 1596 return "", err 1597 } 1598 return fmt.Sprintf(updateCommentsOfAccountFormat, comment, account), nil 1599 } 1600 1601 func getSqlForUpdateStatusOfAccount(ctx context.Context, status, timestamp, account string) (string, error) { 1602 err := inputNameIsInvalid(ctx, status, account) 1603 if err != nil { 1604 return "", err 1605 } 1606 return fmt.Sprintf(updateStatusOfAccountFormat, status, timestamp, account), nil 1607 } 1608 1609 func getSqlForUpdateStatusAndVersionOfAccount(ctx context.Context, status, account string, version uint64) (string, error) { 1610 err := inputNameIsInvalid(ctx, status, account) 1611 if err != nil { 1612 return "", err 1613 } 1614 return fmt.Sprintf(updateStatusAndVersionOfAccountFormat, status, version, account), nil 1615 } 1616 1617 func getSqlForDeleteAccountFromMoAccount(ctx context.Context, account string) (string, error) { 1618 err := inputNameIsInvalid(ctx, account) 1619 if err != nil { 1620 return "", err 1621 } 1622 return fmt.Sprintf(deleteAccountFromMoAccountFormat, account), nil 1623 } 1624 1625 func getSqlForPasswordOfUser(ctx context.Context, user string) (string, error) { 1626 err := inputNameIsInvalid(ctx, user) 1627 if err != nil { 1628 return "", err 1629 } 1630 return fmt.Sprintf(getPasswordOfUserFormat, user), nil 1631 } 1632 1633 func getSqlForUpdatePasswordOfUser(ctx context.Context, password, user string) (string, error) { 1634 err := inputNameIsInvalid(ctx, user) 1635 if err != nil { 1636 return "", err 1637 } 1638 return fmt.Sprintf(updatePasswordOfUserFormat, password, user), nil 1639 } 1640 1641 func getSqlForCheckRoleExists(ctx context.Context, roleID int, roleName string) (string, error) { 1642 err := inputNameIsInvalid(ctx, roleName) 1643 if err != nil { 1644 return "", err 1645 } 1646 return fmt.Sprintf(checkRoleExistsFormat, roleID, roleName), nil 1647 } 1648 1649 func getSqlForRoleNameOfRoleId(roleId int64) string { 1650 return fmt.Sprintf(roleNameOfRoleIdFormat, roleId) 1651 } 1652 1653 func getSqlForRoleIdOfRole(ctx context.Context, roleName string) (string, error) { 1654 err := inputNameIsInvalid(ctx, roleName) 1655 if err != nil { 1656 return "", err 1657 } 1658 return fmt.Sprintf(roleIdOfRoleFormat, roleName), nil 1659 } 1660 1661 func getSqlForRoleOfUser(ctx context.Context, userID int64, roleName string) (string, error) { 1662 err := inputNameIsInvalid(ctx, roleName) 1663 if err != nil { 1664 return "", err 1665 } 1666 return fmt.Sprintf(getRoleOfUserFormat, userID, roleName), nil 1667 } 1668 1669 func getSqlForRoleIdOfUserId(userId int) string { 1670 return fmt.Sprintf(getRoleIdOfUserIdFormat, userId) 1671 } 1672 1673 func getSqlForCheckUserGrant(roleId, userId int64) string { 1674 return fmt.Sprintf(checkUserGrantFormat, roleId, userId) 1675 } 1676 1677 func getSqlForCheckUserHasRole(ctx context.Context, userName string, roleId int64) (string, error) { 1678 err := inputNameIsInvalid(ctx, userName) 1679 if err != nil { 1680 return "", err 1681 } 1682 return fmt.Sprintf(checkUserHasRoleFormat, userName, roleId), nil 1683 } 1684 1685 func getSqlForCheckUserGrantWGO(roleId, userId int64) string { 1686 return fmt.Sprintf(checkUserGrantWGOFormat, roleId, userId) 1687 } 1688 1689 func getSqlForUpdateUserGrant(roleId, userId int64, timestamp string, withGrantOption bool) string { 1690 return fmt.Sprintf(updateUserGrantFormat, timestamp, withGrantOption, roleId, userId) 1691 } 1692 1693 func getSqlForInsertUserGrant(roleId, userId int64, timestamp string, withGrantOption bool) string { 1694 return fmt.Sprintf(insertUserGrantFormat, roleId, userId, timestamp, withGrantOption) 1695 } 1696 1697 func getSqlForDeleteUserGrant(roleId, userId int64) string { 1698 return fmt.Sprintf(deleteUserGrantFormat, roleId, userId) 1699 } 1700 1701 func getSqlForCheckRoleGrant(grantedId, granteeId int64) string { 1702 return fmt.Sprintf(checkRoleGrantFormat, grantedId, granteeId) 1703 } 1704 1705 func getSqlForCheckRoleGrantWGO(grantedId int64) string { 1706 return fmt.Sprintf(getRoleGrantWGOFormat, grantedId) 1707 } 1708 1709 func getSqlForUpdateRoleGrant(grantedId, granteeId, operationRoleId, operationUserId int64, timestamp string, withGrantOption bool) string { 1710 return fmt.Sprintf(updateRoleGrantFormat, operationRoleId, operationUserId, timestamp, withGrantOption, grantedId, granteeId) 1711 } 1712 1713 func getSqlForInsertRoleGrant(grantedId, granteeId, operationRoleId, operationUserId int64, timestamp string, withGrantOption bool) string { 1714 return fmt.Sprintf(insertRoleGrantFormat, grantedId, granteeId, operationRoleId, operationUserId, timestamp, withGrantOption) 1715 } 1716 1717 func getSqlForDeleteRoleGrant(grantedId, granteeId int64) string { 1718 return fmt.Sprintf(deleteRoleGrantFormat, grantedId, granteeId) 1719 } 1720 1721 func getSqlForGetAllStuffRoleGrantFormat() string { 1722 return getAllStuffRoleGrantFormat 1723 } 1724 1725 func getSqlForInheritedRoleIdOfRoleId(roleId int64) string { 1726 return fmt.Sprintf(getInheritedRoleIdOfRoleIdFormat, roleId) 1727 } 1728 1729 func getSqlForCheckRoleHasPrivilege(roleId int64, objType objectType, objId, privilegeId int64) string { 1730 return fmt.Sprintf(checkRoleHasPrivilegeFormat, roleId, objType, objId, privilegeId) 1731 } 1732 1733 func getSqlForCheckRoleHasPrivilegeWGO(privilegeId int64) string { 1734 return fmt.Sprintf(checkRoleHasPrivilegeWGOFormat, privilegeId) 1735 } 1736 1737 func getSqlForCheckRoleHasPrivilegeWGOOrWithOwnerShip(privilegeId, allPrivId, ownershipPrivId int64) string { 1738 return fmt.Sprintf(checkRoleHasPrivilegeWGOOrWithOwnershipFormat, privilegeId, allPrivId, ownershipPrivId) 1739 } 1740 1741 func getSqlForUpdateRolePrivs(userId int64, timestamp string, withGrantOption bool, roleId int64, objType objectType, objId, privilegeId int64) string { 1742 return fmt.Sprintf(updateRolePrivsFormat, userId, timestamp, withGrantOption, roleId, objType, objId, privilegeId) 1743 } 1744 1745 func getSqlForInsertRolePrivs(roleId int64, roleName, objType string, objId, privilegeId int64, privilegeName, privilegeLevel string, operationUserId int64, grantedTime string, withGrantOption bool) string { 1746 return fmt.Sprintf(insertRolePrivsFormat, roleId, roleName, objType, objId, privilegeId, privilegeName, privilegeLevel, operationUserId, grantedTime, withGrantOption) 1747 } 1748 1749 func getSqlForDeleteRolePrivs(roleId int64, objType string, objId, privilegeId int64, privilegeLevel string) string { 1750 return fmt.Sprintf(deleteRolePrivsFormat, roleId, objType, objId, privilegeId, privilegeLevel) 1751 } 1752 1753 func getSqlForCheckWithGrantOptionForTableStarStar(roleId int64, privId PrivilegeType) string { 1754 return fmt.Sprintf(checkWithGrantOptionForTableStarStar, objectTypeTable, roleId, privId, privilegeLevelStarStar) 1755 } 1756 1757 func getSqlForCheckWithGrantOptionForTableDatabaseStar(ctx context.Context, roleId int64, privId PrivilegeType, dbName string) (string, error) { 1758 err := inputNameIsInvalid(ctx, dbName) 1759 if err != nil { 1760 return "", err 1761 } 1762 return fmt.Sprintf(checkWithGrantOptionForTableDatabaseStar, objectTypeTable, roleId, privId, privilegeLevelDatabaseStar, dbName), nil 1763 } 1764 1765 func getSqlForCheckWithGrantOptionForTableDatabaseTable(ctx context.Context, roleId int64, privId PrivilegeType, dbName string, tableName string) (string, error) { 1766 err := inputNameIsInvalid(ctx, dbName, tableName) 1767 if err != nil { 1768 return "", err 1769 } 1770 return fmt.Sprintf(checkWithGrantOptionForTableDatabaseTable, objectTypeTable, roleId, privId, privilegeLevelDatabaseTable, dbName, tableName), nil 1771 } 1772 1773 func getSqlForCheckWithGrantOptionForDatabaseStar(roleId int64, privId PrivilegeType) string { 1774 return fmt.Sprintf(checkWithGrantOptionForDatabaseStar, objectTypeDatabase, roleId, privId, privilegeLevelStar) 1775 } 1776 1777 func getSqlForCheckWithGrantOptionForDatabaseStarStar(roleId int64, privId PrivilegeType) string { 1778 return fmt.Sprintf(checkWithGrantOptionForDatabaseStarStar, objectTypeDatabase, roleId, privId, privilegeLevelStarStar) 1779 } 1780 1781 func getSqlForCheckWithGrantOptionForDatabaseDB(ctx context.Context, roleId int64, privId PrivilegeType, dbName string) (string, error) { 1782 err := inputNameIsInvalid(ctx, dbName) 1783 if err != nil { 1784 return "", err 1785 } 1786 return fmt.Sprintf(checkWithGrantOptionForDatabaseDB, objectTypeDatabase, roleId, privId, privilegeLevelDatabase, dbName), nil 1787 } 1788 1789 func getSqlForCheckWithGrantOptionForAccountStar(roleId int64, privId PrivilegeType) string { 1790 return fmt.Sprintf(checkWithGrantOptionForAccountStar, objectTypeAccount, roleId, privId, privilegeLevelStarStar) 1791 } 1792 1793 func getSqlForCheckRoleHasTableLevelPrivilege(ctx context.Context, roleId int64, privId PrivilegeType, dbName string, tableName string) (string, error) { 1794 err := inputNameIsInvalid(ctx, dbName, tableName) 1795 if err != nil { 1796 return "", err 1797 } 1798 return fmt.Sprintf(checkRoleHasTableLevelPrivilegeFormat, objectTypeTable, roleId, privId, privilegeLevelDatabaseTable, privilegeLevelTable, dbName, tableName), nil 1799 } 1800 1801 func getSqlForCheckRoleHasTableLevelForDatabaseStar(ctx context.Context, roleId int64, privId PrivilegeType, dbName string) (string, error) { 1802 err := inputNameIsInvalid(ctx, dbName) 1803 if err != nil { 1804 return "", err 1805 } 1806 return fmt.Sprintf(checkRoleHasTableLevelForDatabaseStarFormat, objectTypeTable, roleId, privId, privilegeLevelDatabaseStar, privilegeLevelStar, dbName), nil 1807 } 1808 1809 func getSqlForCheckRoleHasTableLevelForStarStar(roleId int64, privId PrivilegeType) string { 1810 return fmt.Sprintf(checkRoleHasTableLevelForStarStarFormat, objectTypeTable, roleId, privId, privilegeLevelStarStar) 1811 } 1812 1813 func getSqlForCheckRoleHasDatabaseLevelForStarStar(roleId int64, privId PrivilegeType, level privilegeLevelType) string { 1814 return fmt.Sprintf(checkRoleHasDatabaseLevelForStarStarFormat, objectTypeDatabase, roleId, privId, level) 1815 } 1816 1817 func getSqlForCheckRoleHasDatabaseLevelForDatabase(ctx context.Context, roleId int64, privId PrivilegeType, dbName string) (string, error) { 1818 err := inputNameIsInvalid(ctx, dbName) 1819 if err != nil { 1820 return "", err 1821 } 1822 return fmt.Sprintf(checkRoleHasDatabaseLevelForDatabaseFormat, objectTypeDatabase, roleId, privId, privilegeLevelDatabase, dbName), nil 1823 } 1824 1825 func getSqlForCheckRoleHasAccountLevelForStar(roleId int64, privId PrivilegeType) string { 1826 return fmt.Sprintf(checkRoleHasAccountLevelForStarFormat, objectTypeAccount, roleId, privId, privilegeLevelStar) 1827 } 1828 1829 func getSqlForgetUserRolesExpectPublicRole(pRoleId int, userId uint32) string { 1830 return fmt.Sprintf(getUserRolesExpectPublicRoleFormat, pRoleId, userId) 1831 } 1832 1833 func getSqlForGetDbIdAndType(ctx context.Context, dbName string, checkNameValid bool, account_id uint64) (string, error) { 1834 if checkNameValid { 1835 err := inputNameIsInvalid(ctx, dbName) 1836 if err != nil { 1837 return "", err 1838 } 1839 } 1840 return fmt.Sprintf(getDbIdAndTypFormat, dbName, account_id), nil 1841 } 1842 1843 func getSqlForInsertIntoMoPubs(ctx context.Context, pubName, databaseName string, databaseId uint64, allTable bool, tableList, accountList string, owner, creator uint32, comment string, checkNameValid bool) (string, error) { 1844 if checkNameValid { 1845 err := inputNameIsInvalid(ctx, pubName, databaseName) 1846 if err != nil { 1847 return "", err 1848 } 1849 } 1850 return fmt.Sprintf(insertIntoMoPubsFormat, pubName, databaseName, databaseId, allTable, tableList, accountList, owner, creator, comment), nil 1851 } 1852 1853 func getSqlForGetPubInfo(ctx context.Context, pubName string, checkNameValid bool) (string, error) { 1854 if checkNameValid { 1855 err := inputNameIsInvalid(ctx, pubName) 1856 if err != nil { 1857 return "", err 1858 } 1859 } 1860 return fmt.Sprintf(getPubInfoFormat, pubName), nil 1861 } 1862 1863 func getSqlForUpdatePubInfo(ctx context.Context, pubName string, accountList string, comment string, dbName string, dbId uint64, checkNameValid bool) (string, error) { 1864 if checkNameValid { 1865 err := inputNameIsInvalid(ctx, pubName) 1866 if err != nil { 1867 return "", err 1868 } 1869 } 1870 return fmt.Sprintf(updatePubInfoFormat, accountList, comment, dbName, dbId, pubName), nil 1871 } 1872 1873 func getSqlForDropPubInfo(ctx context.Context, pubName string, checkNameValid bool) (string, error) { 1874 if checkNameValid { 1875 err := inputNameIsInvalid(ctx, pubName) 1876 if err != nil { 1877 return "", err 1878 } 1879 } 1880 return fmt.Sprintf(dropPubFormat, pubName), nil 1881 } 1882 1883 func getSqlForDbPubCount(ctx context.Context, dbName string) (string, error) { 1884 1885 err := inputNameIsInvalid(ctx, dbName) 1886 if err != nil { 1887 return "", err 1888 } 1889 return fmt.Sprintf(getDbPubCountFormat, dbName), nil 1890 } 1891 1892 func getSqlForCheckDatabase(ctx context.Context, dbName string) (string, error) { 1893 err := inputNameIsInvalid(ctx, dbName) 1894 if err != nil { 1895 return "", err 1896 } 1897 return fmt.Sprintf(checkDatabaseFormat, dbName), nil 1898 } 1899 1900 func getSqlForCheckDatabaseWithOwner(ctx context.Context, dbName string, accountId int64) (string, error) { 1901 err := inputNameIsInvalid(ctx, dbName) 1902 if err != nil { 1903 return "", err 1904 } 1905 return fmt.Sprintf(checkDatabaseWithOwnerFormat, dbName, accountId), nil 1906 } 1907 1908 func getSqlForCheckDatabaseTable(ctx context.Context, dbName, tableName string) (string, error) { 1909 err := inputNameIsInvalid(ctx, dbName, tableName) 1910 if err != nil { 1911 return "", err 1912 } 1913 return fmt.Sprintf(checkDatabaseTableFormat, dbName, tableName), nil 1914 } 1915 1916 func getSqlForDeleteRole(roleId int64) []string { 1917 return []string{ 1918 fmt.Sprintf(deleteRoleFromMoRoleFormat, roleId), 1919 fmt.Sprintf(deleteRoleFromMoUserGrantFormat, roleId), 1920 fmt.Sprintf(deleteRoleFromMoRoleGrantFormat, roleId, roleId), 1921 fmt.Sprintf(deleteRoleFromMoRolePrivsFormat, roleId), 1922 } 1923 } 1924 1925 func getSqlForDropAccount() []string { 1926 return dropSqls 1927 } 1928 1929 func getSqlForDeleteUser(userId int64) []string { 1930 return []string{ 1931 fmt.Sprintf(deleteUserFromMoUserFormat, userId), 1932 fmt.Sprintf(deleteUserFromMoUserGrantFormat, userId), 1933 } 1934 } 1935 1936 func getSqlForDeleteMysqlCompatbilityMode(dtname string) string { 1937 return fmt.Sprintf(deleteMysqlCompatbilityModeFormat, dtname) 1938 } 1939 1940 func getSqlForGetSystemVariableValueWithDatabase(dtname, variable_name string) string { 1941 return fmt.Sprintf(getSystemVariableValueWithDatabaseFormat, dtname, variable_name) 1942 } 1943 1944 func getSystemVariablesWithAccount(accountId uint64) string { 1945 return fmt.Sprintf(getSystemVariablesWithAccountFromat, accountId) 1946 } 1947 1948 // getSqlForGetSystemVariableValueWithAccount will get sql for get variable value with specific account 1949 func getSqlForGetSystemVariableValueWithAccount(accountId uint64, varName string) string { 1950 return fmt.Sprintf(getSystemVariableValueWithAccountFromat, accountId, varName) 1951 } 1952 1953 // getSqlForUpdateSystemVariableValue returns a SQL query to update the value of a system variable for a given account. 1954 func getSqlForUpdateSystemVariableValue(varValue string, accountId uint64, varName string) string { 1955 return fmt.Sprintf(updateSystemVariableValueFormat, varValue, accountId, varName) 1956 } 1957 1958 func getSqlForupdateConfigurationByDbNameAndAccountName(ctx context.Context, varValue, accountName, dbName, varName string) (string, error) { 1959 err := inputNameIsInvalid(ctx, dbName) 1960 if err != nil { 1961 return "", err 1962 } 1963 return fmt.Sprintf(updateConfigurationByDbNameAndAccountNameFormat, varValue, accountName, dbName, varName), nil 1964 } 1965 1966 func getSqlForupdateConfigurationByAccount(ctx context.Context, varValue, accountName, varName string) (string, error) { 1967 err := inputNameIsInvalid(ctx, accountName) 1968 if err != nil { 1969 return "", err 1970 } 1971 return fmt.Sprintf(updateConfigurationByAccountNameFormat, varValue, accountName, varName), nil 1972 } 1973 1974 func getSqlForSpBody(_ context.Context, name string, db string) (string, error) { 1975 return fmt.Sprintf(fetchSqlOfSpFormat, name, db), nil 1976 } 1977 1978 // isIndexTable decides a table is the index table or not 1979 func isIndexTable(name string) bool { 1980 return strings.HasPrefix(name, catalog.IndexTableNamePrefix) 1981 } 1982 1983 // isClusterTable decides a table is the cluster table or not 1984 func isClusterTable(dbName, name string) bool { 1985 if dbName == moCatalog { 1986 if _, ok := sysAccountTables[name]; ok { 1987 return false 1988 } 1989 1990 //if it is neither among the tables nor the index table, 1991 //it is the cluster table. 1992 if _, ok := predefinedTables[name]; !ok && !isIndexTable(name) { 1993 return true 1994 } 1995 } 1996 return false 1997 } 1998 1999 // getSqlForGrantOwnershipOnDatabase get the sql for grant ownership on database 2000 func getSqlForGrantOwnershipOnDatabase(dbName, roleName string) string { 2001 return fmt.Sprintf(grantOwnershipOnDatabaseFormat, dbName, roleName) 2002 } 2003 2004 // getSqlForGrantOwnershipOnTable get the sql for grant ownership on database 2005 func getSqlForGrantOwnershipOnTable(dbName, tbName, roleName string) string { 2006 return fmt.Sprintf(grantOwnershipOnTableFormat, dbName, tbName, roleName) 2007 } 2008 2009 // getSqlForRevokeOwnershipFromDatabase get the sql for revoke ownership on database 2010 func getSqlForRevokeOwnershipFromDatabase(dbName, roleName string) string { 2011 return fmt.Sprintf(revokeOwnershipFromDatabaseFormat, dbName, roleName) 2012 } 2013 2014 // getSqlForGrantOwnershipOnTable get the sql for grant ownership on database 2015 func getSqlForRevokeOwnershipFromTable(dbName, tbName, roleName string) string { 2016 return fmt.Sprintf(revokeOwnershipFromTableFormat, dbName, tbName, roleName) 2017 } 2018 2019 // getSqlForGetOwnerOfDatabase get the sql for get the owner of the database 2020 func getSqlForGetOwnerOfDatabase(dbName string) string { 2021 return fmt.Sprintf(getOwnerOfDatabaseFormat, dbName) 2022 } 2023 2024 // getSqlForGetOwnerOfTable get the sql for get the owner of the table 2025 func getSqlForGetOwnerOfTable(dbName, tbName string) string { 2026 return fmt.Sprintf(getOwnerOfTableFormat, dbName, tbName) 2027 } 2028 2029 // getSqlForGetRolesOfCurrentUser get the sql for get the roles of the user 2030 func getSqlForGetRolesOfCurrentUser(userId int64) string { 2031 return fmt.Sprintf(getRolesOfCurrentUserFormat, userId) 2032 } 2033 2034 // getSqlForCheckProcedureExistence get the sql for check the procedure exist or not 2035 func getSqlForCheckProcedureExistence(pdName, dbName string) string { 2036 return fmt.Sprintf(checkProcedureExistence, pdName, dbName) 2037 } 2038 2039 func isBannedDatabase(dbName string) bool { 2040 _, ok := bannedCatalogDatabases[dbName] 2041 return ok 2042 } 2043 2044 func isBannedPrivilege(priv PrivilegeType) bool { 2045 _, ok := bannedPrivileges[priv] 2046 return ok 2047 } 2048 2049 type specialTag int 2050 2051 const ( 2052 specialTagNone specialTag = 0 2053 specialTagAdmin specialTag = 1 2054 specialTagWithGrantOption specialTag = 2 2055 specialTagOwnerOfObject specialTag = 4 2056 ) 2057 2058 type privilegeKind int 2059 2060 const ( 2061 privilegeKindGeneral privilegeKind = iota //as same as definition in the privilegeEntriesMap 2062 privilegeKindInherit //General + with_grant_option 2063 privilegeKindSpecial //no obj_type,obj_id,privilege_level. only needs (MOADMIN / ACCOUNTADMIN, with_grant_option, owner of object) 2064 privilegeKindNone //does not need any privilege 2065 ) 2066 2067 type clusterTableOperationType int 2068 2069 const ( 2070 clusterTableNone clusterTableOperationType = iota 2071 clusterTableCreate 2072 clusterTableSelect //read only 2073 clusterTableModify //include insert,update,delete 2074 clusterTableDrop 2075 ) 2076 2077 type privilege struct { 2078 kind privilegeKind 2079 //account: the privilege can be defined before constructing the plan. 2080 //database: (do not need the database_id) the privilege can be defined before constructing the plan. 2081 //table: need table id. the privilege can be defined after constructing the plan. 2082 //function: need function id ? 2083 objType objectType 2084 entries []privilegeEntry 2085 special specialTag 2086 //the statement writes the database or table directly like drop database and table 2087 writeDatabaseAndTableDirectly bool 2088 //operate the cluster table 2089 isClusterTable bool 2090 //operation on cluster table, 2091 clusterTableOperation clusterTableOperationType 2092 //can execute in restricted status 2093 canExecInRestricted bool 2094 } 2095 2096 func (p *privilege) objectType() objectType { 2097 return p.objType 2098 } 2099 2100 func (p *privilege) privilegeKind() privilegeKind { 2101 return p.kind 2102 } 2103 2104 type privilegeEntryType int 2105 2106 const ( 2107 privilegeEntryTypeGeneral privilegeEntryType = iota 2108 privilegeEntryTypeCompound //multi privileges take effect together 2109 ) 2110 2111 // privilegeItem is the item for in the compound entry 2112 type privilegeItem struct { 2113 privilegeTyp PrivilegeType 2114 role *tree.Role 2115 users []*tree.User 2116 dbName string 2117 tableName string 2118 isClusterTable bool 2119 clusterTableOperation clusterTableOperationType 2120 } 2121 2122 // compoundEntry is the entry has multi privilege items 2123 type compoundEntry struct { 2124 items []privilegeItem 2125 } 2126 2127 // privilegeEntry denotes the entry of the privilege that appears in the table mo_role_privs 2128 type privilegeEntry struct { 2129 privilegeId PrivilegeType 2130 //the predefined privilege level for the privilege. 2131 //it is not always the same as the one in the runtime. 2132 privilegeLevel privilegeLevelType 2133 objType objectType 2134 objId int 2135 withGrantOption bool 2136 //for object type table 2137 databaseName string 2138 tableName string 2139 privilegeEntryTyp privilegeEntryType 2140 compound *compoundEntry 2141 } 2142 2143 var ( 2144 //initial privilege entries 2145 privilegeEntriesMap = map[PrivilegeType]privilegeEntry{ 2146 PrivilegeTypeCreateAccount: {PrivilegeTypeCreateAccount, privilegeLevelStar, objectTypeAccount, objectIDAll, false, "", "", privilegeEntryTypeGeneral, nil}, 2147 PrivilegeTypeDropAccount: {PrivilegeTypeDropAccount, privilegeLevelStar, objectTypeAccount, objectIDAll, false, "", "", privilegeEntryTypeGeneral, nil}, 2148 PrivilegeTypeAlterAccount: {PrivilegeTypeAlterAccount, privilegeLevelStar, objectTypeAccount, objectIDAll, false, "", "", privilegeEntryTypeGeneral, nil}, 2149 PrivilegeTypeUpgradeAccount: {PrivilegeTypeUpgradeAccount, privilegeLevelStar, objectTypeAccount, objectIDAll, false, "", "", privilegeEntryTypeGeneral, nil}, 2150 PrivilegeTypeCreateUser: {PrivilegeTypeCreateUser, privilegeLevelStar, objectTypeAccount, objectIDAll, true, "", "", privilegeEntryTypeGeneral, nil}, 2151 PrivilegeTypeDropUser: {PrivilegeTypeDropUser, privilegeLevelStar, objectTypeAccount, objectIDAll, true, "", "", privilegeEntryTypeGeneral, nil}, 2152 PrivilegeTypeAlterUser: {PrivilegeTypeAlterUser, privilegeLevelStar, objectTypeAccount, objectIDAll, true, "", "", privilegeEntryTypeGeneral, nil}, 2153 PrivilegeTypeCreateRole: {PrivilegeTypeCreateRole, privilegeLevelStar, objectTypeAccount, objectIDAll, true, "", "", privilegeEntryTypeGeneral, nil}, 2154 PrivilegeTypeDropRole: {PrivilegeTypeDropRole, privilegeLevelStar, objectTypeAccount, objectIDAll, true, "", "", privilegeEntryTypeGeneral, nil}, 2155 PrivilegeTypeAlterRole: {PrivilegeTypeAlterRole, privilegeLevelStar, objectTypeAccount, objectIDAll, true, "", "", privilegeEntryTypeGeneral, nil}, 2156 PrivilegeTypeCreateDatabase: {PrivilegeTypeCreateDatabase, privilegeLevelStar, objectTypeAccount, objectIDAll, true, "", "", privilegeEntryTypeGeneral, nil}, 2157 PrivilegeTypeDropDatabase: {PrivilegeTypeDropDatabase, privilegeLevelStar, objectTypeAccount, objectIDAll, true, "", "", privilegeEntryTypeGeneral, nil}, 2158 PrivilegeTypeShowDatabases: {PrivilegeTypeShowDatabases, privilegeLevelStar, objectTypeAccount, objectIDAll, true, "", "", privilegeEntryTypeGeneral, nil}, 2159 PrivilegeTypeConnect: {PrivilegeTypeConnect, privilegeLevelStar, objectTypeAccount, objectIDAll, true, "", "", privilegeEntryTypeGeneral, nil}, 2160 PrivilegeTypeManageGrants: {PrivilegeTypeManageGrants, privilegeLevelStar, objectTypeAccount, objectIDAll, true, "", "", privilegeEntryTypeGeneral, nil}, 2161 PrivilegeTypeAccountAll: {PrivilegeTypeAccountAll, privilegeLevelStar, objectTypeAccount, objectIDAll, true, "", "", privilegeEntryTypeGeneral, nil}, 2162 PrivilegeTypeAccountOwnership: {PrivilegeTypeAccountOwnership, privilegeLevelStar, objectTypeAccount, objectIDAll, true, "", "", privilegeEntryTypeGeneral, nil}, 2163 PrivilegeTypeUserOwnership: {PrivilegeTypeUserOwnership, privilegeLevelStar, objectTypeAccount, objectIDAll, true, "", "", privilegeEntryTypeGeneral, nil}, 2164 PrivilegeTypeRoleOwnership: {PrivilegeTypeRoleOwnership, privilegeLevelStar, objectTypeAccount, objectIDAll, true, "", "", privilegeEntryTypeGeneral, nil}, 2165 PrivilegeTypeShowTables: {PrivilegeTypeShowTables, privilegeLevelStar, objectTypeDatabase, objectIDAll, true, "", "", privilegeEntryTypeGeneral, nil}, 2166 PrivilegeTypeCreateObject: {PrivilegeTypeCreateObject, privilegeLevelStar, objectTypeDatabase, objectIDAll, true, "", "", privilegeEntryTypeGeneral, nil}, 2167 PrivilegeTypeCreateTable: {PrivilegeTypeCreateTable, privilegeLevelStar, objectTypeDatabase, objectIDAll, true, "", "", privilegeEntryTypeGeneral, nil}, 2168 PrivilegeTypeCreateView: {PrivilegeTypeCreateView, privilegeLevelStar, objectTypeDatabase, objectIDAll, true, "", "", privilegeEntryTypeGeneral, nil}, 2169 PrivilegeTypeDropObject: {PrivilegeTypeDropObject, privilegeLevelStar, objectTypeDatabase, objectIDAll, true, "", "", privilegeEntryTypeGeneral, nil}, 2170 PrivilegeTypeDropTable: {PrivilegeTypeDropTable, privilegeLevelStar, objectTypeDatabase, objectIDAll, true, "", "", privilegeEntryTypeGeneral, nil}, 2171 PrivilegeTypeDropView: {PrivilegeTypeDropView, privilegeLevelStar, objectTypeDatabase, objectIDAll, true, "", "", privilegeEntryTypeGeneral, nil}, 2172 PrivilegeTypeAlterObject: {PrivilegeTypeAlterObject, privilegeLevelStar, objectTypeDatabase, objectIDAll, true, "", "", privilegeEntryTypeGeneral, nil}, 2173 PrivilegeTypeAlterTable: {PrivilegeTypeAlterTable, privilegeLevelStar, objectTypeDatabase, objectIDAll, true, "", "", privilegeEntryTypeGeneral, nil}, 2174 PrivilegeTypeAlterView: {PrivilegeTypeAlterView, privilegeLevelStar, objectTypeDatabase, objectIDAll, true, "", "", privilegeEntryTypeGeneral, nil}, 2175 PrivilegeTypeDatabaseAll: {PrivilegeTypeDatabaseAll, privilegeLevelStar, objectTypeDatabase, objectIDAll, true, "", "", privilegeEntryTypeGeneral, nil}, 2176 PrivilegeTypeDatabaseOwnership: {PrivilegeTypeDatabaseOwnership, privilegeLevelStar, objectTypeDatabase, objectIDAll, true, "", "", privilegeEntryTypeGeneral, nil}, 2177 PrivilegeTypeSelect: {PrivilegeTypeSelect, privilegeLevelStarStar, objectTypeTable, objectIDAll, true, "", "", privilegeEntryTypeGeneral, nil}, 2178 PrivilegeTypeInsert: {PrivilegeTypeInsert, privilegeLevelStarStar, objectTypeTable, objectIDAll, true, "", "", privilegeEntryTypeGeneral, nil}, 2179 PrivilegeTypeUpdate: {PrivilegeTypeUpdate, privilegeLevelStarStar, objectTypeTable, objectIDAll, true, "", "", privilegeEntryTypeGeneral, nil}, 2180 PrivilegeTypeTruncate: {PrivilegeTypeTruncate, privilegeLevelStarStar, objectTypeTable, objectIDAll, true, "", "", privilegeEntryTypeGeneral, nil}, 2181 PrivilegeTypeDelete: {PrivilegeTypeDelete, privilegeLevelStarStar, objectTypeTable, objectIDAll, true, "", "", privilegeEntryTypeGeneral, nil}, 2182 PrivilegeTypeReference: {PrivilegeTypeReference, privilegeLevelStarStar, objectTypeTable, objectIDAll, true, "", "", privilegeEntryTypeGeneral, nil}, 2183 PrivilegeTypeIndex: {PrivilegeTypeIndex, privilegeLevelStarStar, objectTypeTable, objectIDAll, true, "", "", privilegeEntryTypeGeneral, nil}, 2184 PrivilegeTypeTableAll: {PrivilegeTypeTableAll, privilegeLevelStarStar, objectTypeTable, objectIDAll, true, "", "", privilegeEntryTypeGeneral, nil}, 2185 PrivilegeTypeTableOwnership: {PrivilegeTypeTableOwnership, privilegeLevelStarStar, objectTypeTable, objectIDAll, true, "", "", privilegeEntryTypeGeneral, nil}, 2186 PrivilegeTypeExecute: {PrivilegeTypeExecute, privilegeLevelRoutine, objectTypeFunction, objectIDAll, true, "", "", privilegeEntryTypeGeneral, nil}, 2187 PrivilegeTypeValues: {PrivilegeTypeValues, privilegeLevelStarStar, objectTypeTable, objectIDAll, true, "", "", privilegeEntryTypeGeneral, nil}, 2188 } 2189 2190 //the initial entries of mo_role_privs for the role 'moadmin' 2191 entriesOfMoAdminForMoRolePrivsFor = []PrivilegeType{ 2192 PrivilegeTypeCreateAccount, 2193 PrivilegeTypeDropAccount, 2194 PrivilegeTypeAlterAccount, 2195 PrivilegeTypeUpgradeAccount, 2196 PrivilegeTypeCreateUser, 2197 PrivilegeTypeDropUser, 2198 PrivilegeTypeAlterUser, 2199 PrivilegeTypeCreateRole, 2200 PrivilegeTypeDropRole, 2201 PrivilegeTypeCreateDatabase, 2202 PrivilegeTypeDropDatabase, 2203 PrivilegeTypeShowDatabases, 2204 PrivilegeTypeConnect, 2205 PrivilegeTypeManageGrants, 2206 PrivilegeTypeAccountAll, 2207 PrivilegeTypeShowTables, 2208 PrivilegeTypeCreateTable, 2209 PrivilegeTypeDropTable, 2210 PrivilegeTypeAlterTable, 2211 PrivilegeTypeCreateView, 2212 PrivilegeTypeDropView, 2213 PrivilegeTypeAlterView, 2214 PrivilegeTypeDatabaseAll, 2215 PrivilegeTypeDatabaseOwnership, 2216 PrivilegeTypeSelect, 2217 PrivilegeTypeInsert, 2218 PrivilegeTypeUpdate, 2219 PrivilegeTypeTruncate, 2220 PrivilegeTypeDelete, 2221 PrivilegeTypeReference, 2222 PrivilegeTypeIndex, 2223 PrivilegeTypeTableAll, 2224 PrivilegeTypeTableOwnership, 2225 PrivilegeTypeValues, 2226 } 2227 2228 //the initial entries of mo_role_privs for the role 'accountadmin' 2229 entriesOfAccountAdminForMoRolePrivsFor = []PrivilegeType{ 2230 PrivilegeTypeCreateUser, 2231 PrivilegeTypeDropUser, 2232 PrivilegeTypeAlterUser, 2233 PrivilegeTypeCreateRole, 2234 PrivilegeTypeDropRole, 2235 PrivilegeTypeCreateDatabase, 2236 PrivilegeTypeDropDatabase, 2237 PrivilegeTypeShowDatabases, 2238 PrivilegeTypeConnect, 2239 PrivilegeTypeManageGrants, 2240 PrivilegeTypeAccountAll, 2241 PrivilegeTypeShowTables, 2242 PrivilegeTypeCreateTable, 2243 PrivilegeTypeDropTable, 2244 PrivilegeTypeAlterTable, 2245 PrivilegeTypeCreateView, 2246 PrivilegeTypeDropView, 2247 PrivilegeTypeAlterView, 2248 PrivilegeTypeDatabaseAll, 2249 PrivilegeTypeDatabaseOwnership, 2250 PrivilegeTypeSelect, 2251 PrivilegeTypeInsert, 2252 PrivilegeTypeUpdate, 2253 PrivilegeTypeTruncate, 2254 PrivilegeTypeDelete, 2255 PrivilegeTypeReference, 2256 PrivilegeTypeIndex, 2257 PrivilegeTypeTableAll, 2258 PrivilegeTypeTableOwnership, 2259 PrivilegeTypeValues, 2260 } 2261 2262 //the initial entries of mo_role_privs for the role 'public' 2263 entriesOfPublicForMoRolePrivsFor = []PrivilegeType{ 2264 PrivilegeTypeConnect, 2265 } 2266 ) 2267 2268 type verifiedRoleType int 2269 2270 const ( 2271 roleType verifiedRoleType = iota 2272 userType 2273 ) 2274 2275 // privilegeCache cache privileges on table 2276 type privilegeCache struct { 2277 //For objectType table 2278 //For objectType table *, *.* 2279 storeForTable [int(privilegeLevelEnd)]btree.Set[PrivilegeType] 2280 //For objectType table database.* 2281 storeForTable2 btree.Map[string, *btree.Set[PrivilegeType]] 2282 //For objectType table database.table , table 2283 storeForTable3 btree.Map[string, *btree.Map[string, *btree.Set[PrivilegeType]]] 2284 2285 //For objectType database *, *.* 2286 storeForDatabase [int(privilegeLevelEnd)]btree.Set[PrivilegeType] 2287 //For objectType database 2288 storeForDatabase2 btree.Map[string, *btree.Set[PrivilegeType]] 2289 //For objectType account * 2290 storeForAccount [int(privilegeLevelEnd)]btree.Set[PrivilegeType] 2291 total atomic.Uint64 2292 hit atomic.Uint64 2293 } 2294 2295 // has checks the cache has privilege on a table 2296 func (pc *privilegeCache) has(objTyp objectType, plt privilegeLevelType, dbName, tableName string, priv PrivilegeType) bool { 2297 pc.total.Add(1) 2298 privSet := pc.getPrivilegeSet(objTyp, plt, dbName, tableName) 2299 if privSet != nil && privSet.Contains(priv) { 2300 pc.hit.Add(1) 2301 return true 2302 } 2303 return false 2304 } 2305 2306 func (pc *privilegeCache) getPrivilegeSet(objTyp objectType, plt privilegeLevelType, dbName, tableName string) *btree.Set[PrivilegeType] { 2307 switch objTyp { 2308 case objectTypeTable: 2309 switch plt { 2310 case privilegeLevelStarStar, privilegeLevelStar: 2311 return &pc.storeForTable[plt] 2312 case privilegeLevelDatabaseStar: 2313 dbStore, ok1 := pc.storeForTable2.Get(dbName) 2314 if !ok1 { 2315 dbStore = &btree.Set[PrivilegeType]{} 2316 pc.storeForTable2.Set(dbName, dbStore) 2317 } 2318 return dbStore 2319 case privilegeLevelDatabaseTable, privilegeLevelTable: 2320 tableStore, ok1 := pc.storeForTable3.Get(dbName) 2321 if !ok1 { 2322 tableStore = &btree.Map[string, *btree.Set[PrivilegeType]]{} 2323 pc.storeForTable3.Set(dbName, tableStore) 2324 } 2325 privSet, ok2 := tableStore.Get(tableName) 2326 if !ok2 { 2327 privSet = &btree.Set[PrivilegeType]{} 2328 tableStore.Set(tableName, privSet) 2329 } 2330 return privSet 2331 default: 2332 return nil 2333 } 2334 case objectTypeDatabase: 2335 switch plt { 2336 case privilegeLevelStar, privilegeLevelStarStar: 2337 return &pc.storeForDatabase[plt] 2338 case privilegeLevelDatabase: 2339 dbStore, ok1 := pc.storeForDatabase2.Get(dbName) 2340 if !ok1 { 2341 dbStore = &btree.Set[PrivilegeType]{} 2342 pc.storeForDatabase2.Set(dbName, dbStore) 2343 } 2344 return dbStore 2345 default: 2346 return nil 2347 } 2348 case objectTypeAccount: 2349 return &pc.storeForAccount[plt] 2350 default: 2351 return nil 2352 } 2353 2354 } 2355 2356 // set replaces the privileges by new ones 2357 func (pc *privilegeCache) set(objTyp objectType, plt privilegeLevelType, dbName, tableName string, priv ...PrivilegeType) { 2358 privSet := pc.getPrivilegeSet(objTyp, plt, dbName, tableName) 2359 if privSet != nil { 2360 privSet.Clear() 2361 for _, p := range priv { 2362 privSet.Insert(p) 2363 } 2364 } 2365 } 2366 2367 // add puts the privileges without replacing existed ones 2368 func (pc *privilegeCache) add(objTyp objectType, plt privilegeLevelType, dbName, tableName string, priv ...PrivilegeType) { 2369 privSet := pc.getPrivilegeSet(objTyp, plt, dbName, tableName) 2370 if privSet != nil { 2371 for _, p := range priv { 2372 privSet.Insert(p) 2373 } 2374 } 2375 } 2376 2377 // invalidate makes the cache empty 2378 func (pc *privilegeCache) invalidate() { 2379 if pc == nil { 2380 return 2381 } 2382 //total := pc.total.Swap(0) 2383 //hit := pc.hit.Swap(0) 2384 for i := privilegeLevelStar; i < privilegeLevelEnd; i++ { 2385 pc.storeForTable[i].Clear() 2386 pc.storeForDatabase[i].Clear() 2387 pc.storeForAccount[i].Clear() 2388 } 2389 pc.storeForTable2.Clear() 2390 pc.storeForTable3.Clear() 2391 pc.storeForDatabase2.Clear() 2392 //ratio := float64(0) 2393 //if total == 0 { 2394 // ratio = 0 2395 //} else { 2396 // ratio = float64(hit) / float64(total) 2397 //} 2398 //logutil.Debugf("-->hit %d total %d ratio %f", hit, total, ratio) 2399 } 2400 2401 // verifiedRole holds the role info that has been checked 2402 type verifiedRole struct { 2403 typ verifiedRoleType 2404 name string 2405 id int64 2406 userIsAdmin bool 2407 } 2408 2409 // verifyRoleFunc gets result set from mo_role_grant or mo_user_grant 2410 func verifyRoleFunc(ctx context.Context, bh BackgroundExec, sql, name string, typ verifiedRoleType) (*verifiedRole, error) { 2411 var err error 2412 var erArray []ExecResult 2413 var roleId int64 2414 bh.ClearExecResultSet() 2415 err = bh.Exec(ctx, sql) 2416 if err != nil { 2417 return nil, err 2418 } 2419 2420 erArray, err = getResultSet(ctx, bh) 2421 if err != nil { 2422 return nil, err 2423 } 2424 2425 if execResultArrayHasData(erArray) { 2426 roleId, err = erArray[0].GetInt64(ctx, 0, 0) 2427 if err != nil { 2428 return nil, err 2429 } 2430 return &verifiedRole{typ, name, roleId, false}, nil 2431 } 2432 return nil, nil 2433 } 2434 2435 // userIsAdministrator checks the user is the administrator 2436 func userIsAdministrator(ctx context.Context, bh BackgroundExec, userId int64, account *TenantInfo) (bool, error) { 2437 var err error 2438 var erArray []ExecResult 2439 var sql string 2440 if account.IsSysTenant() { 2441 sql, err = getSqlForRoleOfUser(ctx, userId, moAdminRoleName) 2442 } else { 2443 sql, err = getSqlForRoleOfUser(ctx, userId, accountAdminRoleName) 2444 } 2445 if err != nil { 2446 return false, err 2447 } 2448 2449 bh.ClearExecResultSet() 2450 err = bh.Exec(ctx, sql) 2451 if err != nil { 2452 return false, err 2453 } 2454 2455 erArray, err = getResultSet(ctx, bh) 2456 if err != nil { 2457 return false, err 2458 } 2459 2460 if execResultArrayHasData(erArray) { 2461 return true, nil 2462 } 2463 return false, nil 2464 } 2465 2466 type visitTag int 2467 2468 const ( 2469 vtUnVisited visitTag = 0 2470 vtVisited visitTag = 1 2471 vtVisiting visitTag = -1 2472 ) 2473 2474 // edge <from,to> in the graph 2475 type edge struct { 2476 from int64 2477 to int64 2478 invalid bool 2479 } 2480 2481 func (e *edge) isInvalid() bool { 2482 return e.invalid 2483 } 2484 2485 func (e *edge) setInvalid() { 2486 e.invalid = true 2487 } 2488 2489 // graph the acyclic graph 2490 type graph struct { 2491 edges []*edge 2492 vertexes map[int64]int 2493 adjacent map[int64][]int 2494 } 2495 2496 func NewGraph() *graph { 2497 return &graph{ 2498 vertexes: make(map[int64]int), 2499 adjacent: make(map[int64][]int), 2500 } 2501 } 2502 2503 // addEdge adds the directed edge <from,to> into the graph 2504 func (g *graph) addEdge(from, to int64) int { 2505 edgeId := len(g.edges) 2506 g.edges = append(g.edges, &edge{from, to, false}) 2507 g.adjacent[from] = append(g.adjacent[from], edgeId) 2508 g.vertexes[from] = 0 2509 g.vertexes[to] = 0 2510 return edgeId 2511 } 2512 2513 // removeEdge removes the directed edge (edgeId) from the graph 2514 func (g *graph) removeEdge(edgeId int) { 2515 e := g.getEdge(edgeId) 2516 e.setInvalid() 2517 } 2518 2519 func (g *graph) getEdge(eid int) *edge { 2520 return g.edges[eid] 2521 } 2522 2523 // dfs use the toposort to check the loop 2524 func (g *graph) toposort(u int64, visited map[int64]visitTag) bool { 2525 visited[u] = vtVisiting 2526 //loop on adjacent vertex 2527 for _, eid := range g.adjacent[u] { 2528 e := g.getEdge(eid) 2529 if e.isInvalid() { 2530 continue 2531 } 2532 if visited[e.to] == vtVisiting { //find the loop in the vertex 2533 return false 2534 } else if visited[e.to] == vtUnVisited && !g.toposort(e.to, visited) { //find the loop in the adjacent vertexes 2535 return false 2536 } 2537 } 2538 visited[u] = vtVisited 2539 return true 2540 } 2541 2542 // hasLoop checks the loop 2543 func (g *graph) hasLoop(start int64) bool { 2544 visited := make(map[int64]visitTag) 2545 for v := range g.vertexes { 2546 visited[v] = vtUnVisited 2547 } 2548 2549 return !g.toposort(start, visited) 2550 } 2551 2552 func inputNameIsInvalid(ctx context.Context, inputs ...string) error { 2553 for _, input := range inputs { 2554 for _, t := range input { 2555 if t == ' ' || t == '\t' || t == '`' || t == '"' || t == '\'' { 2556 return moerr.NewInternalError(ctx, `invalid input`) 2557 } 2558 } 2559 } 2560 return nil 2561 } 2562 2563 // nameIsInvalid checks the name of user/role is valid or not 2564 func nameIsInvalid(name string) bool { 2565 s := strings.TrimSpace(name) 2566 if len(s) == 0 { 2567 return true 2568 } 2569 return strings.Contains(s, ":") || strings.Contains(s, "#") 2570 } 2571 func accountNameIsInvalid(name string) bool { 2572 s := strings.TrimSpace(name) 2573 if len(s) == 0 { 2574 return true 2575 } 2576 for _, c := range s { 2577 switch { 2578 case c >= '0' && c <= '9': 2579 continue 2580 case c >= 'a' && c <= 'z': 2581 continue 2582 case c >= 'A' && c <= 'Z': 2583 continue 2584 case c == '_' || c == '-': 2585 continue 2586 default: 2587 return true 2588 } 2589 } 2590 return false 2591 } 2592 2593 // normalizeName normalizes and checks the name 2594 func normalizeName(ctx context.Context, name string) (string, error) { 2595 s := strings.TrimSpace(name) 2596 if nameIsInvalid(s) { 2597 return "", moerr.NewInternalError(ctx, `the name "%s" is invalid`, name) 2598 } 2599 return s, nil 2600 } 2601 2602 func normalizeNameOfAccount(ctx context.Context, ca *createAccount) error { 2603 s := strings.TrimSpace(ca.Name) 2604 if len(s) == 0 { 2605 return moerr.NewInternalError(ctx, `the name "%s" is invalid`, ca.Name) 2606 } 2607 if accountNameIsInvalid(s) { 2608 return moerr.NewInternalError(ctx, `the name "%s" is invalid`, ca.Name) 2609 } 2610 ca.Name = s 2611 return nil 2612 } 2613 2614 // normalizeNameOfRole normalizes the name 2615 func normalizeNameOfRole(ctx context.Context, role *tree.Role) error { 2616 var err error 2617 role.UserName, err = normalizeName(ctx, role.UserName) 2618 return err 2619 } 2620 2621 // normalizeNamesOfRoles normalizes the names and checks them 2622 func normalizeNamesOfRoles(ctx context.Context, roles []*tree.Role) error { 2623 var err error 2624 for i := 0; i < len(roles); i++ { 2625 err = normalizeNameOfRole(ctx, roles[i]) 2626 if err != nil { 2627 return err 2628 } 2629 } 2630 return nil 2631 } 2632 2633 // normalizeNameOfUser normalizes the name 2634 func normalizeNameOfUser(ctx context.Context, user *tree.User) error { 2635 var err error 2636 user.Username, err = normalizeName(ctx, user.Username) 2637 return err 2638 } 2639 2640 // normalizeNamesOfUsers normalizes the names and checks them 2641 func normalizeNamesOfUsers(ctx context.Context, users []*tree.User) error { 2642 var err error 2643 for i := 0; i < len(users); i++ { 2644 err = normalizeNameOfUser(ctx, users[i]) 2645 if err != nil { 2646 return err 2647 } 2648 } 2649 return nil 2650 } 2651 2652 // finishTxn cleanup the transaction started by the BEGIN statement. 2653 // If the transaction is successful, commit it. Otherwise, rollback it. 2654 // err == nil means there is no failure during the transaction execution. 2655 // so the transaction is successful. Else, it is failed. 2656 // !!!Note: if the transaction is not started by the BEGIN statement, it 2657 // has been COMMIT or ROLLBACK already. It is wrong to COMMIT or ROLLBACK again, obviously. 2658 // It is wrong to call this function to commit or rollback the transaction. 2659 func finishTxn(ctx context.Context, bh BackgroundExec, err error) error { 2660 rollbackTxn := func() error { 2661 //ROLLBACK the transaction 2662 rbErr := bh.Exec(ctx, "rollback;") 2663 if rbErr != nil { 2664 //if ROLLBACK failed, return the COMMIT error with the input err also 2665 return errors.Join(rbErr, err) 2666 } 2667 return err 2668 } 2669 if err == nil { 2670 //normal COMMIT the transaction 2671 err = bh.Exec(ctx, "commit;") 2672 if err != nil { 2673 //if COMMIT failed, ROLLBACK the transaction 2674 return rollbackTxn() 2675 } 2676 return err 2677 } 2678 return rollbackTxn() 2679 } 2680 2681 type alterUser struct { 2682 IfExists bool 2683 Users []*user 2684 Role *tree.Role 2685 MiscOpt tree.UserMiscOption 2686 // comment or attribute 2687 CommentOrAttribute tree.AccountCommentOrAttribute 2688 } 2689 2690 type user struct { 2691 Username string 2692 Hostname string 2693 AuthExist bool 2694 IdentTyp tree.AccountIdentifiedOption 2695 IdentStr string 2696 } 2697 2698 func doAlterUser(ctx context.Context, ses *Session, au *alterUser) (err error) { 2699 var sql string 2700 var vr *verifiedRole 2701 var erArray []ExecResult 2702 var encryption string 2703 account := ses.GetTenantInfo() 2704 currentUser := account.GetUser() 2705 2706 //1.authenticate the actions 2707 if au.Role != nil { 2708 return moerr.NewInternalError(ctx, "not support alter role") 2709 } 2710 if au.MiscOpt != nil { 2711 return moerr.NewInternalError(ctx, "not support password or lock operation") 2712 } 2713 if au.CommentOrAttribute.Exist { 2714 return moerr.NewInternalError(ctx, "not support alter comment or attribute") 2715 } 2716 if len(au.Users) != 1 { 2717 return moerr.NewInternalError(ctx, "can only alter one user at a time") 2718 } 2719 user := au.Users[0] 2720 2721 bh := ses.GetBackgroundExec(ctx) 2722 defer bh.Close() 2723 2724 userName, err := normalizeName(ctx, user.Username) 2725 if err != nil { 2726 return err 2727 } 2728 hostName := user.Hostname 2729 password := user.IdentStr 2730 if len(password) == 0 { 2731 return moerr.NewInternalError(ctx, "password is empty string") 2732 } 2733 //put it into the single transaction 2734 err = bh.Exec(ctx, "begin") 2735 defer func() { 2736 err = finishTxn(ctx, bh, err) 2737 }() 2738 if err != nil { 2739 return err 2740 } 2741 2742 if !user.AuthExist { 2743 return moerr.NewInternalError(ctx, "Operation ALTER USER failed for '%s'@'%s', alter Auth is nil", userName, hostName) 2744 } 2745 2746 if user.IdentTyp != tree.AccountIdentifiedByPassword { 2747 return moerr.NewInternalError(ctx, "Operation ALTER USER failed for '%s'@'%s', only support alter Auth by identified by", userName, hostName) 2748 } 2749 2750 //check the user exists or not 2751 sql, err = getSqlForPasswordOfUser(ctx, userName) 2752 if err != nil { 2753 return err 2754 } 2755 vr, err = verifyRoleFunc(ctx, bh, sql, userName, roleType) 2756 if err != nil { 2757 return err 2758 } 2759 2760 if vr == nil { 2761 //If Exists : 2762 // false : return an error 2763 // true : return and do nothing 2764 if !au.IfExists { 2765 return moerr.NewInternalError(ctx, "Operation ALTER USER failed for '%s'@'%s', user does't exist", userName, hostName) 2766 } else { 2767 return err 2768 } 2769 } 2770 2771 //if the user is admin user with the role moadmin or accountadmin, 2772 //the user can be altered 2773 //otherwise only general user can alter itself 2774 if account.IsSysTenant() { 2775 sql, err = getSqlForCheckUserHasRole(ctx, currentUser, moAdminRoleID) 2776 } else { 2777 sql, err = getSqlForCheckUserHasRole(ctx, currentUser, accountAdminRoleID) 2778 } 2779 if err != nil { 2780 return err 2781 } 2782 2783 bh.ClearExecResultSet() 2784 err = bh.Exec(ctx, sql) 2785 if err != nil { 2786 return err 2787 } 2788 2789 erArray, err = getResultSet(ctx, bh) 2790 if err != nil { 2791 return err 2792 } 2793 2794 //encryption the password 2795 encryption = HashPassWord(password) 2796 2797 if execResultArrayHasData(erArray) || getGlobalPu().SV.SkipCheckPrivilege { 2798 sql, err = getSqlForUpdatePasswordOfUser(ctx, encryption, userName) 2799 if err != nil { 2800 return err 2801 } 2802 err = bh.Exec(ctx, sql) 2803 if err != nil { 2804 return err 2805 } 2806 } else { 2807 if currentUser != userName { 2808 return moerr.NewInternalError(ctx, "Operation ALTER USER failed for '%s'@'%s', don't have the privilege to alter", userName, hostName) 2809 } 2810 sql, err = getSqlForUpdatePasswordOfUser(ctx, encryption, userName) 2811 if err != nil { 2812 return err 2813 } 2814 err = bh.Exec(ctx, sql) 2815 if err != nil { 2816 return err 2817 } 2818 } 2819 return err 2820 } 2821 2822 type alterAccount struct { 2823 IfExists bool 2824 Name string 2825 2826 AuthExist bool 2827 AdminName string 2828 IdentTyp tree.AccountIdentifiedOption 2829 IdentStr string 2830 2831 // status_option or not 2832 StatusOption tree.AccountStatus 2833 // comment or not 2834 Comment tree.AccountComment 2835 } 2836 2837 func doAlterAccount(ctx context.Context, ses *Session, aa *alterAccount) (err error) { 2838 var sql string 2839 var erArray []ExecResult 2840 var targetAccountId uint64 2841 var version uint64 2842 var accountExist bool 2843 var accountStatus string 2844 account := ses.GetTenantInfo() 2845 if !(account.IsSysTenant() && account.IsMoAdminRole()) { 2846 return moerr.NewInternalError(ctx, "tenant %s user %s role %s do not have the privilege to alter the account", 2847 account.GetTenant(), account.GetUser(), account.GetDefaultRole()) 2848 } 2849 2850 optionBits := uint8(0) 2851 if aa.AuthExist { 2852 optionBits |= 1 2853 } 2854 if aa.StatusOption.Exist { 2855 optionBits |= 1 << 1 2856 } 2857 if aa.Comment.Exist { 2858 optionBits |= 1 << 2 2859 } 2860 optionCount := bits.OnesCount8(optionBits) 2861 if optionCount == 0 { 2862 return moerr.NewInternalError(ctx, "at least one option at a time") 2863 } 2864 if optionCount > 1 { 2865 return moerr.NewInternalError(ctx, "at most one option at a time") 2866 } 2867 2868 //normalize the name 2869 aa.Name, err = normalizeName(ctx, aa.Name) 2870 if err != nil { 2871 return err 2872 } 2873 2874 if aa.AuthExist { 2875 aa.AdminName, err = normalizeName(ctx, aa.AdminName) 2876 if err != nil { 2877 return err 2878 } 2879 if aa.IdentTyp != tree.AccountIdentifiedByPassword { 2880 return moerr.NewInternalError(ctx, "only support identified by password") 2881 } 2882 2883 if len(aa.IdentStr) == 0 { 2884 err = moerr.NewInternalError(ctx, "password is empty string") 2885 return err 2886 } 2887 } 2888 2889 if aa.StatusOption.Exist { 2890 //SYS account can not be suspended 2891 if isSysTenant(aa.Name) { 2892 return moerr.NewInternalError(ctx, "account sys can not be suspended") 2893 } 2894 } 2895 2896 alterAccountFunc := func() (rtnErr error) { 2897 bh := ses.GetBackgroundExec(ctx) 2898 defer bh.Close() 2899 2900 rtnErr = bh.Exec(ctx, "begin") 2901 defer func() { 2902 rtnErr = finishTxn(ctx, bh, rtnErr) 2903 }() 2904 if rtnErr != nil { 2905 return rtnErr 2906 } 2907 2908 //step 1: check account exists or not 2909 //get accountID 2910 sql, rtnErr = getSqlForCheckTenant(ctx, aa.Name) 2911 if rtnErr != nil { 2912 return rtnErr 2913 } 2914 bh.ClearExecResultSet() 2915 rtnErr = bh.Exec(ctx, sql) 2916 if rtnErr != nil { 2917 return rtnErr 2918 } 2919 2920 erArray, rtnErr = getResultSet(ctx, bh) 2921 if rtnErr != nil { 2922 return rtnErr 2923 } 2924 2925 if execResultArrayHasData(erArray) { 2926 for i := uint64(0); i < erArray[0].GetRowCount(); i++ { 2927 targetAccountId, rtnErr = erArray[0].GetUint64(ctx, i, 0) 2928 if rtnErr != nil { 2929 return rtnErr 2930 } 2931 2932 accountStatus, rtnErr = erArray[0].GetString(ctx, 0, 2) 2933 if rtnErr != nil { 2934 return rtnErr 2935 } 2936 2937 version, rtnErr = erArray[0].GetUint64(ctx, i, 3) 2938 if rtnErr != nil { 2939 return rtnErr 2940 } 2941 } 2942 accountExist = true 2943 } else { 2944 //IfExists : 2945 // false : return an error 2946 // true : skip and do nothing 2947 if !aa.IfExists { 2948 return moerr.NewInternalError(ctx, "there is no account %s", aa.Name) 2949 } 2950 } 2951 2952 if accountExist { 2953 //Option 1: alter the password of admin for the account 2954 if aa.AuthExist { 2955 //!!!NOTE!!!:switch into the target account's context, then update the table mo_user. 2956 accountCtx := defines.AttachAccountId(ctx, uint32(targetAccountId)) 2957 2958 //1, check the admin exists or not 2959 sql, rtnErr = getSqlForPasswordOfUser(ctx, aa.AdminName) 2960 if rtnErr != nil { 2961 return rtnErr 2962 } 2963 bh.ClearExecResultSet() 2964 rtnErr = bh.Exec(accountCtx, sql) 2965 if rtnErr != nil { 2966 return rtnErr 2967 } 2968 2969 erArray, rtnErr = getResultSet(accountCtx, bh) 2970 if rtnErr != nil { 2971 return rtnErr 2972 } 2973 2974 if !execResultArrayHasData(erArray) { 2975 rtnErr = moerr.NewInternalError(accountCtx, "there is no user %s", aa.AdminName) 2976 return 2977 } 2978 2979 //2, update the password 2980 //encryption the password 2981 encryption := HashPassWord(aa.IdentStr) 2982 sql, rtnErr = getSqlForUpdatePasswordOfUser(ctx, encryption, aa.AdminName) 2983 if rtnErr != nil { 2984 return rtnErr 2985 } 2986 bh.ClearExecResultSet() 2987 rtnErr = bh.Exec(accountCtx, sql) 2988 if rtnErr != nil { 2989 return rtnErr 2990 } 2991 } 2992 2993 //Option 2: alter the comment of the account 2994 if aa.Comment.Exist { 2995 sql, rtnErr = getSqlForUpdateCommentsOfAccount(ctx, aa.Comment.Comment, aa.Name) 2996 if rtnErr != nil { 2997 return rtnErr 2998 } 2999 bh.ClearExecResultSet() 3000 rtnErr = bh.Exec(ctx, sql) 3001 if rtnErr != nil { 3002 return rtnErr 3003 } 3004 } 3005 3006 //Option 3: suspend or resume the account 3007 if aa.StatusOption.Exist { 3008 if aa.StatusOption.Option == tree.AccountStatusSuspend { 3009 sql, rtnErr = getSqlForUpdateStatusOfAccount(ctx, aa.StatusOption.Option.String(), types.CurrentTimestamp().String2(time.UTC, 0), aa.Name) 3010 if rtnErr != nil { 3011 return rtnErr 3012 } 3013 bh.ClearExecResultSet() 3014 rtnErr = bh.Exec(ctx, sql) 3015 if rtnErr != nil { 3016 return rtnErr 3017 } 3018 } else if aa.StatusOption.Option == tree.AccountStatusOpen { 3019 sql, rtnErr = getSqlForUpdateStatusAndVersionOfAccount(ctx, aa.StatusOption.Option.String(), aa.Name, (version+1)%math.MaxUint64) 3020 if rtnErr != nil { 3021 return rtnErr 3022 } 3023 bh.ClearExecResultSet() 3024 rtnErr = bh.Exec(ctx, sql) 3025 if rtnErr != nil { 3026 return rtnErr 3027 } 3028 } else if aa.StatusOption.Option == tree.AccountStatusRestricted { 3029 sql, rtnErr = getSqlForUpdateStatusOfAccount(ctx, aa.StatusOption.Option.String(), types.CurrentTimestamp().String2(time.UTC, 0), aa.Name) 3030 if rtnErr != nil { 3031 return rtnErr 3032 } 3033 bh.ClearExecResultSet() 3034 rtnErr = bh.Exec(ctx, sql) 3035 if rtnErr != nil { 3036 return rtnErr 3037 } 3038 } 3039 } 3040 } 3041 return rtnErr 3042 } 3043 3044 err = alterAccountFunc() 3045 if err != nil { 3046 return err 3047 } 3048 3049 //if alter account suspend, add the account to kill queue 3050 if accountExist { 3051 if aa.StatusOption.Exist && aa.StatusOption.Option == tree.AccountStatusSuspend { 3052 ses.getRoutineManager().accountRoutine.EnKillQueue(int64(targetAccountId), version) 3053 3054 if err := postDropSuspendAccount(ctx, ses, aa.Name, int64(targetAccountId), version); err != nil { 3055 logutil.Errorf("post alter account suspend error: %s", err.Error()) 3056 } 3057 } 3058 3059 if aa.StatusOption.Exist && aa.StatusOption.Option == tree.AccountStatusRestricted { 3060 accountId2RoutineMap := ses.getRoutineManager().accountRoutine.deepCopyRoutineMap() 3061 if rtMap, ok := accountId2RoutineMap[int64(targetAccountId)]; ok { 3062 for rt := range rtMap { 3063 rt.setResricted(true) 3064 } 3065 } 3066 err = postAlterSessionStatus(ctx, ses, aa.Name, int64(targetAccountId), tree.AccountStatusRestricted.String()) 3067 if err != nil { 3068 logutil.Errorf("post alter account restricted error: %s", err.Error()) 3069 } 3070 } 3071 3072 if aa.StatusOption.Exist && aa.StatusOption.Option == tree.AccountStatusOpen && accountStatus == tree.AccountStatusRestricted.String() { 3073 accountId2RoutineMap := ses.getRoutineManager().accountRoutine.deepCopyRoutineMap() 3074 if rtMap, ok := accountId2RoutineMap[int64(targetAccountId)]; ok { 3075 for rt := range rtMap { 3076 rt.setResricted(false) 3077 } 3078 } 3079 err = postAlterSessionStatus(ctx, ses, aa.Name, int64(targetAccountId), tree.AccountStatusOpen.String()) 3080 if err != nil { 3081 logutil.Errorf("post alter account not restricted error: %s", err.Error()) 3082 } 3083 } 3084 } 3085 3086 return err 3087 } 3088 3089 // doSetSecondaryRoleAll set the session role of the user with smallness role_id 3090 func doSetSecondaryRoleAll(ctx context.Context, ses *Session) (err error) { 3091 var sql string 3092 var userId uint32 3093 var erArray []ExecResult 3094 var roleId int64 3095 var roleName string 3096 3097 account := ses.GetTenantInfo() 3098 // get current user_id 3099 userId = account.GetUserID() 3100 3101 // init role_id and role_name 3102 roleId = publicRoleID 3103 roleName = publicRoleName 3104 3105 // step1:get all roles expect public 3106 bh := ses.GetBackgroundExec(ctx) 3107 defer bh.Close() 3108 3109 err = bh.Exec(ctx, "begin;") 3110 defer func() { 3111 err = finishTxn(ctx, bh, err) 3112 }() 3113 if err != nil { 3114 return err 3115 } 3116 3117 sql = getSqlForgetUserRolesExpectPublicRole(publicRoleID, userId) 3118 bh.ClearExecResultSet() 3119 err = bh.Exec(ctx, sql) 3120 if err != nil { 3121 return err 3122 } 3123 3124 erArray, err = getResultSet(ctx, bh) 3125 if err != nil { 3126 return err 3127 } 3128 if execResultArrayHasData(erArray) { 3129 roleId, err = erArray[0].GetInt64(ctx, 0, 0) 3130 if err != nil { 3131 return err 3132 } 3133 3134 roleName, err = erArray[0].GetString(ctx, 0, 1) 3135 if err != nil { 3136 return err 3137 } 3138 } 3139 3140 // step2 : switch the default role and role id; 3141 account.SetDefaultRoleID(uint32(roleId)) 3142 account.SetDefaultRole(roleName) 3143 3144 return err 3145 } 3146 3147 // doSwitchRole accomplishes the Use Role and Use Secondary Role statement 3148 func doSwitchRole(ctx context.Context, ses *Session, sr *tree.SetRole) (err error) { 3149 var sql string 3150 var erArray []ExecResult 3151 var roleId int64 3152 3153 account := ses.GetTenantInfo() 3154 3155 if sr.SecondaryRole { 3156 //use secondary role all or none 3157 switch sr.SecondaryRoleType { 3158 case tree.SecondaryRoleTypeAll: 3159 doSetSecondaryRoleAll(ctx, ses) 3160 account.SetUseSecondaryRole(true) 3161 case tree.SecondaryRoleTypeNone: 3162 account.SetUseSecondaryRole(false) 3163 } 3164 } else if sr.Role != nil { 3165 err = normalizeNameOfRole(ctx, sr.Role) 3166 if err != nil { 3167 return err 3168 } 3169 3170 //step1 : check the role exists or not; 3171 3172 switchRoleFunc := func() (rtnErr error) { 3173 bh := ses.GetBackgroundExec(ctx) 3174 defer bh.Close() 3175 3176 rtnErr = bh.Exec(ctx, "begin;") 3177 defer func() { 3178 rtnErr = finishTxn(ctx, bh, rtnErr) 3179 }() 3180 if rtnErr != nil { 3181 return rtnErr 3182 } 3183 3184 sql, rtnErr = getSqlForRoleIdOfRole(ctx, sr.Role.UserName) 3185 if rtnErr != nil { 3186 return rtnErr 3187 } 3188 bh.ClearExecResultSet() 3189 rtnErr = bh.Exec(ctx, sql) 3190 if rtnErr != nil { 3191 return rtnErr 3192 } 3193 3194 erArray, rtnErr = getResultSet(ctx, bh) 3195 if rtnErr != nil { 3196 return rtnErr 3197 } 3198 if execResultArrayHasData(erArray) { 3199 roleId, rtnErr = erArray[0].GetInt64(ctx, 0, 0) 3200 if rtnErr != nil { 3201 return rtnErr 3202 } 3203 } else { 3204 return moerr.NewInternalError(ctx, "there is no role %s", sr.Role.UserName) 3205 } 3206 3207 //step2 : check the role has been granted to the user or not 3208 sql = getSqlForCheckUserGrant(roleId, int64(account.GetUserID())) 3209 bh.ClearExecResultSet() 3210 rtnErr = bh.Exec(ctx, sql) 3211 if rtnErr != nil { 3212 return rtnErr 3213 } 3214 3215 erArray, rtnErr = getResultSet(ctx, bh) 3216 if rtnErr != nil { 3217 return rtnErr 3218 } 3219 3220 if !execResultArrayHasData(erArray) { 3221 return moerr.NewInternalError(ctx, "the role %s has not be granted to the user %s", sr.Role.UserName, account.GetUser()) 3222 } 3223 return rtnErr 3224 } 3225 3226 err = switchRoleFunc() 3227 if err != nil { 3228 return err 3229 } 3230 3231 //step3 : switch the default role and role id; 3232 account.SetDefaultRoleID(uint32(roleId)) 3233 account.SetDefaultRole(sr.Role.UserName) 3234 //then, reset secondary role to none 3235 account.SetUseSecondaryRole(false) 3236 3237 return err 3238 } 3239 3240 return err 3241 } 3242 3243 func getSubscriptionMeta(ctx context.Context, dbName string, ses FeSession, txn TxnOperator) (*plan.SubscriptionMeta, error) { 3244 dbMeta, err := getGlobalPu().StorageEngine.Database(ctx, dbName, txn) 3245 if err != nil { 3246 logutil.Errorf("Get Subscription database %s meta error: %s", dbName, err.Error()) 3247 return nil, moerr.NewNoDB(ctx) 3248 } 3249 3250 if dbMeta.IsSubscription(ctx) { 3251 if sub, err := checkSubscriptionValid(ctx, ses, dbMeta.GetCreateSql(ctx)); err != nil { 3252 return nil, err 3253 } else { 3254 return sub, nil 3255 } 3256 } 3257 return nil, nil 3258 } 3259 3260 func checkSubscriptionValidCommon(ctx context.Context, ses FeSession, subName, accName, pubName string) (subs *plan.SubscriptionMeta, err error) { 3261 bh := ses.GetBackgroundExec(ctx) 3262 defer bh.Close() 3263 var ( 3264 sql, accStatus, accountList, databaseName string 3265 erArray []ExecResult 3266 tenantInfo *TenantInfo 3267 accId int64 3268 newCtx context.Context 3269 tenantName string 3270 ) 3271 3272 tenantInfo = ses.GetTenantInfo() 3273 if tenantInfo != nil && accName == tenantInfo.GetTenant() { 3274 return nil, moerr.NewInternalError(ctx, "can not subscribe to self") 3275 } 3276 3277 newCtx = defines.AttachAccountId(ctx, catalog.System_Account) 3278 3279 //get pubAccountId from publication info 3280 sql, err = getSqlForAccountIdAndStatus(newCtx, accName, true) 3281 if err != nil { 3282 return nil, err 3283 } 3284 err = bh.Exec(ctx, "begin;") 3285 defer func() { 3286 err = finishTxn(ctx, bh, err) 3287 }() 3288 if err != nil { 3289 return nil, err 3290 } 3291 bh.ClearExecResultSet() 3292 err = bh.Exec(newCtx, sql) 3293 if err != nil { 3294 return nil, err 3295 } 3296 3297 erArray, err = getResultSet(newCtx, bh) 3298 if err != nil { 3299 return nil, err 3300 } 3301 3302 if !execResultArrayHasData(erArray) { 3303 return nil, moerr.NewInternalError(newCtx, "there is no publication account %s", accName) 3304 } 3305 accId, err = erArray[0].GetInt64(newCtx, 0, 0) 3306 if err != nil { 3307 return nil, err 3308 } 3309 3310 accStatus, err = erArray[0].GetString(newCtx, 0, 1) 3311 if err != nil { 3312 return nil, err 3313 } 3314 3315 if accStatus == tree.AccountStatusSuspend.String() { 3316 return nil, moerr.NewInternalError(newCtx, "the account %s is suspended", accName) 3317 } 3318 3319 //check the publication is already exist or not 3320 3321 newCtx = defines.AttachAccountId(ctx, uint32(accId)) 3322 sql, err = getSqlForPubInfoForSub(newCtx, pubName, true) 3323 if err != nil { 3324 return nil, err 3325 } 3326 bh.ClearExecResultSet() 3327 err = bh.Exec(newCtx, sql) 3328 if err != nil { 3329 return nil, err 3330 } 3331 if erArray, err = getResultSet(newCtx, bh); err != nil { 3332 return nil, err 3333 } 3334 if !execResultArrayHasData(erArray) { 3335 return nil, moerr.NewInternalError(newCtx, "there is no publication %s", pubName) 3336 } 3337 3338 databaseName, err = erArray[0].GetString(newCtx, 0, 0) 3339 3340 if err != nil { 3341 return nil, err 3342 } 3343 3344 accountList, err = erArray[0].GetString(newCtx, 0, 1) 3345 if err != nil { 3346 return nil, err 3347 } 3348 3349 if tenantInfo == nil { 3350 var tenantId uint32 3351 tenantId, err = defines.GetAccountId(ctx) 3352 if err != nil { 3353 return nil, err 3354 } 3355 3356 sql = getSqlForGetAccountName(tenantId) 3357 bh.ClearExecResultSet() 3358 newCtx = defines.AttachAccountId(ctx, catalog.System_Account) 3359 err = bh.Exec(newCtx, sql) 3360 if err != nil { 3361 return nil, err 3362 } 3363 if erArray, err = getResultSet(newCtx, bh); err != nil { 3364 return nil, err 3365 } 3366 if !execResultArrayHasData(erArray) { 3367 return nil, moerr.NewInternalError(newCtx, "there is no account, account id %d ", tenantId) 3368 } 3369 3370 tenantName, err = erArray[0].GetString(newCtx, 0, 0) 3371 if err != nil { 3372 return nil, err 3373 } 3374 if !canSub(tenantName, accountList) { 3375 return nil, moerr.NewInternalError(newCtx, "the account %s is not allowed to subscribe the publication %s", tenantName, pubName) 3376 } 3377 } else if !canSub(tenantInfo.GetTenant(), accountList) { 3378 logError(ses, ses.GetDebugString(), 3379 "checkSubscriptionValidCommon", 3380 zap.String("subName", subName), 3381 zap.String("accName", accName), 3382 zap.String("pubName", pubName), 3383 zap.String("databaseName", databaseName), 3384 zap.String("accountList", accountList), 3385 zap.String("tenant", tenantInfo.GetTenant())) 3386 return nil, moerr.NewInternalError(newCtx, "the account %s is not allowed to subscribe the publication %s", tenantInfo.GetTenant(), pubName) 3387 } 3388 3389 subs = &plan.SubscriptionMeta{ 3390 Name: pubName, 3391 AccountId: int32(accId), 3392 DbName: databaseName, 3393 AccountName: accName, 3394 SubName: subName, 3395 } 3396 3397 return subs, err 3398 } 3399 3400 func checkSubscriptionValid(ctx context.Context, ses FeSession, createSql string) (*plan.SubscriptionMeta, error) { 3401 var ( 3402 err error 3403 accName, pubName, subName string 3404 ) 3405 if subName, accName, pubName, err = getSubInfoFromSql(ctx, ses, createSql); err != nil { 3406 return nil, err 3407 } 3408 return checkSubscriptionValidCommon(ctx, ses, subName, accName, pubName) 3409 } 3410 3411 func isDbPublishing(ctx context.Context, dbName string, ses FeSession) (ok bool, err error) { 3412 bh := ses.GetBackgroundExec(ctx) 3413 defer bh.Close() 3414 var ( 3415 sql string 3416 erArray []ExecResult 3417 count int64 3418 ) 3419 3420 if _, isSysDb := sysDatabases[dbName]; isSysDb { 3421 return false, err 3422 } 3423 3424 sql, err = getSqlForDbPubCount(ctx, dbName) 3425 if err != nil { 3426 return false, err 3427 } 3428 err = bh.Exec(ctx, "begin;") 3429 defer func() { 3430 err = finishTxn(ctx, bh, err) 3431 }() 3432 if err != nil { 3433 return false, err 3434 } 3435 bh.ClearExecResultSet() 3436 err = bh.Exec(ctx, sql) 3437 if err != nil { 3438 return false, err 3439 } 3440 erArray, err = getResultSet(ctx, bh) 3441 if err != nil { 3442 return false, err 3443 } 3444 if !execResultArrayHasData(erArray) { 3445 return false, moerr.NewInternalError(ctx, "there is no publication for database %s", dbName) 3446 } 3447 count, err = erArray[0].GetInt64(ctx, 0, 0) 3448 if err != nil { 3449 return false, err 3450 } 3451 3452 return count > 0, err 3453 } 3454 3455 func checkStageExistOrNot(ctx context.Context, bh BackgroundExec, stageName string) (bool, error) { 3456 var sql string 3457 var erArray []ExecResult 3458 var err error 3459 sql, err = getSqlForCheckStage(ctx, stageName) 3460 if err != nil { 3461 return false, err 3462 } 3463 bh.ClearExecResultSet() 3464 err = bh.Exec(ctx, sql) 3465 if err != nil { 3466 return false, err 3467 } 3468 3469 erArray, err = getResultSet(ctx, bh) 3470 if err != nil { 3471 return false, err 3472 } 3473 3474 if execResultArrayHasData(erArray) { 3475 return true, nil 3476 } 3477 return false, nil 3478 } 3479 3480 func formatCredentials(credentials tree.StageCredentials) string { 3481 var rstr string 3482 if credentials.Exist { 3483 for i := 0; i < len(credentials.Credentials)-1; i += 2 { 3484 rstr += fmt.Sprintf("%s=%s", credentials.Credentials[i], credentials.Credentials[i+1]) 3485 if i != len(credentials.Credentials)-2 { 3486 rstr += "," 3487 } 3488 } 3489 } 3490 return rstr 3491 } 3492 3493 func doCreateStage(ctx context.Context, ses *Session, cs *tree.CreateStage) (err error) { 3494 var sql string 3495 //var err error 3496 var stageExist bool 3497 var credentials string 3498 var StageStatus string 3499 var comment string 3500 bh := ses.GetBackgroundExec(ctx) 3501 defer bh.Close() 3502 3503 // check create stage priv 3504 err = doCheckRole(ctx, ses) 3505 if err != nil { 3506 return err 3507 } 3508 3509 err = bh.Exec(ctx, "begin;") 3510 defer func() { 3511 err = finishTxn(ctx, bh, err) 3512 }() 3513 if err != nil { 3514 return err 3515 } 3516 3517 // check stage 3518 stageExist, err = checkStageExistOrNot(ctx, bh, string(cs.Name)) 3519 if err != nil { 3520 return err 3521 } 3522 3523 if stageExist { 3524 if !cs.IfNotExists { 3525 return moerr.NewInternalError(ctx, "the stage %s exists", cs.Name) 3526 } else { 3527 // do nothing 3528 return err 3529 } 3530 } else { 3531 // format credentials and hash it 3532 credentials = HashPassWord(formatCredentials(cs.Credentials)) 3533 3534 if !cs.Status.Exist { 3535 StageStatus = "disabled" 3536 } else { 3537 StageStatus = cs.Status.Option.String() 3538 } 3539 3540 if cs.Comment.Exist { 3541 comment = cs.Comment.Comment 3542 } 3543 3544 sql, err = getSqlForInsertIntoMoStages(ctx, string(cs.Name), cs.Url, credentials, StageStatus, types.CurrentTimestamp().String2(time.UTC, 0), comment) 3545 if err != nil { 3546 return err 3547 } 3548 3549 err = bh.Exec(ctx, sql) 3550 if err != nil { 3551 return err 3552 } 3553 } 3554 3555 return err 3556 } 3557 3558 func doCheckFilePath(ctx context.Context, ses *Session, ep *tree.ExportParam) (err error) { 3559 //var err error 3560 var filePath string 3561 var sql string 3562 var erArray []ExecResult 3563 var stageName string 3564 var stageStatus string 3565 var url string 3566 if ep == nil { 3567 return err 3568 } 3569 3570 bh := ses.GetBackgroundExec(ctx) 3571 defer bh.Close() 3572 3573 err = bh.Exec(ctx, "begin;") 3574 defer func() { 3575 err = finishTxn(ctx, bh, err) 3576 }() 3577 if err != nil { 3578 return err 3579 } 3580 3581 // detect filepath contain stage or not 3582 filePath = ep.FilePath 3583 if !strings.Contains(filePath, ":") { 3584 // the filepath is the target path 3585 sql = getSqlForCheckStageStatus(ctx, "enabled") 3586 bh.ClearExecResultSet() 3587 err = bh.Exec(ctx, sql) 3588 if err != nil { 3589 return err 3590 } 3591 3592 erArray, err = getResultSet(ctx, bh) 3593 if err != nil { 3594 return err 3595 } 3596 3597 // if have stage enabled 3598 if execResultArrayHasData(erArray) { 3599 return moerr.NewInternalError(ctx, "stage exists, please try to check and use a stage instead") 3600 } else { 3601 // use the filepath 3602 return err 3603 } 3604 } else { 3605 stageName = strings.Split(filePath, ":")[0] 3606 // check the stage status 3607 sql, err = getSqlForCheckStageStatusWithStageName(ctx, stageName) 3608 if err != nil { 3609 return err 3610 } 3611 bh.ClearExecResultSet() 3612 err = bh.Exec(ctx, sql) 3613 if err != nil { 3614 return err 3615 } 3616 3617 erArray, err = getResultSet(ctx, bh) 3618 if err != nil { 3619 return err 3620 } 3621 if execResultArrayHasData(erArray) { 3622 stageStatus, err = erArray[0].GetString(ctx, 0, 1) 3623 if err != nil { 3624 return err 3625 } 3626 3627 // is the stage staus is disabled 3628 if stageStatus == tree.StageStatusDisabled.String() { 3629 return moerr.NewInternalError(ctx, "stage '%s' is invalid, please check", stageName) 3630 } else if stageStatus == tree.StageStatusEnabled.String() { 3631 // replace the filepath using stage url 3632 url, err = erArray[0].GetString(ctx, 0, 0) 3633 if err != nil { 3634 return err 3635 } 3636 3637 filePath = strings.Replace(filePath, stageName+":", url, 1) 3638 ses.ep.userConfig.StageFilePath = filePath 3639 } 3640 } else { 3641 return moerr.NewInternalError(ctx, "stage '%s' is not exists, please check", stageName) 3642 } 3643 } 3644 return err 3645 3646 } 3647 3648 func doAlterStage(ctx context.Context, ses *Session, as *tree.AlterStage) (err error) { 3649 var sql string 3650 //var err error 3651 var stageExist bool 3652 var credentials string 3653 bh := ses.GetBackgroundExec(ctx) 3654 defer bh.Close() 3655 3656 // check create stage priv 3657 err = doCheckRole(ctx, ses) 3658 if err != nil { 3659 return err 3660 } 3661 3662 optionBits := uint8(0) 3663 if as.UrlOption.Exist { 3664 optionBits |= 1 3665 } 3666 if as.CredentialsOption.Exist { 3667 optionBits |= 1 << 1 3668 } 3669 if as.StatusOption.Exist { 3670 optionBits |= 1 << 2 3671 } 3672 if as.Comment.Exist { 3673 optionBits |= 1 << 3 3674 } 3675 optionCount := bits.OnesCount8(optionBits) 3676 if optionCount == 0 { 3677 return moerr.NewInternalError(ctx, "at least one option at a time") 3678 } 3679 if optionCount > 1 { 3680 return moerr.NewInternalError(ctx, "at most one option at a time") 3681 } 3682 3683 err = bh.Exec(ctx, "begin;") 3684 defer func() { 3685 err = finishTxn(ctx, bh, err) 3686 }() 3687 if err != nil { 3688 return err 3689 } 3690 3691 // check stage 3692 stageExist, err = checkStageExistOrNot(ctx, bh, string(as.Name)) 3693 if err != nil { 3694 return err 3695 } 3696 3697 if !stageExist { 3698 if !as.IfNotExists { 3699 return moerr.NewInternalError(ctx, "the stage %s not exists", as.Name) 3700 } else { 3701 // do nothing 3702 return err 3703 } 3704 } else { 3705 if as.UrlOption.Exist { 3706 sql = getsqlForUpdateStageUrl(string(as.Name), as.UrlOption.Url) 3707 err = bh.Exec(ctx, sql) 3708 if err != nil { 3709 return err 3710 } 3711 } 3712 3713 if as.CredentialsOption.Exist { 3714 credentials = HashPassWord(formatCredentials(as.CredentialsOption)) 3715 sql = getsqlForUpdateStageCredentials(string(as.Name), credentials) 3716 err = bh.Exec(ctx, sql) 3717 if err != nil { 3718 return err 3719 } 3720 } 3721 3722 if as.StatusOption.Exist { 3723 sql = getsqlForUpdateStageStatus(string(as.Name), as.StatusOption.Option.String()) 3724 err = bh.Exec(ctx, sql) 3725 if err != nil { 3726 return err 3727 } 3728 } 3729 3730 if as.Comment.Exist { 3731 sql = getsqlForUpdateStageComment(string(as.Name), as.Comment.Comment) 3732 err = bh.Exec(ctx, sql) 3733 if err != nil { 3734 return err 3735 } 3736 } 3737 } 3738 return err 3739 } 3740 3741 func doDropStage(ctx context.Context, ses *Session, ds *tree.DropStage) (err error) { 3742 var sql string 3743 //var err error 3744 var stageExist bool 3745 bh := ses.GetBackgroundExec(ctx) 3746 defer bh.Close() 3747 3748 // check create stage priv 3749 err = doCheckRole(ctx, ses) 3750 if err != nil { 3751 return err 3752 } 3753 3754 err = bh.Exec(ctx, "begin;") 3755 defer func() { 3756 err = finishTxn(ctx, bh, err) 3757 }() 3758 if err != nil { 3759 return err 3760 } 3761 3762 // check stage 3763 stageExist, err = checkStageExistOrNot(ctx, bh, string(ds.Name)) 3764 if err != nil { 3765 return err 3766 } 3767 3768 if !stageExist { 3769 if !ds.IfNotExists { 3770 return moerr.NewInternalError(ctx, "the stage %s not exists", ds.Name) 3771 } else { 3772 // do nothing 3773 return err 3774 } 3775 } else { 3776 sql = getSqlForDropStage(string(ds.Name)) 3777 err = bh.Exec(ctx, sql) 3778 if err != nil { 3779 return err 3780 } 3781 } 3782 return err 3783 } 3784 3785 func doCreatePublication(ctx context.Context, ses *Session, cp *tree.CreatePublication) (err error) { 3786 bh := ses.GetBackgroundExec(ctx) 3787 defer bh.Close() 3788 const allTable = true 3789 var ( 3790 sql string 3791 dbId uint64 3792 dbType string 3793 tableList string 3794 accountList string 3795 tenantInfo *TenantInfo 3796 ) 3797 3798 tenantInfo = ses.GetTenantInfo() 3799 3800 if !tenantInfo.IsAdminRole() { 3801 return moerr.NewInternalError(ctx, "only admin can create publication") 3802 } 3803 3804 if cp.AccountsSet == nil || cp.AccountsSet.All { 3805 accountList = "all" 3806 } else { 3807 accts := make([]string, 0, len(cp.AccountsSet.SetAccounts)) 3808 for _, acct := range cp.AccountsSet.SetAccounts { 3809 accName := string(acct) 3810 if accountNameIsInvalid(accName) { 3811 return moerr.NewInternalError(ctx, "invalid account name '%s'", accName) 3812 } 3813 accts = append(accts, accName) 3814 } 3815 sort.Strings(accts) 3816 accountList = strings.Join(accts, ",") 3817 } 3818 3819 pubDb := string(cp.Database) 3820 3821 if _, ok := sysDatabases[pubDb]; ok { 3822 return moerr.NewInternalError(ctx, "invalid database name '%s', not support publishing system database", pubDb) 3823 } 3824 3825 err = bh.Exec(ctx, "begin;") 3826 defer func() { 3827 err = finishTxn(ctx, bh, err) 3828 }() 3829 if err != nil { 3830 return err 3831 } 3832 bh.ClearExecResultSet() 3833 3834 if dbId, dbType, err = getDbIdAndType(ctx, bh, tenantInfo, pubDb); err != nil { 3835 return err 3836 } 3837 if dbType != "" { //TODO: check the dat_type 3838 return moerr.NewInternalError(ctx, "database '%s' is not a user database", cp.Database) 3839 } 3840 3841 sql, err = getSqlForInsertIntoMoPubs(ctx, string(cp.Name), pubDb, dbId, allTable, tableList, accountList, tenantInfo.GetDefaultRoleID(), tenantInfo.GetUserID(), cp.Comment, true) 3842 if err != nil { 3843 return err 3844 } 3845 err = bh.Exec(ctx, sql) 3846 if err != nil { 3847 return err 3848 } 3849 return err 3850 } 3851 3852 func doAlterPublication(ctx context.Context, ses *Session, ap *tree.AlterPublication) (err error) { 3853 bh := ses.GetBackgroundExec(ctx) 3854 defer bh.Close() 3855 var ( 3856 allAccount bool 3857 accountList string 3858 accountListSep []string 3859 comment string 3860 dbName string 3861 dbId uint64 3862 dbType string 3863 sql string 3864 erArray []ExecResult 3865 tenantInfo *TenantInfo 3866 ) 3867 3868 tenantInfo = ses.GetTenantInfo() 3869 3870 if !tenantInfo.IsAdminRole() { 3871 return moerr.NewInternalError(ctx, "only admin can alter publication") 3872 } 3873 3874 err = bh.Exec(ctx, "begin;") 3875 defer func() { 3876 err = finishTxn(ctx, bh, err) 3877 }() 3878 if err != nil { 3879 return err 3880 } 3881 bh.ClearExecResultSet() 3882 3883 sql, err = getSqlForGetPubInfo(ctx, string(ap.Name), true) 3884 if err != nil { 3885 return err 3886 } 3887 err = bh.Exec(ctx, sql) 3888 if err != nil { 3889 return err 3890 } 3891 erArray, err = getResultSet(ctx, bh) 3892 if err != nil { 3893 return err 3894 } 3895 if !execResultArrayHasData(erArray) { 3896 return moerr.NewInternalError(ctx, "publication '%s' does not exist", ap.Name) 3897 } 3898 bh.ClearExecResultSet() 3899 3900 // alter account 3901 if accountList, err = erArray[0].GetString(ctx, 0, 0); err != nil { 3902 return err 3903 } 3904 allAccount = accountList == "all" 3905 3906 if ap.AccountsSet != nil { 3907 switch { 3908 case ap.AccountsSet.All: 3909 accountList = "all" 3910 case len(ap.AccountsSet.SetAccounts) > 0: 3911 /* do not check accountName if exists here */ 3912 accts := make([]string, 0, len(ap.AccountsSet.SetAccounts)) 3913 for _, acct := range ap.AccountsSet.SetAccounts { 3914 s := string(acct) 3915 if accountNameIsInvalid(s) { 3916 return moerr.NewInternalError(ctx, "invalid account name '%s'", s) 3917 } 3918 accts = append(accts, s) 3919 } 3920 sort.Strings(accts) 3921 accountList = strings.Join(accts, ",") 3922 case len(ap.AccountsSet.DropAccounts) > 0: 3923 if allAccount { 3924 return moerr.NewInternalError(ctx, "cannot drop accounts from all account option") 3925 } 3926 accountListSep = strings.Split(accountList, ",") 3927 for _, acct := range ap.AccountsSet.DropAccounts { 3928 if accountNameIsInvalid(string(acct)) { 3929 return moerr.NewInternalError(ctx, "invalid account name '%s'", acct) 3930 } 3931 idx := sort.SearchStrings(accountListSep, string(acct)) 3932 if idx < len(accountListSep) && accountListSep[idx] == string(acct) { 3933 accountListSep = append(accountListSep[:idx], accountListSep[idx+1:]...) 3934 } 3935 } 3936 accountList = strings.Join(accountListSep, ",") 3937 case len(ap.AccountsSet.AddAccounts) > 0: 3938 if allAccount { 3939 return moerr.NewInternalError(ctx, "cannot add account from all account option") 3940 } 3941 accountListSep = strings.Split(accountList, ",") 3942 for _, acct := range ap.AccountsSet.AddAccounts { 3943 if accountNameIsInvalid(string(acct)) { 3944 return moerr.NewInternalError(ctx, "invalid account name '%s'", acct) 3945 } 3946 idx := sort.SearchStrings(accountListSep, string(acct)) 3947 if idx == len(accountListSep) || accountListSep[idx] != string(acct) { 3948 accountListSep = append(accountListSep[:idx], append([]string{string(acct)}, accountListSep[idx:]...)...) 3949 } 3950 } 3951 accountList = strings.Join(accountListSep, ",") 3952 } 3953 } 3954 3955 // alter comment 3956 if comment, err = erArray[0].GetString(ctx, 0, 1); err != nil { 3957 return err 3958 } 3959 3960 if ap.Comment != "" { 3961 comment = ap.Comment 3962 } 3963 3964 // alter db 3965 if dbName, err = erArray[0].GetString(ctx, 0, 2); err != nil { 3966 return err 3967 } 3968 if dbId, err = erArray[0].GetUint64(ctx, 0, 3); err != nil { 3969 return err 3970 } 3971 3972 if ap.DbName != "" { 3973 dbName = ap.DbName 3974 if _, ok := sysDatabases[dbName]; ok { 3975 return moerr.NewInternalError(ctx, "invalid database name '%s', not support publishing system database", dbName) 3976 } 3977 3978 if dbId, dbType, err = getDbIdAndType(ctx, bh, tenantInfo, dbName); err != nil { 3979 return err 3980 } 3981 if dbType != "" { //TODO: check the dat_type 3982 return moerr.NewInternalError(ctx, "database '%s' is not a user database", dbName) 3983 } 3984 } 3985 3986 sql, err = getSqlForUpdatePubInfo(ctx, string(ap.Name), accountList, comment, dbName, dbId, false) 3987 if err != nil { 3988 return err 3989 } 3990 return bh.Exec(ctx, sql) 3991 } 3992 3993 func doDropPublication(ctx context.Context, ses *Session, dp *tree.DropPublication) (err error) { 3994 bh := ses.GetBackgroundExec(ctx) 3995 defer bh.Close() 3996 bh.ClearExecResultSet() 3997 var ( 3998 sql string 3999 erArray []ExecResult 4000 tenantInfo *TenantInfo 4001 ) 4002 4003 tenantInfo = ses.GetTenantInfo() 4004 4005 if !tenantInfo.IsAdminRole() { 4006 return moerr.NewInternalError(ctx, "only admin can drop publication") 4007 } 4008 4009 err = bh.Exec(ctx, "begin;") 4010 defer func() { 4011 err = finishTxn(ctx, bh, err) 4012 }() 4013 if err != nil { 4014 return err 4015 } 4016 sql, err = getSqlForGetPubInfo(ctx, string(dp.Name), true) 4017 if err != nil { 4018 return err 4019 } 4020 bh.ClearExecResultSet() 4021 err = bh.Exec(ctx, sql) 4022 if err != nil { 4023 return err 4024 } 4025 erArray, err = getResultSet(ctx, bh) 4026 if err != nil { 4027 return err 4028 } 4029 if !execResultArrayHasData(erArray) { 4030 return moerr.NewInternalError(ctx, "publication '%s' does not exist", dp.Name) 4031 } 4032 4033 sql, err = getSqlForDropPubInfo(ctx, string(dp.Name), false) 4034 if err != nil { 4035 return err 4036 } 4037 4038 err = bh.Exec(ctx, sql) 4039 if err != nil { 4040 return err 4041 } 4042 4043 return err 4044 } 4045 4046 type dropAccount struct { 4047 IfExists bool 4048 Name string 4049 } 4050 4051 // doDropAccount accomplishes the DropAccount statement 4052 func doDropAccount(ctx context.Context, ses *Session, da *dropAccount) (err error) { 4053 bh := ses.GetBackgroundExec(ctx) 4054 defer bh.Close() 4055 4056 //set backgroundHandler's default schema 4057 if handler, ok := bh.(*backExec); ok { 4058 handler.backSes. 4059 txnCompileCtx.dbName = catalog.MO_CATALOG 4060 } 4061 4062 var sql, db, table string 4063 var erArray []ExecResult 4064 var databases map[string]int8 4065 var dbSql, prefix string 4066 var sqlsForDropDatabases = make([]string, 0, 5) 4067 4068 var deleteCtx context.Context 4069 var accountId int64 4070 var version uint64 4071 var hasAccount = true 4072 clusterTables := make(map[string]int) 4073 4074 da.Name, err = normalizeName(ctx, da.Name) 4075 if err != nil { 4076 return err 4077 } 4078 4079 if isSysTenant(da.Name) { 4080 return moerr.NewInternalError(ctx, "can not delete the account %s", da.Name) 4081 } 4082 4083 dropAccountFunc := func() (rtnErr error) { 4084 rtnErr = bh.Exec(ctx, "begin;") 4085 defer func() { 4086 rtnErr = finishTxn(ctx, bh, rtnErr) 4087 }() 4088 if rtnErr != nil { 4089 return rtnErr 4090 } 4091 4092 //check the account exists or not 4093 sql, rtnErr = getSqlForCheckTenant(ctx, da.Name) 4094 if rtnErr != nil { 4095 return rtnErr 4096 } 4097 bh.ClearExecResultSet() 4098 rtnErr = bh.Exec(ctx, sql) 4099 if rtnErr != nil { 4100 return rtnErr 4101 } 4102 4103 erArray, rtnErr = getResultSet(ctx, bh) 4104 if rtnErr != nil { 4105 return rtnErr 4106 } 4107 4108 if execResultArrayHasData(erArray) { 4109 accountId, rtnErr = erArray[0].GetInt64(ctx, 0, 0) 4110 if rtnErr != nil { 4111 return rtnErr 4112 } 4113 version, rtnErr = erArray[0].GetUint64(ctx, 0, 3) 4114 if rtnErr != nil { 4115 return rtnErr 4116 } 4117 } else { 4118 //no such account 4119 if !da.IfExists { //when the "IF EXISTS" is set, just skip it. 4120 rtnErr = moerr.NewInternalError(ctx, "there is no account %s", da.Name) 4121 return 4122 } 4123 hasAccount = false 4124 } 4125 4126 if !hasAccount { 4127 return rtnErr 4128 } 4129 4130 //drop tables of the tenant 4131 //NOTE!!!: single DDL drop statement per single transaction 4132 //SWITCH TO THE CONTEXT of the deleted context 4133 deleteCtx = defines.AttachAccountId(ctx, uint32(accountId)) 4134 4135 //step 2 : drop table mo_user 4136 //step 3 : drop table mo_role 4137 //step 4 : drop table mo_user_grant 4138 //step 5 : drop table mo_role_grant 4139 //step 6 : drop table mo_role_privs 4140 //step 7 : drop table mo_user_defined_function 4141 //step 8 : drop table mo_mysql_compatibility_mode 4142 //step 9 : drop table %!%mo_increment_columns 4143 for _, sql = range getSqlForDropAccount() { 4144 rtnErr = bh.Exec(deleteCtx, sql) 4145 if rtnErr != nil { 4146 return rtnErr 4147 } 4148 } 4149 4150 //drop databases created by user 4151 databases = make(map[string]int8) 4152 dbSql = "show databases;" 4153 bh.ClearExecResultSet() 4154 rtnErr = bh.Exec(deleteCtx, dbSql) 4155 if rtnErr != nil { 4156 return rtnErr 4157 } 4158 4159 erArray, rtnErr = getResultSet(ctx, bh) 4160 if rtnErr != nil { 4161 return rtnErr 4162 } 4163 4164 for i := uint64(0); i < erArray[0].GetRowCount(); i++ { 4165 db, rtnErr = erArray[0].GetString(ctx, i, 0) 4166 if rtnErr != nil { 4167 return rtnErr 4168 } 4169 databases[db] = 0 4170 } 4171 4172 prefix = "drop database if exists " 4173 4174 for db = range databases { 4175 if db == "mo_catalog" { 4176 continue 4177 } 4178 bb := &bytes.Buffer{} 4179 bb.WriteString(prefix) 4180 //handle the database annotated by '`' 4181 bb.WriteString("`") 4182 bb.WriteString(db) 4183 bb.WriteString("`") 4184 4185 bb.WriteString(";") 4186 sqlsForDropDatabases = append(sqlsForDropDatabases, bb.String()) 4187 } 4188 4189 for _, sql = range sqlsForDropDatabases { 4190 rtnErr = bh.Exec(deleteCtx, sql) 4191 if rtnErr != nil { 4192 return rtnErr 4193 } 4194 } 4195 4196 // drop table mo_mysql_compatibility_mode 4197 rtnErr = bh.Exec(deleteCtx, dropMoMysqlCompatibilityModeSql) 4198 if rtnErr != nil { 4199 return rtnErr 4200 } 4201 4202 // drop table mo_pubs 4203 rtnErr = bh.Exec(deleteCtx, dropMoPubsSql) 4204 if rtnErr != nil { 4205 return rtnErr 4206 } 4207 4208 // drop autoIcr table 4209 rtnErr = bh.Exec(deleteCtx, dropAutoIcrColSql) 4210 if rtnErr != nil { 4211 return rtnErr 4212 } 4213 4214 // drop mo_catalog.mo_indexes under general tenant 4215 rtnErr = bh.Exec(deleteCtx, dropMoIndexes) 4216 if rtnErr != nil { 4217 return rtnErr 4218 } 4219 4220 // drop mo_catalog.mo_table_partitions under general tenant 4221 rtnErr = bh.Exec(deleteCtx, dropMoTablePartitions) 4222 if rtnErr != nil { 4223 return rtnErr 4224 } 4225 4226 rtnErr = bh.Exec(deleteCtx, dropMoForeignKeys) 4227 if rtnErr != nil { 4228 return rtnErr 4229 } 4230 4231 // delete the account in the mo_account of the sys account 4232 sql, rtnErr = getSqlForDeleteAccountFromMoAccount(ctx, da.Name) 4233 if rtnErr != nil { 4234 return rtnErr 4235 } 4236 rtnErr = bh.Exec(ctx, sql) 4237 if rtnErr != nil { 4238 return rtnErr 4239 } 4240 4241 // get all cluster table in the mo_catalog 4242 sql = "show tables from mo_catalog;" 4243 bh.ClearExecResultSet() 4244 rtnErr = bh.Exec(ctx, sql) 4245 if rtnErr != nil { 4246 return rtnErr 4247 } 4248 4249 erArray, rtnErr = getResultSet(ctx, bh) 4250 if rtnErr != nil { 4251 return rtnErr 4252 } 4253 4254 for i := uint64(0); i < erArray[0].GetRowCount(); i++ { 4255 table, rtnErr = erArray[0].GetString(ctx, i, 0) 4256 if rtnErr != nil { 4257 return rtnErr 4258 } 4259 if isClusterTable("mo_catalog", table) { 4260 clusterTables[table] = 0 4261 } 4262 } 4263 4264 // delete all data of the account in the cluster table 4265 for clusterTable := range clusterTables { 4266 sql = fmt.Sprintf("delete from mo_catalog.`%s` where account_id = %d;", clusterTable, accountId) 4267 bh.ClearExecResultSet() 4268 rtnErr = bh.Exec(ctx, sql) 4269 if rtnErr != nil { 4270 return rtnErr 4271 } 4272 } 4273 return rtnErr 4274 } 4275 4276 err = dropAccountFunc() 4277 if err != nil { 4278 return err 4279 } 4280 4281 // if drop the account, add the account to kill queue 4282 ses.getRoutineManager().accountRoutine.EnKillQueue(accountId, version) 4283 4284 if err := postDropSuspendAccount(ctx, ses, da.Name, accountId, version); err != nil { 4285 logutil.Errorf("post drop account error: %s", err.Error()) 4286 } 4287 4288 return err 4289 } 4290 4291 func postDropSuspendAccount( 4292 ctx context.Context, ses *Session, accountName string, accountID int64, version uint64, 4293 ) (err error) { 4294 qc := getGlobalPu().QueryClient 4295 if qc == nil { 4296 return moerr.NewInternalError(ctx, "query client is not initialized") 4297 } 4298 var nodes []string 4299 currTenant := ses.GetTenantInfo().GetTenant() 4300 currUser := ses.GetTenantInfo().User 4301 labels := clusterservice.NewSelector().SelectByLabel( 4302 map[string]string{"account": accountName}, clusterservice.Contain) 4303 sysTenant := isSysTenant(currTenant) 4304 if sysTenant { 4305 route.RouteForSuperTenant(clusterservice.NewSelector(), currUser, nil, 4306 func(s *metadata.CNService) { 4307 nodes = append(nodes, s.QueryAddress) 4308 }) 4309 } else { 4310 route.RouteForCommonTenant(labels, nil, func(s *metadata.CNService) { 4311 nodes = append(nodes, s.QueryAddress) 4312 }) 4313 } 4314 4315 var retErr error 4316 genRequest := func() *query.Request { 4317 req := qc.NewRequest(query.CmdMethod_KillConn) 4318 req.KillConnRequest = &query.KillConnRequest{ 4319 AccountID: accountID, 4320 Version: version, 4321 } 4322 return req 4323 } 4324 4325 handleValidResponse := func(nodeAddr string, rsp *query.Response) { 4326 if rsp != nil && rsp.KillConnResponse != nil && !rsp.KillConnResponse.Success { 4327 retErr = moerr.NewInternalError(ctx, 4328 fmt.Sprintf("kill connection for account %s failed on node %s", accountName, nodeAddr)) 4329 } 4330 } 4331 4332 handleInvalidResponse := func(nodeAddr string) { 4333 retErr = moerr.NewInternalError(ctx, 4334 fmt.Sprintf("kill connection for account %s failed on node %s", accountName, nodeAddr)) 4335 } 4336 4337 err = queryservice.RequestMultipleCn(ctx, nodes, qc, genRequest, handleValidResponse, handleInvalidResponse) 4338 return errors.Join(err, retErr) 4339 } 4340 4341 // doDropUser accomplishes the DropUser statement 4342 func doDropUser(ctx context.Context, ses *Session, du *tree.DropUser) (err error) { 4343 var vr *verifiedRole 4344 var sql string 4345 var sqls []string 4346 var erArray []ExecResult 4347 account := ses.GetTenantInfo() 4348 err = normalizeNamesOfUsers(ctx, du.Users) 4349 if err != nil { 4350 return err 4351 } 4352 4353 bh := ses.GetBackgroundExec(ctx) 4354 defer bh.Close() 4355 4356 //put it into the single transaction 4357 err = bh.Exec(ctx, "begin;") 4358 defer func() { 4359 err = finishTxn(ctx, bh, err) 4360 }() 4361 if err != nil { 4362 return err 4363 } 4364 4365 //step1: check users exists or not. 4366 //handle "IF EXISTS" 4367 for _, user := range du.Users { 4368 sql, err = getSqlForPasswordOfUser(ctx, user.Username) 4369 if err != nil { 4370 return err 4371 } 4372 vr, err = verifyRoleFunc(ctx, bh, sql, user.Username, roleType) 4373 if err != nil { 4374 return err 4375 } 4376 4377 if vr == nil { 4378 if !du.IfExists { //when the "IF EXISTS" is set, just skip it. 4379 return moerr.NewInternalError(ctx, "there is no user %s", user.Username) 4380 } 4381 } 4382 4383 if vr == nil { 4384 continue 4385 } 4386 4387 //if the user is admin user with the role moadmin or accountadmin, 4388 //the user can not be deleted. 4389 if account.IsSysTenant() { 4390 sql, err = getSqlForCheckUserHasRole(ctx, user.Username, moAdminRoleID) 4391 } else { 4392 sql, err = getSqlForCheckUserHasRole(ctx, user.Username, accountAdminRoleID) 4393 } 4394 if err != nil { 4395 return err 4396 } 4397 4398 bh.ClearExecResultSet() 4399 err = bh.Exec(ctx, sql) 4400 if err != nil { 4401 return err 4402 } 4403 4404 erArray, err = getResultSet(ctx, bh) 4405 if err != nil { 4406 return err 4407 } 4408 4409 if execResultArrayHasData(erArray) { 4410 return moerr.NewInternalError(ctx, "can not delete the user %s", user.Username) 4411 } 4412 4413 //step2 : delete mo_user 4414 //step3 : delete mo_user_grant 4415 sqls = getSqlForDeleteUser(vr.id) 4416 for _, sqlx := range sqls { 4417 bh.ClearExecResultSet() 4418 err = bh.Exec(ctx, sqlx) 4419 if err != nil { 4420 return err 4421 } 4422 } 4423 } 4424 return err 4425 } 4426 4427 // doDropRole accomplishes the DropRole statement 4428 func doDropRole(ctx context.Context, ses *Session, dr *tree.DropRole) (err error) { 4429 var vr *verifiedRole 4430 var sql string 4431 account := ses.GetTenantInfo() 4432 err = normalizeNamesOfRoles(ctx, dr.Roles) 4433 if err != nil { 4434 return err 4435 } 4436 4437 bh := ses.GetBackgroundExec(ctx) 4438 defer bh.Close() 4439 4440 //put it into the single transaction 4441 err = bh.Exec(ctx, "begin;") 4442 defer func() { 4443 err = finishTxn(ctx, bh, err) 4444 }() 4445 if err != nil { 4446 return err 4447 } 4448 4449 //step1: check roles exists or not. 4450 //handle "IF EXISTS" 4451 for _, role := range dr.Roles { 4452 sql, err = getSqlForRoleIdOfRole(ctx, role.UserName) 4453 if err != nil { 4454 return err 4455 } 4456 vr, err = verifyRoleFunc(ctx, bh, sql, role.UserName, roleType) 4457 if err != nil { 4458 return err 4459 } 4460 4461 if vr == nil { 4462 if !dr.IfExists { //when the "IF EXISTS" is set, just skip it. 4463 return moerr.NewInternalError(ctx, "there is no role %s", role.UserName) 4464 } 4465 } 4466 4467 //step2 : delete mo_role 4468 //step3 : delete mo_user_grant 4469 //step4 : delete mo_role_grant 4470 //step5 : delete mo_role_privs 4471 if vr == nil { 4472 continue 4473 } 4474 4475 //NOTE: if the role is the admin role (moadmin,accountadmin) or public, 4476 //the role can not be deleted. 4477 if account.IsNameOfAdminRoles(vr.name) || isPublicRole(vr.name) { 4478 return moerr.NewInternalError(ctx, "can not delete the role %s", vr.name) 4479 } 4480 4481 sqls := getSqlForDeleteRole(vr.id) 4482 for _, sqlx := range sqls { 4483 bh.ClearExecResultSet() 4484 err = bh.Exec(ctx, sqlx) 4485 if err != nil { 4486 return err 4487 } 4488 } 4489 } 4490 4491 return err 4492 } 4493 4494 type rmPkg func(path string) error 4495 4496 func doDropFunction(ctx context.Context, ses *Session, df *tree.DropFunction, rm rmPkg) (err error) { 4497 var sql string 4498 var argstr string 4499 var bodyStr string 4500 var checkDatabase string 4501 var dbName string 4502 var dbExists bool 4503 var funcId int64 4504 var erArray []ExecResult 4505 4506 bh := ses.GetBackgroundExec(ctx) 4507 defer bh.Close() 4508 4509 // a database must be selected or specified as qualifier when create a function 4510 if df.Name.HasNoNameQualifier() { 4511 if ses.DatabaseNameIsEmpty() { 4512 return moerr.NewNoDBNoCtx() 4513 } 4514 dbName = ses.GetDatabaseName() 4515 } else { 4516 dbName = string(df.Name.Name.SchemaName) 4517 } 4518 4519 // authticate db exists 4520 dbExists, err = checkDatabaseExistsOrNot(ctx, ses.GetBackgroundExec(ctx), dbName) 4521 if err != nil { 4522 return err 4523 } 4524 if !dbExists { 4525 return moerr.NewBadDB(ctx, dbName) 4526 } 4527 4528 // validate database name and signature (name + args) 4529 bh.ClearExecResultSet() 4530 checkDatabase = fmt.Sprintf(checkUdfArgs, string(df.Name.Name.ObjectName), dbName) 4531 err = bh.Exec(ctx, checkDatabase) 4532 if err != nil { 4533 return err 4534 } 4535 4536 erArray, err = getResultSet(ctx, bh) 4537 if err != nil { 4538 return err 4539 } 4540 4541 if execResultArrayHasData(erArray) { 4542 receivedArgsType := make([]string, len(df.Args)) 4543 for i, arg := range df.Args { 4544 typ, err := plan2.GetFunctionArgTypeStrFromAst(arg) 4545 if err != nil { 4546 return err 4547 } 4548 receivedArgsType[i] = typ 4549 } 4550 4551 // function with provided name and db exists, now check arguments 4552 for i := uint64(0); i < erArray[0].GetRowCount(); i++ { 4553 argstr, err = erArray[0].GetString(ctx, i, 0) 4554 if err != nil { 4555 return err 4556 } 4557 funcId, err = erArray[0].GetInt64(ctx, i, 1) 4558 if err != nil { 4559 return err 4560 } 4561 bodyStr, err = erArray[0].GetString(ctx, i, 2) 4562 if err != nil { 4563 return err 4564 } 4565 argList := make([]*function.Arg, 0) 4566 json.Unmarshal([]byte(argstr), &argList) 4567 if len(argList) == len(df.Args) { 4568 match := true 4569 for j, arg := range argList { 4570 typ := receivedArgsType[j] 4571 if arg.Type != typ { 4572 match = false 4573 break 4574 } 4575 } 4576 if !match { 4577 continue 4578 } 4579 handleArgMatch := func() (rtnErr error) { 4580 //put it into the single transaction 4581 rtnErr = bh.Exec(ctx, "begin;") 4582 defer func() { 4583 rtnErr = finishTxn(ctx, bh, rtnErr) 4584 if rtnErr == nil { 4585 u := &function.NonSqlUdfBody{} 4586 if json.Unmarshal([]byte(bodyStr), u) == nil && u.Import { 4587 rm(u.Body) 4588 } 4589 } 4590 }() 4591 if rtnErr != nil { 4592 return rtnErr 4593 } 4594 4595 sql = fmt.Sprintf(deleteUserDefinedFunctionFormat, funcId) 4596 4597 rtnErr = bh.Exec(ctx, sql) 4598 if rtnErr != nil { 4599 return rtnErr 4600 } 4601 return rtnErr 4602 } 4603 return handleArgMatch() 4604 } 4605 } 4606 } 4607 // no such function 4608 return moerr.NewNoUDFNoCtx(string(df.Name.Name.ObjectName)) 4609 } 4610 4611 func doDropFunctionWithDB(ctx context.Context, ses *Session, stmt tree.Statement, rm rmPkg) (err error) { 4612 var sql string 4613 var bodyStr string 4614 var funcId int64 4615 var erArray []ExecResult 4616 var dbName string 4617 4618 switch st := stmt.(type) { 4619 case *tree.DropDatabase: 4620 dbName = string(st.Name) 4621 default: 4622 } 4623 4624 bh := ses.GetBackgroundExec(ctx) 4625 defer bh.Close() 4626 4627 // validate database name and signature (name + args) 4628 bh.ClearExecResultSet() 4629 sql = getSqlForCheckUdfWithDb(dbName) 4630 err = bh.Exec(ctx, sql) 4631 if err != nil { 4632 return err 4633 } 4634 4635 erArray, err = getResultSet(ctx, bh) 4636 if err != nil { 4637 return err 4638 } 4639 4640 if execResultArrayHasData(erArray) { 4641 for i := uint64(0); i < erArray[0].GetRowCount(); i++ { 4642 funcId, err = erArray[0].GetInt64(ctx, i, 0) 4643 if err != nil { 4644 return err 4645 } 4646 bodyStr, err = erArray[0].GetString(ctx, i, 1) 4647 if err != nil { 4648 return err 4649 } 4650 4651 handleArgMatch := func() (rtnErr error) { 4652 //put it into the single transaction 4653 rtnErr = bh.Exec(ctx, "begin;") 4654 defer func() { 4655 rtnErr = finishTxn(ctx, bh, rtnErr) 4656 if rtnErr == nil { 4657 u := &function.NonSqlUdfBody{} 4658 if json.Unmarshal([]byte(bodyStr), u) == nil && u.Import { 4659 rm(u.Body) 4660 } 4661 } 4662 }() 4663 if rtnErr != nil { 4664 return rtnErr 4665 } 4666 4667 sql = fmt.Sprintf(deleteUserDefinedFunctionFormat, funcId) 4668 4669 rtnErr = bh.Exec(ctx, sql) 4670 if rtnErr != nil { 4671 return rtnErr 4672 } 4673 return rtnErr 4674 } 4675 4676 err = handleArgMatch() 4677 if err != nil { 4678 return err 4679 } 4680 } 4681 } 4682 4683 return err 4684 } 4685 4686 func doDropProcedure(ctx context.Context, ses *Session, dp *tree.DropProcedure) (err error) { 4687 var sql string 4688 var checkDatabase string 4689 var dbName string 4690 var procId int64 4691 var erArray []ExecResult 4692 4693 bh := ses.GetBackgroundExec(ctx) 4694 defer bh.Close() 4695 4696 if dp.Name.HasNoNameQualifier() { 4697 if ses.DatabaseNameIsEmpty() { 4698 return moerr.NewNoDBNoCtx() 4699 } 4700 dbName = ses.GetDatabaseName() 4701 } else { 4702 dbName = string(dp.Name.Name.SchemaName) 4703 } 4704 4705 // validate database name and signature (name + args) 4706 bh.ClearExecResultSet() 4707 checkDatabase = fmt.Sprintf(checkStoredProcedureArgs, string(dp.Name.Name.ObjectName), dbName) 4708 err = bh.Exec(ctx, checkDatabase) 4709 if err != nil { 4710 return err 4711 } 4712 4713 erArray, err = getResultSet(ctx, bh) 4714 if err != nil { 4715 return err 4716 } 4717 4718 if execResultArrayHasData(erArray) { 4719 // function with provided name and db exists, for now we don't support overloading for stored procedure, so go to handle deletion. 4720 procId, err = erArray[0].GetInt64(ctx, 0, 0) 4721 if err != nil { 4722 return err 4723 } 4724 handleArgMatch := func() (rtnErr error) { 4725 //put it into the single transaction 4726 rtnErr = bh.Exec(ctx, "begin;") 4727 defer func() { 4728 rtnErr = finishTxn(ctx, bh, rtnErr) 4729 }() 4730 if rtnErr != nil { 4731 return rtnErr 4732 } 4733 4734 sql = fmt.Sprintf(deleteStoredProcedureFormat, procId) 4735 4736 rtnErr = bh.Exec(ctx, sql) 4737 if rtnErr != nil { 4738 return rtnErr 4739 } 4740 return rtnErr 4741 } 4742 return handleArgMatch() 4743 } else { 4744 // no such procedure 4745 if dp.IfExists { 4746 return nil 4747 } 4748 return moerr.NewNoUDFNoCtx(string(dp.Name.Name.ObjectName)) 4749 } 4750 } 4751 4752 // doRevokePrivilege accomplishes the RevokePrivilege statement 4753 func doRevokePrivilege(ctx context.Context, ses FeSession, rp *tree.RevokePrivilege) (err error) { 4754 var vr *verifiedRole 4755 var objType objectType 4756 var privLevel privilegeLevelType 4757 var objId int64 4758 var privType PrivilegeType 4759 var sql string 4760 err = normalizeNamesOfRoles(ctx, rp.Roles) 4761 if err != nil { 4762 return err 4763 } 4764 4765 account := ses.GetTenantInfo() 4766 bh := ses.GetBackgroundExec(ctx) 4767 defer bh.Close() 4768 4769 verifiedRoles := make([]*verifiedRole, len(rp.Roles)) 4770 checkedPrivilegeTypes := make([]PrivilegeType, len(rp.Privileges)) 4771 4772 //put it into the single transaction 4773 err = bh.Exec(ctx, "begin;") 4774 defer func() { 4775 err = finishTxn(ctx, bh, err) 4776 }() 4777 if err != nil { 4778 return err 4779 } 4780 4781 //handle "IF EXISTS" 4782 //step 1: check roles. exists or not. 4783 for i, user := range rp.Roles { 4784 //check Revoke privilege on xxx yyy from moadmin(accountadmin) 4785 if account.IsNameOfAdminRoles(user.UserName) { 4786 return moerr.NewInternalError(ctx, "the privilege can not be revoked from the role %s", user.UserName) 4787 } 4788 sql, err = getSqlForRoleIdOfRole(ctx, user.UserName) 4789 if err != nil { 4790 return err 4791 } 4792 vr, err = verifyRoleFunc(ctx, bh, sql, user.UserName, roleType) 4793 if err != nil { 4794 return err 4795 } 4796 verifiedRoles[i] = vr 4797 if vr == nil { 4798 if !rp.IfExists { //when the "IF EXISTS" is set, just skip it. 4799 return moerr.NewInternalError(ctx, "there is no role %s", user.UserName) 4800 } 4801 } 4802 } 4803 4804 //get the object type 4805 objType, err = convertAstObjectTypeToObjectType(ctx, rp.ObjType) 4806 if err != nil { 4807 return err 4808 } 4809 4810 //check the privilege and the object type 4811 for i, priv := range rp.Privileges { 4812 privType, err = convertAstPrivilegeTypeToPrivilegeType(ctx, priv.Type, rp.ObjType) 4813 if err != nil { 4814 return err 4815 } 4816 //check the match between the privilegeScope and the objectType 4817 err = matchPrivilegeTypeWithObjectType(ctx, privType, objType) 4818 if err != nil { 4819 return err 4820 } 4821 checkedPrivilegeTypes[i] = privType 4822 } 4823 4824 //step 2: decide the object type , the object id and the privilege_level 4825 privLevel, objId, err = checkPrivilegeObjectTypeAndPrivilegeLevel(ctx, ses, bh, rp.ObjType, *rp.Level) 4826 if err != nil { 4827 return err 4828 } 4829 4830 //step 3: delete the granted privilege 4831 for _, privType = range checkedPrivilegeTypes { 4832 for _, role := range verifiedRoles { 4833 if role == nil { 4834 continue 4835 } 4836 if privType == PrivilegeTypeConnect && isPublicRole(role.name) { 4837 return moerr.NewInternalError(ctx, "the privilege %s can not be revoked from the role %s", privType, role.name) 4838 } 4839 sql = getSqlForDeleteRolePrivs(role.id, objType.String(), objId, int64(privType), privLevel.String()) 4840 bh.ClearExecResultSet() 4841 err = bh.Exec(ctx, sql) 4842 if err != nil { 4843 return err 4844 } 4845 } 4846 } 4847 return err 4848 } 4849 4850 // getDatabaseOrTableId gets the id of the database or the table 4851 func getDatabaseOrTableId(ctx context.Context, bh BackgroundExec, isDb bool, dbName, tableName string) (int64, error) { 4852 var err error 4853 var sql string 4854 var erArray []ExecResult 4855 var id int64 4856 if isDb { 4857 sql, err = getSqlForCheckDatabase(ctx, dbName) 4858 } else { 4859 sql, err = getSqlForCheckDatabaseTable(ctx, dbName, tableName) 4860 } 4861 if err != nil { 4862 return 0, err 4863 } 4864 bh.ClearExecResultSet() 4865 err = bh.Exec(ctx, sql) 4866 if err != nil { 4867 return 0, err 4868 } 4869 4870 erArray, err = getResultSet(ctx, bh) 4871 if err != nil { 4872 return 0, err 4873 } 4874 4875 if execResultArrayHasData(erArray) { 4876 id, err = erArray[0].GetInt64(ctx, 0, 0) 4877 if err != nil { 4878 return 0, err 4879 } 4880 return id, nil 4881 } 4882 if isDb { 4883 return 0, moerr.NewInternalError(ctx, `there is no database "%s"`, dbName) 4884 } else { 4885 //TODO: check the database exists or not first 4886 return 0, moerr.NewInternalError(ctx, `there is no table "%s" in database "%s"`, tableName, dbName) 4887 } 4888 } 4889 4890 // convertAstObjectTypeToObjectType gets the object type from the ast 4891 func convertAstObjectTypeToObjectType(ctx context.Context, ot tree.ObjectType) (objectType, error) { 4892 var objType objectType 4893 switch ot { 4894 case tree.OBJECT_TYPE_TABLE: 4895 objType = objectTypeTable 4896 case tree.OBJECT_TYPE_DATABASE: 4897 objType = objectTypeDatabase 4898 case tree.OBJECT_TYPE_ACCOUNT: 4899 objType = objectTypeAccount 4900 default: 4901 return 0, moerr.NewInternalError(ctx, `the object type "%s" is unsupported`, ot.String()) 4902 } 4903 return objType, nil 4904 } 4905 4906 // checkPrivilegeObjectTypeAndPrivilegeLevel checks the relationship among the privilege type, the object type and the privilege level. 4907 // it returns the converted object type, the privilege level and the object id. 4908 func checkPrivilegeObjectTypeAndPrivilegeLevel(ctx context.Context, ses FeSession, bh BackgroundExec, 4909 ot tree.ObjectType, pl tree.PrivilegeLevel) (privilegeLevelType, int64, error) { 4910 var privLevel privilegeLevelType 4911 var objId int64 4912 var err error 4913 var dbName string 4914 4915 switch ot { 4916 case tree.OBJECT_TYPE_TABLE: 4917 switch pl.Level { 4918 case tree.PRIVILEGE_LEVEL_TYPE_STAR: 4919 privLevel = privilegeLevelStar 4920 objId, err = getDatabaseOrTableId(ctx, bh, true, ses.GetDatabaseName(), "") 4921 if err != nil { 4922 return 0, 0, err 4923 } 4924 case tree.PRIVILEGE_LEVEL_TYPE_STAR_STAR: 4925 privLevel = privilegeLevelStarStar 4926 objId = objectIDAll 4927 case tree.PRIVILEGE_LEVEL_TYPE_DATABASE_STAR: 4928 privLevel = privilegeLevelDatabaseStar 4929 objId, err = getDatabaseOrTableId(ctx, bh, true, pl.DbName, "") 4930 if err != nil { 4931 return 0, 0, err 4932 } 4933 case tree.PRIVILEGE_LEVEL_TYPE_DATABASE_TABLE: 4934 privLevel = privilegeLevelDatabaseTable 4935 objId, err = getDatabaseOrTableId(ctx, bh, false, pl.DbName, pl.TabName) 4936 if err != nil { 4937 return 0, 0, err 4938 } 4939 case tree.PRIVILEGE_LEVEL_TYPE_TABLE: 4940 privLevel = privilegeLevelTable 4941 objId, err = getDatabaseOrTableId(ctx, bh, false, ses.GetDatabaseName(), pl.TabName) 4942 if err != nil { 4943 return 0, 0, err 4944 } 4945 default: 4946 err = moerr.NewInternalError(ctx, `in the object type "%s" the privilege level "%s" is unsupported`, ot.String(), pl.String()) 4947 return 0, 0, err 4948 } 4949 case tree.OBJECT_TYPE_DATABASE: 4950 switch pl.Level { 4951 case tree.PRIVILEGE_LEVEL_TYPE_STAR: 4952 privLevel = privilegeLevelStar 4953 objId = objectIDAll 4954 case tree.PRIVILEGE_LEVEL_TYPE_STAR_STAR: 4955 privLevel = privilegeLevelStarStar 4956 objId = objectIDAll 4957 case tree.PRIVILEGE_LEVEL_TYPE_TABLE: 4958 //in the syntax, we can not distinguish the table name from the database name. 4959 privLevel = privilegeLevelDatabase 4960 dbName = pl.TabName 4961 objId, err = getDatabaseOrTableId(ctx, bh, true, dbName, "") 4962 if err != nil { 4963 return 0, 0, err 4964 } 4965 case tree.PRIVILEGE_LEVEL_TYPE_DATABASE: 4966 privLevel = privilegeLevelDatabase 4967 dbName = pl.DbName 4968 objId, err = getDatabaseOrTableId(ctx, bh, true, dbName, "") 4969 if err != nil { 4970 return 0, 0, err 4971 } 4972 default: 4973 err = moerr.NewInternalError(ctx, `in the object type "%s" the privilege level "%s" is unsupported`, ot.String(), pl.String()) 4974 return 0, 0, err 4975 } 4976 case tree.OBJECT_TYPE_ACCOUNT: 4977 switch pl.Level { 4978 case tree.PRIVILEGE_LEVEL_TYPE_STAR: 4979 privLevel = privilegeLevelStar 4980 objId = objectIDAll 4981 default: 4982 err = moerr.NewInternalError(ctx, `in the object type "%s" the privilege level "%s" is unsupported`, ot.String(), pl.String()) 4983 return 0, 0, err 4984 } 4985 default: 4986 err = moerr.NewInternalError(ctx, `the object type "%s" is unsupported`, ot.String()) 4987 return 0, 0, err 4988 } 4989 4990 return privLevel, objId, err 4991 } 4992 4993 // matchPrivilegeTypeWithObjectType matches the privilege type with the object type 4994 func matchPrivilegeTypeWithObjectType(ctx context.Context, privType PrivilegeType, objType objectType) error { 4995 var err error 4996 switch privType.Scope() { 4997 case PrivilegeScopeSys, PrivilegeScopeAccount, PrivilegeScopeUser, PrivilegeScopeRole: 4998 if objType != objectTypeAccount { 4999 err = moerr.NewInternalError(ctx, `the privilege "%s" can only be granted to the object type "account"`, privType) 5000 } 5001 case PrivilegeScopeDatabase: 5002 if objType != objectTypeDatabase { 5003 err = moerr.NewInternalError(ctx, `the privilege "%s" can only be granted to the object type "database"`, privType) 5004 } 5005 case PrivilegeScopeTable: 5006 if objType != objectTypeTable { 5007 err = moerr.NewInternalError(ctx, `the privilege "%s" can only be granted to the object type "table"`, privType) 5008 } 5009 case PrivilegeScopeRoutine: 5010 if objType != objectTypeFunction { 5011 err = moerr.NewInternalError(ctx, `the privilege "%s" can only be granted to the object type "function"`, privType) 5012 } 5013 } 5014 return err 5015 } 5016 5017 // doGrantPrivilege accomplishes the GrantPrivilege statement 5018 func doGrantPrivilege(ctx context.Context, ses FeSession, gp *tree.GrantPrivilege) (err error) { 5019 var erArray []ExecResult 5020 var roleId int64 5021 var privType PrivilegeType 5022 var objType objectType 5023 var privLevel privilegeLevelType 5024 var objId int64 5025 var sql string 5026 var userId uint32 5027 5028 err = normalizeNamesOfRoles(ctx, gp.Roles) 5029 if err != nil { 5030 return err 5031 } 5032 5033 account := ses.GetTenantInfo() 5034 if account == nil { 5035 userId = defines.GetUserId(ctx) 5036 } else { 5037 userId = account.GetUserID() 5038 } 5039 5040 bh := ses.GetBackgroundExec(ctx) 5041 defer bh.Close() 5042 5043 //Get primary keys 5044 //step 1: get role_id 5045 verifiedRoles := make([]*verifiedRole, len(gp.Roles)) 5046 checkedPrivilegeTypes := make([]PrivilegeType, len(gp.Privileges)) 5047 5048 //put it into the single transaction 5049 err = bh.Exec(ctx, "begin;") 5050 defer func() { 5051 err = finishTxn(ctx, bh, err) 5052 }() 5053 if err != nil { 5054 return err 5055 } 5056 5057 for i, role := range gp.Roles { 5058 //check Grant privilege on xxx yyy to moadmin(accountadmin) 5059 if account != nil && account.IsNameOfAdminRoles(role.UserName) { 5060 return moerr.NewInternalError(ctx, "the privilege can not be granted to the role %s", role.UserName) 5061 } 5062 sql, err = getSqlForRoleIdOfRole(ctx, role.UserName) 5063 if err != nil { 5064 return err 5065 } 5066 bh.ClearExecResultSet() 5067 err = bh.Exec(ctx, sql) 5068 if err != nil { 5069 return err 5070 } 5071 5072 erArray, err = getResultSet(ctx, bh) 5073 if err != nil { 5074 return err 5075 } 5076 5077 if execResultArrayHasData(erArray) { 5078 for j := uint64(0); j < erArray[0].GetRowCount(); j++ { 5079 roleId, err = erArray[0].GetInt64(ctx, j, 0) 5080 if err != nil { 5081 return err 5082 } 5083 } 5084 } else { 5085 return moerr.NewInternalError(ctx, "there is no role %s", role.UserName) 5086 } 5087 verifiedRoles[i] = &verifiedRole{ 5088 typ: roleType, 5089 name: role.UserName, 5090 id: roleId, 5091 } 5092 } 5093 5094 //get the object type 5095 objType, err = convertAstObjectTypeToObjectType(ctx, gp.ObjType) 5096 if err != nil { 5097 return err 5098 } 5099 5100 //check the privilege and the object type 5101 for i, priv := range gp.Privileges { 5102 privType, err = convertAstPrivilegeTypeToPrivilegeType(ctx, priv.Type, gp.ObjType) 5103 if err != nil { 5104 return err 5105 } 5106 if isBannedPrivilege(privType) { 5107 return moerr.NewInternalError(ctx, "the privilege %s can not be granted", privType) 5108 } 5109 //check the match between the privilegeScope and the objectType 5110 err = matchPrivilegeTypeWithObjectType(ctx, privType, objType) 5111 if err != nil { 5112 return err 5113 } 5114 checkedPrivilegeTypes[i] = privType 5115 } 5116 5117 //step 2: get obj_type, privilege_level 5118 //step 3: get obj_id 5119 privLevel, objId, err = checkPrivilegeObjectTypeAndPrivilegeLevel(ctx, ses, bh, gp.ObjType, *gp.Level) 5120 if err != nil { 5121 return err 5122 } 5123 5124 //step 4: get privilege_id 5125 //step 5: check exists 5126 //step 6: update or insert 5127 5128 for _, privType = range checkedPrivilegeTypes { 5129 for _, role := range verifiedRoles { 5130 sql = getSqlForCheckRoleHasPrivilege(role.id, objType, objId, int64(privType)) 5131 //check exists 5132 bh.ClearExecResultSet() 5133 err = bh.Exec(ctx, sql) 5134 if err != nil { 5135 return err 5136 } 5137 5138 erArray, err = getResultSet(ctx, bh) 5139 if err != nil { 5140 return err 5141 } 5142 5143 //choice 1 : update the record 5144 //choice 2 : inset new record 5145 choice := 1 5146 if execResultArrayHasData(erArray) { 5147 for j := uint64(0); j < erArray[0].GetRowCount(); j++ { 5148 _, err = erArray[0].GetInt64(ctx, j, 0) 5149 if err != nil { 5150 return err 5151 } 5152 } 5153 } else { 5154 choice = 2 5155 } 5156 5157 if choice == 1 { //update the record 5158 sql = getSqlForUpdateRolePrivs(int64(userId), 5159 types.CurrentTimestamp().String2(time.UTC, 0), 5160 gp.GrantOption, role.id, objType, objId, int64(privType)) 5161 } else if choice == 2 { //insert new record 5162 sql = getSqlForInsertRolePrivs(role.id, role.name, objType.String(), objId, 5163 int64(privType), privType.String(), privLevel.String(), int64(userId), 5164 types.CurrentTimestamp().String2(time.UTC, 0), gp.GrantOption) 5165 } 5166 5167 //insert or update 5168 bh.ClearExecResultSet() 5169 err = bh.Exec(ctx, sql) 5170 if err != nil { 5171 return err 5172 } 5173 } 5174 } 5175 5176 return err 5177 } 5178 5179 // doRevokeRole accomplishes the RevokeRole statement 5180 func doRevokeRole(ctx context.Context, ses *Session, rr *tree.RevokeRole) (err error) { 5181 var sql string 5182 err = normalizeNamesOfRoles(ctx, rr.Roles) 5183 if err != nil { 5184 return err 5185 } 5186 err = normalizeNamesOfUsers(ctx, rr.Users) 5187 if err != nil { 5188 return err 5189 } 5190 5191 account := ses.GetTenantInfo() 5192 bh := ses.GetBackgroundExec(ctx) 5193 defer bh.Close() 5194 5195 //step1 : check Roles exists or not 5196 var vr *verifiedRole 5197 5198 verifiedFromRoles := make([]*verifiedRole, len(rr.Roles)) 5199 verifiedToRoles := make([]*verifiedRole, len(rr.Users)) 5200 5201 //put it into the single transaction 5202 err = bh.Exec(ctx, "begin;") 5203 defer func() { 5204 err = finishTxn(ctx, bh, err) 5205 }() 5206 if err != nil { 5207 return err 5208 } 5209 5210 //handle "IF EXISTS" 5211 //step1 : check Users are real Users or Roles, exists or not 5212 for i, user := range rr.Users { 5213 sql, err = getSqlForRoleIdOfRole(ctx, user.Username) 5214 if err != nil { 5215 return err 5216 } 5217 vr, err = verifyRoleFunc(ctx, bh, sql, user.Username, roleType) 5218 if err != nil { 5219 return err 5220 } 5221 if vr != nil { 5222 verifiedToRoles[i] = vr 5223 } else { 5224 //check user 5225 sql, err = getSqlForPasswordOfUser(ctx, user.Username) 5226 if err != nil { 5227 return err 5228 } 5229 vr, err = verifyRoleFunc(ctx, bh, sql, user.Username, userType) 5230 if err != nil { 5231 return err 5232 } 5233 verifiedToRoles[i] = vr 5234 if vr == nil { 5235 if !rr.IfExists { //when the "IF EXISTS" is set, just skip the check 5236 return moerr.NewInternalError(ctx, "there is no role or user %s", user.Username) 5237 } 5238 } 5239 } 5240 } 5241 5242 //handle "IF EXISTS" 5243 //step2 : check roles before the FROM clause 5244 for i, role := range rr.Roles { 5245 sql, err = getSqlForRoleIdOfRole(ctx, role.UserName) 5246 if err != nil { 5247 return err 5248 } 5249 vr, err = verifyRoleFunc(ctx, bh, sql, role.UserName, roleType) 5250 if err != nil { 5251 return err 5252 } 5253 if vr == nil { 5254 return moerr.NewInternalError(ctx, "there is no role %s", role.UserName) 5255 } 5256 verifiedFromRoles[i] = vr 5257 } 5258 5259 //step3 : process Revoke role from role 5260 //step4 : process Revoke role from user 5261 for _, from := range verifiedFromRoles { 5262 for _, to := range verifiedToRoles { 5263 if to == nil { //Under "IF EXISTS" 5264 continue 5265 } 5266 if account.IsNameOfAdminRoles(from.name) { 5267 //check Revoke moadmin from root,dump,userX 5268 //check Revoke accountadmin from root,dump,userX 5269 //check Revoke moadmin(accountadmin) from roleX 5270 return moerr.NewInternalError(ctx, "the role %s can not be revoked", from.name) 5271 } else if isPublicRole(from.name) { 5272 return moerr.NewInternalError(ctx, "the role %s can not be revoked", from.name) 5273 } 5274 5275 if to.typ == roleType { 5276 //check Revoke roleX from moadmin(accountadmin) 5277 if account.IsNameOfAdminRoles(to.name) { 5278 return moerr.NewInternalError(ctx, "the role %s can not be revoked from the role %s", from.name, to.name) 5279 } else if isPublicRole(to.name) { 5280 //check Revoke roleX from public 5281 return moerr.NewInternalError(ctx, "the role %s can not be revoked from the role %s", from.name, to.name) 5282 } 5283 } 5284 5285 if to.typ == roleType { 5286 //revoke from role 5287 //delete (granted_id,grantee_id) from the mo_role_grant 5288 sql = getSqlForDeleteRoleGrant(from.id, to.id) 5289 } else { 5290 //revoke from user 5291 //delete (roleId,userId) from the mo_user_grant 5292 sql = getSqlForDeleteUserGrant(from.id, to.id) 5293 } 5294 err = bh.Exec(ctx, sql) 5295 if err != nil { 5296 return err 5297 } 5298 } 5299 } 5300 5301 return err 5302 } 5303 5304 // verifySpecialRolesInGrant verifies the special roles in the Grant statement 5305 func verifySpecialRolesInGrant(ctx context.Context, account *TenantInfo, from, to *verifiedRole) error { 5306 if account.IsNameOfAdminRoles(from.name) { 5307 if to.typ == userType { 5308 //check Grant moadmin to root,dump 5309 //check Grant accountadmin to admin_name 5310 //check Grant moadmin to userX 5311 //check Grant accountadmin to userX 5312 if !to.userIsAdmin { 5313 return moerr.NewInternalError(ctx, "the role %s can not be granted to non administration user %s", from.name, to.name) 5314 } 5315 } else { 5316 //check Grant moadmin(accountadmin) to roleX 5317 if !account.IsNameOfAdminRoles(to.name) { 5318 return moerr.NewInternalError(ctx, "the role %s can not be granted to the other role %s", from.name, to.name) 5319 } 5320 } 5321 } else if isPublicRole(from.name) && to.typ == roleType { 5322 return moerr.NewInternalError(ctx, "the role %s can not be granted to the other role %s", from.name, to.name) 5323 } 5324 5325 if to.typ == roleType { 5326 //check Grant roleX to moadmin(accountadmin) 5327 if account.IsNameOfAdminRoles(to.name) { 5328 return moerr.NewInternalError(ctx, "the role %s can not be granted to the role %s", from.name, to.name) 5329 } else if isPublicRole(to.name) { 5330 //check Grant roleX to public 5331 return moerr.NewInternalError(ctx, "the role %s can not be granted to the role %s", from.name, to.name) 5332 } 5333 } 5334 return nil 5335 } 5336 5337 // doGrantRole accomplishes the GrantRole statement 5338 func doGrantRole(ctx context.Context, ses *Session, gr *tree.GrantRole) (err error) { 5339 var erArray []ExecResult 5340 var withGrantOption int64 5341 var sql string 5342 err = normalizeNamesOfRoles(ctx, gr.Roles) 5343 if err != nil { 5344 return err 5345 } 5346 err = normalizeNamesOfUsers(ctx, gr.Users) 5347 if err != nil { 5348 return err 5349 } 5350 5351 account := ses.GetTenantInfo() 5352 bh := ses.GetBackgroundExec(ctx) 5353 defer bh.Close() 5354 5355 //step1 : check Roles exists or not 5356 var vr *verifiedRole 5357 var needLoadMoRoleGrant bool 5358 var grantedId, granteeId int64 5359 var useIsAdmin bool 5360 5361 verifiedFromRoles := make([]*verifiedRole, len(gr.Roles)) 5362 verifiedToRoles := make([]*verifiedRole, len(gr.Users)) 5363 5364 //load mo_role_grant into memory for 5365 checkLoopGraph := NewGraph() 5366 5367 //put it into the single transaction 5368 err = bh.Exec(ctx, "begin;") 5369 defer func() { 5370 err = finishTxn(ctx, bh, err) 5371 }() 5372 if err != nil { 5373 return err 5374 } 5375 5376 for i, role := range gr.Roles { 5377 sql, err = getSqlForRoleIdOfRole(ctx, role.UserName) 5378 if err != nil { 5379 return err 5380 } 5381 vr, err = verifyRoleFunc(ctx, bh, sql, role.UserName, roleType) 5382 if err != nil { 5383 return err 5384 } 5385 if vr == nil { 5386 return moerr.NewInternalError(ctx, "there is no role %s", role.UserName) 5387 } 5388 verifiedFromRoles[i] = vr 5389 } 5390 5391 //step2 : check Users are real Users or Roles, exists or not 5392 for i, user := range gr.Users { 5393 sql, err = getSqlForRoleIdOfRole(ctx, user.Username) 5394 if err != nil { 5395 return err 5396 } 5397 vr, err = verifyRoleFunc(ctx, bh, sql, user.Username, roleType) 5398 if err != nil { 5399 return err 5400 } 5401 if vr != nil { 5402 verifiedToRoles[i] = vr 5403 } else { 5404 //check user exists or not 5405 sql, err = getSqlForPasswordOfUser(ctx, user.Username) 5406 if err != nil { 5407 return err 5408 } 5409 vr, err = verifyRoleFunc(ctx, bh, sql, user.Username, userType) 5410 if err != nil { 5411 return err 5412 } 5413 if vr == nil { 5414 return moerr.NewInternalError(ctx, "there is no role or user %s", user.Username) 5415 } 5416 verifiedToRoles[i] = vr 5417 5418 //the user is the administrator or not 5419 useIsAdmin, err = userIsAdministrator(ctx, bh, vr.id, account) 5420 if err != nil { 5421 return err 5422 } 5423 verifiedToRoles[i].userIsAdmin = useIsAdmin 5424 } 5425 } 5426 5427 //If there is at least one role in the verifiedToRoles, 5428 //it is necessary to load the mo_role_grant 5429 for _, role := range verifiedToRoles { 5430 if role.typ == roleType { 5431 needLoadMoRoleGrant = true 5432 break 5433 } 5434 } 5435 5436 if needLoadMoRoleGrant { 5437 //load mo_role_grant 5438 sql = getSqlForGetAllStuffRoleGrantFormat() 5439 bh.ClearExecResultSet() 5440 err = bh.Exec(ctx, sql) 5441 if err != nil { 5442 return err 5443 } 5444 5445 erArray, err = getResultSet(ctx, bh) 5446 if err != nil { 5447 return err 5448 } 5449 5450 if execResultArrayHasData(erArray) { 5451 for j := uint64(0); j < erArray[0].GetRowCount(); j++ { 5452 //column grantedId 5453 grantedId, err = erArray[0].GetInt64(ctx, j, 0) 5454 if err != nil { 5455 return err 5456 } 5457 5458 //column granteeId 5459 granteeId, err = erArray[0].GetInt64(ctx, j, 1) 5460 if err != nil { 5461 return err 5462 } 5463 5464 checkLoopGraph.addEdge(grantedId, granteeId) 5465 } 5466 } 5467 } 5468 5469 //step3 : process Grant role to role 5470 //step4 : process Grant role to user 5471 5472 for _, from := range verifiedFromRoles { 5473 for _, to := range verifiedToRoles { 5474 err = verifySpecialRolesInGrant(ctx, account, from, to) 5475 if err != nil { 5476 return err 5477 } 5478 5479 if to.typ == roleType { 5480 if from.id == to.id { //direct loop 5481 return moerr.NewRoleGrantedToSelf(ctx, from.name, to.name) 5482 } else { 5483 //check the indirect loop 5484 edgeId := checkLoopGraph.addEdge(from.id, to.id) 5485 has := checkLoopGraph.hasLoop(from.id) 5486 if has { 5487 return moerr.NewRoleGrantedToSelf(ctx, from.name, to.name) 5488 } 5489 //restore the graph 5490 checkLoopGraph.removeEdge(edgeId) 5491 } 5492 5493 //grant to role 5494 //get (granted_id,grantee_id,with_grant_option) from the mo_role_grant 5495 sql = getSqlForCheckRoleGrant(from.id, to.id) 5496 } else { 5497 //grant to user 5498 //get (roleId,userId,with_grant_option) from the mo_user_grant 5499 sql = getSqlForCheckUserGrant(from.id, to.id) 5500 } 5501 bh.ClearExecResultSet() 5502 err = bh.Exec(ctx, sql) 5503 if err != nil { 5504 return err 5505 } 5506 5507 erArray, err = getResultSet(ctx, bh) 5508 if err != nil { 5509 return err 5510 } 5511 5512 //For Grant role to role 5513 //choice 1: (granted_id,grantee_id) exists and with_grant_option is same. 5514 // Do nothing. 5515 //choice 2: (granted_id,grantee_id) exists and with_grant_option is different. 5516 // Update. 5517 //choice 3: (granted_id,grantee_id) does not exist. 5518 // Insert. 5519 5520 //For Grant role to user 5521 //choice 1: (roleId,userId) exists and with_grant_option is same. 5522 // Do nothing. 5523 //choice 2: (roleId,userId) exists and with_grant_option is different. 5524 // Update. 5525 //choice 3: (roleId,userId) does not exist. 5526 // Insert. 5527 choice := 1 5528 if execResultArrayHasData(erArray) { 5529 for j := uint64(0); j < erArray[0].GetRowCount(); j++ { 5530 withGrantOption, err = erArray[0].GetInt64(ctx, j, 2) 5531 if err != nil { 5532 return err 5533 } 5534 if (withGrantOption == 1) != gr.GrantOption { 5535 choice = 2 5536 } 5537 } 5538 } else { 5539 choice = 3 5540 } 5541 5542 sql = "" 5543 if choice == 2 { 5544 //update grant time 5545 if to.typ == roleType { 5546 sql = getSqlForUpdateRoleGrant(from.id, to.id, int64(account.GetDefaultRoleID()), int64(account.GetUserID()), types.CurrentTimestamp().String2(time.UTC, 0), gr.GrantOption) 5547 } else { 5548 sql = getSqlForUpdateUserGrant(from.id, to.id, types.CurrentTimestamp().String2(time.UTC, 0), gr.GrantOption) 5549 } 5550 } else if choice == 3 { 5551 //insert new record 5552 if to.typ == roleType { 5553 sql = getSqlForInsertRoleGrant(from.id, to.id, int64(account.GetDefaultRoleID()), int64(account.GetUserID()), types.CurrentTimestamp().String2(time.UTC, 0), gr.GrantOption) 5554 } else { 5555 sql = getSqlForInsertUserGrant(from.id, to.id, types.CurrentTimestamp().String2(time.UTC, 0), gr.GrantOption) 5556 } 5557 } 5558 5559 if choice != 1 { 5560 err = bh.Exec(ctx, sql) 5561 if err != nil { 5562 return err 5563 } 5564 } 5565 } 5566 } 5567 5568 return err 5569 } 5570 5571 // determinePrivilegeSetOfStatement decides the privileges that the statement needs before running it. 5572 // That is the Set P for the privilege Set . 5573 func determinePrivilegeSetOfStatement(stmt tree.Statement) *privilege { 5574 typs := make([]PrivilegeType, 0, 5) 5575 kind := privilegeKindGeneral 5576 special := specialTagNone 5577 objType := objectTypeAccount 5578 canExecInRestricted := false 5579 var extraEntries []privilegeEntry 5580 writeDatabaseAndTableDirectly := false 5581 var clusterTable bool 5582 var clusterTableOperation clusterTableOperationType 5583 dbName := "" 5584 switch st := stmt.(type) { 5585 case *tree.CreateAccount: 5586 typs = append(typs, PrivilegeTypeCreateAccount) 5587 case *tree.DropAccount: 5588 typs = append(typs, PrivilegeTypeDropAccount) 5589 case *tree.AlterAccount: 5590 typs = append(typs, PrivilegeTypeAlterAccount) 5591 case *tree.UpgradeStatement: 5592 typs = append(typs, PrivilegeTypeUpgradeAccount) 5593 objType = objectTypeNone 5594 kind = privilegeKindSpecial 5595 special = specialTagAdmin 5596 canExecInRestricted = true 5597 case *tree.CreateUser: 5598 if st.Role == nil { 5599 typs = append(typs, PrivilegeTypeCreateUser, PrivilegeTypeAccountAll /*, PrivilegeTypeAccountOwnership*/) 5600 } else { 5601 typs = append(typs, PrivilegeTypeAccountAll /*, PrivilegeTypeAccountOwnership*/) 5602 me1 := &compoundEntry{ 5603 items: []privilegeItem{ 5604 {privilegeTyp: PrivilegeTypeCreateUser}, 5605 {privilegeTyp: PrivilegeTypeManageGrants}, 5606 }, 5607 } 5608 me2 := &compoundEntry{ 5609 items: []privilegeItem{ 5610 {privilegeTyp: PrivilegeTypeCreateUser}, 5611 {privilegeTyp: PrivilegeTypeCanGrantRoleToOthersInCreateUser, role: st.Role, users: st.Users}, 5612 }, 5613 } 5614 5615 entry1 := privilegeEntry{ 5616 privilegeEntryTyp: privilegeEntryTypeCompound, 5617 compound: me1, 5618 } 5619 entry2 := privilegeEntry{ 5620 privilegeEntryTyp: privilegeEntryTypeCompound, 5621 compound: me2, 5622 } 5623 extraEntries = append(extraEntries, entry1, entry2) 5624 } 5625 case *tree.DropUser: 5626 typs = append(typs, PrivilegeTypeDropUser, PrivilegeTypeAccountAll /*, PrivilegeTypeAccountOwnership, PrivilegeTypeUserOwnership*/) 5627 case *tree.AlterUser: 5628 typs = append(typs, PrivilegeTypeAlterUser, PrivilegeTypeAccountAll /*, PrivilegeTypeAccountOwnership, PrivilegeTypeUserOwnership*/) 5629 case *tree.CreateRole: 5630 typs = append(typs, PrivilegeTypeCreateRole, PrivilegeTypeAccountAll /*, PrivilegeTypeAccountOwnership*/) 5631 case *tree.DropRole: 5632 typs = append(typs, PrivilegeTypeDropRole, PrivilegeTypeAccountAll /*, PrivilegeTypeAccountOwnership, PrivilegeTypeRoleOwnership*/) 5633 case *tree.Grant: 5634 if st.Typ == tree.GrantTypeRole { 5635 kind = privilegeKindInherit 5636 typs = append(typs, PrivilegeTypeManageGrants, PrivilegeTypeAccountAll /*, PrivilegeTypeAccountOwnership, PrivilegeTypeRoleOwnership*/) 5637 } else if st.Typ == tree.GrantTypePrivilege { 5638 objType = objectTypeNone 5639 kind = privilegeKindSpecial 5640 special = specialTagAdmin | specialTagWithGrantOption | specialTagOwnerOfObject 5641 } 5642 case *tree.GrantRole: 5643 kind = privilegeKindInherit 5644 typs = append(typs, PrivilegeTypeManageGrants, PrivilegeTypeAccountAll /*, PrivilegeTypeAccountOwnership, PrivilegeTypeRoleOwnership*/) 5645 case *tree.GrantPrivilege: 5646 objType = objectTypeNone 5647 kind = privilegeKindSpecial 5648 special = specialTagAdmin | specialTagWithGrantOption | specialTagOwnerOfObject 5649 case *tree.Revoke: 5650 if st.Typ == tree.RevokeTypeRole { 5651 typs = append(typs, PrivilegeTypeManageGrants, PrivilegeTypeAccountAll /*, PrivilegeTypeAccountOwnership, PrivilegeTypeRoleOwnership*/) 5652 } else if st.Typ == tree.RevokeTypePrivilege { 5653 objType = objectTypeNone 5654 kind = privilegeKindSpecial 5655 special = specialTagAdmin 5656 } 5657 case *tree.RevokeRole: 5658 typs = append(typs, PrivilegeTypeManageGrants, PrivilegeTypeAccountAll /*, PrivilegeTypeAccountOwnership, PrivilegeTypeRoleOwnership*/) 5659 case *tree.RevokePrivilege: 5660 objType = objectTypeNone 5661 kind = privilegeKindSpecial 5662 special = specialTagAdmin 5663 case *tree.CreateDatabase: 5664 typs = append(typs, PrivilegeTypeCreateDatabase, PrivilegeTypeAccountAll /*, PrivilegeTypeAccountOwnership*/) 5665 case *tree.DropDatabase: 5666 typs = append(typs, PrivilegeTypeDropDatabase, PrivilegeTypeAccountAll /*, PrivilegeTypeAccountOwnership*/) 5667 writeDatabaseAndTableDirectly = true 5668 dbName = string(st.Name) 5669 case *tree.ShowDatabases: 5670 typs = append(typs, PrivilegeTypeShowDatabases, PrivilegeTypeAccountAll /*, PrivilegeTypeAccountOwnership*/) 5671 canExecInRestricted = true 5672 case *tree.ShowSequences: 5673 typs = append(typs, PrivilegeTypeAccountAll, PrivilegeTypeDatabaseOwnership) 5674 canExecInRestricted = true 5675 case *tree.Use: 5676 typs = append(typs, PrivilegeTypeConnect, PrivilegeTypeAccountAll /*, PrivilegeTypeAccountOwnership*/) 5677 canExecInRestricted = true 5678 case *tree.ShowTables, *tree.ShowCreateTable, *tree.ShowColumns, *tree.ShowCreateView, *tree.ShowCreateDatabase, 5679 *tree.ShowCreatePublications: 5680 objType = objectTypeDatabase 5681 typs = append(typs, PrivilegeTypeShowTables, PrivilegeTypeDatabaseAll, PrivilegeTypeDatabaseOwnership) 5682 canExecInRestricted = true 5683 case *tree.CreateTable: 5684 objType = objectTypeDatabase 5685 typs = append(typs, PrivilegeTypeCreateTable, PrivilegeTypeDatabaseAll, PrivilegeTypeDatabaseOwnership) 5686 writeDatabaseAndTableDirectly = true 5687 if st.IsClusterTable { 5688 clusterTable = true 5689 clusterTableOperation = clusterTableCreate 5690 } 5691 dbName = string(st.Table.SchemaName) 5692 case *tree.CreateView: 5693 objType = objectTypeDatabase 5694 typs = append(typs, PrivilegeTypeCreateView, PrivilegeTypeDatabaseAll, PrivilegeTypeDatabaseOwnership) 5695 writeDatabaseAndTableDirectly = true 5696 if st.Name != nil { 5697 dbName = string(st.Name.SchemaName) 5698 } 5699 case *tree.CreateSource: 5700 objType = objectTypeDatabase 5701 typs = append(typs, PrivilegeTypeCreateView, PrivilegeTypeDatabaseAll, PrivilegeTypeDatabaseOwnership) 5702 writeDatabaseAndTableDirectly = true 5703 if st.SourceName != nil { 5704 dbName = string(st.SourceName.SchemaName) 5705 } 5706 case *tree.CreateConnector: 5707 objType = objectTypeDatabase 5708 typs = append(typs, PrivilegeTypeCreateView, PrivilegeTypeDatabaseAll, PrivilegeTypeDatabaseOwnership) 5709 writeDatabaseAndTableDirectly = true 5710 if st.TableName != nil { 5711 dbName = string(st.TableName.SchemaName) 5712 } 5713 case *tree.CreateSequence: 5714 objType = objectTypeDatabase 5715 typs = append(typs, PrivilegeTypeDatabaseAll, PrivilegeTypeDatabaseOwnership) 5716 writeDatabaseAndTableDirectly = true 5717 if st.Name != nil { 5718 dbName = string(st.Name.SchemaName) 5719 } 5720 case *tree.AlterSequence: 5721 objType = objectTypeDatabase 5722 typs = append(typs, PrivilegeTypeDatabaseAll, PrivilegeTypeDatabaseOwnership) 5723 writeDatabaseAndTableDirectly = true 5724 if st.Name != nil { 5725 dbName = string(st.Name.SchemaName) 5726 } 5727 case *tree.AlterView: 5728 objType = objectTypeDatabase 5729 typs = append(typs, PrivilegeTypeAlterView, PrivilegeTypeDatabaseAll, PrivilegeTypeDatabaseOwnership) 5730 writeDatabaseAndTableDirectly = true 5731 if st.Name != nil { 5732 dbName = string(st.Name.SchemaName) 5733 } 5734 case *tree.AlterDataBaseConfig: 5735 objType = objectTypeNone 5736 kind = privilegeKindNone 5737 case *tree.CreateFunction: 5738 objType = objectTypeDatabase 5739 typs = append(typs, PrivilegeTypeCreateView, PrivilegeTypeDatabaseAll, PrivilegeTypeDatabaseOwnership) 5740 writeDatabaseAndTableDirectly = true 5741 5742 case *tree.AlterTable: 5743 objType = objectTypeDatabase 5744 typs = append(typs, PrivilegeTypeAlterTable, PrivilegeTypeDatabaseAll, PrivilegeTypeDatabaseOwnership) 5745 writeDatabaseAndTableDirectly = true 5746 if st.Table != nil { 5747 dbName = string(st.Table.SchemaName) 5748 } 5749 case *tree.CreateProcedure: 5750 objType = objectTypeDatabase 5751 typs = append(typs, PrivilegeTypeCreateView, PrivilegeTypeDatabaseAll, PrivilegeTypeDatabaseOwnership) 5752 writeDatabaseAndTableDirectly = true 5753 case *tree.CallStmt: // TODO: redesign privilege for calling a procedure 5754 objType = objectTypeDatabase 5755 typs = append(typs, PrivilegeTypeCreateView, PrivilegeTypeDatabaseAll, PrivilegeTypeDatabaseOwnership) 5756 writeDatabaseAndTableDirectly = true 5757 case *tree.DropTable: 5758 objType = objectTypeDatabase 5759 typs = append(typs, PrivilegeTypeDropTable, PrivilegeTypeDropObject, PrivilegeTypeDatabaseAll, PrivilegeTypeDatabaseOwnership) 5760 writeDatabaseAndTableDirectly = true 5761 if len(st.Names) != 0 { 5762 dbName = string(st.Names[0].SchemaName) 5763 } 5764 case *tree.DropView: 5765 objType = objectTypeDatabase 5766 typs = append(typs, PrivilegeTypeDropView, PrivilegeTypeDropObject, PrivilegeTypeDatabaseAll, PrivilegeTypeDatabaseOwnership) 5767 writeDatabaseAndTableDirectly = true 5768 if len(st.Names) != 0 { 5769 dbName = string(st.Names[0].SchemaName) 5770 } 5771 case *tree.DropSequence: 5772 objType = objectTypeDatabase 5773 typs = append(typs, PrivilegeTypeDropObject, PrivilegeTypeDatabaseAll, PrivilegeTypeDatabaseOwnership) 5774 writeDatabaseAndTableDirectly = true 5775 if len(st.Names) != 0 { 5776 dbName = string(st.Names[0].SchemaName) 5777 } 5778 case *tree.DropFunction: 5779 objType = objectTypeDatabase 5780 typs = append(typs, PrivilegeTypeCreateView, PrivilegeTypeDatabaseAll, PrivilegeTypeDatabaseOwnership) 5781 writeDatabaseAndTableDirectly = true 5782 case *tree.DropProcedure: 5783 objType = objectTypeDatabase 5784 typs = append(typs, PrivilegeTypeCreateView, PrivilegeTypeDatabaseAll, PrivilegeTypeDatabaseOwnership) 5785 writeDatabaseAndTableDirectly = true 5786 case *tree.Select: 5787 objType = objectTypeTable 5788 typs = append(typs, PrivilegeTypeSelect, PrivilegeTypeTableAll, PrivilegeTypeTableOwnership) 5789 canExecInRestricted = true 5790 case *tree.Do: 5791 objType = objectTypeTable 5792 typs = append(typs, PrivilegeTypeSelect, PrivilegeTypeTableAll, PrivilegeTypeTableOwnership) 5793 case *tree.Insert: 5794 objType = objectTypeTable 5795 typs = append(typs, PrivilegeTypeInsert, PrivilegeTypeTableAll, PrivilegeTypeTableOwnership) 5796 writeDatabaseAndTableDirectly = true 5797 case *tree.Replace: 5798 objType = objectTypeTable 5799 typs = append(typs, PrivilegeTypeTableAll, PrivilegeTypeTableOwnership) 5800 entry1 := privilegeEntry{ 5801 privilegeEntryTyp: privilegeEntryTypeCompound, 5802 compound: &compoundEntry{ 5803 items: []privilegeItem{ 5804 {privilegeTyp: PrivilegeTypeInsert}, 5805 {privilegeTyp: PrivilegeTypeDelete}, 5806 }, 5807 }, 5808 } 5809 5810 extraEntries = append(extraEntries, entry1) 5811 writeDatabaseAndTableDirectly = true 5812 case *tree.Load: 5813 objType = objectTypeTable 5814 typs = append(typs, PrivilegeTypeInsert, PrivilegeTypeTableAll, PrivilegeTypeTableOwnership) 5815 writeDatabaseAndTableDirectly = true 5816 if st.Table != nil { 5817 dbName = string(st.Table.SchemaName) 5818 } 5819 case *tree.Update: 5820 objType = objectTypeTable 5821 typs = append(typs, PrivilegeTypeUpdate, PrivilegeTypeTableAll, PrivilegeTypeTableOwnership) 5822 writeDatabaseAndTableDirectly = true 5823 case *tree.Delete: 5824 objType = objectTypeTable 5825 typs = append(typs, PrivilegeTypeDelete, PrivilegeTypeTableAll, PrivilegeTypeTableOwnership) 5826 writeDatabaseAndTableDirectly = true 5827 canExecInRestricted = true 5828 case *tree.CreateIndex: 5829 objType = objectTypeTable 5830 typs = append(typs, PrivilegeTypeIndex, PrivilegeTypeTableAll, PrivilegeTypeTableOwnership) 5831 writeDatabaseAndTableDirectly = true 5832 if st.Table != nil { 5833 dbName = string(st.Table.SchemaName) 5834 } 5835 case *tree.DropIndex: 5836 objType = objectTypeTable 5837 typs = append(typs, PrivilegeTypeIndex, PrivilegeTypeTableAll, PrivilegeTypeTableOwnership) 5838 writeDatabaseAndTableDirectly = true 5839 if st.TableName != nil { 5840 dbName = string(st.TableName.SchemaName) 5841 } 5842 case *tree.ShowProcessList, *tree.ShowErrors, *tree.ShowWarnings, *tree.ShowVariables, 5843 *tree.ShowStatus, *tree.ShowTarget, *tree.ShowTableStatus, 5844 *tree.ShowGrants, *tree.ShowCollation, *tree.ShowIndex, 5845 *tree.ShowTableNumber, *tree.ShowColumnNumber, 5846 *tree.ShowTableValues, *tree.ShowNodeList, *tree.ShowRolesStmt, 5847 *tree.ShowLocks, *tree.ShowFunctionOrProcedureStatus, *tree.ShowPublications, *tree.ShowSubscriptions, 5848 *tree.ShowBackendServers, *tree.ShowStages, *tree.ShowConnectors, *tree.DropConnector, 5849 *tree.PauseDaemonTask, *tree.CancelDaemonTask, *tree.ResumeDaemonTask: 5850 objType = objectTypeNone 5851 kind = privilegeKindNone 5852 canExecInRestricted = true 5853 case *tree.ShowAccounts: 5854 objType = objectTypeNone 5855 kind = privilegeKindSpecial 5856 special = specialTagAdmin 5857 canExecInRestricted = true 5858 case *tree.ShowAccountUpgrade: 5859 objType = objectTypeNone 5860 kind = privilegeKindSpecial 5861 special = specialTagAdmin 5862 canExecInRestricted = true 5863 case *tree.ExplainFor, *tree.ExplainAnalyze, *tree.ExplainStmt: 5864 objType = objectTypeNone 5865 kind = privilegeKindNone 5866 case *tree.BeginTransaction, *tree.CommitTransaction, *tree.RollbackTransaction: 5867 objType = objectTypeNone 5868 kind = privilegeKindNone 5869 case *tree.SetVar: 5870 objType = objectTypeNone 5871 kind = privilegeKindNone 5872 canExecInRestricted = true 5873 case *tree.SetDefaultRole, *tree.SetRole, *tree.SetPassword: 5874 objType = objectTypeNone 5875 kind = privilegeKindNone 5876 case *tree.PrepareStmt, *tree.PrepareString, *tree.Deallocate, *tree.Reset: 5877 objType = objectTypeNone 5878 kind = privilegeKindNone 5879 case *tree.Execute: 5880 objType = objectTypeNone 5881 kind = privilegeKindNone 5882 case *tree.Declare: 5883 objType = objectTypeNone 5884 kind = privilegeKindNone 5885 case *InternalCmdFieldList: 5886 objType = objectTypeNone 5887 kind = privilegeKindNone 5888 case *tree.ValuesStatement: 5889 objType = objectTypeTable 5890 typs = append(typs, PrivilegeTypeValues, PrivilegeTypeTableAll, PrivilegeTypeTableOwnership) 5891 case *tree.ShowSnapShots: 5892 typs = append(typs, PrivilegeTypeAccountAll) 5893 objType = objectTypeDatabase 5894 kind = privilegeKindNone 5895 case *tree.CreateSnapShot, *tree.DropSnapShot: 5896 typs = append(typs, PrivilegeTypeAccountAll) 5897 objType = objectTypeDatabase 5898 kind = privilegeKindNone 5899 case *tree.RestoreSnapShot: 5900 typs = append(typs, PrivilegeTypeAccountAll) 5901 objType = objectTypeDatabase 5902 kind = privilegeKindNone 5903 case *tree.TruncateTable: 5904 objType = objectTypeTable 5905 typs = append(typs, PrivilegeTypeTruncate, PrivilegeTypeTableAll, PrivilegeTypeTableOwnership) 5906 writeDatabaseAndTableDirectly = true 5907 if st.Name != nil { 5908 dbName = string(st.Name.SchemaName) 5909 } 5910 case *tree.MoDump: 5911 objType = objectTypeTable 5912 typs = append(typs, PrivilegeTypeSelect, PrivilegeTypeTableAll, PrivilegeTypeTableOwnership) 5913 case *tree.Kill: 5914 objType = objectTypeNone 5915 kind = privilegeKindNone 5916 case *tree.LockTableStmt, *tree.UnLockTableStmt: 5917 objType = objectTypeNone 5918 kind = privilegeKindNone 5919 case *tree.CreatePublication, *tree.DropPublication, *tree.AlterPublication: 5920 typs = append(typs, PrivilegeTypeAccountAll) 5921 objType = objectTypeDatabase 5922 kind = privilegeKindNone 5923 case *tree.SetTransaction: 5924 objType = objectTypeNone 5925 kind = privilegeKindNone 5926 case *tree.CreateStage, *tree.AlterStage, *tree.DropStage: 5927 objType = objectTypeNone 5928 kind = privilegeKindNone 5929 case *tree.BackupStart: 5930 objType = objectTypeNone 5931 kind = privilegeKindSpecial 5932 special = specialTagAdmin 5933 case *tree.EmptyStmt: 5934 objType = objectTypeNone 5935 kind = privilegeKindNone 5936 default: 5937 panic(fmt.Sprintf("does not have the privilege definition of the statement %s", stmt)) 5938 } 5939 5940 entries := make([]privilegeEntry, len(typs)) 5941 for i, typ := range typs { 5942 entries[i] = privilegeEntriesMap[typ] 5943 entries[i].databaseName = dbName 5944 } 5945 entries = append(entries, extraEntries...) 5946 return &privilege{ 5947 kind: kind, 5948 objType: objType, 5949 entries: entries, 5950 special: special, 5951 writeDatabaseAndTableDirectly: writeDatabaseAndTableDirectly, 5952 isClusterTable: clusterTable, 5953 clusterTableOperation: clusterTableOperation, 5954 canExecInRestricted: canExecInRestricted, 5955 } 5956 } 5957 5958 // privilege will be done on the table 5959 type privilegeTips struct { 5960 typ PrivilegeType 5961 databaseName string 5962 tableName string 5963 isClusterTable bool 5964 clusterTableOperation clusterTableOperationType 5965 } 5966 5967 type privilegeTipsArray []privilegeTips 5968 5969 func (pot privilegeTips) String() string { 5970 return fmt.Sprintf("%s %s %s", pot.typ, pot.databaseName, pot.tableName) 5971 } 5972 5973 func (pota privilegeTipsArray) String() string { 5974 b := strings.Builder{} 5975 for _, table := range pota { 5976 b.WriteString(table.String()) 5977 b.WriteString("\n") 5978 } 5979 return b.String() 5980 } 5981 5982 // extractPrivilegeTipsFromPlan extracts the privilege tips from the plan 5983 func extractPrivilegeTipsFromPlan(p *plan2.Plan) privilegeTipsArray { 5984 //NOTE: the pts may be nil when the plan does operate any table. 5985 var pts privilegeTipsArray 5986 appendPt := func(pt privilegeTips) { 5987 pts = append(pts, pt) 5988 } 5989 if p.GetQuery() != nil { //select,insert select, update, delete 5990 q := p.GetQuery() 5991 5992 // lastNode := q.Nodes[len(q.Nodes)-1] 5993 var t PrivilegeType 5994 var clusterTable bool 5995 var clusterTableOperation clusterTableOperationType 5996 5997 switch q.StmtType { 5998 case plan.Query_UPDATE: 5999 t = PrivilegeTypeUpdate 6000 clusterTableOperation = clusterTableModify 6001 case plan.Query_DELETE: 6002 t = PrivilegeTypeDelete 6003 clusterTableOperation = clusterTableModify 6004 case plan.Query_INSERT: 6005 t = PrivilegeTypeInsert 6006 clusterTableOperation = clusterTableModify 6007 default: 6008 t = PrivilegeTypeSelect 6009 clusterTableOperation = clusterTableSelect 6010 } 6011 6012 for _, node := range q.Nodes { 6013 if node.NodeType == plan.Node_TABLE_SCAN { 6014 if node.ObjRef != nil { 6015 if node.TableDef != nil && node.TableDef.TableType == catalog.SystemClusterRel { 6016 clusterTable = true 6017 } else { 6018 clusterTable = isClusterTable(node.ObjRef.GetSchemaName(), node.ObjRef.GetObjName()) 6019 } 6020 6021 var scanTyp PrivilegeType 6022 switch q.StmtType { 6023 case plan.Query_UPDATE: 6024 scanTyp = PrivilegeTypeUpdate 6025 clusterTableOperation = clusterTableModify 6026 case plan.Query_DELETE: 6027 scanTyp = PrivilegeTypeDelete 6028 clusterTableOperation = clusterTableModify 6029 default: 6030 scanTyp = PrivilegeTypeSelect 6031 clusterTableOperation = clusterTableSelect 6032 } 6033 6034 //do not check the privilege of the index table 6035 if !isIndexTable(node.ObjRef.GetObjName()) { 6036 appendPt(privilegeTips{ 6037 typ: scanTyp, 6038 databaseName: node.ObjRef.GetSchemaName(), 6039 tableName: node.ObjRef.GetObjName(), 6040 isClusterTable: clusterTable, 6041 clusterTableOperation: clusterTableOperation, 6042 }) 6043 } else if node.ParentObjRef != nil { 6044 appendPt(privilegeTips{ 6045 typ: scanTyp, 6046 databaseName: node.ParentObjRef.GetSchemaName(), 6047 tableName: node.ParentObjRef.GetObjName(), 6048 isClusterTable: clusterTable, 6049 clusterTableOperation: clusterTableOperation, 6050 }) 6051 } 6052 } 6053 } else if node.NodeType == plan.Node_INSERT { 6054 if node.InsertCtx != nil && node.InsertCtx.Ref != nil { 6055 objRef := node.InsertCtx.Ref 6056 //do not check the privilege of the index table 6057 if !isIndexTable(node.ObjRef.GetObjName()) { 6058 appendPt(privilegeTips{ 6059 typ: t, 6060 databaseName: objRef.GetSchemaName(), 6061 tableName: objRef.GetObjName(), 6062 isClusterTable: node.InsertCtx.IsClusterTable, 6063 clusterTableOperation: clusterTableModify, 6064 }) 6065 } 6066 } 6067 } else if node.NodeType == plan.Node_DELETE { 6068 if node.DeleteCtx != nil && node.DeleteCtx.Ref != nil { 6069 objRef := node.DeleteCtx.Ref 6070 //do not check the privilege of the index table 6071 if !isIndexTable(node.ObjRef.GetObjName()) { 6072 appendPt(privilegeTips{ 6073 typ: t, 6074 databaseName: objRef.GetSchemaName(), 6075 tableName: objRef.GetObjName(), 6076 isClusterTable: node.DeleteCtx.IsClusterTable, 6077 clusterTableOperation: clusterTableModify, 6078 }) 6079 } 6080 } 6081 } 6082 } 6083 } else if p.GetDdl() != nil { 6084 if p.GetDdl().GetTruncateTable() != nil { 6085 truncateTable := p.GetDdl().GetTruncateTable() 6086 appendPt(privilegeTips{ 6087 typ: PrivilegeTypeTruncate, 6088 databaseName: truncateTable.GetDatabase(), 6089 tableName: truncateTable.GetTable(), 6090 isClusterTable: truncateTable.GetClusterTable().GetIsClusterTable(), 6091 clusterTableOperation: clusterTableModify, 6092 }) 6093 } else if p.GetDdl().GetDropTable() != nil { 6094 dropTable := p.GetDdl().GetDropTable() 6095 appendPt(privilegeTips{ 6096 typ: PrivilegeTypeDropTable, 6097 databaseName: dropTable.GetDatabase(), 6098 tableName: dropTable.GetTable(), 6099 isClusterTable: dropTable.GetClusterTable().GetIsClusterTable(), 6100 clusterTableOperation: clusterTableDrop, 6101 }) 6102 } else if p.GetDdl().GetCreateIndex() != nil { 6103 createIndex := p.GetDdl().GetCreateIndex() 6104 appendPt(privilegeTips{ 6105 typ: PrivilegeTypeDropTable, 6106 databaseName: createIndex.GetDatabase(), 6107 tableName: createIndex.GetTable(), 6108 clusterTableOperation: clusterTableModify, 6109 }) 6110 } else if p.GetDdl().GetDropIndex() != nil { 6111 dropIndex := p.GetDdl().GetDropIndex() 6112 appendPt(privilegeTips{ 6113 typ: PrivilegeTypeDropTable, 6114 databaseName: dropIndex.GetDatabase(), 6115 tableName: dropIndex.GetTable(), 6116 clusterTableOperation: clusterTableModify, 6117 }) 6118 } 6119 } 6120 return pts 6121 } 6122 6123 // convertPrivilegeTipsToPrivilege constructs the privilege entries from the privilege tips from the plan 6124 func convertPrivilegeTipsToPrivilege(priv *privilege, arr privilegeTipsArray) { 6125 //rewirte the privilege entries based on privilege tips 6126 if priv.objectType() != objectTypeTable && 6127 priv.objectType() != objectTypeDatabase { 6128 return 6129 } 6130 6131 //NOTE: when the arr is nil, it denotes that there is no operation on the table. 6132 6133 type pair struct { 6134 databaseName string 6135 tableName string 6136 } 6137 6138 dedup := make(map[pair]int8) 6139 6140 //multi privileges take effect together 6141 entries := make([]privilegeEntry, 0, len(arr)) 6142 multiPrivs := make([]privilegeItem, 0, len(arr)) 6143 for _, tips := range arr { 6144 multiPrivs = append(multiPrivs, privilegeItem{ 6145 privilegeTyp: tips.typ, 6146 dbName: tips.databaseName, 6147 tableName: tips.tableName, 6148 isClusterTable: tips.isClusterTable, 6149 clusterTableOperation: tips.clusterTableOperation, 6150 }) 6151 6152 dedup[pair{tips.databaseName, tips.tableName}] = 1 6153 } 6154 6155 me := &compoundEntry{multiPrivs} 6156 entries = append(entries, privilegeEntry{privilegeEntryTyp: privilegeEntryTypeCompound, compound: me}) 6157 6158 //optional predefined privilege : tableAll, ownership 6159 predefined := []PrivilegeType{PrivilegeTypeTableAll, PrivilegeTypeTableOwnership} 6160 for _, p := range predefined { 6161 for par := range dedup { 6162 e := privilegeEntriesMap[p] 6163 e.databaseName = par.databaseName 6164 e.tableName = par.tableName 6165 entries = append(entries, e) 6166 } 6167 } 6168 6169 priv.entries = entries 6170 } 6171 6172 // getSqlFromPrivilegeEntry generates the query sql for the privilege entry 6173 func getSqlFromPrivilegeEntry(ctx context.Context, roleId int64, entry privilegeEntry) (string, error) { 6174 var err error 6175 var sql string 6176 //for object type table, need concrete tableid 6177 //TODO: table level check should be done after getting the plan 6178 if entry.objType == objectTypeTable { 6179 switch entry.privilegeLevel { 6180 case privilegeLevelDatabaseTable, privilegeLevelTable: 6181 sql, err = getSqlForCheckRoleHasTableLevelPrivilege(ctx, roleId, entry.privilegeId, entry.databaseName, entry.tableName) 6182 case privilegeLevelDatabaseStar, privilegeLevelStar: 6183 sql, err = getSqlForCheckRoleHasTableLevelForDatabaseStar(ctx, roleId, entry.privilegeId, entry.databaseName) 6184 case privilegeLevelStarStar: 6185 sql = getSqlForCheckRoleHasTableLevelForStarStar(roleId, entry.privilegeId) 6186 default: 6187 return "", moerr.NewInternalError(ctx, "unsupported privilegel level %s for the privilege %s", entry.privilegeLevel, entry.privilegeId) 6188 } 6189 } else if entry.objType == objectTypeDatabase { 6190 switch entry.privilegeLevel { 6191 case privilegeLevelStar, privilegeLevelStarStar: 6192 sql = getSqlForCheckRoleHasDatabaseLevelForStarStar(roleId, entry.privilegeId, entry.privilegeLevel) 6193 case privilegeLevelDatabase: 6194 sql, err = getSqlForCheckRoleHasDatabaseLevelForDatabase(ctx, roleId, entry.privilegeId, entry.databaseName) 6195 default: 6196 return "", moerr.NewInternalError(ctx, "unsupported privilegel level %s for the privilege %s", entry.privilegeLevel, entry.privilegeId) 6197 } 6198 } else if entry.objType == objectTypeAccount { 6199 switch entry.privilegeLevel { 6200 case privilegeLevelStar: 6201 sql = getSqlForCheckRoleHasAccountLevelForStar(roleId, entry.privilegeId) 6202 default: 6203 return "false", moerr.NewInternalError(ctx, "unsupported privilegel level %s for the privilege %s", entry.privilegeLevel, entry.privilegeId) 6204 } 6205 } else { 6206 sql = getSqlForCheckRoleHasPrivilege(roleId, entry.objType, int64(entry.objId), int64(entry.privilegeId)) 6207 } 6208 return sql, err 6209 } 6210 6211 // getPrivilegeLevelsOfObjectType gets the privilege levels of the objectType 6212 func getPrivilegeLevelsOfObjectType(ctx context.Context, objType objectType) ([]privilegeLevelType, error) { 6213 if ret, ok := objectType2privilegeLevels[objType]; ok { 6214 return ret, nil 6215 } 6216 return nil, moerr.NewInternalError(ctx, "do not support the object type %s", objType.String()) 6217 } 6218 6219 // getSqlForPrivilege generates the query sql for the privilege entry 6220 func getSqlForPrivilege(ctx context.Context, roleId int64, entry privilegeEntry, pl privilegeLevelType) (string, error) { 6221 var sql string 6222 var err error 6223 //for object type table, need concrete tableid 6224 switch entry.objType { 6225 case objectTypeTable: 6226 switch pl { 6227 case privilegeLevelDatabaseTable, privilegeLevelTable: 6228 sql, err = getSqlForCheckRoleHasTableLevelPrivilege(ctx, roleId, entry.privilegeId, entry.databaseName, entry.tableName) 6229 case privilegeLevelDatabaseStar, privilegeLevelStar: 6230 sql, err = getSqlForCheckRoleHasTableLevelForDatabaseStar(ctx, roleId, entry.privilegeId, entry.databaseName) 6231 case privilegeLevelStarStar: 6232 sql = getSqlForCheckRoleHasTableLevelForStarStar(roleId, entry.privilegeId) 6233 default: 6234 return "", moerr.NewInternalError(ctx, "the privilege level %s for the privilege %s is unsupported", pl, entry.privilegeId) 6235 } 6236 case objectTypeDatabase: 6237 switch pl { 6238 case privilegeLevelStar, privilegeLevelStarStar: 6239 sql = getSqlForCheckRoleHasDatabaseLevelForStarStar(roleId, entry.privilegeId, pl) 6240 case privilegeLevelDatabase: 6241 sql, err = getSqlForCheckRoleHasDatabaseLevelForDatabase(ctx, roleId, entry.privilegeId, entry.databaseName) 6242 default: 6243 return "", moerr.NewInternalError(ctx, "the privilege level %s for the privilege %s is unsupported", pl, entry.privilegeId) 6244 } 6245 case objectTypeAccount: 6246 switch pl { 6247 case privilegeLevelStar: 6248 sql = getSqlForCheckRoleHasAccountLevelForStar(roleId, entry.privilegeId) 6249 default: 6250 return "false", moerr.NewInternalError(ctx, "the privilege level %s for the privilege %s is unsupported", pl, entry.privilegeId) 6251 } 6252 default: 6253 sql = getSqlForCheckRoleHasPrivilege(roleId, entry.objType, int64(entry.objId), int64(entry.privilegeId)) 6254 } 6255 6256 return sql, err 6257 } 6258 6259 // getSqlForPrivilege2 complements the database name and calls getSqlForPrivilege 6260 func getSqlForPrivilege2(ctx context.Context, ses *Session, roleId int64, entry privilegeEntry, pl privilegeLevelType) (string, error) { 6261 //handle the empty database 6262 if len(entry.databaseName) == 0 { 6263 entry.databaseName = ses.GetDatabaseName() 6264 } 6265 return getSqlForPrivilege(ctx, roleId, entry, pl) 6266 } 6267 6268 // verifyPrivilegeEntryInMultiPrivilegeLevels checks the privilege 6269 // with multi-privilege levels exists or not 6270 func verifyPrivilegeEntryInMultiPrivilegeLevels( 6271 ctx context.Context, 6272 bh BackgroundExec, 6273 ses *Session, 6274 cache *privilegeCache, 6275 roleId int64, 6276 entry privilegeEntry, 6277 pls []privilegeLevelType, 6278 enableCache bool) (bool, error) { 6279 var erArray []ExecResult 6280 var sql string 6281 var yes bool 6282 var err error 6283 dbName := entry.databaseName 6284 if len(dbName) == 0 { 6285 dbName = ses.GetDatabaseName() 6286 } 6287 for _, pl := range pls { 6288 if cache != nil && enableCache { 6289 yes = cache.has(entry.objType, pl, dbName, entry.tableName, entry.privilegeId) 6290 if yes { 6291 return true, nil 6292 } 6293 } 6294 sql, err = getSqlForPrivilege2(ctx, ses, roleId, entry, pl) 6295 if err != nil { 6296 return false, err 6297 } 6298 6299 bh.ClearExecResultSet() 6300 err = bh.Exec(ctx, sql) 6301 if err != nil { 6302 return false, err 6303 } 6304 6305 erArray, err = getResultSet(ctx, bh) 6306 if err != nil { 6307 return false, err 6308 } 6309 6310 if execResultArrayHasData(erArray) { 6311 if cache != nil && enableCache { 6312 cache.add(entry.objType, pl, dbName, entry.tableName, entry.privilegeId) 6313 } 6314 return true, nil 6315 } 6316 } 6317 return false, nil 6318 } 6319 6320 // determineRoleSetHasPrivilegeSet decides the role set has at least one privilege of the privilege set. 6321 // The algorithm 2. 6322 func determineRoleSetHasPrivilegeSet(ctx context.Context, bh BackgroundExec, ses *Session, roleIds *btree.Set[int64], priv *privilege, enableCache bool) (bool, error) { 6323 var err error 6324 var pls []privilegeLevelType 6325 6326 var yes bool 6327 var yes2 bool 6328 //there is no privilege needs, just approve 6329 if len(priv.entries) == 0 { 6330 return false, nil 6331 } 6332 6333 cache := ses.GetPrivilegeCache() 6334 6335 for _, roleId := range roleIds.Keys() { 6336 for _, entry := range priv.entries { 6337 if entry.privilegeEntryTyp == privilegeEntryTypeGeneral { 6338 pls, err = getPrivilegeLevelsOfObjectType(ctx, entry.objType) 6339 if err != nil { 6340 return false, err 6341 } 6342 6343 yes2 = verifyLightPrivilege(ses, 6344 entry.databaseName, 6345 priv.writeDatabaseAndTableDirectly, 6346 priv.isClusterTable, 6347 priv.clusterTableOperation) 6348 6349 if yes2 { 6350 yes, err = verifyPrivilegeEntryInMultiPrivilegeLevels(ctx, bh, ses, cache, roleId, entry, pls, enableCache) 6351 if err != nil { 6352 return false, err 6353 } 6354 } 6355 6356 if yes { 6357 return true, nil 6358 } 6359 } else if entry.privilegeEntryTyp == privilegeEntryTypeCompound { 6360 if entry.compound != nil { 6361 allTrue := true 6362 //multi privileges take effect together 6363 for _, mi := range entry.compound.items { 6364 if mi.privilegeTyp == PrivilegeTypeCanGrantRoleToOthersInCreateUser { 6365 //TODO: normalize the name 6366 //TODO: simplify the logic 6367 yes, err = determineUserCanGrantRolesToOthersInternal(ctx, bh, ses, []*tree.Role{mi.role}) 6368 if err != nil { 6369 return false, err 6370 } 6371 if yes { 6372 from := &verifiedRole{ 6373 typ: roleType, 6374 name: mi.role.UserName, 6375 } 6376 for _, user := range mi.users { 6377 to := &verifiedRole{ 6378 typ: userType, 6379 name: user.Username, 6380 } 6381 err = verifySpecialRolesInGrant(ctx, ses.GetTenantInfo(), from, to) 6382 if err != nil { 6383 return false, err 6384 } 6385 } 6386 } 6387 } else { 6388 tempEntry := privilegeEntriesMap[mi.privilegeTyp] 6389 tempEntry.databaseName = mi.dbName 6390 tempEntry.tableName = mi.tableName 6391 tempEntry.privilegeEntryTyp = privilegeEntryTypeGeneral 6392 tempEntry.compound = nil 6393 pls, err = getPrivilegeLevelsOfObjectType(ctx, tempEntry.objType) 6394 if err != nil { 6395 return false, err 6396 } 6397 6398 yes2 = verifyLightPrivilege(ses, 6399 tempEntry.databaseName, 6400 priv.writeDatabaseAndTableDirectly, 6401 mi.isClusterTable, 6402 mi.clusterTableOperation) 6403 6404 if yes2 { 6405 //At least there is one success 6406 yes, err = verifyPrivilegeEntryInMultiPrivilegeLevels(ctx, bh, ses, cache, roleId, tempEntry, pls, enableCache) 6407 if err != nil { 6408 return false, err 6409 } 6410 } 6411 } 6412 if !yes { 6413 allTrue = false 6414 break 6415 } 6416 } 6417 6418 if allTrue { 6419 return allTrue, nil 6420 } 6421 } 6422 } 6423 } 6424 } 6425 return false, nil 6426 } 6427 6428 // determineUserHasPrivilegeSet decides the privileges of user can satisfy the requirement of the privilege set 6429 // The algorithm 1. 6430 func determineUserHasPrivilegeSet(ctx context.Context, ses *Session, priv *privilege) (ret bool, err error) { 6431 var erArray []ExecResult 6432 var yes bool 6433 var roleB int64 6434 var ok bool 6435 var grantedIds *btree.Set[int64] 6436 var enableCache bool 6437 6438 //check privilege cache first 6439 if len(priv.entries) == 0 { 6440 return false, nil 6441 } 6442 6443 enableCache, err = privilegeCacheIsEnabled(ctx, ses) 6444 if err != nil { 6445 return false, err 6446 } 6447 if enableCache { 6448 yes, err = checkPrivilegeInCache(ctx, ses, priv, enableCache) 6449 if err != nil { 6450 return false, err 6451 } 6452 if yes { 6453 return true, nil 6454 } 6455 } 6456 6457 tenant := ses.GetTenantInfo() 6458 bh := ses.GetBackgroundExec(ctx) 6459 defer bh.Close() 6460 6461 if ses.tStmt != nil { 6462 // for reset frontend query's txn-id 6463 // NEED to skip this background session txn, which used by authenticateUserCanExecuteStatement() 6464 ses.tStmt.SetSkipTxn(true) 6465 } 6466 6467 //the set of roles the (k+1) th iteration during the execution 6468 roleSetOfKPlusOneThIteration := &btree.Set[int64]{} 6469 //the set of roles the k th iteration during the execution 6470 roleSetOfKthIteration := &btree.Set[int64]{} 6471 //the set of roles visited by traversal algorithm 6472 roleSetOfVisited := &btree.Set[int64]{} 6473 //simple mo_role_grant cache 6474 cacheOfMoRoleGrant := &btree.Map[int64, *btree.Set[int64]]{} 6475 6476 //step 1: The Set R1 {default role id} 6477 //The primary role (in use) 6478 roleSetOfKthIteration.Insert((int64)(tenant.GetDefaultRoleID())) 6479 6480 err = bh.Exec(ctx, "begin;") 6481 defer func() { 6482 err = finishTxn(ctx, bh, err) 6483 }() 6484 if err != nil { 6485 return false, err 6486 } 6487 6488 //step 2: The Set R2 {the roleid granted to the userid} 6489 //If the user uses the all secondary roles, the secondary roles needed to be loaded 6490 err = loadAllSecondaryRoles(ctx, bh, tenant, roleSetOfKthIteration) 6491 if err != nil { 6492 return false, err 6493 } 6494 6495 //init RVisited = Rk 6496 roleSetOfKthIteration.Scan(func(roleId int64) bool { 6497 roleSetOfVisited.Insert(roleId) 6498 return true 6499 }) 6500 6501 //Call the algorithm 2. 6502 //If the result of the algorithm 2 is true, Then return true; 6503 yes, err = determineRoleSetHasPrivilegeSet(ctx, bh, ses, roleSetOfKthIteration, priv, enableCache) 6504 if err != nil { 6505 return false, err 6506 } 6507 if yes { 6508 ret = true 6509 return ret, err 6510 } 6511 /* 6512 step 3: !!!NOTE all roleid in Rk has been processed by the algorithm 2. 6513 RVisited is the set of all roleid that has been processed. 6514 RVisited = Rk; 6515 For { 6516 For roleA in Rk { 6517 Find the peer roleB in the table mo_role_grant(granted_id,grantee_id) with grantee_id = roleA; 6518 If roleB is not in RVisited, Then add roleB into R(k+1); 6519 add roleB into RVisited; 6520 } 6521 6522 If R(k+1) is empty, Then return false; 6523 //Call the algorithm 2. 6524 If the result of the algorithm 2 is true, Then return true; 6525 Rk = R(k+1); 6526 R(k+1) = {}; 6527 } 6528 */ 6529 for { 6530 quit := false 6531 select { 6532 case <-ctx.Done(): 6533 quit = true 6534 default: 6535 } 6536 if quit { 6537 break 6538 } 6539 6540 roleSetOfKPlusOneThIteration.Clear() 6541 6542 //get roleB of roleA 6543 for _, roleA := range roleSetOfKthIteration.Keys() { 6544 if grantedIds, ok = cacheOfMoRoleGrant.Get(roleA); ok { 6545 for _, grantedId := range grantedIds.Keys() { 6546 roleSetOfKPlusOneThIteration.Insert(grantedId) 6547 } 6548 continue 6549 } 6550 grantedIds = &btree.Set[int64]{} 6551 cacheOfMoRoleGrant.Set(roleA, grantedIds) 6552 sqlForInheritedRoleIdOfRoleId := getSqlForInheritedRoleIdOfRoleId(roleA) 6553 bh.ClearExecResultSet() 6554 err = bh.Exec(ctx, sqlForInheritedRoleIdOfRoleId) 6555 if err != nil { 6556 return false, moerr.NewInternalError(ctx, "get inherited role id of the role id. error:%v", err) 6557 } 6558 6559 erArray, err = getResultSet(ctx, bh) 6560 if err != nil { 6561 return false, err 6562 } 6563 6564 if execResultArrayHasData(erArray) { 6565 for i := uint64(0); i < erArray[0].GetRowCount(); i++ { 6566 roleB, err = erArray[0].GetInt64(ctx, i, 0) 6567 if err != nil { 6568 return false, err 6569 } 6570 6571 if !roleSetOfVisited.Contains(roleB) { 6572 roleSetOfVisited.Insert(roleB) 6573 roleSetOfKPlusOneThIteration.Insert(roleB) 6574 grantedIds.Insert(roleB) 6575 } 6576 } 6577 } 6578 } 6579 6580 //no more roleB, it is done 6581 if roleSetOfKPlusOneThIteration.Len() == 0 { 6582 ret = false 6583 return ret, err 6584 } 6585 6586 //Call the algorithm 2. 6587 //If the result of the algorithm 2 is true, Then return true; 6588 yes, err = determineRoleSetHasPrivilegeSet(ctx, bh, ses, roleSetOfKPlusOneThIteration, priv, enableCache) 6589 if err != nil { 6590 return false, err 6591 } 6592 6593 if yes { 6594 ret = true 6595 return ret, err 6596 } 6597 roleSetOfKthIteration, roleSetOfKPlusOneThIteration = roleSetOfKPlusOneThIteration, roleSetOfKthIteration 6598 } 6599 return ret, err 6600 } 6601 6602 const ( 6603 goOn int = iota 6604 successDone //ri has indirect relation with the Uc 6605 ) 6606 6607 // loadAllSecondaryRoles loads all secondary roles 6608 func loadAllSecondaryRoles(ctx context.Context, bh BackgroundExec, account *TenantInfo, roleSetOfCurrentUser *btree.Set[int64]) error { 6609 var err error 6610 var sql string 6611 6612 var erArray []ExecResult 6613 var roleId int64 6614 6615 if account.GetUseSecondaryRole() { 6616 sql = getSqlForRoleIdOfUserId(int(account.GetUserID())) 6617 bh.ClearExecResultSet() 6618 err = bh.Exec(ctx, sql) 6619 if err != nil { 6620 return err 6621 } 6622 6623 erArray, err = getResultSet(ctx, bh) 6624 if err != nil { 6625 return err 6626 } 6627 6628 if execResultArrayHasData(erArray) { 6629 for i := uint64(0); i < erArray[0].GetRowCount(); i++ { 6630 roleId, err = erArray[0].GetInt64(ctx, i, 0) 6631 if err != nil { 6632 return err 6633 } 6634 roleSetOfCurrentUser.Insert(roleId) 6635 } 6636 } 6637 } 6638 return err 6639 } 6640 6641 // determineUserCanGrantRolesToOthersInternal decides if the user can grant roles to other users or roles 6642 // the same as the grant/revoke privilege, role with inputted transaction and BackgroundExec 6643 func determineUserCanGrantRolesToOthersInternal(ctx context.Context, bh BackgroundExec, ses *Session, fromRoles []*tree.Role) (bool, error) { 6644 //step1: normalize the names of roles and users 6645 var err error 6646 err = normalizeNamesOfRoles(ctx, fromRoles) 6647 if err != nil { 6648 return false, err 6649 } 6650 6651 //step2: decide the current user 6652 account := ses.GetTenantInfo() 6653 6654 //step3: check the link: roleX -> roleA -> .... -> roleZ -> the current user. Every link has the with_grant_option. 6655 var vr *verifiedRole 6656 var ret = true 6657 var granted bool 6658 //the temporal set of roles during the execution 6659 var tempRoleSet *btree.Set[int64] 6660 var sql string 6661 //the set of roles the (k+1) th iteration during the execution 6662 roleSetOfKPlusOneThIteration := &btree.Set[int64]{} 6663 //the set of roles the k th iteration during the execution 6664 roleSetOfKthIteration := &btree.Set[int64]{} 6665 //the set of roles of the current user that executes this statement or function 6666 roleSetOfCurrentUser := &btree.Set[int64]{} 6667 //the set of roles visited by traversal algorithm 6668 roleSetOfVisited := &btree.Set[int64]{} 6669 verifiedFromRoles := make([]*verifiedRole, len(fromRoles)) 6670 6671 //step 1 : add the primary role 6672 roleSetOfCurrentUser.Insert(int64(account.GetDefaultRoleID())) 6673 6674 for i, role := range fromRoles { 6675 sql, err = getSqlForRoleIdOfRole(ctx, role.UserName) 6676 if err != nil { 6677 return false, err 6678 } 6679 vr, err = verifyRoleFunc(ctx, bh, sql, role.UserName, roleType) 6680 if err != nil { 6681 return false, err 6682 } 6683 if vr == nil { 6684 return false, moerr.NewInternalError(ctx, "there is no role %s", role.UserName) 6685 } 6686 verifiedFromRoles[i] = vr 6687 } 6688 6689 //step 2: The Set R2 {the roleid granted to the userid} 6690 //If the user uses the all secondary roles, the secondary roles needed to be loaded 6691 err = loadAllSecondaryRoles(ctx, bh, account, roleSetOfCurrentUser) 6692 if err != nil { 6693 return false, err 6694 } 6695 6696 for _, role := range verifiedFromRoles { 6697 //if it is the role in use, do the check 6698 if roleSetOfCurrentUser.Contains(role.id) { 6699 //check the direct relation between role and user 6700 granted, err = isRoleGrantedToUserWGO(ctx, bh, role.id, int64(account.GetUserID())) 6701 if err != nil { 6702 return false, err 6703 } 6704 if granted { 6705 continue 6706 } 6707 } 6708 6709 roleSetOfKthIteration.Clear() 6710 roleSetOfVisited.Clear() 6711 roleSetOfKthIteration.Insert(role.id) 6712 6713 riResult := goOn 6714 //It is kind of level traversal 6715 for roleSetOfKthIteration.Len() != 0 && riResult == goOn { 6716 roleSetOfKPlusOneThIteration.Clear() 6717 for _, ri := range roleSetOfKthIteration.Keys() { 6718 tempRoleSet, err = getRoleSetThatRoleGrantedToWGO(ctx, bh, ri, roleSetOfVisited, roleSetOfKPlusOneThIteration) 6719 if err != nil { 6720 return false, err 6721 } 6722 6723 if setIsIntersected(tempRoleSet, roleSetOfCurrentUser) { 6724 riResult = successDone 6725 break 6726 } 6727 } 6728 6729 //swap Rk,R(k+1) 6730 roleSetOfKthIteration, roleSetOfKPlusOneThIteration = roleSetOfKPlusOneThIteration, roleSetOfKthIteration 6731 } 6732 6733 if riResult != successDone { 6734 //fail 6735 ret = false 6736 break 6737 } 6738 } 6739 return ret, err 6740 } 6741 6742 // determineUserCanGrantRoleToOtherUsers decides if the user can grant roles to other users or roles 6743 // the same as the grant/revoke privilege, role. 6744 func determineUserCanGrantRolesToOthers(ctx context.Context, ses *Session, fromRoles []*tree.Role) (ret bool, err error) { 6745 //step1: normalize the names of roles and users 6746 err = normalizeNamesOfRoles(ctx, fromRoles) 6747 if err != nil { 6748 return false, err 6749 } 6750 6751 //step2: decide the current user 6752 bh := ses.GetBackgroundExec(ctx) 6753 defer bh.Close() 6754 6755 //put it into the single transaction 6756 err = bh.Exec(ctx, "begin;") 6757 defer func() { 6758 err = finishTxn(ctx, bh, err) 6759 }() 6760 if err != nil { 6761 return false, err 6762 } 6763 6764 ret, err = determineUserCanGrantRolesToOthersInternal(ctx, bh, ses, fromRoles) 6765 if err != nil { 6766 return false, err 6767 } 6768 6769 return ret, err 6770 } 6771 6772 // isRoleGrantedToUserWGO verifies the role has been granted to the user with with_grant_option = true. 6773 // Algorithm 1 6774 func isRoleGrantedToUserWGO(ctx context.Context, bh BackgroundExec, roleId, UserId int64) (bool, error) { 6775 var err error 6776 var erArray []ExecResult 6777 sql := getSqlForCheckUserGrantWGO(roleId, UserId) 6778 bh.ClearExecResultSet() 6779 err = bh.Exec(ctx, sql) 6780 if err != nil { 6781 return false, err 6782 } 6783 6784 erArray, err = getResultSet(ctx, bh) 6785 if err != nil { 6786 return false, err 6787 } 6788 6789 if execResultArrayHasData(erArray) { 6790 return true, nil 6791 } 6792 6793 return false, nil 6794 } 6795 6796 // getRoleSetThatRoleGrantedToWGO returns all the roles that the role has been granted to with with_grant_option = true. 6797 // Algorithm 2 6798 func getRoleSetThatRoleGrantedToWGO(ctx context.Context, bh BackgroundExec, roleId int64, RVisited, RkPlusOne *btree.Set[int64]) (*btree.Set[int64], error) { 6799 var err error 6800 var erArray []ExecResult 6801 var id int64 6802 rset := &btree.Set[int64]{} 6803 sql := getSqlForCheckRoleGrantWGO(roleId) 6804 bh.ClearExecResultSet() 6805 err = bh.Exec(ctx, sql) 6806 if err != nil { 6807 return nil, err 6808 } 6809 6810 erArray, err = getResultSet(ctx, bh) 6811 if err != nil { 6812 return nil, err 6813 } 6814 6815 if execResultArrayHasData(erArray) { 6816 for i := uint64(0); i < erArray[0].GetRowCount(); i++ { 6817 id, err = erArray[0].GetInt64(ctx, i, 0) 6818 if err != nil { 6819 return nil, err 6820 } 6821 if !RVisited.Contains(id) { 6822 RVisited.Insert(id) 6823 RkPlusOne.Insert(id) 6824 rset.Insert(id) 6825 } 6826 } 6827 } 6828 6829 return rset, err 6830 } 6831 6832 // authenticateUserCanExecuteStatementWithObjectTypeAccountAndDatabase decides the user has the privilege of executing the statement with object type account 6833 func authenticateUserCanExecuteStatementWithObjectTypeAccountAndDatabase(ctx context.Context, ses *Session, stmt tree.Statement) (bool, error) { 6834 var err error 6835 var ok, yes bool 6836 priv := ses.GetPrivilege() 6837 if priv.objectType() != objectTypeAccount && priv.objectType() != objectTypeDatabase { //do nothing 6838 return true, nil 6839 } 6840 ok, err = determineUserHasPrivilegeSet(ctx, ses, priv) 6841 if err != nil { 6842 return false, err 6843 } 6844 6845 //double check privilege of drop table 6846 if !ok && ses.GetFromRealUser() && ses.GetTenantInfo() != nil && ses.GetTenantInfo().IsSysTenant() { 6847 switch dropTable := stmt.(type) { 6848 case *tree.DropTable: 6849 dbName := string(dropTable.Names[0].SchemaName) 6850 if len(dbName) == 0 { 6851 dbName = ses.GetDatabaseName() 6852 } 6853 return isClusterTable(dbName, string(dropTable.Names[0].ObjectName)), nil 6854 } 6855 } 6856 6857 //for GrantRole statement, check with_grant_option 6858 if !ok && priv.kind == privilegeKindInherit { 6859 grant := stmt.(*tree.Grant) 6860 grantRole := grant.GrantRole 6861 yes, err = determineUserCanGrantRolesToOthers(ctx, ses, grantRole.Roles) 6862 if err != nil { 6863 return false, err 6864 } 6865 if yes { 6866 return true, nil 6867 } 6868 } 6869 //for Create User statement with default role. 6870 //TODO: 6871 6872 // support dropdatabase and droptable for owner 6873 if !ok && ses.GetFromRealUser() && ses.GetTenantInfo() != nil && priv.kind == privilegeKindGeneral { 6874 switch st := stmt.(type) { 6875 case *tree.DropDatabase: 6876 // get the databasename 6877 dbName := string(st.Name) 6878 if _, inSet := sysDatabases[dbName]; inSet { 6879 return ok, nil 6880 } 6881 return checkRoleWhetherDatabaseOwner(ctx, ses, dbName, ok) 6882 case *tree.DropTable: 6883 // get the databasename and tablename 6884 if len(st.Names) != 1 { 6885 return ok, nil 6886 } 6887 dbName := string(st.Names[0].SchemaName) 6888 if len(dbName) == 0 { 6889 dbName = ses.GetDatabaseName() 6890 } 6891 if _, inSet := sysDatabases[dbName]; inSet { 6892 return ok, nil 6893 } 6894 tbName := string(st.Names[0].ObjectName) 6895 return checkRoleWhetherTableOwner(ctx, ses, dbName, tbName, ok) 6896 } 6897 } 6898 return ok, nil 6899 } 6900 6901 func checkRoleWhetherTableOwner(ctx context.Context, ses *Session, dbName, tbName string, ok bool) (bool, error) { 6902 var owner int64 6903 var err error 6904 var erArray []ExecResult 6905 var sql string 6906 roles := make([]int64, 0) 6907 tenantInfo := ses.GetTenantInfo() 6908 // current user 6909 currentUser := tenantInfo.GetUserID() 6910 6911 bh := ses.GetBackgroundExec(ctx) 6912 defer bh.Close() 6913 6914 // getOwner of the table 6915 sql = getSqlForGetOwnerOfTable(dbName, tbName) 6916 bh.ClearExecResultSet() 6917 err = bh.Exec(ctx, sql) 6918 if err != nil { 6919 return ok, nil 6920 } 6921 erArray, err = getResultSet(ctx, bh) 6922 if err != nil { 6923 return ok, nil 6924 } 6925 6926 if execResultArrayHasData(erArray) { 6927 owner, err = erArray[0].GetInt64(ctx, 0, 0) 6928 if err != nil { 6929 return ok, nil 6930 } 6931 } else { 6932 return ok, nil 6933 } 6934 6935 // check role 6936 if tenantInfo.GetUseSecondaryRole() { 6937 sql = getSqlForGetRolesOfCurrentUser(int64(currentUser)) 6938 bh.ClearExecResultSet() 6939 err = bh.Exec(ctx, sql) 6940 if err != nil { 6941 return ok, nil 6942 } 6943 erArray, err = getResultSet(ctx, bh) 6944 if err != nil { 6945 return ok, nil 6946 } 6947 6948 if execResultArrayHasData(erArray) { 6949 for i := uint64(0); i < erArray[0].GetRowCount(); i++ { 6950 role, err := erArray[0].GetInt64(ctx, i, 0) 6951 if err != nil { 6952 return ok, nil 6953 } 6954 roles = append(roles, role) 6955 } 6956 } else { 6957 return ok, nil 6958 } 6959 6960 // check the role whether the table's owner 6961 for _, role := range roles { 6962 if role == owner { 6963 return true, nil 6964 } 6965 } 6966 } else { 6967 currentRole := tenantInfo.GetDefaultRoleID() 6968 if owner == int64(currentRole) { 6969 return true, nil 6970 } 6971 } 6972 return ok, nil 6973 6974 } 6975 6976 func checkRoleWhetherDatabaseOwner(ctx context.Context, ses *Session, dbName string, ok bool) (bool, error) { 6977 var owner int64 6978 var err error 6979 var erArray []ExecResult 6980 var sql string 6981 roles := make([]int64, 0) 6982 6983 tenantInfo := ses.GetTenantInfo() 6984 // current user 6985 currentUser := tenantInfo.GetUserID() 6986 6987 bh := ses.GetBackgroundExec(ctx) 6988 defer bh.Close() 6989 6990 // getOwner of the database 6991 sql = getSqlForGetOwnerOfDatabase(dbName) 6992 bh.ClearExecResultSet() 6993 err = bh.Exec(ctx, sql) 6994 if err != nil { 6995 return ok, nil 6996 } 6997 erArray, err = getResultSet(ctx, bh) 6998 if err != nil { 6999 return ok, nil 7000 } 7001 7002 if execResultArrayHasData(erArray) { 7003 owner, err = erArray[0].GetInt64(ctx, 0, 0) 7004 if err != nil { 7005 return ok, nil 7006 } 7007 } else { 7008 return ok, nil 7009 } 7010 7011 // check role 7012 if tenantInfo.GetUseSecondaryRole() { 7013 sql = getSqlForGetRolesOfCurrentUser(int64(currentUser)) 7014 bh.ClearExecResultSet() 7015 err = bh.Exec(ctx, sql) 7016 if err != nil { 7017 return ok, nil 7018 } 7019 erArray, err = getResultSet(ctx, bh) 7020 if err != nil { 7021 return ok, nil 7022 } 7023 7024 if execResultArrayHasData(erArray) { 7025 for i := uint64(0); i < erArray[0].GetRowCount(); i++ { 7026 role, err := erArray[0].GetInt64(ctx, i, 0) 7027 if err != nil { 7028 return ok, nil 7029 } 7030 roles = append(roles, role) 7031 } 7032 } else { 7033 return ok, nil 7034 } 7035 7036 // check the role whether the database's owner 7037 for _, role := range roles { 7038 if role == owner { 7039 return true, nil 7040 } 7041 } 7042 } else { 7043 currentRole := tenantInfo.GetDefaultRoleID() 7044 if owner == int64(currentRole) { 7045 return true, nil 7046 } 7047 } 7048 return ok, nil 7049 } 7050 7051 // authenticateUserCanExecuteStatementWithObjectTypeDatabaseAndTable 7052 // decides the user has the privilege of executing the statement 7053 // with object type table from the plan 7054 func authenticateUserCanExecuteStatementWithObjectTypeDatabaseAndTable(ctx context.Context, 7055 ses *Session, 7056 stmt tree.Statement, 7057 p *plan2.Plan) (bool, error) { 7058 priv := determinePrivilegeSetOfStatement(stmt) 7059 if priv.objectType() == objectTypeTable { 7060 //only sys account, moadmin role can exec mo_ctrl 7061 if hasMoCtrl(p) { 7062 if !verifyAccountCanExecMoCtrl(ses.GetTenantInfo()) { 7063 return false, moerr.NewInternalError(ctx, "do not have privilege to execute the statement") 7064 } 7065 } 7066 arr := extractPrivilegeTipsFromPlan(p) 7067 if len(arr) == 0 { 7068 return true, nil 7069 } 7070 convertPrivilegeTipsToPrivilege(priv, arr) 7071 ok, err := determineUserHasPrivilegeSet(ctx, ses, priv) 7072 if err != nil { 7073 return false, err 7074 } 7075 return ok, nil 7076 } 7077 return true, nil 7078 } 7079 7080 // formSqlFromGrantPrivilege makes the sql for querying the database. 7081 func formSqlFromGrantPrivilege(ctx context.Context, ses *Session, gp *tree.GrantPrivilege, priv *tree.Privilege) (string, error) { 7082 tenant := ses.GetTenantInfo() 7083 sql := "" 7084 var privType PrivilegeType 7085 var err error 7086 privType, err = convertAstPrivilegeTypeToPrivilegeType(ctx, priv.Type, gp.ObjType) 7087 if err != nil { 7088 return "", err 7089 } 7090 switch gp.ObjType { 7091 case tree.OBJECT_TYPE_TABLE: 7092 switch gp.Level.Level { 7093 case tree.PRIVILEGE_LEVEL_TYPE_STAR: 7094 sql, err = getSqlForCheckWithGrantOptionForTableDatabaseStar(ctx, int64(tenant.GetDefaultRoleID()), privType, ses.GetDatabaseName()) 7095 case tree.PRIVILEGE_LEVEL_TYPE_STAR_STAR: 7096 sql = getSqlForCheckWithGrantOptionForTableStarStar(int64(tenant.GetDefaultRoleID()), privType) 7097 case tree.PRIVILEGE_LEVEL_TYPE_DATABASE_STAR: 7098 sql, err = getSqlForCheckWithGrantOptionForTableDatabaseStar(ctx, int64(tenant.GetDefaultRoleID()), privType, gp.Level.DbName) 7099 case tree.PRIVILEGE_LEVEL_TYPE_DATABASE_TABLE: 7100 sql, err = getSqlForCheckWithGrantOptionForTableDatabaseTable(ctx, int64(tenant.GetDefaultRoleID()), privType, gp.Level.DbName, gp.Level.TabName) 7101 case tree.PRIVILEGE_LEVEL_TYPE_TABLE: 7102 sql, err = getSqlForCheckWithGrantOptionForTableDatabaseTable(ctx, int64(tenant.GetDefaultRoleID()), privType, ses.GetDatabaseName(), gp.Level.TabName) 7103 default: 7104 return "", moerr.NewInternalError(ctx, "in object type %v privilege level type %v is unsupported", gp.ObjType, gp.Level.Level) 7105 } 7106 case tree.OBJECT_TYPE_DATABASE: 7107 switch gp.Level.Level { 7108 case tree.PRIVILEGE_LEVEL_TYPE_STAR: 7109 sql = getSqlForCheckWithGrantOptionForDatabaseStar(int64(tenant.GetDefaultRoleID()), privType) 7110 case tree.PRIVILEGE_LEVEL_TYPE_STAR_STAR: 7111 sql = getSqlForCheckWithGrantOptionForDatabaseStarStar(int64(tenant.GetDefaultRoleID()), privType) 7112 case tree.PRIVILEGE_LEVEL_TYPE_TABLE: 7113 //in the syntax, we can not distinguish the table name from the database name. 7114 sql, err = getSqlForCheckWithGrantOptionForDatabaseDB(ctx, int64(tenant.GetDefaultRoleID()), privType, gp.Level.TabName) 7115 case tree.PRIVILEGE_LEVEL_TYPE_DATABASE: 7116 sql, err = getSqlForCheckWithGrantOptionForDatabaseDB(ctx, int64(tenant.GetDefaultRoleID()), privType, gp.Level.DbName) 7117 default: 7118 return "", moerr.NewInternalError(ctx, "in object type %v privilege level type %v is unsupported", gp.ObjType, gp.Level.Level) 7119 } 7120 case tree.OBJECT_TYPE_ACCOUNT: 7121 switch gp.Level.Level { 7122 case tree.PRIVILEGE_LEVEL_TYPE_STAR: 7123 sql = getSqlForCheckWithGrantOptionForAccountStar(int64(tenant.GetDefaultRoleID()), privType) 7124 default: 7125 return "", moerr.NewInternalError(ctx, "in object type %v privilege level type %v is unsupported", gp.ObjType, gp.Level.Level) 7126 } 7127 default: 7128 return "", moerr.NewInternalError(ctx, "object type %v is unsupported", gp.ObjType) 7129 } 7130 return sql, err 7131 } 7132 7133 // getSqlForCheckRoleHasPrivilegeWGODependsOnPrivType return getSqlForCheckRoleHasPrivilegeWGO denpends on the pritype 7134 func getSqlForCheckRoleHasPrivilegeWGODependsOnPrivType(privType PrivilegeType) string { 7135 switch privType { 7136 // account level privleges 7137 case PrivilegeTypeCreateAccount: 7138 return getSqlForCheckRoleHasPrivilegeWGOOrWithOwnerShip(int64(privType), int64(PrivilegeTypeAccountAll), int64(PrivilegeTypeAccountOwnership)) 7139 case PrivilegeTypeDropAccount: 7140 return getSqlForCheckRoleHasPrivilegeWGOOrWithOwnerShip(int64(privType), int64(PrivilegeTypeAccountAll), int64(PrivilegeTypeAccountOwnership)) 7141 case PrivilegeTypeAlterAccount: 7142 return getSqlForCheckRoleHasPrivilegeWGOOrWithOwnerShip(int64(privType), int64(PrivilegeTypeAccountAll), int64(PrivilegeTypeAccountOwnership)) 7143 case PrivilegeTypeUpgradeAccount: 7144 return getSqlForCheckRoleHasPrivilegeWGOOrWithOwnerShip(int64(privType), int64(PrivilegeTypeAccountAll), int64(PrivilegeTypeAccountOwnership)) 7145 case PrivilegeTypeCreateUser: 7146 return getSqlForCheckRoleHasPrivilegeWGOOrWithOwnerShip(int64(privType), int64(PrivilegeTypeAccountAll), int64(PrivilegeTypeAccountOwnership)) 7147 case PrivilegeTypeDropUser: 7148 return getSqlForCheckRoleHasPrivilegeWGOOrWithOwnerShip(int64(privType), int64(PrivilegeTypeAccountAll), int64(PrivilegeTypeAccountOwnership)) 7149 case PrivilegeTypeAlterUser: 7150 return getSqlForCheckRoleHasPrivilegeWGOOrWithOwnerShip(int64(privType), int64(PrivilegeTypeAccountAll), int64(PrivilegeTypeAccountOwnership)) 7151 case PrivilegeTypeCreateRole: 7152 return getSqlForCheckRoleHasPrivilegeWGOOrWithOwnerShip(int64(privType), int64(PrivilegeTypeAccountAll), int64(PrivilegeTypeAccountOwnership)) 7153 case PrivilegeTypeDropRole: 7154 return getSqlForCheckRoleHasPrivilegeWGOOrWithOwnerShip(int64(privType), int64(PrivilegeTypeAccountAll), int64(PrivilegeTypeAccountOwnership)) 7155 case PrivilegeTypeAlterRole: 7156 return getSqlForCheckRoleHasPrivilegeWGOOrWithOwnerShip(int64(privType), int64(PrivilegeTypeAccountAll), int64(PrivilegeTypeAccountOwnership)) 7157 case PrivilegeTypeCreateDatabase: 7158 return getSqlForCheckRoleHasPrivilegeWGOOrWithOwnerShip(int64(privType), int64(PrivilegeTypeAccountAll), int64(PrivilegeTypeAccountOwnership)) 7159 case PrivilegeTypeDropDatabase: 7160 return getSqlForCheckRoleHasPrivilegeWGOOrWithOwnerShip(int64(privType), int64(PrivilegeTypeAccountAll), int64(PrivilegeTypeAccountOwnership)) 7161 case PrivilegeTypeShowDatabases: 7162 return getSqlForCheckRoleHasPrivilegeWGOOrWithOwnerShip(int64(privType), int64(PrivilegeTypeAccountAll), int64(PrivilegeTypeAccountOwnership)) 7163 case PrivilegeTypeConnect: 7164 return getSqlForCheckRoleHasPrivilegeWGOOrWithOwnerShip(int64(privType), int64(PrivilegeTypeAccountAll), int64(PrivilegeTypeAccountOwnership)) 7165 case PrivilegeTypeManageGrants: 7166 return getSqlForCheckRoleHasPrivilegeWGOOrWithOwnerShip(int64(privType), int64(PrivilegeTypeAccountAll), int64(PrivilegeTypeAccountOwnership)) 7167 case PrivilegeTypeAccountAll: 7168 return getSqlForCheckRoleHasPrivilegeWGOOrWithOwnerShip(int64(privType), int64(PrivilegeTypeAccountAll), int64(PrivilegeTypeAccountOwnership)) 7169 case PrivilegeTypeAccountOwnership: 7170 return getSqlForCheckRoleHasPrivilegeWGO(int64(privType)) 7171 7172 // database level privileges 7173 case PrivilegeTypeShowTables: 7174 return getSqlForCheckRoleHasPrivilegeWGOOrWithOwnerShip(int64(privType), int64(PrivilegeTypeDatabaseAll), int64(PrivilegeTypeDatabaseOwnership)) 7175 case PrivilegeTypeCreateTable: 7176 return getSqlForCheckRoleHasPrivilegeWGOOrWithOwnerShip(int64(privType), int64(PrivilegeTypeDatabaseAll), int64(PrivilegeTypeDatabaseOwnership)) 7177 case PrivilegeTypeDropTable: 7178 return getSqlForCheckRoleHasPrivilegeWGOOrWithOwnerShip(int64(privType), int64(PrivilegeTypeDatabaseAll), int64(PrivilegeTypeDatabaseOwnership)) 7179 case PrivilegeTypeCreateView: 7180 return getSqlForCheckRoleHasPrivilegeWGOOrWithOwnerShip(int64(privType), int64(PrivilegeTypeDatabaseAll), int64(PrivilegeTypeDatabaseOwnership)) 7181 case PrivilegeTypeDropView: 7182 return getSqlForCheckRoleHasPrivilegeWGOOrWithOwnerShip(int64(privType), int64(PrivilegeTypeDatabaseAll), int64(PrivilegeTypeDatabaseOwnership)) 7183 case PrivilegeTypeAlterView: 7184 return getSqlForCheckRoleHasPrivilegeWGOOrWithOwnerShip(int64(privType), int64(PrivilegeTypeDatabaseAll), int64(PrivilegeTypeDatabaseOwnership)) 7185 case PrivilegeTypeAlterTable: 7186 return getSqlForCheckRoleHasPrivilegeWGOOrWithOwnerShip(int64(privType), int64(PrivilegeTypeDatabaseAll), int64(PrivilegeTypeDatabaseOwnership)) 7187 case PrivilegeTypeDatabaseAll: 7188 return getSqlForCheckRoleHasPrivilegeWGOOrWithOwnerShip(int64(privType), int64(PrivilegeTypeDatabaseAll), int64(PrivilegeTypeDatabaseOwnership)) 7189 case PrivilegeTypeDatabaseOwnership: 7190 return getSqlForCheckRoleHasPrivilegeWGO(int64(privType)) 7191 7192 // table level privileges 7193 case PrivilegeTypeSelect: 7194 return getSqlForCheckRoleHasPrivilegeWGOOrWithOwnerShip(int64(privType), int64(PrivilegeTypeTableAll), int64(PrivilegeTypeTableOwnership)) 7195 case PrivilegeTypeInsert: 7196 return getSqlForCheckRoleHasPrivilegeWGOOrWithOwnerShip(int64(privType), int64(PrivilegeTypeTableAll), int64(PrivilegeTypeTableOwnership)) 7197 case PrivilegeTypeUpdate: 7198 return getSqlForCheckRoleHasPrivilegeWGOOrWithOwnerShip(int64(privType), int64(PrivilegeTypeTableAll), int64(PrivilegeTypeTableOwnership)) 7199 case PrivilegeTypeTruncate: 7200 return getSqlForCheckRoleHasPrivilegeWGOOrWithOwnerShip(int64(privType), int64(PrivilegeTypeTableAll), int64(PrivilegeTypeTableOwnership)) 7201 case PrivilegeTypeDelete: 7202 return getSqlForCheckRoleHasPrivilegeWGOOrWithOwnerShip(int64(privType), int64(PrivilegeTypeTableAll), int64(PrivilegeTypeTableOwnership)) 7203 case PrivilegeTypeReference: 7204 return getSqlForCheckRoleHasPrivilegeWGOOrWithOwnerShip(int64(privType), int64(PrivilegeTypeTableAll), int64(PrivilegeTypeTableOwnership)) 7205 case PrivilegeTypeIndex: 7206 return getSqlForCheckRoleHasPrivilegeWGOOrWithOwnerShip(int64(privType), int64(PrivilegeTypeTableAll), int64(PrivilegeTypeTableOwnership)) 7207 case PrivilegeTypeTableAll: 7208 return getSqlForCheckRoleHasPrivilegeWGOOrWithOwnerShip(int64(privType), int64(PrivilegeTypeTableAll), int64(PrivilegeTypeTableOwnership)) 7209 case PrivilegeTypeTableOwnership: 7210 return getSqlForCheckRoleHasPrivilegeWGO(int64(privType)) 7211 7212 // other privileges 7213 case PrivilegeTypeExecute: 7214 return getSqlForCheckRoleHasPrivilegeWGO(int64(privType)) 7215 case PrivilegeTypeValues: 7216 return getSqlForCheckRoleHasPrivilegeWGO(int64(privType)) 7217 7218 default: 7219 return getSqlForCheckRoleHasPrivilegeWGO(int64(privType)) 7220 } 7221 7222 } 7223 7224 // getRoleSetThatPrivilegeGrantedToWGO gets all roles that the privilege granted to with with_grant_option = true 7225 // The algorithm 3 7226 func getRoleSetThatPrivilegeGrantedToWGO(ctx context.Context, bh BackgroundExec, privType PrivilegeType) (*btree.Set[int64], error) { 7227 var err error 7228 var erArray []ExecResult 7229 var id int64 7230 rset := &btree.Set[int64]{} 7231 sql := getSqlForCheckRoleHasPrivilegeWGODependsOnPrivType(privType) 7232 bh.ClearExecResultSet() 7233 err = bh.Exec(ctx, sql) 7234 if err != nil { 7235 return nil, err 7236 } 7237 7238 erArray, err = getResultSet(ctx, bh) 7239 if err != nil { 7240 return nil, err 7241 } 7242 7243 if execResultArrayHasData(erArray) { 7244 for i := uint64(0); i < erArray[0].GetRowCount(); i++ { 7245 id, err = erArray[0].GetInt64(ctx, i, 0) 7246 if err != nil { 7247 return nil, err 7248 } 7249 rset.Insert(id) 7250 } 7251 } 7252 7253 return rset, err 7254 } 7255 7256 // setIsIntersected decides the A is intersecting the B. 7257 func setIsIntersected(A, B *btree.Set[int64]) bool { 7258 if A.Len() > B.Len() { 7259 A, B = B, A 7260 } 7261 iter := A.Iter() 7262 for x := iter.First(); x; x = iter.Next() { 7263 if B.Contains(iter.Key()) { 7264 return true 7265 } 7266 } 7267 return false 7268 } 7269 7270 // determineUserCanGrantPrivilegesToOthers decides the privileges can be granted to others. 7271 func determineUserCanGrantPrivilegesToOthers(ctx context.Context, ses *Session, gp *tree.GrantPrivilege) (ret bool, err error) { 7272 //step1: normalize the names of roles and users 7273 //step2: decide the current user 7274 account := ses.GetTenantInfo() 7275 bh := ses.GetBackgroundExec(ctx) 7276 defer bh.Close() 7277 7278 //step3: check the link: roleX -> roleA -> .... -> roleZ -> the current user. Every link has the with_grant_option. 7279 ret = true 7280 var privType PrivilegeType 7281 //the temporal set of roles during the execution 7282 var tempRoleSet *btree.Set[int64] 7283 //the set of roles that the privilege granted to with WGO=true 7284 var roleSetOfPrivilegeGrantedToWGO *btree.Set[int64] 7285 //the set of roles the (k+1) th iteration during the execution 7286 roleSetOfKPlusOneThIteration := &btree.Set[int64]{} 7287 //the set of roles the k th iteration during the execution 7288 roleSetOfKthIteration := &btree.Set[int64]{} 7289 //the set of roles visited by traversal algorithm 7290 roleSetOfVisited := &btree.Set[int64]{} 7291 //the set of roles of the current user that executes this statement or function 7292 roleSetOfCurrentUser := &btree.Set[int64]{} 7293 7294 roleSetOfCurrentUser.Insert(int64(account.GetDefaultRoleID())) 7295 7296 //put it into the single transaction 7297 err = bh.Exec(ctx, "begin;") 7298 defer func() { 7299 err = finishTxn(ctx, bh, err) 7300 }() 7301 if err != nil { 7302 return false, err 7303 } 7304 7305 //step 2: The Set R2 {the roleid granted to the userid} 7306 //If the user uses the all secondary roles, the secondary roles needed to be loaded 7307 err = loadAllSecondaryRoles(ctx, bh, account, roleSetOfCurrentUser) 7308 if err != nil { 7309 return false, err 7310 } 7311 7312 for _, priv := range gp.Privileges { 7313 privType, err = convertAstPrivilegeTypeToPrivilegeType(ctx, priv.Type, gp.ObjType) 7314 if err != nil { 7315 return false, err 7316 } 7317 7318 //call the algorithm 3. 7319 roleSetOfPrivilegeGrantedToWGO, err = getRoleSetThatPrivilegeGrantedToWGO(ctx, bh, privType) 7320 if err != nil { 7321 return false, err 7322 } 7323 7324 if setIsIntersected(roleSetOfPrivilegeGrantedToWGO, roleSetOfCurrentUser) { 7325 continue 7326 } 7327 7328 riResult := goOn 7329 for _, rx := range roleSetOfPrivilegeGrantedToWGO.Keys() { 7330 roleSetOfKthIteration.Clear() 7331 roleSetOfVisited.Clear() 7332 roleSetOfKthIteration.Insert(rx) 7333 7334 //It is kind of level traversal 7335 for roleSetOfKthIteration.Len() != 0 && riResult == goOn { 7336 roleSetOfKPlusOneThIteration.Clear() 7337 for _, ri := range roleSetOfKthIteration.Keys() { 7338 tempRoleSet, err = getRoleSetThatRoleGrantedToWGO(ctx, bh, ri, roleSetOfVisited, roleSetOfKPlusOneThIteration) 7339 if err != nil { 7340 return false, err 7341 } 7342 7343 if setIsIntersected(tempRoleSet, roleSetOfCurrentUser) { 7344 riResult = successDone 7345 break 7346 } 7347 } 7348 7349 //swap Rk,R(k+1) 7350 roleSetOfKthIteration, roleSetOfKPlusOneThIteration = roleSetOfKPlusOneThIteration, roleSetOfKthIteration 7351 } 7352 7353 if riResult == successDone { 7354 break 7355 } 7356 } 7357 if riResult != successDone { 7358 ret = false 7359 break 7360 } 7361 } 7362 return ret, err 7363 } 7364 7365 func convertAstPrivilegeTypeToPrivilegeType(ctx context.Context, priv tree.PrivilegeType, ot tree.ObjectType) (PrivilegeType, error) { 7366 var privType PrivilegeType 7367 switch priv { 7368 case tree.PRIVILEGE_TYPE_STATIC_CREATE_ACCOUNT: 7369 privType = PrivilegeTypeCreateAccount 7370 case tree.PRIVILEGE_TYPE_STATIC_DROP_ACCOUNT: 7371 privType = PrivilegeTypeDropAccount 7372 case tree.PRIVILEGE_TYPE_STATIC_ALTER_ACCOUNT: 7373 privType = PrivilegeTypeAlterAccount 7374 case tree.PRIVILEGE_TYPE_STATIC_UPGRADE_ACCOUNT: 7375 privType = PrivilegeTypeUpgradeAccount 7376 case tree.PRIVILEGE_TYPE_STATIC_CREATE_USER: 7377 privType = PrivilegeTypeCreateUser 7378 case tree.PRIVILEGE_TYPE_STATIC_DROP_USER: 7379 privType = PrivilegeTypeDropUser 7380 case tree.PRIVILEGE_TYPE_STATIC_ALTER_USER: 7381 privType = PrivilegeTypeAlterUser 7382 case tree.PRIVILEGE_TYPE_STATIC_CREATE_ROLE: 7383 privType = PrivilegeTypeCreateRole 7384 case tree.PRIVILEGE_TYPE_STATIC_DROP_ROLE: 7385 privType = PrivilegeTypeDropRole 7386 case tree.PRIVILEGE_TYPE_STATIC_ALTER_ROLE: 7387 privType = PrivilegeTypeAlterRole 7388 case tree.PRIVILEGE_TYPE_STATIC_CREATE_DATABASE: 7389 privType = PrivilegeTypeCreateDatabase 7390 case tree.PRIVILEGE_TYPE_STATIC_DROP_DATABASE: 7391 privType = PrivilegeTypeDropDatabase 7392 case tree.PRIVILEGE_TYPE_STATIC_SHOW_DATABASES: 7393 privType = PrivilegeTypeShowDatabases 7394 case tree.PRIVILEGE_TYPE_STATIC_CONNECT: 7395 privType = PrivilegeTypeConnect 7396 case tree.PRIVILEGE_TYPE_STATIC_MANAGE_GRANTS: 7397 privType = PrivilegeTypeManageGrants 7398 case tree.PRIVILEGE_TYPE_STATIC_ALL: 7399 switch ot { 7400 case tree.OBJECT_TYPE_ACCOUNT: 7401 privType = PrivilegeTypeAccountAll 7402 case tree.OBJECT_TYPE_DATABASE: 7403 privType = PrivilegeTypeDatabaseAll 7404 case tree.OBJECT_TYPE_TABLE: 7405 privType = PrivilegeTypeTableAll 7406 default: 7407 return 0, moerr.NewInternalError(ctx, `the object type "%s" do not support the privilege "%s"`, ot.String(), priv.ToString()) 7408 } 7409 case tree.PRIVILEGE_TYPE_STATIC_OWNERSHIP: 7410 switch ot { 7411 case tree.OBJECT_TYPE_DATABASE: 7412 privType = PrivilegeTypeDatabaseOwnership 7413 case tree.OBJECT_TYPE_TABLE: 7414 privType = PrivilegeTypeTableOwnership 7415 default: 7416 return 0, moerr.NewInternalError(ctx, `the object type "%s" do not support the privilege "%s"`, ot.String(), priv.ToString()) 7417 } 7418 case tree.PRIVILEGE_TYPE_STATIC_SHOW_TABLES: 7419 privType = PrivilegeTypeShowTables 7420 case tree.PRIVILEGE_TYPE_STATIC_CREATE_TABLE: 7421 privType = PrivilegeTypeCreateTable 7422 case tree.PRIVILEGE_TYPE_STATIC_DROP_TABLE: 7423 privType = PrivilegeTypeDropTable 7424 case tree.PRIVILEGE_TYPE_STATIC_CREATE_VIEW: 7425 privType = PrivilegeTypeCreateView 7426 case tree.PRIVILEGE_TYPE_STATIC_DROP_VIEW: 7427 privType = PrivilegeTypeDropView 7428 case tree.PRIVILEGE_TYPE_STATIC_ALTER_VIEW: 7429 privType = PrivilegeTypeAlterView 7430 case tree.PRIVILEGE_TYPE_STATIC_ALTER_TABLE: 7431 privType = PrivilegeTypeAlterTable 7432 case tree.PRIVILEGE_TYPE_STATIC_SELECT: 7433 privType = PrivilegeTypeSelect 7434 case tree.PRIVILEGE_TYPE_STATIC_INSERT: 7435 privType = PrivilegeTypeInsert 7436 case tree.PRIVILEGE_TYPE_STATIC_UPDATE: 7437 privType = PrivilegeTypeUpdate 7438 case tree.PRIVILEGE_TYPE_STATIC_DELETE: 7439 privType = PrivilegeTypeDelete 7440 case tree.PRIVILEGE_TYPE_STATIC_INDEX: 7441 privType = PrivilegeTypeIndex 7442 case tree.PRIVILEGE_TYPE_STATIC_EXECUTE: 7443 privType = PrivilegeTypeExecute 7444 case tree.PRIVILEGE_TYPE_STATIC_TRUNCATE: 7445 privType = PrivilegeTypeTruncate 7446 case tree.PRIVILEGE_TYPE_STATIC_REFERENCE: 7447 privType = PrivilegeTypeReference 7448 case tree.PRIVILEGE_TYPE_STATIC_VALUES: 7449 privType = PrivilegeTypeValues 7450 default: 7451 return 0, moerr.NewInternalError(ctx, "unsupported privilege type %s", priv.ToString()) 7452 } 7453 return privType, nil 7454 } 7455 7456 // authenticateUserCanExecuteStatementWithObjectTypeNone decides the user has the privilege of executing the statement with object type none 7457 func authenticateUserCanExecuteStatementWithObjectTypeNone(ctx context.Context, ses *Session, stmt tree.Statement) (bool, error) { 7458 priv := ses.GetPrivilege() 7459 if priv.objectType() != objectTypeNone { //do nothing 7460 return true, nil 7461 } 7462 tenant := ses.GetTenantInfo() 7463 7464 if priv.privilegeKind() == privilegeKindNone { // do nothing 7465 return true, nil 7466 } else if priv.privilegeKind() == privilegeKindSpecial { //GrantPrivilege, RevokePrivilege 7467 7468 checkGrantPrivilege := func(g *tree.GrantPrivilege) (bool, error) { 7469 //in the version 0.6, only the moAdmin and accountAdmin can grant the privilege. 7470 if tenant.IsAdminRole() { 7471 return true, nil 7472 } 7473 return determineUserCanGrantPrivilegesToOthers(ctx, ses, g) 7474 } 7475 7476 checkRevokePrivilege := func() (bool, error) { 7477 //in the version 0.6, only the moAdmin and accountAdmin can revoke the privilege. 7478 return tenant.IsAdminRole(), nil 7479 } 7480 7481 checkShowAccountsPrivilege := func() (bool, error) { 7482 //only the moAdmin and accountAdmin can execute the show accounts. 7483 return tenant.IsAdminRole(), nil 7484 } 7485 7486 checkBackUpStartPrivilege := func() (bool, error) { 7487 //only the moAdmin can execute the backup statement 7488 return tenant.IsSysTenant(), nil 7489 } 7490 7491 switch gp := stmt.(type) { 7492 case *tree.Grant: 7493 if gp.Typ == tree.GrantTypePrivilege { 7494 yes, err := checkGrantPrivilege(&gp.GrantPrivilege) 7495 if err != nil { 7496 return yes, err 7497 } 7498 if yes { 7499 return yes, nil 7500 } 7501 } 7502 case *tree.Revoke: 7503 if gp.Typ == tree.RevokeTypePrivilege { 7504 return checkRevokePrivilege() 7505 } 7506 case *tree.GrantPrivilege: 7507 yes, err := checkGrantPrivilege(gp) 7508 if err != nil { 7509 return yes, err 7510 } 7511 if yes { 7512 return yes, nil 7513 } 7514 case *tree.RevokePrivilege: 7515 return checkRevokePrivilege() 7516 case *tree.ShowAccounts: 7517 return checkShowAccountsPrivilege() 7518 case *tree.ShowAccountUpgrade: 7519 return tenant.IsMoAdminRole(), nil 7520 case *tree.UpgradeStatement: 7521 return tenant.IsMoAdminRole(), nil 7522 case *tree.BackupStart: 7523 return checkBackUpStartPrivilege() 7524 } 7525 } 7526 7527 return false, nil 7528 } 7529 7530 // checkSysExistsOrNot checks the SYS tenant exists or not. 7531 func checkSysExistsOrNot(ctx context.Context, bh BackgroundExec) (bool, error) { 7532 var erArray []ExecResult 7533 var err error 7534 var tableNames []string 7535 var tableName string 7536 7537 dbSql := "show databases;" 7538 bh.ClearExecResultSet() 7539 err = bh.Exec(ctx, dbSql) 7540 if err != nil { 7541 return false, err 7542 } 7543 7544 erArray, err = getResultSet(ctx, bh) 7545 if err != nil { 7546 return false, err 7547 } 7548 if len(erArray) != 1 { 7549 return false, moerr.NewInternalError(ctx, "it must have result set") 7550 } 7551 7552 for i := uint64(0); i < erArray[0].GetRowCount(); i++ { 7553 _, err = erArray[0].GetString(ctx, i, 0) 7554 if err != nil { 7555 return false, err 7556 } 7557 } 7558 7559 sql := "show tables from mo_catalog;" 7560 bh.ClearExecResultSet() 7561 err = bh.Exec(ctx, sql) 7562 if err != nil { 7563 return false, err 7564 } 7565 7566 erArray, err = getResultSet(ctx, bh) 7567 if err != nil { 7568 return false, err 7569 } 7570 if len(erArray) != 1 { 7571 return false, moerr.NewInternalError(ctx, "it must have result set") 7572 } 7573 7574 for i := uint64(0); i < erArray[0].GetRowCount(); i++ { 7575 tableName, err = erArray[0].GetString(ctx, i, 0) 7576 if err != nil { 7577 return false, err 7578 } 7579 tableNames = append(tableNames, tableName) 7580 } 7581 7582 //if there is at least one catalog table, it denotes the sys tenant exists. 7583 for _, name := range tableNames { 7584 if _, ok := sysWantedTables[name]; ok { 7585 return true, nil 7586 } 7587 } 7588 7589 return false, nil 7590 } 7591 7592 // InitSysTenantOld initializes the tenant SYS before any tenants and accepting any requests 7593 // during the system is booting. 7594 // Deprecated: Use InitSysTenant instead 7595 func InitSysTenantOld(ctx context.Context, aicm *defines.AutoIncrCacheManager, finalVersion string) (err error) { 7596 var exists bool 7597 var mp *mpool.MPool 7598 pu := config.GetParameterUnit(ctx) 7599 7600 tenant := &TenantInfo{ 7601 Tenant: sysAccountName, 7602 User: rootName, 7603 DefaultRole: moAdminRoleName, 7604 TenantID: sysAccountID, 7605 UserID: rootID, 7606 DefaultRoleID: moAdminRoleID, 7607 } 7608 7609 ctx = defines.AttachAccount(ctx, uint32(sysAccountID), uint32(rootID), uint32(moAdminRoleID)) 7610 7611 mp, err = mpool.NewMPool("init_system_tenant", 0, mpool.NoFixed) 7612 if err != nil { 7613 return err 7614 } 7615 defer mpool.DeleteMPool(mp) 7616 //Note: it is special here. The connection ctx here is ctx also. 7617 //Actually, it is ok here. the ctx is moServerCtx instead of requestCtx 7618 upstream := &Session{ 7619 feSessionImpl: feSessionImpl{ 7620 proto: &FakeProtocol{}, 7621 }, 7622 7623 seqCurValues: make(map[uint64]string), 7624 seqLastValue: new(string), 7625 } 7626 bh := NewBackgroundExec(ctx, upstream, mp) 7627 defer bh.Close() 7628 7629 //USE the mo_catalog 7630 err = bh.Exec(ctx, "use mo_catalog;") 7631 if err != nil { 7632 return err 7633 } 7634 7635 err = bh.Exec(ctx, createDbInformationSchemaSql) 7636 if err != nil { 7637 return err 7638 } 7639 7640 err = bh.Exec(ctx, "begin;") 7641 defer func() { 7642 err = finishTxn(ctx, bh, err) 7643 }() 7644 if err != nil { 7645 return err 7646 } 7647 7648 exists, err = checkSysExistsOrNot(ctx, bh) 7649 if err != nil { 7650 return err 7651 } 7652 7653 if !exists { 7654 err = createTablesInMoCatalogOld(ctx, bh, tenant, pu, finalVersion) 7655 if err != nil { 7656 return err 7657 } 7658 } 7659 7660 return err 7661 } 7662 7663 // createTablesInMoCatalogOld creates catalog tables in the database mo_catalog. 7664 // Deprecated: Use createTablesInMoCatalog instead 7665 func createTablesInMoCatalogOld(ctx context.Context, bh BackgroundExec, tenant *TenantInfo, pu *config.ParameterUnit, finalVersion string) error { 7666 var err error 7667 var initMoAccount string 7668 var initDataSqls []string 7669 if !tenant.IsSysTenant() { 7670 return moerr.NewInternalError(ctx, "only sys tenant can execute the function") 7671 } 7672 7673 addSqlIntoSet := func(sql string) { 7674 initDataSqls = append(initDataSqls, sql) 7675 } 7676 7677 //create tables for the tenant 7678 for _, sql := range createSqls { 7679 addSqlIntoSet(sql) 7680 } 7681 7682 //initialize the default data of tables for the tenant 7683 //step 1: add new tenant entry to the mo_account 7684 initMoAccount = fmt.Sprintf(initMoAccountFormat, sysAccountID, sysAccountName, sysAccountStatus, types.CurrentTimestamp().String2(time.UTC, 0), sysAccountComments, finalVersion) 7685 addSqlIntoSet(initMoAccount) 7686 7687 //step 2:add new role entries to the mo_role 7688 7689 initMoRole1 := fmt.Sprintf(initMoRoleFormat, moAdminRoleID, moAdminRoleName, rootID, moAdminRoleID, types.CurrentTimestamp().String2(time.UTC, 0), "") 7690 initMoRole2 := fmt.Sprintf(initMoRoleFormat, publicRoleID, publicRoleName, rootID, moAdminRoleID, types.CurrentTimestamp().String2(time.UTC, 0), "") 7691 addSqlIntoSet(initMoRole1) 7692 addSqlIntoSet(initMoRole2) 7693 7694 //step 3:add new user entry to the mo_user 7695 7696 defaultPassword := rootPassword 7697 if d := os.Getenv(defaultPasswordEnv); d != "" { 7698 defaultPassword = d 7699 } 7700 7701 //encryption the password 7702 encryption := HashPassWord(defaultPassword) 7703 7704 initMoUser1 := fmt.Sprintf(initMoUserFormat, rootID, rootHost, rootName, encryption, rootStatus, types.CurrentTimestamp().String2(time.UTC, 0), rootExpiredTime, rootLoginType, rootCreatorID, rootOwnerRoleID, rootDefaultRoleID) 7705 initMoUser2 := fmt.Sprintf(initMoUserFormat, dumpID, dumpHost, dumpName, encryption, dumpStatus, types.CurrentTimestamp().String2(time.UTC, 0), dumpExpiredTime, dumpLoginType, dumpCreatorID, dumpOwnerRoleID, dumpDefaultRoleID) 7706 addSqlIntoSet(initMoUser1) 7707 addSqlIntoSet(initMoUser2) 7708 7709 //step4: add new entries to the mo_role_privs 7710 //moadmin role 7711 for _, t := range entriesOfMoAdminForMoRolePrivsFor { 7712 entry := privilegeEntriesMap[t] 7713 initMoRolePriv := fmt.Sprintf(initMoRolePrivFormat, 7714 moAdminRoleID, moAdminRoleName, 7715 entry.objType, entry.objId, 7716 entry.privilegeId, entry.privilegeId.String(), entry.privilegeLevel, 7717 rootID, types.CurrentTimestamp().String2(time.UTC, 0), 7718 entry.withGrantOption) 7719 addSqlIntoSet(initMoRolePriv) 7720 } 7721 7722 //public role 7723 for _, t := range entriesOfPublicForMoRolePrivsFor { 7724 entry := privilegeEntriesMap[t] 7725 initMoRolePriv := fmt.Sprintf(initMoRolePrivFormat, 7726 publicRoleID, publicRoleName, 7727 entry.objType, entry.objId, 7728 entry.privilegeId, entry.privilegeId.String(), entry.privilegeLevel, 7729 rootID, types.CurrentTimestamp().String2(time.UTC, 0), 7730 entry.withGrantOption) 7731 addSqlIntoSet(initMoRolePriv) 7732 } 7733 7734 //step5: add new entries to the mo_user_grant 7735 7736 initMoUserGrant1 := fmt.Sprintf(initMoUserGrantFormat, moAdminRoleID, rootID, types.CurrentTimestamp().String2(time.UTC, 0), false) 7737 initMoUserGrant2 := fmt.Sprintf(initMoUserGrantFormat, publicRoleID, rootID, types.CurrentTimestamp().String2(time.UTC, 0), false) 7738 addSqlIntoSet(initMoUserGrant1) 7739 addSqlIntoSet(initMoUserGrant2) 7740 initMoUserGrant4 := fmt.Sprintf(initMoUserGrantFormat, moAdminRoleID, dumpID, types.CurrentTimestamp().String2(time.UTC, 0), false) 7741 initMoUserGrant5 := fmt.Sprintf(initMoUserGrantFormat, publicRoleID, dumpID, types.CurrentTimestamp().String2(time.UTC, 0), false) 7742 addSqlIntoSet(initMoUserGrant4) 7743 addSqlIntoSet(initMoUserGrant5) 7744 7745 //setp6: add new entries to the mo_mysql_compatibility_mode 7746 for _, variable := range gSysVarsDefs { 7747 if _, ok := configInitVariables[variable.Name]; ok { 7748 addsql := addInitSystemVariablesSql(sysAccountID, sysAccountName, variable.Name, pu) 7749 if len(addsql) != 0 { 7750 addSqlIntoSet(addsql) 7751 } 7752 } else { 7753 initMoMysqlCompatibilityMode := fmt.Sprintf(initMoMysqlCompatbilityModeWithoutDataBaseFormat, sysAccountID, sysAccountName, variable.Name, getVariableValue(variable.Default), true) 7754 addSqlIntoSet(initMoMysqlCompatibilityMode) 7755 } 7756 } 7757 7758 //fill the mo_account, mo_role, mo_user, mo_role_privs, mo_user_grant, mo_mysql_compatibility_mode 7759 for _, sql := range initDataSqls { 7760 err = bh.Exec(ctx, sql) 7761 if err != nil { 7762 return err 7763 } 7764 } 7765 return err 7766 } 7767 7768 func checkTenantExistsOrNot(ctx context.Context, bh BackgroundExec, userName string) (bool, error) { 7769 var sqlForCheckTenant string 7770 var erArray []ExecResult 7771 var err error 7772 ctx, span := trace.Debug(ctx, "checkTenantExistsOrNot") 7773 defer span.End() 7774 sqlForCheckTenant, err = getSqlForCheckTenant(ctx, userName) 7775 if err != nil { 7776 return false, err 7777 } 7778 bh.ClearExecResultSet() 7779 err = bh.Exec(ctx, sqlForCheckTenant) 7780 if err != nil { 7781 return false, err 7782 } 7783 7784 erArray, err = getResultSet(ctx, bh) 7785 if err != nil { 7786 return false, err 7787 } 7788 7789 if execResultArrayHasData(erArray) { 7790 return true, nil 7791 } 7792 return false, nil 7793 } 7794 7795 func checkDatabaseExistsOrNot(ctx context.Context, bh BackgroundExec, dbName string) (bool, error) { 7796 var sqlForCheckDatabase string 7797 var erArray []ExecResult 7798 var err error 7799 ctx, span := trace.Debug(ctx, "checkTenantExistsOrNot") 7800 defer span.End() 7801 sqlForCheckDatabase, err = getSqlForCheckDatabase(ctx, dbName) 7802 if err != nil { 7803 return false, err 7804 } 7805 bh.ClearExecResultSet() 7806 err = bh.Exec(ctx, sqlForCheckDatabase) 7807 if err != nil { 7808 return false, err 7809 } 7810 7811 erArray, err = getResultSet(ctx, bh) 7812 if err != nil { 7813 return false, err 7814 } 7815 7816 if execResultArrayHasData(erArray) { 7817 return true, nil 7818 } 7819 return false, nil 7820 } 7821 7822 type createAccount struct { 7823 IfNotExists bool 7824 Name string 7825 AdminName string 7826 IdentTyp tree.AccountIdentifiedOption 7827 IdentStr string 7828 StatusOption tree.AccountStatus 7829 Comment tree.AccountComment 7830 } 7831 7832 // InitGeneralTenant initializes the application level tenant 7833 func InitGeneralTenant(ctx context.Context, ses *Session, ca *createAccount) (err error) { 7834 var exists bool 7835 var newTenant *TenantInfo 7836 var newTenantCtx context.Context 7837 var mp *mpool.MPool 7838 ctx, span := trace.Debug(ctx, "InitGeneralTenant") 7839 defer span.End() 7840 tenant := ses.GetTenantInfo() 7841 finalVersion := ses.rm.baseService.GetFinalVersion() 7842 7843 if !(tenant.IsSysTenant() && tenant.IsMoAdminRole()) { 7844 return moerr.NewInternalError(ctx, "tenant %s user %s role %s do not have the privilege to create the new account", tenant.GetTenant(), tenant.GetUser(), tenant.GetDefaultRole()) 7845 } 7846 7847 //normalize the name 7848 err = normalizeNameOfAccount(ctx, ca) 7849 if err != nil { 7850 return err 7851 } 7852 7853 ca.AdminName, err = normalizeName(ctx, ca.AdminName) 7854 if err != nil { 7855 return err 7856 } 7857 7858 if ca.IdentTyp == tree.AccountIdentifiedByPassword { 7859 if len(ca.IdentStr) == 0 { 7860 return moerr.NewInternalError(ctx, "password is empty string") 7861 } 7862 } 7863 7864 ctx = defines.AttachAccount(ctx, uint32(tenant.GetTenantID()), uint32(tenant.GetUserID()), uint32(tenant.GetDefaultRoleID())) 7865 7866 _, st := trace.Debug(ctx, "InitGeneralTenant.init_general_tenant") 7867 mp, err = mpool.NewMPool("init_general_tenant", 0, mpool.NoFixed) 7868 if err != nil { 7869 st.End() 7870 return err 7871 } 7872 st.End() 7873 defer mpool.DeleteMPool(mp) 7874 7875 bh := ses.GetBackgroundExec(ctx) 7876 defer bh.Close() 7877 7878 createNewAccount := func() (rtnErr error) { 7879 rtnErr = bh.Exec(ctx, "begin;") 7880 defer func() { 7881 rtnErr = finishTxn(ctx, bh, rtnErr) 7882 }() 7883 if rtnErr != nil { 7884 return rtnErr 7885 } 7886 7887 //USE the mo_catalog 7888 // MOVE into txn, make sure only create ONE txn. 7889 rtnErr = bh.Exec(ctx, "use mo_catalog;") 7890 if rtnErr != nil { 7891 return rtnErr 7892 } 7893 7894 // check account exists or not 7895 exists, rtnErr = checkTenantExistsOrNot(ctx, bh, ca.Name) 7896 if rtnErr != nil { 7897 return rtnErr 7898 } 7899 7900 if exists { 7901 if !ca.IfNotExists { //do nothing 7902 return moerr.NewInternalError(ctx, "the tenant %s exists", ca.Name) 7903 } 7904 return rtnErr 7905 } else { 7906 newTenant, newTenantCtx, rtnErr = createTablesInMoCatalogOfGeneralTenant(ctx, bh, finalVersion, ca) 7907 if rtnErr != nil { 7908 return rtnErr 7909 } 7910 } 7911 7912 // create some tables and databases for new account 7913 rtnErr = bh.Exec(newTenantCtx, createMoIndexesSql) 7914 if rtnErr != nil { 7915 return rtnErr 7916 } 7917 7918 rtnErr = bh.Exec(newTenantCtx, createMoTablePartitionsSql) 7919 if rtnErr != nil { 7920 return rtnErr 7921 } 7922 7923 rtnErr = bh.Exec(newTenantCtx, createAutoTableSql) 7924 if rtnErr != nil { 7925 return rtnErr 7926 } 7927 7928 rtnErr = bh.Exec(newTenantCtx, createMoForeignKeysSql) 7929 if rtnErr != nil { 7930 return rtnErr 7931 } 7932 7933 //create createDbSqls 7934 createDbSqls := []string{ 7935 "create database " + motrace.SystemDBConst + ";", 7936 "create database " + mometric.MetricDBConst + ";", 7937 createDbInformationSchemaSql, 7938 "create database mysql;", 7939 } 7940 for _, db := range createDbSqls { 7941 rtnErr = bh.Exec(newTenantCtx, db) 7942 if rtnErr != nil { 7943 return rtnErr 7944 } 7945 } 7946 7947 // create tables for new account 7948 rtnErr = createTablesInMoCatalogOfGeneralTenant2(bh, ca, newTenantCtx, newTenant, getGlobalPu()) 7949 if rtnErr != nil { 7950 return rtnErr 7951 } 7952 rtnErr = createTablesInSystemOfGeneralTenant(newTenantCtx, bh, newTenant) 7953 if rtnErr != nil { 7954 return rtnErr 7955 } 7956 rtnErr = createTablesInInformationSchemaOfGeneralTenant(newTenantCtx, bh) 7957 if rtnErr != nil { 7958 return rtnErr 7959 } 7960 return rtnErr 7961 } 7962 7963 err = createNewAccount() 7964 if err != nil { 7965 return err 7966 } 7967 7968 if !exists { 7969 //just skip nonexistent pubs 7970 _ = createSubscriptionDatabase(ctx, bh, newTenant, ses) 7971 } 7972 7973 return err 7974 } 7975 7976 // createTablesInMoCatalogOfGeneralTenant creates catalog tables in the database mo_catalog. 7977 func createTablesInMoCatalogOfGeneralTenant(ctx context.Context, bh BackgroundExec, finalVersion string, ca *createAccount) (*TenantInfo, context.Context, error) { 7978 var err error 7979 var initMoAccount string 7980 var erArray []ExecResult 7981 var newTenantID int64 7982 var newUserId int64 7983 var comment = "" 7984 var newTenant *TenantInfo 7985 var newTenantCtx context.Context 7986 var sql string 7987 //var configuration string 7988 //var sql string 7989 ctx, span := trace.Debug(ctx, "createTablesInMoCatalogOfGeneralTenant") 7990 defer span.End() 7991 7992 if nameIsInvalid(ca.Name) { 7993 return nil, nil, moerr.NewInternalError(ctx, "the account name is invalid") 7994 } 7995 7996 if nameIsInvalid(ca.AdminName) { 7997 return nil, nil, moerr.NewInternalError(ctx, "the admin name is invalid") 7998 } 7999 8000 //!!!NOTE : Insert into mo_account with original context. 8001 // Other operations with a new context with new tenant info 8002 //step 1: add new tenant entry to the mo_account 8003 if ca.Comment.Exist { 8004 comment = ca.Comment.Comment 8005 } 8006 8007 //determine the status of the account 8008 status := sysAccountStatus 8009 if ca.StatusOption.Exist { 8010 if ca.StatusOption.Option == tree.AccountStatusSuspend { 8011 status = tree.AccountStatusSuspend.String() 8012 } 8013 } 8014 8015 initMoAccount = fmt.Sprintf(initMoAccountWithoutIDFormat, ca.Name, ca.AdminName, status, types.CurrentTimestamp().String2(time.UTC, 0), comment, finalVersion) 8016 //execute the insert 8017 err = bh.Exec(ctx, initMoAccount) 8018 if err != nil { 8019 return nil, nil, err 8020 } 8021 8022 //query the tenant id 8023 bh.ClearExecResultSet() 8024 sql, err = getSqlForCheckTenant(ctx, ca.Name) 8025 if err != nil { 8026 return nil, nil, err 8027 } 8028 err = bh.Exec(ctx, sql) 8029 if err != nil { 8030 return nil, nil, err 8031 } 8032 8033 erArray, err = getResultSet(ctx, bh) 8034 if err != nil { 8035 return nil, nil, err 8036 } 8037 8038 if execResultArrayHasData(erArray) { 8039 newTenantID, err = erArray[0].GetInt64(ctx, 0, 0) 8040 if err != nil { 8041 return nil, nil, err 8042 } 8043 } else { 8044 return nil, nil, moerr.NewInternalError(ctx, "get the id of tenant %s failed", ca.Name) 8045 } 8046 8047 newUserId = int64(GetAdminUserId()) 8048 8049 newTenant = &TenantInfo{ 8050 Tenant: ca.Name, 8051 User: ca.AdminName, 8052 DefaultRole: accountAdminRoleName, 8053 TenantID: uint32(newTenantID), 8054 UserID: uint32(newUserId), 8055 DefaultRoleID: accountAdminRoleID, 8056 } 8057 //with new tenant 8058 newTenantCtx = defines.AttachAccount(ctx, uint32(newTenantID), uint32(newUserId), uint32(accountAdminRoleID)) 8059 return newTenant, newTenantCtx, err 8060 } 8061 8062 func createTablesInMoCatalogOfGeneralTenant2(bh BackgroundExec, ca *createAccount, newTenantCtx context.Context, newTenant *TenantInfo, pu *config.ParameterUnit) error { 8063 var err error 8064 var initDataSqls []string 8065 newTenantCtx, span := trace.Debug(newTenantCtx, "createTablesInMoCatalogOfGeneralTenant2") 8066 defer span.End() 8067 //create tables for the tenant 8068 for _, sql := range createSqls { 8069 //only the SYS tenant has the table mo_account 8070 if strings.HasPrefix(sql, "create table mo_catalog.mo_account") { 8071 continue 8072 } 8073 err = bh.Exec(newTenantCtx, sql) 8074 if err != nil { 8075 return err 8076 } 8077 } 8078 8079 //initialize the default data of tables for the tenant 8080 addSqlIntoSet := func(sql string) { 8081 initDataSqls = append(initDataSqls, sql) 8082 } 8083 //step 2:add new role entries to the mo_role 8084 initMoRole1 := fmt.Sprintf(initMoRoleFormat, accountAdminRoleID, accountAdminRoleName, newTenant.GetUserID(), newTenant.GetDefaultRoleID(), types.CurrentTimestamp().String2(time.UTC, 0), "") 8085 initMoRole2 := fmt.Sprintf(initMoRoleFormat, publicRoleID, publicRoleName, newTenant.GetUserID(), newTenant.GetDefaultRoleID(), types.CurrentTimestamp().String2(time.UTC, 0), "") 8086 addSqlIntoSet(initMoRole1) 8087 addSqlIntoSet(initMoRole2) 8088 8089 //step 3:add new user entry to the mo_user 8090 if ca.IdentTyp != tree.AccountIdentifiedByPassword { 8091 err = moerr.NewInternalError(newTenantCtx, "only support password verification now") 8092 return err 8093 } 8094 name := ca.AdminName 8095 password := ca.IdentStr 8096 if len(password) == 0 { 8097 err = moerr.NewInternalError(newTenantCtx, "password is empty string") 8098 return err 8099 } 8100 //encryption the password 8101 encryption := HashPassWord(password) 8102 status := rootStatus 8103 //TODO: fix the status of user or account 8104 if ca.StatusOption.Exist { 8105 if ca.StatusOption.Option == tree.AccountStatusSuspend { 8106 status = tree.AccountStatusSuspend.String() 8107 } 8108 } 8109 //the first user id in the general tenant 8110 initMoUser1 := fmt.Sprintf(initMoUserFormat, newTenant.GetUserID(), rootHost, name, encryption, status, 8111 types.CurrentTimestamp().String2(time.UTC, 0), rootExpiredTime, rootLoginType, 8112 newTenant.GetUserID(), newTenant.GetDefaultRoleID(), accountAdminRoleID) 8113 addSqlIntoSet(initMoUser1) 8114 8115 //step4: add new entries to the mo_role_privs 8116 //accountadmin role 8117 for _, t := range entriesOfAccountAdminForMoRolePrivsFor { 8118 entry := privilegeEntriesMap[t] 8119 initMoRolePriv := fmt.Sprintf(initMoRolePrivFormat, 8120 accountAdminRoleID, accountAdminRoleName, 8121 entry.objType, entry.objId, 8122 entry.privilegeId, entry.privilegeId.String(), entry.privilegeLevel, 8123 newTenant.GetUserID(), types.CurrentTimestamp().String2(time.UTC, 0), 8124 entry.withGrantOption) 8125 addSqlIntoSet(initMoRolePriv) 8126 } 8127 8128 //public role 8129 for _, t := range entriesOfPublicForMoRolePrivsFor { 8130 entry := privilegeEntriesMap[t] 8131 initMoRolePriv := fmt.Sprintf(initMoRolePrivFormat, 8132 publicRoleID, publicRoleName, 8133 entry.objType, entry.objId, 8134 entry.privilegeId, entry.privilegeId.String(), entry.privilegeLevel, 8135 newTenant.GetUserID(), types.CurrentTimestamp().String2(time.UTC, 0), 8136 entry.withGrantOption) 8137 addSqlIntoSet(initMoRolePriv) 8138 } 8139 8140 //step5: add new entries to the mo_user_grant 8141 initMoUserGrant1 := fmt.Sprintf(initMoUserGrantFormat, accountAdminRoleID, newTenant.GetUserID(), types.CurrentTimestamp().String2(time.UTC, 0), true) 8142 addSqlIntoSet(initMoUserGrant1) 8143 initMoUserGrant2 := fmt.Sprintf(initMoUserGrantFormat, publicRoleID, newTenant.GetUserID(), types.CurrentTimestamp().String2(time.UTC, 0), true) 8144 addSqlIntoSet(initMoUserGrant2) 8145 8146 //setp6: add new entries to the mo_mysql_compatibility_mode 8147 for _, variable := range gSysVarsDefs { 8148 if _, ok := configInitVariables[variable.Name]; ok { 8149 addsql := addInitSystemVariablesSql(int(newTenant.GetTenantID()), newTenant.GetTenant(), variable.Name, pu) 8150 if len(addsql) != 0 { 8151 addSqlIntoSet(addsql) 8152 } 8153 } else { 8154 initMoMysqlCompatibilityMode := fmt.Sprintf(initMoMysqlCompatbilityModeWithoutDataBaseFormat, newTenant.GetTenantID(), newTenant.GetTenant(), variable.Name, getVariableValue(variable.Default), true) 8155 addSqlIntoSet(initMoMysqlCompatibilityMode) 8156 } 8157 } 8158 8159 //fill the mo_role, mo_user, mo_role_privs, mo_user_grant, mo_role_grant 8160 for _, sql := range initDataSqls { 8161 bh.ClearExecResultSet() 8162 err = bh.Exec(newTenantCtx, sql) 8163 if err != nil { 8164 return err 8165 } 8166 } 8167 return nil 8168 } 8169 8170 // createTablesInSystemOfGeneralTenant creates the database system and system_metrics as the external tables. 8171 func createTablesInSystemOfGeneralTenant(ctx context.Context, bh BackgroundExec, newTenant *TenantInfo) error { 8172 ctx, span := trace.Debug(ctx, "createTablesInSystemOfGeneralTenant") 8173 defer span.End() 8174 8175 var err error 8176 sqls := make([]string, 0) 8177 sqls = append(sqls, "use "+motrace.SystemDBConst+";") 8178 traceTables := motrace.GetSchemaForAccount(ctx, newTenant.GetTenant()) 8179 sqls = append(sqls, traceTables...) 8180 sqls = append(sqls, "use "+mometric.MetricDBConst+";") 8181 metricTables := mometric.GetSchemaForAccount(ctx, newTenant.GetTenant()) 8182 sqls = append(sqls, metricTables...) 8183 8184 for _, sql := range sqls { 8185 bh.ClearExecResultSet() 8186 err = bh.Exec(ctx, sql) 8187 if err != nil { 8188 return err 8189 } 8190 } 8191 return err 8192 } 8193 8194 // createTablesInInformationSchemaOfGeneralTenant creates the database information_schema and the views or tables. 8195 func createTablesInInformationSchemaOfGeneralTenant(ctx context.Context, bh BackgroundExec) error { 8196 ctx, span := trace.Debug(ctx, "createTablesInInformationSchemaOfGeneralTenant") 8197 defer span.End() 8198 //with new tenant 8199 //TODO: when we have the auto_increment column, we need new strategy. 8200 8201 var err error 8202 sqls := make([]string, 0, len(sysview.InitInformationSchemaSysTables)+len(sysview.InitMysqlSysTables)+4) 8203 8204 sqls = append(sqls, "use information_schema;") 8205 sqls = append(sqls, sysview.InitInformationSchemaSysTables...) 8206 sqls = append(sqls, "use mysql;") 8207 sqls = append(sqls, sysview.InitMysqlSysTables...) 8208 8209 for _, sql := range sqls { 8210 bh.ClearExecResultSet() 8211 err = bh.Exec(ctx, sql) 8212 if err != nil { 8213 return err 8214 } 8215 } 8216 return err 8217 } 8218 8219 // create subscription database 8220 func createSubscriptionDatabase(ctx context.Context, bh BackgroundExec, newTenant *TenantInfo, ses *Session) error { 8221 ctx, span := trace.Debug(ctx, "createSubscriptionDatabase") 8222 defer span.End() 8223 8224 var err error 8225 subscriptions := make([]string, 0) 8226 //process the syspublications 8227 syspublications_value, err := ses.GetGlobalVar(ctx, "syspublications") 8228 if err != nil { 8229 return err 8230 } 8231 8232 if syspublications, ok := syspublications_value.(string); ok { 8233 if len(syspublications) == 0 { 8234 return err 8235 } 8236 subscriptions = strings.Split(syspublications, ",") 8237 } 8238 // if no subscriptions, return 8239 if len(subscriptions) == 0 { 8240 return err 8241 } 8242 8243 //with new tenant 8244 ctx = defines.AttachAccount(ctx, uint32(newTenant.GetTenantID()), uint32(newTenant.GetUserID()), uint32(newTenant.GetDefaultRoleID())) 8245 8246 createSubscriptionFormat := `create database %s from sys publication %s;` 8247 sqls := make([]string, 0, len(subscriptions)) 8248 for _, subscription := range subscriptions { 8249 sqls = append(sqls, fmt.Sprintf(createSubscriptionFormat, subscription, subscription)) 8250 } 8251 for _, sql := range sqls { 8252 bh.ClearExecResultSet() 8253 err = bh.Exec(ctx, sql) 8254 if err != nil { 8255 return err 8256 } 8257 } 8258 return err 8259 } 8260 8261 type createUser struct { 8262 IfNotExists bool 8263 Users []*user 8264 Role *tree.Role 8265 MiscOpt tree.UserMiscOption 8266 // comment or attribute 8267 CommentOrAttribute tree.AccountCommentOrAttribute 8268 } 8269 8270 // InitUser creates new user for the tenant 8271 func InitUser(ctx context.Context, ses *Session, tenant *TenantInfo, cu *createUser) (err error) { 8272 var exists int 8273 var erArray []ExecResult 8274 var newUserId int64 8275 var host string 8276 var newRoleId int64 8277 var status string 8278 var sql string 8279 var mp *mpool.MPool 8280 8281 for _, u := range cu.Users { 8282 u.Username, err = normalizeName(ctx, u.Username) 8283 if err != nil { 8284 return err 8285 } 8286 } 8287 8288 if cu.Role != nil { 8289 err = normalizeNameOfRole(ctx, cu.Role) 8290 if err != nil { 8291 return err 8292 } 8293 } 8294 8295 mp, err = mpool.NewMPool("init_user", 0, mpool.NoFixed) 8296 if err != nil { 8297 return err 8298 } 8299 defer mpool.DeleteMPool(mp) 8300 8301 bh := ses.GetBackgroundExec(ctx) 8302 defer bh.Close() 8303 8304 err = bh.Exec(ctx, "begin;") 8305 defer func() { 8306 err = finishTxn(ctx, bh, err) 8307 }() 8308 if err != nil { 8309 return err 8310 } 8311 8312 //TODO: get role and the id of role 8313 newRoleId = publicRoleID 8314 if cu.Role != nil { 8315 sql, err = getSqlForRoleIdOfRole(ctx, cu.Role.UserName) 8316 if err != nil { 8317 return err 8318 } 8319 bh.ClearExecResultSet() 8320 err = bh.Exec(ctx, sql) 8321 if err != nil { 8322 return err 8323 } 8324 erArray, err = getResultSet(ctx, bh) 8325 if err != nil { 8326 return err 8327 } 8328 if !execResultArrayHasData(erArray) { 8329 return moerr.NewInternalError(ctx, "there is no role %s", cu.Role.UserName) 8330 } 8331 newRoleId, err = erArray[0].GetInt64(ctx, 0, 0) 8332 if err != nil { 8333 return err 8334 } 8335 8336 from := &verifiedRole{ 8337 typ: roleType, 8338 name: cu.Role.UserName, 8339 } 8340 8341 for _, user := range cu.Users { 8342 to := &verifiedRole{ 8343 typ: userType, 8344 name: user.Username, 8345 } 8346 err = verifySpecialRolesInGrant(ctx, tenant, from, to) 8347 if err != nil { 8348 return err 8349 } 8350 } 8351 } 8352 8353 //TODO: get password_option or lock_option. there is no field in mo_user to store it. 8354 status = userStatusUnlock 8355 if cu.MiscOpt != nil { 8356 if _, ok := cu.MiscOpt.(*tree.UserMiscOptionAccountLock); ok { 8357 status = userStatusLock 8358 } 8359 } 8360 8361 for _, user := range cu.Users { 8362 //dedup with user 8363 sql, err = getSqlForPasswordOfUser(ctx, user.Username) 8364 if err != nil { 8365 return err 8366 } 8367 bh.ClearExecResultSet() 8368 err = bh.Exec(ctx, sql) 8369 if err != nil { 8370 return err 8371 } 8372 8373 erArray, err = getResultSet(ctx, bh) 8374 if err != nil { 8375 return err 8376 } 8377 exists = 0 8378 if execResultArrayHasData(erArray) { 8379 exists = 1 8380 } 8381 8382 //dedup with the role 8383 if exists == 0 { 8384 sql, err = getSqlForRoleIdOfRole(ctx, user.Username) 8385 if err != nil { 8386 return err 8387 } 8388 bh.ClearExecResultSet() 8389 err = bh.Exec(ctx, sql) 8390 if err != nil { 8391 return err 8392 } 8393 8394 erArray, err = getResultSet(ctx, bh) 8395 if err != nil { 8396 return err 8397 } 8398 if execResultArrayHasData(erArray) { 8399 exists = 2 8400 } 8401 } 8402 8403 if exists != 0 { 8404 if cu.IfNotExists { //do nothing 8405 continue 8406 } 8407 if exists == 1 { 8408 err = moerr.NewInternalError(ctx, "the user %s exists", user.Username) 8409 } else if exists == 2 { 8410 err = moerr.NewInternalError(ctx, "there is a role with the same name as the user") 8411 } 8412 8413 return err 8414 } 8415 8416 if !user.AuthExist { 8417 return moerr.NewInternalError(ctx, "the user %s misses the auth_option", user.Username) 8418 } 8419 8420 if user.IdentTyp != tree.AccountIdentifiedByPassword { 8421 return moerr.NewInternalError(ctx, "only support password verification now") 8422 } 8423 8424 password := user.IdentStr 8425 if len(password) == 0 { 8426 return moerr.NewInternalError(ctx, "password is empty string") 8427 } 8428 8429 //encryption the password 8430 encryption := HashPassWord(password) 8431 8432 //TODO: get comment or attribute. there is no field in mo_user to store it. 8433 host = user.Hostname 8434 if len(user.Hostname) == 0 || user.Hostname == "%" { 8435 host = rootHost 8436 } 8437 initMoUser1 := fmt.Sprintf(initMoUserWithoutIDFormat, host, user.Username, encryption, status, 8438 types.CurrentTimestamp().String2(time.UTC, 0), rootExpiredTime, rootLoginType, 8439 tenant.GetUserID(), tenant.GetDefaultRoleID(), newRoleId) 8440 8441 bh.ClearExecResultSet() 8442 err = bh.Exec(ctx, initMoUser1) 8443 if err != nil { 8444 return err 8445 } 8446 8447 //query the id 8448 bh.ClearExecResultSet() 8449 sql, err = getSqlForPasswordOfUser(ctx, user.Username) 8450 if err != nil { 8451 return err 8452 } 8453 err = bh.Exec(ctx, sql) 8454 if err != nil { 8455 return err 8456 } 8457 8458 erArray, err = getResultSet(ctx, bh) 8459 if err != nil { 8460 return err 8461 } 8462 8463 if !execResultArrayHasData(erArray) { 8464 return moerr.NewInternalError(ctx, "get the id of user %s failed", user.Username) 8465 } 8466 newUserId, err = erArray[0].GetInt64(ctx, 0, 0) 8467 if err != nil { 8468 return err 8469 } 8470 8471 initMoUserGrant1 := fmt.Sprintf(initMoUserGrantFormat, newRoleId, newUserId, types.CurrentTimestamp().String2(time.UTC, 0), true) 8472 err = bh.Exec(ctx, initMoUserGrant1) 8473 if err != nil { 8474 return err 8475 } 8476 8477 //if it is not public role, just insert the record for public 8478 if newRoleId != publicRoleID { 8479 initMoUserGrant2 := fmt.Sprintf(initMoUserGrantFormat, publicRoleID, newUserId, types.CurrentTimestamp().String2(time.UTC, 0), true) 8480 err = bh.Exec(ctx, initMoUserGrant2) 8481 if err != nil { 8482 return err 8483 } 8484 } 8485 } 8486 return err 8487 } 8488 8489 // InitRole creates the new role 8490 func InitRole(ctx context.Context, ses *Session, tenant *TenantInfo, cr *tree.CreateRole) (err error) { 8491 var exists int 8492 var erArray []ExecResult 8493 var sql string 8494 err = normalizeNamesOfRoles(ctx, cr.Roles) 8495 if err != nil { 8496 return err 8497 } 8498 8499 bh := ses.GetBackgroundExec(ctx) 8500 defer bh.Close() 8501 8502 err = bh.Exec(ctx, "begin;") 8503 defer func() { 8504 err = finishTxn(ctx, bh, err) 8505 }() 8506 if err != nil { 8507 return err 8508 } 8509 8510 for _, r := range cr.Roles { 8511 exists = 0 8512 if isPredefinedRole(r.UserName) { 8513 exists = 3 8514 } else { 8515 //dedup with role 8516 sql, err = getSqlForRoleIdOfRole(ctx, r.UserName) 8517 if err != nil { 8518 return err 8519 } 8520 bh.ClearExecResultSet() 8521 err = bh.Exec(ctx, sql) 8522 if err != nil { 8523 return err 8524 } 8525 8526 erArray, err = getResultSet(ctx, bh) 8527 if err != nil { 8528 return err 8529 } 8530 if execResultArrayHasData(erArray) { 8531 exists = 1 8532 } 8533 8534 //dedup with user 8535 if exists == 0 { 8536 sql, err = getSqlForPasswordOfUser(ctx, r.UserName) 8537 if err != nil { 8538 return err 8539 } 8540 bh.ClearExecResultSet() 8541 err = bh.Exec(ctx, sql) 8542 if err != nil { 8543 return err 8544 } 8545 8546 erArray, err = getResultSet(ctx, bh) 8547 if err != nil { 8548 return err 8549 } 8550 if execResultArrayHasData(erArray) { 8551 exists = 2 8552 } 8553 } 8554 } 8555 8556 if exists != 0 { 8557 if cr.IfNotExists { 8558 continue 8559 } 8560 if exists == 1 { 8561 err = moerr.NewInternalError(ctx, "the role %s exists", r.UserName) 8562 } else if exists == 2 { 8563 err = moerr.NewInternalError(ctx, "there is a user with the same name as the role %s", r.UserName) 8564 } else if exists == 3 { 8565 err = moerr.NewInternalError(ctx, "can not use the name %s. it is the name of the predefined role", r.UserName) 8566 } 8567 8568 return err 8569 } 8570 8571 initMoRole := fmt.Sprintf(initMoRoleWithoutIDFormat, r.UserName, tenant.GetUserID(), tenant.GetDefaultRoleID(), 8572 types.CurrentTimestamp().String2(time.UTC, 0), "") 8573 err = bh.Exec(ctx, initMoRole) 8574 if err != nil { 8575 return err 8576 } 8577 } 8578 return err 8579 } 8580 8581 func Upload(ses FeSession, execCtx *ExecCtx, localPath string, storageDir string) (string, error) { 8582 loadLocalReader, loadLocalWriter := io.Pipe() 8583 8584 // watch and cancel 8585 // TODO use context.AfterFunc in go1.21 8586 funcCtx, cancel := context.WithCancel(execCtx.reqCtx) 8587 defer cancel() 8588 go func() { 8589 defer loadLocalReader.Close() 8590 8591 <-funcCtx.Done() 8592 }() 8593 8594 // write to pipe 8595 loadLocalErrGroup := new(errgroup.Group) 8596 loadLocalErrGroup.Go(func() error { 8597 param := &tree.ExternParam{ 8598 ExParamConst: tree.ExParamConst{ 8599 Filepath: localPath, 8600 }, 8601 } 8602 return processLoadLocal(ses, execCtx, param, loadLocalWriter) 8603 }) 8604 8605 // read from pipe and upload 8606 ioVector := fileservice.IOVector{ 8607 FilePath: fileservice.JoinPath(defines.SharedFileServiceName, path.Join("udf", storageDir, localPath[strings.LastIndex(localPath, "/")+1:])), 8608 Entries: []fileservice.IOEntry{ 8609 { 8610 Size: -1, 8611 ReaderForWrite: loadLocalReader, 8612 }, 8613 }, 8614 } 8615 8616 fileService := getGlobalPu().FileService 8617 _ = fileService.Delete(execCtx.reqCtx, ioVector.FilePath) 8618 err := fileService.Write(execCtx.reqCtx, ioVector) 8619 err = errors.Join(err, loadLocalErrGroup.Wait()) 8620 if err != nil { 8621 return "", err 8622 } 8623 8624 return ioVector.FilePath, nil 8625 } 8626 8627 func InitFunction(ses *Session, execCtx *ExecCtx, tenant *TenantInfo, cf *tree.CreateFunction) (err error) { 8628 var initMoUdf string 8629 var retTypeStr string 8630 var dbName string 8631 var dbExists bool 8632 var checkExistence string 8633 var argsJson []byte 8634 var argsCondition string 8635 var fmtctx *tree.FmtCtx 8636 var argList []*function.Arg 8637 var typeList []string 8638 var erArray []ExecResult 8639 8640 // a database must be selected or specified as qualifier when create a function 8641 if cf.Name.HasNoNameQualifier() { 8642 if ses.DatabaseNameIsEmpty() { 8643 return moerr.NewNoDBNoCtx() 8644 } 8645 dbName = ses.GetDatabaseName() 8646 } else { 8647 dbName = string(cf.Name.Name.SchemaName) 8648 } 8649 8650 // authticate db exists 8651 dbExists, err = checkDatabaseExistsOrNot(execCtx.reqCtx, ses.GetBackgroundExec(execCtx.reqCtx), dbName) 8652 if err != nil { 8653 return err 8654 } 8655 if !dbExists { 8656 return moerr.NewBadDB(execCtx.reqCtx, dbName) 8657 } 8658 8659 bh := ses.GetBackgroundExec(execCtx.reqCtx) 8660 defer bh.Close() 8661 8662 // format return type 8663 fmtctx = tree.NewFmtCtx(dialect.MYSQL, tree.WithQuoteString(true)) 8664 retTypeStr, err = plan2.GetFunctionTypeStrFromAst(cf.ReturnType.Type) 8665 if err != nil { 8666 return err 8667 } 8668 8669 // build argmap and marshal as json 8670 argList = make([]*function.Arg, len(cf.Args)) 8671 typeList = make([]string, len(cf.Args)) 8672 for i := 0; i < len(cf.Args); i++ { 8673 argList[i] = &function.Arg{} 8674 argList[i].Name = cf.Args[i].GetName(fmtctx) 8675 fmtctx.Reset() 8676 typ, err := plan2.GetFunctionArgTypeStrFromAst(cf.Args[i]) 8677 if err != nil { 8678 return err 8679 } 8680 argList[i].Type = typ 8681 typeList[i] = typ 8682 } 8683 argsJson, err = json.Marshal(argList) 8684 if err != nil { 8685 return err 8686 } 8687 8688 if len(typeList) == 0 { 8689 argsCondition = "is null" 8690 } else if len(typeList) == 1 { 8691 argsCondition = fmt.Sprintf(`= '"%v"'`, typeList[0]) 8692 } else { 8693 typesJson, _ := json.Marshal(typeList) 8694 argsCondition = fmt.Sprintf(`= '%v'`, string(typesJson)) 8695 } 8696 8697 // validate duplicate function declaration 8698 bh.ClearExecResultSet() 8699 checkExistence = fmt.Sprintf(checkUdfExistence, string(cf.Name.Name.ObjectName), dbName, argsCondition) 8700 err = bh.Exec(execCtx.reqCtx, checkExistence) 8701 if err != nil { 8702 return err 8703 } 8704 8705 erArray, err = getResultSet(execCtx.reqCtx, bh) 8706 if err != nil { 8707 return err 8708 } 8709 8710 if execResultArrayHasData(erArray) && !cf.Replace { 8711 return moerr.NewUDFAlreadyExistsNoCtx(string(cf.Name.Name.ObjectName)) 8712 } 8713 8714 err = bh.Exec(execCtx.reqCtx, "begin;") 8715 defer func() { 8716 err = finishTxn(execCtx.reqCtx, bh, err) 8717 }() 8718 if err != nil { 8719 return err 8720 } 8721 8722 var body string 8723 if cf.Language == string(tree.SQL) { 8724 body = cf.Body 8725 } else { 8726 if cf.Import { 8727 // check 8728 if cf.Language == string(tree.PYTHON) { 8729 if !strings.HasSuffix(cf.Body, ".py") && 8730 !strings.HasSuffix(cf.Body, ".whl") { 8731 return moerr.NewInvalidInput(execCtx.reqCtx, "file '"+cf.Body+"', only support '*.py', '*.whl'") 8732 } 8733 if strings.HasSuffix(cf.Body, ".whl") { 8734 dotIdx := strings.LastIndex(cf.Handler, ".") 8735 if dotIdx < 1 { 8736 return moerr.NewInvalidInput(execCtx.reqCtx, "handler '"+cf.Handler+"', when you import a *.whl, the handler should be in the format of '<file or module name>.<function name>'") 8737 } 8738 } 8739 } 8740 // upload 8741 storageDir := string(cf.Name.Name.ObjectName) + "_" + strings.Join(typeList, "-") + "_" 8742 cf.Body, err = Upload(ses, execCtx, cf.Body, storageDir) 8743 if err != nil { 8744 return err 8745 } 8746 } 8747 8748 nb := function.NonSqlUdfBody{ 8749 Handler: cf.Handler, 8750 Import: cf.Import, 8751 Body: cf.Body, 8752 } 8753 var byt []byte 8754 byt, err = json.Marshal(nb) 8755 if err != nil { 8756 return err 8757 } 8758 body = strconv.Quote(string(byt)) 8759 body = body[1 : len(body)-1] 8760 } 8761 8762 if execResultArrayHasData(erArray) { // replace 8763 var id int64 8764 id, err = erArray[0].GetInt64(execCtx.reqCtx, 0, 0) 8765 if err != nil { 8766 return err 8767 } 8768 initMoUdf = fmt.Sprintf(updateMoUserDefinedFunctionFormat, 8769 ses.GetTenantInfo().GetDefaultRoleID(), 8770 string(argsJson), 8771 retTypeStr, body, cf.Language, 8772 tenant.GetUser(), types.CurrentTimestamp().String2(time.UTC, 0), "FUNCTION", "DEFINER", "", "utf8mb4", "utf8mb4_0900_ai_ci", "utf8mb4_0900_ai_ci", 8773 int32(id)) 8774 } else { // create 8775 initMoUdf = fmt.Sprintf(initMoUserDefinedFunctionFormat, 8776 string(cf.Name.Name.ObjectName), 8777 ses.GetTenantInfo().GetDefaultRoleID(), 8778 string(argsJson), 8779 retTypeStr, body, cf.Language, dbName, 8780 tenant.GetUser(), types.CurrentTimestamp().String2(time.UTC, 0), types.CurrentTimestamp().String2(time.UTC, 0), "FUNCTION", "DEFINER", "", "utf8mb4", "utf8mb4_0900_ai_ci", "utf8mb4_0900_ai_ci") 8781 } 8782 8783 err = bh.Exec(execCtx.reqCtx, initMoUdf) 8784 if err != nil { 8785 return err 8786 } 8787 8788 return err 8789 } 8790 8791 func InitProcedure(ctx context.Context, ses *Session, tenant *TenantInfo, cp *tree.CreateProcedure) (err error) { 8792 var initMoProcedure string 8793 var dbName string 8794 var checkExistence string 8795 var argsJson []byte 8796 // var fmtctx *tree.FmtCtx 8797 var erArray []ExecResult 8798 8799 // a database must be selected or specified as qualifier when create a function 8800 if cp.Name.HasNoNameQualifier() { 8801 if ses.DatabaseNameIsEmpty() { 8802 return moerr.NewNoDBNoCtx() 8803 } 8804 dbName = ses.GetDatabaseName() 8805 } else { 8806 dbName = string(cp.Name.Name.SchemaName) 8807 } 8808 8809 bh := ses.GetBackgroundExec(ctx) 8810 defer bh.Close() 8811 8812 // build argmap and marshal as json 8813 fmtctx := tree.NewFmtCtx(dialect.MYSQL, tree.WithQuoteString(true)) 8814 8815 // build argmap and marshal as json 8816 argList := make(map[string]tree.ProcedureArgForMarshal) 8817 for i := 0; i < len(cp.Args); i++ { 8818 curName := cp.Args[i].GetName(fmtctx) 8819 fmtctx.Reset() 8820 argList[curName] = tree.ProcedureArgForMarshal{ 8821 Name: cp.Args[i].(*tree.ProcedureArgDecl).Name, 8822 Type: cp.Args[i].(*tree.ProcedureArgDecl).Type, 8823 InOutType: cp.Args[i].(*tree.ProcedureArgDecl).InOutType, 8824 } 8825 } 8826 argsJson, err = json.Marshal(argList) 8827 if err != nil { 8828 return err 8829 } 8830 8831 // validate duplicate procedure declaration 8832 bh.ClearExecResultSet() 8833 checkExistence = getSqlForCheckProcedureExistence(string(cp.Name.Name.ObjectName), dbName) 8834 err = bh.Exec(ctx, checkExistence) 8835 if err != nil { 8836 return err 8837 } 8838 8839 erArray, err = getResultSet(ctx, bh) 8840 if err != nil { 8841 return err 8842 } 8843 8844 if execResultArrayHasData(erArray) { 8845 return moerr.NewProcedureAlreadyExistsNoCtx(string(cp.Name.Name.ObjectName)) 8846 } 8847 8848 err = bh.Exec(ctx, "begin;") 8849 defer func() { 8850 err = finishTxn(ctx, bh, err) 8851 }() 8852 if err != nil { 8853 return err 8854 } 8855 8856 initMoProcedure = fmt.Sprintf(initMoStoredProcedureFormat, 8857 string(cp.Name.Name.ObjectName), 8858 string(argsJson), 8859 cp.Body, dbName, 8860 tenant.GetUser(), types.CurrentTimestamp().String2(time.UTC, 0), types.CurrentTimestamp().String2(time.UTC, 0), "PROCEDURE", "DEFINER", "", "utf8mb4", "utf8mb4_0900_ai_ci", "utf8mb4_0900_ai_ci") 8861 err = bh.Exec(ctx, initMoProcedure) 8862 if err != nil { 8863 return err 8864 } 8865 return err 8866 } 8867 8868 func doAlterDatabaseConfig(ctx context.Context, ses *Session, ad *tree.AlterDataBaseConfig) error { 8869 var sql string 8870 var erArray []ExecResult 8871 var accountName string 8872 var databaseOwner int64 8873 var currentRole uint32 8874 var err error 8875 8876 dbName := ad.DbName 8877 updateConfig := ad.UpdateConfig 8878 tenantInfo := ses.GetTenantInfo() 8879 accountName = tenantInfo.GetTenant() 8880 currentRole = tenantInfo.GetDefaultRoleID() 8881 8882 updateConfigForDatabase := func() (rtnErr error) { 8883 bh := ses.GetBackgroundExec(ctx) 8884 defer bh.Close() 8885 8886 rtnErr = bh.Exec(ctx, "begin") 8887 defer func() { 8888 rtnErr = finishTxn(ctx, bh, rtnErr) 8889 }() 8890 if rtnErr != nil { 8891 return rtnErr 8892 } 8893 8894 // step1:check database exists or not and get database owner 8895 sql, rtnErr = getSqlForCheckDatabaseWithOwner(ctx, dbName, int64(ses.GetTenantInfo().GetTenantID())) 8896 if rtnErr != nil { 8897 return rtnErr 8898 } 8899 8900 bh.ClearExecResultSet() 8901 rtnErr = bh.Exec(ctx, sql) 8902 if rtnErr != nil { 8903 return rtnErr 8904 } 8905 8906 erArray, rtnErr = getResultSet(ctx, bh) 8907 if rtnErr != nil { 8908 return rtnErr 8909 } 8910 8911 if !execResultArrayHasData(erArray) { 8912 rtnErr = moerr.NewInternalError(ctx, "there is no database %s to change config", dbName) 8913 return 8914 } else { 8915 databaseOwner, rtnErr = erArray[0].GetInt64(ctx, 0, 1) 8916 if rtnErr != nil { 8917 return rtnErr 8918 } 8919 8920 // alter database config privileges check 8921 if databaseOwner != int64(currentRole) { 8922 rtnErr = moerr.NewInternalError(ctx, "do not have privileges to alter database config") 8923 return 8924 } 8925 } 8926 8927 // step2: update the mo_mysql_compatibility_mode of that database 8928 sql, rtnErr = getSqlForupdateConfigurationByDbNameAndAccountName(ctx, updateConfig, accountName, dbName, "version_compatibility") 8929 if rtnErr != nil { 8930 return rtnErr 8931 } 8932 8933 rtnErr = bh.Exec(ctx, sql) 8934 if rtnErr != nil { 8935 return rtnErr 8936 } 8937 return rtnErr 8938 } 8939 8940 err = updateConfigForDatabase() 8941 if err != nil { 8942 return err 8943 } 8944 8945 // step3: update the session verison 8946 if len(ses.GetDatabaseName()) != 0 && ses.GetDatabaseName() == dbName { 8947 err = changeVersion(ctx, ses, ses.GetDatabaseName()) 8948 if err != nil { 8949 return err 8950 } 8951 } 8952 8953 return err 8954 } 8955 8956 func doAlterAccountConfig(ctx context.Context, ses *Session, stmt *tree.AlterDataBaseConfig) error { 8957 var sql string 8958 var newCtx context.Context 8959 var isExist bool 8960 var err error 8961 8962 // alter account config privileges check 8963 if !ses.GetTenantInfo().IsMoAdminRole() { 8964 return moerr.NewInternalError(ctx, "do not have privileges to alter account config") 8965 } 8966 8967 accountName := stmt.AccountName 8968 update_config := stmt.UpdateConfig 8969 8970 updateConfigForAccount := func() (rtnErr error) { 8971 bh := ses.GetBackgroundExec(ctx) 8972 defer bh.Close() 8973 8974 rtnErr = bh.Exec(ctx, "begin") 8975 defer func() { 8976 rtnErr = finishTxn(ctx, bh, rtnErr) 8977 }() 8978 if rtnErr != nil { 8979 return rtnErr 8980 } 8981 8982 // step 1: check account exists or not 8983 newCtx = defines.AttachAccountId(ctx, catalog.System_Account) 8984 isExist, rtnErr = checkTenantExistsOrNot(newCtx, bh, accountName) 8985 if rtnErr != nil { 8986 return rtnErr 8987 } 8988 8989 if !isExist { 8990 return moerr.NewInternalError(ctx, "there is no account %s to change config", accountName) 8991 } 8992 8993 // step2: update the config 8994 sql, rtnErr = getSqlForupdateConfigurationByAccount(ctx, update_config, accountName, "version_compatibility") 8995 if rtnErr != nil { 8996 return rtnErr 8997 } 8998 rtnErr = bh.Exec(ctx, sql) 8999 if rtnErr != nil { 9000 return rtnErr 9001 } 9002 return rtnErr 9003 } 9004 9005 err = updateConfigForAccount() 9006 if err != nil { 9007 return err 9008 } 9009 9010 // step3: update the session verison 9011 if len(ses.GetDatabaseName()) != 0 { 9012 err = changeVersion(ctx, ses, ses.GetDatabaseName()) 9013 if err != nil { 9014 return err 9015 } 9016 } 9017 9018 return err 9019 } 9020 9021 func insertRecordToMoMysqlCompatibilityMode(ctx context.Context, ses *Session, stmt tree.Statement) error { 9022 var sql string 9023 var accountId uint32 9024 var accountName string 9025 var dbName string 9026 var err error 9027 variableName := "version_compatibility" 9028 variableValue := getVariableValue(ses.GetSysVar("version")) 9029 9030 if createDatabaseStmt, ok := stmt.(*tree.CreateDatabase); ok { 9031 dbName = string(createDatabaseStmt.Name) 9032 //if create sys database, do nothing 9033 if _, ok = sysDatabases[dbName]; ok { 9034 return nil 9035 } 9036 9037 insertRecordFunc := func() (rtnErr error) { 9038 bh := ses.GetBackgroundExec(ctx) 9039 defer bh.Close() 9040 9041 rtnErr = bh.Exec(ctx, "begin") 9042 defer func() { 9043 rtnErr = finishTxn(ctx, bh, rtnErr) 9044 }() 9045 if rtnErr != nil { 9046 return rtnErr 9047 } 9048 9049 //step 1: get account_name and database_name 9050 if ses.GetTenantInfo() != nil { 9051 accountName = ses.GetTenantInfo().GetTenant() 9052 accountId = ses.GetTenantInfo().GetTenantID() 9053 } else { 9054 return rtnErr 9055 } 9056 9057 //step 2: check database name 9058 if _, ok = bannedCatalogDatabases[dbName]; ok { 9059 return nil 9060 } 9061 9062 //step 3: insert the record 9063 sql = fmt.Sprintf(initMoMysqlCompatbilityModeFormat, accountId, accountName, dbName, variableName, variableValue, false) 9064 9065 rtnErr = bh.Exec(ctx, sql) 9066 if rtnErr != nil { 9067 return rtnErr 9068 } 9069 return rtnErr 9070 } 9071 err = insertRecordFunc() 9072 if err != nil { 9073 return err 9074 } 9075 } 9076 return nil 9077 9078 } 9079 9080 func deleteRecordToMoMysqlCompatbilityMode(ctx context.Context, ses *Session, stmt tree.Statement) error { 9081 var datname string 9082 var sql string 9083 var err error 9084 9085 if deleteDatabaseStmt, ok := stmt.(*tree.DropDatabase); ok { 9086 datname = string(deleteDatabaseStmt.Name) 9087 //if delete sys database, do nothing 9088 if _, ok = sysDatabases[datname]; ok { 9089 return nil 9090 } 9091 9092 deleteRecordFunc := func() (rtnErr error) { 9093 bh := ses.GetBackgroundExec(ctx) 9094 defer bh.Close() 9095 9096 rtnErr = bh.Exec(ctx, "begin") 9097 defer func() { 9098 rtnErr = finishTxn(ctx, bh, rtnErr) 9099 }() 9100 if rtnErr != nil { 9101 return rtnErr 9102 } 9103 sql = getSqlForDeleteMysqlCompatbilityMode(datname) 9104 9105 rtnErr = bh.Exec(ctx, sql) 9106 if rtnErr != nil { 9107 return rtnErr 9108 } 9109 return rtnErr 9110 } 9111 err = deleteRecordFunc() 9112 if err != nil { 9113 return err 9114 } 9115 } 9116 return nil 9117 } 9118 9119 func GetVersionCompatibility(ctx context.Context, ses *Session, dbName string) (ret string, err error) { 9120 var erArray []ExecResult 9121 var sql string 9122 var resultConfig string 9123 defaultConfig := "0.7" 9124 variableName := "version_compatibility" 9125 bh := ses.GetBackgroundExec(ctx) 9126 defer bh.Close() 9127 9128 err = bh.Exec(ctx, "begin") 9129 defer func() { 9130 err = finishTxn(ctx, bh, err) 9131 }() 9132 if err != nil { 9133 return defaultConfig, err 9134 } 9135 9136 sql = getSqlForGetSystemVariableValueWithDatabase(dbName, variableName) 9137 9138 bh.ClearExecResultSet() 9139 err = bh.Exec(ctx, sql) 9140 if err != nil { 9141 return defaultConfig, err 9142 } 9143 9144 erArray, err = getResultSet(ctx, bh) 9145 if err != nil { 9146 return defaultConfig, err 9147 } 9148 9149 if execResultArrayHasData(erArray) { 9150 resultConfig, err = erArray[0].GetString(ctx, 0, 0) 9151 if err != nil { 9152 return defaultConfig, err 9153 } 9154 } 9155 9156 return resultConfig, err 9157 } 9158 9159 func doInterpretCall(ctx context.Context, ses *Session, call *tree.CallStmt) ([]ExecResult, error) { 9160 // fetch related 9161 var spBody string 9162 var dbName string 9163 var sql string 9164 var argstr string 9165 var err error 9166 var erArray []ExecResult 9167 var argList map[string]tree.ProcedureArgForMarshal 9168 // execute related 9169 var interpreter Interpreter 9170 var varScope [](map[string]interface{}) 9171 var argsMap map[string]tree.Expr 9172 var argsAttr map[string]tree.InOutArgType 9173 9174 // a database must be selected or specified as qualifier when create a function 9175 if call.Name.HasNoNameQualifier() { 9176 if ses.DatabaseNameIsEmpty() { 9177 return nil, moerr.NewNoDBNoCtx() 9178 } 9179 dbName = ses.GetDatabaseName() 9180 } else { 9181 dbName = string(call.Name.Name.SchemaName) 9182 } 9183 9184 sql, err = getSqlForSpBody(ctx, string(call.Name.Name.ObjectName), dbName) 9185 if err != nil { 9186 return nil, err 9187 } 9188 9189 bh := ses.GetBackgroundExec(ctx) 9190 defer bh.Close() 9191 9192 bh.ClearExecResultSet() 9193 9194 err = bh.Exec(ctx, sql) 9195 if err != nil { 9196 return nil, err 9197 } 9198 9199 erArray, err = getResultSet(ctx, bh) 9200 if err != nil { 9201 return nil, err 9202 } 9203 9204 if execResultArrayHasData(erArray) { 9205 // function with provided name and db exists, for now we don't support overloading for stored procedure, so go to handle deletion. 9206 spBody, err = erArray[0].GetString(ctx, 0, 0) 9207 if err != nil { 9208 return nil, err 9209 } 9210 argstr, err = erArray[0].GetString(ctx, 0, 1) 9211 if err != nil { 9212 return nil, err 9213 } 9214 9215 // perform argument length validation 9216 // postpone argument type check until actual execution of its procedure body. This will be handled by the binder. 9217 err = json.Unmarshal([]byte(argstr), &argList) 9218 if err != nil { 9219 return nil, err 9220 } 9221 if len(argList) != len(call.Args) { 9222 return nil, moerr.NewInvalidArg(ctx, string(call.Name.Name.ObjectName)+" procedure have invalid input args length", len(call.Args)) 9223 } 9224 } else { 9225 return nil, moerr.NewNoUDFNoCtx(string(call.Name.Name.ObjectName)) 9226 } 9227 9228 stmt, err := parsers.Parse(ctx, dialect.MYSQL, spBody, 1, 0) 9229 if err != nil { 9230 return nil, err 9231 } 9232 defer func() { 9233 for _, st := range stmt { 9234 st.Free() 9235 } 9236 }() 9237 9238 fmtctx := tree.NewFmtCtx(dialect.MYSQL, tree.WithQuoteString(true)) 9239 9240 argsAttr = make(map[string]tree.InOutArgType) 9241 argsMap = make(map[string]tree.Expr) // map arg to param 9242 9243 // build argsAttr and argsMap 9244 logutil.Info("Interpret procedure call length:" + strconv.Itoa(len(argList))) 9245 i := 0 9246 for curName, v := range argList { 9247 argsAttr[curName] = v.InOutType 9248 argsMap[curName] = call.Args[i] 9249 i++ 9250 } 9251 9252 interpreter.ctx = ctx 9253 interpreter.fmtctx = fmtctx 9254 interpreter.ses = ses 9255 interpreter.varScope = &varScope 9256 interpreter.bh = bh 9257 interpreter.result = nil 9258 interpreter.argsMap = argsMap 9259 interpreter.argsAttr = argsAttr 9260 interpreter.outParamMap = make(map[string]interface{}) 9261 9262 err = interpreter.ExecuteSp(stmt[0], dbName) 9263 if err != nil { 9264 return nil, err 9265 } 9266 return interpreter.GetResult(), nil 9267 } 9268 9269 func doGrantPrivilegeImplicitly(ctx context.Context, ses *Session, stmt tree.Statement) error { 9270 var err error 9271 var sql string 9272 tenantInfo := ses.GetTenantInfo() 9273 if tenantInfo == nil || tenantInfo.IsAdminRole() { 9274 return err 9275 } 9276 currentRole := tenantInfo.GetDefaultRole() 9277 if len(currentRole) == 0 { 9278 return err 9279 } 9280 9281 // 1.first change to moadmin/accountAdmin 9282 var tenantCtx context.Context 9283 tenantInfo = ses.GetTenantInfo() 9284 // if is system account 9285 if tenantInfo.IsSysTenant() { 9286 tenantCtx = defines.AttachAccount(ctx, uint32(sysAccountID), uint32(rootID), uint32(moAdminRoleID)) 9287 } else { 9288 tenantCtx = defines.AttachAccount(ctx, tenantInfo.GetTenantID(), tenantInfo.GetUserID(), uint32(accountAdminRoleID)) 9289 } 9290 9291 // 2.grant database privilege 9292 switch st := stmt.(type) { 9293 case *tree.CreateDatabase: 9294 sql = getSqlForGrantOwnershipOnDatabase(string(st.Name), currentRole) 9295 case *tree.CreateTable: 9296 // get database name 9297 var dbName string 9298 if len(st.Table.SchemaName) == 0 { 9299 dbName = ses.GetDatabaseName() 9300 } else { 9301 dbName = string(st.Table.SchemaName) 9302 } 9303 // get table name 9304 tableName := string(st.Table.ObjectName) 9305 sql = getSqlForGrantOwnershipOnTable(dbName, tableName, currentRole) 9306 } 9307 9308 bh := ses.GetBackgroundExec(tenantCtx) 9309 defer bh.Close() 9310 9311 err = bh.Exec(tenantCtx, sql) 9312 if err != nil { 9313 return err 9314 } 9315 9316 return err 9317 } 9318 9319 func doRevokePrivilegeImplicitly(ctx context.Context, ses *Session, stmt tree.Statement) error { 9320 var err error 9321 var sql string 9322 tenantInfo := ses.GetTenantInfo() 9323 if tenantInfo == nil || tenantInfo.IsAdminRole() { 9324 return err 9325 } 9326 currentRole := tenantInfo.GetDefaultRole() 9327 if len(currentRole) == 0 { 9328 return err 9329 } 9330 9331 // 1.first change to moadmin/accountAdmin 9332 var tenantCtx context.Context 9333 tenantInfo = ses.GetTenantInfo() 9334 // if is system account 9335 if tenantInfo.IsSysTenant() { 9336 tenantCtx = defines.AttachAccount(ctx, uint32(sysAccountID), uint32(rootID), uint32(moAdminRoleID)) 9337 } else { 9338 tenantCtx = defines.AttachAccount(ctx, tenantInfo.GetTenantID(), tenantInfo.GetUserID(), uint32(accountAdminRoleID)) 9339 } 9340 9341 // 2.grant database privilege 9342 switch st := stmt.(type) { 9343 case *tree.DropDatabase: 9344 sql = getSqlForRevokeOwnershipFromDatabase(string(st.Name), currentRole) 9345 case *tree.DropTable: 9346 // get database name 9347 var dbName string 9348 if len(st.Names[0].SchemaName) == 0 { 9349 dbName = ses.GetDatabaseName() 9350 } else { 9351 dbName = string(st.Names[0].SchemaName) 9352 } 9353 // get table name 9354 tableName := string(st.Names[0].ObjectName) 9355 sql = getSqlForRevokeOwnershipFromTable(dbName, tableName, currentRole) 9356 } 9357 9358 bh := ses.GetBackgroundExec(tenantCtx) 9359 defer bh.Close() 9360 9361 err = bh.Exec(tenantCtx, sql) 9362 if err != nil { 9363 return err 9364 } 9365 9366 return err 9367 } 9368 9369 func doGetGlobalSystemVariable(ctx context.Context, ses *Session) (ret map[string]interface{}, err error) { 9370 var sql string 9371 var erArray []ExecResult 9372 var sysVars map[string]interface{} 9373 var accountId uint32 9374 var variableName, variableValue string 9375 var val interface{} 9376 tenantInfo := ses.GetTenantInfo() 9377 9378 sysVars = make(map[string]interface{}) 9379 bh := ses.GetBackgroundExec(ctx) 9380 defer bh.Close() 9381 9382 err = bh.Exec(ctx, "begin;") 9383 defer func() { 9384 err = finishTxn(ctx, bh, err) 9385 }() 9386 if err != nil { 9387 return nil, err 9388 } 9389 9390 accountId = tenantInfo.GetTenantID() 9391 sql = getSystemVariablesWithAccount(uint64(accountId)) 9392 9393 bh.ClearExecResultSet() 9394 err = bh.Exec(ctx, sql) 9395 if err != nil { 9396 return nil, err 9397 } 9398 9399 erArray, err = getResultSet(ctx, bh) 9400 if err != nil { 9401 return nil, err 9402 } 9403 9404 if execResultArrayHasData(erArray) { 9405 for i := uint64(0); i < erArray[0].GetRowCount(); i++ { 9406 variableName, err = erArray[0].GetString(ctx, i, 0) 9407 if err != nil { 9408 return nil, err 9409 } 9410 variableValue, err = erArray[0].GetString(ctx, i, 1) 9411 if err != nil { 9412 return nil, err 9413 } 9414 9415 if sv, ok := gSysVarsDefs[variableName]; ok { 9416 val, err = sv.GetType().ConvertFromString(variableValue) 9417 if err != nil { 9418 logError(ses, ses.GetDebugString(), err.Error(), zap.String("variable name:", variableName), zap.String("convert from variable value:", variableValue)) 9419 return nil, err 9420 } 9421 sysVars[variableName] = val 9422 } 9423 } 9424 } 9425 9426 return sysVars, nil 9427 } 9428 9429 func doSetGlobalSystemVariable(ctx context.Context, ses *Session, varName string, varValue interface{}) error { 9430 var sql string 9431 var accountId uint32 9432 var err error 9433 tenantInfo := ses.GetTenantInfo() 9434 9435 varName = strings.ToLower(varName) 9436 if sv, ok := gSysVarsDefs[varName]; ok { 9437 if sv.GetScope() == ScopeSession { 9438 return moerr.NewInternalError(ctx, errorSystemVariableIsSession()) 9439 } 9440 if !sv.GetDynamic() { 9441 return moerr.NewInternalError(ctx, errorSystemVariableIsReadOnly()) 9442 } 9443 9444 setGlobalFunc := func() (rtnErr error) { 9445 bh := ses.GetBackgroundExec(ctx) 9446 defer bh.Close() 9447 9448 rtnErr = bh.Exec(ctx, "begin;") 9449 defer func() { 9450 rtnErr = finishTxn(ctx, bh, rtnErr) 9451 }() 9452 if rtnErr != nil { 9453 return rtnErr 9454 } 9455 9456 accountId = tenantInfo.GetTenantID() 9457 sql = getSqlForUpdateSystemVariableValue(getVariableValue(varValue), uint64(accountId), varName) 9458 if _, ok := sv.GetType().(SystemVariableBoolType); ok { 9459 logInfo(ses, ses.GetDebugString(), "set global bool type value", zap.String("variable name", varName), zap.String("variable value", getVariableValue(varValue)), zap.String("update sql", sql)) 9460 } 9461 rtnErr = bh.Exec(ctx, sql) 9462 if rtnErr != nil { 9463 return rtnErr 9464 } 9465 return rtnErr 9466 } 9467 err = setGlobalFunc() 9468 if err != nil { 9469 return err 9470 } 9471 return err 9472 } else { 9473 return moerr.NewInternalError(ctx, errorSystemVariableDoesNotExist()) 9474 } 9475 } 9476 9477 func doCheckRole(ctx context.Context, ses *Session) error { 9478 var err error 9479 tenantInfo := ses.GetTenantInfo() 9480 currentAccount := tenantInfo.GetTenant() 9481 currentRole := tenantInfo.GetDefaultRole() 9482 if currentAccount == sysAccountName { 9483 if currentRole != moAdminRoleName { 9484 err = moerr.NewInternalError(ctx, "do not have privilege to execute the statement") 9485 } 9486 } else if currentRole != accountAdminRoleName { 9487 err = moerr.NewInternalError(ctx, "do not have privilege to execute the statement") 9488 } 9489 return err 9490 } 9491 9492 // isSuperUser returns true if the username is dump or root. 9493 func isSuperUser(username string) bool { 9494 u := strings.ToLower(username) 9495 return u == dumpName || u == rootName 9496 } 9497 9498 func addInitSystemVariablesSql(accountId int, accountName, variable_name string, pu *config.ParameterUnit) string { 9499 var initMoMysqlCompatibilityMode string 9500 9501 switch variable_name { 9502 case SaveQueryResult: 9503 if strings.ToLower(pu.SV.SaveQueryResult) == "on" { 9504 initMoMysqlCompatibilityMode = fmt.Sprintf(initMoMysqlCompatbilityModeWithoutDataBaseFormat, accountId, accountName, "save_query_result", getVariableValue(pu.SV.SaveQueryResult), true) 9505 9506 } else { 9507 initMoMysqlCompatibilityMode = fmt.Sprintf(initMoMysqlCompatbilityModeWithoutDataBaseFormat, accountId, accountName, "save_query_result", getVariableValue("off"), true) 9508 } 9509 9510 case QueryResultMaxsize: 9511 initMoMysqlCompatibilityMode = fmt.Sprintf(initMoMysqlCompatbilityModeWithoutDataBaseFormat, accountId, accountName, "query_result_maxsize", getVariableValue(pu.SV.QueryResultMaxsize), true) 9512 9513 case QueryResultTimeout: 9514 initMoMysqlCompatibilityMode = fmt.Sprintf(initMoMysqlCompatbilityModeWithoutDataBaseFormat, accountId, accountName, "query_result_timeout", getVariableValue(pu.SV.QueryResultTimeout), true) 9515 9516 case LowerCaseTableNames: 9517 initMoMysqlCompatibilityMode = fmt.Sprintf(initMoMysqlCompatbilityModeWithoutDataBaseFormat, accountId, accountName, "lower_case_table_names", getVariableValue(pu.SV.LowerCaseTableNames), true) 9518 } 9519 9520 return initMoMysqlCompatibilityMode 9521 } 9522 9523 // postAlterSessionStatus post alter all nodes session status which the tenant has been alter restricted or open. 9524 func postAlterSessionStatus( 9525 ctx context.Context, 9526 ses *Session, 9527 accountName string, 9528 tenantId int64, 9529 status string) error { 9530 qc := getGlobalPu().QueryClient 9531 if qc == nil { 9532 return moerr.NewInternalError(ctx, "query client is not initialized") 9533 } 9534 currTenant := ses.GetTenantInfo().GetTenant() 9535 currUser := ses.GetTenantInfo().GetUser() 9536 var nodes []string 9537 labels := clusterservice.NewSelector().SelectByLabel( 9538 map[string]string{"account": accountName}, clusterservice.Contain) 9539 sysTenant := isSysTenant(currTenant) 9540 if sysTenant { 9541 route.RouteForSuperTenant(clusterservice.NewSelector(), currUser, nil, 9542 func(s *metadata.CNService) { 9543 nodes = append(nodes, s.QueryAddress) 9544 }) 9545 } else { 9546 route.RouteForCommonTenant(labels, nil, func(s *metadata.CNService) { 9547 nodes = append(nodes, s.QueryAddress) 9548 }) 9549 } 9550 9551 var retErr, err error 9552 9553 genRequest := func() *query.Request { 9554 req := qc.NewRequest(query.CmdMethod_AlterAccount) 9555 req.AlterAccountRequest = &query.AlterAccountRequest{ 9556 TenantId: tenantId, 9557 Status: status, 9558 } 9559 return req 9560 } 9561 9562 handleValidResponse := func(nodeAddr string, rsp *query.Response) { 9563 if rsp != nil && rsp.AlterAccountResponse != nil && !rsp.AlterAccountResponse.AlterSuccess { 9564 retErr = moerr.NewInternalError(ctx, 9565 fmt.Sprintf("alter account status for account %s failed on node %s", accountName, nodeAddr)) 9566 } 9567 } 9568 9569 handleInvalidResponse := func(nodeAddr string) { 9570 retErr = moerr.NewInternalError(ctx, 9571 fmt.Sprintf("alter account status for account %s failed on node %s", accountName, nodeAddr)) 9572 } 9573 9574 err = queryservice.RequestMultipleCn(ctx, nodes, qc, genRequest, handleValidResponse, handleInvalidResponse) 9575 return errors.Join(err, retErr) 9576 } 9577 9578 func checkTimeStampValid(ctx context.Context, ses FeSession, snapshotTs int64) (bool, error) { 9579 var sql string 9580 var err error 9581 var erArray []ExecResult 9582 bh := ses.GetBackgroundExec(ctx) 9583 defer bh.Close() 9584 9585 sql = getSqlForCheckSnapshotTs(snapshotTs) 9586 9587 bh.ClearExecResultSet() 9588 err = bh.Exec(ctx, sql) 9589 if err != nil { 9590 return false, err 9591 } 9592 9593 erArray, err = getResultSet(ctx, bh) 9594 if err != nil { 9595 return false, err 9596 } 9597 9598 if !execResultArrayHasData(erArray) { 9599 return false, err 9600 } 9601 9602 return true, nil 9603 } 9604 9605 func getDbIdAndType(ctx context.Context, bh BackgroundExec, tenantInfo *TenantInfo, dbName string) (dbId uint64, dbType string, err error) { 9606 sql, err := getSqlForGetDbIdAndType(ctx, dbName, true, uint64(tenantInfo.GetTenantID())) 9607 if err != nil { 9608 return 9609 } 9610 if bh.Exec(ctx, sql) != nil { 9611 return 9612 } 9613 defer bh.ClearExecResultSet() 9614 9615 erArray, err := getResultSet(ctx, bh) 9616 if err != nil { 9617 return 9618 } 9619 9620 if !execResultArrayHasData(erArray) { 9621 err = moerr.NewInternalError(ctx, "database '%s' does not exist", dbName) 9622 return 9623 } 9624 9625 if dbId, err = erArray[0].GetUint64(ctx, 0, 0); err != nil { 9626 return 9627 } 9628 9629 if dbType, err = erArray[0].GetString(ctx, 0, 1); err != nil { 9630 return 9631 } 9632 9633 return 9634 }