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  }