github.com/matrixorigin/matrixone@v0.7.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 "fmt" 22 "math" 23 "math/bits" 24 "os" 25 "strings" 26 "sync/atomic" 27 "time" 28 29 "github.com/matrixorigin/matrixone/pkg/catalog" 30 31 "github.com/matrixorigin/matrixone/pkg/logutil" 32 "github.com/matrixorigin/matrixone/pkg/util/metric" 33 "github.com/matrixorigin/matrixone/pkg/util/trace" 34 "github.com/matrixorigin/matrixone/pkg/util/trace/impl/motrace" 35 36 "github.com/matrixorigin/matrixone/pkg/util/sysview" 37 38 "github.com/matrixorigin/matrixone/pkg/common/moerr" 39 "github.com/matrixorigin/matrixone/pkg/common/mpool" 40 "github.com/matrixorigin/matrixone/pkg/config" 41 "github.com/matrixorigin/matrixone/pkg/container/types" 42 "github.com/matrixorigin/matrixone/pkg/pb/plan" 43 "github.com/matrixorigin/matrixone/pkg/sql/parsers/dialect" 44 "github.com/matrixorigin/matrixone/pkg/sql/parsers/tree" 45 plan2 "github.com/matrixorigin/matrixone/pkg/sql/plan" 46 "github.com/tidwall/btree" 47 48 "github.com/matrixorigin/matrixone/pkg/defines" 49 ) 50 51 type TenantInfo struct { 52 Tenant string 53 User string 54 DefaultRole string 55 56 TenantID uint32 57 UserID uint32 58 DefaultRoleID uint32 59 60 // true: use secondary role all 61 // false: use secondary role none 62 useAllSecondaryRole bool 63 64 delimiter byte 65 66 version string 67 } 68 69 func (ti *TenantInfo) String() string { 70 return fmt.Sprintf("{account %s%c%s%c%s -- %d%c%d%c%d}", 71 ti.Tenant, ti.delimiter, ti.User, ti.delimiter, ti.DefaultRole, 72 ti.TenantID, ti.delimiter, ti.UserID, ti.delimiter, ti.DefaultRoleID) 73 } 74 75 func (ti *TenantInfo) GetTenant() string { 76 return ti.Tenant 77 } 78 79 func (ti *TenantInfo) GetTenantID() uint32 { 80 return ti.TenantID 81 } 82 83 func (ti *TenantInfo) SetTenantID(id uint32) { 84 ti.TenantID = id 85 } 86 87 func (ti *TenantInfo) GetUser() string { 88 return ti.User 89 } 90 91 func (ti *TenantInfo) GetUserID() uint32 { 92 return ti.UserID 93 } 94 95 func (ti *TenantInfo) SetUserID(id uint32) { 96 ti.UserID = id 97 } 98 99 func (ti *TenantInfo) GetDefaultRole() string { 100 return ti.DefaultRole 101 } 102 103 func (ti *TenantInfo) SetDefaultRole(r string) { 104 ti.DefaultRole = r 105 } 106 107 func (ti *TenantInfo) HasDefaultRole() bool { 108 return len(ti.GetDefaultRole()) != 0 109 } 110 111 func (ti *TenantInfo) GetDefaultRoleID() uint32 { 112 return ti.DefaultRoleID 113 } 114 115 func (ti *TenantInfo) SetDefaultRoleID(id uint32) { 116 ti.DefaultRoleID = id 117 } 118 119 func (ti *TenantInfo) IsSysTenant() bool { 120 return strings.ToLower(ti.GetTenant()) == GetDefaultTenant() 121 } 122 123 func (ti *TenantInfo) IsDefaultRole() bool { 124 return ti.GetDefaultRole() == GetDefaultRole() 125 } 126 127 func (ti *TenantInfo) IsMoAdminRole() bool { 128 return ti.IsSysTenant() && strings.ToLower(ti.GetDefaultRole()) == moAdminRoleName 129 } 130 131 func (ti *TenantInfo) IsAccountAdminRole() bool { 132 return !ti.IsSysTenant() && strings.ToLower(ti.GetDefaultRole()) == accountAdminRoleName 133 } 134 135 func (ti *TenantInfo) IsAdminRole() bool { 136 return ti.IsMoAdminRole() || ti.IsAccountAdminRole() 137 } 138 139 func (ti *TenantInfo) IsNameOfAdminRoles(name string) bool { 140 n := strings.ToLower(name) 141 if ti.IsSysTenant() { 142 return n == moAdminRoleName 143 } else { 144 return n == accountAdminRoleName 145 } 146 } 147 148 func (ti *TenantInfo) SetUseSecondaryRole(v bool) { 149 ti.useAllSecondaryRole = v 150 } 151 152 func (ti *TenantInfo) GetUseSecondaryRole() bool { 153 return ti.useAllSecondaryRole 154 } 155 156 func (ti *TenantInfo) GetVersion() string { 157 return ti.version 158 } 159 160 func (ti *TenantInfo) SetVersion(version string) { 161 ti.version = version 162 } 163 164 func GetDefaultTenant() string { 165 return sysAccountName 166 } 167 168 func GetDefaultRole() string { 169 return moAdminRoleName 170 } 171 172 func isCaseInsensitiveEqual(n string, role string) bool { 173 return strings.ToLower(n) == role 174 } 175 176 func isPublicRole(n string) bool { 177 return isCaseInsensitiveEqual(n, publicRoleName) 178 } 179 180 func isPredefinedRole(r string) bool { 181 n := strings.ToLower(r) 182 return n == publicRoleName || n == accountAdminRoleName || n == moAdminRoleName 183 } 184 185 func isSysTenant(n string) bool { 186 return isCaseInsensitiveEqual(n, sysAccountName) 187 } 188 189 // splitUserInput splits user input into account info 190 func splitUserInput(ctx context.Context, userInput string, delimiter byte) (*TenantInfo, error) { 191 p := strings.IndexByte(userInput, delimiter) 192 if p == -1 { 193 return &TenantInfo{ 194 Tenant: GetDefaultTenant(), 195 User: userInput, 196 delimiter: delimiter, 197 }, nil 198 } else { 199 tenant := userInput[:p] 200 tenant = strings.TrimSpace(tenant) 201 if len(tenant) == 0 { 202 return &TenantInfo{}, moerr.NewInternalError(ctx, "invalid tenant name '%s'", tenant) 203 } 204 userRole := userInput[p+1:] 205 p2 := strings.IndexByte(userRole, delimiter) 206 if p2 == -1 { 207 //tenant:user 208 user := userRole 209 user = strings.TrimSpace(user) 210 if len(user) == 0 { 211 return &TenantInfo{}, moerr.NewInternalError(ctx, "invalid user name '%s'", user) 212 } 213 return &TenantInfo{ 214 Tenant: tenant, 215 User: user, 216 delimiter: delimiter, 217 }, nil 218 } else { 219 user := userRole[:p2] 220 user = strings.TrimSpace(user) 221 if len(user) == 0 { 222 return &TenantInfo{}, moerr.NewInternalError(ctx, "invalid user name '%s'", user) 223 } 224 role := userRole[p2+1:] 225 role = strings.TrimSpace(role) 226 if len(role) == 0 { 227 return &TenantInfo{}, moerr.NewInternalError(ctx, "invalid role name '%s'", role) 228 } 229 return &TenantInfo{ 230 Tenant: tenant, 231 User: user, 232 DefaultRole: role, 233 delimiter: delimiter, 234 }, nil 235 } 236 } 237 } 238 239 //GetTenantInfo extract tenant info from the input of the user. 240 /** 241 The format of the user 242 1. tenant:user:role 243 2. tenant:user 244 3. user 245 246 a new format: 247 1. tenant#user#role 248 2. tenant#user 249 */ 250 func GetTenantInfo(ctx context.Context, userInput string) (*TenantInfo, error) { 251 if strings.IndexByte(userInput, ':') != -1 { 252 return splitUserInput(ctx, userInput, ':') 253 } else if strings.IndexByte(userInput, '#') != -1 { 254 return splitUserInput(ctx, userInput, '#') 255 } 256 return splitUserInput(ctx, userInput, ':') 257 } 258 259 // initUser for initialization or something special 260 type initUser struct { 261 account *TenantInfo 262 password []byte 263 } 264 265 var ( 266 specialUser atomic.Value 267 ) 268 269 // SetSpecialUser saves the user for initialization 270 // !!!NOTE: userName must not contain Colon ':' 271 func SetSpecialUser(userName string, password []byte) { 272 acc := &TenantInfo{ 273 Tenant: sysAccountName, 274 User: userName, 275 DefaultRole: moAdminRoleName, 276 TenantID: sysAccountID, 277 UserID: math.MaxUint32, 278 DefaultRoleID: moAdminRoleID, 279 } 280 281 user := &initUser{ 282 account: acc, 283 password: password, 284 } 285 286 specialUser.Store(user) 287 } 288 289 // isSpecialUser checks the user is the one for initialization 290 func isSpecialUser(userName string) (bool, []byte, *TenantInfo) { 291 user := getSpecialUser() 292 if user != nil && user.account.GetUser() == userName { 293 return true, user.password, user.account 294 } 295 return false, nil, nil 296 } 297 298 // getSpecialUser loads the user for initialization 299 func getSpecialUser() *initUser { 300 value := specialUser.Load() 301 if value == nil { 302 return nil 303 } 304 return value.(*initUser) 305 } 306 307 const ( 308 // createMoUserIndex = 0 309 // createMoAccountIndex = 1 310 // createMoRoleIndex = 2 311 // createMoUserGrantIndex = 3 312 // createMoRoleGrantIndex = 4 313 // createMoRolePrivIndex = 5 314 ) 315 316 const ( 317 //tenant 318 sysAccountID = 0 319 sysAccountName = "sys" 320 sysAccountStatus = "open" 321 sysAccountComments = "system account" 322 323 //role 324 moAdminRoleID = 0 325 moAdminRoleName = "moadmin" 326 // moAdminRoleComment = "super admin role" 327 publicRoleID = 1 328 publicRoleName = "public" 329 // publicRoleComment = "public role" 330 accountAdminRoleID = 2 331 accountAdminRoleName = "accountadmin" 332 // accountAdminRoleComment = "account admin role" 333 334 //user 335 userStatusLock = "lock" 336 userStatusUnlock = "unlock" 337 338 defaultPasswordEnv = "DEFAULT_PASSWORD" 339 340 rootID = 0 341 rootHost = "localhost" 342 rootName = "root" 343 rootPassword = "111" 344 rootStatus = userStatusUnlock 345 rootExpiredTime = "NULL" 346 rootLoginType = "PASSWORD" 347 rootCreatorID = rootID 348 rootOwnerRoleID = moAdminRoleID 349 rootDefaultRoleID = moAdminRoleID 350 351 dumpID = 1 352 dumpHost = "localhost" 353 dumpName = "dump" 354 //dumpPassword = "111" 355 dumpStatus = userStatusUnlock 356 dumpExpiredTime = "NULL" 357 dumpLoginType = "PASSWORD" 358 dumpCreatorID = rootID 359 dumpOwnerRoleID = moAdminRoleID 360 dumpDefaultRoleID = moAdminRoleID 361 362 moCatalog = "mo_catalog" 363 ) 364 365 type objectType int 366 367 const ( 368 objectTypeDatabase objectType = iota 369 objectTypeTable 370 objectTypeFunction 371 objectTypeAccount 372 objectTypeNone 373 374 objectIDAll = 0 //denotes all objects in the object type 375 ) 376 377 func (ot objectType) String() string { 378 switch ot { 379 case objectTypeDatabase: 380 return "database" 381 case objectTypeTable: 382 return "table" 383 case objectTypeFunction: 384 return "function" 385 case objectTypeAccount: 386 return "account" 387 case objectTypeNone: 388 return "none" 389 } 390 panic("unsupported object type") 391 } 392 393 type privilegeLevelType int 394 395 const ( 396 //* 397 privilegeLevelStar privilegeLevelType = iota 398 //*.* 399 privilegeLevelStarStar 400 //db_name 401 privilegeLevelDatabase 402 //db_name.* 403 privilegeLevelDatabaseStar 404 //db_name.tbl_name 405 privilegeLevelDatabaseTable 406 //tbl_name 407 privilegeLevelTable 408 //db_name.routine_name 409 privilegeLevelRoutine 410 // 411 privilegeLevelEnd 412 ) 413 414 func (plt privilegeLevelType) String() string { 415 switch plt { 416 case privilegeLevelStar: 417 return "*" 418 case privilegeLevelStarStar: 419 return "*.*" 420 case privilegeLevelDatabase: 421 return "d" 422 case privilegeLevelDatabaseStar: 423 return "d.*" 424 case privilegeLevelDatabaseTable: 425 return "d.t" 426 case privilegeLevelTable: 427 return "t" 428 case privilegeLevelRoutine: 429 return "r" 430 } 431 panic(fmt.Sprintf("no such privilege level type %d", plt)) 432 } 433 434 type PrivilegeType int 435 436 const ( 437 PrivilegeTypeCreateAccount PrivilegeType = iota 438 PrivilegeTypeDropAccount 439 PrivilegeTypeAlterAccount 440 PrivilegeTypeCreateUser 441 PrivilegeTypeDropUser 442 PrivilegeTypeAlterUser 443 PrivilegeTypeCreateRole 444 PrivilegeTypeDropRole 445 PrivilegeTypeAlterRole 446 PrivilegeTypeCreateDatabase 447 PrivilegeTypeDropDatabase 448 PrivilegeTypeShowDatabases 449 PrivilegeTypeConnect 450 PrivilegeTypeManageGrants 451 PrivilegeTypeAccountAll 452 PrivilegeTypeAccountOwnership 453 PrivilegeTypeUserOwnership 454 PrivilegeTypeRoleOwnership 455 PrivilegeTypeShowTables 456 PrivilegeTypeCreateObject //includes: table, view, stream, sequence, function, dblink,etc 457 PrivilegeTypeCreateTable 458 PrivilegeTypeCreateView 459 PrivilegeTypeDropObject 460 PrivilegeTypeDropTable 461 PrivilegeTypeDropView 462 PrivilegeTypeAlterObject 463 PrivilegeTypeAlterTable 464 PrivilegeTypeAlterView 465 PrivilegeTypeDatabaseAll 466 PrivilegeTypeDatabaseOwnership 467 PrivilegeTypeSelect 468 PrivilegeTypeInsert 469 PrivilegeTypeUpdate 470 PrivilegeTypeTruncate 471 PrivilegeTypeDelete 472 PrivilegeTypeReference 473 PrivilegeTypeIndex //include create/alter/drop index 474 PrivilegeTypeTableAll 475 PrivilegeTypeTableOwnership 476 PrivilegeTypeExecute 477 PrivilegeTypeCanGrantRoleToOthersInCreateUser // used in checking the privilege of CreateUser with the default role 478 PrivilegeTypeValues 479 PrivilegeTypeDump 480 ) 481 482 type PrivilegeScope uint8 483 484 const ( 485 PrivilegeScopeSys PrivilegeScope = 1 486 PrivilegeScopeAccount PrivilegeScope = 2 487 PrivilegeScopeUser PrivilegeScope = 4 488 PrivilegeScopeRole PrivilegeScope = 8 489 PrivilegeScopeDatabase PrivilegeScope = 16 490 PrivilegeScopeTable PrivilegeScope = 32 491 PrivilegeScopeRoutine PrivilegeScope = 64 492 ) 493 494 func (ps PrivilegeScope) String() string { 495 sb := strings.Builder{} 496 first := true 497 for i := 0; i < 8; i++ { 498 var s string 499 switch ps & (1 << i) { 500 case PrivilegeScopeSys: 501 s = "sys" 502 case PrivilegeScopeAccount: 503 s = "account" 504 case PrivilegeScopeUser: 505 s = "user" 506 case PrivilegeScopeRole: 507 s = "role" 508 case PrivilegeScopeDatabase: 509 s = "database" 510 case PrivilegeScopeTable: 511 s = "table" 512 case PrivilegeScopeRoutine: 513 s = "routine" 514 default: 515 s = "" 516 } 517 if len(s) != 0 { 518 if !first { 519 sb.WriteString(",") 520 } else { 521 first = false 522 } 523 sb.WriteString(s) 524 } 525 } 526 return sb.String() 527 } 528 529 func (pt PrivilegeType) String() string { 530 switch pt { 531 case PrivilegeTypeCreateAccount: 532 return "create account" 533 case PrivilegeTypeDropAccount: 534 return "drop account" 535 case PrivilegeTypeAlterAccount: 536 return "alter account" 537 case PrivilegeTypeCreateUser: 538 return "create user" 539 case PrivilegeTypeDropUser: 540 return "drop user" 541 case PrivilegeTypeAlterUser: 542 return "alter user" 543 case PrivilegeTypeCreateRole: 544 return "create role" 545 case PrivilegeTypeDropRole: 546 return "drop role" 547 case PrivilegeTypeAlterRole: 548 return "alter role" 549 case PrivilegeTypeCreateDatabase: 550 return "create database" 551 case PrivilegeTypeDropDatabase: 552 return "drop database" 553 case PrivilegeTypeShowDatabases: 554 return "show databases" 555 case PrivilegeTypeConnect: 556 return "connect" 557 case PrivilegeTypeManageGrants: 558 return "manage grants" 559 case PrivilegeTypeAccountAll: 560 return "account all" 561 case PrivilegeTypeAccountOwnership: 562 return "account ownership" 563 case PrivilegeTypeUserOwnership: 564 return "user ownership" 565 case PrivilegeTypeRoleOwnership: 566 return "role ownership" 567 case PrivilegeTypeShowTables: 568 return "show tables" 569 case PrivilegeTypeCreateObject: 570 return "create object" 571 case PrivilegeTypeCreateTable: 572 return "create table" 573 case PrivilegeTypeCreateView: 574 return "create view" 575 case PrivilegeTypeDropObject: 576 return "drop object" 577 case PrivilegeTypeDropTable: 578 return "drop table" 579 case PrivilegeTypeDropView: 580 return "drop view" 581 case PrivilegeTypeAlterObject: 582 return "alter object" 583 case PrivilegeTypeAlterTable: 584 return "alter table" 585 case PrivilegeTypeAlterView: 586 return "alter view" 587 case PrivilegeTypeDatabaseAll: 588 return "database all" 589 case PrivilegeTypeDatabaseOwnership: 590 return "database ownership" 591 case PrivilegeTypeSelect: 592 return "select" 593 case PrivilegeTypeInsert: 594 return "insert" 595 case PrivilegeTypeUpdate: 596 return "update" 597 case PrivilegeTypeTruncate: 598 return "truncate" 599 case PrivilegeTypeDelete: 600 return "delete" 601 case PrivilegeTypeReference: 602 return "reference" 603 case PrivilegeTypeIndex: 604 return "index" 605 case PrivilegeTypeTableAll: 606 return "table all" 607 case PrivilegeTypeTableOwnership: 608 return "table ownership" 609 case PrivilegeTypeExecute: 610 return "execute" 611 case PrivilegeTypeValues: 612 return "values" 613 case PrivilegeTypeDump: 614 return "dump" 615 } 616 panic(fmt.Sprintf("no such privilege type %d", pt)) 617 } 618 619 func (pt PrivilegeType) Scope() PrivilegeScope { 620 switch pt { 621 case PrivilegeTypeCreateAccount: 622 return PrivilegeScopeSys 623 case PrivilegeTypeDropAccount: 624 return PrivilegeScopeSys 625 case PrivilegeTypeAlterAccount: 626 return PrivilegeScopeSys 627 case PrivilegeTypeCreateUser: 628 return PrivilegeScopeAccount 629 case PrivilegeTypeDropUser: 630 return PrivilegeScopeAccount 631 case PrivilegeTypeAlterUser: 632 return PrivilegeScopeAccount 633 case PrivilegeTypeCreateRole: 634 return PrivilegeScopeAccount 635 case PrivilegeTypeDropRole: 636 return PrivilegeScopeAccount 637 case PrivilegeTypeAlterRole: 638 return PrivilegeScopeAccount 639 case PrivilegeTypeCreateDatabase: 640 return PrivilegeScopeAccount 641 case PrivilegeTypeDropDatabase: 642 return PrivilegeScopeAccount 643 case PrivilegeTypeShowDatabases: 644 return PrivilegeScopeAccount 645 case PrivilegeTypeConnect: 646 return PrivilegeScopeAccount 647 case PrivilegeTypeManageGrants: 648 return PrivilegeScopeAccount 649 case PrivilegeTypeAccountAll: 650 return PrivilegeScopeAccount 651 case PrivilegeTypeAccountOwnership: 652 return PrivilegeScopeAccount 653 case PrivilegeTypeUserOwnership: 654 return PrivilegeScopeUser 655 case PrivilegeTypeRoleOwnership: 656 return PrivilegeScopeRole 657 case PrivilegeTypeShowTables: 658 return PrivilegeScopeDatabase 659 case PrivilegeTypeCreateObject, PrivilegeTypeCreateTable, PrivilegeTypeCreateView: 660 return PrivilegeScopeDatabase 661 case PrivilegeTypeDropObject, PrivilegeTypeDropTable, PrivilegeTypeDropView: 662 return PrivilegeScopeDatabase 663 case PrivilegeTypeAlterObject, PrivilegeTypeAlterTable, PrivilegeTypeAlterView: 664 return PrivilegeScopeDatabase 665 case PrivilegeTypeDatabaseAll: 666 return PrivilegeScopeDatabase 667 case PrivilegeTypeDatabaseOwnership: 668 return PrivilegeScopeDatabase 669 case PrivilegeTypeSelect: 670 return PrivilegeScopeTable 671 case PrivilegeTypeInsert: 672 return PrivilegeScopeTable 673 case PrivilegeTypeUpdate: 674 return PrivilegeScopeTable 675 case PrivilegeTypeTruncate: 676 return PrivilegeScopeTable 677 case PrivilegeTypeDelete: 678 return PrivilegeScopeTable 679 case PrivilegeTypeReference: 680 return PrivilegeScopeTable 681 case PrivilegeTypeIndex: 682 return PrivilegeScopeTable 683 case PrivilegeTypeTableAll: 684 return PrivilegeScopeTable 685 case PrivilegeTypeTableOwnership: 686 return PrivilegeScopeTable 687 case PrivilegeTypeExecute: 688 return PrivilegeScopeTable 689 case PrivilegeTypeValues: 690 return PrivilegeScopeTable 691 case PrivilegeTypeDump: 692 return PrivilegeScopeDatabase 693 } 694 panic(fmt.Sprintf("no such privilege type %d", pt)) 695 } 696 697 var ( 698 sysWantedDatabases = map[string]int8{ 699 "mo_catalog": 0, 700 "information_schema": 0, 701 "system": 0, 702 "system_metrics": 0, 703 } 704 sysWantedTables = map[string]int8{ 705 "mo_user": 0, 706 "mo_account": 0, 707 "mo_role": 0, 708 "mo_user_grant": 0, 709 "mo_role_grant": 0, 710 "mo_role_privs": 0, 711 "mo_user_defined_function": 0, 712 "mo_mysql_compatbility_mode": 0, 713 `%!%mo_increment_columns`: 0, 714 } 715 //predefined tables of the database mo_catalog in every account 716 predefinedTables = map[string]int8{ 717 "mo_database": 0, 718 "mo_tables": 0, 719 "mo_columns": 0, 720 "mo_account": 0, 721 "mo_user": 0, 722 "mo_role": 0, 723 "mo_user_grant": 0, 724 "mo_role_grant": 0, 725 "mo_role_privs": 0, 726 "mo_user_defined_function": 0, 727 "mo_mysql_compatbility_mode": 0, 728 "%!%mo_increment_columns": 0, 729 } 730 createAutoTableSql = "create table `%!%mo_increment_columns`(name varchar(770) primary key, offset bigint unsigned, step bigint unsigned);" 731 //the sqls creating many tables for the tenant. 732 //Wrap them in a transaction 733 createSqls = []string{ 734 `create table mo_user( 735 user_id int signed auto_increment, 736 user_host varchar(100), 737 user_name varchar(300), 738 authentication_string varchar(100), 739 status varchar(8), 740 created_time timestamp, 741 expired_time timestamp, 742 login_type varchar(16), 743 creator int signed, 744 owner int signed, 745 default_role int signed 746 );`, 747 `create table mo_account( 748 account_id int signed auto_increment, 749 account_name varchar(300), 750 status varchar(300), 751 created_time timestamp, 752 comments varchar(256), 753 suspended_time timestamp default NULL 754 );`, 755 `create table mo_role( 756 role_id int signed auto_increment, 757 role_name varchar(300), 758 creator int signed, 759 owner int signed, 760 created_time timestamp, 761 comments text 762 );`, 763 `create table mo_user_grant( 764 role_id int signed, 765 user_id int signed, 766 granted_time timestamp, 767 with_grant_option bool 768 );`, 769 `create table mo_role_grant( 770 granted_id int signed, 771 grantee_id int signed, 772 operation_role_id int signed, 773 operation_user_id int signed, 774 granted_time timestamp, 775 with_grant_option bool 776 );`, 777 `create table mo_role_privs( 778 role_id int signed, 779 role_name varchar(100), 780 obj_type varchar(16), 781 obj_id bigint unsigned, 782 privilege_id int, 783 privilege_name varchar(100), 784 privilege_level varchar(100), 785 operation_user_id int unsigned, 786 granted_time timestamp, 787 with_grant_option bool 788 );`, 789 `create table mo_user_defined_function( 790 function_id int auto_increment, 791 name varchar(100), 792 args text, 793 retType varchar(20), 794 body text, 795 language varchar(20), 796 db varchar(100), 797 definer varchar(50), 798 modified_time timestamp, 799 created_time timestamp, 800 type varchar(10), 801 security_type varchar(10), 802 comment varchar(5000), 803 character_set_client varchar(64), 804 collation_connection varchar(64), 805 database_collation varchar(64), 806 primary key(function_id) 807 );`, 808 `create table mo_mysql_compatbility_mode( 809 configuration_id int auto_increment, 810 account_name varchar(300), 811 dat_name varchar(5000), 812 configuration json, 813 primary key(configuration_id) 814 );`, 815 } 816 817 //drop tables for the tenant 818 dropSqls = []string{ 819 `drop table if exists mo_catalog.mo_user;`, 820 `drop table if exists mo_catalog.mo_role;`, 821 `drop table if exists mo_catalog.mo_user_grant;`, 822 `drop table if exists mo_catalog.mo_role_grant;`, 823 `drop table if exists mo_catalog.mo_role_privs;`, 824 //"drop table if exists mo_catalog.`%!%mo_increment_columns`;", 825 } 826 827 initMoMysqlCompatbilityModeFormat = `insert into mo_catalog.mo_mysql_compatbility_mode( 828 account_name, 829 dat_name, 830 configuration) values ("%s","%s",%s);` 831 832 initMoUserDefinedFunctionFormat = `insert into mo_catalog.mo_user_defined_function( 833 name, 834 args, 835 retType, 836 body, 837 language, 838 db, 839 definer, 840 modified_time, 841 created_time, 842 type, 843 security_type, 844 comment, 845 character_set_client, 846 collation_connection, 847 database_collation) values ("%s",'%s',"%s","%s","%s","%s","%s","%s","%s","%s","%s","%s","%s","%s","%s");` 848 849 initMoAccountFormat = `insert into mo_catalog.mo_account( 850 account_id, 851 account_name, 852 status, 853 created_time, 854 comments) values (%d,"%s","%s","%s","%s");` 855 initMoAccountWithoutIDFormat = `insert into mo_catalog.mo_account( 856 account_name, 857 status, 858 created_time, 859 comments) values ("%s","%s","%s","%s");` 860 initMoRoleFormat = `insert into mo_catalog.mo_role( 861 role_id, 862 role_name, 863 creator, 864 owner, 865 created_time, 866 comments 867 ) values (%d,"%s",%d,%d,"%s","%s");` 868 initMoRoleWithoutIDFormat = `insert into mo_catalog.mo_role( 869 role_name, 870 creator, 871 owner, 872 created_time, 873 comments 874 ) values ("%s",%d,%d,"%s","%s");` 875 initMoUserFormat = `insert into mo_catalog.mo_user( 876 user_id, 877 user_host, 878 user_name, 879 authentication_string, 880 status, 881 created_time, 882 expired_time, 883 login_type, 884 creator, 885 owner, 886 default_role 887 ) values(%d,"%s","%s","%s","%s","%s",%s,"%s",%d,%d,%d);` 888 initMoUserWithoutIDFormat = `insert into mo_catalog.mo_user( 889 user_host, 890 user_name, 891 authentication_string, 892 status, 893 created_time, 894 expired_time, 895 login_type, 896 creator, 897 owner, 898 default_role 899 ) values("%s","%s","%s","%s","%s",%s,"%s",%d,%d,%d);` 900 initMoRolePrivFormat = `insert into mo_catalog.mo_role_privs( 901 role_id, 902 role_name, 903 obj_type, 904 obj_id, 905 privilege_id, 906 privilege_name, 907 privilege_level, 908 operation_user_id, 909 granted_time, 910 with_grant_option 911 ) values(%d,"%s","%s",%d,%d,"%s","%s",%d,"%s",%v);` 912 initMoUserGrantFormat = `insert into mo_catalog.mo_user_grant( 913 role_id, 914 user_id, 915 granted_time, 916 with_grant_option 917 ) values(%d,%d,"%s",%v);` 918 ) 919 920 const ( 921 //privilege verification 922 checkTenantFormat = `select account_id,account_name,status,suspended_time from mo_catalog.mo_account where account_name = "%s";` 923 924 updateCommentsOfAccountFormat = `update mo_catalog.mo_account set comments = "%s" where account_name = "%s";` 925 926 updateStatusOfAccountFormat = `update mo_catalog.mo_account set status = "%s",suspended_time = "%s" where account_name = "%s";` 927 928 deleteAccountFromMoAccountFormat = `delete from mo_catalog.mo_account where account_name = "%s";` 929 930 getPasswordOfUserFormat = `select user_id,authentication_string,default_role from mo_catalog.mo_user where user_name = "%s";` 931 932 updatePasswordOfUserFormat = `update mo_catalog.mo_user set authentication_string = "%s" where user_name = "%s";` 933 934 checkRoleExistsFormat = `select role_id from mo_catalog.mo_role where role_id = %d and role_name = "%s";` 935 936 roleNameOfRoleIdFormat = `select role_name from mo_catalog.mo_role where role_id = %d;` 937 938 roleIdOfRoleFormat = `select role_id from mo_catalog.mo_role where role_name = "%s";` 939 940 //operations on the mo_user_grant 941 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";` 942 943 getRoleIdOfUserIdFormat = `select role_id,with_grant_option from mo_catalog.mo_user_grant where user_id = %d;` 944 945 checkUserGrantFormat = `select role_id,user_id,with_grant_option from mo_catalog.mo_user_grant where role_id = %d and user_id = %d;` 946 947 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;` 948 949 //with_grant_option = true 950 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;` 951 952 updateUserGrantFormat = `update mo_catalog.mo_user_grant set granted_time = "%s", with_grant_option = %v where role_id = %d and user_id = %d;` 953 954 insertUserGrantFormat = `insert into mo_catalog.mo_user_grant(role_id,user_id,granted_time,with_grant_option) values (%d,%d,"%s",%v);` 955 956 deleteUserGrantFormat = `delete from mo_catalog.mo_user_grant where role_id = %d and user_id = %d;` 957 958 //operations on the mo_role_grant 959 checkRoleGrantFormat = `select granted_id,grantee_id,with_grant_option from mo_catalog.mo_role_grant where granted_id = %d and grantee_id = %d;` 960 961 //with_grant_option = true 962 getRoleGrantWGOFormat = `select grantee_id from mo_catalog.mo_role_grant where with_grant_option = true and granted_id = %d;` 963 964 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;` 965 966 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);` 967 968 deleteRoleGrantFormat = `delete from mo_catalog.mo_role_grant where granted_id = %d and grantee_id = %d;` 969 970 getAllStuffRoleGrantFormat = `select granted_id,grantee_id,with_grant_option from mo_catalog.mo_role_grant;` 971 972 getInheritedRoleIdOfRoleIdFormat = `select granted_id,with_grant_option from mo_catalog.mo_role_grant where grantee_id = %d;` 973 974 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;` 975 976 //with_grant_option = true 977 checkRoleHasPrivilegeWGOFormat = `select role_id from mo_catalog.mo_role_privs where with_grant_option = true and privilege_id = %d;` 978 979 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;` 980 981 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) 982 values (%d,"%s","%s",%d,%d,"%s","%s",%d,"%s",%v);` 983 984 deleteRolePrivsFormat = `delete from mo_catalog.mo_role_privs 985 where role_id = %d 986 and obj_type = "%s" 987 and obj_id = %d 988 and privilege_id = %d 989 and privilege_level = "%s";` 990 991 checkDatabaseFormat = `select dat_id from mo_catalog.mo_database where datname = "%s";` 992 993 checkDatabaseTableFormat = `select t.rel_id from mo_catalog.mo_database d, mo_catalog.mo_tables t 994 where d.dat_id = t.reldatabase_id 995 and d.datname = "%s" 996 and t.relname = "%s";` 997 998 //TODO:fix privilege_level string and obj_type string 999 //For object_type : table, privilege_level : *.* 1000 checkWithGrantOptionForTableStarStar = `select rp.privilege_id,rp.with_grant_option 1001 from mo_catalog.mo_database d, mo_catalog.mo_tables t, mo_catalog.mo_role_privs rp 1002 where d.dat_id = t.reldatabase_id 1003 and rp.obj_id = 0 1004 and rp.obj_type = "%s" 1005 and rp.role_id = %d 1006 and rp.privilege_id = %d 1007 and rp.privilege_level = "%s" 1008 and rp.with_grant_option = true;` 1009 1010 //For object_type : table, privilege_level : db.* 1011 checkWithGrantOptionForTableDatabaseStar = `select rp.privilege_id,rp.with_grant_option 1012 from mo_catalog.mo_database d, mo_catalog.mo_tables t, mo_catalog.mo_role_privs rp 1013 where d.dat_id = t.reldatabase_id 1014 and rp.obj_id = 0 1015 and rp.obj_type = "%s" 1016 and rp.role_id = %d 1017 and rp.privilege_id = %d 1018 and rp.privilege_level = "%s" 1019 and d.datname = "%s" 1020 and rp.with_grant_option = true;` 1021 1022 //For object_type : table, privilege_level : db.table 1023 checkWithGrantOptionForTableDatabaseTable = `select rp.privilege_id,rp.with_grant_option 1024 from mo_catalog.mo_database d, mo_catalog.mo_tables t, mo_catalog.mo_role_privs rp 1025 where d.dat_id = t.reldatabase_id 1026 and rp.obj_id = t.rel_id 1027 and rp.obj_type = "%s" 1028 and rp.role_id = %d 1029 and rp.privilege_id = %d 1030 and rp.privilege_level = "%s" 1031 and d.datname = "%s" 1032 and t.relname = "%s" 1033 and rp.with_grant_option = true;` 1034 1035 //For object_type : database, privilege_level : * 1036 checkWithGrantOptionForDatabaseStar = `select rp.privilege_id,rp.with_grant_option 1037 from mo_catalog.mo_database d, mo_catalog.mo_tables t, mo_catalog.mo_role_privs rp 1038 where d.dat_id = t.reldatabase_id 1039 and rp.obj_id = 0 1040 and rp.obj_type = "%s" 1041 and rp.role_id = %d 1042 and rp.privilege_id = %d 1043 and rp.privilege_level = "%s" 1044 and rp.with_grant_option = true;` 1045 1046 //For object_type : database, privilege_level : *.* 1047 checkWithGrantOptionForDatabaseStarStar = `select rp.privilege_id,rp.with_grant_option 1048 from mo_catalog.mo_database d, mo_catalog.mo_tables t, mo_catalog.mo_role_privs rp 1049 where d.dat_id = t.reldatabase_id 1050 and rp.obj_id = 0 1051 and rp.obj_type = "%s" 1052 and rp.role_id = %d 1053 and rp.privilege_id = %d 1054 and rp.privilege_level = "%s" 1055 and rp.with_grant_option = true;` 1056 1057 //For object_type : database, privilege_level : db 1058 checkWithGrantOptionForDatabaseDB = `select rp.privilege_id,rp.with_grant_option 1059 from mo_catalog.mo_database d, mo_catalog.mo_tables t, mo_catalog.mo_role_privs rp 1060 where d.dat_id = t.reldatabase_id 1061 and rp.obj_id = d.dat_id 1062 and rp.obj_type = "%s" 1063 and rp.role_id = %d 1064 and rp.privilege_id = %d 1065 and rp.privilege_level = "%s" 1066 and d.datname = "%s" 1067 and rp.with_grant_option = true;` 1068 1069 //For object_type : account, privilege_level : * 1070 checkWithGrantOptionForAccountStar = `select rp.privilege_id,rp.with_grant_option 1071 from mo_catalog.mo_database d, mo_catalog.mo_tables t, mo_catalog.mo_role_privs rp 1072 where d.dat_id = t.reldatabase_id 1073 and rp.obj_id = 0 1074 and rp.obj_type = "%s" 1075 and rp.role_id = %d 1076 and rp.privilege_id = %d 1077 and rp.privilege_level = "%s" 1078 and rp.with_grant_option = true;` 1079 1080 //for database.table or table 1081 //check the role has the table level privilege for the privilege level (d.t or t) 1082 checkRoleHasTableLevelPrivilegeFormat = `select rp.privilege_id,rp.with_grant_option 1083 from mo_catalog.mo_database d, mo_catalog.mo_tables t, mo_catalog.mo_role_privs rp 1084 where d.dat_id = t.reldatabase_id 1085 and rp.obj_id = t.rel_id 1086 and rp.obj_type = "%s" 1087 and rp.role_id = %d 1088 and rp.privilege_id = %d 1089 and rp.privilege_level in ("%s","%s") 1090 and d.datname = "%s" 1091 and t.relname = "%s";` 1092 1093 //for database.* or * 1094 checkRoleHasTableLevelForDatabaseStarFormat = `select rp.privilege_id,rp.with_grant_option 1095 from mo_catalog.mo_database d, mo_catalog.mo_role_privs rp 1096 where d.dat_id = rp.obj_id 1097 and rp.obj_type = "%s" 1098 and rp.role_id = %d 1099 and rp.privilege_id = %d 1100 and rp.privilege_level in ("%s","%s") 1101 and d.datname = "%s";` 1102 1103 //for *.* 1104 checkRoleHasTableLevelForStarStarFormat = `select rp.privilege_id,rp.with_grant_option 1105 from mo_catalog.mo_role_privs rp 1106 where rp.obj_id = 0 1107 and rp.obj_type = "%s" 1108 and rp.role_id = %d 1109 and rp.privilege_id = %d 1110 and rp.privilege_level = "%s";` 1111 1112 //for * or *.* 1113 checkRoleHasDatabaseLevelForStarStarFormat = `select rp.privilege_id,rp.with_grant_option 1114 from mo_catalog.mo_role_privs rp 1115 where rp.obj_id = 0 1116 and rp.obj_type = "%s" 1117 and rp.role_id = %d 1118 and rp.privilege_id = %d 1119 and rp.privilege_level = "%s";` 1120 1121 //for database 1122 checkRoleHasDatabaseLevelForDatabaseFormat = `select rp.privilege_id,rp.with_grant_option 1123 from mo_catalog.mo_database d, mo_catalog.mo_role_privs rp 1124 where d.dat_id = rp.obj_id 1125 and rp.obj_type = "%s" 1126 and rp.role_id = %d 1127 and rp.privilege_id = %d 1128 and rp.privilege_level = "%s" 1129 and d.datname = "%s";` 1130 1131 //for * 1132 checkRoleHasAccountLevelForStarFormat = `select rp.privilege_id,rp.with_grant_option 1133 from mo_catalog.mo_role_privs rp 1134 where rp.obj_id = 0 1135 and rp.obj_type = "%s" 1136 and rp.role_id = %d 1137 and rp.privilege_id = %d 1138 and rp.privilege_level = "%s";` 1139 1140 checkUdfArgs = `select args,function_id from mo_catalog.mo_user_defined_function where name = "%s" and db = "%s";` 1141 1142 checkUdfExistence = `select function_id from mo_catalog.mo_user_defined_function where name = "%s" and db = "%s" and args = '%s';` 1143 1144 //delete role from mo_role,mo_user_grant,mo_role_grant,mo_role_privs 1145 deleteRoleFromMoRoleFormat = `delete from mo_catalog.mo_role where role_id = %d;` 1146 1147 deleteRoleFromMoUserGrantFormat = `delete from mo_catalog.mo_user_grant where role_id = %d;` 1148 1149 deleteRoleFromMoRoleGrantFormat = `delete from mo_catalog.mo_role_grant where granted_id = %d or grantee_id = %d;` 1150 1151 deleteRoleFromMoRolePrivsFormat = `delete from mo_catalog.mo_role_privs where role_id = %d;` 1152 1153 //delete user from mo_user,mo_user_grant 1154 deleteUserFromMoUserFormat = `delete from mo_catalog.mo_user where user_id = %d;` 1155 1156 deleteUserFromMoUserGrantFormat = `delete from mo_catalog.mo_user_grant where user_id = %d;` 1157 1158 // delete user defined function from mo_user_defined_function 1159 deleteUserDefinedFunctionFormat = `delete from mo_catalog.mo_user_defined_function where function_id = %d;` 1160 1161 // delete a tuple from mo_mysql_compatbility_mode when drop a database 1162 deleteMysqlCompatbilityModeFormat = `delete from mo_catalog.mo_mysql_compatbility_mode where dat_name = "%s";` 1163 1164 deleteMysqlCompatbilityModeForAccountFormat = `delete from mo_catalog.mo_mysql_compatbility_mode where account_name = "%s";` 1165 ) 1166 1167 var ( 1168 objectType2privilegeLevels = map[objectType][]privilegeLevelType{ 1169 objectTypeAccount: {privilegeLevelStar}, 1170 objectTypeDatabase: {privilegeLevelDatabase, 1171 privilegeLevelStar, privilegeLevelStarStar}, 1172 objectTypeTable: {privilegeLevelStarStar, 1173 privilegeLevelDatabaseStar, privilegeLevelStar, 1174 privilegeLevelDatabaseTable, privilegeLevelTable}, 1175 } 1176 1177 // the databases that can not operated by the real user 1178 bannedCatalogDatabases = map[string]int8{ 1179 "mo_catalog": 0, 1180 "information_schema": 0, 1181 "system": 0, 1182 "system_metrics": 0, 1183 "mysql": 0, 1184 "mo_task": 0, 1185 } 1186 1187 // the privileges that can not be granted or revoked 1188 bannedPrivileges = map[PrivilegeType]int8{ 1189 PrivilegeTypeCreateAccount: 0, 1190 PrivilegeTypeAlterAccount: 0, 1191 PrivilegeTypeDropAccount: 0, 1192 } 1193 ) 1194 1195 func getSqlForCheckTenant(tenant string) string { 1196 return fmt.Sprintf(checkTenantFormat, tenant) 1197 } 1198 1199 func getSqlForUpdateCommentsOfAccount(comment, account string) string { 1200 return fmt.Sprintf(updateCommentsOfAccountFormat, comment, account) 1201 } 1202 1203 func getSqlForUpdateStatusOfAccount(status, timestamp, account string) string { 1204 return fmt.Sprintf(updateStatusOfAccountFormat, status, timestamp, account) 1205 } 1206 1207 func getSqlForDeleteAccountFromMoAccount(account string) string { 1208 return fmt.Sprintf(deleteAccountFromMoAccountFormat, account) 1209 } 1210 1211 func getSqlForPasswordOfUser(user string) string { 1212 return fmt.Sprintf(getPasswordOfUserFormat, user) 1213 } 1214 1215 func getSqlForUpdatePasswordOfUser(password, user string) string { 1216 return fmt.Sprintf(updatePasswordOfUserFormat, password, user) 1217 } 1218 1219 func getSqlForCheckRoleExists(roleID int, roleName string) string { 1220 return fmt.Sprintf(checkRoleExistsFormat, roleID, roleName) 1221 } 1222 1223 func getSqlForRoleNameOfRoleId(roleId int64) string { 1224 return fmt.Sprintf(roleNameOfRoleIdFormat, roleId) 1225 } 1226 1227 func getSqlForRoleIdOfRole(roleName string) string { 1228 return fmt.Sprintf(roleIdOfRoleFormat, roleName) 1229 } 1230 1231 func getSqlForRoleOfUser(userID int64, roleName string) string { 1232 return fmt.Sprintf(getRoleOfUserFormat, userID, roleName) 1233 } 1234 1235 func getSqlForRoleIdOfUserId(userId int) string { 1236 return fmt.Sprintf(getRoleIdOfUserIdFormat, userId) 1237 } 1238 1239 func getSqlForCheckUserGrant(roleId, userId int64) string { 1240 return fmt.Sprintf(checkUserGrantFormat, roleId, userId) 1241 } 1242 1243 func getSqlForCheckUserHasRole(userName string, roleId int64) string { 1244 return fmt.Sprintf(checkUserHasRoleFormat, userName, roleId) 1245 } 1246 1247 func getSqlForCheckUserGrantWGO(roleId, userId int64) string { 1248 return fmt.Sprintf(checkUserGrantWGOFormat, roleId, userId) 1249 } 1250 1251 func getSqlForUpdateUserGrant(roleId, userId int64, timestamp string, withGrantOption bool) string { 1252 return fmt.Sprintf(updateUserGrantFormat, timestamp, withGrantOption, roleId, userId) 1253 } 1254 1255 func getSqlForInsertUserGrant(roleId, userId int64, timestamp string, withGrantOption bool) string { 1256 return fmt.Sprintf(insertUserGrantFormat, roleId, userId, timestamp, withGrantOption) 1257 } 1258 1259 func getSqlForDeleteUserGrant(roleId, userId int64) string { 1260 return fmt.Sprintf(deleteUserGrantFormat, roleId, userId) 1261 } 1262 1263 func getSqlForCheckRoleGrant(grantedId, granteeId int64) string { 1264 return fmt.Sprintf(checkRoleGrantFormat, grantedId, granteeId) 1265 } 1266 1267 func getSqlForCheckRoleGrantWGO(grantedId int64) string { 1268 return fmt.Sprintf(getRoleGrantWGOFormat, grantedId) 1269 } 1270 1271 func getSqlForUpdateRoleGrant(grantedId, granteeId, operationRoleId, operationUserId int64, timestamp string, withGrantOption bool) string { 1272 return fmt.Sprintf(updateRoleGrantFormat, operationRoleId, operationUserId, timestamp, withGrantOption, grantedId, granteeId) 1273 } 1274 1275 func getSqlForInsertRoleGrant(grantedId, granteeId, operationRoleId, operationUserId int64, timestamp string, withGrantOption bool) string { 1276 return fmt.Sprintf(insertRoleGrantFormat, grantedId, granteeId, operationRoleId, operationUserId, timestamp, withGrantOption) 1277 } 1278 1279 func getSqlForDeleteRoleGrant(grantedId, granteeId int64) string { 1280 return fmt.Sprintf(deleteRoleGrantFormat, grantedId, granteeId) 1281 } 1282 1283 func getSqlForGetAllStuffRoleGrantFormat() string { 1284 return getAllStuffRoleGrantFormat 1285 } 1286 1287 func getSqlForInheritedRoleIdOfRoleId(roleId int64) string { 1288 return fmt.Sprintf(getInheritedRoleIdOfRoleIdFormat, roleId) 1289 } 1290 1291 func getSqlForCheckRoleHasPrivilege(roleId int64, objType objectType, objId, privilegeId int64) string { 1292 return fmt.Sprintf(checkRoleHasPrivilegeFormat, roleId, objType, objId, privilegeId) 1293 } 1294 1295 func getSqlForCheckRoleHasPrivilegeWGO(privilegeId int64) string { 1296 return fmt.Sprintf(checkRoleHasPrivilegeWGOFormat, privilegeId) 1297 } 1298 1299 func getSqlForUpdateRolePrivs(userId int64, timestamp string, withGrantOption bool, roleId int64, objType objectType, objId, privilegeId int64) string { 1300 return fmt.Sprintf(updateRolePrivsFormat, userId, timestamp, withGrantOption, roleId, objType, objId, privilegeId) 1301 } 1302 1303 func getSqlForInsertRolePrivs(roleId int64, roleName, objType string, objId, privilegeId int64, privilegeName, privilegeLevel string, operationUserId int64, grantedTime string, withGrantOption bool) string { 1304 return fmt.Sprintf(insertRolePrivsFormat, roleId, roleName, objType, objId, privilegeId, privilegeName, privilegeLevel, operationUserId, grantedTime, withGrantOption) 1305 } 1306 1307 func getSqlForDeleteRolePrivs(roleId int64, objType string, objId, privilegeId int64, privilegeLevel string) string { 1308 return fmt.Sprintf(deleteRolePrivsFormat, roleId, objType, objId, privilegeId, privilegeLevel) 1309 } 1310 1311 func getSqlForCheckWithGrantOptionForTableStarStar(roleId int64, privId PrivilegeType) string { 1312 return fmt.Sprintf(checkWithGrantOptionForTableStarStar, objectTypeTable, roleId, privId, privilegeLevelStarStar) 1313 } 1314 1315 func getSqlForCheckWithGrantOptionForTableDatabaseStar(roleId int64, privId PrivilegeType, dbName string) string { 1316 return fmt.Sprintf(checkWithGrantOptionForTableDatabaseStar, objectTypeTable, roleId, privId, privilegeLevelDatabaseStar, dbName) 1317 } 1318 1319 func getSqlForCheckWithGrantOptionForTableDatabaseTable(roleId int64, privId PrivilegeType, dbName string, tableName string) string { 1320 return fmt.Sprintf(checkWithGrantOptionForTableDatabaseTable, objectTypeTable, roleId, privId, privilegeLevelDatabaseTable, dbName, tableName) 1321 } 1322 1323 func getSqlForCheckWithGrantOptionForDatabaseStar(roleId int64, privId PrivilegeType) string { 1324 return fmt.Sprintf(checkWithGrantOptionForDatabaseStar, objectTypeDatabase, roleId, privId, privilegeLevelStar) 1325 } 1326 1327 func getSqlForCheckWithGrantOptionForDatabaseStarStar(roleId int64, privId PrivilegeType) string { 1328 return fmt.Sprintf(checkWithGrantOptionForDatabaseStarStar, objectTypeDatabase, roleId, privId, privilegeLevelStarStar) 1329 } 1330 1331 func getSqlForCheckWithGrantOptionForDatabaseDB(roleId int64, privId PrivilegeType, dbName string) string { 1332 return fmt.Sprintf(checkWithGrantOptionForDatabaseDB, objectTypeDatabase, roleId, privId, privilegeLevelDatabase, dbName) 1333 } 1334 1335 func getSqlForCheckWithGrantOptionForAccountStar(roleId int64, privId PrivilegeType) string { 1336 return fmt.Sprintf(checkWithGrantOptionForAccountStar, objectTypeAccount, roleId, privId, privilegeLevelStarStar) 1337 } 1338 1339 func getSqlForCheckRoleHasTableLevelPrivilege(roleId int64, privId PrivilegeType, dbName string, tableName string) string { 1340 return fmt.Sprintf(checkRoleHasTableLevelPrivilegeFormat, objectTypeTable, roleId, privId, privilegeLevelDatabaseTable, privilegeLevelTable, dbName, tableName) 1341 } 1342 1343 func getSqlForCheckRoleHasTableLevelForDatabaseStar(roleId int64, privId PrivilegeType, dbName string) string { 1344 return fmt.Sprintf(checkRoleHasTableLevelForDatabaseStarFormat, objectTypeTable, roleId, privId, privilegeLevelDatabaseStar, privilegeLevelStar, dbName) 1345 } 1346 1347 func getSqlForCheckRoleHasTableLevelForStarStar(roleId int64, privId PrivilegeType) string { 1348 return fmt.Sprintf(checkRoleHasTableLevelForStarStarFormat, objectTypeTable, roleId, privId, privilegeLevelStarStar) 1349 } 1350 1351 func getSqlForCheckRoleHasDatabaseLevelForStarStar(roleId int64, privId PrivilegeType, level privilegeLevelType) string { 1352 return fmt.Sprintf(checkRoleHasDatabaseLevelForStarStarFormat, objectTypeDatabase, roleId, privId, level) 1353 } 1354 1355 func getSqlForCheckRoleHasDatabaseLevelForDatabase(roleId int64, privId PrivilegeType, dbName string) string { 1356 return fmt.Sprintf(checkRoleHasDatabaseLevelForDatabaseFormat, objectTypeDatabase, roleId, privId, privilegeLevelDatabase, dbName) 1357 } 1358 1359 func getSqlForCheckRoleHasAccountLevelForStar(roleId int64, privId PrivilegeType) string { 1360 return fmt.Sprintf(checkRoleHasAccountLevelForStarFormat, objectTypeAccount, roleId, privId, privilegeLevelStar) 1361 } 1362 1363 func getSqlForCheckDatabase(dbName string) string { 1364 return fmt.Sprintf(checkDatabaseFormat, dbName) 1365 } 1366 1367 func getSqlForCheckDatabaseTable(dbName, tableName string) string { 1368 return fmt.Sprintf(checkDatabaseTableFormat, dbName, tableName) 1369 } 1370 1371 func getSqlForDeleteRole(roleId int64) []string { 1372 return []string{ 1373 fmt.Sprintf(deleteRoleFromMoRoleFormat, roleId), 1374 fmt.Sprintf(deleteRoleFromMoUserGrantFormat, roleId), 1375 fmt.Sprintf(deleteRoleFromMoRoleGrantFormat, roleId, roleId), 1376 fmt.Sprintf(deleteRoleFromMoRolePrivsFormat, roleId), 1377 } 1378 } 1379 1380 func getSqlForDropAccount() []string { 1381 return dropSqls 1382 } 1383 1384 func getSqlForDeleteUser(userId int64) []string { 1385 return []string{ 1386 fmt.Sprintf(deleteUserFromMoUserFormat, userId), 1387 fmt.Sprintf(deleteUserFromMoUserGrantFormat, userId), 1388 } 1389 } 1390 1391 func getSqlForDeleteMysqlCompatbilityMode(dtname string) string { 1392 return fmt.Sprintf(deleteMysqlCompatbilityModeFormat, dtname) 1393 } 1394 1395 func getSqlForDeleteMysqlCompatbilityModeForAccount(account_name string) string { 1396 return fmt.Sprintf(deleteMysqlCompatbilityModeForAccountFormat, account_name) 1397 } 1398 1399 // isClusterTable decides a table is the index table or not 1400 func isIndexTable(name string) bool { 1401 return strings.HasPrefix(name, "__mo_index_unique") 1402 } 1403 1404 // isClusterTable decides a table is the cluster table or not 1405 func isClusterTable(dbName, name string) bool { 1406 if dbName == moCatalog { 1407 //if it is neither among the tables nor the index table, 1408 //it is the cluster table. 1409 if _, ok := predefinedTables[name]; !ok && !isIndexTable(name) { 1410 return true 1411 } 1412 } 1413 return false 1414 } 1415 1416 func isBannedDatabase(dbName string) bool { 1417 _, ok := bannedCatalogDatabases[dbName] 1418 return ok 1419 } 1420 1421 func isBannedPrivilege(priv PrivilegeType) bool { 1422 _, ok := bannedPrivileges[priv] 1423 return ok 1424 } 1425 1426 type specialTag int 1427 1428 const ( 1429 specialTagNone specialTag = 0 1430 specialTagAdmin specialTag = 1 1431 specialTagWithGrantOption specialTag = 2 1432 specialTagOwnerOfObject specialTag = 4 1433 ) 1434 1435 type privilegeKind int 1436 1437 const ( 1438 privilegeKindGeneral privilegeKind = iota //as same as definition in the privilegeEntriesMap 1439 privilegeKindInherit //General + with_grant_option 1440 privilegeKindSpecial //no obj_type,obj_id,privilege_level. only needs (MOADMIN / ACCOUNTADMIN, with_grant_option, owner of object) 1441 privilegeKindNone //does not need any privilege 1442 ) 1443 1444 type clusterTableOperationType int 1445 1446 const ( 1447 clusterTableNone clusterTableOperationType = iota 1448 clusterTableCreate 1449 clusterTableSelect //read only 1450 clusterTableModify //include insert,update,delete 1451 clusterTableDrop 1452 ) 1453 1454 type privilege struct { 1455 kind privilegeKind 1456 //account: the privilege can be defined before constructing the plan. 1457 //database: (do not need the database_id) the privilege can be defined before constructing the plan. 1458 //table: need table id. the privilege can be defined after constructing the plan. 1459 //function: need function id ? 1460 objType objectType 1461 entries []privilegeEntry 1462 special specialTag 1463 //the statement writes the database or table directly like drop database and table 1464 writeDatabaseAndTableDirectly bool 1465 //operate the cluster table 1466 isClusterTable bool 1467 //operation on cluster table, 1468 clusterTableOperation clusterTableOperationType 1469 } 1470 1471 func (p *privilege) objectType() objectType { 1472 return p.objType 1473 } 1474 1475 func (p *privilege) privilegeKind() privilegeKind { 1476 return p.kind 1477 } 1478 1479 type privilegeEntryType int 1480 1481 const ( 1482 privilegeEntryTypeGeneral privilegeEntryType = iota 1483 privilegeEntryTypeCompound //multi privileges take effect together 1484 ) 1485 1486 // privilegeItem is the item for in the compound entry 1487 type privilegeItem struct { 1488 privilegeTyp PrivilegeType 1489 role *tree.Role 1490 users []*tree.User 1491 dbName string 1492 tableName string 1493 isClusterTable bool 1494 clusterTableOperation clusterTableOperationType 1495 } 1496 1497 // compoundEntry is the entry has multi privilege items 1498 type compoundEntry struct { 1499 items []privilegeItem 1500 } 1501 1502 // privilegeEntry denotes the entry of the privilege that appears in the table mo_role_privs 1503 type privilegeEntry struct { 1504 privilegeId PrivilegeType 1505 //the predefined privilege level for the privilege. 1506 //it is not always the same as the one in the runtime. 1507 privilegeLevel privilegeLevelType 1508 objType objectType 1509 objId int 1510 withGrantOption bool 1511 //for object type table 1512 databaseName string 1513 tableName string 1514 privilegeEntryTyp privilegeEntryType 1515 compound *compoundEntry 1516 } 1517 1518 var ( 1519 //initial privilege entries 1520 privilegeEntriesMap = map[PrivilegeType]privilegeEntry{ 1521 PrivilegeTypeCreateAccount: {PrivilegeTypeCreateAccount, privilegeLevelStar, objectTypeAccount, objectIDAll, false, "", "", privilegeEntryTypeGeneral, nil}, 1522 PrivilegeTypeDropAccount: {PrivilegeTypeDropAccount, privilegeLevelStar, objectTypeAccount, objectIDAll, false, "", "", privilegeEntryTypeGeneral, nil}, 1523 PrivilegeTypeAlterAccount: {PrivilegeTypeAlterAccount, privilegeLevelStar, objectTypeAccount, objectIDAll, false, "", "", privilegeEntryTypeGeneral, nil}, 1524 PrivilegeTypeCreateUser: {PrivilegeTypeCreateUser, privilegeLevelStar, objectTypeAccount, objectIDAll, true, "", "", privilegeEntryTypeGeneral, nil}, 1525 PrivilegeTypeDropUser: {PrivilegeTypeDropUser, privilegeLevelStar, objectTypeAccount, objectIDAll, true, "", "", privilegeEntryTypeGeneral, nil}, 1526 PrivilegeTypeAlterUser: {PrivilegeTypeAlterUser, privilegeLevelStar, objectTypeAccount, objectIDAll, true, "", "", privilegeEntryTypeGeneral, nil}, 1527 PrivilegeTypeCreateRole: {PrivilegeTypeCreateRole, privilegeLevelStar, objectTypeAccount, objectIDAll, true, "", "", privilegeEntryTypeGeneral, nil}, 1528 PrivilegeTypeDropRole: {PrivilegeTypeDropRole, privilegeLevelStar, objectTypeAccount, objectIDAll, true, "", "", privilegeEntryTypeGeneral, nil}, 1529 PrivilegeTypeAlterRole: {PrivilegeTypeAlterRole, privilegeLevelStar, objectTypeAccount, objectIDAll, true, "", "", privilegeEntryTypeGeneral, nil}, 1530 PrivilegeTypeCreateDatabase: {PrivilegeTypeCreateDatabase, privilegeLevelStar, objectTypeAccount, objectIDAll, true, "", "", privilegeEntryTypeGeneral, nil}, 1531 PrivilegeTypeDropDatabase: {PrivilegeTypeDropDatabase, privilegeLevelStar, objectTypeAccount, objectIDAll, true, "", "", privilegeEntryTypeGeneral, nil}, 1532 PrivilegeTypeShowDatabases: {PrivilegeTypeShowDatabases, privilegeLevelStar, objectTypeAccount, objectIDAll, true, "", "", privilegeEntryTypeGeneral, nil}, 1533 PrivilegeTypeConnect: {PrivilegeTypeConnect, privilegeLevelStar, objectTypeAccount, objectIDAll, true, "", "", privilegeEntryTypeGeneral, nil}, 1534 PrivilegeTypeManageGrants: {PrivilegeTypeManageGrants, privilegeLevelStar, objectTypeAccount, objectIDAll, true, "", "", privilegeEntryTypeGeneral, nil}, 1535 PrivilegeTypeAccountAll: {PrivilegeTypeAccountAll, privilegeLevelStar, objectTypeAccount, objectIDAll, true, "", "", privilegeEntryTypeGeneral, nil}, 1536 PrivilegeTypeAccountOwnership: {PrivilegeTypeAccountOwnership, privilegeLevelStar, objectTypeAccount, objectIDAll, true, "", "", privilegeEntryTypeGeneral, nil}, 1537 PrivilegeTypeUserOwnership: {PrivilegeTypeUserOwnership, privilegeLevelStar, objectTypeAccount, objectIDAll, true, "", "", privilegeEntryTypeGeneral, nil}, 1538 PrivilegeTypeRoleOwnership: {PrivilegeTypeRoleOwnership, privilegeLevelStar, objectTypeAccount, objectIDAll, true, "", "", privilegeEntryTypeGeneral, nil}, 1539 PrivilegeTypeShowTables: {PrivilegeTypeShowTables, privilegeLevelStar, objectTypeDatabase, objectIDAll, true, "", "", privilegeEntryTypeGeneral, nil}, 1540 PrivilegeTypeCreateObject: {PrivilegeTypeCreateObject, privilegeLevelStar, objectTypeDatabase, objectIDAll, true, "", "", privilegeEntryTypeGeneral, nil}, 1541 PrivilegeTypeCreateTable: {PrivilegeTypeCreateTable, privilegeLevelStar, objectTypeDatabase, objectIDAll, true, "", "", privilegeEntryTypeGeneral, nil}, 1542 PrivilegeTypeCreateView: {PrivilegeTypeCreateView, privilegeLevelStar, objectTypeDatabase, objectIDAll, true, "", "", privilegeEntryTypeGeneral, nil}, 1543 PrivilegeTypeDropObject: {PrivilegeTypeDropObject, privilegeLevelStar, objectTypeDatabase, objectIDAll, true, "", "", privilegeEntryTypeGeneral, nil}, 1544 PrivilegeTypeDropTable: {PrivilegeTypeDropTable, privilegeLevelStar, objectTypeDatabase, objectIDAll, true, "", "", privilegeEntryTypeGeneral, nil}, 1545 PrivilegeTypeDropView: {PrivilegeTypeDropView, privilegeLevelStar, objectTypeDatabase, objectIDAll, true, "", "", privilegeEntryTypeGeneral, nil}, 1546 PrivilegeTypeAlterObject: {PrivilegeTypeAlterObject, privilegeLevelStar, objectTypeDatabase, objectIDAll, true, "", "", privilegeEntryTypeGeneral, nil}, 1547 PrivilegeTypeAlterTable: {PrivilegeTypeAlterTable, privilegeLevelStar, objectTypeDatabase, objectIDAll, true, "", "", privilegeEntryTypeGeneral, nil}, 1548 PrivilegeTypeAlterView: {PrivilegeTypeAlterView, privilegeLevelStar, objectTypeDatabase, objectIDAll, true, "", "", privilegeEntryTypeGeneral, nil}, 1549 PrivilegeTypeDatabaseAll: {PrivilegeTypeDatabaseAll, privilegeLevelStar, objectTypeDatabase, objectIDAll, true, "", "", privilegeEntryTypeGeneral, nil}, 1550 PrivilegeTypeDatabaseOwnership: {PrivilegeTypeDatabaseOwnership, privilegeLevelStar, objectTypeDatabase, objectIDAll, true, "", "", privilegeEntryTypeGeneral, nil}, 1551 PrivilegeTypeSelect: {PrivilegeTypeSelect, privilegeLevelStarStar, objectTypeTable, objectIDAll, true, "", "", privilegeEntryTypeGeneral, nil}, 1552 PrivilegeTypeInsert: {PrivilegeTypeInsert, privilegeLevelStarStar, objectTypeTable, objectIDAll, true, "", "", privilegeEntryTypeGeneral, nil}, 1553 PrivilegeTypeUpdate: {PrivilegeTypeUpdate, privilegeLevelStarStar, objectTypeTable, objectIDAll, true, "", "", privilegeEntryTypeGeneral, nil}, 1554 PrivilegeTypeTruncate: {PrivilegeTypeTruncate, privilegeLevelStarStar, objectTypeTable, objectIDAll, true, "", "", privilegeEntryTypeGeneral, nil}, 1555 PrivilegeTypeDelete: {PrivilegeTypeDelete, privilegeLevelStarStar, objectTypeTable, objectIDAll, true, "", "", privilegeEntryTypeGeneral, nil}, 1556 PrivilegeTypeReference: {PrivilegeTypeReference, privilegeLevelStarStar, objectTypeTable, objectIDAll, true, "", "", privilegeEntryTypeGeneral, nil}, 1557 PrivilegeTypeIndex: {PrivilegeTypeIndex, privilegeLevelStarStar, objectTypeTable, objectIDAll, true, "", "", privilegeEntryTypeGeneral, nil}, 1558 PrivilegeTypeTableAll: {PrivilegeTypeTableAll, privilegeLevelStarStar, objectTypeTable, objectIDAll, true, "", "", privilegeEntryTypeGeneral, nil}, 1559 PrivilegeTypeTableOwnership: {PrivilegeTypeTableOwnership, privilegeLevelStarStar, objectTypeTable, objectIDAll, true, "", "", privilegeEntryTypeGeneral, nil}, 1560 PrivilegeTypeExecute: {PrivilegeTypeExecute, privilegeLevelRoutine, objectTypeFunction, objectIDAll, true, "", "", privilegeEntryTypeGeneral, nil}, 1561 PrivilegeTypeValues: {PrivilegeTypeValues, privilegeLevelTable, objectTypeTable, objectIDAll, true, "", "", privilegeEntryTypeGeneral, nil}, 1562 } 1563 1564 //the initial entries of mo_role_privs for the role 'moadmin' 1565 entriesOfMoAdminForMoRolePrivsFor = []PrivilegeType{ 1566 PrivilegeTypeCreateAccount, 1567 PrivilegeTypeDropAccount, 1568 PrivilegeTypeAlterAccount, 1569 PrivilegeTypeCreateUser, 1570 PrivilegeTypeDropUser, 1571 PrivilegeTypeAlterUser, 1572 PrivilegeTypeCreateRole, 1573 PrivilegeTypeDropRole, 1574 PrivilegeTypeCreateDatabase, 1575 PrivilegeTypeDropDatabase, 1576 PrivilegeTypeShowDatabases, 1577 PrivilegeTypeConnect, 1578 PrivilegeTypeManageGrants, 1579 PrivilegeTypeAccountAll, 1580 PrivilegeTypeShowTables, 1581 PrivilegeTypeCreateTable, 1582 PrivilegeTypeDropTable, 1583 PrivilegeTypeAlterTable, 1584 PrivilegeTypeCreateView, 1585 PrivilegeTypeDropView, 1586 PrivilegeTypeAlterView, 1587 PrivilegeTypeDatabaseAll, 1588 PrivilegeTypeDatabaseOwnership, 1589 PrivilegeTypeSelect, 1590 PrivilegeTypeInsert, 1591 PrivilegeTypeUpdate, 1592 PrivilegeTypeTruncate, 1593 PrivilegeTypeDelete, 1594 PrivilegeTypeReference, 1595 PrivilegeTypeIndex, 1596 PrivilegeTypeTableAll, 1597 PrivilegeTypeTableOwnership, 1598 PrivilegeTypeValues, 1599 } 1600 1601 //the initial entries of mo_role_privs for the role 'accountadmin' 1602 entriesOfAccountAdminForMoRolePrivsFor = []PrivilegeType{ 1603 PrivilegeTypeCreateUser, 1604 PrivilegeTypeDropUser, 1605 PrivilegeTypeAlterUser, 1606 PrivilegeTypeCreateRole, 1607 PrivilegeTypeDropRole, 1608 PrivilegeTypeCreateDatabase, 1609 PrivilegeTypeDropDatabase, 1610 PrivilegeTypeShowDatabases, 1611 PrivilegeTypeConnect, 1612 PrivilegeTypeManageGrants, 1613 PrivilegeTypeAccountAll, 1614 PrivilegeTypeShowTables, 1615 PrivilegeTypeCreateTable, 1616 PrivilegeTypeDropTable, 1617 PrivilegeTypeAlterTable, 1618 PrivilegeTypeCreateView, 1619 PrivilegeTypeDropView, 1620 PrivilegeTypeAlterView, 1621 PrivilegeTypeDatabaseAll, 1622 PrivilegeTypeDatabaseOwnership, 1623 PrivilegeTypeSelect, 1624 PrivilegeTypeInsert, 1625 PrivilegeTypeUpdate, 1626 PrivilegeTypeTruncate, 1627 PrivilegeTypeDelete, 1628 PrivilegeTypeReference, 1629 PrivilegeTypeIndex, 1630 PrivilegeTypeTableAll, 1631 PrivilegeTypeTableOwnership, 1632 PrivilegeTypeValues, 1633 } 1634 1635 //the initial entries of mo_role_privs for the role 'public' 1636 entriesOfPublicForMoRolePrivsFor = []PrivilegeType{ 1637 PrivilegeTypeConnect, 1638 } 1639 ) 1640 1641 type verifiedRoleType int 1642 1643 const ( 1644 roleType verifiedRoleType = iota 1645 userType 1646 ) 1647 1648 // privilegeCache cache privileges on table 1649 type privilegeCache struct { 1650 //For objectType table 1651 //For objectType table *, *.* 1652 storeForTable [int(privilegeLevelEnd)]btree.Set[PrivilegeType] 1653 //For objectType table database.* 1654 storeForTable2 btree.Map[string, *btree.Set[PrivilegeType]] 1655 //For objectType table database.table , table 1656 storeForTable3 btree.Map[string, *btree.Map[string, *btree.Set[PrivilegeType]]] 1657 1658 //For objectType database *, *.* 1659 storeForDatabase [int(privilegeLevelEnd)]btree.Set[PrivilegeType] 1660 //For objectType database 1661 storeForDatabase2 btree.Map[string, *btree.Set[PrivilegeType]] 1662 //For objectType account * 1663 storeForAccount [int(privilegeLevelEnd)]btree.Set[PrivilegeType] 1664 total atomic.Uint64 1665 hit atomic.Uint64 1666 } 1667 1668 // has checks the cache has privilege on a table 1669 func (pc *privilegeCache) has(objTyp objectType, plt privilegeLevelType, dbName, tableName string, priv PrivilegeType) bool { 1670 pc.total.Add(1) 1671 privSet := pc.getPrivilegeSet(objTyp, plt, dbName, tableName) 1672 if privSet != nil && privSet.Contains(priv) { 1673 pc.hit.Add(1) 1674 return true 1675 } 1676 return false 1677 } 1678 1679 func (pc *privilegeCache) getPrivilegeSet(objTyp objectType, plt privilegeLevelType, dbName, tableName string) *btree.Set[PrivilegeType] { 1680 switch objTyp { 1681 case objectTypeTable: 1682 switch plt { 1683 case privilegeLevelStarStar, privilegeLevelStar: 1684 return &pc.storeForTable[plt] 1685 case privilegeLevelDatabaseStar: 1686 dbStore, ok1 := pc.storeForTable2.Get(dbName) 1687 if !ok1 { 1688 dbStore = &btree.Set[PrivilegeType]{} 1689 pc.storeForTable2.Set(dbName, dbStore) 1690 } 1691 return dbStore 1692 case privilegeLevelDatabaseTable, privilegeLevelTable: 1693 tableStore, ok1 := pc.storeForTable3.Get(dbName) 1694 if !ok1 { 1695 tableStore = &btree.Map[string, *btree.Set[PrivilegeType]]{} 1696 pc.storeForTable3.Set(dbName, tableStore) 1697 } 1698 privSet, ok2 := tableStore.Get(tableName) 1699 if !ok2 { 1700 privSet = &btree.Set[PrivilegeType]{} 1701 tableStore.Set(tableName, privSet) 1702 } 1703 return privSet 1704 default: 1705 return nil 1706 } 1707 case objectTypeDatabase: 1708 switch plt { 1709 case privilegeLevelStar, privilegeLevelStarStar: 1710 return &pc.storeForDatabase[plt] 1711 case privilegeLevelDatabase: 1712 dbStore, ok1 := pc.storeForDatabase2.Get(dbName) 1713 if !ok1 { 1714 dbStore = &btree.Set[PrivilegeType]{} 1715 pc.storeForDatabase2.Set(dbName, dbStore) 1716 } 1717 return dbStore 1718 default: 1719 return nil 1720 } 1721 case objectTypeAccount: 1722 return &pc.storeForAccount[plt] 1723 default: 1724 return nil 1725 } 1726 1727 } 1728 1729 // set replaces the privileges by new ones 1730 func (pc *privilegeCache) set(objTyp objectType, plt privilegeLevelType, dbName, tableName string, priv ...PrivilegeType) { 1731 privSet := pc.getPrivilegeSet(objTyp, plt, dbName, tableName) 1732 if privSet != nil { 1733 privSet.Clear() 1734 for _, p := range priv { 1735 privSet.Insert(p) 1736 } 1737 } 1738 } 1739 1740 // add puts the privileges without replacing existed ones 1741 func (pc *privilegeCache) add(objTyp objectType, plt privilegeLevelType, dbName, tableName string, priv ...PrivilegeType) { 1742 privSet := pc.getPrivilegeSet(objTyp, plt, dbName, tableName) 1743 if privSet != nil { 1744 for _, p := range priv { 1745 privSet.Insert(p) 1746 } 1747 } 1748 } 1749 1750 // invalidate makes the cache empty 1751 func (pc *privilegeCache) invalidate() { 1752 //total := pc.total.Swap(0) 1753 //hit := pc.hit.Swap(0) 1754 for i := privilegeLevelStar; i < privilegeLevelEnd; i++ { 1755 pc.storeForTable[i].Clear() 1756 pc.storeForDatabase[i].Clear() 1757 pc.storeForAccount[i].Clear() 1758 } 1759 pc.storeForTable2.Clear() 1760 pc.storeForTable3.Clear() 1761 pc.storeForDatabase2.Clear() 1762 //ratio := float64(0) 1763 //if total == 0 { 1764 // ratio = 0 1765 //} else { 1766 // ratio = float64(hit) / float64(total) 1767 //} 1768 //logutil.Debugf("-->hit %d total %d ratio %f", hit, total, ratio) 1769 } 1770 1771 // verifiedRole holds the role info that has been checked 1772 type verifiedRole struct { 1773 typ verifiedRoleType 1774 name string 1775 id int64 1776 userIsAdmin bool 1777 } 1778 1779 // verifyRoleFunc gets result set from mo_role_grant or mo_user_grant 1780 func verifyRoleFunc(ctx context.Context, bh BackgroundExec, sql, name string, typ verifiedRoleType) (*verifiedRole, error) { 1781 var err error 1782 var erArray []ExecResult 1783 var roleId int64 1784 bh.ClearExecResultSet() 1785 err = bh.Exec(ctx, sql) 1786 if err != nil { 1787 return nil, err 1788 } 1789 1790 erArray, err = getResultSet(ctx, bh) 1791 if err != nil { 1792 return nil, err 1793 } 1794 1795 if execResultArrayHasData(erArray) { 1796 roleId, err = erArray[0].GetInt64(ctx, 0, 0) 1797 if err != nil { 1798 return nil, err 1799 } 1800 return &verifiedRole{typ, name, roleId, false}, nil 1801 } 1802 return nil, nil 1803 } 1804 1805 // userIsAdministrator checks the user is the administrator 1806 func userIsAdministrator(ctx context.Context, bh BackgroundExec, userId int64, account *TenantInfo) (bool, error) { 1807 var err error 1808 var erArray []ExecResult 1809 var sql string 1810 if account.IsSysTenant() { 1811 sql = getSqlForRoleOfUser(userId, moAdminRoleName) 1812 } else { 1813 sql = getSqlForRoleOfUser(userId, accountAdminRoleName) 1814 } 1815 1816 bh.ClearExecResultSet() 1817 err = bh.Exec(ctx, sql) 1818 if err != nil { 1819 return false, err 1820 } 1821 1822 erArray, err = getResultSet(ctx, bh) 1823 if err != nil { 1824 return false, err 1825 } 1826 1827 if execResultArrayHasData(erArray) { 1828 return true, nil 1829 } 1830 return false, nil 1831 } 1832 1833 type visitTag int 1834 1835 const ( 1836 vtUnVisited visitTag = 0 1837 vtVisited visitTag = 1 1838 vtVisiting visitTag = -1 1839 ) 1840 1841 // edge <from,to> in the graph 1842 type edge struct { 1843 from int64 1844 to int64 1845 invalid bool 1846 } 1847 1848 func (e *edge) isInvalid() bool { 1849 return e.invalid 1850 } 1851 1852 func (e *edge) setInvalid() { 1853 e.invalid = true 1854 } 1855 1856 // graph the acyclic graph 1857 type graph struct { 1858 edges []*edge 1859 vertexes map[int64]int 1860 adjacent map[int64][]int 1861 } 1862 1863 func NewGraph() *graph { 1864 return &graph{ 1865 vertexes: make(map[int64]int), 1866 adjacent: make(map[int64][]int), 1867 } 1868 } 1869 1870 // addEdge adds the directed edge <from,to> into the graph 1871 func (g *graph) addEdge(from, to int64) int { 1872 edgeId := len(g.edges) 1873 g.edges = append(g.edges, &edge{from, to, false}) 1874 g.adjacent[from] = append(g.adjacent[from], edgeId) 1875 g.vertexes[from] = 0 1876 g.vertexes[to] = 0 1877 return edgeId 1878 } 1879 1880 // removeEdge removes the directed edge (edgeId) from the graph 1881 func (g *graph) removeEdge(edgeId int) { 1882 e := g.getEdge(edgeId) 1883 e.setInvalid() 1884 } 1885 1886 func (g *graph) getEdge(eid int) *edge { 1887 return g.edges[eid] 1888 } 1889 1890 // dfs use the toposort to check the loop 1891 func (g *graph) toposort(u int64, visited map[int64]visitTag) bool { 1892 visited[u] = vtVisiting 1893 //loop on adjacent vertex 1894 for _, eid := range g.adjacent[u] { 1895 e := g.getEdge(eid) 1896 if e.isInvalid() { 1897 continue 1898 } 1899 if visited[e.to] == vtVisiting { //find the loop in the vertex 1900 return false 1901 } else if visited[e.to] == vtUnVisited && !g.toposort(e.to, visited) { //find the loop in the adjacent vertexes 1902 return false 1903 } 1904 } 1905 visited[u] = vtVisited 1906 return true 1907 } 1908 1909 // hasLoop checks the loop 1910 func (g *graph) hasLoop(start int64) bool { 1911 visited := make(map[int64]visitTag) 1912 for v := range g.vertexes { 1913 visited[v] = vtUnVisited 1914 } 1915 1916 return !g.toposort(start, visited) 1917 } 1918 1919 // nameIsInvalid checks the name of account/user/role is valid or not 1920 func nameIsInvalid(name string) bool { 1921 s := strings.TrimSpace(name) 1922 if len(s) == 0 { 1923 return true 1924 } 1925 return strings.Contains(s, ":") || strings.Contains(s, "#") 1926 } 1927 1928 // normalizeName normalizes and checks the name 1929 func normalizeName(ctx context.Context, name string) (string, error) { 1930 s := strings.TrimSpace(name) 1931 if nameIsInvalid(s) { 1932 return "", moerr.NewInternalError(ctx, `the name "%s" is invalid`, name) 1933 } 1934 return s, nil 1935 } 1936 1937 // normalizeNameOfRole normalizes the name 1938 func normalizeNameOfRole(ctx context.Context, role *tree.Role) error { 1939 var err error 1940 role.UserName, err = normalizeName(ctx, role.UserName) 1941 return err 1942 } 1943 1944 // normalizeNamesOfRoles normalizes the names and checks them 1945 func normalizeNamesOfRoles(ctx context.Context, roles []*tree.Role) error { 1946 var err error 1947 for i := 0; i < len(roles); i++ { 1948 err = normalizeNameOfRole(ctx, roles[i]) 1949 if err != nil { 1950 return err 1951 } 1952 } 1953 return nil 1954 } 1955 1956 // normalizeNameOfUser normalizes the name 1957 func normalizeNameOfUser(ctx context.Context, user *tree.User) error { 1958 var err error 1959 user.Username, err = normalizeName(ctx, user.Username) 1960 return err 1961 } 1962 1963 // normalizeNamesOfUsers normalizes the names and checks them 1964 func normalizeNamesOfUsers(ctx context.Context, users []*tree.User) error { 1965 var err error 1966 for i := 0; i < len(users); i++ { 1967 err = normalizeNameOfUser(ctx, users[i]) 1968 if err != nil { 1969 return err 1970 } 1971 } 1972 return nil 1973 } 1974 1975 func doAlterAccount(ctx context.Context, ses *Session, aa *tree.AlterAccount) error { 1976 var err error 1977 var sql string 1978 var erArray []ExecResult 1979 var targetAccountId uint64 1980 var accountExist bool 1981 account := ses.GetTenantInfo() 1982 if !(account.IsSysTenant() && account.IsMoAdminRole()) { 1983 return moerr.NewInternalError(ctx, "tenant %s user %s role %s do not have the privilege to alter the account", 1984 account.GetTenant(), account.GetUser(), account.GetDefaultRole()) 1985 } 1986 1987 optionBits := uint8(0) 1988 if aa.AuthOption.Exist { 1989 optionBits |= 1 1990 } 1991 if aa.StatusOption.Exist { 1992 optionBits |= 1 << 1 1993 } 1994 if aa.Comment.Exist { 1995 optionBits |= 1 << 2 1996 } 1997 optionCount := bits.OnesCount8(optionBits) 1998 if optionCount == 0 { 1999 return moerr.NewInternalError(ctx, "at least one option at a time") 2000 } 2001 if optionCount > 1 { 2002 return moerr.NewInternalError(ctx, "at most one option at a time") 2003 } 2004 2005 //normalize the name 2006 aa.Name, err = normalizeName(ctx, aa.Name) 2007 if err != nil { 2008 return err 2009 } 2010 2011 if aa.AuthOption.Exist { 2012 aa.AuthOption.AdminName, err = normalizeName(ctx, aa.AuthOption.AdminName) 2013 if err != nil { 2014 return err 2015 } 2016 if aa.AuthOption.IdentifiedType.Typ != tree.AccountIdentifiedByPassword { 2017 return moerr.NewInternalError(ctx, "only support identified by password") 2018 } 2019 2020 if len(aa.AuthOption.IdentifiedType.Str) == 0 { 2021 err = moerr.NewInternalError(ctx, "password is empty string") 2022 return err 2023 } 2024 } 2025 2026 if aa.StatusOption.Exist { 2027 //SYS account can not be suspended 2028 if isSysTenant(aa.Name) { 2029 return moerr.NewInternalError(ctx, "account sys can not be suspended") 2030 } 2031 } 2032 2033 bh := ses.GetBackgroundExec(ctx) 2034 defer bh.Close() 2035 2036 err = bh.Exec(ctx, "begin") 2037 if err != nil { 2038 goto handleFailed 2039 } 2040 2041 //step 1: check account exists or not 2042 //get accountID 2043 sql = getSqlForCheckTenant(aa.Name) 2044 bh.ClearExecResultSet() 2045 err = bh.Exec(ctx, sql) 2046 if err != nil { 2047 goto handleFailed 2048 } 2049 2050 erArray, err = getResultSet(ctx, bh) 2051 if err != nil { 2052 goto handleFailed 2053 } 2054 2055 if execResultArrayHasData(erArray) { 2056 for i := uint64(0); i < erArray[0].GetRowCount(); i++ { 2057 targetAccountId, err = erArray[0].GetUint64(ctx, i, 0) 2058 if err != nil { 2059 goto handleFailed 2060 } 2061 } 2062 accountExist = true 2063 } else { 2064 //IfExists : 2065 // false : return an error 2066 // true : skip and do nothing 2067 if !aa.IfExists { 2068 err = moerr.NewInternalError(ctx, "there is no account %s", aa.Name) 2069 goto handleFailed 2070 } 2071 } 2072 2073 if accountExist { 2074 //Option 1: alter the password of admin for the account 2075 if aa.AuthOption.Exist { 2076 //!!!NOTE!!!:switch into the target account's context, then update the table mo_user. 2077 accountCtx := context.WithValue(ctx, defines.TenantIDKey{}, uint32(targetAccountId)) 2078 2079 //1, check the admin exists or not 2080 sql = getSqlForPasswordOfUser(aa.AuthOption.AdminName) 2081 bh.ClearExecResultSet() 2082 err = bh.Exec(accountCtx, sql) 2083 if err != nil { 2084 goto handleFailed 2085 } 2086 2087 erArray, err = getResultSet(accountCtx, bh) 2088 if err != nil { 2089 goto handleFailed 2090 } 2091 2092 if !execResultArrayHasData(erArray) { 2093 err = moerr.NewInternalError(accountCtx, "there is no user %s", aa.AuthOption.AdminName) 2094 goto handleFailed 2095 } 2096 2097 //2, update the password 2098 sql = getSqlForUpdatePasswordOfUser(aa.AuthOption.IdentifiedType.Str, aa.AuthOption.AdminName) 2099 bh.ClearExecResultSet() 2100 err = bh.Exec(accountCtx, sql) 2101 if err != nil { 2102 goto handleFailed 2103 } 2104 } 2105 2106 //Option 2: alter the comment of the account 2107 if aa.Comment.Exist { 2108 sql = getSqlForUpdateCommentsOfAccount(aa.Comment.Comment, aa.Name) 2109 bh.ClearExecResultSet() 2110 err = bh.Exec(ctx, sql) 2111 if err != nil { 2112 goto handleFailed 2113 } 2114 } 2115 2116 //Option 3: suspend or resume the account 2117 if aa.StatusOption.Exist { 2118 sql = getSqlForUpdateStatusOfAccount(aa.StatusOption.Option.String(), types.CurrentTimestamp().String2(time.UTC, 0), aa.Name) 2119 bh.ClearExecResultSet() 2120 err = bh.Exec(ctx, sql) 2121 if err != nil { 2122 goto handleFailed 2123 } 2124 } 2125 } 2126 2127 err = bh.Exec(ctx, "commit;") 2128 if err != nil { 2129 goto handleFailed 2130 } 2131 return err 2132 handleFailed: 2133 //ROLLBACK the transaction 2134 rbErr := bh.Exec(ctx, "rollback;") 2135 if rbErr != nil { 2136 return rbErr 2137 } 2138 return err 2139 } 2140 2141 // doSwitchRole accomplishes the Use Role and Use Secondary Role statement 2142 func doSwitchRole(ctx context.Context, ses *Session, sr *tree.SetRole) error { 2143 var err error 2144 var sql string 2145 var erArray []ExecResult 2146 var roleId int64 2147 2148 account := ses.GetTenantInfo() 2149 2150 if sr.SecondaryRole { 2151 //use secondary role all or none 2152 switch sr.SecondaryRoleType { 2153 case tree.SecondaryRoleTypeAll: 2154 account.SetUseSecondaryRole(true) 2155 case tree.SecondaryRoleTypeNone: 2156 account.SetUseSecondaryRole(false) 2157 } 2158 } else if sr.Role != nil { 2159 err = normalizeNameOfRole(ctx, sr.Role) 2160 if err != nil { 2161 return err 2162 } 2163 2164 //step1 : check the role exists or not; 2165 bh := ses.GetBackgroundExec(ctx) 2166 defer bh.Close() 2167 2168 err = bh.Exec(ctx, "begin;") 2169 if err != nil { 2170 goto handleFailed 2171 } 2172 2173 sql = getSqlForRoleIdOfRole(sr.Role.UserName) 2174 bh.ClearExecResultSet() 2175 err = bh.Exec(ctx, sql) 2176 if err != nil { 2177 goto handleFailed 2178 } 2179 2180 erArray, err = getResultSet(ctx, bh) 2181 if err != nil { 2182 goto handleFailed 2183 } 2184 if execResultArrayHasData(erArray) { 2185 roleId, err = erArray[0].GetInt64(ctx, 0, 0) 2186 if err != nil { 2187 goto handleFailed 2188 } 2189 } else { 2190 err = moerr.NewInternalError(ctx, "there is no role %s", sr.Role.UserName) 2191 goto handleFailed 2192 } 2193 2194 //step2 : check the role has been granted to the user or not 2195 sql = getSqlForCheckUserGrant(roleId, int64(account.GetUserID())) 2196 bh.ClearExecResultSet() 2197 err = bh.Exec(ctx, sql) 2198 if err != nil { 2199 goto handleFailed 2200 } 2201 2202 erArray, err = getResultSet(ctx, bh) 2203 if err != nil { 2204 goto handleFailed 2205 } 2206 2207 if !execResultArrayHasData(erArray) { 2208 err = moerr.NewInternalError(ctx, "the role %s has not be granted to the user %s", sr.Role.UserName, account.GetUser()) 2209 goto handleFailed 2210 } 2211 2212 err = bh.Exec(ctx, "commit;") 2213 if err != nil { 2214 goto handleFailed 2215 } 2216 2217 //step3 : switch the default role and role id; 2218 account.SetDefaultRoleID(uint32(roleId)) 2219 account.SetDefaultRole(sr.Role.UserName) 2220 //then, reset secondary role to none 2221 account.SetUseSecondaryRole(false) 2222 2223 return err 2224 2225 handleFailed: 2226 //ROLLBACK the transaction 2227 rbErr := bh.Exec(ctx, "rollback;") 2228 if rbErr != nil { 2229 return rbErr 2230 } 2231 return err 2232 } 2233 2234 return err 2235 } 2236 2237 // doDropAccount accomplishes the DropAccount statement 2238 func doDropAccount(ctx context.Context, ses *Session, da *tree.DropAccount) error { 2239 bh := ses.GetBackgroundExec(ctx) 2240 defer bh.Close() 2241 var err error 2242 var sql, db, table string 2243 var erArray []ExecResult 2244 2245 var deleteCtx context.Context 2246 var accountId int64 2247 var hasAccount = true 2248 clusterTables := make(map[string]int) 2249 2250 da.Name, err = normalizeName(ctx, da.Name) 2251 if err != nil { 2252 return err 2253 } 2254 2255 if isSysTenant(da.Name) { 2256 return moerr.NewInternalError(ctx, "can not delete the account %s", da.Name) 2257 } 2258 2259 err = bh.Exec(ctx, "begin;") 2260 if err != nil { 2261 goto handleFailed 2262 } 2263 2264 //check the account exists or not 2265 sql = getSqlForCheckTenant(da.Name) 2266 bh.ClearExecResultSet() 2267 err = bh.Exec(ctx, sql) 2268 if err != nil { 2269 goto handleFailed 2270 } 2271 2272 erArray, err = getResultSet(ctx, bh) 2273 if err != nil { 2274 goto handleFailed 2275 } 2276 2277 if execResultArrayHasData(erArray) { 2278 accountId, err = erArray[0].GetInt64(ctx, 0, 0) 2279 if err != nil { 2280 goto handleFailed 2281 } 2282 } else { 2283 //no such account 2284 if !da.IfExists { //when the "IF EXISTS" is set, just skip it. 2285 err = moerr.NewInternalError(ctx, "there is no account %s", da.Name) 2286 goto handleFailed 2287 } 2288 hasAccount = false 2289 } 2290 2291 //drop tables of the tenant 2292 if hasAccount { 2293 //NOTE!!!: single DDL drop statement per single transaction 2294 //SWITCH TO THE CONTEXT of the deleted context 2295 deleteCtx = context.WithValue(ctx, defines.TenantIDKey{}, uint32(accountId)) 2296 2297 //step 2 : drop table mo_user 2298 //step 3 : drop table mo_role 2299 //step 4 : drop table mo_user_grant 2300 //step 5 : drop table mo_role_grant 2301 //step 6 : drop table mo_role_privs 2302 for _, sql = range getSqlForDropAccount() { 2303 err = bh.Exec(deleteCtx, sql) 2304 if err != nil { 2305 goto handleFailed 2306 } 2307 } 2308 2309 //drop databases created by user 2310 databases := make(map[string]int8) 2311 dbSql := "show databases;" 2312 bh.ClearExecResultSet() 2313 err = bh.Exec(deleteCtx, dbSql) 2314 if err != nil { 2315 goto handleFailed 2316 } 2317 2318 erArray, err = getResultSet(ctx, bh) 2319 if err != nil { 2320 goto handleFailed 2321 } 2322 2323 for i := uint64(0); i < erArray[0].GetRowCount(); i++ { 2324 db, err = erArray[0].GetString(ctx, i, 0) 2325 if err != nil { 2326 goto handleFailed 2327 } 2328 databases[db] = 0 2329 } 2330 2331 var sqlsForDropDatabases []string 2332 prefix := "drop database if exists " 2333 2334 for db = range databases { 2335 if db == "mo_catalog" { 2336 continue 2337 } 2338 bb := &bytes.Buffer{} 2339 bb.WriteString(prefix) 2340 //handle the database annotated by '`' 2341 if db != strings.ToLower(db) { 2342 bb.WriteString("`") 2343 bb.WriteString(db) 2344 bb.WriteString("`") 2345 } else { 2346 bb.WriteString(db) 2347 } 2348 bb.WriteString(";") 2349 sqlsForDropDatabases = append(sqlsForDropDatabases, bb.String()) 2350 } 2351 2352 for _, sql = range sqlsForDropDatabases { 2353 err = bh.Exec(deleteCtx, sql) 2354 if err != nil { 2355 goto handleFailed 2356 } 2357 } 2358 } 2359 2360 //step 1 : delete the account in the mo_account of the sys account 2361 sql = getSqlForDeleteAccountFromMoAccount(da.Name) 2362 err = bh.Exec(ctx, sql) 2363 if err != nil { 2364 goto handleFailed 2365 } 2366 2367 //step 2: get all cluster table in the mo_catalog 2368 2369 sql = "show tables from mo_catalog;" 2370 bh.ClearExecResultSet() 2371 err = bh.Exec(ctx, sql) 2372 if err != nil { 2373 goto handleFailed 2374 } 2375 2376 erArray, err = getResultSet(ctx, bh) 2377 if err != nil { 2378 goto handleFailed 2379 } 2380 2381 for i := uint64(0); i < erArray[0].GetRowCount(); i++ { 2382 table, err = erArray[0].GetString(ctx, i, 0) 2383 if err != nil { 2384 goto handleFailed 2385 } 2386 if isClusterTable("mo_catalog", table) { 2387 clusterTables[table] = 0 2388 } 2389 } 2390 2391 //step3 : delete all data of the account in the cluster table 2392 for clusterTable := range clusterTables { 2393 sql = fmt.Sprintf("delete from mo_catalog.`%s` where account_id = %d;", clusterTable, accountId) 2394 bh.ClearExecResultSet() 2395 err = bh.Exec(ctx, sql) 2396 if err != nil { 2397 goto handleFailed 2398 } 2399 } 2400 2401 //step4: delete data of mo_mysql_comaptbility_mode table 2402 sql = getSqlForDeleteMysqlCompatbilityModeForAccount(da.Name) 2403 err = bh.Exec(ctx, sql) 2404 if err != nil { 2405 goto handleFailed 2406 } 2407 2408 err = bh.Exec(ctx, "commit;") 2409 if err != nil { 2410 goto handleFailed 2411 } 2412 return err 2413 2414 handleFailed: 2415 //ROLLBACK the transaction 2416 rbErr := bh.Exec(ctx, "rollback;") 2417 if rbErr != nil { 2418 return rbErr 2419 } 2420 return err 2421 } 2422 2423 // doDropUser accomplishes the DropUser statement 2424 func doDropUser(ctx context.Context, ses *Session, du *tree.DropUser) error { 2425 var err error 2426 var vr *verifiedRole 2427 var sql string 2428 var sqls []string 2429 var erArray []ExecResult 2430 account := ses.GetTenantInfo() 2431 err = normalizeNamesOfUsers(ctx, du.Users) 2432 if err != nil { 2433 return err 2434 } 2435 2436 bh := ses.GetBackgroundExec(ctx) 2437 defer bh.Close() 2438 2439 //put it into the single transaction 2440 err = bh.Exec(ctx, "begin;") 2441 if err != nil { 2442 goto handleFailed 2443 } 2444 2445 //step1: check users exists or not. 2446 //handle "IF EXISTS" 2447 for _, user := range du.Users { 2448 sql = getSqlForPasswordOfUser(user.Username) 2449 vr, err = verifyRoleFunc(ctx, bh, sql, user.Username, roleType) 2450 if err != nil { 2451 goto handleFailed 2452 } 2453 2454 if vr == nil { 2455 if !du.IfExists { //when the "IF EXISTS" is set, just skip it. 2456 err = moerr.NewInternalError(ctx, "there is no user %s", user.Username) 2457 goto handleFailed 2458 } 2459 } 2460 2461 if vr == nil { 2462 continue 2463 } 2464 2465 //if the user is admin user with the role moadmin or accountadmin, 2466 //the user can not be deleted. 2467 if account.IsSysTenant() { 2468 sql = getSqlForCheckUserHasRole(user.Username, moAdminRoleID) 2469 } else { 2470 sql = getSqlForCheckUserHasRole(user.Username, accountAdminRoleID) 2471 } 2472 2473 bh.ClearExecResultSet() 2474 err = bh.Exec(ctx, sql) 2475 if err != nil { 2476 goto handleFailed 2477 } 2478 2479 erArray, err = getResultSet(ctx, bh) 2480 if err != nil { 2481 goto handleFailed 2482 } 2483 2484 if execResultArrayHasData(erArray) { 2485 err = moerr.NewInternalError(ctx, "can not delete the user %s", user.Username) 2486 goto handleFailed 2487 } 2488 2489 //step2 : delete mo_user 2490 //step3 : delete mo_user_grant 2491 sqls = getSqlForDeleteUser(vr.id) 2492 for _, sqlx := range sqls { 2493 bh.ClearExecResultSet() 2494 err = bh.Exec(ctx, sqlx) 2495 if err != nil { 2496 goto handleFailed 2497 } 2498 } 2499 } 2500 2501 err = bh.Exec(ctx, "commit;") 2502 if err != nil { 2503 goto handleFailed 2504 } 2505 2506 return err 2507 2508 handleFailed: 2509 //ROLLBACK the transaction 2510 rbErr := bh.Exec(ctx, "rollback;") 2511 if rbErr != nil { 2512 return rbErr 2513 } 2514 return err 2515 } 2516 2517 // doDropRole accomplishes the DropRole statement 2518 func doDropRole(ctx context.Context, ses *Session, dr *tree.DropRole) error { 2519 var err error 2520 var vr *verifiedRole 2521 account := ses.GetTenantInfo() 2522 err = normalizeNamesOfRoles(ctx, dr.Roles) 2523 if err != nil { 2524 return err 2525 } 2526 2527 bh := ses.GetBackgroundExec(ctx) 2528 defer bh.Close() 2529 2530 //put it into the single transaction 2531 err = bh.Exec(ctx, "begin;") 2532 if err != nil { 2533 goto handleFailed 2534 } 2535 2536 //step1: check roles exists or not. 2537 //handle "IF EXISTS" 2538 for _, role := range dr.Roles { 2539 sql := getSqlForRoleIdOfRole(role.UserName) 2540 vr, err = verifyRoleFunc(ctx, bh, sql, role.UserName, roleType) 2541 if err != nil { 2542 goto handleFailed 2543 } 2544 2545 if vr == nil { 2546 if !dr.IfExists { //when the "IF EXISTS" is set, just skip it. 2547 err = moerr.NewInternalError(ctx, "there is no role %s", role.UserName) 2548 goto handleFailed 2549 } 2550 } 2551 2552 //step2 : delete mo_role 2553 //step3 : delete mo_user_grant 2554 //step4 : delete mo_role_grant 2555 //step5 : delete mo_role_privs 2556 if vr == nil { 2557 continue 2558 } 2559 2560 //NOTE: if the role is the admin role (moadmin,accountadmin) or public, 2561 //the role can not be deleted. 2562 if account.IsNameOfAdminRoles(vr.name) || isPublicRole(vr.name) { 2563 err = moerr.NewInternalError(ctx, "can not delete the role %s", vr.name) 2564 goto handleFailed 2565 } 2566 2567 sqls := getSqlForDeleteRole(vr.id) 2568 for _, sqlx := range sqls { 2569 bh.ClearExecResultSet() 2570 err = bh.Exec(ctx, sqlx) 2571 if err != nil { 2572 goto handleFailed 2573 } 2574 } 2575 } 2576 2577 err = bh.Exec(ctx, "commit;") 2578 if err != nil { 2579 goto handleFailed 2580 } 2581 2582 return err 2583 2584 handleFailed: 2585 //ROLLBACK the transaction 2586 rbErr := bh.Exec(ctx, "rollback;") 2587 if rbErr != nil { 2588 return rbErr 2589 } 2590 return err 2591 } 2592 2593 func doDropFunction(ctx context.Context, ses *Session, df *tree.DropFunction) error { 2594 var err error 2595 var sql string 2596 var argstr string 2597 var checkDatabase string 2598 var dbName string 2599 var funcId int64 2600 var fmtctx *tree.FmtCtx 2601 var erArray []ExecResult 2602 2603 bh := ses.GetBackgroundExec(ctx) 2604 defer bh.Close() 2605 2606 // a database must be selected or specified as qualifier when create a function 2607 if df.Name.HasNoNameQualifier() { 2608 if ses.DatabaseNameIsEmpty() { 2609 return moerr.NewNoDBNoCtx() 2610 } 2611 dbName = ses.GetDatabaseName() 2612 } else { 2613 dbName = string(df.Name.Name.SchemaName) 2614 } 2615 2616 fmtctx = tree.NewFmtCtx(dialect.MYSQL, tree.WithQuoteString(true)) 2617 2618 // validate database name and signature (name + args) 2619 bh.ClearExecResultSet() 2620 checkDatabase = fmt.Sprintf(checkUdfArgs, string(df.Name.Name.ObjectName), dbName) 2621 err = bh.Exec(ctx, checkDatabase) 2622 if err != nil { 2623 goto handleFailed 2624 } 2625 2626 erArray, err = getResultSet(ctx, bh) 2627 if err != nil { 2628 goto handleFailed 2629 } 2630 2631 if execResultArrayHasData(erArray) { 2632 // function with provided name and db exists, now check arguments 2633 for i := uint64(0); i < erArray[0].GetRowCount(); i++ { 2634 argstr, err = erArray[0].GetString(ctx, i, 0) 2635 if err != nil { 2636 goto handleFailed 2637 } 2638 funcId, err = erArray[0].GetInt64(ctx, i, 1) 2639 if err != nil { 2640 goto handleFailed 2641 } 2642 logutil.Debug("argstr: " + argstr) 2643 argMap := make(map[string]string) 2644 json.Unmarshal([]byte(argstr), &argMap) 2645 argCount := 0 2646 if len(argMap) == len(df.Args) { 2647 for _, v := range argMap { 2648 if v != (df.Args[argCount].GetType(fmtctx)) { 2649 goto handleFailed 2650 } 2651 argCount++ 2652 fmtctx.Reset() 2653 } 2654 goto handleArgMatch 2655 } 2656 } 2657 goto handleFailed 2658 } else { 2659 // no such function 2660 return moerr.NewNoUDFNoCtx(string(df.Name.Name.ObjectName)) 2661 } 2662 2663 handleArgMatch: 2664 //put it into the single transaction 2665 err = bh.Exec(ctx, "begin;") 2666 if err != nil { 2667 goto handleFailed 2668 } 2669 2670 sql = fmt.Sprintf(deleteUserDefinedFunctionFormat, funcId) 2671 2672 err = bh.Exec(ctx, sql) 2673 if err != nil { 2674 goto handleFailed 2675 } 2676 2677 err = bh.Exec(ctx, "commit;") 2678 if err != nil { 2679 goto handleFailed 2680 } 2681 2682 return err 2683 2684 handleFailed: 2685 //ROLLBACK the transaction 2686 rbErr := bh.Exec(ctx, "rollback;") 2687 if rbErr != nil { 2688 return rbErr 2689 } 2690 return err 2691 } 2692 2693 // doRevokePrivilege accomplishes the RevokePrivilege statement 2694 func doRevokePrivilege(ctx context.Context, ses *Session, rp *tree.RevokePrivilege) error { 2695 var err error 2696 var vr *verifiedRole 2697 var objType objectType 2698 var privLevel privilegeLevelType 2699 var objId int64 2700 var privType PrivilegeType 2701 err = normalizeNamesOfRoles(ctx, rp.Roles) 2702 if err != nil { 2703 return err 2704 } 2705 2706 account := ses.GetTenantInfo() 2707 bh := ses.GetBackgroundExec(ctx) 2708 defer bh.Close() 2709 2710 verifiedRoles := make([]*verifiedRole, len(rp.Roles)) 2711 checkedPrivilegeTypes := make([]PrivilegeType, len(rp.Privileges)) 2712 2713 //put it into the single transaction 2714 err = bh.Exec(ctx, "begin;") 2715 if err != nil { 2716 goto handleFailed 2717 } 2718 2719 //handle "IF EXISTS" 2720 //step 1: check roles. exists or not. 2721 for i, user := range rp.Roles { 2722 //check Revoke privilege on xxx yyy from moadmin(accountadmin) 2723 if account.IsNameOfAdminRoles(user.UserName) { 2724 err = moerr.NewInternalError(ctx, "the privilege can not be revoked from the role %s", user.UserName) 2725 goto handleFailed 2726 } 2727 sql := getSqlForRoleIdOfRole(user.UserName) 2728 vr, err = verifyRoleFunc(ctx, bh, sql, user.UserName, roleType) 2729 if err != nil { 2730 goto handleFailed 2731 } 2732 verifiedRoles[i] = vr 2733 if vr == nil { 2734 if !rp.IfExists { //when the "IF EXISTS" is set, just skip it. 2735 err = moerr.NewInternalError(ctx, "there is no role %s", user.UserName) 2736 goto handleFailed 2737 } 2738 } 2739 } 2740 2741 //get the object type 2742 objType, err = convertAstObjectTypeToObjectType(ctx, rp.ObjType) 2743 if err != nil { 2744 goto handleFailed 2745 } 2746 2747 //check the privilege and the object type 2748 for i, priv := range rp.Privileges { 2749 privType, err = convertAstPrivilegeTypeToPrivilegeType(ctx, priv.Type, rp.ObjType) 2750 if err != nil { 2751 goto handleFailed 2752 } 2753 //check the match between the privilegeScope and the objectType 2754 err = matchPrivilegeTypeWithObjectType(ctx, privType, objType) 2755 if err != nil { 2756 goto handleFailed 2757 } 2758 checkedPrivilegeTypes[i] = privType 2759 } 2760 2761 //step 2: decide the object type , the object id and the privilege_level 2762 privLevel, objId, err = checkPrivilegeObjectTypeAndPrivilegeLevel(ctx, ses, bh, rp.ObjType, *rp.Level) 2763 if err != nil { 2764 goto handleFailed 2765 } 2766 2767 //step 3: delete the granted privilege 2768 for _, privType = range checkedPrivilegeTypes { 2769 for _, role := range verifiedRoles { 2770 if role == nil { 2771 continue 2772 } 2773 if privType == PrivilegeTypeConnect && isPublicRole(role.name) { 2774 err = moerr.NewInternalError(ctx, "the privilege %s can not be revoked from the role %s", privType, role.name) 2775 goto handleFailed 2776 } 2777 sql := getSqlForDeleteRolePrivs(role.id, objType.String(), objId, int64(privType), privLevel.String()) 2778 bh.ClearExecResultSet() 2779 err = bh.Exec(ctx, sql) 2780 if err != nil { 2781 goto handleFailed 2782 } 2783 } 2784 } 2785 2786 err = bh.Exec(ctx, "commit;") 2787 if err != nil { 2788 goto handleFailed 2789 } 2790 2791 return err 2792 2793 handleFailed: 2794 //ROLLBACK the transaction 2795 rbErr := bh.Exec(ctx, "rollback;") 2796 if rbErr != nil { 2797 return rbErr 2798 } 2799 return err 2800 } 2801 2802 // getDatabaseOrTableId gets the id of the database or the table 2803 func getDatabaseOrTableId(ctx context.Context, bh BackgroundExec, isDb bool, dbName, tableName string) (int64, error) { 2804 var err error 2805 var sql string 2806 var erArray []ExecResult 2807 var id int64 2808 if isDb { 2809 sql = getSqlForCheckDatabase(dbName) 2810 } else { 2811 sql = getSqlForCheckDatabaseTable(dbName, tableName) 2812 } 2813 bh.ClearExecResultSet() 2814 err = bh.Exec(ctx, sql) 2815 if err != nil { 2816 return 0, err 2817 } 2818 2819 erArray, err = getResultSet(ctx, bh) 2820 if err != nil { 2821 return 0, err 2822 } 2823 2824 if execResultArrayHasData(erArray) { 2825 id, err = erArray[0].GetInt64(ctx, 0, 0) 2826 if err != nil { 2827 return 0, err 2828 } 2829 return id, nil 2830 } 2831 if isDb { 2832 return 0, moerr.NewInternalError(ctx, `there is no database "%s"`, dbName) 2833 } else { 2834 //TODO: check the database exists or not first 2835 return 0, moerr.NewInternalError(ctx, `there is no table "%s" in database "%s"`, tableName, dbName) 2836 } 2837 } 2838 2839 // convertAstObjectTypeToObjectType gets the object type from the ast 2840 func convertAstObjectTypeToObjectType(ctx context.Context, ot tree.ObjectType) (objectType, error) { 2841 var objType objectType 2842 switch ot { 2843 case tree.OBJECT_TYPE_TABLE: 2844 objType = objectTypeTable 2845 case tree.OBJECT_TYPE_DATABASE: 2846 objType = objectTypeDatabase 2847 case tree.OBJECT_TYPE_ACCOUNT: 2848 objType = objectTypeAccount 2849 default: 2850 return 0, moerr.NewInternalError(ctx, `the object type "%s" is unsupported`, ot.String()) 2851 } 2852 return objType, nil 2853 } 2854 2855 // checkPrivilegeObjectTypeAndPrivilegeLevel checks the relationship among the privilege type, the object type and the privilege level. 2856 // it returns the converted object type, the privilege level and the object id. 2857 func checkPrivilegeObjectTypeAndPrivilegeLevel(ctx context.Context, ses *Session, bh BackgroundExec, 2858 ot tree.ObjectType, pl tree.PrivilegeLevel) (privilegeLevelType, int64, error) { 2859 var privLevel privilegeLevelType 2860 var objId int64 2861 var err error 2862 var dbName string 2863 2864 switch ot { 2865 case tree.OBJECT_TYPE_TABLE: 2866 switch pl.Level { 2867 case tree.PRIVILEGE_LEVEL_TYPE_STAR: 2868 privLevel = privilegeLevelStar 2869 objId, err = getDatabaseOrTableId(ctx, bh, true, ses.GetDatabaseName(), "") 2870 if err != nil { 2871 return 0, 0, err 2872 } 2873 case tree.PRIVILEGE_LEVEL_TYPE_STAR_STAR: 2874 privLevel = privilegeLevelStarStar 2875 objId = objectIDAll 2876 case tree.PRIVILEGE_LEVEL_TYPE_DATABASE_STAR: 2877 privLevel = privilegeLevelDatabaseStar 2878 objId, err = getDatabaseOrTableId(ctx, bh, true, pl.DbName, "") 2879 if err != nil { 2880 return 0, 0, err 2881 } 2882 case tree.PRIVILEGE_LEVEL_TYPE_DATABASE_TABLE: 2883 privLevel = privilegeLevelDatabaseTable 2884 objId, err = getDatabaseOrTableId(ctx, bh, false, pl.DbName, pl.TabName) 2885 if err != nil { 2886 return 0, 0, err 2887 } 2888 case tree.PRIVILEGE_LEVEL_TYPE_TABLE: 2889 privLevel = privilegeLevelTable 2890 objId, err = getDatabaseOrTableId(ctx, bh, false, ses.GetDatabaseName(), pl.TabName) 2891 if err != nil { 2892 return 0, 0, err 2893 } 2894 default: 2895 err = moerr.NewInternalError(ctx, `in the object type "%s" the privilege level "%s" is unsupported`, ot.String(), pl.String()) 2896 return 0, 0, err 2897 } 2898 case tree.OBJECT_TYPE_DATABASE: 2899 switch pl.Level { 2900 case tree.PRIVILEGE_LEVEL_TYPE_STAR: 2901 privLevel = privilegeLevelStar 2902 objId = objectIDAll 2903 case tree.PRIVILEGE_LEVEL_TYPE_STAR_STAR: 2904 privLevel = privilegeLevelStarStar 2905 objId = objectIDAll 2906 case tree.PRIVILEGE_LEVEL_TYPE_TABLE: 2907 //in the syntax, we can not distinguish the table name from the database name. 2908 privLevel = privilegeLevelDatabase 2909 dbName = pl.TabName 2910 objId, err = getDatabaseOrTableId(ctx, bh, true, dbName, "") 2911 if err != nil { 2912 return 0, 0, err 2913 } 2914 case tree.PRIVILEGE_LEVEL_TYPE_DATABASE: 2915 privLevel = privilegeLevelDatabase 2916 dbName = pl.DbName 2917 objId, err = getDatabaseOrTableId(ctx, bh, true, dbName, "") 2918 if err != nil { 2919 return 0, 0, err 2920 } 2921 default: 2922 err = moerr.NewInternalError(ctx, `in the object type "%s" the privilege level "%s" is unsupported`, ot.String(), pl.String()) 2923 return 0, 0, err 2924 } 2925 case tree.OBJECT_TYPE_ACCOUNT: 2926 switch pl.Level { 2927 case tree.PRIVILEGE_LEVEL_TYPE_STAR: 2928 privLevel = privilegeLevelStar 2929 objId = objectIDAll 2930 default: 2931 err = moerr.NewInternalError(ctx, `in the object type "%s" the privilege level "%s" is unsupported`, ot.String(), pl.String()) 2932 return 0, 0, err 2933 } 2934 default: 2935 err = moerr.NewInternalError(ctx, `the object type "%s" is unsupported`, ot.String()) 2936 return 0, 0, err 2937 } 2938 2939 return privLevel, objId, err 2940 } 2941 2942 // matchPrivilegeTypeWithObjectType matches the privilege type with the object type 2943 func matchPrivilegeTypeWithObjectType(ctx context.Context, privType PrivilegeType, objType objectType) error { 2944 var err error 2945 switch privType.Scope() { 2946 case PrivilegeScopeSys, PrivilegeScopeAccount, PrivilegeScopeUser, PrivilegeScopeRole: 2947 if objType != objectTypeAccount { 2948 err = moerr.NewInternalError(ctx, `the privilege "%s" can only be granted to the object type "account"`, privType) 2949 } 2950 case PrivilegeScopeDatabase: 2951 if objType != objectTypeDatabase { 2952 err = moerr.NewInternalError(ctx, `the privilege "%s" can only be granted to the object type "database"`, privType) 2953 } 2954 case PrivilegeScopeTable: 2955 if objType != objectTypeTable { 2956 err = moerr.NewInternalError(ctx, `the privilege "%s" can only be granted to the object type "table"`, privType) 2957 } 2958 case PrivilegeScopeRoutine: 2959 if objType != objectTypeFunction { 2960 err = moerr.NewInternalError(ctx, `the privilege "%s" can only be granted to the object type "function"`, privType) 2961 } 2962 } 2963 return err 2964 } 2965 2966 // doGrantPrivilege accomplishes the GrantPrivilege statement 2967 func doGrantPrivilege(ctx context.Context, ses *Session, gp *tree.GrantPrivilege) error { 2968 var err error 2969 var erArray []ExecResult 2970 var roleId int64 2971 var privType PrivilegeType 2972 var objType objectType 2973 var privLevel privilegeLevelType 2974 var objId int64 2975 2976 err = normalizeNamesOfRoles(ctx, gp.Roles) 2977 if err != nil { 2978 return err 2979 } 2980 2981 account := ses.GetTenantInfo() 2982 bh := ses.GetBackgroundExec(ctx) 2983 defer bh.Close() 2984 2985 //Get primary keys 2986 //step 1: get role_id 2987 verifiedRoles := make([]*verifiedRole, len(gp.Roles)) 2988 checkedPrivilegeTypes := make([]PrivilegeType, len(gp.Privileges)) 2989 2990 //put it into the single transaction 2991 err = bh.Exec(ctx, "begin;") 2992 if err != nil { 2993 goto handleFailed 2994 } 2995 2996 for i, role := range gp.Roles { 2997 //check Grant privilege on xxx yyy to moadmin(accountadmin) 2998 if account.IsNameOfAdminRoles(role.UserName) { 2999 err = moerr.NewInternalError(ctx, "the privilege can not be granted to the role %s", role.UserName) 3000 goto handleFailed 3001 } 3002 sql := getSqlForRoleIdOfRole(role.UserName) 3003 bh.ClearExecResultSet() 3004 err = bh.Exec(ctx, sql) 3005 if err != nil { 3006 goto handleFailed 3007 } 3008 3009 erArray, err = getResultSet(ctx, bh) 3010 if err != nil { 3011 goto handleFailed 3012 } 3013 3014 if execResultArrayHasData(erArray) { 3015 for j := uint64(0); j < erArray[0].GetRowCount(); j++ { 3016 roleId, err = erArray[0].GetInt64(ctx, j, 0) 3017 if err != nil { 3018 goto handleFailed 3019 } 3020 } 3021 } else { 3022 err = moerr.NewInternalError(ctx, "there is no role %s", role.UserName) 3023 goto handleFailed 3024 } 3025 verifiedRoles[i] = &verifiedRole{ 3026 typ: roleType, 3027 name: role.UserName, 3028 id: roleId, 3029 } 3030 } 3031 3032 //get the object type 3033 objType, err = convertAstObjectTypeToObjectType(ctx, gp.ObjType) 3034 if err != nil { 3035 goto handleFailed 3036 } 3037 3038 //check the privilege and the object type 3039 for i, priv := range gp.Privileges { 3040 privType, err = convertAstPrivilegeTypeToPrivilegeType(ctx, priv.Type, gp.ObjType) 3041 if err != nil { 3042 goto handleFailed 3043 } 3044 if isBannedPrivilege(privType) { 3045 err = moerr.NewInternalError(ctx, "the privilege %s can not be granted", privType) 3046 goto handleFailed 3047 } 3048 //check the match between the privilegeScope and the objectType 3049 err = matchPrivilegeTypeWithObjectType(ctx, privType, objType) 3050 if err != nil { 3051 goto handleFailed 3052 } 3053 checkedPrivilegeTypes[i] = privType 3054 } 3055 3056 //step 2: get obj_type, privilege_level 3057 //step 3: get obj_id 3058 privLevel, objId, err = checkPrivilegeObjectTypeAndPrivilegeLevel(ctx, ses, bh, gp.ObjType, *gp.Level) 3059 if err != nil { 3060 goto handleFailed 3061 } 3062 3063 //step 4: get privilege_id 3064 //step 5: check exists 3065 //step 6: update or insert 3066 3067 for _, privType = range checkedPrivilegeTypes { 3068 for _, role := range verifiedRoles { 3069 sql := getSqlForCheckRoleHasPrivilege(role.id, objType, objId, int64(privType)) 3070 //check exists 3071 bh.ClearExecResultSet() 3072 err = bh.Exec(ctx, sql) 3073 if err != nil { 3074 goto handleFailed 3075 } 3076 3077 erArray, err = getResultSet(ctx, bh) 3078 if err != nil { 3079 goto handleFailed 3080 } 3081 3082 //choice 1 : update the record 3083 //choice 2 : inset new record 3084 choice := 1 3085 if execResultArrayHasData(erArray) { 3086 for j := uint64(0); j < erArray[0].GetRowCount(); j++ { 3087 _, err = erArray[0].GetInt64(ctx, j, 0) 3088 if err != nil { 3089 goto handleFailed 3090 } 3091 } 3092 } else { 3093 choice = 2 3094 } 3095 3096 if choice == 1 { //update the record 3097 sql = getSqlForUpdateRolePrivs(int64(account.GetUserID()), 3098 types.CurrentTimestamp().String2(time.UTC, 0), 3099 gp.GrantOption, role.id, objType, objId, int64(privType)) 3100 } else if choice == 2 { //insert new record 3101 sql = getSqlForInsertRolePrivs(role.id, role.name, objType.String(), objId, 3102 int64(privType), privType.String(), privLevel.String(), int64(account.GetUserID()), 3103 types.CurrentTimestamp().String2(time.UTC, 0), gp.GrantOption) 3104 } 3105 3106 //insert or update 3107 bh.ClearExecResultSet() 3108 err = bh.Exec(ctx, sql) 3109 if err != nil { 3110 goto handleFailed 3111 } 3112 } 3113 } 3114 3115 err = bh.Exec(ctx, "commit;") 3116 if err != nil { 3117 goto handleFailed 3118 } 3119 3120 return err 3121 handleFailed: 3122 //ROLLBACK the transaction 3123 rbErr := bh.Exec(ctx, "rollback;") 3124 if rbErr != nil { 3125 return rbErr 3126 } 3127 return err 3128 } 3129 3130 // doRevokeRole accomplishes the RevokeRole statement 3131 func doRevokeRole(ctx context.Context, ses *Session, rr *tree.RevokeRole) error { 3132 var err error 3133 err = normalizeNamesOfRoles(ctx, rr.Roles) 3134 if err != nil { 3135 return err 3136 } 3137 err = normalizeNamesOfUsers(ctx, rr.Users) 3138 if err != nil { 3139 return err 3140 } 3141 3142 account := ses.GetTenantInfo() 3143 bh := ses.GetBackgroundExec(ctx) 3144 defer bh.Close() 3145 3146 //step1 : check Roles exists or not 3147 var vr *verifiedRole 3148 3149 verifiedFromRoles := make([]*verifiedRole, len(rr.Roles)) 3150 verifiedToRoles := make([]*verifiedRole, len(rr.Users)) 3151 3152 //put it into the single transaction 3153 err = bh.Exec(ctx, "begin;") 3154 if err != nil { 3155 goto handleFailed 3156 } 3157 3158 //handle "IF EXISTS" 3159 //step1 : check Users are real Users or Roles, exists or not 3160 for i, user := range rr.Users { 3161 sql := getSqlForRoleIdOfRole(user.Username) 3162 vr, err = verifyRoleFunc(ctx, bh, sql, user.Username, roleType) 3163 if err != nil { 3164 goto handleFailed 3165 } 3166 if vr != nil { 3167 verifiedToRoles[i] = vr 3168 } else { 3169 //check user 3170 sql = getSqlForPasswordOfUser(user.Username) 3171 vr, err = verifyRoleFunc(ctx, bh, sql, user.Username, userType) 3172 if err != nil { 3173 goto handleFailed 3174 } 3175 verifiedToRoles[i] = vr 3176 if vr == nil { 3177 if !rr.IfExists { //when the "IF EXISTS" is set, just skip the check 3178 err = moerr.NewInternalError(ctx, "there is no role or user %s", user.Username) 3179 goto handleFailed 3180 } 3181 } 3182 } 3183 } 3184 3185 //handle "IF EXISTS" 3186 //step2 : check roles before the FROM clause 3187 for i, role := range rr.Roles { 3188 sql := getSqlForRoleIdOfRole(role.UserName) 3189 vr, err = verifyRoleFunc(ctx, bh, sql, role.UserName, roleType) 3190 if err != nil { 3191 goto handleFailed 3192 } 3193 if vr == nil { 3194 err = moerr.NewInternalError(ctx, "there is no role %s", role.UserName) 3195 goto handleFailed 3196 } 3197 verifiedFromRoles[i] = vr 3198 } 3199 3200 //step3 : process Revoke role from role 3201 //step4 : process Revoke role from user 3202 for _, from := range verifiedFromRoles { 3203 for _, to := range verifiedToRoles { 3204 if to == nil { //Under "IF EXISTS" 3205 continue 3206 } 3207 if account.IsNameOfAdminRoles(from.name) { 3208 //check Revoke moadmin from root,dump,userX 3209 //check Revoke accountadmin from root,dump,userX 3210 //check Revoke moadmin(accountadmin) from roleX 3211 err = moerr.NewInternalError(ctx, "the role %s can not be revoked", from.name) 3212 goto handleFailed 3213 } else if isPublicRole(from.name) { 3214 // 3215 err = moerr.NewInternalError(ctx, "the role %s can not be revoked", from.name) 3216 goto handleFailed 3217 } 3218 3219 if to.typ == roleType { 3220 //check Revoke roleX from moadmin(accountadmin) 3221 if account.IsNameOfAdminRoles(to.name) { 3222 err = moerr.NewInternalError(ctx, "the role %s can not be revoked from the role %s", from.name, to.name) 3223 goto handleFailed 3224 } else if isPublicRole(to.name) { 3225 //check Revoke roleX from public 3226 err = moerr.NewInternalError(ctx, "the role %s can not be revoked from the role %s", from.name, to.name) 3227 goto handleFailed 3228 } 3229 } 3230 3231 sql := "" 3232 if to.typ == roleType { 3233 //revoke from role 3234 //delete (granted_id,grantee_id) from the mo_role_grant 3235 sql = getSqlForDeleteRoleGrant(from.id, to.id) 3236 } else { 3237 //revoke from user 3238 //delete (roleId,userId) from the mo_user_grant 3239 sql = getSqlForDeleteUserGrant(from.id, to.id) 3240 } 3241 err = bh.Exec(ctx, sql) 3242 if err != nil { 3243 goto handleFailed 3244 } 3245 } 3246 } 3247 3248 err = bh.Exec(ctx, "commit;") 3249 if err != nil { 3250 goto handleFailed 3251 } 3252 3253 return err 3254 3255 handleFailed: 3256 //ROLLBACK the transaction 3257 rbErr := bh.Exec(ctx, "rollback;") 3258 if rbErr != nil { 3259 return rbErr 3260 } 3261 return err 3262 } 3263 3264 // verifySpecialRolesInGrant verifies the special roles in the Grant statement 3265 func verifySpecialRolesInGrant(ctx context.Context, account *TenantInfo, from, to *verifiedRole) error { 3266 if account.IsNameOfAdminRoles(from.name) { 3267 if to.typ == userType { 3268 //check Grant moadmin to root,dump 3269 //check Grant accountadmin to admin_name 3270 //check Grant moadmin to userX 3271 //check Grant accountadmin to userX 3272 if !to.userIsAdmin { 3273 return moerr.NewInternalError(ctx, "the role %s can not be granted to non administration user %s", from.name, to.name) 3274 } 3275 } else { 3276 //check Grant moadmin(accountadmin) to roleX 3277 if !account.IsNameOfAdminRoles(to.name) { 3278 return moerr.NewInternalError(ctx, "the role %s can not be granted to the other role %s", from.name, to.name) 3279 } 3280 } 3281 } else if isPublicRole(from.name) && to.typ == roleType { 3282 return moerr.NewInternalError(ctx, "the role %s can not be granted to the other role %s", from.name, to.name) 3283 } 3284 3285 if to.typ == roleType { 3286 //check Grant roleX to moadmin(accountadmin) 3287 if account.IsNameOfAdminRoles(to.name) { 3288 return moerr.NewInternalError(ctx, "the role %s can not be granted to the role %s", from.name, to.name) 3289 } else if isPublicRole(to.name) { 3290 //check Grant roleX to public 3291 return moerr.NewInternalError(ctx, "the role %s can not be granted to the role %s", from.name, to.name) 3292 } 3293 } 3294 return nil 3295 } 3296 3297 // doGrantRole accomplishes the GrantRole statement 3298 func doGrantRole(ctx context.Context, ses *Session, gr *tree.GrantRole) error { 3299 var erArray []ExecResult 3300 var err error 3301 var withGrantOption int64 3302 err = normalizeNamesOfRoles(ctx, gr.Roles) 3303 if err != nil { 3304 return err 3305 } 3306 err = normalizeNamesOfUsers(ctx, gr.Users) 3307 if err != nil { 3308 return err 3309 } 3310 3311 account := ses.GetTenantInfo() 3312 bh := ses.GetBackgroundExec(ctx) 3313 defer bh.Close() 3314 3315 //step1 : check Roles exists or not 3316 var vr *verifiedRole 3317 var needLoadMoRoleGrant bool 3318 var grantedId, granteeId int64 3319 var useIsAdmin bool 3320 3321 verifiedFromRoles := make([]*verifiedRole, len(gr.Roles)) 3322 verifiedToRoles := make([]*verifiedRole, len(gr.Users)) 3323 3324 //load mo_role_grant into memory for 3325 checkLoopGraph := NewGraph() 3326 3327 //put it into the single transaction 3328 err = bh.Exec(ctx, "begin;") 3329 if err != nil { 3330 goto handleFailed 3331 } 3332 3333 for i, role := range gr.Roles { 3334 sql := getSqlForRoleIdOfRole(role.UserName) 3335 vr, err = verifyRoleFunc(ctx, bh, sql, role.UserName, roleType) 3336 if err != nil { 3337 goto handleFailed 3338 } 3339 if vr == nil { 3340 err = moerr.NewInternalError(ctx, "there is no role %s", role.UserName) 3341 goto handleFailed 3342 } 3343 verifiedFromRoles[i] = vr 3344 } 3345 3346 //step2 : check Users are real Users or Roles, exists or not 3347 for i, user := range gr.Users { 3348 sql := getSqlForRoleIdOfRole(user.Username) 3349 vr, err = verifyRoleFunc(ctx, bh, sql, user.Username, roleType) 3350 if err != nil { 3351 goto handleFailed 3352 } 3353 if vr != nil { 3354 verifiedToRoles[i] = vr 3355 } else { 3356 //check user exists or not 3357 sql = getSqlForPasswordOfUser(user.Username) 3358 vr, err = verifyRoleFunc(ctx, bh, sql, user.Username, userType) 3359 if err != nil { 3360 goto handleFailed 3361 } 3362 if vr == nil { 3363 err = moerr.NewInternalError(ctx, "there is no role or user %s", user.Username) 3364 goto handleFailed 3365 } 3366 verifiedToRoles[i] = vr 3367 3368 //the user is the administrator or not 3369 useIsAdmin, err = userIsAdministrator(ctx, bh, vr.id, account) 3370 if err != nil { 3371 goto handleFailed 3372 } 3373 verifiedToRoles[i].userIsAdmin = useIsAdmin 3374 } 3375 } 3376 3377 //If there is at least one role in the verifiedToRoles, 3378 //it is necessary to load the mo_role_grant 3379 for _, role := range verifiedToRoles { 3380 if role.typ == roleType { 3381 needLoadMoRoleGrant = true 3382 break 3383 } 3384 } 3385 3386 if needLoadMoRoleGrant { 3387 //load mo_role_grant 3388 sql := getSqlForGetAllStuffRoleGrantFormat() 3389 bh.ClearExecResultSet() 3390 err = bh.Exec(ctx, sql) 3391 if err != nil { 3392 goto handleFailed 3393 } 3394 3395 erArray, err = getResultSet(ctx, bh) 3396 if err != nil { 3397 goto handleFailed 3398 } 3399 3400 if execResultArrayHasData(erArray) { 3401 for j := uint64(0); j < erArray[0].GetRowCount(); j++ { 3402 //column grantedId 3403 grantedId, err = erArray[0].GetInt64(ctx, j, 0) 3404 if err != nil { 3405 goto handleFailed 3406 } 3407 3408 //column granteeId 3409 granteeId, err = erArray[0].GetInt64(ctx, j, 1) 3410 if err != nil { 3411 goto handleFailed 3412 } 3413 3414 checkLoopGraph.addEdge(grantedId, granteeId) 3415 } 3416 } 3417 } 3418 3419 //step3 : process Grant role to role 3420 //step4 : process Grant role to user 3421 3422 for _, from := range verifiedFromRoles { 3423 for _, to := range verifiedToRoles { 3424 err = verifySpecialRolesInGrant(ctx, account, from, to) 3425 if err != nil { 3426 goto handleFailed 3427 } 3428 3429 sql := "" 3430 if to.typ == roleType { 3431 if from.id == to.id { //direct loop 3432 err = moerr.NewRoleGrantedToSelf(ctx, from.name, to.name) 3433 goto handleFailed 3434 } else { 3435 //check the indirect loop 3436 edgeId := checkLoopGraph.addEdge(from.id, to.id) 3437 has := checkLoopGraph.hasLoop(from.id) 3438 if has { 3439 err = moerr.NewRoleGrantedToSelf(ctx, from.name, to.name) 3440 goto handleFailed 3441 } 3442 //restore the graph 3443 checkLoopGraph.removeEdge(edgeId) 3444 } 3445 3446 //grant to role 3447 //get (granted_id,grantee_id,with_grant_option) from the mo_role_grant 3448 sql = getSqlForCheckRoleGrant(from.id, to.id) 3449 } else { 3450 //grant to user 3451 //get (roleId,userId,with_grant_option) from the mo_user_grant 3452 sql = getSqlForCheckUserGrant(from.id, to.id) 3453 } 3454 bh.ClearExecResultSet() 3455 err = bh.Exec(ctx, sql) 3456 if err != nil { 3457 goto handleFailed 3458 } 3459 3460 erArray, err = getResultSet(ctx, bh) 3461 if err != nil { 3462 goto handleFailed 3463 } 3464 3465 //For Grant role to role 3466 //choice 1: (granted_id,grantee_id) exists and with_grant_option is same. 3467 // Do nothing. 3468 //choice 2: (granted_id,grantee_id) exists and with_grant_option is different. 3469 // Update. 3470 //choice 3: (granted_id,grantee_id) does not exist. 3471 // Insert. 3472 3473 //For Grant role to user 3474 //choice 1: (roleId,userId) exists and with_grant_option is same. 3475 // Do nothing. 3476 //choice 2: (roleId,userId) exists and with_grant_option is different. 3477 // Update. 3478 //choice 3: (roleId,userId) does not exist. 3479 // Insert. 3480 choice := 1 3481 if execResultArrayHasData(erArray) { 3482 for j := uint64(0); j < erArray[0].GetRowCount(); j++ { 3483 withGrantOption, err = erArray[0].GetInt64(ctx, j, 2) 3484 if err != nil { 3485 goto handleFailed 3486 } 3487 if (withGrantOption == 1) != gr.GrantOption { 3488 choice = 2 3489 } 3490 } 3491 } else { 3492 choice = 3 3493 } 3494 3495 sql = "" 3496 if choice == 2 { 3497 //update grant time 3498 if to.typ == roleType { 3499 sql = getSqlForUpdateRoleGrant(from.id, to.id, int64(account.GetDefaultRoleID()), int64(account.GetUserID()), types.CurrentTimestamp().String2(time.UTC, 0), gr.GrantOption) 3500 } else { 3501 sql = getSqlForUpdateUserGrant(from.id, to.id, types.CurrentTimestamp().String2(time.UTC, 0), gr.GrantOption) 3502 } 3503 } else if choice == 3 { 3504 //insert new record 3505 if to.typ == roleType { 3506 sql = getSqlForInsertRoleGrant(from.id, to.id, int64(account.GetDefaultRoleID()), int64(account.GetUserID()), types.CurrentTimestamp().String2(time.UTC, 0), gr.GrantOption) 3507 } else { 3508 sql = getSqlForInsertUserGrant(from.id, to.id, types.CurrentTimestamp().String2(time.UTC, 0), gr.GrantOption) 3509 } 3510 } 3511 3512 if choice != 1 { 3513 err = bh.Exec(ctx, sql) 3514 if err != nil { 3515 goto handleFailed 3516 } 3517 } 3518 } 3519 } 3520 3521 err = bh.Exec(ctx, "commit;") 3522 if err != nil { 3523 goto handleFailed 3524 } 3525 3526 return err 3527 3528 handleFailed: 3529 //ROLLBACK the transaction 3530 rbErr := bh.Exec(ctx, "rollback;") 3531 if rbErr != nil { 3532 return rbErr 3533 } 3534 return err 3535 } 3536 3537 // determinePrivilegeSetOfStatement decides the privileges that the statement needs before running it. 3538 // That is the Set P for the privilege Set . 3539 func determinePrivilegeSetOfStatement(stmt tree.Statement) *privilege { 3540 typs := make([]PrivilegeType, 0, 5) 3541 kind := privilegeKindGeneral 3542 special := specialTagNone 3543 objType := objectTypeAccount 3544 var extraEntries []privilegeEntry 3545 writeDatabaseAndTableDirectly := false 3546 var clusterTable bool 3547 var clusterTableOperation clusterTableOperationType 3548 dbName := "" 3549 switch st := stmt.(type) { 3550 case *tree.CreateAccount: 3551 typs = append(typs, PrivilegeTypeCreateAccount) 3552 case *tree.DropAccount: 3553 typs = append(typs, PrivilegeTypeDropAccount) 3554 case *tree.AlterAccount: 3555 typs = append(typs, PrivilegeTypeAlterAccount) 3556 case *tree.CreateUser: 3557 if st.Role == nil { 3558 typs = append(typs, PrivilegeTypeCreateUser, PrivilegeTypeAccountAll /*, PrivilegeTypeAccountOwnership*/) 3559 } else { 3560 typs = append(typs, PrivilegeTypeAccountAll /*, PrivilegeTypeAccountOwnership*/) 3561 me1 := &compoundEntry{ 3562 items: []privilegeItem{ 3563 {privilegeTyp: PrivilegeTypeCreateUser}, 3564 {privilegeTyp: PrivilegeTypeManageGrants}, 3565 }, 3566 } 3567 me2 := &compoundEntry{ 3568 items: []privilegeItem{ 3569 {privilegeTyp: PrivilegeTypeCreateUser}, 3570 {privilegeTyp: PrivilegeTypeCanGrantRoleToOthersInCreateUser, role: st.Role, users: st.Users}, 3571 }, 3572 } 3573 3574 entry1 := privilegeEntry{ 3575 privilegeEntryTyp: privilegeEntryTypeCompound, 3576 compound: me1, 3577 } 3578 entry2 := privilegeEntry{ 3579 privilegeEntryTyp: privilegeEntryTypeCompound, 3580 compound: me2, 3581 } 3582 extraEntries = append(extraEntries, entry1, entry2) 3583 } 3584 case *tree.DropUser: 3585 typs = append(typs, PrivilegeTypeDropUser, PrivilegeTypeAccountAll /*, PrivilegeTypeAccountOwnership, PrivilegeTypeUserOwnership*/) 3586 case *tree.AlterUser: 3587 typs = append(typs, PrivilegeTypeAlterUser, PrivilegeTypeAccountAll /*, PrivilegeTypeAccountOwnership, PrivilegeTypeUserOwnership*/) 3588 case *tree.CreateRole: 3589 typs = append(typs, PrivilegeTypeCreateRole, PrivilegeTypeAccountAll /*, PrivilegeTypeAccountOwnership*/) 3590 case *tree.DropRole: 3591 typs = append(typs, PrivilegeTypeDropRole, PrivilegeTypeAccountAll /*, PrivilegeTypeAccountOwnership, PrivilegeTypeRoleOwnership*/) 3592 case *tree.Grant: 3593 if st.Typ == tree.GrantTypeRole { 3594 kind = privilegeKindInherit 3595 typs = append(typs, PrivilegeTypeManageGrants, PrivilegeTypeAccountAll /*, PrivilegeTypeAccountOwnership, PrivilegeTypeRoleOwnership*/) 3596 } else if st.Typ == tree.GrantTypePrivilege { 3597 objType = objectTypeNone 3598 kind = privilegeKindSpecial 3599 special = specialTagAdmin | specialTagWithGrantOption | specialTagOwnerOfObject 3600 } 3601 case *tree.GrantRole: 3602 kind = privilegeKindInherit 3603 typs = append(typs, PrivilegeTypeManageGrants, PrivilegeTypeAccountAll /*, PrivilegeTypeAccountOwnership, PrivilegeTypeRoleOwnership*/) 3604 case *tree.GrantPrivilege: 3605 objType = objectTypeNone 3606 kind = privilegeKindSpecial 3607 special = specialTagAdmin | specialTagWithGrantOption | specialTagOwnerOfObject 3608 case *tree.Revoke: 3609 if st.Typ == tree.RevokeTypeRole { 3610 typs = append(typs, PrivilegeTypeManageGrants, PrivilegeTypeAccountAll /*, PrivilegeTypeAccountOwnership, PrivilegeTypeRoleOwnership*/) 3611 } else if st.Typ == tree.RevokeTypePrivilege { 3612 objType = objectTypeNone 3613 kind = privilegeKindSpecial 3614 special = specialTagAdmin 3615 } 3616 case *tree.RevokeRole: 3617 typs = append(typs, PrivilegeTypeManageGrants, PrivilegeTypeAccountAll /*, PrivilegeTypeAccountOwnership, PrivilegeTypeRoleOwnership*/) 3618 case *tree.RevokePrivilege: 3619 objType = objectTypeNone 3620 kind = privilegeKindSpecial 3621 special = specialTagAdmin 3622 case *tree.CreateDatabase: 3623 typs = append(typs, PrivilegeTypeCreateDatabase, PrivilegeTypeAccountAll /*, PrivilegeTypeAccountOwnership*/) 3624 case *tree.DropDatabase: 3625 typs = append(typs, PrivilegeTypeDropDatabase, PrivilegeTypeAccountAll /*, PrivilegeTypeAccountOwnership*/) 3626 writeDatabaseAndTableDirectly = true 3627 dbName = string(st.Name) 3628 case *tree.ShowDatabases: 3629 typs = append(typs, PrivilegeTypeShowDatabases, PrivilegeTypeAccountAll /*, PrivilegeTypeAccountOwnership*/) 3630 case *tree.Use: 3631 typs = append(typs, PrivilegeTypeConnect, PrivilegeTypeAccountAll /*, PrivilegeTypeAccountOwnership*/) 3632 case *tree.ShowTables, *tree.ShowCreateTable, *tree.ShowColumns, *tree.ShowCreateView, *tree.ShowCreateDatabase: 3633 objType = objectTypeDatabase 3634 typs = append(typs, PrivilegeTypeShowTables, PrivilegeTypeDatabaseAll, PrivilegeTypeDatabaseOwnership) 3635 case *tree.CreateTable: 3636 objType = objectTypeDatabase 3637 typs = append(typs, PrivilegeTypeCreateTable, PrivilegeTypeDatabaseAll, PrivilegeTypeDatabaseOwnership) 3638 writeDatabaseAndTableDirectly = true 3639 if st.IsClusterTable { 3640 clusterTable = true 3641 clusterTableOperation = clusterTableCreate 3642 } 3643 dbName = string(st.Table.SchemaName) 3644 case *tree.CreateView: 3645 objType = objectTypeDatabase 3646 typs = append(typs, PrivilegeTypeCreateView, PrivilegeTypeDatabaseAll, PrivilegeTypeDatabaseOwnership) 3647 writeDatabaseAndTableDirectly = true 3648 if st.Name != nil { 3649 dbName = string(st.Name.SchemaName) 3650 } 3651 case *tree.AlterView: 3652 objType = objectTypeDatabase 3653 typs = append(typs, PrivilegeTypeAlterView, PrivilegeTypeDatabaseAll, PrivilegeTypeDatabaseOwnership) 3654 writeDatabaseAndTableDirectly = true 3655 if st.Name != nil { 3656 dbName = string(st.Name.SchemaName) 3657 } 3658 case *tree.AlterDataBaseConfig: 3659 objType = objectTypeNone 3660 kind = privilegeKindNone 3661 case *tree.CreateFunction: 3662 objType = objectTypeDatabase 3663 typs = append(typs, PrivilegeTypeCreateView, PrivilegeTypeDatabaseAll, PrivilegeTypeDatabaseOwnership) 3664 writeDatabaseAndTableDirectly = true 3665 case *tree.DropTable: 3666 objType = objectTypeDatabase 3667 typs = append(typs, PrivilegeTypeDropTable, PrivilegeTypeDropObject, PrivilegeTypeDatabaseAll, PrivilegeTypeDatabaseOwnership) 3668 writeDatabaseAndTableDirectly = true 3669 if len(st.Names) != 0 { 3670 dbName = string(st.Names[0].SchemaName) 3671 } 3672 case *tree.DropView: 3673 objType = objectTypeDatabase 3674 typs = append(typs, PrivilegeTypeDropView, PrivilegeTypeDropObject, PrivilegeTypeDatabaseAll, PrivilegeTypeDatabaseOwnership) 3675 writeDatabaseAndTableDirectly = true 3676 if len(st.Names) != 0 { 3677 dbName = string(st.Names[0].SchemaName) 3678 } 3679 case *tree.DropFunction: 3680 objType = objectTypeDatabase 3681 typs = append(typs, PrivilegeTypeCreateView, PrivilegeTypeDatabaseAll, PrivilegeTypeDatabaseOwnership) 3682 writeDatabaseAndTableDirectly = true 3683 case *tree.Select, *tree.Do: 3684 objType = objectTypeTable 3685 typs = append(typs, PrivilegeTypeSelect, PrivilegeTypeTableAll, PrivilegeTypeTableOwnership) 3686 case *tree.Insert: 3687 objType = objectTypeTable 3688 typs = append(typs, PrivilegeTypeInsert, PrivilegeTypeTableAll, PrivilegeTypeTableOwnership) 3689 writeDatabaseAndTableDirectly = true 3690 case *tree.Replace: 3691 objType = objectTypeTable 3692 typs = append(typs, PrivilegeTypeInsert, PrivilegeTypeTableAll, PrivilegeTypeTableOwnership) 3693 writeDatabaseAndTableDirectly = true 3694 case *tree.Load: 3695 objType = objectTypeTable 3696 typs = append(typs, PrivilegeTypeInsert, PrivilegeTypeTableAll, PrivilegeTypeTableOwnership) 3697 writeDatabaseAndTableDirectly = true 3698 if st.Table != nil { 3699 dbName = string(st.Table.SchemaName) 3700 } 3701 case *tree.Import: 3702 objType = objectTypeTable 3703 typs = append(typs, PrivilegeTypeInsert, PrivilegeTypeTableAll, PrivilegeTypeTableOwnership) 3704 writeDatabaseAndTableDirectly = true 3705 if st.Table != nil { 3706 dbName = string(st.Table.SchemaName) 3707 } 3708 case *tree.Update: 3709 objType = objectTypeTable 3710 typs = append(typs, PrivilegeTypeUpdate, PrivilegeTypeTableAll, PrivilegeTypeTableOwnership) 3711 writeDatabaseAndTableDirectly = true 3712 case *tree.Delete: 3713 objType = objectTypeTable 3714 typs = append(typs, PrivilegeTypeDelete, PrivilegeTypeTableAll, PrivilegeTypeTableOwnership) 3715 writeDatabaseAndTableDirectly = true 3716 case *tree.CreateIndex, *tree.DropIndex: 3717 objType = objectTypeTable 3718 typs = append(typs, PrivilegeTypeIndex, PrivilegeTypeTableAll, PrivilegeTypeTableOwnership) 3719 writeDatabaseAndTableDirectly = true 3720 case *tree.ShowProcessList, *tree.ShowErrors, *tree.ShowWarnings, *tree.ShowVariables, 3721 *tree.ShowStatus, *tree.ShowTarget, *tree.ShowTableStatus, 3722 *tree.ShowGrants, *tree.ShowCollation, *tree.ShowIndex, 3723 *tree.ShowTableNumber, *tree.ShowColumnNumber, 3724 *tree.ShowTableValues, *tree.ShowNodeList, 3725 *tree.ShowLocks, *tree.ShowFunctionStatus: 3726 objType = objectTypeNone 3727 kind = privilegeKindNone 3728 case *tree.ShowAccounts: 3729 objType = objectTypeNone 3730 kind = privilegeKindSpecial 3731 special = specialTagAdmin 3732 case *tree.ExplainFor, *tree.ExplainAnalyze, *tree.ExplainStmt: 3733 objType = objectTypeNone 3734 kind = privilegeKindNone 3735 case *tree.BeginTransaction, *tree.CommitTransaction, *tree.RollbackTransaction, *tree.SetVar: 3736 objType = objectTypeNone 3737 kind = privilegeKindNone 3738 case *tree.SetDefaultRole, *tree.SetRole, *tree.SetPassword: 3739 objType = objectTypeNone 3740 kind = privilegeKindNone 3741 case *tree.PrepareStmt, *tree.PrepareString, *tree.Deallocate, *tree.Reset: 3742 objType = objectTypeNone 3743 kind = privilegeKindNone 3744 case *tree.Execute: 3745 objType = objectTypeNone 3746 kind = privilegeKindNone 3747 case *tree.Declare: 3748 objType = objectTypeNone 3749 kind = privilegeKindNone 3750 case *InternalCmdFieldList: 3751 objType = objectTypeNone 3752 kind = privilegeKindNone 3753 case *tree.ValuesStatement: 3754 objType = objectTypeTable 3755 typs = append(typs, PrivilegeTypeValues, PrivilegeTypeTableAll, PrivilegeTypeTableOwnership) 3756 case *tree.TruncateTable: 3757 objType = objectTypeTable 3758 typs = append(typs, PrivilegeTypeTruncate, PrivilegeTypeTableAll, PrivilegeTypeTableOwnership) 3759 writeDatabaseAndTableDirectly = true 3760 if st.Name != nil { 3761 dbName = string(st.Name.SchemaName) 3762 } 3763 case *tree.MoDump: 3764 if st.Tables != nil { 3765 objType = objectTypeTable 3766 typs = append(typs, PrivilegeTypeDump, PrivilegeTypeTableAll, PrivilegeTypeTableOwnership) 3767 } else { 3768 objType = objectTypeDatabase 3769 typs = append(typs, PrivilegeTypeDump, PrivilegeTypeDatabaseAll, PrivilegeTypeDatabaseOwnership) 3770 } 3771 case *tree.Kill: 3772 objType = objectTypeNone 3773 kind = privilegeKindNone 3774 default: 3775 panic(fmt.Sprintf("does not have the privilege definition of the statement %s", stmt)) 3776 } 3777 3778 entries := make([]privilegeEntry, len(typs)) 3779 for i, typ := range typs { 3780 entries[i] = privilegeEntriesMap[typ] 3781 entries[i].databaseName = dbName 3782 } 3783 entries = append(entries, extraEntries...) 3784 return &privilege{ 3785 kind: kind, 3786 objType: objType, 3787 entries: entries, 3788 special: special, 3789 writeDatabaseAndTableDirectly: writeDatabaseAndTableDirectly, 3790 isClusterTable: clusterTable, 3791 clusterTableOperation: clusterTableOperation} 3792 } 3793 3794 // privilege will be done on the table 3795 type privilegeTips struct { 3796 typ PrivilegeType 3797 databaseName string 3798 tableName string 3799 isClusterTable bool 3800 clusterTableOperation clusterTableOperationType 3801 } 3802 3803 type privilegeTipsArray []privilegeTips 3804 3805 func (pot privilegeTips) String() string { 3806 return fmt.Sprintf("%s %s %s", pot.typ, pot.databaseName, pot.tableName) 3807 } 3808 3809 func (pota privilegeTipsArray) String() string { 3810 b := strings.Builder{} 3811 for _, table := range pota { 3812 b.WriteString(table.String()) 3813 b.WriteString("\n") 3814 } 3815 return b.String() 3816 } 3817 3818 // extractPrivilegeTipsFromPlan extracts the privilege tips from the plan 3819 func extractPrivilegeTipsFromPlan(p *plan2.Plan) privilegeTipsArray { 3820 //NOTE: the pts may be nil when the plan does operate any table. 3821 var pts privilegeTipsArray 3822 appendPt := func(pt privilegeTips) { 3823 pts = append(pts, pt) 3824 } 3825 if p.GetQuery() != nil { //select,insert select, update, delete 3826 q := p.GetQuery() 3827 lastNode := q.Nodes[len(q.Nodes)-1] 3828 var t PrivilegeType 3829 var clusterTable bool 3830 var clusterTableOperation clusterTableOperationType 3831 for _, node := range q.Nodes { 3832 if node.NodeType == plan.Node_TABLE_SCAN { 3833 switch lastNode.NodeType { 3834 case plan.Node_UPDATE: 3835 t = PrivilegeTypeUpdate 3836 clusterTableOperation = clusterTableModify 3837 case plan.Node_DELETE: 3838 t = PrivilegeTypeDelete 3839 clusterTableOperation = clusterTableModify 3840 default: 3841 t = PrivilegeTypeSelect 3842 clusterTableOperation = clusterTableSelect 3843 } 3844 if node.ObjRef != nil { 3845 if node.TableDef != nil && node.TableDef.TableType == catalog.SystemClusterRel { 3846 clusterTable = true 3847 } else { 3848 clusterTable = isClusterTable(node.ObjRef.GetSchemaName(), node.ObjRef.GetObjName()) 3849 } 3850 //do not check the privilege of the index table 3851 if !isIndexTable(node.ObjRef.GetObjName()) { 3852 appendPt(privilegeTips{ 3853 typ: t, 3854 databaseName: node.ObjRef.GetSchemaName(), 3855 tableName: node.ObjRef.GetObjName(), 3856 isClusterTable: clusterTable, 3857 clusterTableOperation: clusterTableOperation, 3858 }) 3859 } 3860 } 3861 } else if node.NodeType == plan.Node_INSERT { //insert select 3862 if node.ObjRef != nil { 3863 if node.TableDef != nil && node.TableDef.TableType == catalog.SystemClusterRel { 3864 clusterTable = true 3865 } else { 3866 clusterTable = isClusterTable(node.ObjRef.GetSchemaName(), node.ObjRef.GetObjName()) 3867 } 3868 //do not check the privilege of the index table 3869 if !isIndexTable(node.ObjRef.GetObjName()) { 3870 appendPt(privilegeTips{ 3871 typ: PrivilegeTypeInsert, 3872 databaseName: node.ObjRef.GetSchemaName(), 3873 tableName: node.ObjRef.GetObjName(), 3874 isClusterTable: clusterTable, 3875 clusterTableOperation: clusterTableModify, 3876 }) 3877 } 3878 } 3879 } else if node.NodeType == plan.Node_DELETE { 3880 if node.ObjRef != nil { 3881 if node.TableDef != nil && node.TableDef.TableType == catalog.SystemClusterRel { 3882 clusterTable = true 3883 } else { 3884 clusterTable = isClusterTable(node.ObjRef.GetSchemaName(), node.ObjRef.GetObjName()) 3885 } 3886 //do not check the privilege of the index table 3887 if !isIndexTable(node.ObjRef.GetObjName()) { 3888 appendPt(privilegeTips{ 3889 typ: PrivilegeTypeDelete, 3890 databaseName: node.ObjRef.GetSchemaName(), 3891 tableName: node.ObjRef.GetObjName(), 3892 isClusterTable: clusterTable, 3893 clusterTableOperation: clusterTableModify, 3894 }) 3895 } 3896 } 3897 } 3898 } 3899 } else if p.GetDdl() != nil { 3900 if p.GetDdl().GetTruncateTable() != nil { 3901 truncateTable := p.GetDdl().GetTruncateTable() 3902 appendPt(privilegeTips{ 3903 typ: PrivilegeTypeTruncate, 3904 databaseName: truncateTable.GetDatabase(), 3905 tableName: truncateTable.GetTable(), 3906 isClusterTable: truncateTable.GetClusterTable().GetIsClusterTable(), 3907 clusterTableOperation: clusterTableModify, 3908 }) 3909 } else if p.GetDdl().GetDropTable() != nil { 3910 dropTable := p.GetDdl().GetDropTable() 3911 appendPt(privilegeTips{ 3912 typ: PrivilegeTypeDropTable, 3913 databaseName: dropTable.GetDatabase(), 3914 tableName: dropTable.GetTable(), 3915 isClusterTable: dropTable.GetClusterTable().GetIsClusterTable(), 3916 clusterTableOperation: clusterTableDrop, 3917 }) 3918 } 3919 } 3920 return pts 3921 } 3922 3923 // convertPrivilegeTipsToPrivilege constructs the privilege entries from the privilege tips from the plan 3924 func convertPrivilegeTipsToPrivilege(priv *privilege, arr privilegeTipsArray) { 3925 //rewirte the privilege entries based on privilege tips 3926 if priv.objectType() != objectTypeTable && 3927 priv.objectType() != objectTypeDatabase { 3928 return 3929 } 3930 3931 //NOTE: when the arr is nil, it denotes that there is no operation on the table. 3932 3933 type pair struct { 3934 databaseName string 3935 tableName string 3936 } 3937 3938 dedup := make(map[pair]int8) 3939 3940 //multi privileges take effect together 3941 entries := make([]privilegeEntry, 0, len(arr)) 3942 multiPrivs := make([]privilegeItem, 0, len(arr)) 3943 for _, tips := range arr { 3944 multiPrivs = append(multiPrivs, privilegeItem{ 3945 privilegeTyp: tips.typ, 3946 dbName: tips.databaseName, 3947 tableName: tips.tableName, 3948 isClusterTable: tips.isClusterTable, 3949 clusterTableOperation: tips.clusterTableOperation, 3950 }) 3951 3952 dedup[pair{tips.databaseName, tips.tableName}] = 1 3953 } 3954 3955 me := &compoundEntry{multiPrivs} 3956 entries = append(entries, privilegeEntry{privilegeEntryTyp: privilegeEntryTypeCompound, compound: me}) 3957 3958 //optional predefined privilege : tableAll, ownership 3959 predefined := []PrivilegeType{PrivilegeTypeTableAll, PrivilegeTypeTableOwnership} 3960 for _, p := range predefined { 3961 for par := range dedup { 3962 e := privilegeEntriesMap[p] 3963 e.databaseName = par.databaseName 3964 e.tableName = par.tableName 3965 entries = append(entries, e) 3966 } 3967 } 3968 3969 priv.entries = entries 3970 } 3971 3972 // getSqlFromPrivilegeEntry generates the query sql for the privilege entry 3973 func getSqlFromPrivilegeEntry(ctx context.Context, roleId int64, entry privilegeEntry) (string, error) { 3974 var sql string 3975 //for object type table, need concrete tableid 3976 //TODO: table level check should be done after getting the plan 3977 if entry.objType == objectTypeTable { 3978 switch entry.privilegeLevel { 3979 case privilegeLevelDatabaseTable, privilegeLevelTable: 3980 sql = getSqlForCheckRoleHasTableLevelPrivilege(roleId, entry.privilegeId, entry.databaseName, entry.tableName) 3981 case privilegeLevelDatabaseStar, privilegeLevelStar: 3982 sql = getSqlForCheckRoleHasTableLevelForDatabaseStar(roleId, entry.privilegeId, entry.databaseName) 3983 case privilegeLevelStarStar: 3984 sql = getSqlForCheckRoleHasTableLevelForStarStar(roleId, entry.privilegeId) 3985 default: 3986 return "", moerr.NewInternalError(ctx, "unsupported privilegel level %s for the privilege %s", entry.privilegeLevel, entry.privilegeId) 3987 } 3988 } else if entry.objType == objectTypeDatabase { 3989 switch entry.privilegeLevel { 3990 case privilegeLevelStar, privilegeLevelStarStar: 3991 sql = getSqlForCheckRoleHasDatabaseLevelForStarStar(roleId, entry.privilegeId, entry.privilegeLevel) 3992 case privilegeLevelDatabase: 3993 sql = getSqlForCheckRoleHasDatabaseLevelForDatabase(roleId, entry.privilegeId, entry.databaseName) 3994 default: 3995 return "", moerr.NewInternalError(ctx, "unsupported privilegel level %s for the privilege %s", entry.privilegeLevel, entry.privilegeId) 3996 } 3997 } else if entry.objType == objectTypeAccount { 3998 switch entry.privilegeLevel { 3999 case privilegeLevelStar: 4000 sql = getSqlForCheckRoleHasAccountLevelForStar(roleId, entry.privilegeId) 4001 default: 4002 return "false", moerr.NewInternalError(ctx, "unsupported privilegel level %s for the privilege %s", entry.privilegeLevel, entry.privilegeId) 4003 } 4004 } else { 4005 sql = getSqlForCheckRoleHasPrivilege(roleId, entry.objType, int64(entry.objId), int64(entry.privilegeId)) 4006 } 4007 return sql, nil 4008 } 4009 4010 // getPrivilegeLevelsOfObjectType gets the privilege levels of the objectType 4011 func getPrivilegeLevelsOfObjectType(ctx context.Context, objType objectType) ([]privilegeLevelType, error) { 4012 if ret, ok := objectType2privilegeLevels[objType]; ok { 4013 return ret, nil 4014 } 4015 return nil, moerr.NewInternalError(ctx, "do not support the object type %s", objType.String()) 4016 } 4017 4018 // getSqlForPrivilege generates the query sql for the privilege entry 4019 func getSqlForPrivilege(ctx context.Context, roleId int64, entry privilegeEntry, pl privilegeLevelType) (string, error) { 4020 var sql string 4021 //for object type table, need concrete tableid 4022 switch entry.objType { 4023 case objectTypeTable: 4024 switch pl { 4025 case privilegeLevelDatabaseTable, privilegeLevelTable: 4026 sql = getSqlForCheckRoleHasTableLevelPrivilege(roleId, entry.privilegeId, entry.databaseName, entry.tableName) 4027 case privilegeLevelDatabaseStar, privilegeLevelStar: 4028 sql = getSqlForCheckRoleHasTableLevelForDatabaseStar(roleId, entry.privilegeId, entry.databaseName) 4029 case privilegeLevelStarStar: 4030 sql = getSqlForCheckRoleHasTableLevelForStarStar(roleId, entry.privilegeId) 4031 default: 4032 return "", moerr.NewInternalError(ctx, "the privilege level %s for the privilege %s is unsupported", pl, entry.privilegeId) 4033 } 4034 case objectTypeDatabase: 4035 switch pl { 4036 case privilegeLevelStar, privilegeLevelStarStar: 4037 sql = getSqlForCheckRoleHasDatabaseLevelForStarStar(roleId, entry.privilegeId, pl) 4038 case privilegeLevelDatabase: 4039 sql = getSqlForCheckRoleHasDatabaseLevelForDatabase(roleId, entry.privilegeId, entry.databaseName) 4040 default: 4041 return "", moerr.NewInternalError(ctx, "the privilege level %s for the privilege %s is unsupported", pl, entry.privilegeId) 4042 } 4043 case objectTypeAccount: 4044 switch pl { 4045 case privilegeLevelStar: 4046 sql = getSqlForCheckRoleHasAccountLevelForStar(roleId, entry.privilegeId) 4047 default: 4048 return "false", moerr.NewInternalError(ctx, "the privilege level %s for the privilege %s is unsupported", pl, entry.privilegeId) 4049 } 4050 default: 4051 sql = getSqlForCheckRoleHasPrivilege(roleId, entry.objType, int64(entry.objId), int64(entry.privilegeId)) 4052 } 4053 4054 return sql, nil 4055 } 4056 4057 // getSqlForPrivilege2 complements the database name and calls getSqlForPrivilege 4058 func getSqlForPrivilege2(ses *Session, roleId int64, entry privilegeEntry, pl privilegeLevelType) (string, error) { 4059 //handle the empty database 4060 if len(entry.databaseName) == 0 { 4061 entry.databaseName = ses.GetDatabaseName() 4062 } 4063 return getSqlForPrivilege(ses.GetRequestContext(), roleId, entry, pl) 4064 } 4065 4066 // verifyPrivilegeEntryInMultiPrivilegeLevels checks the privilege 4067 // with multi-privilege levels exists or not 4068 func verifyPrivilegeEntryInMultiPrivilegeLevels( 4069 ctx context.Context, 4070 bh BackgroundExec, 4071 ses *Session, 4072 cache *privilegeCache, 4073 roleId int64, 4074 entry privilegeEntry, 4075 pls []privilegeLevelType) (bool, error) { 4076 var erArray []ExecResult 4077 var sql string 4078 var yes bool 4079 var err error 4080 dbName := entry.databaseName 4081 if len(dbName) == 0 { 4082 dbName = ses.GetDatabaseName() 4083 } 4084 for _, pl := range pls { 4085 yes = cache.has(entry.objType, pl, dbName, entry.tableName, entry.privilegeId) 4086 if yes { 4087 return true, nil 4088 } 4089 sql, err = getSqlForPrivilege2(ses, roleId, entry, pl) 4090 if err != nil { 4091 return false, err 4092 } 4093 4094 bh.ClearExecResultSet() 4095 err = bh.Exec(ctx, sql) 4096 if err != nil { 4097 return false, err 4098 } 4099 4100 erArray, err = getResultSet(ctx, bh) 4101 if err != nil { 4102 return false, err 4103 } 4104 4105 if execResultArrayHasData(erArray) { 4106 cache.add(entry.objType, pl, dbName, entry.tableName, entry.privilegeId) 4107 return true, nil 4108 } 4109 } 4110 return false, nil 4111 } 4112 4113 // determineRoleSetHasPrivilegeSet decides the role set has at least one privilege of the privilege set. 4114 // The algorithm 2. 4115 func determineRoleSetHasPrivilegeSet(ctx context.Context, bh BackgroundExec, ses *Session, roleIds *btree.Set[int64], priv *privilege) (bool, error) { 4116 var err error 4117 var pls []privilegeLevelType 4118 4119 var yes bool 4120 var yes2 bool 4121 //there is no privilege needs, just approve 4122 if len(priv.entries) == 0 { 4123 return false, nil 4124 } 4125 4126 cache := ses.GetPrivilegeCache() 4127 4128 for _, roleId := range roleIds.Keys() { 4129 for _, entry := range priv.entries { 4130 if entry.privilegeEntryTyp == privilegeEntryTypeGeneral { 4131 pls, err = getPrivilegeLevelsOfObjectType(ctx, entry.objType) 4132 if err != nil { 4133 return false, err 4134 } 4135 4136 yes2 = verifyLightPrivilege(ses, 4137 entry.databaseName, 4138 priv.writeDatabaseAndTableDirectly, 4139 priv.isClusterTable, 4140 priv.clusterTableOperation) 4141 4142 if yes2 { 4143 yes, err = verifyPrivilegeEntryInMultiPrivilegeLevels(ctx, bh, ses, cache, roleId, entry, pls) 4144 if err != nil { 4145 return false, err 4146 } 4147 } 4148 4149 if yes { 4150 return true, nil 4151 } 4152 } else if entry.privilegeEntryTyp == privilegeEntryTypeCompound { 4153 if entry.compound != nil { 4154 allTrue := true 4155 //multi privileges take effect together 4156 for _, mi := range entry.compound.items { 4157 if mi.privilegeTyp == PrivilegeTypeCanGrantRoleToOthersInCreateUser { 4158 //TODO: normalize the name 4159 //TODO: simplify the logic 4160 yes, err = determineUserCanGrantRolesToOthersInternal(ctx, bh, ses, []*tree.Role{mi.role}) 4161 if err != nil { 4162 return false, err 4163 } 4164 if yes { 4165 from := &verifiedRole{ 4166 typ: roleType, 4167 name: mi.role.UserName, 4168 } 4169 for _, user := range mi.users { 4170 to := &verifiedRole{ 4171 typ: userType, 4172 name: user.Username, 4173 } 4174 err = verifySpecialRolesInGrant(ctx, ses.GetTenantInfo(), from, to) 4175 if err != nil { 4176 return false, err 4177 } 4178 } 4179 } 4180 } else { 4181 tempEntry := privilegeEntriesMap[mi.privilegeTyp] 4182 tempEntry.databaseName = mi.dbName 4183 tempEntry.tableName = mi.tableName 4184 tempEntry.privilegeEntryTyp = privilegeEntryTypeGeneral 4185 tempEntry.compound = nil 4186 pls, err = getPrivilegeLevelsOfObjectType(ctx, tempEntry.objType) 4187 if err != nil { 4188 return false, err 4189 } 4190 4191 yes2 = verifyLightPrivilege(ses, 4192 tempEntry.databaseName, 4193 priv.writeDatabaseAndTableDirectly, 4194 mi.isClusterTable, 4195 mi.clusterTableOperation) 4196 4197 if yes2 { 4198 //At least there is one success 4199 yes, err = verifyPrivilegeEntryInMultiPrivilegeLevels(ctx, bh, ses, cache, roleId, tempEntry, pls) 4200 if err != nil { 4201 return false, err 4202 } 4203 } 4204 } 4205 if !yes { 4206 allTrue = false 4207 break 4208 } 4209 } 4210 4211 if allTrue { 4212 return allTrue, nil 4213 } 4214 } 4215 } 4216 } 4217 } 4218 return false, nil 4219 } 4220 4221 // determineUserHasPrivilegeSet decides the privileges of user can satisfy the requirement of the privilege set 4222 // The algorithm 1. 4223 func determineUserHasPrivilegeSet(ctx context.Context, ses *Session, priv *privilege, stmt tree.Statement) (bool, error) { 4224 var erArray []ExecResult 4225 var yes bool 4226 var err error 4227 var roleB int64 4228 var ret bool 4229 var ok bool 4230 var grantedIds *btree.Set[int64] 4231 4232 tenant := ses.GetTenantInfo() 4233 bh := ses.GetBackgroundExec(ctx) 4234 defer bh.Close() 4235 4236 //the set of roles the (k+1) th iteration during the execution 4237 roleSetOfKPlusOneThIteration := &btree.Set[int64]{} 4238 //the set of roles the k th iteration during the execution 4239 roleSetOfKthIteration := &btree.Set[int64]{} 4240 //the set of roles visited by traversal algorithm 4241 roleSetOfVisited := &btree.Set[int64]{} 4242 //simple mo_role_grant cache 4243 cacheOfMoRoleGrant := &btree.Map[int64, *btree.Set[int64]]{} 4244 4245 //step 1: The Set R1 {default role id} 4246 //The primary role (in use) 4247 roleSetOfKthIteration.Insert((int64)(tenant.GetDefaultRoleID())) 4248 4249 err = bh.Exec(ctx, "begin;") 4250 if err != nil { 4251 goto handleFailed 4252 } 4253 4254 //step 2: The Set R2 {the roleid granted to the userid} 4255 //If the user uses the all secondary roles, the secondary roles needed to be loaded 4256 err = loadAllSecondaryRoles(ctx, bh, tenant, roleSetOfKthIteration) 4257 if err != nil { 4258 goto handleFailed 4259 } 4260 4261 //init RVisited = Rk 4262 roleSetOfKthIteration.Scan(func(roleId int64) bool { 4263 roleSetOfVisited.Insert(roleId) 4264 return true 4265 }) 4266 4267 //Call the algorithm 2. 4268 //If the result of the algorithm 2 is true, Then return true; 4269 yes, err = determineRoleSetHasPrivilegeSet(ctx, bh, ses, roleSetOfKthIteration, priv) 4270 if err != nil { 4271 goto handleFailed 4272 } 4273 if yes { 4274 ret = true 4275 goto handleSuccess 4276 } 4277 /* 4278 step 3: !!!NOTE all roleid in Rk has been processed by the algorithm 2. 4279 RVisited is the set of all roleid that has been processed. 4280 RVisited = Rk; 4281 For { 4282 For roleA in Rk { 4283 Find the peer roleB in the table mo_role_grant(granted_id,grantee_id) with grantee_id = roleA; 4284 If roleB is not in RVisited, Then add roleB into R(k+1); 4285 add roleB into RVisited; 4286 } 4287 4288 If R(k+1) is empty, Then return false; 4289 //Call the algorithm 2. 4290 If the result of the algorithm 2 is true, Then return true; 4291 Rk = R(k+1); 4292 R(k+1) = {}; 4293 } 4294 */ 4295 for { 4296 quit := false 4297 select { 4298 case <-ctx.Done(): 4299 quit = true 4300 default: 4301 } 4302 if quit { 4303 break 4304 } 4305 4306 roleSetOfKPlusOneThIteration.Clear() 4307 4308 //get roleB of roleA 4309 for _, roleA := range roleSetOfKthIteration.Keys() { 4310 if grantedIds, ok = cacheOfMoRoleGrant.Get(roleA); ok { 4311 for _, grantedId := range grantedIds.Keys() { 4312 roleSetOfKPlusOneThIteration.Insert(grantedId) 4313 } 4314 continue 4315 } 4316 grantedIds = &btree.Set[int64]{} 4317 cacheOfMoRoleGrant.Set(roleA, grantedIds) 4318 sqlForInheritedRoleIdOfRoleId := getSqlForInheritedRoleIdOfRoleId(roleA) 4319 bh.ClearExecResultSet() 4320 err = bh.Exec(ctx, sqlForInheritedRoleIdOfRoleId) 4321 if err != nil { 4322 err = moerr.NewInternalError(ctx, "get inherited role id of the role id. error:%v", err) 4323 goto handleFailed 4324 } 4325 4326 erArray, err = getResultSet(ctx, bh) 4327 if err != nil { 4328 goto handleFailed 4329 } 4330 4331 if execResultArrayHasData(erArray) { 4332 for i := uint64(0); i < erArray[0].GetRowCount(); i++ { 4333 roleB, err = erArray[0].GetInt64(ctx, i, 0) 4334 if err != nil { 4335 goto handleFailed 4336 } 4337 4338 if !roleSetOfVisited.Contains(roleB) { 4339 roleSetOfVisited.Insert(roleB) 4340 roleSetOfKPlusOneThIteration.Insert(roleB) 4341 grantedIds.Insert(roleB) 4342 } 4343 } 4344 } 4345 } 4346 4347 //no more roleB, it is done 4348 if roleSetOfKPlusOneThIteration.Len() == 0 { 4349 ret = false 4350 goto handleSuccess 4351 } 4352 4353 //Call the algorithm 2. 4354 //If the result of the algorithm 2 is true, Then return true; 4355 yes, err = determineRoleSetHasPrivilegeSet(ctx, bh, ses, roleSetOfKPlusOneThIteration, priv) 4356 if err != nil { 4357 goto handleFailed 4358 } 4359 4360 if yes { 4361 ret = true 4362 goto handleSuccess 4363 } 4364 roleSetOfKthIteration, roleSetOfKPlusOneThIteration = roleSetOfKPlusOneThIteration, roleSetOfKthIteration 4365 } 4366 4367 handleSuccess: 4368 err = bh.Exec(ctx, "commit;") 4369 if err != nil { 4370 goto handleFailed 4371 } 4372 4373 return ret, err 4374 4375 handleFailed: 4376 //ROLLBACK the transaction 4377 rbErr := bh.Exec(ctx, "rollback;") 4378 if rbErr != nil { 4379 return false, rbErr 4380 } 4381 return false, err 4382 } 4383 4384 const ( 4385 goOn int = iota 4386 successDone //ri has indirect relation with the Uc 4387 ) 4388 4389 // loadAllSecondaryRoles loads all secondary roles 4390 func loadAllSecondaryRoles(ctx context.Context, bh BackgroundExec, account *TenantInfo, roleSetOfCurrentUser *btree.Set[int64]) error { 4391 var err error 4392 var sql string 4393 4394 var erArray []ExecResult 4395 var roleId int64 4396 4397 if account.GetUseSecondaryRole() { 4398 sql = getSqlForRoleIdOfUserId(int(account.GetUserID())) 4399 bh.ClearExecResultSet() 4400 err = bh.Exec(ctx, sql) 4401 if err != nil { 4402 return err 4403 } 4404 4405 erArray, err = getResultSet(ctx, bh) 4406 if err != nil { 4407 return err 4408 } 4409 4410 if execResultArrayHasData(erArray) { 4411 for i := uint64(0); i < erArray[0].GetRowCount(); i++ { 4412 roleId, err = erArray[0].GetInt64(ctx, i, 0) 4413 if err != nil { 4414 return err 4415 } 4416 roleSetOfCurrentUser.Insert(roleId) 4417 } 4418 } 4419 } 4420 return err 4421 } 4422 4423 // determineUserCanGrantRolesToOthersInternal decides if the user can grant roles to other users or roles 4424 // the same as the grant/revoke privilege, role with inputted transaction and BackgroundExec 4425 func determineUserCanGrantRolesToOthersInternal(ctx context.Context, bh BackgroundExec, ses *Session, fromRoles []*tree.Role) (bool, error) { 4426 //step1: normalize the names of roles and users 4427 var err error 4428 err = normalizeNamesOfRoles(ctx, fromRoles) 4429 if err != nil { 4430 return false, err 4431 } 4432 4433 //step2: decide the current user 4434 account := ses.GetTenantInfo() 4435 4436 //step3: check the link: roleX -> roleA -> .... -> roleZ -> the current user. Every link has the with_grant_option. 4437 var vr *verifiedRole 4438 var ret = true 4439 var granted bool 4440 //the temporal set of roles during the execution 4441 var tempRoleSet *btree.Set[int64] 4442 var sql string 4443 //the set of roles the (k+1) th iteration during the execution 4444 roleSetOfKPlusOneThIteration := &btree.Set[int64]{} 4445 //the set of roles the k th iteration during the execution 4446 roleSetOfKthIteration := &btree.Set[int64]{} 4447 //the set of roles of the current user that executes this statement or function 4448 roleSetOfCurrentUser := &btree.Set[int64]{} 4449 //the set of roles visited by traversal algorithm 4450 roleSetOfVisited := &btree.Set[int64]{} 4451 verifiedFromRoles := make([]*verifiedRole, len(fromRoles)) 4452 4453 //step 1 : add the primary role 4454 roleSetOfCurrentUser.Insert(int64(account.GetDefaultRoleID())) 4455 4456 for i, role := range fromRoles { 4457 sql = getSqlForRoleIdOfRole(role.UserName) 4458 vr, err = verifyRoleFunc(ctx, bh, sql, role.UserName, roleType) 4459 if err != nil { 4460 goto handleFailed 4461 } 4462 if vr == nil { 4463 err = moerr.NewInternalError(ctx, "there is no role %s", role.UserName) 4464 goto handleFailed 4465 } 4466 verifiedFromRoles[i] = vr 4467 } 4468 4469 //step 2: The Set R2 {the roleid granted to the userid} 4470 //If the user uses the all secondary roles, the secondary roles needed to be loaded 4471 err = loadAllSecondaryRoles(ctx, bh, account, roleSetOfCurrentUser) 4472 if err != nil { 4473 goto handleFailed 4474 } 4475 4476 for _, role := range verifiedFromRoles { 4477 //if it is the role in use, do the check 4478 if roleSetOfCurrentUser.Contains(role.id) { 4479 //check the direct relation between role and user 4480 granted, err = isRoleGrantedToUserWGO(ctx, bh, role.id, int64(account.GetUserID())) 4481 if err != nil { 4482 goto handleFailed 4483 } 4484 if granted { 4485 continue 4486 } 4487 } 4488 4489 roleSetOfKthIteration.Clear() 4490 roleSetOfVisited.Clear() 4491 roleSetOfKthIteration.Insert(role.id) 4492 4493 riResult := goOn 4494 //It is kind of level traversal 4495 for roleSetOfKthIteration.Len() != 0 && riResult == goOn { 4496 roleSetOfKPlusOneThIteration.Clear() 4497 for _, ri := range roleSetOfKthIteration.Keys() { 4498 tempRoleSet, err = getRoleSetThatRoleGrantedToWGO(ctx, bh, ri, roleSetOfVisited, roleSetOfKPlusOneThIteration) 4499 if err != nil { 4500 goto handleFailed 4501 } 4502 4503 if setIsIntersected(tempRoleSet, roleSetOfCurrentUser) { 4504 riResult = successDone 4505 break 4506 } 4507 } 4508 4509 //swap Rk,R(k+1) 4510 roleSetOfKthIteration, roleSetOfKPlusOneThIteration = roleSetOfKPlusOneThIteration, roleSetOfKthIteration 4511 } 4512 4513 if riResult != successDone { 4514 //fail 4515 ret = false 4516 break 4517 } 4518 } 4519 return ret, err 4520 4521 handleFailed: 4522 return false, err 4523 } 4524 4525 // determineUserCanGrantRoleToOtherUsers decides if the user can grant roles to other users or roles 4526 // the same as the grant/revoke privilege, role. 4527 func determineUserCanGrantRolesToOthers(ctx context.Context, ses *Session, fromRoles []*tree.Role) (bool, error) { 4528 //step1: normalize the names of roles and users 4529 var err error 4530 var ret bool 4531 err = normalizeNamesOfRoles(ctx, fromRoles) 4532 if err != nil { 4533 return false, err 4534 } 4535 4536 //step2: decide the current user 4537 bh := ses.GetBackgroundExec(ctx) 4538 defer bh.Close() 4539 4540 //put it into the single transaction 4541 err = bh.Exec(ctx, "begin;") 4542 if err != nil { 4543 goto handleFailed 4544 } 4545 4546 ret, err = determineUserCanGrantRolesToOthersInternal(ctx, bh, ses, fromRoles) 4547 if err != nil { 4548 goto handleFailed 4549 } 4550 4551 err = bh.Exec(ctx, "commit;") 4552 if err != nil { 4553 goto handleFailed 4554 } 4555 4556 return ret, err 4557 4558 handleFailed: 4559 //ROLLBACK the transaction 4560 rbErr := bh.Exec(ctx, "rollback;") 4561 if rbErr != nil { 4562 return false, rbErr 4563 } 4564 return false, err 4565 } 4566 4567 // isRoleGrantedToUserWGO verifies the role has been granted to the user with with_grant_option = true. 4568 // Algorithm 1 4569 func isRoleGrantedToUserWGO(ctx context.Context, bh BackgroundExec, roleId, UserId int64) (bool, error) { 4570 var err error 4571 var erArray []ExecResult 4572 sql := getSqlForCheckUserGrantWGO(roleId, UserId) 4573 bh.ClearExecResultSet() 4574 err = bh.Exec(ctx, sql) 4575 if err != nil { 4576 return false, err 4577 } 4578 4579 erArray, err = getResultSet(ctx, bh) 4580 if err != nil { 4581 return false, err 4582 } 4583 4584 if execResultArrayHasData(erArray) { 4585 return true, nil 4586 } 4587 4588 return false, nil 4589 } 4590 4591 // getRoleSetThatRoleGrantedToWGO returns all the roles that the role has been granted to with with_grant_option = true. 4592 // Algorithm 2 4593 func getRoleSetThatRoleGrantedToWGO(ctx context.Context, bh BackgroundExec, roleId int64, RVisited, RkPlusOne *btree.Set[int64]) (*btree.Set[int64], error) { 4594 var err error 4595 var erArray []ExecResult 4596 var id int64 4597 rset := &btree.Set[int64]{} 4598 sql := getSqlForCheckRoleGrantWGO(roleId) 4599 bh.ClearExecResultSet() 4600 err = bh.Exec(ctx, sql) 4601 if err != nil { 4602 return nil, err 4603 } 4604 4605 erArray, err = getResultSet(ctx, bh) 4606 if err != nil { 4607 return nil, err 4608 } 4609 4610 if execResultArrayHasData(erArray) { 4611 for i := uint64(0); i < erArray[0].GetRowCount(); i++ { 4612 id, err = erArray[0].GetInt64(ctx, i, 0) 4613 if err != nil { 4614 return nil, err 4615 } 4616 if !RVisited.Contains(id) { 4617 RVisited.Insert(id) 4618 RkPlusOne.Insert(id) 4619 rset.Insert(id) 4620 } 4621 } 4622 } 4623 4624 return rset, err 4625 } 4626 4627 // authenticateUserCanExecuteStatementWithObjectTypeAccountAndDatabase decides the user has the privilege of executing the statement with object type account 4628 func authenticateUserCanExecuteStatementWithObjectTypeAccountAndDatabase(ctx context.Context, ses *Session, stmt tree.Statement) (bool, error) { 4629 var err error 4630 var ok, yes bool 4631 priv := ses.GetPrivilege() 4632 if priv.objectType() != objectTypeAccount && priv.objectType() != objectTypeDatabase { //do nothing 4633 return true, nil 4634 } 4635 ok, err = determineUserHasPrivilegeSet(ctx, ses, priv, stmt) 4636 if err != nil { 4637 return false, err 4638 } 4639 4640 //double check privilege of drop table 4641 if !ok && ses.GetFromRealUser() && ses.GetTenantInfo() != nil && ses.GetTenantInfo().IsSysTenant() { 4642 switch dropTable := stmt.(type) { 4643 case *tree.DropTable: 4644 dbName := string(dropTable.Names[0].SchemaName) 4645 if len(dbName) == 0 { 4646 dbName = ses.GetDatabaseName() 4647 } 4648 return isClusterTable(dbName, string(dropTable.Names[0].ObjectName)), nil 4649 } 4650 } 4651 4652 //for GrantRole statement, check with_grant_option 4653 if !ok && priv.kind == privilegeKindInherit { 4654 grant := stmt.(*tree.Grant) 4655 grantRole := grant.GrantRole 4656 yes, err = determineUserCanGrantRolesToOthers(ctx, ses, grantRole.Roles) 4657 if err != nil { 4658 return false, err 4659 } 4660 if yes { 4661 return true, nil 4662 } 4663 } 4664 //for Create User statement with default role. 4665 //TODO: 4666 4667 return ok, nil 4668 } 4669 4670 // authenticateUserCanExecuteStatementWithObjectTypeDatabaseAndTable 4671 // decides the user has the privilege of executing the statement 4672 // with object type table from the plan 4673 func authenticateUserCanExecuteStatementWithObjectTypeDatabaseAndTable(ctx context.Context, 4674 ses *Session, 4675 stmt tree.Statement, 4676 p *plan2.Plan) (bool, error) { 4677 priv := determinePrivilegeSetOfStatement(stmt) 4678 if priv.objectType() == objectTypeTable { 4679 arr := extractPrivilegeTipsFromPlan(p) 4680 if len(arr) == 0 { 4681 return true, nil 4682 } 4683 convertPrivilegeTipsToPrivilege(priv, arr) 4684 ok, err := determineUserHasPrivilegeSet(ctx, ses, priv, stmt) 4685 if err != nil { 4686 return false, err 4687 } 4688 return ok, nil 4689 } 4690 return true, nil 4691 } 4692 4693 // formSqlFromGrantPrivilege makes the sql for querying the database. 4694 func formSqlFromGrantPrivilege(ctx context.Context, ses *Session, gp *tree.GrantPrivilege, priv *tree.Privilege) (string, error) { 4695 tenant := ses.GetTenantInfo() 4696 sql := "" 4697 var privType PrivilegeType 4698 var err error 4699 privType, err = convertAstPrivilegeTypeToPrivilegeType(ctx, priv.Type, gp.ObjType) 4700 if err != nil { 4701 return "", err 4702 } 4703 switch gp.ObjType { 4704 case tree.OBJECT_TYPE_TABLE: 4705 switch gp.Level.Level { 4706 case tree.PRIVILEGE_LEVEL_TYPE_STAR: 4707 sql = getSqlForCheckWithGrantOptionForTableDatabaseStar(int64(tenant.GetDefaultRoleID()), privType, ses.GetDatabaseName()) 4708 case tree.PRIVILEGE_LEVEL_TYPE_STAR_STAR: 4709 sql = getSqlForCheckWithGrantOptionForTableStarStar(int64(tenant.GetDefaultRoleID()), privType) 4710 case tree.PRIVILEGE_LEVEL_TYPE_DATABASE_STAR: 4711 sql = getSqlForCheckWithGrantOptionForTableDatabaseStar(int64(tenant.GetDefaultRoleID()), privType, gp.Level.DbName) 4712 case tree.PRIVILEGE_LEVEL_TYPE_DATABASE_TABLE: 4713 sql = getSqlForCheckWithGrantOptionForTableDatabaseTable(int64(tenant.GetDefaultRoleID()), privType, gp.Level.DbName, gp.Level.TabName) 4714 case tree.PRIVILEGE_LEVEL_TYPE_TABLE: 4715 sql = getSqlForCheckWithGrantOptionForTableDatabaseTable(int64(tenant.GetDefaultRoleID()), privType, ses.GetDatabaseName(), gp.Level.TabName) 4716 default: 4717 return "", moerr.NewInternalError(ctx, "in object type %v privilege level type %v is unsupported", gp.ObjType, gp.Level.Level) 4718 } 4719 case tree.OBJECT_TYPE_DATABASE: 4720 switch gp.Level.Level { 4721 case tree.PRIVILEGE_LEVEL_TYPE_STAR: 4722 sql = getSqlForCheckWithGrantOptionForDatabaseStar(int64(tenant.GetDefaultRoleID()), privType) 4723 case tree.PRIVILEGE_LEVEL_TYPE_STAR_STAR: 4724 sql = getSqlForCheckWithGrantOptionForDatabaseStarStar(int64(tenant.GetDefaultRoleID()), privType) 4725 case tree.PRIVILEGE_LEVEL_TYPE_TABLE: 4726 //in the syntax, we can not distinguish the table name from the database name. 4727 sql = getSqlForCheckWithGrantOptionForDatabaseDB(int64(tenant.GetDefaultRoleID()), privType, gp.Level.TabName) 4728 case tree.PRIVILEGE_LEVEL_TYPE_DATABASE: 4729 sql = getSqlForCheckWithGrantOptionForDatabaseDB(int64(tenant.GetDefaultRoleID()), privType, gp.Level.DbName) 4730 default: 4731 return "", moerr.NewInternalError(ctx, "in object type %v privilege level type %v is unsupported", gp.ObjType, gp.Level.Level) 4732 } 4733 case tree.OBJECT_TYPE_ACCOUNT: 4734 switch gp.Level.Level { 4735 case tree.PRIVILEGE_LEVEL_TYPE_STAR: 4736 sql = getSqlForCheckWithGrantOptionForAccountStar(int64(tenant.GetDefaultRoleID()), privType) 4737 default: 4738 return "", moerr.NewInternalError(ctx, "in object type %v privilege level type %v is unsupported", gp.ObjType, gp.Level.Level) 4739 } 4740 default: 4741 return "", moerr.NewInternalError(ctx, "object type %v is unsupported", gp.ObjType) 4742 } 4743 return sql, nil 4744 } 4745 4746 // getRoleSetThatPrivilegeGrantedToWGO gets all roles that the privilege granted to with with_grant_option = true 4747 // The algorithm 3 4748 func getRoleSetThatPrivilegeGrantedToWGO(ctx context.Context, bh BackgroundExec, privType PrivilegeType) (*btree.Set[int64], error) { 4749 var err error 4750 var erArray []ExecResult 4751 var id int64 4752 rset := &btree.Set[int64]{} 4753 sql := getSqlForCheckRoleHasPrivilegeWGO(int64(privType)) 4754 bh.ClearExecResultSet() 4755 err = bh.Exec(ctx, sql) 4756 if err != nil { 4757 return nil, err 4758 } 4759 4760 erArray, err = getResultSet(ctx, bh) 4761 if err != nil { 4762 return nil, err 4763 } 4764 4765 if execResultArrayHasData(erArray) { 4766 for i := uint64(0); i < erArray[0].GetRowCount(); i++ { 4767 id, err = erArray[0].GetInt64(ctx, i, 0) 4768 if err != nil { 4769 return nil, err 4770 } 4771 rset.Insert(id) 4772 } 4773 } 4774 4775 return rset, err 4776 } 4777 4778 // setIsIntersected decides the A is intersecting the B. 4779 func setIsIntersected(A, B *btree.Set[int64]) bool { 4780 if A.Len() > B.Len() { 4781 A, B = B, A 4782 } 4783 iter := A.Iter() 4784 for x := iter.First(); x; x = iter.Next() { 4785 if B.Contains(iter.Key()) { 4786 return true 4787 } 4788 } 4789 return false 4790 } 4791 4792 // determineUserCanGrantPrivilegesToOthers decides the privileges can be granted to others. 4793 func determineUserCanGrantPrivilegesToOthers(ctx context.Context, ses *Session, gp *tree.GrantPrivilege) (bool, error) { 4794 //step1: normalize the names of roles and users 4795 var err error 4796 //step2: decide the current user 4797 account := ses.GetTenantInfo() 4798 bh := ses.GetBackgroundExec(ctx) 4799 defer bh.Close() 4800 4801 //step3: check the link: roleX -> roleA -> .... -> roleZ -> the current user. Every link has the with_grant_option. 4802 var ret = true 4803 var privType PrivilegeType 4804 //the temporal set of roles during the execution 4805 var tempRoleSet *btree.Set[int64] 4806 //the set of roles that the privilege granted to with WGO=true 4807 var roleSetOfPrivilegeGrantedToWGO *btree.Set[int64] 4808 //the set of roles the (k+1) th iteration during the execution 4809 roleSetOfKPlusOneThIteration := &btree.Set[int64]{} 4810 //the set of roles the k th iteration during the execution 4811 roleSetOfKthIteration := &btree.Set[int64]{} 4812 //the set of roles visited by traversal algorithm 4813 roleSetOfVisited := &btree.Set[int64]{} 4814 //the set of roles of the current user that executes this statement or function 4815 roleSetOfCurrentUser := &btree.Set[int64]{} 4816 4817 roleSetOfCurrentUser.Insert(int64(account.GetDefaultRoleID())) 4818 4819 //put it into the single transaction 4820 err = bh.Exec(ctx, "begin;") 4821 if err != nil { 4822 goto handleFailed 4823 } 4824 4825 //step 2: The Set R2 {the roleid granted to the userid} 4826 //If the user uses the all secondary roles, the secondary roles needed to be loaded 4827 err = loadAllSecondaryRoles(ctx, bh, account, roleSetOfCurrentUser) 4828 if err != nil { 4829 goto handleFailed 4830 } 4831 4832 for _, priv := range gp.Privileges { 4833 privType, err = convertAstPrivilegeTypeToPrivilegeType(ctx, priv.Type, gp.ObjType) 4834 if err != nil { 4835 goto handleFailed 4836 } 4837 4838 //call the algorithm 3. 4839 roleSetOfPrivilegeGrantedToWGO, err = getRoleSetThatPrivilegeGrantedToWGO(ctx, bh, privType) 4840 if err != nil { 4841 goto handleFailed 4842 } 4843 4844 if setIsIntersected(roleSetOfPrivilegeGrantedToWGO, roleSetOfCurrentUser) { 4845 continue 4846 } 4847 4848 riResult := goOn 4849 for _, rx := range roleSetOfPrivilegeGrantedToWGO.Keys() { 4850 roleSetOfKthIteration.Clear() 4851 roleSetOfVisited.Clear() 4852 roleSetOfKthIteration.Insert(rx) 4853 4854 //It is kind of level traversal 4855 for roleSetOfKthIteration.Len() != 0 && riResult == goOn { 4856 roleSetOfKPlusOneThIteration.Clear() 4857 for _, ri := range roleSetOfKthIteration.Keys() { 4858 tempRoleSet, err = getRoleSetThatRoleGrantedToWGO(ctx, bh, ri, roleSetOfVisited, roleSetOfKPlusOneThIteration) 4859 if err != nil { 4860 goto handleFailed 4861 } 4862 4863 if setIsIntersected(tempRoleSet, roleSetOfCurrentUser) { 4864 riResult = successDone 4865 break 4866 } 4867 } 4868 4869 //swap Rk,R(k+1) 4870 roleSetOfKthIteration, roleSetOfKPlusOneThIteration = roleSetOfKPlusOneThIteration, roleSetOfKthIteration 4871 } 4872 4873 if riResult == successDone { 4874 break 4875 } 4876 } 4877 if riResult != successDone { 4878 ret = false 4879 break 4880 } 4881 } 4882 4883 err = bh.Exec(ctx, "commit;") 4884 if err != nil { 4885 goto handleFailed 4886 } 4887 4888 return ret, err 4889 4890 handleFailed: 4891 //ROLLBACK the transaction 4892 rbErr := bh.Exec(ctx, "rollback;") 4893 if rbErr != nil { 4894 return false, rbErr 4895 } 4896 return false, err 4897 } 4898 4899 func convertAstPrivilegeTypeToPrivilegeType(ctx context.Context, priv tree.PrivilegeType, ot tree.ObjectType) (PrivilegeType, error) { 4900 var privType PrivilegeType 4901 switch priv { 4902 case tree.PRIVILEGE_TYPE_STATIC_CREATE_ACCOUNT: 4903 privType = PrivilegeTypeCreateAccount 4904 case tree.PRIVILEGE_TYPE_STATIC_DROP_ACCOUNT: 4905 privType = PrivilegeTypeDropAccount 4906 case tree.PRIVILEGE_TYPE_STATIC_ALTER_ACCOUNT: 4907 privType = PrivilegeTypeAlterAccount 4908 case tree.PRIVILEGE_TYPE_STATIC_CREATE_USER: 4909 privType = PrivilegeTypeCreateUser 4910 case tree.PRIVILEGE_TYPE_STATIC_DROP_USER: 4911 privType = PrivilegeTypeDropUser 4912 case tree.PRIVILEGE_TYPE_STATIC_ALTER_USER: 4913 privType = PrivilegeTypeAlterUser 4914 case tree.PRIVILEGE_TYPE_STATIC_CREATE_ROLE: 4915 privType = PrivilegeTypeCreateRole 4916 case tree.PRIVILEGE_TYPE_STATIC_DROP_ROLE: 4917 privType = PrivilegeTypeDropRole 4918 case tree.PRIVILEGE_TYPE_STATIC_ALTER_ROLE: 4919 privType = PrivilegeTypeAlterRole 4920 case tree.PRIVILEGE_TYPE_STATIC_CREATE_DATABASE: 4921 privType = PrivilegeTypeCreateDatabase 4922 case tree.PRIVILEGE_TYPE_STATIC_DROP_DATABASE: 4923 privType = PrivilegeTypeDropDatabase 4924 case tree.PRIVILEGE_TYPE_STATIC_SHOW_DATABASES: 4925 privType = PrivilegeTypeShowDatabases 4926 case tree.PRIVILEGE_TYPE_STATIC_CONNECT: 4927 privType = PrivilegeTypeConnect 4928 case tree.PRIVILEGE_TYPE_STATIC_MANAGE_GRANTS: 4929 privType = PrivilegeTypeManageGrants 4930 case tree.PRIVILEGE_TYPE_STATIC_ALL: 4931 switch ot { 4932 case tree.OBJECT_TYPE_ACCOUNT: 4933 privType = PrivilegeTypeAccountAll 4934 case tree.OBJECT_TYPE_DATABASE: 4935 privType = PrivilegeTypeDatabaseAll 4936 case tree.OBJECT_TYPE_TABLE: 4937 privType = PrivilegeTypeTableAll 4938 default: 4939 return 0, moerr.NewInternalError(ctx, `the object type "%s" do not support the privilege "%s"`, ot.String(), priv.ToString()) 4940 } 4941 case tree.PRIVILEGE_TYPE_STATIC_OWNERSHIP: 4942 switch ot { 4943 case tree.OBJECT_TYPE_DATABASE: 4944 privType = PrivilegeTypeDatabaseOwnership 4945 case tree.OBJECT_TYPE_TABLE: 4946 privType = PrivilegeTypeTableOwnership 4947 default: 4948 return 0, moerr.NewInternalError(ctx, `the object type "%s" do not support the privilege "%s"`, ot.String(), priv.ToString()) 4949 } 4950 case tree.PRIVILEGE_TYPE_STATIC_SHOW_TABLES: 4951 privType = PrivilegeTypeShowTables 4952 case tree.PRIVILEGE_TYPE_STATIC_CREATE_TABLE: 4953 privType = PrivilegeTypeCreateTable 4954 case tree.PRIVILEGE_TYPE_STATIC_DROP_TABLE: 4955 privType = PrivilegeTypeDropTable 4956 case tree.PRIVILEGE_TYPE_STATIC_CREATE_VIEW: 4957 privType = PrivilegeTypeCreateView 4958 case tree.PRIVILEGE_TYPE_STATIC_DROP_VIEW: 4959 privType = PrivilegeTypeDropView 4960 case tree.PRIVILEGE_TYPE_STATIC_ALTER_VIEW: 4961 privType = PrivilegeTypeAlterView 4962 case tree.PRIVILEGE_TYPE_STATIC_ALTER_TABLE: 4963 privType = PrivilegeTypeAlterTable 4964 case tree.PRIVILEGE_TYPE_STATIC_SELECT: 4965 privType = PrivilegeTypeSelect 4966 case tree.PRIVILEGE_TYPE_STATIC_INSERT: 4967 privType = PrivilegeTypeInsert 4968 case tree.PRIVILEGE_TYPE_STATIC_UPDATE: 4969 privType = PrivilegeTypeUpdate 4970 case tree.PRIVILEGE_TYPE_STATIC_DELETE: 4971 privType = PrivilegeTypeDelete 4972 case tree.PRIVILEGE_TYPE_STATIC_INDEX: 4973 privType = PrivilegeTypeIndex 4974 case tree.PRIVILEGE_TYPE_STATIC_EXECUTE: 4975 privType = PrivilegeTypeExecute 4976 case tree.PRIVILEGE_TYPE_STATIC_TRUNCATE: 4977 privType = PrivilegeTypeTruncate 4978 case tree.PRIVILEGE_TYPE_STATIC_REFERENCE: 4979 privType = PrivilegeTypeReference 4980 case tree.PRIVILEGE_TYPE_STATIC_VALUES: 4981 privType = PrivilegeTypeValues 4982 default: 4983 return 0, moerr.NewInternalError(ctx, "unsupported privilege type %s", priv.ToString()) 4984 } 4985 return privType, nil 4986 } 4987 4988 // authenticateUserCanExecuteStatementWithObjectTypeNone decides the user has the privilege of executing the statement with object type none 4989 func authenticateUserCanExecuteStatementWithObjectTypeNone(ctx context.Context, ses *Session, stmt tree.Statement) (bool, error) { 4990 priv := ses.GetPrivilege() 4991 if priv.objectType() != objectTypeNone { //do nothing 4992 return true, nil 4993 } 4994 tenant := ses.GetTenantInfo() 4995 4996 if priv.privilegeKind() == privilegeKindNone { // do nothing 4997 return true, nil 4998 } else if priv.privilegeKind() == privilegeKindSpecial { //GrantPrivilege, RevokePrivilege 4999 5000 checkGrantPrivilege := func(g *tree.GrantPrivilege) (bool, error) { 5001 //in the version 0.6, only the moAdmin and accountAdmin can grant the privilege. 5002 if tenant.IsAdminRole() { 5003 return true, nil 5004 } 5005 return determineUserCanGrantPrivilegesToOthers(ctx, ses, g) 5006 } 5007 5008 checkRevokePrivilege := func() (bool, error) { 5009 //in the version 0.6, only the moAdmin and accountAdmin can revoke the privilege. 5010 return tenant.IsAdminRole(), nil 5011 } 5012 5013 checkShowAccountsPrivilege := func() (bool, error) { 5014 //only the moAdmin and accountAdmin can execute the show accounts. 5015 return tenant.IsAdminRole(), nil 5016 } 5017 5018 switch gp := stmt.(type) { 5019 case *tree.Grant: 5020 if gp.Typ == tree.GrantTypePrivilege { 5021 yes, err := checkGrantPrivilege(&gp.GrantPrivilege) 5022 if err != nil { 5023 return yes, err 5024 } 5025 if yes { 5026 return yes, nil 5027 } 5028 } 5029 case *tree.Revoke: 5030 if gp.Typ == tree.RevokeTypePrivilege { 5031 return checkRevokePrivilege() 5032 } 5033 case *tree.GrantPrivilege: 5034 yes, err := checkGrantPrivilege(gp) 5035 if err != nil { 5036 return yes, err 5037 } 5038 if yes { 5039 return yes, nil 5040 } 5041 case *tree.RevokePrivilege: 5042 return checkRevokePrivilege() 5043 case *tree.ShowAccounts: 5044 return checkShowAccountsPrivilege() 5045 } 5046 } 5047 5048 return false, nil 5049 } 5050 5051 // checkSysExistsOrNot checks the SYS tenant exists or not. 5052 func checkSysExistsOrNot(ctx context.Context, bh BackgroundExec, pu *config.ParameterUnit) (bool, error) { 5053 var erArray []ExecResult 5054 var err error 5055 var tableNames []string 5056 var tableName string 5057 5058 dbSql := "show databases;" 5059 bh.ClearExecResultSet() 5060 err = bh.Exec(ctx, dbSql) 5061 if err != nil { 5062 return false, err 5063 } 5064 5065 erArray, err = getResultSet(ctx, bh) 5066 if err != nil { 5067 return false, err 5068 } 5069 if len(erArray) != 1 { 5070 return false, moerr.NewInternalError(ctx, "it must have result set") 5071 } 5072 5073 for i := uint64(0); i < erArray[0].GetRowCount(); i++ { 5074 _, err = erArray[0].GetString(ctx, i, 0) 5075 if err != nil { 5076 return false, err 5077 } 5078 } 5079 5080 sql := "show tables from mo_catalog;" 5081 bh.ClearExecResultSet() 5082 err = bh.Exec(ctx, sql) 5083 if err != nil { 5084 return false, err 5085 } 5086 5087 erArray, err = getResultSet(ctx, bh) 5088 if err != nil { 5089 return false, err 5090 } 5091 if len(erArray) != 1 { 5092 return false, moerr.NewInternalError(ctx, "it must have result set") 5093 } 5094 5095 for i := uint64(0); i < erArray[0].GetRowCount(); i++ { 5096 tableName, err = erArray[0].GetString(ctx, i, 0) 5097 if err != nil { 5098 return false, err 5099 } 5100 tableNames = append(tableNames, tableName) 5101 } 5102 5103 //if there is at least one catalog table, it denotes the sys tenant exists. 5104 for _, name := range tableNames { 5105 if _, ok := sysWantedTables[name]; ok { 5106 return true, nil 5107 } 5108 } 5109 5110 return false, nil 5111 } 5112 5113 // InitSysTenant initializes the tenant SYS before any tenants and accepting any requests 5114 // during the system is booting. 5115 func InitSysTenant(ctx context.Context, autoincrcaches defines.AutoIncrCaches) error { 5116 var err error 5117 var exists bool 5118 pu := config.GetParameterUnit(ctx) 5119 5120 tenant := &TenantInfo{ 5121 Tenant: sysAccountName, 5122 User: rootName, 5123 DefaultRole: moAdminRoleName, 5124 TenantID: sysAccountID, 5125 UserID: rootID, 5126 DefaultRoleID: moAdminRoleID, 5127 } 5128 5129 ctx = context.WithValue(ctx, defines.TenantIDKey{}, uint32(sysAccountID)) 5130 ctx = context.WithValue(ctx, defines.UserIDKey{}, uint32(rootID)) 5131 ctx = context.WithValue(ctx, defines.RoleIDKey{}, uint32(moAdminRoleID)) 5132 5133 mp, err := mpool.NewMPool("init_system_tenant", 0, mpool.NoFixed) 5134 if err != nil { 5135 return err 5136 } 5137 defer mpool.DeleteMPool(mp) 5138 bh := NewBackgroundHandler(ctx, mp, pu, autoincrcaches) 5139 defer bh.Close() 5140 5141 //USE the mo_catalog 5142 err = bh.Exec(ctx, "use mo_catalog;") 5143 if err != nil { 5144 return err 5145 } 5146 5147 err = bh.Exec(ctx, createAutoTableSql) 5148 if err != nil { 5149 return err 5150 } 5151 5152 err = bh.Exec(ctx, "begin;") 5153 if err != nil { 5154 goto handleFailed 5155 } 5156 5157 exists, err = checkSysExistsOrNot(ctx, bh, pu) 5158 if err != nil { 5159 goto handleFailed 5160 } 5161 5162 if !exists { 5163 err = createTablesInMoCatalog(ctx, bh, tenant, pu) 5164 if err != nil { 5165 goto handleFailed 5166 } 5167 5168 err = createTablesInInformationSchema(ctx, bh, tenant, pu) 5169 if err != nil { 5170 goto handleFailed 5171 } 5172 } 5173 5174 err = bh.Exec(ctx, "commit;") 5175 if err != nil { 5176 goto handleFailed 5177 } 5178 return err 5179 handleFailed: 5180 //ROLLBACK the transaction 5181 rbErr := bh.Exec(ctx, "rollback;") 5182 if rbErr != nil { 5183 return rbErr 5184 } 5185 return err 5186 } 5187 5188 // createTablesInMoCatalog creates catalog tables in the database mo_catalog. 5189 func createTablesInMoCatalog(ctx context.Context, bh BackgroundExec, tenant *TenantInfo, pu *config.ParameterUnit) error { 5190 var err error 5191 var initMoAccount string 5192 var initDataSqls []string 5193 if !tenant.IsSysTenant() { 5194 return moerr.NewInternalError(ctx, "only sys tenant can execute the function") 5195 } 5196 5197 addSqlIntoSet := func(sql string) { 5198 initDataSqls = append(initDataSqls, sql) 5199 } 5200 5201 //create tables for the tenant 5202 for _, sql := range createSqls { 5203 addSqlIntoSet(sql) 5204 } 5205 5206 //initialize the default data of tables for the tenant 5207 //step 1: add new tenant entry to the mo_account 5208 initMoAccount = fmt.Sprintf(initMoAccountFormat, sysAccountID, sysAccountName, sysAccountStatus, types.CurrentTimestamp().String2(time.UTC, 0), sysAccountComments) 5209 addSqlIntoSet(initMoAccount) 5210 5211 //step 2:add new role entries to the mo_role 5212 5213 initMoRole1 := fmt.Sprintf(initMoRoleFormat, moAdminRoleID, moAdminRoleName, rootID, moAdminRoleID, types.CurrentTimestamp().String2(time.UTC, 0), "") 5214 initMoRole2 := fmt.Sprintf(initMoRoleFormat, publicRoleID, publicRoleName, rootID, moAdminRoleID, types.CurrentTimestamp().String2(time.UTC, 0), "") 5215 addSqlIntoSet(initMoRole1) 5216 addSqlIntoSet(initMoRole2) 5217 5218 //step 3:add new user entry to the mo_user 5219 5220 defaultPassword := rootPassword 5221 if d := os.Getenv(defaultPasswordEnv); d != "" { 5222 defaultPassword = d 5223 } 5224 5225 initMoUser1 := fmt.Sprintf(initMoUserFormat, rootID, rootHost, rootName, defaultPassword, rootStatus, types.CurrentTimestamp().String2(time.UTC, 0), rootExpiredTime, rootLoginType, rootCreatorID, rootOwnerRoleID, rootDefaultRoleID) 5226 initMoUser2 := fmt.Sprintf(initMoUserFormat, dumpID, dumpHost, dumpName, defaultPassword, dumpStatus, types.CurrentTimestamp().String2(time.UTC, 0), dumpExpiredTime, dumpLoginType, dumpCreatorID, dumpOwnerRoleID, dumpDefaultRoleID) 5227 addSqlIntoSet(initMoUser1) 5228 addSqlIntoSet(initMoUser2) 5229 5230 //step4: add new entries to the mo_role_privs 5231 //moadmin role 5232 for _, t := range entriesOfMoAdminForMoRolePrivsFor { 5233 entry := privilegeEntriesMap[t] 5234 initMoRolePriv := fmt.Sprintf(initMoRolePrivFormat, 5235 moAdminRoleID, moAdminRoleName, 5236 entry.objType, entry.objId, 5237 entry.privilegeId, entry.privilegeId.String(), entry.privilegeLevel, 5238 rootID, types.CurrentTimestamp().String2(time.UTC, 0), 5239 entry.withGrantOption) 5240 addSqlIntoSet(initMoRolePriv) 5241 } 5242 5243 //public role 5244 for _, t := range entriesOfPublicForMoRolePrivsFor { 5245 entry := privilegeEntriesMap[t] 5246 initMoRolePriv := fmt.Sprintf(initMoRolePrivFormat, 5247 publicRoleID, publicRoleName, 5248 entry.objType, entry.objId, 5249 entry.privilegeId, entry.privilegeId.String(), entry.privilegeLevel, 5250 rootID, types.CurrentTimestamp().String2(time.UTC, 0), 5251 entry.withGrantOption) 5252 addSqlIntoSet(initMoRolePriv) 5253 } 5254 5255 //step5: add new entries to the mo_user_grant 5256 5257 initMoUserGrant1 := fmt.Sprintf(initMoUserGrantFormat, moAdminRoleID, rootID, types.CurrentTimestamp().String2(time.UTC, 0), false) 5258 initMoUserGrant2 := fmt.Sprintf(initMoUserGrantFormat, publicRoleID, rootID, types.CurrentTimestamp().String2(time.UTC, 0), false) 5259 addSqlIntoSet(initMoUserGrant1) 5260 addSqlIntoSet(initMoUserGrant2) 5261 initMoUserGrant4 := fmt.Sprintf(initMoUserGrantFormat, moAdminRoleID, dumpID, types.CurrentTimestamp().String2(time.UTC, 0), false) 5262 initMoUserGrant5 := fmt.Sprintf(initMoUserGrantFormat, publicRoleID, dumpID, types.CurrentTimestamp().String2(time.UTC, 0), false) 5263 addSqlIntoSet(initMoUserGrant4) 5264 addSqlIntoSet(initMoUserGrant5) 5265 5266 //fill the mo_account, mo_role, mo_user, mo_role_privs, mo_user_grant 5267 for _, sql := range initDataSqls { 5268 err = bh.Exec(ctx, sql) 5269 if err != nil { 5270 goto handleFailed 5271 } 5272 } 5273 5274 handleFailed: 5275 return err 5276 } 5277 5278 // createTablesInInformationSchema creates the database information_schema and the views or tables. 5279 func createTablesInInformationSchema(ctx context.Context, bh BackgroundExec, tenant *TenantInfo, pu *config.ParameterUnit) error { 5280 err := bh.Exec(ctx, "create database if not exists information_schema;") 5281 if err != nil { 5282 return err 5283 } 5284 return err 5285 } 5286 5287 func checkTenantExistsOrNot(ctx context.Context, bh BackgroundExec, userName string) (bool, error) { 5288 var sqlForCheckTenant string 5289 var erArray []ExecResult 5290 var err error 5291 ctx, span := trace.Debug(ctx, "checkTenantExistsOrNot") 5292 defer span.End() 5293 sqlForCheckTenant = getSqlForCheckTenant(userName) 5294 bh.ClearExecResultSet() 5295 err = bh.Exec(ctx, sqlForCheckTenant) 5296 if err != nil { 5297 return false, err 5298 } 5299 5300 erArray, err = getResultSet(ctx, bh) 5301 if err != nil { 5302 return false, err 5303 } 5304 5305 if execResultArrayHasData(erArray) { 5306 return true, nil 5307 } 5308 return false, nil 5309 } 5310 5311 // InitGeneralTenant initializes the application level tenant 5312 func InitGeneralTenant(ctx context.Context, ses *Session, ca *tree.CreateAccount) error { 5313 var err error 5314 var exists bool 5315 var newTenant *TenantInfo 5316 var newTenantCtx context.Context 5317 var newUserId int64 5318 ctx, span := trace.Debug(ctx, "InitGeneralTenant") 5319 defer span.End() 5320 tenant := ses.GetTenantInfo() 5321 pu := config.GetParameterUnit(ctx) 5322 5323 if !(tenant.IsSysTenant() && tenant.IsMoAdminRole()) { 5324 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()) 5325 } 5326 5327 //normalize the name 5328 ca.Name, err = normalizeName(ctx, ca.Name) 5329 if err != nil { 5330 return err 5331 } 5332 5333 ca.AuthOption.AdminName, err = normalizeName(ctx, ca.AuthOption.AdminName) 5334 if err != nil { 5335 return err 5336 } 5337 ctx = context.WithValue(ctx, defines.TenantIDKey{}, uint32(tenant.GetTenantID())) 5338 ctx = context.WithValue(ctx, defines.UserIDKey{}, uint32(tenant.GetUserID())) 5339 ctx = context.WithValue(ctx, defines.RoleIDKey{}, uint32(tenant.GetDefaultRoleID())) 5340 5341 _, st := trace.Debug(ctx, "InitGeneralTenant.init_general_tenant") 5342 mp, err := mpool.NewMPool("init_general_tenant", 0, mpool.NoFixed) 5343 if err != nil { 5344 st.End() 5345 return err 5346 } 5347 st.End() 5348 defer mpool.DeleteMPool(mp) 5349 5350 bh := ses.GetBackgroundExec(ctx) 5351 defer bh.Close() 5352 5353 //USE the mo_catalog 5354 err = bh.Exec(ctx, "use mo_catalog;") 5355 if err != nil { 5356 return err 5357 } 5358 5359 err = bh.Exec(ctx, "begin;") 5360 if err != nil { 5361 goto handleFailed 5362 } 5363 5364 exists, err = checkTenantExistsOrNot(ctx, bh, ca.Name) 5365 if err != nil { 5366 goto handleFailed 5367 } 5368 5369 if exists { 5370 if !ca.IfNotExists { //do nothing 5371 err = moerr.NewInternalError(ctx, "the tenant %s exists", ca.Name) 5372 goto handleFailed 5373 } 5374 } else { 5375 newTenant, newTenantCtx, newUserId, err = createTablesInMoCatalogOfGeneralTenant(ctx, bh, tenant, pu, ca) 5376 if err != nil { 5377 goto handleFailed 5378 } 5379 err = bh.Exec(ctx, "commit;") 5380 if err != nil { 5381 goto handleFailed 5382 } 5383 5384 err = bh.Exec(newTenantCtx, createAutoTableSql) 5385 if err != nil { 5386 return err 5387 } 5388 5389 err = bh.Exec(ctx, "begin;") 5390 if err != nil { 5391 goto handleFailed 5392 } 5393 5394 err = createTablesInMoCatalogOfGeneralTenant2(tenant, bh, ca, newTenantCtx, int64(newTenant.TenantID), newUserId) 5395 if err != nil { 5396 goto handleFailed 5397 } 5398 5399 err = createTablesInSystemOfGeneralTenant(ctx, bh, tenant, pu, newTenant) 5400 if err != nil { 5401 goto handleFailed 5402 } 5403 5404 err = createTablesInInformationSchemaOfGeneralTenant(ctx, bh, tenant, pu, newTenant) 5405 if err != nil { 5406 goto handleFailed 5407 } 5408 } 5409 5410 err = bh.Exec(ctx, "commit;") 5411 if err != nil { 5412 goto handleFailed 5413 } 5414 return err 5415 handleFailed: 5416 //ROLLBACK the transaction 5417 rbErr := bh.Exec(ctx, "rollback;") 5418 if rbErr != nil { 5419 return rbErr 5420 } 5421 return err 5422 } 5423 5424 // createTablesInMoCatalogOfGeneralTenant creates catalog tables in the database mo_catalog. 5425 func createTablesInMoCatalogOfGeneralTenant(ctx context.Context, bh BackgroundExec, tenant *TenantInfo, pu *config.ParameterUnit, ca *tree.CreateAccount) (*TenantInfo, context.Context, int64, error) { 5426 var err error 5427 var initMoAccount string 5428 var erArray []ExecResult 5429 var newTenantID int64 5430 var newUserId int64 5431 var comment = "" 5432 var newTenant *TenantInfo 5433 var newTenantCtx context.Context 5434 ctx, span := trace.Debug(ctx, "createTablesInMoCatalogOfGeneralTenant") 5435 defer span.End() 5436 5437 if nameIsInvalid(ca.Name) { 5438 err = moerr.NewInternalError(ctx, "the account name is invalid") 5439 goto handleFailed 5440 } 5441 5442 if nameIsInvalid(ca.AuthOption.AdminName) { 5443 err = moerr.NewInternalError(ctx, "the admin name is invalid") 5444 goto handleFailed 5445 } 5446 5447 //!!!NOTE : Insert into mo_account with original context. 5448 // Other operations with a new context with new tenant info 5449 //step 1: add new tenant entry to the mo_account 5450 if ca.Comment.Exist { 5451 comment = ca.Comment.Comment 5452 } 5453 5454 initMoAccount = fmt.Sprintf(initMoAccountWithoutIDFormat, ca.Name, sysAccountStatus, types.CurrentTimestamp().String2(time.UTC, 0), comment) 5455 //execute the insert 5456 err = bh.Exec(ctx, initMoAccount) 5457 if err != nil { 5458 goto handleFailed 5459 } 5460 5461 //query the tenant id 5462 bh.ClearExecResultSet() 5463 err = bh.Exec(ctx, getSqlForCheckTenant(ca.Name)) 5464 if err != nil { 5465 goto handleFailed 5466 } 5467 5468 erArray, err = getResultSet(ctx, bh) 5469 if err != nil { 5470 goto handleFailed 5471 } 5472 5473 if execResultArrayHasData(erArray) { 5474 newTenantID, err = erArray[0].GetInt64(ctx, 0, 0) 5475 if err != nil { 5476 goto handleFailed 5477 } 5478 } else { 5479 err = moerr.NewInternalError(ctx, "get the id of tenant %s failed", ca.Name) 5480 goto handleFailed 5481 } 5482 5483 newTenant = &TenantInfo{ 5484 Tenant: ca.Name, 5485 User: ca.AuthOption.AdminName, 5486 DefaultRole: publicRoleName, 5487 TenantID: uint32(newTenantID), 5488 UserID: uint32(newUserId), 5489 DefaultRoleID: publicRoleID, 5490 } 5491 //with new tenant 5492 newTenantCtx = context.WithValue(ctx, defines.TenantIDKey{}, uint32(newTenantID)) 5493 newUserId = dumpID + 1 5494 newTenantCtx = context.WithValue(newTenantCtx, defines.UserIDKey{}, uint32(newUserId)) 5495 newTenantCtx = context.WithValue(newTenantCtx, defines.RoleIDKey{}, uint32(publicRoleID)) 5496 handleFailed: 5497 return newTenant, newTenantCtx, newUserId, err 5498 } 5499 5500 func createTablesInMoCatalogOfGeneralTenant2(tenant *TenantInfo, bh BackgroundExec, ca *tree.CreateAccount, newTenantCtx context.Context, newTenantID, newUserId int64) error { 5501 var err error 5502 var initDataSqls []string 5503 newTenantCtx, span := trace.Debug(newTenantCtx, "createTablesInMoCatalogOfGeneralTenant2") 5504 defer span.End() 5505 //create tables for the tenant 5506 for _, sql := range createSqls { 5507 //only the SYS tenant has the table mo_account 5508 if strings.HasPrefix(sql, "create table mo_account") { 5509 continue 5510 } 5511 err = bh.Exec(newTenantCtx, sql) 5512 if err != nil { 5513 return err 5514 } 5515 } 5516 5517 //initialize the default data of tables for the tenant 5518 addSqlIntoSet := func(sql string) { 5519 initDataSqls = append(initDataSqls, sql) 5520 } 5521 //step 2:add new role entries to the mo_role 5522 initMoRole1 := fmt.Sprintf(initMoRoleFormat, accountAdminRoleID, accountAdminRoleName, tenant.GetUserID(), tenant.GetDefaultRoleID(), types.CurrentTimestamp().String2(time.UTC, 0), "") 5523 initMoRole2 := fmt.Sprintf(initMoRoleFormat, publicRoleID, publicRoleName, tenant.GetUserID(), tenant.GetDefaultRoleID(), types.CurrentTimestamp().String2(time.UTC, 0), "") 5524 addSqlIntoSet(initMoRole1) 5525 addSqlIntoSet(initMoRole2) 5526 5527 //step 3:add new user entry to the mo_user 5528 if ca.AuthOption.IdentifiedType.Typ != tree.AccountIdentifiedByPassword { 5529 err = moerr.NewInternalError(newTenantCtx, "only support password verification now") 5530 return err 5531 } 5532 name := ca.AuthOption.AdminName 5533 password := ca.AuthOption.IdentifiedType.Str 5534 if len(password) == 0 { 5535 err = moerr.NewInternalError(newTenantCtx, "password is empty string") 5536 return err 5537 } 5538 status := rootStatus 5539 //TODO: fix the status of user or account 5540 if ca.StatusOption.Exist { 5541 if ca.StatusOption.Option == tree.AccountStatusSuspend { 5542 status = tree.AccountStatusSuspend.String() 5543 } 5544 } 5545 //the first user id in the general tenant 5546 initMoUser1 := fmt.Sprintf(initMoUserFormat, newUserId, rootHost, name, password, status, 5547 types.CurrentTimestamp().String2(time.UTC, 0), rootExpiredTime, rootLoginType, 5548 tenant.GetUserID(), tenant.GetDefaultRoleID(), accountAdminRoleID) 5549 addSqlIntoSet(initMoUser1) 5550 5551 //step4: add new entries to the mo_role_privs 5552 //accountadmin role 5553 for _, t := range entriesOfAccountAdminForMoRolePrivsFor { 5554 entry := privilegeEntriesMap[t] 5555 initMoRolePriv := fmt.Sprintf(initMoRolePrivFormat, 5556 accountAdminRoleID, accountAdminRoleName, 5557 entry.objType, entry.objId, 5558 entry.privilegeId, entry.privilegeId.String(), entry.privilegeLevel, 5559 tenant.GetUserID(), types.CurrentTimestamp().String2(time.UTC, 0), 5560 entry.withGrantOption) 5561 addSqlIntoSet(initMoRolePriv) 5562 } 5563 5564 //public role 5565 for _, t := range entriesOfPublicForMoRolePrivsFor { 5566 entry := privilegeEntriesMap[t] 5567 initMoRolePriv := fmt.Sprintf(initMoRolePrivFormat, 5568 publicRoleID, publicRoleName, 5569 entry.objType, entry.objId, 5570 entry.privilegeId, entry.privilegeId.String(), entry.privilegeLevel, 5571 tenant.GetUserID(), types.CurrentTimestamp().String2(time.UTC, 0), 5572 entry.withGrantOption) 5573 addSqlIntoSet(initMoRolePriv) 5574 } 5575 5576 //step5: add new entries to the mo_user_grant 5577 initMoUserGrant1 := fmt.Sprintf(initMoUserGrantFormat, accountAdminRoleID, newUserId, types.CurrentTimestamp().String2(time.UTC, 0), true) 5578 addSqlIntoSet(initMoUserGrant1) 5579 initMoUserGrant2 := fmt.Sprintf(initMoUserGrantFormat, publicRoleID, newUserId, types.CurrentTimestamp().String2(time.UTC, 0), true) 5580 addSqlIntoSet(initMoUserGrant2) 5581 5582 //fill the mo_role, mo_user, mo_role_privs, mo_user_grant, mo_role_grant 5583 for _, sql := range initDataSqls { 5584 bh.ClearExecResultSet() 5585 err = bh.Exec(newTenantCtx, sql) 5586 if err != nil { 5587 return err 5588 } 5589 } 5590 return nil 5591 } 5592 5593 // createTablesInSystemOfGeneralTenant creates the database system and system_metrics as the external tables. 5594 func createTablesInSystemOfGeneralTenant(ctx context.Context, bh BackgroundExec, tenant *TenantInfo, pu *config.ParameterUnit, newTenant *TenantInfo) error { 5595 ctx, span := trace.Debug(ctx, "createTablesInSystemOfGeneralTenant") 5596 defer span.End() 5597 //with new tenant 5598 ctx = context.WithValue(ctx, defines.TenantIDKey{}, newTenant.GetTenantID()) 5599 ctx = context.WithValue(ctx, defines.UserIDKey{}, newTenant.GetUserID()) 5600 ctx = context.WithValue(ctx, defines.RoleIDKey{}, newTenant.GetDefaultRoleID()) 5601 5602 var err error 5603 sqls := make([]string, 0) 5604 sqls = append(sqls, "create database "+motrace.SystemDBConst+";") 5605 sqls = append(sqls, "use "+motrace.SystemDBConst+";") 5606 traceTables := motrace.GetSchemaForAccount(ctx, newTenant.GetTenant()) 5607 sqls = append(sqls, traceTables...) 5608 sqls = append(sqls, "create database "+metric.MetricDBConst+";") 5609 sqls = append(sqls, "use "+metric.MetricDBConst+";") 5610 metricTables := metric.GetSchemaForAccount(ctx, newTenant.GetTenant()) 5611 sqls = append(sqls, metricTables...) 5612 5613 for _, sql := range sqls { 5614 bh.ClearExecResultSet() 5615 err = bh.Exec(ctx, sql) 5616 if err != nil { 5617 return err 5618 } 5619 } 5620 return err 5621 } 5622 5623 // createTablesInInformationSchemaOfGeneralTenant creates the database information_schema and the views or tables. 5624 func createTablesInInformationSchemaOfGeneralTenant(ctx context.Context, bh BackgroundExec, tenant *TenantInfo, pu *config.ParameterUnit, newTenant *TenantInfo) error { 5625 ctx, span := trace.Debug(ctx, "createTablesInInformationSchemaOfGeneralTenant") 5626 defer span.End() 5627 //with new tenant 5628 //TODO: when we have the auto_increment column, we need new strategy. 5629 ctx = context.WithValue(ctx, defines.TenantIDKey{}, newTenant.GetTenantID()) 5630 ctx = context.WithValue(ctx, defines.UserIDKey{}, newTenant.GetUserID()) 5631 ctx = context.WithValue(ctx, defines.RoleIDKey{}, newTenant.GetDefaultRoleID()) 5632 5633 var err error 5634 sqls := make([]string, 0, len(sysview.InitInformationSchemaSysTables)+len(sysview.InitMysqlSysTables)+4) 5635 5636 sqls = append(sqls, "create database information_schema;") 5637 sqls = append(sqls, "use information_schema;") 5638 sqls = append(sqls, sysview.InitInformationSchemaSysTables...) 5639 sqls = append(sqls, "create database mysql;") 5640 sqls = append(sqls, "use mysql;") 5641 sqls = append(sqls, sysview.InitMysqlSysTables...) 5642 5643 for _, sql := range sqls { 5644 bh.ClearExecResultSet() 5645 err = bh.Exec(ctx, sql) 5646 if err != nil { 5647 return err 5648 } 5649 } 5650 return err 5651 } 5652 5653 func checkUserExistsOrNot(ctx context.Context, pu *config.ParameterUnit, tenantName string) (bool, error) { 5654 mp, err := mpool.NewMPool("check_user_exists", 0, mpool.NoFixed) 5655 if err != nil { 5656 return false, err 5657 } 5658 defer mpool.DeleteMPool(mp) 5659 5660 sqlForCheckUser := getSqlForPasswordOfUser(tenantName) 5661 5662 // A mock autoIncrCaches 5663 aic := defines.AutoIncrCaches{} 5664 erArray, err := executeSQLInBackgroundSession(ctx, mp, pu, sqlForCheckUser, aic) 5665 if err != nil { 5666 return false, err 5667 } 5668 5669 if !execResultArrayHasData(erArray) { 5670 return false, nil 5671 } 5672 5673 return true, nil 5674 } 5675 5676 // InitUser creates new user for the tenant 5677 func InitUser(ctx context.Context, ses *Session, tenant *TenantInfo, cu *tree.CreateUser) error { 5678 var err error 5679 var exists int 5680 var erArray []ExecResult 5681 var newUserId int64 5682 var host string 5683 var newRoleId int64 5684 var status string 5685 5686 err = normalizeNamesOfUsers(ctx, cu.Users) 5687 if err != nil { 5688 return err 5689 } 5690 5691 if cu.Role != nil { 5692 err = normalizeNameOfRole(ctx, cu.Role) 5693 if err != nil { 5694 return err 5695 } 5696 } 5697 5698 mp, err := mpool.NewMPool("init_user", 0, mpool.NoFixed) 5699 if err != nil { 5700 return err 5701 } 5702 defer mpool.DeleteMPool(mp) 5703 5704 bh := ses.GetBackgroundExec(ctx) 5705 defer bh.Close() 5706 5707 err = bh.Exec(ctx, "begin;") 5708 if err != nil { 5709 goto handleFailed 5710 } 5711 5712 //TODO: get role and the id of role 5713 newRoleId = publicRoleID 5714 if cu.Role != nil { 5715 sqlForRoleIdOfRole := getSqlForRoleIdOfRole(cu.Role.UserName) 5716 bh.ClearExecResultSet() 5717 err = bh.Exec(ctx, sqlForRoleIdOfRole) 5718 if err != nil { 5719 goto handleFailed 5720 } 5721 erArray, err = getResultSet(ctx, bh) 5722 if err != nil { 5723 goto handleFailed 5724 } 5725 if !execResultArrayHasData(erArray) { 5726 err = moerr.NewInternalError(ctx, "there is no role %s", cu.Role.UserName) 5727 goto handleFailed 5728 } 5729 newRoleId, err = erArray[0].GetInt64(ctx, 0, 0) 5730 if err != nil { 5731 goto handleFailed 5732 } 5733 5734 from := &verifiedRole{ 5735 typ: roleType, 5736 name: cu.Role.UserName, 5737 } 5738 5739 for _, user := range cu.Users { 5740 to := &verifiedRole{ 5741 typ: userType, 5742 name: user.Username, 5743 } 5744 err = verifySpecialRolesInGrant(ctx, tenant, from, to) 5745 if err != nil { 5746 goto handleFailed 5747 } 5748 } 5749 } 5750 5751 //TODO: get password_option or lock_option. there is no field in mo_user to store it. 5752 status = userStatusUnlock 5753 if cu.MiscOpt != nil { 5754 if _, ok := cu.MiscOpt.(*tree.UserMiscOptionAccountLock); ok { 5755 status = userStatusLock 5756 } 5757 } 5758 5759 for _, user := range cu.Users { 5760 //dedup with user 5761 sql := getSqlForPasswordOfUser(user.Username) 5762 bh.ClearExecResultSet() 5763 err = bh.Exec(ctx, sql) 5764 if err != nil { 5765 goto handleFailed 5766 } 5767 5768 erArray, err = getResultSet(ctx, bh) 5769 if err != nil { 5770 goto handleFailed 5771 } 5772 exists = 0 5773 if execResultArrayHasData(erArray) { 5774 exists = 1 5775 } 5776 5777 //dedup with the role 5778 if exists == 0 { 5779 sqlForRoleIdOfRole := getSqlForRoleIdOfRole(user.Username) 5780 bh.ClearExecResultSet() 5781 err = bh.Exec(ctx, sqlForRoleIdOfRole) 5782 if err != nil { 5783 goto handleFailed 5784 } 5785 5786 erArray, err = getResultSet(ctx, bh) 5787 if err != nil { 5788 goto handleFailed 5789 } 5790 if execResultArrayHasData(erArray) { 5791 exists = 2 5792 } 5793 } 5794 5795 if exists != 0 { 5796 if cu.IfNotExists { //do nothing 5797 continue 5798 } 5799 if exists == 1 { 5800 err = moerr.NewInternalError(ctx, "the user %s exists", user.Username) 5801 } else if exists == 2 { 5802 err = moerr.NewInternalError(ctx, "there is a role with the same name as the user") 5803 } 5804 5805 goto handleFailed 5806 } 5807 5808 if user.AuthOption == nil { 5809 err = moerr.NewInternalError(ctx, "the user %s misses the auth_option", user.Username) 5810 goto handleFailed 5811 } 5812 5813 if user.AuthOption.Typ != tree.AccountIdentifiedByPassword { 5814 err = moerr.NewInternalError(ctx, "only support password verification now") 5815 goto handleFailed 5816 } 5817 5818 password := user.AuthOption.Str 5819 if len(password) == 0 { 5820 err = moerr.NewInternalError(ctx, "password is empty string") 5821 goto handleFailed 5822 } 5823 5824 //TODO: get comment or attribute. there is no field in mo_user to store it. 5825 host = user.Hostname 5826 if len(user.Hostname) == 0 || user.Hostname == "%" { 5827 host = rootHost 5828 } 5829 initMoUser1 := fmt.Sprintf(initMoUserWithoutIDFormat, host, user.Username, password, status, 5830 types.CurrentTimestamp().String2(time.UTC, 0), rootExpiredTime, rootLoginType, 5831 tenant.GetUserID(), tenant.GetDefaultRoleID(), newRoleId) 5832 5833 bh.ClearExecResultSet() 5834 err = bh.Exec(ctx, initMoUser1) 5835 if err != nil { 5836 goto handleFailed 5837 } 5838 5839 //query the id 5840 bh.ClearExecResultSet() 5841 err = bh.Exec(ctx, getSqlForPasswordOfUser(user.Username)) 5842 if err != nil { 5843 goto handleFailed 5844 } 5845 5846 erArray, err = getResultSet(ctx, bh) 5847 if err != nil { 5848 goto handleFailed 5849 } 5850 5851 if !execResultArrayHasData(erArray) { 5852 err = moerr.NewInternalError(ctx, "get the id of user %s failed", user.Username) 5853 goto handleFailed 5854 } 5855 newUserId, err = erArray[0].GetInt64(ctx, 0, 0) 5856 if err != nil { 5857 goto handleFailed 5858 } 5859 5860 initMoUserGrant1 := fmt.Sprintf(initMoUserGrantFormat, newRoleId, newUserId, types.CurrentTimestamp().String2(time.UTC, 0), true) 5861 err = bh.Exec(ctx, initMoUserGrant1) 5862 if err != nil { 5863 goto handleFailed 5864 } 5865 5866 //if it is not public role, just insert the record for public 5867 if newRoleId != publicRoleID { 5868 initMoUserGrant2 := fmt.Sprintf(initMoUserGrantFormat, publicRoleID, newUserId, types.CurrentTimestamp().String2(time.UTC, 0), true) 5869 err = bh.Exec(ctx, initMoUserGrant2) 5870 if err != nil { 5871 goto handleFailed 5872 } 5873 } 5874 } 5875 5876 err = bh.Exec(ctx, "commit;") 5877 if err != nil { 5878 goto handleFailed 5879 } 5880 return err 5881 5882 handleFailed: 5883 //ROLLBACK the transaction 5884 rbErr := bh.Exec(ctx, "rollback;") 5885 if rbErr != nil { 5886 return rbErr 5887 } 5888 return err 5889 } 5890 5891 // InitRole creates the new role 5892 func InitRole(ctx context.Context, ses *Session, tenant *TenantInfo, cr *tree.CreateRole) error { 5893 var err error 5894 var exists int 5895 var erArray []ExecResult 5896 err = normalizeNamesOfRoles(ctx, cr.Roles) 5897 if err != nil { 5898 return err 5899 } 5900 5901 bh := ses.GetBackgroundExec(ctx) 5902 defer bh.Close() 5903 5904 err = bh.Exec(ctx, "begin;") 5905 if err != nil { 5906 goto handleFailed 5907 } 5908 5909 for _, r := range cr.Roles { 5910 exists = 0 5911 if isPredefinedRole(r.UserName) { 5912 exists = 3 5913 } else { 5914 //dedup with role 5915 sqlForRoleIdOfRole := getSqlForRoleIdOfRole(r.UserName) 5916 bh.ClearExecResultSet() 5917 err = bh.Exec(ctx, sqlForRoleIdOfRole) 5918 if err != nil { 5919 goto handleFailed 5920 } 5921 5922 erArray, err = getResultSet(ctx, bh) 5923 if err != nil { 5924 goto handleFailed 5925 } 5926 if execResultArrayHasData(erArray) { 5927 exists = 1 5928 } 5929 5930 //dedup with user 5931 if exists == 0 { 5932 sql := getSqlForPasswordOfUser(r.UserName) 5933 bh.ClearExecResultSet() 5934 err = bh.Exec(ctx, sql) 5935 if err != nil { 5936 goto handleFailed 5937 } 5938 5939 erArray, err = getResultSet(ctx, bh) 5940 if err != nil { 5941 goto handleFailed 5942 } 5943 if execResultArrayHasData(erArray) { 5944 exists = 2 5945 } 5946 } 5947 } 5948 5949 if exists != 0 { 5950 if cr.IfNotExists { 5951 continue 5952 } 5953 if exists == 1 { 5954 err = moerr.NewInternalError(ctx, "the role %s exists", r.UserName) 5955 } else if exists == 2 { 5956 err = moerr.NewInternalError(ctx, "there is a user with the same name as the role %s", r.UserName) 5957 } else if exists == 3 { 5958 err = moerr.NewInternalError(ctx, "can not use the name %s. it is the name of the predefined role", r.UserName) 5959 } 5960 5961 goto handleFailed 5962 } 5963 5964 initMoRole := fmt.Sprintf(initMoRoleWithoutIDFormat, r.UserName, tenant.GetUserID(), tenant.GetDefaultRoleID(), 5965 types.CurrentTimestamp().String2(time.UTC, 0), "") 5966 err = bh.Exec(ctx, initMoRole) 5967 if err != nil { 5968 goto handleFailed 5969 } 5970 } 5971 5972 err = bh.Exec(ctx, "commit;") 5973 if err != nil { 5974 goto handleFailed 5975 } 5976 5977 return err 5978 handleFailed: 5979 //ROLLBACK the transaction 5980 rbErr := bh.Exec(ctx, "rollback;") 5981 if rbErr != nil { 5982 return rbErr 5983 } 5984 return err 5985 } 5986 5987 func InitFunction(ctx context.Context, ses *Session, tenant *TenantInfo, cf *tree.CreateFunction) error { 5988 var err error 5989 var initMoUdf string 5990 var retTypeStr string 5991 var dbName string 5992 var checkExistence string 5993 var argsJson []byte 5994 var fmtctx *tree.FmtCtx 5995 var argMap map[string]string 5996 var erArray []ExecResult 5997 5998 // a database must be selected or specified as qualifier when create a function 5999 if cf.Name.HasNoNameQualifier() { 6000 if ses.DatabaseNameIsEmpty() { 6001 return moerr.NewNoDBNoCtx() 6002 } 6003 dbName = ses.GetDatabaseName() 6004 } else { 6005 dbName = string(cf.Name.Name.SchemaName) 6006 } 6007 6008 bh := ses.GetBackgroundExec(ctx) 6009 defer bh.Close() 6010 6011 // format return type 6012 fmtctx = tree.NewFmtCtx(dialect.MYSQL, tree.WithQuoteString(true)) 6013 cf.ReturnType.Format(fmtctx) 6014 retTypeStr = fmtctx.String() 6015 fmtctx.Reset() 6016 6017 // build argmap and marshal as json 6018 argMap = make(map[string]string) 6019 for i := 0; i < len(cf.Args); i++ { 6020 curName := cf.Args[i].GetName(fmtctx) 6021 fmtctx.Reset() 6022 argMap[curName] = cf.Args[i].GetType(fmtctx) 6023 fmtctx.Reset() 6024 } 6025 argsJson, err = json.Marshal(argMap) 6026 if err != nil { 6027 goto handleFailed 6028 } 6029 6030 // validate duplicate function declaration 6031 bh.ClearExecResultSet() 6032 checkExistence = fmt.Sprintf(checkUdfExistence, string(cf.Name.Name.ObjectName), dbName, string(argsJson)) 6033 logutil.Debug("Exist: " + checkExistence) 6034 err = bh.Exec(ctx, checkExistence) 6035 if err != nil { 6036 goto handleFailed 6037 } 6038 6039 erArray, err = getResultSet(ctx, bh) 6040 if err != nil { 6041 goto handleFailed 6042 } 6043 6044 if execResultArrayHasData(erArray) { 6045 return moerr.NewUDFAlreadyExistsNoCtx(string(cf.Name.Name.ObjectName)) 6046 } 6047 6048 err = bh.Exec(ctx, "begin;") 6049 if err != nil { 6050 goto handleFailed 6051 } 6052 6053 initMoUdf = fmt.Sprintf(initMoUserDefinedFunctionFormat, 6054 string(cf.Name.Name.ObjectName), 6055 string(argsJson), 6056 retTypeStr, cf.Body, cf.Language, dbName, 6057 tenant.User, types.CurrentTimestamp().String2(time.UTC, 0), types.CurrentTimestamp().String2(time.UTC, 0), "FUNCTION", "DEFINER", "", "utf8mb4", "utf8mb4_0900_ai_ci", "utf8mb4_0900_ai_ci") 6058 err = bh.Exec(ctx, initMoUdf) 6059 if err != nil { 6060 goto handleFailed 6061 } 6062 6063 err = bh.Exec(ctx, "commit;") 6064 if err != nil { 6065 goto handleFailed 6066 } 6067 6068 return err 6069 handleFailed: 6070 //ROLLBACK the transaction 6071 rbErr := bh.Exec(ctx, "rollback;") 6072 if rbErr != nil { 6073 return rbErr 6074 } 6075 return err 6076 } 6077 6078 func doAlterDatabaseConfig(ctx context.Context, ses *Session, ad *tree.AlterDataBaseConfig) error { 6079 var err error 6080 var sql string 6081 var erArray []ExecResult 6082 6083 datname := ad.DbName 6084 update_config := "'" + ad.UpdateConfig + "'" 6085 6086 //verify the update_config 6087 if !isInvalidConfigInput(update_config) { 6088 return moerr.NewInvalidInput(ctx, "invalid input %s for alter database config", update_config) 6089 } 6090 6091 bh := ses.GetBackgroundExec(ctx) 6092 defer bh.Close() 6093 6094 err = bh.Exec(ctx, "begin") 6095 if err != nil { 6096 goto handleFailed 6097 } 6098 6099 //step1:check database exists or not 6100 sql = `select datname from mo_catalog.mo_database where datname = "%s";` 6101 sql = fmt.Sprintf(sql, datname) 6102 bh.ClearExecResultSet() 6103 err = bh.Exec(ctx, sql) 6104 if err != nil { 6105 goto handleFailed 6106 } 6107 6108 erArray, err = getResultSet(ctx, bh) 6109 if err != nil { 6110 goto handleFailed 6111 } 6112 6113 if !execResultArrayHasData(erArray) { 6114 err = moerr.NewInternalError(ctx, "there is no database %s", datname) 6115 goto handleFailed 6116 } 6117 6118 //step2: update the mo_mysql_compatbility_mode of that database 6119 sql = `update mo_catalog.mo_mysql_compatbility_mode set configuration = %s where dat_name = "%s";` 6120 sql = fmt.Sprintf(sql, update_config, datname) 6121 err = bh.Exec(ctx, sql) 6122 if err != nil { 6123 goto handleFailed 6124 } 6125 6126 err = bh.Exec(ctx, "commit;") 6127 if err != nil { 6128 goto handleFailed 6129 } 6130 6131 //step3: update the session verison 6132 err = bh.Exec(ctx, "begin") 6133 if err != nil { 6134 goto handleFailed 6135 } 6136 6137 if len(ses.GetDatabaseName()) != 0 && ses.GetDatabaseName() == datname { 6138 err = changeVersion(ctx, ses, ses.GetDatabaseName()) 6139 if err != nil { 6140 goto handleFailed 6141 } 6142 } 6143 6144 err = bh.Exec(ctx, "commit;") 6145 if err != nil { 6146 goto handleFailed 6147 } 6148 return err 6149 6150 handleFailed: 6151 //ROLLBACK the transaction 6152 rbErr := bh.Exec(ctx, "rollback;") 6153 if rbErr != nil { 6154 return rbErr 6155 } 6156 return err 6157 } 6158 6159 func doAlterAccountConfig(ctx context.Context, ses *Session, stmt *tree.AlterDataBaseConfig) error { 6160 var err error 6161 var sql string 6162 var erArray []ExecResult 6163 6164 accountName := stmt.AccountName 6165 update_config := "'" + stmt.UpdateConfig + "'" 6166 6167 //verify the update_config 6168 if !isInvalidConfigInput(update_config) { 6169 return moerr.NewInvalidInput(ctx, "invalid input %s for alter database config", update_config) 6170 } 6171 6172 bh := ses.GetBackgroundExec(ctx) 6173 defer bh.Close() 6174 6175 err = bh.Exec(ctx, "begin") 6176 if err != nil { 6177 goto handleFailed 6178 } 6179 6180 //step 1: check account exists or not 6181 sql = `select account_name from mo_catalog.mo_mysql_compatbility_mode where account_name = "%s";` 6182 sql = fmt.Sprintf(sql, accountName) 6183 bh.ClearExecResultSet() 6184 err = bh.Exec(ctx, sql) 6185 if err != nil { 6186 goto handleFailed 6187 } 6188 6189 erArray, err = getResultSet(ctx, bh) 6190 if err != nil { 6191 goto handleFailed 6192 } 6193 6194 if !execResultArrayHasData(erArray) { 6195 err = moerr.NewInternalError(ctx, "there is no account %s", accountName) 6196 goto handleFailed 6197 } 6198 6199 //step2: update the config table 6200 sql = `update mo_catalog.mo_mysql_compatbility_mode set configuration = %s where account_name = "%s";` 6201 sql = fmt.Sprintf(sql, update_config, accountName) 6202 err = bh.Exec(ctx, sql) 6203 if err != nil { 6204 goto handleFailed 6205 } 6206 err = bh.Exec(ctx, "commit;") 6207 if err != nil { 6208 goto handleFailed 6209 } 6210 6211 //step3: update the session verison 6212 err = bh.Exec(ctx, "begin") 6213 if err != nil { 6214 goto handleFailed 6215 } 6216 6217 if len(ses.GetDatabaseName()) != 0 { 6218 err = changeVersion(ctx, ses, ses.GetDatabaseName()) 6219 if err != nil { 6220 goto handleFailed 6221 } 6222 } 6223 6224 err = bh.Exec(ctx, "commit;") 6225 if err != nil { 6226 goto handleFailed 6227 } 6228 return err 6229 6230 handleFailed: 6231 //ROLLBACK the transaction 6232 rbErr := bh.Exec(ctx, "rollback;") 6233 if rbErr != nil { 6234 return rbErr 6235 } 6236 return err 6237 6238 } 6239 6240 func insertRecordToMoMysqlCompatbilityMode(ctx context.Context, ses *Session, stmt tree.Statement) error { 6241 var err error 6242 var sql string 6243 var accountName string 6244 var datname string 6245 var configuration string 6246 6247 if createDatabaseStmt, ok := stmt.(*tree.CreateDatabase); ok { 6248 bh := ses.GetBackgroundExec(ctx) 6249 defer bh.Close() 6250 6251 err = bh.Exec(ctx, "begin") 6252 if err != nil { 6253 goto handleFailed 6254 } 6255 6256 //step 1: get account_name and database_name 6257 if ses.GetTenantInfo() != nil { 6258 accountName = ses.GetTenantInfo().GetTenant() 6259 } else { 6260 goto handleFailed 6261 } 6262 datname = string(createDatabaseStmt.Name) 6263 6264 //step 2: check database name 6265 if _, ok := bannedCatalogDatabases[datname]; ok { 6266 goto handleFailed 6267 } 6268 6269 //step 3: insert the record 6270 configuration = fmt.Sprintf("'"+"{"+"%q"+":"+"%q"+"}"+"'", "version_compatibility", "0.7") 6271 sql = fmt.Sprintf(initMoMysqlCompatbilityModeFormat, accountName, datname, configuration) 6272 6273 err = bh.Exec(ctx, sql) 6274 if err != nil { 6275 goto handleFailed 6276 } 6277 6278 err = bh.Exec(ctx, "commit;") 6279 if err != nil { 6280 goto handleFailed 6281 } 6282 return err 6283 6284 handleFailed: 6285 //ROLLBACK the transaction 6286 rbErr := bh.Exec(ctx, "rollback;") 6287 if rbErr != nil { 6288 return rbErr 6289 } 6290 return err 6291 } 6292 return nil 6293 6294 } 6295 6296 func deleteRecordToMoMysqlCompatbilityMode(ctx context.Context, ses *Session, stmt tree.Statement) error { 6297 var datname string 6298 6299 if deleteDatabaseStmt, ok := stmt.(*tree.DropDatabase); ok { 6300 datname = string(deleteDatabaseStmt.Name) 6301 deletesql := getSqlForDeleteMysqlCompatbilityMode(datname) 6302 6303 bh := ses.GetBackgroundExec(ctx) 6304 err := bh.Exec(ctx, deletesql) 6305 if err != nil { 6306 return err 6307 } 6308 } 6309 return nil 6310 } 6311 6312 func GetVersionCompatbility(ctx context.Context, ses *Session, dbName string) (string, error) { 6313 var err error 6314 var erArray []ExecResult 6315 defaultConfig := "0.7" 6316 path := "$.version_compatibility" 6317 bh := ses.GetBackgroundExec(ctx) 6318 defer bh.Close() 6319 6320 sql := `select json_unquote(json_extract(configuration,'%s')) from mo_catalog.mo_mysql_compatbility_mode where dat_name = "%s"; ` 6321 sql = fmt.Sprintf(sql, path, dbName) 6322 6323 bh.ClearExecResultSet() 6324 err = bh.Exec(ctx, sql) 6325 if err != nil { 6326 return defaultConfig, err 6327 } 6328 6329 erArray, err = getResultSet(ctx, bh) 6330 if err != nil { 6331 return defaultConfig, err 6332 } 6333 6334 if execResultArrayHasData(erArray) { 6335 config, err := erArray[0].GetString(ctx, 0, 0) 6336 if err != nil { 6337 return defaultConfig, err 6338 } else { 6339 return config, err 6340 } 6341 } 6342 return defaultConfig, err 6343 }