github.com/matrixorigin/matrixone@v1.2.0/pkg/frontend/authenticate.go (about)

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